@desplega.ai/agent-swarm 1.145.0 → 1.147.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.
Files changed (221) hide show
  1. package/README.md +2 -1
  2. package/dist/{acp-adapter-580t41c0.js → acp-adapter-9n319wqc.js} +61 -6
  3. package/dist/{actions-m662tjng.js → actions-2vxqvpr9.js} +9 -8
  4. package/dist/{app-zb3rndm8.js → app-w066xfy0.js} +6 -5
  5. package/dist/assistant-kt31dj2h.js +236 -0
  6. package/dist/{boot-reembed-072x00vn.js → boot-reembed-az5rassp.js} +7 -6
  7. package/dist/{boot-reembed-65zz2smt.js → boot-reembed-j3mm3rfz.js} +8 -7
  8. package/dist/{boot-scrub-logs-yz0ams04.js → boot-scrub-logs-b6h54817.js} +4 -4
  9. package/dist/{claude-adapter-paj270y2.js → claude-adapter-w1z04ann.js} +8 -6
  10. package/dist/{claude-managed-setup-w619jncn.js → claude-managed-setup-f5pmsyrp.js} +24 -3
  11. package/dist/{claude-sdk-session-swt80j9z.js → claude-sdk-session-f0cc1kec.js} +8 -6
  12. package/dist/{cli-dt553ktb.js → cli-0b6y7kxm.js} +1 -1
  13. package/dist/{cli-bxdhw615.js → cli-12fz972k.js} +4 -4
  14. package/dist/{cli-s2f20r5w.js → cli-1th1728g.js} +2 -2
  15. package/dist/{cli-rs6ec3b9.js → cli-3tgwnf43.js} +3 -3
  16. package/dist/{cli-gxnzc6wh.js → cli-4nr988h6.js} +1 -1
  17. package/dist/{cli-axs8e6d4.js → cli-53s590z8.js} +1 -1
  18. package/dist/{cli-ygbjp3z8.js → cli-54wwve05.js} +5 -4
  19. package/dist/{cli-v0asr5yv.js → cli-719k9j2c.js} +2 -2
  20. package/dist/{cli-anktweqr.js → cli-89xfd7f9.js} +21 -47
  21. package/dist/{cli-q34a0e10.js → cli-8v0g1yc8.js} +1 -1
  22. package/dist/cli-9d8ntetj.js +42 -0
  23. package/dist/{cli-z9fprcrf.js → cli-atcve9y8.js} +881 -738
  24. package/dist/{cli-jmb7g47h.js → cli-b5bq9crk.js} +14 -31
  25. package/dist/cli-d8brzxjb.js +190 -0
  26. package/dist/{cli-gzky0gkr.js → cli-de14znh8.js} +2 -2
  27. package/dist/{cli-xytwff7f.js → cli-dttph1bw.js} +2 -2
  28. package/dist/cli-ep19k3mb.js +19 -0
  29. package/dist/{cli-m1xa8be7.js → cli-f146mn5s.js} +7 -50
  30. package/dist/{cli-1fj0chdk.js → cli-f7dsy61y.js} +5 -3
  31. package/dist/{cli-f567d5c1.js → cli-ftht3zzj.js} +2782 -2589
  32. package/dist/{cli-a0g1gbt5.js → cli-hbv0kq6w.js} +2 -2
  33. package/dist/{cli-fhsz3twr.js → cli-jsp14b6c.js} +171 -1
  34. package/dist/{cli-7fnkj1hj.js → cli-kpv03zhj.js} +21 -17
  35. package/dist/{cli-m4j6trn4.js → cli-m8yrsg97.js} +2 -2
  36. package/dist/cli-m9sxbkhm.js +779 -0
  37. package/dist/cli-mmemxxdc.js +823 -0
  38. package/dist/{cli-tqtvj5pt.js → cli-n8508nre.js} +1 -1
  39. package/dist/{cli-z96t0thj.js → cli-p1d5b073.js} +37 -2
  40. package/dist/{cli-gh8y8f36.js → cli-rw51bq3j.js} +13 -10
  41. package/dist/{cli-59ej1c07.js → cli-smby5m17.js} +7 -6
  42. package/dist/{cli-65vqzz3v.js → cli-tzvk9haz.js} +94 -372
  43. package/dist/{cli-dc9k2ba9.js → cli-w9kb3bk1.js} +1 -1
  44. package/dist/{cli-kpev657q.js → cli-y6b6fb76.js} +25 -3
  45. package/dist/{cli-123q2get.js → cli-yz3djrm0.js} +9 -9
  46. package/dist/{cli-wvp6bvy4.js → cli-zhjmqxzh.js} +1 -1
  47. package/dist/cli.js +13 -13
  48. package/dist/{codex-adapter-k98vaw2r.js → codex-adapter-zw4dwsx7.js} +2 -2
  49. package/dist/{codex-hook-9pf19cks.js → codex-hook-bw8p5nh4.js} +2 -2
  50. package/dist/{codex-session-runner-tngtphx7.js → codex-session-runner-k981s65v.js} +2 -2
  51. package/dist/{commands-y8nbr3fv.js → commands-sykrxx7e.js} +4 -4
  52. package/dist/{db-30p4h2t1.js → db-sfbsc8wt.js} +6 -4
  53. package/dist/handlers-0aspcejm.js +603 -0
  54. package/dist/{hook-dcw4jfbj.js → hook-4nvqj2sb.js} +7 -5
  55. package/dist/{hook-21jexvfx.js → hook-hxccs7m5.js} +24 -49
  56. package/dist/{http-r4kq5g8d.js → http-y06z517d.js} +230 -94
  57. package/dist/{index-q3qja6ta.js → index-hssww7kj.js} +15 -14
  58. package/dist/{index-gay66b9w.js → index-k8znfx0z.js} +13 -12
  59. package/dist/{index-53zyht4z.js → index-tce1rss4.js} +371 -110
  60. package/dist/{index-nqvf26za.js → index-x5j894zf.js} +14 -13
  61. package/dist/{keepalive-xs8fa55y.js → keepalive-w733ax66.js} +6 -6
  62. package/dist/{lead-d9m2t4s0.js → lead-75bjqa9d.js} +29 -27
  63. package/dist/{maintenance-3zh82g6z.js → maintenance-w4f1zjck.js} +8 -7
  64. package/dist/{oauth-refresh-sweep-03snsye5.js → oauth-refresh-sweep-wdetky26.js} +5 -5
  65. package/dist/{onboard-0cg1925x.js → onboard-bb5net8s.js} +2 -2
  66. package/dist/{otel-impl-0ab95z27.js → otel-impl-0w7c14ap.js} +1 -1
  67. package/dist/{pi-mono-adapter-dtkz4e7j.js → pi-mono-adapter-2has4gnp.js} +12 -2
  68. package/dist/{pricing-refresh-e5jhzz4j.js → pricing-refresh-9nzsrgcq.js} +6 -6
  69. package/dist/{rbac-roles-p1mf40z3.js → rbac-roles-r3hqjp09.js} +5 -5
  70. package/dist/{rbac-roles-2w3cmrkc.js → rbac-roles-z1jrffbt.js} +4 -4
  71. package/dist/{registry-9kdck5ye.js → registry-v5wytg0s.js} +1 -2
  72. package/dist/{render-v2-xhawry3k.js → render-v2-vbr89fnb.js} +6 -5
  73. package/dist/{seed-pricing-t223sw91.js → seed-pricing-g62hy1pk.js} +7 -5
  74. package/dist/{setup-zcs0rce7.js → setup-gnfqnptp.js} +2 -2
  75. package/dist/{worker-qnp2ka62.js → worker-kznxp4qm.js} +29 -27
  76. package/openapi.json +263 -12
  77. package/package.json +1 -1
  78. package/plugin/commands/start-worker.md +4 -9
  79. package/plugin/pi-skills/start-worker/SKILL.md +4 -9
  80. package/src/be/db/agents.ts +556 -0
  81. package/src/be/db/context-versions.ts +117 -0
  82. package/src/be/db/runtime.ts +406 -0
  83. package/src/be/db/tasks/read.ts +1167 -0
  84. package/src/be/db/tasks/write.ts +953 -0
  85. package/src/be/db.ts +584 -3429
  86. package/src/be/migrations/147_scheduled_tasks_parent_task.sql +7 -0
  87. package/src/be/migrations/148_pages_svg.sql +123 -0
  88. package/src/be/migrations/149_session_tokens.sql +24 -0
  89. package/src/be/scripts/typecheck.ts +1 -0
  90. package/src/be/seed-pricing.ts +13 -8
  91. package/src/be/seed-scripts/catalog/ops-catalog-audit.inline.ts +1 -1
  92. package/src/be/seed-scripts/catalog/ops-catalog-audit.ts +1 -1
  93. package/src/be/seed-scripts/catalog/star-history-refresh.ts +101 -0
  94. package/src/be/seed-scripts/catalog/star-history-renderer.ts +119 -0
  95. package/src/be/seed-scripts/index.ts +17 -0
  96. package/src/be/seed-skills/index.ts +14 -0
  97. package/src/be/swarm-config-guard.ts +5 -2
  98. package/src/be/task-attachment-store.ts +70 -0
  99. package/src/be/users.ts +77 -0
  100. package/src/commands/attachments-section.ts +37 -0
  101. package/src/commands/claude-managed-setup.ts +45 -3
  102. package/src/commands/claude-md-session.ts +408 -0
  103. package/src/commands/context-preamble.ts +15 -3
  104. package/src/commands/profile-sync.ts +205 -5
  105. package/src/commands/provider-credentials.ts +60 -27
  106. package/src/commands/runner.ts +63 -58
  107. package/src/commands/templates.ts +25 -2
  108. package/src/hooks/hook.ts +26 -67
  109. package/src/http/agents.ts +40 -1
  110. package/src/http/auth.ts +13 -1
  111. package/src/http/fs.ts +21 -51
  112. package/src/http/index.ts +2 -0
  113. package/src/http/mcp.ts +32 -0
  114. package/src/http/pages-public.ts +20 -4
  115. package/src/http/pages.ts +11 -3
  116. package/src/http/poll.ts +4 -0
  117. package/src/http/repos.ts +3 -3
  118. package/src/http/sessions.ts +82 -0
  119. package/src/http/tasks.ts +10 -2
  120. package/src/http/utils.ts +79 -1
  121. package/src/prompts/session-templates.ts +12 -8
  122. package/src/providers/acp-adapter.ts +62 -8
  123. package/src/providers/pi-mono-adapter.ts +23 -6
  124. package/src/providers/pricing-sources.md +11 -0
  125. package/src/scheduler/scheduler.test.ts +49 -2
  126. package/src/scheduler/scheduler.ts +4 -0
  127. package/src/scripts-runtime/sdk-allowlist.ts +1 -0
  128. package/src/scripts-runtime/types/stdlib.d.ts +8 -0
  129. package/src/scripts-runtime/types/swarm-sdk.d.ts +8 -0
  130. package/src/server.ts +2 -0
  131. package/src/slack/assistant.ts +87 -46
  132. package/src/slack/handlers.test.ts +1 -3
  133. package/src/slack/handlers.ts +102 -87
  134. package/src/slack/inbound-files.ts +466 -0
  135. package/src/slack/templates.ts +14 -0
  136. package/src/tasks/task-terminal-effects.ts +158 -0
  137. package/src/tests/acp-adapter.test.ts +369 -117
  138. package/src/tests/budget-claim-gate.test.ts +1 -0
  139. package/src/tests/build-pi-skills.test.ts +5 -7
  140. package/src/tests/claude-managed-setup.test.ts +52 -4
  141. package/src/tests/claude-md-session.test.ts +603 -0
  142. package/src/tests/codex-skill-resolver.test.ts +19 -0
  143. package/src/tests/context-versioning.test.ts +107 -0
  144. package/src/tests/cors-allowlist.test.ts +309 -0
  145. package/src/tests/credential-check.test.ts +157 -14
  146. package/src/tests/db-agents.test.ts +91 -0
  147. package/src/tests/db-context-versions.test.ts +37 -0
  148. package/src/tests/db-extraction-contract.test.ts +45 -0
  149. package/src/tests/db-runtime.test.ts +70 -0
  150. package/src/tests/db-task-read-contract.test.ts +624 -0
  151. package/src/tests/db-task-write-contract.test.ts +653 -0
  152. package/src/tests/db-tasks-read.test.ts +183 -0
  153. package/src/tests/db-tasks-write.test.ts +230 -0
  154. package/src/tests/defer-task.test.ts +389 -0
  155. package/src/tests/docs-index-footprint.test.js +2 -2
  156. package/src/tests/e2e-visuals-stage.test.ts +151 -0
  157. package/src/tests/file-lock.test.ts +144 -0
  158. package/src/tests/fixtures/file-lock-holder.ts +13 -0
  159. package/src/tests/fixtures/hold-file-lock.ts +25 -0
  160. package/src/tests/heartbeat-expiry.test.ts +188 -0
  161. package/src/tests/http-api-integration.test.ts +78 -1
  162. package/src/tests/pages-public-html.test.ts +43 -0
  163. package/src/tests/pages-svg-migration.test.ts +42 -0
  164. package/src/tests/preload.ts +4 -1
  165. package/src/tests/profile-sync-warning.test.ts +16 -0
  166. package/src/tests/profile-sync.test.ts +126 -0
  167. package/src/tests/prompt-template-session.test.ts +20 -4
  168. package/src/tests/provider-registration.test.ts +93 -0
  169. package/src/tests/rbac-e2e-helpers.test.ts +53 -0
  170. package/src/tests/rbac-e2e-helpers.ts +19 -2
  171. package/src/tests/reload-config.test.ts +26 -0
  172. package/src/tests/routing-affinity-inventory.test.ts +1 -1
  173. package/src/tests/runner-attachments-section.test.ts +22 -2
  174. package/src/tests/runner-context-preamble.test.ts +30 -0
  175. package/src/tests/runner-deployment-resume.test.ts +107 -0
  176. package/src/tests/runner-repo-autostash.test.ts +12 -0
  177. package/src/tests/script-connections.test.ts +4 -0
  178. package/src/tests/seed-scripts.test.ts +2 -2
  179. package/src/tests/session-tokens.test.ts +279 -0
  180. package/src/tests/slack-file-tools-attachments.test.ts +408 -0
  181. package/src/tests/slack-inbound-files.test.ts +847 -0
  182. package/src/tests/star-history-refresh.test.ts +102 -0
  183. package/src/tests/swarm-config-reserved-keys.test.ts +21 -0
  184. package/src/tests/swarm-repos.test.ts +20 -0
  185. package/src/tests/tool-annotations.test.ts +4 -3
  186. package/src/tests/ui-logs-parser.test.ts +176 -0
  187. package/src/tools/create-page.ts +4 -2
  188. package/src/tools/defer-task.ts +239 -0
  189. package/src/tools/repos/update-repo.ts +2 -2
  190. package/src/tools/schedules/create-schedule.ts +1 -0
  191. package/src/tools/schedules/list-schedules.ts +1 -0
  192. package/src/tools/schedules/patch-schedule.ts +1 -0
  193. package/src/tools/schedules/update-schedule.ts +1 -0
  194. package/src/tools/slack-download-file.ts +60 -29
  195. package/src/tools/slack-read.ts +73 -32
  196. package/src/tools/store-progress.ts +16 -146
  197. package/src/tools/tool-config.ts +1 -0
  198. package/src/tools/utils.ts +21 -0
  199. package/src/types.ts +37 -4
  200. package/src/utils/acp-session-token.ts +56 -0
  201. package/src/utils/file-lock.ts +111 -0
  202. package/src/utils/heartbeat-expiry.ts +78 -0
  203. package/src/utils/request-auth-context.ts +2 -0
  204. package/src/utils/task-attachment-links.ts +22 -0
  205. package/templates/skills/code-quality/content.md +8 -5
  206. package/templates/skills/download-task-attachment/content.md +2 -1
  207. package/{plugin/pi-skills → templates/skills}/review-offered-task/SKILL.md +5 -5
  208. package/templates/skills/review-offered-task/config.json +14 -0
  209. package/{plugin/commands/review-offered-task.md → templates/skills/review-offered-task/content.md} +3 -8
  210. package/templates/skills/scheduling/content.md +4 -0
  211. package/templates/skills/slack-interaction/content.md +2 -2
  212. package/templates/skills/work-on-task/SKILL.md +16 -0
  213. package/templates/skills/work-on-task/config.json +14 -0
  214. package/templates/skills/work-on-task/content.md +11 -0
  215. package/dist/assistant-0qt42nzg.js +0 -212
  216. package/dist/cli-fs1kkqgr.js +0 -317
  217. package/dist/cli-jnf5zghe.js +0 -269
  218. package/dist/cli-n1q8q14d.js +0 -177
  219. package/dist/handlers-yfp1qn81.js +0 -592
  220. package/plugin/commands/work-on-task.md +0 -39
  221. package/plugin/pi-skills/work-on-task/SKILL.md +0 -39
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  renderSteeringDelivery
3
- } from "./cli-dt553ktb.js";
3
+ } from "./cli-0b6y7kxm.js";
4
4
  import {
5
5
  checkCodexCredentials,
6
6
  codexUserHome
7
- } from "./cli-gxnzc6wh.js";
7
+ } from "./cli-4nr988h6.js";
8
8
  import {
9
9
  checkClaudeManagedCredentials
10
10
  } from "./cli-cn6mmc7f.js";
