@askexenow/exe-os 0.8.58 → 0.8.60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/cli.js +92 -12
- package/dist/bin/exe-boot.js +137 -100
- package/dist/bin/exe-cloud.js +35 -3
- package/dist/bin/exe-dispatch.js +3746 -250
- package/dist/bin/exe-gateway.js +50 -15
- package/dist/bin/exe-heartbeat.js +34 -49
- package/dist/bin/exe-link.js +91 -88
- package/dist/bin/exe-new-employee.js +44 -3
- package/dist/bin/exe-pending-reviews.js +4 -27
- package/dist/bin/exe-session-cleanup.js +846 -2946
- package/dist/bin/git-sweep.js +13 -11
- package/dist/bin/scan-tasks.js +13 -11
- package/dist/bin/setup.js +35 -3
- package/dist/bin/update.js +35 -3
- package/dist/gateway/index.js +17 -14
- package/dist/hooks/bug-report-worker.js +13 -11
- package/dist/hooks/commit-complete.js +13 -11
- package/dist/hooks/ingest-worker.js +55 -12
- package/dist/hooks/pre-compact.js +13 -11
- package/dist/hooks/prompt-ingest-worker.js +44 -3
- package/dist/hooks/prompt-submit.js +516 -2611
- package/dist/hooks/response-ingest-worker.js +44 -3
- package/dist/hooks/summary-worker.js +126 -91
- package/dist/index.js +38 -14
- package/dist/lib/cloud-sync.js +91 -88
- package/dist/lib/exe-daemon.js +45 -56
- package/dist/lib/license.js +35 -3
- package/dist/lib/messaging.js +31 -524
- package/dist/lib/tasks.js +13 -11
- package/dist/lib/tmux-routing.js +13 -11
- package/dist/mcp/server.js +51 -16
- package/dist/mcp/tools/create-task.js +13 -11
- package/dist/mcp/tools/list-tasks.js +0 -1
- package/dist/mcp/tools/send-message.js +37 -530
- package/dist/mcp/tools/update-task.js +0 -1
- package/dist/runtime/index.js +34 -11
- package/dist/tui/App.js +92 -12
- package/package.json +1 -1
package/dist/bin/cli.js
CHANGED
|
@@ -4864,6 +4864,32 @@ function readCachedToken() {
|
|
|
4864
4864
|
return null;
|
|
4865
4865
|
}
|
|
4866
4866
|
}
|
|
4867
|
+
function getRawCachedPlan() {
|
|
4868
|
+
try {
|
|
4869
|
+
const token = readCachedToken();
|
|
4870
|
+
if (!token) return null;
|
|
4871
|
+
const parts = token.split(".");
|
|
4872
|
+
if (parts.length !== 3) return null;
|
|
4873
|
+
const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString());
|
|
4874
|
+
const plan = payload.plan ?? "free";
|
|
4875
|
+
const limits = PLAN_LIMITS[plan] ?? PLAN_LIMITS.free;
|
|
4876
|
+
process.stderr.write(
|
|
4877
|
+
`[license] WARN: using unverified cached plan (API unreachable, JWT expired). Plan: ${plan}
|
|
4878
|
+
`
|
|
4879
|
+
);
|
|
4880
|
+
return {
|
|
4881
|
+
valid: true,
|
|
4882
|
+
plan,
|
|
4883
|
+
email: payload.sub ?? "",
|
|
4884
|
+
expiresAt: payload.exp ? new Date(payload.exp * 1e3).toISOString() : null,
|
|
4885
|
+
deviceLimit: limits.devices,
|
|
4886
|
+
employeeLimit: limits.employees,
|
|
4887
|
+
memoryLimit: limits.memories
|
|
4888
|
+
};
|
|
4889
|
+
} catch {
|
|
4890
|
+
return null;
|
|
4891
|
+
}
|
|
4892
|
+
}
|
|
4867
4893
|
function cacheResponse(token) {
|
|
4868
4894
|
try {
|
|
4869
4895
|
writeFileSync2(CACHE_PATH, JSON.stringify({ token }), "utf8");
|
|
@@ -4884,6 +4910,8 @@ async function validateLicense(apiKey, deviceId) {
|
|
|
4884
4910
|
if (data.error === "device_limit_exceeded") {
|
|
4885
4911
|
const cached2 = await getCachedLicense();
|
|
4886
4912
|
if (cached2) return cached2;
|
|
4913
|
+
const raw2 = getRawCachedPlan();
|
|
4914
|
+
if (raw2) return { ...raw2, valid: false };
|
|
4887
4915
|
return { ...FREE_LICENSE, valid: false, plan: "free" };
|
|
4888
4916
|
}
|
|
4889
4917
|
if (data.token) {
|
|
@@ -4904,10 +4932,14 @@ async function validateLicense(apiKey, deviceId) {
|
|
|
4904
4932
|
}
|
|
4905
4933
|
const cached = await getCachedLicense();
|
|
4906
4934
|
if (cached) return cached;
|
|
4935
|
+
const raw = getRawCachedPlan();
|
|
4936
|
+
if (raw) return raw;
|
|
4907
4937
|
return { ...FREE_LICENSE, valid: false, plan: "free" };
|
|
4908
4938
|
} catch {
|
|
4909
4939
|
const cached = await getCachedLicense();
|
|
4910
4940
|
if (cached) return cached;
|
|
4941
|
+
const rawFallback = getRawCachedPlan();
|
|
4942
|
+
if (rawFallback) return rawFallback;
|
|
4911
4943
|
return { ...FREE_LICENSE, valid: false, error: "offline" };
|
|
4912
4944
|
}
|
|
4913
4945
|
}
|
|
@@ -5096,8 +5128,8 @@ MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeHztAMOpR/ZMh+rWuOASjEZ54CGY
|
|
|
5096
5128
|
-----END PUBLIC KEY-----`;
|
|
5097
5129
|
LICENSE_JWT_ALG = "ES256";
|
|
5098
5130
|
PLAN_LIMITS = {
|
|
5099
|
-
free: { devices: 1, employees: 1, memories:
|
|
5100
|
-
pro: { devices: 2, employees: 5, memories:
|
|
5131
|
+
free: { devices: 1, employees: 1, memories: 5e4 },
|
|
5132
|
+
pro: { devices: 2, employees: 5, memories: 25e4 },
|
|
5101
5133
|
team: { devices: 10, employees: 20, memories: 1e6 },
|
|
5102
5134
|
agency: { devices: 50, employees: 100, memories: 1e7 },
|
|
5103
5135
|
enterprise: { devices: -1, employees: -1, memories: -1 }
|
|
@@ -5109,7 +5141,7 @@ MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeHztAMOpR/ZMh+rWuOASjEZ54CGY
|
|
|
5109
5141
|
expiresAt: null,
|
|
5110
5142
|
deviceLimit: 1,
|
|
5111
5143
|
employeeLimit: 1,
|
|
5112
|
-
memoryLimit:
|
|
5144
|
+
memoryLimit: 5e4
|
|
5113
5145
|
};
|
|
5114
5146
|
CACHE_MAX_AGE_MS = 36e5;
|
|
5115
5147
|
_revalTimer = null;
|
|
@@ -13238,6 +13270,21 @@ var init_session_kill_telemetry = __esm({
|
|
|
13238
13270
|
});
|
|
13239
13271
|
|
|
13240
13272
|
// src/lib/tasks-crud.ts
|
|
13273
|
+
var tasks_crud_exports = {};
|
|
13274
|
+
__export(tasks_crud_exports, {
|
|
13275
|
+
TASK_ALREADY_CLAIMED_PREFIX: () => TASK_ALREADY_CLAIMED_PREFIX,
|
|
13276
|
+
checkStaleCompletion: () => checkStaleCompletion,
|
|
13277
|
+
createTaskCore: () => createTaskCore,
|
|
13278
|
+
deleteTaskCore: () => deleteTaskCore,
|
|
13279
|
+
ensureArchitectureDoc: () => ensureArchitectureDoc,
|
|
13280
|
+
ensureGitignoreExe: () => ensureGitignoreExe,
|
|
13281
|
+
extractParentFromContext: () => extractParentFromContext,
|
|
13282
|
+
listTasks: () => listTasks,
|
|
13283
|
+
resolveTask: () => resolveTask,
|
|
13284
|
+
slugify: () => slugify,
|
|
13285
|
+
updateTaskStatus: () => updateTaskStatus,
|
|
13286
|
+
writeCheckpoint: () => writeCheckpoint
|
|
13287
|
+
});
|
|
13241
13288
|
import crypto6 from "crypto";
|
|
13242
13289
|
import path19 from "path";
|
|
13243
13290
|
import { execSync as execSync8 } from "child_process";
|
|
@@ -13854,7 +13901,6 @@ var init_tasks_review = __esm({
|
|
|
13854
13901
|
init_config();
|
|
13855
13902
|
init_employees();
|
|
13856
13903
|
init_notifications();
|
|
13857
|
-
init_tasks_crud();
|
|
13858
13904
|
init_tmux_routing();
|
|
13859
13905
|
init_session_key();
|
|
13860
13906
|
init_state_bus();
|
|
@@ -14990,18 +15036,21 @@ function exportBehaviorsSync(agentId, projectName, sessionKey) {
|
|
|
14990
15036
|
function getMySession() {
|
|
14991
15037
|
return getTransport().getMySession();
|
|
14992
15038
|
}
|
|
15039
|
+
function isRootSession(name) {
|
|
15040
|
+
return name.length > 0 && !name.includes("-");
|
|
15041
|
+
}
|
|
14993
15042
|
function employeeSessionName(employee, exeSession, instance) {
|
|
14994
|
-
if (
|
|
15043
|
+
if (!isRootSession(exeSession)) {
|
|
14995
15044
|
const root = extractRootExe(exeSession);
|
|
14996
15045
|
if (root) {
|
|
14997
15046
|
process.stderr.write(
|
|
14998
|
-
`[tmux-routing] WARN: exeSession="${exeSession}" is not a root
|
|
15047
|
+
`[tmux-routing] WARN: exeSession="${exeSession}" is not a root session, using "${root}" instead
|
|
14999
15048
|
`
|
|
15000
15049
|
);
|
|
15001
15050
|
exeSession = root;
|
|
15002
15051
|
} else {
|
|
15003
15052
|
throw new Error(
|
|
15004
|
-
`Invalid exeSession "${exeSession}" \u2014
|
|
15053
|
+
`Invalid exeSession "${exeSession}" \u2014 contains a dash but no recognizable root session. Pass a root session name (e.g., "exe1", "work", "yoda1")`
|
|
15005
15054
|
);
|
|
15006
15055
|
}
|
|
15007
15056
|
}
|
|
@@ -15009,7 +15058,7 @@ function employeeSessionName(employee, exeSession, instance) {
|
|
|
15009
15058
|
const name = `${employee}${suffix}-${exeSession}`;
|
|
15010
15059
|
if (!VALID_SESSION_NAME.test(name)) {
|
|
15011
15060
|
throw new Error(
|
|
15012
|
-
`Invalid session name "${name}" \u2014 must match {agent}-
|
|
15061
|
+
`Invalid session name "${name}" \u2014 must match {agent}-{rootSession} or {agent}{instance}-{rootSession}`
|
|
15013
15062
|
);
|
|
15014
15063
|
}
|
|
15015
15064
|
return name;
|
|
@@ -15252,11 +15301,11 @@ function ensureEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
15252
15301
|
error: `Error: pass employee name ('${bare}'), not session name ('${employeeName}')`
|
|
15253
15302
|
};
|
|
15254
15303
|
}
|
|
15255
|
-
if (
|
|
15304
|
+
if (!isRootSession(exeSession)) {
|
|
15256
15305
|
const root = extractRootExe(exeSession);
|
|
15257
15306
|
if (root) {
|
|
15258
15307
|
process.stderr.write(
|
|
15259
|
-
`[ensureEmployee] WARN: caller passed exeSession="${exeSession}" (not a root
|
|
15308
|
+
`[ensureEmployee] WARN: caller passed exeSession="${exeSession}" (not a root session). Auto-correcting to "${root}".
|
|
15260
15309
|
`
|
|
15261
15310
|
);
|
|
15262
15311
|
exeSession = root;
|
|
@@ -15264,7 +15313,7 @@ function ensureEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
15264
15313
|
return {
|
|
15265
15314
|
status: "failed",
|
|
15266
15315
|
sessionName: "",
|
|
15267
|
-
error: `Invalid exeSession "${exeSession}" \u2014
|
|
15316
|
+
error: `Invalid exeSession "${exeSession}" \u2014 contains a dash but no recognizable root session. Pass a root session name (e.g., "exe1", "work", "yoda1")`
|
|
15268
15317
|
};
|
|
15269
15318
|
}
|
|
15270
15319
|
}
|
|
@@ -15529,7 +15578,7 @@ var init_tmux_routing = __esm({
|
|
|
15529
15578
|
SPAWN_LOCK_DIR = path24.join(os9.homedir(), ".exe-os", "spawn-locks");
|
|
15530
15579
|
SESSION_CACHE = path24.join(os9.homedir(), ".exe-os", "session-cache");
|
|
15531
15580
|
BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
|
|
15532
|
-
VALID_SESSION_NAME = /^[a-z]
|
|
15581
|
+
VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
|
|
15533
15582
|
VERIFY_PANE_LINES = 200;
|
|
15534
15583
|
INTERCOM_DEBOUNCE_MS = 3e4;
|
|
15535
15584
|
INTERCOM_LOG2 = path24.join(os9.homedir(), ".exe-os", "intercom.log");
|
|
@@ -19515,6 +19564,7 @@ var init_orchestrator = __esm({
|
|
|
19515
19564
|
init_task_router();
|
|
19516
19565
|
init_tmux_routing();
|
|
19517
19566
|
init_task_scope();
|
|
19567
|
+
init_tasks_crud();
|
|
19518
19568
|
STALE_THRESHOLD_MS = 2 * 60 * 60 * 1e3;
|
|
19519
19569
|
MultiAgentOrchestrator = class {
|
|
19520
19570
|
config;
|
|
@@ -19551,6 +19601,26 @@ ${task.context}`,
|
|
|
19551
19601
|
targetEmployee = routed.employee;
|
|
19552
19602
|
routingScore = routed.score;
|
|
19553
19603
|
}
|
|
19604
|
+
try {
|
|
19605
|
+
await createTaskCore({
|
|
19606
|
+
title: task.title,
|
|
19607
|
+
assignedTo: targetEmployee.name,
|
|
19608
|
+
assignedBy: "exe",
|
|
19609
|
+
projectName: task.projectName,
|
|
19610
|
+
priority: task.priority,
|
|
19611
|
+
context: task.context,
|
|
19612
|
+
baseDir: this.config.projectDir,
|
|
19613
|
+
skipDispatch: true
|
|
19614
|
+
});
|
|
19615
|
+
} catch (err) {
|
|
19616
|
+
return {
|
|
19617
|
+
employee: targetEmployee.name,
|
|
19618
|
+
sessionName: "",
|
|
19619
|
+
status: "failed",
|
|
19620
|
+
routingScore,
|
|
19621
|
+
error: `Task creation failed: ${err instanceof Error ? err.message : String(err)}`
|
|
19622
|
+
};
|
|
19623
|
+
}
|
|
19554
19624
|
const result = ensureEmployee(
|
|
19555
19625
|
targetEmployee.name,
|
|
19556
19626
|
this.config.exeSession,
|
|
@@ -19838,7 +19908,17 @@ function useOrchestrator(enabled = true) {
|
|
|
19838
19908
|
const spawnSession = useCallback5(
|
|
19839
19909
|
async (agentId) => {
|
|
19840
19910
|
try {
|
|
19911
|
+
const { createTaskCore: createTaskCore2 } = await Promise.resolve().then(() => (init_tasks_crud(), tasks_crud_exports));
|
|
19841
19912
|
const { ensureEmployee: ensureEmployee2 } = await Promise.resolve().then(() => (init_tmux_routing(), tmux_routing_exports));
|
|
19913
|
+
await createTaskCore2({
|
|
19914
|
+
title: `Session launched for ${agentId} (TUI)`,
|
|
19915
|
+
assignedTo: agentId,
|
|
19916
|
+
assignedBy: "exe",
|
|
19917
|
+
projectName: "exe-os",
|
|
19918
|
+
priority: "p2",
|
|
19919
|
+
context: "Session spawned from TUI Sessions view. Agent will pick up any queued tasks via intercom.",
|
|
19920
|
+
skipDispatch: true
|
|
19921
|
+
});
|
|
19842
19922
|
return ensureEmployee2(agentId, exeSessionRef.current, process.cwd());
|
|
19843
19923
|
} catch {
|
|
19844
19924
|
return null;
|
package/dist/bin/exe-boot.js
CHANGED
|
@@ -2418,6 +2418,32 @@ function readCachedToken() {
|
|
|
2418
2418
|
return null;
|
|
2419
2419
|
}
|
|
2420
2420
|
}
|
|
2421
|
+
function getRawCachedPlan() {
|
|
2422
|
+
try {
|
|
2423
|
+
const token = readCachedToken();
|
|
2424
|
+
if (!token) return null;
|
|
2425
|
+
const parts = token.split(".");
|
|
2426
|
+
if (parts.length !== 3) return null;
|
|
2427
|
+
const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString());
|
|
2428
|
+
const plan = payload.plan ?? "free";
|
|
2429
|
+
const limits = PLAN_LIMITS[plan] ?? PLAN_LIMITS.free;
|
|
2430
|
+
process.stderr.write(
|
|
2431
|
+
`[license] WARN: using unverified cached plan (API unreachable, JWT expired). Plan: ${plan}
|
|
2432
|
+
`
|
|
2433
|
+
);
|
|
2434
|
+
return {
|
|
2435
|
+
valid: true,
|
|
2436
|
+
plan,
|
|
2437
|
+
email: payload.sub ?? "",
|
|
2438
|
+
expiresAt: payload.exp ? new Date(payload.exp * 1e3).toISOString() : null,
|
|
2439
|
+
deviceLimit: limits.devices,
|
|
2440
|
+
employeeLimit: limits.employees,
|
|
2441
|
+
memoryLimit: limits.memories
|
|
2442
|
+
};
|
|
2443
|
+
} catch {
|
|
2444
|
+
return null;
|
|
2445
|
+
}
|
|
2446
|
+
}
|
|
2421
2447
|
function cacheResponse(token) {
|
|
2422
2448
|
try {
|
|
2423
2449
|
writeFileSync3(CACHE_PATH, JSON.stringify({ token }), "utf8");
|
|
@@ -2438,6 +2464,8 @@ async function validateLicense(apiKey, deviceId) {
|
|
|
2438
2464
|
if (data.error === "device_limit_exceeded") {
|
|
2439
2465
|
const cached2 = await getCachedLicense();
|
|
2440
2466
|
if (cached2) return cached2;
|
|
2467
|
+
const raw2 = getRawCachedPlan();
|
|
2468
|
+
if (raw2) return { ...raw2, valid: false };
|
|
2441
2469
|
return { ...FREE_LICENSE, valid: false, plan: "free" };
|
|
2442
2470
|
}
|
|
2443
2471
|
if (data.token) {
|
|
@@ -2458,10 +2486,14 @@ async function validateLicense(apiKey, deviceId) {
|
|
|
2458
2486
|
}
|
|
2459
2487
|
const cached = await getCachedLicense();
|
|
2460
2488
|
if (cached) return cached;
|
|
2489
|
+
const raw = getRawCachedPlan();
|
|
2490
|
+
if (raw) return raw;
|
|
2461
2491
|
return { ...FREE_LICENSE, valid: false, plan: "free" };
|
|
2462
2492
|
} catch {
|
|
2463
2493
|
const cached = await getCachedLicense();
|
|
2464
2494
|
if (cached) return cached;
|
|
2495
|
+
const rawFallback = getRawCachedPlan();
|
|
2496
|
+
if (rawFallback) return rawFallback;
|
|
2465
2497
|
return { ...FREE_LICENSE, valid: false, error: "offline" };
|
|
2466
2498
|
}
|
|
2467
2499
|
}
|
|
@@ -2650,8 +2682,8 @@ MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeHztAMOpR/ZMh+rWuOASjEZ54CGY
|
|
|
2650
2682
|
-----END PUBLIC KEY-----`;
|
|
2651
2683
|
LICENSE_JWT_ALG = "ES256";
|
|
2652
2684
|
PLAN_LIMITS = {
|
|
2653
|
-
free: { devices: 1, employees: 1, memories:
|
|
2654
|
-
pro: { devices: 2, employees: 5, memories:
|
|
2685
|
+
free: { devices: 1, employees: 1, memories: 5e4 },
|
|
2686
|
+
pro: { devices: 2, employees: 5, memories: 25e4 },
|
|
2655
2687
|
team: { devices: 10, employees: 20, memories: 1e6 },
|
|
2656
2688
|
agency: { devices: 50, employees: 100, memories: 1e7 },
|
|
2657
2689
|
enterprise: { devices: -1, employees: -1, memories: -1 }
|
|
@@ -2663,7 +2695,7 @@ MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeHztAMOpR/ZMh+rWuOASjEZ54CGY
|
|
|
2663
2695
|
expiresAt: null,
|
|
2664
2696
|
deviceLimit: 1,
|
|
2665
2697
|
employeeLimit: 1,
|
|
2666
|
-
memoryLimit:
|
|
2698
|
+
memoryLimit: 5e4
|
|
2667
2699
|
};
|
|
2668
2700
|
CACHE_MAX_AGE_MS = 36e5;
|
|
2669
2701
|
_revalTimer = null;
|
|
@@ -3642,7 +3674,6 @@ var init_tasks_review = __esm({
|
|
|
3642
3674
|
init_config();
|
|
3643
3675
|
init_employees();
|
|
3644
3676
|
init_notifications();
|
|
3645
|
-
init_tasks_crud();
|
|
3646
3677
|
init_tmux_routing();
|
|
3647
3678
|
init_session_key();
|
|
3648
3679
|
init_state_bus();
|
|
@@ -4787,18 +4818,21 @@ function exportBehaviorsSync(agentId, projectName, sessionKey) {
|
|
|
4787
4818
|
function getMySession() {
|
|
4788
4819
|
return getTransport().getMySession();
|
|
4789
4820
|
}
|
|
4821
|
+
function isRootSession(name) {
|
|
4822
|
+
return name.length > 0 && !name.includes("-");
|
|
4823
|
+
}
|
|
4790
4824
|
function employeeSessionName(employee, exeSession, instance) {
|
|
4791
|
-
if (
|
|
4825
|
+
if (!isRootSession(exeSession)) {
|
|
4792
4826
|
const root = extractRootExe(exeSession);
|
|
4793
4827
|
if (root) {
|
|
4794
4828
|
process.stderr.write(
|
|
4795
|
-
`[tmux-routing] WARN: exeSession="${exeSession}" is not a root
|
|
4829
|
+
`[tmux-routing] WARN: exeSession="${exeSession}" is not a root session, using "${root}" instead
|
|
4796
4830
|
`
|
|
4797
4831
|
);
|
|
4798
4832
|
exeSession = root;
|
|
4799
4833
|
} else {
|
|
4800
4834
|
throw new Error(
|
|
4801
|
-
`Invalid exeSession "${exeSession}" \u2014
|
|
4835
|
+
`Invalid exeSession "${exeSession}" \u2014 contains a dash but no recognizable root session. Pass a root session name (e.g., "exe1", "work", "yoda1")`
|
|
4802
4836
|
);
|
|
4803
4837
|
}
|
|
4804
4838
|
}
|
|
@@ -4806,7 +4840,7 @@ function employeeSessionName(employee, exeSession, instance) {
|
|
|
4806
4840
|
const name = `${employee}${suffix}-${exeSession}`;
|
|
4807
4841
|
if (!VALID_SESSION_NAME.test(name)) {
|
|
4808
4842
|
throw new Error(
|
|
4809
|
-
`Invalid session name "${name}" \u2014 must match {agent}-
|
|
4843
|
+
`Invalid session name "${name}" \u2014 must match {agent}-{rootSession} or {agent}{instance}-{rootSession}`
|
|
4810
4844
|
);
|
|
4811
4845
|
}
|
|
4812
4846
|
return name;
|
|
@@ -5049,11 +5083,11 @@ function ensureEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
5049
5083
|
error: `Error: pass employee name ('${bare}'), not session name ('${employeeName}')`
|
|
5050
5084
|
};
|
|
5051
5085
|
}
|
|
5052
|
-
if (
|
|
5086
|
+
if (!isRootSession(exeSession)) {
|
|
5053
5087
|
const root = extractRootExe(exeSession);
|
|
5054
5088
|
if (root) {
|
|
5055
5089
|
process.stderr.write(
|
|
5056
|
-
`[ensureEmployee] WARN: caller passed exeSession="${exeSession}" (not a root
|
|
5090
|
+
`[ensureEmployee] WARN: caller passed exeSession="${exeSession}" (not a root session). Auto-correcting to "${root}".
|
|
5057
5091
|
`
|
|
5058
5092
|
);
|
|
5059
5093
|
exeSession = root;
|
|
@@ -5061,7 +5095,7 @@ function ensureEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
5061
5095
|
return {
|
|
5062
5096
|
status: "failed",
|
|
5063
5097
|
sessionName: "",
|
|
5064
|
-
error: `Invalid exeSession "${exeSession}" \u2014
|
|
5098
|
+
error: `Invalid exeSession "${exeSession}" \u2014 contains a dash but no recognizable root session. Pass a root session name (e.g., "exe1", "work", "yoda1")`
|
|
5065
5099
|
};
|
|
5066
5100
|
}
|
|
5067
5101
|
}
|
|
@@ -5326,7 +5360,7 @@ var init_tmux_routing = __esm({
|
|
|
5326
5360
|
SPAWN_LOCK_DIR = path15.join(os6.homedir(), ".exe-os", "spawn-locks");
|
|
5327
5361
|
SESSION_CACHE = path15.join(os6.homedir(), ".exe-os", "session-cache");
|
|
5328
5362
|
BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
|
|
5329
|
-
VALID_SESSION_NAME = /^[a-z]
|
|
5363
|
+
VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
|
|
5330
5364
|
VERIFY_PANE_LINES = 200;
|
|
5331
5365
|
INTERCOM_DEBOUNCE_MS = 3e4;
|
|
5332
5366
|
INTERCOM_LOG2 = path15.join(os6.homedir(), ".exe-os", "intercom.log");
|
|
@@ -5716,6 +5750,9 @@ import { readFileSync as readFileSync12, writeFileSync as writeFileSync8, exists
|
|
|
5716
5750
|
import crypto8 from "crypto";
|
|
5717
5751
|
import path19 from "path";
|
|
5718
5752
|
import { homedir } from "os";
|
|
5753
|
+
function sqlSafe(v) {
|
|
5754
|
+
return v === void 0 ? null : v;
|
|
5755
|
+
}
|
|
5719
5756
|
function logError(msg) {
|
|
5720
5757
|
try {
|
|
5721
5758
|
const logPath = path19.join(homedir(), ".exe-os", "workers.log");
|
|
@@ -5886,18 +5923,18 @@ async function cloudSync(config) {
|
|
|
5886
5923
|
author_device_id, scope)
|
|
5887
5924
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
5888
5925
|
args: [
|
|
5889
|
-
rec.id
|
|
5890
|
-
rec.agent_id
|
|
5891
|
-
rec.agent_role
|
|
5892
|
-
rec.session_id
|
|
5893
|
-
rec.timestamp
|
|
5894
|
-
rec.tool_name
|
|
5895
|
-
rec.project_name
|
|
5896
|
-
rec.has_error ?? 0,
|
|
5897
|
-
rec.raw_text ?? "",
|
|
5898
|
-
rec.version ?? 0,
|
|
5899
|
-
rec.author_device_id
|
|
5900
|
-
rec.scope ?? "business"
|
|
5926
|
+
sqlSafe(rec.id),
|
|
5927
|
+
sqlSafe(rec.agent_id),
|
|
5928
|
+
sqlSafe(rec.agent_role),
|
|
5929
|
+
sqlSafe(rec.session_id),
|
|
5930
|
+
sqlSafe(rec.timestamp),
|
|
5931
|
+
sqlSafe(rec.tool_name),
|
|
5932
|
+
sqlSafe(rec.project_name),
|
|
5933
|
+
sqlSafe(rec.has_error ?? 0),
|
|
5934
|
+
sqlSafe(rec.raw_text ?? ""),
|
|
5935
|
+
sqlSafe(rec.version ?? 0),
|
|
5936
|
+
sqlSafe(rec.author_device_id),
|
|
5937
|
+
sqlSafe(rec.scope ?? "business")
|
|
5901
5938
|
]
|
|
5902
5939
|
}));
|
|
5903
5940
|
await client.batch(stmts, "write");
|
|
@@ -6318,14 +6355,14 @@ async function cloudPullGlobalProcedures(config) {
|
|
|
6318
6355
|
updated_at = excluded.updated_at
|
|
6319
6356
|
WHERE excluded.updated_at > global_procedures.updated_at`,
|
|
6320
6357
|
args: [
|
|
6321
|
-
p.id
|
|
6322
|
-
p.title
|
|
6323
|
-
p.content
|
|
6324
|
-
p.priority ?? "p0",
|
|
6325
|
-
p.domain
|
|
6326
|
-
p.active ?? 1,
|
|
6327
|
-
p.created_at
|
|
6328
|
-
p.updated_at
|
|
6358
|
+
sqlSafe(p.id),
|
|
6359
|
+
sqlSafe(p.title),
|
|
6360
|
+
sqlSafe(p.content),
|
|
6361
|
+
sqlSafe(p.priority ?? "p0"),
|
|
6362
|
+
sqlSafe(p.domain),
|
|
6363
|
+
sqlSafe(p.active ?? 1),
|
|
6364
|
+
sqlSafe(p.created_at),
|
|
6365
|
+
sqlSafe(p.updated_at)
|
|
6329
6366
|
]
|
|
6330
6367
|
}));
|
|
6331
6368
|
await client.batch(stmts, "write");
|
|
@@ -6355,7 +6392,7 @@ async function cloudPullBehaviors(config) {
|
|
|
6355
6392
|
const existing = await client.execute({
|
|
6356
6393
|
sql: `SELECT COUNT(*) as cnt FROM behaviors
|
|
6357
6394
|
WHERE agent_id = ? AND content = ?`,
|
|
6358
|
-
args: [behavior.agent_id
|
|
6395
|
+
args: [sqlSafe(behavior.agent_id), sqlSafe(behavior.content)]
|
|
6359
6396
|
});
|
|
6360
6397
|
if (Number(existing.rows[0]?.cnt) > 0) continue;
|
|
6361
6398
|
await client.execute({
|
|
@@ -6363,15 +6400,15 @@ async function cloudPullBehaviors(config) {
|
|
|
6363
6400
|
(id, agent_id, project_name, domain, content, active, priority, created_at, updated_at)
|
|
6364
6401
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
6365
6402
|
args: [
|
|
6366
|
-
behavior.id
|
|
6367
|
-
behavior.agent_id
|
|
6368
|
-
behavior.project_name
|
|
6369
|
-
behavior.domain
|
|
6370
|
-
behavior.content
|
|
6371
|
-
behavior.active ?? 1,
|
|
6372
|
-
behavior.priority ?? "p1",
|
|
6373
|
-
behavior.created_at
|
|
6374
|
-
behavior.updated_at
|
|
6403
|
+
sqlSafe(behavior.id),
|
|
6404
|
+
sqlSafe(behavior.agent_id),
|
|
6405
|
+
sqlSafe(behavior.project_name),
|
|
6406
|
+
sqlSafe(behavior.domain),
|
|
6407
|
+
sqlSafe(behavior.content),
|
|
6408
|
+
sqlSafe(behavior.active ?? 1),
|
|
6409
|
+
sqlSafe(behavior.priority ?? "p1"),
|
|
6410
|
+
sqlSafe(behavior.created_at),
|
|
6411
|
+
sqlSafe(behavior.updated_at)
|
|
6375
6412
|
]
|
|
6376
6413
|
});
|
|
6377
6414
|
pulled++;
|
|
@@ -6419,7 +6456,7 @@ async function cloudPullGraphRAG(config) {
|
|
|
6419
6456
|
const stmts = blob.entities.map((e) => ({
|
|
6420
6457
|
sql: `INSERT OR IGNORE INTO entities (id, name, type, first_seen, last_seen, properties)
|
|
6421
6458
|
VALUES (?, ?, ?, ?, ?, ?)`,
|
|
6422
|
-
args: [e.id, e.name, e.type, e.first_seen, e.last_seen, e.properties ?? "{}"]
|
|
6459
|
+
args: [sqlSafe(e.id), sqlSafe(e.name), sqlSafe(e.type), sqlSafe(e.first_seen), sqlSafe(e.last_seen), sqlSafe(e.properties ?? "{}")]
|
|
6423
6460
|
}));
|
|
6424
6461
|
await client.batch(stmts, "write");
|
|
6425
6462
|
pulled += stmts.length;
|
|
@@ -6430,15 +6467,15 @@ async function cloudPullGraphRAG(config) {
|
|
|
6430
6467
|
(id, source_entity_id, target_entity_id, type, weight, timestamp, properties, confidence, confidence_label)
|
|
6431
6468
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
6432
6469
|
args: [
|
|
6433
|
-
r.id,
|
|
6434
|
-
r.source_entity_id,
|
|
6435
|
-
r.target_entity_id,
|
|
6436
|
-
r.type,
|
|
6437
|
-
r.weight ?? 1,
|
|
6438
|
-
r.timestamp,
|
|
6439
|
-
r.properties ?? "{}",
|
|
6440
|
-
r.confidence ?? 1,
|
|
6441
|
-
r.confidence_label ?? "extracted"
|
|
6470
|
+
sqlSafe(r.id),
|
|
6471
|
+
sqlSafe(r.source_entity_id),
|
|
6472
|
+
sqlSafe(r.target_entity_id),
|
|
6473
|
+
sqlSafe(r.type),
|
|
6474
|
+
sqlSafe(r.weight ?? 1),
|
|
6475
|
+
sqlSafe(r.timestamp),
|
|
6476
|
+
sqlSafe(r.properties ?? "{}"),
|
|
6477
|
+
sqlSafe(r.confidence ?? 1),
|
|
6478
|
+
sqlSafe(r.confidence_label ?? "extracted")
|
|
6442
6479
|
]
|
|
6443
6480
|
}));
|
|
6444
6481
|
await client.batch(stmts, "write");
|
|
@@ -6447,7 +6484,7 @@ async function cloudPullGraphRAG(config) {
|
|
|
6447
6484
|
if (blob.entity_aliases.length > 0) {
|
|
6448
6485
|
const stmts = blob.entity_aliases.map((a) => ({
|
|
6449
6486
|
sql: `INSERT OR IGNORE INTO entity_aliases (alias, canonical_entity_id) VALUES (?, ?)`,
|
|
6450
|
-
args: [a.alias, a.canonical_entity_id]
|
|
6487
|
+
args: [sqlSafe(a.alias), sqlSafe(a.canonical_entity_id)]
|
|
6451
6488
|
}));
|
|
6452
6489
|
await client.batch(stmts, "write");
|
|
6453
6490
|
pulled += stmts.length;
|
|
@@ -6455,7 +6492,7 @@ async function cloudPullGraphRAG(config) {
|
|
|
6455
6492
|
if (blob.entity_memories.length > 0) {
|
|
6456
6493
|
const stmts = blob.entity_memories.map((em) => ({
|
|
6457
6494
|
sql: `INSERT OR IGNORE INTO entity_memories (entity_id, memory_id) VALUES (?, ?)`,
|
|
6458
|
-
args: [em.entity_id, em.memory_id]
|
|
6495
|
+
args: [sqlSafe(em.entity_id), sqlSafe(em.memory_id)]
|
|
6459
6496
|
}));
|
|
6460
6497
|
await client.batch(stmts, "write");
|
|
6461
6498
|
pulled += stmts.length;
|
|
@@ -6463,7 +6500,7 @@ async function cloudPullGraphRAG(config) {
|
|
|
6463
6500
|
if (blob.relationship_memories.length > 0) {
|
|
6464
6501
|
const stmts = blob.relationship_memories.map((rm) => ({
|
|
6465
6502
|
sql: `INSERT OR IGNORE INTO relationship_memories (relationship_id, memory_id) VALUES (?, ?)`,
|
|
6466
|
-
args: [rm.relationship_id, rm.memory_id]
|
|
6503
|
+
args: [sqlSafe(rm.relationship_id), sqlSafe(rm.memory_id)]
|
|
6467
6504
|
}));
|
|
6468
6505
|
await client.batch(stmts, "write");
|
|
6469
6506
|
pulled += stmts.length;
|
|
@@ -6472,7 +6509,7 @@ async function cloudPullGraphRAG(config) {
|
|
|
6472
6509
|
const stmts = blob.hyperedges.map((h) => ({
|
|
6473
6510
|
sql: `INSERT OR IGNORE INTO hyperedges (id, label, relation, confidence, timestamp)
|
|
6474
6511
|
VALUES (?, ?, ?, ?, ?)`,
|
|
6475
|
-
args: [h.id, h.label, h.relation, h.confidence ?? 1, h.timestamp]
|
|
6512
|
+
args: [sqlSafe(h.id), sqlSafe(h.label), sqlSafe(h.relation), sqlSafe(h.confidence ?? 1), sqlSafe(h.timestamp)]
|
|
6476
6513
|
}));
|
|
6477
6514
|
await client.batch(stmts, "write");
|
|
6478
6515
|
pulled += stmts.length;
|
|
@@ -6480,7 +6517,7 @@ async function cloudPullGraphRAG(config) {
|
|
|
6480
6517
|
if (blob.hyperedge_nodes.length > 0) {
|
|
6481
6518
|
const stmts = blob.hyperedge_nodes.map((hn) => ({
|
|
6482
6519
|
sql: `INSERT OR IGNORE INTO hyperedge_nodes (hyperedge_id, entity_id) VALUES (?, ?)`,
|
|
6483
|
-
args: [hn.hyperedge_id, hn.entity_id]
|
|
6520
|
+
args: [sqlSafe(hn.hyperedge_id), sqlSafe(hn.entity_id)]
|
|
6484
6521
|
}));
|
|
6485
6522
|
await client.batch(stmts, "write");
|
|
6486
6523
|
pulled += stmts.length;
|
|
@@ -6512,22 +6549,22 @@ async function cloudPullTasks(config) {
|
|
|
6512
6549
|
blocked_by, parent_task_id, budget_tokens, budget_fallback_model, tokens_used, tokens_warned_at)
|
|
6513
6550
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
6514
6551
|
args: [
|
|
6515
|
-
t.id
|
|
6516
|
-
t.title
|
|
6517
|
-
t.assigned_to
|
|
6518
|
-
t.assigned_by
|
|
6519
|
-
t.project_name
|
|
6520
|
-
t.priority ?? "p1",
|
|
6521
|
-
t.status ?? "open",
|
|
6522
|
-
t.task_file
|
|
6523
|
-
t.created_at
|
|
6524
|
-
t.updated_at
|
|
6525
|
-
t.blocked_by
|
|
6526
|
-
t.parent_task_id
|
|
6527
|
-
t.budget_tokens
|
|
6528
|
-
t.budget_fallback_model
|
|
6529
|
-
t.tokens_used ?? 0,
|
|
6530
|
-
t.tokens_warned_at
|
|
6552
|
+
sqlSafe(t.id),
|
|
6553
|
+
sqlSafe(t.title),
|
|
6554
|
+
sqlSafe(t.assigned_to),
|
|
6555
|
+
sqlSafe(t.assigned_by),
|
|
6556
|
+
sqlSafe(t.project_name),
|
|
6557
|
+
sqlSafe(t.priority ?? "p1"),
|
|
6558
|
+
sqlSafe(t.status ?? "open"),
|
|
6559
|
+
sqlSafe(t.task_file),
|
|
6560
|
+
sqlSafe(t.created_at),
|
|
6561
|
+
sqlSafe(t.updated_at),
|
|
6562
|
+
sqlSafe(t.blocked_by),
|
|
6563
|
+
sqlSafe(t.parent_task_id),
|
|
6564
|
+
sqlSafe(t.budget_tokens),
|
|
6565
|
+
sqlSafe(t.budget_fallback_model),
|
|
6566
|
+
sqlSafe(t.tokens_used ?? 0),
|
|
6567
|
+
sqlSafe(t.tokens_warned_at)
|
|
6531
6568
|
]
|
|
6532
6569
|
}));
|
|
6533
6570
|
await client.batch(stmts, "write");
|
|
@@ -6559,24 +6596,24 @@ async function cloudPullConversations(config) {
|
|
|
6559
6596
|
content_metadata, agent_response, agent_name, timestamp, ingested_at)
|
|
6560
6597
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
6561
6598
|
args: [
|
|
6562
|
-
c.id
|
|
6563
|
-
c.platform
|
|
6564
|
-
c.external_id
|
|
6565
|
-
c.sender_id
|
|
6566
|
-
c.sender_name
|
|
6567
|
-
c.sender_phone
|
|
6568
|
-
c.sender_email
|
|
6569
|
-
c.recipient_id
|
|
6570
|
-
c.channel_id
|
|
6571
|
-
c.thread_id
|
|
6572
|
-
c.reply_to_id
|
|
6573
|
-
c.content_text
|
|
6574
|
-
c.content_media
|
|
6575
|
-
c.content_metadata
|
|
6576
|
-
c.agent_response
|
|
6577
|
-
c.agent_name
|
|
6578
|
-
c.timestamp
|
|
6579
|
-
c.ingested_at
|
|
6599
|
+
sqlSafe(c.id),
|
|
6600
|
+
sqlSafe(c.platform),
|
|
6601
|
+
sqlSafe(c.external_id),
|
|
6602
|
+
sqlSafe(c.sender_id),
|
|
6603
|
+
sqlSafe(c.sender_name),
|
|
6604
|
+
sqlSafe(c.sender_phone),
|
|
6605
|
+
sqlSafe(c.sender_email),
|
|
6606
|
+
sqlSafe(c.recipient_id),
|
|
6607
|
+
sqlSafe(c.channel_id),
|
|
6608
|
+
sqlSafe(c.thread_id),
|
|
6609
|
+
sqlSafe(c.reply_to_id),
|
|
6610
|
+
sqlSafe(c.content_text),
|
|
6611
|
+
sqlSafe(c.content_media),
|
|
6612
|
+
sqlSafe(c.content_metadata),
|
|
6613
|
+
sqlSafe(c.agent_response),
|
|
6614
|
+
sqlSafe(c.agent_name),
|
|
6615
|
+
sqlSafe(c.timestamp),
|
|
6616
|
+
sqlSafe(c.ingested_at)
|
|
6580
6617
|
]
|
|
6581
6618
|
}));
|
|
6582
6619
|
await client.batch(stmts, "write");
|
|
@@ -6613,7 +6650,7 @@ async function cloudPullDocuments(config) {
|
|
|
6613
6650
|
const stmts = blob.workspaces.map((w) => ({
|
|
6614
6651
|
sql: `INSERT OR IGNORE INTO workspaces (id, slug, name, owner_agent_id, created_at, metadata)
|
|
6615
6652
|
VALUES (?, ?, ?, ?, ?, ?)`,
|
|
6616
|
-
args: [w.id, w.slug, w.name, w.owner_agent_id
|
|
6653
|
+
args: [sqlSafe(w.id), sqlSafe(w.slug), sqlSafe(w.name), sqlSafe(w.owner_agent_id), sqlSafe(w.created_at), sqlSafe(w.metadata)]
|
|
6617
6654
|
}));
|
|
6618
6655
|
await client.batch(stmts, "write");
|
|
6619
6656
|
pulled += stmts.length;
|
|
@@ -6624,14 +6661,14 @@ async function cloudPullDocuments(config) {
|
|
|
6624
6661
|
(id, workspace_id, filename, mime, source_type, user_id, uploaded_at, metadata)
|
|
6625
6662
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
6626
6663
|
args: [
|
|
6627
|
-
d.id,
|
|
6628
|
-
d.workspace_id,
|
|
6629
|
-
d.filename,
|
|
6630
|
-
d.mime
|
|
6631
|
-
d.source_type
|
|
6632
|
-
d.user_id
|
|
6633
|
-
d.uploaded_at,
|
|
6634
|
-
d.metadata
|
|
6664
|
+
sqlSafe(d.id),
|
|
6665
|
+
sqlSafe(d.workspace_id),
|
|
6666
|
+
sqlSafe(d.filename),
|
|
6667
|
+
sqlSafe(d.mime),
|
|
6668
|
+
sqlSafe(d.source_type),
|
|
6669
|
+
sqlSafe(d.user_id),
|
|
6670
|
+
sqlSafe(d.uploaded_at),
|
|
6671
|
+
sqlSafe(d.metadata)
|
|
6635
6672
|
]
|
|
6636
6673
|
}));
|
|
6637
6674
|
await client.batch(stmts, "write");
|