@sunilp-org/jam-cli 0.1.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 (163) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +625 -0
  3. package/dist/commands/ask.d.ts +9 -0
  4. package/dist/commands/ask.d.ts.map +1 -0
  5. package/dist/commands/ask.js +84 -0
  6. package/dist/commands/ask.js.map +1 -0
  7. package/dist/commands/auth.d.ts +4 -0
  8. package/dist/commands/auth.d.ts.map +1 -0
  9. package/dist/commands/auth.js +44 -0
  10. package/dist/commands/auth.js.map +1 -0
  11. package/dist/commands/chat.d.ts +10 -0
  12. package/dist/commands/chat.d.ts.map +1 -0
  13. package/dist/commands/chat.js +57 -0
  14. package/dist/commands/chat.js.map +1 -0
  15. package/dist/commands/completion.d.ts +4 -0
  16. package/dist/commands/completion.d.ts.map +1 -0
  17. package/dist/commands/completion.js +156 -0
  18. package/dist/commands/completion.js.map +1 -0
  19. package/dist/commands/config.d.ts +6 -0
  20. package/dist/commands/config.d.ts.map +1 -0
  21. package/dist/commands/config.js +59 -0
  22. package/dist/commands/config.js.map +1 -0
  23. package/dist/commands/diff.d.ts +9 -0
  24. package/dist/commands/diff.d.ts.map +1 -0
  25. package/dist/commands/diff.js +69 -0
  26. package/dist/commands/diff.js.map +1 -0
  27. package/dist/commands/doctor.d.ts +3 -0
  28. package/dist/commands/doctor.d.ts.map +1 -0
  29. package/dist/commands/doctor.js +86 -0
  30. package/dist/commands/doctor.js.map +1 -0
  31. package/dist/commands/explain.d.ts +7 -0
  32. package/dist/commands/explain.d.ts.map +1 -0
  33. package/dist/commands/explain.js +72 -0
  34. package/dist/commands/explain.js.map +1 -0
  35. package/dist/commands/history.d.ts +3 -0
  36. package/dist/commands/history.d.ts.map +1 -0
  37. package/dist/commands/history.js +99 -0
  38. package/dist/commands/history.js.map +1 -0
  39. package/dist/commands/models.d.ts +3 -0
  40. package/dist/commands/models.d.ts.map +1 -0
  41. package/dist/commands/models.js +39 -0
  42. package/dist/commands/models.js.map +1 -0
  43. package/dist/commands/patch.d.ts +8 -0
  44. package/dist/commands/patch.d.ts.map +1 -0
  45. package/dist/commands/patch.js +158 -0
  46. package/dist/commands/patch.js.map +1 -0
  47. package/dist/commands/run.d.ts +6 -0
  48. package/dist/commands/run.d.ts.map +1 -0
  49. package/dist/commands/run.js +241 -0
  50. package/dist/commands/run.js.map +1 -0
  51. package/dist/commands/search.d.ts +9 -0
  52. package/dist/commands/search.d.ts.map +1 -0
  53. package/dist/commands/search.js +128 -0
  54. package/dist/commands/search.js.map +1 -0
  55. package/dist/config/defaults.d.ts +3 -0
  56. package/dist/config/defaults.d.ts.map +1 -0
  57. package/dist/config/defaults.js +16 -0
  58. package/dist/config/defaults.js.map +1 -0
  59. package/dist/config/loader.d.ts +4 -0
  60. package/dist/config/loader.d.ts.map +1 -0
  61. package/dist/config/loader.js +103 -0
  62. package/dist/config/loader.js.map +1 -0
  63. package/dist/config/schema.d.ts +104 -0
  64. package/dist/config/schema.d.ts.map +1 -0
  65. package/dist/config/schema.js +21 -0
  66. package/dist/config/schema.js.map +1 -0
  67. package/dist/index.d.ts +3 -0
  68. package/dist/index.d.ts.map +1 -0
  69. package/dist/index.js +249 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/providers/base.d.ts +32 -0
  72. package/dist/providers/base.d.ts.map +1 -0
  73. package/dist/providers/base.js +2 -0
  74. package/dist/providers/base.js.map +1 -0
  75. package/dist/providers/factory.d.ts +4 -0
  76. package/dist/providers/factory.d.ts.map +1 -0
  77. package/dist/providers/factory.js +13 -0
  78. package/dist/providers/factory.js.map +1 -0
  79. package/dist/providers/ollama.d.ts +14 -0
  80. package/dist/providers/ollama.d.ts.map +1 -0
  81. package/dist/providers/ollama.js +152 -0
  82. package/dist/providers/ollama.js.map +1 -0
  83. package/dist/storage/history.d.ts +21 -0
  84. package/dist/storage/history.d.ts.map +1 -0
  85. package/dist/storage/history.js +103 -0
  86. package/dist/storage/history.js.map +1 -0
  87. package/dist/tools/apply_patch.d.ts +3 -0
  88. package/dist/tools/apply_patch.d.ts.map +1 -0
  89. package/dist/tools/apply_patch.js +86 -0
  90. package/dist/tools/apply_patch.js.map +1 -0
  91. package/dist/tools/git_diff.d.ts +3 -0
  92. package/dist/tools/git_diff.d.ts.map +1 -0
  93. package/dist/tools/git_diff.js +49 -0
  94. package/dist/tools/git_diff.js.map +1 -0
  95. package/dist/tools/git_status.d.ts +3 -0
  96. package/dist/tools/git_status.d.ts.map +1 -0
  97. package/dist/tools/git_status.js +26 -0
  98. package/dist/tools/git_status.js.map +1 -0
  99. package/dist/tools/index.d.ts +10 -0
  100. package/dist/tools/index.d.ts.map +1 -0
  101. package/dist/tools/index.js +10 -0
  102. package/dist/tools/index.js.map +1 -0
  103. package/dist/tools/list_dir.d.ts +3 -0
  104. package/dist/tools/list_dir.d.ts.map +1 -0
  105. package/dist/tools/list_dir.js +61 -0
  106. package/dist/tools/list_dir.js.map +1 -0
  107. package/dist/tools/read_file.d.ts +3 -0
  108. package/dist/tools/read_file.d.ts.map +1 -0
  109. package/dist/tools/read_file.js +83 -0
  110. package/dist/tools/read_file.js.map +1 -0
  111. package/dist/tools/registry.d.ts +12 -0
  112. package/dist/tools/registry.d.ts.map +1 -0
  113. package/dist/tools/registry.js +76 -0
  114. package/dist/tools/registry.js.map +1 -0
  115. package/dist/tools/run_command.d.ts +6 -0
  116. package/dist/tools/run_command.d.ts.map +1 -0
  117. package/dist/tools/run_command.js +37 -0
  118. package/dist/tools/run_command.js.map +1 -0
  119. package/dist/tools/search_text.d.ts +3 -0
  120. package/dist/tools/search_text.d.ts.map +1 -0
  121. package/dist/tools/search_text.js +171 -0
  122. package/dist/tools/search_text.js.map +1 -0
  123. package/dist/tools/types.d.ts +25 -0
  124. package/dist/tools/types.d.ts.map +1 -0
  125. package/dist/tools/types.js +2 -0
  126. package/dist/tools/types.js.map +1 -0
  127. package/dist/tools/write_file.d.ts +3 -0
  128. package/dist/tools/write_file.d.ts.map +1 -0
  129. package/dist/tools/write_file.js +61 -0
  130. package/dist/tools/write_file.js.map +1 -0
  131. package/dist/ui/chat.d.ts +10 -0
  132. package/dist/ui/chat.d.ts.map +1 -0
  133. package/dist/ui/chat.js +173 -0
  134. package/dist/ui/chat.js.map +1 -0
  135. package/dist/ui/logo.d.ts +14 -0
  136. package/dist/ui/logo.d.ts.map +1 -0
  137. package/dist/ui/logo.js +76 -0
  138. package/dist/ui/logo.js.map +1 -0
  139. package/dist/ui/renderer.d.ts +15 -0
  140. package/dist/ui/renderer.d.ts.map +1 -0
  141. package/dist/ui/renderer.js +61 -0
  142. package/dist/ui/renderer.js.map +1 -0
  143. package/dist/utils/errors.d.ts +14 -0
  144. package/dist/utils/errors.d.ts.map +1 -0
  145. package/dist/utils/errors.js +26 -0
  146. package/dist/utils/errors.js.map +1 -0
  147. package/dist/utils/logger.d.ts +17 -0
  148. package/dist/utils/logger.d.ts.map +1 -0
  149. package/dist/utils/logger.js +50 -0
  150. package/dist/utils/logger.js.map +1 -0
  151. package/dist/utils/secrets.d.ts +4 -0
  152. package/dist/utils/secrets.d.ts.map +1 -0
  153. package/dist/utils/secrets.js +39 -0
  154. package/dist/utils/secrets.js.map +1 -0
  155. package/dist/utils/stream.d.ts +12 -0
  156. package/dist/utils/stream.d.ts.map +1 -0
  157. package/dist/utils/stream.js +54 -0
  158. package/dist/utils/stream.js.map +1 -0
  159. package/dist/utils/workspace.d.ts +14 -0
  160. package/dist/utils/workspace.d.ts.map +1 -0
  161. package/dist/utils/workspace.js +39 -0
  162. package/dist/utils/workspace.js.map +1 -0
  163. package/package.json +84 -0
