@desplega.ai/agent-swarm 1.167.0 → 1.169.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 (184) hide show
  1. package/dist/{acp-adapter-zpvy6321.js → acp-adapter-m47zfx4a.js} +2 -2
  2. package/dist/{actions-fq2zrwtf.js → actions-ws7k3tvq.js} +25 -19
  3. package/dist/{amp-adapter-5gbk7501.js → amp-adapter-nvv8k8j5.js} +1 -1
  4. package/dist/{app-nctetn1e.js → app-80w6qspx.js} +5 -5
  5. package/dist/{assistant-0aq8gjvj.js → assistant-jtq439kw.js} +29 -20
  6. package/dist/{boot-reembed-1ze5853n.js → boot-reembed-3nc0aaed.js} +4 -4
  7. package/dist/{boot-reembed-fmp5ww69.js → boot-reembed-feda8wn8.js} +4 -4
  8. package/dist/{boot-scrub-sweep-cbp8xd4e.js → boot-scrub-sweep-grsa2er0.js} +5 -5
  9. package/dist/{boot-seeds-22tx8a53.js → boot-seeds-gcfgq44f.js} +7 -7
  10. package/dist/{claude-adapter-0jhgeh1d.js → claude-adapter-pjv2q7t8.js} +7 -7
  11. package/dist/{claude-managed-adapter-tzwxy803.js → claude-managed-adapter-0wa8se82.js} +2 -2
  12. package/dist/{claude-managed-setup-nrhfx5b0.js → claude-managed-setup-zxa9p9tx.js} +1 -1
  13. package/dist/{claude-sdk-session-wh77rh83.js → claude-sdk-session-c9j6k9kx.js} +8772 -8663
  14. package/dist/{cli-c2tpw9ck.js → cli-3ry5gx4f.js} +1 -1
  15. package/dist/{cli-wydz3feg.js → cli-61tbnjpf.js} +214 -2472
  16. package/dist/{cli-cexctgn5.js → cli-7vz49g7h.js} +101 -34
  17. package/dist/{cli-6qxmjpem.js → cli-8xjst8q2.js} +34 -22
  18. package/dist/{cli-tx2zvn23.js → cli-91r17hb1.js} +3 -3
  19. package/dist/{cli-577bxkf6.js → cli-a8vps458.js} +182 -2208
  20. package/dist/{cli-tc5zec7v.js → cli-b7y8113e.js} +1 -1
  21. package/dist/{cli-69egj654.js → cli-bqrs5ycj.js} +1 -1
  22. package/dist/{cli-cf2vgn9d.js → cli-dv76vq5d.js} +30 -28
  23. package/dist/{cli-g5erf0zt.js → cli-e2prcx5m.js} +31 -0
  24. package/dist/{cli-c8r99akr.js → cli-e5qk3m2a.js} +209 -31
  25. package/dist/{cli-z1dqhc9y.js → cli-eqfbsxsn.js} +3 -3
  26. package/dist/{cli-kw0jcfje.js → cli-fyeft04q.js} +1 -1
  27. package/dist/{cli-5qkcdv8c.js → cli-gmdajfw5.js} +3 -3
  28. package/dist/{cli-ypgba1a8.js → cli-jkfxpg1b.js} +1 -1
  29. package/dist/{cli-mxvnnv5q.js → cli-jv36y8wz.js} +1 -1
  30. package/dist/{cli-m7vmeepg.js → cli-km8559dm.js} +6 -6
  31. package/dist/{cli-ykt8f7va.js → cli-kp3vfknv.js} +1 -1
  32. package/dist/{cli-ymmc1zxg.js → cli-m23r88re.js} +8 -5
  33. package/dist/{cli-v1pwxreq.js → cli-n4z21pt8.js} +1 -1
  34. package/dist/{cli-mxry91sa.js → cli-qg2zhjfc.js} +73 -4
  35. package/dist/{cli-1yrcfa5s.js → cli-rbr91whd.js} +4 -4
  36. package/dist/{cli-mkdsy1nq.js → cli-rg1c8ccw.js} +93 -7
  37. package/dist/cli-rh44xx46.js +2659 -0
  38. package/dist/cli-s0k2j7q9.js +2084 -0
  39. package/dist/{cli-ty4bzkqr.js → cli-sajr098b.js} +1 -1
  40. package/dist/{cli-6vfz44sr.js → cli-swrz3mj8.js} +1 -1
  41. package/dist/{cli-p8rt8spp.js → cli-vejds37t.js} +2 -2
  42. package/dist/{cli-jbzbr36n.js → cli-w6xa5nf5.js} +1 -1
  43. package/dist/{cli-9q3wt23f.js → cli-x6z90nq9.js} +1 -1
  44. package/dist/{cli-qzmzwegq.js → cli-ysnkvdx6.js} +102 -9
  45. package/dist/{cli-y0kjpfm9.js → cli-yvxfaem2.js} +2 -2
  46. package/dist/{cli-pkj1w46r.js → cli-z48ggfyq.js} +1 -1
  47. package/dist/{cli-6bpvv8h4.js → cli-zzev32jw.js} +1 -1
  48. package/dist/cli.js +20 -17
  49. package/dist/{codex-adapter-cgesnjkr.js → codex-adapter-0kpg09ca.js} +3 -3
  50. package/dist/{codex-hook-15dgc4cb.js → codex-hook-295jpbfa.js} +2 -2
  51. package/dist/{codex-session-runner-8kd7ddhr.js → codex-session-runner-8n672hxh.js} +3 -3
  52. package/dist/{commands-h6zaaxym.js → commands-mhmg5n0x.js} +4 -4
  53. package/dist/{cursor-adapter-v8mm6bp5.js → cursor-adapter-wn8n5zzk.js} +2 -2
  54. package/dist/{db-qg3myn53.js → db-wa6s1mwv.js} +4 -4
  55. package/dist/{dispatcher-7vnwj9qw.js → dispatcher-nhs2pkr8.js} +16 -14
  56. package/dist/{dsh-adapter-tz6hfp5r.js → dsh-adapter-5423p70m.js} +1 -1
  57. package/dist/{grok-adapter-jdt2dz2s.js → grok-adapter-28pkdt80.js} +3 -3
  58. package/dist/{handlers-2qtkpncr.js → handlers-5rtf9nng.js} +19 -17
  59. package/dist/{hook-51yfcgsv.js → hook-krjfkpzy.js} +4 -4
  60. package/dist/{hook-qnbdgwvd.js → hook-qkm73zk6.js} +5 -5
  61. package/dist/{http-jsmtag08.js → http-a397xcn4.js} +4845 -3484
  62. package/dist/{index-2t9kesn1.js → index-ac0v8v9d.js} +4 -4
  63. package/dist/{index-ekywyv2v.js → index-kqre45fr.js} +16 -14
  64. package/dist/{index-bt8wkv1w.js → index-rtxg15ah.js} +17 -15
  65. package/dist/{index-t4g06w93.js → index-vvsq7v45.js} +26 -23
  66. package/dist/{index-cx1sb9bq.js → index-ytdhtdry.js} +50 -11
  67. package/dist/{keepalive-4aezx4bj.js → keepalive-psfh8ysx.js} +6 -6
  68. package/dist/{lead-r44bkpm5.js → lead-m6rppjn7.js} +29 -27
  69. package/dist/{maintenance-grz5jrzh.js → maintenance-41f837ke.js} +4 -4
  70. package/dist/{node-qm9eb6z0.js → node-fkajaq96.js} +1 -1
  71. package/dist/{oauth-refresh-sweep-wm4ctjfj.js → oauth-refresh-sweep-6hr55hm8.js} +5 -5
  72. package/dist/{onboard-v60zgqf0.js → onboard-ktrtd7cz.js} +2 -2
  73. package/dist/{otel-impl-ghh4dyf8.js → otel-impl-dq4f2k3m.js} +1 -1
  74. package/dist/{pi-mono-adapter-0eg8kw2c.js → pi-mono-adapter-e5v9w0hv.js} +3 -2
  75. package/dist/{pricing-refresh-mjrqvnvw.js → pricing-refresh-kmk7j1ra.js} +6 -6
  76. package/dist/{rbac-roles-fd5tskj9.js → rbac-roles-9w1dkkxd.js} +4 -4
  77. package/dist/{rbac-roles-axv4d74x.js → rbac-roles-9ykx9tc5.js} +5 -5
  78. package/dist/{render-v2-k50j33qd.js → render-v2-ycqm53np.js} +5 -5
  79. package/dist/resume-cq2pkp8q.js +70 -0
  80. package/dist/{setup-4syh0pd2.js → setup-0dcmdvbn.js} +2 -2
  81. package/dist/{virtual-modules-ftr9kwe8.js → virtual-modules-1x9k4jcs.js} +1 -1
  82. package/dist/{work-objects-jcdbg8rr.js → work-objects-x01x2fh8.js} +19 -17
  83. package/dist/{worker-x8j8c9sx.js → worker-py1ssb1h.js} +29 -27
  84. package/openapi.json +15622 -15042
  85. package/package.json +8 -5
  86. package/src/apps/store.ts +1 -0
  87. package/src/artifact-sdk/feedback-overlay.ts +528 -0
  88. package/src/be/db/workflow-runs.ts +95 -0
  89. package/src/be/db-queries/slack-inbound.ts +489 -0
  90. package/src/be/db.ts +9 -2
  91. package/src/be/extensions/assets.ts +1 -1
  92. package/src/be/migrations/203_workflow_run_parent_step.sql +10 -0
  93. package/src/be/migrations/204_slack_inbound_receipts.sql +51 -0
  94. package/src/be/script-connections.ts +41 -7
  95. package/src/be/scripts/run-saved.ts +40 -20
  96. package/src/be/swarm-config-guard.ts +4 -0
  97. package/src/extensions/catalog.generated.json +17 -0
  98. package/src/extensions/catalog.ts +1 -1
  99. package/src/extensions/dispatcher.ts +3 -3
  100. package/src/heartbeat/heartbeat.ts +152 -2
  101. package/src/heartbeat/templates.ts +16 -0
  102. package/src/http/all-routes.ts +1 -0
  103. package/src/http/index.ts +2 -0
  104. package/src/http/integrations.ts +3 -1
  105. package/src/http/mcp-bridge.ts +1 -0
  106. package/src/http/pages-public.ts +7 -2
  107. package/src/http/pages.ts +178 -0
  108. package/src/http/script-connections.ts +35 -0
  109. package/src/http/slack-inbound.ts +107 -0
  110. package/src/http/tasks.ts +45 -27
  111. package/src/http/users.ts +1 -1
  112. package/src/http/webhooks.ts +20 -20
  113. package/src/prompts/session-templates.ts +32 -0
  114. package/src/providers/acp-targets.ts +1 -1
  115. package/src/providers/amp-adapter.ts +2 -2
  116. package/src/providers/claude-adapter.ts +6 -0
  117. package/src/providers/claude-background-keepalive.ts +100 -0
  118. package/src/providers/claude-managed-adapter.ts +2 -11
  119. package/src/providers/claude-sdk-session.ts +7 -1
  120. package/src/providers/dsh-adapter.ts +1 -1
  121. package/src/providers/opencode-adapter.ts +1 -2
  122. package/src/providers/pi-mono-adapter.ts +3 -3
  123. package/src/realtime/browser.generated.txt +8 -8
  124. package/src/realtime/browser.ts +3 -3
  125. package/src/scheduler/scheduler.ts +82 -13
  126. package/src/scripts-runtime/executors/quickjs-pool-config.ts +26 -0
  127. package/src/scripts-runtime/executors/quickjs.ts +9 -2
  128. package/src/scripts-runtime/executors/registry.ts +1 -1
  129. package/src/server.ts +1 -0
  130. package/src/slack/actions.ts +6 -2
  131. package/src/slack/app.ts +5 -0
  132. package/src/slack/assistant.ts +15 -5
  133. package/src/slack/egress-scrub.ts +3 -2
  134. package/src/slack/handlers.ts +36 -18
  135. package/src/slack/inbound-dispatch.ts +549 -0
  136. package/src/slack/inbound-files.ts +2 -0
  137. package/src/telemetry-context.ts +1 -0
  138. package/src/tests/claude-background-keepalive-wiring.test.ts +220 -0
  139. package/src/tests/claude-background-keepalive.fixture.ts +162 -0
  140. package/src/tests/claude-background-keepalive.test.ts +139 -0
  141. package/src/tests/codex-oauth-device.test.ts +1 -1
  142. package/src/tests/connection-embedded-auth.test.ts +51 -0
  143. package/src/tests/docs-index-footprint.test.js +3 -3
  144. package/src/tests/dsh-adapter.test.ts +1 -1
  145. package/src/tests/extensions-catalog.test.ts +1 -0
  146. package/src/tests/extensions-example-slack-reply-gate.test.ts +756 -0
  147. package/src/tests/heartbeat-checklist.test.ts +243 -0
  148. package/src/tests/pages-feedback.test.ts +218 -0
  149. package/src/tests/schedule-target-type.test.ts +136 -0
  150. package/src/tests/script-connections-http.test.ts +45 -0
  151. package/src/tests/script-connections-mcp.test.ts +41 -0
  152. package/src/tests/script-connections.test.ts +2 -0
  153. package/src/tests/script-executor-quickjs-pool.test.ts +106 -0
  154. package/src/tests/script-executor-registry.test.ts +56 -0
  155. package/src/tests/send-task-self-send.test.ts +107 -0
  156. package/src/tests/slack-inbound-diagnostics-auth.test.ts +93 -0
  157. package/src/tests/slack-inbound-receipts.test.ts +684 -0
  158. package/src/tests/slack-session-status.test.ts +4 -2
  159. package/src/tests/ui-e2e-ingest-payload.test.ts +5 -1
  160. package/src/tests/user-token-routes.test.ts +1 -1
  161. package/src/tests/workflow-executors.test.ts +3 -2
  162. package/src/tests/workflow-sub-workflow.test.ts +363 -0
  163. package/src/tools/script-connections/tool.ts +35 -3
  164. package/src/tools/send-task.ts +9 -1
  165. package/src/utils/internal-ai/complete-structured.ts +6 -3
  166. package/src/utils/runtime-model-catalog.ts +1 -1
  167. package/src/workflows/engine.ts +17 -1
  168. package/src/workflows/executors/agent-task.ts +2 -2
  169. package/src/workflows/executors/human-in-the-loop.ts +3 -3
  170. package/src/workflows/executors/registry.ts +2 -0
  171. package/src/workflows/executors/script.ts +1 -1
  172. package/src/workflows/executors/sub-workflow.ts +135 -0
  173. package/src/workflows/executors/wait.ts +3 -3
  174. package/src/workflows/recovery.ts +11 -1
  175. package/src/workflows/resume.ts +77 -0
  176. package/src/workflows/wait-filter.ts +5 -7
  177. package/templates/extensions/README.md +1 -0
  178. package/templates/extensions/slack-reply-gate/README.md +98 -0
  179. package/templates/extensions/slack-reply-gate/hooks.ts +582 -0
  180. package/templates/extensions/slack-reply-gate/manifest.json +8 -0
  181. package/templates/skills/heartbeat-runbook/content.md +3 -1
  182. package/templates/skills/pages/content.md +25 -0
  183. package/templates/skills/swarm-scripts/SKILL.md +10 -0
  184. package/templates/skills/swarm-scripts/content.md +10 -0
