@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.
Files changed (303) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/package.json +21 -70
  3. package/scripts/format-prompts.ts +1 -3
  4. package/src/cli/args.ts +2 -7
  5. package/src/cli/config-cli.ts +1 -1
  6. package/src/cli/plugin-cli.ts +1 -1
  7. package/src/cli/setup-cli.ts +1 -1
  8. package/src/cli/update-cli.ts +1 -1
  9. package/src/cli/web-search-cli.ts +1 -1
  10. package/src/cli.ts +0 -1
  11. package/src/commands/config.ts +1 -1
  12. package/src/commands/grep.ts +1 -1
  13. package/src/commands/jupyter.ts +1 -1
  14. package/src/commands/plugin.ts +1 -1
  15. package/src/commands/setup.ts +1 -1
  16. package/src/commands/shell.ts +1 -1
  17. package/src/commands/ssh.ts +1 -1
  18. package/src/commands/stats.ts +1 -1
  19. package/src/commands/update.ts +1 -1
  20. package/src/config/model-registry.ts +3 -4
  21. package/src/config/model-resolver.ts +36 -9
  22. package/src/config/prompt-templates.ts +1 -9
  23. package/src/config/settings-schema.ts +32 -88
  24. package/src/config/settings.ts +3 -4
  25. package/src/debug/index.ts +1 -1
  26. package/src/debug/log-formatting.ts +1 -1
  27. package/src/debug/log-viewer.ts +2 -2
  28. package/src/discovery/helpers.ts +13 -3
  29. package/src/exa/index.ts +1 -35
  30. package/src/exa/render.ts +30 -190
  31. package/src/export/html/index.ts +1 -1
  32. package/src/extensibility/custom-tools/loader.ts +1 -1
  33. package/src/extensibility/custom-tools/types.ts +5 -1
  34. package/src/extensibility/custom-tools/wrapper.ts +1 -1
  35. package/src/extensibility/extensions/runner.ts +1 -1
  36. package/src/extensibility/extensions/types.ts +1 -1
  37. package/src/extensibility/extensions/wrapper.ts +7 -15
  38. package/src/extensibility/hooks/runner.ts +1 -1
  39. package/src/extensibility/hooks/types.ts +1 -1
  40. package/src/extensibility/plugins/doctor.ts +1 -1
  41. package/src/index.ts +13 -13
  42. package/src/lsp/index.ts +77 -24
  43. package/src/lsp/render.ts +34 -583
  44. package/src/lsp/types.ts +3 -3
  45. package/src/lsp/utils.ts +1 -1
  46. package/src/main.ts +1 -1
  47. package/src/mcp/tool-bridge.ts +1 -24
  48. package/src/modes/components/assistant-message.ts +7 -7
  49. package/src/modes/components/bash-execution.ts +50 -112
  50. package/src/modes/components/bordered-loader.ts +1 -1
  51. package/src/modes/components/branch-summary-message.ts +16 -10
  52. package/src/modes/components/compaction-summary-message.ts +20 -12
  53. package/src/modes/components/context-group.ts +106 -0
  54. package/src/modes/components/custom-message.ts +4 -5
  55. package/src/modes/components/diff.ts +2 -2
  56. package/src/modes/components/dynamic-border.ts +1 -1
  57. package/src/modes/components/extensions/extension-dashboard.ts +1 -1
  58. package/src/modes/components/extensions/extension-list.ts +1 -1
  59. package/src/modes/components/extensions/inspector-panel.ts +1 -1
  60. package/src/modes/components/footer.ts +2 -2
  61. package/src/modes/components/history-search.ts +1 -1
  62. package/src/modes/components/hook-editor.ts +1 -1
  63. package/src/modes/components/hook-input.ts +1 -1
  64. package/src/modes/components/hook-message.ts +4 -5
  65. package/src/modes/components/hook-selector.ts +1 -1
  66. package/src/modes/components/index.ts +0 -2
  67. package/src/modes/components/keybinding-hints.ts +1 -1
  68. package/src/modes/components/login-dialog.ts +1 -1
  69. package/src/modes/components/mcp-add-wizard.ts +1 -1
  70. package/src/modes/components/model-selector.ts +1 -1
  71. package/src/modes/components/oauth-selector.ts +1 -1
  72. package/src/modes/components/plugin-settings.ts +1 -1
  73. package/src/modes/components/python-execution.ts +51 -91
  74. package/src/modes/components/queue-mode-selector.ts +1 -1
  75. package/src/modes/components/session-selector.ts +1 -1
  76. package/src/modes/components/settings-defs.ts +5 -10
  77. package/src/modes/components/settings-selector.ts +1 -1
  78. package/src/modes/components/show-images-selector.ts +1 -1
  79. package/src/modes/components/skill-message.ts +4 -4
  80. package/src/modes/components/status-line/segments.ts +2 -2
  81. package/src/modes/components/status-line/separators.ts +1 -1
  82. package/src/modes/components/status-line-segment-editor.ts +1 -1
  83. package/src/modes/components/status-line.ts +1 -1
  84. package/src/modes/components/theme-selector.ts +1 -1
  85. package/src/modes/components/thinking-selector.ts +1 -1
  86. package/src/modes/components/todo-display.ts +2 -4
  87. package/src/modes/components/todo-reminder.ts +4 -4
  88. package/src/modes/components/tool-execution.ts +118 -440
  89. package/src/modes/components/tool-image-display.ts +107 -0
  90. package/src/modes/components/tree-selector.ts +2 -2
  91. package/src/modes/components/ttsr-notification.ts +4 -17
  92. package/src/modes/components/user-message-selector.ts +1 -1
  93. package/src/modes/components/user-message.ts +9 -10
  94. package/src/modes/components/welcome.ts +1 -1
  95. package/src/modes/controllers/command-controller.ts +1 -1
  96. package/src/modes/controllers/event-controller.ts +58 -187
  97. package/src/modes/controllers/extension-ui-controller.ts +1 -1
  98. package/src/modes/controllers/input-controller.ts +3 -1
  99. package/src/modes/controllers/mcp-command-controller.ts +1 -1
  100. package/src/modes/controllers/selector-controller.ts +3 -26
  101. package/src/modes/controllers/ssh-command-controller.ts +1 -1
  102. package/src/modes/interactive-mode.ts +3 -7
  103. package/src/modes/print-mode.ts +5 -5
  104. package/src/modes/rpc/rpc-mode.ts +1 -1
  105. package/src/modes/types.ts +1 -2
  106. package/src/modes/utils/ui-helpers.ts +34 -32
  107. package/src/patch/edit-tool.ts +742 -0
  108. package/src/patch/index.ts +32 -898
  109. package/src/patch/schemas.ts +208 -0
  110. package/src/patch/shared.ts +83 -151
  111. package/src/prompts/agents/explore.md +22 -37
  112. package/src/prompts/agents/init.md +1 -1
  113. package/src/prompts/agents/librarian.md +29 -20
  114. package/src/prompts/agents/oracle.md +9 -2
  115. package/src/prompts/agents/reviewer.md +14 -48
  116. package/src/prompts/agents/task.md +16 -8
  117. package/src/prompts/compaction/branch-summary.md +4 -1
  118. package/src/prompts/compaction/compaction-summary.md +4 -1
  119. package/src/prompts/system/subagent-system-prompt.md +1 -1
  120. package/src/prompts/system/system-prompt.md +162 -178
  121. package/src/prompts/system/verification-reminder.md +6 -0
  122. package/src/sdk.ts +0 -9
  123. package/src/session/agent-session.ts +244 -1459
  124. package/src/session/model-controller.ts +406 -0
  125. package/src/session/retry-utils.ts +71 -0
  126. package/src/session/session-manager.ts +22 -186
  127. package/src/session/session-types.ts +312 -0
  128. package/src/session/stats.ts +387 -0
  129. package/src/session/streaming-edit.ts +258 -0
  130. package/src/session/ttsr.ts +213 -0
  131. package/src/slash-commands/builtin-registry.ts +0 -8
  132. package/src/stt/recorder.ts +2 -2
  133. package/src/system-prompt.ts +1 -14
  134. package/src/task/agents.ts +7 -33
  135. package/src/task/executor.ts +50 -438
  136. package/src/task/index.ts +104 -71
  137. package/src/task/progress-tracker.ts +390 -0
  138. package/src/task/render.ts +371 -187
  139. package/src/task/subprocess-tool-registry.ts +1 -1
  140. package/src/task/types.ts +14 -47
  141. package/src/tools/ask.ts +31 -42
  142. package/src/tools/bash-interactive.ts +2 -2
  143. package/src/tools/bash-interceptor.ts +2 -2
  144. package/src/tools/bash-normalize.ts +1 -1
  145. package/src/tools/bash-skill-urls.ts +2 -2
  146. package/src/tools/bash.ts +87 -136
  147. package/src/tools/browser.ts +54 -84
  148. package/src/tools/create-tools.ts +186 -0
  149. package/src/tools/default-renderer.ts +104 -0
  150. package/src/tools/explore.ts +11 -10
  151. package/src/tools/fetch.ts +24 -114
  152. package/src/tools/find.ts +48 -132
  153. package/src/tools/gemini-image.ts +5 -15
  154. package/src/tools/github.ts +450 -0
  155. package/src/tools/grep.ts +43 -179
  156. package/src/tools/index.ts +35 -198
  157. package/src/tools/json-tree.ts +3 -3
  158. package/src/tools/librarian.ts +18 -18
  159. package/src/tools/list-limit.ts +2 -2
  160. package/src/tools/notebook.ts +35 -87
  161. package/src/tools/oracle.ts +25 -25
  162. package/src/tools/output-meta.ts +89 -4
  163. package/src/tools/output-utils.ts +2 -2
  164. package/src/tools/python.ts +86 -637
  165. package/src/tools/read.ts +36 -119
  166. package/src/tools/reviewer-tool.ts +19 -21
  167. package/src/tools/search-code.ts +128 -0
  168. package/src/tools/ssh.ts +67 -126
  169. package/src/tools/subagent-tool.ts +197 -123
  170. package/src/tools/todo-write.ts +15 -31
  171. package/src/tools/tool-errors.ts +0 -30
  172. package/src/tools/undo-edit.ts +30 -67
  173. package/src/tools/write.ts +78 -127
  174. package/src/tui/code-cell.ts +4 -4
  175. package/src/tui/file-list.ts +2 -2
  176. package/src/tui/output-block.ts +1 -1
  177. package/src/tui/status-line.ts +1 -1
  178. package/src/tui/tree-list.ts +2 -2
  179. package/src/tui/types.ts +1 -1
  180. package/src/tui/utils.ts +1 -1
  181. package/src/{tools → ui}/render-utils.ts +87 -126
  182. package/src/utils/external-editor.ts +4 -4
  183. package/src/utils/file-mentions.ts +1 -1
  184. package/src/utils/index.ts +30 -0
  185. package/src/utils/tools-manager.ts +9 -19
  186. package/src/web/github-client.ts +290 -0
  187. package/src/web/scrapers/github.ts +11 -62
  188. package/src/web/search/auth.ts +1 -3
  189. package/src/web/search/index.ts +82 -46
  190. package/src/web/search/provider.ts +11 -16
  191. package/src/web/search/providers/grep.ts +160 -0
  192. package/src/web/search/render.ts +48 -235
  193. package/src/web/search/types.ts +1 -1
  194. package/src/commands/commit.ts +0 -36
  195. package/src/commit/agentic/agent.ts +0 -311
  196. package/src/commit/agentic/fallback.ts +0 -96
  197. package/src/commit/agentic/index.ts +0 -359
  198. package/src/commit/agentic/prompts/analyze-file.md +0 -22
  199. package/src/commit/agentic/prompts/session-user.md +0 -25
  200. package/src/commit/agentic/prompts/split-confirm.md +0 -1
  201. package/src/commit/agentic/prompts/system.md +0 -38
  202. package/src/commit/agentic/state.ts +0 -69
  203. package/src/commit/agentic/tools/analyze-file.ts +0 -118
  204. package/src/commit/agentic/tools/git-file-diff.ts +0 -194
  205. package/src/commit/agentic/tools/git-hunk.ts +0 -50
  206. package/src/commit/agentic/tools/git-overview.ts +0 -84
  207. package/src/commit/agentic/tools/index.ts +0 -56
  208. package/src/commit/agentic/tools/propose-changelog.ts +0 -128
  209. package/src/commit/agentic/tools/propose-commit.ts +0 -154
  210. package/src/commit/agentic/tools/recent-commits.ts +0 -81
  211. package/src/commit/agentic/tools/split-commit.ts +0 -280
  212. package/src/commit/agentic/topo-sort.ts +0 -44
  213. package/src/commit/agentic/trivial.ts +0 -51
  214. package/src/commit/agentic/validation.ts +0 -200
  215. package/src/commit/analysis/conventional.ts +0 -165
  216. package/src/commit/analysis/index.ts +0 -4
  217. package/src/commit/analysis/scope.ts +0 -242
  218. package/src/commit/analysis/summary.ts +0 -112
  219. package/src/commit/analysis/validation.ts +0 -66
  220. package/src/commit/changelog/detect.ts +0 -37
  221. package/src/commit/changelog/generate.ts +0 -110
  222. package/src/commit/changelog/index.ts +0 -234
  223. package/src/commit/changelog/parse.ts +0 -44
  224. package/src/commit/cli.ts +0 -93
  225. package/src/commit/git/diff.ts +0 -148
  226. package/src/commit/git/errors.ts +0 -9
  227. package/src/commit/git/index.ts +0 -211
  228. package/src/commit/git/operations.ts +0 -54
  229. package/src/commit/index.ts +0 -5
  230. package/src/commit/map-reduce/index.ts +0 -64
  231. package/src/commit/map-reduce/map-phase.ts +0 -178
  232. package/src/commit/map-reduce/reduce-phase.ts +0 -145
  233. package/src/commit/map-reduce/utils.ts +0 -9
  234. package/src/commit/message.ts +0 -11
  235. package/src/commit/model-selection.ts +0 -69
  236. package/src/commit/pipeline.ts +0 -243
  237. package/src/commit/prompts/analysis-system.md +0 -148
  238. package/src/commit/prompts/analysis-user.md +0 -38
  239. package/src/commit/prompts/changelog-system.md +0 -50
  240. package/src/commit/prompts/changelog-user.md +0 -18
  241. package/src/commit/prompts/file-observer-system.md +0 -24
  242. package/src/commit/prompts/file-observer-user.md +0 -8
  243. package/src/commit/prompts/reduce-system.md +0 -50
  244. package/src/commit/prompts/reduce-user.md +0 -17
  245. package/src/commit/prompts/summary-retry.md +0 -3
  246. package/src/commit/prompts/summary-system.md +0 -38
  247. package/src/commit/prompts/summary-user.md +0 -13
  248. package/src/commit/prompts/types-description.md +0 -2
  249. package/src/commit/types.ts +0 -109
  250. package/src/commit/utils/exclusions.ts +0 -42
  251. package/src/mcp/render.ts +0 -123
  252. package/src/modes/components/agent-dashboard.ts +0 -1130
  253. package/src/modes/components/codemode-group.ts +0 -369
  254. package/src/modes/components/read-tool-group.ts +0 -119
  255. package/src/modes/components/visual-truncate.ts +0 -63
  256. package/src/prompts/system/subagent-user-prompt.md +0 -8
  257. package/src/prompts/tools/ask.md +0 -44
  258. package/src/prompts/tools/bash.md +0 -24
  259. package/src/prompts/tools/browser.md +0 -33
  260. package/src/prompts/tools/calculator.md +0 -12
  261. package/src/prompts/tools/explore.md +0 -29
  262. package/src/prompts/tools/fetch.md +0 -16
  263. package/src/prompts/tools/find.md +0 -18
  264. package/src/prompts/tools/gemini-image.md +0 -23
  265. package/src/prompts/tools/grep.md +0 -28
  266. package/src/prompts/tools/hashline.md +0 -232
  267. package/src/prompts/tools/librarian.md +0 -24
  268. package/src/prompts/tools/lsp.md +0 -28
  269. package/src/prompts/tools/oracle.md +0 -26
  270. package/src/prompts/tools/patch.md +0 -74
  271. package/src/prompts/tools/python.md +0 -66
  272. package/src/prompts/tools/read.md +0 -36
  273. package/src/prompts/tools/replace.md +0 -38
  274. package/src/prompts/tools/reviewer.md +0 -41
  275. package/src/prompts/tools/ssh.md +0 -51
  276. package/src/prompts/tools/task-summary.md +0 -28
  277. package/src/prompts/tools/task.md +0 -146
  278. package/src/prompts/tools/todo-write.md +0 -65
  279. package/src/prompts/tools/undo-edit.md +0 -7
  280. package/src/prompts/tools/web-search.md +0 -19
  281. package/src/prompts/tools/write.md +0 -18
  282. package/src/task/batch.ts +0 -102
  283. package/src/task/discovery.ts +0 -126
  284. package/src/task/parallel.ts +0 -84
  285. package/src/task/template.ts +0 -32
  286. package/src/tools/calculator.ts +0 -537
  287. package/src/tools/jtd-to-typescript.ts +0 -198
  288. package/src/tools/renderers.ts +0 -60
  289. package/src/tools/tool-result.ts +0 -86
  290. /package/src/{modes/theme → theme}/dark.json +0 -0
  291. /package/src/{modes/theme → theme}/defaults/dark-catppuccin.json +0 -0
  292. /package/src/{modes/theme → theme}/defaults/dark-dracula.json +0 -0
  293. /package/src/{modes/theme → theme}/defaults/dark-gruvbox.json +0 -0
  294. /package/src/{modes/theme → theme}/defaults/dark-solarized.json +0 -0
  295. /package/src/{modes/theme → theme}/defaults/dark-tokyo-night.json +0 -0
  296. /package/src/{modes/theme → theme}/defaults/index.ts +0 -0
  297. /package/src/{modes/theme → theme}/defaults/light-catppuccin.json +0 -0
  298. /package/src/{modes/theme → theme}/defaults/light-github.json +0 -0
  299. /package/src/{modes/theme → theme}/defaults/light-solarized.json +0 -0
  300. /package/src/{modes/theme → theme}/light.json +0 -0
  301. /package/src/{modes/theme → theme}/mermaid-cache.ts +0 -0
  302. /package/src/{modes/theme → theme}/theme-schema.json +0 -0
  303. /package/src/{modes/theme → theme}/theme.ts +0 -0
