@askexenow/exe-os 0.9.65 → 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} +1532 -2173
- package/dist/bin/backfill-conversations.js +528 -20
- package/dist/bin/backfill-responses.js +528 -20
- package/dist/bin/backfill-vectors.js +255 -20
- package/dist/bin/bulk-sync-postgres.js +4876 -0
- package/dist/bin/cleanup-stale-review-tasks.js +529 -21
- package/dist/bin/cli.js +3471 -1491
- package/dist/bin/exe-agent-config.js +4 -0
- package/dist/bin/exe-agent.js +16 -0
- package/dist/bin/exe-assign.js +528 -20
- package/dist/bin/exe-boot.js +492 -54
- package/dist/bin/exe-call.js +16 -0
- package/dist/bin/exe-cloud.js +7415 -518
- package/dist/bin/exe-dispatch.js +540 -22
- package/dist/bin/exe-doctor.js +3404 -1225
- package/dist/bin/exe-export-behaviors.js +542 -24
- package/dist/bin/exe-forget.js +529 -21
- package/dist/bin/exe-gateway.js +595 -25
- package/dist/bin/exe-heartbeat.js +541 -24
- package/dist/bin/exe-kill.js +529 -21
- package/dist/bin/exe-launch-agent.js +2334 -1067
- package/dist/bin/exe-new-employee.js +324 -166
- package/dist/bin/exe-pending-messages.js +529 -21
- package/dist/bin/exe-pending-notifications.js +529 -21
- package/dist/bin/exe-pending-reviews.js +529 -21
- package/dist/bin/exe-rename.js +529 -21
- package/dist/bin/exe-review.js +529 -21
- package/dist/bin/exe-search.js +542 -24
- package/dist/bin/exe-session-cleanup.js +540 -22
- package/dist/bin/exe-settings.js +14 -0
- package/dist/bin/exe-start-codex.js +817 -144
- package/dist/bin/exe-start-opencode.js +776 -80
- package/dist/bin/exe-status.js +529 -21
- package/dist/bin/exe-team.js +529 -21
- package/dist/bin/git-sweep.js +540 -22
- package/dist/bin/graph-backfill.js +580 -21
- package/dist/bin/graph-export.js +529 -21
- package/dist/bin/graph-layer-benchmark.js +109 -0
- package/dist/bin/install.js +420 -289
- package/dist/bin/intercom-check.js +540 -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 +540 -22
- package/dist/bin/setup.js +790 -206
- package/dist/bin/shard-migrate.js +528 -20
- package/dist/bin/update.js +4 -0
- package/dist/gateway/index.js +593 -23
- package/dist/hooks/bug-report-worker.js +651 -64
- package/dist/hooks/codex-stop-task-finalizer.js +540 -22
- package/dist/hooks/commit-complete.js +540 -22
- package/dist/hooks/error-recall.js +542 -24
- package/dist/hooks/exe-heartbeat-hook.js +4 -0
- package/dist/hooks/ingest-worker.js +4 -0
- package/dist/hooks/ingest.js +539 -22
- package/dist/hooks/instructions-loaded.js +529 -21
- package/dist/hooks/notification.js +529 -21
- package/dist/hooks/post-compact.js +529 -21
- package/dist/hooks/post-tool-combined.js +543 -25
- package/dist/hooks/pre-compact.js +772 -127
- package/dist/hooks/pre-tool-use.js +529 -21
- package/dist/hooks/prompt-submit.js +543 -25
- package/dist/hooks/session-end.js +673 -140
- package/dist/hooks/session-start.js +662 -26
- package/dist/hooks/stop.js +540 -23
- package/dist/hooks/subagent-stop.js +529 -21
- package/dist/hooks/summary-worker.js +571 -126
- package/dist/index.js +593 -23
- package/dist/lib/agent-config.js +4 -0
- package/dist/lib/cloud-sync.js +408 -47
- package/dist/lib/config.js +25 -1
- package/dist/lib/consolidation.js +5 -1
- package/dist/lib/database.js +128 -0
- package/dist/lib/db-daemon-client.js +4 -0
- package/dist/lib/db.js +128 -0
- package/dist/lib/device-registry.js +128 -0
- package/dist/lib/embedder.js +25 -1
- package/dist/lib/employee-templates.js +16 -0
- package/dist/lib/employees.js +4 -0
- package/dist/lib/exe-daemon-client.js +4 -0
- package/dist/lib/exe-daemon.js +3158 -930
- package/dist/lib/hybrid-search.js +542 -24
- package/dist/lib/identity.js +7 -0
- package/dist/lib/keychain.js +178 -22
- package/dist/lib/license.js +4 -0
- package/dist/lib/messaging.js +7 -0
- package/dist/lib/reminders.js +7 -0
- package/dist/lib/schedules.js +255 -20
- package/dist/lib/skill-learning.js +28 -1
- package/dist/lib/status-brief.js +39 -0
- package/dist/lib/store.js +528 -20
- package/dist/lib/task-router.js +4 -0
- package/dist/lib/tasks.js +28 -1
- package/dist/lib/tmux-routing.js +28 -1
- package/dist/lib/token-spend.js +7 -0
- package/dist/mcp/server.js +2739 -813
- package/dist/mcp/tools/complete-reminder.js +7 -0
- package/dist/mcp/tools/create-reminder.js +7 -0
- package/dist/mcp/tools/create-task.js +28 -1
- package/dist/mcp/tools/deactivate-behavior.js +7 -0
- package/dist/mcp/tools/list-reminders.js +7 -0
- package/dist/mcp/tools/list-tasks.js +7 -0
- package/dist/mcp/tools/send-message.js +7 -0
- package/dist/mcp/tools/update-task.js +28 -1
- package/dist/runtime/index.js +540 -22
- package/dist/tui/App.js +618 -29
- package/package.json +9 -5
- package/src/commands/exe/cloud.md +11 -8
- package/stack.release.json +3 -3
- package/src/commands/exe/link.md +0 -17
|
@@ -213,6 +213,11 @@ function normalizeAutoUpdate(raw) {
|
|
|
213
213
|
const userAU = raw.autoUpdate ?? {};
|
|
214
214
|
raw.autoUpdate = { ...defaultAU, ...userAU };
|
|
215
215
|
}
|
|
216
|
+
function normalizeOrchestration(raw) {
|
|
217
|
+
const defaultOrg = DEFAULT_CONFIG.orchestration;
|
|
218
|
+
const userOrg = raw.orchestration ?? {};
|
|
219
|
+
raw.orchestration = { ...defaultOrg, ...userOrg };
|
|
220
|
+
}
|
|
216
221
|
async function loadConfig() {
|
|
217
222
|
const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
|
|
218
223
|
await ensurePrivateDir(dir);
|
|
@@ -237,10 +242,15 @@ async function loadConfig() {
|
|
|
237
242
|
normalizeScalingRoadmap(migratedCfg);
|
|
238
243
|
normalizeSessionLifecycle(migratedCfg);
|
|
239
244
|
normalizeAutoUpdate(migratedCfg);
|
|
245
|
+
normalizeOrchestration(migratedCfg);
|
|
240
246
|
const config = { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
|
|
241
247
|
if (config.dbPath.startsWith("~")) {
|
|
242
248
|
config.dbPath = config.dbPath.replace(/^~/, os.homedir());
|
|
243
249
|
}
|
|
250
|
+
const envDbPath = path.join(dir, "memories.db");
|
|
251
|
+
if (process.env.EXE_OS_DIR && config.dbPath !== envDbPath && !existsSync2(config.dbPath) && existsSync2(envDbPath)) {
|
|
252
|
+
config.dbPath = envDbPath;
|
|
253
|
+
}
|
|
244
254
|
return config;
|
|
245
255
|
} catch {
|
|
246
256
|
return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
|
|
@@ -260,7 +270,16 @@ function loadConfigSync() {
|
|
|
260
270
|
normalizeScalingRoadmap(migratedCfg);
|
|
261
271
|
normalizeSessionLifecycle(migratedCfg);
|
|
262
272
|
normalizeAutoUpdate(migratedCfg);
|
|
263
|
-
|
|
273
|
+
normalizeOrchestration(migratedCfg);
|
|
274
|
+
const config = { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
|
|
275
|
+
if (config.dbPath.startsWith("~")) {
|
|
276
|
+
config.dbPath = config.dbPath.replace(/^~/, os.homedir());
|
|
277
|
+
}
|
|
278
|
+
const envDbPath = path.join(dir, "memories.db");
|
|
279
|
+
if (process.env.EXE_OS_DIR && config.dbPath !== envDbPath && !existsSync2(config.dbPath) && existsSync2(envDbPath)) {
|
|
280
|
+
config.dbPath = envDbPath;
|
|
281
|
+
}
|
|
282
|
+
return config;
|
|
264
283
|
} catch {
|
|
265
284
|
return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
|
|
266
285
|
}
|
|
@@ -281,6 +300,7 @@ async function loadConfigFrom(configPath) {
|
|
|
281
300
|
normalizeScalingRoadmap(migratedCfg);
|
|
282
301
|
normalizeSessionLifecycle(migratedCfg);
|
|
283
302
|
normalizeAutoUpdate(migratedCfg);
|
|
303
|
+
normalizeOrchestration(migratedCfg);
|
|
284
304
|
return { ...DEFAULT_CONFIG, ...migratedCfg };
|
|
285
305
|
} catch {
|
|
286
306
|
return { ...DEFAULT_CONFIG };
|
|
@@ -352,6 +372,10 @@ var init_config = __esm({
|
|
|
352
372
|
checkOnBoot: true,
|
|
353
373
|
autoInstall: false,
|
|
354
374
|
checkIntervalMs: 24 * 60 * 60 * 1e3
|
|
375
|
+
},
|
|
376
|
+
orchestration: {
|
|
377
|
+
phase: "phase_1_coo",
|
|
378
|
+
phaseSetBy: "default"
|
|
355
379
|
}
|
|
356
380
|
};
|
|
357
381
|
CONFIG_MIGRATIONS = [
|
|
@@ -1795,6 +1819,9 @@ function getClient() {
|
|
|
1795
1819
|
if (_daemonClient && _daemonClient._isDaemonActive()) {
|
|
1796
1820
|
return _daemonClient;
|
|
1797
1821
|
}
|
|
1822
|
+
if (!_resilientClient) {
|
|
1823
|
+
return _adapterClient;
|
|
1824
|
+
}
|
|
1798
1825
|
return _resilientClient;
|
|
1799
1826
|
}
|
|
1800
1827
|
async function initDaemonClient() {
|
|
@@ -2827,6 +2854,127 @@ async function ensureSchema() {
|
|
|
2827
2854
|
VALUES (new.rowid, new.content, new.subject, new.predicate, new.object);
|
|
2828
2855
|
END;
|
|
2829
2856
|
`);
|
|
2857
|
+
await client.executeMultiple(`
|
|
2858
|
+
CREATE TABLE IF NOT EXISTS agent_sessions (
|
|
2859
|
+
id TEXT PRIMARY KEY,
|
|
2860
|
+
agent_id TEXT NOT NULL,
|
|
2861
|
+
project_name TEXT,
|
|
2862
|
+
started_at TEXT NOT NULL,
|
|
2863
|
+
last_event_at TEXT NOT NULL,
|
|
2864
|
+
event_count INTEGER NOT NULL DEFAULT 0,
|
|
2865
|
+
properties TEXT DEFAULT '{}'
|
|
2866
|
+
);
|
|
2867
|
+
|
|
2868
|
+
CREATE INDEX IF NOT EXISTS idx_agent_sessions_agent_time
|
|
2869
|
+
ON agent_sessions(agent_id, started_at);
|
|
2870
|
+
|
|
2871
|
+
CREATE TABLE IF NOT EXISTS agent_goals (
|
|
2872
|
+
id TEXT PRIMARY KEY,
|
|
2873
|
+
statement TEXT NOT NULL,
|
|
2874
|
+
owner_agent_id TEXT,
|
|
2875
|
+
project_name TEXT,
|
|
2876
|
+
status TEXT NOT NULL DEFAULT 'open',
|
|
2877
|
+
priority INTEGER NOT NULL DEFAULT 5,
|
|
2878
|
+
success_criteria TEXT,
|
|
2879
|
+
parent_goal_id TEXT,
|
|
2880
|
+
due_at TEXT,
|
|
2881
|
+
achieved_at TEXT,
|
|
2882
|
+
supersedes_id TEXT,
|
|
2883
|
+
created_at TEXT NOT NULL,
|
|
2884
|
+
updated_at TEXT NOT NULL,
|
|
2885
|
+
source_memory_id TEXT
|
|
2886
|
+
);
|
|
2887
|
+
|
|
2888
|
+
CREATE INDEX IF NOT EXISTS idx_agent_goals_project_status
|
|
2889
|
+
ON agent_goals(project_name, status, priority);
|
|
2890
|
+
|
|
2891
|
+
CREATE TABLE IF NOT EXISTS agent_events (
|
|
2892
|
+
id TEXT PRIMARY KEY,
|
|
2893
|
+
event_type TEXT NOT NULL,
|
|
2894
|
+
occurred_at TEXT NOT NULL,
|
|
2895
|
+
sequence_index INTEGER NOT NULL,
|
|
2896
|
+
actor_agent_id TEXT,
|
|
2897
|
+
agent_role TEXT,
|
|
2898
|
+
project_name TEXT,
|
|
2899
|
+
session_id TEXT,
|
|
2900
|
+
task_id TEXT,
|
|
2901
|
+
goal_id TEXT,
|
|
2902
|
+
parent_event_id TEXT,
|
|
2903
|
+
intention TEXT,
|
|
2904
|
+
outcome TEXT,
|
|
2905
|
+
evidence_memory_id TEXT,
|
|
2906
|
+
impact TEXT,
|
|
2907
|
+
payload TEXT DEFAULT '{}',
|
|
2908
|
+
created_at TEXT NOT NULL
|
|
2909
|
+
);
|
|
2910
|
+
|
|
2911
|
+
CREATE INDEX IF NOT EXISTS idx_agent_events_time
|
|
2912
|
+
ON agent_events(occurred_at, sequence_index);
|
|
2913
|
+
|
|
2914
|
+
CREATE INDEX IF NOT EXISTS idx_agent_events_session_seq
|
|
2915
|
+
ON agent_events(session_id, sequence_index);
|
|
2916
|
+
|
|
2917
|
+
CREATE INDEX IF NOT EXISTS idx_agent_events_goal_time
|
|
2918
|
+
ON agent_events(goal_id, occurred_at);
|
|
2919
|
+
|
|
2920
|
+
CREATE INDEX IF NOT EXISTS idx_agent_events_memory
|
|
2921
|
+
ON agent_events(evidence_memory_id);
|
|
2922
|
+
|
|
2923
|
+
CREATE TABLE IF NOT EXISTS agent_goal_links (
|
|
2924
|
+
id TEXT PRIMARY KEY,
|
|
2925
|
+
goal_id TEXT NOT NULL,
|
|
2926
|
+
link_type TEXT NOT NULL,
|
|
2927
|
+
target_id TEXT NOT NULL,
|
|
2928
|
+
target_type TEXT NOT NULL,
|
|
2929
|
+
created_at TEXT NOT NULL
|
|
2930
|
+
);
|
|
2931
|
+
|
|
2932
|
+
CREATE INDEX IF NOT EXISTS idx_agent_goal_links_goal
|
|
2933
|
+
ON agent_goal_links(goal_id, target_type);
|
|
2934
|
+
|
|
2935
|
+
CREATE TABLE IF NOT EXISTS agent_semantic_labels (
|
|
2936
|
+
id TEXT PRIMARY KEY,
|
|
2937
|
+
source_memory_id TEXT NOT NULL,
|
|
2938
|
+
event_id TEXT,
|
|
2939
|
+
labeler TEXT NOT NULL,
|
|
2940
|
+
schema_version INTEGER NOT NULL DEFAULT 1,
|
|
2941
|
+
confidence REAL NOT NULL DEFAULT 0,
|
|
2942
|
+
labels TEXT NOT NULL,
|
|
2943
|
+
created_at TEXT NOT NULL,
|
|
2944
|
+
updated_at TEXT NOT NULL
|
|
2945
|
+
);
|
|
2946
|
+
|
|
2947
|
+
CREATE INDEX IF NOT EXISTS idx_agent_semantic_labels_memory
|
|
2948
|
+
ON agent_semantic_labels(source_memory_id, labeler);
|
|
2949
|
+
|
|
2950
|
+
CREATE INDEX IF NOT EXISTS idx_agent_semantic_labels_event
|
|
2951
|
+
ON agent_semantic_labels(event_id);
|
|
2952
|
+
|
|
2953
|
+
CREATE TABLE IF NOT EXISTS agent_reflection_checkpoints (
|
|
2954
|
+
id TEXT PRIMARY KEY,
|
|
2955
|
+
project_name TEXT,
|
|
2956
|
+
session_id TEXT,
|
|
2957
|
+
window_start_at TEXT NOT NULL,
|
|
2958
|
+
window_end_at TEXT NOT NULL,
|
|
2959
|
+
event_count INTEGER NOT NULL DEFAULT 0,
|
|
2960
|
+
goal_count INTEGER NOT NULL DEFAULT 0,
|
|
2961
|
+
success_count INTEGER NOT NULL DEFAULT 0,
|
|
2962
|
+
failure_count INTEGER NOT NULL DEFAULT 0,
|
|
2963
|
+
risk_count INTEGER NOT NULL DEFAULT 0,
|
|
2964
|
+
summary TEXT NOT NULL,
|
|
2965
|
+
learnings TEXT NOT NULL DEFAULT '[]',
|
|
2966
|
+
next_actions TEXT NOT NULL DEFAULT '[]',
|
|
2967
|
+
evidence_event_ids TEXT NOT NULL DEFAULT '[]',
|
|
2968
|
+
confidence REAL NOT NULL DEFAULT 0,
|
|
2969
|
+
created_at TEXT NOT NULL
|
|
2970
|
+
);
|
|
2971
|
+
|
|
2972
|
+
CREATE INDEX IF NOT EXISTS idx_agent_reflection_project_time
|
|
2973
|
+
ON agent_reflection_checkpoints(project_name, window_end_at);
|
|
2974
|
+
|
|
2975
|
+
CREATE INDEX IF NOT EXISTS idx_agent_reflection_session_time
|
|
2976
|
+
ON agent_reflection_checkpoints(session_id, window_end_at);
|
|
2977
|
+
`);
|
|
2830
2978
|
try {
|
|
2831
2979
|
await client.execute({
|
|
2832
2980
|
sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
|
|
@@ -2979,12 +3127,13 @@ var keychain_exports = {};
|
|
|
2979
3127
|
__export(keychain_exports, {
|
|
2980
3128
|
deleteMasterKey: () => deleteMasterKey,
|
|
2981
3129
|
exportMnemonic: () => exportMnemonic,
|
|
3130
|
+
getKeyStorageInfo: () => getKeyStorageInfo,
|
|
2982
3131
|
getMasterKey: () => getMasterKey,
|
|
2983
3132
|
importMnemonic: () => importMnemonic,
|
|
2984
3133
|
setMasterKey: () => setMasterKey
|
|
2985
3134
|
});
|
|
2986
3135
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
2987
|
-
import { existsSync as existsSync6 } from "fs";
|
|
3136
|
+
import { existsSync as existsSync6, statSync as statSync2 } from "fs";
|
|
2988
3137
|
import { execSync as execSync2 } from "child_process";
|
|
2989
3138
|
import path6 from "path";
|
|
2990
3139
|
import os5 from "os";
|
|
@@ -2994,29 +3143,65 @@ function getKeyDir() {
|
|
|
2994
3143
|
function getKeyPath() {
|
|
2995
3144
|
return path6.join(getKeyDir(), "master.key");
|
|
2996
3145
|
}
|
|
2997
|
-
function
|
|
3146
|
+
function nativeKeychainAllowed() {
|
|
3147
|
+
return process.env.EXE_OS_DISABLE_NATIVE_KEYCHAIN !== "1";
|
|
3148
|
+
}
|
|
3149
|
+
function linuxSecretAvailable() {
|
|
3150
|
+
if (!nativeKeychainAllowed()) return false;
|
|
3151
|
+
if (process.platform !== "linux") return false;
|
|
3152
|
+
if (linuxSecretAvailability !== null) return linuxSecretAvailability;
|
|
3153
|
+
try {
|
|
3154
|
+
execSync2("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
|
|
3155
|
+
} catch {
|
|
3156
|
+
linuxSecretAvailability = false;
|
|
3157
|
+
return false;
|
|
3158
|
+
}
|
|
3159
|
+
try {
|
|
3160
|
+
execSync2("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
|
|
3161
|
+
linuxSecretAvailability = true;
|
|
3162
|
+
} catch {
|
|
3163
|
+
linuxSecretAvailability = false;
|
|
3164
|
+
}
|
|
3165
|
+
return linuxSecretAvailability;
|
|
3166
|
+
}
|
|
3167
|
+
function isRootOnlyTrustedServerKeyFile(keyPath) {
|
|
3168
|
+
if (process.platform !== "linux") return false;
|
|
3169
|
+
try {
|
|
3170
|
+
const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
|
|
3171
|
+
const st = statSync2(keyPath);
|
|
3172
|
+
if (!st.isFile() || (st.mode & 63) !== 0) return false;
|
|
3173
|
+
if (uid === 0) return true;
|
|
3174
|
+
const exeOsDir = process.env.EXE_OS_DIR;
|
|
3175
|
+
return Boolean(exeOsDir && path6.resolve(keyPath).startsWith(path6.resolve(exeOsDir) + path6.sep));
|
|
3176
|
+
} catch {
|
|
3177
|
+
return false;
|
|
3178
|
+
}
|
|
3179
|
+
}
|
|
3180
|
+
function macKeychainGet(service = SERVICE) {
|
|
3181
|
+
if (!nativeKeychainAllowed()) return null;
|
|
2998
3182
|
if (process.platform !== "darwin") return null;
|
|
2999
3183
|
try {
|
|
3000
3184
|
return execSync2(
|
|
3001
|
-
`security find-generic-password -s "${
|
|
3185
|
+
`security find-generic-password -s "${service}" -a "${ACCOUNT}" -w 2>/dev/null`,
|
|
3002
3186
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
3003
3187
|
).trim();
|
|
3004
3188
|
} catch {
|
|
3005
3189
|
return null;
|
|
3006
3190
|
}
|
|
3007
3191
|
}
|
|
3008
|
-
function macKeychainSet(value) {
|
|
3192
|
+
function macKeychainSet(value, service = SERVICE) {
|
|
3193
|
+
if (!nativeKeychainAllowed()) return false;
|
|
3009
3194
|
if (process.platform !== "darwin") return false;
|
|
3010
3195
|
try {
|
|
3011
3196
|
try {
|
|
3012
3197
|
execSync2(
|
|
3013
|
-
`security delete-generic-password -s "${
|
|
3198
|
+
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
3014
3199
|
{ timeout: 5e3 }
|
|
3015
3200
|
);
|
|
3016
3201
|
} catch {
|
|
3017
3202
|
}
|
|
3018
3203
|
execSync2(
|
|
3019
|
-
`security add-generic-password -s "${
|
|
3204
|
+
`security add-generic-password -s "${service}" -a "${ACCOUNT}" -w "${value}"`,
|
|
3020
3205
|
{ timeout: 5e3 }
|
|
3021
3206
|
);
|
|
3022
3207
|
return true;
|
|
@@ -3024,11 +3209,12 @@ function macKeychainSet(value) {
|
|
|
3024
3209
|
return false;
|
|
3025
3210
|
}
|
|
3026
3211
|
}
|
|
3027
|
-
function macKeychainDelete() {
|
|
3212
|
+
function macKeychainDelete(service = SERVICE) {
|
|
3213
|
+
if (!nativeKeychainAllowed()) return false;
|
|
3028
3214
|
if (process.platform !== "darwin") return false;
|
|
3029
3215
|
try {
|
|
3030
3216
|
execSync2(
|
|
3031
|
-
`security delete-generic-password -s "${
|
|
3217
|
+
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
3032
3218
|
{ timeout: 5e3 }
|
|
3033
3219
|
);
|
|
3034
3220
|
return true;
|
|
@@ -3036,22 +3222,22 @@ function macKeychainDelete() {
|
|
|
3036
3222
|
return false;
|
|
3037
3223
|
}
|
|
3038
3224
|
}
|
|
3039
|
-
function linuxSecretGet() {
|
|
3040
|
-
if (
|
|
3225
|
+
function linuxSecretGet(service = SERVICE) {
|
|
3226
|
+
if (!linuxSecretAvailable()) return null;
|
|
3041
3227
|
try {
|
|
3042
3228
|
return execSync2(
|
|
3043
|
-
`secret-tool lookup service "${
|
|
3229
|
+
`secret-tool lookup service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
3044
3230
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
3045
3231
|
).trim();
|
|
3046
3232
|
} catch {
|
|
3047
3233
|
return null;
|
|
3048
3234
|
}
|
|
3049
3235
|
}
|
|
3050
|
-
function linuxSecretSet(value) {
|
|
3051
|
-
if (
|
|
3236
|
+
function linuxSecretSet(value, service = SERVICE) {
|
|
3237
|
+
if (!linuxSecretAvailable()) return false;
|
|
3052
3238
|
try {
|
|
3053
3239
|
execSync2(
|
|
3054
|
-
`echo -n "${value}" | secret-tool store --label="exe-os master key" service "${
|
|
3240
|
+
`echo -n "${value}" | secret-tool store --label="exe-os master key" service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
3055
3241
|
{ timeout: 5e3 }
|
|
3056
3242
|
);
|
|
3057
3243
|
return true;
|
|
@@ -3059,11 +3245,12 @@ function linuxSecretSet(value) {
|
|
|
3059
3245
|
return false;
|
|
3060
3246
|
}
|
|
3061
3247
|
}
|
|
3062
|
-
function linuxSecretDelete() {
|
|
3248
|
+
function linuxSecretDelete(service = SERVICE) {
|
|
3249
|
+
if (!nativeKeychainAllowed()) return false;
|
|
3063
3250
|
if (process.platform !== "linux") return false;
|
|
3064
3251
|
try {
|
|
3065
3252
|
execSync2(
|
|
3066
|
-
`secret-tool clear service "${
|
|
3253
|
+
`secret-tool clear service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
3067
3254
|
{ timeout: 5e3 }
|
|
3068
3255
|
);
|
|
3069
3256
|
return true;
|
|
@@ -3072,6 +3259,7 @@ function linuxSecretDelete() {
|
|
|
3072
3259
|
}
|
|
3073
3260
|
}
|
|
3074
3261
|
async function tryKeytar() {
|
|
3262
|
+
if (!nativeKeychainAllowed()) return null;
|
|
3075
3263
|
try {
|
|
3076
3264
|
return await import("keytar");
|
|
3077
3265
|
} catch {
|
|
@@ -3145,7 +3333,19 @@ async function writeMachineBoundFileFallback(b64) {
|
|
|
3145
3333
|
return "plaintext";
|
|
3146
3334
|
}
|
|
3147
3335
|
async function getMasterKey() {
|
|
3148
|
-
|
|
3336
|
+
let nativeValue = macKeychainGet() ?? linuxSecretGet();
|
|
3337
|
+
if (!nativeValue) {
|
|
3338
|
+
const legacyValue = macKeychainGet(LEGACY_SERVICE) ?? linuxSecretGet(LEGACY_SERVICE);
|
|
3339
|
+
if (legacyValue) {
|
|
3340
|
+
const migrated = macKeychainSet(legacyValue) || linuxSecretSet(legacyValue);
|
|
3341
|
+
if (migrated) {
|
|
3342
|
+
macKeychainDelete(LEGACY_SERVICE);
|
|
3343
|
+
linuxSecretDelete(LEGACY_SERVICE);
|
|
3344
|
+
process.stderr.write("[keychain] Migrated keychain service from exe-mem to exe-os.\n");
|
|
3345
|
+
}
|
|
3346
|
+
nativeValue = legacyValue;
|
|
3347
|
+
}
|
|
3348
|
+
}
|
|
3149
3349
|
if (nativeValue) {
|
|
3150
3350
|
return Buffer.from(nativeValue, "base64");
|
|
3151
3351
|
}
|
|
@@ -3153,12 +3353,17 @@ async function getMasterKey() {
|
|
|
3153
3353
|
if (keytar) {
|
|
3154
3354
|
try {
|
|
3155
3355
|
const keytarValue = await keytar.getPassword(SERVICE, ACCOUNT);
|
|
3156
|
-
|
|
3157
|
-
|
|
3356
|
+
const legacyKeytarValue = keytarValue ?? await keytar.getPassword(LEGACY_SERVICE, ACCOUNT);
|
|
3357
|
+
if (legacyKeytarValue) {
|
|
3358
|
+
const migrated = macKeychainSet(legacyKeytarValue) || linuxSecretSet(legacyKeytarValue);
|
|
3158
3359
|
if (migrated) {
|
|
3159
3360
|
process.stderr.write("[keychain] Migrated key from keytar to native keychain.\n");
|
|
3361
|
+
try {
|
|
3362
|
+
await keytar.deletePassword(LEGACY_SERVICE, ACCOUNT);
|
|
3363
|
+
} catch {
|
|
3364
|
+
}
|
|
3160
3365
|
}
|
|
3161
|
-
return Buffer.from(
|
|
3366
|
+
return Buffer.from(legacyKeytarValue, "base64");
|
|
3162
3367
|
}
|
|
3163
3368
|
} catch {
|
|
3164
3369
|
}
|
|
@@ -3183,7 +3388,7 @@ async function getMasterKey() {
|
|
|
3183
3388
|
const decrypted = decryptWithMachineKey(content, machineKey);
|
|
3184
3389
|
if (!decrypted) {
|
|
3185
3390
|
process.stderr.write(
|
|
3186
|
-
"[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase: exe-os
|
|
3391
|
+
"[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase during setup: exe-os setup\n"
|
|
3187
3392
|
);
|
|
3188
3393
|
return null;
|
|
3189
3394
|
}
|
|
@@ -3192,6 +3397,9 @@ async function getMasterKey() {
|
|
|
3192
3397
|
b64Value = content;
|
|
3193
3398
|
}
|
|
3194
3399
|
const key = Buffer.from(b64Value, "base64");
|
|
3400
|
+
if (!content.startsWith(ENCRYPTED_PREFIX) && isRootOnlyTrustedServerKeyFile(keyPath)) {
|
|
3401
|
+
return key;
|
|
3402
|
+
}
|
|
3195
3403
|
const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
|
|
3196
3404
|
if (migrated) {
|
|
3197
3405
|
process.stderr.write("[keychain] Migrated key from file to native keychain.\n");
|
|
@@ -3219,6 +3427,97 @@ async function getMasterKey() {
|
|
|
3219
3427
|
return null;
|
|
3220
3428
|
}
|
|
3221
3429
|
}
|
|
3430
|
+
async function getKeyStorageInfo() {
|
|
3431
|
+
if (macKeychainGet()) {
|
|
3432
|
+
return {
|
|
3433
|
+
kind: "macos-keychain",
|
|
3434
|
+
secure: true,
|
|
3435
|
+
note: "stored in macOS Keychain via built-in security CLI"
|
|
3436
|
+
};
|
|
3437
|
+
}
|
|
3438
|
+
if (macKeychainGet(LEGACY_SERVICE)) {
|
|
3439
|
+
return {
|
|
3440
|
+
kind: "macos-keychain",
|
|
3441
|
+
secure: true,
|
|
3442
|
+
note: "stored in legacy macOS Keychain service exe-mem; next key read migrates it to exe-os"
|
|
3443
|
+
};
|
|
3444
|
+
}
|
|
3445
|
+
if (linuxSecretGet()) {
|
|
3446
|
+
return {
|
|
3447
|
+
kind: "linux-secret-service",
|
|
3448
|
+
secure: true,
|
|
3449
|
+
note: "stored in Linux Secret Service via secret-tool"
|
|
3450
|
+
};
|
|
3451
|
+
}
|
|
3452
|
+
if (linuxSecretGet(LEGACY_SERVICE)) {
|
|
3453
|
+
return {
|
|
3454
|
+
kind: "linux-secret-service",
|
|
3455
|
+
secure: true,
|
|
3456
|
+
note: "stored in legacy Linux Secret Service service exe-mem; next key read migrates it to exe-os"
|
|
3457
|
+
};
|
|
3458
|
+
}
|
|
3459
|
+
const keytar = await tryKeytar();
|
|
3460
|
+
if (keytar) {
|
|
3461
|
+
try {
|
|
3462
|
+
if (await keytar.getPassword(SERVICE, ACCOUNT)) {
|
|
3463
|
+
return {
|
|
3464
|
+
kind: "legacy-keytar",
|
|
3465
|
+
secure: true,
|
|
3466
|
+
note: "stored in legacy keytar backend; will migrate to native keychain when possible"
|
|
3467
|
+
};
|
|
3468
|
+
}
|
|
3469
|
+
if (await keytar.getPassword(LEGACY_SERVICE, ACCOUNT)) {
|
|
3470
|
+
return {
|
|
3471
|
+
kind: "legacy-keytar",
|
|
3472
|
+
secure: true,
|
|
3473
|
+
note: "stored in legacy keytar service exe-mem; will migrate to native exe-os keychain when possible"
|
|
3474
|
+
};
|
|
3475
|
+
}
|
|
3476
|
+
} catch {
|
|
3477
|
+
}
|
|
3478
|
+
}
|
|
3479
|
+
const keyPath = getKeyPath();
|
|
3480
|
+
if (!existsSync6(keyPath)) {
|
|
3481
|
+
return {
|
|
3482
|
+
kind: "missing",
|
|
3483
|
+
secure: false,
|
|
3484
|
+
path: keyPath,
|
|
3485
|
+
note: "no key found in OS keychain, legacy keytar, or file fallback"
|
|
3486
|
+
};
|
|
3487
|
+
}
|
|
3488
|
+
try {
|
|
3489
|
+
const content = (await readFile3(keyPath, "utf-8")).trim();
|
|
3490
|
+
if (content.startsWith(ENCRYPTED_PREFIX)) {
|
|
3491
|
+
return {
|
|
3492
|
+
kind: "encrypted-file",
|
|
3493
|
+
secure: true,
|
|
3494
|
+
path: keyPath,
|
|
3495
|
+
note: "stored in machine-bound encrypted file fallback"
|
|
3496
|
+
};
|
|
3497
|
+
}
|
|
3498
|
+
if (isRootOnlyTrustedServerKeyFile(keyPath)) {
|
|
3499
|
+
return {
|
|
3500
|
+
kind: "server-secret-file",
|
|
3501
|
+
secure: true,
|
|
3502
|
+
path: keyPath,
|
|
3503
|
+
note: "stored as root-only trusted server secret file"
|
|
3504
|
+
};
|
|
3505
|
+
}
|
|
3506
|
+
return {
|
|
3507
|
+
kind: "plaintext-file",
|
|
3508
|
+
secure: false,
|
|
3509
|
+
path: keyPath,
|
|
3510
|
+
note: "stored in legacy plaintext file; reading it will migrate or encrypt it"
|
|
3511
|
+
};
|
|
3512
|
+
} catch {
|
|
3513
|
+
return {
|
|
3514
|
+
kind: "missing",
|
|
3515
|
+
secure: false,
|
|
3516
|
+
path: keyPath,
|
|
3517
|
+
note: "key file exists but could not be read"
|
|
3518
|
+
};
|
|
3519
|
+
}
|
|
3520
|
+
}
|
|
3222
3521
|
async function setMasterKey(key) {
|
|
3223
3522
|
const b64 = key.toString("base64");
|
|
3224
3523
|
if (macKeychainSet(b64) || linuxSecretSet(b64)) {
|
|
@@ -3244,10 +3543,13 @@ async function setMasterKey(key) {
|
|
|
3244
3543
|
async function deleteMasterKey() {
|
|
3245
3544
|
macKeychainDelete();
|
|
3246
3545
|
linuxSecretDelete();
|
|
3546
|
+
macKeychainDelete(LEGACY_SERVICE);
|
|
3547
|
+
linuxSecretDelete(LEGACY_SERVICE);
|
|
3247
3548
|
const keytar = await tryKeytar();
|
|
3248
3549
|
if (keytar) {
|
|
3249
3550
|
try {
|
|
3250
3551
|
await keytar.deletePassword(SERVICE, ACCOUNT);
|
|
3552
|
+
await keytar.deletePassword(LEGACY_SERVICE, ACCOUNT);
|
|
3251
3553
|
} catch {
|
|
3252
3554
|
}
|
|
3253
3555
|
}
|
|
@@ -3285,12 +3587,14 @@ async function importMnemonic(mnemonic) {
|
|
|
3285
3587
|
const entropy = mnemonicToEntropy(trimmed);
|
|
3286
3588
|
return Buffer.from(entropy, "hex");
|
|
3287
3589
|
}
|
|
3288
|
-
var SERVICE, ACCOUNT, ENCRYPTED_PREFIX;
|
|
3590
|
+
var SERVICE, LEGACY_SERVICE, ACCOUNT, linuxSecretAvailability, ENCRYPTED_PREFIX;
|
|
3289
3591
|
var init_keychain = __esm({
|
|
3290
3592
|
"src/lib/keychain.ts"() {
|
|
3291
3593
|
"use strict";
|
|
3292
|
-
SERVICE = "exe-
|
|
3594
|
+
SERVICE = "exe-os";
|
|
3595
|
+
LEGACY_SERVICE = "exe-mem";
|
|
3293
3596
|
ACCOUNT = "master-key";
|
|
3597
|
+
linuxSecretAvailability = null;
|
|
3294
3598
|
ENCRYPTED_PREFIX = "enc:";
|
|
3295
3599
|
}
|
|
3296
3600
|
});
|
|
@@ -3366,7 +3670,7 @@ __export(shard_manager_exports, {
|
|
|
3366
3670
|
shardExists: () => shardExists
|
|
3367
3671
|
});
|
|
3368
3672
|
import path7 from "path";
|
|
3369
|
-
import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as
|
|
3673
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as statSync3 } from "fs";
|
|
3370
3674
|
import { createClient as createClient2 } from "@libsql/client";
|
|
3371
3675
|
function initShardManager(encryptionKey) {
|
|
3372
3676
|
_encryptionKey = encryptionKey;
|
|
@@ -3430,7 +3734,7 @@ async function auditShardHealth(options = {}) {
|
|
|
3430
3734
|
const shards = [];
|
|
3431
3735
|
for (const name of names) {
|
|
3432
3736
|
const dbPath = path7.join(SHARDS_DIR, `${name}.db`);
|
|
3433
|
-
const stat =
|
|
3737
|
+
const stat = statSync3(dbPath);
|
|
3434
3738
|
const item = {
|
|
3435
3739
|
name,
|
|
3436
3740
|
path: dbPath,
|
|
@@ -3683,7 +3987,7 @@ async function getReadyShardClient(projectName) {
|
|
|
3683
3987
|
_shardLastAccess.delete(safeName);
|
|
3684
3988
|
const dbPath = path7.join(SHARDS_DIR, `${safeName}.db`);
|
|
3685
3989
|
if (existsSync7(dbPath)) {
|
|
3686
|
-
const stat =
|
|
3990
|
+
const stat = statSync3(dbPath);
|
|
3687
3991
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
3688
3992
|
const archivedPath = path7.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
|
|
3689
3993
|
renameSync3(dbPath, archivedPath);
|
|
@@ -3803,6 +4107,12 @@ var init_platform_procedures = __esm({
|
|
|
3803
4107
|
priority: "p0",
|
|
3804
4108
|
content: "Founder -> coordinator (the executive agent, internally routed as 'COO') -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the coordinator does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
|
|
3805
4109
|
},
|
|
4110
|
+
{
|
|
4111
|
+
title: "Customer orchestration maturity \u2014 recommend, never trap",
|
|
4112
|
+
domain: "workflow",
|
|
4113
|
+
priority: "p1",
|
|
4114
|
+
content: "New customers start best in Phase 1: founder \u2194 coordinator/Chief of Staff, building company context. Suggest Phase 2 executives when domain work repeats; suggest Phase 3 parallel execution only when review/permission gates are ready. This is guidance, not a blocker: users may jump phases anytime. Never overwrite their phase, role titles, identities, or custom org design."
|
|
4115
|
+
},
|
|
3806
4116
|
{
|
|
3807
4117
|
title: "Single dispatch path \u2014 create_task only",
|
|
3808
4118
|
domain: "workflow",
|
|
@@ -3861,6 +4171,12 @@ var init_platform_procedures = __esm({
|
|
|
3861
4171
|
priority: "p0",
|
|
3862
4172
|
content: "exe-build-adv is MANDATORY for ALL work touching 3+ files. Run /exe-build-adv --auto BEFORE implementation. Pipeline: Spec \u2192 AC \u2192 Tests \u2192 Evaluate \u2192 Fix. No multi-file feature ships without pipeline artifacts. No exceptions \u2014 managers reject work without them."
|
|
3863
4173
|
},
|
|
4174
|
+
{
|
|
4175
|
+
title: "Commit discipline \u2014 never leave verified work floating",
|
|
4176
|
+
domain: "workflow",
|
|
4177
|
+
priority: "p1",
|
|
4178
|
+
content: "After any code-change batch passes typecheck/tests/build, run git status, summarize changed files, and commit with a clear message before ending the session. If work must remain uncommitted for review/dogfood, explicitly say so, list the files, and state the blocker. Never imply work is complete while verified changes are still floating locally."
|
|
4179
|
+
},
|
|
3864
4180
|
{
|
|
3865
4181
|
title: "Desktop and TUI are the same product",
|
|
3866
4182
|
domain: "architecture",
|
|
@@ -4565,8 +4881,8 @@ async function validateLicense(apiKey, deviceId) {
|
|
|
4565
4881
|
}
|
|
4566
4882
|
function getCacheAgeMs() {
|
|
4567
4883
|
try {
|
|
4568
|
-
const { statSync:
|
|
4569
|
-
const s =
|
|
4884
|
+
const { statSync: statSync7 } = __require("fs");
|
|
4885
|
+
const s = statSync7(CACHE_PATH);
|
|
4570
4886
|
return Date.now() - s.mtimeMs;
|
|
4571
4887
|
} catch {
|
|
4572
4888
|
return Infinity;
|
|
@@ -5543,7 +5859,7 @@ __export(db_backup_exports, {
|
|
|
5543
5859
|
listBackups: () => listBackups,
|
|
5544
5860
|
rotateBackups: () => rotateBackups
|
|
5545
5861
|
});
|
|
5546
|
-
import { copyFileSync, existsSync as existsSync18, mkdirSync as mkdirSync9, readdirSync as readdirSync5, unlinkSync as unlinkSync7, statSync as
|
|
5862
|
+
import { copyFileSync, existsSync as existsSync18, mkdirSync as mkdirSync9, readdirSync as readdirSync5, unlinkSync as unlinkSync7, statSync as statSync5 } from "fs";
|
|
5547
5863
|
import path19 from "path";
|
|
5548
5864
|
function findActiveDb() {
|
|
5549
5865
|
for (const name of DB_NAMES) {
|
|
@@ -5587,7 +5903,7 @@ function rotateBackups(keepDays = DEFAULT_KEEP_DAYS) {
|
|
|
5587
5903
|
if (!file.endsWith(".db") && !file.endsWith(".db-wal") && !file.endsWith(".db-shm")) continue;
|
|
5588
5904
|
const filePath = path19.join(BACKUP_DIR, file);
|
|
5589
5905
|
try {
|
|
5590
|
-
const stat =
|
|
5906
|
+
const stat = statSync5(filePath);
|
|
5591
5907
|
if (stat.mtimeMs < cutoff) {
|
|
5592
5908
|
unlinkSync7(filePath);
|
|
5593
5909
|
deleted++;
|
|
@@ -5605,7 +5921,7 @@ function listBackups() {
|
|
|
5605
5921
|
const files = readdirSync5(BACKUP_DIR).filter((f) => f.endsWith(".db") && !f.endsWith("-wal") && !f.endsWith("-shm"));
|
|
5606
5922
|
return files.map((name) => {
|
|
5607
5923
|
const p = path19.join(BACKUP_DIR, name);
|
|
5608
|
-
const stat =
|
|
5924
|
+
const stat = statSync5(p);
|
|
5609
5925
|
return { path: p, name, size: stat.size, date: stat.mtime };
|
|
5610
5926
|
}).sort((a, b) => b.date.getTime() - a.date.getTime());
|
|
5611
5927
|
} catch {
|
|
@@ -5638,8 +5954,10 @@ var init_db_backup = __esm({
|
|
|
5638
5954
|
// src/lib/cloud-sync.ts
|
|
5639
5955
|
var cloud_sync_exports = {};
|
|
5640
5956
|
__export(cloud_sync_exports, {
|
|
5957
|
+
CLOUD_REUPLOAD_REQUIRED_MESSAGE: () => CLOUD_REUPLOAD_REQUIRED_MESSAGE,
|
|
5641
5958
|
assertSecureEndpoint: () => assertSecureEndpoint,
|
|
5642
5959
|
buildRosterBlob: () => buildRosterBlob,
|
|
5960
|
+
clearCloudReuploadRequired: () => clearCloudReuploadRequired,
|
|
5643
5961
|
cloudPull: () => cloudPull,
|
|
5644
5962
|
cloudPullBehaviors: () => cloudPullBehaviors,
|
|
5645
5963
|
cloudPullBlob: () => cloudPullBlob,
|
|
@@ -5658,13 +5976,16 @@ __export(cloud_sync_exports, {
|
|
|
5658
5976
|
cloudPushGraphRAG: () => cloudPushGraphRAG,
|
|
5659
5977
|
cloudPushRoster: () => cloudPushRoster,
|
|
5660
5978
|
cloudPushTasks: () => cloudPushTasks,
|
|
5979
|
+
cloudResetMemoryBlobs: () => cloudResetMemoryBlobs,
|
|
5661
5980
|
cloudSync: () => cloudSync,
|
|
5981
|
+
getCloudReuploadRequired: () => getCloudReuploadRequired,
|
|
5982
|
+
markCloudReuploadRequired: () => markCloudReuploadRequired,
|
|
5662
5983
|
mergeConfig: () => mergeConfig,
|
|
5663
5984
|
mergeRosterFromRemote: () => mergeRosterFromRemote,
|
|
5664
5985
|
pushToPostgres: () => pushToPostgres,
|
|
5665
5986
|
recordRosterDeletion: () => recordRosterDeletion
|
|
5666
5987
|
});
|
|
5667
|
-
import { readFileSync as readFileSync13, writeFileSync as writeFileSync9, existsSync as existsSync19, readdirSync as readdirSync6, mkdirSync as mkdirSync10, appendFileSync as appendFileSync3, unlinkSync as unlinkSync8, openSync as openSync2, closeSync as closeSync2, statSync as
|
|
5988
|
+
import { readFileSync as readFileSync13, writeFileSync as writeFileSync9, existsSync as existsSync19, readdirSync as readdirSync6, mkdirSync as mkdirSync10, appendFileSync as appendFileSync3, unlinkSync as unlinkSync8, openSync as openSync2, closeSync as closeSync2, statSync as statSync6 } from "fs";
|
|
5668
5989
|
import crypto4 from "crypto";
|
|
5669
5990
|
import path20 from "path";
|
|
5670
5991
|
import { homedir as homedir2 } from "os";
|
|
@@ -5711,18 +6032,36 @@ function loadPgClient() {
|
|
|
5711
6032
|
const { pathToFileURL: pathToFileURL3 } = await import("url");
|
|
5712
6033
|
const explicitPath = process.env.EXE_OS_PRISMA_CLIENT_PATH;
|
|
5713
6034
|
if (explicitPath) {
|
|
5714
|
-
const
|
|
5715
|
-
const
|
|
5716
|
-
if (!
|
|
5717
|
-
return new
|
|
6035
|
+
const mod = await import(pathToFileURL3(explicitPath).href);
|
|
6036
|
+
const Ctor = mod.PrismaClient ?? mod.default?.PrismaClient;
|
|
6037
|
+
if (!Ctor) throw new Error(`No PrismaClient at ${explicitPath}`);
|
|
6038
|
+
return new Ctor();
|
|
5718
6039
|
}
|
|
5719
6040
|
const exeDbRoot = process.env.EXE_DB_ROOT ?? path20.join(homedir2(), "exe-db");
|
|
5720
|
-
const
|
|
5721
|
-
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5725
|
-
|
|
6041
|
+
const packagePath = path20.join(exeDbRoot, "package.json");
|
|
6042
|
+
if (existsSync19(packagePath)) {
|
|
6043
|
+
const req = createRequire3(packagePath);
|
|
6044
|
+
const entry = req.resolve("@prisma/client");
|
|
6045
|
+
const mod = await import(pathToFileURL3(entry).href);
|
|
6046
|
+
const Ctor = mod.PrismaClient ?? mod.default?.PrismaClient;
|
|
6047
|
+
if (!Ctor) throw new Error("No PrismaClient");
|
|
6048
|
+
return new Ctor();
|
|
6049
|
+
}
|
|
6050
|
+
const { Pool } = await import("pg");
|
|
6051
|
+
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
|
|
6052
|
+
return {
|
|
6053
|
+
async $queryRawUnsafe(query, ...values) {
|
|
6054
|
+
const result = await pool.query(query, values);
|
|
6055
|
+
return result.rows;
|
|
6056
|
+
},
|
|
6057
|
+
async $executeRawUnsafe(query, ...values) {
|
|
6058
|
+
const result = await pool.query(query, values);
|
|
6059
|
+
return result.rowCount ?? 0;
|
|
6060
|
+
},
|
|
6061
|
+
async $disconnect() {
|
|
6062
|
+
await pool.end();
|
|
6063
|
+
}
|
|
6064
|
+
};
|
|
5726
6065
|
})().catch(() => {
|
|
5727
6066
|
_pgFailed = true;
|
|
5728
6067
|
_pgPromise = null;
|
|
@@ -5743,7 +6082,7 @@ async function pushToPostgres(records) {
|
|
|
5743
6082
|
let inserted = 0;
|
|
5744
6083
|
for (const rec of records) {
|
|
5745
6084
|
try {
|
|
5746
|
-
await prisma.$executeRawUnsafe(
|
|
6085
|
+
const changed = await prisma.$executeRawUnsafe(
|
|
5747
6086
|
`INSERT INTO raw.raw_events (id, source, source_id, event_type, payload, metadata, timestamp)
|
|
5748
6087
|
VALUES (gen_random_uuid(), 'cloud_sync', $1, 'memory', $2::jsonb, $3::jsonb, $4)
|
|
5749
6088
|
ON CONFLICT (source, source_id, event_type) DO NOTHING`,
|
|
@@ -5752,7 +6091,7 @@ async function pushToPostgres(records) {
|
|
|
5752
6091
|
JSON.stringify({ agent_id: rec.agent_id, project_name: rec.project_name, tool_name: rec.tool_name }),
|
|
5753
6092
|
rec.timestamp ? new Date(String(rec.timestamp)) : /* @__PURE__ */ new Date()
|
|
5754
6093
|
);
|
|
5755
|
-
inserted
|
|
6094
|
+
inserted += Number(changed ?? 0);
|
|
5756
6095
|
} catch {
|
|
5757
6096
|
}
|
|
5758
6097
|
}
|
|
@@ -5857,6 +6196,23 @@ async function cloudPush(records, maxVersion, config) {
|
|
|
5857
6196
|
return false;
|
|
5858
6197
|
}
|
|
5859
6198
|
}
|
|
6199
|
+
async function cloudResetMemoryBlobs(config) {
|
|
6200
|
+
assertSecureEndpoint(config.endpoint);
|
|
6201
|
+
const resp = await fetchWithRetry(`${config.endpoint}/sync/reset-memory`, {
|
|
6202
|
+
method: "POST",
|
|
6203
|
+
headers: {
|
|
6204
|
+
Authorization: `Bearer ${config.apiKey}`,
|
|
6205
|
+
"Content-Type": "application/json",
|
|
6206
|
+
"X-Device-Id": loadDeviceId()
|
|
6207
|
+
},
|
|
6208
|
+
body: JSON.stringify({ confirm: "LOCAL DB IS SOURCE OF TRUTH" })
|
|
6209
|
+
});
|
|
6210
|
+
if (!resp.ok) {
|
|
6211
|
+
throw new Error(`cloud reset failed: HTTP ${resp.status}`);
|
|
6212
|
+
}
|
|
6213
|
+
const data = await resp.json();
|
|
6214
|
+
return { deleted: Number(data.deleted ?? 0), freedBytes: Number(data.freed_bytes ?? 0) };
|
|
6215
|
+
}
|
|
5860
6216
|
async function cloudPull(sinceVersion, config) {
|
|
5861
6217
|
assertSecureEndpoint(config.endpoint);
|
|
5862
6218
|
try {
|
|
@@ -5876,22 +6232,61 @@ async function cloudPull(sinceVersion, config) {
|
|
|
5876
6232
|
if (!response.ok) return { records: [], maxVersion: sinceVersion };
|
|
5877
6233
|
const data = await response.json();
|
|
5878
6234
|
const allRecords = [];
|
|
5879
|
-
|
|
6235
|
+
let maxReadableVersion = sinceVersion;
|
|
6236
|
+
let skippedBlobs = 0;
|
|
6237
|
+
for (const { version, blob } of data.blobs ?? []) {
|
|
5880
6238
|
try {
|
|
5881
6239
|
const compressed = decryptSyncBlob(blob);
|
|
5882
6240
|
const json = decompress(compressed).toString("utf8");
|
|
5883
6241
|
const records = JSON.parse(json);
|
|
5884
6242
|
allRecords.push(...records);
|
|
6243
|
+
const recordMax = records.reduce((max, rec) => {
|
|
6244
|
+
const v = Number(rec.version ?? 0);
|
|
6245
|
+
return Number.isFinite(v) ? Math.max(max, v) : max;
|
|
6246
|
+
}, 0);
|
|
6247
|
+
const blobVersion = Number(version ?? 0);
|
|
6248
|
+
maxReadableVersion = Math.max(
|
|
6249
|
+
maxReadableVersion,
|
|
6250
|
+
Number.isFinite(blobVersion) ? blobVersion : 0,
|
|
6251
|
+
recordMax
|
|
6252
|
+
);
|
|
5885
6253
|
} catch {
|
|
6254
|
+
skippedBlobs++;
|
|
5886
6255
|
continue;
|
|
5887
6256
|
}
|
|
5888
6257
|
}
|
|
5889
|
-
|
|
6258
|
+
if (skippedBlobs > 0) {
|
|
6259
|
+
logError(`[cloud-sync] PULL skipped ${skippedBlobs} undecryptable blob(s); pull cursor advanced only to last readable version ${maxReadableVersion}`);
|
|
6260
|
+
}
|
|
6261
|
+
return { records: allRecords, maxVersion: maxReadableVersion };
|
|
5890
6262
|
} catch (err) {
|
|
5891
6263
|
logError(`[cloud-sync] PULL FAILED: ${err instanceof Error ? err.message : String(err)}`);
|
|
5892
6264
|
return { records: [], maxVersion: sinceVersion };
|
|
5893
6265
|
}
|
|
5894
6266
|
}
|
|
6267
|
+
async function getCloudReuploadRequired(client = getClient()) {
|
|
6268
|
+
try {
|
|
6269
|
+
await client.execute("CREATE TABLE IF NOT EXISTS sync_meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)");
|
|
6270
|
+
const result = await client.execute("SELECT key, value FROM sync_meta WHERE key IN ('cloud_reupload_required', 'cloud_relink_required')");
|
|
6271
|
+
return result.rows.some((row) => String(row.value ?? "") === "1");
|
|
6272
|
+
} catch {
|
|
6273
|
+
return false;
|
|
6274
|
+
}
|
|
6275
|
+
}
|
|
6276
|
+
async function clearCloudReuploadRequired(client = getClient()) {
|
|
6277
|
+
await client.execute("CREATE TABLE IF NOT EXISTS sync_meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)");
|
|
6278
|
+
await client.execute("INSERT OR REPLACE INTO sync_meta (key, value) VALUES ('cloud_reupload_required', '0')");
|
|
6279
|
+
await client.execute("INSERT OR REPLACE INTO sync_meta (key, value) VALUES ('cloud_relink_required', '0')");
|
|
6280
|
+
await client.execute({
|
|
6281
|
+
sql: "INSERT OR REPLACE INTO sync_meta (key, value) VALUES ('cloud_reuploaded_at', ?)",
|
|
6282
|
+
args: [(/* @__PURE__ */ new Date()).toISOString()]
|
|
6283
|
+
});
|
|
6284
|
+
await client.execute("DELETE FROM sync_meta WHERE key IN ('last_cloud_pull_version', 'last_cloud_push_version')");
|
|
6285
|
+
}
|
|
6286
|
+
async function markCloudReuploadRequired(client = getClient()) {
|
|
6287
|
+
await client.execute("CREATE TABLE IF NOT EXISTS sync_meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)");
|
|
6288
|
+
await client.execute("INSERT OR REPLACE INTO sync_meta (key, value) VALUES ('cloud_reupload_required', '1')");
|
|
6289
|
+
}
|
|
5895
6290
|
async function cloudSync(config) {
|
|
5896
6291
|
if (!isSyncCryptoInitialized()) {
|
|
5897
6292
|
try {
|
|
@@ -5913,13 +6308,10 @@ async function cloudSync(config) {
|
|
|
5913
6308
|
throw new Error("[cloud-sync] Database not initialized. Call initStore() before cloudSync().");
|
|
5914
6309
|
}
|
|
5915
6310
|
try {
|
|
5916
|
-
|
|
5917
|
-
if (String(relink.rows[0]?.value ?? "") === "1") {
|
|
5918
|
-
throw new Error("[cloud-sync] Paused after key rotation. Re-link/reupload cloud sync with the new recovery phrase before syncing.");
|
|
5919
|
-
}
|
|
6311
|
+
if (await getCloudReuploadRequired(client)) throw new Error(CLOUD_REUPLOAD_REQUIRED_MESSAGE);
|
|
5920
6312
|
} catch (err) {
|
|
5921
6313
|
const msg = err instanceof Error ? err.message : String(err);
|
|
5922
|
-
if (msg.includes("
|
|
6314
|
+
if (msg === CLOUD_REUPLOAD_REQUIRED_MESSAGE || msg.includes("key rotation")) throw err;
|
|
5923
6315
|
}
|
|
5924
6316
|
try {
|
|
5925
6317
|
const { getRawClient: getRawClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
@@ -6177,7 +6569,7 @@ async function cloudSync(config) {
|
|
|
6177
6569
|
const { getLatestBackup: getLatestBackup2 } = await Promise.resolve().then(() => (init_db_backup(), db_backup_exports));
|
|
6178
6570
|
const latestBackup = getLatestBackup2();
|
|
6179
6571
|
if (latestBackup) {
|
|
6180
|
-
const backupSize =
|
|
6572
|
+
const backupSize = statSync6(latestBackup).size;
|
|
6181
6573
|
const MAX_CLOUD_BACKUP_BYTES = 50 * 1024 * 1024;
|
|
6182
6574
|
if (backupSize <= MAX_CLOUD_BACKUP_BYTES) {
|
|
6183
6575
|
const backupData = readFileSync13(latestBackup);
|
|
@@ -6848,7 +7240,7 @@ async function cloudPullDocuments(config) {
|
|
|
6848
7240
|
}
|
|
6849
7241
|
return { pulled };
|
|
6850
7242
|
}
|
|
6851
|
-
var LOCALHOST_PATTERNS, FETCH_TIMEOUT_MS, PUSH_BATCH_SIZE, ROSTER_LOCK_PATH, LOCK_STALE_MS, _pgPromise, _pgFailed, ROSTER_DELETIONS_PATH;
|
|
7243
|
+
var LOCALHOST_PATTERNS, FETCH_TIMEOUT_MS, PUSH_BATCH_SIZE, ROSTER_LOCK_PATH, LOCK_STALE_MS, _pgPromise, _pgFailed, CLOUD_REUPLOAD_REQUIRED_MESSAGE, ROSTER_DELETIONS_PATH;
|
|
6852
7244
|
var init_cloud_sync = __esm({
|
|
6853
7245
|
"src/lib/cloud-sync.ts"() {
|
|
6854
7246
|
"use strict";
|
|
@@ -6867,6 +7259,7 @@ var init_cloud_sync = __esm({
|
|
|
6867
7259
|
LOCK_STALE_MS = 3e4;
|
|
6868
7260
|
_pgPromise = null;
|
|
6869
7261
|
_pgFailed = false;
|
|
7262
|
+
CLOUD_REUPLOAD_REQUIRED_MESSAGE = "Cloud sync is blocked because this device rotated its memory encryption key. Run `exe-os cloud reupload` first to re-upload the cloud backup with the new key.";
|
|
6870
7263
|
ROSTER_DELETIONS_PATH = path20.join(EXE_AI_DIR, "roster-deletions.json");
|
|
6871
7264
|
}
|
|
6872
7265
|
});
|
|
@@ -6973,46 +7366,6 @@ function vectorToBlob(vector) {
|
|
|
6973
7366
|
// src/adapters/claude/hooks/summary-worker.ts
|
|
6974
7367
|
init_database();
|
|
6975
7368
|
init_notifications();
|
|
6976
|
-
|
|
6977
|
-
// src/lib/memory-queue-client.ts
|
|
6978
|
-
init_exe_daemon_client();
|
|
6979
|
-
|
|
6980
|
-
// src/lib/memory-queue.ts
|
|
6981
|
-
init_config();
|
|
6982
|
-
import { appendFileSync as appendFileSync2, readFileSync as readFileSync11, renameSync as renameSync5, unlinkSync as unlinkSync4, existsSync as existsSync15, statSync as statSync3 } from "fs";
|
|
6983
|
-
import path16 from "path";
|
|
6984
|
-
var QUEUE_PATH2 = path16.join(EXE_AI_DIR, "memory-queue.jsonl");
|
|
6985
|
-
var PROCESSING_PATH = QUEUE_PATH2 + ".processing";
|
|
6986
|
-
var TTL_MS2 = 24 * 60 * 60 * 1e3;
|
|
6987
|
-
function enqueueMemory(entry) {
|
|
6988
|
-
appendFileSync2(QUEUE_PATH2, JSON.stringify(entry) + "\n");
|
|
6989
|
-
}
|
|
6990
|
-
|
|
6991
|
-
// src/lib/memory-queue-client.ts
|
|
6992
|
-
async function writeMemoryViaDaemon(entry) {
|
|
6993
|
-
if (process.env.EXE_IS_DAEMON === "1") {
|
|
6994
|
-
enqueueMemory(entry);
|
|
6995
|
-
return false;
|
|
6996
|
-
}
|
|
6997
|
-
if (!isClientConnected()) {
|
|
6998
|
-
enqueueMemory(entry);
|
|
6999
|
-
return false;
|
|
7000
|
-
}
|
|
7001
|
-
try {
|
|
7002
|
-
const response = await sendDaemonRequest({
|
|
7003
|
-
type: "write-memory",
|
|
7004
|
-
entry
|
|
7005
|
-
});
|
|
7006
|
-
if (response.ok) return true;
|
|
7007
|
-
enqueueMemory(entry);
|
|
7008
|
-
return false;
|
|
7009
|
-
} catch {
|
|
7010
|
-
enqueueMemory(entry);
|
|
7011
|
-
return false;
|
|
7012
|
-
}
|
|
7013
|
-
}
|
|
7014
|
-
|
|
7015
|
-
// src/adapters/claude/hooks/summary-worker.ts
|
|
7016
7369
|
init_task_scope();
|
|
7017
7370
|
init_employees();
|
|
7018
7371
|
import { execSync as execSync5 } from "child_process";
|
|
@@ -7099,6 +7452,119 @@ function buildAutoCheckpoint(input) {
|
|
|
7099
7452
|
};
|
|
7100
7453
|
}
|
|
7101
7454
|
|
|
7455
|
+
// src/lib/memory-queue-client.ts
|
|
7456
|
+
init_exe_daemon_client();
|
|
7457
|
+
|
|
7458
|
+
// src/lib/memory-queue.ts
|
|
7459
|
+
init_config();
|
|
7460
|
+
import { appendFileSync as appendFileSync2, readFileSync as readFileSync11, renameSync as renameSync5, unlinkSync as unlinkSync4, existsSync as existsSync15, statSync as statSync4 } from "fs";
|
|
7461
|
+
import path16 from "path";
|
|
7462
|
+
var QUEUE_PATH2 = path16.join(EXE_AI_DIR, "memory-queue.jsonl");
|
|
7463
|
+
var PROCESSING_PATH = QUEUE_PATH2 + ".processing";
|
|
7464
|
+
var TTL_MS2 = 24 * 60 * 60 * 1e3;
|
|
7465
|
+
function enqueueMemory(entry) {
|
|
7466
|
+
appendFileSync2(QUEUE_PATH2, JSON.stringify(entry) + "\n");
|
|
7467
|
+
}
|
|
7468
|
+
|
|
7469
|
+
// src/lib/memory-queue-client.ts
|
|
7470
|
+
async function writeMemoryViaDaemon(entry) {
|
|
7471
|
+
if (process.env.EXE_IS_DAEMON === "1") {
|
|
7472
|
+
enqueueMemory(entry);
|
|
7473
|
+
return false;
|
|
7474
|
+
}
|
|
7475
|
+
if (!isClientConnected()) {
|
|
7476
|
+
enqueueMemory(entry);
|
|
7477
|
+
return false;
|
|
7478
|
+
}
|
|
7479
|
+
try {
|
|
7480
|
+
const response = await sendDaemonRequest({
|
|
7481
|
+
type: "write-memory",
|
|
7482
|
+
entry
|
|
7483
|
+
});
|
|
7484
|
+
if (response.ok) return true;
|
|
7485
|
+
enqueueMemory(entry);
|
|
7486
|
+
return false;
|
|
7487
|
+
} catch {
|
|
7488
|
+
enqueueMemory(entry);
|
|
7489
|
+
return false;
|
|
7490
|
+
}
|
|
7491
|
+
}
|
|
7492
|
+
|
|
7493
|
+
// src/lib/checkpoint-orchestrator.ts
|
|
7494
|
+
function toolNameForReason(reason) {
|
|
7495
|
+
switch (reason) {
|
|
7496
|
+
case "periodic":
|
|
7497
|
+
return "auto-summary";
|
|
7498
|
+
case "session-end":
|
|
7499
|
+
return "SessionEnd";
|
|
7500
|
+
case "pre-compact":
|
|
7501
|
+
return "pre-compact-hook";
|
|
7502
|
+
case "capacity-signal":
|
|
7503
|
+
return "auto-checkpoint";
|
|
7504
|
+
}
|
|
7505
|
+
}
|
|
7506
|
+
function importanceForReason(reason, override) {
|
|
7507
|
+
if (override !== void 0) return override;
|
|
7508
|
+
switch (reason) {
|
|
7509
|
+
case "periodic":
|
|
7510
|
+
return 7;
|
|
7511
|
+
case "session-end":
|
|
7512
|
+
case "pre-compact":
|
|
7513
|
+
case "capacity-signal":
|
|
7514
|
+
return 8;
|
|
7515
|
+
}
|
|
7516
|
+
}
|
|
7517
|
+
function buildContinuityCheckpoint(input) {
|
|
7518
|
+
const { checkpointText, decisionTexts } = buildAutoCheckpoint({
|
|
7519
|
+
agentId: input.agentId,
|
|
7520
|
+
agentRole: input.agentRole,
|
|
7521
|
+
sessionId: input.sessionId,
|
|
7522
|
+
projectName: input.projectName,
|
|
7523
|
+
reason: input.reason,
|
|
7524
|
+
memories: input.memories ?? [],
|
|
7525
|
+
tasks: input.tasks ?? [],
|
|
7526
|
+
maxSamples: input.maxSamples
|
|
7527
|
+
});
|
|
7528
|
+
const extra = input.extraSections?.filter((section) => section.trim().length > 0) ?? [];
|
|
7529
|
+
return {
|
|
7530
|
+
checkpointText: extra.length > 0 ? `${checkpointText}
|
|
7531
|
+
|
|
7532
|
+
${extra.join("\n\n")}` : checkpointText,
|
|
7533
|
+
decisionTexts
|
|
7534
|
+
};
|
|
7535
|
+
}
|
|
7536
|
+
async function writeContinuityCheckpoint(input) {
|
|
7537
|
+
const result = buildContinuityCheckpoint(input);
|
|
7538
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
7539
|
+
await writeMemoryViaDaemon({
|
|
7540
|
+
raw_text: result.checkpointText,
|
|
7541
|
+
agent_id: input.agentId,
|
|
7542
|
+
agent_role: input.agentRole,
|
|
7543
|
+
session_id: input.sessionId,
|
|
7544
|
+
tool_name: toolNameForReason(input.reason),
|
|
7545
|
+
project_name: input.projectName,
|
|
7546
|
+
timestamp: now,
|
|
7547
|
+
importance: importanceForReason(input.reason, input.importance),
|
|
7548
|
+
task_id: input.taskId,
|
|
7549
|
+
memory_type: "checkpoint"
|
|
7550
|
+
});
|
|
7551
|
+
const decisionLimit = input.reason === "periodic" ? 3 : 5;
|
|
7552
|
+
for (const decisionText of result.decisionTexts.slice(0, decisionLimit)) {
|
|
7553
|
+
await writeMemoryViaDaemon({
|
|
7554
|
+
raw_text: decisionText,
|
|
7555
|
+
agent_id: input.agentId,
|
|
7556
|
+
agent_role: input.agentRole,
|
|
7557
|
+
session_id: input.sessionId,
|
|
7558
|
+
tool_name: "auto-decision",
|
|
7559
|
+
project_name: input.projectName,
|
|
7560
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7561
|
+
importance: 8,
|
|
7562
|
+
memory_type: "decision"
|
|
7563
|
+
});
|
|
7564
|
+
}
|
|
7565
|
+
return result;
|
|
7566
|
+
}
|
|
7567
|
+
|
|
7102
7568
|
// src/adapters/claude/hooks/summary-worker.ts
|
|
7103
7569
|
async function main() {
|
|
7104
7570
|
const agentId = process.env.AGENT_ID ?? "default";
|
|
@@ -7157,15 +7623,8 @@ async function main() {
|
|
|
7157
7623
|
taskRows = tasks.rows;
|
|
7158
7624
|
} catch {
|
|
7159
7625
|
}
|
|
7160
|
-
const
|
|
7161
|
-
|
|
7162
|
-
agentRole,
|
|
7163
|
-
sessionId: `auto-summary-${Date.now()}`,
|
|
7164
|
-
projectName: primaryProject,
|
|
7165
|
-
reason: "periodic",
|
|
7166
|
-
memories: result.rows,
|
|
7167
|
-
tasks: taskRows
|
|
7168
|
-
});
|
|
7626
|
+
const summarySessionId = `auto-summary-${Date.now()}`;
|
|
7627
|
+
let summaryText = "";
|
|
7169
7628
|
let limitReached = false;
|
|
7170
7629
|
try {
|
|
7171
7630
|
const { assertMemoryLimit: assertMemoryLimit2 } = await Promise.resolve().then(() => (init_plan_limits(), plan_limits_exports));
|
|
@@ -7183,30 +7642,16 @@ async function main() {
|
|
|
7183
7642
|
}
|
|
7184
7643
|
if (limitReached) {
|
|
7185
7644
|
} else {
|
|
7186
|
-
await
|
|
7187
|
-
|
|
7188
|
-
|
|
7189
|
-
|
|
7190
|
-
|
|
7191
|
-
|
|
7192
|
-
|
|
7193
|
-
|
|
7194
|
-
importance: 7,
|
|
7195
|
-
memory_type: "checkpoint"
|
|
7645
|
+
const checkpointResult = await writeContinuityCheckpoint({
|
|
7646
|
+
agentId,
|
|
7647
|
+
agentRole,
|
|
7648
|
+
sessionId: summarySessionId,
|
|
7649
|
+
projectName: primaryProject,
|
|
7650
|
+
reason: "periodic",
|
|
7651
|
+
memories: result.rows,
|
|
7652
|
+
tasks: taskRows
|
|
7196
7653
|
});
|
|
7197
|
-
|
|
7198
|
-
await writeMemoryViaDaemon({
|
|
7199
|
-
raw_text: decisionText,
|
|
7200
|
-
agent_id: agentId,
|
|
7201
|
-
agent_role: agentRole,
|
|
7202
|
-
session_id: `auto-decision-${Date.now()}`,
|
|
7203
|
-
tool_name: "auto-decision",
|
|
7204
|
-
project_name: primaryProject,
|
|
7205
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7206
|
-
importance: 8,
|
|
7207
|
-
memory_type: "decision"
|
|
7208
|
-
});
|
|
7209
|
-
}
|
|
7654
|
+
summaryText = checkpointResult.checkpointText;
|
|
7210
7655
|
if (!canCoordinate(agentId, agentRole)) {
|
|
7211
7656
|
let totalErrors = 0;
|
|
7212
7657
|
for (const [, data] of projects) {
|