@automagik/omni 2.260520.9 → 2.260520.11
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.js +343 -148
- package/dist/lib/canonical-pgserve.d.ts.map +1 -1
- package/dist/lib/pgserve-transport.d.ts +16 -12
- package/dist/lib/pgserve-transport.d.ts.map +1 -1
- package/dist/lib/role-cutover.d.ts +92 -0
- package/dist/lib/role-cutover.d.ts.map +1 -0
- package/dist/runtime-env.d.ts +9 -0
- package/dist/runtime-env.d.ts.map +1 -1
- package/dist/server/index.js +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -22772,7 +22772,7 @@ var require_node_transport = __commonJS((exports) => {
|
|
|
22772
22772
|
var util_1 = require_util();
|
|
22773
22773
|
var tls_1 = __require("tls");
|
|
22774
22774
|
var { resolve: resolve2 } = __require("path");
|
|
22775
|
-
var { readFile, existsSync:
|
|
22775
|
+
var { readFile, existsSync: existsSync12 } = __require("fs");
|
|
22776
22776
|
var dns = __require("dns");
|
|
22777
22777
|
var VERSION2 = "2.29.3";
|
|
22778
22778
|
var LANG = "nats.js";
|
|
@@ -22888,7 +22888,7 @@ var require_node_transport = __commonJS((exports) => {
|
|
|
22888
22888
|
const d = (0, nats_base_client_1.deferred)();
|
|
22889
22889
|
try {
|
|
22890
22890
|
fn = resolve2(fn);
|
|
22891
|
-
if (!
|
|
22891
|
+
if (!existsSync12(fn)) {
|
|
22892
22892
|
d.reject(new Error(`${fn} doesn't exist`));
|
|
22893
22893
|
}
|
|
22894
22894
|
readFile(fn, (err, data2) => {
|
|
@@ -61931,8 +61931,8 @@ var init_a2a_provider = __esm(() => {
|
|
|
61931
61931
|
|
|
61932
61932
|
// ../core/src/providers/nats-genie-provider.ts
|
|
61933
61933
|
import { mkdir, writeFile } from "fs/promises";
|
|
61934
|
-
import { homedir as
|
|
61935
|
-
import { join as
|
|
61934
|
+
import { homedir as homedir9 } from "os";
|
|
61935
|
+
import { join as join15 } from "path";
|
|
61936
61936
|
|
|
61937
61937
|
class NatsGenieProvider {
|
|
61938
61938
|
id;
|
|
@@ -62122,10 +62122,10 @@ class NatsGenieProvider {
|
|
|
62122
62122
|
}
|
|
62123
62123
|
async writeDeadLetter(payload, error2) {
|
|
62124
62124
|
try {
|
|
62125
|
-
const dlDir =
|
|
62125
|
+
const dlDir = join15(homedir9(), ".omni", "dead-letters");
|
|
62126
62126
|
await mkdir(dlDir, { recursive: true });
|
|
62127
62127
|
const filename = `nats-genie-${Date.now()}-${payload.chatId}.json`;
|
|
62128
|
-
await writeFile(
|
|
62128
|
+
await writeFile(join15(dlDir, filename), JSON.stringify({
|
|
62129
62129
|
payload,
|
|
62130
62130
|
error: error2 instanceof Error ? error2.message : String(error2),
|
|
62131
62131
|
timestamp: new Date().toISOString()
|
|
@@ -64004,7 +64004,7 @@ var init_sql = __esm(() => {
|
|
|
64004
64004
|
return new SQL([new StringChunk(str)]);
|
|
64005
64005
|
}
|
|
64006
64006
|
sql2.raw = raw2;
|
|
64007
|
-
function
|
|
64007
|
+
function join16(chunks, separator) {
|
|
64008
64008
|
const result = [];
|
|
64009
64009
|
for (const [i6, chunk] of chunks.entries()) {
|
|
64010
64010
|
if (i6 > 0 && separator !== undefined) {
|
|
@@ -64014,7 +64014,7 @@ var init_sql = __esm(() => {
|
|
|
64014
64014
|
}
|
|
64015
64015
|
return new SQL(result);
|
|
64016
64016
|
}
|
|
64017
|
-
sql2.join =
|
|
64017
|
+
sql2.join = join16;
|
|
64018
64018
|
function identifier(value) {
|
|
64019
64019
|
return new Name(value);
|
|
64020
64020
|
}
|
|
@@ -67241,7 +67241,7 @@ var init_select2 = __esm(() => {
|
|
|
67241
67241
|
return (table2, on) => {
|
|
67242
67242
|
const baseTableName = this.tableName;
|
|
67243
67243
|
const tableName = getTableLikeName(table2);
|
|
67244
|
-
if (typeof tableName === "string" && this.config.joins?.some((
|
|
67244
|
+
if (typeof tableName === "string" && this.config.joins?.some((join16) => join16.alias === tableName)) {
|
|
67245
67245
|
throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
67246
67246
|
}
|
|
67247
67247
|
if (!this.isPartialSelect) {
|
|
@@ -67752,7 +67752,7 @@ var init_update = __esm(() => {
|
|
|
67752
67752
|
createJoin(joinType) {
|
|
67753
67753
|
return (table2, on) => {
|
|
67754
67754
|
const tableName = getTableLikeName(table2);
|
|
67755
|
-
if (typeof tableName === "string" && this.config.joins.some((
|
|
67755
|
+
if (typeof tableName === "string" && this.config.joins.some((join16) => join16.alias === tableName)) {
|
|
67756
67756
|
throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
67757
67757
|
}
|
|
67758
67758
|
if (typeof on === "function") {
|
|
@@ -67802,10 +67802,10 @@ var init_update = __esm(() => {
|
|
|
67802
67802
|
const fromFields = this.getTableLikeFields(this.config.from);
|
|
67803
67803
|
fields[tableName] = fromFields;
|
|
67804
67804
|
}
|
|
67805
|
-
for (const
|
|
67806
|
-
const tableName2 = getTableLikeName(
|
|
67807
|
-
if (typeof tableName2 === "string" && !is(
|
|
67808
|
-
const fromFields = this.getTableLikeFields(
|
|
67805
|
+
for (const join16 of this.config.joins) {
|
|
67806
|
+
const tableName2 = getTableLikeName(join16.table);
|
|
67807
|
+
if (typeof tableName2 === "string" && !is(join16.table, SQL)) {
|
|
67808
|
+
const fromFields = this.getTableLikeFields(join16.table);
|
|
67809
67809
|
fields[tableName2] = fromFields;
|
|
67810
67810
|
}
|
|
67811
67811
|
}
|
|
@@ -82474,7 +82474,7 @@ var require_path = __commonJS((exports) => {
|
|
|
82474
82474
|
function isAbsolute(path) {
|
|
82475
82475
|
return path.charAt(0) === "/";
|
|
82476
82476
|
}
|
|
82477
|
-
function
|
|
82477
|
+
function join20(...args) {
|
|
82478
82478
|
return normalizePath(args.join("/"));
|
|
82479
82479
|
}
|
|
82480
82480
|
function dirname6(path) {
|
|
@@ -82499,7 +82499,7 @@ var require_path = __commonJS((exports) => {
|
|
|
82499
82499
|
exports.basename = basename6;
|
|
82500
82500
|
exports.dirname = dirname6;
|
|
82501
82501
|
exports.isAbsolute = isAbsolute;
|
|
82502
|
-
exports.join =
|
|
82502
|
+
exports.join = join20;
|
|
82503
82503
|
exports.normalizePath = normalizePath;
|
|
82504
82504
|
exports.relative = relative;
|
|
82505
82505
|
exports.resolve = resolve4;
|
|
@@ -124067,7 +124067,7 @@ import { fileURLToPath } from "url";
|
|
|
124067
124067
|
// package.json
|
|
124068
124068
|
var package_default = {
|
|
124069
124069
|
name: "@automagik/omni",
|
|
124070
|
-
version: "2.260520.
|
|
124070
|
+
version: "2.260520.11",
|
|
124071
124071
|
description: "LLM-optimized CLI for Omni",
|
|
124072
124072
|
type: "module",
|
|
124073
124073
|
bin: {
|
|
@@ -125268,7 +125268,7 @@ function pm2NotFoundError() {
|
|
|
125268
125268
|
}
|
|
125269
125269
|
|
|
125270
125270
|
// src/runtime-env.ts
|
|
125271
|
-
import { join as
|
|
125271
|
+
import { join as join7 } from "path";
|
|
125272
125272
|
|
|
125273
125273
|
// src/lib/pgserve-transport.ts
|
|
125274
125274
|
import { existsSync as existsSync4 } from "fs";
|
|
@@ -125330,15 +125330,187 @@ function buildDatabaseUrlForTransport(transport, database, options = {}) {
|
|
|
125330
125330
|
const password = options.password ?? "postgres";
|
|
125331
125331
|
const auth = `${encodeURIComponent(username)}:${encodeURIComponent(password)}`;
|
|
125332
125332
|
if (transport.kind === "unix") {
|
|
125333
|
-
|
|
125334
|
-
host: transport.socketDir,
|
|
125335
|
-
port: String(transport.port)
|
|
125336
|
-
});
|
|
125337
|
-
return `postgresql://${auth}@localhost/${encodeURIComponent(database)}?${params.toString()}`;
|
|
125333
|
+
return `postgresql://${auth}@localhost/${encodeURIComponent(database)}`;
|
|
125338
125334
|
}
|
|
125339
125335
|
return `postgresql://${auth}@${transport.host}:${transport.port}/${encodeURIComponent(database)}`;
|
|
125340
125336
|
}
|
|
125341
125337
|
|
|
125338
|
+
// src/lib/role-cutover.ts
|
|
125339
|
+
import { createHash as createHash2, randomBytes } from "crypto";
|
|
125340
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync4, unlinkSync, writeFileSync as writeFileSync3 } from "fs";
|
|
125341
|
+
import { homedir as homedir3 } from "os";
|
|
125342
|
+
import { join as join6 } from "path";
|
|
125343
|
+
var NAME_PREFIX = "pgserve_";
|
|
125344
|
+
var ROLE_SUFFIX = "_role";
|
|
125345
|
+
var POSTGRES_MAX_IDENT = 63;
|
|
125346
|
+
var FINGERPRINT_HEX_LEN = 12;
|
|
125347
|
+
var OMNI_PUBLISHER = "omni";
|
|
125348
|
+
var SAFE_IDENT = /^[a-z_][a-z0-9_]*$/;
|
|
125349
|
+
function sha256Hex(input) {
|
|
125350
|
+
return createHash2("sha256").update(input, "utf8").digest("hex");
|
|
125351
|
+
}
|
|
125352
|
+
function sanitizeSlug(input) {
|
|
125353
|
+
return input.toLowerCase().replace(/[^a-z0-9_]/g, "_").replace(/^_+|_+$/g, "").replace(/__+/g, "_");
|
|
125354
|
+
}
|
|
125355
|
+
function deriveOmniScopedRoleName() {
|
|
125356
|
+
const fp = sha256Hex("@automagik/omni").slice(0, FINGERPRINT_HEX_LEN);
|
|
125357
|
+
const slug = sanitizeSlug(OMNI_PUBLISHER);
|
|
125358
|
+
const budget = POSTGRES_MAX_IDENT - NAME_PREFIX.length - 1 - fp.length - ROLE_SUFFIX.length;
|
|
125359
|
+
const truncated = slug.slice(0, Math.max(0, budget));
|
|
125360
|
+
return `${NAME_PREFIX}${truncated}_${fp}${ROLE_SUFFIX}`;
|
|
125361
|
+
}
|
|
125362
|
+
function assertSafeIdent(label, value) {
|
|
125363
|
+
if (!SAFE_IDENT.test(value)) {
|
|
125364
|
+
throw new Error(`role-cutover: unsafe ${label} identifier: ${JSON.stringify(value)}`);
|
|
125365
|
+
}
|
|
125366
|
+
}
|
|
125367
|
+
function assertSafePassword(value) {
|
|
125368
|
+
if (!/^[A-Za-z0-9_-]+$/.test(value)) {
|
|
125369
|
+
throw new Error("role-cutover: generated password contains unsafe characters");
|
|
125370
|
+
}
|
|
125371
|
+
}
|
|
125372
|
+
function sentinelDir() {
|
|
125373
|
+
return join6(homedir3(), ".omni");
|
|
125374
|
+
}
|
|
125375
|
+
function sentinelPath() {
|
|
125376
|
+
return join6(sentinelDir(), "scoped-role.json");
|
|
125377
|
+
}
|
|
125378
|
+
function readOmniCutoverSentinel() {
|
|
125379
|
+
const path = sentinelPath();
|
|
125380
|
+
if (!existsSync5(path))
|
|
125381
|
+
return null;
|
|
125382
|
+
try {
|
|
125383
|
+
const raw2 = readFileSync4(path, "utf-8");
|
|
125384
|
+
const parsed = JSON.parse(raw2);
|
|
125385
|
+
if (typeof parsed.roleName === "string" && typeof parsed.database === "string" && typeof parsed.password === "string" && typeof parsed.provisionedAt === "string") {
|
|
125386
|
+
return parsed;
|
|
125387
|
+
}
|
|
125388
|
+
} catch {}
|
|
125389
|
+
return null;
|
|
125390
|
+
}
|
|
125391
|
+
function writeOmniCutoverSentinel(data2) {
|
|
125392
|
+
const dir = sentinelDir();
|
|
125393
|
+
if (!existsSync5(dir))
|
|
125394
|
+
mkdirSync3(dir, { recursive: true, mode: 448 });
|
|
125395
|
+
const path = sentinelPath();
|
|
125396
|
+
writeFileSync3(path, `${JSON.stringify(data2, null, 2)}
|
|
125397
|
+
`, { mode: 384 });
|
|
125398
|
+
}
|
|
125399
|
+
function isOmniRoleCutoverEnabled() {
|
|
125400
|
+
return process.env.OMNI_ROLE_CUTOVER !== "0";
|
|
125401
|
+
}
|
|
125402
|
+
function generatePassword() {
|
|
125403
|
+
return randomBytes(32).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
125404
|
+
}
|
|
125405
|
+
async function ensureOmniScopedRole(opts) {
|
|
125406
|
+
const enabled = opts.enabled ?? isOmniRoleCutoverEnabled();
|
|
125407
|
+
if (!enabled) {
|
|
125408
|
+
return { status: "skipped", reason: "disabled" };
|
|
125409
|
+
}
|
|
125410
|
+
const database = opts.database ?? "omni";
|
|
125411
|
+
const port = opts.port ?? 5432;
|
|
125412
|
+
const roleName = deriveOmniScopedRoleName();
|
|
125413
|
+
try {
|
|
125414
|
+
assertSafeIdent("role", roleName);
|
|
125415
|
+
assertSafeIdent("database", database);
|
|
125416
|
+
} catch (err) {
|
|
125417
|
+
return { status: "skipped", reason: err.message };
|
|
125418
|
+
}
|
|
125419
|
+
const existing = readOmniCutoverSentinel();
|
|
125420
|
+
const password = existing && existing.roleName === roleName && existing.database === database ? existing.password : generatePassword();
|
|
125421
|
+
try {
|
|
125422
|
+
assertSafePassword(password);
|
|
125423
|
+
} catch (err) {
|
|
125424
|
+
return { status: "skipped", reason: err.message };
|
|
125425
|
+
}
|
|
125426
|
+
const sqlScript = [
|
|
125427
|
+
`DO $$
|
|
125428
|
+
BEGIN
|
|
125429
|
+
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = '${roleName}') THEN
|
|
125430
|
+
CREATE ROLE "${roleName}" WITH LOGIN PASSWORD '${password}'
|
|
125431
|
+
NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION NOBYPASSRLS;
|
|
125432
|
+
ELSE
|
|
125433
|
+
ALTER ROLE "${roleName}" WITH LOGIN PASSWORD '${password}'
|
|
125434
|
+
NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION NOBYPASSRLS;
|
|
125435
|
+
END IF;
|
|
125436
|
+
END
|
|
125437
|
+
$$;`,
|
|
125438
|
+
`GRANT CONNECT, TEMPORARY ON DATABASE "${database}" TO "${roleName}";`
|
|
125439
|
+
];
|
|
125440
|
+
const dbCreateOk = await runPsql(sqlScript.join(`
|
|
125441
|
+
`), { socketDir: opts.socketDir, port, database: "postgres" });
|
|
125442
|
+
if (!dbCreateOk) {
|
|
125443
|
+
return { status: "skipped", reason: "psql role provisioning failed" };
|
|
125444
|
+
}
|
|
125445
|
+
const grantsScript = [
|
|
125446
|
+
`GRANT USAGE, CREATE ON SCHEMA public TO "${roleName}";`,
|
|
125447
|
+
`GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO "${roleName}";`,
|
|
125448
|
+
`GRANT USAGE, SELECT, UPDATE ON ALL SEQUENCES IN SCHEMA public TO "${roleName}";`,
|
|
125449
|
+
`ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO "${roleName}";`,
|
|
125450
|
+
`ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT USAGE, SELECT, UPDATE ON SEQUENCES TO "${roleName}";`,
|
|
125451
|
+
`ALTER DEFAULT PRIVILEGES FOR ROLE "${roleName}" IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO "${roleName}";`,
|
|
125452
|
+
`ALTER DEFAULT PRIVILEGES FOR ROLE "${roleName}" IN SCHEMA public GRANT USAGE, SELECT, UPDATE ON SEQUENCES TO "${roleName}";`
|
|
125453
|
+
].join(`
|
|
125454
|
+
`);
|
|
125455
|
+
const grantsOk = await runPsql(grantsScript, { socketDir: opts.socketDir, port, database });
|
|
125456
|
+
if (!grantsOk) {
|
|
125457
|
+
return { status: "skipped", reason: "psql grant step failed" };
|
|
125458
|
+
}
|
|
125459
|
+
writeOmniCutoverSentinel({
|
|
125460
|
+
roleName,
|
|
125461
|
+
database,
|
|
125462
|
+
password,
|
|
125463
|
+
provisionedAt: new Date().toISOString()
|
|
125464
|
+
});
|
|
125465
|
+
return existing && existing.roleName === roleName ? { status: "refreshed", roleName } : { status: "provisioned", roleName };
|
|
125466
|
+
}
|
|
125467
|
+
async function runPsql(sql, opts) {
|
|
125468
|
+
const proc = Bun.spawn({
|
|
125469
|
+
cmd: [
|
|
125470
|
+
"psql",
|
|
125471
|
+
"-h",
|
|
125472
|
+
opts.socketDir,
|
|
125473
|
+
"-p",
|
|
125474
|
+
String(opts.port),
|
|
125475
|
+
"-U",
|
|
125476
|
+
"postgres",
|
|
125477
|
+
"-d",
|
|
125478
|
+
opts.database,
|
|
125479
|
+
"-v",
|
|
125480
|
+
"ON_ERROR_STOP=1",
|
|
125481
|
+
"-c",
|
|
125482
|
+
sql
|
|
125483
|
+
],
|
|
125484
|
+
stdout: "pipe",
|
|
125485
|
+
stderr: "pipe",
|
|
125486
|
+
env: { ...process.env, PGPASSWORD: "postgres" }
|
|
125487
|
+
});
|
|
125488
|
+
const stderr = await new Response(proc.stderr).text();
|
|
125489
|
+
const code = await proc.exited;
|
|
125490
|
+
if (code !== 0) {
|
|
125491
|
+
process.stderr.write(`role-cutover: psql exited ${code}: ${stderr.trim()}
|
|
125492
|
+
`);
|
|
125493
|
+
return false;
|
|
125494
|
+
}
|
|
125495
|
+
return true;
|
|
125496
|
+
}
|
|
125497
|
+
function resolveOmniScopedCredentials() {
|
|
125498
|
+
if (!isOmniRoleCutoverEnabled())
|
|
125499
|
+
return null;
|
|
125500
|
+
const sentinel = readOmniCutoverSentinel();
|
|
125501
|
+
if (!sentinel)
|
|
125502
|
+
return null;
|
|
125503
|
+
const expected = deriveOmniScopedRoleName();
|
|
125504
|
+
if (sentinel.roleName !== expected) {
|
|
125505
|
+
return null;
|
|
125506
|
+
}
|
|
125507
|
+
return {
|
|
125508
|
+
username: sentinel.roleName,
|
|
125509
|
+
password: sentinel.password,
|
|
125510
|
+
roleName: sentinel.roleName
|
|
125511
|
+
};
|
|
125512
|
+
}
|
|
125513
|
+
|
|
125342
125514
|
// src/runtime-env.ts
|
|
125343
125515
|
var LEGACY_DEFAULT_DATABASE_URL = "postgresql://postgres:postgres@localhost:5432/omni";
|
|
125344
125516
|
var LEGACY_PHASE2_DATABASE_URL = "postgresql://postgres:postgres@localhost:8432/omni";
|
|
@@ -125367,21 +125539,34 @@ function resolveDatabaseUrl(serverConfig) {
|
|
|
125367
125539
|
}
|
|
125368
125540
|
return buildEmbeddedDatabaseUrl(resolvePgservePort(serverConfig));
|
|
125369
125541
|
}
|
|
125542
|
+
function applyScopedCredentials(url, creds) {
|
|
125543
|
+
if (!creds)
|
|
125544
|
+
return url;
|
|
125545
|
+
try {
|
|
125546
|
+
const parsed = new URL(url);
|
|
125547
|
+
parsed.username = encodeURIComponent(creds.username);
|
|
125548
|
+
parsed.password = encodeURIComponent(creds.password);
|
|
125549
|
+
return parsed.toString();
|
|
125550
|
+
} catch {
|
|
125551
|
+
return url;
|
|
125552
|
+
}
|
|
125553
|
+
}
|
|
125370
125554
|
function buildRuntimeEnv(serverConfig, cliConfig) {
|
|
125371
125555
|
const pgservePort = resolvePgservePort(serverConfig);
|
|
125372
125556
|
const udsActive = probeCanonicalSocketSync();
|
|
125373
125557
|
const pgHost = udsActive ? resolvePgserveSocketDir() : "";
|
|
125374
125558
|
const pgPort = udsActive ? String(CANONICAL_PG_PORT) : "";
|
|
125559
|
+
const scopedCreds = resolveOmniScopedCredentials();
|
|
125375
125560
|
return {
|
|
125376
125561
|
API_PORT: String(serverConfig.port),
|
|
125377
|
-
DATABASE_URL: resolveDatabaseUrl(serverConfig),
|
|
125562
|
+
DATABASE_URL: applyScopedCredentials(resolveDatabaseUrl(serverConfig), scopedCreds),
|
|
125378
125563
|
PGHOST: pgHost,
|
|
125379
125564
|
PGPORT: pgPort,
|
|
125380
125565
|
OMNI_API_KEY: cliConfig.apiKey ?? "",
|
|
125381
|
-
MEDIA_STORAGE_PATH:
|
|
125382
|
-
OMNI_PACKAGES_DIR:
|
|
125566
|
+
MEDIA_STORAGE_PATH: join7(serverConfig.dataDir, "media"),
|
|
125567
|
+
OMNI_PACKAGES_DIR: join7(serverConfig.dataDir, "packages"),
|
|
125383
125568
|
PGSERVE_EMBEDDED: "false",
|
|
125384
|
-
PGSERVE_DATA:
|
|
125569
|
+
PGSERVE_DATA: join7(serverConfig.dataDir, "pgserve"),
|
|
125385
125570
|
PGSERVE_PORT: String(pgservePort),
|
|
125386
125571
|
NATS_URL: "nats://localhost:4222",
|
|
125387
125572
|
NODE_ENV: serverConfig.nodeEnv,
|
|
@@ -127695,9 +127880,9 @@ function createDeadLettersCommand() {
|
|
|
127695
127880
|
}
|
|
127696
127881
|
|
|
127697
127882
|
// src/commands/doctor.ts
|
|
127698
|
-
import { existsSync as
|
|
127699
|
-
import { homedir as
|
|
127700
|
-
import { join as
|
|
127883
|
+
import { existsSync as existsSync9, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
|
|
127884
|
+
import { homedir as homedir7 } from "os";
|
|
127885
|
+
import { join as join12, resolve } from "path";
|
|
127701
127886
|
init_config();
|
|
127702
127887
|
|
|
127703
127888
|
// src/health.ts
|
|
@@ -127723,14 +127908,14 @@ async function waitForHealth(port, timeoutMs = HEALTH_TIMEOUT_MS) {
|
|
|
127723
127908
|
|
|
127724
127909
|
// src/install-helpers.ts
|
|
127725
127910
|
init_config();
|
|
127726
|
-
import { existsSync as
|
|
127727
|
-
import { homedir as
|
|
127728
|
-
import { join as
|
|
127911
|
+
import { existsSync as existsSync7, readdirSync, writeFileSync as writeFileSync5 } from "fs";
|
|
127912
|
+
import { homedir as homedir5 } from "os";
|
|
127913
|
+
import { join as join9 } from "path";
|
|
127729
127914
|
|
|
127730
127915
|
// src/nats-install.ts
|
|
127731
|
-
import { chmodSync as chmodSync2, existsSync as
|
|
127732
|
-
import { homedir as
|
|
127733
|
-
import { join as
|
|
127916
|
+
import { chmodSync as chmodSync2, existsSync as existsSync6, mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
127917
|
+
import { homedir as homedir4 } from "os";
|
|
127918
|
+
import { join as join8 } from "path";
|
|
127734
127919
|
|
|
127735
127920
|
// ../../node_modules/.bun/ora@8.2.0/node_modules/ora/index.js
|
|
127736
127921
|
init_source();
|
|
@@ -128620,8 +128805,8 @@ function ora(options) {
|
|
|
128620
128805
|
|
|
128621
128806
|
// src/nats-install.ts
|
|
128622
128807
|
init_output();
|
|
128623
|
-
var OMNI_DIR =
|
|
128624
|
-
var NATS_BINARY_PATH =
|
|
128808
|
+
var OMNI_DIR = join8(homedir4(), ".omni");
|
|
128809
|
+
var NATS_BINARY_PATH = join8(OMNI_DIR, "nats-server");
|
|
128625
128810
|
var NATS_VERSION = "v2.12.4";
|
|
128626
128811
|
function platformInfo() {
|
|
128627
128812
|
const platform = process.platform;
|
|
@@ -128644,17 +128829,17 @@ async function downloadNats() {
|
|
|
128644
128829
|
const url = `https://github.com/nats-io/nats-server/releases/download/${NATS_VERSION}/${fileName}`;
|
|
128645
128830
|
const spinner = ora(`Downloading NATS ${NATS_VERSION} for ${info2.os}/${info2.arch}...`).start();
|
|
128646
128831
|
try {
|
|
128647
|
-
|
|
128832
|
+
mkdirSync4(OMNI_DIR, { recursive: true, mode: 448 });
|
|
128648
128833
|
const resp = await fetch(url, { signal: AbortSignal.timeout(60000) });
|
|
128649
128834
|
if (!resp.ok) {
|
|
128650
128835
|
spinner.fail(`NATS download failed: HTTP ${resp.status}`);
|
|
128651
128836
|
return false;
|
|
128652
128837
|
}
|
|
128653
|
-
const tarPath =
|
|
128654
|
-
|
|
128838
|
+
const tarPath = join8(OMNI_DIR, fileName);
|
|
128839
|
+
writeFileSync4(tarPath, Buffer.from(await resp.arrayBuffer()));
|
|
128655
128840
|
spinner.text = "Extracting NATS binary...";
|
|
128656
|
-
const tmpDir =
|
|
128657
|
-
|
|
128841
|
+
const tmpDir = join8(OMNI_DIR, "nats-tmp");
|
|
128842
|
+
mkdirSync4(tmpDir, { recursive: true });
|
|
128658
128843
|
const tar = Bun.spawn({ cmd: ["tar", "-xzf", tarPath, "-C", tmpDir], stdout: "pipe", stderr: "pipe" });
|
|
128659
128844
|
const [tarCode, tarErr] = await Promise.all([tar.exited, new Response(tar.stderr).text()]);
|
|
128660
128845
|
if (tarCode !== 0) {
|
|
@@ -128679,7 +128864,7 @@ async function downloadNats() {
|
|
|
128679
128864
|
}
|
|
128680
128865
|
}
|
|
128681
128866
|
async function ensureNats() {
|
|
128682
|
-
if (
|
|
128867
|
+
if (existsSync6(NATS_BINARY_PATH)) {
|
|
128683
128868
|
raw(` \u2713 NATS binary found at ${NATS_BINARY_PATH}`);
|
|
128684
128869
|
return;
|
|
128685
128870
|
}
|
|
@@ -128689,7 +128874,7 @@ async function ensureNats() {
|
|
|
128689
128874
|
|
|
128690
128875
|
// src/install-helpers.ts
|
|
128691
128876
|
init_output();
|
|
128692
|
-
var DEFAULT_DATA_DIR =
|
|
128877
|
+
var DEFAULT_DATA_DIR = join9(homedir5(), ".omni", "data");
|
|
128693
128878
|
async function detectReinstall(dataDirOverride) {
|
|
128694
128879
|
const hasConfig = detectHasConfig();
|
|
128695
128880
|
const hasPm2Process = await detectHasPm2Process();
|
|
@@ -128702,7 +128887,7 @@ async function detectReinstall(dataDirOverride) {
|
|
|
128702
128887
|
};
|
|
128703
128888
|
}
|
|
128704
128889
|
function detectHasConfig() {
|
|
128705
|
-
if (!
|
|
128890
|
+
if (!existsSync7(getConfigPath()))
|
|
128706
128891
|
return false;
|
|
128707
128892
|
try {
|
|
128708
128893
|
const parsed = loadConfig();
|
|
@@ -128724,7 +128909,7 @@ async function detectHasPm2Process() {
|
|
|
128724
128909
|
}
|
|
128725
128910
|
function detectHasDataDir(dataDirOverride) {
|
|
128726
128911
|
const dataDir = dataDirOverride ?? DEFAULT_DATA_DIR;
|
|
128727
|
-
if (!
|
|
128912
|
+
if (!existsSync7(dataDir))
|
|
128728
128913
|
return false;
|
|
128729
128914
|
try {
|
|
128730
128915
|
return readdirSync(dataDir).filter((e) => e !== ".DS_Store").length > 0;
|
|
@@ -128778,7 +128963,7 @@ ExecStart=/usr/bin/env omni start
|
|
|
128778
128963
|
ExecStop=/usr/bin/env omni stop
|
|
128779
128964
|
ExecReload=/usr/bin/env omni restart
|
|
128780
128965
|
Restart=on-failure
|
|
128781
|
-
PIDFile=${
|
|
128966
|
+
PIDFile=${homedir5()}/.pm2/pm2.pid
|
|
128782
128967
|
|
|
128783
128968
|
[Install]
|
|
128784
128969
|
WantedBy=multi-user.target
|
|
@@ -128789,7 +128974,7 @@ After=network.target
|
|
|
128789
128974
|
|
|
128790
128975
|
[Service]
|
|
128791
128976
|
Type=simple
|
|
128792
|
-
ExecStart="${NATS_BINARY_PATH}" -js -sd "${
|
|
128977
|
+
ExecStart="${NATS_BINARY_PATH}" -js -sd "${join9(dataDir, "nats")}"
|
|
128793
128978
|
Restart=on-failure
|
|
128794
128979
|
RestartSec=5
|
|
128795
128980
|
|
|
@@ -128797,8 +128982,8 @@ RestartSec=5
|
|
|
128797
128982
|
WantedBy=multi-user.target
|
|
128798
128983
|
`;
|
|
128799
128984
|
try {
|
|
128800
|
-
|
|
128801
|
-
|
|
128985
|
+
writeFileSync5("/etc/systemd/system/omni-nats.service", natsUnit, { mode: 420 });
|
|
128986
|
+
writeFileSync5("/etc/systemd/system/omni-api.service", apiUnit, { mode: 420 });
|
|
128802
128987
|
success("Systemd units written to /etc/systemd/system/");
|
|
128803
128988
|
raw(`
|
|
128804
128989
|
Enable with: sudo systemctl enable --now omni-nats omni-api
|
|
@@ -128812,9 +128997,9 @@ WantedBy=multi-user.target
|
|
|
128812
128997
|
init_config();
|
|
128813
128998
|
init_output();
|
|
128814
128999
|
import { spawnSync } from "child_process";
|
|
128815
|
-
import { existsSync as
|
|
128816
|
-
import { homedir as
|
|
128817
|
-
import { join as
|
|
129000
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync5, renameSync, statSync, writeFileSync as writeFileSync6 } from "fs";
|
|
129001
|
+
import { homedir as homedir6 } from "os";
|
|
129002
|
+
import { join as join10 } from "path";
|
|
128818
129003
|
import { gunzipSync, gzipSync } from "zlib";
|
|
128819
129004
|
async function isPgserveInstalled() {
|
|
128820
129005
|
const bin = resolvePgserveBinary();
|
|
@@ -128932,6 +129117,16 @@ async function setupCanonicalPgserve() {
|
|
|
128932
129117
|
if (port === null)
|
|
128933
129118
|
return null;
|
|
128934
129119
|
await ensureOmniDatabaseExists(port);
|
|
129120
|
+
const cutover = await ensureOmniScopedRole({
|
|
129121
|
+
socketDir: resolvePgserveSocketDir(),
|
|
129122
|
+
port,
|
|
129123
|
+
database: OMNI_DATABASE_NAME
|
|
129124
|
+
});
|
|
129125
|
+
if (cutover.status === "provisioned" || cutover.status === "refreshed") {
|
|
129126
|
+
raw(` Scoped role \`${cutover.roleName}\` ${cutover.status} \u2014 omni-api will connect as non-superuser.`);
|
|
129127
|
+
} else if (cutover.status === "skipped" && cutover.reason !== "disabled") {
|
|
129128
|
+
warn(`Scoped-role cutover skipped: ${cutover.reason} \u2014 omni-api falls back to postgres superuser.`);
|
|
129129
|
+
}
|
|
128935
129130
|
return buildOmniDatabaseUrl(port);
|
|
128936
129131
|
}
|
|
128937
129132
|
async function resolveCanonicalPgservePreference(isReinstall, cfg) {
|
|
@@ -128963,18 +129158,18 @@ async function resolveCanonicalPgservePreference(isReinstall, cfg) {
|
|
|
128963
129158
|
raw("");
|
|
128964
129159
|
return true;
|
|
128965
129160
|
}
|
|
128966
|
-
var OMNI_EMBEDDED_PGSERVE_DATA_DIR =
|
|
128967
|
-
var PGSERVE_DEFAULT_DATA_DIR =
|
|
128968
|
-
var PGSERVE_CONFIG_PATH =
|
|
128969
|
-
var OMNI_BACKUPS_DIR =
|
|
129161
|
+
var OMNI_EMBEDDED_PGSERVE_DATA_DIR = join10(homedir6(), ".omni", "data", "pgserve");
|
|
129162
|
+
var PGSERVE_DEFAULT_DATA_DIR = join10(homedir6(), ".pgserve", "data");
|
|
129163
|
+
var PGSERVE_CONFIG_PATH = join10(homedir6(), ".pgserve", "config.json");
|
|
129164
|
+
var OMNI_BACKUPS_DIR = join10(homedir6(), ".omni", "backups");
|
|
128970
129165
|
function getEmbeddedPgserveDataDir() {
|
|
128971
129166
|
return OMNI_EMBEDDED_PGSERVE_DATA_DIR;
|
|
128972
129167
|
}
|
|
128973
129168
|
function getCanonicalPgserveDataDir() {
|
|
128974
|
-
if (!
|
|
129169
|
+
if (!existsSync8(PGSERVE_CONFIG_PATH))
|
|
128975
129170
|
return PGSERVE_DEFAULT_DATA_DIR;
|
|
128976
129171
|
try {
|
|
128977
|
-
const raw2 =
|
|
129172
|
+
const raw2 = readFileSync5(PGSERVE_CONFIG_PATH, "utf8");
|
|
128978
129173
|
const parsed = JSON.parse(raw2);
|
|
128979
129174
|
return typeof parsed.dataDir === "string" && parsed.dataDir.length > 0 ? parsed.dataDir : PGSERVE_DEFAULT_DATA_DIR;
|
|
128980
129175
|
} catch {
|
|
@@ -128982,11 +129177,11 @@ function getCanonicalPgserveDataDir() {
|
|
|
128982
129177
|
}
|
|
128983
129178
|
}
|
|
128984
129179
|
function looksLikePgDataDir(path) {
|
|
128985
|
-
return
|
|
129180
|
+
return existsSync8(join10(path, "PG_VERSION")) && existsSync8(join10(path, "base"));
|
|
128986
129181
|
}
|
|
128987
129182
|
function getSnapshotPath(timestamp = new Date) {
|
|
128988
129183
|
const ts = timestamp.toISOString().replace(/[:.]/g, "-");
|
|
128989
|
-
return
|
|
129184
|
+
return join10(OMNI_BACKUPS_DIR, `embedded-migration-${ts}.sql.gz`);
|
|
128990
129185
|
}
|
|
128991
129186
|
function commandIsAvailable(cmd) {
|
|
128992
129187
|
try {
|
|
@@ -129011,7 +129206,7 @@ function pgEnvFromUrl(url) {
|
|
|
129011
129206
|
}
|
|
129012
129207
|
async function dumpEmbeddedDb(currentDatabaseUrl) {
|
|
129013
129208
|
const embeddedDir = getEmbeddedPgserveDataDir();
|
|
129014
|
-
if (!
|
|
129209
|
+
if (!existsSync8(embeddedDir)) {
|
|
129015
129210
|
return { status: "no-embedded-data", embeddedDir };
|
|
129016
129211
|
}
|
|
129017
129212
|
if (!looksLikePgDataDir(embeddedDir)) {
|
|
@@ -129022,7 +129217,7 @@ async function dumpEmbeddedDb(currentDatabaseUrl) {
|
|
|
129022
129217
|
throw new Error("pg_dump not found in PATH \u2014 install postgresql-client (apt install postgresql-client / brew install postgresql) and retry");
|
|
129023
129218
|
}
|
|
129024
129219
|
const snapshotPath = getSnapshotPath();
|
|
129025
|
-
|
|
129220
|
+
mkdirSync5(OMNI_BACKUPS_DIR, { recursive: true, mode: 448 });
|
|
129026
129221
|
raw(" Dumping embedded database via pg_dump...");
|
|
129027
129222
|
raw(` source data dir: ${embeddedDir}`);
|
|
129028
129223
|
raw(` snapshot: ${snapshotPath}`);
|
|
@@ -129038,7 +129233,7 @@ async function dumpEmbeddedDb(currentDatabaseUrl) {
|
|
|
129038
129233
|
}
|
|
129039
129234
|
const compressed = gzipSync(result.stdout);
|
|
129040
129235
|
const tmpPath = `${snapshotPath}.tmp`;
|
|
129041
|
-
|
|
129236
|
+
writeFileSync6(tmpPath, compressed, { mode: 384 });
|
|
129042
129237
|
renameSync(tmpPath, snapshotPath);
|
|
129043
129238
|
const bytes = statSync(snapshotPath).size;
|
|
129044
129239
|
raw(` snapshot size: ${formatBytes(bytes)}`);
|
|
@@ -129056,7 +129251,7 @@ async function restoreSnapshotToCanonical(dump, canonicalDatabaseUrl) {
|
|
|
129056
129251
|
raw(` snapshot: ${dump.snapshotPath}`);
|
|
129057
129252
|
raw(` canonical data dir: ${getCanonicalPgserveDataDir()}`);
|
|
129058
129253
|
raw(` canonical URL: ${canonicalDatabaseUrl}`);
|
|
129059
|
-
const compressed =
|
|
129254
|
+
const compressed = readFileSync5(dump.snapshotPath);
|
|
129060
129255
|
const sql = gunzipSync(compressed);
|
|
129061
129256
|
const result = spawnSync("psql", ["-v", "ON_ERROR_STOP=1"], {
|
|
129062
129257
|
env: { ...process.env, ...pgEnvFromUrl(canonicalDatabaseUrl) },
|
|
@@ -129087,24 +129282,24 @@ init_output();
|
|
|
129087
129282
|
|
|
129088
129283
|
// src/server-bundle.ts
|
|
129089
129284
|
init_output();
|
|
129090
|
-
import { dirname as dirname2, join as
|
|
129285
|
+
import { dirname as dirname2, join as join11 } from "path";
|
|
129091
129286
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
129092
129287
|
function getServerBundlePath() {
|
|
129093
129288
|
try {
|
|
129094
129289
|
const thisFile = fileURLToPath2(import.meta.url);
|
|
129095
129290
|
const distDir = dirname2(thisFile);
|
|
129096
|
-
return
|
|
129291
|
+
return join11(distDir, "server", "index.js");
|
|
129097
129292
|
} catch {
|
|
129098
|
-
return
|
|
129293
|
+
return join11(process.cwd(), "dist", "server", "index.js");
|
|
129099
129294
|
}
|
|
129100
129295
|
}
|
|
129101
129296
|
function getServerLauncherPath() {
|
|
129102
129297
|
try {
|
|
129103
129298
|
const thisFile = fileURLToPath2(import.meta.url);
|
|
129104
129299
|
const distDir = dirname2(thisFile);
|
|
129105
|
-
return
|
|
129300
|
+
return join11(distDir, "..", "bin", "omni-server");
|
|
129106
129301
|
} catch {
|
|
129107
|
-
return
|
|
129302
|
+
return join11(process.cwd(), "bin", "omni-server");
|
|
129108
129303
|
}
|
|
129109
129304
|
}
|
|
129110
129305
|
function bundleNotFoundError(bundlePath) {
|
|
@@ -129169,10 +129364,10 @@ function productionDeps() {
|
|
|
129169
129364
|
}
|
|
129170
129365
|
},
|
|
129171
129366
|
findOrphanedDataDirs: () => {
|
|
129172
|
-
const roots = [process.cwd(),
|
|
129367
|
+
const roots = [process.cwd(), join12(homedir7(), "workspace"), join12(homedir7(), "repos")];
|
|
129173
129368
|
const found = [];
|
|
129174
129369
|
for (const root of roots) {
|
|
129175
|
-
if (!
|
|
129370
|
+
if (!existsSync9(root))
|
|
129176
129371
|
continue;
|
|
129177
129372
|
try {
|
|
129178
129373
|
scanForOrphans(root, found, 0);
|
|
@@ -129280,7 +129475,7 @@ function scanForOrphans(dir, acc, depth, maxDepth = 4) {
|
|
|
129280
129475
|
for (const name of entries) {
|
|
129281
129476
|
if (name === "node_modules" || name === ".git")
|
|
129282
129477
|
continue;
|
|
129283
|
-
const full =
|
|
129478
|
+
const full = join12(dir, name);
|
|
129284
129479
|
let stats;
|
|
129285
129480
|
try {
|
|
129286
129481
|
stats = statSync2(full);
|
|
@@ -129903,7 +130098,7 @@ Safety:
|
|
|
129903
130098
|
}
|
|
129904
130099
|
|
|
129905
130100
|
// src/commands/done.ts
|
|
129906
|
-
import { existsSync as
|
|
130101
|
+
import { existsSync as existsSync10, readFileSync as readFileSync6 } from "fs";
|
|
129907
130102
|
import { basename, extname } from "path";
|
|
129908
130103
|
|
|
129909
130104
|
// src/context.ts
|
|
@@ -130012,12 +130207,12 @@ async function handleReact(client, ctx, emoji) {
|
|
|
130012
130207
|
await closeTurn(client, "react", `Reacted ${emoji} + turn closed`);
|
|
130013
130208
|
}
|
|
130014
130209
|
async function handleMedia(client, ctx, mediaPath, caption) {
|
|
130015
|
-
if (!
|
|
130210
|
+
if (!existsSync10(mediaPath)) {
|
|
130016
130211
|
return error(`File not found: ${mediaPath}`);
|
|
130017
130212
|
}
|
|
130018
130213
|
try {
|
|
130019
130214
|
const mediaType = getMediaType(mediaPath);
|
|
130020
|
-
const buffer =
|
|
130215
|
+
const buffer = readFileSync6(mediaPath);
|
|
130021
130216
|
const base64 = buffer.toString("base64");
|
|
130022
130217
|
const filename = basename(mediaPath);
|
|
130023
130218
|
await client.messages.sendMedia({
|
|
@@ -130449,7 +130644,7 @@ function createEventsCommand() {
|
|
|
130449
130644
|
}
|
|
130450
130645
|
|
|
130451
130646
|
// src/commands/film.ts
|
|
130452
|
-
import { writeFileSync as
|
|
130647
|
+
import { writeFileSync as writeFileSync7 } from "fs";
|
|
130453
130648
|
import { resolve as resolvePath } from "path";
|
|
130454
130649
|
init_output();
|
|
130455
130650
|
function createFilmCommand() {
|
|
@@ -130513,7 +130708,7 @@ function createFilmCommand() {
|
|
|
130513
130708
|
const videoBuffer = Buffer.from(result.videoBase64, "base64");
|
|
130514
130709
|
if (options.output) {
|
|
130515
130710
|
const outPath = resolvePath(options.output);
|
|
130516
|
-
|
|
130711
|
+
writeFileSync7(outPath, videoBuffer);
|
|
130517
130712
|
success("Video saved", { path: outPath, sizeBytes: videoBuffer.length });
|
|
130518
130713
|
return;
|
|
130519
130714
|
}
|
|
@@ -130537,7 +130732,7 @@ function createFilmCommand() {
|
|
|
130537
130732
|
}
|
|
130538
130733
|
|
|
130539
130734
|
// src/commands/follow-up.ts
|
|
130540
|
-
import { readFileSync as
|
|
130735
|
+
import { readFileSync as readFileSync7 } from "fs";
|
|
130541
130736
|
init_output();
|
|
130542
130737
|
var VALID_SCOPES = ["agents", "instances", "chats"];
|
|
130543
130738
|
function assertScope(scope) {
|
|
@@ -130555,9 +130750,9 @@ async function resolveScopedId(scope, id) {
|
|
|
130555
130750
|
function readJsonArg(raw2) {
|
|
130556
130751
|
let body = raw2;
|
|
130557
130752
|
if (body === "-") {
|
|
130558
|
-
body =
|
|
130753
|
+
body = readFileSync7(0, "utf8");
|
|
130559
130754
|
} else if (body.startsWith("@")) {
|
|
130560
|
-
body =
|
|
130755
|
+
body = readFileSync7(body.slice(1), "utf8");
|
|
130561
130756
|
}
|
|
130562
130757
|
try {
|
|
130563
130758
|
return JSON.parse(body);
|
|
@@ -130709,8 +130904,8 @@ function createHistoryCommand() {
|
|
|
130709
130904
|
}
|
|
130710
130905
|
|
|
130711
130906
|
// src/commands/imagine.ts
|
|
130712
|
-
import { writeFileSync as
|
|
130713
|
-
import { basename as basename2, dirname as dirname3, extname as extname2, join as
|
|
130907
|
+
import { writeFileSync as writeFileSync8 } from "fs";
|
|
130908
|
+
import { basename as basename2, dirname as dirname3, extname as extname2, join as join13 } from "path";
|
|
130714
130909
|
init_output();
|
|
130715
130910
|
var ALLOWED_ASPECT_RATIOS = ["1:1", "4:3", "3:4", "16:9", "9:16", "3:2", "2:3"];
|
|
130716
130911
|
function extensionForMime(mimeType) {
|
|
@@ -130725,9 +130920,9 @@ function buildOutputPath(outputBase, index, total, mimeType) {
|
|
|
130725
130920
|
const ext = extname2(outputBase) || extensionForMime(mimeType);
|
|
130726
130921
|
const stem = basename2(outputBase, extname2(outputBase));
|
|
130727
130922
|
if (total <= 1) {
|
|
130728
|
-
return
|
|
130923
|
+
return join13(dir, `${stem}${ext}`);
|
|
130729
130924
|
}
|
|
130730
|
-
return
|
|
130925
|
+
return join13(dir, `${stem}-${index + 1}${ext}`);
|
|
130731
130926
|
}
|
|
130732
130927
|
function parseAspectRatio(value) {
|
|
130733
130928
|
if (!value)
|
|
@@ -130800,7 +130995,7 @@ function createImagineCommand() {
|
|
|
130800
130995
|
continue;
|
|
130801
130996
|
const path = buildOutputPath(options.output, i, result.images.length, image.mimeType);
|
|
130802
130997
|
try {
|
|
130803
|
-
|
|
130998
|
+
writeFileSync8(path, Buffer.from(image.base64, "base64"));
|
|
130804
130999
|
savedPaths.push(path);
|
|
130805
131000
|
} catch (err) {
|
|
130806
131001
|
const message = err instanceof Error ? err.message : "Unknown error";
|
|
@@ -130845,12 +131040,12 @@ function createImagineCommand() {
|
|
|
130845
131040
|
}
|
|
130846
131041
|
|
|
130847
131042
|
// src/commands/install.ts
|
|
130848
|
-
import { existsSync as
|
|
130849
|
-
import { homedir as
|
|
130850
|
-
import { join as
|
|
131043
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync6 } from "fs";
|
|
131044
|
+
import { homedir as homedir8 } from "os";
|
|
131045
|
+
import { join as join14 } from "path";
|
|
130851
131046
|
init_config();
|
|
130852
131047
|
init_output();
|
|
130853
|
-
var DEFAULT_DATA_DIR2 =
|
|
131048
|
+
var DEFAULT_DATA_DIR2 = join14(homedir8(), ".omni", "data");
|
|
130854
131049
|
function computeDefaultDatabaseUrl() {
|
|
130855
131050
|
return buildEmbeddedDatabaseUrl();
|
|
130856
131051
|
}
|
|
@@ -130949,13 +131144,13 @@ async function startServices(cfg, forceCleanup, forceSystemd, useCanonicalPgserv
|
|
|
130949
131144
|
return false;
|
|
130950
131145
|
}
|
|
130951
131146
|
const bundlePath = getServerBundlePath();
|
|
130952
|
-
if (!
|
|
131147
|
+
if (!existsSync11(bundlePath)) {
|
|
130953
131148
|
warn(`Server bundle not found at: ${bundlePath}
|
|
130954
131149
|
Install @automagik/omni from npm: bun add -g @automagik/omni
|
|
130955
131150
|
Or build locally: make cli-build-full`);
|
|
130956
131151
|
return false;
|
|
130957
131152
|
}
|
|
130958
|
-
|
|
131153
|
+
mkdirSync6(getPm2LogDir(), { recursive: true });
|
|
130959
131154
|
await installPm2Logrotate();
|
|
130960
131155
|
const runtimeEnv = buildInstallRuntimeEnv(cfg, forceCleanup, useCanonicalPgserve);
|
|
130961
131156
|
await runPm2(["delete", PM2_PROCESSES.api]);
|
|
@@ -130973,10 +131168,10 @@ async function startServices(cfg, forceCleanup, forceSystemd, useCanonicalPgserv
|
|
|
130973
131168
|
return false;
|
|
130974
131169
|
}
|
|
130975
131170
|
apiSpinner.succeed(`${PM2_PROCESSES.api} started`);
|
|
130976
|
-
if (
|
|
131171
|
+
if (existsSync11(NATS_BINARY_PATH)) {
|
|
130977
131172
|
const natsSpinner = ora(`Starting ${PM2_PROCESSES.nats}...`).start();
|
|
130978
|
-
const natsDataDir =
|
|
130979
|
-
|
|
131173
|
+
const natsDataDir = join14(cfg.dataDir, "nats");
|
|
131174
|
+
mkdirSync6(natsDataDir, { recursive: true });
|
|
130980
131175
|
const natsArgs = buildPm2StartArgs({
|
|
130981
131176
|
kind: "nats",
|
|
130982
131177
|
script: NATS_BINARY_PATH,
|
|
@@ -132652,7 +132847,7 @@ function createLogsCommand() {
|
|
|
132652
132847
|
}
|
|
132653
132848
|
|
|
132654
132849
|
// src/commands/media.ts
|
|
132655
|
-
import { createWriteStream as createWriteStream2, existsSync as
|
|
132850
|
+
import { createWriteStream as createWriteStream2, existsSync as existsSync13, mkdirSync as mkdirSync8, statSync as statSync4 } from "fs";
|
|
132656
132851
|
import { basename as basename4, dirname as dirname4, resolve as resolve2 } from "path";
|
|
132657
132852
|
import { Readable } from "stream";
|
|
132658
132853
|
import { pipeline } from "stream/promises";
|
|
@@ -132715,14 +132910,14 @@ function resolveOutputPath(outputPath, result) {
|
|
|
132715
132910
|
const resolved = resolve2(outputPath);
|
|
132716
132911
|
if (isDirHint)
|
|
132717
132912
|
return resolve2(resolved, filename);
|
|
132718
|
-
if (
|
|
132913
|
+
if (existsSync13(resolved) && statSync4(resolved).isDirectory())
|
|
132719
132914
|
return resolve2(resolved, filename);
|
|
132720
132915
|
return resolved;
|
|
132721
132916
|
}
|
|
132722
132917
|
async function downloadToFile(url, apiKey, destinationPath) {
|
|
132723
132918
|
const destDir = dirname4(destinationPath);
|
|
132724
|
-
if (!
|
|
132725
|
-
|
|
132919
|
+
if (!existsSync13(destDir))
|
|
132920
|
+
mkdirSync8(destDir, { recursive: true });
|
|
132726
132921
|
const resp = await fetch(url, {
|
|
132727
132922
|
method: "GET",
|
|
132728
132923
|
headers: apiKey ? { "x-api-key": apiKey } : undefined
|
|
@@ -133675,8 +133870,8 @@ init_output();
|
|
|
133675
133870
|
init_src();
|
|
133676
133871
|
import { execFileSync as execFileSync3, execSync } from "child_process";
|
|
133677
133872
|
import * as nodeCrypto2 from "crypto";
|
|
133678
|
-
import { existsSync as
|
|
133679
|
-
import { homedir as
|
|
133873
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync9, readFileSync as readFileSync9, writeFileSync as writeFileSync9 } from "fs";
|
|
133874
|
+
import { homedir as homedir10 } from "os";
|
|
133680
133875
|
import { dirname as dirname5, resolve as resolve3 } from "path";
|
|
133681
133876
|
import { createInterface as createInterface2 } from "readline";
|
|
133682
133877
|
init_config();
|
|
@@ -133903,19 +134098,19 @@ async function pairDevice(gatewayUrl, gatewayToken, keypair, spinner) {
|
|
|
133903
134098
|
ws.close(1000, "pairing complete");
|
|
133904
134099
|
}
|
|
133905
134100
|
}
|
|
133906
|
-
var OPENCLAW_CONFIG_PATH = resolve3(
|
|
134101
|
+
var OPENCLAW_CONFIG_PATH = resolve3(homedir10(), ".openclaw", "openclaw.json");
|
|
133907
134102
|
var PLUGIN_MARKER = "plugin-openclaw/omni.ts";
|
|
133908
134103
|
function readOpenClawConfig(configPath) {
|
|
133909
|
-
if (!
|
|
134104
|
+
if (!existsSync14(configPath))
|
|
133910
134105
|
return {};
|
|
133911
|
-
const raw2 =
|
|
134106
|
+
const raw2 = readFileSync9(configPath, "utf-8").trim();
|
|
133912
134107
|
if (!raw2)
|
|
133913
134108
|
return {};
|
|
133914
134109
|
return JSON.parse(raw2);
|
|
133915
134110
|
}
|
|
133916
134111
|
function writeOpenClawConfig(configPath, config2) {
|
|
133917
|
-
|
|
133918
|
-
|
|
134112
|
+
mkdirSync9(dirname5(configPath), { recursive: true, mode: 448 });
|
|
134113
|
+
writeFileSync9(configPath, `${JSON.stringify(config2, null, 2)}
|
|
133919
134114
|
`, { mode: 384 });
|
|
133920
134115
|
}
|
|
133921
134116
|
function isPluginRegistered(config2, marker, pluginPath) {
|
|
@@ -133947,10 +134142,10 @@ function isValidUuid2(value) {
|
|
|
133947
134142
|
}
|
|
133948
134143
|
function resolvePluginPath(explicit) {
|
|
133949
134144
|
if (explicit) {
|
|
133950
|
-
return
|
|
134145
|
+
return existsSync14(explicit) ? resolve3(explicit) : null;
|
|
133951
134146
|
}
|
|
133952
134147
|
const cwdCandidate = resolve3(process.cwd(), "packages/plugin-openclaw/omni.ts");
|
|
133953
|
-
return
|
|
134148
|
+
return existsSync14(cwdCandidate) ? cwdCandidate : null;
|
|
133954
134149
|
}
|
|
133955
134150
|
function registerPlugin(config2, pluginPath, configPath) {
|
|
133956
134151
|
if (hasOpenClawCli()) {
|
|
@@ -135000,7 +135195,7 @@ function createSayCommand() {
|
|
|
135000
135195
|
}
|
|
135001
135196
|
|
|
135002
135197
|
// src/commands/see.ts
|
|
135003
|
-
import { existsSync as
|
|
135198
|
+
import { existsSync as existsSync15, readFileSync as readFileSync10, statSync as statSync5 } from "fs";
|
|
135004
135199
|
import { extname as extname4 } from "path";
|
|
135005
135200
|
init_output();
|
|
135006
135201
|
var MIME_BY_EXT = {
|
|
@@ -135032,7 +135227,7 @@ function parseMaxTokens(value) {
|
|
|
135032
135227
|
return n2;
|
|
135033
135228
|
}
|
|
135034
135229
|
function loadMedia(file) {
|
|
135035
|
-
if (!
|
|
135230
|
+
if (!existsSync15(file)) {
|
|
135036
135231
|
error(`File not found: ${file}`);
|
|
135037
135232
|
}
|
|
135038
135233
|
const stat = statSync5(file);
|
|
@@ -135043,7 +135238,7 @@ function loadMedia(file) {
|
|
|
135043
135238
|
error(`File is empty: ${file}`);
|
|
135044
135239
|
}
|
|
135045
135240
|
try {
|
|
135046
|
-
return { buffer:
|
|
135241
|
+
return { buffer: readFileSync10(file), mimeType: guessMimeType(file) };
|
|
135047
135242
|
} catch (err2) {
|
|
135048
135243
|
const message2 = err2 instanceof Error ? err2.message : "Unknown error";
|
|
135049
135244
|
return error(`Failed to read ${file}: ${message2}`);
|
|
@@ -135118,7 +135313,7 @@ function createSeeCommand() {
|
|
|
135118
135313
|
}
|
|
135119
135314
|
|
|
135120
135315
|
// src/commands/send.ts
|
|
135121
|
-
import { existsSync as
|
|
135316
|
+
import { existsSync as existsSync16, readFileSync as readFileSync11 } from "fs";
|
|
135122
135317
|
import { basename as basename5, extname as extname5 } from "path";
|
|
135123
135318
|
init_source();
|
|
135124
135319
|
init_config();
|
|
@@ -135138,7 +135333,7 @@ function getMediaType2(path) {
|
|
|
135138
135333
|
return "document";
|
|
135139
135334
|
}
|
|
135140
135335
|
function readFileAsBase64(path) {
|
|
135141
|
-
const buffer3 =
|
|
135336
|
+
const buffer3 = readFileSync11(path);
|
|
135142
135337
|
return buffer3.toString("base64");
|
|
135143
135338
|
}
|
|
135144
135339
|
var messageSenders = {
|
|
@@ -135159,7 +135354,7 @@ var messageSenders = {
|
|
|
135159
135354
|
const { to, media } = options3;
|
|
135160
135355
|
if (!to || !media)
|
|
135161
135356
|
return;
|
|
135162
|
-
if (!
|
|
135357
|
+
if (!existsSync16(media)) {
|
|
135163
135358
|
error(`File not found: ${media}`);
|
|
135164
135359
|
return;
|
|
135165
135360
|
}
|
|
@@ -135691,9 +135886,9 @@ function pickFilename(mimeType, provider) {
|
|
|
135691
135886
|
}
|
|
135692
135887
|
|
|
135693
135888
|
// src/commands/start.ts
|
|
135694
|
-
import { existsSync as
|
|
135695
|
-
import { homedir as
|
|
135696
|
-
import { join as
|
|
135889
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync10 } from "fs";
|
|
135890
|
+
import { homedir as homedir11 } from "os";
|
|
135891
|
+
import { join as join16 } from "path";
|
|
135697
135892
|
init_config();
|
|
135698
135893
|
init_output();
|
|
135699
135894
|
var START_HEALTH_TIMEOUT_MS = 1e4;
|
|
@@ -135702,12 +135897,12 @@ async function runStart() {
|
|
|
135702
135897
|
pm2NotFoundError();
|
|
135703
135898
|
}
|
|
135704
135899
|
const bundlePath = getServerBundlePath();
|
|
135705
|
-
if (!
|
|
135900
|
+
if (!existsSync17(bundlePath)) {
|
|
135706
135901
|
bundleNotFoundError(bundlePath);
|
|
135707
135902
|
}
|
|
135708
135903
|
const serverConfig = loadServerConfig();
|
|
135709
135904
|
const apiPort = serverConfig.port;
|
|
135710
|
-
|
|
135905
|
+
mkdirSync10(getPm2LogDir(), { recursive: true });
|
|
135711
135906
|
info(`Starting ${PM2_PROCESSES.api} (port ${apiPort})...`);
|
|
135712
135907
|
const cliConfig = loadConfig();
|
|
135713
135908
|
const env2 = buildRuntimeEnv(serverConfig, cliConfig);
|
|
@@ -135723,11 +135918,11 @@ async function runStart() {
|
|
|
135723
135918
|
error(`Failed to start ${PM2_PROCESSES.api} (pm2 exit code ${apiCode})`, undefined, 1);
|
|
135724
135919
|
return;
|
|
135725
135920
|
}
|
|
135726
|
-
const natsPath =
|
|
135727
|
-
if (
|
|
135921
|
+
const natsPath = join16(homedir11(), ".omni", "nats-server");
|
|
135922
|
+
if (existsSync17(natsPath)) {
|
|
135728
135923
|
info(`Starting ${PM2_PROCESSES.nats}...`);
|
|
135729
|
-
const natsDataDir =
|
|
135730
|
-
|
|
135924
|
+
const natsDataDir = join16(serverConfig.dataDir, "nats");
|
|
135925
|
+
mkdirSync10(natsDataDir, { recursive: true });
|
|
135731
135926
|
const natsArgs = buildPm2StartArgs({
|
|
135732
135927
|
kind: "nats",
|
|
135733
135928
|
script: natsPath,
|
|
@@ -136147,8 +136342,8 @@ function createTurnsCommand() {
|
|
|
136147
136342
|
}
|
|
136148
136343
|
|
|
136149
136344
|
// src/commands/update.ts
|
|
136150
|
-
import { existsSync as
|
|
136151
|
-
import { join as
|
|
136345
|
+
import { existsSync as existsSync19 } from "fs";
|
|
136346
|
+
import { join as join18 } from "path";
|
|
136152
136347
|
import { createInterface as createInterface3 } from "readline";
|
|
136153
136348
|
init_source();
|
|
136154
136349
|
init_config();
|
|
@@ -136430,9 +136625,9 @@ async function cleanupLegacyArtifacts(skipList) {
|
|
|
136430
136625
|
init_output();
|
|
136431
136626
|
|
|
136432
136627
|
// src/update-diagnostics.ts
|
|
136433
|
-
import { existsSync as
|
|
136434
|
-
import { homedir as
|
|
136435
|
-
import { join as
|
|
136628
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync11, readFileSync as readFileSync12, writeFileSync as writeFileSync10 } from "fs";
|
|
136629
|
+
import { homedir as homedir12 } from "os";
|
|
136630
|
+
import { join as join17 } from "path";
|
|
136436
136631
|
var UPDATE_DIAGNOSTICS_SCHEMA_VERSION = 1;
|
|
136437
136632
|
function createDiagnostics(args) {
|
|
136438
136633
|
const startedAt = new Date().toISOString();
|
|
@@ -136454,18 +136649,18 @@ function createDiagnostics(args) {
|
|
|
136454
136649
|
};
|
|
136455
136650
|
}
|
|
136456
136651
|
function getDiagnosticsDir() {
|
|
136457
|
-
const base = process.env.OMNI_CONFIG_DIR ??
|
|
136458
|
-
return
|
|
136652
|
+
const base = process.env.OMNI_CONFIG_DIR ?? join17(homedir12(), ".omni");
|
|
136653
|
+
return join17(base, "logs");
|
|
136459
136654
|
}
|
|
136460
136655
|
function getDiagnosticsPath(startedAt) {
|
|
136461
136656
|
const safe = startedAt.replace(/:/g, "-");
|
|
136462
|
-
return
|
|
136657
|
+
return join17(getDiagnosticsDir(), `update-diagnostics-${safe}.json`);
|
|
136463
136658
|
}
|
|
136464
136659
|
function tailFileLines(path, maxLines) {
|
|
136465
|
-
if (!
|
|
136660
|
+
if (!existsSync18(path))
|
|
136466
136661
|
return [];
|
|
136467
136662
|
try {
|
|
136468
|
-
const raw2 =
|
|
136663
|
+
const raw2 = readFileSync12(path, "utf8");
|
|
136469
136664
|
const lines = raw2.split(/\r?\n/);
|
|
136470
136665
|
if (lines.length > 0 && lines[lines.length - 1] === "")
|
|
136471
136666
|
lines.pop();
|
|
@@ -136498,10 +136693,10 @@ function writeDiagnostics(state, exitCode) {
|
|
|
136498
136693
|
const dir = getDiagnosticsDir();
|
|
136499
136694
|
const path = getDiagnosticsPath(state.startedAt);
|
|
136500
136695
|
try {
|
|
136501
|
-
if (!
|
|
136502
|
-
|
|
136696
|
+
if (!existsSync18(dir)) {
|
|
136697
|
+
mkdirSync11(dir, { recursive: true, mode: 448 });
|
|
136503
136698
|
}
|
|
136504
|
-
|
|
136699
|
+
writeFileSync10(path, `${JSON.stringify(state, null, 2)}
|
|
136505
136700
|
`, { mode: 384 });
|
|
136506
136701
|
return path;
|
|
136507
136702
|
} catch {
|
|
@@ -136672,7 +136867,7 @@ function printVerifySkippedBanner(latest) {
|
|
|
136672
136867
|
}
|
|
136673
136868
|
function detectParallelNpmGlobalInstall(deps) {
|
|
136674
136869
|
const npmRootFn = deps?.npmRoot ?? defaultNpmRoot;
|
|
136675
|
-
const existsFn = deps?.exists ??
|
|
136870
|
+
const existsFn = deps?.exists ?? existsSync19;
|
|
136676
136871
|
let root;
|
|
136677
136872
|
try {
|
|
136678
136873
|
root = npmRootFn();
|
|
@@ -136682,7 +136877,7 @@ function detectParallelNpmGlobalInstall(deps) {
|
|
|
136682
136877
|
if (root === null || root.length === 0) {
|
|
136683
136878
|
return { detected: false, skipped: "npm-not-on-path" };
|
|
136684
136879
|
}
|
|
136685
|
-
const candidate =
|
|
136880
|
+
const candidate = join18(root, "@automagik", "omni");
|
|
136686
136881
|
if (existsFn(candidate)) {
|
|
136687
136882
|
return { detected: true, path: candidate };
|
|
136688
136883
|
}
|
|
@@ -137079,9 +137274,9 @@ function createVoiceCommand() {
|
|
|
137079
137274
|
const startTime = Date.now();
|
|
137080
137275
|
let saveDir = "";
|
|
137081
137276
|
if (opts.save) {
|
|
137082
|
-
const { mkdirSync:
|
|
137277
|
+
const { mkdirSync: mkdirSync12 } = await import("fs");
|
|
137083
137278
|
saveDir = opts.save;
|
|
137084
|
-
|
|
137279
|
+
mkdirSync12(saveDir, { recursive: true });
|
|
137085
137280
|
info(`Saving audio to: ${saveDir}`);
|
|
137086
137281
|
}
|
|
137087
137282
|
ws.onopen = () => {
|
|
@@ -137305,17 +137500,17 @@ init_config();
|
|
|
137305
137500
|
init_output();
|
|
137306
137501
|
|
|
137307
137502
|
// src/manifest-pin.ts
|
|
137308
|
-
import { existsSync as
|
|
137309
|
-
import { homedir as
|
|
137310
|
-
import { join as
|
|
137503
|
+
import { existsSync as existsSync20, readFileSync as readFileSync13, renameSync as renameSync3, writeFileSync as writeFileSync11 } from "fs";
|
|
137504
|
+
import { homedir as homedir13 } from "os";
|
|
137505
|
+
import { join as join19 } from "path";
|
|
137311
137506
|
var PACKAGE_NAME2 = "@automagik/omni";
|
|
137312
|
-
var BUN_GLOBAL_MANIFEST =
|
|
137507
|
+
var BUN_GLOBAL_MANIFEST = join19(homedir13(), ".bun", "install", "global", "package.json");
|
|
137313
137508
|
function pinManifestEntry(manifestPath, exactVersion) {
|
|
137314
|
-
if (!
|
|
137509
|
+
if (!existsSync20(manifestPath))
|
|
137315
137510
|
return false;
|
|
137316
137511
|
let manifest;
|
|
137317
137512
|
try {
|
|
137318
|
-
manifest = JSON.parse(
|
|
137513
|
+
manifest = JSON.parse(readFileSync13(manifestPath, "utf-8"));
|
|
137319
137514
|
} catch {
|
|
137320
137515
|
return false;
|
|
137321
137516
|
}
|
|
@@ -137341,7 +137536,7 @@ function pinManifestEntry(manifestPath, exactVersion) {
|
|
|
137341
137536
|
return false;
|
|
137342
137537
|
const tmp = `${manifestPath}.tmp.${process.pid}`;
|
|
137343
137538
|
try {
|
|
137344
|
-
|
|
137539
|
+
writeFileSync11(tmp, `${JSON.stringify(manifest, null, 2)}
|
|
137345
137540
|
`, { mode: 420 });
|
|
137346
137541
|
renameSync3(tmp, manifestPath);
|
|
137347
137542
|
} catch {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"canonical-pgserve.d.ts","sourceRoot":"","sources":["../../src/lib/canonical-pgserve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;
|
|
1
|
+
{"version":3,"file":"canonical-pgserve.d.ts","sourceRoot":"","sources":["../../src/lib/canonical-pgserve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AA8OH;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA6BpE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,iCAAiC,CACrD,WAAW,EAAE,OAAO,EACpB,GAAG,EAAE;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,GAC3B,OAAO,CAAC,OAAO,CAAC,CA6BlB;AAwDD;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,IAAI,MAAM,CASnD;AAuCD;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAC1B;IAAE,MAAM,EAAE,kBAAkB,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,MAAM,EAAE,uBAAuB,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACxD;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnF;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,cAAc,CAAC,kBAAkB,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA6D5F;AAED;;;;;;;;GAQG;AACH,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,kBAAkB,EACxB,oBAAoB,EAAE,MAAM,GAC3B,OAAO,CAAC;IAAE,MAAM,EAAE,UAAU,GAAG,SAAS,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAoCpE"}
|
|
@@ -75,21 +75,25 @@ export declare function resolvePgserveControlSocketPath(): string;
|
|
|
75
75
|
export declare function probeCanonicalSocketSync(): boolean;
|
|
76
76
|
/**
|
|
77
77
|
* Build a `postgresql://` URL pointing at the given transport, using the
|
|
78
|
-
* supplied database name.
|
|
79
|
-
* SHARED-DESIGN.md §5.3 (omni-side scope).
|
|
78
|
+
* supplied database name.
|
|
80
79
|
*
|
|
81
|
-
* UDS shape: `postgresql://postgres:postgres@localhost/omni
|
|
80
|
+
* UDS shape: `postgresql://postgres:postgres@localhost/omni` (plain — no
|
|
81
|
+
* libpq `?host=` query param). Socket routing happens via the
|
|
82
|
+
* PGHOST/PGPORT env vars `buildRuntimeEnv` publishes alongside this URL.
|
|
82
83
|
* TCP shape: `postgresql://postgres:postgres@127.0.0.1:5432/omni`
|
|
83
84
|
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
85
|
+
* Why no `?host=` for UDS: postgres.js (omni-api's client) rejects URLs
|
|
86
|
+
* carrying the libpq `?host=` query parameter with the error
|
|
87
|
+
* `unrecognized configuration parameter "host"`. That parameter is a
|
|
88
|
+
* libpq-only convention; postgres.js parses URL query params strictly as
|
|
89
|
+
* connection options and bails. Earlier iterations of this helper tried
|
|
90
|
+
* three shapes that all failed for postgres.js:
|
|
91
|
+
* - `postgresql://user:pass@/db?host=/sock` → Node WHATWG URL: Invalid URL
|
|
92
|
+
* - `postgresql://user:pass@localhost/db?host=/sock` → postgres.js:
|
|
93
|
+
* "unrecognized configuration parameter host"
|
|
94
|
+
* The working shape is the plain `@localhost/db` form, with the actual
|
|
95
|
+
* socket path supplied to postgres.js via PGHOST/PGPORT env vars (which
|
|
96
|
+
* postgres.js inherits as connection defaults).
|
|
93
97
|
*
|
|
94
98
|
* The username/password pair is preserved (not derived from the transport)
|
|
95
99
|
* because omni's pgserve consumer keeps libpq peer-auth via password —
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pgserve-transport.d.ts","sourceRoot":"","sources":["../../src/lib/pgserve-transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAQH,8FAA8F;AAC9F,eAAO,MAAM,iBAAiB,OAAO,CAAC;AActC;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACjD;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAIhD;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,IAAI,MAAM,CAEtD;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,IAAI,MAAM,CAExD;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,IAAI,OAAO,CAElD;AAED
|
|
1
|
+
{"version":3,"file":"pgserve-transport.d.ts","sourceRoot":"","sources":["../../src/lib/pgserve-transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAQH,8FAA8F;AAC9F,eAAO,MAAM,iBAAiB,OAAO,CAAC;AActC;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACjD;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAIhD;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,IAAI,MAAM,CAEtD;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,IAAI,MAAM,CAExD;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,IAAI,OAAO,CAElD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,4BAA4B,CAC1C,SAAS,EAAE,gBAAgB,EAC3B,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GACrD,MAAM,CAWR;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,gBAAgB,CAAC,CA+BzE"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dedicated-role cutover — omni-side scoped non-superuser identity.
|
|
3
|
+
*
|
|
4
|
+
* Wish parity: mirrors genie's `src/lib/role-cutover.ts` (the
|
|
5
|
+
* `genie-dedicated-role-cutover` wish). Omni historically connected to
|
|
6
|
+
* canonical pgserve/autopg as the cluster superuser `postgres:postgres`.
|
|
7
|
+
* A bad omni migration or a compromised omni-api could therefore
|
|
8
|
+
* `DROP DATABASE genie`, exhaust the cluster, create roles, etc. —
|
|
9
|
+
* the same blast-radius problem genie solved with role-cutover.
|
|
10
|
+
*
|
|
11
|
+
* This module provisions a dedicated NON-superuser role scoped to omni's
|
|
12
|
+
* own `omni` database, persists the credential in a sentinel file, and
|
|
13
|
+
* is consumed by `buildRuntimeEnv` to rewrite `DATABASE_URL` to the
|
|
14
|
+
* scoped role at omni-api startup.
|
|
15
|
+
*
|
|
16
|
+
* Scope (MVP):
|
|
17
|
+
* - Provision `pgserve_omni_<fp12>_role` with grants scoped to `omni` DB
|
|
18
|
+
* - Generate a random password at provisioning, persist in sentinel
|
|
19
|
+
* - Idempotent: existing role → refresh grants, regenerate sentinel from
|
|
20
|
+
* password (preserves the operator-visible role identifier)
|
|
21
|
+
* - Kill switch: `OMNI_ROLE_CUTOVER=0` forces legacy `postgres`/`postgres`
|
|
22
|
+
* - Best-effort: any failure logs a warning and falls back to legacy creds
|
|
23
|
+
*
|
|
24
|
+
* Out of scope (deferred to a follow-up wish, matching genie's groups):
|
|
25
|
+
* - Advisory-lock concurrency guards (multi-host simultaneous installs)
|
|
26
|
+
* - Full event sink with audit log + sentinel rotation
|
|
27
|
+
* - Per-tenant fingerprint stability handling beyond package.json
|
|
28
|
+
* - doctor.ts validation that the scoped role is in active use
|
|
29
|
+
* - Migration of pre-cutover objects' ownership to the scoped role
|
|
30
|
+
*/
|
|
31
|
+
/**
|
|
32
|
+
* Compute the scoped role name for an omni install. Deterministic — same
|
|
33
|
+
* install always produces the same role name across reruns.
|
|
34
|
+
*/
|
|
35
|
+
export declare function deriveOmniScopedRoleName(): string;
|
|
36
|
+
export interface OmniRoleCutoverSentinel {
|
|
37
|
+
/** The provisioned role name (matches deriveOmniScopedRoleName output). */
|
|
38
|
+
roleName: string;
|
|
39
|
+
/** Database the role is scoped to (always `omni`). */
|
|
40
|
+
database: string;
|
|
41
|
+
/** Generated password (alphanumeric). */
|
|
42
|
+
password: string;
|
|
43
|
+
/** ISO timestamp of provisioning. */
|
|
44
|
+
provisionedAt: string;
|
|
45
|
+
}
|
|
46
|
+
export declare function readOmniCutoverSentinel(): OmniRoleCutoverSentinel | null;
|
|
47
|
+
export declare function clearOmniCutoverSentinel(): void;
|
|
48
|
+
export declare function isOmniRoleCutoverEnabled(): boolean;
|
|
49
|
+
export interface EnsureOmniScopedRoleOptions {
|
|
50
|
+
/** Path to autopg's canonical Unix socket dir (e.g. /run/user/1000/pgserve). */
|
|
51
|
+
socketDir: string;
|
|
52
|
+
/** Canonical port (default 5432). */
|
|
53
|
+
port?: number;
|
|
54
|
+
/** Database to scope grants to (default 'omni'). */
|
|
55
|
+
database?: string;
|
|
56
|
+
/** Force-enable bypassing the OMNI_ROLE_CUTOVER kill switch (tests). */
|
|
57
|
+
enabled?: boolean;
|
|
58
|
+
}
|
|
59
|
+
export type EnsureOmniScopedRoleResult = {
|
|
60
|
+
status: 'provisioned' | 'refreshed';
|
|
61
|
+
roleName: string;
|
|
62
|
+
} | {
|
|
63
|
+
status: 'skipped';
|
|
64
|
+
reason: string;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Idempotently provision omni's scoped role + grants on canonical pgserve.
|
|
68
|
+
*
|
|
69
|
+
* Side effects:
|
|
70
|
+
* - CREATE ROLE if not exists (or ALTER PASSWORD if exists to keep sentinel in sync)
|
|
71
|
+
* - GRANTs scoped to the omni database
|
|
72
|
+
* - Sentinel written at ~/.omni/scoped-role.json
|
|
73
|
+
*
|
|
74
|
+
* Failure mode: best-effort. Any psql / spawn failure returns
|
|
75
|
+
* `{ status: 'skipped', reason }` and emits a stderr warn. omni-api
|
|
76
|
+
* continues with the legacy `postgres:postgres` path.
|
|
77
|
+
*/
|
|
78
|
+
export declare function ensureOmniScopedRole(opts: EnsureOmniScopedRoleOptions): Promise<EnsureOmniScopedRoleResult>;
|
|
79
|
+
export interface ScopedCredentialOverride {
|
|
80
|
+
username: string;
|
|
81
|
+
password: string;
|
|
82
|
+
roleName: string;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Returns the scoped-role credentials to override `postgres:postgres` with
|
|
86
|
+
* at runtime, or null when cutover is disabled / sentinel missing / kill
|
|
87
|
+
* switch active. Pure: no DB roundtrip.
|
|
88
|
+
*
|
|
89
|
+
* Consumed by buildRuntimeEnv when constructing DATABASE_URL.
|
|
90
|
+
*/
|
|
91
|
+
export declare function resolveOmniScopedCredentials(): ScopedCredentialOverride | null;
|
|
92
|
+
//# sourceMappingURL=role-cutover.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"role-cutover.d.ts","sourceRoot":"","sources":["../../src/lib/role-cutover.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AA+BH;;;GAGG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CAUjD;AAqBD,MAAM,WAAW,uBAAuB;IACtC,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,QAAQ,EAAE,MAAM,CAAC;IACjB,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,qCAAqC;IACrC,aAAa,EAAE,MAAM,CAAC;CACvB;AAUD,wBAAgB,uBAAuB,IAAI,uBAAuB,GAAG,IAAI,CAkBxE;AASD,wBAAgB,wBAAwB,IAAI,IAAI,CAM/C;AAMD,wBAAgB,wBAAwB,IAAI,OAAO,CAElD;AAWD,MAAM,WAAW,2BAA2B;IAC1C,gFAAgF;IAChF,SAAS,EAAE,MAAM,CAAC;IAClB,qCAAqC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,MAAM,0BAA0B,GAClC;IAAE,MAAM,EAAE,aAAa,GAAG,WAAW,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1C;;;;;;;;;;;GAWG;AACH,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,2BAA2B,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAyEjH;AA0CD,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,wBAAgB,4BAA4B,IAAI,wBAAwB,GAAG,IAAI,CAc9E"}
|
package/dist/runtime-env.d.ts
CHANGED
|
@@ -101,6 +101,15 @@ export declare function resolvePgservePort(serverConfig: ServerConfig): number;
|
|
|
101
101
|
* This function never reads `process.env.DATABASE_URL`.
|
|
102
102
|
*/
|
|
103
103
|
export declare function resolveDatabaseUrl(serverConfig: ServerConfig): string;
|
|
104
|
+
/**
|
|
105
|
+
* Replace the userinfo in a postgresql:// URL with the scoped-role
|
|
106
|
+
* credentials. Returns the URL unchanged when `creds` is null. Pure;
|
|
107
|
+
* URL-safe via WHATWG URL.
|
|
108
|
+
*/
|
|
109
|
+
export declare function applyScopedCredentials(url: string, creds: {
|
|
110
|
+
username: string;
|
|
111
|
+
password: string;
|
|
112
|
+
} | null): string;
|
|
104
113
|
/**
|
|
105
114
|
* Build the complete runtime env for the omni-api process.
|
|
106
115
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime-env.d.ts","sourceRoot":"","sources":["../src/runtime-env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"runtime-env.d.ts","sourceRoot":"","sources":["../src/runtime-env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AASxD;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IAQrB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAQF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,oBAAoB,OAAO,CAAC;AAEzC,0EAA0E;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAE/D;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,GAAE,MAA6B,GAAG,MAAM,CAE3F;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,IAAI,MAAM,CAKxD;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,YAAY,GAAG,MAAM,CAMrE;AAgBD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,YAAY,GAAG,MAAM,CAiBrE;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAAG,MAAM,CAWhH;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,GAAG,UAAU,CAqCzF"}
|
package/dist/server/index.js
CHANGED
|
@@ -230137,7 +230137,7 @@ var init_sentry_scrub = __esm(() => {
|
|
|
230137
230137
|
var require_package8 = __commonJS((exports, module) => {
|
|
230138
230138
|
module.exports = {
|
|
230139
230139
|
name: "@omni/api",
|
|
230140
|
-
version: "2.260520.
|
|
230140
|
+
version: "2.260520.11",
|
|
230141
230141
|
type: "module",
|
|
230142
230142
|
exports: {
|
|
230143
230143
|
".": {
|