@askexenow/exe-os 0.9.3 → 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 +1020 -539
- 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/setup.js +4 -4
- package/dist/lib/employee-templates.js +4 -4
- package/dist/tui/App.js +4 -4
- package/package.json +1 -1
package/dist/bin/cli.js
CHANGED
|
@@ -7069,9 +7069,9 @@ Unclassified: ${unclassified}
|
|
|
7069
7069
|
}
|
|
7070
7070
|
async function exportBatches(options) {
|
|
7071
7071
|
const fs8 = await import("fs");
|
|
7072
|
-
const
|
|
7072
|
+
const path44 = await import("path");
|
|
7073
7073
|
const client = getClient();
|
|
7074
|
-
const outDir =
|
|
7074
|
+
const outDir = path44.join(process.cwd(), "exe/output/classifications/input");
|
|
7075
7075
|
fs8.mkdirSync(outDir, { recursive: true });
|
|
7076
7076
|
const countResult = await client.execute({
|
|
7077
7077
|
sql: "SELECT COUNT(*) as cnt FROM memories WHERE intent IS NULL AND outcome IS NULL AND domain IS NULL",
|
|
@@ -7095,7 +7095,7 @@ async function exportBatches(options) {
|
|
|
7095
7095
|
const text = String(row.text || "").replace(/\n/g, " ");
|
|
7096
7096
|
return JSON.stringify({ id: row.id, text });
|
|
7097
7097
|
});
|
|
7098
|
-
const batchFile =
|
|
7098
|
+
const batchFile = path44.join(outDir, `batch-${String(batchNum).padStart(4, "0")}.jsonl`);
|
|
7099
7099
|
fs8.writeFileSync(batchFile, lines.join("\n") + "\n");
|
|
7100
7100
|
exported += batch.rows.length;
|
|
7101
7101
|
offset += options.batchSize;
|
|
@@ -7111,7 +7111,7 @@ async function exportBatches(options) {
|
|
|
7111
7111
|
}
|
|
7112
7112
|
async function importClassifications(importDir) {
|
|
7113
7113
|
const fs8 = await import("fs");
|
|
7114
|
-
const
|
|
7114
|
+
const path44 = await import("path");
|
|
7115
7115
|
const client = getClient();
|
|
7116
7116
|
const files = fs8.readdirSync(importDir).filter((f) => f.endsWith(".jsonl")).sort();
|
|
7117
7117
|
process.stderr.write(`[backfill-metadata] Found ${files.length} JSONL files to import from ${importDir}
|
|
@@ -7119,7 +7119,7 @@ async function importClassifications(importDir) {
|
|
|
7119
7119
|
let imported = 0;
|
|
7120
7120
|
let invalid = 0;
|
|
7121
7121
|
for (const file of files) {
|
|
7122
|
-
const lines = fs8.readFileSync(
|
|
7122
|
+
const lines = fs8.readFileSync(path44.join(importDir, file), "utf-8").split("\n").filter(Boolean);
|
|
7123
7123
|
for (const line of lines) {
|
|
7124
7124
|
try {
|
|
7125
7125
|
const rec = JSON.parse(line);
|
|
@@ -7251,6 +7251,616 @@ var init_backfill_metadata = __esm({
|
|
|
7251
7251
|
}
|
|
7252
7252
|
});
|
|
7253
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");
|
|
7820
|
+
}
|
|
7821
|
+
return {
|
|
7822
|
+
packagePath: argv[flagIndex + 1],
|
|
7823
|
+
strategy: argv.includes(MERGE_FLAG) ? "merge" : "replace"
|
|
7824
|
+
};
|
|
7825
|
+
}
|
|
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"() {
|
|
7848
|
+
"use strict";
|
|
7849
|
+
init_orchestration_package();
|
|
7850
|
+
init_is_main();
|
|
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
|
+
`);
|
|
7858
|
+
process.exit(1);
|
|
7859
|
+
});
|
|
7860
|
+
}
|
|
7861
|
+
}
|
|
7862
|
+
});
|
|
7863
|
+
|
|
7254
7864
|
// src/lib/session-registry.ts
|
|
7255
7865
|
var session_registry_exports = {};
|
|
7256
7866
|
__export(session_registry_exports, {
|
|
@@ -7258,14 +7868,14 @@ __export(session_registry_exports, {
|
|
|
7258
7868
|
pruneStaleSessions: () => pruneStaleSessions,
|
|
7259
7869
|
registerSession: () => registerSession
|
|
7260
7870
|
});
|
|
7261
|
-
import { readFileSync as
|
|
7871
|
+
import { readFileSync as readFileSync12, writeFileSync as writeFileSync10, mkdirSync as mkdirSync11, existsSync as existsSync14 } from "fs";
|
|
7262
7872
|
import { execSync as execSync3 } from "child_process";
|
|
7263
|
-
import
|
|
7264
|
-
import
|
|
7873
|
+
import path16 from "path";
|
|
7874
|
+
import os9 from "os";
|
|
7265
7875
|
function registerSession(entry) {
|
|
7266
|
-
const dir =
|
|
7267
|
-
if (!
|
|
7268
|
-
|
|
7876
|
+
const dir = path16.dirname(REGISTRY_PATH);
|
|
7877
|
+
if (!existsSync14(dir)) {
|
|
7878
|
+
mkdirSync11(dir, { recursive: true });
|
|
7269
7879
|
}
|
|
7270
7880
|
const sessions = listSessions();
|
|
7271
7881
|
const idx = sessions.findIndex((s) => s.windowName === entry.windowName);
|
|
@@ -7274,11 +7884,11 @@ function registerSession(entry) {
|
|
|
7274
7884
|
} else {
|
|
7275
7885
|
sessions.push(entry);
|
|
7276
7886
|
}
|
|
7277
|
-
|
|
7887
|
+
writeFileSync10(REGISTRY_PATH, JSON.stringify(sessions, null, 2));
|
|
7278
7888
|
}
|
|
7279
7889
|
function listSessions() {
|
|
7280
7890
|
try {
|
|
7281
|
-
const raw =
|
|
7891
|
+
const raw = readFileSync12(REGISTRY_PATH, "utf8");
|
|
7282
7892
|
return JSON.parse(raw);
|
|
7283
7893
|
} catch {
|
|
7284
7894
|
return [];
|
|
@@ -7299,7 +7909,7 @@ function pruneStaleSessions() {
|
|
|
7299
7909
|
const alive = sessions.filter((s) => liveSet.has(s.windowName));
|
|
7300
7910
|
const pruned = sessions.length - alive.length;
|
|
7301
7911
|
if (pruned > 0) {
|
|
7302
|
-
|
|
7912
|
+
writeFileSync10(REGISTRY_PATH, JSON.stringify(alive, null, 2));
|
|
7303
7913
|
}
|
|
7304
7914
|
return pruned;
|
|
7305
7915
|
}
|
|
@@ -7307,7 +7917,7 @@ var REGISTRY_PATH;
|
|
|
7307
7917
|
var init_session_registry = __esm({
|
|
7308
7918
|
"src/lib/session-registry.ts"() {
|
|
7309
7919
|
"use strict";
|
|
7310
|
-
REGISTRY_PATH =
|
|
7920
|
+
REGISTRY_PATH = path16.join(os9.homedir(), ".exe-os", "session-registry.json");
|
|
7311
7921
|
}
|
|
7312
7922
|
});
|
|
7313
7923
|
|
|
@@ -7572,12 +8182,12 @@ var init_runtime_table = __esm({
|
|
|
7572
8182
|
});
|
|
7573
8183
|
|
|
7574
8184
|
// src/lib/agent-config.ts
|
|
7575
|
-
import { readFileSync as
|
|
7576
|
-
import
|
|
8185
|
+
import { readFileSync as readFileSync13, writeFileSync as writeFileSync11, existsSync as existsSync15, mkdirSync as mkdirSync12 } from "fs";
|
|
8186
|
+
import path17 from "path";
|
|
7577
8187
|
function loadAgentConfig() {
|
|
7578
|
-
if (!
|
|
8188
|
+
if (!existsSync15(AGENT_CONFIG_PATH)) return {};
|
|
7579
8189
|
try {
|
|
7580
|
-
return JSON.parse(
|
|
8190
|
+
return JSON.parse(readFileSync13(AGENT_CONFIG_PATH, "utf-8"));
|
|
7581
8191
|
} catch {
|
|
7582
8192
|
return {};
|
|
7583
8193
|
}
|
|
@@ -7596,7 +8206,7 @@ var init_agent_config = __esm({
|
|
|
7596
8206
|
"use strict";
|
|
7597
8207
|
init_config();
|
|
7598
8208
|
init_runtime_table();
|
|
7599
|
-
AGENT_CONFIG_PATH =
|
|
8209
|
+
AGENT_CONFIG_PATH = path17.join(EXE_AI_DIR, "agent-config.json");
|
|
7600
8210
|
DEFAULT_MODELS = {
|
|
7601
8211
|
claude: "claude-opus-4",
|
|
7602
8212
|
codex: RUNTIME_TABLE.codex?.defaultModel ?? "gpt-5.4",
|
|
@@ -7614,25 +8224,25 @@ __export(intercom_queue_exports, {
|
|
|
7614
8224
|
queueIntercom: () => queueIntercom,
|
|
7615
8225
|
readQueue: () => readQueue
|
|
7616
8226
|
});
|
|
7617
|
-
import { readFileSync as
|
|
7618
|
-
import
|
|
7619
|
-
import
|
|
7620
|
-
function
|
|
7621
|
-
const dir =
|
|
7622
|
-
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 });
|
|
7623
8233
|
}
|
|
7624
8234
|
function readQueue() {
|
|
7625
8235
|
try {
|
|
7626
|
-
if (!
|
|
7627
|
-
return JSON.parse(
|
|
8236
|
+
if (!existsSync16(QUEUE_PATH)) return [];
|
|
8237
|
+
return JSON.parse(readFileSync14(QUEUE_PATH, "utf8"));
|
|
7628
8238
|
} catch {
|
|
7629
8239
|
return [];
|
|
7630
8240
|
}
|
|
7631
8241
|
}
|
|
7632
8242
|
function writeQueue(queue) {
|
|
7633
|
-
|
|
8243
|
+
ensureDir2();
|
|
7634
8244
|
const tmp = `${QUEUE_PATH}.tmp`;
|
|
7635
|
-
|
|
8245
|
+
writeFileSync12(tmp, JSON.stringify(queue, null, 2));
|
|
7636
8246
|
renameSync3(tmp, QUEUE_PATH);
|
|
7637
8247
|
}
|
|
7638
8248
|
function queueIntercom(targetSession, reason) {
|
|
@@ -7724,20 +8334,20 @@ var QUEUE_PATH, MAX_RETRIES2, TTL_MS, INTERCOM_LOG;
|
|
|
7724
8334
|
var init_intercom_queue = __esm({
|
|
7725
8335
|
"src/lib/intercom-queue.ts"() {
|
|
7726
8336
|
"use strict";
|
|
7727
|
-
QUEUE_PATH =
|
|
8337
|
+
QUEUE_PATH = path18.join(os10.homedir(), ".exe-os", "intercom-queue.json");
|
|
7728
8338
|
MAX_RETRIES2 = 5;
|
|
7729
8339
|
TTL_MS = 60 * 60 * 1e3;
|
|
7730
|
-
INTERCOM_LOG =
|
|
8340
|
+
INTERCOM_LOG = path18.join(os10.homedir(), ".exe-os", "intercom.log");
|
|
7731
8341
|
}
|
|
7732
8342
|
});
|
|
7733
8343
|
|
|
7734
8344
|
// src/lib/plan-limits.ts
|
|
7735
|
-
import { readFileSync as
|
|
7736
|
-
import
|
|
8345
|
+
import { readFileSync as readFileSync15, existsSync as existsSync17 } from "fs";
|
|
8346
|
+
import path19 from "path";
|
|
7737
8347
|
function getLicenseSync() {
|
|
7738
8348
|
try {
|
|
7739
|
-
if (!
|
|
7740
|
-
const raw = JSON.parse(
|
|
8349
|
+
if (!existsSync17(CACHE_PATH2)) return freeLicense();
|
|
8350
|
+
const raw = JSON.parse(readFileSync15(CACHE_PATH2, "utf8"));
|
|
7741
8351
|
if (!raw.token || typeof raw.token !== "string") return freeLicense();
|
|
7742
8352
|
const parts = raw.token.split(".");
|
|
7743
8353
|
if (parts.length !== 3) return freeLicense();
|
|
@@ -7775,8 +8385,8 @@ function assertEmployeeLimitSync(rosterPath) {
|
|
|
7775
8385
|
const filePath = rosterPath ?? EMPLOYEES_PATH;
|
|
7776
8386
|
let count = 0;
|
|
7777
8387
|
try {
|
|
7778
|
-
if (
|
|
7779
|
-
const raw =
|
|
8388
|
+
if (existsSync17(filePath)) {
|
|
8389
|
+
const raw = readFileSync15(filePath, "utf8");
|
|
7780
8390
|
const employees = JSON.parse(raw);
|
|
7781
8391
|
count = Array.isArray(employees) ? employees.length : 0;
|
|
7782
8392
|
}
|
|
@@ -7805,19 +8415,19 @@ var init_plan_limits = __esm({
|
|
|
7805
8415
|
this.name = "PlanLimitError";
|
|
7806
8416
|
}
|
|
7807
8417
|
};
|
|
7808
|
-
CACHE_PATH2 =
|
|
8418
|
+
CACHE_PATH2 = path19.join(EXE_AI_DIR, "license-cache.json");
|
|
7809
8419
|
}
|
|
7810
8420
|
});
|
|
7811
8421
|
|
|
7812
8422
|
// src/lib/notifications.ts
|
|
7813
8423
|
import crypto5 from "crypto";
|
|
7814
|
-
import
|
|
7815
|
-
import
|
|
8424
|
+
import path20 from "path";
|
|
8425
|
+
import os11 from "os";
|
|
7816
8426
|
import {
|
|
7817
|
-
readFileSync as
|
|
7818
|
-
readdirSync as
|
|
8427
|
+
readFileSync as readFileSync16,
|
|
8428
|
+
readdirSync as readdirSync4,
|
|
7819
8429
|
unlinkSync as unlinkSync5,
|
|
7820
|
-
existsSync as
|
|
8430
|
+
existsSync as existsSync18,
|
|
7821
8431
|
rmdirSync
|
|
7822
8432
|
} from "fs";
|
|
7823
8433
|
async function writeNotification(notification) {
|
|
@@ -7942,11 +8552,11 @@ __export(tasks_crud_exports, {
|
|
|
7942
8552
|
writeCheckpoint: () => writeCheckpoint
|
|
7943
8553
|
});
|
|
7944
8554
|
import crypto7 from "crypto";
|
|
7945
|
-
import
|
|
7946
|
-
import
|
|
8555
|
+
import path21 from "path";
|
|
8556
|
+
import os12 from "os";
|
|
7947
8557
|
import { execSync as execSync6 } from "child_process";
|
|
7948
8558
|
import { mkdir as mkdir5, writeFile as writeFile5, appendFile } from "fs/promises";
|
|
7949
|
-
import { existsSync as
|
|
8559
|
+
import { existsSync as existsSync19, readFileSync as readFileSync17 } from "fs";
|
|
7950
8560
|
async function writeCheckpoint(input) {
|
|
7951
8561
|
const client = getClient();
|
|
7952
8562
|
const row = await resolveTask(client, input.taskId);
|
|
@@ -8121,8 +8731,8 @@ ${laneWarning}` : laneWarning;
|
|
|
8121
8731
|
}
|
|
8122
8732
|
if (input.baseDir) {
|
|
8123
8733
|
try {
|
|
8124
|
-
await mkdir5(
|
|
8125
|
-
await mkdir5(
|
|
8734
|
+
await mkdir5(path21.join(input.baseDir, "exe", "output"), { recursive: true });
|
|
8735
|
+
await mkdir5(path21.join(input.baseDir, "exe", "research"), { recursive: true });
|
|
8126
8736
|
await ensureArchitectureDoc(input.baseDir, input.projectName);
|
|
8127
8737
|
await ensureGitignoreExe(input.baseDir);
|
|
8128
8738
|
} catch {
|
|
@@ -8158,10 +8768,10 @@ ${laneWarning}` : laneWarning;
|
|
|
8158
8768
|
});
|
|
8159
8769
|
if (input.baseDir) {
|
|
8160
8770
|
try {
|
|
8161
|
-
const EXE_OS_DIR =
|
|
8162
|
-
const mdPath =
|
|
8163
|
-
const mdDir =
|
|
8164
|
-
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 });
|
|
8165
8775
|
const reviewer = input.reviewer ?? input.assignedBy;
|
|
8166
8776
|
const mdContent = `# ${input.title}
|
|
8167
8777
|
|
|
@@ -8461,9 +9071,9 @@ async function deleteTaskCore(taskId, _baseDir) {
|
|
|
8461
9071
|
return { taskFile, assignedTo, assignedBy, taskSlug };
|
|
8462
9072
|
}
|
|
8463
9073
|
async function ensureArchitectureDoc(baseDir, projectName) {
|
|
8464
|
-
const archPath =
|
|
9074
|
+
const archPath = path21.join(baseDir, "exe", "ARCHITECTURE.md");
|
|
8465
9075
|
try {
|
|
8466
|
-
if (
|
|
9076
|
+
if (existsSync19(archPath)) return;
|
|
8467
9077
|
const template = [
|
|
8468
9078
|
`# ${projectName} \u2014 System Architecture`,
|
|
8469
9079
|
"",
|
|
@@ -8496,10 +9106,10 @@ async function ensureArchitectureDoc(baseDir, projectName) {
|
|
|
8496
9106
|
}
|
|
8497
9107
|
}
|
|
8498
9108
|
async function ensureGitignoreExe(baseDir) {
|
|
8499
|
-
const gitignorePath =
|
|
9109
|
+
const gitignorePath = path21.join(baseDir, ".gitignore");
|
|
8500
9110
|
try {
|
|
8501
|
-
if (
|
|
8502
|
-
const content =
|
|
9111
|
+
if (existsSync19(gitignorePath)) {
|
|
9112
|
+
const content = readFileSync17(gitignorePath, "utf-8");
|
|
8503
9113
|
if (/^\/?exe\/?$/m.test(content)) return;
|
|
8504
9114
|
await appendFile(gitignorePath, "\n# Employee task assignments (private)\n/exe/\n");
|
|
8505
9115
|
} else {
|
|
@@ -8530,8 +9140,8 @@ var init_tasks_crud = __esm({
|
|
|
8530
9140
|
});
|
|
8531
9141
|
|
|
8532
9142
|
// src/lib/tasks-review.ts
|
|
8533
|
-
import
|
|
8534
|
-
import { existsSync as
|
|
9143
|
+
import path22 from "path";
|
|
9144
|
+
import { existsSync as existsSync20, readdirSync as readdirSync5, unlinkSync as unlinkSync6 } from "fs";
|
|
8535
9145
|
async function countPendingReviews(sessionScope) {
|
|
8536
9146
|
const client = getClient();
|
|
8537
9147
|
if (sessionScope) {
|
|
@@ -8712,11 +9322,11 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
|
|
|
8712
9322
|
);
|
|
8713
9323
|
}
|
|
8714
9324
|
try {
|
|
8715
|
-
const cacheDir =
|
|
8716
|
-
if (
|
|
8717
|
-
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)) {
|
|
8718
9328
|
if (f.startsWith("review-notified-")) {
|
|
8719
|
-
unlinkSync6(
|
|
9329
|
+
unlinkSync6(path22.join(cacheDir, f));
|
|
8720
9330
|
}
|
|
8721
9331
|
}
|
|
8722
9332
|
}
|
|
@@ -8737,7 +9347,7 @@ var init_tasks_review = __esm({
|
|
|
8737
9347
|
});
|
|
8738
9348
|
|
|
8739
9349
|
// src/lib/tasks-chain.ts
|
|
8740
|
-
import
|
|
9350
|
+
import path23 from "path";
|
|
8741
9351
|
import { readFile as readFile5, writeFile as writeFile6 } from "fs/promises";
|
|
8742
9352
|
async function cascadeUnblock(taskId, baseDir, now) {
|
|
8743
9353
|
const client = getClient();
|
|
@@ -8754,7 +9364,7 @@ async function cascadeUnblock(taskId, baseDir, now) {
|
|
|
8754
9364
|
});
|
|
8755
9365
|
for (const ur of unblockedRows.rows) {
|
|
8756
9366
|
try {
|
|
8757
|
-
const ubFile =
|
|
9367
|
+
const ubFile = path23.join(baseDir, String(ur.task_file));
|
|
8758
9368
|
let ubContent = await readFile5(ubFile, "utf-8");
|
|
8759
9369
|
ubContent = ubContent.replace(/\*\*Status:\*\* blocked/, "**Status:** open");
|
|
8760
9370
|
ubContent = ubContent.replace(/\n\*\*Blocked by:\*\*.*\n/, "\n");
|
|
@@ -8823,7 +9433,7 @@ var init_tasks_chain = __esm({
|
|
|
8823
9433
|
|
|
8824
9434
|
// src/lib/project-name.ts
|
|
8825
9435
|
import { execSync as execSync7 } from "child_process";
|
|
8826
|
-
import
|
|
9436
|
+
import path24 from "path";
|
|
8827
9437
|
function getProjectName(cwd2) {
|
|
8828
9438
|
const dir = cwd2 ?? process.cwd();
|
|
8829
9439
|
if (_cached2 && _cachedCwd === dir) return _cached2;
|
|
@@ -8836,7 +9446,7 @@ function getProjectName(cwd2) {
|
|
|
8836
9446
|
timeout: 2e3,
|
|
8837
9447
|
stdio: ["pipe", "pipe", "pipe"]
|
|
8838
9448
|
}).trim();
|
|
8839
|
-
repoRoot =
|
|
9449
|
+
repoRoot = path24.dirname(gitCommonDir);
|
|
8840
9450
|
} catch {
|
|
8841
9451
|
repoRoot = execSync7("git rev-parse --show-toplevel", {
|
|
8842
9452
|
cwd: dir,
|
|
@@ -8845,11 +9455,11 @@ function getProjectName(cwd2) {
|
|
|
8845
9455
|
stdio: ["pipe", "pipe", "pipe"]
|
|
8846
9456
|
}).trim();
|
|
8847
9457
|
}
|
|
8848
|
-
_cached2 =
|
|
9458
|
+
_cached2 = path24.basename(repoRoot);
|
|
8849
9459
|
_cachedCwd = dir;
|
|
8850
9460
|
return _cached2;
|
|
8851
9461
|
} catch {
|
|
8852
|
-
_cached2 =
|
|
9462
|
+
_cached2 = path24.basename(dir);
|
|
8853
9463
|
_cachedCwd = dir;
|
|
8854
9464
|
return _cached2;
|
|
8855
9465
|
}
|
|
@@ -9322,8 +9932,8 @@ __export(tasks_exports, {
|
|
|
9322
9932
|
updateTaskStatus: () => updateTaskStatus,
|
|
9323
9933
|
writeCheckpoint: () => writeCheckpoint
|
|
9324
9934
|
});
|
|
9325
|
-
import
|
|
9326
|
-
import { writeFileSync as
|
|
9935
|
+
import path25 from "path";
|
|
9936
|
+
import { writeFileSync as writeFileSync13, mkdirSync as mkdirSync14, unlinkSync as unlinkSync7 } from "fs";
|
|
9327
9937
|
async function createTask(input) {
|
|
9328
9938
|
const result = await createTaskCore(input);
|
|
9329
9939
|
if (!input.skipDispatch && result.status !== "blocked" && !process.env.VITEST) {
|
|
@@ -9342,11 +9952,11 @@ async function updateTask(input) {
|
|
|
9342
9952
|
const { row, taskFile, now, taskId } = await updateTaskStatus(input);
|
|
9343
9953
|
try {
|
|
9344
9954
|
const agent = String(row.assigned_to);
|
|
9345
|
-
const cacheDir =
|
|
9346
|
-
const cachePath =
|
|
9955
|
+
const cacheDir = path25.join(EXE_AI_DIR, "session-cache");
|
|
9956
|
+
const cachePath = path25.join(cacheDir, `current-task-${agent}.json`);
|
|
9347
9957
|
if (input.status === "in_progress") {
|
|
9348
|
-
|
|
9349
|
-
|
|
9958
|
+
mkdirSync14(cacheDir, { recursive: true });
|
|
9959
|
+
writeFileSync13(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
|
|
9350
9960
|
} else if (input.status === "done" || input.status === "blocked" || input.status === "cancelled") {
|
|
9351
9961
|
try {
|
|
9352
9962
|
unlinkSync7(cachePath);
|
|
@@ -9813,13 +10423,13 @@ __export(tmux_routing_exports, {
|
|
|
9813
10423
|
verifyPaneAtCapacity: () => verifyPaneAtCapacity
|
|
9814
10424
|
});
|
|
9815
10425
|
import { execFileSync as execFileSync2, execSync as execSync8 } from "child_process";
|
|
9816
|
-
import { readFileSync as
|
|
9817
|
-
import
|
|
9818
|
-
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";
|
|
9819
10429
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
9820
10430
|
import { unlinkSync as unlinkSync8 } from "fs";
|
|
9821
10431
|
function spawnLockPath(sessionName) {
|
|
9822
|
-
return
|
|
10432
|
+
return path26.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
|
|
9823
10433
|
}
|
|
9824
10434
|
function isProcessAlive(pid) {
|
|
9825
10435
|
try {
|
|
@@ -9830,13 +10440,13 @@ function isProcessAlive(pid) {
|
|
|
9830
10440
|
}
|
|
9831
10441
|
}
|
|
9832
10442
|
function acquireSpawnLock2(sessionName) {
|
|
9833
|
-
if (!
|
|
9834
|
-
|
|
10443
|
+
if (!existsSync21(SPAWN_LOCK_DIR)) {
|
|
10444
|
+
mkdirSync15(SPAWN_LOCK_DIR, { recursive: true });
|
|
9835
10445
|
}
|
|
9836
10446
|
const lockFile = spawnLockPath(sessionName);
|
|
9837
|
-
if (
|
|
10447
|
+
if (existsSync21(lockFile)) {
|
|
9838
10448
|
try {
|
|
9839
|
-
const lock = JSON.parse(
|
|
10449
|
+
const lock = JSON.parse(readFileSync18(lockFile, "utf8"));
|
|
9840
10450
|
const age = Date.now() - lock.timestamp;
|
|
9841
10451
|
if (isProcessAlive(lock.pid) && age < 6e4) {
|
|
9842
10452
|
return false;
|
|
@@ -9844,7 +10454,7 @@ function acquireSpawnLock2(sessionName) {
|
|
|
9844
10454
|
} catch {
|
|
9845
10455
|
}
|
|
9846
10456
|
}
|
|
9847
|
-
|
|
10457
|
+
writeFileSync14(lockFile, JSON.stringify({ pid: process.pid, timestamp: Date.now() }));
|
|
9848
10458
|
return true;
|
|
9849
10459
|
}
|
|
9850
10460
|
function releaseSpawnLock2(sessionName) {
|
|
@@ -9856,13 +10466,13 @@ function releaseSpawnLock2(sessionName) {
|
|
|
9856
10466
|
function resolveBehaviorsExporterScript() {
|
|
9857
10467
|
try {
|
|
9858
10468
|
const thisFile = fileURLToPath4(import.meta.url);
|
|
9859
|
-
const scriptPath =
|
|
9860
|
-
|
|
10469
|
+
const scriptPath = path26.join(
|
|
10470
|
+
path26.dirname(thisFile),
|
|
9861
10471
|
"..",
|
|
9862
10472
|
"bin",
|
|
9863
10473
|
"exe-export-behaviors.js"
|
|
9864
10474
|
);
|
|
9865
|
-
return
|
|
10475
|
+
return existsSync21(scriptPath) ? scriptPath : null;
|
|
9866
10476
|
} catch {
|
|
9867
10477
|
return null;
|
|
9868
10478
|
}
|
|
@@ -9928,12 +10538,12 @@ function extractRootExe(name) {
|
|
|
9928
10538
|
return parts.length > 0 ? parts[parts.length - 1] : null;
|
|
9929
10539
|
}
|
|
9930
10540
|
function registerParentExe(sessionKey, parentExe, dispatchedBy) {
|
|
9931
|
-
if (!
|
|
9932
|
-
|
|
10541
|
+
if (!existsSync21(SESSION_CACHE)) {
|
|
10542
|
+
mkdirSync15(SESSION_CACHE, { recursive: true });
|
|
9933
10543
|
}
|
|
9934
10544
|
const rootExe = extractRootExe(parentExe) ?? parentExe;
|
|
9935
|
-
const filePath =
|
|
9936
|
-
|
|
10545
|
+
const filePath = path26.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
|
|
10546
|
+
writeFileSync14(filePath, JSON.stringify({
|
|
9937
10547
|
parentExe: rootExe,
|
|
9938
10548
|
dispatchedBy: dispatchedBy || rootExe,
|
|
9939
10549
|
registeredAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -9941,7 +10551,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
|
|
|
9941
10551
|
}
|
|
9942
10552
|
function getParentExe(sessionKey) {
|
|
9943
10553
|
try {
|
|
9944
|
-
const data = JSON.parse(
|
|
10554
|
+
const data = JSON.parse(readFileSync18(path26.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
|
|
9945
10555
|
return data.parentExe || null;
|
|
9946
10556
|
} catch {
|
|
9947
10557
|
return null;
|
|
@@ -9949,8 +10559,8 @@ function getParentExe(sessionKey) {
|
|
|
9949
10559
|
}
|
|
9950
10560
|
function getDispatchedBy(sessionKey) {
|
|
9951
10561
|
try {
|
|
9952
|
-
const data = JSON.parse(
|
|
9953
|
-
|
|
10562
|
+
const data = JSON.parse(readFileSync18(
|
|
10563
|
+
path26.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
|
|
9954
10564
|
"utf8"
|
|
9955
10565
|
));
|
|
9956
10566
|
return data.dispatchedBy ?? data.parentExe ?? null;
|
|
@@ -10011,8 +10621,8 @@ async function verifyPaneAtCapacity(sessionName) {
|
|
|
10011
10621
|
}
|
|
10012
10622
|
function readDebounceState() {
|
|
10013
10623
|
try {
|
|
10014
|
-
if (!
|
|
10015
|
-
const raw = JSON.parse(
|
|
10624
|
+
if (!existsSync21(DEBOUNCE_FILE)) return {};
|
|
10625
|
+
const raw = JSON.parse(readFileSync18(DEBOUNCE_FILE, "utf8"));
|
|
10016
10626
|
const state = {};
|
|
10017
10627
|
for (const [key, val] of Object.entries(raw)) {
|
|
10018
10628
|
if (typeof val === "number") {
|
|
@@ -10028,8 +10638,8 @@ function readDebounceState() {
|
|
|
10028
10638
|
}
|
|
10029
10639
|
function writeDebounceState(state) {
|
|
10030
10640
|
try {
|
|
10031
|
-
if (!
|
|
10032
|
-
|
|
10641
|
+
if (!existsSync21(SESSION_CACHE)) mkdirSync15(SESSION_CACHE, { recursive: true });
|
|
10642
|
+
writeFileSync14(DEBOUNCE_FILE, JSON.stringify(state));
|
|
10033
10643
|
} catch {
|
|
10034
10644
|
}
|
|
10035
10645
|
}
|
|
@@ -10127,8 +10737,8 @@ function sendIntercom(targetSession) {
|
|
|
10127
10737
|
try {
|
|
10128
10738
|
const rawAgent = targetSession.split("-")[0] ?? targetSession;
|
|
10129
10739
|
const agent = baseAgentName(rawAgent);
|
|
10130
|
-
const markerPath =
|
|
10131
|
-
if (
|
|
10740
|
+
const markerPath = path26.join(SESSION_CACHE, `current-task-${agent}.json`);
|
|
10741
|
+
if (existsSync21(markerPath)) {
|
|
10132
10742
|
logIntercom(`SKIP \u2192 ${targetSession} (has in_progress task marker \u2014 will auto-chain)`);
|
|
10133
10743
|
return "debounced";
|
|
10134
10744
|
}
|
|
@@ -10253,26 +10863,26 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
10253
10863
|
const transport = getTransport();
|
|
10254
10864
|
const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
|
|
10255
10865
|
const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
|
|
10256
|
-
const logDir =
|
|
10257
|
-
const logFile =
|
|
10258
|
-
if (!
|
|
10259
|
-
|
|
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 });
|
|
10260
10870
|
}
|
|
10261
10871
|
transport.kill(sessionName);
|
|
10262
10872
|
let cleanupSuffix = "";
|
|
10263
10873
|
try {
|
|
10264
10874
|
const thisFile = fileURLToPath4(import.meta.url);
|
|
10265
|
-
const cleanupScript =
|
|
10266
|
-
if (
|
|
10875
|
+
const cleanupScript = path26.join(path26.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
|
|
10876
|
+
if (existsSync21(cleanupScript)) {
|
|
10267
10877
|
cleanupSuffix = `; ${process.execPath} "${cleanupScript}" "${employeeName}" "${exeSession}"`;
|
|
10268
10878
|
}
|
|
10269
10879
|
} catch {
|
|
10270
10880
|
}
|
|
10271
10881
|
try {
|
|
10272
|
-
const claudeJsonPath =
|
|
10882
|
+
const claudeJsonPath = path26.join(os13.homedir(), ".claude.json");
|
|
10273
10883
|
let claudeJson = {};
|
|
10274
10884
|
try {
|
|
10275
|
-
claudeJson = JSON.parse(
|
|
10885
|
+
claudeJson = JSON.parse(readFileSync18(claudeJsonPath, "utf8"));
|
|
10276
10886
|
} catch {
|
|
10277
10887
|
}
|
|
10278
10888
|
if (!claudeJson.projects) claudeJson.projects = {};
|
|
@@ -10280,17 +10890,17 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
10280
10890
|
const trustDir = opts?.cwd ?? projectDir;
|
|
10281
10891
|
if (!projects[trustDir]) projects[trustDir] = {};
|
|
10282
10892
|
projects[trustDir].hasTrustDialogAccepted = true;
|
|
10283
|
-
|
|
10893
|
+
writeFileSync14(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
|
|
10284
10894
|
} catch {
|
|
10285
10895
|
}
|
|
10286
10896
|
try {
|
|
10287
|
-
const settingsDir =
|
|
10897
|
+
const settingsDir = path26.join(os13.homedir(), ".claude", "projects");
|
|
10288
10898
|
const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
|
|
10289
|
-
const projSettingsDir =
|
|
10290
|
-
const settingsPath =
|
|
10899
|
+
const projSettingsDir = path26.join(settingsDir, normalizedKey);
|
|
10900
|
+
const settingsPath = path26.join(projSettingsDir, "settings.json");
|
|
10291
10901
|
let settings = {};
|
|
10292
10902
|
try {
|
|
10293
|
-
settings = JSON.parse(
|
|
10903
|
+
settings = JSON.parse(readFileSync18(settingsPath, "utf8"));
|
|
10294
10904
|
} catch {
|
|
10295
10905
|
}
|
|
10296
10906
|
const perms = settings.permissions ?? {};
|
|
@@ -10318,8 +10928,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
10318
10928
|
if (changed) {
|
|
10319
10929
|
perms.allow = allow;
|
|
10320
10930
|
settings.permissions = perms;
|
|
10321
|
-
|
|
10322
|
-
|
|
10931
|
+
mkdirSync15(projSettingsDir, { recursive: true });
|
|
10932
|
+
writeFileSync14(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
10323
10933
|
}
|
|
10324
10934
|
} catch {
|
|
10325
10935
|
}
|
|
@@ -10334,8 +10944,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
10334
10944
|
let behaviorsFlag = "";
|
|
10335
10945
|
let legacyFallbackWarned = false;
|
|
10336
10946
|
if (!useExeAgent && !useBinSymlink) {
|
|
10337
|
-
const identityPath2 =
|
|
10338
|
-
|
|
10947
|
+
const identityPath2 = path26.join(
|
|
10948
|
+
os13.homedir(),
|
|
10339
10949
|
".exe-os",
|
|
10340
10950
|
"identity",
|
|
10341
10951
|
`${employeeName}.md`
|
|
@@ -10344,13 +10954,13 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
10344
10954
|
const hasAgentFlag = claudeSupportsAgentFlag();
|
|
10345
10955
|
if (hasAgentFlag) {
|
|
10346
10956
|
identityFlag = ` --agent ${employeeName}`;
|
|
10347
|
-
} else if (
|
|
10957
|
+
} else if (existsSync21(identityPath2)) {
|
|
10348
10958
|
identityFlag = ` --append-system-prompt-file ${identityPath2}`;
|
|
10349
10959
|
legacyFallbackWarned = true;
|
|
10350
10960
|
}
|
|
10351
10961
|
const behaviorsFile = exportBehaviorsSync(
|
|
10352
10962
|
employeeName,
|
|
10353
|
-
|
|
10963
|
+
path26.basename(spawnCwd),
|
|
10354
10964
|
sessionName
|
|
10355
10965
|
);
|
|
10356
10966
|
if (behaviorsFile) {
|
|
@@ -10365,16 +10975,16 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
10365
10975
|
}
|
|
10366
10976
|
let sessionContextFlag = "";
|
|
10367
10977
|
try {
|
|
10368
|
-
const ctxDir =
|
|
10369
|
-
|
|
10370
|
-
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`);
|
|
10371
10981
|
const ctxContent = [
|
|
10372
10982
|
`## Session Context`,
|
|
10373
10983
|
`You are running in tmux session: ${sessionName}.`,
|
|
10374
10984
|
`Your parent coordinator session is ${exeSession}.`,
|
|
10375
10985
|
`Your employees (if any) use the -${exeSession} suffix.`
|
|
10376
10986
|
].join("\n");
|
|
10377
|
-
|
|
10987
|
+
writeFileSync14(ctxFile, ctxContent);
|
|
10378
10988
|
sessionContextFlag = ` --append-system-prompt-file ${ctxFile}`;
|
|
10379
10989
|
} catch {
|
|
10380
10990
|
}
|
|
@@ -10451,8 +11061,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
10451
11061
|
transport.pipeLog(sessionName, logFile);
|
|
10452
11062
|
try {
|
|
10453
11063
|
const mySession = getMySession();
|
|
10454
|
-
const dispatchInfo =
|
|
10455
|
-
|
|
11064
|
+
const dispatchInfo = path26.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
|
|
11065
|
+
writeFileSync14(dispatchInfo, JSON.stringify({
|
|
10456
11066
|
dispatchedBy: mySession,
|
|
10457
11067
|
rootExe: exeSession,
|
|
10458
11068
|
provider: useBinSymlink ? ccProvider : useExeAgent ? opts.provider : useCodex ? "openai" : useOpencode ? "opencode" : "anthropic",
|
|
@@ -10526,15 +11136,15 @@ var init_tmux_routing = __esm({
|
|
|
10526
11136
|
init_intercom_queue();
|
|
10527
11137
|
init_plan_limits();
|
|
10528
11138
|
init_employees();
|
|
10529
|
-
SPAWN_LOCK_DIR =
|
|
10530
|
-
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");
|
|
10531
11141
|
BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
|
|
10532
11142
|
VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
|
|
10533
11143
|
VERIFY_PANE_LINES = 200;
|
|
10534
11144
|
INTERCOM_DEBOUNCE_MS = 3e4;
|
|
10535
11145
|
CODEX_DEBOUNCE_MS = 12e4;
|
|
10536
|
-
INTERCOM_LOG2 =
|
|
10537
|
-
DEBOUNCE_FILE =
|
|
11146
|
+
INTERCOM_LOG2 = path26.join(os13.homedir(), ".exe-os", "intercom.log");
|
|
11147
|
+
DEBOUNCE_FILE = path26.join(SESSION_CACHE, "intercom-debounce.json");
|
|
10538
11148
|
DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
|
|
10539
11149
|
BUSY_PATTERN = /[✻✽✶✳·].*…|Running…|• Working|• Ran |• Explored|• Called|esc to interrupt/;
|
|
10540
11150
|
}
|
|
@@ -10801,9 +11411,9 @@ __export(active_agent_exports, {
|
|
|
10801
11411
|
resolveActiveAgentFromTmuxSession: () => resolveActiveAgentFromTmuxSession,
|
|
10802
11412
|
writeActiveAgent: () => writeActiveAgent
|
|
10803
11413
|
});
|
|
10804
|
-
import { readFileSync as
|
|
11414
|
+
import { readFileSync as readFileSync19, writeFileSync as writeFileSync15, mkdirSync as mkdirSync16, unlinkSync as unlinkSync9, readdirSync as readdirSync6 } from "fs";
|
|
10805
11415
|
import { execSync as execSync9 } from "child_process";
|
|
10806
|
-
import
|
|
11416
|
+
import path27 from "path";
|
|
10807
11417
|
function isNameWithOptionalInstance(candidate, baseName) {
|
|
10808
11418
|
if (candidate === baseName) return true;
|
|
10809
11419
|
if (!candidate.startsWith(baseName)) return false;
|
|
@@ -10847,12 +11457,12 @@ function resolveActiveAgentFromTmuxSession(sessionName) {
|
|
|
10847
11457
|
return null;
|
|
10848
11458
|
}
|
|
10849
11459
|
function getMarkerPath() {
|
|
10850
|
-
return
|
|
11460
|
+
return path27.join(CACHE_DIR, `active-agent-${getSessionKey()}.json`);
|
|
10851
11461
|
}
|
|
10852
11462
|
function writeActiveAgent(agentId, agentRole) {
|
|
10853
11463
|
try {
|
|
10854
|
-
|
|
10855
|
-
|
|
11464
|
+
mkdirSync16(CACHE_DIR, { recursive: true });
|
|
11465
|
+
writeFileSync15(
|
|
10856
11466
|
getMarkerPath(),
|
|
10857
11467
|
JSON.stringify({ agentId, agentRole, startedAt: (/* @__PURE__ */ new Date()).toISOString() })
|
|
10858
11468
|
);
|
|
@@ -10868,7 +11478,7 @@ function clearActiveAgent() {
|
|
|
10868
11478
|
function getActiveAgent() {
|
|
10869
11479
|
try {
|
|
10870
11480
|
const markerPath = getMarkerPath();
|
|
10871
|
-
const raw =
|
|
11481
|
+
const raw = readFileSync19(markerPath, "utf8");
|
|
10872
11482
|
const data = JSON.parse(raw);
|
|
10873
11483
|
if (data.agentId) {
|
|
10874
11484
|
if (data.startedAt) {
|
|
@@ -10909,21 +11519,21 @@ function getActiveAgent() {
|
|
|
10909
11519
|
}
|
|
10910
11520
|
function getAllActiveAgents() {
|
|
10911
11521
|
try {
|
|
10912
|
-
const files =
|
|
11522
|
+
const files = readdirSync6(CACHE_DIR);
|
|
10913
11523
|
const sessions = [];
|
|
10914
11524
|
for (const file of files) {
|
|
10915
11525
|
if (!file.startsWith("active-agent-") || !file.endsWith(".json")) continue;
|
|
10916
11526
|
const key = file.slice("active-agent-".length, -".json".length);
|
|
10917
11527
|
if (key === "undefined") continue;
|
|
10918
11528
|
try {
|
|
10919
|
-
const raw =
|
|
11529
|
+
const raw = readFileSync19(path27.join(CACHE_DIR, file), "utf8");
|
|
10920
11530
|
const data = JSON.parse(raw);
|
|
10921
11531
|
if (!data.agentId) continue;
|
|
10922
11532
|
if (data.startedAt) {
|
|
10923
11533
|
const age = Date.now() - new Date(data.startedAt).getTime();
|
|
10924
11534
|
if (age > STALE_MS) {
|
|
10925
11535
|
try {
|
|
10926
|
-
unlinkSync9(
|
|
11536
|
+
unlinkSync9(path27.join(CACHE_DIR, file));
|
|
10927
11537
|
} catch {
|
|
10928
11538
|
}
|
|
10929
11539
|
continue;
|
|
@@ -10946,11 +11556,11 @@ function getAllActiveAgents() {
|
|
|
10946
11556
|
function cleanupSessionMarkers() {
|
|
10947
11557
|
const key = getSessionKey();
|
|
10948
11558
|
try {
|
|
10949
|
-
unlinkSync9(
|
|
11559
|
+
unlinkSync9(path27.join(CACHE_DIR, `active-agent-${key}.json`));
|
|
10950
11560
|
} catch {
|
|
10951
11561
|
}
|
|
10952
11562
|
try {
|
|
10953
|
-
unlinkSync9(
|
|
11563
|
+
unlinkSync9(path27.join(CACHE_DIR, "active-agent-undefined.json"));
|
|
10954
11564
|
} catch {
|
|
10955
11565
|
}
|
|
10956
11566
|
}
|
|
@@ -10961,7 +11571,7 @@ var init_active_agent = __esm({
|
|
|
10961
11571
|
init_config();
|
|
10962
11572
|
init_session_key();
|
|
10963
11573
|
init_employees();
|
|
10964
|
-
CACHE_DIR =
|
|
11574
|
+
CACHE_DIR = path27.join(EXE_AI_DIR, "session-cache");
|
|
10965
11575
|
STALE_MS = 24 * 60 * 60 * 1e3;
|
|
10966
11576
|
}
|
|
10967
11577
|
});
|
|
@@ -11097,10 +11707,10 @@ You report to the COO. All work flows through the COO. These procedures are non-
|
|
|
11097
11707
|
Use store_memory to write a structured summary. Include: project name, what was done,
|
|
11098
11708
|
decisions made, tests status, open items or risks.
|
|
11099
11709
|
|
|
11100
|
-
6. AFTER committing changes to exe-os itself \u2014 REBUILD
|
|
11101
|
-
-
|
|
11102
|
-
-
|
|
11103
|
-
-
|
|
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.
|
|
11104
11714
|
- If the build fails, fix the error and retry before moving on.
|
|
11105
11715
|
|
|
11106
11716
|
7. AFTER reporting \u2014 CHECK FOR NEXT WORK (mandatory):
|
|
@@ -11589,14 +12199,14 @@ __export(exe_rename_exports, {
|
|
|
11589
12199
|
main: () => main2,
|
|
11590
12200
|
renameEmployee: () => renameEmployee
|
|
11591
12201
|
});
|
|
11592
|
-
import { readFileSync as
|
|
12202
|
+
import { readFileSync as readFileSync20, writeFileSync as writeFileSync16, renameSync as renameSync4, unlinkSync as unlinkSync10, existsSync as existsSync22 } from "fs";
|
|
11593
12203
|
import { execSync as execSync10 } from "child_process";
|
|
11594
|
-
import
|
|
12204
|
+
import path28 from "path";
|
|
11595
12205
|
import { homedir as homedir4 } from "os";
|
|
11596
12206
|
async function renameEmployee(oldName, newName, opts = {}) {
|
|
11597
|
-
const rosterPath = opts.rosterPath ??
|
|
11598
|
-
const identityDir = opts.identityDir ??
|
|
11599
|
-
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");
|
|
11600
12210
|
const validation = validateEmployeeName(newName);
|
|
11601
12211
|
if (!validation.valid) {
|
|
11602
12212
|
return { success: false, error: validation.error };
|
|
@@ -11625,40 +12235,40 @@ async function renameEmployee(oldName, newName, opts = {}) {
|
|
|
11625
12235
|
undo: () => {
|
|
11626
12236
|
employee.name = originalName;
|
|
11627
12237
|
employee.systemPrompt = originalPrompt;
|
|
11628
|
-
|
|
12238
|
+
writeFileSync16(rosterPath, JSON.stringify(employees, null, 2) + "\n", "utf-8");
|
|
11629
12239
|
}
|
|
11630
12240
|
});
|
|
11631
|
-
const oldIdentityPath =
|
|
11632
|
-
const newIdentityPath =
|
|
11633
|
-
if (
|
|
11634
|
-
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");
|
|
11635
12245
|
const updatedContent = content.replace(
|
|
11636
12246
|
/^(agent_id:\s*)\S+/m,
|
|
11637
12247
|
`$1${newName}`
|
|
11638
12248
|
);
|
|
11639
12249
|
renameSync4(oldIdentityPath, newIdentityPath);
|
|
11640
|
-
|
|
12250
|
+
writeFileSync16(newIdentityPath, updatedContent, "utf-8");
|
|
11641
12251
|
rollbackStack.push({
|
|
11642
12252
|
description: "restore identity file",
|
|
11643
12253
|
undo: () => {
|
|
11644
|
-
if (
|
|
11645
|
-
|
|
12254
|
+
if (existsSync22(newIdentityPath)) {
|
|
12255
|
+
writeFileSync16(newIdentityPath, content, "utf-8");
|
|
11646
12256
|
renameSync4(newIdentityPath, oldIdentityPath);
|
|
11647
12257
|
}
|
|
11648
12258
|
}
|
|
11649
12259
|
});
|
|
11650
12260
|
}
|
|
11651
|
-
const oldAgentPath =
|
|
11652
|
-
const newAgentPath =
|
|
11653
|
-
if (
|
|
11654
|
-
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");
|
|
11655
12265
|
renameSync4(oldAgentPath, newAgentPath);
|
|
11656
12266
|
rollbackStack.push({
|
|
11657
12267
|
description: "restore agent file",
|
|
11658
12268
|
undo: () => {
|
|
11659
|
-
if (
|
|
12269
|
+
if (existsSync22(newAgentPath)) {
|
|
11660
12270
|
renameSync4(newAgentPath, oldAgentPath);
|
|
11661
|
-
|
|
12271
|
+
writeFileSync16(oldAgentPath, agentContent, "utf-8");
|
|
11662
12272
|
}
|
|
11663
12273
|
}
|
|
11664
12274
|
});
|
|
@@ -11736,10 +12346,10 @@ function removeOldSymlinks(name) {
|
|
|
11736
12346
|
try {
|
|
11737
12347
|
const exeBinPath = findExeBin2();
|
|
11738
12348
|
if (!exeBinPath) return;
|
|
11739
|
-
const binDir =
|
|
12349
|
+
const binDir = path28.dirname(exeBinPath);
|
|
11740
12350
|
for (const suffix of ["", "-opencode"]) {
|
|
11741
|
-
const linkPath =
|
|
11742
|
-
if (
|
|
12351
|
+
const linkPath = path28.join(binDir, `${name}${suffix}`);
|
|
12352
|
+
if (existsSync22(linkPath)) {
|
|
11743
12353
|
try {
|
|
11744
12354
|
unlinkSync10(linkPath);
|
|
11745
12355
|
} catch {
|
|
@@ -11784,16 +12394,16 @@ var init_exe_rename = __esm({
|
|
|
11784
12394
|
});
|
|
11785
12395
|
|
|
11786
12396
|
// src/lib/model-downloader.ts
|
|
11787
|
-
import { createWriteStream, createReadStream as createReadStream2, existsSync as
|
|
12397
|
+
import { createWriteStream, createReadStream as createReadStream2, existsSync as existsSync23, unlinkSync as unlinkSync11, renameSync as renameSync5 } from "fs";
|
|
11788
12398
|
import { mkdir as mkdir6 } from "fs/promises";
|
|
11789
|
-
import { createHash as
|
|
11790
|
-
import
|
|
12399
|
+
import { createHash as createHash3 } from "crypto";
|
|
12400
|
+
import path29 from "path";
|
|
11791
12401
|
async function downloadModel(opts) {
|
|
11792
12402
|
const { destDir, onProgress, fetchFn = globalThis.fetch } = opts;
|
|
11793
|
-
const destPath =
|
|
12403
|
+
const destPath = path29.join(destDir, LOCAL_FILENAME);
|
|
11794
12404
|
const tmpPath = destPath + ".tmp";
|
|
11795
12405
|
await mkdir6(destDir, { recursive: true });
|
|
11796
|
-
if (
|
|
12406
|
+
if (existsSync23(destPath)) {
|
|
11797
12407
|
const hash = await fileHash(destPath);
|
|
11798
12408
|
if (hash === EXPECTED_SHA256) {
|
|
11799
12409
|
return destPath;
|
|
@@ -11805,7 +12415,7 @@ async function downloadModel(opts) {
|
|
|
11805
12415
|
let downloaded = 0;
|
|
11806
12416
|
for (let attempt = 1; attempt <= MAX_RETRIES4; attempt++) {
|
|
11807
12417
|
try {
|
|
11808
|
-
if (
|
|
12418
|
+
if (existsSync23(tmpPath)) unlinkSync11(tmpPath);
|
|
11809
12419
|
const response = await fetchFn(GGUF_URL, {
|
|
11810
12420
|
redirect: "follow",
|
|
11811
12421
|
signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS)
|
|
@@ -11814,7 +12424,7 @@ async function downloadModel(opts) {
|
|
|
11814
12424
|
throw new Error(`Download failed: HTTP ${response.status}`);
|
|
11815
12425
|
}
|
|
11816
12426
|
const contentLength = Number(response.headers.get("content-length") ?? EXPECTED_SIZE);
|
|
11817
|
-
const hash =
|
|
12427
|
+
const hash = createHash3("sha256");
|
|
11818
12428
|
const fileStream = createWriteStream(tmpPath);
|
|
11819
12429
|
const reader = response.body.getReader();
|
|
11820
12430
|
try {
|
|
@@ -11850,7 +12460,7 @@ async function downloadModel(opts) {
|
|
|
11850
12460
|
process.stderr.write(`
|
|
11851
12461
|
Download attempt ${attempt} failed, retrying...
|
|
11852
12462
|
`);
|
|
11853
|
-
if (
|
|
12463
|
+
if (existsSync23(tmpPath)) unlinkSync11(tmpPath);
|
|
11854
12464
|
}
|
|
11855
12465
|
}
|
|
11856
12466
|
}
|
|
@@ -11858,7 +12468,7 @@ Download attempt ${attempt} failed, retrying...
|
|
|
11858
12468
|
}
|
|
11859
12469
|
async function fileHash(filePath) {
|
|
11860
12470
|
return new Promise((resolve, reject) => {
|
|
11861
|
-
const hash =
|
|
12471
|
+
const hash = createHash3("sha256");
|
|
11862
12472
|
const stream = createReadStream2(filePath);
|
|
11863
12473
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
11864
12474
|
stream.on("end", () => resolve(hash.digest("hex")));
|
|
@@ -11913,10 +12523,10 @@ async function disposeEmbedder() {
|
|
|
11913
12523
|
async function embedDirect(text) {
|
|
11914
12524
|
const llamaCpp = await import("node-llama-cpp");
|
|
11915
12525
|
const { MODELS_DIR: MODELS_DIR2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
11916
|
-
const { existsSync:
|
|
11917
|
-
const
|
|
11918
|
-
const modelPath =
|
|
11919
|
-
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)) {
|
|
11920
12530
|
throw new Error(`Embedding model not found at ${modelPath}. Run '/exe-setup' to download it.`);
|
|
11921
12531
|
}
|
|
11922
12532
|
const llama = await llamaCpp.getLlama();
|
|
@@ -11944,141 +12554,6 @@ var init_embedder = __esm({
|
|
|
11944
12554
|
}
|
|
11945
12555
|
});
|
|
11946
12556
|
|
|
11947
|
-
// src/lib/identity.ts
|
|
11948
|
-
var identity_exports = {};
|
|
11949
|
-
__export(identity_exports, {
|
|
11950
|
-
getIdentity: () => getIdentity,
|
|
11951
|
-
getIdentityInjection: () => getIdentityInjection,
|
|
11952
|
-
identityPath: () => identityPath,
|
|
11953
|
-
listIdentities: () => listIdentities,
|
|
11954
|
-
updateIdentity: () => updateIdentity
|
|
11955
|
-
});
|
|
11956
|
-
import { existsSync as existsSync22, mkdirSync as mkdirSync14, readFileSync as readFileSync18, writeFileSync as writeFileSync14 } from "fs";
|
|
11957
|
-
import { readdirSync as readdirSync6 } from "fs";
|
|
11958
|
-
import path27 from "path";
|
|
11959
|
-
import { createHash as createHash3 } from "crypto";
|
|
11960
|
-
function ensureDir2() {
|
|
11961
|
-
if (!existsSync22(IDENTITY_DIR)) {
|
|
11962
|
-
mkdirSync14(IDENTITY_DIR, { recursive: true });
|
|
11963
|
-
}
|
|
11964
|
-
}
|
|
11965
|
-
function identityPath(agentId) {
|
|
11966
|
-
return path27.join(IDENTITY_DIR, `${agentId}.md`);
|
|
11967
|
-
}
|
|
11968
|
-
function parseFrontmatter(raw) {
|
|
11969
|
-
const match = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
11970
|
-
if (!match) {
|
|
11971
|
-
return {
|
|
11972
|
-
frontmatter: {
|
|
11973
|
-
role: "unknown",
|
|
11974
|
-
title: "Unknown",
|
|
11975
|
-
agent_id: "unknown",
|
|
11976
|
-
org_level: "specialist",
|
|
11977
|
-
created_by: "system",
|
|
11978
|
-
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
11979
|
-
},
|
|
11980
|
-
body: raw
|
|
11981
|
-
};
|
|
11982
|
-
}
|
|
11983
|
-
const yamlStr = match[1];
|
|
11984
|
-
const body = match[2].trim();
|
|
11985
|
-
const fm = {};
|
|
11986
|
-
for (const line of yamlStr.split("\n")) {
|
|
11987
|
-
const kv = line.match(/^(\w+):\s*(.+)$/);
|
|
11988
|
-
if (kv) fm[kv[1]] = kv[2].trim();
|
|
11989
|
-
}
|
|
11990
|
-
return {
|
|
11991
|
-
frontmatter: {
|
|
11992
|
-
role: fm.role ?? "unknown",
|
|
11993
|
-
title: fm.title ?? "Unknown",
|
|
11994
|
-
agent_id: fm.agent_id ?? "unknown",
|
|
11995
|
-
org_level: fm.org_level ?? "specialist",
|
|
11996
|
-
created_by: fm.created_by ?? "system",
|
|
11997
|
-
updated_at: fm.updated_at ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
11998
|
-
},
|
|
11999
|
-
body
|
|
12000
|
-
};
|
|
12001
|
-
}
|
|
12002
|
-
function contentHash(content) {
|
|
12003
|
-
return createHash3("sha256").update(content).digest("hex").slice(0, 16);
|
|
12004
|
-
}
|
|
12005
|
-
function getIdentity(agentId) {
|
|
12006
|
-
const filePath = identityPath(agentId);
|
|
12007
|
-
if (!existsSync22(filePath)) return null;
|
|
12008
|
-
const raw = readFileSync18(filePath, "utf-8");
|
|
12009
|
-
const { frontmatter, body } = parseFrontmatter(raw);
|
|
12010
|
-
return {
|
|
12011
|
-
agentId,
|
|
12012
|
-
frontmatter,
|
|
12013
|
-
body,
|
|
12014
|
-
raw,
|
|
12015
|
-
contentHash: contentHash(raw)
|
|
12016
|
-
};
|
|
12017
|
-
}
|
|
12018
|
-
async function updateIdentity(agentId, content, updatedBy) {
|
|
12019
|
-
ensureDir2();
|
|
12020
|
-
const filePath = identityPath(agentId);
|
|
12021
|
-
const hash = contentHash(content);
|
|
12022
|
-
writeFileSync14(filePath, content, "utf-8");
|
|
12023
|
-
try {
|
|
12024
|
-
const client = getClient();
|
|
12025
|
-
await client.execute({
|
|
12026
|
-
sql: `INSERT INTO identity (agent_id, content_hash, updated_at, updated_by)
|
|
12027
|
-
VALUES (?, ?, ?, ?)
|
|
12028
|
-
ON CONFLICT(agent_id) DO UPDATE SET
|
|
12029
|
-
content_hash = excluded.content_hash,
|
|
12030
|
-
updated_at = excluded.updated_at,
|
|
12031
|
-
updated_by = excluded.updated_by`,
|
|
12032
|
-
args: [agentId, hash, (/* @__PURE__ */ new Date()).toISOString(), updatedBy]
|
|
12033
|
-
});
|
|
12034
|
-
} catch {
|
|
12035
|
-
}
|
|
12036
|
-
}
|
|
12037
|
-
function listIdentities() {
|
|
12038
|
-
ensureDir2();
|
|
12039
|
-
const files = readdirSync6(IDENTITY_DIR).filter((f) => f.endsWith(".md"));
|
|
12040
|
-
const results = [];
|
|
12041
|
-
for (const file of files) {
|
|
12042
|
-
const agentId = file.replace(".md", "");
|
|
12043
|
-
const identity = getIdentity(agentId);
|
|
12044
|
-
if (!identity) continue;
|
|
12045
|
-
const lines = identity.body.split("\n").filter((l) => l.trim() && !l.startsWith("#"));
|
|
12046
|
-
const summary = lines[0]?.trim().slice(0, 120) ?? identity.frontmatter.title;
|
|
12047
|
-
results.push({
|
|
12048
|
-
agentId,
|
|
12049
|
-
title: `${identity.frontmatter.title} (${identity.frontmatter.role.toUpperCase()})`,
|
|
12050
|
-
summary
|
|
12051
|
-
});
|
|
12052
|
-
}
|
|
12053
|
-
return results;
|
|
12054
|
-
}
|
|
12055
|
-
function getIdentityInjection(agentId) {
|
|
12056
|
-
const own = getIdentity(agentId);
|
|
12057
|
-
const all = listIdentities();
|
|
12058
|
-
const parts = [];
|
|
12059
|
-
if (own) {
|
|
12060
|
-
parts.push(`## Your Identity (exe.md)
|
|
12061
|
-
These define WHO YOU ARE. Non-negotiable. Permanent.
|
|
12062
|
-
|
|
12063
|
-
${own.body}`);
|
|
12064
|
-
}
|
|
12065
|
-
const teamLines = all.filter((a) => a.agentId !== agentId).map((a) => `- ${a.agentId} (${a.title}): ${a.summary}`);
|
|
12066
|
-
if (teamLines.length > 0) {
|
|
12067
|
-
parts.push(`## Team Identities
|
|
12068
|
-
${teamLines.join("\n")}`);
|
|
12069
|
-
}
|
|
12070
|
-
return parts.join("\n\n");
|
|
12071
|
-
}
|
|
12072
|
-
var IDENTITY_DIR;
|
|
12073
|
-
var init_identity = __esm({
|
|
12074
|
-
"src/lib/identity.ts"() {
|
|
12075
|
-
"use strict";
|
|
12076
|
-
init_config();
|
|
12077
|
-
init_database();
|
|
12078
|
-
IDENTITY_DIR = path27.join(EXE_AI_DIR, "identity");
|
|
12079
|
-
}
|
|
12080
|
-
});
|
|
12081
|
-
|
|
12082
12557
|
// src/lib/identity-templates.ts
|
|
12083
12558
|
var identity_templates_exports = {};
|
|
12084
12559
|
__export(identity_templates_exports, {
|
|
@@ -12626,36 +13101,36 @@ __export(session_wrappers_exports, {
|
|
|
12626
13101
|
generateSessionWrappers: () => generateSessionWrappers
|
|
12627
13102
|
});
|
|
12628
13103
|
import {
|
|
12629
|
-
existsSync as
|
|
12630
|
-
readFileSync as
|
|
12631
|
-
writeFileSync as
|
|
12632
|
-
mkdirSync as
|
|
13104
|
+
existsSync as existsSync24,
|
|
13105
|
+
readFileSync as readFileSync21,
|
|
13106
|
+
writeFileSync as writeFileSync17,
|
|
13107
|
+
mkdirSync as mkdirSync17,
|
|
12633
13108
|
chmodSync,
|
|
12634
13109
|
readdirSync as readdirSync7,
|
|
12635
13110
|
unlinkSync as unlinkSync12
|
|
12636
13111
|
} from "fs";
|
|
12637
|
-
import
|
|
13112
|
+
import path30 from "path";
|
|
12638
13113
|
import { homedir as homedir5 } from "os";
|
|
12639
13114
|
function generateSessionWrappers(packageRoot, homeDir) {
|
|
12640
13115
|
const home = homeDir ?? homedir5();
|
|
12641
|
-
const binDir =
|
|
12642
|
-
const rosterPath =
|
|
12643
|
-
|
|
12644
|
-
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");
|
|
12645
13120
|
const candidates = [
|
|
12646
|
-
|
|
12647
|
-
|
|
13121
|
+
path30.join(packageRoot, "dist", "bin", "exe-start.sh"),
|
|
13122
|
+
path30.join(packageRoot, "src", "bin", "exe-start.sh")
|
|
12648
13123
|
];
|
|
12649
13124
|
for (const src of candidates) {
|
|
12650
|
-
if (
|
|
12651
|
-
|
|
13125
|
+
if (existsSync24(src)) {
|
|
13126
|
+
writeFileSync17(exeStartDst, readFileSync21(src));
|
|
12652
13127
|
chmodSync(exeStartDst, 493);
|
|
12653
13128
|
break;
|
|
12654
13129
|
}
|
|
12655
13130
|
}
|
|
12656
13131
|
let employees = [];
|
|
12657
13132
|
try {
|
|
12658
|
-
employees = JSON.parse(
|
|
13133
|
+
employees = JSON.parse(readFileSync21(rosterPath, "utf8"));
|
|
12659
13134
|
} catch {
|
|
12660
13135
|
return { created: 0, pathConfigured: false };
|
|
12661
13136
|
}
|
|
@@ -12665,9 +13140,9 @@ function generateSessionWrappers(packageRoot, homeDir) {
|
|
|
12665
13140
|
try {
|
|
12666
13141
|
for (const f of readdirSync7(binDir)) {
|
|
12667
13142
|
if (f === "exe-start") continue;
|
|
12668
|
-
const fPath =
|
|
13143
|
+
const fPath = path30.join(binDir, f);
|
|
12669
13144
|
try {
|
|
12670
|
-
const content =
|
|
13145
|
+
const content = readFileSync21(fPath, "utf8");
|
|
12671
13146
|
if (content.includes("exe-start")) {
|
|
12672
13147
|
unlinkSync12(fPath);
|
|
12673
13148
|
}
|
|
@@ -12682,30 +13157,30 @@ exec "${exeStartDst}" "$0" "$@"
|
|
|
12682
13157
|
`;
|
|
12683
13158
|
for (const emp of employees) {
|
|
12684
13159
|
for (let n = 1; n <= MAX_N; n++) {
|
|
12685
|
-
const wrapperPath =
|
|
12686
|
-
|
|
13160
|
+
const wrapperPath = path30.join(binDir, `${emp.name}${n}`);
|
|
13161
|
+
writeFileSync17(wrapperPath, wrapperContent);
|
|
12687
13162
|
chmodSync(wrapperPath, 493);
|
|
12688
13163
|
created++;
|
|
12689
13164
|
}
|
|
12690
13165
|
}
|
|
12691
13166
|
const codexLauncherCandidates = [
|
|
12692
|
-
|
|
12693
|
-
|
|
13167
|
+
path30.join(packageRoot, "dist", "bin", "exe-start-codex.js"),
|
|
13168
|
+
path30.join(packageRoot, "src", "bin", "exe-start-codex.ts")
|
|
12694
13169
|
];
|
|
12695
13170
|
let codexLauncher = null;
|
|
12696
13171
|
for (const c of codexLauncherCandidates) {
|
|
12697
|
-
if (
|
|
13172
|
+
if (existsSync24(c)) {
|
|
12698
13173
|
codexLauncher = c;
|
|
12699
13174
|
break;
|
|
12700
13175
|
}
|
|
12701
13176
|
}
|
|
12702
13177
|
if (codexLauncher) {
|
|
12703
13178
|
for (const emp of employees) {
|
|
12704
|
-
const wrapperPath =
|
|
13179
|
+
const wrapperPath = path30.join(binDir, `${emp.name}-codex`);
|
|
12705
13180
|
const content = `#!/bin/bash
|
|
12706
13181
|
exec node "${codexLauncher}" --agent ${emp.name} "$@"
|
|
12707
13182
|
`;
|
|
12708
|
-
|
|
13183
|
+
writeFileSync17(wrapperPath, content);
|
|
12709
13184
|
chmodSync(wrapperPath, 493);
|
|
12710
13185
|
created++;
|
|
12711
13186
|
}
|
|
@@ -12724,24 +13199,24 @@ export PATH="${binDir}:$PATH"
|
|
|
12724
13199
|
const shell = process.env.SHELL ?? "/bin/bash";
|
|
12725
13200
|
const profilePaths = [];
|
|
12726
13201
|
if (shell.includes("zsh")) {
|
|
12727
|
-
profilePaths.push(
|
|
13202
|
+
profilePaths.push(path30.join(home, ".zshrc"));
|
|
12728
13203
|
} else if (shell.includes("bash")) {
|
|
12729
|
-
profilePaths.push(
|
|
12730
|
-
profilePaths.push(
|
|
13204
|
+
profilePaths.push(path30.join(home, ".bashrc"));
|
|
13205
|
+
profilePaths.push(path30.join(home, ".bash_profile"));
|
|
12731
13206
|
} else {
|
|
12732
|
-
profilePaths.push(
|
|
13207
|
+
profilePaths.push(path30.join(home, ".profile"));
|
|
12733
13208
|
}
|
|
12734
13209
|
for (const profilePath of profilePaths) {
|
|
12735
13210
|
try {
|
|
12736
13211
|
let content = "";
|
|
12737
13212
|
try {
|
|
12738
|
-
content =
|
|
13213
|
+
content = readFileSync21(profilePath, "utf8");
|
|
12739
13214
|
} catch {
|
|
12740
13215
|
}
|
|
12741
13216
|
if (content.includes(".exe-os/bin")) {
|
|
12742
13217
|
return false;
|
|
12743
13218
|
}
|
|
12744
|
-
|
|
13219
|
+
writeFileSync17(profilePath, content + exportLine);
|
|
12745
13220
|
return true;
|
|
12746
13221
|
} catch {
|
|
12747
13222
|
continue;
|
|
@@ -12764,36 +13239,36 @@ __export(setup_wizard_exports, {
|
|
|
12764
13239
|
validateModel: () => validateModel
|
|
12765
13240
|
});
|
|
12766
13241
|
import crypto11 from "crypto";
|
|
12767
|
-
import { existsSync as
|
|
12768
|
-
import
|
|
12769
|
-
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";
|
|
12770
13245
|
import { createInterface as createInterface3 } from "readline";
|
|
12771
13246
|
function findPackageRoot2() {
|
|
12772
|
-
let dir =
|
|
12773
|
-
const root =
|
|
13247
|
+
let dir = path31.dirname(new URL(import.meta.url).pathname);
|
|
13248
|
+
const root = path31.parse(dir).root;
|
|
12774
13249
|
while (dir !== root) {
|
|
12775
|
-
const pkgPath =
|
|
12776
|
-
if (
|
|
13250
|
+
const pkgPath = path31.join(dir, "package.json");
|
|
13251
|
+
if (existsSync25(pkgPath)) {
|
|
12777
13252
|
try {
|
|
12778
|
-
const pkg = JSON.parse(
|
|
13253
|
+
const pkg = JSON.parse(readFileSync22(pkgPath, "utf-8"));
|
|
12779
13254
|
if (pkg.name === "@askexenow/exe-os" || pkg.name === "exe-os") return dir;
|
|
12780
13255
|
} catch {
|
|
12781
13256
|
}
|
|
12782
13257
|
}
|
|
12783
|
-
dir =
|
|
13258
|
+
dir = path31.dirname(dir);
|
|
12784
13259
|
}
|
|
12785
13260
|
return null;
|
|
12786
13261
|
}
|
|
12787
13262
|
function loadSetupState() {
|
|
12788
13263
|
try {
|
|
12789
|
-
return JSON.parse(
|
|
13264
|
+
return JSON.parse(readFileSync22(SETUP_STATE_PATH, "utf8"));
|
|
12790
13265
|
} catch {
|
|
12791
13266
|
return { completedSteps: [], startedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
12792
13267
|
}
|
|
12793
13268
|
}
|
|
12794
13269
|
function saveSetupState(state) {
|
|
12795
|
-
|
|
12796
|
-
|
|
13270
|
+
mkdirSync18(path31.dirname(SETUP_STATE_PATH), { recursive: true });
|
|
13271
|
+
writeFileSync18(SETUP_STATE_PATH, JSON.stringify(state, null, 2));
|
|
12797
13272
|
}
|
|
12798
13273
|
function clearSetupState() {
|
|
12799
13274
|
try {
|
|
@@ -12812,10 +13287,10 @@ function ask2(rl, prompt) {
|
|
|
12812
13287
|
});
|
|
12813
13288
|
}
|
|
12814
13289
|
function getAvailableMemoryGB() {
|
|
12815
|
-
return
|
|
13290
|
+
return os14.freemem() / (1024 * 1024 * 1024);
|
|
12816
13291
|
}
|
|
12817
13292
|
function getTotalMemoryGB() {
|
|
12818
|
-
return
|
|
13293
|
+
return os14.totalmem() / (1024 * 1024 * 1024);
|
|
12819
13294
|
}
|
|
12820
13295
|
function isLowMemory() {
|
|
12821
13296
|
return getAvailableMemoryGB() < 2;
|
|
@@ -12826,8 +13301,8 @@ async function validateModel(log) {
|
|
|
12826
13301
|
if (totalGB <= 8 || isLowMemory()) {
|
|
12827
13302
|
log(`System memory: ${totalGB.toFixed(0)}GB total, ${freeGB.toFixed(1)}GB free`);
|
|
12828
13303
|
log("Skipping in-memory model validation (low memory \u2014 will validate on first use).");
|
|
12829
|
-
const modelPath =
|
|
12830
|
-
if (
|
|
13304
|
+
const modelPath = path31.join(MODELS_DIR, LOCAL_FILENAME);
|
|
13305
|
+
if (existsSync25(modelPath)) {
|
|
12831
13306
|
const { statSync: statSync2 } = await import("fs");
|
|
12832
13307
|
const size = statSync2(modelPath).size;
|
|
12833
13308
|
if (size > 300 * 1e6) {
|
|
@@ -12918,7 +13393,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
12918
13393
|
if (state.completedSteps.length > 0) {
|
|
12919
13394
|
log(`Resuming setup from step ${Math.max(...state.completedSteps) + 1}...`);
|
|
12920
13395
|
}
|
|
12921
|
-
if (
|
|
13396
|
+
if (existsSync25(LEGACY_LANCE_PATH)) {
|
|
12922
13397
|
log("\u26A0 Found v1.0 LanceDB at ~/.exe-os/local.lance");
|
|
12923
13398
|
log(" v1.1 uses libSQL (SQLite). Your existing memories are not automatically migrated.");
|
|
12924
13399
|
log(" The old directory will not be modified or deleted.");
|
|
@@ -13082,19 +13557,19 @@ async function runSetupWizard(opts = {}) {
|
|
|
13082
13557
|
await saveConfig(config);
|
|
13083
13558
|
log("");
|
|
13084
13559
|
try {
|
|
13085
|
-
const claudeJsonPath =
|
|
13560
|
+
const claudeJsonPath = path31.join(os14.homedir(), ".claude.json");
|
|
13086
13561
|
let claudeJson = {};
|
|
13087
13562
|
try {
|
|
13088
|
-
claudeJson = JSON.parse(
|
|
13563
|
+
claudeJson = JSON.parse(readFileSync22(claudeJsonPath, "utf8"));
|
|
13089
13564
|
} catch {
|
|
13090
13565
|
}
|
|
13091
13566
|
if (!claudeJson.projects) claudeJson.projects = {};
|
|
13092
13567
|
const projects = claudeJson.projects;
|
|
13093
|
-
for (const dir of [process.cwd(),
|
|
13568
|
+
for (const dir of [process.cwd(), os14.homedir()]) {
|
|
13094
13569
|
if (!projects[dir]) projects[dir] = {};
|
|
13095
13570
|
projects[dir].hasTrustDialogAccepted = true;
|
|
13096
13571
|
}
|
|
13097
|
-
|
|
13572
|
+
writeFileSync18(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
|
|
13098
13573
|
} catch {
|
|
13099
13574
|
}
|
|
13100
13575
|
state.completedSteps.push(5);
|
|
@@ -13108,7 +13583,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
13108
13583
|
const prefs = { ...existingPrefs };
|
|
13109
13584
|
log("=== Config Defaults ===");
|
|
13110
13585
|
log("");
|
|
13111
|
-
const ghosttyDetected =
|
|
13586
|
+
const ghosttyDetected = existsSync25(path31.join(os14.homedir(), ".config", "ghostty")) || existsSync25(path31.join(os14.homedir(), "Library", "Application Support", "com.mitchellh.ghostty"));
|
|
13112
13587
|
if (ghosttyDetected) {
|
|
13113
13588
|
const ghosttyAnswer = await ask2(rl, "Detected Ghostty terminal. Use exe-os Ghostty defaults? (Y/n) ");
|
|
13114
13589
|
prefs.ghostty = ghosttyAnswer.toLowerCase() !== "n";
|
|
@@ -13155,7 +13630,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
13155
13630
|
let missingIdentities = [];
|
|
13156
13631
|
for (const emp of roster) {
|
|
13157
13632
|
const idPath = identityPath2(emp.name);
|
|
13158
|
-
if (!
|
|
13633
|
+
if (!existsSync25(idPath)) {
|
|
13159
13634
|
missingIdentities.push(emp.name);
|
|
13160
13635
|
}
|
|
13161
13636
|
}
|
|
@@ -13187,7 +13662,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
13187
13662
|
}
|
|
13188
13663
|
missingIdentities = [];
|
|
13189
13664
|
for (const emp of roster) {
|
|
13190
|
-
if (!
|
|
13665
|
+
if (!existsSync25(identityPath2(emp.name))) {
|
|
13191
13666
|
missingIdentities.push(emp.name);
|
|
13192
13667
|
}
|
|
13193
13668
|
}
|
|
@@ -13252,9 +13727,9 @@ async function runSetupWizard(opts = {}) {
|
|
|
13252
13727
|
const cooIdentityContent = getIdentityTemplate("coo");
|
|
13253
13728
|
if (cooIdentityContent) {
|
|
13254
13729
|
const cooIdPath = identityPath2(cooName);
|
|
13255
|
-
|
|
13730
|
+
mkdirSync18(path31.dirname(cooIdPath), { recursive: true });
|
|
13256
13731
|
const replaced = cooIdentityContent.replace(/agent_id:\s*exe/g, `agent_id: ${cooName}`).replace(/\$\{agent_id\}/g, cooName);
|
|
13257
|
-
|
|
13732
|
+
writeFileSync18(cooIdPath, replaced, "utf-8");
|
|
13258
13733
|
}
|
|
13259
13734
|
registerBinSymlinks2(cooName);
|
|
13260
13735
|
createdEmployees.push({ name: cooName, role: "COO" });
|
|
@@ -13348,9 +13823,9 @@ async function runSetupWizard(opts = {}) {
|
|
|
13348
13823
|
const ctoIdentityContent = getIdentityTemplate("cto");
|
|
13349
13824
|
if (ctoIdentityContent) {
|
|
13350
13825
|
const ctoIdPath = identityPath2(ctoName);
|
|
13351
|
-
|
|
13826
|
+
mkdirSync18(path31.dirname(ctoIdPath), { recursive: true });
|
|
13352
13827
|
const replaced = ctoIdentityContent.replace(/agent_id:\s*\w+/g, `agent_id: ${ctoName}`).replace(/\$\{agent_id\}/g, ctoName);
|
|
13353
|
-
|
|
13828
|
+
writeFileSync18(ctoIdPath, replaced, "utf-8");
|
|
13354
13829
|
}
|
|
13355
13830
|
registerBinSymlinks2(ctoName);
|
|
13356
13831
|
createdEmployees.push({ name: ctoName, role: "CTO" });
|
|
@@ -13371,9 +13846,9 @@ async function runSetupWizard(opts = {}) {
|
|
|
13371
13846
|
const cmoIdentityContent = getIdentityTemplate("cmo");
|
|
13372
13847
|
if (cmoIdentityContent) {
|
|
13373
13848
|
const cmoIdPath = identityPath2(cmoName);
|
|
13374
|
-
|
|
13849
|
+
mkdirSync18(path31.dirname(cmoIdPath), { recursive: true });
|
|
13375
13850
|
const replaced = cmoIdentityContent.replace(/agent_id:\s*\w+/g, `agent_id: ${cmoName}`).replace(/\$\{agent_id\}/g, cmoName);
|
|
13376
|
-
|
|
13851
|
+
writeFileSync18(cmoIdPath, replaced, "utf-8");
|
|
13377
13852
|
}
|
|
13378
13853
|
registerBinSymlinks2(cmoName);
|
|
13379
13854
|
createdEmployees.push({ name: cmoName, role: "CMO" });
|
|
@@ -13395,7 +13870,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
13395
13870
|
log(`Session shortcuts generated (${cooName}1, ${cooName}2, ...)`);
|
|
13396
13871
|
}
|
|
13397
13872
|
if (wrapResult.pathConfigured) {
|
|
13398
|
-
const binDir =
|
|
13873
|
+
const binDir = path31.join(os14.homedir(), ".exe-os", "bin");
|
|
13399
13874
|
process.env.PATH = `${binDir}:${process.env.PATH ?? ""}`;
|
|
13400
13875
|
pathJustConfigured = true;
|
|
13401
13876
|
}
|
|
@@ -13438,7 +13913,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
13438
13913
|
const pkgRoot2 = findPackageRoot2();
|
|
13439
13914
|
if (pkgRoot2) {
|
|
13440
13915
|
try {
|
|
13441
|
-
version = JSON.parse(
|
|
13916
|
+
version = JSON.parse(readFileSync22(path31.join(pkgRoot2, "package.json"), "utf-8")).version;
|
|
13442
13917
|
} catch {
|
|
13443
13918
|
}
|
|
13444
13919
|
}
|
|
@@ -13472,17 +13947,17 @@ var init_setup_wizard = __esm({
|
|
|
13472
13947
|
init_config();
|
|
13473
13948
|
init_keychain();
|
|
13474
13949
|
init_model_downloader();
|
|
13475
|
-
SETUP_STATE_PATH =
|
|
13950
|
+
SETUP_STATE_PATH = path31.join(os14.homedir(), ".exe-os", "setup-state.json");
|
|
13476
13951
|
}
|
|
13477
13952
|
});
|
|
13478
13953
|
|
|
13479
13954
|
// src/lib/update-check.ts
|
|
13480
13955
|
import { execSync as execSync11 } from "child_process";
|
|
13481
|
-
import { readFileSync as
|
|
13482
|
-
import
|
|
13956
|
+
import { readFileSync as readFileSync23 } from "fs";
|
|
13957
|
+
import path32 from "path";
|
|
13483
13958
|
function getLocalVersion(packageRoot) {
|
|
13484
|
-
const pkgPath =
|
|
13485
|
-
const pkg = JSON.parse(
|
|
13959
|
+
const pkgPath = path32.join(packageRoot, "package.json");
|
|
13960
|
+
const pkg = JSON.parse(readFileSync23(pkgPath, "utf-8"));
|
|
13486
13961
|
return pkg.version;
|
|
13487
13962
|
}
|
|
13488
13963
|
function getRemoteVersion() {
|
|
@@ -18006,8 +18481,8 @@ var init_ErrorOverview = __esm({
|
|
|
18006
18481
|
"use strict";
|
|
18007
18482
|
init_Box();
|
|
18008
18483
|
init_Text();
|
|
18009
|
-
cleanupPath = (
|
|
18010
|
-
return
|
|
18484
|
+
cleanupPath = (path44) => {
|
|
18485
|
+
return path44?.replace(`file://${cwd()}/`, "");
|
|
18011
18486
|
};
|
|
18012
18487
|
stackUtils = new StackUtils({
|
|
18013
18488
|
cwd: cwd(),
|
|
@@ -20415,11 +20890,11 @@ function Footer() {
|
|
|
20415
20890
|
} catch {
|
|
20416
20891
|
}
|
|
20417
20892
|
try {
|
|
20418
|
-
const { existsSync:
|
|
20893
|
+
const { existsSync: existsSync30 } = await import("fs");
|
|
20419
20894
|
const { join } = await import("path");
|
|
20420
20895
|
const home = process.env.HOME ?? "";
|
|
20421
20896
|
const pidPath = join(home, ".exe-os", "exed.pid");
|
|
20422
|
-
setDaemon(
|
|
20897
|
+
setDaemon(existsSync30(pidPath) ? "running" : "stopped");
|
|
20423
20898
|
} catch {
|
|
20424
20899
|
setDaemon("unknown");
|
|
20425
20900
|
}
|
|
@@ -22152,7 +22627,7 @@ var init_anthropic = __esm({
|
|
|
22152
22627
|
|
|
22153
22628
|
// src/gateway/providers/openai-compat.ts
|
|
22154
22629
|
import OpenAI from "openai";
|
|
22155
|
-
import { randomUUID as
|
|
22630
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
22156
22631
|
var OpenAICompatProvider;
|
|
22157
22632
|
var init_openai_compat = __esm({
|
|
22158
22633
|
"src/gateway/providers/openai-compat.ts"() {
|
|
@@ -22269,7 +22744,7 @@ var init_openai_compat = __esm({
|
|
|
22269
22744
|
}
|
|
22270
22745
|
content.push({
|
|
22271
22746
|
type: "tool_use",
|
|
22272
|
-
id: call.id ??
|
|
22747
|
+
id: call.id ?? randomUUID5(),
|
|
22273
22748
|
name: fn.name,
|
|
22274
22749
|
input
|
|
22275
22750
|
});
|
|
@@ -22461,10 +22936,10 @@ var init_hooks = __esm({
|
|
|
22461
22936
|
});
|
|
22462
22937
|
|
|
22463
22938
|
// src/runtime/safety-checks.ts
|
|
22464
|
-
import
|
|
22465
|
-
import
|
|
22939
|
+
import path33 from "path";
|
|
22940
|
+
import os15 from "os";
|
|
22466
22941
|
function checkPathSafety(filePath) {
|
|
22467
|
-
const resolved =
|
|
22942
|
+
const resolved = path33.resolve(filePath);
|
|
22468
22943
|
for (const { pattern, reason } of BYPASS_IMMUNE_PATTERNS) {
|
|
22469
22944
|
const matches = typeof pattern === "function" ? pattern(resolved) : pattern.test(resolved);
|
|
22470
22945
|
if (matches) {
|
|
@@ -22474,7 +22949,7 @@ function checkPathSafety(filePath) {
|
|
|
22474
22949
|
return { safe: true, bypassImmune: true };
|
|
22475
22950
|
}
|
|
22476
22951
|
function checkReadPathSafety(filePath) {
|
|
22477
|
-
const resolved =
|
|
22952
|
+
const resolved = path33.resolve(filePath);
|
|
22478
22953
|
const credPatterns = BYPASS_IMMUNE_PATTERNS.filter(
|
|
22479
22954
|
(p) => typeof p.pattern !== "function" && (p.reason.includes("secrets") || p.reason.includes("Private key") || p.reason.includes("Credential"))
|
|
22480
22955
|
);
|
|
@@ -22489,7 +22964,7 @@ var HOME, BYPASS_IMMUNE_PATTERNS;
|
|
|
22489
22964
|
var init_safety_checks = __esm({
|
|
22490
22965
|
"src/runtime/safety-checks.ts"() {
|
|
22491
22966
|
"use strict";
|
|
22492
|
-
HOME =
|
|
22967
|
+
HOME = os15.homedir();
|
|
22493
22968
|
BYPASS_IMMUNE_PATTERNS = [
|
|
22494
22969
|
{
|
|
22495
22970
|
pattern: /\/\.git\/hooks\//,
|
|
@@ -22500,11 +22975,11 @@ var init_safety_checks = __esm({
|
|
|
22500
22975
|
reason: "Git config can set hooks and command execution"
|
|
22501
22976
|
},
|
|
22502
22977
|
{
|
|
22503
|
-
pattern: (p) => p.startsWith(
|
|
22978
|
+
pattern: (p) => p.startsWith(path33.join(HOME, ".claude")),
|
|
22504
22979
|
reason: "Claude configuration files are protected"
|
|
22505
22980
|
},
|
|
22506
22981
|
{
|
|
22507
|
-
pattern: (p) => p.startsWith(
|
|
22982
|
+
pattern: (p) => p.startsWith(path33.join(HOME, ".exe-os")),
|
|
22508
22983
|
reason: "exe-os configuration files are protected"
|
|
22509
22984
|
},
|
|
22510
22985
|
{
|
|
@@ -22521,7 +22996,7 @@ var init_safety_checks = __esm({
|
|
|
22521
22996
|
},
|
|
22522
22997
|
{
|
|
22523
22998
|
pattern: (p) => {
|
|
22524
|
-
const name =
|
|
22999
|
+
const name = path33.basename(p);
|
|
22525
23000
|
return [".bashrc", ".zshrc", ".profile", ".bash_profile", ".zprofile", ".zshenv"].includes(name);
|
|
22526
23001
|
},
|
|
22527
23002
|
reason: "Shell configuration files can execute arbitrary code on login"
|
|
@@ -22548,7 +23023,7 @@ __export(file_read_exports, {
|
|
|
22548
23023
|
FileReadTool: () => FileReadTool
|
|
22549
23024
|
});
|
|
22550
23025
|
import fs3 from "fs/promises";
|
|
22551
|
-
import
|
|
23026
|
+
import path34 from "path";
|
|
22552
23027
|
import { z } from "zod";
|
|
22553
23028
|
function isBinary(buf) {
|
|
22554
23029
|
for (let i = 0; i < buf.length; i++) {
|
|
@@ -22584,7 +23059,7 @@ var init_file_read = __esm({
|
|
|
22584
23059
|
return { behavior: "allow" };
|
|
22585
23060
|
},
|
|
22586
23061
|
async call(input, context) {
|
|
22587
|
-
const filePath =
|
|
23062
|
+
const filePath = path34.isAbsolute(input.file_path) ? input.file_path : path34.resolve(context.cwd, input.file_path);
|
|
22588
23063
|
let stat2;
|
|
22589
23064
|
try {
|
|
22590
23065
|
stat2 = await fs3.stat(filePath);
|
|
@@ -22624,7 +23099,7 @@ __export(glob_exports, {
|
|
|
22624
23099
|
GlobTool: () => GlobTool
|
|
22625
23100
|
});
|
|
22626
23101
|
import fs4 from "fs/promises";
|
|
22627
|
-
import
|
|
23102
|
+
import path35 from "path";
|
|
22628
23103
|
import { z as z2 } from "zod";
|
|
22629
23104
|
async function walkDir(dir, maxDepth = 10) {
|
|
22630
23105
|
const results = [];
|
|
@@ -22640,7 +23115,7 @@ async function walkDir(dir, maxDepth = 10) {
|
|
|
22640
23115
|
if (entry.isDirectory() && (entry.name === "node_modules" || entry.name === ".git")) {
|
|
22641
23116
|
continue;
|
|
22642
23117
|
}
|
|
22643
|
-
const fullPath =
|
|
23118
|
+
const fullPath = path35.join(current, entry.name);
|
|
22644
23119
|
if (entry.isDirectory()) {
|
|
22645
23120
|
await walk(fullPath, depth + 1);
|
|
22646
23121
|
} else {
|
|
@@ -22674,11 +23149,11 @@ var init_glob = __esm({
|
|
|
22674
23149
|
inputSchema: inputSchema2,
|
|
22675
23150
|
isReadOnly: true,
|
|
22676
23151
|
async call(input, context) {
|
|
22677
|
-
const baseDir = input.path ?
|
|
23152
|
+
const baseDir = input.path ? path35.isAbsolute(input.path) ? input.path : path35.resolve(context.cwd, input.path) : context.cwd;
|
|
22678
23153
|
try {
|
|
22679
23154
|
const entries = await walkDir(baseDir);
|
|
22680
23155
|
const matched = entries.filter(
|
|
22681
|
-
(e) => simpleGlobMatch(
|
|
23156
|
+
(e) => simpleGlobMatch(path35.relative(baseDir, e.path), input.pattern)
|
|
22682
23157
|
);
|
|
22683
23158
|
matched.sort((a, b) => b.mtime - a.mtime);
|
|
22684
23159
|
if (matched.length === 0) {
|
|
@@ -22704,7 +23179,7 @@ __export(grep_exports, {
|
|
|
22704
23179
|
});
|
|
22705
23180
|
import { spawn as spawn2 } from "child_process";
|
|
22706
23181
|
import fs5 from "fs/promises";
|
|
22707
|
-
import
|
|
23182
|
+
import path36 from "path";
|
|
22708
23183
|
import { z as z3 } from "zod";
|
|
22709
23184
|
function runRipgrep(input, searchPath, context) {
|
|
22710
23185
|
return new Promise((resolve, reject) => {
|
|
@@ -22758,7 +23233,7 @@ async function nodeGrep(input, searchPath) {
|
|
|
22758
23233
|
}
|
|
22759
23234
|
for (const entry of entries) {
|
|
22760
23235
|
if (entry.name === "node_modules" || entry.name === ".git") continue;
|
|
22761
|
-
const fullPath =
|
|
23236
|
+
const fullPath = path36.join(dir, entry.name);
|
|
22762
23237
|
if (entry.isDirectory()) {
|
|
22763
23238
|
await walk(fullPath);
|
|
22764
23239
|
} else {
|
|
@@ -22804,7 +23279,7 @@ var init_grep = __esm({
|
|
|
22804
23279
|
inputSchema: inputSchema3,
|
|
22805
23280
|
isReadOnly: true,
|
|
22806
23281
|
async call(input, context) {
|
|
22807
|
-
const searchPath = input.path ?
|
|
23282
|
+
const searchPath = input.path ? path36.isAbsolute(input.path) ? input.path : path36.resolve(context.cwd, input.path) : context.cwd;
|
|
22808
23283
|
try {
|
|
22809
23284
|
const result = await runRipgrep(input, searchPath, context);
|
|
22810
23285
|
return result;
|
|
@@ -22829,7 +23304,7 @@ __export(file_write_exports, {
|
|
|
22829
23304
|
FileWriteTool: () => FileWriteTool
|
|
22830
23305
|
});
|
|
22831
23306
|
import fs6 from "fs/promises";
|
|
22832
|
-
import
|
|
23307
|
+
import path37 from "path";
|
|
22833
23308
|
import { z as z4 } from "zod";
|
|
22834
23309
|
var inputSchema4, FileWriteTool;
|
|
22835
23310
|
var init_file_write = __esm({
|
|
@@ -22857,8 +23332,8 @@ var init_file_write = __esm({
|
|
|
22857
23332
|
return { behavior: "allow" };
|
|
22858
23333
|
},
|
|
22859
23334
|
async call(input, context) {
|
|
22860
|
-
const filePath =
|
|
22861
|
-
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);
|
|
22862
23337
|
await fs6.mkdir(dir, { recursive: true });
|
|
22863
23338
|
await fs6.writeFile(filePath, input.content, "utf-8");
|
|
22864
23339
|
return {
|
|
@@ -22876,7 +23351,7 @@ __export(file_edit_exports, {
|
|
|
22876
23351
|
FileEditTool: () => FileEditTool
|
|
22877
23352
|
});
|
|
22878
23353
|
import fs7 from "fs/promises";
|
|
22879
|
-
import
|
|
23354
|
+
import path38 from "path";
|
|
22880
23355
|
import { z as z5 } from "zod";
|
|
22881
23356
|
function countOccurrences(haystack, needle) {
|
|
22882
23357
|
let count = 0;
|
|
@@ -22917,7 +23392,7 @@ var init_file_edit = __esm({
|
|
|
22917
23392
|
return { behavior: "allow" };
|
|
22918
23393
|
},
|
|
22919
23394
|
async call(input, context) {
|
|
22920
|
-
const filePath =
|
|
23395
|
+
const filePath = path38.isAbsolute(input.file_path) ? input.file_path : path38.resolve(context.cwd, input.file_path);
|
|
22921
23396
|
let content;
|
|
22922
23397
|
try {
|
|
22923
23398
|
content = await fs7.readFile(filePath, "utf-8");
|
|
@@ -23159,7 +23634,7 @@ var init_bash = __esm({
|
|
|
23159
23634
|
// src/tui/views/CommandCenter.tsx
|
|
23160
23635
|
import { useState as useState6, useEffect as useEffect8, useMemo as useMemo4, useCallback as useCallback4, useRef as useRef4 } from "react";
|
|
23161
23636
|
import TextInput from "ink-text-input";
|
|
23162
|
-
import
|
|
23637
|
+
import path39 from "path";
|
|
23163
23638
|
import { homedir as homedir6 } from "os";
|
|
23164
23639
|
import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
23165
23640
|
function CommandCenterView({
|
|
@@ -23194,15 +23669,15 @@ function CommandCenterView({
|
|
|
23194
23669
|
const { createPermissionsFromPreset: createPermissionsFromPreset2, EMPLOYEE_PERMISSIONS: EMPLOYEE_PERMISSIONS2 } = await Promise.resolve().then(() => (init_permissions(), permissions_exports));
|
|
23195
23670
|
const { getPresetByRole: getPresetByRole2 } = await Promise.resolve().then(() => (init_permission_presets(), permission_presets_exports));
|
|
23196
23671
|
const { createDefaultHooks: createDefaultHooks2 } = await Promise.resolve().then(() => (init_hooks(), hooks_exports));
|
|
23197
|
-
const { readFileSync:
|
|
23672
|
+
const { readFileSync: readFileSync27, existsSync: existsSync30 } = await import("fs");
|
|
23198
23673
|
const { join } = await import("path");
|
|
23199
23674
|
const { homedir: homedir8 } = await import("os");
|
|
23200
23675
|
const configPath = join(homedir8(), ".exe-os", "config.json");
|
|
23201
23676
|
let failoverChain = ["anthropic", "opencode", "gemini", "openai"];
|
|
23202
23677
|
let providerConfigs = {};
|
|
23203
|
-
if (
|
|
23678
|
+
if (existsSync30(configPath)) {
|
|
23204
23679
|
try {
|
|
23205
|
-
const raw = JSON.parse(
|
|
23680
|
+
const raw = JSON.parse(readFileSync27(configPath, "utf8"));
|
|
23206
23681
|
if (Array.isArray(raw.failoverChain)) failoverChain = raw.failoverChain;
|
|
23207
23682
|
if (raw.providers && typeof raw.providers === "object") {
|
|
23208
23683
|
providerConfigs = raw.providers;
|
|
@@ -23263,7 +23738,7 @@ function CommandCenterView({
|
|
|
23263
23738
|
const markerDir = join(homedir8(), ".exe-os", "session-cache");
|
|
23264
23739
|
const agentFiles = (await import("fs")).readdirSync(markerDir).filter((f) => f.startsWith("active-agent-"));
|
|
23265
23740
|
for (const f of agentFiles) {
|
|
23266
|
-
const data = JSON.parse(
|
|
23741
|
+
const data = JSON.parse(readFileSync27(join(markerDir, f), "utf8"));
|
|
23267
23742
|
if (data.agentRole) {
|
|
23268
23743
|
agentRole = data.agentRole;
|
|
23269
23744
|
break;
|
|
@@ -23408,7 +23883,7 @@ function CommandCenterView({
|
|
|
23408
23883
|
const demoEntries = DEMO_PROJECTS.map((p) => ({
|
|
23409
23884
|
projectName: p.projectName,
|
|
23410
23885
|
exeSession: p.exeSession,
|
|
23411
|
-
projectDir:
|
|
23886
|
+
projectDir: path39.join(homedir6(), p.projectName),
|
|
23412
23887
|
employeeCount: p.employees.length,
|
|
23413
23888
|
activeCount: p.employees.filter((e) => e.status === "active").length,
|
|
23414
23889
|
memoryCount: p.employees.length * 4e3,
|
|
@@ -23446,7 +23921,7 @@ function CommandCenterView({
|
|
|
23446
23921
|
const { listSessions: listSessions2 } = await Promise.resolve().then(() => (init_session_registry(), session_registry_exports));
|
|
23447
23922
|
const { listTmuxSessions: listTmuxSessions2, inTmux: inTmux2 } = await Promise.resolve().then(() => (init_tmux_status(), tmux_status_exports));
|
|
23448
23923
|
const { loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
23449
|
-
const { existsSync:
|
|
23924
|
+
const { existsSync: existsSync30 } = await import("fs");
|
|
23450
23925
|
const { join } = await import("path");
|
|
23451
23926
|
const client = getClient2();
|
|
23452
23927
|
if (!client) {
|
|
@@ -23517,7 +23992,7 @@ function CommandCenterView({
|
|
|
23517
23992
|
}
|
|
23518
23993
|
const memoryCount = memoryCounts.get(name) ?? 0;
|
|
23519
23994
|
const openTaskCount = openTaskCounts.get(name) ?? 0;
|
|
23520
|
-
const hasGit = projectDir ?
|
|
23995
|
+
const hasGit = projectDir ? existsSync30(join(projectDir, ".git")) : false;
|
|
23521
23996
|
const type = hasGit ? "code" : memoryCount > 0 ? "code" : "automation";
|
|
23522
23997
|
projectList.push({
|
|
23523
23998
|
projectName: name,
|
|
@@ -23542,7 +24017,7 @@ function CommandCenterView({
|
|
|
23542
24017
|
setHealth((h) => ({ ...h, memories: Number(totalResult.rows[0]?.cnt ?? 0) }));
|
|
23543
24018
|
try {
|
|
23544
24019
|
const pidPath = join(process.env.HOME ?? "", ".exe-os", "exed.pid");
|
|
23545
|
-
setHealth((h) => ({ ...h, daemon:
|
|
24020
|
+
setHealth((h) => ({ ...h, daemon: existsSync30(pidPath) ? "running" : "stopped" }));
|
|
23546
24021
|
} catch {
|
|
23547
24022
|
}
|
|
23548
24023
|
const activityResult = await client.execute(
|
|
@@ -23889,7 +24364,7 @@ var init_TmuxPane = __esm({
|
|
|
23889
24364
|
});
|
|
23890
24365
|
|
|
23891
24366
|
// src/lib/task-router.ts
|
|
23892
|
-
import { randomUUID as
|
|
24367
|
+
import { randomUUID as randomUUID6 } from "crypto";
|
|
23893
24368
|
function resolveBloomRouting(complexity, config = DEFAULT_BLOOM_CONFIG) {
|
|
23894
24369
|
const tier = config.complexityToTier[complexity];
|
|
23895
24370
|
const rule = config.tierRules[tier];
|
|
@@ -24412,7 +24887,7 @@ var init_useOrchestrator = __esm({
|
|
|
24412
24887
|
|
|
24413
24888
|
// src/tui/views/Sessions.tsx
|
|
24414
24889
|
import React19, { useState as useState9, useEffect as useEffect11, useCallback as useCallback6 } from "react";
|
|
24415
|
-
import
|
|
24890
|
+
import path40 from "path";
|
|
24416
24891
|
import { homedir as homedir7 } from "os";
|
|
24417
24892
|
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
24418
24893
|
function isCoordinatorEntry(entry) {
|
|
@@ -24450,7 +24925,7 @@ function SessionsView({
|
|
|
24450
24925
|
if (demo) {
|
|
24451
24926
|
setProjects(DEMO_PROJECTS.map((p) => ({
|
|
24452
24927
|
...p,
|
|
24453
|
-
projectDir:
|
|
24928
|
+
projectDir: path40.join(homedir7(), p.projectName),
|
|
24454
24929
|
employees: p.employees.map((e) => ({ ...e, attached: e.status === "active" }))
|
|
24455
24930
|
})));
|
|
24456
24931
|
return;
|
|
@@ -25554,12 +26029,12 @@ async function loadGatewayConfig() {
|
|
|
25554
26029
|
state.running = false;
|
|
25555
26030
|
}
|
|
25556
26031
|
try {
|
|
25557
|
-
const { existsSync:
|
|
26032
|
+
const { existsSync: existsSync30, readFileSync: readFileSync27 } = await import("fs");
|
|
25558
26033
|
const { join } = await import("path");
|
|
25559
26034
|
const home = process.env.HOME ?? "";
|
|
25560
26035
|
const configPath = join(home, ".exe-os", "gateway.json");
|
|
25561
|
-
if (
|
|
25562
|
-
const raw = JSON.parse(
|
|
26036
|
+
if (existsSync30(configPath)) {
|
|
26037
|
+
const raw = JSON.parse(readFileSync27(configPath, "utf8"));
|
|
25563
26038
|
state.port = raw.port ?? 3100;
|
|
25564
26039
|
state.gatewayUrl = raw.gatewayUrl ?? "";
|
|
25565
26040
|
if (raw.adapters) {
|
|
@@ -26182,12 +26657,12 @@ function TeamView({ onBack, onViewSessions }) {
|
|
|
26182
26657
|
setMembers(teamData);
|
|
26183
26658
|
setDbError(null);
|
|
26184
26659
|
try {
|
|
26185
|
-
const { existsSync:
|
|
26660
|
+
const { existsSync: existsSync30, readFileSync: readFileSync27 } = await import("fs");
|
|
26186
26661
|
const { join } = await import("path");
|
|
26187
26662
|
const home = process.env.HOME ?? "";
|
|
26188
26663
|
const gatewayConfig = join(home, ".exe-os", "gateway.json");
|
|
26189
|
-
if (
|
|
26190
|
-
const raw = JSON.parse(
|
|
26664
|
+
if (existsSync30(gatewayConfig)) {
|
|
26665
|
+
const raw = JSON.parse(readFileSync27(gatewayConfig, "utf8"));
|
|
26191
26666
|
if (raw.agents && raw.agents.length > 0) {
|
|
26192
26667
|
setExternals(raw.agents.map((a) => ({
|
|
26193
26668
|
name: a.name,
|
|
@@ -26368,8 +26843,8 @@ __export(wiki_client_exports, {
|
|
|
26368
26843
|
listDocuments: () => listDocuments,
|
|
26369
26844
|
listWorkspaces: () => listWorkspaces
|
|
26370
26845
|
});
|
|
26371
|
-
async function wikiFetch(config,
|
|
26372
|
-
const url = `${config.baseUrl}/api/v1${
|
|
26846
|
+
async function wikiFetch(config, path44, method = "GET", body) {
|
|
26847
|
+
const url = `${config.baseUrl}/api/v1${path44}`;
|
|
26373
26848
|
const headers = {
|
|
26374
26849
|
Authorization: `Bearer ${config.apiKey}`,
|
|
26375
26850
|
"Content-Type": "application/json"
|
|
@@ -26402,7 +26877,7 @@ async function wikiFetch(config, path42, method = "GET", body) {
|
|
|
26402
26877
|
}
|
|
26403
26878
|
}
|
|
26404
26879
|
if (!response.ok) {
|
|
26405
|
-
throw new Error(`Wiki API ${method} ${
|
|
26880
|
+
throw new Error(`Wiki API ${method} ${path44}: ${response.status} ${response.statusText}`);
|
|
26406
26881
|
}
|
|
26407
26882
|
return response.json();
|
|
26408
26883
|
} finally {
|
|
@@ -27012,12 +27487,12 @@ function SettingsView({ onBack }) {
|
|
|
27012
27487
|
}
|
|
27013
27488
|
setProviders(providerList);
|
|
27014
27489
|
try {
|
|
27015
|
-
const { existsSync:
|
|
27490
|
+
const { existsSync: existsSync30 } = await import("fs");
|
|
27016
27491
|
const { join } = await import("path");
|
|
27017
27492
|
const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
27018
27493
|
const cfg = await loadConfig2();
|
|
27019
27494
|
const home = process.env.HOME ?? "";
|
|
27020
|
-
const hasKey =
|
|
27495
|
+
const hasKey = existsSync30(join(home, ".exe-os", "master.key"));
|
|
27021
27496
|
if (cfg.cloud) {
|
|
27022
27497
|
setCloud({
|
|
27023
27498
|
configured: true,
|
|
@@ -27030,22 +27505,22 @@ function SettingsView({ onBack }) {
|
|
|
27030
27505
|
const pidPath = join(home, ".exe-os", "exed.pid");
|
|
27031
27506
|
let daemon = "unknown";
|
|
27032
27507
|
try {
|
|
27033
|
-
daemon =
|
|
27508
|
+
daemon = existsSync30(pidPath) ? "running" : "stopped";
|
|
27034
27509
|
} catch {
|
|
27035
27510
|
}
|
|
27036
27511
|
let version = "unknown";
|
|
27037
27512
|
try {
|
|
27038
|
-
const { readFileSync:
|
|
27513
|
+
const { readFileSync: readFileSync27 } = await import("fs");
|
|
27039
27514
|
const { createRequire } = await import("module");
|
|
27040
27515
|
const require2 = createRequire(import.meta.url);
|
|
27041
27516
|
const pkgPath = require2.resolve("@askexenow/exe-os/package.json");
|
|
27042
|
-
const pkg = JSON.parse(
|
|
27517
|
+
const pkg = JSON.parse(readFileSync27(pkgPath, "utf8"));
|
|
27043
27518
|
version = pkg.version;
|
|
27044
27519
|
} catch {
|
|
27045
27520
|
try {
|
|
27046
|
-
const { readFileSync:
|
|
27521
|
+
const { readFileSync: readFileSync27 } = await import("fs");
|
|
27047
27522
|
const { join: joinPath } = await import("path");
|
|
27048
|
-
const pkg = JSON.parse(
|
|
27523
|
+
const pkg = JSON.parse(readFileSync27(joinPath(process.cwd(), "package.json"), "utf8"));
|
|
27049
27524
|
version = pkg.version;
|
|
27050
27525
|
} catch {
|
|
27051
27526
|
}
|
|
@@ -27846,15 +28321,15 @@ __export(installer_exports2, {
|
|
|
27846
28321
|
verifyOpenCodeHooks: () => verifyOpenCodeHooks
|
|
27847
28322
|
});
|
|
27848
28323
|
import { readFile as readFile6, writeFile as writeFile7, mkdir as mkdir7 } from "fs/promises";
|
|
27849
|
-
import { existsSync as
|
|
27850
|
-
import
|
|
27851
|
-
import
|
|
27852
|
-
async function registerOpenCodeMcp(packageRoot, homeDir =
|
|
27853
|
-
const configDir =
|
|
27854
|
-
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");
|
|
27855
28330
|
await mkdir7(configDir, { recursive: true });
|
|
27856
28331
|
let config = {};
|
|
27857
|
-
if (
|
|
28332
|
+
if (existsSync27(configPath)) {
|
|
27858
28333
|
try {
|
|
27859
28334
|
config = JSON.parse(await readFile6(configPath, "utf-8"));
|
|
27860
28335
|
} catch {
|
|
@@ -27866,7 +28341,7 @@ async function registerOpenCodeMcp(packageRoot, homeDir = os15.homedir()) {
|
|
|
27866
28341
|
}
|
|
27867
28342
|
const newEntry = {
|
|
27868
28343
|
type: "local",
|
|
27869
|
-
command: ["node",
|
|
28344
|
+
command: ["node", path41.join(packageRoot, "dist", "mcp", "server.js")],
|
|
27870
28345
|
enabled: true
|
|
27871
28346
|
};
|
|
27872
28347
|
const current = config.mcp["exe-os"];
|
|
@@ -27880,15 +28355,15 @@ async function registerOpenCodeMcp(packageRoot, homeDir = os15.homedir()) {
|
|
|
27880
28355
|
await writeFile7(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
27881
28356
|
return true;
|
|
27882
28357
|
}
|
|
27883
|
-
async function installOpenCodePlugin(packageRoot, homeDir =
|
|
27884
|
-
const pluginDir =
|
|
27885
|
-
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");
|
|
27886
28361
|
await mkdir7(pluginDir, { recursive: true });
|
|
27887
28362
|
const pluginContent = PLUGIN_TEMPLATE.replace(
|
|
27888
28363
|
/__PACKAGE_ROOT__/g,
|
|
27889
28364
|
packageRoot.replace(/\\/g, "\\\\")
|
|
27890
28365
|
);
|
|
27891
|
-
if (
|
|
28366
|
+
if (existsSync27(pluginPath)) {
|
|
27892
28367
|
const existing = await readFile6(pluginPath, "utf-8");
|
|
27893
28368
|
if (existing === pluginContent) {
|
|
27894
28369
|
return false;
|
|
@@ -27897,17 +28372,17 @@ async function installOpenCodePlugin(packageRoot, homeDir = os15.homedir()) {
|
|
|
27897
28372
|
await writeFile7(pluginPath, pluginContent);
|
|
27898
28373
|
return true;
|
|
27899
28374
|
}
|
|
27900
|
-
function verifyOpenCodeHooks(homeDir =
|
|
27901
|
-
const configPath =
|
|
27902
|
-
const pluginPath =
|
|
27903
|
-
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;
|
|
27904
28379
|
try {
|
|
27905
|
-
const config = JSON.parse(
|
|
28380
|
+
const config = JSON.parse(readFileSync25(configPath, "utf-8"));
|
|
27906
28381
|
if (!config.mcp?.["exe-os"]?.enabled) return false;
|
|
27907
28382
|
} catch {
|
|
27908
28383
|
return false;
|
|
27909
28384
|
}
|
|
27910
|
-
if (!
|
|
28385
|
+
if (!existsSync27(pluginPath)) return false;
|
|
27911
28386
|
return true;
|
|
27912
28387
|
}
|
|
27913
28388
|
async function runOpenCodeInstaller(homeDir) {
|
|
@@ -27940,19 +28415,19 @@ __export(installer_exports3, {
|
|
|
27940
28415
|
verifyCodexHooks: () => verifyCodexHooks
|
|
27941
28416
|
});
|
|
27942
28417
|
import { readFile as readFile7, writeFile as writeFile8, mkdir as mkdir8 } from "fs/promises";
|
|
27943
|
-
import { existsSync as
|
|
27944
|
-
import
|
|
27945
|
-
import
|
|
27946
|
-
async function mergeCodexHooks(packageRoot, homeDir =
|
|
27947
|
-
const codexDir =
|
|
27948
|
-
const hooksPath =
|
|
27949
|
-
const logsDir =
|
|
27950
|
-
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");
|
|
27951
28426
|
const logSuffix = ` 2>> "${hookLogPath}"`;
|
|
27952
28427
|
await mkdir8(codexDir, { recursive: true });
|
|
27953
28428
|
await mkdir8(logsDir, { recursive: true });
|
|
27954
28429
|
let hooksJson = {};
|
|
27955
|
-
if (
|
|
28430
|
+
if (existsSync28(hooksPath)) {
|
|
27956
28431
|
try {
|
|
27957
28432
|
hooksJson = JSON.parse(await readFile7(hooksPath, "utf-8"));
|
|
27958
28433
|
} catch {
|
|
@@ -27969,7 +28444,7 @@ async function mergeCodexHooks(packageRoot, homeDir = os16.homedir()) {
|
|
|
27969
28444
|
hooks: [
|
|
27970
28445
|
{
|
|
27971
28446
|
type: "command",
|
|
27972
|
-
command: `node "${
|
|
28447
|
+
command: `node "${path42.join(packageRoot, "dist", "hooks", "session-start.js")}"${logSuffix}`,
|
|
27973
28448
|
timeout: 30,
|
|
27974
28449
|
statusMessage: "exe-os: loading memory brief"
|
|
27975
28450
|
}
|
|
@@ -27984,11 +28459,11 @@ async function mergeCodexHooks(packageRoot, homeDir = os16.homedir()) {
|
|
|
27984
28459
|
hooks: [
|
|
27985
28460
|
{
|
|
27986
28461
|
type: "command",
|
|
27987
|
-
command: `node "${
|
|
28462
|
+
command: `node "${path42.join(packageRoot, "dist", "hooks", "ingest.js")}"${logSuffix}`
|
|
27988
28463
|
},
|
|
27989
28464
|
{
|
|
27990
28465
|
type: "command",
|
|
27991
|
-
command: `node "${
|
|
28466
|
+
command: `node "${path42.join(packageRoot, "dist", "hooks", "error-recall.js")}"${logSuffix}`
|
|
27992
28467
|
}
|
|
27993
28468
|
]
|
|
27994
28469
|
},
|
|
@@ -28000,11 +28475,11 @@ async function mergeCodexHooks(packageRoot, homeDir = os16.homedir()) {
|
|
|
28000
28475
|
hooks: [
|
|
28001
28476
|
{
|
|
28002
28477
|
type: "command",
|
|
28003
|
-
command: `node "${
|
|
28478
|
+
command: `node "${path42.join(packageRoot, "dist", "hooks", "prompt-submit.js")}"${logSuffix}`
|
|
28004
28479
|
},
|
|
28005
28480
|
{
|
|
28006
28481
|
type: "command",
|
|
28007
|
-
command: `node "${
|
|
28482
|
+
command: `node "${path42.join(packageRoot, "dist", "hooks", "exe-heartbeat-hook.js")}"${logSuffix}`,
|
|
28008
28483
|
timeout: 5
|
|
28009
28484
|
}
|
|
28010
28485
|
]
|
|
@@ -28017,7 +28492,7 @@ async function mergeCodexHooks(packageRoot, homeDir = os16.homedir()) {
|
|
|
28017
28492
|
hooks: [
|
|
28018
28493
|
{
|
|
28019
28494
|
type: "command",
|
|
28020
|
-
command: `node "${
|
|
28495
|
+
command: `node "${path42.join(packageRoot, "dist", "hooks", "stop.js")}"${logSuffix}`
|
|
28021
28496
|
}
|
|
28022
28497
|
]
|
|
28023
28498
|
},
|
|
@@ -28030,7 +28505,7 @@ async function mergeCodexHooks(packageRoot, homeDir = os16.homedir()) {
|
|
|
28030
28505
|
hooks: [
|
|
28031
28506
|
{
|
|
28032
28507
|
type: "command",
|
|
28033
|
-
command: `node "${
|
|
28508
|
+
command: `node "${path42.join(packageRoot, "dist", "hooks", "pre-tool-use.js")}"${logSuffix}`
|
|
28034
28509
|
}
|
|
28035
28510
|
]
|
|
28036
28511
|
},
|
|
@@ -28061,9 +28536,9 @@ async function mergeCodexHooks(packageRoot, homeDir = os16.homedir()) {
|
|
|
28061
28536
|
await writeFile8(hooksPath, JSON.stringify(hooksJson, null, 2) + "\n");
|
|
28062
28537
|
return { added, skipped };
|
|
28063
28538
|
}
|
|
28064
|
-
function verifyCodexHooks(homeDir =
|
|
28065
|
-
const hooksPath =
|
|
28066
|
-
if (!
|
|
28539
|
+
function verifyCodexHooks(homeDir = os17.homedir()) {
|
|
28540
|
+
const hooksPath = path42.join(homeDir, ".codex", "hooks.json");
|
|
28541
|
+
if (!existsSync28(hooksPath)) return false;
|
|
28067
28542
|
try {
|
|
28068
28543
|
const hooksJson = JSON.parse(
|
|
28069
28544
|
__require("fs").readFileSync(hooksPath, "utf-8")
|
|
@@ -28083,14 +28558,14 @@ function verifyCodexHooks(homeDir = os16.homedir()) {
|
|
|
28083
28558
|
return false;
|
|
28084
28559
|
}
|
|
28085
28560
|
}
|
|
28086
|
-
async function installCodexStatusLine(homeDir =
|
|
28561
|
+
async function installCodexStatusLine(homeDir = os17.homedir()) {
|
|
28087
28562
|
const prefs = loadPreferences(homeDir);
|
|
28088
28563
|
if (prefs.codexStatusLine === false) return "opted-out";
|
|
28089
|
-
const codexDir =
|
|
28090
|
-
const configPath =
|
|
28564
|
+
const codexDir = path42.join(homeDir, ".codex");
|
|
28565
|
+
const configPath = path42.join(codexDir, "config.toml");
|
|
28091
28566
|
await mkdir8(codexDir, { recursive: true });
|
|
28092
28567
|
let content = "";
|
|
28093
|
-
if (
|
|
28568
|
+
if (existsSync28(configPath)) {
|
|
28094
28569
|
content = await readFile7(configPath, "utf-8");
|
|
28095
28570
|
if (/\[tui\][\s\S]*?status_line\s*=/.test(content)) {
|
|
28096
28571
|
return "already-configured";
|
|
@@ -28138,14 +28613,14 @@ var init_installer3 = __esm({
|
|
|
28138
28613
|
});
|
|
28139
28614
|
|
|
28140
28615
|
// src/bin/cli.ts
|
|
28141
|
-
import { existsSync as
|
|
28142
|
-
import
|
|
28143
|
-
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";
|
|
28144
28619
|
var args = process.argv.slice(2);
|
|
28145
28620
|
if (args.includes("--version") || args.includes("-v")) {
|
|
28146
28621
|
try {
|
|
28147
|
-
const pkgPath =
|
|
28148
|
-
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"));
|
|
28149
28624
|
console.log(pkg.version);
|
|
28150
28625
|
} catch {
|
|
28151
28626
|
console.log("unknown");
|
|
@@ -28256,6 +28731,12 @@ if (args.includes("--global")) {
|
|
|
28256
28731
|
console.error("Backfill failed:", err instanceof Error ? err.message : String(err));
|
|
28257
28732
|
process.exit(1);
|
|
28258
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));
|
|
28259
28740
|
} else if (args[0] === "send-message" || args[0] === "send_message") {
|
|
28260
28741
|
const target = args[1];
|
|
28261
28742
|
const msgParts = [];
|
|
@@ -28303,11 +28784,11 @@ ID: ${result.id}`);
|
|
|
28303
28784
|
});
|
|
28304
28785
|
await init_App2().then(() => App_exports);
|
|
28305
28786
|
} else {
|
|
28306
|
-
const claudeDir =
|
|
28307
|
-
const settingsPath =
|
|
28308
|
-
const hasClaudeCode =
|
|
28787
|
+
const claudeDir = path43.join(os18.homedir(), ".claude");
|
|
28788
|
+
const settingsPath = path43.join(claudeDir, "settings.json");
|
|
28789
|
+
const hasClaudeCode = existsSync29(settingsPath) && (() => {
|
|
28309
28790
|
try {
|
|
28310
|
-
const raw =
|
|
28791
|
+
const raw = readFileSync26(settingsPath, "utf8");
|
|
28311
28792
|
return raw.includes("exe-os") || raw.includes("exe-mem");
|
|
28312
28793
|
} catch {
|
|
28313
28794
|
return false;
|
|
@@ -28317,9 +28798,9 @@ ID: ${result.id}`);
|
|
|
28317
28798
|
const { DEFAULT_COORDINATOR_TEMPLATE_NAME: DEFAULT_COORDINATOR_TEMPLATE_NAME2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
28318
28799
|
let cooName = DEFAULT_COORDINATOR_TEMPLATE_NAME2;
|
|
28319
28800
|
try {
|
|
28320
|
-
const rosterPath =
|
|
28321
|
-
if (
|
|
28322
|
-
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"));
|
|
28323
28804
|
const coo = roster.find((e) => e.role === "COO");
|
|
28324
28805
|
if (coo) cooName = coo.name;
|
|
28325
28806
|
}
|
|
@@ -28383,14 +28864,14 @@ async function runCodexInstall() {
|
|
|
28383
28864
|
}
|
|
28384
28865
|
}
|
|
28385
28866
|
async function runClaudeCheck() {
|
|
28386
|
-
const claudeDir =
|
|
28387
|
-
const settingsPath =
|
|
28388
|
-
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");
|
|
28389
28870
|
let ok = true;
|
|
28390
|
-
if (
|
|
28871
|
+
if (existsSync29(settingsPath)) {
|
|
28391
28872
|
let settings;
|
|
28392
28873
|
try {
|
|
28393
|
-
settings = JSON.parse(
|
|
28874
|
+
settings = JSON.parse(readFileSync26(settingsPath, "utf8"));
|
|
28394
28875
|
} catch {
|
|
28395
28876
|
console.log("\x1B[31m\u2717\x1B[0m settings.json is malformed (invalid JSON)");
|
|
28396
28877
|
ok = false;
|
|
@@ -28416,10 +28897,10 @@ async function runClaudeCheck() {
|
|
|
28416
28897
|
console.log("\x1B[31m\u2717\x1B[0m settings.json not found");
|
|
28417
28898
|
ok = false;
|
|
28418
28899
|
}
|
|
28419
|
-
if (
|
|
28900
|
+
if (existsSync29(claudeJsonPath)) {
|
|
28420
28901
|
let claudeJson;
|
|
28421
28902
|
try {
|
|
28422
|
-
claudeJson = JSON.parse(
|
|
28903
|
+
claudeJson = JSON.parse(readFileSync26(claudeJsonPath, "utf8"));
|
|
28423
28904
|
} catch {
|
|
28424
28905
|
console.log("\x1B[31m\u2717\x1B[0m claude.json is malformed (invalid JSON)");
|
|
28425
28906
|
ok = false;
|
|
@@ -28438,8 +28919,8 @@ async function runClaudeCheck() {
|
|
|
28438
28919
|
console.log("\x1B[31m\u2717\x1B[0m claude.json not found");
|
|
28439
28920
|
ok = false;
|
|
28440
28921
|
}
|
|
28441
|
-
const skillsDir =
|
|
28442
|
-
if (
|
|
28922
|
+
const skillsDir = path43.join(claudeDir, "skills");
|
|
28923
|
+
if (existsSync29(skillsDir)) {
|
|
28443
28924
|
console.log("\x1B[32m\u2713\x1B[0m Slash skills directory exists");
|
|
28444
28925
|
} else {
|
|
28445
28926
|
console.log("\x1B[31m\u2717\x1B[0m Slash skills directory missing");
|
|
@@ -28455,17 +28936,17 @@ async function runClaudeCheck() {
|
|
|
28455
28936
|
async function runClaudeUninstall(flags = []) {
|
|
28456
28937
|
const dryRun = flags.includes("--dry-run");
|
|
28457
28938
|
const purge = flags.includes("--purge");
|
|
28458
|
-
const homeDir =
|
|
28459
|
-
const claudeDir =
|
|
28460
|
-
const settingsPath =
|
|
28461
|
-
const claudeJsonPath =
|
|
28462
|
-
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");
|
|
28463
28944
|
let removed = 0;
|
|
28464
28945
|
const log = (msg) => console.log(dryRun ? `[dry-run] ${msg}` : msg);
|
|
28465
28946
|
let settings = {};
|
|
28466
|
-
if (
|
|
28947
|
+
if (existsSync29(settingsPath)) {
|
|
28467
28948
|
try {
|
|
28468
|
-
settings = JSON.parse(
|
|
28949
|
+
settings = JSON.parse(readFileSync26(settingsPath, "utf8"));
|
|
28469
28950
|
} catch {
|
|
28470
28951
|
console.error("Your ~/.claude/settings.json appears malformed.");
|
|
28471
28952
|
if (purge) {
|
|
@@ -28503,15 +28984,15 @@ async function runClaudeUninstall(flags = []) {
|
|
|
28503
28984
|
permCount = before - settings.permissions.allow.length;
|
|
28504
28985
|
}
|
|
28505
28986
|
if (!dryRun) {
|
|
28506
|
-
|
|
28987
|
+
writeFileSync19(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
28507
28988
|
}
|
|
28508
28989
|
log("\u2713 Removed exe-os hooks from settings.json");
|
|
28509
28990
|
if (permCount > 0) log(`\u2713 Removed ${permCount} MCP permission entries`);
|
|
28510
28991
|
removed++;
|
|
28511
28992
|
}
|
|
28512
28993
|
}
|
|
28513
|
-
if (
|
|
28514
|
-
const raw =
|
|
28994
|
+
if (existsSync29(claudeJsonPath)) {
|
|
28995
|
+
const raw = readFileSync26(claudeJsonPath, "utf8");
|
|
28515
28996
|
if (raw.length > 1e6) {
|
|
28516
28997
|
console.error("claude.json exceeds 1 MB \u2014 skipping parse.");
|
|
28517
28998
|
} else {
|
|
@@ -28532,7 +29013,7 @@ async function runClaudeUninstall(flags = []) {
|
|
|
28532
29013
|
}
|
|
28533
29014
|
if (removedMcp) {
|
|
28534
29015
|
if (!dryRun) {
|
|
28535
|
-
|
|
29016
|
+
writeFileSync19(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
|
|
28536
29017
|
}
|
|
28537
29018
|
log("\u2713 Removed exe-os MCP server from claude.json");
|
|
28538
29019
|
removed++;
|
|
@@ -28540,14 +29021,14 @@ async function runClaudeUninstall(flags = []) {
|
|
|
28540
29021
|
}
|
|
28541
29022
|
}
|
|
28542
29023
|
}
|
|
28543
|
-
const skillsDir =
|
|
28544
|
-
if (
|
|
29024
|
+
const skillsDir = path43.join(claudeDir, "skills");
|
|
29025
|
+
if (existsSync29(skillsDir)) {
|
|
28545
29026
|
let skillCount = 0;
|
|
28546
29027
|
try {
|
|
28547
29028
|
const entries = readdirSync8(skillsDir);
|
|
28548
29029
|
for (const entry of entries) {
|
|
28549
29030
|
if (entry.startsWith("exe")) {
|
|
28550
|
-
const fullPath =
|
|
29031
|
+
const fullPath = path43.join(skillsDir, entry);
|
|
28551
29032
|
if (!dryRun) rmSync(fullPath, { recursive: true, force: true });
|
|
28552
29033
|
skillCount++;
|
|
28553
29034
|
}
|
|
@@ -28559,30 +29040,30 @@ async function runClaudeUninstall(flags = []) {
|
|
|
28559
29040
|
removed++;
|
|
28560
29041
|
}
|
|
28561
29042
|
}
|
|
28562
|
-
const claudeMdPath =
|
|
28563
|
-
if (
|
|
28564
|
-
const content =
|
|
29043
|
+
const claudeMdPath = path43.join(claudeDir, "CLAUDE.md");
|
|
29044
|
+
if (existsSync29(claudeMdPath)) {
|
|
29045
|
+
const content = readFileSync26(claudeMdPath, "utf8");
|
|
28565
29046
|
const startMarker = "<!-- exe-os:orchestration-start -->";
|
|
28566
29047
|
const endMarker = "<!-- exe-os:orchestration-end -->";
|
|
28567
29048
|
const startIdx = content.indexOf(startMarker);
|
|
28568
29049
|
const endIdx = content.indexOf(endMarker);
|
|
28569
29050
|
if (startIdx !== -1 && endIdx !== -1) {
|
|
28570
29051
|
const cleaned = (content.slice(0, startIdx) + content.slice(endIdx + endMarker.length)).replace(/\n{3,}/g, "\n\n").trim() + "\n";
|
|
28571
|
-
if (!dryRun)
|
|
29052
|
+
if (!dryRun) writeFileSync19(claudeMdPath, cleaned);
|
|
28572
29053
|
log("\u2713 Removed orchestration block from CLAUDE.md");
|
|
28573
29054
|
removed++;
|
|
28574
29055
|
}
|
|
28575
29056
|
}
|
|
28576
|
-
const agentsDir =
|
|
28577
|
-
if (
|
|
29057
|
+
const agentsDir = path43.join(claudeDir, "agents");
|
|
29058
|
+
if (existsSync29(agentsDir)) {
|
|
28578
29059
|
let agentCount = 0;
|
|
28579
29060
|
try {
|
|
28580
29061
|
const entries = readdirSync8(agentsDir).filter((f) => f.endsWith(".md"));
|
|
28581
29062
|
let knownNames = /* @__PURE__ */ new Set();
|
|
28582
|
-
const rosterPath =
|
|
28583
|
-
if (
|
|
29063
|
+
const rosterPath = path43.join(exeOsDir, "exe-employees.json");
|
|
29064
|
+
if (existsSync29(rosterPath)) {
|
|
28584
29065
|
try {
|
|
28585
|
-
const roster = JSON.parse(
|
|
29066
|
+
const roster = JSON.parse(readFileSync26(rosterPath, "utf8"));
|
|
28586
29067
|
knownNames = new Set(roster.map((e) => e.name));
|
|
28587
29068
|
} catch {
|
|
28588
29069
|
}
|
|
@@ -28590,7 +29071,7 @@ async function runClaudeUninstall(flags = []) {
|
|
|
28590
29071
|
for (const entry of entries) {
|
|
28591
29072
|
const name = entry.replace(/\.md$/, "");
|
|
28592
29073
|
if (knownNames.has(name)) {
|
|
28593
|
-
if (!dryRun) rmSync(
|
|
29074
|
+
if (!dryRun) rmSync(path43.join(agentsDir, entry), { force: true });
|
|
28594
29075
|
agentCount++;
|
|
28595
29076
|
}
|
|
28596
29077
|
}
|
|
@@ -28601,16 +29082,16 @@ async function runClaudeUninstall(flags = []) {
|
|
|
28601
29082
|
removed++;
|
|
28602
29083
|
}
|
|
28603
29084
|
}
|
|
28604
|
-
const projectsDir =
|
|
28605
|
-
if (
|
|
29085
|
+
const projectsDir = path43.join(claudeDir, "projects");
|
|
29086
|
+
if (existsSync29(projectsDir)) {
|
|
28606
29087
|
let projectCount = 0;
|
|
28607
29088
|
try {
|
|
28608
29089
|
const projects = readdirSync8(projectsDir);
|
|
28609
29090
|
for (const proj of projects) {
|
|
28610
|
-
const projSettings =
|
|
28611
|
-
if (!
|
|
29091
|
+
const projSettings = path43.join(projectsDir, proj, "settings.json");
|
|
29092
|
+
if (!existsSync29(projSettings)) continue;
|
|
28612
29093
|
try {
|
|
28613
|
-
const pSettings = JSON.parse(
|
|
29094
|
+
const pSettings = JSON.parse(readFileSync26(projSettings, "utf8"));
|
|
28614
29095
|
let changed = false;
|
|
28615
29096
|
if (Array.isArray(pSettings.permissions?.allow)) {
|
|
28616
29097
|
const before = pSettings.permissions.allow.length;
|
|
@@ -28620,7 +29101,7 @@ async function runClaudeUninstall(flags = []) {
|
|
|
28620
29101
|
if (pSettings.permissions.allow.length < before) changed = true;
|
|
28621
29102
|
}
|
|
28622
29103
|
if (changed && !dryRun) {
|
|
28623
|
-
|
|
29104
|
+
writeFileSync19(projSettings, JSON.stringify(pSettings, null, 2) + "\n");
|
|
28624
29105
|
}
|
|
28625
29106
|
if (changed) projectCount++;
|
|
28626
29107
|
} catch {
|
|
@@ -28644,18 +29125,18 @@ async function runClaudeUninstall(flags = []) {
|
|
|
28644
29125
|
};
|
|
28645
29126
|
const exeBinPath = findExeBin3();
|
|
28646
29127
|
if (!exeBinPath) throw new Error("exe-os not found in PATH");
|
|
28647
|
-
const binDir =
|
|
29128
|
+
const binDir = path43.dirname(exeBinPath);
|
|
28648
29129
|
let symlinkCount = 0;
|
|
28649
|
-
const rosterPath =
|
|
28650
|
-
if (
|
|
28651
|
-
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"));
|
|
28652
29133
|
const { DEFAULT_COORDINATOR_TEMPLATE_NAME: DEFAULT_COORDINATOR_TEMPLATE_NAME2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
28653
29134
|
const coordinatorName = roster.find((e) => e.role?.toLowerCase() === "coo")?.name ?? DEFAULT_COORDINATOR_TEMPLATE_NAME2;
|
|
28654
29135
|
for (const emp of roster) {
|
|
28655
29136
|
if (emp.name === coordinatorName) continue;
|
|
28656
29137
|
for (const suffix of ["", "-opencode"]) {
|
|
28657
|
-
const linkPath =
|
|
28658
|
-
if (
|
|
29138
|
+
const linkPath = path43.join(binDir, `${emp.name}${suffix}`);
|
|
29139
|
+
if (existsSync29(linkPath)) {
|
|
28659
29140
|
if (!dryRun) rmSync(linkPath, { force: true });
|
|
28660
29141
|
symlinkCount++;
|
|
28661
29142
|
}
|
|
@@ -28668,7 +29149,7 @@ async function runClaudeUninstall(flags = []) {
|
|
|
28668
29149
|
}
|
|
28669
29150
|
} catch {
|
|
28670
29151
|
}
|
|
28671
|
-
if (purge &&
|
|
29152
|
+
if (purge && existsSync29(exeOsDir)) {
|
|
28672
29153
|
if (!dryRun) {
|
|
28673
29154
|
process.stdout.write("\x1B[33m\u26A0 This will delete all memories, identities, and agent data.\x1B[0m\n");
|
|
28674
29155
|
process.stdout.write(" Removing ~/.exe-os...\n");
|
|
@@ -28693,7 +29174,7 @@ async function checkForUpdateOnBoot() {
|
|
|
28693
29174
|
const config = await loadConfig2();
|
|
28694
29175
|
if (!config.autoUpdate.checkOnBoot) return;
|
|
28695
29176
|
const { checkForUpdate: checkForUpdate2 } = await Promise.resolve().then(() => (init_update(), update_exports));
|
|
28696
|
-
const packageRoot =
|
|
29177
|
+
const packageRoot = path43.resolve(
|
|
28697
29178
|
new URL("../..", import.meta.url).pathname
|
|
28698
29179
|
);
|
|
28699
29180
|
const result = checkForUpdate2(packageRoot);
|
|
@@ -28753,7 +29234,7 @@ async function runActivate(key) {
|
|
|
28753
29234
|
const idTemplate = getIdentityTemplate(identityKey);
|
|
28754
29235
|
if (idTemplate) {
|
|
28755
29236
|
const idPath = identityPath2(name);
|
|
28756
|
-
const dir =
|
|
29237
|
+
const dir = path43.dirname(idPath);
|
|
28757
29238
|
if (!fs8.existsSync(dir)) fs8.mkdirSync(dir, { recursive: true });
|
|
28758
29239
|
fs8.writeFileSync(idPath, idTemplate.replace(/^agent_id: \w+/m, `agent_id: ${name}`), "utf-8");
|
|
28759
29240
|
}
|