moderado 0.3.0

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 (275) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +208 -0
  3. package/dist/args.d.ts +26 -0
  4. package/dist/args.d.ts.map +1 -0
  5. package/dist/args.js +108 -0
  6. package/dist/args.js.map +1 -0
  7. package/dist/commands/chat.d.ts +121 -0
  8. package/dist/commands/chat.d.ts.map +1 -0
  9. package/dist/commands/chat.js +1484 -0
  10. package/dist/commands/chat.js.map +1 -0
  11. package/dist/commands/doctor.d.ts +3 -0
  12. package/dist/commands/doctor.d.ts.map +1 -0
  13. package/dist/commands/doctor.js +61 -0
  14. package/dist/commands/doctor.js.map +1 -0
  15. package/dist/commands/init.d.ts +27 -0
  16. package/dist/commands/init.d.ts.map +1 -0
  17. package/dist/commands/init.js +172 -0
  18. package/dist/commands/init.js.map +1 -0
  19. package/dist/commands/interactive_menu.d.ts +3 -0
  20. package/dist/commands/interactive_menu.d.ts.map +1 -0
  21. package/dist/commands/interactive_menu.js +98 -0
  22. package/dist/commands/interactive_menu.js.map +1 -0
  23. package/dist/commands/models.d.ts +8 -0
  24. package/dist/commands/models.d.ts.map +1 -0
  25. package/dist/commands/models.js +81 -0
  26. package/dist/commands/models.js.map +1 -0
  27. package/dist/commands/run.d.ts +3 -0
  28. package/dist/commands/run.d.ts.map +1 -0
  29. package/dist/commands/run.js +140 -0
  30. package/dist/commands/run.js.map +1 -0
  31. package/dist/config.d.ts +44 -0
  32. package/dist/config.d.ts.map +1 -0
  33. package/dist/config.js +195 -0
  34. package/dist/config.js.map +1 -0
  35. package/dist/credentials.d.ts +14 -0
  36. package/dist/credentials.d.ts.map +1 -0
  37. package/dist/credentials.js +23 -0
  38. package/dist/credentials.js.map +1 -0
  39. package/dist/diagnostic_log.d.ts +2 -0
  40. package/dist/diagnostic_log.d.ts.map +1 -0
  41. package/dist/diagnostic_log.js +21 -0
  42. package/dist/diagnostic_log.js.map +1 -0
  43. package/dist/index.d.ts +3 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +83 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/model_pricing.d.ts +4 -0
  48. package/dist/model_pricing.d.ts.map +1 -0
  49. package/dist/model_pricing.js +10 -0
  50. package/dist/model_pricing.js.map +1 -0
  51. package/dist/sessions.d.ts +203 -0
  52. package/dist/sessions.d.ts.map +1 -0
  53. package/dist/sessions.js +82 -0
  54. package/dist/sessions.js.map +1 -0
  55. package/dist/ui/box.d.ts +14 -0
  56. package/dist/ui/box.d.ts.map +1 -0
  57. package/dist/ui/box.js +52 -0
  58. package/dist/ui/box.js.map +1 -0
  59. package/dist/ui/file_mentions.d.ts +38 -0
  60. package/dist/ui/file_mentions.d.ts.map +1 -0
  61. package/dist/ui/file_mentions.js +119 -0
  62. package/dist/ui/file_mentions.js.map +1 -0
  63. package/dist/ui/help_modal.d.ts +2 -0
  64. package/dist/ui/help_modal.d.ts.map +1 -0
  65. package/dist/ui/help_modal.js +101 -0
  66. package/dist/ui/help_modal.js.map +1 -0
  67. package/dist/ui/model_selector.d.ts +48 -0
  68. package/dist/ui/model_selector.d.ts.map +1 -0
  69. package/dist/ui/model_selector.js +829 -0
  70. package/dist/ui/model_selector.js.map +1 -0
  71. package/dist/ui/popup.d.ts +78 -0
  72. package/dist/ui/popup.d.ts.map +1 -0
  73. package/dist/ui/popup.js +274 -0
  74. package/dist/ui/popup.js.map +1 -0
  75. package/dist/ui/prompt.d.ts +21 -0
  76. package/dist/ui/prompt.d.ts.map +1 -0
  77. package/dist/ui/prompt.js +128 -0
  78. package/dist/ui/prompt.js.map +1 -0
  79. package/dist/ui/provider_connect.d.ts +33 -0
  80. package/dist/ui/provider_connect.d.ts.map +1 -0
  81. package/dist/ui/provider_connect.js +175 -0
  82. package/dist/ui/provider_connect.js.map +1 -0
  83. package/dist/ui/renderer.d.ts +19 -0
  84. package/dist/ui/renderer.d.ts.map +1 -0
  85. package/dist/ui/renderer.js +147 -0
  86. package/dist/ui/renderer.js.map +1 -0
  87. package/dist/ui/session_screen.d.ts +32 -0
  88. package/dist/ui/session_screen.d.ts.map +1 -0
  89. package/dist/ui/session_screen.js +148 -0
  90. package/dist/ui/session_screen.js.map +1 -0
  91. package/dist/ui/session_terminal.d.ts +46 -0
  92. package/dist/ui/session_terminal.d.ts.map +1 -0
  93. package/dist/ui/session_terminal.js +342 -0
  94. package/dist/ui/session_terminal.js.map +1 -0
  95. package/dist/ui/terminal_approval.d.ts +14 -0
  96. package/dist/ui/terminal_approval.d.ts.map +1 -0
  97. package/dist/ui/terminal_approval.js +98 -0
  98. package/dist/ui/terminal_approval.js.map +1 -0
  99. package/dist/ui/welcome.d.ts +130 -0
  100. package/dist/ui/welcome.d.ts.map +1 -0
  101. package/dist/ui/welcome.js +990 -0
  102. package/dist/ui/welcome.js.map +1 -0
  103. package/dist/vendor/contracts/approvals.d.ts +91 -0
  104. package/dist/vendor/contracts/approvals.d.ts.map +1 -0
  105. package/dist/vendor/contracts/approvals.js +22 -0
  106. package/dist/vendor/contracts/approvals.js.map +1 -0
  107. package/dist/vendor/contracts/events.d.ts +1215 -0
  108. package/dist/vendor/contracts/events.d.ts.map +1 -0
  109. package/dist/vendor/contracts/events.js +94 -0
  110. package/dist/vendor/contracts/events.js.map +1 -0
  111. package/dist/vendor/contracts/index.d.ts +7 -0
  112. package/dist/vendor/contracts/index.d.ts.map +1 -0
  113. package/dist/vendor/contracts/index.js +7 -0
  114. package/dist/vendor/contracts/index.js.map +1 -0
  115. package/dist/vendor/contracts/messages.d.ts +181 -0
  116. package/dist/vendor/contracts/messages.d.ts.map +1 -0
  117. package/dist/vendor/contracts/messages.js +40 -0
  118. package/dist/vendor/contracts/messages.js.map +1 -0
  119. package/dist/vendor/contracts/models.d.ts +117 -0
  120. package/dist/vendor/contracts/models.d.ts.map +1 -0
  121. package/dist/vendor/contracts/models.js +37 -0
  122. package/dist/vendor/contracts/models.js.map +1 -0
  123. package/dist/vendor/contracts/provider.d.ts +121 -0
  124. package/dist/vendor/contracts/provider.d.ts.map +1 -0
  125. package/dist/vendor/contracts/provider.js +64 -0
  126. package/dist/vendor/contracts/provider.js.map +1 -0
  127. package/dist/vendor/contracts/tools.d.ts +305 -0
  128. package/dist/vendor/contracts/tools.d.ts.map +1 -0
  129. package/dist/vendor/contracts/tools.js +65 -0
  130. package/dist/vendor/contracts/tools.js.map +1 -0
  131. package/dist/vendor/core/agent.d.ts +39 -0
  132. package/dist/vendor/core/agent.d.ts.map +1 -0
  133. package/dist/vendor/core/agent.js +710 -0
  134. package/dist/vendor/core/agent.js.map +1 -0
  135. package/dist/vendor/core/host_event_stream.d.ts +9 -0
  136. package/dist/vendor/core/host_event_stream.d.ts.map +1 -0
  137. package/dist/vendor/core/host_event_stream.js +12 -0
  138. package/dist/vendor/core/host_event_stream.js.map +1 -0
  139. package/dist/vendor/core/index.d.ts +7 -0
  140. package/dist/vendor/core/index.d.ts.map +1 -0
  141. package/dist/vendor/core/index.js +7 -0
  142. package/dist/vendor/core/index.js.map +1 -0
  143. package/dist/vendor/core/policy.d.ts +19 -0
  144. package/dist/vendor/core/policy.d.ts.map +1 -0
  145. package/dist/vendor/core/policy.js +31 -0
  146. package/dist/vendor/core/policy.js.map +1 -0
  147. package/dist/vendor/core/router.d.ts +26 -0
  148. package/dist/vendor/core/router.d.ts.map +1 -0
  149. package/dist/vendor/core/router.js +222 -0
  150. package/dist/vendor/core/router.js.map +1 -0
  151. package/dist/vendor/core/subagent.d.ts +29 -0
  152. package/dist/vendor/core/subagent.d.ts.map +1 -0
  153. package/dist/vendor/core/subagent.js +66 -0
  154. package/dist/vendor/core/subagent.js.map +1 -0
  155. package/dist/vendor/core/think_filter.d.ts +14 -0
  156. package/dist/vendor/core/think_filter.d.ts.map +1 -0
  157. package/dist/vendor/core/think_filter.js +136 -0
  158. package/dist/vendor/core/think_filter.js.map +1 -0
  159. package/dist/vendor/providers/fake/fake_provider.d.ts +16 -0
  160. package/dist/vendor/providers/fake/fake_provider.d.ts.map +1 -0
  161. package/dist/vendor/providers/fake/fake_provider.js +89 -0
  162. package/dist/vendor/providers/fake/fake_provider.js.map +1 -0
  163. package/dist/vendor/providers/index.d.ts +6 -0
  164. package/dist/vendor/providers/index.d.ts.map +1 -0
  165. package/dist/vendor/providers/index.js +6 -0
  166. package/dist/vendor/providers/index.js.map +1 -0
  167. package/dist/vendor/providers/model_discovery.d.ts +28 -0
  168. package/dist/vendor/providers/model_discovery.d.ts.map +1 -0
  169. package/dist/vendor/providers/model_discovery.js +106 -0
  170. package/dist/vendor/providers/model_discovery.js.map +1 -0
  171. package/dist/vendor/providers/nvidia/nvidia_adapter.d.ts +23 -0
  172. package/dist/vendor/providers/nvidia/nvidia_adapter.d.ts.map +1 -0
  173. package/dist/vendor/providers/nvidia/nvidia_adapter.js +197 -0
  174. package/dist/vendor/providers/nvidia/nvidia_adapter.js.map +1 -0
  175. package/dist/vendor/providers/nvidia/sse_parser.d.ts +3 -0
  176. package/dist/vendor/providers/nvidia/sse_parser.d.ts.map +1 -0
  177. package/dist/vendor/providers/nvidia/sse_parser.js +84 -0
  178. package/dist/vendor/providers/nvidia/sse_parser.js.map +1 -0
  179. package/dist/vendor/providers/openai_compatible_adapter.d.ts +10 -0
  180. package/dist/vendor/providers/openai_compatible_adapter.d.ts.map +1 -0
  181. package/dist/vendor/providers/openai_compatible_adapter.js +8 -0
  182. package/dist/vendor/providers/openai_compatible_adapter.js.map +1 -0
  183. package/dist/vendor/tools/checkpoints.d.ts +27 -0
  184. package/dist/vendor/tools/checkpoints.d.ts.map +1 -0
  185. package/dist/vendor/tools/checkpoints.js +145 -0
  186. package/dist/vendor/tools/checkpoints.js.map +1 -0
  187. package/dist/vendor/tools/diagnostics.d.ts +11 -0
  188. package/dist/vendor/tools/diagnostics.d.ts.map +1 -0
  189. package/dist/vendor/tools/diagnostics.js +16 -0
  190. package/dist/vendor/tools/diagnostics.js.map +1 -0
  191. package/dist/vendor/tools/diff.d.ts +7 -0
  192. package/dist/vendor/tools/diff.d.ts.map +1 -0
  193. package/dist/vendor/tools/diff.js +48 -0
  194. package/dist/vendor/tools/diff.js.map +1 -0
  195. package/dist/vendor/tools/errors.d.ts +17 -0
  196. package/dist/vendor/tools/errors.d.ts.map +1 -0
  197. package/dist/vendor/tools/errors.js +33 -0
  198. package/dist/vendor/tools/errors.js.map +1 -0
  199. package/dist/vendor/tools/git_workspace.d.ts +14 -0
  200. package/dist/vendor/tools/git_workspace.d.ts.map +1 -0
  201. package/dist/vendor/tools/git_workspace.js +42 -0
  202. package/dist/vendor/tools/git_workspace.js.map +1 -0
  203. package/dist/vendor/tools/index.d.ts +22 -0
  204. package/dist/vendor/tools/index.d.ts.map +1 -0
  205. package/dist/vendor/tools/index.js +22 -0
  206. package/dist/vendor/tools/index.js.map +1 -0
  207. package/dist/vendor/tools/jail.d.ts +17 -0
  208. package/dist/vendor/tools/jail.d.ts.map +1 -0
  209. package/dist/vendor/tools/jail.js +221 -0
  210. package/dist/vendor/tools/jail.js.map +1 -0
  211. package/dist/vendor/tools/lsp.d.ts +3 -0
  212. package/dist/vendor/tools/lsp.d.ts.map +1 -0
  213. package/dist/vendor/tools/lsp.js +43 -0
  214. package/dist/vendor/tools/lsp.js.map +1 -0
  215. package/dist/vendor/tools/mcp.d.ts +9 -0
  216. package/dist/vendor/tools/mcp.d.ts.map +1 -0
  217. package/dist/vendor/tools/mcp.js +54 -0
  218. package/dist/vendor/tools/mcp.js.map +1 -0
  219. package/dist/vendor/tools/mcp_adapter.d.ts +15 -0
  220. package/dist/vendor/tools/mcp_adapter.d.ts.map +1 -0
  221. package/dist/vendor/tools/mcp_adapter.js +29 -0
  222. package/dist/vendor/tools/mcp_adapter.js.map +1 -0
  223. package/dist/vendor/tools/registry.d.ts +10 -0
  224. package/dist/vendor/tools/registry.d.ts.map +1 -0
  225. package/dist/vendor/tools/registry.js +126 -0
  226. package/dist/vendor/tools/registry.js.map +1 -0
  227. package/dist/vendor/tools/tools/apply_patch.d.ts +3 -0
  228. package/dist/vendor/tools/tools/apply_patch.d.ts.map +1 -0
  229. package/dist/vendor/tools/tools/apply_patch.js +49 -0
  230. package/dist/vendor/tools/tools/apply_patch.js.map +1 -0
  231. package/dist/vendor/tools/tools/edit_file.d.ts +3 -0
  232. package/dist/vendor/tools/tools/edit_file.d.ts.map +1 -0
  233. package/dist/vendor/tools/tools/edit_file.js +71 -0
  234. package/dist/vendor/tools/tools/edit_file.js.map +1 -0
  235. package/dist/vendor/tools/tools/git_diff.d.ts +3 -0
  236. package/dist/vendor/tools/tools/git_diff.d.ts.map +1 -0
  237. package/dist/vendor/tools/tools/git_diff.js +91 -0
  238. package/dist/vendor/tools/tools/git_diff.js.map +1 -0
  239. package/dist/vendor/tools/tools/language_intelligence.d.ts +4 -0
  240. package/dist/vendor/tools/tools/language_intelligence.d.ts.map +1 -0
  241. package/dist/vendor/tools/tools/language_intelligence.js +13 -0
  242. package/dist/vendor/tools/tools/language_intelligence.js.map +1 -0
  243. package/dist/vendor/tools/tools/list_files.d.ts +9 -0
  244. package/dist/vendor/tools/tools/list_files.d.ts.map +1 -0
  245. package/dist/vendor/tools/tools/list_files.js +165 -0
  246. package/dist/vendor/tools/tools/list_files.js.map +1 -0
  247. package/dist/vendor/tools/tools/read_file.d.ts +3 -0
  248. package/dist/vendor/tools/tools/read_file.d.ts.map +1 -0
  249. package/dist/vendor/tools/tools/read_file.js +72 -0
  250. package/dist/vendor/tools/tools/read_file.js.map +1 -0
  251. package/dist/vendor/tools/tools/run_command.d.ts +12 -0
  252. package/dist/vendor/tools/tools/run_command.d.ts.map +1 -0
  253. package/dist/vendor/tools/tools/run_command.js +421 -0
  254. package/dist/vendor/tools/tools/run_command.js.map +1 -0
  255. package/dist/vendor/tools/tools/run_diagnostics.d.ts +3 -0
  256. package/dist/vendor/tools/tools/run_diagnostics.d.ts.map +1 -0
  257. package/dist/vendor/tools/tools/run_diagnostics.js +11 -0
  258. package/dist/vendor/tools/tools/run_diagnostics.js.map +1 -0
  259. package/dist/vendor/tools/tools/search_files.d.ts +3 -0
  260. package/dist/vendor/tools/tools/search_files.d.ts.map +1 -0
  261. package/dist/vendor/tools/tools/search_files.js +120 -0
  262. package/dist/vendor/tools/tools/search_files.js.map +1 -0
  263. package/dist/vendor/tools/tools/web_search.d.ts +46 -0
  264. package/dist/vendor/tools/tools/web_search.d.ts.map +1 -0
  265. package/dist/vendor/tools/tools/web_search.js +187 -0
  266. package/dist/vendor/tools/tools/web_search.js.map +1 -0
  267. package/dist/vendor/tools/tools/write_file.d.ts +3 -0
  268. package/dist/vendor/tools/tools/write_file.d.ts.map +1 -0
  269. package/dist/vendor/tools/tools/write_file.js +52 -0
  270. package/dist/vendor/tools/tools/write_file.js.map +1 -0
  271. package/dist/windows_credentials.d.ts +15 -0
  272. package/dist/windows_credentials.d.ts.map +1 -0
  273. package/dist/windows_credentials.js +23 -0
  274. package/dist/windows_credentials.js.map +1 -0
  275. package/package.json +28 -0
