@automagik/omni 2.260520.14 → 2.260520.16

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.
@@ -49,7 +49,7 @@ import { type EmbeddedDumpResult } from '../lib/canonical-pgserve.js';
49
49
  /** Severity levels reported by each check. */
50
50
  export type CheckLevel = 'OK' | 'WARN' | 'FAIL';
51
51
  /** Identifier used in tests and --json output. */
52
- export type CheckId = 'pm2-env-drift' | 'cli-key-valid' | 'pgserve-reachable' | 'omni-db-exists' | 'orphaned-data-dirs' | 'version-match' | 'pm2-status' | 'pm2-max-restarts' | 'pm2-logrotate-installed' | 'cli-signing-key-for-locked-instances' | 'pgserve-canonical' | 'port-canonical-owner';
52
+ export type CheckId = 'pm2-env-drift' | 'cli-key-valid' | 'pgserve-reachable' | 'omni-db-exists' | 'orphaned-data-dirs' | 'version-match' | 'pm2-status' | 'pm2-max-restarts' | 'pm2-logrotate-installed' | 'cli-signing-key-for-locked-instances' | 'pgserve-canonical' | 'port-canonical-owner' | 'embedded-data-orphaned';
53
53
  export interface CheckResult {
54
54
  id: CheckId;
55
55
  level: CheckLevel;
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -4660,6 +4660,271 @@ var require_cli_spinners = __commonJS((exports, module) => {
4660
4660
  module.exports = spinners;
4661
4661
  });
4662
4662
 
4663
+ // src/lib/embedded-canonical-migration.ts
4664
+ var exports_embedded_canonical_migration = {};
4665
+ __export(exports_embedded_canonical_migration, {
4666
+ migrateUnmountedEmbeddedToCanonical: () => migrateUnmountedEmbeddedToCanonical,
4667
+ compareEmbeddedVsCanonicalCounts: () => compareEmbeddedVsCanonicalCounts,
4668
+ EMBEDDED_PGSERVE_DATA_DIR: () => EMBEDDED_PGSERVE_DATA_DIR
4669
+ });
4670
+ import { spawn, spawnSync as spawnSync2 } from "child_process";
4671
+ import { existsSync as existsSync9, mkdtempSync } from "fs";
4672
+ import { createServer } from "net";
4673
+ import { homedir as homedir7, tmpdir } from "os";
4674
+ import { join as join11 } from "path";
4675
+ import { setTimeout as sleep2 } from "timers/promises";
4676
+ function defaultLog(line) {
4677
+ process.stdout.write(`${line}
4678
+ `);
4679
+ }
4680
+ function findAutopgPostgresBinary() {
4681
+ const autopgRoot = join11(homedir7(), ".local", "share", "autopg");
4682
+ if (!existsSync9(autopgRoot))
4683
+ return null;
4684
+ let bestPath = null;
4685
+ for (const entry of safeReaddir(autopgRoot)) {
4686
+ const candidate = join11(autopgRoot, entry, "postgres", "bin", "postgres");
4687
+ if (existsSync9(candidate))
4688
+ bestPath = candidate;
4689
+ }
4690
+ return bestPath;
4691
+ }
4692
+ function safeReaddir(path) {
4693
+ try {
4694
+ const { readdirSync: readdirSync2 } = __require("fs");
4695
+ return readdirSync2(path);
4696
+ } catch {
4697
+ return [];
4698
+ }
4699
+ }
4700
+ async function findFreePort() {
4701
+ return new Promise((resolve, reject) => {
4702
+ const server = createServer();
4703
+ server.unref();
4704
+ server.on("error", reject);
4705
+ server.listen(0, "127.0.0.1", () => {
4706
+ const addr = server.address();
4707
+ if (!addr || typeof addr === "string") {
4708
+ server.close();
4709
+ reject(new Error("failed to discover free port"));
4710
+ return;
4711
+ }
4712
+ const port = addr.port;
4713
+ server.close(() => resolve(port));
4714
+ });
4715
+ });
4716
+ }
4717
+ async function spawnTempPostmaster(binary, dataDir, port, log) {
4718
+ const socketDir = mkdtempSync(join11(tmpdir(), "omni-migrate-pg-"));
4719
+ log(` spawning temp postmaster: pid=\u2026 port=${port} socket=${socketDir}`);
4720
+ const child = spawn(binary, [
4721
+ "-D",
4722
+ dataDir,
4723
+ "-p",
4724
+ String(port),
4725
+ "-c",
4726
+ "listen_addresses=127.0.0.1",
4727
+ "-c",
4728
+ `unix_socket_directories=${socketDir}`
4729
+ ], {
4730
+ stdio: ["ignore", "pipe", "pipe"],
4731
+ detached: false
4732
+ });
4733
+ let started = false;
4734
+ let crashed = null;
4735
+ child.stderr?.on("data", (chunk) => {
4736
+ const line = chunk.toString("utf-8");
4737
+ if (!started && /database system is ready to accept connections/.test(line))
4738
+ started = true;
4739
+ });
4740
+ child.on("exit", (code) => {
4741
+ if (!started) {
4742
+ crashed = new Error(`temp postmaster exited with code ${code} before ready`);
4743
+ }
4744
+ });
4745
+ for (let i = 0;i < 200; i++) {
4746
+ if (started)
4747
+ break;
4748
+ if (crashed)
4749
+ throw crashed;
4750
+ await sleep2(100);
4751
+ }
4752
+ if (!started) {
4753
+ child.kill("SIGTERM");
4754
+ throw new Error("temp postmaster failed to become ready within 20s");
4755
+ }
4756
+ log(` temp postmaster ready (pid=${child.pid})`);
4757
+ return {
4758
+ pid: child.pid ?? -1,
4759
+ socketDir,
4760
+ async stop() {
4761
+ log(" stopping temp postmaster (SIGTERM)");
4762
+ child.kill("SIGTERM");
4763
+ await new Promise((resolve) => {
4764
+ const onExit2 = () => resolve();
4765
+ child.once("exit", onExit2);
4766
+ setTimeout(() => {
4767
+ child.kill("SIGKILL");
4768
+ onExit2();
4769
+ }, 1e4);
4770
+ });
4771
+ }
4772
+ };
4773
+ }
4774
+ function psqlCapture(args) {
4775
+ const result = spawnSync2("psql", args, {
4776
+ encoding: "utf-8",
4777
+ env: { ...process.env, PGPASSWORD: "postgres" },
4778
+ timeout: 60000
4779
+ });
4780
+ if (result.status !== 0) {
4781
+ throw new Error(`psql exited ${result.status}: ${result.stderr?.trim() ?? ""}`);
4782
+ }
4783
+ return result.stdout ?? "";
4784
+ }
4785
+ async function copyTable(table, srcArgs, dstArgs, log) {
4786
+ const src = spawn("psql", [...srcArgs, "-c", `\\copy public.${table} TO STDOUT`], {
4787
+ stdio: ["ignore", "pipe", "pipe"],
4788
+ env: { ...process.env, PGPASSWORD: "postgres" }
4789
+ });
4790
+ const dst = spawn("psql", [...dstArgs, "-c", `SET session_replication_role='replica';`, "-c", `\\copy public.${table} FROM STDIN`], {
4791
+ stdio: ["pipe", "pipe", "pipe"],
4792
+ env: { ...process.env, PGPASSWORD: "postgres" }
4793
+ });
4794
+ if (!src.stdout || !dst.stdin)
4795
+ throw new Error(`copy stream not available for ${table}`);
4796
+ src.stdout.pipe(dst.stdin);
4797
+ let dstErr = "";
4798
+ dst.stderr?.on("data", (b) => {
4799
+ dstErr += b.toString("utf-8");
4800
+ });
4801
+ const srcExited = new Promise((resolve) => src.once("exit", (code) => resolve(code ?? -1)));
4802
+ const dstExited = new Promise((resolve) => dst.once("exit", (code) => resolve(code ?? -1)));
4803
+ const [sc, dc] = await Promise.all([srcExited, dstExited]);
4804
+ if (sc !== 0 || dc !== 0) {
4805
+ throw new Error(`copy ${table} failed (src=${sc} dst=${dc}): ${dstErr.trim()}`);
4806
+ }
4807
+ log(` copied ${table}`);
4808
+ }
4809
+ function resetSequences(dstArgs, log) {
4810
+ const script = `
4811
+ SELECT format(
4812
+ 'SELECT setval(%L::regclass, GREATEST(COALESCE((SELECT max(%I) FROM %I.%I), 1), 1));',
4813
+ pg_get_serial_sequence(c.table_schema || '.' || c.table_name, c.column_name),
4814
+ c.column_name, c.table_schema, c.table_name
4815
+ )
4816
+ FROM information_schema.columns c
4817
+ WHERE pg_get_serial_sequence(c.table_schema || '.' || c.table_name, c.column_name) IS NOT NULL
4818
+ AND c.table_schema = 'public';
4819
+ `.trim();
4820
+ const lines = psqlCapture([...dstArgs, "-tAc", script]).split(`
4821
+ `).map((l) => l.trim()).filter(Boolean);
4822
+ if (lines.length === 0)
4823
+ return;
4824
+ log(` resetting ${lines.length} sequence(s)`);
4825
+ psqlCapture([...dstArgs, "-c", lines.join(`
4826
+ `)]);
4827
+ }
4828
+ async function compareEmbeddedVsCanonicalCounts(opts = {}) {
4829
+ const canonicalPort = opts.canonicalPort ?? 5432;
4830
+ if (!existsSync9(EMBEDDED_DIR) || !existsSync9(join11(EMBEDDED_DIR, "PG_VERSION"))) {
4831
+ return { kind: "skipped", reason: "embedded dir absent" };
4832
+ }
4833
+ const binary = findAutopgPostgresBinary();
4834
+ if (!binary)
4835
+ return { kind: "skipped", reason: "autopg postgres binary not found" };
4836
+ const tempPort = await findFreePort();
4837
+ let temp = null;
4838
+ try {
4839
+ temp = await spawnTempPostmaster(binary, EMBEDDED_DIR, tempPort, () => {});
4840
+ const srcArgs = ["-h", "127.0.0.1", "-p", String(tempPort), "-U", "postgres", "-d", "omni"];
4841
+ const dstArgs = ["-h", "127.0.0.1", "-p", String(canonicalPort), "-U", "postgres", "-d", "omni"];
4842
+ const tablesRaw = psqlCapture([
4843
+ ...srcArgs,
4844
+ "-tAc",
4845
+ `SELECT tablename FROM pg_tables WHERE schemaname='public' ORDER BY tablename`
4846
+ ]);
4847
+ const tables = tablesRaw.split(`
4848
+ `).map((s) => s.trim()).filter(Boolean);
4849
+ if (tables.length === 0)
4850
+ return { kind: "skipped", reason: "embedded has no public tables" };
4851
+ const divergent = [];
4852
+ let totalExtra = 0;
4853
+ for (const t of tables) {
4854
+ try {
4855
+ const em = Number.parseInt(psqlCapture([...srcArgs, "-tAc", `SELECT count(*) FROM public.${t}`]).trim(), 10);
4856
+ const ca = Number.parseInt(psqlCapture([...dstArgs, "-tAc", `SELECT count(*) FROM public.${t}`]).trim(), 10);
4857
+ if (Number.isFinite(em) && Number.isFinite(ca) && em > ca) {
4858
+ divergent.push(t);
4859
+ totalExtra += em - ca;
4860
+ }
4861
+ } catch {
4862
+ divergent.push(t);
4863
+ }
4864
+ }
4865
+ if (divergent.length === 0)
4866
+ return { kind: "in-sync" };
4867
+ return { kind: "embedded-has-more", divergentTables: divergent, embeddedRows: totalExtra };
4868
+ } catch (err) {
4869
+ return { kind: "skipped", reason: err instanceof Error ? err.message : String(err) };
4870
+ } finally {
4871
+ if (temp)
4872
+ await temp.stop();
4873
+ }
4874
+ }
4875
+ async function migrateUnmountedEmbeddedToCanonical(opts = {}) {
4876
+ const log = opts.log ?? defaultLog;
4877
+ const canonicalPort = opts.canonicalPort ?? 5432;
4878
+ if (!existsSync9(EMBEDDED_DIR)) {
4879
+ return { status: "skipped", reason: "no embedded data dir" };
4880
+ }
4881
+ if (!existsSync9(join11(EMBEDDED_DIR, "PG_VERSION"))) {
4882
+ return { status: "skipped", reason: "embedded dir missing PG_VERSION" };
4883
+ }
4884
+ const binary = findAutopgPostgresBinary();
4885
+ if (!binary) {
4886
+ return { status: "skipped", reason: "autopg postgres binary not found \u2014 install autopg first" };
4887
+ }
4888
+ log(` using postgres binary: ${binary}`);
4889
+ const tempPort = await findFreePort();
4890
+ const t0 = Date.now();
4891
+ const temp = await spawnTempPostmaster(binary, EMBEDDED_DIR, tempPort, log);
4892
+ try {
4893
+ const srcBaseArgs = ["-h", "127.0.0.1", "-p", String(tempPort), "-U", "postgres", "-d", "omni"];
4894
+ const dstBaseArgs = ["-h", "127.0.0.1", "-p", String(canonicalPort), "-U", "postgres", "-d", "omni"];
4895
+ const tablesRaw = psqlCapture([
4896
+ ...srcBaseArgs,
4897
+ "-tAc",
4898
+ `SELECT tablename FROM pg_tables WHERE schemaname='public' ORDER BY tablename`
4899
+ ]);
4900
+ const tables = tablesRaw.split(`
4901
+ `).map((s) => s.trim()).filter(Boolean);
4902
+ if (tables.length === 0) {
4903
+ return { status: "skipped", reason: "embedded omni has no public tables" };
4904
+ }
4905
+ log(` ${tables.length} tables to migrate`);
4906
+ const truncateList = tables.map((t) => `public.${t}`).join(",");
4907
+ psqlCapture([
4908
+ ...dstBaseArgs,
4909
+ "-c",
4910
+ `SET session_replication_role='replica'; TRUNCATE ${truncateList} RESTART IDENTITY CASCADE;`
4911
+ ]);
4912
+ log(" truncated canonical (CASCADE)");
4913
+ for (const t of tables) {
4914
+ await copyTable(t, srcBaseArgs, dstBaseArgs, log);
4915
+ }
4916
+ resetSequences(dstBaseArgs, log);
4917
+ return { status: "migrated", tables: tables.length, durationMs: Date.now() - t0 };
4918
+ } finally {
4919
+ await temp.stop();
4920
+ }
4921
+ }
4922
+ var EMBEDDED_DIR, EMBEDDED_PGSERVE_DATA_DIR;
4923
+ var init_embedded_canonical_migration = __esm(() => {
4924
+ EMBEDDED_DIR = join11(homedir7(), ".omni", "data", "pgserve");
4925
+ EMBEDDED_PGSERVE_DATA_DIR = EMBEDDED_DIR;
4926
+ });
4927
+
4663
4928
  // ../../node_modules/.bun/qrcode-terminal@0.12.0/node_modules/qrcode-terminal/vendor/QRCode/QRMode.js
4664
4929
  var require_QRMode = __commonJS((exports, module) => {
4665
4930
  module.exports = {
@@ -13153,10 +13418,10 @@ var require_nkeys = __commonJS((exports) => {
13153
13418
  return createPair(Prefix.Cluster);
13154
13419
  }
13155
13420
  exports.createCluster = createCluster;
13156
- function createServer() {
13421
+ function createServer2() {
13157
13422
  return createPair(Prefix.Server);
13158
13423
  }
13159
- exports.createServer = createServer;
13424
+ exports.createServer = createServer2;
13160
13425
  function createCurve() {
13161
13426
  return createPair(Prefix.Curve);
13162
13427
  }
@@ -22772,7 +23037,7 @@ var require_node_transport = __commonJS((exports) => {
22772
23037
  var util_1 = require_util();
22773
23038
  var tls_1 = __require("tls");
22774
23039
  var { resolve: resolve2 } = __require("path");
22775
- var { readFile, existsSync: existsSync12 } = __require("fs");
23040
+ var { readFile, existsSync: existsSync13 } = __require("fs");
22776
23041
  var dns = __require("dns");
22777
23042
  var VERSION2 = "2.29.3";
22778
23043
  var LANG = "nats.js";
@@ -22888,7 +23153,7 @@ var require_node_transport = __commonJS((exports) => {
22888
23153
  const d = (0, nats_base_client_1.deferred)();
22889
23154
  try {
22890
23155
  fn = resolve2(fn);
22891
- if (!existsSync12(fn)) {
23156
+ if (!existsSync13(fn)) {
22892
23157
  d.reject(new Error(`${fn} doesn't exist`));
22893
23158
  }
22894
23159
  readFile(fn, (err, data2) => {
@@ -61798,12 +62063,12 @@ class A2AClient {
61798
62063
  if (state === "completed" || state === "failed") {
61799
62064
  return this.taskToProviderResponse(task, taskId, startMs);
61800
62065
  }
61801
- await sleep2(POLL_INTERVAL_MS);
62066
+ await sleep3(POLL_INTERVAL_MS);
61802
62067
  }
61803
62068
  throw new ProviderError("A2A task polling exhausted", "TIMEOUT", undefined, { taskId });
61804
62069
  }
61805
62070
  }
61806
- function sleep2(ms) {
62071
+ function sleep3(ms) {
61807
62072
  return new Promise((resolve2) => setTimeout(resolve2, ms));
61808
62073
  }
61809
62074
  function createA2AClient(config2) {
@@ -61931,8 +62196,8 @@ var init_a2a_provider = __esm(() => {
61931
62196
 
61932
62197
  // ../core/src/providers/nats-genie-provider.ts
61933
62198
  import { mkdir, writeFile } from "fs/promises";
61934
- import { homedir as homedir9 } from "os";
61935
- import { join as join15 } from "path";
62199
+ import { homedir as homedir10 } from "os";
62200
+ import { join as join16 } from "path";
61936
62201
 
61937
62202
  class NatsGenieProvider {
61938
62203
  id;
@@ -62122,10 +62387,10 @@ class NatsGenieProvider {
62122
62387
  }
62123
62388
  async writeDeadLetter(payload, error2) {
62124
62389
  try {
62125
- const dlDir = join15(homedir9(), ".omni", "dead-letters");
62390
+ const dlDir = join16(homedir10(), ".omni", "dead-letters");
62126
62391
  await mkdir(dlDir, { recursive: true });
62127
62392
  const filename = `nats-genie-${Date.now()}-${payload.chatId}.json`;
62128
- await writeFile(join15(dlDir, filename), JSON.stringify({
62393
+ await writeFile(join16(dlDir, filename), JSON.stringify({
62129
62394
  payload,
62130
62395
  error: error2 instanceof Error ? error2.message : String(error2),
62131
62396
  timestamp: new Date().toISOString()
@@ -64004,7 +64269,7 @@ var init_sql = __esm(() => {
64004
64269
  return new SQL([new StringChunk(str)]);
64005
64270
  }
64006
64271
  sql2.raw = raw2;
64007
- function join16(chunks, separator) {
64272
+ function join17(chunks, separator) {
64008
64273
  const result = [];
64009
64274
  for (const [i6, chunk] of chunks.entries()) {
64010
64275
  if (i6 > 0 && separator !== undefined) {
@@ -64014,7 +64279,7 @@ var init_sql = __esm(() => {
64014
64279
  }
64015
64280
  return new SQL(result);
64016
64281
  }
64017
- sql2.join = join16;
64282
+ sql2.join = join17;
64018
64283
  function identifier(value) {
64019
64284
  return new Name(value);
64020
64285
  }
@@ -67241,7 +67506,7 @@ var init_select2 = __esm(() => {
67241
67506
  return (table2, on) => {
67242
67507
  const baseTableName = this.tableName;
67243
67508
  const tableName = getTableLikeName(table2);
67244
- if (typeof tableName === "string" && this.config.joins?.some((join16) => join16.alias === tableName)) {
67509
+ if (typeof tableName === "string" && this.config.joins?.some((join17) => join17.alias === tableName)) {
67245
67510
  throw new Error(`Alias "${tableName}" is already used in this query`);
67246
67511
  }
67247
67512
  if (!this.isPartialSelect) {
@@ -67752,7 +68017,7 @@ var init_update = __esm(() => {
67752
68017
  createJoin(joinType) {
67753
68018
  return (table2, on) => {
67754
68019
  const tableName = getTableLikeName(table2);
67755
- if (typeof tableName === "string" && this.config.joins.some((join16) => join16.alias === tableName)) {
68020
+ if (typeof tableName === "string" && this.config.joins.some((join17) => join17.alias === tableName)) {
67756
68021
  throw new Error(`Alias "${tableName}" is already used in this query`);
67757
68022
  }
67758
68023
  if (typeof on === "function") {
@@ -67802,10 +68067,10 @@ var init_update = __esm(() => {
67802
68067
  const fromFields = this.getTableLikeFields(this.config.from);
67803
68068
  fields[tableName] = fromFields;
67804
68069
  }
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);
68070
+ for (const join17 of this.config.joins) {
68071
+ const tableName2 = getTableLikeName(join17.table);
68072
+ if (typeof tableName2 === "string" && !is(join17.table, SQL)) {
68073
+ const fromFields = this.getTableLikeFields(join17.table);
67809
68074
  fields[tableName2] = fromFields;
67810
68075
  }
67811
68076
  }
@@ -82474,7 +82739,7 @@ var require_path = __commonJS((exports) => {
82474
82739
  function isAbsolute(path) {
82475
82740
  return path.charAt(0) === "/";
82476
82741
  }
82477
- function join20(...args) {
82742
+ function join21(...args) {
82478
82743
  return normalizePath(args.join("/"));
82479
82744
  }
82480
82745
  function dirname6(path) {
@@ -82499,7 +82764,7 @@ var require_path = __commonJS((exports) => {
82499
82764
  exports.basename = basename6;
82500
82765
  exports.dirname = dirname6;
82501
82766
  exports.isAbsolute = isAbsolute;
82502
- exports.join = join20;
82767
+ exports.join = join21;
82503
82768
  exports.normalizePath = normalizePath;
82504
82769
  exports.relative = relative;
82505
82770
  exports.resolve = resolve4;
@@ -124067,7 +124332,7 @@ import { fileURLToPath } from "url";
124067
124332
  // package.json
124068
124333
  var package_default = {
124069
124334
  name: "@automagik/omni",
124070
- version: "2.260520.14",
124335
+ version: "2.260520.16",
124071
124336
  description: "LLM-optimized CLI for Omni",
124072
124337
  type: "module",
124073
124338
  bin: {
@@ -127889,9 +128154,9 @@ function createDeadLettersCommand() {
127889
128154
  }
127890
128155
 
127891
128156
  // src/commands/doctor.ts
127892
- import { existsSync as existsSync9, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
127893
- import { homedir as homedir7 } from "os";
127894
- import { join as join12, resolve } from "path";
128157
+ import { existsSync as existsSync10, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
128158
+ import { homedir as homedir8 } from "os";
128159
+ import { join as join13, resolve } from "path";
127895
128160
  init_config();
127896
128161
 
127897
128162
  // src/health.ts
@@ -129287,28 +129552,29 @@ function formatBytes(n) {
129287
129552
  }
129288
129553
 
129289
129554
  // src/commands/doctor.ts
129555
+ init_embedded_canonical_migration();
129290
129556
  init_output();
129291
129557
 
129292
129558
  // src/server-bundle.ts
129293
129559
  init_output();
129294
- import { dirname as dirname2, join as join11 } from "path";
129560
+ import { dirname as dirname2, join as join12 } from "path";
129295
129561
  import { fileURLToPath as fileURLToPath2 } from "url";
129296
129562
  function getServerBundlePath() {
129297
129563
  try {
129298
129564
  const thisFile = fileURLToPath2(import.meta.url);
129299
129565
  const distDir = dirname2(thisFile);
129300
- return join11(distDir, "server", "index.js");
129566
+ return join12(distDir, "server", "index.js");
129301
129567
  } catch {
129302
- return join11(process.cwd(), "dist", "server", "index.js");
129568
+ return join12(process.cwd(), "dist", "server", "index.js");
129303
129569
  }
129304
129570
  }
129305
129571
  function getServerLauncherPath() {
129306
129572
  try {
129307
129573
  const thisFile = fileURLToPath2(import.meta.url);
129308
129574
  const distDir = dirname2(thisFile);
129309
- return join11(distDir, "..", "bin", "omni-server");
129575
+ return join12(distDir, "..", "bin", "omni-server");
129310
129576
  } catch {
129311
- return join11(process.cwd(), "bin", "omni-server");
129577
+ return join12(process.cwd(), "bin", "omni-server");
129312
129578
  }
129313
129579
  }
129314
129580
  function bundleNotFoundError(bundlePath) {
@@ -129373,10 +129639,10 @@ function productionDeps() {
129373
129639
  }
129374
129640
  },
129375
129641
  findOrphanedDataDirs: () => {
129376
- const roots = [process.cwd(), join12(homedir7(), "workspace"), join12(homedir7(), "repos")];
129642
+ const roots = [process.cwd(), join13(homedir8(), "workspace"), join13(homedir8(), "repos")];
129377
129643
  const found = [];
129378
129644
  for (const root of roots) {
129379
- if (!existsSync9(root))
129645
+ if (!existsSync10(root))
129380
129646
  continue;
129381
129647
  try {
129382
129648
  scanForOrphans(root, found, 0);
@@ -129484,7 +129750,7 @@ function scanForOrphans(dir, acc, depth, maxDepth = 4) {
129484
129750
  for (const name of entries) {
129485
129751
  if (name === "node_modules" || name === ".git")
129486
129752
  continue;
129487
- const full = join12(dir, name);
129753
+ const full = join13(dir, name);
129488
129754
  let stats;
129489
129755
  try {
129490
129756
  stats = statSync2(full);
@@ -129553,6 +129819,60 @@ async function checkOmniDbExists(deps) {
129553
129819
  }
129554
129820
  return { id: "omni-db-exists", level: "FAIL", detail: "omni database is not reachable" };
129555
129821
  }
129822
+ async function checkEmbeddedDataOrphaned(deps) {
129823
+ const { serverConfig } = deps.loadState();
129824
+ if (serverConfig.useCanonicalPgserve !== true) {
129825
+ return { id: "embedded-data-orphaned", level: "OK", detail: "embedded mode \u2014 no orphan check needed" };
129826
+ }
129827
+ if (!existsSync10(join13(EMBEDDED_PGSERVE_DATA_DIR, "PG_VERSION"))) {
129828
+ return { id: "embedded-data-orphaned", level: "OK", detail: "no embedded data dir present" };
129829
+ }
129830
+ if (!await deps.omniDbExists()) {
129831
+ return {
129832
+ id: "embedded-data-orphaned",
129833
+ level: "OK",
129834
+ detail: "canonical not reachable yet \u2014 embedded check deferred"
129835
+ };
129836
+ }
129837
+ try {
129838
+ const { existsSync: fsExists } = await import("fs");
129839
+ if (!fsExists(EMBEDDED_PGSERVE_DATA_DIR)) {
129840
+ return { id: "embedded-data-orphaned", level: "OK", detail: "no embedded data to compare" };
129841
+ }
129842
+ const { compareEmbeddedVsCanonicalCounts: compareEmbeddedVsCanonicalCounts2 } = await Promise.resolve().then(() => (init_embedded_canonical_migration(), exports_embedded_canonical_migration));
129843
+ const cmp = await compareEmbeddedVsCanonicalCounts2({ canonicalPort: 5432 });
129844
+ if (cmp.kind === "embedded-has-more") {
129845
+ return {
129846
+ id: "embedded-data-orphaned",
129847
+ level: "FAIL",
129848
+ detail: `embedded has ${cmp.embeddedRows} rows in ${cmp.divergentTables.length} tables canonical lacks (${cmp.divergentTables.slice(0, 3).join(", ")}${cmp.divergentTables.length > 3 ? "\u2026" : ""}) \u2014 run \`omni doctor --fix\` to migrate`
129849
+ };
129850
+ }
129851
+ return {
129852
+ id: "embedded-data-orphaned",
129853
+ level: "OK",
129854
+ detail: cmp.kind === "in-sync" ? "embedded \u2194 canonical row counts match" : `compare unavailable: ${cmp.reason}`
129855
+ };
129856
+ } catch (err) {
129857
+ return {
129858
+ id: "embedded-data-orphaned",
129859
+ level: "OK",
129860
+ detail: `compare unavailable: ${err instanceof Error ? err.message : String(err)}`
129861
+ };
129862
+ }
129863
+ }
129864
+ async function fixEmbeddedDataOrphaned(_deps) {
129865
+ raw(" Migrating unmounted embedded pgserve \u2192 canonical autopg...");
129866
+ const result = await migrateUnmountedEmbeddedToCanonical({
129867
+ log: (line) => raw(line)
129868
+ });
129869
+ if (result.status === "skipped") {
129870
+ throw new Error(`migration skipped: ${result.reason}`);
129871
+ }
129872
+ raw(` \u2713 migrated ${result.tables} tables in ${result.durationMs}ms`);
129873
+ raw(" Re-run `omni install --non-interactive` to re-apply scoped-role grants on the restored data.");
129874
+ return `migrated ${result.tables} tables from embedded to canonical (${result.durationMs}ms)`;
129875
+ }
129556
129876
  function checkOrphanedDataDirs(deps) {
129557
129877
  const found = deps.findOrphanedDataDirs();
129558
129878
  if (found.length === 0) {
@@ -129969,7 +130289,8 @@ async function runAllChecks(deps) {
129969
130289
  await checkPm2LogrotateInstalled(deps),
129970
130290
  await checkSigningKeyForLockedInstances(deps),
129971
130291
  checkPgserveCanonical(deps),
129972
- await checkPortCanonicalOwner(deps)
130292
+ await checkPortCanonicalOwner(deps),
130293
+ await checkEmbeddedDataOrphaned(deps)
129973
130294
  ];
129974
130295
  }
129975
130296
  async function applyFix(deps, check) {
@@ -129990,6 +130311,8 @@ async function applyFix(deps, check) {
129990
130311
  return await fixPortCanonicalOwner(deps);
129991
130312
  if (check.id === "pm2-status")
129992
130313
  return await fixPm2Status(deps);
130314
+ if (check.id === "embedded-data-orphaned")
130315
+ return await fixEmbeddedDataOrphaned(deps);
129993
130316
  return null;
129994
130317
  } catch (err) {
129995
130318
  const msg = err instanceof Error ? err.message : String(err);
@@ -130107,7 +130430,7 @@ Safety:
130107
130430
  }
130108
130431
 
130109
130432
  // src/commands/done.ts
130110
- import { existsSync as existsSync10, readFileSync as readFileSync6 } from "fs";
130433
+ import { existsSync as existsSync11, readFileSync as readFileSync6 } from "fs";
130111
130434
  import { basename, extname } from "path";
130112
130435
 
130113
130436
  // src/context.ts
@@ -130216,7 +130539,7 @@ async function handleReact(client, ctx, emoji) {
130216
130539
  await closeTurn(client, "react", `Reacted ${emoji} + turn closed`);
130217
130540
  }
130218
130541
  async function handleMedia(client, ctx, mediaPath, caption) {
130219
- if (!existsSync10(mediaPath)) {
130542
+ if (!existsSync11(mediaPath)) {
130220
130543
  return error(`File not found: ${mediaPath}`);
130221
130544
  }
130222
130545
  try {
@@ -130914,7 +131237,7 @@ function createHistoryCommand() {
130914
131237
 
130915
131238
  // src/commands/imagine.ts
130916
131239
  import { writeFileSync as writeFileSync8 } from "fs";
130917
- import { basename as basename2, dirname as dirname3, extname as extname2, join as join13 } from "path";
131240
+ import { basename as basename2, dirname as dirname3, extname as extname2, join as join14 } from "path";
130918
131241
  init_output();
130919
131242
  var ALLOWED_ASPECT_RATIOS = ["1:1", "4:3", "3:4", "16:9", "9:16", "3:2", "2:3"];
130920
131243
  function extensionForMime(mimeType) {
@@ -130929,9 +131252,9 @@ function buildOutputPath(outputBase, index, total, mimeType) {
130929
131252
  const ext = extname2(outputBase) || extensionForMime(mimeType);
130930
131253
  const stem = basename2(outputBase, extname2(outputBase));
130931
131254
  if (total <= 1) {
130932
- return join13(dir, `${stem}${ext}`);
131255
+ return join14(dir, `${stem}${ext}`);
130933
131256
  }
130934
- return join13(dir, `${stem}-${index + 1}${ext}`);
131257
+ return join14(dir, `${stem}-${index + 1}${ext}`);
130935
131258
  }
130936
131259
  function parseAspectRatio(value) {
130937
131260
  if (!value)
@@ -131049,12 +131372,12 @@ function createImagineCommand() {
131049
131372
  }
131050
131373
 
131051
131374
  // src/commands/install.ts
131052
- import { existsSync as existsSync11, mkdirSync as mkdirSync6 } from "fs";
131053
- import { homedir as homedir8 } from "os";
131054
- import { join as join14 } from "path";
131375
+ import { existsSync as existsSync12, mkdirSync as mkdirSync6 } from "fs";
131376
+ import { homedir as homedir9 } from "os";
131377
+ import { join as join15 } from "path";
131055
131378
  init_config();
131056
131379
  init_output();
131057
- var DEFAULT_DATA_DIR2 = join14(homedir8(), ".omni", "data");
131380
+ var DEFAULT_DATA_DIR2 = join15(homedir9(), ".omni", "data");
131058
131381
  function computeDefaultDatabaseUrl() {
131059
131382
  return buildEmbeddedDatabaseUrl();
131060
131383
  }
@@ -131153,7 +131476,7 @@ async function startServices(cfg, forceCleanup, forceSystemd, useCanonicalPgserv
131153
131476
  return false;
131154
131477
  }
131155
131478
  const bundlePath = getServerBundlePath();
131156
- if (!existsSync11(bundlePath)) {
131479
+ if (!existsSync12(bundlePath)) {
131157
131480
  warn(`Server bundle not found at: ${bundlePath}
131158
131481
  Install @automagik/omni from npm: bun add -g @automagik/omni
131159
131482
  Or build locally: make cli-build-full`);
@@ -131177,9 +131500,9 @@ async function startServices(cfg, forceCleanup, forceSystemd, useCanonicalPgserv
131177
131500
  return false;
131178
131501
  }
131179
131502
  apiSpinner.succeed(`${PM2_PROCESSES.api} started`);
131180
- if (existsSync11(NATS_BINARY_PATH)) {
131503
+ if (existsSync12(NATS_BINARY_PATH)) {
131181
131504
  const natsSpinner = ora(`Starting ${PM2_PROCESSES.nats}...`).start();
131182
- const natsDataDir = join14(cfg.dataDir, "nats");
131505
+ const natsDataDir = join15(cfg.dataDir, "nats");
131183
131506
  mkdirSync6(natsDataDir, { recursive: true });
131184
131507
  const natsArgs = buildPm2StartArgs({
131185
131508
  kind: "nats",
@@ -132856,7 +133179,7 @@ function createLogsCommand() {
132856
133179
  }
132857
133180
 
132858
133181
  // src/commands/media.ts
132859
- import { createWriteStream as createWriteStream2, existsSync as existsSync13, mkdirSync as mkdirSync8, statSync as statSync4 } from "fs";
133182
+ import { createWriteStream as createWriteStream2, existsSync as existsSync14, mkdirSync as mkdirSync8, statSync as statSync4 } from "fs";
132860
133183
  import { basename as basename4, dirname as dirname4, resolve as resolve2 } from "path";
132861
133184
  import { Readable } from "stream";
132862
133185
  import { pipeline } from "stream/promises";
@@ -132919,13 +133242,13 @@ function resolveOutputPath(outputPath, result) {
132919
133242
  const resolved = resolve2(outputPath);
132920
133243
  if (isDirHint)
132921
133244
  return resolve2(resolved, filename);
132922
- if (existsSync13(resolved) && statSync4(resolved).isDirectory())
133245
+ if (existsSync14(resolved) && statSync4(resolved).isDirectory())
132923
133246
  return resolve2(resolved, filename);
132924
133247
  return resolved;
132925
133248
  }
132926
133249
  async function downloadToFile(url, apiKey, destinationPath) {
132927
133250
  const destDir = dirname4(destinationPath);
132928
- if (!existsSync13(destDir))
133251
+ if (!existsSync14(destDir))
132929
133252
  mkdirSync8(destDir, { recursive: true });
132930
133253
  const resp = await fetch(url, {
132931
133254
  method: "GET",
@@ -133879,8 +134202,8 @@ init_output();
133879
134202
  init_src();
133880
134203
  import { execFileSync as execFileSync3, execSync } from "child_process";
133881
134204
  import * as nodeCrypto2 from "crypto";
133882
- import { existsSync as existsSync14, mkdirSync as mkdirSync9, readFileSync as readFileSync9, writeFileSync as writeFileSync9 } from "fs";
133883
- import { homedir as homedir10 } from "os";
134205
+ import { existsSync as existsSync15, mkdirSync as mkdirSync9, readFileSync as readFileSync9, writeFileSync as writeFileSync9 } from "fs";
134206
+ import { homedir as homedir11 } from "os";
133884
134207
  import { dirname as dirname5, resolve as resolve3 } from "path";
133885
134208
  import { createInterface as createInterface2 } from "readline";
133886
134209
  init_config();
@@ -134107,10 +134430,10 @@ async function pairDevice(gatewayUrl, gatewayToken, keypair, spinner) {
134107
134430
  ws.close(1000, "pairing complete");
134108
134431
  }
134109
134432
  }
134110
- var OPENCLAW_CONFIG_PATH = resolve3(homedir10(), ".openclaw", "openclaw.json");
134433
+ var OPENCLAW_CONFIG_PATH = resolve3(homedir11(), ".openclaw", "openclaw.json");
134111
134434
  var PLUGIN_MARKER = "plugin-openclaw/omni.ts";
134112
134435
  function readOpenClawConfig(configPath) {
134113
- if (!existsSync14(configPath))
134436
+ if (!existsSync15(configPath))
134114
134437
  return {};
134115
134438
  const raw2 = readFileSync9(configPath, "utf-8").trim();
134116
134439
  if (!raw2)
@@ -134151,10 +134474,10 @@ function isValidUuid2(value) {
134151
134474
  }
134152
134475
  function resolvePluginPath(explicit) {
134153
134476
  if (explicit) {
134154
- return existsSync14(explicit) ? resolve3(explicit) : null;
134477
+ return existsSync15(explicit) ? resolve3(explicit) : null;
134155
134478
  }
134156
134479
  const cwdCandidate = resolve3(process.cwd(), "packages/plugin-openclaw/omni.ts");
134157
- return existsSync14(cwdCandidate) ? cwdCandidate : null;
134480
+ return existsSync15(cwdCandidate) ? cwdCandidate : null;
134158
134481
  }
134159
134482
  function registerPlugin(config2, pluginPath, configPath) {
134160
134483
  if (hasOpenClawCli()) {
@@ -134864,7 +135187,7 @@ ${formatExamples(examples)}`);
134864
135187
  }
134865
135188
 
134866
135189
  // src/lib/requirements.ts
134867
- import { spawn } from "child_process";
135190
+ import { spawn as spawn2 } from "child_process";
134868
135191
  var REQUIREMENTS = Object.freeze({
134869
135192
  pgserve: ">=2.3",
134870
135193
  genie: ">=5.0"
@@ -134908,7 +135231,7 @@ function fetchPeerVersion(binary) {
134908
135231
  let settled = false;
134909
135232
  let stdout = "";
134910
135233
  let stderr = "";
134911
- const proc = spawn(binary, ["--version"], { stdio: ["ignore", "pipe", "pipe"] });
135234
+ const proc = spawn2(binary, ["--version"], { stdio: ["ignore", "pipe", "pipe"] });
134912
135235
  const timer2 = setTimeout(() => {
134913
135236
  if (settled)
134914
135237
  return;
@@ -135204,7 +135527,7 @@ function createSayCommand() {
135204
135527
  }
135205
135528
 
135206
135529
  // src/commands/see.ts
135207
- import { existsSync as existsSync15, readFileSync as readFileSync10, statSync as statSync5 } from "fs";
135530
+ import { existsSync as existsSync16, readFileSync as readFileSync10, statSync as statSync5 } from "fs";
135208
135531
  import { extname as extname4 } from "path";
135209
135532
  init_output();
135210
135533
  var MIME_BY_EXT = {
@@ -135236,7 +135559,7 @@ function parseMaxTokens(value) {
135236
135559
  return n2;
135237
135560
  }
135238
135561
  function loadMedia(file) {
135239
- if (!existsSync15(file)) {
135562
+ if (!existsSync16(file)) {
135240
135563
  error(`File not found: ${file}`);
135241
135564
  }
135242
135565
  const stat = statSync5(file);
@@ -135322,7 +135645,7 @@ function createSeeCommand() {
135322
135645
  }
135323
135646
 
135324
135647
  // src/commands/send.ts
135325
- import { existsSync as existsSync16, readFileSync as readFileSync11 } from "fs";
135648
+ import { existsSync as existsSync17, readFileSync as readFileSync11 } from "fs";
135326
135649
  import { basename as basename5, extname as extname5 } from "path";
135327
135650
  init_source();
135328
135651
  init_config();
@@ -135363,7 +135686,7 @@ var messageSenders = {
135363
135686
  const { to, media } = options3;
135364
135687
  if (!to || !media)
135365
135688
  return;
135366
- if (!existsSync16(media)) {
135689
+ if (!existsSync17(media)) {
135367
135690
  error(`File not found: ${media}`);
135368
135691
  return;
135369
135692
  }
@@ -135895,9 +136218,9 @@ function pickFilename(mimeType, provider) {
135895
136218
  }
135896
136219
 
135897
136220
  // src/commands/start.ts
135898
- import { existsSync as existsSync17, mkdirSync as mkdirSync10 } from "fs";
135899
- import { homedir as homedir11 } from "os";
135900
- import { join as join16 } from "path";
136221
+ import { existsSync as existsSync18, mkdirSync as mkdirSync10 } from "fs";
136222
+ import { homedir as homedir12 } from "os";
136223
+ import { join as join17 } from "path";
135901
136224
  init_config();
135902
136225
  init_output();
135903
136226
  var START_HEALTH_TIMEOUT_MS = 1e4;
@@ -135906,7 +136229,7 @@ async function runStart() {
135906
136229
  pm2NotFoundError();
135907
136230
  }
135908
136231
  const bundlePath = getServerBundlePath();
135909
- if (!existsSync17(bundlePath)) {
136232
+ if (!existsSync18(bundlePath)) {
135910
136233
  bundleNotFoundError(bundlePath);
135911
136234
  }
135912
136235
  const serverConfig = loadServerConfig();
@@ -135927,10 +136250,10 @@ async function runStart() {
135927
136250
  error(`Failed to start ${PM2_PROCESSES.api} (pm2 exit code ${apiCode})`, undefined, 1);
135928
136251
  return;
135929
136252
  }
135930
- const natsPath = join16(homedir11(), ".omni", "nats-server");
135931
- if (existsSync17(natsPath)) {
136253
+ const natsPath = join17(homedir12(), ".omni", "nats-server");
136254
+ if (existsSync18(natsPath)) {
135932
136255
  info(`Starting ${PM2_PROCESSES.nats}...`);
135933
- const natsDataDir = join16(serverConfig.dataDir, "nats");
136256
+ const natsDataDir = join17(serverConfig.dataDir, "nats");
135934
136257
  mkdirSync10(natsDataDir, { recursive: true });
135935
136258
  const natsArgs = buildPm2StartArgs({
135936
136259
  kind: "nats",
@@ -136351,8 +136674,8 @@ function createTurnsCommand() {
136351
136674
  }
136352
136675
 
136353
136676
  // src/commands/update.ts
136354
- import { existsSync as existsSync19 } from "fs";
136355
- import { join as join18 } from "path";
136677
+ import { existsSync as existsSync20 } from "fs";
136678
+ import { join as join19 } from "path";
136356
136679
  import { createInterface as createInterface3 } from "readline";
136357
136680
  init_source();
136358
136681
  init_config();
@@ -136634,9 +136957,9 @@ async function cleanupLegacyArtifacts(skipList) {
136634
136957
  init_output();
136635
136958
 
136636
136959
  // src/update-diagnostics.ts
136637
- import { existsSync as existsSync18, mkdirSync as mkdirSync11, readFileSync as readFileSync12, writeFileSync as writeFileSync10 } from "fs";
136638
- import { homedir as homedir12 } from "os";
136639
- import { join as join17 } from "path";
136960
+ import { existsSync as existsSync19, mkdirSync as mkdirSync11, readFileSync as readFileSync12, writeFileSync as writeFileSync10 } from "fs";
136961
+ import { homedir as homedir13 } from "os";
136962
+ import { join as join18 } from "path";
136640
136963
  var UPDATE_DIAGNOSTICS_SCHEMA_VERSION = 1;
136641
136964
  function createDiagnostics(args) {
136642
136965
  const startedAt = new Date().toISOString();
@@ -136658,15 +136981,15 @@ function createDiagnostics(args) {
136658
136981
  };
136659
136982
  }
136660
136983
  function getDiagnosticsDir() {
136661
- const base = process.env.OMNI_CONFIG_DIR ?? join17(homedir12(), ".omni");
136662
- return join17(base, "logs");
136984
+ const base = process.env.OMNI_CONFIG_DIR ?? join18(homedir13(), ".omni");
136985
+ return join18(base, "logs");
136663
136986
  }
136664
136987
  function getDiagnosticsPath(startedAt) {
136665
136988
  const safe = startedAt.replace(/:/g, "-");
136666
- return join17(getDiagnosticsDir(), `update-diagnostics-${safe}.json`);
136989
+ return join18(getDiagnosticsDir(), `update-diagnostics-${safe}.json`);
136667
136990
  }
136668
136991
  function tailFileLines(path, maxLines) {
136669
- if (!existsSync18(path))
136992
+ if (!existsSync19(path))
136670
136993
  return [];
136671
136994
  try {
136672
136995
  const raw2 = readFileSync12(path, "utf8");
@@ -136702,7 +137025,7 @@ function writeDiagnostics(state, exitCode) {
136702
137025
  const dir = getDiagnosticsDir();
136703
137026
  const path = getDiagnosticsPath(state.startedAt);
136704
137027
  try {
136705
- if (!existsSync18(dir)) {
137028
+ if (!existsSync19(dir)) {
136706
137029
  mkdirSync11(dir, { recursive: true, mode: 448 });
136707
137030
  }
136708
137031
  writeFileSync10(path, `${JSON.stringify(state, null, 2)}
@@ -136876,7 +137199,7 @@ function printVerifySkippedBanner(latest) {
136876
137199
  }
136877
137200
  function detectParallelNpmGlobalInstall(deps) {
136878
137201
  const npmRootFn = deps?.npmRoot ?? defaultNpmRoot;
136879
- const existsFn = deps?.exists ?? existsSync19;
137202
+ const existsFn = deps?.exists ?? existsSync20;
136880
137203
  let root;
136881
137204
  try {
136882
137205
  root = npmRootFn();
@@ -136886,7 +137209,7 @@ function detectParallelNpmGlobalInstall(deps) {
136886
137209
  if (root === null || root.length === 0) {
136887
137210
  return { detected: false, skipped: "npm-not-on-path" };
136888
137211
  }
136889
- const candidate = join18(root, "@automagik", "omni");
137212
+ const candidate = join19(root, "@automagik", "omni");
136890
137213
  if (existsFn(candidate)) {
136891
137214
  return { detected: true, path: candidate };
136892
137215
  }
@@ -137509,13 +137832,13 @@ init_config();
137509
137832
  init_output();
137510
137833
 
137511
137834
  // src/manifest-pin.ts
137512
- import { existsSync as existsSync20, readFileSync as readFileSync13, renameSync as renameSync3, writeFileSync as writeFileSync11 } from "fs";
137513
- import { homedir as homedir13 } from "os";
137514
- import { join as join19 } from "path";
137835
+ import { existsSync as existsSync21, readFileSync as readFileSync13, renameSync as renameSync3, writeFileSync as writeFileSync11 } from "fs";
137836
+ import { homedir as homedir14 } from "os";
137837
+ import { join as join20 } from "path";
137515
137838
  var PACKAGE_NAME2 = "@automagik/omni";
137516
- var BUN_GLOBAL_MANIFEST = join19(homedir13(), ".bun", "install", "global", "package.json");
137839
+ var BUN_GLOBAL_MANIFEST = join20(homedir14(), ".bun", "install", "global", "package.json");
137517
137840
  function pinManifestEntry(manifestPath, exactVersion) {
137518
- if (!existsSync20(manifestPath))
137841
+ if (!existsSync21(manifestPath))
137519
137842
  return false;
137520
137843
  let manifest;
137521
137844
  try {
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Embedded → canonical migration for the "unmounted embedded dir" path.
3
+ *
4
+ * Background
5
+ * ----------
6
+ * The original `fixPgserveCanonical` flow (canonical-pgserve.ts +
7
+ * doctor.ts) assumes the embedded pgserve is LIVE: omni-api is running
8
+ * against it, pg_dump connects to the live instance, then we stop
9
+ * omni-api, set up canonical, restore, restart on canonical. That
10
+ * worked through the singleton-no-proxy cutover when omni-api could
11
+ * still spawn embedded.
12
+ *
13
+ * Phase 3 (`pgserve-singleton-no-proxy` G2) deleted omni-api's
14
+ * embedded-spawn code. That leaves a regression for any operator who:
15
+ * - Has `useCanonicalPgserve: true` in config (cutover already
16
+ * "succeeded" structurally) but
17
+ * - Never actually moved data — their 8.4 GB sits at
18
+ * `~/.omni/data/pgserve/` as an unmounted postmaster data dir
19
+ * - The canonical `omni` database on autopg is empty
20
+ *
21
+ * Found during Felipe's 2026-05-20 dogfood: omni-api boots cleanly on
22
+ * canonical but `omni instances list` returns nothing — the data is
23
+ * stranded.
24
+ *
25
+ * Solution
26
+ * --------
27
+ * Spawn autopg's bundled `postgres` binary against the unmounted embedded
28
+ * data dir on a free TCP port, copy every public-schema table over to
29
+ * canonical via psql `COPY ... TO STDOUT | COPY ... FROM STDIN` pipes
30
+ * (psql 17 happily connects to a PG18 server — only pg_dump is strict),
31
+ * then shut the temp postmaster down. Postgres version compatibility is
32
+ * sidestepped: both embedded and canonical use the same autopg-bundled
33
+ * postgres binary on this host.
34
+ *
35
+ * Idempotency: caller is expected to gate on `canonical omni DB is
36
+ * empty + embedded dir has data` so re-running this isn't destructive.
37
+ * Within this function: TRUNCATE CASCADE before COPY, sequence reset
38
+ * after.
39
+ *
40
+ * Safety:
41
+ * - Temp postmaster binds 127.0.0.1 only, on a free ephemeral port
42
+ * - Spawned with `unix_socket_directories=/tmp/<unique>` to avoid
43
+ * colliding with canonical's socket dir
44
+ * - Caller takes a snapshot of `~/.omni/data/pgserve/` before invoking
45
+ * (recommended) — this code does NOT mutate the embedded dir
46
+ * - Temp postmaster gets SIGTERM in `finally`; on hard crash the
47
+ * leftover postmaster.pid is recovered by the next spawn attempt
48
+ * (postgres self-heals stale pidfiles on startup)
49
+ */
50
+ export type MigrationResult = {
51
+ status: 'migrated';
52
+ tables: number;
53
+ durationMs: number;
54
+ } | {
55
+ status: 'skipped';
56
+ reason: string;
57
+ };
58
+ export interface MigrateOptions {
59
+ /** TCP port the canonical postmaster is bound on (autopg default 5432). */
60
+ canonicalPort?: number;
61
+ /** Logger sink — defaults to writing prefixed lines to process.stdout. */
62
+ log?: (line: string) => void;
63
+ }
64
+ /**
65
+ * Public entry point — call this from `omni doctor --fix` when the
66
+ * `embedded-data-orphaned` check FAILs (canonical omni DB empty AND
67
+ * embedded dir has valid pg data).
68
+ *
69
+ * Returns `{ status: 'skipped', reason }` for any precondition mismatch
70
+ * so callers can present an actionable diagnostic without aborting the
71
+ * larger --fix run.
72
+ */
73
+ /**
74
+ * Result of comparing embedded vs canonical row counts. Used by the
75
+ * doctor `embedded-data-orphaned` check to detect partial migrations
76
+ * (e.g. Baileys re-attach copies instance rows but the bulk historical
77
+ * tables stay empty until the ETL runs).
78
+ */
79
+ export type CompareResult = {
80
+ kind: 'in-sync';
81
+ } | {
82
+ kind: 'embedded-has-more';
83
+ divergentTables: string[];
84
+ embeddedRows: number;
85
+ } | {
86
+ kind: 'skipped';
87
+ reason: string;
88
+ };
89
+ export interface CompareOptions {
90
+ canonicalPort?: number;
91
+ }
92
+ /**
93
+ * Count rows in every public table on both the embedded data dir and the
94
+ * canonical postmaster, return which tables have MORE rows on embedded.
95
+ * Boots a temp postmaster against the embedded dir (5s ready window),
96
+ * runs two count queries, shuts it down. Best-effort: any spawn / query
97
+ * failure returns `{ kind: 'skipped' }`.
98
+ */
99
+ export declare function compareEmbeddedVsCanonicalCounts(opts?: CompareOptions): Promise<CompareResult>;
100
+ export declare function migrateUnmountedEmbeddedToCanonical(opts?: MigrateOptions): Promise<MigrationResult>;
101
+ /** Re-export the constant so callers / tests can probe the same path. */
102
+ export declare const EMBEDDED_PGSERVE_DATA_DIR: string;
103
+ //# sourceMappingURL=embedded-canonical-migration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedded-canonical-migration.d.ts","sourceRoot":"","sources":["../../src/lib/embedded-canonical-migration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAWH,MAAM,MAAM,eAAe,GACvB;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAC1D;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1C,MAAM,WAAW,cAAc;IAC7B,2EAA2E;IAC3E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0EAA0E;IAC1E,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9B;AA0MD;;;;;;;;GAQG;AACH;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,eAAe,EAAE,MAAM,EAAE,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAC9E;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAExC,MAAM,WAAW,cAAc;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;GAMG;AACH,wBAAsB,gCAAgC,CAAC,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,aAAa,CAAC,CAiDxG;AAED,wBAAsB,mCAAmC,CAAC,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,eAAe,CAAC,CA+D7G;AAED,yEAAyE;AACzE,eAAO,MAAM,yBAAyB,QAAe,CAAC"}
@@ -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.14",
230140
+ version: "2.260520.16",
230141
230141
  type: "module",
230142
230142
  exports: {
230143
230143
  ".": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automagik/omni",
3
- "version": "2.260520.14",
3
+ "version": "2.260520.16",
4
4
  "description": "LLM-optimized CLI for Omni",
5
5
  "type": "module",
6
6
  "bin": {