nuabase 2.3.7 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/README.md +233 -200
  3. package/dist/chunks/local-agent-Bj-QKikS.d.cts +270 -0
  4. package/dist/chunks/local-agent-Bj-QKikS.d.mts +270 -0
  5. package/dist/cjs/chunks/strict-json-schema-bKwaMWm1.cjs +145 -0
  6. package/dist/cjs/index.cjs +991 -11473
  7. package/dist/cjs/local-agent.cjs +809 -953
  8. package/dist/esm/chunks/strict-json-schema-Du2LLrVP.mjs +138 -0
  9. package/dist/esm/index.mjs +989 -11471
  10. package/dist/esm/local-agent.mjs +782 -954
  11. package/dist/index.d.cts +94 -0
  12. package/dist/index.d.mts +94 -0
  13. package/dist/local-agent.d.cts +150 -0
  14. package/dist/local-agent.d.mts +150 -0
  15. package/package.json +12 -24
  16. package/dist/cjs/chunks/logger-Co5uZG0A.cjs +0 -90
  17. package/dist/esm/chunks/logger-DnkHzkX_.mjs +0 -88
  18. package/dist/types/__tests__/helpers/client-factory.d.ts +0 -39
  19. package/dist/types/__tests__/helpers/index.d.ts +0 -2
  20. package/dist/types/backend/direct.d.ts +0 -29
  21. package/dist/types/backend/gateway.d.ts +0 -24
  22. package/dist/types/backend/types.d.ts +0 -68
  23. package/dist/types/index.d.cts +0 -7
  24. package/dist/types/index.d.mts +0 -7
  25. package/dist/types/lib/auth.d.ts +0 -14
  26. package/dist/types/lib/env.d.ts +0 -1
  27. package/dist/types/lib/error-response.d.ts +0 -6
  28. package/dist/types/lib/error-utils.d.ts +0 -6
  29. package/dist/types/local-agent.d.cts +0 -2
  30. package/dist/types/local-agent.d.mts +0 -2
  31. package/dist/types/nua-llm-core/index.d.ts +0 -23
  32. package/dist/types/nua-llm-core/lib/error-utils.d.ts +0 -6
  33. package/dist/types/nua-llm-core/lib/logger.d.ts +0 -44
  34. package/dist/types/nua-llm-core/lib/nua-errors.d.ts +0 -12
  35. package/dist/types/nua-llm-core/lib/prompt-template-utils.d.ts +0 -2
  36. package/dist/types/nua-llm-core/lib/schema-utils.d.ts +0 -1
  37. package/dist/types/nua-llm-core/lib/stable-stringify.d.ts +0 -1
  38. package/dist/types/nua-llm-core/lib/strict-json-schema.d.ts +0 -7
  39. package/dist/types/nua-llm-core/lib/types.d.ts +0 -8
  40. package/dist/types/nua-llm-core/lib/validate-mappable-input-data.d.ts +0 -4
  41. package/dist/types/nua-llm-core/local-agent.d.ts +0 -7
  42. package/dist/types/nua-llm-core/modules/agent/agent-loop.d.ts +0 -10
  43. package/dist/types/nua-llm-core/modules/agent/agent-turn.d.ts +0 -17
  44. package/dist/types/nua-llm-core/modules/agent/provider-formatters.d.ts +0 -22
  45. package/dist/types/nua-llm-core/modules/agent/run-agent.d.ts +0 -7
  46. package/dist/types/nua-llm-core/modules/agent/types.d.ts +0 -90
  47. package/dist/types/nua-llm-core/modules/cast/cast-request.d.ts +0 -32
  48. package/dist/types/nua-llm-core/modules/cast/envelope.d.ts +0 -9
  49. package/dist/types/nua-llm-core/modules/cast/list-schema.d.ts +0 -32
  50. package/dist/types/nua-llm-core/modules/cast/prompts/list-prompt.d.ts +0 -3
  51. package/dist/types/nua-llm-core/modules/cast/prompts/render-prompt.d.ts +0 -7
  52. package/dist/types/nua-llm-core/modules/cast/prompts/value-prompt.d.ts +0 -3
  53. package/dist/types/nua-llm-core/modules/cast/run-cast.d.ts +0 -44
  54. package/dist/types/nua-llm-core/modules/engine/engine-router.d.ts +0 -23
  55. package/dist/types/nua-llm-core/modules/engine/http/http-engine.d.ts +0 -12
  56. package/dist/types/nua-llm-core/modules/engine/http/provider-call.d.ts +0 -33
  57. package/dist/types/nua-llm-core/modules/engine/http/provider-config.d.ts +0 -65
  58. package/dist/types/nua-llm-core/modules/engine/http/provider-engines.d.ts +0 -35
  59. package/dist/types/nua-llm-core/modules/engine/llm-engine.d.ts +0 -73
  60. package/dist/types/nua-llm-core/modules/engine/local-agent/adapters/claude-code.d.ts +0 -2
  61. package/dist/types/nua-llm-core/modules/engine/local-agent/adapters/codex.d.ts +0 -2
  62. package/dist/types/nua-llm-core/modules/engine/local-agent/adapters/failure-classification.d.ts +0 -4
  63. package/dist/types/nua-llm-core/modules/engine/local-agent/adapters/index.d.ts +0 -3
  64. package/dist/types/nua-llm-core/modules/engine/local-agent/adapters/pi.d.ts +0 -2
  65. package/dist/types/nua-llm-core/modules/engine/local-agent/adapters/types.d.ts +0 -61
  66. package/dist/types/nua-llm-core/modules/engine/local-agent/agent-id.d.ts +0 -4
  67. package/dist/types/nua-llm-core/modules/engine/local-agent/create-local-agent.d.ts +0 -36
  68. package/dist/types/nua-llm-core/modules/engine/local-agent/detect.d.ts +0 -20
  69. package/dist/types/nua-llm-core/modules/engine/local-agent/local-agent-engine.d.ts +0 -32
  70. package/dist/types/nua-llm-core/modules/engine/local-agent/local-agent.d.ts +0 -25
  71. package/dist/types/nua-llm-core/modules/engine/local-agent/process-runner.d.ts +0 -16
  72. package/dist/types/nua-llm-core/modules/engine/local-agent/semaphore.d.ts +0 -8
  73. package/dist/types/nua-llm-core/modules/execution/llm-response-extraction.d.ts +0 -5
  74. package/dist/types/nua-llm-core/modules/json-schema-validation/ajv-instances.d.ts +0 -12
  75. package/dist/types/nua-llm-core/modules/json-schema-validation/nua-json-schema-value-validation.d.ts +0 -10
  76. package/dist/types/nua-llm-core/modules/json-schema-validation/validate-json-schema.d.ts +0 -2
  77. package/dist/types/nua-llm-core/modules/model-info/index.d.ts +0 -15
  78. package/dist/types/nua-llm-core/modules/streaming/sse-parser.d.ts +0 -7
  79. package/dist/types/nua-llm-core/nua-llm-client.d.ts +0 -37
  80. package/dist/types/nua.d.ts +0 -42
@@ -1,1043 +1,899 @@
1
1
  'use strict';
2
2
 
