@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,14 @@
1
+ /**
2
+ * JAM — ASCII logo and banner
3
+ *
4
+ * Plain text version is embedded in the README and shown in `--help`.
5
+ * The coloured version (ANSI escape codes, no deps) is shown at startup.
6
+ */
7
+ /** Plain-text logo — used in README and non-TTY environments. */
8
+ export declare const LOGO_PLAIN: string;
9
+ /**
10
+ * Print the logo banner to stdout.
11
+ * Automatically uses ANSI colours when stdout is a TTY.
12
+ */
13
+ export declare function printLogo(noColor?: boolean): void;
14
+ //# sourceMappingURL=logo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logo.d.ts","sourceRoot":"","sources":["../../src/ui/logo.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAkFH,iEAAiE;AACjE,eAAO,MAAM,UAAU,QAAe,CAAC;AAEvC;;;GAGG;AACH,wBAAgB,SAAS,CAAC,OAAO,UAAQ,GAAG,IAAI,CAG/C"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * JAM — ASCII logo and banner
3
+ *
4
+ * Plain text version is embedded in the README and shown in `--help`.
5
+ * The coloured version (ANSI escape codes, no deps) is shown at startup.
6
+ */
7
+ // ── Raw letter art (block-character figlet style) ────────────────────────────
8
+ const LETTERS = [
9
+ ' ██╗ █████╗ ███╗ ███╗',
10
+ ' ██║ ██╔══██╗ ████╗ ████║',
11
+ ' ██║ ███████║ ██╔████╔██║',
12
+ ' ██ ██║ ██╔══██║ ██║╚██╔╝██║',
13
+ ' ╚████╔╝ ██║ ██║ ██║ ╚═╝ ██║',
14
+ ' ╚═══╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝',
15
+ ];
16
+ const TAGLINE = 'developer-first AI CLI';
17
+ const PAD = 3; // spaces between content and border │
18
+ // ── ANSI helpers (no deps — safe to call synchronously) ─────────────────────
19
+ const A = {
20
+ reset: '\x1b[0m',
21
+ dim: '\x1b[2m',
22
+ bold: '\x1b[1m',
23
+ gold: '\x1b[38;2;255;215;0m', // #FFD700
24
+ muted: '\x1b[38;2;136;136;136m', // #888
25
+ };
26
+ function ansi(code, text) {
27
+ return `${code}${text}${A.reset}`;
28
+ }
29
+ // ── Computed dimensions ───────────────────────────────────────────────────────
30
+ const contentWidth = Math.max(...LETTERS.map(l => l.length), TAGLINE.length);
31
+ const innerWidth = contentWidth + PAD * 2;
32
+ const hr = '─'.repeat(innerWidth);
33
+ const tagPad = ' '.repeat(Math.floor((contentWidth - TAGLINE.length) / 2));
34
+ // ── Build plain box ──────────────────────────────────────────────────────────
35
+ function buildPlain() {
36
+ const border = (s) => `│ ${s.padEnd(innerWidth - 2)} │`;
37
+ const blank = `│${' '.repeat(innerWidth)}│`;
38
+ return [
39
+ `╭${hr}╮`,
40
+ blank,
41
+ ...LETTERS.map(border),
42
+ blank,
43
+ border(`${tagPad}${TAGLINE}`),
44
+ blank,
45
+ `╰${hr}╯`,
46
+ ].join('\n');
47
+ }
48
+ // ── Build coloured box (synchronous ANSI, no chalk needed) ──────────────────
49
+ function buildColored() {
50
+ const pad = (s) => s + ' '.repeat(innerWidth - 2 - s.length);
51
+ const blank = ansi(A.dim, `│${' '.repeat(innerWidth)}│`);
52
+ const boxLine = (middle) => ansi(A.dim, '│ ') + middle + ansi(A.dim, ' │');
53
+ const letterLines = LETTERS.map(l => boxLine(pad(ansi(A.bold + A.gold, l))));
54
+ const tagContent = `${tagPad}${ansi(A.muted, TAGLINE)}`;
55
+ return [
56
+ ansi(A.dim, `╭${hr}╮`),
57
+ blank,
58
+ ...letterLines,
59
+ blank,
60
+ boxLine(pad(tagContent)),
61
+ blank,
62
+ ansi(A.dim, `╰${hr}╯`),
63
+ ].join('\n');
64
+ }
65
+ // ── Public exports ───────────────────────────────────────────────────────────
66
+ /** Plain-text logo — used in README and non-TTY environments. */
67
+ export const LOGO_PLAIN = buildPlain();
68
+ /**
69
+ * Print the logo banner to stdout.
70
+ * Automatically uses ANSI colours when stdout is a TTY.
71
+ */
72
+ export function printLogo(noColor = false) {
73
+ const useColor = !noColor && process.stdout.isTTY;
74
+ process.stdout.write((useColor ? buildColored() : LOGO_PLAIN) + '\n\n');
75
+ }
76
+ //# sourceMappingURL=logo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logo.js","sourceRoot":"","sources":["../../src/ui/logo.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,gFAAgF;AAEhF,MAAM,OAAO,GAAG;IACd,+BAA+B;IAC/B,+BAA+B;IAC/B,+BAA+B;IAC/B,+BAA+B;IAC/B,+BAA+B;IAC/B,+BAA+B;CAChC,CAAC;AAEF,MAAM,OAAO,GAAG,0BAA0B,CAAC;AAC3C,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,sCAAsC;AAErD,+EAA+E;AAE/E,MAAM,CAAC,GAAG;IACR,KAAK,EAAI,SAAS;IAClB,GAAG,EAAM,SAAS;IAClB,IAAI,EAAK,SAAS;IAClB,IAAI,EAAK,sBAAsB,EAAI,UAAU;IAC7C,KAAK,EAAI,wBAAwB,EAAE,OAAO;CAClC,CAAC;AAEX,SAAS,IAAI,CAAC,IAAY,EAAE,IAAY;IACtC,OAAO,GAAG,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC;AACpC,CAAC;AAED,iFAAiF;AAEjF,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;AAC7E,MAAM,UAAU,GAAK,YAAY,GAAG,GAAG,GAAG,CAAC,CAAC;AAC5C,MAAM,EAAE,GAAa,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;AAC5C,MAAM,MAAM,GAAS,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAEjF,gFAAgF;AAEhF,SAAS,UAAU;IACjB,MAAM,MAAM,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,GAAG,CAAC,CAAC,IAAI,CAAC;IAChE,MAAM,KAAK,GAAI,IAAI,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC;IAE7C,OAAO;QACL,IAAI,EAAE,GAAG;QACT,KAAK;QACL,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;QACtB,KAAK;QACL,MAAM,CAAC,GAAG,MAAM,GAAG,OAAO,EAAE,CAAC;QAC7B,KAAK;QACL,IAAI,EAAE,GAAG;KACV,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,+EAA+E;AAE/E,SAAS,YAAY;IACnB,MAAM,GAAG,GAAK,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,UAAU,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;IACvE,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IAEzD,MAAM,OAAO,GAAG,CAAC,MAAc,EAAE,EAAE,CACjC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAEjD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAClC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CACvC,CAAC;IAEF,MAAM,UAAU,GAAG,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,CAAC;IAExD,OAAO;QACL,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC;QACtB,KAAK;QACL,GAAG,WAAW;QACd,KAAK;QACL,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACxB,KAAK;QACL,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC;KACvB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,gFAAgF;AAEhF,iEAAiE;AACjE,MAAM,CAAC,MAAM,UAAU,GAAG,UAAU,EAAE,CAAC;AAEvC;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,OAAO,GAAG,KAAK;IACvC,MAAM,QAAQ,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;IAClD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,MAAM,CAAC,CAAC;AAC1E,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { StreamChunk } from '../providers/base.js';
2
+ export declare function renderMarkdown(text: string): Promise<string>;
3
+ export declare function streamToStdout(stream: AsyncIterable<StreamChunk>): Promise<{
4
+ text: string;
5
+ usage?: StreamChunk['usage'];
6
+ }>;
7
+ export declare function printJsonResult(result: {
8
+ response: string;
9
+ usage?: StreamChunk['usage'];
10
+ model?: string;
11
+ }): void;
12
+ export declare function printError(message: string): Promise<void>;
13
+ export declare function printWarning(message: string): Promise<void>;
14
+ export declare function printSuccess(message: string): Promise<void>;
15
+ //# sourceMappingURL=renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/ui/renderer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAyBxD,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAMlE;AAED,wBAAsB,cAAc,CAClC,MAAM,EAAE,aAAa,CAAC,WAAW,CAAC,GACjC,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,WAAW,CAAC,OAAO,CAAC,CAAA;CAAE,CAAC,CAmBzD;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,IAAI,CAEP;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG/D;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGjE;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGjE"}
@@ -0,0 +1,61 @@
1
+ import { marked } from 'marked';
2
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3
+ let terminalRenderer = null;
4
+ let chalkInstance = null;
5
+ async function getChalk() {
6
+ if (!chalkInstance) {
7
+ const mod = await import('chalk');
8
+ chalkInstance = mod.default;
9
+ }
10
+ return chalkInstance;
11
+ }
12
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
+ async function getTerminalRenderer() {
14
+ if (!terminalRenderer) {
15
+ const { default: TerminalRenderer } = await import('marked-terminal');
16
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
17
+ terminalRenderer = new TerminalRenderer();
18
+ }
19
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
20
+ return terminalRenderer;
21
+ }
22
+ export async function renderMarkdown(text) {
23
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
24
+ const renderer = await getTerminalRenderer();
25
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-argument
26
+ marked.use({ renderer });
27
+ return marked(text);
28
+ }
29
+ export async function streamToStdout(stream) {
30
+ let text = '';
31
+ let usage;
32
+ for await (const chunk of stream) {
33
+ if (chunk.done) {
34
+ usage = chunk.usage;
35
+ continue;
36
+ }
37
+ text += chunk.delta;
38
+ process.stdout.write(chunk.delta);
39
+ }
40
+ // End with newline if content doesn't end with one
41
+ if (text && !text.endsWith('\n')) {
42
+ process.stdout.write('\n');
43
+ }
44
+ return { text, usage };
45
+ }
46
+ export function printJsonResult(result) {
47
+ process.stdout.write(JSON.stringify(result, null, 2) + '\n');
48
+ }
49
+ export async function printError(message) {
50
+ const ck = await getChalk();
51
+ process.stderr.write(ck.red(`Error: ${message}`) + '\n');
52
+ }
53
+ export async function printWarning(message) {
54
+ const ck = await getChalk();
55
+ process.stderr.write(ck.yellow(`Warning: ${message}`) + '\n');
56
+ }
57
+ export async function printSuccess(message) {
58
+ const ck = await getChalk();
59
+ process.stderr.write(ck.green(message) + '\n');
60
+ }
61
+ //# sourceMappingURL=renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.js","sourceRoot":"","sources":["../../src/ui/renderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIhC,8DAA8D;AAC9D,IAAI,gBAAgB,GAAQ,IAAI,CAAC;AACjC,IAAI,aAAa,GAAyB,IAAI,CAAC;AAE/C,KAAK,UAAU,QAAQ;IACrB,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;QAClC,aAAa,GAAG,GAAG,CAAC,OAAO,CAAC;IAC9B,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,8DAA8D;AAC9D,KAAK,UAAU,mBAAmB;IAChC,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;QACtE,sGAAsG;QACtG,gBAAgB,GAAG,IAAI,gBAAgB,EAAE,CAAC;IAC5C,CAAC;IACD,+DAA+D;IAC/D,OAAO,gBAAgB,CAAC;AAC1B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAY;IAC/C,mEAAmE;IACnE,MAAM,QAAQ,GAAG,MAAM,mBAAmB,EAAE,CAAC;IAC7C,0GAA0G;IAC1G,MAAM,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;IACzB,OAAO,MAAM,CAAC,IAAI,CAAW,CAAC;AAChC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAkC;IAElC,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,IAAI,KAA2B,CAAC;IAEhC,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QACjC,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;YACf,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;YACpB,SAAS;QACX,CAAC;QACD,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC;QACpB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC;IAED,mDAAmD;IACnD,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACjC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAI/B;IACC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAAe;IAC9C,MAAM,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;IAC5B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAe;IAChD,MAAM,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;IAC5B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,YAAY,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAe;IAChD,MAAM,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;IAC5B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;AACjD,CAAC"}
@@ -0,0 +1,14 @@
1
+ export type ErrorCode = 'CONFIG_INVALID' | 'CONFIG_NOT_FOUND' | 'PROVIDER_AUTH_FAILED' | 'PROVIDER_UNAVAILABLE' | 'PROVIDER_RATE_LIMITED' | 'PROVIDER_STREAM_ERROR' | 'PROVIDER_MODEL_NOT_FOUND' | 'INPUT_MISSING' | 'INPUT_FILE_NOT_FOUND' | 'SECRETS_UNAVAILABLE' | 'TOOL_DENIED' | 'TOOL_NOT_FOUND' | 'TOOL_EXEC_ERROR' | 'UNKNOWN';
2
+ export declare class JamError extends Error {
3
+ readonly code: ErrorCode;
4
+ readonly retryable: boolean;
5
+ readonly statusCode?: number;
6
+ constructor(message: string, code: ErrorCode, options?: {
7
+ retryable?: boolean;
8
+ statusCode?: number;
9
+ cause?: unknown;
10
+ });
11
+ static isJamError(err: unknown): err is JamError;
12
+ static fromUnknown(err: unknown, fallbackCode?: ErrorCode): JamError;
13
+ }
14
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GACjB,gBAAgB,GAChB,kBAAkB,GAClB,sBAAsB,GACtB,sBAAsB,GACtB,uBAAuB,GACvB,uBAAuB,GACvB,0BAA0B,GAC1B,eAAe,GACf,sBAAsB,GACtB,qBAAqB,GACrB,aAAa,GACb,gBAAgB,GAChB,iBAAiB,GACjB,SAAS,CAAC;AAEd,qBAAa,QAAS,SAAQ,KAAK;IACjC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;gBAG3B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,EACf,OAAO,GAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO;IAW7E,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,QAAQ;IAIhD,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,YAAY,GAAE,SAAqB,GAAG,QAAQ;CAOhF"}
@@ -0,0 +1,26 @@
1
+ export class JamError extends Error {
2
+ code;
3
+ retryable;
4
+ statusCode;
5
+ constructor(message, code, options = {}) {
6
+ super(message, { cause: options.cause });
7
+ this.name = 'JamError';
8
+ this.code = code;
9
+ this.retryable = options.retryable ?? false;
10
+ if (options.statusCode !== undefined) {
11
+ this.statusCode = options.statusCode;
12
+ }
13
+ }
14
+ static isJamError(err) {
15
+ return err instanceof JamError;
16
+ }
17
+ static fromUnknown(err, fallbackCode = 'UNKNOWN') {
18
+ if (err instanceof JamError)
19
+ return err;
20
+ if (err instanceof Error) {
21
+ return new JamError(err.message, fallbackCode, { cause: err });
22
+ }
23
+ return new JamError(String(err), fallbackCode);
24
+ }
25
+ }
26
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAgBA,MAAM,OAAO,QAAS,SAAQ,KAAK;IACxB,IAAI,CAAY;IAChB,SAAS,CAAU;IACnB,UAAU,CAAU;IAE7B,YACE,OAAe,EACf,IAAe,EACf,UAAyE,EAAE;QAE3E,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC;QAC5C,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YACrC,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QACvC,CAAC;IACH,CAAC;IAED,MAAM,CAAC,UAAU,CAAC,GAAY;QAC5B,OAAO,GAAG,YAAY,QAAQ,CAAC;IACjC,CAAC;IAED,MAAM,CAAC,WAAW,CAAC,GAAY,EAAE,eAA0B,SAAS;QAClE,IAAI,GAAG,YAAY,QAAQ;YAAE,OAAO,GAAG,CAAC;QACxC,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;YACzB,OAAO,IAAI,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,IAAI,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,YAAY,CAAC,CAAC;IACjD,CAAC;CACF"}
@@ -0,0 +1,17 @@
1
+ type LogLevel = 'silent' | 'error' | 'warn' | 'info' | 'debug';
2
+ export declare class Logger {
3
+ private level;
4
+ private patterns;
5
+ constructor(level?: LogLevel, redactPatterns?: string[]);
6
+ private redact;
7
+ private shouldLog;
8
+ private write;
9
+ error(message: string, ...args: unknown[]): void;
10
+ warn(message: string, ...args: unknown[]): void;
11
+ info(message: string, ...args: unknown[]): void;
12
+ debug(message: string, ...args: unknown[]): void;
13
+ setLevel(level: LogLevel): void;
14
+ }
15
+ export declare const logger: Logger;
16
+ export {};
17
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,KAAK,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAU/D,qBAAa,MAAM;IACjB,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,QAAQ,CAAW;gBAEf,KAAK,GAAE,QAAiB,EAAE,cAAc,GAAE,MAAM,EAAO;IAKnE,OAAO,CAAC,MAAM;IAQd,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,KAAK;IAOb,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAIhD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAI/C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAI/C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAIhD,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;CAGhC;AAGD,eAAO,MAAM,MAAM,QAAe,CAAC"}
@@ -0,0 +1,50 @@
1
+ const LOG_LEVELS = {
2
+ silent: 0,
3
+ error: 1,
4
+ warn: 2,
5
+ info: 3,
6
+ debug: 4,
7
+ };
8
+ export class Logger {
9
+ level;
10
+ patterns;
11
+ constructor(level = 'warn', redactPatterns = []) {
12
+ this.level = level;
13
+ this.patterns = redactPatterns.map((p) => new RegExp(p, 'gi'));
14
+ }
15
+ redact(message) {
16
+ let result = message;
17
+ for (const pattern of this.patterns) {
18
+ result = result.replace(pattern, '[REDACTED]');
19
+ }
20
+ return result;
21
+ }
22
+ shouldLog(level) {
23
+ return LOG_LEVELS[level] <= LOG_LEVELS[this.level];
24
+ }
25
+ write(level, prefix, message, ...args) {
26
+ if (!this.shouldLog(level))
27
+ return;
28
+ const redacted = this.redact(message);
29
+ const extra = args.map((a) => (typeof a === 'string' ? this.redact(a) : a));
30
+ process.stderr.write(`${prefix} ${redacted}${extra.length ? ' ' + extra.join(' ') : ''}\n`);
31
+ }
32
+ error(message, ...args) {
33
+ this.write('error', '[ERROR]', message, ...args);
34
+ }
35
+ warn(message, ...args) {
36
+ this.write('warn', '[WARN] ', message, ...args);
37
+ }
38
+ info(message, ...args) {
39
+ this.write('info', '[INFO] ', message, ...args);
40
+ }
41
+ debug(message, ...args) {
42
+ this.write('debug', '[DEBUG]', message, ...args);
43
+ }
44
+ setLevel(level) {
45
+ this.level = level;
46
+ }
47
+ }
48
+ // Singleton logger — configured at startup in src/index.ts
49
+ export const logger = new Logger();
50
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,GAA6B;IAC3C,MAAM,EAAE,CAAC;IACT,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;CACT,CAAC;AAEF,MAAM,OAAO,MAAM;IACT,KAAK,CAAW;IAChB,QAAQ,CAAW;IAE3B,YAAY,QAAkB,MAAM,EAAE,iBAA2B,EAAE;QACjE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,QAAQ,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IACjE,CAAC;IAEO,MAAM,CAAC,OAAe;QAC5B,IAAI,MAAM,GAAG,OAAO,CAAC;QACrB,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACpC,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QACjD,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,SAAS,CAAC,KAAe;QAC/B,OAAO,UAAU,CAAC,KAAK,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrD,CAAC;IAEO,KAAK,CAAC,KAAe,EAAE,MAAc,EAAE,OAAe,EAAE,GAAG,IAAe;QAChF,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;YAAE,OAAO;QACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACtC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5E,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAC9F,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,GAAG,IAAe;QACvC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;IACnD,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,GAAG,IAAe;QACtC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;IAClD,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,GAAG,IAAe;QACtC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,GAAG,IAAe;QACvC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;IACnD,CAAC;IAED,QAAQ,CAAC,KAAe;QACtB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;CACF;AAED,2DAA2D;AAC3D,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function getSecret(key: string): Promise<string | null>;
2
+ export declare function setSecret(key: string, value: string): Promise<void>;
3
+ export declare function deleteSecret(key: string): Promise<boolean>;
4
+ //# sourceMappingURL=secrets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secrets.d.ts","sourceRoot":"","sources":["../../src/utils/secrets.ts"],"names":[],"mappings":"AAIA,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAanE;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CASzE;AAED,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQhE"}
@@ -0,0 +1,39 @@
1
+ import { logger } from './logger.js';
2
+ const SERVICE_NAME = 'jam-cli';
3
+ export async function getSecret(key) {
4
+ // Try keytar first (secure OS keychain)
5
+ try {
6
+ const keytar = await import('keytar');
7
+ const value = await keytar.default.getPassword(SERVICE_NAME, key);
8
+ if (value !== null)
9
+ return value;
10
+ }
11
+ catch {
12
+ logger.debug('keytar not available, falling back to environment variables');
13
+ }
14
+ // Fall back to environment variable
15
+ const envKey = `JAM_${key.toUpperCase().replace(/-/g, '_')}`;
16
+ return process.env[envKey] ?? null;
17
+ }
18
+ export async function setSecret(key, value) {
19
+ try {
20
+ const keytar = await import('keytar');
21
+ await keytar.default.setPassword(SERVICE_NAME, key, value);
22
+ return;
23
+ }
24
+ catch {
25
+ logger.warn('keytar not available. Credentials will not be stored securely in keychain.');
26
+ logger.warn(`Set the environment variable JAM_${key.toUpperCase().replace(/-/g, '_')} instead.`);
27
+ }
28
+ }
29
+ export async function deleteSecret(key) {
30
+ try {
31
+ const keytar = await import('keytar');
32
+ return keytar.default.deletePassword(SERVICE_NAME, key);
33
+ }
34
+ catch {
35
+ logger.debug('keytar not available, nothing to delete');
36
+ return false;
37
+ }
38
+ }
39
+ //# sourceMappingURL=secrets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secrets.js","sourceRoot":"","sources":["../../src/utils/secrets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,YAAY,GAAG,SAAS,CAAC;AAE/B,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAW;IACzC,wCAAwC;IACxC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;QACtC,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;QAClE,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO,KAAK,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,CAAC,KAAK,CAAC,6DAA6D,CAAC,CAAC;IAC9E,CAAC;IAED,oCAAoC;IACpC,MAAM,MAAM,GAAG,OAAO,GAAG,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;IAC7D,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC;AACrC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAW,EAAE,KAAa;IACxD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;QACtC,MAAM,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,YAAY,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;QAC3D,OAAO;IACT,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,CAAC,IAAI,CAAC,4EAA4E,CAAC,CAAC;QAC1F,MAAM,CAAC,IAAI,CAAC,oCAAoC,GAAG,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC;IACnG,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAW;IAC5C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;QACtC,OAAO,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;IAC1D,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;QACxD,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { StreamChunk } from '../providers/base.js';
2
+ export interface RetryOptions {
3
+ maxAttempts: number;
4
+ baseDelayMs: number;
5
+ maxDelayMs: number;
6
+ }
7
+ export declare function withRetry(factory: () => AsyncIterable<StreamChunk>, options?: Partial<RetryOptions>): AsyncIterable<StreamChunk>;
8
+ export declare function collectStream(stream: AsyncIterable<StreamChunk>): Promise<{
9
+ text: string;
10
+ usage?: StreamChunk['usage'];
11
+ }>;
12
+ //# sourceMappingURL=stream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/utils/stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGxD,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAkBD,wBAAuB,SAAS,CAC9B,OAAO,EAAE,MAAM,aAAa,CAAC,WAAW,CAAC,EACzC,OAAO,GAAE,OAAO,CAAC,YAAY,CAAM,GAClC,aAAa,CAAC,WAAW,CAAC,CA6B5B;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE,aAAa,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC;IAC/E,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;CAC9B,CAAC,CAaD"}
@@ -0,0 +1,54 @@
1
+ import { JamError } from './errors.js';
2
+ const DEFAULT_RETRY_OPTIONS = {
3
+ maxAttempts: 3,
4
+ baseDelayMs: 500,
5
+ maxDelayMs: 10_000,
6
+ };
7
+ function sleep(ms) {
8
+ return new Promise((resolve) => setTimeout(resolve, ms));
9
+ }
10
+ function calcDelay(attempt, baseDelayMs, maxDelayMs) {
11
+ // Exponential backoff with jitter
12
+ const exp = Math.min(baseDelayMs * 2 ** attempt, maxDelayMs);
13
+ return exp * (0.5 + 0.5 * Math.random());
14
+ }
15
+ export async function* withRetry(factory, options = {}) {
16
+ const opts = { ...DEFAULT_RETRY_OPTIONS, ...options };
17
+ let lastError;
18
+ for (let attempt = 0; attempt < opts.maxAttempts; attempt++) {
19
+ if (attempt > 0) {
20
+ const delay = calcDelay(attempt - 1, opts.baseDelayMs, opts.maxDelayMs);
21
+ await sleep(delay);
22
+ }
23
+ try {
24
+ yield* factory();
25
+ return;
26
+ }
27
+ catch (err) {
28
+ lastError = err;
29
+ const jamErr = err instanceof JamError ? err : null;
30
+ if (!jamErr?.retryable) {
31
+ throw err;
32
+ }
33
+ if (attempt < opts.maxAttempts - 1) {
34
+ // Will retry
35
+ continue;
36
+ }
37
+ }
38
+ }
39
+ throw lastError;
40
+ }
41
+ export async function collectStream(stream) {
42
+ let text = '';
43
+ let usage;
44
+ for await (const chunk of stream) {
45
+ if (chunk.done) {
46
+ usage = chunk.usage;
47
+ }
48
+ else {
49
+ text += chunk.delta;
50
+ }
51
+ }
52
+ return { text, usage };
53
+ }
54
+ //# sourceMappingURL=stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/utils/stream.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAQvC,MAAM,qBAAqB,GAAiB;IAC1C,WAAW,EAAE,CAAC;IACd,WAAW,EAAE,GAAG;IAChB,UAAU,EAAE,MAAM;CACnB,CAAC;AAEF,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,SAAS,CAAC,OAAe,EAAE,WAAmB,EAAE,UAAkB;IACzE,kCAAkC;IAClC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,GAAG,CAAC,IAAI,OAAO,EAAE,UAAU,CAAC,CAAC;IAC7D,OAAO,GAAG,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,SAAS,CAC9B,OAAyC,EACzC,UAAiC,EAAE;IAEnC,MAAM,IAAI,GAAG,EAAE,GAAG,qBAAqB,EAAE,GAAG,OAAO,EAAE,CAAC;IACtD,IAAI,SAAkB,CAAC;IAEvB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;QAC5D,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;YAChB,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,GAAG,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;YACxE,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;QAED,IAAI,CAAC;YACH,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO;QACT,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,SAAS,GAAG,GAAG,CAAC;YAChB,MAAM,MAAM,GAAG,GAAG,YAAY,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;YAEpD,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC;gBACvB,MAAM,GAAG,CAAC;YACZ,CAAC;YAED,IAAI,OAAO,GAAG,IAAI,CAAC,WAAW,GAAG,CAAC,EAAE,CAAC;gBACnC,aAAa;gBACb,SAAS;YACX,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,SAAS,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAkC;IAIpE,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,IAAI,KAA2B,CAAC;IAEhC,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QACjC,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;YACf,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QACtB,CAAC;aAAM,CAAC;YACN,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC;QACtB,CAAC;IACH,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AACzB,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Walk up the directory tree from `startDir` to find the nearest `.git` directory.
3
+ * Falls back to `startDir` if no git root is found.
4
+ */
5
+ export declare function findGitRoot(startDir?: string): Promise<string>;
6
+ /**
7
+ * Returns the workspace root (git root if available, otherwise cwd).
8
+ */
9
+ export declare function getWorkspaceRoot(cwd?: string): Promise<string>;
10
+ /**
11
+ * Returns true if the given path is inside a git repository.
12
+ */
13
+ export declare function isGitRepo(cwd?: string): Promise<boolean>;
14
+ //# sourceMappingURL=workspace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../../src/utils/workspace.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAsB,WAAW,CAAC,QAAQ,GAAE,MAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBnF;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,CAEnF;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,OAAO,CAAC,CAG7E"}
@@ -0,0 +1,39 @@
1
+ import { access, constants } from 'node:fs/promises';
2
+ import { dirname, join } from 'node:path';
3
+ /**
4
+ * Walk up the directory tree from `startDir` to find the nearest `.git` directory.
5
+ * Falls back to `startDir` if no git root is found.
6
+ */
7
+ export async function findGitRoot(startDir = process.cwd()) {
8
+ let dir = startDir;
9
+ // eslint-disable-next-line no-constant-condition
10
+ while (true) {
11
+ const gitDir = join(dir, '.git');
12
+ try {
13
+ await access(gitDir, constants.F_OK);
14
+ return dir;
15
+ }
16
+ catch {
17
+ const parent = dirname(dir);
18
+ if (parent === dir) {
19
+ // Reached filesystem root — no git repo found
20
+ return startDir;
21
+ }
22
+ dir = parent;
23
+ }
24
+ }
25
+ }
26
+ /**
27
+ * Returns the workspace root (git root if available, otherwise cwd).
28
+ */
29
+ export async function getWorkspaceRoot(cwd = process.cwd()) {
30
+ return findGitRoot(cwd);
31
+ }
32
+ /**
33
+ * Returns true if the given path is inside a git repository.
34
+ */
35
+ export async function isGitRepo(cwd = process.cwd()) {
36
+ const root = await findGitRoot(cwd);
37
+ return root !== cwd || await access(join(cwd, '.git'), constants.F_OK).then(() => true).catch(() => false);
38
+ }
39
+ //# sourceMappingURL=workspace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../src/utils/workspace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,WAAmB,OAAO,CAAC,GAAG,EAAE;IAChE,IAAI,GAAG,GAAG,QAAQ,CAAC;IACnB,iDAAiD;IACjD,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACjC,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;YACrC,OAAO,GAAG,CAAC;QACb,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;YAC5B,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;gBACnB,8CAA8C;gBAC9C,OAAO,QAAQ,CAAC;YAClB,CAAC;YACD,GAAG,GAAG,MAAM,CAAC;QACf,CAAC;IACH,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IAChE,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IACzD,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,GAAG,CAAC,CAAC;IACpC,OAAO,IAAI,KAAK,GAAG,IAAI,MAAM,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;AAC7G,CAAC"}
package/package.json ADDED
@@ -0,0 +1,84 @@
1
+ {
2
+ "name": "@sunilp-org/jam-cli",
3
+ "version": "0.1.0",
4
+ "description": "Jam — developer-first AI assistant CLI for the terminal. Ask questions, explain code, review diffs, generate patches, and run agentic tasks powered by Ollama.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": {
8
+ "name": "Sunil Prakash",
9
+ "email": "prakashsunil@proton.me",
10
+ "url": "https://github.com/sunilp"
11
+ },
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/sunilp/jam-cli.git"
15
+ },
16
+ "bugs": {
17
+ "url": "https://github.com/sunilp/jam-cli/issues"
18
+ },
19
+ "homepage": "https://github.com/sunilp/jam-cli#readme",
20
+ "keywords": [
21
+ "ai",
22
+ "cli",
23
+ "assistant",
24
+ "terminal",
25
+ "ollama",
26
+ "llm",
27
+ "developer-tools",
28
+ "code-review",
29
+ "agentic",
30
+ "streaming",
31
+ "chat",
32
+ "patch"
33
+ ],
34
+ "engines": {
35
+ "node": ">=20"
36
+ },
37
+ "bin": {
38
+ "jam": "./dist/index.js"
39
+ },
40
+ "files": [
41
+ "dist",
42
+ "README.md",
43
+ "LICENSE"
44
+ ],
45
+ "scripts": {
46
+ "build": "tsc --project tsconfig.build.json",
47
+ "dev": "tsx src/index.ts",
48
+ "typecheck": "tsc --noEmit",
49
+ "lint": "eslint src --ext .ts,.tsx",
50
+ "format": "prettier --write \"src/**/*.{ts,tsx}\"",
51
+ "test": "vitest run",
52
+ "test:watch": "vitest",
53
+ "test:coverage": "vitest run --coverage",
54
+ "clean": "rm -rf dist"
55
+ },
56
+ "dependencies": {
57
+ "chalk": "^5.3.0",
58
+ "commander": "^12.1.0",
59
+ "cosmiconfig": "^9.0.0",
60
+ "ink": "^5.0.1",
61
+ "ink-text-input": "^6.0.0",
62
+ "keytar": "^7.9.0",
63
+ "marked": "^12.0.0",
64
+ "marked-terminal": "^7.1.0",
65
+ "minimatch": "^9.0.5",
66
+ "react": "^18.3.1",
67
+ "zod": "^3.23.8"
68
+ },
69
+ "devDependencies": {
70
+ "@types/node": "^20.14.0",
71
+ "@types/react": "^18.3.3",
72
+ "@typescript-eslint/eslint-plugin": "^7.14.1",
73
+ "@typescript-eslint/parser": "^7.14.1",
74
+ "@vitest/coverage-v8": "^1.6.0",
75
+ "eslint": "^8.57.0",
76
+ "eslint-config-prettier": "^9.1.0",
77
+ "msw": "^2.3.1",
78
+ "prettier": "^3.3.2",
79
+ "tsx": "^4.16.0",
80
+ "typescript": "^5.5.2",
81
+ "undici": "^6.19.2",
82
+ "vitest": "^1.6.0"
83
+ }
84
+ }