one-code-extension 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +219 -219
- package/agents/general-purpose.md +2 -2
- package/docs/guide/README.md +2 -1
- package/docs/guide/bring-your-claude-code-setup.md +60 -9
- package/docs/guide/configuration.md +48 -14
- package/docs/guide/differences-from-claude-code.md +32 -23
- package/docs/guide/doctor.md +20 -13
- package/docs/guide/hooks.md +18 -3
- package/docs/guide/installation.md +27 -4
- package/docs/guide/permissions-modes-and-auto-mode.md +225 -49
- package/docs/guide/providers-and-models.md +137 -54
- package/docs/guide/reference.md +27 -15
- package/docs/guide/sessions-and-context.md +69 -16
- package/docs/guide/skills-plugins-and-mcp.md +57 -20
- package/docs/guide/subagents-and-workflows.md +95 -29
- package/docs/guide/tasks-and-background-work.md +101 -26
- package/docs/guide/terminal-interface.md +24 -12
- package/docs/guide/tools.md +46 -5
- package/docs/guide/troubleshooting.md +13 -9
- package/docs/guide/windows.md +66 -34
- package/extensions/artifacts/gallery.ts +227 -0
- package/extensions/artifacts/index.ts +288 -0
- package/extensions/artifacts/store.ts +570 -0
- package/extensions/artifacts/viewer.ts +199 -0
- package/extensions/ask-user/description.ts +67 -0
- package/extensions/ask-user/dialogs.ts +80 -0
- package/extensions/ask-user/index.ts +37 -33
- package/extensions/ask-user/questions.ts +32 -7
- package/extensions/ask-user/widget.ts +45 -25
- package/extensions/auto-mode/actions.ts +6 -0
- package/extensions/auto-mode/cache.ts +88 -0
- package/extensions/auto-mode/classifier-prompt.ts +5 -4
- package/extensions/auto-mode/classifier.ts +290 -65
- package/extensions/auto-mode/config.ts +72 -20
- package/extensions/auto-mode/decision-log.ts +2 -0
- package/extensions/auto-mode/defaults.ts +1 -1
- package/extensions/auto-mode/denials.ts +123 -0
- package/extensions/auto-mode/git-checkout-programs.ts +187 -0
- package/extensions/auto-mode/git-status-meta.ts +159 -0
- package/extensions/auto-mode/history.ts +189 -0
- package/extensions/auto-mode/instructions.ts +58 -52
- package/extensions/auto-mode/model-select.ts +159 -134
- package/extensions/auto-mode/paths.ts +57 -5
- package/extensions/auto-mode/pause.ts +57 -2
- package/extensions/auto-mode/prompt.ts +37 -21
- package/extensions/auto-mode/read-only-options.ts +724 -0
- package/extensions/auto-mode/resolved-paths-meta.ts +133 -0
- package/extensions/auto-mode/rules.ts +18 -1
- package/extensions/auto-mode/safety-floor.ts +361 -18
- package/extensions/auto-mode/setup-run.ts +20 -14
- package/extensions/auto-mode/shell-analysis.ts +764 -490
- package/extensions/auto-mode/shell-parse.ts +885 -0
- package/extensions/auto-mode/system-note.ts +33 -0
- package/extensions/auto-mode/transcript.ts +80 -51
- package/extensions/background/cron.ts +515 -0
- package/extensions/background/index.ts +514 -236
- package/extensions/background/loop-fire.ts +136 -0
- package/extensions/background/loop-preamble.ts +59 -0
- package/extensions/background/loop-skill.ts +163 -0
- package/extensions/background/monitor-batch.ts +53 -0
- package/extensions/background/noop-fold.ts +128 -0
- package/extensions/background/switch-guard.ts +52 -0
- package/extensions/background/wakeup.ts +159 -55
- package/extensions/bash/background.ts +53 -17
- package/extensions/bash/child.ts +7 -0
- package/extensions/bash/description.ts +188 -0
- package/extensions/bash/guards.ts +15 -67
- package/extensions/bash/index.ts +88 -35
- package/extensions/branding/compaction-keep.ts +63 -0
- package/extensions/branding/declined.ts +22 -0
- package/extensions/branding/index.ts +133 -9
- package/extensions/branding/prompt-editor.ts +53 -6
- package/extensions/branding/queued-edit.ts +31 -0
- package/extensions/branding/replaced-builtins.ts +68 -0
- package/extensions/branding/startup.ts +33 -71
- package/extensions/btw/index.ts +229 -71
- package/extensions/btw/panel.ts +228 -100
- package/extensions/btw/prompt.ts +41 -4
- package/extensions/claude-compat/index.ts +7 -11
- package/extensions/claude-context/index.ts +446 -58
- package/extensions/compaction/cut.ts +157 -0
- package/extensions/compaction/index.ts +216 -75
- package/extensions/compaction/kept-thinking.ts +62 -0
- package/extensions/compaction/prompt.ts +15 -12
- package/extensions/context-budget/index.ts +24 -5
- package/extensions/context-management/index.ts +25 -0
- package/extensions/doctor/build.ts +59 -8
- package/extensions/doctor/builtins.ts +84 -0
- package/extensions/doctor/cli.ts +7 -1
- package/extensions/doctor/compat.ts +88 -23
- package/extensions/doctor/dependencies.ts +41 -5
- package/extensions/doctor/fix-prompt.ts +9 -2
- package/extensions/doctor/index.ts +102 -58
- package/extensions/doctor/models.ts +102 -63
- package/extensions/doctor/presets.ts +42 -27
- package/extensions/doctor/report.ts +19 -2
- package/extensions/doctor/viewer.ts +49 -27
- package/extensions/effort/index.ts +72 -19
- package/extensions/effort/settings.ts +21 -0
- package/extensions/effort/slider.ts +24 -20
- package/extensions/exit/index.ts +32 -1
- package/extensions/file-tracker/index.ts +337 -26
- package/extensions/file-tracker/replay.ts +96 -10
- package/extensions/file-tracker/restore.ts +63 -0
- package/extensions/file-tracker/results.ts +66 -0
- package/extensions/file-tracker/shell-reads.ts +211 -0
- package/extensions/file-tracker/tracker.ts +32 -15
- package/extensions/footer/footer-line.ts +45 -24
- package/extensions/footer/index.ts +47 -2
- package/extensions/footer/pr.ts +34 -5
- package/extensions/hooks/compaction.ts +7 -0
- package/extensions/hooks/executor.ts +32 -30
- package/extensions/hooks/index.ts +198 -31
- package/extensions/hooks/matcher.ts +3 -0
- package/extensions/hooks/protocol.ts +41 -3
- package/extensions/hooks/settings.ts +50 -19
- package/extensions/hooks/subagent-bridge.ts +2 -0
- package/extensions/hooks/trust.ts +13 -5
- package/extensions/idle-compact/index.ts +119 -0
- package/extensions/idle-compact/policy.ts +143 -0
- package/extensions/init/index.ts +11 -10
- package/extensions/init/prompt.ts +25 -32
- package/extensions/interrupted/index.ts +13 -1
- package/extensions/kept-thinking/index.ts +27 -0
- package/extensions/lib/agent-cron.ts +130 -0
- package/extensions/lib/agent-loader.ts +15 -1
- package/extensions/lib/agent-view.ts +85 -0
- package/extensions/lib/anthropic-payload.ts +82 -1
- package/extensions/lib/anthropic-server-call.ts +230 -0
- package/extensions/lib/anthropic-server-tools.ts +485 -0
- package/extensions/lib/app-launch.mjs +94 -0
- package/extensions/lib/argument-hints.ts +190 -0
- package/extensions/lib/atomic-write.ts +6 -2
- package/extensions/lib/auto-memory.ts +75 -0
- package/extensions/lib/bash-parser.ts +84 -0
- package/extensions/lib/btw-fork.ts +93 -0
- package/extensions/lib/child-extensions.ts +42 -0
- package/extensions/lib/child-writes.ts +45 -0
- package/extensions/lib/claude-context.ts +515 -100
- package/extensions/lib/claude-external-includes.ts +68 -0
- package/extensions/lib/claude-id.ts +22 -0
- package/extensions/lib/claude-rules.ts +323 -0
- package/extensions/lib/claude-settings.ts +76 -4
- package/extensions/lib/compaction-boundary.ts +36 -0
- package/extensions/lib/compaction-keep.mjs +83 -0
- package/extensions/lib/config-mode.ts +112 -0
- package/extensions/lib/consent-dialogs.ts +63 -0
- package/extensions/lib/consent-preview.ts +5 -1
- package/extensions/lib/consent-stores.ts +48 -0
- package/extensions/lib/context-facts.ts +78 -0
- package/extensions/lib/context-stack.ts +81 -0
- package/extensions/lib/deferred.ts +219 -25
- package/extensions/lib/dock-rows.ts +60 -0
- package/extensions/lib/empty-tool-result.ts +27 -0
- package/extensions/lib/environment-block.ts +76 -0
- package/extensions/lib/fetch-timeout.ts +24 -6
- package/extensions/{system-prompt → lib}/git-status.ts +51 -13
- package/extensions/lib/git.ts +75 -13
- package/extensions/lib/grammars/LICENSE-tree-sitter-bash +21 -0
- package/extensions/lib/grammars/README.md +2 -0
- package/extensions/lib/grammars/tree-sitter-bash.wasm +0 -0
- package/extensions/lib/guide-docs.ts +45 -0
- package/extensions/lib/headless-output.ts +46 -0
- package/extensions/lib/hook-gate.ts +7 -7
- package/extensions/lib/interrupt.ts +20 -4
- package/extensions/lib/key-input.ts +455 -0
- package/extensions/lib/keys.ts +14 -1
- package/extensions/lib/local-command.ts +47 -13
- package/extensions/lib/mcp-overrides.ts +1 -1
- package/extensions/lib/mcp-share.ts +46 -0
- package/extensions/lib/memory-content.ts +146 -0
- package/extensions/lib/memory-index.ts +18 -0
- package/extensions/lib/memory.ts +134 -123
- package/extensions/lib/model-catalog/huggingface.json +174 -0
- package/extensions/lib/model-catalog/models-dev.json +18297 -0
- package/extensions/lib/model-catalog/openrouter.json +5252 -0
- package/extensions/lib/model-catalog-data.ts +513 -0
- package/extensions/lib/model-catalog.ts +462 -0
- package/extensions/lib/model-choice-warnings.ts +137 -0
- package/extensions/lib/model-pairings.ts +152 -0
- package/extensions/{auto-mode → lib}/model-picker.ts +26 -43
- package/extensions/lib/model-policy.ts +112 -15
- package/extensions/lib/model-tier.ts +283 -355
- package/extensions/lib/model-unusable.ts +1 -1
- package/extensions/lib/newer-model.ts +100 -0
- package/extensions/lib/notices.ts +87 -0
- package/extensions/lib/notifications.ts +308 -64
- package/extensions/lib/one-code-settings.ts +74 -8
- package/extensions/lib/open-browser.ts +63 -0
- package/extensions/lib/openrouter-generation.ts +94 -0
- package/extensions/lib/operation-deadline.ts +30 -0
- package/extensions/lib/original-command.ts +4 -4
- package/extensions/lib/package-version.ts +1 -1
- package/extensions/lib/panel-focus.ts +134 -0
- package/extensions/lib/paths.ts +17 -2
- package/extensions/lib/permission-gate.ts +72 -6
- package/extensions/lib/persisted-output.ts +60 -8
- package/extensions/lib/pi-ai-estimate.ts +19 -3
- package/extensions/lib/pi-version.ts +21 -2
- package/extensions/lib/plan-mode-channels.ts +20 -5
- package/extensions/lib/plugins.ts +26 -17
- package/extensions/lib/powershell-parse-script.ts +208 -0
- package/extensions/lib/powershell-parser.ts +344 -0
- package/extensions/lib/process-tree.ts +131 -8
- package/extensions/lib/prompt-options.ts +82 -0
- package/extensions/lib/queued-delivery.ts +44 -0
- package/extensions/lib/reminders.ts +364 -58
- package/extensions/lib/replaced-builtins.mjs +199 -0
- package/extensions/lib/replay-call.ts +70 -0
- package/extensions/lib/request-replay.ts +439 -0
- package/extensions/lib/scratchpad.ts +81 -14
- package/extensions/lib/send-now-channel.ts +7 -0
- package/extensions/lib/session-model-tier.ts +51 -0
- package/extensions/lib/session-work.ts +64 -0
- package/extensions/lib/settings-channels.ts +4 -4
- package/extensions/lib/shell-exit-semantics.ts +170 -0
- package/extensions/lib/shell-quote.ts +11 -0
- package/extensions/lib/shell-result.ts +70 -0
- package/extensions/lib/shell-spawn.ts +70 -6
- package/extensions/lib/shell-tool.ts +75 -25
- package/extensions/lib/side-call-cache.ts +124 -0
- package/extensions/lib/side-call-run.ts +96 -0
- package/extensions/lib/side-call-usage.ts +38 -0
- package/extensions/lib/side-call.ts +13 -1
- package/extensions/lib/single-flight.ts +18 -0
- package/extensions/lib/skill-body.ts +42 -0
- package/extensions/lib/skill-scan.ts +63 -24
- package/extensions/lib/spill-file.ts +140 -0
- package/extensions/lib/subagent-handback.ts +113 -0
- package/extensions/lib/system-role.ts +156 -0
- package/extensions/lib/terminal-text.ts +114 -0
- package/extensions/lib/text-width.ts +47 -16
- package/extensions/lib/timer-ops.ts +20 -0
- package/extensions/lib/tool-additions.ts +149 -0
- package/extensions/lib/tool-call-corruption.ts +134 -0
- package/extensions/lib/tool-path.ts +66 -0
- package/extensions/lib/tool-variants.ts +69 -0
- package/extensions/lib/tui-render.ts +255 -27
- package/extensions/lib/turn-budget-layout.ts +143 -0
- package/extensions/lib/update-check.mjs +15 -2
- package/extensions/lib/usage-bus.ts +1 -1
- package/extensions/lib/user-denial.ts +38 -0
- package/extensions/lib/workspace-channel.ts +16 -0
- package/extensions/lib/worktree-channel.ts +31 -3
- package/extensions/lib/worktree-isolation.ts +40 -10
- package/extensions/lsp/client.ts +8 -9
- package/extensions/lsp/index.ts +70 -4
- package/extensions/lsp/keep-alive.ts +1 -1
- package/extensions/lsp/trust.ts +119 -0
- package/extensions/lsp/watcher.ts +1 -1
- package/extensions/mcp/announce.ts +87 -5
- package/extensions/mcp/client.ts +161 -48
- package/extensions/mcp/config.ts +132 -8
- package/extensions/mcp/discovery.ts +19 -0
- package/extensions/mcp/index.ts +209 -71
- package/extensions/mcp/oauth/browser.ts +38 -17
- package/extensions/mcp/oauth/flow.ts +25 -17
- package/extensions/mcp/oauth/provider.ts +14 -8
- package/extensions/mcp/oauth/store.ts +34 -16
- package/extensions/mcp/panel/keys.ts +12 -11
- package/extensions/mcp/panel/render.ts +9 -6
- package/extensions/mcp/schema.ts +104 -5
- package/extensions/mcp/trust.ts +151 -67
- package/extensions/memory/entries.ts +23 -14
- package/extensions/memory/index.ts +134 -28
- package/extensions/memory/open-external.ts +33 -18
- package/extensions/memory/panel.ts +135 -26
- package/extensions/newer-model/index.ts +31 -0
- package/extensions/notebook/description.ts +18 -0
- package/extensions/notebook/index.ts +6 -5
- package/extensions/notebook/notebook.ts +1 -1
- package/extensions/permissions/index.ts +1300 -381
- package/extensions/permissions/matcher.ts +425 -74
- package/extensions/permissions/modes.ts +6 -4
- package/extensions/permissions/panel/host.ts +130 -0
- package/extensions/permissions/panel/keys.ts +48 -0
- package/extensions/permissions/panel/render.ts +450 -0
- package/extensions/permissions/panel/state.ts +550 -0
- package/extensions/permissions/powershell-cmdlets.ts +198 -0
- package/extensions/permissions/powershell-paths.ts +197 -0
- package/extensions/permissions/powershell-rules.ts +207 -280
- package/extensions/permissions/powershell-tree.ts +557 -0
- package/extensions/permissions/project-trust.ts +27 -11
- package/extensions/permissions/protected-paths.ts +14 -2
- package/extensions/permissions/session-grant.ts +6 -0
- package/extensions/permissions/settings.ts +166 -31
- package/extensions/permissions/subagent-gate.ts +25 -0
- package/extensions/permissions/workspace.ts +78 -0
- package/extensions/plan-mode/index.ts +156 -69
- package/extensions/plan-mode/reminder.ts +89 -21
- package/extensions/plan-mode/texts.ts +177 -0
- package/extensions/plan-mode/viewer.ts +92 -27
- package/extensions/plugins/counts.ts +3 -3
- package/extensions/plugins/index.ts +61 -46
- package/extensions/plugins/install/install.ts +16 -0
- package/extensions/plugins/marketplace/sync.ts +9 -3
- package/extensions/plugins/marketplace/types.ts +3 -1
- package/extensions/plugins/panel/keys.ts +21 -24
- package/extensions/plugins/panel/render.ts +12 -6
- package/extensions/plugins/shell-expand.ts +107 -0
- package/extensions/plugins/template.ts +32 -15
- package/extensions/powershell/child.ts +7 -0
- package/extensions/powershell/description.ts +38 -6
- package/extensions/powershell/guards.ts +1 -1
- package/extensions/powershell/index.ts +12 -7
- package/extensions/recap/index.ts +65 -60
- package/extensions/recap/prompt.ts +2 -2
- package/extensions/recap/scheduler.ts +3 -5
- package/extensions/search-tools/grep-merge.ts +39 -0
- package/extensions/search-tools/index.ts +0 -0
- package/extensions/send-now/chord.ts +62 -0
- package/extensions/send-now/index.ts +133 -0
- package/extensions/session-title/index.ts +3 -0
- package/extensions/session-title/title.ts +4 -1
- package/extensions/skill/code-review.ts +97 -0
- package/extensions/skill/index.ts +421 -101
- package/extensions/skill/invoke.ts +128 -18
- package/extensions/skill/listing.ts +133 -9
- package/extensions/skill/panel/keys.ts +15 -16
- package/extensions/skill/panel/render.ts +5 -2
- package/extensions/skill/panel/state.ts +12 -1
- package/extensions/subagents/agent-args.ts +39 -0
- package/extensions/subagents/agent-description.ts +132 -0
- package/extensions/subagents/agents.ts +116 -23
- package/extensions/subagents/announce.ts +69 -0
- package/extensions/subagents/default-model.ts +2 -3
- package/extensions/subagents/delegation-steer.ts +4 -4
- package/extensions/subagents/fork-cache.ts +76 -0
- package/extensions/subagents/guide-agent.ts +189 -0
- package/extensions/subagents/hand-back-review.ts +3 -0
- package/extensions/subagents/index.ts +1493 -824
- package/extensions/subagents/live-runs.ts +26 -6
- package/extensions/subagents/model-select.ts +38 -25
- package/extensions/subagents/outcome.ts +2 -2
- package/extensions/subagents/panel-keys.ts +73 -31
- package/extensions/subagents/panel-render.ts +120 -96
- package/extensions/subagents/panel-widget.ts +60 -89
- package/extensions/subagents/runner.ts +108 -80
- package/extensions/subagents/runs.ts +39 -5
- package/extensions/subagents/send-to-main-tool.ts +1 -1
- package/extensions/subagents/session-turns.ts +32 -8
- package/extensions/subagents/shell-panel.ts +36 -178
- package/extensions/subagents/tasks-dialog.ts +170 -0
- package/extensions/subagents/viewport-mirror.ts +95 -0
- package/extensions/subagents/worktree.ts +57 -13
- package/extensions/system-prompt/environment.ts +19 -19
- package/extensions/system-prompt/idle-turn.ts +65 -0
- package/extensions/system-prompt/index.ts +131 -47
- package/extensions/system-prompt/template.ts +24 -50
- package/extensions/system-prompt/tiers/common.ts +23 -64
- package/extensions/system-prompt/tiers/frontier.ts +32 -11
- package/extensions/system-prompt/tiers/low.ts +67 -45
- package/extensions/system-prompt/tiers/mid.ts +96 -38
- package/extensions/system-reminder/index.ts +175 -13
- package/extensions/tasks/descriptions.ts +190 -0
- package/extensions/tasks/index.ts +120 -41
- package/extensions/tasks/store.ts +83 -16
- package/extensions/tool-call-corruption/child.ts +7 -0
- package/extensions/tool-call-corruption/index.ts +237 -0
- package/extensions/tool-search/announce.ts +16 -0
- package/extensions/tool-search/index.ts +189 -41
- package/extensions/tool-style/index.ts +68 -10
- package/extensions/tool-style/write-description.ts +40 -0
- package/extensions/tool-style/write-render.ts +237 -0
- package/extensions/turn-duration/index.ts +7 -3
- package/extensions/turn-duration/line.ts +47 -4
- package/extensions/web/backends.ts +6 -9
- package/extensions/web/description.ts +50 -0
- package/extensions/web/index.ts +118 -53
- package/extensions/web/native-call.ts +15 -0
- package/extensions/web/native-results.ts +41 -0
- package/extensions/web-fetch/description.ts +42 -0
- package/extensions/web-fetch/extract.ts +53 -6
- package/extensions/web-fetch/index.ts +125 -76
- package/extensions/web-fetch/page-content.ts +19 -0
- package/extensions/web-fetch/response.ts +49 -0
- package/extensions/web-fetch/summarize.ts +9 -10
- package/extensions/workflow/agent-session.ts +105 -18
- package/extensions/workflow/args.ts +24 -0
- package/extensions/workflow/description.ts +67 -0
- package/extensions/workflow/globals.ts +17 -3
- package/extensions/workflow/index.ts +145 -162
- package/extensions/workflow/records.ts +1 -0
- package/extensions/workflow/run-manager.ts +29 -6
- package/extensions/workflow/saved-workflows.ts +3 -2
- package/extensions/workflow/types.ts +22 -1
- package/extensions/workflow/viewer.ts +54 -24
- package/extensions/workflow/widget.ts +20 -0
- package/extensions/worktree/descriptions.ts +91 -0
- package/extensions/worktree/guards.ts +316 -54
- package/extensions/worktree/index.ts +121 -39
- package/extensions/worktree/powershell-guards.ts +167 -0
- package/extensions/worktree/rewrite.ts +14 -16
- package/package.json +19 -7
- package/skills/artifact-design/SKILL.md +85 -0
- package/skills/code-review/SKILL.md +20 -20
- package/skills/code-review/cells/arguments-and-flags.md +19 -0
- package/skills/code-review/cells/high-3x5-recall-verify.md +137 -0
- package/skills/code-review/cells/high-8-inline.md +122 -0
- package/skills/code-review/cells/low-1-pass-max4.md +27 -0
- package/skills/code-review/cells/low-1-pass-min-files-4.md +28 -0
- package/skills/code-review/cells/max-5x5-verify-sweep.md +162 -0
- package/skills/code-review/cells/medium-3x5-verify.md +132 -0
- package/skills/code-review/cells/minimal-prompt.md +32 -0
- package/skills/code-review/cells/xhigh-10-inline-sweep.md +149 -0
- package/skills/code-review/cells/xhigh-5x5-verify-sweep.md +162 -0
- package/skills/fewer-permission-prompts/SKILL.md +1 -1
- package/skills/loop/SKILL.md +11 -0
- package/skills/security-review/SKILL.md +2 -5
- package/skills/simplify/SKILL.md +7 -5
- package/skills/workflow-authoring/SKILL.md +143 -0
- package/themes/onecode-light.json +1 -1
- package/themes/onecode.json +1 -1
- package/types/app.d.ts +58 -0
- package/types/community-packages.d.ts +26 -1
- package/extensions/auto-mode/recoverability.ts +0 -229
- package/extensions/lib/capability-index.ts +0 -466
- package/extensions/lib/model-facts.generated.json +0 -2675
- package/extensions/lib/model-facts.ts +0 -162
|
@@ -14,13 +14,16 @@
|
|
|
14
14
|
* `extensionFactories`, which DefaultResourceLoader always loads.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
+
import { childWriteWatcher } from "../lib/child-writes.ts";
|
|
18
|
+
import { randomBytes } from "node:crypto";
|
|
17
19
|
import os from "node:os";
|
|
18
20
|
import { getAgentDir, type ModelRuntime, SessionManager, type ToolDefinition } from "@earendil-works/pi-coding-agent";
|
|
19
21
|
import type { AgentMessage } from "@earendil-works/pi-agent-core";
|
|
20
22
|
import type { Api, Model } from "@earendil-works/pi-ai";
|
|
21
23
|
import { Type } from "typebox";
|
|
22
24
|
import { whenAborted } from "../lib/abort.ts";
|
|
23
|
-
import {
|
|
25
|
+
import { persistIfLarge, sessionResultsDir } from "../lib/persisted-output.ts";
|
|
26
|
+
import { createSharedModelRuntime, disposeChildSession, finalAssistantText, openChildSession } from "../lib/agent-loader.ts";
|
|
24
27
|
import { modelSpec as modelSpecOf, supportsImageInput } from "../lib/model-policy.ts";
|
|
25
28
|
import { isModelUnavailableError } from "../auto-mode/model-select.ts";
|
|
26
29
|
import { agentPromptIdentity, PrefixWarmGate, prefixWarmKey } from "../lib/prefix-warm-gate.ts";
|
|
@@ -28,12 +31,15 @@ import type { PermissionBridge } from "../permissions/subagent-gate.ts";
|
|
|
28
31
|
import { localGateMode, MODE_ENV } from "../lib/permission-gate.ts";
|
|
29
32
|
import type { HookBridge } from "../hooks/subagent-bridge.ts";
|
|
30
33
|
import { summarizeArgs } from "../lib/tui-render.ts";
|
|
31
|
-
import {
|
|
34
|
+
import { type AgentDefinition, agentFileSources, agentToolOptions, discoverAgents, unusableAllowlistError } from "../subagents/agents.ts";
|
|
35
|
+
import { defaultDiscoverRoots, discoverPlugins } from "../lib/plugins.ts";
|
|
36
|
+
import { CHILD_EXTENSION_PATHS } from "../lib/child-extensions.ts";
|
|
37
|
+
import { oneTurnHandbackSlot, subagentHandbackExtension } from "../lib/subagent-handback.ts";
|
|
32
38
|
import type { SubagentDefault } from "../subagents/default-model.ts";
|
|
33
39
|
import { expensiveModelGate, resolveSubagentModel, subagentModelMenu } from "../subagents/model-select.ts";
|
|
34
40
|
import { withoutUnusable } from "../lib/model-unusable.ts";
|
|
35
41
|
import { cleanupWorktree, createWorktree, isGitRepo, type Worktree } from "../subagents/worktree.ts";
|
|
36
|
-
import type { AgentCallOptions, AgentCallResult, AgentEffort, AgentRunUpdate } from "./types.ts";
|
|
42
|
+
import type { AgentCallOptions, AgentCallResult, AgentEffort, AgentRunUpdate, KeptWorktree } from "./types.ts";
|
|
37
43
|
import { WorkflowScriptError } from "./types.ts";
|
|
38
44
|
|
|
39
45
|
const MAX_SCHEMA_RETRIES = 2;
|
|
@@ -52,6 +58,8 @@ export interface AgentRunnerOptions {
|
|
|
52
58
|
unusableModels?: () => ReadonlySet<string>;
|
|
53
59
|
/** An agent's provider refused its model as not usable on this account (`isModelUnavailableError`): report it so every picker skips it. */
|
|
54
60
|
onModelUnusable?: (model: string, reason: string) => void;
|
|
61
|
+
/** An agent's edit or write changed a file (lib/child-writes.ts), for the parent's file-tracker. */
|
|
62
|
+
onChildWrite?: (path: string, agent: string | undefined) => void;
|
|
55
63
|
/**
|
|
56
64
|
* The parent permissions extension's decision closure (same bridge the
|
|
57
65
|
* subagent runner uses): when present, a workflow agent's tool calls route
|
|
@@ -65,6 +73,13 @@ export interface AgentRunnerOptions {
|
|
|
65
73
|
getHookBridge?: () => HookBridge | undefined;
|
|
66
74
|
/** Each finished agent's dollar cost (review S13: workflow agents never reached the footer). */
|
|
67
75
|
onUsage?: (cost: number) => void;
|
|
76
|
+
/**
|
|
77
|
+
* The parent's live MCP tools (lib/mcp-share.ts `watchMcpTools`), injected
|
|
78
|
+
* as custom tools over the parent's connections, as the subagent runner does.
|
|
79
|
+
*/
|
|
80
|
+
getMcpTools?: () => ToolDefinition[] | Promise<ToolDefinition[]>;
|
|
81
|
+
/** Where an answer past OUTPUT_CAP is saved (`<dir>/tool-results/`): the run's directory. */
|
|
82
|
+
resultsDir?: string;
|
|
68
83
|
}
|
|
69
84
|
|
|
70
85
|
/**
|
|
@@ -199,7 +214,9 @@ export class AgentRunner {
|
|
|
199
214
|
static async create(options: AgentRunnerOptions): Promise<AgentRunner> {
|
|
200
215
|
const agentDir = getAgentDir();
|
|
201
216
|
const modelRuntime = await createSharedModelRuntime(agentDir);
|
|
202
|
-
|
|
217
|
+
// The Agent tool's registry: bundled and plugin agents too, not only the user and project folders.
|
|
218
|
+
const plugins = discoverPlugins(defaultDiscoverRoots(agentDir, options.cwd));
|
|
219
|
+
const agentCatalog = discoverAgents(agentFileSources(options.cwd, os.homedir(), plugins.agentDirs));
|
|
203
220
|
const availableModels = [...(await modelRuntime.getAvailable())];
|
|
204
221
|
return new AgentRunner(options, modelRuntime, agentCatalog, availableModels);
|
|
205
222
|
}
|
|
@@ -245,6 +262,12 @@ export class AgentRunner {
|
|
|
245
262
|
|
|
246
263
|
await this.judgeDelegation(prompt, opts, agentDef, signal);
|
|
247
264
|
|
|
265
|
+
// Before the worktree exists: a malformed schema would otherwise leak it.
|
|
266
|
+
if (opts.schema) assertObjectSchema(opts.schema);
|
|
267
|
+
|
|
268
|
+
// Also before the worktree: a rejection here would leak it the same way.
|
|
269
|
+
const mcpTools = (await this.options.getMcpTools?.()) ?? [];
|
|
270
|
+
|
|
248
271
|
let worktree: Worktree | undefined;
|
|
249
272
|
let cwd = this.options.cwd;
|
|
250
273
|
if (opts.isolation === "worktree") {
|
|
@@ -256,13 +279,27 @@ export class AgentRunner {
|
|
|
256
279
|
}
|
|
257
280
|
|
|
258
281
|
const capture: { called: boolean; value: unknown } = { called: false, value: undefined };
|
|
259
|
-
|
|
282
|
+
// An agent without a schema hands its answer back through SubagentHandback,
|
|
283
|
+
// as every child does; with a schema, structured_output is the hand-back.
|
|
284
|
+
const handback = opts.schema ? undefined : oneTurnHandbackSlot();
|
|
285
|
+
const customTools: ToolDefinition[] = [
|
|
286
|
+
...(opts.schema ? [buildStructuredOutputTool(opts.schema, capture)] : []),
|
|
287
|
+
...mcpTools,
|
|
288
|
+
];
|
|
260
289
|
|
|
290
|
+
// The same child session a subagent gets (SUBAGENTS-WORKFLOWS-REVIEW-2026-09-26
|
|
291
|
+
// H2, H3, M6): the curated child extensions, the parent's MCP tools, and the
|
|
292
|
+
// agent file's tool lists through the one shared builder, which keeps
|
|
293
|
+
// `structured_output` on an allowlist and applies `disallowedTools`.
|
|
261
294
|
const session = await openChildSession({
|
|
262
295
|
loader: {
|
|
263
296
|
cwd: this.options.cwd,
|
|
264
297
|
agentDir: getAgentDir(),
|
|
265
298
|
systemPrompt: agentDef?.systemPrompt,
|
|
299
|
+
extraExtensionPaths: CHILD_EXTENSION_PATHS,
|
|
300
|
+
// claude-context (a child extension) injects the CLAUDE.md instructions itself.
|
|
301
|
+
noContextFiles: true,
|
|
302
|
+
...(handback ? { extraFactories: [subagentHandbackExtension(handback)] } : {}),
|
|
266
303
|
getPermissionBridge: this.options.getPermissionBridge,
|
|
267
304
|
getHookBridge: this.options.getHookBridge,
|
|
268
305
|
},
|
|
@@ -272,11 +309,16 @@ export class AgentRunner {
|
|
|
272
309
|
modelRuntime: this.modelRuntime,
|
|
273
310
|
model: modelSpec.model as never,
|
|
274
311
|
thinkingLevel: modelSpec.thinkingLevel as never,
|
|
275
|
-
|
|
312
|
+
...agentToolOptions(agentDef),
|
|
276
313
|
customTools,
|
|
277
314
|
sessionManager: SessionManager.inMemory(cwd),
|
|
278
315
|
},
|
|
279
316
|
onError: (error) => this.options.onNotice?.(`${opts.label ?? "agent"}: extension error in ${error.event}: ${error.error}`),
|
|
317
|
+
}).catch(async (error: unknown) => {
|
|
318
|
+
// Not yet under the prompt's try/finally: a session that fails to open
|
|
319
|
+
// must not leak the worktree and its branch.
|
|
320
|
+
if (worktree) await this.settleWorktree(worktree, opts.label, error);
|
|
321
|
+
throw error;
|
|
280
322
|
});
|
|
281
323
|
|
|
282
324
|
const unhookAbort = whenAborted(signal, () => void session.abort());
|
|
@@ -284,8 +326,11 @@ export class AgentRunner {
|
|
|
284
326
|
// refusing the agent's model (the same check the subagent runner makes, so
|
|
285
327
|
// the refusal reaches every automatic picker — lib/model-unusable.ts).
|
|
286
328
|
// Never let a bad event shape kill the agent.
|
|
329
|
+
const childWrote = childWriteWatcher(session.sessionManager?.getCwd?.() ?? this.options.cwd);
|
|
287
330
|
const unsubscribe = session.subscribe((event) => {
|
|
288
331
|
try {
|
|
332
|
+
const wrote = childWrote(event as never);
|
|
333
|
+
if (wrote) this.options.onChildWrite?.(wrote, opts.label);
|
|
289
334
|
if (event.type === "message_end") {
|
|
290
335
|
const reply = (event as { message?: { role?: string; stopReason?: string; errorMessage?: string; provider?: string; model?: string } }).message;
|
|
291
336
|
if (reply?.role === "assistant" && reply.stopReason === "error" && reply.errorMessage && reply.provider && reply.model && isModelUnavailableError(reply.errorMessage)) {
|
|
@@ -310,7 +355,17 @@ export class AgentRunner {
|
|
|
310
355
|
prefixWarmKey(agentPromptIdentity(agentDef?.name), cwd, model ? modelSpecOf(model) : undefined),
|
|
311
356
|
session,
|
|
312
357
|
);
|
|
358
|
+
let failure: unknown;
|
|
313
359
|
try {
|
|
360
|
+
// An allowlist that matched no real tool would run a tool-less agent.
|
|
361
|
+
const unusable = unusableAllowlistError(
|
|
362
|
+
agentDef,
|
|
363
|
+
session.getAllTools().map((t) => t.name),
|
|
364
|
+
);
|
|
365
|
+
if (unusable) throw new WorkflowScriptError(unusable);
|
|
366
|
+
// A stop during the waits above (MCP tools still connecting, the warm
|
|
367
|
+
// gate) aborted a session that was idle: never send the first request.
|
|
368
|
+
if (signal.aborted) throw new WorkflowScriptError("aborted");
|
|
314
369
|
await session.prompt(this.buildPrompt(prompt, Boolean(opts.schema)));
|
|
315
370
|
if (signal.aborted) throw new WorkflowScriptError("aborted");
|
|
316
371
|
|
|
@@ -318,27 +373,39 @@ export class AgentRunner {
|
|
|
318
373
|
if (opts.schema) {
|
|
319
374
|
value = await this.resolveStructuredOutput(session, capture, signal);
|
|
320
375
|
} else {
|
|
321
|
-
|
|
376
|
+
// The handed-back report, else the agent's last message.
|
|
377
|
+
value = handback?.report ?? finalAssistantText(session.messages);
|
|
322
378
|
if (typeof value !== "string" || !value.trim()) {
|
|
323
379
|
throw new Error("subagent produced no output");
|
|
324
380
|
}
|
|
325
|
-
|
|
381
|
+
// Never cut: a long answer is saved to the run directory and the script
|
|
382
|
+
// gets Claude Code's <persisted-output> block naming the file, which a
|
|
383
|
+
// later agent can read (SUBAGENTS-WORKFLOWS-REVIEW-2026-09-26 M1).
|
|
384
|
+
value = persistIfLarge(value as string, {
|
|
385
|
+
dir: this.options.resultsDir ?? sessionResultsDir(undefined),
|
|
386
|
+
id: `agent-${randomBytes(4).toString("hex")}`,
|
|
387
|
+
maxBytes: OUTPUT_CAP,
|
|
388
|
+
});
|
|
326
389
|
}
|
|
327
390
|
|
|
328
391
|
const stats = session.getSessionStats();
|
|
329
|
-
// cleanupWorktree keeps trees holding uncommitted changes; report those.
|
|
330
|
-
let
|
|
392
|
+
// cleanupWorktree keeps trees holding uncommitted changes or commits; report those.
|
|
393
|
+
let kept: Worktree | undefined;
|
|
331
394
|
if (worktree) {
|
|
332
395
|
const removed = await cleanupWorktree(this.options.cwd, worktree);
|
|
333
|
-
if (!removed)
|
|
396
|
+
if (!removed) kept = worktree;
|
|
334
397
|
worktree = undefined;
|
|
335
398
|
}
|
|
336
399
|
return {
|
|
337
400
|
value,
|
|
338
401
|
tokens: { input: stats.tokens.input, output: stats.tokens.output, total: stats.tokens.total },
|
|
339
402
|
cost: stats.cost,
|
|
340
|
-
worktreePath,
|
|
403
|
+
worktreePath: kept?.path,
|
|
404
|
+
worktreeBranch: kept?.branch,
|
|
341
405
|
};
|
|
406
|
+
} catch (error) {
|
|
407
|
+
failure = error;
|
|
408
|
+
throw error;
|
|
342
409
|
} finally {
|
|
343
410
|
// Whatever the outcome — success, failure, or an abort (a user stop, or
|
|
344
411
|
// the run finishing with this agent un-awaited) — the provider was
|
|
@@ -348,11 +415,26 @@ export class AgentRunner {
|
|
|
348
415
|
releasePrefix(false);
|
|
349
416
|
unsubscribe?.();
|
|
350
417
|
unhookAbort();
|
|
351
|
-
session
|
|
352
|
-
|
|
418
|
+
disposeChildSession(session);
|
|
419
|
+
// A failed or aborted agent can still have edited or committed in its
|
|
420
|
+
// worktree: settled after the session is gone, before the error reaches
|
|
421
|
+
// the caller, so the kept path rides on it.
|
|
422
|
+
if (worktree) await this.settleWorktree(worktree, opts.label, failure);
|
|
353
423
|
}
|
|
354
424
|
}
|
|
355
425
|
|
|
426
|
+
/**
|
|
427
|
+
* Remove a failed agent's worktree, or keep it when it holds changes or
|
|
428
|
+
* commits: then the run log names it, and the kept path rides on `error`
|
|
429
|
+
* (`keptWorktreeOf`) so the agent's end event and the run report list it.
|
|
430
|
+
*/
|
|
431
|
+
private async settleWorktree(worktree: Worktree, label: string | undefined, error: unknown): Promise<void> {
|
|
432
|
+
if (await cleanupWorktree(this.options.cwd, worktree)) return;
|
|
433
|
+
const kept: KeptWorktree = { path: worktree.path, branch: worktree.branch };
|
|
434
|
+
this.options.onNotice?.(`${label ?? "agent"}: worktree kept at ${kept.path} (branch ${kept.branch}) with its changes or commits`);
|
|
435
|
+
if (error instanceof Error) (error as Error & { keptWorktree?: KeptWorktree }).keptWorktree = kept;
|
|
436
|
+
}
|
|
437
|
+
|
|
356
438
|
private judgeDelegation(prompt: string, opts: AgentCallOptions, agentDef: AgentDefinition | undefined, signal: AbortSignal): Promise<void> {
|
|
357
439
|
return judgeWorkflowDelegation({
|
|
358
440
|
bridge: this.options.getPermissionBridge?.(),
|
|
@@ -367,7 +449,7 @@ export class AgentRunner {
|
|
|
367
449
|
|
|
368
450
|
private buildPrompt(prompt: string, structured: boolean): string {
|
|
369
451
|
if (!structured) {
|
|
370
|
-
return `${prompt}\n\
|
|
452
|
+
return `${prompt}\n\nThe report you hand back through SubagentHandback is returned verbatim to an orchestration script, not shown to a human — hand back the requested data/report only.`;
|
|
371
453
|
}
|
|
372
454
|
return `${prompt}\n\nWhen you are done, you MUST call the \`structured_output\` tool exactly once with your final result. Its arguments are the only output the caller receives.`;
|
|
373
455
|
}
|
|
@@ -398,9 +480,7 @@ export class AgentRunner {
|
|
|
398
480
|
|
|
399
481
|
/** Terminating tool capturing schema-validated output (pi validates params pre-execute). */
|
|
400
482
|
function buildStructuredOutputTool(schema: Record<string, unknown>, capture: { called: boolean; value: unknown }): ToolDefinition {
|
|
401
|
-
|
|
402
|
-
throw new WorkflowScriptError("agent() schema must be a JSON Schema with top-level type \"object\" and properties");
|
|
403
|
-
}
|
|
483
|
+
assertObjectSchema(schema);
|
|
404
484
|
return {
|
|
405
485
|
name: "structured_output",
|
|
406
486
|
label: "Structured Output",
|
|
@@ -418,6 +498,13 @@ function buildStructuredOutputTool(schema: Record<string, unknown>, capture: { c
|
|
|
418
498
|
} as ToolDefinition;
|
|
419
499
|
}
|
|
420
500
|
|
|
501
|
+
/** A structured_output schema must be an object schema with properties. */
|
|
502
|
+
function assertObjectSchema(schema: Record<string, unknown>): void {
|
|
503
|
+
if (schema.type !== "object" || typeof schema.properties !== "object") {
|
|
504
|
+
throw new WorkflowScriptError("agent() schema must be a JSON Schema with top-level type \"object\" and properties");
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
421
508
|
/** Pull the first parseable JSON object/array out of free text (```json fences first). */
|
|
422
509
|
function extractJsonObject(text: string): unknown {
|
|
423
510
|
const fenced = text.match(/```(?:json)?\s*\n([\s\S]*?)\n```/);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** The workflow tool's argument preparation (pure). */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The call's arguments with `args` as the script should see it, decoded before
|
|
5
|
+
* the gate, hooks and the stored call see them. Weak models send a list or
|
|
6
|
+
* object as a JSON-encoded string despite the description (every Qwen 3.8
|
|
7
|
+
* model, battery round 7), which breaks `args.map` and `pipeline(args, …)`; a
|
|
8
|
+
* string that parses to an array or object is decoded. Any other value passes
|
|
9
|
+
* verbatim.
|
|
10
|
+
*/
|
|
11
|
+
export function prepareWorkflowArguments(raw: unknown): unknown {
|
|
12
|
+
if (!raw || typeof raw !== "object" || !("args" in raw)) return raw;
|
|
13
|
+
return { ...raw, args: decodedArgs((raw as { args: unknown }).args) };
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function decodedArgs(args: unknown): unknown {
|
|
17
|
+
if (typeof args !== "string" || !/^\s*[[{]/.test(args)) return args;
|
|
18
|
+
try {
|
|
19
|
+
const parsed: unknown = JSON.parse(args);
|
|
20
|
+
return parsed !== null && typeof parsed === "object" ? parsed : args;
|
|
21
|
+
} catch {
|
|
22
|
+
return args;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The workflow tool's model-facing description: Claude Code's Workflow text
|
|
3
|
+
* and its size-guideline line (pure).
|
|
4
|
+
*
|
|
5
|
+
* The authoring reference (script API, quality patterns, resume, worked
|
|
6
|
+
* examples) is the bundled `workflow-authoring` skill, which the description
|
|
7
|
+
* tells the model to load before writing a script. The size line follows
|
|
8
|
+
* `workflowSizeGuideline` in One Code's settings (lib/one-code-settings.ts);
|
|
9
|
+
* "unrestricted" sends no line, as in Claude Code. Changes from Claude Code's
|
|
10
|
+
* text: the setting is named where Claude Code points to its /config row, and
|
|
11
|
+
* tool names are One Code's.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { WorkflowSizeGuideline } from "../lib/one-code-settings.ts";
|
|
15
|
+
|
|
16
|
+
export const WORKFLOW_DESCRIPTION_BODY = `Execute a workflow script that orchestrates multiple subagents deterministically. Workflows run in the background — this tool returns immediately with a task ID, and a <task-notification> arrives when the workflow completes. Use /workflows to watch live progress.
|
|
17
|
+
|
|
18
|
+
ONLY call this tool when the user has explicitly opted into multi-agent orchestration. Workflows can spawn dozens of agents and consume a large amount of tokens; the user must request that scale, not have it inferred. Explicit opt-in means one of:
|
|
19
|
+
- The user included the keyword "ultracode" in their prompt (you'll see a system-reminder confirming it).
|
|
20
|
+
- Ultracode is on for the session (a system-reminder confirms it) — see **Ultracode** in the workflow authoring reference.
|
|
21
|
+
- The user directly asked you to run a workflow or use multi-agent orchestration in their own words ("use a workflow", "run a workflow", "fan out agents", "orchestrate this with subagents"). The ask must be in the user's words — a task that would merely benefit from a workflow does not count.
|
|
22
|
+
- The user invoked a skill or slash command whose instructions tell you to call Workflow.
|
|
23
|
+
- The user asked you to run a specific named or saved workflow.
|
|
24
|
+
|
|
25
|
+
For any other task — even one that would clearly benefit from parallelism — do NOT call this tool. Use the Agent tool (if available) for individual subagents, or briefly describe what a multi-agent workflow could do and how much it would roughly cost, and ask the user whether to run it. Mention they can ask for one with "use a workflow" in a future message to skip the ask.
|
|
26
|
+
|
|
27
|
+
Every script must begin with \`export const meta = {...}\`: a PURE LITERAL (no variables, calls or interpolation) giving the workflow's \`name\`, a one-line \`description\` (shown in the permission dialog) and optionally \`phases\` — one \`{ title, detail? }\` per phase() call, titles matched exactly. Pass the script inline via \`script\` — do not write it to a file first, and do not also set the tool's \`name\` input (that selects a saved workflow); it is plain JavaScript, not TypeScript.
|
|
28
|
+
|
|
29
|
+
The canonical multi-stage pattern — pipeline by default, each dimension verifies as soon as its review completes:
|
|
30
|
+
export const meta = {
|
|
31
|
+
name: 'review-changes',
|
|
32
|
+
description: 'Review changed files across dimensions, verify each finding',
|
|
33
|
+
phases: [{ title: 'Review' }, { title: 'Verify' }],
|
|
34
|
+
}
|
|
35
|
+
const DIMENSIONS = [{key: 'bugs', prompt: '...'}, {key: 'perf', prompt: '...'}]
|
|
36
|
+
const results = await pipeline(
|
|
37
|
+
DIMENSIONS,
|
|
38
|
+
d => agent(d.prompt, {label: \`review:\${d.key}\`, phase: 'Review', schema: FINDINGS_SCHEMA}),
|
|
39
|
+
review => parallel(review.findings.map(f => () =>
|
|
40
|
+
agent(\`Adversarially verify: \${f.title}\`, {label: \`verify:\${f.file}\`, phase: 'Verify', schema: VERDICT_SCHEMA})
|
|
41
|
+
.then(v => ({...f, verdict: v}))
|
|
42
|
+
))
|
|
43
|
+
)
|
|
44
|
+
const confirmed = results.flat().filter(Boolean).filter(f => f.verdict?.isReal)
|
|
45
|
+
return { confirmed }
|
|
46
|
+
// Dimension 'bugs' findings verify while dimension 'perf' is still reviewing. No wasted wall-clock.
|
|
47
|
+
|
|
48
|
+
Before writing a script, load the \`workflow-authoring\` skill — the workflow authoring reference: script API and gotchas, resume, the **Ultracode** section, quality patterns, worked examples.`;
|
|
49
|
+
|
|
50
|
+
/** The agent count each size keeps a workflow under. */
|
|
51
|
+
export const WORKFLOW_SIZE_AGENTS: Record<Exclude<WorkflowSizeGuideline, "unrestricted">, number> = {
|
|
52
|
+
small: 5,
|
|
53
|
+
medium: 10,
|
|
54
|
+
large: 50,
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/** The size-guideline line; undefined when no guideline applies. */
|
|
58
|
+
export function workflowSizeLine(guideline: WorkflowSizeGuideline, configured: boolean): string | undefined {
|
|
59
|
+
if (guideline === "unrestricted") return undefined;
|
|
60
|
+
const opening = configured ? "A workflow size guideline is configured for this session" : "This session has the default workflow size guideline";
|
|
61
|
+
return `${opening}: ${guideline} — keep workflows under ${WORKFLOW_SIZE_AGENTS[guideline]} agents. This is a guideline, not a hard limit — follow it unless the user's prompt calls for a different scale. The user can raise or remove it with \`workflowSizeGuideline\` in ~/.onecode/settings.json.`;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function workflowDescription(guideline: WorkflowSizeGuideline, configured: boolean): string {
|
|
65
|
+
const line = workflowSizeLine(guideline, configured);
|
|
66
|
+
return line ? `${WORKFLOW_DESCRIPTION_BODY}\n\n${line}` : WORKFLOW_DESCRIPTION_BODY;
|
|
67
|
+
}
|
|
@@ -25,7 +25,7 @@ import type {
|
|
|
25
25
|
JournalEntry,
|
|
26
26
|
RunProgressEvent,
|
|
27
27
|
} from "./types.ts";
|
|
28
|
-
import { WorkflowScriptError } from "./types.ts";
|
|
28
|
+
import { keptWorktreeOf, type KeptWorktree, WorkflowScriptError } from "./types.ts";
|
|
29
29
|
import type { ReplayCursor } from "./journal.ts";
|
|
30
30
|
|
|
31
31
|
export const MAX_AGENTS_PER_RUN = 1000;
|
|
@@ -186,6 +186,7 @@ export function createScriptGlobals(options: ScriptGlobalsOptions): { globals: S
|
|
|
186
186
|
replayed: true,
|
|
187
187
|
prompt,
|
|
188
188
|
preview: previewValue(replayed.value),
|
|
189
|
+
...keptWorktreeField(replayed.worktreePath, replayed.worktreeBranch),
|
|
189
190
|
});
|
|
190
191
|
return replayed.value;
|
|
191
192
|
}
|
|
@@ -216,13 +217,14 @@ export function createScriptGlobals(options: ScriptGlobalsOptions): { globals: S
|
|
|
216
217
|
tokens: result.tokens,
|
|
217
218
|
cost: result.cost,
|
|
218
219
|
preview: previewValue(result.value),
|
|
220
|
+
...keptWorktreeField(result.worktreePath, result.worktreeBranch),
|
|
219
221
|
});
|
|
220
222
|
return result.value;
|
|
221
223
|
} catch (error) {
|
|
222
224
|
if (options.signal.aborted) {
|
|
223
225
|
// Close the record: the viewer would otherwise show a completed or
|
|
224
226
|
// stopped run with this agent still "running".
|
|
225
|
-
options.onEvent({ type: "agentEnd", callIndex, label, phase, text: "aborted" });
|
|
227
|
+
options.onEvent({ type: "agentEnd", callIndex, label, phase, text: "aborted", ...keptWorktreeField(keptWorktreeOf(error)?.path, keptWorktreeOf(error)?.branch) });
|
|
226
228
|
throw new WorkflowScriptError("Workflow run was aborted");
|
|
227
229
|
}
|
|
228
230
|
// A script-authoring mistake (bad agentType/model, worktree without a
|
|
@@ -233,7 +235,14 @@ export function createScriptGlobals(options: ScriptGlobalsOptions): { globals: S
|
|
|
233
235
|
if (error instanceof WorkflowScriptError) throw error;
|
|
234
236
|
// A failed agent resolves to null (Claude Code semantics); the
|
|
235
237
|
// failure is surfaced as a progress event, not an exception.
|
|
236
|
-
options.onEvent({
|
|
238
|
+
options.onEvent({
|
|
239
|
+
type: "agentEnd",
|
|
240
|
+
callIndex,
|
|
241
|
+
label,
|
|
242
|
+
phase,
|
|
243
|
+
text: `failed: ${(error as Error).message}`,
|
|
244
|
+
...keptWorktreeField(keptWorktreeOf(error)?.path, keptWorktreeOf(error)?.branch),
|
|
245
|
+
});
|
|
237
246
|
return null;
|
|
238
247
|
}
|
|
239
248
|
});
|
|
@@ -272,3 +281,8 @@ export function createScriptGlobals(options: ScriptGlobalsOptions): { globals: S
|
|
|
272
281
|
|
|
273
282
|
return { globals, state };
|
|
274
283
|
}
|
|
284
|
+
|
|
285
|
+
/** The `worktree` field of an agentEnd event, present only for a kept worktree. */
|
|
286
|
+
function keptWorktreeField(path: string | undefined, branch: string | undefined): { worktree?: KeptWorktree } {
|
|
287
|
+
return path ? { worktree: branch ? { path, branch } : { path } } : {};
|
|
288
|
+
}
|