@askexenow/exe-os 0.8.40 → 0.8.42
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 +805 -642
- package/dist/bin/backfill-responses.js +804 -641
- package/dist/bin/backfill-vectors.js +791 -634
- package/dist/bin/cleanup-stale-review-tasks.js +788 -631
- package/dist/bin/cli.js +1376 -659
- package/dist/bin/exe-agent.js +20 -1
- package/dist/bin/exe-assign.js +1503 -1343
- package/dist/bin/exe-boot.js +2549 -1784
- package/dist/bin/exe-call.js +39 -1
- package/dist/bin/exe-cloud.js +12 -2
- package/dist/bin/exe-dispatch.js +39 -2
- package/dist/bin/exe-doctor.js +791 -634
- package/dist/bin/exe-export-behaviors.js +792 -637
- package/dist/bin/exe-forget.js +145 -0
- package/dist/bin/exe-gateway.js +2501 -1846
- package/dist/bin/exe-heartbeat.js +147 -1
- package/dist/bin/exe-kill.js +795 -640
- package/dist/bin/exe-launch-agent.js +2168 -2008
- package/dist/bin/exe-link.js +44 -12
- package/dist/bin/exe-new-employee.js +6 -2
- package/dist/bin/exe-pending-messages.js +146 -1
- package/dist/bin/exe-pending-notifications.js +788 -631
- package/dist/bin/exe-pending-reviews.js +176 -1
- package/dist/bin/exe-rename.js +23 -0
- package/dist/bin/exe-review.js +490 -327
- package/dist/bin/exe-search.js +157 -4
- package/dist/bin/exe-session-cleanup.js +2487 -403
- package/dist/bin/exe-settings.js +2 -1
- package/dist/bin/exe-status.js +474 -317
- package/dist/bin/exe-team.js +474 -317
- package/dist/bin/git-sweep.js +2691 -151
- package/dist/bin/graph-backfill.js +794 -637
- package/dist/bin/graph-export.js +798 -641
- package/dist/bin/scan-tasks.js +2951 -44
- package/dist/bin/setup.js +50 -26
- package/dist/bin/shard-migrate.js +792 -637
- package/dist/bin/wiki-sync.js +794 -637
- package/dist/gateway/index.js +2542 -1887
- package/dist/hooks/bug-report-worker.js +2118 -576
- package/dist/hooks/commit-complete.js +2690 -150
- package/dist/hooks/error-recall.js +157 -4
- package/dist/hooks/ingest-worker.js +1455 -803
- package/dist/hooks/instructions-loaded.js +151 -0
- package/dist/hooks/notification.js +153 -2
- package/dist/hooks/post-compact.js +164 -0
- package/dist/hooks/pre-compact.js +3073 -101
- package/dist/hooks/pre-tool-use.js +151 -0
- package/dist/hooks/prompt-ingest-worker.js +1670 -1509
- package/dist/hooks/prompt-submit.js +2650 -1074
- package/dist/hooks/response-ingest-worker.js +154 -6
- package/dist/hooks/session-end.js +153 -2
- package/dist/hooks/session-start.js +157 -4
- package/dist/hooks/stop.js +151 -0
- package/dist/hooks/subagent-stop.js +155 -2
- package/dist/hooks/summary-worker.js +190 -21
- package/dist/index.js +326 -102
- package/dist/lib/cloud-sync.js +31 -10
- package/dist/lib/config.js +2 -0
- package/dist/lib/consolidation.js +69 -2
- package/dist/lib/database.js +19 -0
- package/dist/lib/device-registry.js +19 -0
- package/dist/lib/embedder.js +3 -1
- package/dist/lib/employee-templates.js +20 -1
- package/dist/lib/exe-daemon.js +285 -18
- package/dist/lib/hybrid-search.js +157 -4
- package/dist/lib/messaging.js +39 -2
- package/dist/lib/schedules.js +792 -637
- package/dist/lib/store.js +796 -636
- package/dist/lib/tasks.js +1485 -918
- package/dist/lib/tmux-routing.js +194 -10
- package/dist/mcp/server.js +1643 -924
- package/dist/mcp/tools/create-task.js +2283 -829
- package/dist/mcp/tools/list-tasks.js +2788 -159
- package/dist/mcp/tools/send-message.js +39 -2
- package/dist/mcp/tools/update-task.js +79 -0
- package/dist/runtime/index.js +280 -68
- package/dist/tui/App.js +1485 -645
- package/package.json +3 -2
package/dist/bin/cli.js
CHANGED
|
@@ -31,6 +31,7 @@ var config_exports = {};
|
|
|
31
31
|
__export(config_exports, {
|
|
32
32
|
CONFIG_MIGRATIONS: () => CONFIG_MIGRATIONS,
|
|
33
33
|
CONFIG_PATH: () => CONFIG_PATH,
|
|
34
|
+
COO_AGENT_NAME: () => COO_AGENT_NAME,
|
|
34
35
|
CURRENT_CONFIG_VERSION: () => CURRENT_CONFIG_VERSION,
|
|
35
36
|
DB_PATH: () => DB_PATH,
|
|
36
37
|
EXE_AI_DIR: () => EXE_AI_DIR,
|
|
@@ -186,7 +187,7 @@ async function loadConfigFrom(configPath) {
|
|
|
186
187
|
return { ...DEFAULT_CONFIG };
|
|
187
188
|
}
|
|
188
189
|
}
|
|
189
|
-
var EXE_AI_DIR, DB_PATH, MODELS_DIR, CONFIG_PATH, LEGACY_LANCE_PATH, CURRENT_CONFIG_VERSION, DEFAULT_CONFIG, CONFIG_MIGRATIONS;
|
|
190
|
+
var EXE_AI_DIR, DB_PATH, MODELS_DIR, CONFIG_PATH, COO_AGENT_NAME, LEGACY_LANCE_PATH, CURRENT_CONFIG_VERSION, DEFAULT_CONFIG, CONFIG_MIGRATIONS;
|
|
190
191
|
var init_config = __esm({
|
|
191
192
|
"src/lib/config.ts"() {
|
|
192
193
|
"use strict";
|
|
@@ -194,6 +195,7 @@ var init_config = __esm({
|
|
|
194
195
|
DB_PATH = path.join(EXE_AI_DIR, "memories.db");
|
|
195
196
|
MODELS_DIR = path.join(EXE_AI_DIR, "models");
|
|
196
197
|
CONFIG_PATH = path.join(EXE_AI_DIR, "config.json");
|
|
198
|
+
COO_AGENT_NAME = "exe";
|
|
197
199
|
LEGACY_LANCE_PATH = path.join(EXE_AI_DIR, "local.lance");
|
|
198
200
|
CURRENT_CONFIG_VERSION = 1;
|
|
199
201
|
DEFAULT_CONFIG = {
|
|
@@ -1309,6 +1311,13 @@ async function ensureSchema() {
|
|
|
1309
1311
|
});
|
|
1310
1312
|
} catch {
|
|
1311
1313
|
}
|
|
1314
|
+
try {
|
|
1315
|
+
await client.execute({
|
|
1316
|
+
sql: `ALTER TABLE tasks ADD COLUMN session_scope TEXT`,
|
|
1317
|
+
args: []
|
|
1318
|
+
});
|
|
1319
|
+
} catch {
|
|
1320
|
+
}
|
|
1312
1321
|
try {
|
|
1313
1322
|
await client.execute({
|
|
1314
1323
|
sql: `ALTER TABLE memories ADD COLUMN task_id TEXT`,
|
|
@@ -1755,6 +1764,18 @@ async function ensureSchema() {
|
|
|
1755
1764
|
CREATE INDEX IF NOT EXISTS idx_session_kills_agent
|
|
1756
1765
|
ON session_kills(agent_id);
|
|
1757
1766
|
`);
|
|
1767
|
+
await client.execute(`
|
|
1768
|
+
CREATE TABLE IF NOT EXISTS global_procedures (
|
|
1769
|
+
id TEXT PRIMARY KEY,
|
|
1770
|
+
title TEXT NOT NULL,
|
|
1771
|
+
content TEXT NOT NULL,
|
|
1772
|
+
priority TEXT NOT NULL DEFAULT 'p0',
|
|
1773
|
+
domain TEXT,
|
|
1774
|
+
active INTEGER NOT NULL DEFAULT 1,
|
|
1775
|
+
created_at TEXT NOT NULL,
|
|
1776
|
+
updated_at TEXT NOT NULL
|
|
1777
|
+
)
|
|
1778
|
+
`);
|
|
1758
1779
|
await client.executeMultiple(`
|
|
1759
1780
|
CREATE TABLE IF NOT EXISTS conversations (
|
|
1760
1781
|
id TEXT PRIMARY KEY,
|
|
@@ -2059,6 +2080,61 @@ var init_keychain = __esm({
|
|
|
2059
2080
|
}
|
|
2060
2081
|
});
|
|
2061
2082
|
|
|
2083
|
+
// src/lib/state-bus.ts
|
|
2084
|
+
var StateBus, orgBus;
|
|
2085
|
+
var init_state_bus = __esm({
|
|
2086
|
+
"src/lib/state-bus.ts"() {
|
|
2087
|
+
"use strict";
|
|
2088
|
+
StateBus = class {
|
|
2089
|
+
handlers = /* @__PURE__ */ new Map();
|
|
2090
|
+
globalHandlers = /* @__PURE__ */ new Set();
|
|
2091
|
+
/** Emit an event to all subscribers */
|
|
2092
|
+
emit(event) {
|
|
2093
|
+
const typeHandlers = this.handlers.get(event.type);
|
|
2094
|
+
if (typeHandlers) {
|
|
2095
|
+
for (const handler of typeHandlers) {
|
|
2096
|
+
try {
|
|
2097
|
+
handler(event);
|
|
2098
|
+
} catch {
|
|
2099
|
+
}
|
|
2100
|
+
}
|
|
2101
|
+
}
|
|
2102
|
+
for (const handler of this.globalHandlers) {
|
|
2103
|
+
try {
|
|
2104
|
+
handler(event);
|
|
2105
|
+
} catch {
|
|
2106
|
+
}
|
|
2107
|
+
}
|
|
2108
|
+
}
|
|
2109
|
+
/** Subscribe to a specific event type */
|
|
2110
|
+
on(type, handler) {
|
|
2111
|
+
if (!this.handlers.has(type)) {
|
|
2112
|
+
this.handlers.set(type, /* @__PURE__ */ new Set());
|
|
2113
|
+
}
|
|
2114
|
+
this.handlers.get(type).add(handler);
|
|
2115
|
+
}
|
|
2116
|
+
/** Subscribe to ALL events */
|
|
2117
|
+
onAny(handler) {
|
|
2118
|
+
this.globalHandlers.add(handler);
|
|
2119
|
+
}
|
|
2120
|
+
/** Unsubscribe from a specific event type */
|
|
2121
|
+
off(type, handler) {
|
|
2122
|
+
this.handlers.get(type)?.delete(handler);
|
|
2123
|
+
}
|
|
2124
|
+
/** Unsubscribe from ALL events */
|
|
2125
|
+
offAny(handler) {
|
|
2126
|
+
this.globalHandlers.delete(handler);
|
|
2127
|
+
}
|
|
2128
|
+
/** Remove all listeners */
|
|
2129
|
+
clear() {
|
|
2130
|
+
this.handlers.clear();
|
|
2131
|
+
this.globalHandlers.clear();
|
|
2132
|
+
}
|
|
2133
|
+
};
|
|
2134
|
+
orgBus = new StateBus();
|
|
2135
|
+
}
|
|
2136
|
+
});
|
|
2137
|
+
|
|
2062
2138
|
// src/lib/shard-manager.ts
|
|
2063
2139
|
var shard_manager_exports = {};
|
|
2064
2140
|
__export(shard_manager_exports, {
|
|
@@ -2300,6 +2376,71 @@ var init_shard_manager = __esm({
|
|
|
2300
2376
|
}
|
|
2301
2377
|
});
|
|
2302
2378
|
|
|
2379
|
+
// src/lib/global-procedures.ts
|
|
2380
|
+
var global_procedures_exports = {};
|
|
2381
|
+
__export(global_procedures_exports, {
|
|
2382
|
+
deactivateGlobalProcedure: () => deactivateGlobalProcedure,
|
|
2383
|
+
getGlobalProceduresBlock: () => getGlobalProceduresBlock,
|
|
2384
|
+
loadGlobalProcedures: () => loadGlobalProcedures,
|
|
2385
|
+
storeGlobalProcedure: () => storeGlobalProcedure
|
|
2386
|
+
});
|
|
2387
|
+
import { randomUUID } from "crypto";
|
|
2388
|
+
async function loadGlobalProcedures() {
|
|
2389
|
+
const client = getClient();
|
|
2390
|
+
const result = await client.execute({
|
|
2391
|
+
sql: "SELECT * FROM global_procedures WHERE active = 1 ORDER BY priority ASC, created_at ASC",
|
|
2392
|
+
args: []
|
|
2393
|
+
});
|
|
2394
|
+
const procedures = result.rows;
|
|
2395
|
+
if (procedures.length > 0) {
|
|
2396
|
+
_cache = procedures.map((p) => `### ${p.title}
|
|
2397
|
+
${p.content}`).join("\n\n");
|
|
2398
|
+
} else {
|
|
2399
|
+
_cache = "";
|
|
2400
|
+
}
|
|
2401
|
+
_cacheLoaded = true;
|
|
2402
|
+
return procedures;
|
|
2403
|
+
}
|
|
2404
|
+
function getGlobalProceduresBlock() {
|
|
2405
|
+
if (!_cacheLoaded) return "";
|
|
2406
|
+
if (!_cache) return "";
|
|
2407
|
+
return `## Organization-Wide Procedures (MANDATORY \u2014 supersedes all other rules)
|
|
2408
|
+
|
|
2409
|
+
${_cache}
|
|
2410
|
+
`;
|
|
2411
|
+
}
|
|
2412
|
+
async function storeGlobalProcedure(input) {
|
|
2413
|
+
const id = randomUUID();
|
|
2414
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2415
|
+
const client = getClient();
|
|
2416
|
+
await client.execute({
|
|
2417
|
+
sql: `INSERT INTO global_procedures (id, title, content, priority, domain, active, created_at, updated_at)
|
|
2418
|
+
VALUES (?, ?, ?, ?, ?, 1, ?, ?)`,
|
|
2419
|
+
args: [id, input.title, input.content, input.priority ?? "p0", input.domain ?? null, now, now]
|
|
2420
|
+
});
|
|
2421
|
+
await loadGlobalProcedures();
|
|
2422
|
+
return id;
|
|
2423
|
+
}
|
|
2424
|
+
async function deactivateGlobalProcedure(id) {
|
|
2425
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2426
|
+
const client = getClient();
|
|
2427
|
+
const result = await client.execute({
|
|
2428
|
+
sql: "UPDATE global_procedures SET active = 0, updated_at = ? WHERE id = ?",
|
|
2429
|
+
args: [now, id]
|
|
2430
|
+
});
|
|
2431
|
+
await loadGlobalProcedures();
|
|
2432
|
+
return result.rowsAffected > 0;
|
|
2433
|
+
}
|
|
2434
|
+
var _cache, _cacheLoaded;
|
|
2435
|
+
var init_global_procedures = __esm({
|
|
2436
|
+
"src/lib/global-procedures.ts"() {
|
|
2437
|
+
"use strict";
|
|
2438
|
+
init_database();
|
|
2439
|
+
_cache = "";
|
|
2440
|
+
_cacheLoaded = false;
|
|
2441
|
+
}
|
|
2442
|
+
});
|
|
2443
|
+
|
|
2303
2444
|
// src/lib/store.ts
|
|
2304
2445
|
var store_exports = {};
|
|
2305
2446
|
__export(store_exports, {
|
|
@@ -2379,6 +2520,11 @@ async function initStore(options) {
|
|
|
2379
2520
|
"version-query"
|
|
2380
2521
|
);
|
|
2381
2522
|
_nextVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
|
|
2523
|
+
try {
|
|
2524
|
+
const { loadGlobalProcedures: loadGlobalProcedures2 } = await Promise.resolve().then(() => (init_global_procedures(), global_procedures_exports));
|
|
2525
|
+
await loadGlobalProcedures2();
|
|
2526
|
+
} catch {
|
|
2527
|
+
}
|
|
2382
2528
|
}
|
|
2383
2529
|
function classifyTier(record) {
|
|
2384
2530
|
if (record.tool_name === "commit_to_long_term_memory" && (record.importance ?? 0) >= 8) return 1;
|
|
@@ -2420,6 +2566,12 @@ async function writeMemory(record) {
|
|
|
2420
2566
|
supersedes_id: record.supersedes_id ?? null
|
|
2421
2567
|
};
|
|
2422
2568
|
_pendingRecords.push(dbRow);
|
|
2569
|
+
orgBus.emit({
|
|
2570
|
+
type: "memory_stored",
|
|
2571
|
+
agentId: record.agent_id,
|
|
2572
|
+
project: record.project_name,
|
|
2573
|
+
timestamp: record.timestamp
|
|
2574
|
+
});
|
|
2423
2575
|
const MAX_PENDING = 1e3;
|
|
2424
2576
|
if (_pendingRecords.length > MAX_PENDING) {
|
|
2425
2577
|
const dropped = _pendingRecords.length - MAX_PENDING;
|
|
@@ -2765,6 +2917,7 @@ var init_store = __esm({
|
|
|
2765
2917
|
init_database();
|
|
2766
2918
|
init_keychain();
|
|
2767
2919
|
init_config();
|
|
2920
|
+
init_state_bus();
|
|
2768
2921
|
INIT_MAX_RETRIES = 3;
|
|
2769
2922
|
INIT_RETRY_DELAY_MS = 1e3;
|
|
2770
2923
|
_pendingRecords = [];
|
|
@@ -2779,7 +2932,7 @@ var init_store = __esm({
|
|
|
2779
2932
|
// src/lib/exe-daemon-client.ts
|
|
2780
2933
|
import net from "net";
|
|
2781
2934
|
import { spawn } from "child_process";
|
|
2782
|
-
import { randomUUID } from "crypto";
|
|
2935
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
2783
2936
|
import { existsSync as existsSync7, unlinkSync, readFileSync as readFileSync4, openSync, closeSync, statSync } from "fs";
|
|
2784
2937
|
import path7 from "path";
|
|
2785
2938
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
@@ -2971,7 +3124,7 @@ function sendRequest(texts, priority) {
|
|
|
2971
3124
|
resolve({ error: "Not connected" });
|
|
2972
3125
|
return;
|
|
2973
3126
|
}
|
|
2974
|
-
const id =
|
|
3127
|
+
const id = randomUUID2();
|
|
2975
3128
|
const timer = setTimeout(() => {
|
|
2976
3129
|
_pending.delete(id);
|
|
2977
3130
|
resolve({ error: "Request timeout" });
|
|
@@ -2989,7 +3142,7 @@ function sendRequest(texts, priority) {
|
|
|
2989
3142
|
async function pingDaemon() {
|
|
2990
3143
|
if (!_socket || !_connected) return null;
|
|
2991
3144
|
return new Promise((resolve) => {
|
|
2992
|
-
const id =
|
|
3145
|
+
const id = randomUUID2();
|
|
2993
3146
|
const timer = setTimeout(() => {
|
|
2994
3147
|
_pending.delete(id);
|
|
2995
3148
|
resolve(null);
|
|
@@ -3535,7 +3688,8 @@ __export(employee_templates_exports, {
|
|
|
3535
3688
|
function getSessionPrompt(storedPrompt) {
|
|
3536
3689
|
const markerIndex = storedPrompt.indexOf(PROCEDURES_MARKER);
|
|
3537
3690
|
const rolePrompt = markerIndex >= 0 ? storedPrompt.slice(0, markerIndex).trimEnd() : storedPrompt;
|
|
3538
|
-
|
|
3691
|
+
const globalBlock = getGlobalProceduresBlock();
|
|
3692
|
+
return `${globalBlock}${rolePrompt}
|
|
3539
3693
|
${BASE_OPERATING_PROCEDURES}`;
|
|
3540
3694
|
}
|
|
3541
3695
|
function buildCustomEmployeePrompt(name, role) {
|
|
@@ -3575,6 +3729,7 @@ var BASE_OPERATING_PROCEDURES, DEFAULT_EXE, TEMPLATE_VERSION, PROCEDURES_MARKER,
|
|
|
3575
3729
|
var init_employee_templates = __esm({
|
|
3576
3730
|
"src/lib/employee-templates.ts"() {
|
|
3577
3731
|
"use strict";
|
|
3732
|
+
init_global_procedures();
|
|
3578
3733
|
BASE_OPERATING_PROCEDURES = `
|
|
3579
3734
|
EXE OS \u2014 VISION AND NON-NEGOTIABLE PRINCIPLES (above all work):
|
|
3580
3735
|
|
|
@@ -4508,7 +4663,7 @@ __export(license_exports, {
|
|
|
4508
4663
|
validateLicense: () => validateLicense
|
|
4509
4664
|
});
|
|
4510
4665
|
import { readFileSync as readFileSync6, writeFileSync as writeFileSync2, existsSync as existsSync10, mkdirSync as mkdirSync3 } from "fs";
|
|
4511
|
-
import { randomUUID as
|
|
4666
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
4512
4667
|
import path11 from "path";
|
|
4513
4668
|
import { jwtVerify, importSPKI } from "jose";
|
|
4514
4669
|
async function fetchRetry(url, init) {
|
|
@@ -4535,7 +4690,7 @@ function loadDeviceId() {
|
|
|
4535
4690
|
}
|
|
4536
4691
|
} catch {
|
|
4537
4692
|
}
|
|
4538
|
-
const id =
|
|
4693
|
+
const id = randomUUID3();
|
|
4539
4694
|
mkdirSync3(EXE_AI_DIR, { recursive: true });
|
|
4540
4695
|
writeFileSync2(DEVICE_ID_PATH, id, "utf8");
|
|
4541
4696
|
return id;
|
|
@@ -12307,6 +12462,73 @@ var init_Sidebar = __esm({
|
|
|
12307
12462
|
}
|
|
12308
12463
|
});
|
|
12309
12464
|
|
|
12465
|
+
// src/lib/telemetry.ts
|
|
12466
|
+
var telemetry_exports = {};
|
|
12467
|
+
__export(telemetry_exports, {
|
|
12468
|
+
instrumentServer: () => instrumentServer,
|
|
12469
|
+
withTrace: () => withTrace
|
|
12470
|
+
});
|
|
12471
|
+
async function ensureInit() {
|
|
12472
|
+
if (initialized || !ENABLED) return;
|
|
12473
|
+
initialized = true;
|
|
12474
|
+
try {
|
|
12475
|
+
const { NodeSDK } = await import("@opentelemetry/sdk-node");
|
|
12476
|
+
const { ConsoleSpanExporter } = await import("@opentelemetry/sdk-trace-base");
|
|
12477
|
+
const sdk = new NodeSDK({
|
|
12478
|
+
serviceName: "exe-os",
|
|
12479
|
+
traceExporter: new ConsoleSpanExporter()
|
|
12480
|
+
});
|
|
12481
|
+
sdk.start();
|
|
12482
|
+
process.stderr.write("[exe-os] OpenTelemetry tracing enabled\n");
|
|
12483
|
+
} catch (err) {
|
|
12484
|
+
process.stderr.write(
|
|
12485
|
+
`[exe-os] OpenTelemetry init failed: ${err instanceof Error ? err.message : String(err)}
|
|
12486
|
+
`
|
|
12487
|
+
);
|
|
12488
|
+
}
|
|
12489
|
+
}
|
|
12490
|
+
async function withTrace(toolName, fn) {
|
|
12491
|
+
if (!ENABLED) return fn();
|
|
12492
|
+
await ensureInit();
|
|
12493
|
+
const { trace, SpanStatusCode } = await import("@opentelemetry/api");
|
|
12494
|
+
const tracer = trace.getTracer("exe-os", "1.0.0");
|
|
12495
|
+
return tracer.startActiveSpan(`mcp.tool.${toolName}`, async (span) => {
|
|
12496
|
+
span.setAttribute("mcp.tool.name", toolName);
|
|
12497
|
+
try {
|
|
12498
|
+
const result = await fn();
|
|
12499
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
12500
|
+
return result;
|
|
12501
|
+
} catch (err) {
|
|
12502
|
+
span.setStatus({
|
|
12503
|
+
code: SpanStatusCode.ERROR,
|
|
12504
|
+
message: err instanceof Error ? err.message : String(err)
|
|
12505
|
+
});
|
|
12506
|
+
span.recordException(
|
|
12507
|
+
err instanceof Error ? err : new Error(String(err))
|
|
12508
|
+
);
|
|
12509
|
+
throw err;
|
|
12510
|
+
} finally {
|
|
12511
|
+
span.end();
|
|
12512
|
+
}
|
|
12513
|
+
});
|
|
12514
|
+
}
|
|
12515
|
+
function instrumentServer(server) {
|
|
12516
|
+
if (!ENABLED) return;
|
|
12517
|
+
const original = server.registerTool.bind(server);
|
|
12518
|
+
server.registerTool = (name, config, handler) => {
|
|
12519
|
+
const traced = async (...args2) => withTrace(name, () => handler(...args2));
|
|
12520
|
+
return original(name, config, traced);
|
|
12521
|
+
};
|
|
12522
|
+
}
|
|
12523
|
+
var ENABLED, initialized;
|
|
12524
|
+
var init_telemetry = __esm({
|
|
12525
|
+
"src/lib/telemetry.ts"() {
|
|
12526
|
+
"use strict";
|
|
12527
|
+
ENABLED = process.env.EXE_TELEMETRY === "1";
|
|
12528
|
+
initialized = false;
|
|
12529
|
+
}
|
|
12530
|
+
});
|
|
12531
|
+
|
|
12310
12532
|
// src/lib/tmux-status.ts
|
|
12311
12533
|
var tmux_status_exports = {};
|
|
12312
12534
|
__export(tmux_status_exports, {
|
|
@@ -12601,61 +12823,64 @@ function Footer() {
|
|
|
12601
12823
|
return () => clearInterval(timer);
|
|
12602
12824
|
}, []);
|
|
12603
12825
|
async function loadFooterData() {
|
|
12604
|
-
|
|
12605
|
-
|
|
12606
|
-
|
|
12607
|
-
|
|
12608
|
-
const
|
|
12609
|
-
|
|
12826
|
+
const { withTrace: withTrace2 } = await Promise.resolve().then(() => (init_telemetry(), telemetry_exports));
|
|
12827
|
+
return withTrace2("tui.footer.loadData", async () => {
|
|
12828
|
+
try {
|
|
12829
|
+
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
12830
|
+
const client = getClient2();
|
|
12831
|
+
if (client) {
|
|
12832
|
+
const result = await client.execute("SELECT COUNT(*) as cnt FROM memories");
|
|
12833
|
+
setMemoryCount(Number(result.rows[0]?.cnt ?? 0));
|
|
12834
|
+
}
|
|
12835
|
+
} catch {
|
|
12610
12836
|
}
|
|
12611
|
-
|
|
12612
|
-
|
|
12613
|
-
|
|
12614
|
-
|
|
12615
|
-
|
|
12616
|
-
|
|
12617
|
-
|
|
12618
|
-
|
|
12619
|
-
|
|
12620
|
-
|
|
12837
|
+
try {
|
|
12838
|
+
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
12839
|
+
const client = getClient2();
|
|
12840
|
+
if (client) {
|
|
12841
|
+
const result = await client.execute(
|
|
12842
|
+
"SELECT COUNT(*) as cnt FROM tasks WHERE status IN ('open','in_progress')"
|
|
12843
|
+
);
|
|
12844
|
+
setTaskCount(Number(result.rows[0]?.cnt ?? 0));
|
|
12845
|
+
}
|
|
12846
|
+
} catch {
|
|
12621
12847
|
}
|
|
12622
|
-
|
|
12623
|
-
|
|
12624
|
-
|
|
12625
|
-
|
|
12626
|
-
|
|
12627
|
-
|
|
12628
|
-
|
|
12629
|
-
|
|
12630
|
-
|
|
12631
|
-
|
|
12632
|
-
|
|
12633
|
-
|
|
12634
|
-
|
|
12635
|
-
|
|
12636
|
-
|
|
12637
|
-
|
|
12638
|
-
|
|
12639
|
-
|
|
12640
|
-
|
|
12641
|
-
|
|
12642
|
-
|
|
12643
|
-
|
|
12644
|
-
|
|
12645
|
-
|
|
12646
|
-
|
|
12647
|
-
|
|
12648
|
-
|
|
12649
|
-
|
|
12650
|
-
|
|
12651
|
-
}
|
|
12652
|
-
|
|
12653
|
-
} catch {
|
|
12848
|
+
try {
|
|
12849
|
+
const { existsSync: existsSync22 } = await import("fs");
|
|
12850
|
+
const { join } = await import("path");
|
|
12851
|
+
const home = process.env.HOME ?? "";
|
|
12852
|
+
const pidPath = join(home, ".exe-os", "exed.pid");
|
|
12853
|
+
setDaemon(existsSync22(pidPath) ? "running" : "stopped");
|
|
12854
|
+
} catch {
|
|
12855
|
+
setDaemon("unknown");
|
|
12856
|
+
}
|
|
12857
|
+
try {
|
|
12858
|
+
const { checkLicense: checkLicense2 } = await Promise.resolve().then(() => (init_license(), license_exports));
|
|
12859
|
+
const license = await checkLicense2();
|
|
12860
|
+
setPlan(license.plan);
|
|
12861
|
+
} catch {
|
|
12862
|
+
setPlan("free");
|
|
12863
|
+
}
|
|
12864
|
+
try {
|
|
12865
|
+
const { listTmuxSessions: listTmuxSessions2, inTmux: inTmux2 } = await Promise.resolve().then(() => (init_tmux_status(), tmux_status_exports));
|
|
12866
|
+
if (inTmux2()) {
|
|
12867
|
+
const allSessions = listTmuxSessions2();
|
|
12868
|
+
setSessions(allSessions.length);
|
|
12869
|
+
if (!currentSession) {
|
|
12870
|
+
try {
|
|
12871
|
+
const { execSync: execSync13 } = await import("child_process");
|
|
12872
|
+
const name = execSync13("tmux display-message -p '#{session_name}' 2>/dev/null", {
|
|
12873
|
+
encoding: "utf8",
|
|
12874
|
+
timeout: 2e3
|
|
12875
|
+
}).trim();
|
|
12876
|
+
if (name) setCurrentSession(name);
|
|
12877
|
+
} catch {
|
|
12878
|
+
}
|
|
12654
12879
|
}
|
|
12655
12880
|
}
|
|
12881
|
+
} catch {
|
|
12656
12882
|
}
|
|
12657
|
-
}
|
|
12658
|
-
}
|
|
12883
|
+
});
|
|
12659
12884
|
}
|
|
12660
12885
|
return /* @__PURE__ */ jsxs3(Box_default, { flexDirection: "column", children: [
|
|
12661
12886
|
/* @__PURE__ */ jsx5(Text, { color: "#3D3660", children: "\u2500".repeat(process.stdout.columns || 120) }),
|
|
@@ -12696,6 +12921,8 @@ function Footer() {
|
|
|
12696
12921
|
] }),
|
|
12697
12922
|
/* @__PURE__ */ jsx5(Text, { color: "#6B4C9A", children: "1-7 navigate" }),
|
|
12698
12923
|
/* @__PURE__ */ jsx5(Text, { color: "#3D3660", children: "\u2502" }),
|
|
12924
|
+
/* @__PURE__ */ jsx5(Text, { color: "#6B4C9A", children: "d debug" }),
|
|
12925
|
+
/* @__PURE__ */ jsx5(Text, { color: "#3D3660", children: "\u2502" }),
|
|
12699
12926
|
/* @__PURE__ */ jsx5(Text, { color: "#6B4C9A", children: "q quit" })
|
|
12700
12927
|
] })
|
|
12701
12928
|
] })
|
|
@@ -14344,7 +14571,7 @@ var init_anthropic = __esm({
|
|
|
14344
14571
|
|
|
14345
14572
|
// src/gateway/providers/openai-compat.ts
|
|
14346
14573
|
import OpenAI from "openai";
|
|
14347
|
-
import { randomUUID as
|
|
14574
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
14348
14575
|
var OpenAICompatProvider;
|
|
14349
14576
|
var init_openai_compat = __esm({
|
|
14350
14577
|
"src/gateway/providers/openai-compat.ts"() {
|
|
@@ -14461,7 +14688,7 @@ var init_openai_compat = __esm({
|
|
|
14461
14688
|
}
|
|
14462
14689
|
content.push({
|
|
14463
14690
|
type: "tool_use",
|
|
14464
|
-
id: call.id ??
|
|
14691
|
+
id: call.id ?? randomUUID4(),
|
|
14465
14692
|
name: fn.name,
|
|
14466
14693
|
input
|
|
14467
14694
|
});
|
|
@@ -15535,7 +15762,7 @@ function CommandCenterView({
|
|
|
15535
15762
|
setAgentConfig({
|
|
15536
15763
|
provider,
|
|
15537
15764
|
model,
|
|
15538
|
-
systemPrompt: "You are an AI assistant in the exe-os TUI. Help the user with their questions. Be concise.",
|
|
15765
|
+
systemPrompt: getSessionPrompt("You are an AI assistant in the exe-os TUI. Help the user with their questions. Be concise."),
|
|
15539
15766
|
tools: registry,
|
|
15540
15767
|
hooks: createDefaultHooks2(),
|
|
15541
15768
|
permissions,
|
|
@@ -15656,6 +15883,7 @@ function CommandCenterView({
|
|
|
15656
15883
|
employeeCount: p.employees.length,
|
|
15657
15884
|
activeCount: p.employees.filter((e) => e.status === "active").length,
|
|
15658
15885
|
memoryCount: p.employees.length * 4e3,
|
|
15886
|
+
openTaskCount: Math.floor(p.employees.length * 1.5),
|
|
15659
15887
|
status: p.employees.some((e) => e.status === "active") ? "active" : "idle",
|
|
15660
15888
|
type: p.projectName.startsWith("exe-") ? "code" : "automation",
|
|
15661
15889
|
recentTasks: DEMO_RECENT_TASKS[p.projectName] ?? []
|
|
@@ -15667,6 +15895,7 @@ function CommandCenterView({
|
|
|
15667
15895
|
employeeCount: 0,
|
|
15668
15896
|
activeCount: 0,
|
|
15669
15897
|
memoryCount: 0,
|
|
15898
|
+
openTaskCount: 0,
|
|
15670
15899
|
status: "offline",
|
|
15671
15900
|
type: "reference",
|
|
15672
15901
|
recentTasks: []
|
|
@@ -15681,182 +15910,122 @@ function CommandCenterView({
|
|
|
15681
15910
|
return () => clearInterval(timer);
|
|
15682
15911
|
}, []);
|
|
15683
15912
|
async function loadData() {
|
|
15684
|
-
|
|
15685
|
-
|
|
15686
|
-
const { listTmuxSessions: listTmuxSessions2, inTmux: inTmux2 } = await Promise.resolve().then(() => (init_tmux_status(), tmux_status_exports));
|
|
15687
|
-
const { loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
15688
|
-
const { existsSync: existsSync22 } = await import("fs");
|
|
15689
|
-
const { join } = await import("path");
|
|
15690
|
-
const registry = listSessions2();
|
|
15691
|
-
const tmuxSessions = inTmux2() ? new Set(listTmuxSessions2()) : /* @__PURE__ */ new Set();
|
|
15692
|
-
const roster = await loadEmployees2();
|
|
15693
|
-
const exeSessions = /* @__PURE__ */ new Map();
|
|
15694
|
-
for (const entry of registry) {
|
|
15695
|
-
if (entry.agentId === "exe" && tmuxSessions.has(entry.windowName)) {
|
|
15696
|
-
exeSessions.set(entry.windowName, entry.projectDir);
|
|
15697
|
-
}
|
|
15698
|
-
}
|
|
15699
|
-
for (const s of tmuxSessions) {
|
|
15700
|
-
if (/^exe\d+$/.test(s) && !exeSessions.has(s)) exeSessions.set(s, "");
|
|
15701
|
-
}
|
|
15702
|
-
let projectMemoryCounts = /* @__PURE__ */ new Map();
|
|
15703
|
-
let projectRecentTasks = /* @__PURE__ */ new Map();
|
|
15913
|
+
const { withTrace: withTrace2 } = await Promise.resolve().then(() => (init_telemetry(), telemetry_exports));
|
|
15914
|
+
return withTrace2("tui.commandCenter.loadData", async () => {
|
|
15704
15915
|
try {
|
|
15705
15916
|
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
15917
|
+
const { listSessions: listSessions2 } = await Promise.resolve().then(() => (init_session_registry(), session_registry_exports));
|
|
15918
|
+
const { listTmuxSessions: listTmuxSessions2, inTmux: inTmux2 } = await Promise.resolve().then(() => (init_tmux_status(), tmux_status_exports));
|
|
15919
|
+
const { loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
15920
|
+
const { existsSync: existsSync22 } = await import("fs");
|
|
15921
|
+
const { join } = await import("path");
|
|
15706
15922
|
const client = getClient2();
|
|
15707
|
-
if (client) {
|
|
15708
|
-
|
|
15709
|
-
|
|
15710
|
-
);
|
|
15711
|
-
for (const row of memResult.rows) {
|
|
15712
|
-
projectMemoryCounts.set(String(row.project_name), Number(row.cnt));
|
|
15713
|
-
}
|
|
15714
|
-
for (const [, projectDir] of exeSessions) {
|
|
15715
|
-
const projectName = projectDir.split("/").filter(Boolean).pop() ?? "";
|
|
15716
|
-
if (!projectName) continue;
|
|
15717
|
-
const taskResult = await client.execute({
|
|
15718
|
-
sql: "SELECT title FROM tasks WHERE project_name = ? AND status = 'done' ORDER BY updated_at DESC LIMIT 3",
|
|
15719
|
-
args: [projectName]
|
|
15720
|
-
});
|
|
15721
|
-
const tasks = taskResult.rows.map((r) => String(r.title));
|
|
15722
|
-
if (tasks.length > 0) projectRecentTasks.set(projectName, tasks);
|
|
15723
|
-
}
|
|
15923
|
+
if (!client) {
|
|
15924
|
+
setDbError(true);
|
|
15925
|
+
return;
|
|
15724
15926
|
}
|
|
15725
|
-
|
|
15726
|
-
|
|
15727
|
-
|
|
15728
|
-
|
|
15729
|
-
|
|
15927
|
+
const dbProjects = await client.execute(
|
|
15928
|
+
`SELECT DISTINCT project_name FROM memories WHERE project_name IS NOT NULL AND project_name != ''
|
|
15929
|
+
UNION
|
|
15930
|
+
SELECT DISTINCT project_name FROM tasks WHERE project_name IS NOT NULL AND project_name != ''
|
|
15931
|
+
ORDER BY project_name`
|
|
15932
|
+
);
|
|
15933
|
+
const projectNames = dbProjects.rows.map((r) => String(r.project_name));
|
|
15934
|
+
const memResult = await client.execute(
|
|
15935
|
+
"SELECT project_name, COUNT(*) as cnt FROM memories WHERE project_name IS NOT NULL GROUP BY project_name"
|
|
15936
|
+
);
|
|
15937
|
+
const memoryCounts = /* @__PURE__ */ new Map();
|
|
15938
|
+
for (const row of memResult.rows) {
|
|
15939
|
+
memoryCounts.set(String(row.project_name), Number(row.cnt));
|
|
15940
|
+
}
|
|
15941
|
+
const taskCountResult = await client.execute(
|
|
15942
|
+
"SELECT project_name, COUNT(*) as cnt FROM tasks WHERE status IN ('open', 'in_progress') AND project_name IS NOT NULL GROUP BY project_name"
|
|
15943
|
+
);
|
|
15944
|
+
const openTaskCounts = /* @__PURE__ */ new Map();
|
|
15945
|
+
for (const row of taskCountResult.rows) {
|
|
15946
|
+
openTaskCounts.set(String(row.project_name), Number(row.cnt));
|
|
15947
|
+
}
|
|
15948
|
+
const recentResult = await client.execute(
|
|
15949
|
+
"SELECT project_name, title FROM tasks WHERE status = 'done' AND project_name IS NOT NULL ORDER BY updated_at DESC LIMIT 30"
|
|
15950
|
+
);
|
|
15951
|
+
const recentTasksByProject = /* @__PURE__ */ new Map();
|
|
15952
|
+
for (const row of recentResult.rows) {
|
|
15953
|
+
const name = String(row.project_name);
|
|
15954
|
+
const tasks = recentTasksByProject.get(name) ?? [];
|
|
15955
|
+
if (tasks.length < 3) tasks.push(String(row.title));
|
|
15956
|
+
recentTasksByProject.set(name, tasks);
|
|
15957
|
+
}
|
|
15958
|
+
const registry = listSessions2();
|
|
15959
|
+
const tmuxSessions = inTmux2() ? new Set(listTmuxSessions2()) : /* @__PURE__ */ new Set();
|
|
15960
|
+
const roster = await loadEmployees2();
|
|
15730
15961
|
const employeeNames = roster.map((e) => e.name).filter((n) => n !== "exe");
|
|
15731
|
-
|
|
15732
|
-
for (const
|
|
15733
|
-
if (tmuxSessions.has(
|
|
15734
|
-
|
|
15735
|
-
|
|
15736
|
-
|
|
15737
|
-
|
|
15738
|
-
const hasActivity = memoryCount > 0;
|
|
15739
|
-
let type = "automation";
|
|
15740
|
-
if (hasGit && hasActivity) type = "code";
|
|
15741
|
-
else if (hasGit && !hasActivity) type = "reference";
|
|
15742
|
-
projectList.push({
|
|
15743
|
-
projectName,
|
|
15744
|
-
exeSession,
|
|
15745
|
-
projectDir,
|
|
15746
|
-
employeeCount: totalCount,
|
|
15747
|
-
activeCount,
|
|
15748
|
-
memoryCount,
|
|
15749
|
-
status: activeCount > 0 ? "active" : "idle",
|
|
15750
|
-
type,
|
|
15751
|
-
recentTasks: projectRecentTasks.get(projectName) ?? []
|
|
15752
|
-
});
|
|
15753
|
-
}
|
|
15754
|
-
const knownDirs = [
|
|
15755
|
-
process.env.HOME ? join(process.env.HOME, "openclaw") : null,
|
|
15756
|
-
process.env.HOME ? join(process.env.HOME, "agno") : null
|
|
15757
|
-
].filter(Boolean);
|
|
15758
|
-
const activeProjectNames = new Set(projectList.map((p) => p.projectName));
|
|
15759
|
-
for (const dir of knownDirs) {
|
|
15760
|
-
const name = dir.split("/").filter(Boolean).pop() ?? "";
|
|
15761
|
-
if (activeProjectNames.has(name) || !existsSync22(dir) || !existsSync22(join(dir, ".git"))) continue;
|
|
15762
|
-
if ((projectMemoryCounts.get(name) ?? 0) > 0) continue;
|
|
15763
|
-
projectList.push({
|
|
15764
|
-
projectName: name,
|
|
15765
|
-
exeSession: "",
|
|
15766
|
-
projectDir: dir,
|
|
15767
|
-
employeeCount: 0,
|
|
15768
|
-
activeCount: 0,
|
|
15769
|
-
memoryCount: 0,
|
|
15770
|
-
status: "offline",
|
|
15771
|
-
type: "reference",
|
|
15772
|
-
recentTasks: []
|
|
15773
|
-
});
|
|
15774
|
-
}
|
|
15775
|
-
const dbActiveProjectNames = new Set(projectList.map((p) => p.projectName));
|
|
15776
|
-
try {
|
|
15777
|
-
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
15778
|
-
const client = getClient2();
|
|
15779
|
-
if (client) {
|
|
15780
|
-
const dbProjects = await client.execute(
|
|
15781
|
-
`SELECT DISTINCT project_name FROM memories WHERE project_name IS NOT NULL AND project_name != ''
|
|
15782
|
-
UNION
|
|
15783
|
-
SELECT DISTINCT project_name FROM tasks WHERE project_name IS NOT NULL AND project_name != ''
|
|
15784
|
-
ORDER BY project_name`
|
|
15785
|
-
);
|
|
15786
|
-
for (const row of dbProjects.rows) {
|
|
15787
|
-
const name = String(row.project_name);
|
|
15788
|
-
if (dbActiveProjectNames.has(name)) continue;
|
|
15789
|
-
const memCount = projectMemoryCounts.get(name) ?? 0;
|
|
15790
|
-
const agentResult = await client.execute({
|
|
15791
|
-
sql: "SELECT COUNT(DISTINCT agent_id) as cnt FROM memories WHERE project_name = ?",
|
|
15792
|
-
args: [name]
|
|
15793
|
-
});
|
|
15794
|
-
const agentCount = Number(agentResult.rows[0]?.cnt ?? 0);
|
|
15795
|
-
projectList.push({
|
|
15796
|
-
projectName: name,
|
|
15797
|
-
exeSession: "",
|
|
15798
|
-
projectDir: "",
|
|
15799
|
-
employeeCount: agentCount,
|
|
15800
|
-
activeCount: 0,
|
|
15801
|
-
memoryCount: memCount,
|
|
15802
|
-
status: "offline",
|
|
15803
|
-
type: "code",
|
|
15804
|
-
recentTasks: projectRecentTasks.get(name) ?? []
|
|
15805
|
-
});
|
|
15962
|
+
const projectSessions = /* @__PURE__ */ new Map();
|
|
15963
|
+
for (const entry of registry) {
|
|
15964
|
+
if (entry.agentId === "exe" && tmuxSessions.has(entry.windowName)) {
|
|
15965
|
+
const projName = entry.projectDir.split("/").filter(Boolean).pop() ?? "";
|
|
15966
|
+
if (projName) {
|
|
15967
|
+
projectSessions.set(projName, { exeSession: entry.windowName, projectDir: entry.projectDir });
|
|
15968
|
+
}
|
|
15806
15969
|
}
|
|
15807
15970
|
}
|
|
15808
|
-
|
|
15809
|
-
|
|
15810
|
-
|
|
15811
|
-
|
|
15812
|
-
|
|
15813
|
-
|
|
15814
|
-
|
|
15815
|
-
|
|
15816
|
-
|
|
15817
|
-
|
|
15818
|
-
|
|
15819
|
-
|
|
15820
|
-
|
|
15971
|
+
const projectList = [];
|
|
15972
|
+
for (const name of projectNames) {
|
|
15973
|
+
const session = projectSessions.get(name);
|
|
15974
|
+
const exeSession = session?.exeSession ?? "";
|
|
15975
|
+
const projectDir = session?.projectDir ?? "";
|
|
15976
|
+
let activeCount = 0;
|
|
15977
|
+
if (exeSession && tmuxSessions.has(exeSession)) {
|
|
15978
|
+
activeCount = 1;
|
|
15979
|
+
for (const empName of employeeNames) {
|
|
15980
|
+
if (tmuxSessions.has(`${empName}-${exeSession}`)) activeCount++;
|
|
15981
|
+
}
|
|
15982
|
+
}
|
|
15983
|
+
const memoryCount = memoryCounts.get(name) ?? 0;
|
|
15984
|
+
const openTaskCount = openTaskCounts.get(name) ?? 0;
|
|
15985
|
+
const hasGit = projectDir ? existsSync22(join(projectDir, ".git")) : false;
|
|
15986
|
+
const type = hasGit ? "code" : memoryCount > 0 ? "code" : "automation";
|
|
15987
|
+
projectList.push({
|
|
15988
|
+
projectName: name,
|
|
15989
|
+
exeSession,
|
|
15990
|
+
projectDir,
|
|
15991
|
+
employeeCount: activeCount,
|
|
15992
|
+
activeCount,
|
|
15993
|
+
memoryCount,
|
|
15994
|
+
openTaskCount,
|
|
15995
|
+
status: activeCount > 0 ? "active" : "idle",
|
|
15996
|
+
type,
|
|
15997
|
+
recentTasks: recentTasksByProject.get(name) ?? []
|
|
15998
|
+
});
|
|
15999
|
+
}
|
|
16000
|
+
projectList.sort((a, b) => {
|
|
16001
|
+
if (a.activeCount > 0 && b.activeCount === 0) return -1;
|
|
16002
|
+
if (a.activeCount === 0 && b.activeCount > 0) return 1;
|
|
16003
|
+
return b.memoryCount - a.memoryCount;
|
|
15821
16004
|
});
|
|
15822
|
-
|
|
15823
|
-
|
|
15824
|
-
|
|
15825
|
-
|
|
15826
|
-
|
|
15827
|
-
|
|
15828
|
-
|
|
15829
|
-
setHealth((h) => ({ ...h, memories: Number(result.rows[0]?.cnt ?? 0) }));
|
|
16005
|
+
setProjects(projectList);
|
|
16006
|
+
const totalResult = await client.execute("SELECT COUNT(*) as cnt FROM memories");
|
|
16007
|
+
setHealth((h) => ({ ...h, memories: Number(totalResult.rows[0]?.cnt ?? 0) }));
|
|
16008
|
+
try {
|
|
16009
|
+
const pidPath = join(process.env.HOME ?? "", ".exe-os", "exed.pid");
|
|
16010
|
+
setHealth((h) => ({ ...h, daemon: existsSync22(pidPath) ? "running" : "stopped" }));
|
|
16011
|
+
} catch {
|
|
15830
16012
|
}
|
|
15831
|
-
|
|
15832
|
-
|
|
15833
|
-
|
|
15834
|
-
|
|
15835
|
-
|
|
15836
|
-
|
|
15837
|
-
|
|
15838
|
-
|
|
15839
|
-
|
|
15840
|
-
const client = getClient2();
|
|
15841
|
-
if (client) {
|
|
15842
|
-
const activityResult = await client.execute(
|
|
15843
|
-
"SELECT agent_id, tool_name, project_name, created_at, text FROM memories ORDER BY created_at DESC LIMIT 20"
|
|
15844
|
-
);
|
|
15845
|
-
if (activityResult.rows.length > 0) {
|
|
15846
|
-
setActivity(activityResult.rows.slice(0, 8).map((r) => ({
|
|
15847
|
-
time: new Date(String(r.created_at)).toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit", hour12: false }),
|
|
15848
|
-
agent: String(r.agent_id ?? "system"),
|
|
15849
|
-
action: String(r.text ?? "").slice(0, 60)
|
|
15850
|
-
})));
|
|
15851
|
-
}
|
|
16013
|
+
const activityResult = await client.execute(
|
|
16014
|
+
"SELECT agent_id, tool_name, project_name, created_at, text FROM memories ORDER BY created_at DESC LIMIT 20"
|
|
16015
|
+
);
|
|
16016
|
+
if (activityResult.rows.length > 0) {
|
|
16017
|
+
setActivity(activityResult.rows.slice(0, 8).map((r) => ({
|
|
16018
|
+
time: new Date(String(r.created_at)).toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit", hour12: false }),
|
|
16019
|
+
agent: String(r.agent_id ?? "system"),
|
|
16020
|
+
action: String(r.text ?? "").slice(0, 60)
|
|
16021
|
+
})));
|
|
15852
16022
|
}
|
|
15853
16023
|
} catch {
|
|
16024
|
+
setDbError(true);
|
|
16025
|
+
} finally {
|
|
16026
|
+
setLoading(false);
|
|
15854
16027
|
}
|
|
15855
|
-
}
|
|
15856
|
-
setDbError(true);
|
|
15857
|
-
} finally {
|
|
15858
|
-
setLoading(false);
|
|
15859
|
-
}
|
|
16028
|
+
});
|
|
15860
16029
|
}
|
|
15861
16030
|
const daemonColor = health.daemon === "running" ? "green" : health.daemon === "stopped" ? "red" : "gray";
|
|
15862
16031
|
const handleChatSubmit = useCallback4((value) => {
|
|
@@ -15948,7 +16117,7 @@ function CommandCenterView({
|
|
|
15948
16117
|
] }),
|
|
15949
16118
|
/* @__PURE__ */ jsx7(Text, { color: "#6B4C9A", children: "\u2191\u2193 navigate | c to chat | Enter to open | Escape to detach" }),
|
|
15950
16119
|
/* @__PURE__ */ jsx7(Text, { children: " " }),
|
|
15951
|
-
loading ? /* @__PURE__ */ jsx7(Text, { color: "#6B4C9A", children: "Loading projects..." }) : dbError ? /* @__PURE__ */ jsx7(Text, { color: "#EF4444", children: "Database unavailable. Run exe-os setup to initialize." }) : rows.length === 0 ? /* @__PURE__ */ jsx7(Text, { color: "#6B4C9A", children: "
|
|
16120
|
+
loading ? /* @__PURE__ */ jsx7(Text, { color: "#6B4C9A", children: "Loading projects..." }) : dbError ? /* @__PURE__ */ jsx7(Text, { color: "#EF4444", children: "Database unavailable. Run exe-os setup to initialize." }) : rows.length === 0 ? /* @__PURE__ */ jsx7(Text, { color: "#6B4C9A", children: "No projects yet. Run exe-os in a project directory to get started." }) : (() => {
|
|
15952
16121
|
const sections = [];
|
|
15953
16122
|
let currentProjects = [];
|
|
15954
16123
|
let sectionKey = 0;
|
|
@@ -15978,9 +16147,9 @@ function CommandCenterView({
|
|
|
15978
16147
|
] })
|
|
15979
16148
|
] }),
|
|
15980
16149
|
/* @__PURE__ */ jsxs5(Text, { color: isSelected ? "#F0EDE8" : "#6B4C9A", children: [
|
|
15981
|
-
entry.
|
|
16150
|
+
entry.openTaskCount,
|
|
15982
16151
|
" ",
|
|
15983
|
-
entry.
|
|
16152
|
+
entry.openTaskCount === 1 ? "task" : "tasks",
|
|
15984
16153
|
" \xB7 ",
|
|
15985
16154
|
entry.memoryCount.toLocaleString(),
|
|
15986
16155
|
" memories"
|
|
@@ -16058,6 +16227,7 @@ var init_CommandCenter = __esm({
|
|
|
16058
16227
|
init_DemoContext();
|
|
16059
16228
|
init_demo_data();
|
|
16060
16229
|
init_useAgentLoop();
|
|
16230
|
+
init_employee_templates();
|
|
16061
16231
|
}
|
|
16062
16232
|
});
|
|
16063
16233
|
|
|
@@ -16182,7 +16352,7 @@ var init_TmuxPane = __esm({
|
|
|
16182
16352
|
});
|
|
16183
16353
|
|
|
16184
16354
|
// src/lib/task-router.ts
|
|
16185
|
-
import { randomUUID as
|
|
16355
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
16186
16356
|
function resolveBloomRouting(complexity, config = DEFAULT_BLOOM_CONFIG) {
|
|
16187
16357
|
const tier = config.complexityToTier[complexity];
|
|
16188
16358
|
const rule = config.tierRules[tier];
|
|
@@ -16834,9 +17004,15 @@ async function createTaskCore(input) {
|
|
|
16834
17004
|
}
|
|
16835
17005
|
}
|
|
16836
17006
|
const complexity = input.complexity ?? "standard";
|
|
17007
|
+
let sessionScope = null;
|
|
17008
|
+
try {
|
|
17009
|
+
const { resolveExeSession: resolveExeSession2 } = await Promise.resolve().then(() => (init_tmux_routing(), tmux_routing_exports));
|
|
17010
|
+
sessionScope = resolveExeSession2();
|
|
17011
|
+
} catch {
|
|
17012
|
+
}
|
|
16837
17013
|
await client.execute({
|
|
16838
|
-
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)
|
|
16839
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
17014
|
+
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, session_scope, created_at, updated_at)
|
|
17015
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
16840
17016
|
args: [
|
|
16841
17017
|
id,
|
|
16842
17018
|
input.title,
|
|
@@ -16855,6 +17031,7 @@ async function createTaskCore(input) {
|
|
|
16855
17031
|
input.budgetFallbackModel ?? null,
|
|
16856
17032
|
0,
|
|
16857
17033
|
null,
|
|
17034
|
+
sessionScope,
|
|
16858
17035
|
now,
|
|
16859
17036
|
now
|
|
16860
17037
|
]
|
|
@@ -16899,9 +17076,18 @@ async function listTasks(input) {
|
|
|
16899
17076
|
conditions.push("priority = ?");
|
|
16900
17077
|
args2.push(input.priority);
|
|
16901
17078
|
}
|
|
17079
|
+
try {
|
|
17080
|
+
const { resolveExeSession: resolveExeSession2 } = await Promise.resolve().then(() => (init_tmux_routing(), tmux_routing_exports));
|
|
17081
|
+
const session = resolveExeSession2();
|
|
17082
|
+
if (session) {
|
|
17083
|
+
conditions.push("(session_scope IS NULL OR session_scope = ?)");
|
|
17084
|
+
args2.push(session);
|
|
17085
|
+
}
|
|
17086
|
+
} catch {
|
|
17087
|
+
}
|
|
16902
17088
|
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
16903
17089
|
const result = await client.execute({
|
|
16904
|
-
sql: `SELECT * FROM tasks ${where} ORDER BY CASE status WHEN 'blocked' THEN 0 WHEN 'in_progress' THEN 1 WHEN 'open' THEN 2 ELSE 3 END, priority ASC, created_at DESC`,
|
|
17090
|
+
sql: `SELECT * FROM tasks ${where} ORDER BY CASE status WHEN 'blocked' THEN 0 WHEN 'in_progress' THEN 1 WHEN 'open' THEN 2 ELSE 3 END, priority ASC, created_at DESC LIMIT 1000`,
|
|
16905
17091
|
args: args2
|
|
16906
17092
|
});
|
|
16907
17093
|
return result.rows.map((r) => ({
|
|
@@ -17122,6 +17308,34 @@ async function listPendingReviews(limit) {
|
|
|
17122
17308
|
});
|
|
17123
17309
|
return result.rows;
|
|
17124
17310
|
}
|
|
17311
|
+
async function cleanupOrphanedReviews() {
|
|
17312
|
+
const client = getClient();
|
|
17313
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
17314
|
+
const r1 = await client.execute({
|
|
17315
|
+
sql: `UPDATE tasks SET status = 'done', updated_at = ?
|
|
17316
|
+
WHERE status = 'needs_review'
|
|
17317
|
+
AND assigned_by = 'system'
|
|
17318
|
+
AND title LIKE 'Review:%'
|
|
17319
|
+
AND parent_task_id IN (SELECT id FROM tasks WHERE status IN ('done', 'cancelled'))`,
|
|
17320
|
+
args: [now]
|
|
17321
|
+
});
|
|
17322
|
+
const staleThreshold = new Date(Date.now() - 60 * 60 * 1e3).toISOString();
|
|
17323
|
+
const r2 = await client.execute({
|
|
17324
|
+
sql: `UPDATE tasks SET status = 'done', updated_at = ?
|
|
17325
|
+
WHERE status = 'needs_review'
|
|
17326
|
+
AND result IS NOT NULL
|
|
17327
|
+
AND updated_at < ?`,
|
|
17328
|
+
args: [now, staleThreshold]
|
|
17329
|
+
});
|
|
17330
|
+
const total = r1.rowsAffected + r2.rowsAffected;
|
|
17331
|
+
if (total > 0) {
|
|
17332
|
+
process.stderr.write(
|
|
17333
|
+
`[cleanup] Closed ${total} orphaned review(s): ${r1.rowsAffected} cascade + ${r2.rowsAffected} stale
|
|
17334
|
+
`
|
|
17335
|
+
);
|
|
17336
|
+
}
|
|
17337
|
+
return total;
|
|
17338
|
+
}
|
|
17125
17339
|
function getReviewChecklist(role, agent, taskSlug) {
|
|
17126
17340
|
const roleLower = role.toLowerCase();
|
|
17127
17341
|
if (roleLower.includes("engineer") || roleLower === "principal engineer") {
|
|
@@ -17235,6 +17449,7 @@ var init_tasks_review = __esm({
|
|
|
17235
17449
|
init_tasks_crud();
|
|
17236
17450
|
init_tmux_routing();
|
|
17237
17451
|
init_session_key();
|
|
17452
|
+
init_state_bus();
|
|
17238
17453
|
}
|
|
17239
17454
|
});
|
|
17240
17455
|
|
|
@@ -17399,13 +17614,12 @@ function assertSessionScope(actionType, targetProject) {
|
|
|
17399
17614
|
};
|
|
17400
17615
|
}
|
|
17401
17616
|
process.stderr.write(
|
|
17402
|
-
`[session-scope]
|
|
17617
|
+
`[session-scope] BLOCKED cross-project ${actionType}: session project="${currentProject}" \u2260 target project="${targetProject}"
|
|
17403
17618
|
`
|
|
17404
17619
|
);
|
|
17405
17620
|
return {
|
|
17406
|
-
allowed:
|
|
17407
|
-
|
|
17408
|
-
reason: "cross_session_granted",
|
|
17621
|
+
allowed: false,
|
|
17622
|
+
reason: "cross_session_denied",
|
|
17409
17623
|
currentProject,
|
|
17410
17624
|
targetProject,
|
|
17411
17625
|
targetSession: findSessionForProject(targetProject)?.windowName
|
|
@@ -17431,8 +17645,9 @@ async function dispatchTaskToEmployee(input) {
|
|
|
17431
17645
|
try {
|
|
17432
17646
|
const { assertSessionScope: assertSessionScope2 } = (init_session_scope(), __toCommonJS(session_scope_exports));
|
|
17433
17647
|
const check = assertSessionScope2("dispatch_task", input.projectName);
|
|
17434
|
-
if (check.reason === "
|
|
17648
|
+
if (check.reason === "cross_session_denied") {
|
|
17435
17649
|
crossProject = true;
|
|
17650
|
+
return { dispatched: "skipped", crossProject: true };
|
|
17436
17651
|
}
|
|
17437
17652
|
} catch {
|
|
17438
17653
|
}
|
|
@@ -17801,6 +18016,7 @@ var init_skill_learning = __esm({
|
|
|
17801
18016
|
// src/lib/tasks.ts
|
|
17802
18017
|
var tasks_exports = {};
|
|
17803
18018
|
__export(tasks_exports, {
|
|
18019
|
+
cleanupOrphanedReviews: () => cleanupOrphanedReviews,
|
|
17804
18020
|
countNewPendingReviewsSince: () => countNewPendingReviewsSince,
|
|
17805
18021
|
countPendingReviews: () => countPendingReviews,
|
|
17806
18022
|
createTask: () => createTask,
|
|
@@ -17866,6 +18082,21 @@ async function updateTask(input) {
|
|
|
17866
18082
|
});
|
|
17867
18083
|
} catch {
|
|
17868
18084
|
}
|
|
18085
|
+
try {
|
|
18086
|
+
const client = getClient();
|
|
18087
|
+
const cascaded = await client.execute({
|
|
18088
|
+
sql: `UPDATE tasks SET status = 'done', updated_at = ?
|
|
18089
|
+
WHERE parent_task_id = ? AND status = 'needs_review'`,
|
|
18090
|
+
args: [now, taskId]
|
|
18091
|
+
});
|
|
18092
|
+
if (cascaded.rowsAffected > 0) {
|
|
18093
|
+
process.stderr.write(
|
|
18094
|
+
`[cascade] Closed ${cascaded.rowsAffected} orphaned review task(s) for parent ${taskId}
|
|
18095
|
+
`
|
|
18096
|
+
);
|
|
18097
|
+
}
|
|
18098
|
+
} catch {
|
|
18099
|
+
}
|
|
17869
18100
|
}
|
|
17870
18101
|
const isTerminal = input.status === "done" || input.status === "needs_review";
|
|
17871
18102
|
if (isTerminal) {
|
|
@@ -17879,6 +18110,13 @@ async function updateTask(input) {
|
|
|
17879
18110
|
await cascadeUnblock(taskId, input.baseDir, now);
|
|
17880
18111
|
} catch {
|
|
17881
18112
|
}
|
|
18113
|
+
orgBus.emit({
|
|
18114
|
+
type: "task_completed",
|
|
18115
|
+
taskId,
|
|
18116
|
+
employee: String(row.assigned_to),
|
|
18117
|
+
result: input.result ?? "",
|
|
18118
|
+
timestamp: now
|
|
18119
|
+
});
|
|
17882
18120
|
if (row.parent_task_id) {
|
|
17883
18121
|
try {
|
|
17884
18122
|
await checkSubtaskCompletion(String(row.parent_task_id), String(row.project_name));
|
|
@@ -17946,6 +18184,7 @@ var init_tasks = __esm({
|
|
|
17946
18184
|
init_database();
|
|
17947
18185
|
init_config();
|
|
17948
18186
|
init_notifications();
|
|
18187
|
+
init_state_bus();
|
|
17949
18188
|
init_tasks_crud();
|
|
17950
18189
|
init_tasks_review();
|
|
17951
18190
|
init_tasks_crud();
|
|
@@ -18336,9 +18575,29 @@ function getMySession() {
|
|
|
18336
18575
|
return getTransport().getMySession();
|
|
18337
18576
|
}
|
|
18338
18577
|
function employeeSessionName(employee, exeSession, instance) {
|
|
18339
|
-
|
|
18340
|
-
|
|
18341
|
-
|
|
18578
|
+
if (!/^exe\d+$/.test(exeSession)) {
|
|
18579
|
+
const root = extractRootExe(exeSession);
|
|
18580
|
+
if (root) {
|
|
18581
|
+
process.stderr.write(
|
|
18582
|
+
`[tmux-routing] WARN: exeSession="${exeSession}" is not a root exe session, using "${root}" instead
|
|
18583
|
+
`
|
|
18584
|
+
);
|
|
18585
|
+
exeSession = root;
|
|
18586
|
+
} else {
|
|
18587
|
+
throw new Error(
|
|
18588
|
+
`Invalid exeSession "${exeSession}" \u2014 must be a root exe session (e.g., "exe1"), not an agent session`
|
|
18589
|
+
);
|
|
18590
|
+
}
|
|
18591
|
+
}
|
|
18592
|
+
const suffix = instance != null && instance > 0 ? String(instance) : "";
|
|
18593
|
+
const name = `${employee}${suffix}-${exeSession}`;
|
|
18594
|
+
if (!VALID_SESSION_NAME.test(name)) {
|
|
18595
|
+
throw new Error(
|
|
18596
|
+
`Invalid session name "${name}" \u2014 must match {agent}-exe{N} or {agent}{instance}-exe{N}`
|
|
18597
|
+
);
|
|
18598
|
+
}
|
|
18599
|
+
return name;
|
|
18600
|
+
}
|
|
18342
18601
|
function parseParentExe(sessionName, agentId) {
|
|
18343
18602
|
const escaped = agentId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
18344
18603
|
const regex = new RegExp(`^${escaped}\\d*-(.+)$`);
|
|
@@ -18577,6 +18836,22 @@ function ensureEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
18577
18836
|
error: `Error: pass employee name ('${bare}'), not session name ('${employeeName}')`
|
|
18578
18837
|
};
|
|
18579
18838
|
}
|
|
18839
|
+
if (!/^exe\d+$/.test(exeSession)) {
|
|
18840
|
+
const root = extractRootExe(exeSession);
|
|
18841
|
+
if (root) {
|
|
18842
|
+
process.stderr.write(
|
|
18843
|
+
`[ensureEmployee] WARN: caller passed exeSession="${exeSession}" (not a root exe). Auto-correcting to "${root}".
|
|
18844
|
+
`
|
|
18845
|
+
);
|
|
18846
|
+
exeSession = root;
|
|
18847
|
+
} else {
|
|
18848
|
+
return {
|
|
18849
|
+
status: "failed",
|
|
18850
|
+
sessionName: "",
|
|
18851
|
+
error: `Invalid exeSession "${exeSession}" \u2014 must be a root exe session (e.g., "exe1")`
|
|
18852
|
+
};
|
|
18853
|
+
}
|
|
18854
|
+
}
|
|
18580
18855
|
let effectiveInstance = opts?.instance;
|
|
18581
18856
|
if (effectiveInstance === void 0 && opts?.autoInstance) {
|
|
18582
18857
|
const free = findFreeInstance(
|
|
@@ -18823,7 +19098,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
18823
19098
|
releaseSpawnLock2(sessionName);
|
|
18824
19099
|
return { sessionName };
|
|
18825
19100
|
}
|
|
18826
|
-
var SPAWN_LOCK_DIR, SESSION_CACHE, BEHAVIORS_EXPORT_TIMEOUT_MS, VERIFY_PANE_LINES, INTERCOM_DEBOUNCE_MS, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS, BUSY_PATTERN;
|
|
19101
|
+
var SPAWN_LOCK_DIR, SESSION_CACHE, BEHAVIORS_EXPORT_TIMEOUT_MS, VALID_SESSION_NAME, VERIFY_PANE_LINES, INTERCOM_DEBOUNCE_MS, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS, BUSY_PATTERN;
|
|
18827
19102
|
var init_tmux_routing = __esm({
|
|
18828
19103
|
"src/lib/tmux-routing.ts"() {
|
|
18829
19104
|
"use strict";
|
|
@@ -18838,6 +19113,7 @@ var init_tmux_routing = __esm({
|
|
|
18838
19113
|
SPAWN_LOCK_DIR = path30.join(os10.homedir(), ".exe-os", "spawn-locks");
|
|
18839
19114
|
SESSION_CACHE = path30.join(os10.homedir(), ".exe-os", "session-cache");
|
|
18840
19115
|
BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
|
|
19116
|
+
VALID_SESSION_NAME = /^[a-z]+-exe\d+$|^[a-z]+\d+-exe\d+$/;
|
|
18841
19117
|
VERIFY_PANE_LINES = 200;
|
|
18842
19118
|
INTERCOM_DEBOUNCE_MS = 3e4;
|
|
18843
19119
|
INTERCOM_LOG2 = path30.join(os10.homedir(), ".exe-os", "intercom.log");
|
|
@@ -19244,6 +19520,7 @@ function SessionsView({
|
|
|
19244
19520
|
const [viewingEmployee, setViewingEmployee] = useState9(null);
|
|
19245
19521
|
const [viewingProject, setViewingProject] = useState9(null);
|
|
19246
19522
|
const [loading, setLoading] = useState9(!demo);
|
|
19523
|
+
const [sessionError, setSessionError] = useState9(null);
|
|
19247
19524
|
const [tmuxAvailable, setTmuxAvailable] = useState9(true);
|
|
19248
19525
|
const orch = useOrchestrator(!demo);
|
|
19249
19526
|
const [carouselEmployees, setCarouselEmployees] = useState9([]);
|
|
@@ -19419,111 +19696,116 @@ function SessionsView({
|
|
|
19419
19696
|
return ACTIVE_PANE_PATTERN.test(lines.join("\n")) ? "active" : "idle";
|
|
19420
19697
|
}
|
|
19421
19698
|
async function loadSessions() {
|
|
19422
|
-
|
|
19423
|
-
|
|
19424
|
-
const { listTmuxSessions: listTmuxSessions2, inTmux: inTmux2, capturePaneLines: capturePaneLines2, parseActivity: parseActivity2 } = await Promise.resolve().then(() => (init_tmux_status(), tmux_status_exports));
|
|
19425
|
-
const { loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
19426
|
-
const { execSync: execSync13 } = await import("child_process");
|
|
19427
|
-
if (!inTmux2()) {
|
|
19428
|
-
setTmuxAvailable(false);
|
|
19429
|
-
setProjects([]);
|
|
19430
|
-
return;
|
|
19431
|
-
}
|
|
19432
|
-
setTmuxAvailable(true);
|
|
19433
|
-
const attachedMap = /* @__PURE__ */ new Map();
|
|
19699
|
+
const { withTrace: withTrace2 } = await Promise.resolve().then(() => (init_telemetry(), telemetry_exports));
|
|
19700
|
+
return withTrace2("tui.sessions.loadSessions", async () => {
|
|
19434
19701
|
try {
|
|
19435
|
-
const
|
|
19436
|
-
|
|
19437
|
-
|
|
19438
|
-
});
|
|
19439
|
-
|
|
19440
|
-
|
|
19441
|
-
|
|
19442
|
-
|
|
19702
|
+
const { listSessions: listSessions2 } = await Promise.resolve().then(() => (init_session_registry(), session_registry_exports));
|
|
19703
|
+
const { listTmuxSessions: listTmuxSessions2, inTmux: inTmux2, capturePaneLines: capturePaneLines2, parseActivity: parseActivity2 } = await Promise.resolve().then(() => (init_tmux_status(), tmux_status_exports));
|
|
19704
|
+
const { loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
19705
|
+
const { execSync: execSync13 } = await import("child_process");
|
|
19706
|
+
if (!inTmux2()) {
|
|
19707
|
+
setTmuxAvailable(false);
|
|
19708
|
+
setProjects([]);
|
|
19709
|
+
return;
|
|
19710
|
+
}
|
|
19711
|
+
setTmuxAvailable(true);
|
|
19712
|
+
const attachedMap = /* @__PURE__ */ new Map();
|
|
19713
|
+
try {
|
|
19714
|
+
const out = execSync13("tmux list-sessions -F '#{session_name}:#{session_attached}' 2>/dev/null", {
|
|
19715
|
+
encoding: "utf8",
|
|
19716
|
+
timeout: 3e3
|
|
19717
|
+
});
|
|
19718
|
+
for (const line of out.trim().split("\n").filter(Boolean)) {
|
|
19719
|
+
const sepIdx = line.lastIndexOf(":");
|
|
19720
|
+
if (sepIdx > 0) {
|
|
19721
|
+
attachedMap.set(line.slice(0, sepIdx), line.slice(sepIdx + 1) === "1");
|
|
19722
|
+
}
|
|
19443
19723
|
}
|
|
19724
|
+
} catch {
|
|
19444
19725
|
}
|
|
19445
|
-
|
|
19446
|
-
|
|
19447
|
-
|
|
19448
|
-
|
|
19449
|
-
|
|
19450
|
-
|
|
19451
|
-
|
|
19452
|
-
|
|
19453
|
-
|
|
19454
|
-
|
|
19455
|
-
|
|
19456
|
-
|
|
19457
|
-
|
|
19458
|
-
|
|
19459
|
-
|
|
19460
|
-
|
|
19461
|
-
|
|
19462
|
-
|
|
19463
|
-
|
|
19464
|
-
|
|
19465
|
-
|
|
19466
|
-
|
|
19467
|
-
|
|
19468
|
-
|
|
19469
|
-
exeStatus = statusFromPaneLines(exeLines);
|
|
19470
|
-
exeActivity = exeLines.length > 0 ? parseActivity2(exeLines) : "";
|
|
19471
|
-
}
|
|
19472
|
-
const employeeEntries = roster.filter((e) => e.name !== "exe").map((emp) => {
|
|
19473
|
-
const sessionName = `${emp.name}-${exeSession}`;
|
|
19474
|
-
const hasSession = tmuxSessions.has(sessionName);
|
|
19475
|
-
const isCrashed = !hasSession && orch.crashedSessions.includes(emp.name);
|
|
19476
|
-
if (isCrashed) {
|
|
19477
|
-
return {
|
|
19478
|
-
name: emp.name,
|
|
19479
|
-
role: emp.role,
|
|
19480
|
-
status: "crashed",
|
|
19481
|
-
sessionName,
|
|
19482
|
-
activity: "Dead session \u2014 has open tasks",
|
|
19483
|
-
attached: false
|
|
19484
|
-
};
|
|
19726
|
+
const registry = listSessions2();
|
|
19727
|
+
const tmuxSessions = new Set(listTmuxSessions2());
|
|
19728
|
+
const roster = await loadEmployees2();
|
|
19729
|
+
const exeSessions = /* @__PURE__ */ new Map();
|
|
19730
|
+
for (const entry of registry) {
|
|
19731
|
+
if (entry.agentId === "exe" && tmuxSessions.has(entry.windowName)) {
|
|
19732
|
+
exeSessions.set(entry.windowName, entry.projectDir);
|
|
19733
|
+
}
|
|
19734
|
+
}
|
|
19735
|
+
for (const s of tmuxSessions) {
|
|
19736
|
+
if (/^exe\d+$/.test(s) && !exeSessions.has(s)) {
|
|
19737
|
+
exeSessions.set(s, "");
|
|
19738
|
+
}
|
|
19739
|
+
}
|
|
19740
|
+
const projectList = [];
|
|
19741
|
+
for (const [exeSession, projectDir] of exeSessions) {
|
|
19742
|
+
const projectName = projectDir.split("/").filter(Boolean).pop() ?? exeSession;
|
|
19743
|
+
const exeHasSession = tmuxSessions.has(exeSession);
|
|
19744
|
+
let exeStatus = "offline";
|
|
19745
|
+
let exeActivity = "";
|
|
19746
|
+
if (exeHasSession) {
|
|
19747
|
+
const exeLines = capturePaneLines2(exeSession, 10);
|
|
19748
|
+
exeStatus = statusFromPaneLines(exeLines);
|
|
19749
|
+
exeActivity = exeLines.length > 0 ? parseActivity2(exeLines) : "";
|
|
19485
19750
|
}
|
|
19486
|
-
|
|
19751
|
+
const employeeEntries = roster.filter((e) => e.name !== "exe").map((emp) => {
|
|
19752
|
+
const sessionName = `${emp.name}-${exeSession}`;
|
|
19753
|
+
const hasSession = tmuxSessions.has(sessionName);
|
|
19754
|
+
const isCrashed = !hasSession && orch.crashedSessions.includes(emp.name);
|
|
19755
|
+
if (isCrashed) {
|
|
19756
|
+
return {
|
|
19757
|
+
name: emp.name,
|
|
19758
|
+
role: emp.role,
|
|
19759
|
+
status: "crashed",
|
|
19760
|
+
sessionName,
|
|
19761
|
+
activity: "Dead session \u2014 has open tasks",
|
|
19762
|
+
attached: false
|
|
19763
|
+
};
|
|
19764
|
+
}
|
|
19765
|
+
if (!hasSession) {
|
|
19766
|
+
return {
|
|
19767
|
+
name: emp.name,
|
|
19768
|
+
role: emp.role,
|
|
19769
|
+
status: "offline",
|
|
19770
|
+
sessionName,
|
|
19771
|
+
activity: "",
|
|
19772
|
+
attached: false
|
|
19773
|
+
};
|
|
19774
|
+
}
|
|
19775
|
+
const lines = capturePaneLines2(sessionName, 10);
|
|
19487
19776
|
return {
|
|
19488
19777
|
name: emp.name,
|
|
19489
19778
|
role: emp.role,
|
|
19490
|
-
status:
|
|
19779
|
+
status: statusFromPaneLines(lines),
|
|
19491
19780
|
sessionName,
|
|
19492
|
-
activity: "",
|
|
19493
|
-
attached: false
|
|
19781
|
+
activity: lines.length > 0 ? parseActivity2(lines) : "",
|
|
19782
|
+
attached: attachedMap.get(sessionName) ?? false
|
|
19494
19783
|
};
|
|
19495
|
-
}
|
|
19496
|
-
const
|
|
19497
|
-
|
|
19498
|
-
|
|
19499
|
-
|
|
19500
|
-
|
|
19501
|
-
|
|
19502
|
-
|
|
19503
|
-
|
|
19504
|
-
|
|
19505
|
-
|
|
19506
|
-
|
|
19507
|
-
{
|
|
19508
|
-
|
|
19509
|
-
|
|
19510
|
-
|
|
19511
|
-
|
|
19512
|
-
|
|
19513
|
-
|
|
19514
|
-
|
|
19515
|
-
|
|
19516
|
-
|
|
19517
|
-
|
|
19518
|
-
}
|
|
19519
|
-
if (projectList.length === 0) {
|
|
19520
|
-
projectList.push({ projectName: "(no active sessions)", exeSession: "", projectDir: "", employees: [] });
|
|
19784
|
+
});
|
|
19785
|
+
const employees = [
|
|
19786
|
+
{
|
|
19787
|
+
name: "exe",
|
|
19788
|
+
role: "COO",
|
|
19789
|
+
status: exeStatus,
|
|
19790
|
+
sessionName: exeSession,
|
|
19791
|
+
activity: exeActivity,
|
|
19792
|
+
attached: attachedMap.get(exeSession) ?? false
|
|
19793
|
+
},
|
|
19794
|
+
...employeeEntries
|
|
19795
|
+
];
|
|
19796
|
+
projectList.push({ projectName, exeSession, projectDir, employees });
|
|
19797
|
+
}
|
|
19798
|
+
if (projectList.length === 0) {
|
|
19799
|
+
projectList.push({ projectName: "(no active sessions)", exeSession: "", projectDir: "", employees: [] });
|
|
19800
|
+
}
|
|
19801
|
+
setProjects(projectList);
|
|
19802
|
+
setSessionError(null);
|
|
19803
|
+
} catch (err) {
|
|
19804
|
+
setSessionError(err instanceof Error ? err.message : "Failed to query sessions.");
|
|
19805
|
+
} finally {
|
|
19806
|
+
setLoading(false);
|
|
19521
19807
|
}
|
|
19522
|
-
|
|
19523
|
-
} catch {
|
|
19524
|
-
} finally {
|
|
19525
|
-
setLoading(false);
|
|
19526
|
-
}
|
|
19808
|
+
});
|
|
19527
19809
|
}
|
|
19528
19810
|
if (viewingEmployee) {
|
|
19529
19811
|
const inCarousel = carouselEmployees.length > 0;
|
|
@@ -19605,7 +19887,10 @@ function SessionsView({
|
|
|
19605
19887
|
] })
|
|
19606
19888
|
] }),
|
|
19607
19889
|
/* @__PURE__ */ jsx9(Text, { children: " " }),
|
|
19608
|
-
loading ? /* @__PURE__ */ jsx9(Text, { color: "#6B4C9A", children: "Loading sessions..." }) :
|
|
19890
|
+
loading ? /* @__PURE__ */ jsx9(Text, { color: "#6B4C9A", children: "Loading sessions..." }) : sessionError ? /* @__PURE__ */ jsxs7(Text, { color: "#C91B00", children: [
|
|
19891
|
+
"Failed to query sessions: ",
|
|
19892
|
+
sessionError
|
|
19893
|
+
] }) : !tmuxAvailable ? /* @__PURE__ */ jsx9(Text, { color: "#3D3660", children: "tmux not available. Start a tmux session first to manage employees." }) : flatItems.length === 0 ? /* @__PURE__ */ jsx9(Text, { color: "#3D3660", children: "No active sessions. Create a task to spawn an employee." }) : flatItems.map((item, i) => {
|
|
19609
19894
|
const isSelected = i === selectedIdx;
|
|
19610
19895
|
const marker = isSelected ? "\u25B8 " : " ";
|
|
19611
19896
|
if (item.type === "project") {
|
|
@@ -19706,7 +19991,7 @@ function TasksView({ onBack }) {
|
|
|
19706
19991
|
const demo = useDemo();
|
|
19707
19992
|
const [allTasks, setAllTasks] = useState10([]);
|
|
19708
19993
|
const [loading, setLoading] = useState10(!demo);
|
|
19709
|
-
const [dbError, setDbError] = useState10(
|
|
19994
|
+
const [dbError, setDbError] = useState10(null);
|
|
19710
19995
|
const [selectedTask, setSelectedTask] = useState10(0);
|
|
19711
19996
|
const [showDetail, setShowDetail] = useState10(false);
|
|
19712
19997
|
const [statusFilter, setStatusFilter] = useState10("all");
|
|
@@ -19778,40 +20063,43 @@ function TasksView({ onBack }) {
|
|
|
19778
20063
|
}
|
|
19779
20064
|
});
|
|
19780
20065
|
async function loadTasks() {
|
|
19781
|
-
|
|
19782
|
-
|
|
19783
|
-
|
|
19784
|
-
|
|
19785
|
-
const
|
|
19786
|
-
|
|
20066
|
+
const { withTrace: withTrace2 } = await Promise.resolve().then(() => (init_telemetry(), telemetry_exports));
|
|
20067
|
+
return withTrace2("tui.tasks.loadTasks", async () => {
|
|
20068
|
+
try {
|
|
20069
|
+
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
20070
|
+
const client = getClient2();
|
|
20071
|
+
if (client) {
|
|
20072
|
+
const result = await client.execute(
|
|
20073
|
+
`SELECT id, title, priority, assigned_to, assigned_by, status, project_name, created_at, result
|
|
19787
20074
|
FROM tasks
|
|
19788
20075
|
ORDER BY
|
|
19789
20076
|
CASE status WHEN 'in_progress' THEN 0 WHEN 'open' THEN 1 WHEN 'blocked' THEN 2 WHEN 'needs_review' THEN 3 WHEN 'done' THEN 4 ELSE 5 END,
|
|
19790
20077
|
CASE priority WHEN 'p0' THEN 0 WHEN 'p1' THEN 1 WHEN 'p2' THEN 2 ELSE 3 END,
|
|
19791
20078
|
created_at DESC`
|
|
19792
|
-
|
|
19793
|
-
|
|
19794
|
-
|
|
19795
|
-
|
|
19796
|
-
|
|
19797
|
-
|
|
19798
|
-
|
|
19799
|
-
|
|
19800
|
-
|
|
19801
|
-
|
|
19802
|
-
|
|
19803
|
-
|
|
19804
|
-
|
|
19805
|
-
|
|
19806
|
-
|
|
19807
|
-
|
|
19808
|
-
|
|
20079
|
+
);
|
|
20080
|
+
setAllTasks(
|
|
20081
|
+
result.rows.map((r) => ({
|
|
20082
|
+
id: String(r.id ?? ""),
|
|
20083
|
+
priority: String(r.priority ?? "p2").toUpperCase(),
|
|
20084
|
+
title: String(r.title ?? ""),
|
|
20085
|
+
assignee: String(r.assigned_to ?? ""),
|
|
20086
|
+
assignedBy: String(r.assigned_by ?? ""),
|
|
20087
|
+
status: String(r.status ?? "open"),
|
|
20088
|
+
project: String(r.project_name ?? ""),
|
|
20089
|
+
createdAt: String(r.created_at ?? ""),
|
|
20090
|
+
result: String(r.result ?? "")
|
|
20091
|
+
}))
|
|
20092
|
+
);
|
|
20093
|
+
setDbError(null);
|
|
20094
|
+
} else {
|
|
20095
|
+
setDbError("Database client not initialized. Run exe-os setup.");
|
|
20096
|
+
}
|
|
20097
|
+
} catch (err) {
|
|
20098
|
+
setDbError(err instanceof Error ? err.message : "Unknown error");
|
|
20099
|
+
} finally {
|
|
20100
|
+
setLoading(false);
|
|
19809
20101
|
}
|
|
19810
|
-
}
|
|
19811
|
-
setDbError(true);
|
|
19812
|
-
} finally {
|
|
19813
|
-
setLoading(false);
|
|
19814
|
-
}
|
|
20102
|
+
});
|
|
19815
20103
|
}
|
|
19816
20104
|
const selected = taskRows[selectedTask]?.task;
|
|
19817
20105
|
if (showDetail && selected) {
|
|
@@ -19878,7 +20166,10 @@ function TasksView({ onBack }) {
|
|
|
19878
20166
|
filterLabel
|
|
19879
20167
|
] }),
|
|
19880
20168
|
/* @__PURE__ */ jsx10(Text, { children: " " }),
|
|
19881
|
-
loading ? /* @__PURE__ */ jsx10(Text, { color: "#6B4C9A", children: "Loading tasks..." }) : dbError ? /* @__PURE__ */
|
|
20169
|
+
loading ? /* @__PURE__ */ jsx10(Text, { color: "#6B4C9A", children: "Loading tasks..." }) : dbError ? /* @__PURE__ */ jsxs8(Text, { color: "#C91B00", children: [
|
|
20170
|
+
"Failed to load tasks: ",
|
|
20171
|
+
dbError
|
|
20172
|
+
] }) : allTasks.length === 0 ? /* @__PURE__ */ jsx10(Text, { color: "#3D3660", children: "No tasks. Create one with create_task." }) : filteredTasks.length === 0 ? /* @__PURE__ */ jsx10(Text, { color: "#3D3660", children: "No tasks match current filter." }) : displayRows.map((row, i) => {
|
|
19882
20173
|
if (row.type === "header") {
|
|
19883
20174
|
return /* @__PURE__ */ jsxs8(Box_default, { marginTop: i > 0 ? 1 : 0, children: [
|
|
19884
20175
|
/* @__PURE__ */ jsx10(Text, { bold: true, color: "#F0EDE8", children: row.project }),
|
|
@@ -20565,6 +20856,31 @@ function GatewayView({ onBack }) {
|
|
|
20565
20856
|
/* @__PURE__ */ jsx11(Text, { color: "#6B4C9A", children: "Loading gateway status..." })
|
|
20566
20857
|
] });
|
|
20567
20858
|
}
|
|
20859
|
+
if (!gateway.running && gateway.gatewayUrl && connectionStatus === "disconnected") {
|
|
20860
|
+
return /* @__PURE__ */ jsxs9(Box_default, { flexDirection: "column", flexGrow: 1, paddingX: 1, children: [
|
|
20861
|
+
/* @__PURE__ */ jsx11(Box_default, { borderStyle: "single", borderColor: "#3D3660", paddingX: 1, alignSelf: "flex-start", children: /* @__PURE__ */ jsx11(Text, { bold: true, children: "Gateway Monitor" }) }),
|
|
20862
|
+
/* @__PURE__ */ jsx11(Text, { children: " " }),
|
|
20863
|
+
/* @__PURE__ */ jsx11(Text, { color: "#C91B00", children: "Gateway connection failed." }),
|
|
20864
|
+
/* @__PURE__ */ jsx11(Text, { children: " " }),
|
|
20865
|
+
/* @__PURE__ */ jsxs9(Text, { color: "#6B4C9A", children: [
|
|
20866
|
+
"Gateway URL: ",
|
|
20867
|
+
/* @__PURE__ */ jsx11(Text, { color: "#F0EDE8", children: gateway.gatewayUrl })
|
|
20868
|
+
] }),
|
|
20869
|
+
/* @__PURE__ */ jsxs9(Text, { color: "#6B4C9A", children: [
|
|
20870
|
+
"Process: ",
|
|
20871
|
+
/* @__PURE__ */ jsx11(Text, { color: "#C91B00", children: "not running" })
|
|
20872
|
+
] }),
|
|
20873
|
+
/* @__PURE__ */ jsx11(Text, { children: " " }),
|
|
20874
|
+
/* @__PURE__ */ jsxs9(Text, { color: "#6B4C9A", children: [
|
|
20875
|
+
"Start the gateway: ",
|
|
20876
|
+
/* @__PURE__ */ jsx11(Text, { bold: true, children: "exe-os gateway" })
|
|
20877
|
+
] }),
|
|
20878
|
+
/* @__PURE__ */ jsxs9(Text, { color: "#6B4C9A", children: [
|
|
20879
|
+
"Or check your config: ",
|
|
20880
|
+
/* @__PURE__ */ jsx11(Text, { bold: true, children: "~/.exe-os/gateway.json" })
|
|
20881
|
+
] })
|
|
20882
|
+
] });
|
|
20883
|
+
}
|
|
20568
20884
|
if (!gateway.running && gateway.adapters.length === 0 && !gateway.gatewayUrl) {
|
|
20569
20885
|
return /* @__PURE__ */ jsxs9(Box_default, { flexDirection: "column", flexGrow: 1, paddingX: 1, children: [
|
|
20570
20886
|
/* @__PURE__ */ jsx11(Box_default, { borderStyle: "single", borderColor: "#3D3660", paddingX: 1, alignSelf: "flex-start", children: /* @__PURE__ */ jsx11(Text, { bold: true, children: "Gateway Monitor" }) }),
|
|
@@ -20851,14 +21167,30 @@ var init_agent_status = __esm({
|
|
|
20851
21167
|
// src/tui/views/Team.tsx
|
|
20852
21168
|
import React22, { useState as useState12, useEffect as useEffect14 } from "react";
|
|
20853
21169
|
import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
20854
|
-
function
|
|
21170
|
+
function roleBadgeColor(role) {
|
|
21171
|
+
switch (role.toLowerCase()) {
|
|
21172
|
+
case "coo":
|
|
21173
|
+
return "#F5D76E";
|
|
21174
|
+
// gold
|
|
21175
|
+
case "cto":
|
|
21176
|
+
return "#3B82F6";
|
|
21177
|
+
// blue
|
|
21178
|
+
case "cmo":
|
|
21179
|
+
return "#6B4C9A";
|
|
21180
|
+
// purple
|
|
21181
|
+
default:
|
|
21182
|
+
return "#F0EDE8";
|
|
21183
|
+
}
|
|
21184
|
+
}
|
|
21185
|
+
function TeamView({ onBack, onViewSessions }) {
|
|
20855
21186
|
const demo = useDemo();
|
|
20856
21187
|
const [members, setMembers] = useState12([]);
|
|
20857
21188
|
const [externals, setExternals] = useState12([]);
|
|
20858
21189
|
const [loading, setLoading] = useState12(!demo);
|
|
20859
|
-
const [dbError, setDbError] = useState12(
|
|
21190
|
+
const [dbError, setDbError] = useState12(null);
|
|
20860
21191
|
const [selectedIdx, setSelectedIdx] = useState12(0);
|
|
20861
21192
|
const [showDetail, setShowDetail] = useState12(false);
|
|
21193
|
+
const [showAddHint, setShowAddHint] = useState12(false);
|
|
20862
21194
|
const orch = useOrchestrator(!demo);
|
|
20863
21195
|
const orchEmployeeMap = new Map(orch.employees.map((e) => [e.name, e]));
|
|
20864
21196
|
const allItems = [...members, ...externals.map((e) => ({ ...e, activity: "", memoryCount: 0 }))];
|
|
@@ -20873,7 +21205,7 @@ function TeamView({ onBack }) {
|
|
|
20873
21205
|
const timer = setInterval(loadTeam, 5e3);
|
|
20874
21206
|
return () => clearInterval(timer);
|
|
20875
21207
|
}, []);
|
|
20876
|
-
use_input_default((
|
|
21208
|
+
use_input_default((input, key) => {
|
|
20877
21209
|
if (showDetail) {
|
|
20878
21210
|
if (key.escape) setShowDetail(false);
|
|
20879
21211
|
return;
|
|
@@ -20882,91 +21214,103 @@ function TeamView({ onBack }) {
|
|
|
20882
21214
|
onBack?.();
|
|
20883
21215
|
return;
|
|
20884
21216
|
}
|
|
21217
|
+
if (input === "a") {
|
|
21218
|
+
setShowAddHint(true);
|
|
21219
|
+
setTimeout(() => setShowAddHint(false), 3e3);
|
|
21220
|
+
return;
|
|
21221
|
+
}
|
|
21222
|
+
if (input === "s" && selected) {
|
|
21223
|
+
onViewSessions?.(selected.name);
|
|
21224
|
+
return;
|
|
21225
|
+
}
|
|
20885
21226
|
if (key.upArrow && selectedIdx > 0) setSelectedIdx(selectedIdx - 1);
|
|
20886
21227
|
if (key.downArrow && selectedIdx < allItems.length - 1) setSelectedIdx(selectedIdx + 1);
|
|
20887
21228
|
if (key.return && allItems.length > 0) setShowDetail(true);
|
|
20888
21229
|
});
|
|
20889
21230
|
async function loadTeam() {
|
|
20890
|
-
|
|
20891
|
-
|
|
20892
|
-
const roster = await loadEmployees2();
|
|
20893
|
-
let memoryCounts = /* @__PURE__ */ new Map();
|
|
20894
|
-
let projectsByEmployee = /* @__PURE__ */ new Map();
|
|
20895
|
-
let currentTaskByEmployee = /* @__PURE__ */ new Map();
|
|
21231
|
+
const { withTrace: withTrace2 } = await Promise.resolve().then(() => (init_telemetry(), telemetry_exports));
|
|
21232
|
+
return withTrace2("tui.team.loadTeam", async () => {
|
|
20896
21233
|
try {
|
|
20897
|
-
const {
|
|
20898
|
-
const
|
|
20899
|
-
|
|
20900
|
-
|
|
20901
|
-
|
|
20902
|
-
|
|
20903
|
-
}
|
|
20904
|
-
|
|
20905
|
-
|
|
20906
|
-
|
|
21234
|
+
const { loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
21235
|
+
const roster = await loadEmployees2();
|
|
21236
|
+
let memoryCounts = /* @__PURE__ */ new Map();
|
|
21237
|
+
let projectsByEmployee = /* @__PURE__ */ new Map();
|
|
21238
|
+
let currentTaskByEmployee = /* @__PURE__ */ new Map();
|
|
21239
|
+
try {
|
|
21240
|
+
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
21241
|
+
const client = getClient2();
|
|
21242
|
+
if (client) {
|
|
21243
|
+
const memResult = await client.execute("SELECT agent_id, COUNT(*) as cnt FROM memories GROUP BY agent_id");
|
|
21244
|
+
for (const row of memResult.rows) {
|
|
21245
|
+
memoryCounts.set(String(row.agent_id), Number(row.cnt));
|
|
21246
|
+
}
|
|
21247
|
+
for (const emp of roster) {
|
|
21248
|
+
const projResult = await client.execute({
|
|
21249
|
+
sql: `SELECT DISTINCT project_name,
|
|
20907
21250
|
MAX(CASE WHEN status = 'in_progress' THEN 1 WHEN status = 'open' THEN 2 ELSE 3 END) as urgency
|
|
20908
21251
|
FROM tasks WHERE assigned_to = ? AND status IN ('open','in_progress','done')
|
|
20909
21252
|
GROUP BY project_name ORDER BY urgency ASC LIMIT 5`,
|
|
20910
|
-
|
|
20911
|
-
|
|
20912
|
-
|
|
20913
|
-
|
|
20914
|
-
|
|
20915
|
-
|
|
20916
|
-
|
|
20917
|
-
|
|
20918
|
-
|
|
20919
|
-
|
|
20920
|
-
|
|
20921
|
-
|
|
20922
|
-
|
|
20923
|
-
|
|
20924
|
-
|
|
20925
|
-
|
|
20926
|
-
|
|
20927
|
-
|
|
21253
|
+
args: [emp.name]
|
|
21254
|
+
});
|
|
21255
|
+
const projects = projResult.rows.filter((r) => !DEPRECATED_PROJECTS.has(String(r.project_name))).map((r) => {
|
|
21256
|
+
const urgency = Number(r.urgency);
|
|
21257
|
+
let pStatus = "idle";
|
|
21258
|
+
if (urgency === 1) pStatus = "active";
|
|
21259
|
+
else if (urgency === 2) pStatus = "has_tasks";
|
|
21260
|
+
return { name: String(r.project_name), status: pStatus };
|
|
21261
|
+
});
|
|
21262
|
+
if (projects.length > 0) projectsByEmployee.set(emp.name, projects);
|
|
21263
|
+
}
|
|
21264
|
+
for (const emp of roster) {
|
|
21265
|
+
const taskResult = await client.execute({
|
|
21266
|
+
sql: "SELECT title FROM tasks WHERE assigned_to = ? AND status = 'in_progress' ORDER BY updated_at DESC LIMIT 1",
|
|
21267
|
+
args: [emp.name]
|
|
21268
|
+
});
|
|
21269
|
+
if (taskResult.rows.length > 0) {
|
|
21270
|
+
currentTaskByEmployee.set(emp.name, String(taskResult.rows[0].title));
|
|
21271
|
+
}
|
|
20928
21272
|
}
|
|
20929
21273
|
}
|
|
21274
|
+
} catch {
|
|
20930
21275
|
}
|
|
20931
|
-
|
|
20932
|
-
|
|
20933
|
-
|
|
20934
|
-
|
|
20935
|
-
|
|
20936
|
-
|
|
20937
|
-
|
|
20938
|
-
|
|
20939
|
-
|
|
20940
|
-
|
|
20941
|
-
|
|
20942
|
-
|
|
20943
|
-
|
|
20944
|
-
|
|
20945
|
-
|
|
20946
|
-
|
|
20947
|
-
|
|
20948
|
-
|
|
20949
|
-
|
|
20950
|
-
|
|
20951
|
-
|
|
20952
|
-
|
|
20953
|
-
|
|
20954
|
-
|
|
20955
|
-
|
|
20956
|
-
|
|
20957
|
-
|
|
20958
|
-
|
|
20959
|
-
|
|
20960
|
-
})));
|
|
21276
|
+
const teamData = roster.map((emp) => {
|
|
21277
|
+
const agentSt = getAgentStatus(emp.name);
|
|
21278
|
+
return {
|
|
21279
|
+
name: emp.name,
|
|
21280
|
+
role: emp.role,
|
|
21281
|
+
status: agentSt.label,
|
|
21282
|
+
activity: agentSt.label === "active" ? "Processing..." : "",
|
|
21283
|
+
memoryCount: memoryCounts.get(emp.name) ?? 0,
|
|
21284
|
+
projects: projectsByEmployee.get(emp.name),
|
|
21285
|
+
currentTask: currentTaskByEmployee.get(emp.name),
|
|
21286
|
+
sessionName: agentSt.session
|
|
21287
|
+
};
|
|
21288
|
+
});
|
|
21289
|
+
setMembers(teamData);
|
|
21290
|
+
setDbError(null);
|
|
21291
|
+
try {
|
|
21292
|
+
const { existsSync: existsSync22, readFileSync: readFileSync18 } = await import("fs");
|
|
21293
|
+
const { join } = await import("path");
|
|
21294
|
+
const home = process.env.HOME ?? "";
|
|
21295
|
+
const gatewayConfig = join(home, ".exe-os", "gateway.json");
|
|
21296
|
+
if (existsSync22(gatewayConfig)) {
|
|
21297
|
+
const raw = JSON.parse(readFileSync18(gatewayConfig, "utf8"));
|
|
21298
|
+
if (raw.agents && raw.agents.length > 0) {
|
|
21299
|
+
setExternals(raw.agents.map((a) => ({
|
|
21300
|
+
name: a.name,
|
|
21301
|
+
role: a.role ?? "external agent",
|
|
21302
|
+
status: "offline"
|
|
21303
|
+
})));
|
|
21304
|
+
}
|
|
20961
21305
|
}
|
|
21306
|
+
} catch {
|
|
20962
21307
|
}
|
|
20963
|
-
} catch {
|
|
21308
|
+
} catch (err) {
|
|
21309
|
+
setDbError(err instanceof Error ? err.message : "Unknown error");
|
|
21310
|
+
} finally {
|
|
21311
|
+
setLoading(false);
|
|
20964
21312
|
}
|
|
20965
|
-
}
|
|
20966
|
-
setDbError(true);
|
|
20967
|
-
} finally {
|
|
20968
|
-
setLoading(false);
|
|
20969
|
-
}
|
|
21313
|
+
});
|
|
20970
21314
|
}
|
|
20971
21315
|
const totalCount = members.length + externals.length;
|
|
20972
21316
|
const selected = allItems[selectedIdx];
|
|
@@ -20983,7 +21327,7 @@ function TeamView({ onBack }) {
|
|
|
20983
21327
|
/* @__PURE__ */ jsx12(Text, { children: " " }),
|
|
20984
21328
|
/* @__PURE__ */ jsxs10(Text, { children: [
|
|
20985
21329
|
"Role: ",
|
|
20986
|
-
/* @__PURE__ */ jsx12(Text, { bold: true, children: selected.role })
|
|
21330
|
+
/* @__PURE__ */ jsx12(Text, { bold: true, color: roleBadgeColor(selected.role), children: selected.role })
|
|
20987
21331
|
] }),
|
|
20988
21332
|
/* @__PURE__ */ jsxs10(Text, { children: [
|
|
20989
21333
|
"Status: ",
|
|
@@ -21012,8 +21356,9 @@ function TeamView({ onBack }) {
|
|
|
21012
21356
|
/* @__PURE__ */ jsx12(Box_default, { borderStyle: "single", borderColor: "#3D3660", paddingX: 1, alignSelf: "flex-start", children: /* @__PURE__ */ jsx12(Text, { bold: true, children: "Team Roster" }) }),
|
|
21013
21357
|
/* @__PURE__ */ jsxs10(Text, { color: "#6B4C9A", children: [
|
|
21014
21358
|
totalCount,
|
|
21015
|
-
" agents |
|
|
21359
|
+
" agents | \u2191\u2193 navigate | Enter details | a add | s sessions"
|
|
21016
21360
|
] }),
|
|
21361
|
+
showAddHint && /* @__PURE__ */ jsx12(Text, { color: "#F5D76E", children: "Run /exe-new-employee <name> from CLI to add an employee." }),
|
|
21017
21362
|
!demo && orch.pendingReviews > 0 && /* @__PURE__ */ jsxs10(Text, { color: "#6B4C9A", children: [
|
|
21018
21363
|
orch.pendingReviews,
|
|
21019
21364
|
" review(s) pending exe attention"
|
|
@@ -21021,7 +21366,10 @@ function TeamView({ onBack }) {
|
|
|
21021
21366
|
/* @__PURE__ */ jsx12(Text, { children: " " }),
|
|
21022
21367
|
/* @__PURE__ */ jsx12(Text, { bold: true, children: "INTERNAL" }),
|
|
21023
21368
|
/* @__PURE__ */ jsx12(Text, { children: " " }),
|
|
21024
|
-
loading ? /* @__PURE__ */ jsx12(Text, { color: "#6B4C9A", children: " Loading
|
|
21369
|
+
loading ? /* @__PURE__ */ jsx12(Text, { color: "#6B4C9A", children: " Loading employee roster..." }) : dbError ? /* @__PURE__ */ jsxs10(Text, { color: "#C91B00", children: [
|
|
21370
|
+
" Failed to load roster: ",
|
|
21371
|
+
dbError
|
|
21372
|
+
] }) : members.length === 0 ? /* @__PURE__ */ jsx12(Text, { color: "#3D3660", children: " No employees configured. Run /exe-new-employee." }) : /* @__PURE__ */ jsx12(Box_default, { flexDirection: "row", flexWrap: "wrap", gap: 1, children: members.map((m, i) => {
|
|
21025
21373
|
const isSelected = i === selectedIdx;
|
|
21026
21374
|
const orchEmp = orchEmployeeMap.get(m.name);
|
|
21027
21375
|
return /* @__PURE__ */ jsxs10(
|
|
@@ -21037,7 +21385,7 @@ function TeamView({ onBack }) {
|
|
|
21037
21385
|
/* @__PURE__ */ jsxs10(Box_default, { gap: 1, children: [
|
|
21038
21386
|
/* @__PURE__ */ jsx12(StatusDot, { status: m.status, showLabel: false }),
|
|
21039
21387
|
/* @__PURE__ */ jsx12(Text, { bold: true, color: isSelected ? "#F5D76E" : "#F0EDE8", children: m.name }),
|
|
21040
|
-
/* @__PURE__ */ jsxs10(Text, { color: isSelected ? "#F5D76E" :
|
|
21388
|
+
/* @__PURE__ */ jsxs10(Text, { color: isSelected ? "#F5D76E" : roleBadgeColor(m.role), children: [
|
|
21041
21389
|
"(",
|
|
21042
21390
|
m.role,
|
|
21043
21391
|
")"
|
|
@@ -21263,6 +21611,26 @@ var init_wiki_client = __esm({
|
|
|
21263
21611
|
import React23, { useState as useState13, useEffect as useEffect15 } from "react";
|
|
21264
21612
|
import TextInput2 from "ink-text-input";
|
|
21265
21613
|
import { Fragment as Fragment4, jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
21614
|
+
function agentColor(agentId) {
|
|
21615
|
+
switch (agentId.toLowerCase()) {
|
|
21616
|
+
case "exe":
|
|
21617
|
+
return "#F5D76E";
|
|
21618
|
+
case "yoshi":
|
|
21619
|
+
return "#3B82F6";
|
|
21620
|
+
case "mari":
|
|
21621
|
+
return "#6B4C9A";
|
|
21622
|
+
default:
|
|
21623
|
+
return "#F0EDE8";
|
|
21624
|
+
}
|
|
21625
|
+
}
|
|
21626
|
+
function formatTimeAgo(iso) {
|
|
21627
|
+
const diff2 = Date.now() - new Date(iso).getTime();
|
|
21628
|
+
const hours = Math.floor(diff2 / 36e5);
|
|
21629
|
+
if (hours < 1) return "just now";
|
|
21630
|
+
if (hours < 24) return `${hours}h ago`;
|
|
21631
|
+
const days = Math.floor(hours / 24);
|
|
21632
|
+
return `${days}d ago`;
|
|
21633
|
+
}
|
|
21266
21634
|
function WikiView({ onBack }) {
|
|
21267
21635
|
const demo = useDemo();
|
|
21268
21636
|
const [activePanel, setActivePanel] = useState13("Workspaces");
|
|
@@ -21273,6 +21641,12 @@ function WikiView({ onBack }) {
|
|
|
21273
21641
|
const [chatHistory, setChatHistory] = useState13([]);
|
|
21274
21642
|
const [chatInput, setChatInput] = useState13("");
|
|
21275
21643
|
const [chatFocused, setChatFocused] = useState13(false);
|
|
21644
|
+
const [searchMode, setSearchMode] = useState13(false);
|
|
21645
|
+
const [searchQuery, setSearchQuery] = useState13("");
|
|
21646
|
+
const [searchResults, setSearchResults] = useState13([]);
|
|
21647
|
+
const [searchLoading, setSearchLoading] = useState13(false);
|
|
21648
|
+
const [selectedResultIdx, setSelectedResultIdx] = useState13(0);
|
|
21649
|
+
const [expandedResultIdx, setExpandedResultIdx] = useState13(null);
|
|
21276
21650
|
const [loading, setLoading] = useState13(true);
|
|
21277
21651
|
const [connected, setConnected] = useState13(false);
|
|
21278
21652
|
const [wikiUrl, setWikiUrl] = useState13("");
|
|
@@ -21366,6 +21740,55 @@ function WikiView({ onBack }) {
|
|
|
21366
21740
|
setSending(false);
|
|
21367
21741
|
}
|
|
21368
21742
|
}
|
|
21743
|
+
async function searchMemories2(query) {
|
|
21744
|
+
if (!query.trim()) {
|
|
21745
|
+
setSearchResults([]);
|
|
21746
|
+
return;
|
|
21747
|
+
}
|
|
21748
|
+
if (demo) {
|
|
21749
|
+
const q = query.toLowerCase();
|
|
21750
|
+
setSearchResults(
|
|
21751
|
+
DEMO_SEARCH_RESULTS.filter((r) => r.rawText.toLowerCase().includes(q))
|
|
21752
|
+
);
|
|
21753
|
+
return;
|
|
21754
|
+
}
|
|
21755
|
+
setSearchLoading(true);
|
|
21756
|
+
try {
|
|
21757
|
+
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
21758
|
+
const client = getClient2();
|
|
21759
|
+
const result = await client.execute({
|
|
21760
|
+
sql: `SELECT id, agent_id, raw_text, timestamp, project_name
|
|
21761
|
+
FROM memories
|
|
21762
|
+
WHERE raw_text LIKE ? AND COALESCE(status, 'active') = 'active'
|
|
21763
|
+
ORDER BY timestamp DESC LIMIT 20`,
|
|
21764
|
+
args: [`%${query}%`]
|
|
21765
|
+
});
|
|
21766
|
+
setSearchResults(
|
|
21767
|
+
result.rows.map((r) => ({
|
|
21768
|
+
id: String(r.id),
|
|
21769
|
+
agentId: String(r.agent_id),
|
|
21770
|
+
rawText: String(r.raw_text),
|
|
21771
|
+
timestamp: String(r.timestamp),
|
|
21772
|
+
projectName: String(r.project_name ?? "")
|
|
21773
|
+
}))
|
|
21774
|
+
);
|
|
21775
|
+
} catch {
|
|
21776
|
+
setSearchResults([]);
|
|
21777
|
+
} finally {
|
|
21778
|
+
setSearchLoading(false);
|
|
21779
|
+
}
|
|
21780
|
+
}
|
|
21781
|
+
useEffect15(() => {
|
|
21782
|
+
if (!searchMode) return;
|
|
21783
|
+
const timer = setTimeout(() => {
|
|
21784
|
+
searchMemories2(searchQuery);
|
|
21785
|
+
}, 300);
|
|
21786
|
+
return () => clearTimeout(timer);
|
|
21787
|
+
}, [searchQuery, searchMode]);
|
|
21788
|
+
useEffect15(() => {
|
|
21789
|
+
setSelectedResultIdx(0);
|
|
21790
|
+
setExpandedResultIdx(null);
|
|
21791
|
+
}, [searchResults]);
|
|
21369
21792
|
async function selectWorkspace(idx) {
|
|
21370
21793
|
setSelectedWorkspaceIdx(idx);
|
|
21371
21794
|
const ws = workspaces[idx];
|
|
@@ -21386,6 +21809,32 @@ function WikiView({ onBack }) {
|
|
|
21386
21809
|
}
|
|
21387
21810
|
}
|
|
21388
21811
|
use_input_default((input, key) => {
|
|
21812
|
+
if (searchMode && !chatFocused) {
|
|
21813
|
+
if (key.escape) {
|
|
21814
|
+
setSearchMode(false);
|
|
21815
|
+
setSearchQuery("");
|
|
21816
|
+
setSearchResults([]);
|
|
21817
|
+
setExpandedResultIdx(null);
|
|
21818
|
+
return;
|
|
21819
|
+
}
|
|
21820
|
+
if (key.upArrow && selectedResultIdx > 0) {
|
|
21821
|
+
setSelectedResultIdx(selectedResultIdx - 1);
|
|
21822
|
+
setExpandedResultIdx(null);
|
|
21823
|
+
return;
|
|
21824
|
+
}
|
|
21825
|
+
if (key.downArrow && selectedResultIdx < searchResults.length - 1) {
|
|
21826
|
+
setSelectedResultIdx(selectedResultIdx + 1);
|
|
21827
|
+
setExpandedResultIdx(null);
|
|
21828
|
+
return;
|
|
21829
|
+
}
|
|
21830
|
+
if (key.return && searchResults.length > 0) {
|
|
21831
|
+
setExpandedResultIdx(
|
|
21832
|
+
expandedResultIdx === selectedResultIdx ? null : selectedResultIdx
|
|
21833
|
+
);
|
|
21834
|
+
return;
|
|
21835
|
+
}
|
|
21836
|
+
return;
|
|
21837
|
+
}
|
|
21389
21838
|
if (chatFocused) {
|
|
21390
21839
|
if (key.escape) {
|
|
21391
21840
|
setChatFocused(false);
|
|
@@ -21397,6 +21846,13 @@ function WikiView({ onBack }) {
|
|
|
21397
21846
|
}
|
|
21398
21847
|
return;
|
|
21399
21848
|
}
|
|
21849
|
+
if (input === "/" && activePanel !== "Chat") {
|
|
21850
|
+
setSearchMode(true);
|
|
21851
|
+
setSearchQuery("");
|
|
21852
|
+
setSearchResults(demo ? DEMO_SEARCH_RESULTS : []);
|
|
21853
|
+
setExpandedResultIdx(null);
|
|
21854
|
+
return;
|
|
21855
|
+
}
|
|
21400
21856
|
if (key.leftArrow) {
|
|
21401
21857
|
const panelIdx = PANELS.indexOf(activePanel);
|
|
21402
21858
|
if (panelIdx === 0) {
|
|
@@ -21474,9 +21930,53 @@ function WikiView({ onBack }) {
|
|
|
21474
21930
|
/* @__PURE__ */ jsx13(Text, { bold: true, children: selectedWs.name })
|
|
21475
21931
|
] }) : null
|
|
21476
21932
|
] }),
|
|
21477
|
-
/* @__PURE__ */ jsx13(Text, { color: "#6B4C9A", children: "\u2190\u2192 switch panels | \u2191\u2193 navigate | /
|
|
21933
|
+
/* @__PURE__ */ jsx13(Text, { color: "#6B4C9A", children: "\u2190\u2192 switch panels | \u2191\u2193 navigate | / search memories | Enter select" }),
|
|
21478
21934
|
/* @__PURE__ */ jsx13(Text, { children: " " }),
|
|
21479
|
-
/* @__PURE__ */ jsxs11(Box_default, {
|
|
21935
|
+
searchMode ? /* @__PURE__ */ jsxs11(Box_default, { flexDirection: "column", flexGrow: 1, children: [
|
|
21936
|
+
/* @__PURE__ */ jsxs11(Box_default, { paddingX: 1, children: [
|
|
21937
|
+
/* @__PURE__ */ jsx13(Text, { color: "#F5D76E", children: "Search: " }),
|
|
21938
|
+
/* @__PURE__ */ jsx13(
|
|
21939
|
+
TextInput2,
|
|
21940
|
+
{
|
|
21941
|
+
value: searchQuery,
|
|
21942
|
+
onChange: setSearchQuery,
|
|
21943
|
+
placeholder: "search memories...",
|
|
21944
|
+
focus: true
|
|
21945
|
+
}
|
|
21946
|
+
),
|
|
21947
|
+
/* @__PURE__ */ jsx13(Text, { color: "#6B4C9A", children: " (esc to close)" })
|
|
21948
|
+
] }),
|
|
21949
|
+
/* @__PURE__ */ jsx13(Text, { children: " " }),
|
|
21950
|
+
searchLoading ? /* @__PURE__ */ jsx13(Text, { color: "#6B4C9A", children: " Searching..." }) : searchResults.length === 0 && searchQuery.trim() ? /* @__PURE__ */ jsx13(Text, { color: "#6B4C9A", children: " No results found." }) : searchResults.length === 0 ? /* @__PURE__ */ jsx13(Text, { color: "#6B4C9A", children: " Type to search exe-os memories." }) : searchResults.map((result, i) => {
|
|
21951
|
+
const isSelected = i === selectedResultIdx;
|
|
21952
|
+
const isExpanded = i === expandedResultIdx;
|
|
21953
|
+
const snippet = result.rawText.slice(0, 80);
|
|
21954
|
+
return /* @__PURE__ */ jsxs11(Box_default, { flexDirection: "column", children: [
|
|
21955
|
+
/* @__PURE__ */ jsxs11(
|
|
21956
|
+
Text,
|
|
21957
|
+
{
|
|
21958
|
+
backgroundColor: isSelected ? "#6B4C9A" : void 0,
|
|
21959
|
+
color: isSelected ? "#F5D76E" : void 0,
|
|
21960
|
+
children: [
|
|
21961
|
+
" ",
|
|
21962
|
+
/* @__PURE__ */ jsx13(Text, { color: isSelected ? "#F5D76E" : agentColor(result.agentId), bold: true, children: result.agentId.padEnd(8) }),
|
|
21963
|
+
/* @__PURE__ */ jsxs11(Text, { color: isSelected ? "#F5D76E" : "#F0EDE8", children: [
|
|
21964
|
+
snippet,
|
|
21965
|
+
result.rawText.length > 80 ? "..." : ""
|
|
21966
|
+
] }),
|
|
21967
|
+
" ",
|
|
21968
|
+
/* @__PURE__ */ jsx13(Text, { color: isSelected ? "#F5D76E" : "#3D3660", dimColor: !isSelected, children: formatTimeAgo(result.timestamp) })
|
|
21969
|
+
]
|
|
21970
|
+
}
|
|
21971
|
+
),
|
|
21972
|
+
isExpanded ? /* @__PURE__ */ jsx13(Box_default, { paddingX: 4, marginBottom: 1, children: /* @__PURE__ */ jsx13(Text, { color: "#F0EDE8", wrap: "wrap", children: result.rawText }) }) : null
|
|
21973
|
+
] }, result.id);
|
|
21974
|
+
}),
|
|
21975
|
+
searchResults.length > 0 ? /* @__PURE__ */ jsxs11(Fragment4, { children: [
|
|
21976
|
+
/* @__PURE__ */ jsx13(Text, { children: " " }),
|
|
21977
|
+
/* @__PURE__ */ jsx13(Text, { color: "#3D3660", children: " \u2191\u2193 navigate | Enter expand | Esc close" })
|
|
21978
|
+
] }) : null
|
|
21979
|
+
] }) : /* @__PURE__ */ jsxs11(Box_default, { flexGrow: 1, gap: 1, children: [
|
|
21480
21980
|
/* @__PURE__ */ jsxs11(Box_default, { flexDirection: "column", width: "25%", children: [
|
|
21481
21981
|
/* @__PURE__ */ jsxs11(Text, { bold: true, backgroundColor: panelHeaderBg("Workspaces"), color: panelHeaderColor("Workspaces"), children: [
|
|
21482
21982
|
activePanel === "Workspaces" ? "\u25B8 " : " ",
|
|
@@ -21558,7 +22058,7 @@ function WikiView({ onBack }) {
|
|
|
21558
22058
|
] })
|
|
21559
22059
|
] });
|
|
21560
22060
|
}
|
|
21561
|
-
var PANELS, MAX_VISIBLE_MESSAGES;
|
|
22061
|
+
var PANELS, MAX_VISIBLE_MESSAGES, DEMO_SEARCH_RESULTS;
|
|
21562
22062
|
var init_Wiki = __esm({
|
|
21563
22063
|
async "src/tui/views/Wiki.tsx"() {
|
|
21564
22064
|
"use strict";
|
|
@@ -21567,53 +22067,48 @@ var init_Wiki = __esm({
|
|
|
21567
22067
|
init_demo_data();
|
|
21568
22068
|
PANELS = ["Workspaces", "Documents", "Chat"];
|
|
21569
22069
|
MAX_VISIBLE_MESSAGES = 12;
|
|
22070
|
+
DEMO_SEARCH_RESULTS = [
|
|
22071
|
+
{ id: "1", agentId: "yoshi", rawText: "Reviewed PR #42 \u2014 approved with minor comment on error handling pattern", timestamp: new Date(Date.now() - 2 * 36e5).toISOString(), projectName: "exe-os" },
|
|
22072
|
+
{ id: "2", agentId: "tom", rawText: "Implemented session routing with deterministic naming: agent-exeN convention", timestamp: new Date(Date.now() - 5 * 36e5).toISOString(), projectName: "exe-os" },
|
|
22073
|
+
{ id: "3", agentId: "exe", rawText: "Status brief: 3 tasks completed, 1 blocked on wiki integration", timestamp: new Date(Date.now() - 8 * 36e5).toISOString(), projectName: "exe-os" },
|
|
22074
|
+
{ id: "4", agentId: "mari", rawText: "Created brand guidelines document \u2014 Exe Foundry Bold design system", timestamp: new Date(Date.now() - 24 * 36e5).toISOString(), projectName: "exe-os" },
|
|
22075
|
+
{ id: "5", agentId: "tom", rawText: "Fixed CommandCenter project filtering \u2014 DB-first, no random directories", timestamp: new Date(Date.now() - 48 * 36e5).toISOString(), projectName: "exe-os" }
|
|
22076
|
+
];
|
|
21570
22077
|
}
|
|
21571
22078
|
});
|
|
21572
22079
|
|
|
21573
22080
|
// src/tui/views/Settings.tsx
|
|
21574
|
-
import React24, { useState as useState14, useEffect as useEffect16 } from "react";
|
|
22081
|
+
import React24, { useState as useState14, useEffect as useEffect16, useCallback as useCallback7 } from "react";
|
|
21575
22082
|
import { Fragment as Fragment5, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
22083
|
+
function maskSecret(value) {
|
|
22084
|
+
if (value.length <= 10) return "****";
|
|
22085
|
+
return `${value.slice(0, 6)}...${value.slice(-4)}`;
|
|
22086
|
+
}
|
|
21576
22087
|
function SettingsView({ onBack }) {
|
|
21577
22088
|
const [providers, setProviders] = useState14([]);
|
|
21578
|
-
const [
|
|
21579
|
-
|
|
21580
|
-
|
|
21581
|
-
|
|
21582
|
-
searchMode: "checking..."
|
|
21583
|
-
});
|
|
21584
|
-
const [runtime, setRuntime] = useState14({
|
|
21585
|
-
consolidation: true,
|
|
21586
|
-
consolidationModel: "...",
|
|
21587
|
-
skillLearning: true,
|
|
21588
|
-
skillThreshold: 3,
|
|
21589
|
-
skillModel: "...",
|
|
21590
|
-
failoverChain: ["anthropic", "opencode", "gemini", "openai"]
|
|
21591
|
-
});
|
|
21592
|
-
const [employeeModels, setEmployeeModels] = useState14([]);
|
|
22089
|
+
const [cloud, setCloud] = useState14({ configured: false, endpoint: "", apiKey: "" });
|
|
22090
|
+
const [license, setLicense] = useState14({ valid: false, plan: "checking...", expiresAt: null, deviceLimit: 0, employeeLimit: 0, memoryLimit: 0 });
|
|
22091
|
+
const [system, setSystem] = useState14({ daemon: "unknown", version: "...", dbPath: "...", embeddingModel: "...", encryption: "checking..." });
|
|
22092
|
+
const [gateway, setGateway] = useState14({ adapters: [] });
|
|
21593
22093
|
const [selectedSection, setSelectedSection] = useState14(0);
|
|
21594
22094
|
const [loading, setLoading] = useState14(true);
|
|
21595
|
-
const
|
|
21596
|
-
|
|
21597
|
-
|
|
21598
|
-
|
|
21599
|
-
|
|
21600
|
-
|
|
21601
|
-
|
|
21602
|
-
|
|
21603
|
-
onBack?.();
|
|
21604
|
-
return;
|
|
21605
|
-
}
|
|
21606
|
-
if (key.upArrow && selectedSection > 0) setSelectedSection(selectedSection - 1);
|
|
21607
|
-
if (key.downArrow && selectedSection < SECTION_NAMES.length - 1) setSelectedSection(selectedSection + 1);
|
|
21608
|
-
});
|
|
21609
|
-
async function loadSettings() {
|
|
21610
|
-
const providerList = [
|
|
21611
|
-
{ name: "Anthropic", configured: !!process.env.ANTHROPIC_API_KEY, detail: process.env.ANTHROPIC_API_KEY ? "ANTHROPIC_API_KEY set" : "not configured" },
|
|
21612
|
-
{ name: "OpenCode", configured: !!process.env.OPENCODE_API_KEY, detail: process.env.OPENCODE_API_KEY ? "OPENCODE_API_KEY set" : "not configured" },
|
|
21613
|
-
{ name: "Gemini", configured: !!process.env.GEMINI_API_KEY, detail: process.env.GEMINI_API_KEY ? "GEMINI_API_KEY set" : "not configured" },
|
|
21614
|
-
{ name: "OpenAI", configured: !!process.env.OPENAI_API_KEY, detail: process.env.OPENAI_API_KEY ? "OPENAI_API_KEY set" : "not configured" },
|
|
21615
|
-
{ name: "Chutes", configured: !!process.env.CHUTES_API_KEY, detail: process.env.CHUTES_API_KEY ? "CHUTES_API_KEY set" : "not configured" }
|
|
22095
|
+
const loadSettings = useCallback7(async () => {
|
|
22096
|
+
setLoading(true);
|
|
22097
|
+
const envKeys = [
|
|
22098
|
+
["Anthropic", "ANTHROPIC_API_KEY"],
|
|
22099
|
+
["OpenCode", "OPENCODE_API_KEY"],
|
|
22100
|
+
["Gemini", "GEMINI_API_KEY"],
|
|
22101
|
+
["OpenAI", "OPENAI_API_KEY"],
|
|
22102
|
+
["Chutes", "CHUTES_API_KEY"]
|
|
21616
22103
|
];
|
|
22104
|
+
const providerList = envKeys.map(([name, envVar]) => {
|
|
22105
|
+
const val = process.env[envVar];
|
|
22106
|
+
return {
|
|
22107
|
+
name,
|
|
22108
|
+
configured: !!val,
|
|
22109
|
+
detail: val ? maskSecret(val) : "not configured"
|
|
22110
|
+
};
|
|
22111
|
+
});
|
|
21617
22112
|
try {
|
|
21618
22113
|
const { execSync: execSync13 } = await import("child_process");
|
|
21619
22114
|
execSync13("curl -s --max-time 1 http://localhost:11434/api/tags", { timeout: 2e3 });
|
|
@@ -21625,112 +22120,101 @@ function SettingsView({ onBack }) {
|
|
|
21625
22120
|
try {
|
|
21626
22121
|
const { existsSync: existsSync22 } = await import("fs");
|
|
21627
22122
|
const { join } = await import("path");
|
|
21628
|
-
const home = process.env.HOME ?? "";
|
|
21629
|
-
const hasKey = existsSync22(join(home, ".exe-os", "master.key"));
|
|
21630
22123
|
const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
21631
22124
|
const cfg = await loadConfig2();
|
|
21632
|
-
setMemory({
|
|
21633
|
-
encryption: hasKey ? "SQLCipher AES-256" : "not configured",
|
|
21634
|
-
embeddingModel: cfg.modelFile ?? "unknown",
|
|
21635
|
-
cloudSync: cfg.cloud ? "enabled" : "disabled",
|
|
21636
|
-
searchMode: cfg.searchMode ?? "hybrid"
|
|
21637
|
-
});
|
|
21638
|
-
const rawCfg = cfg;
|
|
21639
|
-
const chain = Array.isArray(rawCfg.failoverChain) ? rawCfg.failoverChain : ["anthropic", "opencode", "gemini", "openai"];
|
|
21640
|
-
setRuntime({
|
|
21641
|
-
consolidation: cfg.consolidationEnabled,
|
|
21642
|
-
consolidationModel: cfg.consolidationModel,
|
|
21643
|
-
skillLearning: cfg.skillLearning,
|
|
21644
|
-
skillThreshold: cfg.skillThreshold,
|
|
21645
|
-
skillModel: cfg.skillModel,
|
|
21646
|
-
failoverChain: chain
|
|
21647
|
-
});
|
|
21648
|
-
} catch {
|
|
21649
|
-
}
|
|
21650
|
-
try {
|
|
21651
|
-
const { loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
21652
|
-
const roster = await loadEmployees2();
|
|
21653
|
-
const { existsSync: existsSync22, readFileSync: readFileSync18 } = await import("fs");
|
|
21654
|
-
const { join } = await import("path");
|
|
21655
22125
|
const home = process.env.HOME ?? "";
|
|
21656
|
-
const
|
|
21657
|
-
|
|
21658
|
-
|
|
21659
|
-
|
|
21660
|
-
|
|
21661
|
-
|
|
21662
|
-
|
|
21663
|
-
|
|
21664
|
-
|
|
21665
|
-
}
|
|
22126
|
+
const hasKey = existsSync22(join(home, ".exe-os", "master.key"));
|
|
22127
|
+
if (cfg.cloud) {
|
|
22128
|
+
setCloud({
|
|
22129
|
+
configured: true,
|
|
22130
|
+
endpoint: cfg.cloud.endpoint,
|
|
22131
|
+
apiKey: maskSecret(cfg.cloud.apiKey)
|
|
22132
|
+
});
|
|
22133
|
+
} else {
|
|
22134
|
+
setCloud({ configured: false, endpoint: "", apiKey: "" });
|
|
21666
22135
|
}
|
|
21667
|
-
|
|
21668
|
-
|
|
21669
|
-
|
|
21670
|
-
|
|
21671
|
-
}
|
|
21672
|
-
} catch {
|
|
21673
|
-
}
|
|
21674
|
-
try {
|
|
21675
|
-
const { existsSync: existsSync22, readFileSync: readFileSync18 } = await import("fs");
|
|
21676
|
-
const { join } = await import("path");
|
|
21677
|
-
const home = process.env.HOME ?? "";
|
|
21678
|
-
const ccSettingsPath = join(home, ".claude", "settings.json");
|
|
21679
|
-
const installed = existsSync22(ccSettingsPath);
|
|
21680
|
-
let hooksWired = false;
|
|
21681
|
-
if (installed) {
|
|
21682
|
-
try {
|
|
21683
|
-
const settings = JSON.parse(readFileSync18(ccSettingsPath, "utf8"));
|
|
21684
|
-
const hooks = settings.hooks;
|
|
21685
|
-
if (hooks) {
|
|
21686
|
-
hooksWired = Object.values(hooks).flat().some((h) => h.command?.includes("exe-os") || h.command?.includes("exe-mem"));
|
|
21687
|
-
}
|
|
21688
|
-
} catch {
|
|
21689
|
-
}
|
|
22136
|
+
const pidPath = join(home, ".exe-os", "exed.pid");
|
|
22137
|
+
let daemon = "unknown";
|
|
22138
|
+
try {
|
|
22139
|
+
daemon = existsSync22(pidPath) ? "running" : "stopped";
|
|
22140
|
+
} catch {
|
|
21690
22141
|
}
|
|
21691
|
-
|
|
21692
|
-
|
|
21693
|
-
|
|
21694
|
-
|
|
21695
|
-
|
|
21696
|
-
|
|
21697
|
-
|
|
21698
|
-
|
|
21699
|
-
|
|
22142
|
+
let version = "unknown";
|
|
22143
|
+
try {
|
|
22144
|
+
const { readFileSync: readFileSync18 } = await import("fs");
|
|
22145
|
+
const { createRequire } = await import("module");
|
|
22146
|
+
const require2 = createRequire(import.meta.url);
|
|
22147
|
+
const pkgPath = require2.resolve("@askexenow/exe-os/package.json");
|
|
22148
|
+
const pkg = JSON.parse(readFileSync18(pkgPath, "utf8"));
|
|
22149
|
+
version = pkg.version;
|
|
22150
|
+
} catch {
|
|
21700
22151
|
try {
|
|
21701
|
-
const
|
|
21702
|
-
|
|
22152
|
+
const { readFileSync: readFileSync18 } = await import("fs");
|
|
22153
|
+
const { join: joinPath } = await import("path");
|
|
22154
|
+
const pkg = JSON.parse(readFileSync18(joinPath(process.cwd(), "package.json"), "utf8"));
|
|
22155
|
+
version = pkg.version;
|
|
21703
22156
|
} catch {
|
|
21704
|
-
setLicense({ valid: false, detail: "invalid license file" });
|
|
21705
22157
|
}
|
|
21706
|
-
} else {
|
|
21707
|
-
setLicense({ valid: false, detail: "no license" });
|
|
21708
22158
|
}
|
|
22159
|
+
setSystem({
|
|
22160
|
+
daemon,
|
|
22161
|
+
version,
|
|
22162
|
+
dbPath: cfg.dbPath,
|
|
22163
|
+
embeddingModel: cfg.modelFile ?? "unknown",
|
|
22164
|
+
encryption: hasKey ? "SQLCipher AES-256" : "not configured"
|
|
22165
|
+
});
|
|
21709
22166
|
} catch {
|
|
21710
22167
|
}
|
|
21711
22168
|
try {
|
|
21712
|
-
const {
|
|
21713
|
-
const
|
|
21714
|
-
|
|
21715
|
-
|
|
21716
|
-
|
|
21717
|
-
|
|
21718
|
-
|
|
21719
|
-
|
|
21720
|
-
|
|
22169
|
+
const { checkLicense: checkLicense2 } = await Promise.resolve().then(() => (init_license(), license_exports));
|
|
22170
|
+
const lic = await checkLicense2();
|
|
22171
|
+
setLicense({
|
|
22172
|
+
valid: lic.valid,
|
|
22173
|
+
plan: lic.plan.toUpperCase(),
|
|
22174
|
+
expiresAt: lic.expiresAt,
|
|
22175
|
+
deviceLimit: lic.deviceLimit,
|
|
22176
|
+
employeeLimit: lic.employeeLimit,
|
|
22177
|
+
memoryLimit: lic.memoryLimit
|
|
22178
|
+
});
|
|
21721
22179
|
} catch {
|
|
22180
|
+
setLicense({ valid: false, plan: "FREE", expiresAt: null, deviceLimit: 1, employeeLimit: 1, memoryLimit: 5e3 });
|
|
21722
22181
|
}
|
|
21723
|
-
|
|
21724
|
-
|
|
21725
|
-
|
|
21726
|
-
|
|
22182
|
+
const gatewayAdapters = [
|
|
22183
|
+
{ name: "WhatsApp", configured: !!process.env.WHATSAPP_API_TOKEN || !!process.env.WHATSAPP_PHONE_NUMBER_ID },
|
|
22184
|
+
{ name: "Telegram", configured: !!process.env.TELEGRAM_BOT_TOKEN },
|
|
22185
|
+
{ name: "Discord", configured: !!process.env.DISCORD_BOT_TOKEN },
|
|
22186
|
+
{ name: "Slack", configured: !!process.env.SLACK_BOT_TOKEN }
|
|
22187
|
+
];
|
|
22188
|
+
setGateway({ adapters: gatewayAdapters });
|
|
22189
|
+
setLoading(false);
|
|
22190
|
+
}, []);
|
|
22191
|
+
useEffect16(() => {
|
|
22192
|
+
loadSettings();
|
|
22193
|
+
}, [loadSettings]);
|
|
22194
|
+
use_input_default((input, key) => {
|
|
22195
|
+
if (key.leftArrow) {
|
|
22196
|
+
onBack?.();
|
|
22197
|
+
return;
|
|
22198
|
+
}
|
|
22199
|
+
if (key.upArrow && selectedSection > 0) setSelectedSection(selectedSection - 1);
|
|
22200
|
+
if (key.downArrow && selectedSection < SECTION_NAMES.length - 1) setSelectedSection(selectedSection + 1);
|
|
22201
|
+
if (input === "r") {
|
|
22202
|
+
loadSettings();
|
|
22203
|
+
}
|
|
22204
|
+
});
|
|
22205
|
+
const statusDot = (ok) => ok ? "\u2022" : "\u2022";
|
|
22206
|
+
const statusColor = (ok) => ok ? GREEN : DIM;
|
|
22207
|
+
const sectionColor = (idx) => selectedSection === idx ? YELLOW : void 0;
|
|
22208
|
+
const sectionBg = (idx) => selectedSection === idx ? DIM : void 0;
|
|
21727
22209
|
const sectionMarker = (idx) => selectedSection === idx ? "\u25B8 " : " ";
|
|
22210
|
+
const anyGateway = gateway.adapters.some((a) => a.configured);
|
|
22211
|
+
const formatLimit = (n) => n === -1 ? "unlimited" : n.toLocaleString();
|
|
21728
22212
|
return /* @__PURE__ */ jsxs12(Box_default, { flexDirection: "column", flexGrow: 1, paddingX: 1, children: [
|
|
21729
22213
|
/* @__PURE__ */ jsx14(Box_default, { borderStyle: "single", borderColor: "#3D3660", paddingX: 1, alignSelf: "flex-start", children: /* @__PURE__ */ jsx14(Text, { bold: true, children: "Settings" }) }),
|
|
21730
|
-
/* @__PURE__ */ jsx14(Text, { color:
|
|
22214
|
+
/* @__PURE__ */ jsx14(Text, { color: DIM, children: "\u2191\u2193 navigate sections r refresh" }),
|
|
21731
22215
|
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21732
22216
|
loading && /* @__PURE__ */ jsxs12(Fragment5, { children: [
|
|
21733
|
-
/* @__PURE__ */ jsx14(Text, { color:
|
|
22217
|
+
/* @__PURE__ */ jsx14(Text, { color: DIM, children: "Loading settings..." }),
|
|
21734
22218
|
/* @__PURE__ */ jsx14(Text, { children: " " })
|
|
21735
22219
|
] }),
|
|
21736
22220
|
/* @__PURE__ */ jsxs12(Text, { bold: true, backgroundColor: sectionBg(0), color: sectionColor(0), children: [
|
|
@@ -21740,6 +22224,8 @@ function SettingsView({ onBack }) {
|
|
|
21740
22224
|
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21741
22225
|
providers.map((p) => /* @__PURE__ */ jsxs12(Text, { children: [
|
|
21742
22226
|
" ",
|
|
22227
|
+
/* @__PURE__ */ jsx14(Text, { color: statusColor(p.configured), children: statusDot(p.configured) }),
|
|
22228
|
+
" ",
|
|
21743
22229
|
p.name,
|
|
21744
22230
|
": ",
|
|
21745
22231
|
/* @__PURE__ */ jsx14(Text, { color: statusColor(p.configured), children: p.detail })
|
|
@@ -21747,131 +22233,274 @@ function SettingsView({ onBack }) {
|
|
|
21747
22233
|
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21748
22234
|
/* @__PURE__ */ jsxs12(Text, { bold: true, backgroundColor: sectionBg(1), color: sectionColor(1), children: [
|
|
21749
22235
|
sectionMarker(1),
|
|
21750
|
-
"
|
|
22236
|
+
"Cloud Sync"
|
|
21751
22237
|
] }),
|
|
21752
22238
|
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21753
|
-
/* @__PURE__ */ jsxs12(
|
|
22239
|
+
cloud.configured ? /* @__PURE__ */ jsxs12(Fragment5, { children: [
|
|
22240
|
+
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
22241
|
+
" ",
|
|
22242
|
+
/* @__PURE__ */ jsx14(Text, { color: GREEN, children: statusDot(true) }),
|
|
22243
|
+
" Status: ",
|
|
22244
|
+
/* @__PURE__ */ jsx14(Text, { color: GREEN, children: "connected" })
|
|
22245
|
+
] }),
|
|
22246
|
+
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
22247
|
+
" ",
|
|
22248
|
+
"Endpoint: ",
|
|
22249
|
+
/* @__PURE__ */ jsx14(Text, { color: GREEN, children: cloud.endpoint })
|
|
22250
|
+
] }),
|
|
22251
|
+
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
22252
|
+
" ",
|
|
22253
|
+
"API key: ",
|
|
22254
|
+
/* @__PURE__ */ jsx14(Text, { color: DIM, children: cloud.apiKey })
|
|
22255
|
+
] })
|
|
22256
|
+
] }) : /* @__PURE__ */ jsxs12(Text, { children: [
|
|
21754
22257
|
" ",
|
|
21755
|
-
|
|
21756
|
-
|
|
22258
|
+
/* @__PURE__ */ jsx14(Text, { color: DIM, children: statusDot(false) }),
|
|
22259
|
+
" ",
|
|
22260
|
+
/* @__PURE__ */ jsx14(Text, { color: DIM, children: "Not configured \u2014 run /exe-cloud" })
|
|
21757
22261
|
] }),
|
|
21758
|
-
/* @__PURE__ */
|
|
21759
|
-
|
|
21760
|
-
|
|
21761
|
-
|
|
22262
|
+
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
22263
|
+
/* @__PURE__ */ jsxs12(Text, { bold: true, backgroundColor: sectionBg(2), color: sectionColor(2), children: [
|
|
22264
|
+
sectionMarker(2),
|
|
22265
|
+
"License"
|
|
21762
22266
|
] }),
|
|
22267
|
+
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21763
22268
|
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
21764
22269
|
" ",
|
|
21765
|
-
"
|
|
21766
|
-
/* @__PURE__ */ jsx14(Text, { color:
|
|
22270
|
+
"Plan: ",
|
|
22271
|
+
/* @__PURE__ */ jsx14(Text, { color: license.plan === "FREE" ? YELLOW : GREEN, children: license.plan })
|
|
21767
22272
|
] }),
|
|
21768
|
-
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
22273
|
+
license.expiresAt && /* @__PURE__ */ jsxs12(Text, { children: [
|
|
21769
22274
|
" ",
|
|
21770
|
-
"
|
|
21771
|
-
/* @__PURE__ */ jsx14(Text, { color:
|
|
21772
|
-
] }),
|
|
21773
|
-
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21774
|
-
/* @__PURE__ */ jsxs12(Text, { bold: true, backgroundColor: sectionBg(2), color: sectionColor(2), children: [
|
|
21775
|
-
sectionMarker(2),
|
|
21776
|
-
"Runtime"
|
|
22275
|
+
"Expires: ",
|
|
22276
|
+
/* @__PURE__ */ jsx14(Text, { color: GREEN, children: license.expiresAt.split("T")[0] })
|
|
21777
22277
|
] }),
|
|
21778
|
-
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21779
22278
|
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
21780
22279
|
" ",
|
|
21781
|
-
"
|
|
21782
|
-
/* @__PURE__ */ jsx14(Text, { color:
|
|
21783
|
-
" (",
|
|
21784
|
-
runtime.consolidationModel,
|
|
21785
|
-
")"
|
|
22280
|
+
"Devices: ",
|
|
22281
|
+
/* @__PURE__ */ jsx14(Text, { color: GREEN, children: formatLimit(license.deviceLimit) })
|
|
21786
22282
|
] }),
|
|
21787
22283
|
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
21788
22284
|
" ",
|
|
21789
|
-
"
|
|
21790
|
-
/* @__PURE__ */ jsx14(Text, { color:
|
|
21791
|
-
" (threshold: ",
|
|
21792
|
-
runtime.skillThreshold,
|
|
21793
|
-
")"
|
|
22285
|
+
"Employees: ",
|
|
22286
|
+
/* @__PURE__ */ jsx14(Text, { color: GREEN, children: formatLimit(license.employeeLimit) })
|
|
21794
22287
|
] }),
|
|
21795
22288
|
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
21796
22289
|
" ",
|
|
21797
|
-
"
|
|
21798
|
-
/* @__PURE__ */ jsx14(Text, { color:
|
|
22290
|
+
"Memory limit: ",
|
|
22291
|
+
/* @__PURE__ */ jsx14(Text, { color: GREEN, children: formatLimit(license.memoryLimit) })
|
|
21799
22292
|
] }),
|
|
21800
22293
|
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21801
22294
|
/* @__PURE__ */ jsxs12(Text, { bold: true, backgroundColor: sectionBg(3), color: sectionColor(3), children: [
|
|
21802
22295
|
sectionMarker(3),
|
|
21803
|
-
"
|
|
22296
|
+
"System"
|
|
21804
22297
|
] }),
|
|
21805
22298
|
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21806
|
-
|
|
21807
|
-
" ",
|
|
21808
|
-
"Loading..."
|
|
21809
|
-
] }) : employeeModels.length === 0 ? /* @__PURE__ */ jsxs12(Text, { color: "#6B4C9A", children: [
|
|
22299
|
+
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
21810
22300
|
" ",
|
|
21811
|
-
"
|
|
21812
|
-
|
|
22301
|
+
/* @__PURE__ */ jsx14(Text, { color: system.daemon === "running" ? GREEN : DIM, children: statusDot(system.daemon === "running") }),
|
|
22302
|
+
" Daemon: ",
|
|
22303
|
+
/* @__PURE__ */ jsx14(Text, { color: system.daemon === "running" ? GREEN : DIM, children: system.daemon })
|
|
22304
|
+
] }),
|
|
22305
|
+
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
21813
22306
|
" ",
|
|
21814
|
-
|
|
21815
|
-
|
|
21816
|
-
/* @__PURE__ */ jsx14(Text, { color: "#22C55E", children: e.model }),
|
|
21817
|
-
" ",
|
|
21818
|
-
/* @__PURE__ */ jsxs12(Text, { color: "#6B4C9A", children: [
|
|
21819
|
-
"via ",
|
|
21820
|
-
e.provider
|
|
21821
|
-
] })
|
|
21822
|
-
] }, e.name)),
|
|
21823
|
-
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21824
|
-
/* @__PURE__ */ jsxs12(Text, { bold: true, backgroundColor: sectionBg(4), color: sectionColor(4), children: [
|
|
21825
|
-
sectionMarker(4),
|
|
21826
|
-
"Integrations"
|
|
22307
|
+
"Version: ",
|
|
22308
|
+
/* @__PURE__ */ jsx14(Text, { color: GREEN, children: system.version })
|
|
21827
22309
|
] }),
|
|
21828
|
-
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21829
22310
|
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
21830
22311
|
" ",
|
|
21831
|
-
"
|
|
21832
|
-
/* @__PURE__ */ jsx14(Text, { color:
|
|
21833
|
-
claudeCode.installed && /* @__PURE__ */ jsxs12(Text, { color: claudeCode.hooksWired ? "#22C55E" : "#6B4C9A", children: [
|
|
21834
|
-
" \u2014 hooks ",
|
|
21835
|
-
claudeCode.hooksWired ? "wired" : "not wired"
|
|
21836
|
-
] })
|
|
22312
|
+
"Encryption: ",
|
|
22313
|
+
/* @__PURE__ */ jsx14(Text, { color: system.encryption.includes("AES") ? GREEN : DIM, children: system.encryption })
|
|
21837
22314
|
] }),
|
|
21838
22315
|
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
21839
22316
|
" ",
|
|
21840
|
-
"
|
|
21841
|
-
/* @__PURE__ */ jsx14(Text, { color:
|
|
22317
|
+
"Embedding: ",
|
|
22318
|
+
/* @__PURE__ */ jsx14(Text, { color: GREEN, children: system.embeddingModel })
|
|
21842
22319
|
] }),
|
|
21843
22320
|
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
21844
22321
|
" ",
|
|
21845
|
-
"
|
|
21846
|
-
/* @__PURE__ */ jsx14(Text, { color:
|
|
22322
|
+
"DB path: ",
|
|
22323
|
+
/* @__PURE__ */ jsx14(Text, { color: DIM, children: system.dbPath })
|
|
22324
|
+
] }),
|
|
22325
|
+
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
22326
|
+
/* @__PURE__ */ jsxs12(Text, { bold: true, backgroundColor: sectionBg(4), color: sectionColor(4), children: [
|
|
22327
|
+
sectionMarker(4),
|
|
22328
|
+
"Gateway"
|
|
22329
|
+
] }),
|
|
22330
|
+
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
22331
|
+
anyGateway ? gateway.adapters.map((a) => /* @__PURE__ */ jsxs12(Text, { children: [
|
|
22332
|
+
" ",
|
|
22333
|
+
/* @__PURE__ */ jsx14(Text, { color: statusColor(a.configured), children: statusDot(a.configured) }),
|
|
22334
|
+
" ",
|
|
22335
|
+
a.name,
|
|
22336
|
+
": ",
|
|
22337
|
+
/* @__PURE__ */ jsx14(Text, { color: statusColor(a.configured), children: a.configured ? "configured" : "not configured" })
|
|
22338
|
+
] }, a.name)) : /* @__PURE__ */ jsxs12(Text, { children: [
|
|
22339
|
+
" ",
|
|
22340
|
+
/* @__PURE__ */ jsx14(Text, { color: DIM, children: statusDot(false) }),
|
|
22341
|
+
" ",
|
|
22342
|
+
/* @__PURE__ */ jsx14(Text, { color: DIM, children: "No gateway configured" })
|
|
21847
22343
|
] })
|
|
21848
22344
|
] });
|
|
21849
22345
|
}
|
|
21850
|
-
var SECTION_NAMES;
|
|
22346
|
+
var SECTION_NAMES, GREEN, DIM, YELLOW;
|
|
21851
22347
|
var init_Settings = __esm({
|
|
21852
22348
|
async "src/tui/views/Settings.tsx"() {
|
|
21853
22349
|
"use strict";
|
|
21854
22350
|
await init_ink2();
|
|
21855
|
-
SECTION_NAMES = ["Providers", "
|
|
22351
|
+
SECTION_NAMES = ["Providers", "Cloud Sync", "License", "System", "Gateway"];
|
|
22352
|
+
GREEN = "#22C55E";
|
|
22353
|
+
DIM = "#6B4C9A";
|
|
22354
|
+
YELLOW = "#F5D76E";
|
|
22355
|
+
}
|
|
22356
|
+
});
|
|
22357
|
+
|
|
22358
|
+
// src/tui/views/DebugPanel.tsx
|
|
22359
|
+
import React25, { useState as useState15, useEffect as useEffect17 } from "react";
|
|
22360
|
+
import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
22361
|
+
function formatEvent(e) {
|
|
22362
|
+
switch (e.type) {
|
|
22363
|
+
case "task_completed":
|
|
22364
|
+
return `${e.employee}: "${e.result.slice(0, 60)}"`;
|
|
22365
|
+
case "review_created":
|
|
22366
|
+
return `${e.employee} \u2192 ${e.reviewer}`;
|
|
22367
|
+
case "employee_status":
|
|
22368
|
+
return `${e.employee}: ${e.status}`;
|
|
22369
|
+
case "memory_stored":
|
|
22370
|
+
return `${e.agentId} [${e.project}]`;
|
|
22371
|
+
case "session_started":
|
|
22372
|
+
return `${e.employee} (${e.sessionId.slice(0, 8)})`;
|
|
22373
|
+
case "session_ended":
|
|
22374
|
+
return `${e.employee} (${e.sessionId.slice(0, 8)})`;
|
|
22375
|
+
case "gateway_message":
|
|
22376
|
+
return `${e.platform}/${e.senderId} \u2192 ${e.botId}`;
|
|
22377
|
+
}
|
|
22378
|
+
}
|
|
22379
|
+
function DebugPanel() {
|
|
22380
|
+
const [events, setEvents] = useState15([]);
|
|
22381
|
+
useEffect17(() => {
|
|
22382
|
+
let counter = 0;
|
|
22383
|
+
const handler = (event) => {
|
|
22384
|
+
setEvents((prev) => {
|
|
22385
|
+
const next = [...prev, { event, id: counter++ }];
|
|
22386
|
+
return next.slice(-MAX_EVENTS);
|
|
22387
|
+
});
|
|
22388
|
+
};
|
|
22389
|
+
orgBus.onAny(handler);
|
|
22390
|
+
return () => {
|
|
22391
|
+
orgBus.offAny(handler);
|
|
22392
|
+
};
|
|
22393
|
+
}, []);
|
|
22394
|
+
return /* @__PURE__ */ jsxs13(Box_default, { flexDirection: "column", borderStyle: "single", borderColor: "#6B4C9A", flexGrow: 1, paddingX: 1, children: [
|
|
22395
|
+
/* @__PURE__ */ jsx15(Text, { bold: true, color: "#F5D76E", children: "Debug \u2014 Live Events" }),
|
|
22396
|
+
/* @__PURE__ */ jsx15(Text, { color: "#3D3660", children: "\u2500".repeat(40) }),
|
|
22397
|
+
events.length === 0 ? /* @__PURE__ */ jsx15(Text, { color: "#3D3660", children: "Waiting for events..." }) : events.slice(-DISPLAY_EVENTS).map(({ event, id }) => {
|
|
22398
|
+
const time = event.timestamp?.slice(11, 19) ?? "??:??:??";
|
|
22399
|
+
const color = EVENT_COLORS[event.type] ?? "#6B4C9A";
|
|
22400
|
+
const summary = formatEvent(event);
|
|
22401
|
+
return /* @__PURE__ */ jsxs13(Text, { color, children: [
|
|
22402
|
+
"[",
|
|
22403
|
+
time,
|
|
22404
|
+
"] ",
|
|
22405
|
+
event.type,
|
|
22406
|
+
" \u2014 ",
|
|
22407
|
+
summary
|
|
22408
|
+
] }, id);
|
|
22409
|
+
})
|
|
22410
|
+
] });
|
|
22411
|
+
}
|
|
22412
|
+
var MAX_EVENTS, DISPLAY_EVENTS, EVENT_COLORS;
|
|
22413
|
+
var init_DebugPanel = __esm({
|
|
22414
|
+
async "src/tui/views/DebugPanel.tsx"() {
|
|
22415
|
+
"use strict";
|
|
22416
|
+
await init_ink2();
|
|
22417
|
+
init_state_bus();
|
|
22418
|
+
MAX_EVENTS = 50;
|
|
22419
|
+
DISPLAY_EVENTS = 20;
|
|
22420
|
+
EVENT_COLORS = {
|
|
22421
|
+
task_completed: "#22C55E",
|
|
22422
|
+
review_created: "#F59E0B",
|
|
22423
|
+
employee_status: "#3B82F6",
|
|
22424
|
+
memory_stored: "#8B5CF6",
|
|
22425
|
+
session_started: "#06B6D4",
|
|
22426
|
+
session_ended: "#EF4444",
|
|
22427
|
+
gateway_message: "#EC4899"
|
|
22428
|
+
};
|
|
22429
|
+
}
|
|
22430
|
+
});
|
|
22431
|
+
|
|
22432
|
+
// src/tui/components/HelpOverlay.tsx
|
|
22433
|
+
import React26 from "react";
|
|
22434
|
+
import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
22435
|
+
function HelpOverlay({ tabName, shortcuts }) {
|
|
22436
|
+
return /* @__PURE__ */ jsxs14(
|
|
22437
|
+
Box_default,
|
|
22438
|
+
{
|
|
22439
|
+
flexDirection: "column",
|
|
22440
|
+
borderStyle: "double",
|
|
22441
|
+
borderColor: "#6B4C9A",
|
|
22442
|
+
paddingX: 2,
|
|
22443
|
+
paddingY: 1,
|
|
22444
|
+
width: 50,
|
|
22445
|
+
alignSelf: "center",
|
|
22446
|
+
children: [
|
|
22447
|
+
/* @__PURE__ */ jsxs14(Text, { bold: true, color: "#F5D76E", children: [
|
|
22448
|
+
"Keyboard Shortcuts \u2014 ",
|
|
22449
|
+
tabName
|
|
22450
|
+
] }),
|
|
22451
|
+
/* @__PURE__ */ jsx16(Text, { children: " " }),
|
|
22452
|
+
shortcuts.map((s, i) => /* @__PURE__ */ jsxs14(Box_default, { gap: 1, children: [
|
|
22453
|
+
/* @__PURE__ */ jsx16(Text, { color: "#F5D76E", bold: true, children: s.key.padEnd(10) }),
|
|
22454
|
+
/* @__PURE__ */ jsx16(Text, { color: "#F0EDE8", children: s.description })
|
|
22455
|
+
] }, i)),
|
|
22456
|
+
/* @__PURE__ */ jsx16(Text, { children: " " }),
|
|
22457
|
+
/* @__PURE__ */ jsx16(Text, { bold: true, color: "#F5D76E", children: "Global" }),
|
|
22458
|
+
/* @__PURE__ */ jsx16(Text, { children: " " }),
|
|
22459
|
+
/* @__PURE__ */ jsxs14(Box_default, { gap: 1, children: [
|
|
22460
|
+
/* @__PURE__ */ jsx16(Text, { color: "#F5D76E", bold: true, children: "1-7".padEnd(10) }),
|
|
22461
|
+
/* @__PURE__ */ jsx16(Text, { color: "#F0EDE8", children: "Switch tabs" })
|
|
22462
|
+
] }),
|
|
22463
|
+
/* @__PURE__ */ jsxs14(Box_default, { gap: 1, children: [
|
|
22464
|
+
/* @__PURE__ */ jsx16(Text, { color: "#F5D76E", bold: true, children: "q".padEnd(10) }),
|
|
22465
|
+
/* @__PURE__ */ jsx16(Text, { color: "#F0EDE8", children: "Quit" })
|
|
22466
|
+
] }),
|
|
22467
|
+
/* @__PURE__ */ jsxs14(Box_default, { gap: 1, children: [
|
|
22468
|
+
/* @__PURE__ */ jsx16(Text, { color: "#F5D76E", bold: true, children: "?".padEnd(10) }),
|
|
22469
|
+
/* @__PURE__ */ jsx16(Text, { color: "#F0EDE8", children: "Toggle this help" })
|
|
22470
|
+
] }),
|
|
22471
|
+
/* @__PURE__ */ jsxs14(Box_default, { gap: 1, children: [
|
|
22472
|
+
/* @__PURE__ */ jsx16(Text, { color: "#F5D76E", bold: true, children: "Esc".padEnd(10) }),
|
|
22473
|
+
/* @__PURE__ */ jsx16(Text, { color: "#F0EDE8", children: "Back to sidebar" })
|
|
22474
|
+
] }),
|
|
22475
|
+
/* @__PURE__ */ jsx16(Text, { children: " " }),
|
|
22476
|
+
/* @__PURE__ */ jsx16(Text, { color: "#6B4C9A", children: "Press ? to close" })
|
|
22477
|
+
]
|
|
22478
|
+
}
|
|
22479
|
+
);
|
|
22480
|
+
}
|
|
22481
|
+
var init_HelpOverlay = __esm({
|
|
22482
|
+
async "src/tui/components/HelpOverlay.tsx"() {
|
|
22483
|
+
"use strict";
|
|
22484
|
+
await init_ink2();
|
|
21856
22485
|
}
|
|
21857
22486
|
});
|
|
21858
22487
|
|
|
21859
22488
|
// src/tui/App.tsx
|
|
21860
22489
|
var App_exports = {};
|
|
21861
|
-
import { useState as
|
|
21862
|
-
import { jsx as
|
|
22490
|
+
import { useState as useState16, useEffect as useEffect18, useCallback as useCallback8 } from "react";
|
|
22491
|
+
import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
21863
22492
|
function App2() {
|
|
21864
|
-
const [section, setSection] =
|
|
22493
|
+
const [section, setSection] = useState16("command-center");
|
|
21865
22494
|
const { exit } = use_app_default();
|
|
21866
|
-
const [, forceUpdate] =
|
|
21867
|
-
|
|
22495
|
+
const [, forceUpdate] = useState16(0);
|
|
22496
|
+
useEffect18(() => {
|
|
21868
22497
|
const handleResize = () => forceUpdate((n) => n + 1);
|
|
21869
22498
|
process.stdout.on("resize", handleResize);
|
|
21870
22499
|
return () => {
|
|
21871
22500
|
process.stdout.off("resize", handleResize);
|
|
21872
22501
|
};
|
|
21873
22502
|
}, []);
|
|
21874
|
-
useMouseEvent(
|
|
22503
|
+
useMouseEvent(useCallback8((event) => {
|
|
21875
22504
|
if (event.button !== 0) return;
|
|
21876
22505
|
if (event.col <= 26) {
|
|
21877
22506
|
const tabIdx = event.row - 4;
|
|
@@ -21883,22 +22512,33 @@ function App2() {
|
|
|
21883
22512
|
setFocus("content");
|
|
21884
22513
|
}
|
|
21885
22514
|
}, []));
|
|
21886
|
-
const [focus, setFocus] =
|
|
21887
|
-
const [
|
|
21888
|
-
const
|
|
22515
|
+
const [focus, setFocus] = useState16("sidebar");
|
|
22516
|
+
const [showDebug, setShowDebug] = useState16(false);
|
|
22517
|
+
const [showHelp, setShowHelp] = useState16(false);
|
|
22518
|
+
const [focusedProject, setFocusedProject] = useState16(null);
|
|
22519
|
+
const handleSelectProject = useCallback8((projectName) => {
|
|
21889
22520
|
setFocusedProject(projectName);
|
|
21890
22521
|
setSection("sessions");
|
|
21891
22522
|
setFocus("content");
|
|
21892
22523
|
}, []);
|
|
21893
|
-
const handleBackToCommandCenter =
|
|
22524
|
+
const handleBackToCommandCenter = useCallback8(() => {
|
|
21894
22525
|
setSection("command-center");
|
|
21895
22526
|
setFocus("sidebar");
|
|
21896
22527
|
}, []);
|
|
21897
22528
|
use_input_default((input, key) => {
|
|
22529
|
+
if (input === "?" || key.shift && input === "/") {
|
|
22530
|
+
setShowHelp((prev) => !prev);
|
|
22531
|
+
return;
|
|
22532
|
+
}
|
|
21898
22533
|
const idx = parseInt(input, 10);
|
|
21899
22534
|
if (idx >= 1 && idx <= SECTIONS.length) {
|
|
21900
22535
|
setSection(SECTIONS[idx - 1].key);
|
|
21901
22536
|
setFocus("sidebar");
|
|
22537
|
+
setShowHelp(false);
|
|
22538
|
+
return;
|
|
22539
|
+
}
|
|
22540
|
+
if (input === "d" && !key.ctrl) {
|
|
22541
|
+
setShowDebug((prev) => !prev);
|
|
21902
22542
|
return;
|
|
21903
22543
|
}
|
|
21904
22544
|
if (input === "q" && !key.ctrl) {
|
|
@@ -21926,27 +22566,37 @@ function App2() {
|
|
|
21926
22566
|
}
|
|
21927
22567
|
}
|
|
21928
22568
|
});
|
|
21929
|
-
const consumeFocusedProject =
|
|
22569
|
+
const consumeFocusedProject = useCallback8(() => {
|
|
21930
22570
|
setFocusedProject(null);
|
|
21931
22571
|
}, []);
|
|
21932
22572
|
const views = {
|
|
21933
|
-
"command-center": /* @__PURE__ */
|
|
21934
|
-
sessions: /* @__PURE__ */
|
|
21935
|
-
tasks: /* @__PURE__ */
|
|
21936
|
-
team: /* @__PURE__ */
|
|
21937
|
-
|
|
21938
|
-
|
|
21939
|
-
|
|
22573
|
+
"command-center": /* @__PURE__ */ jsx17(CommandCenterView, { onSelectProject: handleSelectProject, isFocused: focus === "content" && section === "command-center", onBack: () => setFocus("sidebar") }),
|
|
22574
|
+
sessions: /* @__PURE__ */ jsx17(SessionsView, { initialProject: focusedProject, onConsumeInitialProject: consumeFocusedProject, onBackToCommandCenter: handleBackToCommandCenter, onBack: () => setFocus("sidebar") }),
|
|
22575
|
+
tasks: /* @__PURE__ */ jsx17(TasksView, { onBack: () => setFocus("sidebar") }),
|
|
22576
|
+
team: /* @__PURE__ */ jsx17(TeamView, { onBack: () => setFocus("sidebar"), onViewSessions: (name) => {
|
|
22577
|
+
setFocusedProject(name);
|
|
22578
|
+
setSection("sessions");
|
|
22579
|
+
setFocus("content");
|
|
22580
|
+
} }),
|
|
22581
|
+
gateway: /* @__PURE__ */ jsx17(GatewayView, { onBack: () => setFocus("sidebar") }),
|
|
22582
|
+
wiki: /* @__PURE__ */ jsx17(WikiView, { onBack: () => setFocus("sidebar") }),
|
|
22583
|
+
settings: /* @__PURE__ */ jsx17(SettingsView, { onBack: () => setFocus("sidebar") })
|
|
21940
22584
|
};
|
|
21941
|
-
return /* @__PURE__ */
|
|
21942
|
-
/* @__PURE__ */
|
|
21943
|
-
/* @__PURE__ */
|
|
21944
|
-
|
|
22585
|
+
return /* @__PURE__ */ jsx17(ErrorBoundary2, { children: /* @__PURE__ */ jsx17(AlternateScreen, { children: /* @__PURE__ */ jsx17(DemoProvider, { demo: isDemo, children: /* @__PURE__ */ jsxs15(Box_default, { flexDirection: "column", flexGrow: 1, children: [
|
|
22586
|
+
/* @__PURE__ */ jsxs15(Box_default, { flexGrow: 1, children: [
|
|
22587
|
+
/* @__PURE__ */ jsx17(Sidebar, { active: section, onSelect: setSection, onQuit: exit, focused: focus === "sidebar" }),
|
|
22588
|
+
showHelp ? /* @__PURE__ */ jsx17(
|
|
22589
|
+
HelpOverlay,
|
|
22590
|
+
{
|
|
22591
|
+
tabName: TAB_SHORTCUTS[section].name,
|
|
22592
|
+
shortcuts: TAB_SHORTCUTS[section].shortcuts
|
|
22593
|
+
}
|
|
22594
|
+
) : showDebug ? /* @__PURE__ */ jsx17(DebugPanel, {}) : views[section]
|
|
21945
22595
|
] }),
|
|
21946
|
-
/* @__PURE__ */
|
|
22596
|
+
/* @__PURE__ */ jsx17(Footer, {})
|
|
21947
22597
|
] }) }) }) });
|
|
21948
22598
|
}
|
|
21949
|
-
var isDemo;
|
|
22599
|
+
var TAB_SHORTCUTS, isDemo;
|
|
21950
22600
|
var init_App2 = __esm({
|
|
21951
22601
|
async "src/tui/App.tsx"() {
|
|
21952
22602
|
"use strict";
|
|
@@ -21964,6 +22614,73 @@ var init_App2 = __esm({
|
|
|
21964
22614
|
await init_Team();
|
|
21965
22615
|
await init_Wiki();
|
|
21966
22616
|
await init_Settings();
|
|
22617
|
+
await init_DebugPanel();
|
|
22618
|
+
await init_HelpOverlay();
|
|
22619
|
+
TAB_SHORTCUTS = {
|
|
22620
|
+
"command-center": {
|
|
22621
|
+
name: "Command Center",
|
|
22622
|
+
shortcuts: [
|
|
22623
|
+
{ key: "\u2191\u2193", description: "Navigate projects" },
|
|
22624
|
+
{ key: "Enter", description: "Select project" },
|
|
22625
|
+
{ key: "/", description: "Enter chat mode" },
|
|
22626
|
+
{ key: "n", description: "New task" }
|
|
22627
|
+
]
|
|
22628
|
+
},
|
|
22629
|
+
sessions: {
|
|
22630
|
+
name: "Sessions",
|
|
22631
|
+
shortcuts: [
|
|
22632
|
+
{ key: "\u2191\u2193", description: "Navigate sessions" },
|
|
22633
|
+
{ key: "Enter", description: "View session output" },
|
|
22634
|
+
{ key: "k", description: "Kill session" },
|
|
22635
|
+
{ key: "r", description: "Restart agent" }
|
|
22636
|
+
]
|
|
22637
|
+
},
|
|
22638
|
+
tasks: {
|
|
22639
|
+
name: "Tasks",
|
|
22640
|
+
shortcuts: [
|
|
22641
|
+
{ key: "\u2191\u2193", description: "Navigate tasks" },
|
|
22642
|
+
{ key: "Enter", description: "View task detail" },
|
|
22643
|
+
{ key: "n", description: "Create new task" },
|
|
22644
|
+
{ key: "f", description: "Cycle status filter" },
|
|
22645
|
+
{ key: "p", description: "Filter by priority" }
|
|
22646
|
+
]
|
|
22647
|
+
},
|
|
22648
|
+
team: {
|
|
22649
|
+
name: "Team",
|
|
22650
|
+
shortcuts: [
|
|
22651
|
+
{ key: "\u2191\u2193", description: "Navigate employees" },
|
|
22652
|
+
{ key: "Enter", description: "View detail" },
|
|
22653
|
+
{ key: "a", description: "Add employee" },
|
|
22654
|
+
{ key: "s", description: "View sessions" }
|
|
22655
|
+
]
|
|
22656
|
+
},
|
|
22657
|
+
gateway: {
|
|
22658
|
+
name: "Gateway",
|
|
22659
|
+
shortcuts: [
|
|
22660
|
+
{ key: "\u2191\u2193", description: "Navigate sections" },
|
|
22661
|
+
{ key: "f", description: "Cycle platform filter" },
|
|
22662
|
+
{ key: "\u2192", description: "Next conversation" },
|
|
22663
|
+
{ key: "r", description: "Reconnect" }
|
|
22664
|
+
]
|
|
22665
|
+
},
|
|
22666
|
+
wiki: {
|
|
22667
|
+
name: "Wiki",
|
|
22668
|
+
shortcuts: [
|
|
22669
|
+
{ key: "\u2190\u2192", description: "Switch panels" },
|
|
22670
|
+
{ key: "\u2191\u2193", description: "Navigate items" },
|
|
22671
|
+
{ key: "/", description: "Search memories" },
|
|
22672
|
+
{ key: "Enter", description: "Select" }
|
|
22673
|
+
]
|
|
22674
|
+
},
|
|
22675
|
+
settings: {
|
|
22676
|
+
name: "Settings",
|
|
22677
|
+
shortcuts: [
|
|
22678
|
+
{ key: "\u2191\u2193", description: "Navigate sections" },
|
|
22679
|
+
{ key: "Enter", description: "Edit setting" },
|
|
22680
|
+
{ key: "r", description: "Refresh status" }
|
|
22681
|
+
]
|
|
22682
|
+
}
|
|
22683
|
+
};
|
|
21967
22684
|
isDemo = process.argv.includes("--demo");
|
|
21968
22685
|
process.stderr.write(`[exe-tui] Terminal: ${TERMINAL_TYPE}
|
|
21969
22686
|
`);
|
|
@@ -22004,7 +22721,7 @@ var init_App2 = __esm({
|
|
|
22004
22721
|
stdin.unref = () => stdin;
|
|
22005
22722
|
}
|
|
22006
22723
|
}
|
|
22007
|
-
render_default(/* @__PURE__ */
|
|
22724
|
+
render_default(/* @__PURE__ */ jsx17(App2, {}));
|
|
22008
22725
|
}
|
|
22009
22726
|
});
|
|
22010
22727
|
|