agent-termo 1.0.1 → 1.0.2

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 (65) hide show
  1. package/README.md +27 -2
  2. package/dist/agents/index.d.ts +5 -0
  3. package/dist/agents/index.d.ts.map +1 -0
  4. package/dist/agents/index.js +86 -0
  5. package/dist/agents/index.js.map +1 -0
  6. package/dist/cli.d.ts +3 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +97 -168
  9. package/dist/cli.js.map +4 -4
  10. package/dist/diff/index.d.ts +9 -0
  11. package/dist/diff/index.d.ts.map +1 -0
  12. package/dist/diff/index.js +213 -0
  13. package/dist/diff/index.js.map +1 -0
  14. package/dist/llm/client.d.ts +39 -0
  15. package/dist/llm/client.d.ts.map +1 -0
  16. package/dist/llm/client.js +188 -0
  17. package/dist/llm/client.js.map +1 -0
  18. package/dist/llm/models.d.ts +19 -0
  19. package/dist/llm/models.d.ts.map +1 -0
  20. package/dist/llm/models.js +45 -0
  21. package/dist/llm/models.js.map +1 -0
  22. package/dist/llm/tools.d.ts +3 -0
  23. package/dist/llm/tools.d.ts.map +1 -0
  24. package/dist/llm/tools.js +204 -0
  25. package/dist/llm/tools.js.map +1 -0
  26. package/dist/main.d.ts +2 -0
  27. package/dist/main.d.ts.map +1 -0
  28. package/dist/main.js +91 -140
  29. package/dist/main.js.map +4 -4
  30. package/dist/memory/index.d.ts +10 -0
  31. package/dist/memory/index.d.ts.map +1 -0
  32. package/dist/memory/index.js +117 -0
  33. package/dist/memory/index.js.map +1 -0
  34. package/dist/tools/index.d.ts +5 -0
  35. package/dist/tools/index.d.ts.map +1 -0
  36. package/dist/tools/index.js +334 -0
  37. package/dist/tools/index.js.map +1 -0
  38. package/dist/types/index.d.ts +119 -0
  39. package/dist/types/index.d.ts.map +1 -0
  40. package/dist/types/index.js +5 -0
  41. package/dist/types/index.js.map +1 -0
  42. package/dist/ui/index.d.ts +47 -0
  43. package/dist/ui/index.d.ts.map +1 -0
  44. package/dist/ui/index.js +321 -0
  45. package/dist/ui/index.js.map +1 -0
  46. package/dist/ui/screen.d.ts +59 -0
  47. package/dist/ui/screen.d.ts.map +1 -0
  48. package/dist/ui/screen.js +629 -0
  49. package/dist/ui/screen.js.map +1 -0
  50. package/dist/utils/ansi.d.ts +62 -0
  51. package/dist/utils/ansi.d.ts.map +1 -0
  52. package/dist/utils/ansi.js +116 -0
  53. package/dist/utils/ansi.js.map +1 -0
  54. package/dist/utils/config.d.ts +9 -0
  55. package/dist/utils/config.d.ts.map +1 -0
  56. package/dist/utils/config.js +120 -0
  57. package/dist/utils/config.js.map +1 -0
  58. package/package.json +1 -1
  59. package/src/cli.ts +1 -1
  60. package/src/llm/client.ts +24 -0
  61. package/src/llm/models.ts +55 -0
  62. package/src/main.ts +201 -75
  63. package/src/ui/index.ts +256 -389
  64. package/src/ui/screen.ts +698 -0
  65. package/src/utils/config.ts +37 -20
