MCPcopy
hub / github.com/coder/mux / upsertSubagentReportArtifact

Function upsertSubagentReportArtifact

src/node/services/subagentReportArtifacts.ts:242–349  ·  view source on GitHub ↗
(params: {
  /** Workspace id that owns the session dir we're writing into (used for file locking). */
  workspaceId: string;
  workspaceSessionDir: string;
  childTaskId: string;
  parentWorkspaceId: string;
  ancestorWorkspaceIds: string[];
  reportMarkdown: string;
  /** Task-level model string used when running the sub-agent (optional for legacy entries). */
  model?: string;
  /** Task-level thinking/reasoning level used when running the sub-agent (optional for legacy entries). */
  thinkingLevel?: ThinkingLevel;
  workflowOwnedAncestorWorkspaceIds?: string[];
  planFilePath?: string;
  structuredOutput?: unknown;
  title?: string;
  nowMs?: number;
})

Source from the content-addressed store, hash-verified

240}
241
242export async function upsertSubagentReportArtifact(params: {
243 /** Workspace id that owns the session dir we're writing into (used for file locking). */
244 workspaceId: string;
245 workspaceSessionDir: string;
246 childTaskId: string;
247 parentWorkspaceId: string;
248 ancestorWorkspaceIds: string[];
249 reportMarkdown: string;
250 /** Task-level model string used when running the sub-agent (optional for legacy entries). */
251 model?: string;
252 /** Task-level thinking/reasoning level used when running the sub-agent (optional for legacy entries). */
253 thinkingLevel?: ThinkingLevel;
254 workflowOwnedAncestorWorkspaceIds?: string[];
255 planFilePath?: string;
256 structuredOutput?: unknown;
257 title?: string;
258 nowMs?: number;
259}): Promise<SubagentReportArtifactIndexEntry> {
260 let updated: SubagentReportArtifactIndexEntry | null = null;
261
262 await workspaceFileLocks.withLock(params.workspaceId, async () => {
263 const nowMs = params.nowMs ?? Date.now();
264
265 const model =
266 typeof params.model === "string" && params.model.trim().length > 0
267 ? params.model.trim()
268 : undefined;
269 const thinkingLevel = coerceThinkingLevel(params.thinkingLevel);
270
271 const planFilePath =
272 typeof params.planFilePath === "string" && params.planFilePath.trim().length > 0
273 ? params.planFilePath.trim()
274 : undefined;
275
276 const file = await readSubagentReportArtifactsFile(params.workspaceSessionDir);
277 const existing = file.artifactsByChildTaskId[params.childTaskId] ?? null;
278 const createdAtMs = existing?.createdAtMs ?? nowMs;
279
280 // Write the report payload first so we never publish an index entry without a report body.
281 const reportPath = getSubagentReportArtifactPath(
282 params.workspaceSessionDir,
283 params.childTaskId
284 );
285 try {
286 await fsPromises.mkdir(path.dirname(reportPath), { recursive: true });
287 await writeFileAtomic(
288 reportPath,
289 JSON.stringify(
290 {
291 childTaskId: params.childTaskId,
292 parentWorkspaceId: params.parentWorkspaceId,
293 createdAtMs,
294 updatedAtMs: nowMs,
295 model,
296 thinkingLevel,
297 title: params.title,
298 ancestorWorkspaceIds: params.ancestorWorkspaceIds,
299 workflowOwnedAncestorWorkspaceIds: params.workflowOwnedAncestorWorkspaceIds,

Callers 5

writeTaskReportFunction · 0.90

Calls 5

coerceThinkingLevelFunction · 0.90
withLockMethod · 0.80

Tested by 2

writeTaskReportFunction · 0.72