@bastani/atomic 0.9.13-alpha.2 → 0.9.13-alpha.3
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/CHANGELOG.md +14 -0
- package/README.md +1 -1
- package/dist/builtin/i-have-adhd/package.json +1 -1
- package/dist/builtin/intercom/CHANGELOG.md +14 -0
- package/dist/builtin/intercom/README.md +12 -12
- package/dist/builtin/intercom/incoming-message-delivery.ts +1 -1
- package/dist/builtin/intercom/index.ts +1 -1
- package/dist/builtin/intercom/intercom-tool.ts +1 -1
- package/dist/builtin/intercom/intercom-utils.ts +3 -6
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/intercom/result-renderers.ts +1 -1
- package/dist/builtin/intercom/session-target.ts +1 -15
- package/dist/builtin/intercom/skills/intercom/SKILL.md +6 -6
- package/dist/builtin/intercom/terminal-ordering-barrier.ts +2 -2
- package/dist/builtin/intercom/ui/inline-message.ts +7 -5
- package/dist/builtin/intercom/ui/session-list.ts +23 -10
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/CHANGELOG.md +19 -0
- package/dist/builtin/subagents/README.md +29 -73
- package/dist/builtin/subagents/package.json +2 -2
- package/dist/builtin/subagents/prompts/parallel-cleanup.md +1 -1
- package/dist/builtin/subagents/prompts/parallel-review.md +1 -1
- package/dist/builtin/subagents/prompts/review-loop.md +2 -2
- package/dist/builtin/subagents/skills/subagent/SKILL.md +23 -59
- package/dist/builtin/subagents/skills/tmux/SKILL.md +1 -1
- package/dist/builtin/subagents/src/extension/control-notices.ts +2 -3
- package/dist/builtin/subagents/src/extension/doctor.ts +2 -14
- package/dist/builtin/subagents/src/extension/fanout-child.ts +1 -17
- package/dist/builtin/subagents/src/extension/index.ts +9 -70
- package/dist/builtin/subagents/src/extension/notification-content.ts +1 -1
- package/dist/builtin/subagents/src/extension/prompt-guidance.ts +2 -2
- package/dist/builtin/subagents/src/extension/schemas.ts +2 -8
- package/dist/builtin/subagents/src/extension/tool-description.ts +2 -3
- package/dist/builtin/subagents/src/intercom/intercom-bridge.ts +1 -1
- package/dist/builtin/subagents/src/intercom/result-intercom.ts +5 -46
- package/dist/builtin/subagents/src/runs/{background → foreground}/completion-notification.ts +2 -2
- package/dist/builtin/subagents/src/runs/foreground/inprocess-run-sync.ts +25 -88
- package/dist/builtin/subagents/src/runs/{background → foreground}/notify.ts +5 -5
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-context.ts +11 -28
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel-task.ts +3 -0
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel.ts +2 -0
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-runtime.ts +0 -5
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-single.ts +30 -20
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-status.ts +4 -4
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-types.ts +0 -13
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor.ts +104 -48
- package/dist/builtin/subagents/src/runs/inprocess/index.ts +1 -1
- package/dist/builtin/subagents/src/runs/inprocess/runner.ts +5 -5
- package/dist/builtin/subagents/src/runs/inprocess/runtime-support/nested-api.ts +0 -7
- package/dist/builtin/subagents/src/runs/inprocess/runtime-support/nested-core.ts +0 -10
- package/dist/builtin/subagents/src/runs/inprocess/runtime-support/nested-projection.ts +3 -108
- package/dist/builtin/subagents/src/runs/inprocess/runtime-support/nested-sanitize.ts +0 -4
- package/dist/builtin/subagents/src/runs/shared/subagent-control.ts +1 -1
- package/dist/builtin/subagents/src/shared/formatters.ts +3 -5
- package/dist/builtin/subagents/src/shared/model-resolution.ts +78 -0
- package/dist/builtin/subagents/src/shared/status-format.ts +4 -11
- package/dist/builtin/subagents/src/shared/types-config.ts +10 -9
- package/dist/builtin/subagents/src/shared/types-nested.ts +127 -0
- package/dist/builtin/subagents/src/shared/types-results.ts +2 -8
- package/dist/builtin/subagents/src/shared/types-runtime.ts +0 -9
- package/dist/builtin/subagents/src/shared/types.ts +1 -1
- package/dist/builtin/subagents/src/shared/utils.ts +1 -109
- package/dist/builtin/subagents/src/slash/slash-commands.ts +7 -17
- package/dist/builtin/subagents/src/tui/render-event-formatting.ts +2 -252
- package/dist/builtin/subagents/src/tui/render-layout.ts +4 -4
- package/dist/builtin/subagents/src/tui/render-result.ts +0 -9
- package/dist/builtin/subagents/src/tui/render-stable-output.ts +1 -34
- package/dist/builtin/subagents/src/tui/render.ts +0 -2
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +12 -0
- package/dist/builtin/workflows/README.md +3 -3
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/durable/backend.ts +11 -0
- package/dist/builtin/workflows/src/durable/completed-catalog-stage-groups.ts +63 -25
- package/dist/builtin/workflows/src/durable/completed-catalog.ts +166 -25
- package/dist/builtin/workflows/src/durable/dbos-backend.ts +42 -24
- package/dist/builtin/workflows/src/durable/dbos-envelope.ts +2 -1
- package/dist/builtin/workflows/src/durable/run-timing.ts +28 -7
- package/dist/builtin/workflows/src/durable/scoped-backend.ts +4 -0
- package/dist/builtin/workflows/src/durable/targeted-inspection.ts +110 -0
- package/dist/builtin/workflows/src/engine/run-durable-stage-session.ts +2 -2
- package/dist/builtin/workflows/src/engine/runtime.ts +19 -2
- package/dist/builtin/workflows/src/extension/extension-runtime-state.ts +3 -0
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +680 -152
- package/dist/builtin/workflows/src/extension/runtime-durable-resume.ts +6 -0
- package/dist/builtin/workflows/src/extension/ui-surface.ts +2 -0
- package/dist/builtin/workflows/src/extension/workflow-command-registration.ts +6 -1
- package/dist/builtin/workflows/src/extension/workflow-targets.ts +18 -10
- package/dist/builtin/workflows/src/extension/workflow-tool-inspection.ts +31 -16
- package/dist/builtin/workflows/src/extension/workflow-tool-send.ts +75 -3
- package/dist/builtin/workflows/src/extension/workflow-tool.ts +53 -6
- package/dist/builtin/workflows/src/runs/background/run-inspect.ts +5 -1
- package/dist/builtin/workflows/src/runs/foreground/executor-stage-call.ts +94 -60
- package/dist/builtin/workflows/src/runs/foreground/executor-stage-context.ts +1 -1
- package/dist/builtin/workflows/src/runs/foreground/executor-stage-control.ts +7 -7
- package/dist/builtin/workflows/src/runs/foreground/executor-stage-factory.ts +25 -4
- package/dist/builtin/workflows/src/runs/foreground/executor-stage-types.ts +4 -1
- package/dist/builtin/workflows/src/runs/foreground/executor-types.ts +2 -0
- package/dist/builtin/workflows/src/runs/foreground/stage-runner-controller.ts +142 -4
- package/dist/builtin/workflows/src/runs/foreground/stage-runner-types.ts +2 -0
- package/dist/builtin/workflows/src/runs/foreground/stage-session-heartbeat.ts +88 -0
- package/dist/builtin/workflows/src/tui/run-detail.ts +25 -12
- package/dist/builtin/workflows/src/tui/workflow-resume-selector.ts +1 -0
- package/dist/core/agent-session-events.d.ts.map +1 -1
- package/dist/core/agent-session-events.js +16 -5
- package/dist/core/agent-session-events.js.map +1 -1
- package/dist/core/agent-session-export.d.ts.map +1 -1
- package/dist/core/agent-session-export.js +2 -1
- package/dist/core/agent-session-export.js.map +1 -1
- package/dist/core/agent-session-methods.d.ts +8 -4
- package/dist/core/agent-session-methods.d.ts.map +1 -1
- package/dist/core/agent-session-methods.js.map +1 -1
- package/dist/core/agent-session-prompt.d.ts.map +1 -1
- package/dist/core/agent-session-prompt.js +5 -0
- package/dist/core/agent-session-prompt.js.map +1 -1
- package/dist/core/agent-session-summary.d.ts +21 -0
- package/dist/core/agent-session-summary.d.ts.map +1 -0
- package/dist/core/agent-session-summary.js +156 -0
- package/dist/core/agent-session-summary.js.map +1 -0
- package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
- package/dist/core/agent-session-tool-registry.js +0 -4
- package/dist/core/agent-session-tool-registry.js.map +1 -1
- package/dist/core/agent-session-transfer.d.ts.map +1 -1
- package/dist/core/agent-session-transfer.js +0 -2
- package/dist/core/agent-session-transfer.js.map +1 -1
- package/dist/core/agent-session-tree.d.ts.map +1 -1
- package/dist/core/agent-session-tree.js +6 -0
- package/dist/core/agent-session-tree.js.map +1 -1
- package/dist/core/agent-session.d.ts +7 -3
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +8 -5
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/atomic-guide-command.js +2 -2
- package/dist/core/atomic-guide-command.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +1 -0
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/index.d.ts +1 -0
- package/dist/core/compaction/index.d.ts.map +1 -1
- package/dist/core/compaction/index.js +1 -0
- package/dist/core/compaction/index.js.map +1 -1
- package/dist/core/compaction/session-summarization.d.ts +41 -0
- package/dist/core/compaction/session-summarization.d.ts.map +1 -0
- package/dist/core/compaction/session-summarization.js +97 -0
- package/dist/core/compaction/session-summarization.js.map +1 -0
- package/dist/core/extensions/ui-types.d.ts +2 -0
- package/dist/core/extensions/ui-types.d.ts.map +1 -1
- package/dist/core/extensions/ui-types.js.map +1 -1
- package/dist/core/session-manager-core.d.ts +3 -1
- package/dist/core/session-manager-core.d.ts.map +1 -1
- package/dist/core/session-manager-core.js +9 -1
- package/dist/core/session-manager-core.js.map +1 -1
- package/dist/core/session-manager-entries.d.ts +24 -1
- package/dist/core/session-manager-entries.d.ts.map +1 -1
- package/dist/core/session-manager-entries.js +48 -0
- package/dist/core/session-manager-entries.js.map +1 -1
- package/dist/core/session-manager-list.d.ts.map +1 -1
- package/dist/core/session-manager-list.js +10 -0
- package/dist/core/session-manager-list.js.map +1 -1
- package/dist/core/session-manager-types.d.ts +10 -1
- package/dist/core/session-manager-types.d.ts.map +1 -1
- package/dist/core/session-manager-types.js.map +1 -1
- package/dist/core/settings-manager-basic-accessors.d.ts +3 -0
- package/dist/core/settings-manager-basic-accessors.d.ts.map +1 -1
- package/dist/core/settings-manager-basic-accessors.js +5 -0
- package/dist/core/settings-manager-basic-accessors.js.map +1 -1
- package/dist/core/settings-manager.d.ts +1 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/settings-types.d.ts +4 -0
- package/dist/core/settings-types.d.ts.map +1 -1
- package/dist/core/settings-types.js.map +1 -1
- package/dist/core/slash-commands.js +2 -2
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/tools/bash.d.ts +0 -15
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +3 -81
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/fetch-url.d.ts +12 -0
- package/dist/core/tools/fetch-url.d.ts.map +1 -1
- package/dist/core/tools/fetch-url.js +76 -10
- package/dist/core/tools/fetch-url.js.map +1 -1
- package/dist/core/tools/index.js +4 -4
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/session-temp-dir.d.ts +2 -2
- package/dist/core/tools/session-temp-dir.d.ts.map +1 -1
- package/dist/core/tools/session-temp-dir.js +6 -7
- package/dist/core/tools/session-temp-dir.js.map +1 -1
- package/dist/core/usage-totals.js +1 -1
- package/dist/core/usage-totals.js.map +1 -1
- package/dist/modes/interactive/components/footer.js +1 -1
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/host-session-picker.d.ts.map +1 -1
- package/dist/modes/interactive/components/host-session-picker.js +1 -0
- package/dist/modes/interactive/components/host-session-picker.js.map +1 -1
- package/dist/modes/interactive/components/session-selector-list.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector-list.js +29 -4
- package/dist/modes/interactive/components/session-selector-list.js.map +1 -1
- package/dist/modes/interactive/components/session-selector-search.js +1 -1
- package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector-content.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector-content.js +6 -0
- package/dist/modes/interactive/components/tree-selector-content.js.map +1 -1
- package/dist/modes/interactive-engine/protocol.d.ts.map +1 -1
- package/dist/modes/interactive-engine/protocol.js +4 -1
- package/dist/modes/interactive-engine/protocol.js.map +1 -1
- package/docs/environment-variables.md +1 -1
- package/docs/intercom.md +20 -21
- package/docs/quickstart.md +5 -1
- package/docs/sdk.md +1 -1
- package/docs/session-format.md +15 -0
- package/docs/sessions.md +8 -0
- package/docs/settings.md +6 -0
- package/docs/subagents.md +19 -31
- package/docs/tools.md +3 -5
- package/docs/usage.md +1 -1
- package/docs/windows.md +1 -1
- package/docs/workflows.md +60 -32
- package/npm-shrinkwrap.json +29 -29
- package/package.json +2 -2
- package/dist/builtin/subagents/src/runs/background/async-job-tracker.ts +0 -331
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-async.ts +0 -161
- package/dist/builtin/subagents/src/runs/inprocess/background-single.ts +0 -195
- package/dist/builtin/subagents/src/runs/inprocess/background.ts +0 -90
- package/dist/builtin/subagents/src/shared/types-async.ts +0 -247
- package/dist/builtin/subagents/src/tui/render-widget-graph.ts +0 -217
- package/dist/builtin/subagents/src/tui/render-widget.ts +0 -366
- package/dist/core/async/format.d.ts +0 -3
- package/dist/core/async/format.d.ts.map +0 -1
- package/dist/core/async/format.js +0 -52
- package/dist/core/async/format.js.map +0 -1
- package/dist/core/async/job-manager.d.ts +0 -40
- package/dist/core/async/job-manager.d.ts.map +0 -1
- package/dist/core/async/job-manager.js +0 -293
- package/dist/core/async/job-manager.js.map +0 -1
- package/dist/core/async/session-manager.d.ts +0 -16
- package/dist/core/async/session-manager.d.ts.map +0 -1
- package/dist/core/async/session-manager.js +0 -34
- package/dist/core/async/session-manager.js.map +0 -1
- package/dist/core/async/types.d.ts +0 -23
- package/dist/core/async/types.d.ts.map +0 -1
- package/dist/core/async/types.js +0 -2
- package/dist/core/async/types.js.map +0 -1
- package/dist/core/tools/bash-async-execution.d.ts +0 -27
- package/dist/core/tools/bash-async-execution.d.ts.map +0 -1
- package/dist/core/tools/bash-async-execution.js +0 -81
- package/dist/core/tools/bash-async-execution.js.map +0 -1
- package/dist/core/tools/bash-async-jobs.d.ts +0 -30
- package/dist/core/tools/bash-async-jobs.d.ts.map +0 -1
- package/dist/core/tools/bash-async-jobs.js +0 -87
- package/dist/core/tools/bash-async-jobs.js.map +0 -1
- package/dist/core/tools/bash-async-output.d.ts +0 -13
- package/dist/core/tools/bash-async-output.d.ts.map +0 -1
- package/dist/core/tools/bash-async-output.js +0 -122
- package/dist/core/tools/bash-async-output.js.map +0 -1
|
@@ -1,23 +1,32 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
1
3
|
import type { ExtensionContext } from "@bastani/atomic";
|
|
2
4
|
import { handleManagementAction } from "../../agents/agent-management.ts";
|
|
3
5
|
import { resolveExecutionAgentScope } from "../../agents/agent-scope.ts";
|
|
4
6
|
import { clearPendingForegroundControlNotices } from "../../extension/control-notices.ts";
|
|
5
7
|
import { buildDoctorReport } from "../../extension/doctor.ts";
|
|
6
8
|
import {
|
|
9
|
+
INTERCOM_BRIDGE_MARKER,
|
|
7
10
|
resolveIntercomBridge,
|
|
8
11
|
resolveIntercomSessionTarget,
|
|
9
12
|
resolveSubagentIntercomTarget,
|
|
10
13
|
} from "../../intercom/intercom-bridge.ts";
|
|
11
14
|
import { requestSupervisorAuthorization } from "../../intercom/supervisor-authorization.ts";
|
|
12
15
|
import { getArtifactsDir } from "../../shared/artifacts.ts";
|
|
13
|
-
import { toModelInfo } from "../../shared/model-info.ts";
|
|
14
|
-
import {
|
|
16
|
+
import { collectKnownModelProviders, toModelInfo } from "../../shared/model-info.ts";
|
|
17
|
+
import { createCandidateModelResolver } from "../../shared/model-resolution.ts";
|
|
18
|
+
import {
|
|
19
|
+
injectSingleProgressInstruction,
|
|
20
|
+
resolveSingleProgress,
|
|
21
|
+
writeInitialProgressFile,
|
|
22
|
+
} from "../../shared/settings.ts";
|
|
15
23
|
import {
|
|
16
24
|
DEFAULT_ARTIFACT_CONFIG,
|
|
17
25
|
getCurrentSubagentDepth,
|
|
18
26
|
isWorkflowStageOrchestrationContext,
|
|
19
27
|
resolveChildMaxSubagentDepth,
|
|
20
28
|
resolveWorkflowStageMaxSubagentDepth,
|
|
29
|
+
type SingleResult,
|
|
21
30
|
SUBAGENT_ACTIONS,
|
|
22
31
|
type SubagentToolResult,
|
|
23
32
|
workflowSessionMetadataFromContext,
|
|
@@ -30,16 +39,17 @@ import {
|
|
|
30
39
|
import { inheritedIntercomGroup } from "../shared/intercom-group.js";
|
|
31
40
|
import { currentModelFullId } from "../shared/model-fallback.ts";
|
|
32
41
|
import { resolveControlConfig } from "../shared/subagent-control.ts";
|
|
33
|
-
import { runAsyncPath } from "./subagent-executor-async.ts";
|
|
34
42
|
import { checkDepthForExecution, prepareExecutionContext } from "./subagent-executor-context.ts";
|
|
35
43
|
import { toExecutionErrorResult, withForkContext } from "./subagent-executor-input.ts";
|
|
36
44
|
import { runParallelPath } from "./subagent-executor-parallel.ts";
|
|
37
45
|
import { resolveRequestedCwd } from "./subagent-executor-resume.ts";
|
|
38
46
|
import { resolveSubagentExecutorRuntimeDeps } from "./subagent-executor-runtime.ts";
|
|
39
|
-
import { runSinglePath } from "./subagent-executor-single.ts";
|
|
47
|
+
import { createForwardSingleUpdate, runSinglePath } from "./subagent-executor-single.ts";
|
|
40
48
|
import {
|
|
41
49
|
foregroundStatusResult,
|
|
42
50
|
getForegroundControl,
|
|
51
|
+
notifyDetachedForegroundChildExit,
|
|
52
|
+
replaceForegroundRunChild,
|
|
43
53
|
retainedForegroundStatusResult,
|
|
44
54
|
} from "./subagent-executor-status.ts";
|
|
45
55
|
import {
|
|
@@ -54,6 +64,7 @@ async function resumeRetainedForegroundChild(
|
|
|
54
64
|
message: string,
|
|
55
65
|
ctx: ExtensionContext,
|
|
56
66
|
deps: ResolvedExecutorDeps,
|
|
67
|
+
onUpdate: ((r: SubagentToolResult) => void) | undefined,
|
|
57
68
|
): Promise<SubagentToolResult | undefined> {
|
|
58
69
|
const requested = params.id ?? params.runId;
|
|
59
70
|
if (!requested) return undefined;
|
|
@@ -82,47 +93,93 @@ async function resumeRetainedForegroundChild(
|
|
|
82
93
|
? resolveSubagentIntercomTarget(run.runId, child.agent, child.index)
|
|
83
94
|
: undefined;
|
|
84
95
|
const supervisorAuthorization = await requestSupervisorAuthorization(deps.pi.events, supervisedTarget);
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
96
|
+
const artifactConfig = { ...DEFAULT_ARTIFACT_CONFIG, enabled: params.artifacts !== false };
|
|
97
|
+
const artifactsDir = getArtifactsDir(parentSessionFile);
|
|
98
|
+
const progressDir = resolveSingleProgress(agentConfig, params.progress, message)
|
|
99
|
+
? path.join(artifactsDir, "progress", run.runId)
|
|
100
|
+
: undefined;
|
|
101
|
+
if (progressDir) {
|
|
102
|
+
writeInitialProgressFile(progressDir);
|
|
103
|
+
message = injectSingleProgressInstruction(message, progressDir);
|
|
104
|
+
}
|
|
105
|
+
const cleanupProgress = (): void => {
|
|
106
|
+
if (!progressDir || artifactConfig.enabled) return;
|
|
107
|
+
try {
|
|
108
|
+
fs.rmSync(progressDir, { recursive: true, force: true });
|
|
109
|
+
} catch {
|
|
110
|
+
// Scratch cleanup must never replace the child run's result or original error.
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
const forwardSingleUpdate = createForwardSingleUpdate(
|
|
114
|
+
onUpdate,
|
|
115
|
+
getForegroundControl(deps.state, run.runId),
|
|
116
|
+
child.agent,
|
|
117
|
+
child.index,
|
|
118
|
+
);
|
|
119
|
+
let result: SingleResult;
|
|
120
|
+
try {
|
|
121
|
+
result = await deps.runtime.runSync(run.cwd, agents, child.agent, message, {
|
|
91
122
|
cwd: run.cwd,
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
123
|
+
signal: ctx.signal,
|
|
124
|
+
interruptSignal: ctx.signal,
|
|
125
|
+
allowIntercomDetach: agentConfig.systemPrompt?.includes(INTERCOM_BRIDGE_MARKER) === true,
|
|
126
|
+
intercomEvents: deps.pi.events,
|
|
127
|
+
runId: run.runId,
|
|
128
|
+
index: child.index,
|
|
129
|
+
sessionDir: child.sessionFile ? path.dirname(child.sessionFile) : undefined,
|
|
130
|
+
sessionFile: child.sessionFile,
|
|
131
|
+
share: params.share === true,
|
|
132
|
+
artifactsDir: artifactConfig.enabled ? artifactsDir : undefined,
|
|
133
|
+
artifactConfig,
|
|
134
|
+
maxOutput: params.maxOutput,
|
|
135
|
+
maxSubagentDepth:
|
|
136
|
+
child.maxSubagentDepth ??
|
|
137
|
+
resolveChildMaxSubagentDepth(
|
|
138
|
+
resolveWorkflowStageMaxSubagentDepth(ctx, deps.config.maxSubagentDepth),
|
|
139
|
+
agentConfig.maxSubagentDepth,
|
|
140
|
+
),
|
|
141
|
+
parentDepth: getCurrentSubagentDepth(ctx),
|
|
142
|
+
workflowStageSubagentGuard: isWorkflowStageOrchestrationContext(ctx),
|
|
96
143
|
workflowSessionMetadata: workflowSessionMetadataFromContext(ctx),
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
})
|
|
144
|
+
controlConfig: resolveControlConfig(deps.config.control, params.control),
|
|
145
|
+
intercomSessionName: intercomBridge.active
|
|
146
|
+
? resolveSubagentIntercomTarget(run.runId, child.agent, child.index)
|
|
147
|
+
: undefined,
|
|
148
|
+
orchestratorIntercomTarget: intercomBridge.active ? intercomBridge.orchestratorTarget : undefined,
|
|
149
|
+
intercomGroup: inheritedIntercomGroup(ctx),
|
|
150
|
+
supervisorAuthorization,
|
|
151
|
+
modelOverride: params.model,
|
|
152
|
+
availableModels: ctx.modelRegistry.getAvailable().map(toModelInfo),
|
|
153
|
+
knownModelProviders: collectKnownModelProviders(ctx.modelRegistry),
|
|
154
|
+
resolveCandidateModel: createCandidateModelResolver(ctx.modelRegistry, ctx.model?.provider),
|
|
155
|
+
preferredModelProvider: ctx.model?.provider,
|
|
156
|
+
currentModel: currentModelFullId(ctx.model),
|
|
157
|
+
onUpdate: forwardSingleUpdate,
|
|
158
|
+
onDetachedExit: (detachedResult) => {
|
|
159
|
+
cleanupProgress();
|
|
160
|
+
if (detachedResult) {
|
|
161
|
+
replaceForegroundRunChild(deps.state, run.runId, child.index, detachedResult);
|
|
162
|
+
notifyDetachedForegroundChildExit({
|
|
163
|
+
pi: deps.pi,
|
|
164
|
+
runId: run.runId,
|
|
165
|
+
mode: "single",
|
|
166
|
+
index: child.index,
|
|
167
|
+
result: detachedResult,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
} catch (error) {
|
|
173
|
+
cleanupProgress();
|
|
174
|
+
throw error;
|
|
175
|
+
}
|
|
176
|
+
if (!result.detached) cleanupProgress();
|
|
177
|
+
replaceForegroundRunChild(deps.state, run.runId, child.index, result, { onlyWhenDetached: false });
|
|
178
|
+
return {
|
|
179
|
+
content: [{ type: "text", text: result.finalOutput ?? result.envelope ?? result.error ?? "" }],
|
|
180
|
+
details: { mode: "single", runId: run.runId, results: [result] },
|
|
181
|
+
...(result.status === "error" ? { isError: true } : {}),
|
|
182
|
+
};
|
|
126
183
|
}
|
|
127
184
|
const MUTATING_MANAGEMENT_ACTIONS = new Set(["create", "update", "delete"]);
|
|
128
185
|
/**
|
|
@@ -141,8 +198,9 @@ async function handleManagementRequest(input: {
|
|
|
141
198
|
requestCwd: string;
|
|
142
199
|
ctx: ExtensionContext;
|
|
143
200
|
deps: ResolvedExecutorDeps;
|
|
201
|
+
onUpdate?: (r: SubagentToolResult) => void;
|
|
144
202
|
}): Promise<SubagentToolResult> {
|
|
145
|
-
const { params, paramsWithResolvedCwd, requestCwd, ctx, deps } = input;
|
|
203
|
+
const { params, paramsWithResolvedCwd, requestCwd, ctx, deps, onUpdate } = input;
|
|
146
204
|
const action = params.action;
|
|
147
205
|
if (!action) {
|
|
148
206
|
return {
|
|
@@ -243,7 +301,7 @@ async function handleManagementRequest(input: {
|
|
|
243
301
|
}
|
|
244
302
|
const inProcess = await resumeInProcessChild(targetRunId, message, { model: ctx.model });
|
|
245
303
|
if (inProcess) return inProcess;
|
|
246
|
-
const retained = await resumeRetainedForegroundChild(paramsWithResolvedCwd, message, ctx, deps);
|
|
304
|
+
const retained = await resumeRetainedForegroundChild(paramsWithResolvedCwd, message, ctx, deps, onUpdate);
|
|
247
305
|
if (retained) return retained;
|
|
248
306
|
return {
|
|
249
307
|
content: [{ type: "text", text: `No in-process child found for '${targetRunId}'.` }],
|
|
@@ -315,7 +373,7 @@ export function createSubagentExecutor(rawDeps: ExecutorDeps): {
|
|
|
315
373
|
const requestCwd = resolveRequestedCwd(ctx.cwd, params.cwd);
|
|
316
374
|
const paramsWithResolvedCwd = params.cwd === undefined ? params : { ...params, cwd: requestCwd };
|
|
317
375
|
if (params.action) {
|
|
318
|
-
return handleManagementRequest({ params, paramsWithResolvedCwd, requestCwd, ctx, deps });
|
|
376
|
+
return handleManagementRequest({ params, paramsWithResolvedCwd, requestCwd, ctx, deps, onUpdate });
|
|
319
377
|
}
|
|
320
378
|
// Fanout authorization gates delegation and every management action that can
|
|
321
379
|
// start or continue agent execution. Only `list`, `get`, `status`, and
|
|
@@ -337,8 +395,6 @@ export function createSubagentExecutor(rawDeps: ExecutorDeps): {
|
|
|
337
395
|
const prepared = built.prepared!;
|
|
338
396
|
let nestedForegroundStarted = false;
|
|
339
397
|
try {
|
|
340
|
-
const asyncResult = await runAsyncPath(prepared.execData, deps);
|
|
341
|
-
if (asyncResult) return withForkContext(asyncResult, prepared.effectiveParams.context);
|
|
342
398
|
if (prepared.foregroundControl) {
|
|
343
399
|
prepared.writeNestedForegroundEvent("subagent.nested.started");
|
|
344
400
|
nestedForegroundStarted = true;
|
|
@@ -45,7 +45,7 @@ import { type InProcessNestedResumeOutcome, registerInProcessNestedAttempt } fro
|
|
|
45
45
|
import { createInProcessChildPromptBehavior } from "./prompt-behavior.ts";
|
|
46
46
|
|
|
47
47
|
export type ChildStatus = NativeAgentStatus;
|
|
48
|
-
export type ContinuationReason = "
|
|
48
|
+
export type ContinuationReason = "intercom-coordination";
|
|
49
49
|
export type TerminationCauseName = NativeTerminationCause;
|
|
50
50
|
export type TerminalStatus = "ok" | "error" | "skipped" | "interrupted" | "continued";
|
|
51
51
|
|
|
@@ -1105,8 +1105,8 @@ export class SubagentControlRuntime {
|
|
|
1105
1105
|
return running;
|
|
1106
1106
|
}
|
|
1107
1107
|
|
|
1108
|
-
|
|
1109
|
-
if (running.status !== "running") throw new Error("
|
|
1108
|
+
continueDetached(running: RunningAttempt, _reason: ContinuationReason): string {
|
|
1109
|
+
if (running.status !== "running") throw new Error("continue_detached requires a running attempt");
|
|
1110
1110
|
this.native.publishChildStatus(running.child.identity.path, nativeStatus("continued"));
|
|
1111
1111
|
running.status = "continued";
|
|
1112
1112
|
running.promise.catch(() => undefined);
|
|
@@ -1363,12 +1363,12 @@ export function run_child_attempt(
|
|
|
1363
1363
|
);
|
|
1364
1364
|
}
|
|
1365
1365
|
|
|
1366
|
-
export function
|
|
1366
|
+
export function continue_detached(
|
|
1367
1367
|
control: SubagentControlRuntime,
|
|
1368
1368
|
running: RunningAttempt,
|
|
1369
1369
|
reason: ContinuationReason,
|
|
1370
1370
|
): string {
|
|
1371
|
-
return control.
|
|
1371
|
+
return control.continueDetached(running, reason);
|
|
1372
1372
|
}
|
|
1373
1373
|
|
|
1374
1374
|
export function reload_cold_child(control: SubagentControlRuntime, pathValue: string, message: string): AdmittedResult {
|
|
@@ -25,9 +25,7 @@ export {
|
|
|
25
25
|
MAX_NESTED_STEPS,
|
|
26
26
|
MAX_PROCESSED_NESTED_EVENTS,
|
|
27
27
|
NESTED_EVENTS_DIR,
|
|
28
|
-
NESTED_RUNS_DIR,
|
|
29
28
|
resolveInheritedNestedRouteFromEnv,
|
|
30
|
-
resolveNestedAsyncDir,
|
|
31
29
|
resolveNestedParentAddressFromEnv,
|
|
32
30
|
resolveNestedRouteFromEnv,
|
|
33
31
|
validateNestedRouteShape,
|
|
@@ -41,11 +39,6 @@ export {
|
|
|
41
39
|
export {
|
|
42
40
|
attachRootChildrenToSteps,
|
|
43
41
|
hasLiveNestedDescendants,
|
|
44
|
-
isTopLevelAsyncDir,
|
|
45
|
-
nestedArtifactEnv,
|
|
46
|
-
nestedResultsPath,
|
|
47
|
-
nestedSummaryFromAsyncStatus,
|
|
48
|
-
updateAsyncJobNestedProjection,
|
|
49
42
|
updateForegroundNestedProjection,
|
|
50
43
|
} from "./nested-projection.ts";
|
|
51
44
|
export type { NestedRunMatch, NestedRunResolutionScope } from "./nested-registry.ts";
|
|
@@ -7,7 +7,6 @@ import { registerInProcessNestedRoute } from "../nested-routing.ts";
|
|
|
7
7
|
import { isSafeNestedPathId, type NestedPathEntry } from "./nested-paths.ts";
|
|
8
8
|
|
|
9
9
|
export const NESTED_EVENTS_DIR = path.join(TEMP_ROOT_DIR, "nested-subagent-events");
|
|
10
|
-
export const NESTED_RUNS_DIR = path.join(TEMP_ROOT_DIR, "nested-subagent-runs");
|
|
11
10
|
export const ROUTE_FILE = "route.json";
|
|
12
11
|
export const REGISTRY_FILE = "registry.json";
|
|
13
12
|
export const MAX_NESTED_EVENT_BYTES = 64 * 1024;
|
|
@@ -163,7 +162,6 @@ function cleanupOldSubdirectories(root: string, maxAgeDays: number): void {
|
|
|
163
162
|
|
|
164
163
|
export function cleanupOldNestedRuntimeDirs(maxAgeDays: number): void {
|
|
165
164
|
cleanupOldSubdirectories(NESTED_EVENTS_DIR, maxAgeDays);
|
|
166
|
-
cleanupOldSubdirectories(NESTED_RUNS_DIR, maxAgeDays);
|
|
167
165
|
}
|
|
168
166
|
|
|
169
167
|
export function resolveNestedRouteFromEnv(_env: NodeJS.ProcessEnv = process.env): NestedRoute | undefined {
|
|
@@ -180,14 +178,6 @@ export function resolveNestedParentAddressFromEnv(
|
|
|
180
178
|
return undefined;
|
|
181
179
|
}
|
|
182
180
|
|
|
183
|
-
export function resolveNestedAsyncDir(rootRunId: string, run: NestedRunSummary): string | undefined {
|
|
184
|
-
if (!run.asyncDir) return undefined;
|
|
185
|
-
const resolved = path.resolve(run.asyncDir);
|
|
186
|
-
const nestedRoot = path.resolve(NESTED_RUNS_DIR, rootRunId, run.id);
|
|
187
|
-
const relative = path.relative(nestedRoot, resolved);
|
|
188
|
-
return resolved === nestedRoot || (!relative.startsWith("..") && !path.isAbsolute(relative)) ? resolved : undefined;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
181
|
export function clampNumber(value: unknown): number | undefined {
|
|
192
182
|
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
193
183
|
}
|
|
@@ -1,15 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
ASYNC_DIR,
|
|
5
|
-
type AsyncJobState,
|
|
6
|
-
type AsyncStatus,
|
|
7
|
-
type NestedRunSummary,
|
|
8
|
-
RESULTS_DIR,
|
|
9
|
-
type SubagentRunMode,
|
|
10
|
-
type SubagentState,
|
|
11
|
-
} from "../../../shared/types.ts";
|
|
12
|
-
import { assertSafeId, containedPath, MAX_NESTED_CHILDREN, MAX_NESTED_STEPS, NESTED_RUNS_DIR } from "./nested-core.ts";
|
|
1
|
+
import type { NestedRunSummary, SubagentState } from "../../../shared/types.ts";
|
|
2
|
+
import { MAX_NESTED_CHILDREN } from "./nested-core.ts";
|
|
13
3
|
import { projectNestedEvents } from "./nested-registry.ts";
|
|
14
4
|
import { terminal } from "./nested-sanitize.ts";
|
|
15
5
|
|
|
@@ -19,9 +9,7 @@ export function attachRootChildrenToSteps<T extends { children?: NestedRunSummar
|
|
|
19
9
|
children: NestedRunSummary[] | undefined,
|
|
20
10
|
): void {
|
|
21
11
|
if (!steps?.length) return;
|
|
22
|
-
for (const step of steps)
|
|
23
|
-
step.children = undefined;
|
|
24
|
-
}
|
|
12
|
+
for (const step of steps) step.children = undefined;
|
|
25
13
|
if (!children?.length) return;
|
|
26
14
|
for (const child of children) {
|
|
27
15
|
if (child.parentRunId !== rootRunId || child.parentStepIndex === undefined) continue;
|
|
@@ -35,13 +23,6 @@ export function attachRootChildrenToSteps<T extends { children?: NestedRunSummar
|
|
|
35
23
|
}
|
|
36
24
|
}
|
|
37
25
|
|
|
38
|
-
export function updateAsyncJobNestedProjection(job: AsyncJobState): void {
|
|
39
|
-
if (!job.nestedRoute) return;
|
|
40
|
-
const registry = projectNestedEvents(job.nestedRoute);
|
|
41
|
-
job.nestedChildren = registry.children;
|
|
42
|
-
attachRootChildrenToSteps(job.asyncId, job.steps, registry.children);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
26
|
export function updateForegroundNestedProjection(
|
|
46
27
|
control: SubagentState["foregroundControls"] extends Map<string, infer T> ? T : never,
|
|
47
28
|
): void {
|
|
@@ -59,89 +40,3 @@ export function hasLiveNestedDescendants(children: NestedRunSummary[] | undefine
|
|
|
59
40
|
}
|
|
60
41
|
return false;
|
|
61
42
|
}
|
|
62
|
-
|
|
63
|
-
export function nestedSummaryFromAsyncStatus(
|
|
64
|
-
status: AsyncStatus,
|
|
65
|
-
asyncDir: string,
|
|
66
|
-
fallback: {
|
|
67
|
-
id: string;
|
|
68
|
-
parentRunId: string;
|
|
69
|
-
parentStepIndex?: number;
|
|
70
|
-
depth: number;
|
|
71
|
-
path?: Array<{ runId: string; stepIndex?: number; agent?: string }>;
|
|
72
|
-
mode?: SubagentRunMode;
|
|
73
|
-
ts: number;
|
|
74
|
-
},
|
|
75
|
-
): NestedRunSummary {
|
|
76
|
-
return {
|
|
77
|
-
id: status.runId || fallback.id,
|
|
78
|
-
parentRunId: fallback.parentRunId,
|
|
79
|
-
...(fallback.parentStepIndex !== undefined ? { parentStepIndex: fallback.parentStepIndex } : {}),
|
|
80
|
-
depth: fallback.depth,
|
|
81
|
-
path: fallback.path ?? [
|
|
82
|
-
{
|
|
83
|
-
runId: fallback.parentRunId,
|
|
84
|
-
...(fallback.parentStepIndex !== undefined ? { stepIndex: fallback.parentStepIndex } : {}),
|
|
85
|
-
},
|
|
86
|
-
],
|
|
87
|
-
asyncDir,
|
|
88
|
-
...(status.pid ? { pid: status.pid } : {}),
|
|
89
|
-
...(status.sessionId ? { sessionId: status.sessionId } : {}),
|
|
90
|
-
mode: status.mode ?? fallback.mode,
|
|
91
|
-
state: status.state,
|
|
92
|
-
...(status.activityState ? { activityState: status.activityState } : {}),
|
|
93
|
-
...(status.lastActivityAt !== undefined ? { lastActivityAt: status.lastActivityAt } : {}),
|
|
94
|
-
...(status.currentTool ? { currentTool: status.currentTool } : {}),
|
|
95
|
-
...(status.currentToolStartedAt !== undefined ? { currentToolStartedAt: status.currentToolStartedAt } : {}),
|
|
96
|
-
...(status.currentPath ? { currentPath: status.currentPath } : {}),
|
|
97
|
-
...(status.turnCount !== undefined ? { turnCount: status.turnCount } : {}),
|
|
98
|
-
...(status.toolCount !== undefined ? { toolCount: status.toolCount } : {}),
|
|
99
|
-
...(status.totalTokens ? { totalTokens: status.totalTokens } : {}),
|
|
100
|
-
...(status.startedAt !== undefined ? { startedAt: status.startedAt } : { startedAt: fallback.ts }),
|
|
101
|
-
...(status.endedAt !== undefined ? { endedAt: status.endedAt } : {}),
|
|
102
|
-
lastUpdate: status.lastUpdate ?? fallback.ts,
|
|
103
|
-
...(status.sessionFile ? { sessionFile: status.sessionFile } : {}),
|
|
104
|
-
...(status.steps?.length
|
|
105
|
-
? {
|
|
106
|
-
steps: status.steps
|
|
107
|
-
.map((step) => ({
|
|
108
|
-
agent: step.agent,
|
|
109
|
-
status: step.status,
|
|
110
|
-
...(step.sessionFile ? { sessionFile: step.sessionFile } : {}),
|
|
111
|
-
...(step.activityState ? { activityState: step.activityState } : {}),
|
|
112
|
-
...(step.lastActivityAt !== undefined ? { lastActivityAt: step.lastActivityAt } : {}),
|
|
113
|
-
...(step.currentTool ? { currentTool: step.currentTool } : {}),
|
|
114
|
-
...(step.currentToolStartedAt !== undefined
|
|
115
|
-
? { currentToolStartedAt: step.currentToolStartedAt }
|
|
116
|
-
: {}),
|
|
117
|
-
...(step.currentPath ? { currentPath: step.currentPath } : {}),
|
|
118
|
-
...(step.turnCount !== undefined ? { turnCount: step.turnCount } : {}),
|
|
119
|
-
...(step.toolCount !== undefined ? { toolCount: step.toolCount } : {}),
|
|
120
|
-
...(step.startedAt !== undefined ? { startedAt: step.startedAt } : {}),
|
|
121
|
-
...(step.endedAt !== undefined ? { endedAt: step.endedAt } : {}),
|
|
122
|
-
...(step.error ? { error: step.error } : {}),
|
|
123
|
-
}))
|
|
124
|
-
.slice(0, MAX_NESTED_STEPS),
|
|
125
|
-
}
|
|
126
|
-
: {}),
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
export function nestedArtifactEnv(rootRunId: string, parentRunId: string): Record<string, string> {
|
|
131
|
-
const envPrefix = APP_NAME.toUpperCase();
|
|
132
|
-
return {
|
|
133
|
-
[`${envPrefix}_SUBAGENT_NESTED_ROOT_RUN_ID`]: rootRunId,
|
|
134
|
-
[`${envPrefix}_SUBAGENT_NESTED_PARENT_RUN_ID`]: parentRunId,
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
export function isTopLevelAsyncDir(asyncDir: string): boolean {
|
|
139
|
-
const resolved = path.resolve(asyncDir);
|
|
140
|
-
return containedPath(ASYNC_DIR, resolved) && !containedPath(NESTED_RUNS_DIR, resolved);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
export function nestedResultsPath(rootRunId: string, id: string): string {
|
|
144
|
-
assertSafeId("rootRunId", rootRunId);
|
|
145
|
-
assertSafeId("id", id);
|
|
146
|
-
return path.join(RESULTS_DIR, "nested", rootRunId, `${id}.json`);
|
|
147
|
-
}
|
|
@@ -91,10 +91,6 @@ export function sanitizeSummary(input: unknown, depth = 0): NestedRunSummary | u
|
|
|
91
91
|
depth: Math.min(Math.max(0, clampNumber(raw.depth) ?? 0), MAX_NESTED_DEPTH),
|
|
92
92
|
path: pathParts,
|
|
93
93
|
state: sanitizeState(raw.state, "running"),
|
|
94
|
-
...(stringValue(raw.asyncDir, 2048) ? { asyncDir: stringValue(raw.asyncDir, 2048) } : {}),
|
|
95
|
-
...(clampNumber(raw.pid) !== undefined && clampNumber(raw.pid)! > 0 && Number.isInteger(clampNumber(raw.pid))
|
|
96
|
-
? { pid: clampNumber(raw.pid) }
|
|
97
|
-
: {}),
|
|
98
94
|
...(stringValue(raw.sessionId, 256) ? { sessionId: stringValue(raw.sessionId, 256) } : {}),
|
|
99
95
|
...(stringValue(raw.sessionFile, 2048) ? { sessionFile: stringValue(raw.sessionFile, 2048) } : {}),
|
|
100
96
|
...(stringValue(raw.intercomTarget, 256) ? { intercomTarget: stringValue(raw.intercomTarget, 256) } : {}),
|
|
@@ -8,7 +8,7 @@ import type {
|
|
|
8
8
|
} from "../../shared/types.ts";
|
|
9
9
|
|
|
10
10
|
const CONTROL_EVENT_TYPES: ControlEventType[] = ["active_long_running", "needs_attention"];
|
|
11
|
-
const CONTROL_NOTIFICATION_CHANNELS: ControlNotificationChannel[] = ["event", "
|
|
11
|
+
const CONTROL_NOTIFICATION_CHANNELS: ControlNotificationChannel[] = ["event", "intercom"];
|
|
12
12
|
const DEFAULT_NOTIFY_ON: ControlEventType[] = ["active_long_running", "needs_attention"];
|
|
13
13
|
|
|
14
14
|
export const DEFAULT_CONTROL_CONFIG: ResolvedControlConfig = {
|
|
@@ -14,13 +14,11 @@ export function formatTokens(n: number): string {
|
|
|
14
14
|
|
|
15
15
|
export function formatModelThinking(model?: string, thinking?: string, fastMode?: boolean): string {
|
|
16
16
|
const parsed = model ? splitKnownThinkingSuffix(model) : undefined;
|
|
17
|
-
|
|
17
|
+
// Keep the full `provider/model` id so subagent lines read exactly like the
|
|
18
|
+
// main chat's model display; only a known thinking suffix is split off.
|
|
19
|
+
const displayModel = parsed?.baseModel ?? model;
|
|
18
20
|
const explicitThinking = THINKING_LEVELS.find((level) => level === thinking?.trim());
|
|
19
21
|
const displayThinking = parsed?.thinkingSuffix ? parsed.thinkingSuffix.slice(1) : explicitThinking;
|
|
20
|
-
if (displayModel) {
|
|
21
|
-
const slashIdx = displayModel.lastIndexOf("/");
|
|
22
|
-
if (slashIdx !== -1) displayModel = displayModel.slice(slashIdx + 1);
|
|
23
|
-
}
|
|
24
22
|
const parts = [displayModel, displayThinking ? `thinking ${displayThinking}` : undefined].filter(Boolean);
|
|
25
23
|
if (fastMode && parts.length > 0) parts.push("fast");
|
|
26
24
|
return parts.join(" · ");
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolution of a selected model candidate id to a concrete registry model.
|
|
3
|
+
*
|
|
4
|
+
* `buildModelCandidates` yields `provider/model[:thinking]` strings. Those
|
|
5
|
+
* strings alone never reach the child session: `createAgentSession` takes a
|
|
6
|
+
* `Model<Api>` object, and when no model is supplied it restores the model
|
|
7
|
+
* persisted in the session file. For a fork-context child that file is a copy
|
|
8
|
+
* of the parent's, so the parent's model silently won. Resolving the selected
|
|
9
|
+
* candidate to a real model here is what lets the configured model be handed
|
|
10
|
+
* to the child session instead.
|
|
11
|
+
*
|
|
12
|
+
* The lookup semantics deliberately mirror the SDK's own fallback-entry
|
|
13
|
+
* resolution (`resolveFallbackModel`), so the primary candidate and the
|
|
14
|
+
* fallback candidates handed to the same session agree on what a candidate
|
|
15
|
+
* string means.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import type { Api, Model } from "@earendil-works/pi-ai/compat";
|
|
19
|
+
import { splitKnownThinkingSuffix, THINKING_LEVELS, type ThinkingLevel } from "./model-info.ts";
|
|
20
|
+
|
|
21
|
+
/** Registry surface needed to resolve a candidate; satisfied by `ctx.modelRegistry`. */
|
|
22
|
+
export interface CandidateModelLookup {
|
|
23
|
+
getAvailable(): Model<Api>[];
|
|
24
|
+
find(provider: string, modelId: string): Model<Api> | undefined;
|
|
25
|
+
hasConfiguredAuth(model: Model<Api>): boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** A candidate string resolved to a concrete model and its requested thinking level. */
|
|
29
|
+
export interface ResolvedCandidateModel {
|
|
30
|
+
model: Model<Api>;
|
|
31
|
+
thinkingLevel?: ThinkingLevel;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Resolve one `provider/model[:thinking]` candidate id against the registry.
|
|
36
|
+
* Returns `undefined` when the candidate names no usable model, which leaves
|
|
37
|
+
* the caller on its previous behavior rather than failing the run.
|
|
38
|
+
*/
|
|
39
|
+
export type CandidateModelResolver = (candidateId: string) => ResolvedCandidateModel | undefined;
|
|
40
|
+
|
|
41
|
+
function thinkingLevelFromSuffix(suffix: string): ThinkingLevel | undefined {
|
|
42
|
+
if (!suffix) return undefined;
|
|
43
|
+
const level = suffix.slice(1);
|
|
44
|
+
return THINKING_LEVELS.find((known) => known === level);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function resolveCandidateModel(
|
|
48
|
+
candidateId: string,
|
|
49
|
+
lookup: CandidateModelLookup,
|
|
50
|
+
preferredProvider?: string,
|
|
51
|
+
): ResolvedCandidateModel | undefined {
|
|
52
|
+
const trimmed = candidateId.trim();
|
|
53
|
+
if (!trimmed) return undefined;
|
|
54
|
+
const { baseModel, thinkingSuffix } = splitKnownThinkingSuffix(trimmed);
|
|
55
|
+
const thinkingLevel = thinkingLevelFromSuffix(thinkingSuffix);
|
|
56
|
+
const slash = baseModel.indexOf("/");
|
|
57
|
+
if (slash < 0) {
|
|
58
|
+
const available = lookup.getAvailable().filter((entry) => entry.id === baseModel);
|
|
59
|
+
const model =
|
|
60
|
+
available.find((entry) => entry.provider === preferredProvider) ??
|
|
61
|
+
(available.length === 1 ? available[0] : undefined);
|
|
62
|
+
if (!model) return undefined;
|
|
63
|
+
return thinkingLevel === undefined ? { model } : { model, thinkingLevel };
|
|
64
|
+
}
|
|
65
|
+
const provider = baseModel.slice(0, slash);
|
|
66
|
+
const modelId = baseModel.slice(slash + 1);
|
|
67
|
+
const model = lookup.find(provider, modelId);
|
|
68
|
+
if (!model || !lookup.hasConfiguredAuth(model)) return undefined;
|
|
69
|
+
return thinkingLevel === undefined ? { model } : { model, thinkingLevel };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Bind a registry and the parent's provider into a reusable candidate resolver. */
|
|
73
|
+
export function createCandidateModelResolver(
|
|
74
|
+
lookup: CandidateModelLookup,
|
|
75
|
+
preferredProvider?: string,
|
|
76
|
+
): CandidateModelResolver {
|
|
77
|
+
return (candidateId: string) => resolveCandidateModel(candidateId, lookup, preferredProvider);
|
|
78
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { ActivityState
|
|
1
|
+
import type { ActivityState } from "./types.ts";
|
|
2
2
|
|
|
3
|
-
type
|
|
3
|
+
type StepStatus = "pending" | "running" | "complete" | "completed" | "failed" | "paused";
|
|
4
|
+
type StepStatusLike = { status: StepStatus };
|
|
4
5
|
|
|
5
6
|
function formatActivityAge(ms: number): string {
|
|
6
7
|
if (ms < 1000) return "now";
|
|
@@ -24,18 +25,10 @@ export function formatActivityLabel(
|
|
|
24
25
|
return age === "now" ? "active now" : `active ${age} ago`;
|
|
25
26
|
}
|
|
26
27
|
|
|
27
|
-
function isCompletedStepStatus(status:
|
|
28
|
+
function isCompletedStepStatus(status: StepStatus): boolean {
|
|
28
29
|
return status === "complete" || status === "completed";
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
export function aggregateStepStatus(steps: StepStatusLike[]): AsyncJobStep["status"] {
|
|
32
|
-
if (steps.some((step) => step.status === "running")) return "running";
|
|
33
|
-
if (steps.some((step) => step.status === "failed")) return "failed";
|
|
34
|
-
if (steps.some((step) => step.status === "paused")) return "paused";
|
|
35
|
-
if (steps.length > 0 && steps.every((step) => isCompletedStepStatus(step.status))) return "complete";
|
|
36
|
-
return "pending";
|
|
37
|
-
}
|
|
38
|
-
|
|
39
32
|
export function formatAgentRunningLabel(count: number): string {
|
|
40
33
|
return count === 1 ? "1 agent running" : `${count} agents running`;
|
|
41
34
|
}
|