@askexenow/exe-os 0.8.55 → 0.8.57
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 +13 -0
- package/dist/bin/backfill-responses.js +13 -0
- package/dist/bin/backfill-vectors.js +65 -6
- package/dist/bin/cleanup-stale-review-tasks.js +407 -57
- package/dist/bin/cli.js +6364 -6248
- package/dist/bin/exe-agent.js +13 -0
- package/dist/bin/exe-assign.js +13 -0
- package/dist/bin/exe-boot.js +541 -433
- package/dist/bin/exe-call.js +13 -0
- package/dist/bin/exe-doctor.js +76 -5
- package/dist/bin/exe-export-behaviors.js +13 -0
- package/dist/bin/exe-forget.js +13 -0
- package/dist/bin/exe-gateway.js +73 -29
- package/dist/bin/exe-heartbeat.js +248 -41
- package/dist/bin/exe-kill.js +14 -1
- package/dist/bin/exe-launch-agent.js +13 -0
- package/dist/bin/exe-new-employee.js +13 -0
- package/dist/bin/exe-pending-messages.js +13 -0
- package/dist/bin/exe-pending-notifications.js +13 -0
- package/dist/bin/exe-pending-reviews.js +56 -34
- package/dist/bin/exe-rename.js +13 -0
- package/dist/bin/exe-review.js +13 -0
- package/dist/bin/exe-search.js +13 -0
- package/dist/bin/exe-session-cleanup.js +2972 -2924
- package/dist/bin/exe-status.js +410 -66
- package/dist/bin/exe-team.js +13 -0
- package/dist/bin/git-sweep.js +3442 -3392
- package/dist/bin/graph-backfill.js +13 -0
- package/dist/bin/graph-export.js +13 -0
- package/dist/bin/install.js +47 -3
- package/dist/bin/scan-tasks.js +3602 -3556
- package/dist/bin/setup.js +13 -0
- package/dist/bin/shard-migrate.js +13 -0
- package/dist/bin/update.js +485 -0
- package/dist/bin/wiki-sync.js +13 -0
- package/dist/gateway/index.js +73 -29
- package/dist/hooks/bug-report-worker.js +73 -29
- package/dist/hooks/commit-complete.js +3437 -3392
- package/dist/hooks/error-recall.js +13 -0
- package/dist/hooks/ingest-worker.js +130 -34
- package/dist/hooks/ingest.js +25 -6
- package/dist/hooks/instructions-loaded.js +13 -0
- package/dist/hooks/notification.js +13 -0
- package/dist/hooks/post-compact.js +371 -53
- package/dist/hooks/pre-compact.js +3121 -3075
- package/dist/hooks/pre-tool-use.js +400 -93
- package/dist/hooks/prompt-ingest-worker.js +13 -0
- package/dist/hooks/prompt-submit.js +73 -29
- package/dist/hooks/response-ingest-worker.js +13 -0
- package/dist/hooks/session-end.js +382 -64
- package/dist/hooks/session-start.js +355 -37
- package/dist/hooks/stop.js +381 -62
- package/dist/hooks/subagent-stop.js +371 -53
- package/dist/hooks/summary-worker.js +739 -219
- package/dist/index.js +93 -37
- package/dist/lib/employee-templates.js +13 -0
- package/dist/lib/exe-daemon.js +94 -41
- package/dist/lib/hybrid-search.js +13 -0
- package/dist/lib/schedules.js +13 -0
- package/dist/lib/store.js +13 -0
- package/dist/lib/tasks.js +60 -29
- package/dist/lib/tmux-routing.js +60 -29
- package/dist/mcp/server.js +136 -38
- package/dist/mcp/tools/create-task.js +60 -29
- package/dist/mcp/tools/list-tasks.js +116 -2511
- package/dist/mcp/tools/update-task.js +273 -243
- package/dist/runtime/index.js +93 -37
- package/dist/tui/App.js +5609 -5541
- package/package.json +1 -1
- package/src/commands/exe/build-adv.md +2 -2
- package/src/commands/exe/heartbeat.md +2 -1
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
4
6
|
var __esm = (fn, res) => function __init() {
|
|
5
7
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
6
8
|
};
|
|
@@ -8,6 +10,15 @@ var __export = (target, all) => {
|
|
|
8
10
|
for (var name in all)
|
|
9
11
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
12
|
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
11
22
|
|
|
12
23
|
// src/lib/db-retry.ts
|
|
13
24
|
function isBusyError(err) {
|
|
@@ -1105,6 +1116,61 @@ var init_config = __esm({
|
|
|
1105
1116
|
}
|
|
1106
1117
|
});
|
|
1107
1118
|
|
|
1119
|
+
// src/lib/state-bus.ts
|
|
1120
|
+
var StateBus, orgBus;
|
|
1121
|
+
var init_state_bus = __esm({
|
|
1122
|
+
"src/lib/state-bus.ts"() {
|
|
1123
|
+
"use strict";
|
|
1124
|
+
StateBus = class {
|
|
1125
|
+
handlers = /* @__PURE__ */ new Map();
|
|
1126
|
+
globalHandlers = /* @__PURE__ */ new Set();
|
|
1127
|
+
/** Emit an event to all subscribers */
|
|
1128
|
+
emit(event) {
|
|
1129
|
+
const typeHandlers = this.handlers.get(event.type);
|
|
1130
|
+
if (typeHandlers) {
|
|
1131
|
+
for (const handler of typeHandlers) {
|
|
1132
|
+
try {
|
|
1133
|
+
handler(event);
|
|
1134
|
+
} catch {
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
for (const handler of this.globalHandlers) {
|
|
1139
|
+
try {
|
|
1140
|
+
handler(event);
|
|
1141
|
+
} catch {
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
/** Subscribe to a specific event type */
|
|
1146
|
+
on(type, handler) {
|
|
1147
|
+
if (!this.handlers.has(type)) {
|
|
1148
|
+
this.handlers.set(type, /* @__PURE__ */ new Set());
|
|
1149
|
+
}
|
|
1150
|
+
this.handlers.get(type).add(handler);
|
|
1151
|
+
}
|
|
1152
|
+
/** Subscribe to ALL events */
|
|
1153
|
+
onAny(handler) {
|
|
1154
|
+
this.globalHandlers.add(handler);
|
|
1155
|
+
}
|
|
1156
|
+
/** Unsubscribe from a specific event type */
|
|
1157
|
+
off(type, handler) {
|
|
1158
|
+
this.handlers.get(type)?.delete(handler);
|
|
1159
|
+
}
|
|
1160
|
+
/** Unsubscribe from ALL events */
|
|
1161
|
+
offAny(handler) {
|
|
1162
|
+
this.globalHandlers.delete(handler);
|
|
1163
|
+
}
|
|
1164
|
+
/** Remove all listeners */
|
|
1165
|
+
clear() {
|
|
1166
|
+
this.handlers.clear();
|
|
1167
|
+
this.globalHandlers.clear();
|
|
1168
|
+
}
|
|
1169
|
+
};
|
|
1170
|
+
orgBus = new StateBus();
|
|
1171
|
+
}
|
|
1172
|
+
});
|
|
1173
|
+
|
|
1108
1174
|
// src/lib/shard-manager.ts
|
|
1109
1175
|
var shard_manager_exports = {};
|
|
1110
1176
|
__export(shard_manager_exports, {
|
|
@@ -1435,6 +1501,19 @@ var init_platform_procedures = __esm({
|
|
|
1435
1501
|
domain: "architecture",
|
|
1436
1502
|
priority: "p0",
|
|
1437
1503
|
content: "Desktop and TUI are the SAME product in different renderers. Same data contracts, same interactions, same acceptance criteria. Desktop tab specs in ARCHITECTURE.md ARE the TUI specs. When building TUI, cross-reference Desktop spec. Different tab names, identical behavior. Never treat them as separate products."
|
|
1504
|
+
},
|
|
1505
|
+
// --- Orchestration golden path ---
|
|
1506
|
+
{
|
|
1507
|
+
title: "Task lifecycle \u2014 the golden path every agent follows",
|
|
1508
|
+
domain: "workflow",
|
|
1509
|
+
priority: "p0",
|
|
1510
|
+
content: "create_task is dispatch + delivery. Task lifecycle: open \u2192 in_progress (you start) \u2192 done (update_task when finished) \u2192 needs_review (reviewer nudged) \u2192 closed (COO only via close_task). DB is the reliable delivery \u2014 intercom is just a speedup nudge. If you finish a task, self-chain: check for next task immediately (step 7). Never wait for a nudge. Never say 'standing by.'"
|
|
1511
|
+
},
|
|
1512
|
+
{
|
|
1513
|
+
title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
|
|
1514
|
+
domain: "architecture",
|
|
1515
|
+
priority: "p0",
|
|
1516
|
+
content: "Tasks live in the DB. Intercom (tmux send-keys) is fire-and-forget \u2014 it may fail, get garbled, or arrive mid-work. Never rely on intercom for task delivery. The UserPromptSubmit hook checks the DB for new tasks on every prompt. Your operating procedures step 7 says check for next work. The daemon nudges idle agents as a speedup. If you have no tasks, you found them all."
|
|
1438
1517
|
}
|
|
1439
1518
|
];
|
|
1440
1519
|
PLATFORM_PROCEDURE_TITLES = new Set(
|
|
@@ -1514,6 +1593,324 @@ ${p.content}`).join("\n\n");
|
|
|
1514
1593
|
}
|
|
1515
1594
|
});
|
|
1516
1595
|
|
|
1596
|
+
// src/lib/session-registry.ts
|
|
1597
|
+
import path4 from "path";
|
|
1598
|
+
import os3 from "os";
|
|
1599
|
+
var REGISTRY_PATH;
|
|
1600
|
+
var init_session_registry = __esm({
|
|
1601
|
+
"src/lib/session-registry.ts"() {
|
|
1602
|
+
"use strict";
|
|
1603
|
+
REGISTRY_PATH = path4.join(os3.homedir(), ".exe-os", "session-registry.json");
|
|
1604
|
+
}
|
|
1605
|
+
});
|
|
1606
|
+
|
|
1607
|
+
// src/lib/session-key.ts
|
|
1608
|
+
import { execSync } from "child_process";
|
|
1609
|
+
function getSessionKey() {
|
|
1610
|
+
if (_cached) return _cached;
|
|
1611
|
+
let pid = process.ppid;
|
|
1612
|
+
for (let i = 0; i < 10; i++) {
|
|
1613
|
+
try {
|
|
1614
|
+
const info = execSync(`ps -p ${pid} -o ppid=,comm=`, {
|
|
1615
|
+
encoding: "utf8",
|
|
1616
|
+
timeout: 2e3
|
|
1617
|
+
}).trim();
|
|
1618
|
+
const match = info.match(/^\s*(\d+)\s+(.+)$/);
|
|
1619
|
+
if (!match) break;
|
|
1620
|
+
const [, ppid, cmd] = match;
|
|
1621
|
+
if (cmd === "claude" || cmd.endsWith("/claude")) {
|
|
1622
|
+
_cached = String(pid);
|
|
1623
|
+
return _cached;
|
|
1624
|
+
}
|
|
1625
|
+
pid = parseInt(ppid, 10);
|
|
1626
|
+
if (pid <= 1) break;
|
|
1627
|
+
} catch {
|
|
1628
|
+
break;
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
_cached = process.env.CLAUDE_CODE_SSE_PORT ?? String(process.ppid);
|
|
1632
|
+
return _cached;
|
|
1633
|
+
}
|
|
1634
|
+
var _cached;
|
|
1635
|
+
var init_session_key = __esm({
|
|
1636
|
+
"src/lib/session-key.ts"() {
|
|
1637
|
+
"use strict";
|
|
1638
|
+
_cached = null;
|
|
1639
|
+
}
|
|
1640
|
+
});
|
|
1641
|
+
|
|
1642
|
+
// src/lib/tmux-transport.ts
|
|
1643
|
+
var tmux_transport_exports = {};
|
|
1644
|
+
__export(tmux_transport_exports, {
|
|
1645
|
+
TmuxTransport: () => TmuxTransport
|
|
1646
|
+
});
|
|
1647
|
+
import { execFileSync } from "child_process";
|
|
1648
|
+
var QUIET, TmuxTransport;
|
|
1649
|
+
var init_tmux_transport = __esm({
|
|
1650
|
+
"src/lib/tmux-transport.ts"() {
|
|
1651
|
+
"use strict";
|
|
1652
|
+
QUIET = {
|
|
1653
|
+
encoding: "utf8",
|
|
1654
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
1655
|
+
};
|
|
1656
|
+
TmuxTransport = class {
|
|
1657
|
+
getMySession() {
|
|
1658
|
+
try {
|
|
1659
|
+
return execFileSync("tmux", ["display-message", "-p", "#{session_name}"], QUIET).trim() || null;
|
|
1660
|
+
} catch {
|
|
1661
|
+
return null;
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
listSessions() {
|
|
1665
|
+
try {
|
|
1666
|
+
return execFileSync("tmux", ["list-sessions", "-F", "#{session_name}"], QUIET).trim().split("\n").filter(Boolean);
|
|
1667
|
+
} catch {
|
|
1668
|
+
return [];
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1671
|
+
isAlive(target) {
|
|
1672
|
+
try {
|
|
1673
|
+
const sessions = this.listSessions();
|
|
1674
|
+
if (!sessions.includes(target)) return false;
|
|
1675
|
+
const paneStatus = execFileSync(
|
|
1676
|
+
"tmux",
|
|
1677
|
+
["list-panes", "-t", target, "-F", "#{pane_dead}"],
|
|
1678
|
+
QUIET
|
|
1679
|
+
).trim();
|
|
1680
|
+
return paneStatus !== "1";
|
|
1681
|
+
} catch {
|
|
1682
|
+
return false;
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
sendKeys(target, keys) {
|
|
1686
|
+
execFileSync("tmux", ["send-keys", "-t", target, keys, "Enter"], QUIET);
|
|
1687
|
+
}
|
|
1688
|
+
capturePane(target, lines) {
|
|
1689
|
+
const args = ["capture-pane", "-t", target, "-p"];
|
|
1690
|
+
if (lines) args.push("-S", `-${lines}`);
|
|
1691
|
+
return execFileSync("tmux", args, { ...QUIET, timeout: 3e3 });
|
|
1692
|
+
}
|
|
1693
|
+
isPaneInCopyMode(target) {
|
|
1694
|
+
try {
|
|
1695
|
+
const result = execFileSync(
|
|
1696
|
+
"tmux",
|
|
1697
|
+
["display-message", "-p", "-t", target, "#{pane_in_mode}"],
|
|
1698
|
+
{ ...QUIET, timeout: 3e3 }
|
|
1699
|
+
).trim();
|
|
1700
|
+
return result === "1";
|
|
1701
|
+
} catch {
|
|
1702
|
+
return false;
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
spawn(name, config) {
|
|
1706
|
+
try {
|
|
1707
|
+
const args = ["new-session", "-d", "-s", name];
|
|
1708
|
+
if (config.cwd) args.push("-c", config.cwd);
|
|
1709
|
+
args.push(config.command);
|
|
1710
|
+
execFileSync("tmux", args);
|
|
1711
|
+
return { sessionName: name };
|
|
1712
|
+
} catch (e) {
|
|
1713
|
+
return { sessionName: name, error: `spawn failed: ${e}` };
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
kill(target) {
|
|
1717
|
+
try {
|
|
1718
|
+
execFileSync("tmux", ["kill-session", "-t", target], QUIET);
|
|
1719
|
+
} catch {
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
pipeLog(target, logFile) {
|
|
1723
|
+
try {
|
|
1724
|
+
const safePath = logFile.replace(/'/g, "'\\''");
|
|
1725
|
+
execFileSync("tmux", ["pipe-pane", "-t", target, `cat >> '${safePath}'`], QUIET);
|
|
1726
|
+
} catch {
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
};
|
|
1730
|
+
}
|
|
1731
|
+
});
|
|
1732
|
+
|
|
1733
|
+
// src/lib/transport.ts
|
|
1734
|
+
function getTransport() {
|
|
1735
|
+
if (!_transport) {
|
|
1736
|
+
const { TmuxTransport: TmuxTransport2 } = (init_tmux_transport(), __toCommonJS(tmux_transport_exports));
|
|
1737
|
+
_transport = new TmuxTransport2();
|
|
1738
|
+
}
|
|
1739
|
+
return _transport;
|
|
1740
|
+
}
|
|
1741
|
+
var _transport;
|
|
1742
|
+
var init_transport = __esm({
|
|
1743
|
+
"src/lib/transport.ts"() {
|
|
1744
|
+
"use strict";
|
|
1745
|
+
_transport = null;
|
|
1746
|
+
}
|
|
1747
|
+
});
|
|
1748
|
+
|
|
1749
|
+
// src/lib/cc-agent-support.ts
|
|
1750
|
+
import { execSync as execSync2 } from "child_process";
|
|
1751
|
+
var init_cc_agent_support = __esm({
|
|
1752
|
+
"src/lib/cc-agent-support.ts"() {
|
|
1753
|
+
"use strict";
|
|
1754
|
+
}
|
|
1755
|
+
});
|
|
1756
|
+
|
|
1757
|
+
// src/lib/mcp-prefix.ts
|
|
1758
|
+
var MCP_PRIMARY_KEY, MCP_LEGACY_KEY, MCP_TOOL_PREFIXES;
|
|
1759
|
+
var init_mcp_prefix = __esm({
|
|
1760
|
+
"src/lib/mcp-prefix.ts"() {
|
|
1761
|
+
"use strict";
|
|
1762
|
+
MCP_PRIMARY_KEY = "exe-os";
|
|
1763
|
+
MCP_LEGACY_KEY = "exe-mem";
|
|
1764
|
+
MCP_TOOL_PREFIXES = [
|
|
1765
|
+
`mcp__${MCP_PRIMARY_KEY}__`,
|
|
1766
|
+
`mcp__${MCP_LEGACY_KEY}__`
|
|
1767
|
+
];
|
|
1768
|
+
}
|
|
1769
|
+
});
|
|
1770
|
+
|
|
1771
|
+
// src/lib/provider-table.ts
|
|
1772
|
+
var init_provider_table = __esm({
|
|
1773
|
+
"src/lib/provider-table.ts"() {
|
|
1774
|
+
"use strict";
|
|
1775
|
+
}
|
|
1776
|
+
});
|
|
1777
|
+
|
|
1778
|
+
// src/lib/intercom-queue.ts
|
|
1779
|
+
import { readFileSync as readFileSync2, writeFileSync, renameSync as renameSync2, existsSync as existsSync4, mkdirSync as mkdirSync2 } from "fs";
|
|
1780
|
+
import path5 from "path";
|
|
1781
|
+
import os4 from "os";
|
|
1782
|
+
var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
|
|
1783
|
+
var init_intercom_queue = __esm({
|
|
1784
|
+
"src/lib/intercom-queue.ts"() {
|
|
1785
|
+
"use strict";
|
|
1786
|
+
QUEUE_PATH = path5.join(os4.homedir(), ".exe-os", "intercom-queue.json");
|
|
1787
|
+
TTL_MS = 60 * 60 * 1e3;
|
|
1788
|
+
INTERCOM_LOG = path5.join(os4.homedir(), ".exe-os", "intercom.log");
|
|
1789
|
+
}
|
|
1790
|
+
});
|
|
1791
|
+
|
|
1792
|
+
// src/lib/employees.ts
|
|
1793
|
+
import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
|
|
1794
|
+
import { existsSync as existsSync5, symlinkSync, readlinkSync, readFileSync as readFileSync3 } from "fs";
|
|
1795
|
+
import { execSync as execSync3 } from "child_process";
|
|
1796
|
+
import path6 from "path";
|
|
1797
|
+
var EMPLOYEES_PATH;
|
|
1798
|
+
var init_employees = __esm({
|
|
1799
|
+
"src/lib/employees.ts"() {
|
|
1800
|
+
"use strict";
|
|
1801
|
+
init_config();
|
|
1802
|
+
EMPLOYEES_PATH = path6.join(EXE_AI_DIR, "exe-employees.json");
|
|
1803
|
+
}
|
|
1804
|
+
});
|
|
1805
|
+
|
|
1806
|
+
// src/lib/license.ts
|
|
1807
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, existsSync as existsSync6, mkdirSync as mkdirSync3 } from "fs";
|
|
1808
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
1809
|
+
import path7 from "path";
|
|
1810
|
+
import { jwtVerify, importSPKI } from "jose";
|
|
1811
|
+
var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH;
|
|
1812
|
+
var init_license = __esm({
|
|
1813
|
+
"src/lib/license.ts"() {
|
|
1814
|
+
"use strict";
|
|
1815
|
+
init_config();
|
|
1816
|
+
LICENSE_PATH = path7.join(EXE_AI_DIR, "license.key");
|
|
1817
|
+
CACHE_PATH = path7.join(EXE_AI_DIR, "license-cache.json");
|
|
1818
|
+
DEVICE_ID_PATH = path7.join(EXE_AI_DIR, "device-id");
|
|
1819
|
+
}
|
|
1820
|
+
});
|
|
1821
|
+
|
|
1822
|
+
// src/lib/plan-limits.ts
|
|
1823
|
+
import { readFileSync as readFileSync5, existsSync as existsSync7 } from "fs";
|
|
1824
|
+
import path8 from "path";
|
|
1825
|
+
var CACHE_PATH2;
|
|
1826
|
+
var init_plan_limits = __esm({
|
|
1827
|
+
"src/lib/plan-limits.ts"() {
|
|
1828
|
+
"use strict";
|
|
1829
|
+
init_database();
|
|
1830
|
+
init_employees();
|
|
1831
|
+
init_license();
|
|
1832
|
+
init_config();
|
|
1833
|
+
CACHE_PATH2 = path8.join(EXE_AI_DIR, "license-cache.json");
|
|
1834
|
+
}
|
|
1835
|
+
});
|
|
1836
|
+
|
|
1837
|
+
// src/lib/tmux-routing.ts
|
|
1838
|
+
import { readFileSync as readFileSync6, writeFileSync as writeFileSync3, mkdirSync as mkdirSync4, existsSync as existsSync8, appendFileSync } from "fs";
|
|
1839
|
+
import path9 from "path";
|
|
1840
|
+
import os5 from "os";
|
|
1841
|
+
import { fileURLToPath } from "url";
|
|
1842
|
+
function getMySession() {
|
|
1843
|
+
return getTransport().getMySession();
|
|
1844
|
+
}
|
|
1845
|
+
function extractRootExe(name) {
|
|
1846
|
+
const match = name.match(/(exe\d+)$/);
|
|
1847
|
+
return match?.[1] ?? null;
|
|
1848
|
+
}
|
|
1849
|
+
function getParentExe(sessionKey) {
|
|
1850
|
+
try {
|
|
1851
|
+
const data = JSON.parse(readFileSync6(path9.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
|
|
1852
|
+
return data.parentExe || null;
|
|
1853
|
+
} catch {
|
|
1854
|
+
return null;
|
|
1855
|
+
}
|
|
1856
|
+
}
|
|
1857
|
+
function resolveExeSession() {
|
|
1858
|
+
const mySession = getMySession();
|
|
1859
|
+
if (!mySession) return null;
|
|
1860
|
+
try {
|
|
1861
|
+
const key = getSessionKey();
|
|
1862
|
+
const parentExe = getParentExe(key);
|
|
1863
|
+
if (parentExe) {
|
|
1864
|
+
return extractRootExe(parentExe) ?? parentExe;
|
|
1865
|
+
}
|
|
1866
|
+
} catch {
|
|
1867
|
+
}
|
|
1868
|
+
return extractRootExe(mySession) ?? mySession;
|
|
1869
|
+
}
|
|
1870
|
+
var SPAWN_LOCK_DIR, SESSION_CACHE, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS;
|
|
1871
|
+
var init_tmux_routing = __esm({
|
|
1872
|
+
"src/lib/tmux-routing.ts"() {
|
|
1873
|
+
"use strict";
|
|
1874
|
+
init_session_registry();
|
|
1875
|
+
init_session_key();
|
|
1876
|
+
init_transport();
|
|
1877
|
+
init_cc_agent_support();
|
|
1878
|
+
init_mcp_prefix();
|
|
1879
|
+
init_provider_table();
|
|
1880
|
+
init_intercom_queue();
|
|
1881
|
+
init_plan_limits();
|
|
1882
|
+
SPAWN_LOCK_DIR = path9.join(os5.homedir(), ".exe-os", "spawn-locks");
|
|
1883
|
+
SESSION_CACHE = path9.join(os5.homedir(), ".exe-os", "session-cache");
|
|
1884
|
+
INTERCOM_LOG2 = path9.join(os5.homedir(), ".exe-os", "intercom.log");
|
|
1885
|
+
DEBOUNCE_FILE = path9.join(SESSION_CACHE, "intercom-debounce.json");
|
|
1886
|
+
DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
|
|
1887
|
+
}
|
|
1888
|
+
});
|
|
1889
|
+
|
|
1890
|
+
// src/lib/task-scope.ts
|
|
1891
|
+
function getCurrentSessionScope() {
|
|
1892
|
+
try {
|
|
1893
|
+
return resolveExeSession();
|
|
1894
|
+
} catch {
|
|
1895
|
+
return null;
|
|
1896
|
+
}
|
|
1897
|
+
}
|
|
1898
|
+
function sessionScopeFilter(sessionScope, tableAlias) {
|
|
1899
|
+
const scope = sessionScope !== void 0 ? sessionScope : getCurrentSessionScope();
|
|
1900
|
+
if (!scope) return { sql: "", args: [] };
|
|
1901
|
+
const col = tableAlias ? `${tableAlias}.session_scope` : "session_scope";
|
|
1902
|
+
return {
|
|
1903
|
+
sql: ` AND (${col} IS NULL OR ${col} = ?)`,
|
|
1904
|
+
args: [scope]
|
|
1905
|
+
};
|
|
1906
|
+
}
|
|
1907
|
+
var init_task_scope = __esm({
|
|
1908
|
+
"src/lib/task-scope.ts"() {
|
|
1909
|
+
"use strict";
|
|
1910
|
+
init_tmux_routing();
|
|
1911
|
+
}
|
|
1912
|
+
});
|
|
1913
|
+
|
|
1517
1914
|
// src/lib/store.ts
|
|
1518
1915
|
init_database();
|
|
1519
1916
|
|
|
@@ -1563,57 +1960,7 @@ async function getMasterKey() {
|
|
|
1563
1960
|
|
|
1564
1961
|
// src/lib/store.ts
|
|
1565
1962
|
init_config();
|
|
1566
|
-
|
|
1567
|
-
// src/lib/state-bus.ts
|
|
1568
|
-
var StateBus = class {
|
|
1569
|
-
handlers = /* @__PURE__ */ new Map();
|
|
1570
|
-
globalHandlers = /* @__PURE__ */ new Set();
|
|
1571
|
-
/** Emit an event to all subscribers */
|
|
1572
|
-
emit(event) {
|
|
1573
|
-
const typeHandlers = this.handlers.get(event.type);
|
|
1574
|
-
if (typeHandlers) {
|
|
1575
|
-
for (const handler of typeHandlers) {
|
|
1576
|
-
try {
|
|
1577
|
-
handler(event);
|
|
1578
|
-
} catch {
|
|
1579
|
-
}
|
|
1580
|
-
}
|
|
1581
|
-
}
|
|
1582
|
-
for (const handler of this.globalHandlers) {
|
|
1583
|
-
try {
|
|
1584
|
-
handler(event);
|
|
1585
|
-
} catch {
|
|
1586
|
-
}
|
|
1587
|
-
}
|
|
1588
|
-
}
|
|
1589
|
-
/** Subscribe to a specific event type */
|
|
1590
|
-
on(type, handler) {
|
|
1591
|
-
if (!this.handlers.has(type)) {
|
|
1592
|
-
this.handlers.set(type, /* @__PURE__ */ new Set());
|
|
1593
|
-
}
|
|
1594
|
-
this.handlers.get(type).add(handler);
|
|
1595
|
-
}
|
|
1596
|
-
/** Subscribe to ALL events */
|
|
1597
|
-
onAny(handler) {
|
|
1598
|
-
this.globalHandlers.add(handler);
|
|
1599
|
-
}
|
|
1600
|
-
/** Unsubscribe from a specific event type */
|
|
1601
|
-
off(type, handler) {
|
|
1602
|
-
this.handlers.get(type)?.delete(handler);
|
|
1603
|
-
}
|
|
1604
|
-
/** Unsubscribe from ALL events */
|
|
1605
|
-
offAny(handler) {
|
|
1606
|
-
this.globalHandlers.delete(handler);
|
|
1607
|
-
}
|
|
1608
|
-
/** Remove all listeners */
|
|
1609
|
-
clear() {
|
|
1610
|
-
this.handlers.clear();
|
|
1611
|
-
this.globalHandlers.clear();
|
|
1612
|
-
}
|
|
1613
|
-
};
|
|
1614
|
-
var orgBus = new StateBus();
|
|
1615
|
-
|
|
1616
|
-
// src/lib/store.ts
|
|
1963
|
+
init_state_bus();
|
|
1617
1964
|
var INIT_MAX_RETRIES = 3;
|
|
1618
1965
|
var INIT_RETRY_DELAY_MS = 1e3;
|
|
1619
1966
|
function isBusyError2(err) {
|
|
@@ -1693,15 +2040,16 @@ async function initStore(options) {
|
|
|
1693
2040
|
|
|
1694
2041
|
// src/bin/cleanup-stale-review-tasks.ts
|
|
1695
2042
|
init_database();
|
|
2043
|
+
init_task_scope();
|
|
1696
2044
|
|
|
1697
2045
|
// src/lib/is-main.ts
|
|
1698
2046
|
import { realpathSync } from "fs";
|
|
1699
|
-
import { fileURLToPath } from "url";
|
|
2047
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1700
2048
|
function isMainModule(importMetaUrl) {
|
|
1701
2049
|
if (process.argv[1] == null) return false;
|
|
1702
2050
|
try {
|
|
1703
2051
|
const scriptPath = realpathSync(process.argv[1]);
|
|
1704
|
-
const modulePath = realpathSync(
|
|
2052
|
+
const modulePath = realpathSync(fileURLToPath2(importMetaUrl));
|
|
1705
2053
|
return scriptPath === modulePath;
|
|
1706
2054
|
} catch {
|
|
1707
2055
|
return importMetaUrl === `file://${process.argv[1]}` || importMetaUrl === new URL(process.argv[1], "file://").href;
|
|
@@ -1722,15 +2070,16 @@ async function findZombies(beforeIso, assignedTo) {
|
|
|
1722
2070
|
assigneeClause = "AND assigned_to = ?";
|
|
1723
2071
|
args.push(assignedTo);
|
|
1724
2072
|
}
|
|
2073
|
+
const csScope = sessionScopeFilter();
|
|
1725
2074
|
const result = await client.execute({
|
|
1726
2075
|
sql: `SELECT id, assigned_to, title, created_at
|
|
1727
2076
|
FROM tasks
|
|
1728
2077
|
WHERE status IN ('open', 'in_progress')
|
|
1729
2078
|
AND title LIKE 'Review:%'
|
|
1730
2079
|
${beforeClause}
|
|
1731
|
-
${assigneeClause}
|
|
2080
|
+
${assigneeClause}${csScope.sql}
|
|
1732
2081
|
ORDER BY created_at ASC`,
|
|
1733
|
-
args
|
|
2082
|
+
args: [...args, ...csScope.args]
|
|
1734
2083
|
});
|
|
1735
2084
|
return result.rows.map((r) => ({
|
|
1736
2085
|
id: String(r.id),
|
|
@@ -1741,12 +2090,13 @@ async function findZombies(beforeIso, assignedTo) {
|
|
|
1741
2090
|
}
|
|
1742
2091
|
async function statsByAssignee() {
|
|
1743
2092
|
const client = getClient();
|
|
2093
|
+
const sbScope = sessionScopeFilter();
|
|
1744
2094
|
const r = await client.execute({
|
|
1745
2095
|
sql: `SELECT assigned_to, COUNT(*) as n, MIN(created_at) as oldest, MAX(created_at) as newest
|
|
1746
2096
|
FROM tasks
|
|
1747
|
-
WHERE status IN ('open','in_progress') AND title LIKE 'Review:%'
|
|
2097
|
+
WHERE status IN ('open','in_progress') AND title LIKE 'Review:%'${sbScope.sql}
|
|
1748
2098
|
GROUP BY assigned_to ORDER BY n DESC`,
|
|
1749
|
-
args: []
|
|
2099
|
+
args: [...sbScope.args]
|
|
1750
2100
|
});
|
|
1751
2101
|
console.log("Stats by assignee:");
|
|
1752
2102
|
for (const row of r.rows) {
|