openhorse 0.2.21 → 0.2.23
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/cli.js +25 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +189 -49
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/parser.d.ts.map +1 -1
- package/dist/commands/parser.js +8 -3
- package/dist/commands/parser.js.map +1 -1
- package/dist/commands/types.d.ts +2 -0
- package/dist/commands/types.d.ts.map +1 -1
- package/dist/commands/types.js.map +1 -1
- package/dist/core/cost-tracker.d.ts +45 -5
- package/dist/core/cost-tracker.d.ts.map +1 -1
- package/dist/core/cost-tracker.js +78 -13
- package/dist/core/cost-tracker.js.map +1 -1
- package/dist/framework/index.d.ts +1 -1
- package/dist/framework/index.d.ts.map +1 -1
- package/dist/framework/index.js.map +1 -1
- package/dist/framework/query.d.ts +25 -0
- package/dist/framework/query.d.ts.map +1 -1
- package/dist/framework/query.js +196 -49
- package/dist/framework/query.js.map +1 -1
- package/dist/framework/store.d.ts +6 -1
- package/dist/framework/store.d.ts.map +1 -1
- package/dist/framework/store.js +10 -1
- package/dist/framework/store.js.map +1 -1
- package/dist/harness/capsule.d.ts +1 -0
- package/dist/harness/capsule.d.ts.map +1 -1
- package/dist/harness/capsule.js +38 -9
- package/dist/harness/capsule.js.map +1 -1
- package/dist/harness/contract.d.ts +2 -0
- package/dist/harness/contract.d.ts.map +1 -1
- package/dist/harness/contract.js +78 -14
- package/dist/harness/contract.js.map +1 -1
- package/dist/harness/index.d.ts +2 -2
- package/dist/harness/index.d.ts.map +1 -1
- package/dist/harness/index.js +4 -1
- package/dist/harness/index.js.map +1 -1
- package/dist/harness/ledger.d.ts.map +1 -1
- package/dist/harness/ledger.js +6 -2
- package/dist/harness/ledger.js.map +1 -1
- package/dist/harness/state.d.ts.map +1 -1
- package/dist/harness/state.js +37 -7
- package/dist/harness/state.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/ink-ui/components/StatusLine.d.ts.map +1 -1
- package/dist/ink-ui/components/StatusLine.js +0 -2
- package/dist/ink-ui/components/StatusLine.js.map +1 -1
- package/dist/ink-ui/screens/ReplScreen.d.ts.map +1 -1
- package/dist/ink-ui/screens/ReplScreen.js +12 -5
- package/dist/ink-ui/screens/ReplScreen.js.map +1 -1
- package/dist/runtime/agent-runtime-controller.d.ts.map +1 -1
- package/dist/runtime/agent-runtime-controller.js +11 -1
- package/dist/runtime/agent-runtime-controller.js.map +1 -1
- package/dist/runtime/aggregate-tool-presenter.d.ts +13 -0
- package/dist/runtime/aggregate-tool-presenter.d.ts.map +1 -0
- package/dist/runtime/aggregate-tool-presenter.js +44 -0
- package/dist/runtime/aggregate-tool-presenter.js.map +1 -0
- package/dist/runtime/chat-controller.d.ts +9 -2
- package/dist/runtime/chat-controller.d.ts.map +1 -1
- package/dist/runtime/chat-controller.js +345 -90
- package/dist/runtime/chat-controller.js.map +1 -1
- package/dist/runtime/rich-text/ansi-parser.d.ts +1 -1
- package/dist/runtime/rich-text/ansi-parser.d.ts.map +1 -1
- package/dist/runtime/rich-text/ansi-parser.js +93 -55
- package/dist/runtime/rich-text/ansi-parser.js.map +1 -1
- package/dist/runtime/rich-text/layout.d.ts +2 -11
- package/dist/runtime/rich-text/layout.d.ts.map +1 -1
- package/dist/runtime/rich-text/layout.js +280 -245
- package/dist/runtime/rich-text/layout.js.map +1 -1
- package/dist/runtime/rich-text/markdown-parser.js +31 -24
- package/dist/runtime/rich-text/markdown-parser.js.map +1 -1
- package/dist/runtime/rich-text/types.d.ts +1 -1
- package/dist/runtime/rich-text/types.d.ts.map +1 -1
- package/dist/runtime/subagents/production.d.ts.map +1 -1
- package/dist/runtime/subagents/production.js +28 -3
- package/dist/runtime/subagents/production.js.map +1 -1
- package/dist/runtime/subagents/result-parser.d.ts.map +1 -1
- package/dist/runtime/subagents/result-parser.js +54 -40
- package/dist/runtime/subagents/result-parser.js.map +1 -1
- package/dist/runtime/subagents/types.d.ts +2 -0
- package/dist/runtime/subagents/types.d.ts.map +1 -1
- package/dist/runtime/subagents/types.js +5 -1
- package/dist/runtime/subagents/types.js.map +1 -1
- package/dist/runtime/tool-detail-repository.d.ts +45 -0
- package/dist/runtime/tool-detail-repository.d.ts.map +1 -0
- package/dist/runtime/tool-detail-repository.js +131 -0
- package/dist/runtime/tool-detail-repository.js.map +1 -0
- package/dist/runtime/tool-output-presentation.d.ts +89 -0
- package/dist/runtime/tool-output-presentation.d.ts.map +1 -0
- package/dist/runtime/tool-output-presentation.js +329 -0
- package/dist/runtime/tool-output-presentation.js.map +1 -0
- package/dist/runtime/ui-events.d.ts +17 -0
- package/dist/runtime/ui-events.d.ts.map +1 -1
- package/dist/runtime/ui-events.js.map +1 -1
- package/dist/runtime/ui-view-model.d.ts +9 -0
- package/dist/runtime/ui-view-model.d.ts.map +1 -1
- package/dist/runtime/ui-view-model.js +59 -37
- package/dist/runtime/ui-view-model.js.map +1 -1
- package/dist/services/compact/auto-compact.d.ts +15 -2
- package/dist/services/compact/auto-compact.d.ts.map +1 -1
- package/dist/services/compact/auto-compact.js +56 -24
- package/dist/services/compact/auto-compact.js.map +1 -1
- package/dist/services/compact/compact.d.ts +2 -0
- package/dist/services/compact/compact.d.ts.map +1 -1
- package/dist/services/compact/compact.js +22 -5
- package/dist/services/compact/compact.js.map +1 -1
- package/dist/services/compact/coordinator.d.ts +26 -0
- package/dist/services/compact/coordinator.d.ts.map +1 -0
- package/dist/services/compact/coordinator.js +44 -0
- package/dist/services/compact/coordinator.js.map +1 -0
- package/dist/services/compact/index.d.ts +1 -0
- package/dist/services/compact/index.d.ts.map +1 -1
- package/dist/services/compact/index.js +3 -1
- package/dist/services/compact/index.js.map +1 -1
- package/dist/services/compact/summary-generator.d.ts +6 -2
- package/dist/services/compact/summary-generator.d.ts.map +1 -1
- package/dist/services/compact/summary-generator.js +73 -31
- package/dist/services/compact/summary-generator.js.map +1 -1
- package/dist/services/config-dir.d.ts +11 -1
- package/dist/services/config-dir.d.ts.map +1 -1
- package/dist/services/config-dir.js +19 -2
- package/dist/services/config-dir.js.map +1 -1
- package/dist/services/config.d.ts +4 -2
- package/dist/services/config.d.ts.map +1 -1
- package/dist/services/config.js +40 -0
- package/dist/services/config.js.map +1 -1
- package/dist/services/doctor.d.ts +2 -0
- package/dist/services/doctor.d.ts.map +1 -1
- package/dist/services/doctor.js +8 -1
- package/dist/services/doctor.js.map +1 -1
- package/dist/services/global-config.d.ts +10 -0
- package/dist/services/global-config.d.ts.map +1 -1
- package/dist/services/global-config.js.map +1 -1
- package/dist/services/llm.d.ts +21 -4
- package/dist/services/llm.d.ts.map +1 -1
- package/dist/services/llm.js +66 -8
- package/dist/services/llm.js.map +1 -1
- package/dist/services/model-context.d.ts +36 -0
- package/dist/services/model-context.d.ts.map +1 -1
- package/dist/services/model-context.js +245 -32
- package/dist/services/model-context.js.map +1 -1
- package/dist/services/redaction.js +1 -1
- package/dist/services/redaction.js.map +1 -1
- package/dist/services/session-storage.d.ts +42 -1
- package/dist/services/session-storage.d.ts.map +1 -1
- package/dist/services/session-storage.js +175 -54
- package/dist/services/session-storage.js.map +1 -1
- package/dist/services/storage-maintenance.d.ts.map +1 -1
- package/dist/services/storage-maintenance.js +3 -2
- package/dist/services/storage-maintenance.js.map +1 -1
- package/dist/services/usage-state.d.ts +55 -5
- package/dist/services/usage-state.d.ts.map +1 -1
- package/dist/services/usage-state.js +185 -59
- package/dist/services/usage-state.js.map +1 -1
- package/dist/services/verification-profile.d.ts.map +1 -1
- package/dist/services/verification-profile.js +3 -2
- package/dist/services/verification-profile.js.map +1 -1
- package/dist/services/workspace-diff.d.ts.map +1 -1
- package/dist/services/workspace-diff.js +34 -3
- package/dist/services/workspace-diff.js.map +1 -1
- package/dist/services/yaml-config.js +1 -1
- package/dist/skills/runtime.d.ts +9 -5
- package/dist/skills/runtime.d.ts.map +1 -1
- package/dist/skills/runtime.js +157 -12
- package/dist/skills/runtime.js.map +1 -1
- package/dist/terminal-ui/editor.d.ts.map +1 -1
- package/dist/terminal-ui/editor.js +14 -3
- package/dist/terminal-ui/editor.js.map +1 -1
- package/dist/terminal-ui/launch.d.ts +21 -0
- package/dist/terminal-ui/launch.d.ts.map +1 -1
- package/dist/terminal-ui/launch.js +203 -45
- package/dist/terminal-ui/launch.js.map +1 -1
- package/dist/terminal-ui/output-queue.d.ts +43 -0
- package/dist/terminal-ui/output-queue.d.ts.map +1 -0
- package/dist/terminal-ui/output-queue.js +139 -0
- package/dist/terminal-ui/output-queue.js.map +1 -0
- package/dist/terminal-ui/raw-editor.d.ts +42 -0
- package/dist/terminal-ui/raw-editor.d.ts.map +1 -1
- package/dist/terminal-ui/raw-editor.js +337 -41
- package/dist/terminal-ui/raw-editor.js.map +1 -1
- package/dist/tools/bash_security.d.ts.map +1 -1
- package/dist/tools/bash_security.js +14 -5
- package/dist/tools/bash_security.js.map +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +176 -73
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/plan.d.ts.map +1 -1
- package/dist/tools/plan.js +7 -0
- package/dist/tools/plan.js.map +1 -1
- package/dist/tools/web.d.ts +10 -0
- package/dist/tools/web.d.ts.map +1 -1
- package/dist/tools/web.js +81 -1
- package/dist/tools/web.js.map +1 -1
- package/dist/tui-core/input-parser.d.ts +9 -2
- package/dist/tui-core/input-parser.d.ts.map +1 -1
- package/dist/tui-core/input-parser.js +57 -3
- package/dist/tui-core/input-parser.js.map +1 -1
- package/dist/tui-core/style.d.ts +16 -0
- package/dist/tui-core/style.d.ts.map +1 -1
- package/dist/tui-core/style.js +22 -1
- package/dist/tui-core/style.js.map +1 -1
- package/dist/tui-ui/inline-surface.d.ts +69 -12
- package/dist/tui-ui/inline-surface.d.ts.map +1 -1
- package/dist/tui-ui/inline-surface.js +366 -94
- package/dist/tui-ui/inline-surface.js.map +1 -1
- package/dist/tui-ui/input-ownership.d.ts +46 -0
- package/dist/tui-ui/input-ownership.d.ts.map +1 -0
- package/dist/tui-ui/input-ownership.js +74 -0
- package/dist/tui-ui/input-ownership.js.map +1 -0
- package/dist/tui-ui/launch.d.ts +2 -0
- package/dist/tui-ui/launch.d.ts.map +1 -1
- package/dist/tui-ui/launch.js +289 -43
- package/dist/tui-ui/launch.js.map +1 -1
- package/dist/tui-ui/layout.d.ts +52 -2
- package/dist/tui-ui/layout.d.ts.map +1 -1
- package/dist/tui-ui/layout.js +230 -76
- package/dist/tui-ui/layout.js.map +1 -1
- package/dist/tui-ui/runner.d.ts +101 -8
- package/dist/tui-ui/runner.d.ts.map +1 -1
- package/dist/tui-ui/runner.js +843 -51
- package/dist/tui-ui/runner.js.map +1 -1
- package/dist/tui-ui/state.d.ts +70 -4
- package/dist/tui-ui/state.d.ts.map +1 -1
- package/dist/tui-ui/state.js +251 -20
- package/dist/tui-ui/state.js.map +1 -1
- package/dist/tui-ui/theme-profile.d.ts +25 -0
- package/dist/tui-ui/theme-profile.d.ts.map +1 -0
- package/dist/tui-ui/theme-profile.js +130 -0
- package/dist/tui-ui/theme-profile.js.map +1 -0
- package/dist/tui-ui/theme.d.ts +13 -0
- package/dist/tui-ui/theme.d.ts.map +1 -0
- package/dist/tui-ui/theme.js +20 -0
- package/dist/tui-ui/theme.js.map +1 -0
- package/dist/tui-ui/transcript-cache.d.ts +5 -3
- package/dist/tui-ui/transcript-cache.d.ts.map +1 -1
- package/dist/tui-ui/transcript-cache.js +16 -9
- package/dist/tui-ui/transcript-cache.js.map +1 -1
- package/dist/tui-ui/transcript-inspector-layout.d.ts +9 -0
- package/dist/tui-ui/transcript-inspector-layout.d.ts.map +1 -0
- package/dist/tui-ui/transcript-inspector-layout.js +97 -0
- package/dist/tui-ui/transcript-inspector-layout.js.map +1 -0
- package/dist/tui-ui/transcript-inspector-surface.d.ts +18 -0
- package/dist/tui-ui/transcript-inspector-surface.d.ts.map +1 -0
- package/dist/tui-ui/transcript-inspector-surface.js +88 -0
- package/dist/tui-ui/transcript-inspector-surface.js.map +1 -0
- package/dist/tui-ui/transcript-inspector.d.ts +35 -0
- package/dist/tui-ui/transcript-inspector.d.ts.map +1 -0
- package/dist/tui-ui/transcript-inspector.js +128 -0
- package/dist/tui-ui/transcript-inspector.js.map +1 -0
- package/dist/tui-ui/transcript-layout.d.ts +22 -0
- package/dist/tui-ui/transcript-layout.d.ts.map +1 -0
- package/dist/tui-ui/transcript-layout.js +439 -0
- package/dist/tui-ui/transcript-layout.js.map +1 -0
- package/dist/ui/status-bar.d.ts +1 -1
- package/dist/ui/status-bar.d.ts.map +1 -1
- package/dist/ui/status-bar.js +2 -15
- package/dist/ui/status-bar.js.map +1 -1
- package/dist/ui-v2/components/shell.d.ts.map +1 -1
- package/dist/ui-v2/components/shell.js +0 -8
- package/dist/ui-v2/components/shell.js.map +1 -1
- package/package.json +1 -1
|
@@ -61,6 +61,8 @@ const ui_events_1 = require("./ui-events");
|
|
|
61
61
|
const ui_view_model_1 = require("./ui-view-model");
|
|
62
62
|
const agent_status_1 = require("./agent-status");
|
|
63
63
|
const loop_budget_1 = require("./loop-budget");
|
|
64
|
+
const tool_output_presentation_1 = require("./tool-output-presentation");
|
|
65
|
+
const aggregate_tool_presenter_1 = require("./aggregate-tool-presenter");
|
|
64
66
|
const ANSI_PATTERN = /\x1b\[[0-9;?]*[A-Za-z]/g;
|
|
65
67
|
const LOCAL_FAST_PATH_INLINE_OUTPUT_BYTES = 2048;
|
|
66
68
|
const TRACE_ARGS_ARTIFACT_THRESHOLD_BYTES = 160;
|
|
@@ -121,7 +123,18 @@ function compactMiddle(text, maxLength) {
|
|
|
121
123
|
return `${compact.slice(0, headLength)}...${compact.slice(-tailLength)}`;
|
|
122
124
|
}
|
|
123
125
|
function compactToolArgs(args, maxLength = 160) {
|
|
124
|
-
for (const key of [
|
|
126
|
+
for (const key of [
|
|
127
|
+
'path',
|
|
128
|
+
'file_path',
|
|
129
|
+
'file',
|
|
130
|
+
'cwd',
|
|
131
|
+
'command',
|
|
132
|
+
'pattern',
|
|
133
|
+
'query',
|
|
134
|
+
'url',
|
|
135
|
+
'target',
|
|
136
|
+
'sessionId',
|
|
137
|
+
]) {
|
|
125
138
|
const value = args[key];
|
|
126
139
|
if (typeof value === 'string') {
|
|
127
140
|
return compactMiddle(value, maxLength);
|
|
@@ -148,16 +161,14 @@ function buildTraceArgsDetails(projectPath, name, args) {
|
|
|
148
161
|
const argsSummary = compactToolArgs(args);
|
|
149
162
|
const fullArgs = (0, session_storage_1.redactTraceText)(fullToolArgsForTrace(name, args)).trim();
|
|
150
163
|
const argsBytes = byteLength(fullArgs);
|
|
151
|
-
if (!projectPath
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
164
|
+
if (!projectPath ||
|
|
165
|
+
!fullArgs ||
|
|
166
|
+
fullArgs === (0, session_storage_1.redactTraceText)(argsSummary) ||
|
|
167
|
+
argsBytes <= TRACE_ARGS_ARTIFACT_THRESHOLD_BYTES) {
|
|
155
168
|
return { argsSummary };
|
|
156
169
|
}
|
|
157
170
|
const artifact = (0, tool_artifacts_1.storeArtifact)(projectPath, `${name}-args`, fullArgs, argsBytes);
|
|
158
|
-
return artifact
|
|
159
|
-
? { argsSummary, argsArtifactId: artifact.id, argsBytes }
|
|
160
|
-
: { argsSummary };
|
|
171
|
+
return artifact ? { argsSummary, argsArtifactId: artifact.id, argsBytes } : { argsSummary };
|
|
161
172
|
}
|
|
162
173
|
function parseToolCallArgsForRuntime(toolCall) {
|
|
163
174
|
try {
|
|
@@ -211,7 +222,9 @@ function createPreToolCheckpoint(events, sessionId, turnId, checkpointId, cwd, t
|
|
|
211
222
|
checkpointFiles: checkpoint?.files.map(file => file.path) ?? [],
|
|
212
223
|
workspaceFiles: relativeTargets,
|
|
213
224
|
note: checkpoint
|
|
214
|
-
?
|
|
225
|
+
? risky
|
|
226
|
+
? 'risky_multi_file_checkpoint'
|
|
227
|
+
: 'pre_edit_checkpoint'
|
|
215
228
|
: 'pre_edit_checkpoint_skipped',
|
|
216
229
|
});
|
|
217
230
|
return { created: true, targetCount: targets.length, risky };
|
|
@@ -239,7 +252,9 @@ function formatWorkspaceFileForTrace(file) {
|
|
|
239
252
|
const metadata = [
|
|
240
253
|
typeof file.sizeBytes === 'number' ? `${file.sizeBytes}B` : '',
|
|
241
254
|
typeof file.mtimeMs === 'number' ? `mtime=${file.mtimeMs}` : '',
|
|
242
|
-
]
|
|
255
|
+
]
|
|
256
|
+
.filter(Boolean)
|
|
257
|
+
.join(' ');
|
|
243
258
|
return `${file.status} ${file.path}${metadata ? ` (${metadata})` : ''}`;
|
|
244
259
|
}
|
|
245
260
|
function appendWorkspaceSnapshotTrace(events, sessionId, turnId, phase, snapshot) {
|
|
@@ -275,19 +290,13 @@ function appendWorkspaceDeltaTrace(events, sessionId, turnId, before, after) {
|
|
|
275
290
|
return delta;
|
|
276
291
|
}
|
|
277
292
|
function workspaceDeltaHasTurnChanges(delta) {
|
|
278
|
-
return delta.newFilesByTurn.length > 0
|
|
279
|
-
|
|
280
|
-
|
|
293
|
+
return (delta.newFilesByTurn.length > 0 ||
|
|
294
|
+
delta.changedByTurn.length > 0 ||
|
|
295
|
+
delta.resolvedByTurn.length > 0);
|
|
281
296
|
}
|
|
282
297
|
function formatFailureRecoveryNotice(turnId, delta, checkpointIds) {
|
|
283
|
-
const files = compactPathList([
|
|
284
|
-
|
|
285
|
-
...delta.changedByTurn,
|
|
286
|
-
...delta.resolvedByTurn,
|
|
287
|
-
], 8);
|
|
288
|
-
const fileText = files.length > 0
|
|
289
|
-
? files.join(', ')
|
|
290
|
-
: 'workspace changes recorded';
|
|
298
|
+
const files = compactPathList([...delta.newFilesByTurn, ...delta.changedByTurn, ...delta.resolvedByTurn], 8);
|
|
299
|
+
const fileText = files.length > 0 ? files.join(', ') : 'workspace changes recorded';
|
|
291
300
|
const checkpointText = checkpointIds.length > 0
|
|
292
301
|
? ` Checkpoints: ${checkpointIds.join(', ')}. Preview rollback with /checkpoint restore <id>; restore each listed checkpoint if multiple.`
|
|
293
302
|
: '';
|
|
@@ -348,15 +357,17 @@ function withVerificationLoopStats(stats, summary) {
|
|
|
348
357
|
verificationPassedCommands: compactVerificationCommands(summary.passedCommands),
|
|
349
358
|
verificationFailedCommands: compactVerificationCommands(summary.failedCommands),
|
|
350
359
|
verificationMissingCommands: compactVerificationCommands(summary.missingCommands),
|
|
351
|
-
verificationSkippedReason: summary.skippedReason
|
|
360
|
+
verificationSkippedReason: summary.skippedReason
|
|
361
|
+
? (0, session_storage_1.redactTraceText)(summary.skippedReason)
|
|
362
|
+
: undefined,
|
|
352
363
|
};
|
|
353
364
|
}
|
|
354
365
|
function shouldRecordVerificationLoopStats(profile, summary) {
|
|
355
|
-
return profile.changedFiles.length > 0
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
366
|
+
return (profile.changedFiles.length > 0 ||
|
|
367
|
+
summary.commandsRun.length > 0 ||
|
|
368
|
+
summary.passedCommands.length > 0 ||
|
|
369
|
+
summary.failedCommands.length > 0 ||
|
|
370
|
+
summary.missingCommands.length > 0);
|
|
360
371
|
}
|
|
361
372
|
function appendPostWorkspaceTrace(events, sessionId, turnId, cwd, before, verificationResults = []) {
|
|
362
373
|
const postWorkspace = (0, workspace_state_1.captureWorkspaceSnapshot)(cwd);
|
|
@@ -451,11 +462,78 @@ function toolStartContent(event) {
|
|
|
451
462
|
function toolFinishContent(event) {
|
|
452
463
|
return (0, ui_view_model_1.formatToolActivityTranscript)((0, ui_view_model_1.toolActivityFromFinished)(event, compactToolArgs(event.args, TOOL_TRANSCRIPT_ARG_BUDGET)));
|
|
453
464
|
}
|
|
465
|
+
function structuredToolStartActivity(event, seq) {
|
|
466
|
+
const command = event.name === 'exec_command' && typeof event.args.command === 'string'
|
|
467
|
+
? event.args.command
|
|
468
|
+
: undefined;
|
|
469
|
+
const safeCommand = command ? (0, session_storage_1.redactTraceText)(command) : undefined;
|
|
470
|
+
return {
|
|
471
|
+
state: 'running',
|
|
472
|
+
name: event.name,
|
|
473
|
+
detail: command ? '' : (0, session_storage_1.redactTraceText)(compactToolArgs(event.args, TOOL_TRANSCRIPT_ARG_BUDGET)),
|
|
474
|
+
command: safeCommand,
|
|
475
|
+
body: '',
|
|
476
|
+
seq,
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
function structuredToolFinishActivity(event, seq, options = {}) {
|
|
480
|
+
const modelVisible = (0, tool_serializer_1.parseToolResultEnvelope)(event.modelVisibleResult);
|
|
481
|
+
const durable = (0, tool_serializer_1.parseToolResultEnvelope)(event.result);
|
|
482
|
+
const durableOutput = typeof durable.output === 'string' ? durable.output : '';
|
|
483
|
+
const displayOutput = typeof modelVisible.output === 'string' ? modelVisible.output : durableOutput;
|
|
484
|
+
const outputBytes = event.outputBytes ?? Buffer.byteLength(durableOutput, 'utf8');
|
|
485
|
+
const aggregatePresentation = (0, aggregate_tool_presenter_1.presentAggregateToolResult)(event.name, durableOutput, outputBytes);
|
|
486
|
+
const aggregate = aggregatePresentation?.view;
|
|
487
|
+
const storedArtifact = event.artifactRef ?? (options.projectPath && durableOutput && (outputBytes > tool_output_presentation_1.DEFAULT_TOOL_OUTPUT_POLICY.inlineMaxBytes || aggregate)
|
|
488
|
+
? (0, tool_artifacts_1.storeArtifact)(options.projectPath, event.name, durableOutput, outputBytes) ?? undefined
|
|
489
|
+
: undefined);
|
|
490
|
+
const artifactRef = storedArtifact
|
|
491
|
+
? { id: storedArtifact.id, outputBytes: storedArtifact.outputBytes }
|
|
492
|
+
: undefined;
|
|
493
|
+
const outputView = (0, tool_output_presentation_1.createToolOutputView)({
|
|
494
|
+
toolName: event.name,
|
|
495
|
+
success: event.success,
|
|
496
|
+
summary: event.summary,
|
|
497
|
+
rawOutput: durableOutput.length <= 64 * 1024 ? durableOutput : displayOutput,
|
|
498
|
+
outputBytes,
|
|
499
|
+
artifactRef,
|
|
500
|
+
callId: event.callId,
|
|
501
|
+
sequence: seq,
|
|
502
|
+
turnId: options.turnId,
|
|
503
|
+
policy: tool_output_presentation_1.DEFAULT_TOOL_OUTPUT_POLICY,
|
|
504
|
+
});
|
|
505
|
+
if (aggregate) {
|
|
506
|
+
outputView.aggregate = {
|
|
507
|
+
...aggregate,
|
|
508
|
+
steps: aggregate.steps.map(step => ({ ...step, detailRef: outputView.detailRef })),
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
const command = event.name === 'exec_command' && typeof event.args.command === 'string'
|
|
512
|
+
? event.args.command
|
|
513
|
+
: undefined;
|
|
514
|
+
const safeCommand = command ? (0, session_storage_1.redactTraceText)(command) : undefined;
|
|
515
|
+
return {
|
|
516
|
+
state: event.success ? 'success' : 'error',
|
|
517
|
+
name: event.name,
|
|
518
|
+
detail: command ? '' : (0, session_storage_1.redactTraceText)(compactToolArgs(event.args, TOOL_TRANSCRIPT_ARG_BUDGET)),
|
|
519
|
+
command: safeCommand,
|
|
520
|
+
duration: `${event.duration}ms`,
|
|
521
|
+
summary: event.summary ? (0, session_storage_1.redactTraceText)(event.summary.split(/\r?\n/u, 1)[0]) : undefined,
|
|
522
|
+
outputBytes,
|
|
523
|
+
body: (0, session_storage_1.redactTraceText)(modelVisible.output),
|
|
524
|
+
error: event.error ? (0, session_storage_1.redactTraceText)(event.error) : undefined,
|
|
525
|
+
seq,
|
|
526
|
+
artifactHint: artifactRef ? `/artifacts show ${artifactRef.id} --full` : undefined,
|
|
527
|
+
callId: event.callId,
|
|
528
|
+
turnId: options.turnId,
|
|
529
|
+
outputView,
|
|
530
|
+
};
|
|
531
|
+
}
|
|
454
532
|
function isSyntheticCompactContext(content) {
|
|
455
|
-
return content.startsWith('[OpenHorse Context State v2]')
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
533
|
+
return (content.startsWith('[OpenHorse Context State v2]') ||
|
|
534
|
+
content.startsWith('[Context Summary]') ||
|
|
535
|
+
content.startsWith('I will continue from this OpenHorse Context State') ||
|
|
536
|
+
content.startsWith('I understand the context. I will continue the conversation with this background information.'));
|
|
459
537
|
}
|
|
460
538
|
function sessionToolCallSummaries(message) {
|
|
461
539
|
return (message.tool_calls ?? []).map(call => {
|
|
@@ -506,16 +584,25 @@ function sessionToolResultSummary(message, toolCallsById) {
|
|
|
506
584
|
const args = parseToolCallArgs(call.function.arguments);
|
|
507
585
|
const detail = compactToolArgs(args);
|
|
508
586
|
const parsed = parseSessionToolResult(message.content);
|
|
509
|
-
const firstLine = parsed.summary ||
|
|
587
|
+
const firstLine = parsed.summary ||
|
|
588
|
+
`${parsed.success ? '✓' : '✗'} ${call.function.name}${detail ? ` ${detail}` : ''}`;
|
|
510
589
|
return parsed.error ? `${firstLine}\nError: ${parsed.error}` : firstLine;
|
|
511
590
|
}
|
|
512
|
-
function sessionMessagesToTranscriptEntries(sessionId) {
|
|
513
|
-
const
|
|
514
|
-
const
|
|
515
|
-
|
|
591
|
+
function sessionMessagesToTranscriptEntries(sessionId, options = {}) {
|
|
592
|
+
const messages = (0, session_storage_1.loadSessionTranscriptMessages)(sessionId);
|
|
593
|
+
const resultTraces = options.includeToolOutputViews
|
|
594
|
+
? (0, session_storage_1.readSessionTraceEvents)(sessionId).filter(trace => trace.type === 'tool_result' && trace.callId)
|
|
595
|
+
: [];
|
|
596
|
+
const resultTraceByCallId = new Map(resultTraces.map(trace => [trace.callId, trace]));
|
|
597
|
+
const sequenceByCallId = new Map();
|
|
598
|
+
resultTraces.forEach((trace, index) => {
|
|
599
|
+
if (!sequenceByCallId.has(trace.callId))
|
|
600
|
+
sequenceByCallId.set(trace.callId, index + 1);
|
|
601
|
+
});
|
|
516
602
|
const entries = [];
|
|
517
603
|
const toolCallsById = new Map();
|
|
518
604
|
const completedToolCallIds = new Set();
|
|
605
|
+
let fallbackToolSequence = 0;
|
|
519
606
|
for (const message of messages) {
|
|
520
607
|
for (const call of message.tool_calls ?? []) {
|
|
521
608
|
toolCallsById.set(call.id, call);
|
|
@@ -538,17 +625,73 @@ function sessionMessagesToTranscriptEntries(sessionId) {
|
|
|
538
625
|
}
|
|
539
626
|
for (const summary of sessionToolCallSummaries(message)) {
|
|
540
627
|
if (!completedToolCallIds.has(summary.id)) {
|
|
541
|
-
entries.push({
|
|
628
|
+
entries.push({
|
|
629
|
+
id: `${idBase}-tool-call-${entries.length}`,
|
|
630
|
+
role: 'tool',
|
|
631
|
+
content: summary.content,
|
|
632
|
+
});
|
|
542
633
|
}
|
|
543
634
|
}
|
|
544
635
|
return;
|
|
545
636
|
}
|
|
546
637
|
if (message.role === 'tool') {
|
|
547
638
|
const summary = sessionToolResultSummary(message, toolCallsById);
|
|
639
|
+
const call = message.toolCallId ? toolCallsById.get(message.toolCallId) : undefined;
|
|
640
|
+
const trace = message.toolCallId ? resultTraceByCallId.get(message.toolCallId) : undefined;
|
|
641
|
+
const durable = (0, tool_serializer_1.parseToolResultEnvelope)(message.content);
|
|
642
|
+
const modelVisible = message.modelVisibleContent
|
|
643
|
+
? (0, tool_serializer_1.parseToolResultEnvelope)(message.modelVisibleContent)
|
|
644
|
+
: durable;
|
|
645
|
+
const durableOutput = typeof durable.output === 'string' ? durable.output : '';
|
|
646
|
+
const displayOutput = typeof modelVisible.output === 'string' ? modelVisible.output : durableOutput;
|
|
647
|
+
const outputBytes = trace?.outputBytes
|
|
648
|
+
?? (durable.schemaVersion === 1 ? durable.outputBytes : undefined)
|
|
649
|
+
?? Buffer.byteLength(durableOutput, 'utf8');
|
|
650
|
+
const artifactId = durable.artifactRef?.id ?? trace?.artifactId;
|
|
651
|
+
fallbackToolSequence += 1;
|
|
652
|
+
const sequence = message.toolCallId
|
|
653
|
+
? sequenceByCallId.get(message.toolCallId) ?? fallbackToolSequence
|
|
654
|
+
: fallbackToolSequence;
|
|
655
|
+
const outputView = options.includeToolOutputViews && call && message.toolCallId
|
|
656
|
+
? (0, tool_output_presentation_1.createToolOutputView)({
|
|
657
|
+
toolName: call.function.name,
|
|
658
|
+
success: durable.success,
|
|
659
|
+
summary: durable.summary,
|
|
660
|
+
rawOutput: durableOutput.length <= 64 * 1024 ? durableOutput : displayOutput,
|
|
661
|
+
outputBytes,
|
|
662
|
+
artifactRef: artifactId ? { id: artifactId, outputBytes } : undefined,
|
|
663
|
+
callId: message.toolCallId,
|
|
664
|
+
sequence,
|
|
665
|
+
turnId: trace?.turnId,
|
|
666
|
+
policy: tool_output_presentation_1.DEFAULT_TOOL_OUTPUT_POLICY,
|
|
667
|
+
})
|
|
668
|
+
: undefined;
|
|
548
669
|
entries.push({
|
|
549
670
|
id: `${idBase}-tool`,
|
|
550
671
|
role: 'tool',
|
|
551
|
-
content: summary ??
|
|
672
|
+
content: summary ??
|
|
673
|
+
(message.toolCallId
|
|
674
|
+
? `Tool result ${message.toolCallId}\n${message.content}`
|
|
675
|
+
: message.content),
|
|
676
|
+
toolActivity: call && message.toolCallId && outputView
|
|
677
|
+
? {
|
|
678
|
+
state: durable.success ? 'success' : 'error',
|
|
679
|
+
name: call.function.name,
|
|
680
|
+
detail: (0, session_storage_1.redactTraceText)(compactToolArgs(parseToolCallArgs(call.function.arguments))),
|
|
681
|
+
summary: durable.summary
|
|
682
|
+
? (0, session_storage_1.redactTraceText)(durable.summary.split(/\r?\n/u, 1)[0])
|
|
683
|
+
: undefined,
|
|
684
|
+
outputBytes,
|
|
685
|
+
body: (0, session_storage_1.redactTraceText)(durableOutput.length <= 64 * 1024 ? durableOutput : displayOutput),
|
|
686
|
+
error: durable.error ? (0, session_storage_1.redactTraceText)(durable.error) : undefined,
|
|
687
|
+
duration: typeof trace?.duration === 'number' ? `${trace.duration}ms` : undefined,
|
|
688
|
+
seq: sequence,
|
|
689
|
+
artifactHint: artifactId ? `/artifacts show ${artifactId} --full` : undefined,
|
|
690
|
+
callId: message.toolCallId,
|
|
691
|
+
turnId: trace?.turnId,
|
|
692
|
+
outputView,
|
|
693
|
+
}
|
|
694
|
+
: undefined,
|
|
552
695
|
});
|
|
553
696
|
return;
|
|
554
697
|
}
|
|
@@ -633,19 +776,27 @@ function parseLocalFastPath(input) {
|
|
|
633
776
|
}
|
|
634
777
|
const readMatch = /^(?:read|读取)\s+(.+)$/i.exec(text);
|
|
635
778
|
const readTarget = readMatch?.[1]?.trim();
|
|
636
|
-
const looksLikePath = Boolean(readTarget)
|
|
637
|
-
|
|
638
|
-
|
|
779
|
+
const looksLikePath = Boolean(readTarget) &&
|
|
780
|
+
!/\s/.test(readTarget) &&
|
|
781
|
+
(/[/\\.]/.test(readTarget) || readTarget.startsWith('~'));
|
|
639
782
|
if (readTarget && looksLikePath) {
|
|
640
783
|
return { tool: 'read_file', args: { path: readTarget }, label: `read ${readTarget}` };
|
|
641
784
|
}
|
|
642
785
|
const grepMatch = /^(?:grep|搜索)\s+(.+)$/i.exec(text);
|
|
643
786
|
if (grepMatch?.[1]?.trim()) {
|
|
644
|
-
return {
|
|
787
|
+
return {
|
|
788
|
+
tool: 'grep',
|
|
789
|
+
args: { pattern: grepMatch[1].trim() },
|
|
790
|
+
label: `grep ${grepMatch[1].trim()}`,
|
|
791
|
+
};
|
|
645
792
|
}
|
|
646
793
|
const runTestMatch = /^(?:run\s+test|运行测试)\s*[::]\s*(.+)$/i.exec(text);
|
|
647
794
|
if (runTestMatch?.[1]?.trim()) {
|
|
648
|
-
return {
|
|
795
|
+
return {
|
|
796
|
+
tool: 'exec_command',
|
|
797
|
+
args: { command: runTestMatch[1].trim() },
|
|
798
|
+
label: `run test: ${runTestMatch[1].trim()}`,
|
|
799
|
+
};
|
|
649
800
|
}
|
|
650
801
|
return null;
|
|
651
802
|
}
|
|
@@ -683,7 +834,7 @@ function formatLocalFastPathAssistantContent(action, rawResult, projectPath) {
|
|
|
683
834
|
lines.push('', 'Preview:', preview);
|
|
684
835
|
return { content: lines.join('\n'), artifactRef };
|
|
685
836
|
}
|
|
686
|
-
function createToolEventPresenter(events) {
|
|
837
|
+
function createToolEventPresenter(events, options = {}) {
|
|
687
838
|
const runningToolEntries = new Map();
|
|
688
839
|
let toolSequenceCounter = 0;
|
|
689
840
|
return {
|
|
@@ -693,12 +844,7 @@ function createToolEventPresenter(events) {
|
|
|
693
844
|
role: 'tool',
|
|
694
845
|
title: 'tool',
|
|
695
846
|
content: toolStartContent(event),
|
|
696
|
-
toolActivity:
|
|
697
|
-
state: 'running',
|
|
698
|
-
name: event.name,
|
|
699
|
-
detail: '',
|
|
700
|
-
seq,
|
|
701
|
-
},
|
|
847
|
+
toolActivity: structuredToolStartActivity(event, seq),
|
|
702
848
|
});
|
|
703
849
|
runningToolEntries.set(event.callId, {
|
|
704
850
|
entryId,
|
|
@@ -721,15 +867,7 @@ function createToolEventPresenter(events) {
|
|
|
721
867
|
const content = toolFinishContent(event);
|
|
722
868
|
const stored = runningToolEntries.get(event.callId);
|
|
723
869
|
const seq = stored?.sequence ?? ++toolSequenceCounter;
|
|
724
|
-
const
|
|
725
|
-
const toolActivity = {
|
|
726
|
-
state,
|
|
727
|
-
name: event.name,
|
|
728
|
-
detail: '',
|
|
729
|
-
duration: `${event.duration}ms`,
|
|
730
|
-
error: event.error,
|
|
731
|
-
seq,
|
|
732
|
-
};
|
|
870
|
+
const toolActivity = structuredToolFinishActivity(event, seq, options);
|
|
733
871
|
if (stored) {
|
|
734
872
|
events.finalize(stored.entryId, {
|
|
735
873
|
role: event.success ? 'tool' : 'error',
|
|
@@ -757,7 +895,12 @@ function createToolEventPresenter(events) {
|
|
|
757
895
|
summary: event.summary,
|
|
758
896
|
error: event.error,
|
|
759
897
|
outputBytes: event.outputBytes,
|
|
760
|
-
artifactRef:
|
|
898
|
+
artifactRef: toolActivity.outputView?.detailRef?.artifactId
|
|
899
|
+
? {
|
|
900
|
+
id: toolActivity.outputView.detailRef.artifactId,
|
|
901
|
+
outputBytes: toolActivity.outputView.detailRef.outputBytes,
|
|
902
|
+
}
|
|
903
|
+
: event.artifactRef,
|
|
761
904
|
sequence: seq,
|
|
762
905
|
batchCount: event.batchCount,
|
|
763
906
|
batchIndex: event.batchIndex,
|
|
@@ -773,6 +916,7 @@ function createToolEventPresenter(events) {
|
|
|
773
916
|
state: 'skipped',
|
|
774
917
|
name: entry.name,
|
|
775
918
|
detail: '',
|
|
919
|
+
body: '',
|
|
776
920
|
error: reason,
|
|
777
921
|
seq: entry.sequence,
|
|
778
922
|
},
|
|
@@ -800,7 +944,7 @@ async function captureConsoleOutput(fn) {
|
|
|
800
944
|
const originalError = console.error;
|
|
801
945
|
const originalWarn = console.warn;
|
|
802
946
|
const capture = (...args) => {
|
|
803
|
-
lines.push(stripAnsi(args.map(arg => typeof arg === 'string' ? arg : JSON.stringify(arg)).join(' ')));
|
|
947
|
+
lines.push(stripAnsi(args.map(arg => (typeof arg === 'string' ? arg : JSON.stringify(arg))).join(' ')));
|
|
804
948
|
};
|
|
805
949
|
console.log = capture;
|
|
806
950
|
console.error = capture;
|
|
@@ -850,7 +994,7 @@ class AgentChatController {
|
|
|
850
994
|
}
|
|
851
995
|
const command = (0, commands_1.findCommand)(parsed.name);
|
|
852
996
|
if (!command) {
|
|
853
|
-
if ((0, skills_1.hasMatchingSkill)(text)) {
|
|
997
|
+
if ((0, skills_1.hasMatchingSkill)(text, this.runtime.cwd)) {
|
|
854
998
|
await this.runChat(text, options);
|
|
855
999
|
return;
|
|
856
1000
|
}
|
|
@@ -902,7 +1046,9 @@ class AgentChatController {
|
|
|
902
1046
|
}
|
|
903
1047
|
}
|
|
904
1048
|
async runLocalFastPath(input, action, options = {}) {
|
|
905
|
-
const activeSession = this.runtime.getSession() ??
|
|
1049
|
+
const activeSession = this.runtime.getSession() ??
|
|
1050
|
+
this.runtime.ensureSession() ??
|
|
1051
|
+
(0, session_storage_1.loadSessionMeta)(this.runtime.getSession()?.id ?? '');
|
|
906
1052
|
const sessionId = activeSession?.id;
|
|
907
1053
|
const turnId = traceTurnId(options.turnId);
|
|
908
1054
|
const localCallId = `local-${turnId}`;
|
|
@@ -981,22 +1127,27 @@ class AgentChatController {
|
|
|
981
1127
|
modelVisibleToolBytes: 0,
|
|
982
1128
|
summarizedBytes: outputBytes,
|
|
983
1129
|
});
|
|
1130
|
+
const localToolResultEvent = {
|
|
1131
|
+
type: 'tool_result',
|
|
1132
|
+
name: action.tool,
|
|
1133
|
+
args: action.args,
|
|
1134
|
+
callId: localCallId,
|
|
1135
|
+
result,
|
|
1136
|
+
modelVisibleResult: result,
|
|
1137
|
+
duration,
|
|
1138
|
+
success: envelope.success,
|
|
1139
|
+
error: envelope.error,
|
|
1140
|
+
summary: envelope.summary,
|
|
1141
|
+
outputBytes,
|
|
1142
|
+
artifactRef: formattedLocalResult.artifactRef,
|
|
1143
|
+
};
|
|
984
1144
|
this.events.append({
|
|
985
1145
|
role: envelope.success ? 'tool' : 'error',
|
|
986
1146
|
title: 'local',
|
|
987
|
-
content: toolFinishContent(
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
callId: localCallId,
|
|
992
|
-
result,
|
|
993
|
-
modelVisibleResult: result,
|
|
994
|
-
duration,
|
|
995
|
-
success: envelope.success,
|
|
996
|
-
error: envelope.error,
|
|
997
|
-
summary: envelope.summary,
|
|
998
|
-
outputBytes,
|
|
999
|
-
artifactRef: formattedLocalResult.artifactRef,
|
|
1147
|
+
content: toolFinishContent(localToolResultEvent),
|
|
1148
|
+
toolActivity: structuredToolFinishActivity(localToolResultEvent, 1, {
|
|
1149
|
+
projectPath: this.runtime.cwd,
|
|
1150
|
+
turnId,
|
|
1000
1151
|
}),
|
|
1001
1152
|
});
|
|
1002
1153
|
this.runtime.store.addMessage({ role: 'assistant', content: assistantContent });
|
|
@@ -1083,13 +1234,19 @@ class AgentChatController {
|
|
|
1083
1234
|
config: this.runtime.config,
|
|
1084
1235
|
store: this.runtime.store,
|
|
1085
1236
|
llm: this.runtime.llm,
|
|
1237
|
+
compactCoordinator: this.runtime.compactCoordinator,
|
|
1086
1238
|
runtime: this.runtime.runtime,
|
|
1087
1239
|
sessionId: this.runtime.getSession()?.id,
|
|
1088
1240
|
turnId,
|
|
1089
1241
|
ensureSession: this.runtime.ensureSession,
|
|
1090
1242
|
setSession: session => {
|
|
1091
1243
|
this.runtime.setSession(session);
|
|
1092
|
-
this.
|
|
1244
|
+
const renderer = this.controllerOptions.uiRenderer
|
|
1245
|
+
?? this.runtime.config.ui?.renderer
|
|
1246
|
+
?? 'terminal';
|
|
1247
|
+
this.events.replaceTranscript(sessionMessagesToTranscriptEntries(session.id, {
|
|
1248
|
+
includeToolOutputViews: renderer === 'tui',
|
|
1249
|
+
}));
|
|
1093
1250
|
},
|
|
1094
1251
|
sessionRestored: event => {
|
|
1095
1252
|
this.events.sessionRestored?.(event);
|
|
@@ -1147,7 +1304,11 @@ class AgentChatController {
|
|
|
1147
1304
|
content: `▸ subtask ${event.role} started: ${event.objective.slice(0, 120)}`,
|
|
1148
1305
|
});
|
|
1149
1306
|
}
|
|
1150
|
-
else if (event.state === 'completed' ||
|
|
1307
|
+
else if (event.state === 'completed' ||
|
|
1308
|
+
event.state === 'failed' ||
|
|
1309
|
+
event.state === 'cancelled' ||
|
|
1310
|
+
event.state === 'timed_out' ||
|
|
1311
|
+
event.state === 'rejected') {
|
|
1151
1312
|
const summary = event.summary ? ` — ${event.summary.slice(0, 200)}` : '';
|
|
1152
1313
|
this.events.append({
|
|
1153
1314
|
role: 'system',
|
|
@@ -1181,7 +1342,11 @@ class AgentChatController {
|
|
|
1181
1342
|
}
|
|
1182
1343
|
async runChat(input, options = {}) {
|
|
1183
1344
|
if (!input) {
|
|
1184
|
-
this.events.append({
|
|
1345
|
+
this.events.append({
|
|
1346
|
+
role: 'error',
|
|
1347
|
+
content: 'Usage: /chat <message>',
|
|
1348
|
+
errorLayer: 'runtime',
|
|
1349
|
+
});
|
|
1185
1350
|
return;
|
|
1186
1351
|
}
|
|
1187
1352
|
if (!this.runtime.llm || !(0, config_1.isConfigured)(this.runtime.config)) {
|
|
@@ -1194,7 +1359,9 @@ class AgentChatController {
|
|
|
1194
1359
|
}
|
|
1195
1360
|
const abortSignal = options.abortSignal;
|
|
1196
1361
|
const turnId = traceTurnId(options.turnId);
|
|
1197
|
-
const activeSession = this.runtime.getSession() ??
|
|
1362
|
+
const activeSession = this.runtime.getSession() ??
|
|
1363
|
+
this.runtime.ensureSession() ??
|
|
1364
|
+
(0, session_storage_1.loadSessionMeta)(this.runtime.getSession()?.id ?? '');
|
|
1198
1365
|
const sessionId = activeSession?.id;
|
|
1199
1366
|
const preWorkspace = (0, workspace_state_1.captureWorkspaceSnapshot)(this.runtime.cwd);
|
|
1200
1367
|
const runtimeTools = (0, tools_1.getRuntimeTools)();
|
|
@@ -1237,7 +1404,9 @@ class AgentChatController {
|
|
|
1237
1404
|
const intent = harness.updateContractFromUserInput(input);
|
|
1238
1405
|
harness.recordAppliedSkills(skillResolution.skills);
|
|
1239
1406
|
// Reconcile diagnostic: when harness state is present but objective may be incomplete
|
|
1240
|
-
if (snapshot.harnessState &&
|
|
1407
|
+
if (snapshot.harnessState &&
|
|
1408
|
+
!snapshot.harnessState.rootObjective &&
|
|
1409
|
+
!snapshot.harnessState.contract?.objective) {
|
|
1241
1410
|
this.events.setStatus('Resume diagnostic: harness state restored but objective may be incomplete. Run /harness explain to review.');
|
|
1242
1411
|
}
|
|
1243
1412
|
const subagentConfig = this.runtime.config.subagents;
|
|
@@ -1245,7 +1414,10 @@ class AgentChatController {
|
|
|
1245
1414
|
// turns, but respects an active skill scope: when a skill restricts the
|
|
1246
1415
|
// tool set, subtask is not appended (the skill owns the scope).
|
|
1247
1416
|
const projectPath = activeSession?.projectPath;
|
|
1248
|
-
const subagentBundle = subagentConfig &&
|
|
1417
|
+
const subagentBundle = subagentConfig &&
|
|
1418
|
+
subagentConfig.mode !== 'off' &&
|
|
1419
|
+
this.runtime.llm &&
|
|
1420
|
+
!skillResolution.toolScopeActive
|
|
1249
1421
|
? (0, subagents_1.createSubagentBundleForTurn)({
|
|
1250
1422
|
config: subagentConfig,
|
|
1251
1423
|
cwd: this.runtime.cwd,
|
|
@@ -1253,7 +1425,7 @@ class AgentChatController {
|
|
|
1253
1425
|
modelLabel: this.runtime.llm.getModel(),
|
|
1254
1426
|
rootObjectiveSummary: harness.toJSON()?.rootObjective ?? input,
|
|
1255
1427
|
abortSignal,
|
|
1256
|
-
onSubtaskEvent:
|
|
1428
|
+
onSubtaskEvent: event => {
|
|
1257
1429
|
this.handleSubtaskEvent(event, sessionId, turnId);
|
|
1258
1430
|
},
|
|
1259
1431
|
onSubtaskResult: (result, _batchId) => {
|
|
@@ -1310,10 +1482,14 @@ class AgentChatController {
|
|
|
1310
1482
|
let finalModel = '';
|
|
1311
1483
|
let pendingCompleteTrace = null;
|
|
1312
1484
|
let pendingCompleteStats;
|
|
1485
|
+
let pendingCompact;
|
|
1313
1486
|
const verificationResults = [];
|
|
1314
1487
|
const sessionMessagesToRecord = [];
|
|
1315
1488
|
const assistantStream = createAssistantStreamPresenter(this.events, abortSignal);
|
|
1316
|
-
const toolEvents = createToolEventPresenter(this.events
|
|
1489
|
+
const toolEvents = createToolEventPresenter(this.events, {
|
|
1490
|
+
projectPath: this.runtime.cwd,
|
|
1491
|
+
turnId,
|
|
1492
|
+
});
|
|
1317
1493
|
let checkpointSequence = 0;
|
|
1318
1494
|
const checkpointIds = [];
|
|
1319
1495
|
const streamCallbacks = {
|
|
@@ -1384,6 +1560,10 @@ class AgentChatController {
|
|
|
1384
1560
|
harness,
|
|
1385
1561
|
input,
|
|
1386
1562
|
loopBudget,
|
|
1563
|
+
onContextUsage: usage => {
|
|
1564
|
+
this.runtime.store.setContextUsage(usage);
|
|
1565
|
+
},
|
|
1566
|
+
compactCoordinator: this.runtime.compactCoordinator,
|
|
1387
1567
|
})) {
|
|
1388
1568
|
switch (event.type) {
|
|
1389
1569
|
case 'request_start':
|
|
@@ -1434,9 +1614,7 @@ class AgentChatController {
|
|
|
1434
1614
|
this.events.append({ role: 'status', content: suggestion });
|
|
1435
1615
|
}
|
|
1436
1616
|
}
|
|
1437
|
-
const checkpointId = checkpointSequence === 0
|
|
1438
|
-
? turnId
|
|
1439
|
-
: `${turnId}-checkpoint-${checkpointSequence + 1}`;
|
|
1617
|
+
const checkpointId = checkpointSequence === 0 ? turnId : `${turnId}-checkpoint-${checkpointSequence + 1}`;
|
|
1440
1618
|
const checkpointResult = createPreToolCheckpoint(this.events, sessionId, turnId, checkpointId, this.runtime.cwd, event.toolCalls);
|
|
1441
1619
|
if (checkpointResult.created) {
|
|
1442
1620
|
checkpointIds.push(checkpointId);
|
|
@@ -1446,6 +1624,7 @@ class AgentChatController {
|
|
|
1446
1624
|
this.events.append({
|
|
1447
1625
|
role: 'status',
|
|
1448
1626
|
title: 'checkpoint',
|
|
1627
|
+
statusTone: 'warning',
|
|
1449
1628
|
content: `Risky edit: ${checkpointResult.targetCount} files in one turn. Checkpoint ${checkpointId} created for rollback (/checkpoints restore ${checkpointId}).`,
|
|
1450
1629
|
});
|
|
1451
1630
|
}
|
|
@@ -1453,6 +1632,7 @@ class AgentChatController {
|
|
|
1453
1632
|
this.events.append({
|
|
1454
1633
|
role: 'status',
|
|
1455
1634
|
title: 'checkpoint',
|
|
1635
|
+
statusTone: 'warning',
|
|
1456
1636
|
content: `Risky edit: ${checkpointResult.targetCount} files in one turn, but checkpoint creation failed. Restore any pre-existing checkpoint manually or revert via git.`,
|
|
1457
1637
|
});
|
|
1458
1638
|
}
|
|
@@ -1606,6 +1786,7 @@ class AgentChatController {
|
|
|
1606
1786
|
finalContent = event.content;
|
|
1607
1787
|
finalUsage = event.usage;
|
|
1608
1788
|
finalModel = event.model;
|
|
1789
|
+
pendingCompact = event.compact;
|
|
1609
1790
|
if (event.stats) {
|
|
1610
1791
|
pendingCompleteStats = event.stats;
|
|
1611
1792
|
recordProviderTraceEvents(this.events, sessionId, turnId, event.stats);
|
|
@@ -1662,6 +1843,7 @@ class AgentChatController {
|
|
|
1662
1843
|
this.events.append({
|
|
1663
1844
|
role: 'status',
|
|
1664
1845
|
title: 'recovery',
|
|
1846
|
+
statusTone: 'warning',
|
|
1665
1847
|
content: recoveryNotice,
|
|
1666
1848
|
});
|
|
1667
1849
|
}
|
|
@@ -1694,6 +1876,7 @@ class AgentChatController {
|
|
|
1694
1876
|
this.events.append({
|
|
1695
1877
|
role: 'status',
|
|
1696
1878
|
title: 'verification',
|
|
1879
|
+
statusTone: 'warning',
|
|
1697
1880
|
content: notice,
|
|
1698
1881
|
});
|
|
1699
1882
|
finalContent = finalContent ? `${finalContent}\n\n${notice}` : notice;
|
|
@@ -1738,7 +1921,12 @@ class AgentChatController {
|
|
|
1738
1921
|
lines.push(`Next: ${stats.continuationHint}`);
|
|
1739
1922
|
}
|
|
1740
1923
|
const notice = lines.join('\n');
|
|
1741
|
-
this.events.append({
|
|
1924
|
+
this.events.append({
|
|
1925
|
+
role: 'status',
|
|
1926
|
+
title: 'budget',
|
|
1927
|
+
statusTone: 'warning',
|
|
1928
|
+
content: notice,
|
|
1929
|
+
});
|
|
1742
1930
|
finalContent = finalContent ? `${finalContent}\n\n${notice}` : notice;
|
|
1743
1931
|
appendAssistantNotice(sessionMessagesToRecord, notice);
|
|
1744
1932
|
}
|
|
@@ -1751,6 +1939,65 @@ class AgentChatController {
|
|
|
1751
1939
|
if (sessionId && sessionMessagesToRecord.length > 0) {
|
|
1752
1940
|
(0, session_storage_1.appendSessionMessages)(sessionId, sessionMessagesToRecord);
|
|
1753
1941
|
}
|
|
1942
|
+
if (pendingCompact) {
|
|
1943
|
+
try {
|
|
1944
|
+
let committedCheckpointId;
|
|
1945
|
+
if (sessionId) {
|
|
1946
|
+
const sourceMessageCount = (0, session_storage_1.readSessionMessages)(sessionId).length;
|
|
1947
|
+
const checkpoint = (0, session_storage_1.commitSessionCompactCheckpoint)({
|
|
1948
|
+
sessionId,
|
|
1949
|
+
mode: pendingCompact.mode,
|
|
1950
|
+
modelId: finalModel || this.runtime.llm.getModel(),
|
|
1951
|
+
sourceMessageCount,
|
|
1952
|
+
transcriptStartMessageIndex: Math.max(0, sourceMessageCount - 20),
|
|
1953
|
+
modelHistory: pendingCompact.modelHistory,
|
|
1954
|
+
summary: pendingCompact.summary,
|
|
1955
|
+
beforeUsage: pendingCompact.before,
|
|
1956
|
+
afterUsage: pendingCompact.after,
|
|
1957
|
+
});
|
|
1958
|
+
committedCheckpointId = checkpoint.checkpointId;
|
|
1959
|
+
this.runtime.store.setState({ conversationHistory: checkpoint.modelHistory });
|
|
1960
|
+
}
|
|
1961
|
+
else {
|
|
1962
|
+
this.runtime.store.setState({
|
|
1963
|
+
conversationHistory: pendingCompact.modelHistory.filter(message => message.role !== 'system'),
|
|
1964
|
+
});
|
|
1965
|
+
}
|
|
1966
|
+
this.runtime.store.setContextUsage(pendingCompact.after);
|
|
1967
|
+
if (sessionId) {
|
|
1968
|
+
recordTraceEvent(this.events, sessionId, {
|
|
1969
|
+
turnId,
|
|
1970
|
+
type: 'compact_completed',
|
|
1971
|
+
checkpointId: committedCheckpointId,
|
|
1972
|
+
model: finalModel || this.runtime.llm.getModel(),
|
|
1973
|
+
note: pendingCompact.mode,
|
|
1974
|
+
});
|
|
1975
|
+
}
|
|
1976
|
+
this.events.append({
|
|
1977
|
+
role: 'status',
|
|
1978
|
+
title: 'auto-compact',
|
|
1979
|
+
statusTone: 'neutral',
|
|
1980
|
+
content: `Context reached ${pendingCompact.before.percent}% of the safe input budget. Agent core committed a ${pendingCompact.mode} compact checkpoint; current context is ${pendingCompact.after.percent}%.`,
|
|
1981
|
+
});
|
|
1982
|
+
}
|
|
1983
|
+
catch (error) {
|
|
1984
|
+
if (sessionId) {
|
|
1985
|
+
recordTraceEvent(this.events, sessionId, {
|
|
1986
|
+
turnId,
|
|
1987
|
+
type: 'compact_failed',
|
|
1988
|
+
model: finalModel || this.runtime.llm.getModel(),
|
|
1989
|
+
error: compactTraceError(error),
|
|
1990
|
+
note: pendingCompact.mode,
|
|
1991
|
+
});
|
|
1992
|
+
}
|
|
1993
|
+
this.events.append({
|
|
1994
|
+
role: 'error',
|
|
1995
|
+
title: 'compact-failed',
|
|
1996
|
+
content: `Compact checkpoint failed; the previous model context remains active. ${error instanceof Error ? error.message : String(error)}`,
|
|
1997
|
+
errorLayer: 'runtime',
|
|
1998
|
+
});
|
|
1999
|
+
}
|
|
2000
|
+
}
|
|
1754
2001
|
if (finalUsage) {
|
|
1755
2002
|
// Fold subagent token usage into /cost accounting.
|
|
1756
2003
|
if (subagentBundle) {
|
|
@@ -1803,6 +2050,7 @@ class AgentChatController {
|
|
|
1803
2050
|
this.events.append({
|
|
1804
2051
|
role: 'status',
|
|
1805
2052
|
title: 'recovery',
|
|
2053
|
+
statusTone: 'warning',
|
|
1806
2054
|
content: recoveryNotice,
|
|
1807
2055
|
});
|
|
1808
2056
|
}
|
|
@@ -1811,7 +2059,11 @@ class AgentChatController {
|
|
|
1811
2059
|
return;
|
|
1812
2060
|
}
|
|
1813
2061
|
assistantStream.discardSegment();
|
|
1814
|
-
this.events.append({
|
|
2062
|
+
this.events.append({
|
|
2063
|
+
role: 'error',
|
|
2064
|
+
content: formatChatError(error),
|
|
2065
|
+
errorLayer: errorLayerForChatError(error),
|
|
2066
|
+
});
|
|
1815
2067
|
this.events.setStatus('Turn failed. Ready for the next input.');
|
|
1816
2068
|
const failedStats = error instanceof framework_1.QueryLoopError
|
|
1817
2069
|
? error.stats
|
|
@@ -1837,6 +2089,7 @@ class AgentChatController {
|
|
|
1837
2089
|
this.events.append({
|
|
1838
2090
|
role: 'status',
|
|
1839
2091
|
title: 'recovery',
|
|
2092
|
+
statusTone: 'warning',
|
|
1840
2093
|
content: recoveryNotice,
|
|
1841
2094
|
});
|
|
1842
2095
|
}
|
|
@@ -1879,7 +2132,9 @@ exports.InkChatController = AgentChatController;
|
|
|
1879
2132
|
function loadSessionIntoRuntime(runtime, sessionId) {
|
|
1880
2133
|
const history = (0, session_storage_1.loadSessionHistory)(sessionId);
|
|
1881
2134
|
runtime.store.setState({ conversationHistory: history });
|
|
1882
|
-
runtime.store.setState({
|
|
2135
|
+
runtime.store.setState({
|
|
2136
|
+
harnessState: (0, session_storage_1.loadSessionHarnessState)(sessionId) ?? (0, session_storage_1.loadSessionMeta)(sessionId)?.harnessState,
|
|
2137
|
+
});
|
|
1883
2138
|
return `Restored ${history.length} messages`;
|
|
1884
2139
|
}
|
|
1885
2140
|
function closeSession(runtime) {
|