@@ -6,25 +6,20 @@ import { Text } from "@nghyane/arcane-tui";
6
6
  import { ptree } from "@nghyane/arcane-utils";
7
7
  import { type Static, Type } from "@sinclair/typebox";
8
8
  import { parse as parseHtml } from "node-html-parser";
9
- import { renderPromptTemplate } from "../config/prompt-templates";
10
9
  import type { RenderResultOptions } from "../extensibility/custom-tools/types";
11
- import { type Theme, theme } from "../modes/theme/theme";
12
- import fetchDescription from "../prompts/tools/fetch.md" with { type: "text" };
13
10
  import { DEFAULT_MAX_BYTES, truncateHead } from "../session/streaming-output";
11
+ import { type Theme, theme } from "../theme/theme";
14
12
  import { renderStatusLine } from "../tui";
15
- import { CachedOutputBlock } from "../tui/output-block";
13
+ import { formatCount } from "../ui/render-utils";
16
14
  import { ensureTool } from "../utils/tools-manager";
17
15
  import { specialHandlers } from "../web/scrapers";
18
16
  import type { RenderResult } from "../web/scrapers/types";
19
17
  import { finalizeOutput, loadPage, MAX_OUTPUT_CHARS } from "../web/scrapers/types";
20
18
  import { convertWithMarkitdown, fetchBinary } from "../web/scrapers/utils";
