@nghyane/arcane 0.1.13 → 0.1.14
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 +48 -113
- package/src/modes/components/bordered-loader.ts +1 -1
- package/src/modes/components/branch-summary-message.ts +13 -10
- package/src/modes/components/compaction-summary-message.ts +14 -13
- 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 +49 -92
- 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/frontmatter.md +1 -1
- package/src/prompts/agents/init.md +2 -2
- package/src/prompts/agents/librarian.md +30 -21
- package/src/prompts/agents/oracle.md +9 -2
- package/src/prompts/agents/reviewer.md +15 -49
- package/src/prompts/agents/task.md +17 -9
- package/src/prompts/compaction/branch-summary-context.md +1 -1
- package/src/prompts/compaction/branch-summary-preamble.md +1 -1
- package/src/prompts/compaction/branch-summary.md +4 -1
- package/src/prompts/compaction/compaction-short-summary.md +1 -1
- package/src/prompts/compaction/compaction-summary-context.md +1 -1
- package/src/prompts/compaction/compaction-summary.md +4 -1
- package/src/prompts/compaction/compaction-turn-prefix.md +1 -1
- package/src/prompts/compaction/compaction-update-summary.md +1 -1
- package/src/prompts/memories/consolidation.md +1 -1
- package/src/prompts/memories/read_path.md +1 -1
- package/src/prompts/memories/stage_one_input.md +1 -1
- package/src/prompts/memories/stage_one_system.md +1 -1
- package/src/prompts/review-request.md +1 -1
- package/src/prompts/system/agent-creation-architect.md +1 -1
- package/src/prompts/system/agent-creation-user.md +1 -1
- package/src/prompts/system/custom-system-prompt.md +1 -1
- package/src/prompts/system/file-operations.md +1 -1
- package/src/prompts/system/subagent-system-prompt.md +2 -2
- package/src/prompts/system/summarization-system.md +1 -1
- package/src/prompts/system/system-prompt.md +163 -178
- package/src/prompts/system/title-system.md +1 -1
- package/src/prompts/system/ttsr-interrupt.md +1 -1
- package/src/prompts/system/verification-reminder.md +6 -0
- package/src/prompts/system/web-search.md +1 -1
- package/src/sdk.ts +0 -9
- package/src/session/agent-session.ts +244 -1459
- package/src/session/model-controller.ts +406 -0
- package/src/session/retry-utils.ts +71 -0
- package/src/session/session-manager.ts +22 -186
- package/src/session/session-types.ts +312 -0
- package/src/session/stats.ts +387 -0
- package/src/session/streaming-edit.ts +258 -0
- package/src/session/ttsr.ts +213 -0
- package/src/slash-commands/builtin-registry.ts +0 -8
- package/src/stt/recorder.ts +2 -2
- package/src/system-prompt.ts +1 -14
- package/src/task/agents.ts +7 -33
- package/src/task/executor.ts +50 -438
- package/src/task/index.ts +104 -71
- package/src/task/progress-tracker.ts +390 -0
- package/src/task/render.ts +371 -187
- package/src/task/subprocess-tool-registry.ts +1 -1
- package/src/task/types.ts +14 -47
- package/src/tools/ask.ts +31 -42
- package/src/tools/bash-interactive.ts +2 -2
- package/src/tools/bash-interceptor.ts +2 -2
- package/src/tools/bash-normalize.ts +1 -1
- package/src/tools/bash-skill-urls.ts +2 -2
- package/src/tools/bash.ts +87 -136
- package/src/tools/browser.ts +54 -84
- package/src/tools/create-tools.ts +186 -0
- package/src/tools/default-renderer.ts +104 -0
- package/src/tools/explore.ts +11 -10
- package/src/tools/fetch.ts +24 -114
- package/src/tools/find.ts +48 -132
- package/src/tools/gemini-image.ts +5 -15
- package/src/tools/github.ts +450 -0
- package/src/tools/grep.ts +43 -179
- package/src/tools/index.ts +35 -198
- package/src/tools/json-tree.ts +3 -3
- package/src/tools/librarian.ts +18 -18
- package/src/tools/list-limit.ts +2 -2
- package/src/tools/notebook.ts +35 -87
- package/src/tools/oracle.ts +25 -25
- package/src/tools/output-meta.ts +89 -4
- package/src/tools/output-utils.ts +2 -2
- package/src/tools/python.ts +86 -637
- package/src/tools/read.ts +36 -119
- package/src/tools/reviewer-tool.ts +19 -21
- package/src/tools/search-code.ts +128 -0
- package/src/tools/ssh.ts +67 -126
- package/src/tools/subagent-tool.ts +197 -123
- package/src/tools/todo-write.ts +15 -31
- package/src/tools/tool-errors.ts +0 -30
- package/src/tools/undo-edit.ts +30 -67
- package/src/tools/write.ts +78 -127
- package/src/tui/code-cell.ts +4 -4
- package/src/tui/file-list.ts +2 -2
- package/src/tui/output-block.ts +1 -1
- package/src/tui/status-line.ts +1 -1
- package/src/tui/tree-list.ts +2 -2
- package/src/tui/types.ts +1 -1
- package/src/tui/utils.ts +1 -1
- package/src/{tools → ui}/render-utils.ts +87 -126
- package/src/utils/external-editor.ts +4 -4
- package/src/utils/file-mentions.ts +1 -1
- package/src/utils/index.ts +30 -0
- package/src/utils/tools-manager.ts +9 -19
- package/src/web/github-client.ts +290 -0
- package/src/web/scrapers/github.ts +11 -62
- package/src/web/search/auth.ts +1 -3
- package/src/web/search/index.ts +82 -46
- package/src/web/search/provider.ts +11 -16
- package/src/web/search/providers/grep.ts +160 -0
- package/src/web/search/render.ts +48 -235
- package/src/web/search/types.ts +1 -1
- package/src/commands/commit.ts +0 -36
- package/src/commit/agentic/agent.ts +0 -311
- package/src/commit/agentic/fallback.ts +0 -96
- package/src/commit/agentic/index.ts +0 -359
- package/src/commit/agentic/prompts/analyze-file.md +0 -22
- package/src/commit/agentic/prompts/session-user.md +0 -25
- package/src/commit/agentic/prompts/split-confirm.md +0 -1
- package/src/commit/agentic/prompts/system.md +0 -38
- package/src/commit/agentic/state.ts +0 -69
- package/src/commit/agentic/tools/analyze-file.ts +0 -118
- package/src/commit/agentic/tools/git-file-diff.ts +0 -194
- package/src/commit/agentic/tools/git-hunk.ts +0 -50
- package/src/commit/agentic/tools/git-overview.ts +0 -84
- package/src/commit/agentic/tools/index.ts +0 -56
- package/src/commit/agentic/tools/propose-changelog.ts +0 -128
- package/src/commit/agentic/tools/propose-commit.ts +0 -154
- package/src/commit/agentic/tools/recent-commits.ts +0 -81
- package/src/commit/agentic/tools/split-commit.ts +0 -280
- package/src/commit/agentic/topo-sort.ts +0 -44
- package/src/commit/agentic/trivial.ts +0 -51
- package/src/commit/agentic/validation.ts +0 -200
- package/src/commit/analysis/conventional.ts +0 -165
- package/src/commit/analysis/index.ts +0 -4
- package/src/commit/analysis/scope.ts +0 -242
- package/src/commit/analysis/summary.ts +0 -112
- package/src/commit/analysis/validation.ts +0 -66
- package/src/commit/changelog/detect.ts +0 -37
- package/src/commit/changelog/generate.ts +0 -110
- package/src/commit/changelog/index.ts +0 -234
- package/src/commit/changelog/parse.ts +0 -44
- package/src/commit/cli.ts +0 -93
- package/src/commit/git/diff.ts +0 -148
- package/src/commit/git/errors.ts +0 -9
- package/src/commit/git/index.ts +0 -211
- package/src/commit/git/operations.ts +0 -54
- package/src/commit/index.ts +0 -5
- package/src/commit/map-reduce/index.ts +0 -64
- package/src/commit/map-reduce/map-phase.ts +0 -178
- package/src/commit/map-reduce/reduce-phase.ts +0 -145
- package/src/commit/map-reduce/utils.ts +0 -9
- package/src/commit/message.ts +0 -11
- package/src/commit/model-selection.ts +0 -69
- package/src/commit/pipeline.ts +0 -243
- package/src/commit/prompts/analysis-system.md +0 -148
- package/src/commit/prompts/analysis-user.md +0 -38
- package/src/commit/prompts/changelog-system.md +0 -50
- package/src/commit/prompts/changelog-user.md +0 -18
- package/src/commit/prompts/file-observer-system.md +0 -24
- package/src/commit/prompts/file-observer-user.md +0 -8
- package/src/commit/prompts/reduce-system.md +0 -50
- package/src/commit/prompts/reduce-user.md +0 -17
- package/src/commit/prompts/summary-retry.md +0 -3
- package/src/commit/prompts/summary-system.md +0 -38
- package/src/commit/prompts/summary-user.md +0 -13
- package/src/commit/prompts/types-description.md +0 -2
- package/src/commit/types.ts +0 -109
- package/src/commit/utils/exclusions.ts +0 -42
- package/src/mcp/render.ts +0 -123
- package/src/modes/components/agent-dashboard.ts +0 -1130
- package/src/modes/components/codemode-group.ts +0 -369
- package/src/modes/components/read-tool-group.ts +0 -119
- package/src/modes/components/visual-truncate.ts +0 -63
- package/src/prompts/system/subagent-user-prompt.md +0 -8
- package/src/prompts/tools/ask.md +0 -44
- package/src/prompts/tools/bash.md +0 -24
- package/src/prompts/tools/browser.md +0 -33
- package/src/prompts/tools/calculator.md +0 -12
- package/src/prompts/tools/explore.md +0 -29
- package/src/prompts/tools/fetch.md +0 -16
- package/src/prompts/tools/find.md +0 -18
- package/src/prompts/tools/gemini-image.md +0 -23
- package/src/prompts/tools/grep.md +0 -28
- package/src/prompts/tools/hashline.md +0 -232
- package/src/prompts/tools/librarian.md +0 -24
- package/src/prompts/tools/lsp.md +0 -28
- package/src/prompts/tools/oracle.md +0 -26
- package/src/prompts/tools/patch.md +0 -74
- package/src/prompts/tools/python.md +0 -66
- package/src/prompts/tools/read.md +0 -36
- package/src/prompts/tools/replace.md +0 -38
- package/src/prompts/tools/reviewer.md +0 -41
- package/src/prompts/tools/ssh.md +0 -51
- package/src/prompts/tools/task-summary.md +0 -28
- package/src/prompts/tools/task.md +0 -146
- package/src/prompts/tools/todo-write.md +0 -65
- package/src/prompts/tools/undo-edit.md +0 -7
- package/src/prompts/tools/web-search.md +0 -19
- package/src/prompts/tools/write.md +0 -18
- package/src/task/batch.ts +0 -102
- package/src/task/discovery.ts +0 -126
- package/src/task/parallel.ts +0 -84
- package/src/task/template.ts +0 -32
- package/src/tools/calculator.ts +0 -537
- package/src/tools/jtd-to-typescript.ts +0 -198
- package/src/tools/renderers.ts +0 -60
- package/src/tools/tool-result.ts +0 -86
- /package/src/{modes/theme → theme}/dark.json +0 -0
- /package/src/{modes/theme → theme}/defaults/dark-catppuccin.json +0 -0
- /package/src/{modes/theme → theme}/defaults/dark-dracula.json +0 -0
- /package/src/{modes/theme → theme}/defaults/dark-gruvbox.json +0 -0
- /package/src/{modes/theme → theme}/defaults/dark-solarized.json +0 -0
- /package/src/{modes/theme → theme}/defaults/dark-tokyo-night.json +0 -0
- /package/src/{modes/theme → theme}/defaults/index.ts +0 -0
- /package/src/{modes/theme → theme}/defaults/light-catppuccin.json +0 -0
- /package/src/{modes/theme → theme}/defaults/light-github.json +0 -0
- /package/src/{modes/theme → theme}/defaults/light-solarized.json +0 -0
- /package/src/{modes/theme → theme}/light.json +0 -0
- /package/src/{modes/theme → theme}/mermaid-cache.ts +0 -0
- /package/src/{modes/theme → theme}/theme-schema.json +0 -0
- /package/src/{modes/theme → theme}/theme.ts +0 -0
package/src/main.ts
CHANGED
|
@@ -27,11 +27,11 @@ import { initializeWithSettings } from "./discovery";
|
|
|
27
27
|
import { exportFromFile } from "./export/html";
|
|
28
28
|
import type { ExtensionUIContext } from "./extensibility/extensions/types";
|
|
29
29
|
import { InteractiveMode, runPrintMode, runRpcMode } from "./modes";
|
|
30
|
-
import { initTheme, stopThemeWatcher } from "./modes/theme/theme";
|
|
31
30
|
import { type CreateAgentSessionOptions, createAgentSession, discoverAuthStorage } from "./sdk";
|
|
32
31
|
import type { AgentSession } from "./session/agent-session";
|
|
33
32
|
import { type SessionInfo, SessionManager } from "./session/session-manager";
|
|
34
33
|
import { resolvePromptInput } from "./system-prompt";
|
|
34
|
+
import { initTheme, stopThemeWatcher } from "./theme/theme";
|
|
35
35
|
import { getChangelogPath, getNewEntries, parseChangelog } from "./utils/changelog";
|
|
36
36
|
import { printTimings, time } from "./utils/timings";
|
|
37
37
|
import { VERSION } from "./version";
|
package/src/mcp/tool-bridge.ts
CHANGED
|
@@ -6,16 +6,9 @@
|
|
|
6
6
|
import type { AgentToolUpdateCallback } from "@nghyane/arcane-agent";
|
|
7
7
|
import type { TSchema } from "@sinclair/typebox";
|
|
8
8
|
import type { SourceMeta } from "../capability/types";
|
|
9
|
-
import type {
|
|
10
|
-
CustomTool,
|
|
11
|
-
CustomToolContext,
|
|
12
|
-
CustomToolResult,
|
|
13
|
-
RenderResultOptions,
|
|
14
|
-
} from "../extensibility/custom-tools/types";
|
|
15
|
-
import type { Theme } from "../modes/theme/theme";
|
|
9
|
+
import type { CustomTool, CustomToolContext, CustomToolResult } from "../extensibility/custom-tools/types";
|
|
16
10
|
import { ToolAbortError, throwIfAborted } from "../tools/tool-errors";
|
|
17
11
|
import { callTool } from "./client";
|
|
18
|
-
import { renderMCPCall, renderMCPResult } from "./render";
|
|
19
12
|
import type { MCPContent, MCPServerConnection, MCPToolDefinition } from "./types";
|
|
20
13
|
|
|
21
14
|
function withAbort<T>(promise: Promise<T>, signal?: AbortSignal): Promise<T> {
|
|
@@ -198,14 +191,6 @@ export class MCPTool implements CustomTool<TSchema, MCPToolDetails> {
|
|
|
198
191
|
this.mcpServerName = connection.name;
|
|
199
192
|
}
|
|
200
193
|
|
|
201
|
-
renderCall(args: unknown, _options: RenderResultOptions, theme: Theme) {
|
|
202
|
-
return renderMCPCall((args ?? {}) as Record<string, unknown>, theme, this.label);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
renderResult(result: CustomToolResult<MCPToolDetails>, options: RenderResultOptions, theme: Theme, args?: unknown) {
|
|
206
|
-
return renderMCPResult(result, options, theme, (args ?? {}) as Record<string, unknown>);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
194
|
async execute(
|
|
210
195
|
_toolCallId: string,
|
|
211
196
|
params: unknown,
|
|
@@ -304,14 +289,6 @@ export class DeferredMCPTool implements CustomTool<TSchema, MCPToolDetails> {
|
|
|
304
289
|
this.#fallbackProviderName = source?.providerName;
|
|
305
290
|
}
|
|
306
291
|
|
|
307
|
-
renderCall(args: unknown, _options: RenderResultOptions, theme: Theme) {
|
|
308
|
-
return renderMCPCall((args ?? {}) as Record<string, unknown>, theme, this.label);
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
renderResult(result: CustomToolResult<MCPToolDetails>, options: RenderResultOptions, theme: Theme, args?: unknown) {
|
|
312
|
-
return renderMCPResult(result, options, theme, (args ?? {}) as Record<string, unknown>);
|
|
313
|
-
}
|
|
314
|
-
|
|
315
292
|
async execute(
|
|
316
293
|
_toolCallId: string,
|
|
317
294
|
params: unknown,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { AssistantMessage } from "@nghyane/arcane-ai";
|
|
2
2
|
import { Container, Markdown, Spacer, TERMINAL, Text } from "@nghyane/arcane-tui";
|
|
3
3
|
import { logger } from "@nghyane/arcane-utils";
|
|
4
|
-
import { hasPendingMermaid, prerenderMermaid } from "../../
|
|
5
|
-
import { getMarkdownTheme, theme } from "../../
|
|
4
|
+
import { hasPendingMermaid, prerenderMermaid } from "../../theme/mermaid-cache";
|
|
5
|
+
import { getMarkdownTheme, theme } from "../../theme/theme";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Component that renders a complete assistant message
|
|
@@ -90,7 +90,7 @@ export class AssistantMessageComponent extends Container {
|
|
|
90
90
|
if (content.type === "text" && content.text.trim()) {
|
|
91
91
|
// Assistant text messages with no background - trim the text
|
|
92
92
|
// Set paddingY=0 to avoid extra spacing before tool executions
|
|
93
|
-
this.#contentContainer.addChild(new Markdown(content.text.trim(),
|
|
93
|
+
this.#contentContainer.addChild(new Markdown(content.text.trim(), 2, 0, getMarkdownTheme()));
|
|
94
94
|
} else if (content.type === "thinking" && content.thinking.trim()) {
|
|
95
95
|
// Add spacing only when another visible assistant content block follows.
|
|
96
96
|
// This avoids a superfluous blank line before separately-rendered tool execution blocks.
|
|
@@ -100,14 +100,14 @@ export class AssistantMessageComponent extends Container {
|
|
|
100
100
|
|
|
101
101
|
if (this.hideThinkingBlock) {
|
|
102
102
|
// Show static "Thinking..." label when hidden
|
|
103
|
-
this.#contentContainer.addChild(new Text(theme.italic(theme.fg("thinkingText", "Thinking...")),
|
|
103
|
+
this.#contentContainer.addChild(new Text(theme.italic(theme.fg("thinkingText", "Thinking...")), 2, 0));
|
|
104
104
|
if (hasVisibleContentAfter) {
|
|
105
105
|
this.#contentContainer.addChild(new Spacer(1));
|
|
106
106
|
}
|
|
107
107
|
} else {
|
|
108
108
|
// Thinking traces in thinkingText color, italic
|
|
109
109
|
this.#contentContainer.addChild(
|
|
110
|
-
new Markdown(content.thinking.trim(),
|
|
110
|
+
new Markdown(content.thinking.trim(), 2, 0, getMarkdownTheme(), {
|
|
111
111
|
color: (text: string) => theme.fg("thinkingText", text),
|
|
112
112
|
italic: true,
|
|
113
113
|
}),
|
|
@@ -133,11 +133,11 @@ export class AssistantMessageComponent extends Container {
|
|
|
133
133
|
} else {
|
|
134
134
|
this.#contentContainer.addChild(new Spacer(1));
|
|
135
135
|
}
|
|
136
|
-
this.#contentContainer.addChild(new Text(theme.fg("error", abortMessage),
|
|
136
|
+
this.#contentContainer.addChild(new Text(theme.fg("error", abortMessage), 2, 0));
|
|
137
137
|
} else if (message.stopReason === "error") {
|
|
138
138
|
const errorMsg = message.errorMessage || "Unknown error";
|
|
139
139
|
this.#contentContainer.addChild(new Spacer(1));
|
|
140
|
-
this.#contentContainer.addChild(new Text(theme.fg("error", `Error: ${errorMsg}`),
|
|
140
|
+
this.#contentContainer.addChild(new Text(theme.fg("error", `Error: ${errorMsg}`), 2, 0));
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
}
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Component for displaying bash command execution with streaming output.
|
|
3
|
+
* Tree-style output: tail 4 lines on success, all on error.
|
|
3
4
|
*/
|
|
4
5
|
|
|
5
6
|
import { sanitizeText } from "@nghyane/arcane-natives";
|
|
6
7
|
import { Container, Loader, Spacer, Text, type TUI } from "@nghyane/arcane-tui";
|
|
7
|
-
import { getSymbolTheme, theme } from "../../
|
|
8
|
-
import { formatBytes } from "../../session/streaming-output";
|
|
8
|
+
import { getSymbolTheme, theme } from "../../theme/theme";
|
|
9
9
|
import type { TruncationMeta } from "../../tools/output-meta";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
10
|
+
import { renderStatusLine } from "../../tui/status-line";
|
|
11
|
+
import { formatCount, replaceTabs } from "../../ui/render-utils";
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
const PREVIEW_LINES = 20;
|
|
13
|
+
const TAIL_LINES = 4;
|
|
15
14
|
const MAX_DISPLAY_LINE_CHARS = 4000;
|
|
16
15
|
|
|
17
16
|
export class BashExecutionComponent extends Container {
|
|
@@ -21,50 +20,37 @@ export class BashExecutionComponent extends Container {
|
|
|
21
20
|
#loader: Loader;
|
|
22
21
|
#truncation?: TruncationMeta;
|
|
23
22
|
#expanded = false;
|
|
24
|
-
#
|
|
23
|
+
#headerText: Text;
|
|
24
|
+
#bodyText: Text;
|
|
25
25
|
|
|
26
26
|
constructor(
|
|
27
27
|
private readonly command: string,
|
|
28
28
|
ui: TUI,
|
|
29
|
-
|
|
29
|
+
_excludeFromContext = false,
|
|
30
30
|
) {
|
|
31
31
|
super();
|
|
32
|
-
|
|
33
|
-
// Use dim border for excluded-from-context commands (!! prefix)
|
|
34
|
-
const colorKey = excludeFromContext ? "dim" : "bashMode";
|
|
35
|
-
const borderColor = (str: string) => theme.fg(colorKey, str);
|
|
36
|
-
|
|
37
|
-
// Add spacer
|
|
38
32
|
this.addChild(new Spacer(1));
|
|
39
33
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
this.addChild(this.#
|
|
34
|
+
this.#headerText = new Text(
|
|
35
|
+
renderStatusLine({ icon: "running", title: "Bash", description: `$ ${command}` }, theme),
|
|
36
|
+
1,
|
|
37
|
+
0,
|
|
38
|
+
);
|
|
39
|
+
this.addChild(this.#headerText);
|
|
46
40
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
this.#contentContainer.addChild(header);
|
|
41
|
+
this.#bodyText = new Text("", 1, 0);
|
|
42
|
+
this.addChild(this.#bodyText);
|
|
50
43
|
|
|
51
|
-
// Loader
|
|
52
44
|
this.#loader = new Loader(
|
|
53
45
|
ui,
|
|
54
|
-
spinner => theme.fg(
|
|
46
|
+
spinner => theme.fg("accent", spinner),
|
|
55
47
|
text => theme.fg("muted", text),
|
|
56
|
-
|
|
48
|
+
"Running\u2026 (esc to cancel)",
|
|
57
49
|
getSymbolTheme().spinnerFrames,
|
|
58
50
|
);
|
|
59
|
-
this
|
|
60
|
-
|
|
61
|
-
// Bottom border
|
|
62
|
-
this.addChild(new DynamicBorder(borderColor));
|
|
51
|
+
this.addChild(this.#loader);
|
|
63
52
|
}
|
|
64
53
|
|
|
65
|
-
/**
|
|
66
|
-
* Set whether the output is expanded (shows full output) or collapsed (preview only).
|
|
67
|
-
*/
|
|
68
54
|
setExpanded(expanded: boolean): void {
|
|
69
55
|
this.#expanded = expanded;
|
|
70
56
|
this.#updateDisplay();
|
|
@@ -77,11 +63,8 @@ export class BashExecutionComponent extends Container {
|
|
|
77
63
|
|
|
78
64
|
appendOutput(chunk: string): void {
|
|
79
65
|
const clean = sanitizeText(chunk);
|
|
80
|
-
|
|
81
|
-
// Append to output lines
|
|
82
66
|
const newLines = clean.split("\n").map(line => this.#clampDisplayLine(line));
|
|
83
67
|
if (this.#outputLines.length > 0 && newLines.length > 0) {
|
|
84
|
-
// Append first chunk to last line (incomplete line continuation)
|
|
85
68
|
this.#outputLines[this.#outputLines.length - 1] = this.#clampDisplayLine(
|
|
86
69
|
`${this.#outputLines[this.#outputLines.length - 1]}${newLines[0]}`,
|
|
87
70
|
);
|
|
@@ -89,7 +72,6 @@ export class BashExecutionComponent extends Container {
|
|
|
89
72
|
} else {
|
|
90
73
|
this.#outputLines.push(...newLines);
|
|
91
74
|
}
|
|
92
|
-
|
|
93
75
|
this.#updateDisplay();
|
|
94
76
|
}
|
|
95
77
|
|
|
@@ -108,93 +90,52 @@ export class BashExecutionComponent extends Container {
|
|
|
108
90
|
if (options?.output !== undefined) {
|
|
109
91
|
this.#setOutput(options.output);
|
|
110
92
|
}
|
|
111
|
-
|
|
112
|
-
// Stop loader
|
|
113
93
|
this.#loader.stop();
|
|
114
|
-
|
|
115
94
|
this.#updateDisplay();
|
|
116
95
|
}
|
|
117
96
|
|
|
118
97
|
#updateDisplay(): void {
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
if (availableLines.length > 0) {
|
|
134
|
-
if (this.#expanded) {
|
|
135
|
-
// Show all lines
|
|
136
|
-
const displayText = availableLines.map(line => theme.fg("muted", line)).join("\n");
|
|
137
|
-
this.#contentContainer.addChild(new Text(`\n${displayText}`, 1, 0));
|
|
138
|
-
} else {
|
|
139
|
-
// Use shared visual truncation utility, recomputed per render width
|
|
140
|
-
const styledOutput = previewLogicalLines.map(line => theme.fg("muted", line)).join("\n");
|
|
141
|
-
const previewText = `\n${styledOutput}`;
|
|
142
|
-
this.#contentContainer.addChild({
|
|
143
|
-
render: (width: number) => {
|
|
144
|
-
const { visualLines } = truncateToVisualLines(previewText, PREVIEW_LINES, width, 1);
|
|
145
|
-
return visualLines;
|
|
146
|
-
},
|
|
147
|
-
invalidate: () => {},
|
|
148
|
-
});
|
|
149
|
-
}
|
|
98
|
+
const isError = this.#status === "error";
|
|
99
|
+
const isDone = this.#status !== "running";
|
|
100
|
+
const lines = this.#outputLines.filter(l => l.trim());
|
|
101
|
+
const total = lines.length;
|
|
102
|
+
|
|
103
|
+
// Update header
|
|
104
|
+
if (isDone) {
|
|
105
|
+
const icon = isError ? "error" : this.#status === "cancelled" ? "warning" : "success";
|
|
106
|
+
const meta: string[] = [];
|
|
107
|
+
if (isError && this.#exitCode !== undefined) meta.push(`exit ${this.#exitCode}`);
|
|
108
|
+
if (total > 0) meta.push(formatCount("line", total));
|
|
109
|
+
this.#headerText.setText(
|
|
110
|
+
renderStatusLine({ icon, title: "Bash", description: `$ ${this.command}`, meta }, theme),
|
|
111
|
+
);
|
|
150
112
|
}
|
|
151
113
|
|
|
152
|
-
//
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
const
|
|
114
|
+
// Build tree-style body
|
|
115
|
+
const bodyLines: string[] = [];
|
|
116
|
+
if (total > 0) {
|
|
117
|
+
const showAll = isError || this.#expanded;
|
|
118
|
+
const displayLines = showAll ? lines : lines.slice(-TAIL_LINES);
|
|
119
|
+
const skipped = total - displayLines.length;
|
|
157
120
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
statusParts.push(theme.fg("dim", `… ${hiddenLineCount} more lines (ctrl+o to expand)`));
|
|
121
|
+
if (skipped > 0) {
|
|
122
|
+
bodyLines.push(theme.fg("dim", `\u2026 (${skipped} earlier lines)`));
|
|
161
123
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
statusParts.push(theme.fg("warning", "(cancelled)"));
|
|
165
|
-
} else if (this.#status === "error") {
|
|
166
|
-
statusParts.push(theme.fg("error", `(exit ${this.#exitCode})`));
|
|
124
|
+
for (let i = 0; i < displayLines.length; i++) {
|
|
125
|
+
bodyLines.push(theme.fg("toolOutput", replaceTabs(displayLines[i])));
|
|
167
126
|
}
|
|
168
|
-
|
|
169
127
|
if (this.#truncation) {
|
|
170
|
-
|
|
171
|
-
if (this.#truncation.artifactId) {
|
|
172
|
-
warnings.push(`Full output: artifact://${this.#truncation.artifactId}`);
|
|
173
|
-
}
|
|
174
|
-
if (this.#truncation.truncatedBy === "lines") {
|
|
175
|
-
warnings.push(
|
|
176
|
-
`Truncated: showing ${this.#truncation.outputLines} of ${this.#truncation.totalLines} lines`,
|
|
177
|
-
);
|
|
178
|
-
} else {
|
|
179
|
-
warnings.push(
|
|
180
|
-
`Truncated: ${this.#truncation.outputLines} lines shown (${formatBytes(this.#truncation.outputBytes)} limit)`,
|
|
181
|
-
);
|
|
182
|
-
}
|
|
183
|
-
statusParts.push(theme.fg("warning", warnings.join(". ")));
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
if (statusParts.length > 0) {
|
|
187
|
-
this.#contentContainer.addChild(new Text(`\n${statusParts.join("\n")}`, 1, 0));
|
|
128
|
+
bodyLines.push(theme.fg("warning", "output truncated"));
|
|
188
129
|
}
|
|
189
130
|
}
|
|
131
|
+
|
|
132
|
+
this.#bodyText.setText(bodyLines.length > 0 ? bodyLines.join("\n") : "");
|
|
190
133
|
}
|
|
191
134
|
|
|
192
135
|
#clampDisplayLine(line: string): string {
|
|
193
|
-
if (line.length <= MAX_DISPLAY_LINE_CHARS)
|
|
194
|
-
return line;
|
|
195
|
-
}
|
|
136
|
+
if (line.length <= MAX_DISPLAY_LINE_CHARS) return line;
|
|
196
137
|
const omitted = line.length - MAX_DISPLAY_LINE_CHARS;
|
|
197
|
-
return `${line.slice(0, MAX_DISPLAY_LINE_CHARS)}
|
|
138
|
+
return `${line.slice(0, MAX_DISPLAY_LINE_CHARS)}\u2026 [${omitted} chars omitted]`;
|
|
198
139
|
}
|
|
199
140
|
|
|
200
141
|
#setOutput(output: string): void {
|
|
@@ -202,16 +143,10 @@ export class BashExecutionComponent extends Container {
|
|
|
202
143
|
this.#outputLines = clean ? clean.split("\n").map(line => this.#clampDisplayLine(line)) : [];
|
|
203
144
|
}
|
|
204
145
|
|
|
205
|
-
/**
|
|
206
|
-
* Get the raw output for creating BashExecutionMessage.
|
|
207
|
-
*/
|
|
208
146
|
getOutput(): string {
|
|
209
147
|
return this.#outputLines.join("\n");
|
|
210
148
|
}
|
|
211
149
|
|
|
212
|
-
/**
|
|
213
|
-
* Get the command that was executed.
|
|
214
|
-
*/
|
|
215
150
|
getCommand(): string {
|
|
216
151
|
return this.command;
|
|
217
152
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CancellableLoader, Container, Spacer, Text, type TUI } from "@nghyane/arcane-tui";
|
|
2
|
-
import type { Theme } from "../../
|
|
2
|
+
import type { Theme } from "../../theme/theme";
|
|
3
3
|
import { DynamicBorder } from "./dynamic-border";
|
|
4
4
|
|
|
5
5
|
/** Loader wrapped with borders for hook UI */
|
|
@@ -1,16 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { getMarkdownTheme, theme } from "../../modes/theme/theme";
|
|
1
|
+
import { Container, LeftBorderBox, Markdown, Spacer, Text } from "@nghyane/arcane-tui";
|
|
3
2
|
import type { BranchSummaryMessage } from "../../session/messages";
|
|
3
|
+
import { getMarkdownTheme, theme } from "../../theme/theme";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Component that renders a branch summary message with collapsed/expanded state.
|
|
7
|
-
* Uses same background color as hook messages for visual consistency.
|
|
8
7
|
*/
|
|
9
|
-
export class BranchSummaryMessageComponent extends
|
|
8
|
+
export class BranchSummaryMessageComponent extends Container {
|
|
9
|
+
#box: LeftBorderBox;
|
|
10
10
|
#expanded = false;
|
|
11
11
|
|
|
12
12
|
constructor(private readonly message: BranchSummaryMessage) {
|
|
13
|
-
super(
|
|
13
|
+
super();
|
|
14
|
+
this.addChild(new Spacer(1));
|
|
15
|
+
this.#box = new LeftBorderBox(1, 1, s => theme.fg("dim", s));
|
|
16
|
+
this.addChild(this.#box);
|
|
14
17
|
this.#updateDisplay();
|
|
15
18
|
}
|
|
16
19
|
|
|
@@ -25,21 +28,21 @@ export class BranchSummaryMessageComponent extends Box {
|
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
#updateDisplay(): void {
|
|
28
|
-
this.clear();
|
|
31
|
+
this.#box.clear();
|
|
29
32
|
|
|
30
33
|
const label = theme.fg("customMessageLabel", theme.bold("[branch]"));
|
|
31
|
-
this.addChild(new Text(label, 0, 0));
|
|
32
|
-
this.addChild(new Spacer(1));
|
|
34
|
+
this.#box.addChild(new Text(label, 0, 0));
|
|
35
|
+
this.#box.addChild(new Spacer(1));
|
|
33
36
|
|
|
34
37
|
if (this.#expanded) {
|
|
35
38
|
const header = "**Branch Summary**\n\n";
|
|
36
|
-
this.addChild(
|
|
39
|
+
this.#box.addChild(
|
|
37
40
|
new Markdown(header + this.message.summary, 0, 0, getMarkdownTheme(), {
|
|
38
41
|
color: (text: string) => theme.fg("customMessageText", text),
|
|
39
42
|
}),
|
|
40
43
|
);
|
|
41
44
|
} else {
|
|
42
|
-
this.addChild(new Text(theme.fg("customMessageText", "Branch summary
|
|
45
|
+
this.#box.addChild(new Text(theme.fg("customMessageText", "Branch summary"), 0, 0));
|
|
43
46
|
}
|
|
44
47
|
}
|
|
45
48
|
}
|
|
@@ -1,16 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { getMarkdownTheme, theme } from "../../modes/theme/theme";
|
|
1
|
+
import { Container, LeftBorderBox, Markdown, Spacer, Text } from "@nghyane/arcane-tui";
|
|
3
2
|
import type { CompactionSummaryMessage } from "../../session/messages";
|
|
3
|
+
import { getMarkdownTheme, theme } from "../../theme/theme";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Component that renders a compaction message with collapsed/expanded state.
|
|
7
|
-
* Uses same background color as hook messages for visual consistency.
|
|
8
7
|
*/
|
|
9
|
-
export class CompactionSummaryMessageComponent extends
|
|
8
|
+
export class CompactionSummaryMessageComponent extends Container {
|
|
9
|
+
#box: LeftBorderBox;
|
|
10
10
|
#expanded = false;
|
|
11
11
|
|
|
12
12
|
constructor(private readonly message: CompactionSummaryMessage) {
|
|
13
|
-
super(
|
|
13
|
+
super();
|
|
14
|
+
this.addChild(new Spacer(1));
|
|
15
|
+
this.#box = new LeftBorderBox(1, 1, s => theme.fg("dim", s));
|
|
16
|
+
this.addChild(this.#box);
|
|
14
17
|
this.#updateDisplay();
|
|
15
18
|
}
|
|
16
19
|
|
|
@@ -25,26 +28,24 @@ export class CompactionSummaryMessageComponent extends Box {
|
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
#updateDisplay(): void {
|
|
28
|
-
this.clear();
|
|
31
|
+
this.#box.clear();
|
|
29
32
|
|
|
30
33
|
const tokenStr = this.message.tokensBefore.toLocaleString();
|
|
31
34
|
const label = theme.fg("customMessageLabel", theme.bold("[compaction]"));
|
|
32
|
-
this.addChild(new Text(label, 0, 0));
|
|
33
|
-
this.addChild(new Spacer(1));
|
|
35
|
+
this.#box.addChild(new Text(label, 0, 0));
|
|
36
|
+
this.#box.addChild(new Spacer(1));
|
|
34
37
|
|
|
35
38
|
if (this.#expanded) {
|
|
36
39
|
const header = `**Compacted from ${tokenStr} tokens**\n\n`;
|
|
37
|
-
this.addChild(
|
|
40
|
+
this.#box.addChild(
|
|
38
41
|
new Markdown(header + this.message.summary, 0, 0, getMarkdownTheme(), {
|
|
39
42
|
color: (text: string) => theme.fg("customMessageText", text),
|
|
40
43
|
}),
|
|
41
44
|
);
|
|
42
45
|
} else {
|
|
43
|
-
this.addChild(
|
|
44
|
-
new Text(theme.fg("customMessageText", `Compacted from ${tokenStr} tokens (ctrl+o to expand)`), 0, 0),
|
|
45
|
-
);
|
|
46
|
+
this.#box.addChild(new Text(theme.fg("customMessageText", `Compacted from ${tokenStr} tokens`), 0, 0));
|
|
46
47
|
if (this.message.shortSummary) {
|
|
47
|
-
this.addChild(new Text(theme.fg("customMessageText", this.message.shortSummary), 0, 1));
|
|
48
|
+
this.#box.addChild(new Text(theme.fg("customMessageText", this.message.shortSummary), 0, 1));
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
51
|
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { Component } from "@nghyane/arcane-tui";
|
|
2
|
+
import { Spacer } from "@nghyane/arcane-tui";
|
|
3
|
+
import { theme } from "../../theme/theme";
|
|
4
|
+
import { formatCount, formatStatusIcon } from "../../ui/render-utils";
|
|
5
|
+
import type { ToolExecutionComponent } from "./tool-execution";
|
|
6
|
+
|
|
7
|
+
const CONTEXT_TOOL_LABELS: Record<string, string> = {
|
|
8
|
+
read: "read",
|
|
9
|
+
grep: "grep",
|
|
10
|
+
find: "find",
|
|
11
|
+
fetch: "fetch",
|
|
12
|
+
search_code: "search",
|
|
13
|
+
lsp: "lsp",
|
|
14
|
+
notebook: "notebook",
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Groups consecutive context-gathering tools (read, grep, find, etc.) into
|
|
19
|
+
* a single collapsible summary line to reduce visual noise.
|
|
20
|
+
*
|
|
21
|
+
* Collapsed: "Gathered context 3 reads, 2 greps, 1 find"
|
|
22
|
+
* Expanded: summary + individual tool components
|
|
23
|
+
*/
|
|
24
|
+
export class ContextGroupComponent implements Component {
|
|
25
|
+
#entries: Array<{ name: string; component: ToolExecutionComponent }> = [];
|
|
26
|
+
#expanded = false;
|
|
27
|
+
#pendingCount = 0;
|
|
28
|
+
#spacer: Spacer;
|
|
29
|
+
|
|
30
|
+
constructor() {
|
|
31
|
+
this.#spacer = new Spacer(1);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
addTool(name: string, component: ToolExecutionComponent): void {
|
|
35
|
+
this.#entries.push({ name, component });
|
|
36
|
+
this.#pendingCount++;
|
|
37
|
+
component.setExpanded(this.#expanded);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
markDone(): void {
|
|
41
|
+
this.#pendingCount = Math.max(0, this.#pendingCount - 1);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
setExpanded(expanded: boolean): void {
|
|
45
|
+
if (this.#expanded === expanded) return;
|
|
46
|
+
this.#expanded = expanded;
|
|
47
|
+
for (const entry of this.#entries) {
|
|
48
|
+
entry.component.setExpanded(expanded);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
setMarginTop(lines: number): void {
|
|
53
|
+
this.#spacer.setLines(lines);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
get size(): number {
|
|
57
|
+
return this.#entries.length;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
invalidate(): void {
|
|
61
|
+
for (const entry of this.#entries) {
|
|
62
|
+
entry.component.invalidate?.();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
render(width: number): string[] {
|
|
67
|
+
const lines: string[] = [];
|
|
68
|
+
|
|
69
|
+
// Margin
|
|
70
|
+
lines.push(...this.#spacer.render(width));
|
|
71
|
+
|
|
72
|
+
// Summary line
|
|
73
|
+
const allDone = this.#pendingCount <= 0;
|
|
74
|
+
const icon = allDone ? formatStatusIcon("success", theme) : formatStatusIcon("running", theme);
|
|
75
|
+
const label = allDone ? "Gathered context" : "Gathering context…";
|
|
76
|
+
|
|
77
|
+
// Count by tool type
|
|
78
|
+
const counts = new Map<string, number>();
|
|
79
|
+
for (const entry of this.#entries) {
|
|
80
|
+
const displayName = CONTEXT_TOOL_LABELS[entry.name] ?? entry.name;
|
|
81
|
+
counts.set(displayName, (counts.get(displayName) ?? 0) + 1);
|
|
82
|
+
}
|
|
83
|
+
const parts: string[] = [];
|
|
84
|
+
for (const [name, count] of counts) {
|
|
85
|
+
parts.push(formatCount(name, count));
|
|
86
|
+
}
|
|
87
|
+
const summary = parts.join(", ");
|
|
88
|
+
|
|
89
|
+
const summaryLine = ` ${icon} ${theme.fg("muted", label)} ${theme.fg("dim", summary)}`;
|
|
90
|
+
lines.push(summaryLine);
|
|
91
|
+
|
|
92
|
+
// Always show individual tool entries, indented under summary
|
|
93
|
+
const indent = " ";
|
|
94
|
+
const innerWidth = width - indent.length;
|
|
95
|
+
for (let i = 0; i < this.#entries.length; i++) {
|
|
96
|
+
const entryLines = this.#entries[i].component.render(innerWidth);
|
|
97
|
+
for (const line of entryLines) {
|
|
98
|
+
if (line.trim()) {
|
|
99
|
+
lines.push(indent + line);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return lines;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import type { TextContent } from "@nghyane/arcane-ai";
|
|
2
2
|
import type { Component } from "@nghyane/arcane-tui";
|
|
3
|
-
import {
|
|
3
|
+
import { Container, LeftBorderBox, Markdown, Spacer, Text } from "@nghyane/arcane-tui";
|
|
4
4
|
import type { MessageRenderer } from "../../extensibility/extensions/types";
|
|
5
|
-
import { getMarkdownTheme, theme } from "../../modes/theme/theme";
|
|
6
5
|
import type { CustomMessage } from "../../session/messages";
|
|
6
|
+
import { getMarkdownTheme, theme } from "../../theme/theme";
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Component that renders a custom message entry from extensions.
|
|
10
10
|
* Uses distinct styling to differentiate from user messages.
|
|
11
11
|
*/
|
|
12
12
|
export class CustomMessageComponent extends Container {
|
|
13
|
-
#box:
|
|
13
|
+
#box: LeftBorderBox;
|
|
14
14
|
#customComponent?: Component;
|
|
15
15
|
#expanded = false;
|
|
16
16
|
|
|
@@ -22,8 +22,7 @@ export class CustomMessageComponent extends Container {
|
|
|
22
22
|
|
|
23
23
|
this.addChild(new Spacer(1));
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
this.#box = new Box(1, 1, t => theme.bg("customMessageBg", t));
|
|
25
|
+
this.#box = new LeftBorderBox(1, 1, s => theme.fg("dim", s));
|
|
27
26
|
|
|
28
27
|
this.#rebuild();
|
|
29
28
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as Diff from "diff";
|
|
2
|
-
import { theme } from "../../
|
|
3
|
-
import { replaceTabs } from "../../
|
|
2
|
+
import { theme } from "../../theme/theme";
|
|
3
|
+
import { replaceTabs } from "../../ui/render-utils";
|
|
4
4
|
|
|
5
5
|
/** SGR dim on / normal intensity — additive, preserves fg/bg colors. */
|
|
6
6
|
const DIM = "\x1b[2m";
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
} from "@nghyane/arcane-tui";
|
|
24
24
|
import { Settings } from "../../../config/settings";
|
|
25
25
|
import { DynamicBorder } from "../../../modes/components/dynamic-border";
|
|
26
|
-
import { theme } from "../../../
|
|
26
|
+
import { theme } from "../../../theme/theme";
|
|
27
27
|
import { ExtensionList } from "./extension-list";
|
|
28
28
|
import { InspectorPanel } from "./inspector-panel";
|
|
29
29
|
import { applyFilter, createInitialState, filterByProvider, refreshState, toggleProvider } from "./state-manager";
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { type Component, matchesKey, padding, truncateToWidth, visibleWidth } from "@nghyane/arcane-tui";
|
|
9
9
|
import { isProviderEnabled } from "../../../discovery";
|
|
10
|
-
import { theme } from "../../../
|
|
10
|
+
import { theme } from "../../../theme/theme";
|
|
11
11
|
import { applyFilter } from "./state-manager";
|
|
12
12
|
import type { Extension, ExtensionKind, ExtensionState } from "./types";
|
|
13
13
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import * as os from "node:os";
|
|
7
7
|
import { type Component, truncateToWidth, wrapTextWithAnsi } from "@nghyane/arcane-tui";
|
|
8
|
-
import { theme } from "../../../
|
|
8
|
+
import { theme } from "../../../theme/theme";
|
|
9
9
|
import type { Extension, ExtensionState } from "./types";
|
|
10
10
|
|
|
11
11
|
export class InspectorPanel implements Component {
|