@@ -18,10 +18,10 @@ import {
18
18
  renderMemoriesPrompt,
19
19
  resolveScriptsOnlyMode,
20
20
  writeSkillsToFilesystem
21
- } from "./cli-z9fprcrf.js";
21
+ } from "./cli-atcve9y8.js";
22
22
  import {
23
23
  checkClaudeCredentials
24
- } from "./cli-v0asr5yv.js";
24
+ } from "./cli-719k9j2c.js";
25
25
  import {
26
26
  MAX_RATE_LIMIT_RESET_MS,
27
27
  isCodexCreditsExhaustedMessage,
@@ -34,7 +34,7 @@ import {
34
34
  } from "./cli-s25avqg9.js";
35
35
  import {
36
36
  validateJsonSchema
37
- } from "./cli-123q2get.js";
37
+ } from "./cli-yz3djrm0.js";
38
38
  import {
39
39
  authJsonToCredentialSelection,
40
40
  credentialsToAuthJson,
@@ -50,14 +50,18 @@ import {
50
50
  getApiKey
51
51
  } from "./cli-f14fvzag.js";
52
52
  import {
53
+ buildContextPreamble,
54
+ buildResumeContextPreamble,
53
55
  contentSha256,
56
+ init_context_preamble,
54
57
  init_profile_sync,
58
+ prependContextPreamble,
55
59
  prependProfileSyncRejectionBanner,
56
60
  resolveClaudeMdPath,
57
61
  syncProfileFilesToServer,
58
62
  writeIdentityBaselines,
59
63
  writeProfileFileFromDb
60
- } from "./cli-fs1kkqgr.js";
64
+ } from "./cli-m9sxbkhm.js";
61
65
  import {
62
66
  ensure,
63
67
  initOtel,
@@ -65,10 +69,13 @@ import {
65
69
  injectTraceContext,
66
70
  isPollTracingEnabled,
67
71
  startSpan,
68
- taskAttachmentDisplayUrl,
69
72
  withSpan,
70
73
  withSpanContext
71
- } from "./cli-jmb7g47h.js";
74
+ } from "./cli-b5bq9crk.js";
75
+ import {
76
+ init_task_attachment_links,
77
+ taskAttachmentFetchCommand
78
+ } from "./cli-9d8ntetj.js";
72
79
  import {
73
80
  ProviderNameSchema,
74
81
  initTelemetry,
@@ -76,7 +83,7 @@ import {
76
83
  init_types,
77
84
  resolveTaskModelSelection,
78
85
  telemetry
79
- } from "./cli-f567d5c1.js";
86
+ } from "./cli-ftht3zzj.js";
80
87
  import {
81
88
  generateDefaultClaudeMd,
82
89
  generateDefaultIdentityMd,
@@ -86,7 +93,7 @@ import {
86
93
  init_base_prompt,
87
94
  init_defaults,
88
95
  init_templates
89
- } from "./cli-kpev657q.js";
96
+ } from "./cli-y6b6fb76.js";
90
97
  import {
91
98
  configureHttpResolver,
92
99
  init_resolver,
@@ -95,7 +102,7 @@ import {
95
102
  interpolate,
96
103
  isSteeringEnabled,
97
104
  resolveTemplateAsync
98
- } from "./cli-7fnkj1hj.js";
105
+ } from "./cli-kpv03zhj.js";
99
106
  import {
100
107
  getMcpBaseUrl,
101
108
  init_constants
@@ -144,15 +151,15 @@ async function materializeCodexAuthJson(_slot, creds, deps = {}) {
144
151
  async function createProviderAdapter(provider) {
145
152
  switch (provider) {
146
153
  case "claude": {
147
- const { ClaudeAdapter } = await import("./claude-adapter-paj270y2.js");
154
+ const { ClaudeAdapter } = await import("./claude-adapter-w1z04ann.js");
148
155
  return new ClaudeAdapter;
149
156
  }
150
157
  case "pi": {
151
- const { PiMonoAdapter } = await import("./pi-mono-adapter-dtkz4e7j.js");
158
+ const { PiMonoAdapter } = await import("./pi-mono-adapter-2has4gnp.js");
152
159
  return new PiMonoAdapter;
153
160
  }
154
161
  case "codex": {
155
- const { CodexAdapter } = await import("./codex-adapter-k98vaw2r.js");
162
+ const { CodexAdapter } = await import("./codex-adapter-zw4dwsx7.js");
156
163
  return new CodexAdapter;
157
164
  }
158
165
  case "claude-managed": {
@@ -168,7 +175,7 @@ async function createProviderAdapter(provider) {
168
175
  return new OpencodeAdapter;
169
176
  }
170
177
  case "acp": {
171
- const { ACPAdapter } = await import("./acp-adapter-580t41c0.js");
178
+ const { ACPAdapter } = await import("./acp-adapter-9n319wqc.js");
172
179
  return new ACPAdapter;
173
180
  }
174
181
  default:
@@ -536,332 +543,62 @@ function detectVcsProvider(url) {
536
543
  return null;
537
544
  }
538
545
 
539
- // src/commands/context-preamble.ts
540
- init_secret_scrubber();
541
- init_steering_enabled();
542
- var CONTEXT_PREAMBLE_MAX_TOKENS = Number(process.env.CONTEXT_PREAMBLE_MAX_TOKENS || "2000");
543
- var CONTEXT_PREAMBLE_MAX_CHARS = CONTEXT_PREAMBLE_MAX_TOKENS * 4;
544
- var CONTEXT_PREAMBLE_MAX_ANCESTORS = 5;
545
- var CONTEXT_PREAMBLE_RESUME_MAX_TOKENS = Number(process.env.CONTEXT_PREAMBLE_RESUME_MAX_TOKENS || "4000");
546
- var CONTEXT_PREAMBLE_RESUME_MAX_CHARS = CONTEXT_PREAMBLE_RESUME_MAX_TOKENS * 4;
547
- var CONTEXT_PREAMBLE_RESUME_SESSION_LOG_LIMIT = 50;
548
- async function fetchTaskContextForPreamble(apiUrl, apiKey, taskId) {
549
- const headers = {};
550
- if (apiKey)
551
- headers.Authorization = `Bearer ${apiKey}`;
552
- try {
553
- const response = await fetch(`${apiUrl}/api/tasks/${taskId}`, { headers });
554
- if (!response.ok)
546
+ // src/commands/attachments-section.ts
547
+ init_task_attachment_links();
548
+ function buildAttachmentsSection(taskId, attachmentsRaw) {
549
+ if (!taskId || !Array.isArray(attachmentsRaw) || attachmentsRaw.length === 0)
550
+ return "";
551
+ const lines = attachmentsRaw.filter((a) => !!a && typeof a === "object").map((a) => {
552
+ const id = typeof a.id === "string" ? a.id : undefined;
553
+ const name = typeof a.name === "string" ? a.name : id;
554
+ if (!id || !name)
555
555
  return null;
556
- const data = await response.json();
557
- return {
558
- id: data.id,
559
- task: data.task,
560
- output: data.output,
561
- progress: data.progress,
562
- status: data.status,
563
- taskType: data.taskType,
564
- parentTaskId: data.parentTaskId,
565
- attachments: data.attachments
566
- };
567
- } catch {
568
- return null;
569
- }
570
- }
571
- function formatAttachmentPointer(att) {
572
- const pointer = taskAttachmentDisplayUrl(att);
573
- return pointer || "(no pointer)";
574
- }
575
- async function buildContextPreamble(apiUrl, apiKey, parentTaskId) {
576
- const ancestors = [];
577
- let currentId = parentTaskId;
578
- while (currentId && ancestors.length < CONTEXT_PREAMBLE_MAX_ANCESTORS) {
579
- const ctx = await fetchTaskContextForPreamble(apiUrl, apiKey, currentId);
580
- if (!ctx)
581
- break;
582
- ancestors.push(ctx);
583
- currentId = ctx.parentTaskId;
584
- }
585
- if (ancestors.length === 0)
586
- return null;
587
- const parent = ancestors[0];
588
- if (!parent)
589
- return null;
590
- const lines = [
591
- `
592
- ---`,
593
- "## Prior Conversation Context",
594
- "",
595
- "This task is a follow-up in an ongoing thread. Here is a summary of prior work to maintain continuity.",
596
- ""
597
- ];
598
- const subjectPreview = parent.task.slice(0, 600).replace(/\n/g, " ");
599
- lines.push(`### Immediate Prior Task (ID: \`${parent.id}\`)`);
600
- lines.push(`**Task:** ${subjectPreview}`);
601
- lines.push("");
602
- const rawResult = parent.output || parent.progress;
603
- if (rawResult) {
604
- const outputBudget = Math.floor(CONTEXT_PREAMBLE_MAX_CHARS * 0.55);
605
- const truncated = rawResult.length > outputBudget ? `${rawResult.slice(0, outputBudget)}
606
-
607
- [output truncated — full history via \`get-task-details\` with taskId \`${parent.id}\`]` : rawResult;
608
- lines.push("**Outcome:**");
609
- lines.push(truncated);
610
- lines.push("");
611
- } else {
612
- lines.push("**Outcome:** (no output recorded yet — task may still be in progress)");
613
- lines.push("");
614
- }
615
- const atts = parent.attachments?.filter((a) => a.name && (a.url || a.path || a.pageId));
616
- if (atts && atts.length > 0) {
617
- lines.push("**Artifacts from prior task:**");
618
- for (const att of atts.slice(0, 10)) {
619
- const pointer = formatAttachmentPointer(att);
620
- const note = att.description || att.intent || "";
621
- lines.push(` - **${att.name}**: \`${pointer}\`${note ? ` — ${note}` : ""}`);
622
- }
623
- lines.push("");
624
- }
625
- lines.push(`To review the full prior conversation call \`get-task-details\` with taskId \`${parent.id}\`.`);
626
- if (ancestors.length > 1) {
627
- lines.push("");
628
- lines.push("### Older Ancestor Tasks (pointers only — call `get-task-details` for full details)");
629
- for (const ancestor of ancestors.slice(1)) {
630
- const brief = ancestor.task.slice(0, 200).replace(/\n/g, " ");
631
- lines.push(`- \`${ancestor.id}\` — ${brief}`);
632
- }
633
- }
634
- lines.push("", "---", "");
635
- let preamble = lines.join(`
636
- `);
637
- if (preamble.length > CONTEXT_PREAMBLE_MAX_CHARS) {
638
- preamble = `${preamble.slice(0, CONTEXT_PREAMBLE_MAX_CHARS)}
639
-
640
- [context preamble truncated to ${CONTEXT_PREAMBLE_MAX_TOKENS}-token budget]
556
+ const details = [
557
+ typeof a.mimeType === "string" ? a.mimeType : null,
558
+ typeof a.sizeBytes === "number" ? `${a.sizeBytes} bytes` : null
559
+ ].filter(Boolean).join(", ");
560
+ const cmd = taskAttachmentFetchCommand(taskId, id, name);
561
+ return `- ${name}${details ? ` (${details})` : ""}: \`${cmd}\``;
562
+ }).filter((line) => line !== null);
563
+ if (lines.length === 0)
564
+ return "";
565
+ return `
641
566
 
642
- ---
643
- `;
644
- }
645
- return preamble;
646
- }
647
- async function fetchSessionLogsForResume(apiUrl, apiKey, taskId) {
648
- const headers = {};
649
- if (apiKey)
650
- headers.Authorization = `Bearer ${apiKey}`;
651
- try {
652
- const url = `${apiUrl}/api/tasks/${taskId}/session-logs?limit=${CONTEXT_PREAMBLE_RESUME_SESSION_LOG_LIMIT}`;
653
- const response = await fetch(url, { headers });
654
- if (!response.ok)
655
- return [];
656
- const data = await response.json();
657
- return Array.isArray(data.logs) ? data.logs : [];
658
- } catch {
659
- return [];
660
- }
661
- }
662
- async function fetchSteeringMessagesForResume(apiUrl, apiKey, taskId) {
663
- const headers = {};
664
- if (apiKey)
665
- headers.Authorization = `Bearer ${apiKey}`;
666
- try {
667
- const response = await fetch(`${apiUrl}/api/tasks/${taskId}/steering-messages?status=pending,promoted`, { headers });
668
- if (!response.ok)
669
- return [];
670
- const data = await response.json();
671
- return Array.isArray(data.messages) ? data.messages.filter((message) => (message.status === "pending" || message.status === "promoted") && typeof message.body === "string" && typeof message.createdAt === "string") : [];
672
- } catch {
673
- return [];
674
- }
675
- }
676
- function summarizeSessionLogLine(line) {
677
- const ts = line.createdAt.slice(11, 19);
678
- let parsed;
679
- try {
680
- parsed = JSON.parse(line.content);
681
- } catch {
682
- const snippet2 = line.content.replace(/\s+/g, " ").slice(0, 120);
683
- return snippet2 ? `[${ts}] ${snippet2}` : null;
684
- }
685
- if (!parsed || typeof parsed !== "object")
686
- return null;
687
- const obj = parsed;
688
- const message = obj.message;
689
- const content = message?.content;
690
- if (Array.isArray(content)) {
691
- for (const block of content) {
692
- if (!block || typeof block !== "object")
693
- continue;
694
- const b = block;
695
- if (b.type === "tool_use" && typeof b.name === "string") {
696
- const input = b.input;
697
- const file = input?.file_path ?? input?.path ?? input?.command;
698
- const fileStr = typeof file === "string" ? ` ${file}` : "";
699
- return `[${ts}] ${b.name}${fileStr}`;
700
- }
701
- }
702
- }
703
- if (obj.type === "tool_use" && typeof obj.name === "string") {
704
- const input = obj.input;
705
- const file = input?.file_path ?? input?.path ?? input?.command;
706
- const fileStr = typeof file === "string" ? ` ${file}` : "";
707
- return `[${ts}] ${obj.name}${fileStr}`;
708
- }
709
- const snippet = JSON.stringify(parsed).replace(/\s+/g, " ").slice(0, 120);
710
- return snippet ? `[${ts}] ${snippet}` : null;
711
- }
712
- var MAX_RESUME_CHAIN_DEPTH = 10;
713
- async function walkResumeChain(apiUrl, apiKey, immediateParentId) {
714
- const chain = [];
715
- let currentId = immediateParentId;
716
- for (let depth = 0;depth < MAX_RESUME_CHAIN_DEPTH && currentId; depth++) {
717
- const ctx = await fetchTaskContextForPreamble(apiUrl, apiKey, currentId);
718
- if (!ctx)
719
- break;
720
- chain.push(ctx);
721
- if (ctx.taskType !== "resume")
722
- break;
723
- currentId = ctx.parentTaskId;
724
- }
725
- return chain;
567
+ \uD83D\uDCCE Attachment(s) — fetch directly, no need to discover the storage path yourself:
568
+ ${lines.join(`
569
+ `)}`;
726
570
  }
727
- async function buildResumeContextPreamble(apiUrl, apiKey, parentTaskId) {
728
- const chain = await walkResumeChain(apiUrl, apiKey, parentTaskId);
729
- if (chain.length === 0)
730
- return null;
731
- const original = chain[chain.length - 1] ?? chain[0];
732
- if (!original)
733
- return null;
734
- const parent = chain[0] ?? original;
735
- const steeringEnabled = isSteeringEnabled();
736
- const [logsBatches, steeringBatches] = await Promise.all([
737
- Promise.all(chain.map((c2) => fetchSessionLogsForResume(apiUrl, apiKey, c2.id))),
738
- steeringEnabled ? Promise.all(chain.map((c2) => fetchSteeringMessagesForResume(apiUrl, apiKey, c2.id))) : Promise.resolve([])
739
- ]);
740
- const merged = logsBatches.flat();
741
- merged.sort((a, b) => a.createdAt.localeCompare(b.createdAt));
742
- const recentLogs = merged.slice(-CONTEXT_PREAMBLE_RESUME_SESSION_LOG_LIMIT);
743
- const steeringMessages = steeringBatches.flat();
744
- steeringMessages.sort((a, b) => a.createdAt.localeCompare(b.createdAt));
745
- const descBudget = Math.floor(CONTEXT_PREAMBLE_RESUME_MAX_CHARS * 0.4);
746
- let logsBudget = Math.floor(CONTEXT_PREAMBLE_RESUME_MAX_CHARS * 0.3);
747
- let artBudget = Math.floor(CONTEXT_PREAMBLE_RESUME_MAX_CHARS * 0.1);
748
- const steeringBudget = Math.floor(CONTEXT_PREAMBLE_RESUME_MAX_CHARS * 0.1);
749
- const header = [
750
- `
751
- ---`,
752
- "## Resuming Interrupted Task",
753
- "",
754
- "This task is a fresh-session continuation of an interrupted task (graceful",
755
- "shutdown / context-limit / operator action). The block below summarizes the",
756
- "original task, what was done so far, and the artifacts in flight.",
757
- "",
758
- "**Do not redo work already completed below — extend it.**",
759
- "",
760
- `Original task ID: \`${original.id}\``,
761
- chain.length > 1 ? `Resume chain depth: ${chain.length} (this is at least the ${chain.length === 2 ? "2nd" : chain.length === 3 ? "3rd" : `${chain.length}th`} resume attempt).` : "",
762
- "",
763
- "---",
764
- "",
765
- "### Original Task Description",
766
- ""
767
- ].filter((s) => s !== "").join(`
768
- `);
769
- const descSection = original.task;
770
- const summaryLines = [];
771
- for (const line of recentLogs) {
772
- const summary = summarizeSessionLogLine(line);
773
- if (!summary)
774
- continue;
775
- summaryLines.push(summary);
776
- }
777
- const scrubbedSummary = summaryLines.map((s) => scrubSecrets(s));
778
- let logsSection = scrubbedSummary.join(`
779
- `);
780
- if (descSection.length > descBudget) {
781
- const overflow = descSection.length - descBudget;
782
- logsBudget = Math.max(0, logsBudget - Math.ceil(overflow / 2));
783
- artBudget = Math.max(0, artBudget - Math.floor(overflow / 2));
784
- }
785
- while (logsSection.length > logsBudget && scrubbedSummary.length > 0) {
786
- scrubbedSummary.shift();
787
- logsSection = scrubbedSummary.join(`
788
- `);
789
- }
790
- const steeringLines = steeringEnabled ? steeringMessages.map((message) => {
791
- const ts = message.createdAt.slice(11, 19);
792
- return `[${ts}] ${scrubSecrets(message.body)}`;
793
- }) : [];
794
- let steeringSection = steeringLines.join(`
795
- `);
796
- while (steeringSection.length > steeringBudget && steeringLines.length > 0) {
797
- steeringLines.shift();
798
- steeringSection = steeringLines.join(`
799
- `);
800
- }
801
- const atts = parent.attachments?.filter((a) => a.name && (a.url || a.path || a.pageId)) ?? [];
802
- const artLines = [];
803
- for (const att of atts) {
804
- const pointer = formatAttachmentPointer(att);
805
- artLines.push(` - **${att.name}**: \`${pointer}\``);
806
- }
807
- let artSection = artLines.join(`
808
- `);
809
- while (artSection.length > artBudget && artLines.length > 0) {
810
- artLines.pop();
811
- artSection = artLines.join(`
812
- `);
813
- }
814
- const sections = [header, descSection, ""];
815
- if (logsSection) {
816
- sections.push("### Recent Tool Calls", "", logsSection, "");
817
- }
818
- if (artSection) {
819
- sections.push("### Artifacts In Flight", "", artSection, "");
820
- }
821
- if (steeringEnabled && steeringSection) {
822
- sections.push("### Undelivered Steering Messages", "", steeringSection, "");
823
- }
824
- sections.push("---", "", `To review the full prior session call \`get-task-details\` with taskId \`${original.id}\`.`, "", "---", "");
825
- let preamble = sections.join(`
826
- `);
827
- if (preamble.length > CONTEXT_PREAMBLE_RESUME_MAX_CHARS) {
828
- preamble = `${preamble.slice(0, CONTEXT_PREAMBLE_RESUME_MAX_CHARS)}
829
571
 
830
- [resume preamble truncated to ${CONTEXT_PREAMBLE_RESUME_MAX_TOKENS}-token budget]
831
-
832
- ---
833
- `;
834
- }
835
- return preamble;
836
- }
572
+ // src/commands/runner.ts
573
+ init_context_preamble();
837
574
 
838
575
  // src/commands/provider-credentials.ts
839
576
  init_secret_scrubber();
840
- function isBedrockSdkMode(env) {
577
+ function isBedrockMode(env) {
841
578
  const mode = env.BEDROCK_AUTH_MODE?.toLowerCase();
842
- return mode === "sdk" || mode === undefined && Boolean(env.MODEL_OVERRIDE?.toLowerCase().startsWith("amazon-bedrock/"));
579
+ return mode === "sdk" || mode === "bearer" || mode === undefined && Boolean(env.MODEL_OVERRIDE?.toLowerCase().startsWith("amazon-bedrock/"));
580
+ }
581
+ function shouldRefreshBedrockStatus(opts) {
582
+ return opts.harnessProvider === "pi" && isBedrockMode(opts.env) && opts.now - opts.lastRefreshAt > opts.intervalMs;
843
583
  }
584
+ var CREDENTIAL_PROVIDER_CHECKERS = {
585
+ claude: (env) => checkClaudeCredentials(env),
586
+ "claude-managed": (env) => checkClaudeManagedCredentials(env),
587
+ codex: (env, opts) => checkCodexCredentials(env, opts),
588
+ devin: (env) => checkDevinCredentials(env),
589
+ opencode: (env, opts) => checkOpencodeCredentials(env, opts),
590
+ pi: async (env, opts) => {
591
+ const { checkPiMonoCredentials } = await import("./pi-mono-adapter-2has4gnp.js");
592
+ return checkPiMonoCredentials(env, opts);
593
+ },
594
+ acp: () => ({ ready: true, missing: [], satisfiedBy: "sdk-delegated" })
595
+ };
844
596
  async function checkProviderCredentials(provider, env, opts) {
845
- switch (provider) {
846
- case "claude":
847
- return checkClaudeCredentials(env);
848
- case "claude-managed":
849
- return checkClaudeManagedCredentials(env);
850
- case "codex":
851
- return checkCodexCredentials(env, opts);
852
- case "devin":
853
- return checkDevinCredentials(env);
854
- case "opencode":
855
- return checkOpencodeCredentials(env, opts);
856
- case "pi": {
857
- const { checkPiMonoCredentials } = await import("./pi-mono-adapter-dtkz4e7j.js");
858
- return checkPiMonoCredentials(env, opts);
859
- }
860
- case "acp":
861
- return { ready: true, missing: [], satisfiedBy: "sdk-delegated" };
862
- default:
863
- throw new Error(`checkProviderCredentials: unknown provider "${provider}". Supported: claude, claude-managed, codex, devin, opencode, pi, acp.`);
597
+ const checker = CREDENTIAL_PROVIDER_CHECKERS[provider];
598
+ if (!checker) {
599
+ throw new Error(`checkProviderCredentials: unknown provider "${provider}". Supported: ${Object.keys(CREDENTIAL_PROVIDER_CHECKERS).join(", ")}.`);
864
600
  }
601
+ return checker(env, opts);
865
602
  }
866
603
  var LIVE_TEST_TIMEOUT_MS = 5000;
867
604
  async function timedFetch(url, init) {
@@ -987,7 +724,7 @@ async function validateProviderCredentials(provider) {
987
724
  }
988
725
  case "pi":
989
726
  case "opencode": {
990
- if (provider === "pi" && isBedrockSdkMode(env)) {
727
+ if (provider === "pi" && isBedrockMode(env)) {
991
728
  return presenceCheckOk();
992
729
  }
993
730
  if (env.OPENROUTER_API_KEY)
@@ -1432,6 +1169,7 @@ async function listSwarmAutostashes(clonePath, role) {
1432
1169
  }
1433
1170
  var CONTINUATION_TASK_TYPES = new Set([
1434
1171
  "resume",
1172
+ "deferred",
1435
1173
  "follow-up",
1436
1174
  "reroute-decision",
1437
1175
  "agentmail-reply",
@@ -2436,12 +2174,14 @@ async function resumeTaskViaAPI(config, taskId) {
2436
2174
  }
2437
2175
  async function buildResumePrompt(task, fmt = (cmd) => `/${cmd}`, options) {
2438
2176
  const hasMcp = options?.hasMcp !== false;
2439
- const completionInstructions = hasMcp ? '\n\nWhen done, use `store-progress` with status: "completed" and include your output.' : "";
2177
+ const completionInstructions = await buildTaskOutputInstructions(task.outputSchema, hasMcp);
2178
+ const attachmentsSection = buildAttachmentsSection(task.id, task.attachments);
2440
2179
  if (task.progress) {
2441
2180
  const result2 = await resolveTemplateAsync("task.resumption.with_progress", {
2442
2181
  work_on_task_cmd: hasMcp ? fmt("work-on-task") : "",
2443
2182
  task_id: hasMcp ? task.id : "",
2444
2183
  task_description: task.task,
2184
+ attachments_section: attachmentsSection,
2445
2185
  progress: task.progress,
2446
2186
  completion_instructions: completionInstructions
2447
2187
  });
@@ -2451,6 +2191,7 @@ async function buildResumePrompt(task, fmt = (cmd) => `/${cmd}`, options) {
2451
2191
  work_on_task_cmd: hasMcp ? fmt("work-on-task") : "",
2452
2192
  task_id: hasMcp ? task.id : "",
2453
2193
  task_description: task.task,
2194
+ attachments_section: attachmentsSection,
2454
2195
  completion_instructions: completionInstructions
2455
2196
  });
2456
2197
  return result.text;
@@ -2934,29 +2675,13 @@ async function pollForTriggerOnce(opts) {
2934
2675
  }
2935
2676
  return null;
2936
2677
  }
2937
- function buildAttachmentsSection(taskId, attachmentsRaw) {
2938
- if (!taskId || !Array.isArray(attachmentsRaw) || attachmentsRaw.length === 0)
2939
- return "";
2940
- const lines = attachmentsRaw.filter((a) => !!a && typeof a === "object").map((a) => {
2941
- const id = typeof a.id === "string" ? a.id : undefined;
2942
- const name = typeof a.name === "string" ? a.name : id;
2943
- if (!id || !name)
2944
- return null;
2945
- const details = [
2946
- typeof a.mimeType === "string" ? a.mimeType : null,
2947
- typeof a.sizeBytes === "number" ? `${a.sizeBytes} bytes` : null
2948
- ].filter(Boolean).join(", ");
2949
- const url = `$MCP_BASE_URL/api/fs/tasks/${taskId}/files/${id}/raw`;
2950
- const cmd = `curl -s -H "Authorization: Bearer \${AGENT_SWARM_API_KEY:-$API_KEY}" -H "X-Agent-ID: $AGENT_ID" "${url}" -o /tmp/${name}`;
2951
- return `- ${name}${details ? ` (${details})` : ""}: \`${cmd}\``;
2952
- }).filter((line) => line !== null);
2953
- if (lines.length === 0)
2678
+ async function buildTaskOutputInstructions(outputSchema, hasMcp) {
2679
+ if (!hasMcp)
2954
2680
  return "";
2955
- return `
2956
-
2957
- \uD83D\uDCCE Attachment(s) — fetch directly, no need to discover the storage path yourself:
2958
- ${lines.join(`
2959
- `)}`;
2681
+ const result = outputSchema && typeof outputSchema === "object" ? await resolveTemplateAsync("task.output.schema", {
2682
+ schema: JSON.stringify(outputSchema, null, 2)
2683
+ }) : await resolveTemplateAsync("task.output.generic", {});
2684
+ return result.text;
2960
2685
  }
2961
2686
  async function buildPromptForTrigger(trigger, defaultPrompt, fmt = (cmd) => `/${cmd}`, options) {
2962
2687
  const hasMcp = options?.hasMcp !== false;
@@ -2967,24 +2692,15 @@ async function buildPromptForTrigger(trigger, defaultPrompt, fmt = (cmd) => `/${
2967
2692
 
2968
2693
  Task: "${taskDesc}"` : "";
2969
2694
  const taskObj = trigger.task;
2970
- let outputInstructions;
2971
- if (!hasMcp) {
2972
- outputInstructions = "";
2973
- } else if (taskObj?.outputSchema && typeof taskObj.outputSchema === "object") {
2974
- outputInstructions = `
2975
-
2976
- **Required Output Format**: When completing this task, you MUST call store-progress with output that is valid JSON conforming to this schema:
2977
- \`\`\`json
2978
- ${JSON.stringify(taskObj.outputSchema, null, 2)}
2979
- \`\`\`
2980
- Call store-progress with status "completed" and your JSON output. If your output doesn't match the schema, the tool call will fail and you should fix and retry.`;
2981
- } else {
2982
- outputInstructions = '\n\nWhen done, use `store-progress` with status: "completed" and include your output.';
2983
- }
2695
+ const outputInstructions = await buildTaskOutputInstructions(taskObj?.outputSchema, hasMcp);
2984
2696
  const requestedBy = trigger.requestedBy;
2697
+ const requesterDetails = [
2698
+ requestedBy?.email,
2699
+ requestedBy?.id ? `user ${requestedBy.id}` : undefined
2700
+ ].filter(Boolean);
2985
2701
  const requestedBySection = requestedBy ? `
2986
2702
 
2987
- Requested by: ${requestedBy.name}${requestedBy.email ? ` (${requestedBy.email})` : ""}` : "";
2703
+ Requested by: ${requestedBy.name}${requesterDetails.length > 0 ? ` (${requesterDetails.join(", ")})` : ""}` : "";
2988
2704
  const attachmentsSection = buildAttachmentsSection(trigger.taskId, taskObj?.attachments);
2989
2705
  const result = await resolveTemplateAsync("task.trigger.assigned", {
2990
2706
  work_on_task_cmd: hasMcp ? fmt("work-on-task") : "",
@@ -4689,7 +4405,7 @@ ${additionalSystemPrompt}` : basePrompt;
4689
4405
  if (task.parentTaskId && apiUrl) {
4690
4406
  const contextPreamble = await buildContextPreamble(apiUrl, apiKey, task.parentTaskId);
4691
4407
  if (contextPreamble) {
4692
- resumePrompt = contextPreamble + resumePrompt;
4408
+ resumePrompt = prependContextPreamble(resumePrompt, contextPreamble);
4693
4409
  console.log(`[${role}] Injected context preamble into resumed follow-up task prompt (parent: ${task.parentTaskId.slice(0, 8)})`);
4694
4410
  }
4695
4411
  }
@@ -4855,7 +4571,13 @@ ${additionalSystemPrompt}` : basePrompt;
4855
4571
  if (currentHarness !== cachedCredHarnessProvider) {
4856
4572
  cachedCredHarnessProvider = currentHarness;
4857
4573
  buildCredStatusReport(currentHarness, process.env, {}, "post_task").then((snap) => reportCredStatus(apiUrl, apiKey, agentId, runtimeInstanceId, snap)).catch((err) => console.warn(`[${role}] cred_status post_task report failed (non-fatal): ${err}`));
4858
- } else if (currentHarness === "pi" && isBedrockSdkMode(process.env) && Date.now() - lastBedrockRefreshAt > BEDROCK_REFRESH_INTERVAL_MS) {
4574
+ } else if (shouldRefreshBedrockStatus({
4575
+ harnessProvider: currentHarness,
4576
+ env: process.env,
4577
+ lastRefreshAt: lastBedrockRefreshAt,
4578
+ now: Date.now(),
4579
+ intervalMs: BEDROCK_REFRESH_INTERVAL_MS
4580
+ })) {
4859
4581
  lastBedrockRefreshAt = Date.now();
4860
4582
  buildCredStatusReport(currentHarness, process.env, {}, "post_task").then((snap) => reportCredStatus(apiUrl, apiKey, agentId, runtimeInstanceId, snap)).catch((err) => console.warn(`[${role}] bedrock enumeration refresh failed (non-fatal): ${err}`));
4861
4583
  }
@@ -4973,7 +4695,7 @@ ${additionalSystemPrompt}` : basePrompt;
4973
4695
  const isResumeTask = taskObj.taskType === "resume";
4974
4696
  const contextPreamble = isResumeTask ? await buildResumeContextPreamble(apiUrl, apiKey, taskObj.parentTaskId) : await buildContextPreamble(apiUrl, apiKey, taskObj.parentTaskId);
4975
4697
  if (contextPreamble) {
4976
- triggerPrompt = contextPreamble + triggerPrompt;
4698
+ triggerPrompt = prependContextPreamble(triggerPrompt, contextPreamble);
4977
4699
  console.log(`[${role}] Injected ${isResumeTask ? "resume" : "context"} preamble for ${isResumeTask ? "resume" : "follow-up"} task (parent: ${taskObj.parentTaskId.slice(0, 8)})`);
4978
4700
  }
4979
4701
  }
@@ -7,7 +7,7 @@ var package_default;
7
7
  var init_package = __esm(() => {
8
8
  package_default = {
9
9
  name: "@desplega.ai/agent-swarm",
10
- version: "1.145.0",
10
+ version: "1.147.0",
11
11
  description: "agent-swarm.dev — an open-source operating system for AI work: a lead agent breaks goals into tasks, routes them to specialized workers such as Claude Code or Codex, runs each worker in an isolated container, and preserves shared memory, tools, schedules, and review gates so delegated work compounds across sessions.",
12
12
  keywords: [
13
13
  "agent-swarm.dev",