@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
package/dist/lib/messaging.js
CHANGED
|
@@ -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,21 +840,46 @@ 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/lib/messaging.ts
|
|
815
880
|
init_database();
|
|
816
881
|
init_tmux_routing();
|
|
882
|
+
init_task_scope();
|
|
817
883
|
import crypto from "crypto";
|
|
818
884
|
function generateUlid() {
|
|
819
885
|
const timestamp = Date.now().toString(36).padStart(10, "0");
|
|
@@ -828,6 +894,7 @@ function rowToMessage(row) {
|
|
|
828
894
|
targetAgent: row.target_agent,
|
|
829
895
|
targetProject: row.target_project ?? null,
|
|
830
896
|
targetDevice: row.target_device,
|
|
897
|
+
sessionScope: row.session_scope ?? null,
|
|
831
898
|
content: row.content,
|
|
832
899
|
priority: row.priority ?? "normal",
|
|
833
900
|
status: row.status ?? "pending",
|
|
@@ -846,15 +913,17 @@ async function sendMessage(input) {
|
|
|
846
913
|
const id = generateUlid();
|
|
847
914
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
848
915
|
const targetDevice = input.targetDevice ?? "local";
|
|
916
|
+
const sessionScope = input.sessionScope === void 0 ? resolveExeSession() : input.sessionScope;
|
|
849
917
|
await client.execute({
|
|
850
|
-
sql: `INSERT INTO messages (id, from_agent, from_device, target_agent, target_project, target_device, content, priority, status, created_at)
|
|
851
|
-
VALUES (?, ?, 'local', ?, ?, ?, ?, ?, 'pending', ?)`,
|
|
918
|
+
sql: `INSERT INTO messages (id, from_agent, from_device, target_agent, target_project, target_device, session_scope, content, priority, status, created_at)
|
|
919
|
+
VALUES (?, ?, 'local', ?, ?, ?, ?, ?, ?, 'pending', ?)`,
|
|
852
920
|
args: [
|
|
853
921
|
id,
|
|
854
922
|
input.fromAgent,
|
|
855
923
|
input.targetAgent,
|
|
856
924
|
input.targetProject ?? null,
|
|
857
925
|
targetDevice,
|
|
926
|
+
sessionScope,
|
|
858
927
|
input.content,
|
|
859
928
|
input.priority ?? "normal",
|
|
860
929
|
now
|
|
@@ -868,9 +937,10 @@ async function sendMessage(input) {
|
|
|
868
937
|
}
|
|
869
938
|
} catch {
|
|
870
939
|
}
|
|
940
|
+
const sentScope = strictSessionScopeFilter(sessionScope);
|
|
871
941
|
const result = await client.execute({
|
|
872
|
-
sql:
|
|
873
|
-
args: [id]
|
|
942
|
+
sql: `SELECT * FROM messages WHERE id = ?${sentScope.sql}`,
|
|
943
|
+
args: [id, ...sentScope.args]
|
|
874
944
|
});
|
|
875
945
|
return rowToMessage(result.rows[0]);
|
|
876
946
|
}
|
|
@@ -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,85 +1019,101 @@ async function deliverLocalMessage(messageId) {
|
|
|
948
1019
|
return false;
|
|
949
1020
|
}
|
|
950
1021
|
}
|
|
951
|
-
async function getPendingMessages(targetAgent) {
|
|
1022
|
+
async function getPendingMessages(targetAgent, sessionScope) {
|
|
952
1023
|
const client = getClient();
|
|
1024
|
+
const scope = strictSessionScopeFilter(sessionScope);
|
|
953
1025
|
const result = await client.execute({
|
|
954
1026
|
sql: `SELECT * FROM messages
|
|
955
|
-
WHERE target_agent = ? AND status IN ('pending', 'delivered')
|
|
1027
|
+
WHERE target_agent = ? AND status IN ('pending', 'delivered')${scope.sql}
|
|
956
1028
|
ORDER BY id`,
|
|
957
|
-
args: [targetAgent]
|
|
1029
|
+
args: [targetAgent, ...scope.args]
|
|
958
1030
|
});
|
|
959
1031
|
return result.rows.map((row) => rowToMessage(row));
|
|
960
1032
|
}
|
|
961
|
-
async function markRead(messageId) {
|
|
1033
|
+
async function markRead(messageId, sessionScope) {
|
|
962
1034
|
const client = getClient();
|
|
1035
|
+
const scope = strictSessionScopeFilter(sessionScope);
|
|
963
1036
|
await client.execute({
|
|
964
|
-
sql:
|
|
965
|
-
|
|
1037
|
+
sql: `UPDATE messages SET status = 'read'
|
|
1038
|
+
WHERE id = ? AND status IN ('pending', 'delivered')${scope.sql}`,
|
|
1039
|
+
args: [messageId, ...scope.args]
|
|
966
1040
|
});
|
|
967
1041
|
}
|
|
968
|
-
async function markAcknowledged(messageId) {
|
|
1042
|
+
async function markAcknowledged(messageId, sessionScope) {
|
|
969
1043
|
const client = getClient();
|
|
1044
|
+
const scope = strictSessionScopeFilter(sessionScope);
|
|
970
1045
|
await client.execute({
|
|
971
|
-
sql:
|
|
972
|
-
|
|
1046
|
+
sql: `UPDATE messages SET status = 'acknowledged', processed_at = ?
|
|
1047
|
+
WHERE id = ? AND status = 'read'${scope.sql}`,
|
|
1048
|
+
args: [(/* @__PURE__ */ new Date()).toISOString(), messageId, ...scope.args]
|
|
973
1049
|
});
|
|
974
1050
|
}
|
|
975
|
-
async function markProcessed(messageId) {
|
|
1051
|
+
async function markProcessed(messageId, sessionScope) {
|
|
976
1052
|
const client = getClient();
|
|
1053
|
+
const scope = strictSessionScopeFilter(sessionScope);
|
|
977
1054
|
await client.execute({
|
|
978
|
-
sql:
|
|
979
|
-
|
|
1055
|
+
sql: `UPDATE messages SET status = 'processed', processed_at = ?
|
|
1056
|
+
WHERE id = ?${scope.sql}`,
|
|
1057
|
+
args: [(/* @__PURE__ */ new Date()).toISOString(), messageId, ...scope.args]
|
|
980
1058
|
});
|
|
981
1059
|
}
|
|
982
|
-
async function getMessageStatus(messageId) {
|
|
1060
|
+
async function getMessageStatus(messageId, sessionScope) {
|
|
983
1061
|
const client = getClient();
|
|
1062
|
+
const scope = strictSessionScopeFilter(sessionScope);
|
|
984
1063
|
const result = await client.execute({
|
|
985
|
-
sql:
|
|
986
|
-
args: [messageId]
|
|
1064
|
+
sql: `SELECT status FROM messages WHERE id = ?${scope.sql}`,
|
|
1065
|
+
args: [messageId, ...scope.args]
|
|
987
1066
|
});
|
|
988
1067
|
return result.rows[0]?.status ?? null;
|
|
989
1068
|
}
|
|
990
|
-
async function getUnacknowledgedMessages(targetAgent) {
|
|
1069
|
+
async function getUnacknowledgedMessages(targetAgent, sessionScope) {
|
|
991
1070
|
const client = getClient();
|
|
1071
|
+
const scope = strictSessionScopeFilter(sessionScope);
|
|
992
1072
|
const result = await client.execute({
|
|
993
1073
|
sql: `SELECT * FROM messages
|
|
994
|
-
WHERE target_agent = ? AND status IN ('pending', 'delivered', 'read')
|
|
1074
|
+
WHERE target_agent = ? AND status IN ('pending', 'delivered', 'read')${scope.sql}
|
|
995
1075
|
ORDER BY id`,
|
|
996
|
-
args: [targetAgent]
|
|
1076
|
+
args: [targetAgent, ...scope.args]
|
|
997
1077
|
});
|
|
998
1078
|
return result.rows.map((row) => rowToMessage(row));
|
|
999
1079
|
}
|
|
1000
|
-
async function getReadMessages(targetAgent) {
|
|
1080
|
+
async function getReadMessages(targetAgent, sessionScope) {
|
|
1001
1081
|
const client = getClient();
|
|
1082
|
+
const scope = strictSessionScopeFilter(sessionScope);
|
|
1002
1083
|
const result = await client.execute({
|
|
1003
|
-
sql:
|
|
1004
|
-
|
|
1084
|
+
sql: `SELECT * FROM messages
|
|
1085
|
+
WHERE target_agent = ? AND status = 'read'${scope.sql}
|
|
1086
|
+
ORDER BY id`,
|
|
1087
|
+
args: [targetAgent, ...scope.args]
|
|
1005
1088
|
});
|
|
1006
1089
|
return result.rows.map((row) => rowToMessage(row));
|
|
1007
1090
|
}
|
|
1008
|
-
async function markFailed(messageId, reason) {
|
|
1091
|
+
async function markFailed(messageId, reason, sessionScope) {
|
|
1009
1092
|
const client = getClient();
|
|
1093
|
+
const scope = strictSessionScopeFilter(sessionScope);
|
|
1010
1094
|
await client.execute({
|
|
1011
|
-
sql:
|
|
1012
|
-
|
|
1095
|
+
sql: `UPDATE messages SET status = 'failed', failed_at = ?, failure_reason = ?
|
|
1096
|
+
WHERE id = ?${scope.sql}`,
|
|
1097
|
+
args: [(/* @__PURE__ */ new Date()).toISOString(), reason, messageId, ...scope.args]
|
|
1013
1098
|
});
|
|
1014
1099
|
}
|
|
1015
|
-
async function getFailedMessages() {
|
|
1100
|
+
async function getFailedMessages(sessionScope) {
|
|
1016
1101
|
const client = getClient();
|
|
1102
|
+
const scope = strictSessionScopeFilter(sessionScope);
|
|
1017
1103
|
const result = await client.execute({
|
|
1018
|
-
sql:
|
|
1019
|
-
args: []
|
|
1104
|
+
sql: `SELECT * FROM messages WHERE status = 'failed'${scope.sql} ORDER BY created_at DESC`,
|
|
1105
|
+
args: [...scope.args]
|
|
1020
1106
|
});
|
|
1021
1107
|
return result.rows.map((row) => rowToMessage(row));
|
|
1022
1108
|
}
|
|
1023
|
-
async function retryPendingMessages() {
|
|
1109
|
+
async function retryPendingMessages(sessionScope) {
|
|
1024
1110
|
const client = getClient();
|
|
1111
|
+
const scope = strictSessionScopeFilter(sessionScope);
|
|
1025
1112
|
const result = await client.execute({
|
|
1026
1113
|
sql: `SELECT * FROM messages
|
|
1027
|
-
WHERE status = 'pending' AND retry_count <
|
|
1114
|
+
WHERE status = 'pending' AND retry_count < ?${scope.sql}
|
|
1028
1115
|
ORDER BY id`,
|
|
1029
|
-
args: [MAX_RETRIES]
|
|
1116
|
+
args: [MAX_RETRIES, ...scope.args]
|
|
1030
1117
|
});
|
|
1031
1118
|
let delivered = 0;
|
|
1032
1119
|
for (const row of result.rows) {
|
package/dist/lib/reminders.js
CHANGED
|
@@ -3,9 +3,18 @@ var __esm = (fn, res) => function __init() {
|
|
|
3
3
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
4
4
|
};
|
|
5
5
|
|
|
6
|
+
// src/lib/secure-files.ts
|
|
7
|
+
import { chmodSync, existsSync, mkdirSync } from "fs";
|
|
8
|
+
import { chmod, mkdir } from "fs/promises";
|
|
9
|
+
var init_secure_files = __esm({
|
|
10
|
+
"src/lib/secure-files.ts"() {
|
|
11
|
+
"use strict";
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
|
|
6
15
|
// src/lib/config.ts
|
|
7
|
-
import { readFile, writeFile
|
|
8
|
-
import { readFileSync, existsSync, renameSync } from "fs";
|
|
16
|
+
import { readFile, writeFile } from "fs/promises";
|
|
17
|
+
import { readFileSync, existsSync as existsSync2, renameSync } from "fs";
|
|
9
18
|
import path from "path";
|
|
10
19
|
import os from "os";
|
|
11
20
|
function resolveDataDir() {
|
|
@@ -13,7 +22,7 @@ function resolveDataDir() {
|
|
|
13
22
|
if (process.env.EXE_MEM_DIR) return process.env.EXE_MEM_DIR;
|
|
14
23
|
const newDir = path.join(os.homedir(), ".exe-os");
|
|
15
24
|
const legacyDir = path.join(os.homedir(), ".exe-mem");
|
|
16
|
-
if (!
|
|
25
|
+
if (!existsSync2(newDir) && existsSync2(legacyDir)) {
|
|
17
26
|
try {
|
|
18
27
|
renameSync(legacyDir, newDir);
|
|
19
28
|
process.stderr.write(`[exe-os] Migrated data directory: ~/.exe-mem \u2192 ~/.exe-os
|
|
@@ -28,6 +37,7 @@ var EXE_AI_DIR, DB_PATH, MODELS_DIR, CONFIG_PATH, LEGACY_LANCE_PATH, CURRENT_CON
|
|
|
28
37
|
var init_config = __esm({
|
|
29
38
|
"src/lib/config.ts"() {
|
|
30
39
|
"use strict";
|
|
40
|
+
init_secure_files();
|
|
31
41
|
EXE_AI_DIR = resolveDataDir();
|
|
32
42
|
DB_PATH = path.join(EXE_AI_DIR, "memories.db");
|
|
33
43
|
MODELS_DIR = path.join(EXE_AI_DIR, "models");
|
|
@@ -103,19 +113,39 @@ import { createClient } from "@libsql/client";
|
|
|
103
113
|
// src/lib/employees.ts
|
|
104
114
|
init_config();
|
|
105
115
|
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
106
|
-
import { existsSync as
|
|
116
|
+
import { existsSync as existsSync3, symlinkSync, readlinkSync, readFileSync as readFileSync2, renameSync as renameSync2, unlinkSync, writeFileSync } from "fs";
|
|
107
117
|
import { execSync } from "child_process";
|
|
108
118
|
import path2 from "path";
|
|
109
119
|
import os2 from "os";
|
|
110
120
|
var EMPLOYEES_PATH = path2.join(EXE_AI_DIR, "exe-employees.json");
|
|
121
|
+
var IDENTITY_DIR = path2.join(EXE_AI_DIR, "identity");
|
|
122
|
+
|
|
123
|
+
// src/lib/database-adapter.ts
|
|
124
|
+
import os3 from "os";
|
|
125
|
+
import path3 from "path";
|
|
126
|
+
import { createRequire } from "module";
|
|
127
|
+
import { pathToFileURL } from "url";
|
|
128
|
+
var BOOLEAN_COLUMNS_BY_TABLE = {
|
|
129
|
+
memories: /* @__PURE__ */ new Set(["has_error", "draft"]),
|
|
130
|
+
behaviors: /* @__PURE__ */ new Set(["active"]),
|
|
131
|
+
notifications: /* @__PURE__ */ new Set(["read"]),
|
|
132
|
+
users: /* @__PURE__ */ new Set(["has_personal_memory"])
|
|
133
|
+
};
|
|
134
|
+
var BOOLEAN_COLUMN_NAMES = new Set(
|
|
135
|
+
Object.values(BOOLEAN_COLUMNS_BY_TABLE).flatMap((cols) => [...cols])
|
|
136
|
+
);
|
|
111
137
|
|
|
112
138
|
// src/lib/database.ts
|
|
113
139
|
var _resilientClient = null;
|
|
114
140
|
var _daemonClient = null;
|
|
141
|
+
var _adapterClient = null;
|
|
115
142
|
function getClient() {
|
|
116
|
-
if (!
|
|
143
|
+
if (!_adapterClient) {
|
|
117
144
|
throw new Error("Database client not initialized. Call initDatabase() first.");
|
|
118
145
|
}
|
|
146
|
+
if (process.env.DATABASE_URL) {
|
|
147
|
+
return _adapterClient;
|
|
148
|
+
}
|
|
119
149
|
if (process.env.EXE_IS_DAEMON === "1") {
|
|
120
150
|
return _resilientClient;
|
|
121
151
|
}
|