@minpeter/pss-runtime 0.1.0-next.2 → 0.1.0-next.4

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.
Files changed (145) hide show
  1. package/README.md +172 -85
  2. package/dist/agent-host-session-store.js +2 -4
  3. package/dist/agent-host-session-store.js.map +1 -1
  4. package/dist/agent-loop.js +9 -8
  5. package/dist/agent-loop.js.map +1 -1
  6. package/dist/agent-namespace.js +3 -7
  7. package/dist/agent-namespace.js.map +1 -1
  8. package/dist/agent-options.d.ts +4 -19
  9. package/dist/agent-options.js +2 -8
  10. package/dist/agent-options.js.map +1 -1
  11. package/dist/agent-resume.js +2 -82
  12. package/dist/agent-resume.js.map +1 -1
  13. package/dist/agent-session-entry.d.ts +1 -1
  14. package/dist/agent.d.ts +4 -4
  15. package/dist/agent.js +19 -89
  16. package/dist/agent.js.map +1 -1
  17. package/dist/cloudflare/cloudflare-agent-context.d.ts +40 -0
  18. package/dist/cloudflare/cloudflare-agent-context.js +37 -0
  19. package/dist/cloudflare/cloudflare-agent-context.js.map +1 -0
  20. package/dist/cloudflare/cloudflare-alarm-budget.d.ts +18 -0
  21. package/dist/cloudflare/cloudflare-alarm-budget.js +77 -0
  22. package/dist/cloudflare/cloudflare-alarm-budget.js.map +1 -0
  23. package/dist/cloudflare/cloudflare-alarm-drainer.d.ts +45 -0
  24. package/dist/cloudflare/cloudflare-alarm-drainer.js +103 -0
  25. package/dist/cloudflare/cloudflare-alarm-drainer.js.map +1 -0
  26. package/dist/cloudflare/cloudflare-alarm-run-drain.d.ts +13 -0
  27. package/dist/cloudflare/cloudflare-alarm-run-drain.js +81 -0
  28. package/dist/cloudflare/cloudflare-alarm-run-drain.js.map +1 -0
  29. package/dist/cloudflare/cloudflare-alarm-work.js +110 -0
  30. package/dist/cloudflare/cloudflare-alarm-work.js.map +1 -0
  31. package/dist/cloudflare/cloudflare-checkpoint-store.js +39 -0
  32. package/dist/cloudflare/cloudflare-checkpoint-store.js.map +1 -0
  33. package/dist/cloudflare/cloudflare-durable-object-fetch.d.ts +21 -0
  34. package/dist/cloudflare/cloudflare-durable-object-fetch.js +11 -0
  35. package/dist/cloudflare/cloudflare-durable-object-fetch.js.map +1 -0
  36. package/dist/cloudflare/cloudflare-event-store.js +33 -0
  37. package/dist/cloudflare/cloudflare-event-store.js.map +1 -0
  38. package/dist/cloudflare/cloudflare-execution-session-store.js +40 -0
  39. package/dist/cloudflare/cloudflare-execution-session-store.js.map +1 -0
  40. package/dist/cloudflare/cloudflare-execution-store.js +35 -0
  41. package/dist/cloudflare/cloudflare-execution-store.js.map +1 -0
  42. package/dist/cloudflare/cloudflare-host.d.ts +61 -0
  43. package/dist/cloudflare/cloudflare-host.js +113 -0
  44. package/dist/cloudflare/cloudflare-host.js.map +1 -0
  45. package/dist/cloudflare/cloudflare-notification-store.js +59 -0
  46. package/dist/cloudflare/cloudflare-notification-store.js.map +1 -0
  47. package/dist/cloudflare/cloudflare-run-store.js +81 -0
  48. package/dist/cloudflare/cloudflare-run-store.js.map +1 -0
  49. package/dist/cloudflare/cloudflare-store-utils.js +43 -0
  50. package/dist/cloudflare/cloudflare-store-utils.js.map +1 -0
  51. package/dist/cloudflare/durable-object-storage.d.ts +20 -0
  52. package/dist/cloudflare/durable-object-storage.js +76 -0
  53. package/dist/cloudflare/durable-object-storage.js.map +1 -0
  54. package/dist/cloudflare/index.d.ts +7 -0
  55. package/dist/cloudflare/index.js +6 -0
  56. package/dist/execution/capabilities.d.ts +40 -0
  57. package/dist/execution/host.d.ts +9 -0
  58. package/dist/execution/host.js +49 -1
  59. package/dist/execution/host.js.map +1 -1
  60. package/dist/execution/index.d.ts +3 -1
  61. package/dist/execution/index.js +2 -1
  62. package/dist/execution/memory.js +1 -1
  63. package/dist/execution/memory.js.map +1 -1
  64. package/dist/execution/types.d.ts +5 -10
  65. package/dist/index.d.ts +9 -5
  66. package/dist/index.js +6 -2
  67. package/dist/llm-tool-execution.js.map +1 -1
  68. package/dist/llm.d.ts +1 -21
  69. package/dist/llm.js +12 -14
  70. package/dist/llm.js.map +1 -1
  71. package/dist/plugins.d.ts +27 -5
  72. package/dist/plugins.js +35 -6
  73. package/dist/plugins.js.map +1 -1
  74. package/dist/session/delegate-input.d.ts +9 -0
  75. package/dist/session/delegate-input.js +16 -0
  76. package/dist/session/delegate-input.js.map +1 -0
  77. package/dist/session/events.d.ts +43 -25
  78. package/dist/session/events.js +41 -0
  79. package/dist/session/events.js.map +1 -0
  80. package/dist/session/input-meta-types.d.ts +10 -0
  81. package/dist/session/input-meta.d.ts +13 -0
  82. package/dist/session/input-meta.js +45 -0
  83. package/dist/session/input-meta.js.map +1 -0
  84. package/dist/session/input.d.ts +4 -0
  85. package/dist/session/mapping.js +4 -2
  86. package/dist/session/mapping.js.map +1 -1
  87. package/dist/session/runtime-input-emit.js +41 -0
  88. package/dist/session/runtime-input-emit.js.map +1 -0
  89. package/dist/session/runtime-input.js +5 -1
  90. package/dist/session/runtime-input.js.map +1 -1
  91. package/dist/session/session-events.js +20 -6
  92. package/dist/session/session-events.js.map +1 -1
  93. package/dist/session/session-notification.js +3 -2
  94. package/dist/session/session-notification.js.map +1 -1
  95. package/dist/session/session-runtime-drain.js +3 -9
  96. package/dist/session/session-runtime-drain.js.map +1 -1
  97. package/dist/session/session-turn-processor.js +10 -20
  98. package/dist/session/session-turn-processor.js.map +1 -1
  99. package/dist/session/session.js +15 -8
  100. package/dist/session/session.js.map +1 -1
  101. package/package.json +6 -1
  102. package/dist/agent-child-runs.js +0 -16
  103. package/dist/agent-child-runs.js.map +0 -1
  104. package/dist/agent-host-capabilities.js +0 -9
  105. package/dist/agent-host-capabilities.js.map +0 -1
  106. package/dist/agent-validation.js +0 -35
  107. package/dist/agent-validation.js.map +0 -1
  108. package/dist/child-session-cleanups.js +0 -61
  109. package/dist/child-session-cleanups.js.map +0 -1
  110. package/dist/execution/run.js +0 -55
  111. package/dist/execution/run.js.map +0 -1
  112. package/dist/subagent-background-child-run-state.js +0 -51
  113. package/dist/subagent-background-child-run-state.js.map +0 -1
  114. package/dist/subagent-background-child-run.js +0 -103
  115. package/dist/subagent-background-child-run.js.map +0 -1
  116. package/dist/subagent-background-in-process.js +0 -98
  117. package/dist/subagent-background-in-process.js.map +0 -1
  118. package/dist/subagent-background-notification-inbox.js +0 -106
  119. package/dist/subagent-background-notification-inbox.js.map +0 -1
  120. package/dist/subagent-background-notify.js +0 -136
  121. package/dist/subagent-background-notify.js.map +0 -1
  122. package/dist/subagent-background-resume-group.js +0 -99
  123. package/dist/subagent-background-resume-group.js.map +0 -1
  124. package/dist/subagent-background-runner.js +0 -115
  125. package/dist/subagent-background-runner.js.map +0 -1
  126. package/dist/subagent-background-schedule.js +0 -43
  127. package/dist/subagent-background-schedule.js.map +0 -1
  128. package/dist/subagent-child-run.js +0 -68
  129. package/dist/subagent-child-run.js.map +0 -1
  130. package/dist/subagent-job-cancel.js +0 -84
  131. package/dist/subagent-job-cancel.js.map +0 -1
  132. package/dist/subagent-job-observer.js +0 -19
  133. package/dist/subagent-job-observer.js.map +0 -1
  134. package/dist/subagent-job-output.js +0 -87
  135. package/dist/subagent-job-output.js.map +0 -1
  136. package/dist/subagent-job-state.js +0 -66
  137. package/dist/subagent-job-state.js.map +0 -1
  138. package/dist/subagent-jobs.js +0 -96
  139. package/dist/subagent-jobs.js.map +0 -1
  140. package/dist/subagent-prompt-schema.js +0 -114
  141. package/dist/subagent-prompt-schema.js.map +0 -1
  142. package/dist/subagent-run.js +0 -111
  143. package/dist/subagent-run.js.map +0 -1
  144. package/dist/subagents.js +0 -125
  145. package/dist/subagents.js.map +0 -1
