@askexenow/exe-os 0.9.7 → 0.9.9
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 +953 -105
- package/dist/bin/backfill-responses.js +952 -104
- package/dist/bin/backfill-vectors.js +956 -108
- package/dist/bin/cleanup-stale-review-tasks.js +802 -58
- package/dist/bin/cli.js +2292 -1070
- package/dist/bin/exe-agent-config.js +157 -101
- package/dist/bin/exe-agent.js +55 -29
- package/dist/bin/exe-assign.js +940 -92
- package/dist/bin/exe-boot.js +1424 -442
- package/dist/bin/exe-call.js +240 -141
- package/dist/bin/exe-cloud.js +198 -70
- package/dist/bin/exe-dispatch.js +951 -192
- package/dist/bin/exe-doctor.js +791 -51
- package/dist/bin/exe-export-behaviors.js +790 -42
- package/dist/bin/exe-forget.js +771 -31
- package/dist/bin/exe-gateway.js +1592 -521
- package/dist/bin/exe-heartbeat.js +850 -109
- package/dist/bin/exe-kill.js +783 -35
- package/dist/bin/exe-launch-agent.js +1030 -107
- package/dist/bin/exe-link.js +916 -110
- package/dist/bin/exe-new-employee.js +526 -217
- package/dist/bin/exe-pending-messages.js +1046 -62
- package/dist/bin/exe-pending-notifications.js +1318 -111
- package/dist/bin/exe-pending-reviews.js +1040 -72
- package/dist/bin/exe-rename.js +772 -59
- package/dist/bin/exe-review.js +772 -32
- package/dist/bin/exe-search.js +982 -128
- package/dist/bin/exe-session-cleanup.js +1180 -306
- package/dist/bin/exe-settings.js +185 -105
- package/dist/bin/exe-start-codex.js +886 -132
- package/dist/bin/exe-start-opencode.js +873 -119
- package/dist/bin/exe-status.js +803 -59
- package/dist/bin/exe-team.js +772 -32
- package/dist/bin/git-sweep.js +1046 -223
- package/dist/bin/graph-backfill.js +779 -31
- package/dist/bin/graph-export.js +785 -37
- package/dist/bin/install.js +632 -200
- package/dist/bin/scan-tasks.js +1055 -232
- package/dist/bin/setup.js +1419 -320
- package/dist/bin/shard-migrate.js +783 -35
- package/dist/bin/update.js +138 -49
- package/dist/bin/wiki-sync.js +782 -34
- package/dist/gateway/index.js +1444 -449
- package/dist/hooks/bug-report-worker.js +1141 -269
- package/dist/hooks/codex-stop-task-finalizer.js +4678 -0
- package/dist/hooks/commit-complete.js +1044 -221
- package/dist/hooks/error-recall.js +989 -135
- package/dist/hooks/exe-heartbeat-hook.js +99 -75
- package/dist/hooks/ingest-worker.js +4176 -3226
- package/dist/hooks/ingest.js +920 -168
- package/dist/hooks/instructions-loaded.js +874 -70
- package/dist/hooks/notification.js +860 -56
- package/dist/hooks/post-compact.js +881 -73
- package/dist/hooks/pre-compact.js +1050 -227
- package/dist/hooks/pre-tool-use.js +1084 -159
- package/dist/hooks/prompt-ingest-worker.js +1089 -164
- package/dist/hooks/prompt-submit.js +1469 -515
- package/dist/hooks/response-ingest-worker.js +1104 -179
- package/dist/hooks/session-end.js +1085 -251
- package/dist/hooks/session-start.js +1241 -231
- package/dist/hooks/stop.js +935 -109
- package/dist/hooks/subagent-stop.js +881 -73
- package/dist/hooks/summary-worker.js +1323 -307
- package/dist/index.js +1449 -452
- package/dist/lib/agent-config.js +28 -6
- package/dist/lib/cloud-sync.js +909 -115
- package/dist/lib/config.js +30 -10
- package/dist/lib/consolidation.js +42 -9
- package/dist/lib/database.js +739 -33
- package/dist/lib/db-daemon-client.js +73 -19
- package/dist/lib/db.js +2359 -0
- package/dist/lib/device-registry.js +760 -47
- package/dist/lib/embedder.js +201 -73
- package/dist/lib/employee-templates.js +30 -4
- package/dist/lib/employees.js +290 -86
- package/dist/lib/exe-daemon-client.js +187 -83
- package/dist/lib/exe-daemon.js +1696 -616
- package/dist/lib/hybrid-search.js +982 -128
- package/dist/lib/identity.js +43 -13
- package/dist/lib/license.js +133 -48
- package/dist/lib/messaging.js +167 -80
- package/dist/lib/reminders.js +35 -5
- package/dist/lib/schedules.js +772 -32
- package/dist/lib/skill-learning.js +54 -7
- package/dist/lib/store.js +779 -31
- package/dist/lib/task-router.js +94 -73
- package/dist/lib/tasks.js +298 -225
- package/dist/lib/tmux-routing.js +246 -172
- package/dist/lib/token-spend.js +52 -14
- package/dist/mcp/server.js +2893 -850
- package/dist/mcp/tools/complete-reminder.js +35 -5
- package/dist/mcp/tools/create-reminder.js +35 -5
- package/dist/mcp/tools/create-task.js +507 -323
- package/dist/mcp/tools/deactivate-behavior.js +40 -10
- package/dist/mcp/tools/list-reminders.js +35 -5
- package/dist/mcp/tools/list-tasks.js +277 -104
- package/dist/mcp/tools/send-message.js +129 -56
- package/dist/mcp/tools/update-task.js +1864 -188
- package/dist/runtime/index.js +1083 -259
- package/dist/tui/App.js +1501 -434
- package/package.json +3 -2
|
@@ -26,9 +26,18 @@ var init_db_retry = __esm({
|
|
|
26
26
|
}
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
+
// src/lib/secure-files.ts
|
|
30
|
+
import { chmodSync, existsSync, mkdirSync } from "fs";
|
|
31
|
+
import { chmod, mkdir } from "fs/promises";
|
|
32
|
+
var init_secure_files = __esm({
|
|
33
|
+
"src/lib/secure-files.ts"() {
|
|
34
|
+
"use strict";
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
29
38
|
// src/lib/config.ts
|
|
30
|
-
import { readFile, writeFile
|
|
31
|
-
import { readFileSync, existsSync, renameSync } from "fs";
|
|
39
|
+
import { readFile, writeFile } from "fs/promises";
|
|
40
|
+
import { readFileSync, existsSync as existsSync2, renameSync } from "fs";
|
|
32
41
|
import path from "path";
|
|
33
42
|
import os from "os";
|
|
34
43
|
function resolveDataDir() {
|
|
@@ -36,7 +45,7 @@ function resolveDataDir() {
|
|
|
36
45
|
if (process.env.EXE_MEM_DIR) return process.env.EXE_MEM_DIR;
|
|
37
46
|
const newDir = path.join(os.homedir(), ".exe-os");
|
|
38
47
|
const legacyDir = path.join(os.homedir(), ".exe-mem");
|
|
39
|
-
if (!
|
|
48
|
+
if (!existsSync2(newDir) && existsSync2(legacyDir)) {
|
|
40
49
|
try {
|
|
41
50
|
renameSync(legacyDir, newDir);
|
|
42
51
|
process.stderr.write(`[exe-os] Migrated data directory: ~/.exe-mem \u2192 ~/.exe-os
|
|
@@ -51,6 +60,7 @@ var EXE_AI_DIR, DB_PATH, MODELS_DIR, CONFIG_PATH, LEGACY_LANCE_PATH, CURRENT_CON
|
|
|
51
60
|
var init_config = __esm({
|
|
52
61
|
"src/lib/config.ts"() {
|
|
53
62
|
"use strict";
|
|
63
|
+
init_secure_files();
|
|
54
64
|
EXE_AI_DIR = resolveDataDir();
|
|
55
65
|
DB_PATH = path.join(EXE_AI_DIR, "memories.db");
|
|
56
66
|
MODELS_DIR = path.join(EXE_AI_DIR, "models");
|
|
@@ -119,7 +129,7 @@ var init_config = __esm({
|
|
|
119
129
|
|
|
120
130
|
// src/lib/employees.ts
|
|
121
131
|
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
122
|
-
import { existsSync as
|
|
132
|
+
import { existsSync as existsSync3, symlinkSync, readlinkSync, readFileSync as readFileSync2, renameSync as renameSync2, unlinkSync, writeFileSync } from "fs";
|
|
123
133
|
import { execSync } from "child_process";
|
|
124
134
|
import path2 from "path";
|
|
125
135
|
import os2 from "os";
|
|
@@ -136,7 +146,7 @@ function getCoordinatorName(employees = loadEmployeesSync()) {
|
|
|
136
146
|
return getCoordinatorEmployee(employees)?.name ?? DEFAULT_COORDINATOR_TEMPLATE_NAME;
|
|
137
147
|
}
|
|
138
148
|
function loadEmployeesSync(employeesPath = EMPLOYEES_PATH) {
|
|
139
|
-
if (!
|
|
149
|
+
if (!existsSync3(employeesPath)) return [];
|
|
140
150
|
try {
|
|
141
151
|
return JSON.parse(readFileSync2(employeesPath, "utf-8"));
|
|
142
152
|
} catch {
|
|
@@ -154,7 +164,7 @@ function baseAgentName(name, employees) {
|
|
|
154
164
|
if (getEmployee(roster, base)) return base;
|
|
155
165
|
return name;
|
|
156
166
|
}
|
|
157
|
-
var EMPLOYEES_PATH, DEFAULT_COORDINATOR_TEMPLATE_NAME, COORDINATOR_ROLE;
|
|
167
|
+
var EMPLOYEES_PATH, DEFAULT_COORDINATOR_TEMPLATE_NAME, COORDINATOR_ROLE, IDENTITY_DIR;
|
|
158
168
|
var init_employees = __esm({
|
|
159
169
|
"src/lib/employees.ts"() {
|
|
160
170
|
"use strict";
|
|
@@ -162,15 +172,40 @@ var init_employees = __esm({
|
|
|
162
172
|
EMPLOYEES_PATH = path2.join(EXE_AI_DIR, "exe-employees.json");
|
|
163
173
|
DEFAULT_COORDINATOR_TEMPLATE_NAME = "exe";
|
|
164
174
|
COORDINATOR_ROLE = "COO";
|
|
175
|
+
IDENTITY_DIR = path2.join(EXE_AI_DIR, "identity");
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
// src/lib/database-adapter.ts
|
|
180
|
+
import os3 from "os";
|
|
181
|
+
import path3 from "path";
|
|
182
|
+
import { createRequire } from "module";
|
|
183
|
+
import { pathToFileURL } from "url";
|
|
184
|
+
var BOOLEAN_COLUMNS_BY_TABLE, BOOLEAN_COLUMN_NAMES;
|
|
185
|
+
var init_database_adapter = __esm({
|
|
186
|
+
"src/lib/database-adapter.ts"() {
|
|
187
|
+
"use strict";
|
|
188
|
+
BOOLEAN_COLUMNS_BY_TABLE = {
|
|
189
|
+
memories: /* @__PURE__ */ new Set(["has_error", "draft"]),
|
|
190
|
+
behaviors: /* @__PURE__ */ new Set(["active"]),
|
|
191
|
+
notifications: /* @__PURE__ */ new Set(["read"]),
|
|
192
|
+
users: /* @__PURE__ */ new Set(["has_personal_memory"])
|
|
193
|
+
};
|
|
194
|
+
BOOLEAN_COLUMN_NAMES = new Set(
|
|
195
|
+
Object.values(BOOLEAN_COLUMNS_BY_TABLE).flatMap((cols) => [...cols])
|
|
196
|
+
);
|
|
165
197
|
}
|
|
166
198
|
});
|
|
167
199
|
|
|
168
200
|
// src/lib/database.ts
|
|
169
201
|
import { createClient } from "@libsql/client";
|
|
170
202
|
function getClient() {
|
|
171
|
-
if (!
|
|
203
|
+
if (!_adapterClient) {
|
|
172
204
|
throw new Error("Database client not initialized. Call initDatabase() first.");
|
|
173
205
|
}
|
|
206
|
+
if (process.env.DATABASE_URL) {
|
|
207
|
+
return _adapterClient;
|
|
208
|
+
}
|
|
174
209
|
if (process.env.EXE_IS_DAEMON === "1") {
|
|
175
210
|
return _resilientClient;
|
|
176
211
|
}
|
|
@@ -179,25 +214,27 @@ function getClient() {
|
|
|
179
214
|
}
|
|
180
215
|
return _resilientClient;
|
|
181
216
|
}
|
|
182
|
-
var _resilientClient, _daemonClient;
|
|
217
|
+
var _resilientClient, _daemonClient, _adapterClient;
|
|
183
218
|
var init_database = __esm({
|
|
184
219
|
"src/lib/database.ts"() {
|
|
185
220
|
"use strict";
|
|
186
221
|
init_db_retry();
|
|
187
222
|
init_employees();
|
|
223
|
+
init_database_adapter();
|
|
188
224
|
_resilientClient = null;
|
|
189
225
|
_daemonClient = null;
|
|
226
|
+
_adapterClient = null;
|
|
190
227
|
}
|
|
191
228
|
});
|
|
192
229
|
|
|
193
230
|
// src/lib/session-registry.ts
|
|
194
|
-
import
|
|
195
|
-
import
|
|
231
|
+
import path4 from "path";
|
|
232
|
+
import os4 from "os";
|
|
196
233
|
var REGISTRY_PATH;
|
|
197
234
|
var init_session_registry = __esm({
|
|
198
235
|
"src/lib/session-registry.ts"() {
|
|
199
236
|
"use strict";
|
|
200
|
-
REGISTRY_PATH =
|
|
237
|
+
REGISTRY_PATH = path4.join(os4.homedir(), ".exe-os", "session-registry.json");
|
|
201
238
|
}
|
|
202
239
|
});
|
|
203
240
|
|
|
@@ -433,10 +470,10 @@ var init_runtime_table = __esm({
|
|
|
433
470
|
});
|
|
434
471
|
|
|
435
472
|
// src/lib/agent-config.ts
|
|
436
|
-
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, existsSync as
|
|
437
|
-
import
|
|
473
|
+
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, existsSync as existsSync4 } from "fs";
|
|
474
|
+
import path5 from "path";
|
|
438
475
|
function loadAgentConfig() {
|
|
439
|
-
if (!
|
|
476
|
+
if (!existsSync4(AGENT_CONFIG_PATH)) return {};
|
|
440
477
|
try {
|
|
441
478
|
return JSON.parse(readFileSync3(AGENT_CONFIG_PATH, "utf-8"));
|
|
442
479
|
} catch {
|
|
@@ -457,7 +494,8 @@ var init_agent_config = __esm({
|
|
|
457
494
|
"use strict";
|
|
458
495
|
init_config();
|
|
459
496
|
init_runtime_table();
|
|
460
|
-
|
|
497
|
+
init_secure_files();
|
|
498
|
+
AGENT_CONFIG_PATH = path5.join(EXE_AI_DIR, "agent-config.json");
|
|
461
499
|
DEFAULT_MODELS = {
|
|
462
500
|
claude: "claude-opus-4",
|
|
463
501
|
codex: RUNTIME_TABLE.codex?.defaultModel ?? "gpt-5.4",
|
|
@@ -467,16 +505,16 @@ var init_agent_config = __esm({
|
|
|
467
505
|
});
|
|
468
506
|
|
|
469
507
|
// src/lib/intercom-queue.ts
|
|
470
|
-
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, renameSync as renameSync3, existsSync as
|
|
471
|
-
import
|
|
472
|
-
import
|
|
508
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, renameSync as renameSync3, existsSync as existsSync5, mkdirSync as mkdirSync2 } from "fs";
|
|
509
|
+
import path6 from "path";
|
|
510
|
+
import os5 from "os";
|
|
473
511
|
function ensureDir() {
|
|
474
|
-
const dir =
|
|
475
|
-
if (!
|
|
512
|
+
const dir = path6.dirname(QUEUE_PATH);
|
|
513
|
+
if (!existsSync5(dir)) mkdirSync2(dir, { recursive: true });
|
|
476
514
|
}
|
|
477
515
|
function readQueue() {
|
|
478
516
|
try {
|
|
479
|
-
if (!
|
|
517
|
+
if (!existsSync5(QUEUE_PATH)) return [];
|
|
480
518
|
return JSON.parse(readFileSync4(QUEUE_PATH, "utf8"));
|
|
481
519
|
} catch {
|
|
482
520
|
return [];
|
|
@@ -509,31 +547,34 @@ var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
|
|
|
509
547
|
var init_intercom_queue = __esm({
|
|
510
548
|
"src/lib/intercom-queue.ts"() {
|
|
511
549
|
"use strict";
|
|
512
|
-
QUEUE_PATH =
|
|
550
|
+
QUEUE_PATH = path6.join(os5.homedir(), ".exe-os", "intercom-queue.json");
|
|
513
551
|
TTL_MS = 60 * 60 * 1e3;
|
|
514
|
-
INTERCOM_LOG =
|
|
552
|
+
INTERCOM_LOG = path6.join(os5.homedir(), ".exe-os", "intercom.log");
|
|
515
553
|
}
|
|
516
554
|
});
|
|
517
555
|
|
|
518
556
|
// src/lib/license.ts
|
|
519
|
-
import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, existsSync as
|
|
557
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, existsSync as existsSync6, mkdirSync as mkdirSync3 } from "fs";
|
|
520
558
|
import { randomUUID } from "crypto";
|
|
521
|
-
import
|
|
559
|
+
import { createRequire as createRequire2 } from "module";
|
|
560
|
+
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
561
|
+
import os6 from "os";
|
|
562
|
+
import path7 from "path";
|
|
522
563
|
import { jwtVerify, importSPKI } from "jose";
|
|
523
564
|
var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH;
|
|
524
565
|
var init_license = __esm({
|
|
525
566
|
"src/lib/license.ts"() {
|
|
526
567
|
"use strict";
|
|
527
568
|
init_config();
|
|
528
|
-
LICENSE_PATH =
|
|
529
|
-
CACHE_PATH =
|
|
530
|
-
DEVICE_ID_PATH =
|
|
569
|
+
LICENSE_PATH = path7.join(EXE_AI_DIR, "license.key");
|
|
570
|
+
CACHE_PATH = path7.join(EXE_AI_DIR, "license-cache.json");
|
|
571
|
+
DEVICE_ID_PATH = path7.join(EXE_AI_DIR, "device-id");
|
|
531
572
|
}
|
|
532
573
|
});
|
|
533
574
|
|
|
534
575
|
// src/lib/plan-limits.ts
|
|
535
|
-
import { readFileSync as readFileSync6, existsSync as
|
|
536
|
-
import
|
|
576
|
+
import { readFileSync as readFileSync6, existsSync as existsSync7 } from "fs";
|
|
577
|
+
import path8 from "path";
|
|
537
578
|
var CACHE_PATH2;
|
|
538
579
|
var init_plan_limits = __esm({
|
|
539
580
|
"src/lib/plan-limits.ts"() {
|
|
@@ -542,15 +583,15 @@ var init_plan_limits = __esm({
|
|
|
542
583
|
init_employees();
|
|
543
584
|
init_license();
|
|
544
585
|
init_config();
|
|
545
|
-
CACHE_PATH2 =
|
|
586
|
+
CACHE_PATH2 = path8.join(EXE_AI_DIR, "license-cache.json");
|
|
546
587
|
}
|
|
547
588
|
});
|
|
548
589
|
|
|
549
590
|
// src/lib/tmux-routing.ts
|
|
550
591
|
import { execFileSync as execFileSync2, execSync as execSync4 } from "child_process";
|
|
551
|
-
import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, existsSync as
|
|
552
|
-
import
|
|
553
|
-
import
|
|
592
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, existsSync as existsSync8, appendFileSync, readdirSync } from "fs";
|
|
593
|
+
import path9 from "path";
|
|
594
|
+
import os7 from "os";
|
|
554
595
|
import { fileURLToPath } from "url";
|
|
555
596
|
function getMySession() {
|
|
556
597
|
return getTransport().getMySession();
|
|
@@ -590,7 +631,7 @@ function extractRootExe(name) {
|
|
|
590
631
|
}
|
|
591
632
|
function getParentExe(sessionKey) {
|
|
592
633
|
try {
|
|
593
|
-
const data = JSON.parse(readFileSync7(
|
|
634
|
+
const data = JSON.parse(readFileSync7(path9.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
|
|
594
635
|
return data.parentExe || null;
|
|
595
636
|
} catch {
|
|
596
637
|
return null;
|
|
@@ -623,7 +664,7 @@ function isEmployeeAlive(sessionName) {
|
|
|
623
664
|
}
|
|
624
665
|
function readDebounceState() {
|
|
625
666
|
try {
|
|
626
|
-
if (!
|
|
667
|
+
if (!existsSync8(DEBOUNCE_FILE)) return {};
|
|
627
668
|
const raw = JSON.parse(readFileSync7(DEBOUNCE_FILE, "utf8"));
|
|
628
669
|
const state = {};
|
|
629
670
|
for (const [key, val] of Object.entries(raw)) {
|
|
@@ -640,7 +681,7 @@ function readDebounceState() {
|
|
|
640
681
|
}
|
|
641
682
|
function writeDebounceState(state) {
|
|
642
683
|
try {
|
|
643
|
-
if (!
|
|
684
|
+
if (!existsSync8(SESSION_CACHE)) mkdirSync4(SESSION_CACHE, { recursive: true });
|
|
644
685
|
writeFileSync5(DEBOUNCE_FILE, JSON.stringify(state));
|
|
645
686
|
} catch {
|
|
646
687
|
}
|
|
@@ -735,8 +776,8 @@ function sendIntercom(targetSession) {
|
|
|
735
776
|
try {
|
|
736
777
|
const rawAgent = targetSession.split("-")[0] ?? targetSession;
|
|
737
778
|
const agent = baseAgentName(rawAgent);
|
|
738
|
-
const markerPath =
|
|
739
|
-
if (
|
|
779
|
+
const markerPath = path9.join(SESSION_CACHE, `current-task-${agent}.json`);
|
|
780
|
+
if (existsSync8(markerPath)) {
|
|
740
781
|
logIntercom(`SKIP \u2192 ${targetSession} (has in_progress task marker \u2014 will auto-chain)`);
|
|
741
782
|
return "debounced";
|
|
742
783
|
}
|
|
@@ -745,8 +786,8 @@ function sendIntercom(targetSession) {
|
|
|
745
786
|
try {
|
|
746
787
|
const rawAgent = targetSession.split("-")[0] ?? targetSession;
|
|
747
788
|
const agent = baseAgentName(rawAgent);
|
|
748
|
-
const taskDir =
|
|
749
|
-
if (
|
|
789
|
+
const taskDir = path9.join(process.cwd(), "exe", agent);
|
|
790
|
+
if (existsSync8(taskDir)) {
|
|
750
791
|
const files = readdirSync(taskDir).filter(
|
|
751
792
|
(f) => f.endsWith(".md") && f !== "DONE.txt"
|
|
752
793
|
);
|
|
@@ -799,24 +840,49 @@ var init_tmux_routing = __esm({
|
|
|
799
840
|
init_intercom_queue();
|
|
800
841
|
init_plan_limits();
|
|
801
842
|
init_employees();
|
|
802
|
-
SPAWN_LOCK_DIR =
|
|
803
|
-
SESSION_CACHE =
|
|
843
|
+
SPAWN_LOCK_DIR = path9.join(os7.homedir(), ".exe-os", "spawn-locks");
|
|
844
|
+
SESSION_CACHE = path9.join(os7.homedir(), ".exe-os", "session-cache");
|
|
804
845
|
VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
|
|
805
846
|
INTERCOM_DEBOUNCE_MS = 3e4;
|
|
806
847
|
CODEX_DEBOUNCE_MS = 12e4;
|
|
807
|
-
INTERCOM_LOG2 =
|
|
808
|
-
DEBOUNCE_FILE =
|
|
848
|
+
INTERCOM_LOG2 = path9.join(os7.homedir(), ".exe-os", "intercom.log");
|
|
849
|
+
DEBOUNCE_FILE = path9.join(SESSION_CACHE, "intercom-debounce.json");
|
|
809
850
|
DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
|
|
810
851
|
BUSY_PATTERN = /[✻✽✶✳·].*…|Running…|• Working|• Ran |• Explored|• Called|esc to interrupt/;
|
|
811
852
|
}
|
|
812
853
|
});
|
|
813
854
|
|
|
855
|
+
// src/lib/task-scope.ts
|
|
856
|
+
function getCurrentSessionScope() {
|
|
857
|
+
try {
|
|
858
|
+
return resolveExeSession();
|
|
859
|
+
} catch {
|
|
860
|
+
return null;
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
function strictSessionScopeFilter(sessionScope, tableAlias) {
|
|
864
|
+
const scope = sessionScope !== void 0 ? sessionScope : getCurrentSessionScope();
|
|
865
|
+
if (!scope) return { sql: "", args: [] };
|
|
866
|
+
const col = tableAlias ? `${tableAlias}.session_scope` : "session_scope";
|
|
867
|
+
return {
|
|
868
|
+
sql: ` AND ${col} = ?`,
|
|
869
|
+
args: [scope]
|
|
870
|
+
};
|
|
871
|
+
}
|
|
872
|
+
var init_task_scope = __esm({
|
|
873
|
+
"src/lib/task-scope.ts"() {
|
|
874
|
+
"use strict";
|
|
875
|
+
init_tmux_routing();
|
|
876
|
+
}
|
|
877
|
+
});
|
|
878
|
+
|
|
814
879
|
// src/mcp/tools/send-message.ts
|
|
815
880
|
import { z } from "zod";
|
|
816
881
|
|
|
817
882
|
// src/lib/messaging.ts
|
|
818
883
|
init_database();
|
|
819
884
|
init_tmux_routing();
|
|
885
|
+
init_task_scope();
|
|
820
886
|
import crypto from "crypto";
|
|
821
887
|
function generateUlid() {
|
|
822
888
|
const timestamp = Date.now().toString(36).padStart(10, "0");
|
|
@@ -831,6 +897,7 @@ function rowToMessage(row) {
|
|
|
831
897
|
targetAgent: row.target_agent,
|
|
832
898
|
targetProject: row.target_project ?? null,
|
|
833
899
|
targetDevice: row.target_device,
|
|
900
|
+
sessionScope: row.session_scope ?? null,
|
|
834
901
|
content: row.content,
|
|
835
902
|
priority: row.priority ?? "normal",
|
|
836
903
|
status: row.status ?? "pending",
|
|
@@ -849,15 +916,17 @@ async function sendMessage(input) {
|
|
|
849
916
|
const id = generateUlid();
|
|
850
917
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
851
918
|
const targetDevice = input.targetDevice ?? "local";
|
|
919
|
+
const sessionScope = input.sessionScope === void 0 ? resolveExeSession() : input.sessionScope;
|
|
852
920
|
await client.execute({
|
|
853
|
-
sql: `INSERT INTO messages (id, from_agent, from_device, target_agent, target_project, target_device, content, priority, status, created_at)
|
|
854
|
-
VALUES (?, ?, 'local', ?, ?, ?, ?, ?, 'pending', ?)`,
|
|
921
|
+
sql: `INSERT INTO messages (id, from_agent, from_device, target_agent, target_project, target_device, session_scope, content, priority, status, created_at)
|
|
922
|
+
VALUES (?, ?, 'local', ?, ?, ?, ?, ?, ?, 'pending', ?)`,
|
|
855
923
|
args: [
|
|
856
924
|
id,
|
|
857
925
|
input.fromAgent,
|
|
858
926
|
input.targetAgent,
|
|
859
927
|
input.targetProject ?? null,
|
|
860
928
|
targetDevice,
|
|
929
|
+
sessionScope,
|
|
861
930
|
input.content,
|
|
862
931
|
input.priority ?? "normal",
|
|
863
932
|
now
|
|
@@ -871,9 +940,10 @@ async function sendMessage(input) {
|
|
|
871
940
|
}
|
|
872
941
|
} catch {
|
|
873
942
|
}
|
|
943
|
+
const sentScope = strictSessionScopeFilter(sessionScope);
|
|
874
944
|
const result = await client.execute({
|
|
875
|
-
sql:
|
|
876
|
-
args: [id]
|
|
945
|
+
sql: `SELECT * FROM messages WHERE id = ?${sentScope.sql}`,
|
|
946
|
+
args: [id, ...sentScope.args]
|
|
877
947
|
});
|
|
878
948
|
return rowToMessage(result.rows[0]);
|
|
879
949
|
}
|
|
@@ -895,6 +965,7 @@ async function deliverCrossMachineMessage(messageId, targetDevice) {
|
|
|
895
965
|
fromAgent: msg.fromAgent,
|
|
896
966
|
targetAgent: msg.targetAgent,
|
|
897
967
|
targetProject: msg.targetProject,
|
|
968
|
+
sessionScope: msg.sessionScope,
|
|
898
969
|
content: msg.content,
|
|
899
970
|
priority: msg.priority,
|
|
900
971
|
createdAt: msg.createdAt
|
|
@@ -938,7 +1009,7 @@ async function deliverLocalMessage(messageId) {
|
|
|
938
1009
|
} catch {
|
|
939
1010
|
const newRetryCount = msg.retryCount + 1;
|
|
940
1011
|
if (newRetryCount >= MAX_RETRIES) {
|
|
941
|
-
await markFailed(messageId, "session unavailable after 10 retries");
|
|
1012
|
+
await markFailed(messageId, "session unavailable after 10 retries", msg.sessionScope);
|
|
942
1013
|
} else {
|
|
943
1014
|
await client.execute({
|
|
944
1015
|
sql: "UPDATE messages SET retry_count = ? WHERE id = ?",
|
|
@@ -948,11 +1019,13 @@ async function deliverLocalMessage(messageId) {
|
|
|
948
1019
|
return false;
|
|
949
1020
|
}
|
|
950
1021
|
}
|
|
951
|
-
async function markFailed(messageId, reason) {
|
|
1022
|
+
async function markFailed(messageId, reason, sessionScope) {
|
|
952
1023
|
const client = getClient();
|
|
1024
|
+
const scope = strictSessionScopeFilter(sessionScope);
|
|
953
1025
|
await client.execute({
|
|
954
|
-
sql:
|
|
955
|
-
|
|
1026
|
+
sql: `UPDATE messages SET status = 'failed', failed_at = ?, failure_reason = ?
|
|
1027
|
+
WHERE id = ?${scope.sql}`,
|
|
1028
|
+
args: [(/* @__PURE__ */ new Date()).toISOString(), reason, messageId, ...scope.args]
|
|
956
1029
|
});
|
|
957
1030
|
}
|
|
958
1031
|
|
|
@@ -962,8 +1035,8 @@ init_session_key();
|
|
|
962
1035
|
init_employees();
|
|
963
1036
|
import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, unlinkSync as unlinkSync2, readdirSync as readdirSync2 } from "fs";
|
|
964
1037
|
import { execSync as execSync5 } from "child_process";
|
|
965
|
-
import
|
|
966
|
-
var CACHE_DIR =
|
|
1038
|
+
import path10 from "path";
|
|
1039
|
+
var CACHE_DIR = path10.join(EXE_AI_DIR, "session-cache");
|
|
967
1040
|
var STALE_MS = 24 * 60 * 60 * 1e3;
|
|
968
1041
|
function isNameWithOptionalInstance(candidate, baseName) {
|
|
969
1042
|
if (candidate === baseName) return true;
|
|
@@ -1008,7 +1081,7 @@ function resolveActiveAgentFromTmuxSession(sessionName) {
|
|
|
1008
1081
|
return null;
|
|
1009
1082
|
}
|
|
1010
1083
|
function getMarkerPath() {
|
|
1011
|
-
return
|
|
1084
|
+
return path10.join(CACHE_DIR, `active-agent-${getSessionKey()}.json`);
|
|
1012
1085
|
}
|
|
1013
1086
|
function getActiveAgent() {
|
|
1014
1087
|
try {
|