nuabase 2.3.4 → 2.3.5
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/README.md +53 -2
- package/dist/cjs/chunks/logger-Co5uZG0A.cjs +90 -0
- package/dist/cjs/index.cjs +1516 -1380
- package/dist/cjs/local-agent.cjs +886 -0
- package/dist/esm/chunks/logger-DnkHzkX_.mjs +88 -0
- package/dist/esm/index.mjs +1516 -1380
- package/dist/esm/local-agent.mjs +884 -0
- package/dist/types/__tests__/helpers/client-factory.d.ts +33 -11
- package/dist/types/__tests__/helpers/index.d.ts +2 -1
- package/dist/types/backend/direct.d.ts +19 -7
- package/dist/types/backend/types.d.ts +7 -3
- package/dist/types/index.d.cts +3 -2
- package/dist/types/index.d.mts +3 -2
- package/dist/types/local-agent.d.cts +2 -0
- package/dist/types/local-agent.d.mts +2 -0
- package/dist/types/nua-llm-core/index.d.ts +23 -0
- package/dist/types/nua-llm-core/lib/error-utils.d.ts +6 -0
- package/dist/types/nua-llm-core/lib/logger.d.ts +44 -0
- package/dist/types/nua-llm-core/lib/nua-errors.d.ts +12 -0
- package/dist/types/nua-llm-core/lib/prompt-template-utils.d.ts +2 -0
- package/dist/types/nua-llm-core/lib/schema-utils.d.ts +1 -0
- package/dist/types/nua-llm-core/lib/stable-stringify.d.ts +1 -0
- package/dist/types/nua-llm-core/lib/strict-json-schema.d.ts +7 -0
- package/dist/types/nua-llm-core/lib/types.d.ts +8 -0
- package/dist/types/nua-llm-core/lib/validate-mappable-input-data.d.ts +4 -0
- package/dist/types/nua-llm-core/local-agent.d.ts +7 -0
- package/dist/types/nua-llm-core/modules/agent/agent-loop.d.ts +10 -0
- package/dist/types/nua-llm-core/modules/agent/agent-turn.d.ts +17 -0
- package/dist/types/nua-llm-core/modules/agent/provider-formatters.d.ts +22 -0
- package/dist/types/nua-llm-core/modules/agent/run-agent.d.ts +7 -0
- package/dist/types/nua-llm-core/modules/agent/types.d.ts +90 -0
- package/dist/types/nua-llm-core/modules/cast/cast-request.d.ts +32 -0
- package/dist/types/nua-llm-core/modules/cast/envelope.d.ts +9 -0
- package/dist/types/nua-llm-core/modules/cast/list-schema.d.ts +32 -0
- package/dist/types/nua-llm-core/modules/cast/prompts/list-prompt.d.ts +3 -0
- package/dist/types/nua-llm-core/modules/cast/prompts/render-prompt.d.ts +7 -0
- package/dist/types/nua-llm-core/modules/cast/prompts/value-prompt.d.ts +3 -0
- package/dist/types/nua-llm-core/modules/cast/run-cast.d.ts +44 -0
- package/dist/types/nua-llm-core/modules/engine/engine-router.d.ts +23 -0
- package/dist/types/nua-llm-core/modules/engine/http/http-engine.d.ts +12 -0
- package/dist/types/nua-llm-core/modules/engine/http/provider-call.d.ts +33 -0
- package/dist/types/nua-llm-core/modules/engine/http/provider-config.d.ts +65 -0
- package/dist/types/nua-llm-core/modules/engine/http/provider-engines.d.ts +35 -0
- package/dist/types/nua-llm-core/modules/engine/llm-engine.d.ts +73 -0
- package/dist/types/nua-llm-core/modules/engine/local-agent/adapters/claude-code.d.ts +2 -0
- package/dist/types/nua-llm-core/modules/engine/local-agent/adapters/codex.d.ts +2 -0
- package/dist/types/nua-llm-core/modules/engine/local-agent/adapters/failure-classification.d.ts +4 -0
- package/dist/types/nua-llm-core/modules/engine/local-agent/adapters/index.d.ts +3 -0
- package/dist/types/nua-llm-core/modules/engine/local-agent/adapters/types.d.ts +61 -0
- package/dist/types/nua-llm-core/modules/engine/local-agent/agent-id.d.ts +4 -0
- package/dist/types/nua-llm-core/modules/engine/local-agent/create-local-agent.d.ts +36 -0
- package/dist/types/nua-llm-core/modules/engine/local-agent/detect.d.ts +20 -0
- package/dist/types/nua-llm-core/modules/engine/local-agent/local-agent-engine.d.ts +32 -0
- package/dist/types/nua-llm-core/modules/engine/local-agent/local-agent.d.ts +25 -0
- package/dist/types/nua-llm-core/modules/engine/local-agent/process-runner.d.ts +16 -0
- package/dist/types/nua-llm-core/modules/engine/local-agent/semaphore.d.ts +8 -0
- package/dist/types/nua-llm-core/modules/execution/llm-response-extraction.d.ts +5 -0
- package/dist/types/nua-llm-core/modules/json-schema-validation/ajv-instances.d.ts +12 -0
- package/dist/types/nua-llm-core/modules/json-schema-validation/nua-json-schema-value-validation.d.ts +10 -0
- package/dist/types/nua-llm-core/modules/json-schema-validation/validate-json-schema.d.ts +2 -0
- package/dist/types/nua-llm-core/modules/model-info/index.d.ts +15 -0
- package/dist/types/nua-llm-core/modules/streaming/sse-parser.d.ts +7 -0
- package/dist/types/nua-llm-core/nua-llm-client.d.ts +37 -0
- package/dist/types/nua.d.ts +6 -1
- package/package.json +19 -2
|
@@ -0,0 +1,884 @@
|
|
|
1
|
+
import { r as requireLogger } from './chunks/logger-DnkHzkX_.mjs';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
|
|
4
|
+
var localAgent$1 = {};
|
|
5
|
+
|
|
6
|
+
var createLocalAgent = {};
|
|
7
|
+
|
|
8
|
+
var adapters = {};
|
|
9
|
+
|
|
10
|
+
var claudeCode = {};
|
|
11
|
+
|
|
12
|
+
var failureClassification = {};
|
|
13
|
+
|
|
14
|
+
var hasRequiredFailureClassification;
|
|
15
|
+
function requireFailureClassification() {
|
|
16
|
+
if (hasRequiredFailureClassification) return failureClassification;
|
|
17
|
+
hasRequiredFailureClassification = 1;
|
|
18
|
+
Object.defineProperty(failureClassification, "__esModule", { value: true });
|
|
19
|
+
failureClassification.classifyAgentFailure = classifyAgentFailure;
|
|
20
|
+
failureClassification.stderrTail = stderrTail;
|
|
21
|
+
const FATAL_PATTERNS = [
|
|
22
|
+
/not logged in/i,
|
|
23
|
+
/logged out/i,
|
|
24
|
+
/(please|need to|must) (run .*)?log ?in/i,
|
|
25
|
+
/authenticat/i,
|
|
26
|
+
/unauthori[sz]ed/i,
|
|
27
|
+
/invalid api key/i,
|
|
28
|
+
/oauth/i,
|
|
29
|
+
/usage limit/i,
|
|
30
|
+
/rate.?limit/i,
|
|
31
|
+
/quota/i,
|
|
32
|
+
/credit balance/i,
|
|
33
|
+
/\b40[13]\b/,
|
|
34
|
+
/\b429\b/,
|
|
35
|
+
/not supported when using/i,
|
|
36
|
+
/model .* (does not exist|not found|not available)/i
|
|
37
|
+
];
|
|
38
|
+
function classifyAgentFailure(agent, message) {
|
|
39
|
+
const full = `${agent}: ${message}`;
|
|
40
|
+
if (FATAL_PATTERNS.some((pattern) => pattern.test(message))) {
|
|
41
|
+
return { kind: "fatal", message: full };
|
|
42
|
+
}
|
|
43
|
+
return { kind: "transient", message: full };
|
|
44
|
+
}
|
|
45
|
+
function stderrTail(result, maxChars = 2e3) {
|
|
46
|
+
const stderr = result.stderr.trim();
|
|
47
|
+
return stderr.length > maxChars ? stderr.slice(-maxChars) : stderr;
|
|
48
|
+
}
|
|
49
|
+
return failureClassification;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
var hasRequiredClaudeCode;
|
|
53
|
+
function requireClaudeCode() {
|
|
54
|
+
if (hasRequiredClaudeCode) return claudeCode;
|
|
55
|
+
hasRequiredClaudeCode = 1;
|
|
56
|
+
Object.defineProperty(claudeCode, "__esModule", { value: true });
|
|
57
|
+
claudeCode.claudeCodeAdapter = void 0;
|
|
58
|
+
const failure_classification_1 = requireFailureClassification();
|
|
59
|
+
const SYSTEM_PROMPT = [
|
|
60
|
+
"You are a data transformation function called by a program.",
|
|
61
|
+
"You have no tools. Follow the instructions in the user message exactly",
|
|
62
|
+
"and reply only with the requested JSON."
|
|
63
|
+
].join(" ");
|
|
64
|
+
claudeCode.claudeCodeAdapter = {
|
|
65
|
+
id: "claude-code",
|
|
66
|
+
binaryName: "claude",
|
|
67
|
+
apiKeyEnvVars: ["ANTHROPIC_API_KEY", "ANTHROPIC_AUTH_TOKEN"],
|
|
68
|
+
modelAliases: { haiku: "haiku", sonnet: "sonnet", opus: "opus" },
|
|
69
|
+
// Claude Code accepts any JSON Schema with an object root.
|
|
70
|
+
nativeSchema(envelopeSchema) {
|
|
71
|
+
return envelopeSchema;
|
|
72
|
+
},
|
|
73
|
+
buildInvocation(request, model) {
|
|
74
|
+
const args = [
|
|
75
|
+
"-p",
|
|
76
|
+
"--output-format",
|
|
77
|
+
"json",
|
|
78
|
+
"--tools",
|
|
79
|
+
"",
|
|
80
|
+
"--setting-sources",
|
|
81
|
+
"",
|
|
82
|
+
"--strict-mcp-config",
|
|
83
|
+
"--no-session-persistence",
|
|
84
|
+
"--system-prompt",
|
|
85
|
+
SYSTEM_PROMPT
|
|
86
|
+
];
|
|
87
|
+
if (model !== void 0) {
|
|
88
|
+
args.push("--model", model);
|
|
89
|
+
}
|
|
90
|
+
if (request.enforcement.kind === "native") {
|
|
91
|
+
args.push("--json-schema", JSON.stringify(request.enforcement.schema));
|
|
92
|
+
}
|
|
93
|
+
return { args, stdin: request.prompt };
|
|
94
|
+
},
|
|
95
|
+
readResult(result, request) {
|
|
96
|
+
let json;
|
|
97
|
+
try {
|
|
98
|
+
json = JSON.parse(result.stdout);
|
|
99
|
+
} catch {
|
|
100
|
+
return {
|
|
101
|
+
kind: "failed",
|
|
102
|
+
failure: (0, failure_classification_1.classifyAgentFailure)("claude", `exited with code ${result.exitCode} without a JSON result: ${(0, failure_classification_1.stderrTail)(result)}`)
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
if (json.is_error) {
|
|
106
|
+
const message = json.result || `error (${json.subtype ?? "unknown"})`;
|
|
107
|
+
if (json.api_error_status === 400 && /input_schema|json.?schema/i.test(message)) {
|
|
108
|
+
return {
|
|
109
|
+
kind: "failed",
|
|
110
|
+
failure: { kind: "schema-rejected", message: `claude rejected the output schema: ${message}` }
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
if (json.api_error_status === 401 || json.api_error_status === 403 || json.api_error_status === 429) {
|
|
114
|
+
return { kind: "failed", failure: { kind: "fatal", message: `claude: ${message}` } };
|
|
115
|
+
}
|
|
116
|
+
return { kind: "failed", failure: (0, failure_classification_1.classifyAgentFailure)("claude", message) };
|
|
117
|
+
}
|
|
118
|
+
if (json.subtype !== "success") {
|
|
119
|
+
return {
|
|
120
|
+
kind: "failed",
|
|
121
|
+
failure: {
|
|
122
|
+
kind: "transient",
|
|
123
|
+
message: `claude did not finish successfully (${json.subtype ?? "no subtype"})`
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
const usage = json.usage ?? {};
|
|
128
|
+
const promptTokens = (usage.input_tokens ?? 0) + (usage.cache_creation_input_tokens ?? 0) + (usage.cache_read_input_tokens ?? 0);
|
|
129
|
+
const completionTokens = usage.output_tokens ?? 0;
|
|
130
|
+
const reported = {
|
|
131
|
+
usage: { promptTokens, completionTokens, totalTokens: promptTokens + completionTokens },
|
|
132
|
+
model: Object.keys(json.modelUsage ?? {})[0],
|
|
133
|
+
costUsdEstimate: json.total_cost_usd
|
|
134
|
+
};
|
|
135
|
+
if (request.enforcement.kind === "in-prompt") {
|
|
136
|
+
return { kind: "answered", answer: { kind: "text", text: json.result ?? "" }, ...reported };
|
|
137
|
+
}
|
|
138
|
+
if (!json.structured_output) {
|
|
139
|
+
return {
|
|
140
|
+
kind: "failed",
|
|
141
|
+
failure: {
|
|
142
|
+
kind: "transient",
|
|
143
|
+
message: `claude returned no structured output. Reply: ${json.result ?? ""}`
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
kind: "answered",
|
|
149
|
+
answer: { kind: "structured", envelope: json.structured_output },
|
|
150
|
+
...reported
|
|
151
|
+
};
|
|
152
|
+
},
|
|
153
|
+
loginStatusArgs: ["auth", "status"],
|
|
154
|
+
readLoginStatus(result) {
|
|
155
|
+
try {
|
|
156
|
+
const status = JSON.parse(result.stdout);
|
|
157
|
+
return { loggedIn: status.loggedIn === true, detail: status.authMethod };
|
|
158
|
+
} catch {
|
|
159
|
+
return { loggedIn: false, detail: (0, failure_classification_1.stderrTail)(result) || result.stdout.trim() };
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
return claudeCode;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
var codex = {};
|
|
167
|
+
|
|
168
|
+
var strictJsonSchema = {};
|
|
169
|
+
|
|
170
|
+
var hasRequiredStrictJsonSchema;
|
|
171
|
+
function requireStrictJsonSchema() {
|
|
172
|
+
if (hasRequiredStrictJsonSchema) return strictJsonSchema;
|
|
173
|
+
hasRequiredStrictJsonSchema = 1;
|
|
174
|
+
Object.defineProperty(strictJsonSchema, "__esModule", { value: true });
|
|
175
|
+
strictJsonSchema.toStrictSchema = toStrictSchema;
|
|
176
|
+
const STRICT_UNSUPPORTED_KEYWORDS = /* @__PURE__ */ new Set([
|
|
177
|
+
"patternProperties",
|
|
178
|
+
"propertyNames",
|
|
179
|
+
"unevaluatedProperties",
|
|
180
|
+
"dependentRequired",
|
|
181
|
+
"dependentSchemas",
|
|
182
|
+
"if",
|
|
183
|
+
"then",
|
|
184
|
+
"else",
|
|
185
|
+
"not",
|
|
186
|
+
"allOf",
|
|
187
|
+
"oneOf"
|
|
188
|
+
]);
|
|
189
|
+
function toStrictSchema(schema) {
|
|
190
|
+
return strictNode(schema);
|
|
191
|
+
}
|
|
192
|
+
function strictNode(node) {
|
|
193
|
+
if (typeof node !== "object" || node === null || Array.isArray(node)) {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
const schema = node;
|
|
197
|
+
for (const key of Object.keys(schema)) {
|
|
198
|
+
if (STRICT_UNSUPPORTED_KEYWORDS.has(key))
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
const result = { ...schema };
|
|
202
|
+
delete result.$schema;
|
|
203
|
+
const isObject = schema.type === "object" || Array.isArray(schema.type) && schema.type.includes("object") || schema.properties !== void 0;
|
|
204
|
+
if (isObject) {
|
|
205
|
+
const properties = schema.properties ?? {};
|
|
206
|
+
if (schema.additionalProperties !== void 0 && schema.additionalProperties !== false) {
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
const required = new Set(schema.required ?? []);
|
|
210
|
+
const shapedProperties = {};
|
|
211
|
+
for (const [name, child] of Object.entries(properties)) {
|
|
212
|
+
if (!required.has(name))
|
|
213
|
+
return null;
|
|
214
|
+
const shaped = strictNode(child);
|
|
215
|
+
if (!shaped)
|
|
216
|
+
return null;
|
|
217
|
+
shapedProperties[name] = shaped;
|
|
218
|
+
}
|
|
219
|
+
result.properties = shapedProperties;
|
|
220
|
+
result.required = Object.keys(shapedProperties);
|
|
221
|
+
result.additionalProperties = false;
|
|
222
|
+
}
|
|
223
|
+
if (schema.items !== void 0) {
|
|
224
|
+
const shaped = strictNode(schema.items);
|
|
225
|
+
if (!shaped)
|
|
226
|
+
return null;
|
|
227
|
+
result.items = shaped;
|
|
228
|
+
}
|
|
229
|
+
if (schema.prefixItems !== void 0)
|
|
230
|
+
return null;
|
|
231
|
+
if (schema.anyOf !== void 0) {
|
|
232
|
+
const variants = schema.anyOf.map(strictNode);
|
|
233
|
+
if (variants.some((v) => v === null))
|
|
234
|
+
return null;
|
|
235
|
+
result.anyOf = variants;
|
|
236
|
+
}
|
|
237
|
+
for (const defsKey of ["$defs", "definitions"]) {
|
|
238
|
+
if (schema[defsKey] !== void 0) {
|
|
239
|
+
const defs = {};
|
|
240
|
+
for (const [name, child] of Object.entries(schema[defsKey])) {
|
|
241
|
+
const shaped = strictNode(child);
|
|
242
|
+
if (!shaped)
|
|
243
|
+
return null;
|
|
244
|
+
defs[name] = shaped;
|
|
245
|
+
}
|
|
246
|
+
result[defsKey] = defs;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return result;
|
|
250
|
+
}
|
|
251
|
+
return strictJsonSchema;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
var hasRequiredCodex;
|
|
255
|
+
function requireCodex() {
|
|
256
|
+
if (hasRequiredCodex) return codex;
|
|
257
|
+
hasRequiredCodex = 1;
|
|
258
|
+
Object.defineProperty(codex, "__esModule", { value: true });
|
|
259
|
+
codex.codexAdapter = void 0;
|
|
260
|
+
const strict_json_schema_1 = requireStrictJsonSchema();
|
|
261
|
+
const failure_classification_1 = requireFailureClassification();
|
|
262
|
+
const SCHEMA_FILE = "output-schema.json";
|
|
263
|
+
const LAST_MESSAGE_FILE = "last-message.txt";
|
|
264
|
+
codex.codexAdapter = {
|
|
265
|
+
id: "codex",
|
|
266
|
+
binaryName: "codex",
|
|
267
|
+
apiKeyEnvVars: ["OPENAI_API_KEY", "CODEX_API_KEY"],
|
|
268
|
+
// Codex's models have no equivalent among the aliases; set one with localAgent({ model }).
|
|
269
|
+
modelAliases: {},
|
|
270
|
+
// Codex accepts only OpenAI strict-mode schemas.
|
|
271
|
+
nativeSchema(envelopeSchema) {
|
|
272
|
+
return (0, strict_json_schema_1.toStrictSchema)(envelopeSchema);
|
|
273
|
+
},
|
|
274
|
+
buildInvocation(request, model) {
|
|
275
|
+
const args = [
|
|
276
|
+
"exec",
|
|
277
|
+
"-",
|
|
278
|
+
"--skip-git-repo-check",
|
|
279
|
+
"--ephemeral",
|
|
280
|
+
"--ignore-user-config",
|
|
281
|
+
"--ignore-rules",
|
|
282
|
+
"--sandbox",
|
|
283
|
+
"read-only",
|
|
284
|
+
"-c",
|
|
285
|
+
"model_reasoning_effort=low",
|
|
286
|
+
"--json",
|
|
287
|
+
"-o",
|
|
288
|
+
LAST_MESSAGE_FILE
|
|
289
|
+
];
|
|
290
|
+
if (model !== void 0) {
|
|
291
|
+
args.push("-m", model);
|
|
292
|
+
}
|
|
293
|
+
const files = [];
|
|
294
|
+
if (request.enforcement.kind === "native") {
|
|
295
|
+
args.push("--output-schema", SCHEMA_FILE);
|
|
296
|
+
files.push({ name: SCHEMA_FILE, content: JSON.stringify(request.enforcement.schema) });
|
|
297
|
+
}
|
|
298
|
+
return { args, stdin: request.prompt, files, outputFiles: [LAST_MESSAGE_FILE] };
|
|
299
|
+
},
|
|
300
|
+
readResult(result, request) {
|
|
301
|
+
const events = parseEvents(result.stdout);
|
|
302
|
+
const failed = events.find((e) => e.type === "turn.failed" || e.type === "error");
|
|
303
|
+
if (failed) {
|
|
304
|
+
const message = failed.error?.message ?? failed.message ?? "unknown error";
|
|
305
|
+
if (/invalid_json_schema/.test(message)) {
|
|
306
|
+
return {
|
|
307
|
+
kind: "failed",
|
|
308
|
+
failure: { kind: "schema-rejected", message: `codex rejected the output schema: ${message}` }
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
return { kind: "failed", failure: (0, failure_classification_1.classifyAgentFailure)("codex", message) };
|
|
312
|
+
}
|
|
313
|
+
const agentMessages = events.filter((e) => e.item?.type === "agent_message");
|
|
314
|
+
const lastMessage = result.outputFiles[LAST_MESSAGE_FILE] ?? agentMessages[agentMessages.length - 1]?.item?.text;
|
|
315
|
+
if (result.exitCode !== 0 || lastMessage === void 0) {
|
|
316
|
+
return {
|
|
317
|
+
kind: "failed",
|
|
318
|
+
failure: (0, failure_classification_1.classifyAgentFailure)("codex", `exited with code ${result.exitCode} without a reply: ${(0, failure_classification_1.stderrTail)(result)}`)
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
const completed = events.filter((e) => e.type === "turn.completed");
|
|
322
|
+
const promptTokens = completed.reduce((sum, e) => sum + (e.usage?.input_tokens ?? 0), 0);
|
|
323
|
+
const completionTokens = completed.reduce((sum, e) => sum + (e.usage?.output_tokens ?? 0), 0);
|
|
324
|
+
const reported = {
|
|
325
|
+
usage: { promptTokens, completionTokens, totalTokens: promptTokens + completionTokens },
|
|
326
|
+
// Codex does not report which model answered.
|
|
327
|
+
model: void 0,
|
|
328
|
+
costUsdEstimate: void 0
|
|
329
|
+
};
|
|
330
|
+
if (request.enforcement.kind === "in-prompt") {
|
|
331
|
+
return { kind: "answered", answer: { kind: "text", text: lastMessage }, ...reported };
|
|
332
|
+
}
|
|
333
|
+
let envelope;
|
|
334
|
+
try {
|
|
335
|
+
envelope = JSON.parse(lastMessage);
|
|
336
|
+
} catch {
|
|
337
|
+
return {
|
|
338
|
+
kind: "failed",
|
|
339
|
+
failure: { kind: "transient", message: `codex reply is not JSON: ${lastMessage}` }
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
return { kind: "answered", answer: { kind: "structured", envelope }, ...reported };
|
|
343
|
+
},
|
|
344
|
+
loginStatusArgs: ["login", "status"],
|
|
345
|
+
readLoginStatus(result) {
|
|
346
|
+
const detail = `${result.stdout}
|
|
347
|
+
${result.stderr}`.trim();
|
|
348
|
+
return { loggedIn: result.exitCode === 0, detail };
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
function parseEvents(stdout) {
|
|
352
|
+
const events = [];
|
|
353
|
+
for (const line of stdout.split("\n")) {
|
|
354
|
+
const trimmed = line.trim();
|
|
355
|
+
if (!trimmed.startsWith("{"))
|
|
356
|
+
continue;
|
|
357
|
+
try {
|
|
358
|
+
events.push(JSON.parse(trimmed));
|
|
359
|
+
} catch {
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
return events;
|
|
363
|
+
}
|
|
364
|
+
return codex;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
var hasRequiredAdapters;
|
|
368
|
+
function requireAdapters() {
|
|
369
|
+
if (hasRequiredAdapters) return adapters;
|
|
370
|
+
hasRequiredAdapters = 1;
|
|
371
|
+
Object.defineProperty(adapters, "__esModule", { value: true });
|
|
372
|
+
adapters.AGENT_ADAPTERS = void 0;
|
|
373
|
+
const claude_code_1 = requireClaudeCode();
|
|
374
|
+
const codex_1 = requireCodex();
|
|
375
|
+
adapters.AGENT_ADAPTERS = {
|
|
376
|
+
"claude-code": claude_code_1.claudeCodeAdapter,
|
|
377
|
+
codex: codex_1.codexAdapter
|
|
378
|
+
};
|
|
379
|
+
return adapters;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
var agentId = {};
|
|
383
|
+
|
|
384
|
+
var hasRequiredAgentId;
|
|
385
|
+
function requireAgentId() {
|
|
386
|
+
if (hasRequiredAgentId) return agentId;
|
|
387
|
+
hasRequiredAgentId = 1;
|
|
388
|
+
(function(exports$1) {
|
|
389
|
+
Object.defineProperty(exports$1, "__esModule", { value: true });
|
|
390
|
+
exports$1.LOCAL_AGENT_IDS = void 0;
|
|
391
|
+
exports$1.isLocalAgentId = isLocalAgentId;
|
|
392
|
+
exports$1.LOCAL_AGENT_IDS = ["claude-code", "codex"];
|
|
393
|
+
const LOCAL_AGENT_ID_SET = new Set(exports$1.LOCAL_AGENT_IDS);
|
|
394
|
+
function isLocalAgentId(value) {
|
|
395
|
+
return typeof value === "string" && LOCAL_AGENT_ID_SET.has(value);
|
|
396
|
+
}
|
|
397
|
+
})(agentId);
|
|
398
|
+
return agentId;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
var detect = {};
|
|
402
|
+
|
|
403
|
+
var processRunner = {};
|
|
404
|
+
|
|
405
|
+
const require$4 = createRequire(import.meta.url);
|
|
406
|
+
function __require$3() { return require$4("node:child_process"); }
|
|
407
|
+
|
|
408
|
+
const require$3 = createRequire(import.meta.url);
|
|
409
|
+
function __require$2() { return require$3("node:fs"); }
|
|
410
|
+
|
|
411
|
+
const require$2 = createRequire(import.meta.url);
|
|
412
|
+
function __require$1() { return require$2("node:os"); }
|
|
413
|
+
|
|
414
|
+
const require$1 = createRequire(import.meta.url);
|
|
415
|
+
function __require() { return require$1("node:path"); }
|
|
416
|
+
|
|
417
|
+
var hasRequiredProcessRunner;
|
|
418
|
+
function requireProcessRunner() {
|
|
419
|
+
if (hasRequiredProcessRunner) return processRunner;
|
|
420
|
+
hasRequiredProcessRunner = 1;
|
|
421
|
+
var __createBinding = processRunner && processRunner.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
422
|
+
if (k2 === void 0) k2 = k;
|
|
423
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
424
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
425
|
+
desc = { enumerable: true, get: function() {
|
|
426
|
+
return m[k];
|
|
427
|
+
} };
|
|
428
|
+
}
|
|
429
|
+
Object.defineProperty(o, k2, desc);
|
|
430
|
+
}) : (function(o, m, k, k2) {
|
|
431
|
+
if (k2 === void 0) k2 = k;
|
|
432
|
+
o[k2] = m[k];
|
|
433
|
+
}));
|
|
434
|
+
var __setModuleDefault = processRunner && processRunner.__setModuleDefault || (Object.create ? (function(o, v) {
|
|
435
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
436
|
+
}) : function(o, v) {
|
|
437
|
+
o["default"] = v;
|
|
438
|
+
});
|
|
439
|
+
var __importStar = processRunner && processRunner.__importStar || /* @__PURE__ */ (function() {
|
|
440
|
+
var ownKeys = function(o) {
|
|
441
|
+
ownKeys = Object.getOwnPropertyNames || function(o2) {
|
|
442
|
+
var ar = [];
|
|
443
|
+
for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
|
|
444
|
+
return ar;
|
|
445
|
+
};
|
|
446
|
+
return ownKeys(o);
|
|
447
|
+
};
|
|
448
|
+
return function(mod) {
|
|
449
|
+
if (mod && mod.__esModule) return mod;
|
|
450
|
+
var result = {};
|
|
451
|
+
if (mod != null) {
|
|
452
|
+
for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
453
|
+
}
|
|
454
|
+
__setModuleDefault(result, mod);
|
|
455
|
+
return result;
|
|
456
|
+
};
|
|
457
|
+
})();
|
|
458
|
+
Object.defineProperty(processRunner, "__esModule", { value: true });
|
|
459
|
+
processRunner.runInvocation = runInvocation;
|
|
460
|
+
processRunner.findOnPath = findOnPath;
|
|
461
|
+
const node_child_process_1 = __require$3();
|
|
462
|
+
const fs = __importStar(__require$2());
|
|
463
|
+
const os = __importStar(__require$1());
|
|
464
|
+
const path = __importStar(__require());
|
|
465
|
+
const KILL_GRACE_MS = 2e3;
|
|
466
|
+
async function runInvocation(options) {
|
|
467
|
+
const workDir = fs.mkdtempSync(path.join(os.tmpdir(), "nua-local-agent-"));
|
|
468
|
+
try {
|
|
469
|
+
for (const file of options.invocation.files ?? []) {
|
|
470
|
+
fs.writeFileSync(path.join(workDir, file.name), file.content);
|
|
471
|
+
}
|
|
472
|
+
const result = await spawnAndCollect(options, workDir);
|
|
473
|
+
for (const name of options.invocation.outputFiles ?? []) {
|
|
474
|
+
const filePath = path.join(workDir, name);
|
|
475
|
+
result.outputFiles[name] = fs.existsSync(filePath) ? fs.readFileSync(filePath, "utf8") : void 0;
|
|
476
|
+
}
|
|
477
|
+
return result;
|
|
478
|
+
} finally {
|
|
479
|
+
fs.rmSync(workDir, { recursive: true, force: true });
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
function spawnAndCollect(options, cwd) {
|
|
483
|
+
const env = { ...process.env };
|
|
484
|
+
for (const name of options.unsetEnv ?? []) {
|
|
485
|
+
delete env[name];
|
|
486
|
+
}
|
|
487
|
+
return new Promise((resolve, reject) => {
|
|
488
|
+
const child = (0, node_child_process_1.spawn)(options.binaryPath, options.invocation.args, {
|
|
489
|
+
cwd,
|
|
490
|
+
env,
|
|
491
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
492
|
+
windowsHide: true
|
|
493
|
+
});
|
|
494
|
+
const stdout = [];
|
|
495
|
+
const stderr = [];
|
|
496
|
+
let timedOut = false;
|
|
497
|
+
let killTimer;
|
|
498
|
+
const timeoutTimer = setTimeout(() => {
|
|
499
|
+
timedOut = true;
|
|
500
|
+
child.kill("SIGINT");
|
|
501
|
+
killTimer = setTimeout(() => child.kill("SIGKILL"), KILL_GRACE_MS);
|
|
502
|
+
}, options.timeoutMs);
|
|
503
|
+
child.stdout.on("data", (chunk) => stdout.push(chunk));
|
|
504
|
+
child.stderr.on("data", (chunk) => stderr.push(chunk));
|
|
505
|
+
child.on("error", (error) => {
|
|
506
|
+
clearTimeout(timeoutTimer);
|
|
507
|
+
clearTimeout(killTimer);
|
|
508
|
+
const reason = error.code === "ENOENT" ? "not found" : error.message;
|
|
509
|
+
reject(new Error(`Could not start ${options.binaryPath}: ${reason}`));
|
|
510
|
+
});
|
|
511
|
+
child.on("close", (exitCode) => {
|
|
512
|
+
clearTimeout(timeoutTimer);
|
|
513
|
+
clearTimeout(killTimer);
|
|
514
|
+
resolve({
|
|
515
|
+
exitCode,
|
|
516
|
+
stdout: Buffer.concat(stdout).toString("utf8"),
|
|
517
|
+
stderr: Buffer.concat(stderr).toString("utf8"),
|
|
518
|
+
timedOut,
|
|
519
|
+
outputFiles: {}
|
|
520
|
+
});
|
|
521
|
+
});
|
|
522
|
+
child.stdin.on("error", () => void 0);
|
|
523
|
+
child.stdin.end(options.invocation.stdin);
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
function findOnPath(binaryName) {
|
|
527
|
+
const isWindows = process.platform === "win32";
|
|
528
|
+
const extensions = isWindows ? (process.env.PATHEXT ?? ".EXE;.CMD;.BAT").split(";").filter(Boolean) : [""];
|
|
529
|
+
if (isWindows) {
|
|
530
|
+
extensions.sort((a, b) => Number(b.toUpperCase() === ".EXE") - Number(a.toUpperCase() === ".EXE"));
|
|
531
|
+
}
|
|
532
|
+
for (const dir of (process.env.PATH ?? "").split(path.delimiter)) {
|
|
533
|
+
if (!dir)
|
|
534
|
+
continue;
|
|
535
|
+
for (const ext of extensions) {
|
|
536
|
+
const candidate = path.join(dir, binaryName + ext);
|
|
537
|
+
try {
|
|
538
|
+
if (fs.statSync(candidate).isFile()) {
|
|
539
|
+
if (!isWindows)
|
|
540
|
+
fs.accessSync(candidate, fs.constants.X_OK);
|
|
541
|
+
return candidate;
|
|
542
|
+
}
|
|
543
|
+
} catch {
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
return null;
|
|
548
|
+
}
|
|
549
|
+
return processRunner;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
var hasRequiredDetect;
|
|
553
|
+
function requireDetect() {
|
|
554
|
+
if (hasRequiredDetect) return detect;
|
|
555
|
+
hasRequiredDetect = 1;
|
|
556
|
+
Object.defineProperty(detect, "__esModule", { value: true });
|
|
557
|
+
detect.detectLocalAgents = detectLocalAgents;
|
|
558
|
+
const adapters_1 = requireAdapters();
|
|
559
|
+
const agent_id_1 = requireAgentId();
|
|
560
|
+
const process_runner_1 = requireProcessRunner();
|
|
561
|
+
const STATUS_TIMEOUT_MS = 2e4;
|
|
562
|
+
async function detectLocalAgents(binaryPaths = {}) {
|
|
563
|
+
return Promise.all(agent_id_1.LOCAL_AGENT_IDS.map((id) => detectAgent(adapters_1.AGENT_ADAPTERS[id], binaryPaths[id])));
|
|
564
|
+
}
|
|
565
|
+
async function detectAgent(adapter, binaryPathOverride) {
|
|
566
|
+
const binaryPath = binaryPathOverride ?? (0, process_runner_1.findOnPath)(adapter.binaryName);
|
|
567
|
+
if (!binaryPath) {
|
|
568
|
+
return { agent: adapter.id, installed: false, loggedIn: false };
|
|
569
|
+
}
|
|
570
|
+
try {
|
|
571
|
+
const [versionResult, statusResult] = await Promise.all([
|
|
572
|
+
(0, process_runner_1.runInvocation)({
|
|
573
|
+
binaryPath,
|
|
574
|
+
invocation: { args: ["--version"], stdin: "" },
|
|
575
|
+
timeoutMs: STATUS_TIMEOUT_MS
|
|
576
|
+
}),
|
|
577
|
+
(0, process_runner_1.runInvocation)({
|
|
578
|
+
binaryPath,
|
|
579
|
+
invocation: { args: adapter.loginStatusArgs, stdin: "" },
|
|
580
|
+
timeoutMs: STATUS_TIMEOUT_MS,
|
|
581
|
+
// Report the CLI's own login, not an API key that happens to be set.
|
|
582
|
+
unsetEnv: adapter.apiKeyEnvVars
|
|
583
|
+
})
|
|
584
|
+
]);
|
|
585
|
+
if (versionResult.exitCode !== 0) {
|
|
586
|
+
return {
|
|
587
|
+
agent: adapter.id,
|
|
588
|
+
installed: false,
|
|
589
|
+
loggedIn: false,
|
|
590
|
+
detail: `${binaryPath} --version exited with code ${versionResult.exitCode}`
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
const login = adapter.readLoginStatus(statusResult);
|
|
594
|
+
return {
|
|
595
|
+
agent: adapter.id,
|
|
596
|
+
installed: true,
|
|
597
|
+
loggedIn: login.loggedIn,
|
|
598
|
+
binaryPath,
|
|
599
|
+
version: versionResult.stdout.trim() || void 0,
|
|
600
|
+
detail: login.detail
|
|
601
|
+
};
|
|
602
|
+
} catch (error) {
|
|
603
|
+
return {
|
|
604
|
+
agent: adapter.id,
|
|
605
|
+
installed: false,
|
|
606
|
+
loggedIn: false,
|
|
607
|
+
detail: error instanceof Error ? error.message : String(error)
|
|
608
|
+
};
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
return detect;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
var localAgent = {};
|
|
615
|
+
|
|
616
|
+
var localAgentEngine = {};
|
|
617
|
+
|
|
618
|
+
var hasRequiredLocalAgentEngine;
|
|
619
|
+
function requireLocalAgentEngine() {
|
|
620
|
+
if (hasRequiredLocalAgentEngine) return localAgentEngine;
|
|
621
|
+
hasRequiredLocalAgentEngine = 1;
|
|
622
|
+
Object.defineProperty(localAgentEngine, "__esModule", { value: true });
|
|
623
|
+
localAgentEngine.LocalAgentEngine = void 0;
|
|
624
|
+
const logger_1 = requireLogger();
|
|
625
|
+
const process_runner_1 = requireProcessRunner();
|
|
626
|
+
class LocalAgentEngine {
|
|
627
|
+
constructor(runner, model) {
|
|
628
|
+
this.runner = runner;
|
|
629
|
+
this.model = model;
|
|
630
|
+
}
|
|
631
|
+
nativeSchema(envelopeSchema) {
|
|
632
|
+
return this.runner.adapter.nativeSchema(envelopeSchema);
|
|
633
|
+
}
|
|
634
|
+
attempt(request) {
|
|
635
|
+
return this.runner.limiter.run(() => this.runAgent(request));
|
|
636
|
+
}
|
|
637
|
+
async runAgent(request) {
|
|
638
|
+
const { adapter, binaryPath, logger, timeoutMs, unsetEnv } = this.runner;
|
|
639
|
+
const spanId = (0, logger_1.generateSpanId)();
|
|
640
|
+
const startTime = Date.now();
|
|
641
|
+
const method = request.enforcement.kind;
|
|
642
|
+
logger.info("LLM call started", {
|
|
643
|
+
type: "llm_call_start",
|
|
644
|
+
span_id: spanId,
|
|
645
|
+
service: adapter.id,
|
|
646
|
+
method,
|
|
647
|
+
binaryPath,
|
|
648
|
+
model: this.model ?? "default"
|
|
649
|
+
});
|
|
650
|
+
const failed = (failure) => {
|
|
651
|
+
(0, logger_1.logLlmCallError)(logger, spanId, adapter.id, method, failure.message, Date.now() - startTime);
|
|
652
|
+
return { kind: "failed", failure };
|
|
653
|
+
};
|
|
654
|
+
let result;
|
|
655
|
+
try {
|
|
656
|
+
result = await (0, process_runner_1.runInvocation)({
|
|
657
|
+
binaryPath,
|
|
658
|
+
invocation: adapter.buildInvocation(request, this.model),
|
|
659
|
+
timeoutMs,
|
|
660
|
+
unsetEnv
|
|
661
|
+
});
|
|
662
|
+
} catch (error) {
|
|
663
|
+
return failed({ kind: "fatal", message: error instanceof Error ? error.message : String(error) });
|
|
664
|
+
}
|
|
665
|
+
if (result.timedOut) {
|
|
666
|
+
return failed({ kind: "fatal", message: `${adapter.id} did not finish within ${timeoutMs}ms` });
|
|
667
|
+
}
|
|
668
|
+
const reply = adapter.readResult(result, request);
|
|
669
|
+
if (reply.kind === "failed") {
|
|
670
|
+
return failed(reply.failure);
|
|
671
|
+
}
|
|
672
|
+
logger.info("LLM call completed", {
|
|
673
|
+
type: "llm_call_complete",
|
|
674
|
+
span_id: spanId,
|
|
675
|
+
service: adapter.id,
|
|
676
|
+
method,
|
|
677
|
+
exitCode: result.exitCode,
|
|
678
|
+
usage: reply.usage,
|
|
679
|
+
duration_ms: Date.now() - startTime
|
|
680
|
+
});
|
|
681
|
+
return {
|
|
682
|
+
kind: "answered",
|
|
683
|
+
answer: reply.answer,
|
|
684
|
+
usage: reply.usage,
|
|
685
|
+
origin: {
|
|
686
|
+
engine: "local-agent",
|
|
687
|
+
agent: adapter.id,
|
|
688
|
+
model: reply.model ?? this.model,
|
|
689
|
+
costUsdEstimate: reply.costUsdEstimate
|
|
690
|
+
}
|
|
691
|
+
};
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
localAgentEngine.LocalAgentEngine = LocalAgentEngine;
|
|
695
|
+
return localAgentEngine;
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
var hasRequiredLocalAgent$1;
|
|
699
|
+
function requireLocalAgent$1() {
|
|
700
|
+
if (hasRequiredLocalAgent$1) return localAgent;
|
|
701
|
+
hasRequiredLocalAgent$1 = 1;
|
|
702
|
+
Object.defineProperty(localAgent, "__esModule", { value: true });
|
|
703
|
+
localAgent.LocalAgent = void 0;
|
|
704
|
+
const local_agent_engine_1 = requireLocalAgentEngine();
|
|
705
|
+
class LocalAgent {
|
|
706
|
+
constructor(runner, defaultModel) {
|
|
707
|
+
this.runner = runner;
|
|
708
|
+
this.defaultModel = defaultModel;
|
|
709
|
+
this.agent = runner.adapter.id;
|
|
710
|
+
this.logger = runner.logger;
|
|
711
|
+
}
|
|
712
|
+
/**
|
|
713
|
+
* No model choice runs the default model. An alias runs the CLI's equivalent
|
|
714
|
+
* model, if it has one. Provider models cannot run on a local agent.
|
|
715
|
+
*/
|
|
716
|
+
route(model) {
|
|
717
|
+
if (model === void 0) {
|
|
718
|
+
return this.routeTo(this.defaultModel);
|
|
719
|
+
}
|
|
720
|
+
if (!("alias" in model)) {
|
|
721
|
+
return {
|
|
722
|
+
kind: "unroutable",
|
|
723
|
+
message: `${this.agent} takes model aliases, not provider models. Set the agent's own model with localAgent({ model }).`
|
|
724
|
+
};
|
|
725
|
+
}
|
|
726
|
+
const agentModel = this.runner.adapter.modelAliases[model.alias];
|
|
727
|
+
if (agentModel === void 0) {
|
|
728
|
+
return { kind: "unroutable", message: `Model alias "${model.alias}" has no ${this.agent} equivalent` };
|
|
729
|
+
}
|
|
730
|
+
return this.routeTo(agentModel);
|
|
731
|
+
}
|
|
732
|
+
routeTo(model) {
|
|
733
|
+
return { kind: "routed", engine: new local_agent_engine_1.LocalAgentEngine(this.runner, model) };
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
localAgent.LocalAgent = LocalAgent;
|
|
737
|
+
return localAgent;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
var semaphore = {};
|
|
741
|
+
|
|
742
|
+
var hasRequiredSemaphore;
|
|
743
|
+
function requireSemaphore() {
|
|
744
|
+
if (hasRequiredSemaphore) return semaphore;
|
|
745
|
+
hasRequiredSemaphore = 1;
|
|
746
|
+
Object.defineProperty(semaphore, "__esModule", { value: true });
|
|
747
|
+
semaphore.Semaphore = void 0;
|
|
748
|
+
class Semaphore {
|
|
749
|
+
constructor(limit) {
|
|
750
|
+
this.limit = limit;
|
|
751
|
+
this.active = 0;
|
|
752
|
+
this.waiting = [];
|
|
753
|
+
}
|
|
754
|
+
async run(task) {
|
|
755
|
+
if (this.active >= this.limit) {
|
|
756
|
+
await new Promise((resolve) => this.waiting.push(resolve));
|
|
757
|
+
} else {
|
|
758
|
+
this.active++;
|
|
759
|
+
}
|
|
760
|
+
try {
|
|
761
|
+
return await task();
|
|
762
|
+
} finally {
|
|
763
|
+
const next = this.waiting.shift();
|
|
764
|
+
if (next) {
|
|
765
|
+
next();
|
|
766
|
+
} else {
|
|
767
|
+
this.active--;
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
semaphore.Semaphore = Semaphore;
|
|
773
|
+
return semaphore;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
var hasRequiredCreateLocalAgent;
|
|
777
|
+
function requireCreateLocalAgent() {
|
|
778
|
+
if (hasRequiredCreateLocalAgent) return createLocalAgent;
|
|
779
|
+
hasRequiredCreateLocalAgent = 1;
|
|
780
|
+
Object.defineProperty(createLocalAgent, "__esModule", { value: true });
|
|
781
|
+
createLocalAgent.localAgent = localAgent;
|
|
782
|
+
createLocalAgent.findLocalAgent = findLocalAgent;
|
|
783
|
+
const logger_1 = requireLogger();
|
|
784
|
+
const adapters_1 = requireAdapters();
|
|
785
|
+
const agent_id_1 = requireAgentId();
|
|
786
|
+
const detect_1 = requireDetect();
|
|
787
|
+
const local_agent_1 = requireLocalAgent$1();
|
|
788
|
+
const process_runner_1 = requireProcessRunner();
|
|
789
|
+
const semaphore_1 = requireSemaphore();
|
|
790
|
+
const DEFAULT_TIMEOUT_MS = 18e4;
|
|
791
|
+
const DEFAULT_CONCURRENCY = 2;
|
|
792
|
+
function localAgent(config) {
|
|
793
|
+
if (!(0, agent_id_1.isLocalAgentId)(config.agent)) {
|
|
794
|
+
throw new TypeError(`Unknown local agent: ${String(config.agent)}`);
|
|
795
|
+
}
|
|
796
|
+
const settings = parseOptions(config);
|
|
797
|
+
const adapter = adapters_1.AGENT_ADAPTERS[config.agent];
|
|
798
|
+
const binaryPath = config.binaryPath ?? (0, process_runner_1.findOnPath)(adapter.binaryName);
|
|
799
|
+
if (!binaryPath) {
|
|
800
|
+
throw new Error(`${adapter.binaryName} was not found on PATH. Install ${config.agent} or set binaryPath.`);
|
|
801
|
+
}
|
|
802
|
+
return setUpLocalAgent(adapter, binaryPath, settings);
|
|
803
|
+
}
|
|
804
|
+
async function findLocalAgent(options = {}) {
|
|
805
|
+
const settings = parseOptions(options);
|
|
806
|
+
const statuses = await (0, detect_1.detectLocalAgents)();
|
|
807
|
+
for (const status of statuses) {
|
|
808
|
+
if (status.installed && status.loggedIn) {
|
|
809
|
+
return setUpLocalAgent(adapters_1.AGENT_ADAPTERS[status.agent], status.binaryPath, settings);
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
const summary = statuses.map((s) => `${s.agent}: ${s.installed ? "not logged in" : "not installed"}`).join(", ");
|
|
813
|
+
throw new Error(`No logged-in coding agent found (${summary})`);
|
|
814
|
+
}
|
|
815
|
+
function parseOptions(options) {
|
|
816
|
+
const concurrency = options.concurrency ?? DEFAULT_CONCURRENCY;
|
|
817
|
+
if (!Number.isInteger(concurrency) || concurrency < 1) {
|
|
818
|
+
throw new TypeError("concurrency must be a positive integer");
|
|
819
|
+
}
|
|
820
|
+
if (options.model !== void 0 && options.model.trim() === "") {
|
|
821
|
+
throw new TypeError("model must be a non-empty string; omit it to use the agent's default model");
|
|
822
|
+
}
|
|
823
|
+
return {
|
|
824
|
+
model: options.model,
|
|
825
|
+
timeoutMs: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,
|
|
826
|
+
concurrency,
|
|
827
|
+
auth: options.auth ?? "subscription",
|
|
828
|
+
logger: options.logger ?? new logger_1.ConsoleLogger()
|
|
829
|
+
};
|
|
830
|
+
}
|
|
831
|
+
function setUpLocalAgent(adapter, binaryPath, settings) {
|
|
832
|
+
if (/\.(cmd|bat)$/i.test(binaryPath)) {
|
|
833
|
+
throw new Error(`${binaryPath} is a .cmd shim, which local agents cannot run safely. Set binaryPath to the agent's native executable.`);
|
|
834
|
+
}
|
|
835
|
+
const runner = {
|
|
836
|
+
adapter,
|
|
837
|
+
binaryPath,
|
|
838
|
+
timeoutMs: settings.timeoutMs,
|
|
839
|
+
unsetEnv: settings.auth === "subscription" ? adapter.apiKeyEnvVars : [],
|
|
840
|
+
limiter: new semaphore_1.Semaphore(settings.concurrency),
|
|
841
|
+
logger: settings.logger
|
|
842
|
+
};
|
|
843
|
+
return new local_agent_1.LocalAgent(runner, settings.model);
|
|
844
|
+
}
|
|
845
|
+
return createLocalAgent;
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
var hasRequiredLocalAgent;
|
|
849
|
+
function requireLocalAgent() {
|
|
850
|
+
if (hasRequiredLocalAgent) return localAgent$1;
|
|
851
|
+
hasRequiredLocalAgent = 1;
|
|
852
|
+
(function(exports$1) {
|
|
853
|
+
Object.defineProperty(exports$1, "__esModule", { value: true });
|
|
854
|
+
exports$1.isLocalAgentId = exports$1.LOCAL_AGENT_IDS = exports$1.detectLocalAgents = exports$1.localAgent = exports$1.findLocalAgent = void 0;
|
|
855
|
+
var create_local_agent_1 = requireCreateLocalAgent();
|
|
856
|
+
Object.defineProperty(exports$1, "findLocalAgent", { enumerable: true, get: function() {
|
|
857
|
+
return create_local_agent_1.findLocalAgent;
|
|
858
|
+
} });
|
|
859
|
+
Object.defineProperty(exports$1, "localAgent", { enumerable: true, get: function() {
|
|
860
|
+
return create_local_agent_1.localAgent;
|
|
861
|
+
} });
|
|
862
|
+
var detect_1 = requireDetect();
|
|
863
|
+
Object.defineProperty(exports$1, "detectLocalAgents", { enumerable: true, get: function() {
|
|
864
|
+
return detect_1.detectLocalAgents;
|
|
865
|
+
} });
|
|
866
|
+
var agent_id_1 = requireAgentId();
|
|
867
|
+
Object.defineProperty(exports$1, "LOCAL_AGENT_IDS", { enumerable: true, get: function() {
|
|
868
|
+
return agent_id_1.LOCAL_AGENT_IDS;
|
|
869
|
+
} });
|
|
870
|
+
Object.defineProperty(exports$1, "isLocalAgentId", { enumerable: true, get: function() {
|
|
871
|
+
return agent_id_1.isLocalAgentId;
|
|
872
|
+
} });
|
|
873
|
+
})(localAgent$1);
|
|
874
|
+
return localAgent$1;
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
var localAgentExports = requireLocalAgent();
|
|
878
|
+
|
|
879
|
+
var LOCAL_AGENT_IDS = localAgentExports.LOCAL_AGENT_IDS;
|
|
880
|
+
var detectLocalAgents = localAgentExports.detectLocalAgents;
|
|
881
|
+
var findLocalAgent = localAgentExports.findLocalAgent;
|
|
882
|
+
var isLocalAgentId = localAgentExports.isLocalAgentId;
|
|
883
|
+
var localAgent$2 = localAgentExports.localAgent;
|
|
884
|
+
export { LOCAL_AGENT_IDS, detectLocalAgents, findLocalAgent, isLocalAgentId, localAgent$2 as localAgent };
|