21
19
  import type { ToolSession } from ".";
22
- import { applyListLimit } from "./list-limit";
23
- import type { OutputMeta } from "./output-meta";
20
+ import { type OutputMeta, toolResult } from "./output-meta";
24
21
  import { allocateOutputArtifact } from "./output-utils";
25
- import { formatExpandHint } from "./render-utils";
26
22
  import { ToolAbortError } from "./tool-errors";
27
- import { toolResult } from "./tool-result";
28
23
 
29
24
  // =============================================================================
30
25
  // Types and Constants
@@ -838,8 +833,8 @@ async function renderUrl(url: string, timeout: number, raw: boolean, signal?: Ab
838
833
 
839
834
  const fetchSchema = Type.Object({
840
835
  url: Type.String({ description: "URL to fetch" }),
841
- timeout: Type.Optional(Type.Number({ description: "Timeout in seconds (default: 20)" })),
842
- raw: Type.Optional(Type.Boolean({ description: "Return raw HTML without transforms" })),
836
+ timeout: Type.Optional(Type.Number({ description: "Timeout in seconds" })),
837
+ raw: Type.Optional(Type.Boolean({ description: "Return raw content without readability extraction" })),
843
838
  });
844
839
 
845
840
  export interface FetchToolDetails {
@@ -852,15 +847,13 @@ export interface FetchToolDetails {
852
847
  meta?: OutputMeta;
853
848
  }
854
849
 
855
- export class FetchTool implements AgentTool<typeof fetchSchema, FetchToolDetails> {
850
+ export class FetchTool implements AgentTool<typeof fetchSchema, FetchToolDetails, Theme> {
856
851
  readonly name = "fetch";
857
852
  readonly label = "Fetch";
858
- readonly description: string;
853
+ description = "Fetch a URL and return its content";
859
854
  readonly parameters = fetchSchema;
860
855
 
861
- constructor(private readonly session: ToolSession) {
862
- this.description = renderPromptTemplate(fetchDescription);
863
- }
856
+ constructor(private readonly session: ToolSession) {}
864
857
 
865
858
  async execute(
866
859
  _toolCallId: string,
@@ -936,11 +929,10 @@ export class FetchTool implements AgentTool<typeof fetchSchema, FetchToolDetails
936
929
 
937
930
  return resultBuilder.done();
938
931
  }
939
- }
940
932
 
941
- // =============================================================================
942
- // TUI Rendering
943
- // =============================================================================
933
+ renderCall = renderFetchCall;
934
+ renderResult = renderFetchResult;
935
+ }
944
936
 
945
937
  /** Truncate text to max length with ellipsis */
946
938
  function truncate(text: string, maxLen: number, ellipsis: string): string {
@@ -965,7 +957,7 @@ function countNonEmptyLines(text: string): number {
965
957
  }
966
958
 
967
959
  /** Render fetch call (URL preview) */
968
- export function renderFetchCall(
960
+ function renderFetchCall(
969
961
  args: { url?: string; timeout?: number; raw?: boolean },
970
962
  _options: RenderResultOptions,
971
963
  uiTheme: Theme = theme,
@@ -982,110 +974,28 @@ export function renderFetchCall(
982
974
  }
983
975
 
984
976
  /** Render fetch result with tree-based layout */
985
- export function renderFetchResult(
977
+ function renderFetchResult(
986
978
  result: { content: Array<{ type: string; text?: string }>; details?: FetchToolDetails },
987
- options: RenderResultOptions,
979
+ _options: RenderResultOptions,
988
980
  uiTheme: Theme = theme,
989
981
  ): Component {
990
982
  const details = result.details;
991
-
992
983
  if (!details) {
993
984
  return new Text(uiTheme.fg("error", "No response data"), 0, 0);
994
985
  }
995
986
 
996
987
  const domain = getDomain(details.finalUrl);
997
- const path = truncate(details.finalUrl.replace(/^https?:\/\/[^/]+/, ""), 50, "…");
998
- const hasRedirect = details.url !== details.finalUrl;
999
- const hasNotes = details.notes.length > 0;
1000
- const truncation = details.meta?.truncation;
1001
- const truncated = Boolean(details.truncated || truncation);
1002
-
1003
- const header = renderStatusLine(
1004
- {
1005
- icon: truncated ? "warning" : "success",
1006
- title: "Fetch",
1007
- description: `${domain}${path ? ` ${path}` : ""}`,
1008
- },
1009
- uiTheme,
1010
- );
1011
-
988
+ const truncated = Boolean(details.truncated || details.meta?.truncation);
1012
989
  const contentText = result.content[0]?.text ?? "";
1013
- const contentBody = contentText.includes("---\n\n")
1014
- ? contentText.split("---\n\n").slice(1).join("---\n\n")
1015
- : contentText;
1016
- const lineCount = countNonEmptyLines(contentBody);
1017
- const charCount = contentBody.trim().length;
1018
- const contentLines = contentBody.split("\n").filter(l => l.trim());
1019
-
1020
- const metadataLines: string[] = [
1021
- `${uiTheme.fg("muted", "Content-Type:")} ${details.contentType || "unknown"}`,
1022
- `${uiTheme.fg("muted", "Method:")} ${details.method}`,
1023
- ];
1024
- if (hasRedirect) {
1025
- metadataLines.push(`${uiTheme.fg("muted", "Final URL:")} ${uiTheme.fg("mdLinkUrl", details.finalUrl)}`);
1026
- }
1027
- const lineLabel = `${lineCount} line${lineCount === 1 ? "" : "s"}`;
1028
- metadataLines.push(`${uiTheme.fg("muted", "Lines:")} ${lineLabel}`);
1029
- metadataLines.push(`${uiTheme.fg("muted", "Chars:")} ${charCount}`);
1030
- if (truncated) {
1031
- metadataLines.push(uiTheme.fg("warning", `${uiTheme.status.warning} Output truncated`));
1032
- if (truncation?.artifactId) {
1033
- metadataLines.push(uiTheme.fg("warning", `Full output: artifact://${truncation.artifactId}`));
1034
- }
1035
- }
1036
- if (hasNotes) {
1037
- metadataLines.push(`${uiTheme.fg("muted", "Notes:")} ${details.notes.join("; ")}`);
1038
- }
990
+ const lineCount = countNonEmptyLines(contentText);
1039
991
 
1040
- const outputBlock = new CachedOutputBlock();
1041
- let lastExpanded: boolean | undefined;
1042
- let contentPreviewLines: string[] | undefined;
1043
-
1044
- return {
1045
- render: (width: number) => {
1046
- const { expanded } = options;
1047
-
1048
- if (contentPreviewLines === undefined || lastExpanded !== expanded) {
1049
- const previewLimit = expanded ? 12 : 3;
1050
- const previewList = applyListLimit(contentLines, { headLimit: previewLimit });
1051
- const previewLines = previewList.items.map(line => truncate(line.trimEnd(), 120, "…"));
1052
- const remaining = Math.max(0, contentLines.length - previewLines.length);
1053
- contentPreviewLines =
1054
- previewLines.length > 0
1055
- ? previewLines.map(line => uiTheme.fg("dim", line))
1056
- : [uiTheme.fg("dim", "(no content)")];
1057
- if (remaining > 0) {
1058
- const hint = formatExpandHint(uiTheme, expanded, true);
1059
- contentPreviewLines.push(uiTheme.fg("muted", `… ${remaining} more lines${hint ? ` ${hint}` : ""}`));
1060
- }
1061
- lastExpanded = expanded;
1062
- outputBlock.invalidate();
1063
- }
992
+ const meta: string[] = [];
993
+ if (lineCount > 0) meta.push(formatCount("line", lineCount));
994
+ if (truncated) meta.push(uiTheme.fg("warning", "truncated"));
1064
995
 
1065
- return outputBlock.render(
1066
- {
1067
- header,
1068
- state: truncated ? "warning" : "success",
1069
- sections: [
1070
- { label: uiTheme.fg("toolTitle", "Metadata"), lines: metadataLines },
1071
- { label: uiTheme.fg("toolTitle", "Content Preview"), lines: contentPreviewLines },
1072
- ],
1073
- width,
1074
- applyBg: false,
1075
- },
1076
- uiTheme,
1077
- );
1078
- },
1079
- invalidate: () => {
1080
- outputBlock.invalidate();
1081
- contentPreviewLines = undefined;
1082
- lastExpanded = undefined;
1083
- },
1084
- };
996
+ return new Text(
997
+ renderStatusLine({ icon: truncated ? "warning" : "success", title: "Fetch", description: domain, meta }, uiTheme),
998
+ 0,
999
+ 0,
1000
+ );
1085
1001
  }
1086
-
1087
- export const fetchToolRenderer = {
1088
- renderCall: renderFetchCall,
1089
- renderResult: renderFetchResult,
1090
- mergeCallAndResult: true,
1091
- };
package/src/tools/find.ts CHANGED
@@ -7,32 +7,21 @@ import { Text } from "@nghyane/arcane-tui";
7
7
  import { isEnoent, untilAborted } from "@nghyane/arcane-utils";
8
8
  import type { Static } from "@sinclair/typebox";
9
9
  import { Type } from "@sinclair/typebox";
10
- import { renderPromptTemplate } from "../config/prompt-templates";
11
10
  import type { RenderResultOptions } from "../extensibility/custom-tools/types";
12
- import type { Theme } from "../modes/theme/theme";
13
- import findDescription from "../prompts/tools/find.md" with { type: "text" };
14
11
  import { type TruncationResult, truncateHead } from "../session/streaming-output";
15
- import {
16
- Ellipsis,
17
- Hasher,
18
- type RenderCache,
19
- renderFileList,
20
- renderStatusLine,
21
- renderTreeList,
22
- truncateToWidth,
23
- } from "../tui";
12
+ import type { Theme } from "../theme/theme";
13
+ import { renderStatusLine } from "../tui";
14
+ import { formatCount, formatEmptyMessage, formatErrorMessage } from "../ui/render-utils";
24
15
  import type { ToolSession } from ".";
25
16
  import { applyListLimit } from "./list-limit";
26
- import type { OutputMeta } from "./output-meta";
17
+ import { type OutputMeta, toolResult } from "./output-meta";
27
18
  import { resolveToCwd } from "./path-utils";
28
- import { formatCount, formatEmptyMessage, formatErrorMessage, PREVIEW_LIMITS } from "./render-utils";
29
19
  import { ToolAbortError, ToolError, throwIfAborted } from "./tool-errors";
30
- import { toolResult } from "./tool-result";
31
20
 
32
21
  const findSchema = Type.Object({
33
- pattern: Type.String({ description: "Glob pattern, e.g. '*.ts', 'src/**/*.json', 'lib/*.tsx'" }),
34
- hidden: Type.Optional(Type.Boolean({ description: "Include hidden files and directories (default: true)" })),
35
- limit: Type.Optional(Type.Number({ description: "Max results (default: 1000)" })),
22
+ pattern: Type.String({ description: "Glob pattern to match file paths" }),
23
+ hidden: Type.Optional(Type.Boolean({ description: "Include hidden files and directories" })),
24
+ limit: Type.Optional(Type.Number({ description: "Max number of results to return" })),
36
25
  });
37
26
 
38
27
  export type FindToolInput = Static<typeof findSchema>;
@@ -122,10 +111,10 @@ export interface FindToolOptions {
122
111
  operations?: FindOperations;
123
112
  }
124
113
 
125
- export class FindTool implements AgentTool<typeof findSchema, FindToolDetails> {
114
+ export class FindTool implements AgentTool<typeof findSchema, FindToolDetails, Theme> {
126
115
  readonly name = "find";
127
116
  readonly label = "Find";
128
- readonly description: string;
117
+ description = "Find files by glob pattern";
129
118
  readonly parameters = findSchema;
130
119
 
131
120
  readonly #customOps?: FindOperations;
@@ -135,7 +124,6 @@ export class FindTool implements AgentTool<typeof findSchema, FindToolDetails> {
135
124
  options?: FindToolOptions,
136
125
  ) {
137
126
  this.#customOps = options?.operations;
138
- this.description = renderPromptTemplate(findDescription);
139
127
  }
140
128
 
141
129
  async execute(
@@ -392,21 +380,7 @@ export class FindTool implements AgentTool<typeof findSchema, FindToolDetails> {
392
380
  return resultBuilder.done();
393
381
  });
394
382
  }
395
- }
396
-
397
- // =============================================================================
398
- // TUI Renderer
399
- // =============================================================================
400
383
 
401
- interface FindRenderArgs {
402
- pattern: string;
403
- limit?: number;
404
- }
405
-
406
- const COLLAPSED_LIST_LIMIT = PREVIEW_LIMITS.COLLAPSED_ITEMS;
407
-
408
- export const findToolRenderer = {
409
- inline: true,
410
384
  renderCall(args: FindRenderArgs, _options: RenderResultOptions, uiTheme: Theme): Component {
411
385
  const meta: string[] = [];
412
386
  if (args.limit !== undefined) meta.push(`limit:${args.limit}`);
@@ -416,11 +390,11 @@ export const findToolRenderer = {
416
390
  uiTheme,
417
391
  );
418
392
  return new Text(text, 0, 0);
419
- },
393
+ }
420
394
 
421
395
  renderResult(
422
396
  result: { content: Array<{ type: string; text?: string }>; details?: FindToolDetails; isError?: boolean },
423
- options: RenderResultOptions,
397
+ _options: RenderResultOptions,
424
398
  uiTheme: Theme,
425
399
  args?: FindRenderArgs,
426
400
  ): Component {
@@ -431,110 +405,52 @@ export const findToolRenderer = {
431
405
  return new Text(formatErrorMessage(errorText, uiTheme), 0, 0);
432
406
  }
433
407
 
434
- const hasDetailedData = details?.fileCount !== undefined;
435
- const textContent = result.content?.find(c => c.type === "text")?.text;
408
+ const fileCount = details?.fileCount ?? 0;
436
409
 
437
- if (!hasDetailedData) {
438
- if (
439
- !textContent ||
440
- textContent.includes("No files matching") ||
441
- textContent.includes("No files found") ||
442
- textContent.trim() === ""
443
- ) {
410
+ if (fileCount === 0) {
411
+ const textContent = result.content?.find(c => c.type === "text")?.text;
412
+ if (!textContent || textContent.includes("No files") || textContent.trim() === "") {
444
413
  return new Text(formatEmptyMessage("No files found", uiTheme), 0, 0);
445
414
  }
446
-
447
415
  const lines = textContent.split("\n").filter(l => l.trim());
448
- const header = renderStatusLine(
449
- {
450
- icon: "success",
451
- title: "Find",
452
- description: args?.pattern,
453
- meta: [formatCount("file", lines.length)],
454
- },
455
- uiTheme,
416
+ return new Text(
417
+ renderStatusLine(
418
+ {
419
+ icon: "success",
420
+ title: "Find",
421
+ description: args?.pattern,
422
+ meta: [formatCount("file", lines.length)],
423
+ },
424
+ uiTheme,
425
+ ),
426
+ 0,
427
+ 0,
456
428
  );
457
- let cached: RenderCache | undefined;
458
- return {
459
- render(width: number): string[] {
460
- const { expanded } = options;
461
- const key = new Hasher().bool(expanded).u32(width).digest();
462
- if (cached?.key === key) return cached.lines;
463
- const listLines = renderTreeList(
464
- {
465
- items: lines,
466
- expanded,
467
- maxCollapsed: COLLAPSED_LIST_LIMIT,
468
- itemType: "file",
469
- renderItem: line => uiTheme.fg("accent", line),
470
- },
471
- uiTheme,
472
- );
473
- const result = [header, ...listLines].map(l => truncateToWidth(l, width, Ellipsis.Omit));
474
- cached = { key, lines: result };
475
- return result;
476
- },
477
- invalidate() {
478
- cached = undefined;
479
- },
480
- };
481
429
  }
482
430
 
483
- const fileCount = details?.fileCount ?? 0;
484
- const truncation = details?.truncation ?? details?.meta?.truncation;
485
- const limits = details?.meta?.limits;
486
- const truncated = Boolean(details?.truncated || truncation || details?.resultLimitReached || limits?.resultLimit);
487
- const files = details?.files ?? [];
488
-
489
- if (fileCount === 0) {
490
- const header = renderStatusLine(
491
- { icon: "warning", title: "Find", description: args?.pattern, meta: ["0 files"] },
492
- uiTheme,
493
- );
494
- return new Text([header, formatEmptyMessage("No files found", uiTheme)].join("\n"), 0, 0);
495
- }
431
+ const truncated = Boolean(
432
+ details?.truncated ||
433
+ details?.truncation ||
434
+ details?.meta?.truncation ||
435
+ details?.resultLimitReached ||
436
+ details?.meta?.limits?.resultLimit,
437
+ );
496
438
  const meta: string[] = [formatCount("file", fileCount)];
497
439
  if (details?.scopePath) meta.push(`in ${details.scopePath}`);
498
440
  if (truncated) meta.push(uiTheme.fg("warning", "truncated"));
499
- const header = renderStatusLine(
500
- { icon: truncated ? "warning" : "success", title: "Find", description: args?.pattern, meta },
501
- uiTheme,
502
- );
503
441
 
504
- const truncationReasons: string[] = [];
505
- if (details?.resultLimitReached) truncationReasons.push(`limit ${details.resultLimitReached} results`);
506
- if (limits?.resultLimit) truncationReasons.push(`limit ${limits.resultLimit.reached} results`);
507
- if (truncation) truncationReasons.push(truncation.truncatedBy === "lines" ? "line limit" : "size limit");
508
- const artifactId = truncation && "artifactId" in truncation ? truncation.artifactId : undefined;
509
- if (artifactId) truncationReasons.push(`full output: artifact://${artifactId}`);
510
-
511
- const extraLines: string[] = [];
512
- if (truncationReasons.length > 0) {
513
- extraLines.push(uiTheme.fg("warning", `truncated: ${truncationReasons.join(", ")}`));
514
- }
442
+ return new Text(
443
+ renderStatusLine(
444
+ { icon: truncated ? "warning" : "success", title: "Find", description: args?.pattern, meta },
445
+ uiTheme,
446
+ ),
447
+ 0,
448
+ 0,
449
+ );
450
+ }
451
+ }
515
452
 
516
- let cached: RenderCache | undefined;
517
- return {
518
- render(width: number): string[] {
519
- const { expanded } = options;
520
- const key = new Hasher().bool(expanded).u32(width).digest();
521
- if (cached?.key === key) return cached.lines;
522
- const fileLines = renderFileList(
523
- {
524
- files: files.map(entry => ({ path: entry, isDirectory: entry.endsWith("/") })),
525
- expanded,
526
- maxCollapsed: COLLAPSED_LIST_LIMIT,
527
- },
528
- uiTheme,
529
- );
530
- const result = [header, ...fileLines, ...extraLines].map(l => truncateToWidth(l, width, Ellipsis.Omit));
531
- cached = { key, lines: result };
532
- return result;
533
- },
534
- invalidate() {
535
- cached = undefined;
536
- },
537
- };
538
- },
539
- mergeCallAndResult: true,
540
- };
453
+ interface FindRenderArgs {
454
+ pattern: string;
455
+ limit?: number;
456
+ }
@@ -4,9 +4,7 @@ import { getAntigravityHeaders, getEnvApiKey, StringEnum } from "@nghyane/arcane
4
4
  import { $env, ptree, readSseJson, Snowflake, untilAborted } from "@nghyane/arcane-utils";
5
5
  import { type Static, Type } from "@sinclair/typebox";
6
6
  import type { ModelRegistry } from "../config/model-registry";
7
- import { renderPromptTemplate } from "../config/prompt-templates";
8
7
  import type { CustomTool } from "../extensibility/custom-tools/types";
9
- import geminiImageDescription from "../prompts/tools/gemini-image.md" with { type: "text" };
10
8
  import { detectSupportedImageMimeTypeFromFile } from "../utils/mime";
11
9
  import { resolveReadPath } from "./path-utils";
12
10
 
@@ -115,9 +113,9 @@ const baseImageSchema = Type.Object(
115
113
  { additionalProperties: false },
116
114
  );
117
115
 
118
- export const geminiImageSchema = baseImageSchema;
119
- export type GeminiImageParams = Static<typeof geminiImageSchema>;
120
- export type GeminiResponseModality = Static<typeof responseModalitySchema>;
116
+ const geminiImageSchema = baseImageSchema;
117
+ type GeminiImageParams = Static<typeof geminiImageSchema>;
118
+ type GeminiResponseModality = Static<typeof responseModalitySchema>;
121
119
 
122
120
  /**
123
121
  * Assembles a structured prompt from the provided parameters.
@@ -612,10 +610,10 @@ async function parseAntigravitySseForImage(response: Response, signal?: AbortSig
612
610
  return { images, text: textParts, usage };
613
611
  }
614
612
 
615
- export const geminiImageTool: CustomTool<typeof geminiImageSchema, GeminiImageToolDetails> = {
613
+ const geminiImageTool: CustomTool<typeof geminiImageSchema, GeminiImageToolDetails> = {
616
614
  name: "generate_image",
617
615
  label: "GenerateImage",
618
- description: renderPromptTemplate(geminiImageDescription),
616
+ description: "",
619
617
  parameters: geminiImageSchema,
620
618
  async execute(_toolCallId, params, _onUpdate, ctx, signal) {
621
619
  return untilAborted(signal, async () => {
@@ -897,11 +895,3 @@ export async function getGeminiImageTools(): Promise<
897
895
  if (!apiKey) return [];
898
896
  return [geminiImageTool];
899
897
  }
900
-
901
- export async function getGeminiImageToolsWithRegistry(
902
- modelRegistry: ModelRegistry,
903
- ): Promise<Array<CustomTool<typeof geminiImageSchema, GeminiImageToolDetails>>> {
904
- const apiKey = await findImageApiKey(modelRegistry);
905
- if (!apiKey) return [];
906
- return [geminiImageTool];
907
- }