@askexenow/exe-os 0.9.66 → 0.9.67

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.
Files changed (99) hide show
  1. package/deploy/stack-manifests/v0.9.json +54 -5
  2. package/dist/bin/age-ontology-load.js +61 -0
  3. package/dist/bin/agentic-ontology-backfill.js +4708 -0
  4. package/dist/bin/agentic-reflection-backfill.js +4144 -0
  5. package/dist/bin/{exe-link.js → agentic-semantic-label.js} +1523 -2275
  6. package/dist/bin/backfill-conversations.js +506 -20
  7. package/dist/bin/backfill-responses.js +506 -20
  8. package/dist/bin/backfill-vectors.js +233 -20
  9. package/dist/bin/bulk-sync-postgres.js +4876 -0
  10. package/dist/bin/cleanup-stale-review-tasks.js +507 -21
  11. package/dist/bin/cli.js +2450 -1530
  12. package/dist/bin/exe-assign.js +506 -20
  13. package/dist/bin/exe-boot.js +410 -60
  14. package/dist/bin/exe-cloud.js +795 -105
  15. package/dist/bin/exe-dispatch.js +516 -22
  16. package/dist/bin/exe-doctor.js +587 -30
  17. package/dist/bin/exe-export-behaviors.js +518 -24
  18. package/dist/bin/exe-forget.js +507 -21
  19. package/dist/bin/exe-gateway.js +571 -25
  20. package/dist/bin/exe-heartbeat.js +518 -24
  21. package/dist/bin/exe-kill.js +507 -21
  22. package/dist/bin/exe-launch-agent.js +2312 -1069
  23. package/dist/bin/exe-new-employee.js +197 -165
  24. package/dist/bin/exe-pending-messages.js +507 -21
  25. package/dist/bin/exe-pending-notifications.js +507 -21
  26. package/dist/bin/exe-pending-reviews.js +507 -21
  27. package/dist/bin/exe-rename.js +507 -21
  28. package/dist/bin/exe-review.js +507 -21
  29. package/dist/bin/exe-search.js +518 -24
  30. package/dist/bin/exe-session-cleanup.js +516 -22
  31. package/dist/bin/exe-settings.js +4 -0
  32. package/dist/bin/exe-start-codex.js +682 -143
  33. package/dist/bin/exe-start-opencode.js +627 -79
  34. package/dist/bin/exe-status.js +507 -21
  35. package/dist/bin/exe-team.js +507 -21
  36. package/dist/bin/git-sweep.js +516 -22
  37. package/dist/bin/graph-backfill.js +558 -21
  38. package/dist/bin/graph-export.js +507 -21
  39. package/dist/bin/graph-layer-benchmark.js +109 -0
  40. package/dist/bin/install.js +305 -288
  41. package/dist/bin/intercom-check.js +516 -22
  42. package/dist/bin/postgres-agentic-reflection-backfill.js +187 -0
  43. package/dist/bin/postgres-agentic-semantic-backfill.js +237 -0
  44. package/dist/bin/scan-tasks.js +516 -22
  45. package/dist/bin/setup.js +412 -62
  46. package/dist/bin/shard-migrate.js +506 -20
  47. package/dist/gateway/index.js +569 -23
  48. package/dist/hooks/bug-report-worker.js +519 -25
  49. package/dist/hooks/codex-stop-task-finalizer.js +516 -22
  50. package/dist/hooks/commit-complete.js +516 -22
  51. package/dist/hooks/error-recall.js +518 -24
  52. package/dist/hooks/ingest.js +516 -22
  53. package/dist/hooks/instructions-loaded.js +507 -21
  54. package/dist/hooks/notification.js +507 -21
  55. package/dist/hooks/post-compact.js +507 -21
  56. package/dist/hooks/post-tool-combined.js +519 -25
  57. package/dist/hooks/pre-compact.js +516 -22
  58. package/dist/hooks/pre-tool-use.js +507 -21
  59. package/dist/hooks/prompt-submit.js +519 -25
  60. package/dist/hooks/session-end.js +516 -22
  61. package/dist/hooks/session-start.js +520 -26
  62. package/dist/hooks/stop.js +517 -23
  63. package/dist/hooks/subagent-stop.js +507 -21
  64. package/dist/hooks/summary-worker.js +411 -61
  65. package/dist/index.js +569 -23
  66. package/dist/lib/cloud-sync.js +391 -53
  67. package/dist/lib/config.js +13 -1
  68. package/dist/lib/consolidation.js +1 -1
  69. package/dist/lib/database.js +124 -0
  70. package/dist/lib/db.js +124 -0
  71. package/dist/lib/device-registry.js +124 -0
  72. package/dist/lib/embedder.js +13 -1
  73. package/dist/lib/exe-daemon.js +2184 -561
  74. package/dist/lib/hybrid-search.js +518 -24
  75. package/dist/lib/identity.js +3 -0
  76. package/dist/lib/keychain.js +178 -22
  77. package/dist/lib/messaging.js +3 -0
  78. package/dist/lib/reminders.js +3 -0
  79. package/dist/lib/schedules.js +233 -20
  80. package/dist/lib/skill-learning.js +16 -1
  81. package/dist/lib/store.js +506 -20
  82. package/dist/lib/tasks.js +16 -1
  83. package/dist/lib/tmux-routing.js +16 -1
  84. package/dist/lib/token-spend.js +3 -0
  85. package/dist/mcp/server.js +1757 -428
  86. package/dist/mcp/tools/complete-reminder.js +3 -0
  87. package/dist/mcp/tools/create-reminder.js +3 -0
  88. package/dist/mcp/tools/create-task.js +16 -1
  89. package/dist/mcp/tools/deactivate-behavior.js +3 -0
  90. package/dist/mcp/tools/list-reminders.js +3 -0
  91. package/dist/mcp/tools/list-tasks.js +3 -0
  92. package/dist/mcp/tools/send-message.js +3 -0
  93. package/dist/mcp/tools/update-task.js +16 -1
  94. package/dist/runtime/index.js +516 -22
  95. package/dist/tui/App.js +594 -29
  96. package/package.json +8 -5
  97. package/src/commands/exe/cloud.md +6 -10
  98. package/stack.release.json +3 -3
  99. package/src/commands/exe/link.md +0 -18
