@askexenow/exe-os 0.9.1 → 0.9.2

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.
@@ -698,10 +698,10 @@ async function disposeEmbedder() {
698
698
  async function embedDirect(text) {
699
699
  const llamaCpp = await import("node-llama-cpp");
700
700
  const { MODELS_DIR: MODELS_DIR2 } = await Promise.resolve().then(() => (init_config(), config_exports));
701
- const { existsSync: existsSync31 } = await import("fs");
702
- const path38 = await import("path");
703
- const modelPath = path38.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
704
- if (!existsSync31(modelPath)) {
701
+ const { existsSync: existsSync32 } = await import("fs");
702
+ const path40 = await import("path");
703
+ const modelPath = path40.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
704
+ if (!existsSync32(modelPath)) {
705
705
  throw new Error(`Embedding model not found at ${modelPath}. Run '/exe-setup' to download it.`);
706
706
  }
707
707
  const llama = await llamaCpp.getLlama();
@@ -6108,7 +6108,7 @@ var init_agent_config = __esm({
6108
6108
  AGENT_CONFIG_PATH = path16.join(EXE_AI_DIR, "agent-config.json");
6109
6109
  KNOWN_RUNTIMES = {
6110
6110
  claude: ["claude-opus-4", "claude-sonnet-4", "claude-haiku-4.5"],
6111
- codex: ["gpt-5.4", "gpt-5.5", "o3", "o4-mini"],
6111
+ codex: ["gpt-5.4", "gpt-5.5", "gpt-5.3-codex-spark", "o3", "o4-mini"],
6112
6112
  opencode: ["anthropic/claude-sonnet-4-6", "openai/gpt-5.4", "google/gemini-2.5-pro", "deepseek/deepseek-r3", "minimax/minimax-m2.5"]
6113
6113
  };
6114
6114
  RUNTIME_LABELS = {
@@ -9817,7 +9817,7 @@ __export(consolidation_exports, {
9817
9817
  selectUnconsolidated: () => selectUnconsolidated,
9818
9818
  storeConsolidation: () => storeConsolidation
9819
9819
  });
9820
- import { randomUUID as randomUUID5 } from "crypto";
9820
+ import { randomUUID as randomUUID6 } from "crypto";
9821
9821
  async function selectUnconsolidated(client, limit = 200) {
9822
9822
  const result = await client.execute({
9823
9823
  sql: `SELECT id, agent_id, project_name, tool_name, raw_text, timestamp
@@ -9913,7 +9913,7 @@ async function consolidateCluster(cluster, model) {
9913
9913
  return textBlock?.text ?? "";
9914
9914
  }
9915
9915
  async function storeConsolidation(client, cluster, synthesisText, embedFn) {
9916
- const consolidatedId = randomUUID5();
9916
+ const consolidatedId = randomUUID6();
9917
9917
  const now = (/* @__PURE__ */ new Date()).toISOString();
9918
9918
  const rawText = `CONSOLIDATION [${cluster.dateRange}, ${cluster.projectName}]:
9919
9919
 
@@ -9938,7 +9938,7 @@ ${synthesisText}`;
9938
9938
  const linkStmts = sourceIds.map((sourceId) => ({
9939
9939
  sql: `INSERT INTO consolidations (id, consolidated_memory_id, source_memory_id, created_at)
9940
9940
  VALUES (?, ?, ?, ?)`,
9941
- args: [randomUUID5(), consolidatedId, sourceId, now]
9941
+ args: [randomUUID6(), consolidatedId, sourceId, now]
9942
9942
  }));
9943
9943
  const placeholders = sourceIds.map(() => "?").join(",");
9944
9944
  const markStmt = {
@@ -10184,8 +10184,8 @@ __export(wiki_client_exports, {
10184
10184
  listDocuments: () => listDocuments,
10185
10185
  listWorkspaces: () => listWorkspaces
10186
10186
  });
10187
- async function wikiFetch(config2, path38, method = "GET", body) {
10188
- const url = `${config2.baseUrl}/api/v1${path38}`;
10187
+ async function wikiFetch(config2, path40, method = "GET", body) {
10188
+ const url = `${config2.baseUrl}/api/v1${path40}`;
10189
10189
  const headers = {
10190
10190
  Authorization: `Bearer ${config2.apiKey}`,
10191
10191
  "Content-Type": "application/json"
@@ -10218,7 +10218,7 @@ async function wikiFetch(config2, path38, method = "GET", body) {
10218
10218
  }
10219
10219
  }
10220
10220
  if (!response.ok) {
10221
- throw new Error(`Wiki API ${method} ${path38}: ${response.status} ${response.statusText}`);
10221
+ throw new Error(`Wiki API ${method} ${path40}: ${response.status} ${response.statusText}`);
10222
10222
  }
10223
10223
  return response.json();
10224
10224
  } finally {
@@ -10327,14 +10327,14 @@ __export(worker_gate_exports, {
10327
10327
  tryAcquireBackfillLock: () => tryAcquireBackfillLock,
10328
10328
  tryAcquireWorkerSlot: () => tryAcquireWorkerSlot
10329
10329
  });
10330
- import { readdirSync as readdirSync9, writeFileSync as writeFileSync15, unlinkSync as unlinkSync8, mkdirSync as mkdirSync12, existsSync as existsSync24 } from "fs";
10331
- import path31 from "path";
10330
+ import { readdirSync as readdirSync9, writeFileSync as writeFileSync17, unlinkSync as unlinkSync8, mkdirSync as mkdirSync14, existsSync as existsSync25 } from "fs";
10331
+ import path33 from "path";
10332
10332
  function tryAcquireWorkerSlot() {
10333
10333
  try {
10334
- mkdirSync12(WORKER_PID_DIR, { recursive: true });
10334
+ mkdirSync14(WORKER_PID_DIR, { recursive: true });
10335
10335
  const reservationId = `res-${process.pid}-${Date.now()}`;
10336
- const reservationPath = path31.join(WORKER_PID_DIR, `${reservationId}.pid`);
10337
- writeFileSync15(reservationPath, String(process.pid));
10336
+ const reservationPath = path33.join(WORKER_PID_DIR, `${reservationId}.pid`);
10337
+ writeFileSync17(reservationPath, String(process.pid));
10338
10338
  const files = readdirSync9(WORKER_PID_DIR);
10339
10339
  let alive = 0;
10340
10340
  for (const f of files) {
@@ -10351,7 +10351,7 @@ function tryAcquireWorkerSlot() {
10351
10351
  alive++;
10352
10352
  } catch {
10353
10353
  try {
10354
- unlinkSync8(path31.join(WORKER_PID_DIR, f));
10354
+ unlinkSync8(path33.join(WORKER_PID_DIR, f));
10355
10355
  } catch {
10356
10356
  }
10357
10357
  }
@@ -10374,21 +10374,21 @@ function tryAcquireWorkerSlot() {
10374
10374
  }
10375
10375
  function registerWorkerPid(pid) {
10376
10376
  try {
10377
- mkdirSync12(WORKER_PID_DIR, { recursive: true });
10378
- writeFileSync15(path31.join(WORKER_PID_DIR, `worker-${pid}.pid`), String(pid));
10377
+ mkdirSync14(WORKER_PID_DIR, { recursive: true });
10378
+ writeFileSync17(path33.join(WORKER_PID_DIR, `worker-${pid}.pid`), String(pid));
10379
10379
  } catch {
10380
10380
  }
10381
10381
  }
10382
10382
  function cleanupWorkerPid() {
10383
10383
  try {
10384
- unlinkSync8(path31.join(WORKER_PID_DIR, `worker-${process.pid}.pid`));
10384
+ unlinkSync8(path33.join(WORKER_PID_DIR, `worker-${process.pid}.pid`));
10385
10385
  } catch {
10386
10386
  }
10387
10387
  }
10388
10388
  function tryAcquireBackfillLock() {
10389
10389
  try {
10390
- mkdirSync12(WORKER_PID_DIR, { recursive: true });
10391
- if (existsSync24(BACKFILL_LOCK)) {
10390
+ mkdirSync14(WORKER_PID_DIR, { recursive: true });
10391
+ if (existsSync25(BACKFILL_LOCK)) {
10392
10392
  try {
10393
10393
  const pid = parseInt(
10394
10394
  __require("fs").readFileSync(BACKFILL_LOCK, "utf8").trim(),
@@ -10404,7 +10404,7 @@ function tryAcquireBackfillLock() {
10404
10404
  } catch {
10405
10405
  }
10406
10406
  }
10407
- writeFileSync15(BACKFILL_LOCK, String(process.pid));
10407
+ writeFileSync17(BACKFILL_LOCK, String(process.pid));
10408
10408
  return true;
10409
10409
  } catch {
10410
10410
  return true;
@@ -10421,9 +10421,9 @@ var init_worker_gate = __esm({
10421
10421
  "src/lib/worker-gate.ts"() {
10422
10422
  "use strict";
10423
10423
  init_config();
10424
- WORKER_PID_DIR = path31.join(EXE_AI_DIR, "worker-pids");
10424
+ WORKER_PID_DIR = path33.join(EXE_AI_DIR, "worker-pids");
10425
10425
  MAX_CONCURRENT_WORKERS = 3;
10426
- BACKFILL_LOCK = path31.join(WORKER_PID_DIR, "backfill.lock");
10426
+ BACKFILL_LOCK = path33.join(WORKER_PID_DIR, "backfill.lock");
10427
10427
  }
10428
10428
  });
10429
10429
 
@@ -10446,8 +10446,8 @@ __export(crdt_sync_exports, {
10446
10446
  rebuildFromDb: () => rebuildFromDb
10447
10447
  });
10448
10448
  import * as Y from "yjs";
10449
- import { readFileSync as readFileSync22, writeFileSync as writeFileSync16, existsSync as existsSync27, mkdirSync as mkdirSync13, unlinkSync as unlinkSync9 } from "fs";
10450
- import path34 from "path";
10449
+ import { readFileSync as readFileSync24, writeFileSync as writeFileSync18, existsSync as existsSync28, mkdirSync as mkdirSync15, unlinkSync as unlinkSync9 } from "fs";
10450
+ import path36 from "path";
10451
10451
  import { homedir as homedir5 } from "os";
10452
10452
  function getStatePath() {
10453
10453
  return _statePathOverride ?? DEFAULT_STATE_PATH;
@@ -10459,9 +10459,9 @@ function initCrdtDoc() {
10459
10459
  if (doc) return doc;
10460
10460
  doc = new Y.Doc();
10461
10461
  const sp = getStatePath();
10462
- if (existsSync27(sp)) {
10462
+ if (existsSync28(sp)) {
10463
10463
  try {
10464
- const state = readFileSync22(sp);
10464
+ const state = readFileSync24(sp);
10465
10465
  Y.applyUpdate(doc, new Uint8Array(state));
10466
10466
  } catch {
10467
10467
  console.warn("[crdt-sync] WARN: corrupted state file, rebuilding from DB");
@@ -10603,10 +10603,10 @@ function persistState() {
10603
10603
  if (!doc) return;
10604
10604
  try {
10605
10605
  const sp = getStatePath();
10606
- const dir = path34.dirname(sp);
10607
- if (!existsSync27(dir)) mkdirSync13(dir, { recursive: true });
10606
+ const dir = path36.dirname(sp);
10607
+ if (!existsSync28(dir)) mkdirSync15(dir, { recursive: true });
10608
10608
  const state = Y.encodeStateAsUpdate(doc);
10609
- writeFileSync16(sp, Buffer.from(state));
10609
+ writeFileSync18(sp, Buffer.from(state));
10610
10610
  } catch {
10611
10611
  }
10612
10612
  }
@@ -10647,7 +10647,7 @@ var DEFAULT_STATE_PATH, _statePathOverride, doc;
10647
10647
  var init_crdt_sync = __esm({
10648
10648
  "src/lib/crdt-sync.ts"() {
10649
10649
  "use strict";
10650
- DEFAULT_STATE_PATH = path34.join(homedir5(), ".exe-os", "crdt-state.bin");
10650
+ DEFAULT_STATE_PATH = path36.join(homedir5(), ".exe-os", "crdt-state.bin");
10651
10651
  _statePathOverride = null;
10652
10652
  doc = null;
10653
10653
  }
@@ -10660,8 +10660,8 @@ init_database();
10660
10660
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
10661
10661
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
10662
10662
  import { spawn as spawn3 } from "child_process";
10663
- import { existsSync as existsSync30, openSync as openSync3, mkdirSync as mkdirSync15, closeSync as closeSync3 } from "fs";
10664
- import path37 from "path";
10663
+ import { existsSync as existsSync31, openSync as openSync3, mkdirSync as mkdirSync17, closeSync as closeSync3 } from "fs";
10664
+ import path39 from "path";
10665
10665
  import { fileURLToPath as fileURLToPath5 } from "url";
10666
10666
 
10667
10667
  // src/mcp/tools/recall-my-memory.ts
@@ -11331,10 +11331,10 @@ function registerCreateTask(server2) {
11331
11331
  skipDispatch: true
11332
11332
  });
11333
11333
  try {
11334
- const { existsSync: existsSync31, mkdirSync: mkdirSync16, writeFileSync: writeFileSync18 } = await import("fs");
11334
+ const { existsSync: existsSync32, mkdirSync: mkdirSync18, writeFileSync: writeFileSync20 } = await import("fs");
11335
11335
  const { identityPath: identityPath2 } = await Promise.resolve().then(() => (init_identity(), identity_exports));
11336
11336
  const idPath = identityPath2(assigned_to);
11337
- if (!existsSync31(idPath)) {
11337
+ if (!existsSync32(idPath)) {
11338
11338
  const { loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
11339
11339
  const employees = await loadEmployees2();
11340
11340
  const emp = employees.find((e) => e.name === assigned_to);
@@ -11343,8 +11343,8 @@ function registerCreateTask(server2) {
11343
11343
  const template = getTemplateForTitle2(emp.role);
11344
11344
  if (template) {
11345
11345
  const dir = (await import("path")).dirname(idPath);
11346
- if (!existsSync31(dir)) mkdirSync16(dir, { recursive: true });
11347
- writeFileSync18(idPath, template.replace(/^agent_id: \w+/m, `agent_id: ${assigned_to}`), "utf-8");
11346
+ if (!existsSync32(dir)) mkdirSync18(dir, { recursive: true });
11347
+ writeFileSync20(idPath, template.replace(/^agent_id: \w+/m, `agent_id: ${assigned_to}`), "utf-8");
11348
11348
  }
11349
11349
  }
11350
11350
  }
@@ -14689,9 +14689,9 @@ var HostingerApiClient = class {
14689
14689
  }
14690
14690
  this.lastRequestTime = Date.now();
14691
14691
  }
14692
- async request(method, path38, body) {
14692
+ async request(method, path40, body) {
14693
14693
  await this.rateLimit();
14694
- const url = `${this.baseUrl}${path38}`;
14694
+ const url = `${this.baseUrl}${path40}`;
14695
14695
  const headers = {
14696
14696
  Authorization: `Bearer ${this.apiKey}`,
14697
14697
  "Content-Type": "application/json",
@@ -14764,8 +14764,8 @@ async function requestCloudflare(cfApiToken, zoneId, options) {
14764
14764
  }
14765
14765
  return envelope.result;
14766
14766
  }
14767
- function buildUrl(zoneId, path38 = "/dns_records", query) {
14768
- const normalizedPath = path38.startsWith("/") ? path38 : `/${path38}`;
14767
+ function buildUrl(zoneId, path40 = "/dns_records", query) {
14768
+ const normalizedPath = path40.startsWith("/") ? path40 : `/${path40}`;
14769
14769
  const url = new URL(
14770
14770
  `${CLOUDFLARE_API_BASE_URL}/zones/${zoneId}${normalizedPath}`
14771
14771
  );
@@ -15070,9 +15070,433 @@ function buildInventoryRecord(params) {
15070
15070
  };
15071
15071
  }
15072
15072
 
15073
+ // src/mcp/tools/export-orchestration.ts
15074
+ init_active_agent();
15075
+ import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync15 } from "fs";
15076
+ import path29 from "path";
15077
+ import { z as z38 } from "zod";
15078
+
15079
+ // src/lib/orchestration-package.ts
15080
+ init_database();
15081
+ init_identity();
15082
+ init_platform_procedures();
15083
+ import { randomUUID as randomUUID5 } from "crypto";
15084
+ import { copyFileSync, existsSync as existsSync22, mkdirSync as mkdirSync12, readFileSync as readFileSync18, writeFileSync as writeFileSync14 } from "fs";
15085
+ import os11 from "os";
15086
+ import path28 from "path";
15087
+ var PACKAGE_VERSION = "1.0";
15088
+ var ROSTER_FILENAME = "exe-employees.json";
15089
+ var ROSTER_BACKUP_FILENAME = "exe-employees.json.bak";
15090
+ var EXE_OS_DIRNAME = ".exe-os";
15091
+ var DEFAULT_BEHAVIOR_PRIORITY = "p1";
15092
+ var DEFAULT_PROCEDURE_PRIORITY = "p0";
15093
+ var DEFAULT_IDENTITY_UPDATED_BY = "orchestration-import";
15094
+ function ensureObject(value, label) {
15095
+ if (value == null || Array.isArray(value) || typeof value !== "object") {
15096
+ throw new Error(`${label} must be an object`);
15097
+ }
15098
+ return value;
15099
+ }
15100
+ function ensureString(value, label) {
15101
+ if (typeof value !== "string") {
15102
+ throw new Error(`${label} must be a string`);
15103
+ }
15104
+ return value;
15105
+ }
15106
+ function ensureOptionalString(value, label) {
15107
+ if (value == null) return void 0;
15108
+ return ensureString(value, label);
15109
+ }
15110
+ function ensureNullableString(value, label) {
15111
+ if (value == null) return null;
15112
+ return ensureString(value, label);
15113
+ }
15114
+ function ensurePriority(value, label, fallback) {
15115
+ if (value == null) return fallback;
15116
+ if (value === "p0" || value === "p1" || value === "p2") {
15117
+ return value;
15118
+ }
15119
+ throw new Error(`${label} must be one of: p0, p1, p2`);
15120
+ }
15121
+ function validateRosterEntry(value, index) {
15122
+ const record = ensureObject(value, `roster[${index}]`);
15123
+ return {
15124
+ name: ensureString(record.name, `roster[${index}].name`),
15125
+ role: ensureString(record.role, `roster[${index}].role`),
15126
+ systemPrompt: ensureString(record.systemPrompt, `roster[${index}].systemPrompt`),
15127
+ createdAt: typeof record.createdAt === "string" ? record.createdAt : "",
15128
+ templateName: ensureOptionalString(record.templateName, `roster[${index}].templateName`),
15129
+ templateVersion: typeof record.templateVersion === "number" ? record.templateVersion : void 0
15130
+ };
15131
+ }
15132
+ function validateBehaviorEntry(value, index) {
15133
+ const record = ensureObject(value, `behaviors[${index}]`);
15134
+ return {
15135
+ agent_id: ensureString(record.agent_id, `behaviors[${index}].agent_id`),
15136
+ project_name: ensureNullableString(record.project_name, `behaviors[${index}].project_name`),
15137
+ domain: ensureNullableString(record.domain, `behaviors[${index}].domain`),
15138
+ content: ensureString(record.content, `behaviors[${index}].content`),
15139
+ priority: ensurePriority(record.priority, `behaviors[${index}].priority`, DEFAULT_BEHAVIOR_PRIORITY)
15140
+ };
15141
+ }
15142
+ function validateProcedureEntry(value, index) {
15143
+ const record = ensureObject(value, `procedures[${index}]`);
15144
+ return {
15145
+ title: ensureString(record.title, `procedures[${index}].title`),
15146
+ content: ensureString(record.content, `procedures[${index}].content`),
15147
+ priority: ensurePriority(record.priority, `procedures[${index}].priority`, DEFAULT_PROCEDURE_PRIORITY),
15148
+ domain: ensureNullableString(record.domain, `procedures[${index}].domain`)
15149
+ };
15150
+ }
15151
+ function getRosterPath() {
15152
+ return path28.join(os11.homedir(), EXE_OS_DIRNAME, ROSTER_FILENAME);
15153
+ }
15154
+ function getBackupPath() {
15155
+ return path28.join(os11.homedir(), EXE_OS_DIRNAME, ROSTER_BACKUP_FILENAME);
15156
+ }
15157
+ function readRosterFile() {
15158
+ const rosterPath = getRosterPath();
15159
+ if (!existsSync22(rosterPath)) return [];
15160
+ const raw = readFileSync18(rosterPath, "utf-8");
15161
+ const parsed = JSON.parse(raw);
15162
+ if (!Array.isArray(parsed)) {
15163
+ throw new Error("Roster file must contain a JSON array");
15164
+ }
15165
+ return parsed.map((entry, index) => validateRosterEntry(entry, index));
15166
+ }
15167
+ function writeRosterFile(roster) {
15168
+ if (roster.length === 0) {
15169
+ throw new Error("Refusing to write empty roster \u2014 this would delete all employees");
15170
+ }
15171
+ const rosterPath = getRosterPath();
15172
+ mkdirSync12(path28.dirname(rosterPath), { recursive: true });
15173
+ if (existsSync22(rosterPath)) {
15174
+ const currentRoster = readRosterFile();
15175
+ if (roster.length < currentRoster.length) {
15176
+ throw new Error(
15177
+ `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.`
15178
+ );
15179
+ }
15180
+ copyFileSync(rosterPath, getBackupPath());
15181
+ }
15182
+ writeFileSync14(rosterPath, `${JSON.stringify(roster, null, 2)}
15183
+ `, "utf-8");
15184
+ }
15185
+ function buildImportedRosterEntries(roster, timestamp) {
15186
+ return roster.map((entry) => ({
15187
+ name: entry.name,
15188
+ role: entry.role,
15189
+ systemPrompt: entry.systemPrompt,
15190
+ createdAt: timestamp,
15191
+ ...entry.templateName != null ? { templateName: entry.templateName } : {},
15192
+ ...entry.templateVersion != null ? { templateVersion: entry.templateVersion } : {}
15193
+ }));
15194
+ }
15195
+ async function insertBehaviors(behaviors, timestamp) {
15196
+ const client = getClient();
15197
+ for (const behavior of behaviors) {
15198
+ await client.execute({
15199
+ sql: `INSERT INTO behaviors (id, agent_id, project_name, domain, priority, content, active, created_at, updated_at)
15200
+ VALUES (?, ?, ?, ?, ?, ?, 1, ?, ?)`,
15201
+ args: [
15202
+ randomUUID5(),
15203
+ behavior.agent_id,
15204
+ behavior.project_name,
15205
+ behavior.domain,
15206
+ behavior.priority,
15207
+ behavior.content,
15208
+ timestamp,
15209
+ timestamp
15210
+ ]
15211
+ });
15212
+ }
15213
+ return behaviors.length;
15214
+ }
15215
+ async function insertProcedures(procedures, timestamp, options) {
15216
+ const client = getClient();
15217
+ const skipTitles = options?.skipTitles ?? /* @__PURE__ */ new Set();
15218
+ let inserted = 0;
15219
+ for (const procedure of procedures) {
15220
+ if (skipTitles.has(procedure.title) || PLATFORM_PROCEDURE_TITLES.has(procedure.title)) {
15221
+ continue;
15222
+ }
15223
+ await client.execute({
15224
+ sql: `INSERT INTO global_procedures (id, title, content, priority, domain, active, created_at, updated_at)
15225
+ VALUES (?, ?, ?, ?, ?, 1, ?, ?)`,
15226
+ args: [
15227
+ randomUUID5(),
15228
+ procedure.title,
15229
+ procedure.content,
15230
+ procedure.priority,
15231
+ procedure.domain,
15232
+ timestamp,
15233
+ timestamp
15234
+ ]
15235
+ });
15236
+ skipTitles.add(procedure.title);
15237
+ inserted += 1;
15238
+ }
15239
+ return inserted;
15240
+ }
15241
+ async function replaceBehaviorsAndProcedures(behaviors, procedures, timestamp) {
15242
+ const client = getClient();
15243
+ await client.execute({
15244
+ sql: "UPDATE behaviors SET active = 0, updated_at = ? WHERE active = 1",
15245
+ args: [timestamp]
15246
+ });
15247
+ await client.execute({
15248
+ sql: "UPDATE global_procedures SET active = 0, updated_at = ? WHERE active = 1",
15249
+ args: [timestamp]
15250
+ });
15251
+ return {
15252
+ behaviors: await insertBehaviors(behaviors, timestamp),
15253
+ procedures: await insertProcedures(procedures, timestamp)
15254
+ };
15255
+ }
15256
+ async function mergeRosterEntries(importedRoster, timestamp) {
15257
+ const currentRoster = readRosterFile();
15258
+ const existingNames = new Set(currentRoster.map((entry) => entry.name.toLowerCase()));
15259
+ const additions = buildImportedRosterEntries(
15260
+ importedRoster.filter((entry) => !existingNames.has(entry.name.toLowerCase())),
15261
+ timestamp
15262
+ );
15263
+ if (additions.length > 0) {
15264
+ writeRosterFile([...currentRoster, ...additions]);
15265
+ }
15266
+ return additions.length;
15267
+ }
15268
+ async function replaceRosterEntries(importedRoster, timestamp) {
15269
+ const currentRoster = readRosterFile();
15270
+ const importedByName = new Map(
15271
+ buildImportedRosterEntries(importedRoster, timestamp).map((entry) => [entry.name.toLowerCase(), entry])
15272
+ );
15273
+ const merged = currentRoster.map((existing) => {
15274
+ const imported = importedByName.get(existing.name.toLowerCase());
15275
+ if (imported) {
15276
+ importedByName.delete(existing.name.toLowerCase());
15277
+ return imported;
15278
+ }
15279
+ return existing;
15280
+ });
15281
+ for (const newEntry of importedByName.values()) {
15282
+ merged.push(newEntry);
15283
+ }
15284
+ writeRosterFile(merged);
15285
+ return importedRoster.length;
15286
+ }
15287
+ async function importIdentities(identities, updatedBy) {
15288
+ const entries = Object.entries(identities);
15289
+ for (const [agentId, content] of entries) {
15290
+ await updateIdentity(agentId, content, updatedBy);
15291
+ }
15292
+ return entries.length;
15293
+ }
15294
+ async function getActiveProcedureTitles() {
15295
+ const client = getClient();
15296
+ const result = await client.execute({
15297
+ sql: "SELECT title FROM global_procedures WHERE active = 1",
15298
+ args: []
15299
+ });
15300
+ return new Set(result.rows.map((row) => String(row.title)));
15301
+ }
15302
+ async function exportOrchestration(createdBy) {
15303
+ const client = getClient();
15304
+ const roster = readRosterFile().map((entry) => ({
15305
+ ...entry,
15306
+ createdAt: ""
15307
+ }));
15308
+ const identities = {};
15309
+ for (const identitySummary of listIdentities()) {
15310
+ const identity = getIdentity(identitySummary.agentId);
15311
+ if (identity?.raw) {
15312
+ identities[identitySummary.agentId] = identity.raw;
15313
+ }
15314
+ }
15315
+ const behaviorResult = await client.execute({
15316
+ sql: "SELECT agent_id, project_name, domain, content, priority FROM behaviors WHERE active = 1",
15317
+ args: []
15318
+ });
15319
+ const procedureResult = await client.execute({
15320
+ sql: "SELECT title, content, priority, domain FROM global_procedures WHERE active = 1",
15321
+ args: []
15322
+ });
15323
+ const behaviors = behaviorResult.rows.map((row) => ({
15324
+ agent_id: String(row.agent_id),
15325
+ project_name: row.project_name == null ? null : String(row.project_name),
15326
+ domain: row.domain == null ? null : String(row.domain),
15327
+ content: String(row.content),
15328
+ priority: ensurePriority(row.priority, "behaviors.priority", DEFAULT_BEHAVIOR_PRIORITY)
15329
+ }));
15330
+ const procedures = procedureResult.rows.map((row) => ({
15331
+ title: String(row.title),
15332
+ content: String(row.content),
15333
+ priority: ensurePriority(row.priority, "procedures.priority", DEFAULT_PROCEDURE_PRIORITY),
15334
+ domain: row.domain == null ? null : String(row.domain)
15335
+ })).filter((procedure) => !PLATFORM_PROCEDURE_TITLES.has(procedure.title));
15336
+ return {
15337
+ version: PACKAGE_VERSION,
15338
+ created_by: createdBy,
15339
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
15340
+ roster,
15341
+ identities,
15342
+ behaviors,
15343
+ procedures
15344
+ };
15345
+ }
15346
+ async function importOrchestration(pkg, strategy) {
15347
+ const validated = validatePackage(pkg);
15348
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
15349
+ const updatedBy = validated.created_by || DEFAULT_IDENTITY_UPDATED_BY;
15350
+ const rosterCount = strategy === "replace" ? await replaceRosterEntries(validated.roster, timestamp) : await mergeRosterEntries(validated.roster, timestamp);
15351
+ const identityCount = await importIdentities(validated.identities, updatedBy);
15352
+ if (strategy === "replace") {
15353
+ const replaced = await replaceBehaviorsAndProcedures(
15354
+ validated.behaviors,
15355
+ validated.procedures,
15356
+ timestamp
15357
+ );
15358
+ return {
15359
+ imported: {
15360
+ roster: rosterCount,
15361
+ identities: identityCount,
15362
+ behaviors: replaced.behaviors,
15363
+ procedures: replaced.procedures
15364
+ }
15365
+ };
15366
+ }
15367
+ const existingProcedureTitles = await getActiveProcedureTitles();
15368
+ const behaviorCount = await insertBehaviors(validated.behaviors, timestamp);
15369
+ const procedureCount = await insertProcedures(
15370
+ validated.procedures,
15371
+ timestamp,
15372
+ { skipTitles: existingProcedureTitles }
15373
+ );
15374
+ return {
15375
+ imported: {
15376
+ roster: rosterCount,
15377
+ identities: identityCount,
15378
+ behaviors: behaviorCount,
15379
+ procedures: procedureCount
15380
+ }
15381
+ };
15382
+ }
15383
+ function validatePackage(data) {
15384
+ const record = ensureObject(data, "package");
15385
+ const version = ensureString(record.version, "version");
15386
+ if (version !== PACKAGE_VERSION) {
15387
+ throw new Error(`Unsupported orchestration package version: ${version}`);
15388
+ }
15389
+ if (!Array.isArray(record.roster)) {
15390
+ throw new Error("roster is required and must be an array");
15391
+ }
15392
+ if (record.identities == null || Array.isArray(record.identities) || typeof record.identities !== "object") {
15393
+ throw new Error("identities is required and must be an object");
15394
+ }
15395
+ if (!Array.isArray(record.behaviors)) {
15396
+ throw new Error("behaviors is required and must be an array");
15397
+ }
15398
+ if (!Array.isArray(record.procedures)) {
15399
+ throw new Error("procedures is required and must be an array");
15400
+ }
15401
+ const identities = Object.entries(record.identities).reduce(
15402
+ (acc, [agentId, content]) => {
15403
+ acc[agentId] = ensureString(content, `identities.${agentId}`);
15404
+ return acc;
15405
+ },
15406
+ {}
15407
+ );
15408
+ return {
15409
+ version: PACKAGE_VERSION,
15410
+ created_by: ensureString(record.created_by, "created_by"),
15411
+ created_at: ensureString(record.created_at, "created_at"),
15412
+ roster: record.roster.map((entry, index) => validateRosterEntry(entry, index)),
15413
+ identities,
15414
+ behaviors: record.behaviors.map((entry, index) => validateBehaviorEntry(entry, index)),
15415
+ procedures: record.procedures.map((entry, index) => validateProcedureEntry(entry, index))
15416
+ };
15417
+ }
15418
+
15419
+ // src/mcp/tools/export-orchestration.ts
15420
+ init_store();
15421
+ function registerExportOrchestration(server2) {
15422
+ server2.registerTool(
15423
+ "export_orchestration",
15424
+ {
15425
+ title: "Export Orchestration",
15426
+ description: "Export roster, identities, behaviors, and customer procedures to a JSON package.",
15427
+ inputSchema: {
15428
+ output_path: z38.string().describe("File path to write the JSON package")
15429
+ }
15430
+ },
15431
+ async ({ output_path }) => {
15432
+ try {
15433
+ await initStore();
15434
+ const pkg = await exportOrchestration(getActiveAgent().agentId);
15435
+ mkdirSync13(path29.dirname(output_path), { recursive: true });
15436
+ writeFileSync15(output_path, `${JSON.stringify(pkg, null, 2)}
15437
+ `, "utf-8");
15438
+ return {
15439
+ content: [{
15440
+ type: "text",
15441
+ text: `Exported ${pkg.roster.length} roster entries, ${Object.keys(pkg.identities).length} identities, ${pkg.behaviors.length} behaviors, ${pkg.procedures.length} procedures to ${output_path}`
15442
+ }]
15443
+ };
15444
+ } catch (err) {
15445
+ return {
15446
+ content: [{
15447
+ type: "text",
15448
+ text: `Failed to export orchestration: ${err instanceof Error ? err.message : String(err)}`
15449
+ }],
15450
+ isError: true
15451
+ };
15452
+ }
15453
+ }
15454
+ );
15455
+ }
15456
+
15457
+ // src/mcp/tools/import-orchestration.ts
15458
+ import { readFileSync as readFileSync19 } from "fs";
15459
+ import { z as z39 } from "zod";
15460
+ init_store();
15461
+ function registerImportOrchestration(server2) {
15462
+ server2.registerTool(
15463
+ "import_orchestration",
15464
+ {
15465
+ title: "Import Orchestration",
15466
+ description: "Import roster, identities, behaviors, and procedures from an orchestration package.",
15467
+ inputSchema: {
15468
+ package_path: z39.string().describe("Path to the orchestration package JSON file"),
15469
+ merge_strategy: z39.enum(["replace", "merge"]).default("merge").describe("How to apply the package: replace existing data or merge additively")
15470
+ }
15471
+ },
15472
+ async ({ package_path, merge_strategy }) => {
15473
+ try {
15474
+ await initStore();
15475
+ const raw = readFileSync19(package_path, "utf-8");
15476
+ const pkg = validatePackage(JSON.parse(raw));
15477
+ const result = await importOrchestration(pkg, merge_strategy);
15478
+ return {
15479
+ content: [{
15480
+ type: "text",
15481
+ text: `Imported ${result.imported.roster} roster entries, ${result.imported.identities} identities, ${result.imported.behaviors} behaviors, ${result.imported.procedures} procedures using ${merge_strategy} strategy`
15482
+ }]
15483
+ };
15484
+ } catch (err) {
15485
+ return {
15486
+ content: [{
15487
+ type: "text",
15488
+ text: `Failed to import orchestration: ${err instanceof Error ? err.message : String(err)}`
15489
+ }],
15490
+ isError: true
15491
+ };
15492
+ }
15493
+ }
15494
+ );
15495
+ }
15496
+
15073
15497
  // src/mcp/tools/query-conversations.ts
15074
15498
  init_database();
15075
- import { z as z38 } from "zod";
15499
+ import { z as z40 } from "zod";
15076
15500
  function registerQueryConversations(server2) {
15077
15501
  server2.registerTool(
15078
15502
  "query_conversations",
@@ -15080,14 +15504,14 @@ function registerQueryConversations(server2) {
15080
15504
  title: "Query Conversations",
15081
15505
  description: "Search across all adapter messages by content, sender, date range, or platform. Returns messages with source attribution (platform, sender, timestamp).",
15082
15506
  inputSchema: {
15083
- query: z38.string().optional().describe("Full-text search query across message content and responses"),
15084
- sender: z38.string().optional().describe("Filter by sender ID or name (partial match)"),
15085
- platform: z38.string().optional().describe("Filter by platform: whatsapp, signal, telegram, discord, imessage, slack, email, webchat"),
15086
- after: z38.string().optional().describe("Filter messages after this ISO 8601 date (e.g. 2026-04-01)"),
15087
- before: z38.string().optional().describe("Filter messages before this ISO 8601 date (e.g. 2026-04-15)"),
15088
- channel_id: z38.string().optional().describe("Filter by channel/chat ID"),
15089
- thread_id: z38.string().optional().describe("Filter by conversation thread ID"),
15090
- limit: z38.number().int().min(1).max(100).optional().default(25).describe("Max results to return (default 25, max 100)")
15507
+ query: z40.string().optional().describe("Full-text search query across message content and responses"),
15508
+ sender: z40.string().optional().describe("Filter by sender ID or name (partial match)"),
15509
+ platform: z40.string().optional().describe("Filter by platform: whatsapp, signal, telegram, discord, imessage, slack, email, webchat"),
15510
+ after: z40.string().optional().describe("Filter messages after this ISO 8601 date (e.g. 2026-04-01)"),
15511
+ before: z40.string().optional().describe("Filter messages before this ISO 8601 date (e.g. 2026-04-15)"),
15512
+ channel_id: z40.string().optional().describe("Filter by channel/chat ID"),
15513
+ thread_id: z40.string().optional().describe("Filter by conversation thread ID"),
15514
+ limit: z40.number().int().min(1).max(100).optional().default(25).describe("Max results to return (default 25, max 100)")
15091
15515
  }
15092
15516
  },
15093
15517
  async (params) => {
@@ -15194,19 +15618,19 @@ function registerQueryConversations(server2) {
15194
15618
  }
15195
15619
 
15196
15620
  // src/mcp/tools/load-skill.ts
15197
- import { z as z39 } from "zod";
15198
- import { readFileSync as readFileSync18, readdirSync as readdirSync8, statSync as statSync3 } from "fs";
15199
- import path28 from "path";
15621
+ import { z as z41 } from "zod";
15622
+ import { readFileSync as readFileSync20, readdirSync as readdirSync8, statSync as statSync3 } from "fs";
15623
+ import path30 from "path";
15200
15624
  import { homedir as homedir2 } from "os";
15201
- var SKILLS_DIR = path28.join(homedir2(), ".claude", "skills");
15625
+ var SKILLS_DIR = path30.join(homedir2(), ".claude", "skills");
15202
15626
  function listAvailableSkills() {
15203
15627
  try {
15204
15628
  const entries = readdirSync8(SKILLS_DIR);
15205
15629
  return entries.filter((entry) => {
15206
15630
  try {
15207
- const entryPath = path28.join(SKILLS_DIR, entry);
15631
+ const entryPath = path30.join(SKILLS_DIR, entry);
15208
15632
  if (!statSync3(entryPath).isDirectory()) return false;
15209
- const skillFile = path28.join(entryPath, "SKILL.md");
15633
+ const skillFile = path30.join(entryPath, "SKILL.md");
15210
15634
  statSync3(skillFile);
15211
15635
  return true;
15212
15636
  } catch {
@@ -15224,7 +15648,7 @@ function registerLoadSkill(server2) {
15224
15648
  title: "Load Skill",
15225
15649
  description: "Load domain-specific guidance into your context. Use when you need specialized knowledge for a task (e.g., load_skill('seo') before doing SEO work, load_skill('code-reviewer') before reviewing code). Pass skill_name='list' to see all available skills.",
15226
15650
  inputSchema: {
15227
- skill_name: z39.string().describe(
15651
+ skill_name: z41.string().describe(
15228
15652
  "Skill to load (e.g. 'seo', 'code-reviewer', 'frontend-design'). Pass 'list' to see all available skills."
15229
15653
  )
15230
15654
  }
@@ -15249,10 +15673,10 @@ ${skills.map((s) => `- ${s}`).join("\n")}`
15249
15673
  }]
15250
15674
  };
15251
15675
  }
15252
- const sanitized = path28.basename(skill_name);
15253
- const skillFile = path28.join(SKILLS_DIR, sanitized, "SKILL.md");
15676
+ const sanitized = path30.basename(skill_name);
15677
+ const skillFile = path30.join(SKILLS_DIR, sanitized, "SKILL.md");
15254
15678
  try {
15255
- const content = readFileSync18(skillFile, "utf-8");
15679
+ const content = readFileSync20(skillFile, "utf-8");
15256
15680
  return {
15257
15681
  content: [{
15258
15682
  type: "text",
@@ -15281,7 +15705,7 @@ ${available.map((s) => `- ${s}`).join("\n")}` : "\n\nNo skills found in ~/.claud
15281
15705
  // src/mcp/tools/consolidate-memories.ts
15282
15706
  init_database();
15283
15707
  init_active_agent();
15284
- import { z as z40 } from "zod";
15708
+ import { z as z42 } from "zod";
15285
15709
  function registerConsolidateMemories(server2) {
15286
15710
  server2.registerTool(
15287
15711
  "consolidate_memories",
@@ -15289,8 +15713,8 @@ function registerConsolidateMemories(server2) {
15289
15713
  title: "Consolidate Memories",
15290
15714
  description: "Trigger content-aware memory consolidation. Groups recent memories by project, uses LLM to extract key facts, decisions, and patterns, then stores a high-importance summary and archives the originals. Runs automatically during idle time, but can be triggered manually when you want to compress your working memory.",
15291
15715
  inputSchema: {
15292
- max_clusters: z40.coerce.number().optional().default(5).describe("Maximum number of clusters to consolidate (default 5)"),
15293
- model: z40.string().optional().describe("LLM model for summarization (defaults to config value)")
15716
+ max_clusters: z42.coerce.number().optional().default(5).describe("Maximum number of clusters to consolidate (default 5)"),
15717
+ model: z42.string().optional().describe("LLM model for summarization (defaults to config value)")
15294
15718
  }
15295
15719
  },
15296
15720
  async ({ max_clusters, model }) => {
@@ -15346,7 +15770,7 @@ Consolidated summaries stored as tier-1 (importance=9) memories.`
15346
15770
  init_global_procedures();
15347
15771
  init_active_agent();
15348
15772
  init_employees();
15349
- import { z as z41 } from "zod";
15773
+ import { z as z43 } from "zod";
15350
15774
  function registerStoreGlobalProcedure(server2) {
15351
15775
  server2.registerTool(
15352
15776
  "store_global_procedure",
@@ -15354,10 +15778,10 @@ function registerStoreGlobalProcedure(server2) {
15354
15778
  title: "Store Global Procedure",
15355
15779
  description: "Create an organization-wide procedure (Layer 0) that supersedes identity, expertise, and experience. Use for hard rules that every employee must follow. RESTRICTED: only coordinator or founder sessions.",
15356
15780
  inputSchema: {
15357
- title: z41.string().describe("Short title for the procedure"),
15358
- content: z41.string().max(500).describe("The procedure content \u2014 clear, actionable instruction"),
15359
- priority: z41.enum(["p0", "p1", "p2"]).optional().describe("Priority tier. p0 = always (default). p1 = standard. p2 = nice-to-have."),
15360
- domain: z41.string().optional().describe("Category: workflow, code-style, communication, architecture, testing, security")
15781
+ title: z43.string().describe("Short title for the procedure"),
15782
+ content: z43.string().max(500).describe("The procedure content \u2014 clear, actionable instruction"),
15783
+ priority: z43.enum(["p0", "p1", "p2"]).optional().describe("Priority tier. p0 = always (default). p1 = standard. p2 = nice-to-have."),
15784
+ domain: z43.string().optional().describe("Category: workflow, code-style, communication, architecture, testing, security")
15361
15785
  }
15362
15786
  },
15363
15787
  async ({ title, content, priority, domain }) => {
@@ -15435,7 +15859,7 @@ init_global_procedures();
15435
15859
  init_active_agent();
15436
15860
  init_database();
15437
15861
  init_employees();
15438
- import { z as z42 } from "zod";
15862
+ import { z as z44 } from "zod";
15439
15863
  function registerDeactivateGlobalProcedure(server2) {
15440
15864
  server2.registerTool(
15441
15865
  "deactivate_global_procedure",
@@ -15443,7 +15867,7 @@ function registerDeactivateGlobalProcedure(server2) {
15443
15867
  title: "Deactivate Global Procedure",
15444
15868
  description: "Soft-delete a global procedure by setting active = 0. RESTRICTED: only coordinator or founder sessions. Use list_global_procedures to find the procedure ID first.",
15445
15869
  inputSchema: {
15446
- procedure_id: z42.string().describe("UUID of the global procedure to deactivate")
15870
+ procedure_id: z44.string().describe("UUID of the global procedure to deactivate")
15447
15871
  }
15448
15872
  },
15449
15873
  async ({ procedure_id }) => {
@@ -15498,7 +15922,7 @@ Content: ${row.content}`
15498
15922
  }
15499
15923
 
15500
15924
  // src/mcp/tools/search-everything.ts
15501
- import { z as z43 } from "zod";
15925
+ import { z as z45 } from "zod";
15502
15926
 
15503
15927
  // src/lib/unified-search.ts
15504
15928
  var DEFAULT_LIMIT = 10;
@@ -15665,11 +16089,11 @@ function registerSearchEverything(server2) {
15665
16089
  title: "Search Everything",
15666
16090
  description: "Search across all data stores \u2014 memories, conversations, and wiki \u2014 in one query. Returns merged results sorted by relevance with entity links.",
15667
16091
  inputSchema: {
15668
- query: z43.string().describe("What to search for across all data stores"),
15669
- sources: z43.array(z43.enum(["memory", "conversations", "wiki"])).optional().describe(
16092
+ query: z45.string().describe("What to search for across all data stores"),
16093
+ sources: z45.array(z45.enum(["memory", "conversations", "wiki"])).optional().describe(
15670
16094
  "Which sources to search (default: all). Options: memory, conversations, wiki"
15671
16095
  ),
15672
- limit: z43.coerce.number().int().min(1).max(50).optional().default(10).describe("Max results to return (default 10, max 50)")
16096
+ limit: z45.coerce.number().int().min(1).max(50).optional().default(10).describe("Max results to return (default 10, max 50)")
15673
16097
  }
15674
16098
  },
15675
16099
  async (params) => {
@@ -15730,7 +16154,7 @@ init_store();
15730
16154
  init_active_agent();
15731
16155
  init_database();
15732
16156
  init_plan_limits();
15733
- import { z as z44 } from "zod";
16157
+ import { z as z46 } from "zod";
15734
16158
  import crypto14 from "crypto";
15735
16159
  function registerStoreDecision(server2) {
15736
16160
  server2.registerTool(
@@ -15739,13 +16163,13 @@ function registerStoreDecision(server2) {
15739
16163
  title: "Store Decision",
15740
16164
  description: "Store an authoritative decision keyed by domain. Use this when a decision is made that should be canonical \u2014 future lookups via get_decision return the latest decision for that domain. Supports supersession chains.",
15741
16165
  inputSchema: {
15742
- domain: z44.string().describe(
16166
+ domain: z46.string().describe(
15743
16167
  "Domain key, e.g. 'auth-strategy', 'db-migration-approach', 'api-versioning'"
15744
16168
  ),
15745
- decision: z44.string().describe("The decision text \u2014 what was decided"),
15746
- rationale: z44.string().optional().describe("Why this decision was made \u2014 constraints, trade-offs, context"),
15747
- supersedes: z44.string().optional().describe("UUID of the decision this supersedes (previous decision for this domain)"),
15748
- project_name: z44.string().optional().describe("Project name")
16169
+ decision: z46.string().describe("The decision text \u2014 what was decided"),
16170
+ rationale: z46.string().optional().describe("Why this decision was made \u2014 constraints, trade-offs, context"),
16171
+ supersedes: z46.string().optional().describe("UUID of the decision this supersedes (previous decision for this domain)"),
16172
+ project_name: z46.string().optional().describe("Project name")
15749
16173
  }
15750
16174
  },
15751
16175
  async ({ domain, decision, rationale, supersedes, project_name }) => {
@@ -15813,7 +16237,7 @@ Supersedes: ${supersedes}` : ""}`
15813
16237
 
15814
16238
  // src/mcp/tools/get-decision.ts
15815
16239
  init_database();
15816
- import { z as z45 } from "zod";
16240
+ import { z as z47 } from "zod";
15817
16241
  function registerGetDecision(server2) {
15818
16242
  server2.registerTool(
15819
16243
  "get_decision",
@@ -15821,7 +16245,7 @@ function registerGetDecision(server2) {
15821
16245
  title: "Get Decision",
15822
16246
  description: "Retrieve the latest authoritative decision for a domain. Returns the current active decision and the supersession history.",
15823
16247
  inputSchema: {
15824
- domain: z45.string().describe(
16248
+ domain: z47.string().describe(
15825
16249
  "Domain key to look up, e.g. 'auth-strategy', 'db-migration-approach'"
15826
16250
  )
15827
16251
  }
@@ -15884,15 +16308,15 @@ function registerGetDecision(server2) {
15884
16308
  }
15885
16309
 
15886
16310
  // src/mcp/tools/get-agent-spend.ts
15887
- import { z as z46 } from "zod";
16311
+ import { z as z48 } from "zod";
15888
16312
 
15889
16313
  // src/lib/token-spend.ts
15890
16314
  init_database();
15891
16315
  import { readdir } from "fs/promises";
15892
16316
  import { createReadStream } from "fs";
15893
16317
  import { createInterface } from "readline";
15894
- import path29 from "path";
15895
- import os11 from "os";
16318
+ import path31 from "path";
16319
+ import os12 from "os";
15896
16320
  var MODEL_PRICING = {
15897
16321
  // Opus 4.5+ ($5/$25 — Anthropic price drop from original Opus 4)
15898
16322
  "claude-opus-4-7": { input: 5 / 1e6, output: 25 / 1e6, cacheRead: 0.5 / 1e6, cacheWrite: 6.25 / 1e6 },
@@ -15940,18 +16364,18 @@ async function getAgentSpend(period = "7d") {
15940
16364
  for (const row of result.rows) {
15941
16365
  sessionAgent.set(row.session_uuid, row.agent_id);
15942
16366
  }
15943
- const claudeDir = path29.join(os11.homedir(), ".claude", "projects");
16367
+ const claudeDir = path31.join(os12.homedir(), ".claude", "projects");
15944
16368
  let projectDirs = [];
15945
16369
  try {
15946
16370
  const entries = await readdir(claudeDir);
15947
- projectDirs = entries.map((e) => path29.join(claudeDir, e));
16371
+ projectDirs = entries.map((e) => path31.join(claudeDir, e));
15948
16372
  } catch {
15949
16373
  return [];
15950
16374
  }
15951
16375
  const agentTotals = /* @__PURE__ */ new Map();
15952
16376
  for (const [sessionUuid, agentId] of sessionAgent) {
15953
16377
  for (const dir of projectDirs) {
15954
- const jsonlPath = path29.join(dir, `${sessionUuid}.jsonl`);
16378
+ const jsonlPath = path31.join(dir, `${sessionUuid}.jsonl`);
15955
16379
  try {
15956
16380
  const usage = await extractSessionUsage(jsonlPath);
15957
16381
  if (usage.input === 0 && usage.output === 0) continue;
@@ -16046,8 +16470,8 @@ function registerGetAgentSpend(server2) {
16046
16470
  title: "Get Agent Spend",
16047
16471
  description: "Get per-agent token spend attribution. Shows input, output, and cache tokens consumed by each agent over a time period, with estimated cost.",
16048
16472
  inputSchema: {
16049
- period: z46.enum(["24h", "7d", "30d"]).default("7d").describe("Time period to query"),
16050
- agent_id: z46.string().optional().describe("Filter to a specific agent (e.g. 'tom', 'yoshi')")
16473
+ period: z48.enum(["24h", "7d", "30d"]).default("7d").describe("Time period to query"),
16474
+ agent_id: z48.string().optional().describe("Filter to a specific agent (e.g. 'tom', 'yoshi')")
16051
16475
  }
16052
16476
  },
16053
16477
  async ({ period, agent_id }) => {
@@ -16113,7 +16537,7 @@ function registerGetAgentSpend(server2) {
16113
16537
  // src/mcp/tools/get-graph-stats.ts
16114
16538
  init_database();
16115
16539
  init_graph_query();
16116
- import { z as z47 } from "zod";
16540
+ import { z as z49 } from "zod";
16117
16541
  function registerGetGraphStats(server2) {
16118
16542
  server2.registerTool(
16119
16543
  "get_graph_stats",
@@ -16121,7 +16545,7 @@ function registerGetGraphStats(server2) {
16121
16545
  title: "Get Graph Stats",
16122
16546
  description: "Get knowledge graph summary statistics: entity count, relationship count, and entity type breakdown.",
16123
16547
  inputSchema: {
16124
- _dummy: z47.string().optional().describe("Unused \u2014 no input required")
16548
+ _dummy: z49.string().optional().describe("Unused \u2014 no input required")
16125
16549
  }
16126
16550
  },
16127
16551
  async () => {
@@ -16163,7 +16587,7 @@ function registerGetGraphStats(server2) {
16163
16587
  // src/mcp/tools/get-entity-neighbors.ts
16164
16588
  init_database();
16165
16589
  init_graph_query();
16166
- import { z as z48 } from "zod";
16590
+ import { z as z50 } from "zod";
16167
16591
  function registerGetEntityNeighbors(server2) {
16168
16592
  server2.registerTool(
16169
16593
  "get_entity_neighbors",
@@ -16171,7 +16595,7 @@ function registerGetEntityNeighbors(server2) {
16171
16595
  title: "Get Entity Neighbors",
16172
16596
  description: "Get connected entities for a given entity name. Returns neighbors with relationship types, directions, and weights.",
16173
16597
  inputSchema: {
16174
- entity_name: z48.string().describe("Name of the entity to find neighbors for")
16598
+ entity_name: z50.string().describe("Name of the entity to find neighbors for")
16175
16599
  }
16176
16600
  },
16177
16601
  async ({ entity_name }) => {
@@ -16240,7 +16664,7 @@ function registerGetEntityNeighbors(server2) {
16240
16664
  // src/mcp/tools/get-hot-entities.ts
16241
16665
  init_database();
16242
16666
  init_graph_query();
16243
- import { z as z49 } from "zod";
16667
+ import { z as z51 } from "zod";
16244
16668
  var PERIOD_MS = {
16245
16669
  "24h": 24 * 60 * 60 * 1e3,
16246
16670
  "7d": 7 * 24 * 60 * 60 * 1e3,
@@ -16253,8 +16677,8 @@ function registerGetHotEntities(server2) {
16253
16677
  title: "Get Hot Entities",
16254
16678
  description: "Get trending entities \u2014 those with the most new relationships in a time period. Surfaces what's most active in the knowledge graph.",
16255
16679
  inputSchema: {
16256
- period: z49.enum(["24h", "7d", "30d"]).default("7d").describe("Time period to look back"),
16257
- limit: z49.number().int().min(1).max(50).default(10).describe("Max entities to return")
16680
+ period: z51.enum(["24h", "7d", "30d"]).default("7d").describe("Time period to look back"),
16681
+ limit: z51.number().int().min(1).max(50).default(10).describe("Max entities to return")
16258
16682
  }
16259
16683
  },
16260
16684
  async ({ period, limit }) => {
@@ -16302,7 +16726,7 @@ function registerGetHotEntities(server2) {
16302
16726
 
16303
16727
  // src/mcp/tools/export-graph.ts
16304
16728
  init_database();
16305
- import { z as z50 } from "zod";
16729
+ import { z as z52 } from "zod";
16306
16730
 
16307
16731
  // src/lib/graph-export.ts
16308
16732
  async function loadGraphData(client) {
@@ -16515,7 +16939,7 @@ function registerExportGraph(server2) {
16515
16939
  title: "Export Graph",
16516
16940
  description: "Export the knowledge graph as a markdown report (inline) or an interactive HTML visualization (writes file, returns path).",
16517
16941
  inputSchema: {
16518
- format: z50.enum(["html", "markdown"]).default("markdown").describe("Export format: markdown (inline) or html (file)")
16942
+ format: z52.enum(["html", "markdown"]).default("markdown").describe("Export format: markdown (inline) or html (file)")
16519
16943
  }
16520
16944
  },
16521
16945
  async ({ format }) => {
@@ -16529,12 +16953,12 @@ function registerExportGraph(server2) {
16529
16953
  }
16530
16954
  const html = await exportGraphHTML(client);
16531
16955
  const fs = await import("fs");
16532
- const path38 = await import("path");
16533
- const os13 = await import("os");
16534
- const outDir = path38.join(os13.homedir(), ".exe-os", "exports");
16956
+ const path40 = await import("path");
16957
+ const os14 = await import("os");
16958
+ const outDir = path40.join(os14.homedir(), ".exe-os", "exports");
16535
16959
  fs.mkdirSync(outDir, { recursive: true });
16536
16960
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
16537
- const filePath = path38.join(outDir, `graph-${timestamp}.html`);
16961
+ const filePath = path40.join(outDir, `graph-${timestamp}.html`);
16538
16962
  fs.writeFileSync(filePath, html, "utf-8");
16539
16963
  return {
16540
16964
  content: [
@@ -16565,7 +16989,7 @@ Open in a browser to explore interactively.`
16565
16989
 
16566
16990
  // src/mcp/tools/find-similar-trajectories.ts
16567
16991
  init_skill_learning();
16568
- import { z as z51 } from "zod";
16992
+ import { z as z53 } from "zod";
16569
16993
  function registerFindSimilarTrajectories(server2) {
16570
16994
  server2.registerTool(
16571
16995
  "find_similar_trajectories",
@@ -16573,7 +16997,7 @@ function registerFindSimilarTrajectories(server2) {
16573
16997
  title: "Find Similar Trajectories",
16574
16998
  description: 'Find past task trajectories that match a described tool sequence. Input a comma-separated tool sequence (e.g. "Read, Edit, Bash, Read") to find similar past workflows.',
16575
16999
  inputSchema: {
16576
- description: z51.string().describe(
17000
+ description: z53.string().describe(
16577
17001
  'Tool sequence to match \u2014 comma-separated tool names (e.g. "Read, Grep, Edit, Bash:npm, Bash:git")'
16578
17002
  )
16579
17003
  }
@@ -16644,7 +17068,7 @@ ${withSkill.length} trajectory(s) already extracted into skill(s).`
16644
17068
 
16645
17069
  // src/mcp/tools/get-session-kills.ts
16646
17070
  init_session_kill_telemetry();
16647
- import { z as z52 } from "zod";
17071
+ import { z as z54 } from "zod";
16648
17072
  var PERIOD_MS2 = {
16649
17073
  "24h": 24 * 60 * 60 * 1e3,
16650
17074
  "7d": 7 * 24 * 60 * 60 * 1e3,
@@ -16660,7 +17084,7 @@ function registerGetSessionKills(server2) {
16660
17084
  title: "Get Session Kills",
16661
17085
  description: "Get session kill telemetry: how many idle/TTL sessions were killed, tokens saved, and estimated cost savings over a time period.",
16662
17086
  inputSchema: {
16663
- period: z52.enum(["24h", "7d", "30d"]).default("7d").describe("Time period to query")
17087
+ period: z54.enum(["24h", "7d", "30d"]).default("7d").describe("Time period to query")
16664
17088
  }
16665
17089
  },
16666
17090
  async ({ period }) => {
@@ -16700,7 +17124,7 @@ function registerGetSessionKills(server2) {
16700
17124
 
16701
17125
  // src/mcp/tools/list-agent-sessions.ts
16702
17126
  init_session_registry();
16703
- import { z as z53 } from "zod";
17127
+ import { z as z55 } from "zod";
16704
17128
  function registerListAgentSessions(server2) {
16705
17129
  server2.registerTool(
16706
17130
  "list_agent_sessions",
@@ -16708,7 +17132,7 @@ function registerListAgentSessions(server2) {
16708
17132
  title: "List Agent Sessions",
16709
17133
  description: "List all registered agent sessions with their agent ID, project, PID, and registration time.",
16710
17134
  inputSchema: {
16711
- _placeholder: z53.string().optional().describe("No input required")
17135
+ _placeholder: z55.string().optional().describe("No input required")
16712
17136
  }
16713
17137
  },
16714
17138
  async () => {
@@ -16754,11 +17178,11 @@ function registerListAgentSessions(server2) {
16754
17178
  }
16755
17179
 
16756
17180
  // src/mcp/tools/get-daemon-health.ts
16757
- import { z as z54 } from "zod";
16758
- import { existsSync as existsSync22, readFileSync as readFileSync19 } from "fs";
16759
- import path30 from "path";
17181
+ import { z as z56 } from "zod";
17182
+ import { existsSync as existsSync23, readFileSync as readFileSync21 } from "fs";
17183
+ import path32 from "path";
16760
17184
  import { homedir as homedir3 } from "os";
16761
- var PID_PATH2 = path30.join(homedir3(), ".exe-os", "exed.pid");
17185
+ var PID_PATH2 = path32.join(homedir3(), ".exe-os", "exed.pid");
16762
17186
  function formatUptime(seconds) {
16763
17187
  const h = Math.floor(seconds / 3600);
16764
17188
  const m = Math.floor(seconds % 3600 / 60);
@@ -16769,8 +17193,8 @@ function formatUptime(seconds) {
16769
17193
  }
16770
17194
  function isDaemonAlive() {
16771
17195
  try {
16772
- if (!existsSync22(PID_PATH2)) return { alive: false, pid: null };
16773
- const pid = parseInt(readFileSync19(PID_PATH2, "utf8").trim(), 10);
17196
+ if (!existsSync23(PID_PATH2)) return { alive: false, pid: null };
17197
+ const pid = parseInt(readFileSync21(PID_PATH2, "utf8").trim(), 10);
16774
17198
  if (isNaN(pid) || pid <= 0) return { alive: false, pid: null };
16775
17199
  process.kill(pid, 0);
16776
17200
  return { alive: true, pid };
@@ -16785,7 +17209,7 @@ function registerGetDaemonHealth(server2) {
16785
17209
  title: "Get Daemon Health",
16786
17210
  description: "Check the embedding daemon (exed) health: whether it's running, its PID, uptime, and requests served.",
16787
17211
  inputSchema: {
16788
- _placeholder: z54.string().optional().describe("No input required")
17212
+ _placeholder: z56.string().optional().describe("No input required")
16789
17213
  }
16790
17214
  },
16791
17215
  async () => {
@@ -16837,14 +17261,14 @@ function registerGetDaemonHealth(server2) {
16837
17261
  // src/mcp/tools/get-auto-wake-status.ts
16838
17262
  init_database();
16839
17263
  init_session_registry();
16840
- import { z as z55 } from "zod";
17264
+ import { z as z57 } from "zod";
16841
17265
 
16842
17266
  // src/lib/daemon-orchestration.ts
16843
17267
  init_tmux_routing();
16844
17268
  init_task_scope();
16845
17269
  init_employees();
16846
17270
  import { execSync as execSync10 } from "child_process";
16847
- import { existsSync as existsSync23, readFileSync as readFileSync20, writeFileSync as writeFileSync14 } from "fs";
17271
+ import { existsSync as existsSync24, readFileSync as readFileSync22, writeFileSync as writeFileSync16 } from "fs";
16848
17272
  import { homedir as homedir4 } from "os";
16849
17273
  import { join as join2 } from "path";
16850
17274
  var IDLE_NUDGE_DEDUP_MS = Number(process.env.EXE_NUDGE_INTERVAL_MS) || 6e4;
@@ -16865,7 +17289,7 @@ function registerGetAutoWakeStatus(server2) {
16865
17289
  title: "Get Auto-Wake Status",
16866
17290
  description: "Check auto-wake status: orphaned tasks (assigned agent has no running session), tasks blocked by auto-wake retry limit, and session activity.",
16867
17291
  inputSchema: {
16868
- _placeholder: z55.string().optional().describe("No input required")
17292
+ _placeholder: z57.string().optional().describe("No input required")
16869
17293
  }
16870
17294
  },
16871
17295
  async () => {
@@ -16946,16 +17370,16 @@ function registerGetAutoWakeStatus(server2) {
16946
17370
  // src/mcp/tools/get-worker-gate.ts
16947
17371
  init_worker_gate();
16948
17372
  init_config();
16949
- import { z as z56 } from "zod";
16950
- import { readdirSync as readdirSync10, existsSync as existsSync25 } from "fs";
16951
- import path32 from "path";
16952
- var WORKER_PID_DIR2 = path32.join(EXE_AI_DIR, "worker-pids");
17373
+ import { z as z58 } from "zod";
17374
+ import { readdirSync as readdirSync10, existsSync as existsSync26 } from "fs";
17375
+ import path34 from "path";
17376
+ var WORKER_PID_DIR2 = path34.join(EXE_AI_DIR, "worker-pids");
16953
17377
  function countAliveWorkers() {
16954
17378
  let alive = 0;
16955
17379
  let stale = 0;
16956
17380
  let reservations = 0;
16957
17381
  try {
16958
- if (!existsSync25(WORKER_PID_DIR2)) return { alive: 0, stale: 0, reservations: 0 };
17382
+ if (!existsSync26(WORKER_PID_DIR2)) return { alive: 0, stale: 0, reservations: 0 };
16959
17383
  const files = readdirSync10(WORKER_PID_DIR2);
16960
17384
  for (const f of files) {
16961
17385
  if (!f.endsWith(".pid")) continue;
@@ -16984,7 +17408,7 @@ function registerGetWorkerGate(server2) {
16984
17408
  title: "Get Worker Gate",
16985
17409
  description: "Check worker concurrency gate status: how many worker slots are in use, the maximum allowed, and whether new workers can spawn.",
16986
17410
  inputSchema: {
16987
- _placeholder: z56.string().optional().describe("No input required")
17411
+ _placeholder: z58.string().optional().describe("No input required")
16988
17412
  }
16989
17413
  },
16990
17414
  async () => {
@@ -17020,12 +17444,12 @@ function registerGetWorkerGate(server2) {
17020
17444
 
17021
17445
  // src/mcp/tools/run-memory-audit.ts
17022
17446
  init_database();
17023
- import { z as z57 } from "zod";
17447
+ import { z as z59 } from "zod";
17024
17448
 
17025
17449
  // src/bin/exe-doctor.ts
17026
17450
  init_store();
17027
17451
  init_database();
17028
- import os12 from "os";
17452
+ import os13 from "os";
17029
17453
 
17030
17454
  // src/lib/is-main.ts
17031
17455
  import { realpathSync } from "fs";
@@ -17043,10 +17467,10 @@ function isMainModule(importMetaUrl) {
17043
17467
  }
17044
17468
 
17045
17469
  // src/bin/exe-doctor.ts
17046
- import { existsSync as existsSync26, readFileSync as readFileSync21 } from "fs";
17470
+ import { existsSync as existsSync27, readFileSync as readFileSync23 } from "fs";
17047
17471
  import { spawn as spawn2 } from "child_process";
17048
- import path33 from "path";
17049
- import { randomUUID as randomUUID6 } from "crypto";
17472
+ import path35 from "path";
17473
+ import { randomUUID as randomUUID7 } from "crypto";
17050
17474
 
17051
17475
  // src/lib/conflict-detector.ts
17052
17476
  var DEFAULT_MAX_PAIRS = 100;
@@ -17448,7 +17872,7 @@ async function auditOrphanedProjects(client) {
17448
17872
  for (const row of result.rows) {
17449
17873
  const name = row.project_name;
17450
17874
  const count = Number(row.cnt);
17451
- const exists = existsSync26(path33.join(home, name)) || existsSync26(path33.join(home, "..", name)) || existsSync26(path33.join(process.cwd(), "..", name));
17875
+ const exists = existsSync27(path35.join(home, name)) || existsSync27(path35.join(home, "..", name)) || existsSync27(path35.join(process.cwd(), "..", name));
17452
17876
  if (!exists) {
17453
17877
  orphans.push({ project_name: name, count });
17454
17878
  }
@@ -17456,18 +17880,18 @@ async function auditOrphanedProjects(client) {
17456
17880
  return orphans;
17457
17881
  }
17458
17882
  function auditHookHealth() {
17459
- const logPath = path33.join(
17883
+ const logPath = path35.join(
17460
17884
  process.env.HOME ?? process.env.USERPROFILE ?? "",
17461
17885
  ".exe-os",
17462
17886
  "logs",
17463
17887
  "hooks.log"
17464
17888
  );
17465
- if (!existsSync26(logPath)) {
17889
+ if (!existsSync27(logPath)) {
17466
17890
  return { logExists: false, totalLines: 0, errorsLastHour: 0, topPatterns: [] };
17467
17891
  }
17468
17892
  let content;
17469
17893
  try {
17470
- content = readFileSync21(logPath, "utf-8");
17894
+ content = readFileSync23(logPath, "utf-8");
17471
17895
  } catch {
17472
17896
  return { logExists: false, totalLines: 0, errorsLastHour: 0, topPatterns: [] };
17473
17897
  }
@@ -17542,7 +17966,7 @@ function formatReport(report, flags) {
17542
17966
  }
17543
17967
  lines.push("");
17544
17968
  }
17545
- const totalMemGB = os12.totalmem() / (1024 * 1024 * 1024);
17969
+ const totalMemGB = os13.totalmem() / (1024 * 1024 * 1024);
17546
17970
  const isLowMemSystem = totalMemGB <= 8;
17547
17971
  if (isLowMemSystem && report.nullVectors > 0) {
17548
17972
  lines.push(`\u{1F7E2} Null vectors: ${fmtNum(report.nullVectors)} / ${fmtNum(s.total)} (expected \u2014 8GB system, keyword search mode)`);
@@ -17664,7 +18088,7 @@ async function fixNullVectors() {
17664
18088
  }
17665
18089
  }
17666
18090
  const npmRoot = (await import("child_process")).execSync("npm root -g", { encoding: "utf8" }).trim();
17667
- const backfillPath = path33.join(npmRoot, "exe-os", "dist", "bin", "backfill-vectors.js");
18091
+ const backfillPath = path35.join(npmRoot, "exe-os", "dist", "bin", "backfill-vectors.js");
17668
18092
  return new Promise((resolve, reject) => {
17669
18093
  const child = spawn2("node", [backfillPath], { stdio: "inherit" });
17670
18094
  if (child.pid) registerWorkerPid2(child.pid);
@@ -17720,7 +18144,7 @@ async function fixBloated(client, bloated, dryRun) {
17720
18144
  tool_name, project_name, has_error, raw_text, vector, version, consolidated)
17721
18145
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, 0, 0)`,
17722
18146
  args: [
17723
- randomUUID6(),
18147
+ randomUUID7(),
17724
18148
  row.agent_id,
17725
18149
  row.agent_role,
17726
18150
  row.session_id,
@@ -17824,8 +18248,8 @@ function registerRunMemoryAudit(server2) {
17824
18248
  title: "Run Memory Audit",
17825
18249
  description: "Run a memory health audit: total counts, per-agent breakdown, null vectors, duplicates, FTS sync status, bloated records, and conflict detection (contradictory/superseded memories).",
17826
18250
  inputSchema: {
17827
- agent_id: z57.string().optional().describe("Filter audit to a specific agent"),
17828
- project_name: z57.string().optional().describe("Filter audit to a specific project")
18251
+ agent_id: z59.string().optional().describe("Filter audit to a specific agent"),
18252
+ project_name: z59.string().optional().describe("Filter audit to a specific project")
17829
18253
  }
17830
18254
  },
17831
18255
  async ({ agent_id, project_name }) => {
@@ -17858,13 +18282,13 @@ function registerRunMemoryAudit(server2) {
17858
18282
  }
17859
18283
 
17860
18284
  // src/mcp/tools/cloud-sync.ts
17861
- import { z as z58 } from "zod";
18285
+ import { z as z60 } from "zod";
17862
18286
 
17863
18287
  // src/lib/cloud-sync.ts
17864
18288
  init_database();
17865
- import { readFileSync as readFileSync23, writeFileSync as writeFileSync17, existsSync as existsSync28, readdirSync as readdirSync11, mkdirSync as mkdirSync14, appendFileSync as appendFileSync2, unlinkSync as unlinkSync10, openSync as openSync2, closeSync as closeSync2 } from "fs";
18289
+ import { readFileSync as readFileSync25, writeFileSync as writeFileSync19, existsSync as existsSync29, readdirSync as readdirSync11, mkdirSync as mkdirSync16, appendFileSync as appendFileSync2, unlinkSync as unlinkSync10, openSync as openSync2, closeSync as closeSync2 } from "fs";
17866
18290
  import crypto16 from "crypto";
17867
- import path35 from "path";
18291
+ import path37 from "path";
17868
18292
  import { homedir as homedir6 } from "os";
17869
18293
 
17870
18294
  // src/lib/crypto.ts
@@ -17938,7 +18362,7 @@ function sqlSafe(v) {
17938
18362
  }
17939
18363
  function logError(msg) {
17940
18364
  try {
17941
- const logPath = path35.join(homedir6(), ".exe-os", "workers.log");
18365
+ const logPath = path37.join(homedir6(), ".exe-os", "workers.log");
17942
18366
  appendFileSync2(logPath, `${(/* @__PURE__ */ new Date()).toISOString()} ${msg}
17943
18367
  `);
17944
18368
  } catch {
@@ -17947,24 +18371,24 @@ function logError(msg) {
17947
18371
  var LOCALHOST_PATTERNS = /^(localhost|127\.0\.0\.1|\[::1\])$/i;
17948
18372
  var FETCH_TIMEOUT_MS4 = 3e4;
17949
18373
  var PUSH_BATCH_SIZE = 5e3;
17950
- var ROSTER_LOCK_PATH = path35.join(EXE_AI_DIR, "roster-merge.lock");
18374
+ var ROSTER_LOCK_PATH = path37.join(EXE_AI_DIR, "roster-merge.lock");
17951
18375
  var LOCK_STALE_MS = 3e4;
17952
18376
  async function withRosterLock(fn) {
17953
18377
  try {
17954
18378
  const fd = openSync2(ROSTER_LOCK_PATH, "wx");
17955
18379
  closeSync2(fd);
17956
- writeFileSync17(ROSTER_LOCK_PATH, String(Date.now()));
18380
+ writeFileSync19(ROSTER_LOCK_PATH, String(Date.now()));
17957
18381
  } catch (err) {
17958
18382
  if (err.code === "EEXIST") {
17959
18383
  try {
17960
- const ts2 = parseInt(readFileSync23(ROSTER_LOCK_PATH, "utf-8"), 10);
18384
+ const ts2 = parseInt(readFileSync25(ROSTER_LOCK_PATH, "utf-8"), 10);
17961
18385
  if (Date.now() - ts2 < LOCK_STALE_MS) {
17962
18386
  throw new Error("Roster merge already in progress \u2014 another sync is running");
17963
18387
  }
17964
18388
  unlinkSync10(ROSTER_LOCK_PATH);
17965
18389
  const fd = openSync2(ROSTER_LOCK_PATH, "wx");
17966
18390
  closeSync2(fd);
17967
- writeFileSync17(ROSTER_LOCK_PATH, String(Date.now()));
18391
+ writeFileSync19(ROSTER_LOCK_PATH, String(Date.now()));
17968
18392
  } catch (retryErr) {
17969
18393
  if (retryErr instanceof Error && retryErr.message.includes("already in progress")) throw retryErr;
17970
18394
  throw new Error("Roster merge already in progress \u2014 another sync is running");
@@ -18338,8 +18762,8 @@ async function cloudSync(config2) {
18338
18762
  try {
18339
18763
  const employees = await loadEmployees();
18340
18764
  rosterResult.employees = employees.length;
18341
- const idDir = path35.join(EXE_AI_DIR, "identity");
18342
- if (existsSync28(idDir)) {
18765
+ const idDir = path37.join(EXE_AI_DIR, "identity");
18766
+ if (existsSync29(idDir)) {
18343
18767
  rosterResult.identities = readdirSync11(idDir).filter((f) => f.endsWith(".md")).length;
18344
18768
  }
18345
18769
  } catch {
@@ -18357,49 +18781,49 @@ async function cloudSync(config2) {
18357
18781
  roster: rosterResult
18358
18782
  };
18359
18783
  }
18360
- var ROSTER_DELETIONS_PATH = path35.join(EXE_AI_DIR, "roster-deletions.json");
18784
+ var ROSTER_DELETIONS_PATH = path37.join(EXE_AI_DIR, "roster-deletions.json");
18361
18785
  function consumeRosterDeletions() {
18362
18786
  try {
18363
- if (!existsSync28(ROSTER_DELETIONS_PATH)) return [];
18364
- const deletions = JSON.parse(readFileSync23(ROSTER_DELETIONS_PATH, "utf-8"));
18365
- writeFileSync17(ROSTER_DELETIONS_PATH, "[]");
18787
+ if (!existsSync29(ROSTER_DELETIONS_PATH)) return [];
18788
+ const deletions = JSON.parse(readFileSync25(ROSTER_DELETIONS_PATH, "utf-8"));
18789
+ writeFileSync19(ROSTER_DELETIONS_PATH, "[]");
18366
18790
  return deletions;
18367
18791
  } catch {
18368
18792
  return [];
18369
18793
  }
18370
18794
  }
18371
18795
  function buildRosterBlob(paths) {
18372
- const rosterPath = paths?.rosterPath ?? path35.join(EXE_AI_DIR, "exe-employees.json");
18373
- const identityDir = paths?.identityDir ?? path35.join(EXE_AI_DIR, "identity");
18374
- const configPath = paths?.configPath ?? path35.join(EXE_AI_DIR, "config.json");
18796
+ const rosterPath = paths?.rosterPath ?? path37.join(EXE_AI_DIR, "exe-employees.json");
18797
+ const identityDir = paths?.identityDir ?? path37.join(EXE_AI_DIR, "identity");
18798
+ const configPath = paths?.configPath ?? path37.join(EXE_AI_DIR, "config.json");
18375
18799
  let roster = [];
18376
- if (existsSync28(rosterPath)) {
18800
+ if (existsSync29(rosterPath)) {
18377
18801
  try {
18378
- roster = JSON.parse(readFileSync23(rosterPath, "utf-8"));
18802
+ roster = JSON.parse(readFileSync25(rosterPath, "utf-8"));
18379
18803
  } catch {
18380
18804
  }
18381
18805
  }
18382
18806
  const identities = {};
18383
- if (existsSync28(identityDir)) {
18807
+ if (existsSync29(identityDir)) {
18384
18808
  for (const file of readdirSync11(identityDir).filter((f) => f.endsWith(".md"))) {
18385
18809
  try {
18386
- identities[file] = readFileSync23(path35.join(identityDir, file), "utf-8");
18810
+ identities[file] = readFileSync25(path37.join(identityDir, file), "utf-8");
18387
18811
  } catch {
18388
18812
  }
18389
18813
  }
18390
18814
  }
18391
18815
  let config2;
18392
- if (existsSync28(configPath)) {
18816
+ if (existsSync29(configPath)) {
18393
18817
  try {
18394
- config2 = JSON.parse(readFileSync23(configPath, "utf-8"));
18818
+ config2 = JSON.parse(readFileSync25(configPath, "utf-8"));
18395
18819
  } catch {
18396
18820
  }
18397
18821
  }
18398
18822
  let agentConfig;
18399
- const agentConfigPath = path35.join(EXE_AI_DIR, "agent-config.json");
18400
- if (existsSync28(agentConfigPath)) {
18823
+ const agentConfigPath = path37.join(EXE_AI_DIR, "agent-config.json");
18824
+ if (existsSync29(agentConfigPath)) {
18401
18825
  try {
18402
- agentConfig = JSON.parse(readFileSync23(agentConfigPath, "utf-8"));
18826
+ agentConfig = JSON.parse(readFileSync25(agentConfigPath, "utf-8"));
18403
18827
  } catch {
18404
18828
  }
18405
18829
  }
@@ -18475,23 +18899,23 @@ async function cloudPullRoster(config2) {
18475
18899
  }
18476
18900
  }
18477
18901
  function mergeConfig(remoteConfig, configPath) {
18478
- const cfgPath = configPath ?? path35.join(EXE_AI_DIR, "config.json");
18902
+ const cfgPath = configPath ?? path37.join(EXE_AI_DIR, "config.json");
18479
18903
  let local = {};
18480
- if (existsSync28(cfgPath)) {
18904
+ if (existsSync29(cfgPath)) {
18481
18905
  try {
18482
- local = JSON.parse(readFileSync23(cfgPath, "utf-8"));
18906
+ local = JSON.parse(readFileSync25(cfgPath, "utf-8"));
18483
18907
  } catch {
18484
18908
  }
18485
18909
  }
18486
18910
  const merged = { ...remoteConfig, ...local };
18487
- const dir = path35.dirname(cfgPath);
18488
- if (!existsSync28(dir)) mkdirSync14(dir, { recursive: true });
18489
- writeFileSync17(cfgPath, JSON.stringify(merged, null, 2), "utf-8");
18911
+ const dir = path37.dirname(cfgPath);
18912
+ if (!existsSync29(dir)) mkdirSync16(dir, { recursive: true });
18913
+ writeFileSync19(cfgPath, JSON.stringify(merged, null, 2), "utf-8");
18490
18914
  }
18491
18915
  async function mergeRosterFromRemote(remote, paths) {
18492
18916
  return withRosterLock(async () => {
18493
18917
  const rosterPath = paths?.rosterPath ?? void 0;
18494
- const identityDir = paths?.identityDir ?? path35.join(EXE_AI_DIR, "identity");
18918
+ const identityDir = paths?.identityDir ?? path37.join(EXE_AI_DIR, "identity");
18495
18919
  const localEmployees = await loadEmployees(rosterPath);
18496
18920
  const localNames = new Set(localEmployees.map((e) => e.name));
18497
18921
  let added = 0;
@@ -18512,15 +18936,15 @@ async function mergeRosterFromRemote(remote, paths) {
18512
18936
  ) ?? lookupKey;
18513
18937
  const remoteIdentity = remote.identities[matchedKey];
18514
18938
  if (remoteIdentity) {
18515
- if (!existsSync28(identityDir)) mkdirSync14(identityDir, { recursive: true });
18516
- const idPath = path35.join(identityDir, `${remoteEmp.name}.md`);
18939
+ if (!existsSync29(identityDir)) mkdirSync16(identityDir, { recursive: true });
18940
+ const idPath = path37.join(identityDir, `${remoteEmp.name}.md`);
18517
18941
  let localIdentity = null;
18518
18942
  try {
18519
- localIdentity = existsSync28(idPath) ? readFileSync23(idPath, "utf-8") : null;
18943
+ localIdentity = existsSync29(idPath) ? readFileSync25(idPath, "utf-8") : null;
18520
18944
  } catch {
18521
18945
  }
18522
18946
  if (localIdentity !== remoteIdentity) {
18523
- writeFileSync17(idPath, remoteIdentity, "utf-8");
18947
+ writeFileSync19(idPath, remoteIdentity, "utf-8");
18524
18948
  identitiesUpdated++;
18525
18949
  }
18526
18950
  }
@@ -18546,16 +18970,16 @@ async function mergeRosterFromRemote(remote, paths) {
18546
18970
  }
18547
18971
  if (remote.agentConfig && Object.keys(remote.agentConfig).length > 0) {
18548
18972
  try {
18549
- const agentConfigPath = path35.join(EXE_AI_DIR, "agent-config.json");
18973
+ const agentConfigPath = path37.join(EXE_AI_DIR, "agent-config.json");
18550
18974
  let local = {};
18551
- if (existsSync28(agentConfigPath)) {
18975
+ if (existsSync29(agentConfigPath)) {
18552
18976
  try {
18553
- local = JSON.parse(readFileSync23(agentConfigPath, "utf-8"));
18977
+ local = JSON.parse(readFileSync25(agentConfigPath, "utf-8"));
18554
18978
  } catch {
18555
18979
  }
18556
18980
  }
18557
18981
  const merged = { ...remote.agentConfig, ...local };
18558
- writeFileSync17(agentConfigPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
18982
+ writeFileSync19(agentConfigPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
18559
18983
  } catch {
18560
18984
  }
18561
18985
  }
@@ -18989,7 +19413,7 @@ function registerCloudSync(server2) {
18989
19413
  title: "Cloud Sync",
18990
19414
  description: "Trigger a cloud sync cycle \u2014 pulls remote changes then pushes local. Reports pushed/pulled counts for memories, behaviors, graph, tasks, and more.",
18991
19415
  inputSchema: {
18992
- force: z58.boolean().default(false).describe("Force sync even if recently synced")
19416
+ force: z60.boolean().default(false).describe("Force sync even if recently synced")
18993
19417
  }
18994
19418
  },
18995
19419
  async () => {
@@ -19042,7 +19466,7 @@ function registerCloudSync(server2) {
19042
19466
 
19043
19467
  // src/mcp/tools/get-memory-cardinality.ts
19044
19468
  init_database();
19045
- import { z as z59 } from "zod";
19469
+ import { z as z61 } from "zod";
19046
19470
  function registerGetMemoryCardinality(server2) {
19047
19471
  server2.registerTool(
19048
19472
  "get_memory_cardinality",
@@ -19050,7 +19474,7 @@ function registerGetMemoryCardinality(server2) {
19050
19474
  title: "Get Memory Cardinality",
19051
19475
  description: "Get memory counts: total active memories and per-project breakdown. Optionally filter by agent.",
19052
19476
  inputSchema: {
19053
- agent_id: z59.string().optional().describe("Filter to a specific agent (e.g. 'tom', 'exe')")
19477
+ agent_id: z61.string().optional().describe("Filter to a specific agent (e.g. 'tom', 'exe')")
19054
19478
  }
19055
19479
  },
19056
19480
  async ({ agent_id }) => {
@@ -19133,7 +19557,7 @@ function registerGetMemoryCardinality(server2) {
19133
19557
  init_database();
19134
19558
  init_consolidation();
19135
19559
  init_config();
19136
- import { z as z60 } from "zod";
19560
+ import { z as z62 } from "zod";
19137
19561
  function registerRunConsolidation(server2) {
19138
19562
  server2.registerTool(
19139
19563
  "run_consolidation",
@@ -19141,7 +19565,7 @@ function registerRunConsolidation(server2) {
19141
19565
  title: "Run Consolidation",
19142
19566
  description: "Run memory consolidation \u2014 synthesizes unconsolidated memories into meta-insights. Use dry_run=true (default) to preview without executing.",
19143
19567
  inputSchema: {
19144
- dry_run: z60.boolean().default(true).describe("Preview mode \u2014 show what would be consolidated without doing it")
19568
+ dry_run: z62.boolean().default(true).describe("Preview mode \u2014 show what would be consolidated without doing it")
19145
19569
  }
19146
19570
  },
19147
19571
  async ({ dry_run }) => {
@@ -19210,7 +19634,7 @@ function registerRunConsolidation(server2) {
19210
19634
 
19211
19635
  // src/mcp/tools/get-license-status.ts
19212
19636
  init_license();
19213
- import { z as z61 } from "zod";
19637
+ import { z as z63 } from "zod";
19214
19638
  var FEATURES = [
19215
19639
  "cloud_sync",
19216
19640
  "external_agents",
@@ -19224,7 +19648,7 @@ function registerGetLicenseStatus(server2) {
19224
19648
  title: "Get License Status",
19225
19649
  description: "Get current license status: plan, validity, feature gates, limits, and expiry.",
19226
19650
  inputSchema: {
19227
- _dummy: z61.string().optional().describe("Unused \u2014 no input required")
19651
+ _dummy: z63.string().optional().describe("Unused \u2014 no input required")
19228
19652
  }
19229
19653
  },
19230
19654
  async () => {
@@ -19276,16 +19700,16 @@ function registerGetLicenseStatus(server2) {
19276
19700
  }
19277
19701
 
19278
19702
  // src/mcp/tools/people-roster.ts
19279
- import { z as z62 } from "zod";
19703
+ import { z as z64 } from "zod";
19280
19704
 
19281
19705
  // src/lib/people.ts
19282
19706
  init_config();
19283
19707
  import { readFile as readFile5, writeFile as writeFile6, mkdir as mkdir5 } from "fs/promises";
19284
- import { existsSync as existsSync29, readFileSync as readFileSync24 } from "fs";
19285
- import path36 from "path";
19286
- var PEOPLE_PATH = path36.join(EXE_AI_DIR, "people.json");
19708
+ import { existsSync as existsSync30, readFileSync as readFileSync26 } from "fs";
19709
+ import path38 from "path";
19710
+ var PEOPLE_PATH = path38.join(EXE_AI_DIR, "people.json");
19287
19711
  async function loadPeople() {
19288
- if (!existsSync29(PEOPLE_PATH)) return [];
19712
+ if (!existsSync30(PEOPLE_PATH)) return [];
19289
19713
  try {
19290
19714
  const raw = await readFile5(PEOPLE_PATH, "utf-8");
19291
19715
  return JSON.parse(raw);
@@ -19294,7 +19718,7 @@ async function loadPeople() {
19294
19718
  }
19295
19719
  }
19296
19720
  async function savePeople(people) {
19297
- await mkdir5(path36.dirname(PEOPLE_PATH), { recursive: true });
19721
+ await mkdir5(path38.dirname(PEOPLE_PATH), { recursive: true });
19298
19722
  await writeFile6(PEOPLE_PATH, JSON.stringify(people, null, 2) + "\n", "utf-8");
19299
19723
  }
19300
19724
  async function addPerson(person) {
@@ -19324,10 +19748,10 @@ function registerAddPerson(server2) {
19324
19748
  title: "Add Person",
19325
19749
  description: "Add or update a key human in the people roster. Used for co-founders, partners, customers \u2014 anyone agents need to know about.",
19326
19750
  inputSchema: {
19327
- name: z62.string().describe("Person's name"),
19328
- role: z62.string().describe("Their role (e.g. co-founder, customer, partner)"),
19329
- relationship: z62.string().describe("Relationship to the organization (e.g. co-founder, early adopter, investor)"),
19330
- notes: z62.string().optional().describe("Additional context about this person")
19751
+ name: z64.string().describe("Person's name"),
19752
+ role: z64.string().describe("Their role (e.g. co-founder, customer, partner)"),
19753
+ relationship: z64.string().describe("Relationship to the organization (e.g. co-founder, early adopter, investor)"),
19754
+ notes: z64.string().optional().describe("Additional context about this person")
19331
19755
  }
19332
19756
  },
19333
19757
  async ({ name, role, relationship, notes }) => {
@@ -19373,7 +19797,7 @@ function registerGetPerson(server2) {
19373
19797
  title: "Get Person",
19374
19798
  description: "Look up a specific person by name from the people roster.",
19375
19799
  inputSchema: {
19376
- name: z62.string().describe("Person's name to look up")
19800
+ name: z64.string().describe("Person's name to look up")
19377
19801
  }
19378
19802
  },
19379
19803
  async ({ name }) => {
@@ -19401,7 +19825,7 @@ init_active_agent();
19401
19825
  init_agent_config();
19402
19826
  init_runtime_table();
19403
19827
  init_employees();
19404
- import { z as z63 } from "zod";
19828
+ import { z as z65 } from "zod";
19405
19829
  function registerSetAgentConfig(server2) {
19406
19830
  server2.registerTool(
19407
19831
  "set_agent_config",
@@ -19409,9 +19833,9 @@ function registerSetAgentConfig(server2) {
19409
19833
  title: "Set Agent Config",
19410
19834
  description: "Set or view per-agent runtime + model configuration. Controls which runtime (claude, codex, opencode) and model each agent uses when dispatched. COO-only. Omit runtime/model to view current config for an agent or all agents.",
19411
19835
  inputSchema: {
19412
- agent_id: z63.string().optional().describe("Agent name, or 'default' for org-wide default. Omit to view all agents."),
19413
- runtime: z63.string().optional().describe(`Runtime: ${Object.keys(KNOWN_RUNTIMES).join(", ")}`),
19414
- model: z63.string().optional().describe("Model name (e.g. claude-opus-4, gpt-5.4, anthropic/claude-sonnet-4-6)")
19836
+ agent_id: z65.string().optional().describe("Agent name, or 'default' for org-wide default. Omit to view all agents."),
19837
+ runtime: z65.string().optional().describe(`Runtime: ${Object.keys(KNOWN_RUNTIMES).join(", ")}`),
19838
+ model: z65.string().optional().describe("Model name (e.g. claude-opus-4, gpt-5.4, anthropic/claude-sonnet-4-6)")
19415
19839
  }
19416
19840
  },
19417
19841
  async ({ agent_id, runtime, model }) => {
@@ -19604,6 +20028,8 @@ registerListWikiPages(server);
19604
20028
  registerGetWikiPage(server);
19605
20029
  registerUpdateWikiPage(server);
19606
20030
  registerDeployClient(server);
20031
+ registerExportOrchestration(server);
20032
+ registerImportOrchestration(server);
19607
20033
  registerQueryConversations(server);
19608
20034
  registerLoadSkill(server);
19609
20035
  registerConsolidateMemories(server);
@@ -19695,14 +20121,14 @@ try {
19695
20121
  `
19696
20122
  );
19697
20123
  const thisFile = fileURLToPath5(import.meta.url);
19698
- const backfillPath = path37.resolve(
19699
- path37.dirname(thisFile),
20124
+ const backfillPath = path39.resolve(
20125
+ path39.dirname(thisFile),
19700
20126
  "../bin/backfill-vectors.js"
19701
20127
  );
19702
- if (existsSync30(backfillPath)) {
20128
+ if (existsSync31(backfillPath)) {
19703
20129
  const { EXE_AI_DIR: exeDir } = await Promise.resolve().then(() => (init_config(), config_exports));
19704
- const logPath = path37.join(exeDir, "workers.log");
19705
- mkdirSync15(path37.dirname(logPath), { recursive: true });
20130
+ const logPath = path39.join(exeDir, "workers.log");
20131
+ mkdirSync17(path39.dirname(logPath), { recursive: true });
19706
20132
  let logFd = "ignore";
19707
20133
  try {
19708
20134
  logFd = openSync3(logPath, "a");