@@ -0,0 +1,76 @@
1
+ import * as readline from 'node:readline/promises';
2
+ import { stdin, stdout } from 'node:process';
3
+ import { JamError } from '../utils/errors.js';
4
+ import { readFileTool } from './read_file.js';
5
+ import { listDirTool } from './list_dir.js';
6
+ import { searchTextTool } from './search_text.js';
7
+ import { gitDiffTool } from './git_diff.js';
8
+ import { gitStatusTool } from './git_status.js';
9
+ import { applyPatchTool } from './apply_patch.js';
10
+ import { writeFileTool } from './write_file.js';
11
+ export class ToolRegistry {
12
+ tools = new Map();
13
+ register(tool) {
14
+ this.tools.set(tool.name, tool);
15
+ }
16
+ get(name) {
17
+ return this.tools.get(name);
18
+ }
19
+ list() {
20
+ return Array.from(this.tools.values());
21
+ }
22
+ async execute(name, args, ctx, policy) {
23
+ const tool = this.tools.get(name);
24
+ if (tool === undefined) {
25
+ throw new JamError(`Tool not found: "${name}"`, 'TOOL_NOT_FOUND');
26
+ }
27
+ if (!tool.readonly) {
28
+ // Write tool — enforce policy
29
+ if (policy === 'never') {
30
+ throw new JamError(`Tool execution denied by policy: "${name}" is a write tool and policy is "never".`, 'TOOL_DENIED');
31
+ }
32
+ if (policy === 'ask_every_time') {
33
+ const confirmed = await this.confirmExecution(tool, args);
34
+ if (!confirmed) {
35
+ throw new JamError(`Tool execution denied by user: "${name}"`, 'TOOL_DENIED');
36
+ }
37
+ }
38
+ // policy === 'allowlist' falls through to execution below
39
+ }
40
+ try {
41
+ return await tool.execute(args, ctx);
42
+ }
43
+ catch (err) {
44
+ if (JamError.isJamError(err))
45
+ throw err;
46
+ throw new JamError(`Tool "${name}" threw an unexpected error.`, 'TOOL_EXEC_ERROR', { cause: err });
47
+ }
48
+ }
49
+ async confirmExecution(tool, args) {
50
+ const rl = readline.createInterface({ input: stdin, output: stdout });
51
+ try {
52
+ const argsJson = JSON.stringify(args, null, 2);
53
+ const prompt = `\nTool: ${tool.name}\n` +
54
+ `Description: ${tool.description}\n` +
55
+ `Args:\n${argsJson}\n` +
56
+ `\nThis is a write operation. Proceed? [y/N] `;
57
+ const answer = await rl.question(prompt);
58
+ return answer.trim().toLowerCase() === 'y';
59
+ }
60
+ finally {
61
+ rl.close();
62
+ }
63
+ }
64
+ }
65
+ export function createDefaultRegistry() {
66
+ const registry = new ToolRegistry();
67
+ registry.register(readFileTool);
68
+ registry.register(listDirTool);
69
+ registry.register(searchTextTool);
70
+ registry.register(gitDiffTool);
71
+ registry.register(gitStatusTool);
72
+ registry.register(applyPatchTool);
73
+ registry.register(writeFileTool);
74
+ return registry;
75
+ }
76
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/tools/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Spawns a child process and returns stdout as a string.
3
+ * Rejects with an Error containing stderr if the process exits with a non-zero code.
4
+ */
5
+ export declare function runCommand(command: string, args: string[], cwd: string, timeoutMs?: number): Promise<string>;
6
+ //# sourceMappingURL=run_command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run_command.d.ts","sourceRoot":"","sources":["../../src/tools/run_command.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,UAAU,CACxB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,EACX,SAAS,SAAS,GACjB,OAAO,CAAC,MAAM,CAAC,CAuCjB"}
@@ -0,0 +1,37 @@
1
+ import { spawn } from 'node:child_process';
2
+ /**
3
+ * Spawns a child process and returns stdout as a string.
4
+ * Rejects with an Error containing stderr if the process exits with a non-zero code.
5
+ */
6
+ export function runCommand(command, args, cwd, timeoutMs = 30_000) {
7
+ return new Promise((resolve, reject) => {
8
+ const child = spawn(command, args, { cwd, stdio: ['ignore', 'pipe', 'pipe'] });
9
+ let stdout = '';
10
+ let stderr = '';
11
+ child.stdout.on('data', (chunk) => {
12
+ stdout += chunk.toString('utf8');
13
+ });
14
+ child.stderr.on('data', (chunk) => {
15
+ stderr += chunk.toString('utf8');
16
+ });
17
+ const timer = setTimeout(() => {
18
+ child.kill('SIGTERM');
19
+ reject(new Error(`Command timed out after ${timeoutMs}ms: ${command} ${args.join(' ')}`));
20
+ }, timeoutMs);
21
+ child.on('close', (code) => {
22
+ clearTimeout(timer);
23
+ if (code === 0) {
24
+ resolve(stdout);
25
+ }
26
+ else {
27
+ const detail = stderr.trim() || stdout.trim();
28
+ reject(new Error(`Command "${command} ${args.join(' ')}" exited with code ${code}${detail ? `: ${detail}` : ''}`));
29
+ }
30
+ });
31
+ child.on('error', (err) => {
32
+ clearTimeout(timer);
33
+ reject(err);
34
+ });
35
+ });
36
+ }
37
+ //# sourceMappingURL=run_command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run_command.js","sourceRoot":"","sources":["../../src/tools/run_command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C;;;GAGG;AACH,MAAM,UAAU,UAAU,CACxB,OAAe,EACf,IAAc,EACd,GAAW,EACX,SAAS,GAAG,MAAM;IAElB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;QAE/E,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,MAAM,GAAG,EAAE,CAAC;QAEhB,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YACxC,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YACxC,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACtB,MAAM,CAAC,IAAI,KAAK,CAAC,2BAA2B,SAAS,OAAO,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5F,CAAC,EAAE,SAAS,CAAC,CAAC;QAEd,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACzB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;gBACf,OAAO,CAAC,MAAM,CAAC,CAAC;YAClB,CAAC;iBAAM,CAAC;gBACN,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;gBAC9C,MAAM,CACJ,IAAI,KAAK,CACP,YAAY,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,sBAAsB,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAChG,CACF,CAAC;YACJ,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACxB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,MAAM,CAAC,GAAG,CAAC,CAAC;QACd,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ToolDefinition } from './types.js';
2
+ export declare const searchTextTool: ToolDefinition;
3
+ //# sourceMappingURL=search_text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search_text.d.ts","sourceRoot":"","sources":["../../src/tools/search_text.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAA2B,MAAM,YAAY,CAAC;AAuI1E,eAAO,MAAM,cAAc,EAAE,cAkE5B,CAAC"}
@@ -0,0 +1,171 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { readdir, readFile } from 'node:fs/promises';
3
+ import { resolve, join, relative } from 'node:path';
4
+ import { JamError } from '../utils/errors.js';
5
+ const SEARCH_TIMEOUT_MS = 10_000;
6
+ const DEFAULT_MAX_RESULTS = 20;
7
+ function runRipgrep(query, cwd, glob, maxResults) {
8
+ return new Promise((resolve, reject) => {
9
+ const args = [
10
+ '--line-number',
11
+ '--no-heading',
12
+ '--color=never',
13
+ `--max-count=${maxResults}`,
14
+ ];
15
+ if (glob !== undefined) {
16
+ args.push('--glob', glob);
17
+ }
18
+ args.push(query, '.');
19
+ const child = spawn('rg', args, { cwd, stdio: ['ignore', 'pipe', 'pipe'] });
20
+ let stdout = '';
21
+ let stderr = '';
22
+ child.stdout.on('data', (chunk) => {
23
+ stdout += chunk.toString('utf8');
24
+ });
25
+ child.stderr.on('data', (chunk) => {
26
+ stderr += chunk.toString('utf8');
27
+ });
28
+ const timer = setTimeout(() => {
29
+ child.kill('SIGTERM');
30
+ reject(new Error('ripgrep timed out'));
31
+ }, SEARCH_TIMEOUT_MS);
32
+ child.on('close', (code) => {
33
+ clearTimeout(timer);
34
+ if (code === 0 || code === 1) {
35
+ // code 1 = no matches, which is fine
36
+ resolve(stdout.trim() === '' ? [] : stdout.trim().split('\n'));
37
+ }
38
+ else {
39
+ reject(new Error(`rg exited with code ${code}: ${stderr}`));
40
+ }
41
+ });
42
+ child.on('error', (err) => {
43
+ clearTimeout(timer);
44
+ reject(err);
45
+ });
46
+ });
47
+ }
48
+ async function collectFiles(dir, globPattern) {
49
+ const results = [];
50
+ async function walk(current) {
51
+ let entries;
52
+ try {
53
+ entries = await readdir(current, { withFileTypes: true });
54
+ }
55
+ catch {
56
+ return;
57
+ }
58
+ for (const entry of entries) {
59
+ const name = String(entry.name);
60
+ // Skip hidden directories (like .git) and node_modules
61
+ if (name.startsWith('.') || name === 'node_modules') {
62
+ continue;
63
+ }
64
+ const fullPath = join(current, name);
65
+ if (entry.isDirectory()) {
66
+ await walk(fullPath);
67
+ }
68
+ else if (entry.isFile()) {
69
+ if (globPattern !== undefined) {
70
+ // Simple glob: support *.ext and **/*.ext patterns
71
+ const dotIdx = globPattern.lastIndexOf('.');
72
+ if (dotIdx !== -1) {
73
+ const ext = globPattern.slice(dotIdx);
74
+ if (!name.endsWith(ext)) {
75
+ continue;
76
+ }
77
+ }
78
+ }
79
+ results.push(fullPath);
80
+ }
81
+ }
82
+ }
83
+ await walk(dir);
84
+ return results;
85
+ }
86
+ async function nodeFallbackSearch(query, workspaceRoot, glob, maxResults) {
87
+ const files = await collectFiles(workspaceRoot, glob);
88
+ const matchLines = [];
89
+ const lowerQuery = query.toLowerCase();
90
+ outer: for (const file of files) {
91
+ let content;
92
+ try {
93
+ content = await readFile(file, 'utf8');
94
+ }
95
+ catch {
96
+ continue;
97
+ }
98
+ const lines = content.split('\n');
99
+ for (let i = 0; i < lines.length; i++) {
100
+ const line = lines[i] ?? '';
101
+ if (line.toLowerCase().includes(lowerQuery)) {
102
+ const relPath = relative(workspaceRoot, file);
103
+ matchLines.push(`${relPath}:${i + 1}: ${line}`);
104
+ if (matchLines.length >= maxResults) {
105
+ break outer;
106
+ }
107
+ }
108
+ }
109
+ }
110
+ return matchLines;
111
+ }
112
+ export const searchTextTool = {
113
+ name: 'search_text',
114
+ description: 'Search for text across files in the workspace. Uses ripgrep if available, otherwise falls back to a Node.js implementation.',
115
+ readonly: true,
116
+ parameters: {
117
+ type: 'object',
118
+ properties: {
119
+ query: { type: 'string', description: 'The text or regex pattern to search for.' },
120
+ glob: {
121
+ type: 'string',
122
+ description: 'Optional glob pattern to restrict the search (e.g. "**/*.ts").',
123
+ optional: true,
124
+ },
125
+ maxResults: {
126
+ type: 'number',
127
+ description: `Maximum number of results to return. Defaults to ${DEFAULT_MAX_RESULTS}.`,
128
+ optional: true,
129
+ },
130
+ },
131
+ required: ['query'],
132
+ },
133
+ async execute(args, ctx) {
134
+ const query = args['query'];
135
+ if (typeof query !== 'string' || query.trim() === '') {
136
+ throw new JamError('Argument "query" must be a non-empty string.', 'INPUT_MISSING');
137
+ }
138
+ const glob = typeof args['glob'] === 'string' ? args['glob'] : undefined;
139
+ const maxResults = typeof args['maxResults'] === 'number' && args['maxResults'] > 0
140
+ ? args['maxResults']
141
+ : DEFAULT_MAX_RESULTS;
142
+ const absoluteRoot = resolve(ctx.workspaceRoot);
143
+ let matchLines;
144
+ let usedFallback = false;
145
+ try {
146
+ matchLines = await runRipgrep(query, absoluteRoot, glob, maxResults);
147
+ }
148
+ catch {
149
+ // rg not available or failed — fall back to Node.js search
150
+ usedFallback = true;
151
+ try {
152
+ matchLines = await nodeFallbackSearch(query, absoluteRoot, glob, maxResults);
153
+ }
154
+ catch (err) {
155
+ throw new JamError('Search failed.', 'TOOL_EXEC_ERROR', { cause: err });
156
+ }
157
+ }
158
+ if (matchLines.length === 0) {
159
+ return {
160
+ output: 'No matches found.',
161
+ metadata: { query, usedFallback, matchCount: 0 },
162
+ };
163
+ }
164
+ const output = matchLines.join('\n');
165
+ return {
166
+ output,
167
+ metadata: { query, usedFallback, matchCount: matchLines.length },
168
+ };
169
+ },
170
+ };
171
+ //# sourceMappingURL=search_text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search_text.js","sourceRoot":"","sources":["../../src/tools/search_text.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAErD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAG9C,MAAM,iBAAiB,GAAG,MAAM,CAAC;AACjC,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAE/B,SAAS,UAAU,CACjB,KAAa,EACb,GAAW,EACX,IAAwB,EACxB,UAAkB;IAElB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,IAAI,GAAG;YACX,eAAe;YACf,cAAc;YACd,eAAe;YACf,eAAe,UAAU,EAAE;SAC5B,CAAC;QAEF,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC5B,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAEtB,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;QAE5E,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,MAAM,GAAG,EAAE,CAAC;QAEhB,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YACxC,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YACxC,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACtB,MAAM,CAAC,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAAC;QACzC,CAAC,EAAE,iBAAiB,CAAC,CAAC;QAEtB,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACzB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,IAAI,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;gBAC7B,qCAAqC;gBACrC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;YACjE,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,IAAI,KAAK,CAAC,uBAAuB,IAAI,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC;YAC9D,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACxB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,MAAM,CAAC,GAAG,CAAC,CAAC;QACd,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,GAAW,EAAE,WAA+B;IACtE,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,UAAU,IAAI,CAAC,OAAe;QACjC,IAAI,OAAiB,CAAC;QACtB,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;QACT,CAAC;QAED,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAChC,uDAAuD;YACvD,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,KAAK,cAAc,EAAE,CAAC;gBACpD,SAAS;YACX,CAAC;YAED,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YACrC,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;YACvB,CAAC;iBAAM,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;gBAC1B,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;oBAC9B,mDAAmD;oBACnD,MAAM,MAAM,GAAG,WAAW,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;oBAC5C,IAAI,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;wBAClB,MAAM,GAAG,GAAG,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;wBACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;4BACxB,SAAS;wBACX,CAAC;oBACH,CAAC;gBACH,CAAC;gBACD,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC;IAChB,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,KAAK,UAAU,kBAAkB,CAC/B,KAAa,EACb,aAAqB,EACrB,IAAwB,EACxB,UAAkB;IAElB,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;IACtD,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAEvC,KAAK,EAAE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAChC,IAAI,OAAe,CAAC;QACpB,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACzC,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC5B,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC5C,MAAM,OAAO,GAAG,QAAQ,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;gBAC9C,UAAU,CAAC,IAAI,CAAC,GAAG,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;gBAChD,IAAI,UAAU,CAAC,MAAM,IAAI,UAAU,EAAE,CAAC;oBACpC,MAAM,KAAK,CAAC;gBACd,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,CAAC,MAAM,cAAc,GAAmB;IAC5C,IAAI,EAAE,aAAa;IACnB,WAAW,EACT,6HAA6H;IAC/H,QAAQ,EAAE,IAAI;IACd,UAAU,EAAE;QACV,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,0CAA0C,EAAE;YAClF,IAAI,EAAE;gBACJ,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,gEAAgE;gBAC7E,QAAQ,EAAE,IAAI;aACf;YACD,UAAU,EAAE;gBACV,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,oDAAoD,mBAAmB,GAAG;gBACvF,QAAQ,EAAE,IAAI;aACf;SACF;QACD,QAAQ,EAAE,CAAC,OAAO,CAAC;KACpB;IAED,KAAK,CAAC,OAAO,CAAC,IAA6B,EAAE,GAAgB;QAC3D,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;QAC5B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACrD,MAAM,IAAI,QAAQ,CAAC,8CAA8C,EAAE,eAAe,CAAC,CAAC;QACtF,CAAC;QAED,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACzE,MAAM,UAAU,GACd,OAAO,IAAI,CAAC,YAAY,CAAC,KAAK,QAAQ,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC;YAC9D,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC;YACpB,CAAC,CAAC,mBAAmB,CAAC;QAE1B,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAEhD,IAAI,UAAoB,CAAC;QACzB,IAAI,YAAY,GAAG,KAAK,CAAC;QAEzB,IAAI,CAAC;YACH,UAAU,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;QACvE,CAAC;QAAC,MAAM,CAAC;YACP,2DAA2D;YAC3D,YAAY,GAAG,IAAI,CAAC;YACpB,IAAI,CAAC;gBACH,UAAU,GAAG,MAAM,kBAAkB,CAAC,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;YAC/E,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,IAAI,QAAQ,CAAC,gBAAgB,EAAE,iBAAiB,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;YAC1E,CAAC;QACH,CAAC;QAED,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,OAAO;gBACL,MAAM,EAAE,mBAAmB;gBAC3B,QAAQ,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC,EAAE;aACjD,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAErC,OAAO;YACL,MAAM;YACN,QAAQ,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,CAAC,MAAM,EAAE;SACjE,CAAC;IACJ,CAAC;CACF,CAAC"}
@@ -0,0 +1,25 @@
1
+ export interface ToolContext {
2
+ workspaceRoot: string;
3
+ cwd: string;
4
+ }
5
+ export interface ToolResult {
6
+ output: string;
7
+ error?: string;
8
+ metadata?: Record<string, unknown>;
9
+ }
10
+ export interface ToolDefinition {
11
+ name: string;
12
+ description: string;
13
+ readonly: boolean;
14
+ parameters: {
15
+ type: 'object';
16
+ properties: Record<string, {
17
+ type: string;
18
+ description: string;
19
+ optional?: boolean;
20
+ }>;
21
+ required: string[];
22
+ };
23
+ execute(args: Record<string, unknown>, ctx: ToolContext): Promise<ToolResult>;
24
+ }
25
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/tools/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE;QACV,IAAI,EAAE,QAAQ,CAAC;QACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;SAAE,CAAC,CAAC;QACtF,QAAQ,EAAE,MAAM,EAAE,CAAC;KACpB,CAAC;IACF,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CAC/E"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/tools/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ import type { ToolDefinition } from './types.js';
2
+ export declare const writeFileTool: ToolDefinition;
3
+ //# sourceMappingURL=write_file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write_file.d.ts","sourceRoot":"","sources":["../../src/tools/write_file.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAA2B,MAAM,YAAY,CAAC;AAE1E,eAAO,MAAM,aAAa,EAAE,cAqE3B,CAAC"}
@@ -0,0 +1,61 @@
1
+ import { writeFile, appendFile, mkdir } from 'node:fs/promises';
2
+ import { resolve, dirname } from 'node:path';
3
+ import { JamError } from '../utils/errors.js';
4
+ export const writeFileTool = {
5
+ name: 'write_file',
6
+ description: 'Write or append content to a file. Creates parent directories if they do not exist.',
7
+ readonly: false,
8
+ parameters: {
9
+ type: 'object',
10
+ properties: {
11
+ path: { type: 'string', description: 'Path to the file, relative to workspace root.' },
12
+ content: { type: 'string', description: 'Content to write to the file.' },
13
+ mode: {
14
+ type: 'string',
15
+ description: '"overwrite" (default) replaces the file; "append" adds to the end.',
16
+ optional: true,
17
+ },
18
+ },
19
+ required: ['path', 'content'],
20
+ },
21
+ async execute(args, ctx) {
22
+ const filePath = args['path'];
23
+ if (typeof filePath !== 'string' || filePath.trim() === '') {
24
+ throw new JamError('Argument "path" must be a non-empty string.', 'INPUT_MISSING');
25
+ }
26
+ const content = args['content'];
27
+ if (typeof content !== 'string') {
28
+ throw new JamError('Argument "content" must be a string.', 'INPUT_MISSING');
29
+ }
30
+ const mode = args['mode'] === 'append' ? 'append' : 'overwrite';
31
+ const absolutePath = resolve(ctx.workspaceRoot, filePath);
32
+ const parentDir = dirname(absolutePath);
33
+ try {
34
+ await mkdir(parentDir, { recursive: true });
35
+ }
36
+ catch (err) {
37
+ throw new JamError(`Failed to create parent directories for: ${filePath}`, 'TOOL_EXEC_ERROR', { cause: err });
38
+ }
39
+ const byteLength = Buffer.byteLength(content, 'utf8');
40
+ try {
41
+ if (mode === 'append') {
42
+ await appendFile(absolutePath, content, 'utf8');
43
+ }
44
+ else {
45
+ await writeFile(absolutePath, content, 'utf8');
46
+ }
47
+ }
48
+ catch (err) {
49
+ throw new JamError(`Failed to write file: ${filePath}`, 'TOOL_EXEC_ERROR', { cause: err });
50
+ }
51
+ return {
52
+ output: `Written ${byteLength} bytes to ${filePath}`,
53
+ metadata: {
54
+ path: absolutePath,
55
+ mode,
56
+ bytes: byteLength,
57
+ },
58
+ };
59
+ },
60
+ };
61
+ //# sourceMappingURL=write_file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write_file.js","sourceRoot":"","sources":["../../src/tools/write_file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAG9C,MAAM,CAAC,MAAM,aAAa,GAAmB;IAC3C,IAAI,EAAE,YAAY;IAClB,WAAW,EACT,qFAAqF;IACvF,QAAQ,EAAE,KAAK;IACf,UAAU,EAAE;QACV,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,+CAA+C,EAAE;YACtF,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,+BAA+B,EAAE;YACzE,IAAI,EAAE;gBACJ,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,oEAAoE;gBACjF,QAAQ,EAAE,IAAI;aACf;SACF;QACD,QAAQ,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC;KAC9B;IAED,KAAK,CAAC,OAAO,CAAC,IAA6B,EAAE,GAAgB;QAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;QAC9B,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YAC3D,MAAM,IAAI,QAAQ,CAAC,6CAA6C,EAAE,eAAe,CAAC,CAAC;QACrF,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;QAChC,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAChC,MAAM,IAAI,QAAQ,CAAC,sCAAsC,EAAE,eAAe,CAAC,CAAC;QAC9E,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC;QAChE,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;QAC1D,MAAM,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;QAExC,IAAI,CAAC;YACH,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,QAAQ,CAChB,4CAA4C,QAAQ,EAAE,EACtD,iBAAiB,EACjB,EAAE,KAAK,EAAE,GAAG,EAAE,CACf,CAAC;QACJ,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAEtD,IAAI,CAAC;YACH,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACtB,MAAM,UAAU,CAAC,YAAY,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;YAClD,CAAC;iBAAM,CAAC;gBACN,MAAM,SAAS,CAAC,YAAY,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;YACjD,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,QAAQ,CAChB,yBAAyB,QAAQ,EAAE,EACnC,iBAAiB,EACjB,EAAE,KAAK,EAAE,GAAG,EAAE,CACf,CAAC;QACJ,CAAC;QAED,OAAO;YACL,MAAM,EAAE,WAAW,UAAU,aAAa,QAAQ,EAAE;YACpD,QAAQ,EAAE;gBACR,IAAI,EAAE,YAAY;gBAClB,IAAI;gBACJ,KAAK,EAAE,UAAU;aAClB;SACF,CAAC;IACJ,CAAC;CACF,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { ProviderAdapter, Message } from '../providers/base.js';
2
+ import type { JamConfig } from '../config/schema.js';
3
+ export interface ChatOptions {
4
+ provider: ProviderAdapter;
5
+ config: JamConfig;
6
+ sessionId: string;
7
+ initialMessages: Message[];
8
+ }
9
+ export declare function startChat(options: ChatOptions): Promise<void>;
10
+ //# sourceMappingURL=chat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../src/ui/chat.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGrD,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,eAAe,CAAC;IAC1B,MAAM,EAAE,SAAS,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,OAAO,EAAE,CAAC;CAC5B;AAkRD,wBAAsB,SAAS,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAWnE"}
@@ -0,0 +1,173 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useEffect, useCallback, useRef } from 'react';
3
+ import { render, Box, Text, useApp, useInput, Static } from 'ink';
4
+ import TextInput from 'ink-text-input';
5
+ import { appendMessage } from '../storage/history.js';
6
+ function formatRole(role) {
7
+ switch (role) {
8
+ case 'user':
9
+ return 'You';
10
+ case 'assistant':
11
+ return 'Jam';
12
+ case 'system':
13
+ return 'System';
14
+ default:
15
+ return role;
16
+ }
17
+ }
18
+ function MessageItem({ message }) {
19
+ const roleColor = message.role === 'user' ? 'blue' : message.role === 'assistant' ? 'green' : 'gray';
20
+ return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Text, { color: roleColor, bold: true, children: formatRole(message.role) }), _jsx(Text, { children: message.content })] }));
21
+ }
22
+ function ChatApp({ provider, config, sessionId, initialMessages, }) {
23
+ const { exit } = useApp();
24
+ // Messages that have been fully committed (shown via Static)
25
+ const [committedMessages, setCommittedMessages] = useState(() => initialMessages
26
+ .filter((m) => m.role !== 'system')
27
+ .map((m) => ({
28
+ role: m.role,
29
+ content: m.content,
30
+ timestamp: new Date().toISOString(),
31
+ })));
32
+ // Current in-progress assistant streaming text
33
+ const [streamingText, setStreamingText] = useState('');
34
+ // Whether we are currently streaming
35
+ const [isStreaming, setIsStreaming] = useState(false);
36
+ // Whether we are waiting for the first chunk (show spinner)
37
+ const [isThinking, setIsThinking] = useState(false);
38
+ // Error message to display
39
+ const [errorMessage, setErrorMessage] = useState(null);
40
+ // User's current input
41
+ const [inputValue, setInputValue] = useState('');
42
+ // Whether input is disabled (during streaming)
43
+ const [inputDisabled, setInputDisabled] = useState(false);
44
+ // Abort controller ref for cancelling generation
45
+ const abortRef = useRef(null);
46
+ // Track ctrl-c timing for double-press exit
47
+ const lastCtrlCRef = useRef(0);
48
+ // Conversation history for the provider (includes all roles)
49
+ const conversationRef = useRef(initialMessages);
50
+ useInput((_input, key) => {
51
+ if (key.ctrl && _input === 'c') {
52
+ const now = Date.now();
53
+ if (isStreaming) {
54
+ // First Ctrl-C during streaming: abort current generation
55
+ if (abortRef.current) {
56
+ abortRef.current.abort();
57
+ }
58
+ return;
59
+ }
60
+ // Double Ctrl-C within 1 second: exit
61
+ if (now - lastCtrlCRef.current < 1000) {
62
+ exit();
63
+ return;
64
+ }
65
+ lastCtrlCRef.current = now;
66
+ }
67
+ });
68
+ const handleSubmit = useCallback(async (value) => {
69
+ const trimmed = value.trim();
70
+ if (!trimmed || inputDisabled)
71
+ return;
72
+ setInputValue('');
73
+ setErrorMessage(null);
74
+ const userMessage = { role: 'user', content: trimmed };
75
+ const userDisplay = {
76
+ role: 'user',
77
+ content: trimmed,
78
+ timestamp: new Date().toISOString(),
79
+ };
80
+ // Persist user message
81
+ try {
82
+ await appendMessage(sessionId, userMessage);
83
+ }
84
+ catch {
85
+ // Non-fatal; continue
86
+ }
87
+ // Add to committed messages display
88
+ setCommittedMessages((prev) => [...prev, userDisplay]);
89
+ // Update conversation history
90
+ conversationRef.current = [...conversationRef.current, userMessage];
91
+ // Start streaming
92
+ setIsThinking(true);
93
+ setIsStreaming(true);
94
+ setInputDisabled(true);
95
+ const profile = config.profiles[config.defaultProfile];
96
+ const abortController = new AbortController();
97
+ abortRef.current = abortController;
98
+ let fullResponse = '';
99
+ let interrupted = false;
100
+ try {
101
+ const stream = provider.streamCompletion({
102
+ messages: conversationRef.current,
103
+ model: profile?.model,
104
+ temperature: profile?.temperature,
105
+ maxTokens: profile?.maxTokens,
106
+ systemPrompt: profile?.systemPrompt,
107
+ });
108
+ for await (const chunk of stream) {
109
+ if (abortController.signal.aborted) {
110
+ interrupted = true;
111
+ break;
112
+ }
113
+ if (!chunk.done) {
114
+ fullResponse += chunk.delta;
115
+ setIsThinking(false);
116
+ setStreamingText(fullResponse);
117
+ }
118
+ }
119
+ }
120
+ catch (err) {
121
+ if (!abortController.signal.aborted) {
122
+ const message = err instanceof Error ? err.message : String(err);
123
+ setErrorMessage(`Error: ${message}`);
124
+ }
125
+ else {
126
+ interrupted = true;
127
+ }
128
+ }
129
+ // Finalize the streamed message
130
+ const finalContent = interrupted
131
+ ? fullResponse + (fullResponse ? '\n[Generation interrupted]' : '[Generation interrupted]')
132
+ : fullResponse;
133
+ setStreamingText('');
134
+ setIsThinking(false);
135
+ setIsStreaming(false);
136
+ setInputDisabled(false);
137
+ abortRef.current = null;
138
+ if (finalContent) {
139
+ const assistantMessage = { role: 'assistant', content: finalContent };
140
+ const assistantDisplay = {
141
+ role: 'assistant',
142
+ content: finalContent,
143
+ timestamp: new Date().toISOString(),
144
+ };
145
+ // Persist assistant message
146
+ try {
147
+ await appendMessage(sessionId, assistantMessage);
148
+ }
149
+ catch {
150
+ // Non-fatal; continue
151
+ }
152
+ conversationRef.current = [...conversationRef.current, assistantMessage];
153
+ setCommittedMessages((prev) => [...prev, assistantDisplay]);
154
+ }
155
+ }, [inputDisabled, sessionId, config, provider]);
156
+ // Spinner frames for "Thinking..."
157
+ const [spinnerFrame, setSpinnerFrame] = useState(0);
158
+ const spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
159
+ useEffect(() => {
160
+ if (!isThinking)
161
+ return;
162
+ const timer = setInterval(() => {
163
+ setSpinnerFrame((f) => (f + 1) % spinnerFrames.length);
164
+ }, 80);
165
+ return () => clearInterval(timer);
166
+ }, [isThinking, spinnerFrames.length]);
167
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Static, { items: committedMessages, children: (message, index) => _jsx(MessageItem, { message: message }, index) }), isThinking && (_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { color: "yellow", children: [spinnerFrames[spinnerFrame] ?? '⠋', " Thinking..."] }) })), streamingText !== '' && (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Text, { color: "green", bold: true, children: "Jam" }), _jsx(Text, { children: streamingText })] })), errorMessage !== null && (_jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: "red", children: errorMessage }) })), _jsxs(Box, { children: [_jsx(Text, { color: "blue", bold: true, children: '> ' }), _jsx(TextInput, { value: inputValue, onChange: setInputValue, onSubmit: (val) => { void handleSubmit(val); }, placeholder: inputDisabled ? 'Generating...' : 'Ask something... (Ctrl-C twice to exit)', focus: !inputDisabled })] })] }));
168
+ }
169
+ export async function startChat(options) {
170
+ const { waitUntilExit } = render(_jsx(ChatApp, { provider: options.provider, config: options.config, sessionId: options.sessionId, initialMessages: options.initialMessages }));
171
+ await waitUntilExit();
172
+ }
173
+ //# sourceMappingURL=chat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat.js","sourceRoot":"","sources":["../../src/ui/chat.tsx"],"names":[],"mappings":"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"}