surfcode 0.0.0-stage → 0.1.1
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.
- package/LICENSE +21 -0
- package/README.md +325 -2
- package/assets/surfcode-logo.gif +0 -0
- package/dist/cli/auth.js +315 -0
- package/dist/cli/auth.js.map +1 -0
- package/dist/cli/config.js +228 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/headless.js +355 -0
- package/dist/cli/headless.js.map +1 -0
- package/dist/cli/inspect.js +462 -0
- package/dist/cli/inspect.js.map +1 -0
- package/dist/cli/interactive.js +130 -0
- package/dist/cli/interactive.js.map +1 -0
- package/dist/cli/sessions.js +170 -0
- package/dist/cli/sessions.js.map +1 -0
- package/dist/cli/sync.js +190 -0
- package/dist/cli/sync.js.map +1 -0
- package/dist/cli/util.js +345 -0
- package/dist/cli/util.js.map +1 -0
- package/dist/cli.js +485 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/agent.js +298 -0
- package/dist/core/agent.js.map +1 -0
- package/dist/core/agents.js +55 -0
- package/dist/core/agents.js.map +1 -0
- package/dist/core/auth.js +107 -0
- package/dist/core/auth.js.map +1 -0
- package/dist/core/catalog.js +306 -0
- package/dist/core/catalog.js.map +1 -0
- package/dist/core/chat/anthropic.js +222 -0
- package/dist/core/chat/anthropic.js.map +1 -0
- package/dist/core/chat/common.js +367 -0
- package/dist/core/chat/common.js.map +1 -0
- package/dist/core/chat/google.js +180 -0
- package/dist/core/chat/google.js.map +1 -0
- package/dist/core/chat/index.js +80 -0
- package/dist/core/chat/index.js.map +1 -0
- package/dist/core/chat/openai.js +164 -0
- package/dist/core/chat/openai.js.map +1 -0
- package/dist/core/chat/types.js +2 -0
- package/dist/core/chat/types.js.map +1 -0
- package/dist/core/clipboard.js +34 -0
- package/dist/core/clipboard.js.map +1 -0
- package/dist/core/compact.js +39 -0
- package/dist/core/compact.js.map +1 -0
- package/dist/core/config.js +211 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/delegate.js +184 -0
- package/dist/core/delegate.js.map +1 -0
- package/dist/core/effort.js +80 -0
- package/dist/core/effort.js.map +1 -0
- package/dist/core/errors.js +32 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/free.js +21 -0
- package/dist/core/free.js.map +1 -0
- package/dist/core/github.js +445 -0
- package/dist/core/github.js.map +1 -0
- package/dist/core/paths.js +51 -0
- package/dist/core/paths.js.map +1 -0
- package/dist/core/prompt.js +95 -0
- package/dist/core/prompt.js.map +1 -0
- package/dist/core/provider.js +298 -0
- package/dist/core/provider.js.map +1 -0
- package/dist/core/session.js +159 -0
- package/dist/core/session.js.map +1 -0
- package/dist/core/sync.js +126 -0
- package/dist/core/sync.js.map +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/usage.js +127 -0
- package/dist/core/usage.js.map +1 -0
- package/dist/core/workspace.js +70 -0
- package/dist/core/workspace.js.map +1 -0
- package/dist/data/models.json +1 -0
- package/dist/sync/server.js +179 -0
- package/dist/sync/server.js.map +1 -0
- package/dist/tools/diff.js +21 -0
- package/dist/tools/diff.js.map +1 -0
- package/dist/tools/files.js +227 -0
- package/dist/tools/files.js.map +1 -0
- package/dist/tools/github.js +238 -0
- package/dist/tools/github.js.map +1 -0
- package/dist/tools/index.js +34 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/search.js +231 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/tools/shell.js +118 -0
- package/dist/tools/shell.js.map +1 -0
- package/dist/tools/todos.js +50 -0
- package/dist/tools/todos.js.map +1 -0
- package/dist/tools/webfetch.js +108 -0
- package/dist/tools/webfetch.js.map +1 -0
- package/dist/tui/App.js +2984 -0
- package/dist/tui/App.js.map +1 -0
- package/dist/tui/ansi.js +151 -0
- package/dist/tui/ansi.js.map +1 -0
- package/dist/tui/commands.js +61 -0
- package/dist/tui/commands.js.map +1 -0
- package/dist/tui/explorer.js +152 -0
- package/dist/tui/explorer.js.map +1 -0
- package/dist/tui/icons.js +21 -0
- package/dist/tui/icons.js.map +1 -0
- package/dist/tui/layout.js +324 -0
- package/dist/tui/layout.js.map +1 -0
- package/dist/tui/markdown.js +355 -0
- package/dist/tui/markdown.js.map +1 -0
- package/dist/tui/overlays.js +316 -0
- package/dist/tui/overlays.js.map +1 -0
- package/dist/tui/render.js +234 -0
- package/dist/tui/render.js.map +1 -0
- package/dist/tui/theme.js +148 -0
- package/dist/tui/theme.js.map +1 -0
- package/dist/tui/types.js +73 -0
- package/dist/tui/types.js.map +1 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- package/package.json +75 -4
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
import { addUsage, costForUsage, emptyUsage } from './usage.js';
|
|
2
|
+
import { buildSystemPrompt } from './prompt.js';
|
|
3
|
+
import { streamChat } from './chat/index.js';
|
|
4
|
+
import { createDelegateTool } from './delegate.js';
|
|
5
|
+
import { isAbortError, SurfError } from './errors.js';
|
|
6
|
+
import { findTool, toolSchemas } from '../tools/index.js';
|
|
7
|
+
export async function runAgent(options) {
|
|
8
|
+
const { cwd, provider, model, mode, tools, callbacks, permissions, maxSteps, signal } = options;
|
|
9
|
+
let messages = [...options.history];
|
|
10
|
+
const userMessage = { role: 'user', content: options.input.trim() };
|
|
11
|
+
if (!userMessage.content)
|
|
12
|
+
throw new SurfError('The prompt is empty.');
|
|
13
|
+
messages.push(userMessage);
|
|
14
|
+
const toolsEnabled = model.meta?.tool_call !== false;
|
|
15
|
+
const usage = emptyUsage();
|
|
16
|
+
const activeTools = [...tools];
|
|
17
|
+
const delegateWorkers = options.delegates?.map((delegate) => `${delegate.provider.id}/${delegate.model.id}`) ?? [];
|
|
18
|
+
if (toolsEnabled && options.delegates?.length) {
|
|
19
|
+
activeTools.push(createDelegateTool({
|
|
20
|
+
delegates: options.delegates,
|
|
21
|
+
getHistory: () => messages,
|
|
22
|
+
signal,
|
|
23
|
+
cwd,
|
|
24
|
+
maxTokens: options.maxTokens,
|
|
25
|
+
temperature: options.temperature,
|
|
26
|
+
effort: options.effort,
|
|
27
|
+
onUsage(delta) {
|
|
28
|
+
addUsage(usage, delta);
|
|
29
|
+
callbacks.onUsage({ ...usage });
|
|
30
|
+
}
|
|
31
|
+
}));
|
|
32
|
+
}
|
|
33
|
+
const system = await buildSystemPrompt({
|
|
34
|
+
cwd,
|
|
35
|
+
mode,
|
|
36
|
+
modelName: model.name,
|
|
37
|
+
providerName: provider.name,
|
|
38
|
+
toolsEnabled,
|
|
39
|
+
effort: options.effort,
|
|
40
|
+
agentWorkers: delegateWorkers
|
|
41
|
+
});
|
|
42
|
+
const schemas = toolsEnabled ? toolSchemas(activeTools) : [];
|
|
43
|
+
let aborted = false;
|
|
44
|
+
let todos = [];
|
|
45
|
+
let emptyRetries = 0;
|
|
46
|
+
for (let step = 1; step <= maxSteps; step += 1) {
|
|
47
|
+
if (signal.aborted) {
|
|
48
|
+
aborted = true;
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
callbacks.onStep?.(step, maxSteps);
|
|
52
|
+
let partialText = '';
|
|
53
|
+
let partialReasoning = '';
|
|
54
|
+
let result;
|
|
55
|
+
try {
|
|
56
|
+
result = await streamChat({
|
|
57
|
+
provider,
|
|
58
|
+
model,
|
|
59
|
+
messages,
|
|
60
|
+
system,
|
|
61
|
+
tools: schemas,
|
|
62
|
+
options: {
|
|
63
|
+
signal,
|
|
64
|
+
maxTokens: options.maxTokens,
|
|
65
|
+
temperature: options.temperature,
|
|
66
|
+
effort: options.effort,
|
|
67
|
+
showReasoning: options.showReasoning,
|
|
68
|
+
timeout: provider.settings.timeout
|
|
69
|
+
},
|
|
70
|
+
callbacks: {
|
|
71
|
+
onText: (delta) => {
|
|
72
|
+
partialText += delta;
|
|
73
|
+
callbacks.onText(delta);
|
|
74
|
+
},
|
|
75
|
+
onReasoning: (delta) => {
|
|
76
|
+
partialReasoning += delta;
|
|
77
|
+
callbacks.onReasoning(delta);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
if (signal.aborted || isAbortError(error)) {
|
|
84
|
+
aborted = true;
|
|
85
|
+
if (partialText || partialReasoning) {
|
|
86
|
+
messages.push({
|
|
87
|
+
role: 'assistant',
|
|
88
|
+
content: partialText,
|
|
89
|
+
...(partialReasoning ? { reasoning: partialReasoning } : {})
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
if (error instanceof Error && error.name === 'TimeoutError') {
|
|
95
|
+
throw new SurfError('The provider did not finish the request in time and it was aborted.', {
|
|
96
|
+
hint: 'Try again, switch models with /model, or raise providers.<id>.settings.timeout in the config.',
|
|
97
|
+
cause: error,
|
|
98
|
+
retryable: true
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
103
|
+
const turnUsage = {
|
|
104
|
+
inputTokens: result.usage.inputTokens ?? 0,
|
|
105
|
+
outputTokens: result.usage.outputTokens ?? 0,
|
|
106
|
+
reasoningTokens: result.usage.reasoningTokens ?? 0,
|
|
107
|
+
cacheReadTokens: result.usage.cacheReadTokens ?? 0,
|
|
108
|
+
cacheWriteTokens: result.usage.cacheWriteTokens ?? 0,
|
|
109
|
+
cost: costForUsage(model.meta, result.usage, provider.dialect),
|
|
110
|
+
requests: 1
|
|
111
|
+
};
|
|
112
|
+
addUsage(usage, turnUsage);
|
|
113
|
+
callbacks.onUsage({ ...usage });
|
|
114
|
+
if (result.text || result.reasoning || result.toolCalls.length > 0) {
|
|
115
|
+
messages.push({
|
|
116
|
+
role: 'assistant',
|
|
117
|
+
content: result.text,
|
|
118
|
+
...(result.reasoning ? { reasoning: result.reasoning } : {}),
|
|
119
|
+
...(result.toolCalls.length > 0 ? { toolCalls: result.toolCalls } : {}),
|
|
120
|
+
...(result.thinkingBlocks?.length ? { thinkingBlocks: result.thinkingBlocks } : {})
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
if (result.toolCalls.length === 0) {
|
|
124
|
+
if (result.finishReason === 'length' || result.finishReason === 'max_tokens') {
|
|
125
|
+
messages.push({
|
|
126
|
+
role: 'assistant',
|
|
127
|
+
content: '_Response reached the output limit. Ask me to continue if you need the rest._'
|
|
128
|
+
});
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
// An empty response (provider hiccup, content filter, dropped stream)
|
|
132
|
+
// used to end the turn silently. Nudge the model once so the task
|
|
133
|
+
// continues instead of appearing to stop for no reason.
|
|
134
|
+
if (!result.text && !result.reasoning && !aborted && step < maxSteps && emptyRetries < 1) {
|
|
135
|
+
emptyRetries += 1;
|
|
136
|
+
messages.push({ role: 'user', content: '(Your previous reply was empty. Continue the task.)' });
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
for (let index = 0; index < result.toolCalls.length; index += 1) {
|
|
142
|
+
const call = result.toolCalls[index];
|
|
143
|
+
if (signal.aborted) {
|
|
144
|
+
aborted = true;
|
|
145
|
+
for (const remaining of result.toolCalls.slice(index)) {
|
|
146
|
+
const cancelled = { output: 'Cancelled by user.', isError: true };
|
|
147
|
+
callbacks.onToolStart(remaining, findTool(activeTools, remaining.name));
|
|
148
|
+
callbacks.onToolResult(remaining, cancelled, 0);
|
|
149
|
+
messages.push({
|
|
150
|
+
role: 'tool',
|
|
151
|
+
toolCallId: remaining.id,
|
|
152
|
+
name: remaining.name,
|
|
153
|
+
content: cancelled.output,
|
|
154
|
+
isError: true
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
const tool = findTool(activeTools, call.name);
|
|
160
|
+
callbacks.onToolStart(call, tool);
|
|
161
|
+
const started = Date.now();
|
|
162
|
+
let toolResult;
|
|
163
|
+
try {
|
|
164
|
+
if (call.rawArguments && Object.keys(call.arguments).length === 0) {
|
|
165
|
+
toolResult = {
|
|
166
|
+
output: `Invalid JSON arguments for ${call.name}: ${call.rawArguments.slice(0, 500)}`,
|
|
167
|
+
isError: true
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
else if (!tool) {
|
|
171
|
+
toolResult = {
|
|
172
|
+
output: `Unknown tool: ${call.name}. Available tools: ${activeTools.map((entry) => entry.name).join(', ')}.`,
|
|
173
|
+
isError: true
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
toolResult = await executeWithPermission(call, tool, options, permissions, mode, callbacks, todos, (next) => {
|
|
178
|
+
todos = next;
|
|
179
|
+
callbacks.onTodos?.(next);
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
if (signal.aborted || isAbortError(error)) {
|
|
185
|
+
toolResult = { output: 'Cancelled by user.', isError: true };
|
|
186
|
+
aborted = true;
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
toolResult = {
|
|
190
|
+
output: error instanceof Error ? error.message : String(error),
|
|
191
|
+
isError: true
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
const duration = Date.now() - started;
|
|
196
|
+
callbacks.onToolResult(call, toolResult, duration);
|
|
197
|
+
messages.push({
|
|
198
|
+
role: 'tool',
|
|
199
|
+
toolCallId: call.id,
|
|
200
|
+
name: call.name,
|
|
201
|
+
content: toolResult.output,
|
|
202
|
+
...(toolResult.isError ? { isError: true } : {})
|
|
203
|
+
});
|
|
204
|
+
if (aborted)
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
if (aborted)
|
|
208
|
+
break;
|
|
209
|
+
if (step === maxSteps) {
|
|
210
|
+
messages.push({
|
|
211
|
+
role: 'assistant',
|
|
212
|
+
content: `_Stopped after ${maxSteps} tool steps. Ask me to continue, or raise maxSteps in the config._`
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return { messages, usage, aborted };
|
|
217
|
+
}
|
|
218
|
+
async function executeWithPermission(call, tool, options, permissions, mode, callbacks, todos, setTodos) {
|
|
219
|
+
const permission = buildPermissionRequest(call, tool);
|
|
220
|
+
if (mode === 'plan' && !tool.readOnly) {
|
|
221
|
+
return {
|
|
222
|
+
output: `Plan mode blocked ${tool.name}. Switch to build mode to make changes.`,
|
|
223
|
+
isError: true,
|
|
224
|
+
display: { summary: 'blocked by plan mode' }
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
const policy = permissions[tool.action] ?? 'ask';
|
|
228
|
+
if (policy === 'deny') {
|
|
229
|
+
return {
|
|
230
|
+
output: `Permission denied by policy for ${tool.action}.`,
|
|
231
|
+
isError: true,
|
|
232
|
+
display: { summary: 'denied by policy' }
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
if (policy === 'ask') {
|
|
236
|
+
const decision = await callbacks.requestPermission(permission);
|
|
237
|
+
if (decision === 'deny') {
|
|
238
|
+
return {
|
|
239
|
+
output: 'Permission denied by user. Do not retry this exact action.',
|
|
240
|
+
isError: true,
|
|
241
|
+
display: { summary: 'denied' }
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
const context = {
|
|
246
|
+
cwd: options.cwd,
|
|
247
|
+
signal: options.signal,
|
|
248
|
+
allowOutsideWorkspace: options.allowOutsideWorkspace,
|
|
249
|
+
planMode: mode === 'plan',
|
|
250
|
+
requestPermission: async () => 'allow',
|
|
251
|
+
setTodos,
|
|
252
|
+
getTodos: () => todos
|
|
253
|
+
};
|
|
254
|
+
return await tool.execute(call.arguments, context);
|
|
255
|
+
}
|
|
256
|
+
function buildPermissionRequest(call, tool) {
|
|
257
|
+
const path = typeof call.arguments.path === 'string' ? call.arguments.path : undefined;
|
|
258
|
+
const command = typeof call.arguments.command === 'string' ? call.arguments.command : undefined;
|
|
259
|
+
const url = typeof call.arguments.url === 'string' ? call.arguments.url : undefined;
|
|
260
|
+
let request;
|
|
261
|
+
if (tool.action === 'shell') {
|
|
262
|
+
const risk = riskyCommand(command ?? '') ? 'high' : 'medium';
|
|
263
|
+
request = {
|
|
264
|
+
action: 'shell',
|
|
265
|
+
title: 'Run shell command',
|
|
266
|
+
detail: command,
|
|
267
|
+
risk,
|
|
268
|
+
rule: command
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
else if (tool.action === 'write') {
|
|
272
|
+
request = {
|
|
273
|
+
action: 'write',
|
|
274
|
+
title: tool.name === 'edit' ? 'Edit file' : 'Write file',
|
|
275
|
+
detail: path,
|
|
276
|
+
risk: 'medium',
|
|
277
|
+
rule: path
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
else if (tool.action === 'fetch') {
|
|
281
|
+
request = { action: 'fetch', title: 'Fetch URL', detail: url, risk: 'low', rule: url };
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
request = {
|
|
285
|
+
action: 'read',
|
|
286
|
+
title: tool.name === 'read' ? 'Read file' : tool.name,
|
|
287
|
+
detail: path ?? url ?? (typeof call.arguments.pattern === 'string' ? call.arguments.pattern : undefined),
|
|
288
|
+
risk: 'low',
|
|
289
|
+
rule: path
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
const custom = tool.permission?.(call.arguments);
|
|
293
|
+
return custom ? { ...request, ...custom } : request;
|
|
294
|
+
}
|
|
295
|
+
function riskyCommand(command) {
|
|
296
|
+
return /(\brm\s+-[a-z]*r|\bsudo\b|\bmkfs\b|\bdd\s+if=|\bgit\s+(reset\s+--hard|clean\s+-[a-z]*f)|\bcurl\b[^|]*\|\s*(ba)?sh|\bchmod\s+-R\s+777|\bkillall\b|\bshutdown\b|\breboot\b)/i.test(command);
|
|
297
|
+
}
|
|
298
|
+
//# sourceMappingURL=agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/core/agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { findModel, providerById } from './catalog.js';
|
|
2
|
+
import { resolveSelection } from './provider.js';
|
|
3
|
+
/**
|
|
4
|
+
* Worker references are always `provider/model`. Model ids may themselves
|
|
5
|
+
* contain slashes, so only the first slash separates the two halves.
|
|
6
|
+
*/
|
|
7
|
+
export function parseWorkerRef(reference) {
|
|
8
|
+
const trimmed = reference.trim();
|
|
9
|
+
const slash = trimmed.indexOf('/');
|
|
10
|
+
if (slash <= 0 || slash === trimmed.length - 1)
|
|
11
|
+
return undefined;
|
|
12
|
+
return {
|
|
13
|
+
provider: trimmed.slice(0, slash),
|
|
14
|
+
model: trimmed.slice(slash + 1)
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export function workerLabel(worker) {
|
|
18
|
+
return `${worker.provider}/${worker.model}`;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Resolve every configured worker against the catalog and the user's saved
|
|
22
|
+
* credentials. One broken worker never blocks the rest of /agent mode.
|
|
23
|
+
*/
|
|
24
|
+
export async function resolveAgentWorkers(catalog, config) {
|
|
25
|
+
const delegates = [];
|
|
26
|
+
const failures = [];
|
|
27
|
+
const seen = new Set();
|
|
28
|
+
for (const worker of config.agents.workers) {
|
|
29
|
+
const label = workerLabel(worker);
|
|
30
|
+
if (seen.has(label))
|
|
31
|
+
continue;
|
|
32
|
+
seen.add(label);
|
|
33
|
+
if (!providerById(catalog, worker.provider)) {
|
|
34
|
+
failures.push(`${label} — unknown provider`);
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
if (!findModel(catalog, worker.provider, worker.model)) {
|
|
38
|
+
failures.push(`${label} — model not in catalog`);
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
const selection = await resolveSelection(catalog, config, {
|
|
43
|
+
provider: worker.provider,
|
|
44
|
+
model: worker.model
|
|
45
|
+
});
|
|
46
|
+
delegates.push({ provider: selection.provider, model: selection.model });
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
50
|
+
failures.push(`${label} — ${reason}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return { delegates, failures };
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=agents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents.js","sourceRoot":"","sources":["../../src/core/agents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAgB,MAAM,cAAc,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGjD;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,SAAiB;IAC9C,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC;IACjC,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,KAAK,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IACjE,OAAO;QACL,QAAQ,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC;QACjC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC;KAChC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAmB;IAC7C,OAAO,GAAG,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;AAC9C,CAAC;AAOD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,OAAgB,EAChB,MAAkB;IAElB,MAAM,SAAS,GAAoB,EAAE,CAAC;IACtC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QAC3C,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;QAClC,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,SAAS;QAC9B,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAChB,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5C,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,qBAAqB,CAAC,CAAC;YAC7C,SAAS;QACX,CAAC;QACD,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YACvD,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,yBAAyB,CAAC,CAAC;YACjD,SAAS;QACX,CAAC;QACD,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE;gBACxD,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,KAAK,EAAE,MAAM,CAAC,KAAK;aACpB,CAAC,CAAC;YACH,SAAS,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,SAAS,CAAC,QAAQ,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC;QAC3E,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACtE,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,MAAM,MAAM,EAAE,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;AACjC,CAAC"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { ensurePaths, getPaths, writeFileAtomic } from './paths.js';
|
|
4
|
+
const authSchema = z.object({
|
|
5
|
+
version: z.literal(1).default(1),
|
|
6
|
+
keys: z.record(z.string(), z.string()).default({})
|
|
7
|
+
});
|
|
8
|
+
const LOCAL_PROVIDERS = new Set(['ollama', 'llamacpp', 'vllm', 'lmstudio']);
|
|
9
|
+
let cached;
|
|
10
|
+
export async function loadAuth(force = false) {
|
|
11
|
+
const paths = getPaths();
|
|
12
|
+
let raw;
|
|
13
|
+
try {
|
|
14
|
+
raw = await readFile(paths.authFile, 'utf8');
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
if (error.code === 'ENOENT') {
|
|
18
|
+
cached = { version: 1, keys: {} };
|
|
19
|
+
return cached;
|
|
20
|
+
}
|
|
21
|
+
throw error;
|
|
22
|
+
}
|
|
23
|
+
if (cached && !force)
|
|
24
|
+
return cached;
|
|
25
|
+
try {
|
|
26
|
+
const parsed = authSchema.safeParse(JSON.parse(raw));
|
|
27
|
+
if (!parsed.success)
|
|
28
|
+
throw new Error('invalid shape');
|
|
29
|
+
cached = parsed.data;
|
|
30
|
+
return cached;
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
throw new Error(`Could not parse auth file at ${paths.authFile}.`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export async function saveProviderKey(providerId, key) {
|
|
37
|
+
await ensurePaths();
|
|
38
|
+
const auth = await loadAuth(true);
|
|
39
|
+
auth.keys[providerId] = key.trim();
|
|
40
|
+
await writeFileAtomic(getPaths().authFile, `${JSON.stringify(auth, null, 2)}\n`);
|
|
41
|
+
cached = auth;
|
|
42
|
+
}
|
|
43
|
+
export async function removeProviderKey(providerId) {
|
|
44
|
+
const paths = getPaths();
|
|
45
|
+
const auth = await loadAuth(true);
|
|
46
|
+
if (!(providerId in auth.keys))
|
|
47
|
+
return false;
|
|
48
|
+
delete auth.keys[providerId];
|
|
49
|
+
await writeFileAtomic(paths.authFile, `${JSON.stringify(auth, null, 2)}\n`);
|
|
50
|
+
cached = auth;
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
export async function getStoredKey(providerId) {
|
|
54
|
+
const auth = await loadAuth();
|
|
55
|
+
return auth.keys[providerId]?.trim() || undefined;
|
|
56
|
+
}
|
|
57
|
+
export function envKeyFor(provider) {
|
|
58
|
+
for (const name of provider.env) {
|
|
59
|
+
const value = process.env[name]?.trim();
|
|
60
|
+
if (value)
|
|
61
|
+
return value;
|
|
62
|
+
}
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
export function envNameFor(provider) {
|
|
66
|
+
for (const name of provider.env) {
|
|
67
|
+
if (process.env[name]?.trim())
|
|
68
|
+
return name;
|
|
69
|
+
}
|
|
70
|
+
return provider.env[0];
|
|
71
|
+
}
|
|
72
|
+
export function isKeylessProvider(provider) {
|
|
73
|
+
if (LOCAL_PROVIDERS.has(provider.id))
|
|
74
|
+
return true;
|
|
75
|
+
if (provider.local)
|
|
76
|
+
return true;
|
|
77
|
+
// OpenAI-compatible localhost servers often do not require a key.
|
|
78
|
+
return typeof provider.api === 'string' && /localhost|127\.0\.0\.1|0\.0\.0\.0/.test(provider.api);
|
|
79
|
+
}
|
|
80
|
+
export async function credentialStatus(providers, config) {
|
|
81
|
+
const auth = await loadAuth();
|
|
82
|
+
return providers.map((provider) => {
|
|
83
|
+
const settings = config.providers[provider.id] ?? config.customProviders[provider.id] ?? {};
|
|
84
|
+
const envName = envNameFor(provider);
|
|
85
|
+
if (settings?.apiKey?.trim()) {
|
|
86
|
+
return { provider, configured: true, source: 'config', envName, masked: mask(settings.apiKey) };
|
|
87
|
+
}
|
|
88
|
+
if (auth.keys[provider.id]?.trim()) {
|
|
89
|
+
return { provider, configured: true, source: 'auth', envName, masked: mask(auth.keys[provider.id]) };
|
|
90
|
+
}
|
|
91
|
+
const envValue = envKeyFor(provider);
|
|
92
|
+
if (envValue) {
|
|
93
|
+
return { provider, configured: true, source: 'env', envName, masked: mask(envValue) };
|
|
94
|
+
}
|
|
95
|
+
if (isKeylessProvider(provider) || settings?.keyless) {
|
|
96
|
+
return { provider, configured: true, source: 'keyless', envName };
|
|
97
|
+
}
|
|
98
|
+
return { provider, configured: false, envName };
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
export function mask(key) {
|
|
102
|
+
const trimmed = key.trim();
|
|
103
|
+
if (trimmed.length <= 8)
|
|
104
|
+
return '••••';
|
|
105
|
+
return `${trimmed.slice(0, 4)}…${trimmed.slice(-4)}`;
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/core/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGpE,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1B,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAChC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;CACnD,CAAC,CAAC;AAEH,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;AAE5E,IAAI,MAA6B,CAAC;AAElC,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,KAAK,GAAG,KAAK;IAC1C,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IACzB,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC/C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvD,MAAM,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;YAClC,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;IACD,IAAI,MAAM,IAAI,CAAC,KAAK;QAAE,OAAO,MAAM,CAAC;IACpC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;QACrD,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;QACtD,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC;QACrB,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,gCAAgC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC;IACrE,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,UAAkB,EAAE,GAAW;IACnE,MAAM,WAAW,EAAE,CAAC;IACpB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IACnC,MAAM,eAAe,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IACjF,MAAM,GAAG,IAAI,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,UAAkB;IACxD,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IACzB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,CAAC,CAAC,UAAU,IAAI,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7C,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC7B,MAAM,eAAe,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IAC5E,MAAM,GAAG,IAAI,CAAC;IACd,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,UAAkB;IACnD,MAAM,IAAI,GAAG,MAAM,QAAQ,EAAE,CAAC;IAC9B,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,QAAyB;IACjD,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,GAAG,EAAE,CAAC;QAChC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC;QACxC,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;IAC1B,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,QAAyB;IAClD,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,GAAG,EAAE,CAAC;QAChC,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE;YAAE,OAAO,IAAI,CAAC;IAC7C,CAAC;IACD,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,QAAyB;IACzD,IAAI,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QAAE,OAAO,IAAI,CAAC;IAClD,IAAI,QAAQ,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAChC,kEAAkE;IAClE,OAAO,OAAO,QAAQ,CAAC,GAAG,KAAK,QAAQ,IAAI,mCAAmC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AACpG,CAAC;AAUD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,SAA4B,EAC5B,MAAkB;IAElB,MAAM,IAAI,GAAG,MAAM,QAAQ,EAAE,CAAC;IAC9B,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;QAChC,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;QAC5F,MAAM,OAAO,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;QACrC,IAAI,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC;YAC7B,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,QAAiB,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3G,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC;YACnC,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,MAAe,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAE,CAAC,EAAE,CAAC;QACjH,CAAC;QACD,MAAM,QAAQ,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;QACrC,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,KAAc,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QACjG,CAAC;QACD,IAAI,iBAAiB,CAAC,QAAQ,CAAC,IAAI,QAAQ,EAAE,OAAO,EAAE,CAAC;YACrD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,SAAkB,EAAE,OAAO,EAAE,CAAC;QAC7E,CAAC;QACD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;IAClD,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,GAAW;IAC9B,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC;QAAE,OAAO,MAAM,CAAC;IACvC,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACvD,CAAC"}
|