@@ -183,6 +183,10 @@ async function loadConfig() {
183
183
  if (config.dbPath.startsWith("~")) {
184
184
  config.dbPath = config.dbPath.replace(/^~/, os.homedir());
185
185
  }
186
+ const envDbPath = path.join(dir, "memories.db");
187
+ if (process.env.EXE_OS_DIR && config.dbPath !== envDbPath && !existsSync2(config.dbPath) && existsSync2(envDbPath)) {
188
+ config.dbPath = envDbPath;
189
+ }
186
190
  return config;
187
191
  } catch {
188
192
  return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
@@ -203,7 +207,15 @@ function loadConfigSync() {
203
207
  normalizeSessionLifecycle(migratedCfg);
204
208
  normalizeAutoUpdate(migratedCfg);
205
209
  normalizeOrchestration(migratedCfg);
206
- return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
210
+ const config = { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
211
+ if (config.dbPath.startsWith("~")) {
212
+ config.dbPath = config.dbPath.replace(/^~/, os.homedir());
213
+ }
214
+ const envDbPath = path.join(dir, "memories.db");
215
+ if (process.env.EXE_OS_DIR && config.dbPath !== envDbPath && !existsSync2(config.dbPath) && existsSync2(envDbPath)) {
216
+ config.dbPath = envDbPath;
217
+ }
218
+ return config;
207
219
  } catch {
208
220
  return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
209
221
  }
@@ -2324,6 +2336,9 @@ function getClient() {
2324
2336
  if (_daemonClient && _daemonClient._isDaemonActive()) {
2325
2337
  return _daemonClient;
2326
2338
  }
2339
+ if (!_resilientClient) {
2340
+ return _adapterClient;
2341
+ }
2327
2342
  return _resilientClient;
2328
2343
  }
2329
2344
  async function initDaemonClient() {
@@ -3356,6 +3371,127 @@ async function ensureSchema() {
3356
3371
  VALUES (new.rowid, new.content, new.subject, new.predicate, new.object);
3357
3372
  END;
3358
3373
  `);
3374
+ await client.executeMultiple(`
3375
+ CREATE TABLE IF NOT EXISTS agent_sessions (
3376
+ id TEXT PRIMARY KEY,
3377
+ agent_id TEXT NOT NULL,
3378
+ project_name TEXT,
3379
+ started_at TEXT NOT NULL,
3380
+ last_event_at TEXT NOT NULL,
3381
+ event_count INTEGER NOT NULL DEFAULT 0,
3382
+ properties TEXT DEFAULT '{}'
3383
+ );
3384
+
3385
+ CREATE INDEX IF NOT EXISTS idx_agent_sessions_agent_time
3386
+ ON agent_sessions(agent_id, started_at);
3387
+
3388
+ CREATE TABLE IF NOT EXISTS agent_goals (
3389
+ id TEXT PRIMARY KEY,
3390
+ statement TEXT NOT NULL,
3391
+ owner_agent_id TEXT,
3392
+ project_name TEXT,
3393
+ status TEXT NOT NULL DEFAULT 'open',
3394
+ priority INTEGER NOT NULL DEFAULT 5,
3395
+ success_criteria TEXT,
3396
+ parent_goal_id TEXT,
3397
+ due_at TEXT,
3398
+ achieved_at TEXT,
3399
+ supersedes_id TEXT,
3400
+ created_at TEXT NOT NULL,
3401
+ updated_at TEXT NOT NULL,
3402
+ source_memory_id TEXT
3403
+ );
3404
+
3405
+ CREATE INDEX IF NOT EXISTS idx_agent_goals_project_status
3406
+ ON agent_goals(project_name, status, priority);
3407
+
3408
+ CREATE TABLE IF NOT EXISTS agent_events (
3409
+ id TEXT PRIMARY KEY,
3410
+ event_type TEXT NOT NULL,
3411
+ occurred_at TEXT NOT NULL,
3412
+ sequence_index INTEGER NOT NULL,
3413
+ actor_agent_id TEXT,
3414
+ agent_role TEXT,
3415
+ project_name TEXT,
3416
+ session_id TEXT,
3417
+ task_id TEXT,
3418
+ goal_id TEXT,
3419
+ parent_event_id TEXT,
3420
+ intention TEXT,
3421
+ outcome TEXT,
3422
+ evidence_memory_id TEXT,
3423
+ impact TEXT,
3424
+ payload TEXT DEFAULT '{}',
3425
+ created_at TEXT NOT NULL
3426
+ );
3427
+
3428
+ CREATE INDEX IF NOT EXISTS idx_agent_events_time
3429
+ ON agent_events(occurred_at, sequence_index);
3430
+
3431
+ CREATE INDEX IF NOT EXISTS idx_agent_events_session_seq
3432
+ ON agent_events(session_id, sequence_index);
3433
+
3434
+ CREATE INDEX IF NOT EXISTS idx_agent_events_goal_time
3435
+ ON agent_events(goal_id, occurred_at);
3436
+
3437
+ CREATE INDEX IF NOT EXISTS idx_agent_events_memory
3438
+ ON agent_events(evidence_memory_id);
3439
+
3440
+ CREATE TABLE IF NOT EXISTS agent_goal_links (
3441
+ id TEXT PRIMARY KEY,
3442
+ goal_id TEXT NOT NULL,
3443
+ link_type TEXT NOT NULL,
3444
+ target_id TEXT NOT NULL,
3445
+ target_type TEXT NOT NULL,
3446
+ created_at TEXT NOT NULL
3447
+ );
3448
+
3449
+ CREATE INDEX IF NOT EXISTS idx_agent_goal_links_goal
3450
+ ON agent_goal_links(goal_id, target_type);
3451
+
3452
+ CREATE TABLE IF NOT EXISTS agent_semantic_labels (
3453
+ id TEXT PRIMARY KEY,
3454
+ source_memory_id TEXT NOT NULL,
3455
+ event_id TEXT,
3456
+ labeler TEXT NOT NULL,
3457
+ schema_version INTEGER NOT NULL DEFAULT 1,
3458
+ confidence REAL NOT NULL DEFAULT 0,
3459
+ labels TEXT NOT NULL,
3460
+ created_at TEXT NOT NULL,
3461
+ updated_at TEXT NOT NULL
3462
+ );
3463
+
3464
+ CREATE INDEX IF NOT EXISTS idx_agent_semantic_labels_memory
3465
+ ON agent_semantic_labels(source_memory_id, labeler);
3466
+
3467
+ CREATE INDEX IF NOT EXISTS idx_agent_semantic_labels_event
3468
+ ON agent_semantic_labels(event_id);
3469
+
3470
+ CREATE TABLE IF NOT EXISTS agent_reflection_checkpoints (
3471
+ id TEXT PRIMARY KEY,
3472
+ project_name TEXT,
3473
+ session_id TEXT,
3474
+ window_start_at TEXT NOT NULL,
3475
+ window_end_at TEXT NOT NULL,
3476
+ event_count INTEGER NOT NULL DEFAULT 0,
3477
+ goal_count INTEGER NOT NULL DEFAULT 0,
3478
+ success_count INTEGER NOT NULL DEFAULT 0,
3479
+ failure_count INTEGER NOT NULL DEFAULT 0,
3480
+ risk_count INTEGER NOT NULL DEFAULT 0,
3481
+ summary TEXT NOT NULL,
3482
+ learnings TEXT NOT NULL DEFAULT '[]',
3483
+ next_actions TEXT NOT NULL DEFAULT '[]',
3484
+ evidence_event_ids TEXT NOT NULL DEFAULT '[]',
3485
+ confidence REAL NOT NULL DEFAULT 0,
3486
+ created_at TEXT NOT NULL
3487
+ );
3488
+
3489
+ CREATE INDEX IF NOT EXISTS idx_agent_reflection_project_time
3490
+ ON agent_reflection_checkpoints(project_name, window_end_at);
3491
+
3492
+ CREATE INDEX IF NOT EXISTS idx_agent_reflection_session_time
3493
+ ON agent_reflection_checkpoints(session_id, window_end_at);
3494
+ `);
3359
3495
  try {
3360
3496
  await client.execute({
3361
3497
  sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
@@ -6737,7 +6873,7 @@ var init_task_scope = __esm({
6737
6873
 
6738
6874
  // src/lib/keychain.ts
6739
6875
  import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod as chmod2 } from "fs/promises";
6740
- import { existsSync as existsSync17 } from "fs";
6876
+ import { existsSync as existsSync17, statSync as statSync3 } from "fs";
6741
6877
  import { execSync as execSync8 } from "child_process";
6742
6878
  import path21 from "path";
6743
6879
  import os12 from "os";
@@ -6747,29 +6883,78 @@ function getKeyDir() {
6747
6883
  function getKeyPath() {
6748
6884
  return path21.join(getKeyDir(), "master.key");
6749
6885
  }
6750
- function macKeychainGet() {
6886
+ function nativeKeychainAllowed() {
6887
+ return process.env.EXE_OS_DISABLE_NATIVE_KEYCHAIN !== "1";
6888
+ }
6889
+ function linuxSecretAvailable() {
6890
+ if (!nativeKeychainAllowed()) return false;
6891
+ if (process.platform !== "linux") return false;
6892
+ if (linuxSecretAvailability !== null) return linuxSecretAvailability;
6893
+ try {
6894
+ execSync8("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
6895
+ } catch {
6896
+ linuxSecretAvailability = false;
6897
+ return false;
6898
+ }
6899
+ try {
6900
+ execSync8("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
6901
+ linuxSecretAvailability = true;
6902
+ } catch {
6903
+ linuxSecretAvailability = false;
6904
+ }
6905
+ return linuxSecretAvailability;
6906
+ }
6907
+ function isRootOnlyTrustedServerKeyFile(keyPath) {
6908
+ if (process.platform !== "linux") return false;
6909
+ try {
6910
+ const uid = typeof os12.userInfo().uid === "number" ? os12.userInfo().uid : -1;
6911
+ const st = statSync3(keyPath);
6912
+ if (!st.isFile() || (st.mode & 63) !== 0) return false;
6913
+ if (uid === 0) return true;
6914
+ const exeOsDir = process.env.EXE_OS_DIR;
6915
+ return Boolean(exeOsDir && path21.resolve(keyPath).startsWith(path21.resolve(exeOsDir) + path21.sep));
6916
+ } catch {
6917
+ return false;
6918
+ }
6919
+ }
6920
+ function macKeychainGet(service = SERVICE) {
6921
+ if (!nativeKeychainAllowed()) return null;
6751
6922
  if (process.platform !== "darwin") return null;
6752
6923
  try {
6753
6924
  return execSync8(
6754
- `security find-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w 2>/dev/null`,
6925
+ `security find-generic-password -s "${service}" -a "${ACCOUNT}" -w 2>/dev/null`,
6755
6926
  { encoding: "utf-8", timeout: 5e3 }
6756
6927
  ).trim();
6757
6928
  } catch {
6758
6929
  return null;
6759
6930
  }
6760
6931
  }
6761
- function macKeychainSet(value) {
6932
+ function macKeychainSet(value, service = SERVICE) {
6933
+ if (!nativeKeychainAllowed()) return false;
6762
6934
  if (process.platform !== "darwin") return false;
6763
6935
  try {
6764
6936
  try {
6765
6937
  execSync8(
6766
- `security delete-generic-password -s "${SERVICE}" -a "${ACCOUNT}" 2>/dev/null`,
6938
+ `security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
6767
6939
  { timeout: 5e3 }
6768
6940
  );
6769
6941
  } catch {
6770
6942
  }
6771
6943
  execSync8(
6772
- `security add-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w "${value}"`,
6944
+ `security add-generic-password -s "${service}" -a "${ACCOUNT}" -w "${value}"`,
6945
+ { timeout: 5e3 }
6946
+ );
6947
+ return true;
6948
+ } catch {
6949
+ return false;
6950
+ }
6951
+ }
6952
+ function macKeychainDelete(service = SERVICE) {
6953
+ if (!nativeKeychainAllowed()) return false;
6954
+ if (process.platform !== "darwin") return false;
6955
+ try {
6956
+ execSync8(
6957
+ `security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
6773
6958
  { timeout: 5e3 }
6774
6959
  );
6775
6960
  return true;
@@ -6777,22 +6962,35 @@ function macKeychainSet(value) {
6777
6962
  return false;
6778
6963
  }
6779
6964
  }
6780
- function linuxSecretGet() {
6781
- if (process.platform !== "linux") return null;
6965
+ function linuxSecretGet(service = SERVICE) {
6966
+ if (!linuxSecretAvailable()) return null;
6782
6967
  try {
6783
6968
  return execSync8(
6784
- `secret-tool lookup service "${SERVICE}" account "${ACCOUNT}" 2>/dev/null`,
6969
+ `secret-tool lookup service "${service}" account "${ACCOUNT}" 2>/dev/null`,
6785
6970
  { encoding: "utf-8", timeout: 5e3 }
6786
6971
  ).trim();
6787
6972
  } catch {
6788
6973
  return null;
6789
6974
  }
6790
6975
  }
6791
- function linuxSecretSet(value) {
6976
+ function linuxSecretSet(value, service = SERVICE) {
6977
+ if (!linuxSecretAvailable()) return false;
6978
+ try {
6979
+ execSync8(
6980
+ `echo -n "${value}" | secret-tool store --label="exe-os master key" service "${service}" account "${ACCOUNT}" 2>/dev/null`,
6981
+ { timeout: 5e3 }
6982
+ );
6983
+ return true;
6984
+ } catch {
6985
+ return false;
6986
+ }
6987
+ }
6988
+ function linuxSecretDelete(service = SERVICE) {
6989
+ if (!nativeKeychainAllowed()) return false;
6792
6990
  if (process.platform !== "linux") return false;
6793
6991
  try {
6794
6992
  execSync8(
6795
- `echo -n "${value}" | secret-tool store --label="exe-os master key" service "${SERVICE}" account "${ACCOUNT}"`,
6993
+ `secret-tool clear service "${service}" account "${ACCOUNT}" 2>/dev/null`,
6796
6994
  { timeout: 5e3 }
6797
6995
  );
6798
6996
  return true;
@@ -6801,6 +6999,7 @@ function linuxSecretSet(value) {
6801
6999
  }
6802
7000
  }
6803
7001
  async function tryKeytar() {
7002
+ if (!nativeKeychainAllowed()) return null;
6804
7003
  try {
6805
7004
  return await import("keytar");
6806
7005
  } catch {
@@ -6874,7 +7073,19 @@ async function writeMachineBoundFileFallback(b64) {
6874
7073
  return "plaintext";
6875
7074
  }
6876
7075
  async function getMasterKey() {
6877
- const nativeValue = macKeychainGet() ?? linuxSecretGet();
7076
+ let nativeValue = macKeychainGet() ?? linuxSecretGet();
7077
+ if (!nativeValue) {
7078
+ const legacyValue = macKeychainGet(LEGACY_SERVICE) ?? linuxSecretGet(LEGACY_SERVICE);
7079
+ if (legacyValue) {
7080
+ const migrated = macKeychainSet(legacyValue) || linuxSecretSet(legacyValue);
7081
+ if (migrated) {
7082
+ macKeychainDelete(LEGACY_SERVICE);
7083
+ linuxSecretDelete(LEGACY_SERVICE);
7084
+ process.stderr.write("[keychain] Migrated keychain service from exe-mem to exe-os.\n");
7085
+ }
7086
+ nativeValue = legacyValue;
7087
+ }
7088
+ }
6878
7089
  if (nativeValue) {
6879
7090
  return Buffer.from(nativeValue, "base64");
6880
7091
  }
@@ -6882,12 +7093,17 @@ async function getMasterKey() {
6882
7093
  if (keytar) {
6883
7094
  try {
6884
7095
  const keytarValue = await keytar.getPassword(SERVICE, ACCOUNT);
6885
- if (keytarValue) {
6886
- const migrated = macKeychainSet(keytarValue) || linuxSecretSet(keytarValue);
7096
+ const legacyKeytarValue = keytarValue ?? await keytar.getPassword(LEGACY_SERVICE, ACCOUNT);
7097
+ if (legacyKeytarValue) {
7098
+ const migrated = macKeychainSet(legacyKeytarValue) || linuxSecretSet(legacyKeytarValue);
6887
7099
  if (migrated) {
6888
7100
  process.stderr.write("[keychain] Migrated key from keytar to native keychain.\n");
7101
+ try {
7102
+ await keytar.deletePassword(LEGACY_SERVICE, ACCOUNT);
7103
+ } catch {
7104
+ }
6889
7105
  }
6890
- return Buffer.from(keytarValue, "base64");
7106
+ return Buffer.from(legacyKeytarValue, "base64");
6891
7107
  }
6892
7108
  } catch {
6893
7109
  }
@@ -6912,7 +7128,7 @@ async function getMasterKey() {
6912
7128
  const decrypted = decryptWithMachineKey(content, machineKey);
6913
7129
  if (!decrypted) {
6914
7130
  process.stderr.write(
6915
- "[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase: exe-os link import\n"
7131
+ "[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase during setup: exe-os setup\n"
6916
7132
  );
6917
7133
  return null;
6918
7134
  }
@@ -6921,6 +7137,9 @@ async function getMasterKey() {
6921
7137
  b64Value = content;
6922
7138
  }
6923
7139
  const key = Buffer.from(b64Value, "base64");
7140
+ if (!content.startsWith(ENCRYPTED_PREFIX) && isRootOnlyTrustedServerKeyFile(keyPath)) {
7141
+ return key;
7142
+ }
6924
7143
  const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
6925
7144
  if (migrated) {
6926
7145
  process.stderr.write("[keychain] Migrated key from file to native keychain.\n");
@@ -6948,12 +7167,14 @@ async function getMasterKey() {
6948
7167
  return null;
6949
7168
  }
6950
7169
  }
6951
- var SERVICE, ACCOUNT, ENCRYPTED_PREFIX;
7170
+ var SERVICE, LEGACY_SERVICE, ACCOUNT, linuxSecretAvailability, ENCRYPTED_PREFIX;
6952
7171
  var init_keychain = __esm({
6953
7172
  "src/lib/keychain.ts"() {
6954
7173
  "use strict";
6955
- SERVICE = "exe-mem";
7174
+ SERVICE = "exe-os";
7175
+ LEGACY_SERVICE = "exe-mem";
6956
7176
  ACCOUNT = "master-key";
7177
+ linuxSecretAvailability = null;
6957
7178
  ENCRYPTED_PREFIX = "enc:";
6958
7179
  }
6959
7180
  });
@@ -7168,7 +7389,7 @@ __export(shard_manager_exports, {
7168
7389
  shardExists: () => shardExists
7169
7390
  });
7170
7391
  import path22 from "path";
7171
- import { existsSync as existsSync18, mkdirSync as mkdirSync9, readdirSync as readdirSync5, renameSync as renameSync5, statSync as statSync3 } from "fs";
7392
+ import { existsSync as existsSync18, mkdirSync as mkdirSync9, readdirSync as readdirSync5, renameSync as renameSync5, statSync as statSync4 } from "fs";
7172
7393
  import { createClient as createClient2 } from "@libsql/client";
7173
7394
  function initShardManager(encryptionKey) {
7174
7395
  _encryptionKey = encryptionKey;
@@ -7232,7 +7453,7 @@ async function auditShardHealth(options = {}) {
7232
7453
  const shards = [];
7233
7454
  for (const name of names) {
7234
7455
  const dbPath = path22.join(SHARDS_DIR, `${name}.db`);
7235
- const stat = statSync3(dbPath);
7456
+ const stat = statSync4(dbPath);
7236
7457
  const item = {
7237
7458
  name,
7238
7459
  path: dbPath,
@@ -7485,7 +7706,7 @@ async function getReadyShardClient(projectName) {
7485
7706
  _shardLastAccess.delete(safeName);
7486
7707
  const dbPath = path22.join(SHARDS_DIR, `${safeName}.db`);
7487
7708
  if (existsSync18(dbPath)) {
7488
- const stat = statSync3(dbPath);
7709
+ const stat = statSync4(dbPath);
7489
7710
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
7490
7711
  const archivedPath = path22.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
7491
7712
  renameSync5(dbPath, archivedPath);
@@ -7992,6 +8213,274 @@ var init_memory_cards = __esm({
7992
8213
  }
7993
8214
  });
7994
8215
 
8216
+ // src/lib/agentic-ontology.ts
8217
+ var agentic_ontology_exports = {};
8218
+ __export(agentic_ontology_exports, {
8219
+ clean: () => clean,
8220
+ extractGoalCandidates: () => extractGoalCandidates,
8221
+ inferIntention: () => inferIntention,
8222
+ inferOntologyEventType: () => inferOntologyEventType,
8223
+ inferOutcome: () => inferOutcome,
8224
+ inferSemanticLabel: () => inferSemanticLabel,
8225
+ insertOntologyForBatch: () => insertOntologyForBatch,
8226
+ insertOntologyForMemory: () => insertOntologyForMemory,
8227
+ ontologyPayload: () => ontologyPayload,
8228
+ stableId: () => stableId2
8229
+ });
8230
+ import { createHash as createHash3 } from "crypto";
8231
+ function stableId2(...parts) {
8232
+ return createHash3("sha256").update(parts.map((p) => String(p ?? "")).join("::")).digest("hex").slice(0, 32);
8233
+ }
8234
+ function clean(text, max = 240) {
8235
+ return text.replace(/\u0000/g, "").replace(/```[\s\S]*?```/g, " ").replace(/\s+/g, " ").trim().slice(0, max);
8236
+ }
8237
+ function inferOntologyEventType(row) {
8238
+ const lower = row.raw_text.toLowerCase();
8239
+ if (row.has_error) return "error";
8240
+ if (/\b(done|complete|completed|fixed|resolved|shipped|deployed|pushed|published)\b/.test(lower)) return "milestone";
8241
+ if (/\b(blocked|failed|error|bug|regression|broken)\b/.test(lower)) return "problem";
8242
+ if (/\b(decided|decision|adr|we chose|approved|rejected)\b/.test(lower)) return "decision";
8243
+ if (/\b(goal|need to|we need|want to|trying to|objective)\b/.test(lower)) return "goal_signal";
8244
+ if (["Bash", "Read", "Edit", "Write", "Grep", "Glob"].includes(row.tool_name)) return "tool_action";
8245
+ if (row.tool_name.startsWith("memory_card")) return "memory_card";
8246
+ return "memory_observation";
8247
+ }
8248
+ function inferIntention(row) {
8249
+ if (row.intent) return clean(row.intent, 220);
8250
+ const text = clean(row.raw_text, 1e3);
8251
+ const patterns = [
8252
+ /(?:we need to|need to|let'?s|i want to|we should|goal is to|objective is to|trying to)\s+([^.!?\n]{8,220})/i,
8253
+ /(?:so that|in order to)\s+([^.!?\n]{8,220})/i,
8254
+ /(?:task|plan):\s*([^.!?\n]{8,220})/i
8255
+ ];
8256
+ for (const p of patterns) {
8257
+ const m = text.match(p);
8258
+ if (m?.[1]) return clean(m[1], 220);
8259
+ }
8260
+ if (["Bash", "Read", "Edit", "Write", "Grep", "Glob"].includes(row.tool_name)) {
8261
+ return `${row.tool_name} during ${row.project_name}`;
8262
+ }
8263
+ return null;
8264
+ }
8265
+ function inferOutcome(row) {
8266
+ if (row.outcome) return clean(row.outcome, 220);
8267
+ if (row.has_error) return "error";
8268
+ const lower = row.raw_text.toLowerCase();
8269
+ if (/\b(done|complete|completed|fixed|resolved|shipped|deployed|pushed|published|passed)\b/.test(lower)) return "success_signal";
8270
+ if (/\b(blocked|failed|error|regression|broken|not working|could not)\b/.test(lower)) return "failure_signal";
8271
+ if (/\b(warning|risk|concern|caveat)\b/.test(lower)) return "risk_signal";
8272
+ return null;
8273
+ }
8274
+ function extractGoalCandidates(row) {
8275
+ const text = clean(row.raw_text, 1600);
8276
+ const patterns = [
8277
+ /(?:we need to|need to|i want to|we should|goal is to|objective is to|trying to|let'?s)\s+([^.!?\n]{12,220})/gi,
8278
+ /(?:success means|success criteria|so that)\s+([^.!?\n]{12,220})/gi
8279
+ ];
8280
+ const out = [];
8281
+ for (const pattern of patterns) {
8282
+ for (const m of text.matchAll(pattern)) {
8283
+ const candidate = clean(m[1] ?? "", 220);
8284
+ if (candidate.length >= 12 && !out.some((x) => x.toLowerCase() === candidate.toLowerCase())) out.push(candidate);
8285
+ if (out.length >= 3) return out;
8286
+ }
8287
+ }
8288
+ return out;
8289
+ }
8290
+ function uniq(values, max = 6) {
8291
+ const out = [];
8292
+ for (const value of values.map((v) => clean(v, 220)).filter(Boolean)) {
8293
+ if (!out.some((x) => x.toLowerCase() === value.toLowerCase())) out.push(value);
8294
+ if (out.length >= max) break;
8295
+ }
8296
+ return out;
8297
+ }
8298
+ function extractMatches(text, patterns, max = 5) {
8299
+ const out = [];
8300
+ for (const pattern of patterns) {
8301
+ for (const match of text.matchAll(pattern)) {
8302
+ const value = match[1] ?? match[0];
8303
+ if (value) out.push(value);
8304
+ if (out.length >= max) return uniq(out, max);
8305
+ }
8306
+ }
8307
+ return uniq(out, max);
8308
+ }
8309
+ function inferSemanticLabel(row) {
8310
+ const text = clean(row.raw_text, 2400);
8311
+ const eventType = inferOntologyEventType(row);
8312
+ const intention = inferIntention(row);
8313
+ const outcome = inferOutcome(row);
8314
+ const goals = extractGoalCandidates(row);
8315
+ const milestones = extractMatches(text, [
8316
+ /\b(?:completed|finished|fixed|resolved|shipped|deployed|published|pushed|passed)\b([^.!?\n]{0,180})/gi,
8317
+ /(?:milestone|done):\s*([^.!?\n]{8,220})/gi
8318
+ ]);
8319
+ const problems = extractMatches(text, [
8320
+ /\b(?:blocked by|failed because|bug|regression|broken|not working|error)\b([^.!?\n]{0,180})/gi,
8321
+ /(?:problem|issue|risk):\s*([^.!?\n]{8,220})/gi
8322
+ ]);
8323
+ const decisions = extractMatches(text, [
8324
+ /(?:decided|decision|adr|we chose|approved|rejected)\s+([^.!?\n]{8,220})/gi
8325
+ ]);
8326
+ const temporalAnchors = extractMatches(text, [
8327
+ /\b(\d{4}-\d{2}-\d{2}(?:[T ][0-9:.+-Z]+)?)\b/g,
8328
+ /\b(today|yesterday|tomorrow|this week|next week|last week|morning|afternoon|tonight)\b/gi
8329
+ ], 8);
8330
+ const nextActions = extractMatches(text, [
8331
+ /(?:next|todo|follow[- ]?up|remaining|need to)\s*:?\s*([^.!?\n]{8,220})/gi
8332
+ ]);
8333
+ const actors = uniq([
8334
+ row.agent_id,
8335
+ ...extractMatches(text, [/\b(?:agent|employee|owner|assignee)[:= ]+([a-zA-Z][a-zA-Z0-9_-]{1,40})/gi], 5)
8336
+ ], 6);
8337
+ const successSignals = milestones.length ? milestones : outcome === "success_signal" ? [clean(text, 180)] : [];
8338
+ const failureSignals = problems.length ? problems : outcome === "failure_signal" || row.has_error ? [clean(text, 180)] : [];
8339
+ const impact = successSignals.length && failureSignals.length ? "mixed" : failureSignals.length ? "negative" : successSignals.length ? "positive" : "neutral";
8340
+ const signalCount = goals.length + milestones.length + problems.length + decisions.length + nextActions.length;
8341
+ return {
8342
+ labeler: "deterministic",
8343
+ schemaVersion: 1,
8344
+ eventType,
8345
+ intention,
8346
+ outcome,
8347
+ impact,
8348
+ confidence: Math.min(0.95, 0.45 + signalCount * 0.08 + (intention ? 0.1 : 0) + (outcome ? 0.1 : 0)),
8349
+ goals,
8350
+ milestones,
8351
+ problems,
8352
+ decisions,
8353
+ actors,
8354
+ temporalAnchors,
8355
+ successSignals,
8356
+ failureSignals,
8357
+ nextActions,
8358
+ summary: clean(text, 280)
8359
+ };
8360
+ }
8361
+ function ontologyPayload(row) {
8362
+ const semantic = inferSemanticLabel(row);
8363
+ return {
8364
+ tool_name: row.tool_name,
8365
+ memory_version: row.version ?? null,
8366
+ domain: row.domain ?? null,
8367
+ trajectory: row.trajectory ? safeJson(row.trajectory) : null,
8368
+ semantic
8369
+ };
8370
+ }
8371
+ function safeJson(value) {
8372
+ try {
8373
+ return JSON.parse(value);
8374
+ } catch {
8375
+ return value.slice(0, 1e3);
8376
+ }
8377
+ }
8378
+ async function resolveClient(client) {
8379
+ if (client) return client;
8380
+ const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
8381
+ return getClient2();
8382
+ }
8383
+ async function insertOntologyForMemory(row, client) {
8384
+ const db = await resolveClient(client);
8385
+ const occurredAt = row.timestamp;
8386
+ const sequence = Number(row.version ?? 0) || Math.floor(new Date(occurredAt).getTime() / 1e3);
8387
+ const eventType = inferOntologyEventType(row);
8388
+ const intention = inferIntention(row);
8389
+ const outcome = inferOutcome(row);
8390
+ const eventId = stableId2("event", row.id);
8391
+ const now = (/* @__PURE__ */ new Date()).toISOString();
8392
+ await db.execute({
8393
+ sql: `INSERT INTO agent_sessions (id, agent_id, project_name, started_at, last_event_at, event_count, properties)
8394
+ VALUES (?, ?, ?, ?, ?, 1, ?)
8395
+ ON CONFLICT(id) DO UPDATE SET last_event_at = MAX(last_event_at, excluded.last_event_at),
8396
+ event_count = event_count + 1`,
8397
+ args: [row.session_id, row.agent_id, row.project_name, occurredAt, occurredAt, JSON.stringify({ agent_role: row.agent_role })]
8398
+ });
8399
+ await db.execute({
8400
+ sql: `INSERT OR IGNORE INTO agent_events
8401
+ (id, event_type, occurred_at, sequence_index, actor_agent_id, agent_role, project_name,
8402
+ session_id, task_id, goal_id, parent_event_id, intention, outcome, evidence_memory_id,
8403
+ impact, payload, created_at)
8404
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL, ?, ?, ?, ?, ?, ?)`,
8405
+ args: [
8406
+ eventId,
8407
+ eventType,
8408
+ occurredAt,
8409
+ sequence,
8410
+ row.agent_id,
8411
+ row.agent_role,
8412
+ row.project_name,
8413
+ row.session_id,
8414
+ row.task_id ?? null,
8415
+ intention,
8416
+ outcome,
8417
+ row.id,
8418
+ row.has_error ? "negative" : outcome === "success_signal" ? "positive" : "neutral",
8419
+ JSON.stringify(ontologyPayload(row)),
8420
+ now
8421
+ ]
8422
+ });
8423
+ const semantic = inferSemanticLabel(row);
8424
+ await db.execute({
8425
+ sql: `INSERT INTO agent_semantic_labels
8426
+ (id, source_memory_id, event_id, labeler, schema_version, confidence, labels, created_at, updated_at)
8427
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
8428
+ ON CONFLICT(id) DO UPDATE SET confidence = excluded.confidence,
8429
+ labels = excluded.labels, updated_at = excluded.updated_at`,
8430
+ args: [
8431
+ stableId2("semantic", row.id, semantic.labeler, semantic.schemaVersion),
8432
+ row.id,
8433
+ eventId,
8434
+ semantic.labeler,
8435
+ semantic.schemaVersion,
8436
+ semantic.confidence,
8437
+ JSON.stringify(semantic),
8438
+ now,
8439
+ now
8440
+ ]
8441
+ });
8442
+ for (const statement of extractGoalCandidates(row)) {
8443
+ const goalId = stableId2("goal", row.project_name, statement.toLowerCase());
8444
+ await db.execute({
8445
+ sql: `INSERT INTO agent_goals
8446
+ (id, statement, owner_agent_id, project_name, status, priority, success_criteria,
8447
+ parent_goal_id, due_at, achieved_at, supersedes_id, created_at, updated_at, source_memory_id)
8448
+ VALUES (?, ?, ?, ?, 'open', 5, NULL, NULL, NULL, NULL, NULL, ?, ?, ?)
8449
+ ON CONFLICT(id) DO UPDATE SET updated_at = excluded.updated_at`,
8450
+ args: [goalId, statement, row.agent_id, row.project_name, now, now, row.id]
8451
+ });
8452
+ await db.execute({
8453
+ sql: `INSERT OR IGNORE INTO agent_goal_links
8454
+ (id, goal_id, link_type, target_id, target_type, created_at)
8455
+ VALUES (?, ?, 'evidence', ?, 'memory', ?)`,
8456
+ args: [stableId2("goal_link", goalId, row.id, "memory"), goalId, row.id, now]
8457
+ });
8458
+ await db.execute({
8459
+ sql: `INSERT OR IGNORE INTO agent_goal_links
8460
+ (id, goal_id, link_type, target_id, target_type, created_at)
8461
+ VALUES (?, ?, 'event', ?, 'event', ?)`,
8462
+ args: [stableId2("goal_link", goalId, eventId, "event"), goalId, eventId, now]
8463
+ });
8464
+ }
8465
+ }
8466
+ async function insertOntologyForBatch(rows, client) {
8467
+ const db = await resolveClient(client);
8468
+ let count = 0;
8469
+ for (const row of rows) {
8470
+ try {
8471
+ await insertOntologyForMemory(row, db);
8472
+ count++;
8473
+ } catch {
8474
+ }
8475
+ }
8476
+ return count;
8477
+ }
8478
+ var init_agentic_ontology = __esm({
8479
+ "src/lib/agentic-ontology.ts"() {
8480
+ "use strict";
8481
+ }
8482
+ });
8483
+
7995
8484
  // src/lib/store.ts
7996
8485
  var store_exports = {};
7997
8486
  __export(store_exports, {
@@ -8335,6 +8824,11 @@ async function flushBatch() {
8335
8824
  await insertMemoryCardsForBatch2(batch);
8336
8825
  } catch {
8337
8826
  }
8827
+ try {
8828
+ const { insertOntologyForBatch: insertOntologyForBatch2 } = await Promise.resolve().then(() => (init_agentic_ontology(), agentic_ontology_exports));
8829
+ await insertOntologyForBatch2(batch);
8830
+ } catch {
8831
+ }
8338
8832
  schedulePostWriteMemoryHygiene(batch.map((row) => row.id));
8339
8833
  _pendingRecords.splice(0, batch.length);
8340
8834
  try {