package/dist/index.js ADDED
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { parseCliArgs, getHelpText } from './args.js';
6
+ import { handleModelsCommand } from './commands/models.js';
7
+ import { handleRunCommand } from './commands/run.js';
8
+ import { handleChatSession } from './commands/chat.js';
9
+ import { handleDoctorCommand } from './commands/doctor.js';
10
+ import { writeDiagnosticLog } from './diagnostic_log.js';
11
+ function getVersion() {
12
+ try {
13
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
14
+ // Check root VERSION (3 levels up from apps/cli/dist)
15
+ const rootVersion = path.resolve(__dirname, '../../../VERSION');
16
+ if (fs.existsSync(rootVersion)) {
17
+ return fs.readFileSync(rootVersion, 'utf8').trim();
18
+ }
19
+ // Check package.json
20
+ const pkgJson = path.resolve(__dirname, '../package.json');
21
+ if (fs.existsSync(pkgJson)) {
22
+ const parsed = JSON.parse(fs.readFileSync(pkgJson, 'utf8'));
23
+ return `v${parsed.version}`;
24
+ }
25
+ }
26
+ catch {
27
+ // ignore
28
+ }
29
+ return 'v0.1.0';
30
+ }
31
+ async function main() {
32
+ const args = parseCliArgs();
33
+ if (args.help) {
34
+ process.stdout.write(getHelpText());
35
+ process.exitCode = 0;
36
+ return;
37
+ }
38
+ if (args.version) {
39
+ process.stdout.write(`${getVersion()}\n`);
40
+ process.exitCode = 0;
41
+ return;
42
+ }
43
+ const abortController = new AbortController();
44
+ const handleSigint = () => {
45
+ process.stdout.write('\n\x1b[33mReceived SIGINT, aborting session gracefully...\x1b[0m\n');
46
+ abortController.abort();
47
+ };
48
+ process.on('SIGINT', handleSigint);
49
+ process.on('SIGTERM', handleSigint);
50
+ let exitCode = 0;
51
+ try {
52
+ if (args.command === 'doctor') {
53
+ exitCode = await handleDoctorCommand(args);
54
+ }
55
+ else if (args.command === 'models') {
56
+ exitCode = await handleModelsCommand(args);
57
+ }
58
+ else if (args.command === 'run') {
59
+ exitCode = await handleRunCommand(args, abortController.signal);
60
+ }
61
+ else {
62
+ if (args.nonInteractive) {
63
+ process.stdout.write(getHelpText());
64
+ exitCode = 0;
65
+ }
66
+ else {
67
+ exitCode = await handleChatSession(args, getVersion(), abortController.signal);
68
+ }
69
+ }
70
+ }
71
+ finally {
72
+ process.off('SIGINT', handleSigint);
73
+ process.off('SIGTERM', handleSigint);
74
+ }
75
+ process.exitCode = exitCode;
76
+ process.exit(exitCode);
77
+ }
78
+ main().catch((err) => {
79
+ writeDiagnosticLog(process.argv[2] ?? 'interactive', err);
80
+ process.stderr.write(`\x1b[1;31mFatal error:\x1b[0m ${err.message}\n`);
81
+ process.exitCode = 1;
82
+ });
83
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { ModelInventoryEntry } from '@moderado/contracts';
2
+ /** Use only exact, provider-advertised prompt and completion prices. */
3
+ export declare function findModelPricing(models: ModelInventoryEntry[], modelId: string): Record<string, string> | undefined;
4
+ //# sourceMappingURL=model_pricing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model_pricing.d.ts","sourceRoot":"","sources":["../src/model_pricing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE/D,wEAAwE;AACxE,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,mBAAmB,EAAE,EAC7B,OAAO,EAAE,MAAM,GACd,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAOpC"}
@@ -0,0 +1,10 @@
1
+ /** Use only exact, provider-advertised prompt and completion prices. */
2
+ export function findModelPricing(models, modelId) {
3
+ const pricing = models.find((model) => model.id === modelId)?.pricing;
4
+ const prompt = Number(pricing?.prompt);
5
+ const completion = Number(pricing?.completion);
6
+ return Number.isFinite(prompt) && prompt >= 0 && Number.isFinite(completion) && completion >= 0
7
+ ? pricing
8
+ : undefined;
9
+ }
10
+ //# sourceMappingURL=model_pricing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model_pricing.js","sourceRoot":"","sources":["../src/model_pricing.ts"],"names":[],"mappings":"AAEA,wEAAwE;AACxE,MAAM,UAAU,gBAAgB,CAC9B,MAA6B,EAC7B,OAAe;IAEf,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,OAAO,CAAC,EAAE,OAAO,CAAC;IACtE,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACvC,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAC/C,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,UAAU,IAAI,CAAC;QAC7F,CAAC,CAAC,OAAO;QACT,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC"}
@@ -0,0 +1,203 @@
1
+ import { z } from 'zod';
2
+ import { type ChatMessage, type ChatUsage } from '@moderado/contracts';
3
+ export declare const StoredSessionSchema: z.ZodObject<{
4
+ schemaVersion: z.ZodLiteral<1>;
5
+ id: z.ZodString;
6
+ workspaceRoot: z.ZodString;
7
+ createdAt: z.ZodString;
8
+ updatedAt: z.ZodString;
9
+ providerId: z.ZodOptional<z.ZodString>;
10
+ providerName: z.ZodOptional<z.ZodString>;
11
+ modelId: z.ZodOptional<z.ZodString>;
12
+ mode: z.ZodEnum<["Plan", "Execute"]>;
13
+ messages: z.ZodArray<z.ZodDiscriminatedUnion<"role", [z.ZodObject<{
14
+ role: z.ZodLiteral<"system">;
15
+ content: z.ZodString;
16
+ }, "strip", z.ZodTypeAny, {
17
+ role: "system";
18
+ content: string;
19
+ }, {
20
+ role: "system";
21
+ content: string;
22
+ }>, z.ZodObject<{
23
+ role: z.ZodLiteral<"user">;
24
+ content: z.ZodString;
25
+ }, "strip", z.ZodTypeAny, {
26
+ role: "user";
27
+ content: string;
28
+ }, {
29
+ role: "user";
30
+ content: string;
31
+ }>, z.ZodObject<{
32
+ role: z.ZodLiteral<"assistant">;
33
+ content: z.ZodDefault<z.ZodNullable<z.ZodString>>;
34
+ toolCalls: z.ZodOptional<z.ZodArray<z.ZodObject<{
35
+ id: z.ZodString;
36
+ name: z.ZodString;
37
+ arguments: z.ZodRecord<z.ZodString, z.ZodUnknown>;
38
+ }, "strip", z.ZodTypeAny, {
39
+ id: string;
40
+ name: string;
41
+ arguments: Record<string, unknown>;
42
+ }, {
43
+ id: string;
44
+ name: string;
45
+ arguments: Record<string, unknown>;
46
+ }>, "many">>;
47
+ }, "strip", z.ZodTypeAny, {
48
+ role: "assistant";
49
+ content: string | null;
50
+ toolCalls?: {
51
+ id: string;
52
+ name: string;
53
+ arguments: Record<string, unknown>;
54
+ }[] | undefined;
55
+ }, {
56
+ role: "assistant";
57
+ content?: string | null | undefined;
58
+ toolCalls?: {
59
+ id: string;
60
+ name: string;
61
+ arguments: Record<string, unknown>;
62
+ }[] | undefined;
63
+ }>, z.ZodObject<{
64
+ role: z.ZodLiteral<"tool">;
65
+ toolCallId: z.ZodString;
66
+ name: z.ZodString;
67
+ content: z.ZodString;
68
+ status: z.ZodDefault<z.ZodEnum<["success", "error", "denied"]>>;
69
+ }, "strip", z.ZodTypeAny, {
70
+ status: "denied" | "success" | "error";
71
+ name: string;
72
+ role: "tool";
73
+ content: string;
74
+ toolCallId: string;
75
+ }, {
76
+ name: string;
77
+ role: "tool";
78
+ content: string;
79
+ toolCallId: string;
80
+ status?: "denied" | "success" | "error" | undefined;
81
+ }>]>, "many">;
82
+ usage: z.ZodObject<{
83
+ promptTokens: z.ZodNumber;
84
+ completionTokens: z.ZodNumber;
85
+ totalTokens: z.ZodNumber;
86
+ costUsd: z.ZodOptional<z.ZodNumber>;
87
+ costKnown: z.ZodBoolean;
88
+ available: z.ZodDefault<z.ZodBoolean>;
89
+ }, "strip", z.ZodTypeAny, {
90
+ promptTokens: number;
91
+ completionTokens: number;
92
+ totalTokens: number;
93
+ costKnown: boolean;
94
+ available: boolean;
95
+ costUsd?: number | undefined;
96
+ }, {
97
+ promptTokens: number;
98
+ completionTokens: number;
99
+ totalTokens: number;
100
+ costKnown: boolean;
101
+ costUsd?: number | undefined;
102
+ available?: boolean | undefined;
103
+ }>;
104
+ }, "strip", z.ZodTypeAny, {
105
+ id: string;
106
+ mode: "Plan" | "Execute";
107
+ schemaVersion: 1;
108
+ workspaceRoot: string;
109
+ createdAt: string;
110
+ updatedAt: string;
111
+ messages: ({
112
+ role: "system";
113
+ content: string;
114
+ } | {
115
+ role: "user";
116
+ content: string;
117
+ } | {
118
+ role: "assistant";
119
+ content: string | null;
120
+ toolCalls?: {
121
+ id: string;
122
+ name: string;
123
+ arguments: Record<string, unknown>;
124
+ }[] | undefined;
125
+ } | {
126
+ status: "denied" | "success" | "error";
127
+ name: string;
128
+ role: "tool";
129
+ content: string;
130
+ toolCallId: string;
131
+ })[];
132
+ usage: {
133
+ promptTokens: number;
134
+ completionTokens: number;
135
+ totalTokens: number;
136
+ costKnown: boolean;
137
+ available: boolean;
138
+ costUsd?: number | undefined;
139
+ };
140
+ providerId?: string | undefined;
141
+ providerName?: string | undefined;
142
+ modelId?: string | undefined;
143
+ }, {
144
+ id: string;
145
+ mode: "Plan" | "Execute";
146
+ schemaVersion: 1;
147
+ workspaceRoot: string;
148
+ createdAt: string;
149
+ updatedAt: string;
150
+ messages: ({
151
+ role: "system";
152
+ content: string;
153
+ } | {
154
+ role: "user";
155
+ content: string;
156
+ } | {
157
+ role: "assistant";
158
+ content?: string | null | undefined;
159
+ toolCalls?: {
160
+ id: string;
161
+ name: string;
162
+ arguments: Record<string, unknown>;
163
+ }[] | undefined;
164
+ } | {
165
+ name: string;
166
+ role: "tool";
167
+ content: string;
168
+ toolCallId: string;
169
+ status?: "denied" | "success" | "error" | undefined;
170
+ })[];
171
+ usage: {
172
+ promptTokens: number;
173
+ completionTokens: number;
174
+ totalTokens: number;
175
+ costKnown: boolean;
176
+ costUsd?: number | undefined;
177
+ available?: boolean | undefined;
178
+ };
179
+ providerId?: string | undefined;
180
+ providerName?: string | undefined;
181
+ modelId?: string | undefined;
182
+ }>;
183
+ export type StoredSession = z.infer<typeof StoredSessionSchema>;
184
+ export declare function createSession(workspaceRoot: string, details?: Partial<Pick<StoredSession, 'providerId' | 'providerName' | 'modelId' | 'mode'>>): StoredSession;
185
+ export declare class SessionStore {
186
+ private readonly home;
187
+ constructor(home?: string);
188
+ getDirectory(workspaceRoot: string): string;
189
+ getSessionPath(session: StoredSession): string;
190
+ save(session: StoredSession): void;
191
+ listSessions(workspaceRoot: string): StoredSession[];
192
+ loadLatestSession(workspaceRoot: string): StoredSession | undefined;
193
+ }
194
+ export declare function calculateSessionCost(usage: ChatUsage | undefined, pricing?: Record<string, string>): {
195
+ costKnown: boolean;
196
+ costUsd?: number;
197
+ };
198
+ /** Output speed uses only generated tokens, never prompt/context processing time. */
199
+ export declare function calculateOutputTokenRate(completionTokens: number, streamDurationMs: number): number | undefined;
200
+ export declare function formatSessionCost(usage: StoredSession['usage']): string;
201
+ export declare function exportSessionMarkdown(session: StoredSession): string;
202
+ export declare function compactSessionMessages(messages: ChatMessage[]): ChatMessage[];
203
+ //# sourceMappingURL=sessions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../src/sessions.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAqB,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAG1F,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAA8W,CAAC;AAC/Y,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,wBAAgB,aAAa,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,GAAE,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,YAAY,GAAG,cAAc,GAAG,SAAS,GAAG,MAAM,CAAC,CAAM,GAAG,aAAa,CAGlK;AAED,qBAAa,YAAY;IACX,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,SAAe;IAChD,YAAY,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM;IAC3C,cAAc,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM;IAC9C,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IASlC,YAAY,CAAC,aAAa,EAAE,MAAM,GAAG,aAAa,EAAE;IAOpD,iBAAiB,CAAC,aAAa,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;CACpE;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAI7I;AAED,qFAAqF;AACrF,wBAAgB,wBAAwB,CAAC,gBAAgB,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG/G;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,GAAG,MAAM,CAIvE;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAIpE;AACD,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE,CAM7E"}
@@ -0,0 +1,82 @@
1
+ import crypto from 'node:crypto';
2
+ import fs from 'node:fs';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+ import { z } from 'zod';
6
+ import { ChatMessageSchema } from './vendor/contracts/index.js';
7
+ const UsageSchema = z.object({ promptTokens: z.number().int().nonnegative(), completionTokens: z.number().int().nonnegative(), totalTokens: z.number().int().nonnegative(), costUsd: z.number().nonnegative().optional(), costKnown: z.boolean(), available: z.boolean().default(false) });
8
+ export const StoredSessionSchema = z.object({ schemaVersion: z.literal(1), id: z.string().uuid(), workspaceRoot: z.string().min(1), createdAt: z.string().datetime(), updatedAt: z.string().datetime(), providerId: z.string().optional(), providerName: z.string().optional(), modelId: z.string().optional(), mode: z.enum(['Plan', 'Execute']), messages: z.array(ChatMessageSchema), usage: UsageSchema });
9
+ export function createSession(workspaceRoot, details = {}) {
10
+ const now = new Date().toISOString();
11
+ return { schemaVersion: 1, id: crypto.randomUUID(), workspaceRoot, createdAt: now, updatedAt: now, providerId: details.providerId, providerName: details.providerName, modelId: details.modelId, mode: details.mode ?? 'Execute', messages: [], usage: { promptTokens: 0, completionTokens: 0, totalTokens: 0, costKnown: false, available: false } };
12
+ }
13
+ export class SessionStore {
14
+ home;
15
+ constructor(home = os.homedir()) {
16
+ this.home = home;
17
+ }
18
+ getDirectory(workspaceRoot) { return path.join(this.home, '.moderado', 'sessions', crypto.createHash('sha256').update(workspaceRoot).digest('hex')); }
19
+ getSessionPath(session) { return path.join(this.getDirectory(session.workspaceRoot), session.id + '.json'); }
20
+ save(session) {
21
+ const checked = StoredSessionSchema.parse({ ...session, updatedAt: new Date().toISOString() });
22
+ const dir = this.getDirectory(checked.workspaceRoot);
23
+ fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
24
+ const target = this.getSessionPath(checked);
25
+ const temp = target + '.' + crypto.randomUUID() + '.tmp';
26
+ fs.writeFileSync(temp, JSON.stringify(checked, null, 2), { encoding: 'utf8', mode: 0o600 });
27
+ fs.renameSync(temp, target);
28
+ }
29
+ listSessions(workspaceRoot) {
30
+ const dir = this.getDirectory(workspaceRoot);
31
+ if (!fs.existsSync(dir))
32
+ return [];
33
+ return fs.readdirSync(dir).filter((entry) => entry.endsWith('.json')).flatMap((entry) => {
34
+ try {
35
+ return [StoredSessionSchema.parse(JSON.parse(fs.readFileSync(path.join(dir, entry), 'utf8')))];
36
+ }
37
+ catch {
38
+ return [];
39
+ }
40
+ }).sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
41
+ }
42
+ loadLatestSession(workspaceRoot) { return this.listSessions(workspaceRoot)[0]; }
43
+ }
44
+ export function calculateSessionCost(usage, pricing) {
45
+ const prompt = Number(pricing?.prompt);
46
+ const completion = Number(pricing?.completion);
47
+ if (!usage || !Number.isFinite(prompt) || !Number.isFinite(completion) || prompt < 0 || completion < 0)
48
+ return { costKnown: false };
49
+ return { costKnown: true, costUsd: usage.promptTokens * prompt + usage.completionTokens * completion };
50
+ }
51
+ /** Output speed uses only generated tokens, never prompt/context processing time. */
52
+ export function calculateOutputTokenRate(completionTokens, streamDurationMs) {
53
+ if (!Number.isFinite(completionTokens) || completionTokens <= 0 || !Number.isFinite(streamDurationMs) || streamDurationMs <= 0)
54
+ return undefined;
55
+ return completionTokens / (streamDurationMs / 1_000);
56
+ }
57
+ export function formatSessionCost(usage) {
58
+ if (!usage.available || !usage.costKnown || usage.costUsd === undefined)
59
+ return 'Cost unknown';
60
+ if (usage.costUsd === 0)
61
+ return '$0.00';
62
+ return `$${usage.costUsd < 0.01 ? usage.costUsd.toFixed(6) : usage.costUsd.toFixed(4)}`;
63
+ }
64
+ function redact(text) { return text.replace(/(?:nvapi-|sk-)[A-Za-z0-9_-]+/g, '[redacted]'); }
65
+ export function exportSessionMarkdown(session) {
66
+ const lines = ['# Moderado session', '', 'Updated: ' + session.updatedAt, ''];
67
+ for (const message of session.messages) {
68
+ if (message.role !== 'tool')
69
+ lines.push('## ' + message.role, '', redact(message.content ?? ''), '');
70
+ }
71
+ return lines.join('\n');
72
+ }
73
+ export function compactSessionMessages(messages) {
74
+ const conversational = messages.filter((message) => message.role === 'user' || message.role === 'assistant');
75
+ if (conversational.length <= 4)
76
+ return [...messages];
77
+ const removed = conversational.slice(0, -4);
78
+ const kept = conversational.slice(-4);
79
+ const summary = removed.map((message) => message.role + ': ' + redact((message.content ?? '').slice(0, 240))).join('\n');
80
+ return [{ role: 'system', content: 'Compacted ' + removed.length + ' earlier messages:\n' + summary }, ...kept];
81
+ }
82
+ //# sourceMappingURL=sessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../src/sessions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export declare function stripAnsi(text: string): string;
2
+ export declare function getVisibleWidth(text: string): number;
3
+ export interface BoxOptions {
4
+ title?: string;
5
+ minWidth?: number;
6
+ borderColor?: string;
7
+ titleColor?: string;
8
+ }
9
+ /**
10
+ * Renders an enclosed Unicode box with mathematically guaranteed alignment
11
+ * regardless of ANSI color escape codes or string lengths.
12
+ */
13
+ export declare function renderBox(lines: string[], options?: BoxOptions): string;
14
+ //# sourceMappingURL=box.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"box.d.ts","sourceRoot":"","sources":["../../src/ui/box.ts"],"names":[],"mappings":"AACA,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG9C;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,UAAe,GAAG,MAAM,CA6C3E"}
package/dist/ui/box.js ADDED
@@ -0,0 +1,52 @@
1
+ // Strips ANSI escape sequences to compute visual display width
2
+ export function stripAnsi(text) {
3
+ // eslint-disable-next-line no-control-regex
4
+ return text.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, '');
5
+ }
6
+ export function getVisibleWidth(text) {
7
+ return stripAnsi(text).length;
8
+ }
9
+ /**
10
+ * Renders an enclosed Unicode box with mathematically guaranteed alignment
11
+ * regardless of ANSI color escape codes or string lengths.
12
+ */
13
+ export function renderBox(lines, options = {}) {
14
+ const border = options.borderColor ?? '\x1b[38;5;240m';
15
+ const reset = '\x1b[0m';
16
+ const titleColor = options.titleColor ?? '\x1b[1;38;5;75m';
17
+ // Calculate required width
18
+ let maxContentWidth = options.title ? getVisibleWidth(options.title) + 4 : 0;
19
+ for (const line of lines) {
20
+ if (line !== '---') {
21
+ const w = getVisibleWidth(line);
22
+ if (w > maxContentWidth) {
23
+ maxContentWidth = w;
24
+ }
25
+ }
26
+ }
27
+ const innerWidth = Math.max(maxContentWidth + 4, options.minWidth ?? 60);
28
+ let output = '';
29
+ // 1. Top border
30
+ if (options.title) {
31
+ const titleVis = getVisibleWidth(options.title);
32
+ const rightDashes = innerWidth - titleVis - 3;
33
+ output += `${border}╭─ ${titleColor}${options.title}${reset}${border} ${'─'.repeat(Math.max(0, rightDashes))}╮${reset}\n`;
34
+ }
35
+ else {
36
+ output += `${border}╭${'─'.repeat(innerWidth)}╮${reset}\n`;
37
+ }
38
+ // 2. Content lines
39
+ for (const line of lines) {
40
+ if (line === '---') {
41
+ output += `${border}├${'─'.repeat(innerWidth)}┤${reset}\n`;
42
+ continue;
43
+ }
44
+ const vis = getVisibleWidth(line);
45
+ const padRight = Math.max(0, innerWidth - vis - 2);
46
+ output += `${border}│${reset} ${line}${' '.repeat(padRight)}${border}│${reset}\n`;
47
+ }
48
+ // 3. Bottom border
49
+ output += `${border}╰${'─'.repeat(innerWidth)}╯${reset}\n`;
50
+ return output;
51
+ }
52
+ //# sourceMappingURL=box.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"box.js","sourceRoot":"","sources":["../../src/ui/box.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,4CAA4C;IAC5C,OAAO,IAAI,CAAC,OAAO,CAAC,wBAAwB,EAAE,EAAE,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;AAChC,CAAC;AASD;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,KAAe,EAAE,UAAsB,EAAE;IACjE,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,IAAI,gBAAgB,CAAC;IACvD,MAAM,KAAK,GAAG,SAAS,CAAC;IACxB,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,iBAAiB,CAAC;IAE3D,2BAA2B;IAC3B,IAAI,eAAe,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7E,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;YACnB,MAAM,CAAC,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;YAChC,IAAI,CAAC,GAAG,eAAe,EAAE,CAAC;gBACxB,eAAe,GAAG,CAAC,CAAC;YACtB,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,GAAG,CAAC,EAAE,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;IAEzE,IAAI,MAAM,GAAG,EAAE,CAAC;IAEhB,gBAAgB;IAChB,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,QAAQ,GAAG,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAChD,MAAM,WAAW,GAAG,UAAU,GAAG,QAAQ,GAAG,CAAC,CAAC;QAC9C,MAAM,IAAI,GAAG,MAAM,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,GAAG,KAAK,GAAG,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC;IAC5H,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,GAAG,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,KAAK,IAAI,CAAC;IAC7D,CAAC;IAED,mBAAmB;IACnB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;YACnB,MAAM,IAAI,GAAG,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,KAAK,IAAI,CAAC;YAC3D,SAAS;QACX,CAAC;QAED,MAAM,GAAG,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC;QACnD,MAAM,IAAI,GAAG,MAAM,IAAI,KAAK,KAAK,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,IAAI,KAAK,IAAI,CAAC;IACrF,CAAC;IAED,mBAAmB;IACnB,MAAM,IAAI,GAAG,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,KAAK,IAAI,CAAC;IAE3D,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Parse `@`-mention tokens out of composer text and expand them to absolute
3
+ * workspace paths. Only the token directly at the caret is auto-completed;
4
+ * submission expands every token to a path + excerpt block appended to the
5
+ * prompt, keeping the model context explicit and approval-free (reads are
6
+ * auto-approved by the jail).
7
+ */
8
+ export interface MentionExpansion {
9
+ /** Prompt sent to the model, with each `@token` replaced by path + excerpt. */
10
+ text: string;
11
+ /** Mention tokens that could not be resolved (reported back to the user). */
12
+ unresolved: string[];
13
+ }
14
+ export declare const IMAGE_EXTENSIONS: Record<string, string>;
15
+ export declare function isImagePath(filePath: string): boolean;
16
+ export declare function getImageMimeType(filePath: string): string | undefined;
17
+ /** Parse the `@`-token that ends at the caret, for autocomplete filtering. */
18
+ export declare function activeMentionToken(input: string, caret: number): {
19
+ token: string;
20
+ start: number;
21
+ } | undefined;
22
+ export interface WorkspaceFileSource {
23
+ listFiles(relativePath: string): Promise<string[]>;
24
+ readFile(relativePath: string): Promise<string>;
25
+ readImage?(relativePath: string): Promise<Buffer>;
26
+ }
27
+ export declare function createWorkspaceFileSource(workspaceRoot: string): WorkspaceFileSource;
28
+ export declare function filterMentionCandidates(candidates: string[], token: string, limit?: number): string[];
29
+ /**
30
+ * Expand every `@token` mention into a fenced block with the file path and a
31
+ * capped excerpt (first 200 lines) or attached image payload. Unresolvable
32
+ * tokens are left verbatim and reported, so nothing silently disappears from
33
+ * the user's prompt.
34
+ */
35
+ export declare function expandMentions(input: string, workspace: WorkspaceFileSource, options?: {
36
+ maxExcerptLines?: number;
37
+ }): Promise<MentionExpansion>;
38
+ //# sourceMappingURL=file_mentions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file_mentions.d.ts","sourceRoot":"","sources":["../../src/ui/file_mentions.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,+EAA+E;IAC/E,IAAI,EAAE,MAAM,CAAC;IACb,6EAA6E;IAC7E,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAID,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CASnD,CAAC;AAEF,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAGrD;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGrE;AAED,8EAA8E;AAC9E,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAK7G;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACnD,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAChD,SAAS,CAAC,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACnD;AAED,wBAAgB,yBAAyB,CAAC,aAAa,EAAE,MAAM,GAAG,mBAAmB,CAcpF;AAED,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,MAAM,EAAE,CAehG;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,mBAAmB,EAC9B,OAAO,GAAE;IAAE,eAAe,CAAC,EAAE,MAAM,CAAA;CAAO,GACzC,OAAO,CAAC,gBAAgB,CAAC,CAuD3B"}
@@ -0,0 +1,119 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { listFiles, resolveInJail } from '../vendor/tools/index.js';
4
+ const MENTION_PATTERN = /@([\w./\\-]+)/g;
5
+ export const IMAGE_EXTENSIONS = {
6
+ '.png': 'image/png',
7
+ '.jpg': 'image/jpeg',
8
+ '.jpeg': 'image/jpeg',
9
+ '.gif': 'image/gif',
10
+ '.webp': 'image/webp',
11
+ '.svg': 'image/svg+xml',
12
+ '.bmp': 'image/bmp',
13
+ '.ico': 'image/x-icon',
14
+ };
15
+ export function isImagePath(filePath) {
16
+ const ext = path.extname(filePath).toLowerCase();
17
+ return ext in IMAGE_EXTENSIONS;
18
+ }
19
+ export function getImageMimeType(filePath) {
20
+ const ext = path.extname(filePath).toLowerCase();
21
+ return IMAGE_EXTENSIONS[ext];
22
+ }
23
+ /** Parse the `@`-token that ends at the caret, for autocomplete filtering. */
24
+ export function activeMentionToken(input, caret) {
25
+ const before = input.slice(0, caret);
26
+ const match = /@([\w./\\-]*)$/.exec(before);
27
+ if (!match)
28
+ return undefined;
29
+ return { token: match[1].replace(/\\/g, '/'), start: caret - match[0].length };
30
+ }
31
+ export function createWorkspaceFileSource(workspaceRoot) {
32
+ return {
33
+ async listFiles(relativePath) {
34
+ return listFiles(workspaceRoot, relativePath, { recursive: true, maxDepth: 5, limit: 50 });
35
+ },
36
+ async readFile(relativePath) {
37
+ const canonical = resolveInJail(workspaceRoot, relativePath);
38
+ return fs.readFileSync(canonical, 'utf8');
39
+ },
40
+ async readImage(relativePath) {
41
+ const canonical = resolveInJail(workspaceRoot, relativePath);
42
+ return fs.readFileSync(canonical);
43
+ },
44
+ };
45
+ }
46
+ export function filterMentionCandidates(candidates, token, limit = 8) {
47
+ const q = token.toLowerCase().trim();
48
+ if (!q)
49
+ return candidates.slice(0, limit);
50
+ const exactStart = [];
51
+ const substring = [];
52
+ for (const candidate of candidates) {
53
+ const normalized = candidate.toLowerCase();
54
+ const base = path.basename(candidate).toLowerCase();
55
+ if (base.startsWith(q) || normalized.startsWith(q)) {
56
+ exactStart.push(candidate);
57
+ }
58
+ else if (normalized.includes(q)) {
59
+ substring.push(candidate);
60
+ }
61
+ }
62
+ return [...exactStart, ...substring].slice(0, limit);
63
+ }
64
+ /**
65
+ * Expand every `@token` mention into a fenced block with the file path and a
66
+ * capped excerpt (first 200 lines) or attached image payload. Unresolvable
67
+ * tokens are left verbatim and reported, so nothing silently disappears from
68
+ * the user's prompt.
69
+ */
70
+ export async function expandMentions(input, workspace, options = {}) {
71
+ const maxLines = options.maxExcerptLines ?? 200;
72
+ const unresolved = [];
73
+ let text = input;
74
+ const matches = [...input.matchAll(MENTION_PATTERN)];
75
+ for (const match of matches.reverse()) {
76
+ const rawToken = match[1];
77
+ const token = rawToken.replace(/\\/g, '/');
78
+ const full = `@${rawToken}`;
79
+ try {
80
+ const files = await workspace.listFiles(token);
81
+ const target = files.length === 1 ? files[0] : files[0] ?? token;
82
+ if (isImagePath(target)) {
83
+ const mime = getImageMimeType(target) ?? 'application/octet-stream';
84
+ if (workspace.readImage) {
85
+ const buffer = await workspace.readImage(target);
86
+ if (buffer.byteLength > 1024 * 1024) {
87
+ text = text.replace(full, `\n--- @${target} (image) ---\n[Attached image: ${target} (${mime}, ${buffer.byteLength} bytes - exceeded 1MB inline limit)]\n--- end @${target} ---`);
88
+ }
89
+ else {
90
+ const base64 = buffer.toString('base64');
91
+ text = text.replace(full, `\n--- @${target} (image) ---\n[Attached image: ${target} (${mime}, ${buffer.byteLength} bytes)]\ndata:${mime};base64,${base64}\n--- end @${target} ---`);
92
+ }
93
+ }
94
+ else {
95
+ try {
96
+ const content = await workspace.readFile(target);
97
+ text = text.replace(full, `\n--- @${target} ---\n${content}\n--- end @${target} ---`);
98
+ }
99
+ catch {
100
+ text = text.replace(full, `\n--- @${target} (image) ---\n[Attached image: ${target} (${mime})]\n--- end @${target} ---`);
101
+ }
102
+ }
103
+ }
104
+ else {
105
+ const content = await workspace.readFile(target);
106
+ const lines = content.split(/\r?\n/).slice(0, maxLines);
107
+ text = text.replace(full, `\n--- @${target} ---\n${lines.join('\n')}\n--- end @${target} ---`);
108
+ }
109
+ }
110
+ catch {
111
+ unresolved.push(full);
112
+ }
113
+ }
114
+ for (const missing of unresolved) {
115
+ text = text.replace(missing, `${missing} (file not found)`);
116
+ }
117
+ return { text: text.trim(), unresolved };
118
+ }
119
+ //# sourceMappingURL=file_mentions.js.map