@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.
- package/deploy/stack-manifests/v0.9.json +54 -5
- package/dist/bin/age-ontology-load.js +61 -0
- package/dist/bin/agentic-ontology-backfill.js +4708 -0
- package/dist/bin/agentic-reflection-backfill.js +4144 -0
- package/dist/bin/{exe-link.js → agentic-semantic-label.js} +1523 -2275
- package/dist/bin/backfill-conversations.js +506 -20
- package/dist/bin/backfill-responses.js +506 -20
- package/dist/bin/backfill-vectors.js +233 -20
- package/dist/bin/bulk-sync-postgres.js +4876 -0
- package/dist/bin/cleanup-stale-review-tasks.js +507 -21
- package/dist/bin/cli.js +2450 -1530
- package/dist/bin/exe-assign.js +506 -20
- package/dist/bin/exe-boot.js +410 -60
- package/dist/bin/exe-cloud.js +795 -105
- package/dist/bin/exe-dispatch.js +516 -22
- package/dist/bin/exe-doctor.js +587 -30
- package/dist/bin/exe-export-behaviors.js +518 -24
- package/dist/bin/exe-forget.js +507 -21
- package/dist/bin/exe-gateway.js +571 -25
- package/dist/bin/exe-heartbeat.js +518 -24
- package/dist/bin/exe-kill.js +507 -21
- package/dist/bin/exe-launch-agent.js +2312 -1069
- package/dist/bin/exe-new-employee.js +197 -165
- package/dist/bin/exe-pending-messages.js +507 -21
- package/dist/bin/exe-pending-notifications.js +507 -21
- package/dist/bin/exe-pending-reviews.js +507 -21
- package/dist/bin/exe-rename.js +507 -21
- package/dist/bin/exe-review.js +507 -21
- package/dist/bin/exe-search.js +518 -24
- package/dist/bin/exe-session-cleanup.js +516 -22
- package/dist/bin/exe-settings.js +4 -0
- package/dist/bin/exe-start-codex.js +682 -143
- package/dist/bin/exe-start-opencode.js +627 -79
- package/dist/bin/exe-status.js +507 -21
- package/dist/bin/exe-team.js +507 -21
- package/dist/bin/git-sweep.js +516 -22
- package/dist/bin/graph-backfill.js +558 -21
- package/dist/bin/graph-export.js +507 -21
- package/dist/bin/graph-layer-benchmark.js +109 -0
- package/dist/bin/install.js +305 -288
- package/dist/bin/intercom-check.js +516 -22
- package/dist/bin/postgres-agentic-reflection-backfill.js +187 -0
- package/dist/bin/postgres-agentic-semantic-backfill.js +237 -0
- package/dist/bin/scan-tasks.js +516 -22
- package/dist/bin/setup.js +412 -62
- package/dist/bin/shard-migrate.js +506 -20
- package/dist/gateway/index.js +569 -23
- package/dist/hooks/bug-report-worker.js +519 -25
- package/dist/hooks/codex-stop-task-finalizer.js +516 -22
- package/dist/hooks/commit-complete.js +516 -22
- package/dist/hooks/error-recall.js +518 -24
- package/dist/hooks/ingest.js +516 -22
- package/dist/hooks/instructions-loaded.js +507 -21
- package/dist/hooks/notification.js +507 -21
- package/dist/hooks/post-compact.js +507 -21
- package/dist/hooks/post-tool-combined.js +519 -25
- package/dist/hooks/pre-compact.js +516 -22
- package/dist/hooks/pre-tool-use.js +507 -21
- package/dist/hooks/prompt-submit.js +519 -25
- package/dist/hooks/session-end.js +516 -22
- package/dist/hooks/session-start.js +520 -26
- package/dist/hooks/stop.js +517 -23
- package/dist/hooks/subagent-stop.js +507 -21
- package/dist/hooks/summary-worker.js +411 -61
- package/dist/index.js +569 -23
- package/dist/lib/cloud-sync.js +391 -53
- package/dist/lib/config.js +13 -1
- package/dist/lib/consolidation.js +1 -1
- package/dist/lib/database.js +124 -0
- package/dist/lib/db.js +124 -0
- package/dist/lib/device-registry.js +124 -0
- package/dist/lib/embedder.js +13 -1
- package/dist/lib/exe-daemon.js +2184 -561
- package/dist/lib/hybrid-search.js +518 -24
- package/dist/lib/identity.js +3 -0
- package/dist/lib/keychain.js +178 -22
- package/dist/lib/messaging.js +3 -0
- package/dist/lib/reminders.js +3 -0
- package/dist/lib/schedules.js +233 -20
- package/dist/lib/skill-learning.js +16 -1
- package/dist/lib/store.js +506 -20
- package/dist/lib/tasks.js +16 -1
- package/dist/lib/tmux-routing.js +16 -1
- package/dist/lib/token-spend.js +3 -0
- package/dist/mcp/server.js +1757 -428
- package/dist/mcp/tools/complete-reminder.js +3 -0
- package/dist/mcp/tools/create-reminder.js +3 -0
- package/dist/mcp/tools/create-task.js +16 -1
- package/dist/mcp/tools/deactivate-behavior.js +3 -0
- package/dist/mcp/tools/list-reminders.js +3 -0
- package/dist/mcp/tools/list-tasks.js +3 -0
- package/dist/mcp/tools/send-message.js +3 -0
- package/dist/mcp/tools/update-task.js +16 -1
- package/dist/runtime/index.js +516 -22
- package/dist/tui/App.js +594 -29
- package/package.json +8 -5
- package/src/commands/exe/cloud.md +6 -10
- package/stack.release.json +3 -3
- package/src/commands/exe/link.md +0 -18
package/dist/index.js
CHANGED
|
@@ -183,6 +183,10 @@ async function loadConfig() {
|
|
|
183
183
|
if (config2.dbPath.startsWith("~")) {
|
|
184
184
|
config2.dbPath = config2.dbPath.replace(/^~/, os2.homedir());
|
|
185
185
|
}
|
|
186
|
+
const envDbPath = path2.join(dir, "memories.db");
|
|
187
|
+
if (process.env.EXE_OS_DIR && config2.dbPath !== envDbPath && !existsSync2(config2.dbPath) && existsSync2(envDbPath)) {
|
|
188
|
+
config2.dbPath = envDbPath;
|
|
189
|
+
}
|
|
186
190
|
return config2;
|
|
187
191
|
} catch {
|
|
188
192
|
return { ...DEFAULT_CONFIG, dbPath: path2.join(dir, "memories.db") };
|
|
@@ -203,7 +207,15 @@ function loadConfigSync() {
|
|
|
203
207
|
normalizeSessionLifecycle(migratedCfg);
|
|
204
208
|
normalizeAutoUpdate(migratedCfg);
|
|
205
209
|
normalizeOrchestration(migratedCfg);
|
|
206
|
-
|
|
210
|
+
const config2 = { ...DEFAULT_CONFIG, dbPath: path2.join(dir, "memories.db"), ...migratedCfg };
|
|
211
|
+
if (config2.dbPath.startsWith("~")) {
|
|
212
|
+
config2.dbPath = config2.dbPath.replace(/^~/, os2.homedir());
|
|
213
|
+
}
|
|
214
|
+
const envDbPath = path2.join(dir, "memories.db");
|
|
215
|
+
if (process.env.EXE_OS_DIR && config2.dbPath !== envDbPath && !existsSync2(config2.dbPath) && existsSync2(envDbPath)) {
|
|
216
|
+
config2.dbPath = envDbPath;
|
|
217
|
+
}
|
|
218
|
+
return config2;
|
|
207
219
|
} catch {
|
|
208
220
|
return { ...DEFAULT_CONFIG, dbPath: path2.join(dir, "memories.db") };
|
|
209
221
|
}
|
|
@@ -2545,6 +2557,9 @@ function getClient() {
|
|
|
2545
2557
|
if (_daemonClient && _daemonClient._isDaemonActive()) {
|
|
2546
2558
|
return _daemonClient;
|
|
2547
2559
|
}
|
|
2560
|
+
if (!_resilientClient) {
|
|
2561
|
+
return _adapterClient;
|
|
2562
|
+
}
|
|
2548
2563
|
return _resilientClient;
|
|
2549
2564
|
}
|
|
2550
2565
|
async function initDaemonClient() {
|
|
@@ -3577,6 +3592,127 @@ async function ensureSchema() {
|
|
|
3577
3592
|
VALUES (new.rowid, new.content, new.subject, new.predicate, new.object);
|
|
3578
3593
|
END;
|
|
3579
3594
|
`);
|
|
3595
|
+
await client.executeMultiple(`
|
|
3596
|
+
CREATE TABLE IF NOT EXISTS agent_sessions (
|
|
3597
|
+
id TEXT PRIMARY KEY,
|
|
3598
|
+
agent_id TEXT NOT NULL,
|
|
3599
|
+
project_name TEXT,
|
|
3600
|
+
started_at TEXT NOT NULL,
|
|
3601
|
+
last_event_at TEXT NOT NULL,
|
|
3602
|
+
event_count INTEGER NOT NULL DEFAULT 0,
|
|
3603
|
+
properties TEXT DEFAULT '{}'
|
|
3604
|
+
);
|
|
3605
|
+
|
|
3606
|
+
CREATE INDEX IF NOT EXISTS idx_agent_sessions_agent_time
|
|
3607
|
+
ON agent_sessions(agent_id, started_at);
|
|
3608
|
+
|
|
3609
|
+
CREATE TABLE IF NOT EXISTS agent_goals (
|
|
3610
|
+
id TEXT PRIMARY KEY,
|
|
3611
|
+
statement TEXT NOT NULL,
|
|
3612
|
+
owner_agent_id TEXT,
|
|
3613
|
+
project_name TEXT,
|
|
3614
|
+
status TEXT NOT NULL DEFAULT 'open',
|
|
3615
|
+
priority INTEGER NOT NULL DEFAULT 5,
|
|
3616
|
+
success_criteria TEXT,
|
|
3617
|
+
parent_goal_id TEXT,
|
|
3618
|
+
due_at TEXT,
|
|
3619
|
+
achieved_at TEXT,
|
|
3620
|
+
supersedes_id TEXT,
|
|
3621
|
+
created_at TEXT NOT NULL,
|
|
3622
|
+
updated_at TEXT NOT NULL,
|
|
3623
|
+
source_memory_id TEXT
|
|
3624
|
+
);
|
|
3625
|
+
|
|
3626
|
+
CREATE INDEX IF NOT EXISTS idx_agent_goals_project_status
|
|
3627
|
+
ON agent_goals(project_name, status, priority);
|
|
3628
|
+
|
|
3629
|
+
CREATE TABLE IF NOT EXISTS agent_events (
|
|
3630
|
+
id TEXT PRIMARY KEY,
|
|
3631
|
+
event_type TEXT NOT NULL,
|
|
3632
|
+
occurred_at TEXT NOT NULL,
|
|
3633
|
+
sequence_index INTEGER NOT NULL,
|
|
3634
|
+
actor_agent_id TEXT,
|
|
3635
|
+
agent_role TEXT,
|
|
3636
|
+
project_name TEXT,
|
|
3637
|
+
session_id TEXT,
|
|
3638
|
+
task_id TEXT,
|
|
3639
|
+
goal_id TEXT,
|
|
3640
|
+
parent_event_id TEXT,
|
|
3641
|
+
intention TEXT,
|
|
3642
|
+
outcome TEXT,
|
|
3643
|
+
evidence_memory_id TEXT,
|
|
3644
|
+
impact TEXT,
|
|
3645
|
+
payload TEXT DEFAULT '{}',
|
|
3646
|
+
created_at TEXT NOT NULL
|
|
3647
|
+
);
|
|
3648
|
+
|
|
3649
|
+
CREATE INDEX IF NOT EXISTS idx_agent_events_time
|
|
3650
|
+
ON agent_events(occurred_at, sequence_index);
|
|
3651
|
+
|
|
3652
|
+
CREATE INDEX IF NOT EXISTS idx_agent_events_session_seq
|
|
3653
|
+
ON agent_events(session_id, sequence_index);
|
|
3654
|
+
|
|
3655
|
+
CREATE INDEX IF NOT EXISTS idx_agent_events_goal_time
|
|
3656
|
+
ON agent_events(goal_id, occurred_at);
|
|
3657
|
+
|
|
3658
|
+
CREATE INDEX IF NOT EXISTS idx_agent_events_memory
|
|
3659
|
+
ON agent_events(evidence_memory_id);
|
|
3660
|
+
|
|
3661
|
+
CREATE TABLE IF NOT EXISTS agent_goal_links (
|
|
3662
|
+
id TEXT PRIMARY KEY,
|
|
3663
|
+
goal_id TEXT NOT NULL,
|
|
3664
|
+
link_type TEXT NOT NULL,
|
|
3665
|
+
target_id TEXT NOT NULL,
|
|
3666
|
+
target_type TEXT NOT NULL,
|
|
3667
|
+
created_at TEXT NOT NULL
|
|
3668
|
+
);
|
|
3669
|
+
|
|
3670
|
+
CREATE INDEX IF NOT EXISTS idx_agent_goal_links_goal
|
|
3671
|
+
ON agent_goal_links(goal_id, target_type);
|
|
3672
|
+
|
|
3673
|
+
CREATE TABLE IF NOT EXISTS agent_semantic_labels (
|
|
3674
|
+
id TEXT PRIMARY KEY,
|
|
3675
|
+
source_memory_id TEXT NOT NULL,
|
|
3676
|
+
event_id TEXT,
|
|
3677
|
+
labeler TEXT NOT NULL,
|
|
3678
|
+
schema_version INTEGER NOT NULL DEFAULT 1,
|
|
3679
|
+
confidence REAL NOT NULL DEFAULT 0,
|
|
3680
|
+
labels TEXT NOT NULL,
|
|
3681
|
+
created_at TEXT NOT NULL,
|
|
3682
|
+
updated_at TEXT NOT NULL
|
|
3683
|
+
);
|
|
3684
|
+
|
|
3685
|
+
CREATE INDEX IF NOT EXISTS idx_agent_semantic_labels_memory
|
|
3686
|
+
ON agent_semantic_labels(source_memory_id, labeler);
|
|
3687
|
+
|
|
3688
|
+
CREATE INDEX IF NOT EXISTS idx_agent_semantic_labels_event
|
|
3689
|
+
ON agent_semantic_labels(event_id);
|
|
3690
|
+
|
|
3691
|
+
CREATE TABLE IF NOT EXISTS agent_reflection_checkpoints (
|
|
3692
|
+
id TEXT PRIMARY KEY,
|
|
3693
|
+
project_name TEXT,
|
|
3694
|
+
session_id TEXT,
|
|
3695
|
+
window_start_at TEXT NOT NULL,
|
|
3696
|
+
window_end_at TEXT NOT NULL,
|
|
3697
|
+
event_count INTEGER NOT NULL DEFAULT 0,
|
|
3698
|
+
goal_count INTEGER NOT NULL DEFAULT 0,
|
|
3699
|
+
success_count INTEGER NOT NULL DEFAULT 0,
|
|
3700
|
+
failure_count INTEGER NOT NULL DEFAULT 0,
|
|
3701
|
+
risk_count INTEGER NOT NULL DEFAULT 0,
|
|
3702
|
+
summary TEXT NOT NULL,
|
|
3703
|
+
learnings TEXT NOT NULL DEFAULT '[]',
|
|
3704
|
+
next_actions TEXT NOT NULL DEFAULT '[]',
|
|
3705
|
+
evidence_event_ids TEXT NOT NULL DEFAULT '[]',
|
|
3706
|
+
confidence REAL NOT NULL DEFAULT 0,
|
|
3707
|
+
created_at TEXT NOT NULL
|
|
3708
|
+
);
|
|
3709
|
+
|
|
3710
|
+
CREATE INDEX IF NOT EXISTS idx_agent_reflection_project_time
|
|
3711
|
+
ON agent_reflection_checkpoints(project_name, window_end_at);
|
|
3712
|
+
|
|
3713
|
+
CREATE INDEX IF NOT EXISTS idx_agent_reflection_session_time
|
|
3714
|
+
ON agent_reflection_checkpoints(session_id, window_end_at);
|
|
3715
|
+
`);
|
|
3580
3716
|
try {
|
|
3581
3717
|
await client.execute({
|
|
3582
3718
|
sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
|
|
@@ -7035,7 +7171,7 @@ var init_tmux_routing = __esm({
|
|
|
7035
7171
|
|
|
7036
7172
|
// src/lib/keychain.ts
|
|
7037
7173
|
import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod as chmod2 } from "fs/promises";
|
|
7038
|
-
import { existsSync as existsSync16 } from "fs";
|
|
7174
|
+
import { existsSync as existsSync16, statSync as statSync2 } from "fs";
|
|
7039
7175
|
import { execSync as execSync8 } from "child_process";
|
|
7040
7176
|
import path20 from "path";
|
|
7041
7177
|
import os13 from "os";
|
|
@@ -7045,29 +7181,65 @@ function getKeyDir() {
|
|
|
7045
7181
|
function getKeyPath() {
|
|
7046
7182
|
return path20.join(getKeyDir(), "master.key");
|
|
7047
7183
|
}
|
|
7048
|
-
function
|
|
7184
|
+
function nativeKeychainAllowed() {
|
|
7185
|
+
return process.env.EXE_OS_DISABLE_NATIVE_KEYCHAIN !== "1";
|
|
7186
|
+
}
|
|
7187
|
+
function linuxSecretAvailable() {
|
|
7188
|
+
if (!nativeKeychainAllowed()) return false;
|
|
7189
|
+
if (process.platform !== "linux") return false;
|
|
7190
|
+
if (linuxSecretAvailability !== null) return linuxSecretAvailability;
|
|
7191
|
+
try {
|
|
7192
|
+
execSync8("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
|
|
7193
|
+
} catch {
|
|
7194
|
+
linuxSecretAvailability = false;
|
|
7195
|
+
return false;
|
|
7196
|
+
}
|
|
7197
|
+
try {
|
|
7198
|
+
execSync8("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
|
|
7199
|
+
linuxSecretAvailability = true;
|
|
7200
|
+
} catch {
|
|
7201
|
+
linuxSecretAvailability = false;
|
|
7202
|
+
}
|
|
7203
|
+
return linuxSecretAvailability;
|
|
7204
|
+
}
|
|
7205
|
+
function isRootOnlyTrustedServerKeyFile(keyPath) {
|
|
7206
|
+
if (process.platform !== "linux") return false;
|
|
7207
|
+
try {
|
|
7208
|
+
const uid = typeof os13.userInfo().uid === "number" ? os13.userInfo().uid : -1;
|
|
7209
|
+
const st = statSync2(keyPath);
|
|
7210
|
+
if (!st.isFile() || (st.mode & 63) !== 0) return false;
|
|
7211
|
+
if (uid === 0) return true;
|
|
7212
|
+
const exeOsDir = process.env.EXE_OS_DIR;
|
|
7213
|
+
return Boolean(exeOsDir && path20.resolve(keyPath).startsWith(path20.resolve(exeOsDir) + path20.sep));
|
|
7214
|
+
} catch {
|
|
7215
|
+
return false;
|
|
7216
|
+
}
|
|
7217
|
+
}
|
|
7218
|
+
function macKeychainGet(service = SERVICE) {
|
|
7219
|
+
if (!nativeKeychainAllowed()) return null;
|
|
7049
7220
|
if (process.platform !== "darwin") return null;
|
|
7050
7221
|
try {
|
|
7051
7222
|
return execSync8(
|
|
7052
|
-
`security find-generic-password -s "${
|
|
7223
|
+
`security find-generic-password -s "${service}" -a "${ACCOUNT}" -w 2>/dev/null`,
|
|
7053
7224
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
7054
7225
|
).trim();
|
|
7055
7226
|
} catch {
|
|
7056
7227
|
return null;
|
|
7057
7228
|
}
|
|
7058
7229
|
}
|
|
7059
|
-
function macKeychainSet(value) {
|
|
7230
|
+
function macKeychainSet(value, service = SERVICE) {
|
|
7231
|
+
if (!nativeKeychainAllowed()) return false;
|
|
7060
7232
|
if (process.platform !== "darwin") return false;
|
|
7061
7233
|
try {
|
|
7062
7234
|
try {
|
|
7063
7235
|
execSync8(
|
|
7064
|
-
`security delete-generic-password -s "${
|
|
7236
|
+
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
7065
7237
|
{ timeout: 5e3 }
|
|
7066
7238
|
);
|
|
7067
7239
|
} catch {
|
|
7068
7240
|
}
|
|
7069
7241
|
execSync8(
|
|
7070
|
-
`security add-generic-password -s "${
|
|
7242
|
+
`security add-generic-password -s "${service}" -a "${ACCOUNT}" -w "${value}"`,
|
|
7071
7243
|
{ timeout: 5e3 }
|
|
7072
7244
|
);
|
|
7073
7245
|
return true;
|
|
@@ -7075,22 +7247,48 @@ function macKeychainSet(value) {
|
|
|
7075
7247
|
return false;
|
|
7076
7248
|
}
|
|
7077
7249
|
}
|
|
7078
|
-
function
|
|
7079
|
-
if (
|
|
7250
|
+
function macKeychainDelete(service = SERVICE) {
|
|
7251
|
+
if (!nativeKeychainAllowed()) return false;
|
|
7252
|
+
if (process.platform !== "darwin") return false;
|
|
7253
|
+
try {
|
|
7254
|
+
execSync8(
|
|
7255
|
+
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
7256
|
+
{ timeout: 5e3 }
|
|
7257
|
+
);
|
|
7258
|
+
return true;
|
|
7259
|
+
} catch {
|
|
7260
|
+
return false;
|
|
7261
|
+
}
|
|
7262
|
+
}
|
|
7263
|
+
function linuxSecretGet(service = SERVICE) {
|
|
7264
|
+
if (!linuxSecretAvailable()) return null;
|
|
7080
7265
|
try {
|
|
7081
7266
|
return execSync8(
|
|
7082
|
-
`secret-tool lookup service "${
|
|
7267
|
+
`secret-tool lookup service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
7083
7268
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
7084
7269
|
).trim();
|
|
7085
7270
|
} catch {
|
|
7086
7271
|
return null;
|
|
7087
7272
|
}
|
|
7088
7273
|
}
|
|
7089
|
-
function linuxSecretSet(value) {
|
|
7274
|
+
function linuxSecretSet(value, service = SERVICE) {
|
|
7275
|
+
if (!linuxSecretAvailable()) return false;
|
|
7276
|
+
try {
|
|
7277
|
+
execSync8(
|
|
7278
|
+
`echo -n "${value}" | secret-tool store --label="exe-os master key" service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
7279
|
+
{ timeout: 5e3 }
|
|
7280
|
+
);
|
|
7281
|
+
return true;
|
|
7282
|
+
} catch {
|
|
7283
|
+
return false;
|
|
7284
|
+
}
|
|
7285
|
+
}
|
|
7286
|
+
function linuxSecretDelete(service = SERVICE) {
|
|
7287
|
+
if (!nativeKeychainAllowed()) return false;
|
|
7090
7288
|
if (process.platform !== "linux") return false;
|
|
7091
7289
|
try {
|
|
7092
7290
|
execSync8(
|
|
7093
|
-
`
|
|
7291
|
+
`secret-tool clear service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
7094
7292
|
{ timeout: 5e3 }
|
|
7095
7293
|
);
|
|
7096
7294
|
return true;
|
|
@@ -7099,6 +7297,7 @@ function linuxSecretSet(value) {
|
|
|
7099
7297
|
}
|
|
7100
7298
|
}
|
|
7101
7299
|
async function tryKeytar() {
|
|
7300
|
+
if (!nativeKeychainAllowed()) return null;
|
|
7102
7301
|
try {
|
|
7103
7302
|
return await import("keytar");
|
|
7104
7303
|
} catch {
|
|
@@ -7172,7 +7371,19 @@ async function writeMachineBoundFileFallback(b64) {
|
|
|
7172
7371
|
return "plaintext";
|
|
7173
7372
|
}
|
|
7174
7373
|
async function getMasterKey() {
|
|
7175
|
-
|
|
7374
|
+
let nativeValue = macKeychainGet() ?? linuxSecretGet();
|
|
7375
|
+
if (!nativeValue) {
|
|
7376
|
+
const legacyValue = macKeychainGet(LEGACY_SERVICE) ?? linuxSecretGet(LEGACY_SERVICE);
|
|
7377
|
+
if (legacyValue) {
|
|
7378
|
+
const migrated = macKeychainSet(legacyValue) || linuxSecretSet(legacyValue);
|
|
7379
|
+
if (migrated) {
|
|
7380
|
+
macKeychainDelete(LEGACY_SERVICE);
|
|
7381
|
+
linuxSecretDelete(LEGACY_SERVICE);
|
|
7382
|
+
process.stderr.write("[keychain] Migrated keychain service from exe-mem to exe-os.\n");
|
|
7383
|
+
}
|
|
7384
|
+
nativeValue = legacyValue;
|
|
7385
|
+
}
|
|
7386
|
+
}
|
|
7176
7387
|
if (nativeValue) {
|
|
7177
7388
|
return Buffer.from(nativeValue, "base64");
|
|
7178
7389
|
}
|
|
@@ -7180,12 +7391,17 @@ async function getMasterKey() {
|
|
|
7180
7391
|
if (keytar) {
|
|
7181
7392
|
try {
|
|
7182
7393
|
const keytarValue = await keytar.getPassword(SERVICE, ACCOUNT);
|
|
7183
|
-
|
|
7184
|
-
|
|
7394
|
+
const legacyKeytarValue = keytarValue ?? await keytar.getPassword(LEGACY_SERVICE, ACCOUNT);
|
|
7395
|
+
if (legacyKeytarValue) {
|
|
7396
|
+
const migrated = macKeychainSet(legacyKeytarValue) || linuxSecretSet(legacyKeytarValue);
|
|
7185
7397
|
if (migrated) {
|
|
7186
7398
|
process.stderr.write("[keychain] Migrated key from keytar to native keychain.\n");
|
|
7399
|
+
try {
|
|
7400
|
+
await keytar.deletePassword(LEGACY_SERVICE, ACCOUNT);
|
|
7401
|
+
} catch {
|
|
7402
|
+
}
|
|
7187
7403
|
}
|
|
7188
|
-
return Buffer.from(
|
|
7404
|
+
return Buffer.from(legacyKeytarValue, "base64");
|
|
7189
7405
|
}
|
|
7190
7406
|
} catch {
|
|
7191
7407
|
}
|
|
@@ -7210,7 +7426,7 @@ async function getMasterKey() {
|
|
|
7210
7426
|
const decrypted = decryptWithMachineKey(content, machineKey);
|
|
7211
7427
|
if (!decrypted) {
|
|
7212
7428
|
process.stderr.write(
|
|
7213
|
-
"[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase: exe-os
|
|
7429
|
+
"[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase during setup: exe-os setup\n"
|
|
7214
7430
|
);
|
|
7215
7431
|
return null;
|
|
7216
7432
|
}
|
|
@@ -7219,6 +7435,9 @@ async function getMasterKey() {
|
|
|
7219
7435
|
b64Value = content;
|
|
7220
7436
|
}
|
|
7221
7437
|
const key = Buffer.from(b64Value, "base64");
|
|
7438
|
+
if (!content.startsWith(ENCRYPTED_PREFIX) && isRootOnlyTrustedServerKeyFile(keyPath)) {
|
|
7439
|
+
return key;
|
|
7440
|
+
}
|
|
7222
7441
|
const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
|
|
7223
7442
|
if (migrated) {
|
|
7224
7443
|
process.stderr.write("[keychain] Migrated key from file to native keychain.\n");
|
|
@@ -7246,12 +7465,14 @@ async function getMasterKey() {
|
|
|
7246
7465
|
return null;
|
|
7247
7466
|
}
|
|
7248
7467
|
}
|
|
7249
|
-
var SERVICE, ACCOUNT, ENCRYPTED_PREFIX;
|
|
7468
|
+
var SERVICE, LEGACY_SERVICE, ACCOUNT, linuxSecretAvailability, ENCRYPTED_PREFIX;
|
|
7250
7469
|
var init_keychain = __esm({
|
|
7251
7470
|
"src/lib/keychain.ts"() {
|
|
7252
7471
|
"use strict";
|
|
7253
|
-
SERVICE = "exe-
|
|
7472
|
+
SERVICE = "exe-os";
|
|
7473
|
+
LEGACY_SERVICE = "exe-mem";
|
|
7254
7474
|
ACCOUNT = "master-key";
|
|
7475
|
+
linuxSecretAvailability = null;
|
|
7255
7476
|
ENCRYPTED_PREFIX = "enc:";
|
|
7256
7477
|
}
|
|
7257
7478
|
});
|
|
@@ -7466,7 +7687,7 @@ __export(shard_manager_exports, {
|
|
|
7466
7687
|
shardExists: () => shardExists
|
|
7467
7688
|
});
|
|
7468
7689
|
import path21 from "path";
|
|
7469
|
-
import { existsSync as existsSync17, mkdirSync as mkdirSync8, readdirSync as readdirSync4, renameSync as renameSync4, statSync as
|
|
7690
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync8, readdirSync as readdirSync4, renameSync as renameSync4, statSync as statSync3 } from "fs";
|
|
7470
7691
|
import { createClient as createClient2 } from "@libsql/client";
|
|
7471
7692
|
function initShardManager(encryptionKey) {
|
|
7472
7693
|
_encryptionKey = encryptionKey;
|
|
@@ -7530,7 +7751,7 @@ async function auditShardHealth(options = {}) {
|
|
|
7530
7751
|
const shards = [];
|
|
7531
7752
|
for (const name of names) {
|
|
7532
7753
|
const dbPath = path21.join(SHARDS_DIR, `${name}.db`);
|
|
7533
|
-
const stat =
|
|
7754
|
+
const stat = statSync3(dbPath);
|
|
7534
7755
|
const item = {
|
|
7535
7756
|
name,
|
|
7536
7757
|
path: dbPath,
|
|
@@ -7783,7 +8004,7 @@ async function getReadyShardClient(projectName) {
|
|
|
7783
8004
|
_shardLastAccess.delete(safeName);
|
|
7784
8005
|
const dbPath = path21.join(SHARDS_DIR, `${safeName}.db`);
|
|
7785
8006
|
if (existsSync17(dbPath)) {
|
|
7786
|
-
const stat =
|
|
8007
|
+
const stat = statSync3(dbPath);
|
|
7787
8008
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
7788
8009
|
const archivedPath = path21.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
|
|
7789
8010
|
renameSync4(dbPath, archivedPath);
|
|
@@ -8290,6 +8511,274 @@ var init_memory_cards = __esm({
|
|
|
8290
8511
|
}
|
|
8291
8512
|
});
|
|
8292
8513
|
|
|
8514
|
+
// src/lib/agentic-ontology.ts
|
|
8515
|
+
var agentic_ontology_exports = {};
|
|
8516
|
+
__export(agentic_ontology_exports, {
|
|
8517
|
+
clean: () => clean,
|
|
8518
|
+
extractGoalCandidates: () => extractGoalCandidates,
|
|
8519
|
+
inferIntention: () => inferIntention,
|
|
8520
|
+
inferOntologyEventType: () => inferOntologyEventType,
|
|
8521
|
+
inferOutcome: () => inferOutcome,
|
|
8522
|
+
inferSemanticLabel: () => inferSemanticLabel,
|
|
8523
|
+
insertOntologyForBatch: () => insertOntologyForBatch,
|
|
8524
|
+
insertOntologyForMemory: () => insertOntologyForMemory,
|
|
8525
|
+
ontologyPayload: () => ontologyPayload,
|
|
8526
|
+
stableId: () => stableId2
|
|
8527
|
+
});
|
|
8528
|
+
import { createHash as createHash3 } from "crypto";
|
|
8529
|
+
function stableId2(...parts) {
|
|
8530
|
+
return createHash3("sha256").update(parts.map((p) => String(p ?? "")).join("::")).digest("hex").slice(0, 32);
|
|
8531
|
+
}
|
|
8532
|
+
function clean(text, max = 240) {
|
|
8533
|
+
return text.replace(/\u0000/g, "").replace(/```[\s\S]*?```/g, " ").replace(/\s+/g, " ").trim().slice(0, max);
|
|
8534
|
+
}
|
|
8535
|
+
function inferOntologyEventType(row) {
|
|
8536
|
+
const lower = row.raw_text.toLowerCase();
|
|
8537
|
+
if (row.has_error) return "error";
|
|
8538
|
+
if (/\b(done|complete|completed|fixed|resolved|shipped|deployed|pushed|published)\b/.test(lower)) return "milestone";
|
|
8539
|
+
if (/\b(blocked|failed|error|bug|regression|broken)\b/.test(lower)) return "problem";
|
|
8540
|
+
if (/\b(decided|decision|adr|we chose|approved|rejected)\b/.test(lower)) return "decision";
|
|
8541
|
+
if (/\b(goal|need to|we need|want to|trying to|objective)\b/.test(lower)) return "goal_signal";
|
|
8542
|
+
if (["Bash", "Read", "Edit", "Write", "Grep", "Glob"].includes(row.tool_name)) return "tool_action";
|
|
8543
|
+
if (row.tool_name.startsWith("memory_card")) return "memory_card";
|
|
8544
|
+
return "memory_observation";
|
|
8545
|
+
}
|
|
8546
|
+
function inferIntention(row) {
|
|
8547
|
+
if (row.intent) return clean(row.intent, 220);
|
|
8548
|
+
const text = clean(row.raw_text, 1e3);
|
|
8549
|
+
const patterns = [
|
|
8550
|
+
/(?: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,
|
|
8551
|
+
/(?:so that|in order to)\s+([^.!?\n]{8,220})/i,
|
|
8552
|
+
/(?:task|plan):\s*([^.!?\n]{8,220})/i
|
|
8553
|
+
];
|
|
8554
|
+
for (const p of patterns) {
|
|
8555
|
+
const m = text.match(p);
|
|
8556
|
+
if (m?.[1]) return clean(m[1], 220);
|
|
8557
|
+
}
|
|
8558
|
+
if (["Bash", "Read", "Edit", "Write", "Grep", "Glob"].includes(row.tool_name)) {
|
|
8559
|
+
return `${row.tool_name} during ${row.project_name}`;
|
|
8560
|
+
}
|
|
8561
|
+
return null;
|
|
8562
|
+
}
|
|
8563
|
+
function inferOutcome(row) {
|
|
8564
|
+
if (row.outcome) return clean(row.outcome, 220);
|
|
8565
|
+
if (row.has_error) return "error";
|
|
8566
|
+
const lower = row.raw_text.toLowerCase();
|
|
8567
|
+
if (/\b(done|complete|completed|fixed|resolved|shipped|deployed|pushed|published|passed)\b/.test(lower)) return "success_signal";
|
|
8568
|
+
if (/\b(blocked|failed|error|regression|broken|not working|could not)\b/.test(lower)) return "failure_signal";
|
|
8569
|
+
if (/\b(warning|risk|concern|caveat)\b/.test(lower)) return "risk_signal";
|
|
8570
|
+
return null;
|
|
8571
|
+
}
|
|
8572
|
+
function extractGoalCandidates(row) {
|
|
8573
|
+
const text = clean(row.raw_text, 1600);
|
|
8574
|
+
const patterns = [
|
|
8575
|
+
/(?: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,
|
|
8576
|
+
/(?:success means|success criteria|so that)\s+([^.!?\n]{12,220})/gi
|
|
8577
|
+
];
|
|
8578
|
+
const out = [];
|
|
8579
|
+
for (const pattern of patterns) {
|
|
8580
|
+
for (const m of text.matchAll(pattern)) {
|
|
8581
|
+
const candidate = clean(m[1] ?? "", 220);
|
|
8582
|
+
if (candidate.length >= 12 && !out.some((x) => x.toLowerCase() === candidate.toLowerCase())) out.push(candidate);
|
|
8583
|
+
if (out.length >= 3) return out;
|
|
8584
|
+
}
|
|
8585
|
+
}
|
|
8586
|
+
return out;
|
|
8587
|
+
}
|
|
8588
|
+
function uniq(values, max = 6) {
|
|
8589
|
+
const out = [];
|
|
8590
|
+
for (const value of values.map((v) => clean(v, 220)).filter(Boolean)) {
|
|
8591
|
+
if (!out.some((x) => x.toLowerCase() === value.toLowerCase())) out.push(value);
|
|
8592
|
+
if (out.length >= max) break;
|
|
8593
|
+
}
|
|
8594
|
+
return out;
|
|
8595
|
+
}
|
|
8596
|
+
function extractMatches(text, patterns, max = 5) {
|
|
8597
|
+
const out = [];
|
|
8598
|
+
for (const pattern of patterns) {
|
|
8599
|
+
for (const match of text.matchAll(pattern)) {
|
|
8600
|
+
const value = match[1] ?? match[0];
|
|
8601
|
+
if (value) out.push(value);
|
|
8602
|
+
if (out.length >= max) return uniq(out, max);
|
|
8603
|
+
}
|
|
8604
|
+
}
|
|
8605
|
+
return uniq(out, max);
|
|
8606
|
+
}
|
|
8607
|
+
function inferSemanticLabel(row) {
|
|
8608
|
+
const text = clean(row.raw_text, 2400);
|
|
8609
|
+
const eventType = inferOntologyEventType(row);
|
|
8610
|
+
const intention = inferIntention(row);
|
|
8611
|
+
const outcome = inferOutcome(row);
|
|
8612
|
+
const goals = extractGoalCandidates(row);
|
|
8613
|
+
const milestones = extractMatches(text, [
|
|
8614
|
+
/\b(?:completed|finished|fixed|resolved|shipped|deployed|published|pushed|passed)\b([^.!?\n]{0,180})/gi,
|
|
8615
|
+
/(?:milestone|done):\s*([^.!?\n]{8,220})/gi
|
|
8616
|
+
]);
|
|
8617
|
+
const problems = extractMatches(text, [
|
|
8618
|
+
/\b(?:blocked by|failed because|bug|regression|broken|not working|error)\b([^.!?\n]{0,180})/gi,
|
|
8619
|
+
/(?:problem|issue|risk):\s*([^.!?\n]{8,220})/gi
|
|
8620
|
+
]);
|
|
8621
|
+
const decisions = extractMatches(text, [
|
|
8622
|
+
/(?:decided|decision|adr|we chose|approved|rejected)\s+([^.!?\n]{8,220})/gi
|
|
8623
|
+
]);
|
|
8624
|
+
const temporalAnchors = extractMatches(text, [
|
|
8625
|
+
/\b(\d{4}-\d{2}-\d{2}(?:[T ][0-9:.+-Z]+)?)\b/g,
|
|
8626
|
+
/\b(today|yesterday|tomorrow|this week|next week|last week|morning|afternoon|tonight)\b/gi
|
|
8627
|
+
], 8);
|
|
8628
|
+
const nextActions = extractMatches(text, [
|
|
8629
|
+
/(?:next|todo|follow[- ]?up|remaining|need to)\s*:?\s*([^.!?\n]{8,220})/gi
|
|
8630
|
+
]);
|
|
8631
|
+
const actors = uniq([
|
|
8632
|
+
row.agent_id,
|
|
8633
|
+
...extractMatches(text, [/\b(?:agent|employee|owner|assignee)[:= ]+([a-zA-Z][a-zA-Z0-9_-]{1,40})/gi], 5)
|
|
8634
|
+
], 6);
|
|
8635
|
+
const successSignals = milestones.length ? milestones : outcome === "success_signal" ? [clean(text, 180)] : [];
|
|
8636
|
+
const failureSignals = problems.length ? problems : outcome === "failure_signal" || row.has_error ? [clean(text, 180)] : [];
|
|
8637
|
+
const impact = successSignals.length && failureSignals.length ? "mixed" : failureSignals.length ? "negative" : successSignals.length ? "positive" : "neutral";
|
|
8638
|
+
const signalCount = goals.length + milestones.length + problems.length + decisions.length + nextActions.length;
|
|
8639
|
+
return {
|
|
8640
|
+
labeler: "deterministic",
|
|
8641
|
+
schemaVersion: 1,
|
|
8642
|
+
eventType,
|
|
8643
|
+
intention,
|
|
8644
|
+
outcome,
|
|
8645
|
+
impact,
|
|
8646
|
+
confidence: Math.min(0.95, 0.45 + signalCount * 0.08 + (intention ? 0.1 : 0) + (outcome ? 0.1 : 0)),
|
|
8647
|
+
goals,
|
|
8648
|
+
milestones,
|
|
8649
|
+
problems,
|
|
8650
|
+
decisions,
|
|
8651
|
+
actors,
|
|
8652
|
+
temporalAnchors,
|
|
8653
|
+
successSignals,
|
|
8654
|
+
failureSignals,
|
|
8655
|
+
nextActions,
|
|
8656
|
+
summary: clean(text, 280)
|
|
8657
|
+
};
|
|
8658
|
+
}
|
|
8659
|
+
function ontologyPayload(row) {
|
|
8660
|
+
const semantic = inferSemanticLabel(row);
|
|
8661
|
+
return {
|
|
8662
|
+
tool_name: row.tool_name,
|
|
8663
|
+
memory_version: row.version ?? null,
|
|
8664
|
+
domain: row.domain ?? null,
|
|
8665
|
+
trajectory: row.trajectory ? safeJson(row.trajectory) : null,
|
|
8666
|
+
semantic
|
|
8667
|
+
};
|
|
8668
|
+
}
|
|
8669
|
+
function safeJson(value) {
|
|
8670
|
+
try {
|
|
8671
|
+
return JSON.parse(value);
|
|
8672
|
+
} catch {
|
|
8673
|
+
return value.slice(0, 1e3);
|
|
8674
|
+
}
|
|
8675
|
+
}
|
|
8676
|
+
async function resolveClient(client) {
|
|
8677
|
+
if (client) return client;
|
|
8678
|
+
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
8679
|
+
return getClient2();
|
|
8680
|
+
}
|
|
8681
|
+
async function insertOntologyForMemory(row, client) {
|
|
8682
|
+
const db = await resolveClient(client);
|
|
8683
|
+
const occurredAt = row.timestamp;
|
|
8684
|
+
const sequence = Number(row.version ?? 0) || Math.floor(new Date(occurredAt).getTime() / 1e3);
|
|
8685
|
+
const eventType = inferOntologyEventType(row);
|
|
8686
|
+
const intention = inferIntention(row);
|
|
8687
|
+
const outcome = inferOutcome(row);
|
|
8688
|
+
const eventId = stableId2("event", row.id);
|
|
8689
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
8690
|
+
await db.execute({
|
|
8691
|
+
sql: `INSERT INTO agent_sessions (id, agent_id, project_name, started_at, last_event_at, event_count, properties)
|
|
8692
|
+
VALUES (?, ?, ?, ?, ?, 1, ?)
|
|
8693
|
+
ON CONFLICT(id) DO UPDATE SET last_event_at = MAX(last_event_at, excluded.last_event_at),
|
|
8694
|
+
event_count = event_count + 1`,
|
|
8695
|
+
args: [row.session_id, row.agent_id, row.project_name, occurredAt, occurredAt, JSON.stringify({ agent_role: row.agent_role })]
|
|
8696
|
+
});
|
|
8697
|
+
await db.execute({
|
|
8698
|
+
sql: `INSERT OR IGNORE INTO agent_events
|
|
8699
|
+
(id, event_type, occurred_at, sequence_index, actor_agent_id, agent_role, project_name,
|
|
8700
|
+
session_id, task_id, goal_id, parent_event_id, intention, outcome, evidence_memory_id,
|
|
8701
|
+
impact, payload, created_at)
|
|
8702
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL, ?, ?, ?, ?, ?, ?)`,
|
|
8703
|
+
args: [
|
|
8704
|
+
eventId,
|
|
8705
|
+
eventType,
|
|
8706
|
+
occurredAt,
|
|
8707
|
+
sequence,
|
|
8708
|
+
row.agent_id,
|
|
8709
|
+
row.agent_role,
|
|
8710
|
+
row.project_name,
|
|
8711
|
+
row.session_id,
|
|
8712
|
+
row.task_id ?? null,
|
|
8713
|
+
intention,
|
|
8714
|
+
outcome,
|
|
8715
|
+
row.id,
|
|
8716
|
+
row.has_error ? "negative" : outcome === "success_signal" ? "positive" : "neutral",
|
|
8717
|
+
JSON.stringify(ontologyPayload(row)),
|
|
8718
|
+
now
|
|
8719
|
+
]
|
|
8720
|
+
});
|
|
8721
|
+
const semantic = inferSemanticLabel(row);
|
|
8722
|
+
await db.execute({
|
|
8723
|
+
sql: `INSERT INTO agent_semantic_labels
|
|
8724
|
+
(id, source_memory_id, event_id, labeler, schema_version, confidence, labels, created_at, updated_at)
|
|
8725
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
8726
|
+
ON CONFLICT(id) DO UPDATE SET confidence = excluded.confidence,
|
|
8727
|
+
labels = excluded.labels, updated_at = excluded.updated_at`,
|
|
8728
|
+
args: [
|
|
8729
|
+
stableId2("semantic", row.id, semantic.labeler, semantic.schemaVersion),
|
|
8730
|
+
row.id,
|
|
8731
|
+
eventId,
|
|
8732
|
+
semantic.labeler,
|
|
8733
|
+
semantic.schemaVersion,
|
|
8734
|
+
semantic.confidence,
|
|
8735
|
+
JSON.stringify(semantic),
|
|
8736
|
+
now,
|
|
8737
|
+
now
|
|
8738
|
+
]
|
|
8739
|
+
});
|
|
8740
|
+
for (const statement of extractGoalCandidates(row)) {
|
|
8741
|
+
const goalId = stableId2("goal", row.project_name, statement.toLowerCase());
|
|
8742
|
+
await db.execute({
|
|
8743
|
+
sql: `INSERT INTO agent_goals
|
|
8744
|
+
(id, statement, owner_agent_id, project_name, status, priority, success_criteria,
|
|
8745
|
+
parent_goal_id, due_at, achieved_at, supersedes_id, created_at, updated_at, source_memory_id)
|
|
8746
|
+
VALUES (?, ?, ?, ?, 'open', 5, NULL, NULL, NULL, NULL, NULL, ?, ?, ?)
|
|
8747
|
+
ON CONFLICT(id) DO UPDATE SET updated_at = excluded.updated_at`,
|
|
8748
|
+
args: [goalId, statement, row.agent_id, row.project_name, now, now, row.id]
|
|
8749
|
+
});
|
|
8750
|
+
await db.execute({
|
|
8751
|
+
sql: `INSERT OR IGNORE INTO agent_goal_links
|
|
8752
|
+
(id, goal_id, link_type, target_id, target_type, created_at)
|
|
8753
|
+
VALUES (?, ?, 'evidence', ?, 'memory', ?)`,
|
|
8754
|
+
args: [stableId2("goal_link", goalId, row.id, "memory"), goalId, row.id, now]
|
|
8755
|
+
});
|
|
8756
|
+
await db.execute({
|
|
8757
|
+
sql: `INSERT OR IGNORE INTO agent_goal_links
|
|
8758
|
+
(id, goal_id, link_type, target_id, target_type, created_at)
|
|
8759
|
+
VALUES (?, ?, 'event', ?, 'event', ?)`,
|
|
8760
|
+
args: [stableId2("goal_link", goalId, eventId, "event"), goalId, eventId, now]
|
|
8761
|
+
});
|
|
8762
|
+
}
|
|
8763
|
+
}
|
|
8764
|
+
async function insertOntologyForBatch(rows, client) {
|
|
8765
|
+
const db = await resolveClient(client);
|
|
8766
|
+
let count = 0;
|
|
8767
|
+
for (const row of rows) {
|
|
8768
|
+
try {
|
|
8769
|
+
await insertOntologyForMemory(row, db);
|
|
8770
|
+
count++;
|
|
8771
|
+
} catch {
|
|
8772
|
+
}
|
|
8773
|
+
}
|
|
8774
|
+
return count;
|
|
8775
|
+
}
|
|
8776
|
+
var init_agentic_ontology = __esm({
|
|
8777
|
+
"src/lib/agentic-ontology.ts"() {
|
|
8778
|
+
"use strict";
|
|
8779
|
+
}
|
|
8780
|
+
});
|
|
8781
|
+
|
|
8293
8782
|
// src/lib/store.ts
|
|
8294
8783
|
var store_exports = {};
|
|
8295
8784
|
__export(store_exports, {
|
|
@@ -8633,6 +9122,11 @@ async function flushBatch() {
|
|
|
8633
9122
|
await insertMemoryCardsForBatch2(batch);
|
|
8634
9123
|
} catch {
|
|
8635
9124
|
}
|
|
9125
|
+
try {
|
|
9126
|
+
const { insertOntologyForBatch: insertOntologyForBatch2 } = await Promise.resolve().then(() => (init_agentic_ontology(), agentic_ontology_exports));
|
|
9127
|
+
await insertOntologyForBatch2(batch);
|
|
9128
|
+
} catch {
|
|
9129
|
+
}
|
|
8636
9130
|
schedulePostWriteMemoryHygiene(batch.map((row) => row.id));
|
|
8637
9131
|
_pendingRecords.splice(0, batch.length);
|
|
8638
9132
|
try {
|
|
@@ -9841,6 +10335,7 @@ __export(graph_rag_exports, {
|
|
|
9841
10335
|
extractBatch: () => extractBatch,
|
|
9842
10336
|
extractFromCode: () => extractFromCode,
|
|
9843
10337
|
extractFromMemory: () => extractFromMemory,
|
|
10338
|
+
extractHeuristicMemoryGraph: () => extractHeuristicMemoryGraph,
|
|
9844
10339
|
mergeEntities: () => mergeEntities,
|
|
9845
10340
|
normalizeEntityName: () => normalizeEntityName,
|
|
9846
10341
|
registerAlias: () => registerAlias,
|
|
@@ -9996,6 +10491,57 @@ function extractFromCode(source, filePath) {
|
|
|
9996
10491
|
}
|
|
9997
10492
|
return { entities, relationships, hyperedges: [] };
|
|
9998
10493
|
}
|
|
10494
|
+
function pushUniqueEntity(entities, seen, name, type) {
|
|
10495
|
+
const normalized = normalizeEntityName(name);
|
|
10496
|
+
if (!normalized || normalized.length < 2) return;
|
|
10497
|
+
const key = `${normalized.toLowerCase()}::${type.toLowerCase()}`;
|
|
10498
|
+
if (seen.has(key)) return;
|
|
10499
|
+
seen.add(key);
|
|
10500
|
+
entities.push({ name: normalized.slice(0, 160), type });
|
|
10501
|
+
}
|
|
10502
|
+
function pushHeuristicRelationship(relationships, source, sourceType, target, targetType, relationship, confidence = 0.6) {
|
|
10503
|
+
if (!source || !target || source === target) return;
|
|
10504
|
+
relationships.push({
|
|
10505
|
+
source,
|
|
10506
|
+
sourceType,
|
|
10507
|
+
target,
|
|
10508
|
+
targetType,
|
|
10509
|
+
relationship,
|
|
10510
|
+
confidence,
|
|
10511
|
+
confidenceLabel: "inferred"
|
|
10512
|
+
});
|
|
10513
|
+
}
|
|
10514
|
+
function extractHeuristicMemoryGraph(content, agentId) {
|
|
10515
|
+
const entities = [];
|
|
10516
|
+
const relationships = [];
|
|
10517
|
+
const seen = /* @__PURE__ */ new Set();
|
|
10518
|
+
pushUniqueEntity(entities, seen, agentId, "person");
|
|
10519
|
+
const toolMatch = content.match(/^(Bash|Read|Edit|Write|Grep|Glob|AssistantResponse|Tool|Ran|Wrote|Edited):/m);
|
|
10520
|
+
if (toolMatch?.[1]) {
|
|
10521
|
+
pushUniqueEntity(entities, seen, toolMatch[1], "tool");
|
|
10522
|
+
pushHeuristicRelationship(relationships, agentId, "person", toolMatch[1], "tool", "uses", 0.75);
|
|
10523
|
+
}
|
|
10524
|
+
const repoMatches = [...content.matchAll(/\/Users\/[^/\s]+\/([A-Za-z0-9_.-]+)|\/opt\/([A-Za-z0-9_.-]+)/g)].map((m) => m[1] ?? m[2]).filter((repo) => Boolean(repo)).slice(0, 6);
|
|
10525
|
+
for (const repo of repoMatches) {
|
|
10526
|
+
pushUniqueEntity(entities, seen, repo, "project");
|
|
10527
|
+
pushHeuristicRelationship(relationships, agentId, "person", repo, "project", "worked_on", 0.7);
|
|
10528
|
+
}
|
|
10529
|
+
const pathMatches = new Set(
|
|
10530
|
+
(content.match(/(?:\/[\w .@-]+)+(?:\.[A-Za-z0-9]{1,10})|(?:[\w@.-]+\/)+[\w@.-]+\.(?:ts|tsx|js|jsx|json|md|yml|yaml|sql|py|go|rs|sh|css|html)/g) ?? []).slice(0, 10)
|
|
10531
|
+
);
|
|
10532
|
+
for (const filePath of pathMatches) {
|
|
10533
|
+
pushUniqueEntity(entities, seen, filePath, "file");
|
|
10534
|
+
pushHeuristicRelationship(relationships, agentId, "person", filePath, "file", "uses", 0.65);
|
|
10535
|
+
}
|
|
10536
|
+
const backtickTerms = [...content.matchAll(/`([^`\n]{2,80})`/g)].map((m) => m[1]).slice(0, 10);
|
|
10537
|
+
for (const term of backtickTerms) {
|
|
10538
|
+
if (!term || term.length < 2) continue;
|
|
10539
|
+
const type = term.includes("/") || /\.[A-Za-z0-9]{1,10}$/.test(term) ? "file" : "concept";
|
|
10540
|
+
pushUniqueEntity(entities, seen, term, type);
|
|
10541
|
+
pushHeuristicRelationship(relationships, agentId, "person", term, type, "uses", 0.55);
|
|
10542
|
+
}
|
|
10543
|
+
return { entities, relationships, hyperedges: [] };
|
|
10544
|
+
}
|
|
9999
10545
|
async function extractFromMemory(content, agentId, model = "claude-haiku-4-5-20251001", filePath) {
|
|
10000
10546
|
if (content.length < 50) {
|
|
10001
10547
|
return { entities: [], relationships: [], hyperedges: [] };
|
|
@@ -10051,7 +10597,7 @@ async function extractFromMemory(content, agentId, model = "claude-haiku-4-5-202
|
|
|
10051
10597
|
`
|
|
10052
10598
|
);
|
|
10053
10599
|
}
|
|
10054
|
-
return
|
|
10600
|
+
return extractHeuristicMemoryGraph(content, agentId);
|
|
10055
10601
|
}
|
|
10056
10602
|
async function storeExtraction(client, extraction, memoryId, timestamp) {
|
|
10057
10603
|
let entitiesStored = 0;
|