@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,212 +0,0 @@
1
- import {
2
- bufferThreadMessage,
3
- getBufferMessageCount,
4
- wasEventSeen
5
- } from "./cli-m1xa8be7.js";
6
- import {
7
- hasOtherUserMention
8
- } from "./cli-jnf5zghe.js";
9
- import {
10
- resolveSlackUserId,
11
- rewriteSlackMentions
12
- } from "./cli-xytwff7f.js";
13
- import"./cli-z96t0thj.js";
14
- import {
15
- createTaskWithSiblingAwareness
16
- } from "./cli-axs8e6d4.js";
17
- import {
18
- ackSlackMessage,
19
- ensureSlackThreadTree,
20
- isSlackRenderV2Enabled,
21
- require_dist
22
- } from "./cli-jmb7g47h.js";
23
- import"./cli-q51yprfq.js";
24
- import"./cli-yatxqynm.js";
25
- import {
26
- getAgentWorkingOnThread,
27
- getLeadAgent,
28
- getMostRecentTaskInThread,
29
- init_context_key,
30
- init_db,
31
- reactionName,
32
- slackContextKey
33
- } from "./cli-f567d5c1.js";
34
- import"./cli-kpev657q.js";
35
- import {
36
- init_resolver,
37
- resolveTemplate
38
- } from "./cli-7fnkj1hj.js";
39
- import"./cli-e29gmdmw.js";
40
- import"./cli-c2mk1kgf.js";
41
- import {
42
- init_env_flag,
43
- isEnvFlagEnabled
44
- } from "./cli-ej6gbxfb.js";
45
- import"./cli-sd0mxa3c.js";
46
- import"./cli-w5e1d1vv.js";
47
- import"./cli-dc9k2ba9.js";
48
- import"./cli-xqcq9y5e.js";
49
- import"./cli-pzxba7gw.js";
50
- import"./cli-zf8jjwex.js";
51
- import"./cli-bd957dgb.js";
52
- import {
53
- __toESM
54
- } from "./cli-bc05qbss.js";
55
-
56
- // src/slack/assistant.ts
57
- init_db();
58
- init_resolver();
59
- init_context_key();
60
- var import_bolt = __toESM(require_dist(), 1);
61
- init_env_flag();
62
- var isAdditiveSlack = () => isEnvFlagEnabled("ADDITIVE_SLACK", false);
63
- var cachedBotUserId = null;
64
- function createAssistant() {
65
- return new import_bolt.Assistant({
66
- threadStarted: async ({ say, setSuggestedPrompts, saveThreadContext }) => {
67
- try {
68
- await saveThreadContext();
69
- if (!isSlackRenderV2Enabled()) {
70
- const greetingResult = resolveTemplate("slack.assistant.greeting", {});
71
- await say(greetingResult.text);
72
- }
73
- await setSuggestedPrompts({
74
- title: "Try these:",
75
- prompts: [
76
- { title: "Check status", message: "What's the current status of all agents?" },
77
- { title: "Assign a task", message: "Can you help me with..." },
78
- { title: "List recent tasks", message: "Show me the most recent tasks" }
79
- ]
80
- });
81
- } catch (error) {
82
- console.error("[Slack] Assistant threadStarted error:", error);
83
- }
84
- },
85
- threadContextChanged: async ({ saveThreadContext }) => {
86
- await saveThreadContext();
87
- },
88
- userMessage: async ({ message, body, say, setStatus, setTitle, getThreadContext, client }) => {
89
- const eventId = body?.event_id;
90
- if (wasEventSeen(eventId)) {
91
- console.log(`[Slack] dropping Slack retry: event_id=${eventId}`);
92
- return;
93
- }
94
- const safeSetStatus = async (status) => {
95
- try {
96
- await setStatus(status);
97
- } catch (error) {
98
- console.warn("[Slack] setStatus failed (thread may not be an assistant thread):", error);
99
- }
100
- };
101
- const safeSetTitle = async (title) => {
102
- try {
103
- await setTitle(title);
104
- } catch (error) {
105
- console.warn("[Slack] setTitle failed (thread may not be an assistant thread):", error);
106
- }
107
- };
108
- try {
109
- const msg = message;
110
- const threadTs = msg.thread_ts || message.ts;
111
- const channelId = message.channel;
112
- const messageText = msg.text || "";
113
- const userId = msg.user || "";
114
- const renderedMessageText = await rewriteSlackMentions(messageText);
115
- if (!cachedBotUserId) {
116
- try {
117
- const authResult = await client.auth.test();
118
- cachedBotUserId = authResult.user_id ?? null;
119
- } catch (e) {
120
- console.warn("[Slack] assistant: auth.test() failed — skipping bot-mention check", e);
121
- }
122
- }
123
- if (cachedBotUserId) {
124
- const botMentioned = messageText.includes(`<@${cachedBotUserId}>`);
125
- if (!botMentioned && hasOtherUserMention(messageText, cachedBotUserId)) {
126
- console.log(`[Slack] assistant: skipping message in ${channelId}/${threadTs} — mentions another user, not us`);
127
- return;
128
- }
129
- }
130
- const requestedByUserId = userId ? await resolveSlackUserId(client, userId, {
131
- sampleEventType: "assistant_message",
132
- sampleContext: messageText
133
- }) : undefined;
134
- const workingAgent = await getAgentWorkingOnThread(channelId, threadTs);
135
- if (workingAgent && workingAgent.status !== "offline") {
136
- if (isAdditiveSlack()) {
137
- bufferThreadMessage(channelId, threadTs, messageText, userId, message.ts);
138
- const count = getBufferMessageCount(`${channelId}:${threadTs}`);
139
- const event = count === 1 ? "accepted" : "buffered";
140
- await ackSlackMessage(client, channelId, message.ts, reactionName(event), event);
141
- await safeSetStatus("Queuing follow-up...");
142
- return;
143
- }
144
- const latestTask = await getMostRecentTaskInThread(channelId, threadTs);
145
- const task2 = await createTaskWithSiblingAwareness(renderedMessageText, {
146
- agentId: workingAgent.id,
147
- source: "slack",
148
- slackChannelId: channelId,
149
- slackThreadTs: threadTs,
150
- slackTriggerMessageTs: message.ts,
151
- slackUserId: userId,
152
- parentTaskId: latestTask?.id,
153
- requestedByUserId,
154
- contextKey: slackContextKey({ channelId, threadTs })
155
- });
156
- await ackSlackMessage(client, channelId, message.ts, reactionName("accepted"), "accepted");
157
- if (isSlackRenderV2Enabled())
158
- await ensureSlackThreadTree([task2.id]);
159
- await safeSetStatus("Processing follow-up...");
160
- return;
161
- }
162
- await safeSetStatus("Processing your request...");
163
- if (renderedMessageText) {
164
- const title = renderedMessageText.length > 50 ? `${renderedMessageText.slice(0, 47)}...` : renderedMessageText;
165
- await safeSetTitle(title);
166
- }
167
- const ctx = await getThreadContext();
168
- const channelContext = ctx && typeof ctx === "object" && "channel_id" in ctx && ctx.channel_id ? `
169
-
170
- [User is viewing channel <#${ctx.channel_id}>]` : "";
171
- const lead = await getLeadAgent();
172
- if (!lead) {
173
- const task2 = await createTaskWithSiblingAwareness(renderedMessageText + channelContext, {
174
- source: "slack",
175
- slackChannelId: channelId,
176
- slackThreadTs: threadTs,
177
- slackTriggerMessageTs: message.ts,
178
- slackUserId: userId,
179
- requestedByUserId,
180
- contextKey: slackContextKey({ channelId, threadTs })
181
- });
182
- await ackSlackMessage(client, channelId, message.ts, reactionName("accepted"), "accepted");
183
- if (isSlackRenderV2Enabled()) {
184
- await ensureSlackThreadTree([task2.id]);
185
- } else {
186
- const offlineResult = resolveTemplate("slack.assistant.offline", {});
187
- await say(offlineResult.text);
188
- }
189
- return;
190
- }
191
- const task = await createTaskWithSiblingAwareness(renderedMessageText + channelContext, {
192
- agentId: lead.id,
193
- source: "slack",
194
- slackChannelId: channelId,
195
- slackThreadTs: threadTs,
196
- slackTriggerMessageTs: message.ts,
197
- slackUserId: userId,
198
- requestedByUserId,
199
- contextKey: slackContextKey({ channelId, threadTs })
200
- });
201
- await ackSlackMessage(client, channelId, message.ts, reactionName("accepted"), "accepted");
202
- if (isSlackRenderV2Enabled())
203
- await ensureSlackThreadTree([task.id]);
204
- } catch (error) {
205
- console.error("[Slack] Assistant userMessage error:", error);
206
- }
207
- }
208
- });
209
- }
210
- export {
211
- createAssistant
212
- };
@@ -1,317 +0,0 @@
1
- import {
2
- IDENTITY_FIELD_BUDGETS,
3
- init_identity_field_budget,
4
- init_templates
5
- } from "./cli-kpev657q.js";
6
- import {
7
- init_resolver,
8
- resolveTemplateAsync
9
- } from "./cli-7fnkj1hj.js";
10
- import {
11
- MAX_PROFILE_FILE_LENGTH,
12
- init_constants
13
- } from "./cli-e29gmdmw.js";
14
- import {
15
- init_secret_scrubber,
16
- scrubSecrets
17
- } from "./cli-xqcq9y5e.js";
18
- import {
19
- __esm
20
- } from "./cli-bc05qbss.js";
21
-
22
- // src/commands/profile-sync.ts
23
- function contentSha256(content) {
24
- return new Bun.CryptoHasher("sha256").update(content).digest("hex");
25
- }
26
- async function renderProfileSyncRejectionBanner(event) {
27
- const data = event.data;
28
- const field = data?.field;
29
- const diskSize = data?.diskSize;
30
- const dbSize = data?.dbSize;
31
- const budget = data?.budget;
32
- const delta = data?.delta;
33
- if (typeof field !== "string" || !(field in PROFILE_FIELD_DETAILS) || typeof diskSize !== "number" || typeof dbSize !== "number" || typeof budget !== "number" || typeof delta !== "number") {
34
- return null;
35
- }
36
- const details = PROFILE_FIELD_DETAILS[field];
37
- const result = await resolveTemplateAsync("task.profile_sync_rejection", {
38
- timestamp: event.createdAt,
39
- field_label: details.label,
40
- disk_size: diskSize,
41
- db_size: dbSize,
42
- budget,
43
- delta: delta >= 0 ? `+${delta}` : String(delta),
44
- event_id: event.id,
45
- recovery_guidance: details.recoveryGuidance
46
- });
47
- return result.skipped ? null : result.text;
48
- }
49
- async function fetchProfileSyncRejectionBanner(config, fetchImpl = fetch, readFile = readFileIfExists) {
50
- try {
51
- const responses = await Promise.all(Object.keys(IDENTITY_FIELD_BUDGETS).map(async (field) => {
52
- const fetchLatestEvent = async (event) => {
53
- const query = new URLSearchParams({
54
- event,
55
- agentId: config.agentId,
56
- dataField: field,
57
- limit: "1"
58
- });
59
- const response = await fetchImpl(`${config.apiUrl}/api/events?${query}`, {
60
- headers: {
61
- Authorization: `Bearer ${config.apiKey}`,
62
- "X-Agent-ID": config.agentId
63
- }
64
- });
65
- if (!response.ok)
66
- return null;
67
- const payload = await response.json();
68
- return payload.events?.[0] ?? null;
69
- };
70
- const [rejection, reconciliation] = await Promise.all([
71
- fetchLatestEvent("system.profile_sync_rejected"),
72
- fetchLatestEvent("system.profile_sync_reconciled")
73
- ]);
74
- return { rejection, reconciliation };
75
- }));
76
- const latestEvents = responses.flatMap(({ rejection, reconciliation }) => rejection ? [{ rejection, reconciliation }] : []);
77
- if (latestEvents.length === 0)
78
- return "";
79
- let profile = null;
80
- const profileResponse = await fetchImpl(`${config.apiUrl}/me`, {
81
- headers: {
82
- Authorization: `Bearer ${config.apiKey}`,
83
- "X-Agent-ID": config.agentId
84
- }
85
- });
86
- if (profileResponse.ok) {
87
- profile = await profileResponse.json();
88
- }
89
- let disk = null;
90
- if (config.claudeMdPath) {
91
- disk = {
92
- soulMd: await readFile(SOUL_MD_PATH),
93
- identityMd: await readFile(IDENTITY_MD_PATH),
94
- claudeMd: await readFile(config.claudeMdPath),
95
- toolsMd: await readFile(TOOLS_MD_PATH)
96
- };
97
- }
98
- const unresolved = latestEvents.flatMap(({ rejection, reconciliation }) => {
99
- if (reconciliation && reconciliation.createdAt > rejection.createdAt)
100
- return [];
101
- const event = rejection;
102
- const field = event.data?.field;
103
- const rejectedDbHash = event.data?.dbHash;
104
- const currentValue = typeof field === "string" ? profile?.[field] : undefined;
105
- const diskValue = typeof field === "string" ? disk?.[field] : undefined;
106
- if (typeof currentValue === "string" && diskValue === currentValue)
107
- return [];
108
- return !(typeof rejectedDbHash === "string" && typeof currentValue === "string" && contentSha256(currentValue) !== rejectedDbHash) ? [event] : [];
109
- });
110
- const banners = await Promise.all(unresolved.map(renderProfileSyncRejectionBanner));
111
- return banners.filter((banner) => banner !== null).join("");
112
- } catch {
113
- return "";
114
- }
115
- }
116
- async function prependProfileSyncRejectionBanner(prompt, config, fetchImpl = fetch, readFile = readFileIfExists) {
117
- const banner = await fetchProfileSyncRejectionBanner(config, fetchImpl, readFile);
118
- return banner ? { prompt: banner + prompt, injected: true } : { prompt, injected: false };
119
- }
120
- async function writeIdentityBaselines(baselines) {
121
- await Bun.write(IDENTITY_BASELINES_PATH, JSON.stringify(baselines));
122
- }
123
- async function readIdentityBaselines(readFile = readFileIfExists) {
124
- try {
125
- const raw = await readFile(IDENTITY_BASELINES_PATH);
126
- if (!raw)
127
- return null;
128
- return JSON.parse(raw);
129
- } catch {
130
- return null;
131
- }
132
- }
133
- function warnProfileFileTooLarge(agentId, field, actualLength, source = "profile-sync") {
134
- console.warn(`[${source}] Skipping profile sync for agent ${agentId}, field ${field}: ${actualLength} characters exceeds the ${MAX_PROFILE_FILE_LENGTH}-character cap.`);
135
- }
136
- async function writeProfileFileFromDb(filePath, dbContent, now = () => new Date) {
137
- const file = Bun.file(filePath);
138
- let backupPath = null;
139
- if (await file.exists()) {
140
- const localContent = await file.text();
141
- if (localContent !== dbContent) {
142
- backupPath = `${filePath}.pre-boot-${now().toISOString()}.bak`;
143
- await Bun.write(backupPath, localContent);
144
- }
145
- }
146
- await Bun.write(filePath, dbContent);
147
- return backupPath;
148
- }
149
- function resolveClaudeMdPath(completedProviders) {
150
- const anyNonClaude = completedProviders.some((p) => p !== "claude");
151
- return anyNonClaude ? WORKSPACE_CLAUDE_MD_PATH : CLAUDE_MD_PATH;
152
- }
153
- function buildIndependentIdentityPayloads(updates, changeSource) {
154
- return Object.entries(updates).map(([field, value]) => ({
155
- label: `identity.${field}`,
156
- body: { [field]: value, changeSource }
157
- }));
158
- }
159
- function extractSetupScriptContent(raw, agentId = "unknown") {
160
- if (!raw.trim())
161
- return null;
162
- const startIdx = raw.indexOf(SETUP_MARKER_START);
163
- const endIdx = raw.indexOf(SETUP_MARKER_END);
164
- let content;
165
- if (startIdx !== -1 && endIdx !== -1) {
166
- content = raw.substring(startIdx + SETUP_MARKER_START.length, endIdx).trim();
167
- } else {
168
- content = raw.replace(/^#!\/bin\/bash\n/, "").trim();
169
- }
170
- if (!content)
171
- return null;
172
- if (content.length > MAX_PROFILE_FILE_LENGTH) {
173
- warnProfileFileTooLarge(agentId, "setupScript", content.length);
174
- return null;
175
- }
176
- return content;
177
- }
178
- function buildIdentityPayload(files, baselines, agentId = "unknown") {
179
- const updates = {};
180
- if (files.soulMd !== undefined) {
181
- const content = files.soulMd;
182
- if (baselines?.soulMd && contentSha256(content) === baselines.soulMd) {} else if (content.trim()) {
183
- if (content.length < IDENTITY_FILE_MIN_LENGTH) {
184
- console.error(`[profile-sync] Skipping SOUL.md sync: content too short (${content.length} chars, minimum ${IDENTITY_FILE_MIN_LENGTH}). This prevents accidental profile corruption.`);
185
- } else {
186
- updates.soulMd = content;
187
- }
188
- }
189
- }
190
- if (files.identityMd !== undefined) {
191
- const content = files.identityMd;
192
- if (baselines?.identityMd && contentSha256(content) === baselines.identityMd) {} else if (content.trim()) {
193
- if (content.length < IDENTITY_FILE_MIN_LENGTH) {
194
- console.error(`[profile-sync] Skipping IDENTITY.md sync: content too short (${content.length} chars, minimum ${IDENTITY_FILE_MIN_LENGTH}). This prevents accidental profile corruption.`);
195
- } else {
196
- updates.identityMd = content;
197
- }
198
- }
199
- }
200
- if (files.toolsMd !== undefined) {
201
- const content = files.toolsMd;
202
- if (baselines?.toolsMd && contentSha256(content) === baselines.toolsMd) {} else if (content.trim()) {
203
- updates.toolsMd = content;
204
- }
205
- }
206
- if (files.heartbeatMd !== undefined) {
207
- const content = files.heartbeatMd;
208
- if (baselines?.heartbeatMd && contentSha256(content) === baselines.heartbeatMd) {} else if (content.length > MAX_PROFILE_FILE_LENGTH) {
209
- warnProfileFileTooLarge(agentId, "heartbeatMd", content.length);
210
- } else {
211
- updates.heartbeatMd = content;
212
- }
213
- }
214
- return updates;
215
- }
216
- async function readFileIfExists(path) {
217
- try {
218
- const file = Bun.file(path);
219
- if (!await file.exists())
220
- return;
221
- return await file.text();
222
- } catch {
223
- return;
224
- }
225
- }
226
- async function collectProfilePayloads(fields, changeSource, readFile = readFileIfExists, claudeMdPath = CLAUDE_MD_PATH, agentId = "unknown") {
227
- const payloads = [];
228
- const baselines = changeSource === "session_sync" ? await readIdentityBaselines(readFile) : null;
229
- if (fields.includes("identity")) {
230
- const updates = buildIdentityPayload({
231
- soulMd: await readFile(SOUL_MD_PATH),
232
- identityMd: await readFile(IDENTITY_MD_PATH),
233
- toolsMd: await readFile(TOOLS_MD_PATH),
234
- heartbeatMd: await readFile(HEARTBEAT_MD_PATH)
235
- }, baselines, agentId);
236
- payloads.push(...buildIndependentIdentityPayloads(updates, changeSource));
237
- }
238
- if (fields.includes("claude")) {
239
- const raw = await readFile(claudeMdPath);
240
- if (raw?.trim()) {
241
- if (baselines?.claudeMd && contentSha256(raw) === baselines.claudeMd) {} else {
242
- payloads.push({ label: "claude", body: { claudeMd: raw, changeSource } });
243
- }
244
- }
245
- }
246
- if (fields.includes("setup")) {
247
- const raw = await readFile(SETUP_SCRIPT_PATH);
248
- if (raw !== undefined) {
249
- const content = extractSetupScriptContent(raw, agentId);
250
- if (content !== null) {
251
- payloads.push({ label: "setup", body: { setupScript: content, changeSource } });
252
- }
253
- }
254
- }
255
- return payloads;
256
- }
257
- async function postProfileUpdate(opts, payload) {
258
- const doFetch = opts.fetchImpl ?? fetch;
259
- try {
260
- const resp = await doFetch(`${opts.apiUrl}/api/agents/${opts.agentId}/profile`, {
261
- method: "PUT",
262
- headers: {
263
- "Content-Type": "application/json",
264
- Authorization: `Bearer ${opts.apiKey}`,
265
- "X-Agent-ID": opts.agentId
266
- },
267
- body: JSON.stringify(payload.body)
268
- });
269
- if (!resp.ok) {
270
- let detail = "";
271
- try {
272
- detail = (await resp.text()).slice(0, 500);
273
- } catch {}
274
- console.warn(scrubSecrets(`[profile-sync] ${payload.label} sync failed: HTTP ${resp.status}${detail ? ` — ${detail}` : ""}`));
275
- }
276
- } catch (err) {
277
- const msg = err instanceof Error ? err.message : String(err);
278
- console.warn(scrubSecrets(`[profile-sync] ${payload.label} sync errored: ${msg}`));
279
- }
280
- }
281
- async function syncProfileFilesToServer(opts) {
282
- const changeSource = opts.changeSource ?? "session_sync";
283
- const fields = opts.fields ?? ["identity", "claude", "setup"];
284
- const payloads = await collectProfilePayloads(fields, changeSource, readFileIfExists, opts.claudeMdPath ?? CLAUDE_MD_PATH, opts.agentId);
285
- for (const payload of payloads) {
286
- await postProfileUpdate(opts, payload);
287
- }
288
- }
289
- var SOUL_MD_PATH = "/workspace/SOUL.md", IDENTITY_MD_PATH = "/workspace/IDENTITY.md", TOOLS_MD_PATH = "/workspace/TOOLS.md", HEARTBEAT_MD_PATH = "/workspace/HEARTBEAT.md", SETUP_SCRIPT_PATH = "/workspace/start-up.sh", IDENTITY_BASELINES_PATH = "/tmp/identity-baselines.json", PROFILE_FIELD_DETAILS, CLAUDE_MD_PATH, WORKSPACE_CLAUDE_MD_PATH = "/workspace/CLAUDE.md", IDENTITY_FILE_MIN_LENGTH = 500, SETUP_MARKER_START = "# === Agent-managed setup (from DB) ===", SETUP_MARKER_END = "# === End agent-managed setup ===";
290
- var init_profile_sync = __esm(() => {
291
- init_resolver();
292
- init_constants();
293
- init_identity_field_budget();
294
- init_secret_scrubber();
295
- init_templates();
296
- PROFILE_FIELD_DETAILS = {
297
- soulMd: {
298
- label: `soulMd (${SOUL_MD_PATH})`,
299
- recoveryGuidance: `Inspect and shrink the live ${SOUL_MD_PATH} first, moving durable tail content into memory. After a worker restart, use ${SOUL_MD_PATH}.pre-boot-<timestamp>.bak as the fallback copy of the rejected content.`
300
- },
301
- identityMd: {
302
- label: `identityMd (${IDENTITY_MD_PATH})`,
303
- recoveryGuidance: `Inspect and shrink the live ${IDENTITY_MD_PATH} first, moving durable tail content into memory. After a worker restart, use ${IDENTITY_MD_PATH}.pre-boot-<timestamp>.bak as the fallback copy of the rejected content.`
304
- },
305
- claudeMd: {
306
- label: "claudeMd (/workspace/CLAUDE.md for non-Claude harnesses; ~/.claude/CLAUDE.md for Claude)",
307
- recoveryGuidance: "Inspect and shrink the live CLAUDE.md source first, moving durable tail content into memory. After a worker restart, non-Claude harnesses can use /workspace/CLAUDE.md.pre-boot-<timestamp>.bak as the fallback copy; Claude's native ~/.claude/CLAUDE.md source is not archived by that boot step."
308
- },
309
- toolsMd: {
310
- label: `toolsMd (${TOOLS_MD_PATH})`,
311
- recoveryGuidance: `Inspect and shrink the live ${TOOLS_MD_PATH} first, moving durable tail content into memory. After a worker restart, use ${TOOLS_MD_PATH}.pre-boot-<timestamp>.bak as the fallback copy of the rejected content.`
312
- }
313
- };
314
- CLAUDE_MD_PATH = `${process.env.HOME}/.claude/CLAUDE.md`;
315
- });
316
-
317
- export { contentSha256, prependProfileSyncRejectionBanner, writeIdentityBaselines, readIdentityBaselines, warnProfileFileTooLarge, writeProfileFileFromDb, resolveClaudeMdPath, buildIndependentIdentityPayloads, syncProfileFilesToServer, init_profile_sync };