@runeya/runeya 2.0.121 → 2.0.122

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.
@@ -17,7 +17,6 @@ import {
17
17
  apiKeyStore,
18
18
  appVersion,
19
19
  applyPersistedLanMode,
20
- atomicWriteSecure,
21
20
  auditService,
22
21
  canEnvAction,
23
22
  chatRouter,
@@ -51,7 +50,6 @@ import {
51
50
  requireServiceAction,
52
51
  resolveAgentCwd,
53
52
  resolveConversationCwd,
54
- resolveConversationRunDir,
55
53
  resolveEffectiveAgentId,
56
54
  resolveServiceVariables,
57
55
  resolveWorkspaceCwd,
@@ -64,7 +62,7 @@ import {
64
62
  soleAccountScope,
65
63
  startCliSession,
66
64
  vaultOfProject
67
- } from "./chunk-HJUFIZ7H.js";
65
+ } from "./chunk-BVBK2WII.js";
68
66
  import {
69
67
  resolveCliInvocation,
70
68
  whichCommand
@@ -87,7 +85,7 @@ import {
87
85
  stopClaudeTranscriptWatcher,
88
86
  stopCodexTranscriptWatcher,
89
87
  verifyJwt
90
- } from "./chunk-OVV52N5F.js";
88
+ } from "./chunk-VNLIA5PV.js";
91
89
  import "./chunk-MD3VW4HQ.js";
92
90
  import {
93
91
  agentManager,
@@ -125,11 +123,14 @@ import {
125
123
  stableEncryptValue,
126
124
  traefikManager,
127
125
  unregisterInstance
128
- } from "./chunk-CNTL6NVU.js";
126
+ } from "./chunk-XTLQOYLT.js";
129
127
  import {
130
128
  settingsManager
131
- } from "./chunk-3N55WR7F.js";
132
- import "./chunk-YZU5FNXR.js";
129
+ } from "./chunk-NIU3CN5A.js";
130
+ import {
131
+ atomicWriteSecure,
132
+ resolveConversationRunDir
133
+ } from "./chunk-GL7WA5K3.js";
133
134
  import {
134
135
  AGENT_LONG_FETCH_TIMEOUT,
135
136
  AGENT_STOP_FETCH_TIMEOUT,
@@ -6579,11 +6580,61 @@ async function reconcileOrgCanary(orgId) {
6579
6580
  }
6580
6581
 
6581
6582
  // ../server/src/services/cloud-sync-bridge.ts
6582
- import { randomUUID as randomUUID5 } from "crypto";
6583
+ import { randomUUID as randomUUID6 } from "crypto";
6583
6584
  import { mkdir as mkdir7, rm as rm3 } from "fs/promises";
6585
+ import * as Y2 from "yjs";
6586
+
6587
+ // ../server/src/services/sync-doc-cache.ts
6588
+ import { readFileSync, renameSync, rmSync, writeFileSync, mkdirSync } from "fs";
6589
+ import { readFile as readFile4 } from "fs/promises";
6590
+ import { dirname as dirname4, join as join10 } from "path";
6591
+ import { randomUUID as randomUUID5 } from "crypto";
6584
6592
  import * as Y from "yjs";
6593
+ var FILE = "sync-doc.bin";
6594
+ function cachePath(orgId) {
6595
+ return join10(orgVaultRoot(orgId), FILE);
6596
+ }
6597
+ async function readSyncDoc(orgId) {
6598
+ try {
6599
+ return new Uint8Array(await readFile4(cachePath(orgId)));
6600
+ } catch {
6601
+ return null;
6602
+ }
6603
+ }
6604
+ function mergeWith(existing, state) {
6605
+ if (!existing) return state;
6606
+ try {
6607
+ return Y.mergeUpdates([existing, state]);
6608
+ } catch {
6609
+ return state;
6610
+ }
6611
+ }
6612
+ async function writeSyncDoc(orgId, state) {
6613
+ await atomicWriteSecure(cachePath(orgId), mergeWith(await readSyncDoc(orgId), state));
6614
+ }
6615
+ function writeSyncDocSync(orgId, state) {
6616
+ const path = cachePath(orgId);
6617
+ let existing = null;
6618
+ try {
6619
+ existing = new Uint8Array(readFileSync(path));
6620
+ } catch {
6621
+ }
6622
+ mkdirSync(dirname4(path), { recursive: true });
6623
+ const tmp = `${path}.${process.pid}.${randomUUID5()}.tmp`;
6624
+ try {
6625
+ writeFileSync(tmp, mergeWith(existing, state), { mode: 384 });
6626
+ renameSync(tmp, path);
6627
+ } catch (err) {
6628
+ rmSync(tmp, { force: true });
6629
+ throw err;
6630
+ }
6631
+ }
6632
+
6633
+ // ../server/src/services/cloud-sync-bridge.ts
6585
6634
  var LOCAL_ORIGIN = "local-bridge";
6586
6635
  var REMOTE_ORIGIN = "remote";
6636
+ var CACHE_ORIGIN = "cache";
6637
+ var PERSIST_DEBOUNCE_MS = 1e3;
6587
6638
  var RECONNECT_DELAY_MS = 3e3;
6588
6639
  var UNAUTHENTICATED_RETRY_MS = 5 * 6e4;
6589
6640
  var OUTDATED_RETRY_MS = 30 * 6e4;
@@ -6616,12 +6667,12 @@ var ProjectHeldElsewhereError = class extends Error {
6616
6667
  code = "PROJECT_HELD_ELSEWHERE";
6617
6668
  };
6618
6669
  var OrgSyncConnection = class {
6619
- doc = new Y.Doc();
6670
+ doc = new Y2.Doc();
6620
6671
  projects = getCollection(this.doc, "projects");
6621
6672
  services = getCollection(this.doc, "services");
6622
6673
  environments = getCollection(this.doc, "environments");
6623
6674
  logParsers = getCollection(this.doc, PARSERS);
6624
- conn = randomUUID5();
6675
+ conn = randomUUID6();
6625
6676
  link;
6626
6677
  stopped = false;
6627
6678
  initializing = true;
@@ -6657,6 +6708,31 @@ var OrgSyncConnection = class {
6657
6708
  * creating a project sees it appear on their teammates' machines.
6658
6709
  */
6659
6710
  initialDocApplied = false;
6711
+ /**
6712
+ * Whether local state has been written into the doc.
6713
+ *
6714
+ * Never before the doc holds the known history — reloaded from disk, or
6715
+ * received from the cloud. Written into an empty doc, local state is
6716
+ * concurrent with every past write and loses to some of them at random: an
6717
+ * offline edit reverted, a service on disk erased by an older deletion.
6718
+ */
6719
+ seeded = false;
6720
+ /** Store applications started by remote events and not finished yet. */
6721
+ applying = /* @__PURE__ */ new Set();
6722
+ /**
6723
+ * When each entity was last changed by a remote update (`collection:id` → tick).
6724
+ *
6725
+ * Reconciliation reads the stores, waits, then writes what it read. A remote
6726
+ * change landing in between makes that read stale, and writing it would erase
6727
+ * the value that just arrived — for every member. Entities touched since the
6728
+ * read began are left alone: their application brings the disk up to date,
6729
+ * and the reconciliation it triggers starts from there.
6730
+ */
6731
+ remoteTouch = /* @__PURE__ */ new Map();
6732
+ remoteClock = 0;
6733
+ persistTimer = null;
6734
+ /** The cache write under way, so stopping can wait for it to land. */
6735
+ persisting = Promise.resolve();
6660
6736
  unsubscribes = [];
6661
6737
  onSaved = () => void this.reconcileLocalToDoc();
6662
6738
  constructor(link) {
@@ -6686,29 +6762,79 @@ var OrgSyncConnection = class {
6686
6762
  if (txn.origin !== REMOTE_ORIGIN) return;
6687
6763
  const isInitial = !this.initialDocApplied;
6688
6764
  if (name === "projects") this.initialDocApplied = true;
6689
- void this.applyDocEventsToStore(name, events, isInitial);
6765
+ this.track(this.applyDocEventsToStore(name, events, isInitial));
6690
6766
  });
6691
6767
  }
6692
6768
  this.logParsers.observeDeep((events, txn) => {
6693
6769
  if (txn.origin !== REMOTE_ORIGIN) return;
6694
- void this.applyParserEventsToStore(events);
6770
+ this.track(this.applyParserEventsToStore(events));
6695
6771
  });
6696
6772
  projectStore.events.on("saved", this.onSaved);
6697
6773
  this.unsubscribes.push(serviceStore.onChange(this.onSaved));
6698
6774
  this.unsubscribes.push(environmentStore.onChange(this.onSaved));
6699
6775
  this.unsubscribes.push(logParserStore.onLocalChange(this.onSaved));
6776
+ const cached = await readSyncDoc(this.link.orgId);
6777
+ if (cached) {
6778
+ try {
6779
+ Y2.applyUpdate(this.doc, cached, CACHE_ORIGIN);
6780
+ this.initialDocApplied = true;
6781
+ } catch (err) {
6782
+ console.error("[cloud-sync] unreadable sync cache for org %s, ignored:", this.link.orgId, err.message);
6783
+ }
6784
+ }
6785
+ this.doc.on("update", () => this.schedulePersist());
6786
+ if (cached && this.initialDocApplied) await this.seed();
6787
+ void this.streamLoop();
6788
+ }
6789
+ /** Write local state on top of the known history, then owe it to the cloud. */
6790
+ async seed() {
6791
+ this.seeded = true;
6700
6792
  await this.reconcileLocalToDoc();
6701
6793
  this.initializing = false;
6702
6794
  this.needsPush = true;
6703
- void this.streamLoop();
6704
6795
  }
6796
+ track(work) {
6797
+ this.applying.add(work);
6798
+ void work.finally(() => this.applying.delete(work));
6799
+ }
6800
+ async settleApplying() {
6801
+ while (this.applying.size > 0) await Promise.allSettled(this.applying);
6802
+ }
6803
+ schedulePersist() {
6804
+ if (this.stopped || this.persistTimer) return;
6805
+ this.persistTimer = setTimeout(() => {
6806
+ this.persistTimer = null;
6807
+ this.persisting = this.persisting.then(() => this.persist());
6808
+ }, PERSIST_DEBOUNCE_MS);
6809
+ }
6810
+ async persist() {
6811
+ if (this.stopped) return;
6812
+ try {
6813
+ await writeSyncDoc(this.link.orgId, Y2.encodeStateAsUpdate(this.doc));
6814
+ } catch (err) {
6815
+ console.error("[cloud-sync] could not save sync cache for org %s:", this.link.orgId, err.message);
6816
+ }
6817
+ }
6818
+ /** Resolves once any cache write already under way has landed. */
6705
6819
  stop() {
6706
6820
  this.stopped = true;
6707
6821
  this.state = "stopped";
6708
6822
  projectStore.events.off("saved", this.onSaved);
6709
6823
  for (const off of this.unsubscribes.splice(0)) off();
6710
6824
  this.abort?.abort();
6825
+ if (this.persistTimer) {
6826
+ clearTimeout(this.persistTimer);
6827
+ this.persistTimer = null;
6828
+ }
6829
+ if (this.seeded) {
6830
+ try {
6831
+ writeSyncDocSync(this.link.orgId, Y2.encodeStateAsUpdate(this.doc));
6832
+ } catch (err) {
6833
+ console.error("[cloud-sync] could not save sync cache for org %s:", this.link.orgId, err.message);
6834
+ }
6835
+ }
6711
6836
  this.doc.destroy();
6837
+ return this.persisting;
6712
6838
  }
6713
6839
  // ---- Transport -------------------------------------------------------
6714
6840
  /**
@@ -6786,7 +6912,7 @@ var OrgSyncConnection = class {
6786
6912
  if (!svRes.ok) return;
6787
6913
  const { sv } = await svRes.json();
6788
6914
  const cloudSv = new Uint8Array(Buffer.from(sv, "base64"));
6789
- const diff = Y.encodeStateAsUpdate(this.doc, cloudSv);
6915
+ const diff = Y2.encodeStateAsUpdate(this.doc, cloudSv);
6790
6916
  await this.pushUpdate(diff);
6791
6917
  } catch (err) {
6792
6918
  if (err instanceof SyncAuthError || err instanceof SyncOutdatedError) throw err;
@@ -6848,7 +6974,7 @@ var OrgSyncConnection = class {
6848
6974
  }
6849
6975
  async streamOnce() {
6850
6976
  this.abort = new AbortController();
6851
- const since = Buffer.from(Y.encodeStateVector(this.doc)).toString("base64");
6977
+ const since = Buffer.from(Y2.encodeStateVector(this.doc)).toString("base64");
6852
6978
  const res = await fetch(this.url(`/stream?conn=${this.conn}&since=${encodeURIComponent(since)}`), {
6853
6979
  headers: { Authorization: await this.authHeader(), [APP_VERSION_HEADER]: appVersion },
6854
6980
  signal: this.abort.signal
@@ -6872,8 +6998,17 @@ var OrgSyncConnection = class {
6872
6998
  try {
6873
6999
  const payload = JSON.parse(line.slice(6));
6874
7000
  const update = new Uint8Array(Buffer.from(payload.update, "base64"));
6875
- Y.applyUpdate(this.doc, update, REMOTE_ORIGIN);
7001
+ Y2.applyUpdate(this.doc, update, REMOTE_ORIGIN);
6876
7002
  } catch {
7003
+ continue;
7004
+ }
7005
+ if (!this.seeded) {
7006
+ this.initialDocApplied = true;
7007
+ await this.settleApplying();
7008
+ if (this.stopped) return;
7009
+ await this.seed();
7010
+ await this.initialPush();
7011
+ this.needsPush = false;
6877
7012
  }
6878
7013
  }
6879
7014
  }
@@ -7018,6 +7153,7 @@ var OrgSyncConnection = class {
7018
7153
  if (typeof topKey === "string") affected.add(topKey);
7019
7154
  }
7020
7155
  }
7156
+ for (const id of [...deleted, ...affected]) this.remoteTouch.set(`${name}:${id}`, ++this.remoteClock);
7021
7157
  for (const id of deleted) {
7022
7158
  if (!this.isTrackedForDeletion(name, id)) continue;
7023
7159
  await this.deleteLocally(name, id);
@@ -7170,7 +7306,9 @@ var OrgSyncConnection = class {
7170
7306
  * propagate — otherwise a service could never be removed.
7171
7307
  */
7172
7308
  async reconcileLocalToDoc() {
7173
- if (this.stopped || this.pulling) return;
7309
+ if (this.stopped || this.pulling || !this.seeded) return;
7310
+ const readAt = this.remoteClock;
7311
+ const touchedSinceRead = (name, id) => (this.remoteTouch.get(`${name}:${id}`) ?? 0) > readAt;
7174
7312
  const projects = (await projectStore.listDiskFormByOrg(this.link.orgId)).filter((p) => !this.refusalFor(p.id));
7175
7313
  const projectIds = projects.map((p) => p.id);
7176
7314
  const serviceIds = [...new Set(projects.flatMap((p) => p.serviceIds ?? []))];
@@ -7188,10 +7326,12 @@ var OrgSyncConnection = class {
7188
7326
  const collection = this.collection(name);
7189
7327
  const entities = local[name];
7190
7328
  const ids = new Set(entities.map((e) => e.id));
7191
- for (const entity of entities) writeEntity(collection, entity.id, entity);
7329
+ for (const entity of entities) {
7330
+ if (!touchedSinceRead(name, entity.id)) writeEntity(collection, entity.id, entity);
7331
+ }
7192
7332
  if (name === "projects") continue;
7193
7333
  for (const id of Array.from(collection.keys())) {
7194
- if (ids.has(id)) continue;
7334
+ if (ids.has(id) || touchedSinceRead(name, id)) continue;
7195
7335
  if (this.belongsToOwnedProject(name, id, ownedProjectIds)) collection.delete(id);
7196
7336
  }
7197
7337
  }
@@ -7380,21 +7520,24 @@ var CloudSyncBridge = class {
7380
7520
  disconnect(orgId) {
7381
7521
  const existing = this.connections.get(orgId);
7382
7522
  if (existing) {
7383
- existing.stop();
7523
+ void existing.stop();
7384
7524
  this.connections.delete(orgId);
7385
7525
  }
7386
7526
  }
7527
+ /** Stops at once; the promise only says when pending cache writes have landed. */
7387
7528
  stopAll() {
7388
- for (const conn of this.connections.values()) conn.stop();
7529
+ const stopping = [...this.connections.values()].map((conn) => conn.stop());
7389
7530
  this.connections.clear();
7390
7531
  this.keyMismatch.clear();
7532
+ return Promise.all(stopping).then(() => {
7533
+ });
7391
7534
  }
7392
7535
  };
7393
7536
  var cloudSyncBridge = new CloudSyncBridge();
7394
7537
 
7395
7538
  // ../server/src/services/key-adoption.ts
7396
- import { readdir as readdir3, readFile as readFile4, writeFile as writeFile6, mkdir as mkdir8, copyFile, rename as rename4, stat as stat5 } from "fs/promises";
7397
- import { join as join10 } from "path";
7539
+ import { readdir as readdir3, readFile as readFile5, writeFile as writeFile6, mkdir as mkdir8, copyFile, rename as rename4, stat as stat5 } from "fs/promises";
7540
+ import { join as join11 } from "path";
7398
7541
  import { createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, randomBytes as randomBytes2 } from "crypto";
7399
7542
  var ALGORITHM = "aes-256-gcm";
7400
7543
  function isAgentTriplet(value) {
@@ -7474,10 +7617,10 @@ async function adoptOrgKey(orgId, newKey, masterPassword, now) {
7474
7617
  const touchedRoots = /* @__PURE__ */ new Set();
7475
7618
  for (const vaultRoot of await rootsOfOrg(orgId)) {
7476
7619
  for (const name of await jsonFilesIn(vaultRoot)) {
7477
- const path = join10(vaultRoot, name);
7620
+ const path = join11(vaultRoot, name);
7478
7621
  let parsed;
7479
7622
  try {
7480
- parsed = JSON.parse(await readFile4(path, "utf-8"));
7623
+ parsed = JSON.parse(await readFile5(path, "utf-8"));
7481
7624
  } catch {
7482
7625
  continue;
7483
7626
  }
@@ -7491,14 +7634,14 @@ async function adoptOrgKey(orgId, newKey, masterPassword, now) {
7491
7634
  const stamp = now.toISOString().replace(/[:.]/g, "-").substring(0, 19);
7492
7635
  const backups = [];
7493
7636
  for (const vaultRoot of touchedRoots) {
7494
- const backupDir = join10(vaultRoot, `backup-key-${stamp}`);
7637
+ const backupDir = join11(vaultRoot, `backup-key-${stamp}`);
7495
7638
  await mkdir8(backupDir, { recursive: true });
7496
7639
  for (const name of await jsonFilesIn(vaultRoot)) {
7497
- await copyFile(join10(vaultRoot, name), join10(backupDir, name));
7640
+ await copyFile(join11(vaultRoot, name), join11(backupDir, name));
7498
7641
  }
7499
7642
  for (const name of [".encryption.key.enc", ".runeya-verify"]) {
7500
- if (await exists(join10(vaultRoot, name))) {
7501
- await copyFile(join10(vaultRoot, name), join10(backupDir, name));
7643
+ if (await exists(join11(vaultRoot, name))) {
7644
+ await copyFile(join11(vaultRoot, name), join11(backupDir, name));
7502
7645
  }
7503
7646
  }
7504
7647
  backups.push(backupDir);
@@ -7963,13 +8106,13 @@ var cloudSyncRouter = router({
7963
8106
  // ../server/src/trpc/routers/filesystem.ts
7964
8107
  import { readdir as readdir4, stat as stat6 } from "fs/promises";
7965
8108
  import { homedir as homedir3 } from "os";
7966
- import { isAbsolute, join as join11, resolve as resolve2, dirname as dirname4, basename } from "path";
8109
+ import { isAbsolute, join as join12, resolve as resolve2, dirname as dirname5, basename } from "path";
7967
8110
  import { z as z24 } from "zod";
7968
8111
  var MAX_ENTRIES2 = 500;
7969
8112
  var PATH_SCHEMA = z24.string().min(1).max(4096);
7970
8113
  function safeResolve(input) {
7971
8114
  if (input.includes("\0")) throw new Error("Chemin invalide");
7972
- const expanded = input.startsWith("~") ? join11(homedir3(), input.slice(1)) : input;
8115
+ const expanded = input.startsWith("~") ? join12(homedir3(), input.slice(1)) : input;
7973
8116
  if (!isAbsolute(expanded)) throw new Error("Le chemin doit \xEAtre absolu");
7974
8117
  return resolve2(expanded);
7975
8118
  }
@@ -8005,13 +8148,13 @@ var filesystemRouter = router({
8005
8148
  const truncated = names.length > MAX_ENTRIES2;
8006
8149
  const entries2 = [];
8007
8150
  for (const name of names.slice(0, MAX_ENTRIES2)) {
8008
- const path = join11(dir, name);
8151
+ const path = join12(dir, name);
8009
8152
  entries2.push({ name, path, hasRuneyaProject: await holdsRuneyaProject(path) });
8010
8153
  }
8011
8154
  return {
8012
8155
  path: dir,
8013
8156
  // Null at the filesystem root, which is what stops "up" from looping.
8014
- parent: dirname4(dir) === dir ? null : dirname4(dir),
8157
+ parent: dirname5(dir) === dir ? null : dirname5(dir),
8015
8158
  name: basename(dir) || dir,
8016
8159
  entries: entries2,
8017
8160
  truncated,
@@ -8266,8 +8409,8 @@ async function ensureFilePermissions() {
8266
8409
  }
8267
8410
 
8268
8411
  // ../server/src/services/vault-migration.ts
8269
- import { readdir as readdir5, readFile as readFile5, writeFile as writeFile7, mkdir as mkdir9, copyFile as copyFile2, unlink, rename as rename5, stat as stat8 } from "fs/promises";
8270
- import { join as join12 } from "path";
8412
+ import { readdir as readdir5, readFile as readFile6, writeFile as writeFile7, mkdir as mkdir9, copyFile as copyFile2, unlink, rename as rename5, stat as stat8 } from "fs/promises";
8413
+ import { join as join13 } from "path";
8271
8414
  var KEY_FILES = [".encryption.key.enc", ".runeya-verify"];
8272
8415
  var MACHINE_FILES = [
8273
8416
  "agents.json",
@@ -8297,17 +8440,17 @@ async function openLegacyVault(legacyRoot, masterPassword) {
8297
8440
  }
8298
8441
  async function migrateLegacyVault(legacyRoot, machineRootDir, legacyKey, machineKey, now) {
8299
8442
  const stamp = now.toISOString().replace(/[:.]/g, "-").substring(0, 19);
8300
- const backupDir = join12(legacyRoot, `backup-${stamp}`);
8443
+ const backupDir = join13(legacyRoot, `backup-${stamp}`);
8301
8444
  await mkdir9(backupDir, { recursive: true });
8302
8445
  const jsonFiles = await vaultJsonFiles(legacyRoot);
8303
8446
  for (const name of [...jsonFiles, ...KEY_FILES]) {
8304
- if (await exists2(join12(legacyRoot, name))) {
8305
- await copyFile2(join12(legacyRoot, name), join12(backupDir, name));
8447
+ if (await exists2(join13(legacyRoot, name))) {
8448
+ await copyFile2(join13(legacyRoot, name), join13(backupDir, name));
8306
8449
  }
8307
8450
  }
8308
8451
  const rekeyed = [];
8309
8452
  for (const name of jsonFiles) {
8310
- const raw = await readFile5(join12(legacyRoot, name), "utf-8");
8453
+ const raw = await readFile6(join13(legacyRoot, name), "utf-8");
8311
8454
  let parsed;
8312
8455
  try {
8313
8456
  parsed = JSON.parse(raw);
@@ -8317,13 +8460,13 @@ async function migrateLegacyVault(legacyRoot, machineRootDir, legacyKey, machine
8317
8460
  const counter = { n: 0 };
8318
8461
  const converted = rekeyValue(parsed, legacyKey, machineKey, counter);
8319
8462
  if (counter.n === 0) continue;
8320
- const tmp = join12(legacyRoot, `${name}.tmp`);
8463
+ const tmp = join13(legacyRoot, `${name}.tmp`);
8321
8464
  await writeFile7(tmp, JSON.stringify(converted, null, 2), "utf-8");
8322
- await rename5(tmp, join12(legacyRoot, name));
8465
+ await rename5(tmp, join13(legacyRoot, name));
8323
8466
  rekeyed.push({ file: name, values: counter.n });
8324
8467
  }
8325
8468
  for (const { file, values } of rekeyed) {
8326
- const parsed = JSON.parse(await readFile5(join12(legacyRoot, file), "utf-8"));
8469
+ const parsed = JSON.parse(await readFile6(join13(legacyRoot, file), "utf-8"));
8327
8470
  const check = { n: 0 };
8328
8471
  rekeyValue(parsed, machineKey, machineKey, check);
8329
8472
  if (check.n !== values) {
@@ -8336,9 +8479,9 @@ async function migrateLegacyVault(legacyRoot, machineRootDir, legacyKey, machine
8336
8479
  const moved = [];
8337
8480
  const skipped = [];
8338
8481
  for (const name of MACHINE_FILES) {
8339
- const from = join12(legacyRoot, name);
8482
+ const from = join13(legacyRoot, name);
8340
8483
  if (!await exists2(from)) continue;
8341
- const to = join12(machineRootDir, name);
8484
+ const to = join13(machineRootDir, name);
8342
8485
  if (await exists2(to)) {
8343
8486
  skipped.push(name);
8344
8487
  continue;
@@ -8348,15 +8491,15 @@ async function migrateLegacyVault(legacyRoot, machineRootDir, legacyKey, machine
8348
8491
  moved.push(name);
8349
8492
  }
8350
8493
  for (const name of KEY_FILES) {
8351
- const path = join12(legacyRoot, name);
8494
+ const path = join13(legacyRoot, name);
8352
8495
  if (await exists2(path)) await unlink(path);
8353
8496
  }
8354
8497
  return { backupDir, rekeyed, moved, skipped };
8355
8498
  }
8356
8499
 
8357
8500
  // ../server/src/services/settings-migration.ts
8358
- import { readFile as readFile6, writeFile as writeFile8, rename as rename6, unlink as unlink2, mkdir as mkdir10, chmod as chmod4, stat as stat9 } from "fs/promises";
8359
- import { join as join13 } from "path";
8501
+ import { readFile as readFile7, writeFile as writeFile8, rename as rename6, unlink as unlink2, mkdir as mkdir10, chmod as chmod4, stat as stat9 } from "fs/promises";
8502
+ import { join as join14 } from "path";
8360
8503
  var SETTINGS_FILE = "settings.json";
8361
8504
  var SETTINGS_PRIVATE_FILE = "settings.private.json";
8362
8505
  async function exists3(path) {
@@ -8370,8 +8513,8 @@ async function legacySource(filename) {
8370
8513
  }
8371
8514
  async function moveInto(root, filename, from) {
8372
8515
  await mkdir10(root, { recursive: true });
8373
- const to = join13(root, filename);
8374
- const contents = await readFile6(from, "utf-8");
8516
+ const to = join14(root, filename);
8517
+ const contents = await readFile7(from, "utf-8");
8375
8518
  const tmp = to + ".tmp";
8376
8519
  await writeFile8(tmp, contents, "utf-8");
8377
8520
  await rename6(tmp, to);
@@ -8395,7 +8538,7 @@ async function migrateSettingsIntoVaults() {
8395
8538
  const orgId = orgs[0];
8396
8539
  const root = orgVaultRoot(orgId);
8397
8540
  for (const { filename, from } of sources) {
8398
- if (await exists3(join13(root, filename))) continue;
8541
+ if (await exists3(join14(root, filename))) continue;
8399
8542
  await moveInto(root, filename, from);
8400
8543
  report.files.push(filename);
8401
8544
  }
@@ -8409,16 +8552,16 @@ async function migrateSettingsIntoVaults() {
8409
8552
  // ../server/src/migrations/migrate-from-legacy.ts
8410
8553
  import { createRequire } from "module";
8411
8554
  import { randomBytes as randomBytes3, createCipheriv as createCipheriv3, createDecipheriv as createDecipheriv3 } from "crypto";
8412
- import { randomUUID as randomUUID6 } from "crypto";
8555
+ import { randomUUID as randomUUID7 } from "crypto";
8413
8556
  import {
8414
- readFile as readFile7,
8557
+ readFile as readFile8,
8415
8558
  writeFile as writeFile9,
8416
8559
  rename as rename7,
8417
8560
  mkdir as mkdir11,
8418
8561
  access as access2,
8419
8562
  readdir as readdir6
8420
8563
  } from "fs/promises";
8421
- import { join as join14, dirname as dirname5 } from "path";
8564
+ import { join as join15, dirname as dirname6 } from "path";
8422
8565
  var _require = createRequire(import.meta.url);
8423
8566
  var PARSER_ID_MAP = {
8424
8567
  "stack-monitor-parser-jsons": "native:json",
@@ -8535,7 +8678,7 @@ async function getSodium() {
8535
8678
  return _sodium;
8536
8679
  }
8537
8680
  async function decryptLegacyFile(filePath, key, sodium) {
8538
- const raw = (await readFile7(filePath, "utf-8")).trim();
8681
+ const raw = (await readFile8(filePath, "utf-8")).trim();
8539
8682
  if (!raw || raw === "[]" || raw === "{}") {
8540
8683
  try {
8541
8684
  return JSON.parse(raw);
@@ -8560,7 +8703,7 @@ async function atomicWrite(path, data) {
8560
8703
  }
8561
8704
  async function runLegacyMigration(dataDir) {
8562
8705
  const legacyRoot = env.DATA_DIR;
8563
- const legacyKeyPath = join14(legacyRoot, "dbs", "encryption-key.json");
8706
+ const legacyKeyPath = join15(legacyRoot, "dbs", "encryption-key.json");
8564
8707
  try {
8565
8708
  await access2(legacyKeyPath);
8566
8709
  } catch {
@@ -8571,17 +8714,17 @@ async function runLegacyMigration(dataDir) {
8571
8714
  const legacyTmp = `${legacyRoot}-tmp`;
8572
8715
  await rename7(legacyRoot, legacyTmp);
8573
8716
  await mkdir11(dataDir, { recursive: true });
8574
- const legacyOld = join14(dataDir, `backup-${timestamp}`);
8717
+ const legacyOld = join15(dataDir, `backup-${timestamp}`);
8575
8718
  await rename7(legacyTmp, legacyOld);
8576
8719
  console.log(`[legacy-migration] Legacy data backed up to ${legacyOld}`);
8577
- const keyJson = JSON.parse(await readFile7(join14(legacyOld, "dbs", "encryption-key.json"), "utf-8"));
8720
+ const keyJson = JSON.parse(await readFile8(join15(legacyOld, "dbs", "encryption-key.json"), "utf-8"));
8578
8721
  const sodium = await getSodium();
8579
8722
  const sodiumKey = sodium.from_base64(keyJson.encryptionKey);
8580
8723
  const keyBuffer = Buffer.from(sodiumKey);
8581
8724
  const runyeaKeyHex = keyBuffer.toString("hex");
8582
8725
  await setEncryptionKey(runyeaKeyHex);
8583
8726
  console.log("[legacy-migration] Encryption key loaded in memory (temporary)");
8584
- const dbsDir = join14(legacyOld, "dbs");
8727
+ const dbsDir = join15(legacyOld, "dbs");
8585
8728
  async function readEncrypted(filePath) {
8586
8729
  try {
8587
8730
  return await decryptLegacyFile(filePath, sodiumKey, sodium);
@@ -8590,29 +8733,29 @@ async function runLegacyMigration(dataDir) {
8590
8733
  return null;
8591
8734
  }
8592
8735
  }
8593
- const envsDir = join14(dbsDir, "envs");
8736
+ const envsDir = join15(dbsDir, "envs");
8594
8737
  const envFiles = (await readdir6(envsDir).catch(() => [])).filter((f) => f.endsWith(".encrypted.json"));
8595
8738
  const legacyEnvs = {};
8596
8739
  for (const file of envFiles) {
8597
8740
  const name = file.replace(".encrypted.json", "");
8598
- legacyEnvs[name] = await readEncrypted(join14(envsDir, file));
8741
+ legacyEnvs[name] = await readEncrypted(join15(envsDir, file));
8599
8742
  }
8600
- const servicesDir = join14(dbsDir, "services");
8743
+ const servicesDir = join15(dbsDir, "services");
8601
8744
  const serviceFiles = (await readdir6(servicesDir).catch(() => [])).filter((f) => f.endsWith(".encrypted.json"));
8602
8745
  const legacyServices = {};
8603
8746
  for (const file of serviceFiles) {
8604
8747
  const name = file.replace(".encrypted.json", "");
8605
8748
  if (!name) continue;
8606
- const data = await readEncrypted(join14(servicesDir, file));
8749
+ const data = await readEncrypted(join15(servicesDir, file));
8607
8750
  if (data?.label) legacyServices[name] = data;
8608
8751
  }
8609
- const overridesDir = join14(dbsDir, "overrides");
8752
+ const overridesDir = join15(dbsDir, "overrides");
8610
8753
  const overrideFiles = (await readdir6(overridesDir).catch(() => [])).filter((f) => f.endsWith(".encrypted.json"));
8611
8754
  const legacyServiceOverrides = {};
8612
8755
  const legacyEnvOverrides = {};
8613
8756
  for (const file of overrideFiles) {
8614
8757
  const baseName = file.replace(".encrypted.json", "");
8615
- const data = await readEncrypted(join14(overridesDir, file));
8758
+ const data = await readEncrypted(join15(overridesDir, file));
8616
8759
  if (!data) continue;
8617
8760
  if (baseName.endsWith("-envs")) {
8618
8761
  legacyServiceOverrides[baseName.slice(0, -5)] = data;
@@ -8620,18 +8763,18 @@ async function runLegacyMigration(dataDir) {
8620
8763
  legacyEnvOverrides[baseName.slice(0, -12)] = data;
8621
8764
  }
8622
8765
  }
8623
- const parsersDir = join14(dbsDir, "parsers");
8766
+ const parsersDir = join15(dbsDir, "parsers");
8624
8767
  const parserFiles = (await readdir6(parsersDir).catch(() => [])).filter((f) => f.endsWith(".encrypted.json"));
8625
8768
  const legacyParsers = [];
8626
8769
  for (const file of parserFiles) {
8627
- const data = await readEncrypted(join14(parsersDir, file));
8770
+ const data = await readEncrypted(join15(parsersDir, file));
8628
8771
  if (data?.id) legacyParsers.push(data);
8629
8772
  }
8630
- const projectMonoId = randomUUID6();
8773
+ const projectMonoId = randomUUID7();
8631
8774
  const envIdMap = {};
8632
8775
  const labelToKey = {};
8633
8776
  for (const [name, legacyEnv] of Object.entries(legacyEnvs)) {
8634
- envIdMap[name] = randomUUID6();
8777
+ envIdMap[name] = randomUUID7();
8635
8778
  if (legacyEnv?.label) labelToKey[legacyEnv.label] = name;
8636
8779
  }
8637
8780
  const runeEnvs = [];
@@ -8656,7 +8799,7 @@ async function runLegacyMigration(dataDir) {
8656
8799
  if (hasInvalidInterpolation(value)) continue;
8657
8800
  const cleaned = cleanVarKey(key);
8658
8801
  if (inheritedVars[cleaned] === value) continue;
8659
- const varId = randomUUID6();
8802
+ const varId = randomUUID7();
8660
8803
  variables[varId] = makeVariable(cleaned, value);
8661
8804
  varIdLookup.set(`${envIdMap[name]}:${cleaned}`, varId);
8662
8805
  }
@@ -8677,7 +8820,7 @@ async function runLegacyMigration(dataDir) {
8677
8820
  const serviceIdMap = {};
8678
8821
  const runeServices = [];
8679
8822
  for (const [name, legacy] of Object.entries(legacyServices)) {
8680
- const id = randomUUID6();
8823
+ const id = randomUUID7();
8681
8824
  serviceIdMap[name] = id;
8682
8825
  const rootPath = legacy.rootPath || "";
8683
8826
  const rootPathCwd = rootPath && rootPath !== "." ? rootPath : "";
@@ -8686,7 +8829,7 @@ async function runLegacyMigration(dataDir) {
8686
8829
  const parts = [cmd.spawnCmd, ...cmd.spawnArgs || []].filter(Boolean);
8687
8830
  if (!parts.length) continue;
8688
8831
  commands.push({
8689
- id: cmd.id || randomUUID6(),
8832
+ id: cmd.id || randomUUID7(),
8690
8833
  label: "Launch",
8691
8834
  command: parts.join(" "),
8692
8835
  cwd: cmd.spawnOptions?.cwd || "",
@@ -8747,7 +8890,7 @@ async function runLegacyMigration(dataDir) {
8747
8890
  const legacyBootstrapCmds = container.bootstrap?.commands || [];
8748
8891
  if (legacyBootstrapCmds.length > 0) {
8749
8892
  dockerConfig.bootstrapCommands = legacyBootstrapCmds.filter((bs) => bs.cmd || bs.entrypoint).map((bs, idx) => ({
8750
- id: bs.id || randomUUID6(),
8893
+ id: bs.id || randomUUID7(),
8751
8894
  label: bs.label || `Bootstrap ${idx + 1}`,
8752
8895
  command: bs.cmd || "",
8753
8896
  ...bs.entrypoint ? { entrypoint: bs.entrypoint } : {},
@@ -8795,7 +8938,7 @@ async function runLegacyMigration(dataDir) {
8795
8938
  cwd: serviceCwd,
8796
8939
  runner: dockerConfig ? "docker" : "native",
8797
8940
  shortcuts: (legacy.shortcuts || []).filter((s) => s.spawnCmd || s.label).map((s) => ({
8798
- id: s.id || randomUUID6(),
8941
+ id: s.id || randomUUID7(),
8799
8942
  label: s.label || s.spawnCmd || "",
8800
8943
  command: [s.spawnCmd, ...s.spawnArgs || []].filter(Boolean).join(" "),
8801
8944
  ...s.spawnOptions?.cwd ? { cwd: s.spawnOptions.cwd } : {}
@@ -8835,7 +8978,7 @@ async function runLegacyMigration(dataDir) {
8835
8978
  );
8836
8979
  if (!svcScopedEnv) {
8837
8980
  svcScopedEnv = {
8838
- id: randomUUID6(),
8981
+ id: randomUUID7(),
8839
8982
  projectId: projectMonoId,
8840
8983
  name: `${service?.name || name} (${globalEnv.name})`,
8841
8984
  scope: "service",
@@ -8859,7 +9002,7 @@ async function runLegacyMigration(dataDir) {
8859
9002
  const varPost = typeof varData === "object" ? String(varData.suffix ?? "") : "";
8860
9003
  if (!varKey || existingKeys.has(cleanVarKey(varKey))) continue;
8861
9004
  const cleaned = cleanVarKey(varKey);
8862
- const varId = randomUUID6();
9005
+ const varId = randomUUID7();
8863
9006
  svcScopedEnv.variables[varId] = makeVariable(cleaned, varValue, varPre, varPost);
8864
9007
  existingKeys.add(cleaned);
8865
9008
  }
@@ -8879,7 +9022,7 @@ async function runLegacyMigration(dataDir) {
8879
9022
  );
8880
9023
  if (!svcScopedEnv) {
8881
9024
  svcScopedEnv = {
8882
- id: randomUUID6(),
9025
+ id: randomUUID7(),
8883
9026
  projectId: projectMonoId,
8884
9027
  name: `${service?.name || serviceName} (${globalEnv.name})`,
8885
9028
  scope: "service",
@@ -8900,7 +9043,7 @@ async function runLegacyMigration(dataDir) {
8900
9043
  const baseEntry = Object.entries(svcScopedEnv.variables).find(([, v]) => v.key === cleaned);
8901
9044
  let varId = baseEntry?.[0];
8902
9045
  if (!varId) {
8903
- varId = randomUUID6();
9046
+ varId = randomUUID7();
8904
9047
  svcScopedEnv.variables[varId] = {
8905
9048
  key: cleaned,
8906
9049
  value: { value: "", pre: "", post: "", isSecret: false, shareWithAi: false, injectIntoAi: false, required: false, overrideOnly: false, description: "" }
@@ -8930,13 +9073,13 @@ async function runLegacyMigration(dataDir) {
8930
9073
  flatOverrides[varId] = makeVariable(cleaned, value);
8931
9074
  }
8932
9075
  } else {
8933
- flatOverrides[randomUUID6()] = makeVariable(cleaned, value);
9076
+ flatOverrides[randomUUID7()] = makeVariable(cleaned, value);
8934
9077
  }
8935
9078
  } else {
8936
9079
  const cleaned = cleanVarKey(key);
8937
9080
  const existingVarId = Object.entries(env2.variables).find(([, v]) => v.key === cleaned)?.[0];
8938
9081
  if (!existingVarId) {
8939
- const varId = randomUUID6();
9082
+ const varId = randomUUID7();
8940
9083
  env2.variables[varId] = makeVariable(cleaned, value);
8941
9084
  varIdLookup.set(`${envId}:${cleaned}`, varId);
8942
9085
  }
@@ -8965,7 +9108,7 @@ async function runLegacyMigration(dataDir) {
8965
9108
  }
8966
9109
  let existingSettings = {};
8967
9110
  try {
8968
- existingSettings = JSON.parse(await readFile7(join14(dataDir, "settings.json"), "utf-8"));
9111
+ existingSettings = JSON.parse(await readFile8(join15(dataDir, "settings.json"), "utf-8"));
8969
9112
  } catch {
8970
9113
  }
8971
9114
  const migratedParsers = legacyParsers.map((p) => ({
@@ -8986,11 +9129,11 @@ ${p.transform ?? ""}`,
8986
9129
  ...migratedParsers
8987
9130
  ]
8988
9131
  };
8989
- await atomicWrite(join14(dataDir, "projects.json"), runeProjects);
8990
- await atomicWrite(join14(dataDir, "services.json"), runeServices);
8991
- await atomicWrite(join14(dataDir, "environments.json"), runeEnvs);
8992
- await atomicWrite(join14(dataDir, "environment-overrides.json"), flatOverrides);
8993
- await atomicWrite(join14(dataDir, "settings.json"), newSettings);
9132
+ await atomicWrite(join15(dataDir, "projects.json"), runeProjects);
9133
+ await atomicWrite(join15(dataDir, "services.json"), runeServices);
9134
+ await atomicWrite(join15(dataDir, "environments.json"), runeEnvs);
9135
+ await atomicWrite(join15(dataDir, "environment-overrides.json"), flatOverrides);
9136
+ await atomicWrite(join15(dataDir, "settings.json"), newSettings);
8994
9137
  const svcEnvCount = runeEnvs.filter((e) => e.scope === "service").length;
8995
9138
  console.log(`[legacy-migration] Written: ${runeProjects.length} projects, ${runeServices.length} services, ${runeEnvs.length} environments (${svcEnvCount} service-scoped)`);
8996
9139
  console.log(`[legacy-migration] Overrides: ${Object.keys(flatOverrides).length}, custom parsers: ${migratedParsers.length} (all disabled \u2014 rewrite required)`);
@@ -9004,9 +9147,9 @@ async function findLegacyKeyInBackup(dataDir) {
9004
9147
  const entries2 = await readdir6(dataDir);
9005
9148
  const backupDirs = entries2.filter((e) => e.startsWith("backup-")).sort((a, b) => a < b ? -1 : a > b ? 1 : 0).reverse();
9006
9149
  for (const dir of backupDirs) {
9007
- const keyJsonPath = join14(dataDir, dir, "dbs", "encryption-key.json");
9150
+ const keyJsonPath = join15(dataDir, dir, "dbs", "encryption-key.json");
9008
9151
  try {
9009
- const raw = await readFile7(keyJsonPath, "utf-8");
9152
+ const raw = await readFile8(keyJsonPath, "utf-8");
9010
9153
  const parsed = JSON.parse(raw);
9011
9154
  if (!parsed.encryptionKey) continue;
9012
9155
  const sodium = await getSodium();
@@ -9027,8 +9170,8 @@ async function runOverrideOnlyMigration(dataDir) {
9027
9170
  const { resolve: resolve4 } = await import("path");
9028
9171
  const abDataDir = resolve4(dataDir);
9029
9172
  const candidateDirs = [
9030
- join14(dirname5(env.DATA_DIR), ".runeya", "dbs", "overrides"),
9031
- join14(abDataDir, "dbs", "overrides")
9173
+ join15(dirname6(env.DATA_DIR), ".runeya", "dbs", "overrides"),
9174
+ join15(abDataDir, "dbs", "overrides")
9032
9175
  ];
9033
9176
  let overridesDir = null;
9034
9177
  let overrideFiles = [];
@@ -9044,7 +9187,7 @@ async function runOverrideOnlyMigration(dataDir) {
9044
9187
  }
9045
9188
  }
9046
9189
  if (!overridesDir || overrideFiles.length === 0) return false;
9047
- const legacyKeyPath = join14(overridesDir, "..", "encryption-key.json");
9190
+ const legacyKeyPath = join15(overridesDir, "..", "encryption-key.json");
9048
9191
  try {
9049
9192
  await access2(legacyKeyPath);
9050
9193
  return false;
@@ -9062,7 +9205,7 @@ async function runOverrideOnlyMigration(dataDir) {
9062
9205
  const envNameToId = {};
9063
9206
  let envsRaw;
9064
9207
  try {
9065
- envsRaw = JSON.parse(await readFile7(join14(abDataDir, "environments.json"), "utf-8"));
9208
+ envsRaw = JSON.parse(await readFile8(join15(abDataDir, "environments.json"), "utf-8"));
9066
9209
  for (const _env of envsRaw) {
9067
9210
  const env2 = _env;
9068
9211
  if (env2["name"] && env2["id"]) {
@@ -9081,7 +9224,7 @@ async function runOverrideOnlyMigration(dataDir) {
9081
9224
  let servicesRaw = [];
9082
9225
  const serviceNameToId = {};
9083
9226
  try {
9084
- servicesRaw = JSON.parse(await readFile7(join14(abDataDir, "services.json"), "utf-8"));
9227
+ servicesRaw = JSON.parse(await readFile8(join15(abDataDir, "services.json"), "utf-8"));
9085
9228
  for (const _svc of servicesRaw) {
9086
9229
  const svc = _svc;
9087
9230
  if (svc["name"] && svc["id"]) serviceNameToId[svc["name"]] = svc["id"];
@@ -9098,7 +9241,7 @@ async function runOverrideOnlyMigration(dataDir) {
9098
9241
  const envName = baseName.slice(0, -"-environment".length);
9099
9242
  let data;
9100
9243
  try {
9101
- data = await decryptLegacyFile(join14(overridesDir, file), sodiumKey, sodium);
9244
+ data = await decryptLegacyFile(join15(overridesDir, file), sodiumKey, sodium);
9102
9245
  } catch (err) {
9103
9246
  console.warn(`[override-migration] Failed to decrypt ${file}: ${err.message}`);
9104
9247
  continue;
@@ -9120,12 +9263,12 @@ async function runOverrideOnlyMigration(dataDir) {
9120
9263
  if (isSameAsBase(value, baseVar)) continue;
9121
9264
  flatOverrides[varId] = makeVariable(cleaned, value);
9122
9265
  } else {
9123
- flatOverrides[randomUUID6()] = makeVariable(cleaned, value);
9266
+ flatOverrides[randomUUID7()] = makeVariable(cleaned, value);
9124
9267
  }
9125
9268
  }
9126
9269
  }
9127
9270
  if (Object.keys(flatOverrides).length > 0) {
9128
- await atomicWrite(join14(abDataDir, "environment-overrides.json"), flatOverrides);
9271
+ await atomicWrite(join15(abDataDir, "environment-overrides.json"), flatOverrides);
9129
9272
  console.log(`[override-migration] Written ${Object.keys(flatOverrides).length} override(s) to environment-overrides.json`);
9130
9273
  }
9131
9274
  let envsModified = false;
@@ -9135,7 +9278,7 @@ async function runOverrideOnlyMigration(dataDir) {
9135
9278
  const serviceName = baseName.slice(0, -"-envs".length);
9136
9279
  let data;
9137
9280
  try {
9138
- data = await decryptLegacyFile(join14(overridesDir, file), sodiumKey, sodium);
9281
+ data = await decryptLegacyFile(join15(overridesDir, file), sodiumKey, sodium);
9139
9282
  } catch (err) {
9140
9283
  console.warn(`[override-migration] Failed to decrypt ${file}: ${err.message}`);
9141
9284
  continue;
@@ -9157,7 +9300,7 @@ async function runOverrideOnlyMigration(dataDir) {
9157
9300
  );
9158
9301
  if (!svcScopedEnv) {
9159
9302
  svcScopedEnv = {
9160
- id: randomUUID6(),
9303
+ id: randomUUID7(),
9161
9304
  projectId: globalEnv["projectId"],
9162
9305
  name: `${service?.["name"] || serviceName} (${globalEnv["name"]})`,
9163
9306
  scope: "service",
@@ -9179,7 +9322,7 @@ async function runOverrideOnlyMigration(dataDir) {
9179
9322
  const baseEntry = Object.entries(svcScopedEnv["variables"]).find(([, v]) => v.key === cleaned);
9180
9323
  let varId = baseEntry?.[0];
9181
9324
  if (!varId) {
9182
- varId = randomUUID6();
9325
+ varId = randomUUID7();
9183
9326
  svcScopedEnv["variables"][varId] = {
9184
9327
  key: cleaned,
9185
9328
  value: { value: "", pre: "", post: "", isSecret: false, shareWithAi: false, injectIntoAi: false, required: false, overrideOnly: false, description: "" }
@@ -9194,7 +9337,7 @@ async function runOverrideOnlyMigration(dataDir) {
9194
9337
  }
9195
9338
  }
9196
9339
  if (envsModified) {
9197
- await atomicWrite(join14(abDataDir, "environments.json"), envsRaw);
9340
+ await atomicWrite(join15(abDataDir, "environments.json"), envsRaw);
9198
9341
  console.log("[override-migration] Merged service overrides into environments.json");
9199
9342
  }
9200
9343
  const migratedDir = overridesDir.replace(/overrides$/, "overrides-migrated");
@@ -9209,7 +9352,7 @@ async function runOverrideOnlyMigration(dataDir) {
9209
9352
  }
9210
9353
 
9211
9354
  // ../server/src/services/server-state.ts
9212
- import { join as join15 } from "path";
9355
+ import { join as join16 } from "path";
9213
9356
  import { stat as stat10 } from "fs/promises";
9214
9357
  var ENCRYPTED_KEY_FILENAME2 = ".encryption.key.enc";
9215
9358
  var VERIFY_FILENAME2 = ".runeya-verify";
@@ -9219,22 +9362,22 @@ async function getServerState() {
9219
9362
  let hasVerify = false;
9220
9363
  let hasData = false;
9221
9364
  try {
9222
- await stat10(join15(dataDir, ENCRYPTED_KEY_FILENAME2));
9365
+ await stat10(join16(dataDir, ENCRYPTED_KEY_FILENAME2));
9223
9366
  hasEncFile = true;
9224
9367
  } catch {
9225
9368
  }
9226
9369
  try {
9227
- await stat10(join15(dataDir, VERIFY_FILENAME2));
9370
+ await stat10(join16(dataDir, VERIFY_FILENAME2));
9228
9371
  hasVerify = true;
9229
9372
  } catch {
9230
9373
  }
9231
9374
  try {
9232
- await stat10(join15(dataDir, "projects.json"));
9375
+ await stat10(join16(dataDir, "projects.json"));
9233
9376
  hasData = true;
9234
9377
  } catch {
9235
9378
  }
9236
9379
  try {
9237
- await stat10(join15(dataDir, "project.json"));
9380
+ await stat10(join16(dataDir, "project.json"));
9238
9381
  hasData = true;
9239
9382
  } catch {
9240
9383
  }
@@ -10369,7 +10512,7 @@ async function createLocalServer() {
10369
10512
  stopClaudeTranscriptWatcher();
10370
10513
  stopCodexTranscriptWatcher();
10371
10514
  imageCleanupService.stop();
10372
- cloudSyncBridge.stopAll();
10515
+ void cloudSyncBridge.stopAll();
10373
10516
  await Promise.all([
10374
10517
  unregisterInstance(),
10375
10518
  agentSpawner.shutdown(),
@@ -10386,7 +10529,7 @@ async function createLocalServer() {
10386
10529
  ]);
10387
10530
  console.log("[server] Shutdown complete");
10388
10531
  };
10389
- const { initCompanion } = await import("./companion-AUMA6RGX.js");
10532
+ const { initCompanion } = await import("./companion-HEJHC3UR.js");
10390
10533
  initCompanion();
10391
10534
  return { app, server, wss, shutdown };
10392
10535
  }
@@ -10517,7 +10660,7 @@ function onTrayServicesChanged(listener) {
10517
10660
 
10518
10661
  // ../server/src/services/tray-icon.ts
10519
10662
  import { mkdir as mkdir12, writeFile as writeFile10, rename as rename8 } from "fs/promises";
10520
- import { join as join16 } from "path";
10663
+ import { join as join17 } from "path";
10521
10664
 
10522
10665
  // ../server/src/services/png-to-ico.ts
10523
10666
  function isPng(bytes) {
@@ -10677,7 +10820,7 @@ var FETCH_TIMEOUT_MS = 3e3;
10677
10820
  var CACHE_TTL_MS = 10 * 6e4;
10678
10821
  var cache2 = /* @__PURE__ */ new Map();
10679
10822
  function trayIconDir() {
10680
- return join16(machineRoot(), "tray-icons");
10823
+ return join17(machineRoot(), "tray-icons");
10681
10824
  }
10682
10825
  async function resolveTrayIcon(platform = process.platform) {
10683
10826
  const orgId = getCurrentProject()?.orgId;
@@ -10706,7 +10849,7 @@ async function renderThemedIcon(platform) {
10706
10849
  async function writeTrayIcon(stem, png, platform) {
10707
10850
  const dir = trayIconDir();
10708
10851
  await mkdir12(dir, { recursive: true });
10709
- const path = join16(dir, stem);
10852
+ const path = join17(dir, stem);
10710
10853
  if (platform === "win32") {
10711
10854
  const ico = pngToIco(png);
10712
10855
  return ico ? writeAtomic(`${path}.ico`, ico) : null;
@@ -10833,4 +10976,4 @@ export {
10833
10976
  startProcess,
10834
10977
  stopProcess
10835
10978
  };
10836
- //# sourceMappingURL=src-JIS3X4OU.js.map
10979
+ //# sourceMappingURL=src-YUVA6WCM.js.map