@nghyane/arcane 0.1.13 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/package.json +21 -70
- package/scripts/format-prompts.ts +1 -3
- package/src/cli/args.ts +2 -7
- package/src/cli/config-cli.ts +1 -1
- package/src/cli/plugin-cli.ts +1 -1
- package/src/cli/setup-cli.ts +1 -1
- package/src/cli/update-cli.ts +1 -1
- package/src/cli/web-search-cli.ts +1 -1
- package/src/cli.ts +0 -1
- package/src/commands/config.ts +1 -1
- package/src/commands/grep.ts +1 -1
- package/src/commands/jupyter.ts +1 -1
- package/src/commands/plugin.ts +1 -1
- package/src/commands/setup.ts +1 -1
- package/src/commands/shell.ts +1 -1
- package/src/commands/ssh.ts +1 -1
- package/src/commands/stats.ts +1 -1
- package/src/commands/update.ts +1 -1
- package/src/config/model-registry.ts +3 -4
- package/src/config/model-resolver.ts +36 -9
- package/src/config/prompt-templates.ts +1 -9
- package/src/config/settings-schema.ts +32 -88
- package/src/config/settings.ts +3 -4
- package/src/debug/index.ts +1 -1
- package/src/debug/log-formatting.ts +1 -1
- package/src/debug/log-viewer.ts +2 -2
- package/src/discovery/helpers.ts +13 -3
- package/src/exa/index.ts +1 -35
- package/src/exa/render.ts +30 -190
- package/src/export/html/index.ts +1 -1
- package/src/extensibility/custom-tools/loader.ts +1 -1
- package/src/extensibility/custom-tools/types.ts +5 -1
- package/src/extensibility/custom-tools/wrapper.ts +1 -1
- package/src/extensibility/extensions/runner.ts +1 -1
- package/src/extensibility/extensions/types.ts +1 -1
- package/src/extensibility/extensions/wrapper.ts +7 -15
- package/src/extensibility/hooks/runner.ts +1 -1
- package/src/extensibility/hooks/types.ts +1 -1
- package/src/extensibility/plugins/doctor.ts +1 -1
- package/src/index.ts +13 -13
- package/src/lsp/index.ts +77 -24
- package/src/lsp/render.ts +34 -583
- package/src/lsp/types.ts +3 -3
- package/src/lsp/utils.ts +1 -1
- package/src/main.ts +1 -1
- package/src/mcp/tool-bridge.ts +1 -24
- package/src/modes/components/assistant-message.ts +7 -7
- package/src/modes/components/bash-execution.ts +50 -112
- package/src/modes/components/bordered-loader.ts +1 -1
- package/src/modes/components/branch-summary-message.ts +16 -10
- package/src/modes/components/compaction-summary-message.ts +20 -12
- package/src/modes/components/context-group.ts +106 -0
- package/src/modes/components/custom-message.ts +4 -5
- package/src/modes/components/diff.ts +2 -2
- package/src/modes/components/dynamic-border.ts +1 -1
- package/src/modes/components/extensions/extension-dashboard.ts +1 -1
- package/src/modes/components/extensions/extension-list.ts +1 -1
- package/src/modes/components/extensions/inspector-panel.ts +1 -1
- package/src/modes/components/footer.ts +2 -2
- package/src/modes/components/history-search.ts +1 -1
- package/src/modes/components/hook-editor.ts +1 -1
- package/src/modes/components/hook-input.ts +1 -1
- package/src/modes/components/hook-message.ts +4 -5
- package/src/modes/components/hook-selector.ts +1 -1
- package/src/modes/components/index.ts +0 -2
- package/src/modes/components/keybinding-hints.ts +1 -1
- package/src/modes/components/login-dialog.ts +1 -1
- package/src/modes/components/mcp-add-wizard.ts +1 -1
- package/src/modes/components/model-selector.ts +1 -1
- package/src/modes/components/oauth-selector.ts +1 -1
- package/src/modes/components/plugin-settings.ts +1 -1
- package/src/modes/components/python-execution.ts +51 -91
- package/src/modes/components/queue-mode-selector.ts +1 -1
- package/src/modes/components/session-selector.ts +1 -1
- package/src/modes/components/settings-defs.ts +5 -10
- package/src/modes/components/settings-selector.ts +1 -1
- package/src/modes/components/show-images-selector.ts +1 -1
- package/src/modes/components/skill-message.ts +4 -4
- package/src/modes/components/status-line/segments.ts +2 -2
- package/src/modes/components/status-line/separators.ts +1 -1
- package/src/modes/components/status-line-segment-editor.ts +1 -1
- package/src/modes/components/status-line.ts +1 -1
- package/src/modes/components/theme-selector.ts +1 -1
- package/src/modes/components/thinking-selector.ts +1 -1
- package/src/modes/components/todo-display.ts +2 -4
- package/src/modes/components/todo-reminder.ts +4 -4
- package/src/modes/components/tool-execution.ts +118 -440
- package/src/modes/components/tool-image-display.ts +107 -0
- package/src/modes/components/tree-selector.ts +2 -2
- package/src/modes/components/ttsr-notification.ts +4 -17
- package/src/modes/components/user-message-selector.ts +1 -1
- package/src/modes/components/user-message.ts +9 -10
- package/src/modes/components/welcome.ts +1 -1
- package/src/modes/controllers/command-controller.ts +1 -1
- package/src/modes/controllers/event-controller.ts +58 -187
- package/src/modes/controllers/extension-ui-controller.ts +1 -1
- package/src/modes/controllers/input-controller.ts +3 -1
- package/src/modes/controllers/mcp-command-controller.ts +1 -1
- package/src/modes/controllers/selector-controller.ts +3 -26
- package/src/modes/controllers/ssh-command-controller.ts +1 -1
- package/src/modes/interactive-mode.ts +3 -7
- package/src/modes/print-mode.ts +5 -5
- package/src/modes/rpc/rpc-mode.ts +1 -1
- package/src/modes/types.ts +1 -2
- package/src/modes/utils/ui-helpers.ts +34 -32
- package/src/patch/edit-tool.ts +742 -0
- package/src/patch/index.ts +32 -898
- package/src/patch/schemas.ts +208 -0
- package/src/patch/shared.ts +83 -151
- package/src/prompts/agents/explore.md +22 -37
- package/src/prompts/agents/init.md +1 -1
- package/src/prompts/agents/librarian.md +29 -20
- package/src/prompts/agents/oracle.md +9 -2
- package/src/prompts/agents/reviewer.md +14 -48
- package/src/prompts/agents/task.md +16 -8
- package/src/prompts/compaction/branch-summary.md +4 -1
- package/src/prompts/compaction/compaction-summary.md +4 -1
- package/src/prompts/system/subagent-system-prompt.md +1 -1
- package/src/prompts/system/system-prompt.md +162 -178
- package/src/prompts/system/verification-reminder.md +6 -0
- package/src/sdk.ts +0 -9
- package/src/session/agent-session.ts +244 -1459
- package/src/session/model-controller.ts +406 -0
- package/src/session/retry-utils.ts +71 -0
- package/src/session/session-manager.ts +22 -186
- package/src/session/session-types.ts +312 -0
- package/src/session/stats.ts +387 -0
- package/src/session/streaming-edit.ts +258 -0
- package/src/session/ttsr.ts +213 -0
- package/src/slash-commands/builtin-registry.ts +0 -8
- package/src/stt/recorder.ts +2 -2
- package/src/system-prompt.ts +1 -14
- package/src/task/agents.ts +7 -33
- package/src/task/executor.ts +50 -438
- package/src/task/index.ts +104 -71
- package/src/task/progress-tracker.ts +390 -0
- package/src/task/render.ts +371 -187
- package/src/task/subprocess-tool-registry.ts +1 -1
- package/src/task/types.ts +14 -47
- package/src/tools/ask.ts +31 -42
- package/src/tools/bash-interactive.ts +2 -2
- package/src/tools/bash-interceptor.ts +2 -2
- package/src/tools/bash-normalize.ts +1 -1
- package/src/tools/bash-skill-urls.ts +2 -2
- package/src/tools/bash.ts +87 -136
- package/src/tools/browser.ts +54 -84
- package/src/tools/create-tools.ts +186 -0
- package/src/tools/default-renderer.ts +104 -0
- package/src/tools/explore.ts +11 -10
- package/src/tools/fetch.ts +24 -114
- package/src/tools/find.ts +48 -132
- package/src/tools/gemini-image.ts +5 -15
- package/src/tools/github.ts +450 -0
- package/src/tools/grep.ts +43 -179
- package/src/tools/index.ts +35 -198
- package/src/tools/json-tree.ts +3 -3
- package/src/tools/librarian.ts +18 -18
- package/src/tools/list-limit.ts +2 -2
- package/src/tools/notebook.ts +35 -87
- package/src/tools/oracle.ts +25 -25
- package/src/tools/output-meta.ts +89 -4
- package/src/tools/output-utils.ts +2 -2
- package/src/tools/python.ts +86 -637
- package/src/tools/read.ts +36 -119
- package/src/tools/reviewer-tool.ts +19 -21
- package/src/tools/search-code.ts +128 -0
- package/src/tools/ssh.ts +67 -126
- package/src/tools/subagent-tool.ts +197 -123
- package/src/tools/todo-write.ts +15 -31
- package/src/tools/tool-errors.ts +0 -30
- package/src/tools/undo-edit.ts +30 -67
- package/src/tools/write.ts +78 -127
- package/src/tui/code-cell.ts +4 -4
- package/src/tui/file-list.ts +2 -2
- package/src/tui/output-block.ts +1 -1
- package/src/tui/status-line.ts +1 -1
- package/src/tui/tree-list.ts +2 -2
- package/src/tui/types.ts +1 -1
- package/src/tui/utils.ts +1 -1
- package/src/{tools → ui}/render-utils.ts +87 -126
- package/src/utils/external-editor.ts +4 -4
- package/src/utils/file-mentions.ts +1 -1
- package/src/utils/index.ts +30 -0
- package/src/utils/tools-manager.ts +9 -19
- package/src/web/github-client.ts +290 -0
- package/src/web/scrapers/github.ts +11 -62
- package/src/web/search/auth.ts +1 -3
- package/src/web/search/index.ts +82 -46
- package/src/web/search/provider.ts +11 -16
- package/src/web/search/providers/grep.ts +160 -0
- package/src/web/search/render.ts +48 -235
- package/src/web/search/types.ts +1 -1
- package/src/commands/commit.ts +0 -36
- package/src/commit/agentic/agent.ts +0 -311
- package/src/commit/agentic/fallback.ts +0 -96
- package/src/commit/agentic/index.ts +0 -359
- package/src/commit/agentic/prompts/analyze-file.md +0 -22
- package/src/commit/agentic/prompts/session-user.md +0 -25
- package/src/commit/agentic/prompts/split-confirm.md +0 -1
- package/src/commit/agentic/prompts/system.md +0 -38
- package/src/commit/agentic/state.ts +0 -69
- package/src/commit/agentic/tools/analyze-file.ts +0 -118
- package/src/commit/agentic/tools/git-file-diff.ts +0 -194
- package/src/commit/agentic/tools/git-hunk.ts +0 -50
- package/src/commit/agentic/tools/git-overview.ts +0 -84
- package/src/commit/agentic/tools/index.ts +0 -56
- package/src/commit/agentic/tools/propose-changelog.ts +0 -128
- package/src/commit/agentic/tools/propose-commit.ts +0 -154
- package/src/commit/agentic/tools/recent-commits.ts +0 -81
- package/src/commit/agentic/tools/split-commit.ts +0 -280
- package/src/commit/agentic/topo-sort.ts +0 -44
- package/src/commit/agentic/trivial.ts +0 -51
- package/src/commit/agentic/validation.ts +0 -200
- package/src/commit/analysis/conventional.ts +0 -165
- package/src/commit/analysis/index.ts +0 -4
- package/src/commit/analysis/scope.ts +0 -242
- package/src/commit/analysis/summary.ts +0 -112
- package/src/commit/analysis/validation.ts +0 -66
- package/src/commit/changelog/detect.ts +0 -37
- package/src/commit/changelog/generate.ts +0 -110
- package/src/commit/changelog/index.ts +0 -234
- package/src/commit/changelog/parse.ts +0 -44
- package/src/commit/cli.ts +0 -93
- package/src/commit/git/diff.ts +0 -148
- package/src/commit/git/errors.ts +0 -9
- package/src/commit/git/index.ts +0 -211
- package/src/commit/git/operations.ts +0 -54
- package/src/commit/index.ts +0 -5
- package/src/commit/map-reduce/index.ts +0 -64
- package/src/commit/map-reduce/map-phase.ts +0 -178
- package/src/commit/map-reduce/reduce-phase.ts +0 -145
- package/src/commit/map-reduce/utils.ts +0 -9
- package/src/commit/message.ts +0 -11
- package/src/commit/model-selection.ts +0 -69
- package/src/commit/pipeline.ts +0 -243
- package/src/commit/prompts/analysis-system.md +0 -148
- package/src/commit/prompts/analysis-user.md +0 -38
- package/src/commit/prompts/changelog-system.md +0 -50
- package/src/commit/prompts/changelog-user.md +0 -18
- package/src/commit/prompts/file-observer-system.md +0 -24
- package/src/commit/prompts/file-observer-user.md +0 -8
- package/src/commit/prompts/reduce-system.md +0 -50
- package/src/commit/prompts/reduce-user.md +0 -17
- package/src/commit/prompts/summary-retry.md +0 -3
- package/src/commit/prompts/summary-system.md +0 -38
- package/src/commit/prompts/summary-user.md +0 -13
- package/src/commit/prompts/types-description.md +0 -2
- package/src/commit/types.ts +0 -109
- package/src/commit/utils/exclusions.ts +0 -42
- package/src/mcp/render.ts +0 -123
- package/src/modes/components/agent-dashboard.ts +0 -1130
- package/src/modes/components/codemode-group.ts +0 -369
- package/src/modes/components/read-tool-group.ts +0 -119
- package/src/modes/components/visual-truncate.ts +0 -63
- package/src/prompts/system/subagent-user-prompt.md +0 -8
- package/src/prompts/tools/ask.md +0 -44
- package/src/prompts/tools/bash.md +0 -24
- package/src/prompts/tools/browser.md +0 -33
- package/src/prompts/tools/calculator.md +0 -12
- package/src/prompts/tools/explore.md +0 -29
- package/src/prompts/tools/fetch.md +0 -16
- package/src/prompts/tools/find.md +0 -18
- package/src/prompts/tools/gemini-image.md +0 -23
- package/src/prompts/tools/grep.md +0 -28
- package/src/prompts/tools/hashline.md +0 -232
- package/src/prompts/tools/librarian.md +0 -24
- package/src/prompts/tools/lsp.md +0 -28
- package/src/prompts/tools/oracle.md +0 -26
- package/src/prompts/tools/patch.md +0 -74
- package/src/prompts/tools/python.md +0 -66
- package/src/prompts/tools/read.md +0 -36
- package/src/prompts/tools/replace.md +0 -38
- package/src/prompts/tools/reviewer.md +0 -41
- package/src/prompts/tools/ssh.md +0 -51
- package/src/prompts/tools/task-summary.md +0 -28
- package/src/prompts/tools/task.md +0 -146
- package/src/prompts/tools/todo-write.md +0 -65
- package/src/prompts/tools/undo-edit.md +0 -7
- package/src/prompts/tools/web-search.md +0 -19
- package/src/prompts/tools/write.md +0 -18
- package/src/task/batch.ts +0 -102
- package/src/task/discovery.ts +0 -126
- package/src/task/parallel.ts +0 -84
- package/src/task/template.ts +0 -32
- package/src/tools/calculator.ts +0 -537
- package/src/tools/jtd-to-typescript.ts +0 -198
- package/src/tools/renderers.ts +0 -60
- package/src/tools/tool-result.ts +0 -86
- /package/src/{modes/theme → theme}/dark.json +0 -0
- /package/src/{modes/theme → theme}/defaults/dark-catppuccin.json +0 -0
- /package/src/{modes/theme → theme}/defaults/dark-dracula.json +0 -0
- /package/src/{modes/theme → theme}/defaults/dark-gruvbox.json +0 -0
- /package/src/{modes/theme → theme}/defaults/dark-solarized.json +0 -0
- /package/src/{modes/theme → theme}/defaults/dark-tokyo-night.json +0 -0
- /package/src/{modes/theme → theme}/defaults/index.ts +0 -0
- /package/src/{modes/theme → theme}/defaults/light-catppuccin.json +0 -0
- /package/src/{modes/theme → theme}/defaults/light-github.json +0 -0
- /package/src/{modes/theme → theme}/defaults/light-solarized.json +0 -0
- /package/src/{modes/theme → theme}/light.json +0 -0
- /package/src/{modes/theme → theme}/mermaid-cache.ts +0 -0
- /package/src/{modes/theme → theme}/theme-schema.json +0 -0
- /package/src/{modes/theme → theme}/theme.ts +0 -0
package/src/task/executor.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* In-process
|
|
2
|
+
* In-process subagent executor.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Manages agent lifecycle (session creation, abort handling, cleanup) and
|
|
5
|
+
* forwards AgentEvents to an EventBus. All observation (progress tracking,
|
|
6
|
+
* output extraction, usage accumulation) is the caller's responsibility
|
|
7
|
+
* via EventBus subscriptions.
|
|
5
8
|
*/
|
|
6
9
|
import * as path from "node:path";
|
|
7
10
|
import type { AgentEvent, ThinkingLevel } from "@nghyane/arcane-agent";
|
|
@@ -20,23 +23,14 @@ import { createAgentSession, discoverAuthStorage } from "../sdk";
|
|
|
20
23
|
import type { AgentSession, AgentSessionEvent } from "../session/agent-session";
|
|
21
24
|
import type { AuthStorage } from "../session/auth-storage";
|
|
22
25
|
import { SessionManager } from "../session/session-manager";
|
|
23
|
-
import {
|
|
26
|
+
import type { ContextFileEntry } from "../tools";
|
|
24
27
|
import { ToolAbortError } from "../tools/tool-errors";
|
|
25
28
|
import type { EventBus } from "../utils/event-bus";
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
type AgentDefinition,
|
|
29
|
-
type AgentProgress,
|
|
30
|
-
MAX_OUTPUT_BYTES,
|
|
31
|
-
MAX_OUTPUT_LINES,
|
|
32
|
-
type SingleResult,
|
|
33
|
-
TASK_SUBAGENT_EVENT_CHANNEL,
|
|
34
|
-
TASK_SUBAGENT_PROGRESS_CHANNEL,
|
|
35
|
-
} from "./types";
|
|
29
|
+
import { type AgentDefinition, type SingleResult, TASK_SUBAGENT_EVENT_CHANNEL } from "./types";
|
|
36
30
|
|
|
37
31
|
const MCP_CALL_TIMEOUT_MS = 60_000;
|
|
38
32
|
|
|
39
|
-
/** Agent event types
|
|
33
|
+
/** Agent event types worth forwarding. */
|
|
40
34
|
const agentEventTypes = new Set<AgentEvent["type"]>([
|
|
41
35
|
"agent_start",
|
|
42
36
|
"agent_end",
|
|
@@ -110,13 +104,13 @@ export interface ExecutorOptions {
|
|
|
110
104
|
isSubagent?: boolean;
|
|
111
105
|
enableLsp?: boolean;
|
|
112
106
|
signal?: AbortSignal;
|
|
113
|
-
onProgress?: (progress: AgentProgress) => void;
|
|
114
107
|
sessionFile?: string | null;
|
|
115
108
|
persistArtifacts?: boolean;
|
|
116
109
|
artifactsDir?: string;
|
|
117
110
|
/** Path to parent conversation context file */
|
|
118
111
|
contextFile?: string;
|
|
119
|
-
|
|
112
|
+
/** EventBus for forwarding agent events. Required — all observation happens here. */
|
|
113
|
+
eventBus: EventBus;
|
|
120
114
|
contextFiles?: ContextFileEntry[];
|
|
121
115
|
skills?: Skill[];
|
|
122
116
|
preloadedSkills?: Skill[];
|
|
@@ -127,55 +121,6 @@ export interface ExecutorOptions {
|
|
|
127
121
|
settings?: Settings;
|
|
128
122
|
}
|
|
129
123
|
|
|
130
|
-
/**
|
|
131
|
-
* Extract a short preview from tool args for display.
|
|
132
|
-
*/
|
|
133
|
-
function extractToolArgsPreview(args: Record<string, unknown>): string {
|
|
134
|
-
// Priority order for preview
|
|
135
|
-
const previewKeys = ["command", "file_path", "path", "pattern", "query", "url", "task", "prompt"];
|
|
136
|
-
|
|
137
|
-
for (const key of previewKeys) {
|
|
138
|
-
if (args[key] && typeof args[key] === "string") {
|
|
139
|
-
const value = args[key] as string;
|
|
140
|
-
return value.length > 60 ? `${value.slice(0, 59)}…` : value;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
return "";
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
function getNumberField(record: Record<string, unknown>, key: string): number | undefined {
|
|
148
|
-
if (!Object.hasOwn(record, key)) return undefined;
|
|
149
|
-
const value = record[key];
|
|
150
|
-
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
function firstNumberField(record: Record<string, unknown>, keys: string[]): number | undefined {
|
|
154
|
-
for (const key of keys) {
|
|
155
|
-
const value = getNumberField(record, key);
|
|
156
|
-
if (value !== undefined) return value;
|
|
157
|
-
}
|
|
158
|
-
return undefined;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Normalize usage objects from different event formats.
|
|
163
|
-
*/
|
|
164
|
-
function getUsageTokens(usage: unknown): number {
|
|
165
|
-
if (!usage || typeof usage !== "object") return 0;
|
|
166
|
-
const record = usage as Record<string, unknown>;
|
|
167
|
-
|
|
168
|
-
const totalTokens = firstNumberField(record, ["totalTokens", "total_tokens"]);
|
|
169
|
-
if (totalTokens !== undefined && totalTokens > 0) return totalTokens;
|
|
170
|
-
|
|
171
|
-
const input = firstNumberField(record, ["input", "input_tokens", "inputTokens"]) ?? 0;
|
|
172
|
-
const output = firstNumberField(record, ["output", "output_tokens", "outputTokens"]) ?? 0;
|
|
173
|
-
const cacheRead = firstNumberField(record, ["cacheRead", "cache_read", "cacheReadTokens"]) ?? 0;
|
|
174
|
-
const cacheWrite = firstNumberField(record, ["cacheWrite", "cache_write", "cacheWriteTokens"]) ?? 0;
|
|
175
|
-
|
|
176
|
-
return input + output + cacheRead + cacheWrite;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
124
|
/**
|
|
180
125
|
* Create proxy tools that reuse the parent's MCP connections.
|
|
181
126
|
*/
|
|
@@ -188,9 +133,7 @@ function createMCPProxyTools(mcpManager: MCPManager): CustomTool<TSchema>[] {
|
|
|
188
133
|
description: tool.description ?? "",
|
|
189
134
|
parameters: tool.parameters as TSchema,
|
|
190
135
|
execute: async (_toolCallId, params, _onUpdate, _ctx, signal) => {
|
|
191
|
-
if (signal?.aborted)
|
|
192
|
-
throw new ToolAbortError();
|
|
193
|
-
}
|
|
136
|
+
if (signal?.aborted) throw new ToolAbortError();
|
|
194
137
|
const serverName = mcpTool.mcpServerName ?? "";
|
|
195
138
|
const mcpToolName = mcpTool.mcpToolName ?? "";
|
|
196
139
|
try {
|
|
@@ -231,28 +174,14 @@ function createMCPProxyTools(mcpManager: MCPManager): CustomTool<TSchema>[] {
|
|
|
231
174
|
|
|
232
175
|
/**
|
|
233
176
|
* Run a single agent in-process.
|
|
177
|
+
*
|
|
178
|
+
* Forwards all AgentEvents to options.eventBus. Callers observe progress,
|
|
179
|
+
* usage, and output by subscribing to the bus before calling this function.
|
|
234
180
|
*/
|
|
235
181
|
export async function runAgent(options: ExecutorOptions): Promise<SingleResult> {
|
|
236
|
-
const { cwd, agent, task, index, id, modelOverride, thinkingLevel, enableLsp, signal,
|
|
182
|
+
const { cwd, agent, task, index, id, modelOverride, thinkingLevel, enableLsp, signal, eventBus } = options;
|
|
237
183
|
const startTime = Date.now();
|
|
238
184
|
|
|
239
|
-
// Initialize progress
|
|
240
|
-
const progress: AgentProgress = {
|
|
241
|
-
index,
|
|
242
|
-
id,
|
|
243
|
-
agent: agent.name,
|
|
244
|
-
status: "running",
|
|
245
|
-
task,
|
|
246
|
-
description: options.description,
|
|
247
|
-
lastIntent: undefined,
|
|
248
|
-
recentTools: [],
|
|
249
|
-
recentOutput: [],
|
|
250
|
-
toolCount: 0,
|
|
251
|
-
tokens: 0,
|
|
252
|
-
durationMs: 0,
|
|
253
|
-
toolHistory: [],
|
|
254
|
-
};
|
|
255
|
-
|
|
256
185
|
// Check if already aborted
|
|
257
186
|
if (signal?.aborted) {
|
|
258
187
|
return {
|
|
@@ -262,16 +191,14 @@ export async function runAgent(options: ExecutorOptions): Promise<SingleResult>
|
|
|
262
191
|
task,
|
|
263
192
|
description: options.description,
|
|
264
193
|
exitCode: 1,
|
|
265
|
-
output: "",
|
|
266
194
|
stderr: "Aborted before start",
|
|
267
|
-
truncated: false,
|
|
268
195
|
durationMs: 0,
|
|
269
196
|
tokens: 0,
|
|
270
197
|
error: "Aborted",
|
|
271
198
|
};
|
|
272
199
|
}
|
|
273
200
|
|
|
274
|
-
// Set up artifact paths
|
|
201
|
+
// Set up artifact paths
|
|
275
202
|
let subtaskSessionFile: string | undefined;
|
|
276
203
|
if (options.artifactsDir) {
|
|
277
204
|
subtaskSessionFile = path.join(options.artifactsDir, `${id}.jsonl`);
|
|
@@ -279,12 +206,9 @@ export async function runAgent(options: ExecutorOptions): Promise<SingleResult>
|
|
|
279
206
|
|
|
280
207
|
const settings = options.settings ?? Settings.isolated();
|
|
281
208
|
// Sub-agents never get the task tool — no recursive nesting
|
|
282
|
-
let toolNames
|
|
283
|
-
if (agent.tools && agent.tools.length > 0) {
|
|
284
|
-
toolNames = agent.tools.filter(name => name !== "task");
|
|
285
|
-
}
|
|
209
|
+
let toolNames = agent.tools.filter(name => name !== "task");
|
|
286
210
|
const pythonToolMode = settings.get("python.toolMode") ?? "both";
|
|
287
|
-
if (toolNames
|
|
211
|
+
if (toolNames.includes("exec")) {
|
|
288
212
|
const expanded = toolNames.filter(name => name !== "exec");
|
|
289
213
|
if (pythonToolMode === "bash-only") {
|
|
290
214
|
expanded.push("bash");
|
|
@@ -298,14 +222,9 @@ export async function runAgent(options: ExecutorOptions): Promise<SingleResult>
|
|
|
298
222
|
|
|
299
223
|
const modelPatterns = normalizeModelPatterns(modelOverride ?? agent.model);
|
|
300
224
|
const sessionFile = subtaskSessionFile ?? null;
|
|
301
|
-
|
|
302
225
|
const lspEnabled = enableLsp ?? true;
|
|
303
226
|
const skipPythonPreflight = Array.isArray(toolNames) && !toolNames.includes("python");
|
|
304
227
|
|
|
305
|
-
const outputChunks: string[] = [];
|
|
306
|
-
const finalOutputChunks: string[] = [];
|
|
307
|
-
const RECENT_OUTPUT_TAIL_BYTES = 8 * 1024;
|
|
308
|
-
let recentOutputTail = "";
|
|
309
228
|
let stderr = "";
|
|
310
229
|
let resolved = false;
|
|
311
230
|
type AbortReason = "signal" | "terminate";
|
|
@@ -318,17 +237,6 @@ export async function runAgent(options: ExecutorOptions): Promise<SingleResult>
|
|
|
318
237
|
let activeSession: AgentSession | null = null;
|
|
319
238
|
let unsubscribe: (() => void) | null = null;
|
|
320
239
|
|
|
321
|
-
// Accumulate usage incrementally from message_end events (no memory for streaming events)
|
|
322
|
-
const accumulatedUsage = {
|
|
323
|
-
input: 0,
|
|
324
|
-
output: 0,
|
|
325
|
-
cacheRead: 0,
|
|
326
|
-
cacheWrite: 0,
|
|
327
|
-
totalTokens: 0,
|
|
328
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
329
|
-
};
|
|
330
|
-
let hasUsage = false;
|
|
331
|
-
|
|
332
240
|
const requestAbort = (reason: AbortReason) => {
|
|
333
241
|
if (abortSent) {
|
|
334
242
|
if (reason === "signal" && abortReason !== "signal") {
|
|
@@ -345,6 +253,11 @@ export async function runAgent(options: ExecutorOptions): Promise<SingleResult>
|
|
|
345
253
|
}
|
|
346
254
|
};
|
|
347
255
|
|
|
256
|
+
/** Allow external observers (e.g. ProgressTracker) to request termination. */
|
|
257
|
+
const terminateListener = eventBus.on("executor:terminate", () => {
|
|
258
|
+
requestAbort("terminate");
|
|
259
|
+
});
|
|
260
|
+
|
|
348
261
|
// Handle abort signal
|
|
349
262
|
const onAbort = () => {
|
|
350
263
|
if (!resolved) requestAbort("signal");
|
|
@@ -353,273 +266,15 @@ export async function runAgent(options: ExecutorOptions): Promise<SingleResult>
|
|
|
353
266
|
signal.addEventListener("abort", onAbort, { once: true, signal: listenerSignal });
|
|
354
267
|
}
|
|
355
268
|
|
|
356
|
-
|
|
357
|
-
let lastProgressEmitMs = 0;
|
|
358
|
-
let progressTimeoutId: NodeJS.Timeout | null = null;
|
|
359
|
-
|
|
360
|
-
const emitProgressNow = () => {
|
|
361
|
-
progress.durationMs = Date.now() - startTime;
|
|
362
|
-
onProgress?.({ ...progress });
|
|
363
|
-
if (options.eventBus) {
|
|
364
|
-
options.eventBus.emit(TASK_SUBAGENT_PROGRESS_CHANNEL, {
|
|
365
|
-
index,
|
|
366
|
-
agent: agent.name,
|
|
367
|
-
task,
|
|
368
|
-
progress: { ...progress },
|
|
369
|
-
});
|
|
370
|
-
}
|
|
371
|
-
lastProgressEmitMs = Date.now();
|
|
372
|
-
};
|
|
373
|
-
|
|
374
|
-
const scheduleProgress = (flush = false) => {
|
|
375
|
-
if (flush) {
|
|
376
|
-
if (progressTimeoutId) {
|
|
377
|
-
clearTimeout(progressTimeoutId);
|
|
378
|
-
progressTimeoutId = null;
|
|
379
|
-
}
|
|
380
|
-
emitProgressNow();
|
|
381
|
-
return;
|
|
382
|
-
}
|
|
383
|
-
const now = Date.now();
|
|
384
|
-
const elapsed = now - lastProgressEmitMs;
|
|
385
|
-
if (lastProgressEmitMs === 0 || elapsed >= PROGRESS_COALESCE_MS) {
|
|
386
|
-
if (progressTimeoutId) {
|
|
387
|
-
clearTimeout(progressTimeoutId);
|
|
388
|
-
progressTimeoutId = null;
|
|
389
|
-
}
|
|
390
|
-
emitProgressNow();
|
|
391
|
-
return;
|
|
392
|
-
}
|
|
393
|
-
if (progressTimeoutId) return;
|
|
394
|
-
progressTimeoutId = setTimeout(() => {
|
|
395
|
-
progressTimeoutId = null;
|
|
396
|
-
emitProgressNow();
|
|
397
|
-
}, PROGRESS_COALESCE_MS - elapsed);
|
|
398
|
-
};
|
|
399
|
-
|
|
400
|
-
const getMessageContent = (message: unknown): unknown => {
|
|
401
|
-
if (message && typeof message === "object" && "content" in message) {
|
|
402
|
-
return (message as { content?: unknown }).content;
|
|
403
|
-
}
|
|
404
|
-
return undefined;
|
|
405
|
-
};
|
|
406
|
-
|
|
407
|
-
const getMessageUsage = (message: unknown): unknown => {
|
|
408
|
-
if (message && typeof message === "object" && "usage" in message) {
|
|
409
|
-
return (message as { usage?: unknown }).usage;
|
|
410
|
-
}
|
|
411
|
-
return undefined;
|
|
412
|
-
};
|
|
413
|
-
|
|
414
|
-
const updateRecentOutputLines = () => {
|
|
415
|
-
const lines = recentOutputTail.split("\n").filter(line => line.trim());
|
|
416
|
-
progress.recentOutput = lines.slice(-8).reverse();
|
|
417
|
-
};
|
|
418
|
-
|
|
419
|
-
const appendRecentOutputTail = (text: string) => {
|
|
420
|
-
if (!text) return;
|
|
421
|
-
recentOutputTail += text;
|
|
422
|
-
if (recentOutputTail.length > RECENT_OUTPUT_TAIL_BYTES) {
|
|
423
|
-
recentOutputTail = recentOutputTail.slice(-RECENT_OUTPUT_TAIL_BYTES);
|
|
424
|
-
}
|
|
425
|
-
updateRecentOutputLines();
|
|
426
|
-
};
|
|
427
|
-
|
|
428
|
-
const replaceRecentOutputFromContent = (content: unknown[]) => {
|
|
429
|
-
recentOutputTail = "";
|
|
430
|
-
for (const block of content) {
|
|
431
|
-
if (!block || typeof block !== "object") continue;
|
|
432
|
-
const record = block as { type?: unknown; text?: unknown };
|
|
433
|
-
if (record.type !== "text" || typeof record.text !== "string") continue;
|
|
434
|
-
if (!record.text) continue;
|
|
435
|
-
recentOutputTail += record.text;
|
|
436
|
-
if (recentOutputTail.length > RECENT_OUTPUT_TAIL_BYTES) {
|
|
437
|
-
recentOutputTail = recentOutputTail.slice(-RECENT_OUTPUT_TAIL_BYTES);
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
updateRecentOutputLines();
|
|
441
|
-
};
|
|
442
|
-
|
|
443
|
-
const resetRecentOutput = () => {
|
|
444
|
-
recentOutputTail = "";
|
|
445
|
-
progress.recentOutput = [];
|
|
446
|
-
};
|
|
447
|
-
|
|
269
|
+
// Forward agent events to EventBus — the only thing processEvent does
|
|
448
270
|
const processEvent = (event: AgentEvent) => {
|
|
449
271
|
if (resolved) return;
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
event,
|
|
457
|
-
});
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
const now = Date.now();
|
|
461
|
-
let flushProgress = false;
|
|
462
|
-
|
|
463
|
-
switch (event.type) {
|
|
464
|
-
case "message_start":
|
|
465
|
-
if (event.message?.role === "assistant") {
|
|
466
|
-
resetRecentOutput();
|
|
467
|
-
}
|
|
468
|
-
break;
|
|
469
|
-
|
|
470
|
-
case "tool_execution_start": {
|
|
471
|
-
// Skip Code Mode sub-tool events — they inflate toolCount and corrupt currentTool tracking
|
|
472
|
-
if (event.parentToolCallId) break;
|
|
473
|
-
progress.toolCount++;
|
|
474
|
-
progress.currentTool = event.toolName;
|
|
475
|
-
progress.currentToolArgs = extractToolArgsPreview(
|
|
476
|
-
(event as { toolArgs?: Record<string, unknown> }).toolArgs || event.args || {},
|
|
477
|
-
);
|
|
478
|
-
progress.currentToolStartMs = now;
|
|
479
|
-
const intent = event.intent?.trim();
|
|
480
|
-
if (intent) {
|
|
481
|
-
progress.lastIntent = intent;
|
|
482
|
-
}
|
|
483
|
-
// Add running entry to history (capped at 50)
|
|
484
|
-
if (progress.toolHistory.length < 50) {
|
|
485
|
-
progress.toolHistory.push({
|
|
486
|
-
tool: event.toolName,
|
|
487
|
-
args: progress.currentToolArgs,
|
|
488
|
-
status: "running",
|
|
489
|
-
});
|
|
490
|
-
}
|
|
491
|
-
break;
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
case "tool_execution_end": {
|
|
495
|
-
// Skip Code Mode sub-tool events
|
|
496
|
-
if (event.parentToolCallId) break;
|
|
497
|
-
const isError = !!(event as { isError?: boolean }).isError;
|
|
498
|
-
if (progress.currentTool) {
|
|
499
|
-
progress.recentTools.unshift({
|
|
500
|
-
tool: progress.currentTool,
|
|
501
|
-
args: progress.currentToolArgs || "",
|
|
502
|
-
endMs: now,
|
|
503
|
-
});
|
|
504
|
-
if (progress.recentTools.length > 5) {
|
|
505
|
-
progress.recentTools.pop();
|
|
506
|
-
}
|
|
507
|
-
// Update the last running entry in history to final status
|
|
508
|
-
for (let i = progress.toolHistory.length - 1; i >= 0; i--) {
|
|
509
|
-
if (progress.toolHistory[i].status === "running") {
|
|
510
|
-
progress.toolHistory[i].status = isError ? "error" : "success";
|
|
511
|
-
break;
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
progress.currentTool = undefined;
|
|
516
|
-
progress.currentToolArgs = undefined;
|
|
517
|
-
progress.currentToolStartMs = undefined;
|
|
518
|
-
|
|
519
|
-
// Check for registered subagent tool handler
|
|
520
|
-
const handler = subprocessToolRegistry.getHandler(event.toolName);
|
|
521
|
-
const eventArgs = (event as { args?: Record<string, unknown> }).args ?? {};
|
|
522
|
-
if (handler) {
|
|
523
|
-
// Check if handler wants to terminate the session
|
|
524
|
-
if (
|
|
525
|
-
handler.shouldTerminate?.({
|
|
526
|
-
toolName: event.toolName,
|
|
527
|
-
toolCallId: event.toolCallId,
|
|
528
|
-
args: eventArgs,
|
|
529
|
-
result: event.result,
|
|
530
|
-
isError: event.isError,
|
|
531
|
-
})
|
|
532
|
-
) {
|
|
533
|
-
requestAbort("terminate");
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
flushProgress = true;
|
|
537
|
-
break;
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
case "message_update": {
|
|
541
|
-
if (event.message?.role !== "assistant") break;
|
|
542
|
-
const assistantEvent = (
|
|
543
|
-
event as AgentEvent & {
|
|
544
|
-
assistantMessageEvent?: { type?: string; delta?: string };
|
|
545
|
-
}
|
|
546
|
-
).assistantMessageEvent;
|
|
547
|
-
if (assistantEvent?.type === "text_delta" && typeof assistantEvent.delta === "string") {
|
|
548
|
-
appendRecentOutputTail(assistantEvent.delta);
|
|
549
|
-
break;
|
|
550
|
-
}
|
|
551
|
-
if (assistantEvent && assistantEvent.type !== "text_delta") {
|
|
552
|
-
break;
|
|
553
|
-
}
|
|
554
|
-
const updateContent =
|
|
555
|
-
getMessageContent(event.message) || (event as AgentEvent & { content?: unknown }).content;
|
|
556
|
-
if (updateContent && Array.isArray(updateContent)) {
|
|
557
|
-
replaceRecentOutputFromContent(updateContent);
|
|
558
|
-
}
|
|
559
|
-
break;
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
case "message_end": {
|
|
563
|
-
// Extract text from assistant and toolResult messages (not user prompts)
|
|
564
|
-
const role = event.message?.role;
|
|
565
|
-
if (role === "assistant") {
|
|
566
|
-
const messageContent =
|
|
567
|
-
getMessageContent(event.message) || (event as AgentEvent & { content?: unknown }).content;
|
|
568
|
-
if (messageContent && Array.isArray(messageContent)) {
|
|
569
|
-
for (const block of messageContent) {
|
|
570
|
-
if (block.type === "text" && block.text) {
|
|
571
|
-
outputChunks.push(block.text);
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
// Extract and accumulate usage (prefer message.usage, fallback to event.usage)
|
|
577
|
-
const messageUsage = getMessageUsage(event.message) || (event as AgentEvent & { usage?: unknown }).usage;
|
|
578
|
-
if (messageUsage && typeof messageUsage === "object") {
|
|
579
|
-
// Only count assistant messages (not tool results, etc.)
|
|
580
|
-
if (role === "assistant") {
|
|
581
|
-
const usageRecord = messageUsage as Record<string, unknown>;
|
|
582
|
-
const costRecord = (messageUsage as { cost?: Record<string, unknown> }).cost;
|
|
583
|
-
hasUsage = true;
|
|
584
|
-
accumulatedUsage.input += getNumberField(usageRecord, "input") ?? 0;
|
|
585
|
-
accumulatedUsage.output += getNumberField(usageRecord, "output") ?? 0;
|
|
586
|
-
accumulatedUsage.cacheRead += getNumberField(usageRecord, "cacheRead") ?? 0;
|
|
587
|
-
accumulatedUsage.cacheWrite += getNumberField(usageRecord, "cacheWrite") ?? 0;
|
|
588
|
-
accumulatedUsage.totalTokens += getNumberField(usageRecord, "totalTokens") ?? 0;
|
|
589
|
-
if (costRecord) {
|
|
590
|
-
accumulatedUsage.cost.input += getNumberField(costRecord, "input") ?? 0;
|
|
591
|
-
accumulatedUsage.cost.output += getNumberField(costRecord, "output") ?? 0;
|
|
592
|
-
accumulatedUsage.cost.cacheRead += getNumberField(costRecord, "cacheRead") ?? 0;
|
|
593
|
-
accumulatedUsage.cost.cacheWrite += getNumberField(costRecord, "cacheWrite") ?? 0;
|
|
594
|
-
accumulatedUsage.cost.total += getNumberField(costRecord, "total") ?? 0;
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
// Accumulate tokens for progress display
|
|
598
|
-
progress.tokens += getUsageTokens(messageUsage);
|
|
599
|
-
}
|
|
600
|
-
break;
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
case "agent_end":
|
|
604
|
-
// Extract final content from assistant messages only (not user prompts)
|
|
605
|
-
if (event.messages && Array.isArray(event.messages)) {
|
|
606
|
-
for (const msg of event.messages) {
|
|
607
|
-
if ((msg as { role?: string })?.role !== "assistant") continue;
|
|
608
|
-
const messageContent = getMessageContent(msg);
|
|
609
|
-
if (messageContent && Array.isArray(messageContent)) {
|
|
610
|
-
for (const block of messageContent) {
|
|
611
|
-
if (block.type === "text" && block.text) {
|
|
612
|
-
finalOutputChunks.push(block.text);
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
flushProgress = true;
|
|
619
|
-
break;
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
scheduleProgress(flushProgress);
|
|
272
|
+
eventBus.emit(TASK_SUBAGENT_EVENT_CHANNEL, {
|
|
273
|
+
index,
|
|
274
|
+
agent: agent.name,
|
|
275
|
+
task,
|
|
276
|
+
event,
|
|
277
|
+
});
|
|
623
278
|
};
|
|
624
279
|
|
|
625
280
|
const runSubagent = async (): Promise<{
|
|
@@ -646,7 +301,10 @@ export async function runAgent(options: ExecutorOptions): Promise<SingleResult>
|
|
|
646
301
|
const authStorage = options.authStorage ?? (await discoverAuthStorage());
|
|
647
302
|
checkAbort();
|
|
648
303
|
const modelRegistry = options.modelRegistry ?? new ModelRegistry(authStorage);
|
|
649
|
-
|
|
304
|
+
// Skip refresh when reusing parent's registry — models are already discovered
|
|
305
|
+
if (!options.modelRegistry) {
|
|
306
|
+
await modelRegistry.refresh();
|
|
307
|
+
}
|
|
650
308
|
checkAbort();
|
|
651
309
|
|
|
652
310
|
const { model, thinkingLevel: resolvedThinkingLevel } = resolveModelOverride(
|
|
@@ -681,13 +339,13 @@ export async function runAgent(options: ExecutorOptions): Promise<SingleResult>
|
|
|
681
339
|
}),
|
|
682
340
|
sessionManager,
|
|
683
341
|
hasUI: false,
|
|
684
|
-
spawns: "",
|
|
685
342
|
isSubagent: true,
|
|
686
343
|
parentTaskPrefix: id,
|
|
687
344
|
enableLsp: lspEnabled,
|
|
688
345
|
skipPythonPreflight,
|
|
689
346
|
enableMCP,
|
|
690
347
|
customTools: mcpProxyTools.length > 0 ? mcpProxyTools : undefined,
|
|
348
|
+
disableExtensionDiscovery: true,
|
|
691
349
|
});
|
|
692
350
|
|
|
693
351
|
activeSession = session;
|
|
@@ -717,15 +375,15 @@ export async function runAgent(options: ExecutorOptions): Promise<SingleResult>
|
|
|
717
375
|
if (extensionRunner) {
|
|
718
376
|
extensionRunner.initialize(
|
|
719
377
|
{
|
|
720
|
-
sendMessage: (message,
|
|
721
|
-
session.sendCustomMessage(message,
|
|
378
|
+
sendMessage: (message, msgOptions) => {
|
|
379
|
+
session.sendCustomMessage(message, msgOptions).catch(e => {
|
|
722
380
|
logger.error("Extension sendMessage failed", {
|
|
723
381
|
error: e instanceof Error ? e.message : String(e),
|
|
724
382
|
});
|
|
725
383
|
});
|
|
726
384
|
},
|
|
727
|
-
sendUserMessage: (content,
|
|
728
|
-
session.sendUserMessage(content,
|
|
385
|
+
sendUserMessage: (content, msgOptions) => {
|
|
386
|
+
session.sendUserMessage(content, msgOptions).catch(e => {
|
|
729
387
|
logger.error("Extension sendUserMessage failed", {
|
|
730
388
|
error: e instanceof Error ? e.message : String(e),
|
|
731
389
|
});
|
|
@@ -739,13 +397,13 @@ export async function runAgent(options: ExecutorOptions): Promise<SingleResult>
|
|
|
739
397
|
},
|
|
740
398
|
getActiveTools: () => session.getActiveToolNames(),
|
|
741
399
|
getAllTools: () => session.getAllToolNames(),
|
|
742
|
-
setActiveTools: (
|
|
743
|
-
session.setActiveToolsByName(
|
|
400
|
+
setActiveTools: (names: string[]) =>
|
|
401
|
+
session.setActiveToolsByName(names.filter(name => !parentOwnedToolNames.has(name))),
|
|
744
402
|
getCommands: () => [],
|
|
745
|
-
setModel: async
|
|
746
|
-
const key = await session.modelRegistry.getApiKey(
|
|
403
|
+
setModel: async modelStr => {
|
|
404
|
+
const key = await session.modelRegistry.getApiKey(modelStr);
|
|
747
405
|
if (!key) return false;
|
|
748
|
-
await session.setModel(
|
|
406
|
+
await session.setModel(modelStr);
|
|
749
407
|
return true;
|
|
750
408
|
},
|
|
751
409
|
getThinkingLevel: () => session.thinkingLevel,
|
|
@@ -761,17 +419,14 @@ export async function runAgent(options: ExecutorOptions): Promise<SingleResult>
|
|
|
761
419
|
getSystemPrompt: () => session.systemPrompt,
|
|
762
420
|
compact: async instructionsOrOptions => {
|
|
763
421
|
const instructions = typeof instructionsOrOptions === "string" ? instructionsOrOptions : undefined;
|
|
764
|
-
const
|
|
422
|
+
const compactOptions =
|
|
765
423
|
instructionsOrOptions && typeof instructionsOrOptions === "object"
|
|
766
424
|
? instructionsOrOptions
|
|
767
425
|
: undefined;
|
|
768
|
-
await session.compact(instructions,
|
|
426
|
+
await session.compact(instructions, compactOptions);
|
|
769
427
|
},
|
|
770
428
|
},
|
|
771
429
|
);
|
|
772
|
-
extensionRunner.onError(err => {
|
|
773
|
-
logger.error("Extension error", { path: err.extensionPath, error: err.error });
|
|
774
|
-
});
|
|
775
430
|
await extensionRunner.emit({ type: "session_start" });
|
|
776
431
|
}
|
|
777
432
|
|
|
@@ -841,45 +496,13 @@ export async function runAgent(options: ExecutorOptions): Promise<SingleResult>
|
|
|
841
496
|
const done = await runSubagent();
|
|
842
497
|
resolved = true;
|
|
843
498
|
listenerController.abort();
|
|
499
|
+
terminateListener();
|
|
844
500
|
|
|
845
|
-
if (progressTimeoutId) {
|
|
846
|
-
clearTimeout(progressTimeoutId);
|
|
847
|
-
progressTimeoutId = null;
|
|
848
|
-
}
|
|
849
|
-
|
|
850
|
-
const exitCode = done.exitCode;
|
|
851
501
|
if (done.error) {
|
|
852
502
|
stderr = done.error;
|
|
853
503
|
}
|
|
854
504
|
|
|
855
|
-
// Use final output if available, otherwise accumulated output
|
|
856
|
-
const rawOutput = finalOutputChunks.length > 0 ? finalOutputChunks.join("") : outputChunks.join("");
|
|
857
|
-
const { content: truncatedOutput, truncated } = truncateTail(rawOutput, {
|
|
858
|
-
maxBytes: MAX_OUTPUT_BYTES,
|
|
859
|
-
maxLines: MAX_OUTPUT_LINES,
|
|
860
|
-
});
|
|
861
|
-
|
|
862
|
-
// Write output artifact (input and jsonl already written in real-time)
|
|
863
|
-
// Compute output metadata for agent:// URL integration
|
|
864
|
-
let outputMeta: { lineCount: number; charCount: number } | undefined;
|
|
865
|
-
let outputPath: string | undefined;
|
|
866
|
-
if (options.artifactsDir) {
|
|
867
|
-
outputPath = path.join(options.artifactsDir, `${id}.md`);
|
|
868
|
-
try {
|
|
869
|
-
await Bun.write(outputPath, rawOutput);
|
|
870
|
-
outputMeta = {
|
|
871
|
-
lineCount: rawOutput.split("\n").length,
|
|
872
|
-
charCount: rawOutput.length,
|
|
873
|
-
};
|
|
874
|
-
} catch {
|
|
875
|
-
// Non-fatal
|
|
876
|
-
}
|
|
877
|
-
}
|
|
878
|
-
|
|
879
|
-
// Update final progress
|
|
880
505
|
const wasAborted = done.aborted || signal?.aborted || false;
|
|
881
|
-
progress.status = wasAborted ? "aborted" : exitCode === 0 ? "completed" : "failed";
|
|
882
|
-
scheduleProgress(true);
|
|
883
506
|
|
|
884
507
|
return {
|
|
885
508
|
index,
|
|
@@ -887,22 +510,11 @@ export async function runAgent(options: ExecutorOptions): Promise<SingleResult>
|
|
|
887
510
|
agent: agent.name,
|
|
888
511
|
task,
|
|
889
512
|
description: options.description,
|
|
890
|
-
|
|
891
|
-
exitCode,
|
|
892
|
-
output: truncatedOutput,
|
|
513
|
+
exitCode: done.exitCode,
|
|
893
514
|
stderr,
|
|
894
|
-
truncated,
|
|
895
515
|
durationMs: Date.now() - startTime,
|
|
896
|
-
tokens:
|
|
897
|
-
error: exitCode !== 0 && stderr ? stderr : undefined,
|
|
516
|
+
tokens: 0,
|
|
517
|
+
error: done.exitCode !== 0 && stderr ? stderr : undefined,
|
|
898
518
|
aborted: wasAborted,
|
|
899
|
-
usage: hasUsage ? accumulatedUsage : undefined,
|
|
900
|
-
outputPath,
|
|
901
|
-
outputMeta,
|
|
902
|
-
toolHistory: progress.toolHistory.map(t => ({
|
|
903
|
-
tool: t.tool,
|
|
904
|
-
args: t.args,
|
|
905
|
-
status: t.status === "running" ? ("error" as const) : t.status,
|
|
906
|
-
})),
|
|
907
519
|
};
|
|
908
520
|
}
|