@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
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type Component,
|
|
3
|
+
getImageDimensions,
|
|
4
|
+
Image,
|
|
5
|
+
ImageProtocol,
|
|
6
|
+
imageFallback,
|
|
7
|
+
Spacer,
|
|
8
|
+
TERMINAL,
|
|
9
|
+
} from "@nghyane/arcane-tui";
|
|
10
|
+
import { convertToPng } from "../../utils/image-convert";
|
|
11
|
+
|
|
12
|
+
type ImageBlock = { data?: string; mimeType?: string };
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Manages image rendering for tool results.
|
|
16
|
+
* Handles Kitty PNG conversion, spacers, and fallback text.
|
|
17
|
+
*/
|
|
18
|
+
export class ToolImageDisplay {
|
|
19
|
+
#images: Image[] = [];
|
|
20
|
+
#spacers: Spacer[] = [];
|
|
21
|
+
#convertedImages = new Map<number, { data: string; mimeType: string }>();
|
|
22
|
+
#parent: { addChild(c: Component): void; removeChild(c: Component): void };
|
|
23
|
+
#onUpdate: () => void;
|
|
24
|
+
|
|
25
|
+
constructor(parent: { addChild(c: Component): void; removeChild(c: Component): void }, onUpdate: () => void) {
|
|
26
|
+
this.#parent = parent;
|
|
27
|
+
this.#onUpdate = onUpdate;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Trigger async PNG conversion for Kitty protocol.
|
|
32
|
+
* Call when result is first received or updated.
|
|
33
|
+
*/
|
|
34
|
+
convertForKitty(imageBlocks: ImageBlock[]): void {
|
|
35
|
+
if (TERMINAL.imageProtocol !== ImageProtocol.Kitty) return;
|
|
36
|
+
|
|
37
|
+
for (let i = 0; i < imageBlocks.length; i++) {
|
|
38
|
+
const img = imageBlocks[i];
|
|
39
|
+
if (!img.data || !img.mimeType) continue;
|
|
40
|
+
if (img.mimeType === "image/png") continue;
|
|
41
|
+
if (this.#convertedImages.has(i)) continue;
|
|
42
|
+
|
|
43
|
+
const index = i;
|
|
44
|
+
convertToPng(img.data, img.mimeType)
|
|
45
|
+
.then(converted => {
|
|
46
|
+
if (converted) {
|
|
47
|
+
this.#convertedImages.set(index, converted);
|
|
48
|
+
this.#onUpdate();
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
.catch(() => {});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Update displayed images. Removes old components, adds new ones.
|
|
57
|
+
*/
|
|
58
|
+
update(imageBlocks: ImageBlock[], showImages: boolean, themeFg: (s: string) => string): void {
|
|
59
|
+
// Remove old
|
|
60
|
+
for (const img of this.#images) this.#parent.removeChild(img);
|
|
61
|
+
for (const spacer of this.#spacers) this.#parent.removeChild(spacer);
|
|
62
|
+
this.#images = [];
|
|
63
|
+
this.#spacers = [];
|
|
64
|
+
|
|
65
|
+
for (let i = 0; i < imageBlocks.length; i++) {
|
|
66
|
+
const img = imageBlocks[i];
|
|
67
|
+
if (!TERMINAL.imageProtocol || !showImages || !img.data || !img.mimeType) continue;
|
|
68
|
+
|
|
69
|
+
const converted = this.#convertedImages.get(i);
|
|
70
|
+
const imageData = converted?.data ?? img.data;
|
|
71
|
+
const imageMimeType = converted?.mimeType ?? img.mimeType;
|
|
72
|
+
|
|
73
|
+
// Kitty requires PNG — skip unconverted non-PNG
|
|
74
|
+
if (TERMINAL.imageProtocol === ImageProtocol.Kitty && imageMimeType !== "image/png") {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const spacer = new Spacer(1);
|
|
79
|
+
this.#parent.addChild(spacer);
|
|
80
|
+
this.#spacers.push(spacer);
|
|
81
|
+
|
|
82
|
+
const imageComponent = new Image(
|
|
83
|
+
imageData,
|
|
84
|
+
imageMimeType,
|
|
85
|
+
{
|
|
86
|
+
fallbackColor: (s: string) => themeFg(s),
|
|
87
|
+
},
|
|
88
|
+
{ maxWidthCells: 60 },
|
|
89
|
+
);
|
|
90
|
+
this.#images.push(imageComponent);
|
|
91
|
+
this.#parent.addChild(imageComponent);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Get text fallback for images when terminal doesn't support image display.
|
|
97
|
+
*/
|
|
98
|
+
static fallbackText(imageBlocks: ImageBlock[]): string {
|
|
99
|
+
return imageBlocks
|
|
100
|
+
.filter((img): img is ImageBlock & { mimeType: string } => !!img.mimeType)
|
|
101
|
+
.map(img => {
|
|
102
|
+
const dims = img.data ? (getImageDimensions(img.data, img.mimeType) ?? undefined) : undefined;
|
|
103
|
+
return imageFallback(img.mimeType, dims);
|
|
104
|
+
})
|
|
105
|
+
.join("\n");
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -8,9 +8,9 @@ import {
|
|
|
8
8
|
TruncatedText,
|
|
9
9
|
truncateToWidth,
|
|
10
10
|
} from "@nghyane/arcane-tui";
|
|
11
|
-
import { theme } from "../../modes/theme/theme";
|
|
12
11
|
import type { SessionTreeNode } from "../../session/session-manager";
|
|
13
|
-
import {
|
|
12
|
+
import { theme } from "../../theme/theme";
|
|
13
|
+
import { shortenPath } from "../../ui/render-utils";
|
|
14
14
|
import { DynamicBorder } from "./dynamic-border";
|
|
15
15
|
|
|
16
16
|
/** Gutter info: position (displayIndent where connector was) and whether to show │ */
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Container, LeftBorderBox, Spacer, Text } from "@nghyane/arcane-tui";
|
|
2
2
|
import type { Rule } from "../../capability/rule";
|
|
3
|
-
import { theme } from "../../
|
|
3
|
+
import { theme } from "../../theme/theme";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Component that renders a TTSR (Time Traveling Stream Rules) notification.
|
|
7
7
|
* Shows when a rule violation is detected and the stream is being rewound.
|
|
8
8
|
*/
|
|
9
9
|
export class TtsrNotificationComponent extends Container {
|
|
10
|
-
#box:
|
|
10
|
+
#box: LeftBorderBox;
|
|
11
11
|
#expanded = false;
|
|
12
12
|
|
|
13
13
|
constructor(private readonly rules: Rule[]) {
|
|
@@ -15,8 +15,7 @@ export class TtsrNotificationComponent extends Container {
|
|
|
15
15
|
|
|
16
16
|
this.addChild(new Spacer(1));
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
this.#box = new Box(1, 1, t => theme.inverse(theme.fg("warning", t)));
|
|
18
|
+
this.#box = new LeftBorderBox(1, 1, s => theme.fg("warning", s));
|
|
20
19
|
this.addChild(this.#box);
|
|
21
20
|
|
|
22
21
|
this.#rebuild();
|
|
@@ -61,20 +60,8 @@ export class TtsrNotificationComponent extends Container {
|
|
|
61
60
|
}
|
|
62
61
|
}
|
|
63
62
|
|
|
64
|
-
// Use italic for subtle distinction (fg colors conflict with inverse)
|
|
65
63
|
this.#box.addChild(new Text(theme.italic(displayText), 0, 0));
|
|
66
64
|
}
|
|
67
65
|
}
|
|
68
|
-
|
|
69
|
-
// Show expand hint if collapsed and there's more content
|
|
70
|
-
if (!this.#expanded) {
|
|
71
|
-
const hasMoreContent = this.rules.some(r => {
|
|
72
|
-
const desc = r.description || r.content;
|
|
73
|
-
return desc && desc.split("\n").length > 2;
|
|
74
|
-
});
|
|
75
|
-
if (hasMoreContent) {
|
|
76
|
-
this.#box.addChild(new Text(theme.italic(" (ctrl+o to expand)"), 0, 0));
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
66
|
}
|
|
80
67
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Component, Container, matchesKey, Spacer, Text, truncateToWidth } from "@nghyane/arcane-tui";
|
|
2
|
-
import { theme } from "../../
|
|
2
|
+
import { theme } from "../../theme/theme";
|
|
3
3
|
import { DynamicBorder } from "./dynamic-border";
|
|
4
4
|
|
|
5
5
|
interface UserMessageItem {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Container, Markdown, Spacer } from "@nghyane/arcane-tui";
|
|
2
|
-
import { getMarkdownTheme, theme } from "../../
|
|
1
|
+
import { Container, LeftBorderBox, Markdown, Spacer } from "@nghyane/arcane-tui";
|
|
2
|
+
import { getMarkdownTheme, theme } from "../../theme/theme";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Component that renders a user message
|
|
@@ -7,18 +7,17 @@ import { getMarkdownTheme, theme } from "../../modes/theme/theme";
|
|
|
7
7
|
export class UserMessageComponent extends Container {
|
|
8
8
|
constructor(text: string, synthetic = false) {
|
|
9
9
|
super();
|
|
10
|
-
const bgColor = (value: string) => theme.bg("userMessageBg", value);
|
|
11
|
-
const leftBorder = theme.fg("accent", "▎");
|
|
12
10
|
const color = synthetic
|
|
13
11
|
? (value: string) => theme.fg("dim", value)
|
|
14
12
|
: (value: string) => theme.fg("userMessageText", value);
|
|
15
13
|
this.addChild(new Spacer(1));
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}),
|
|
14
|
+
const borderBox = new LeftBorderBox(
|
|
15
|
+
2,
|
|
16
|
+
1,
|
|
17
|
+
s => theme.fg("accent", s),
|
|
18
|
+
t => theme.bg("userMessageBg", t),
|
|
22
19
|
);
|
|
20
|
+
borderBox.addChild(new Markdown(text, 0, 0, getMarkdownTheme(), { color }));
|
|
21
|
+
this.addChild(borderBox);
|
|
23
22
|
}
|
|
24
23
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Component, padding, truncateToWidth, visibleWidth } from "@nghyane/arcane-tui";
|
|
2
2
|
import { APP_NAME } from "@nghyane/arcane-utils/dirs";
|
|
3
|
-
import { theme } from "../../
|
|
3
|
+
import { theme } from "../../theme/theme";
|
|
4
4
|
|
|
5
5
|
export interface RecentSession {
|
|
6
6
|
name: string;
|
|
@@ -22,10 +22,10 @@ import { BashExecutionComponent } from "../../modes/components/bash-execution";
|
|
|
22
22
|
import { BorderedLoader } from "../../modes/components/bordered-loader";
|
|
23
23
|
import { DynamicBorder } from "../../modes/components/dynamic-border";
|
|
24
24
|
import { PythonExecutionComponent } from "../../modes/components/python-execution";
|
|
25
|
-
import { getMarkdownTheme, getSymbolTheme, theme } from "../../modes/theme/theme";
|
|
26
25
|
import type { InteractiveModeContext } from "../../modes/types";
|
|
27
26
|
import type { AuthStorage } from "../../session/auth-storage";
|
|
28
27
|
import { createCompactionSummaryMessage } from "../../session/messages";
|
|
28
|
+
import { getMarkdownTheme, getSymbolTheme, theme } from "../../theme/theme";
|
|
29
29
|
import { outputMeta } from "../../tools/output-meta";
|
|
30
30
|
import { resolveToCwd } from "../../tools/path-utils";
|
|
31
31
|
import { getChangelogPath, parseChangelog } from "../../utils/changelog";
|
|
@@ -1,80 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Loader, TERMINAL
|
|
1
|
+
import { type AgentTool, toolDetails } from "@nghyane/arcane-agent";
|
|
2
|
+
import { Loader, TERMINAL } from "@nghyane/arcane-tui";
|
|
3
3
|
import { settings } from "../../config/settings";
|
|
4
4
|
import { AssistantMessageComponent } from "../../modes/components/assistant-message";
|
|
5
|
-
import {
|
|
6
|
-
import { ReadToolGroupComponent } from "../../modes/components/read-tool-group";
|
|
5
|
+
import { ContextGroupComponent } from "../../modes/components/context-group";
|
|
7
6
|
import { TodoReminderComponent } from "../../modes/components/todo-reminder";
|
|
8
7
|
import { ToolExecutionComponent } from "../../modes/components/tool-execution";
|
|
9
8
|
import { TtsrNotificationComponent } from "../../modes/components/ttsr-notification";
|
|
10
|
-
import {
|
|
11
|
-
import type { InteractiveModeContext, TodoItem } from "../../modes/types";
|
|
9
|
+
import type { InteractiveModeContext } from "../../modes/types";
|
|
12
10
|
import type { AgentSessionEvent } from "../../session/agent-session";
|
|
11
|
+
import { getSymbolTheme, theme } from "../../theme/theme";
|
|
12
|
+
import { getToolTier, isContextTool } from "../../ui/render-utils";
|
|
13
13
|
|
|
14
14
|
export class EventController {
|
|
15
|
-
#lastReadGroup: ReadToolGroupComponent | undefined = undefined;
|
|
16
|
-
#codemodeGroups = new Map<string, CodeModeGroupComponent>();
|
|
17
15
|
#lastThinkingCount = 0;
|
|
18
16
|
#renderedCustomMessages = new Set<string>();
|
|
19
|
-
#
|
|
17
|
+
#currentContextGroup?: ContextGroupComponent;
|
|
18
|
+
#toolGroups = new Map<string, ContextGroupComponent>();
|
|
20
19
|
|
|
21
20
|
constructor(private ctx: InteractiveModeContext) {}
|
|
22
21
|
|
|
23
|
-
#resetReadGroup(): void {
|
|
24
|
-
this.#lastReadGroup = undefined;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
#getReadGroup(): ReadToolGroupComponent {
|
|
28
|
-
if (!this.#lastReadGroup) {
|
|
29
|
-
this.ctx.chatContainer.addChild(new Text("", 0, 0));
|
|
30
|
-
const group = new ReadToolGroupComponent();
|
|
31
|
-
group.setExpanded(this.ctx.toolOutputExpanded);
|
|
32
|
-
this.ctx.chatContainer.addChild(group);
|
|
33
|
-
this.#lastReadGroup = group;
|
|
34
|
-
}
|
|
35
|
-
return this.#lastReadGroup;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
#updateWorkingMessageFromIntent(intent: string | undefined): void {
|
|
39
|
-
const trimmed = intent?.trim();
|
|
40
|
-
if (!trimmed || trimmed === this.#lastIntent) return;
|
|
41
|
-
this.#lastIntent = trimmed;
|
|
42
|
-
this.ctx.setWorkingMessage(`${trimmed} (esc to interrupt)`);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
#ensureCodemodeGroup(id: string): CodeModeGroupComponent {
|
|
46
|
-
let group = this.#codemodeGroups.get(id);
|
|
47
|
-
if (!group) {
|
|
48
|
-
this.#resetReadGroup();
|
|
49
|
-
group = new CodeModeGroupComponent(this.ctx.ui);
|
|
50
|
-
group.setExpanded(this.ctx.toolOutputExpanded);
|
|
51
|
-
this.ctx.chatContainer.addChild(group);
|
|
52
|
-
this.#codemodeGroups.set(id, group);
|
|
53
|
-
this.ctx.pendingTools.set(id, group);
|
|
54
|
-
this.#hideLoader();
|
|
55
|
-
}
|
|
56
|
-
return group;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
#hideLoader(): void {
|
|
60
|
-
if (!this.ctx.loadingAnimation) return;
|
|
61
|
-
this.ctx.loadingAnimation.stop();
|
|
62
|
-
this.ctx.statusContainer.clear();
|
|
63
|
-
this.ctx.loadingAnimation = undefined;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
#restoreLoader(): void {
|
|
67
|
-
if (this.ctx.loadingAnimation || this.#codemodeGroups.size > 0) return;
|
|
68
|
-
this.ctx.loadingAnimation = new Loader(
|
|
69
|
-
this.ctx.ui,
|
|
70
|
-
spinner => theme.fg("accent", spinner),
|
|
71
|
-
text => theme.fg("muted", text),
|
|
72
|
-
`Working\u2026 (esc to interrupt)`,
|
|
73
|
-
getSymbolTheme().spinnerFrames,
|
|
74
|
-
);
|
|
75
|
-
this.ctx.statusContainer.addChild(this.ctx.loadingAnimation);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
22
|
subscribeToAgent(): void {
|
|
79
23
|
this.ctx.unsubscribe = this.ctx.session.subscribe(async (event: AgentSessionEvent) => {
|
|
80
24
|
await this.handleEvent(event);
|
|
@@ -91,7 +35,6 @@ export class EventController {
|
|
|
91
35
|
|
|
92
36
|
switch (event.type) {
|
|
93
37
|
case "agent_start":
|
|
94
|
-
this.#lastIntent = undefined;
|
|
95
38
|
if (this.ctx.retryEscapeHandler) {
|
|
96
39
|
this.ctx.editor.onEscape = this.ctx.retryEscapeHandler;
|
|
97
40
|
this.ctx.retryEscapeHandler = undefined;
|
|
@@ -124,11 +67,11 @@ export class EventController {
|
|
|
124
67
|
break;
|
|
125
68
|
}
|
|
126
69
|
this.#renderedCustomMessages.add(signature);
|
|
127
|
-
this.#
|
|
70
|
+
this.#finalizeContextGroup();
|
|
128
71
|
this.ctx.addMessageToChat(event.message);
|
|
129
72
|
this.ctx.ui.requestRender();
|
|
130
73
|
} else if (event.message.role === "user") {
|
|
131
|
-
this.#
|
|
74
|
+
this.#finalizeContextGroup();
|
|
132
75
|
this.ctx.addMessageToChat(event.message);
|
|
133
76
|
if (!event.message.synthetic) {
|
|
134
77
|
this.ctx.editor.setText("");
|
|
@@ -136,12 +79,12 @@ export class EventController {
|
|
|
136
79
|
}
|
|
137
80
|
this.ctx.ui.requestRender();
|
|
138
81
|
} else if (event.message.role === "fileMention") {
|
|
139
|
-
this.#
|
|
82
|
+
this.#finalizeContextGroup();
|
|
140
83
|
this.ctx.addMessageToChat(event.message);
|
|
141
84
|
this.ctx.ui.requestRender();
|
|
142
85
|
} else if (event.message.role === "assistant") {
|
|
143
86
|
this.#lastThinkingCount = 0;
|
|
144
|
-
this.#
|
|
87
|
+
this.#finalizeContextGroup();
|
|
145
88
|
this.ctx.streamingComponent = new AssistantMessageComponent(undefined, this.ctx.hideThinkingBlock);
|
|
146
89
|
this.ctx.streamingMessage = event.message;
|
|
147
90
|
this.ctx.chatContainer.addChild(this.ctx.streamingComponent);
|
|
@@ -159,49 +102,15 @@ export class EventController {
|
|
|
159
102
|
content => content.type === "thinking" && content.thinking.trim(),
|
|
160
103
|
).length;
|
|
161
104
|
if (thinkingCount > this.#lastThinkingCount) {
|
|
162
|
-
this.#resetReadGroup();
|
|
163
105
|
this.#lastThinkingCount = thinkingCount;
|
|
164
106
|
}
|
|
165
107
|
|
|
166
108
|
for (const content of this.ctx.streamingMessage.content) {
|
|
167
109
|
if (content.type !== "toolCall") continue;
|
|
168
|
-
// Code Mode: create group component early during streaming for intent display
|
|
169
|
-
if (content.name === "code") {
|
|
170
|
-
const group = this.#ensureCodemodeGroup(content.id);
|
|
171
|
-
const args = content.arguments;
|
|
172
|
-
if (args && typeof args === "object" && INTENT_FIELD in args) {
|
|
173
|
-
const intent = (args[INTENT_FIELD] as string | undefined)?.trim();
|
|
174
|
-
if (intent) group.setIntent(intent);
|
|
175
|
-
}
|
|
176
|
-
continue;
|
|
177
|
-
}
|
|
178
110
|
|
|
179
111
|
if (!this.ctx.pendingTools.has(content.id)) {
|
|
180
|
-
if (content.name === "read") {
|
|
181
|
-
const group = this.#getReadGroup();
|
|
182
|
-
group.updateArgs(content.arguments, content.id);
|
|
183
|
-
this.ctx.pendingTools.set(content.id, group);
|
|
184
|
-
continue;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
this.#resetReadGroup();
|
|
188
|
-
this.ctx.chatContainer.addChild(new Text("", 0, 0));
|
|
189
112
|
const tool = this.ctx.session.getToolByName(content.name);
|
|
190
|
-
|
|
191
|
-
content.name,
|
|
192
|
-
content.arguments,
|
|
193
|
-
{
|
|
194
|
-
showImages: settings.get("terminal.showImages"),
|
|
195
|
-
editFuzzyThreshold: settings.get("edit.fuzzyThreshold"),
|
|
196
|
-
editAllowFuzzy: settings.get("edit.fuzzyMatch"),
|
|
197
|
-
},
|
|
198
|
-
tool,
|
|
199
|
-
this.ctx.ui,
|
|
200
|
-
this.ctx.sessionManager.getCwd(),
|
|
201
|
-
);
|
|
202
|
-
component.setExpanded(this.ctx.toolOutputExpanded);
|
|
203
|
-
this.ctx.chatContainer.addChild(component);
|
|
204
|
-
this.ctx.pendingTools.set(content.id, component);
|
|
113
|
+
this.#appendTool(content.id, content.name, content.arguments, tool);
|
|
205
114
|
} else {
|
|
206
115
|
const component = this.ctx.pendingTools.get(content.id);
|
|
207
116
|
if (component) {
|
|
@@ -210,15 +119,6 @@ export class EventController {
|
|
|
210
119
|
}
|
|
211
120
|
}
|
|
212
121
|
|
|
213
|
-
// Update working message with intent — skip for code tools that already have a visible group
|
|
214
|
-
for (const content of this.ctx.streamingMessage.content) {
|
|
215
|
-
if (content.type !== "toolCall") continue;
|
|
216
|
-
if (this.#codemodeGroups.has(content.id)) continue;
|
|
217
|
-
const args = content.arguments;
|
|
218
|
-
if (!args || typeof args !== "object" || !(INTENT_FIELD in args)) continue;
|
|
219
|
-
this.#updateWorkingMessageFromIntent(args[INTENT_FIELD] as string | undefined);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
122
|
this.ctx.ui.requestRender();
|
|
223
123
|
}
|
|
224
124
|
break;
|
|
@@ -260,68 +160,11 @@ export class EventController {
|
|
|
260
160
|
break;
|
|
261
161
|
|
|
262
162
|
case "tool_execution_start": {
|
|
263
|
-
if (
|
|
264
|
-
if (event.toolName === "code") {
|
|
265
|
-
const group = this.#ensureCodemodeGroup(event.toolCallId);
|
|
266
|
-
const intent = (event.intent ?? (event.args as Record<string, unknown>)?.agent__intent) as
|
|
267
|
-
| string
|
|
268
|
-
| undefined;
|
|
269
|
-
if (typeof intent === "string" && intent.trim()) {
|
|
270
|
-
group.setIntent(intent.trim());
|
|
271
|
-
}
|
|
272
|
-
this.ctx.ui.requestRender();
|
|
273
|
-
break;
|
|
274
|
-
}
|
|
275
|
-
// Route sub-tools into their parent codemode group
|
|
276
|
-
if (event.parentToolCallId) {
|
|
277
|
-
const parentGroup = this.#codemodeGroups.get(event.parentToolCallId);
|
|
278
|
-
if (parentGroup) {
|
|
279
|
-
const tool = event.tool ?? this.ctx.session.getToolByName(event.toolName);
|
|
280
|
-
const handle = parentGroup.addSubTool(
|
|
281
|
-
event.toolCallId,
|
|
282
|
-
event.toolName,
|
|
283
|
-
event.args,
|
|
284
|
-
tool,
|
|
285
|
-
{
|
|
286
|
-
showImages: settings.get("terminal.showImages"),
|
|
287
|
-
editFuzzyThreshold: settings.get("edit.fuzzyThreshold"),
|
|
288
|
-
editAllowFuzzy: settings.get("edit.fuzzyMatch"),
|
|
289
|
-
},
|
|
290
|
-
this.ctx.ui,
|
|
291
|
-
this.ctx.sessionManager.getCwd(),
|
|
292
|
-
);
|
|
293
|
-
this.ctx.pendingTools.set(event.toolCallId, handle);
|
|
294
|
-
this.ctx.ui.requestRender();
|
|
295
|
-
break;
|
|
296
|
-
}
|
|
297
|
-
}
|
|
163
|
+
if (event.intent) this.ctx.setWorkingMessage(`${event.intent} (esc to interrupt)`);
|
|
298
164
|
|
|
299
165
|
if (!this.ctx.pendingTools.has(event.toolCallId)) {
|
|
300
|
-
if (event.toolName === "read") {
|
|
301
|
-
const group = this.#getReadGroup();
|
|
302
|
-
group.updateArgs(event.args, event.toolCallId);
|
|
303
|
-
this.ctx.pendingTools.set(event.toolCallId, group);
|
|
304
|
-
this.ctx.ui.requestRender();
|
|
305
|
-
break;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
this.#resetReadGroup();
|
|
309
166
|
const tool = event.tool ?? this.ctx.session.getToolByName(event.toolName);
|
|
310
|
-
|
|
311
|
-
event.toolName,
|
|
312
|
-
event.args,
|
|
313
|
-
{
|
|
314
|
-
showImages: settings.get("terminal.showImages"),
|
|
315
|
-
editFuzzyThreshold: settings.get("edit.fuzzyThreshold"),
|
|
316
|
-
editAllowFuzzy: settings.get("edit.fuzzyMatch"),
|
|
317
|
-
},
|
|
318
|
-
tool,
|
|
319
|
-
this.ctx.ui,
|
|
320
|
-
this.ctx.sessionManager.getCwd(),
|
|
321
|
-
);
|
|
322
|
-
component.setExpanded(this.ctx.toolOutputExpanded);
|
|
323
|
-
this.ctx.chatContainer.addChild(component);
|
|
324
|
-
this.ctx.pendingTools.set(event.toolCallId, component);
|
|
167
|
+
this.#appendTool(event.toolCallId, event.toolName, event.args, tool);
|
|
325
168
|
this.ctx.ui.requestRender();
|
|
326
169
|
}
|
|
327
170
|
break;
|
|
@@ -341,30 +184,23 @@ export class EventController {
|
|
|
341
184
|
if (component) {
|
|
342
185
|
component.updateResult({ ...event.result, isError: event.isError }, false, event.toolCallId);
|
|
343
186
|
this.ctx.pendingTools.delete(event.toolCallId);
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
// Code Mode: finalize the group when the "code" tool ends
|
|
347
|
-
if (event.toolName === "code") {
|
|
348
|
-
const group = this.#codemodeGroups.get(event.toolCallId);
|
|
187
|
+
// Mark context group completion
|
|
188
|
+
const group = this.#toolGroups.get(event.toolCallId);
|
|
349
189
|
if (group) {
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
group.setLogs(details.logs);
|
|
353
|
-
}
|
|
354
|
-
group.setDone();
|
|
355
|
-
this.#codemodeGroups.delete(event.toolCallId);
|
|
190
|
+
group.markDone();
|
|
191
|
+
this.#toolGroups.delete(event.toolCallId);
|
|
356
192
|
}
|
|
357
|
-
this
|
|
193
|
+
this.ctx.ui.requestRender();
|
|
358
194
|
}
|
|
359
195
|
// Update todo display when todo_write tool completes
|
|
360
196
|
if (event.toolName === "todo_write" && !event.isError) {
|
|
361
|
-
const details = event.result.details
|
|
197
|
+
const details = toolDetails("todo_write", (event.result.details ?? {}) as Record<string, unknown>);
|
|
362
198
|
if (details?.todos) {
|
|
363
199
|
this.ctx.setTodos(details.todos);
|
|
364
200
|
}
|
|
365
201
|
} else if (event.toolName === "todo_write" && event.isError) {
|
|
366
202
|
const textContent = event.result.content.find(
|
|
367
|
-
(content: { type:
|
|
203
|
+
(content): content is { type: "text"; text: string } => content.type === "text",
|
|
368
204
|
)?.text;
|
|
369
205
|
this.ctx.showWarning(
|
|
370
206
|
`Todo update failed${textContent ? `: ${textContent}` : ". Progress may be stale until todo_write succeeds."}`,
|
|
@@ -374,6 +210,7 @@ export class EventController {
|
|
|
374
210
|
}
|
|
375
211
|
|
|
376
212
|
case "agent_end":
|
|
213
|
+
this.#finalizeContextGroup();
|
|
377
214
|
if (this.ctx.loadingAnimation) {
|
|
378
215
|
this.ctx.loadingAnimation.stop();
|
|
379
216
|
this.ctx.loadingAnimation = undefined;
|
|
@@ -385,7 +222,7 @@ export class EventController {
|
|
|
385
222
|
this.ctx.streamingMessage = undefined;
|
|
386
223
|
}
|
|
387
224
|
this.ctx.pendingTools.clear();
|
|
388
|
-
this.#
|
|
225
|
+
this.#toolGroups.clear();
|
|
389
226
|
this.ctx.ui.requestRender();
|
|
390
227
|
this.sendCompletionNotification();
|
|
391
228
|
break;
|
|
@@ -480,6 +317,7 @@ export class EventController {
|
|
|
480
317
|
}
|
|
481
318
|
|
|
482
319
|
case "ttsr_triggered": {
|
|
320
|
+
this.#finalizeContextGroup();
|
|
483
321
|
const component = new TtsrNotificationComponent(event.rules);
|
|
484
322
|
component.setExpanded(this.ctx.toolOutputExpanded);
|
|
485
323
|
this.ctx.chatContainer.addChild(component);
|
|
@@ -488,6 +326,7 @@ export class EventController {
|
|
|
488
326
|
}
|
|
489
327
|
|
|
490
328
|
case "todo_reminder": {
|
|
329
|
+
this.#finalizeContextGroup();
|
|
491
330
|
const component = new TodoReminderComponent(event.todos, event.attempt, event.maxAttempts);
|
|
492
331
|
this.ctx.chatContainer.addChild(component);
|
|
493
332
|
this.ctx.ui.requestRender();
|
|
@@ -496,6 +335,38 @@ export class EventController {
|
|
|
496
335
|
}
|
|
497
336
|
}
|
|
498
337
|
|
|
338
|
+
#appendTool(toolCallId: string, toolName: string, args: unknown, tool: AgentTool | undefined): void {
|
|
339
|
+
const tier = getToolTier(toolName);
|
|
340
|
+
const component = new ToolExecutionComponent(
|
|
341
|
+
toolName,
|
|
342
|
+
args,
|
|
343
|
+
{ showImages: settings.get("terminal.showImages"), tier },
|
|
344
|
+
tool,
|
|
345
|
+
this.ctx.ui,
|
|
346
|
+
this.ctx.sessionManager.getCwd(),
|
|
347
|
+
);
|
|
348
|
+
component.setExpanded(this.ctx.toolOutputExpanded);
|
|
349
|
+
|
|
350
|
+
if (isContextTool(toolName)) {
|
|
351
|
+
if (!this.#currentContextGroup) {
|
|
352
|
+
this.#currentContextGroup = new ContextGroupComponent();
|
|
353
|
+
this.#currentContextGroup.setExpanded(this.ctx.toolOutputExpanded);
|
|
354
|
+
this.ctx.chatContainer.addChild(this.#currentContextGroup);
|
|
355
|
+
}
|
|
356
|
+
this.#currentContextGroup.addTool(toolName, component);
|
|
357
|
+
this.#toolGroups.set(toolCallId, this.#currentContextGroup);
|
|
358
|
+
} else {
|
|
359
|
+
this.#finalizeContextGroup();
|
|
360
|
+
this.ctx.chatContainer.addChild(component);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
this.ctx.pendingTools.set(toolCallId, component);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
#finalizeContextGroup(): void {
|
|
367
|
+
this.#currentContextGroup = undefined;
|
|
368
|
+
}
|
|
369
|
+
|
|
499
370
|
sendCompletionNotification(): void {
|
|
500
371
|
if (this.ctx.isBackgrounded === false) return;
|
|
501
372
|
const notify = settings.get("completion.notify");
|
|
@@ -14,8 +14,8 @@ import type {
|
|
|
14
14
|
import { HookEditorComponent } from "../../modes/components/hook-editor";
|
|
15
15
|
import { HookInputComponent } from "../../modes/components/hook-input";
|
|
16
16
|
import { HookSelectorComponent } from "../../modes/components/hook-selector";
|
|
17
|
-
import { getAvailableThemesWithPaths, getThemeByName, setTheme, type Theme, theme } from "../../modes/theme/theme";
|
|
18
17
|
import type { InteractiveModeContext } from "../../modes/types";
|
|
18
|
+
import { getAvailableThemesWithPaths, getThemeByName, setTheme, type Theme, theme } from "../../theme/theme";
|
|
19
19
|
import { setTerminalTitle } from "../../utils/title-generator";
|
|
20
20
|
|
|
21
21
|
export class ExtensionUiController {
|
|
@@ -3,11 +3,11 @@ import type { AgentMessage } from "@nghyane/arcane-agent";
|
|
|
3
3
|
import { copyToClipboard, readImageFromClipboard, sanitizeText } from "@nghyane/arcane-natives";
|
|
4
4
|
import { $env } from "@nghyane/arcane-utils";
|
|
5
5
|
import { settings } from "../../config/settings";
|
|
6
|
-
import { theme } from "../../modes/theme/theme";
|
|
7
6
|
import type { InteractiveModeContext } from "../../modes/types";
|
|
8
7
|
import type { AgentSessionEvent } from "../../session/agent-session";
|
|
9
8
|
import { SKILL_PROMPT_MESSAGE_TYPE, type SkillPromptDetails } from "../../session/messages";
|
|
10
9
|
import { executeBuiltinSlashCommand } from "../../slash-commands/builtin-registry";
|
|
10
|
+
import { theme } from "../../theme/theme";
|
|
11
11
|
import { getEditorCommand, openInEditor } from "../../utils/external-editor";
|
|
12
12
|
import { resizeImage } from "../../utils/image-resize";
|
|
13
13
|
import { generateSessionTitle, setTerminalTitle } from "../../utils/title-generator";
|
|
@@ -52,6 +52,8 @@ export class InputController {
|
|
|
52
52
|
this.ctx.editor.setText("");
|
|
53
53
|
this.ctx.isPythonMode = false;
|
|
54
54
|
this.ctx.updateEditorBorderColor();
|
|
55
|
+
} else if (this.ctx.session.isStreaming) {
|
|
56
|
+
this.ctx.agent.abort();
|
|
55
57
|
} else if (!this.ctx.editor.getText().trim()) {
|
|
56
58
|
// Double-escape with empty editor triggers /tree, /branch, or nothing based on setting
|
|
57
59
|
const action = settings.get("doubleEscapeAction");
|
|
@@ -19,10 +19,10 @@ import {
|
|
|
19
19
|
import { MCPOAuthFlow } from "../../mcp/oauth-flow";
|
|
20
20
|
import type { MCPServerConfig, MCPServerConnection } from "../../mcp/types";
|
|
21
21
|
import type { OAuthCredential } from "../../session/auth-storage";
|
|
22
|
+
import { theme } from "../../theme/theme";
|
|
22
23
|
import { openPath } from "../../utils/open";
|
|
23
24
|
import { DynamicBorder } from "../components/dynamic-border";
|
|
24
25
|
import { MCPAddWizard } from "../components/mcp-add-wizard";
|
|
25
|
-
import { theme } from "../theme/theme";
|
|
26
26
|
import type { InteractiveModeContext } from "../types";
|
|
27
27
|
|
|
28
28
|
function withTimeout<T>(promise: Promise<T>, timeoutMs: number, message: string): Promise<T> {
|