3
- var logger = require('./chunks/logger-Co5uZG0A.cjs');
4
- var node_module = require('node:module');
5
-
6
- var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
7
- var localAgent$1 = {};
8
-
9
- var createLocalAgent = {};
10
-
11
- var adapters = {};
12
-
13
- var claudeCode = {};
14
-
15
- var failureClassification = {};
16
-
17
- var hasRequiredFailureClassification;
18
- function requireFailureClassification() {
19
- if (hasRequiredFailureClassification) return failureClassification;
20
- hasRequiredFailureClassification = 1;
21
- Object.defineProperty(failureClassification, "__esModule", { value: true });
22
- failureClassification.classifyAgentFailure = classifyAgentFailure;
23
- failureClassification.stderrTail = stderrTail;
24
- const FATAL_PATTERNS = [
25
- /not logged in/i,
26
- /logged out/i,
27
- /(please|need to|must) (run .*)?log ?in/i,
28
- /authenticat/i,
29
- /unauthori[sz]ed/i,
30
- /invalid api key/i,
31
- /oauth/i,
32
- /usage limit/i,
33
- /rate.?limit/i,
34
- /quota/i,
35
- /credit balance/i,
36
- /\b40[13]\b/,
37
- /\b429\b/,
38
- /not supported when using/i,
39
- /model .* (does not exist|not found|not available)/i
40
- ];
41
- function classifyAgentFailure(agent, message) {
42
- const full = `${agent}: ${message}`;
43
- if (FATAL_PATTERNS.some((pattern) => pattern.test(message))) {
44
- return { kind: "fatal", message: full };
45
- }
46
- return { kind: "transient", message: full };
3
+ var strictJsonSchema = require('./chunks/strict-json-schema-bKwaMWm1.cjs');
4
+ var node_child_process = require('node:child_process');
5
+ var fs = require('node:fs');
6
+ var os = require('node:os');
7
+ var path = require('node:path');
8
+ var node_crypto = require('node:crypto');
9
+ var node_util = require('node:util');
10
+
11
+ function _interopNamespaceDefault(e) {
12
+ var n = Object.create(null);
13
+ if (e) {
14
+ Object.keys(e).forEach(function (k) {
15
+ if (k !== 'default') {
16
+ var d = Object.getOwnPropertyDescriptor(e, k);
17
+ Object.defineProperty(n, k, d.get ? d : {
18
+ enumerable: true,
19
+ get: function () { return e[k]; }
20
+ });
21
+ }
22
+ });
47
23
  }
48
- function stderrTail(result, maxChars = 2e3) {
49
- const stderr = result.stderr.trim();
50
- return stderr.length > maxChars ? stderr.slice(-maxChars) : stderr;
24
+ n.default = e;
25
+ return Object.freeze(n);
26
+ }
27
+
28
+ var fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs);
29
+ var os__namespace = /*#__PURE__*/_interopNamespaceDefault(os);
30
+ var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
31
+
32
+ const FATAL_PATTERNS = [
33
+ /not logged in/i,
34
+ /logged out/i,
35
+ /(please|need to|must) (run .*)?log ?in/i,
36
+ /authenticat/i,
37
+ /unauthori[sz]ed/i,
38
+ /invalid api key/i,
39
+ /oauth/i,
40
+ /usage limit/i,
41
+ /rate.?limit/i,
42
+ /quota/i,
43
+ /credit balance/i,
44
+ /\b40[13]\b/,
45
+ /\b429\b/,
46
+ /not supported when using/i,
47
+ /model .* (does not exist|not found|not available)/i
48
+ ];
49
+ function classifyAgentFailure(message) {
50
+ if (FATAL_PATTERNS.some((pattern) => pattern.test(message))) {
51
+ return { kind: "fatal", message };
51
52
  }
52
- return failureClassification;
53
+ return { kind: "transient", message };
54
+ }
55
+ function stderrTail(result, maxChars = 2e3) {
56
+ const stderr = result.stderr.trim();
57
+ return stderr.length > maxChars ? stderr.slice(-maxChars) : stderr;
53
58
  }
54
59
 
55
- var hasRequiredClaudeCode;
56
- function requireClaudeCode() {
57
- if (hasRequiredClaudeCode) return claudeCode;
58
- hasRequiredClaudeCode = 1;
59
- Object.defineProperty(claudeCode, "__esModule", { value: true });
60
- claudeCode.claudeCodeAdapter = void 0;
61
- const failure_classification_1 = requireFailureClassification();
62
- const SYSTEM_PROMPT = [
63
- "You are a data transformation function called by a program.",
64
- "You have no tools. Follow the instructions in the user message exactly",
65
- "and reply only with the requested JSON."
66
- ].join(" ");
67
- claudeCode.claudeCodeAdapter = {
68
- id: "claude-code",
69
- binaryName: "claude",
70
- apiKeyEnvVars: ["ANTHROPIC_API_KEY", "ANTHROPIC_AUTH_TOKEN"],
71
- modelAliases: { haiku: "haiku", sonnet: "sonnet", opus: "opus" },
72
- // Claude Code accepts any JSON Schema with an object root.
73
- nativeSchema(envelopeSchema) {
74
- return envelopeSchema;
75
- },
76
- buildInvocation(request, model) {
77
- const args = [
78
- "-p",
79
- "--output-format",
80
- "json",
81
- "--tools",
82
- "",
83
- "--setting-sources",
84
- "",
85
- "--strict-mcp-config",
86
- "--no-session-persistence",
87
- "--system-prompt",
88
- SYSTEM_PROMPT
89
- ];
90
- if (model !== void 0) {
91
- args.push("--model", model);
92
- }
93
- if (request.enforcement.kind === "native") {
94
- args.push("--json-schema", JSON.stringify(request.enforcement.schema));
95
- }
96
- return { args, stdin: request.prompt };
97
- },
98
- readResult(result, request) {
99
- let json;
100
- try {
101
- json = JSON.parse(result.stdout);
102
- } catch {
103
- return {
104
- kind: "failed",
105
- failure: (0, failure_classification_1.classifyAgentFailure)("claude", `exited with code ${result.exitCode} without a JSON result: ${(0, failure_classification_1.stderrTail)(result)}`)
106
- };
107
- }
108
- if (json.is_error) {
109
- const message = json.result || `error (${json.subtype ?? "unknown"})`;
110
- if (json.api_error_status === 400 && /input_schema|json.?schema/i.test(message)) {
111
- return {
112
- kind: "failed",
113
- failure: { kind: "schema-rejected", message: `claude rejected the output schema: ${message}` }
114
- };
115
- }
116
- if (json.api_error_status === 401 || json.api_error_status === 403 || json.api_error_status === 429) {
117
- return { kind: "failed", failure: { kind: "fatal", message: `claude: ${message}` } };
118
- }
119
- return { kind: "failed", failure: (0, failure_classification_1.classifyAgentFailure)("claude", message) };
120
- }
121
- if (json.subtype !== "success") {
122
- return {
123
- kind: "failed",
124
- failure: {
125
- kind: "transient",
126
- message: `claude did not finish successfully (${json.subtype ?? "no subtype"})`
127
- }
128
- };
129
- }
130
- const usage = json.usage ?? {};
131
- const promptTokens = (usage.input_tokens ?? 0) + (usage.cache_creation_input_tokens ?? 0) + (usage.cache_read_input_tokens ?? 0);
132
- const completionTokens = usage.output_tokens ?? 0;
133
- const reported = {
134
- usage: { promptTokens, completionTokens, totalTokens: promptTokens + completionTokens },
135
- model: Object.keys(json.modelUsage ?? {})[0],
136
- costUsdEstimate: json.total_cost_usd
60
+ const SYSTEM_PROMPT$1 = [
61
+ "You are a data transformation function called by a program.",
62
+ "You have no tools. Follow the instructions in the user message exactly",
63
+ "and reply only with the requested JSON."
64
+ ].join(" ");
65
+ const claudeCodeAdapter = {
66
+ id: "claude-code",
67
+ binaryName: "claude",
68
+ apiKeyEnvVars: ["ANTHROPIC_API_KEY", "ANTHROPIC_AUTH_TOKEN"],
69
+ modelAliases: { haiku: "haiku", sonnet: "sonnet", opus: "opus" },
70
+ // Claude Code accepts any JSON Schema with an object root.
71
+ nativeSchema(envelopeSchema) {
72
+ return envelopeSchema;
73
+ },
74
+ buildInvocation(request, { model, effort }) {
75
+ const args = [
76
+ "-p",
77
+ "--output-format",
78
+ "json",
79
+ "--tools",
80
+ "",
81
+ "--setting-sources",
82
+ "",
83
+ "--strict-mcp-config",
84
+ "--no-session-persistence",
85
+ "--system-prompt",
86
+ SYSTEM_PROMPT$1
87
+ ];
88
+ if (model !== void 0) {
89
+ args.push("--model", model);
90
+ }
91
+ if (effort !== void 0) {
92
+ args.push("--effort", effort);
93
+ }
94
+ if (request.enforcement.kind === "native") {
95
+ args.push("--json-schema", JSON.stringify(request.enforcement.schema));
96
+ }
97
+ return { args, stdin: request.prompt };
98
+ },
99
+ readResult(result, request) {
100
+ let json;
101
+ try {
102
+ json = JSON.parse(result.stdout);
103
+ } catch {
104
+ return {
105
+ kind: "failed",
106
+ failure: classifyAgentFailure(
107
+ `exited with code ${result.exitCode} without a JSON result: ${stderrTail(result)}`
108
+ )
137
109
  };
138
- if (request.enforcement.kind === "in-prompt") {
139
- return { kind: "answered", answer: { kind: "text", text: json.result ?? "" }, ...reported };
140
- }
141
- if (!json.structured_output) {
110
+ }
111
+ if (json.is_error) {
112
+ const message = json.result || `error (${json.subtype ?? "unknown"})`;
113
+ if (json.api_error_status === 400 && /input_schema|json.?schema/i.test(message)) {
142
114
  return {
143
115
  kind: "failed",
144
- failure: {
145
- kind: "transient",
146
- message: `claude returned no structured output. Reply: ${json.result ?? ""}`
147
- }
116
+ failure: { kind: "schema-rejected", message: `rejected the output schema: ${message}` }
148
117
  };
149
118
  }
150
- return {
151
- kind: "answered",
152
- answer: { kind: "structured", envelope: json.structured_output },
153
- ...reported
154
- };
155
- },
156
- loginStatusArgs: ["auth", "status"],
157
- readLoginStatus(result) {
158
- try {
159
- const status = JSON.parse(result.stdout);
160
- return { loggedIn: status.loggedIn === true, detail: status.authMethod };
161
- } catch {
162
- return { loggedIn: false, detail: (0, failure_classification_1.stderrTail)(result) || result.stdout.trim() };
163
- }
164
- }
165
- };
166
- return claudeCode;
167
- }
168
-
169
- var codex = {};
170
-
171
- var strictJsonSchema = {};
172
-
173
- var hasRequiredStrictJsonSchema;
174
- function requireStrictJsonSchema() {
175
- if (hasRequiredStrictJsonSchema) return strictJsonSchema;
176
- hasRequiredStrictJsonSchema = 1;
177
- Object.defineProperty(strictJsonSchema, "__esModule", { value: true });
178
- strictJsonSchema.toStrictSchema = toStrictSchema;
179
- const STRICT_UNSUPPORTED_KEYWORDS = /* @__PURE__ */ new Set([
180
- "patternProperties",
181
- "propertyNames",
182
- "unevaluatedProperties",
183
- "dependentRequired",
184
- "dependentSchemas",
185
- "if",
186
- "then",
187
- "else",
188
- "not",
189
- "allOf",
190
- "oneOf"
191
- ]);
192
- function toStrictSchema(schema) {
193
- return strictNode(schema);
194
- }
195
- function strictNode(node) {
196
- if (typeof node !== "object" || node === null || Array.isArray(node)) {
197
- return null;
198
- }
199
- const schema = node;
200
- for (const key of Object.keys(schema)) {
201
- if (STRICT_UNSUPPORTED_KEYWORDS.has(key))
202
- return null;
203
- }
204
- const result = { ...schema };
205
- delete result.$schema;
206
- const isObject = schema.type === "object" || Array.isArray(schema.type) && schema.type.includes("object") || schema.properties !== void 0;
207
- if (isObject) {
208
- const properties = schema.properties ?? {};
209
- if (schema.additionalProperties !== void 0 && schema.additionalProperties !== false) {
210
- return null;
211
- }
212
- const required = new Set(schema.required ?? []);
213
- const shapedProperties = {};
214
- for (const [name, child] of Object.entries(properties)) {
215
- if (!required.has(name))
216
- return null;
217
- const shaped = strictNode(child);
218
- if (!shaped)
219
- return null;
220
- shapedProperties[name] = shaped;
119
+ if (json.api_error_status === 401 || json.api_error_status === 403 || json.api_error_status === 429) {
120
+ return { kind: "failed", failure: { kind: "fatal", message } };
221
121
  }
222
- result.properties = shapedProperties;
223
- result.required = Object.keys(shapedProperties);
224
- result.additionalProperties = false;
122
+ return { kind: "failed", failure: classifyAgentFailure(message) };
225
123
  }
226
- if (schema.items !== void 0) {
227
- const shaped = strictNode(schema.items);
228
- if (!shaped)
229
- return null;
230
- result.items = shaped;
124
+ if (json.subtype !== "success") {
125
+ return {
126
+ kind: "failed",
127
+ failure: {
128
+ kind: "transient",
129
+ message: `did not finish successfully (${json.subtype ?? "no subtype"})`
130
+ }
131
+ };
231
132
  }
232
- if (schema.prefixItems !== void 0)
233
- return null;
234
- if (schema.anyOf !== void 0) {
235
- const variants = schema.anyOf.map(strictNode);
236
- if (variants.some((v) => v === null))
237
- return null;
238
- result.anyOf = variants;
133
+ const usage = json.usage ?? {};
134
+ const promptTokens = (usage.input_tokens ?? 0) + (usage.cache_creation_input_tokens ?? 0) + (usage.cache_read_input_tokens ?? 0);
135
+ const completionTokens = usage.output_tokens ?? 0;
136
+ const reported = {
137
+ usage: {
138
+ promptTokens,
139
+ completionTokens,
140
+ totalTokens: promptTokens + completionTokens,
141
+ ...usage.cache_read_input_tokens !== void 0 && { promptCacheReadTokens: usage.cache_read_input_tokens },
142
+ ...usage.cache_creation_input_tokens !== void 0 && {
143
+ promptCacheWriteTokens: usage.cache_creation_input_tokens
144
+ }
145
+ },
146
+ model: Object.keys(json.modelUsage ?? {})[0],
147
+ costUsdEstimate: json.total_cost_usd
148
+ };
149
+ if (request.enforcement.kind === "in-prompt") {
150
+ return { kind: "answered", answer: { kind: "text", text: json.result ?? "" }, ...reported };
239
151
  }
240
- for (const defsKey of ["$defs", "definitions"]) {
241
- if (schema[defsKey] !== void 0) {
242
- const defs = {};
243
- for (const [name, child] of Object.entries(schema[defsKey])) {
244
- const shaped = strictNode(child);
245
- if (!shaped)
246
- return null;
247
- defs[name] = shaped;
152
+ if (!json.structured_output) {
153
+ return {
154
+ kind: "failed",
155
+ failure: {
156
+ kind: "transient",
157
+ message: `returned no structured output. Reply: ${json.result ?? ""}`
248
158
  }
249
- result[defsKey] = defs;
250
- }
159
+ };
251
160
  }
252
- return result;
161
+ return {
162
+ kind: "answered",
163
+ answer: { kind: "structured", envelope: json.structured_output },
164
+ ...reported
165
+ };
166
+ },
167
+ loginStatusArgs: ["auth", "status"],
168
+ readLoginStatus(result) {
169
+ try {
170
+ const status = JSON.parse(result.stdout);
171
+ return { loggedIn: status.loggedIn === true, detail: status.authMethod };
172
+ } catch {
173
+ return { loggedIn: false, detail: stderrTail(result) || result.stdout.trim() };
174
+ }
175
+ },
176
+ sessionArgs(model, approval) {
177
+ return [
178
+ ...model === void 0 ? [] : ["--model", model],
179
+ ...approval === "auto" ? ["--permission-mode", "auto"] : []
180
+ ];
253
181
  }
254
- return strictJsonSchema;
255
- }
256
-
257
- var hasRequiredCodex;
258
- function requireCodex() {
259
- if (hasRequiredCodex) return codex;
260
- hasRequiredCodex = 1;
261
- Object.defineProperty(codex, "__esModule", { value: true });
262
- codex.codexAdapter = void 0;
263
- const strict_json_schema_1 = requireStrictJsonSchema();
264
- const failure_classification_1 = requireFailureClassification();
265
- const SCHEMA_FILE = "output-schema.json";
266
- const LAST_MESSAGE_FILE = "last-message.txt";
267
- codex.codexAdapter = {
268
- id: "codex",
269
- binaryName: "codex",
270
- apiKeyEnvVars: ["OPENAI_API_KEY", "CODEX_API_KEY"],
271
- // Codex's models have no equivalent among the aliases; set one with localAgent({ model }).
272
- modelAliases: {},
273
- // Codex accepts only OpenAI strict-mode schemas.
274
- nativeSchema(envelopeSchema) {
275
- return (0, strict_json_schema_1.toStrictSchema)(envelopeSchema);
276
- },
277
- buildInvocation(request, model) {
278
- const args = [
279
- "exec",
280
- "-",
281
- "--skip-git-repo-check",
282
- "--ephemeral",
283
- "--ignore-user-config",
284
- "--ignore-rules",
285
- "--sandbox",
286
- "read-only",
287
- "-c",
288
- "model_reasoning_effort=low",
289
- "--json",
290
- "-o",
291
- LAST_MESSAGE_FILE
292
- ];
293
- if (model !== void 0) {
294
- args.push("-m", model);
295
- }
296
- const files = [];
297
- if (request.enforcement.kind === "native") {
298
- args.push("--output-schema", SCHEMA_FILE);
299
- files.push({ name: SCHEMA_FILE, content: JSON.stringify(request.enforcement.schema) });
300
- }
301
- return { args, stdin: request.prompt, files, outputFiles: [LAST_MESSAGE_FILE] };
302
- },
303
- readResult(result, request) {
304
- const events = parseEvents(result.stdout);
305
- const failed = events.find((e) => e.type === "turn.failed" || e.type === "error");
306
- if (failed) {
307
- const message = failed.error?.message ?? failed.message ?? "unknown error";
308
- if (/invalid_json_schema/.test(message)) {
309
- return {
310
- kind: "failed",
311
- failure: { kind: "schema-rejected", message: `codex rejected the output schema: ${message}` }
312
- };
313
- }
314
- return { kind: "failed", failure: (0, failure_classification_1.classifyAgentFailure)("codex", message) };
315
- }
316
- const agentMessages = events.filter((e) => e.item?.type === "agent_message");
317
- const lastMessage = result.outputFiles[LAST_MESSAGE_FILE] ?? agentMessages[agentMessages.length - 1]?.item?.text;
318
- if (result.exitCode !== 0 || lastMessage === void 0) {
182
+ };
183
+
184
+ const SCHEMA_FILE = "output-schema.json";
185
+ const LAST_MESSAGE_FILE = "last-message.txt";
186
+ const codexAdapter = {
187
+ id: "codex",
188
+ binaryName: "codex",
189
+ apiKeyEnvVars: ["OPENAI_API_KEY", "CODEX_API_KEY"],
190
+ // Codex's models have no equivalent among the aliases; set one with localAgent({ model }).
191
+ modelAliases: {},
192
+ // Codex accepts only OpenAI strict-mode schemas.
193
+ nativeSchema(envelopeSchema) {
194
+ return strictJsonSchema.toStrictSchema(envelopeSchema);
195
+ },
196
+ buildInvocation(request, { model, effort }) {
197
+ const args = [
198
+ "exec",
199
+ "-",
200
+ "--skip-git-repo-check",
201
+ "--ephemeral",
202
+ "--ignore-user-config",
203
+ "--ignore-rules",
204
+ "--sandbox",
205
+ "read-only",
206
+ "--json",
207
+ "-o",
208
+ LAST_MESSAGE_FILE
209
+ ];
210
+ if (model !== void 0) {
211
+ args.push("-m", model);
212
+ }
213
+ if (effort !== void 0) {
214
+ args.push("-c", `model_reasoning_effort=${effort}`);
215
+ }
216
+ const files = [];
217
+ if (request.enforcement.kind === "native") {
218
+ args.push("--output-schema", SCHEMA_FILE);
219
+ files.push({ name: SCHEMA_FILE, content: JSON.stringify(request.enforcement.schema) });
220
+ }
221
+ return { args, stdin: request.prompt, files, outputFiles: [LAST_MESSAGE_FILE] };
222
+ },
223
+ readResult(result, request) {
224
+ const events = parseEvents$1(result.stdout);
225
+ const failed = events.find((e) => e.type === "turn.failed" || e.type === "error");
226
+ if (failed) {
227
+ const raw = failed.error?.message ?? failed.message ?? "unknown error";
228
+ const message = apiErrorMessage(raw);
229
+ if (/invalid_json_schema/.test(raw)) {
319
230
  return {
320
231
  kind: "failed",
321
- failure: (0, failure_classification_1.classifyAgentFailure)("codex", `exited with code ${result.exitCode} without a reply: ${(0, failure_classification_1.stderrTail)(result)}`)
232
+ failure: { kind: "schema-rejected", message: `rejected the output schema: ${message}` }
322
233
  };
323
234
  }
324
- const completed = events.filter((e) => e.type === "turn.completed");
325
- const promptTokens = completed.reduce((sum, e) => sum + (e.usage?.input_tokens ?? 0), 0);
326
- const completionTokens = completed.reduce((sum, e) => sum + (e.usage?.output_tokens ?? 0), 0);
327
- const reported = {
328
- usage: { promptTokens, completionTokens, totalTokens: promptTokens + completionTokens },
329
- // Codex does not report which model answered.
330
- model: void 0,
331
- costUsdEstimate: void 0
235
+ return { kind: "failed", failure: { ...classifyAgentFailure(raw), message } };
236
+ }
237
+ const agentMessages = events.filter((e) => e.item?.type === "agent_message");
238
+ const lastMessage = result.outputFiles[LAST_MESSAGE_FILE] ?? agentMessages[agentMessages.length - 1]?.item?.text;
239
+ if (result.exitCode !== 0 || lastMessage === void 0) {
240
+ return {
241
+ kind: "failed",
242
+ failure: classifyAgentFailure(
243
+ `exited with code ${result.exitCode} without a reply: ${stderrTail(result)}`
244
+ )
332
245
  };
333
- if (request.enforcement.kind === "in-prompt") {
334
- return { kind: "answered", answer: { kind: "text", text: lastMessage }, ...reported };
335
- }
336
- let envelope;
337
- try {
338
- envelope = JSON.parse(lastMessage);
339
- } catch {
340
- return {
341
- kind: "failed",
342
- failure: { kind: "transient", message: `codex reply is not JSON: ${lastMessage}` }
343
- };
344
- }
345
- return { kind: "answered", answer: { kind: "structured", envelope }, ...reported };
346
- },
347
- loginStatusArgs: ["login", "status"],
348
- readLoginStatus(result) {
349
- const detail = `${result.stdout}
350
- ${result.stderr}`.trim();
351
- return { loggedIn: result.exitCode === 0, detail };
352
246
  }
353
- };
354
- function parseEvents(stdout) {
355
- const events = [];
356
- for (const line of stdout.split("\n")) {
357
- const trimmed = line.trim();
358
- if (!trimmed.startsWith("{"))
359
- continue;
360
- try {
361
- events.push(JSON.parse(trimmed));
362
- } catch {
363
- }
247
+ const completed = events.filter((e) => e.type === "turn.completed");
248
+ const promptTokens = completed.reduce((sum, e) => sum + (e.usage?.input_tokens ?? 0), 0);
249
+ const completionTokens = completed.reduce((sum, e) => sum + (e.usage?.output_tokens ?? 0), 0);
250
+ const cacheReadReported = completed.some((e) => e.usage?.cached_input_tokens !== void 0);
251
+ const cacheReadTokens = completed.reduce((sum, e) => sum + (e.usage?.cached_input_tokens ?? 0), 0);
252
+ const reported = {
253
+ usage: {
254
+ promptTokens,
255
+ completionTokens,
256
+ totalTokens: promptTokens + completionTokens,
257
+ ...cacheReadReported && { promptCacheReadTokens: cacheReadTokens }
258
+ },
259
+ // Codex does not report which model answered.
260
+ model: void 0,
261
+ costUsdEstimate: void 0
262
+ };
263
+ if (request.enforcement.kind === "in-prompt") {
264
+ return { kind: "answered", answer: { kind: "text", text: lastMessage }, ...reported };
364
265
  }
365
- return events;
366
- }
367
- return codex;
368
- }
369
-
370
- var pi = {};
371
-
372
- var hasRequiredPi;
373
- function requirePi() {
374
- if (hasRequiredPi) return pi;
375
- hasRequiredPi = 1;
376
- Object.defineProperty(pi, "__esModule", { value: true });
377
- pi.piAdapter = void 0;
378
- const failure_classification_1 = requireFailureClassification();
379
- const SYSTEM_PROMPT = [
380
- "You are a data transformation function called by a program.",
381
- "You have no tools. Follow the instructions in the user message exactly",
382
- "and reply only with the requested JSON."
383
- ].join(" ");
384
- pi.piAdapter = {
385
- id: "pi",
386
- binaryName: "pi",
387
- // Every environment credential Pi's providers recognize. Under `auth:
388
- // "subscription"` these are removed so Pi bills its own `auth.json` login.
389
- apiKeyEnvVars: [
390
- "AI_GATEWAY_API_KEY",
391
- "ANT_LING_API_KEY",
392
- "ANTHROPIC_API_KEY",
393
- "ANTHROPIC_AUTH_TOKEN",
394
- "ANTHROPIC_OAUTH_TOKEN",
395
- "AWS_ACCESS_KEY_ID",
396
- "AWS_SECRET_ACCESS_KEY",
397
- "AWS_SESSION_TOKEN",
398
- "AZURE_OPENAI_API_KEY",
399
- "BASETEN_API_KEY",
400
- "CEREBRAS_API_KEY",
401
- "CLOUDFLARE_API_KEY",
402
- "COPILOT_GITHUB_TOKEN",
403
- "DEEPSEEK_API_KEY",
404
- "FIREWORKS_API_KEY",
405
- "GEMINI_API_KEY",
406
- "GOOGLE_API_KEY",
407
- "GOOGLE_CLOUD_API_KEY",
408
- "GROQ_API_KEY",
409
- "HF_TOKEN",
410
- "KIMI_API_KEY",
411
- "META_API_KEY",
412
- "MINIMAX_API_KEY",
413
- "MINIMAX_CN_API_KEY",
414
- "MISTRAL_API_KEY",
415
- "MOONSHOT_API_KEY",
416
- "NVIDIA_API_KEY",
417
- "OPENAI_API_KEY",
418
- "OPENCODE_API_KEY",
419
- "OPENROUTER_API_KEY",
420
- "QWEN_TOKEN_PLAN_API_KEY",
421
- "QWEN_TOKEN_PLAN_CN_API_KEY",
422
- "RADIUS_API_KEY",
423
- "TOGETHER_API_KEY",
424
- "XAI_API_KEY",
425
- "XIAOMI_API_KEY",
426
- "XIAOMI_TOKEN_PLAN_AMS_API_KEY",
427
- "XIAOMI_TOKEN_PLAN_CN_API_KEY",
428
- "XIAOMI_TOKEN_PLAN_SGP_API_KEY",
429
- "ZAI_API_KEY",
430
- "ZAI_CODING_CN_API_KEY"
431
- ],
432
- // Pi uses its own `provider/id` model names; set one with localAgent({ model }).
433
- modelAliases: {},
434
- nativeSchema() {
435
- return null;
436
- },
437
- buildInvocation(request, model) {
438
- const args = [
439
- "--mode",
440
- "json",
441
- "--no-session",
442
- "--no-tools",
443
- "--no-builtin-tools",
444
- "--no-extensions",
445
- "--no-skills",
446
- "--no-prompt-templates",
447
- "--no-themes",
448
- "--no-context-files",
449
- "--system-prompt",
450
- SYSTEM_PROMPT,
451
- "--offline"
452
- ];
453
- if (model !== void 0) {
454
- args.push("--model", model);
455
- }
456
- return { args, stdin: request.prompt };
457
- },
458
- readResult(result, request) {
459
- const events = parseEvents(result.stdout);
460
- const assistant = events.filter((event) => event.type === "message_end" && event.message?.role === "assistant").map((event) => event.message).pop();
461
- if (assistant && (assistant.stopReason === "error" || assistant.errorMessage)) {
462
- return failed((0, failure_classification_1.classifyAgentFailure)("pi", assistant.errorMessage ?? "pi stopped with an error"));
463
- }
464
- const retryFailed = events.find((event) => event.type === "auto_retry_end" && event.success === false);
465
- if (retryFailed) {
466
- return failed((0, failure_classification_1.classifyAgentFailure)("pi", retryFailed.finalError ?? "auto retry failed"));
467
- }
468
- if (!assistant) {
469
- return failed((0, failure_classification_1.classifyAgentFailure)("pi", `exited with code ${result.exitCode} without a reply: ${(0, failure_classification_1.stderrTail)(result)}`));
470
- }
471
- const text = (assistant.content ?? []).filter((block) => block.type === "text").map((block) => block.text ?? "").join("");
472
- const usage = assistant.usage ?? {};
473
- const promptTokens = (usage.input ?? 0) + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0);
474
- const completionTokens = usage.output ?? 0;
475
- const reported = {
476
- usage: { promptTokens, completionTokens, totalTokens: promptTokens + completionTokens },
477
- model: assistant.model,
478
- costUsdEstimate: usage.cost?.total
479
- };
480
- if (request.enforcement.kind === "in-prompt") {
481
- return { kind: "answered", answer: { kind: "text", text }, ...reported };
482
- }
483
- let envelope;
484
- try {
485
- envelope = JSON.parse(text);
486
- } catch {
487
- return failed({ kind: "transient", message: `pi reply is not JSON: ${text}` });
488
- }
489
- return { kind: "answered", answer: { kind: "structured", envelope }, ...reported };
490
- },
491
- // Pi has no provider-agnostic login check: `pi auth check` requires --provider
492
- // or --model, and the provider differs per user (it is not known until Pi's
493
- // settings are read). Report installed Pi as logged in; the first real call
494
- // surfaces any auth error, which classifyAgentFailure marks fatal.
495
- loginStatusArgs: ["--version"],
496
- readLoginStatus(result) {
266
+ let envelope;
267
+ try {
268
+ envelope = JSON.parse(lastMessage);
269
+ } catch {
497
270
  return {
498
- loggedIn: result.exitCode === 0,
499
- detail: "installed; auth is verified on the first call"
271
+ kind: "failed",
272
+ failure: { kind: "transient", message: `reply is not JSON: ${lastMessage}` }
500
273
  };
501
274
  }
502
- };
503
- function failed(failure) {
504
- return { kind: "failed", failure };
275
+ return { kind: "answered", answer: { kind: "structured", envelope }, ...reported };
276
+ },
277
+ loginStatusArgs: ["login", "status"],
278
+ readLoginStatus(result) {
279
+ const detail = `${result.stdout}
280
+ ${result.stderr}`.trim();
281
+ return { loggedIn: result.exitCode === 0, detail };
282
+ },
283
+ sessionArgs(model, approval) {
284
+ return [
285
+ ...model === void 0 ? [] : ["--model", model],
286
+ ...approval === "auto" ? ["--approve-for-me"] : []
287
+ ];
505
288
  }
506
- function parseEvents(stdout) {
507
- const events = [];
508
- for (const line of stdout.split("\n")) {
509
- const trimmed = line.replace(/\r$/, "").trim();
510
- if (!trimmed.startsWith("{"))
511
- continue;
512
- try {
513
- const parsed = JSON.parse(trimmed);
514
- if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
515
- events.push(parsed);
516
- }
517
- } catch {
518
- }
289
+ };
290
+ function parseEvents$1(stdout) {
291
+ const events = [];
292
+ for (const line of stdout.split("\n")) {
293
+ const trimmed = line.trim();
294
+ if (!trimmed.startsWith("{")) continue;
295
+ try {
296
+ events.push(JSON.parse(trimmed));
297
+ } catch {
519
298
  }
520
- return events;
521
299
  }
522
- return pi;
300
+ return events;
523
301
  }
524
-
525
- var hasRequiredAdapters;
526
- function requireAdapters() {
527
- if (hasRequiredAdapters) return adapters;
528
- hasRequiredAdapters = 1;
529
- Object.defineProperty(adapters, "__esModule", { value: true });
530
- adapters.AGENT_ADAPTERS = void 0;
531
- const claude_code_1 = requireClaudeCode();
532
- const codex_1 = requireCodex();
533
- const pi_1 = requirePi();
534
- adapters.AGENT_ADAPTERS = {
535
- "claude-code": claude_code_1.claudeCodeAdapter,
536
- codex: codex_1.codexAdapter,
537
- pi: pi_1.piAdapter
538
- };
539
- return adapters;
302
+ function apiErrorMessage(message) {
303
+ try {
304
+ const inner = JSON.parse(message)?.error?.message;
305
+ if (typeof inner === "string") return inner;
306
+ } catch {
307
+ }
308
+ return message;
540
309
  }
541
310
 
542
- var agentId = {};
543
-
544
- var hasRequiredAgentId;
545
- function requireAgentId() {
546
- if (hasRequiredAgentId) return agentId;
547
- hasRequiredAgentId = 1;
548
- (function(exports$1) {
549
- Object.defineProperty(exports$1, "__esModule", { value: true });
550
- exports$1.LOCAL_AGENT_IDS = void 0;
551
- exports$1.isLocalAgentId = isLocalAgentId;
552
- exports$1.LOCAL_AGENT_IDS = ["claude-code", "codex", "pi"];
553
- const LOCAL_AGENT_ID_SET = new Set(exports$1.LOCAL_AGENT_IDS);
554
- function isLocalAgentId(value) {
555
- return typeof value === "string" && LOCAL_AGENT_ID_SET.has(value);
311
+ const SYSTEM_PROMPT = [
312
+ "You are a data transformation function called by a program.",
313
+ "You have no tools. Follow the instructions in the user message exactly",
314
+ "and reply only with the requested JSON."
315
+ ].join(" ");
316
+ const piAdapter = {
317
+ id: "pi",
318
+ binaryName: "pi",
319
+ // Every environment credential Pi's providers recognize. Under `auth:
320
+ // "subscription"` these are removed so Pi bills its own `auth.json` login.
321
+ apiKeyEnvVars: [
322
+ "AI_GATEWAY_API_KEY",
323
+ "ANT_LING_API_KEY",
324
+ "ANTHROPIC_API_KEY",
325
+ "ANTHROPIC_AUTH_TOKEN",
326
+ "ANTHROPIC_OAUTH_TOKEN",
327
+ "AWS_ACCESS_KEY_ID",
328
+ "AWS_SECRET_ACCESS_KEY",
329
+ "AWS_SESSION_TOKEN",
330
+ "AZURE_OPENAI_API_KEY",
331
+ "BASETEN_API_KEY",
332
+ "CEREBRAS_API_KEY",
333
+ "CLOUDFLARE_API_KEY",
334
+ "COPILOT_GITHUB_TOKEN",
335
+ "DEEPSEEK_API_KEY",
336
+ "FIREWORKS_API_KEY",
337
+ "GEMINI_API_KEY",
338
+ "GOOGLE_API_KEY",
339
+ "GOOGLE_CLOUD_API_KEY",
340
+ "GROQ_API_KEY",
341
+ "HF_TOKEN",
342
+ "KIMI_API_KEY",
343
+ "META_API_KEY",
344
+ "MINIMAX_API_KEY",
345
+ "MINIMAX_CN_API_KEY",
346
+ "MISTRAL_API_KEY",
347
+ "MOONSHOT_API_KEY",
348
+ "NVIDIA_API_KEY",
349
+ "OPENAI_API_KEY",
350
+ "OPENCODE_API_KEY",
351
+ "OPENROUTER_API_KEY",
352
+ "QWEN_TOKEN_PLAN_API_KEY",
353
+ "QWEN_TOKEN_PLAN_CN_API_KEY",
354
+ "RADIUS_API_KEY",
355
+ "TOGETHER_API_KEY",
356
+ "XAI_API_KEY",
357
+ "XIAOMI_API_KEY",
358
+ "XIAOMI_TOKEN_PLAN_AMS_API_KEY",
359
+ "XIAOMI_TOKEN_PLAN_CN_API_KEY",
360
+ "XIAOMI_TOKEN_PLAN_SGP_API_KEY",
361
+ "ZAI_API_KEY",
362
+ "ZAI_CODING_CN_API_KEY"
363
+ ],
364
+ // Pi uses its own `provider/id` model names; set one with localAgent({ model }).
365
+ modelAliases: {},
366
+ nativeSchema() {
367
+ return null;
368
+ },
369
+ buildInvocation(request, { model, effort }) {
370
+ const args = [
371
+ "--mode",
372
+ "json",
373
+ "--no-session",
374
+ "--no-tools",
375
+ "--no-builtin-tools",
376
+ "--no-extensions",
377
+ "--no-skills",
378
+ "--no-prompt-templates",
379
+ "--no-themes",
380
+ "--no-context-files",
381
+ "--system-prompt",
382
+ SYSTEM_PROMPT,
383
+ "--offline"
384
+ ];
385
+ if (model !== void 0) {
386
+ args.push("--model", model);
387
+ }
388
+ if (effort !== void 0) {
389
+ args.push("--thinking", effort);
390
+ }
391
+ return { args, stdin: request.prompt };
392
+ },
393
+ readResult(result, request) {
394
+ const events = parseEvents(result.stdout);
395
+ const assistant = events.filter((event) => event.type === "message_end" && event.message?.role === "assistant").map((event) => event.message).pop();
396
+ if (assistant && (assistant.stopReason === "error" || assistant.errorMessage)) {
397
+ return failed(classifyAgentFailure(assistant.errorMessage ?? "stopped with an error"));
398
+ }
399
+ const retryFailed = events.find((event) => event.type === "auto_retry_end" && event.success === false);
400
+ if (retryFailed) {
401
+ return failed(classifyAgentFailure(retryFailed.finalError ?? "auto retry failed"));
402
+ }
403
+ if (!assistant) {
404
+ return failed(
405
+ classifyAgentFailure(
406
+ `exited with code ${result.exitCode} without a reply: ${stderrTail(result)}`
407
+ )
408
+ );
409
+ }
410
+ const text = (assistant.content ?? []).filter((block) => block.type === "text").map((block) => block.text ?? "").join("");
411
+ const usage = assistant.usage ?? {};
412
+ const promptTokens = (usage.input ?? 0) + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0);
413
+ const completionTokens = usage.output ?? 0;
414
+ const reported = {
415
+ usage: {
416
+ promptTokens,
417
+ completionTokens,
418
+ totalTokens: promptTokens + completionTokens,
419
+ ...usage.cacheRead !== void 0 && { promptCacheReadTokens: usage.cacheRead },
420
+ ...usage.cacheWrite !== void 0 && { promptCacheWriteTokens: usage.cacheWrite }
421
+ },
422
+ model: assistant.model,
423
+ costUsdEstimate: usage.cost?.total
424
+ };
425
+ if (request.enforcement.kind === "in-prompt") {
426
+ return { kind: "answered", answer: { kind: "text", text }, ...reported };
556
427
  }
557
- })(agentId);
558
- return agentId;
428
+ let envelope;
429
+ try {
430
+ envelope = JSON.parse(text);
431
+ } catch {
432
+ return failed({ kind: "transient", message: `reply is not JSON: ${text}` });
433
+ }
434
+ return { kind: "answered", answer: { kind: "structured", envelope }, ...reported };
435
+ },
436
+ // Pi has no provider-agnostic login check: `pi auth check` requires --provider
437
+ // or --model, and the provider differs per user (it is not known until Pi's
438
+ // settings are read). Report installed Pi as logged in; the first real call
439
+ // surfaces any auth error, which classifyAgentFailure marks fatal.
440
+ loginStatusArgs: ["--version"],
441
+ readLoginStatus(result) {
442
+ return {
443
+ loggedIn: result.exitCode === 0,
444
+ detail: "installed; auth is verified on the first call"
445
+ };
446
+ },
447
+ sessionArgs(model, approval) {
448
+ return [
449
+ ...model === void 0 ? [] : ["--model", model],
450
+ ...approval === "auto" ? ["--approve"] : []
451
+ ];
452
+ }
453
+ };
454
+ function failed(failure) {
455
+ return { kind: "failed", failure };
456
+ }
457
+ function parseEvents(stdout) {
458
+ const events = [];
459
+ for (const line of stdout.split("\n")) {
460
+ const trimmed = line.replace(/\r$/, "").trim();
461
+ if (!trimmed.startsWith("{")) continue;
462
+ try {
463
+ const parsed = JSON.parse(trimmed);
464
+ if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
465
+ events.push(parsed);
466
+ }
467
+ } catch {
468
+ }
469
+ }
470
+ return events;
559
471
  }
560
472
 
561
- var detect = {};
562
-
563
- var processRunner = {};
564
-
565
- const require$4 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('local-agent.cjs', document.baseURI).href)));
566
- function __require$3() { return require$4("node:child_process"); }
567
-
568
- const require$3 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('local-agent.cjs', document.baseURI).href)));
569
- function __require$2() { return require$3("node:fs"); }
570
-
571
- const require$2 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('local-agent.cjs', document.baseURI).href)));
572
- function __require$1() { return require$2("node:os"); }
473
+ const AGENT_ADAPTERS = {
474
+ "claude-code": claudeCodeAdapter,
475
+ codex: codexAdapter,
476
+ pi: piAdapter
477
+ };
573
478
 
574
- const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('local-agent.cjs', document.baseURI).href)));
575
- function __require() { return require$1("node:path"); }
479
+ const LOCAL_AGENT_IDS = ["claude-code", "codex", "pi"];
480
+ const LOCAL_AGENT_ID_SET = new Set(LOCAL_AGENT_IDS);
481
+ function isLocalAgentId(value) {
482
+ return typeof value === "string" && LOCAL_AGENT_ID_SET.has(value);
483
+ }
576
484
 
577
- var hasRequiredProcessRunner;
578
- function requireProcessRunner() {
579
- if (hasRequiredProcessRunner) return processRunner;
580
- hasRequiredProcessRunner = 1;
581
- var __createBinding = processRunner && processRunner.__createBinding || (Object.create ? (function(o, m, k, k2) {
582
- if (k2 === void 0) k2 = k;
583
- var desc = Object.getOwnPropertyDescriptor(m, k);
584
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
585
- desc = { enumerable: true, get: function() {
586
- return m[k];
587
- } };
485
+ const KILL_GRACE_MS = 2e3;
486
+ async function runInvocation(options) {
487
+ const workDir = fs__namespace.mkdtempSync(path__namespace.join(os__namespace.tmpdir(), "nua-local-agent-"));
488
+ try {
489
+ for (const file of options.invocation.files ?? []) {
490
+ fs__namespace.writeFileSync(path__namespace.join(workDir, file.name), file.content);
588
491
  }
589
- Object.defineProperty(o, k2, desc);
590
- }) : (function(o, m, k, k2) {
591
- if (k2 === void 0) k2 = k;
592
- o[k2] = m[k];
593
- }));
594
- var __setModuleDefault = processRunner && processRunner.__setModuleDefault || (Object.create ? (function(o, v) {
595
- Object.defineProperty(o, "default", { enumerable: true, value: v });
596
- }) : function(o, v) {
597
- o["default"] = v;
598
- });
599
- var __importStar = processRunner && processRunner.__importStar || /* @__PURE__ */ (function() {
600
- var ownKeys = function(o) {
601
- ownKeys = Object.getOwnPropertyNames || function(o2) {
602
- var ar = [];
603
- for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
604
- return ar;
605
- };
606
- return ownKeys(o);
607
- };
608
- return function(mod) {
609
- if (mod && mod.__esModule) return mod;
610
- var result = {};
611
- if (mod != null) {
612
- for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
613
- }
614
- __setModuleDefault(result, mod);
615
- return result;
616
- };
617
- })();
618
- Object.defineProperty(processRunner, "__esModule", { value: true });
619
- processRunner.runInvocation = runInvocation;
620
- processRunner.findOnPath = findOnPath;
621
- const node_child_process_1 = __require$3();
622
- const fs = __importStar(__require$2());
623
- const os = __importStar(__require$1());
624
- const path = __importStar(__require());
625
- const KILL_GRACE_MS = 2e3;
626
- async function runInvocation(options) {
627
- const workDir = fs.mkdtempSync(path.join(os.tmpdir(), "nua-local-agent-"));
628
- try {
629
- for (const file of options.invocation.files ?? []) {
630
- fs.writeFileSync(path.join(workDir, file.name), file.content);
631
- }
632
- const result = await spawnAndCollect(options, workDir);
633
- for (const name of options.invocation.outputFiles ?? []) {
634
- const filePath = path.join(workDir, name);
635
- result.outputFiles[name] = fs.existsSync(filePath) ? fs.readFileSync(filePath, "utf8") : void 0;
636
- }
637
- return result;
638
- } finally {
639
- fs.rmSync(workDir, { recursive: true, force: true });
492
+ const result = await spawnAndCollect(options, workDir);
493
+ for (const name of options.invocation.outputFiles ?? []) {
494
+ const filePath = path__namespace.join(workDir, name);
495
+ result.outputFiles[name] = fs__namespace.existsSync(filePath) ? fs__namespace.readFileSync(filePath, "utf8") : void 0;
640
496
  }
497
+ return result;
498
+ } finally {
499
+ fs__namespace.rmSync(workDir, { recursive: true, force: true });
641
500
  }
642
- function spawnAndCollect(options, cwd) {
643
- const env = { ...process.env };
644
- for (const name of options.unsetEnv ?? []) {
645
- delete env[name];
646
- }
647
- return new Promise((resolve, reject) => {
648
- const child = (0, node_child_process_1.spawn)(options.binaryPath, options.invocation.args, {
649
- cwd,
650
- env,
651
- stdio: ["pipe", "pipe", "pipe"],
652
- windowsHide: true
653
- });
654
- const stdout = [];
655
- const stderr = [];
656
- let timedOut = false;
657
- let killTimer;
658
- const timeoutTimer = setTimeout(() => {
659
- timedOut = true;
660
- child.kill("SIGINT");
661
- killTimer = setTimeout(() => child.kill("SIGKILL"), KILL_GRACE_MS);
662
- }, options.timeoutMs);
663
- child.stdout.on("data", (chunk) => stdout.push(chunk));
664
- child.stderr.on("data", (chunk) => stderr.push(chunk));
665
- child.on("error", (error) => {
666
- clearTimeout(timeoutTimer);
667
- clearTimeout(killTimer);
668
- const reason = error.code === "ENOENT" ? "not found" : error.message;
669
- reject(new Error(`Could not start ${options.binaryPath}: ${reason}`));
670
- });
671
- child.on("close", (exitCode) => {
672
- clearTimeout(timeoutTimer);
673
- clearTimeout(killTimer);
674
- resolve({
675
- exitCode,
676
- stdout: Buffer.concat(stdout).toString("utf8"),
677
- stderr: Buffer.concat(stderr).toString("utf8"),
678
- timedOut,
679
- outputFiles: {}
680
- });
501
+ }
502
+ function spawnAndCollect(options, cwd) {
503
+ const env = { ...process.env };
504
+ for (const name of options.unsetEnv ?? []) {
505
+ delete env[name];
506
+ }
507
+ return new Promise((resolve, reject) => {
508
+ const child = node_child_process.spawn(options.binaryPath, options.invocation.args, {
509
+ cwd,
510
+ env,
511
+ stdio: ["pipe", "pipe", "pipe"],
512
+ windowsHide: true
513
+ });
514
+ const stdout = [];
515
+ const stderr = [];
516
+ let timedOut = false;
517
+ let killTimer;
518
+ const timeoutTimer = setTimeout(() => {
519
+ timedOut = true;
520
+ child.kill("SIGINT");
521
+ killTimer = setTimeout(() => child.kill("SIGKILL"), KILL_GRACE_MS);
522
+ }, options.timeoutMs);
523
+ child.stdout.on("data", (chunk) => stdout.push(chunk));
524
+ child.stderr.on("data", (chunk) => stderr.push(chunk));
525
+ child.on("error", (error) => {
526
+ clearTimeout(timeoutTimer);
527
+ clearTimeout(killTimer);
528
+ const reason = error.code === "ENOENT" ? "not found" : error.message;
529
+ reject(new Error(`Could not start ${options.binaryPath}: ${reason}`));
530
+ });
531
+ child.on("close", (exitCode) => {
532
+ clearTimeout(timeoutTimer);
533
+ clearTimeout(killTimer);
534
+ resolve({
535
+ exitCode,
536
+ stdout: Buffer.concat(stdout).toString("utf8"),
537
+ stderr: Buffer.concat(stderr).toString("utf8"),
538
+ timedOut,
539
+ outputFiles: {}
681
540
  });
682
- child.stdin.on("error", () => void 0);
683
- child.stdin.end(options.invocation.stdin);
684
541
  });
542
+ child.stdin.on("error", () => void 0);
543
+ child.stdin.end(options.invocation.stdin);
544
+ });
545
+ }
546
+ function findOnPath(binaryName) {
547
+ const isWindows = process.platform === "win32";
548
+ const extensions = isWindows ? (process.env.PATHEXT ?? ".EXE;.CMD;.BAT").split(";").filter(Boolean) : [""];
549
+ if (isWindows) {
550
+ extensions.sort((a, b) => Number(b.toUpperCase() === ".EXE") - Number(a.toUpperCase() === ".EXE"));
685
551
  }
686
- function findOnPath(binaryName) {
687
- const isWindows = process.platform === "win32";
688
- const extensions = isWindows ? (process.env.PATHEXT ?? ".EXE;.CMD;.BAT").split(";").filter(Boolean) : [""];
689
- if (isWindows) {
690
- extensions.sort((a, b) => Number(b.toUpperCase() === ".EXE") - Number(a.toUpperCase() === ".EXE"));
691
- }
692
- for (const dir of (process.env.PATH ?? "").split(path.delimiter)) {
693
- if (!dir)
694
- continue;
695
- for (const ext of extensions) {
696
- const candidate = path.join(dir, binaryName + ext);
697
- try {
698
- if (fs.statSync(candidate).isFile()) {
699
- if (!isWindows)
700
- fs.accessSync(candidate, fs.constants.X_OK);
701
- return candidate;
702
- }
703
- } catch {
552
+ for (const dir of (process.env.PATH ?? "").split(path__namespace.delimiter)) {
553
+ if (!dir) continue;
554
+ for (const ext of extensions) {
555
+ const candidate = path__namespace.join(dir, binaryName + ext);
556
+ try {
557
+ if (fs__namespace.statSync(candidate).isFile()) {
558
+ if (!isWindows) fs__namespace.accessSync(candidate, fs__namespace.constants.X_OK);
559
+ return candidate;
704
560
  }
561
+ } catch {
705
562
  }
706
563
  }
707
- return null;
708
564
  }
709
- return processRunner;
565
+ return null;
710
566
  }
711
567
 
712
- var hasRequiredDetect;
713
- function requireDetect() {
714
- if (hasRequiredDetect) return detect;
715
- hasRequiredDetect = 1;
716
- Object.defineProperty(detect, "__esModule", { value: true });
717
- detect.detectLocalAgents = detectLocalAgents;
718
- const adapters_1 = requireAdapters();
719
- const agent_id_1 = requireAgentId();
720
- const process_runner_1 = requireProcessRunner();
721
- const STATUS_TIMEOUT_MS = 2e4;
722
- async function detectLocalAgents(binaryPaths = {}) {
723
- return Promise.all(agent_id_1.LOCAL_AGENT_IDS.map((id) => detectAgent(adapters_1.AGENT_ADAPTERS[id], binaryPaths[id])));
568
+ const STATUS_TIMEOUT_MS = 2e4;
569
+ async function detectLocalAgents(binaryPaths = {}) {
570
+ return Promise.all(
571
+ LOCAL_AGENT_IDS.map((id) => detectAgent(AGENT_ADAPTERS[id], binaryPaths[id]))
572
+ );
573
+ }
574
+ async function detectAgent(adapter, binaryPathOverride) {
575
+ const binaryPath = binaryPathOverride ?? findOnPath(adapter.binaryName);
576
+ if (!binaryPath) {
577
+ return { agent: adapter.id, installed: false, loggedIn: false };
724
578
  }
725
- async function detectAgent(adapter, binaryPathOverride) {
726
- const binaryPath = binaryPathOverride ?? (0, process_runner_1.findOnPath)(adapter.binaryName);
727
- if (!binaryPath) {
728
- return { agent: adapter.id, installed: false, loggedIn: false };
729
- }
730
- try {
731
- const [versionResult, statusResult] = await Promise.all([
732
- (0, process_runner_1.runInvocation)({
733
- binaryPath,
734
- invocation: { args: ["--version"], stdin: "" },
735
- timeoutMs: STATUS_TIMEOUT_MS
736
- }),
737
- (0, process_runner_1.runInvocation)({
738
- binaryPath,
739
- invocation: { args: adapter.loginStatusArgs, stdin: "" },
740
- timeoutMs: STATUS_TIMEOUT_MS,
741
- // Report the CLI's own login, not an API key that happens to be set.
742
- unsetEnv: adapter.apiKeyEnvVars
743
- })
744
- ]);
745
- if (versionResult.exitCode !== 0) {
746
- return {
747
- agent: adapter.id,
748
- installed: false,
749
- loggedIn: false,
750
- detail: `${binaryPath} --version exited with code ${versionResult.exitCode}`
751
- };
752
- }
753
- const login = adapter.readLoginStatus(statusResult);
754
- return {
755
- agent: adapter.id,
756
- installed: true,
757
- loggedIn: login.loggedIn,
579
+ try {
580
+ const [versionResult, statusResult] = await Promise.all([
581
+ runInvocation({
758
582
  binaryPath,
759
- version: versionResult.stdout.trim() || void 0,
760
- detail: login.detail
761
- };
762
- } catch (error) {
583
+ invocation: { args: ["--version"], stdin: "" },
584
+ timeoutMs: STATUS_TIMEOUT_MS
585
+ }),
586
+ runInvocation({
587
+ binaryPath,
588
+ invocation: { args: adapter.loginStatusArgs, stdin: "" },
589
+ timeoutMs: STATUS_TIMEOUT_MS,
590
+ // Report the CLI's own login, not an API key that happens to be set.
591
+ unsetEnv: adapter.apiKeyEnvVars
592
+ })
593
+ ]);
594
+ if (versionResult.exitCode !== 0) {
763
595
  return {
764
596
  agent: adapter.id,
765
597
  installed: false,
766
598
  loggedIn: false,
767
- detail: error instanceof Error ? error.message : String(error)
599
+ detail: `${binaryPath} --version exited with code ${versionResult.exitCode}`
768
600
  };
769
601
  }
602
+ const login = adapter.readLoginStatus(statusResult);
603
+ return {
604
+ agent: adapter.id,
605
+ installed: true,
606
+ loggedIn: login.loggedIn,
607
+ binaryPath,
608
+ version: versionResult.stdout.trim() || void 0,
609
+ detail: login.detail
610
+ };
611
+ } catch (error) {
612
+ return {
613
+ agent: adapter.id,
614
+ installed: false,
615
+ loggedIn: false,
616
+ detail: error instanceof Error ? error.message : String(error)
617
+ };
770
618
  }
771
- return detect;
772
619
  }
773
620
 
774
- var localAgent = {};
775
-
776
- var localAgentEngine = {};
777
-
778
- var hasRequiredLocalAgentEngine;
779
- function requireLocalAgentEngine() {
780
- if (hasRequiredLocalAgentEngine) return localAgentEngine;
781
- hasRequiredLocalAgentEngine = 1;
782
- Object.defineProperty(localAgentEngine, "__esModule", { value: true });
783
- localAgentEngine.LocalAgentEngine = void 0;
784
- const logger_1 = logger.requireLogger();
785
- const process_runner_1 = requireProcessRunner();
786
- class LocalAgentEngine {
787
- constructor(runner, model) {
788
- this.runner = runner;
789
- this.model = model;
790
- }
791
- nativeSchema(envelopeSchema) {
792
- return this.runner.adapter.nativeSchema(envelopeSchema);
793
- }
794
- attempt(request) {
795
- return this.runner.limiter.run(() => this.runAgent(request));
796
- }
797
- async runAgent(request) {
798
- const { adapter, binaryPath, logger, timeoutMs, unsetEnv } = this.runner;
799
- const spanId = (0, logger_1.generateSpanId)();
800
- const startTime = Date.now();
801
- const method = request.enforcement.kind;
802
- logger.info("LLM call started", {
803
- type: "llm_call_start",
804
- span_id: spanId,
805
- service: adapter.id,
806
- method,
621
+ class LocalAgentEngine {
622
+ constructor(runner, call) {
623
+ this.runner = runner;
624
+ this.call = call;
625
+ }
626
+ nativeSchema(envelopeSchema) {
627
+ return this.runner.adapter.nativeSchema(envelopeSchema);
628
+ }
629
+ attempt(request) {
630
+ return this.runner.limiter.run(() => this.runAgent(request));
631
+ }
632
+ async runAgent(request) {
633
+ const { adapter, binaryPath, logger, unsetEnv } = this.runner;
634
+ const { model, effort, timeoutMs } = this.call;
635
+ const spanId = strictJsonSchema.generateSpanId();
636
+ const startTime = Date.now();
637
+ const method = request.enforcement.kind;
638
+ logger.info("LLM call started", {
639
+ type: "llm_call_start",
640
+ span_id: spanId,
641
+ service: adapter.id,
642
+ method,
643
+ binaryPath,
644
+ model: model ?? "default"
645
+ });
646
+ const failed = (failure) => {
647
+ strictJsonSchema.logLlmCallError(logger, spanId, adapter.id, method, failure.message, Date.now() - startTime);
648
+ return { kind: "failed", failure };
649
+ };
650
+ let result;
651
+ try {
652
+ result = await runInvocation({
807
653
  binaryPath,
808
- model: this.model ?? "default"
654
+ invocation: adapter.buildInvocation(request, { model, effort }),
655
+ timeoutMs,
656
+ unsetEnv
809
657
  });
810
- const failed = (failure) => {
811
- (0, logger_1.logLlmCallError)(logger, spanId, adapter.id, method, failure.message, Date.now() - startTime);
812
- return { kind: "failed", failure };
813
- };
814
- let result;
815
- try {
816
- result = await (0, process_runner_1.runInvocation)({
817
- binaryPath,
818
- invocation: adapter.buildInvocation(request, this.model),
819
- timeoutMs,
820
- unsetEnv
821
- });
822
- } catch (error) {
823
- return failed({ kind: "fatal", message: error instanceof Error ? error.message : String(error) });
824
- }
825
- if (result.timedOut) {
826
- return failed({ kind: "fatal", message: `${adapter.id} did not finish within ${timeoutMs}ms` });
827
- }
828
- const reply = adapter.readResult(result, request);
829
- if (reply.kind === "failed") {
830
- return failed(reply.failure);
658
+ } catch (error) {
659
+ return failed({ kind: "fatal", message: error instanceof Error ? error.message : String(error) });
660
+ }
661
+ if (result.timedOut) {
662
+ return failed({ kind: "fatal", message: `did not finish within ${timeoutMs}ms` });
663
+ }
664
+ const reply = adapter.readResult(result, request);
665
+ if (reply.kind === "failed") {
666
+ return failed(reply.failure);
667
+ }
668
+ logger.info("LLM call completed", {
669
+ type: "llm_call_complete",
670
+ span_id: spanId,
671
+ service: adapter.id,
672
+ method,
673
+ exitCode: result.exitCode,
674
+ usage: reply.usage,
675
+ duration_ms: Date.now() - startTime
676
+ });
677
+ return {
678
+ kind: "answered",
679
+ answer: reply.answer,
680
+ usage: reply.usage,
681
+ origin: {
682
+ engine: "local-agent",
683
+ agent: adapter.id,
684
+ model: reply.model ?? model,
685
+ costUsdEstimate: reply.costUsdEstimate
831
686
  }
832
- logger.info("LLM call completed", {
833
- type: "llm_call_complete",
834
- span_id: spanId,
835
- service: adapter.id,
836
- method,
837
- exitCode: result.exitCode,
838
- usage: reply.usage,
839
- duration_ms: Date.now() - startTime
840
- });
841
- return {
842
- kind: "answered",
843
- answer: reply.answer,
844
- usage: reply.usage,
845
- origin: {
846
- engine: "local-agent",
847
- agent: adapter.id,
848
- model: reply.model ?? this.model,
849
- costUsdEstimate: reply.costUsdEstimate
850
- }
851
- };
852
- }
687
+ };
853
688
  }
854
- localAgentEngine.LocalAgentEngine = LocalAgentEngine;
855
- return localAgentEngine;
856
689
  }
857
690
 
858
- var hasRequiredLocalAgent$1;
859
- function requireLocalAgent$1() {
860
- if (hasRequiredLocalAgent$1) return localAgent;
861
- hasRequiredLocalAgent$1 = 1;
862
- Object.defineProperty(localAgent, "__esModule", { value: true });
863
- localAgent.LocalAgent = void 0;
864
- const local_agent_engine_1 = requireLocalAgentEngine();
865
- class LocalAgent {
866
- constructor(runner, defaultModel) {
867
- this.runner = runner;
868
- this.defaultModel = defaultModel;
869
- this.agent = runner.adapter.id;
870
- this.logger = runner.logger;
691
+ class LocalAgent {
692
+ constructor(runner, call) {
693
+ this.runner = runner;
694
+ this.call = call;
695
+ this.agent = runner.adapter.id;
696
+ this.logger = runner.logger;
697
+ }
698
+ /**
699
+ * The same agent with other call options, sharing this one's executable,
700
+ * environment, logger and limit on processes running at once. Options left
701
+ * out keep this agent's; a model or effort given as undefined is the CLI's
702
+ * default.
703
+ */
704
+ with(options) {
705
+ if (options.model !== void 0 && options.model.trim() === "") {
706
+ throw new TypeError("model must be a non-empty string; pass undefined to use the agent's default model");
871
707
  }
872
- /**
873
- * No model choice runs the default model. An alias runs the CLI's equivalent
874
- * model, if it has one. Provider models cannot run on a local agent.
875
- */
876
- route(model) {
877
- if (model === void 0) {
878
- return this.routeTo(this.defaultModel);
879
- }
880
- if (!("alias" in model)) {
881
- return {
882
- kind: "unroutable",
883
- message: `${this.agent} takes model aliases, not provider models. Set the agent's own model with localAgent({ model }).`
884
- };
885
- }
886
- const agentModel = this.runner.adapter.modelAliases[model.alias];
887
- if (agentModel === void 0) {
888
- return { kind: "unroutable", message: `Model alias "${model.alias}" has no ${this.agent} equivalent` };
889
- }
890
- return this.routeTo(agentModel);
708
+ return new LocalAgent(this.runner, {
709
+ ...this.call,
710
+ ...options,
711
+ timeoutMs: options.timeoutMs ?? this.call.timeoutMs
712
+ });
713
+ }
714
+ /**
715
+ * No model choice runs the default model. An alias runs the CLI's equivalent
716
+ * model, if it has one. Provider models cannot run on a local agent.
717
+ */
718
+ route(model) {
719
+ if (model === void 0) {
720
+ return this.routeTo(this.call);
721
+ }
722
+ if (!("alias" in model)) {
723
+ return {
724
+ kind: "unroutable",
725
+ message: `${this.agent} takes model aliases, not provider models. Set the agent's own model with localAgent({ model }) or with().`
726
+ };
891
727
  }
892
- routeTo(model) {
893
- return { kind: "routed", engine: new local_agent_engine_1.LocalAgentEngine(this.runner, model) };
728
+ const agentModel = this.runner.adapter.modelAliases[model.alias];
729
+ if (agentModel === void 0) {
730
+ return { kind: "unroutable", message: `Model alias "${model.alias}" has no ${this.agent} equivalent` };
894
731
  }
732
+ return this.routeTo({ ...this.call, model: agentModel });
733
+ }
734
+ routeTo(call) {
735
+ return { kind: "routed", engine: new LocalAgentEngine(this.runner, call) };
895
736
  }
896
- localAgent.LocalAgent = LocalAgent;
897
- return localAgent;
898
737
  }
899
738
 
900
- var semaphore = {};
901
-
902
- var hasRequiredSemaphore;
903
- function requireSemaphore() {
904
- if (hasRequiredSemaphore) return semaphore;
905
- hasRequiredSemaphore = 1;
906
- Object.defineProperty(semaphore, "__esModule", { value: true });
907
- semaphore.Semaphore = void 0;
908
- class Semaphore {
909
- constructor(limit) {
910
- this.limit = limit;
911
- this.active = 0;
912
- this.waiting = [];
739
+ class Semaphore {
740
+ constructor(limit) {
741
+ this.limit = limit;
742
+ this.active = 0;
743
+ this.waiting = [];
744
+ }
745
+ async run(task) {
746
+ if (this.active >= this.limit) {
747
+ await new Promise((resolve) => this.waiting.push(resolve));
748
+ } else {
749
+ this.active++;
913
750
  }
914
- async run(task) {
915
- if (this.active >= this.limit) {
916
- await new Promise((resolve) => this.waiting.push(resolve));
751
+ try {
752
+ return await task();
753
+ } finally {
754
+ const next = this.waiting.shift();
755
+ if (next) {
756
+ next();
917
757
  } else {
918
- this.active++;
919
- }
920
- try {
921
- return await task();
922
- } finally {
923
- const next = this.waiting.shift();
924
- if (next) {
925
- next();
926
- } else {
927
- this.active--;
928
- }
758
+ this.active--;
929
759
  }
930
760
  }
931
761
  }
932
- semaphore.Semaphore = Semaphore;
933
- return semaphore;
934
762
  }
935
763
 
936
- var hasRequiredCreateLocalAgent;
937
- function requireCreateLocalAgent() {
938
- if (hasRequiredCreateLocalAgent) return createLocalAgent;
939
- hasRequiredCreateLocalAgent = 1;
940
- Object.defineProperty(createLocalAgent, "__esModule", { value: true });
941
- createLocalAgent.localAgent = localAgent;
942
- createLocalAgent.findLocalAgent = findLocalAgent;
943
- const logger_1 = logger.requireLogger();
944
- const adapters_1 = requireAdapters();
945
- const agent_id_1 = requireAgentId();
946
- const detect_1 = requireDetect();
947
- const local_agent_1 = requireLocalAgent$1();
948
- const process_runner_1 = requireProcessRunner();
949
- const semaphore_1 = requireSemaphore();
950
- const DEFAULT_TIMEOUT_MS = 18e4;
951
- const DEFAULT_CONCURRENCY = 2;
952
- function localAgent(config) {
953
- if (!(0, agent_id_1.isLocalAgentId)(config.agent)) {
954
- throw new TypeError(`Unknown local agent: ${String(config.agent)}`);
955
- }
956
- const settings = parseOptions(config);
957
- const adapter = adapters_1.AGENT_ADAPTERS[config.agent];
958
- const binaryPath = config.binaryPath ?? (0, process_runner_1.findOnPath)(adapter.binaryName);
959
- if (!binaryPath) {
960
- throw new Error(`${adapter.binaryName} was not found on PATH. Install ${config.agent} or set binaryPath.`);
961
- }
962
- return setUpLocalAgent(adapter, binaryPath, settings);
764
+ const DEFAULT_TIMEOUT_MS = 18e4;
765
+ const DEFAULT_CONCURRENCY = 2;
766
+ function localAgent(config) {
767
+ if (!isLocalAgentId(config.agent)) {
768
+ throw new TypeError(`Unknown local agent: ${String(config.agent)}`);
963
769
  }
964
- async function findLocalAgent(options = {}) {
965
- const settings = parseOptions(options);
966
- const statuses = await (0, detect_1.detectLocalAgents)();
967
- for (const status of statuses) {
968
- if (status.installed && status.loggedIn) {
969
- return setUpLocalAgent(adapters_1.AGENT_ADAPTERS[status.agent], status.binaryPath, settings);
970
- }
971
- }
972
- const summary = statuses.map((s) => `${s.agent}: ${s.installed ? "not logged in" : "not installed"}`).join(", ");
973
- throw new Error(`No logged-in coding agent found (${summary})`);
770
+ const settings = parseOptions(config);
771
+ const adapter = AGENT_ADAPTERS[config.agent];
772
+ const binaryPath = config.binaryPath ?? findOnPath(adapter.binaryName);
773
+ if (!binaryPath) {
774
+ throw new Error(`${adapter.binaryName} was not found on PATH. Install ${config.agent} or set binaryPath.`);
974
775
  }
975
- function parseOptions(options) {
976
- const concurrency = options.concurrency ?? DEFAULT_CONCURRENCY;
977
- if (!Number.isInteger(concurrency) || concurrency < 1) {
978
- throw new TypeError("concurrency must be a positive integer");
979
- }
980
- if (options.model !== void 0 && options.model.trim() === "") {
981
- throw new TypeError("model must be a non-empty string; omit it to use the agent's default model");
776
+ return setUpLocalAgent(adapter, binaryPath, settings);
777
+ }
778
+ async function findLocalAgent(options = {}) {
779
+ const settings = parseOptions(options);
780
+ const statuses = await detectLocalAgents();
781
+ for (const status of statuses) {
782
+ if (status.installed && status.loggedIn) {
783
+ return setUpLocalAgent(AGENT_ADAPTERS[status.agent], status.binaryPath, settings);
982
784
  }
983
- return {
984
- model: options.model,
985
- timeoutMs: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,
986
- concurrency,
987
- auth: options.auth ?? "subscription",
988
- logger: options.logger ?? new logger_1.ConsoleLogger()
989
- };
990
785
  }
991
- function setUpLocalAgent(adapter, binaryPath, settings) {
992
- if (/\.(cmd|bat)$/i.test(binaryPath)) {
993
- throw new Error(`${binaryPath} is a .cmd shim, which local agents cannot run safely. Set binaryPath to the agent's native executable.`);
994
- }
995
- const runner = {
996
- adapter,
997
- binaryPath,
998
- timeoutMs: settings.timeoutMs,
999
- unsetEnv: settings.auth === "subscription" ? adapter.apiKeyEnvVars : [],
1000
- limiter: new semaphore_1.Semaphore(settings.concurrency),
1001
- logger: settings.logger
1002
- };
1003
- return new local_agent_1.LocalAgent(runner, settings.model);
786
+ const summary = statuses.map((s) => `${s.agent}: ${s.installed ? "not logged in" : "not installed"}`).join(", ");
787
+ throw new Error(`No logged-in coding agent found (${summary})`);
788
+ }
789
+ function parseOptions(options) {
790
+ const concurrency = options.concurrency ?? DEFAULT_CONCURRENCY;
791
+ if (!Number.isInteger(concurrency) || concurrency < 1) {
792
+ throw new TypeError("concurrency must be a positive integer");
1004
793
  }
1005
- return createLocalAgent;
794
+ if (options.model !== void 0 && options.model.trim() === "") {
795
+ throw new TypeError("model must be a non-empty string; omit it to use the agent's default model");
796
+ }
797
+ return {
798
+ model: options.model,
799
+ effort: options.effort,
800
+ timeoutMs: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,
801
+ concurrency,
802
+ auth: options.auth ?? "subscription",
803
+ logger: options.logger ?? new strictJsonSchema.ConsoleLogger()
804
+ };
1006
805
  }
1007
-
1008
- var hasRequiredLocalAgent;
1009
- function requireLocalAgent() {
1010
- if (hasRequiredLocalAgent) return localAgent$1;
1011
- hasRequiredLocalAgent = 1;
1012
- (function(exports$1) {
1013
- Object.defineProperty(exports$1, "__esModule", { value: true });
1014
- exports$1.isLocalAgentId = exports$1.LOCAL_AGENT_IDS = exports$1.detectLocalAgents = exports$1.localAgent = exports$1.findLocalAgent = void 0;
1015
- var create_local_agent_1 = requireCreateLocalAgent();
1016
- Object.defineProperty(exports$1, "findLocalAgent", { enumerable: true, get: function() {
1017
- return create_local_agent_1.findLocalAgent;
1018
- } });
1019
- Object.defineProperty(exports$1, "localAgent", { enumerable: true, get: function() {
1020
- return create_local_agent_1.localAgent;
1021
- } });
1022
- var detect_1 = requireDetect();
1023
- Object.defineProperty(exports$1, "detectLocalAgents", { enumerable: true, get: function() {
1024
- return detect_1.detectLocalAgents;
1025
- } });
1026
- var agent_id_1 = requireAgentId();
1027
- Object.defineProperty(exports$1, "LOCAL_AGENT_IDS", { enumerable: true, get: function() {
1028
- return agent_id_1.LOCAL_AGENT_IDS;
1029
- } });
1030
- Object.defineProperty(exports$1, "isLocalAgentId", { enumerable: true, get: function() {
1031
- return agent_id_1.isLocalAgentId;
1032
- } });
1033
- })(localAgent$1);
1034
- return localAgent$1;
806
+ function setUpLocalAgent(adapter, binaryPath, settings) {
807
+ if (/\.(cmd|bat)$/i.test(binaryPath)) {
808
+ throw new Error(
809
+ `${binaryPath} is a .cmd shim, which local agents cannot run safely. Set binaryPath to the agent's native executable.`
810
+ );
811
+ }
812
+ const runner = {
813
+ adapter,
814
+ binaryPath,
815
+ unsetEnv: settings.auth === "subscription" ? adapter.apiKeyEnvVars : [],
816
+ limiter: new Semaphore(settings.concurrency),
817
+ logger: settings.logger
818
+ };
819
+ return new LocalAgent(runner, {
820
+ model: settings.model,
821
+ effort: settings.effort,
822
+ timeoutMs: settings.timeoutMs
823
+ });
1035
824
  }
1036
825
 
1037
- var localAgentExports = requireLocalAgent();
826
+ const LINUX_MAX_ARGUMENT_BYTES = 131072;
827
+ function agentSessionMode(platform = process.platform) {
828
+ if (platform === "win32") return "none";
829
+ return platform === "darwin" ? "terminal" : "command";
830
+ }
831
+ async function startAgentSession(config) {
832
+ if (!isLocalAgentId(config.agent)) {
833
+ throw new TypeError(`Unknown local agent: ${String(config.agent)}`);
834
+ }
835
+ const platform = config.platform ?? process.platform;
836
+ const mode = agentSessionMode(platform);
837
+ if (mode === "none") {
838
+ return refused("unsupported_platform", `Agent sessions need a POSIX shell, which ${platform} lacks.`);
839
+ }
840
+ if (platform === "linux" && Buffer.byteLength(config.prompt) >= LINUX_MAX_ARGUMENT_BYTES) {
841
+ return refused("prompt_too_long", `The prompt is too long to pass to ${config.agent} on ${platform}.`);
842
+ }
843
+ const adapter = AGENT_ADAPTERS[config.agent];
844
+ const binaryPath = config.binaryPath ?? findOnPath(adapter.binaryName);
845
+ if (!binaryPath) {
846
+ return refused(
847
+ "agent_not_found",
848
+ `${adapter.binaryName} was not found on PATH. Install ${config.agent} or set binaryPath.`
849
+ );
850
+ }
851
+ const files = writeSessionFiles(config, binaryPath, adapter.sessionArgs(config.model, config.approval ?? "ask"));
852
+ if (mode === "command") return { kind: "command", files };
853
+ try {
854
+ await node_util.promisify(node_child_process.execFile)("open", [files.launcherPath]);
855
+ } catch (error) {
856
+ return { kind: "open_failed", files, error: error instanceof Error ? error.message : String(error) };
857
+ }
858
+ return { kind: "opened", files };
859
+ }
860
+ function refused(reason, message) {
861
+ return { kind: "refused", reason, message };
862
+ }
863
+ function writeSessionFiles(config, binaryPath, agentArgs) {
864
+ const name = config.name ?? defaultSessionName(config.agent);
865
+ fs__namespace.mkdirSync(config.dir, { recursive: true, mode: 448 });
866
+ const promptPath = path__namespace.join(config.dir, `${name}.md`);
867
+ const launcherPath = path__namespace.join(config.dir, `${name}.command`);
868
+ fs__namespace.writeFileSync(promptPath, config.prompt, { mode: 384, flag: "wx" });
869
+ fs__namespace.writeFileSync(launcherPath, sessionLauncher({ cwd: config.cwd, binaryPath, agentArgs, promptPath }), {
870
+ mode: 448,
871
+ flag: "wx"
872
+ });
873
+ return { promptPath, launcherPath, command: `sh ${shellQuote(launcherPath)}` };
874
+ }
875
+ function defaultSessionName(agent) {
876
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replaceAll(":", "-");
877
+ return `${stamp}-${agent}-${node_crypto.randomBytes(2).toString("hex")}`;
878
+ }
879
+ function sessionLauncher({ cwd, binaryPath, agentArgs, promptPath }) {
880
+ const command = [binaryPath, ...agentArgs].map(shellQuote).join(" ");
881
+ return [
882
+ "#!/bin/sh",
883
+ `cd ${shellQuote(cwd)} || exit 1`,
884
+ `exec ${command} -- "$(cat ${shellQuote(promptPath)})"`,
885
+ ""
886
+ ].join("\n");
887
+ }
888
+ function shellQuote(value) {
889
+ return `'${value.replaceAll("'", `'\\''`)}'`;
890
+ }
1038
891
 
1039
- exports.LOCAL_AGENT_IDS = localAgentExports.LOCAL_AGENT_IDS;
1040
- exports.detectLocalAgents = localAgentExports.detectLocalAgents;
1041
- exports.findLocalAgent = localAgentExports.findLocalAgent;
1042
- exports.isLocalAgentId = localAgentExports.isLocalAgentId;
1043
- exports.localAgent = localAgentExports.localAgent;
892
+ exports.LOCAL_AGENT_IDS = LOCAL_AGENT_IDS;
893
+ exports.agentSessionMode = agentSessionMode;
894
+ exports.detectLocalAgents = detectLocalAgents;
895
+ exports.findLocalAgent = findLocalAgent;
896
+ exports.isLocalAgentId = isLocalAgentId;
897
+ exports.localAgent = localAgent;
898
+ exports.sessionLauncher = sessionLauncher;
899
+ exports.startAgentSession = startAgentSession;