@oh-my-pi/pi-coding-agent 15.10.3 → 15.10.5
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 +72 -0
- package/dist/types/capability/rule-buckets.d.ts +1 -1
- package/dist/types/capability/rule.d.ts +6 -1
- package/dist/types/cli/update-cli.d.ts +11 -1
- package/dist/types/config/model-registry.d.ts +18 -1
- package/dist/types/discovery/at-imports.d.ts +15 -0
- package/dist/types/edit/diff.d.ts +3 -2
- package/dist/types/eval/__tests__/helpers-local-roots.test.d.ts +1 -0
- package/dist/types/eval/__tests__/js-context-manager.test.d.ts +1 -0
- package/dist/types/eval/backend.d.ts +7 -0
- package/dist/types/eval/bridge-timeout.d.ts +1 -1
- package/dist/types/eval/{llm-bridge.d.ts → completion-bridge.d.ts} +8 -8
- package/dist/types/eval/idle-timeout.d.ts +1 -1
- package/dist/types/eval/js/context-manager.d.ts +1 -0
- package/dist/types/eval/js/executor.d.ts +2 -0
- package/dist/types/eval/js/index.d.ts +1 -1
- package/dist/types/eval/js/shared/helpers.d.ts +6 -0
- package/dist/types/eval/js/shared/runtime.d.ts +5 -0
- package/dist/types/eval/js/worker-protocol.d.ts +6 -0
- package/dist/types/eval/py/executor.d.ts +7 -0
- package/dist/types/eval/py/index.d.ts +1 -1
- package/dist/types/export/ttsr.d.ts +14 -0
- package/dist/types/extensibility/extensions/types.d.ts +8 -1
- package/dist/types/extensibility/legacy-pi-ai-shim.d.ts +1 -1
- package/dist/types/internal-urls/local-protocol.d.ts +10 -0
- package/dist/types/mcp/oauth-flow.d.ts +2 -2
- package/dist/types/modes/components/custom-editor.d.ts +3 -0
- package/dist/types/modes/components/{status-line.d.ts → status-line/component.d.ts} +2 -32
- package/dist/types/modes/components/status-line/index.d.ts +1 -0
- package/dist/types/modes/components/status-line/types.d.ts +31 -2
- package/dist/types/modes/image-references.d.ts +8 -3
- package/dist/types/modes/interactive-mode.d.ts +1 -1
- package/dist/types/modes/theme/theme.d.ts +2 -1
- package/dist/types/modes/types.d.ts +2 -1
- package/dist/types/modes/utils/ui-helpers.d.ts +2 -2
- package/dist/types/session/agent-session.d.ts +0 -2
- package/dist/types/tools/ask.d.ts +1 -0
- package/dist/types/tools/browser/tab-worker.d.ts +15 -0
- package/dist/types/tools/index.d.ts +17 -0
- package/dist/types/tools/render-utils.d.ts +1 -1
- package/dist/types/tools/tool-timeouts.d.ts +1 -1
- package/dist/types/utils/block-context.d.ts +35 -0
- package/dist/types/utils/image-loading.d.ts +12 -0
- package/package.json +29 -9
- package/src/capability/rule-buckets.ts +4 -2
- package/src/capability/rule.ts +10 -1
- package/src/cli/auth-broker-cli.ts +6 -7
- package/src/cli/auth-gateway-cli.ts +1 -1
- package/src/cli/list-models.ts +5 -0
- package/src/cli/update-cli.ts +138 -16
- package/src/config/model-registry.ts +81 -2
- package/src/debug/index.ts +4 -8
- package/src/discovery/at-imports.ts +273 -0
- package/src/discovery/builtin-rules/index.ts +4 -0
- package/src/discovery/builtin-rules/ts-no-test-timers.md +55 -0
- package/src/discovery/builtin-rules/ts-redundant-clear-guard.md +75 -0
- package/src/discovery/helpers.ts +2 -1
- package/src/edit/diff.ts +114 -4
- package/src/edit/hashline/diff.ts +1 -1
- package/src/edit/hashline/execute.ts +1 -1
- package/src/edit/modes/patch.ts +6 -2
- package/src/edit/modes/replace.ts +1 -1
- package/src/edit/renderer.ts +12 -2
- package/src/eval/__tests__/agent-bridge.test.ts +13 -0
- package/src/eval/__tests__/{llm-bridge.test.ts → completion-bridge.test.ts} +60 -54
- package/src/eval/__tests__/helpers-local-roots.test.ts +58 -0
- package/src/eval/__tests__/js-context-manager.test.ts +241 -0
- package/src/eval/agent-bridge.ts +6 -1
- package/src/eval/backend.ts +15 -0
- package/src/eval/bridge-timeout.ts +1 -1
- package/src/eval/{llm-bridge.ts → completion-bridge.ts} +30 -27
- package/src/eval/idle-timeout.ts +1 -1
- package/src/eval/js/context-manager.ts +70 -8
- package/src/eval/js/executor.ts +3 -0
- package/src/eval/js/index.ts +7 -1
- package/src/eval/js/shared/helpers.ts +53 -6
- package/src/eval/js/shared/prelude.txt +4 -4
- package/src/eval/js/shared/runtime.ts +8 -0
- package/src/eval/js/tool-bridge.ts +3 -3
- package/src/eval/js/worker-core.ts +1 -0
- package/src/eval/js/worker-entry.ts +6 -0
- package/src/eval/js/worker-protocol.ts +6 -0
- package/src/eval/py/executor.ts +12 -0
- package/src/eval/py/index.ts +7 -1
- package/src/eval/py/prelude.py +46 -7
- package/src/eval/py/runner.py +1 -0
- package/src/exa/render.ts +1 -1
- package/src/export/ttsr.ts +122 -1
- package/src/extensibility/extensions/types.ts +8 -1
- package/src/extensibility/legacy-pi-ai-shim.ts +1 -1
- package/src/extensibility/plugins/doctor.ts +1 -1
- package/src/extensibility/plugins/legacy-pi-compat.ts +6 -5
- package/src/goals/tools/goal-tool.ts +1 -1
- package/src/internal-urls/docs-index.generated.ts +8 -6
- package/src/internal-urls/local-protocol.ts +13 -0
- package/src/lsp/render.ts +8 -6
- package/src/mcp/oauth-flow.ts +3 -3
- package/src/mcp/render.ts +7 -1
- package/src/modes/components/custom-editor.ts +12 -6
- package/src/modes/components/login-dialog.ts +1 -1
- package/src/modes/components/oauth-selector.ts +4 -4
- package/src/modes/components/read-tool-group.ts +10 -3
- package/src/modes/components/{status-line.ts → status-line/component.ts} +18 -40
- package/src/modes/components/status-line/index.ts +1 -0
- package/src/modes/components/status-line/types.ts +23 -8
- package/src/modes/components/tips.txt +1 -1
- package/src/modes/components/tool-execution.ts +1 -1
- package/src/modes/components/transcript-container.ts +17 -10
- package/src/modes/components/user-message.ts +6 -3
- package/src/modes/components/welcome.ts +1 -1
- package/src/modes/controllers/extension-ui-controller.ts +143 -127
- package/src/modes/controllers/input-controller.ts +36 -10
- package/src/modes/controllers/mcp-command-controller.ts +28 -12
- package/src/modes/controllers/selector-controller.ts +4 -11
- package/src/modes/controllers/ssh-command-controller.ts +2 -2
- package/src/modes/image-references.ts +13 -7
- package/src/modes/interactive-mode.ts +2 -2
- package/src/modes/rpc/rpc-mode.ts +1 -1
- package/src/modes/setup-wizard/scenes/sign-in.ts +3 -11
- package/src/modes/theme/theme.ts +95 -1
- package/src/modes/types.ts +2 -1
- package/src/modes/utils/ui-helpers.ts +14 -5
- package/src/prompts/system/tiny-title-system.md +1 -1
- package/src/prompts/system/title-system.md +16 -3
- package/src/prompts/system/workflow-notice.md +1 -1
- package/src/prompts/tools/bash.md +1 -1
- package/src/prompts/tools/eval.md +6 -6
- package/src/sdk.ts +31 -14
- package/src/session/agent-session.ts +213 -155
- package/src/session/session-manager.ts +1 -1
- package/src/slash-commands/builtin-registry.ts +1 -1
- package/src/system-prompt.ts +15 -9
- package/src/task/render.ts +20 -8
- package/src/tools/ask.ts +14 -5
- package/src/tools/bash-interactive.ts +1 -1
- package/src/tools/bash.ts +14 -2
- package/src/tools/browser/render.ts +5 -2
- package/src/tools/browser/tab-worker.ts +211 -91
- package/src/tools/debug.ts +5 -2
- package/src/tools/eval-render.ts +8 -5
- package/src/tools/eval.ts +2 -2
- package/src/tools/gh-renderer.ts +29 -15
- package/src/tools/index.ts +32 -0
- package/src/tools/inspect-image-renderer.ts +12 -5
- package/src/tools/job.ts +9 -6
- package/src/tools/memory-render.ts +19 -5
- package/src/tools/read.ts +165 -18
- package/src/tools/render-utils.ts +3 -1
- package/src/tools/resolve.ts +1 -1
- package/src/tools/review.ts +1 -1
- package/src/tools/ssh.ts +4 -1
- package/src/tools/todo.ts +8 -1
- package/src/tools/tool-timeouts.ts +1 -1
- package/src/tools/write.ts +1 -1
- package/src/tui/code-cell.ts +1 -1
- package/src/utils/block-context.ts +312 -0
- package/src/utils/image-loading.ts +31 -1
- package/src/utils/title-generator.ts +2 -2
- package/src/web/search/providers/codex.ts +1 -1
- package/src/web/search/render.ts +14 -6
- /package/dist/types/eval/__tests__/{llm-bridge.test.d.ts → completion-bridge.test.d.ts} +0 -0
package/src/tools/gh-renderer.ts
CHANGED
|
@@ -163,8 +163,8 @@ function getJobStateVisual(
|
|
|
163
163
|
): { iconRaw: string; iconColor: ToolUIColor; textColor: ThemeColor } {
|
|
164
164
|
if (job.conclusion && SUCCESS_CONCLUSIONS.has(job.conclusion)) {
|
|
165
165
|
return {
|
|
166
|
-
iconRaw: theme.
|
|
167
|
-
iconColor: "
|
|
166
|
+
iconRaw: theme.symbol("tool.gh"),
|
|
167
|
+
iconColor: "accent",
|
|
168
168
|
textColor: "success",
|
|
169
169
|
};
|
|
170
170
|
}
|
|
@@ -327,14 +327,21 @@ function renderFallbackComponent(
|
|
|
327
327
|
const title = formatOpTitle(args.op);
|
|
328
328
|
const meta = buildOpMeta(args);
|
|
329
329
|
const isError = result.isError === true;
|
|
330
|
-
const
|
|
330
|
+
const success = !isError && Boolean(text);
|
|
331
331
|
const header = renderStatusLine(
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
332
|
+
success
|
|
333
|
+
? {
|
|
334
|
+
iconOverride: theme.styledSymbol("tool.gh", "accent"),
|
|
335
|
+
title,
|
|
336
|
+
titleColor: "accent",
|
|
337
|
+
meta,
|
|
338
|
+
}
|
|
339
|
+
: {
|
|
340
|
+
icon: isError ? "error" : "warning",
|
|
341
|
+
title,
|
|
342
|
+
titleColor: isError ? "error" : "accent",
|
|
343
|
+
meta,
|
|
344
|
+
},
|
|
338
345
|
theme,
|
|
339
346
|
);
|
|
340
347
|
|
|
@@ -438,12 +445,19 @@ export const githubToolRenderer = {
|
|
|
438
445
|
if (watch) {
|
|
439
446
|
const isError = result.isError === true;
|
|
440
447
|
const header = renderStatusLine(
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
448
|
+
isError
|
|
449
|
+
? {
|
|
450
|
+
icon: "error",
|
|
451
|
+
title: "GitHub Run Watch",
|
|
452
|
+
titleColor: "error",
|
|
453
|
+
meta: [getWatchHeader(watch)],
|
|
454
|
+
}
|
|
455
|
+
: {
|
|
456
|
+
iconOverride: uiTheme.styledSymbol("tool.gh", "accent"),
|
|
457
|
+
title: "GitHub Run Watch",
|
|
458
|
+
titleColor: "accent",
|
|
459
|
+
meta: [getWatchHeader(watch)],
|
|
460
|
+
},
|
|
447
461
|
uiTheme,
|
|
448
462
|
);
|
|
449
463
|
return framedBlock(uiTheme, width => {
|
package/src/tools/index.ts
CHANGED
|
@@ -342,6 +342,38 @@ export function computeEssentialBuiltinNames(settings: Settings): string[] {
|
|
|
342
342
|
return [...DEFAULT_ESSENTIAL_TOOL_NAMES];
|
|
343
343
|
}
|
|
344
344
|
|
|
345
|
+
/**
|
|
346
|
+
* Filter the initial active tool set when `tools.discoveryMode === "all"`.
|
|
347
|
+
*
|
|
348
|
+
* Non-essential discoverable built-ins are hidden — the model rediscovers them
|
|
349
|
+
* via `search_tool_bm25` and activates them on demand. A tool survives hiding
|
|
350
|
+
* when it is essential, explicitly requested, restored from a prior selection,
|
|
351
|
+
* or required by a forced tool_choice feature (`forceActive`). The last case is
|
|
352
|
+
* load-bearing: a named tool_choice (e.g. the eager `todo` prelude) must
|
|
353
|
+
* reference a tool present in the request, or the provider rejects it with 400.
|
|
354
|
+
*/
|
|
355
|
+
export function filterInitialToolsForDiscoveryAll(
|
|
356
|
+
initialToolNames: string[],
|
|
357
|
+
opts: {
|
|
358
|
+
loadModeOf: (name: string) => BuiltinToolLoadMode | undefined;
|
|
359
|
+
essentialNames: ReadonlySet<string>;
|
|
360
|
+
explicitlyRequested: ReadonlySet<string>;
|
|
361
|
+
restored: ReadonlySet<string>;
|
|
362
|
+
forceActive: ReadonlySet<string>;
|
|
363
|
+
},
|
|
364
|
+
): string[] {
|
|
365
|
+
return initialToolNames.filter(name => {
|
|
366
|
+
const loadMode = opts.loadModeOf(name);
|
|
367
|
+
if (!loadMode) return true; // not a built-in — leave MCP/custom/extension to existing logic
|
|
368
|
+
if (loadMode === "essential") return true;
|
|
369
|
+
if (opts.essentialNames.has(name)) return true;
|
|
370
|
+
if (opts.explicitlyRequested.has(name)) return true;
|
|
371
|
+
if (opts.restored.has(name)) return true;
|
|
372
|
+
if (opts.forceActive.has(name)) return true;
|
|
373
|
+
return false;
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
|
|
345
377
|
/**
|
|
346
378
|
* Public callable factory map. External callers may invoke `BUILTIN_TOOLS.read(session)` or
|
|
347
379
|
* `BUILTIN_TOOLS[name](session)` to construct a tool directly.
|
|
@@ -53,12 +53,19 @@ export const inspectImageToolRenderer = {
|
|
|
53
53
|
const details = result.details;
|
|
54
54
|
const rawPath = details?.imagePath ?? args?.path ?? "";
|
|
55
55
|
const pathDisplay = rawPath ? shortenPath(rawPath) : "image";
|
|
56
|
+
const success = !result.isError;
|
|
56
57
|
const header = renderStatusLine(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
success
|
|
59
|
+
? {
|
|
60
|
+
iconOverride: uiTheme.styledSymbol("tool.inspectImage", "accent"),
|
|
61
|
+
title: "Inspect",
|
|
62
|
+
description: pathDisplay,
|
|
63
|
+
}
|
|
64
|
+
: {
|
|
65
|
+
icon: "error",
|
|
66
|
+
title: "Inspect",
|
|
67
|
+
description: pathDisplay,
|
|
68
|
+
},
|
|
62
69
|
uiTheme,
|
|
63
70
|
);
|
|
64
71
|
|
package/src/tools/job.ts
CHANGED
|
@@ -355,7 +355,7 @@ const PREVIEW_LINE_WIDTH = 80;
|
|
|
355
355
|
function statusToIcon(status: JobSnapshot["status"]): ToolUIStatus {
|
|
356
356
|
switch (status) {
|
|
357
357
|
case "completed":
|
|
358
|
-
return "
|
|
358
|
+
return "done";
|
|
359
359
|
case "failed":
|
|
360
360
|
return "error";
|
|
361
361
|
case "cancelled":
|
|
@@ -468,11 +468,14 @@ export const jobToolRenderer = {
|
|
|
468
468
|
itemType: "job",
|
|
469
469
|
renderItem: job => {
|
|
470
470
|
const lines: string[] = [];
|
|
471
|
-
const icon =
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
471
|
+
const icon =
|
|
472
|
+
job.status === "completed"
|
|
473
|
+
? uiTheme.styledSymbol("tool.job", "accent")
|
|
474
|
+
: formatStatusIcon(
|
|
475
|
+
statusToIcon(job.status),
|
|
476
|
+
uiTheme,
|
|
477
|
+
job.status === "running" ? options.spinnerFrame : undefined,
|
|
478
|
+
);
|
|
476
479
|
const typeBadge = formatBadge(job.type, statusToColor(job.status), uiTheme);
|
|
477
480
|
const idText = uiTheme.fg("muted", job.id);
|
|
478
481
|
const rawLabelLines = (job.label || "(no label)").split(/\r?\n/);
|
|
@@ -49,10 +49,11 @@ function queryHeader(
|
|
|
49
49
|
icon: ToolUIStatus,
|
|
50
50
|
theme: Theme,
|
|
51
51
|
meta?: string[],
|
|
52
|
+
iconOverride?: string,
|
|
52
53
|
): string {
|
|
53
54
|
const trimmed = replaceTabs((query ?? "").trim());
|
|
54
55
|
const description = trimmed ? truncateToWidth(trimmed, 80, Ellipsis.Unicode) : undefined;
|
|
55
|
-
return renderStatusLine({ icon, title, description, meta }, theme);
|
|
56
|
+
return renderStatusLine({ icon, iconOverride, title, description, meta }, theme);
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
function retainComponent(contents: string[], header: string, getExpanded: () => boolean, theme: Theme): Component {
|
|
@@ -96,7 +97,11 @@ export const retainToolRenderer = {
|
|
|
96
97
|
// trailing period so it reads cleanly as a status meta segment.
|
|
97
98
|
const summary = resultText(result).replace(/\.$/, "");
|
|
98
99
|
const header = renderStatusLine(
|
|
99
|
-
{
|
|
100
|
+
{
|
|
101
|
+
iconOverride: theme.styledSymbol("tool.memory", "accent"),
|
|
102
|
+
title: "Retain",
|
|
103
|
+
meta: summary ? [summary] : undefined,
|
|
104
|
+
},
|
|
100
105
|
theme,
|
|
101
106
|
);
|
|
102
107
|
return retainComponent(contents, header, () => options.expanded, theme);
|
|
@@ -121,9 +126,11 @@ export const recallToolRenderer = {
|
|
|
121
126
|
const text = resultText(result);
|
|
122
127
|
const match = text.match(/^Found (\d+) relevant/);
|
|
123
128
|
const found = match ? Number(match[1]) : 0;
|
|
124
|
-
const icon: ToolUIStatus = found > 0 ? "success" : "warning";
|
|
125
129
|
const meta = [found > 0 ? `${found} found` : "no matches"];
|
|
126
|
-
const header =
|
|
130
|
+
const header =
|
|
131
|
+
found > 0
|
|
132
|
+
? queryHeader("Recall", args?.query, "success", theme, meta, theme.styledSymbol("tool.memory", "accent"))
|
|
133
|
+
: queryHeader("Recall", args?.query, "warning", theme, meta);
|
|
127
134
|
if (found === 0) {
|
|
128
135
|
return new Text(header, 0, 0);
|
|
129
136
|
}
|
|
@@ -163,7 +170,14 @@ export const reflectToolRenderer = {
|
|
|
163
170
|
if (result.isError) {
|
|
164
171
|
return new Text(formatErrorMessage(resultText(result) || "Reflect failed", theme), 0, 0);
|
|
165
172
|
}
|
|
166
|
-
const header = queryHeader(
|
|
173
|
+
const header = queryHeader(
|
|
174
|
+
"Reflect",
|
|
175
|
+
args?.query,
|
|
176
|
+
"success",
|
|
177
|
+
theme,
|
|
178
|
+
undefined,
|
|
179
|
+
theme.styledSymbol("tool.memory", "accent"),
|
|
180
|
+
);
|
|
167
181
|
const answer = resultText(result);
|
|
168
182
|
const answerLines = answer.split("\n").filter(line => line.trim().length > 0);
|
|
169
183
|
return createCachedComponent(
|
package/src/tools/read.ts
CHANGED
|
@@ -9,7 +9,12 @@ import type { Component } from "@oh-my-pi/pi-tui";
|
|
|
9
9
|
import { Text } from "@oh-my-pi/pi-tui";
|
|
10
10
|
import { getRemoteDir, logger, prompt, readImageMetadata, untilAborted } from "@oh-my-pi/pi-utils";
|
|
11
11
|
import * as z from "zod/v4";
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
canonicalSnapshotKey,
|
|
14
|
+
getFileSnapshotStore,
|
|
15
|
+
recordFileSnapshot,
|
|
16
|
+
SNAPSHOT_MAX_BYTES,
|
|
17
|
+
} from "../edit/file-snapshot-store";
|
|
13
18
|
import { normalizeToLF } from "../edit/normalize";
|
|
14
19
|
import { isNotebookPath, readEditableNotebookText } from "../edit/notebook";
|
|
15
20
|
import type { RenderResultOptions } from "../extensibility/custom-tools/types";
|
|
@@ -30,6 +35,7 @@ import {
|
|
|
30
35
|
} from "../session/streaming-output";
|
|
31
36
|
import { fileHyperlink, renderCodeCell, renderMarkdownCell, renderStatusLine, tryResolveInternalUrlSync } from "../tui";
|
|
32
37
|
import { CachedOutputBlock, markFramedBlockComponent } from "../tui/output-block";
|
|
38
|
+
import { buildLineEntriesWithBlockContext, type LineEntry, lineEntriesToPlainText } from "../utils/block-context";
|
|
33
39
|
import { resolveFileDisplayMode } from "../utils/file-display-mode";
|
|
34
40
|
import { ImageInputTooLargeError, loadImageInput, MAX_IMAGE_INPUT_BYTES } from "../utils/image-loading";
|
|
35
41
|
import { convertFileWithMarkit } from "../utils/markit";
|
|
@@ -108,6 +114,15 @@ const PROSE_SUMMARY_EXTENSIONS = new Set([".md", ".txt"]);
|
|
|
108
114
|
// Remote mount path prefix (sshfs mounts) - skip fuzzy matching to avoid hangs
|
|
109
115
|
const REMOTE_MOUNT_PREFIX = getRemoteDir() + path.sep;
|
|
110
116
|
|
|
117
|
+
async function readBracketContextFullLines(absolutePath: string, fileSize: number): Promise<string[] | undefined> {
|
|
118
|
+
if (fileSize > SNAPSHOT_MAX_BYTES) return undefined;
|
|
119
|
+
try {
|
|
120
|
+
return normalizeToLF(await Bun.file(absolutePath).text()).split("\n");
|
|
121
|
+
} catch {
|
|
122
|
+
return undefined;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
111
126
|
function isRemoteMountPath(absolutePath: string): boolean {
|
|
112
127
|
return absolutePath.startsWith(REMOTE_MOUNT_PREFIX);
|
|
113
128
|
}
|
|
@@ -174,6 +189,21 @@ function formatTextWithMode(
|
|
|
174
189
|
return text;
|
|
175
190
|
}
|
|
176
191
|
|
|
192
|
+
const BRACKET_CONTEXT_ELLIPSIS = "…";
|
|
193
|
+
|
|
194
|
+
function formatLineEntryWithMode(entry: LineEntry, shouldAddHashLines: boolean, shouldAddLineNumbers: boolean): string {
|
|
195
|
+
if (entry.kind === "ellipsis") return BRACKET_CONTEXT_ELLIPSIS;
|
|
196
|
+
return formatSingleLine(entry.lineNumber, entry.text, shouldAddHashLines, shouldAddLineNumbers);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function formatLineEntriesWithMode(
|
|
200
|
+
entries: readonly LineEntry[],
|
|
201
|
+
shouldAddHashLines: boolean,
|
|
202
|
+
shouldAddLineNumbers: boolean,
|
|
203
|
+
): string {
|
|
204
|
+
return entries.map(entry => formatLineEntryWithMode(entry, shouldAddHashLines, shouldAddLineNumbers)).join("\n");
|
|
205
|
+
}
|
|
206
|
+
|
|
177
207
|
const BRACE_PAIRS: Record<string, string> = { "{": "}", "(": ")", "[": "]" };
|
|
178
208
|
const BRACE_TAIL_TRAILING_RE = /^[;,)\]}]*$/;
|
|
179
209
|
|
|
@@ -915,6 +945,21 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
|
|
|
915
945
|
emittedHashlineHeader = true;
|
|
916
946
|
return prependHashlineHeader(formatted, hashContext);
|
|
917
947
|
};
|
|
948
|
+
const formatLineEntries = (entries: readonly LineEntry[], startNum: number): string => {
|
|
949
|
+
const firstLine = entries.find(entry => entry.kind === "line");
|
|
950
|
+
details.displayContent = {
|
|
951
|
+
text: lineEntriesToPlainText(entries, BRACKET_CONTEXT_ELLIPSIS),
|
|
952
|
+
startLine: firstLine?.kind === "line" ? firstLine.lineNumber : startNum,
|
|
953
|
+
};
|
|
954
|
+
const formatted = formatLineEntriesWithMode(entries, shouldAddHashLines, shouldAddLineNumbers);
|
|
955
|
+
if (!hashContext || emittedHashlineHeader) return formatted;
|
|
956
|
+
emittedHashlineHeader = true;
|
|
957
|
+
return prependHashlineHeader(formatted, hashContext);
|
|
958
|
+
};
|
|
959
|
+
const buildLineEntries = (endLineDisplay: number): LineEntry[] =>
|
|
960
|
+
buildLineEntriesWithBlockContext(allLines, [{ startLine: startLineDisplay, endLine: endLineDisplay }], {
|
|
961
|
+
path: options.sourcePath,
|
|
962
|
+
});
|
|
918
963
|
|
|
919
964
|
let outputText: string;
|
|
920
965
|
let truncationInfo:
|
|
@@ -946,7 +991,12 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
|
|
|
946
991
|
options: { direction: "head", startLine: startLineDisplay, totalFileLines: totalLines },
|
|
947
992
|
};
|
|
948
993
|
} else if (truncation.truncated) {
|
|
949
|
-
|
|
994
|
+
const outputLines = truncation.outputLines ?? countTextLines(truncation.content);
|
|
995
|
+
const endLineDisplay = startLineDisplay + Math.max(0, outputLines - 1);
|
|
996
|
+
outputText =
|
|
997
|
+
options.raw === true
|
|
998
|
+
? formatText(truncation.content, startLineDisplay)
|
|
999
|
+
: formatLineEntries(buildLineEntries(endLineDisplay), startLineDisplay);
|
|
950
1000
|
details.truncation = truncation;
|
|
951
1001
|
truncationInfo = {
|
|
952
1002
|
result: truncation,
|
|
@@ -956,10 +1006,16 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
|
|
|
956
1006
|
const remaining = allLines.length - (startLine + userLimitedLines);
|
|
957
1007
|
const nextOffset = startLine + userLimitedLines + 1;
|
|
958
1008
|
|
|
959
|
-
outputText =
|
|
1009
|
+
outputText =
|
|
1010
|
+
options.raw === true
|
|
1011
|
+
? formatText(selectedContent, startLineDisplay)
|
|
1012
|
+
: formatLineEntries(buildLineEntries(endLine), startLineDisplay);
|
|
960
1013
|
outputText += `\n\n[${remaining} more lines in ${options.entityLabel}. Use :${nextOffset} to continue]`;
|
|
961
1014
|
} else {
|
|
962
|
-
outputText =
|
|
1015
|
+
outputText =
|
|
1016
|
+
options.raw === true
|
|
1017
|
+
? formatText(truncation.content, startLineDisplay)
|
|
1018
|
+
: formatLineEntries(buildLineEntries(endLine), startLineDisplay);
|
|
963
1019
|
}
|
|
964
1020
|
|
|
965
1021
|
resultBuilder.text(outputText);
|
|
@@ -1011,21 +1067,37 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
|
|
|
1011
1067
|
if (options.sourceUrl) resultBuilder.sourceUrl(options.sourceUrl);
|
|
1012
1068
|
if (options.sourceInternal) resultBuilder.sourceInternal(options.sourceInternal);
|
|
1013
1069
|
|
|
1014
|
-
const parts: string[] = [];
|
|
1015
1070
|
const outOfBounds: LineRange[] = [];
|
|
1071
|
+
const visibleSpans: Array<{ startLine: number; endLine: number }> = [];
|
|
1072
|
+
const rawParts: string[] = [];
|
|
1016
1073
|
for (const range of ranges) {
|
|
1017
1074
|
if (range.startLine > totalLines) {
|
|
1018
1075
|
outOfBounds.push(range);
|
|
1019
1076
|
continue;
|
|
1020
1077
|
}
|
|
1021
1078
|
const effectiveEnd = Math.min(range.endLine ?? totalLines, totalLines);
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1079
|
+
visibleSpans.push({ startLine: range.startLine, endLine: effectiveEnd });
|
|
1080
|
+
if (options.raw === true) {
|
|
1081
|
+
rawParts.push(allLines.slice(range.startLine - 1, effectiveEnd).join("\n"));
|
|
1082
|
+
}
|
|
1026
1083
|
}
|
|
1027
1084
|
|
|
1028
|
-
|
|
1085
|
+
let outputText = "";
|
|
1086
|
+
if (options.raw === true) {
|
|
1087
|
+
outputText = rawParts.length > 0 ? rawParts.join("\n\n…\n\n") : "";
|
|
1088
|
+
} else if (visibleSpans.length > 0) {
|
|
1089
|
+
const entries = buildLineEntriesWithBlockContext(allLines, visibleSpans, { path: options.sourcePath });
|
|
1090
|
+
const firstLine = entries.find(entry => entry.kind === "line");
|
|
1091
|
+
if (firstLine?.kind === "line") {
|
|
1092
|
+
details.displayContent = {
|
|
1093
|
+
text: lineEntriesToPlainText(entries, BRACKET_CONTEXT_ELLIPSIS),
|
|
1094
|
+
startLine: firstLine.lineNumber,
|
|
1095
|
+
};
|
|
1096
|
+
}
|
|
1097
|
+
const formatted = formatLineEntriesWithMode(entries, shouldAddHashLines, shouldAddLineNumbers);
|
|
1098
|
+
outputText = hashContext && !emittedHashlineHeader ? prependHashlineHeader(formatted, hashContext) : formatted;
|
|
1099
|
+
if (hashContext) emittedHashlineHeader = true;
|
|
1100
|
+
}
|
|
1029
1101
|
const notices: string[] = [];
|
|
1030
1102
|
for (const range of outOfBounds) {
|
|
1031
1103
|
const bound = range.endLine !== undefined ? `${range.startLine}-${range.endLine}` : `${range.startLine}`;
|
|
@@ -1046,6 +1118,7 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
|
|
|
1046
1118
|
async #readLocalFileMultiRange(
|
|
1047
1119
|
absolutePath: string,
|
|
1048
1120
|
ranges: readonly LineRange[],
|
|
1121
|
+
fileSize: number,
|
|
1049
1122
|
parsed: ParsedSelector,
|
|
1050
1123
|
displayMode: { hashLines: boolean; lineNumbers: boolean },
|
|
1051
1124
|
suffixResolution: { from: string; to: string } | undefined,
|
|
@@ -1053,6 +1126,7 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
|
|
|
1053
1126
|
): Promise<{
|
|
1054
1127
|
outputText: string;
|
|
1055
1128
|
columnTruncated: number;
|
|
1129
|
+
displayContent?: { text: string; startLine: number };
|
|
1056
1130
|
bridgeResult?: AgentToolResult<ReadToolDetails>;
|
|
1057
1131
|
}> {
|
|
1058
1132
|
const rawSelector = isRawSelector(parsed);
|
|
@@ -1085,7 +1159,11 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
|
|
|
1085
1159
|
|
|
1086
1160
|
const blocks: string[] = [];
|
|
1087
1161
|
const notices: string[] = [];
|
|
1162
|
+
const visibleSpans: Array<{ startLine: number; endLine: number }> = [];
|
|
1163
|
+
const displayLineByNumber = new Map<number, string>();
|
|
1164
|
+
const fullLines = rawSelector ? undefined : await readBracketContextFullLines(absolutePath, fileSize);
|
|
1088
1165
|
let columnTruncated = 0;
|
|
1166
|
+
let displayContent: { text: string; startLine: number } | undefined;
|
|
1089
1167
|
|
|
1090
1168
|
for (const range of ranges) {
|
|
1091
1169
|
const rangeStart = range.startLine - 1; // 0-indexed
|
|
@@ -1125,11 +1203,43 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
|
|
|
1125
1203
|
}
|
|
1126
1204
|
if (cloned) displayLines = cloned;
|
|
1127
1205
|
}
|
|
1128
|
-
const
|
|
1129
|
-
|
|
1206
|
+
const endLine = range.startLine + Math.max(0, displayLines.length - 1);
|
|
1207
|
+
visibleSpans.push({ startLine: range.startLine, endLine });
|
|
1208
|
+
for (let i = 0; i < displayLines.length; i++) {
|
|
1209
|
+
displayLineByNumber.set(range.startLine + i, displayLines[i] ?? "");
|
|
1210
|
+
}
|
|
1211
|
+
if (!fullLines || rawSelector) {
|
|
1212
|
+
const blockText = displayLines.join("\n");
|
|
1213
|
+
blocks.push(formatTextWithMode(blockText, range.startLine, shouldAddHashLines, shouldAddLineNumbers));
|
|
1214
|
+
}
|
|
1130
1215
|
}
|
|
1131
1216
|
|
|
1132
|
-
let outputText
|
|
1217
|
+
let outputText: string;
|
|
1218
|
+
if (!rawSelector && fullLines && visibleSpans.length > 0) {
|
|
1219
|
+
const entries = buildLineEntriesWithBlockContext(
|
|
1220
|
+
fullLines,
|
|
1221
|
+
visibleSpans,
|
|
1222
|
+
{ path: absolutePath },
|
|
1223
|
+
{
|
|
1224
|
+
lineText: (lineNumber, sourceText) => {
|
|
1225
|
+
const visibleText = displayLineByNumber.get(lineNumber);
|
|
1226
|
+
if (visibleText !== undefined) return visibleText;
|
|
1227
|
+
if (maxColumns <= 0) return sourceText;
|
|
1228
|
+
const truncated = truncateLine(sourceText, maxColumns);
|
|
1229
|
+
if (truncated.wasTruncated) columnTruncated = maxColumns;
|
|
1230
|
+
return truncated.text;
|
|
1231
|
+
},
|
|
1232
|
+
},
|
|
1233
|
+
);
|
|
1234
|
+
const firstLine = entries.find(entry => entry.kind === "line");
|
|
1235
|
+
displayContent = {
|
|
1236
|
+
text: lineEntriesToPlainText(entries, BRACKET_CONTEXT_ELLIPSIS),
|
|
1237
|
+
startLine: firstLine?.kind === "line" ? firstLine.lineNumber : (visibleSpans[0]?.startLine ?? 1),
|
|
1238
|
+
};
|
|
1239
|
+
outputText = formatLineEntriesWithMode(entries, shouldAddHashLines, shouldAddLineNumbers);
|
|
1240
|
+
} else {
|
|
1241
|
+
outputText = blocks.join("\n\n…\n\n");
|
|
1242
|
+
}
|
|
1133
1243
|
if (shouldAddHashLines && outputText) {
|
|
1134
1244
|
const tag = await recordFileSnapshot(this.session, absolutePath);
|
|
1135
1245
|
if (tag) {
|
|
@@ -1139,7 +1249,7 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
|
|
|
1139
1249
|
if (notices.length > 0) {
|
|
1140
1250
|
outputText = outputText ? `${outputText}\n${notices.join("\n")}` : notices.join("\n");
|
|
1141
1251
|
}
|
|
1142
|
-
return { outputText, columnTruncated };
|
|
1252
|
+
return { outputText, columnTruncated, displayContent };
|
|
1143
1253
|
}
|
|
1144
1254
|
|
|
1145
1255
|
async #readArchiveDirectory(
|
|
@@ -1818,6 +1928,7 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
|
|
|
1818
1928
|
const multiResult = await this.#readLocalFileMultiRange(
|
|
1819
1929
|
absolutePath,
|
|
1820
1930
|
parsed.ranges,
|
|
1931
|
+
fileSize,
|
|
1821
1932
|
parsed,
|
|
1822
1933
|
displayMode,
|
|
1823
1934
|
suffixResolution,
|
|
@@ -1826,7 +1937,7 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
|
|
|
1826
1937
|
if (multiResult.bridgeResult) return multiResult.bridgeResult;
|
|
1827
1938
|
content = [{ type: "text", text: multiResult.outputText }];
|
|
1828
1939
|
sourcePath = absolutePath;
|
|
1829
|
-
details = {};
|
|
1940
|
+
details = multiResult.displayContent ? { displayContent: multiResult.displayContent } : {};
|
|
1830
1941
|
if (multiResult.columnTruncated > 0) {
|
|
1831
1942
|
columnTruncated = multiResult.columnTruncated;
|
|
1832
1943
|
}
|
|
@@ -1930,6 +2041,15 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
|
|
|
1930
2041
|
if (cloned) displayLines = cloned;
|
|
1931
2042
|
}
|
|
1932
2043
|
|
|
2044
|
+
const displayLineByNumber = new Map<number, string>();
|
|
2045
|
+
for (let i = 0; i < displayLines.length; i++) {
|
|
2046
|
+
displayLineByNumber.set(startLineDisplay + i, displayLines[i] ?? "");
|
|
2047
|
+
}
|
|
2048
|
+
const bracketContextFullLines = rawSelector
|
|
2049
|
+
? undefined
|
|
2050
|
+
: await readBracketContextFullLines(absolutePath, fileSize);
|
|
2051
|
+
const displayedEndLine = startLineDisplay + Math.max(0, displayLines.length - 1);
|
|
2052
|
+
|
|
1933
2053
|
const selectedContent = displayLines.join("\n");
|
|
1934
2054
|
const userLimitedLines = collectedLines.length;
|
|
1935
2055
|
|
|
@@ -1979,6 +2099,33 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
|
|
|
1979
2099
|
emittedHashlineHeader = true;
|
|
1980
2100
|
return prependHashlineHeader(formatted, hashContext);
|
|
1981
2101
|
};
|
|
2102
|
+
const formatBracketAwareText = (): string | undefined => {
|
|
2103
|
+
if (!bracketContextFullLines) return undefined;
|
|
2104
|
+
const entries = buildLineEntriesWithBlockContext(
|
|
2105
|
+
bracketContextFullLines,
|
|
2106
|
+
[{ startLine: startLineDisplay, endLine: displayedEndLine }],
|
|
2107
|
+
{ path: absolutePath },
|
|
2108
|
+
{
|
|
2109
|
+
lineText: (lineNumber, sourceText) => {
|
|
2110
|
+
const visibleText = displayLineByNumber.get(lineNumber);
|
|
2111
|
+
if (visibleText !== undefined) return visibleText;
|
|
2112
|
+
if (maxColumns <= 0) return sourceText;
|
|
2113
|
+
const truncated = truncateLine(sourceText, maxColumns);
|
|
2114
|
+
if (truncated.wasTruncated) columnTruncated = maxColumns;
|
|
2115
|
+
return truncated.text;
|
|
2116
|
+
},
|
|
2117
|
+
},
|
|
2118
|
+
);
|
|
2119
|
+
const firstLine = entries.find(entry => entry.kind === "line");
|
|
2120
|
+
capturedDisplayContent = {
|
|
2121
|
+
text: lineEntriesToPlainText(entries, BRACKET_CONTEXT_ELLIPSIS),
|
|
2122
|
+
startLine: firstLine?.kind === "line" ? firstLine.lineNumber : startLineDisplay,
|
|
2123
|
+
};
|
|
2124
|
+
const formatted = formatLineEntriesWithMode(entries, shouldAddHashLines, shouldAddLineNumbers);
|
|
2125
|
+
if (!hashContext || emittedHashlineHeader) return formatted;
|
|
2126
|
+
emittedHashlineHeader = true;
|
|
2127
|
+
return prependHashlineHeader(formatted, hashContext);
|
|
2128
|
+
};
|
|
1982
2129
|
|
|
1983
2130
|
let outputText: string;
|
|
1984
2131
|
|
|
@@ -2005,7 +2152,7 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
|
|
|
2005
2152
|
options: { direction: "head", startLine: startLineDisplay, totalFileLines },
|
|
2006
2153
|
};
|
|
2007
2154
|
} else if (truncation.truncated) {
|
|
2008
|
-
outputText = formatText(truncation.content, startLineDisplay);
|
|
2155
|
+
outputText = formatBracketAwareText() ?? formatText(truncation.content, startLineDisplay);
|
|
2009
2156
|
details = { truncation };
|
|
2010
2157
|
sourcePath = absolutePath;
|
|
2011
2158
|
truncationInfo = {
|
|
@@ -2016,13 +2163,13 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
|
|
|
2016
2163
|
const remaining = totalFileLines - (startLine + userLimitedLines);
|
|
2017
2164
|
const nextOffset = startLine + userLimitedLines + 1;
|
|
2018
2165
|
|
|
2019
|
-
outputText = formatText(truncation.content, startLineDisplay);
|
|
2166
|
+
outputText = formatBracketAwareText() ?? formatText(truncation.content, startLineDisplay);
|
|
2020
2167
|
outputText += `\n\n[${remaining} more lines in file. Use :${nextOffset} to continue]`;
|
|
2021
2168
|
details = {};
|
|
2022
2169
|
sourcePath = absolutePath;
|
|
2023
2170
|
} else {
|
|
2024
2171
|
// No truncation, no user limit exceeded
|
|
2025
|
-
outputText = formatText(truncation.content, startLineDisplay);
|
|
2172
|
+
outputText = formatBracketAwareText() ?? formatText(truncation.content, startLineDisplay);
|
|
2026
2173
|
details = {};
|
|
2027
2174
|
sourcePath = absolutePath;
|
|
2028
2175
|
}
|
|
@@ -133,6 +133,8 @@ export function formatStatusIcon(status: ToolUIStatus, theme: Theme, spinnerFram
|
|
|
133
133
|
switch (status) {
|
|
134
134
|
case "success":
|
|
135
135
|
return theme.styledSymbol("status.success", "success");
|
|
136
|
+
case "done":
|
|
137
|
+
return theme.styledSymbol("status.done", "success");
|
|
136
138
|
case "error":
|
|
137
139
|
return theme.styledSymbol("status.error", "error");
|
|
138
140
|
case "warning":
|
|
@@ -276,7 +278,7 @@ export function formatCodeFrameLine(
|
|
|
276
278
|
// Tool UI Helpers
|
|
277
279
|
// =============================================================================
|
|
278
280
|
|
|
279
|
-
export type ToolUIStatus = "success" | "error" | "warning" | "info" | "pending" | "running" | "aborted";
|
|
281
|
+
export type ToolUIStatus = "success" | "done" | "error" | "warning" | "info" | "pending" | "running" | "aborted";
|
|
280
282
|
export type ToolUIColor = "success" | "error" | "warning" | "accent" | "muted";
|
|
281
283
|
|
|
282
284
|
export interface ToolUITitleOptions {
|
package/src/tools/resolve.ts
CHANGED
|
@@ -241,7 +241,7 @@ export const resolveToolRenderer = {
|
|
|
241
241
|
const isApply = action === "apply" && !result.isError;
|
|
242
242
|
const isFailedApply = action === "apply" && result.isError;
|
|
243
243
|
const bgColor = result.isError ? "error" : isApply ? "success" : "warning";
|
|
244
|
-
const icon = isApply ? uiTheme.
|
|
244
|
+
const icon = isApply ? uiTheme.styledSymbol("tool.resolve", "accent") : uiTheme.status.error;
|
|
245
245
|
const verb = isApply ? "Accept" : isFailedApply ? "Failed" : "Discard";
|
|
246
246
|
const separator = ": ";
|
|
247
247
|
const separatorIndex = label.indexOf(separator);
|
package/src/tools/review.ts
CHANGED
|
@@ -169,7 +169,7 @@ export const reportFindingTool: AgentTool<typeof ReportFindingParams, ReportFind
|
|
|
169
169
|
}`;
|
|
170
170
|
|
|
171
171
|
return new Text(
|
|
172
|
-
`${theme.
|
|
172
|
+
`${theme.styledSymbol("tool.review", "accent")} ${icon} ${theme.fg(color, `[${label}]`)} ${theme.fg(
|
|
173
173
|
"dim",
|
|
174
174
|
location,
|
|
175
175
|
)}`,
|
package/src/tools/ssh.ts
CHANGED
|
@@ -273,7 +273,10 @@ export const sshToolRenderer = {
|
|
|
273
273
|
const details = result.details;
|
|
274
274
|
const host = args?.host || "…";
|
|
275
275
|
const command = args?.command ?? "";
|
|
276
|
-
const header = renderStatusLine(
|
|
276
|
+
const header = renderStatusLine(
|
|
277
|
+
{ iconOverride: uiTheme.styledSymbol("tool.ssh", "accent"), title: "SSH", description: `[${host}]` },
|
|
278
|
+
uiTheme,
|
|
279
|
+
);
|
|
277
280
|
const cmdLines = formatSshCommandLines(command, uiTheme);
|
|
278
281
|
const textContent = result.content?.find(c => c.type === "text")?.text ?? "";
|
|
279
282
|
const outputBlock = new CachedOutputBlock();
|
package/src/tools/todo.ts
CHANGED
|
@@ -881,7 +881,14 @@ export const todoToolRenderer = {
|
|
|
881
881
|
keys.add(task.content);
|
|
882
882
|
}
|
|
883
883
|
const allTasks = phases.flatMap(phase => phase.tasks);
|
|
884
|
-
const header = renderStatusLine(
|
|
884
|
+
const header = renderStatusLine(
|
|
885
|
+
{
|
|
886
|
+
iconOverride: uiTheme.styledSymbol("tool.todo", "accent"),
|
|
887
|
+
title: "Todo",
|
|
888
|
+
meta: [`${allTasks.length} tasks`],
|
|
889
|
+
},
|
|
890
|
+
uiTheme,
|
|
891
|
+
);
|
|
885
892
|
if (allTasks.length === 0) {
|
|
886
893
|
const fallback = result.content?.find(content => content.type === "text")?.text ?? "No todos";
|
|
887
894
|
return new Text(`${header}\n ${uiTheme.fg("dim", fallback)}`, 0, 0);
|
|
@@ -9,7 +9,7 @@ export interface ToolTimeoutConfig {
|
|
|
9
9
|
|
|
10
10
|
export const TOOL_TIMEOUTS = {
|
|
11
11
|
bash: { default: 300, min: 1, max: 3600 },
|
|
12
|
-
eval: { default: 30, min: 1, max:
|
|
12
|
+
eval: { default: 30, min: 1, max: 3600 },
|
|
13
13
|
browser: { default: 30, min: 1, max: 300 },
|
|
14
14
|
ssh: { default: 60, min: 1, max: 3600 },
|
|
15
15
|
fetch: { default: 20, min: 1, max: 45 },
|
package/src/tools/write.ts
CHANGED
|
@@ -1081,7 +1081,7 @@ export const writeToolRenderer = {
|
|
|
1081
1081
|
: "";
|
|
1082
1082
|
const header = renderStatusLine(
|
|
1083
1083
|
{
|
|
1084
|
-
|
|
1084
|
+
iconOverride: uiTheme.styledSymbol("tool.write", "accent"),
|
|
1085
1085
|
title: "Write",
|
|
1086
1086
|
description: `${langIcon} ${pathDisplay}${lineSuffix}${execSuffix}`,
|
|
1087
1087
|
},
|
package/src/tui/code-cell.ts
CHANGED