@@ -1,136 +0,0 @@
1
- import { enqueueDurableBackgroundNotification } from "./subagent-background-notification-inbox.js";
2
- //#region src/subagent-background-notify.ts
3
- function registerBackgroundJobGroup({ groupId, groups, job }) {
4
- if (!groupId) return;
5
- let group = groups.get(groupId);
6
- if (!group) {
7
- group = {
8
- completedEvents: [],
9
- failedNotifiedJobIds: /* @__PURE__ */ new Set(),
10
- finalNotified: false,
11
- id: groupId,
12
- jobIds: /* @__PURE__ */ new Set()
13
- };
14
- groups.set(groupId, group);
15
- }
16
- group.jobIds.add(job.id);
17
- }
18
- async function notifyBackgroundCompletion({ endEvent, groups, job, jobs, parentSession }) {
19
- const group = job.groupId ? groups.get(job.groupId) : void 0;
20
- if (!group) {
21
- await notifyParentSession({
22
- input: buildBackgroundReminder([job]),
23
- jobs: [job],
24
- observerEvents: [endEvent],
25
- parentSession
26
- });
27
- return;
28
- }
29
- group.completedEvents.push(endEvent);
30
- if (isFailureStatus(endEvent.status)) {
31
- group.failedNotifiedJobIds.add(job.id);
32
- await notifyParentSession({
33
- input: buildBackgroundReminder([job]),
34
- jobs: [job],
35
- observerEvents: [endEvent],
36
- parentSession
37
- });
38
- }
39
- if (!isGroupSettled(group, jobs) || group.finalNotified) return;
40
- group.finalNotified = true;
41
- const notifyableGroupJobs = [...group.jobIds].map((id) => jobs.get(id)).filter(isDefinedJob).filter((groupJob) => !group.failedNotifiedJobIds.has(groupJob.id));
42
- if (notifyableGroupJobs.length === 0) {
43
- groups.delete(group.id);
44
- return;
45
- }
46
- const observerEvents = group.completedEvents.filter((event) => !group.failedNotifiedJobIds.has(event.task_id ?? ""));
47
- await notifyParentSession({
48
- input: buildBackgroundReminder(notifyableGroupJobs),
49
- jobs: notifyableGroupJobs,
50
- observerEvents: [...observerEvents],
51
- parentSession
52
- });
53
- groups.delete(group.id);
54
- }
55
- async function notifyParentSession({ input, jobs, observerEvents, parentSession }) {
56
- try {
57
- if (await enqueueDurableBackgroundNotification({
58
- input,
59
- jobs,
60
- observerEvents
61
- }) === "queued-only") return;
62
- await Promise.all(observerEvents.map((event) => parentSession.emitObserverEvent(event)));
63
- await parentSession.notify(input, {
64
- deferWhenUnobserved: true,
65
- observerEvents
66
- });
67
- } catch (error) {
68
- await parentSession.emitObserverEvent({
69
- message: errorMessage(error),
70
- type: "turn-error"
71
- });
72
- }
73
- }
74
- function buildBackgroundReminder(jobs) {
75
- return {
76
- text: jobs.length === 1 ? buildSingleJobReminder(jobs[0]) : buildGroupReminder(jobs),
77
- type: "user-text"
78
- };
79
- }
80
- function buildSingleJobReminder(job) {
81
- if (!job) return [
82
- "<system-reminder>",
83
- "[BACKGROUND TASK COMPLETED]",
84
- "[SUBAGENT JOB RESULT READY]",
85
- "A background task completed, but its task metadata is no longer available.",
86
- "</system-reminder>"
87
- ].join("\n");
88
- return [
89
- "<system-reminder>",
90
- "[BACKGROUND TASK COMPLETED]",
91
- "[SUBAGENT JOB RESULT READY]",
92
- `Task ID: ${job.id}`,
93
- `Subagent: ${job.subagent}`,
94
- `Status: ${job.status}`,
95
- `Description: ${sanitizeReminderField(job.description ?? "")}`,
96
- `Use background_output({ task_id: "${job.id}" }) to retrieve the result.`,
97
- "</system-reminder>"
98
- ].join("\n");
99
- }
100
- function buildGroupReminder(jobs) {
101
- return [
102
- "<system-reminder>",
103
- "[ALL BACKGROUND TASKS COMPLETE]",
104
- `Completed task count: ${jobs.length}`,
105
- "Tasks:",
106
- ...jobs.map((job) => `- ${job.id} (${job.subagent}): ${job.status}. Description: ${sanitizeReminderField(job.description ?? "")}. Use background_output({ task_id: "${job.id}" }) to retrieve the result.`),
107
- "</system-reminder>"
108
- ].join("\n");
109
- }
110
- function isGroupSettled(group, jobs) {
111
- for (const id of group.jobIds) {
112
- const job = jobs.get(id);
113
- if (!job || isActiveJobStatus(job.status) || !job.settled) return false;
114
- }
115
- return true;
116
- }
117
- function isActiveJobStatus(status) {
118
- return status === "pending" || status === "running";
119
- }
120
- function isFailureStatus(status) {
121
- return status === "aborted" || status === "cancelled" || status === "error";
122
- }
123
- function isDefinedJob(job) {
124
- return job !== void 0;
125
- }
126
- function sanitizeReminderField(value) {
127
- return value.replaceAll("\r", " ").replaceAll("\n", " ").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
128
- }
129
- function errorMessage(error) {
130
- if (error instanceof Error) return error.message;
131
- return String(error);
132
- }
133
- //#endregion
134
- export { notifyBackgroundCompletion, registerBackgroundJobGroup };
135
-
136
- //# sourceMappingURL=subagent-background-notify.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"subagent-background-notify.js","names":[],"sources":["../src/subagent-background-notify.ts"],"sourcesContent":["import type { AgentEvent } from \"./session/events\";\nimport type { UserInput } from \"./session/input\";\nimport { enqueueDurableBackgroundNotification } from \"./subagent-background-notification-inbox\";\nimport type {\n RuntimeInputSink,\n SubagentJob,\n SubagentJobGroup,\n} from \"./subagent-types\";\n\nexport function registerBackgroundJobGroup({\n groupId,\n groups,\n job,\n}: {\n readonly groupId: string | undefined;\n readonly groups: Map<string, SubagentJobGroup>;\n readonly job: SubagentJob;\n}): void {\n if (!groupId) {\n return;\n }\n\n let group = groups.get(groupId);\n if (!group) {\n group = {\n completedEvents: [],\n failedNotifiedJobIds: new Set(),\n finalNotified: false,\n id: groupId,\n jobIds: new Set(),\n };\n groups.set(groupId, group);\n }\n group.jobIds.add(job.id);\n}\n\nexport async function notifyBackgroundCompletion({\n endEvent,\n groups,\n job,\n jobs,\n parentSession,\n}: {\n readonly endEvent: Extract<AgentEvent, { type: \"subagent-job-end\" }>;\n readonly groups: Map<string, SubagentJobGroup>;\n readonly job: SubagentJob;\n readonly jobs: Map<string, SubagentJob>;\n readonly parentSession: RuntimeInputSink;\n}): Promise<void> {\n const group = job.groupId ? groups.get(job.groupId) : undefined;\n if (!group) {\n await notifyParentSession({\n input: buildBackgroundReminder([job]),\n jobs: [job],\n observerEvents: [endEvent],\n parentSession,\n });\n return;\n }\n\n group.completedEvents.push(endEvent);\n if (isFailureStatus(endEvent.status)) {\n group.failedNotifiedJobIds.add(job.id);\n await notifyParentSession({\n input: buildBackgroundReminder([job]),\n jobs: [job],\n observerEvents: [endEvent],\n parentSession,\n });\n }\n\n if (!isGroupSettled(group, jobs) || group.finalNotified) {\n return;\n }\n\n group.finalNotified = true;\n const groupJobs = [...group.jobIds]\n .map((id) => jobs.get(id))\n .filter(isDefinedJob);\n const notifyableGroupJobs = groupJobs.filter(\n (groupJob) => !group.failedNotifiedJobIds.has(groupJob.id)\n );\n if (notifyableGroupJobs.length === 0) {\n groups.delete(group.id);\n return;\n }\n const observerEvents = group.completedEvents.filter(\n (event) => !group.failedNotifiedJobIds.has(event.task_id ?? \"\")\n );\n await notifyParentSession({\n input: buildBackgroundReminder(notifyableGroupJobs),\n jobs: notifyableGroupJobs,\n observerEvents: [...observerEvents],\n parentSession,\n });\n groups.delete(group.id);\n}\n\nasync function notifyParentSession({\n input,\n jobs,\n observerEvents,\n parentSession,\n}: {\n readonly input: UserInput;\n readonly jobs: readonly SubagentJob[];\n readonly observerEvents: readonly AgentEvent[];\n readonly parentSession: RuntimeInputSink;\n}): Promise<void> {\n try {\n const mode = await enqueueDurableBackgroundNotification({\n input,\n jobs,\n observerEvents,\n });\n if (mode === \"queued-only\") {\n return;\n }\n\n await Promise.all(\n observerEvents.map((event) => parentSession.emitObserverEvent(event))\n );\n await parentSession.notify(input, {\n deferWhenUnobserved: true,\n observerEvents,\n });\n } catch (error) {\n await parentSession.emitObserverEvent({\n message: errorMessage(error),\n type: \"turn-error\",\n });\n }\n}\n\nfunction buildBackgroundReminder(jobs: readonly SubagentJob[]): UserInput {\n const text =\n jobs.length === 1\n ? buildSingleJobReminder(jobs[0])\n : buildGroupReminder(jobs);\n return { text, type: \"user-text\" };\n}\n\nfunction buildSingleJobReminder(job: SubagentJob | undefined): string {\n if (!job) {\n return [\n \"<system-reminder>\",\n \"[BACKGROUND TASK COMPLETED]\",\n \"[SUBAGENT JOB RESULT READY]\",\n \"A background task completed, but its task metadata is no longer available.\",\n \"</system-reminder>\",\n ].join(\"\\n\");\n }\n\n return [\n \"<system-reminder>\",\n \"[BACKGROUND TASK COMPLETED]\",\n \"[SUBAGENT JOB RESULT READY]\",\n `Task ID: ${job.id}`,\n `Subagent: ${job.subagent}`,\n `Status: ${job.status}`,\n `Description: ${sanitizeReminderField(job.description ?? \"\")}`,\n `Use background_output({ task_id: \"${job.id}\" }) to retrieve the result.`,\n \"</system-reminder>\",\n ].join(\"\\n\");\n}\n\nfunction buildGroupReminder(jobs: readonly SubagentJob[]): string {\n return [\n \"<system-reminder>\",\n \"[ALL BACKGROUND TASKS COMPLETE]\",\n `Completed task count: ${jobs.length}`,\n \"Tasks:\",\n ...jobs.map(\n (job) =>\n `- ${job.id} (${job.subagent}): ${job.status}. Description: ${sanitizeReminderField(\n job.description ?? \"\"\n )}. Use background_output({ task_id: \"${job.id}\" }) to retrieve the result.`\n ),\n \"</system-reminder>\",\n ].join(\"\\n\");\n}\n\nfunction isGroupSettled(\n group: SubagentJobGroup,\n jobs: Map<string, SubagentJob>\n): boolean {\n for (const id of group.jobIds) {\n const job = jobs.get(id);\n if (!job || isActiveJobStatus(job.status) || !job.settled) {\n return false;\n }\n }\n\n return true;\n}\n\nfunction isActiveJobStatus(status: SubagentJob[\"status\"]): boolean {\n return status === \"pending\" || status === \"running\";\n}\n\nfunction isFailureStatus(\n status: Extract<AgentEvent, { type: \"subagent-job-end\" }>[\"status\"]\n): boolean {\n return status === \"aborted\" || status === \"cancelled\" || status === \"error\";\n}\n\nfunction isDefinedJob(job: SubagentJob | undefined): job is SubagentJob {\n return job !== undefined;\n}\n\nfunction sanitizeReminderField(value: string): string {\n return value\n .replaceAll(\"\\r\", \" \")\n .replaceAll(\"\\n\", \" \")\n .replaceAll(\"<\", \"&lt;\")\n .replaceAll(\">\", \"&gt;\");\n}\n\nfunction errorMessage(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n\n return String(error);\n}\n"],"mappings":"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"}
@@ -1,99 +0,0 @@
1
- import { readDurableBackgroundChildRunState } from "./subagent-background-child-run-state.js";
2
- import { backgroundRunJobStatus, isActiveJob } from "./subagent-job-state.js";
3
- //#region src/subagent-background-resume-group.ts
4
- async function buildDurableResumeGroups({ currentJob, host, jobs, run, state }) {
5
- const groups = /* @__PURE__ */ new Map();
6
- if (!(state.groupId && run.parentRunId)) return groups;
7
- const group = {
8
- completedEvents: [],
9
- failedNotifiedJobIds: /* @__PURE__ */ new Set(),
10
- finalNotified: false,
11
- id: state.groupId,
12
- jobIds: /* @__PURE__ */ new Set()
13
- };
14
- groups.set(group.id, group);
15
- for (const sibling of await host.store.runs.listByParentRunId(run.parentRunId)) await addSiblingToGroup({
16
- currentJob,
17
- group,
18
- host,
19
- jobs,
20
- run,
21
- sibling,
22
- state
23
- });
24
- return groups;
25
- }
26
- async function addSiblingToGroup({ currentJob, group, host, jobs, run, sibling, state }) {
27
- if (sibling.kind !== "background-subagent") return;
28
- const siblingState = readDurableBackgroundChildRunState(await host.store.checkpoints.latest(sibling.runId));
29
- if (!siblingState || siblingState.groupId !== state.groupId) return;
30
- const siblingJob = sibling.runId === run.runId ? currentJob : durableSiblingJob({
31
- host,
32
- run: sibling,
33
- state: siblingState
34
- });
35
- jobs.set(siblingJob.id, siblingJob);
36
- group.jobIds.add(siblingJob.id);
37
- const endEvent = durableTerminalEvent(siblingJob, sibling.output);
38
- if (!endEvent || sibling.runId === run.runId) return;
39
- group.completedEvents.push(endEvent);
40
- if (endEvent.status === "aborted" || endEvent.status === "cancelled" || endEvent.status === "error") group.failedNotifiedJobIds.add(siblingJob.id);
41
- }
42
- function durableSiblingJob({ host, run, state }) {
43
- const status = backgroundRunJobStatus(run.status) ?? "pending";
44
- const compactResult = compactSubagentResult(run.output);
45
- return {
46
- abort: () => void 0,
47
- childRunId: run.runId,
48
- cleanup: () => Promise.resolve(),
49
- dedupeKey: run.dedupeKey,
50
- delegateToolCallId: state.delegateToolCallId,
51
- description: state.description,
52
- executionHost: host,
53
- groupId: state.groupId,
54
- id: run.publicTaskId ?? run.runId,
55
- parentRunId: run.parentRunId,
56
- parentSessionKey: state.parentSessionKey,
57
- promise: Promise.resolve(),
58
- result: compactResult,
59
- sessionKey: run.sessionKey,
60
- settled: !isActiveJob(status),
61
- status,
62
- subagent: state.subagent
63
- };
64
- }
65
- function durableTerminalEvent(job, output) {
66
- if (job.status !== "completed" && job.status !== "cancelled") return null;
67
- const result = compactSubagentResult(output);
68
- return {
69
- error: result?.error,
70
- eventCount: result?.eventCount ?? 0,
71
- delegateToolCallId: job.delegateToolCallId,
72
- status: job.status,
73
- subagent: job.subagent,
74
- task_id: job.id,
75
- type: "subagent-job-end"
76
- };
77
- }
78
- function compactSubagentResult(output) {
79
- if (!isRecord(output)) return;
80
- if (typeof output.eventCount !== "number" || output.run_in_background !== false || typeof output.subagent !== "string" || typeof output.text !== "string" || !isCompactResultStatus(output.result)) return;
81
- return {
82
- ...typeof output.error === "string" ? { error: output.error } : {},
83
- eventCount: output.eventCount,
84
- result: output.result,
85
- run_in_background: false,
86
- subagent: output.subagent,
87
- text: output.text
88
- };
89
- }
90
- function isCompactResultStatus(value) {
91
- return value === "aborted" || value === "completed" || value === "error";
92
- }
93
- function isRecord(value) {
94
- return typeof value === "object" && value !== null;
95
- }
96
- //#endregion
97
- export { buildDurableResumeGroups };
98
-
99
- //# sourceMappingURL=subagent-background-resume-group.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"subagent-background-resume-group.js","names":[],"sources":["../src/subagent-background-resume-group.ts"],"sourcesContent":["import type { ExecutionHost, RunRecord } from \"./execution/types\";\nimport type { AgentEvent } from \"./session/events\";\nimport type { DurableBackgroundChildRunState } from \"./subagent-background-child-run-state\";\nimport { readDurableBackgroundChildRunState } from \"./subagent-background-child-run-state\";\nimport { backgroundRunJobStatus, isActiveJob } from \"./subagent-job-state\";\nimport type {\n CompactSubagentResult,\n SubagentJob,\n SubagentJobGroup,\n} from \"./subagent-types\";\n\nexport async function buildDurableResumeGroups({\n currentJob,\n host,\n jobs,\n run,\n state,\n}: {\n readonly currentJob: SubagentJob;\n readonly host: ExecutionHost;\n readonly jobs: Map<string, SubagentJob>;\n readonly run: RunRecord;\n readonly state: DurableBackgroundChildRunState;\n}): Promise<Map<string, SubagentJobGroup>> {\n const groups = new Map<string, SubagentJobGroup>();\n if (!(state.groupId && run.parentRunId)) {\n return groups;\n }\n\n const group: SubagentJobGroup = {\n completedEvents: [],\n failedNotifiedJobIds: new Set(),\n finalNotified: false,\n id: state.groupId,\n jobIds: new Set(),\n };\n groups.set(group.id, group);\n\n for (const sibling of await host.store.runs.listByParentRunId(\n run.parentRunId\n )) {\n await addSiblingToGroup({\n currentJob,\n group,\n host,\n jobs,\n run,\n sibling,\n state,\n });\n }\n\n return groups;\n}\n\nasync function addSiblingToGroup({\n currentJob,\n group,\n host,\n jobs,\n run,\n sibling,\n state,\n}: {\n readonly currentJob: SubagentJob;\n readonly group: SubagentJobGroup;\n readonly host: ExecutionHost;\n readonly jobs: Map<string, SubagentJob>;\n readonly run: RunRecord;\n readonly sibling: RunRecord;\n readonly state: DurableBackgroundChildRunState;\n}): Promise<void> {\n if (sibling.kind !== \"background-subagent\") {\n return;\n }\n\n const siblingState = readDurableBackgroundChildRunState(\n await host.store.checkpoints.latest(sibling.runId)\n );\n if (!siblingState || siblingState.groupId !== state.groupId) {\n return;\n }\n\n const siblingJob =\n sibling.runId === run.runId\n ? currentJob\n : durableSiblingJob({ host, run: sibling, state: siblingState });\n jobs.set(siblingJob.id, siblingJob);\n group.jobIds.add(siblingJob.id);\n\n const endEvent = durableTerminalEvent(siblingJob, sibling.output);\n if (!endEvent || sibling.runId === run.runId) {\n return;\n }\n group.completedEvents.push(endEvent);\n if (\n endEvent.status === \"aborted\" ||\n endEvent.status === \"cancelled\" ||\n endEvent.status === \"error\"\n ) {\n group.failedNotifiedJobIds.add(siblingJob.id);\n }\n}\n\nfunction durableSiblingJob({\n host,\n run,\n state,\n}: {\n readonly host: ExecutionHost;\n readonly run: RunRecord;\n readonly state: DurableBackgroundChildRunState;\n}): SubagentJob {\n const status = backgroundRunJobStatus(run.status) ?? \"pending\";\n const compactResult = compactSubagentResult(run.output);\n return {\n abort: () => undefined,\n childRunId: run.runId,\n cleanup: () => Promise.resolve(),\n dedupeKey: run.dedupeKey,\n delegateToolCallId: state.delegateToolCallId,\n description: state.description,\n executionHost: host,\n groupId: state.groupId,\n id: run.publicTaskId ?? run.runId,\n parentRunId: run.parentRunId,\n parentSessionKey: state.parentSessionKey,\n promise: Promise.resolve(),\n result: compactResult,\n sessionKey: run.sessionKey,\n settled: !isActiveJob(status),\n status,\n subagent: state.subagent,\n };\n}\n\nfunction durableTerminalEvent(\n job: SubagentJob,\n output: unknown\n): Extract<AgentEvent, { type: \"subagent-job-end\" }> | null {\n if (job.status !== \"completed\" && job.status !== \"cancelled\") {\n return null;\n }\n\n const result = compactSubagentResult(output);\n return {\n error: result?.error,\n eventCount: result?.eventCount ?? 0,\n delegateToolCallId: job.delegateToolCallId,\n status: job.status,\n subagent: job.subagent,\n task_id: job.id,\n type: \"subagent-job-end\",\n };\n}\n\nfunction compactSubagentResult(\n output: unknown\n): CompactSubagentResult | undefined {\n if (!isRecord(output)) {\n return;\n }\n\n if (\n typeof output.eventCount !== \"number\" ||\n output.run_in_background !== false ||\n typeof output.subagent !== \"string\" ||\n typeof output.text !== \"string\" ||\n !isCompactResultStatus(output.result)\n ) {\n return;\n }\n\n return {\n ...(typeof output.error === \"string\" ? { error: output.error } : {}),\n eventCount: output.eventCount,\n result: output.result,\n run_in_background: false,\n subagent: output.subagent,\n text: output.text,\n };\n}\n\nfunction isCompactResultStatus(\n value: unknown\n): value is CompactSubagentResult[\"result\"] {\n return value === \"aborted\" || value === \"completed\" || value === \"error\";\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n"],"mappings":"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"}
@@ -1,115 +0,0 @@
1
- import { childRunStatus, updateBackgroundRunStatus } from "./subagent-background-child-run.js";
2
- import { notifyBackgroundCompletion } from "./subagent-background-notify.js";
3
- import { emitBackgroundJobUpdate } from "./subagent-job-observer.js";
4
- import { collectSubagentRunWithEvents } from "./subagent-run.js";
5
- //#region src/subagent-background-runner.ts
6
- const durableCancelPollMs = 250;
7
- async function runBackgroundJob({ childSession, groups, jobs, job, parentSession, prompt }) {
8
- if (job.status === "cancelled") return;
9
- job.status = "running";
10
- if (await syncDurableCancellation(job, childSession)) return;
11
- const stopCancelWatcher = startDurableCancellationWatcher(job, childSession);
12
- try {
13
- const { result } = await collectSubagentRunWithEvents(await childSession.send(prompt), job.subagent, (event) => emitBackgroundJobUpdate(parentSession, job, event));
14
- if (await syncDurableCancellation(job, childSession)) return;
15
- const previousResult = job.result;
16
- job.result = result;
17
- if (!await updateBackgroundRunStatus(job, childRunStatus(result.result))) {
18
- job.result = previousResult;
19
- job.status = "cancelled";
20
- childSession.interrupt();
21
- return;
22
- }
23
- job.status = result.result;
24
- } catch (error) {
25
- if (await syncDurableCancellation(job, childSession)) return;
26
- const jobError = error instanceof Error ? error : new Error(String(error));
27
- const previousResult = job.result;
28
- job.result = {
29
- error: errorMessage(jobError),
30
- eventCount: 0,
31
- result: "error",
32
- run_in_background: false,
33
- subagent: job.subagent,
34
- text: ""
35
- };
36
- if (!await updateBackgroundRunStatus(job, "error")) {
37
- job.result = previousResult;
38
- job.status = "cancelled";
39
- childSession.interrupt();
40
- return;
41
- }
42
- job.status = "error";
43
- } finally {
44
- stopCancelWatcher();
45
- }
46
- if (await syncDurableCancellation(job, childSession)) return;
47
- job.settled = true;
48
- await notifyBackgroundCompletion({
49
- endEvent: {
50
- error: job.result?.error,
51
- eventCount: job.result?.eventCount ?? 0,
52
- delegateToolCallId: job.delegateToolCallId,
53
- status: job.result?.result ?? "error",
54
- subagent: job.subagent,
55
- task_id: job.id,
56
- type: "subagent-job-end"
57
- },
58
- groups,
59
- job,
60
- jobs,
61
- parentSession
62
- });
63
- }
64
- function startDurableCancellationWatcher(job, childSession) {
65
- let stopped = false;
66
- let timeoutId;
67
- const poll = async () => {
68
- if (stopped) return;
69
- await syncDurableCancellation(job, childSession);
70
- if (stopped || job.status === "cancelled") return;
71
- timeoutId = setTimeout(() => {
72
- queueCancelPoll(poll, job, childSession);
73
- }, durableCancelPollMs);
74
- };
75
- queueCancelPoll(poll, job, childSession);
76
- return () => {
77
- stopped = true;
78
- if (timeoutId) clearTimeout(timeoutId);
79
- };
80
- }
81
- function queueCancelPoll(poll, job, childSession) {
82
- poll().catch((error) => {
83
- job.status = "error";
84
- job.result = {
85
- error: errorMessage(error),
86
- eventCount: 0,
87
- result: "error",
88
- run_in_background: false,
89
- subagent: job.subagent,
90
- text: ""
91
- };
92
- childSession.interrupt();
93
- });
94
- }
95
- async function syncDurableCancellation(job, childSession) {
96
- if (job.status === "cancelled") {
97
- childSession.interrupt();
98
- return true;
99
- }
100
- if (!(job.executionHost && job.childRunId)) return false;
101
- const run = await job.executionHost.store.runs.get(job.childRunId);
102
- const leaseLost = job.childRunLeaseId && run?.lease?.leaseId !== job.childRunLeaseId;
103
- if (run?.status !== "cancelled" && !leaseLost) return false;
104
- job.status = "cancelled";
105
- childSession.interrupt();
106
- return true;
107
- }
108
- function errorMessage(error) {
109
- if (error instanceof Error) return error.message;
110
- return String(error);
111
- }
112
- //#endregion
113
- export { runBackgroundJob };
114
-
115
- //# sourceMappingURL=subagent-background-runner.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"subagent-background-runner.js","names":[],"sources":["../src/subagent-background-runner.ts"],"sourcesContent":["import type { AgentInput } from \"./session/input\";\nimport {\n childRunStatus,\n updateBackgroundRunStatus,\n} from \"./subagent-background-child-run\";\nimport { notifyBackgroundCompletion } from \"./subagent-background-notify\";\nimport { emitBackgroundJobUpdate } from \"./subagent-job-observer\";\nimport { collectSubagentRunWithEvents } from \"./subagent-run\";\nimport type {\n RuntimeInputSink,\n Subagent,\n SubagentJob,\n SubagentJobGroup,\n} from \"./subagent-types\";\n\ntype BackgroundChildSession = ReturnType<Subagent[\"session\"]>;\n\nconst durableCancelPollMs = 250;\n\nexport async function runBackgroundJob({\n childSession,\n groups,\n jobs,\n job,\n parentSession,\n prompt,\n}: {\n readonly childSession: BackgroundChildSession;\n readonly groups: Map<string, SubagentJobGroup>;\n readonly jobs: Map<string, SubagentJob>;\n readonly job: SubagentJob;\n readonly parentSession: RuntimeInputSink;\n readonly prompt: AgentInput;\n}): Promise<void> {\n if (job.status === \"cancelled\") {\n return;\n }\n job.status = \"running\";\n if (await syncDurableCancellation(job, childSession)) {\n return;\n }\n\n const stopCancelWatcher = startDurableCancellationWatcher(job, childSession);\n try {\n const { result } = await collectSubagentRunWithEvents(\n await childSession.send(prompt),\n job.subagent,\n (event) => emitBackgroundJobUpdate(parentSession, job, event)\n );\n if (await syncDurableCancellation(job, childSession)) {\n return;\n }\n const previousResult = job.result;\n job.result = result;\n const updated = await updateBackgroundRunStatus(\n job,\n childRunStatus(result.result)\n );\n if (!updated) {\n job.result = previousResult;\n job.status = \"cancelled\";\n childSession.interrupt();\n return;\n }\n job.status = result.result;\n } catch (error) {\n if (await syncDurableCancellation(job, childSession)) {\n return;\n }\n const jobError = error instanceof Error ? error : new Error(String(error));\n const previousResult = job.result;\n job.result = {\n error: errorMessage(jobError),\n eventCount: 0,\n result: \"error\",\n run_in_background: false,\n subagent: job.subagent,\n text: \"\",\n };\n const updated = await updateBackgroundRunStatus(job, \"error\");\n if (!updated) {\n job.result = previousResult;\n job.status = \"cancelled\";\n childSession.interrupt();\n return;\n }\n job.status = \"error\";\n } finally {\n stopCancelWatcher();\n }\n\n if (await syncDurableCancellation(job, childSession)) {\n return;\n }\n\n job.settled = true;\n await notifyBackgroundCompletion({\n endEvent: {\n error: job.result?.error,\n eventCount: job.result?.eventCount ?? 0,\n delegateToolCallId: job.delegateToolCallId,\n status: job.result?.result ?? \"error\",\n subagent: job.subagent,\n task_id: job.id,\n type: \"subagent-job-end\",\n },\n groups,\n job,\n jobs,\n parentSession,\n });\n}\n\nfunction startDurableCancellationWatcher(\n job: SubagentJob,\n childSession: BackgroundChildSession\n): () => void {\n let stopped = false;\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n const poll = async (): Promise<void> => {\n if (stopped) {\n return;\n }\n await syncDurableCancellation(job, childSession);\n if (stopped || job.status === \"cancelled\") {\n return;\n }\n timeoutId = setTimeout(() => {\n queueCancelPoll(poll, job, childSession);\n }, durableCancelPollMs);\n };\n\n queueCancelPoll(poll, job, childSession);\n return () => {\n stopped = true;\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n };\n}\n\nfunction queueCancelPoll(\n poll: () => Promise<void>,\n job: SubagentJob,\n childSession: BackgroundChildSession\n): void {\n poll().catch((error: unknown) => {\n job.status = \"error\";\n job.result = {\n error: errorMessage(error),\n eventCount: 0,\n result: \"error\",\n run_in_background: false,\n subagent: job.subagent,\n text: \"\",\n };\n childSession.interrupt();\n });\n}\n\nasync function syncDurableCancellation(\n job: SubagentJob,\n childSession: BackgroundChildSession\n): Promise<boolean> {\n if (job.status === \"cancelled\") {\n childSession.interrupt();\n return true;\n }\n if (!(job.executionHost && job.childRunId)) {\n return false;\n }\n\n const run = await job.executionHost.store.runs.get(job.childRunId);\n const leaseLost =\n job.childRunLeaseId && run?.lease?.leaseId !== job.childRunLeaseId;\n if (run?.status !== \"cancelled\" && !leaseLost) {\n return false;\n }\n\n job.status = \"cancelled\";\n childSession.interrupt();\n return true;\n}\n\nfunction errorMessage(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n\n return String(error);\n}\n"],"mappings":"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"}
@@ -1,43 +0,0 @@
1
- import { registerBackgroundJobGroup } from "./subagent-background-notify.js";
2
- //#region src/subagent-background-schedule.ts
3
- async function scheduleDurableBackgroundJob({ childRun, delegateToolCallId, description, executionHost, groupId, groups, id, jobs, parentRunId, parentSession, parentSessionKey, ownerNamespace, subagent }) {
4
- const job = {
5
- abort: () => void 0,
6
- childRunId: childRun.runId,
7
- cleanup: () => Promise.resolve(),
8
- dedupeKey: childRun.dedupeKey,
9
- description,
10
- id,
11
- delegateToolCallId,
12
- executionHost,
13
- ownerNamespace,
14
- parentSessionKey,
15
- parentRunId,
16
- promise: Promise.resolve(),
17
- groupId,
18
- sessionKey: childRun.sessionKey,
19
- settled: true,
20
- status: "pending",
21
- subagent
22
- };
23
- jobs.set(id, job);
24
- registerBackgroundJobGroup({
25
- groupId,
26
- groups,
27
- job
28
- });
29
- await parentSession.emitObserverEvent({
30
- description,
31
- delegateToolCallId,
32
- run_in_background: true,
33
- subagent,
34
- task_id: id,
35
- type: "subagent-job-start"
36
- });
37
- await executionHost.scheduler.enqueueRun(childRun.runId);
38
- return job;
39
- }
40
- //#endregion
41
- export { scheduleDurableBackgroundJob };
42
-
43
- //# sourceMappingURL=subagent-background-schedule.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"subagent-background-schedule.js","names":[],"sources":["../src/subagent-background-schedule.ts"],"sourcesContent":["import type { RunRecord } from \"./execution/types\";\nimport { registerBackgroundJobGroup } from \"./subagent-background-notify\";\nimport type {\n RuntimeInputSink,\n SubagentJob,\n SubagentJobGroup,\n} from \"./subagent-types\";\n\nexport async function scheduleDurableBackgroundJob({\n childRun,\n delegateToolCallId,\n description,\n executionHost,\n groupId,\n groups,\n id,\n jobs,\n parentRunId,\n parentSession,\n parentSessionKey,\n ownerNamespace,\n subagent,\n}: {\n readonly childRun: RunRecord;\n readonly delegateToolCallId?: string;\n readonly description?: string;\n readonly executionHost: NonNullable<SubagentJob[\"executionHost\"]>;\n readonly groupId?: string;\n readonly groups: Map<string, SubagentJobGroup>;\n readonly id: string;\n readonly jobs: Map<string, SubagentJob>;\n readonly parentRunId?: string;\n readonly parentSession: RuntimeInputSink;\n readonly parentSessionKey?: string;\n readonly ownerNamespace?: string;\n readonly subagent: string;\n}): Promise<SubagentJob> {\n const job: SubagentJob = {\n abort: () => undefined,\n childRunId: childRun.runId,\n cleanup: () => Promise.resolve(),\n dedupeKey: childRun.dedupeKey,\n description,\n id,\n delegateToolCallId,\n executionHost,\n ownerNamespace,\n parentSessionKey,\n parentRunId,\n promise: Promise.resolve(),\n groupId,\n sessionKey: childRun.sessionKey,\n settled: true,\n status: \"pending\",\n subagent,\n };\n jobs.set(id, job);\n registerBackgroundJobGroup({ groupId, groups, job });\n await parentSession.emitObserverEvent({\n description,\n delegateToolCallId,\n run_in_background: true,\n subagent,\n task_id: id,\n type: \"subagent-job-start\",\n });\n await executionHost.scheduler.enqueueRun(childRun.runId);\n return job;\n}\n"],"mappings":";;AAQA,eAAsB,6BAA6B,EACjD,UACA,oBACA,aACA,eACA,SACA,QACA,IACA,MACA,aACA,eACA,kBACA,gBACA,YAeuB;CACvB,MAAM,MAAmB;EACvB,aAAa,KAAA;EACb,YAAY,SAAS;EACrB,eAAe,QAAQ,QAAQ;EAC/B,WAAW,SAAS;EACpB;EACA;EACA;EACA;EACA;EACA;EACA;EACA,SAAS,QAAQ,QAAQ;EACzB;EACA,YAAY,SAAS;EACrB,SAAS;EACT,QAAQ;EACR;CACF;CACA,KAAK,IAAI,IAAI,GAAG;CAChB,2BAA2B;EAAE;EAAS;EAAQ;CAAI,CAAC;CACnD,MAAM,cAAc,kBAAkB;EACpC;EACA;EACA,mBAAmB;EACnB;EACA,SAAS;EACT,MAAM;CACR,CAAC;CACD,MAAM,cAAc,UAAU,WAAW,SAAS,KAAK;CACvD,OAAO;AACT"}
@@ -1,68 +0,0 @@
1
- import { runBlockingDelegation } from "./subagent-run.js";
2
- //#region src/subagent-child-run.ts
3
- async function runBlockingChild({ abortSignal, dedupeKey, executionHost, parentRunId, prompt, sessionKey, subagent }) {
4
- const run = await getOrCreateBlockingChildRun({
5
- dedupeKey,
6
- executionHost,
7
- parentRunId,
8
- sessionKey
9
- });
10
- const result = await runBlockingDelegation({
11
- abortSignal,
12
- prompt,
13
- sessionKey,
14
- subagent
15
- });
16
- if (executionHost && run) await executionHost.store.runs.update({
17
- ...run,
18
- checkpointVersion: run.checkpointVersion,
19
- status: childRunStatus(result.result)
20
- });
21
- return result;
22
- }
23
- function blockingSubagentDedupeKey(parentRunId, toolCallId) {
24
- return `blocking-subagent:${parentRunId}:${toolCallId ?? "unknown"}`;
25
- }
26
- async function getOrCreateBlockingChildRun({ dedupeKey, executionHost, parentRunId, sessionKey }) {
27
- if (!executionHost) return;
28
- const existing = await executionHost.store.runs.getByDedupeKey(dedupeKey);
29
- if (existing) return existing;
30
- const run = {
31
- checkpointVersion: 0,
32
- dedupeKey,
33
- kind: "subagent",
34
- parentRunId,
35
- rootRunId: parentRunId,
36
- runId: `child:${dedupeKey}`,
37
- sessionKey,
38
- status: "queued"
39
- };
40
- await executionHost.store.runs.create(run);
41
- await executionHost.store.checkpoints.append({
42
- checkpointId: crypto.randomUUID(),
43
- phase: "before-child-run",
44
- runId: run.runId,
45
- runtimeState: {},
46
- sessionSnapshot: {},
47
- version: 1
48
- }, { expectedVersion: 0 });
49
- await executionHost.store.checkpoints.append({
50
- checkpointId: crypto.randomUUID(),
51
- childRunId: run.runId,
52
- phase: "child-linked",
53
- runId: run.runId,
54
- runtimeState: {},
55
- sessionSnapshot: {},
56
- version: 2
57
- }, { expectedVersion: 1 });
58
- return await executionHost.store.runs.get(run.runId) ?? run;
59
- }
60
- function childRunStatus(result) {
61
- if (result === "aborted") return "cancelled";
62
- if (result === "error") return "error";
63
- return "completed";
64
- }
65
- //#endregion
66
- export { blockingSubagentDedupeKey, runBlockingChild };
67
-
68
- //# sourceMappingURL=subagent-child-run.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"subagent-child-run.js","names":[],"sources":["../src/subagent-child-run.ts"],"sourcesContent":["import type { ExecutionHost, RunRecord, RunStatus } from \"./execution/types\";\nimport type { AgentInput } from \"./session/input\";\nimport { runBlockingDelegation } from \"./subagent-run\";\nimport type { CompactSubagentResult, Subagent } from \"./subagent-types\";\n\nexport type BlockingSubagentRunCache = Map<\n string,\n Promise<CompactSubagentResult>\n>;\n\nexport async function runBlockingChild({\n abortSignal,\n dedupeKey,\n executionHost,\n parentRunId,\n prompt,\n sessionKey,\n subagent,\n}: {\n readonly abortSignal?: AbortSignal;\n readonly dedupeKey: string;\n readonly executionHost?: ExecutionHost;\n readonly parentRunId: string;\n readonly prompt: AgentInput;\n readonly sessionKey: string;\n readonly subagent: Subagent;\n}): Promise<CompactSubagentResult> {\n const run = await getOrCreateBlockingChildRun({\n dedupeKey,\n executionHost,\n parentRunId,\n sessionKey,\n });\n const result = await runBlockingDelegation({\n abortSignal,\n prompt,\n sessionKey,\n subagent,\n });\n if (executionHost && run) {\n await executionHost.store.runs.update({\n ...run,\n checkpointVersion: run.checkpointVersion,\n status: childRunStatus(result.result),\n });\n }\n return result;\n}\n\nexport function blockingSubagentDedupeKey(\n parentRunId: string,\n toolCallId: string | undefined\n): string {\n return `blocking-subagent:${parentRunId}:${toolCallId ?? \"unknown\"}`;\n}\n\nasync function getOrCreateBlockingChildRun({\n dedupeKey,\n executionHost,\n parentRunId,\n sessionKey,\n}: {\n readonly dedupeKey: string;\n readonly executionHost?: ExecutionHost;\n readonly parentRunId: string;\n readonly sessionKey: string;\n}): Promise<RunRecord | undefined> {\n if (!executionHost) {\n return;\n }\n\n const existing = await executionHost.store.runs.getByDedupeKey(dedupeKey);\n if (existing) {\n return existing;\n }\n\n const run: RunRecord = {\n checkpointVersion: 0,\n dedupeKey,\n kind: \"subagent\",\n parentRunId,\n rootRunId: parentRunId,\n runId: `child:${dedupeKey}`,\n sessionKey,\n status: \"queued\",\n };\n await executionHost.store.runs.create(run);\n await executionHost.store.checkpoints.append(\n {\n checkpointId: crypto.randomUUID(),\n phase: \"before-child-run\",\n runId: run.runId,\n runtimeState: {},\n sessionSnapshot: {},\n version: 1,\n },\n { expectedVersion: 0 }\n );\n await executionHost.store.checkpoints.append(\n {\n checkpointId: crypto.randomUUID(),\n childRunId: run.runId,\n phase: \"child-linked\",\n runId: run.runId,\n runtimeState: {},\n sessionSnapshot: {},\n version: 2,\n },\n { expectedVersion: 1 }\n );\n const linked = await executionHost.store.runs.get(run.runId);\n return linked ?? run;\n}\n\nfunction childRunStatus(\n result: CompactSubagentResult[\"result\"]\n): Extract<RunStatus, \"cancelled\" | \"completed\" | \"error\"> {\n if (result === \"aborted\") {\n return \"cancelled\";\n }\n\n if (result === \"error\") {\n return \"error\";\n }\n\n return \"completed\";\n}\n"],"mappings":";;AAUA,eAAsB,iBAAiB,EACrC,aACA,WACA,eACA,aACA,QACA,YACA,YASiC;CACjC,MAAM,MAAM,MAAM,4BAA4B;EAC5C;EACA;EACA;EACA;CACF,CAAC;CACD,MAAM,SAAS,MAAM,sBAAsB;EACzC;EACA;EACA;EACA;CACF,CAAC;CACD,IAAI,iBAAiB,KACnB,MAAM,cAAc,MAAM,KAAK,OAAO;EACpC,GAAG;EACH,mBAAmB,IAAI;EACvB,QAAQ,eAAe,OAAO,MAAM;CACtC,CAAC;CAEH,OAAO;AACT;AAEA,SAAgB,0BACd,aACA,YACQ;CACR,OAAO,qBAAqB,YAAY,GAAG,cAAc;AAC3D;AAEA,eAAe,4BAA4B,EACzC,WACA,eACA,aACA,cAMiC;CACjC,IAAI,CAAC,eACH;CAGF,MAAM,WAAW,MAAM,cAAc,MAAM,KAAK,eAAe,SAAS;CACxE,IAAI,UACF,OAAO;CAGT,MAAM,MAAiB;EACrB,mBAAmB;EACnB;EACA,MAAM;EACN;EACA,WAAW;EACX,OAAO,SAAS;EAChB;EACA,QAAQ;CACV;CACA,MAAM,cAAc,MAAM,KAAK,OAAO,GAAG;CACzC,MAAM,cAAc,MAAM,YAAY,OACpC;EACE,cAAc,OAAO,WAAW;EAChC,OAAO;EACP,OAAO,IAAI;EACX,cAAc,CAAC;EACf,iBAAiB,CAAC;EAClB,SAAS;CACX,GACA,EAAE,iBAAiB,EAAE,CACvB;CACA,MAAM,cAAc,MAAM,YAAY,OACpC;EACE,cAAc,OAAO,WAAW;EAChC,YAAY,IAAI;EAChB,OAAO;EACP,OAAO,IAAI;EACX,cAAc,CAAC;EACf,iBAAiB,CAAC;EAClB,SAAS;CACX,GACA,EAAE,iBAAiB,EAAE,CACvB;CAEA,OAAO,MADc,cAAc,MAAM,KAAK,IAAI,IAAI,KAAK,KAC1C;AACnB;AAEA,SAAS,eACP,QACyD;CACzD,IAAI,WAAW,WACb,OAAO;CAGT,IAAI,WAAW,SACb,OAAO;CAGT,OAAO;AACT"}
@@ -1,84 +0,0 @@
1
- import { cancelBackgroundChildRun } from "./subagent-background-child-run.js";
2
- import { assertBackgroundTaskId, backgroundRunJobStatus, cancelJob, isActiveJob } from "./subagent-job-state.js";
3
- import { jsonSchema, tool } from "ai";
4
- //#region src/subagent-job-cancel.ts
5
- function createBackgroundCancelTool(jobs, executionHost, scope) {
6
- return tool({
7
- description: "Cancel an active background subagent job.",
8
- execute: async (input) => {
9
- assertBackgroundTaskId(input.task_id, "background_cancel");
10
- const job = jobs.get(input.task_id);
11
- if (!job) {
12
- const durableCancel = await durableBackgroundCancel(input.task_id, executionHost, scope);
13
- if (durableCancel) return durableCancel;
14
- throw new Error(`Unknown background subagent task ${input.task_id}.`);
15
- }
16
- const durableLocalCancel = await cancelDurableLocalJob(job, scope);
17
- if (durableLocalCancel) return durableLocalCancel;
18
- if (isActiveJob(job.status)) cancelJob(job);
19
- return {
20
- status: job.status,
21
- task_id: job.id
22
- };
23
- },
24
- inputSchema: jsonSchema({
25
- additionalProperties: false,
26
- properties: { task_id: { type: "string" } },
27
- required: ["task_id"],
28
- type: "object"
29
- })
30
- });
31
- }
32
- async function cancelDurableLocalJob(job, scope) {
33
- if (!(job.executionHost && job.childRunId)) return null;
34
- const record = await job.executionHost.store.runs.get(job.childRunId);
35
- if (record?.kind !== "background-subagent") return null;
36
- if (scope && !record.sessionKey.startsWith(scope.childSessionKeyPrefix)) return null;
37
- const currentStatus = backgroundRunJobStatus(record.status);
38
- if (!currentStatus) return null;
39
- if (currentStatus === "pending" || currentStatus === "running") {
40
- const nextStatus = backgroundRunJobStatus((await cancelBackgroundChildRun({
41
- executionHost: job.executionHost,
42
- runId: record.runId
43
- }))?.status);
44
- if (nextStatus === "cancelled") {
45
- cancelJob(job);
46
- return {
47
- status: "cancelled",
48
- task_id: job.id
49
- };
50
- }
51
- return {
52
- status: nextStatus ?? currentStatus,
53
- task_id: job.id
54
- };
55
- }
56
- return {
57
- status: currentStatus,
58
- task_id: job.id
59
- };
60
- }
61
- async function durableBackgroundCancel(taskId, executionHost, scope) {
62
- if (!executionHost) return null;
63
- const host = executionHost;
64
- const record = await host.store.runs.get(`background:${taskId}`);
65
- if (record?.kind !== "background-subagent") return null;
66
- if (scope && !record.sessionKey.startsWith(scope.childSessionKeyPrefix)) return null;
67
- const currentStatus = backgroundRunJobStatus(record.status);
68
- if (!currentStatus) return null;
69
- if (currentStatus === "pending" || currentStatus === "running") return {
70
- status: backgroundRunJobStatus((await cancelBackgroundChildRun({
71
- executionHost: host,
72
- runId: record.runId
73
- }))?.status) ?? currentStatus,
74
- task_id: taskId
75
- };
76
- return {
77
- status: currentStatus,
78
- task_id: taskId
79
- };
80
- }
81
- //#endregion
82
- export { createBackgroundCancelTool };
83
-
84
- //# sourceMappingURL=subagent-job-cancel.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"subagent-job-cancel.js","names":[],"sources":["../src/subagent-job-cancel.ts"],"sourcesContent":["import { jsonSchema, tool } from \"ai\";\nimport type { ExecutionHost } from \"./execution/types\";\nimport { cancelBackgroundChildRun } from \"./subagent-background-child-run\";\nimport {\n assertBackgroundTaskId,\n backgroundRunJobStatus,\n cancelJob,\n isActiveJob,\n} from \"./subagent-job-state\";\nimport type { BackgroundCancelInput, SubagentJob } from \"./subagent-types\";\n\ninterface BackgroundToolScope {\n readonly childSessionKeyPrefix: string;\n}\n\nexport function createBackgroundCancelTool(\n jobs: Map<string, SubagentJob>,\n executionHost?: ExecutionHost,\n scope?: BackgroundToolScope\n) {\n return tool<BackgroundCancelInput, unknown, Record<string, unknown>>({\n description: \"Cancel an active background subagent job.\",\n execute: async (input: BackgroundCancelInput) => {\n assertBackgroundTaskId(input.task_id, \"background_cancel\");\n const job = jobs.get(input.task_id);\n if (!job) {\n const durableCancel = await durableBackgroundCancel(\n input.task_id,\n executionHost,\n scope\n );\n if (durableCancel) {\n return durableCancel;\n }\n\n throw new Error(`Unknown background subagent task ${input.task_id}.`);\n }\n\n const durableLocalCancel = await cancelDurableLocalJob(job, scope);\n if (durableLocalCancel) {\n return durableLocalCancel;\n }\n\n if (isActiveJob(job.status)) {\n cancelJob(job);\n }\n\n return {\n status: job.status,\n task_id: job.id,\n };\n },\n inputSchema: jsonSchema<BackgroundCancelInput>({\n additionalProperties: false,\n properties: {\n task_id: { type: \"string\" },\n },\n required: [\"task_id\"],\n type: \"object\",\n }),\n });\n}\n\nasync function cancelDurableLocalJob(\n job: SubagentJob,\n scope: BackgroundToolScope | undefined\n): Promise<Record<string, unknown> | null> {\n if (!(job.executionHost && job.childRunId)) {\n return null;\n }\n\n const record = await job.executionHost.store.runs.get(job.childRunId);\n if (record?.kind !== \"background-subagent\") {\n return null;\n }\n if (scope && !record.sessionKey.startsWith(scope.childSessionKeyPrefix)) {\n return null;\n }\n\n const currentStatus = backgroundRunJobStatus(record.status);\n if (!currentStatus) {\n return null;\n }\n if (currentStatus === \"pending\" || currentStatus === \"running\") {\n const cancelled = await cancelBackgroundChildRun({\n executionHost: job.executionHost,\n runId: record.runId,\n });\n const nextStatus = backgroundRunJobStatus(cancelled?.status);\n if (nextStatus === \"cancelled\") {\n cancelJob(job);\n return { status: \"cancelled\", task_id: job.id };\n }\n\n return { status: nextStatus ?? currentStatus, task_id: job.id };\n }\n\n return { status: currentStatus, task_id: job.id };\n}\n\nasync function durableBackgroundCancel(\n taskId: string,\n executionHost: ExecutionHost | undefined,\n scope: BackgroundToolScope | undefined\n): Promise<Record<string, unknown> | null> {\n if (!executionHost) {\n return null;\n }\n const host = executionHost;\n\n const record = await host.store.runs.get(`background:${taskId}`);\n if (record?.kind !== \"background-subagent\") {\n return null;\n }\n if (scope && !record.sessionKey.startsWith(scope.childSessionKeyPrefix)) {\n return null;\n }\n\n const currentStatus = backgroundRunJobStatus(record.status);\n if (!currentStatus) {\n return null;\n }\n\n if (currentStatus === \"pending\" || currentStatus === \"running\") {\n const cancelled = await cancelBackgroundChildRun({\n executionHost: host,\n runId: record.runId,\n });\n return {\n status: backgroundRunJobStatus(cancelled?.status) ?? currentStatus,\n task_id: taskId,\n };\n }\n\n return { status: currentStatus, task_id: taskId };\n}\n"],"mappings":";;;;AAeA,SAAgB,2BACd,MACA,eACA,OACA;CACA,OAAO,KAA8D;EACnE,aAAa;EACb,SAAS,OAAO,UAAiC;GAC/C,uBAAuB,MAAM,SAAS,mBAAmB;GACzD,MAAM,MAAM,KAAK,IAAI,MAAM,OAAO;GAClC,IAAI,CAAC,KAAK;IACR,MAAM,gBAAgB,MAAM,wBAC1B,MAAM,SACN,eACA,KACF;IACA,IAAI,eACF,OAAO;IAGT,MAAM,IAAI,MAAM,oCAAoC,MAAM,QAAQ,EAAE;GACtE;GAEA,MAAM,qBAAqB,MAAM,sBAAsB,KAAK,KAAK;GACjE,IAAI,oBACF,OAAO;GAGT,IAAI,YAAY,IAAI,MAAM,GACxB,UAAU,GAAG;GAGf,OAAO;IACL,QAAQ,IAAI;IACZ,SAAS,IAAI;GACf;EACF;EACA,aAAa,WAAkC;GAC7C,sBAAsB;GACtB,YAAY,EACV,SAAS,EAAE,MAAM,SAAS,EAC5B;GACA,UAAU,CAAC,SAAS;GACpB,MAAM;EACR,CAAC;CACH,CAAC;AACH;AAEA,eAAe,sBACb,KACA,OACyC;CACzC,IAAI,EAAE,IAAI,iBAAiB,IAAI,aAC7B,OAAO;CAGT,MAAM,SAAS,MAAM,IAAI,cAAc,MAAM,KAAK,IAAI,IAAI,UAAU;CACpE,IAAI,QAAQ,SAAS,uBACnB,OAAO;CAET,IAAI,SAAS,CAAC,OAAO,WAAW,WAAW,MAAM,qBAAqB,GACpE,OAAO;CAGT,MAAM,gBAAgB,uBAAuB,OAAO,MAAM;CAC1D,IAAI,CAAC,eACH,OAAO;CAET,IAAI,kBAAkB,aAAa,kBAAkB,WAAW;EAK9D,MAAM,aAAa,wBAAuB,MAJlB,yBAAyB;GAC/C,eAAe,IAAI;GACnB,OAAO,OAAO;EAChB,CAAC,IACoD,MAAM;EAC3D,IAAI,eAAe,aAAa;GAC9B,UAAU,GAAG;GACb,OAAO;IAAE,QAAQ;IAAa,SAAS,IAAI;GAAG;EAChD;EAEA,OAAO;GAAE,QAAQ,cAAc;GAAe,SAAS,IAAI;EAAG;CAChE;CAEA,OAAO;EAAE,QAAQ;EAAe,SAAS,IAAI;CAAG;AAClD;AAEA,eAAe,wBACb,QACA,eACA,OACyC;CACzC,IAAI,CAAC,eACH,OAAO;CAET,MAAM,OAAO;CAEb,MAAM,SAAS,MAAM,KAAK,MAAM,KAAK,IAAI,cAAc,QAAQ;CAC/D,IAAI,QAAQ,SAAS,uBACnB,OAAO;CAET,IAAI,SAAS,CAAC,OAAO,WAAW,WAAW,MAAM,qBAAqB,GACpE,OAAO;CAGT,MAAM,gBAAgB,uBAAuB,OAAO,MAAM;CAC1D,IAAI,CAAC,eACH,OAAO;CAGT,IAAI,kBAAkB,aAAa,kBAAkB,WAKnD,OAAO;EACL,QAAQ,wBAAuB,MALT,yBAAyB;GAC/C,eAAe;GACf,OAAO,OAAO;EAChB,CAAC,IAE2C,MAAM,KAAK;EACrD,SAAS;CACX;CAGF,OAAO;EAAE,QAAQ;EAAe,SAAS;CAAO;AAClD"}
@@ -1,19 +0,0 @@
1
- //#region src/subagent-job-observer.ts
2
- function emitBackgroundJobUpdate(parentSession, job, event) {
3
- if (!isParentVisibleJobUpdate(event)) return Promise.resolve();
4
- return parentSession.emitObserverEvent({
5
- eventType: event.type,
6
- delegateToolCallId: job.delegateToolCallId,
7
- status: job.status,
8
- subagent: job.subagent,
9
- task_id: job.id,
10
- type: "subagent-job-update"
11
- });
12
- }
13
- function isParentVisibleJobUpdate(event) {
14
- return event.type === "assistant-text" || event.type === "tool-call" || event.type === "tool-result" || event.type === "turn-abort" || event.type === "turn-error";
15
- }
16
- //#endregion
17
- export { emitBackgroundJobUpdate };
18
-
19
- //# sourceMappingURL=subagent-job-observer.js.map