@askexenow/exe-os 0.9.7 → 0.9.8
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 +754 -79
- package/dist/bin/backfill-responses.js +752 -77
- package/dist/bin/backfill-vectors.js +752 -77
- package/dist/bin/cleanup-stale-review-tasks.js +657 -35
- package/dist/bin/cli.js +1388 -605
- package/dist/bin/exe-agent-config.js +123 -95
- package/dist/bin/exe-agent.js +41 -25
- package/dist/bin/exe-assign.js +732 -57
- package/dist/bin/exe-boot.js +784 -153
- package/dist/bin/exe-call.js +209 -138
- package/dist/bin/exe-cloud.js +35 -12
- package/dist/bin/exe-dispatch.js +692 -70
- package/dist/bin/exe-doctor.js +648 -26
- package/dist/bin/exe-export-behaviors.js +650 -20
- package/dist/bin/exe-forget.js +635 -13
- package/dist/bin/exe-gateway.js +1053 -271
- package/dist/bin/exe-heartbeat.js +665 -43
- package/dist/bin/exe-kill.js +646 -16
- package/dist/bin/exe-launch-agent.js +887 -97
- package/dist/bin/exe-link.js +658 -43
- package/dist/bin/exe-new-employee.js +378 -177
- package/dist/bin/exe-pending-messages.js +656 -34
- package/dist/bin/exe-pending-notifications.js +635 -13
- package/dist/bin/exe-pending-reviews.js +659 -37
- package/dist/bin/exe-rename.js +645 -30
- package/dist/bin/exe-review.js +635 -13
- package/dist/bin/exe-search.js +771 -88
- package/dist/bin/exe-session-cleanup.js +834 -150
- package/dist/bin/exe-settings.js +127 -91
- package/dist/bin/exe-start-codex.js +729 -94
- package/dist/bin/exe-start-opencode.js +717 -82
- package/dist/bin/exe-status.js +657 -35
- package/dist/bin/exe-team.js +635 -13
- package/dist/bin/git-sweep.js +720 -89
- package/dist/bin/graph-backfill.js +643 -13
- package/dist/bin/graph-export.js +646 -16
- package/dist/bin/install.js +596 -193
- package/dist/bin/scan-tasks.js +724 -93
- package/dist/bin/setup.js +1038 -210
- package/dist/bin/shard-migrate.js +645 -15
- package/dist/bin/wiki-sync.js +646 -16
- package/dist/gateway/index.js +1027 -245
- package/dist/hooks/bug-report-worker.js +891 -170
- package/dist/hooks/commit-complete.js +718 -87
- package/dist/hooks/error-recall.js +776 -93
- package/dist/hooks/exe-heartbeat-hook.js +85 -71
- package/dist/hooks/ingest-worker.js +840 -156
- package/dist/hooks/ingest.js +90 -73
- package/dist/hooks/instructions-loaded.js +669 -38
- package/dist/hooks/notification.js +661 -30
- package/dist/hooks/post-compact.js +674 -43
- package/dist/hooks/pre-compact.js +718 -87
- package/dist/hooks/pre-tool-use.js +872 -125
- package/dist/hooks/prompt-ingest-worker.js +758 -83
- package/dist/hooks/prompt-submit.js +1060 -319
- package/dist/hooks/response-ingest-worker.js +758 -83
- package/dist/hooks/session-end.js +721 -90
- package/dist/hooks/session-start.js +1031 -207
- package/dist/hooks/stop.js +680 -49
- package/dist/hooks/subagent-stop.js +674 -43
- package/dist/hooks/summary-worker.js +816 -132
- package/dist/index.js +1015 -232
- package/dist/lib/cloud-sync.js +663 -48
- package/dist/lib/consolidation.js +26 -3
- package/dist/lib/database.js +626 -18
- package/dist/lib/db.js +2261 -0
- package/dist/lib/device-registry.js +640 -25
- package/dist/lib/embedder.js +96 -43
- package/dist/lib/employee-templates.js +16 -0
- package/dist/lib/employees.js +259 -83
- package/dist/lib/exe-daemon-client.js +101 -63
- package/dist/lib/exe-daemon.js +894 -162
- package/dist/lib/hybrid-search.js +771 -88
- package/dist/lib/identity.js +27 -7
- package/dist/lib/messaging.js +55 -28
- package/dist/lib/reminders.js +21 -1
- package/dist/lib/schedules.js +636 -14
- package/dist/lib/skill-learning.js +21 -1
- package/dist/lib/store.js +643 -13
- package/dist/lib/task-router.js +82 -71
- package/dist/lib/tasks.js +98 -71
- package/dist/lib/tmux-routing.js +87 -60
- package/dist/lib/token-spend.js +26 -6
- package/dist/mcp/server.js +1784 -458
- package/dist/mcp/tools/complete-reminder.js +21 -1
- package/dist/mcp/tools/create-reminder.js +21 -1
- package/dist/mcp/tools/create-task.js +290 -164
- package/dist/mcp/tools/deactivate-behavior.js +24 -4
- package/dist/mcp/tools/list-reminders.js +21 -1
- package/dist/mcp/tools/list-tasks.js +195 -38
- package/dist/mcp/tools/send-message.js +58 -31
- package/dist/mcp/tools/update-task.js +75 -48
- package/dist/runtime/index.js +720 -89
- package/dist/tui/App.js +853 -123
- package/package.json +3 -2
|
@@ -143,14 +143,34 @@ function loadEmployeesSync(employeesPath = EMPLOYEES_PATH) {
|
|
|
143
143
|
function getEmployee(employees, name) {
|
|
144
144
|
return employees.find((e) => e.name.toLowerCase() === name.toLowerCase());
|
|
145
145
|
}
|
|
146
|
+
var IDENTITY_DIR = path2.join(EXE_AI_DIR, "identity");
|
|
147
|
+
|
|
148
|
+
// src/lib/database-adapter.ts
|
|
149
|
+
import os3 from "os";
|
|
150
|
+
import path3 from "path";
|
|
151
|
+
import { createRequire } from "module";
|
|
152
|
+
import { pathToFileURL } from "url";
|
|
153
|
+
var BOOLEAN_COLUMNS_BY_TABLE = {
|
|
154
|
+
memories: /* @__PURE__ */ new Set(["has_error", "draft"]),
|
|
155
|
+
behaviors: /* @__PURE__ */ new Set(["active"]),
|
|
156
|
+
notifications: /* @__PURE__ */ new Set(["read"]),
|
|
157
|
+
users: /* @__PURE__ */ new Set(["has_personal_memory"])
|
|
158
|
+
};
|
|
159
|
+
var BOOLEAN_COLUMN_NAMES = new Set(
|
|
160
|
+
Object.values(BOOLEAN_COLUMNS_BY_TABLE).flatMap((cols) => [...cols])
|
|
161
|
+
);
|
|
146
162
|
|
|
147
163
|
// src/lib/database.ts
|
|
148
164
|
var _resilientClient = null;
|
|
149
165
|
var _daemonClient = null;
|
|
166
|
+
var _adapterClient = null;
|
|
150
167
|
function getClient() {
|
|
151
|
-
if (!
|
|
168
|
+
if (!_adapterClient) {
|
|
152
169
|
throw new Error("Database client not initialized. Call initDatabase() first.");
|
|
153
170
|
}
|
|
171
|
+
if (process.env.DATABASE_URL) {
|
|
172
|
+
return _adapterClient;
|
|
173
|
+
}
|
|
154
174
|
if (process.env.EXE_IS_DAEMON === "1") {
|
|
155
175
|
return _resilientClient;
|
|
156
176
|
}
|
|
@@ -174,7 +194,7 @@ async function deactivateBehavior(id) {
|
|
|
174
194
|
init_config();
|
|
175
195
|
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync, unlinkSync as unlinkSync2, readdirSync } from "fs";
|
|
176
196
|
import { execSync as execSync3 } from "child_process";
|
|
177
|
-
import
|
|
197
|
+
import path4 from "path";
|
|
178
198
|
|
|
179
199
|
// src/lib/session-key.ts
|
|
180
200
|
import { execSync as execSync2 } from "child_process";
|
|
@@ -239,7 +259,7 @@ function getSessionKey() {
|
|
|
239
259
|
}
|
|
240
260
|
|
|
241
261
|
// src/lib/active-agent.ts
|
|
242
|
-
var CACHE_DIR =
|
|
262
|
+
var CACHE_DIR = path4.join(EXE_AI_DIR, "session-cache");
|
|
243
263
|
var STALE_MS = 24 * 60 * 60 * 1e3;
|
|
244
264
|
function isNameWithOptionalInstance(candidate, baseName) {
|
|
245
265
|
if (candidate === baseName) return true;
|
|
@@ -284,7 +304,7 @@ function resolveActiveAgentFromTmuxSession(sessionName) {
|
|
|
284
304
|
return null;
|
|
285
305
|
}
|
|
286
306
|
function getMarkerPath() {
|
|
287
|
-
return
|
|
307
|
+
return path4.join(CACHE_DIR, `active-agent-${getSessionKey()}.json`);
|
|
288
308
|
}
|
|
289
309
|
function getActiveAgent() {
|
|
290
310
|
try {
|
|
@@ -111,14 +111,34 @@ import { execSync } from "child_process";
|
|
|
111
111
|
import path2 from "path";
|
|
112
112
|
import os2 from "os";
|
|
113
113
|
var EMPLOYEES_PATH = path2.join(EXE_AI_DIR, "exe-employees.json");
|
|
114
|
+
var IDENTITY_DIR = path2.join(EXE_AI_DIR, "identity");
|
|
115
|
+
|
|
116
|
+
// src/lib/database-adapter.ts
|
|
117
|
+
import os3 from "os";
|
|
118
|
+
import path3 from "path";
|
|
119
|
+
import { createRequire } from "module";
|
|
120
|
+
import { pathToFileURL } from "url";
|
|
121
|
+
var BOOLEAN_COLUMNS_BY_TABLE = {
|
|
122
|
+
memories: /* @__PURE__ */ new Set(["has_error", "draft"]),
|
|
123
|
+
behaviors: /* @__PURE__ */ new Set(["active"]),
|
|
124
|
+
notifications: /* @__PURE__ */ new Set(["read"]),
|
|
125
|
+
users: /* @__PURE__ */ new Set(["has_personal_memory"])
|
|
126
|
+
};
|
|
127
|
+
var BOOLEAN_COLUMN_NAMES = new Set(
|
|
128
|
+
Object.values(BOOLEAN_COLUMNS_BY_TABLE).flatMap((cols) => [...cols])
|
|
129
|
+
);
|
|
114
130
|
|
|
115
131
|
// src/lib/database.ts
|
|
116
132
|
var _resilientClient = null;
|
|
117
133
|
var _daemonClient = null;
|
|
134
|
+
var _adapterClient = null;
|
|
118
135
|
function getClient() {
|
|
119
|
-
if (!
|
|
136
|
+
if (!_adapterClient) {
|
|
120
137
|
throw new Error("Database client not initialized. Call initDatabase() first.");
|
|
121
138
|
}
|
|
139
|
+
if (process.env.DATABASE_URL) {
|
|
140
|
+
return _adapterClient;
|
|
141
|
+
}
|
|
122
142
|
if (process.env.EXE_IS_DAEMON === "1") {
|
|
123
143
|
return _resilientClient;
|
|
124
144
|
}
|
|
@@ -123,21 +123,68 @@ import { existsSync as existsSync2, symlinkSync, readlinkSync, readFileSync as r
|
|
|
123
123
|
import { execSync } from "child_process";
|
|
124
124
|
import path2 from "path";
|
|
125
125
|
import os2 from "os";
|
|
126
|
-
|
|
126
|
+
function normalizeRole(role) {
|
|
127
|
+
return (role ?? "").trim().toLowerCase();
|
|
128
|
+
}
|
|
129
|
+
function isCoordinatorRole(role) {
|
|
130
|
+
return normalizeRole(role) === normalizeRole(COORDINATOR_ROLE);
|
|
131
|
+
}
|
|
132
|
+
function getCoordinatorEmployee(employees) {
|
|
133
|
+
return employees.find((e) => isCoordinatorRole(e.role));
|
|
134
|
+
}
|
|
135
|
+
function loadEmployeesSync(employeesPath = EMPLOYEES_PATH) {
|
|
136
|
+
if (!existsSync2(employeesPath)) return [];
|
|
137
|
+
try {
|
|
138
|
+
return JSON.parse(readFileSync2(employeesPath, "utf-8"));
|
|
139
|
+
} catch {
|
|
140
|
+
return [];
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
function getEmployee(employees, name) {
|
|
144
|
+
return employees.find((e) => e.name.toLowerCase() === name.toLowerCase());
|
|
145
|
+
}
|
|
146
|
+
var EMPLOYEES_PATH, DEFAULT_COORDINATOR_TEMPLATE_NAME, COORDINATOR_ROLE, IDENTITY_DIR;
|
|
127
147
|
var init_employees = __esm({
|
|
128
148
|
"src/lib/employees.ts"() {
|
|
129
149
|
"use strict";
|
|
130
150
|
init_config();
|
|
131
151
|
EMPLOYEES_PATH = path2.join(EXE_AI_DIR, "exe-employees.json");
|
|
152
|
+
DEFAULT_COORDINATOR_TEMPLATE_NAME = "exe";
|
|
153
|
+
COORDINATOR_ROLE = "COO";
|
|
154
|
+
IDENTITY_DIR = path2.join(EXE_AI_DIR, "identity");
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// src/lib/database-adapter.ts
|
|
159
|
+
import os3 from "os";
|
|
160
|
+
import path3 from "path";
|
|
161
|
+
import { createRequire } from "module";
|
|
162
|
+
import { pathToFileURL } from "url";
|
|
163
|
+
var BOOLEAN_COLUMNS_BY_TABLE, BOOLEAN_COLUMN_NAMES;
|
|
164
|
+
var init_database_adapter = __esm({
|
|
165
|
+
"src/lib/database-adapter.ts"() {
|
|
166
|
+
"use strict";
|
|
167
|
+
BOOLEAN_COLUMNS_BY_TABLE = {
|
|
168
|
+
memories: /* @__PURE__ */ new Set(["has_error", "draft"]),
|
|
169
|
+
behaviors: /* @__PURE__ */ new Set(["active"]),
|
|
170
|
+
notifications: /* @__PURE__ */ new Set(["read"]),
|
|
171
|
+
users: /* @__PURE__ */ new Set(["has_personal_memory"])
|
|
172
|
+
};
|
|
173
|
+
BOOLEAN_COLUMN_NAMES = new Set(
|
|
174
|
+
Object.values(BOOLEAN_COLUMNS_BY_TABLE).flatMap((cols) => [...cols])
|
|
175
|
+
);
|
|
132
176
|
}
|
|
133
177
|
});
|
|
134
178
|
|
|
135
179
|
// src/lib/database.ts
|
|
136
180
|
import { createClient } from "@libsql/client";
|
|
137
181
|
function getClient() {
|
|
138
|
-
if (!
|
|
182
|
+
if (!_adapterClient) {
|
|
139
183
|
throw new Error("Database client not initialized. Call initDatabase() first.");
|
|
140
184
|
}
|
|
185
|
+
if (process.env.DATABASE_URL) {
|
|
186
|
+
return _adapterClient;
|
|
187
|
+
}
|
|
141
188
|
if (process.env.EXE_IS_DAEMON === "1") {
|
|
142
189
|
return _resilientClient;
|
|
143
190
|
}
|
|
@@ -146,21 +193,23 @@ function getClient() {
|
|
|
146
193
|
}
|
|
147
194
|
return _resilientClient;
|
|
148
195
|
}
|
|
149
|
-
var _resilientClient, _daemonClient;
|
|
196
|
+
var _resilientClient, _daemonClient, _adapterClient;
|
|
150
197
|
var init_database = __esm({
|
|
151
198
|
"src/lib/database.ts"() {
|
|
152
199
|
"use strict";
|
|
153
200
|
init_db_retry();
|
|
154
201
|
init_employees();
|
|
202
|
+
init_database_adapter();
|
|
155
203
|
_resilientClient = null;
|
|
156
204
|
_daemonClient = null;
|
|
205
|
+
_adapterClient = null;
|
|
157
206
|
}
|
|
158
207
|
});
|
|
159
208
|
|
|
160
209
|
// src/lib/notifications.ts
|
|
161
210
|
import crypto from "crypto";
|
|
162
|
-
import
|
|
163
|
-
import
|
|
211
|
+
import path4 from "path";
|
|
212
|
+
import os4 from "os";
|
|
164
213
|
import {
|
|
165
214
|
readFileSync as readFileSync3,
|
|
166
215
|
readdirSync,
|
|
@@ -231,13 +280,13 @@ var init_state_bus = __esm({
|
|
|
231
280
|
});
|
|
232
281
|
|
|
233
282
|
// src/lib/session-registry.ts
|
|
234
|
-
import
|
|
235
|
-
import
|
|
283
|
+
import path5 from "path";
|
|
284
|
+
import os5 from "os";
|
|
236
285
|
var REGISTRY_PATH;
|
|
237
286
|
var init_session_registry = __esm({
|
|
238
287
|
"src/lib/session-registry.ts"() {
|
|
239
288
|
"use strict";
|
|
240
|
-
REGISTRY_PATH =
|
|
289
|
+
REGISTRY_PATH = path5.join(os5.homedir(), ".exe-os", "session-registry.json");
|
|
241
290
|
}
|
|
242
291
|
});
|
|
243
292
|
|
|
@@ -473,14 +522,14 @@ var init_runtime_table = __esm({
|
|
|
473
522
|
|
|
474
523
|
// src/lib/agent-config.ts
|
|
475
524
|
import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, existsSync as existsSync4, mkdirSync } from "fs";
|
|
476
|
-
import
|
|
525
|
+
import path6 from "path";
|
|
477
526
|
var AGENT_CONFIG_PATH, DEFAULT_MODELS;
|
|
478
527
|
var init_agent_config = __esm({
|
|
479
528
|
"src/lib/agent-config.ts"() {
|
|
480
529
|
"use strict";
|
|
481
530
|
init_config();
|
|
482
531
|
init_runtime_table();
|
|
483
|
-
AGENT_CONFIG_PATH =
|
|
532
|
+
AGENT_CONFIG_PATH = path6.join(EXE_AI_DIR, "agent-config.json");
|
|
484
533
|
DEFAULT_MODELS = {
|
|
485
534
|
claude: "claude-opus-4",
|
|
486
535
|
codex: RUNTIME_TABLE.codex?.defaultModel ?? "gpt-5.4",
|
|
@@ -491,37 +540,37 @@ var init_agent_config = __esm({
|
|
|
491
540
|
|
|
492
541
|
// src/lib/intercom-queue.ts
|
|
493
542
|
import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, renameSync as renameSync3, existsSync as existsSync5, mkdirSync as mkdirSync2 } from "fs";
|
|
494
|
-
import
|
|
495
|
-
import
|
|
543
|
+
import path7 from "path";
|
|
544
|
+
import os6 from "os";
|
|
496
545
|
var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
|
|
497
546
|
var init_intercom_queue = __esm({
|
|
498
547
|
"src/lib/intercom-queue.ts"() {
|
|
499
548
|
"use strict";
|
|
500
|
-
QUEUE_PATH =
|
|
549
|
+
QUEUE_PATH = path7.join(os6.homedir(), ".exe-os", "intercom-queue.json");
|
|
501
550
|
TTL_MS = 60 * 60 * 1e3;
|
|
502
|
-
INTERCOM_LOG =
|
|
551
|
+
INTERCOM_LOG = path7.join(os6.homedir(), ".exe-os", "intercom.log");
|
|
503
552
|
}
|
|
504
553
|
});
|
|
505
554
|
|
|
506
555
|
// src/lib/license.ts
|
|
507
556
|
import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, existsSync as existsSync6, mkdirSync as mkdirSync3 } from "fs";
|
|
508
557
|
import { randomUUID } from "crypto";
|
|
509
|
-
import
|
|
558
|
+
import path8 from "path";
|
|
510
559
|
import { jwtVerify, importSPKI } from "jose";
|
|
511
560
|
var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH;
|
|
512
561
|
var init_license = __esm({
|
|
513
562
|
"src/lib/license.ts"() {
|
|
514
563
|
"use strict";
|
|
515
564
|
init_config();
|
|
516
|
-
LICENSE_PATH =
|
|
517
|
-
CACHE_PATH =
|
|
518
|
-
DEVICE_ID_PATH =
|
|
565
|
+
LICENSE_PATH = path8.join(EXE_AI_DIR, "license.key");
|
|
566
|
+
CACHE_PATH = path8.join(EXE_AI_DIR, "license-cache.json");
|
|
567
|
+
DEVICE_ID_PATH = path8.join(EXE_AI_DIR, "device-id");
|
|
519
568
|
}
|
|
520
569
|
});
|
|
521
570
|
|
|
522
571
|
// src/lib/plan-limits.ts
|
|
523
572
|
import { readFileSync as readFileSync7, existsSync as existsSync7 } from "fs";
|
|
524
|
-
import
|
|
573
|
+
import path9 from "path";
|
|
525
574
|
var CACHE_PATH2;
|
|
526
575
|
var init_plan_limits = __esm({
|
|
527
576
|
"src/lib/plan-limits.ts"() {
|
|
@@ -530,14 +579,14 @@ var init_plan_limits = __esm({
|
|
|
530
579
|
init_employees();
|
|
531
580
|
init_license();
|
|
532
581
|
init_config();
|
|
533
|
-
CACHE_PATH2 =
|
|
582
|
+
CACHE_PATH2 = path9.join(EXE_AI_DIR, "license-cache.json");
|
|
534
583
|
}
|
|
535
584
|
});
|
|
536
585
|
|
|
537
586
|
// src/lib/tmux-routing.ts
|
|
538
587
|
import { readFileSync as readFileSync8, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, existsSync as existsSync8, appendFileSync, readdirSync as readdirSync2 } from "fs";
|
|
539
|
-
import
|
|
540
|
-
import
|
|
588
|
+
import path10 from "path";
|
|
589
|
+
import os7 from "os";
|
|
541
590
|
import { fileURLToPath } from "url";
|
|
542
591
|
function getMySession() {
|
|
543
592
|
return getTransport().getMySession();
|
|
@@ -550,7 +599,7 @@ function extractRootExe(name) {
|
|
|
550
599
|
}
|
|
551
600
|
function getParentExe(sessionKey) {
|
|
552
601
|
try {
|
|
553
|
-
const data = JSON.parse(readFileSync8(
|
|
602
|
+
const data = JSON.parse(readFileSync8(path10.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
|
|
554
603
|
return data.parentExe || null;
|
|
555
604
|
} catch {
|
|
556
605
|
return null;
|
|
@@ -593,10 +642,10 @@ var init_tmux_routing = __esm({
|
|
|
593
642
|
init_intercom_queue();
|
|
594
643
|
init_plan_limits();
|
|
595
644
|
init_employees();
|
|
596
|
-
SPAWN_LOCK_DIR =
|
|
597
|
-
SESSION_CACHE =
|
|
598
|
-
INTERCOM_LOG2 =
|
|
599
|
-
DEBOUNCE_FILE =
|
|
645
|
+
SPAWN_LOCK_DIR = path10.join(os7.homedir(), ".exe-os", "spawn-locks");
|
|
646
|
+
SESSION_CACHE = path10.join(os7.homedir(), ".exe-os", "session-cache");
|
|
647
|
+
INTERCOM_LOG2 = path10.join(os7.homedir(), ".exe-os", "intercom.log");
|
|
648
|
+
DEBOUNCE_FILE = path10.join(SESSION_CACHE, "intercom-debounce.json");
|
|
600
649
|
DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
|
|
601
650
|
}
|
|
602
651
|
});
|
|
@@ -627,8 +676,8 @@ var init_task_scope = __esm({
|
|
|
627
676
|
|
|
628
677
|
// src/lib/tasks-crud.ts
|
|
629
678
|
import crypto2 from "crypto";
|
|
630
|
-
import
|
|
631
|
-
import
|
|
679
|
+
import path11 from "path";
|
|
680
|
+
import os8 from "os";
|
|
632
681
|
import { execSync as execSync4 } from "child_process";
|
|
633
682
|
import { mkdir as mkdir3, writeFile as writeFile3, appendFile } from "fs/promises";
|
|
634
683
|
import { existsSync as existsSync9, readFileSync as readFileSync9 } from "fs";
|
|
@@ -713,7 +762,7 @@ var init_tasks_crud = __esm({
|
|
|
713
762
|
});
|
|
714
763
|
|
|
715
764
|
// src/lib/tasks-review.ts
|
|
716
|
-
import
|
|
765
|
+
import path12 from "path";
|
|
717
766
|
import { existsSync as existsSync10, readdirSync as readdirSync3, unlinkSync as unlinkSync3 } from "fs";
|
|
718
767
|
var init_tasks_review = __esm({
|
|
719
768
|
"src/lib/tasks-review.ts"() {
|
|
@@ -729,7 +778,7 @@ var init_tasks_review = __esm({
|
|
|
729
778
|
});
|
|
730
779
|
|
|
731
780
|
// src/lib/tasks-chain.ts
|
|
732
|
-
import
|
|
781
|
+
import path13 from "path";
|
|
733
782
|
import { readFile as readFile3, writeFile as writeFile4 } from "fs/promises";
|
|
734
783
|
var init_tasks_chain = __esm({
|
|
735
784
|
"src/lib/tasks-chain.ts"() {
|
|
@@ -753,7 +802,7 @@ var init_tasks_notify = __esm({
|
|
|
753
802
|
});
|
|
754
803
|
|
|
755
804
|
// src/lib/tasks.ts
|
|
756
|
-
import
|
|
805
|
+
import path14 from "path";
|
|
757
806
|
import { writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, unlinkSync as unlinkSync4 } from "fs";
|
|
758
807
|
var init_tasks = __esm({
|
|
759
808
|
"src/lib/tasks.ts"() {
|
|
@@ -774,7 +823,7 @@ var init_tasks = __esm({
|
|
|
774
823
|
|
|
775
824
|
// src/lib/project-name.ts
|
|
776
825
|
import { execSync as execSync5 } from "child_process";
|
|
777
|
-
import
|
|
826
|
+
import path15 from "path";
|
|
778
827
|
function getProjectName(cwd) {
|
|
779
828
|
const dir = cwd ?? process.cwd();
|
|
780
829
|
if (_cached2 && _cachedCwd === dir) return _cached2;
|
|
@@ -787,7 +836,7 @@ function getProjectName(cwd) {
|
|
|
787
836
|
timeout: 2e3,
|
|
788
837
|
stdio: ["pipe", "pipe", "pipe"]
|
|
789
838
|
}).trim();
|
|
790
|
-
repoRoot =
|
|
839
|
+
repoRoot = path15.dirname(gitCommonDir);
|
|
791
840
|
} catch {
|
|
792
841
|
repoRoot = execSync5("git rev-parse --show-toplevel", {
|
|
793
842
|
cwd: dir,
|
|
@@ -796,11 +845,11 @@ function getProjectName(cwd) {
|
|
|
796
845
|
stdio: ["pipe", "pipe", "pipe"]
|
|
797
846
|
}).trim();
|
|
798
847
|
}
|
|
799
|
-
_cached2 =
|
|
848
|
+
_cached2 = path15.basename(repoRoot);
|
|
800
849
|
_cachedCwd = dir;
|
|
801
850
|
return _cached2;
|
|
802
851
|
} catch {
|
|
803
|
-
_cached2 =
|
|
852
|
+
_cached2 = path15.basename(dir);
|
|
804
853
|
_cachedCwd = dir;
|
|
805
854
|
return _cached2;
|
|
806
855
|
}
|
|
@@ -818,12 +867,111 @@ var init_project_name = __esm({
|
|
|
818
867
|
init_tasks();
|
|
819
868
|
init_project_name();
|
|
820
869
|
import { z } from "zod";
|
|
870
|
+
|
|
871
|
+
// src/lib/active-agent.ts
|
|
872
|
+
init_config();
|
|
873
|
+
init_session_key();
|
|
874
|
+
init_employees();
|
|
875
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync7, mkdirSync as mkdirSync6, unlinkSync as unlinkSync5, readdirSync as readdirSync4 } from "fs";
|
|
876
|
+
import { execSync as execSync6 } from "child_process";
|
|
877
|
+
import path16 from "path";
|
|
878
|
+
var CACHE_DIR = path16.join(EXE_AI_DIR, "session-cache");
|
|
879
|
+
var STALE_MS = 24 * 60 * 60 * 1e3;
|
|
880
|
+
function isNameWithOptionalInstance(candidate, baseName) {
|
|
881
|
+
if (candidate === baseName) return true;
|
|
882
|
+
if (!candidate.startsWith(baseName)) return false;
|
|
883
|
+
return /^\d+$/.test(candidate.slice(baseName.length));
|
|
884
|
+
}
|
|
885
|
+
function resolveEmployeeFromSessionPrefix(prefix, employees) {
|
|
886
|
+
const sorted = [...employees].sort((a, b) => b.name.length - a.name.length);
|
|
887
|
+
for (const employee of sorted) {
|
|
888
|
+
if (isNameWithOptionalInstance(prefix, employee.name)) {
|
|
889
|
+
return { agentId: employee.name, agentRole: employee.role };
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
return null;
|
|
893
|
+
}
|
|
894
|
+
function resolveActiveAgentFromTmuxSession(sessionName) {
|
|
895
|
+
const employees = loadEmployeesSync();
|
|
896
|
+
const coordinator = getCoordinatorEmployee(employees);
|
|
897
|
+
const coordinatorName = coordinator?.name ?? DEFAULT_COORDINATOR_TEMPLATE_NAME;
|
|
898
|
+
if (isNameWithOptionalInstance(sessionName, coordinatorName)) {
|
|
899
|
+
return {
|
|
900
|
+
agentId: coordinatorName,
|
|
901
|
+
agentRole: coordinator?.role ?? "COO"
|
|
902
|
+
};
|
|
903
|
+
}
|
|
904
|
+
if (isNameWithOptionalInstance(sessionName, DEFAULT_COORDINATOR_TEMPLATE_NAME)) {
|
|
905
|
+
return {
|
|
906
|
+
agentId: coordinator?.name ?? DEFAULT_COORDINATOR_TEMPLATE_NAME,
|
|
907
|
+
agentRole: coordinator?.role ?? "COO"
|
|
908
|
+
};
|
|
909
|
+
}
|
|
910
|
+
if (sessionName.includes("-")) {
|
|
911
|
+
const prefix = sessionName.split("-")[0] ?? "";
|
|
912
|
+
const employee = resolveEmployeeFromSessionPrefix(prefix, employees);
|
|
913
|
+
if (employee) return employee;
|
|
914
|
+
const legacy = prefix.match(/^([a-zA-Z]+)\d*$/);
|
|
915
|
+
if (legacy?.[1] && legacy[1] !== DEFAULT_COORDINATOR_TEMPLATE_NAME) {
|
|
916
|
+
const emp = getEmployee(employees, legacy[1]);
|
|
917
|
+
return { agentId: emp?.name ?? legacy[1], agentRole: emp?.role ?? "employee" };
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
return null;
|
|
921
|
+
}
|
|
922
|
+
function getMarkerPath() {
|
|
923
|
+
return path16.join(CACHE_DIR, `active-agent-${getSessionKey()}.json`);
|
|
924
|
+
}
|
|
925
|
+
function getActiveAgent() {
|
|
926
|
+
try {
|
|
927
|
+
const markerPath = getMarkerPath();
|
|
928
|
+
const raw = readFileSync10(markerPath, "utf8");
|
|
929
|
+
const data = JSON.parse(raw);
|
|
930
|
+
if (data.agentId) {
|
|
931
|
+
if (data.startedAt) {
|
|
932
|
+
const age = Date.now() - new Date(data.startedAt).getTime();
|
|
933
|
+
if (age > STALE_MS) {
|
|
934
|
+
try {
|
|
935
|
+
unlinkSync5(markerPath);
|
|
936
|
+
} catch {
|
|
937
|
+
}
|
|
938
|
+
} else {
|
|
939
|
+
return {
|
|
940
|
+
agentId: data.agentId,
|
|
941
|
+
agentRole: data.agentRole || "employee"
|
|
942
|
+
};
|
|
943
|
+
}
|
|
944
|
+
} else {
|
|
945
|
+
return {
|
|
946
|
+
agentId: data.agentId,
|
|
947
|
+
agentRole: data.agentRole || "employee"
|
|
948
|
+
};
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
} catch {
|
|
952
|
+
}
|
|
953
|
+
try {
|
|
954
|
+
const sessionName = execSync6(
|
|
955
|
+
"tmux display-message -p '#{session_name}' 2>/dev/null",
|
|
956
|
+
{ encoding: "utf8", timeout: 2e3 }
|
|
957
|
+
).trim();
|
|
958
|
+
const resolved = resolveActiveAgentFromTmuxSession(sessionName);
|
|
959
|
+
if (resolved) return resolved;
|
|
960
|
+
} catch {
|
|
961
|
+
}
|
|
962
|
+
return {
|
|
963
|
+
agentId: process.env.AGENT_ID || "default",
|
|
964
|
+
agentRole: process.env.AGENT_ROLE || "employee"
|
|
965
|
+
};
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
// src/mcp/tools/list-tasks.ts
|
|
821
969
|
function registerListTasks(server) {
|
|
822
970
|
server.registerTool(
|
|
823
971
|
"list_tasks",
|
|
824
972
|
{
|
|
825
973
|
title: "List Tasks",
|
|
826
|
-
description: "Query tasks by assignee, status, project, or priority. Defaults to current project. Pass project_name='all'
|
|
974
|
+
description: "Query tasks by assignee, status, project, or priority. Defaults to current project. Pass project_name='all' for all projects. When querying your own tasks, project filter is skipped automatically.",
|
|
827
975
|
inputSchema: {
|
|
828
976
|
assigned_to: z.string().optional().describe("Filter by employee name"),
|
|
829
977
|
status: z.enum(["open", "in_progress", "done", "blocked", "cancelled"]).optional().describe("Filter by status"),
|
|
@@ -833,7 +981,16 @@ function registerListTasks(server) {
|
|
|
833
981
|
},
|
|
834
982
|
async ({ assigned_to, status, project_name, priority }) => {
|
|
835
983
|
try {
|
|
836
|
-
|
|
984
|
+
let resolvedProject;
|
|
985
|
+
if (project_name === "all") {
|
|
986
|
+
resolvedProject = void 0;
|
|
987
|
+
} else if (project_name) {
|
|
988
|
+
resolvedProject = project_name;
|
|
989
|
+
} else {
|
|
990
|
+
const { agentId } = getActiveAgent();
|
|
991
|
+
const queryingSelf = !assigned_to || assigned_to === agentId;
|
|
992
|
+
resolvedProject = queryingSelf ? void 0 : getProjectName();
|
|
993
|
+
}
|
|
837
994
|
const tasks = await listTasks({
|
|
838
995
|
assignedTo: assigned_to,
|
|
839
996
|
status,
|