@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/web/search/render.ts
CHANGED
|
@@ -5,63 +5,15 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import type { Component } from "@nghyane/arcane-tui";
|
|
8
|
-
import { Text
|
|
8
|
+
import { Text } from "@nghyane/arcane-tui";
|
|
9
9
|
import type { RenderResultOptions } from "../../extensibility/custom-tools/types";
|
|
10
|
-
import type { Theme } from "../../
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
formatCount,
|
|
14
|
-
formatExpandHint,
|
|
15
|
-
formatMoreItems,
|
|
16
|
-
formatStatusIcon,
|
|
17
|
-
getDomain,
|
|
18
|
-
getPreviewLines,
|
|
19
|
-
PREVIEW_LIMITS,
|
|
20
|
-
TRUNCATE_LENGTHS,
|
|
21
|
-
truncateToWidth,
|
|
22
|
-
} from "../../tools/render-utils";
|
|
23
|
-
import { renderStatusLine, renderTreeList } from "../../tui";
|
|
24
|
-
import { CachedOutputBlock } from "../../tui/output-block";
|
|
10
|
+
import type { Theme } from "../../theme/theme";
|
|
11
|
+
import { renderStatusLine } from "../../tui";
|
|
12
|
+
import { formatCount, formatMoreItems, getDomain, truncateToWidth } from "../../ui/render-utils";
|
|
25
13
|
import { getSearchProvider } from "./provider";
|
|
26
14
|
import type { SearchResponse } from "./types";
|
|
27
15
|
|
|
28
|
-
const
|
|
29
|
-
const MAX_EXPANDED_ANSWER_LINES = PREVIEW_LIMITS.EXPANDED_LINES;
|
|
30
|
-
const MAX_ANSWER_LINE_LEN = TRUNCATE_LENGTHS.LINE;
|
|
31
|
-
const MAX_SNIPPET_LINES = 2;
|
|
32
|
-
const MAX_SNIPPET_LINE_LEN = TRUNCATE_LENGTHS.LINE;
|
|
33
|
-
const MAX_COLLAPSED_ITEMS = PREVIEW_LIMITS.COLLAPSED_ITEMS;
|
|
34
|
-
const MAX_QUERY_PREVIEW = 2;
|
|
35
|
-
const MAX_QUERY_LEN = 90;
|
|
36
|
-
const MAX_REQUEST_ID_LEN = 36;
|
|
37
|
-
|
|
38
|
-
function renderFallbackText(contentText: string, expanded: boolean, theme: Theme): Component {
|
|
39
|
-
const lines = contentText.split("\n").filter(line => line.trim());
|
|
40
|
-
const maxLines = expanded ? lines.length : 6;
|
|
41
|
-
const displayLines = lines.slice(0, maxLines).map(line => truncateToWidth(line.trim(), 110));
|
|
42
|
-
const remaining = lines.length - displayLines.length;
|
|
43
|
-
|
|
44
|
-
const headerIcon = formatStatusIcon("warning", theme);
|
|
45
|
-
const expandHint = formatExpandHint(theme, expanded, remaining > 0);
|
|
46
|
-
let text = `${headerIcon} ${theme.fg("dim", "Response")}${expandHint}`;
|
|
47
|
-
|
|
48
|
-
if (displayLines.length === 0) {
|
|
49
|
-
text += `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg("muted", "No response data")}`;
|
|
50
|
-
return new Text(text, 0, 0);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
for (let i = 0; i < displayLines.length; i++) {
|
|
54
|
-
const isLast = i === displayLines.length - 1 && remaining === 0;
|
|
55
|
-
const branch = isLast ? theme.tree.last : theme.tree.branch;
|
|
56
|
-
text += `\n ${theme.fg("dim", branch)} ${theme.fg("dim", displayLines[i])}`;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (!expanded && remaining > 0) {
|
|
60
|
-
text += `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg("muted", formatMoreItems(remaining, "line"))}`;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return new Text(text, 0, 0);
|
|
64
|
-
}
|
|
16
|
+
const MAX_COLLAPSED_SOURCES = 5;
|
|
65
17
|
|
|
66
18
|
export interface SearchRenderDetails {
|
|
67
19
|
response: SearchResponse;
|
|
@@ -81,203 +33,70 @@ export function renderSearchResult(
|
|
|
81
33
|
},
|
|
82
34
|
): Component {
|
|
83
35
|
const details = result.details;
|
|
84
|
-
|
|
85
|
-
// Handle error case
|
|
86
|
-
if (details?.error) {
|
|
87
|
-
return new Text(theme.fg("error", `Error: ${details.error}`), 0, 0);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const rawText = result.content?.find(block => block.type === "text")?.text?.trim() ?? "";
|
|
91
36
|
const response = details?.response;
|
|
92
|
-
|
|
93
|
-
return renderFallbackText(rawText, options.expanded, theme);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
const sources = Array.isArray(response.sources) ? response.sources : [];
|
|
37
|
+
const sources = Array.isArray(response?.sources) ? response.sources : [];
|
|
97
38
|
const sourceCount = sources.length;
|
|
98
|
-
const
|
|
99
|
-
const citationCount = citations.length;
|
|
100
|
-
const searchQueries = Array.isArray(response.searchQueries)
|
|
39
|
+
const searchQueries = Array.isArray(response?.searchQueries)
|
|
101
40
|
? response.searchQueries.filter(item => typeof item === "string")
|
|
102
41
|
: [];
|
|
103
|
-
const provider = response
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
.map(l => l.trim())
|
|
113
|
-
: [];
|
|
114
|
-
const totalAnswerLines = answerLines.length;
|
|
115
|
-
|
|
116
|
-
const providerLabel = provider !== "none" ? getSearchProvider(provider).label : "None";
|
|
42
|
+
const provider = response?.provider;
|
|
43
|
+
|
|
44
|
+
const providerLabel = provider
|
|
45
|
+
? provider === "none"
|
|
46
|
+
? "None"
|
|
47
|
+
: provider === "grep"
|
|
48
|
+
? "grep.app"
|
|
49
|
+
: getSearchProvider(provider).label
|
|
50
|
+
: "auto";
|
|
117
51
|
const queryPreview = args?.query
|
|
118
52
|
? truncateToWidth(args.query, 80)
|
|
119
53
|
: searchQueries[0]
|
|
120
54
|
? truncateToWidth(searchQueries[0], 80)
|
|
121
55
|
: undefined;
|
|
56
|
+
|
|
122
57
|
const header = renderStatusLine(
|
|
123
58
|
{
|
|
124
|
-
icon: sourceCount > 0 ? "success" : "warning",
|
|
59
|
+
icon: sourceCount > 0 ? "success" : details?.error ? "error" : "warning",
|
|
125
60
|
title: "Web Search",
|
|
126
|
-
description:
|
|
127
|
-
meta: [formatCount("source", sourceCount)],
|
|
61
|
+
description: queryPreview,
|
|
62
|
+
meta: [formatCount("source", sourceCount), providerLabel],
|
|
128
63
|
},
|
|
129
64
|
theme,
|
|
130
65
|
);
|
|
131
66
|
|
|
132
|
-
|
|
133
|
-
metaLines.push(`${theme.fg("muted", "Provider:")} ${theme.fg("text", providerLabel)}`);
|
|
134
|
-
if (response.authMode)
|
|
135
|
-
metaLines.push(
|
|
136
|
-
`${theme.fg("muted", "Auth:")} ${theme.fg("text", response.authMode === "oauth" ? "OAuth" : response.authMode === "api_key" ? "API key" : response.authMode)}`,
|
|
137
|
-
);
|
|
138
|
-
if (response.model) metaLines.push(`${theme.fg("muted", "Model:")} ${theme.fg("text", response.model)}`);
|
|
139
|
-
metaLines.push(`${theme.fg("muted", "Sources:")} ${theme.fg("text", String(sourceCount))}`);
|
|
140
|
-
if (citationCount > 0)
|
|
141
|
-
metaLines.push(`${theme.fg("muted", "Citations:")} ${theme.fg("text", String(citationCount))}`);
|
|
142
|
-
if (response.usage) {
|
|
143
|
-
const usageParts: string[] = [];
|
|
144
|
-
if (response.usage.inputTokens !== undefined) usageParts.push(`in ${response.usage.inputTokens}`);
|
|
145
|
-
if (response.usage.outputTokens !== undefined) usageParts.push(`out ${response.usage.outputTokens}`);
|
|
146
|
-
if (response.usage.totalTokens !== undefined) usageParts.push(`total ${response.usage.totalTokens}`);
|
|
147
|
-
if (response.usage.searchRequests !== undefined) usageParts.push(`search ${response.usage.searchRequests}`);
|
|
148
|
-
if (usageParts.length > 0)
|
|
149
|
-
metaLines.push(`${theme.fg("muted", "Usage:")} ${theme.fg("text", usageParts.join(theme.sep.dot))}`);
|
|
150
|
-
}
|
|
151
|
-
if (response.requestId) {
|
|
152
|
-
metaLines.push(
|
|
153
|
-
`${theme.fg("muted", "Request:")} ${theme.fg("text", truncateToWidth(response.requestId, MAX_REQUEST_ID_LEN))}`,
|
|
154
|
-
);
|
|
155
|
-
}
|
|
156
|
-
if (searchQueries.length > 0) {
|
|
157
|
-
const queriesPreview = searchQueries.slice(0, MAX_QUERY_PREVIEW);
|
|
158
|
-
const queryList = queriesPreview.map(q => truncateToWidth(q, MAX_QUERY_LEN));
|
|
159
|
-
const suffix = searchQueries.length > queriesPreview.length ? "…" : "";
|
|
160
|
-
metaLines.push(`${theme.fg("muted", "Queries:")} ${theme.fg("text", queryList.join("; "))}${suffix}`);
|
|
161
|
-
}
|
|
67
|
+
let text = header;
|
|
162
68
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
// Read mutable state at render time
|
|
168
|
-
const { expanded } = options;
|
|
69
|
+
if (details?.error) {
|
|
70
|
+
text += `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg("error", details.error)}`;
|
|
71
|
+
return new Text(text, 0, 0);
|
|
72
|
+
}
|
|
169
73
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
? args?.allowLongAnswer
|
|
174
|
-
? answerLines.slice(0, args.maxAnswerLines ?? answerLines.length)
|
|
175
|
-
: getPreviewLines(contentText, answerLimit, MAX_ANSWER_LINE_LEN)
|
|
176
|
-
: [];
|
|
177
|
-
const remainingAnswer = totalAnswerLines - answerPreview.length;
|
|
74
|
+
const { expanded } = options;
|
|
75
|
+
const maxItems = expanded ? sources.length : Math.min(sources.length, MAX_COLLAPSED_SOURCES);
|
|
76
|
+
const remaining = sources.length - maxItems;
|
|
178
77
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
const age =
|
|
196
|
-
formatAge(src.ageSeconds) || (typeof src.publishedDate === "string" ? src.publishedDate : "");
|
|
197
|
-
const metaParts: string[] = [];
|
|
198
|
-
if (domain) metaParts.push(theme.fg("dim", `(${domain})`));
|
|
199
|
-
if (typeof src.author === "string" && src.author.trim())
|
|
200
|
-
metaParts.push(theme.fg("muted", src.author));
|
|
201
|
-
if (age) metaParts.push(theme.fg("muted", age));
|
|
202
|
-
const metaSep = theme.fg("dim", theme.sep.dot);
|
|
203
|
-
const metaSuffix = metaParts.length > 0 ? ` ${metaParts.join(metaSep)}` : "";
|
|
204
|
-
const srcLines: string[] = [`${theme.fg("accent", title)}${metaSuffix}`];
|
|
205
|
-
const snippetText = typeof src.snippet === "string" ? src.snippet : "";
|
|
206
|
-
if (snippetText.trim()) {
|
|
207
|
-
const snippetLines = getPreviewLines(snippetText, MAX_SNIPPET_LINES, MAX_SNIPPET_LINE_LEN);
|
|
208
|
-
for (const snippetLine of snippetLines) {
|
|
209
|
-
srcLines.push(theme.fg("muted", `${theme.format.dash} ${snippetLine}`));
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
if (url) srcLines.push(theme.fg("mdLinkUrl", url));
|
|
213
|
-
return srcLines;
|
|
214
|
-
},
|
|
215
|
-
},
|
|
216
|
-
theme,
|
|
217
|
-
);
|
|
78
|
+
for (let i = 0; i < maxItems; i++) {
|
|
79
|
+
const src = sources[i];
|
|
80
|
+
const isLast = i === maxItems - 1 && remaining === 0;
|
|
81
|
+
const branch = isLast ? theme.tree.last : theme.tree.branch;
|
|
82
|
+
const titleText =
|
|
83
|
+
typeof src.title === "string" && src.title.trim()
|
|
84
|
+
? src.title
|
|
85
|
+
: typeof src.url === "string" && src.url.trim()
|
|
86
|
+
? src.url
|
|
87
|
+
: "Untitled";
|
|
88
|
+
const title = truncateToWidth(titleText, 70);
|
|
89
|
+
const url = typeof src.url === "string" ? src.url : "";
|
|
90
|
+
const domain = url ? getDomain(url) : "";
|
|
91
|
+
const domainPart = domain ? ` ${theme.fg("dim", `(${domain})`)}` : "";
|
|
92
|
+
text += `\n ${theme.fg("dim", branch)} ${theme.fg("accent", title)}${domainPart}`;
|
|
93
|
+
}
|
|
218
94
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
const border = (t: string) => theme.fg(borderColor, t);
|
|
223
|
-
const contentPrefix = border(`${theme.boxSharp.vertical} `);
|
|
224
|
-
const contentSuffix = border(theme.boxSharp.vertical);
|
|
225
|
-
const contentWidth = Math.max(0, width - visibleWidth(contentPrefix) - visibleWidth(contentSuffix));
|
|
226
|
-
const answerTreeLines = answerPreview.length > 0 ? answerPreview : ["No answer text returned"];
|
|
227
|
-
const answerTree = renderTreeList(
|
|
228
|
-
{
|
|
229
|
-
items: answerTreeLines,
|
|
230
|
-
expanded: true,
|
|
231
|
-
maxCollapsed: answerTreeLines.length,
|
|
232
|
-
itemType: "line",
|
|
233
|
-
renderItem: (line, context) => {
|
|
234
|
-
const coloredLine =
|
|
235
|
-
line === "No answer text returned" ? theme.fg("muted", line) : theme.fg("dim", line);
|
|
236
|
-
if (!args?.allowLongAnswer) {
|
|
237
|
-
return coloredLine;
|
|
238
|
-
}
|
|
239
|
-
const prefixWidth = visibleWidth(context.continuePrefix);
|
|
240
|
-
const wrapWidth = Math.max(10, contentWidth - prefixWidth);
|
|
241
|
-
return wrapTextWithAnsi(coloredLine, wrapWidth);
|
|
242
|
-
},
|
|
243
|
-
},
|
|
244
|
-
theme,
|
|
245
|
-
);
|
|
246
|
-
if (remainingAnswer > 0) {
|
|
247
|
-
answerTree.push(theme.fg("muted", formatMoreItems(remainingAnswer, "line")));
|
|
248
|
-
}
|
|
95
|
+
if (remaining > 0) {
|
|
96
|
+
text += `\n ${theme.fg("dim", theme.tree.last)} ${theme.fg("muted", formatMoreItems(remaining, "source"))}`;
|
|
97
|
+
}
|
|
249
98
|
|
|
250
|
-
|
|
251
|
-
{
|
|
252
|
-
header,
|
|
253
|
-
state: sourceCount > 0 ? "success" : "warning",
|
|
254
|
-
sections: [
|
|
255
|
-
...(queryPreview
|
|
256
|
-
? [
|
|
257
|
-
{
|
|
258
|
-
lines: [`${theme.fg("muted", "Query:")} ${theme.fg("text", queryPreview)}`],
|
|
259
|
-
},
|
|
260
|
-
]
|
|
261
|
-
: []),
|
|
262
|
-
{
|
|
263
|
-
label: theme.fg("toolTitle", "Answer"),
|
|
264
|
-
lines: answerTree,
|
|
265
|
-
},
|
|
266
|
-
{
|
|
267
|
-
label: theme.fg("toolTitle", "Sources"),
|
|
268
|
-
lines: sourceTree.length > 0 ? sourceTree : [theme.fg("muted", "No sources returned")],
|
|
269
|
-
},
|
|
270
|
-
{ label: theme.fg("toolTitle", "Metadata"), lines: metaLines },
|
|
271
|
-
],
|
|
272
|
-
width,
|
|
273
|
-
},
|
|
274
|
-
theme,
|
|
275
|
-
);
|
|
276
|
-
},
|
|
277
|
-
invalidate() {
|
|
278
|
-
outputBlock.invalidate();
|
|
279
|
-
},
|
|
280
|
-
};
|
|
99
|
+
return new Text(text, 0, 0);
|
|
281
100
|
}
|
|
282
101
|
|
|
283
102
|
/** Render web search call (query preview) */
|
|
@@ -291,9 +110,3 @@ export function renderSearchCall(
|
|
|
291
110
|
const text = renderStatusLine({ icon: "pending", title: "Web Search", description: query, meta: [provider] }, theme);
|
|
292
111
|
return new Text(text, 0, 0);
|
|
293
112
|
}
|
|
294
|
-
|
|
295
|
-
export const webSearchToolRenderer = {
|
|
296
|
-
renderCall: renderSearchCall,
|
|
297
|
-
renderResult: renderSearchResult,
|
|
298
|
-
mergeCallAndResult: true,
|
|
299
|
-
};
|
package/src/web/search/types.ts
CHANGED
|
@@ -48,7 +48,7 @@ export interface SearchUsage {
|
|
|
48
48
|
|
|
49
49
|
/** Unified response across providers */
|
|
50
50
|
export interface SearchResponse {
|
|
51
|
-
provider: SearchProviderId | "none";
|
|
51
|
+
provider: SearchProviderId | "grep" | "none";
|
|
52
52
|
/** Synthesized answer text (anthropic, perplexity) */
|
|
53
53
|
answer?: string;
|
|
54
54
|
/** Search result sources */
|
package/src/commands/commit.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generate and optionally push a commit with changelog updates.
|
|
3
|
-
*/
|
|
4
|
-
import { Command, Flags } from "@nghyane/arcane-utils/cli";
|
|
5
|
-
import { runCommitCommand } from "../commit";
|
|
6
|
-
import type { CommitCommandArgs } from "../commit/types";
|
|
7
|
-
import { initTheme } from "../modes/theme/theme";
|
|
8
|
-
|
|
9
|
-
export default class Commit extends Command {
|
|
10
|
-
static description = "Generate a commit message and update changelogs";
|
|
11
|
-
|
|
12
|
-
static flags = {
|
|
13
|
-
push: Flags.boolean({ description: "Push after committing" }),
|
|
14
|
-
"dry-run": Flags.boolean({ description: "Preview without committing" }),
|
|
15
|
-
"no-changelog": Flags.boolean({ description: "Skip changelog updates" }),
|
|
16
|
-
legacy: Flags.boolean({ description: "Use legacy deterministic pipeline" }),
|
|
17
|
-
context: Flags.string({ char: "c", description: "Additional context for the model" }),
|
|
18
|
-
model: Flags.string({ char: "m", description: "Override model selection" }),
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
async run(): Promise<void> {
|
|
22
|
-
const { flags } = await this.parse(Commit);
|
|
23
|
-
|
|
24
|
-
const cmd: CommitCommandArgs = {
|
|
25
|
-
push: flags.push ?? false,
|
|
26
|
-
dryRun: flags["dry-run"] ?? false,
|
|
27
|
-
noChangelog: flags["no-changelog"] ?? false,
|
|
28
|
-
legacy: flags.legacy,
|
|
29
|
-
context: flags.context,
|
|
30
|
-
model: flags.model,
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
await initTheme();
|
|
34
|
-
await runCommitCommand(cmd);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
@@ -1,311 +0,0 @@
|
|
|
1
|
-
import type { Api, Model } from "@nghyane/arcane-ai";
|
|
2
|
-
import { Markdown } from "@nghyane/arcane-tui";
|
|
3
|
-
import chalk from "chalk";
|
|
4
|
-
import type { ControlledGit } from "../../commit/git";
|
|
5
|
-
import typesDescriptionPrompt from "../../commit/prompts/types-description.md" with { type: "text" };
|
|
6
|
-
import type { ModelRegistry } from "../../config/model-registry";
|
|
7
|
-
import { renderPromptTemplate } from "../../config/prompt-templates";
|
|
8
|
-
import type { Settings } from "../../config/settings";
|
|
9
|
-
import { getMarkdownTheme } from "../../modes/theme/theme";
|
|
10
|
-
import { createAgentSession } from "../../sdk";
|
|
11
|
-
import type { AgentSessionEvent } from "../../session/agent-session";
|
|
12
|
-
import type { AuthStorage } from "../../session/auth-storage";
|
|
13
|
-
import agentUserPrompt from "./prompts/session-user.md" with { type: "text" };
|
|
14
|
-
import agentSystemPrompt from "./prompts/system.md" with { type: "text" };
|
|
15
|
-
import type { CommitAgentState } from "./state";
|
|
16
|
-
import { createCommitTools } from "./tools";
|
|
17
|
-
|
|
18
|
-
export interface CommitAgentInput {
|
|
19
|
-
cwd: string;
|
|
20
|
-
git: ControlledGit;
|
|
21
|
-
model: Model<Api>;
|
|
22
|
-
settings: Settings;
|
|
23
|
-
modelRegistry: ModelRegistry;
|
|
24
|
-
authStorage: AuthStorage;
|
|
25
|
-
userContext?: string;
|
|
26
|
-
contextFiles?: Array<{ path: string; content: string }>;
|
|
27
|
-
changelogTargets: string[];
|
|
28
|
-
requireChangelog: boolean;
|
|
29
|
-
diffText?: string;
|
|
30
|
-
existingChangelogEntries?: ExistingChangelogEntries[];
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export interface ExistingChangelogEntries {
|
|
34
|
-
path: string;
|
|
35
|
-
sections: Array<{ name: string; items: string[] }>;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export async function runCommitAgentSession(input: CommitAgentInput): Promise<CommitAgentState> {
|
|
39
|
-
const typesDescription = renderPromptTemplate(typesDescriptionPrompt);
|
|
40
|
-
const systemPrompt = renderPromptTemplate(agentSystemPrompt, {
|
|
41
|
-
types_description: typesDescription,
|
|
42
|
-
});
|
|
43
|
-
const state: CommitAgentState = { diffText: input.diffText };
|
|
44
|
-
const spawns = "quick_task";
|
|
45
|
-
const tools = createCommitTools({
|
|
46
|
-
cwd: input.cwd,
|
|
47
|
-
git: input.git,
|
|
48
|
-
authStorage: input.authStorage,
|
|
49
|
-
modelRegistry: input.modelRegistry,
|
|
50
|
-
settings: input.settings,
|
|
51
|
-
spawns,
|
|
52
|
-
state,
|
|
53
|
-
changelogTargets: input.changelogTargets,
|
|
54
|
-
enableAnalyzeFiles: true,
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
const { session } = await createAgentSession({
|
|
58
|
-
cwd: input.cwd,
|
|
59
|
-
authStorage: input.authStorage,
|
|
60
|
-
modelRegistry: input.modelRegistry,
|
|
61
|
-
settings: input.settings,
|
|
62
|
-
model: input.model,
|
|
63
|
-
systemPrompt,
|
|
64
|
-
customTools: tools,
|
|
65
|
-
enableLsp: false,
|
|
66
|
-
enableMCP: false,
|
|
67
|
-
hasUI: false,
|
|
68
|
-
spawns,
|
|
69
|
-
toolNames: ["__none__"],
|
|
70
|
-
contextFiles: input.contextFiles,
|
|
71
|
-
disableExtensionDiscovery: true,
|
|
72
|
-
skills: [],
|
|
73
|
-
promptTemplates: [],
|
|
74
|
-
slashCommands: [],
|
|
75
|
-
});
|
|
76
|
-
let toolCalls = 0;
|
|
77
|
-
let messageCount = 0;
|
|
78
|
-
let isThinking = false;
|
|
79
|
-
let thinkingLineActive = false;
|
|
80
|
-
const toolArgsById = new Map<string, { name: string; args?: Record<string, unknown> }>();
|
|
81
|
-
const writeThinkingLine = (text: string) => {
|
|
82
|
-
const line = chalk.dim(`… ${text}`);
|
|
83
|
-
process.stdout.write(`\r\x1b[2K${line}`);
|
|
84
|
-
thinkingLineActive = true;
|
|
85
|
-
};
|
|
86
|
-
const clearThinkingLine = () => {
|
|
87
|
-
if (!thinkingLineActive) return;
|
|
88
|
-
process.stdout.write("\r\x1b[2K");
|
|
89
|
-
thinkingLineActive = false;
|
|
90
|
-
};
|
|
91
|
-
const unsubscribe = session.subscribe((event: AgentSessionEvent) => {
|
|
92
|
-
switch (event.type) {
|
|
93
|
-
case "message_start":
|
|
94
|
-
if (event.message.role === "assistant") {
|
|
95
|
-
isThinking = true;
|
|
96
|
-
thinkingLineActive = false;
|
|
97
|
-
}
|
|
98
|
-
break;
|
|
99
|
-
case "message_update": {
|
|
100
|
-
if (event.message?.role !== "assistant") break;
|
|
101
|
-
const preview = extractMessagePreview(event.message?.content ?? []);
|
|
102
|
-
if (!preview) break;
|
|
103
|
-
writeThinkingLine(preview);
|
|
104
|
-
break;
|
|
105
|
-
}
|
|
106
|
-
case "tool_execution_start":
|
|
107
|
-
toolCalls += 1;
|
|
108
|
-
toolArgsById.set(event.toolCallId, { name: event.toolName, args: event.args });
|
|
109
|
-
break;
|
|
110
|
-
case "message_end": {
|
|
111
|
-
const role = event.message?.role;
|
|
112
|
-
if (role === "assistant") {
|
|
113
|
-
messageCount += 1;
|
|
114
|
-
isThinking = false;
|
|
115
|
-
clearThinkingLine();
|
|
116
|
-
const assistantMessage = event.message as { stopReason?: string; errorMessage?: string };
|
|
117
|
-
if (assistantMessage.stopReason === "error" && assistantMessage.errorMessage) {
|
|
118
|
-
writeStdout(`● Error: ${assistantMessage.errorMessage}`);
|
|
119
|
-
}
|
|
120
|
-
const messageText = extractMessageText(event.message?.content ?? []);
|
|
121
|
-
if (messageText) {
|
|
122
|
-
writeAssistantMessage(messageText);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
break;
|
|
126
|
-
}
|
|
127
|
-
case "tool_execution_end": {
|
|
128
|
-
const stored = toolArgsById.get(event.toolCallId) ?? { name: event.toolName };
|
|
129
|
-
toolArgsById.delete(event.toolCallId);
|
|
130
|
-
clearThinkingLine();
|
|
131
|
-
const toolLabel = formatToolLabel(stored.name);
|
|
132
|
-
const symbol = event.isError ? "" : "";
|
|
133
|
-
writeStdout(`${symbol} ${toolLabel}`);
|
|
134
|
-
const argsLines = formatToolArgs(stored.args);
|
|
135
|
-
if (argsLines.length > 0) {
|
|
136
|
-
writeStdout(formatToolArgsBlock(argsLines));
|
|
137
|
-
}
|
|
138
|
-
break;
|
|
139
|
-
}
|
|
140
|
-
case "agent_end":
|
|
141
|
-
if (isThinking) {
|
|
142
|
-
isThinking = false;
|
|
143
|
-
}
|
|
144
|
-
writeStdout(`● agent finished (${messageCount} messages, ${toolCalls} tools)`);
|
|
145
|
-
break;
|
|
146
|
-
default:
|
|
147
|
-
break;
|
|
148
|
-
}
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
try {
|
|
152
|
-
const prompt = renderPromptTemplate(agentUserPrompt, {
|
|
153
|
-
user_context: input.userContext,
|
|
154
|
-
changelog_targets: input.changelogTargets.length > 0 ? input.changelogTargets.join("\n") : undefined,
|
|
155
|
-
existing_changelog_entries: input.existingChangelogEntries,
|
|
156
|
-
});
|
|
157
|
-
const MAX_RETRIES = 3;
|
|
158
|
-
let retryCount = 0;
|
|
159
|
-
const needsChangelog = input.requireChangelog && input.changelogTargets.length > 0;
|
|
160
|
-
|
|
161
|
-
await session.prompt(prompt, { expandPromptTemplates: false });
|
|
162
|
-
while (retryCount < MAX_RETRIES && !isProposalComplete(state, needsChangelog)) {
|
|
163
|
-
retryCount += 1;
|
|
164
|
-
const reminder = buildReminderMessage(state, needsChangelog, retryCount, MAX_RETRIES);
|
|
165
|
-
await session.prompt(reminder, { expandPromptTemplates: false });
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
return state;
|
|
169
|
-
} finally {
|
|
170
|
-
unsubscribe();
|
|
171
|
-
await session.dispose();
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
function writeStdout(message: string): void {
|
|
176
|
-
process.stdout.write(`${message}\n`);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
function extractMessagePreview(content: Array<{ type: string; text?: string }>): string | null {
|
|
180
|
-
const textBlocks = content
|
|
181
|
-
.filter(block => block.type === "text" && typeof block.text === "string")
|
|
182
|
-
.map(block => block.text?.trim())
|
|
183
|
-
.filter((value): value is string => Boolean(value));
|
|
184
|
-
if (textBlocks.length === 0) return null;
|
|
185
|
-
const combined = textBlocks.join(" ").replace(/\s+/g, " ").trim();
|
|
186
|
-
return truncateToolArg(combined);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
function extractMessageText(content: Array<{ type: string; text?: string }>): string | null {
|
|
190
|
-
const textBlocks = content
|
|
191
|
-
.filter(block => block.type === "text" && typeof block.text === "string")
|
|
192
|
-
.map(block => block.text ?? "")
|
|
193
|
-
.filter(value => value.trim().length > 0);
|
|
194
|
-
if (textBlocks.length === 0) return null;
|
|
195
|
-
return textBlocks.join("\n").trim();
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
function writeAssistantMessage(message: string): void {
|
|
199
|
-
const lines = renderMarkdownLines(message);
|
|
200
|
-
if (lines.length === 0) return;
|
|
201
|
-
let firstContentIndex = lines.findIndex(line => line.trim().length > 0);
|
|
202
|
-
if (firstContentIndex === -1) {
|
|
203
|
-
firstContentIndex = 0;
|
|
204
|
-
}
|
|
205
|
-
for (const [index, line] of lines.entries()) {
|
|
206
|
-
const prefix = index === firstContentIndex ? "● " : " ";
|
|
207
|
-
writeStdout(`${prefix}${line}`.trimEnd());
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
function renderMarkdownLines(message: string): string[] {
|
|
212
|
-
const width = Math.max(40, process.stdout.columns ?? 100);
|
|
213
|
-
const markdown = new Markdown(message, 0, 0, getMarkdownTheme());
|
|
214
|
-
return markdown.render(width);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
function formatToolLabel(toolName: string): string {
|
|
218
|
-
const displayName = toolName
|
|
219
|
-
.split(/[_-]/)
|
|
220
|
-
.map(segment => segment.charAt(0).toUpperCase() + segment.slice(1))
|
|
221
|
-
.join("");
|
|
222
|
-
return displayName;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
function formatToolArgs(args?: Record<string, unknown>): string[] {
|
|
226
|
-
if (!args || Object.keys(args).length === 0) return [];
|
|
227
|
-
const lines: string[] = [];
|
|
228
|
-
const visit = (value: unknown, keyPath: string) => {
|
|
229
|
-
if (value === null || value === undefined) return;
|
|
230
|
-
if (Array.isArray(value)) {
|
|
231
|
-
if (value.length === 0) return;
|
|
232
|
-
const rendered = value.map(item => renderPrimitive(item)).filter(Boolean);
|
|
233
|
-
if (rendered.length > 0) {
|
|
234
|
-
lines.push(`${keyPath}: ${rendered.join(", ")}`);
|
|
235
|
-
}
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
if (typeof value === "object") {
|
|
239
|
-
const entries = Object.entries(value as Record<string, unknown>);
|
|
240
|
-
if (entries.length === 0) return;
|
|
241
|
-
for (const [childKey, childValue] of entries) {
|
|
242
|
-
visit(childValue, `${keyPath}.${childKey}`);
|
|
243
|
-
}
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
|
-
const rendered = renderPrimitive(value);
|
|
247
|
-
if (rendered) {
|
|
248
|
-
lines.push(`${keyPath}: ${rendered}`);
|
|
249
|
-
}
|
|
250
|
-
};
|
|
251
|
-
for (const [key, value] of Object.entries(args)) {
|
|
252
|
-
visit(value, key);
|
|
253
|
-
}
|
|
254
|
-
return lines;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
function renderPrimitive(value: unknown): string | null {
|
|
258
|
-
if (value === null || value === undefined) return null;
|
|
259
|
-
if (typeof value === "string") {
|
|
260
|
-
const trimmed = value.trim();
|
|
261
|
-
return trimmed.length > 0 ? trimmed : null;
|
|
262
|
-
}
|
|
263
|
-
if (typeof value === "number" || typeof value === "boolean") {
|
|
264
|
-
return String(value);
|
|
265
|
-
}
|
|
266
|
-
return null;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
function formatToolArgsBlock(lines: string[]): string {
|
|
270
|
-
return lines
|
|
271
|
-
.map((line, index) => {
|
|
272
|
-
if (index === 0) return ` ⎿ ${line}`;
|
|
273
|
-
const branch = index === lines.length - 1 ? "└" : "├";
|
|
274
|
-
return ` ${branch} ${line}`;
|
|
275
|
-
})
|
|
276
|
-
.join("\n");
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
function isProposalComplete(state: CommitAgentState, requireChangelog: boolean): boolean {
|
|
280
|
-
const hasCommit = Boolean(state.proposal ?? state.splitProposal);
|
|
281
|
-
const hasChangelog = !requireChangelog || Boolean(state.changelogProposal);
|
|
282
|
-
return hasCommit && hasChangelog;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
function buildReminderMessage(
|
|
286
|
-
state: CommitAgentState,
|
|
287
|
-
requireChangelog: boolean,
|
|
288
|
-
retryCount: number,
|
|
289
|
-
maxRetries: number,
|
|
290
|
-
): string {
|
|
291
|
-
const missing: string[] = [];
|
|
292
|
-
if (!state.proposal && !state.splitProposal) {
|
|
293
|
-
missing.push("commit proposal (propose_commit or split_commit)");
|
|
294
|
-
}
|
|
295
|
-
if (requireChangelog && !state.changelogProposal) {
|
|
296
|
-
missing.push("changelog entries (propose_changelog)");
|
|
297
|
-
}
|
|
298
|
-
return `<system-reminder>
|
|
299
|
-
CRITICAL: You must call the required tools before finishing.
|
|
300
|
-
|
|
301
|
-
Missing: ${missing.join(", ") || "none"}.
|
|
302
|
-
Reminder ${retryCount} of ${maxRetries}.
|
|
303
|
-
|
|
304
|
-
Call the missing tool(s) now.
|
|
305
|
-
</system-reminder>`;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
function truncateToolArg(value: string): string {
|
|
309
|
-
if (value.length <= 40) return value;
|
|
310
|
-
return `${value.slice(0, 39)}…`;
|
|
311
|
-
}
|