@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
|
@@ -248,6 +248,10 @@ async function loadConfig() {
|
|
|
248
248
|
if (config.dbPath.startsWith("~")) {
|
|
249
249
|
config.dbPath = config.dbPath.replace(/^~/, os.homedir());
|
|
250
250
|
}
|
|
251
|
+
const envDbPath = path.join(dir, "memories.db");
|
|
252
|
+
if (process.env.EXE_OS_DIR && config.dbPath !== envDbPath && !existsSync2(config.dbPath) && existsSync2(envDbPath)) {
|
|
253
|
+
config.dbPath = envDbPath;
|
|
254
|
+
}
|
|
251
255
|
return config;
|
|
252
256
|
} catch {
|
|
253
257
|
return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
|
|
@@ -268,7 +272,15 @@ function loadConfigSync() {
|
|
|
268
272
|
normalizeSessionLifecycle(migratedCfg);
|
|
269
273
|
normalizeAutoUpdate(migratedCfg);
|
|
270
274
|
normalizeOrchestration(migratedCfg);
|
|
271
|
-
|
|
275
|
+
const config = { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
|
|
276
|
+
if (config.dbPath.startsWith("~")) {
|
|
277
|
+
config.dbPath = config.dbPath.replace(/^~/, os.homedir());
|
|
278
|
+
}
|
|
279
|
+
const envDbPath = path.join(dir, "memories.db");
|
|
280
|
+
if (process.env.EXE_OS_DIR && config.dbPath !== envDbPath && !existsSync2(config.dbPath) && existsSync2(envDbPath)) {
|
|
281
|
+
config.dbPath = envDbPath;
|
|
282
|
+
}
|
|
283
|
+
return config;
|
|
272
284
|
} catch {
|
|
273
285
|
return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
|
|
274
286
|
}
|
|
@@ -1608,6 +1620,9 @@ function getClient() {
|
|
|
1608
1620
|
if (_daemonClient && _daemonClient._isDaemonActive()) {
|
|
1609
1621
|
return _daemonClient;
|
|
1610
1622
|
}
|
|
1623
|
+
if (!_resilientClient) {
|
|
1624
|
+
return _adapterClient;
|
|
1625
|
+
}
|
|
1611
1626
|
return _resilientClient;
|
|
1612
1627
|
}
|
|
1613
1628
|
async function initDaemonClient() {
|
|
@@ -2640,6 +2655,127 @@ async function ensureSchema() {
|
|
|
2640
2655
|
VALUES (new.rowid, new.content, new.subject, new.predicate, new.object);
|
|
2641
2656
|
END;
|
|
2642
2657
|
`);
|
|
2658
|
+
await client.executeMultiple(`
|
|
2659
|
+
CREATE TABLE IF NOT EXISTS agent_sessions (
|
|
2660
|
+
id TEXT PRIMARY KEY,
|
|
2661
|
+
agent_id TEXT NOT NULL,
|
|
2662
|
+
project_name TEXT,
|
|
2663
|
+
started_at TEXT NOT NULL,
|
|
2664
|
+
last_event_at TEXT NOT NULL,
|
|
2665
|
+
event_count INTEGER NOT NULL DEFAULT 0,
|
|
2666
|
+
properties TEXT DEFAULT '{}'
|
|
2667
|
+
);
|
|
2668
|
+
|
|
2669
|
+
CREATE INDEX IF NOT EXISTS idx_agent_sessions_agent_time
|
|
2670
|
+
ON agent_sessions(agent_id, started_at);
|
|
2671
|
+
|
|
2672
|
+
CREATE TABLE IF NOT EXISTS agent_goals (
|
|
2673
|
+
id TEXT PRIMARY KEY,
|
|
2674
|
+
statement TEXT NOT NULL,
|
|
2675
|
+
owner_agent_id TEXT,
|
|
2676
|
+
project_name TEXT,
|
|
2677
|
+
status TEXT NOT NULL DEFAULT 'open',
|
|
2678
|
+
priority INTEGER NOT NULL DEFAULT 5,
|
|
2679
|
+
success_criteria TEXT,
|
|
2680
|
+
parent_goal_id TEXT,
|
|
2681
|
+
due_at TEXT,
|
|
2682
|
+
achieved_at TEXT,
|
|
2683
|
+
supersedes_id TEXT,
|
|
2684
|
+
created_at TEXT NOT NULL,
|
|
2685
|
+
updated_at TEXT NOT NULL,
|
|
2686
|
+
source_memory_id TEXT
|
|
2687
|
+
);
|
|
2688
|
+
|
|
2689
|
+
CREATE INDEX IF NOT EXISTS idx_agent_goals_project_status
|
|
2690
|
+
ON agent_goals(project_name, status, priority);
|
|
2691
|
+
|
|
2692
|
+
CREATE TABLE IF NOT EXISTS agent_events (
|
|
2693
|
+
id TEXT PRIMARY KEY,
|
|
2694
|
+
event_type TEXT NOT NULL,
|
|
2695
|
+
occurred_at TEXT NOT NULL,
|
|
2696
|
+
sequence_index INTEGER NOT NULL,
|
|
2697
|
+
actor_agent_id TEXT,
|
|
2698
|
+
agent_role TEXT,
|
|
2699
|
+
project_name TEXT,
|
|
2700
|
+
session_id TEXT,
|
|
2701
|
+
task_id TEXT,
|
|
2702
|
+
goal_id TEXT,
|
|
2703
|
+
parent_event_id TEXT,
|
|
2704
|
+
intention TEXT,
|
|
2705
|
+
outcome TEXT,
|
|
2706
|
+
evidence_memory_id TEXT,
|
|
2707
|
+
impact TEXT,
|
|
2708
|
+
payload TEXT DEFAULT '{}',
|
|
2709
|
+
created_at TEXT NOT NULL
|
|
2710
|
+
);
|
|
2711
|
+
|
|
2712
|
+
CREATE INDEX IF NOT EXISTS idx_agent_events_time
|
|
2713
|
+
ON agent_events(occurred_at, sequence_index);
|
|
2714
|
+
|
|
2715
|
+
CREATE INDEX IF NOT EXISTS idx_agent_events_session_seq
|
|
2716
|
+
ON agent_events(session_id, sequence_index);
|
|
2717
|
+
|
|
2718
|
+
CREATE INDEX IF NOT EXISTS idx_agent_events_goal_time
|
|
2719
|
+
ON agent_events(goal_id, occurred_at);
|
|
2720
|
+
|
|
2721
|
+
CREATE INDEX IF NOT EXISTS idx_agent_events_memory
|
|
2722
|
+
ON agent_events(evidence_memory_id);
|
|
2723
|
+
|
|
2724
|
+
CREATE TABLE IF NOT EXISTS agent_goal_links (
|
|
2725
|
+
id TEXT PRIMARY KEY,
|
|
2726
|
+
goal_id TEXT NOT NULL,
|
|
2727
|
+
link_type TEXT NOT NULL,
|
|
2728
|
+
target_id TEXT NOT NULL,
|
|
2729
|
+
target_type TEXT NOT NULL,
|
|
2730
|
+
created_at TEXT NOT NULL
|
|
2731
|
+
);
|
|
2732
|
+
|
|
2733
|
+
CREATE INDEX IF NOT EXISTS idx_agent_goal_links_goal
|
|
2734
|
+
ON agent_goal_links(goal_id, target_type);
|
|
2735
|
+
|
|
2736
|
+
CREATE TABLE IF NOT EXISTS agent_semantic_labels (
|
|
2737
|
+
id TEXT PRIMARY KEY,
|
|
2738
|
+
source_memory_id TEXT NOT NULL,
|
|
2739
|
+
event_id TEXT,
|
|
2740
|
+
labeler TEXT NOT NULL,
|
|
2741
|
+
schema_version INTEGER NOT NULL DEFAULT 1,
|
|
2742
|
+
confidence REAL NOT NULL DEFAULT 0,
|
|
2743
|
+
labels TEXT NOT NULL,
|
|
2744
|
+
created_at TEXT NOT NULL,
|
|
2745
|
+
updated_at TEXT NOT NULL
|
|
2746
|
+
);
|
|
2747
|
+
|
|
2748
|
+
CREATE INDEX IF NOT EXISTS idx_agent_semantic_labels_memory
|
|
2749
|
+
ON agent_semantic_labels(source_memory_id, labeler);
|
|
2750
|
+
|
|
2751
|
+
CREATE INDEX IF NOT EXISTS idx_agent_semantic_labels_event
|
|
2752
|
+
ON agent_semantic_labels(event_id);
|
|
2753
|
+
|
|
2754
|
+
CREATE TABLE IF NOT EXISTS agent_reflection_checkpoints (
|
|
2755
|
+
id TEXT PRIMARY KEY,
|
|
2756
|
+
project_name TEXT,
|
|
2757
|
+
session_id TEXT,
|
|
2758
|
+
window_start_at TEXT NOT NULL,
|
|
2759
|
+
window_end_at TEXT NOT NULL,
|
|
2760
|
+
event_count INTEGER NOT NULL DEFAULT 0,
|
|
2761
|
+
goal_count INTEGER NOT NULL DEFAULT 0,
|
|
2762
|
+
success_count INTEGER NOT NULL DEFAULT 0,
|
|
2763
|
+
failure_count INTEGER NOT NULL DEFAULT 0,
|
|
2764
|
+
risk_count INTEGER NOT NULL DEFAULT 0,
|
|
2765
|
+
summary TEXT NOT NULL,
|
|
2766
|
+
learnings TEXT NOT NULL DEFAULT '[]',
|
|
2767
|
+
next_actions TEXT NOT NULL DEFAULT '[]',
|
|
2768
|
+
evidence_event_ids TEXT NOT NULL DEFAULT '[]',
|
|
2769
|
+
confidence REAL NOT NULL DEFAULT 0,
|
|
2770
|
+
created_at TEXT NOT NULL
|
|
2771
|
+
);
|
|
2772
|
+
|
|
2773
|
+
CREATE INDEX IF NOT EXISTS idx_agent_reflection_project_time
|
|
2774
|
+
ON agent_reflection_checkpoints(project_name, window_end_at);
|
|
2775
|
+
|
|
2776
|
+
CREATE INDEX IF NOT EXISTS idx_agent_reflection_session_time
|
|
2777
|
+
ON agent_reflection_checkpoints(session_id, window_end_at);
|
|
2778
|
+
`);
|
|
2643
2779
|
try {
|
|
2644
2780
|
await client.execute({
|
|
2645
2781
|
sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
|
|
@@ -2803,7 +2939,7 @@ __export(shard_manager_exports, {
|
|
|
2803
2939
|
shardExists: () => shardExists
|
|
2804
2940
|
});
|
|
2805
2941
|
import path7 from "path";
|
|
2806
|
-
import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as
|
|
2942
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as statSync3 } from "fs";
|
|
2807
2943
|
import { createClient as createClient2 } from "@libsql/client";
|
|
2808
2944
|
function initShardManager(encryptionKey) {
|
|
2809
2945
|
_encryptionKey = encryptionKey;
|
|
@@ -2867,7 +3003,7 @@ async function auditShardHealth(options = {}) {
|
|
|
2867
3003
|
const shards = [];
|
|
2868
3004
|
for (const name of names) {
|
|
2869
3005
|
const dbPath = path7.join(SHARDS_DIR, `${name}.db`);
|
|
2870
|
-
const stat =
|
|
3006
|
+
const stat = statSync3(dbPath);
|
|
2871
3007
|
const item = {
|
|
2872
3008
|
name,
|
|
2873
3009
|
path: dbPath,
|
|
@@ -3120,7 +3256,7 @@ async function getReadyShardClient(projectName) {
|
|
|
3120
3256
|
_shardLastAccess.delete(safeName);
|
|
3121
3257
|
const dbPath = path7.join(SHARDS_DIR, `${safeName}.db`);
|
|
3122
3258
|
if (existsSync7(dbPath)) {
|
|
3123
|
-
const stat =
|
|
3259
|
+
const stat = statSync3(dbPath);
|
|
3124
3260
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
3125
3261
|
const archivedPath = path7.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
|
|
3126
3262
|
renameSync3(dbPath, archivedPath);
|
|
@@ -3627,6 +3763,274 @@ var init_memory_cards = __esm({
|
|
|
3627
3763
|
}
|
|
3628
3764
|
});
|
|
3629
3765
|
|
|
3766
|
+
// src/lib/agentic-ontology.ts
|
|
3767
|
+
var agentic_ontology_exports = {};
|
|
3768
|
+
__export(agentic_ontology_exports, {
|
|
3769
|
+
clean: () => clean,
|
|
3770
|
+
extractGoalCandidates: () => extractGoalCandidates,
|
|
3771
|
+
inferIntention: () => inferIntention,
|
|
3772
|
+
inferOntologyEventType: () => inferOntologyEventType,
|
|
3773
|
+
inferOutcome: () => inferOutcome,
|
|
3774
|
+
inferSemanticLabel: () => inferSemanticLabel,
|
|
3775
|
+
insertOntologyForBatch: () => insertOntologyForBatch,
|
|
3776
|
+
insertOntologyForMemory: () => insertOntologyForMemory,
|
|
3777
|
+
ontologyPayload: () => ontologyPayload,
|
|
3778
|
+
stableId: () => stableId2
|
|
3779
|
+
});
|
|
3780
|
+
import { createHash as createHash3 } from "crypto";
|
|
3781
|
+
function stableId2(...parts) {
|
|
3782
|
+
return createHash3("sha256").update(parts.map((p) => String(p ?? "")).join("::")).digest("hex").slice(0, 32);
|
|
3783
|
+
}
|
|
3784
|
+
function clean(text, max = 240) {
|
|
3785
|
+
return text.replace(/\u0000/g, "").replace(/```[\s\S]*?```/g, " ").replace(/\s+/g, " ").trim().slice(0, max);
|
|
3786
|
+
}
|
|
3787
|
+
function inferOntologyEventType(row) {
|
|
3788
|
+
const lower = row.raw_text.toLowerCase();
|
|
3789
|
+
if (row.has_error) return "error";
|
|
3790
|
+
if (/\b(done|complete|completed|fixed|resolved|shipped|deployed|pushed|published)\b/.test(lower)) return "milestone";
|
|
3791
|
+
if (/\b(blocked|failed|error|bug|regression|broken)\b/.test(lower)) return "problem";
|
|
3792
|
+
if (/\b(decided|decision|adr|we chose|approved|rejected)\b/.test(lower)) return "decision";
|
|
3793
|
+
if (/\b(goal|need to|we need|want to|trying to|objective)\b/.test(lower)) return "goal_signal";
|
|
3794
|
+
if (["Bash", "Read", "Edit", "Write", "Grep", "Glob"].includes(row.tool_name)) return "tool_action";
|
|
3795
|
+
if (row.tool_name.startsWith("memory_card")) return "memory_card";
|
|
3796
|
+
return "memory_observation";
|
|
3797
|
+
}
|
|
3798
|
+
function inferIntention(row) {
|
|
3799
|
+
if (row.intent) return clean(row.intent, 220);
|
|
3800
|
+
const text = clean(row.raw_text, 1e3);
|
|
3801
|
+
const patterns = [
|
|
3802
|
+
/(?: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,
|
|
3803
|
+
/(?:so that|in order to)\s+([^.!?\n]{8,220})/i,
|
|
3804
|
+
/(?:task|plan):\s*([^.!?\n]{8,220})/i
|
|
3805
|
+
];
|
|
3806
|
+
for (const p of patterns) {
|
|
3807
|
+
const m = text.match(p);
|
|
3808
|
+
if (m?.[1]) return clean(m[1], 220);
|
|
3809
|
+
}
|
|
3810
|
+
if (["Bash", "Read", "Edit", "Write", "Grep", "Glob"].includes(row.tool_name)) {
|
|
3811
|
+
return `${row.tool_name} during ${row.project_name}`;
|
|
3812
|
+
}
|
|
3813
|
+
return null;
|
|
3814
|
+
}
|
|
3815
|
+
function inferOutcome(row) {
|
|
3816
|
+
if (row.outcome) return clean(row.outcome, 220);
|
|
3817
|
+
if (row.has_error) return "error";
|
|
3818
|
+
const lower = row.raw_text.toLowerCase();
|
|
3819
|
+
if (/\b(done|complete|completed|fixed|resolved|shipped|deployed|pushed|published|passed)\b/.test(lower)) return "success_signal";
|
|
3820
|
+
if (/\b(blocked|failed|error|regression|broken|not working|could not)\b/.test(lower)) return "failure_signal";
|
|
3821
|
+
if (/\b(warning|risk|concern|caveat)\b/.test(lower)) return "risk_signal";
|
|
3822
|
+
return null;
|
|
3823
|
+
}
|
|
3824
|
+
function extractGoalCandidates(row) {
|
|
3825
|
+
const text = clean(row.raw_text, 1600);
|
|
3826
|
+
const patterns = [
|
|
3827
|
+
/(?: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,
|
|
3828
|
+
/(?:success means|success criteria|so that)\s+([^.!?\n]{12,220})/gi
|
|
3829
|
+
];
|
|
3830
|
+
const out = [];
|
|
3831
|
+
for (const pattern of patterns) {
|
|
3832
|
+
for (const m of text.matchAll(pattern)) {
|
|
3833
|
+
const candidate = clean(m[1] ?? "", 220);
|
|
3834
|
+
if (candidate.length >= 12 && !out.some((x) => x.toLowerCase() === candidate.toLowerCase())) out.push(candidate);
|
|
3835
|
+
if (out.length >= 3) return out;
|
|
3836
|
+
}
|
|
3837
|
+
}
|
|
3838
|
+
return out;
|
|
3839
|
+
}
|
|
3840
|
+
function uniq(values, max = 6) {
|
|
3841
|
+
const out = [];
|
|
3842
|
+
for (const value of values.map((v) => clean(v, 220)).filter(Boolean)) {
|
|
3843
|
+
if (!out.some((x) => x.toLowerCase() === value.toLowerCase())) out.push(value);
|
|
3844
|
+
if (out.length >= max) break;
|
|
3845
|
+
}
|
|
3846
|
+
return out;
|
|
3847
|
+
}
|
|
3848
|
+
function extractMatches(text, patterns, max = 5) {
|
|
3849
|
+
const out = [];
|
|
3850
|
+
for (const pattern of patterns) {
|
|
3851
|
+
for (const match of text.matchAll(pattern)) {
|
|
3852
|
+
const value = match[1] ?? match[0];
|
|
3853
|
+
if (value) out.push(value);
|
|
3854
|
+
if (out.length >= max) return uniq(out, max);
|
|
3855
|
+
}
|
|
3856
|
+
}
|
|
3857
|
+
return uniq(out, max);
|
|
3858
|
+
}
|
|
3859
|
+
function inferSemanticLabel(row) {
|
|
3860
|
+
const text = clean(row.raw_text, 2400);
|
|
3861
|
+
const eventType = inferOntologyEventType(row);
|
|
3862
|
+
const intention = inferIntention(row);
|
|
3863
|
+
const outcome = inferOutcome(row);
|
|
3864
|
+
const goals = extractGoalCandidates(row);
|
|
3865
|
+
const milestones = extractMatches(text, [
|
|
3866
|
+
/\b(?:completed|finished|fixed|resolved|shipped|deployed|published|pushed|passed)\b([^.!?\n]{0,180})/gi,
|
|
3867
|
+
/(?:milestone|done):\s*([^.!?\n]{8,220})/gi
|
|
3868
|
+
]);
|
|
3869
|
+
const problems = extractMatches(text, [
|
|
3870
|
+
/\b(?:blocked by|failed because|bug|regression|broken|not working|error)\b([^.!?\n]{0,180})/gi,
|
|
3871
|
+
/(?:problem|issue|risk):\s*([^.!?\n]{8,220})/gi
|
|
3872
|
+
]);
|
|
3873
|
+
const decisions = extractMatches(text, [
|
|
3874
|
+
/(?:decided|decision|adr|we chose|approved|rejected)\s+([^.!?\n]{8,220})/gi
|
|
3875
|
+
]);
|
|
3876
|
+
const temporalAnchors = extractMatches(text, [
|
|
3877
|
+
/\b(\d{4}-\d{2}-\d{2}(?:[T ][0-9:.+-Z]+)?)\b/g,
|
|
3878
|
+
/\b(today|yesterday|tomorrow|this week|next week|last week|morning|afternoon|tonight)\b/gi
|
|
3879
|
+
], 8);
|
|
3880
|
+
const nextActions = extractMatches(text, [
|
|
3881
|
+
/(?:next|todo|follow[- ]?up|remaining|need to)\s*:?\s*([^.!?\n]{8,220})/gi
|
|
3882
|
+
]);
|
|
3883
|
+
const actors = uniq([
|
|
3884
|
+
row.agent_id,
|
|
3885
|
+
...extractMatches(text, [/\b(?:agent|employee|owner|assignee)[:= ]+([a-zA-Z][a-zA-Z0-9_-]{1,40})/gi], 5)
|
|
3886
|
+
], 6);
|
|
3887
|
+
const successSignals = milestones.length ? milestones : outcome === "success_signal" ? [clean(text, 180)] : [];
|
|
3888
|
+
const failureSignals = problems.length ? problems : outcome === "failure_signal" || row.has_error ? [clean(text, 180)] : [];
|
|
3889
|
+
const impact = successSignals.length && failureSignals.length ? "mixed" : failureSignals.length ? "negative" : successSignals.length ? "positive" : "neutral";
|
|
3890
|
+
const signalCount = goals.length + milestones.length + problems.length + decisions.length + nextActions.length;
|
|
3891
|
+
return {
|
|
3892
|
+
labeler: "deterministic",
|
|
3893
|
+
schemaVersion: 1,
|
|
3894
|
+
eventType,
|
|
3895
|
+
intention,
|
|
3896
|
+
outcome,
|
|
3897
|
+
impact,
|
|
3898
|
+
confidence: Math.min(0.95, 0.45 + signalCount * 0.08 + (intention ? 0.1 : 0) + (outcome ? 0.1 : 0)),
|
|
3899
|
+
goals,
|
|
3900
|
+
milestones,
|
|
3901
|
+
problems,
|
|
3902
|
+
decisions,
|
|
3903
|
+
actors,
|
|
3904
|
+
temporalAnchors,
|
|
3905
|
+
successSignals,
|
|
3906
|
+
failureSignals,
|
|
3907
|
+
nextActions,
|
|
3908
|
+
summary: clean(text, 280)
|
|
3909
|
+
};
|
|
3910
|
+
}
|
|
3911
|
+
function ontologyPayload(row) {
|
|
3912
|
+
const semantic = inferSemanticLabel(row);
|
|
3913
|
+
return {
|
|
3914
|
+
tool_name: row.tool_name,
|
|
3915
|
+
memory_version: row.version ?? null,
|
|
3916
|
+
domain: row.domain ?? null,
|
|
3917
|
+
trajectory: row.trajectory ? safeJson(row.trajectory) : null,
|
|
3918
|
+
semantic
|
|
3919
|
+
};
|
|
3920
|
+
}
|
|
3921
|
+
function safeJson(value) {
|
|
3922
|
+
try {
|
|
3923
|
+
return JSON.parse(value);
|
|
3924
|
+
} catch {
|
|
3925
|
+
return value.slice(0, 1e3);
|
|
3926
|
+
}
|
|
3927
|
+
}
|
|
3928
|
+
async function resolveClient(client) {
|
|
3929
|
+
if (client) return client;
|
|
3930
|
+
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
3931
|
+
return getClient2();
|
|
3932
|
+
}
|
|
3933
|
+
async function insertOntologyForMemory(row, client) {
|
|
3934
|
+
const db = await resolveClient(client);
|
|
3935
|
+
const occurredAt = row.timestamp;
|
|
3936
|
+
const sequence = Number(row.version ?? 0) || Math.floor(new Date(occurredAt).getTime() / 1e3);
|
|
3937
|
+
const eventType = inferOntologyEventType(row);
|
|
3938
|
+
const intention = inferIntention(row);
|
|
3939
|
+
const outcome = inferOutcome(row);
|
|
3940
|
+
const eventId = stableId2("event", row.id);
|
|
3941
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3942
|
+
await db.execute({
|
|
3943
|
+
sql: `INSERT INTO agent_sessions (id, agent_id, project_name, started_at, last_event_at, event_count, properties)
|
|
3944
|
+
VALUES (?, ?, ?, ?, ?, 1, ?)
|
|
3945
|
+
ON CONFLICT(id) DO UPDATE SET last_event_at = MAX(last_event_at, excluded.last_event_at),
|
|
3946
|
+
event_count = event_count + 1`,
|
|
3947
|
+
args: [row.session_id, row.agent_id, row.project_name, occurredAt, occurredAt, JSON.stringify({ agent_role: row.agent_role })]
|
|
3948
|
+
});
|
|
3949
|
+
await db.execute({
|
|
3950
|
+
sql: `INSERT OR IGNORE INTO agent_events
|
|
3951
|
+
(id, event_type, occurred_at, sequence_index, actor_agent_id, agent_role, project_name,
|
|
3952
|
+
session_id, task_id, goal_id, parent_event_id, intention, outcome, evidence_memory_id,
|
|
3953
|
+
impact, payload, created_at)
|
|
3954
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL, ?, ?, ?, ?, ?, ?)`,
|
|
3955
|
+
args: [
|
|
3956
|
+
eventId,
|
|
3957
|
+
eventType,
|
|
3958
|
+
occurredAt,
|
|
3959
|
+
sequence,
|
|
3960
|
+
row.agent_id,
|
|
3961
|
+
row.agent_role,
|
|
3962
|
+
row.project_name,
|
|
3963
|
+
row.session_id,
|
|
3964
|
+
row.task_id ?? null,
|
|
3965
|
+
intention,
|
|
3966
|
+
outcome,
|
|
3967
|
+
row.id,
|
|
3968
|
+
row.has_error ? "negative" : outcome === "success_signal" ? "positive" : "neutral",
|
|
3969
|
+
JSON.stringify(ontologyPayload(row)),
|
|
3970
|
+
now
|
|
3971
|
+
]
|
|
3972
|
+
});
|
|
3973
|
+
const semantic = inferSemanticLabel(row);
|
|
3974
|
+
await db.execute({
|
|
3975
|
+
sql: `INSERT INTO agent_semantic_labels
|
|
3976
|
+
(id, source_memory_id, event_id, labeler, schema_version, confidence, labels, created_at, updated_at)
|
|
3977
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
3978
|
+
ON CONFLICT(id) DO UPDATE SET confidence = excluded.confidence,
|
|
3979
|
+
labels = excluded.labels, updated_at = excluded.updated_at`,
|
|
3980
|
+
args: [
|
|
3981
|
+
stableId2("semantic", row.id, semantic.labeler, semantic.schemaVersion),
|
|
3982
|
+
row.id,
|
|
3983
|
+
eventId,
|
|
3984
|
+
semantic.labeler,
|
|
3985
|
+
semantic.schemaVersion,
|
|
3986
|
+
semantic.confidence,
|
|
3987
|
+
JSON.stringify(semantic),
|
|
3988
|
+
now,
|
|
3989
|
+
now
|
|
3990
|
+
]
|
|
3991
|
+
});
|
|
3992
|
+
for (const statement of extractGoalCandidates(row)) {
|
|
3993
|
+
const goalId = stableId2("goal", row.project_name, statement.toLowerCase());
|
|
3994
|
+
await db.execute({
|
|
3995
|
+
sql: `INSERT INTO agent_goals
|
|
3996
|
+
(id, statement, owner_agent_id, project_name, status, priority, success_criteria,
|
|
3997
|
+
parent_goal_id, due_at, achieved_at, supersedes_id, created_at, updated_at, source_memory_id)
|
|
3998
|
+
VALUES (?, ?, ?, ?, 'open', 5, NULL, NULL, NULL, NULL, NULL, ?, ?, ?)
|
|
3999
|
+
ON CONFLICT(id) DO UPDATE SET updated_at = excluded.updated_at`,
|
|
4000
|
+
args: [goalId, statement, row.agent_id, row.project_name, now, now, row.id]
|
|
4001
|
+
});
|
|
4002
|
+
await db.execute({
|
|
4003
|
+
sql: `INSERT OR IGNORE INTO agent_goal_links
|
|
4004
|
+
(id, goal_id, link_type, target_id, target_type, created_at)
|
|
4005
|
+
VALUES (?, ?, 'evidence', ?, 'memory', ?)`,
|
|
4006
|
+
args: [stableId2("goal_link", goalId, row.id, "memory"), goalId, row.id, now]
|
|
4007
|
+
});
|
|
4008
|
+
await db.execute({
|
|
4009
|
+
sql: `INSERT OR IGNORE INTO agent_goal_links
|
|
4010
|
+
(id, goal_id, link_type, target_id, target_type, created_at)
|
|
4011
|
+
VALUES (?, ?, 'event', ?, 'event', ?)`,
|
|
4012
|
+
args: [stableId2("goal_link", goalId, eventId, "event"), goalId, eventId, now]
|
|
4013
|
+
});
|
|
4014
|
+
}
|
|
4015
|
+
}
|
|
4016
|
+
async function insertOntologyForBatch(rows, client) {
|
|
4017
|
+
const db = await resolveClient(client);
|
|
4018
|
+
let count = 0;
|
|
4019
|
+
for (const row of rows) {
|
|
4020
|
+
try {
|
|
4021
|
+
await insertOntologyForMemory(row, db);
|
|
4022
|
+
count++;
|
|
4023
|
+
} catch {
|
|
4024
|
+
}
|
|
4025
|
+
}
|
|
4026
|
+
return count;
|
|
4027
|
+
}
|
|
4028
|
+
var init_agentic_ontology = __esm({
|
|
4029
|
+
"src/lib/agentic-ontology.ts"() {
|
|
4030
|
+
"use strict";
|
|
4031
|
+
}
|
|
4032
|
+
});
|
|
4033
|
+
|
|
3630
4034
|
// src/lib/runtime-table.ts
|
|
3631
4035
|
var RUNTIME_TABLE, DEFAULT_RUNTIME;
|
|
3632
4036
|
var init_runtime_table = __esm({
|
|
@@ -3965,6 +4369,56 @@ var init_preferences = __esm({
|
|
|
3965
4369
|
}
|
|
3966
4370
|
});
|
|
3967
4371
|
|
|
4372
|
+
// src/adapters/mcp-http-config.ts
|
|
4373
|
+
import { chmodSync as chmodSync2, existsSync as existsSync11, mkdirSync as mkdirSync6, readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "fs";
|
|
4374
|
+
import { randomBytes } from "crypto";
|
|
4375
|
+
import path12 from "path";
|
|
4376
|
+
import os9 from "os";
|
|
4377
|
+
function mcpHttpPort() {
|
|
4378
|
+
return process.env.EXE_MCP_PORT || DEFAULT_MCP_HTTP_PORT;
|
|
4379
|
+
}
|
|
4380
|
+
function mcpHttpUrl() {
|
|
4381
|
+
return `http://127.0.0.1:${mcpHttpPort()}/mcp`;
|
|
4382
|
+
}
|
|
4383
|
+
function readOrCreateDaemonToken(homeDir = os9.homedir()) {
|
|
4384
|
+
const exeDir = path12.join(homeDir, ".exe-os");
|
|
4385
|
+
const tokenPath = path12.join(exeDir, "exed.token");
|
|
4386
|
+
if (existsSync11(tokenPath)) {
|
|
4387
|
+
try {
|
|
4388
|
+
const token2 = readFileSync7(tokenPath, "utf-8").trim();
|
|
4389
|
+
if (/^[a-f0-9]{64}$/i.test(token2)) return token2;
|
|
4390
|
+
} catch {
|
|
4391
|
+
}
|
|
4392
|
+
}
|
|
4393
|
+
const token = randomBytes(32).toString("hex");
|
|
4394
|
+
mkdirSync6(exeDir, { recursive: true });
|
|
4395
|
+
writeFileSync6(tokenPath, `${token}
|
|
4396
|
+
`, "utf-8");
|
|
4397
|
+
try {
|
|
4398
|
+
chmodSync2(tokenPath, 384);
|
|
4399
|
+
} catch {
|
|
4400
|
+
}
|
|
4401
|
+
return token;
|
|
4402
|
+
}
|
|
4403
|
+
function buildMcpHttpHeaders(homeDir = os9.homedir(), opts = {}) {
|
|
4404
|
+
const agentId = opts.useShellPlaceholders ? "${AGENT_ID:-exe}" : opts.agentId ?? DEFAULT_MCP_HTTP_AGENT_ID;
|
|
4405
|
+
const agentRole = opts.useShellPlaceholders ? "${AGENT_ROLE:-COO}" : opts.agentRole ?? DEFAULT_MCP_HTTP_AGENT_ROLE;
|
|
4406
|
+
return {
|
|
4407
|
+
Authorization: `Bearer ${readOrCreateDaemonToken(homeDir)}`,
|
|
4408
|
+
"X-Agent-Id": agentId,
|
|
4409
|
+
"X-Agent-Role": agentRole
|
|
4410
|
+
};
|
|
4411
|
+
}
|
|
4412
|
+
var DEFAULT_MCP_HTTP_PORT, DEFAULT_MCP_HTTP_AGENT_ID, DEFAULT_MCP_HTTP_AGENT_ROLE;
|
|
4413
|
+
var init_mcp_http_config = __esm({
|
|
4414
|
+
"src/adapters/mcp-http-config.ts"() {
|
|
4415
|
+
"use strict";
|
|
4416
|
+
DEFAULT_MCP_HTTP_PORT = "48739";
|
|
4417
|
+
DEFAULT_MCP_HTTP_AGENT_ID = "exe";
|
|
4418
|
+
DEFAULT_MCP_HTTP_AGENT_ROLE = "COO";
|
|
4419
|
+
}
|
|
4420
|
+
});
|
|
4421
|
+
|
|
3968
4422
|
// src/adapters/runtime-hook-manifest.ts
|
|
3969
4423
|
function commandHasAnyMarker(command, markers) {
|
|
3970
4424
|
return markers.some((marker) => command.includes(marker));
|
|
@@ -4109,29 +4563,29 @@ var init_runtime_hook_manifest = __esm({
|
|
|
4109
4563
|
});
|
|
4110
4564
|
|
|
4111
4565
|
// src/adapters/claude/installer.ts
|
|
4112
|
-
import { readFile as readFile4, writeFile as writeFile4, mkdir as mkdir4, readdir } from "fs/promises";
|
|
4113
|
-
import { existsSync as
|
|
4114
|
-
import { createHash as
|
|
4115
|
-
import
|
|
4116
|
-
import
|
|
4566
|
+
import { readFile as readFile4, writeFile as writeFile4, mkdir as mkdir4, readdir, rm } from "fs/promises";
|
|
4567
|
+
import { existsSync as existsSync12, readFileSync as readFileSync8, writeFileSync as writeFileSync7, copyFileSync, mkdirSync as mkdirSync7 } from "fs";
|
|
4568
|
+
import { createHash as createHash4 } from "crypto";
|
|
4569
|
+
import path13 from "path";
|
|
4570
|
+
import os10 from "os";
|
|
4117
4571
|
import { execSync as execSync5 } from "child_process";
|
|
4118
4572
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
4119
4573
|
function resolvePackageRoot() {
|
|
4120
4574
|
const thisFile = fileURLToPath2(import.meta.url);
|
|
4121
|
-
let dir =
|
|
4122
|
-
const root =
|
|
4575
|
+
let dir = path13.dirname(thisFile);
|
|
4576
|
+
const root = path13.parse(dir).root;
|
|
4123
4577
|
while (dir !== root) {
|
|
4124
|
-
const pkgPath =
|
|
4125
|
-
if (
|
|
4578
|
+
const pkgPath = path13.join(dir, "package.json");
|
|
4579
|
+
if (existsSync12(pkgPath)) {
|
|
4126
4580
|
try {
|
|
4127
|
-
const pkg = JSON.parse(
|
|
4581
|
+
const pkg = JSON.parse(readFileSync8(pkgPath, "utf-8"));
|
|
4128
4582
|
if (pkg.name === "@askexenow/exe-os" || pkg.name === "exe-os") return dir;
|
|
4129
4583
|
} catch {
|
|
4130
4584
|
}
|
|
4131
4585
|
}
|
|
4132
|
-
dir =
|
|
4586
|
+
dir = path13.dirname(dir);
|
|
4133
4587
|
}
|
|
4134
|
-
return
|
|
4588
|
+
return path13.resolve(path13.dirname(thisFile), "..", "..", "..");
|
|
4135
4589
|
}
|
|
4136
4590
|
var EXE_SECTION_START, EXE_SECTION_END, ORCHESTRATION_RULES;
|
|
4137
4591
|
var init_installer = __esm({
|
|
@@ -4140,6 +4594,7 @@ var init_installer = __esm({
|
|
|
4140
4594
|
init_agent_symlinks();
|
|
4141
4595
|
init_mcp_prefix();
|
|
4142
4596
|
init_preferences();
|
|
4597
|
+
init_mcp_http_config();
|
|
4143
4598
|
init_runtime_hook_manifest();
|
|
4144
4599
|
EXE_SECTION_START = "<!-- exe-os:orchestration-start -->";
|
|
4145
4600
|
EXE_SECTION_END = "<!-- exe-os:orchestration-end -->";
|
|
@@ -4168,19 +4623,19 @@ __export(installer_exports, {
|
|
|
4168
4623
|
verifyCodexHooks: () => verifyCodexHooks
|
|
4169
4624
|
});
|
|
4170
4625
|
import { readFile as readFile5, writeFile as writeFile5, mkdir as mkdir5 } from "fs/promises";
|
|
4171
|
-
import { existsSync as
|
|
4172
|
-
import
|
|
4173
|
-
import
|
|
4174
|
-
async function mergeCodexHooks(packageRoot, homeDir =
|
|
4175
|
-
const codexDir =
|
|
4176
|
-
const hooksPath =
|
|
4177
|
-
const logsDir =
|
|
4178
|
-
const hookLogPath =
|
|
4626
|
+
import { existsSync as existsSync13, readFileSync as readFileSync9 } from "fs";
|
|
4627
|
+
import path14 from "path";
|
|
4628
|
+
import os11 from "os";
|
|
4629
|
+
async function mergeCodexHooks(packageRoot, homeDir = os11.homedir()) {
|
|
4630
|
+
const codexDir = path14.join(homeDir, ".codex");
|
|
4631
|
+
const hooksPath = path14.join(codexDir, "hooks.json");
|
|
4632
|
+
const logsDir = path14.join(homeDir, ".exe-os", "logs");
|
|
4633
|
+
const hookLogPath = path14.join(logsDir, "hooks.log");
|
|
4179
4634
|
const logSuffix = ` 2>> "${hookLogPath}"`;
|
|
4180
4635
|
await mkdir5(codexDir, { recursive: true });
|
|
4181
4636
|
await mkdir5(logsDir, { recursive: true });
|
|
4182
4637
|
let hooksJson = {};
|
|
4183
|
-
if (
|
|
4638
|
+
if (existsSync13(hooksPath)) {
|
|
4184
4639
|
try {
|
|
4185
4640
|
hooksJson = JSON.parse(await readFile5(hooksPath, "utf-8"));
|
|
4186
4641
|
} catch {
|
|
@@ -4191,19 +4646,6 @@ async function mergeCodexHooks(packageRoot, homeDir = os10.homedir()) {
|
|
|
4191
4646
|
hooksJson.hooks = {};
|
|
4192
4647
|
}
|
|
4193
4648
|
const hooksToRegister = [
|
|
4194
|
-
{
|
|
4195
|
-
event: "SessionStart",
|
|
4196
|
-
group: {
|
|
4197
|
-
hooks: [
|
|
4198
|
-
{
|
|
4199
|
-
type: "command",
|
|
4200
|
-
command: `node "${path13.join(packageRoot, "dist", "hooks", "session-start.js")}"${logSuffix}`,
|
|
4201
|
-
timeout: 30
|
|
4202
|
-
}
|
|
4203
|
-
]
|
|
4204
|
-
},
|
|
4205
|
-
marker: EXE_HOOKS.sessionStart
|
|
4206
|
-
},
|
|
4207
4649
|
{
|
|
4208
4650
|
event: "PostToolUse",
|
|
4209
4651
|
group: {
|
|
@@ -4213,7 +4655,7 @@ async function mergeCodexHooks(packageRoot, homeDir = os10.homedir()) {
|
|
|
4213
4655
|
// Combined hook: runs ingest + error-recall in one Node process.
|
|
4214
4656
|
// Eliminates a cold-start cycle per tool call (~3-6s savings on Codex).
|
|
4215
4657
|
type: "command",
|
|
4216
|
-
command: `node "${
|
|
4658
|
+
command: `node "${path14.join(packageRoot, "dist", "hooks", "post-tool-combined.js")}"${logSuffix}`
|
|
4217
4659
|
}
|
|
4218
4660
|
]
|
|
4219
4661
|
},
|
|
@@ -4227,7 +4669,7 @@ async function mergeCodexHooks(packageRoot, homeDir = os10.homedir()) {
|
|
|
4227
4669
|
// Single hook: prompt-submit handles memory retrieval + entity boost.
|
|
4228
4670
|
// exe-heartbeat-hook is CC-specific (intercom) — omitted on Codex.
|
|
4229
4671
|
type: "command",
|
|
4230
|
-
command: `node "${
|
|
4672
|
+
command: `node "${path14.join(packageRoot, "dist", "hooks", "prompt-submit.js")}"${logSuffix}`
|
|
4231
4673
|
}
|
|
4232
4674
|
]
|
|
4233
4675
|
},
|
|
@@ -4239,7 +4681,7 @@ async function mergeCodexHooks(packageRoot, homeDir = os10.homedir()) {
|
|
|
4239
4681
|
hooks: [
|
|
4240
4682
|
{
|
|
4241
4683
|
type: "command",
|
|
4242
|
-
command: `node "${
|
|
4684
|
+
command: `node "${path14.join(packageRoot, "dist", "hooks", "stop.js")}"${logSuffix}`
|
|
4243
4685
|
}
|
|
4244
4686
|
]
|
|
4245
4687
|
},
|
|
@@ -4252,7 +4694,7 @@ async function mergeCodexHooks(packageRoot, homeDir = os10.homedir()) {
|
|
|
4252
4694
|
hooks: [
|
|
4253
4695
|
{
|
|
4254
4696
|
type: "command",
|
|
4255
|
-
command: `node "${
|
|
4697
|
+
command: `node "${path14.join(packageRoot, "dist", "hooks", "pre-tool-use.js")}"${logSuffix}`
|
|
4256
4698
|
}
|
|
4257
4699
|
]
|
|
4258
4700
|
},
|
|
@@ -4261,6 +4703,16 @@ async function mergeCodexHooks(packageRoot, homeDir = os10.homedir()) {
|
|
|
4261
4703
|
];
|
|
4262
4704
|
let added = 0;
|
|
4263
4705
|
let skipped = 0;
|
|
4706
|
+
const sessionStartGroups = hooksJson.hooks["SessionStart"];
|
|
4707
|
+
if (Array.isArray(sessionStartGroups)) {
|
|
4708
|
+
hooksJson.hooks["SessionStart"] = sessionStartGroups.map((g) => ({
|
|
4709
|
+
...g,
|
|
4710
|
+
hooks: g.hooks.filter((h) => !h.command.includes(EXE_HOOKS.sessionStart))
|
|
4711
|
+
})).filter((g) => g.hooks.length > 0);
|
|
4712
|
+
if (hooksJson.hooks["SessionStart"].length === 0) {
|
|
4713
|
+
delete hooksJson.hooks["SessionStart"];
|
|
4714
|
+
}
|
|
4715
|
+
}
|
|
4264
4716
|
const postToolGroups = hooksJson.hooks["PostToolUse"];
|
|
4265
4717
|
if (Array.isArray(postToolGroups)) {
|
|
4266
4718
|
hooksJson.hooks["PostToolUse"] = postToolGroups.map((g) => ({
|
|
@@ -4290,15 +4742,13 @@ async function mergeCodexHooks(packageRoot, homeDir = os10.homedir()) {
|
|
|
4290
4742
|
await writeFile5(hooksPath, JSON.stringify(hooksJson, null, 2) + "\n");
|
|
4291
4743
|
return { added, skipped };
|
|
4292
4744
|
}
|
|
4293
|
-
function verifyCodexHooks(homeDir =
|
|
4294
|
-
const hooksPath =
|
|
4295
|
-
if (!
|
|
4745
|
+
function verifyCodexHooks(homeDir = os11.homedir()) {
|
|
4746
|
+
const hooksPath = path14.join(homeDir, ".codex", "hooks.json");
|
|
4747
|
+
if (!existsSync13(hooksPath)) return false;
|
|
4296
4748
|
try {
|
|
4297
|
-
const hooksJson = JSON.parse(
|
|
4298
|
-
__require("fs").readFileSync(hooksPath, "utf-8")
|
|
4299
|
-
);
|
|
4749
|
+
const hooksJson = JSON.parse(readFileSync9(hooksPath, "utf-8"));
|
|
4300
4750
|
if (!hooksJson.hooks) return false;
|
|
4301
|
-
const required = ["
|
|
4751
|
+
const required = ["PostToolUse", "UserPromptSubmit", "Stop", "PreToolUse"];
|
|
4302
4752
|
for (const event of required) {
|
|
4303
4753
|
const groups = hooksJson.hooks[event];
|
|
4304
4754
|
if (!groups || !groups.some(
|
|
@@ -4316,19 +4766,23 @@ function verifyCodexHooks(homeDir = os10.homedir()) {
|
|
|
4316
4766
|
)) {
|
|
4317
4767
|
return false;
|
|
4318
4768
|
}
|
|
4769
|
+
const sessionStartCommands = (hooksJson.hooks.SessionStart ?? []).flatMap((g) => g.hooks.map((h) => h.command));
|
|
4770
|
+
if (sessionStartCommands.some((cmd) => cmd.includes(EXE_HOOKS.sessionStart))) {
|
|
4771
|
+
return false;
|
|
4772
|
+
}
|
|
4319
4773
|
return true;
|
|
4320
4774
|
} catch {
|
|
4321
4775
|
return false;
|
|
4322
4776
|
}
|
|
4323
4777
|
}
|
|
4324
|
-
async function installCodexStatusLine(homeDir =
|
|
4778
|
+
async function installCodexStatusLine(homeDir = os11.homedir()) {
|
|
4325
4779
|
const prefs = loadPreferences(homeDir);
|
|
4326
4780
|
if (prefs.codexStatusLine === false) return "opted-out";
|
|
4327
|
-
const codexDir =
|
|
4328
|
-
const configPath =
|
|
4781
|
+
const codexDir = path14.join(homeDir, ".codex");
|
|
4782
|
+
const configPath = path14.join(codexDir, "config.toml");
|
|
4329
4783
|
await mkdir5(codexDir, { recursive: true });
|
|
4330
4784
|
let content = "";
|
|
4331
|
-
if (
|
|
4785
|
+
if (existsSync13(configPath)) {
|
|
4332
4786
|
content = await readFile5(configPath, "utf-8");
|
|
4333
4787
|
if (/\[tui\][\s\S]*?status_line\s*=/.test(content)) {
|
|
4334
4788
|
return "already-configured";
|
|
@@ -4345,53 +4799,47 @@ status_line = [${DEFAULT_CODEX_STATUS_LINE.map((s) => `"${s}"`).join(", ")}]`;
|
|
|
4345
4799
|
await writeFile5(configPath, content);
|
|
4346
4800
|
return "installed";
|
|
4347
4801
|
}
|
|
4348
|
-
function
|
|
4802
|
+
function tomlString(value) {
|
|
4803
|
+
return JSON.stringify(value);
|
|
4804
|
+
}
|
|
4805
|
+
function codexHttpHeadersToml(homeDir) {
|
|
4806
|
+
const headers = buildMcpHttpHeaders(homeDir);
|
|
4807
|
+
return `{ ${Object.entries(headers).map(([key, value]) => `${tomlString(key)} = ${tomlString(value)}`).join(", ")} }`;
|
|
4808
|
+
}
|
|
4809
|
+
function desiredCodexMcpSection(homeDir) {
|
|
4349
4810
|
return [
|
|
4350
4811
|
"[mcp_servers.exe-os]",
|
|
4351
|
-
`
|
|
4352
|
-
`
|
|
4812
|
+
`url = ${tomlString(mcpHttpUrl())}`,
|
|
4813
|
+
`http_headers = ${codexHttpHeadersToml(homeDir)}`,
|
|
4353
4814
|
`startup_timeout_sec = ${CODEX_EXE_MCP_STARTUP_TIMEOUT_SEC}`,
|
|
4354
4815
|
`tool_timeout_sec = ${CODEX_EXE_MCP_TOOL_TIMEOUT_SEC}`,
|
|
4355
4816
|
""
|
|
4356
4817
|
].join("\n");
|
|
4357
4818
|
}
|
|
4358
|
-
function reconcileCodexMcpSection(sectionContent,
|
|
4819
|
+
function reconcileCodexMcpSection(sectionContent, homeDir) {
|
|
4359
4820
|
const desiredLines = {
|
|
4360
|
-
|
|
4361
|
-
|
|
4821
|
+
url: `url = ${tomlString(mcpHttpUrl())}`,
|
|
4822
|
+
headers: `http_headers = ${codexHttpHeadersToml(homeDir)}`,
|
|
4362
4823
|
startup: `startup_timeout_sec = ${CODEX_EXE_MCP_STARTUP_TIMEOUT_SEC}`,
|
|
4363
4824
|
tool: `tool_timeout_sec = ${CODEX_EXE_MCP_TOOL_TIMEOUT_SEC}`
|
|
4364
4825
|
};
|
|
4365
4826
|
let next = sectionContent;
|
|
4366
|
-
|
|
4367
|
-
const
|
|
4368
|
-
|
|
4369
|
-
const updated = next.replace(regex, desired);
|
|
4370
|
-
if (updated !== next) {
|
|
4371
|
-
next = updated;
|
|
4372
|
-
changed = true;
|
|
4373
|
-
}
|
|
4374
|
-
return;
|
|
4375
|
-
}
|
|
4376
|
-
next = next.endsWith("\n") ? `${next}${desired}
|
|
4827
|
+
next = next.split("\n").filter((line) => !/^(command|args|env|type|url|http_headers|startup_timeout_sec|tool_timeout_sec)\s*=/.test(line.trim())).join("\n").replace(/\n{3,}/g, "\n\n");
|
|
4828
|
+
for (const line of [desiredLines.url, desiredLines.headers, desiredLines.startup, desiredLines.tool]) {
|
|
4829
|
+
next = next.endsWith("\n") ? `${next}${line}
|
|
4377
4830
|
` : `${next}
|
|
4378
|
-
${
|
|
4831
|
+
${line}
|
|
4379
4832
|
`;
|
|
4380
|
-
|
|
4381
|
-
};
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
}
|
|
4388
|
-
async function registerCodexMcpServer(packageRoot, homeDir = os10.homedir()) {
|
|
4389
|
-
const codexDir = path13.join(homeDir, ".codex");
|
|
4390
|
-
const configPath = path13.join(codexDir, "config.toml");
|
|
4391
|
-
const serverJsPath = path13.join(packageRoot, "dist", "mcp", "server.js");
|
|
4833
|
+
}
|
|
4834
|
+
return { content: next, changed: next !== sectionContent };
|
|
4835
|
+
}
|
|
4836
|
+
async function registerCodexMcpServer(packageRoot, homeDir = os11.homedir()) {
|
|
4837
|
+
const codexDir = path14.join(homeDir, ".codex");
|
|
4838
|
+
const configPath = path14.join(codexDir, "config.toml");
|
|
4839
|
+
void packageRoot;
|
|
4392
4840
|
await mkdir5(codexDir, { recursive: true });
|
|
4393
4841
|
let content = "";
|
|
4394
|
-
if (
|
|
4842
|
+
if (existsSync13(configPath)) {
|
|
4395
4843
|
content = await readFile5(configPath, "utf-8");
|
|
4396
4844
|
}
|
|
4397
4845
|
const sectionHeader = "[mcp_servers.exe-os]";
|
|
@@ -4401,7 +4849,7 @@ async function registerCodexMcpServer(packageRoot, homeDir = os10.homedir()) {
|
|
|
4401
4849
|
const nextSectionMatch = afterHeader.match(/\n\[(?!mcp_servers\.exe-os)/);
|
|
4402
4850
|
const sectionEnd = nextSectionMatch ? headerIndex + sectionHeader.length + nextSectionMatch.index : content.length;
|
|
4403
4851
|
const sectionContent = content.slice(headerIndex, sectionEnd);
|
|
4404
|
-
const reconciled = reconcileCodexMcpSection(sectionContent,
|
|
4852
|
+
const reconciled = reconcileCodexMcpSection(sectionContent, homeDir);
|
|
4405
4853
|
if (!reconciled.changed) {
|
|
4406
4854
|
return "already-registered";
|
|
4407
4855
|
}
|
|
@@ -4409,17 +4857,17 @@ async function registerCodexMcpServer(packageRoot, homeDir = os10.homedir()) {
|
|
|
4409
4857
|
await writeFile5(configPath, content);
|
|
4410
4858
|
return "updated";
|
|
4411
4859
|
}
|
|
4412
|
-
const newSection = desiredCodexMcpSection(
|
|
4860
|
+
const newSection = desiredCodexMcpSection(homeDir);
|
|
4413
4861
|
const separator = content.length > 0 && !content.endsWith("\n") ? "\n\n" : content.length > 0 ? "\n" : "";
|
|
4414
4862
|
content = content + separator + newSection;
|
|
4415
4863
|
await writeFile5(configPath, content);
|
|
4416
4864
|
return "registered";
|
|
4417
4865
|
}
|
|
4418
|
-
async function ensureCodexHooksFeature(homeDir =
|
|
4419
|
-
const configPath =
|
|
4420
|
-
await mkdir5(
|
|
4866
|
+
async function ensureCodexHooksFeature(homeDir = os11.homedir()) {
|
|
4867
|
+
const configPath = path14.join(homeDir, ".codex", "config.toml");
|
|
4868
|
+
await mkdir5(path14.join(homeDir, ".codex"), { recursive: true });
|
|
4421
4869
|
let content = "";
|
|
4422
|
-
if (
|
|
4870
|
+
if (existsSync13(configPath)) {
|
|
4423
4871
|
content = await readFile5(configPath, "utf-8");
|
|
4424
4872
|
}
|
|
4425
4873
|
if (/\[features\][\s\S]*?codex_hooks\s*=\s*true/.test(content)) {
|
|
@@ -4474,6 +4922,7 @@ var init_installer2 = __esm({
|
|
|
4474
4922
|
init_installer();
|
|
4475
4923
|
init_preferences();
|
|
4476
4924
|
init_runtime_hook_manifest();
|
|
4925
|
+
init_mcp_http_config();
|
|
4477
4926
|
DEFAULT_CODEX_STATUS_LINE = [
|
|
4478
4927
|
"model-with-reasoning",
|
|
4479
4928
|
"current-dir",
|
|
@@ -4500,20 +4949,20 @@ __export(agent_config_exports, {
|
|
|
4500
4949
|
saveAgentConfig: () => saveAgentConfig,
|
|
4501
4950
|
setAgentRuntime: () => setAgentRuntime
|
|
4502
4951
|
});
|
|
4503
|
-
import { readFileSync as
|
|
4504
|
-
import
|
|
4952
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync8, existsSync as existsSync14 } from "fs";
|
|
4953
|
+
import path15 from "path";
|
|
4505
4954
|
function loadAgentConfig() {
|
|
4506
|
-
if (!
|
|
4955
|
+
if (!existsSync14(AGENT_CONFIG_PATH)) return {};
|
|
4507
4956
|
try {
|
|
4508
|
-
return JSON.parse(
|
|
4957
|
+
return JSON.parse(readFileSync10(AGENT_CONFIG_PATH, "utf-8"));
|
|
4509
4958
|
} catch {
|
|
4510
4959
|
return {};
|
|
4511
4960
|
}
|
|
4512
4961
|
}
|
|
4513
4962
|
function saveAgentConfig(config) {
|
|
4514
|
-
const dir =
|
|
4963
|
+
const dir = path15.dirname(AGENT_CONFIG_PATH);
|
|
4515
4964
|
ensurePrivateDirSync(dir);
|
|
4516
|
-
|
|
4965
|
+
writeFileSync8(AGENT_CONFIG_PATH, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
4517
4966
|
enforcePrivateFileSync(AGENT_CONFIG_PATH);
|
|
4518
4967
|
}
|
|
4519
4968
|
function getAgentRuntime(agentId) {
|
|
@@ -4557,7 +5006,7 @@ var init_agent_config = __esm({
|
|
|
4557
5006
|
init_config();
|
|
4558
5007
|
init_runtime_table();
|
|
4559
5008
|
init_secure_files();
|
|
4560
|
-
AGENT_CONFIG_PATH =
|
|
5009
|
+
AGENT_CONFIG_PATH = path15.join(EXE_AI_DIR, "agent-config.json");
|
|
4561
5010
|
KNOWN_RUNTIMES = {
|
|
4562
5011
|
claude: ["claude-opus-4.6", "claude-opus-4", "claude-sonnet-4.6", "claude-sonnet-4", "claude-haiku-4.5"],
|
|
4563
5012
|
codex: ["gpt-5.4", "gpt-5.5", "gpt-5.3-codex-spark", "o3", "o4-mini"],
|
|
@@ -4577,13 +5026,13 @@ var init_agent_config = __esm({
|
|
|
4577
5026
|
});
|
|
4578
5027
|
|
|
4579
5028
|
// src/bin/exe-start-codex.ts
|
|
4580
|
-
import
|
|
4581
|
-
import
|
|
5029
|
+
import os12 from "os";
|
|
5030
|
+
import path16 from "path";
|
|
4582
5031
|
import {
|
|
4583
|
-
existsSync as
|
|
4584
|
-
readFileSync as
|
|
4585
|
-
writeFileSync as
|
|
4586
|
-
mkdirSync as
|
|
5032
|
+
existsSync as existsSync15,
|
|
5033
|
+
readFileSync as readFileSync11,
|
|
5034
|
+
writeFileSync as writeFileSync9,
|
|
5035
|
+
mkdirSync as mkdirSync8,
|
|
4587
5036
|
readdirSync as readdirSync4
|
|
4588
5037
|
} from "fs";
|
|
4589
5038
|
import { spawnSync } from "child_process";
|
|
@@ -4594,11 +5043,12 @@ init_database();
|
|
|
4594
5043
|
|
|
4595
5044
|
// src/lib/keychain.ts
|
|
4596
5045
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
4597
|
-
import { existsSync as existsSync6 } from "fs";
|
|
5046
|
+
import { existsSync as existsSync6, statSync as statSync2 } from "fs";
|
|
4598
5047
|
import { execSync as execSync2 } from "child_process";
|
|
4599
5048
|
import path6 from "path";
|
|
4600
5049
|
import os5 from "os";
|
|
4601
|
-
var SERVICE = "exe-
|
|
5050
|
+
var SERVICE = "exe-os";
|
|
5051
|
+
var LEGACY_SERVICE = "exe-mem";
|
|
4602
5052
|
var ACCOUNT = "master-key";
|
|
4603
5053
|
function getKeyDir() {
|
|
4604
5054
|
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path6.join(os5.homedir(), ".exe-os");
|
|
@@ -4606,29 +5056,66 @@ function getKeyDir() {
|
|
|
4606
5056
|
function getKeyPath() {
|
|
4607
5057
|
return path6.join(getKeyDir(), "master.key");
|
|
4608
5058
|
}
|
|
4609
|
-
function
|
|
5059
|
+
function nativeKeychainAllowed() {
|
|
5060
|
+
return process.env.EXE_OS_DISABLE_NATIVE_KEYCHAIN !== "1";
|
|
5061
|
+
}
|
|
5062
|
+
var linuxSecretAvailability = null;
|
|
5063
|
+
function linuxSecretAvailable() {
|
|
5064
|
+
if (!nativeKeychainAllowed()) return false;
|
|
5065
|
+
if (process.platform !== "linux") return false;
|
|
5066
|
+
if (linuxSecretAvailability !== null) return linuxSecretAvailability;
|
|
5067
|
+
try {
|
|
5068
|
+
execSync2("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
|
|
5069
|
+
} catch {
|
|
5070
|
+
linuxSecretAvailability = false;
|
|
5071
|
+
return false;
|
|
5072
|
+
}
|
|
5073
|
+
try {
|
|
5074
|
+
execSync2("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
|
|
5075
|
+
linuxSecretAvailability = true;
|
|
5076
|
+
} catch {
|
|
5077
|
+
linuxSecretAvailability = false;
|
|
5078
|
+
}
|
|
5079
|
+
return linuxSecretAvailability;
|
|
5080
|
+
}
|
|
5081
|
+
function isRootOnlyTrustedServerKeyFile(keyPath) {
|
|
5082
|
+
if (process.platform !== "linux") return false;
|
|
5083
|
+
try {
|
|
5084
|
+
const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
|
|
5085
|
+
const st = statSync2(keyPath);
|
|
5086
|
+
if (!st.isFile() || (st.mode & 63) !== 0) return false;
|
|
5087
|
+
if (uid === 0) return true;
|
|
5088
|
+
const exeOsDir = process.env.EXE_OS_DIR;
|
|
5089
|
+
return Boolean(exeOsDir && path6.resolve(keyPath).startsWith(path6.resolve(exeOsDir) + path6.sep));
|
|
5090
|
+
} catch {
|
|
5091
|
+
return false;
|
|
5092
|
+
}
|
|
5093
|
+
}
|
|
5094
|
+
function macKeychainGet(service = SERVICE) {
|
|
5095
|
+
if (!nativeKeychainAllowed()) return null;
|
|
4610
5096
|
if (process.platform !== "darwin") return null;
|
|
4611
5097
|
try {
|
|
4612
5098
|
return execSync2(
|
|
4613
|
-
`security find-generic-password -s "${
|
|
5099
|
+
`security find-generic-password -s "${service}" -a "${ACCOUNT}" -w 2>/dev/null`,
|
|
4614
5100
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
4615
5101
|
).trim();
|
|
4616
5102
|
} catch {
|
|
4617
5103
|
return null;
|
|
4618
5104
|
}
|
|
4619
5105
|
}
|
|
4620
|
-
function macKeychainSet(value) {
|
|
5106
|
+
function macKeychainSet(value, service = SERVICE) {
|
|
5107
|
+
if (!nativeKeychainAllowed()) return false;
|
|
4621
5108
|
if (process.platform !== "darwin") return false;
|
|
4622
5109
|
try {
|
|
4623
5110
|
try {
|
|
4624
5111
|
execSync2(
|
|
4625
|
-
`security delete-generic-password -s "${
|
|
5112
|
+
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
4626
5113
|
{ timeout: 5e3 }
|
|
4627
5114
|
);
|
|
4628
5115
|
} catch {
|
|
4629
5116
|
}
|
|
4630
5117
|
execSync2(
|
|
4631
|
-
`security add-generic-password -s "${
|
|
5118
|
+
`security add-generic-password -s "${service}" -a "${ACCOUNT}" -w "${value}"`,
|
|
4632
5119
|
{ timeout: 5e3 }
|
|
4633
5120
|
);
|
|
4634
5121
|
return true;
|
|
@@ -4636,22 +5123,48 @@ function macKeychainSet(value) {
|
|
|
4636
5123
|
return false;
|
|
4637
5124
|
}
|
|
4638
5125
|
}
|
|
4639
|
-
function
|
|
4640
|
-
if (
|
|
5126
|
+
function macKeychainDelete(service = SERVICE) {
|
|
5127
|
+
if (!nativeKeychainAllowed()) return false;
|
|
5128
|
+
if (process.platform !== "darwin") return false;
|
|
5129
|
+
try {
|
|
5130
|
+
execSync2(
|
|
5131
|
+
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
5132
|
+
{ timeout: 5e3 }
|
|
5133
|
+
);
|
|
5134
|
+
return true;
|
|
5135
|
+
} catch {
|
|
5136
|
+
return false;
|
|
5137
|
+
}
|
|
5138
|
+
}
|
|
5139
|
+
function linuxSecretGet(service = SERVICE) {
|
|
5140
|
+
if (!linuxSecretAvailable()) return null;
|
|
4641
5141
|
try {
|
|
4642
5142
|
return execSync2(
|
|
4643
|
-
`secret-tool lookup service "${
|
|
5143
|
+
`secret-tool lookup service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
4644
5144
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
4645
5145
|
).trim();
|
|
4646
5146
|
} catch {
|
|
4647
5147
|
return null;
|
|
4648
5148
|
}
|
|
4649
5149
|
}
|
|
4650
|
-
function linuxSecretSet(value) {
|
|
5150
|
+
function linuxSecretSet(value, service = SERVICE) {
|
|
5151
|
+
if (!linuxSecretAvailable()) return false;
|
|
5152
|
+
try {
|
|
5153
|
+
execSync2(
|
|
5154
|
+
`echo -n "${value}" | secret-tool store --label="exe-os master key" service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
5155
|
+
{ timeout: 5e3 }
|
|
5156
|
+
);
|
|
5157
|
+
return true;
|
|
5158
|
+
} catch {
|
|
5159
|
+
return false;
|
|
5160
|
+
}
|
|
5161
|
+
}
|
|
5162
|
+
function linuxSecretDelete(service = SERVICE) {
|
|
5163
|
+
if (!nativeKeychainAllowed()) return false;
|
|
4651
5164
|
if (process.platform !== "linux") return false;
|
|
4652
5165
|
try {
|
|
4653
5166
|
execSync2(
|
|
4654
|
-
`
|
|
5167
|
+
`secret-tool clear service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
4655
5168
|
{ timeout: 5e3 }
|
|
4656
5169
|
);
|
|
4657
5170
|
return true;
|
|
@@ -4660,6 +5173,7 @@ function linuxSecretSet(value) {
|
|
|
4660
5173
|
}
|
|
4661
5174
|
}
|
|
4662
5175
|
async function tryKeytar() {
|
|
5176
|
+
if (!nativeKeychainAllowed()) return null;
|
|
4663
5177
|
try {
|
|
4664
5178
|
return await import("keytar");
|
|
4665
5179
|
} catch {
|
|
@@ -4685,8 +5199,8 @@ function deriveMachineKey() {
|
|
|
4685
5199
|
}
|
|
4686
5200
|
function readMachineId() {
|
|
4687
5201
|
try {
|
|
4688
|
-
const { readFileSync:
|
|
4689
|
-
return
|
|
5202
|
+
const { readFileSync: readFileSync12 } = __require("fs");
|
|
5203
|
+
return readFileSync12("/etc/machine-id", "utf-8").trim();
|
|
4690
5204
|
} catch {
|
|
4691
5205
|
return "";
|
|
4692
5206
|
}
|
|
@@ -4734,7 +5248,19 @@ async function writeMachineBoundFileFallback(b64) {
|
|
|
4734
5248
|
return "plaintext";
|
|
4735
5249
|
}
|
|
4736
5250
|
async function getMasterKey() {
|
|
4737
|
-
|
|
5251
|
+
let nativeValue = macKeychainGet() ?? linuxSecretGet();
|
|
5252
|
+
if (!nativeValue) {
|
|
5253
|
+
const legacyValue = macKeychainGet(LEGACY_SERVICE) ?? linuxSecretGet(LEGACY_SERVICE);
|
|
5254
|
+
if (legacyValue) {
|
|
5255
|
+
const migrated = macKeychainSet(legacyValue) || linuxSecretSet(legacyValue);
|
|
5256
|
+
if (migrated) {
|
|
5257
|
+
macKeychainDelete(LEGACY_SERVICE);
|
|
5258
|
+
linuxSecretDelete(LEGACY_SERVICE);
|
|
5259
|
+
process.stderr.write("[keychain] Migrated keychain service from exe-mem to exe-os.\n");
|
|
5260
|
+
}
|
|
5261
|
+
nativeValue = legacyValue;
|
|
5262
|
+
}
|
|
5263
|
+
}
|
|
4738
5264
|
if (nativeValue) {
|
|
4739
5265
|
return Buffer.from(nativeValue, "base64");
|
|
4740
5266
|
}
|
|
@@ -4742,12 +5268,17 @@ async function getMasterKey() {
|
|
|
4742
5268
|
if (keytar) {
|
|
4743
5269
|
try {
|
|
4744
5270
|
const keytarValue = await keytar.getPassword(SERVICE, ACCOUNT);
|
|
4745
|
-
|
|
4746
|
-
|
|
5271
|
+
const legacyKeytarValue = keytarValue ?? await keytar.getPassword(LEGACY_SERVICE, ACCOUNT);
|
|
5272
|
+
if (legacyKeytarValue) {
|
|
5273
|
+
const migrated = macKeychainSet(legacyKeytarValue) || linuxSecretSet(legacyKeytarValue);
|
|
4747
5274
|
if (migrated) {
|
|
4748
5275
|
process.stderr.write("[keychain] Migrated key from keytar to native keychain.\n");
|
|
5276
|
+
try {
|
|
5277
|
+
await keytar.deletePassword(LEGACY_SERVICE, ACCOUNT);
|
|
5278
|
+
} catch {
|
|
5279
|
+
}
|
|
4749
5280
|
}
|
|
4750
|
-
return Buffer.from(
|
|
5281
|
+
return Buffer.from(legacyKeytarValue, "base64");
|
|
4751
5282
|
}
|
|
4752
5283
|
} catch {
|
|
4753
5284
|
}
|
|
@@ -4772,7 +5303,7 @@ async function getMasterKey() {
|
|
|
4772
5303
|
const decrypted = decryptWithMachineKey(content, machineKey);
|
|
4773
5304
|
if (!decrypted) {
|
|
4774
5305
|
process.stderr.write(
|
|
4775
|
-
"[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase: exe-os
|
|
5306
|
+
"[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase during setup: exe-os setup\n"
|
|
4776
5307
|
);
|
|
4777
5308
|
return null;
|
|
4778
5309
|
}
|
|
@@ -4781,6 +5312,9 @@ async function getMasterKey() {
|
|
|
4781
5312
|
b64Value = content;
|
|
4782
5313
|
}
|
|
4783
5314
|
const key = Buffer.from(b64Value, "base64");
|
|
5315
|
+
if (!content.startsWith(ENCRYPTED_PREFIX) && isRootOnlyTrustedServerKeyFile(keyPath)) {
|
|
5316
|
+
return key;
|
|
5317
|
+
}
|
|
4784
5318
|
const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
|
|
4785
5319
|
if (migrated) {
|
|
4786
5320
|
process.stderr.write("[keychain] Migrated key from file to native keychain.\n");
|
|
@@ -5147,6 +5681,11 @@ async function flushBatch() {
|
|
|
5147
5681
|
await insertMemoryCardsForBatch2(batch);
|
|
5148
5682
|
} catch {
|
|
5149
5683
|
}
|
|
5684
|
+
try {
|
|
5685
|
+
const { insertOntologyForBatch: insertOntologyForBatch2 } = await Promise.resolve().then(() => (init_agentic_ontology(), agentic_ontology_exports));
|
|
5686
|
+
await insertOntologyForBatch2(batch);
|
|
5687
|
+
} catch {
|
|
5688
|
+
}
|
|
5150
5689
|
schedulePostWriteMemoryHygiene(batch.map((row) => row.id));
|
|
5151
5690
|
_pendingRecords.splice(0, batch.length);
|
|
5152
5691
|
try {
|
|
@@ -5215,7 +5754,7 @@ import {
|
|
|
5215
5754
|
existsSync as existsSync8,
|
|
5216
5755
|
mkdirSync as mkdirSync3,
|
|
5217
5756
|
readdirSync as readdirSync2,
|
|
5218
|
-
statSync as
|
|
5757
|
+
statSync as statSync4,
|
|
5219
5758
|
unlinkSync as unlinkSync3,
|
|
5220
5759
|
writeFileSync as writeFileSync3
|
|
5221
5760
|
} from "fs";
|
|
@@ -5287,7 +5826,7 @@ function sweepStaleBehaviorExports(now = Date.now()) {
|
|
|
5287
5826
|
for (const entry of entries) {
|
|
5288
5827
|
const filePath = path8.join(BEHAVIORS_EXPORT_DIR, entry);
|
|
5289
5828
|
try {
|
|
5290
|
-
const stat =
|
|
5829
|
+
const stat = statSync4(filePath);
|
|
5291
5830
|
if (now - stat.mtimeMs > STALE_EXPORT_AGE_MS) {
|
|
5292
5831
|
unlinkSync3(filePath);
|
|
5293
5832
|
}
|
|
@@ -5365,7 +5904,7 @@ When done with a task: call update_task with status "done" and a result summary.
|
|
|
5365
5904
|
Always call store_memory to persist important decisions.
|
|
5366
5905
|
`;
|
|
5367
5906
|
function resolveAgent(argv) {
|
|
5368
|
-
const invokedAs =
|
|
5907
|
+
const invokedAs = path16.basename(argv[1] ?? "");
|
|
5369
5908
|
if (invokedAs && invokedAs !== "exe-start-codex" && !invokedAs.endsWith(".js")) {
|
|
5370
5909
|
const agent2 = invokedAs.replace(/-codex$/, "").toLowerCase();
|
|
5371
5910
|
return { agent: agent2, passthrough: argv.slice(2) };
|
|
@@ -5391,24 +5930,24 @@ function resolveAgent(argv) {
|
|
|
5391
5930
|
return { agent, passthrough, sessionName };
|
|
5392
5931
|
}
|
|
5393
5932
|
function loadIdentity(agent) {
|
|
5394
|
-
const dir =
|
|
5395
|
-
const exact =
|
|
5396
|
-
if (
|
|
5397
|
-
const content =
|
|
5933
|
+
const dir = path16.join(os12.homedir(), ".exe-os", "identity");
|
|
5934
|
+
const exact = path16.join(dir, `${agent}.md`);
|
|
5935
|
+
if (existsSync15(exact)) {
|
|
5936
|
+
const content = readFileSync11(exact, "utf-8").trim();
|
|
5398
5937
|
if (content) return content;
|
|
5399
5938
|
}
|
|
5400
5939
|
try {
|
|
5401
5940
|
const files = readdirSync4(dir);
|
|
5402
5941
|
const match = files.find((f) => f.toLowerCase() === `${agent.toLowerCase()}.md`);
|
|
5403
5942
|
if (match) {
|
|
5404
|
-
const content =
|
|
5943
|
+
const content = readFileSync11(path16.join(dir, match), "utf-8").trim();
|
|
5405
5944
|
if (content) return content;
|
|
5406
5945
|
}
|
|
5407
5946
|
} catch {
|
|
5408
5947
|
}
|
|
5409
5948
|
try {
|
|
5410
|
-
const rosterPath =
|
|
5411
|
-
const roster = JSON.parse(
|
|
5949
|
+
const rosterPath = path16.join(os12.homedir(), ".exe-os", "exe-employees.json");
|
|
5950
|
+
const roster = JSON.parse(readFileSync11(rosterPath, "utf8"));
|
|
5412
5951
|
const emp = roster.find((e) => e.name.toLowerCase() === agent.toLowerCase());
|
|
5413
5952
|
if (emp?.systemPrompt && emp.systemPrompt.trim().length > 20) {
|
|
5414
5953
|
return emp.systemPrompt;
|
|
@@ -5418,22 +5957,22 @@ function loadIdentity(agent) {
|
|
|
5418
5957
|
return null;
|
|
5419
5958
|
}
|
|
5420
5959
|
function writePromptFile(agent, identity, behaviorsPath, globalProcedures) {
|
|
5421
|
-
const promptDir =
|
|
5422
|
-
|
|
5960
|
+
const promptDir = path16.join(os12.homedir(), ".exe-os", "codex-prompt");
|
|
5961
|
+
mkdirSync8(promptDir, { recursive: true });
|
|
5423
5962
|
let prompt = "";
|
|
5424
5963
|
if (globalProcedures) {
|
|
5425
5964
|
prompt += globalProcedures + "\n\n";
|
|
5426
5965
|
}
|
|
5427
5966
|
prompt += identity;
|
|
5428
|
-
if (behaviorsPath &&
|
|
5429
|
-
const behaviors =
|
|
5967
|
+
if (behaviorsPath && existsSync15(behaviorsPath)) {
|
|
5968
|
+
const behaviors = readFileSync11(behaviorsPath, "utf-8").trim();
|
|
5430
5969
|
if (behaviors) {
|
|
5431
5970
|
prompt += "\n\n" + behaviors;
|
|
5432
5971
|
}
|
|
5433
5972
|
}
|
|
5434
5973
|
prompt += "\n" + BOOT_INSTRUCTIONS;
|
|
5435
|
-
const outPath =
|
|
5436
|
-
|
|
5974
|
+
const outPath = path16.join(promptDir, `${agent}.md`);
|
|
5975
|
+
writeFileSync9(outPath, prompt, "utf-8");
|
|
5437
5976
|
return outPath;
|
|
5438
5977
|
}
|
|
5439
5978
|
async function main() {
|
|
@@ -5524,8 +6063,8 @@ async function main() {
|
|
|
5524
6063
|
process.env.EXE_RUNTIME = "codex";
|
|
5525
6064
|
const empRole = (() => {
|
|
5526
6065
|
try {
|
|
5527
|
-
const emps =
|
|
5528
|
-
|
|
6066
|
+
const emps = readFileSync11(
|
|
6067
|
+
path16.join(os12.homedir(), ".exe-os", "exe-employees.json"),
|
|
5529
6068
|
"utf-8"
|
|
5530
6069
|
);
|
|
5531
6070
|
const found = JSON.parse(emps).find(
|
|
@@ -5562,14 +6101,14 @@ async function main() {
|
|
|
5562
6101
|
if (WORKTREE_ROLES.has(empRole)) {
|
|
5563
6102
|
try {
|
|
5564
6103
|
const { execSync: es } = await import("child_process");
|
|
5565
|
-
const worktreeDir =
|
|
6104
|
+
const worktreeDir = path16.join(process.cwd(), ".worktrees", worktreeName);
|
|
5566
6105
|
const branchName = `${worktreeName}/codex-${Date.now()}`;
|
|
5567
|
-
if (
|
|
6106
|
+
if (existsSync15(worktreeDir)) {
|
|
5568
6107
|
worktreePath = worktreeDir;
|
|
5569
6108
|
process.stderr.write(`[exe-start-codex] Reusing worktree at ${worktreeDir}
|
|
5570
6109
|
`);
|
|
5571
6110
|
} else {
|
|
5572
|
-
|
|
6111
|
+
mkdirSync8(path16.dirname(worktreeDir), { recursive: true });
|
|
5573
6112
|
es(`git worktree add "${worktreeDir}" -b "${branchName}" HEAD`, {
|
|
5574
6113
|
encoding: "utf-8",
|
|
5575
6114
|
timeout: 3e4
|