@askexenow/exe-os 0.8.40 → 0.8.42
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/backfill-conversations.js +805 -642
- package/dist/bin/backfill-responses.js +804 -641
- package/dist/bin/backfill-vectors.js +791 -634
- package/dist/bin/cleanup-stale-review-tasks.js +788 -631
- package/dist/bin/cli.js +1376 -659
- package/dist/bin/exe-agent.js +20 -1
- package/dist/bin/exe-assign.js +1503 -1343
- package/dist/bin/exe-boot.js +2549 -1784
- package/dist/bin/exe-call.js +39 -1
- package/dist/bin/exe-cloud.js +12 -2
- package/dist/bin/exe-dispatch.js +39 -2
- package/dist/bin/exe-doctor.js +791 -634
- package/dist/bin/exe-export-behaviors.js +792 -637
- package/dist/bin/exe-forget.js +145 -0
- package/dist/bin/exe-gateway.js +2501 -1846
- package/dist/bin/exe-heartbeat.js +147 -1
- package/dist/bin/exe-kill.js +795 -640
- package/dist/bin/exe-launch-agent.js +2168 -2008
- package/dist/bin/exe-link.js +44 -12
- package/dist/bin/exe-new-employee.js +6 -2
- package/dist/bin/exe-pending-messages.js +146 -1
- package/dist/bin/exe-pending-notifications.js +788 -631
- package/dist/bin/exe-pending-reviews.js +176 -1
- package/dist/bin/exe-rename.js +23 -0
- package/dist/bin/exe-review.js +490 -327
- package/dist/bin/exe-search.js +157 -4
- package/dist/bin/exe-session-cleanup.js +2487 -403
- package/dist/bin/exe-settings.js +2 -1
- package/dist/bin/exe-status.js +474 -317
- package/dist/bin/exe-team.js +474 -317
- package/dist/bin/git-sweep.js +2691 -151
- package/dist/bin/graph-backfill.js +794 -637
- package/dist/bin/graph-export.js +798 -641
- package/dist/bin/scan-tasks.js +2951 -44
- package/dist/bin/setup.js +50 -26
- package/dist/bin/shard-migrate.js +792 -637
- package/dist/bin/wiki-sync.js +794 -637
- package/dist/gateway/index.js +2542 -1887
- package/dist/hooks/bug-report-worker.js +2118 -576
- package/dist/hooks/commit-complete.js +2690 -150
- package/dist/hooks/error-recall.js +157 -4
- package/dist/hooks/ingest-worker.js +1455 -803
- package/dist/hooks/instructions-loaded.js +151 -0
- package/dist/hooks/notification.js +153 -2
- package/dist/hooks/post-compact.js +164 -0
- package/dist/hooks/pre-compact.js +3073 -101
- package/dist/hooks/pre-tool-use.js +151 -0
- package/dist/hooks/prompt-ingest-worker.js +1670 -1509
- package/dist/hooks/prompt-submit.js +2650 -1074
- package/dist/hooks/response-ingest-worker.js +154 -6
- package/dist/hooks/session-end.js +153 -2
- package/dist/hooks/session-start.js +157 -4
- package/dist/hooks/stop.js +151 -0
- package/dist/hooks/subagent-stop.js +155 -2
- package/dist/hooks/summary-worker.js +190 -21
- package/dist/index.js +326 -102
- package/dist/lib/cloud-sync.js +31 -10
- package/dist/lib/config.js +2 -0
- package/dist/lib/consolidation.js +69 -2
- package/dist/lib/database.js +19 -0
- package/dist/lib/device-registry.js +19 -0
- package/dist/lib/embedder.js +3 -1
- package/dist/lib/employee-templates.js +20 -1
- package/dist/lib/exe-daemon.js +285 -18
- package/dist/lib/hybrid-search.js +157 -4
- package/dist/lib/messaging.js +39 -2
- package/dist/lib/schedules.js +792 -637
- package/dist/lib/store.js +796 -636
- package/dist/lib/tasks.js +1485 -918
- package/dist/lib/tmux-routing.js +194 -10
- package/dist/mcp/server.js +1643 -924
- package/dist/mcp/tools/create-task.js +2283 -829
- package/dist/mcp/tools/list-tasks.js +2788 -159
- package/dist/mcp/tools/send-message.js +39 -2
- package/dist/mcp/tools/update-task.js +79 -0
- package/dist/runtime/index.js +280 -68
- package/dist/tui/App.js +1485 -645
- package/package.json +3 -2
package/dist/lib/tmux-routing.js
CHANGED
|
@@ -749,6 +749,61 @@ var init_session_kill_telemetry = __esm({
|
|
|
749
749
|
}
|
|
750
750
|
});
|
|
751
751
|
|
|
752
|
+
// src/lib/state-bus.ts
|
|
753
|
+
var StateBus, orgBus;
|
|
754
|
+
var init_state_bus = __esm({
|
|
755
|
+
"src/lib/state-bus.ts"() {
|
|
756
|
+
"use strict";
|
|
757
|
+
StateBus = class {
|
|
758
|
+
handlers = /* @__PURE__ */ new Map();
|
|
759
|
+
globalHandlers = /* @__PURE__ */ new Set();
|
|
760
|
+
/** Emit an event to all subscribers */
|
|
761
|
+
emit(event) {
|
|
762
|
+
const typeHandlers = this.handlers.get(event.type);
|
|
763
|
+
if (typeHandlers) {
|
|
764
|
+
for (const handler of typeHandlers) {
|
|
765
|
+
try {
|
|
766
|
+
handler(event);
|
|
767
|
+
} catch {
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
for (const handler of this.globalHandlers) {
|
|
772
|
+
try {
|
|
773
|
+
handler(event);
|
|
774
|
+
} catch {
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
/** Subscribe to a specific event type */
|
|
779
|
+
on(type, handler) {
|
|
780
|
+
if (!this.handlers.has(type)) {
|
|
781
|
+
this.handlers.set(type, /* @__PURE__ */ new Set());
|
|
782
|
+
}
|
|
783
|
+
this.handlers.get(type).add(handler);
|
|
784
|
+
}
|
|
785
|
+
/** Subscribe to ALL events */
|
|
786
|
+
onAny(handler) {
|
|
787
|
+
this.globalHandlers.add(handler);
|
|
788
|
+
}
|
|
789
|
+
/** Unsubscribe from a specific event type */
|
|
790
|
+
off(type, handler) {
|
|
791
|
+
this.handlers.get(type)?.delete(handler);
|
|
792
|
+
}
|
|
793
|
+
/** Unsubscribe from ALL events */
|
|
794
|
+
offAny(handler) {
|
|
795
|
+
this.globalHandlers.delete(handler);
|
|
796
|
+
}
|
|
797
|
+
/** Remove all listeners */
|
|
798
|
+
clear() {
|
|
799
|
+
this.handlers.clear();
|
|
800
|
+
this.globalHandlers.clear();
|
|
801
|
+
}
|
|
802
|
+
};
|
|
803
|
+
orgBus = new StateBus();
|
|
804
|
+
}
|
|
805
|
+
});
|
|
806
|
+
|
|
752
807
|
// src/lib/tasks-crud.ts
|
|
753
808
|
import crypto3 from "crypto";
|
|
754
809
|
import path8 from "path";
|
|
@@ -892,9 +947,15 @@ async function createTaskCore(input) {
|
|
|
892
947
|
}
|
|
893
948
|
}
|
|
894
949
|
const complexity = input.complexity ?? "standard";
|
|
950
|
+
let sessionScope = null;
|
|
951
|
+
try {
|
|
952
|
+
const { resolveExeSession: resolveExeSession2 } = await Promise.resolve().then(() => (init_tmux_routing(), tmux_routing_exports));
|
|
953
|
+
sessionScope = resolveExeSession2();
|
|
954
|
+
} catch {
|
|
955
|
+
}
|
|
895
956
|
await client.execute({
|
|
896
|
-
sql: `INSERT INTO tasks (id, title, assigned_to, assigned_by, project_name, priority, status, task_file, blocked_by, parent_task_id, reviewer, context, complexity, budget_tokens, budget_fallback_model, tokens_used, tokens_warned_at, created_at, updated_at)
|
|
897
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
957
|
+
sql: `INSERT INTO tasks (id, title, assigned_to, assigned_by, project_name, priority, status, task_file, blocked_by, parent_task_id, reviewer, context, complexity, budget_tokens, budget_fallback_model, tokens_used, tokens_warned_at, session_scope, created_at, updated_at)
|
|
958
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
898
959
|
args: [
|
|
899
960
|
id,
|
|
900
961
|
input.title,
|
|
@@ -913,6 +974,7 @@ async function createTaskCore(input) {
|
|
|
913
974
|
input.budgetFallbackModel ?? null,
|
|
914
975
|
0,
|
|
915
976
|
null,
|
|
977
|
+
sessionScope,
|
|
916
978
|
now,
|
|
917
979
|
now
|
|
918
980
|
]
|
|
@@ -957,9 +1019,18 @@ async function listTasks(input) {
|
|
|
957
1019
|
conditions.push("priority = ?");
|
|
958
1020
|
args.push(input.priority);
|
|
959
1021
|
}
|
|
1022
|
+
try {
|
|
1023
|
+
const { resolveExeSession: resolveExeSession2 } = await Promise.resolve().then(() => (init_tmux_routing(), tmux_routing_exports));
|
|
1024
|
+
const session = resolveExeSession2();
|
|
1025
|
+
if (session) {
|
|
1026
|
+
conditions.push("(session_scope IS NULL OR session_scope = ?)");
|
|
1027
|
+
args.push(session);
|
|
1028
|
+
}
|
|
1029
|
+
} catch {
|
|
1030
|
+
}
|
|
960
1031
|
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
961
1032
|
const result = await client.execute({
|
|
962
|
-
sql: `SELECT * FROM tasks ${where} ORDER BY CASE status WHEN 'blocked' THEN 0 WHEN 'in_progress' THEN 1 WHEN 'open' THEN 2 ELSE 3 END, priority ASC, created_at DESC`,
|
|
1033
|
+
sql: `SELECT * FROM tasks ${where} ORDER BY CASE status WHEN 'blocked' THEN 0 WHEN 'in_progress' THEN 1 WHEN 'open' THEN 2 ELSE 3 END, priority ASC, created_at DESC LIMIT 1000`,
|
|
963
1034
|
args
|
|
964
1035
|
});
|
|
965
1036
|
return result.rows.map((r) => ({
|
|
@@ -1180,6 +1251,34 @@ async function listPendingReviews(limit) {
|
|
|
1180
1251
|
});
|
|
1181
1252
|
return result.rows;
|
|
1182
1253
|
}
|
|
1254
|
+
async function cleanupOrphanedReviews() {
|
|
1255
|
+
const client = getClient();
|
|
1256
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1257
|
+
const r1 = await client.execute({
|
|
1258
|
+
sql: `UPDATE tasks SET status = 'done', updated_at = ?
|
|
1259
|
+
WHERE status = 'needs_review'
|
|
1260
|
+
AND assigned_by = 'system'
|
|
1261
|
+
AND title LIKE 'Review:%'
|
|
1262
|
+
AND parent_task_id IN (SELECT id FROM tasks WHERE status IN ('done', 'cancelled'))`,
|
|
1263
|
+
args: [now]
|
|
1264
|
+
});
|
|
1265
|
+
const staleThreshold = new Date(Date.now() - 60 * 60 * 1e3).toISOString();
|
|
1266
|
+
const r2 = await client.execute({
|
|
1267
|
+
sql: `UPDATE tasks SET status = 'done', updated_at = ?
|
|
1268
|
+
WHERE status = 'needs_review'
|
|
1269
|
+
AND result IS NOT NULL
|
|
1270
|
+
AND updated_at < ?`,
|
|
1271
|
+
args: [now, staleThreshold]
|
|
1272
|
+
});
|
|
1273
|
+
const total = r1.rowsAffected + r2.rowsAffected;
|
|
1274
|
+
if (total > 0) {
|
|
1275
|
+
process.stderr.write(
|
|
1276
|
+
`[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r2.rowsAffected} stale
|
|
1277
|
+
`
|
|
1278
|
+
);
|
|
1279
|
+
}
|
|
1280
|
+
return total;
|
|
1281
|
+
}
|
|
1183
1282
|
function getReviewChecklist(role, agent, taskSlug) {
|
|
1184
1283
|
const roleLower = role.toLowerCase();
|
|
1185
1284
|
if (roleLower.includes("engineer") || roleLower === "principal engineer") {
|
|
@@ -1293,6 +1392,7 @@ var init_tasks_review = __esm({
|
|
|
1293
1392
|
init_tasks_crud();
|
|
1294
1393
|
init_tmux_routing();
|
|
1295
1394
|
init_session_key();
|
|
1395
|
+
init_state_bus();
|
|
1296
1396
|
}
|
|
1297
1397
|
});
|
|
1298
1398
|
|
|
@@ -1457,13 +1557,12 @@ function assertSessionScope(actionType, targetProject) {
|
|
|
1457
1557
|
};
|
|
1458
1558
|
}
|
|
1459
1559
|
process.stderr.write(
|
|
1460
|
-
`[session-scope]
|
|
1560
|
+
`[session-scope] BLOCKED cross-project ${actionType}: session project="${currentProject}" \u2260 target project="${targetProject}"
|
|
1461
1561
|
`
|
|
1462
1562
|
);
|
|
1463
1563
|
return {
|
|
1464
|
-
allowed:
|
|
1465
|
-
|
|
1466
|
-
reason: "cross_session_granted",
|
|
1564
|
+
allowed: false,
|
|
1565
|
+
reason: "cross_session_denied",
|
|
1467
1566
|
currentProject,
|
|
1468
1567
|
targetProject,
|
|
1469
1568
|
targetSession: findSessionForProject(targetProject)?.windowName
|
|
@@ -1489,8 +1588,9 @@ async function dispatchTaskToEmployee(input) {
|
|
|
1489
1588
|
try {
|
|
1490
1589
|
const { assertSessionScope: assertSessionScope2 } = (init_session_scope(), __toCommonJS(session_scope_exports));
|
|
1491
1590
|
const check = assertSessionScope2("dispatch_task", input.projectName);
|
|
1492
|
-
if (check.reason === "
|
|
1591
|
+
if (check.reason === "cross_session_denied") {
|
|
1493
1592
|
crossProject = true;
|
|
1593
|
+
return { dispatched: "skipped", crossProject: true };
|
|
1494
1594
|
}
|
|
1495
1595
|
} catch {
|
|
1496
1596
|
}
|
|
@@ -1859,6 +1959,7 @@ var init_skill_learning = __esm({
|
|
|
1859
1959
|
// src/lib/tasks.ts
|
|
1860
1960
|
var tasks_exports = {};
|
|
1861
1961
|
__export(tasks_exports, {
|
|
1962
|
+
cleanupOrphanedReviews: () => cleanupOrphanedReviews,
|
|
1862
1963
|
countNewPendingReviewsSince: () => countNewPendingReviewsSince,
|
|
1863
1964
|
countPendingReviews: () => countPendingReviews,
|
|
1864
1965
|
createTask: () => createTask,
|
|
@@ -1924,6 +2025,21 @@ async function updateTask(input) {
|
|
|
1924
2025
|
});
|
|
1925
2026
|
} catch {
|
|
1926
2027
|
}
|
|
2028
|
+
try {
|
|
2029
|
+
const client = getClient();
|
|
2030
|
+
const cascaded = await client.execute({
|
|
2031
|
+
sql: `UPDATE tasks SET status = 'done', updated_at = ?
|
|
2032
|
+
WHERE parent_task_id = ? AND status = 'needs_review'`,
|
|
2033
|
+
args: [now, taskId]
|
|
2034
|
+
});
|
|
2035
|
+
if (cascaded.rowsAffected > 0) {
|
|
2036
|
+
process.stderr.write(
|
|
2037
|
+
`[cascade] Closed ${cascaded.rowsAffected} orphaned review task(s) for parent ${taskId}
|
|
2038
|
+
`
|
|
2039
|
+
);
|
|
2040
|
+
}
|
|
2041
|
+
} catch {
|
|
2042
|
+
}
|
|
1927
2043
|
}
|
|
1928
2044
|
const isTerminal = input.status === "done" || input.status === "needs_review";
|
|
1929
2045
|
if (isTerminal) {
|
|
@@ -1937,6 +2053,13 @@ async function updateTask(input) {
|
|
|
1937
2053
|
await cascadeUnblock(taskId, input.baseDir, now);
|
|
1938
2054
|
} catch {
|
|
1939
2055
|
}
|
|
2056
|
+
orgBus.emit({
|
|
2057
|
+
type: "task_completed",
|
|
2058
|
+
taskId,
|
|
2059
|
+
employee: String(row.assigned_to),
|
|
2060
|
+
result: input.result ?? "",
|
|
2061
|
+
timestamp: now
|
|
2062
|
+
});
|
|
1940
2063
|
if (row.parent_task_id) {
|
|
1941
2064
|
try {
|
|
1942
2065
|
await checkSubtaskCompletion(String(row.parent_task_id), String(row.project_name));
|
|
@@ -2004,6 +2127,7 @@ var init_tasks = __esm({
|
|
|
2004
2127
|
init_database();
|
|
2005
2128
|
init_config();
|
|
2006
2129
|
init_notifications();
|
|
2130
|
+
init_state_bus();
|
|
2007
2131
|
init_tasks_crud();
|
|
2008
2132
|
init_tasks_review();
|
|
2009
2133
|
init_tasks_crud();
|
|
@@ -2294,6 +2418,29 @@ var init_capacity_monitor = __esm({
|
|
|
2294
2418
|
});
|
|
2295
2419
|
|
|
2296
2420
|
// src/lib/tmux-routing.ts
|
|
2421
|
+
var tmux_routing_exports = {};
|
|
2422
|
+
__export(tmux_routing_exports, {
|
|
2423
|
+
acquireSpawnLock: () => acquireSpawnLock,
|
|
2424
|
+
employeeSessionName: () => employeeSessionName,
|
|
2425
|
+
ensureEmployee: () => ensureEmployee,
|
|
2426
|
+
extractRootExe: () => extractRootExe,
|
|
2427
|
+
findFreeInstance: () => findFreeInstance,
|
|
2428
|
+
getDispatchedBy: () => getDispatchedBy,
|
|
2429
|
+
getMySession: () => getMySession,
|
|
2430
|
+
getParentExe: () => getParentExe,
|
|
2431
|
+
getSessionState: () => getSessionState,
|
|
2432
|
+
isEmployeeAlive: () => isEmployeeAlive,
|
|
2433
|
+
isExeSession: () => isExeSession,
|
|
2434
|
+
isSessionBusy: () => isSessionBusy,
|
|
2435
|
+
notifyParentExe: () => notifyParentExe,
|
|
2436
|
+
parseParentExe: () => parseParentExe,
|
|
2437
|
+
registerParentExe: () => registerParentExe,
|
|
2438
|
+
releaseSpawnLock: () => releaseSpawnLock,
|
|
2439
|
+
resolveExeSession: () => resolveExeSession,
|
|
2440
|
+
sendIntercom: () => sendIntercom,
|
|
2441
|
+
spawnEmployee: () => spawnEmployee,
|
|
2442
|
+
verifyPaneAtCapacity: () => verifyPaneAtCapacity
|
|
2443
|
+
});
|
|
2297
2444
|
import { execFileSync as execFileSync2, execSync as execSync6 } from "child_process";
|
|
2298
2445
|
import { readFileSync as readFileSync9, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, existsSync as existsSync10, appendFileSync } from "fs";
|
|
2299
2446
|
import path13 from "path";
|
|
@@ -2371,8 +2518,28 @@ function getMySession() {
|
|
|
2371
2518
|
return getTransport().getMySession();
|
|
2372
2519
|
}
|
|
2373
2520
|
function employeeSessionName(employee, exeSession, instance) {
|
|
2521
|
+
if (!/^exe\d+$/.test(exeSession)) {
|
|
2522
|
+
const root = extractRootExe(exeSession);
|
|
2523
|
+
if (root) {
|
|
2524
|
+
process.stderr.write(
|
|
2525
|
+
`[tmux-routing] WARN: exeSession="${exeSession}" is not a root exe session, using "${root}" instead
|
|
2526
|
+
`
|
|
2527
|
+
);
|
|
2528
|
+
exeSession = root;
|
|
2529
|
+
} else {
|
|
2530
|
+
throw new Error(
|
|
2531
|
+
`Invalid exeSession "${exeSession}" \u2014 must be a root exe session (e.g., "exe1"), not an agent session`
|
|
2532
|
+
);
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2374
2535
|
const suffix = instance != null && instance > 0 ? String(instance) : "";
|
|
2375
|
-
|
|
2536
|
+
const name = `${employee}${suffix}-${exeSession}`;
|
|
2537
|
+
if (!VALID_SESSION_NAME.test(name)) {
|
|
2538
|
+
throw new Error(
|
|
2539
|
+
`Invalid session name "${name}" \u2014 must match {agent}-exe{N} or {agent}{instance}-exe{N}`
|
|
2540
|
+
);
|
|
2541
|
+
}
|
|
2542
|
+
return name;
|
|
2376
2543
|
}
|
|
2377
2544
|
function parseParentExe(sessionName, agentId) {
|
|
2378
2545
|
const escaped = agentId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -2612,6 +2779,22 @@ function ensureEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
2612
2779
|
error: `Error: pass employee name ('${bare}'), not session name ('${employeeName}')`
|
|
2613
2780
|
};
|
|
2614
2781
|
}
|
|
2782
|
+
if (!/^exe\d+$/.test(exeSession)) {
|
|
2783
|
+
const root = extractRootExe(exeSession);
|
|
2784
|
+
if (root) {
|
|
2785
|
+
process.stderr.write(
|
|
2786
|
+
`[ensureEmployee] WARN: caller passed exeSession="${exeSession}" (not a root exe). Auto-correcting to "${root}".
|
|
2787
|
+
`
|
|
2788
|
+
);
|
|
2789
|
+
exeSession = root;
|
|
2790
|
+
} else {
|
|
2791
|
+
return {
|
|
2792
|
+
status: "failed",
|
|
2793
|
+
sessionName: "",
|
|
2794
|
+
error: `Invalid exeSession "${exeSession}" \u2014 must be a root exe session (e.g., "exe1")`
|
|
2795
|
+
};
|
|
2796
|
+
}
|
|
2797
|
+
}
|
|
2615
2798
|
let effectiveInstance = opts?.instance;
|
|
2616
2799
|
if (effectiveInstance === void 0 && opts?.autoInstance) {
|
|
2617
2800
|
const free = findFreeInstance(
|
|
@@ -2858,7 +3041,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
2858
3041
|
releaseSpawnLock(sessionName);
|
|
2859
3042
|
return { sessionName };
|
|
2860
3043
|
}
|
|
2861
|
-
var SPAWN_LOCK_DIR, SESSION_CACHE, BEHAVIORS_EXPORT_TIMEOUT_MS, VERIFY_PANE_LINES, INTERCOM_DEBOUNCE_MS, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS, BUSY_PATTERN;
|
|
3044
|
+
var SPAWN_LOCK_DIR, SESSION_CACHE, BEHAVIORS_EXPORT_TIMEOUT_MS, VALID_SESSION_NAME, VERIFY_PANE_LINES, INTERCOM_DEBOUNCE_MS, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS, BUSY_PATTERN;
|
|
2862
3045
|
var init_tmux_routing = __esm({
|
|
2863
3046
|
"src/lib/tmux-routing.ts"() {
|
|
2864
3047
|
init_session_registry();
|
|
@@ -2872,6 +3055,7 @@ var init_tmux_routing = __esm({
|
|
|
2872
3055
|
SPAWN_LOCK_DIR = path13.join(os5.homedir(), ".exe-os", "spawn-locks");
|
|
2873
3056
|
SESSION_CACHE = path13.join(os5.homedir(), ".exe-os", "session-cache");
|
|
2874
3057
|
BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
|
|
3058
|
+
VALID_SESSION_NAME = /^[a-z]+-exe\d+$|^[a-z]+\d+-exe\d+$/;
|
|
2875
3059
|
VERIFY_PANE_LINES = 200;
|
|
2876
3060
|
INTERCOM_DEBOUNCE_MS = 3e4;
|
|
2877
3061
|
INTERCOM_LOG2 = path13.join(os5.homedir(), ".exe-os", "intercom.log");
|