@askexenow/exe-os 0.9.2 → 0.9.4
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/dist/bin/cli.js +1075 -575
- package/dist/bin/exe-agent.js +4 -4
- package/dist/bin/exe-boot.js +4 -4
- package/dist/bin/exe-call.js +4 -4
- package/dist/bin/exe-launch-agent.js +4 -4
- package/dist/bin/exe-new-employee.js +23 -4
- package/dist/bin/install.js +23 -4
- package/dist/bin/setup.js +4 -4
- package/dist/lib/employee-templates.js +4 -4
- package/dist/mcp/server.js +34 -12
- package/dist/tui/App.js +4 -4
- package/package.json +1 -1
package/dist/bin/cli.js
CHANGED
|
@@ -1322,20 +1322,39 @@ function setupGhostty(home) {
|
|
|
1322
1322
|
const configPath = path5.join(configDir, "config");
|
|
1323
1323
|
const backupPath = path5.join(configDir, "config.backup");
|
|
1324
1324
|
mkdirSync3(configDir, { recursive: true });
|
|
1325
|
+
const START_MARKER = "# \u2500\u2500 exe-os:ghostty-start \u2500\u2500";
|
|
1326
|
+
const END_MARKER = "# \u2500\u2500 exe-os:ghostty-end \u2500\u2500";
|
|
1327
|
+
const assetContent = readFileSync4(assetPath, "utf8").trim();
|
|
1328
|
+
const markedSection = `${START_MARKER}
|
|
1329
|
+
${assetContent}
|
|
1330
|
+
${END_MARKER}`;
|
|
1325
1331
|
if (existsSync5(configPath)) {
|
|
1326
1332
|
const existing = readFileSync4(configPath, "utf8");
|
|
1327
|
-
if (existing.includes(
|
|
1328
|
-
|
|
1333
|
+
if (existing.includes(START_MARKER) && existing.includes(END_MARKER)) {
|
|
1334
|
+
const before = existing.slice(0, existing.indexOf(START_MARKER));
|
|
1335
|
+
const after = existing.slice(existing.indexOf(END_MARKER) + END_MARKER.length);
|
|
1336
|
+
writeFileSync3(configPath, `${before}${markedSection}${after}`);
|
|
1337
|
+
} else if (existing.includes("Exe OS")) {
|
|
1338
|
+
if (!existsSync5(backupPath)) {
|
|
1339
|
+
copyFileSync(configPath, backupPath);
|
|
1340
|
+
process.stderr.write(`exe-os: backed up existing Ghostty config to ${backupPath}
|
|
1341
|
+
`);
|
|
1342
|
+
}
|
|
1343
|
+
writeFileSync3(configPath, `${markedSection}
|
|
1344
|
+
`);
|
|
1329
1345
|
} else {
|
|
1330
1346
|
if (!existsSync5(backupPath)) {
|
|
1331
1347
|
copyFileSync(configPath, backupPath);
|
|
1332
1348
|
process.stderr.write(`exe-os: backed up existing Ghostty config to ${backupPath}
|
|
1333
1349
|
`);
|
|
1334
1350
|
}
|
|
1335
|
-
|
|
1351
|
+
writeFileSync3(configPath, `${markedSection}
|
|
1352
|
+
|
|
1353
|
+
${existing}`);
|
|
1336
1354
|
}
|
|
1337
1355
|
} else {
|
|
1338
|
-
|
|
1356
|
+
writeFileSync3(configPath, `${markedSection}
|
|
1357
|
+
`);
|
|
1339
1358
|
}
|
|
1340
1359
|
process.stderr.write("exe-os: Ghostty config installed\n");
|
|
1341
1360
|
}
|
|
@@ -7050,9 +7069,9 @@ Unclassified: ${unclassified}
|
|
|
7050
7069
|
}
|
|
7051
7070
|
async function exportBatches(options) {
|
|
7052
7071
|
const fs8 = await import("fs");
|
|
7053
|
-
const
|
|
7072
|
+
const path44 = await import("path");
|
|
7054
7073
|
const client = getClient();
|
|
7055
|
-
const outDir =
|
|
7074
|
+
const outDir = path44.join(process.cwd(), "exe/output/classifications/input");
|
|
7056
7075
|
fs8.mkdirSync(outDir, { recursive: true });
|
|
7057
7076
|
const countResult = await client.execute({
|
|
7058
7077
|
sql: "SELECT COUNT(*) as cnt FROM memories WHERE intent IS NULL AND outcome IS NULL AND domain IS NULL",
|
|
@@ -7076,7 +7095,7 @@ async function exportBatches(options) {
|
|
|
7076
7095
|
const text = String(row.text || "").replace(/\n/g, " ");
|
|
7077
7096
|
return JSON.stringify({ id: row.id, text });
|
|
7078
7097
|
});
|
|
7079
|
-
const batchFile =
|
|
7098
|
+
const batchFile = path44.join(outDir, `batch-${String(batchNum).padStart(4, "0")}.jsonl`);
|
|
7080
7099
|
fs8.writeFileSync(batchFile, lines.join("\n") + "\n");
|
|
7081
7100
|
exported += batch.rows.length;
|
|
7082
7101
|
offset += options.batchSize;
|
|
@@ -7092,7 +7111,7 @@ async function exportBatches(options) {
|
|
|
7092
7111
|
}
|
|
7093
7112
|
async function importClassifications(importDir) {
|
|
7094
7113
|
const fs8 = await import("fs");
|
|
7095
|
-
const
|
|
7114
|
+
const path44 = await import("path");
|
|
7096
7115
|
const client = getClient();
|
|
7097
7116
|
const files = fs8.readdirSync(importDir).filter((f) => f.endsWith(".jsonl")).sort();
|
|
7098
7117
|
process.stderr.write(`[backfill-metadata] Found ${files.length} JSONL files to import from ${importDir}
|
|
@@ -7100,7 +7119,7 @@ async function importClassifications(importDir) {
|
|
|
7100
7119
|
let imported = 0;
|
|
7101
7120
|
let invalid = 0;
|
|
7102
7121
|
for (const file of files) {
|
|
7103
|
-
const lines = fs8.readFileSync(
|
|
7122
|
+
const lines = fs8.readFileSync(path44.join(importDir, file), "utf-8").split("\n").filter(Boolean);
|
|
7104
7123
|
for (const line of lines) {
|
|
7105
7124
|
try {
|
|
7106
7125
|
const rec = JSON.parse(line);
|
|
@@ -7190,42 +7209,652 @@ async function backfillMetadata(options) {
|
|
|
7190
7209
|
await disposeStore();
|
|
7191
7210
|
return { classified: result.classified, skipped: result.skipped, failed: 0, entitiesPopulated: 0, remaining: result.remaining };
|
|
7192
7211
|
}
|
|
7193
|
-
if (options.entities) {
|
|
7194
|
-
entitiesPopulated = await backfillEntities(options);
|
|
7195
|
-
} else {
|
|
7196
|
-
const result = await backfillClassifications(options);
|
|
7197
|
-
classified = result.classified;
|
|
7198
|
-
skipped = result.skipped;
|
|
7199
|
-
failed = result.failed;
|
|
7200
|
-
remaining = result.remaining;
|
|
7212
|
+
if (options.entities) {
|
|
7213
|
+
entitiesPopulated = await backfillEntities(options);
|
|
7214
|
+
} else {
|
|
7215
|
+
const result = await backfillClassifications(options);
|
|
7216
|
+
classified = result.classified;
|
|
7217
|
+
skipped = result.skipped;
|
|
7218
|
+
failed = result.failed;
|
|
7219
|
+
remaining = result.remaining;
|
|
7220
|
+
}
|
|
7221
|
+
await disposeStore();
|
|
7222
|
+
return { classified, skipped, failed, entitiesPopulated, remaining };
|
|
7223
|
+
}
|
|
7224
|
+
var VALID_INTENTS, VALID_OUTCOMES, VALID_DOMAINS, VALID_AUDIENCES, VALID_LANGUAGE_TYPES, MAX_TEXT_LENGTH, BATCH_SLEEP_MS, MARKETING_AGENT_MARKERS, RESEARCH_AGENT_MARKERS;
|
|
7225
|
+
var init_backfill_metadata = __esm({
|
|
7226
|
+
"src/bin/backfill-metadata.ts"() {
|
|
7227
|
+
"use strict";
|
|
7228
|
+
init_store();
|
|
7229
|
+
init_database();
|
|
7230
|
+
init_is_main();
|
|
7231
|
+
init_employees();
|
|
7232
|
+
VALID_INTENTS = /* @__PURE__ */ new Set(["decision", "question", "correction", "report", "discovery", "implementation"]);
|
|
7233
|
+
VALID_OUTCOMES = /* @__PURE__ */ new Set(["success", "failure", "partial", "superseded"]);
|
|
7234
|
+
VALID_DOMAINS = /* @__PURE__ */ new Set(["code", "architecture", "marketing", "operations", "customer", "research"]);
|
|
7235
|
+
VALID_AUDIENCES = /* @__PURE__ */ new Set(["founder", "team", "self"]);
|
|
7236
|
+
VALID_LANGUAGE_TYPES = /* @__PURE__ */ new Set(["code", "prose", "mixed", "json", "sql"]);
|
|
7237
|
+
MAX_TEXT_LENGTH = 2e3;
|
|
7238
|
+
BATCH_SLEEP_MS = 1e3;
|
|
7239
|
+
MARKETING_AGENT_MARKERS = roleAgentMarkers("CMO", "mari");
|
|
7240
|
+
RESEARCH_AGENT_MARKERS = roleAgentMarkers("AI Product Lead", "gen");
|
|
7241
|
+
if (isMainModule(import.meta.url)) {
|
|
7242
|
+
const options = parseArgs2(process.argv.slice(2));
|
|
7243
|
+
backfillMetadata(options).then((result) => {
|
|
7244
|
+
console.log(JSON.stringify(result, null, 2));
|
|
7245
|
+
process.exit(result.failed > 0 ? 1 : 0);
|
|
7246
|
+
}).catch((err) => {
|
|
7247
|
+
console.error("[backfill-metadata] Fatal:", err instanceof Error ? err.message : String(err));
|
|
7248
|
+
process.exit(1);
|
|
7249
|
+
});
|
|
7250
|
+
}
|
|
7251
|
+
}
|
|
7252
|
+
});
|
|
7253
|
+
|
|
7254
|
+
// src/lib/identity.ts
|
|
7255
|
+
var identity_exports = {};
|
|
7256
|
+
__export(identity_exports, {
|
|
7257
|
+
getIdentity: () => getIdentity,
|
|
7258
|
+
getIdentityInjection: () => getIdentityInjection,
|
|
7259
|
+
identityPath: () => identityPath,
|
|
7260
|
+
listIdentities: () => listIdentities,
|
|
7261
|
+
updateIdentity: () => updateIdentity
|
|
7262
|
+
});
|
|
7263
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync8, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "fs";
|
|
7264
|
+
import { readdirSync as readdirSync3 } from "fs";
|
|
7265
|
+
import path13 from "path";
|
|
7266
|
+
import { createHash as createHash2 } from "crypto";
|
|
7267
|
+
function ensureDir() {
|
|
7268
|
+
if (!existsSync12(IDENTITY_DIR)) {
|
|
7269
|
+
mkdirSync8(IDENTITY_DIR, { recursive: true });
|
|
7270
|
+
}
|
|
7271
|
+
}
|
|
7272
|
+
function identityPath(agentId) {
|
|
7273
|
+
return path13.join(IDENTITY_DIR, `${agentId}.md`);
|
|
7274
|
+
}
|
|
7275
|
+
function parseFrontmatter(raw) {
|
|
7276
|
+
const match = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
7277
|
+
if (!match) {
|
|
7278
|
+
return {
|
|
7279
|
+
frontmatter: {
|
|
7280
|
+
role: "unknown",
|
|
7281
|
+
title: "Unknown",
|
|
7282
|
+
agent_id: "unknown",
|
|
7283
|
+
org_level: "specialist",
|
|
7284
|
+
created_by: "system",
|
|
7285
|
+
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
7286
|
+
},
|
|
7287
|
+
body: raw
|
|
7288
|
+
};
|
|
7289
|
+
}
|
|
7290
|
+
const yamlStr = match[1];
|
|
7291
|
+
const body = match[2].trim();
|
|
7292
|
+
const fm = {};
|
|
7293
|
+
for (const line of yamlStr.split("\n")) {
|
|
7294
|
+
const kv = line.match(/^(\w+):\s*(.+)$/);
|
|
7295
|
+
if (kv) fm[kv[1]] = kv[2].trim();
|
|
7296
|
+
}
|
|
7297
|
+
return {
|
|
7298
|
+
frontmatter: {
|
|
7299
|
+
role: fm.role ?? "unknown",
|
|
7300
|
+
title: fm.title ?? "Unknown",
|
|
7301
|
+
agent_id: fm.agent_id ?? "unknown",
|
|
7302
|
+
org_level: fm.org_level ?? "specialist",
|
|
7303
|
+
created_by: fm.created_by ?? "system",
|
|
7304
|
+
updated_at: fm.updated_at ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
7305
|
+
},
|
|
7306
|
+
body
|
|
7307
|
+
};
|
|
7308
|
+
}
|
|
7309
|
+
function contentHash(content) {
|
|
7310
|
+
return createHash2("sha256").update(content).digest("hex").slice(0, 16);
|
|
7311
|
+
}
|
|
7312
|
+
function getIdentity(agentId) {
|
|
7313
|
+
const filePath = identityPath(agentId);
|
|
7314
|
+
if (!existsSync12(filePath)) return null;
|
|
7315
|
+
const raw = readFileSync9(filePath, "utf-8");
|
|
7316
|
+
const { frontmatter, body } = parseFrontmatter(raw);
|
|
7317
|
+
return {
|
|
7318
|
+
agentId,
|
|
7319
|
+
frontmatter,
|
|
7320
|
+
body,
|
|
7321
|
+
raw,
|
|
7322
|
+
contentHash: contentHash(raw)
|
|
7323
|
+
};
|
|
7324
|
+
}
|
|
7325
|
+
async function updateIdentity(agentId, content, updatedBy) {
|
|
7326
|
+
ensureDir();
|
|
7327
|
+
const filePath = identityPath(agentId);
|
|
7328
|
+
const hash = contentHash(content);
|
|
7329
|
+
writeFileSync7(filePath, content, "utf-8");
|
|
7330
|
+
try {
|
|
7331
|
+
const client = getClient();
|
|
7332
|
+
await client.execute({
|
|
7333
|
+
sql: `INSERT INTO identity (agent_id, content_hash, updated_at, updated_by)
|
|
7334
|
+
VALUES (?, ?, ?, ?)
|
|
7335
|
+
ON CONFLICT(agent_id) DO UPDATE SET
|
|
7336
|
+
content_hash = excluded.content_hash,
|
|
7337
|
+
updated_at = excluded.updated_at,
|
|
7338
|
+
updated_by = excluded.updated_by`,
|
|
7339
|
+
args: [agentId, hash, (/* @__PURE__ */ new Date()).toISOString(), updatedBy]
|
|
7340
|
+
});
|
|
7341
|
+
} catch {
|
|
7342
|
+
}
|
|
7343
|
+
}
|
|
7344
|
+
function listIdentities() {
|
|
7345
|
+
ensureDir();
|
|
7346
|
+
const files = readdirSync3(IDENTITY_DIR).filter((f) => f.endsWith(".md"));
|
|
7347
|
+
const results = [];
|
|
7348
|
+
for (const file of files) {
|
|
7349
|
+
const agentId = file.replace(".md", "");
|
|
7350
|
+
const identity = getIdentity(agentId);
|
|
7351
|
+
if (!identity) continue;
|
|
7352
|
+
const lines = identity.body.split("\n").filter((l) => l.trim() && !l.startsWith("#"));
|
|
7353
|
+
const summary = lines[0]?.trim().slice(0, 120) ?? identity.frontmatter.title;
|
|
7354
|
+
results.push({
|
|
7355
|
+
agentId,
|
|
7356
|
+
title: `${identity.frontmatter.title} (${identity.frontmatter.role.toUpperCase()})`,
|
|
7357
|
+
summary
|
|
7358
|
+
});
|
|
7359
|
+
}
|
|
7360
|
+
return results;
|
|
7361
|
+
}
|
|
7362
|
+
function getIdentityInjection(agentId) {
|
|
7363
|
+
const own = getIdentity(agentId);
|
|
7364
|
+
const all = listIdentities();
|
|
7365
|
+
const parts = [];
|
|
7366
|
+
if (own) {
|
|
7367
|
+
parts.push(`## Your Identity (exe.md)
|
|
7368
|
+
These define WHO YOU ARE. Non-negotiable. Permanent.
|
|
7369
|
+
|
|
7370
|
+
${own.body}`);
|
|
7371
|
+
}
|
|
7372
|
+
const teamLines = all.filter((a) => a.agentId !== agentId).map((a) => `- ${a.agentId} (${a.title}): ${a.summary}`);
|
|
7373
|
+
if (teamLines.length > 0) {
|
|
7374
|
+
parts.push(`## Team Identities
|
|
7375
|
+
${teamLines.join("\n")}`);
|
|
7376
|
+
}
|
|
7377
|
+
return parts.join("\n\n");
|
|
7378
|
+
}
|
|
7379
|
+
var IDENTITY_DIR;
|
|
7380
|
+
var init_identity = __esm({
|
|
7381
|
+
"src/lib/identity.ts"() {
|
|
7382
|
+
"use strict";
|
|
7383
|
+
init_config();
|
|
7384
|
+
init_database();
|
|
7385
|
+
IDENTITY_DIR = path13.join(EXE_AI_DIR, "identity");
|
|
7386
|
+
}
|
|
7387
|
+
});
|
|
7388
|
+
|
|
7389
|
+
// src/lib/orchestration-package.ts
|
|
7390
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
7391
|
+
import { copyFileSync as copyFileSync2, existsSync as existsSync13, mkdirSync as mkdirSync9, readFileSync as readFileSync10, writeFileSync as writeFileSync8 } from "fs";
|
|
7392
|
+
import os8 from "os";
|
|
7393
|
+
import path14 from "path";
|
|
7394
|
+
function ensureObject(value, label) {
|
|
7395
|
+
if (value == null || Array.isArray(value) || typeof value !== "object") {
|
|
7396
|
+
throw new Error(`${label} must be an object`);
|
|
7397
|
+
}
|
|
7398
|
+
return value;
|
|
7399
|
+
}
|
|
7400
|
+
function ensureString(value, label) {
|
|
7401
|
+
if (typeof value !== "string") {
|
|
7402
|
+
throw new Error(`${label} must be a string`);
|
|
7403
|
+
}
|
|
7404
|
+
return value;
|
|
7405
|
+
}
|
|
7406
|
+
function ensureOptionalString(value, label) {
|
|
7407
|
+
if (value == null) return void 0;
|
|
7408
|
+
return ensureString(value, label);
|
|
7409
|
+
}
|
|
7410
|
+
function ensureNullableString(value, label) {
|
|
7411
|
+
if (value == null) return null;
|
|
7412
|
+
return ensureString(value, label);
|
|
7413
|
+
}
|
|
7414
|
+
function ensurePriority(value, label, fallback) {
|
|
7415
|
+
if (value == null) return fallback;
|
|
7416
|
+
if (value === "p0" || value === "p1" || value === "p2") {
|
|
7417
|
+
return value;
|
|
7418
|
+
}
|
|
7419
|
+
throw new Error(`${label} must be one of: p0, p1, p2`);
|
|
7420
|
+
}
|
|
7421
|
+
function validateRosterEntry(value, index) {
|
|
7422
|
+
const record = ensureObject(value, `roster[${index}]`);
|
|
7423
|
+
return {
|
|
7424
|
+
name: ensureString(record.name, `roster[${index}].name`),
|
|
7425
|
+
role: ensureString(record.role, `roster[${index}].role`),
|
|
7426
|
+
systemPrompt: ensureString(record.systemPrompt, `roster[${index}].systemPrompt`),
|
|
7427
|
+
createdAt: typeof record.createdAt === "string" ? record.createdAt : "",
|
|
7428
|
+
templateName: ensureOptionalString(record.templateName, `roster[${index}].templateName`),
|
|
7429
|
+
templateVersion: typeof record.templateVersion === "number" ? record.templateVersion : void 0
|
|
7430
|
+
};
|
|
7431
|
+
}
|
|
7432
|
+
function validateBehaviorEntry(value, index) {
|
|
7433
|
+
const record = ensureObject(value, `behaviors[${index}]`);
|
|
7434
|
+
return {
|
|
7435
|
+
agent_id: ensureString(record.agent_id, `behaviors[${index}].agent_id`),
|
|
7436
|
+
project_name: ensureNullableString(record.project_name, `behaviors[${index}].project_name`),
|
|
7437
|
+
domain: ensureNullableString(record.domain, `behaviors[${index}].domain`),
|
|
7438
|
+
content: ensureString(record.content, `behaviors[${index}].content`),
|
|
7439
|
+
priority: ensurePriority(record.priority, `behaviors[${index}].priority`, DEFAULT_BEHAVIOR_PRIORITY)
|
|
7440
|
+
};
|
|
7441
|
+
}
|
|
7442
|
+
function validateProcedureEntry(value, index) {
|
|
7443
|
+
const record = ensureObject(value, `procedures[${index}]`);
|
|
7444
|
+
return {
|
|
7445
|
+
title: ensureString(record.title, `procedures[${index}].title`),
|
|
7446
|
+
content: ensureString(record.content, `procedures[${index}].content`),
|
|
7447
|
+
priority: ensurePriority(record.priority, `procedures[${index}].priority`, DEFAULT_PROCEDURE_PRIORITY),
|
|
7448
|
+
domain: ensureNullableString(record.domain, `procedures[${index}].domain`)
|
|
7449
|
+
};
|
|
7450
|
+
}
|
|
7451
|
+
function getRosterPath() {
|
|
7452
|
+
return path14.join(os8.homedir(), EXE_OS_DIRNAME, ROSTER_FILENAME);
|
|
7453
|
+
}
|
|
7454
|
+
function getBackupPath() {
|
|
7455
|
+
return path14.join(os8.homedir(), EXE_OS_DIRNAME, ROSTER_BACKUP_FILENAME);
|
|
7456
|
+
}
|
|
7457
|
+
function readRosterFile() {
|
|
7458
|
+
const rosterPath = getRosterPath();
|
|
7459
|
+
if (!existsSync13(rosterPath)) return [];
|
|
7460
|
+
const raw = readFileSync10(rosterPath, "utf-8");
|
|
7461
|
+
const parsed = JSON.parse(raw);
|
|
7462
|
+
if (!Array.isArray(parsed)) {
|
|
7463
|
+
throw new Error("Roster file must contain a JSON array");
|
|
7464
|
+
}
|
|
7465
|
+
return parsed.map((entry, index) => validateRosterEntry(entry, index));
|
|
7466
|
+
}
|
|
7467
|
+
function writeRosterFile(roster) {
|
|
7468
|
+
if (roster.length === 0) {
|
|
7469
|
+
throw new Error("Refusing to write empty roster \u2014 this would delete all employees");
|
|
7470
|
+
}
|
|
7471
|
+
const rosterPath = getRosterPath();
|
|
7472
|
+
mkdirSync9(path14.dirname(rosterPath), { recursive: true });
|
|
7473
|
+
if (existsSync13(rosterPath)) {
|
|
7474
|
+
const currentRoster = readRosterFile();
|
|
7475
|
+
if (roster.length < currentRoster.length) {
|
|
7476
|
+
throw new Error(
|
|
7477
|
+
`Refusing to write roster with ${roster.length} entries \u2014 current roster has ${currentRoster.length}. Import would delete ${currentRoster.length - roster.length} employee(s). Use merge strategy instead, or add the missing entries to the package.`
|
|
7478
|
+
);
|
|
7479
|
+
}
|
|
7480
|
+
copyFileSync2(rosterPath, getBackupPath());
|
|
7481
|
+
}
|
|
7482
|
+
writeFileSync8(rosterPath, `${JSON.stringify(roster, null, 2)}
|
|
7483
|
+
`, "utf-8");
|
|
7484
|
+
}
|
|
7485
|
+
function buildImportedRosterEntries(roster, timestamp) {
|
|
7486
|
+
return roster.map((entry) => ({
|
|
7487
|
+
name: entry.name,
|
|
7488
|
+
role: entry.role,
|
|
7489
|
+
systemPrompt: entry.systemPrompt,
|
|
7490
|
+
createdAt: timestamp,
|
|
7491
|
+
...entry.templateName != null ? { templateName: entry.templateName } : {},
|
|
7492
|
+
...entry.templateVersion != null ? { templateVersion: entry.templateVersion } : {}
|
|
7493
|
+
}));
|
|
7494
|
+
}
|
|
7495
|
+
async function insertBehaviors(behaviors, timestamp) {
|
|
7496
|
+
const client = getClient();
|
|
7497
|
+
for (const behavior of behaviors) {
|
|
7498
|
+
await client.execute({
|
|
7499
|
+
sql: `INSERT INTO behaviors (id, agent_id, project_name, domain, priority, content, active, created_at, updated_at)
|
|
7500
|
+
VALUES (?, ?, ?, ?, ?, ?, 1, ?, ?)`,
|
|
7501
|
+
args: [
|
|
7502
|
+
randomUUID4(),
|
|
7503
|
+
behavior.agent_id,
|
|
7504
|
+
behavior.project_name,
|
|
7505
|
+
behavior.domain,
|
|
7506
|
+
behavior.priority,
|
|
7507
|
+
behavior.content,
|
|
7508
|
+
timestamp,
|
|
7509
|
+
timestamp
|
|
7510
|
+
]
|
|
7511
|
+
});
|
|
7512
|
+
}
|
|
7513
|
+
return behaviors.length;
|
|
7514
|
+
}
|
|
7515
|
+
async function insertProcedures(procedures, timestamp, options) {
|
|
7516
|
+
const client = getClient();
|
|
7517
|
+
const skipTitles = options?.skipTitles ?? /* @__PURE__ */ new Set();
|
|
7518
|
+
let inserted = 0;
|
|
7519
|
+
for (const procedure of procedures) {
|
|
7520
|
+
if (skipTitles.has(procedure.title) || PLATFORM_PROCEDURE_TITLES.has(procedure.title)) {
|
|
7521
|
+
continue;
|
|
7522
|
+
}
|
|
7523
|
+
await client.execute({
|
|
7524
|
+
sql: `INSERT INTO global_procedures (id, title, content, priority, domain, active, created_at, updated_at)
|
|
7525
|
+
VALUES (?, ?, ?, ?, ?, 1, ?, ?)`,
|
|
7526
|
+
args: [
|
|
7527
|
+
randomUUID4(),
|
|
7528
|
+
procedure.title,
|
|
7529
|
+
procedure.content,
|
|
7530
|
+
procedure.priority,
|
|
7531
|
+
procedure.domain,
|
|
7532
|
+
timestamp,
|
|
7533
|
+
timestamp
|
|
7534
|
+
]
|
|
7535
|
+
});
|
|
7536
|
+
skipTitles.add(procedure.title);
|
|
7537
|
+
inserted += 1;
|
|
7538
|
+
}
|
|
7539
|
+
return inserted;
|
|
7540
|
+
}
|
|
7541
|
+
async function replaceBehaviorsAndProcedures(behaviors, procedures, timestamp) {
|
|
7542
|
+
const client = getClient();
|
|
7543
|
+
const existingBehaviors = await client.execute({
|
|
7544
|
+
sql: "SELECT agent_id, content FROM behaviors WHERE active = 1",
|
|
7545
|
+
args: []
|
|
7546
|
+
});
|
|
7547
|
+
const existingBehaviorKeys = new Set(
|
|
7548
|
+
existingBehaviors.rows.map((row) => `${String(row.agent_id)}::${String(row.content)}`)
|
|
7549
|
+
);
|
|
7550
|
+
const newBehaviors = behaviors.filter(
|
|
7551
|
+
(b) => !existingBehaviorKeys.has(`${b.agent_id}::${b.content}`)
|
|
7552
|
+
);
|
|
7553
|
+
const existingProcedureTitles = await getActiveProcedureTitles();
|
|
7554
|
+
return {
|
|
7555
|
+
behaviors: await insertBehaviors(newBehaviors, timestamp),
|
|
7556
|
+
procedures: await insertProcedures(procedures, timestamp, { skipTitles: existingProcedureTitles })
|
|
7557
|
+
};
|
|
7558
|
+
}
|
|
7559
|
+
async function mergeRosterEntries(importedRoster, timestamp) {
|
|
7560
|
+
const currentRoster = readRosterFile();
|
|
7561
|
+
const existingNames = new Set(currentRoster.map((entry) => entry.name.toLowerCase()));
|
|
7562
|
+
const additions = buildImportedRosterEntries(
|
|
7563
|
+
importedRoster.filter((entry) => !existingNames.has(entry.name.toLowerCase())),
|
|
7564
|
+
timestamp
|
|
7565
|
+
);
|
|
7566
|
+
if (additions.length > 0) {
|
|
7567
|
+
writeRosterFile([...currentRoster, ...additions]);
|
|
7568
|
+
}
|
|
7569
|
+
return additions.length;
|
|
7570
|
+
}
|
|
7571
|
+
async function replaceRosterEntries(importedRoster, timestamp) {
|
|
7572
|
+
const currentRoster = readRosterFile();
|
|
7573
|
+
const importedByName = new Map(
|
|
7574
|
+
buildImportedRosterEntries(importedRoster, timestamp).map((entry) => [entry.name.toLowerCase(), entry])
|
|
7575
|
+
);
|
|
7576
|
+
const merged = currentRoster.map((existing) => {
|
|
7577
|
+
const imported = importedByName.get(existing.name.toLowerCase());
|
|
7578
|
+
if (imported) {
|
|
7579
|
+
importedByName.delete(existing.name.toLowerCase());
|
|
7580
|
+
return imported;
|
|
7581
|
+
}
|
|
7582
|
+
return existing;
|
|
7583
|
+
});
|
|
7584
|
+
for (const newEntry of importedByName.values()) {
|
|
7585
|
+
merged.push(newEntry);
|
|
7586
|
+
}
|
|
7587
|
+
writeRosterFile(merged);
|
|
7588
|
+
return importedRoster.length;
|
|
7589
|
+
}
|
|
7590
|
+
async function importIdentities(identities, updatedBy) {
|
|
7591
|
+
const entries = Object.entries(identities);
|
|
7592
|
+
let imported = 0;
|
|
7593
|
+
for (const [agentId, content] of entries) {
|
|
7594
|
+
const existing = getIdentity(agentId);
|
|
7595
|
+
if (existing?.raw) {
|
|
7596
|
+
continue;
|
|
7597
|
+
}
|
|
7598
|
+
await updateIdentity(agentId, content, updatedBy);
|
|
7599
|
+
imported += 1;
|
|
7600
|
+
}
|
|
7601
|
+
return imported;
|
|
7602
|
+
}
|
|
7603
|
+
async function getActiveProcedureTitles() {
|
|
7604
|
+
const client = getClient();
|
|
7605
|
+
const result = await client.execute({
|
|
7606
|
+
sql: "SELECT title FROM global_procedures WHERE active = 1",
|
|
7607
|
+
args: []
|
|
7608
|
+
});
|
|
7609
|
+
return new Set(result.rows.map((row) => String(row.title)));
|
|
7610
|
+
}
|
|
7611
|
+
async function exportOrchestration(createdBy) {
|
|
7612
|
+
const client = getClient();
|
|
7613
|
+
const roster = readRosterFile().map((entry) => ({
|
|
7614
|
+
...entry,
|
|
7615
|
+
createdAt: ""
|
|
7616
|
+
}));
|
|
7617
|
+
const identities = {};
|
|
7618
|
+
for (const identitySummary of listIdentities()) {
|
|
7619
|
+
const identity = getIdentity(identitySummary.agentId);
|
|
7620
|
+
if (identity?.raw) {
|
|
7621
|
+
identities[identitySummary.agentId] = identity.raw;
|
|
7622
|
+
}
|
|
7623
|
+
}
|
|
7624
|
+
const behaviorResult = await client.execute({
|
|
7625
|
+
sql: "SELECT agent_id, project_name, domain, content, priority FROM behaviors WHERE active = 1",
|
|
7626
|
+
args: []
|
|
7627
|
+
});
|
|
7628
|
+
const procedureResult = await client.execute({
|
|
7629
|
+
sql: "SELECT title, content, priority, domain FROM global_procedures WHERE active = 1",
|
|
7630
|
+
args: []
|
|
7631
|
+
});
|
|
7632
|
+
const behaviors = behaviorResult.rows.map((row) => ({
|
|
7633
|
+
agent_id: String(row.agent_id),
|
|
7634
|
+
project_name: row.project_name == null ? null : String(row.project_name),
|
|
7635
|
+
domain: row.domain == null ? null : String(row.domain),
|
|
7636
|
+
content: String(row.content),
|
|
7637
|
+
priority: ensurePriority(row.priority, "behaviors.priority", DEFAULT_BEHAVIOR_PRIORITY)
|
|
7638
|
+
}));
|
|
7639
|
+
const procedures = procedureResult.rows.map((row) => ({
|
|
7640
|
+
title: String(row.title),
|
|
7641
|
+
content: String(row.content),
|
|
7642
|
+
priority: ensurePriority(row.priority, "procedures.priority", DEFAULT_PROCEDURE_PRIORITY),
|
|
7643
|
+
domain: row.domain == null ? null : String(row.domain)
|
|
7644
|
+
})).filter((procedure) => !PLATFORM_PROCEDURE_TITLES.has(procedure.title));
|
|
7645
|
+
return {
|
|
7646
|
+
version: PACKAGE_VERSION,
|
|
7647
|
+
created_by: createdBy,
|
|
7648
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7649
|
+
roster,
|
|
7650
|
+
identities,
|
|
7651
|
+
behaviors,
|
|
7652
|
+
procedures
|
|
7653
|
+
};
|
|
7654
|
+
}
|
|
7655
|
+
async function importOrchestration(pkg, strategy) {
|
|
7656
|
+
const validated = validatePackage(pkg);
|
|
7657
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
7658
|
+
const updatedBy = validated.created_by || DEFAULT_IDENTITY_UPDATED_BY;
|
|
7659
|
+
const rosterCount = strategy === "replace" ? await replaceRosterEntries(validated.roster, timestamp) : await mergeRosterEntries(validated.roster, timestamp);
|
|
7660
|
+
const identityCount = await importIdentities(validated.identities, updatedBy);
|
|
7661
|
+
if (strategy === "replace") {
|
|
7662
|
+
const replaced = await replaceBehaviorsAndProcedures(
|
|
7663
|
+
validated.behaviors,
|
|
7664
|
+
validated.procedures,
|
|
7665
|
+
timestamp
|
|
7666
|
+
);
|
|
7667
|
+
return {
|
|
7668
|
+
imported: {
|
|
7669
|
+
roster: rosterCount,
|
|
7670
|
+
identities: identityCount,
|
|
7671
|
+
behaviors: replaced.behaviors,
|
|
7672
|
+
procedures: replaced.procedures
|
|
7673
|
+
}
|
|
7674
|
+
};
|
|
7675
|
+
}
|
|
7676
|
+
const existingProcedureTitles = await getActiveProcedureTitles();
|
|
7677
|
+
const behaviorCount = await insertBehaviors(validated.behaviors, timestamp);
|
|
7678
|
+
const procedureCount = await insertProcedures(
|
|
7679
|
+
validated.procedures,
|
|
7680
|
+
timestamp,
|
|
7681
|
+
{ skipTitles: existingProcedureTitles }
|
|
7682
|
+
);
|
|
7683
|
+
return {
|
|
7684
|
+
imported: {
|
|
7685
|
+
roster: rosterCount,
|
|
7686
|
+
identities: identityCount,
|
|
7687
|
+
behaviors: behaviorCount,
|
|
7688
|
+
procedures: procedureCount
|
|
7689
|
+
}
|
|
7690
|
+
};
|
|
7691
|
+
}
|
|
7692
|
+
function validatePackage(data) {
|
|
7693
|
+
const record = ensureObject(data, "package");
|
|
7694
|
+
const version = ensureString(record.version, "version");
|
|
7695
|
+
if (version !== PACKAGE_VERSION) {
|
|
7696
|
+
throw new Error(`Unsupported orchestration package version: ${version}`);
|
|
7697
|
+
}
|
|
7698
|
+
if (!Array.isArray(record.roster)) {
|
|
7699
|
+
throw new Error("roster is required and must be an array");
|
|
7700
|
+
}
|
|
7701
|
+
if (record.identities == null || Array.isArray(record.identities) || typeof record.identities !== "object") {
|
|
7702
|
+
throw new Error("identities is required and must be an object");
|
|
7703
|
+
}
|
|
7704
|
+
if (!Array.isArray(record.behaviors)) {
|
|
7705
|
+
throw new Error("behaviors is required and must be an array");
|
|
7706
|
+
}
|
|
7707
|
+
if (!Array.isArray(record.procedures)) {
|
|
7708
|
+
throw new Error("procedures is required and must be an array");
|
|
7709
|
+
}
|
|
7710
|
+
const identities = Object.entries(record.identities).reduce(
|
|
7711
|
+
(acc, [agentId, content]) => {
|
|
7712
|
+
acc[agentId] = ensureString(content, `identities.${agentId}`);
|
|
7713
|
+
return acc;
|
|
7714
|
+
},
|
|
7715
|
+
{}
|
|
7716
|
+
);
|
|
7717
|
+
return {
|
|
7718
|
+
version: PACKAGE_VERSION,
|
|
7719
|
+
created_by: ensureString(record.created_by, "created_by"),
|
|
7720
|
+
created_at: ensureString(record.created_at, "created_at"),
|
|
7721
|
+
roster: record.roster.map((entry, index) => validateRosterEntry(entry, index)),
|
|
7722
|
+
identities,
|
|
7723
|
+
behaviors: record.behaviors.map((entry, index) => validateBehaviorEntry(entry, index)),
|
|
7724
|
+
procedures: record.procedures.map((entry, index) => validateProcedureEntry(entry, index))
|
|
7725
|
+
};
|
|
7726
|
+
}
|
|
7727
|
+
var PACKAGE_VERSION, ROSTER_FILENAME, ROSTER_BACKUP_FILENAME, EXE_OS_DIRNAME, DEFAULT_BEHAVIOR_PRIORITY, DEFAULT_PROCEDURE_PRIORITY, DEFAULT_IDENTITY_UPDATED_BY;
|
|
7728
|
+
var init_orchestration_package = __esm({
|
|
7729
|
+
"src/lib/orchestration-package.ts"() {
|
|
7730
|
+
"use strict";
|
|
7731
|
+
init_database();
|
|
7732
|
+
init_identity();
|
|
7733
|
+
init_platform_procedures();
|
|
7734
|
+
PACKAGE_VERSION = "1.0";
|
|
7735
|
+
ROSTER_FILENAME = "exe-employees.json";
|
|
7736
|
+
ROSTER_BACKUP_FILENAME = "exe-employees.json.bak";
|
|
7737
|
+
EXE_OS_DIRNAME = ".exe-os";
|
|
7738
|
+
DEFAULT_BEHAVIOR_PRIORITY = "p1";
|
|
7739
|
+
DEFAULT_PROCEDURE_PRIORITY = "p0";
|
|
7740
|
+
DEFAULT_IDENTITY_UPDATED_BY = "orchestration-import";
|
|
7741
|
+
}
|
|
7742
|
+
});
|
|
7743
|
+
|
|
7744
|
+
// src/bin/exe-export.ts
|
|
7745
|
+
var exe_export_exports = {};
|
|
7746
|
+
__export(exe_export_exports, {
|
|
7747
|
+
runExeExport: () => runExeExport
|
|
7748
|
+
});
|
|
7749
|
+
import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync9 } from "fs";
|
|
7750
|
+
import path15 from "path";
|
|
7751
|
+
function printUsage() {
|
|
7752
|
+
process.stdout.write("Usage: exe-os export --output <path>\n");
|
|
7753
|
+
}
|
|
7754
|
+
function parseOutputPath(argv) {
|
|
7755
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
7756
|
+
printUsage();
|
|
7757
|
+
return null;
|
|
7758
|
+
}
|
|
7759
|
+
const flagIndex = argv.indexOf(OUTPUT_FLAG);
|
|
7760
|
+
if (flagIndex === -1 || !argv[flagIndex + 1]) {
|
|
7761
|
+
throw new Error("Missing required --output <path> argument");
|
|
7762
|
+
}
|
|
7763
|
+
return argv[flagIndex + 1];
|
|
7764
|
+
}
|
|
7765
|
+
async function runExeExport(argv = process.argv.slice(2)) {
|
|
7766
|
+
const outputPath = parseOutputPath(argv);
|
|
7767
|
+
if (outputPath == null) return;
|
|
7768
|
+
await initStore();
|
|
7769
|
+
try {
|
|
7770
|
+
const pkg = await exportOrchestration("cli");
|
|
7771
|
+
mkdirSync10(path15.dirname(outputPath), { recursive: true });
|
|
7772
|
+
writeFileSync9(outputPath, `${JSON.stringify(pkg, null, 2)}
|
|
7773
|
+
`, "utf-8");
|
|
7774
|
+
process.stdout.write(
|
|
7775
|
+
`Exported ${pkg.roster.length} roster entries, ${Object.keys(pkg.identities).length} identities, ${pkg.behaviors.length} behaviors, ${pkg.procedures.length} procedures to ${outputPath}
|
|
7776
|
+
`
|
|
7777
|
+
);
|
|
7778
|
+
} finally {
|
|
7779
|
+
try {
|
|
7780
|
+
await disposeStore();
|
|
7781
|
+
} catch {
|
|
7782
|
+
}
|
|
7783
|
+
}
|
|
7784
|
+
}
|
|
7785
|
+
var OUTPUT_FLAG;
|
|
7786
|
+
var init_exe_export = __esm({
|
|
7787
|
+
"src/bin/exe-export.ts"() {
|
|
7788
|
+
"use strict";
|
|
7789
|
+
init_orchestration_package();
|
|
7790
|
+
init_is_main();
|
|
7791
|
+
init_store();
|
|
7792
|
+
OUTPUT_FLAG = "--output";
|
|
7793
|
+
if (isMainModule(import.meta.url) && (process.argv[1] ?? "").includes("exe-export")) {
|
|
7794
|
+
runExeExport().catch((err) => {
|
|
7795
|
+
process.stderr.write(`exe-os export failed: ${err instanceof Error ? err.message : String(err)}
|
|
7796
|
+
`);
|
|
7797
|
+
process.exit(1);
|
|
7798
|
+
});
|
|
7799
|
+
}
|
|
7800
|
+
}
|
|
7801
|
+
});
|
|
7802
|
+
|
|
7803
|
+
// src/bin/exe-import.ts
|
|
7804
|
+
var exe_import_exports = {};
|
|
7805
|
+
__export(exe_import_exports, {
|
|
7806
|
+
runExeImport: () => runExeImport
|
|
7807
|
+
});
|
|
7808
|
+
import { readFileSync as readFileSync11 } from "fs";
|
|
7809
|
+
function printUsage2() {
|
|
7810
|
+
process.stdout.write("Usage: exe-os import --from <path> [--merge]\n");
|
|
7811
|
+
}
|
|
7812
|
+
function parseArgs3(argv) {
|
|
7813
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
7814
|
+
printUsage2();
|
|
7815
|
+
return null;
|
|
7816
|
+
}
|
|
7817
|
+
const flagIndex = argv.indexOf(FROM_FLAG);
|
|
7818
|
+
if (flagIndex === -1 || !argv[flagIndex + 1]) {
|
|
7819
|
+
throw new Error("Missing required --from <path> argument");
|
|
7201
7820
|
}
|
|
7202
|
-
|
|
7203
|
-
|
|
7821
|
+
return {
|
|
7822
|
+
packagePath: argv[flagIndex + 1],
|
|
7823
|
+
strategy: argv.includes(MERGE_FLAG) ? "merge" : "replace"
|
|
7824
|
+
};
|
|
7204
7825
|
}
|
|
7205
|
-
|
|
7206
|
-
|
|
7207
|
-
|
|
7826
|
+
async function runExeImport(argv = process.argv.slice(2)) {
|
|
7827
|
+
const parsed = parseArgs3(argv);
|
|
7828
|
+
if (parsed == null) return;
|
|
7829
|
+
await initStore();
|
|
7830
|
+
try {
|
|
7831
|
+
const raw = readFileSync11(parsed.packagePath, "utf-8");
|
|
7832
|
+
const pkg = validatePackage(JSON.parse(raw));
|
|
7833
|
+
const result = await importOrchestration(pkg, parsed.strategy);
|
|
7834
|
+
process.stdout.write(
|
|
7835
|
+
`Imported ${result.imported.roster} roster entries, ${result.imported.identities} identities, ${result.imported.behaviors} behaviors, ${result.imported.procedures} procedures using ${parsed.strategy} strategy
|
|
7836
|
+
`
|
|
7837
|
+
);
|
|
7838
|
+
} finally {
|
|
7839
|
+
try {
|
|
7840
|
+
await disposeStore();
|
|
7841
|
+
} catch {
|
|
7842
|
+
}
|
|
7843
|
+
}
|
|
7844
|
+
}
|
|
7845
|
+
var FROM_FLAG, MERGE_FLAG;
|
|
7846
|
+
var init_exe_import = __esm({
|
|
7847
|
+
"src/bin/exe-import.ts"() {
|
|
7208
7848
|
"use strict";
|
|
7209
|
-
|
|
7210
|
-
init_database();
|
|
7849
|
+
init_orchestration_package();
|
|
7211
7850
|
init_is_main();
|
|
7212
|
-
|
|
7213
|
-
|
|
7214
|
-
|
|
7215
|
-
|
|
7216
|
-
|
|
7217
|
-
|
|
7218
|
-
|
|
7219
|
-
BATCH_SLEEP_MS = 1e3;
|
|
7220
|
-
MARKETING_AGENT_MARKERS = roleAgentMarkers("CMO", "mari");
|
|
7221
|
-
RESEARCH_AGENT_MARKERS = roleAgentMarkers("AI Product Lead", "gen");
|
|
7222
|
-
if (isMainModule(import.meta.url)) {
|
|
7223
|
-
const options = parseArgs2(process.argv.slice(2));
|
|
7224
|
-
backfillMetadata(options).then((result) => {
|
|
7225
|
-
console.log(JSON.stringify(result, null, 2));
|
|
7226
|
-
process.exit(result.failed > 0 ? 1 : 0);
|
|
7227
|
-
}).catch((err) => {
|
|
7228
|
-
console.error("[backfill-metadata] Fatal:", err instanceof Error ? err.message : String(err));
|
|
7851
|
+
init_store();
|
|
7852
|
+
FROM_FLAG = "--from";
|
|
7853
|
+
MERGE_FLAG = "--merge";
|
|
7854
|
+
if (isMainModule(import.meta.url) && (process.argv[1] ?? "").includes("exe-import")) {
|
|
7855
|
+
runExeImport().catch((err) => {
|
|
7856
|
+
process.stderr.write(`exe-os import failed: ${err instanceof Error ? err.message : String(err)}
|
|
7857
|
+
`);
|
|
7229
7858
|
process.exit(1);
|
|
7230
7859
|
});
|
|
7231
7860
|
}
|
|
@@ -7239,14 +7868,14 @@ __export(session_registry_exports, {
|
|
|
7239
7868
|
pruneStaleSessions: () => pruneStaleSessions,
|
|
7240
7869
|
registerSession: () => registerSession
|
|
7241
7870
|
});
|
|
7242
|
-
import { readFileSync as
|
|
7871
|
+
import { readFileSync as readFileSync12, writeFileSync as writeFileSync10, mkdirSync as mkdirSync11, existsSync as existsSync14 } from "fs";
|
|
7243
7872
|
import { execSync as execSync3 } from "child_process";
|
|
7244
|
-
import
|
|
7245
|
-
import
|
|
7873
|
+
import path16 from "path";
|
|
7874
|
+
import os9 from "os";
|
|
7246
7875
|
function registerSession(entry) {
|
|
7247
|
-
const dir =
|
|
7248
|
-
if (!
|
|
7249
|
-
|
|
7876
|
+
const dir = path16.dirname(REGISTRY_PATH);
|
|
7877
|
+
if (!existsSync14(dir)) {
|
|
7878
|
+
mkdirSync11(dir, { recursive: true });
|
|
7250
7879
|
}
|
|
7251
7880
|
const sessions = listSessions();
|
|
7252
7881
|
const idx = sessions.findIndex((s) => s.windowName === entry.windowName);
|
|
@@ -7255,11 +7884,11 @@ function registerSession(entry) {
|
|
|
7255
7884
|
} else {
|
|
7256
7885
|
sessions.push(entry);
|
|
7257
7886
|
}
|
|
7258
|
-
|
|
7887
|
+
writeFileSync10(REGISTRY_PATH, JSON.stringify(sessions, null, 2));
|
|
7259
7888
|
}
|
|
7260
7889
|
function listSessions() {
|
|
7261
7890
|
try {
|
|
7262
|
-
const raw =
|
|
7891
|
+
const raw = readFileSync12(REGISTRY_PATH, "utf8");
|
|
7263
7892
|
return JSON.parse(raw);
|
|
7264
7893
|
} catch {
|
|
7265
7894
|
return [];
|
|
@@ -7280,7 +7909,7 @@ function pruneStaleSessions() {
|
|
|
7280
7909
|
const alive = sessions.filter((s) => liveSet.has(s.windowName));
|
|
7281
7910
|
const pruned = sessions.length - alive.length;
|
|
7282
7911
|
if (pruned > 0) {
|
|
7283
|
-
|
|
7912
|
+
writeFileSync10(REGISTRY_PATH, JSON.stringify(alive, null, 2));
|
|
7284
7913
|
}
|
|
7285
7914
|
return pruned;
|
|
7286
7915
|
}
|
|
@@ -7288,7 +7917,7 @@ var REGISTRY_PATH;
|
|
|
7288
7917
|
var init_session_registry = __esm({
|
|
7289
7918
|
"src/lib/session-registry.ts"() {
|
|
7290
7919
|
"use strict";
|
|
7291
|
-
REGISTRY_PATH =
|
|
7920
|
+
REGISTRY_PATH = path16.join(os9.homedir(), ".exe-os", "session-registry.json");
|
|
7292
7921
|
}
|
|
7293
7922
|
});
|
|
7294
7923
|
|
|
@@ -7553,12 +8182,12 @@ var init_runtime_table = __esm({
|
|
|
7553
8182
|
});
|
|
7554
8183
|
|
|
7555
8184
|
// src/lib/agent-config.ts
|
|
7556
|
-
import { readFileSync as
|
|
7557
|
-
import
|
|
8185
|
+
import { readFileSync as readFileSync13, writeFileSync as writeFileSync11, existsSync as existsSync15, mkdirSync as mkdirSync12 } from "fs";
|
|
8186
|
+
import path17 from "path";
|
|
7558
8187
|
function loadAgentConfig() {
|
|
7559
|
-
if (!
|
|
8188
|
+
if (!existsSync15(AGENT_CONFIG_PATH)) return {};
|
|
7560
8189
|
try {
|
|
7561
|
-
return JSON.parse(
|
|
8190
|
+
return JSON.parse(readFileSync13(AGENT_CONFIG_PATH, "utf-8"));
|
|
7562
8191
|
} catch {
|
|
7563
8192
|
return {};
|
|
7564
8193
|
}
|
|
@@ -7577,7 +8206,7 @@ var init_agent_config = __esm({
|
|
|
7577
8206
|
"use strict";
|
|
7578
8207
|
init_config();
|
|
7579
8208
|
init_runtime_table();
|
|
7580
|
-
AGENT_CONFIG_PATH =
|
|
8209
|
+
AGENT_CONFIG_PATH = path17.join(EXE_AI_DIR, "agent-config.json");
|
|
7581
8210
|
DEFAULT_MODELS = {
|
|
7582
8211
|
claude: "claude-opus-4",
|
|
7583
8212
|
codex: RUNTIME_TABLE.codex?.defaultModel ?? "gpt-5.4",
|
|
@@ -7595,25 +8224,25 @@ __export(intercom_queue_exports, {
|
|
|
7595
8224
|
queueIntercom: () => queueIntercom,
|
|
7596
8225
|
readQueue: () => readQueue
|
|
7597
8226
|
});
|
|
7598
|
-
import { readFileSync as
|
|
7599
|
-
import
|
|
7600
|
-
import
|
|
7601
|
-
function
|
|
7602
|
-
const dir =
|
|
7603
|
-
if (!
|
|
8227
|
+
import { readFileSync as readFileSync14, writeFileSync as writeFileSync12, renameSync as renameSync3, existsSync as existsSync16, mkdirSync as mkdirSync13 } from "fs";
|
|
8228
|
+
import path18 from "path";
|
|
8229
|
+
import os10 from "os";
|
|
8230
|
+
function ensureDir2() {
|
|
8231
|
+
const dir = path18.dirname(QUEUE_PATH);
|
|
8232
|
+
if (!existsSync16(dir)) mkdirSync13(dir, { recursive: true });
|
|
7604
8233
|
}
|
|
7605
8234
|
function readQueue() {
|
|
7606
8235
|
try {
|
|
7607
|
-
if (!
|
|
7608
|
-
return JSON.parse(
|
|
8236
|
+
if (!existsSync16(QUEUE_PATH)) return [];
|
|
8237
|
+
return JSON.parse(readFileSync14(QUEUE_PATH, "utf8"));
|
|
7609
8238
|
} catch {
|
|
7610
8239
|
return [];
|
|
7611
8240
|
}
|
|
7612
8241
|
}
|
|
7613
8242
|
function writeQueue(queue) {
|
|
7614
|
-
|
|
8243
|
+
ensureDir2();
|
|
7615
8244
|
const tmp = `${QUEUE_PATH}.tmp`;
|
|
7616
|
-
|
|
8245
|
+
writeFileSync12(tmp, JSON.stringify(queue, null, 2));
|
|
7617
8246
|
renameSync3(tmp, QUEUE_PATH);
|
|
7618
8247
|
}
|
|
7619
8248
|
function queueIntercom(targetSession, reason) {
|
|
@@ -7705,20 +8334,20 @@ var QUEUE_PATH, MAX_RETRIES2, TTL_MS, INTERCOM_LOG;
|
|
|
7705
8334
|
var init_intercom_queue = __esm({
|
|
7706
8335
|
"src/lib/intercom-queue.ts"() {
|
|
7707
8336
|
"use strict";
|
|
7708
|
-
QUEUE_PATH =
|
|
8337
|
+
QUEUE_PATH = path18.join(os10.homedir(), ".exe-os", "intercom-queue.json");
|
|
7709
8338
|
MAX_RETRIES2 = 5;
|
|
7710
8339
|
TTL_MS = 60 * 60 * 1e3;
|
|
7711
|
-
INTERCOM_LOG =
|
|
8340
|
+
INTERCOM_LOG = path18.join(os10.homedir(), ".exe-os", "intercom.log");
|
|
7712
8341
|
}
|
|
7713
8342
|
});
|
|
7714
8343
|
|
|
7715
8344
|
// src/lib/plan-limits.ts
|
|
7716
|
-
import { readFileSync as
|
|
7717
|
-
import
|
|
8345
|
+
import { readFileSync as readFileSync15, existsSync as existsSync17 } from "fs";
|
|
8346
|
+
import path19 from "path";
|
|
7718
8347
|
function getLicenseSync() {
|
|
7719
8348
|
try {
|
|
7720
|
-
if (!
|
|
7721
|
-
const raw = JSON.parse(
|
|
8349
|
+
if (!existsSync17(CACHE_PATH2)) return freeLicense();
|
|
8350
|
+
const raw = JSON.parse(readFileSync15(CACHE_PATH2, "utf8"));
|
|
7722
8351
|
if (!raw.token || typeof raw.token !== "string") return freeLicense();
|
|
7723
8352
|
const parts = raw.token.split(".");
|
|
7724
8353
|
if (parts.length !== 3) return freeLicense();
|
|
@@ -7756,8 +8385,8 @@ function assertEmployeeLimitSync(rosterPath) {
|
|
|
7756
8385
|
const filePath = rosterPath ?? EMPLOYEES_PATH;
|
|
7757
8386
|
let count = 0;
|
|
7758
8387
|
try {
|
|
7759
|
-
if (
|
|
7760
|
-
const raw =
|
|
8388
|
+
if (existsSync17(filePath)) {
|
|
8389
|
+
const raw = readFileSync15(filePath, "utf8");
|
|
7761
8390
|
const employees = JSON.parse(raw);
|
|
7762
8391
|
count = Array.isArray(employees) ? employees.length : 0;
|
|
7763
8392
|
}
|
|
@@ -7786,19 +8415,19 @@ var init_plan_limits = __esm({
|
|
|
7786
8415
|
this.name = "PlanLimitError";
|
|
7787
8416
|
}
|
|
7788
8417
|
};
|
|
7789
|
-
CACHE_PATH2 =
|
|
8418
|
+
CACHE_PATH2 = path19.join(EXE_AI_DIR, "license-cache.json");
|
|
7790
8419
|
}
|
|
7791
8420
|
});
|
|
7792
8421
|
|
|
7793
8422
|
// src/lib/notifications.ts
|
|
7794
8423
|
import crypto5 from "crypto";
|
|
7795
|
-
import
|
|
7796
|
-
import
|
|
8424
|
+
import path20 from "path";
|
|
8425
|
+
import os11 from "os";
|
|
7797
8426
|
import {
|
|
7798
|
-
readFileSync as
|
|
7799
|
-
readdirSync as
|
|
8427
|
+
readFileSync as readFileSync16,
|
|
8428
|
+
readdirSync as readdirSync4,
|
|
7800
8429
|
unlinkSync as unlinkSync5,
|
|
7801
|
-
existsSync as
|
|
8430
|
+
existsSync as existsSync18,
|
|
7802
8431
|
rmdirSync
|
|
7803
8432
|
} from "fs";
|
|
7804
8433
|
async function writeNotification(notification) {
|
|
@@ -7923,11 +8552,11 @@ __export(tasks_crud_exports, {
|
|
|
7923
8552
|
writeCheckpoint: () => writeCheckpoint
|
|
7924
8553
|
});
|
|
7925
8554
|
import crypto7 from "crypto";
|
|
7926
|
-
import
|
|
7927
|
-
import
|
|
8555
|
+
import path21 from "path";
|
|
8556
|
+
import os12 from "os";
|
|
7928
8557
|
import { execSync as execSync6 } from "child_process";
|
|
7929
8558
|
import { mkdir as mkdir5, writeFile as writeFile5, appendFile } from "fs/promises";
|
|
7930
|
-
import { existsSync as
|
|
8559
|
+
import { existsSync as existsSync19, readFileSync as readFileSync17 } from "fs";
|
|
7931
8560
|
async function writeCheckpoint(input) {
|
|
7932
8561
|
const client = getClient();
|
|
7933
8562
|
const row = await resolveTask(client, input.taskId);
|
|
@@ -8102,8 +8731,8 @@ ${laneWarning}` : laneWarning;
|
|
|
8102
8731
|
}
|
|
8103
8732
|
if (input.baseDir) {
|
|
8104
8733
|
try {
|
|
8105
|
-
await mkdir5(
|
|
8106
|
-
await mkdir5(
|
|
8734
|
+
await mkdir5(path21.join(input.baseDir, "exe", "output"), { recursive: true });
|
|
8735
|
+
await mkdir5(path21.join(input.baseDir, "exe", "research"), { recursive: true });
|
|
8107
8736
|
await ensureArchitectureDoc(input.baseDir, input.projectName);
|
|
8108
8737
|
await ensureGitignoreExe(input.baseDir);
|
|
8109
8738
|
} catch {
|
|
@@ -8139,10 +8768,10 @@ ${laneWarning}` : laneWarning;
|
|
|
8139
8768
|
});
|
|
8140
8769
|
if (input.baseDir) {
|
|
8141
8770
|
try {
|
|
8142
|
-
const EXE_OS_DIR =
|
|
8143
|
-
const mdPath =
|
|
8144
|
-
const mdDir =
|
|
8145
|
-
if (!
|
|
8771
|
+
const EXE_OS_DIR = path21.join(os12.homedir(), ".exe-os");
|
|
8772
|
+
const mdPath = path21.join(EXE_OS_DIR, taskFile);
|
|
8773
|
+
const mdDir = path21.dirname(mdPath);
|
|
8774
|
+
if (!existsSync19(mdDir)) await mkdir5(mdDir, { recursive: true });
|
|
8146
8775
|
const reviewer = input.reviewer ?? input.assignedBy;
|
|
8147
8776
|
const mdContent = `# ${input.title}
|
|
8148
8777
|
|
|
@@ -8442,9 +9071,9 @@ async function deleteTaskCore(taskId, _baseDir) {
|
|
|
8442
9071
|
return { taskFile, assignedTo, assignedBy, taskSlug };
|
|
8443
9072
|
}
|
|
8444
9073
|
async function ensureArchitectureDoc(baseDir, projectName) {
|
|
8445
|
-
const archPath =
|
|
9074
|
+
const archPath = path21.join(baseDir, "exe", "ARCHITECTURE.md");
|
|
8446
9075
|
try {
|
|
8447
|
-
if (
|
|
9076
|
+
if (existsSync19(archPath)) return;
|
|
8448
9077
|
const template = [
|
|
8449
9078
|
`# ${projectName} \u2014 System Architecture`,
|
|
8450
9079
|
"",
|
|
@@ -8477,10 +9106,10 @@ async function ensureArchitectureDoc(baseDir, projectName) {
|
|
|
8477
9106
|
}
|
|
8478
9107
|
}
|
|
8479
9108
|
async function ensureGitignoreExe(baseDir) {
|
|
8480
|
-
const gitignorePath =
|
|
9109
|
+
const gitignorePath = path21.join(baseDir, ".gitignore");
|
|
8481
9110
|
try {
|
|
8482
|
-
if (
|
|
8483
|
-
const content =
|
|
9111
|
+
if (existsSync19(gitignorePath)) {
|
|
9112
|
+
const content = readFileSync17(gitignorePath, "utf-8");
|
|
8484
9113
|
if (/^\/?exe\/?$/m.test(content)) return;
|
|
8485
9114
|
await appendFile(gitignorePath, "\n# Employee task assignments (private)\n/exe/\n");
|
|
8486
9115
|
} else {
|
|
@@ -8511,8 +9140,8 @@ var init_tasks_crud = __esm({
|
|
|
8511
9140
|
});
|
|
8512
9141
|
|
|
8513
9142
|
// src/lib/tasks-review.ts
|
|
8514
|
-
import
|
|
8515
|
-
import { existsSync as
|
|
9143
|
+
import path22 from "path";
|
|
9144
|
+
import { existsSync as existsSync20, readdirSync as readdirSync5, unlinkSync as unlinkSync6 } from "fs";
|
|
8516
9145
|
async function countPendingReviews(sessionScope) {
|
|
8517
9146
|
const client = getClient();
|
|
8518
9147
|
if (sessionScope) {
|
|
@@ -8693,11 +9322,11 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
|
|
|
8693
9322
|
);
|
|
8694
9323
|
}
|
|
8695
9324
|
try {
|
|
8696
|
-
const cacheDir =
|
|
8697
|
-
if (
|
|
8698
|
-
for (const f of
|
|
9325
|
+
const cacheDir = path22.join(EXE_AI_DIR, "session-cache");
|
|
9326
|
+
if (existsSync20(cacheDir)) {
|
|
9327
|
+
for (const f of readdirSync5(cacheDir)) {
|
|
8699
9328
|
if (f.startsWith("review-notified-")) {
|
|
8700
|
-
unlinkSync6(
|
|
9329
|
+
unlinkSync6(path22.join(cacheDir, f));
|
|
8701
9330
|
}
|
|
8702
9331
|
}
|
|
8703
9332
|
}
|
|
@@ -8718,7 +9347,7 @@ var init_tasks_review = __esm({
|
|
|
8718
9347
|
});
|
|
8719
9348
|
|
|
8720
9349
|
// src/lib/tasks-chain.ts
|
|
8721
|
-
import
|
|
9350
|
+
import path23 from "path";
|
|
8722
9351
|
import { readFile as readFile5, writeFile as writeFile6 } from "fs/promises";
|
|
8723
9352
|
async function cascadeUnblock(taskId, baseDir, now) {
|
|
8724
9353
|
const client = getClient();
|
|
@@ -8735,7 +9364,7 @@ async function cascadeUnblock(taskId, baseDir, now) {
|
|
|
8735
9364
|
});
|
|
8736
9365
|
for (const ur of unblockedRows.rows) {
|
|
8737
9366
|
try {
|
|
8738
|
-
const ubFile =
|
|
9367
|
+
const ubFile = path23.join(baseDir, String(ur.task_file));
|
|
8739
9368
|
let ubContent = await readFile5(ubFile, "utf-8");
|
|
8740
9369
|
ubContent = ubContent.replace(/\*\*Status:\*\* blocked/, "**Status:** open");
|
|
8741
9370
|
ubContent = ubContent.replace(/\n\*\*Blocked by:\*\*.*\n/, "\n");
|
|
@@ -8804,7 +9433,7 @@ var init_tasks_chain = __esm({
|
|
|
8804
9433
|
|
|
8805
9434
|
// src/lib/project-name.ts
|
|
8806
9435
|
import { execSync as execSync7 } from "child_process";
|
|
8807
|
-
import
|
|
9436
|
+
import path24 from "path";
|
|
8808
9437
|
function getProjectName(cwd2) {
|
|
8809
9438
|
const dir = cwd2 ?? process.cwd();
|
|
8810
9439
|
if (_cached2 && _cachedCwd === dir) return _cached2;
|
|
@@ -8817,7 +9446,7 @@ function getProjectName(cwd2) {
|
|
|
8817
9446
|
timeout: 2e3,
|
|
8818
9447
|
stdio: ["pipe", "pipe", "pipe"]
|
|
8819
9448
|
}).trim();
|
|
8820
|
-
repoRoot =
|
|
9449
|
+
repoRoot = path24.dirname(gitCommonDir);
|
|
8821
9450
|
} catch {
|
|
8822
9451
|
repoRoot = execSync7("git rev-parse --show-toplevel", {
|
|
8823
9452
|
cwd: dir,
|
|
@@ -8826,11 +9455,11 @@ function getProjectName(cwd2) {
|
|
|
8826
9455
|
stdio: ["pipe", "pipe", "pipe"]
|
|
8827
9456
|
}).trim();
|
|
8828
9457
|
}
|
|
8829
|
-
_cached2 =
|
|
9458
|
+
_cached2 = path24.basename(repoRoot);
|
|
8830
9459
|
_cachedCwd = dir;
|
|
8831
9460
|
return _cached2;
|
|
8832
9461
|
} catch {
|
|
8833
|
-
_cached2 =
|
|
9462
|
+
_cached2 = path24.basename(dir);
|
|
8834
9463
|
_cachedCwd = dir;
|
|
8835
9464
|
return _cached2;
|
|
8836
9465
|
}
|
|
@@ -9303,8 +9932,8 @@ __export(tasks_exports, {
|
|
|
9303
9932
|
updateTaskStatus: () => updateTaskStatus,
|
|
9304
9933
|
writeCheckpoint: () => writeCheckpoint
|
|
9305
9934
|
});
|
|
9306
|
-
import
|
|
9307
|
-
import { writeFileSync as
|
|
9935
|
+
import path25 from "path";
|
|
9936
|
+
import { writeFileSync as writeFileSync13, mkdirSync as mkdirSync14, unlinkSync as unlinkSync7 } from "fs";
|
|
9308
9937
|
async function createTask(input) {
|
|
9309
9938
|
const result = await createTaskCore(input);
|
|
9310
9939
|
if (!input.skipDispatch && result.status !== "blocked" && !process.env.VITEST) {
|
|
@@ -9323,11 +9952,11 @@ async function updateTask(input) {
|
|
|
9323
9952
|
const { row, taskFile, now, taskId } = await updateTaskStatus(input);
|
|
9324
9953
|
try {
|
|
9325
9954
|
const agent = String(row.assigned_to);
|
|
9326
|
-
const cacheDir =
|
|
9327
|
-
const cachePath =
|
|
9955
|
+
const cacheDir = path25.join(EXE_AI_DIR, "session-cache");
|
|
9956
|
+
const cachePath = path25.join(cacheDir, `current-task-${agent}.json`);
|
|
9328
9957
|
if (input.status === "in_progress") {
|
|
9329
|
-
|
|
9330
|
-
|
|
9958
|
+
mkdirSync14(cacheDir, { recursive: true });
|
|
9959
|
+
writeFileSync13(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
|
|
9331
9960
|
} else if (input.status === "done" || input.status === "blocked" || input.status === "cancelled") {
|
|
9332
9961
|
try {
|
|
9333
9962
|
unlinkSync7(cachePath);
|
|
@@ -9794,13 +10423,13 @@ __export(tmux_routing_exports, {
|
|
|
9794
10423
|
verifyPaneAtCapacity: () => verifyPaneAtCapacity
|
|
9795
10424
|
});
|
|
9796
10425
|
import { execFileSync as execFileSync2, execSync as execSync8 } from "child_process";
|
|
9797
|
-
import { readFileSync as
|
|
9798
|
-
import
|
|
9799
|
-
import
|
|
10426
|
+
import { readFileSync as readFileSync18, writeFileSync as writeFileSync14, mkdirSync as mkdirSync15, existsSync as existsSync21, appendFileSync as appendFileSync2 } from "fs";
|
|
10427
|
+
import path26 from "path";
|
|
10428
|
+
import os13 from "os";
|
|
9800
10429
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
9801
10430
|
import { unlinkSync as unlinkSync8 } from "fs";
|
|
9802
10431
|
function spawnLockPath(sessionName) {
|
|
9803
|
-
return
|
|
10432
|
+
return path26.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
|
|
9804
10433
|
}
|
|
9805
10434
|
function isProcessAlive(pid) {
|
|
9806
10435
|
try {
|
|
@@ -9811,13 +10440,13 @@ function isProcessAlive(pid) {
|
|
|
9811
10440
|
}
|
|
9812
10441
|
}
|
|
9813
10442
|
function acquireSpawnLock2(sessionName) {
|
|
9814
|
-
if (!
|
|
9815
|
-
|
|
10443
|
+
if (!existsSync21(SPAWN_LOCK_DIR)) {
|
|
10444
|
+
mkdirSync15(SPAWN_LOCK_DIR, { recursive: true });
|
|
9816
10445
|
}
|
|
9817
10446
|
const lockFile = spawnLockPath(sessionName);
|
|
9818
|
-
if (
|
|
10447
|
+
if (existsSync21(lockFile)) {
|
|
9819
10448
|
try {
|
|
9820
|
-
const lock = JSON.parse(
|
|
10449
|
+
const lock = JSON.parse(readFileSync18(lockFile, "utf8"));
|
|
9821
10450
|
const age = Date.now() - lock.timestamp;
|
|
9822
10451
|
if (isProcessAlive(lock.pid) && age < 6e4) {
|
|
9823
10452
|
return false;
|
|
@@ -9825,7 +10454,7 @@ function acquireSpawnLock2(sessionName) {
|
|
|
9825
10454
|
} catch {
|
|
9826
10455
|
}
|
|
9827
10456
|
}
|
|
9828
|
-
|
|
10457
|
+
writeFileSync14(lockFile, JSON.stringify({ pid: process.pid, timestamp: Date.now() }));
|
|
9829
10458
|
return true;
|
|
9830
10459
|
}
|
|
9831
10460
|
function releaseSpawnLock2(sessionName) {
|
|
@@ -9837,13 +10466,13 @@ function releaseSpawnLock2(sessionName) {
|
|
|
9837
10466
|
function resolveBehaviorsExporterScript() {
|
|
9838
10467
|
try {
|
|
9839
10468
|
const thisFile = fileURLToPath4(import.meta.url);
|
|
9840
|
-
const scriptPath =
|
|
9841
|
-
|
|
10469
|
+
const scriptPath = path26.join(
|
|
10470
|
+
path26.dirname(thisFile),
|
|
9842
10471
|
"..",
|
|
9843
10472
|
"bin",
|
|
9844
10473
|
"exe-export-behaviors.js"
|
|
9845
10474
|
);
|
|
9846
|
-
return
|
|
10475
|
+
return existsSync21(scriptPath) ? scriptPath : null;
|
|
9847
10476
|
} catch {
|
|
9848
10477
|
return null;
|
|
9849
10478
|
}
|
|
@@ -9909,12 +10538,12 @@ function extractRootExe(name) {
|
|
|
9909
10538
|
return parts.length > 0 ? parts[parts.length - 1] : null;
|
|
9910
10539
|
}
|
|
9911
10540
|
function registerParentExe(sessionKey, parentExe, dispatchedBy) {
|
|
9912
|
-
if (!
|
|
9913
|
-
|
|
10541
|
+
if (!existsSync21(SESSION_CACHE)) {
|
|
10542
|
+
mkdirSync15(SESSION_CACHE, { recursive: true });
|
|
9914
10543
|
}
|
|
9915
10544
|
const rootExe = extractRootExe(parentExe) ?? parentExe;
|
|
9916
|
-
const filePath =
|
|
9917
|
-
|
|
10545
|
+
const filePath = path26.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
|
|
10546
|
+
writeFileSync14(filePath, JSON.stringify({
|
|
9918
10547
|
parentExe: rootExe,
|
|
9919
10548
|
dispatchedBy: dispatchedBy || rootExe,
|
|
9920
10549
|
registeredAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -9922,7 +10551,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
|
|
|
9922
10551
|
}
|
|
9923
10552
|
function getParentExe(sessionKey) {
|
|
9924
10553
|
try {
|
|
9925
|
-
const data = JSON.parse(
|
|
10554
|
+
const data = JSON.parse(readFileSync18(path26.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
|
|
9926
10555
|
return data.parentExe || null;
|
|
9927
10556
|
} catch {
|
|
9928
10557
|
return null;
|
|
@@ -9930,8 +10559,8 @@ function getParentExe(sessionKey) {
|
|
|
9930
10559
|
}
|
|
9931
10560
|
function getDispatchedBy(sessionKey) {
|
|
9932
10561
|
try {
|
|
9933
|
-
const data = JSON.parse(
|
|
9934
|
-
|
|
10562
|
+
const data = JSON.parse(readFileSync18(
|
|
10563
|
+
path26.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
|
|
9935
10564
|
"utf8"
|
|
9936
10565
|
));
|
|
9937
10566
|
return data.dispatchedBy ?? data.parentExe ?? null;
|
|
@@ -9992,8 +10621,8 @@ async function verifyPaneAtCapacity(sessionName) {
|
|
|
9992
10621
|
}
|
|
9993
10622
|
function readDebounceState() {
|
|
9994
10623
|
try {
|
|
9995
|
-
if (!
|
|
9996
|
-
const raw = JSON.parse(
|
|
10624
|
+
if (!existsSync21(DEBOUNCE_FILE)) return {};
|
|
10625
|
+
const raw = JSON.parse(readFileSync18(DEBOUNCE_FILE, "utf8"));
|
|
9997
10626
|
const state = {};
|
|
9998
10627
|
for (const [key, val] of Object.entries(raw)) {
|
|
9999
10628
|
if (typeof val === "number") {
|
|
@@ -10009,8 +10638,8 @@ function readDebounceState() {
|
|
|
10009
10638
|
}
|
|
10010
10639
|
function writeDebounceState(state) {
|
|
10011
10640
|
try {
|
|
10012
|
-
if (!
|
|
10013
|
-
|
|
10641
|
+
if (!existsSync21(SESSION_CACHE)) mkdirSync15(SESSION_CACHE, { recursive: true });
|
|
10642
|
+
writeFileSync14(DEBOUNCE_FILE, JSON.stringify(state));
|
|
10014
10643
|
} catch {
|
|
10015
10644
|
}
|
|
10016
10645
|
}
|
|
@@ -10108,8 +10737,8 @@ function sendIntercom(targetSession) {
|
|
|
10108
10737
|
try {
|
|
10109
10738
|
const rawAgent = targetSession.split("-")[0] ?? targetSession;
|
|
10110
10739
|
const agent = baseAgentName(rawAgent);
|
|
10111
|
-
const markerPath =
|
|
10112
|
-
if (
|
|
10740
|
+
const markerPath = path26.join(SESSION_CACHE, `current-task-${agent}.json`);
|
|
10741
|
+
if (existsSync21(markerPath)) {
|
|
10113
10742
|
logIntercom(`SKIP \u2192 ${targetSession} (has in_progress task marker \u2014 will auto-chain)`);
|
|
10114
10743
|
return "debounced";
|
|
10115
10744
|
}
|
|
@@ -10234,26 +10863,26 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
10234
10863
|
const transport = getTransport();
|
|
10235
10864
|
const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
|
|
10236
10865
|
const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
|
|
10237
|
-
const logDir =
|
|
10238
|
-
const logFile =
|
|
10239
|
-
if (!
|
|
10240
|
-
|
|
10866
|
+
const logDir = path26.join(os13.homedir(), ".exe-os", "session-logs");
|
|
10867
|
+
const logFile = path26.join(logDir, `${instanceLabel}-${Date.now()}.log`);
|
|
10868
|
+
if (!existsSync21(logDir)) {
|
|
10869
|
+
mkdirSync15(logDir, { recursive: true });
|
|
10241
10870
|
}
|
|
10242
10871
|
transport.kill(sessionName);
|
|
10243
10872
|
let cleanupSuffix = "";
|
|
10244
10873
|
try {
|
|
10245
10874
|
const thisFile = fileURLToPath4(import.meta.url);
|
|
10246
|
-
const cleanupScript =
|
|
10247
|
-
if (
|
|
10875
|
+
const cleanupScript = path26.join(path26.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
|
|
10876
|
+
if (existsSync21(cleanupScript)) {
|
|
10248
10877
|
cleanupSuffix = `; ${process.execPath} "${cleanupScript}" "${employeeName}" "${exeSession}"`;
|
|
10249
10878
|
}
|
|
10250
10879
|
} catch {
|
|
10251
10880
|
}
|
|
10252
10881
|
try {
|
|
10253
|
-
const claudeJsonPath =
|
|
10882
|
+
const claudeJsonPath = path26.join(os13.homedir(), ".claude.json");
|
|
10254
10883
|
let claudeJson = {};
|
|
10255
10884
|
try {
|
|
10256
|
-
claudeJson = JSON.parse(
|
|
10885
|
+
claudeJson = JSON.parse(readFileSync18(claudeJsonPath, "utf8"));
|
|
10257
10886
|
} catch {
|
|
10258
10887
|
}
|
|
10259
10888
|
if (!claudeJson.projects) claudeJson.projects = {};
|
|
@@ -10261,17 +10890,17 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
10261
10890
|
const trustDir = opts?.cwd ?? projectDir;
|
|
10262
10891
|
if (!projects[trustDir]) projects[trustDir] = {};
|
|
10263
10892
|
projects[trustDir].hasTrustDialogAccepted = true;
|
|
10264
|
-
|
|
10893
|
+
writeFileSync14(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
|
|
10265
10894
|
} catch {
|
|
10266
10895
|
}
|
|
10267
10896
|
try {
|
|
10268
|
-
const settingsDir =
|
|
10897
|
+
const settingsDir = path26.join(os13.homedir(), ".claude", "projects");
|
|
10269
10898
|
const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
|
|
10270
|
-
const projSettingsDir =
|
|
10271
|
-
const settingsPath =
|
|
10899
|
+
const projSettingsDir = path26.join(settingsDir, normalizedKey);
|
|
10900
|
+
const settingsPath = path26.join(projSettingsDir, "settings.json");
|
|
10272
10901
|
let settings = {};
|
|
10273
10902
|
try {
|
|
10274
|
-
settings = JSON.parse(
|
|
10903
|
+
settings = JSON.parse(readFileSync18(settingsPath, "utf8"));
|
|
10275
10904
|
} catch {
|
|
10276
10905
|
}
|
|
10277
10906
|
const perms = settings.permissions ?? {};
|
|
@@ -10299,8 +10928,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
10299
10928
|
if (changed) {
|
|
10300
10929
|
perms.allow = allow;
|
|
10301
10930
|
settings.permissions = perms;
|
|
10302
|
-
|
|
10303
|
-
|
|
10931
|
+
mkdirSync15(projSettingsDir, { recursive: true });
|
|
10932
|
+
writeFileSync14(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
10304
10933
|
}
|
|
10305
10934
|
} catch {
|
|
10306
10935
|
}
|
|
@@ -10315,8 +10944,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
10315
10944
|
let behaviorsFlag = "";
|
|
10316
10945
|
let legacyFallbackWarned = false;
|
|
10317
10946
|
if (!useExeAgent && !useBinSymlink) {
|
|
10318
|
-
const identityPath2 =
|
|
10319
|
-
|
|
10947
|
+
const identityPath2 = path26.join(
|
|
10948
|
+
os13.homedir(),
|
|
10320
10949
|
".exe-os",
|
|
10321
10950
|
"identity",
|
|
10322
10951
|
`${employeeName}.md`
|
|
@@ -10325,13 +10954,13 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
10325
10954
|
const hasAgentFlag = claudeSupportsAgentFlag();
|
|
10326
10955
|
if (hasAgentFlag) {
|
|
10327
10956
|
identityFlag = ` --agent ${employeeName}`;
|
|
10328
|
-
} else if (
|
|
10957
|
+
} else if (existsSync21(identityPath2)) {
|
|
10329
10958
|
identityFlag = ` --append-system-prompt-file ${identityPath2}`;
|
|
10330
10959
|
legacyFallbackWarned = true;
|
|
10331
10960
|
}
|
|
10332
10961
|
const behaviorsFile = exportBehaviorsSync(
|
|
10333
10962
|
employeeName,
|
|
10334
|
-
|
|
10963
|
+
path26.basename(spawnCwd),
|
|
10335
10964
|
sessionName
|
|
10336
10965
|
);
|
|
10337
10966
|
if (behaviorsFile) {
|
|
@@ -10346,16 +10975,16 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
10346
10975
|
}
|
|
10347
10976
|
let sessionContextFlag = "";
|
|
10348
10977
|
try {
|
|
10349
|
-
const ctxDir =
|
|
10350
|
-
|
|
10351
|
-
const ctxFile =
|
|
10978
|
+
const ctxDir = path26.join(os13.homedir(), ".exe-os", "session-cache");
|
|
10979
|
+
mkdirSync15(ctxDir, { recursive: true });
|
|
10980
|
+
const ctxFile = path26.join(ctxDir, `session-context-${sessionName}.md`);
|
|
10352
10981
|
const ctxContent = [
|
|
10353
10982
|
`## Session Context`,
|
|
10354
10983
|
`You are running in tmux session: ${sessionName}.`,
|
|
10355
10984
|
`Your parent coordinator session is ${exeSession}.`,
|
|
10356
10985
|
`Your employees (if any) use the -${exeSession} suffix.`
|
|
10357
10986
|
].join("\n");
|
|
10358
|
-
|
|
10987
|
+
writeFileSync14(ctxFile, ctxContent);
|
|
10359
10988
|
sessionContextFlag = ` --append-system-prompt-file ${ctxFile}`;
|
|
10360
10989
|
} catch {
|
|
10361
10990
|
}
|
|
@@ -10432,8 +11061,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
10432
11061
|
transport.pipeLog(sessionName, logFile);
|
|
10433
11062
|
try {
|
|
10434
11063
|
const mySession = getMySession();
|
|
10435
|
-
const dispatchInfo =
|
|
10436
|
-
|
|
11064
|
+
const dispatchInfo = path26.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
|
|
11065
|
+
writeFileSync14(dispatchInfo, JSON.stringify({
|
|
10437
11066
|
dispatchedBy: mySession,
|
|
10438
11067
|
rootExe: exeSession,
|
|
10439
11068
|
provider: useBinSymlink ? ccProvider : useExeAgent ? opts.provider : useCodex ? "openai" : useOpencode ? "opencode" : "anthropic",
|
|
@@ -10507,15 +11136,15 @@ var init_tmux_routing = __esm({
|
|
|
10507
11136
|
init_intercom_queue();
|
|
10508
11137
|
init_plan_limits();
|
|
10509
11138
|
init_employees();
|
|
10510
|
-
SPAWN_LOCK_DIR =
|
|
10511
|
-
SESSION_CACHE =
|
|
11139
|
+
SPAWN_LOCK_DIR = path26.join(os13.homedir(), ".exe-os", "spawn-locks");
|
|
11140
|
+
SESSION_CACHE = path26.join(os13.homedir(), ".exe-os", "session-cache");
|
|
10512
11141
|
BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
|
|
10513
11142
|
VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
|
|
10514
11143
|
VERIFY_PANE_LINES = 200;
|
|
10515
11144
|
INTERCOM_DEBOUNCE_MS = 3e4;
|
|
10516
11145
|
CODEX_DEBOUNCE_MS = 12e4;
|
|
10517
|
-
INTERCOM_LOG2 =
|
|
10518
|
-
DEBOUNCE_FILE =
|
|
11146
|
+
INTERCOM_LOG2 = path26.join(os13.homedir(), ".exe-os", "intercom.log");
|
|
11147
|
+
DEBOUNCE_FILE = path26.join(SESSION_CACHE, "intercom-debounce.json");
|
|
10519
11148
|
DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
|
|
10520
11149
|
BUSY_PATTERN = /[✻✽✶✳·].*…|Running…|• Working|• Ran |• Explored|• Called|esc to interrupt/;
|
|
10521
11150
|
}
|
|
@@ -10782,9 +11411,9 @@ __export(active_agent_exports, {
|
|
|
10782
11411
|
resolveActiveAgentFromTmuxSession: () => resolveActiveAgentFromTmuxSession,
|
|
10783
11412
|
writeActiveAgent: () => writeActiveAgent
|
|
10784
11413
|
});
|
|
10785
|
-
import { readFileSync as
|
|
11414
|
+
import { readFileSync as readFileSync19, writeFileSync as writeFileSync15, mkdirSync as mkdirSync16, unlinkSync as unlinkSync9, readdirSync as readdirSync6 } from "fs";
|
|
10786
11415
|
import { execSync as execSync9 } from "child_process";
|
|
10787
|
-
import
|
|
11416
|
+
import path27 from "path";
|
|
10788
11417
|
function isNameWithOptionalInstance(candidate, baseName) {
|
|
10789
11418
|
if (candidate === baseName) return true;
|
|
10790
11419
|
if (!candidate.startsWith(baseName)) return false;
|
|
@@ -10828,12 +11457,12 @@ function resolveActiveAgentFromTmuxSession(sessionName) {
|
|
|
10828
11457
|
return null;
|
|
10829
11458
|
}
|
|
10830
11459
|
function getMarkerPath() {
|
|
10831
|
-
return
|
|
11460
|
+
return path27.join(CACHE_DIR, `active-agent-${getSessionKey()}.json`);
|
|
10832
11461
|
}
|
|
10833
11462
|
function writeActiveAgent(agentId, agentRole) {
|
|
10834
11463
|
try {
|
|
10835
|
-
|
|
10836
|
-
|
|
11464
|
+
mkdirSync16(CACHE_DIR, { recursive: true });
|
|
11465
|
+
writeFileSync15(
|
|
10837
11466
|
getMarkerPath(),
|
|
10838
11467
|
JSON.stringify({ agentId, agentRole, startedAt: (/* @__PURE__ */ new Date()).toISOString() })
|
|
10839
11468
|
);
|
|
@@ -10849,7 +11478,7 @@ function clearActiveAgent() {
|
|
|
10849
11478
|
function getActiveAgent() {
|
|
10850
11479
|
try {
|
|
10851
11480
|
const markerPath = getMarkerPath();
|
|
10852
|
-
const raw =
|
|
11481
|
+
const raw = readFileSync19(markerPath, "utf8");
|
|
10853
11482
|
const data = JSON.parse(raw);
|
|
10854
11483
|
if (data.agentId) {
|
|
10855
11484
|
if (data.startedAt) {
|
|
@@ -10890,21 +11519,21 @@ function getActiveAgent() {
|
|
|
10890
11519
|
}
|
|
10891
11520
|
function getAllActiveAgents() {
|
|
10892
11521
|
try {
|
|
10893
|
-
const files =
|
|
11522
|
+
const files = readdirSync6(CACHE_DIR);
|
|
10894
11523
|
const sessions = [];
|
|
10895
11524
|
for (const file of files) {
|
|
10896
11525
|
if (!file.startsWith("active-agent-") || !file.endsWith(".json")) continue;
|
|
10897
11526
|
const key = file.slice("active-agent-".length, -".json".length);
|
|
10898
11527
|
if (key === "undefined") continue;
|
|
10899
11528
|
try {
|
|
10900
|
-
const raw =
|
|
11529
|
+
const raw = readFileSync19(path27.join(CACHE_DIR, file), "utf8");
|
|
10901
11530
|
const data = JSON.parse(raw);
|
|
10902
11531
|
if (!data.agentId) continue;
|
|
10903
11532
|
if (data.startedAt) {
|
|
10904
11533
|
const age = Date.now() - new Date(data.startedAt).getTime();
|
|
10905
11534
|
if (age > STALE_MS) {
|
|
10906
11535
|
try {
|
|
10907
|
-
unlinkSync9(
|
|
11536
|
+
unlinkSync9(path27.join(CACHE_DIR, file));
|
|
10908
11537
|
} catch {
|
|
10909
11538
|
}
|
|
10910
11539
|
continue;
|
|
@@ -10927,11 +11556,11 @@ function getAllActiveAgents() {
|
|
|
10927
11556
|
function cleanupSessionMarkers() {
|
|
10928
11557
|
const key = getSessionKey();
|
|
10929
11558
|
try {
|
|
10930
|
-
unlinkSync9(
|
|
11559
|
+
unlinkSync9(path27.join(CACHE_DIR, `active-agent-${key}.json`));
|
|
10931
11560
|
} catch {
|
|
10932
11561
|
}
|
|
10933
11562
|
try {
|
|
10934
|
-
unlinkSync9(
|
|
11563
|
+
unlinkSync9(path27.join(CACHE_DIR, "active-agent-undefined.json"));
|
|
10935
11564
|
} catch {
|
|
10936
11565
|
}
|
|
10937
11566
|
}
|
|
@@ -10942,7 +11571,7 @@ var init_active_agent = __esm({
|
|
|
10942
11571
|
init_config();
|
|
10943
11572
|
init_session_key();
|
|
10944
11573
|
init_employees();
|
|
10945
|
-
CACHE_DIR =
|
|
11574
|
+
CACHE_DIR = path27.join(EXE_AI_DIR, "session-cache");
|
|
10946
11575
|
STALE_MS = 24 * 60 * 60 * 1e3;
|
|
10947
11576
|
}
|
|
10948
11577
|
});
|
|
@@ -11078,10 +11707,10 @@ You report to the COO. All work flows through the COO. These procedures are non-
|
|
|
11078
11707
|
Use store_memory to write a structured summary. Include: project name, what was done,
|
|
11079
11708
|
decisions made, tests status, open items or risks.
|
|
11080
11709
|
|
|
11081
|
-
6. AFTER committing changes to exe-os itself \u2014 REBUILD
|
|
11082
|
-
-
|
|
11083
|
-
-
|
|
11084
|
-
-
|
|
11710
|
+
6. AFTER committing changes to exe-os itself \u2014 REBUILD:
|
|
11711
|
+
- If you are the COO or CTO on the MAIN branch (not a worktree): run \`npm run deploy\`.
|
|
11712
|
+
- If you are in a git worktree: run \`npm run build\` ONLY. NEVER run deploy from a worktree \u2014 it re-registers hooks pointing at the worktree path, and deleting the worktree breaks every hook system-wide.
|
|
11713
|
+
- Engineers and specialists: ALWAYS use \`npm run build\` only. Deploy is restricted to COO and CTO on main.
|
|
11085
11714
|
- If the build fails, fix the error and retry before moving on.
|
|
11086
11715
|
|
|
11087
11716
|
7. AFTER reporting \u2014 CHECK FOR NEXT WORK (mandatory):
|
|
@@ -11570,14 +12199,14 @@ __export(exe_rename_exports, {
|
|
|
11570
12199
|
main: () => main2,
|
|
11571
12200
|
renameEmployee: () => renameEmployee
|
|
11572
12201
|
});
|
|
11573
|
-
import { readFileSync as
|
|
12202
|
+
import { readFileSync as readFileSync20, writeFileSync as writeFileSync16, renameSync as renameSync4, unlinkSync as unlinkSync10, existsSync as existsSync22 } from "fs";
|
|
11574
12203
|
import { execSync as execSync10 } from "child_process";
|
|
11575
|
-
import
|
|
12204
|
+
import path28 from "path";
|
|
11576
12205
|
import { homedir as homedir4 } from "os";
|
|
11577
12206
|
async function renameEmployee(oldName, newName, opts = {}) {
|
|
11578
|
-
const rosterPath = opts.rosterPath ??
|
|
11579
|
-
const identityDir = opts.identityDir ??
|
|
11580
|
-
const agentsDir = opts.agentsDir ??
|
|
12207
|
+
const rosterPath = opts.rosterPath ?? path28.join(homedir4(), ".exe-os", "exe-employees.json");
|
|
12208
|
+
const identityDir = opts.identityDir ?? path28.join(homedir4(), ".exe-os", "identity");
|
|
12209
|
+
const agentsDir = opts.agentsDir ?? path28.join(homedir4(), ".claude", "agents");
|
|
11581
12210
|
const validation = validateEmployeeName(newName);
|
|
11582
12211
|
if (!validation.valid) {
|
|
11583
12212
|
return { success: false, error: validation.error };
|
|
@@ -11606,40 +12235,40 @@ async function renameEmployee(oldName, newName, opts = {}) {
|
|
|
11606
12235
|
undo: () => {
|
|
11607
12236
|
employee.name = originalName;
|
|
11608
12237
|
employee.systemPrompt = originalPrompt;
|
|
11609
|
-
|
|
12238
|
+
writeFileSync16(rosterPath, JSON.stringify(employees, null, 2) + "\n", "utf-8");
|
|
11610
12239
|
}
|
|
11611
12240
|
});
|
|
11612
|
-
const oldIdentityPath =
|
|
11613
|
-
const newIdentityPath =
|
|
11614
|
-
if (
|
|
11615
|
-
const content =
|
|
12241
|
+
const oldIdentityPath = path28.join(identityDir, `${rosterOldName}.md`);
|
|
12242
|
+
const newIdentityPath = path28.join(identityDir, `${newName}.md`);
|
|
12243
|
+
if (existsSync22(oldIdentityPath)) {
|
|
12244
|
+
const content = readFileSync20(oldIdentityPath, "utf-8");
|
|
11616
12245
|
const updatedContent = content.replace(
|
|
11617
12246
|
/^(agent_id:\s*)\S+/m,
|
|
11618
12247
|
`$1${newName}`
|
|
11619
12248
|
);
|
|
11620
12249
|
renameSync4(oldIdentityPath, newIdentityPath);
|
|
11621
|
-
|
|
12250
|
+
writeFileSync16(newIdentityPath, updatedContent, "utf-8");
|
|
11622
12251
|
rollbackStack.push({
|
|
11623
12252
|
description: "restore identity file",
|
|
11624
12253
|
undo: () => {
|
|
11625
|
-
if (
|
|
11626
|
-
|
|
12254
|
+
if (existsSync22(newIdentityPath)) {
|
|
12255
|
+
writeFileSync16(newIdentityPath, content, "utf-8");
|
|
11627
12256
|
renameSync4(newIdentityPath, oldIdentityPath);
|
|
11628
12257
|
}
|
|
11629
12258
|
}
|
|
11630
12259
|
});
|
|
11631
12260
|
}
|
|
11632
|
-
const oldAgentPath =
|
|
11633
|
-
const newAgentPath =
|
|
11634
|
-
if (
|
|
11635
|
-
const agentContent =
|
|
12261
|
+
const oldAgentPath = path28.join(agentsDir, `${rosterOldName}.md`);
|
|
12262
|
+
const newAgentPath = path28.join(agentsDir, `${newName}.md`);
|
|
12263
|
+
if (existsSync22(oldAgentPath)) {
|
|
12264
|
+
const agentContent = readFileSync20(oldAgentPath, "utf-8");
|
|
11636
12265
|
renameSync4(oldAgentPath, newAgentPath);
|
|
11637
12266
|
rollbackStack.push({
|
|
11638
12267
|
description: "restore agent file",
|
|
11639
12268
|
undo: () => {
|
|
11640
|
-
if (
|
|
12269
|
+
if (existsSync22(newAgentPath)) {
|
|
11641
12270
|
renameSync4(newAgentPath, oldAgentPath);
|
|
11642
|
-
|
|
12271
|
+
writeFileSync16(oldAgentPath, agentContent, "utf-8");
|
|
11643
12272
|
}
|
|
11644
12273
|
}
|
|
11645
12274
|
});
|
|
@@ -11717,10 +12346,10 @@ function removeOldSymlinks(name) {
|
|
|
11717
12346
|
try {
|
|
11718
12347
|
const exeBinPath = findExeBin2();
|
|
11719
12348
|
if (!exeBinPath) return;
|
|
11720
|
-
const binDir =
|
|
12349
|
+
const binDir = path28.dirname(exeBinPath);
|
|
11721
12350
|
for (const suffix of ["", "-opencode"]) {
|
|
11722
|
-
const linkPath =
|
|
11723
|
-
if (
|
|
12351
|
+
const linkPath = path28.join(binDir, `${name}${suffix}`);
|
|
12352
|
+
if (existsSync22(linkPath)) {
|
|
11724
12353
|
try {
|
|
11725
12354
|
unlinkSync10(linkPath);
|
|
11726
12355
|
} catch {
|
|
@@ -11765,16 +12394,16 @@ var init_exe_rename = __esm({
|
|
|
11765
12394
|
});
|
|
11766
12395
|
|
|
11767
12396
|
// src/lib/model-downloader.ts
|
|
11768
|
-
import { createWriteStream, createReadStream as createReadStream2, existsSync as
|
|
12397
|
+
import { createWriteStream, createReadStream as createReadStream2, existsSync as existsSync23, unlinkSync as unlinkSync11, renameSync as renameSync5 } from "fs";
|
|
11769
12398
|
import { mkdir as mkdir6 } from "fs/promises";
|
|
11770
|
-
import { createHash as
|
|
11771
|
-
import
|
|
12399
|
+
import { createHash as createHash3 } from "crypto";
|
|
12400
|
+
import path29 from "path";
|
|
11772
12401
|
async function downloadModel(opts) {
|
|
11773
12402
|
const { destDir, onProgress, fetchFn = globalThis.fetch } = opts;
|
|
11774
|
-
const destPath =
|
|
12403
|
+
const destPath = path29.join(destDir, LOCAL_FILENAME);
|
|
11775
12404
|
const tmpPath = destPath + ".tmp";
|
|
11776
12405
|
await mkdir6(destDir, { recursive: true });
|
|
11777
|
-
if (
|
|
12406
|
+
if (existsSync23(destPath)) {
|
|
11778
12407
|
const hash = await fileHash(destPath);
|
|
11779
12408
|
if (hash === EXPECTED_SHA256) {
|
|
11780
12409
|
return destPath;
|
|
@@ -11786,7 +12415,7 @@ async function downloadModel(opts) {
|
|
|
11786
12415
|
let downloaded = 0;
|
|
11787
12416
|
for (let attempt = 1; attempt <= MAX_RETRIES4; attempt++) {
|
|
11788
12417
|
try {
|
|
11789
|
-
if (
|
|
12418
|
+
if (existsSync23(tmpPath)) unlinkSync11(tmpPath);
|
|
11790
12419
|
const response = await fetchFn(GGUF_URL, {
|
|
11791
12420
|
redirect: "follow",
|
|
11792
12421
|
signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS)
|
|
@@ -11795,7 +12424,7 @@ async function downloadModel(opts) {
|
|
|
11795
12424
|
throw new Error(`Download failed: HTTP ${response.status}`);
|
|
11796
12425
|
}
|
|
11797
12426
|
const contentLength = Number(response.headers.get("content-length") ?? EXPECTED_SIZE);
|
|
11798
|
-
const hash =
|
|
12427
|
+
const hash = createHash3("sha256");
|
|
11799
12428
|
const fileStream = createWriteStream(tmpPath);
|
|
11800
12429
|
const reader = response.body.getReader();
|
|
11801
12430
|
try {
|
|
@@ -11831,7 +12460,7 @@ async function downloadModel(opts) {
|
|
|
11831
12460
|
process.stderr.write(`
|
|
11832
12461
|
Download attempt ${attempt} failed, retrying...
|
|
11833
12462
|
`);
|
|
11834
|
-
if (
|
|
12463
|
+
if (existsSync23(tmpPath)) unlinkSync11(tmpPath);
|
|
11835
12464
|
}
|
|
11836
12465
|
}
|
|
11837
12466
|
}
|
|
@@ -11839,7 +12468,7 @@ Download attempt ${attempt} failed, retrying...
|
|
|
11839
12468
|
}
|
|
11840
12469
|
async function fileHash(filePath) {
|
|
11841
12470
|
return new Promise((resolve, reject) => {
|
|
11842
|
-
const hash =
|
|
12471
|
+
const hash = createHash3("sha256");
|
|
11843
12472
|
const stream = createReadStream2(filePath);
|
|
11844
12473
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
11845
12474
|
stream.on("end", () => resolve(hash.digest("hex")));
|
|
@@ -11894,10 +12523,10 @@ async function disposeEmbedder() {
|
|
|
11894
12523
|
async function embedDirect(text) {
|
|
11895
12524
|
const llamaCpp = await import("node-llama-cpp");
|
|
11896
12525
|
const { MODELS_DIR: MODELS_DIR2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
11897
|
-
const { existsSync:
|
|
11898
|
-
const
|
|
11899
|
-
const modelPath =
|
|
11900
|
-
if (!
|
|
12526
|
+
const { existsSync: existsSync30 } = await import("fs");
|
|
12527
|
+
const path44 = await import("path");
|
|
12528
|
+
const modelPath = path44.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
|
|
12529
|
+
if (!existsSync30(modelPath)) {
|
|
11901
12530
|
throw new Error(`Embedding model not found at ${modelPath}. Run '/exe-setup' to download it.`);
|
|
11902
12531
|
}
|
|
11903
12532
|
const llama = await llamaCpp.getLlama();
|
|
@@ -11925,141 +12554,6 @@ var init_embedder = __esm({
|
|
|
11925
12554
|
}
|
|
11926
12555
|
});
|
|
11927
12556
|
|
|
11928
|
-
// src/lib/identity.ts
|
|
11929
|
-
var identity_exports = {};
|
|
11930
|
-
__export(identity_exports, {
|
|
11931
|
-
getIdentity: () => getIdentity,
|
|
11932
|
-
getIdentityInjection: () => getIdentityInjection,
|
|
11933
|
-
identityPath: () => identityPath,
|
|
11934
|
-
listIdentities: () => listIdentities,
|
|
11935
|
-
updateIdentity: () => updateIdentity
|
|
11936
|
-
});
|
|
11937
|
-
import { existsSync as existsSync22, mkdirSync as mkdirSync14, readFileSync as readFileSync18, writeFileSync as writeFileSync14 } from "fs";
|
|
11938
|
-
import { readdirSync as readdirSync6 } from "fs";
|
|
11939
|
-
import path27 from "path";
|
|
11940
|
-
import { createHash as createHash3 } from "crypto";
|
|
11941
|
-
function ensureDir2() {
|
|
11942
|
-
if (!existsSync22(IDENTITY_DIR)) {
|
|
11943
|
-
mkdirSync14(IDENTITY_DIR, { recursive: true });
|
|
11944
|
-
}
|
|
11945
|
-
}
|
|
11946
|
-
function identityPath(agentId) {
|
|
11947
|
-
return path27.join(IDENTITY_DIR, `${agentId}.md`);
|
|
11948
|
-
}
|
|
11949
|
-
function parseFrontmatter(raw) {
|
|
11950
|
-
const match = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
11951
|
-
if (!match) {
|
|
11952
|
-
return {
|
|
11953
|
-
frontmatter: {
|
|
11954
|
-
role: "unknown",
|
|
11955
|
-
title: "Unknown",
|
|
11956
|
-
agent_id: "unknown",
|
|
11957
|
-
org_level: "specialist",
|
|
11958
|
-
created_by: "system",
|
|
11959
|
-
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
11960
|
-
},
|
|
11961
|
-
body: raw
|
|
11962
|
-
};
|
|
11963
|
-
}
|
|
11964
|
-
const yamlStr = match[1];
|
|
11965
|
-
const body = match[2].trim();
|
|
11966
|
-
const fm = {};
|
|
11967
|
-
for (const line of yamlStr.split("\n")) {
|
|
11968
|
-
const kv = line.match(/^(\w+):\s*(.+)$/);
|
|
11969
|
-
if (kv) fm[kv[1]] = kv[2].trim();
|
|
11970
|
-
}
|
|
11971
|
-
return {
|
|
11972
|
-
frontmatter: {
|
|
11973
|
-
role: fm.role ?? "unknown",
|
|
11974
|
-
title: fm.title ?? "Unknown",
|
|
11975
|
-
agent_id: fm.agent_id ?? "unknown",
|
|
11976
|
-
org_level: fm.org_level ?? "specialist",
|
|
11977
|
-
created_by: fm.created_by ?? "system",
|
|
11978
|
-
updated_at: fm.updated_at ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
11979
|
-
},
|
|
11980
|
-
body
|
|
11981
|
-
};
|
|
11982
|
-
}
|
|
11983
|
-
function contentHash(content) {
|
|
11984
|
-
return createHash3("sha256").update(content).digest("hex").slice(0, 16);
|
|
11985
|
-
}
|
|
11986
|
-
function getIdentity(agentId) {
|
|
11987
|
-
const filePath = identityPath(agentId);
|
|
11988
|
-
if (!existsSync22(filePath)) return null;
|
|
11989
|
-
const raw = readFileSync18(filePath, "utf-8");
|
|
11990
|
-
const { frontmatter, body } = parseFrontmatter(raw);
|
|
11991
|
-
return {
|
|
11992
|
-
agentId,
|
|
11993
|
-
frontmatter,
|
|
11994
|
-
body,
|
|
11995
|
-
raw,
|
|
11996
|
-
contentHash: contentHash(raw)
|
|
11997
|
-
};
|
|
11998
|
-
}
|
|
11999
|
-
async function updateIdentity(agentId, content, updatedBy) {
|
|
12000
|
-
ensureDir2();
|
|
12001
|
-
const filePath = identityPath(agentId);
|
|
12002
|
-
const hash = contentHash(content);
|
|
12003
|
-
writeFileSync14(filePath, content, "utf-8");
|
|
12004
|
-
try {
|
|
12005
|
-
const client = getClient();
|
|
12006
|
-
await client.execute({
|
|
12007
|
-
sql: `INSERT INTO identity (agent_id, content_hash, updated_at, updated_by)
|
|
12008
|
-
VALUES (?, ?, ?, ?)
|
|
12009
|
-
ON CONFLICT(agent_id) DO UPDATE SET
|
|
12010
|
-
content_hash = excluded.content_hash,
|
|
12011
|
-
updated_at = excluded.updated_at,
|
|
12012
|
-
updated_by = excluded.updated_by`,
|
|
12013
|
-
args: [agentId, hash, (/* @__PURE__ */ new Date()).toISOString(), updatedBy]
|
|
12014
|
-
});
|
|
12015
|
-
} catch {
|
|
12016
|
-
}
|
|
12017
|
-
}
|
|
12018
|
-
function listIdentities() {
|
|
12019
|
-
ensureDir2();
|
|
12020
|
-
const files = readdirSync6(IDENTITY_DIR).filter((f) => f.endsWith(".md"));
|
|
12021
|
-
const results = [];
|
|
12022
|
-
for (const file of files) {
|
|
12023
|
-
const agentId = file.replace(".md", "");
|
|
12024
|
-
const identity = getIdentity(agentId);
|
|
12025
|
-
if (!identity) continue;
|
|
12026
|
-
const lines = identity.body.split("\n").filter((l) => l.trim() && !l.startsWith("#"));
|
|
12027
|
-
const summary = lines[0]?.trim().slice(0, 120) ?? identity.frontmatter.title;
|
|
12028
|
-
results.push({
|
|
12029
|
-
agentId,
|
|
12030
|
-
title: `${identity.frontmatter.title} (${identity.frontmatter.role.toUpperCase()})`,
|
|
12031
|
-
summary
|
|
12032
|
-
});
|
|
12033
|
-
}
|
|
12034
|
-
return results;
|
|
12035
|
-
}
|
|
12036
|
-
function getIdentityInjection(agentId) {
|
|
12037
|
-
const own = getIdentity(agentId);
|
|
12038
|
-
const all = listIdentities();
|
|
12039
|
-
const parts = [];
|
|
12040
|
-
if (own) {
|
|
12041
|
-
parts.push(`## Your Identity (exe.md)
|
|
12042
|
-
These define WHO YOU ARE. Non-negotiable. Permanent.
|
|
12043
|
-
|
|
12044
|
-
${own.body}`);
|
|
12045
|
-
}
|
|
12046
|
-
const teamLines = all.filter((a) => a.agentId !== agentId).map((a) => `- ${a.agentId} (${a.title}): ${a.summary}`);
|
|
12047
|
-
if (teamLines.length > 0) {
|
|
12048
|
-
parts.push(`## Team Identities
|
|
12049
|
-
${teamLines.join("\n")}`);
|
|
12050
|
-
}
|
|
12051
|
-
return parts.join("\n\n");
|
|
12052
|
-
}
|
|
12053
|
-
var IDENTITY_DIR;
|
|
12054
|
-
var init_identity = __esm({
|
|
12055
|
-
"src/lib/identity.ts"() {
|
|
12056
|
-
"use strict";
|
|
12057
|
-
init_config();
|
|
12058
|
-
init_database();
|
|
12059
|
-
IDENTITY_DIR = path27.join(EXE_AI_DIR, "identity");
|
|
12060
|
-
}
|
|
12061
|
-
});
|
|
12062
|
-
|
|
12063
12557
|
// src/lib/identity-templates.ts
|
|
12064
12558
|
var identity_templates_exports = {};
|
|
12065
12559
|
__export(identity_templates_exports, {
|
|
@@ -12607,36 +13101,36 @@ __export(session_wrappers_exports, {
|
|
|
12607
13101
|
generateSessionWrappers: () => generateSessionWrappers
|
|
12608
13102
|
});
|
|
12609
13103
|
import {
|
|
12610
|
-
existsSync as
|
|
12611
|
-
readFileSync as
|
|
12612
|
-
writeFileSync as
|
|
12613
|
-
mkdirSync as
|
|
13104
|
+
existsSync as existsSync24,
|
|
13105
|
+
readFileSync as readFileSync21,
|
|
13106
|
+
writeFileSync as writeFileSync17,
|
|
13107
|
+
mkdirSync as mkdirSync17,
|
|
12614
13108
|
chmodSync,
|
|
12615
13109
|
readdirSync as readdirSync7,
|
|
12616
13110
|
unlinkSync as unlinkSync12
|
|
12617
13111
|
} from "fs";
|
|
12618
|
-
import
|
|
13112
|
+
import path30 from "path";
|
|
12619
13113
|
import { homedir as homedir5 } from "os";
|
|
12620
13114
|
function generateSessionWrappers(packageRoot, homeDir) {
|
|
12621
13115
|
const home = homeDir ?? homedir5();
|
|
12622
|
-
const binDir =
|
|
12623
|
-
const rosterPath =
|
|
12624
|
-
|
|
12625
|
-
const exeStartDst =
|
|
13116
|
+
const binDir = path30.join(home, ".exe-os", "bin");
|
|
13117
|
+
const rosterPath = path30.join(home, ".exe-os", "exe-employees.json");
|
|
13118
|
+
mkdirSync17(binDir, { recursive: true });
|
|
13119
|
+
const exeStartDst = path30.join(binDir, "exe-start");
|
|
12626
13120
|
const candidates = [
|
|
12627
|
-
|
|
12628
|
-
|
|
13121
|
+
path30.join(packageRoot, "dist", "bin", "exe-start.sh"),
|
|
13122
|
+
path30.join(packageRoot, "src", "bin", "exe-start.sh")
|
|
12629
13123
|
];
|
|
12630
13124
|
for (const src of candidates) {
|
|
12631
|
-
if (
|
|
12632
|
-
|
|
13125
|
+
if (existsSync24(src)) {
|
|
13126
|
+
writeFileSync17(exeStartDst, readFileSync21(src));
|
|
12633
13127
|
chmodSync(exeStartDst, 493);
|
|
12634
13128
|
break;
|
|
12635
13129
|
}
|
|
12636
13130
|
}
|
|
12637
13131
|
let employees = [];
|
|
12638
13132
|
try {
|
|
12639
|
-
employees = JSON.parse(
|
|
13133
|
+
employees = JSON.parse(readFileSync21(rosterPath, "utf8"));
|
|
12640
13134
|
} catch {
|
|
12641
13135
|
return { created: 0, pathConfigured: false };
|
|
12642
13136
|
}
|
|
@@ -12646,9 +13140,9 @@ function generateSessionWrappers(packageRoot, homeDir) {
|
|
|
12646
13140
|
try {
|
|
12647
13141
|
for (const f of readdirSync7(binDir)) {
|
|
12648
13142
|
if (f === "exe-start") continue;
|
|
12649
|
-
const fPath =
|
|
13143
|
+
const fPath = path30.join(binDir, f);
|
|
12650
13144
|
try {
|
|
12651
|
-
const content =
|
|
13145
|
+
const content = readFileSync21(fPath, "utf8");
|
|
12652
13146
|
if (content.includes("exe-start")) {
|
|
12653
13147
|
unlinkSync12(fPath);
|
|
12654
13148
|
}
|
|
@@ -12663,30 +13157,30 @@ exec "${exeStartDst}" "$0" "$@"
|
|
|
12663
13157
|
`;
|
|
12664
13158
|
for (const emp of employees) {
|
|
12665
13159
|
for (let n = 1; n <= MAX_N; n++) {
|
|
12666
|
-
const wrapperPath =
|
|
12667
|
-
|
|
13160
|
+
const wrapperPath = path30.join(binDir, `${emp.name}${n}`);
|
|
13161
|
+
writeFileSync17(wrapperPath, wrapperContent);
|
|
12668
13162
|
chmodSync(wrapperPath, 493);
|
|
12669
13163
|
created++;
|
|
12670
13164
|
}
|
|
12671
13165
|
}
|
|
12672
13166
|
const codexLauncherCandidates = [
|
|
12673
|
-
|
|
12674
|
-
|
|
13167
|
+
path30.join(packageRoot, "dist", "bin", "exe-start-codex.js"),
|
|
13168
|
+
path30.join(packageRoot, "src", "bin", "exe-start-codex.ts")
|
|
12675
13169
|
];
|
|
12676
13170
|
let codexLauncher = null;
|
|
12677
13171
|
for (const c of codexLauncherCandidates) {
|
|
12678
|
-
if (
|
|
13172
|
+
if (existsSync24(c)) {
|
|
12679
13173
|
codexLauncher = c;
|
|
12680
13174
|
break;
|
|
12681
13175
|
}
|
|
12682
13176
|
}
|
|
12683
13177
|
if (codexLauncher) {
|
|
12684
13178
|
for (const emp of employees) {
|
|
12685
|
-
const wrapperPath =
|
|
13179
|
+
const wrapperPath = path30.join(binDir, `${emp.name}-codex`);
|
|
12686
13180
|
const content = `#!/bin/bash
|
|
12687
13181
|
exec node "${codexLauncher}" --agent ${emp.name} "$@"
|
|
12688
13182
|
`;
|
|
12689
|
-
|
|
13183
|
+
writeFileSync17(wrapperPath, content);
|
|
12690
13184
|
chmodSync(wrapperPath, 493);
|
|
12691
13185
|
created++;
|
|
12692
13186
|
}
|
|
@@ -12705,24 +13199,24 @@ export PATH="${binDir}:$PATH"
|
|
|
12705
13199
|
const shell = process.env.SHELL ?? "/bin/bash";
|
|
12706
13200
|
const profilePaths = [];
|
|
12707
13201
|
if (shell.includes("zsh")) {
|
|
12708
|
-
profilePaths.push(
|
|
13202
|
+
profilePaths.push(path30.join(home, ".zshrc"));
|
|
12709
13203
|
} else if (shell.includes("bash")) {
|
|
12710
|
-
profilePaths.push(
|
|
12711
|
-
profilePaths.push(
|
|
13204
|
+
profilePaths.push(path30.join(home, ".bashrc"));
|
|
13205
|
+
profilePaths.push(path30.join(home, ".bash_profile"));
|
|
12712
13206
|
} else {
|
|
12713
|
-
profilePaths.push(
|
|
13207
|
+
profilePaths.push(path30.join(home, ".profile"));
|
|
12714
13208
|
}
|
|
12715
13209
|
for (const profilePath of profilePaths) {
|
|
12716
13210
|
try {
|
|
12717
13211
|
let content = "";
|
|
12718
13212
|
try {
|
|
12719
|
-
content =
|
|
13213
|
+
content = readFileSync21(profilePath, "utf8");
|
|
12720
13214
|
} catch {
|
|
12721
13215
|
}
|
|
12722
13216
|
if (content.includes(".exe-os/bin")) {
|
|
12723
13217
|
return false;
|
|
12724
13218
|
}
|
|
12725
|
-
|
|
13219
|
+
writeFileSync17(profilePath, content + exportLine);
|
|
12726
13220
|
return true;
|
|
12727
13221
|
} catch {
|
|
12728
13222
|
continue;
|
|
@@ -12745,36 +13239,36 @@ __export(setup_wizard_exports, {
|
|
|
12745
13239
|
validateModel: () => validateModel
|
|
12746
13240
|
});
|
|
12747
13241
|
import crypto11 from "crypto";
|
|
12748
|
-
import { existsSync as
|
|
12749
|
-
import
|
|
12750
|
-
import
|
|
13242
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync18, readFileSync as readFileSync22, writeFileSync as writeFileSync18, unlinkSync as unlinkSync13 } from "fs";
|
|
13243
|
+
import os14 from "os";
|
|
13244
|
+
import path31 from "path";
|
|
12751
13245
|
import { createInterface as createInterface3 } from "readline";
|
|
12752
13246
|
function findPackageRoot2() {
|
|
12753
|
-
let dir =
|
|
12754
|
-
const root =
|
|
13247
|
+
let dir = path31.dirname(new URL(import.meta.url).pathname);
|
|
13248
|
+
const root = path31.parse(dir).root;
|
|
12755
13249
|
while (dir !== root) {
|
|
12756
|
-
const pkgPath =
|
|
12757
|
-
if (
|
|
13250
|
+
const pkgPath = path31.join(dir, "package.json");
|
|
13251
|
+
if (existsSync25(pkgPath)) {
|
|
12758
13252
|
try {
|
|
12759
|
-
const pkg = JSON.parse(
|
|
13253
|
+
const pkg = JSON.parse(readFileSync22(pkgPath, "utf-8"));
|
|
12760
13254
|
if (pkg.name === "@askexenow/exe-os" || pkg.name === "exe-os") return dir;
|
|
12761
13255
|
} catch {
|
|
12762
13256
|
}
|
|
12763
13257
|
}
|
|
12764
|
-
dir =
|
|
13258
|
+
dir = path31.dirname(dir);
|
|
12765
13259
|
}
|
|
12766
13260
|
return null;
|
|
12767
13261
|
}
|
|
12768
13262
|
function loadSetupState() {
|
|
12769
13263
|
try {
|
|
12770
|
-
return JSON.parse(
|
|
13264
|
+
return JSON.parse(readFileSync22(SETUP_STATE_PATH, "utf8"));
|
|
12771
13265
|
} catch {
|
|
12772
13266
|
return { completedSteps: [], startedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
12773
13267
|
}
|
|
12774
13268
|
}
|
|
12775
13269
|
function saveSetupState(state) {
|
|
12776
|
-
|
|
12777
|
-
|
|
13270
|
+
mkdirSync18(path31.dirname(SETUP_STATE_PATH), { recursive: true });
|
|
13271
|
+
writeFileSync18(SETUP_STATE_PATH, JSON.stringify(state, null, 2));
|
|
12778
13272
|
}
|
|
12779
13273
|
function clearSetupState() {
|
|
12780
13274
|
try {
|
|
@@ -12793,10 +13287,10 @@ function ask2(rl, prompt) {
|
|
|
12793
13287
|
});
|
|
12794
13288
|
}
|
|
12795
13289
|
function getAvailableMemoryGB() {
|
|
12796
|
-
return
|
|
13290
|
+
return os14.freemem() / (1024 * 1024 * 1024);
|
|
12797
13291
|
}
|
|
12798
13292
|
function getTotalMemoryGB() {
|
|
12799
|
-
return
|
|
13293
|
+
return os14.totalmem() / (1024 * 1024 * 1024);
|
|
12800
13294
|
}
|
|
12801
13295
|
function isLowMemory() {
|
|
12802
13296
|
return getAvailableMemoryGB() < 2;
|
|
@@ -12807,8 +13301,8 @@ async function validateModel(log) {
|
|
|
12807
13301
|
if (totalGB <= 8 || isLowMemory()) {
|
|
12808
13302
|
log(`System memory: ${totalGB.toFixed(0)}GB total, ${freeGB.toFixed(1)}GB free`);
|
|
12809
13303
|
log("Skipping in-memory model validation (low memory \u2014 will validate on first use).");
|
|
12810
|
-
const modelPath =
|
|
12811
|
-
if (
|
|
13304
|
+
const modelPath = path31.join(MODELS_DIR, LOCAL_FILENAME);
|
|
13305
|
+
if (existsSync25(modelPath)) {
|
|
12812
13306
|
const { statSync: statSync2 } = await import("fs");
|
|
12813
13307
|
const size = statSync2(modelPath).size;
|
|
12814
13308
|
if (size > 300 * 1e6) {
|
|
@@ -12899,7 +13393,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
12899
13393
|
if (state.completedSteps.length > 0) {
|
|
12900
13394
|
log(`Resuming setup from step ${Math.max(...state.completedSteps) + 1}...`);
|
|
12901
13395
|
}
|
|
12902
|
-
if (
|
|
13396
|
+
if (existsSync25(LEGACY_LANCE_PATH)) {
|
|
12903
13397
|
log("\u26A0 Found v1.0 LanceDB at ~/.exe-os/local.lance");
|
|
12904
13398
|
log(" v1.1 uses libSQL (SQLite). Your existing memories are not automatically migrated.");
|
|
12905
13399
|
log(" The old directory will not be modified or deleted.");
|
|
@@ -13063,19 +13557,19 @@ async function runSetupWizard(opts = {}) {
|
|
|
13063
13557
|
await saveConfig(config);
|
|
13064
13558
|
log("");
|
|
13065
13559
|
try {
|
|
13066
|
-
const claudeJsonPath =
|
|
13560
|
+
const claudeJsonPath = path31.join(os14.homedir(), ".claude.json");
|
|
13067
13561
|
let claudeJson = {};
|
|
13068
13562
|
try {
|
|
13069
|
-
claudeJson = JSON.parse(
|
|
13563
|
+
claudeJson = JSON.parse(readFileSync22(claudeJsonPath, "utf8"));
|
|
13070
13564
|
} catch {
|
|
13071
13565
|
}
|
|
13072
13566
|
if (!claudeJson.projects) claudeJson.projects = {};
|
|
13073
13567
|
const projects = claudeJson.projects;
|
|
13074
|
-
for (const dir of [process.cwd(),
|
|
13568
|
+
for (const dir of [process.cwd(), os14.homedir()]) {
|
|
13075
13569
|
if (!projects[dir]) projects[dir] = {};
|
|
13076
13570
|
projects[dir].hasTrustDialogAccepted = true;
|
|
13077
13571
|
}
|
|
13078
|
-
|
|
13572
|
+
writeFileSync18(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
|
|
13079
13573
|
} catch {
|
|
13080
13574
|
}
|
|
13081
13575
|
state.completedSteps.push(5);
|
|
@@ -13089,7 +13583,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
13089
13583
|
const prefs = { ...existingPrefs };
|
|
13090
13584
|
log("=== Config Defaults ===");
|
|
13091
13585
|
log("");
|
|
13092
|
-
const ghosttyDetected =
|
|
13586
|
+
const ghosttyDetected = existsSync25(path31.join(os14.homedir(), ".config", "ghostty")) || existsSync25(path31.join(os14.homedir(), "Library", "Application Support", "com.mitchellh.ghostty"));
|
|
13093
13587
|
if (ghosttyDetected) {
|
|
13094
13588
|
const ghosttyAnswer = await ask2(rl, "Detected Ghostty terminal. Use exe-os Ghostty defaults? (Y/n) ");
|
|
13095
13589
|
prefs.ghostty = ghosttyAnswer.toLowerCase() !== "n";
|
|
@@ -13136,7 +13630,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
13136
13630
|
let missingIdentities = [];
|
|
13137
13631
|
for (const emp of roster) {
|
|
13138
13632
|
const idPath = identityPath2(emp.name);
|
|
13139
|
-
if (!
|
|
13633
|
+
if (!existsSync25(idPath)) {
|
|
13140
13634
|
missingIdentities.push(emp.name);
|
|
13141
13635
|
}
|
|
13142
13636
|
}
|
|
@@ -13168,7 +13662,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
13168
13662
|
}
|
|
13169
13663
|
missingIdentities = [];
|
|
13170
13664
|
for (const emp of roster) {
|
|
13171
|
-
if (!
|
|
13665
|
+
if (!existsSync25(identityPath2(emp.name))) {
|
|
13172
13666
|
missingIdentities.push(emp.name);
|
|
13173
13667
|
}
|
|
13174
13668
|
}
|
|
@@ -13233,9 +13727,9 @@ async function runSetupWizard(opts = {}) {
|
|
|
13233
13727
|
const cooIdentityContent = getIdentityTemplate("coo");
|
|
13234
13728
|
if (cooIdentityContent) {
|
|
13235
13729
|
const cooIdPath = identityPath2(cooName);
|
|
13236
|
-
|
|
13730
|
+
mkdirSync18(path31.dirname(cooIdPath), { recursive: true });
|
|
13237
13731
|
const replaced = cooIdentityContent.replace(/agent_id:\s*exe/g, `agent_id: ${cooName}`).replace(/\$\{agent_id\}/g, cooName);
|
|
13238
|
-
|
|
13732
|
+
writeFileSync18(cooIdPath, replaced, "utf-8");
|
|
13239
13733
|
}
|
|
13240
13734
|
registerBinSymlinks2(cooName);
|
|
13241
13735
|
createdEmployees.push({ name: cooName, role: "COO" });
|
|
@@ -13329,9 +13823,9 @@ async function runSetupWizard(opts = {}) {
|
|
|
13329
13823
|
const ctoIdentityContent = getIdentityTemplate("cto");
|
|
13330
13824
|
if (ctoIdentityContent) {
|
|
13331
13825
|
const ctoIdPath = identityPath2(ctoName);
|
|
13332
|
-
|
|
13826
|
+
mkdirSync18(path31.dirname(ctoIdPath), { recursive: true });
|
|
13333
13827
|
const replaced = ctoIdentityContent.replace(/agent_id:\s*\w+/g, `agent_id: ${ctoName}`).replace(/\$\{agent_id\}/g, ctoName);
|
|
13334
|
-
|
|
13828
|
+
writeFileSync18(ctoIdPath, replaced, "utf-8");
|
|
13335
13829
|
}
|
|
13336
13830
|
registerBinSymlinks2(ctoName);
|
|
13337
13831
|
createdEmployees.push({ name: ctoName, role: "CTO" });
|
|
@@ -13352,9 +13846,9 @@ async function runSetupWizard(opts = {}) {
|
|
|
13352
13846
|
const cmoIdentityContent = getIdentityTemplate("cmo");
|
|
13353
13847
|
if (cmoIdentityContent) {
|
|
13354
13848
|
const cmoIdPath = identityPath2(cmoName);
|
|
13355
|
-
|
|
13849
|
+
mkdirSync18(path31.dirname(cmoIdPath), { recursive: true });
|
|
13356
13850
|
const replaced = cmoIdentityContent.replace(/agent_id:\s*\w+/g, `agent_id: ${cmoName}`).replace(/\$\{agent_id\}/g, cmoName);
|
|
13357
|
-
|
|
13851
|
+
writeFileSync18(cmoIdPath, replaced, "utf-8");
|
|
13358
13852
|
}
|
|
13359
13853
|
registerBinSymlinks2(cmoName);
|
|
13360
13854
|
createdEmployees.push({ name: cmoName, role: "CMO" });
|
|
@@ -13376,7 +13870,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
13376
13870
|
log(`Session shortcuts generated (${cooName}1, ${cooName}2, ...)`);
|
|
13377
13871
|
}
|
|
13378
13872
|
if (wrapResult.pathConfigured) {
|
|
13379
|
-
const binDir =
|
|
13873
|
+
const binDir = path31.join(os14.homedir(), ".exe-os", "bin");
|
|
13380
13874
|
process.env.PATH = `${binDir}:${process.env.PATH ?? ""}`;
|
|
13381
13875
|
pathJustConfigured = true;
|
|
13382
13876
|
}
|
|
@@ -13419,7 +13913,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
13419
13913
|
const pkgRoot2 = findPackageRoot2();
|
|
13420
13914
|
if (pkgRoot2) {
|
|
13421
13915
|
try {
|
|
13422
|
-
version = JSON.parse(
|
|
13916
|
+
version = JSON.parse(readFileSync22(path31.join(pkgRoot2, "package.json"), "utf-8")).version;
|
|
13423
13917
|
} catch {
|
|
13424
13918
|
}
|
|
13425
13919
|
}
|
|
@@ -13453,17 +13947,17 @@ var init_setup_wizard = __esm({
|
|
|
13453
13947
|
init_config();
|
|
13454
13948
|
init_keychain();
|
|
13455
13949
|
init_model_downloader();
|
|
13456
|
-
SETUP_STATE_PATH =
|
|
13950
|
+
SETUP_STATE_PATH = path31.join(os14.homedir(), ".exe-os", "setup-state.json");
|
|
13457
13951
|
}
|
|
13458
13952
|
});
|
|
13459
13953
|
|
|
13460
13954
|
// src/lib/update-check.ts
|
|
13461
13955
|
import { execSync as execSync11 } from "child_process";
|
|
13462
|
-
import { readFileSync as
|
|
13463
|
-
import
|
|
13956
|
+
import { readFileSync as readFileSync23 } from "fs";
|
|
13957
|
+
import path32 from "path";
|
|
13464
13958
|
function getLocalVersion(packageRoot) {
|
|
13465
|
-
const pkgPath =
|
|
13466
|
-
const pkg = JSON.parse(
|
|
13959
|
+
const pkgPath = path32.join(packageRoot, "package.json");
|
|
13960
|
+
const pkg = JSON.parse(readFileSync23(pkgPath, "utf-8"));
|
|
13467
13961
|
return pkg.version;
|
|
13468
13962
|
}
|
|
13469
13963
|
function getRemoteVersion() {
|
|
@@ -17987,8 +18481,8 @@ var init_ErrorOverview = __esm({
|
|
|
17987
18481
|
"use strict";
|
|
17988
18482
|
init_Box();
|
|
17989
18483
|
init_Text();
|
|
17990
|
-
cleanupPath = (
|
|
17991
|
-
return
|
|
18484
|
+
cleanupPath = (path44) => {
|
|
18485
|
+
return path44?.replace(`file://${cwd()}/`, "");
|
|
17992
18486
|
};
|
|
17993
18487
|
stackUtils = new StackUtils({
|
|
17994
18488
|
cwd: cwd(),
|
|
@@ -20396,11 +20890,11 @@ function Footer() {
|
|
|
20396
20890
|
} catch {
|
|
20397
20891
|
}
|
|
20398
20892
|
try {
|
|
20399
|
-
const { existsSync:
|
|
20893
|
+
const { existsSync: existsSync30 } = await import("fs");
|
|
20400
20894
|
const { join } = await import("path");
|
|
20401
20895
|
const home = process.env.HOME ?? "";
|
|
20402
20896
|
const pidPath = join(home, ".exe-os", "exed.pid");
|
|
20403
|
-
setDaemon(
|
|
20897
|
+
setDaemon(existsSync30(pidPath) ? "running" : "stopped");
|
|
20404
20898
|
} catch {
|
|
20405
20899
|
setDaemon("unknown");
|
|
20406
20900
|
}
|
|
@@ -22133,7 +22627,7 @@ var init_anthropic = __esm({
|
|
|
22133
22627
|
|
|
22134
22628
|
// src/gateway/providers/openai-compat.ts
|
|
22135
22629
|
import OpenAI from "openai";
|
|
22136
|
-
import { randomUUID as
|
|
22630
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
22137
22631
|
var OpenAICompatProvider;
|
|
22138
22632
|
var init_openai_compat = __esm({
|
|
22139
22633
|
"src/gateway/providers/openai-compat.ts"() {
|
|
@@ -22250,7 +22744,7 @@ var init_openai_compat = __esm({
|
|
|
22250
22744
|
}
|
|
22251
22745
|
content.push({
|
|
22252
22746
|
type: "tool_use",
|
|
22253
|
-
id: call.id ??
|
|
22747
|
+
id: call.id ?? randomUUID5(),
|
|
22254
22748
|
name: fn.name,
|
|
22255
22749
|
input
|
|
22256
22750
|
});
|
|
@@ -22442,10 +22936,10 @@ var init_hooks = __esm({
|
|
|
22442
22936
|
});
|
|
22443
22937
|
|
|
22444
22938
|
// src/runtime/safety-checks.ts
|
|
22445
|
-
import
|
|
22446
|
-
import
|
|
22939
|
+
import path33 from "path";
|
|
22940
|
+
import os15 from "os";
|
|
22447
22941
|
function checkPathSafety(filePath) {
|
|
22448
|
-
const resolved =
|
|
22942
|
+
const resolved = path33.resolve(filePath);
|
|
22449
22943
|
for (const { pattern, reason } of BYPASS_IMMUNE_PATTERNS) {
|
|
22450
22944
|
const matches = typeof pattern === "function" ? pattern(resolved) : pattern.test(resolved);
|
|
22451
22945
|
if (matches) {
|
|
@@ -22455,7 +22949,7 @@ function checkPathSafety(filePath) {
|
|
|
22455
22949
|
return { safe: true, bypassImmune: true };
|
|
22456
22950
|
}
|
|
22457
22951
|
function checkReadPathSafety(filePath) {
|
|
22458
|
-
const resolved =
|
|
22952
|
+
const resolved = path33.resolve(filePath);
|
|
22459
22953
|
const credPatterns = BYPASS_IMMUNE_PATTERNS.filter(
|
|
22460
22954
|
(p) => typeof p.pattern !== "function" && (p.reason.includes("secrets") || p.reason.includes("Private key") || p.reason.includes("Credential"))
|
|
22461
22955
|
);
|
|
@@ -22470,7 +22964,7 @@ var HOME, BYPASS_IMMUNE_PATTERNS;
|
|
|
22470
22964
|
var init_safety_checks = __esm({
|
|
22471
22965
|
"src/runtime/safety-checks.ts"() {
|
|
22472
22966
|
"use strict";
|
|
22473
|
-
HOME =
|
|
22967
|
+
HOME = os15.homedir();
|
|
22474
22968
|
BYPASS_IMMUNE_PATTERNS = [
|
|
22475
22969
|
{
|
|
22476
22970
|
pattern: /\/\.git\/hooks\//,
|
|
@@ -22481,11 +22975,11 @@ var init_safety_checks = __esm({
|
|
|
22481
22975
|
reason: "Git config can set hooks and command execution"
|
|
22482
22976
|
},
|
|
22483
22977
|
{
|
|
22484
|
-
pattern: (p) => p.startsWith(
|
|
22978
|
+
pattern: (p) => p.startsWith(path33.join(HOME, ".claude")),
|
|
22485
22979
|
reason: "Claude configuration files are protected"
|
|
22486
22980
|
},
|
|
22487
22981
|
{
|
|
22488
|
-
pattern: (p) => p.startsWith(
|
|
22982
|
+
pattern: (p) => p.startsWith(path33.join(HOME, ".exe-os")),
|
|
22489
22983
|
reason: "exe-os configuration files are protected"
|
|
22490
22984
|
},
|
|
22491
22985
|
{
|
|
@@ -22502,7 +22996,7 @@ var init_safety_checks = __esm({
|
|
|
22502
22996
|
},
|
|
22503
22997
|
{
|
|
22504
22998
|
pattern: (p) => {
|
|
22505
|
-
const name =
|
|
22999
|
+
const name = path33.basename(p);
|
|
22506
23000
|
return [".bashrc", ".zshrc", ".profile", ".bash_profile", ".zprofile", ".zshenv"].includes(name);
|
|
22507
23001
|
},
|
|
22508
23002
|
reason: "Shell configuration files can execute arbitrary code on login"
|
|
@@ -22529,7 +23023,7 @@ __export(file_read_exports, {
|
|
|
22529
23023
|
FileReadTool: () => FileReadTool
|
|
22530
23024
|
});
|
|
22531
23025
|
import fs3 from "fs/promises";
|
|
22532
|
-
import
|
|
23026
|
+
import path34 from "path";
|
|
22533
23027
|
import { z } from "zod";
|
|
22534
23028
|
function isBinary(buf) {
|
|
22535
23029
|
for (let i = 0; i < buf.length; i++) {
|
|
@@ -22565,7 +23059,7 @@ var init_file_read = __esm({
|
|
|
22565
23059
|
return { behavior: "allow" };
|
|
22566
23060
|
},
|
|
22567
23061
|
async call(input, context) {
|
|
22568
|
-
const filePath =
|
|
23062
|
+
const filePath = path34.isAbsolute(input.file_path) ? input.file_path : path34.resolve(context.cwd, input.file_path);
|
|
22569
23063
|
let stat2;
|
|
22570
23064
|
try {
|
|
22571
23065
|
stat2 = await fs3.stat(filePath);
|
|
@@ -22605,7 +23099,7 @@ __export(glob_exports, {
|
|
|
22605
23099
|
GlobTool: () => GlobTool
|
|
22606
23100
|
});
|
|
22607
23101
|
import fs4 from "fs/promises";
|
|
22608
|
-
import
|
|
23102
|
+
import path35 from "path";
|
|
22609
23103
|
import { z as z2 } from "zod";
|
|
22610
23104
|
async function walkDir(dir, maxDepth = 10) {
|
|
22611
23105
|
const results = [];
|
|
@@ -22621,7 +23115,7 @@ async function walkDir(dir, maxDepth = 10) {
|
|
|
22621
23115
|
if (entry.isDirectory() && (entry.name === "node_modules" || entry.name === ".git")) {
|
|
22622
23116
|
continue;
|
|
22623
23117
|
}
|
|
22624
|
-
const fullPath =
|
|
23118
|
+
const fullPath = path35.join(current, entry.name);
|
|
22625
23119
|
if (entry.isDirectory()) {
|
|
22626
23120
|
await walk(fullPath, depth + 1);
|
|
22627
23121
|
} else {
|
|
@@ -22655,11 +23149,11 @@ var init_glob = __esm({
|
|
|
22655
23149
|
inputSchema: inputSchema2,
|
|
22656
23150
|
isReadOnly: true,
|
|
22657
23151
|
async call(input, context) {
|
|
22658
|
-
const baseDir = input.path ?
|
|
23152
|
+
const baseDir = input.path ? path35.isAbsolute(input.path) ? input.path : path35.resolve(context.cwd, input.path) : context.cwd;
|
|
22659
23153
|
try {
|
|
22660
23154
|
const entries = await walkDir(baseDir);
|
|
22661
23155
|
const matched = entries.filter(
|
|
22662
|
-
(e) => simpleGlobMatch(
|
|
23156
|
+
(e) => simpleGlobMatch(path35.relative(baseDir, e.path), input.pattern)
|
|
22663
23157
|
);
|
|
22664
23158
|
matched.sort((a, b) => b.mtime - a.mtime);
|
|
22665
23159
|
if (matched.length === 0) {
|
|
@@ -22685,7 +23179,7 @@ __export(grep_exports, {
|
|
|
22685
23179
|
});
|
|
22686
23180
|
import { spawn as spawn2 } from "child_process";
|
|
22687
23181
|
import fs5 from "fs/promises";
|
|
22688
|
-
import
|
|
23182
|
+
import path36 from "path";
|
|
22689
23183
|
import { z as z3 } from "zod";
|
|
22690
23184
|
function runRipgrep(input, searchPath, context) {
|
|
22691
23185
|
return new Promise((resolve, reject) => {
|
|
@@ -22739,7 +23233,7 @@ async function nodeGrep(input, searchPath) {
|
|
|
22739
23233
|
}
|
|
22740
23234
|
for (const entry of entries) {
|
|
22741
23235
|
if (entry.name === "node_modules" || entry.name === ".git") continue;
|
|
22742
|
-
const fullPath =
|
|
23236
|
+
const fullPath = path36.join(dir, entry.name);
|
|
22743
23237
|
if (entry.isDirectory()) {
|
|
22744
23238
|
await walk(fullPath);
|
|
22745
23239
|
} else {
|
|
@@ -22785,7 +23279,7 @@ var init_grep = __esm({
|
|
|
22785
23279
|
inputSchema: inputSchema3,
|
|
22786
23280
|
isReadOnly: true,
|
|
22787
23281
|
async call(input, context) {
|
|
22788
|
-
const searchPath = input.path ?
|
|
23282
|
+
const searchPath = input.path ? path36.isAbsolute(input.path) ? input.path : path36.resolve(context.cwd, input.path) : context.cwd;
|
|
22789
23283
|
try {
|
|
22790
23284
|
const result = await runRipgrep(input, searchPath, context);
|
|
22791
23285
|
return result;
|
|
@@ -22810,7 +23304,7 @@ __export(file_write_exports, {
|
|
|
22810
23304
|
FileWriteTool: () => FileWriteTool
|
|
22811
23305
|
});
|
|
22812
23306
|
import fs6 from "fs/promises";
|
|
22813
|
-
import
|
|
23307
|
+
import path37 from "path";
|
|
22814
23308
|
import { z as z4 } from "zod";
|
|
22815
23309
|
var inputSchema4, FileWriteTool;
|
|
22816
23310
|
var init_file_write = __esm({
|
|
@@ -22838,8 +23332,8 @@ var init_file_write = __esm({
|
|
|
22838
23332
|
return { behavior: "allow" };
|
|
22839
23333
|
},
|
|
22840
23334
|
async call(input, context) {
|
|
22841
|
-
const filePath =
|
|
22842
|
-
const dir =
|
|
23335
|
+
const filePath = path37.isAbsolute(input.file_path) ? input.file_path : path37.resolve(context.cwd, input.file_path);
|
|
23336
|
+
const dir = path37.dirname(filePath);
|
|
22843
23337
|
await fs6.mkdir(dir, { recursive: true });
|
|
22844
23338
|
await fs6.writeFile(filePath, input.content, "utf-8");
|
|
22845
23339
|
return {
|
|
@@ -22857,7 +23351,7 @@ __export(file_edit_exports, {
|
|
|
22857
23351
|
FileEditTool: () => FileEditTool
|
|
22858
23352
|
});
|
|
22859
23353
|
import fs7 from "fs/promises";
|
|
22860
|
-
import
|
|
23354
|
+
import path38 from "path";
|
|
22861
23355
|
import { z as z5 } from "zod";
|
|
22862
23356
|
function countOccurrences(haystack, needle) {
|
|
22863
23357
|
let count = 0;
|
|
@@ -22898,7 +23392,7 @@ var init_file_edit = __esm({
|
|
|
22898
23392
|
return { behavior: "allow" };
|
|
22899
23393
|
},
|
|
22900
23394
|
async call(input, context) {
|
|
22901
|
-
const filePath =
|
|
23395
|
+
const filePath = path38.isAbsolute(input.file_path) ? input.file_path : path38.resolve(context.cwd, input.file_path);
|
|
22902
23396
|
let content;
|
|
22903
23397
|
try {
|
|
22904
23398
|
content = await fs7.readFile(filePath, "utf-8");
|
|
@@ -23140,7 +23634,7 @@ var init_bash = __esm({
|
|
|
23140
23634
|
// src/tui/views/CommandCenter.tsx
|
|
23141
23635
|
import { useState as useState6, useEffect as useEffect8, useMemo as useMemo4, useCallback as useCallback4, useRef as useRef4 } from "react";
|
|
23142
23636
|
import TextInput from "ink-text-input";
|
|
23143
|
-
import
|
|
23637
|
+
import path39 from "path";
|
|
23144
23638
|
import { homedir as homedir6 } from "os";
|
|
23145
23639
|
import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
23146
23640
|
function CommandCenterView({
|
|
@@ -23175,15 +23669,15 @@ function CommandCenterView({
|
|
|
23175
23669
|
const { createPermissionsFromPreset: createPermissionsFromPreset2, EMPLOYEE_PERMISSIONS: EMPLOYEE_PERMISSIONS2 } = await Promise.resolve().then(() => (init_permissions(), permissions_exports));
|
|
23176
23670
|
const { getPresetByRole: getPresetByRole2 } = await Promise.resolve().then(() => (init_permission_presets(), permission_presets_exports));
|
|
23177
23671
|
const { createDefaultHooks: createDefaultHooks2 } = await Promise.resolve().then(() => (init_hooks(), hooks_exports));
|
|
23178
|
-
const { readFileSync:
|
|
23672
|
+
const { readFileSync: readFileSync27, existsSync: existsSync30 } = await import("fs");
|
|
23179
23673
|
const { join } = await import("path");
|
|
23180
23674
|
const { homedir: homedir8 } = await import("os");
|
|
23181
23675
|
const configPath = join(homedir8(), ".exe-os", "config.json");
|
|
23182
23676
|
let failoverChain = ["anthropic", "opencode", "gemini", "openai"];
|
|
23183
23677
|
let providerConfigs = {};
|
|
23184
|
-
if (
|
|
23678
|
+
if (existsSync30(configPath)) {
|
|
23185
23679
|
try {
|
|
23186
|
-
const raw = JSON.parse(
|
|
23680
|
+
const raw = JSON.parse(readFileSync27(configPath, "utf8"));
|
|
23187
23681
|
if (Array.isArray(raw.failoverChain)) failoverChain = raw.failoverChain;
|
|
23188
23682
|
if (raw.providers && typeof raw.providers === "object") {
|
|
23189
23683
|
providerConfigs = raw.providers;
|
|
@@ -23244,7 +23738,7 @@ function CommandCenterView({
|
|
|
23244
23738
|
const markerDir = join(homedir8(), ".exe-os", "session-cache");
|
|
23245
23739
|
const agentFiles = (await import("fs")).readdirSync(markerDir).filter((f) => f.startsWith("active-agent-"));
|
|
23246
23740
|
for (const f of agentFiles) {
|
|
23247
|
-
const data = JSON.parse(
|
|
23741
|
+
const data = JSON.parse(readFileSync27(join(markerDir, f), "utf8"));
|
|
23248
23742
|
if (data.agentRole) {
|
|
23249
23743
|
agentRole = data.agentRole;
|
|
23250
23744
|
break;
|
|
@@ -23389,7 +23883,7 @@ function CommandCenterView({
|
|
|
23389
23883
|
const demoEntries = DEMO_PROJECTS.map((p) => ({
|
|
23390
23884
|
projectName: p.projectName,
|
|
23391
23885
|
exeSession: p.exeSession,
|
|
23392
|
-
projectDir:
|
|
23886
|
+
projectDir: path39.join(homedir6(), p.projectName),
|
|
23393
23887
|
employeeCount: p.employees.length,
|
|
23394
23888
|
activeCount: p.employees.filter((e) => e.status === "active").length,
|
|
23395
23889
|
memoryCount: p.employees.length * 4e3,
|
|
@@ -23427,7 +23921,7 @@ function CommandCenterView({
|
|
|
23427
23921
|
const { listSessions: listSessions2 } = await Promise.resolve().then(() => (init_session_registry(), session_registry_exports));
|
|
23428
23922
|
const { listTmuxSessions: listTmuxSessions2, inTmux: inTmux2 } = await Promise.resolve().then(() => (init_tmux_status(), tmux_status_exports));
|
|
23429
23923
|
const { loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
23430
|
-
const { existsSync:
|
|
23924
|
+
const { existsSync: existsSync30 } = await import("fs");
|
|
23431
23925
|
const { join } = await import("path");
|
|
23432
23926
|
const client = getClient2();
|
|
23433
23927
|
if (!client) {
|
|
@@ -23498,7 +23992,7 @@ function CommandCenterView({
|
|
|
23498
23992
|
}
|
|
23499
23993
|
const memoryCount = memoryCounts.get(name) ?? 0;
|
|
23500
23994
|
const openTaskCount = openTaskCounts.get(name) ?? 0;
|
|
23501
|
-
const hasGit = projectDir ?
|
|
23995
|
+
const hasGit = projectDir ? existsSync30(join(projectDir, ".git")) : false;
|
|
23502
23996
|
const type = hasGit ? "code" : memoryCount > 0 ? "code" : "automation";
|
|
23503
23997
|
projectList.push({
|
|
23504
23998
|
projectName: name,
|
|
@@ -23523,7 +24017,7 @@ function CommandCenterView({
|
|
|
23523
24017
|
setHealth((h) => ({ ...h, memories: Number(totalResult.rows[0]?.cnt ?? 0) }));
|
|
23524
24018
|
try {
|
|
23525
24019
|
const pidPath = join(process.env.HOME ?? "", ".exe-os", "exed.pid");
|
|
23526
|
-
setHealth((h) => ({ ...h, daemon:
|
|
24020
|
+
setHealth((h) => ({ ...h, daemon: existsSync30(pidPath) ? "running" : "stopped" }));
|
|
23527
24021
|
} catch {
|
|
23528
24022
|
}
|
|
23529
24023
|
const activityResult = await client.execute(
|
|
@@ -23870,7 +24364,7 @@ var init_TmuxPane = __esm({
|
|
|
23870
24364
|
});
|
|
23871
24365
|
|
|
23872
24366
|
// src/lib/task-router.ts
|
|
23873
|
-
import { randomUUID as
|
|
24367
|
+
import { randomUUID as randomUUID6 } from "crypto";
|
|
23874
24368
|
function resolveBloomRouting(complexity, config = DEFAULT_BLOOM_CONFIG) {
|
|
23875
24369
|
const tier = config.complexityToTier[complexity];
|
|
23876
24370
|
const rule = config.tierRules[tier];
|
|
@@ -24393,7 +24887,7 @@ var init_useOrchestrator = __esm({
|
|
|
24393
24887
|
|
|
24394
24888
|
// src/tui/views/Sessions.tsx
|
|
24395
24889
|
import React19, { useState as useState9, useEffect as useEffect11, useCallback as useCallback6 } from "react";
|
|
24396
|
-
import
|
|
24890
|
+
import path40 from "path";
|
|
24397
24891
|
import { homedir as homedir7 } from "os";
|
|
24398
24892
|
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
24399
24893
|
function isCoordinatorEntry(entry) {
|
|
@@ -24431,7 +24925,7 @@ function SessionsView({
|
|
|
24431
24925
|
if (demo) {
|
|
24432
24926
|
setProjects(DEMO_PROJECTS.map((p) => ({
|
|
24433
24927
|
...p,
|
|
24434
|
-
projectDir:
|
|
24928
|
+
projectDir: path40.join(homedir7(), p.projectName),
|
|
24435
24929
|
employees: p.employees.map((e) => ({ ...e, attached: e.status === "active" }))
|
|
24436
24930
|
})));
|
|
24437
24931
|
return;
|
|
@@ -25535,12 +26029,12 @@ async function loadGatewayConfig() {
|
|
|
25535
26029
|
state.running = false;
|
|
25536
26030
|
}
|
|
25537
26031
|
try {
|
|
25538
|
-
const { existsSync:
|
|
26032
|
+
const { existsSync: existsSync30, readFileSync: readFileSync27 } = await import("fs");
|
|
25539
26033
|
const { join } = await import("path");
|
|
25540
26034
|
const home = process.env.HOME ?? "";
|
|
25541
26035
|
const configPath = join(home, ".exe-os", "gateway.json");
|
|
25542
|
-
if (
|
|
25543
|
-
const raw = JSON.parse(
|
|
26036
|
+
if (existsSync30(configPath)) {
|
|
26037
|
+
const raw = JSON.parse(readFileSync27(configPath, "utf8"));
|
|
25544
26038
|
state.port = raw.port ?? 3100;
|
|
25545
26039
|
state.gatewayUrl = raw.gatewayUrl ?? "";
|
|
25546
26040
|
if (raw.adapters) {
|
|
@@ -26163,12 +26657,12 @@ function TeamView({ onBack, onViewSessions }) {
|
|
|
26163
26657
|
setMembers(teamData);
|
|
26164
26658
|
setDbError(null);
|
|
26165
26659
|
try {
|
|
26166
|
-
const { existsSync:
|
|
26660
|
+
const { existsSync: existsSync30, readFileSync: readFileSync27 } = await import("fs");
|
|
26167
26661
|
const { join } = await import("path");
|
|
26168
26662
|
const home = process.env.HOME ?? "";
|
|
26169
26663
|
const gatewayConfig = join(home, ".exe-os", "gateway.json");
|
|
26170
|
-
if (
|
|
26171
|
-
const raw = JSON.parse(
|
|
26664
|
+
if (existsSync30(gatewayConfig)) {
|
|
26665
|
+
const raw = JSON.parse(readFileSync27(gatewayConfig, "utf8"));
|
|
26172
26666
|
if (raw.agents && raw.agents.length > 0) {
|
|
26173
26667
|
setExternals(raw.agents.map((a) => ({
|
|
26174
26668
|
name: a.name,
|
|
@@ -26349,8 +26843,8 @@ __export(wiki_client_exports, {
|
|
|
26349
26843
|
listDocuments: () => listDocuments,
|
|
26350
26844
|
listWorkspaces: () => listWorkspaces
|
|
26351
26845
|
});
|
|
26352
|
-
async function wikiFetch(config,
|
|
26353
|
-
const url = `${config.baseUrl}/api/v1${
|
|
26846
|
+
async function wikiFetch(config, path44, method = "GET", body) {
|
|
26847
|
+
const url = `${config.baseUrl}/api/v1${path44}`;
|
|
26354
26848
|
const headers = {
|
|
26355
26849
|
Authorization: `Bearer ${config.apiKey}`,
|
|
26356
26850
|
"Content-Type": "application/json"
|
|
@@ -26383,7 +26877,7 @@ async function wikiFetch(config, path42, method = "GET", body) {
|
|
|
26383
26877
|
}
|
|
26384
26878
|
}
|
|
26385
26879
|
if (!response.ok) {
|
|
26386
|
-
throw new Error(`Wiki API ${method} ${
|
|
26880
|
+
throw new Error(`Wiki API ${method} ${path44}: ${response.status} ${response.statusText}`);
|
|
26387
26881
|
}
|
|
26388
26882
|
return response.json();
|
|
26389
26883
|
} finally {
|
|
@@ -26993,12 +27487,12 @@ function SettingsView({ onBack }) {
|
|
|
26993
27487
|
}
|
|
26994
27488
|
setProviders(providerList);
|
|
26995
27489
|
try {
|
|
26996
|
-
const { existsSync:
|
|
27490
|
+
const { existsSync: existsSync30 } = await import("fs");
|
|
26997
27491
|
const { join } = await import("path");
|
|
26998
27492
|
const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
26999
27493
|
const cfg = await loadConfig2();
|
|
27000
27494
|
const home = process.env.HOME ?? "";
|
|
27001
|
-
const hasKey =
|
|
27495
|
+
const hasKey = existsSync30(join(home, ".exe-os", "master.key"));
|
|
27002
27496
|
if (cfg.cloud) {
|
|
27003
27497
|
setCloud({
|
|
27004
27498
|
configured: true,
|
|
@@ -27011,22 +27505,22 @@ function SettingsView({ onBack }) {
|
|
|
27011
27505
|
const pidPath = join(home, ".exe-os", "exed.pid");
|
|
27012
27506
|
let daemon = "unknown";
|
|
27013
27507
|
try {
|
|
27014
|
-
daemon =
|
|
27508
|
+
daemon = existsSync30(pidPath) ? "running" : "stopped";
|
|
27015
27509
|
} catch {
|
|
27016
27510
|
}
|
|
27017
27511
|
let version = "unknown";
|
|
27018
27512
|
try {
|
|
27019
|
-
const { readFileSync:
|
|
27513
|
+
const { readFileSync: readFileSync27 } = await import("fs");
|
|
27020
27514
|
const { createRequire } = await import("module");
|
|
27021
27515
|
const require2 = createRequire(import.meta.url);
|
|
27022
27516
|
const pkgPath = require2.resolve("@askexenow/exe-os/package.json");
|
|
27023
|
-
const pkg = JSON.parse(
|
|
27517
|
+
const pkg = JSON.parse(readFileSync27(pkgPath, "utf8"));
|
|
27024
27518
|
version = pkg.version;
|
|
27025
27519
|
} catch {
|
|
27026
27520
|
try {
|
|
27027
|
-
const { readFileSync:
|
|
27521
|
+
const { readFileSync: readFileSync27 } = await import("fs");
|
|
27028
27522
|
const { join: joinPath } = await import("path");
|
|
27029
|
-
const pkg = JSON.parse(
|
|
27523
|
+
const pkg = JSON.parse(readFileSync27(joinPath(process.cwd(), "package.json"), "utf8"));
|
|
27030
27524
|
version = pkg.version;
|
|
27031
27525
|
} catch {
|
|
27032
27526
|
}
|
|
@@ -27827,15 +28321,15 @@ __export(installer_exports2, {
|
|
|
27827
28321
|
verifyOpenCodeHooks: () => verifyOpenCodeHooks
|
|
27828
28322
|
});
|
|
27829
28323
|
import { readFile as readFile6, writeFile as writeFile7, mkdir as mkdir7 } from "fs/promises";
|
|
27830
|
-
import { existsSync as
|
|
27831
|
-
import
|
|
27832
|
-
import
|
|
27833
|
-
async function registerOpenCodeMcp(packageRoot, homeDir =
|
|
27834
|
-
const configDir =
|
|
27835
|
-
const configPath =
|
|
28324
|
+
import { existsSync as existsSync27, readFileSync as readFileSync25 } from "fs";
|
|
28325
|
+
import path41 from "path";
|
|
28326
|
+
import os16 from "os";
|
|
28327
|
+
async function registerOpenCodeMcp(packageRoot, homeDir = os16.homedir()) {
|
|
28328
|
+
const configDir = path41.join(homeDir, ".config", "opencode");
|
|
28329
|
+
const configPath = path41.join(configDir, "opencode.json");
|
|
27836
28330
|
await mkdir7(configDir, { recursive: true });
|
|
27837
28331
|
let config = {};
|
|
27838
|
-
if (
|
|
28332
|
+
if (existsSync27(configPath)) {
|
|
27839
28333
|
try {
|
|
27840
28334
|
config = JSON.parse(await readFile6(configPath, "utf-8"));
|
|
27841
28335
|
} catch {
|
|
@@ -27847,7 +28341,7 @@ async function registerOpenCodeMcp(packageRoot, homeDir = os15.homedir()) {
|
|
|
27847
28341
|
}
|
|
27848
28342
|
const newEntry = {
|
|
27849
28343
|
type: "local",
|
|
27850
|
-
command: ["node",
|
|
28344
|
+
command: ["node", path41.join(packageRoot, "dist", "mcp", "server.js")],
|
|
27851
28345
|
enabled: true
|
|
27852
28346
|
};
|
|
27853
28347
|
const current = config.mcp["exe-os"];
|
|
@@ -27861,15 +28355,15 @@ async function registerOpenCodeMcp(packageRoot, homeDir = os15.homedir()) {
|
|
|
27861
28355
|
await writeFile7(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
27862
28356
|
return true;
|
|
27863
28357
|
}
|
|
27864
|
-
async function installOpenCodePlugin(packageRoot, homeDir =
|
|
27865
|
-
const pluginDir =
|
|
27866
|
-
const pluginPath =
|
|
28358
|
+
async function installOpenCodePlugin(packageRoot, homeDir = os16.homedir()) {
|
|
28359
|
+
const pluginDir = path41.join(homeDir, ".config", "opencode", "plugins");
|
|
28360
|
+
const pluginPath = path41.join(pluginDir, "exe-os.mjs");
|
|
27867
28361
|
await mkdir7(pluginDir, { recursive: true });
|
|
27868
28362
|
const pluginContent = PLUGIN_TEMPLATE.replace(
|
|
27869
28363
|
/__PACKAGE_ROOT__/g,
|
|
27870
28364
|
packageRoot.replace(/\\/g, "\\\\")
|
|
27871
28365
|
);
|
|
27872
|
-
if (
|
|
28366
|
+
if (existsSync27(pluginPath)) {
|
|
27873
28367
|
const existing = await readFile6(pluginPath, "utf-8");
|
|
27874
28368
|
if (existing === pluginContent) {
|
|
27875
28369
|
return false;
|
|
@@ -27878,17 +28372,17 @@ async function installOpenCodePlugin(packageRoot, homeDir = os15.homedir()) {
|
|
|
27878
28372
|
await writeFile7(pluginPath, pluginContent);
|
|
27879
28373
|
return true;
|
|
27880
28374
|
}
|
|
27881
|
-
function verifyOpenCodeHooks(homeDir =
|
|
27882
|
-
const configPath =
|
|
27883
|
-
const pluginPath =
|
|
27884
|
-
if (!
|
|
28375
|
+
function verifyOpenCodeHooks(homeDir = os16.homedir()) {
|
|
28376
|
+
const configPath = path41.join(homeDir, ".config", "opencode", "opencode.json");
|
|
28377
|
+
const pluginPath = path41.join(homeDir, ".config", "opencode", "plugins", "exe-os.mjs");
|
|
28378
|
+
if (!existsSync27(configPath)) return false;
|
|
27885
28379
|
try {
|
|
27886
|
-
const config = JSON.parse(
|
|
28380
|
+
const config = JSON.parse(readFileSync25(configPath, "utf-8"));
|
|
27887
28381
|
if (!config.mcp?.["exe-os"]?.enabled) return false;
|
|
27888
28382
|
} catch {
|
|
27889
28383
|
return false;
|
|
27890
28384
|
}
|
|
27891
|
-
if (!
|
|
28385
|
+
if (!existsSync27(pluginPath)) return false;
|
|
27892
28386
|
return true;
|
|
27893
28387
|
}
|
|
27894
28388
|
async function runOpenCodeInstaller(homeDir) {
|
|
@@ -27921,19 +28415,19 @@ __export(installer_exports3, {
|
|
|
27921
28415
|
verifyCodexHooks: () => verifyCodexHooks
|
|
27922
28416
|
});
|
|
27923
28417
|
import { readFile as readFile7, writeFile as writeFile8, mkdir as mkdir8 } from "fs/promises";
|
|
27924
|
-
import { existsSync as
|
|
27925
|
-
import
|
|
27926
|
-
import
|
|
27927
|
-
async function mergeCodexHooks(packageRoot, homeDir =
|
|
27928
|
-
const codexDir =
|
|
27929
|
-
const hooksPath =
|
|
27930
|
-
const logsDir =
|
|
27931
|
-
const hookLogPath =
|
|
28418
|
+
import { existsSync as existsSync28 } from "fs";
|
|
28419
|
+
import path42 from "path";
|
|
28420
|
+
import os17 from "os";
|
|
28421
|
+
async function mergeCodexHooks(packageRoot, homeDir = os17.homedir()) {
|
|
28422
|
+
const codexDir = path42.join(homeDir, ".codex");
|
|
28423
|
+
const hooksPath = path42.join(codexDir, "hooks.json");
|
|
28424
|
+
const logsDir = path42.join(homeDir, ".exe-os", "logs");
|
|
28425
|
+
const hookLogPath = path42.join(logsDir, "hooks.log");
|
|
27932
28426
|
const logSuffix = ` 2>> "${hookLogPath}"`;
|
|
27933
28427
|
await mkdir8(codexDir, { recursive: true });
|
|
27934
28428
|
await mkdir8(logsDir, { recursive: true });
|
|
27935
28429
|
let hooksJson = {};
|
|
27936
|
-
if (
|
|
28430
|
+
if (existsSync28(hooksPath)) {
|
|
27937
28431
|
try {
|
|
27938
28432
|
hooksJson = JSON.parse(await readFile7(hooksPath, "utf-8"));
|
|
27939
28433
|
} catch {
|
|
@@ -27950,7 +28444,7 @@ async function mergeCodexHooks(packageRoot, homeDir = os16.homedir()) {
|
|
|
27950
28444
|
hooks: [
|
|
27951
28445
|
{
|
|
27952
28446
|
type: "command",
|
|
27953
|
-
command: `node "${
|
|
28447
|
+
command: `node "${path42.join(packageRoot, "dist", "hooks", "session-start.js")}"${logSuffix}`,
|
|
27954
28448
|
timeout: 30,
|
|
27955
28449
|
statusMessage: "exe-os: loading memory brief"
|
|
27956
28450
|
}
|
|
@@ -27965,11 +28459,11 @@ async function mergeCodexHooks(packageRoot, homeDir = os16.homedir()) {
|
|
|
27965
28459
|
hooks: [
|
|
27966
28460
|
{
|
|
27967
28461
|
type: "command",
|
|
27968
|
-
command: `node "${
|
|
28462
|
+
command: `node "${path42.join(packageRoot, "dist", "hooks", "ingest.js")}"${logSuffix}`
|
|
27969
28463
|
},
|
|
27970
28464
|
{
|
|
27971
28465
|
type: "command",
|
|
27972
|
-
command: `node "${
|
|
28466
|
+
command: `node "${path42.join(packageRoot, "dist", "hooks", "error-recall.js")}"${logSuffix}`
|
|
27973
28467
|
}
|
|
27974
28468
|
]
|
|
27975
28469
|
},
|
|
@@ -27981,11 +28475,11 @@ async function mergeCodexHooks(packageRoot, homeDir = os16.homedir()) {
|
|
|
27981
28475
|
hooks: [
|
|
27982
28476
|
{
|
|
27983
28477
|
type: "command",
|
|
27984
|
-
command: `node "${
|
|
28478
|
+
command: `node "${path42.join(packageRoot, "dist", "hooks", "prompt-submit.js")}"${logSuffix}`
|
|
27985
28479
|
},
|
|
27986
28480
|
{
|
|
27987
28481
|
type: "command",
|
|
27988
|
-
command: `node "${
|
|
28482
|
+
command: `node "${path42.join(packageRoot, "dist", "hooks", "exe-heartbeat-hook.js")}"${logSuffix}`,
|
|
27989
28483
|
timeout: 5
|
|
27990
28484
|
}
|
|
27991
28485
|
]
|
|
@@ -27998,7 +28492,7 @@ async function mergeCodexHooks(packageRoot, homeDir = os16.homedir()) {
|
|
|
27998
28492
|
hooks: [
|
|
27999
28493
|
{
|
|
28000
28494
|
type: "command",
|
|
28001
|
-
command: `node "${
|
|
28495
|
+
command: `node "${path42.join(packageRoot, "dist", "hooks", "stop.js")}"${logSuffix}`
|
|
28002
28496
|
}
|
|
28003
28497
|
]
|
|
28004
28498
|
},
|
|
@@ -28011,7 +28505,7 @@ async function mergeCodexHooks(packageRoot, homeDir = os16.homedir()) {
|
|
|
28011
28505
|
hooks: [
|
|
28012
28506
|
{
|
|
28013
28507
|
type: "command",
|
|
28014
|
-
command: `node "${
|
|
28508
|
+
command: `node "${path42.join(packageRoot, "dist", "hooks", "pre-tool-use.js")}"${logSuffix}`
|
|
28015
28509
|
}
|
|
28016
28510
|
]
|
|
28017
28511
|
},
|
|
@@ -28042,9 +28536,9 @@ async function mergeCodexHooks(packageRoot, homeDir = os16.homedir()) {
|
|
|
28042
28536
|
await writeFile8(hooksPath, JSON.stringify(hooksJson, null, 2) + "\n");
|
|
28043
28537
|
return { added, skipped };
|
|
28044
28538
|
}
|
|
28045
|
-
function verifyCodexHooks(homeDir =
|
|
28046
|
-
const hooksPath =
|
|
28047
|
-
if (!
|
|
28539
|
+
function verifyCodexHooks(homeDir = os17.homedir()) {
|
|
28540
|
+
const hooksPath = path42.join(homeDir, ".codex", "hooks.json");
|
|
28541
|
+
if (!existsSync28(hooksPath)) return false;
|
|
28048
28542
|
try {
|
|
28049
28543
|
const hooksJson = JSON.parse(
|
|
28050
28544
|
__require("fs").readFileSync(hooksPath, "utf-8")
|
|
@@ -28064,14 +28558,14 @@ function verifyCodexHooks(homeDir = os16.homedir()) {
|
|
|
28064
28558
|
return false;
|
|
28065
28559
|
}
|
|
28066
28560
|
}
|
|
28067
|
-
async function installCodexStatusLine(homeDir =
|
|
28561
|
+
async function installCodexStatusLine(homeDir = os17.homedir()) {
|
|
28068
28562
|
const prefs = loadPreferences(homeDir);
|
|
28069
28563
|
if (prefs.codexStatusLine === false) return "opted-out";
|
|
28070
|
-
const codexDir =
|
|
28071
|
-
const configPath =
|
|
28564
|
+
const codexDir = path42.join(homeDir, ".codex");
|
|
28565
|
+
const configPath = path42.join(codexDir, "config.toml");
|
|
28072
28566
|
await mkdir8(codexDir, { recursive: true });
|
|
28073
28567
|
let content = "";
|
|
28074
|
-
if (
|
|
28568
|
+
if (existsSync28(configPath)) {
|
|
28075
28569
|
content = await readFile7(configPath, "utf-8");
|
|
28076
28570
|
if (/\[tui\][\s\S]*?status_line\s*=/.test(content)) {
|
|
28077
28571
|
return "already-configured";
|
|
@@ -28119,14 +28613,14 @@ var init_installer3 = __esm({
|
|
|
28119
28613
|
});
|
|
28120
28614
|
|
|
28121
28615
|
// src/bin/cli.ts
|
|
28122
|
-
import { existsSync as
|
|
28123
|
-
import
|
|
28124
|
-
import
|
|
28616
|
+
import { existsSync as existsSync29, readFileSync as readFileSync26, writeFileSync as writeFileSync19, readdirSync as readdirSync8, rmSync } from "fs";
|
|
28617
|
+
import path43 from "path";
|
|
28618
|
+
import os18 from "os";
|
|
28125
28619
|
var args = process.argv.slice(2);
|
|
28126
28620
|
if (args.includes("--version") || args.includes("-v")) {
|
|
28127
28621
|
try {
|
|
28128
|
-
const pkgPath =
|
|
28129
|
-
const pkg = JSON.parse(
|
|
28622
|
+
const pkgPath = path43.join(path43.dirname(new URL(import.meta.url).pathname), "..", "..", "package.json");
|
|
28623
|
+
const pkg = JSON.parse(readFileSync26(pkgPath, "utf8"));
|
|
28130
28624
|
console.log(pkg.version);
|
|
28131
28625
|
} catch {
|
|
28132
28626
|
console.log("unknown");
|
|
@@ -28237,6 +28731,12 @@ if (args.includes("--global")) {
|
|
|
28237
28731
|
console.error("Backfill failed:", err instanceof Error ? err.message : String(err));
|
|
28238
28732
|
process.exit(1);
|
|
28239
28733
|
}
|
|
28734
|
+
} else if (args[0] === "export") {
|
|
28735
|
+
const { runExeExport: runExeExport2 } = await Promise.resolve().then(() => (init_exe_export(), exe_export_exports));
|
|
28736
|
+
await runExeExport2(args.slice(1));
|
|
28737
|
+
} else if (args[0] === "import") {
|
|
28738
|
+
const { runExeImport: runExeImport2 } = await Promise.resolve().then(() => (init_exe_import(), exe_import_exports));
|
|
28739
|
+
await runExeImport2(args.slice(1));
|
|
28240
28740
|
} else if (args[0] === "send-message" || args[0] === "send_message") {
|
|
28241
28741
|
const target = args[1];
|
|
28242
28742
|
const msgParts = [];
|
|
@@ -28284,11 +28784,11 @@ ID: ${result.id}`);
|
|
|
28284
28784
|
});
|
|
28285
28785
|
await init_App2().then(() => App_exports);
|
|
28286
28786
|
} else {
|
|
28287
|
-
const claudeDir =
|
|
28288
|
-
const settingsPath =
|
|
28289
|
-
const hasClaudeCode =
|
|
28787
|
+
const claudeDir = path43.join(os18.homedir(), ".claude");
|
|
28788
|
+
const settingsPath = path43.join(claudeDir, "settings.json");
|
|
28789
|
+
const hasClaudeCode = existsSync29(settingsPath) && (() => {
|
|
28290
28790
|
try {
|
|
28291
|
-
const raw =
|
|
28791
|
+
const raw = readFileSync26(settingsPath, "utf8");
|
|
28292
28792
|
return raw.includes("exe-os") || raw.includes("exe-mem");
|
|
28293
28793
|
} catch {
|
|
28294
28794
|
return false;
|
|
@@ -28298,9 +28798,9 @@ ID: ${result.id}`);
|
|
|
28298
28798
|
const { DEFAULT_COORDINATOR_TEMPLATE_NAME: DEFAULT_COORDINATOR_TEMPLATE_NAME2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
28299
28799
|
let cooName = DEFAULT_COORDINATOR_TEMPLATE_NAME2;
|
|
28300
28800
|
try {
|
|
28301
|
-
const rosterPath =
|
|
28302
|
-
if (
|
|
28303
|
-
const roster = JSON.parse(
|
|
28801
|
+
const rosterPath = path43.join(os18.homedir(), ".exe-os", "exe-employees.json");
|
|
28802
|
+
if (existsSync29(rosterPath)) {
|
|
28803
|
+
const roster = JSON.parse(readFileSync26(rosterPath, "utf8"));
|
|
28304
28804
|
const coo = roster.find((e) => e.role === "COO");
|
|
28305
28805
|
if (coo) cooName = coo.name;
|
|
28306
28806
|
}
|
|
@@ -28364,14 +28864,14 @@ async function runCodexInstall() {
|
|
|
28364
28864
|
}
|
|
28365
28865
|
}
|
|
28366
28866
|
async function runClaudeCheck() {
|
|
28367
|
-
const claudeDir =
|
|
28368
|
-
const settingsPath =
|
|
28369
|
-
const claudeJsonPath =
|
|
28867
|
+
const claudeDir = path43.join(os18.homedir(), ".claude");
|
|
28868
|
+
const settingsPath = path43.join(claudeDir, "settings.json");
|
|
28869
|
+
const claudeJsonPath = path43.join(os18.homedir(), ".claude.json");
|
|
28370
28870
|
let ok = true;
|
|
28371
|
-
if (
|
|
28871
|
+
if (existsSync29(settingsPath)) {
|
|
28372
28872
|
let settings;
|
|
28373
28873
|
try {
|
|
28374
|
-
settings = JSON.parse(
|
|
28874
|
+
settings = JSON.parse(readFileSync26(settingsPath, "utf8"));
|
|
28375
28875
|
} catch {
|
|
28376
28876
|
console.log("\x1B[31m\u2717\x1B[0m settings.json is malformed (invalid JSON)");
|
|
28377
28877
|
ok = false;
|
|
@@ -28397,10 +28897,10 @@ async function runClaudeCheck() {
|
|
|
28397
28897
|
console.log("\x1B[31m\u2717\x1B[0m settings.json not found");
|
|
28398
28898
|
ok = false;
|
|
28399
28899
|
}
|
|
28400
|
-
if (
|
|
28900
|
+
if (existsSync29(claudeJsonPath)) {
|
|
28401
28901
|
let claudeJson;
|
|
28402
28902
|
try {
|
|
28403
|
-
claudeJson = JSON.parse(
|
|
28903
|
+
claudeJson = JSON.parse(readFileSync26(claudeJsonPath, "utf8"));
|
|
28404
28904
|
} catch {
|
|
28405
28905
|
console.log("\x1B[31m\u2717\x1B[0m claude.json is malformed (invalid JSON)");
|
|
28406
28906
|
ok = false;
|
|
@@ -28419,8 +28919,8 @@ async function runClaudeCheck() {
|
|
|
28419
28919
|
console.log("\x1B[31m\u2717\x1B[0m claude.json not found");
|
|
28420
28920
|
ok = false;
|
|
28421
28921
|
}
|
|
28422
|
-
const skillsDir =
|
|
28423
|
-
if (
|
|
28922
|
+
const skillsDir = path43.join(claudeDir, "skills");
|
|
28923
|
+
if (existsSync29(skillsDir)) {
|
|
28424
28924
|
console.log("\x1B[32m\u2713\x1B[0m Slash skills directory exists");
|
|
28425
28925
|
} else {
|
|
28426
28926
|
console.log("\x1B[31m\u2717\x1B[0m Slash skills directory missing");
|
|
@@ -28436,17 +28936,17 @@ async function runClaudeCheck() {
|
|
|
28436
28936
|
async function runClaudeUninstall(flags = []) {
|
|
28437
28937
|
const dryRun = flags.includes("--dry-run");
|
|
28438
28938
|
const purge = flags.includes("--purge");
|
|
28439
|
-
const homeDir =
|
|
28440
|
-
const claudeDir =
|
|
28441
|
-
const settingsPath =
|
|
28442
|
-
const claudeJsonPath =
|
|
28443
|
-
const exeOsDir =
|
|
28939
|
+
const homeDir = os18.homedir();
|
|
28940
|
+
const claudeDir = path43.join(homeDir, ".claude");
|
|
28941
|
+
const settingsPath = path43.join(claudeDir, "settings.json");
|
|
28942
|
+
const claudeJsonPath = path43.join(homeDir, ".claude.json");
|
|
28943
|
+
const exeOsDir = path43.join(homeDir, ".exe-os");
|
|
28444
28944
|
let removed = 0;
|
|
28445
28945
|
const log = (msg) => console.log(dryRun ? `[dry-run] ${msg}` : msg);
|
|
28446
28946
|
let settings = {};
|
|
28447
|
-
if (
|
|
28947
|
+
if (existsSync29(settingsPath)) {
|
|
28448
28948
|
try {
|
|
28449
|
-
settings = JSON.parse(
|
|
28949
|
+
settings = JSON.parse(readFileSync26(settingsPath, "utf8"));
|
|
28450
28950
|
} catch {
|
|
28451
28951
|
console.error("Your ~/.claude/settings.json appears malformed.");
|
|
28452
28952
|
if (purge) {
|
|
@@ -28484,15 +28984,15 @@ async function runClaudeUninstall(flags = []) {
|
|
|
28484
28984
|
permCount = before - settings.permissions.allow.length;
|
|
28485
28985
|
}
|
|
28486
28986
|
if (!dryRun) {
|
|
28487
|
-
|
|
28987
|
+
writeFileSync19(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
28488
28988
|
}
|
|
28489
28989
|
log("\u2713 Removed exe-os hooks from settings.json");
|
|
28490
28990
|
if (permCount > 0) log(`\u2713 Removed ${permCount} MCP permission entries`);
|
|
28491
28991
|
removed++;
|
|
28492
28992
|
}
|
|
28493
28993
|
}
|
|
28494
|
-
if (
|
|
28495
|
-
const raw =
|
|
28994
|
+
if (existsSync29(claudeJsonPath)) {
|
|
28995
|
+
const raw = readFileSync26(claudeJsonPath, "utf8");
|
|
28496
28996
|
if (raw.length > 1e6) {
|
|
28497
28997
|
console.error("claude.json exceeds 1 MB \u2014 skipping parse.");
|
|
28498
28998
|
} else {
|
|
@@ -28513,7 +29013,7 @@ async function runClaudeUninstall(flags = []) {
|
|
|
28513
29013
|
}
|
|
28514
29014
|
if (removedMcp) {
|
|
28515
29015
|
if (!dryRun) {
|
|
28516
|
-
|
|
29016
|
+
writeFileSync19(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
|
|
28517
29017
|
}
|
|
28518
29018
|
log("\u2713 Removed exe-os MCP server from claude.json");
|
|
28519
29019
|
removed++;
|
|
@@ -28521,14 +29021,14 @@ async function runClaudeUninstall(flags = []) {
|
|
|
28521
29021
|
}
|
|
28522
29022
|
}
|
|
28523
29023
|
}
|
|
28524
|
-
const skillsDir =
|
|
28525
|
-
if (
|
|
29024
|
+
const skillsDir = path43.join(claudeDir, "skills");
|
|
29025
|
+
if (existsSync29(skillsDir)) {
|
|
28526
29026
|
let skillCount = 0;
|
|
28527
29027
|
try {
|
|
28528
29028
|
const entries = readdirSync8(skillsDir);
|
|
28529
29029
|
for (const entry of entries) {
|
|
28530
29030
|
if (entry.startsWith("exe")) {
|
|
28531
|
-
const fullPath =
|
|
29031
|
+
const fullPath = path43.join(skillsDir, entry);
|
|
28532
29032
|
if (!dryRun) rmSync(fullPath, { recursive: true, force: true });
|
|
28533
29033
|
skillCount++;
|
|
28534
29034
|
}
|
|
@@ -28540,30 +29040,30 @@ async function runClaudeUninstall(flags = []) {
|
|
|
28540
29040
|
removed++;
|
|
28541
29041
|
}
|
|
28542
29042
|
}
|
|
28543
|
-
const claudeMdPath =
|
|
28544
|
-
if (
|
|
28545
|
-
const content =
|
|
29043
|
+
const claudeMdPath = path43.join(claudeDir, "CLAUDE.md");
|
|
29044
|
+
if (existsSync29(claudeMdPath)) {
|
|
29045
|
+
const content = readFileSync26(claudeMdPath, "utf8");
|
|
28546
29046
|
const startMarker = "<!-- exe-os:orchestration-start -->";
|
|
28547
29047
|
const endMarker = "<!-- exe-os:orchestration-end -->";
|
|
28548
29048
|
const startIdx = content.indexOf(startMarker);
|
|
28549
29049
|
const endIdx = content.indexOf(endMarker);
|
|
28550
29050
|
if (startIdx !== -1 && endIdx !== -1) {
|
|
28551
29051
|
const cleaned = (content.slice(0, startIdx) + content.slice(endIdx + endMarker.length)).replace(/\n{3,}/g, "\n\n").trim() + "\n";
|
|
28552
|
-
if (!dryRun)
|
|
29052
|
+
if (!dryRun) writeFileSync19(claudeMdPath, cleaned);
|
|
28553
29053
|
log("\u2713 Removed orchestration block from CLAUDE.md");
|
|
28554
29054
|
removed++;
|
|
28555
29055
|
}
|
|
28556
29056
|
}
|
|
28557
|
-
const agentsDir =
|
|
28558
|
-
if (
|
|
29057
|
+
const agentsDir = path43.join(claudeDir, "agents");
|
|
29058
|
+
if (existsSync29(agentsDir)) {
|
|
28559
29059
|
let agentCount = 0;
|
|
28560
29060
|
try {
|
|
28561
29061
|
const entries = readdirSync8(agentsDir).filter((f) => f.endsWith(".md"));
|
|
28562
29062
|
let knownNames = /* @__PURE__ */ new Set();
|
|
28563
|
-
const rosterPath =
|
|
28564
|
-
if (
|
|
29063
|
+
const rosterPath = path43.join(exeOsDir, "exe-employees.json");
|
|
29064
|
+
if (existsSync29(rosterPath)) {
|
|
28565
29065
|
try {
|
|
28566
|
-
const roster = JSON.parse(
|
|
29066
|
+
const roster = JSON.parse(readFileSync26(rosterPath, "utf8"));
|
|
28567
29067
|
knownNames = new Set(roster.map((e) => e.name));
|
|
28568
29068
|
} catch {
|
|
28569
29069
|
}
|
|
@@ -28571,7 +29071,7 @@ async function runClaudeUninstall(flags = []) {
|
|
|
28571
29071
|
for (const entry of entries) {
|
|
28572
29072
|
const name = entry.replace(/\.md$/, "");
|
|
28573
29073
|
if (knownNames.has(name)) {
|
|
28574
|
-
if (!dryRun) rmSync(
|
|
29074
|
+
if (!dryRun) rmSync(path43.join(agentsDir, entry), { force: true });
|
|
28575
29075
|
agentCount++;
|
|
28576
29076
|
}
|
|
28577
29077
|
}
|
|
@@ -28582,16 +29082,16 @@ async function runClaudeUninstall(flags = []) {
|
|
|
28582
29082
|
removed++;
|
|
28583
29083
|
}
|
|
28584
29084
|
}
|
|
28585
|
-
const projectsDir =
|
|
28586
|
-
if (
|
|
29085
|
+
const projectsDir = path43.join(claudeDir, "projects");
|
|
29086
|
+
if (existsSync29(projectsDir)) {
|
|
28587
29087
|
let projectCount = 0;
|
|
28588
29088
|
try {
|
|
28589
29089
|
const projects = readdirSync8(projectsDir);
|
|
28590
29090
|
for (const proj of projects) {
|
|
28591
|
-
const projSettings =
|
|
28592
|
-
if (!
|
|
29091
|
+
const projSettings = path43.join(projectsDir, proj, "settings.json");
|
|
29092
|
+
if (!existsSync29(projSettings)) continue;
|
|
28593
29093
|
try {
|
|
28594
|
-
const pSettings = JSON.parse(
|
|
29094
|
+
const pSettings = JSON.parse(readFileSync26(projSettings, "utf8"));
|
|
28595
29095
|
let changed = false;
|
|
28596
29096
|
if (Array.isArray(pSettings.permissions?.allow)) {
|
|
28597
29097
|
const before = pSettings.permissions.allow.length;
|
|
@@ -28601,7 +29101,7 @@ async function runClaudeUninstall(flags = []) {
|
|
|
28601
29101
|
if (pSettings.permissions.allow.length < before) changed = true;
|
|
28602
29102
|
}
|
|
28603
29103
|
if (changed && !dryRun) {
|
|
28604
|
-
|
|
29104
|
+
writeFileSync19(projSettings, JSON.stringify(pSettings, null, 2) + "\n");
|
|
28605
29105
|
}
|
|
28606
29106
|
if (changed) projectCount++;
|
|
28607
29107
|
} catch {
|
|
@@ -28625,18 +29125,18 @@ async function runClaudeUninstall(flags = []) {
|
|
|
28625
29125
|
};
|
|
28626
29126
|
const exeBinPath = findExeBin3();
|
|
28627
29127
|
if (!exeBinPath) throw new Error("exe-os not found in PATH");
|
|
28628
|
-
const binDir =
|
|
29128
|
+
const binDir = path43.dirname(exeBinPath);
|
|
28629
29129
|
let symlinkCount = 0;
|
|
28630
|
-
const rosterPath =
|
|
28631
|
-
if (
|
|
28632
|
-
const roster = JSON.parse(
|
|
29130
|
+
const rosterPath = path43.join(exeOsDir, "exe-employees.json");
|
|
29131
|
+
if (existsSync29(rosterPath)) {
|
|
29132
|
+
const roster = JSON.parse(readFileSync26(rosterPath, "utf8"));
|
|
28633
29133
|
const { DEFAULT_COORDINATOR_TEMPLATE_NAME: DEFAULT_COORDINATOR_TEMPLATE_NAME2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
28634
29134
|
const coordinatorName = roster.find((e) => e.role?.toLowerCase() === "coo")?.name ?? DEFAULT_COORDINATOR_TEMPLATE_NAME2;
|
|
28635
29135
|
for (const emp of roster) {
|
|
28636
29136
|
if (emp.name === coordinatorName) continue;
|
|
28637
29137
|
for (const suffix of ["", "-opencode"]) {
|
|
28638
|
-
const linkPath =
|
|
28639
|
-
if (
|
|
29138
|
+
const linkPath = path43.join(binDir, `${emp.name}${suffix}`);
|
|
29139
|
+
if (existsSync29(linkPath)) {
|
|
28640
29140
|
if (!dryRun) rmSync(linkPath, { force: true });
|
|
28641
29141
|
symlinkCount++;
|
|
28642
29142
|
}
|
|
@@ -28649,7 +29149,7 @@ async function runClaudeUninstall(flags = []) {
|
|
|
28649
29149
|
}
|
|
28650
29150
|
} catch {
|
|
28651
29151
|
}
|
|
28652
|
-
if (purge &&
|
|
29152
|
+
if (purge && existsSync29(exeOsDir)) {
|
|
28653
29153
|
if (!dryRun) {
|
|
28654
29154
|
process.stdout.write("\x1B[33m\u26A0 This will delete all memories, identities, and agent data.\x1B[0m\n");
|
|
28655
29155
|
process.stdout.write(" Removing ~/.exe-os...\n");
|
|
@@ -28674,7 +29174,7 @@ async function checkForUpdateOnBoot() {
|
|
|
28674
29174
|
const config = await loadConfig2();
|
|
28675
29175
|
if (!config.autoUpdate.checkOnBoot) return;
|
|
28676
29176
|
const { checkForUpdate: checkForUpdate2 } = await Promise.resolve().then(() => (init_update(), update_exports));
|
|
28677
|
-
const packageRoot =
|
|
29177
|
+
const packageRoot = path43.resolve(
|
|
28678
29178
|
new URL("../..", import.meta.url).pathname
|
|
28679
29179
|
);
|
|
28680
29180
|
const result = checkForUpdate2(packageRoot);
|
|
@@ -28734,7 +29234,7 @@ async function runActivate(key) {
|
|
|
28734
29234
|
const idTemplate = getIdentityTemplate(identityKey);
|
|
28735
29235
|
if (idTemplate) {
|
|
28736
29236
|
const idPath = identityPath2(name);
|
|
28737
|
-
const dir =
|
|
29237
|
+
const dir = path43.dirname(idPath);
|
|
28738
29238
|
if (!fs8.existsSync(dir)) fs8.mkdirSync(dir, { recursive: true });
|
|
28739
29239
|
fs8.writeFileSync(idPath, idTemplate.replace(/^agent_id: \w+/m, `agent_id: ${name}`), "utf-8");
|
|
28740
29240
|
}
|