@askexenow/exe-os 0.8.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +178 -79
- package/dist/bin/backfill-responses.js +160 -8
- package/dist/bin/backfill-vectors.js +130 -1
- package/dist/bin/cleanup-stale-review-tasks.js +130 -1
- package/dist/bin/cli.js +10111 -7540
- package/dist/bin/exe-agent.js +159 -1
- package/dist/bin/exe-assign.js +235 -16
- package/dist/bin/exe-boot.js +344 -472
- package/dist/bin/exe-call.js +145 -1
- package/dist/bin/exe-cloud.js +11 -0
- package/dist/bin/exe-dispatch.js +37 -24
- package/dist/bin/exe-doctor.js +130 -1
- package/dist/bin/exe-export-behaviors.js +150 -7
- package/dist/bin/exe-forget.js +822 -665
- package/dist/bin/exe-gateway.js +470 -62
- package/dist/bin/exe-heartbeat.js +133 -2
- package/dist/bin/exe-kill.js +150 -7
- package/dist/bin/exe-launch-agent.js +150 -7
- package/dist/bin/exe-new-employee.js +756 -224
- package/dist/bin/exe-pending-messages.js +132 -2
- package/dist/bin/exe-pending-notifications.js +130 -1
- package/dist/bin/exe-pending-reviews.js +132 -2
- package/dist/bin/exe-review.js +160 -8
- package/dist/bin/exe-search.js +2473 -2008
- package/dist/bin/exe-session-cleanup.js +238 -51
- package/dist/bin/exe-settings.js +11 -0
- package/dist/bin/exe-status.js +130 -1
- package/dist/bin/exe-team.js +130 -1
- package/dist/bin/git-sweep.js +272 -16
- package/dist/bin/graph-backfill.js +150 -7
- package/dist/bin/graph-export.js +150 -7
- package/dist/bin/install.js +5 -0
- package/dist/bin/scan-tasks.js +238 -19
- package/dist/bin/setup.js +1776 -10
- package/dist/bin/shard-migrate.js +150 -7
- package/dist/bin/update.js +9 -6
- package/dist/bin/wiki-sync.js +150 -7
- package/dist/gateway/index.js +470 -62
- package/dist/hooks/bug-report-worker.js +195 -35
- package/dist/hooks/commit-complete.js +272 -16
- package/dist/hooks/error-recall.js +2313 -1847
- package/dist/hooks/exe-heartbeat-hook.js +5 -0
- package/dist/hooks/ingest-worker.js +330 -58
- package/dist/hooks/ingest.js +11 -0
- package/dist/hooks/instructions-loaded.js +199 -10
- package/dist/hooks/notification.js +199 -10
- package/dist/hooks/post-compact.js +199 -10
- package/dist/hooks/pre-compact.js +199 -10
- package/dist/hooks/pre-tool-use.js +199 -10
- package/dist/hooks/prompt-ingest-worker.js +179 -14
- package/dist/hooks/prompt-submit.js +781 -285
- package/dist/hooks/response-ingest-worker.js +1900 -1405
- package/dist/hooks/session-end.js +456 -12
- package/dist/hooks/session-start.js +2188 -1724
- package/dist/hooks/stop.js +200 -10
- package/dist/hooks/subagent-stop.js +199 -10
- package/dist/hooks/summary-worker.js +604 -334
- package/dist/index.js +554 -61
- package/dist/lib/cloud-sync.js +5 -0
- package/dist/lib/config.js +13 -0
- package/dist/lib/consolidation.js +5 -0
- package/dist/lib/database.js +104 -0
- package/dist/lib/device-registry.js +109 -0
- package/dist/lib/embedder.js +13 -0
- package/dist/lib/employee-templates.js +53 -26
- package/dist/lib/employees.js +5 -0
- package/dist/lib/exe-daemon-client.js +5 -0
- package/dist/lib/exe-daemon.js +493 -79
- package/dist/lib/file-grep.js +20 -4
- package/dist/lib/hybrid-search.js +1435 -190
- package/dist/lib/identity-templates.js +126 -5
- package/dist/lib/identity.js +5 -0
- package/dist/lib/license.js +5 -0
- package/dist/lib/messaging.js +37 -24
- package/dist/lib/schedules.js +130 -1
- package/dist/lib/skill-learning.js +11 -0
- package/dist/lib/status-brief.js +5 -0
- package/dist/lib/store.js +199 -10
- package/dist/lib/task-router.js +72 -6
- package/dist/lib/tasks.js +179 -50
- package/dist/lib/tmux-routing.js +179 -46
- package/dist/mcp/server.js +2129 -1855
- package/dist/mcp/tools/create-task.js +86 -36
- package/dist/mcp/tools/deactivate-behavior.js +5 -0
- package/dist/mcp/tools/list-tasks.js +39 -11
- package/dist/mcp/tools/send-message.js +37 -24
- package/dist/mcp/tools/update-task.js +153 -38
- package/dist/runtime/index.js +451 -59
- package/dist/tui/App.js +454 -59
- package/package.json +1 -1
|
@@ -233,6 +233,27 @@ async function ensureSchema() {
|
|
|
233
233
|
});
|
|
234
234
|
} catch {
|
|
235
235
|
}
|
|
236
|
+
try {
|
|
237
|
+
await client.execute({
|
|
238
|
+
sql: `ALTER TABLE tasks ADD COLUMN checkpoint TEXT`,
|
|
239
|
+
args: []
|
|
240
|
+
});
|
|
241
|
+
} catch {
|
|
242
|
+
}
|
|
243
|
+
try {
|
|
244
|
+
await client.execute({
|
|
245
|
+
sql: `ALTER TABLE tasks ADD COLUMN checkpoint_count INTEGER NOT NULL DEFAULT 0`,
|
|
246
|
+
args: []
|
|
247
|
+
});
|
|
248
|
+
} catch {
|
|
249
|
+
}
|
|
250
|
+
try {
|
|
251
|
+
await client.execute({
|
|
252
|
+
sql: `ALTER TABLE tasks ADD COLUMN complexity TEXT NOT NULL DEFAULT 'standard'`,
|
|
253
|
+
args: []
|
|
254
|
+
});
|
|
255
|
+
} catch {
|
|
256
|
+
}
|
|
236
257
|
try {
|
|
237
258
|
await client.execute({
|
|
238
259
|
sql: `ALTER TABLE memories ADD COLUMN task_id TEXT`,
|
|
@@ -643,6 +664,15 @@ async function ensureSchema() {
|
|
|
643
664
|
} catch {
|
|
644
665
|
}
|
|
645
666
|
}
|
|
667
|
+
for (const col of [
|
|
668
|
+
"ALTER TABLE memories ADD COLUMN source_path TEXT",
|
|
669
|
+
"ALTER TABLE memories ADD COLUMN source_type TEXT DEFAULT 'text'"
|
|
670
|
+
]) {
|
|
671
|
+
try {
|
|
672
|
+
await client.execute(col);
|
|
673
|
+
} catch {
|
|
674
|
+
}
|
|
675
|
+
}
|
|
646
676
|
await client.executeMultiple(`
|
|
647
677
|
CREATE INDEX IF NOT EXISTS idx_memories_workspace
|
|
648
678
|
ON memories(workspace_id);
|
|
@@ -707,6 +737,34 @@ async function ensureSchema() {
|
|
|
707
737
|
CREATE INDEX IF NOT EXISTS idx_conversations_channel
|
|
708
738
|
ON conversations(channel_id);
|
|
709
739
|
`);
|
|
740
|
+
try {
|
|
741
|
+
await client.execute({
|
|
742
|
+
sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
|
|
743
|
+
args: []
|
|
744
|
+
});
|
|
745
|
+
} catch {
|
|
746
|
+
}
|
|
747
|
+
try {
|
|
748
|
+
await client.execute({
|
|
749
|
+
sql: `ALTER TABLE tasks ADD COLUMN budget_fallback_model TEXT`,
|
|
750
|
+
args: []
|
|
751
|
+
});
|
|
752
|
+
} catch {
|
|
753
|
+
}
|
|
754
|
+
try {
|
|
755
|
+
await client.execute({
|
|
756
|
+
sql: `ALTER TABLE tasks ADD COLUMN tokens_used INTEGER DEFAULT 0`,
|
|
757
|
+
args: []
|
|
758
|
+
});
|
|
759
|
+
} catch {
|
|
760
|
+
}
|
|
761
|
+
try {
|
|
762
|
+
await client.execute({
|
|
763
|
+
sql: `ALTER TABLE tasks ADD COLUMN tokens_warned_at INTEGER`,
|
|
764
|
+
args: []
|
|
765
|
+
});
|
|
766
|
+
} catch {
|
|
767
|
+
}
|
|
710
768
|
await client.executeMultiple(`
|
|
711
769
|
CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
|
|
712
770
|
content_text,
|
|
@@ -733,6 +791,52 @@ async function ensureSchema() {
|
|
|
733
791
|
VALUES (new.rowid, new.content_text, new.sender_name, new.agent_response);
|
|
734
792
|
END;
|
|
735
793
|
`);
|
|
794
|
+
try {
|
|
795
|
+
await client.execute({
|
|
796
|
+
sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
|
|
797
|
+
args: []
|
|
798
|
+
});
|
|
799
|
+
} catch {
|
|
800
|
+
}
|
|
801
|
+
try {
|
|
802
|
+
await client.execute(
|
|
803
|
+
`CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)`
|
|
804
|
+
);
|
|
805
|
+
} catch {
|
|
806
|
+
}
|
|
807
|
+
try {
|
|
808
|
+
await client.execute({
|
|
809
|
+
sql: `UPDATE memories SET tier = 1 WHERE tool_name = 'commit_to_long_term_memory' AND importance >= 8 AND tier = 3`,
|
|
810
|
+
args: []
|
|
811
|
+
});
|
|
812
|
+
await client.execute({
|
|
813
|
+
sql: `UPDATE memories SET tier = 2 WHERE tool_name IN ('store_memory', 'manual') AND importance >= 5 AND tier = 3`,
|
|
814
|
+
args: []
|
|
815
|
+
});
|
|
816
|
+
} catch {
|
|
817
|
+
}
|
|
818
|
+
try {
|
|
819
|
+
await client.execute({
|
|
820
|
+
sql: `ALTER TABLE memories ADD COLUMN supersedes_id TEXT`,
|
|
821
|
+
args: []
|
|
822
|
+
});
|
|
823
|
+
} catch {
|
|
824
|
+
}
|
|
825
|
+
try {
|
|
826
|
+
await client.execute(
|
|
827
|
+
`CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL`
|
|
828
|
+
);
|
|
829
|
+
} catch {
|
|
830
|
+
}
|
|
831
|
+
for (const col of [
|
|
832
|
+
"ALTER TABLE tasks ADD COLUMN checkpoint TEXT",
|
|
833
|
+
"ALTER TABLE tasks ADD COLUMN checkpoint_count INTEGER DEFAULT 0"
|
|
834
|
+
]) {
|
|
835
|
+
try {
|
|
836
|
+
await client.execute(col);
|
|
837
|
+
} catch {
|
|
838
|
+
}
|
|
839
|
+
}
|
|
736
840
|
}
|
|
737
841
|
var _client, initTurso;
|
|
738
842
|
var init_database = __esm({
|
|
@@ -809,6 +913,11 @@ function normalizeSessionLifecycle(raw) {
|
|
|
809
913
|
const userSL = raw.sessionLifecycle ?? {};
|
|
810
914
|
raw.sessionLifecycle = { ...defaultSL, ...userSL };
|
|
811
915
|
}
|
|
916
|
+
function normalizeAutoUpdate(raw) {
|
|
917
|
+
const defaultAU = DEFAULT_CONFIG.autoUpdate;
|
|
918
|
+
const userAU = raw.autoUpdate ?? {};
|
|
919
|
+
raw.autoUpdate = { ...defaultAU, ...userAU };
|
|
920
|
+
}
|
|
812
921
|
async function loadConfig() {
|
|
813
922
|
const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
|
|
814
923
|
await mkdir2(dir, { recursive: true });
|
|
@@ -831,6 +940,7 @@ async function loadConfig() {
|
|
|
831
940
|
}
|
|
832
941
|
normalizeScalingRoadmap(migratedCfg);
|
|
833
942
|
normalizeSessionLifecycle(migratedCfg);
|
|
943
|
+
normalizeAutoUpdate(migratedCfg);
|
|
834
944
|
const config = { ...DEFAULT_CONFIG, dbPath: path2.join(dir, "memories.db"), ...migratedCfg };
|
|
835
945
|
if (config.dbPath.startsWith("~")) {
|
|
836
946
|
config.dbPath = config.dbPath.replace(/^~/, os.homedir());
|
|
@@ -906,6 +1016,11 @@ var init_config = __esm({
|
|
|
906
1016
|
idleKillTicksRequired: 3,
|
|
907
1017
|
idleKillIntercomAckWindowMs: 1e4,
|
|
908
1018
|
maxAutoInstances: 10
|
|
1019
|
+
},
|
|
1020
|
+
autoUpdate: {
|
|
1021
|
+
checkOnBoot: true,
|
|
1022
|
+
autoInstall: false,
|
|
1023
|
+
checkIntervalMs: 24 * 60 * 60 * 1e3
|
|
909
1024
|
}
|
|
910
1025
|
};
|
|
911
1026
|
CONFIG_MIGRATIONS = [
|
|
@@ -1039,13 +1154,27 @@ async function ensureShardSchema(client) {
|
|
|
1039
1154
|
"ALTER TABLE memories ADD COLUMN document_id TEXT",
|
|
1040
1155
|
"ALTER TABLE memories ADD COLUMN user_id TEXT",
|
|
1041
1156
|
"ALTER TABLE memories ADD COLUMN char_offset INTEGER",
|
|
1042
|
-
"ALTER TABLE memories ADD COLUMN page_number INTEGER"
|
|
1157
|
+
"ALTER TABLE memories ADD COLUMN page_number INTEGER",
|
|
1158
|
+
// Source provenance columns (must match database.ts)
|
|
1159
|
+
"ALTER TABLE memories ADD COLUMN source_path TEXT",
|
|
1160
|
+
"ALTER TABLE memories ADD COLUMN source_type TEXT DEFAULT 'text'",
|
|
1161
|
+
"ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3",
|
|
1162
|
+
"ALTER TABLE memories ADD COLUMN supersedes_id TEXT"
|
|
1043
1163
|
]) {
|
|
1044
1164
|
try {
|
|
1045
1165
|
await client.execute(col);
|
|
1046
1166
|
} catch {
|
|
1047
1167
|
}
|
|
1048
1168
|
}
|
|
1169
|
+
for (const idx of [
|
|
1170
|
+
"CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)",
|
|
1171
|
+
"CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL"
|
|
1172
|
+
]) {
|
|
1173
|
+
try {
|
|
1174
|
+
await client.execute(idx);
|
|
1175
|
+
} catch {
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1049
1178
|
try {
|
|
1050
1179
|
await client.execute("CREATE INDEX IF NOT EXISTS idx_memories_status ON memories(status)");
|
|
1051
1180
|
} catch {
|
|
@@ -1279,9 +1408,10 @@ async function createTaskCore(input) {
|
|
|
1279
1408
|
} catch {
|
|
1280
1409
|
}
|
|
1281
1410
|
}
|
|
1411
|
+
const complexity = input.complexity ?? "standard";
|
|
1282
1412
|
await client.execute({
|
|
1283
|
-
sql: `INSERT INTO tasks (id, title, assigned_to, assigned_by, project_name, priority, status, task_file, blocked_by, parent_task_id, reviewer, context, created_at, updated_at)
|
|
1284
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
1413
|
+
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)
|
|
1414
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
1285
1415
|
args: [
|
|
1286
1416
|
id,
|
|
1287
1417
|
input.title,
|
|
@@ -1295,6 +1425,11 @@ async function createTaskCore(input) {
|
|
|
1295
1425
|
parentTaskId,
|
|
1296
1426
|
input.reviewer ?? null,
|
|
1297
1427
|
input.context,
|
|
1428
|
+
input.budgetTokens ?? null,
|
|
1429
|
+
input.budgetFallbackModel ?? null,
|
|
1430
|
+
0,
|
|
1431
|
+
null,
|
|
1432
|
+
complexity,
|
|
1298
1433
|
now,
|
|
1299
1434
|
now
|
|
1300
1435
|
]
|
|
@@ -1310,7 +1445,11 @@ async function createTaskCore(input) {
|
|
|
1310
1445
|
taskFile,
|
|
1311
1446
|
createdAt: now,
|
|
1312
1447
|
updatedAt: now,
|
|
1313
|
-
warning
|
|
1448
|
+
warning,
|
|
1449
|
+
budgetTokens: input.budgetTokens ?? null,
|
|
1450
|
+
budgetFallbackModel: input.budgetFallbackModel ?? null,
|
|
1451
|
+
tokensUsed: 0,
|
|
1452
|
+
tokensWarnedAt: null
|
|
1314
1453
|
};
|
|
1315
1454
|
}
|
|
1316
1455
|
async function ensureArchitectureDoc(baseDir, projectName) {
|
|
@@ -1670,11 +1809,12 @@ function queueIntercom(targetSession, reason) {
|
|
|
1670
1809
|
}
|
|
1671
1810
|
writeQueue(queue);
|
|
1672
1811
|
}
|
|
1673
|
-
var QUEUE_PATH, INTERCOM_LOG;
|
|
1812
|
+
var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
|
|
1674
1813
|
var init_intercom_queue = __esm({
|
|
1675
1814
|
"src/lib/intercom-queue.ts"() {
|
|
1676
1815
|
"use strict";
|
|
1677
1816
|
QUEUE_PATH = path8.join(os4.homedir(), ".exe-os", "intercom-queue.json");
|
|
1817
|
+
TTL_MS = 60 * 60 * 1e3;
|
|
1678
1818
|
INTERCOM_LOG = path8.join(os4.homedir(), ".exe-os", "intercom.log");
|
|
1679
1819
|
}
|
|
1680
1820
|
});
|
|
@@ -1797,6 +1937,17 @@ function getGitRoot(dir) {
|
|
|
1797
1937
|
return null;
|
|
1798
1938
|
}
|
|
1799
1939
|
}
|
|
1940
|
+
function getMainRepoRoot(dir) {
|
|
1941
|
+
try {
|
|
1942
|
+
const commonDir = execSync5(
|
|
1943
|
+
"git rev-parse --path-format=absolute --git-common-dir",
|
|
1944
|
+
{ cwd: dir, encoding: "utf-8", timeout: GIT_TIMEOUT_MS, stdio: ["pipe", "pipe", "pipe"] }
|
|
1945
|
+
).trim();
|
|
1946
|
+
return realpath(path11.dirname(commonDir));
|
|
1947
|
+
} catch {
|
|
1948
|
+
return null;
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1800
1951
|
function worktreePath(repoRoot, employeeName, instance) {
|
|
1801
1952
|
const label = instanceLabel(employeeName, instance);
|
|
1802
1953
|
return path11.join(repoRoot, ".worktrees", label);
|
|
@@ -2022,6 +2173,11 @@ function getSessionState(sessionName) {
|
|
|
2022
2173
|
if (!transport.isAlive(sessionName)) return "offline";
|
|
2023
2174
|
try {
|
|
2024
2175
|
const pane = transport.capturePane(sessionName, 5);
|
|
2176
|
+
if (!pane.includes("\u276F") && !pane.includes("Claude Code") && !BUSY_PATTERN.test(pane) && !/Running…/.test(pane)) {
|
|
2177
|
+
if (/\$\s*$/.test(pane) || /% $/.test(pane.trimEnd())) {
|
|
2178
|
+
return "no_claude";
|
|
2179
|
+
}
|
|
2180
|
+
}
|
|
2025
2181
|
if (/Running…/.test(pane)) return "tool";
|
|
2026
2182
|
if (BUSY_PATTERN.test(pane)) return "thinking";
|
|
2027
2183
|
return "idle";
|
|
@@ -2029,10 +2185,6 @@ function getSessionState(sessionName) {
|
|
|
2029
2185
|
return "offline";
|
|
2030
2186
|
}
|
|
2031
2187
|
}
|
|
2032
|
-
function isSessionBusy(sessionName) {
|
|
2033
|
-
const state = getSessionState(sessionName);
|
|
2034
|
-
return state === "thinking" || state === "tool";
|
|
2035
|
-
}
|
|
2036
2188
|
function isExeSession(sessionName) {
|
|
2037
2189
|
return /^exe\d*$/.test(sessionName);
|
|
2038
2190
|
}
|
|
@@ -2052,7 +2204,14 @@ function sendIntercom(targetSession) {
|
|
|
2052
2204
|
logIntercom(`SKIP \u2192 ${targetSession} (session not found)`);
|
|
2053
2205
|
return "failed";
|
|
2054
2206
|
}
|
|
2055
|
-
|
|
2207
|
+
const sessionState = getSessionState(targetSession);
|
|
2208
|
+
if (sessionState === "no_claude") {
|
|
2209
|
+
queueIntercom(targetSession, "claude not running in session");
|
|
2210
|
+
recordDebounce(targetSession);
|
|
2211
|
+
logIntercom(`QUEUED \u2192 ${targetSession} (no claude process \u2014 raw shell detected)`);
|
|
2212
|
+
return "queued";
|
|
2213
|
+
}
|
|
2214
|
+
if (sessionState === "thinking" || sessionState === "tool") {
|
|
2056
2215
|
queueIntercom(targetSession, "session busy at send time");
|
|
2057
2216
|
recordDebounce(targetSession);
|
|
2058
2217
|
logIntercom(`QUEUED \u2192 ${targetSession} (session busy, will retry from queue)`);
|
|
@@ -2064,18 +2223,7 @@ function sendIntercom(targetSession) {
|
|
|
2064
2223
|
}
|
|
2065
2224
|
transport.sendKeys(targetSession, "/exe-intercom");
|
|
2066
2225
|
recordDebounce(targetSession);
|
|
2067
|
-
|
|
2068
|
-
try {
|
|
2069
|
-
execSync6(`sleep ${INTERCOM_POLL_INTERVAL_S}`);
|
|
2070
|
-
} catch {
|
|
2071
|
-
}
|
|
2072
|
-
const state = getSessionState(targetSession);
|
|
2073
|
-
if (state === "thinking" || state === "tool") {
|
|
2074
|
-
logIntercom(`ACKNOWLEDGED \u2192 ${targetSession} (state=${state}, poll=${i + 1})`);
|
|
2075
|
-
return "acknowledged";
|
|
2076
|
-
}
|
|
2077
|
-
}
|
|
2078
|
-
logIntercom(`DELIVERED \u2192 ${targetSession} (no state transition after ${INTERCOM_POLL_MAX_ATTEMPTS}s)`);
|
|
2226
|
+
logIntercom(`DELIVERED \u2192 ${targetSession} (fire-and-forget)`);
|
|
2079
2227
|
return "delivered";
|
|
2080
2228
|
} catch {
|
|
2081
2229
|
logIntercom(`FAIL \u2192 ${targetSession}`);
|
|
@@ -2129,7 +2277,8 @@ function ensureEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
2129
2277
|
return { status: "failed", sessionName, error: "intercom delivery failed" };
|
|
2130
2278
|
}
|
|
2131
2279
|
const spawnOpts = { ...opts, instance: effectiveInstance };
|
|
2132
|
-
const
|
|
2280
|
+
const mainRoot = getMainRepoRoot(projectDir) ?? projectDir;
|
|
2281
|
+
const wtPath = ensureWorktree(mainRoot, employeeName, effectiveInstance);
|
|
2133
2282
|
if (wtPath) {
|
|
2134
2283
|
spawnOpts.cwd = wtPath;
|
|
2135
2284
|
}
|
|
@@ -2310,7 +2459,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
2310
2459
|
let booted = false;
|
|
2311
2460
|
for (let i = 0; i < 30; i++) {
|
|
2312
2461
|
try {
|
|
2313
|
-
execSync6("sleep
|
|
2462
|
+
execSync6("sleep 0.5");
|
|
2314
2463
|
} catch {
|
|
2315
2464
|
}
|
|
2316
2465
|
try {
|
|
@@ -2330,7 +2479,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
2330
2479
|
}
|
|
2331
2480
|
}
|
|
2332
2481
|
if (!booted) {
|
|
2333
|
-
return { sessionName, error: `${useExeAgent ? "exe-agent" : "claude"} did not boot within
|
|
2482
|
+
return { sessionName, error: `${useExeAgent ? "exe-agent" : "claude"} did not boot within 15s` };
|
|
2334
2483
|
}
|
|
2335
2484
|
if (!useExeAgent) {
|
|
2336
2485
|
try {
|
|
@@ -2348,7 +2497,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
2348
2497
|
});
|
|
2349
2498
|
return { sessionName };
|
|
2350
2499
|
}
|
|
2351
|
-
var SESSION_CACHE, BEHAVIORS_EXPORT_TIMEOUT_MS, INTERCOM_DEBOUNCE_MS, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS, BUSY_PATTERN
|
|
2500
|
+
var SESSION_CACHE, BEHAVIORS_EXPORT_TIMEOUT_MS, INTERCOM_DEBOUNCE_MS, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS, BUSY_PATTERN;
|
|
2352
2501
|
var init_tmux_routing = __esm({
|
|
2353
2502
|
"src/lib/tmux-routing.ts"() {
|
|
2354
2503
|
"use strict";
|
|
@@ -2368,8 +2517,6 @@ var init_tmux_routing = __esm({
|
|
|
2368
2517
|
DEBOUNCE_FILE = path12.join(SESSION_CACHE, "intercom-debounce.json");
|
|
2369
2518
|
DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
|
|
2370
2519
|
BUSY_PATTERN = /[✻✽✶✳·].*…|Running…/;
|
|
2371
|
-
INTERCOM_POLL_INTERVAL_S = 1;
|
|
2372
|
-
INTERCOM_POLL_MAX_ATTEMPTS = 8;
|
|
2373
2520
|
}
|
|
2374
2521
|
});
|
|
2375
2522
|
|
|
@@ -2407,12 +2554,23 @@ function getProjectName(cwd) {
|
|
|
2407
2554
|
const dir = cwd ?? process.cwd();
|
|
2408
2555
|
if (_cached2 && _cachedCwd === dir) return _cached2;
|
|
2409
2556
|
try {
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2557
|
+
let repoRoot;
|
|
2558
|
+
try {
|
|
2559
|
+
const gitCommonDir = execSync7("git rev-parse --path-format=absolute --git-common-dir", {
|
|
2560
|
+
cwd: dir,
|
|
2561
|
+
encoding: "utf8",
|
|
2562
|
+
timeout: 2e3,
|
|
2563
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
2564
|
+
}).trim();
|
|
2565
|
+
repoRoot = path15.dirname(gitCommonDir);
|
|
2566
|
+
} catch {
|
|
2567
|
+
repoRoot = execSync7("git rev-parse --show-toplevel", {
|
|
2568
|
+
cwd: dir,
|
|
2569
|
+
encoding: "utf8",
|
|
2570
|
+
timeout: 2e3,
|
|
2571
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
2572
|
+
}).trim();
|
|
2573
|
+
}
|
|
2416
2574
|
_cached2 = path15.basename(repoRoot);
|
|
2417
2575
|
_cachedCwd = dir;
|
|
2418
2576
|
return _cached2;
|
|
@@ -2518,7 +2676,9 @@ async function dispatchTaskToEmployee(input) {
|
|
|
2518
2676
|
return { dispatched, session: sessionName, crossProject };
|
|
2519
2677
|
} else {
|
|
2520
2678
|
const projectDir = input.projectDir ?? process.cwd();
|
|
2521
|
-
const result = ensureEmployee(input.assignedTo, exeSession, projectDir
|
|
2679
|
+
const result = ensureEmployee(input.assignedTo, exeSession, projectDir, {
|
|
2680
|
+
autoInstance: input.assignedTo === "tom" || input.assignedTo === "sasha"
|
|
2681
|
+
});
|
|
2522
2682
|
if (result.status === "failed") {
|
|
2523
2683
|
process.stderr.write(
|
|
2524
2684
|
`[dispatch] Failed to spawn ${input.assignedTo}: ${result.error}
|