@spunto/build 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spunto/build",
3
- "version": "0.7.0",
3
+ "version": "0.9.0",
4
4
  "description": "Spunto's shared Build engine — the devcontainer image protocol and VS Code extension registry clients, with no database, no HTTP framework and no UI.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -40,6 +40,8 @@ export const TASK_EVENT_TYPES = [
40
40
  // cacheCreationTokens?, contextTokens?, costUsd?, turns?, durationMs? } — see `summarizeUsage`
41
41
  "usage",
42
42
  "session.ended", // { status, stopReason?, summary? }
43
+ // { tasks: [{ id, kind, description }] } — what the harness still runs in the background, whole
44
+ "session.background",
43
45
  "raw", // anything an adapter could not place
44
46
  ] as const
45
47
  export type TaskEventType = (typeof TASK_EVENT_TYPES)[number]
@@ -272,6 +274,23 @@ function adaptClaudeJson(obj: Record<string, unknown>): NormalizedEvent[] {
272
274
  ]
273
275
  }
274
276
 
277
+ // The set of background tasks (a `run_in_background` shell, a backgrounded subagent) still
278
+ // alive, restated whole on every change. Why it has to be read: a `result` ends the *turn*, not
279
+ // the work — measured, a turn that leaves a background task running emits its `result`, and
280
+ // when that task finishes the harness wakes itself up for another turn and another `result`,
281
+ // nobody having said anything. So a `result` is a hand-back only if nothing was left running
282
+ // behind it, and this line is the only place that says so.
283
+ if (type === "system" && obj.subtype === "background_tasks_changed") {
284
+ const tasks = (Array.isArray(obj.tasks) ? obj.tasks : [])
285
+ .filter((t): t is Record<string, unknown> => !!t && typeof t === "object")
286
+ .map((t) => ({
287
+ id: typeof t.task_id === "string" ? t.task_id : null,
288
+ kind: typeof t.task_type === "string" ? t.task_type : null,
289
+ description: typeof t.description === "string" ? t.description : null,
290
+ }))
291
+ return [{ type: "session.background", payload: { tasks } }]
292
+ }
293
+
275
294
  if (type === "assistant" || type === "user") {
276
295
  const message = obj.message as Record<string, unknown> | undefined
277
296
  const content = Array.isArray(message?.content) ? message!.content : []
@@ -9,7 +9,7 @@
9
9
  // jointure sans import.
10
10
  //
11
11
  // Contexte complet, et la mesure qui a motivé tout ça (un conteneur mort laisse la ligne `ready`
12
- // indéfiniment) : `rfc/0026-les-etats-d-un-worker.md` dans le dépôt Spunto Cloud.
12
+ // indéfiniment) : `rfc/0027-les-etats-d-un-worker.md` dans le dépôt Spunto Cloud.
13
13
 
14
14
  /**
15
15
  * Tous les statuts qu'un worker peut porter.