@@ -44,7 +44,7 @@ import type {
44
44
  * default; the image installs exactly this version and the per-task settings
45
45
  * set `amp.updates.mode: "disabled"`. Bump it deliberately, with a live run.
46
46
  */
47
- export const AMP_PACKAGE = "@ampcode/cli@0.0.1791460855-g1f688c";
47
+ export const AMP_PACKAGE = "@ampcode/cli@0.0.1791633643-g895a91";
48
48
 
49
49
  /** MCP server name. Amp exposes its tools as `agent_swarm` / `store_progress` (dashes become underscores). */
50
50
  const AMP_MCP_SERVER_NAME = "agent-swarm";
@@ -537,7 +537,7 @@ class AmpSession implements ProviderSession {
537
537
  }
538
538
 
539
539
  private get stdin(): AmpStdin {
540
- return this.proc.stdin as unknown as AmpStdin;
540
+ return this.proc.stdin as AmpStdin;
541
541
  }
542
542
 
543
543
  private async writeInput(text: string): Promise<void> {
@@ -41,6 +41,7 @@ import {
41
41
  terminateProcessGroup,
42
42
  } from "../utils/process-group";
43
43
  import { scrubSecrets } from "../utils/secret-scrubber";
44
+ import { ClaudeBackgroundKeepalive } from "./claude-background-keepalive";
44
45
  import { normalizeClaudeMessage } from "./claude-session-events";
45
46
  import { resolveSlashSkillPrompt } from "./codex-skill-resolver";
46
47
  import { CTX_MODE_NUDGE_EVERY } from "./ctx-mode-env";
@@ -904,6 +905,8 @@ class ClaudeSession implements ProviderSession {
904
905
  private lastAssistantText = "";
905
906
  /** Per-session stream-json transcript used by the parent-owned session summarizer. */
906
907
  private transcript: string[];
908
+ /** Keeps the session heartbeat fresh while Claude idles on background tasks. */
909
+ private backgroundKeepalive: ClaudeBackgroundKeepalive;
907
910
  readonly deliverSteering?: (delivery: SteerDelivery) => Promise<SteerDeliveryResult>;
908
911
 
909
912
  constructor(
@@ -925,6 +928,7 @@ class ClaudeSession implements ProviderSession {
925
928
  this.contextWindowSize = getContextWindowSize(model);
926
929
  this.systemPromptFile = systemPromptFile;
927
930
  this.transcript = [`User: ${scrubSecrets(config.prompt)}`];
931
+ this.backgroundKeepalive = new ClaudeBackgroundKeepalive(config);
928
932
  const cmd = this.buildCommand();
929
933
 
930
934
  console.log(
@@ -1158,6 +1162,7 @@ class ClaudeSession implements ProviderSession {
1158
1162
  try {
1159
1163
  await Promise.all([stdoutPromise, stderrPromise]);
1160
1164
  } finally {
1165
+ this.backgroundKeepalive.stop();
1161
1166
  this.closeStdin();
1162
1167
  }
1163
1168
  await logFileHandle.end();
@@ -1226,6 +1231,7 @@ class ClaudeSession implements ProviderSession {
1226
1231
  if (json.type === "result") {
1227
1232
  this.closeStdin();
1228
1233
  }
1234
+ this.backgroundKeepalive.observe(json);
1229
1235
 
1230
1236
  const normalized = normalizeClaudeMessage(json, {
1231
1237
  taskId: this.config.taskId,
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Keeps a Claude session's heartbeat fresh while it waits on background work.
3
+ *
4
+ * A Claude session that starts a `run_in_background` Bash job (or backgrounds a
5
+ * subagent) can end its turn and sit idle until the job's task_notification
6
+ * wakes it. During that wait it makes no tool calls and streams no output, so
7
+ * neither liveness input (the PostToolUse heartbeat and session-log ingestion)
8
+ * moves `active_sessions.lastHeartbeatAt`, and the stalled-task sweep classifies
9
+ * the live session as stale after `HEARTBEAT_STALL_STALE_HB_MIN`.
10
+ *
11
+ * Claude Code emits `system/background_tasks_changed` with the full set of live
12
+ * background tasks on every membership change (REPLACE semantics). While that
13
+ * set holds at least one non-ambient task, this pings the session heartbeat on
14
+ * an interval. With no background work the timer never runs, so a hung session
15
+ * still goes stale. A background job that never settles is bounded too: the
16
+ * keepalive stops once the session has emitted nothing for
17
+ * `BACKGROUND_KEEPALIVE_MAX_IDLE_MS`.
18
+ */
19
+
20
+ /** Ping interval; well inside the 15-minute stale-session threshold. */
21
+ export const BACKGROUND_KEEPALIVE_INTERVAL_MS = 60_000;
22
+ /** Longest silent wait on background work that the keepalive will cover. */
23
+ export const BACKGROUND_KEEPALIVE_MAX_IDLE_MS = 2 * 60 * 60_000;
24
+
25
+ type BackgroundTaskEntry = { task_id?: unknown; ambient?: unknown };
26
+
27
+ export interface ClaudeBackgroundKeepaliveOptions {
28
+ apiUrl: string;
29
+ apiKey: string;
30
+ agentId: string;
31
+ taskId: string;
32
+ intervalMs?: number;
33
+ maxIdleMs?: number;
34
+ }
35
+
36
+ export class ClaudeBackgroundKeepalive {
37
+ private liveTaskIds: string[] = [];
38
+ private timer: ReturnType<typeof setInterval> | undefined;
39
+ private lastMessageAt = Date.now();
40
+ private stopped = false;
41
+ private readonly intervalMs: number;
42
+ private readonly maxIdleMs: number;
43
+
44
+ constructor(private readonly options: ClaudeBackgroundKeepaliveOptions) {
45
+ this.intervalMs = options.intervalMs ?? BACKGROUND_KEEPALIVE_INTERVAL_MS;
46
+ this.maxIdleMs = options.maxIdleMs ?? BACKGROUND_KEEPALIVE_MAX_IDLE_MS;
47
+ }
48
+
49
+ /** Feed every protocol message the Claude process emits. */
50
+ observe(message: { type?: string; subtype?: string; tasks?: unknown }): void {
51
+ if (this.stopped) return;
52
+ this.lastMessageAt = Date.now();
53
+ if (message.type === "system" && message.subtype === "background_tasks_changed") {
54
+ const tasks = Array.isArray(message.tasks) ? (message.tasks as BackgroundTaskEntry[]) : [];
55
+ // Ambient tasks (live-update watchers, skip_transcript tasks) are not
56
+ // activity; Claude Code asks hosts to leave them out of activity signals.
57
+ this.liveTaskIds = tasks
58
+ .filter((task) => task && task.ambient !== true && typeof task.task_id === "string")
59
+ .map((task) => task.task_id as string);
60
+ }
61
+ // Any message restarts a keepalive the idle cap stopped, while work is live.
62
+ if (this.liveTaskIds.length > 0) this.start();
63
+ else this.clearTimer();
64
+ }
65
+
66
+ /** Stop pinging for good; call when the session ends. */
67
+ stop(): void {
68
+ this.stopped = true;
69
+ this.liveTaskIds = [];
70
+ this.clearTimer();
71
+ }
72
+
73
+ private start(): void {
74
+ if (this.timer !== undefined) return;
75
+ if (!this.options.apiUrl || !this.options.taskId) return;
76
+ this.timer = setInterval(() => this.tick(), this.intervalMs);
77
+ }
78
+
79
+ private tick(): void {
80
+ if (Date.now() - this.lastMessageAt > this.maxIdleMs) {
81
+ this.clearTimer();
82
+ return;
83
+ }
84
+ const { apiUrl, apiKey, agentId, taskId } = this.options;
85
+ void fetch(`${apiUrl}/api/active-sessions/heartbeat/${encodeURIComponent(taskId)}`, {
86
+ method: "PUT",
87
+ headers: {
88
+ "Content-Type": "application/json",
89
+ Authorization: `Bearer ${apiKey}`,
90
+ "X-Agent-ID": agentId,
91
+ },
92
+ }).catch(() => {});
93
+ }
94
+
95
+ private clearTimer(): void {
96
+ if (this.timer === undefined) return;
97
+ clearInterval(this.timer);
98
+ this.timer = undefined;
99
+ }
100
+ }
@@ -37,8 +37,6 @@
37
37
 
38
38
  import Anthropic from "@anthropic-ai/sdk";
39
39
  // Real type usages (the Phase 1 imports become non-decorative as of this phase).
40
- import type { BetaManagedAgentsAgent as Agent } from "@anthropic-ai/sdk/resources/beta/agents";
41
- import type { BetaEnvironment as Environment } from "@anthropic-ai/sdk/resources/beta/environments";
42
40
  import type {
43
41
  BetaManagedAgentsAgentMCPToolResultEvent,
44
42
  BetaManagedAgentsAgentMCPToolUseEvent,
@@ -57,7 +55,6 @@ import type {
57
55
  BetaManagedAgentsSession as Session,
58
56
  BetaManagedAgentsSessionEvent as SessionEvent,
59
57
  } from "@anthropic-ai/sdk/resources/beta/sessions";
60
- import type { BetaSkill as Skill } from "@anthropic-ai/sdk/resources/beta/skills";
61
58
 
62
59
  import { checkToolLoop } from "../hooks/tool-loop-detection";
63
60
  import {
@@ -107,13 +104,6 @@ export function checkClaudeManagedCredentials(env: Record<string, string | undef
107
104
  };
108
105
  }
109
106
 
110
- // Re-export the type aliases at module level so adjacent files / tests can use
111
- // the short names without re-discovering the long Beta-prefixed ones. Kept on
112
- // `void` lines so unused-import lints stay quiet for the type imports above.
113
- void (null as unknown as Agent);
114
- void (null as unknown as Environment);
115
- void (null as unknown as Skill);
116
-
117
107
  /**
118
108
  * Required env vars validated at construction time. Listing them in one place
119
109
  * keeps the error messages consistent and makes it easy for Phase 2 (worker
@@ -677,7 +667,7 @@ class ClaudeManagedSession implements ProviderSession {
677
667
  events: [
678
668
  {
679
669
  type: "user.message",
680
- content: this.userMessageContent as unknown as Record<string, unknown>[],
670
+ content: this.userMessageContent,
681
671
  },
682
672
  ],
683
673
  });
@@ -857,6 +847,7 @@ export class ClaudeManagedAdapter implements ProviderAdapter {
857
847
  // our narrower `ManagedAgentsClient` interface (which exists for
858
848
  // testability) but TypeScript can't infer that without us spelling out
859
849
  // every method signature on both sides.
850
+ // oxlint-disable-next-line anti-slop/no-chained-type-assertions -- see the comment above.
860
851
  this.client = new Anthropic({ apiKey: this.apiKey }) as unknown as ManagedAgentsClient;
861
852
  }
862
853
  }
@@ -29,6 +29,7 @@ import {
29
29
  cleanupTaskFile,
30
30
  runClaudeSessionSummary,
31
31
  } from "./claude-adapter";
32
+ import { ClaudeBackgroundKeepalive } from "./claude-background-keepalive";
32
33
  import type { ClaudeProtocolMessage } from "./claude-session-events";
33
34
  import { normalizeClaudeMessage } from "./claude-session-events";
34
35
  import type {
@@ -317,8 +318,11 @@ class ClaudeSdkSession implements ProviderSession {
317
318
  private acceptingInput = true;
318
319
  private errorTracker = new SessionErrorTracker();
319
320
  private shutdownPromise: Promise<void> | undefined;
321
+ /** Keeps the session heartbeat fresh while Claude idles on background tasks. */
322
+ private backgroundKeepalive: ClaudeBackgroundKeepalive;
320
323
 
321
324
  constructor(private options: CreateClaudeSdkSessionOptions) {
325
+ this.backgroundKeepalive = new ClaudeBackgroundKeepalive(options.config);
322
326
  this.model = options.model;
323
327
  this.contextWindowSize = getContextWindowSize(options.model);
324
328
  this.transcript = [`User: ${scrubSecrets(options.config.prompt)}`];
@@ -405,7 +409,8 @@ class ClaudeSdkSession implements ProviderSession {
405
409
  }
406
410
 
407
411
  private handleMessage(message: SDKMessage): boolean {
408
- const json = message as unknown as ClaudeProtocolMessage;
412
+ const json = message as ClaudeProtocolMessage;
413
+ this.backgroundKeepalive.observe(json);
409
414
  const normalized = normalizeClaudeMessage(json, {
410
415
  taskId: this.options.config.taskId,
411
416
  agentId: this.options.config.agentId,
@@ -514,6 +519,7 @@ class ClaudeSdkSession implements ProviderSession {
514
519
  this.emit({ type: "error", message, category: "sdk_transport" });
515
520
  }
516
521
  } finally {
522
+ this.backgroundKeepalive.stop();
517
523
  this.acceptingInput = false;
518
524
  this.input.close();
519
525
  if (this.aborted) {
@@ -37,7 +37,7 @@ import type {
37
37
  } from "./types";
38
38
 
39
39
  // npm's `latest` is older and lacks the JSON/stdin contract used here.
40
- export const DSH_PACKAGE = "@deepseek-ai/dsh@0.2.1-alpha.1";
40
+ export const DSH_PACKAGE = "@deepseek-ai/dsh@0.2.1-alpha.2";
41
41
 
42
42
  export function checkDshCredentials(env: Record<string, string | undefined>): CredStatus {
43
43
  return env.DEEPSEEK_API_KEY?.trim() || env.OPENROUTER_API_KEY?.trim()
@@ -559,8 +559,7 @@ export class OpencodeSession implements ProviderSession {
559
559
  // so the dashboard's Activity timeline mirrors what other providers
560
560
  // emit. We fire tool_start the first time we see a tool part (any
561
561
  // status); tool_end fires once when state transitions to "completed".
562
- const props = (ev as unknown as { properties: { sessionID?: string; part?: unknown } })
563
- .properties;
562
+ const props = (ev as { properties: { sessionID?: string; part?: unknown } }).properties;
564
563
  if (props.sessionID !== this._sessionId) break;
565
564
  const part = props.part as
566
565
  | {
@@ -1692,9 +1692,9 @@ export class PiMonoAdapter implements ProviderAdapter {
1692
1692
  try {
1693
1693
  const sessionManager = SessionManager.create(this.lastCwd);
1694
1694
  // SessionManager stores sessions as files — check if the session exists
1695
- const sessions = await (
1696
- sessionManager as unknown as { list(): Promise<Array<{ id: string }>> }
1697
- ).list?.();
1695
+ // oxlint-disable-next-line anti-slop/no-chained-type-assertions -- pi declares list() as static, so this optional call finds nothing.
1696
+ const listable = sessionManager as unknown as { list?(): Promise<Array<{ id: string }>> };
1697
+ const sessions = await listable.list?.();
1698
1698
  return sessions?.some((s) => s.id === sessionId) ?? false;
1699
1699
  } catch {
1700
1700
  return false;