@askexenow/exe-os 0.9.64 → 0.9.66
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 +4 -4
- package/dist/bin/backfill-conversations.js +22 -0
- package/dist/bin/backfill-responses.js +22 -0
- package/dist/bin/backfill-vectors.js +22 -0
- package/dist/bin/cleanup-stale-review-tasks.js +22 -0
- package/dist/bin/cli.js +2280 -1199
- package/dist/bin/exe-agent-config.js +4 -0
- package/dist/bin/exe-agent.js +16 -0
- package/dist/bin/exe-assign.js +22 -0
- package/dist/bin/exe-boot.js +116 -7
- package/dist/bin/exe-call.js +16 -0
- package/dist/bin/exe-cloud.js +6671 -464
- package/dist/bin/exe-dispatch.js +24 -0
- package/dist/bin/exe-doctor.js +2845 -1223
- package/dist/bin/exe-export-behaviors.js +24 -0
- package/dist/bin/exe-forget.js +22 -0
- package/dist/bin/exe-gateway.js +24 -0
- package/dist/bin/exe-heartbeat.js +23 -0
- package/dist/bin/exe-kill.js +22 -0
- package/dist/bin/exe-launch-agent.js +24 -0
- package/dist/bin/exe-link.js +310 -178
- package/dist/bin/exe-new-employee.js +127 -1
- package/dist/bin/exe-pending-messages.js +22 -0
- package/dist/bin/exe-pending-notifications.js +22 -0
- package/dist/bin/exe-pending-reviews.js +22 -0
- package/dist/bin/exe-rename.js +22 -0
- package/dist/bin/exe-review.js +22 -0
- package/dist/bin/exe-search.js +24 -0
- package/dist/bin/exe-session-cleanup.js +24 -0
- package/dist/bin/exe-settings.js +10 -0
- package/dist/bin/exe-start-codex.js +135 -1
- package/dist/bin/exe-start-opencode.js +149 -1
- package/dist/bin/exe-status.js +22 -0
- package/dist/bin/exe-team.js +22 -0
- package/dist/bin/git-sweep.js +24 -0
- package/dist/bin/graph-backfill.js +22 -0
- package/dist/bin/graph-export.js +22 -0
- package/dist/bin/install.js +115 -1
- package/dist/bin/intercom-check.js +24 -0
- package/dist/bin/scan-tasks.js +24 -0
- package/dist/bin/setup.js +412 -157
- package/dist/bin/shard-migrate.js +22 -0
- package/dist/bin/update.js +4 -0
- package/dist/gateway/index.js +24 -0
- package/dist/hooks/bug-report-worker.js +135 -42
- package/dist/hooks/codex-stop-task-finalizer.js +24 -0
- package/dist/hooks/commit-complete.js +24 -0
- package/dist/hooks/error-recall.js +24 -0
- package/dist/hooks/exe-heartbeat-hook.js +4 -0
- package/dist/hooks/ingest-worker.js +4 -0
- package/dist/hooks/ingest.js +23 -0
- package/dist/hooks/instructions-loaded.js +22 -0
- package/dist/hooks/notification.js +22 -0
- package/dist/hooks/post-compact.js +22 -0
- package/dist/hooks/post-tool-combined.js +24 -0
- package/dist/hooks/pre-compact.js +260 -109
- package/dist/hooks/pre-tool-use.js +22 -0
- package/dist/hooks/prompt-submit.js +24 -0
- package/dist/hooks/session-end.js +161 -122
- package/dist/hooks/session-start.js +142 -0
- package/dist/hooks/stop.js +23 -0
- package/dist/hooks/subagent-stop.js +22 -0
- package/dist/hooks/summary-worker.js +195 -79
- package/dist/index.js +24 -0
- package/dist/lib/agent-config.js +4 -0
- package/dist/lib/cloud-sync.js +50 -6
- package/dist/lib/config.js +12 -0
- package/dist/lib/consolidation.js +4 -0
- package/dist/lib/database.js +4 -0
- package/dist/lib/db-daemon-client.js +4 -0
- package/dist/lib/db.js +4 -0
- package/dist/lib/device-registry.js +4 -0
- package/dist/lib/embedder.js +12 -0
- 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 +1144 -480
- package/dist/lib/hybrid-search.js +24 -0
- package/dist/lib/identity.js +4 -0
- package/dist/lib/license.js +4 -0
- package/dist/lib/messaging.js +4 -0
- package/dist/lib/reminders.js +4 -0
- package/dist/lib/schedules.js +22 -0
- package/dist/lib/skill-learning.js +12 -0
- package/dist/lib/status-brief.js +39 -0
- package/dist/lib/store.js +22 -0
- package/dist/lib/task-router.js +4 -0
- package/dist/lib/tasks.js +12 -0
- package/dist/lib/tmux-routing.js +12 -0
- package/dist/lib/token-spend.js +4 -0
- package/dist/mcp/server.js +1045 -427
- package/dist/mcp/tools/complete-reminder.js +4 -0
- package/dist/mcp/tools/create-reminder.js +4 -0
- package/dist/mcp/tools/create-task.js +12 -0
- package/dist/mcp/tools/deactivate-behavior.js +4 -0
- package/dist/mcp/tools/list-reminders.js +4 -0
- package/dist/mcp/tools/list-tasks.js +4 -0
- package/dist/mcp/tools/send-message.js +4 -0
- package/dist/mcp/tools/update-task.js +12 -0
- package/dist/runtime/index.js +24 -0
- package/dist/tui/App.js +24 -0
- package/package.json +3 -2
- package/src/commands/exe/cloud.md +15 -8
- package/src/commands/exe/link.md +7 -6
- package/stack.release.json +2 -2
package/dist/bin/setup.js
CHANGED
|
@@ -139,6 +139,11 @@ function normalizeAutoUpdate(raw) {
|
|
|
139
139
|
const userAU = raw.autoUpdate ?? {};
|
|
140
140
|
raw.autoUpdate = { ...defaultAU, ...userAU };
|
|
141
141
|
}
|
|
142
|
+
function normalizeOrchestration(raw) {
|
|
143
|
+
const defaultOrg = DEFAULT_CONFIG.orchestration;
|
|
144
|
+
const userOrg = raw.orchestration ?? {};
|
|
145
|
+
raw.orchestration = { ...defaultOrg, ...userOrg };
|
|
146
|
+
}
|
|
142
147
|
async function loadConfig() {
|
|
143
148
|
const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
|
|
144
149
|
await ensurePrivateDir(dir);
|
|
@@ -163,6 +168,7 @@ async function loadConfig() {
|
|
|
163
168
|
normalizeScalingRoadmap(migratedCfg);
|
|
164
169
|
normalizeSessionLifecycle(migratedCfg);
|
|
165
170
|
normalizeAutoUpdate(migratedCfg);
|
|
171
|
+
normalizeOrchestration(migratedCfg);
|
|
166
172
|
const config = { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
|
|
167
173
|
if (config.dbPath.startsWith("~")) {
|
|
168
174
|
config.dbPath = config.dbPath.replace(/^~/, os.homedir());
|
|
@@ -186,6 +192,7 @@ function loadConfigSync() {
|
|
|
186
192
|
normalizeScalingRoadmap(migratedCfg);
|
|
187
193
|
normalizeSessionLifecycle(migratedCfg);
|
|
188
194
|
normalizeAutoUpdate(migratedCfg);
|
|
195
|
+
normalizeOrchestration(migratedCfg);
|
|
189
196
|
return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
|
|
190
197
|
} catch {
|
|
191
198
|
return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
|
|
@@ -207,6 +214,7 @@ async function loadConfigFrom(configPath) {
|
|
|
207
214
|
normalizeScalingRoadmap(migratedCfg);
|
|
208
215
|
normalizeSessionLifecycle(migratedCfg);
|
|
209
216
|
normalizeAutoUpdate(migratedCfg);
|
|
217
|
+
normalizeOrchestration(migratedCfg);
|
|
210
218
|
return { ...DEFAULT_CONFIG, ...migratedCfg };
|
|
211
219
|
} catch {
|
|
212
220
|
return { ...DEFAULT_CONFIG };
|
|
@@ -278,6 +286,10 @@ var init_config = __esm({
|
|
|
278
286
|
checkOnBoot: true,
|
|
279
287
|
autoInstall: false,
|
|
280
288
|
checkIntervalMs: 24 * 60 * 60 * 1e3
|
|
289
|
+
},
|
|
290
|
+
orchestration: {
|
|
291
|
+
phase: "phase_1_coo",
|
|
292
|
+
phaseSetBy: "default"
|
|
281
293
|
}
|
|
282
294
|
};
|
|
283
295
|
CONFIG_MIGRATIONS = [
|
|
@@ -415,8 +427,8 @@ function deriveMachineKey() {
|
|
|
415
427
|
}
|
|
416
428
|
function readMachineId() {
|
|
417
429
|
try {
|
|
418
|
-
const { readFileSync:
|
|
419
|
-
return
|
|
430
|
+
const { readFileSync: readFileSync14 } = __require("fs");
|
|
431
|
+
return readFileSync14("/etc/machine-id", "utf-8").trim();
|
|
420
432
|
} catch {
|
|
421
433
|
return "";
|
|
422
434
|
}
|
|
@@ -1129,10 +1141,10 @@ async function disposeEmbedder() {
|
|
|
1129
1141
|
async function embedDirect(text) {
|
|
1130
1142
|
const llamaCpp = await import("node-llama-cpp");
|
|
1131
1143
|
const { MODELS_DIR: MODELS_DIR2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
1132
|
-
const { existsSync:
|
|
1133
|
-
const
|
|
1134
|
-
const modelPath =
|
|
1135
|
-
if (!
|
|
1144
|
+
const { existsSync: existsSync18 } = await import("fs");
|
|
1145
|
+
const path18 = await import("path");
|
|
1146
|
+
const modelPath = path18.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
|
|
1147
|
+
if (!existsSync18(modelPath)) {
|
|
1136
1148
|
throw new Error(`Embedding model not found at ${modelPath}. Run '/exe-setup' to download it.`);
|
|
1137
1149
|
}
|
|
1138
1150
|
const llama = await llamaCpp.getLlama();
|
|
@@ -4503,8 +4515,10 @@ var init_db_backup = __esm({
|
|
|
4503
4515
|
// src/lib/cloud-sync.ts
|
|
4504
4516
|
var cloud_sync_exports = {};
|
|
4505
4517
|
__export(cloud_sync_exports, {
|
|
4518
|
+
CLOUD_RELINK_REQUIRED_MESSAGE: () => CLOUD_RELINK_REQUIRED_MESSAGE,
|
|
4506
4519
|
assertSecureEndpoint: () => assertSecureEndpoint,
|
|
4507
4520
|
buildRosterBlob: () => buildRosterBlob,
|
|
4521
|
+
clearCloudRelinkRequired: () => clearCloudRelinkRequired,
|
|
4508
4522
|
cloudPull: () => cloudPull,
|
|
4509
4523
|
cloudPullBehaviors: () => cloudPullBehaviors,
|
|
4510
4524
|
cloudPullBlob: () => cloudPullBlob,
|
|
@@ -4524,6 +4538,7 @@ __export(cloud_sync_exports, {
|
|
|
4524
4538
|
cloudPushRoster: () => cloudPushRoster,
|
|
4525
4539
|
cloudPushTasks: () => cloudPushTasks,
|
|
4526
4540
|
cloudSync: () => cloudSync,
|
|
4541
|
+
getCloudRelinkRequired: () => getCloudRelinkRequired,
|
|
4527
4542
|
mergeConfig: () => mergeConfig,
|
|
4528
4543
|
mergeRosterFromRemote: () => mergeRosterFromRemote,
|
|
4529
4544
|
pushToPostgres: () => pushToPostgres,
|
|
@@ -4544,31 +4559,43 @@ function logError(msg) {
|
|
|
4544
4559
|
} catch {
|
|
4545
4560
|
}
|
|
4546
4561
|
}
|
|
4562
|
+
function isTruthyEnv(value) {
|
|
4563
|
+
return /^(1|true|yes|on)$/i.test(value ?? "");
|
|
4564
|
+
}
|
|
4547
4565
|
function loadPgClient() {
|
|
4548
4566
|
if (_pgFailed) return null;
|
|
4549
|
-
const postgresUrl = process.env.DATABASE_URL;
|
|
4550
4567
|
const configPath = path12.join(EXE_AI_DIR, "config.json");
|
|
4551
4568
|
let cloudPostgresUrl;
|
|
4569
|
+
let configEnabled = false;
|
|
4552
4570
|
try {
|
|
4553
4571
|
if (existsSync12(configPath)) {
|
|
4554
4572
|
const cfg = JSON.parse(readFileSync8(configPath, "utf8"));
|
|
4555
4573
|
cloudPostgresUrl = cfg.cloud?.postgresUrl;
|
|
4556
|
-
|
|
4557
|
-
_pgFailed = true;
|
|
4558
|
-
return null;
|
|
4559
|
-
}
|
|
4574
|
+
configEnabled = cfg.cloud?.syncToPostgres === true;
|
|
4560
4575
|
}
|
|
4561
4576
|
} catch {
|
|
4562
4577
|
}
|
|
4563
|
-
const
|
|
4578
|
+
const envEnabled = isTruthyEnv(process.env.EXE_CLOUD_SYNC_TO_POSTGRES);
|
|
4579
|
+
if (!envEnabled && !configEnabled) {
|
|
4580
|
+
return null;
|
|
4581
|
+
}
|
|
4582
|
+
const url = process.env.DATABASE_URL || cloudPostgresUrl;
|
|
4564
4583
|
if (!url) {
|
|
4565
4584
|
_pgFailed = true;
|
|
4566
4585
|
return null;
|
|
4567
4586
|
}
|
|
4568
4587
|
if (!_pgPromise) {
|
|
4569
4588
|
_pgPromise = (async () => {
|
|
4589
|
+
if (!process.env.DATABASE_URL) process.env.DATABASE_URL = url;
|
|
4570
4590
|
const { createRequire: createRequire3 } = await import("module");
|
|
4571
4591
|
const { pathToFileURL: pathToFileURL3 } = await import("url");
|
|
4592
|
+
const explicitPath = process.env.EXE_OS_PRISMA_CLIENT_PATH;
|
|
4593
|
+
if (explicitPath) {
|
|
4594
|
+
const mod2 = await import(pathToFileURL3(explicitPath).href);
|
|
4595
|
+
const Ctor2 = mod2.PrismaClient ?? mod2.default?.PrismaClient;
|
|
4596
|
+
if (!Ctor2) throw new Error(`No PrismaClient at ${explicitPath}`);
|
|
4597
|
+
return new Ctor2();
|
|
4598
|
+
}
|
|
4572
4599
|
const exeDbRoot = process.env.EXE_DB_ROOT ?? path12.join(homedir2(), "exe-db");
|
|
4573
4600
|
const req = createRequire3(path12.join(exeDbRoot, "package.json"));
|
|
4574
4601
|
const entry = req.resolve("@prisma/client");
|
|
@@ -4745,6 +4772,24 @@ async function cloudPull(sinceVersion, config) {
|
|
|
4745
4772
|
return { records: [], maxVersion: sinceVersion };
|
|
4746
4773
|
}
|
|
4747
4774
|
}
|
|
4775
|
+
async function getCloudRelinkRequired(client = getClient()) {
|
|
4776
|
+
try {
|
|
4777
|
+
await client.execute("CREATE TABLE IF NOT EXISTS sync_meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)");
|
|
4778
|
+
const relink = await client.execute("SELECT value FROM sync_meta WHERE key = 'cloud_relink_required' LIMIT 1");
|
|
4779
|
+
return String(relink.rows[0]?.value ?? "") === "1";
|
|
4780
|
+
} catch {
|
|
4781
|
+
return false;
|
|
4782
|
+
}
|
|
4783
|
+
}
|
|
4784
|
+
async function clearCloudRelinkRequired(client = getClient()) {
|
|
4785
|
+
await client.execute("CREATE TABLE IF NOT EXISTS sync_meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)");
|
|
4786
|
+
await client.execute("INSERT OR REPLACE INTO sync_meta (key, value) VALUES ('cloud_relink_required', '0')");
|
|
4787
|
+
await client.execute({
|
|
4788
|
+
sql: "INSERT OR REPLACE INTO sync_meta (key, value) VALUES ('cloud_relinked_at', ?)",
|
|
4789
|
+
args: [(/* @__PURE__ */ new Date()).toISOString()]
|
|
4790
|
+
});
|
|
4791
|
+
await client.execute("DELETE FROM sync_meta WHERE key IN ('last_cloud_pull_version', 'last_cloud_push_version')");
|
|
4792
|
+
}
|
|
4748
4793
|
async function cloudSync(config) {
|
|
4749
4794
|
if (!isSyncCryptoInitialized()) {
|
|
4750
4795
|
try {
|
|
@@ -4765,6 +4810,12 @@ async function cloudSync(config) {
|
|
|
4765
4810
|
} catch {
|
|
4766
4811
|
throw new Error("[cloud-sync] Database not initialized. Call initStore() before cloudSync().");
|
|
4767
4812
|
}
|
|
4813
|
+
try {
|
|
4814
|
+
if (await getCloudRelinkRequired(client)) throw new Error(CLOUD_RELINK_REQUIRED_MESSAGE);
|
|
4815
|
+
} catch (err) {
|
|
4816
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
4817
|
+
if (msg.includes("Paused after key rotation")) throw err;
|
|
4818
|
+
}
|
|
4768
4819
|
try {
|
|
4769
4820
|
const { getRawClient: getRawClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
4770
4821
|
await getRawClient2().execute("PRAGMA wal_checkpoint(PASSIVE)");
|
|
@@ -5692,7 +5743,7 @@ async function cloudPullDocuments(config) {
|
|
|
5692
5743
|
}
|
|
5693
5744
|
return { pulled };
|
|
5694
5745
|
}
|
|
5695
|
-
var LOCALHOST_PATTERNS, FETCH_TIMEOUT_MS, PUSH_BATCH_SIZE, ROSTER_LOCK_PATH, LOCK_STALE_MS, _pgPromise, _pgFailed, ROSTER_DELETIONS_PATH;
|
|
5746
|
+
var LOCALHOST_PATTERNS, FETCH_TIMEOUT_MS, PUSH_BATCH_SIZE, ROSTER_LOCK_PATH, LOCK_STALE_MS, _pgPromise, _pgFailed, CLOUD_RELINK_REQUIRED_MESSAGE, ROSTER_DELETIONS_PATH;
|
|
5696
5747
|
var init_cloud_sync = __esm({
|
|
5697
5748
|
"src/lib/cloud-sync.ts"() {
|
|
5698
5749
|
"use strict";
|
|
@@ -5711,43 +5762,194 @@ var init_cloud_sync = __esm({
|
|
|
5711
5762
|
LOCK_STALE_MS = 3e4;
|
|
5712
5763
|
_pgPromise = null;
|
|
5713
5764
|
_pgFailed = false;
|
|
5765
|
+
CLOUD_RELINK_REQUIRED_MESSAGE = "[cloud-sync] Paused after key rotation. Run `exe-os cloud relink --dry-run` for the safe relink checklist.";
|
|
5714
5766
|
ROSTER_DELETIONS_PATH = path12.join(EXE_AI_DIR, "roster-deletions.json");
|
|
5715
5767
|
}
|
|
5716
5768
|
});
|
|
5717
5769
|
|
|
5770
|
+
// src/lib/key-backup-status.ts
|
|
5771
|
+
var key_backup_status_exports = {};
|
|
5772
|
+
__export(key_backup_status_exports, {
|
|
5773
|
+
getKeyBackupStatus: () => getKeyBackupStatus,
|
|
5774
|
+
keyBackupMarkerPath: () => keyBackupMarkerPath,
|
|
5775
|
+
markKeyBackupConfirmed: () => markKeyBackupConfirmed
|
|
5776
|
+
});
|
|
5777
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync6, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "fs";
|
|
5778
|
+
import path13 from "path";
|
|
5779
|
+
function keyBackupMarkerPath() {
|
|
5780
|
+
return path13.join(EXE_AI_DIR, "key-backup-confirmed.json");
|
|
5781
|
+
}
|
|
5782
|
+
function getKeyBackupStatus() {
|
|
5783
|
+
const marker = keyBackupMarkerPath();
|
|
5784
|
+
if (!existsSync13(marker)) return { exists: false };
|
|
5785
|
+
try {
|
|
5786
|
+
const parsed = JSON.parse(readFileSync9(marker, "utf8"));
|
|
5787
|
+
return {
|
|
5788
|
+
exists: true,
|
|
5789
|
+
confirmedAt: parsed.confirmedAt,
|
|
5790
|
+
source: parsed.source
|
|
5791
|
+
};
|
|
5792
|
+
} catch {
|
|
5793
|
+
return { exists: true };
|
|
5794
|
+
}
|
|
5795
|
+
}
|
|
5796
|
+
function markKeyBackupConfirmed(source) {
|
|
5797
|
+
mkdirSync6(EXE_AI_DIR, { recursive: true, mode: 448 });
|
|
5798
|
+
writeFileSync7(
|
|
5799
|
+
keyBackupMarkerPath(),
|
|
5800
|
+
JSON.stringify({ confirmedAt: (/* @__PURE__ */ new Date()).toISOString(), source }, null, 2) + "\n",
|
|
5801
|
+
{ mode: 384 }
|
|
5802
|
+
);
|
|
5803
|
+
}
|
|
5804
|
+
var init_key_backup_status = __esm({
|
|
5805
|
+
"src/lib/key-backup-status.ts"() {
|
|
5806
|
+
"use strict";
|
|
5807
|
+
init_config();
|
|
5808
|
+
}
|
|
5809
|
+
});
|
|
5810
|
+
|
|
5811
|
+
// src/lib/orchestration-phase.ts
|
|
5812
|
+
var orchestration_phase_exports = {};
|
|
5813
|
+
__export(orchestration_phase_exports, {
|
|
5814
|
+
ORCHESTRATION_PHASES: () => ORCHESTRATION_PHASES,
|
|
5815
|
+
applyDefaultOrchestrationPhase: () => applyDefaultOrchestrationPhase,
|
|
5816
|
+
getConfigOrchestrationPhase: () => getConfigOrchestrationPhase,
|
|
5817
|
+
getOrchestrationPhaseInfo: () => getOrchestrationPhaseInfo,
|
|
5818
|
+
loadOrchestrationPhase: () => loadOrchestrationPhase,
|
|
5819
|
+
normalizeOrchestrationPhase: () => normalizeOrchestrationPhase,
|
|
5820
|
+
phaseReminderLine: () => phaseReminderLine,
|
|
5821
|
+
setOrchestrationPhase: () => setOrchestrationPhase
|
|
5822
|
+
});
|
|
5823
|
+
function normalizeOrchestrationPhase(input) {
|
|
5824
|
+
if (typeof input !== "string") return "phase_1_coo";
|
|
5825
|
+
const normalized = input.trim().toLowerCase().replace(/\s+/g, "_");
|
|
5826
|
+
if (["1", "phase1", "phase_1", "coo", "coo_mode", "chief_of_staff", "phase_1_coo"].includes(normalized)) {
|
|
5827
|
+
return "phase_1_coo";
|
|
5828
|
+
}
|
|
5829
|
+
if (["2", "phase2", "phase_2", "executives", "executive", "executive_bench", "phase_2_executives"].includes(normalized)) {
|
|
5830
|
+
return "phase_2_executives";
|
|
5831
|
+
}
|
|
5832
|
+
if (["3", "phase3", "phase_3", "parallel", "parallel_org", "parallel_execution", "phase_3_parallel_org"].includes(normalized)) {
|
|
5833
|
+
return "phase_3_parallel_org";
|
|
5834
|
+
}
|
|
5835
|
+
if (ORCHESTRATION_PHASES.includes(normalized)) return normalized;
|
|
5836
|
+
return "phase_1_coo";
|
|
5837
|
+
}
|
|
5838
|
+
function getOrchestrationPhaseInfo(phase) {
|
|
5839
|
+
return PHASE_INFO[normalizeOrchestrationPhase(phase)];
|
|
5840
|
+
}
|
|
5841
|
+
function getConfigOrchestrationPhase(config) {
|
|
5842
|
+
const orchestration = config.orchestration;
|
|
5843
|
+
return normalizeOrchestrationPhase(orchestration?.phase);
|
|
5844
|
+
}
|
|
5845
|
+
function applyDefaultOrchestrationPhase(config) {
|
|
5846
|
+
if (!config.orchestration) {
|
|
5847
|
+
config.orchestration = {
|
|
5848
|
+
phase: "phase_1_coo",
|
|
5849
|
+
phaseSetAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5850
|
+
phaseSetBy: "setup-default"
|
|
5851
|
+
};
|
|
5852
|
+
return config;
|
|
5853
|
+
}
|
|
5854
|
+
if (!config.orchestration.phase) {
|
|
5855
|
+
config.orchestration = {
|
|
5856
|
+
...config.orchestration,
|
|
5857
|
+
phase: "phase_1_coo",
|
|
5858
|
+
phaseSetAt: config.orchestration.phaseSetAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
5859
|
+
phaseSetBy: config.orchestration.phaseSetBy ?? "setup-default"
|
|
5860
|
+
};
|
|
5861
|
+
}
|
|
5862
|
+
return config;
|
|
5863
|
+
}
|
|
5864
|
+
async function loadOrchestrationPhase() {
|
|
5865
|
+
const config = await loadConfig();
|
|
5866
|
+
return getOrchestrationPhaseInfo(config.orchestration?.phase);
|
|
5867
|
+
}
|
|
5868
|
+
async function setOrchestrationPhase(phaseInput, setBy = "user") {
|
|
5869
|
+
const config = await loadConfig();
|
|
5870
|
+
const phase = normalizeOrchestrationPhase(phaseInput);
|
|
5871
|
+
config.orchestration = {
|
|
5872
|
+
...config.orchestration ?? {},
|
|
5873
|
+
phase,
|
|
5874
|
+
phaseSetAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5875
|
+
phaseSetBy: setBy
|
|
5876
|
+
};
|
|
5877
|
+
await saveConfig(config);
|
|
5878
|
+
return getOrchestrationPhaseInfo(phase);
|
|
5879
|
+
}
|
|
5880
|
+
function phaseReminderLine(phase) {
|
|
5881
|
+
const info = getOrchestrationPhaseInfo(phase);
|
|
5882
|
+
return `${info.shortLabel}: ${info.focus}. ${info.nextSuggestion}`;
|
|
5883
|
+
}
|
|
5884
|
+
var ORCHESTRATION_PHASES, PHASE_INFO;
|
|
5885
|
+
var init_orchestration_phase = __esm({
|
|
5886
|
+
"src/lib/orchestration-phase.ts"() {
|
|
5887
|
+
"use strict";
|
|
5888
|
+
init_config();
|
|
5889
|
+
ORCHESTRATION_PHASES = [
|
|
5890
|
+
"phase_1_coo",
|
|
5891
|
+
"phase_2_executives",
|
|
5892
|
+
"phase_3_parallel_org"
|
|
5893
|
+
];
|
|
5894
|
+
PHASE_INFO = {
|
|
5895
|
+
phase_1_coo: {
|
|
5896
|
+
phase: "phase_1_coo",
|
|
5897
|
+
shortLabel: "Phase 1 \u2014 COO mode",
|
|
5898
|
+
label: "Phase 1 \u2014 COO / Chief of Staff mode",
|
|
5899
|
+
focus: "building company context before delegation",
|
|
5900
|
+
nextSuggestion: "Unlock executives when technical, marketing, ops, legal, or finance work repeats."
|
|
5901
|
+
},
|
|
5902
|
+
phase_2_executives: {
|
|
5903
|
+
phase: "phase_2_executives",
|
|
5904
|
+
shortLabel: "Phase 2 \u2014 Executive bench",
|
|
5905
|
+
label: "Phase 2 \u2014 Executive bench",
|
|
5906
|
+
focus: "COO works with domain executives like CTO/CMO before specialist fan-out",
|
|
5907
|
+
nextSuggestion: "Unlock parallel execution when review gates, permissions, and workflows are ready."
|
|
5908
|
+
},
|
|
5909
|
+
phase_3_parallel_org: {
|
|
5910
|
+
phase: "phase_3_parallel_org",
|
|
5911
|
+
shortLabel: "Phase 3 \u2014 Parallel org",
|
|
5912
|
+
label: "Phase 3 \u2014 Parallel execution org",
|
|
5913
|
+
focus: "executives can delegate to specialists in parallel with review gates",
|
|
5914
|
+
nextSuggestion: "Keep review/CI/permission gates healthy; downgrade anytime if you want simpler COO-only mode."
|
|
5915
|
+
}
|
|
5916
|
+
};
|
|
5917
|
+
}
|
|
5918
|
+
});
|
|
5919
|
+
|
|
5718
5920
|
// src/lib/preferences.ts
|
|
5719
5921
|
var preferences_exports = {};
|
|
5720
5922
|
__export(preferences_exports, {
|
|
5721
5923
|
loadPreferences: () => loadPreferences,
|
|
5722
5924
|
savePreferences: () => savePreferences
|
|
5723
5925
|
});
|
|
5724
|
-
import { existsSync as
|
|
5725
|
-
import
|
|
5926
|
+
import { existsSync as existsSync14, readFileSync as readFileSync10, writeFileSync as writeFileSync8 } from "fs";
|
|
5927
|
+
import path14 from "path";
|
|
5726
5928
|
import os7 from "os";
|
|
5727
5929
|
function loadPreferences(homeDir = os7.homedir()) {
|
|
5728
|
-
const configPath =
|
|
5729
|
-
if (!
|
|
5930
|
+
const configPath = path14.join(homeDir, ".exe-os", "config.json");
|
|
5931
|
+
if (!existsSync14(configPath)) return {};
|
|
5730
5932
|
try {
|
|
5731
|
-
const config = JSON.parse(
|
|
5933
|
+
const config = JSON.parse(readFileSync10(configPath, "utf-8"));
|
|
5732
5934
|
return config.preferences ?? {};
|
|
5733
5935
|
} catch {
|
|
5734
5936
|
return {};
|
|
5735
5937
|
}
|
|
5736
5938
|
}
|
|
5737
5939
|
function savePreferences(prefs, homeDir = os7.homedir()) {
|
|
5738
|
-
const configDir =
|
|
5739
|
-
const configPath =
|
|
5940
|
+
const configDir = path14.join(homeDir, ".exe-os");
|
|
5941
|
+
const configPath = path14.join(configDir, "config.json");
|
|
5740
5942
|
ensurePrivateDirSync(configDir);
|
|
5741
5943
|
let config = {};
|
|
5742
|
-
if (
|
|
5944
|
+
if (existsSync14(configPath)) {
|
|
5743
5945
|
try {
|
|
5744
|
-
config = JSON.parse(
|
|
5946
|
+
config = JSON.parse(readFileSync10(configPath, "utf-8"));
|
|
5745
5947
|
} catch {
|
|
5746
5948
|
config = {};
|
|
5747
5949
|
}
|
|
5748
5950
|
}
|
|
5749
5951
|
config.preferences = prefs;
|
|
5750
|
-
|
|
5952
|
+
writeFileSync8(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
5751
5953
|
enforcePrivateFileSync(configPath);
|
|
5752
5954
|
}
|
|
5753
5955
|
var init_preferences = __esm({
|
|
@@ -5795,6 +5997,12 @@ var init_platform_procedures = __esm({
|
|
|
5795
5997
|
priority: "p0",
|
|
5796
5998
|
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."
|
|
5797
5999
|
},
|
|
6000
|
+
{
|
|
6001
|
+
title: "Customer orchestration maturity \u2014 recommend, never trap",
|
|
6002
|
+
domain: "workflow",
|
|
6003
|
+
priority: "p1",
|
|
6004
|
+
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."
|
|
6005
|
+
},
|
|
5798
6006
|
{
|
|
5799
6007
|
title: "Single dispatch path \u2014 create_task only",
|
|
5800
6008
|
domain: "workflow",
|
|
@@ -5853,6 +6061,12 @@ var init_platform_procedures = __esm({
|
|
|
5853
6061
|
priority: "p0",
|
|
5854
6062
|
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."
|
|
5855
6063
|
},
|
|
6064
|
+
{
|
|
6065
|
+
title: "Commit discipline \u2014 never leave verified work floating",
|
|
6066
|
+
domain: "workflow",
|
|
6067
|
+
priority: "p1",
|
|
6068
|
+
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."
|
|
6069
|
+
},
|
|
5856
6070
|
{
|
|
5857
6071
|
title: "Desktop and TUI are the same product",
|
|
5858
6072
|
domain: "architecture",
|
|
@@ -6620,17 +6834,17 @@ __export(identity_exports, {
|
|
|
6620
6834
|
listIdentities: () => listIdentities,
|
|
6621
6835
|
updateIdentity: () => updateIdentity
|
|
6622
6836
|
});
|
|
6623
|
-
import { existsSync as
|
|
6837
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync7, readFileSync as readFileSync11, writeFileSync as writeFileSync9 } from "fs";
|
|
6624
6838
|
import { readdirSync as readdirSync3 } from "fs";
|
|
6625
|
-
import
|
|
6839
|
+
import path15 from "path";
|
|
6626
6840
|
import { createHash as createHash2 } from "crypto";
|
|
6627
6841
|
function ensureDir() {
|
|
6628
|
-
if (!
|
|
6629
|
-
|
|
6842
|
+
if (!existsSync15(IDENTITY_DIR2)) {
|
|
6843
|
+
mkdirSync7(IDENTITY_DIR2, { recursive: true });
|
|
6630
6844
|
}
|
|
6631
6845
|
}
|
|
6632
6846
|
function identityPath(agentId) {
|
|
6633
|
-
return
|
|
6847
|
+
return path15.join(IDENTITY_DIR2, `${agentId}.md`);
|
|
6634
6848
|
}
|
|
6635
6849
|
function sanitizeIdentityBody(body) {
|
|
6636
6850
|
return body.replace(/<!--[\s\S]*?-->/g, "").trim();
|
|
@@ -6674,8 +6888,8 @@ function contentHash(content) {
|
|
|
6674
6888
|
}
|
|
6675
6889
|
function getIdentity(agentId) {
|
|
6676
6890
|
const filePath = identityPath(agentId);
|
|
6677
|
-
if (!
|
|
6678
|
-
const raw =
|
|
6891
|
+
if (!existsSync15(filePath)) return null;
|
|
6892
|
+
const raw = readFileSync11(filePath, "utf-8");
|
|
6679
6893
|
const { frontmatter, body } = parseFrontmatter(raw);
|
|
6680
6894
|
return {
|
|
6681
6895
|
agentId,
|
|
@@ -6689,7 +6903,7 @@ async function updateIdentity(agentId, content, updatedBy) {
|
|
|
6689
6903
|
ensureDir();
|
|
6690
6904
|
const filePath = identityPath(agentId);
|
|
6691
6905
|
const hash = contentHash(content);
|
|
6692
|
-
|
|
6906
|
+
writeFileSync9(filePath, content, "utf-8");
|
|
6693
6907
|
try {
|
|
6694
6908
|
const client = getClient();
|
|
6695
6909
|
await client.execute({
|
|
@@ -6747,7 +6961,7 @@ var init_identity = __esm({
|
|
|
6747
6961
|
"use strict";
|
|
6748
6962
|
init_config();
|
|
6749
6963
|
init_database();
|
|
6750
|
-
IDENTITY_DIR2 =
|
|
6964
|
+
IDENTITY_DIR2 = path15.join(EXE_AI_DIR, "identity");
|
|
6751
6965
|
}
|
|
6752
6966
|
});
|
|
6753
6967
|
|
|
@@ -7298,36 +7512,36 @@ __export(session_wrappers_exports, {
|
|
|
7298
7512
|
generateSessionWrappers: () => generateSessionWrappers
|
|
7299
7513
|
});
|
|
7300
7514
|
import {
|
|
7301
|
-
existsSync as
|
|
7302
|
-
readFileSync as
|
|
7303
|
-
writeFileSync as
|
|
7304
|
-
mkdirSync as
|
|
7515
|
+
existsSync as existsSync16,
|
|
7516
|
+
readFileSync as readFileSync12,
|
|
7517
|
+
writeFileSync as writeFileSync10,
|
|
7518
|
+
mkdirSync as mkdirSync8,
|
|
7305
7519
|
chmodSync as chmodSync2,
|
|
7306
7520
|
readdirSync as readdirSync4,
|
|
7307
7521
|
unlinkSync as unlinkSync7
|
|
7308
7522
|
} from "fs";
|
|
7309
|
-
import
|
|
7523
|
+
import path16 from "path";
|
|
7310
7524
|
import { homedir as homedir3 } from "os";
|
|
7311
7525
|
function generateSessionWrappers(packageRoot, homeDir) {
|
|
7312
7526
|
const home = homeDir ?? homedir3();
|
|
7313
|
-
const binDir =
|
|
7314
|
-
const rosterPath =
|
|
7315
|
-
|
|
7316
|
-
const exeStartDst =
|
|
7527
|
+
const binDir = path16.join(home, ".exe-os", "bin");
|
|
7528
|
+
const rosterPath = path16.join(home, ".exe-os", "exe-employees.json");
|
|
7529
|
+
mkdirSync8(binDir, { recursive: true });
|
|
7530
|
+
const exeStartDst = path16.join(binDir, "exe-start");
|
|
7317
7531
|
const candidates = [
|
|
7318
|
-
|
|
7319
|
-
|
|
7532
|
+
path16.join(packageRoot, "dist", "bin", "exe-start.sh"),
|
|
7533
|
+
path16.join(packageRoot, "src", "bin", "exe-start.sh")
|
|
7320
7534
|
];
|
|
7321
7535
|
for (const src of candidates) {
|
|
7322
|
-
if (
|
|
7323
|
-
|
|
7536
|
+
if (existsSync16(src)) {
|
|
7537
|
+
writeFileSync10(exeStartDst, readFileSync12(src));
|
|
7324
7538
|
chmodSync2(exeStartDst, 493);
|
|
7325
7539
|
break;
|
|
7326
7540
|
}
|
|
7327
7541
|
}
|
|
7328
7542
|
let employees = [];
|
|
7329
7543
|
try {
|
|
7330
|
-
employees = JSON.parse(
|
|
7544
|
+
employees = JSON.parse(readFileSync12(rosterPath, "utf8"));
|
|
7331
7545
|
} catch {
|
|
7332
7546
|
return { created: 0, pathConfigured: false };
|
|
7333
7547
|
}
|
|
@@ -7337,9 +7551,9 @@ function generateSessionWrappers(packageRoot, homeDir) {
|
|
|
7337
7551
|
try {
|
|
7338
7552
|
for (const f of readdirSync4(binDir)) {
|
|
7339
7553
|
if (f === "exe-start") continue;
|
|
7340
|
-
const fPath =
|
|
7554
|
+
const fPath = path16.join(binDir, f);
|
|
7341
7555
|
try {
|
|
7342
|
-
const content =
|
|
7556
|
+
const content = readFileSync12(fPath, "utf8");
|
|
7343
7557
|
if (content.includes("exe-start")) {
|
|
7344
7558
|
unlinkSync7(fPath);
|
|
7345
7559
|
}
|
|
@@ -7354,34 +7568,34 @@ exec "${exeStartDst}" "$0" "$@"
|
|
|
7354
7568
|
`;
|
|
7355
7569
|
for (const emp of employees) {
|
|
7356
7570
|
for (let n = 1; n <= MAX_N; n++) {
|
|
7357
|
-
const wrapperPath =
|
|
7358
|
-
|
|
7571
|
+
const wrapperPath = path16.join(binDir, `${emp.name}${n}`);
|
|
7572
|
+
writeFileSync10(wrapperPath, wrapperContent);
|
|
7359
7573
|
chmodSync2(wrapperPath, 493);
|
|
7360
7574
|
created++;
|
|
7361
|
-
const codexPath =
|
|
7362
|
-
|
|
7575
|
+
const codexPath = path16.join(binDir, `${emp.name}${n}-codex`);
|
|
7576
|
+
writeFileSync10(codexPath, wrapperContent);
|
|
7363
7577
|
chmodSync2(codexPath, 493);
|
|
7364
7578
|
created++;
|
|
7365
7579
|
}
|
|
7366
7580
|
}
|
|
7367
7581
|
const codexLauncherCandidates = [
|
|
7368
|
-
|
|
7369
|
-
|
|
7582
|
+
path16.join(packageRoot, "dist", "bin", "exe-start-codex.js"),
|
|
7583
|
+
path16.join(packageRoot, "src", "bin", "exe-start-codex.ts")
|
|
7370
7584
|
];
|
|
7371
7585
|
let codexLauncher = null;
|
|
7372
7586
|
for (const c of codexLauncherCandidates) {
|
|
7373
|
-
if (
|
|
7587
|
+
if (existsSync16(c)) {
|
|
7374
7588
|
codexLauncher = c;
|
|
7375
7589
|
break;
|
|
7376
7590
|
}
|
|
7377
7591
|
}
|
|
7378
7592
|
if (codexLauncher) {
|
|
7379
7593
|
for (const emp of employees) {
|
|
7380
|
-
const wrapperPath =
|
|
7594
|
+
const wrapperPath = path16.join(binDir, `${emp.name}-codex`);
|
|
7381
7595
|
const content = `#!/bin/bash
|
|
7382
7596
|
exec node "${codexLauncher}" --agent ${emp.name} "$@"
|
|
7383
7597
|
`;
|
|
7384
|
-
|
|
7598
|
+
writeFileSync10(wrapperPath, content);
|
|
7385
7599
|
chmodSync2(wrapperPath, 493);
|
|
7386
7600
|
created++;
|
|
7387
7601
|
}
|
|
@@ -7400,24 +7614,24 @@ export PATH="${binDir}:$PATH"
|
|
|
7400
7614
|
const shell = process.env.SHELL ?? "/bin/bash";
|
|
7401
7615
|
const profilePaths = [];
|
|
7402
7616
|
if (shell.includes("zsh")) {
|
|
7403
|
-
profilePaths.push(
|
|
7617
|
+
profilePaths.push(path16.join(home, ".zshrc"));
|
|
7404
7618
|
} else if (shell.includes("bash")) {
|
|
7405
|
-
profilePaths.push(
|
|
7406
|
-
profilePaths.push(
|
|
7619
|
+
profilePaths.push(path16.join(home, ".bashrc"));
|
|
7620
|
+
profilePaths.push(path16.join(home, ".bash_profile"));
|
|
7407
7621
|
} else {
|
|
7408
|
-
profilePaths.push(
|
|
7622
|
+
profilePaths.push(path16.join(home, ".profile"));
|
|
7409
7623
|
}
|
|
7410
7624
|
for (const profilePath of profilePaths) {
|
|
7411
7625
|
try {
|
|
7412
7626
|
let content = "";
|
|
7413
7627
|
try {
|
|
7414
|
-
content =
|
|
7628
|
+
content = readFileSync12(profilePath, "utf8");
|
|
7415
7629
|
} catch {
|
|
7416
7630
|
}
|
|
7417
7631
|
if (content.includes(".exe-os/bin")) {
|
|
7418
7632
|
return false;
|
|
7419
7633
|
}
|
|
7420
|
-
|
|
7634
|
+
writeFileSync10(profilePath, content + exportLine);
|
|
7421
7635
|
return true;
|
|
7422
7636
|
} catch {
|
|
7423
7637
|
continue;
|
|
@@ -7437,9 +7651,9 @@ var init_session_wrappers = __esm({
|
|
|
7437
7651
|
init_config();
|
|
7438
7652
|
init_keychain();
|
|
7439
7653
|
import crypto4 from "crypto";
|
|
7440
|
-
import { existsSync as
|
|
7654
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync9, readFileSync as readFileSync13, writeFileSync as writeFileSync11, unlinkSync as unlinkSync8 } from "fs";
|
|
7441
7655
|
import os8 from "os";
|
|
7442
|
-
import
|
|
7656
|
+
import path17 from "path";
|
|
7443
7657
|
import { createInterface } from "readline";
|
|
7444
7658
|
|
|
7445
7659
|
// src/lib/model-downloader.ts
|
|
@@ -7531,32 +7745,32 @@ async function fileHash(filePath) {
|
|
|
7531
7745
|
|
|
7532
7746
|
// src/lib/setup-wizard.ts
|
|
7533
7747
|
function findPackageRoot2() {
|
|
7534
|
-
let dir =
|
|
7535
|
-
const root =
|
|
7748
|
+
let dir = path17.dirname(new URL(import.meta.url).pathname);
|
|
7749
|
+
const root = path17.parse(dir).root;
|
|
7536
7750
|
while (dir !== root) {
|
|
7537
|
-
const pkgPath =
|
|
7538
|
-
if (
|
|
7751
|
+
const pkgPath = path17.join(dir, "package.json");
|
|
7752
|
+
if (existsSync17(pkgPath)) {
|
|
7539
7753
|
try {
|
|
7540
|
-
const pkg = JSON.parse(
|
|
7754
|
+
const pkg = JSON.parse(readFileSync13(pkgPath, "utf-8"));
|
|
7541
7755
|
if (pkg.name === "@askexenow/exe-os" || pkg.name === "exe-os") return dir;
|
|
7542
7756
|
} catch {
|
|
7543
7757
|
}
|
|
7544
7758
|
}
|
|
7545
|
-
dir =
|
|
7759
|
+
dir = path17.dirname(dir);
|
|
7546
7760
|
}
|
|
7547
7761
|
return null;
|
|
7548
7762
|
}
|
|
7549
|
-
var SETUP_STATE_PATH =
|
|
7763
|
+
var SETUP_STATE_PATH = path17.join(os8.homedir(), ".exe-os", "setup-state.json");
|
|
7550
7764
|
function loadSetupState() {
|
|
7551
7765
|
try {
|
|
7552
|
-
return JSON.parse(
|
|
7766
|
+
return JSON.parse(readFileSync13(SETUP_STATE_PATH, "utf8"));
|
|
7553
7767
|
} catch {
|
|
7554
7768
|
return { completedSteps: [], startedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
7555
7769
|
}
|
|
7556
7770
|
}
|
|
7557
7771
|
function saveSetupState(state) {
|
|
7558
|
-
|
|
7559
|
-
|
|
7772
|
+
mkdirSync9(path17.dirname(SETUP_STATE_PATH), { recursive: true });
|
|
7773
|
+
writeFileSync11(SETUP_STATE_PATH, JSON.stringify(state, null, 2));
|
|
7560
7774
|
}
|
|
7561
7775
|
function clearSetupState() {
|
|
7562
7776
|
try {
|
|
@@ -7606,8 +7820,8 @@ async function validateModel(log) {
|
|
|
7606
7820
|
if (totalGB <= 8 || isLowMemory()) {
|
|
7607
7821
|
log(`System memory: ${totalGB.toFixed(0)}GB total, ${freeGB.toFixed(1)}GB free`);
|
|
7608
7822
|
log("Skipping in-memory model validation (low memory \u2014 will validate on first use).");
|
|
7609
|
-
const modelPath =
|
|
7610
|
-
if (
|
|
7823
|
+
const modelPath = path17.join(MODELS_DIR, LOCAL_FILENAME);
|
|
7824
|
+
if (existsSync17(modelPath)) {
|
|
7611
7825
|
const { statSync: statSync4 } = await import("fs");
|
|
7612
7826
|
const size = statSync4(modelPath).size;
|
|
7613
7827
|
if (size > 300 * 1e6) {
|
|
@@ -7638,10 +7852,10 @@ async function runSetupWizard(opts = {}) {
|
|
|
7638
7852
|
log("");
|
|
7639
7853
|
log("=== exe-os Setup ===");
|
|
7640
7854
|
log("");
|
|
7641
|
-
log("
|
|
7855
|
+
log("What are you setting up?");
|
|
7642
7856
|
log("");
|
|
7643
|
-
log(" [1]
|
|
7644
|
-
log(" [2]
|
|
7857
|
+
log(" [1] First device / brand new Exe OS memory");
|
|
7858
|
+
log(" [2] Another device / I already have a 24-word recovery phrase");
|
|
7645
7859
|
log("");
|
|
7646
7860
|
const installType = await ask(rl, "Choice (1/2): ");
|
|
7647
7861
|
let isPairing = false;
|
|
@@ -7650,16 +7864,20 @@ async function runSetupWizard(opts = {}) {
|
|
|
7650
7864
|
isPairing = true;
|
|
7651
7865
|
log("");
|
|
7652
7866
|
const { importMnemonic: importMnemonic2 } = await Promise.resolve().then(() => (init_keychain(), keychain_exports));
|
|
7653
|
-
|
|
7867
|
+
log("On your existing device, open Terminal and run:");
|
|
7868
|
+
log(" exe-os cloud link --show-full");
|
|
7869
|
+
log("Then copy the 24-word phrase here.");
|
|
7870
|
+
log("");
|
|
7871
|
+
const mnemonic = await ask(rl, "Paste the 24-word recovery phrase: ");
|
|
7654
7872
|
try {
|
|
7655
7873
|
const key = await importMnemonic2(mnemonic);
|
|
7656
7874
|
await setMasterKey(key);
|
|
7657
7875
|
log("Master key imported and stored securely.");
|
|
7658
7876
|
log("");
|
|
7659
|
-
log("
|
|
7660
|
-
log("
|
|
7877
|
+
log("Now paste the Cloud API key from that same `exe-os cloud link --show-full` output.");
|
|
7878
|
+
log("It starts with: exe_sk_");
|
|
7661
7879
|
log("");
|
|
7662
|
-
const apiKey = await ask(rl, "API key (exe_sk_
|
|
7880
|
+
const apiKey = await ask(rl, "Cloud API key (starts with exe_sk_): ");
|
|
7663
7881
|
if (apiKey && apiKey.startsWith("exe_sk_")) {
|
|
7664
7882
|
const cloudEndpoint = "https://askexe.com/cloud";
|
|
7665
7883
|
const cloudCfg = { apiKey, endpoint: cloudEndpoint };
|
|
@@ -7698,7 +7916,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
7698
7916
|
if (state.completedSteps.length > 0) {
|
|
7699
7917
|
log(`Resuming setup from step ${Math.max(...state.completedSteps) + 1}...`);
|
|
7700
7918
|
}
|
|
7701
|
-
if (
|
|
7919
|
+
if (existsSync17(LEGACY_LANCE_PATH)) {
|
|
7702
7920
|
log("\u26A0 Found v1.0 LanceDB at ~/.exe-os/local.lance");
|
|
7703
7921
|
log(" v1.1 uses libSQL (SQLite). Your existing memories are not automatically migrated.");
|
|
7704
7922
|
log(" The old directory will not be modified or deleted.");
|
|
@@ -7722,14 +7940,22 @@ async function runSetupWizard(opts = {}) {
|
|
|
7722
7940
|
log("");
|
|
7723
7941
|
log(" " + mnemonic);
|
|
7724
7942
|
log("");
|
|
7725
|
-
log(" SAVE THIS NOW
|
|
7726
|
-
log("
|
|
7727
|
-
log("
|
|
7943
|
+
log(" SAVE THIS NOW before continuing.");
|
|
7944
|
+
log(" Best: put it in your password manager, or write it down and keep it safe.");
|
|
7945
|
+
log(" This phrase is the ONLY way to decrypt your memories if you lose this computer.");
|
|
7946
|
+
log(" We cannot recover it for you.");
|
|
7728
7947
|
log("");
|
|
7729
7948
|
log(" Like a Bitcoin wallet \u2014 lose the phrase, lose everything.");
|
|
7730
7949
|
log("=============================================================");
|
|
7731
7950
|
log("");
|
|
7732
|
-
await ask(rl, "
|
|
7951
|
+
const confirmation = await ask(rl, 'Type "I SAVED MY RECOVERY PHRASE" after you have saved it: ');
|
|
7952
|
+
if (confirmation !== "I SAVED MY RECOVERY PHRASE") {
|
|
7953
|
+
throw new Error(
|
|
7954
|
+
"Setup cancelled: recovery phrase was not confirmed. Save the 24-word phrase before continuing \u2014 it is required to recover encrypted memories."
|
|
7955
|
+
);
|
|
7956
|
+
}
|
|
7957
|
+
const { markKeyBackupConfirmed: markKeyBackupConfirmed2 } = await Promise.resolve().then(() => (init_key_backup_status(), key_backup_status_exports));
|
|
7958
|
+
markKeyBackupConfirmed2("setup-wizard");
|
|
7733
7959
|
}
|
|
7734
7960
|
state.completedSteps.push(1);
|
|
7735
7961
|
saveSetupState(state);
|
|
@@ -7876,13 +8102,15 @@ async function runSetupWizard(opts = {}) {
|
|
|
7876
8102
|
if (cloudConfig) {
|
|
7877
8103
|
config.cloud = cloudConfig;
|
|
7878
8104
|
}
|
|
8105
|
+
const { applyDefaultOrchestrationPhase: applyDefaultOrchestrationPhase2 } = await Promise.resolve().then(() => (init_orchestration_phase(), orchestration_phase_exports));
|
|
8106
|
+
applyDefaultOrchestrationPhase2(config);
|
|
7879
8107
|
await saveConfig(config);
|
|
7880
8108
|
log("");
|
|
7881
8109
|
try {
|
|
7882
|
-
const claudeJsonPath =
|
|
8110
|
+
const claudeJsonPath = path17.join(os8.homedir(), ".claude.json");
|
|
7883
8111
|
let claudeJson = {};
|
|
7884
8112
|
try {
|
|
7885
|
-
claudeJson = JSON.parse(
|
|
8113
|
+
claudeJson = JSON.parse(readFileSync13(claudeJsonPath, "utf8"));
|
|
7886
8114
|
} catch {
|
|
7887
8115
|
}
|
|
7888
8116
|
if (!claudeJson.projects) claudeJson.projects = {};
|
|
@@ -7891,7 +8119,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
7891
8119
|
if (!projects[dir]) projects[dir] = {};
|
|
7892
8120
|
projects[dir].hasTrustDialogAccepted = true;
|
|
7893
8121
|
}
|
|
7894
|
-
|
|
8122
|
+
writeFileSync11(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
|
|
7895
8123
|
} catch {
|
|
7896
8124
|
}
|
|
7897
8125
|
state.completedSteps.push(5);
|
|
@@ -7905,7 +8133,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
7905
8133
|
const prefs = { ...existingPrefs };
|
|
7906
8134
|
log("=== Config Defaults ===");
|
|
7907
8135
|
log("");
|
|
7908
|
-
const ghosttyDetected =
|
|
8136
|
+
const ghosttyDetected = existsSync17(path17.join(os8.homedir(), ".config", "ghostty")) || existsSync17(path17.join(os8.homedir(), "Library", "Application Support", "com.mitchellh.ghostty"));
|
|
7909
8137
|
if (ghosttyDetected) {
|
|
7910
8138
|
const ghosttyAnswer = await ask(rl, "Detected Ghostty terminal. Use exe-os Ghostty defaults? (Y/n) ");
|
|
7911
8139
|
prefs.ghostty = ghosttyAnswer.toLowerCase() !== "n";
|
|
@@ -7952,7 +8180,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
7952
8180
|
let missingIdentities = [];
|
|
7953
8181
|
for (const emp of roster) {
|
|
7954
8182
|
const idPath = identityPath2(emp.name);
|
|
7955
|
-
if (!
|
|
8183
|
+
if (!existsSync17(idPath)) {
|
|
7956
8184
|
missingIdentities.push(emp.name);
|
|
7957
8185
|
}
|
|
7958
8186
|
}
|
|
@@ -7984,7 +8212,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
7984
8212
|
}
|
|
7985
8213
|
missingIdentities = [];
|
|
7986
8214
|
for (const emp of roster) {
|
|
7987
|
-
if (!
|
|
8215
|
+
if (!existsSync17(identityPath2(emp.name))) {
|
|
7988
8216
|
missingIdentities.push(emp.name);
|
|
7989
8217
|
}
|
|
7990
8218
|
}
|
|
@@ -8043,9 +8271,9 @@ async function runSetupWizard(opts = {}) {
|
|
|
8043
8271
|
const cooIdentityContent = getIdentityTemplate("coo");
|
|
8044
8272
|
if (cooIdentityContent) {
|
|
8045
8273
|
const cooIdPath = identityPath2(cooName);
|
|
8046
|
-
|
|
8274
|
+
mkdirSync9(path17.dirname(cooIdPath), { recursive: true });
|
|
8047
8275
|
const replaced = cooIdentityContent.replace(/agent_id:\s*exe/g, `agent_id: ${cooName}`).replace(/\$\{agent_id\}/g, cooName);
|
|
8048
|
-
|
|
8276
|
+
writeFileSync11(cooIdPath, replaced, "utf-8");
|
|
8049
8277
|
}
|
|
8050
8278
|
registerBinSymlinks2(cooName);
|
|
8051
8279
|
createdEmployees.push({ name: cooName, role: "COO" });
|
|
@@ -8096,7 +8324,8 @@ async function runSetupWizard(opts = {}) {
|
|
|
8096
8324
|
}
|
|
8097
8325
|
if (!isLicensed) {
|
|
8098
8326
|
log("");
|
|
8099
|
-
log("You're all set.
|
|
8327
|
+
log("You're all set. You're starting in Phase 1: COO / Chief of Staff mode.");
|
|
8328
|
+
log("Your COO will learn your company context first. You can unlock executives later anytime.");
|
|
8100
8329
|
log("When you're ready for specialists, add a license key at askexe.com.");
|
|
8101
8330
|
log("");
|
|
8102
8331
|
log(`Type your COO's name to start: /${cooName}`);
|
|
@@ -8111,67 +8340,89 @@ async function runSetupWizard(opts = {}) {
|
|
|
8111
8340
|
}
|
|
8112
8341
|
if (!state.completedSteps.includes(8)) {
|
|
8113
8342
|
let employees = await loadEmployees2(EMPLOYEES_PATH2).catch(() => []);
|
|
8114
|
-
log("===
|
|
8343
|
+
log("=== Orchestration Phase ===");
|
|
8115
8344
|
log("");
|
|
8116
|
-
log("
|
|
8117
|
-
log("
|
|
8345
|
+
log("Recommended default: Phase 1 \u2014 COO / Chief of Staff mode.");
|
|
8346
|
+
log("Start with one-on-one conversations so your COO learns your company,");
|
|
8347
|
+
log("vision, priorities, constraints, and operating style before delegating.");
|
|
8118
8348
|
log("");
|
|
8119
|
-
|
|
8120
|
-
const ctoDefault = ctoTemplate?.name ?? "cto";
|
|
8121
|
-
log(` CTO \u2014 engineering, architecture, code reviews (default: ${ctoDefault})`);
|
|
8122
|
-
const cmoTemplate = getTemplateByRole2("CMO");
|
|
8123
|
-
const cmoDefault = cmoTemplate?.name ?? "cmo";
|
|
8124
|
-
log(` CMO \u2014 design, brand, content, marketing (default: ${cmoDefault})`);
|
|
8349
|
+
log("You can jump ahead now if you want. This is a suggestion, not a blocker.");
|
|
8125
8350
|
log("");
|
|
8126
|
-
|
|
8127
|
-
|
|
8128
|
-
|
|
8129
|
-
const ctoEmployee = {
|
|
8130
|
-
name: ctoName,
|
|
8131
|
-
role: "CTO",
|
|
8132
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8133
|
-
templateName: ctoDefault,
|
|
8134
|
-
templateVersion: 1
|
|
8135
|
-
};
|
|
8136
|
-
employees = addEmployee2(employees, ctoEmployee);
|
|
8137
|
-
await saveEmployees2(employees, EMPLOYEES_PATH2);
|
|
8138
|
-
}
|
|
8139
|
-
const ctoIdentityContent = getIdentityTemplate("cto");
|
|
8140
|
-
if (ctoIdentityContent) {
|
|
8141
|
-
const ctoIdPath = identityPath2(ctoName);
|
|
8142
|
-
mkdirSync8(path16.dirname(ctoIdPath), { recursive: true });
|
|
8143
|
-
const replaced = ctoIdentityContent.replace(/agent_id:\s*\w+/g, `agent_id: ${ctoName}`).replace(/\$\{agent_id\}/g, ctoName);
|
|
8144
|
-
writeFileSync10(ctoIdPath, replaced, "utf-8");
|
|
8145
|
-
}
|
|
8146
|
-
registerBinSymlinks2(ctoName);
|
|
8147
|
-
createdEmployees.push({ name: ctoName, role: "CTO" });
|
|
8148
|
-
log(`Created ${ctoName} (CTO)`);
|
|
8149
|
-
const cmoNameInput = await ask(rl, `Name your CMO (default: ${cmoDefault}): `);
|
|
8150
|
-
const cmoName = (cmoNameInput || cmoDefault).toLowerCase();
|
|
8151
|
-
if (!employees.some((e) => e.name === cmoName)) {
|
|
8152
|
-
const cmoEmployee = {
|
|
8153
|
-
name: cmoName,
|
|
8154
|
-
role: "CMO",
|
|
8155
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8156
|
-
templateName: cmoDefault,
|
|
8157
|
-
templateVersion: 1
|
|
8158
|
-
};
|
|
8159
|
-
employees = addEmployee2(employees, cmoEmployee);
|
|
8160
|
-
await saveEmployees2(employees, EMPLOYEES_PATH2);
|
|
8161
|
-
}
|
|
8162
|
-
const cmoIdentityContent = getIdentityTemplate("cmo");
|
|
8163
|
-
if (cmoIdentityContent) {
|
|
8164
|
-
const cmoIdPath = identityPath2(cmoName);
|
|
8165
|
-
mkdirSync8(path16.dirname(cmoIdPath), { recursive: true });
|
|
8166
|
-
const replaced = cmoIdentityContent.replace(/agent_id:\s*\w+/g, `agent_id: ${cmoName}`).replace(/\$\{agent_id\}/g, cmoName);
|
|
8167
|
-
writeFileSync10(cmoIdPath, replaced, "utf-8");
|
|
8168
|
-
}
|
|
8169
|
-
registerBinSymlinks2(cmoName);
|
|
8170
|
-
createdEmployees.push({ name: cmoName, role: "CMO" });
|
|
8171
|
-
log(`Created ${cmoName} (CMO)`);
|
|
8351
|
+
log(" Phase 1: COO only \u2014 build company context first");
|
|
8352
|
+
log(" Phase 2: Executive bench \u2014 add CTO/CMO for repeated domain work");
|
|
8353
|
+
log(" Phase 3: Parallel org \u2014 specialists execute in parallel with reviews");
|
|
8172
8354
|
log("");
|
|
8173
|
-
|
|
8174
|
-
|
|
8355
|
+
const unlockExecutives = (await ask(rl, "Unlock Phase 2 executives now? (y/N): ")).toLowerCase() === "y";
|
|
8356
|
+
const { setOrchestrationPhase: setOrchestrationPhase2 } = await Promise.resolve().then(() => (init_orchestration_phase(), orchestration_phase_exports));
|
|
8357
|
+
if (!unlockExecutives) {
|
|
8358
|
+
await setOrchestrationPhase2("phase_1_coo", "setup-wizard");
|
|
8359
|
+
log("");
|
|
8360
|
+
log("Starting in Phase 1. Your executive templates are available when you're ready.");
|
|
8361
|
+
log("Later: run `exe-os org unlock executives` to move to Phase 2.");
|
|
8362
|
+
state.completedSteps.push(8);
|
|
8363
|
+
saveSetupState(state);
|
|
8364
|
+
} else {
|
|
8365
|
+
await setOrchestrationPhase2("phase_2_executives", "setup-wizard");
|
|
8366
|
+
log("");
|
|
8367
|
+
log("Phase 2 enabled. Let's name your executive bench.");
|
|
8368
|
+
log("");
|
|
8369
|
+
const ctoTemplate = getTemplateByRole2("CTO");
|
|
8370
|
+
const ctoDefault = ctoTemplate?.name ?? "cto";
|
|
8371
|
+
log(` CTO \u2014 engineering, architecture, code reviews (default: ${ctoDefault})`);
|
|
8372
|
+
const cmoTemplate = getTemplateByRole2("CMO");
|
|
8373
|
+
const cmoDefault = cmoTemplate?.name ?? "cmo";
|
|
8374
|
+
log(` CMO \u2014 design, brand, content, marketing (default: ${cmoDefault})`);
|
|
8375
|
+
log("");
|
|
8376
|
+
const ctoNameInput = await ask(rl, `Name your CTO (default: ${ctoDefault}): `);
|
|
8377
|
+
const ctoName = (ctoNameInput || ctoDefault).toLowerCase();
|
|
8378
|
+
if (!employees.some((e) => e.name === ctoName)) {
|
|
8379
|
+
const ctoEmployee = {
|
|
8380
|
+
name: ctoName,
|
|
8381
|
+
role: "CTO",
|
|
8382
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8383
|
+
templateName: ctoDefault,
|
|
8384
|
+
templateVersion: 1
|
|
8385
|
+
};
|
|
8386
|
+
employees = addEmployee2(employees, ctoEmployee);
|
|
8387
|
+
await saveEmployees2(employees, EMPLOYEES_PATH2);
|
|
8388
|
+
}
|
|
8389
|
+
const ctoIdentityContent = getIdentityTemplate("cto");
|
|
8390
|
+
if (ctoIdentityContent) {
|
|
8391
|
+
const ctoIdPath = identityPath2(ctoName);
|
|
8392
|
+
mkdirSync9(path17.dirname(ctoIdPath), { recursive: true });
|
|
8393
|
+
const replaced = ctoIdentityContent.replace(/agent_id:\s*\w+/g, `agent_id: ${ctoName}`).replace(/\$\{agent_id\}/g, ctoName);
|
|
8394
|
+
writeFileSync11(ctoIdPath, replaced, "utf-8");
|
|
8395
|
+
}
|
|
8396
|
+
registerBinSymlinks2(ctoName);
|
|
8397
|
+
createdEmployees.push({ name: ctoName, role: "CTO" });
|
|
8398
|
+
log(`Created ${ctoName} (CTO)`);
|
|
8399
|
+
const cmoNameInput = await ask(rl, `Name your CMO (default: ${cmoDefault}): `);
|
|
8400
|
+
const cmoName = (cmoNameInput || cmoDefault).toLowerCase();
|
|
8401
|
+
if (!employees.some((e) => e.name === cmoName)) {
|
|
8402
|
+
const cmoEmployee = {
|
|
8403
|
+
name: cmoName,
|
|
8404
|
+
role: "CMO",
|
|
8405
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8406
|
+
templateName: cmoDefault,
|
|
8407
|
+
templateVersion: 1
|
|
8408
|
+
};
|
|
8409
|
+
employees = addEmployee2(employees, cmoEmployee);
|
|
8410
|
+
await saveEmployees2(employees, EMPLOYEES_PATH2);
|
|
8411
|
+
}
|
|
8412
|
+
const cmoIdentityContent = getIdentityTemplate("cmo");
|
|
8413
|
+
if (cmoIdentityContent) {
|
|
8414
|
+
const cmoIdPath = identityPath2(cmoName);
|
|
8415
|
+
mkdirSync9(path17.dirname(cmoIdPath), { recursive: true });
|
|
8416
|
+
const replaced = cmoIdentityContent.replace(/agent_id:\s*\w+/g, `agent_id: ${cmoName}`).replace(/\$\{agent_id\}/g, cmoName);
|
|
8417
|
+
writeFileSync11(cmoIdPath, replaced, "utf-8");
|
|
8418
|
+
}
|
|
8419
|
+
registerBinSymlinks2(cmoName);
|
|
8420
|
+
createdEmployees.push({ name: cmoName, role: "CMO" });
|
|
8421
|
+
log(`Created ${cmoName} (CMO)`);
|
|
8422
|
+
log("");
|
|
8423
|
+
state.completedSteps.push(8);
|
|
8424
|
+
saveSetupState(state);
|
|
8425
|
+
}
|
|
8175
8426
|
} else {
|
|
8176
8427
|
log("Step 8 already complete \u2014 skipping.");
|
|
8177
8428
|
}
|
|
@@ -8186,7 +8437,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
8186
8437
|
log(`Session shortcuts generated (${cooName}1, ${cooName}2, ...)`);
|
|
8187
8438
|
}
|
|
8188
8439
|
if (wrapResult.pathConfigured) {
|
|
8189
|
-
const binDir =
|
|
8440
|
+
const binDir = path17.join(os8.homedir(), ".exe-os", "bin");
|
|
8190
8441
|
process.env.PATH = `${binDir}:${process.env.PATH ?? ""}`;
|
|
8191
8442
|
pathJustConfigured = true;
|
|
8192
8443
|
}
|
|
@@ -8229,7 +8480,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
8229
8480
|
const pkgRoot2 = findPackageRoot2();
|
|
8230
8481
|
if (pkgRoot2) {
|
|
8231
8482
|
try {
|
|
8232
|
-
version = JSON.parse(
|
|
8483
|
+
version = JSON.parse(readFileSync13(path17.join(pkgRoot2, "package.json"), "utf-8")).version;
|
|
8233
8484
|
} catch {
|
|
8234
8485
|
}
|
|
8235
8486
|
}
|
|
@@ -8243,6 +8494,10 @@ async function runSetupWizard(opts = {}) {
|
|
|
8243
8494
|
log("");
|
|
8244
8495
|
log("=== Next Steps ===");
|
|
8245
8496
|
log("");
|
|
8497
|
+
log(" Recommended start: Phase 1 \u2014 talk to your COO first");
|
|
8498
|
+
log(" Check/change phase: exe-os org phase");
|
|
8499
|
+
log(" Unlock executives later: exe-os org unlock executives");
|
|
8500
|
+
log("");
|
|
8246
8501
|
log(` cd into a project folder: cd ~/my-project`);
|
|
8247
8502
|
log(` Launch your COO: ${cooName}1`);
|
|
8248
8503
|
if (pathJustConfigured) {
|