@omnicross/cli-launcher 0.1.10 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +237 -90
- package/dist/index.d.cts +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +121 -11
- package/dist/pty-adapter.cjs +108 -9
- package/dist/pty-adapter.js +78 -6
- package/dist/types.cjs +18 -1
- package/package.json +59 -58
- package/dist/chunk-HNYCLVZP.cjs +0 -1023
- package/dist/chunk-K7IZD73K.js +0 -1023
package/dist/index.cjs
CHANGED
|
@@ -1,18 +1,52 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
4
19
|
|
|
5
|
-
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
CHAT_PROXY_BASE_PATH: () => CHAT_PROXY_BASE_PATH,
|
|
24
|
+
CLAUDE_PROXY_API_KEY_SENTINEL: () => CLAUDE_PROXY_API_KEY_SENTINEL,
|
|
25
|
+
CODEX_PROXY_BASE_PATH: () => CODEX_PROXY_BASE_PATH,
|
|
26
|
+
CODEX_PROXY_PROVIDER_NAME: () => CODEX_PROXY_PROVIDER_NAME,
|
|
27
|
+
OPENCODE_PROXY_PROVIDER_ID: () => OPENCODE_PROXY_PROVIDER_ID,
|
|
28
|
+
OPENCODE_PROXY_TOKEN_ENV: () => OPENCODE_PROXY_TOKEN_ENV,
|
|
29
|
+
buildChatCliLaunchConfig: () => buildChatCliLaunchConfig,
|
|
30
|
+
buildClaudeCliLaunchConfig: () => buildClaudeCliLaunchConfig,
|
|
31
|
+
buildClaudeRuntimeLaunchDescriptor: () => buildClaudeRuntimeLaunchDescriptor,
|
|
32
|
+
buildCodexConfigOverrides: () => buildCodexConfigOverrides,
|
|
33
|
+
buildCodexLaunchConfig: () => buildCodexLaunchConfig,
|
|
34
|
+
buildCodexRuntimeLaunchDescriptor: () => buildCodexRuntimeLaunchDescriptor,
|
|
35
|
+
buildGeminiCliLaunchConfig: () => buildGeminiCliLaunchConfig,
|
|
36
|
+
getProcessSupervisor: () => getProcessSupervisor,
|
|
37
|
+
routeLeaseDescriptorPort: () => routeLeaseDescriptorPort
|
|
38
|
+
});
|
|
39
|
+
module.exports = __toCommonJS(src_exports);
|
|
6
40
|
|
|
7
41
|
// src/supervisor.ts
|
|
8
|
-
var
|
|
9
|
-
var
|
|
42
|
+
var import_node_crypto = require("crypto");
|
|
43
|
+
var import_serializeError = require("@omnicross/core/serializeError");
|
|
10
44
|
|
|
11
45
|
// src/child-adapter.ts
|
|
12
|
-
var
|
|
46
|
+
var import_node_child_process2 = require("child_process");
|
|
13
47
|
|
|
14
48
|
// src/kill-tree.ts
|
|
15
|
-
|
|
49
|
+
var import_node_child_process = require("child_process");
|
|
16
50
|
var TAG = "[ProcessSupervisor]";
|
|
17
51
|
var MIN_GRACE_MS = 0;
|
|
18
52
|
var MAX_GRACE_MS = 6e4;
|
|
@@ -22,12 +56,12 @@ function isProcessAlive(pid) {
|
|
|
22
56
|
try {
|
|
23
57
|
process.kill(pid, 0);
|
|
24
58
|
return true;
|
|
25
|
-
} catch
|
|
59
|
+
} catch {
|
|
26
60
|
return false;
|
|
27
61
|
}
|
|
28
62
|
}
|
|
29
63
|
function killProcessTree(pid, opts) {
|
|
30
|
-
const graceMs = Math.max(MIN_GRACE_MS, Math.min(MAX_GRACE_MS,
|
|
64
|
+
const graceMs = Math.max(MIN_GRACE_MS, Math.min(MAX_GRACE_MS, opts?.graceMs ?? DEFAULT_GRACE_MS));
|
|
31
65
|
if (!isProcessAlive(pid)) return;
|
|
32
66
|
if (IS_WIN) {
|
|
33
67
|
killTreeWindows(pid, graceMs);
|
|
@@ -37,7 +71,7 @@ function killProcessTree(pid, opts) {
|
|
|
37
71
|
}
|
|
38
72
|
function killTreeWindows(pid, graceMs) {
|
|
39
73
|
try {
|
|
40
|
-
|
|
74
|
+
(0, import_node_child_process.spawn)("taskkill", ["/T", "/PID", String(pid)], {
|
|
41
75
|
detached: true,
|
|
42
76
|
windowsHide: true,
|
|
43
77
|
stdio: "ignore"
|
|
@@ -48,7 +82,7 @@ function killTreeWindows(pid, graceMs) {
|
|
|
48
82
|
const timer = setTimeout(() => {
|
|
49
83
|
if (!isProcessAlive(pid)) return;
|
|
50
84
|
try {
|
|
51
|
-
|
|
85
|
+
(0, import_node_child_process.spawn)("taskkill", ["/F", "/T", "/PID", String(pid)], {
|
|
52
86
|
detached: true,
|
|
53
87
|
windowsHide: true,
|
|
54
88
|
stdio: "ignore"
|
|
@@ -83,6 +117,7 @@ function killTreeUnix(pid, graceMs) {
|
|
|
83
117
|
// src/child-adapter.ts
|
|
84
118
|
var TAG2 = "[ProcessSupervisor]";
|
|
85
119
|
var IS_WIN2 = process.platform === "win32";
|
|
120
|
+
var PREBUFFER_CHUNK_LIMIT = 512;
|
|
86
121
|
function createChildAdapter(input) {
|
|
87
122
|
const [command, ...args] = input.argv;
|
|
88
123
|
if (!command) {
|
|
@@ -96,12 +131,14 @@ function createChildAdapter(input) {
|
|
|
96
131
|
windowsVerbatimArguments: input.windowsVerbatimArguments,
|
|
97
132
|
detached: !IS_WIN2
|
|
98
133
|
};
|
|
99
|
-
const child =
|
|
100
|
-
const
|
|
134
|
+
const child = (0, import_node_child_process2.spawn)(command, args, opts);
|
|
135
|
+
const stdoutPump = pump(child.stdout);
|
|
136
|
+
const stderrPump = pump(child.stderr);
|
|
137
|
+
const stdinMode = input.stdinMode ?? (input.input ? "pipe-closed" : "pipe-open");
|
|
101
138
|
if (input.input && child.stdin) {
|
|
102
139
|
child.stdin.write(input.input, () => {
|
|
103
140
|
if (stdinMode === "pipe-closed") {
|
|
104
|
-
|
|
141
|
+
child.stdin?.end();
|
|
105
142
|
}
|
|
106
143
|
});
|
|
107
144
|
} else if (stdinMode === "pipe-closed" && child.stdin) {
|
|
@@ -111,12 +148,10 @@ function createChildAdapter(input) {
|
|
|
111
148
|
return {
|
|
112
149
|
pid: child.pid,
|
|
113
150
|
onStdout(cb) {
|
|
114
|
-
|
|
115
|
-
_optionalChain([child, 'access', _8 => _8.stdout, 'optionalAccess', _9 => _9.on, 'call', _10 => _10("data", cb)]);
|
|
151
|
+
stdoutPump.subscribe(cb);
|
|
116
152
|
},
|
|
117
153
|
onStderr(cb) {
|
|
118
|
-
|
|
119
|
-
_optionalChain([child, 'access', _14 => _14.stderr, 'optionalAccess', _15 => _15.on, 'call', _16 => _16("data", cb)]);
|
|
154
|
+
stderrPump.subscribe(cb);
|
|
120
155
|
},
|
|
121
156
|
wait() {
|
|
122
157
|
return new Promise((resolve) => {
|
|
@@ -125,7 +160,7 @@ function createChildAdapter(input) {
|
|
|
125
160
|
resolve({ code: -1, signal: null });
|
|
126
161
|
});
|
|
127
162
|
child.on("close", (code, signal) => {
|
|
128
|
-
resolve({ code, signal:
|
|
163
|
+
resolve({ code, signal: signal ?? null });
|
|
129
164
|
});
|
|
130
165
|
});
|
|
131
166
|
},
|
|
@@ -135,7 +170,7 @@ function createChildAdapter(input) {
|
|
|
135
170
|
killProcessTree(child.pid);
|
|
136
171
|
} else {
|
|
137
172
|
try {
|
|
138
|
-
child.kill(
|
|
173
|
+
child.kill(signal ?? "SIGTERM");
|
|
139
174
|
} catch (err) {
|
|
140
175
|
console.warn(TAG2, `child.kill failed for pid=${child.pid}:`, err);
|
|
141
176
|
}
|
|
@@ -145,12 +180,126 @@ function createChildAdapter(input) {
|
|
|
145
180
|
dispose() {
|
|
146
181
|
if (disposed) return;
|
|
147
182
|
disposed = true;
|
|
148
|
-
|
|
149
|
-
|
|
183
|
+
stdoutPump.dispose();
|
|
184
|
+
stderrPump.dispose();
|
|
185
|
+
child.stdout?.removeAllListeners();
|
|
186
|
+
child.stderr?.removeAllListeners();
|
|
150
187
|
child.removeAllListeners();
|
|
151
188
|
}
|
|
152
189
|
};
|
|
153
190
|
}
|
|
191
|
+
function pump(stream) {
|
|
192
|
+
const buffered = [];
|
|
193
|
+
let subscriber = null;
|
|
194
|
+
if (!stream) {
|
|
195
|
+
return { subscribe: () => {
|
|
196
|
+
}, dispose: () => {
|
|
197
|
+
} };
|
|
198
|
+
}
|
|
199
|
+
stream.setEncoding("utf8");
|
|
200
|
+
const onData = (chunk) => {
|
|
201
|
+
if (subscriber) {
|
|
202
|
+
subscriber(chunk);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
if (buffered.length >= PREBUFFER_CHUNK_LIMIT) buffered.shift();
|
|
206
|
+
buffered.push(chunk);
|
|
207
|
+
};
|
|
208
|
+
stream.on("data", onData);
|
|
209
|
+
return {
|
|
210
|
+
subscribe(cb) {
|
|
211
|
+
subscriber = cb;
|
|
212
|
+
const replay = buffered.splice(0, buffered.length);
|
|
213
|
+
for (const chunk of replay) cb(chunk);
|
|
214
|
+
},
|
|
215
|
+
dispose() {
|
|
216
|
+
subscriber = null;
|
|
217
|
+
buffered.length = 0;
|
|
218
|
+
stream.off("data", onData);
|
|
219
|
+
stream.resume();
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// src/pty-adapter.ts
|
|
225
|
+
var import_node_module = require("module");
|
|
226
|
+
var import_node_path = require("path");
|
|
227
|
+
var import_meta = {};
|
|
228
|
+
var requireFromThisModule = (0, import_node_module.createRequire)(
|
|
229
|
+
typeof __filename === "string" && (0, import_node_path.isAbsolute)(__filename) ? __filename : import_meta.url
|
|
230
|
+
);
|
|
231
|
+
function buildPtyEnv(overlay) {
|
|
232
|
+
return overlay ? { ...process.env, ...overlay } : { ...process.env };
|
|
233
|
+
}
|
|
234
|
+
function createPtyAdapter(input) {
|
|
235
|
+
const nodePty = requireFromThisModule("node-pty");
|
|
236
|
+
const shell = input.shell ?? (process.platform === "win32" ? "powershell.exe" : "/bin/bash");
|
|
237
|
+
const pty = nodePty.spawn(shell, input.args ?? [], {
|
|
238
|
+
name: "xterm-256color",
|
|
239
|
+
cols: input.cols ?? 120,
|
|
240
|
+
rows: input.rows ?? 30,
|
|
241
|
+
cwd: input.cwd,
|
|
242
|
+
env: buildPtyEnv(input.env)
|
|
243
|
+
});
|
|
244
|
+
const stdoutListeners = [];
|
|
245
|
+
const stderrListeners = [];
|
|
246
|
+
const dataDisposable = pty.onData((data) => {
|
|
247
|
+
for (const cb of stdoutListeners) cb(data);
|
|
248
|
+
});
|
|
249
|
+
let exitResolve = null;
|
|
250
|
+
const exitPromise = new Promise((resolve) => {
|
|
251
|
+
exitResolve = resolve;
|
|
252
|
+
});
|
|
253
|
+
const exitDisposable = pty.onExit(({ exitCode, signal }) => {
|
|
254
|
+
exitResolve?.({ code: exitCode, signal: signal != null ? String(signal) : null });
|
|
255
|
+
});
|
|
256
|
+
let disposed = false;
|
|
257
|
+
return {
|
|
258
|
+
pid: pty.pid,
|
|
259
|
+
onStdout(cb) {
|
|
260
|
+
stdoutListeners.push(cb);
|
|
261
|
+
},
|
|
262
|
+
onStderr(cb) {
|
|
263
|
+
stderrListeners.push(cb);
|
|
264
|
+
},
|
|
265
|
+
stdin: {
|
|
266
|
+
write(data) {
|
|
267
|
+
if (!disposed) pty.write(data);
|
|
268
|
+
},
|
|
269
|
+
end() {
|
|
270
|
+
if (!disposed) pty.write("");
|
|
271
|
+
},
|
|
272
|
+
destroy() {
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
write(data) {
|
|
276
|
+
if (!disposed) pty.write(data);
|
|
277
|
+
},
|
|
278
|
+
resize(cols, rows) {
|
|
279
|
+
if (!disposed) pty.resize(cols, rows);
|
|
280
|
+
},
|
|
281
|
+
wait() {
|
|
282
|
+
return exitPromise;
|
|
283
|
+
},
|
|
284
|
+
kill(signal) {
|
|
285
|
+
if (disposed) return;
|
|
286
|
+
try {
|
|
287
|
+
pty.kill(signal);
|
|
288
|
+
} catch {
|
|
289
|
+
}
|
|
290
|
+
},
|
|
291
|
+
dispose() {
|
|
292
|
+
if (disposed) return;
|
|
293
|
+
disposed = true;
|
|
294
|
+
dataDisposable.dispose();
|
|
295
|
+
exitDisposable.dispose();
|
|
296
|
+
try {
|
|
297
|
+
pty.kill();
|
|
298
|
+
} catch {
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
}
|
|
154
303
|
|
|
155
304
|
// src/run-registry.ts
|
|
156
305
|
var MAX_EXITED = 500;
|
|
@@ -232,9 +381,9 @@ function createProcessSupervisor() {
|
|
|
232
381
|
const registry = createRunRegistry();
|
|
233
382
|
const active = /* @__PURE__ */ new Map();
|
|
234
383
|
function spawn(input) {
|
|
235
|
-
const runId =
|
|
384
|
+
const runId = input.runId ?? (0, import_node_crypto.randomUUID)();
|
|
236
385
|
const now = Date.now();
|
|
237
|
-
const captureOutput =
|
|
386
|
+
const captureOutput = input.captureOutput ?? true;
|
|
238
387
|
if (input.replaceExistingScope && input.scopeKey) {
|
|
239
388
|
cancelScope(input.scopeKey, "manual-cancel");
|
|
240
389
|
}
|
|
@@ -259,7 +408,6 @@ function createProcessSupervisor() {
|
|
|
259
408
|
let adapter;
|
|
260
409
|
try {
|
|
261
410
|
if (input.mode === "pty") {
|
|
262
|
-
const { createPtyAdapter } = (_chunkHNYCLVZPcjs.init_pty_adapter.call(void 0, ), _chunkHNYCLVZPcjs.__toCommonJS.call(void 0, _chunkHNYCLVZPcjs.pty_adapter_exports));
|
|
263
411
|
adapter = createPtyAdapter(input);
|
|
264
412
|
} else {
|
|
265
413
|
adapter = createChildAdapter(input);
|
|
@@ -272,7 +420,7 @@ function createProcessSupervisor() {
|
|
|
272
420
|
exitSignal: null,
|
|
273
421
|
durationMs: 0,
|
|
274
422
|
stdout: "",
|
|
275
|
-
stderr:
|
|
423
|
+
stderr: (0, import_serializeError.serializeError)(err),
|
|
276
424
|
timedOut: false,
|
|
277
425
|
noOutputTimedOut: false
|
|
278
426
|
};
|
|
@@ -287,7 +435,7 @@ function createProcessSupervisor() {
|
|
|
287
435
|
registry.updateState(runId, "running", { pid: adapter.pid });
|
|
288
436
|
function cancelRun(reason) {
|
|
289
437
|
if (settled) return;
|
|
290
|
-
forcedReason =
|
|
438
|
+
forcedReason = reason ?? "manual-cancel";
|
|
291
439
|
registry.updateState(runId, "exiting", { terminationReason: forcedReason });
|
|
292
440
|
adapter.kill("SIGKILL");
|
|
293
441
|
}
|
|
@@ -327,32 +475,32 @@ function createProcessSupervisor() {
|
|
|
327
475
|
if (captureOutput) stdout += chunk;
|
|
328
476
|
registry.touchOutput(runId);
|
|
329
477
|
resetNoOutputTimer();
|
|
330
|
-
|
|
478
|
+
input.onStdout?.(chunk);
|
|
331
479
|
});
|
|
332
480
|
adapter.onStderr((chunk) => {
|
|
333
481
|
if (captureOutput) stderr += chunk;
|
|
334
482
|
registry.touchOutput(runId);
|
|
335
483
|
resetNoOutputTimer();
|
|
336
|
-
|
|
484
|
+
input.onStderr?.(chunk);
|
|
337
485
|
});
|
|
338
486
|
let stdinHandle;
|
|
339
487
|
if (adapter.stdin) {
|
|
340
488
|
stdinHandle = {
|
|
341
489
|
write(data) {
|
|
342
|
-
|
|
490
|
+
adapter.stdin?.write(data);
|
|
343
491
|
},
|
|
344
492
|
end() {
|
|
345
|
-
|
|
493
|
+
adapter.stdin?.end();
|
|
346
494
|
},
|
|
347
495
|
destroy() {
|
|
348
|
-
|
|
496
|
+
adapter.stdin?.destroy();
|
|
349
497
|
}
|
|
350
498
|
};
|
|
351
499
|
}
|
|
352
500
|
const waitPromise = adapter.wait().then(({ code, signal }) => {
|
|
353
501
|
settled = true;
|
|
354
502
|
clearTimers();
|
|
355
|
-
const reason =
|
|
503
|
+
const reason = forcedReason ?? (code === -1 ? "spawn-error" : signal ? "signal" : "exit");
|
|
356
504
|
registry.finalize(runId, reason, code, signal);
|
|
357
505
|
active.delete(runId);
|
|
358
506
|
adapter.dispose();
|
|
@@ -409,8 +557,8 @@ function createProcessSupervisor() {
|
|
|
409
557
|
}
|
|
410
558
|
|
|
411
559
|
// src/proxy-env/claude-proxy-env.ts
|
|
412
|
-
var
|
|
413
|
-
var
|
|
560
|
+
var import_completion = require("@omnicross/core/completion");
|
|
561
|
+
var import_provider_proxy = require("@omnicross/core/provider-proxy");
|
|
414
562
|
var CLAUDE_PROXY_API_KEY_SENTINEL = "omnicross-proxy";
|
|
415
563
|
function buildClaudeRuntimeLaunchDescriptor(baseUrl, model, routeToken) {
|
|
416
564
|
return {
|
|
@@ -430,21 +578,21 @@ async function buildClaudeCliLaunchConfig(inputs) {
|
|
|
430
578
|
`claude proxy: provider not found: ${inputs.providerId}. Add a provider row to the daemon config (omnicross providers add \u2026).`
|
|
431
579
|
);
|
|
432
580
|
}
|
|
433
|
-
const { apiKey } =
|
|
581
|
+
const { apiKey } = (0, import_completion.resolveProviderEndpoint)(provider);
|
|
434
582
|
if (!resolveApiKey(apiKey)) {
|
|
435
583
|
throw new Error(
|
|
436
584
|
`claude proxy: provider "${inputs.providerId}" has no valid API key. Set apiKey (or a $ENV_VAR reference) on the provider row.`
|
|
437
585
|
);
|
|
438
586
|
}
|
|
439
587
|
const route = {
|
|
440
|
-
sessionId:
|
|
588
|
+
sessionId: inputs.sessionId ?? null,
|
|
441
589
|
targetProviderFormat: provider.apiFormat === "anthropic" ? "anthropic" : "transform",
|
|
442
590
|
model: inputs.model,
|
|
443
591
|
ingressFormat: "anthropic-messages",
|
|
444
592
|
authMode: "byo",
|
|
445
593
|
providerId: inputs.providerId
|
|
446
594
|
};
|
|
447
|
-
const proxy =
|
|
595
|
+
const proxy = (0, import_provider_proxy.getProviderProxy)();
|
|
448
596
|
const token = proxy.addRoute(route);
|
|
449
597
|
const baseUrl = proxy.getBaseUrl();
|
|
450
598
|
console.info("[buildClaudeCliLaunchConfig] claude route ready", {
|
|
@@ -460,7 +608,7 @@ async function buildClaudeCliLaunchConfig(inputs) {
|
|
|
460
608
|
onSessionEnd: () => {
|
|
461
609
|
try {
|
|
462
610
|
proxy.removeRoute(token);
|
|
463
|
-
} catch
|
|
611
|
+
} catch {
|
|
464
612
|
}
|
|
465
613
|
}
|
|
466
614
|
};
|
|
@@ -474,11 +622,11 @@ function resolveApiKey(apiKey) {
|
|
|
474
622
|
}
|
|
475
623
|
|
|
476
624
|
// src/proxy-env/cli-proxy-env.ts
|
|
477
|
-
var
|
|
478
|
-
var
|
|
479
|
-
var
|
|
480
|
-
|
|
481
|
-
|
|
625
|
+
var import_node_fs = require("fs");
|
|
626
|
+
var import_node_os = require("os");
|
|
627
|
+
var import_node_path2 = require("path");
|
|
628
|
+
var import_completion2 = require("@omnicross/core/completion");
|
|
629
|
+
var import_provider_proxy2 = require("@omnicross/core/provider-proxy");
|
|
482
630
|
var CHAT_PROXY_BASE_PATH = "/v1";
|
|
483
631
|
var OPENCODE_PROXY_PROVIDER_ID = "omnicross";
|
|
484
632
|
var OPENCODE_PROXY_TOKEN_ENV = "OMNICROSS_OPENCODE_TOKEN";
|
|
@@ -489,21 +637,21 @@ async function buildChatCliLaunchConfig(inputs) {
|
|
|
489
637
|
`${inputs.backendId} proxy: provider not found: ${inputs.providerId}. Add an OpenAI-compatible provider in Settings \u2192 LLM Providers.`
|
|
490
638
|
);
|
|
491
639
|
}
|
|
492
|
-
const { apiKey } =
|
|
640
|
+
const { apiKey } = (0, import_completion2.resolveProviderEndpoint)(provider);
|
|
493
641
|
if (!resolveApiKey2(apiKey)) {
|
|
494
642
|
throw new Error(
|
|
495
643
|
`${inputs.backendId} proxy: provider "${inputs.providerId}" has no valid API key. Add an API key in Settings \u2192 LLM Providers.`
|
|
496
644
|
);
|
|
497
645
|
}
|
|
498
646
|
const route = {
|
|
499
|
-
sessionId:
|
|
647
|
+
sessionId: inputs.sessionId ?? null,
|
|
500
648
|
targetProviderFormat: "transform",
|
|
501
649
|
model: inputs.model,
|
|
502
650
|
ingressFormat: "openai-chat",
|
|
503
651
|
authMode: "byo",
|
|
504
652
|
providerId: inputs.providerId
|
|
505
653
|
};
|
|
506
|
-
const proxy =
|
|
654
|
+
const proxy = (0, import_provider_proxy2.getProviderProxy)();
|
|
507
655
|
const token = proxy.addRoute(route);
|
|
508
656
|
const baseUrl = proxy.getBaseUrl();
|
|
509
657
|
const chatBase = `${baseUrl}${CHAT_PROXY_BASE_PATH}`;
|
|
@@ -529,7 +677,7 @@ async function buildChatCliLaunchConfig(inputs) {
|
|
|
529
677
|
for (const c of cleanups) {
|
|
530
678
|
try {
|
|
531
679
|
c();
|
|
532
|
-
} catch
|
|
680
|
+
} catch {
|
|
533
681
|
}
|
|
534
682
|
}
|
|
535
683
|
}
|
|
@@ -576,10 +724,10 @@ function buildOpencodeEnv(ctx) {
|
|
|
576
724
|
}
|
|
577
725
|
}
|
|
578
726
|
};
|
|
579
|
-
const dir =
|
|
580
|
-
const configPath =
|
|
581
|
-
|
|
582
|
-
ctx.cleanups.push(() =>
|
|
727
|
+
const dir = (0, import_node_fs.mkdtempSync)((0, import_node_path2.join)((0, import_node_os.tmpdir)(), "omnicross-opencode-"));
|
|
728
|
+
const configPath = (0, import_node_path2.join)(dir, "opencode.json");
|
|
729
|
+
(0, import_node_fs.writeFileSync)(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
730
|
+
ctx.cleanups.push(() => (0, import_node_fs.rmSync)(dir, { recursive: true, force: true }));
|
|
583
731
|
return {
|
|
584
732
|
OPENCODE_CONFIG: configPath,
|
|
585
733
|
[OPENCODE_PROXY_TOKEN_ENV]: ctx.token
|
|
@@ -592,21 +740,21 @@ async function buildGeminiCliLaunchConfig(inputs) {
|
|
|
592
740
|
`gemini-cli proxy: provider not found: ${inputs.providerId}. Add a Gemini-compatible provider in Settings \u2192 LLM Providers.`
|
|
593
741
|
);
|
|
594
742
|
}
|
|
595
|
-
const { apiKey } =
|
|
743
|
+
const { apiKey } = (0, import_completion2.resolveProviderEndpoint)(provider);
|
|
596
744
|
if (!resolveApiKey2(apiKey)) {
|
|
597
745
|
throw new Error(
|
|
598
746
|
`gemini-cli proxy: provider "${inputs.providerId}" has no valid API key. Add an API key in Settings \u2192 LLM Providers.`
|
|
599
747
|
);
|
|
600
748
|
}
|
|
601
749
|
const route = {
|
|
602
|
-
sessionId:
|
|
750
|
+
sessionId: inputs.sessionId ?? null,
|
|
603
751
|
targetProviderFormat: "transform",
|
|
604
752
|
model: inputs.model,
|
|
605
753
|
ingressFormat: "gemini-generatecontent",
|
|
606
754
|
authMode: "byo",
|
|
607
755
|
providerId: inputs.providerId
|
|
608
756
|
};
|
|
609
|
-
const proxy =
|
|
757
|
+
const proxy = (0, import_provider_proxy2.getProviderProxy)();
|
|
610
758
|
const token = proxy.addRoute(route);
|
|
611
759
|
const baseUrl = proxy.getBaseUrl();
|
|
612
760
|
console.log("[buildGeminiCliLaunchConfig] gemini-CLI route ready (forced API-key)", {
|
|
@@ -628,7 +776,7 @@ async function buildGeminiCliLaunchConfig(inputs) {
|
|
|
628
776
|
onSessionEnd: () => {
|
|
629
777
|
try {
|
|
630
778
|
proxy.removeRoute(token);
|
|
631
|
-
} catch
|
|
779
|
+
} catch {
|
|
632
780
|
}
|
|
633
781
|
}
|
|
634
782
|
};
|
|
@@ -642,13 +790,11 @@ function resolveApiKey2(apiKey) {
|
|
|
642
790
|
}
|
|
643
791
|
|
|
644
792
|
// src/proxy-env/codex-proxy-env.ts
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
793
|
+
var import_completion3 = require("@omnicross/core/completion");
|
|
794
|
+
var import_provider_proxy3 = require("@omnicross/core/provider-proxy");
|
|
650
795
|
var CODEX_PROXY_PROVIDER_NAME = "omnicross";
|
|
651
796
|
var CODEX_PROXY_BASE_PATH = "/openai";
|
|
797
|
+
var CODEX_IMAGE_GENERATION_CAPABILITY_MARKER = "omnicross";
|
|
652
798
|
function buildCodexConfigOverrides(baseUrl) {
|
|
653
799
|
const name = CODEX_PROXY_PROVIDER_NAME;
|
|
654
800
|
const providerBaseUrl = `${baseUrl}${CODEX_PROXY_BASE_PATH}`;
|
|
@@ -662,7 +808,9 @@ function buildCodexConfigOverrides(baseUrl) {
|
|
|
662
808
|
"-c",
|
|
663
809
|
`model_providers.${name}.wire_api="responses"`,
|
|
664
810
|
"-c",
|
|
665
|
-
`model_providers.${name}.env_key="${
|
|
811
|
+
`model_providers.${name}.env_key="${import_provider_proxy3.ROUTE_LEASE_CODEX_TOKEN_ENV}"`,
|
|
812
|
+
"-c",
|
|
813
|
+
`model_providers.${name}.http_headers={"X-OpenAI-Actor-Authorization"="${CODEX_IMAGE_GENERATION_CAPABILITY_MARKER}"}`,
|
|
666
814
|
// disable_response_storage: the CLI sends full context each turn (no
|
|
667
815
|
// server-side response store) — required because the proxy upstream is
|
|
668
816
|
// stateless w.r.t. Codex's response-id store (design Q3 contract).
|
|
@@ -672,12 +820,12 @@ function buildCodexConfigOverrides(baseUrl) {
|
|
|
672
820
|
}
|
|
673
821
|
function buildCodexRuntimeLaunchDescriptor(baseUrl, routeToken) {
|
|
674
822
|
return {
|
|
675
|
-
env: { [
|
|
823
|
+
env: { [import_provider_proxy3.ROUTE_LEASE_CODEX_TOKEN_ENV]: routeToken },
|
|
676
824
|
extraArgs: buildCodexConfigOverrides(baseUrl)
|
|
677
825
|
};
|
|
678
826
|
}
|
|
679
827
|
async function buildCodexLaunchConfig(inputs) {
|
|
680
|
-
const authMode =
|
|
828
|
+
const authMode = inputs.authMode ?? "byo";
|
|
681
829
|
if (authMode === "byo") {
|
|
682
830
|
const provider = await inputs.llmConfig.getProvider(inputs.providerId);
|
|
683
831
|
if (!provider) {
|
|
@@ -685,7 +833,7 @@ async function buildCodexLaunchConfig(inputs) {
|
|
|
685
833
|
`Codex proxy: provider not found: ${inputs.providerId}. Add an OpenAI-compatible provider in Settings \u2192 LLM Providers.`
|
|
686
834
|
);
|
|
687
835
|
}
|
|
688
|
-
const { apiKey } =
|
|
836
|
+
const { apiKey } = (0, import_completion3.resolveProviderEndpoint)(provider);
|
|
689
837
|
const resolved = resolveApiKey3(apiKey);
|
|
690
838
|
if (!resolved) {
|
|
691
839
|
throw new Error(
|
|
@@ -696,15 +844,15 @@ async function buildCodexLaunchConfig(inputs) {
|
|
|
696
844
|
throw new Error("Codex proxy: subscription mode requires a codex subscription profile.");
|
|
697
845
|
}
|
|
698
846
|
const route = {
|
|
699
|
-
sessionId:
|
|
847
|
+
sessionId: inputs.sessionId ?? null,
|
|
700
848
|
targetProviderFormat: "openai-responses",
|
|
701
849
|
model: inputs.model,
|
|
702
850
|
ingressFormat: "openai-responses",
|
|
703
851
|
authMode,
|
|
704
852
|
providerId: inputs.providerId,
|
|
705
|
-
subscriptionProfile:
|
|
853
|
+
subscriptionProfile: inputs.subscriptionProfile ?? null
|
|
706
854
|
};
|
|
707
|
-
const proxy =
|
|
855
|
+
const proxy = (0, import_provider_proxy3.getProviderProxy)();
|
|
708
856
|
const token = proxy.addRoute(route);
|
|
709
857
|
const baseUrl = proxy.getBaseUrl();
|
|
710
858
|
console.log("[buildCodexLaunchConfig] Codex route ready", {
|
|
@@ -732,9 +880,7 @@ function resolveApiKey3(apiKey) {
|
|
|
732
880
|
}
|
|
733
881
|
|
|
734
882
|
// src/proxy-env/runtime-launch-descriptor.ts
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
883
|
+
var import_provider_proxy4 = require("@omnicross/core/provider-proxy");
|
|
738
884
|
var routeLeaseDescriptorPort = {
|
|
739
885
|
has(runtime) {
|
|
740
886
|
return runtime === "claude" || runtime === "codex";
|
|
@@ -747,7 +893,7 @@ var routeLeaseDescriptorPort = {
|
|
|
747
893
|
return buildCodexRuntimeLaunchDescriptor(input.proxyBaseUrl, input.routeToken);
|
|
748
894
|
default: {
|
|
749
895
|
const exhaustive = runtime;
|
|
750
|
-
throw new
|
|
896
|
+
throw new import_provider_proxy4.RouteLeaseError("runtime_unsupported", `runtime adapter unavailable: ${String(exhaustive)}`);
|
|
751
897
|
}
|
|
752
898
|
}
|
|
753
899
|
}
|
|
@@ -759,20 +905,21 @@ function getProcessSupervisor() {
|
|
|
759
905
|
if (!instance) instance = createProcessSupervisor();
|
|
760
906
|
return instance;
|
|
761
907
|
}
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
908
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
909
|
+
0 && (module.exports = {
|
|
910
|
+
CHAT_PROXY_BASE_PATH,
|
|
911
|
+
CLAUDE_PROXY_API_KEY_SENTINEL,
|
|
912
|
+
CODEX_PROXY_BASE_PATH,
|
|
913
|
+
CODEX_PROXY_PROVIDER_NAME,
|
|
914
|
+
OPENCODE_PROXY_PROVIDER_ID,
|
|
915
|
+
OPENCODE_PROXY_TOKEN_ENV,
|
|
916
|
+
buildChatCliLaunchConfig,
|
|
917
|
+
buildClaudeCliLaunchConfig,
|
|
918
|
+
buildClaudeRuntimeLaunchDescriptor,
|
|
919
|
+
buildCodexConfigOverrides,
|
|
920
|
+
buildCodexLaunchConfig,
|
|
921
|
+
buildCodexRuntimeLaunchDescriptor,
|
|
922
|
+
buildGeminiCliLaunchConfig,
|
|
923
|
+
getProcessSupervisor,
|
|
924
|
+
routeLeaseDescriptorPort
|
|
925
|
+
});
|
package/dist/index.d.cts
CHANGED
|
@@ -14,6 +14,16 @@ import { SubscriptionAuthProfile } from '@omnicross/core/pipeline/SubscriptionAu
|
|
|
14
14
|
* - Windows: windowsHide=true, not detached
|
|
15
15
|
* - Unix: detached=true for process group kill support
|
|
16
16
|
*
|
|
17
|
+
* PIPES ARE DRAINED FROM THE FIRST TICK, not from whenever a consumer shows up.
|
|
18
|
+
* `stdio` is `['pipe','pipe','pipe']`, and a piped stream nobody reads stalls the
|
|
19
|
+
* child once the OS pipe buffer fills — on Windows and Linux the child's write is
|
|
20
|
+
* synchronous, so "stalls" means its event loop stops, permanently, with the
|
|
21
|
+
* process still alive. (The desktop app hit exactly this with the daemon's
|
|
22
|
+
* stderr.) So both streams are attached immediately and buffered into a bounded
|
|
23
|
+
* ring; `onStdout`/`onStderr` replay that ring to the consumer, so early output
|
|
24
|
+
* is not lost either. A caller that never subscribes still cannot wedge its
|
|
25
|
+
* child.
|
|
26
|
+
*
|
|
17
27
|
* @module child-adapter
|
|
18
28
|
*/
|
|
19
29
|
|
package/dist/index.d.ts
CHANGED
|
@@ -14,6 +14,16 @@ import { SubscriptionAuthProfile } from '@omnicross/core/pipeline/SubscriptionAu
|
|
|
14
14
|
* - Windows: windowsHide=true, not detached
|
|
15
15
|
* - Unix: detached=true for process group kill support
|
|
16
16
|
*
|
|
17
|
+
* PIPES ARE DRAINED FROM THE FIRST TICK, not from whenever a consumer shows up.
|
|
18
|
+
* `stdio` is `['pipe','pipe','pipe']`, and a piped stream nobody reads stalls the
|
|
19
|
+
* child once the OS pipe buffer fills — on Windows and Linux the child's write is
|
|
20
|
+
* synchronous, so "stalls" means its event loop stops, permanently, with the
|
|
21
|
+
* process still alive. (The desktop app hit exactly this with the daemon's
|
|
22
|
+
* stderr.) So both streams are attached immediately and buffered into a bounded
|
|
23
|
+
* ring; `onStdout`/`onStderr` replay that ring to the consumer, so early output
|
|
24
|
+
* is not lost either. A caller that never subscribes still cannot wedge its
|
|
25
|
+
* child.
|
|
26
|
+
*
|
|
17
27
|
* @module child-adapter
|
|
18
28
|
*/
|
|
19
29
|
|