@duckmind/dm-windows-x64 0.60.6 → 0.60.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dm.exe +0 -0
- package/extensions/.dm-extensions.json +70 -123
- package/extensions/dm-9router-ext/src/index.js +410 -5
- package/extensions/dm-caveman/extensions/caveman.js +283 -12
- package/extensions/dm-cliproxy/index.js +182 -2
- package/extensions/dm-cliproxy/scripts/check-config-migration.js +66 -8
- package/extensions/dm-cliproxy/src/apply.js +228 -1
- package/extensions/dm-cliproxy/src/cache.js +42 -1
- package/extensions/dm-cliproxy/src/commands.js +50 -2
- package/extensions/dm-cliproxy/src/compat.js +81 -1
- package/extensions/dm-cliproxy/src/config.js +192 -2
- package/extensions/dm-cliproxy/src/conflicts.js +46 -1
- package/extensions/dm-cliproxy/src/fetch-models.js +190 -1
- package/extensions/dm-cliproxy/src/fetch-usage.js +41 -1
- package/extensions/dm-cliproxy/src/log.js +23 -1
- package/extensions/dm-cliproxy/src/status-quota.js +77 -1
- package/extensions/dm-cliproxy/src/ui-frame.js +50 -1
- package/extensions/dm-cliproxy/src/ui-hub/hub.js +199 -2
- package/extensions/dm-cliproxy/src/ui-hub/index.js +26 -2
- package/extensions/dm-cliproxy/src/ui-hub/shell.js +46 -1
- package/extensions/dm-cliproxy/src/ui-hub/view-diagnostics.js +69 -1
- package/extensions/dm-cliproxy/src/ui-hub/view-models.js +379 -1
- package/extensions/dm-cliproxy/src/ui-hub/view-usage.js +106 -1
- package/extensions/dm-cliproxy/src/ui-picker/catalog.js +41 -1
- package/extensions/dm-cliproxy/src/ui-picker/mutate.js +115 -1
- package/extensions/dm-cliproxy/src/ui-picker/prompt-confirm.js +35 -1
- package/extensions/dm-cliproxy/src/ui-picker/prompt-name.js +62 -1
- package/extensions/dm-cliproxy/src/ui-picker/providers.js +45 -1
- package/extensions/dm-cliproxy/src/ui-picker/render-text.js +34 -1
- package/extensions/dm-cliproxy/src/ui-picker/rows.js +57 -1
- package/extensions/dm-cliproxy/src/ui-setup.js +260 -2
- package/extensions/dm-cliproxy/src/ui-usage.js +151 -1
- package/extensions/dm-cliproxy/src/usage-shared-cache.js +97 -1
- package/extensions/dm-context/src/context.js +144 -1
- package/extensions/dm-context/src/index.js +339 -7
- package/extensions/dm-context/src/utils.js +9 -1
- package/extensions/dm-cua/bin/browser-cua.mjs +73 -8
- package/extensions/dm-cua/index.js +75 -6
- package/extensions/dm-cua/src/browser-cua-lib.mjs +490 -6
- package/extensions/dm-cua/src/browser-install.mjs +331 -2
- package/extensions/dm-fff/src/index.js +688 -12
- package/extensions/dm-fff/src/query.js +60 -1
- package/extensions/dm-goal/src/goal.js +894 -23
- package/extensions/dm-image2/index.js +103 -9
- package/extensions/dm-image2/src/image-lib.mjs +1275 -8
- package/extensions/dm-subagents/install.mjs +62 -8
- package/extensions/dm-subagents/src/agents/agent-management.js +1190 -36
- package/extensions/dm-subagents/src/agents/agent-memory.js +216 -6
- package/extensions/dm-subagents/src/agents/agent-scope.js +5 -1
- package/extensions/dm-subagents/src/agents/agent-selection.js +20 -1
- package/extensions/dm-subagents/src/agents/agent-serializer.js +120 -5
- package/extensions/dm-subagents/src/agents/agents.js +1139 -11
- package/extensions/dm-subagents/src/agents/chain-serializer.js +299 -11
- package/extensions/dm-subagents/src/agents/frontmatter.js +65 -6
- package/extensions/dm-subagents/src/agents/identity.js +29 -1
- package/extensions/dm-subagents/src/agents/proactive-skills.js +141 -1
- package/extensions/dm-subagents/src/agents/skills.js +614 -6
- package/extensions/dm-subagents/src/extension/config.js +35 -2
- package/extensions/dm-subagents/src/extension/control-notices.js +69 -4
- package/extensions/dm-subagents/src/extension/doctor.js +172 -15
- package/extensions/dm-subagents/src/extension/fanout-child.js +158 -231
- package/extensions/dm-subagents/src/extension/index.js +521 -359
- package/extensions/dm-subagents/src/extension/rpc.js +266 -7
- package/extensions/dm-subagents/src/extension/schemas.js +275 -1
- package/extensions/dm-subagents/src/extension/tool-description.js +111 -6
- package/extensions/dm-subagents/src/intercom/intercom-bridge.js +126 -4
- package/extensions/dm-subagents/src/intercom/native-supervisor-channel.js +452 -5
- package/extensions/dm-subagents/src/intercom/result-intercom.js +319 -3
- package/extensions/dm-subagents/src/profiles/profiles.js +458 -3
- package/extensions/dm-subagents/src/runs/background/async-execution.js +834 -40
- package/extensions/dm-subagents/src/runs/background/async-job-tracker.js +435 -14
- package/extensions/dm-subagents/src/runs/background/async-resume.js +334 -8
- package/extensions/dm-subagents/src/runs/background/async-status.js +313 -12
- package/extensions/dm-subagents/src/runs/background/chain-append.js +245 -2
- package/extensions/dm-subagents/src/runs/background/chain-root-attachment.js +136 -1
- package/extensions/dm-subagents/src/runs/background/completion-batcher.js +94 -1
- package/extensions/dm-subagents/src/runs/background/completion-dedupe.js +54 -1
- package/extensions/dm-subagents/src/runs/background/control-channel.js +190 -1
- package/extensions/dm-subagents/src/runs/background/fleet-view.js +483 -17
- package/extensions/dm-subagents/src/runs/background/notify.js +129 -3
- package/extensions/dm-subagents/src/runs/background/parallel-groups.js +34 -1
- package/extensions/dm-subagents/src/runs/background/result-watcher.js +236 -6
- package/extensions/dm-subagents/src/runs/background/run-id-resolver.js +76 -4
- package/extensions/dm-subagents/src/runs/background/run-status.js +427 -23
- package/extensions/dm-subagents/src/runs/background/scheduled-runs.js +487 -4
- package/extensions/dm-subagents/src/runs/background/stale-run-reconciler.js +306 -9
- package/extensions/dm-subagents/src/runs/background/subagent-runner.js +2849 -73
- package/extensions/dm-subagents/src/runs/background/top-level-async.js +5 -1
- package/extensions/dm-subagents/src/runs/background/wait.js +206 -11
- package/extensions/dm-subagents/src/runs/foreground/chain-clarify.js +1013 -12
- package/extensions/dm-subagents/src/runs/foreground/chain-execution.js +980 -101
- package/extensions/dm-subagents/src/runs/foreground/execution.js +1165 -45
- package/extensions/dm-subagents/src/runs/foreground/subagent-executor.js +3157 -222
- package/extensions/dm-subagents/src/runs/shared/acceptance.js +835 -3
- package/extensions/dm-subagents/src/runs/shared/chain-outputs.js +104 -1
- package/extensions/dm-subagents/src/runs/shared/completion-guard.js +116 -3
- package/extensions/dm-subagents/src/runs/shared/dm-args.js +208 -1
- package/extensions/dm-subagents/src/runs/shared/dm-spawn.js +90 -1
- package/extensions/dm-subagents/src/runs/shared/dynamic-fanout.js +282 -1
- package/extensions/dm-subagents/src/runs/shared/long-running-guard.js +148 -1
- package/extensions/dm-subagents/src/runs/shared/mcp-direct-tool-allowlist.js +305 -1
- package/extensions/dm-subagents/src/runs/shared/model-fallback.js +194 -1
- package/extensions/dm-subagents/src/runs/shared/model-scope.js +65 -1
- package/extensions/dm-subagents/src/runs/shared/nested-events.js +851 -8
- package/extensions/dm-subagents/src/runs/shared/nested-path.js +41 -1
- package/extensions/dm-subagents/src/runs/shared/nested-render.js +105 -1
- package/extensions/dm-subagents/src/runs/shared/parallel-utils.js +81 -4
- package/extensions/dm-subagents/src/runs/shared/run-history.js +51 -4
- package/extensions/dm-subagents/src/runs/shared/single-output.js +149 -8
- package/extensions/dm-subagents/src/runs/shared/structured-output.js +58 -1
- package/extensions/dm-subagents/src/runs/shared/subagent-control.js +166 -5
- package/extensions/dm-subagents/src/runs/shared/subagent-prompt-runtime.js +329 -13
- package/extensions/dm-subagents/src/runs/shared/tool-budget.js +73 -1
- package/extensions/dm-subagents/src/runs/shared/turn-budget.js +47 -4
- package/extensions/dm-subagents/src/runs/shared/workflow-graph.js +196 -1
- package/extensions/dm-subagents/src/runs/shared/worktree.js +435 -3
- package/extensions/dm-subagents/src/shared/artifacts.js +92 -2
- package/extensions/dm-subagents/src/shared/atomic-json.js +55 -1
- package/extensions/dm-subagents/src/shared/child-transcript.js +167 -5
- package/extensions/dm-subagents/src/shared/file-coalescer.js +25 -1
- package/extensions/dm-subagents/src/shared/fork-context.js +147 -4
- package/extensions/dm-subagents/src/shared/formatters.js +98 -7
- package/extensions/dm-subagents/src/shared/jsonl-writer.js +56 -2
- package/extensions/dm-subagents/src/shared/model-info.js +62 -1
- package/extensions/dm-subagents/src/shared/post-exit-stdio-guard.js +68 -1
- package/extensions/dm-subagents/src/shared/session-identity.js +6 -1
- package/extensions/dm-subagents/src/shared/session-tokens.js +39 -2
- package/extensions/dm-subagents/src/shared/settings.js +198 -11
- package/extensions/dm-subagents/src/shared/status-format.js +53 -1
- package/extensions/dm-subagents/src/shared/types.js +184 -6
- package/extensions/dm-subagents/src/shared/utils.js +462 -2
- package/extensions/dm-subagents/src/slash/prompt-template-bridge.js +288 -1
- package/extensions/dm-subagents/src/slash/prompt-workflows.js +297 -7
- package/extensions/dm-subagents/src/slash/slash-bridge.js +118 -1
- package/extensions/dm-subagents/src/slash/slash-commands.js +1287 -31
- package/extensions/dm-subagents/src/slash/slash-live-state.js +240 -4
- package/extensions/dm-subagents/src/tui/render-helpers.js +64 -1
- package/extensions/dm-subagents/src/tui/render.js +1542 -4
- package/extensions/dm-usage/index.js +1294 -9
- package/extensions/greedysearch-dm/bin/cdp-greedy.mjs +40 -9
- package/extensions/greedysearch-dm/bin/cdp-headless.mjs +5 -2
- package/extensions/greedysearch-dm/bin/cdp-visible.mjs +5 -2
- package/extensions/greedysearch-dm/bin/cdp.mjs +896 -30
- package/extensions/greedysearch-dm/bin/gschrome.mjs +30 -2
- package/extensions/greedysearch-dm/bin/kill-visible.mjs +7 -2
- package/extensions/greedysearch-dm/bin/launch-visible.mjs +13 -2
- package/extensions/greedysearch-dm/bin/launch.mjs +282 -10
- package/extensions/greedysearch-dm/bin/mcp.mjs +386 -361
- package/extensions/greedysearch-dm/bin/search.mjs +620 -540
- package/extensions/greedysearch-dm/bin/visible.mjs +22 -2
- package/extensions/greedysearch-dm/extractors/bing-copilot.mjs +329 -579
- package/extensions/greedysearch-dm/extractors/chatgpt.mjs +301 -583
- package/extensions/greedysearch-dm/extractors/common.mjs +408 -32
- package/extensions/greedysearch-dm/extractors/consensus.mjs +376 -365
- package/extensions/greedysearch-dm/extractors/consent.mjs +303 -14
- package/extensions/greedysearch-dm/extractors/gemini.mjs +228 -592
- package/extensions/greedysearch-dm/extractors/google-ai.mjs +78 -499
- package/extensions/greedysearch-dm/extractors/logically.mjs +270 -347
- package/extensions/greedysearch-dm/extractors/perplexity.mjs +243 -581
- package/extensions/greedysearch-dm/extractors/selectors.mjs +32 -1
- package/extensions/greedysearch-dm/extractors/semantic-scholar.mjs +130 -317
- package/extensions/greedysearch-dm/index.js +123 -23
- package/extensions/greedysearch-dm/src/fetcher.mjs +576 -2
- package/extensions/greedysearch-dm/src/formatters/results.js +95 -10
- package/extensions/greedysearch-dm/src/formatters/sources.js +57 -1
- package/extensions/greedysearch-dm/src/formatters/synthesis.js +49 -1
- package/extensions/greedysearch-dm/src/github.mjs +222 -7
- package/extensions/greedysearch-dm/src/reddit.mjs +145 -14
- package/extensions/greedysearch-dm/src/search/browser-lifecycle.mjs +340 -9
- package/extensions/greedysearch-dm/src/search/challenge-detect.mjs +112 -4
- package/extensions/greedysearch-dm/src/search/chrome.mjs +486 -285
- package/extensions/greedysearch-dm/src/search/constants.mjs +109 -8
- package/extensions/greedysearch-dm/src/search/defaults.mjs +10 -1
- package/extensions/greedysearch-dm/src/search/engines.mjs +79 -9
- package/extensions/greedysearch-dm/src/search/fetch-source.mjs +441 -349
- package/extensions/greedysearch-dm/src/search/file-sources.mjs +29 -7
- package/extensions/greedysearch-dm/src/search/minimize.mjs +86 -1
- package/extensions/greedysearch-dm/src/search/output.mjs +51 -5
- package/extensions/greedysearch-dm/src/search/paths.mjs +48 -1
- package/extensions/greedysearch-dm/src/search/pdf.mjs +63 -2
- package/extensions/greedysearch-dm/src/search/port-pid.mjs +69 -1
- package/extensions/greedysearch-dm/src/search/progress.mjs +109 -2
- package/extensions/greedysearch-dm/src/search/query.mjs +21 -1
- package/extensions/greedysearch-dm/src/search/recovery.mjs +49 -1
- package/extensions/greedysearch-dm/src/search/research.mjs +2227 -458
- package/extensions/greedysearch-dm/src/search/scale-aware.mjs +61 -11
- package/extensions/greedysearch-dm/src/search/simple-research.mjs +396 -805
- package/extensions/greedysearch-dm/src/search/sources.mjs +412 -1
- package/extensions/greedysearch-dm/src/search/synthesis-runner.mjs +127 -12
- package/extensions/greedysearch-dm/src/search/synthesis.mjs +202 -12
- package/extensions/greedysearch-dm/src/tools/greedy-search-handler.js +209 -23
- package/extensions/greedysearch-dm/src/tools/shared.js +226 -10
- package/extensions/greedysearch-dm/src/utils/content.mjs +35 -4
- package/extensions/greedysearch-dm/src/utils/helpers.js +22 -1
- package/extensions/greedysearch-dm/src/utils/node-runtime.mjs +10 -1
- package/extensions/greedysearch-dm/src/utils/system-cmds.mjs +61 -1
- package/package.json +1 -1
|
@@ -1 +1,5 @@
|
|
|
1
|
-
function
|
|
1
|
+
export function applyForceTopLevelAsyncOverride(params, depth, forceTopLevelAsync) {
|
|
2
|
+
if (!(depth === 0 && forceTopLevelAsync))
|
|
3
|
+
return params;
|
|
4
|
+
return { ...params, async: true, clarify: false };
|
|
5
|
+
}
|
|
@@ -1,11 +1,206 @@
|
|
|
1
|
-
import*as d from"node:fs";import*as C from"node:path";import*as _ from"node:fs";import*as c from"node:path";var v=new Map;function f$($){return $ instanceof Error?$.message:String($)}function z$($){return typeof $==="object"&&$!==null&&"code"in $&&$.code==="ENOENT"}function F$($){let j=c.join($,"status.json"),f;try{f=_.statSync(j)}catch(X){if(z$(X))return null;throw Error(`Failed to inspect async status file '${j}': ${f$(X)}`,{cause:X instanceof Error?X:void 0})}let J=v.get(j);if(J&&J.mtime===f.mtimeMs)return J.status;let Q;try{Q=_.readFileSync(j,"utf-8")}catch(X){if(z$(X))return null;throw Error(`Failed to read async status file '${j}': ${f$(X)}`,{cause:X instanceof Error?X:void 0})}let Z;try{Z=JSON.parse(Q)}catch(X){throw Error(`Failed to parse async status file '${j}': ${f$(X)}`,{cause:X instanceof Error?X:void 0})}if(v.set(j,{mtime:f.mtimeMs,status:Z}),v.size>50){let X=v.keys().next().value;if(X)v.delete(X)}return Z}import*as D from"node:os";import*as P from"node:path";var A$="subagent:async-complete",T$="subagent:control-event",_$="subagent:control-intercom",C$="subagent:result-intercom";function o($){return $.trim().replace(/[^A-Za-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"unknown"}function $0($){let j=$?.env??process.env,f=$&&Object.hasOwn($,"getuid")?$.getuid:process.getuid?.bind(process);if(typeof f==="function")return`uid-${f()}`;for(let X of["USERNAME","USER","LOGNAME"]){let B=j[X];if(B)return`user-${o(B)}`}let J=$&&Object.hasOwn($,"userInfo")?$.userInfo:D.userInfo;try{let X=J?.().username;if(X)return`user-${o(X)}`}catch{}let Q=j.USERPROFILE??j.HOME;if(Q)return`home-${o(Q)}`;let Z=$&&Object.hasOwn($,"homedir")?$.homedir:D.homedir;try{let X=Z?.();if(X)return`home-${o(X)}`}catch{}return"shared"}var x=P.join(D.tmpdir(),`dm-subagents-${$0()}`),N=P.join(x,"async-subagent-results"),u=P.join(x,"async-subagent-runs"),j0=P.join(x,"chain-runs"),Bj=P.join(x,"artifacts");function w($){if($<1000)return`${$}ms`;if($<60000)return`${($/1000).toFixed(1)}s`;return`${Math.floor($/60000)}m${Math.floor($%60000/1000)}s`}import{randomUUID as G0}from"node:crypto";import*as A from"node:fs";import*as L from"node:path";import*as S$ from"node:path";var f0=128,J0=4;function J$($){return typeof $==="string"&&$.length>0&&$.length<=f0&&!S$.isAbsolute($)&&!$.includes("/")&&!$.includes("\\")&&!$.includes("..")}function b$($){return typeof $==="number"&&Number.isFinite($)?$:void 0}function E$($,j){return typeof $==="string"&&$.length>0?$.slice(0,j):void 0}function y$($){if(!Array.isArray($))return[];return $.map((j)=>{if(!j||typeof j!=="object")return;let f=j;if(!J$(f.runId))return;return{runId:f.runId,...b$(f.stepIndex)!==void 0?{stepIndex:b$(f.stepIndex)}:{},...E$(f.agent,128)?{agent:E$(f.agent,128)}:{}}}).filter((j)=>Boolean(j)).slice(0,J0)}import*as E from"node:path";import{fileURLToPath as x$}from"node:url";import*as y from"node:os";import*as b from"node:path";var Sj=b.join(y.homedir(),".config","mcp","mcp.json"),yj={cursor:[b.join(y.homedir(),".cursor","mcp.json")],"claude-code":[b.join(y.homedir(),".claude","mcp.json"),b.join(y.homedir(),".claude.json"),b.join(y.homedir(),".claude","claude_desktop_config.json")],"claude-desktop":[b.join(y.homedir(),"Library","Application Support","Claude","claude_desktop_config.json")],codex:[b.join(y.homedir(),".codex","config.json")],windsurf:[b.join(y.homedir(),".windsurf","mcp.json")],vscode:[".vscode/mcp.json"]};import{Compile as Nj}from"typebox/compile";function I$($,j){let f=x$($),J=E.extname(f),Q=[".js",".mjs",".cjs",".ts",".mts",".cts"].includes(J)?J:".ts";return E.join(E.dirname(f),`${j}${Q}`)}function N$($){return E.basename(x$($)).startsWith("dm-args.")}function Q0($=import.meta.url){let j=N$($)?"subagent-prompt-runtime":E.join("..","runs","shared","subagent-prompt-runtime");return I$($,j)}function q0($=import.meta.url){let j=N$($)?E.join("..","..","extension","fanout-child"):"fanout-child";return I$($,j)}var pj=Q0(),lj=q0();import*as X0 from"node:fs";import*as R from"node:path";var B0=[10,25,50,100,200,500,1000,2000,4000],K0=new Set(["EACCES","EBUSY","EPERM"]),R$=typeof SharedArrayBuffer<"u"?new SharedArrayBuffer(4):void 0,D$=R$?new Int32Array(R$):void 0;function Y0($){if($<=0)return;if(D$)try{Atomics.wait(D$,0,0,$);return}catch{}let j=Date.now()+$;while(Date.now()<j);}function H0($){let j=$?.code;return typeof j==="string"&&K0.has(j)}function W0($,j,f,J,Q){for(let Z=0;;Z++)try{$.renameSync(j,f);return}catch(X){let B=J[Z];if(B===void 0||!H0(X))throw X;Q(B)}}function O0($={}){let j=$.fs??X0,f=$.now??Date.now,J=$.pid??process.pid,Q=$.random??Math.random,X=$.retryRenameErrors??process.platform==="win32"?$.retryDelaysMs??B0:[],B=$.wait??Y0;return(K,H)=>{j.mkdirSync(R.dirname(K),{recursive:!0});let V=R.join(R.dirname(K),`.${R.basename(K)}.${J}.${f()}.${Q().toString(36).slice(2)}.tmp`);try{j.writeFileSync(V,JSON.stringify(H,null,2),"utf-8"),W0(j,V,K,X,B)}finally{j.rmSync(V,{force:!0})}}}var k=O0();var l=L.join(x,"nested-subagent-events"),V0="route.json",L0="registry.json",B$=65536,Z$=12,h=16,Q$=3;function r($){return J$($)}function U0($,j){if(!r(j))throw Error(`${$} must be a non-empty safe id token.`)}function P$($,j){U0($,j)}function q$($,j){let f=L.resolve($),J=L.resolve(j);return J===f||J.startsWith(`${f}${L.sep}`)}function k$($){return L.dirname(L.resolve($.eventSink))}function a($){if(P$("rootRunId",$.rootRunId),P$("capabilityToken",$.capabilityToken),!q$(l,$.eventSink))throw Error("Nested event sink is outside the subagent nested event root.");if(!q$(l,$.controlInbox))throw Error("Nested control inbox is outside the subagent nested event root.");if(k$($)!==L.dirname(L.resolve($.controlInbox)))throw Error("Nested event sink and control inbox must share one route root.")}function g$($,j){if(!j.asyncDir)return;let f=L.resolve(j.asyncDir),J=L.resolve(x,"nested-subagent-runs",$,j.id),Q=L.relative(J,f);return f===J||!Q.startsWith("..")&&!L.isAbsolute(Q)?f:void 0}function Y($){return typeof $==="number"&&Number.isFinite($)?$:void 0}function O($,j=512){return typeof $==="string"&&$.length>0?$.slice(0,j):void 0}function M0($){if(!$||typeof $!=="object")return;let j=$,f=Y(j.input),J=Y(j.output),Q=Y(j.total);return f!==void 0&&J!==void 0&&Q!==void 0?{input:f,output:J,total:Q}:void 0}function z0($){if(!$||typeof $!=="object")return;let j=$,f=Y(j.inputTokens),J=Y(j.outputTokens),Q=Y(j.costUsd);return f!==void 0&&J!==void 0&&Q!==void 0?{inputTokens:f,outputTokens:J,costUsd:Q}:void 0}function i($){if(!$||typeof $!=="object")return;let j=$,f=Y(j.maxTurns),J=Y(j.graceTurns),Q=Y(j.turnCount),Z=j.outcome==="within-budget"||j.outcome==="wrap-up-requested"||j.outcome==="exceeded"?j.outcome:void 0;if(f===void 0||J===void 0||Q===void 0||!Z)return;return{maxTurns:f,graceTurns:J,turnCount:Q,outcome:Z,...Y(j.wrapUpRequestedAtTurn)!==void 0?{wrapUpRequestedAtTurn:Y(j.wrapUpRequestedAtTurn)}:{},...Y(j.exceededAtTurn)!==void 0?{exceededAtTurn:Y(j.exceededAtTurn)}:{}}}function F0($,j){return $==="queued"||$==="running"||$==="complete"||$==="failed"||$==="paused"?$:j}function A0($,j){if(!$||typeof $!=="object")return;let f=$,J=O(f.agent,128);if(!J)return;let Q=f.status==="pending"||f.status==="running"||f.status==="complete"||f.status==="completed"||f.status==="failed"||f.status==="paused"?f.status:"pending";return{agent:J,status:Q,...O(f.sessionFile,2048)?{sessionFile:O(f.sessionFile,2048)}:{},...f.activityState==="active_long_running"||f.activityState==="needs_attention"?{activityState:f.activityState}:{},...Y(f.lastActivityAt)!==void 0?{lastActivityAt:Y(f.lastActivityAt)}:{},...O(f.currentTool,128)?{currentTool:O(f.currentTool,128)}:{},...Y(f.currentToolStartedAt)!==void 0?{currentToolStartedAt:Y(f.currentToolStartedAt)}:{},...O(f.currentPath,2048)?{currentPath:O(f.currentPath,2048)}:{},...Y(f.turnCount)!==void 0?{turnCount:Y(f.turnCount)}:{},...Y(f.toolCount)!==void 0?{toolCount:Y(f.toolCount)}:{},...Y(f.startedAt)!==void 0?{startedAt:Y(f.startedAt)}:{},...Y(f.endedAt)!==void 0?{endedAt:Y(f.endedAt)}:{},...O(f.error,1024)?{error:O(f.error,1024)}:{},...f.timedOut===!0?{timedOut:!0}:{},...i(f.turnBudget)?{turnBudget:i(f.turnBudget)}:{},...f.turnBudgetExceeded===!0?{turnBudgetExceeded:!0}:{},...f.wrapUpRequested===!0?{wrapUpRequested:!0}:{},...j<Q$&&Array.isArray(f.children)?{children:f.children.map((Z)=>s(Z,j+1)).filter((Z)=>Boolean(Z)).slice(0,h)}:{}}}function s($,j=0){if(!$||typeof $!=="object")return;let f=$;if(!r(f.id)||!r(f.parentRunId))return;let J=y$(f.path),Q=Array.isArray(f.steps)?f.steps.map((B)=>A0(B,j+1)).filter((B)=>Boolean(B)).slice(0,Z$):void 0,Z=M0(f.totalTokens),X=z0(f.totalCost);return{id:f.id,parentRunId:f.parentRunId,...Y(f.parentStepIndex)!==void 0?{parentStepIndex:Y(f.parentStepIndex)}:{},...O(f.parentAgent,128)?{parentAgent:O(f.parentAgent,128)}:{},depth:Math.min(Math.max(0,Y(f.depth)??0),Q$),path:J,state:F0(f.state,"running"),...O(f.asyncDir,2048)?{asyncDir:O(f.asyncDir,2048)}:{},...Y(f.pid)!==void 0&&Y(f.pid)>0&&Number.isInteger(Y(f.pid))?{pid:Y(f.pid)}:{},...O(f.sessionId,256)?{sessionId:O(f.sessionId,256)}:{},...O(f.sessionFile,2048)?{sessionFile:O(f.sessionFile,2048)}:{},...O(f.intercomTarget,256)?{intercomTarget:O(f.intercomTarget,256)}:{},...O(f.ownerIntercomTarget,256)?{ownerIntercomTarget:O(f.ownerIntercomTarget,256)}:{},...O(f.leafIntercomTarget,256)?{leafIntercomTarget:O(f.leafIntercomTarget,256)}:{},...f.ownerState==="live"||f.ownerState==="gone"||f.ownerState==="unknown"?{ownerState:f.ownerState}:{},...O(f.controlInbox,2048)?{controlInbox:O(f.controlInbox,2048)}:{},...O(f.capabilityToken,128)?{capabilityToken:O(f.capabilityToken,128)}:{},...f.mode==="single"||f.mode==="parallel"||f.mode==="chain"?{mode:f.mode}:{},...O(f.agent,128)?{agent:O(f.agent,128)}:{},...Array.isArray(f.agents)?{agents:f.agents.map((B)=>O(B,128)).filter((B)=>Boolean(B)).slice(0,Z$)}:{},...Y(f.currentStep)!==void 0?{currentStep:Y(f.currentStep)}:{},...Y(f.chainStepCount)!==void 0?{chainStepCount:Y(f.chainStepCount)}:{},...f.activityState==="active_long_running"||f.activityState==="needs_attention"?{activityState:f.activityState}:{},...Y(f.lastActivityAt)!==void 0?{lastActivityAt:Y(f.lastActivityAt)}:{},...O(f.currentTool,128)?{currentTool:O(f.currentTool,128)}:{},...Y(f.currentToolStartedAt)!==void 0?{currentToolStartedAt:Y(f.currentToolStartedAt)}:{},...O(f.currentPath,2048)?{currentPath:O(f.currentPath,2048)}:{},...Y(f.turnCount)!==void 0?{turnCount:Y(f.turnCount)}:{},...Y(f.toolCount)!==void 0?{toolCount:Y(f.toolCount)}:{},...Z?{totalTokens:Z}:{},...X?{totalCost:X}:{},...Y(f.startedAt)!==void 0?{startedAt:Y(f.startedAt)}:{},...Y(f.endedAt)!==void 0?{endedAt:Y(f.endedAt)}:{},...Y(f.lastUpdate)!==void 0?{lastUpdate:Y(f.lastUpdate)}:{},...Y(f.timeoutMs)!==void 0?{timeoutMs:Y(f.timeoutMs)}:{},...Y(f.deadlineAt)!==void 0?{deadlineAt:Y(f.deadlineAt)}:{},...f.timedOut===!0?{timedOut:!0}:{},...i(f.turnBudget)?{turnBudget:i(f.turnBudget)}:{},...f.turnBudgetExceeded===!0?{turnBudgetExceeded:!0}:{},...f.wrapUpRequested===!0?{wrapUpRequested:!0}:{},...O(f.error,1024)?{error:O(f.error,1024)}:{},...Q&&Q.length>0?{steps:Q}:{},...j<Q$&&Array.isArray(f.children)?{children:f.children.map((B)=>s(B,j+1)).filter((B)=>Boolean(B)).slice(0,h)}:{}}}function X$($,j){if(Buffer.byteLength($,"utf-8")>B$)return;let f;try{f=JSON.parse($)}catch{return}if(!f||typeof f!=="object")return;let J=f;if(J.type!=="subagent.nested.started"&&J.type!=="subagent.nested.updated"&&J.type!=="subagent.nested.completed")return;if(J.rootRunId!==j.rootRunId||J.capabilityToken!==j.capabilityToken)return;if(!r(J.parentRunId))return;let Q=Y(J.ts);if(Q===void 0)return;let Z=s(J.child);if(!Z||Z.id===j.rootRunId)return;let X={...Z,controlInbox:j.controlInbox,capabilityToken:j.capabilityToken,ownerState:Z.ownerState??"unknown"};return{type:J.type,ts:Q,rootRunId:j.rootRunId,parentRunId:J.parentRunId,...Y(J.parentStepIndex)!==void 0?{parentStepIndex:Y(J.parentStepIndex)}:{},capabilityToken:j.capabilityToken,child:X}}function T0($,j){if(!$.includes(`
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
${B}`:X,V=(($.steps?.length)?$.steps:[{agent:"subagent",status:"running"}]).map((W)=>W.status==="running"||W.status==="pending"?{...W,status:"failed",activityState:void 0,endedAt:W.endedAt??f,durationMs:W.startedAt!==void 0&&W.durationMs===void 0?Math.max(0,f-W.startedAt):W.durationMs,exitCode:W.exitCode??1,error:W.error??K}:W),q={...$,state:"failed",activityState:void 0,lastUpdate:f,endedAt:f,steps:V},z=V[$.currentStep??0]?.agent??V[0]?.agent??"subagent";return{status:q,message:K,result:{id:Q,agent:z,mode:$.mode,success:!1,state:"failed",summary:K,results:V.map((W)=>({agent:W.agent,output:W.status==="complete"||W.status==="completed"?"":K,error:W.status==="complete"||W.status==="completed"?void 0:W.error??K,success:W.status==="complete"||W.status==="completed",model:W.model,attemptedModels:W.attemptedModels,modelAttempts:W.modelAttempts,sessionFile:W.sessionFile})),exitCode:1,timestamp:f,durationMs:Math.max(0,f-$.startedAt),asyncDir:j,sessionId:$.sessionId,sessionFile:$.sessionFile}}}function n$($,j,f,J,Q){let Z=v0(j,$,J,Q);return k(f,Z.result),k(T.join($,"status.json"),Z.status),R0(T.join($,"events.jsonl"),{type:"subagent.run.repaired_stale",ts:J,runId:Z.status.runId,pid:j.pid,resultPath:f,message:Z.message}),{status:Z.status,repaired:!0,resultPath:f,message:Z.message}}function o$($){return $==="complete"||$==="failed"||$==="paused"}function*Y$($){for(let j of $??[])yield j,yield*Y$(j.children),yield*Y$(j.steps?.flatMap((f)=>f.children??[]))}function p$($,j={}){let f=e($);for(let J of Y$(f.children)){if(J.state!=="running"&&J.state!=="queued")continue;let Q=g$($.rootRunId,J);if(!Q)continue;let Z=H$(Q,{...j,resultsDir:T.join(j.resultsDir??N,"nested",$.rootRunId)}),X=Z.status;if(!X)continue;if(!Z.repaired&&!o$(X.state))continue;let B=j.now?.()??Date.now();h$($,{type:o$(X.state)?"subagent.nested.completed":"subagent.nested.updated",ts:B,parentRunId:J.parentRunId,parentStepIndex:J.parentStepIndex,child:d$(X,Q,{id:J.id,parentRunId:J.parentRunId,parentStepIndex:J.parentStepIndex,depth:J.depth,path:J.path,mode:J.mode,ts:B})})}}function c0($,j=process.kill){try{return j($,0),"alive"}catch(f){let J=typeof f==="object"&&f!==null&&"code"in f?f.code:void 0;if(J==="ESRCH")return"dead";if(J==="EPERM")return"unknown";return"unknown"}}function H$($,j={}){let f=j.now?.()??Date.now(),J=D0($),Q=!J&&j.startedRun?g0($,j.startedRun,f):void 0,Z=J??Q;if(!Z)return{status:null,repaired:!1};let X=Z.runId||T.basename($),B=T.join(j.resultsDir??N,`${X}.json`);if(M.existsSync(B)){let H=Z.state==="running"||Z.state==="queued"?k0(Z,B,f):void 0;if(H)return k(T.join($,"status.json"),H),{status:H,repaired:!0,resultPath:B,message:"Existing async result file was used to repair stale running status."};return{status:Z,repaired:!1,resultPath:B}}if(Z.state!=="running"||typeof Z.pid!=="number")return{status:J??null,repaired:!1,resultPath:B};if(!J){let H=j.startedRun?.startedAt??Z.startedAt;if(f-H<(j.missingStatusGraceMs??1000))return{status:null,repaired:!1,resultPath:B}}if(c0(Z.pid,j.kill)!=="dead"){let H=j.staleAlivePidMs??86400000,V=Z.lastUpdate??Z.startedAt;if(f-V<=H)return{status:J??null,repaired:!1,resultPath:B};let q=`Async runner process ${Z.pid} still has a live PID, but status has not updated for ${f-V}ms. Marked run failed by stale-run reconciliation because PID ownership cannot be verified.`;return n$($,Z,B,f,q)}return n$($,Z,B,f)}function m($){return $ instanceof Error?$.message:String($)}function W$($){return typeof $==="object"&&$!==null&&"code"in $&&$.code==="ENOENT"}function h0($,j){let f=C.join($,j);try{return d.statSync(f).isDirectory()}catch(J){if(W$(J))return!1;throw Error(`Failed to inspect async run path '${f}': ${m(J)}`,{cause:J instanceof Error?J:void 0})}}function m0($){if(!$)return;try{return d.statSync($).mtimeMs}catch(j){if(W$(j))return;throw Error(`Failed to inspect async output file '${$}': ${m(j)}`,{cause:j instanceof Error?j:void 0})}}function d0($,j){if(j.state!=="running")return{activityState:j.activityState,lastActivityAt:j.lastActivityAt};let f=j.outputFile?C.isAbsolute(j.outputFile)?j.outputFile:C.join($,j.outputFile):void 0,J=typeof j.currentStep==="number"?j.steps?.[j.currentStep]:void 0;return{activityState:j.activityState,lastActivityAt:j.lastActivityAt??m0(f)??J?.lastActivityAt??J?.startedAt??j.startedAt}}function n0($,j,f=[],J){if(j.sessionId!==void 0&&typeof j.sessionId!=="string")throw Error(`Invalid async status '${C.join($,"status.json")}': sessionId must be a string.`);let{activityState:Q,lastActivityAt:Z}=d0($,j),X=j.steps??[],B=j.chainStepCount??X.length,K=t(j.parallelGroups,X.length,B),H=[];if(f.length===0&&J)try{H=e(J)?.children??[]}catch(q){f.push(`Nested status unavailable: ${m(q)}`)}let V=X.map((q,z)=>{let{activityState:W,lastActivityAt:U}=q;return{index:z,agent:q.agent,...q.label?{label:q.label}:{},...q.phase?{phase:q.phase}:{},...q.outputName?{outputName:q.outputName}:{},...q.structured?{structured:q.structured}:{},status:q.status,...W?{activityState:W}:{},...U?{lastActivityAt:U}:{},...q.currentTool?{currentTool:q.currentTool}:{},...q.currentToolArgs?{currentToolArgs:q.currentToolArgs}:{},...q.currentToolStartedAt?{currentToolStartedAt:q.currentToolStartedAt}:{},...q.currentPath?{currentPath:q.currentPath}:{},...q.recentTools?{recentTools:q.recentTools.map((S)=>({...S}))}:{},...q.recentOutput?{recentOutput:[...q.recentOutput]}:{},...q.turnCount!==void 0?{turnCount:q.turnCount}:{},...q.toolCount!==void 0?{toolCount:q.toolCount}:{},...q.steerCount!==void 0?{steerCount:q.steerCount}:{},...q.lastSteerAt!==void 0?{lastSteerAt:q.lastSteerAt}:{},...q.durationMs!==void 0?{durationMs:q.durationMs}:{},...q.tokens?{tokens:q.tokens}:{},...q.totalCost?{totalCost:q.totalCost}:{},...q.skills?{skills:q.skills}:{},...q.model?{model:q.model}:{},...q.thinking?{thinking:q.thinking}:{},...q.attemptedModels?{attemptedModels:q.attemptedModels}:{},...q.error?{error:q.error}:{},...q.timedOut!==void 0?{timedOut:q.timedOut}:{},...q.turnBudget?{turnBudget:q.turnBudget}:{},...q.turnBudgetExceeded!==void 0?{turnBudgetExceeded:q.turnBudgetExceeded}:{},...q.wrapUpRequested!==void 0?{wrapUpRequested:q.wrapUpRequested}:{},...q.children?.length?{children:q.children}:{}}});return m$(j.runId||C.basename($),V,H),{id:j.runId||C.basename($),asyncDir:$,...j.sessionId?{sessionId:j.sessionId}:{},state:j.state,...j.error?{error:j.error}:{},activityState:Q,lastActivityAt:Z,currentTool:j.currentTool,currentToolStartedAt:j.currentToolStartedAt,currentPath:j.currentPath,turnCount:j.turnCount,toolCount:j.toolCount,steerCount:j.steerCount,lastSteerAt:j.lastSteerAt,mode:j.mode,cwd:j.cwd,startedAt:j.startedAt,lastUpdate:j.lastUpdate,endedAt:j.endedAt,...j.timeoutMs!==void 0?{timeoutMs:j.timeoutMs}:{},...j.deadlineAt!==void 0?{deadlineAt:j.deadlineAt}:{},...j.timedOut!==void 0?{timedOut:j.timedOut}:{},...j.turnBudget?{turnBudget:j.turnBudget}:{},...j.turnBudgetExceeded!==void 0?{turnBudgetExceeded:j.turnBudgetExceeded}:{},...j.wrapUpRequested!==void 0?{wrapUpRequested:j.wrapUpRequested}:{},currentStep:j.currentStep,...j.chainStepCount!==void 0?{chainStepCount:j.chainStepCount}:{},...j.pendingAppends!==void 0?{pendingAppends:j.pendingAppends}:{},...K.length?{parallelGroups:K}:{},steps:V,...H.length?{nestedChildren:H}:{},...f.length?{nestedWarnings:f}:{},...j.sessionDir?{sessionDir:j.sessionDir}:{},...j.outputFile?{outputFile:j.outputFile}:{},...j.totalTokens?{totalTokens:j.totalTokens}:{},...j.totalCost?{totalCost:j.totalCost}:{},...j.sessionFile?{sessionFile:j.sessionFile}:{}}}function o0($){let j=(f)=>{switch(f){case"running":return 0;case"queued":return 1;case"failed":return 2;case"paused":return 2;case"complete":return 3}};return[...$].sort((f,J)=>{let Q=j(f.state)-j(J.state);if(Q!==0)return Q;let Z=f.lastUpdate??f.endedAt??f.startedAt;return(J.lastUpdate??J.endedAt??J.startedAt)-Z})}function O$($,j={}){let f;try{f=d.readdirSync($).filter((K)=>h0($,K))}catch(K){if(W$(K))return[];throw Error(`Failed to list async runs in '${$}': ${m(K)}`,{cause:K instanceof Error?K:void 0})}let J=j.states?new Set(j.states):void 0,Q=[],Z,X=(K)=>{if(!Z)Z=c$();return Z.get(K)};for(let K of f){let H=C.join($,K),q=(j.reconcile===!1?void 0:H$(H,{resultsDir:j.resultsDir,kill:j.kill,now:j.now}))?.status??F$(H);if(!q)continue;if(J&&!J.has(q.state))continue;if(j.sessionId&&q.sessionId!==j.sessionId)continue;let z=[],W;try{if(W=X(q.runId||C.basename(H)),W)p$(W,{resultsDir:j.resultsDir,kill:j.kill,now:j.now})}catch(S){z.push(`Nested status unavailable: ${m(S)}`)}let U=n0(H,q,z,W);Q.push(U)}let B=o0(Q);return j.limit!==void 0?B.slice(0,j.limit):B}var l$=["queued","running"],u0=1800000,p0=250,l0=1000,r0=[A$,T$,_$,C$];function i0($,j){return new Promise((f)=>{if(j?.aborted){f();return}let J=setTimeout(()=>{j?.removeEventListener("abort",Q),f()},$),Q=()=>{clearTimeout(J),f()};j?.addEventListener("abort",Q,{once:!0})})}function a0($,j,f){let J=f.sleep??i0,Q=f.events;if(!Q)return J($,j);return new Promise((Z)=>{let X=!1,B=[],K=new AbortController,H=()=>{if(X)return;X=!0,K.abort(),j?.removeEventListener("abort",H);for(let V of B)try{V()}catch{}Z()};if(j?.aborted){H();return}j?.addEventListener("abort",H,{once:!0});for(let V of r0)try{B.push(Q.on(V,H))}catch{}J($,K.signal).then(H)})}function r$($,j){return $.id===j||$.id.startsWith(j)}function $$($){return $.activityState==="needs_attention"}function G$($,j){let f=j.asyncDirRoot??u,J=j.resultsDir??N,Q=O$(f,{states:[...l$],sessionId:j.state.currentSessionId??void 0,resultsDir:J,kill:j.kill,now:j.now});return $.id?Q.filter((Z)=>r$(Z,$.id)):Q}function s0($,j,f){return G$($,j).filter((J)=>$$(J)&&f.has(J.id))}function e0($,j){let f=j.asyncDirRoot??u,J=j.resultsDir??N,Q=O$(f,{sessionId:j.state.currentSessionId??void 0,resultsDir:J,kill:j.kill,now:j.now});return $.id?Q.filter((Z)=>r$(Z,$.id)):Q}function t0($){if($.length===0)return"";let j={complete:0,failed:0,paused:0};for(let J of $)if(J.state in j)j[J.state]+=1;let f=[];if(j.complete)f.push(`${j.complete} complete`);if(j.failed)f.push(`${j.failed} failed`);if(j.paused)f.push(`${j.paused} paused`);return f.join(", ")}function I($,j=!1){return{content:[{type:"text",text:$}],...j?{isError:!0}:{},details:{mode:"management",results:[]}}}async function Pf($,j,f){let J=f.now??Date.now,Q=Math.max(p0,f.pollIntervalMs??l0),Z=$.timeoutMs!==void 0&&$.timeoutMs>0?$.timeoutMs:u0,X=J(),B=$.id?!0:$.all===!0,K;try{K=G$($,f)}catch(G){return I(G instanceof Error?G.message:String(G),!0)}if(K.length===0){let G=$.id?`No active run matched "${$.id}". Nothing to wait for.`:"No active async runs in this session. Nothing to wait for.";return I(G)}if($.id){let G=K.filter((F)=>F.id===$.id);if(G.length===1)K=G;else if(K.length>1)return I(`Ambiguous async run id prefix "${$.id}" matched ${K.length} active runs: ${K.map((F)=>F.id).join(", ")}. Pass a longer id.`,!0)}let H=$.id?{...$,id:K[0].id}:$,V=new Set(K.map((G)=>G.id)),q=V.size,z=K.filter((G)=>!$$(G)),W=(G,F)=>{if(F.length>0)return!0;if(B)return G.every((j$)=>!V.has(j$.id));return G.filter((j$)=>V.has(j$.id)).length<q},U=K.filter((G)=>$$(G));while(!W(z,U)){if(j?.aborted){let G=z.map((F)=>`${F.id} (${F.state})`).join(", ");return I(`Wait aborted after ${w(J()-X)}. Still active: ${G}.`,!0)}if(J()-X>=Z){let G=z.map((F)=>`${F.id} (${F.state})`).join(", ");return I(`Wait timed out after ${w(Z)} with ${z.length} run(s) still active: ${G}. The runs are detached and keep going; call wait again or inspect with subagent({ action: "status" }).`,!0)}await a0(Q,j,f);try{K=G$(H,f),z=K.filter((G)=>!$$(G)),U=s0(H,f,V)}catch(G){return I(G instanceof Error?G.message:String(G),!0)}}let S="",n=0;try{let F=e0(H,f).filter((g)=>!l$.includes(g.state)&&V.has(g.id));n=F.length,S=t0(F)}catch{}let V$=U.length>0?` ${U.length} run(s) need attention: ${U.map((G)=>G.id).join(", ")} — inspect with subagent({ action: "status" }) then nudge/resume/interrupt.`:"",L$=z.filter((G)=>V.has(G.id)).length,U$=w(J()-X),M$=S?` Outcome: ${S}.`:"";if(B){let G=$.id?`run "${$.id}"`:`${q} async run(s)`,F=U.length>0?"attention required":"done",g=U.length>0?"Relevant completion/control events have been observed; inspect status if the notification is not visible yet.":"Completion events have been observed; inspect status if the notification is not visible yet.";return I(`Waited ${U$} for ${G}; ${F}.${M$}${V$} ${g}`)}let i$=L$>0?` ${L$} run(s) still in flight — call wait again to catch the next one.`:U.length>0?" No other runs are waitable until attention is handled.":" No runs remain in flight.",a$=U.length>0&&n===0?`${U.length} of ${q} run(s) need attention`:`${n} of ${q} run(s) finished`,s$=n>0?" Completion events for the finished run(s) have been observed; inspect status if the notification is not visible yet.":" Relevant control events have been observed; inspect status if the notification is not visible yet.";return I(`Waited ${U$}; ${a$}.${M$}${V$}${i$}${s$}`)}export{Pf as waitForSubagents};
|
|
1
|
+
import { listAsyncRuns } from "./async-status.js";
|
|
2
|
+
import {
|
|
3
|
+
ASYNC_DIR,
|
|
4
|
+
RESULTS_DIR,
|
|
5
|
+
SUBAGENT_ASYNC_COMPLETE_EVENT,
|
|
6
|
+
SUBAGENT_CONTROL_EVENT,
|
|
7
|
+
SUBAGENT_CONTROL_INTERCOM_EVENT,
|
|
8
|
+
SUBAGENT_RESULT_INTERCOM_EVENT
|
|
9
|
+
} from "../../shared/types.js";
|
|
10
|
+
import { formatDuration } from "../../shared/formatters.js";
|
|
11
|
+
const ACTIVE_STATES = ["queued", "running"];
|
|
12
|
+
const DEFAULT_TIMEOUT_MS = 30 * 60 * 1000;
|
|
13
|
+
const MIN_POLL_INTERVAL_MS = 250;
|
|
14
|
+
const DEFAULT_POLL_INTERVAL_MS = 1000;
|
|
15
|
+
const WAKE_CHANNELS = [
|
|
16
|
+
SUBAGENT_ASYNC_COMPLETE_EVENT,
|
|
17
|
+
SUBAGENT_CONTROL_EVENT,
|
|
18
|
+
SUBAGENT_CONTROL_INTERCOM_EVENT,
|
|
19
|
+
SUBAGENT_RESULT_INTERCOM_EVENT
|
|
20
|
+
];
|
|
21
|
+
function defaultSleep(ms, signal) {
|
|
22
|
+
return new Promise((resolve) => {
|
|
23
|
+
if (signal?.aborted) {
|
|
24
|
+
resolve();
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const timer = setTimeout(() => {
|
|
28
|
+
signal?.removeEventListener("abort", onAbort);
|
|
29
|
+
resolve();
|
|
30
|
+
}, ms);
|
|
31
|
+
const onAbort = () => {
|
|
32
|
+
clearTimeout(timer);
|
|
33
|
+
resolve();
|
|
34
|
+
};
|
|
35
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
function waitForWake(ms, signal, deps) {
|
|
39
|
+
const sleep = deps.sleep ?? defaultSleep;
|
|
40
|
+
const events = deps.events;
|
|
41
|
+
if (!events)
|
|
42
|
+
return sleep(ms, signal);
|
|
43
|
+
return new Promise((resolve) => {
|
|
44
|
+
let settled = false;
|
|
45
|
+
const unsubs = [];
|
|
46
|
+
const wakeController = new AbortController;
|
|
47
|
+
const done = () => {
|
|
48
|
+
if (settled)
|
|
49
|
+
return;
|
|
50
|
+
settled = true;
|
|
51
|
+
wakeController.abort();
|
|
52
|
+
signal?.removeEventListener("abort", done);
|
|
53
|
+
for (const u of unsubs) {
|
|
54
|
+
try {
|
|
55
|
+
u();
|
|
56
|
+
} catch {}
|
|
57
|
+
}
|
|
58
|
+
resolve();
|
|
59
|
+
};
|
|
60
|
+
if (signal?.aborted) {
|
|
61
|
+
done();
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
signal?.addEventListener("abort", done, { once: true });
|
|
65
|
+
for (const channel of WAKE_CHANNELS) {
|
|
66
|
+
try {
|
|
67
|
+
unsubs.push(events.on(channel, done));
|
|
68
|
+
} catch {}
|
|
69
|
+
}
|
|
70
|
+
sleep(ms, wakeController.signal).then(done);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
function matchesId(run, id) {
|
|
74
|
+
return run.id === id || run.id.startsWith(id);
|
|
75
|
+
}
|
|
76
|
+
function needsAttention(run) {
|
|
77
|
+
return run.activityState === "needs_attention";
|
|
78
|
+
}
|
|
79
|
+
function activeRunsForSession(params, deps) {
|
|
80
|
+
const asyncDirRoot = deps.asyncDirRoot ?? ASYNC_DIR;
|
|
81
|
+
const resultsDir = deps.resultsDir ?? RESULTS_DIR;
|
|
82
|
+
const runs = listAsyncRuns(asyncDirRoot, {
|
|
83
|
+
states: [...ACTIVE_STATES],
|
|
84
|
+
sessionId: deps.state.currentSessionId ?? undefined,
|
|
85
|
+
resultsDir,
|
|
86
|
+
kill: deps.kill,
|
|
87
|
+
now: deps.now
|
|
88
|
+
});
|
|
89
|
+
return params.id ? runs.filter((run) => matchesId(run, params.id)) : runs;
|
|
90
|
+
}
|
|
91
|
+
function attentionRunsForSession(params, deps, initialIds) {
|
|
92
|
+
return activeRunsForSession(params, deps).filter((run) => needsAttention(run) && initialIds.has(run.id));
|
|
93
|
+
}
|
|
94
|
+
function allRunsForSession(params, deps) {
|
|
95
|
+
const asyncDirRoot = deps.asyncDirRoot ?? ASYNC_DIR;
|
|
96
|
+
const resultsDir = deps.resultsDir ?? RESULTS_DIR;
|
|
97
|
+
const runs = listAsyncRuns(asyncDirRoot, {
|
|
98
|
+
sessionId: deps.state.currentSessionId ?? undefined,
|
|
99
|
+
resultsDir,
|
|
100
|
+
kill: deps.kill,
|
|
101
|
+
now: deps.now
|
|
102
|
+
});
|
|
103
|
+
return params.id ? runs.filter((run) => matchesId(run, params.id)) : runs;
|
|
104
|
+
}
|
|
105
|
+
function summarizeTerminalRuns(runs) {
|
|
106
|
+
if (runs.length === 0)
|
|
107
|
+
return "";
|
|
108
|
+
const counts = { complete: 0, failed: 0, paused: 0 };
|
|
109
|
+
for (const run of runs) {
|
|
110
|
+
if (run.state in counts)
|
|
111
|
+
counts[run.state] += 1;
|
|
112
|
+
}
|
|
113
|
+
const parts = [];
|
|
114
|
+
if (counts.complete)
|
|
115
|
+
parts.push(`${counts.complete} complete`);
|
|
116
|
+
if (counts.failed)
|
|
117
|
+
parts.push(`${counts.failed} failed`);
|
|
118
|
+
if (counts.paused)
|
|
119
|
+
parts.push(`${counts.paused} paused`);
|
|
120
|
+
return parts.join(", ");
|
|
121
|
+
}
|
|
122
|
+
function result(text, isError = false) {
|
|
123
|
+
return {
|
|
124
|
+
content: [{ type: "text", text }],
|
|
125
|
+
...isError ? { isError: true } : {},
|
|
126
|
+
details: { mode: "management", results: [] }
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
export async function waitForSubagents(params, signal, deps) {
|
|
130
|
+
const now = deps.now ?? Date.now;
|
|
131
|
+
const pollIntervalMs = Math.max(MIN_POLL_INTERVAL_MS, deps.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS);
|
|
132
|
+
const timeoutMs = params.timeoutMs !== undefined && params.timeoutMs > 0 ? params.timeoutMs : DEFAULT_TIMEOUT_MS;
|
|
133
|
+
const startedAt = now();
|
|
134
|
+
const waitForAll = params.id ? true : params.all === true;
|
|
135
|
+
let active;
|
|
136
|
+
try {
|
|
137
|
+
active = activeRunsForSession(params, deps);
|
|
138
|
+
} catch (error) {
|
|
139
|
+
return result(error instanceof Error ? error.message : String(error), true);
|
|
140
|
+
}
|
|
141
|
+
if (active.length === 0) {
|
|
142
|
+
const finished = params.id ? `No active run matched "${params.id}". Nothing to wait for.` : "No active async runs in this session. Nothing to wait for.";
|
|
143
|
+
return result(finished);
|
|
144
|
+
}
|
|
145
|
+
if (params.id) {
|
|
146
|
+
const exact = active.filter((run) => run.id === params.id);
|
|
147
|
+
if (exact.length === 1)
|
|
148
|
+
active = exact;
|
|
149
|
+
else if (active.length > 1) {
|
|
150
|
+
return result(`Ambiguous async run id prefix "${params.id}" matched ${active.length} active runs: ${active.map((run) => run.id).join(", ")}. Pass a longer id.`, true);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
const waitParams = params.id ? { ...params, id: active[0].id } : params;
|
|
154
|
+
const initialIds = new Set(active.map((run) => run.id));
|
|
155
|
+
const initialCount = initialIds.size;
|
|
156
|
+
let pending = active.filter((run) => !needsAttention(run));
|
|
157
|
+
const done = (active, attention) => {
|
|
158
|
+
if (attention.length > 0)
|
|
159
|
+
return true;
|
|
160
|
+
if (waitForAll)
|
|
161
|
+
return active.every((run) => !initialIds.has(run.id));
|
|
162
|
+
const stillActiveInitial = active.filter((run) => initialIds.has(run.id));
|
|
163
|
+
return stillActiveInitial.length < initialCount;
|
|
164
|
+
};
|
|
165
|
+
let attention = active.filter((run) => needsAttention(run));
|
|
166
|
+
while (!done(pending, attention)) {
|
|
167
|
+
if (signal?.aborted) {
|
|
168
|
+
const stillActive = pending.map((run) => `${run.id} (${run.state})`).join(", ");
|
|
169
|
+
return result(`Wait aborted after ${formatDuration(now() - startedAt)}. Still active: ${stillActive}.`, true);
|
|
170
|
+
}
|
|
171
|
+
if (now() - startedAt >= timeoutMs) {
|
|
172
|
+
const stillActive = pending.map((run) => `${run.id} (${run.state})`).join(", ");
|
|
173
|
+
return result(`Wait timed out after ${formatDuration(timeoutMs)} with ${pending.length} run(s) still active: ${stillActive}. ` + `The runs are detached and keep going; call wait again or inspect with subagent({ action: "status" }).`, true);
|
|
174
|
+
}
|
|
175
|
+
await waitForWake(pollIntervalMs, signal, deps);
|
|
176
|
+
try {
|
|
177
|
+
active = activeRunsForSession(waitParams, deps);
|
|
178
|
+
pending = active.filter((run) => !needsAttention(run));
|
|
179
|
+
attention = attentionRunsForSession(waitParams, deps, initialIds);
|
|
180
|
+
} catch (error) {
|
|
181
|
+
return result(error instanceof Error ? error.message : String(error), true);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
let terminalSummary = "";
|
|
185
|
+
let finishedCount = 0;
|
|
186
|
+
try {
|
|
187
|
+
const allNow = allRunsForSession(waitParams, deps);
|
|
188
|
+
const terminal = allNow.filter((run) => !ACTIVE_STATES.includes(run.state) && initialIds.has(run.id));
|
|
189
|
+
finishedCount = terminal.length;
|
|
190
|
+
terminalSummary = summarizeTerminalRuns(terminal);
|
|
191
|
+
} catch {}
|
|
192
|
+
const attentionNote = attention.length > 0 ? ` ${attention.length} run(s) need attention: ${attention.map((r) => r.id).join(", ")} — inspect with subagent({ action: "status" }) then nudge/resume/interrupt.` : "";
|
|
193
|
+
const stillRunning = pending.filter((run) => initialIds.has(run.id)).length;
|
|
194
|
+
const elapsed = formatDuration(now() - startedAt);
|
|
195
|
+
const outcome = terminalSummary ? ` Outcome: ${terminalSummary}.` : "";
|
|
196
|
+
if (waitForAll) {
|
|
197
|
+
const scope = params.id ? `run "${params.id}"` : `${initialCount} async run(s)`;
|
|
198
|
+
const status = attention.length > 0 ? "attention required" : "done";
|
|
199
|
+
const notificationText = attention.length > 0 ? "Relevant completion/control events have been observed; inspect status if the notification is not visible yet." : "Completion events have been observed; inspect status if the notification is not visible yet.";
|
|
200
|
+
return result(`Waited ${elapsed} for ${scope}; ${status}.${outcome}${attentionNote} ${notificationText}`);
|
|
201
|
+
}
|
|
202
|
+
const remainder = stillRunning > 0 ? ` ${stillRunning} run(s) still in flight — call wait again to catch the next one.` : attention.length > 0 ? " No other runs are waitable until attention is handled." : " No runs remain in flight.";
|
|
203
|
+
const progress = attention.length > 0 && finishedCount === 0 ? `${attention.length} of ${initialCount} run(s) need attention` : `${finishedCount} of ${initialCount} run(s) finished`;
|
|
204
|
+
const notificationText = finishedCount > 0 ? " Completion events for the finished run(s) have been observed; inspect status if the notification is not visible yet." : " Relevant control events have been observed; inspect status if the notification is not visible yet.";
|
|
205
|
+
return result(`Waited ${elapsed}; ${progress}.${outcome}${attentionNote}${remainder}${notificationText}`);
|
|
206
|
+
}
|