omnigateway 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -5
- package/bin/omni.js +454 -228
- package/gateway.js +225 -59
- package/package.json +1 -1
- package/public/assets/{Chip-Ccqsb_Mq.js → Chip-C69u2U_b.js} +2 -2
- package/public/assets/{CopyValue-cAwgC1sU.js → CopyValue-CJy2T0H6.js} +1 -1
- package/public/assets/{Field-Devm4K46.js → Field-Sc8mDqJv.js} +1 -1
- package/public/assets/{Lamp-BXSUIAtG.js → Lamp-7jD_9929.js} +2 -2
- package/public/assets/{Meter-Fn8X7t60.js → Meter-C0nUftAa.js} +2 -2
- package/public/assets/{Modal-Dqir9wBz.js → Modal-CiVHSJmm.js} +2 -2
- package/public/assets/Rack-CMqGBP4I.js +147 -0
- package/public/assets/{Readout-BKpOZIGX.js → Readout-Dv2dZWtI.js} +4 -4
- package/public/assets/{States-DBzsiHjQ.js → States-D55MhqMx.js} +10 -10
- package/public/assets/{Table-DPDJeeVc.js → Table-DBB3jdgi.js} +1 -1
- package/public/assets/{Toggle-BhViDMm9.js → Toggle-BoGjb5oi.js} +3 -3
- package/public/assets/_app-p5Mz7sXD.js +1 -0
- package/public/assets/_app.accounts-B5wMO9TH.js +51 -0
- package/public/assets/_app.console-Bka7AkiL.js +25 -0
- package/public/assets/_app.index-MnQuadXb.js +61 -0
- package/public/assets/_app.keys-BX8k8COP.js +39 -0
- package/public/assets/_app.logs-DD-sd4fn.js +33 -0
- package/public/assets/_app.models-CezFNL6y.js +144 -0
- package/public/assets/{_app.settings-DA1aYcR4.js → _app.settings-D1taAt8B.js} +3 -3
- package/public/assets/{_app.usage-DAyYUfIi.js → _app.usage-BRhEvwVr.js} +28 -28
- package/public/assets/index-vCuK1fRQ.js +170 -0
- package/public/assets/{login-DXHM-Noj.js → login-DaC-wVpI.js} +8 -8
- package/public/assets/{queries-BMwc6EvM.js → queries-2E6-CboE.js} +12 -12
- package/public/assets/{trash-2-JF_uX2gE.js → trash-2--aH2iKg-.js} +1 -1
- package/public/index.html +2 -2
- package/public/assets/Rack-XtfiZ6GC.js +0 -147
- package/public/assets/_app-B8lqq_ks.js +0 -1
- package/public/assets/_app.accounts-DSMHSYBF.js +0 -51
- package/public/assets/_app.index-DXH5sH41.js +0 -61
- package/public/assets/_app.keys-DdEyVy_b.js +0 -39
- package/public/assets/_app.logs-Camxditb.js +0 -33
- package/public/assets/_app.models-CuD-JtGS.js +0 -144
- package/public/assets/index-BtjyVE1i.js +0 -170
package/bin/omni.js
CHANGED
|
@@ -188,6 +188,23 @@ class GatewayError extends Error {
|
|
|
188
188
|
}
|
|
189
189
|
// packages/ir/src/logger.ts
|
|
190
190
|
var LEVELS = { debug: 10, info: 20, warn: 30, error: 40 };
|
|
191
|
+
var ANSI2 = /\u001B\[[0-9;]*m/g;
|
|
192
|
+
var HEAD = /^(\S+) (DEBUG|INFO|WARN|ERROR) {1,2}(.*)$/;
|
|
193
|
+
var FIELDS = / {2}(?=[a-zA-Z]+=)/;
|
|
194
|
+
function parseLine(raw) {
|
|
195
|
+
const absent = { raw, at: null, level: null, msg: null };
|
|
196
|
+
const match = HEAD.exec(raw.replace(ANSI2, ""));
|
|
197
|
+
if (match === null)
|
|
198
|
+
return absent;
|
|
199
|
+
const [, instant, label, tail] = match;
|
|
200
|
+
if (instant === undefined || label === undefined || tail === undefined)
|
|
201
|
+
return absent;
|
|
202
|
+
const at = Date.parse(instant);
|
|
203
|
+
if (Number.isNaN(at))
|
|
204
|
+
return absent;
|
|
205
|
+
const msg = tail.split(FIELDS, 1)[0] ?? tail;
|
|
206
|
+
return { raw, at, level: label.toLowerCase(), msg };
|
|
207
|
+
}
|
|
191
208
|
var noopLogger = {
|
|
192
209
|
debug: () => {},
|
|
193
210
|
info: () => {},
|
|
@@ -234,6 +251,7 @@ function loadConfig(env) {
|
|
|
234
251
|
const derivedBaseUrl = `http://${host}:${port}`;
|
|
235
252
|
const baseUrl = optionalText(env.OMNI_BASE_URL, derivedBaseUrl).replace(/\/+$/, "") || derivedBaseUrl;
|
|
236
253
|
const staticDir = env.OMNI_STATIC_DIR?.trim();
|
|
254
|
+
const logFile = env.OMNI_LOG_FILE?.trim();
|
|
237
255
|
const rawLogLevel = env.OMNI_LOG_LEVEL?.trim();
|
|
238
256
|
const logLevel = parseLogLevel(rawLogLevel);
|
|
239
257
|
return {
|
|
@@ -244,7 +262,8 @@ function loadConfig(env) {
|
|
|
244
262
|
databasePath: optionalText(env.OMNI_DB_PATH, "./omnigateway.db"),
|
|
245
263
|
encryptionKey,
|
|
246
264
|
baseUrl,
|
|
247
|
-
staticDir: staticDir === undefined || staticDir.length === 0 ? null : staticDir
|
|
265
|
+
staticDir: staticDir === undefined || staticDir.length === 0 ? null : staticDir,
|
|
266
|
+
logFile: logFile === undefined || logFile.length === 0 ? null : logFile
|
|
248
267
|
};
|
|
249
268
|
}
|
|
250
269
|
// packages/providers/src/body.ts
|
|
@@ -669,7 +688,7 @@ async function* decodeAnthropic(messages) {
|
|
|
669
688
|
if (cb.type === "text")
|
|
670
689
|
yield { type: "blockStart", index, block: { type: "text" } };
|
|
671
690
|
else if (cb.type === "thinking")
|
|
672
|
-
yield { type: "blockStart", index, block: { type: "thinking" } };
|
|
691
|
+
yield { type: "blockStart", index, block: { type: "thinking", signed: true } };
|
|
673
692
|
else if (cb.type === "tool_use")
|
|
674
693
|
yield {
|
|
675
694
|
type: "blockStart",
|
|
@@ -689,7 +708,7 @@ async function* decodeAnthropic(messages) {
|
|
|
689
708
|
index,
|
|
690
709
|
delta: { type: "thinking", text: delta.thinking ?? "" }
|
|
691
710
|
};
|
|
692
|
-
else if (delta.type === "signature_delta")
|
|
711
|
+
else if (delta.type === "signature_delta" && (delta.signature ?? "") !== "")
|
|
693
712
|
yield {
|
|
694
713
|
type: "blockDelta",
|
|
695
714
|
index,
|
|
@@ -761,6 +780,9 @@ function wireCacheControl(c) {
|
|
|
761
780
|
return {};
|
|
762
781
|
return { cache_control: { type: c.type, ...c.ttl === undefined ? {} : { ttl: c.ttl } } };
|
|
763
782
|
}
|
|
783
|
+
function isReplayableThinking(b) {
|
|
784
|
+
return b.type !== "thinking" || b.signature !== undefined && b.signature !== "";
|
|
785
|
+
}
|
|
764
786
|
function encodeBlock(b) {
|
|
765
787
|
const cache = wireCacheControl(cacheControlOf(b));
|
|
766
788
|
switch (b.type) {
|
|
@@ -790,6 +812,16 @@ function encodeSystemTurn(content) {
|
|
|
790
812
|
return content.flatMap((b) => b.type === "text" ? [b.text] : []).join(`
|
|
791
813
|
`);
|
|
792
814
|
}
|
|
815
|
+
function systemCacheControl(req) {
|
|
816
|
+
const cacheable = req.messages.flatMap((message) => message.content.flatMap((block) => block.type === "thinking" ? [] : [{ role: message.role, block }]));
|
|
817
|
+
const markedSystemBlocks = cacheable.filter(({ role, block }) => role === "system" && cacheControlOf(block) !== undefined);
|
|
818
|
+
const final = markedSystemBlocks.at(-1);
|
|
819
|
+
const promoted = final !== undefined && final.block.type === "text" && cacheable.at(-1) === final ? cacheControlOf(final.block) : undefined;
|
|
820
|
+
return {
|
|
821
|
+
...promoted === undefined ? {} : { promoted },
|
|
822
|
+
lost: markedSystemBlocks.length > (promoted === undefined ? 0 : 1)
|
|
823
|
+
};
|
|
824
|
+
}
|
|
793
825
|
function encodeToolChoice(c) {
|
|
794
826
|
switch (c.type) {
|
|
795
827
|
case "auto":
|
|
@@ -813,18 +845,30 @@ function toWire(req, model, opts) {
|
|
|
813
845
|
system = [{ type: "text", text: OAUTH_IDENTITY }, ...system ?? []];
|
|
814
846
|
note2("anthropic:oauth-system-prefix");
|
|
815
847
|
}
|
|
848
|
+
const systemCache = systemCacheControl(req);
|
|
849
|
+
if (systemCache.lost)
|
|
850
|
+
note2("anthropic:system-turn-cache-control-dropped");
|
|
816
851
|
const body = {
|
|
817
852
|
model,
|
|
818
|
-
messages: req.messages.
|
|
819
|
-
if (m.role !== "system")
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
853
|
+
messages: req.messages.flatMap((m) => {
|
|
854
|
+
if (m.role !== "system") {
|
|
855
|
+
const replayable = m.content.filter(isReplayableThinking);
|
|
856
|
+
if (replayable.length !== m.content.length)
|
|
857
|
+
note2("anthropic:unsigned-thinking-dropped");
|
|
858
|
+
if (replayable.length === 0)
|
|
859
|
+
return [];
|
|
860
|
+
return [{ role: m.role, content: replayable.map(encodeBlock) }];
|
|
861
|
+
}
|
|
862
|
+
return [{ role: m.role, content: encodeSystemTurn(m.content) }];
|
|
825
863
|
}),
|
|
826
864
|
max_tokens: req.maxTokens ?? 4096,
|
|
827
|
-
stream: req.stream
|
|
865
|
+
stream: req.stream,
|
|
866
|
+
...systemCache.promoted === undefined ? {} : {
|
|
867
|
+
cache_control: {
|
|
868
|
+
type: systemCache.promoted.type,
|
|
869
|
+
...systemCache.promoted.ttl === undefined ? {} : { ttl: systemCache.promoted.ttl }
|
|
870
|
+
}
|
|
871
|
+
}
|
|
828
872
|
};
|
|
829
873
|
if (system !== undefined && system.length > 0)
|
|
830
874
|
body.system = system;
|
|
@@ -2181,6 +2225,62 @@ function createConnectFlows(deps) {
|
|
|
2181
2225
|
}
|
|
2182
2226
|
};
|
|
2183
2227
|
}
|
|
2228
|
+
// packages/control/src/console.ts
|
|
2229
|
+
var UNIT_NAME = "omnigateway.service";
|
|
2230
|
+
var MAX_CONSOLE_LINES = 500;
|
|
2231
|
+
var DEFAULT_CONSOLE_LINES = 200;
|
|
2232
|
+
function resolveConsoleSource(input) {
|
|
2233
|
+
const path = input.logFile?.trim();
|
|
2234
|
+
if (path !== undefined && path.length > 0)
|
|
2235
|
+
return { kind: "file", path };
|
|
2236
|
+
if (input.unitInstalled)
|
|
2237
|
+
return { kind: "journal", unit: UNIT_NAME, scope: input.scope };
|
|
2238
|
+
return { kind: "none" };
|
|
2239
|
+
}
|
|
2240
|
+
function consoleLimit(requested) {
|
|
2241
|
+
const value = requested === undefined ? DEFAULT_CONSOLE_LINES : Number(requested);
|
|
2242
|
+
if (!Number.isFinite(value))
|
|
2243
|
+
return DEFAULT_CONSOLE_LINES;
|
|
2244
|
+
return Math.floor(Math.min(Math.max(1, value), MAX_CONSOLE_LINES));
|
|
2245
|
+
}
|
|
2246
|
+
function keep(line, query) {
|
|
2247
|
+
if (query.since !== undefined && (line.at === null || line.at <= query.since))
|
|
2248
|
+
return false;
|
|
2249
|
+
if (query.level === undefined || line.level === null)
|
|
2250
|
+
return true;
|
|
2251
|
+
return LEVELS[line.level] >= LEVELS[query.level];
|
|
2252
|
+
}
|
|
2253
|
+
var SCAN_FACTOR = 20;
|
|
2254
|
+
var SCAN_LIMIT = 5000;
|
|
2255
|
+
function scanWidth(query) {
|
|
2256
|
+
const filtered = query.level !== undefined || query.since !== undefined;
|
|
2257
|
+
return filtered ? Math.min(query.lines * SCAN_FACTOR, SCAN_LIMIT) : query.lines;
|
|
2258
|
+
}
|
|
2259
|
+
async function readSource(deps, source, lines) {
|
|
2260
|
+
if (source.kind === "none")
|
|
2261
|
+
return "";
|
|
2262
|
+
if (source.kind === "file")
|
|
2263
|
+
return deps.readFile(source.path, lines) ?? "";
|
|
2264
|
+
const scope = source.scope === "system" ? [] : ["--user"];
|
|
2265
|
+
const result = await deps.run([
|
|
2266
|
+
"journalctl",
|
|
2267
|
+
...scope,
|
|
2268
|
+
"-u",
|
|
2269
|
+
source.unit,
|
|
2270
|
+
"-n",
|
|
2271
|
+
String(lines),
|
|
2272
|
+
"--no-pager",
|
|
2273
|
+
"--output=cat"
|
|
2274
|
+
]);
|
|
2275
|
+
return result.code === 0 ? result.stdout : "";
|
|
2276
|
+
}
|
|
2277
|
+
async function readConsole(deps, source, query) {
|
|
2278
|
+
const limited = { ...query, lines: consoleLimit(query.lines) };
|
|
2279
|
+
const text = await readSource(deps, source, scanWidth(limited));
|
|
2280
|
+
const lines = text.split(`
|
|
2281
|
+
`).filter((raw) => raw.trim().length > 0).map(parseLine).filter((line) => keep(line, limited)).slice(-limited.lines);
|
|
2282
|
+
return source.kind === "file" ? { source: "file", path: source.path, lines } : { source: source.kind, lines };
|
|
2283
|
+
}
|
|
2184
2284
|
// node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/external.js
|
|
2185
2285
|
var exports_external = {};
|
|
2186
2286
|
__export(exports_external, {
|
|
@@ -18241,6 +18341,50 @@ async function putSettings(store, input) {
|
|
|
18241
18341
|
await store.config.putSettings(settings);
|
|
18242
18342
|
return settings;
|
|
18243
18343
|
}
|
|
18344
|
+
// packages/control/src/tail.ts
|
|
18345
|
+
import { closeSync, fstatSync, openSync, readSync, statSync } from "fs";
|
|
18346
|
+
var CHUNK = 64 * 1024;
|
|
18347
|
+
var MAX_BYTES = 8 * 1024 * 1024;
|
|
18348
|
+
function tailFile(path, lines) {
|
|
18349
|
+
let fd;
|
|
18350
|
+
try {
|
|
18351
|
+
fd = openSync(path, "r");
|
|
18352
|
+
} catch {
|
|
18353
|
+
return null;
|
|
18354
|
+
}
|
|
18355
|
+
try {
|
|
18356
|
+
const size = fstatSync(fd).size;
|
|
18357
|
+
if (size === 0)
|
|
18358
|
+
return "";
|
|
18359
|
+
const budget = Math.min(size, MAX_BYTES);
|
|
18360
|
+
let read = 0;
|
|
18361
|
+
let newlines = 0;
|
|
18362
|
+
const chunks = [];
|
|
18363
|
+
while (read < budget && newlines <= lines) {
|
|
18364
|
+
const span = Math.min(CHUNK, budget - read);
|
|
18365
|
+
const buffer = Buffer.allocUnsafe(span);
|
|
18366
|
+
const position = size - read - span;
|
|
18367
|
+
readSync(fd, buffer, 0, span, position);
|
|
18368
|
+
chunks.unshift(buffer);
|
|
18369
|
+
read += span;
|
|
18370
|
+
for (const byte of buffer)
|
|
18371
|
+
if (byte === 10)
|
|
18372
|
+
newlines++;
|
|
18373
|
+
}
|
|
18374
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
18375
|
+
} catch {
|
|
18376
|
+
return null;
|
|
18377
|
+
} finally {
|
|
18378
|
+
closeSync(fd);
|
|
18379
|
+
}
|
|
18380
|
+
}
|
|
18381
|
+
function fileExists(path) {
|
|
18382
|
+
try {
|
|
18383
|
+
return statSync(path).isFile();
|
|
18384
|
+
} catch {
|
|
18385
|
+
return false;
|
|
18386
|
+
}
|
|
18387
|
+
}
|
|
18244
18388
|
// packages/control/src/usage.ts
|
|
18245
18389
|
var MAX_LOG_LIMIT = 500;
|
|
18246
18390
|
var DEFAULT_LOG_LIMIT = 100;
|
|
@@ -18475,6 +18619,278 @@ async function pollUntilAuthorized(flows, start, deps) {
|
|
|
18475
18619
|
}
|
|
18476
18620
|
}
|
|
18477
18621
|
|
|
18622
|
+
// apps/cli/src/service.ts
|
|
18623
|
+
import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, rmSync, writeFileSync } from "fs";
|
|
18624
|
+
import { homedir as homedir2 } from "os";
|
|
18625
|
+
import { dirname, join as join2 } from "path";
|
|
18626
|
+
var UNIT_NAME2 = "omnigateway.service";
|
|
18627
|
+
function unitPath(scope) {
|
|
18628
|
+
return scope === "system" ? join2("/etc/systemd/system", UNIT_NAME2) : join2(homedir2(), ".config", "systemd", "user", UNIT_NAME2);
|
|
18629
|
+
}
|
|
18630
|
+
function systemctlArgs(scope, args) {
|
|
18631
|
+
return scope === "system" ? ["systemctl", ...args] : ["systemctl", "--user", ...args];
|
|
18632
|
+
}
|
|
18633
|
+
function pidFile(stateDir) {
|
|
18634
|
+
return join2(stateDir, "gateway.pid");
|
|
18635
|
+
}
|
|
18636
|
+
function logFile(stateDir) {
|
|
18637
|
+
return join2(stateDir, "gateway.log");
|
|
18638
|
+
}
|
|
18639
|
+
function supervisedLogFile(deps) {
|
|
18640
|
+
const configured = deps.logFile?.trim();
|
|
18641
|
+
return configured !== undefined && configured.length > 0 ? configured : logFile(deps.stateDir);
|
|
18642
|
+
}
|
|
18643
|
+
function defaultStateDir(env2) {
|
|
18644
|
+
const xdg = env2.XDG_STATE_HOME;
|
|
18645
|
+
const base = typeof xdg === "string" && xdg.length > 0 ? xdg : join2(homedir2(), ".local", "state");
|
|
18646
|
+
return join2(base, "omnigateway");
|
|
18647
|
+
}
|
|
18648
|
+
function unitFile(input) {
|
|
18649
|
+
return `[Unit]
|
|
18650
|
+
Description=${input.description ?? "OmniGateway"}
|
|
18651
|
+
After=network-online.target
|
|
18652
|
+
Wants=network-online.target
|
|
18653
|
+
|
|
18654
|
+
[Service]
|
|
18655
|
+
Type=simple
|
|
18656
|
+
WorkingDirectory=${input.root}
|
|
18657
|
+
EnvironmentFile=${join2(input.root, ".env")}
|
|
18658
|
+
ExecStart=${input.bun} ${input.entrypoint}
|
|
18659
|
+
Restart=on-failure
|
|
18660
|
+
RestartSec=2
|
|
18661
|
+
|
|
18662
|
+
[Install]
|
|
18663
|
+
WantedBy=default.target
|
|
18664
|
+
`;
|
|
18665
|
+
}
|
|
18666
|
+
function unitInstalled(deps) {
|
|
18667
|
+
return existsSync2(deps.unitPath);
|
|
18668
|
+
}
|
|
18669
|
+
function readPid(stateDir) {
|
|
18670
|
+
const file2 = pidFile(stateDir);
|
|
18671
|
+
if (!existsSync2(file2))
|
|
18672
|
+
return null;
|
|
18673
|
+
const pid = Number(readFileSync2(file2, "utf8").trim());
|
|
18674
|
+
return Number.isInteger(pid) && pid > 0 ? pid : null;
|
|
18675
|
+
}
|
|
18676
|
+
function livePid(deps) {
|
|
18677
|
+
const pid = readPid(deps.stateDir);
|
|
18678
|
+
if (pid === null)
|
|
18679
|
+
return null;
|
|
18680
|
+
if (deps.alive(pid))
|
|
18681
|
+
return pid;
|
|
18682
|
+
rmSync(pidFile(deps.stateDir), { force: true });
|
|
18683
|
+
return null;
|
|
18684
|
+
}
|
|
18685
|
+
async function status(deps) {
|
|
18686
|
+
if (unitInstalled(deps)) {
|
|
18687
|
+
const active = await deps.run(systemctlArgs(deps.scope, ["is-active", UNIT_NAME2]));
|
|
18688
|
+
const state = active.stdout.trim() || active.stderr.trim() || "unknown";
|
|
18689
|
+
const shown = await deps.run(systemctlArgs(deps.scope, ["show", UNIT_NAME2, "--property=MainPID", "--value"]));
|
|
18690
|
+
const pid2 = Number(shown.stdout.trim());
|
|
18691
|
+
return {
|
|
18692
|
+
supervisor: "systemd",
|
|
18693
|
+
running: state === "active",
|
|
18694
|
+
pid: Number.isInteger(pid2) && pid2 > 0 ? pid2 : null,
|
|
18695
|
+
state,
|
|
18696
|
+
unitPath: deps.unitPath,
|
|
18697
|
+
logFile: null
|
|
18698
|
+
};
|
|
18699
|
+
}
|
|
18700
|
+
const pid = livePid(deps);
|
|
18701
|
+
return {
|
|
18702
|
+
supervisor: pid === null ? "none" : "pidfile",
|
|
18703
|
+
running: pid !== null,
|
|
18704
|
+
pid,
|
|
18705
|
+
state: null,
|
|
18706
|
+
unitPath: null,
|
|
18707
|
+
logFile: supervisedLogFile(deps)
|
|
18708
|
+
};
|
|
18709
|
+
}
|
|
18710
|
+
async function start(deps, input) {
|
|
18711
|
+
if (unitInstalled(deps)) {
|
|
18712
|
+
const result = await deps.run(systemctlArgs(deps.scope, ["start", UNIT_NAME2]));
|
|
18713
|
+
if (result.code !== 0) {
|
|
18714
|
+
throw new Error(result.stderr.trim() || `systemctl start exited ${result.code}`);
|
|
18715
|
+
}
|
|
18716
|
+
return {
|
|
18717
|
+
supervisor: "systemd",
|
|
18718
|
+
pid: null,
|
|
18719
|
+
healthy: await waitForHealth(deps, input.baseUrl)
|
|
18720
|
+
};
|
|
18721
|
+
}
|
|
18722
|
+
const running = livePid(deps);
|
|
18723
|
+
if (running !== null) {
|
|
18724
|
+
return {
|
|
18725
|
+
supervisor: "pidfile",
|
|
18726
|
+
pid: running,
|
|
18727
|
+
healthy: await waitForHealth(deps, input.baseUrl)
|
|
18728
|
+
};
|
|
18729
|
+
}
|
|
18730
|
+
mkdirSync(deps.stateDir, { recursive: true });
|
|
18731
|
+
const file2 = supervisedLogFile(deps);
|
|
18732
|
+
mkdirSync(dirname(file2), { recursive: true });
|
|
18733
|
+
const pid = deps.spawn({
|
|
18734
|
+
argv: input.argv,
|
|
18735
|
+
cwd: deps.root,
|
|
18736
|
+
env: { ...input.env, OMNI_LOG_FILE: file2 },
|
|
18737
|
+
logFile: file2
|
|
18738
|
+
});
|
|
18739
|
+
writeFileSync(pidFile(deps.stateDir), `${pid}
|
|
18740
|
+
`);
|
|
18741
|
+
return { supervisor: "pidfile", pid, healthy: await waitForHealth(deps, input.baseUrl) };
|
|
18742
|
+
}
|
|
18743
|
+
var HEALTH_TIMEOUT_MS = 1e4;
|
|
18744
|
+
var HEALTH_INTERVAL_MS = 200;
|
|
18745
|
+
async function waitForHealth(deps, baseUrl) {
|
|
18746
|
+
const attempts = Math.ceil(HEALTH_TIMEOUT_MS / HEALTH_INTERVAL_MS);
|
|
18747
|
+
for (let attempt = 0;attempt < attempts; attempt++) {
|
|
18748
|
+
if (await deps.probe(baseUrl))
|
|
18749
|
+
return true;
|
|
18750
|
+
await deps.sleep(HEALTH_INTERVAL_MS);
|
|
18751
|
+
}
|
|
18752
|
+
return false;
|
|
18753
|
+
}
|
|
18754
|
+
var STOP_GRACE_MS = 5000;
|
|
18755
|
+
var STOP_INTERVAL_MS = 100;
|
|
18756
|
+
async function stop(deps) {
|
|
18757
|
+
if (unitInstalled(deps)) {
|
|
18758
|
+
const result = await deps.run(systemctlArgs(deps.scope, ["stop", UNIT_NAME2]));
|
|
18759
|
+
if (result.code !== 0) {
|
|
18760
|
+
throw new Error(result.stderr.trim() || `systemctl stop exited ${result.code}`);
|
|
18761
|
+
}
|
|
18762
|
+
return { supervisor: "systemd", stopped: true };
|
|
18763
|
+
}
|
|
18764
|
+
const pid = livePid(deps);
|
|
18765
|
+
if (pid === null)
|
|
18766
|
+
return { supervisor: "none", stopped: false };
|
|
18767
|
+
deps.kill(pid, "SIGTERM");
|
|
18768
|
+
const attempts = Math.ceil(STOP_GRACE_MS / STOP_INTERVAL_MS);
|
|
18769
|
+
for (let attempt = 0;deps.alive(pid); attempt++) {
|
|
18770
|
+
if (attempt >= attempts) {
|
|
18771
|
+
deps.kill(pid, "SIGKILL");
|
|
18772
|
+
break;
|
|
18773
|
+
}
|
|
18774
|
+
await deps.sleep(STOP_INTERVAL_MS);
|
|
18775
|
+
}
|
|
18776
|
+
rmSync(pidFile(deps.stateDir), { force: true });
|
|
18777
|
+
return { supervisor: "pidfile", stopped: true };
|
|
18778
|
+
}
|
|
18779
|
+
async function install(deps, input) {
|
|
18780
|
+
const path = deps.unitPath;
|
|
18781
|
+
if (existsSync2(path) && !input.force) {
|
|
18782
|
+
throw new Error(`${path} already exists; pass --force to replace it`);
|
|
18783
|
+
}
|
|
18784
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
18785
|
+
writeFileSync(path, unitFile({ root: deps.root, bun: input.bun, entrypoint: input.entrypoint }));
|
|
18786
|
+
const reload = await deps.run(systemctlArgs(deps.scope, ["daemon-reload"]));
|
|
18787
|
+
let enabled = false;
|
|
18788
|
+
if (input.enable) {
|
|
18789
|
+
const result = await deps.run(systemctlArgs(deps.scope, ["enable", UNIT_NAME2]));
|
|
18790
|
+
enabled = result.code === 0;
|
|
18791
|
+
}
|
|
18792
|
+
return { path, reloaded: reload.code === 0, enabled };
|
|
18793
|
+
}
|
|
18794
|
+
async function uninstall(deps) {
|
|
18795
|
+
const path = deps.unitPath;
|
|
18796
|
+
if (!existsSync2(path))
|
|
18797
|
+
return { path, removed: false };
|
|
18798
|
+
await deps.run(systemctlArgs(deps.scope, ["disable", "--now", UNIT_NAME2]));
|
|
18799
|
+
rmSync(path, { force: true });
|
|
18800
|
+
await deps.run(systemctlArgs(deps.scope, ["daemon-reload"]));
|
|
18801
|
+
return { path, removed: true };
|
|
18802
|
+
}
|
|
18803
|
+
function consoleSource(deps) {
|
|
18804
|
+
const configured = deps.logFile?.trim();
|
|
18805
|
+
const chosen = configured !== undefined && configured.length > 0 && fileExists(configured) ? configured : unitInstalled(deps) ? undefined : fileExists(supervisedLogFile(deps)) ? supervisedLogFile(deps) : undefined;
|
|
18806
|
+
return {
|
|
18807
|
+
source: resolveConsoleSource({
|
|
18808
|
+
...chosen === undefined ? {} : { logFile: chosen },
|
|
18809
|
+
unitInstalled: unitInstalled(deps),
|
|
18810
|
+
scope: deps.scope
|
|
18811
|
+
}),
|
|
18812
|
+
deps: {
|
|
18813
|
+
readFile: (path, lines) => tailFile(path, lines),
|
|
18814
|
+
run: deps.run
|
|
18815
|
+
}
|
|
18816
|
+
};
|
|
18817
|
+
}
|
|
18818
|
+
async function serviceLogs(deps, lines) {
|
|
18819
|
+
const { source, deps: readDeps } = consoleSource(deps);
|
|
18820
|
+
const read = await readConsole(readDeps, source, { lines });
|
|
18821
|
+
return read.lines.map((line) => line.raw).join(`
|
|
18822
|
+
`);
|
|
18823
|
+
}
|
|
18824
|
+
|
|
18825
|
+
// apps/cli/src/commands/console.ts
|
|
18826
|
+
var FOLLOW_INTERVAL_MS = 2000;
|
|
18827
|
+
var LEVEL_TONE = {
|
|
18828
|
+
debug: "dim",
|
|
18829
|
+
warn: "yellow",
|
|
18830
|
+
error: "red"
|
|
18831
|
+
};
|
|
18832
|
+
function render(ctx, lines) {
|
|
18833
|
+
return lines.map((line) => {
|
|
18834
|
+
const tone = line.level === null ? undefined : LEVEL_TONE[line.level];
|
|
18835
|
+
return tone === undefined ? line.raw : paint(ctx, tone, line.raw);
|
|
18836
|
+
}).join(`
|
|
18837
|
+
`);
|
|
18838
|
+
}
|
|
18839
|
+
function sourceHint(source) {
|
|
18840
|
+
if (source.kind === "file")
|
|
18841
|
+
return `${source.path} (named by OMNI_LOG_FILE)`;
|
|
18842
|
+
if (source.kind === "journal")
|
|
18843
|
+
return `systemd journal for ${source.unit}`;
|
|
18844
|
+
return "not captured \u2014 run under systemd, or start it with `omni start`";
|
|
18845
|
+
}
|
|
18846
|
+
function empty(source) {
|
|
18847
|
+
if (source.kind !== "none")
|
|
18848
|
+
return `no output yet in ${sourceHint(source)}`;
|
|
18849
|
+
return [
|
|
18850
|
+
"this gateway's output is not being captured, so there is nothing to show.",
|
|
18851
|
+
"run it in the foreground and its output goes to your terminal instead.",
|
|
18852
|
+
"to capture it: `omni service install`, or `omni start`, which redirects",
|
|
18853
|
+
"output to a file and points OMNI_LOG_FILE at it."
|
|
18854
|
+
].join(`
|
|
18855
|
+
`);
|
|
18856
|
+
}
|
|
18857
|
+
var console_ = {
|
|
18858
|
+
usage: "console [-n N] [--follow] [--level debug|info|warn|error]",
|
|
18859
|
+
summary: "Show the gateway process's own output",
|
|
18860
|
+
options: {
|
|
18861
|
+
number: { type: "string", short: "n" },
|
|
18862
|
+
follow: { type: "boolean" },
|
|
18863
|
+
level: { type: "string" },
|
|
18864
|
+
system: { type: "boolean" }
|
|
18865
|
+
},
|
|
18866
|
+
async run(args, { ctx, writer, service }) {
|
|
18867
|
+
const lines = numberFlag(args.values, "number") ?? 50;
|
|
18868
|
+
const rawLevel = stringFlag(args.values, "level");
|
|
18869
|
+
const level = parseLogLevel(rawLevel);
|
|
18870
|
+
if (rawLevel !== undefined && level === null) {
|
|
18871
|
+
throw new UsageError(`unknown level "${rawLevel}"; use debug, info, warn or error`);
|
|
18872
|
+
}
|
|
18873
|
+
const { source, deps } = consoleSource(service());
|
|
18874
|
+
const query = { lines, ...level === null ? {} : { level } };
|
|
18875
|
+
const first = await readConsole(deps, source, query);
|
|
18876
|
+
emit(ctx, writer, first, () => first.lines.length === 0 ? empty(source) : render(ctx, first.lines));
|
|
18877
|
+
if (!ctx.json && first.lines.length > 0) {
|
|
18878
|
+
note(ctx, writer, paint(ctx, "dim", `reading ${sourceHint(source)}`));
|
|
18879
|
+
}
|
|
18880
|
+
if (boolFlag(args.values, "follow") !== true || ctx.json)
|
|
18881
|
+
return;
|
|
18882
|
+
let seen = first.lines.at(-1)?.at ?? 0;
|
|
18883
|
+
for (;; ) {
|
|
18884
|
+
await Bun.sleep(FOLLOW_INTERVAL_MS);
|
|
18885
|
+
const next = await readConsole(deps, source, { ...query, since: seen });
|
|
18886
|
+
if (next.lines.length === 0)
|
|
18887
|
+
continue;
|
|
18888
|
+
seen = next.lines.at(-1)?.at ?? seen;
|
|
18889
|
+
writer.out(render(ctx, next.lines));
|
|
18890
|
+
}
|
|
18891
|
+
}
|
|
18892
|
+
};
|
|
18893
|
+
|
|
18478
18894
|
// apps/cli/src/command.ts
|
|
18479
18895
|
var PROVIDER_TONE = {
|
|
18480
18896
|
anthropic: "magenta",
|
|
@@ -18515,7 +18931,7 @@ var credentialsList = {
|
|
|
18515
18931
|
{ header: "STATE" },
|
|
18516
18932
|
{ header: "EXPIRES" }
|
|
18517
18933
|
], credentials.map((c) => {
|
|
18518
|
-
const
|
|
18934
|
+
const status2 = condition(c);
|
|
18519
18935
|
return [
|
|
18520
18936
|
c.id,
|
|
18521
18937
|
provider(ctx, c.provider),
|
|
@@ -18523,7 +18939,7 @@ var credentialsList = {
|
|
|
18523
18939
|
c.authType,
|
|
18524
18940
|
String(c.tier),
|
|
18525
18941
|
String(c.weight),
|
|
18526
|
-
state(ctx,
|
|
18942
|
+
state(ctx, status2.ok, status2.text),
|
|
18527
18943
|
formatTime(c.expiresAt)
|
|
18528
18944
|
];
|
|
18529
18945
|
}));
|
|
@@ -18539,7 +18955,7 @@ var credentialsShow = {
|
|
|
18539
18955
|
async run(args, { ctx, writer }) {
|
|
18540
18956
|
const id = requirePositional(args, 0, "credential id");
|
|
18541
18957
|
const credential = await findCredential(ctx, id);
|
|
18542
|
-
const
|
|
18958
|
+
const status2 = condition(credential);
|
|
18543
18959
|
const data = {
|
|
18544
18960
|
id: credential.id,
|
|
18545
18961
|
provider: credential.provider,
|
|
@@ -18562,7 +18978,7 @@ var credentialsShow = {
|
|
|
18562
18978
|
["provider", provider(ctx, credential.provider)],
|
|
18563
18979
|
["label", credential.label],
|
|
18564
18980
|
["auth", credential.authType],
|
|
18565
|
-
["state", state(ctx,
|
|
18981
|
+
["state", state(ctx, status2.ok, status2.text)],
|
|
18566
18982
|
["tier", String(credential.tier)],
|
|
18567
18983
|
["weight", String(credential.weight)],
|
|
18568
18984
|
["account", credential.accountEmail ?? "\u2014"],
|
|
@@ -18697,12 +19113,12 @@ var credentialsHealth = {
|
|
|
18697
19113
|
};
|
|
18698
19114
|
|
|
18699
19115
|
// apps/cli/src/commands/db.ts
|
|
18700
|
-
import { existsSync as
|
|
19116
|
+
import { existsSync as existsSync3 } from "fs";
|
|
18701
19117
|
var dbMigrate = {
|
|
18702
19118
|
usage: "db migrate",
|
|
18703
19119
|
summary: "Create or upgrade the database schema",
|
|
18704
19120
|
async run(_args, { ctx, writer }) {
|
|
18705
|
-
const existed =
|
|
19121
|
+
const existed = existsSync3(ctx.databasePath);
|
|
18706
19122
|
const store = await ctx.store();
|
|
18707
19123
|
await store.config.getSettings();
|
|
18708
19124
|
emit(ctx, writer, { path: ctx.databasePath, created: !existed }, () => fields([
|
|
@@ -19030,207 +19446,8 @@ ${candidates}${excluded}`;
|
|
|
19030
19446
|
import { existsSync as existsSync5 } from "fs";
|
|
19031
19447
|
|
|
19032
19448
|
// apps/cli/src/runtime.ts
|
|
19033
|
-
import { closeSync, existsSync as existsSync4, openSync } from "fs";
|
|
19449
|
+
import { closeSync as closeSync2, existsSync as existsSync4, openSync as openSync2 } from "fs";
|
|
19034
19450
|
import { join as join3 } from "path";
|
|
19035
|
-
|
|
19036
|
-
// apps/cli/src/service.ts
|
|
19037
|
-
import { existsSync as existsSync3, mkdirSync, readFileSync as readFileSync2, rmSync, writeFileSync } from "fs";
|
|
19038
|
-
import { homedir as homedir2 } from "os";
|
|
19039
|
-
import { dirname, join as join2 } from "path";
|
|
19040
|
-
var UNIT_NAME = "omnigateway.service";
|
|
19041
|
-
function unitPath(scope) {
|
|
19042
|
-
return scope === "system" ? join2("/etc/systemd/system", UNIT_NAME) : join2(homedir2(), ".config", "systemd", "user", UNIT_NAME);
|
|
19043
|
-
}
|
|
19044
|
-
function systemctlArgs(scope, args) {
|
|
19045
|
-
return scope === "system" ? ["systemctl", ...args] : ["systemctl", "--user", ...args];
|
|
19046
|
-
}
|
|
19047
|
-
function pidFile(stateDir) {
|
|
19048
|
-
return join2(stateDir, "gateway.pid");
|
|
19049
|
-
}
|
|
19050
|
-
function logFile(stateDir) {
|
|
19051
|
-
return join2(stateDir, "gateway.log");
|
|
19052
|
-
}
|
|
19053
|
-
function defaultStateDir(env2) {
|
|
19054
|
-
const xdg = env2.XDG_STATE_HOME;
|
|
19055
|
-
const base = typeof xdg === "string" && xdg.length > 0 ? xdg : join2(homedir2(), ".local", "state");
|
|
19056
|
-
return join2(base, "omnigateway");
|
|
19057
|
-
}
|
|
19058
|
-
function unitFile(input) {
|
|
19059
|
-
return `[Unit]
|
|
19060
|
-
Description=${input.description ?? "OmniGateway"}
|
|
19061
|
-
After=network-online.target
|
|
19062
|
-
Wants=network-online.target
|
|
19063
|
-
|
|
19064
|
-
[Service]
|
|
19065
|
-
Type=simple
|
|
19066
|
-
WorkingDirectory=${input.root}
|
|
19067
|
-
EnvironmentFile=${join2(input.root, ".env")}
|
|
19068
|
-
ExecStart=${input.bun} ${input.entrypoint}
|
|
19069
|
-
Restart=on-failure
|
|
19070
|
-
RestartSec=2
|
|
19071
|
-
|
|
19072
|
-
[Install]
|
|
19073
|
-
WantedBy=default.target
|
|
19074
|
-
`;
|
|
19075
|
-
}
|
|
19076
|
-
function unitInstalled(deps) {
|
|
19077
|
-
return existsSync3(deps.unitPath);
|
|
19078
|
-
}
|
|
19079
|
-
function readPid(stateDir) {
|
|
19080
|
-
const file2 = pidFile(stateDir);
|
|
19081
|
-
if (!existsSync3(file2))
|
|
19082
|
-
return null;
|
|
19083
|
-
const pid = Number(readFileSync2(file2, "utf8").trim());
|
|
19084
|
-
return Number.isInteger(pid) && pid > 0 ? pid : null;
|
|
19085
|
-
}
|
|
19086
|
-
function livePid(deps) {
|
|
19087
|
-
const pid = readPid(deps.stateDir);
|
|
19088
|
-
if (pid === null)
|
|
19089
|
-
return null;
|
|
19090
|
-
if (deps.alive(pid))
|
|
19091
|
-
return pid;
|
|
19092
|
-
rmSync(pidFile(deps.stateDir), { force: true });
|
|
19093
|
-
return null;
|
|
19094
|
-
}
|
|
19095
|
-
async function status(deps) {
|
|
19096
|
-
if (unitInstalled(deps)) {
|
|
19097
|
-
const active = await deps.run(systemctlArgs(deps.scope, ["is-active", UNIT_NAME]));
|
|
19098
|
-
const state2 = active.stdout.trim() || active.stderr.trim() || "unknown";
|
|
19099
|
-
const shown = await deps.run(systemctlArgs(deps.scope, ["show", UNIT_NAME, "--property=MainPID", "--value"]));
|
|
19100
|
-
const pid2 = Number(shown.stdout.trim());
|
|
19101
|
-
return {
|
|
19102
|
-
supervisor: "systemd",
|
|
19103
|
-
running: state2 === "active",
|
|
19104
|
-
pid: Number.isInteger(pid2) && pid2 > 0 ? pid2 : null,
|
|
19105
|
-
state: state2,
|
|
19106
|
-
unitPath: deps.unitPath,
|
|
19107
|
-
logFile: null
|
|
19108
|
-
};
|
|
19109
|
-
}
|
|
19110
|
-
const pid = livePid(deps);
|
|
19111
|
-
return {
|
|
19112
|
-
supervisor: pid === null ? "none" : "pidfile",
|
|
19113
|
-
running: pid !== null,
|
|
19114
|
-
pid,
|
|
19115
|
-
state: null,
|
|
19116
|
-
unitPath: null,
|
|
19117
|
-
logFile: logFile(deps.stateDir)
|
|
19118
|
-
};
|
|
19119
|
-
}
|
|
19120
|
-
async function start(deps, input) {
|
|
19121
|
-
if (unitInstalled(deps)) {
|
|
19122
|
-
const result = await deps.run(systemctlArgs(deps.scope, ["start", UNIT_NAME]));
|
|
19123
|
-
if (result.code !== 0) {
|
|
19124
|
-
throw new Error(result.stderr.trim() || `systemctl start exited ${result.code}`);
|
|
19125
|
-
}
|
|
19126
|
-
return {
|
|
19127
|
-
supervisor: "systemd",
|
|
19128
|
-
pid: null,
|
|
19129
|
-
healthy: await waitForHealth(deps, input.baseUrl)
|
|
19130
|
-
};
|
|
19131
|
-
}
|
|
19132
|
-
const running = livePid(deps);
|
|
19133
|
-
if (running !== null) {
|
|
19134
|
-
return {
|
|
19135
|
-
supervisor: "pidfile",
|
|
19136
|
-
pid: running,
|
|
19137
|
-
healthy: await waitForHealth(deps, input.baseUrl)
|
|
19138
|
-
};
|
|
19139
|
-
}
|
|
19140
|
-
mkdirSync(deps.stateDir, { recursive: true });
|
|
19141
|
-
const pid = deps.spawn({
|
|
19142
|
-
argv: input.argv,
|
|
19143
|
-
cwd: deps.root,
|
|
19144
|
-
env: input.env,
|
|
19145
|
-
logFile: logFile(deps.stateDir)
|
|
19146
|
-
});
|
|
19147
|
-
writeFileSync(pidFile(deps.stateDir), `${pid}
|
|
19148
|
-
`);
|
|
19149
|
-
return { supervisor: "pidfile", pid, healthy: await waitForHealth(deps, input.baseUrl) };
|
|
19150
|
-
}
|
|
19151
|
-
var HEALTH_TIMEOUT_MS = 1e4;
|
|
19152
|
-
var HEALTH_INTERVAL_MS = 200;
|
|
19153
|
-
async function waitForHealth(deps, baseUrl) {
|
|
19154
|
-
const attempts = Math.ceil(HEALTH_TIMEOUT_MS / HEALTH_INTERVAL_MS);
|
|
19155
|
-
for (let attempt = 0;attempt < attempts; attempt++) {
|
|
19156
|
-
if (await deps.probe(baseUrl))
|
|
19157
|
-
return true;
|
|
19158
|
-
await deps.sleep(HEALTH_INTERVAL_MS);
|
|
19159
|
-
}
|
|
19160
|
-
return false;
|
|
19161
|
-
}
|
|
19162
|
-
var STOP_GRACE_MS = 5000;
|
|
19163
|
-
var STOP_INTERVAL_MS = 100;
|
|
19164
|
-
async function stop(deps) {
|
|
19165
|
-
if (unitInstalled(deps)) {
|
|
19166
|
-
const result = await deps.run(systemctlArgs(deps.scope, ["stop", UNIT_NAME]));
|
|
19167
|
-
if (result.code !== 0) {
|
|
19168
|
-
throw new Error(result.stderr.trim() || `systemctl stop exited ${result.code}`);
|
|
19169
|
-
}
|
|
19170
|
-
return { supervisor: "systemd", stopped: true };
|
|
19171
|
-
}
|
|
19172
|
-
const pid = livePid(deps);
|
|
19173
|
-
if (pid === null)
|
|
19174
|
-
return { supervisor: "none", stopped: false };
|
|
19175
|
-
deps.kill(pid, "SIGTERM");
|
|
19176
|
-
const attempts = Math.ceil(STOP_GRACE_MS / STOP_INTERVAL_MS);
|
|
19177
|
-
for (let attempt = 0;deps.alive(pid); attempt++) {
|
|
19178
|
-
if (attempt >= attempts) {
|
|
19179
|
-
deps.kill(pid, "SIGKILL");
|
|
19180
|
-
break;
|
|
19181
|
-
}
|
|
19182
|
-
await deps.sleep(STOP_INTERVAL_MS);
|
|
19183
|
-
}
|
|
19184
|
-
rmSync(pidFile(deps.stateDir), { force: true });
|
|
19185
|
-
return { supervisor: "pidfile", stopped: true };
|
|
19186
|
-
}
|
|
19187
|
-
async function install(deps, input) {
|
|
19188
|
-
const path = deps.unitPath;
|
|
19189
|
-
if (existsSync3(path) && !input.force) {
|
|
19190
|
-
throw new Error(`${path} already exists; pass --force to replace it`);
|
|
19191
|
-
}
|
|
19192
|
-
mkdirSync(dirname(path), { recursive: true });
|
|
19193
|
-
writeFileSync(path, unitFile({ root: deps.root, bun: input.bun, entrypoint: input.entrypoint }));
|
|
19194
|
-
const reload = await deps.run(systemctlArgs(deps.scope, ["daemon-reload"]));
|
|
19195
|
-
let enabled = false;
|
|
19196
|
-
if (input.enable) {
|
|
19197
|
-
const result = await deps.run(systemctlArgs(deps.scope, ["enable", UNIT_NAME]));
|
|
19198
|
-
enabled = result.code === 0;
|
|
19199
|
-
}
|
|
19200
|
-
return { path, reloaded: reload.code === 0, enabled };
|
|
19201
|
-
}
|
|
19202
|
-
async function uninstall(deps) {
|
|
19203
|
-
const path = deps.unitPath;
|
|
19204
|
-
if (!existsSync3(path))
|
|
19205
|
-
return { path, removed: false };
|
|
19206
|
-
await deps.run(systemctlArgs(deps.scope, ["disable", "--now", UNIT_NAME]));
|
|
19207
|
-
rmSync(path, { force: true });
|
|
19208
|
-
await deps.run(systemctlArgs(deps.scope, ["daemon-reload"]));
|
|
19209
|
-
return { path, removed: true };
|
|
19210
|
-
}
|
|
19211
|
-
async function serviceLogs(deps, lines) {
|
|
19212
|
-
if (unitInstalled(deps)) {
|
|
19213
|
-
const args = deps.scope === "system" ? [] : ["--user"];
|
|
19214
|
-
const result = await deps.run([
|
|
19215
|
-
"journalctl",
|
|
19216
|
-
...args,
|
|
19217
|
-
"-u",
|
|
19218
|
-
UNIT_NAME,
|
|
19219
|
-
"-n",
|
|
19220
|
-
String(lines),
|
|
19221
|
-
"--no-pager"
|
|
19222
|
-
]);
|
|
19223
|
-
return result.stdout.trimEnd();
|
|
19224
|
-
}
|
|
19225
|
-
const file2 = logFile(deps.stateDir);
|
|
19226
|
-
if (!existsSync3(file2))
|
|
19227
|
-
return "";
|
|
19228
|
-
return readFileSync2(file2, "utf8").split(`
|
|
19229
|
-
`).slice(-lines).join(`
|
|
19230
|
-
`).trimEnd();
|
|
19231
|
-
}
|
|
19232
|
-
|
|
19233
|
-
// apps/cli/src/runtime.ts
|
|
19234
19451
|
var runCommand = async (argv) => {
|
|
19235
19452
|
const proc = Bun.spawn([...argv], { stdout: "pipe", stderr: "pipe" });
|
|
19236
19453
|
const [stdout, stderr, code] = await Promise.all([
|
|
@@ -19241,7 +19458,7 @@ var runCommand = async (argv) => {
|
|
|
19241
19458
|
return { code, stdout, stderr };
|
|
19242
19459
|
};
|
|
19243
19460
|
var spawnDetached = ({ argv, cwd, env: env2, logFile: logFile2 }) => {
|
|
19244
|
-
const fd =
|
|
19461
|
+
const fd = openSync2(logFile2, "a");
|
|
19245
19462
|
try {
|
|
19246
19463
|
const proc = Bun.spawn([...argv], {
|
|
19247
19464
|
cwd,
|
|
@@ -19253,7 +19470,7 @@ var spawnDetached = ({ argv, cwd, env: env2, logFile: logFile2 }) => {
|
|
|
19253
19470
|
proc.unref();
|
|
19254
19471
|
return proc.pid;
|
|
19255
19472
|
} finally {
|
|
19256
|
-
|
|
19473
|
+
closeSync2(fd);
|
|
19257
19474
|
}
|
|
19258
19475
|
};
|
|
19259
19476
|
async function runForeground(input) {
|
|
@@ -19294,11 +19511,13 @@ function gatewayEntrypoint(root, cliDir = import.meta.dir) {
|
|
|
19294
19511
|
return candidates.find((path) => existsSync4(path)) ?? null;
|
|
19295
19512
|
}
|
|
19296
19513
|
function createServiceDeps(input) {
|
|
19514
|
+
const logFile2 = input.env.OMNI_LOG_FILE?.trim();
|
|
19297
19515
|
return {
|
|
19298
19516
|
root: input.root,
|
|
19299
19517
|
stateDir: defaultStateDir(input.env),
|
|
19300
19518
|
scope: input.scope,
|
|
19301
19519
|
unitPath: unitPath(input.scope),
|
|
19520
|
+
...logFile2 === undefined || logFile2.length === 0 ? {} : { logFile: logFile2 },
|
|
19302
19521
|
run: runCommand,
|
|
19303
19522
|
spawn: spawnDetached,
|
|
19304
19523
|
probe: probeHealth,
|
|
@@ -19341,7 +19560,7 @@ var start2 = {
|
|
|
19341
19560
|
emit(ctx, writer, result, () => {
|
|
19342
19561
|
const how = result.supervisor === "systemd" ? "systemd" : `pid ${result.pid}`;
|
|
19343
19562
|
if (!result.healthy) {
|
|
19344
|
-
const where = result.supervisor === "systemd" ? "journalctl -u omnigateway.service" :
|
|
19563
|
+
const where = result.supervisor === "systemd" ? "journalctl -u omnigateway.service" : supervisedLogFile(deps);
|
|
19345
19564
|
return `${state(ctx, false, "started but /health never answered")} (${how}); see ${where}`;
|
|
19346
19565
|
}
|
|
19347
19566
|
return `${state(ctx, true, "running")} (${how}) at ${baseUrl}`;
|
|
@@ -19434,7 +19653,8 @@ var doctor = {
|
|
|
19434
19653
|
gatewayEntrypoint: gatewayEntrypoint(deps.root),
|
|
19435
19654
|
unitInstalled: unit,
|
|
19436
19655
|
supervisor: status2.supervisor,
|
|
19437
|
-
running: status2.running
|
|
19656
|
+
running: status2.running,
|
|
19657
|
+
consoleSource: consoleSource(deps).source
|
|
19438
19658
|
};
|
|
19439
19659
|
emit(ctx, writer, checks3, () => {
|
|
19440
19660
|
const ok = (value, text) => state(ctx, value, text);
|
|
@@ -19449,7 +19669,8 @@ var doctor = {
|
|
|
19449
19669
|
["config", checks3.configError === null ? ok(true, "ok") : ok(false, checks3.configError)],
|
|
19450
19670
|
["entrypoint", checks3.gatewayEntrypoint ?? ok(false, "not found")],
|
|
19451
19671
|
["systemd unit", unit ? deps.scope : paint(ctx, "dim", "none")],
|
|
19452
|
-
["gateway", ok(status2.running, status2.running ? "running" : "stopped")]
|
|
19672
|
+
["gateway", ok(status2.running, status2.running ? "running" : "stopped")],
|
|
19673
|
+
["console log", sourceHint(checks3.consoleSource)]
|
|
19453
19674
|
]);
|
|
19454
19675
|
});
|
|
19455
19676
|
}
|
|
@@ -19653,11 +19874,12 @@ var usage = {
|
|
|
19653
19874
|
};
|
|
19654
19875
|
var logs = {
|
|
19655
19876
|
usage: "logs [-n N] [--follow] [--service]",
|
|
19656
|
-
summary: "Show recent requests
|
|
19877
|
+
summary: "Show recent requests (--service is an alias for `omni console`)",
|
|
19657
19878
|
options: {
|
|
19658
19879
|
number: { type: "string", short: "n" },
|
|
19659
19880
|
follow: { type: "boolean" },
|
|
19660
|
-
service: { type: "boolean" }
|
|
19881
|
+
service: { type: "boolean" },
|
|
19882
|
+
system: { type: "boolean" }
|
|
19661
19883
|
},
|
|
19662
19884
|
async run(args, { ctx, writer, service }) {
|
|
19663
19885
|
const limit = numberFlag(args.values, "number") ?? 20;
|
|
@@ -19667,7 +19889,7 @@ var logs = {
|
|
|
19667
19889
|
return;
|
|
19668
19890
|
}
|
|
19669
19891
|
const store = await ctx.store();
|
|
19670
|
-
const
|
|
19892
|
+
const render2 = (rows) => table([
|
|
19671
19893
|
{ header: "AT" },
|
|
19672
19894
|
{ header: "MODEL" },
|
|
19673
19895
|
{ header: "RESOLVED" },
|
|
@@ -19685,7 +19907,7 @@ var logs = {
|
|
|
19685
19907
|
String(row.durationMs)
|
|
19686
19908
|
]));
|
|
19687
19909
|
const first = await recentLogs(store, limit);
|
|
19688
|
-
emit(ctx, writer, { logs: first }, () => first.length === 0 ? "no requests logged yet" :
|
|
19910
|
+
emit(ctx, writer, { logs: first }, () => first.length === 0 ? "no requests logged yet" : render2(first));
|
|
19689
19911
|
if (args.values.follow !== true || ctx.json)
|
|
19690
19912
|
return;
|
|
19691
19913
|
let seen = first[0]?.at ?? 0;
|
|
@@ -19695,7 +19917,7 @@ var logs = {
|
|
|
19695
19917
|
if (next.length === 0)
|
|
19696
19918
|
continue;
|
|
19697
19919
|
seen = next[0]?.at ?? seen;
|
|
19698
|
-
writer.out(
|
|
19920
|
+
writer.out(render2(next.reverse()));
|
|
19699
19921
|
}
|
|
19700
19922
|
}
|
|
19701
19923
|
};
|
|
@@ -19708,6 +19930,7 @@ var COMMANDS = {
|
|
|
19708
19930
|
restart,
|
|
19709
19931
|
doctor,
|
|
19710
19932
|
logs,
|
|
19933
|
+
console: console_,
|
|
19711
19934
|
usage,
|
|
19712
19935
|
connect,
|
|
19713
19936
|
"service install": serviceInstall,
|
|
@@ -19770,7 +19993,10 @@ function resolveCommand(argv) {
|
|
|
19770
19993
|
|
|
19771
19994
|
// apps/cli/src/help.ts
|
|
19772
19995
|
var GROUPS = [
|
|
19773
|
-
{
|
|
19996
|
+
{
|
|
19997
|
+
title: "Gateway",
|
|
19998
|
+
prefixes: ["status", "start", "stop", "restart", "doctor", "logs", "console"]
|
|
19999
|
+
},
|
|
19774
20000
|
{ title: "Service", prefixes: ["service "] },
|
|
19775
20001
|
{ title: "Accounts", prefixes: ["connect", "credentials "] },
|
|
19776
20002
|
{ title: "Models", prefixes: ["models "] },
|