@askexenow/exe-os 0.9.112 → 0.9.113
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/README.md +9 -7
- package/dist/bin/agentic-ontology-backfill.js +54 -11
- package/dist/bin/agentic-reflection-backfill.js +29 -1
- package/dist/bin/agentic-semantic-label.js +29 -1
- package/dist/bin/backfill-conversations.js +53 -10
- package/dist/bin/backfill-responses.js +54 -11
- package/dist/bin/backfill-vectors.js +29 -1
- package/dist/bin/bulk-sync-postgres.js +55 -12
- package/dist/bin/cleanup-stale-review-tasks.js +75 -15
- package/dist/bin/cli.js +293 -76
- package/dist/bin/exe-agent-config.js +7 -1
- package/dist/bin/exe-agent.js +28 -2
- package/dist/bin/exe-assign.js +54 -11
- package/dist/bin/exe-boot.js +481 -147
- package/dist/bin/exe-call.js +45 -4
- package/dist/bin/exe-cloud.js +93 -15
- package/dist/bin/exe-dispatch.js +369 -24
- package/dist/bin/exe-doctor.js +53 -10
- package/dist/bin/exe-export-behaviors.js +54 -11
- package/dist/bin/exe-forget.js +54 -11
- package/dist/bin/exe-gateway.js +128 -23
- package/dist/bin/exe-heartbeat.js +75 -15
- package/dist/bin/exe-kill.js +54 -11
- package/dist/bin/exe-launch-agent.js +70 -12
- package/dist/bin/exe-new-employee.js +175 -7
- package/dist/bin/exe-pending-messages.js +75 -15
- package/dist/bin/exe-pending-notifications.js +75 -15
- package/dist/bin/exe-pending-reviews.js +75 -15
- package/dist/bin/exe-rename.js +54 -11
- package/dist/bin/exe-review.js +54 -11
- package/dist/bin/exe-search.js +54 -11
- package/dist/bin/exe-session-cleanup.js +491 -146
- package/dist/bin/exe-settings.js +10 -4
- package/dist/bin/exe-start-codex.js +524 -245
- package/dist/bin/exe-start-opencode.js +534 -165
- package/dist/bin/exe-status.js +75 -15
- package/dist/bin/exe-support.js +1 -1
- package/dist/bin/exe-team.js +54 -11
- package/dist/bin/git-sweep.js +369 -24
- package/dist/bin/graph-backfill.js +54 -11
- package/dist/bin/graph-export.js +54 -11
- package/dist/bin/install.js +62 -4
- package/dist/bin/intercom-check.js +491 -146
- package/dist/bin/pre-publish.js +13 -1
- package/dist/bin/scan-tasks.js +369 -24
- package/dist/bin/setup.js +91 -13
- package/dist/bin/shard-migrate.js +54 -11
- package/dist/bin/stack-update.js +1 -1
- package/dist/bin/update.js +3 -3
- package/dist/gateway/index.js +128 -23
- package/dist/hooks/bug-report-worker.js +128 -23
- package/dist/hooks/codex-stop-task-finalizer.js +512 -140
- package/dist/hooks/commit-complete.js +369 -24
- package/dist/hooks/error-recall.js +54 -11
- package/dist/hooks/ingest.js +4575 -252
- package/dist/hooks/instructions-loaded.js +54 -11
- package/dist/hooks/notification.js +54 -11
- package/dist/hooks/post-compact.js +75 -15
- package/dist/hooks/post-tool-combined.js +75 -15
- package/dist/hooks/pre-compact.js +449 -104
- package/dist/hooks/pre-tool-use.js +90 -15
- package/dist/hooks/prompt-submit.js +129 -24
- package/dist/hooks/session-end.js +451 -109
- package/dist/hooks/session-start.js +104 -16
- package/dist/hooks/stop.js +74 -14
- package/dist/hooks/subagent-stop.js +75 -15
- package/dist/hooks/summary-worker.js +73 -7
- package/dist/index.js +128 -23
- package/dist/lib/agent-config.js +16 -1
- package/dist/lib/cloud-sync.js +38 -1
- package/dist/lib/consolidation.js +16 -1
- package/dist/lib/database.js +16 -0
- package/dist/lib/db.js +16 -0
- package/dist/lib/device-registry.js +16 -0
- package/dist/lib/employee-templates.js +29 -3
- package/dist/lib/employees.js +16 -1
- package/dist/lib/exe-daemon.js +268 -42
- package/dist/lib/hybrid-search.js +54 -11
- package/dist/lib/license.js +3 -3
- package/dist/lib/messaging.js +21 -4
- package/dist/lib/schedules.js +29 -1
- package/dist/lib/skill-learning.js +458 -70
- package/dist/lib/status-brief.js +14 -1
- package/dist/lib/store.js +54 -11
- package/dist/lib/tasks.js +393 -91
- package/dist/lib/tmux-routing.js +316 -14
- package/dist/mcp/server.js +169 -30
- package/dist/mcp/tools/create-task.js +75 -13
- package/dist/mcp/tools/deactivate-behavior.js +33 -24
- package/dist/mcp/tools/list-tasks.js +21 -4
- package/dist/mcp/tools/send-message.js +21 -4
- package/dist/mcp/tools/update-task.js +390 -91
- package/dist/runtime/index.js +446 -101
- package/dist/tui/App.js +208 -54
- package/package.json +1 -1
|
@@ -319,6 +319,394 @@ var init_config = __esm({
|
|
|
319
319
|
}
|
|
320
320
|
});
|
|
321
321
|
|
|
322
|
+
// src/lib/runtime-table.ts
|
|
323
|
+
var RUNTIME_TABLE, DEFAULT_RUNTIME;
|
|
324
|
+
var init_runtime_table = __esm({
|
|
325
|
+
"src/lib/runtime-table.ts"() {
|
|
326
|
+
"use strict";
|
|
327
|
+
RUNTIME_TABLE = {
|
|
328
|
+
codex: {
|
|
329
|
+
binary: "codex",
|
|
330
|
+
launchMode: "interactive",
|
|
331
|
+
autoApproveFlag: "--dangerously-bypass-approvals-and-sandbox",
|
|
332
|
+
inlineFlag: "--no-alt-screen",
|
|
333
|
+
apiKeyEnv: "OPENAI_API_KEY",
|
|
334
|
+
defaultModel: "gpt-5.5"
|
|
335
|
+
},
|
|
336
|
+
opencode: {
|
|
337
|
+
binary: "opencode",
|
|
338
|
+
launchMode: "exec",
|
|
339
|
+
autoApproveFlag: "--dangerously-skip-permissions",
|
|
340
|
+
inlineFlag: "",
|
|
341
|
+
apiKeyEnv: "ANTHROPIC_API_KEY",
|
|
342
|
+
defaultModel: "anthropic/claude-sonnet-4-6"
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
DEFAULT_RUNTIME = "claude";
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
// src/lib/agent-config.ts
|
|
350
|
+
var agent_config_exports = {};
|
|
351
|
+
__export(agent_config_exports, {
|
|
352
|
+
AGENT_CONFIG_PATH: () => AGENT_CONFIG_PATH,
|
|
353
|
+
DEFAULT_MODELS: () => DEFAULT_MODELS,
|
|
354
|
+
KNOWN_RUNTIMES: () => KNOWN_RUNTIMES,
|
|
355
|
+
RUNTIME_LABELS: () => RUNTIME_LABELS,
|
|
356
|
+
clearAgentRuntime: () => clearAgentRuntime,
|
|
357
|
+
getAgentRuntime: () => getAgentRuntime,
|
|
358
|
+
loadAgentConfig: () => loadAgentConfig,
|
|
359
|
+
saveAgentConfig: () => saveAgentConfig,
|
|
360
|
+
setAgentMcps: () => setAgentMcps,
|
|
361
|
+
setAgentRuntime: () => setAgentRuntime
|
|
362
|
+
});
|
|
363
|
+
import { readFileSync as readFileSync2, writeFileSync, existsSync as existsSync3 } from "fs";
|
|
364
|
+
import path2 from "path";
|
|
365
|
+
function loadAgentConfig() {
|
|
366
|
+
if (!existsSync3(AGENT_CONFIG_PATH)) return {};
|
|
367
|
+
try {
|
|
368
|
+
return JSON.parse(readFileSync2(AGENT_CONFIG_PATH, "utf-8"));
|
|
369
|
+
} catch {
|
|
370
|
+
return {};
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
function saveAgentConfig(config) {
|
|
374
|
+
const dir = path2.dirname(AGENT_CONFIG_PATH);
|
|
375
|
+
ensurePrivateDirSync(dir);
|
|
376
|
+
writeFileSync(AGENT_CONFIG_PATH, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
377
|
+
enforcePrivateFileSync(AGENT_CONFIG_PATH);
|
|
378
|
+
}
|
|
379
|
+
function getAgentRuntime(agentId) {
|
|
380
|
+
const config = loadAgentConfig();
|
|
381
|
+
const entry = config[agentId];
|
|
382
|
+
if (entry) return entry;
|
|
383
|
+
const orgDefault = config["default"];
|
|
384
|
+
if (orgDefault) return orgDefault;
|
|
385
|
+
return { runtime: DEFAULT_RUNTIME, model: DEFAULT_MODELS[DEFAULT_RUNTIME] };
|
|
386
|
+
}
|
|
387
|
+
function setAgentRuntime(agentId, runtime, model, reasoning_effort, mcps) {
|
|
388
|
+
const knownModels = KNOWN_RUNTIMES[runtime];
|
|
389
|
+
if (!knownModels) {
|
|
390
|
+
return {
|
|
391
|
+
ok: false,
|
|
392
|
+
error: `Unknown runtime "${runtime}". Valid: ${Object.keys(KNOWN_RUNTIMES).join(", ")}`
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
if (!knownModels.includes(model)) {
|
|
396
|
+
return {
|
|
397
|
+
ok: false,
|
|
398
|
+
error: `Unknown model "${model}" for runtime "${runtime}". Valid: ${knownModels.join(", ")}`
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
const config = loadAgentConfig();
|
|
402
|
+
const existing = config[agentId];
|
|
403
|
+
const entry = { runtime, model };
|
|
404
|
+
if (reasoning_effort) entry.reasoning_effort = reasoning_effort;
|
|
405
|
+
if (mcps !== void 0) {
|
|
406
|
+
entry.mcps = mcps.includes("exe-os") ? mcps : ["exe-os", ...mcps];
|
|
407
|
+
} else if (existing?.mcps) {
|
|
408
|
+
entry.mcps = existing.mcps;
|
|
409
|
+
}
|
|
410
|
+
config[agentId] = entry;
|
|
411
|
+
saveAgentConfig(config);
|
|
412
|
+
return { ok: true };
|
|
413
|
+
}
|
|
414
|
+
function setAgentMcps(agentId, mcps) {
|
|
415
|
+
const config = loadAgentConfig();
|
|
416
|
+
const existing = config[agentId] ?? getAgentRuntime(agentId);
|
|
417
|
+
existing.mcps = mcps.includes("exe-os") ? mcps : ["exe-os", ...mcps];
|
|
418
|
+
config[agentId] = existing;
|
|
419
|
+
saveAgentConfig(config);
|
|
420
|
+
return { ok: true };
|
|
421
|
+
}
|
|
422
|
+
function clearAgentRuntime(agentId) {
|
|
423
|
+
const config = loadAgentConfig();
|
|
424
|
+
delete config[agentId];
|
|
425
|
+
saveAgentConfig(config);
|
|
426
|
+
}
|
|
427
|
+
var AGENT_CONFIG_PATH, KNOWN_RUNTIMES, RUNTIME_LABELS, DEFAULT_MODELS;
|
|
428
|
+
var init_agent_config = __esm({
|
|
429
|
+
"src/lib/agent-config.ts"() {
|
|
430
|
+
"use strict";
|
|
431
|
+
init_config();
|
|
432
|
+
init_runtime_table();
|
|
433
|
+
init_secure_files();
|
|
434
|
+
AGENT_CONFIG_PATH = path2.join(EXE_AI_DIR, "agent-config.json");
|
|
435
|
+
KNOWN_RUNTIMES = {
|
|
436
|
+
claude: ["claude-opus-4.6", "claude-opus-4", "claude-sonnet-4.6", "claude-sonnet-4", "claude-haiku-4.5"],
|
|
437
|
+
codex: ["gpt-5.4", "gpt-5.5", "gpt-5.3-codex-spark", "o3", "o4-mini"],
|
|
438
|
+
opencode: ["anthropic/claude-sonnet-4-6", "openai/gpt-5.4", "google/gemini-2.5-pro", "deepseek/deepseek-r3", "minimax/minimax-m2.5"]
|
|
439
|
+
};
|
|
440
|
+
RUNTIME_LABELS = {
|
|
441
|
+
claude: "Claude Code (Anthropic)",
|
|
442
|
+
codex: "Codex (OpenAI)",
|
|
443
|
+
opencode: "OpenCode (open source)"
|
|
444
|
+
};
|
|
445
|
+
DEFAULT_MODELS = {
|
|
446
|
+
claude: "claude-opus-4.6",
|
|
447
|
+
codex: RUNTIME_TABLE.codex?.defaultModel ?? "gpt-5.4",
|
|
448
|
+
opencode: RUNTIME_TABLE.opencode?.defaultModel ?? "anthropic/claude-sonnet-4-6"
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
// src/lib/employees.ts
|
|
454
|
+
var employees_exports = {};
|
|
455
|
+
__export(employees_exports, {
|
|
456
|
+
COORDINATOR_ROLE: () => COORDINATOR_ROLE,
|
|
457
|
+
DEFAULT_COORDINATOR_TEMPLATE_NAME: () => DEFAULT_COORDINATOR_TEMPLATE_NAME,
|
|
458
|
+
EMPLOYEES_PATH: () => EMPLOYEES_PATH,
|
|
459
|
+
addEmployee: () => addEmployee,
|
|
460
|
+
baseAgentName: () => baseAgentName,
|
|
461
|
+
canCoordinate: () => canCoordinate,
|
|
462
|
+
getCoordinatorEmployee: () => getCoordinatorEmployee,
|
|
463
|
+
getCoordinatorName: () => getCoordinatorName,
|
|
464
|
+
getEmployee: () => getEmployee,
|
|
465
|
+
getEmployeeByRole: () => getEmployeeByRole,
|
|
466
|
+
getEmployeeNamesByRole: () => getEmployeeNamesByRole,
|
|
467
|
+
hasRole: () => hasRole,
|
|
468
|
+
hireEmployee: () => hireEmployee,
|
|
469
|
+
isCoordinatorName: () => isCoordinatorName,
|
|
470
|
+
isCoordinatorRole: () => isCoordinatorRole,
|
|
471
|
+
isMultiInstance: () => isMultiInstance,
|
|
472
|
+
loadEmployees: () => loadEmployees,
|
|
473
|
+
loadEmployeesSync: () => loadEmployeesSync,
|
|
474
|
+
normalizeRole: () => normalizeRole,
|
|
475
|
+
normalizeRosterCase: () => normalizeRosterCase,
|
|
476
|
+
registerBinSymlinks: () => registerBinSymlinks,
|
|
477
|
+
saveEmployees: () => saveEmployees,
|
|
478
|
+
validateEmployeeName: () => validateEmployeeName
|
|
479
|
+
});
|
|
480
|
+
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
481
|
+
import { existsSync as existsSync4, symlinkSync, readlinkSync, readFileSync as readFileSync3, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
|
|
482
|
+
import { execSync } from "child_process";
|
|
483
|
+
import path3 from "path";
|
|
484
|
+
import os2 from "os";
|
|
485
|
+
function normalizeRole(role) {
|
|
486
|
+
return (role ?? "").trim().toLowerCase();
|
|
487
|
+
}
|
|
488
|
+
function isCoordinatorRole(role) {
|
|
489
|
+
return normalizeRole(role) === normalizeRole(COORDINATOR_ROLE);
|
|
490
|
+
}
|
|
491
|
+
function getCoordinatorEmployee(employees) {
|
|
492
|
+
return employees.find((e) => isCoordinatorRole(e.role));
|
|
493
|
+
}
|
|
494
|
+
function getCoordinatorName(employees = loadEmployeesSync()) {
|
|
495
|
+
return getCoordinatorEmployee(employees)?.name ?? DEFAULT_COORDINATOR_TEMPLATE_NAME;
|
|
496
|
+
}
|
|
497
|
+
function isCoordinatorName(agentName, employees = loadEmployeesSync()) {
|
|
498
|
+
if (!agentName) return false;
|
|
499
|
+
return agentName.toLowerCase() === getCoordinatorName(employees).toLowerCase();
|
|
500
|
+
}
|
|
501
|
+
function canCoordinate(agentName, agentRole, employees = loadEmployeesSync()) {
|
|
502
|
+
return agentName === "default" || isCoordinatorRole(agentRole) || isCoordinatorName(agentName, employees);
|
|
503
|
+
}
|
|
504
|
+
function validateEmployeeName(name) {
|
|
505
|
+
if (!name) {
|
|
506
|
+
return { valid: false, error: "Name is required" };
|
|
507
|
+
}
|
|
508
|
+
if (name.length > 32) {
|
|
509
|
+
return { valid: false, error: "Name must be 32 characters or fewer" };
|
|
510
|
+
}
|
|
511
|
+
if (!/^[a-z][a-z0-9]*$/.test(name)) {
|
|
512
|
+
return {
|
|
513
|
+
valid: false,
|
|
514
|
+
error: "Name must start with a letter and contain only lowercase alphanumeric characters"
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
return { valid: true };
|
|
518
|
+
}
|
|
519
|
+
async function loadEmployees(employeesPath = EMPLOYEES_PATH) {
|
|
520
|
+
if (!existsSync4(employeesPath)) {
|
|
521
|
+
return [];
|
|
522
|
+
}
|
|
523
|
+
const raw = await readFile2(employeesPath, "utf-8");
|
|
524
|
+
try {
|
|
525
|
+
return JSON.parse(raw);
|
|
526
|
+
} catch {
|
|
527
|
+
return [];
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
async function saveEmployees(employees, employeesPath = EMPLOYEES_PATH) {
|
|
531
|
+
await mkdir2(path3.dirname(employeesPath), { recursive: true });
|
|
532
|
+
await writeFile2(employeesPath, JSON.stringify(employees, null, 2) + "\n", "utf-8");
|
|
533
|
+
}
|
|
534
|
+
function loadEmployeesSync(employeesPath = EMPLOYEES_PATH) {
|
|
535
|
+
if (!existsSync4(employeesPath)) return [];
|
|
536
|
+
try {
|
|
537
|
+
return JSON.parse(readFileSync3(employeesPath, "utf-8"));
|
|
538
|
+
} catch {
|
|
539
|
+
return [];
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
function getEmployee(employees, name) {
|
|
543
|
+
return employees.find((e) => e.name.toLowerCase() === name.toLowerCase());
|
|
544
|
+
}
|
|
545
|
+
function getEmployeeByRole(employees, role) {
|
|
546
|
+
const lower = role.toLowerCase();
|
|
547
|
+
return employees.find((e) => e.role.toLowerCase() === lower);
|
|
548
|
+
}
|
|
549
|
+
function getEmployeeNamesByRole(employees, role) {
|
|
550
|
+
const lower = role.toLowerCase();
|
|
551
|
+
return employees.filter((e) => e.role.toLowerCase() === lower).map((e) => e.name);
|
|
552
|
+
}
|
|
553
|
+
function hasRole(agentName, role) {
|
|
554
|
+
const employees = loadEmployeesSync();
|
|
555
|
+
const emp = getEmployee(employees, agentName);
|
|
556
|
+
return emp ? emp.role.toLowerCase() === role.toLowerCase() : false;
|
|
557
|
+
}
|
|
558
|
+
function baseAgentName(name, employees) {
|
|
559
|
+
const match = name.match(/^([a-zA-Z]+)\d+$/);
|
|
560
|
+
if (!match) return name;
|
|
561
|
+
const base = match[1];
|
|
562
|
+
const roster = employees ?? loadEmployeesSync();
|
|
563
|
+
if (getEmployee(roster, base)) return base;
|
|
564
|
+
return name;
|
|
565
|
+
}
|
|
566
|
+
function isMultiInstance(agentName, employees) {
|
|
567
|
+
const roster = employees ?? loadEmployeesSync();
|
|
568
|
+
const emp = getEmployee(roster, agentName);
|
|
569
|
+
if (!emp) return false;
|
|
570
|
+
return MULTI_INSTANCE_ROLES.has(emp.role.toLowerCase());
|
|
571
|
+
}
|
|
572
|
+
function addEmployee(employees, employee) {
|
|
573
|
+
const { systemPrompt: _legacyPrompt, ...rest } = employee;
|
|
574
|
+
const normalized = { ...rest, name: employee.name.toLowerCase() };
|
|
575
|
+
if (employees.some((e) => e.name.toLowerCase() === normalized.name)) {
|
|
576
|
+
throw new Error(`Employee '${normalized.name}' already exists`);
|
|
577
|
+
}
|
|
578
|
+
return [...employees, normalized];
|
|
579
|
+
}
|
|
580
|
+
function appendToCoordinatorTeam(employee) {
|
|
581
|
+
const coordinator = getCoordinatorEmployee(loadEmployeesSync());
|
|
582
|
+
if (!coordinator) return;
|
|
583
|
+
const idPath = path3.join(IDENTITY_DIR, `${coordinator.name}.md`);
|
|
584
|
+
if (!existsSync4(idPath)) return;
|
|
585
|
+
const content = readFileSync3(idPath, "utf-8");
|
|
586
|
+
if (content.includes(`**${capitalize(employee.name)}`)) return;
|
|
587
|
+
const teamMatch = content.match(TEAM_SECTION_RE);
|
|
588
|
+
if (!teamMatch || teamMatch.index === void 0) return;
|
|
589
|
+
const afterTeam = content.slice(teamMatch.index + teamMatch[0].length);
|
|
590
|
+
const nextHeading = afterTeam.match(/\n## /);
|
|
591
|
+
const entry = `
|
|
592
|
+
**${capitalize(employee.name)} (${employee.role}):** Newly hired. Update this description as the role develops.
|
|
593
|
+
`;
|
|
594
|
+
let updated;
|
|
595
|
+
if (nextHeading && nextHeading.index !== void 0) {
|
|
596
|
+
const insertAt = teamMatch.index + teamMatch[0].length + nextHeading.index;
|
|
597
|
+
updated = content.slice(0, insertAt) + entry + content.slice(insertAt);
|
|
598
|
+
} else {
|
|
599
|
+
updated = content.trimEnd() + "\n" + entry;
|
|
600
|
+
}
|
|
601
|
+
writeFileSync2(idPath, updated, "utf-8");
|
|
602
|
+
}
|
|
603
|
+
function capitalize(s) {
|
|
604
|
+
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
605
|
+
}
|
|
606
|
+
async function hireEmployee(employee) {
|
|
607
|
+
const employees = await loadEmployees();
|
|
608
|
+
const updated = addEmployee(employees, employee);
|
|
609
|
+
await saveEmployees(updated);
|
|
610
|
+
try {
|
|
611
|
+
appendToCoordinatorTeam(employee);
|
|
612
|
+
} catch {
|
|
613
|
+
}
|
|
614
|
+
try {
|
|
615
|
+
const { loadAgentConfig: loadAgentConfig2, saveAgentConfig: saveAgentConfig2 } = await Promise.resolve().then(() => (init_agent_config(), agent_config_exports));
|
|
616
|
+
const config = loadAgentConfig2();
|
|
617
|
+
const name = employee.name.toLowerCase();
|
|
618
|
+
if (!config[name] && config["default"]) {
|
|
619
|
+
config[name] = { ...config["default"] };
|
|
620
|
+
saveAgentConfig2(config);
|
|
621
|
+
}
|
|
622
|
+
} catch {
|
|
623
|
+
}
|
|
624
|
+
return updated;
|
|
625
|
+
}
|
|
626
|
+
async function normalizeRosterCase(rosterPath) {
|
|
627
|
+
const employees = await loadEmployees(rosterPath);
|
|
628
|
+
let changed = false;
|
|
629
|
+
for (const emp of employees) {
|
|
630
|
+
if (emp.name !== emp.name.toLowerCase()) {
|
|
631
|
+
const oldName = emp.name;
|
|
632
|
+
emp.name = emp.name.toLowerCase();
|
|
633
|
+
changed = true;
|
|
634
|
+
try {
|
|
635
|
+
const identityDir = path3.join(os2.homedir(), ".exe-os", "identity");
|
|
636
|
+
const oldPath = path3.join(identityDir, `${oldName}.md`);
|
|
637
|
+
const newPath = path3.join(identityDir, `${emp.name}.md`);
|
|
638
|
+
if (existsSync4(oldPath) && !existsSync4(newPath)) {
|
|
639
|
+
renameSync2(oldPath, newPath);
|
|
640
|
+
} else if (existsSync4(oldPath) && oldPath !== newPath) {
|
|
641
|
+
const content = readFileSync3(oldPath, "utf-8");
|
|
642
|
+
writeFileSync2(newPath, content, "utf-8");
|
|
643
|
+
if (oldPath.toLowerCase() !== newPath.toLowerCase()) {
|
|
644
|
+
unlinkSync(oldPath);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
} catch {
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
if (changed) {
|
|
652
|
+
await saveEmployees(employees, rosterPath);
|
|
653
|
+
}
|
|
654
|
+
return changed;
|
|
655
|
+
}
|
|
656
|
+
function findExeBin() {
|
|
657
|
+
try {
|
|
658
|
+
return execSync(process.platform === "win32" ? "where exe-os" : "which exe-os", { encoding: "utf8" }).trim();
|
|
659
|
+
} catch {
|
|
660
|
+
return null;
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
function registerBinSymlinks(name) {
|
|
664
|
+
const created = [];
|
|
665
|
+
const skipped = [];
|
|
666
|
+
const errors = [];
|
|
667
|
+
const exeBinPath = findExeBin();
|
|
668
|
+
if (!exeBinPath) {
|
|
669
|
+
errors.push("Could not find 'exe-os' in PATH");
|
|
670
|
+
return { created, skipped, errors };
|
|
671
|
+
}
|
|
672
|
+
const binDir = path3.dirname(exeBinPath);
|
|
673
|
+
let target;
|
|
674
|
+
try {
|
|
675
|
+
target = readlinkSync(exeBinPath);
|
|
676
|
+
} catch {
|
|
677
|
+
errors.push("Could not read 'exe' symlink");
|
|
678
|
+
return { created, skipped, errors };
|
|
679
|
+
}
|
|
680
|
+
for (const suffix of ["", "-opencode"]) {
|
|
681
|
+
const linkName = `${name}${suffix}`;
|
|
682
|
+
const linkPath = path3.join(binDir, linkName);
|
|
683
|
+
if (existsSync4(linkPath)) {
|
|
684
|
+
skipped.push(linkName);
|
|
685
|
+
continue;
|
|
686
|
+
}
|
|
687
|
+
try {
|
|
688
|
+
symlinkSync(target, linkPath);
|
|
689
|
+
created.push(linkName);
|
|
690
|
+
} catch (err) {
|
|
691
|
+
errors.push(`${linkName}: ${err instanceof Error ? err.message : String(err)}`);
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
return { created, skipped, errors };
|
|
695
|
+
}
|
|
696
|
+
var EMPLOYEES_PATH, DEFAULT_COORDINATOR_TEMPLATE_NAME, COORDINATOR_ROLE, MULTI_INSTANCE_ROLES, IDENTITY_DIR, TEAM_SECTION_RE;
|
|
697
|
+
var init_employees = __esm({
|
|
698
|
+
"src/lib/employees.ts"() {
|
|
699
|
+
"use strict";
|
|
700
|
+
init_config();
|
|
701
|
+
EMPLOYEES_PATH = path3.join(EXE_AI_DIR, "exe-employees.json");
|
|
702
|
+
DEFAULT_COORDINATOR_TEMPLATE_NAME = "exe";
|
|
703
|
+
COORDINATOR_ROLE = "COO";
|
|
704
|
+
MULTI_INSTANCE_ROLES = /* @__PURE__ */ new Set(["principal engineer", "content production specialist", "staff code reviewer"]);
|
|
705
|
+
IDENTITY_DIR = path3.join(EXE_AI_DIR, "identity");
|
|
706
|
+
TEAM_SECTION_RE = /^## Team\b.*$/m;
|
|
707
|
+
}
|
|
708
|
+
});
|
|
709
|
+
|
|
322
710
|
// src/types/memory.ts
|
|
323
711
|
var EMBEDDING_DIM;
|
|
324
712
|
var init_memory = __esm({
|
|
@@ -330,8 +718,8 @@ var init_memory = __esm({
|
|
|
330
718
|
|
|
331
719
|
// src/lib/daemon-auth.ts
|
|
332
720
|
import crypto from "crypto";
|
|
333
|
-
import
|
|
334
|
-
import { existsSync as
|
|
721
|
+
import path5 from "path";
|
|
722
|
+
import { existsSync as existsSync6, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
335
723
|
function normalizeToken(token) {
|
|
336
724
|
if (!token) return null;
|
|
337
725
|
const trimmed = token.trim();
|
|
@@ -339,8 +727,8 @@ function normalizeToken(token) {
|
|
|
339
727
|
}
|
|
340
728
|
function readDaemonToken() {
|
|
341
729
|
try {
|
|
342
|
-
if (!
|
|
343
|
-
return normalizeToken(
|
|
730
|
+
if (!existsSync6(DAEMON_TOKEN_PATH)) return null;
|
|
731
|
+
return normalizeToken(readFileSync4(DAEMON_TOKEN_PATH, "utf8"));
|
|
344
732
|
} catch {
|
|
345
733
|
return null;
|
|
346
734
|
}
|
|
@@ -350,7 +738,7 @@ function ensureDaemonToken(seed) {
|
|
|
350
738
|
if (existing) return existing;
|
|
351
739
|
const token = normalizeToken(seed) ?? crypto.randomBytes(32).toString("hex");
|
|
352
740
|
ensurePrivateDirSync(EXE_AI_DIR);
|
|
353
|
-
|
|
741
|
+
writeFileSync3(DAEMON_TOKEN_PATH, `${token}
|
|
354
742
|
`, "utf8");
|
|
355
743
|
enforcePrivateFileSync(DAEMON_TOKEN_PATH);
|
|
356
744
|
return token;
|
|
@@ -361,7 +749,7 @@ var init_daemon_auth = __esm({
|
|
|
361
749
|
"use strict";
|
|
362
750
|
init_config();
|
|
363
751
|
init_secure_files();
|
|
364
|
-
DAEMON_TOKEN_PATH =
|
|
752
|
+
DAEMON_TOKEN_PATH = path5.join(EXE_AI_DIR, "exed.token");
|
|
365
753
|
}
|
|
366
754
|
});
|
|
367
755
|
|
|
@@ -370,8 +758,8 @@ import net from "net";
|
|
|
370
758
|
import os4 from "os";
|
|
371
759
|
import { spawn, execSync as execSync2 } from "child_process";
|
|
372
760
|
import { randomUUID } from "crypto";
|
|
373
|
-
import { existsSync as
|
|
374
|
-
import
|
|
761
|
+
import { existsSync as existsSync7, unlinkSync as unlinkSync3, readFileSync as readFileSync5, openSync as openSync2, closeSync as closeSync2, statSync as statSync2 } from "fs";
|
|
762
|
+
import path6 from "path";
|
|
375
763
|
import { fileURLToPath } from "url";
|
|
376
764
|
function handleData(chunk) {
|
|
377
765
|
_buffer += chunk.toString();
|
|
@@ -407,9 +795,9 @@ function isZombie(pid) {
|
|
|
407
795
|
}
|
|
408
796
|
}
|
|
409
797
|
function cleanupStaleFiles() {
|
|
410
|
-
if (
|
|
798
|
+
if (existsSync7(PID_PATH)) {
|
|
411
799
|
try {
|
|
412
|
-
const pid = parseInt(
|
|
800
|
+
const pid = parseInt(readFileSync5(PID_PATH, "utf8").trim(), 10);
|
|
413
801
|
if (pid > 0) {
|
|
414
802
|
try {
|
|
415
803
|
process.kill(pid, 0);
|
|
@@ -434,11 +822,11 @@ function cleanupStaleFiles() {
|
|
|
434
822
|
}
|
|
435
823
|
}
|
|
436
824
|
function findPackageRoot() {
|
|
437
|
-
let dir =
|
|
438
|
-
const { root } =
|
|
825
|
+
let dir = path6.dirname(fileURLToPath(import.meta.url));
|
|
826
|
+
const { root } = path6.parse(dir);
|
|
439
827
|
while (dir !== root) {
|
|
440
|
-
if (
|
|
441
|
-
dir =
|
|
828
|
+
if (existsSync7(path6.join(dir, "package.json"))) return dir;
|
|
829
|
+
dir = path6.dirname(dir);
|
|
442
830
|
}
|
|
443
831
|
return null;
|
|
444
832
|
}
|
|
@@ -456,8 +844,8 @@ function spawnDaemon() {
|
|
|
456
844
|
process.stderr.write("[exed-client] WARN: cannot find package root\n");
|
|
457
845
|
return;
|
|
458
846
|
}
|
|
459
|
-
const daemonPath =
|
|
460
|
-
if (!
|
|
847
|
+
const daemonPath = path6.join(pkgRoot, "dist", "lib", "exe-daemon.js");
|
|
848
|
+
if (!existsSync7(daemonPath)) {
|
|
461
849
|
process.stderr.write(`[exed-client] WARN: daemon script not found at ${daemonPath}
|
|
462
850
|
`);
|
|
463
851
|
return;
|
|
@@ -466,7 +854,7 @@ function spawnDaemon() {
|
|
|
466
854
|
const daemonToken = ensureDaemonToken(process.env[DAEMON_TOKEN_ENV] ?? null);
|
|
467
855
|
process.stderr.write(`[exed-client] Spawning daemon: ${resolvedPath}
|
|
468
856
|
`);
|
|
469
|
-
const logPath =
|
|
857
|
+
const logPath = path6.join(path6.dirname(SOCKET_PATH), "exed.log");
|
|
470
858
|
let stderrFd = "ignore";
|
|
471
859
|
try {
|
|
472
860
|
stderrFd = openSync2(logPath, "a");
|
|
@@ -631,9 +1019,9 @@ function killAndRespawnDaemon() {
|
|
|
631
1019
|
}
|
|
632
1020
|
try {
|
|
633
1021
|
process.stderr.write("[exed-client] Killing daemon for restart...\n");
|
|
634
|
-
if (
|
|
1022
|
+
if (existsSync7(PID_PATH)) {
|
|
635
1023
|
try {
|
|
636
|
-
const pid = parseInt(
|
|
1024
|
+
const pid = parseInt(readFileSync5(PID_PATH, "utf8").trim(), 10);
|
|
637
1025
|
if (pid > 0) {
|
|
638
1026
|
try {
|
|
639
1027
|
process.kill(pid, "SIGKILL");
|
|
@@ -756,9 +1144,9 @@ var init_exe_daemon_client = __esm({
|
|
|
756
1144
|
"use strict";
|
|
757
1145
|
init_config();
|
|
758
1146
|
init_daemon_auth();
|
|
759
|
-
SOCKET_PATH = process.env.EXE_DAEMON_SOCK ?? process.env.EXE_EMBED_SOCK ??
|
|
760
|
-
PID_PATH = process.env.EXE_DAEMON_PID ?? process.env.EXE_EMBED_PID ??
|
|
761
|
-
SPAWN_LOCK_PATH =
|
|
1147
|
+
SOCKET_PATH = process.env.EXE_DAEMON_SOCK ?? process.env.EXE_EMBED_SOCK ?? path6.join(EXE_AI_DIR, "exed.sock");
|
|
1148
|
+
PID_PATH = process.env.EXE_DAEMON_PID ?? process.env.EXE_EMBED_PID ?? path6.join(EXE_AI_DIR, "exed.pid");
|
|
1149
|
+
SPAWN_LOCK_PATH = path6.join(EXE_AI_DIR, "exed-spawn.lock");
|
|
762
1150
|
SPAWN_LOCK_STALE_MS = 3e4;
|
|
763
1151
|
CONNECT_TIMEOUT_MS = 15e3;
|
|
764
1152
|
REQUEST_TIMEOUT_MS = 3e4;
|
|
@@ -814,10 +1202,10 @@ async function disposeEmbedder() {
|
|
|
814
1202
|
async function embedDirect(text) {
|
|
815
1203
|
const llamaCpp = await import("node-llama-cpp");
|
|
816
1204
|
const { MODELS_DIR: MODELS_DIR2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
817
|
-
const { existsSync:
|
|
818
|
-
const
|
|
819
|
-
const modelPath =
|
|
820
|
-
if (!
|
|
1205
|
+
const { existsSync: existsSync9 } = await import("fs");
|
|
1206
|
+
const path8 = await import("path");
|
|
1207
|
+
const modelPath = path8.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
|
|
1208
|
+
if (!existsSync9(modelPath)) {
|
|
821
1209
|
throw new Error(`Embedding model not found at ${modelPath}. Run '/exe-setup' to download it.`);
|
|
822
1210
|
}
|
|
823
1211
|
const llama = await llamaCpp.getLlama();
|
|
@@ -863,12 +1251,12 @@ __export(license_exports, {
|
|
|
863
1251
|
stopLicenseRevalidation: () => stopLicenseRevalidation,
|
|
864
1252
|
validateLicense: () => validateLicense
|
|
865
1253
|
});
|
|
866
|
-
import { readFileSync as
|
|
1254
|
+
import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, existsSync as existsSync8, mkdirSync as mkdirSync3 } from "fs";
|
|
867
1255
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
868
1256
|
import { createRequire as createRequire2 } from "module";
|
|
869
1257
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
870
1258
|
import os5 from "os";
|
|
871
|
-
import
|
|
1259
|
+
import path7 from "path";
|
|
872
1260
|
import { jwtVerify, importSPKI } from "jose";
|
|
873
1261
|
async function fetchRetry(url, init) {
|
|
874
1262
|
try {
|
|
@@ -879,37 +1267,37 @@ async function fetchRetry(url, init) {
|
|
|
879
1267
|
}
|
|
880
1268
|
}
|
|
881
1269
|
function loadDeviceId() {
|
|
882
|
-
const deviceJsonPath =
|
|
1270
|
+
const deviceJsonPath = path7.join(EXE_AI_DIR, "device.json");
|
|
883
1271
|
try {
|
|
884
|
-
if (
|
|
885
|
-
const data = JSON.parse(
|
|
1272
|
+
if (existsSync8(deviceJsonPath)) {
|
|
1273
|
+
const data = JSON.parse(readFileSync6(deviceJsonPath, "utf8"));
|
|
886
1274
|
if (data.deviceId) return data.deviceId;
|
|
887
1275
|
}
|
|
888
1276
|
} catch {
|
|
889
1277
|
}
|
|
890
1278
|
try {
|
|
891
|
-
if (
|
|
892
|
-
const id2 =
|
|
1279
|
+
if (existsSync8(DEVICE_ID_PATH)) {
|
|
1280
|
+
const id2 = readFileSync6(DEVICE_ID_PATH, "utf8").trim();
|
|
893
1281
|
if (id2) return id2;
|
|
894
1282
|
}
|
|
895
1283
|
} catch {
|
|
896
1284
|
}
|
|
897
1285
|
const id = randomUUID2();
|
|
898
1286
|
mkdirSync3(EXE_AI_DIR, { recursive: true });
|
|
899
|
-
|
|
1287
|
+
writeFileSync4(DEVICE_ID_PATH, id, "utf8");
|
|
900
1288
|
return id;
|
|
901
1289
|
}
|
|
902
1290
|
function loadLicense() {
|
|
903
1291
|
try {
|
|
904
|
-
if (!
|
|
905
|
-
return
|
|
1292
|
+
if (!existsSync8(LICENSE_PATH)) return null;
|
|
1293
|
+
return readFileSync6(LICENSE_PATH, "utf8").trim();
|
|
906
1294
|
} catch {
|
|
907
1295
|
return null;
|
|
908
1296
|
}
|
|
909
1297
|
}
|
|
910
1298
|
function saveLicense(apiKey) {
|
|
911
1299
|
mkdirSync3(EXE_AI_DIR, { recursive: true });
|
|
912
|
-
|
|
1300
|
+
writeFileSync4(LICENSE_PATH, apiKey.trim(), { encoding: "utf8", mode: 384 });
|
|
913
1301
|
}
|
|
914
1302
|
async function verifyLicenseJwt(token) {
|
|
915
1303
|
try {
|
|
@@ -935,8 +1323,8 @@ async function verifyLicenseJwt(token) {
|
|
|
935
1323
|
}
|
|
936
1324
|
async function getCachedLicense() {
|
|
937
1325
|
try {
|
|
938
|
-
if (!
|
|
939
|
-
const raw = JSON.parse(
|
|
1326
|
+
if (!existsSync8(CACHE_PATH)) return null;
|
|
1327
|
+
const raw = JSON.parse(readFileSync6(CACHE_PATH, "utf8"));
|
|
940
1328
|
if (!raw.token || typeof raw.token !== "string") return null;
|
|
941
1329
|
return await verifyLicenseJwt(raw.token);
|
|
942
1330
|
} catch {
|
|
@@ -945,8 +1333,8 @@ async function getCachedLicense() {
|
|
|
945
1333
|
}
|
|
946
1334
|
function readCachedLicenseToken() {
|
|
947
1335
|
try {
|
|
948
|
-
if (!
|
|
949
|
-
const raw = JSON.parse(
|
|
1336
|
+
if (!existsSync8(CACHE_PATH)) return null;
|
|
1337
|
+
const raw = JSON.parse(readFileSync6(CACHE_PATH, "utf8"));
|
|
950
1338
|
return typeof raw.token === "string" ? raw.token : null;
|
|
951
1339
|
} catch {
|
|
952
1340
|
return null;
|
|
@@ -980,7 +1368,7 @@ function getRawCachedPlan() {
|
|
|
980
1368
|
}
|
|
981
1369
|
function cacheResponse(token) {
|
|
982
1370
|
try {
|
|
983
|
-
|
|
1371
|
+
writeFileSync4(CACHE_PATH, JSON.stringify({ token }), "utf8");
|
|
984
1372
|
} catch {
|
|
985
1373
|
}
|
|
986
1374
|
}
|
|
@@ -988,8 +1376,8 @@ function loadPrismaForLicense() {
|
|
|
988
1376
|
if (_prismaFailed) return null;
|
|
989
1377
|
const dbUrl = process.env.DATABASE_URL;
|
|
990
1378
|
if (!dbUrl) {
|
|
991
|
-
const exeDbRoot = process.env.EXE_DB_ROOT ??
|
|
992
|
-
if (!
|
|
1379
|
+
const exeDbRoot = process.env.EXE_DB_ROOT ?? path7.join(os5.homedir(), "exe-db");
|
|
1380
|
+
if (!existsSync8(path7.join(exeDbRoot, "package.json"))) {
|
|
993
1381
|
_prismaFailed = true;
|
|
994
1382
|
return null;
|
|
995
1383
|
}
|
|
@@ -1003,8 +1391,8 @@ function loadPrismaForLicense() {
|
|
|
1003
1391
|
if (!Ctor2) throw new Error(`No PrismaClient at ${explicitPath}`);
|
|
1004
1392
|
return new Ctor2();
|
|
1005
1393
|
}
|
|
1006
|
-
const exeDbRoot = process.env.EXE_DB_ROOT ??
|
|
1007
|
-
const req = createRequire2(
|
|
1394
|
+
const exeDbRoot = process.env.EXE_DB_ROOT ?? path7.join(os5.homedir(), "exe-db");
|
|
1395
|
+
const req = createRequire2(path7.join(exeDbRoot, "package.json"));
|
|
1008
1396
|
const entry = req.resolve("@prisma/client");
|
|
1009
1397
|
const mod = await import(pathToFileURL2(entry).href);
|
|
1010
1398
|
const Ctor = mod.PrismaClient ?? mod.default?.PrismaClient;
|
|
@@ -1083,7 +1471,7 @@ async function validateLicense(apiKey, deviceId) {
|
|
|
1083
1471
|
const pgResult = await validateViaPostgres(apiKey);
|
|
1084
1472
|
if (pgResult) {
|
|
1085
1473
|
try {
|
|
1086
|
-
|
|
1474
|
+
writeFileSync4(CACHE_PATH, JSON.stringify({ pgLicense: pgResult, ts: Date.now() }), "utf8");
|
|
1087
1475
|
} catch {
|
|
1088
1476
|
}
|
|
1089
1477
|
return pgResult;
|
|
@@ -1093,8 +1481,8 @@ async function validateLicense(apiKey, deviceId) {
|
|
|
1093
1481
|
const cached = await getCachedLicense();
|
|
1094
1482
|
if (cached) return cached;
|
|
1095
1483
|
try {
|
|
1096
|
-
if (
|
|
1097
|
-
const raw = JSON.parse(
|
|
1484
|
+
if (existsSync8(CACHE_PATH)) {
|
|
1485
|
+
const raw = JSON.parse(readFileSync6(CACHE_PATH, "utf8"));
|
|
1098
1486
|
if (raw.pgLicense && raw.ts && Date.now() - raw.ts < 7 * 24 * 60 * 60 * 1e3) {
|
|
1099
1487
|
return raw.pgLicense;
|
|
1100
1488
|
}
|
|
@@ -1118,9 +1506,9 @@ async function checkLicense() {
|
|
|
1118
1506
|
let key = loadLicense();
|
|
1119
1507
|
if (!key) {
|
|
1120
1508
|
try {
|
|
1121
|
-
const configPath =
|
|
1122
|
-
if (
|
|
1123
|
-
const raw = JSON.parse(
|
|
1509
|
+
const configPath = path7.join(EXE_AI_DIR, "config.json");
|
|
1510
|
+
if (existsSync8(configPath)) {
|
|
1511
|
+
const raw = JSON.parse(readFileSync6(configPath, "utf8"));
|
|
1124
1512
|
const cloud = raw.cloud;
|
|
1125
1513
|
if (cloud?.apiKey) {
|
|
1126
1514
|
key = cloud.apiKey;
|
|
@@ -1213,7 +1601,7 @@ async function assertVpsLicense(opts) {
|
|
|
1213
1601
|
}
|
|
1214
1602
|
if (!transientFailure) {
|
|
1215
1603
|
throw new Error(
|
|
1216
|
-
"License validation failed: unknown backend state. Restore network connectivity to https://askexe.com
|
|
1604
|
+
"License validation failed: unknown backend state. Restore network connectivity to https://cloud.askexe.com and retry."
|
|
1217
1605
|
);
|
|
1218
1606
|
}
|
|
1219
1607
|
const fresh = await getCachedLicense();
|
|
@@ -1250,7 +1638,7 @@ async function assertVpsLicense(opts) {
|
|
|
1250
1638
|
} catch {
|
|
1251
1639
|
}
|
|
1252
1640
|
throw new Error(
|
|
1253
|
-
`License validation unreachable for more than ${graceDays} days. Restore network connectivity to https://askexe.com
|
|
1641
|
+
`License validation unreachable for more than ${graceDays} days. Restore network connectivity to https://cloud.askexe.com and retry. This VPS image refuses to boot after the offline grace window.`
|
|
1254
1642
|
);
|
|
1255
1643
|
}
|
|
1256
1644
|
function startLicenseRevalidation(intervalMs = 36e5) {
|
|
@@ -1279,10 +1667,10 @@ var init_license = __esm({
|
|
|
1279
1667
|
"src/lib/license.ts"() {
|
|
1280
1668
|
"use strict";
|
|
1281
1669
|
init_config();
|
|
1282
|
-
LICENSE_PATH =
|
|
1283
|
-
CACHE_PATH =
|
|
1284
|
-
DEVICE_ID_PATH =
|
|
1285
|
-
API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://askexe.com
|
|
1670
|
+
LICENSE_PATH = path7.join(EXE_AI_DIR, "license.key");
|
|
1671
|
+
CACHE_PATH = path7.join(EXE_AI_DIR, "license-cache.json");
|
|
1672
|
+
DEVICE_ID_PATH = path7.join(EXE_AI_DIR, "device-id");
|
|
1673
|
+
API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://cloud.askexe.com";
|
|
1286
1674
|
RETRY_DELAY_MS = 500;
|
|
1287
1675
|
LICENSE_PUBLIC_KEY_PEM = `-----BEGIN PUBLIC KEY-----
|
|
1288
1676
|
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeHztAMOpR/ZMh+rWuOASjEZ54CGY
|
|
@@ -1316,24 +1704,15 @@ MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeHztAMOpR/ZMh+rWuOASjEZ54CGY
|
|
|
1316
1704
|
import crypto3 from "crypto";
|
|
1317
1705
|
|
|
1318
1706
|
// src/lib/database.ts
|
|
1319
|
-
import { chmodSync as chmodSync2, existsSync as
|
|
1707
|
+
import { chmodSync as chmodSync2, existsSync as existsSync5, statSync, copyFileSync, unlinkSync as unlinkSync2, openSync, closeSync, mkdirSync as mkdirSync2 } from "fs";
|
|
1320
1708
|
import { createClient } from "@libsql/client";
|
|
1321
1709
|
import { homedir } from "os";
|
|
1322
1710
|
import { join } from "path";
|
|
1323
|
-
|
|
1324
|
-
// src/lib/employees.ts
|
|
1325
|
-
init_config();
|
|
1326
|
-
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
1327
|
-
import { existsSync as existsSync3, symlinkSync, readlinkSync, readFileSync as readFileSync2, renameSync as renameSync2, unlinkSync, writeFileSync } from "fs";
|
|
1328
|
-
import { execSync } from "child_process";
|
|
1329
|
-
import path2 from "path";
|
|
1330
|
-
import os2 from "os";
|
|
1331
|
-
var EMPLOYEES_PATH = path2.join(EXE_AI_DIR, "exe-employees.json");
|
|
1332
|
-
var IDENTITY_DIR = path2.join(EXE_AI_DIR, "identity");
|
|
1711
|
+
init_employees();
|
|
1333
1712
|
|
|
1334
1713
|
// src/lib/database-adapter.ts
|
|
1335
1714
|
import os3 from "os";
|
|
1336
|
-
import
|
|
1715
|
+
import path4 from "path";
|
|
1337
1716
|
import { createRequire } from "module";
|
|
1338
1717
|
import { pathToFileURL } from "url";
|
|
1339
1718
|
var BOOLEAN_COLUMNS_BY_TABLE = {
|
|
@@ -1389,6 +1768,15 @@ function getClient() {
|
|
|
1389
1768
|
// src/lib/behaviors.ts
|
|
1390
1769
|
import crypto2 from "crypto";
|
|
1391
1770
|
async function storeBehavior(opts) {
|
|
1771
|
+
try {
|
|
1772
|
+
const { loadEmployeesSync: loadEmployeesSync2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
1773
|
+
const roster = loadEmployeesSync2();
|
|
1774
|
+
if (roster.length > 0 && !roster.some((e) => e.name === opts.agentId)) {
|
|
1775
|
+
throw new Error(`Agent "${opts.agentId}" not found in roster. Cannot store behavior for unregistered agent.`);
|
|
1776
|
+
}
|
|
1777
|
+
} catch (e) {
|
|
1778
|
+
if (e instanceof Error && e.message.includes("not found in roster")) throw e;
|
|
1779
|
+
}
|
|
1392
1780
|
const client = getClient();
|
|
1393
1781
|
const id = crypto2.randomUUID();
|
|
1394
1782
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|