@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/runtime/index.js
CHANGED
|
@@ -666,6 +666,13 @@ async function ensureSchema() {
|
|
|
666
666
|
});
|
|
667
667
|
} catch {
|
|
668
668
|
}
|
|
669
|
+
try {
|
|
670
|
+
await client.execute({
|
|
671
|
+
sql: `ALTER TABLE tasks ADD COLUMN session_scope TEXT`,
|
|
672
|
+
args: []
|
|
673
|
+
});
|
|
674
|
+
} catch {
|
|
675
|
+
}
|
|
669
676
|
try {
|
|
670
677
|
await client.execute({
|
|
671
678
|
sql: `ALTER TABLE memories ADD COLUMN task_id TEXT`,
|
|
@@ -1112,6 +1119,18 @@ async function ensureSchema() {
|
|
|
1112
1119
|
CREATE INDEX IF NOT EXISTS idx_session_kills_agent
|
|
1113
1120
|
ON session_kills(agent_id);
|
|
1114
1121
|
`);
|
|
1122
|
+
await client.execute(`
|
|
1123
|
+
CREATE TABLE IF NOT EXISTS global_procedures (
|
|
1124
|
+
id TEXT PRIMARY KEY,
|
|
1125
|
+
title TEXT NOT NULL,
|
|
1126
|
+
content TEXT NOT NULL,
|
|
1127
|
+
priority TEXT NOT NULL DEFAULT 'p0',
|
|
1128
|
+
domain TEXT,
|
|
1129
|
+
active INTEGER NOT NULL DEFAULT 1,
|
|
1130
|
+
created_at TEXT NOT NULL,
|
|
1131
|
+
updated_at TEXT NOT NULL
|
|
1132
|
+
)
|
|
1133
|
+
`);
|
|
1115
1134
|
await client.executeMultiple(`
|
|
1116
1135
|
CREATE TABLE IF NOT EXISTS conversations (
|
|
1117
1136
|
id TEXT PRIMARY KEY,
|
|
@@ -1677,6 +1696,61 @@ var init_session_kill_telemetry = __esm({
|
|
|
1677
1696
|
}
|
|
1678
1697
|
});
|
|
1679
1698
|
|
|
1699
|
+
// src/lib/state-bus.ts
|
|
1700
|
+
var StateBus, orgBus;
|
|
1701
|
+
var init_state_bus = __esm({
|
|
1702
|
+
"src/lib/state-bus.ts"() {
|
|
1703
|
+
"use strict";
|
|
1704
|
+
StateBus = class {
|
|
1705
|
+
handlers = /* @__PURE__ */ new Map();
|
|
1706
|
+
globalHandlers = /* @__PURE__ */ new Set();
|
|
1707
|
+
/** Emit an event to all subscribers */
|
|
1708
|
+
emit(event) {
|
|
1709
|
+
const typeHandlers = this.handlers.get(event.type);
|
|
1710
|
+
if (typeHandlers) {
|
|
1711
|
+
for (const handler of typeHandlers) {
|
|
1712
|
+
try {
|
|
1713
|
+
handler(event);
|
|
1714
|
+
} catch {
|
|
1715
|
+
}
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
for (const handler of this.globalHandlers) {
|
|
1719
|
+
try {
|
|
1720
|
+
handler(event);
|
|
1721
|
+
} catch {
|
|
1722
|
+
}
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
/** Subscribe to a specific event type */
|
|
1726
|
+
on(type, handler) {
|
|
1727
|
+
if (!this.handlers.has(type)) {
|
|
1728
|
+
this.handlers.set(type, /* @__PURE__ */ new Set());
|
|
1729
|
+
}
|
|
1730
|
+
this.handlers.get(type).add(handler);
|
|
1731
|
+
}
|
|
1732
|
+
/** Subscribe to ALL events */
|
|
1733
|
+
onAny(handler) {
|
|
1734
|
+
this.globalHandlers.add(handler);
|
|
1735
|
+
}
|
|
1736
|
+
/** Unsubscribe from a specific event type */
|
|
1737
|
+
off(type, handler) {
|
|
1738
|
+
this.handlers.get(type)?.delete(handler);
|
|
1739
|
+
}
|
|
1740
|
+
/** Unsubscribe from ALL events */
|
|
1741
|
+
offAny(handler) {
|
|
1742
|
+
this.globalHandlers.delete(handler);
|
|
1743
|
+
}
|
|
1744
|
+
/** Remove all listeners */
|
|
1745
|
+
clear() {
|
|
1746
|
+
this.handlers.clear();
|
|
1747
|
+
this.globalHandlers.clear();
|
|
1748
|
+
}
|
|
1749
|
+
};
|
|
1750
|
+
orgBus = new StateBus();
|
|
1751
|
+
}
|
|
1752
|
+
});
|
|
1753
|
+
|
|
1680
1754
|
// src/lib/tasks-crud.ts
|
|
1681
1755
|
import crypto3 from "crypto";
|
|
1682
1756
|
import path9 from "path";
|
|
@@ -1820,9 +1894,15 @@ async function createTaskCore(input) {
|
|
|
1820
1894
|
}
|
|
1821
1895
|
}
|
|
1822
1896
|
const complexity = input.complexity ?? "standard";
|
|
1897
|
+
let sessionScope = null;
|
|
1898
|
+
try {
|
|
1899
|
+
const { resolveExeSession: resolveExeSession2 } = await Promise.resolve().then(() => (init_tmux_routing(), tmux_routing_exports));
|
|
1900
|
+
sessionScope = resolveExeSession2();
|
|
1901
|
+
} catch {
|
|
1902
|
+
}
|
|
1823
1903
|
await client.execute({
|
|
1824
|
-
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)
|
|
1825
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
1904
|
+
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)
|
|
1905
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
1826
1906
|
args: [
|
|
1827
1907
|
id,
|
|
1828
1908
|
input.title,
|
|
@@ -1841,6 +1921,7 @@ async function createTaskCore(input) {
|
|
|
1841
1921
|
input.budgetFallbackModel ?? null,
|
|
1842
1922
|
0,
|
|
1843
1923
|
null,
|
|
1924
|
+
sessionScope,
|
|
1844
1925
|
now,
|
|
1845
1926
|
now
|
|
1846
1927
|
]
|
|
@@ -1885,9 +1966,18 @@ async function listTasks(input) {
|
|
|
1885
1966
|
conditions.push("priority = ?");
|
|
1886
1967
|
args.push(input.priority);
|
|
1887
1968
|
}
|
|
1969
|
+
try {
|
|
1970
|
+
const { resolveExeSession: resolveExeSession2 } = await Promise.resolve().then(() => (init_tmux_routing(), tmux_routing_exports));
|
|
1971
|
+
const session = resolveExeSession2();
|
|
1972
|
+
if (session) {
|
|
1973
|
+
conditions.push("(session_scope IS NULL OR session_scope = ?)");
|
|
1974
|
+
args.push(session);
|
|
1975
|
+
}
|
|
1976
|
+
} catch {
|
|
1977
|
+
}
|
|
1888
1978
|
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
1889
1979
|
const result = await client.execute({
|
|
1890
|
-
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`,
|
|
1980
|
+
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`,
|
|
1891
1981
|
args
|
|
1892
1982
|
});
|
|
1893
1983
|
return result.rows.map((r) => ({
|
|
@@ -2108,6 +2198,34 @@ async function listPendingReviews(limit) {
|
|
|
2108
2198
|
});
|
|
2109
2199
|
return result.rows;
|
|
2110
2200
|
}
|
|
2201
|
+
async function cleanupOrphanedReviews() {
|
|
2202
|
+
const client = getClient();
|
|
2203
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2204
|
+
const r1 = await client.execute({
|
|
2205
|
+
sql: `UPDATE tasks SET status = 'done', updated_at = ?
|
|
2206
|
+
WHERE status = 'needs_review'
|
|
2207
|
+
AND assigned_by = 'system'
|
|
2208
|
+
AND title LIKE 'Review:%'
|
|
2209
|
+
AND parent_task_id IN (SELECT id FROM tasks WHERE status IN ('done', 'cancelled'))`,
|
|
2210
|
+
args: [now]
|
|
2211
|
+
});
|
|
2212
|
+
const staleThreshold = new Date(Date.now() - 60 * 60 * 1e3).toISOString();
|
|
2213
|
+
const r2 = await client.execute({
|
|
2214
|
+
sql: `UPDATE tasks SET status = 'done', updated_at = ?
|
|
2215
|
+
WHERE status = 'needs_review'
|
|
2216
|
+
AND result IS NOT NULL
|
|
2217
|
+
AND updated_at < ?`,
|
|
2218
|
+
args: [now, staleThreshold]
|
|
2219
|
+
});
|
|
2220
|
+
const total = r1.rowsAffected + r2.rowsAffected;
|
|
2221
|
+
if (total > 0) {
|
|
2222
|
+
process.stderr.write(
|
|
2223
|
+
`[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r2.rowsAffected} stale
|
|
2224
|
+
`
|
|
2225
|
+
);
|
|
2226
|
+
}
|
|
2227
|
+
return total;
|
|
2228
|
+
}
|
|
2111
2229
|
function getReviewChecklist(role, agent, taskSlug) {
|
|
2112
2230
|
const roleLower = role.toLowerCase();
|
|
2113
2231
|
if (roleLower.includes("engineer") || roleLower === "principal engineer") {
|
|
@@ -2221,6 +2339,7 @@ var init_tasks_review = __esm({
|
|
|
2221
2339
|
init_tasks_crud();
|
|
2222
2340
|
init_tmux_routing();
|
|
2223
2341
|
init_session_key();
|
|
2342
|
+
init_state_bus();
|
|
2224
2343
|
}
|
|
2225
2344
|
});
|
|
2226
2345
|
|
|
@@ -2385,13 +2504,12 @@ function assertSessionScope(actionType, targetProject) {
|
|
|
2385
2504
|
};
|
|
2386
2505
|
}
|
|
2387
2506
|
process.stderr.write(
|
|
2388
|
-
`[session-scope]
|
|
2507
|
+
`[session-scope] BLOCKED cross-project ${actionType}: session project="${currentProject}" \u2260 target project="${targetProject}"
|
|
2389
2508
|
`
|
|
2390
2509
|
);
|
|
2391
2510
|
return {
|
|
2392
|
-
allowed:
|
|
2393
|
-
|
|
2394
|
-
reason: "cross_session_granted",
|
|
2511
|
+
allowed: false,
|
|
2512
|
+
reason: "cross_session_denied",
|
|
2395
2513
|
currentProject,
|
|
2396
2514
|
targetProject,
|
|
2397
2515
|
targetSession: findSessionForProject(targetProject)?.windowName
|
|
@@ -2417,8 +2535,9 @@ async function dispatchTaskToEmployee(input) {
|
|
|
2417
2535
|
try {
|
|
2418
2536
|
const { assertSessionScope: assertSessionScope2 } = (init_session_scope(), __toCommonJS(session_scope_exports));
|
|
2419
2537
|
const check = assertSessionScope2("dispatch_task", input.projectName);
|
|
2420
|
-
if (check.reason === "
|
|
2538
|
+
if (check.reason === "cross_session_denied") {
|
|
2421
2539
|
crossProject = true;
|
|
2540
|
+
return { dispatched: "skipped", crossProject: true };
|
|
2422
2541
|
}
|
|
2423
2542
|
} catch {
|
|
2424
2543
|
}
|
|
@@ -2849,6 +2968,7 @@ var init_skill_learning = __esm({
|
|
|
2849
2968
|
// src/lib/tasks.ts
|
|
2850
2969
|
var tasks_exports = {};
|
|
2851
2970
|
__export(tasks_exports, {
|
|
2971
|
+
cleanupOrphanedReviews: () => cleanupOrphanedReviews,
|
|
2852
2972
|
countNewPendingReviewsSince: () => countNewPendingReviewsSince,
|
|
2853
2973
|
countPendingReviews: () => countPendingReviews,
|
|
2854
2974
|
createTask: () => createTask,
|
|
@@ -2914,6 +3034,21 @@ async function updateTask(input) {
|
|
|
2914
3034
|
});
|
|
2915
3035
|
} catch {
|
|
2916
3036
|
}
|
|
3037
|
+
try {
|
|
3038
|
+
const client = getClient();
|
|
3039
|
+
const cascaded = await client.execute({
|
|
3040
|
+
sql: `UPDATE tasks SET status = 'done', updated_at = ?
|
|
3041
|
+
WHERE parent_task_id = ? AND status = 'needs_review'`,
|
|
3042
|
+
args: [now, taskId]
|
|
3043
|
+
});
|
|
3044
|
+
if (cascaded.rowsAffected > 0) {
|
|
3045
|
+
process.stderr.write(
|
|
3046
|
+
`[cascade] Closed ${cascaded.rowsAffected} orphaned review task(s) for parent ${taskId}
|
|
3047
|
+
`
|
|
3048
|
+
);
|
|
3049
|
+
}
|
|
3050
|
+
} catch {
|
|
3051
|
+
}
|
|
2917
3052
|
}
|
|
2918
3053
|
const isTerminal = input.status === "done" || input.status === "needs_review";
|
|
2919
3054
|
if (isTerminal) {
|
|
@@ -2927,6 +3062,13 @@ async function updateTask(input) {
|
|
|
2927
3062
|
await cascadeUnblock(taskId, input.baseDir, now);
|
|
2928
3063
|
} catch {
|
|
2929
3064
|
}
|
|
3065
|
+
orgBus.emit({
|
|
3066
|
+
type: "task_completed",
|
|
3067
|
+
taskId,
|
|
3068
|
+
employee: String(row.assigned_to),
|
|
3069
|
+
result: input.result ?? "",
|
|
3070
|
+
timestamp: now
|
|
3071
|
+
});
|
|
2930
3072
|
if (row.parent_task_id) {
|
|
2931
3073
|
try {
|
|
2932
3074
|
await checkSubtaskCompletion(String(row.parent_task_id), String(row.project_name));
|
|
@@ -2994,6 +3136,7 @@ var init_tasks = __esm({
|
|
|
2994
3136
|
init_database();
|
|
2995
3137
|
init_config();
|
|
2996
3138
|
init_notifications();
|
|
3139
|
+
init_state_bus();
|
|
2997
3140
|
init_tasks_crud();
|
|
2998
3141
|
init_tasks_review();
|
|
2999
3142
|
init_tasks_crud();
|
|
@@ -3384,8 +3527,28 @@ function getMySession() {
|
|
|
3384
3527
|
return getTransport().getMySession();
|
|
3385
3528
|
}
|
|
3386
3529
|
function employeeSessionName(employee, exeSession, instance) {
|
|
3530
|
+
if (!/^exe\d+$/.test(exeSession)) {
|
|
3531
|
+
const root = extractRootExe(exeSession);
|
|
3532
|
+
if (root) {
|
|
3533
|
+
process.stderr.write(
|
|
3534
|
+
`[tmux-routing] WARN: exeSession="${exeSession}" is not a root exe session, using "${root}" instead
|
|
3535
|
+
`
|
|
3536
|
+
);
|
|
3537
|
+
exeSession = root;
|
|
3538
|
+
} else {
|
|
3539
|
+
throw new Error(
|
|
3540
|
+
`Invalid exeSession "${exeSession}" \u2014 must be a root exe session (e.g., "exe1"), not an agent session`
|
|
3541
|
+
);
|
|
3542
|
+
}
|
|
3543
|
+
}
|
|
3387
3544
|
const suffix = instance != null && instance > 0 ? String(instance) : "";
|
|
3388
|
-
|
|
3545
|
+
const name = `${employee}${suffix}-${exeSession}`;
|
|
3546
|
+
if (!VALID_SESSION_NAME.test(name)) {
|
|
3547
|
+
throw new Error(
|
|
3548
|
+
`Invalid session name "${name}" \u2014 must match {agent}-exe{N} or {agent}{instance}-exe{N}`
|
|
3549
|
+
);
|
|
3550
|
+
}
|
|
3551
|
+
return name;
|
|
3389
3552
|
}
|
|
3390
3553
|
function parseParentExe(sessionName, agentId) {
|
|
3391
3554
|
const escaped = agentId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -3625,6 +3788,22 @@ function ensureEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
3625
3788
|
error: `Error: pass employee name ('${bare}'), not session name ('${employeeName}')`
|
|
3626
3789
|
};
|
|
3627
3790
|
}
|
|
3791
|
+
if (!/^exe\d+$/.test(exeSession)) {
|
|
3792
|
+
const root = extractRootExe(exeSession);
|
|
3793
|
+
if (root) {
|
|
3794
|
+
process.stderr.write(
|
|
3795
|
+
`[ensureEmployee] WARN: caller passed exeSession="${exeSession}" (not a root exe). Auto-correcting to "${root}".
|
|
3796
|
+
`
|
|
3797
|
+
);
|
|
3798
|
+
exeSession = root;
|
|
3799
|
+
} else {
|
|
3800
|
+
return {
|
|
3801
|
+
status: "failed",
|
|
3802
|
+
sessionName: "",
|
|
3803
|
+
error: `Invalid exeSession "${exeSession}" \u2014 must be a root exe session (e.g., "exe1")`
|
|
3804
|
+
};
|
|
3805
|
+
}
|
|
3806
|
+
}
|
|
3628
3807
|
let effectiveInstance = opts?.instance;
|
|
3629
3808
|
if (effectiveInstance === void 0 && opts?.autoInstance) {
|
|
3630
3809
|
const free = findFreeInstance(
|
|
@@ -3871,7 +4050,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
3871
4050
|
releaseSpawnLock(sessionName);
|
|
3872
4051
|
return { sessionName };
|
|
3873
4052
|
}
|
|
3874
|
-
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;
|
|
4053
|
+
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;
|
|
3875
4054
|
var init_tmux_routing = __esm({
|
|
3876
4055
|
"src/lib/tmux-routing.ts"() {
|
|
3877
4056
|
"use strict";
|
|
@@ -3886,6 +4065,7 @@ var init_tmux_routing = __esm({
|
|
|
3886
4065
|
SPAWN_LOCK_DIR = path14.join(os6.homedir(), ".exe-os", "spawn-locks");
|
|
3887
4066
|
SESSION_CACHE = path14.join(os6.homedir(), ".exe-os", "session-cache");
|
|
3888
4067
|
BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
|
|
4068
|
+
VALID_SESSION_NAME = /^[a-z]+-exe\d+$|^[a-z]+\d+-exe\d+$/;
|
|
3889
4069
|
VERIFY_PANE_LINES = 200;
|
|
3890
4070
|
INTERCOM_DEBOUNCE_MS = 3e4;
|
|
3891
4071
|
INTERCOM_LOG2 = path14.join(os6.homedir(), ".exe-os", "intercom.log");
|
|
@@ -4195,6 +4375,71 @@ var init_shard_manager = __esm({
|
|
|
4195
4375
|
}
|
|
4196
4376
|
});
|
|
4197
4377
|
|
|
4378
|
+
// src/lib/global-procedures.ts
|
|
4379
|
+
var global_procedures_exports = {};
|
|
4380
|
+
__export(global_procedures_exports, {
|
|
4381
|
+
deactivateGlobalProcedure: () => deactivateGlobalProcedure,
|
|
4382
|
+
getGlobalProceduresBlock: () => getGlobalProceduresBlock,
|
|
4383
|
+
loadGlobalProcedures: () => loadGlobalProcedures,
|
|
4384
|
+
storeGlobalProcedure: () => storeGlobalProcedure
|
|
4385
|
+
});
|
|
4386
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
4387
|
+
async function loadGlobalProcedures() {
|
|
4388
|
+
const client = getClient();
|
|
4389
|
+
const result = await client.execute({
|
|
4390
|
+
sql: "SELECT * FROM global_procedures WHERE active = 1 ORDER BY priority ASC, created_at ASC",
|
|
4391
|
+
args: []
|
|
4392
|
+
});
|
|
4393
|
+
const procedures = result.rows;
|
|
4394
|
+
if (procedures.length > 0) {
|
|
4395
|
+
_cache = procedures.map((p) => `### ${p.title}
|
|
4396
|
+
${p.content}`).join("\n\n");
|
|
4397
|
+
} else {
|
|
4398
|
+
_cache = "";
|
|
4399
|
+
}
|
|
4400
|
+
_cacheLoaded = true;
|
|
4401
|
+
return procedures;
|
|
4402
|
+
}
|
|
4403
|
+
function getGlobalProceduresBlock() {
|
|
4404
|
+
if (!_cacheLoaded) return "";
|
|
4405
|
+
if (!_cache) return "";
|
|
4406
|
+
return `## Organization-Wide Procedures (MANDATORY \u2014 supersedes all other rules)
|
|
4407
|
+
|
|
4408
|
+
${_cache}
|
|
4409
|
+
`;
|
|
4410
|
+
}
|
|
4411
|
+
async function storeGlobalProcedure(input) {
|
|
4412
|
+
const id = randomUUID3();
|
|
4413
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
4414
|
+
const client = getClient();
|
|
4415
|
+
await client.execute({
|
|
4416
|
+
sql: `INSERT INTO global_procedures (id, title, content, priority, domain, active, created_at, updated_at)
|
|
4417
|
+
VALUES (?, ?, ?, ?, ?, 1, ?, ?)`,
|
|
4418
|
+
args: [id, input.title, input.content, input.priority ?? "p0", input.domain ?? null, now, now]
|
|
4419
|
+
});
|
|
4420
|
+
await loadGlobalProcedures();
|
|
4421
|
+
return id;
|
|
4422
|
+
}
|
|
4423
|
+
async function deactivateGlobalProcedure(id) {
|
|
4424
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
4425
|
+
const client = getClient();
|
|
4426
|
+
const result = await client.execute({
|
|
4427
|
+
sql: "UPDATE global_procedures SET active = 0, updated_at = ? WHERE id = ?",
|
|
4428
|
+
args: [now, id]
|
|
4429
|
+
});
|
|
4430
|
+
await loadGlobalProcedures();
|
|
4431
|
+
return result.rowsAffected > 0;
|
|
4432
|
+
}
|
|
4433
|
+
var _cache, _cacheLoaded;
|
|
4434
|
+
var init_global_procedures = __esm({
|
|
4435
|
+
"src/lib/global-procedures.ts"() {
|
|
4436
|
+
"use strict";
|
|
4437
|
+
init_database();
|
|
4438
|
+
_cache = "";
|
|
4439
|
+
_cacheLoaded = false;
|
|
4440
|
+
}
|
|
4441
|
+
});
|
|
4442
|
+
|
|
4198
4443
|
// src/lib/store.ts
|
|
4199
4444
|
var store_exports = {};
|
|
4200
4445
|
__export(store_exports, {
|
|
@@ -4274,6 +4519,11 @@ async function initStore(options) {
|
|
|
4274
4519
|
"version-query"
|
|
4275
4520
|
);
|
|
4276
4521
|
_nextVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
|
|
4522
|
+
try {
|
|
4523
|
+
const { loadGlobalProcedures: loadGlobalProcedures2 } = await Promise.resolve().then(() => (init_global_procedures(), global_procedures_exports));
|
|
4524
|
+
await loadGlobalProcedures2();
|
|
4525
|
+
} catch {
|
|
4526
|
+
}
|
|
4277
4527
|
}
|
|
4278
4528
|
function classifyTier(record) {
|
|
4279
4529
|
if (record.tool_name === "commit_to_long_term_memory" && (record.importance ?? 0) >= 8) return 1;
|
|
@@ -4315,6 +4565,12 @@ async function writeMemory(record) {
|
|
|
4315
4565
|
supersedes_id: record.supersedes_id ?? null
|
|
4316
4566
|
};
|
|
4317
4567
|
_pendingRecords.push(dbRow);
|
|
4568
|
+
orgBus.emit({
|
|
4569
|
+
type: "memory_stored",
|
|
4570
|
+
agentId: record.agent_id,
|
|
4571
|
+
project: record.project_name,
|
|
4572
|
+
timestamp: record.timestamp
|
|
4573
|
+
});
|
|
4318
4574
|
const MAX_PENDING = 1e3;
|
|
4319
4575
|
if (_pendingRecords.length > MAX_PENDING) {
|
|
4320
4576
|
const dropped = _pendingRecords.length - MAX_PENDING;
|
|
@@ -4660,6 +4916,7 @@ var init_store = __esm({
|
|
|
4660
4916
|
init_database();
|
|
4661
4917
|
init_keychain();
|
|
4662
4918
|
init_config();
|
|
4919
|
+
init_state_bus();
|
|
4663
4920
|
INIT_MAX_RETRIES = 3;
|
|
4664
4921
|
INIT_RETRY_DELAY_MS = 1e3;
|
|
4665
4922
|
_pendingRecords = [];
|
|
@@ -6625,60 +6882,15 @@ function createQuietRenderer() {
|
|
|
6625
6882
|
};
|
|
6626
6883
|
}
|
|
6627
6884
|
|
|
6628
|
-
// src/runtime/
|
|
6629
|
-
|
|
6630
|
-
handlers = /* @__PURE__ */ new Map();
|
|
6631
|
-
globalHandlers = /* @__PURE__ */ new Set();
|
|
6632
|
-
/** Emit an event to all subscribers */
|
|
6633
|
-
emit(event) {
|
|
6634
|
-
const typeHandlers = this.handlers.get(event.type);
|
|
6635
|
-
if (typeHandlers) {
|
|
6636
|
-
for (const handler of typeHandlers) {
|
|
6637
|
-
try {
|
|
6638
|
-
handler(event);
|
|
6639
|
-
} catch {
|
|
6640
|
-
}
|
|
6641
|
-
}
|
|
6642
|
-
}
|
|
6643
|
-
for (const handler of this.globalHandlers) {
|
|
6644
|
-
try {
|
|
6645
|
-
handler(event);
|
|
6646
|
-
} catch {
|
|
6647
|
-
}
|
|
6648
|
-
}
|
|
6649
|
-
}
|
|
6650
|
-
/** Subscribe to a specific event type */
|
|
6651
|
-
on(type, handler) {
|
|
6652
|
-
if (!this.handlers.has(type)) {
|
|
6653
|
-
this.handlers.set(type, /* @__PURE__ */ new Set());
|
|
6654
|
-
}
|
|
6655
|
-
this.handlers.get(type).add(handler);
|
|
6656
|
-
}
|
|
6657
|
-
/** Subscribe to ALL events */
|
|
6658
|
-
onAny(handler) {
|
|
6659
|
-
this.globalHandlers.add(handler);
|
|
6660
|
-
}
|
|
6661
|
-
/** Unsubscribe from a specific event type */
|
|
6662
|
-
off(type, handler) {
|
|
6663
|
-
this.handlers.get(type)?.delete(handler);
|
|
6664
|
-
}
|
|
6665
|
-
/** Unsubscribe from ALL events */
|
|
6666
|
-
offAny(handler) {
|
|
6667
|
-
this.globalHandlers.delete(handler);
|
|
6668
|
-
}
|
|
6669
|
-
/** Remove all listeners */
|
|
6670
|
-
clear() {
|
|
6671
|
-
this.handlers.clear();
|
|
6672
|
-
this.globalHandlers.clear();
|
|
6673
|
-
}
|
|
6674
|
-
};
|
|
6675
|
-
var orgBus = new StateBus();
|
|
6885
|
+
// src/runtime/index.ts
|
|
6886
|
+
init_state_bus();
|
|
6676
6887
|
|
|
6677
6888
|
// src/runtime/session-manager.ts
|
|
6678
|
-
import { randomUUID as
|
|
6889
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
6890
|
+
init_state_bus();
|
|
6679
6891
|
|
|
6680
6892
|
// src/runtime/exe-hooks.ts
|
|
6681
|
-
import { randomUUID as
|
|
6893
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
6682
6894
|
function createExeOSHooks(config) {
|
|
6683
6895
|
let sessionRegistered = false;
|
|
6684
6896
|
return {
|
|
@@ -6737,7 +6949,7 @@ function createExeOSHooks(config) {
|
|
|
6737
6949
|
const toolResponse = result.isError ? { error: result.content } : { output: result.content };
|
|
6738
6950
|
const rawText = extractSemanticText2(toolName, toolInput, toolResponse);
|
|
6739
6951
|
await writeMemory2({
|
|
6740
|
-
id:
|
|
6952
|
+
id: randomUUID4(),
|
|
6741
6953
|
agent_id: config.agentId,
|
|
6742
6954
|
agent_role: "employee",
|
|
6743
6955
|
session_id: `api-${config.agentId}`,
|
|
@@ -6760,7 +6972,7 @@ function createExeOSHooks(config) {
|
|
|
6760
6972
|
const { writeMemory: writeMemory2 } = await Promise.resolve().then(() => (init_store(), store_exports));
|
|
6761
6973
|
if (summary) {
|
|
6762
6974
|
await writeMemory2({
|
|
6763
|
-
id:
|
|
6975
|
+
id: randomUUID4(),
|
|
6764
6976
|
agent_id: config.agentId,
|
|
6765
6977
|
agent_role: "employee",
|
|
6766
6978
|
session_id: `api-${config.agentId}`,
|
|
@@ -6831,7 +7043,7 @@ function createExeOSHooks(config) {
|
|
|
6831
7043
|
await client.execute({
|
|
6832
7044
|
sql: `INSERT OR IGNORE INTO notifications (id, type, source_agent, message, task_file, created_at, read)
|
|
6833
7045
|
VALUES (?, 'system', ?, ?, NULL, ?, 0)`,
|
|
6834
|
-
args: [
|
|
7046
|
+
args: [randomUUID4(), config.agentId, message.slice(0, 500), (/* @__PURE__ */ new Date()).toISOString()]
|
|
6835
7047
|
});
|
|
6836
7048
|
} catch {
|
|
6837
7049
|
}
|
|
@@ -6847,7 +7059,7 @@ function createExeOSHooks(config) {
|
|
|
6847
7059
|
try {
|
|
6848
7060
|
const { writeMemory: writeMemory2 } = await Promise.resolve().then(() => (init_store(), store_exports));
|
|
6849
7061
|
await writeMemory2({
|
|
6850
|
-
id:
|
|
7062
|
+
id: randomUUID4(),
|
|
6851
7063
|
agent_id: config.agentId,
|
|
6852
7064
|
agent_role: "employee",
|
|
6853
7065
|
session_id: `api-${config.agentId}`,
|
|
@@ -6869,7 +7081,7 @@ function createExeOSHooks(config) {
|
|
|
6869
7081
|
try {
|
|
6870
7082
|
const { writeMemory: writeMemory2 } = await Promise.resolve().then(() => (init_store(), store_exports));
|
|
6871
7083
|
await writeMemory2({
|
|
6872
|
-
id:
|
|
7084
|
+
id: randomUUID4(),
|
|
6873
7085
|
agent_id: config.agentId,
|
|
6874
7086
|
agent_role: "employee",
|
|
6875
7087
|
session_id: `api-${config.agentId}`,
|
|
@@ -6906,7 +7118,7 @@ function createExeOSHooks(config) {
|
|
|
6906
7118
|
if (tasks.rows.length > 0) {
|
|
6907
7119
|
const taskList = tasks.rows.map((r) => `- [${String(r.status)}] ${String(r.title)} (${String(r.task_file)})`).join("\n");
|
|
6908
7120
|
await writeMemory2({
|
|
6909
|
-
id:
|
|
7121
|
+
id: randomUUID4(),
|
|
6910
7122
|
agent_id: config.agentId,
|
|
6911
7123
|
agent_role: "employee",
|
|
6912
7124
|
session_id: `api-${config.agentId}`,
|
|
@@ -6932,7 +7144,7 @@ ${taskList}`,
|
|
|
6932
7144
|
try {
|
|
6933
7145
|
const { writeMemory: writeMemory2 } = await Promise.resolve().then(() => (init_store(), store_exports));
|
|
6934
7146
|
await writeMemory2({
|
|
6935
|
-
id:
|
|
7147
|
+
id: randomUUID4(),
|
|
6936
7148
|
agent_id: config.agentId,
|
|
6937
7149
|
agent_role: "employee",
|
|
6938
7150
|
session_id: `api-${config.agentId}`,
|
|
@@ -6959,7 +7171,7 @@ var SessionManager = class {
|
|
|
6959
7171
|
eventHandlers = /* @__PURE__ */ new Set();
|
|
6960
7172
|
/** Start a new agent session for an employee */
|
|
6961
7173
|
startSession(employeeId, config) {
|
|
6962
|
-
const sessionId =
|
|
7174
|
+
const sessionId = randomUUID5();
|
|
6963
7175
|
const abortController = new AbortController();
|
|
6964
7176
|
const session = {
|
|
6965
7177
|
info: {
|