@@ -0,0 +1,9 @@
1
+ import type { DiffResult } from '../types/index.js';
2
+ export declare function computeDiff(original: string, proposed: string): DiffResult;
3
+ export interface DiffOptions {
4
+ contextLines?: number;
5
+ maxLines?: number;
6
+ }
7
+ export declare function applyDiffContext(diff: DiffResult, options?: DiffOptions): DiffResult;
8
+ export declare function isNoOpDiff(diff: DiffResult): boolean;
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/diff/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAY,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAI9D,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,UAAU,CA8C1E;AAiGD,MAAM,WAAW,WAAW;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,GAAE,WAAgB,GAAG,UAAU,CA6FxF;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAEpD"}
@@ -0,0 +1,213 @@
1
+ // =============================================================================
2
+ // Diff Engine — line-level diff computation for file change review
3
+ // =============================================================================
4
+ // Uses LCS (Longest Common Subsequence) to compute minimal line-level diffs.
5
+ // ── LCS-based Diff Algorithm ────────────────────────────────────────────────
6
+ export function computeDiff(original, proposed) {
7
+ const originalLines = original.split('\n');
8
+ const proposedLines = proposed.split('\n');
9
+ if (originalLines.length === 1 && originalLines[0] === '') {
10
+ const lines = proposedLines.map((content, i) => ({
11
+ type: 'add',
12
+ lineNumber: i + 1,
13
+ content,
14
+ }));
15
+ return { file: '', lines, additions: proposedLines.length, deletions: 0 };
16
+ }
17
+ if (original === proposed) {
18
+ return { file: '', lines: [], additions: 0, deletions: 0 };
19
+ }
20
+ const m = originalLines.length;
21
+ const n = proposedLines.length;
22
+ const stride = n + 1;
23
+ const table = new Int32Array((m + 1) * (n + 1));
24
+ const get = (i, j) => table[i * stride + j];
25
+ const set = (i, j, val) => { table[i * stride + j] = val; };
26
+ for (let i = 1; i <= m; i++) {
27
+ for (let j = 1; j <= n; j++) {
28
+ if (originalLines[i - 1] === proposedLines[j - 1]) {
29
+ set(i, j, get(i - 1, j - 1) + 1);
30
+ }
31
+ else {
32
+ set(i, j, Math.max(get(i - 1, j), get(i, j - 1)));
33
+ }
34
+ }
35
+ }
36
+ const ops = backtrackLCS(get, originalLines, proposedLines);
37
+ const diffLines = opsToDiffLines(ops);
38
+ let additions = 0;
39
+ let deletions = 0;
40
+ for (const line of diffLines) {
41
+ if (line.type === 'add')
42
+ additions++;
43
+ if (line.type === 'remove')
44
+ deletions++;
45
+ }
46
+ return { file: '', lines: diffLines, additions, deletions };
47
+ }
48
+ function backtrackLCS(get, a, b) {
49
+ const ops = [];
50
+ const m = a.length;
51
+ const n = b.length;
52
+ let i = m;
53
+ let j = n;
54
+ while (i > 0 || j > 0) {
55
+ if (i > 0 && j > 0 && a[i - 1] === b[j - 1]) {
56
+ ops.unshift({
57
+ type: 'same',
58
+ originalIndex: i,
59
+ proposedIndex: j,
60
+ originalLine: a[i - 1],
61
+ proposedLine: b[j - 1],
62
+ });
63
+ i--;
64
+ j--;
65
+ }
66
+ else if (j > 0 && (i === 0 || get(i, j - 1) >= get(i - 1, j))) {
67
+ ops.unshift({
68
+ type: 'add',
69
+ proposedIndex: j,
70
+ originalIndex: i,
71
+ proposedLine: b[j - 1],
72
+ });
73
+ j--;
74
+ }
75
+ else {
76
+ ops.unshift({
77
+ type: 'remove',
78
+ originalIndex: i,
79
+ proposedIndex: j,
80
+ originalLine: a[i - 1],
81
+ });
82
+ i--;
83
+ }
84
+ }
85
+ return ops;
86
+ }
87
+ function opsToDiffLines(ops) {
88
+ const lines = [];
89
+ let originalLineNum = 0;
90
+ let proposedLineNum = 0;
91
+ for (const op of ops) {
92
+ switch (op.type) {
93
+ case 'same': {
94
+ originalLineNum++;
95
+ proposedLineNum++;
96
+ lines.push({
97
+ type: 'context',
98
+ lineNumber: originalLineNum,
99
+ content: op.originalLine ?? '',
100
+ });
101
+ break;
102
+ }
103
+ case 'remove': {
104
+ originalLineNum++;
105
+ lines.push({
106
+ type: 'remove',
107
+ lineNumber: originalLineNum,
108
+ content: op.originalLine ?? '',
109
+ });
110
+ break;
111
+ }
112
+ case 'add': {
113
+ proposedLineNum++;
114
+ lines.push({
115
+ type: 'add',
116
+ lineNumber: proposedLineNum,
117
+ content: op.proposedLine ?? '',
118
+ });
119
+ break;
120
+ }
121
+ }
122
+ }
123
+ return lines;
124
+ }
125
+ export function applyDiffContext(diff, options = {}) {
126
+ const { contextLines = 3, maxLines = 0 } = options;
127
+ if (contextLines <= 0 && maxLines <= 0) {
128
+ return diff;
129
+ }
130
+ // Identify contiguous change regions
131
+ const changeRegions = [];
132
+ let inChange = false;
133
+ let regionStart = 0;
134
+ for (let i = 0; i < diff.lines.length; i++) {
135
+ const line = diff.lines[i];
136
+ if (line.type === 'add' || line.type === 'remove') {
137
+ if (!inChange) {
138
+ regionStart = i;
139
+ inChange = true;
140
+ }
141
+ }
142
+ else {
143
+ if (inChange) {
144
+ changeRegions.push({ start: regionStart, end: i - 1 });
145
+ inChange = false;
146
+ }
147
+ }
148
+ }
149
+ if (inChange) {
150
+ changeRegions.push({ start: regionStart, end: diff.lines.length - 1 });
151
+ }
152
+ // Build merged ranges — use parallel arrays to avoid tuple strict-null issues
153
+ // All accesses use ! because arrays are never sparse at these indices
154
+ const mergeStarts = [];
155
+ const mergeEnds = [];
156
+ for (const region of changeRegions) {
157
+ const start = Math.max(0, region.start - contextLines);
158
+ const end = Math.min(diff.lines.length - 1, region.end + contextLines);
159
+ const lastIdx = mergeStarts.length - 1;
160
+ if (mergeStarts.length > 0 && start <= mergeEnds[lastIdx] + 1) {
161
+ mergeEnds[lastIdx] = Math.max(mergeEnds[lastIdx], end);
162
+ }
163
+ else {
164
+ mergeStarts.push(start);
165
+ mergeEnds.push(end);
166
+ }
167
+ }
168
+ // Build filtered diff lines with ellipsis between non-adjacent ranges
169
+ const filteredLines = [];
170
+ for (let r = 0; r < mergeStarts.length; r++) {
171
+ const rangeStart = mergeStarts[r];
172
+ const rangeEnd = mergeEnds[r];
173
+ const prevEnd = r > 0 ? mergeEnds[r - 1] : -1;
174
+ if (r > 0 && rangeStart > prevEnd + 1) {
175
+ const omitted = rangeStart - prevEnd - 1;
176
+ filteredLines.push({
177
+ type: 'context',
178
+ lineNumber: 0,
179
+ content: '... ' + omitted + ' unchanged lines omitted ...',
180
+ });
181
+ }
182
+ for (let i = rangeStart; i <= rangeEnd; i++) {
183
+ const line = diff.lines[i];
184
+ filteredLines.push(line);
185
+ }
186
+ }
187
+ let finalLines = filteredLines;
188
+ if (maxLines > 0 && finalLines.length > maxLines) {
189
+ const halfMax = Math.floor(maxLines / 2);
190
+ finalLines = [
191
+ ...finalLines.slice(0, halfMax),
192
+ {
193
+ type: 'context',
194
+ lineNumber: 0,
195
+ content: '... ' + (finalLines.length - maxLines) + ' more lines ...',
196
+ },
197
+ ...finalLines.slice(finalLines.length - halfMax),
198
+ ];
199
+ }
200
+ let additions = 0;
201
+ let deletions = 0;
202
+ for (const line of finalLines) {
203
+ if (line.type === 'add')
204
+ additions++;
205
+ if (line.type === 'remove')
206
+ deletions++;
207
+ }
208
+ return { ...diff, lines: finalLines, additions, deletions };
209
+ }
210
+ export function isNoOpDiff(diff) {
211
+ return diff.lines.length === 0 && diff.additions === 0 && diff.deletions === 0;
212
+ }
213
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/diff/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import OpenAI from 'openai';
2
+ import type { ToolCall, ConversationMessage, ToolDef } from '../types/index.js';
3
+ import { type ModelInfo } from './models.js';
4
+ type NIMTool = OpenAI.Chat.ChatCompletionTool;
5
+ export declare class NimClient {
6
+ private client;
7
+ private model;
8
+ constructor(_projectRoot?: string);
9
+ buildToolDefs(toolSchemas: ToolDef[]): NIMTool[];
10
+ getModel(): string;
11
+ setModel(model: string): void;
12
+ /**
13
+ * Fetch the models this API key can use. Never throws: on failure the curated
14
+ * list is returned with `live: false` and the reason in `error`.
15
+ */
16
+ listModels(): Promise<{
17
+ models: ModelInfo[];
18
+ live: boolean;
19
+ error?: string;
20
+ }>;
21
+ /**
22
+ * Streaming chat completion.
23
+ * Handles Stepfun's quirks: filters "null" reasoning chunks, strips reasoning field.
24
+ * Yields { content, toolCalls } at the end with clean text.
25
+ */
26
+ streamComplete(messages: ConversationMessage[], tools?: NIMTool[], onChunk?: (text: string) => void): AsyncGenerator<{
27
+ content: string;
28
+ toolCalls: ToolCall[];
29
+ }, void, unknown>;
30
+ /**
31
+ * Non-streaming completion — for when streaming fails or for retries.
32
+ */
33
+ complete(messages: ConversationMessage[], tools?: NIMTool[]): Promise<{
34
+ content: string;
35
+ toolCalls: ToolCall[];
36
+ }>;
37
+ }
38
+ export { type ToolDef } from '../types/index.js';
39
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/llm/client.ts"],"names":[],"mappings":"AAIA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,KAAK,EAAE,QAAQ,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAChF,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAE1D,KAAK,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC;AAE9C,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,KAAK,CAAS;gBAEV,YAAY,CAAC,EAAE,MAAM;IAcjC,aAAa,CAAC,WAAW,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE;IAWhD,QAAQ,IAAI,MAAM;IAIlB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI7B;;;OAGG;IACG,UAAU,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,SAAS,EAAE,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAenF;;;;OAIG;IACI,cAAc,CACnB,QAAQ,EAAE,mBAAmB,EAAE,EAC/B,KAAK,CAAC,EAAE,OAAO,EAAE,EACjB,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAC/B,cAAc,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,QAAQ,EAAE,CAAA;KAAE,EAAE,IAAI,EAAE,OAAO,CAAC;IA4E5E;;OAEG;IACG,QAAQ,CACZ,QAAQ,EAAE,mBAAmB,EAAE,EAC/B,KAAK,CAAC,EAAE,OAAO,EAAE,GAChB,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,QAAQ,EAAE,CAAA;KAAE,CAAC;CAwDvD;AAED,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,188 @@
1
+ // =============================================================================
2
+ // Nvidia NIM LLM Client — Stepfun + OpenAI-compatible models
3
+ // =============================================================================
4
+ import OpenAI from 'openai';
5
+ import { mergeModels } from './models.js';
6
+ export class NimClient {
7
+ client;
8
+ model;
9
+ constructor(_projectRoot) {
10
+ const apiKey = process.env.NIM_API_KEY ?? '';
11
+ const baseUrl = process.env.NIM_BASE_URL ?? 'https://integrate.api.nvidia.com/v1';
12
+ this.model = process.env.NIM_MODEL ?? 'stepfun-ai/step-3.7-flash';
13
+ const timeout = parseInt(process.env.LLM_TIMEOUT ?? '120000', 10);
14
+ this.client = new OpenAI({
15
+ apiKey,
16
+ baseURL: baseUrl,
17
+ timeout,
18
+ defaultHeaders: { 'User-Agent': 'agent-termo/1.0' },
19
+ });
20
+ }
21
+ buildToolDefs(toolSchemas) {
22
+ return toolSchemas.map((t) => ({
23
+ type: 'function',
24
+ function: {
25
+ name: t.name,
26
+ description: t.description,
27
+ parameters: t.parameters,
28
+ },
29
+ }));
30
+ }
31
+ getModel() {
32
+ return this.model;
33
+ }
34
+ setModel(model) {
35
+ this.model = model;
36
+ }
37
+ /**
38
+ * Fetch the models this API key can use. Never throws: on failure the curated
39
+ * list is returned with `live: false` and the reason in `error`.
40
+ */
41
+ async listModels() {
42
+ try {
43
+ const page = await this.client.models.list({ timeout: 10_000 });
44
+ const ids = page.data.map((m) => m.id);
45
+ if (ids.length === 0)
46
+ throw new Error('empty model list');
47
+ return { models: mergeModels(ids), live: true };
48
+ }
49
+ catch (err) {
50
+ return {
51
+ models: mergeModels(null),
52
+ live: false,
53
+ error: err instanceof Error ? err.message : String(err),
54
+ };
55
+ }
56
+ }
57
+ /**
58
+ * Streaming chat completion.
59
+ * Handles Stepfun's quirks: filters "null" reasoning chunks, strips reasoning field.
60
+ * Yields { content, toolCalls } at the end with clean text.
61
+ */
62
+ async *streamComplete(messages, tools, onChunk) {
63
+ const rawChunks = [];
64
+ const toolCallMap = new Map();
65
+ const stream = await this.client.chat.completions.create({
66
+ model: this.model,
67
+ messages: messages.map((m) => {
68
+ if (m.role === 'tool') {
69
+ return {
70
+ role: 'tool',
71
+ content: m.content,
72
+ tool_call_id: m.id,
73
+ };
74
+ }
75
+ return {
76
+ role: m.role,
77
+ content: m.content,
78
+ };
79
+ }),
80
+ tools: tools,
81
+ temperature: 0.3,
82
+ max_tokens: 8192,
83
+ stream: true,
84
+ });
85
+ for await (const chunk of stream) {
86
+ const delta = chunk.choices[0]?.delta;
87
+ if (!delta)
88
+ continue;
89
+ // Text delta — filter out "null" chunks (Stepfun's reasoning output)
90
+ const rawContent = delta.content ?? '';
91
+ // Check: if it's the literal string "null", it's reasoning noise — skip it
92
+ const isNoise = rawContent === 'null' || rawContent === 'undefined';
93
+ if (!isNoise && rawContent) {
94
+ rawChunks.push(rawContent);
95
+ onChunk?.(rawContent);
96
+ }
97
+ // Tool call deltas (accumulate across chunks via index)
98
+ if (delta.tool_calls) {
99
+ for (const tc of delta.tool_calls) {
100
+ const idx = tc.index ?? 0;
101
+ const prev = toolCallMap.get(idx);
102
+ if (!prev) {
103
+ toolCallMap.set(idx, {
104
+ id: tc.id ?? crypto.randomUUID(),
105
+ name: tc.function?.name ?? '',
106
+ arguments: tc.function?.arguments ?? '',
107
+ });
108
+ }
109
+ else {
110
+ prev.arguments += tc.function?.arguments ?? '';
111
+ if (tc.id && !prev.id)
112
+ prev.id = tc.id;
113
+ }
114
+ }
115
+ }
116
+ }
117
+ // For streaming: content is accumulated in rawChunks (null chunks already filtered)
118
+ // For non-streaming (complete() method): reasoning stripping happens in that method
119
+ const finalContent = rawChunks.join('');
120
+ // Extract tool calls
121
+ const toolCalls = Array.from(toolCallMap.values()).map((tc) => {
122
+ let args = {};
123
+ try {
124
+ args = JSON.parse(tc.arguments);
125
+ }
126
+ catch {
127
+ args = { _raw: tc.arguments };
128
+ }
129
+ return { id: tc.id, name: tc.name, arguments: args };
130
+ });
131
+ yield { content: finalContent, toolCalls };
132
+ }
133
+ /**
134
+ * Non-streaming completion — for when streaming fails or for retries.
135
+ */
136
+ async complete(messages, tools) {
137
+ const response = await this.client.chat.completions.create({
138
+ model: this.model,
139
+ messages: messages.map((m) => {
140
+ if (m.role === 'tool') {
141
+ return { role: 'tool', content: m.content, tool_call_id: m.id };
142
+ }
143
+ return { role: m.role, content: m.content };
144
+ }),
145
+ tools: tools,
146
+ temperature: 0.3,
147
+ max_tokens: 8192,
148
+ stream: false,
149
+ });
150
+ const msg = response.choices[0]?.message;
151
+ // Strip reasoning noise
152
+ let content = msg?.content?.replace(/\[ Reasoning[^\]]*\][^\[]*\[\/ Reasoning\][^\n]*/gi, '').trim() ?? '';
153
+ const toolCalls = (msg?.tool_calls ?? []).map((tc) => {
154
+ let args = {};
155
+ try {
156
+ args = JSON.parse(tc.function.arguments ?? '{}');
157
+ }
158
+ catch {
159
+ args = { _raw: tc.function.arguments };
160
+ }
161
+ return { id: tc.id, name: tc.function.name, arguments: args };
162
+ });
163
+ // If no tool calls but content looks like a tool call request, parse it
164
+ if (toolCalls.length === 0 && content.includes('"tool_calls"')) {
165
+ try {
166
+ const parsed = JSON.parse(content);
167
+ if (parsed.tool_calls?.length) {
168
+ toolCalls.push(...parsed.tool_calls.map((tc) => ({
169
+ id: tc.id ?? crypto.randomUUID(),
170
+ name: tc.function?.name ?? tc.name ?? '',
171
+ arguments: typeof tc.function?.arguments === 'string'
172
+ ? JSON.parse(tc.function.arguments)
173
+ : tc.function?.arguments ?? {},
174
+ })));
175
+ // Remove JSON from content
176
+ const jsonStart = content.indexOf('{"tool_calls"');
177
+ if (jsonStart !== -1)
178
+ content = content.slice(0, jsonStart).trim();
179
+ }
180
+ }
181
+ catch {
182
+ // Not valid JSON — leave as-is
183
+ }
184
+ }
185
+ return { content, toolCalls };
186
+ }
187
+ }
188
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/llm/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export interface ModelInfo {
2
+ id: string;
3
+ note?: string;
4
+ }
5
+ /**
6
+ * Hand-picked chat/coding models worth surfacing first. This list is only a
7
+ * starting point: when the live catalogue is reachable, entries NIM no longer
8
+ * serves are dropped, and everything else NIM returns is still selectable.
9
+ */
10
+ export declare const CURATED_MODELS: ModelInfo[];
11
+ export declare function isChatModel(id: string): boolean;
12
+ /**
13
+ * Build the picker list.
14
+ * - live === null: the catalogue could not be fetched, so offer the curated list.
15
+ * - otherwise: curated entries that NIM serves first, then the rest of the live
16
+ * chat models alphabetically.
17
+ */
18
+ export declare function mergeModels(live: string[] | null): ModelInfo[];
19
+ //# sourceMappingURL=models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/llm/models.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,SAAS,EAWrC,CAAC;AAOF,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAE/C;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,EAAE,CAY9D"}
@@ -0,0 +1,45 @@
1
+ // =============================================================================
2
+ // NVIDIA NIM model catalogue — curated suggestions + live /v1/models merge
3
+ // =============================================================================
4
+ /**
5
+ * Hand-picked chat/coding models worth surfacing first. This list is only a
6
+ * starting point: when the live catalogue is reachable, entries NIM no longer
7
+ * serves are dropped, and everything else NIM returns is still selectable.
8
+ */
9
+ export const CURATED_MODELS = [
10
+ { id: 'stepfun-ai/step-3.7-flash', note: 'default' },
11
+ { id: 'meta/llama-3.1-8b-instruct', note: 'fast, low cost' },
12
+ { id: 'meta/llama-3.1-70b-instruct', note: 'balanced' },
13
+ { id: 'meta/llama-3.3-70b-instruct', note: 'balanced' },
14
+ { id: 'meta/llama-3.1-405b-instruct', note: 'highest quality Llama' },
15
+ { id: 'nvidia/llama-3.1-nemotron-70b-instruct', note: 'NVIDIA tuned' },
16
+ { id: 'qwen/qwen2.5-coder-32b-instruct', note: 'coding' },
17
+ { id: 'deepseek-ai/deepseek-r1', note: 'reasoning' },
18
+ { id: 'moonshotai/kimi-k2-instruct', note: 'agentic / tool use' },
19
+ { id: 'openai/gpt-oss-120b', note: 'open-weight GPT' },
20
+ ];
21
+ // NIM serves embedding, vision, speech and other non-chat models from the same
22
+ // endpoint. Hide the obvious ones so the picker stays about chat models.
23
+ const NON_CHAT = /embed|rerank|retriev|reward|guard|safety|parse|clip|vila|neva|fuyu|kosmos|paligemma|deplot|riva|asr|tts|whisper|diffusion|sdxl|flux|cosmos|segment|bge-|e5-|gliner|pii|streampetr|ocdrnet|bevformer/i;
24
+ export function isChatModel(id) {
25
+ return !NON_CHAT.test(id);
26
+ }
27
+ /**
28
+ * Build the picker list.
29
+ * - live === null: the catalogue could not be fetched, so offer the curated list.
30
+ * - otherwise: curated entries that NIM serves first, then the rest of the live
31
+ * chat models alphabetically.
32
+ */
33
+ export function mergeModels(live) {
34
+ if (!live)
35
+ return [...CURATED_MODELS];
36
+ const liveSet = new Set(live);
37
+ const curated = CURATED_MODELS.filter((m) => liveSet.has(m.id));
38
+ const curatedIds = new Set(curated.map((m) => m.id));
39
+ const rest = live
40
+ .filter((id) => !curatedIds.has(id) && isChatModel(id))
41
+ .sort((a, b) => a.localeCompare(b))
42
+ .map((id) => ({ id }));
43
+ return [...curated, ...rest];
44
+ }
45
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../../src/llm/models.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,2EAA2E;AAC3E,gFAAgF;AAOhF;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAgB;IACzC,EAAE,EAAE,EAAE,2BAA2B,EAAE,IAAI,EAAE,SAAS,EAAE;IACpD,EAAE,EAAE,EAAE,4BAA4B,EAAE,IAAI,EAAE,gBAAgB,EAAE;IAC5D,EAAE,EAAE,EAAE,6BAA6B,EAAE,IAAI,EAAE,UAAU,EAAE;IACvD,EAAE,EAAE,EAAE,6BAA6B,EAAE,IAAI,EAAE,UAAU,EAAE;IACvD,EAAE,EAAE,EAAE,8BAA8B,EAAE,IAAI,EAAE,uBAAuB,EAAE;IACrE,EAAE,EAAE,EAAE,wCAAwC,EAAE,IAAI,EAAE,cAAc,EAAE;IACtE,EAAE,EAAE,EAAE,iCAAiC,EAAE,IAAI,EAAE,QAAQ,EAAE;IACzD,EAAE,EAAE,EAAE,yBAAyB,EAAE,IAAI,EAAE,WAAW,EAAE;IACpD,EAAE,EAAE,EAAE,6BAA6B,EAAE,IAAI,EAAE,oBAAoB,EAAE;IACjE,EAAE,EAAE,EAAE,qBAAqB,EAAE,IAAI,EAAE,iBAAiB,EAAE;CACvD,CAAC;AAEF,+EAA+E;AAC/E,yEAAyE;AACzE,MAAM,QAAQ,GACZ,sMAAsM,CAAC;AAEzM,MAAM,UAAU,WAAW,CAAC,EAAU;IACpC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC5B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,IAAqB;IAC/C,IAAI,CAAC,IAAI;QAAE,OAAO,CAAC,GAAG,cAAc,CAAC,CAAC;IAEtC,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAChE,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACrD,MAAM,IAAI,GAAG,IAAI;SACd,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,WAAW,CAAC,EAAE,CAAC,CAAC;SACtD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;SAClC,GAAG,CAAC,CAAC,EAAE,EAAa,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IAEpC,OAAO,CAAC,GAAG,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ToolDef } from '../types/index.js';
2
+ export declare const TOOL_DEFINITIONS: ToolDef[];
3
+ //# sourceMappingURL=tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/llm/tools.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEjD,eAAO,MAAM,gBAAgB,EAAE,OAAO,EAsMrC,CAAC"}