@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;
|
|
3632
4036
|
var init_runtime_table = __esm({
|
|
@@ -3954,6 +4358,56 @@ var init_preferences = __esm({
|
|
|
3954
4358
|
}
|
|
3955
4359
|
});
|
|
3956
4360
|
|
|
4361
|
+
// src/adapters/mcp-http-config.ts
|
|
4362
|
+
import { chmodSync as chmodSync2, existsSync as existsSync11, mkdirSync as mkdirSync6, readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "fs";
|
|
4363
|
+
import { randomBytes } from "crypto";
|
|
4364
|
+
import path12 from "path";
|
|
4365
|
+
import os9 from "os";
|
|
4366
|
+
function mcpHttpPort() {
|
|
4367
|
+
return process.env.EXE_MCP_PORT || DEFAULT_MCP_HTTP_PORT;
|
|
4368
|
+
}
|
|
4369
|
+
function mcpHttpUrl() {
|
|
4370
|
+
return `http://127.0.0.1:${mcpHttpPort()}/mcp`;
|
|
4371
|
+
}
|
|
4372
|
+
function readOrCreateDaemonToken(homeDir = os9.homedir()) {
|
|
4373
|
+
const exeDir = path12.join(homeDir, ".exe-os");
|
|
4374
|
+
const tokenPath = path12.join(exeDir, "exed.token");
|
|
4375
|
+
if (existsSync11(tokenPath)) {
|
|
4376
|
+
try {
|
|
4377
|
+
const token2 = readFileSync7(tokenPath, "utf-8").trim();
|
|
4378
|
+
if (/^[a-f0-9]{64}$/i.test(token2)) return token2;
|
|
4379
|
+
} catch {
|
|
4380
|
+
}
|
|
4381
|
+
}
|
|
4382
|
+
const token = randomBytes(32).toString("hex");
|
|
4383
|
+
mkdirSync6(exeDir, { recursive: true });
|
|
4384
|
+
writeFileSync6(tokenPath, `${token}
|
|
4385
|
+
`, "utf-8");
|
|
4386
|
+
try {
|
|
4387
|
+
chmodSync2(tokenPath, 384);
|
|
4388
|
+
} catch {
|
|
4389
|
+
}
|
|
4390
|
+
return token;
|
|
4391
|
+
}
|
|
4392
|
+
function buildMcpHttpHeaders(homeDir = os9.homedir(), opts = {}) {
|
|
4393
|
+
const agentId = opts.useShellPlaceholders ? "${AGENT_ID:-exe}" : opts.agentId ?? DEFAULT_MCP_HTTP_AGENT_ID;
|
|
4394
|
+
const agentRole = opts.useShellPlaceholders ? "${AGENT_ROLE:-COO}" : opts.agentRole ?? DEFAULT_MCP_HTTP_AGENT_ROLE;
|
|
4395
|
+
return {
|
|
4396
|
+
Authorization: `Bearer ${readOrCreateDaemonToken(homeDir)}`,
|
|
4397
|
+
"X-Agent-Id": agentId,
|
|
4398
|
+
"X-Agent-Role": agentRole
|
|
4399
|
+
};
|
|
4400
|
+
}
|
|
4401
|
+
var DEFAULT_MCP_HTTP_PORT, DEFAULT_MCP_HTTP_AGENT_ID, DEFAULT_MCP_HTTP_AGENT_ROLE;
|
|
4402
|
+
var init_mcp_http_config = __esm({
|
|
4403
|
+
"src/adapters/mcp-http-config.ts"() {
|
|
4404
|
+
"use strict";
|
|
4405
|
+
DEFAULT_MCP_HTTP_PORT = "48739";
|
|
4406
|
+
DEFAULT_MCP_HTTP_AGENT_ID = "exe";
|
|
4407
|
+
DEFAULT_MCP_HTTP_AGENT_ROLE = "COO";
|
|
4408
|
+
}
|
|
4409
|
+
});
|
|
4410
|
+
|
|
3957
4411
|
// src/adapters/runtime-hook-manifest.ts
|
|
3958
4412
|
function textHasLegacySplitPostToolHook(text) {
|
|
3959
4413
|
return [EXE_HOOK_FILES.ingest, EXE_HOOK_FILES.errorRecall, EXE_HOOK_FILES.ingestWorker].some((file) => text.includes(file));
|
|
@@ -4096,29 +4550,29 @@ var init_runtime_hook_manifest = __esm({
|
|
|
4096
4550
|
});
|
|
4097
4551
|
|
|
4098
4552
|
// src/adapters/claude/installer.ts
|
|
4099
|
-
import { readFile as readFile4, writeFile as writeFile4, mkdir as mkdir4, readdir } from "fs/promises";
|
|
4100
|
-
import { existsSync as
|
|
4101
|
-
import { createHash as
|
|
4102
|
-
import
|
|
4103
|
-
import
|
|
4553
|
+
import { readFile as readFile4, writeFile as writeFile4, mkdir as mkdir4, readdir, rm } from "fs/promises";
|
|
4554
|
+
import { existsSync as existsSync12, readFileSync as readFileSync8, writeFileSync as writeFileSync7, copyFileSync, mkdirSync as mkdirSync7 } from "fs";
|
|
4555
|
+
import { createHash as createHash4 } from "crypto";
|
|
4556
|
+
import path13 from "path";
|
|
4557
|
+
import os10 from "os";
|
|
4104
4558
|
import { execSync as execSync5 } from "child_process";
|
|
4105
4559
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
4106
4560
|
function resolvePackageRoot() {
|
|
4107
4561
|
const thisFile = fileURLToPath2(import.meta.url);
|
|
4108
|
-
let dir =
|
|
4109
|
-
const root =
|
|
4562
|
+
let dir = path13.dirname(thisFile);
|
|
4563
|
+
const root = path13.parse(dir).root;
|
|
4110
4564
|
while (dir !== root) {
|
|
4111
|
-
const pkgPath =
|
|
4112
|
-
if (
|
|
4565
|
+
const pkgPath = path13.join(dir, "package.json");
|
|
4566
|
+
if (existsSync12(pkgPath)) {
|
|
4113
4567
|
try {
|
|
4114
|
-
const pkg = JSON.parse(
|
|
4568
|
+
const pkg = JSON.parse(readFileSync8(pkgPath, "utf-8"));
|
|
4115
4569
|
if (pkg.name === "@askexenow/exe-os" || pkg.name === "exe-os") return dir;
|
|
4116
4570
|
} catch {
|
|
4117
4571
|
}
|
|
4118
4572
|
}
|
|
4119
|
-
dir =
|
|
4573
|
+
dir = path13.dirname(dir);
|
|
4120
4574
|
}
|
|
4121
|
-
return
|
|
4575
|
+
return path13.resolve(path13.dirname(thisFile), "..", "..", "..");
|
|
4122
4576
|
}
|
|
4123
4577
|
var EXE_SECTION_START, EXE_SECTION_END, ORCHESTRATION_RULES;
|
|
4124
4578
|
var init_installer = __esm({
|
|
@@ -4127,6 +4581,7 @@ var init_installer = __esm({
|
|
|
4127
4581
|
init_agent_symlinks();
|
|
4128
4582
|
init_mcp_prefix();
|
|
4129
4583
|
init_preferences();
|
|
4584
|
+
init_mcp_http_config();
|
|
4130
4585
|
init_runtime_hook_manifest();
|
|
4131
4586
|
EXE_SECTION_START = "<!-- exe-os:orchestration-start -->";
|
|
4132
4587
|
EXE_SECTION_END = "<!-- exe-os:orchestration-end -->";
|
|
@@ -4337,15 +4792,16 @@ __export(installer_exports, {
|
|
|
4337
4792
|
verifyOpenCodeHooks: () => verifyOpenCodeHooks
|
|
4338
4793
|
});
|
|
4339
4794
|
import { readFile as readFile5, writeFile as writeFile5, mkdir as mkdir5 } from "fs/promises";
|
|
4340
|
-
import { existsSync as
|
|
4341
|
-
import
|
|
4342
|
-
import
|
|
4343
|
-
async function registerOpenCodeMcp(packageRoot, homeDir =
|
|
4344
|
-
|
|
4345
|
-
const
|
|
4795
|
+
import { existsSync as existsSync13, readFileSync as readFileSync9 } from "fs";
|
|
4796
|
+
import path14 from "path";
|
|
4797
|
+
import os11 from "os";
|
|
4798
|
+
async function registerOpenCodeMcp(packageRoot, homeDir = os11.homedir()) {
|
|
4799
|
+
void packageRoot;
|
|
4800
|
+
const configDir = path14.join(homeDir, ".config", "opencode");
|
|
4801
|
+
const configPath = path14.join(configDir, "opencode.json");
|
|
4346
4802
|
await mkdir5(configDir, { recursive: true });
|
|
4347
4803
|
let config = {};
|
|
4348
|
-
if (
|
|
4804
|
+
if (existsSync13(configPath)) {
|
|
4349
4805
|
try {
|
|
4350
4806
|
config = JSON.parse(await readFile5(configPath, "utf-8"));
|
|
4351
4807
|
} catch {
|
|
@@ -4356,8 +4812,9 @@ async function registerOpenCodeMcp(packageRoot, homeDir = os10.homedir()) {
|
|
|
4356
4812
|
config.mcp = {};
|
|
4357
4813
|
}
|
|
4358
4814
|
const newEntry = {
|
|
4359
|
-
type: "
|
|
4360
|
-
|
|
4815
|
+
type: "remote",
|
|
4816
|
+
url: mcpHttpUrl(),
|
|
4817
|
+
headers: buildMcpHttpHeaders(homeDir),
|
|
4361
4818
|
enabled: true
|
|
4362
4819
|
};
|
|
4363
4820
|
const current = config.mcp["exe-os"];
|
|
@@ -4371,15 +4828,15 @@ async function registerOpenCodeMcp(packageRoot, homeDir = os10.homedir()) {
|
|
|
4371
4828
|
await writeFile5(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
4372
4829
|
return true;
|
|
4373
4830
|
}
|
|
4374
|
-
async function installOpenCodePlugin(packageRoot, homeDir =
|
|
4375
|
-
const pluginDir =
|
|
4376
|
-
const pluginPath =
|
|
4831
|
+
async function installOpenCodePlugin(packageRoot, homeDir = os11.homedir()) {
|
|
4832
|
+
const pluginDir = path14.join(homeDir, ".config", "opencode", "plugins");
|
|
4833
|
+
const pluginPath = path14.join(pluginDir, "exe-os.mjs");
|
|
4377
4834
|
await mkdir5(pluginDir, { recursive: true });
|
|
4378
4835
|
const pluginContent = PLUGIN_TEMPLATE.replace(
|
|
4379
4836
|
/__PACKAGE_ROOT__/g,
|
|
4380
4837
|
packageRoot.replace(/\\/g, "\\\\")
|
|
4381
4838
|
);
|
|
4382
|
-
if (
|
|
4839
|
+
if (existsSync13(pluginPath)) {
|
|
4383
4840
|
const existing = await readFile5(pluginPath, "utf-8");
|
|
4384
4841
|
if (existing === pluginContent) {
|
|
4385
4842
|
return false;
|
|
@@ -4388,19 +4845,19 @@ async function installOpenCodePlugin(packageRoot, homeDir = os10.homedir()) {
|
|
|
4388
4845
|
await writeFile5(pluginPath, pluginContent);
|
|
4389
4846
|
return true;
|
|
4390
4847
|
}
|
|
4391
|
-
function verifyOpenCodeHooks(homeDir =
|
|
4392
|
-
const configPath =
|
|
4393
|
-
const pluginPath =
|
|
4394
|
-
if (!
|
|
4848
|
+
function verifyOpenCodeHooks(homeDir = os11.homedir()) {
|
|
4849
|
+
const configPath = path14.join(homeDir, ".config", "opencode", "opencode.json");
|
|
4850
|
+
const pluginPath = path14.join(homeDir, ".config", "opencode", "plugins", "exe-os.mjs");
|
|
4851
|
+
if (!existsSync13(configPath)) return false;
|
|
4395
4852
|
try {
|
|
4396
|
-
const config = JSON.parse(
|
|
4853
|
+
const config = JSON.parse(readFileSync9(configPath, "utf-8"));
|
|
4397
4854
|
if (!config.mcp?.["exe-os"]?.enabled) return false;
|
|
4398
4855
|
} catch {
|
|
4399
4856
|
return false;
|
|
4400
4857
|
}
|
|
4401
|
-
if (!
|
|
4858
|
+
if (!existsSync13(pluginPath)) return false;
|
|
4402
4859
|
try {
|
|
4403
|
-
const plugin =
|
|
4860
|
+
const plugin = readFileSync9(pluginPath, "utf-8");
|
|
4404
4861
|
if (!plugin.includes(EXE_HOOK_FILES.postToolCombined)) return false;
|
|
4405
4862
|
if (textHasLegacySplitPostToolHook(plugin)) return false;
|
|
4406
4863
|
} catch {
|
|
@@ -4427,17 +4884,18 @@ var init_installer2 = __esm({
|
|
|
4427
4884
|
init_installer();
|
|
4428
4885
|
init_plugin_template();
|
|
4429
4886
|
init_runtime_hook_manifest();
|
|
4887
|
+
init_mcp_http_config();
|
|
4430
4888
|
}
|
|
4431
4889
|
});
|
|
4432
4890
|
|
|
4433
4891
|
// src/bin/exe-start-opencode.ts
|
|
4434
|
-
import
|
|
4435
|
-
import
|
|
4892
|
+
import os12 from "os";
|
|
4893
|
+
import path15 from "path";
|
|
4436
4894
|
import {
|
|
4437
|
-
existsSync as
|
|
4438
|
-
readFileSync as
|
|
4439
|
-
writeFileSync as
|
|
4440
|
-
mkdirSync as
|
|
4895
|
+
existsSync as existsSync14,
|
|
4896
|
+
readFileSync as readFileSync10,
|
|
4897
|
+
writeFileSync as writeFileSync8,
|
|
4898
|
+
mkdirSync as mkdirSync8,
|
|
4441
4899
|
readdirSync as readdirSync4
|
|
4442
4900
|
} from "fs";
|
|
4443
4901
|
import { spawnSync } from "child_process";
|
|
@@ -4448,11 +4906,12 @@ init_database();
|
|
|
4448
4906
|
|
|
4449
4907
|
// src/lib/keychain.ts
|
|
4450
4908
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
4451
|
-
import { existsSync as existsSync6 } from "fs";
|
|
4909
|
+
import { existsSync as existsSync6, statSync as statSync2 } from "fs";
|
|
4452
4910
|
import { execSync as execSync2 } from "child_process";
|
|
4453
4911
|
import path6 from "path";
|
|
4454
4912
|
import os5 from "os";
|
|
4455
|
-
var SERVICE = "exe-
|
|
4913
|
+
var SERVICE = "exe-os";
|
|
4914
|
+
var LEGACY_SERVICE = "exe-mem";
|
|
4456
4915
|
var ACCOUNT = "master-key";
|
|
4457
4916
|
function getKeyDir() {
|
|
4458
4917
|
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path6.join(os5.homedir(), ".exe-os");
|
|
@@ -4460,29 +4919,79 @@ function getKeyDir() {
|
|
|
4460
4919
|
function getKeyPath() {
|
|
4461
4920
|
return path6.join(getKeyDir(), "master.key");
|
|
4462
4921
|
}
|
|
4463
|
-
function
|
|
4922
|
+
function nativeKeychainAllowed() {
|
|
4923
|
+
return process.env.EXE_OS_DISABLE_NATIVE_KEYCHAIN !== "1";
|
|
4924
|
+
}
|
|
4925
|
+
var linuxSecretAvailability = null;
|
|
4926
|
+
function linuxSecretAvailable() {
|
|
4927
|
+
if (!nativeKeychainAllowed()) return false;
|
|
4928
|
+
if (process.platform !== "linux") return false;
|
|
4929
|
+
if (linuxSecretAvailability !== null) return linuxSecretAvailability;
|
|
4930
|
+
try {
|
|
4931
|
+
execSync2("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
|
|
4932
|
+
} catch {
|
|
4933
|
+
linuxSecretAvailability = false;
|
|
4934
|
+
return false;
|
|
4935
|
+
}
|
|
4936
|
+
try {
|
|
4937
|
+
execSync2("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
|
|
4938
|
+
linuxSecretAvailability = true;
|
|
4939
|
+
} catch {
|
|
4940
|
+
linuxSecretAvailability = false;
|
|
4941
|
+
}
|
|
4942
|
+
return linuxSecretAvailability;
|
|
4943
|
+
}
|
|
4944
|
+
function isRootOnlyTrustedServerKeyFile(keyPath) {
|
|
4945
|
+
if (process.platform !== "linux") return false;
|
|
4946
|
+
try {
|
|
4947
|
+
const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
|
|
4948
|
+
const st = statSync2(keyPath);
|
|
4949
|
+
if (!st.isFile() || (st.mode & 63) !== 0) return false;
|
|
4950
|
+
if (uid === 0) return true;
|
|
4951
|
+
const exeOsDir = process.env.EXE_OS_DIR;
|
|
4952
|
+
return Boolean(exeOsDir && path6.resolve(keyPath).startsWith(path6.resolve(exeOsDir) + path6.sep));
|
|
4953
|
+
} catch {
|
|
4954
|
+
return false;
|
|
4955
|
+
}
|
|
4956
|
+
}
|
|
4957
|
+
function macKeychainGet(service = SERVICE) {
|
|
4958
|
+
if (!nativeKeychainAllowed()) return null;
|
|
4464
4959
|
if (process.platform !== "darwin") return null;
|
|
4465
4960
|
try {
|
|
4466
4961
|
return execSync2(
|
|
4467
|
-
`security find-generic-password -s "${
|
|
4962
|
+
`security find-generic-password -s "${service}" -a "${ACCOUNT}" -w 2>/dev/null`,
|
|
4468
4963
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
4469
4964
|
).trim();
|
|
4470
4965
|
} catch {
|
|
4471
4966
|
return null;
|
|
4472
4967
|
}
|
|
4473
4968
|
}
|
|
4474
|
-
function macKeychainSet(value) {
|
|
4969
|
+
function macKeychainSet(value, service = SERVICE) {
|
|
4970
|
+
if (!nativeKeychainAllowed()) return false;
|
|
4475
4971
|
if (process.platform !== "darwin") return false;
|
|
4476
4972
|
try {
|
|
4477
4973
|
try {
|
|
4478
4974
|
execSync2(
|
|
4479
|
-
`security delete-generic-password -s "${
|
|
4975
|
+
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
4480
4976
|
{ timeout: 5e3 }
|
|
4481
4977
|
);
|
|
4482
4978
|
} catch {
|
|
4483
4979
|
}
|
|
4484
4980
|
execSync2(
|
|
4485
|
-
`security add-generic-password -s "${
|
|
4981
|
+
`security add-generic-password -s "${service}" -a "${ACCOUNT}" -w "${value}"`,
|
|
4982
|
+
{ timeout: 5e3 }
|
|
4983
|
+
);
|
|
4984
|
+
return true;
|
|
4985
|
+
} catch {
|
|
4986
|
+
return false;
|
|
4987
|
+
}
|
|
4988
|
+
}
|
|
4989
|
+
function macKeychainDelete(service = SERVICE) {
|
|
4990
|
+
if (!nativeKeychainAllowed()) return false;
|
|
4991
|
+
if (process.platform !== "darwin") return false;
|
|
4992
|
+
try {
|
|
4993
|
+
execSync2(
|
|
4994
|
+
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
4486
4995
|
{ timeout: 5e3 }
|
|
4487
4996
|
);
|
|
4488
4997
|
return true;
|
|
@@ -4490,22 +4999,35 @@ function macKeychainSet(value) {
|
|
|
4490
4999
|
return false;
|
|
4491
5000
|
}
|
|
4492
5001
|
}
|
|
4493
|
-
function linuxSecretGet() {
|
|
4494
|
-
if (
|
|
5002
|
+
function linuxSecretGet(service = SERVICE) {
|
|
5003
|
+
if (!linuxSecretAvailable()) return null;
|
|
4495
5004
|
try {
|
|
4496
5005
|
return execSync2(
|
|
4497
|
-
`secret-tool lookup service "${
|
|
5006
|
+
`secret-tool lookup service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
4498
5007
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
4499
5008
|
).trim();
|
|
4500
5009
|
} catch {
|
|
4501
5010
|
return null;
|
|
4502
5011
|
}
|
|
4503
5012
|
}
|
|
4504
|
-
function linuxSecretSet(value) {
|
|
5013
|
+
function linuxSecretSet(value, service = SERVICE) {
|
|
5014
|
+
if (!linuxSecretAvailable()) return false;
|
|
5015
|
+
try {
|
|
5016
|
+
execSync2(
|
|
5017
|
+
`echo -n "${value}" | secret-tool store --label="exe-os master key" service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
5018
|
+
{ timeout: 5e3 }
|
|
5019
|
+
);
|
|
5020
|
+
return true;
|
|
5021
|
+
} catch {
|
|
5022
|
+
return false;
|
|
5023
|
+
}
|
|
5024
|
+
}
|
|
5025
|
+
function linuxSecretDelete(service = SERVICE) {
|
|
5026
|
+
if (!nativeKeychainAllowed()) return false;
|
|
4505
5027
|
if (process.platform !== "linux") return false;
|
|
4506
5028
|
try {
|
|
4507
5029
|
execSync2(
|
|
4508
|
-
`
|
|
5030
|
+
`secret-tool clear service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
4509
5031
|
{ timeout: 5e3 }
|
|
4510
5032
|
);
|
|
4511
5033
|
return true;
|
|
@@ -4514,6 +5036,7 @@ function linuxSecretSet(value) {
|
|
|
4514
5036
|
}
|
|
4515
5037
|
}
|
|
4516
5038
|
async function tryKeytar() {
|
|
5039
|
+
if (!nativeKeychainAllowed()) return null;
|
|
4517
5040
|
try {
|
|
4518
5041
|
return await import("keytar");
|
|
4519
5042
|
} catch {
|
|
@@ -4539,8 +5062,8 @@ function deriveMachineKey() {
|
|
|
4539
5062
|
}
|
|
4540
5063
|
function readMachineId() {
|
|
4541
5064
|
try {
|
|
4542
|
-
const { readFileSync:
|
|
4543
|
-
return
|
|
5065
|
+
const { readFileSync: readFileSync11 } = __require("fs");
|
|
5066
|
+
return readFileSync11("/etc/machine-id", "utf-8").trim();
|
|
4544
5067
|
} catch {
|
|
4545
5068
|
return "";
|
|
4546
5069
|
}
|
|
@@ -4588,7 +5111,19 @@ async function writeMachineBoundFileFallback(b64) {
|
|
|
4588
5111
|
return "plaintext";
|
|
4589
5112
|
}
|
|
4590
5113
|
async function getMasterKey() {
|
|
4591
|
-
|
|
5114
|
+
let nativeValue = macKeychainGet() ?? linuxSecretGet();
|
|
5115
|
+
if (!nativeValue) {
|
|
5116
|
+
const legacyValue = macKeychainGet(LEGACY_SERVICE) ?? linuxSecretGet(LEGACY_SERVICE);
|
|
5117
|
+
if (legacyValue) {
|
|
5118
|
+
const migrated = macKeychainSet(legacyValue) || linuxSecretSet(legacyValue);
|
|
5119
|
+
if (migrated) {
|
|
5120
|
+
macKeychainDelete(LEGACY_SERVICE);
|
|
5121
|
+
linuxSecretDelete(LEGACY_SERVICE);
|
|
5122
|
+
process.stderr.write("[keychain] Migrated keychain service from exe-mem to exe-os.\n");
|
|
5123
|
+
}
|
|
5124
|
+
nativeValue = legacyValue;
|
|
5125
|
+
}
|
|
5126
|
+
}
|
|
4592
5127
|
if (nativeValue) {
|
|
4593
5128
|
return Buffer.from(nativeValue, "base64");
|
|
4594
5129
|
}
|
|
@@ -4596,12 +5131,17 @@ async function getMasterKey() {
|
|
|
4596
5131
|
if (keytar) {
|
|
4597
5132
|
try {
|
|
4598
5133
|
const keytarValue = await keytar.getPassword(SERVICE, ACCOUNT);
|
|
4599
|
-
|
|
4600
|
-
|
|
5134
|
+
const legacyKeytarValue = keytarValue ?? await keytar.getPassword(LEGACY_SERVICE, ACCOUNT);
|
|
5135
|
+
if (legacyKeytarValue) {
|
|
5136
|
+
const migrated = macKeychainSet(legacyKeytarValue) || linuxSecretSet(legacyKeytarValue);
|
|
4601
5137
|
if (migrated) {
|
|
4602
5138
|
process.stderr.write("[keychain] Migrated key from keytar to native keychain.\n");
|
|
5139
|
+
try {
|
|
5140
|
+
await keytar.deletePassword(LEGACY_SERVICE, ACCOUNT);
|
|
5141
|
+
} catch {
|
|
5142
|
+
}
|
|
4603
5143
|
}
|
|
4604
|
-
return Buffer.from(
|
|
5144
|
+
return Buffer.from(legacyKeytarValue, "base64");
|
|
4605
5145
|
}
|
|
4606
5146
|
} catch {
|
|
4607
5147
|
}
|
|
@@ -4626,7 +5166,7 @@ async function getMasterKey() {
|
|
|
4626
5166
|
const decrypted = decryptWithMachineKey(content, machineKey);
|
|
4627
5167
|
if (!decrypted) {
|
|
4628
5168
|
process.stderr.write(
|
|
4629
|
-
"[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase: exe-os
|
|
5169
|
+
"[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase during setup: exe-os setup\n"
|
|
4630
5170
|
);
|
|
4631
5171
|
return null;
|
|
4632
5172
|
}
|
|
@@ -4635,6 +5175,9 @@ async function getMasterKey() {
|
|
|
4635
5175
|
b64Value = content;
|
|
4636
5176
|
}
|
|
4637
5177
|
const key = Buffer.from(b64Value, "base64");
|
|
5178
|
+
if (!content.startsWith(ENCRYPTED_PREFIX) && isRootOnlyTrustedServerKeyFile(keyPath)) {
|
|
5179
|
+
return key;
|
|
5180
|
+
}
|
|
4638
5181
|
const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
|
|
4639
5182
|
if (migrated) {
|
|
4640
5183
|
process.stderr.write("[keychain] Migrated key from file to native keychain.\n");
|
|
@@ -5001,6 +5544,11 @@ async function flushBatch() {
|
|
|
5001
5544
|
await insertMemoryCardsForBatch2(batch);
|
|
5002
5545
|
} catch {
|
|
5003
5546
|
}
|
|
5547
|
+
try {
|
|
5548
|
+
const { insertOntologyForBatch: insertOntologyForBatch2 } = await Promise.resolve().then(() => (init_agentic_ontology(), agentic_ontology_exports));
|
|
5549
|
+
await insertOntologyForBatch2(batch);
|
|
5550
|
+
} catch {
|
|
5551
|
+
}
|
|
5004
5552
|
schedulePostWriteMemoryHygiene(batch.map((row) => row.id));
|
|
5005
5553
|
_pendingRecords.splice(0, batch.length);
|
|
5006
5554
|
try {
|
|
@@ -5069,7 +5617,7 @@ import {
|
|
|
5069
5617
|
existsSync as existsSync8,
|
|
5070
5618
|
mkdirSync as mkdirSync3,
|
|
5071
5619
|
readdirSync as readdirSync2,
|
|
5072
|
-
statSync as
|
|
5620
|
+
statSync as statSync4,
|
|
5073
5621
|
unlinkSync as unlinkSync3,
|
|
5074
5622
|
writeFileSync as writeFileSync3
|
|
5075
5623
|
} from "fs";
|
|
@@ -5141,7 +5689,7 @@ function sweepStaleBehaviorExports(now = Date.now()) {
|
|
|
5141
5689
|
for (const entry of entries) {
|
|
5142
5690
|
const filePath = path8.join(BEHAVIORS_EXPORT_DIR, entry);
|
|
5143
5691
|
try {
|
|
5144
|
-
const stat =
|
|
5692
|
+
const stat = statSync4(filePath);
|
|
5145
5693
|
if (now - stat.mtimeMs > STALE_EXPORT_AGE_MS) {
|
|
5146
5694
|
unlinkSync3(filePath);
|
|
5147
5695
|
}
|
|
@@ -5204,7 +5752,7 @@ When done with a task: call update_task with status "done".
|
|
|
5204
5752
|
Always call store_memory to persist important findings.
|
|
5205
5753
|
`;
|
|
5206
5754
|
function resolveAgent(argv) {
|
|
5207
|
-
const invokedAs =
|
|
5755
|
+
const invokedAs = path15.basename(argv[1] ?? "");
|
|
5208
5756
|
if (invokedAs && invokedAs !== "exe-start-opencode" && !invokedAs.endsWith(".js")) {
|
|
5209
5757
|
const agent2 = invokedAs.replace(/-opencode$/, "").toLowerCase();
|
|
5210
5758
|
return { agent: agent2, passthrough: argv.slice(2) };
|
|
@@ -5221,24 +5769,24 @@ function resolveAgent(argv) {
|
|
|
5221
5769
|
return { agent, passthrough };
|
|
5222
5770
|
}
|
|
5223
5771
|
function loadIdentity(agent) {
|
|
5224
|
-
const dir =
|
|
5225
|
-
const exact =
|
|
5226
|
-
if (
|
|
5227
|
-
const content =
|
|
5772
|
+
const dir = path15.join(os12.homedir(), ".exe-os", "identity");
|
|
5773
|
+
const exact = path15.join(dir, `${agent}.md`);
|
|
5774
|
+
if (existsSync14(exact)) {
|
|
5775
|
+
const content = readFileSync10(exact, "utf-8").trim();
|
|
5228
5776
|
if (content) return content;
|
|
5229
5777
|
}
|
|
5230
5778
|
try {
|
|
5231
5779
|
const files = readdirSync4(dir);
|
|
5232
5780
|
const match = files.find((f) => f.toLowerCase() === `${agent.toLowerCase()}.md`);
|
|
5233
5781
|
if (match) {
|
|
5234
|
-
const content =
|
|
5782
|
+
const content = readFileSync10(path15.join(dir, match), "utf-8").trim();
|
|
5235
5783
|
if (content) return content;
|
|
5236
5784
|
}
|
|
5237
5785
|
} catch {
|
|
5238
5786
|
}
|
|
5239
5787
|
try {
|
|
5240
|
-
const rosterPath =
|
|
5241
|
-
const roster = JSON.parse(
|
|
5788
|
+
const rosterPath = path15.join(os12.homedir(), ".exe-os", "exe-employees.json");
|
|
5789
|
+
const roster = JSON.parse(readFileSync10(rosterPath, "utf8"));
|
|
5242
5790
|
const emp = roster.find((e) => e.name.toLowerCase() === agent.toLowerCase());
|
|
5243
5791
|
if (emp?.systemPrompt && emp.systemPrompt.trim().length > 20) {
|
|
5244
5792
|
return emp.systemPrompt;
|
|
@@ -5248,18 +5796,18 @@ function loadIdentity(agent) {
|
|
|
5248
5796
|
return null;
|
|
5249
5797
|
}
|
|
5250
5798
|
function writeAgentFile(agent, identity, behaviorsPath) {
|
|
5251
|
-
const agentDir =
|
|
5252
|
-
|
|
5799
|
+
const agentDir = path15.join(os12.homedir(), ".config", "opencode", "agents");
|
|
5800
|
+
mkdirSync8(agentDir, { recursive: true });
|
|
5253
5801
|
let content = identity;
|
|
5254
|
-
if (behaviorsPath &&
|
|
5255
|
-
const behaviors =
|
|
5802
|
+
if (behaviorsPath && existsSync14(behaviorsPath)) {
|
|
5803
|
+
const behaviors = readFileSync10(behaviorsPath, "utf-8").trim();
|
|
5256
5804
|
if (behaviors) {
|
|
5257
5805
|
content += "\n\n" + behaviors;
|
|
5258
5806
|
}
|
|
5259
5807
|
}
|
|
5260
5808
|
content += "\n" + BOOT_INSTRUCTIONS;
|
|
5261
|
-
const outPath =
|
|
5262
|
-
|
|
5809
|
+
const outPath = path15.join(agentDir, `${agent}.md`);
|
|
5810
|
+
writeFileSync8(outPath, content, "utf-8");
|
|
5263
5811
|
return outPath;
|
|
5264
5812
|
}
|
|
5265
5813
|
async function main() {
|
|
@@ -5320,8 +5868,8 @@ async function main() {
|
|
|
5320
5868
|
process.env.EXE_RUNTIME = "opencode";
|
|
5321
5869
|
const empRole = (() => {
|
|
5322
5870
|
try {
|
|
5323
|
-
const emps =
|
|
5324
|
-
|
|
5871
|
+
const emps = readFileSync10(
|
|
5872
|
+
path15.join(os12.homedir(), ".exe-os", "exe-employees.json"),
|
|
5325
5873
|
"utf-8"
|
|
5326
5874
|
);
|
|
5327
5875
|
const found = JSON.parse(emps).find(
|