@selesai/code 0.2.1 → 0.3.1
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/dist/config.d.ts +4 -15
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +5 -45
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +1 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +8 -0
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/diagnostics.d.ts +1 -0
- package/dist/core/diagnostics.d.ts.map +1 -1
- package/dist/core/diagnostics.js.map +1 -1
- package/dist/core/model-registry.d.ts +4 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +101 -51
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/package-manager.d.ts +10 -0
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +93 -8
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/package-manager.test.d.ts +2 -0
- package/dist/core/package-manager.test.d.ts.map +1 -0
- package/dist/core/package-manager.test.js +20 -0
- package/dist/core/package-manager.test.js.map +1 -0
- package/dist/core/resource-loader.d.ts +3 -0
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +10 -0
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/settings-manager.d.ts +1 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/defaults/models.json +64 -113
- package/dist/extensions/caveman/caveman-instructions.cjs +39 -0
- package/dist/extensions/caveman/index.js +116 -0
- package/dist/extensions/caveman/package.json +8 -0
- package/dist/extensions/caveman/test/extension.test.js +185 -0
- package/dist/extensions/caveman/test/helpers.test.js +67 -0
- package/dist/extensions/copy-turn.ts +2 -2
- package/dist/extensions/pi-intercom/broker/broker.ts +2 -3
- package/dist/extensions/pi-intercom/broker/paths.ts +10 -5
- package/dist/extensions/pi-intercom/broker/spawn.ts +2 -3
- package/dist/extensions/pi-intercom/config.ts +2 -2
- package/dist/extensions/pi-intercom/index.ts +2 -2
- package/dist/extensions/pi-intercom/package.json +2 -2
- package/dist/extensions/pi-intercom/ui/compose.ts +3 -3
- package/dist/extensions/pi-intercom/ui/inline-message.ts +3 -3
- package/dist/extensions/pi-intercom/ui/session-list.ts +3 -3
- package/dist/extensions/pi-powerline-footer/bash-mode/editor.ts +2 -2
- package/dist/extensions/pi-powerline-footer/bash-mode/history.ts +2 -1
- package/dist/extensions/pi-powerline-footer/index.ts +40 -47
- package/dist/extensions/pi-powerline-footer/package.json +2 -2
- package/dist/extensions/pi-powerline-footer/tests/bash-mode.test.ts +10 -10
- package/dist/extensions/pi-powerline-footer/tests/jump-shortcuts.test.ts +1 -1
- package/dist/extensions/pi-powerline-footer/tests/working-vibes.test.ts +2 -2
- package/dist/extensions/pi-powerline-footer/theme.ts +6 -6
- package/dist/extensions/pi-powerline-footer/tps.ts +1 -1
- package/dist/extensions/pi-powerline-footer/types.ts +7 -7
- package/dist/extensions/pi-powerline-footer/welcome.ts +23 -16
- package/dist/extensions/pi-powerline-footer/working-vibes.ts +52 -59
- package/dist/extensions/pi-rewind-hook/index.ts +1 -1
- package/dist/extensions/pi-rewind-hook/package.json +1 -1
- package/dist/extensions/pi-subagents/README.md +224 -52
- package/dist/extensions/pi-subagents/agents/architect.md +188 -0
- package/dist/extensions/pi-subagents/agents/builder.md +120 -0
- package/dist/extensions/pi-subagents/agents/commentator.md +131 -0
- package/dist/extensions/pi-subagents/agents/explorer.md +51 -0
- package/dist/extensions/pi-subagents/agents/recapper.md +21 -0
- package/dist/extensions/pi-subagents/install.mjs +93 -0
- package/dist/extensions/pi-subagents/package.json +4 -5
- package/dist/extensions/pi-subagents/prompts/parallel-context-build.md +1 -1
- package/dist/extensions/pi-subagents/prompts/parallel-handoff-plan.md +1 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +76 -13
- package/dist/extensions/pi-subagents/src/agents/agent-management.ts +179 -2
- package/dist/extensions/pi-subagents/src/agents/agent-memory.ts +254 -0
- package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +11 -0
- package/dist/extensions/pi-subagents/src/agents/agents.ts +193 -19
- package/dist/extensions/pi-subagents/src/agents/chain-serializer.ts +27 -2
- package/dist/extensions/pi-subagents/src/extension/config.ts +27 -4
- package/dist/extensions/pi-subagents/src/extension/doctor.ts +1 -7
- package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +3 -2
- package/dist/extensions/pi-subagents/src/extension/index.ts +73 -71
- package/dist/extensions/pi-subagents/src/extension/rpc.ts +369 -0
- package/dist/extensions/pi-subagents/src/extension/schemas.ts +54 -10
- package/dist/extensions/pi-subagents/src/extension/tool-description.ts +200 -0
- package/dist/extensions/pi-subagents/src/intercom/intercom-bridge.ts +21 -253
- package/dist/extensions/pi-subagents/src/intercom/native-supervisor-channel.ts +519 -0
- package/dist/extensions/pi-subagents/src/profiles/profiles.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +195 -105
- package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +88 -2
- package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +67 -10
- package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +34 -4
- package/dist/extensions/pi-subagents/src/runs/background/completion-batcher.ts +166 -0
- package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +156 -1
- package/dist/extensions/pi-subagents/src/runs/background/fleet-view.ts +515 -0
- package/dist/extensions/pi-subagents/src/runs/background/notify.ts +161 -44
- package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +1 -2
- package/dist/extensions/pi-subagents/src/runs/background/run-id-resolver.ts +3 -2
- package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +167 -6
- package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +514 -0
- package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +28 -1
- package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +873 -204
- package/dist/extensions/pi-subagents/src/runs/background/wait.ts +353 -0
- package/dist/extensions/pi-subagents/src/runs/foreground/chain-execution.ts +123 -27
- package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +174 -70
- package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +569 -81
- package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +45 -22
- package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +3 -1
- package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +2 -2
- package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +172 -21
- package/dist/extensions/pi-subagents/src/runs/shared/model-scope.ts +128 -0
- package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +89 -0
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +50 -1
- package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +35 -4
- package/dist/extensions/pi-subagents/src/runs/shared/pi-spawn.ts +63 -45
- package/dist/extensions/pi-subagents/src/runs/shared/single-output.ts +2 -0
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +125 -5
- package/dist/extensions/pi-subagents/src/runs/shared/tool-budget.ts +74 -0
- package/dist/extensions/pi-subagents/src/runs/shared/turn-budget.ts +52 -0
- package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +28 -5
- package/dist/extensions/pi-subagents/src/shared/artifacts.ts +16 -1
- package/dist/extensions/pi-subagents/src/shared/atomic-json.ts +15 -2
- package/dist/extensions/pi-subagents/src/shared/child-transcript.ts +212 -0
- package/dist/extensions/pi-subagents/src/shared/fork-context.ts +133 -22
- package/dist/extensions/pi-subagents/src/shared/settings.ts +3 -1
- package/dist/extensions/pi-subagents/src/shared/types.ts +197 -4
- package/dist/extensions/pi-subagents/src/shared/utils.ts +108 -17
- package/dist/extensions/pi-subagents/src/slash/prompt-workflows.ts +330 -0
- package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +135 -4
- package/dist/extensions/pi-subagents/src/tui/render.ts +32 -12
- package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +94 -0
- package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +2772 -0
- package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +1107 -0
- package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +463 -0
- package/dist/extensions/pi-subagents/test/integration/chain-clarify.test.ts +274 -0
- package/dist/extensions/pi-subagents/test/integration/chain-execution.test.ts +1535 -0
- package/dist/extensions/pi-subagents/test/integration/detect-error.test.ts +242 -0
- package/dist/extensions/pi-subagents/test/integration/doctor-executor.test.ts +128 -0
- package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +252 -0
- package/dist/extensions/pi-subagents/test/integration/foreground-result-size.test.ts +188 -0
- package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +1306 -0
- package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +1033 -0
- package/dist/extensions/pi-subagents/test/integration/parallel-execution.test.ts +397 -0
- package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +583 -0
- package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +691 -0
- package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +892 -0
- package/dist/extensions/pi-subagents/test/integration/session-tokens.test.ts +62 -0
- package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +1824 -0
- package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +1284 -0
- package/dist/extensions/pi-subagents/test/integration/slash-live-state.test.ts +127 -0
- package/dist/extensions/pi-subagents/test/integration/template-resolution.test.ts +299 -0
- package/dist/extensions/pi-subagents/test/integration/top-level-async.test.ts +37 -0
- package/dist/extensions/pi-subagents/test/support/helpers.ts +189 -0
- package/dist/extensions/pi-subagents/test/support/mock-pi-script.mjs +335 -0
- package/dist/extensions/pi-subagents/test/support/mock-pi.ts +129 -0
- package/dist/extensions/pi-subagents/test/support/real-session-child-cli.mjs +184 -0
- package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +285 -0
- package/dist/extensions/pi-subagents/test/support/register-loader.mjs +15 -0
- package/dist/extensions/pi-subagents/test/support/ts-loader.mjs +108 -0
- package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +421 -0
- package/dist/extensions/pi-subagents/test/unit/agent-disabled.test.ts +213 -0
- package/dist/extensions/pi-subagents/test/unit/agent-eject-disable.test.ts +343 -0
- package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +1199 -0
- package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +556 -0
- package/dist/extensions/pi-subagents/test/unit/agent-memory.test.ts +420 -0
- package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +579 -0
- package/dist/extensions/pi-subagents/test/unit/agent-scope.test.ts +20 -0
- package/dist/extensions/pi-subagents/test/unit/agent-selection.test.ts +88 -0
- package/dist/extensions/pi-subagents/test/unit/artifacts.test.ts +24 -0
- package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +86 -0
- package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +221 -0
- package/dist/extensions/pi-subagents/test/unit/async-permission-session.test.ts +98 -0
- package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +285 -0
- package/dist/extensions/pi-subagents/test/unit/atomic-json.test.ts +112 -0
- package/dist/extensions/pi-subagents/test/unit/chain-append.test.ts +206 -0
- package/dist/extensions/pi-subagents/test/unit/chain-root-attachment.test.ts +159 -0
- package/dist/extensions/pi-subagents/test/unit/chain-serializer.test.ts +229 -0
- package/dist/extensions/pi-subagents/test/unit/child-transcript.test.ts +225 -0
- package/dist/extensions/pi-subagents/test/unit/close-grace-timer.test.ts +101 -0
- package/dist/extensions/pi-subagents/test/unit/completion-batcher.test.ts +228 -0
- package/dist/extensions/pi-subagents/test/unit/completion-dedupe.test.ts +36 -0
- package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +152 -0
- package/dist/extensions/pi-subagents/test/unit/config-dir-runtime.test.ts +72 -0
- package/dist/extensions/pi-subagents/test/unit/control-channel.test.ts +327 -0
- package/dist/extensions/pi-subagents/test/unit/control-notices.test.ts +161 -0
- package/dist/extensions/pi-subagents/test/unit/doctor.test.ts +159 -0
- package/dist/extensions/pi-subagents/test/unit/dynamic-fanout.test.ts +217 -0
- package/dist/extensions/pi-subagents/test/unit/extra-agent-dirs.test.ts +88 -0
- package/dist/extensions/pi-subagents/test/unit/file-coalescer.test.ts +68 -0
- package/dist/extensions/pi-subagents/test/unit/foreground-tool-call-compaction.test.ts +78 -0
- package/dist/extensions/pi-subagents/test/unit/fork-context.test.ts +415 -0
- package/dist/extensions/pi-subagents/test/unit/get-final-output.test.ts +126 -0
- package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +271 -0
- package/dist/extensions/pi-subagents/test/unit/intercom-bridge.test.ts +173 -0
- package/dist/extensions/pi-subagents/test/unit/jsonl-writer.test.ts +119 -0
- package/dist/extensions/pi-subagents/test/unit/live-async-resume.test.ts +170 -0
- package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +346 -0
- package/dist/extensions/pi-subagents/test/unit/model-info.test.ts +62 -0
- package/dist/extensions/pi-subagents/test/unit/model-scope-settings.test.ts +87 -0
- package/dist/extensions/pi-subagents/test/unit/model-scope.test.ts +145 -0
- package/dist/extensions/pi-subagents/test/unit/native-supervisor-channel.test.ts +162 -0
- package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +470 -0
- package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +329 -0
- package/dist/extensions/pi-subagents/test/unit/notify.test.ts +319 -0
- package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +70 -0
- package/dist/extensions/pi-subagents/test/unit/parallel-utils.test.ts +247 -0
- package/dist/extensions/pi-subagents/test/unit/path-handling.test.ts +113 -0
- package/dist/extensions/pi-subagents/test/unit/path-resolution.test.ts +94 -0
- package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +803 -0
- package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +209 -0
- package/dist/extensions/pi-subagents/test/unit/pi-spawn.test.ts +238 -0
- package/dist/extensions/pi-subagents/test/unit/proactive-skills.test.ts +118 -0
- package/dist/extensions/pi-subagents/test/unit/profiles.test.ts +299 -0
- package/dist/extensions/pi-subagents/test/unit/prompt-template-bridge.test.ts +408 -0
- package/dist/extensions/pi-subagents/test/unit/prompt-workflows.test.ts +134 -0
- package/dist/extensions/pi-subagents/test/unit/recursion-guard.test.ts +257 -0
- package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +209 -0
- package/dist/extensions/pi-subagents/test/unit/result-intercom.test.ts +226 -0
- package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +294 -0
- package/dist/extensions/pi-subagents/test/unit/run-id-resolver.test.ts +147 -0
- package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +997 -0
- package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +478 -0
- package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +562 -0
- package/dist/extensions/pi-subagents/test/unit/single-output.test.ts +213 -0
- package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +438 -0
- package/dist/extensions/pi-subagents/test/unit/slash-bridge.test.ts +54 -0
- package/dist/extensions/pi-subagents/test/unit/slash-chain-groups.test.ts +464 -0
- package/dist/extensions/pi-subagents/test/unit/stale-run-reconciler.test.ts +255 -0
- package/dist/extensions/pi-subagents/test/unit/status-format.test.ts +19 -0
- package/dist/extensions/pi-subagents/test/unit/subagent-control.test.ts +245 -0
- package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +517 -0
- package/dist/extensions/pi-subagents/test/unit/temp-paths.test.ts +72 -0
- package/dist/extensions/pi-subagents/test/unit/tool-budget.test.ts +52 -0
- package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +237 -0
- package/dist/extensions/pi-subagents/test/unit/total-cost.test.ts +60 -0
- package/dist/extensions/pi-subagents/test/unit/ts-loader.test.ts +33 -0
- package/dist/extensions/pi-subagents/test/unit/turn-budget.test.ts +202 -0
- package/dist/extensions/pi-subagents/test/unit/types-fork-preamble.test.ts +23 -0
- package/dist/extensions/pi-subagents/test/unit/wait.test.ts +398 -0
- package/dist/extensions/pi-subagents/test/unit/widget-nested-render.test.ts +88 -0
- package/dist/extensions/pi-subagents/test/unit/windows-hide-spawn.test.ts +26 -0
- package/dist/extensions/pi-subagents/test/unit/workflow-graph.test.ts +134 -0
- package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +479 -0
- package/dist/extensions/pi-web-agent/package.json +2 -2
- package/dist/extensions/pi-web-agent/src/backends/settings-reader.ts +2 -2
- package/dist/extensions/pi-web-agent/src/changelog-notice.ts +5 -2
- package/dist/extensions/pi-web-agent/src/commands/web-agent-config.ts +1 -1
- package/dist/extensions/pi-web-agent/src/extension.ts +1 -1
- package/dist/extensions/pi-web-agent/src/presentation/config-store.ts +6 -4
- package/dist/extensions/question/helpers.ts +3 -3
- package/dist/extensions/question/index.ts +2 -2
- package/dist/extensions/question/navigation.ts +2 -2
- package/dist/extensions/question/package.json +2 -2
- package/dist/extensions/question/question-list.ts +2 -2
- package/dist/extensions/question/tests/question-list.test.ts +2 -2
- package/dist/extensions/question/tui-adapter.ts +2 -2
- package/dist/extensions/question/types.ts +2 -2
- package/dist/extensions/question/ui-protocol.ts +2 -2
- package/dist/extensions/rtk.ts +2 -2
- package/dist/extensions/tokenin-onboarding.ts +2 -2
- package/dist/extensions/undo.ts +1 -1
- package/dist/extensions/web-agent-onboarding.ts +3 -3
- package/dist/extensions/workflow/adapter.ts +16 -8
- package/dist/extensions/workflow/extension.ts +1 -1
- package/dist/extensions/workflow/package.json +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +4 -0
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +2 -0
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/first-time-setup.d.ts +1 -1
- package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
- package/dist/modes/interactive/components/first-time-setup.js +19 -5
- package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
- package/dist/skills/caveman/SKILL.md +49 -0
- package/dist/skills/handoff-text/SKILL.md +13 -0
- package/dist/utils/thinking-tags.d.ts +7 -0
- package/dist/utils/thinking-tags.d.ts.map +1 -0
- package/dist/utils/thinking-tags.js +63 -0
- package/dist/utils/thinking-tags.js.map +1 -0
- package/docs/docs.json +4 -0
- package/docs/extensions.md +2 -0
- package/docs/settings.md +15 -0
- package/docs/shared-host-extensions.md +109 -0
- package/package.json +2 -2
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
writeArtifact,
|
|
13
13
|
writeMetadata,
|
|
14
14
|
} from "../../shared/artifacts.ts";
|
|
15
|
+
import { createChildTranscriptWriter, type ChildTranscriptWriter } from "../../shared/child-transcript.ts";
|
|
15
16
|
import {
|
|
16
17
|
type AgentProgress,
|
|
17
18
|
type ArtifactPaths,
|
|
@@ -43,12 +44,12 @@ import {
|
|
|
43
44
|
extractTextFromContent,
|
|
44
45
|
} from "../../shared/utils.ts";
|
|
45
46
|
import { buildSkillInjection, resolveSkillsWithFallback } from "../../agents/skills.ts";
|
|
47
|
+
import { buildAgentMemoryInjection } from "../../agents/agent-memory.ts";
|
|
46
48
|
import { evaluateCompletionMutationGuard } from "../shared/completion-guard.ts";
|
|
47
49
|
import { getSelesaiSpawnCommand } from "../shared/pi-spawn.ts";
|
|
48
50
|
import { createJsonlWriter } from "../../shared/jsonl-writer.ts";
|
|
49
51
|
import { attachPostExitStdioGuard, trySignalChild } from "../../shared/post-exit-stdio-guard.ts";
|
|
50
52
|
import { applyThinkingSuffix, buildPiArgs, cleanupTempDir } from "../shared/pi-args.ts";
|
|
51
|
-
import { createSpawnTimingMarkers, emitSpawnTiming } from "../shared/spawn-timing.ts";
|
|
52
53
|
import { readStructuredOutput } from "../shared/structured-output.ts";
|
|
53
54
|
import { captureSingleOutputSnapshot, formatSavedOutputReference, injectOutputPathSystemPrompt, resolveSingleOutput, validateFileOnlyOutputMode, type SingleOutputSnapshot } from "../shared/single-output.ts";
|
|
54
55
|
import {
|
|
@@ -68,6 +69,8 @@ import {
|
|
|
68
69
|
summarizeRecentMutatingFailures,
|
|
69
70
|
} from "../shared/long-running-guard.ts";
|
|
70
71
|
import { acceptanceFailureMessage, evaluateAcceptance, formatAcceptancePrompt, resolveEffectiveAcceptance, stripAcceptanceReport } from "../shared/acceptance.ts";
|
|
72
|
+
import { appendTurnBudgetSystemPrompt, formatTurnBudgetOutput, initialTurnBudgetState, shouldAbortForTurnBudget, turnBudgetExceededMessage, turnBudgetSoftNote, turnBudgetState } from "../shared/turn-budget.ts";
|
|
73
|
+
import { initialToolBudgetState, toolBudgetState } from "../shared/tool-budget.ts";
|
|
71
74
|
|
|
72
75
|
const artifactOutputByResult = new WeakMap<SingleResult, string>();
|
|
73
76
|
const acceptanceOutputByResult = new WeakMap<SingleResult, string>();
|
|
@@ -99,7 +102,7 @@ function resolveAttemptTimeout(options: RunSyncOptions): { timeoutMs: number; re
|
|
|
99
102
|
};
|
|
100
103
|
}
|
|
101
104
|
|
|
102
|
-
function
|
|
105
|
+
function buildSkippedAcceptanceLedger(acceptance: ResolvedAcceptanceConfig, input: { id: string; message: string }): AcceptanceLedger {
|
|
103
106
|
return {
|
|
104
107
|
status: acceptance.level === "none" ? "not-required" : "rejected",
|
|
105
108
|
explicit: acceptance.explicit,
|
|
@@ -108,7 +111,7 @@ function buildTimedOutAcceptanceLedger(acceptance: ResolvedAcceptanceConfig): Ac
|
|
|
108
111
|
criteria: acceptance.criteria,
|
|
109
112
|
runtimeChecks: acceptance.level === "none"
|
|
110
113
|
? []
|
|
111
|
-
: [{ id:
|
|
114
|
+
: [{ id: input.id, status: "failed", message: input.message }],
|
|
112
115
|
verifyRuns: [],
|
|
113
116
|
};
|
|
114
117
|
}
|
|
@@ -176,20 +179,22 @@ async function runSingleAttempt(
|
|
|
176
179
|
skillsWarning?: string;
|
|
177
180
|
jsonlPath?: string;
|
|
178
181
|
artifactPaths?: ArtifactPaths;
|
|
182
|
+
transcriptWriter?: ChildTranscriptWriter;
|
|
179
183
|
attemptNotes: string[];
|
|
180
184
|
outputSnapshot?: SingleOutputSnapshot;
|
|
181
185
|
originalTask?: string;
|
|
182
186
|
},
|
|
183
187
|
): Promise<SingleResult> {
|
|
184
|
-
const
|
|
185
|
-
|
|
188
|
+
const effectiveThinking = options.thinkingOverride ?? agent.thinking;
|
|
189
|
+
const modelArg = applyThinkingSuffix(model, effectiveThinking, options.thinkingOverride !== undefined);
|
|
190
|
+
const { args, env: sharedEnv, tempDir } = buildPiArgs({
|
|
186
191
|
baseArgs: ["--offline", "--mode", "json", "-p"],
|
|
187
192
|
task,
|
|
188
193
|
sessionEnabled: shared.sessionEnabled,
|
|
189
194
|
sessionDir: options.sessionDir,
|
|
190
195
|
sessionFile: options.sessionFile,
|
|
191
|
-
model,
|
|
192
|
-
thinking:
|
|
196
|
+
model: modelArg,
|
|
197
|
+
thinking: effectiveThinking,
|
|
193
198
|
systemPromptMode: agent.systemPromptMode,
|
|
194
199
|
inheritProjectContext: agent.inheritProjectContext,
|
|
195
200
|
inheritSkills: agent.inheritSkills,
|
|
@@ -197,7 +202,7 @@ async function runSingleAttempt(
|
|
|
197
202
|
tools: agent.tools,
|
|
198
203
|
extensions: agent.extensions,
|
|
199
204
|
subagentOnlyExtensions: agent.subagentOnlyExtensions,
|
|
200
|
-
systemPrompt: shared.systemPrompt,
|
|
205
|
+
systemPrompt: appendTurnBudgetSystemPrompt(shared.systemPrompt, options.turnBudget),
|
|
201
206
|
mcpDirectTools: agent.mcpDirectTools,
|
|
202
207
|
cwd: options.cwd ?? runtimeCwd,
|
|
203
208
|
promptFileStem: agent.name,
|
|
@@ -208,11 +213,12 @@ async function runSingleAttempt(
|
|
|
208
213
|
childIndex: options.index ?? 0,
|
|
209
214
|
parentEventSink: options.nestedRoute?.eventSink,
|
|
210
215
|
parentControlInbox: options.nestedRoute?.controlInbox,
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
+
parentRootRunId: options.nestedRoute?.rootRunId,
|
|
217
|
+
parentCapabilityToken: options.nestedRoute?.capabilityToken,
|
|
218
|
+
parentSessionId: options.parentSessionId,
|
|
219
|
+
structuredOutput: options.structuredOutput,
|
|
220
|
+
toolBudget: options.toolBudget,
|
|
221
|
+
});
|
|
216
222
|
|
|
217
223
|
const result: SingleResult = {
|
|
218
224
|
agent: agent.name,
|
|
@@ -222,8 +228,11 @@ async function runSingleAttempt(
|
|
|
222
228
|
usage: emptyUsage(),
|
|
223
229
|
model: modelArg,
|
|
224
230
|
artifactPaths: shared.artifactPaths,
|
|
231
|
+
transcriptPath: shared.transcriptWriter ? shared.artifactPaths?.transcriptPath : undefined,
|
|
225
232
|
skills: shared.resolvedSkillNames,
|
|
226
233
|
skillsWarning: shared.skillsWarning,
|
|
234
|
+
...(options.turnBudget ? { turnBudget: initialTurnBudgetState(options.turnBudget) } : {}),
|
|
235
|
+
...(options.toolBudget ? { toolBudget: initialToolBudgetState(options.toolBudget) } : {}),
|
|
227
236
|
};
|
|
228
237
|
const startTime = Date.now();
|
|
229
238
|
if (options.structuredOutput) {
|
|
@@ -279,24 +288,7 @@ async function runSingleAttempt(
|
|
|
279
288
|
let observedMutationAttempt = false;
|
|
280
289
|
|
|
281
290
|
const exitCode = await new Promise<number>((resolve) => {
|
|
282
|
-
const markers = createSpawnTimingMarkers();
|
|
283
291
|
const spawnSpec = getSelesaiSpawnCommand(args);
|
|
284
|
-
emitSpawnTiming({
|
|
285
|
-
eventsPath: shared.jsonlPath,
|
|
286
|
-
marker: "spawn_start",
|
|
287
|
-
markers,
|
|
288
|
-
runId: options.runId,
|
|
289
|
-
stepIndex: options.index ?? 0,
|
|
290
|
-
agent: agent.name,
|
|
291
|
-
});
|
|
292
|
-
emitSpawnTiming({
|
|
293
|
-
eventsPath: shared.jsonlPath,
|
|
294
|
-
marker: "spawn_command_resolved",
|
|
295
|
-
markers,
|
|
296
|
-
runId: options.runId,
|
|
297
|
-
stepIndex: options.index ?? 0,
|
|
298
|
-
agent: agent.name,
|
|
299
|
-
});
|
|
300
292
|
const proc = spawn(spawnSpec.command, spawnSpec.args, {
|
|
301
293
|
cwd: options.cwd ?? runtimeCwd,
|
|
302
294
|
env: spawnEnv,
|
|
@@ -304,8 +296,6 @@ async function runSingleAttempt(
|
|
|
304
296
|
windowsHide: true,
|
|
305
297
|
});
|
|
306
298
|
const jsonlWriter = createJsonlWriter(shared.jsonlPath, proc.stdout);
|
|
307
|
-
let firstEventEmitted = false;
|
|
308
|
-
let firstJsonlEventEmitted = false;
|
|
309
299
|
let buf = "";
|
|
310
300
|
let processClosed = false;
|
|
311
301
|
let settled = false;
|
|
@@ -318,6 +308,19 @@ async function runSingleAttempt(
|
|
|
318
308
|
let timeoutTimer: NodeJS.Timeout | undefined;
|
|
319
309
|
let timeoutTerminationTimer: NodeJS.Timeout | undefined;
|
|
320
310
|
let timeoutHardKillTimer: NodeJS.Timeout | undefined;
|
|
311
|
+
let turnBudgetSoftReached = false;
|
|
312
|
+
let turnBudgetTerminationTimer: NodeJS.Timeout | undefined;
|
|
313
|
+
let turnBudgetHardKillTimer: NodeJS.Timeout | undefined;
|
|
314
|
+
const clearTurnBudgetTimers = () => {
|
|
315
|
+
if (turnBudgetTerminationTimer) {
|
|
316
|
+
clearTimeout(turnBudgetTerminationTimer);
|
|
317
|
+
turnBudgetTerminationTimer = undefined;
|
|
318
|
+
}
|
|
319
|
+
if (turnBudgetHardKillTimer) {
|
|
320
|
+
clearTimeout(turnBudgetHardKillTimer);
|
|
321
|
+
turnBudgetHardKillTimer = undefined;
|
|
322
|
+
}
|
|
323
|
+
};
|
|
321
324
|
const clearTimeoutTimers = () => {
|
|
322
325
|
if (timeoutTimer) {
|
|
323
326
|
clearTimeout(timeoutTimer);
|
|
@@ -401,6 +404,7 @@ async function runSingleAttempt(
|
|
|
401
404
|
clearFinalDrainTimers();
|
|
402
405
|
clearStdioGuard();
|
|
403
406
|
clearTimeoutTimers();
|
|
407
|
+
clearTurnBudgetTimers();
|
|
404
408
|
if (activityTimer) {
|
|
405
409
|
clearInterval(activityTimer);
|
|
406
410
|
activityTimer = undefined;
|
|
@@ -474,6 +478,50 @@ async function runSingleAttempt(
|
|
|
474
478
|
}));
|
|
475
479
|
return true;
|
|
476
480
|
};
|
|
481
|
+
const requestTurnBudgetAbort = (turnCount: number) => {
|
|
482
|
+
const budget = options.turnBudget;
|
|
483
|
+
if (!budget || result.timedOut || result.turnBudgetExceeded || interruptedByControl || processClosed || settled || detached) return;
|
|
484
|
+
const message = turnBudgetExceededMessage(budget, turnCount);
|
|
485
|
+
result.turnBudgetExceeded = true;
|
|
486
|
+
result.wrapUpRequested = true;
|
|
487
|
+
result.turnBudget = turnBudgetState(budget, turnCount, true);
|
|
488
|
+
result.error = message;
|
|
489
|
+
result.finalOutput = message;
|
|
490
|
+
progress.status = "failed";
|
|
491
|
+
progress.error = message;
|
|
492
|
+
progress.durationMs = Date.now() - startTime;
|
|
493
|
+
fireUpdate();
|
|
494
|
+
trySignalChild(proc, "SIGINT");
|
|
495
|
+
turnBudgetTerminationTimer = setTimeout(() => {
|
|
496
|
+
if (processClosed || settled || detached || result.timedOut) return;
|
|
497
|
+
trySignalChild(proc, "SIGTERM");
|
|
498
|
+
}, 1000);
|
|
499
|
+
turnBudgetTerminationTimer.unref?.();
|
|
500
|
+
turnBudgetHardKillTimer = setTimeout(() => {
|
|
501
|
+
if (processClosed || settled || detached || result.timedOut) return;
|
|
502
|
+
trySignalChild(proc, "SIGKILL");
|
|
503
|
+
}, 4000);
|
|
504
|
+
turnBudgetHardKillTimer.unref?.();
|
|
505
|
+
};
|
|
506
|
+
|
|
507
|
+
const updateTurnBudget = (turnCount: number, terminalAssistantStop: boolean) => {
|
|
508
|
+
const budget = options.turnBudget;
|
|
509
|
+
if (!budget || result.timedOut || result.turnBudgetExceeded) return;
|
|
510
|
+
if (turnCount < budget.maxTurns) {
|
|
511
|
+
result.turnBudget = { ...budget, outcome: "within-budget", turnCount };
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
if (!turnBudgetSoftReached) {
|
|
515
|
+
turnBudgetSoftReached = true;
|
|
516
|
+
result.wrapUpRequested = true;
|
|
517
|
+
appendRecentOutput(progress, [turnBudgetSoftNote(budget, turnCount)]);
|
|
518
|
+
}
|
|
519
|
+
result.turnBudget = turnBudgetState(budget, turnCount, false);
|
|
520
|
+
if (shouldAbortForTurnBudget(budget, turnCount, terminalAssistantStop)) {
|
|
521
|
+
requestTurnBudgetAbort(turnCount);
|
|
522
|
+
}
|
|
523
|
+
};
|
|
524
|
+
|
|
477
525
|
const updateActivityState = (now: number): boolean => {
|
|
478
526
|
if (!controlConfig.enabled) return false;
|
|
479
527
|
const idleState = deriveActivityState({
|
|
@@ -514,35 +562,22 @@ async function runSingleAttempt(
|
|
|
514
562
|
const fireUpdate = () => {
|
|
515
563
|
if (!options.onUpdate || processClosed) return;
|
|
516
564
|
progress.durationMs = Date.now() - startTime;
|
|
517
|
-
const output = result.timedOut && result.finalOutput ? result.finalOutput : getFinalOutput(result.messages);
|
|
565
|
+
const output = (result.timedOut || result.turnBudgetExceeded) && result.finalOutput ? result.finalOutput : getFinalOutput(result.messages);
|
|
518
566
|
emitUpdateSnapshot(output || "(running...)");
|
|
519
567
|
};
|
|
520
568
|
|
|
521
|
-
const emitTiming = (marker: import("../shared/spawn-timing.ts").SpawnTimingMarker) => {
|
|
522
|
-
emitSpawnTiming({
|
|
523
|
-
eventsPath: shared.jsonlPath,
|
|
524
|
-
marker,
|
|
525
|
-
markers,
|
|
526
|
-
runId: options.runId,
|
|
527
|
-
stepIndex: options.index ?? 0,
|
|
528
|
-
agent: agent.name,
|
|
529
|
-
});
|
|
530
|
-
};
|
|
531
|
-
|
|
532
569
|
const processLine = (line: string) => {
|
|
533
570
|
if (!line.trim()) return;
|
|
534
571
|
jsonlWriter.writeLine(line);
|
|
535
572
|
let evt: { type?: string; message?: Message; toolName?: string; args?: unknown };
|
|
536
573
|
try {
|
|
537
574
|
evt = JSON.parse(line) as { type?: string; message?: Message; toolName?: string; args?: unknown };
|
|
538
|
-
if (!firstJsonlEventEmitted) {
|
|
539
|
-
firstJsonlEventEmitted = true;
|
|
540
|
-
emitTiming("child_first_jsonl_event");
|
|
541
|
-
}
|
|
542
575
|
} catch {
|
|
576
|
+
shared.transcriptWriter?.writeStdoutLine(line);
|
|
543
577
|
// Non-JSON stdout lines are expected; only structured events are parsed.
|
|
544
578
|
return;
|
|
545
579
|
}
|
|
580
|
+
shared.transcriptWriter?.writeChildEvent(evt);
|
|
546
581
|
|
|
547
582
|
const now = Date.now();
|
|
548
583
|
progress.durationMs = now - startTime;
|
|
@@ -553,10 +588,16 @@ async function runSingleAttempt(
|
|
|
553
588
|
const toolArgs = evt.args && typeof evt.args === "object" && !Array.isArray(evt.args)
|
|
554
589
|
? evt.args as Record<string, unknown>
|
|
555
590
|
: {};
|
|
591
|
+
let shouldDetachForBlockingIntercom = false;
|
|
556
592
|
if (options.allowIntercomDetach && (evt.toolName === "intercom" || evt.toolName === "contact_supervisor")) {
|
|
557
593
|
intercomStarted = true;
|
|
594
|
+
shouldDetachForBlockingIntercom = (evt.toolName === "intercom" && toolArgs.action === "ask")
|
|
595
|
+
|| (evt.toolName === "contact_supervisor" && (toolArgs.reason === "need_decision" || toolArgs.reason === "interview_request"));
|
|
558
596
|
}
|
|
559
597
|
progress.toolCount++;
|
|
598
|
+
if (options.toolBudget) {
|
|
599
|
+
result.toolBudget = toolBudgetState(options.toolBudget, progress.toolCount);
|
|
600
|
+
}
|
|
560
601
|
progress.currentTool = evt.toolName;
|
|
561
602
|
progress.currentToolArgs = extractToolArgsPreview(toolArgs);
|
|
562
603
|
progress.currentToolStartedAt = now;
|
|
@@ -565,6 +606,9 @@ async function runSingleAttempt(
|
|
|
565
606
|
observedMutationAttempt = observedMutationAttempt || mutates;
|
|
566
607
|
pendingToolResult = { tool: evt.toolName ?? "tool", path: progress.currentPath, mutates, startedAt: now };
|
|
567
608
|
fireUpdate();
|
|
609
|
+
if (shouldDetachForBlockingIntercom && !detached && !processClosed) {
|
|
610
|
+
detachForIntercom();
|
|
611
|
+
}
|
|
568
612
|
}
|
|
569
613
|
|
|
570
614
|
if (evt.type === "tool_execution_end") {
|
|
@@ -587,6 +631,11 @@ async function runSingleAttempt(
|
|
|
587
631
|
if (evt.message.role === "assistant") {
|
|
588
632
|
result.usage.turns++;
|
|
589
633
|
progress.turnCount = result.usage.turns;
|
|
634
|
+
const stopReason = (evt.message as { stopReason?: string }).stopReason;
|
|
635
|
+
const hasToolCall = Array.isArray(evt.message.content)
|
|
636
|
+
&& evt.message.content.some((part) => (part as { type?: string }).type === "toolCall");
|
|
637
|
+
const terminalAssistantStop = stopReason === "stop" && !hasToolCall;
|
|
638
|
+
updateTurnBudget(result.usage.turns, terminalAssistantStop);
|
|
590
639
|
const u = evt.message.usage;
|
|
591
640
|
if (u) {
|
|
592
641
|
result.usage.input += u.input || 0;
|
|
@@ -601,10 +650,7 @@ async function runSingleAttempt(
|
|
|
601
650
|
const assistantText = extractTextFromContent(evt.message.content);
|
|
602
651
|
appendRecentOutput(progress, assistantText.split("\n").slice(-10));
|
|
603
652
|
// Final assistant message: start the exit drain window.
|
|
604
|
-
|
|
605
|
-
const hasToolCall = Array.isArray(evt.message.content)
|
|
606
|
-
&& evt.message.content.some((part) => (part as { type?: string }).type === "toolCall");
|
|
607
|
-
if (stopReason === "stop" && !hasToolCall) {
|
|
653
|
+
if (terminalAssistantStop) {
|
|
608
654
|
if (!evt.message.errorMessage && assistantText.trim()) assistantError = undefined;
|
|
609
655
|
cleanTerminalAssistantStopReceived ||= !evt.message.errorMessage;
|
|
610
656
|
startFinalDrain();
|
|
@@ -617,6 +663,10 @@ async function runSingleAttempt(
|
|
|
617
663
|
if (evt.type === "tool_result_end" && evt.message) {
|
|
618
664
|
result.messages.push(evt.message);
|
|
619
665
|
const resultText = extractTextFromContent(evt.message.content);
|
|
666
|
+
if (options.toolBudget && pendingToolResult && resultText.includes("Tool budget hard limit reached")) {
|
|
667
|
+
result.toolBudgetBlocked = true;
|
|
668
|
+
result.toolBudget = toolBudgetState(options.toolBudget, progress.toolCount, pendingToolResult.tool);
|
|
669
|
+
}
|
|
620
670
|
appendRecentOutput(progress, resultText.split("\n").slice(-10));
|
|
621
671
|
const toolSnapshot = pendingToolResult;
|
|
622
672
|
pendingToolResult = undefined;
|
|
@@ -685,20 +735,12 @@ async function runSingleAttempt(
|
|
|
685
735
|
|
|
686
736
|
const clearStdioGuard = attachPostExitStdioGuard(proc, { idleMs: 2000, hardMs: 8000 });
|
|
687
737
|
proc.stdout.on("data", (d) => {
|
|
688
|
-
if (!firstEventEmitted) {
|
|
689
|
-
firstEventEmitted = true;
|
|
690
|
-
emitTiming("child_first_event");
|
|
691
|
-
}
|
|
692
738
|
buf += d.toString();
|
|
693
739
|
const lines = buf.split("\n");
|
|
694
740
|
buf = lines.pop() || "";
|
|
695
741
|
lines.forEach(processLine);
|
|
696
742
|
});
|
|
697
743
|
proc.stderr.on("data", (d) => {
|
|
698
|
-
if (!firstEventEmitted) {
|
|
699
|
-
firstEventEmitted = true;
|
|
700
|
-
emitTiming("child_first_event");
|
|
701
|
-
}
|
|
702
744
|
stderrBuf += d.toString();
|
|
703
745
|
});
|
|
704
746
|
proc.on("exit", () => {
|
|
@@ -712,18 +754,38 @@ async function runSingleAttempt(
|
|
|
712
754
|
// JSONL artifact flush is best effort.
|
|
713
755
|
});
|
|
714
756
|
cleanupTempDir(tempDir);
|
|
715
|
-
if (detached) {
|
|
716
|
-
finish(-2);
|
|
717
|
-
return;
|
|
718
|
-
}
|
|
719
|
-
processClosed = true;
|
|
720
757
|
if (buf.trim()) processLine(buf);
|
|
758
|
+
if (stderrBuf.trim()) shared.transcriptWriter?.writeStderrText(stderrBuf);
|
|
721
759
|
if (!result.error && assistantError) result.error = assistantError;
|
|
722
760
|
const forcedDrainAfterFinalSuccess = forcedTerminationSignal && cleanTerminalAssistantStopReceived && !result.error;
|
|
723
761
|
if (code !== 0 && stderrBuf.trim() && !result.error && !forcedDrainAfterFinalSuccess) {
|
|
724
762
|
result.error = stderrBuf.trim();
|
|
725
763
|
}
|
|
726
764
|
const finalCode = forcedDrainAfterFinalSuccess ? 0 : forcedTerminationSignal || signal ? (code ?? 1) : (code ?? 0);
|
|
765
|
+
if (detached) {
|
|
766
|
+
result.exitCode = result.error && finalCode === 0 ? 1 : finalCode;
|
|
767
|
+
progress.status = result.exitCode === 0 ? "completed" : "failed";
|
|
768
|
+
progress.durationMs = Date.now() - startTime;
|
|
769
|
+
if (result.error) progress.error = result.error;
|
|
770
|
+
result.progressSummary = {
|
|
771
|
+
toolCount: progress.toolCount,
|
|
772
|
+
tokens: progress.tokens,
|
|
773
|
+
durationMs: progress.durationMs,
|
|
774
|
+
};
|
|
775
|
+
const finalOutput = getFinalOutput(result.messages);
|
|
776
|
+
result.finalOutput = finalOutput.trim() || result.error || result.finalOutput || "Detached child exited without final output.";
|
|
777
|
+
if (result.artifactPaths && options.artifactConfig?.enabled !== false && options.artifactConfig?.includeOutput !== false) {
|
|
778
|
+
try {
|
|
779
|
+
writeArtifact(result.artifactPaths.outputPath, result.finalOutput);
|
|
780
|
+
} catch {
|
|
781
|
+
// Detached children may outlive test/temp cleanup; recovered status is best-effort.
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
options.onDetachedExit?.(snapshotResult(result, snapshotProgress(progress)));
|
|
785
|
+
finish(-2);
|
|
786
|
+
return;
|
|
787
|
+
}
|
|
788
|
+
processClosed = true;
|
|
727
789
|
finish(finalCode);
|
|
728
790
|
});
|
|
729
791
|
proc.on("error", (error) => {
|
|
@@ -733,6 +795,7 @@ async function runSingleAttempt(
|
|
|
733
795
|
// JSONL artifact flush is best effort.
|
|
734
796
|
});
|
|
735
797
|
cleanupTempDir(tempDir);
|
|
798
|
+
if (stderrBuf.trim()) shared.transcriptWriter?.writeStderrText(stderrBuf);
|
|
736
799
|
if (!result.error) {
|
|
737
800
|
result.error = error instanceof Error ? error.message : String(error);
|
|
738
801
|
}
|
|
@@ -815,6 +878,16 @@ async function runSingleAttempt(
|
|
|
815
878
|
: `${errInfo.errorType} failed with exit code ${errInfo.exitCode}`;
|
|
816
879
|
}
|
|
817
880
|
}
|
|
881
|
+
if (result.exitCode === 0 && !result.error) {
|
|
882
|
+
const finalText = getFinalOutput(result.messages);
|
|
883
|
+
const missingStructuredOutput = options.structuredOutput
|
|
884
|
+
? !existsSync(options.structuredOutput.outputPath)
|
|
885
|
+
: false;
|
|
886
|
+
if (!finalText?.trim() && (!options.structuredOutput || missingStructuredOutput)) {
|
|
887
|
+
result.exitCode = 1;
|
|
888
|
+
result.error = "Subagent produced no output (possible model cold-start or empty response).";
|
|
889
|
+
}
|
|
890
|
+
}
|
|
818
891
|
if (options.structuredOutput && result.exitCode === 0 && !result.error) {
|
|
819
892
|
const structured = readStructuredOutput({
|
|
820
893
|
schema: options.structuredOutput.schema,
|
|
@@ -853,6 +926,11 @@ async function runSingleAttempt(
|
|
|
853
926
|
fullOutput = fullOutput.trim()
|
|
854
927
|
? `${timeoutMessage}\n\nPartial output before timeout:\n${fullOutput}`
|
|
855
928
|
: timeoutMessage;
|
|
929
|
+
} else if (result.turnBudgetExceeded && result.turnBudget) {
|
|
930
|
+
fullOutput = formatTurnBudgetOutput(turnBudgetExceededMessage(result.turnBudget, result.turnBudget.turnCount), fullOutput);
|
|
931
|
+
} else if (result.wrapUpRequested && result.turnBudget?.outcome === "wrap-up-requested") {
|
|
932
|
+
const note = turnBudgetSoftNote(result.turnBudget, result.turnBudget.wrapUpRequestedAtTurn ?? result.turnBudget.turnCount);
|
|
933
|
+
fullOutput = fullOutput.trim() ? `${note}\n\n${fullOutput}` : note;
|
|
856
934
|
}
|
|
857
935
|
const completionGuard = result.exitCode === 0 && !result.error && agent.completionGuard !== false
|
|
858
936
|
? evaluateCompletionMutationGuard({
|
|
@@ -977,6 +1055,10 @@ export async function runSync(
|
|
|
977
1055
|
const skillInjection = buildSkillInjection(resolvedSkills);
|
|
978
1056
|
systemPrompt = systemPrompt ? `${systemPrompt}\n\n${skillInjection}` : skillInjection;
|
|
979
1057
|
}
|
|
1058
|
+
const memoryInjection = buildAgentMemoryInjection(agent, skillCwd);
|
|
1059
|
+
if (memoryInjection) {
|
|
1060
|
+
systemPrompt = systemPrompt ? `${systemPrompt}\n\n${memoryInjection}` : memoryInjection;
|
|
1061
|
+
}
|
|
980
1062
|
systemPrompt = injectOutputPathSystemPrompt(systemPrompt, options.outputPath);
|
|
981
1063
|
|
|
982
1064
|
const candidates = buildModelCandidates(
|
|
@@ -984,6 +1066,7 @@ export async function runSync(
|
|
|
984
1066
|
agent.fallbackModels,
|
|
985
1067
|
options.availableModels,
|
|
986
1068
|
options.preferredModelProvider,
|
|
1069
|
+
{ scope: options.modelScope },
|
|
987
1070
|
);
|
|
988
1071
|
const attemptedModels: string[] = [];
|
|
989
1072
|
const modelAttempts: ModelAttempt[] = [];
|
|
@@ -994,6 +1077,7 @@ export async function runSync(
|
|
|
994
1077
|
|
|
995
1078
|
let artifactPathsResult: ArtifactPaths | undefined;
|
|
996
1079
|
let jsonlPath: string | undefined;
|
|
1080
|
+
let transcriptWriter: ChildTranscriptWriter | undefined;
|
|
997
1081
|
if (options.artifactsDir && options.artifactConfig?.enabled !== false) {
|
|
998
1082
|
artifactPathsResult = getArtifactPaths(options.artifactsDir, options.runId, agentName, options.index);
|
|
999
1083
|
ensureArtifactsDir(options.artifactsDir);
|
|
@@ -1003,13 +1087,23 @@ export async function runSync(
|
|
|
1003
1087
|
if (options.artifactConfig?.includeJsonl !== false) {
|
|
1004
1088
|
jsonlPath = artifactPathsResult.jsonlPath;
|
|
1005
1089
|
}
|
|
1090
|
+
if (options.artifactConfig?.includeTranscript !== false) {
|
|
1091
|
+
transcriptWriter = createChildTranscriptWriter({
|
|
1092
|
+
transcriptPath: artifactPathsResult.transcriptPath,
|
|
1093
|
+
source: "foreground",
|
|
1094
|
+
runId: options.runId,
|
|
1095
|
+
agent: agentName,
|
|
1096
|
+
childIndex: options.index,
|
|
1097
|
+
cwd: options.cwd ?? runtimeCwd,
|
|
1098
|
+
});
|
|
1099
|
+
transcriptWriter.writeInitialUserMessage(taskWithAcceptance);
|
|
1100
|
+
}
|
|
1006
1101
|
}
|
|
1007
1102
|
|
|
1008
1103
|
let lastResult: SingleResult | undefined;
|
|
1009
1104
|
const modelsToTry = candidates.length > 0 ? candidates : [undefined];
|
|
1010
1105
|
for (let i = 0; i < modelsToTry.length; i++) {
|
|
1011
1106
|
const candidate = modelsToTry[i];
|
|
1012
|
-
if (candidate) attemptedModels.push(candidate);
|
|
1013
1107
|
const outputSnapshot = captureSingleOutputSnapshot(options.outputPath);
|
|
1014
1108
|
const result = await runSingleAttempt(runtimeCwd, agent, taskWithAcceptance, candidate, options, {
|
|
1015
1109
|
sessionEnabled,
|
|
@@ -1018,24 +1112,27 @@ export async function runSync(
|
|
|
1018
1112
|
skillsWarning: missingSkills.length > 0 ? `Skills not found: ${missingSkills.join(", ")}` : undefined,
|
|
1019
1113
|
jsonlPath,
|
|
1020
1114
|
artifactPaths: artifactPathsResult,
|
|
1115
|
+
transcriptWriter,
|
|
1021
1116
|
attemptNotes,
|
|
1022
1117
|
outputSnapshot,
|
|
1023
1118
|
originalTask: task,
|
|
1024
1119
|
});
|
|
1025
1120
|
lastResult = result;
|
|
1121
|
+
if (result.model) attemptedModels.push(result.model);
|
|
1122
|
+
else if (candidate) attemptedModels.push(candidate);
|
|
1026
1123
|
sumUsage(aggregateUsage, result.usage);
|
|
1027
1124
|
totalToolCount += result.progressSummary?.toolCount ?? 0;
|
|
1028
1125
|
totalDurationMs += result.progressSummary?.durationMs ?? 0;
|
|
1029
1126
|
const attemptSucceeded = result.exitCode === 0 && !result.error;
|
|
1030
1127
|
const attempt: ModelAttempt = {
|
|
1031
|
-
model:
|
|
1128
|
+
model: result.model ?? candidate ?? agent.model ?? "default",
|
|
1032
1129
|
success: attemptSucceeded,
|
|
1033
1130
|
exitCode: result.exitCode,
|
|
1034
1131
|
error: result.error,
|
|
1035
1132
|
usage: { ...result.usage },
|
|
1036
1133
|
};
|
|
1037
1134
|
modelAttempts.push(attempt);
|
|
1038
|
-
if (result.timedOut) {
|
|
1135
|
+
if (result.timedOut || result.turnBudgetExceeded) {
|
|
1039
1136
|
break;
|
|
1040
1137
|
}
|
|
1041
1138
|
if (attemptSucceeded) {
|
|
@@ -1071,6 +1168,9 @@ export async function runSync(
|
|
|
1071
1168
|
}
|
|
1072
1169
|
}
|
|
1073
1170
|
|
|
1171
|
+
if (transcriptWriter) result.transcriptPath = artifactPathsResult?.transcriptPath;
|
|
1172
|
+
if (transcriptWriter?.getError()) result.transcriptError = transcriptWriter.getError();
|
|
1173
|
+
|
|
1074
1174
|
if (artifactPathsResult && options.artifactConfig?.enabled !== false) {
|
|
1075
1175
|
result.artifactPaths = artifactPathsResult;
|
|
1076
1176
|
if (options.artifactConfig?.includeOutput !== false) {
|
|
@@ -1089,6 +1189,8 @@ export async function runSync(
|
|
|
1089
1189
|
durationMs: result.progressSummary?.durationMs,
|
|
1090
1190
|
toolCount: result.progressSummary?.toolCount,
|
|
1091
1191
|
error: result.error,
|
|
1192
|
+
...(transcriptWriter ? { transcriptPath: artifactPathsResult.transcriptPath } : {}),
|
|
1193
|
+
transcriptError: result.transcriptError,
|
|
1092
1194
|
skills: result.skills,
|
|
1093
1195
|
skillsWarning: result.skillsWarning,
|
|
1094
1196
|
timestamp: Date.now(),
|
|
@@ -1114,8 +1216,10 @@ export async function runSync(
|
|
|
1114
1216
|
}
|
|
1115
1217
|
|
|
1116
1218
|
result.acceptance = result.timedOut
|
|
1117
|
-
?
|
|
1118
|
-
:
|
|
1219
|
+
? buildSkippedAcceptanceLedger(effectiveAcceptance, { id: "timeout", message: "Acceptance was not evaluated because the subagent timed out." })
|
|
1220
|
+
: result.turnBudgetExceeded
|
|
1221
|
+
? buildSkippedAcceptanceLedger(effectiveAcceptance, { id: "turn-budget", message: "Acceptance was not evaluated because the subagent exceeded its turn budget." })
|
|
1222
|
+
: await evaluateAcceptance({
|
|
1119
1223
|
acceptance: effectiveAcceptance,
|
|
1120
1224
|
output: acceptanceOutputByResult.get(result) ?? result.finalOutput ?? "",
|
|
1121
1225
|
cwd: options.cwd ?? runtimeCwd,
|