@askexenow/exe-os 0.8.41 → 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 +1326 -655
- package/dist/bin/exe-agent.js +20 -1
- package/dist/bin/exe-assign.js +1503 -1343
- package/dist/bin/exe-boot.js +2508 -1802
- package/dist/bin/exe-call.js +39 -1
- package/dist/bin/exe-dispatch.js +39 -2
- package/dist/bin/exe-doctor.js +790 -633
- package/dist/bin/exe-export-behaviors.js +792 -637
- package/dist/bin/exe-forget.js +145 -0
- package/dist/bin/exe-gateway.js +2487 -1878
- 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 +9 -1
- 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 +147 -1
- package/dist/bin/exe-rename.js +23 -0
- package/dist/bin/exe-review.js +490 -327
- package/dist/bin/exe-search.js +154 -3
- package/dist/bin/exe-session-cleanup.js +2466 -413
- package/dist/bin/exe-status.js +474 -317
- package/dist/bin/exe-team.js +474 -317
- package/dist/bin/git-sweep.js +2690 -150
- 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 +47 -25
- package/dist/bin/shard-migrate.js +792 -637
- package/dist/bin/wiki-sync.js +794 -637
- package/dist/gateway/index.js +2504 -1895
- package/dist/hooks/bug-report-worker.js +2118 -576
- package/dist/hooks/commit-complete.js +2689 -149
- package/dist/hooks/error-recall.js +154 -3
- package/dist/hooks/ingest-worker.js +1420 -814
- 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 +1700 -1541
- package/dist/hooks/prompt-submit.js +2658 -1113
- package/dist/hooks/response-ingest-worker.js +151 -5
- package/dist/hooks/session-end.js +153 -2
- package/dist/hooks/session-start.js +154 -3
- package/dist/hooks/stop.js +151 -0
- package/dist/hooks/subagent-stop.js +151 -0
- package/dist/hooks/summary-worker.js +160 -6
- package/dist/index.js +278 -100
- package/dist/lib/cloud-sync.js +9 -1
- 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/employee-templates.js +20 -1
- package/dist/lib/exe-daemon.js +236 -16
- package/dist/lib/hybrid-search.js +154 -3
- 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 +1614 -1091
- package/dist/lib/tmux-routing.js +149 -9
- package/dist/mcp/server.js +1810 -1137
- package/dist/mcp/tools/create-task.js +2280 -828
- 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 +64 -0
- package/dist/runtime/index.js +235 -67
- package/dist/tui/App.js +1440 -646
- package/package.json +3 -2
package/dist/bin/cli.js
CHANGED
|
@@ -1311,6 +1311,13 @@ async function ensureSchema() {
|
|
|
1311
1311
|
});
|
|
1312
1312
|
} catch {
|
|
1313
1313
|
}
|
|
1314
|
+
try {
|
|
1315
|
+
await client.execute({
|
|
1316
|
+
sql: `ALTER TABLE tasks ADD COLUMN session_scope TEXT`,
|
|
1317
|
+
args: []
|
|
1318
|
+
});
|
|
1319
|
+
} catch {
|
|
1320
|
+
}
|
|
1314
1321
|
try {
|
|
1315
1322
|
await client.execute({
|
|
1316
1323
|
sql: `ALTER TABLE memories ADD COLUMN task_id TEXT`,
|
|
@@ -1757,6 +1764,18 @@ async function ensureSchema() {
|
|
|
1757
1764
|
CREATE INDEX IF NOT EXISTS idx_session_kills_agent
|
|
1758
1765
|
ON session_kills(agent_id);
|
|
1759
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
|
+
`);
|
|
1760
1779
|
await client.executeMultiple(`
|
|
1761
1780
|
CREATE TABLE IF NOT EXISTS conversations (
|
|
1762
1781
|
id TEXT PRIMARY KEY,
|
|
@@ -2061,6 +2080,61 @@ var init_keychain = __esm({
|
|
|
2061
2080
|
}
|
|
2062
2081
|
});
|
|
2063
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
|
+
|
|
2064
2138
|
// src/lib/shard-manager.ts
|
|
2065
2139
|
var shard_manager_exports = {};
|
|
2066
2140
|
__export(shard_manager_exports, {
|
|
@@ -2302,6 +2376,71 @@ var init_shard_manager = __esm({
|
|
|
2302
2376
|
}
|
|
2303
2377
|
});
|
|
2304
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
|
+
|
|
2305
2444
|
// src/lib/store.ts
|
|
2306
2445
|
var store_exports = {};
|
|
2307
2446
|
__export(store_exports, {
|
|
@@ -2381,6 +2520,11 @@ async function initStore(options) {
|
|
|
2381
2520
|
"version-query"
|
|
2382
2521
|
);
|
|
2383
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
|
+
}
|
|
2384
2528
|
}
|
|
2385
2529
|
function classifyTier(record) {
|
|
2386
2530
|
if (record.tool_name === "commit_to_long_term_memory" && (record.importance ?? 0) >= 8) return 1;
|
|
@@ -2422,6 +2566,12 @@ async function writeMemory(record) {
|
|
|
2422
2566
|
supersedes_id: record.supersedes_id ?? null
|
|
2423
2567
|
};
|
|
2424
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
|
+
});
|
|
2425
2575
|
const MAX_PENDING = 1e3;
|
|
2426
2576
|
if (_pendingRecords.length > MAX_PENDING) {
|
|
2427
2577
|
const dropped = _pendingRecords.length - MAX_PENDING;
|
|
@@ -2767,6 +2917,7 @@ var init_store = __esm({
|
|
|
2767
2917
|
init_database();
|
|
2768
2918
|
init_keychain();
|
|
2769
2919
|
init_config();
|
|
2920
|
+
init_state_bus();
|
|
2770
2921
|
INIT_MAX_RETRIES = 3;
|
|
2771
2922
|
INIT_RETRY_DELAY_MS = 1e3;
|
|
2772
2923
|
_pendingRecords = [];
|
|
@@ -2781,7 +2932,7 @@ var init_store = __esm({
|
|
|
2781
2932
|
// src/lib/exe-daemon-client.ts
|
|
2782
2933
|
import net from "net";
|
|
2783
2934
|
import { spawn } from "child_process";
|
|
2784
|
-
import { randomUUID } from "crypto";
|
|
2935
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
2785
2936
|
import { existsSync as existsSync7, unlinkSync, readFileSync as readFileSync4, openSync, closeSync, statSync } from "fs";
|
|
2786
2937
|
import path7 from "path";
|
|
2787
2938
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
@@ -2973,7 +3124,7 @@ function sendRequest(texts, priority) {
|
|
|
2973
3124
|
resolve({ error: "Not connected" });
|
|
2974
3125
|
return;
|
|
2975
3126
|
}
|
|
2976
|
-
const id =
|
|
3127
|
+
const id = randomUUID2();
|
|
2977
3128
|
const timer = setTimeout(() => {
|
|
2978
3129
|
_pending.delete(id);
|
|
2979
3130
|
resolve({ error: "Request timeout" });
|
|
@@ -2991,7 +3142,7 @@ function sendRequest(texts, priority) {
|
|
|
2991
3142
|
async function pingDaemon() {
|
|
2992
3143
|
if (!_socket || !_connected) return null;
|
|
2993
3144
|
return new Promise((resolve) => {
|
|
2994
|
-
const id =
|
|
3145
|
+
const id = randomUUID2();
|
|
2995
3146
|
const timer = setTimeout(() => {
|
|
2996
3147
|
_pending.delete(id);
|
|
2997
3148
|
resolve(null);
|
|
@@ -3537,7 +3688,8 @@ __export(employee_templates_exports, {
|
|
|
3537
3688
|
function getSessionPrompt(storedPrompt) {
|
|
3538
3689
|
const markerIndex = storedPrompt.indexOf(PROCEDURES_MARKER);
|
|
3539
3690
|
const rolePrompt = markerIndex >= 0 ? storedPrompt.slice(0, markerIndex).trimEnd() : storedPrompt;
|
|
3540
|
-
|
|
3691
|
+
const globalBlock = getGlobalProceduresBlock();
|
|
3692
|
+
return `${globalBlock}${rolePrompt}
|
|
3541
3693
|
${BASE_OPERATING_PROCEDURES}`;
|
|
3542
3694
|
}
|
|
3543
3695
|
function buildCustomEmployeePrompt(name, role) {
|
|
@@ -3577,6 +3729,7 @@ var BASE_OPERATING_PROCEDURES, DEFAULT_EXE, TEMPLATE_VERSION, PROCEDURES_MARKER,
|
|
|
3577
3729
|
var init_employee_templates = __esm({
|
|
3578
3730
|
"src/lib/employee-templates.ts"() {
|
|
3579
3731
|
"use strict";
|
|
3732
|
+
init_global_procedures();
|
|
3580
3733
|
BASE_OPERATING_PROCEDURES = `
|
|
3581
3734
|
EXE OS \u2014 VISION AND NON-NEGOTIABLE PRINCIPLES (above all work):
|
|
3582
3735
|
|
|
@@ -4510,7 +4663,7 @@ __export(license_exports, {
|
|
|
4510
4663
|
validateLicense: () => validateLicense
|
|
4511
4664
|
});
|
|
4512
4665
|
import { readFileSync as readFileSync6, writeFileSync as writeFileSync2, existsSync as existsSync10, mkdirSync as mkdirSync3 } from "fs";
|
|
4513
|
-
import { randomUUID as
|
|
4666
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
4514
4667
|
import path11 from "path";
|
|
4515
4668
|
import { jwtVerify, importSPKI } from "jose";
|
|
4516
4669
|
async function fetchRetry(url, init) {
|
|
@@ -4537,7 +4690,7 @@ function loadDeviceId() {
|
|
|
4537
4690
|
}
|
|
4538
4691
|
} catch {
|
|
4539
4692
|
}
|
|
4540
|
-
const id =
|
|
4693
|
+
const id = randomUUID3();
|
|
4541
4694
|
mkdirSync3(EXE_AI_DIR, { recursive: true });
|
|
4542
4695
|
writeFileSync2(DEVICE_ID_PATH, id, "utf8");
|
|
4543
4696
|
return id;
|
|
@@ -12309,6 +12462,73 @@ var init_Sidebar = __esm({
|
|
|
12309
12462
|
}
|
|
12310
12463
|
});
|
|
12311
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
|
+
|
|
12312
12532
|
// src/lib/tmux-status.ts
|
|
12313
12533
|
var tmux_status_exports = {};
|
|
12314
12534
|
__export(tmux_status_exports, {
|
|
@@ -12603,61 +12823,64 @@ function Footer() {
|
|
|
12603
12823
|
return () => clearInterval(timer);
|
|
12604
12824
|
}, []);
|
|
12605
12825
|
async function loadFooterData() {
|
|
12606
|
-
|
|
12607
|
-
|
|
12608
|
-
|
|
12609
|
-
|
|
12610
|
-
const
|
|
12611
|
-
|
|
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 {
|
|
12612
12836
|
}
|
|
12613
|
-
|
|
12614
|
-
|
|
12615
|
-
|
|
12616
|
-
|
|
12617
|
-
|
|
12618
|
-
|
|
12619
|
-
|
|
12620
|
-
|
|
12621
|
-
|
|
12622
|
-
|
|
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 {
|
|
12623
12847
|
}
|
|
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
|
-
}
|
|
12654
|
-
|
|
12655
|
-
} 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
|
+
}
|
|
12656
12879
|
}
|
|
12657
12880
|
}
|
|
12881
|
+
} catch {
|
|
12658
12882
|
}
|
|
12659
|
-
}
|
|
12660
|
-
}
|
|
12883
|
+
});
|
|
12661
12884
|
}
|
|
12662
12885
|
return /* @__PURE__ */ jsxs3(Box_default, { flexDirection: "column", children: [
|
|
12663
12886
|
/* @__PURE__ */ jsx5(Text, { color: "#3D3660", children: "\u2500".repeat(process.stdout.columns || 120) }),
|
|
@@ -12698,6 +12921,8 @@ function Footer() {
|
|
|
12698
12921
|
] }),
|
|
12699
12922
|
/* @__PURE__ */ jsx5(Text, { color: "#6B4C9A", children: "1-7 navigate" }),
|
|
12700
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" }),
|
|
12701
12926
|
/* @__PURE__ */ jsx5(Text, { color: "#6B4C9A", children: "q quit" })
|
|
12702
12927
|
] })
|
|
12703
12928
|
] })
|
|
@@ -14346,7 +14571,7 @@ var init_anthropic = __esm({
|
|
|
14346
14571
|
|
|
14347
14572
|
// src/gateway/providers/openai-compat.ts
|
|
14348
14573
|
import OpenAI from "openai";
|
|
14349
|
-
import { randomUUID as
|
|
14574
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
14350
14575
|
var OpenAICompatProvider;
|
|
14351
14576
|
var init_openai_compat = __esm({
|
|
14352
14577
|
"src/gateway/providers/openai-compat.ts"() {
|
|
@@ -14463,7 +14688,7 @@ var init_openai_compat = __esm({
|
|
|
14463
14688
|
}
|
|
14464
14689
|
content.push({
|
|
14465
14690
|
type: "tool_use",
|
|
14466
|
-
id: call.id ??
|
|
14691
|
+
id: call.id ?? randomUUID4(),
|
|
14467
14692
|
name: fn.name,
|
|
14468
14693
|
input
|
|
14469
14694
|
});
|
|
@@ -15537,7 +15762,7 @@ function CommandCenterView({
|
|
|
15537
15762
|
setAgentConfig({
|
|
15538
15763
|
provider,
|
|
15539
15764
|
model,
|
|
15540
|
-
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."),
|
|
15541
15766
|
tools: registry,
|
|
15542
15767
|
hooks: createDefaultHooks2(),
|
|
15543
15768
|
permissions,
|
|
@@ -15658,6 +15883,7 @@ function CommandCenterView({
|
|
|
15658
15883
|
employeeCount: p.employees.length,
|
|
15659
15884
|
activeCount: p.employees.filter((e) => e.status === "active").length,
|
|
15660
15885
|
memoryCount: p.employees.length * 4e3,
|
|
15886
|
+
openTaskCount: Math.floor(p.employees.length * 1.5),
|
|
15661
15887
|
status: p.employees.some((e) => e.status === "active") ? "active" : "idle",
|
|
15662
15888
|
type: p.projectName.startsWith("exe-") ? "code" : "automation",
|
|
15663
15889
|
recentTasks: DEMO_RECENT_TASKS[p.projectName] ?? []
|
|
@@ -15669,6 +15895,7 @@ function CommandCenterView({
|
|
|
15669
15895
|
employeeCount: 0,
|
|
15670
15896
|
activeCount: 0,
|
|
15671
15897
|
memoryCount: 0,
|
|
15898
|
+
openTaskCount: 0,
|
|
15672
15899
|
status: "offline",
|
|
15673
15900
|
type: "reference",
|
|
15674
15901
|
recentTasks: []
|
|
@@ -15683,182 +15910,122 @@ function CommandCenterView({
|
|
|
15683
15910
|
return () => clearInterval(timer);
|
|
15684
15911
|
}, []);
|
|
15685
15912
|
async function loadData() {
|
|
15686
|
-
|
|
15687
|
-
|
|
15688
|
-
const { listTmuxSessions: listTmuxSessions2, inTmux: inTmux2 } = await Promise.resolve().then(() => (init_tmux_status(), tmux_status_exports));
|
|
15689
|
-
const { loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
15690
|
-
const { existsSync: existsSync22 } = await import("fs");
|
|
15691
|
-
const { join } = await import("path");
|
|
15692
|
-
const registry = listSessions2();
|
|
15693
|
-
const tmuxSessions = inTmux2() ? new Set(listTmuxSessions2()) : /* @__PURE__ */ new Set();
|
|
15694
|
-
const roster = await loadEmployees2();
|
|
15695
|
-
const exeSessions = /* @__PURE__ */ new Map();
|
|
15696
|
-
for (const entry of registry) {
|
|
15697
|
-
if (entry.agentId === "exe" && tmuxSessions.has(entry.windowName)) {
|
|
15698
|
-
exeSessions.set(entry.windowName, entry.projectDir);
|
|
15699
|
-
}
|
|
15700
|
-
}
|
|
15701
|
-
for (const s of tmuxSessions) {
|
|
15702
|
-
if (/^exe\d+$/.test(s) && !exeSessions.has(s)) exeSessions.set(s, "");
|
|
15703
|
-
}
|
|
15704
|
-
let projectMemoryCounts = /* @__PURE__ */ new Map();
|
|
15705
|
-
let projectRecentTasks = /* @__PURE__ */ new Map();
|
|
15913
|
+
const { withTrace: withTrace2 } = await Promise.resolve().then(() => (init_telemetry(), telemetry_exports));
|
|
15914
|
+
return withTrace2("tui.commandCenter.loadData", async () => {
|
|
15706
15915
|
try {
|
|
15707
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");
|
|
15708
15922
|
const client = getClient2();
|
|
15709
|
-
if (client) {
|
|
15710
|
-
|
|
15711
|
-
|
|
15712
|
-
);
|
|
15713
|
-
for (const row of memResult.rows) {
|
|
15714
|
-
projectMemoryCounts.set(String(row.project_name), Number(row.cnt));
|
|
15715
|
-
}
|
|
15716
|
-
for (const [, projectDir] of exeSessions) {
|
|
15717
|
-
const projectName = projectDir.split("/").filter(Boolean).pop() ?? "";
|
|
15718
|
-
if (!projectName) continue;
|
|
15719
|
-
const taskResult = await client.execute({
|
|
15720
|
-
sql: "SELECT title FROM tasks WHERE project_name = ? AND status = 'done' ORDER BY updated_at DESC LIMIT 3",
|
|
15721
|
-
args: [projectName]
|
|
15722
|
-
});
|
|
15723
|
-
const tasks = taskResult.rows.map((r) => String(r.title));
|
|
15724
|
-
if (tasks.length > 0) projectRecentTasks.set(projectName, tasks);
|
|
15725
|
-
}
|
|
15923
|
+
if (!client) {
|
|
15924
|
+
setDbError(true);
|
|
15925
|
+
return;
|
|
15726
15926
|
}
|
|
15727
|
-
|
|
15728
|
-
|
|
15729
|
-
|
|
15730
|
-
|
|
15731
|
-
|
|
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();
|
|
15732
15961
|
const employeeNames = roster.map((e) => e.name).filter((n) => n !== "exe");
|
|
15733
|
-
|
|
15734
|
-
for (const
|
|
15735
|
-
if (tmuxSessions.has(
|
|
15736
|
-
|
|
15737
|
-
|
|
15738
|
-
|
|
15739
|
-
|
|
15740
|
-
const hasActivity = memoryCount > 0;
|
|
15741
|
-
let type = "automation";
|
|
15742
|
-
if (hasGit && hasActivity) type = "code";
|
|
15743
|
-
else if (hasGit && !hasActivity) type = "reference";
|
|
15744
|
-
projectList.push({
|
|
15745
|
-
projectName,
|
|
15746
|
-
exeSession,
|
|
15747
|
-
projectDir,
|
|
15748
|
-
employeeCount: totalCount,
|
|
15749
|
-
activeCount,
|
|
15750
|
-
memoryCount,
|
|
15751
|
-
status: activeCount > 0 ? "active" : "idle",
|
|
15752
|
-
type,
|
|
15753
|
-
recentTasks: projectRecentTasks.get(projectName) ?? []
|
|
15754
|
-
});
|
|
15755
|
-
}
|
|
15756
|
-
const knownDirs = [
|
|
15757
|
-
process.env.HOME ? join(process.env.HOME, "openclaw") : null,
|
|
15758
|
-
process.env.HOME ? join(process.env.HOME, "agno") : null
|
|
15759
|
-
].filter(Boolean);
|
|
15760
|
-
const activeProjectNames = new Set(projectList.map((p) => p.projectName));
|
|
15761
|
-
for (const dir of knownDirs) {
|
|
15762
|
-
const name = dir.split("/").filter(Boolean).pop() ?? "";
|
|
15763
|
-
if (activeProjectNames.has(name) || !existsSync22(dir) || !existsSync22(join(dir, ".git"))) continue;
|
|
15764
|
-
if ((projectMemoryCounts.get(name) ?? 0) > 0) continue;
|
|
15765
|
-
projectList.push({
|
|
15766
|
-
projectName: name,
|
|
15767
|
-
exeSession: "",
|
|
15768
|
-
projectDir: dir,
|
|
15769
|
-
employeeCount: 0,
|
|
15770
|
-
activeCount: 0,
|
|
15771
|
-
memoryCount: 0,
|
|
15772
|
-
status: "offline",
|
|
15773
|
-
type: "reference",
|
|
15774
|
-
recentTasks: []
|
|
15775
|
-
});
|
|
15776
|
-
}
|
|
15777
|
-
const dbActiveProjectNames = new Set(projectList.map((p) => p.projectName));
|
|
15778
|
-
try {
|
|
15779
|
-
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
15780
|
-
const client = getClient2();
|
|
15781
|
-
if (client) {
|
|
15782
|
-
const dbProjects = await client.execute(
|
|
15783
|
-
`SELECT DISTINCT project_name FROM memories WHERE project_name IS NOT NULL AND project_name != ''
|
|
15784
|
-
UNION
|
|
15785
|
-
SELECT DISTINCT project_name FROM tasks WHERE project_name IS NOT NULL AND project_name != ''
|
|
15786
|
-
ORDER BY project_name`
|
|
15787
|
-
);
|
|
15788
|
-
for (const row of dbProjects.rows) {
|
|
15789
|
-
const name = String(row.project_name);
|
|
15790
|
-
if (dbActiveProjectNames.has(name)) continue;
|
|
15791
|
-
const memCount = projectMemoryCounts.get(name) ?? 0;
|
|
15792
|
-
const agentResult = await client.execute({
|
|
15793
|
-
sql: "SELECT COUNT(DISTINCT agent_id) as cnt FROM memories WHERE project_name = ?",
|
|
15794
|
-
args: [name]
|
|
15795
|
-
});
|
|
15796
|
-
const agentCount = Number(agentResult.rows[0]?.cnt ?? 0);
|
|
15797
|
-
projectList.push({
|
|
15798
|
-
projectName: name,
|
|
15799
|
-
exeSession: "",
|
|
15800
|
-
projectDir: "",
|
|
15801
|
-
employeeCount: agentCount,
|
|
15802
|
-
activeCount: 0,
|
|
15803
|
-
memoryCount: memCount,
|
|
15804
|
-
status: "offline",
|
|
15805
|
-
type: "code",
|
|
15806
|
-
recentTasks: projectRecentTasks.get(name) ?? []
|
|
15807
|
-
});
|
|
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
|
+
}
|
|
15808
15969
|
}
|
|
15809
15970
|
}
|
|
15810
|
-
|
|
15811
|
-
|
|
15812
|
-
|
|
15813
|
-
|
|
15814
|
-
|
|
15815
|
-
|
|
15816
|
-
|
|
15817
|
-
|
|
15818
|
-
|
|
15819
|
-
|
|
15820
|
-
|
|
15821
|
-
|
|
15822
|
-
|
|
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;
|
|
15823
16004
|
});
|
|
15824
|
-
|
|
15825
|
-
|
|
15826
|
-
|
|
15827
|
-
|
|
15828
|
-
|
|
15829
|
-
|
|
15830
|
-
|
|
15831
|
-
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 {
|
|
15832
16012
|
}
|
|
15833
|
-
|
|
15834
|
-
|
|
15835
|
-
|
|
15836
|
-
|
|
15837
|
-
|
|
15838
|
-
|
|
15839
|
-
|
|
15840
|
-
|
|
15841
|
-
|
|
15842
|
-
const client = getClient2();
|
|
15843
|
-
if (client) {
|
|
15844
|
-
const activityResult = await client.execute(
|
|
15845
|
-
"SELECT agent_id, tool_name, project_name, created_at, text FROM memories ORDER BY created_at DESC LIMIT 20"
|
|
15846
|
-
);
|
|
15847
|
-
if (activityResult.rows.length > 0) {
|
|
15848
|
-
setActivity(activityResult.rows.slice(0, 8).map((r) => ({
|
|
15849
|
-
time: new Date(String(r.created_at)).toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit", hour12: false }),
|
|
15850
|
-
agent: String(r.agent_id ?? "system"),
|
|
15851
|
-
action: String(r.text ?? "").slice(0, 60)
|
|
15852
|
-
})));
|
|
15853
|
-
}
|
|
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
|
+
})));
|
|
15854
16022
|
}
|
|
15855
16023
|
} catch {
|
|
16024
|
+
setDbError(true);
|
|
16025
|
+
} finally {
|
|
16026
|
+
setLoading(false);
|
|
15856
16027
|
}
|
|
15857
|
-
}
|
|
15858
|
-
setDbError(true);
|
|
15859
|
-
} finally {
|
|
15860
|
-
setLoading(false);
|
|
15861
|
-
}
|
|
16028
|
+
});
|
|
15862
16029
|
}
|
|
15863
16030
|
const daemonColor = health.daemon === "running" ? "green" : health.daemon === "stopped" ? "red" : "gray";
|
|
15864
16031
|
const handleChatSubmit = useCallback4((value) => {
|
|
@@ -15950,7 +16117,7 @@ function CommandCenterView({
|
|
|
15950
16117
|
] }),
|
|
15951
16118
|
/* @__PURE__ */ jsx7(Text, { color: "#6B4C9A", children: "\u2191\u2193 navigate | c to chat | Enter to open | Escape to detach" }),
|
|
15952
16119
|
/* @__PURE__ */ jsx7(Text, { children: " " }),
|
|
15953
|
-
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." }) : (() => {
|
|
15954
16121
|
const sections = [];
|
|
15955
16122
|
let currentProjects = [];
|
|
15956
16123
|
let sectionKey = 0;
|
|
@@ -15980,9 +16147,9 @@ function CommandCenterView({
|
|
|
15980
16147
|
] })
|
|
15981
16148
|
] }),
|
|
15982
16149
|
/* @__PURE__ */ jsxs5(Text, { color: isSelected ? "#F0EDE8" : "#6B4C9A", children: [
|
|
15983
|
-
entry.
|
|
16150
|
+
entry.openTaskCount,
|
|
15984
16151
|
" ",
|
|
15985
|
-
entry.
|
|
16152
|
+
entry.openTaskCount === 1 ? "task" : "tasks",
|
|
15986
16153
|
" \xB7 ",
|
|
15987
16154
|
entry.memoryCount.toLocaleString(),
|
|
15988
16155
|
" memories"
|
|
@@ -16060,6 +16227,7 @@ var init_CommandCenter = __esm({
|
|
|
16060
16227
|
init_DemoContext();
|
|
16061
16228
|
init_demo_data();
|
|
16062
16229
|
init_useAgentLoop();
|
|
16230
|
+
init_employee_templates();
|
|
16063
16231
|
}
|
|
16064
16232
|
});
|
|
16065
16233
|
|
|
@@ -16184,7 +16352,7 @@ var init_TmuxPane = __esm({
|
|
|
16184
16352
|
});
|
|
16185
16353
|
|
|
16186
16354
|
// src/lib/task-router.ts
|
|
16187
|
-
import { randomUUID as
|
|
16355
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
16188
16356
|
function resolveBloomRouting(complexity, config = DEFAULT_BLOOM_CONFIG) {
|
|
16189
16357
|
const tier = config.complexityToTier[complexity];
|
|
16190
16358
|
const rule = config.tierRules[tier];
|
|
@@ -16836,9 +17004,15 @@ async function createTaskCore(input) {
|
|
|
16836
17004
|
}
|
|
16837
17005
|
}
|
|
16838
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
|
+
}
|
|
16839
17013
|
await client.execute({
|
|
16840
|
-
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)
|
|
16841
|
-
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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
16842
17016
|
args: [
|
|
16843
17017
|
id,
|
|
16844
17018
|
input.title,
|
|
@@ -16857,6 +17031,7 @@ async function createTaskCore(input) {
|
|
|
16857
17031
|
input.budgetFallbackModel ?? null,
|
|
16858
17032
|
0,
|
|
16859
17033
|
null,
|
|
17034
|
+
sessionScope,
|
|
16860
17035
|
now,
|
|
16861
17036
|
now
|
|
16862
17037
|
]
|
|
@@ -16901,6 +17076,15 @@ async function listTasks(input) {
|
|
|
16901
17076
|
conditions.push("priority = ?");
|
|
16902
17077
|
args2.push(input.priority);
|
|
16903
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
|
+
}
|
|
16904
17088
|
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
16905
17089
|
const result = await client.execute({
|
|
16906
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`,
|
|
@@ -17265,6 +17449,7 @@ var init_tasks_review = __esm({
|
|
|
17265
17449
|
init_tasks_crud();
|
|
17266
17450
|
init_tmux_routing();
|
|
17267
17451
|
init_session_key();
|
|
17452
|
+
init_state_bus();
|
|
17268
17453
|
}
|
|
17269
17454
|
});
|
|
17270
17455
|
|
|
@@ -17429,13 +17614,12 @@ function assertSessionScope(actionType, targetProject) {
|
|
|
17429
17614
|
};
|
|
17430
17615
|
}
|
|
17431
17616
|
process.stderr.write(
|
|
17432
|
-
`[session-scope]
|
|
17617
|
+
`[session-scope] BLOCKED cross-project ${actionType}: session project="${currentProject}" \u2260 target project="${targetProject}"
|
|
17433
17618
|
`
|
|
17434
17619
|
);
|
|
17435
17620
|
return {
|
|
17436
|
-
allowed:
|
|
17437
|
-
|
|
17438
|
-
reason: "cross_session_granted",
|
|
17621
|
+
allowed: false,
|
|
17622
|
+
reason: "cross_session_denied",
|
|
17439
17623
|
currentProject,
|
|
17440
17624
|
targetProject,
|
|
17441
17625
|
targetSession: findSessionForProject(targetProject)?.windowName
|
|
@@ -17461,8 +17645,9 @@ async function dispatchTaskToEmployee(input) {
|
|
|
17461
17645
|
try {
|
|
17462
17646
|
const { assertSessionScope: assertSessionScope2 } = (init_session_scope(), __toCommonJS(session_scope_exports));
|
|
17463
17647
|
const check = assertSessionScope2("dispatch_task", input.projectName);
|
|
17464
|
-
if (check.reason === "
|
|
17648
|
+
if (check.reason === "cross_session_denied") {
|
|
17465
17649
|
crossProject = true;
|
|
17650
|
+
return { dispatched: "skipped", crossProject: true };
|
|
17466
17651
|
}
|
|
17467
17652
|
} catch {
|
|
17468
17653
|
}
|
|
@@ -17925,6 +18110,13 @@ async function updateTask(input) {
|
|
|
17925
18110
|
await cascadeUnblock(taskId, input.baseDir, now);
|
|
17926
18111
|
} catch {
|
|
17927
18112
|
}
|
|
18113
|
+
orgBus.emit({
|
|
18114
|
+
type: "task_completed",
|
|
18115
|
+
taskId,
|
|
18116
|
+
employee: String(row.assigned_to),
|
|
18117
|
+
result: input.result ?? "",
|
|
18118
|
+
timestamp: now
|
|
18119
|
+
});
|
|
17928
18120
|
if (row.parent_task_id) {
|
|
17929
18121
|
try {
|
|
17930
18122
|
await checkSubtaskCompletion(String(row.parent_task_id), String(row.project_name));
|
|
@@ -17992,6 +18184,7 @@ var init_tasks = __esm({
|
|
|
17992
18184
|
init_database();
|
|
17993
18185
|
init_config();
|
|
17994
18186
|
init_notifications();
|
|
18187
|
+
init_state_bus();
|
|
17995
18188
|
init_tasks_crud();
|
|
17996
18189
|
init_tasks_review();
|
|
17997
18190
|
init_tasks_crud();
|
|
@@ -18382,8 +18575,28 @@ function getMySession() {
|
|
|
18382
18575
|
return getTransport().getMySession();
|
|
18383
18576
|
}
|
|
18384
18577
|
function employeeSessionName(employee, exeSession, instance) {
|
|
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
|
+
}
|
|
18385
18592
|
const suffix = instance != null && instance > 0 ? String(instance) : "";
|
|
18386
|
-
|
|
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;
|
|
18387
18600
|
}
|
|
18388
18601
|
function parseParentExe(sessionName, agentId) {
|
|
18389
18602
|
const escaped = agentId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -18623,6 +18836,22 @@ function ensureEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
18623
18836
|
error: `Error: pass employee name ('${bare}'), not session name ('${employeeName}')`
|
|
18624
18837
|
};
|
|
18625
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
|
+
}
|
|
18626
18855
|
let effectiveInstance = opts?.instance;
|
|
18627
18856
|
if (effectiveInstance === void 0 && opts?.autoInstance) {
|
|
18628
18857
|
const free = findFreeInstance(
|
|
@@ -18869,7 +19098,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
18869
19098
|
releaseSpawnLock2(sessionName);
|
|
18870
19099
|
return { sessionName };
|
|
18871
19100
|
}
|
|
18872
|
-
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;
|
|
18873
19102
|
var init_tmux_routing = __esm({
|
|
18874
19103
|
"src/lib/tmux-routing.ts"() {
|
|
18875
19104
|
"use strict";
|
|
@@ -18884,6 +19113,7 @@ var init_tmux_routing = __esm({
|
|
|
18884
19113
|
SPAWN_LOCK_DIR = path30.join(os10.homedir(), ".exe-os", "spawn-locks");
|
|
18885
19114
|
SESSION_CACHE = path30.join(os10.homedir(), ".exe-os", "session-cache");
|
|
18886
19115
|
BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
|
|
19116
|
+
VALID_SESSION_NAME = /^[a-z]+-exe\d+$|^[a-z]+\d+-exe\d+$/;
|
|
18887
19117
|
VERIFY_PANE_LINES = 200;
|
|
18888
19118
|
INTERCOM_DEBOUNCE_MS = 3e4;
|
|
18889
19119
|
INTERCOM_LOG2 = path30.join(os10.homedir(), ".exe-os", "intercom.log");
|
|
@@ -19290,6 +19520,7 @@ function SessionsView({
|
|
|
19290
19520
|
const [viewingEmployee, setViewingEmployee] = useState9(null);
|
|
19291
19521
|
const [viewingProject, setViewingProject] = useState9(null);
|
|
19292
19522
|
const [loading, setLoading] = useState9(!demo);
|
|
19523
|
+
const [sessionError, setSessionError] = useState9(null);
|
|
19293
19524
|
const [tmuxAvailable, setTmuxAvailable] = useState9(true);
|
|
19294
19525
|
const orch = useOrchestrator(!demo);
|
|
19295
19526
|
const [carouselEmployees, setCarouselEmployees] = useState9([]);
|
|
@@ -19465,111 +19696,116 @@ function SessionsView({
|
|
|
19465
19696
|
return ACTIVE_PANE_PATTERN.test(lines.join("\n")) ? "active" : "idle";
|
|
19466
19697
|
}
|
|
19467
19698
|
async function loadSessions() {
|
|
19468
|
-
|
|
19469
|
-
|
|
19470
|
-
const { listTmuxSessions: listTmuxSessions2, inTmux: inTmux2, capturePaneLines: capturePaneLines2, parseActivity: parseActivity2 } = await Promise.resolve().then(() => (init_tmux_status(), tmux_status_exports));
|
|
19471
|
-
const { loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
19472
|
-
const { execSync: execSync13 } = await import("child_process");
|
|
19473
|
-
if (!inTmux2()) {
|
|
19474
|
-
setTmuxAvailable(false);
|
|
19475
|
-
setProjects([]);
|
|
19476
|
-
return;
|
|
19477
|
-
}
|
|
19478
|
-
setTmuxAvailable(true);
|
|
19479
|
-
const attachedMap = /* @__PURE__ */ new Map();
|
|
19699
|
+
const { withTrace: withTrace2 } = await Promise.resolve().then(() => (init_telemetry(), telemetry_exports));
|
|
19700
|
+
return withTrace2("tui.sessions.loadSessions", async () => {
|
|
19480
19701
|
try {
|
|
19481
|
-
const
|
|
19482
|
-
|
|
19483
|
-
|
|
19484
|
-
});
|
|
19485
|
-
|
|
19486
|
-
|
|
19487
|
-
|
|
19488
|
-
|
|
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
|
+
}
|
|
19723
|
+
}
|
|
19724
|
+
} catch {
|
|
19725
|
+
}
|
|
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);
|
|
19489
19733
|
}
|
|
19490
19734
|
}
|
|
19491
|
-
|
|
19492
|
-
|
|
19493
|
-
|
|
19494
|
-
|
|
19495
|
-
|
|
19496
|
-
|
|
19497
|
-
|
|
19498
|
-
|
|
19499
|
-
|
|
19500
|
-
|
|
19501
|
-
|
|
19502
|
-
|
|
19503
|
-
|
|
19504
|
-
|
|
19505
|
-
|
|
19506
|
-
}
|
|
19507
|
-
const projectList = [];
|
|
19508
|
-
for (const [exeSession, projectDir] of exeSessions) {
|
|
19509
|
-
const projectName = projectDir.split("/").filter(Boolean).pop() ?? exeSession;
|
|
19510
|
-
const exeHasSession = tmuxSessions.has(exeSession);
|
|
19511
|
-
let exeStatus = "offline";
|
|
19512
|
-
let exeActivity = "";
|
|
19513
|
-
if (exeHasSession) {
|
|
19514
|
-
const exeLines = capturePaneLines2(exeSession, 10);
|
|
19515
|
-
exeStatus = statusFromPaneLines(exeLines);
|
|
19516
|
-
exeActivity = exeLines.length > 0 ? parseActivity2(exeLines) : "";
|
|
19517
|
-
}
|
|
19518
|
-
const employeeEntries = roster.filter((e) => e.name !== "exe").map((emp) => {
|
|
19519
|
-
const sessionName = `${emp.name}-${exeSession}`;
|
|
19520
|
-
const hasSession = tmuxSessions.has(sessionName);
|
|
19521
|
-
const isCrashed = !hasSession && orch.crashedSessions.includes(emp.name);
|
|
19522
|
-
if (isCrashed) {
|
|
19523
|
-
return {
|
|
19524
|
-
name: emp.name,
|
|
19525
|
-
role: emp.role,
|
|
19526
|
-
status: "crashed",
|
|
19527
|
-
sessionName,
|
|
19528
|
-
activity: "Dead session \u2014 has open tasks",
|
|
19529
|
-
attached: false
|
|
19530
|
-
};
|
|
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) : "";
|
|
19531
19750
|
}
|
|
19532
|
-
|
|
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);
|
|
19533
19776
|
return {
|
|
19534
19777
|
name: emp.name,
|
|
19535
19778
|
role: emp.role,
|
|
19536
|
-
status:
|
|
19779
|
+
status: statusFromPaneLines(lines),
|
|
19537
19780
|
sessionName,
|
|
19538
|
-
activity: "",
|
|
19539
|
-
attached: false
|
|
19781
|
+
activity: lines.length > 0 ? parseActivity2(lines) : "",
|
|
19782
|
+
attached: attachedMap.get(sessionName) ?? false
|
|
19540
19783
|
};
|
|
19541
|
-
}
|
|
19542
|
-
const
|
|
19543
|
-
|
|
19544
|
-
|
|
19545
|
-
|
|
19546
|
-
|
|
19547
|
-
|
|
19548
|
-
|
|
19549
|
-
|
|
19550
|
-
|
|
19551
|
-
|
|
19552
|
-
|
|
19553
|
-
{
|
|
19554
|
-
|
|
19555
|
-
|
|
19556
|
-
|
|
19557
|
-
|
|
19558
|
-
|
|
19559
|
-
|
|
19560
|
-
|
|
19561
|
-
|
|
19562
|
-
|
|
19563
|
-
|
|
19564
|
-
}
|
|
19565
|
-
if (projectList.length === 0) {
|
|
19566
|
-
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);
|
|
19567
19807
|
}
|
|
19568
|
-
|
|
19569
|
-
} catch {
|
|
19570
|
-
} finally {
|
|
19571
|
-
setLoading(false);
|
|
19572
|
-
}
|
|
19808
|
+
});
|
|
19573
19809
|
}
|
|
19574
19810
|
if (viewingEmployee) {
|
|
19575
19811
|
const inCarousel = carouselEmployees.length > 0;
|
|
@@ -19651,7 +19887,10 @@ function SessionsView({
|
|
|
19651
19887
|
] })
|
|
19652
19888
|
] }),
|
|
19653
19889
|
/* @__PURE__ */ jsx9(Text, { children: " " }),
|
|
19654
|
-
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) => {
|
|
19655
19894
|
const isSelected = i === selectedIdx;
|
|
19656
19895
|
const marker = isSelected ? "\u25B8 " : " ";
|
|
19657
19896
|
if (item.type === "project") {
|
|
@@ -19752,7 +19991,7 @@ function TasksView({ onBack }) {
|
|
|
19752
19991
|
const demo = useDemo();
|
|
19753
19992
|
const [allTasks, setAllTasks] = useState10([]);
|
|
19754
19993
|
const [loading, setLoading] = useState10(!demo);
|
|
19755
|
-
const [dbError, setDbError] = useState10(
|
|
19994
|
+
const [dbError, setDbError] = useState10(null);
|
|
19756
19995
|
const [selectedTask, setSelectedTask] = useState10(0);
|
|
19757
19996
|
const [showDetail, setShowDetail] = useState10(false);
|
|
19758
19997
|
const [statusFilter, setStatusFilter] = useState10("all");
|
|
@@ -19824,40 +20063,43 @@ function TasksView({ onBack }) {
|
|
|
19824
20063
|
}
|
|
19825
20064
|
});
|
|
19826
20065
|
async function loadTasks() {
|
|
19827
|
-
|
|
19828
|
-
|
|
19829
|
-
|
|
19830
|
-
|
|
19831
|
-
const
|
|
19832
|
-
|
|
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
|
|
19833
20074
|
FROM tasks
|
|
19834
20075
|
ORDER BY
|
|
19835
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,
|
|
19836
20077
|
CASE priority WHEN 'p0' THEN 0 WHEN 'p1' THEN 1 WHEN 'p2' THEN 2 ELSE 3 END,
|
|
19837
20078
|
created_at DESC`
|
|
19838
|
-
|
|
19839
|
-
|
|
19840
|
-
|
|
19841
|
-
|
|
19842
|
-
|
|
19843
|
-
|
|
19844
|
-
|
|
19845
|
-
|
|
19846
|
-
|
|
19847
|
-
|
|
19848
|
-
|
|
19849
|
-
|
|
19850
|
-
|
|
19851
|
-
|
|
19852
|
-
|
|
19853
|
-
|
|
19854
|
-
|
|
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);
|
|
19855
20101
|
}
|
|
19856
|
-
}
|
|
19857
|
-
setDbError(true);
|
|
19858
|
-
} finally {
|
|
19859
|
-
setLoading(false);
|
|
19860
|
-
}
|
|
20102
|
+
});
|
|
19861
20103
|
}
|
|
19862
20104
|
const selected = taskRows[selectedTask]?.task;
|
|
19863
20105
|
if (showDetail && selected) {
|
|
@@ -19924,7 +20166,10 @@ function TasksView({ onBack }) {
|
|
|
19924
20166
|
filterLabel
|
|
19925
20167
|
] }),
|
|
19926
20168
|
/* @__PURE__ */ jsx10(Text, { children: " " }),
|
|
19927
|
-
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) => {
|
|
19928
20173
|
if (row.type === "header") {
|
|
19929
20174
|
return /* @__PURE__ */ jsxs8(Box_default, { marginTop: i > 0 ? 1 : 0, children: [
|
|
19930
20175
|
/* @__PURE__ */ jsx10(Text, { bold: true, color: "#F0EDE8", children: row.project }),
|
|
@@ -20611,6 +20856,31 @@ function GatewayView({ onBack }) {
|
|
|
20611
20856
|
/* @__PURE__ */ jsx11(Text, { color: "#6B4C9A", children: "Loading gateway status..." })
|
|
20612
20857
|
] });
|
|
20613
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
|
+
}
|
|
20614
20884
|
if (!gateway.running && gateway.adapters.length === 0 && !gateway.gatewayUrl) {
|
|
20615
20885
|
return /* @__PURE__ */ jsxs9(Box_default, { flexDirection: "column", flexGrow: 1, paddingX: 1, children: [
|
|
20616
20886
|
/* @__PURE__ */ jsx11(Box_default, { borderStyle: "single", borderColor: "#3D3660", paddingX: 1, alignSelf: "flex-start", children: /* @__PURE__ */ jsx11(Text, { bold: true, children: "Gateway Monitor" }) }),
|
|
@@ -20897,14 +21167,30 @@ var init_agent_status = __esm({
|
|
|
20897
21167
|
// src/tui/views/Team.tsx
|
|
20898
21168
|
import React22, { useState as useState12, useEffect as useEffect14 } from "react";
|
|
20899
21169
|
import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
20900
|
-
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 }) {
|
|
20901
21186
|
const demo = useDemo();
|
|
20902
21187
|
const [members, setMembers] = useState12([]);
|
|
20903
21188
|
const [externals, setExternals] = useState12([]);
|
|
20904
21189
|
const [loading, setLoading] = useState12(!demo);
|
|
20905
|
-
const [dbError, setDbError] = useState12(
|
|
21190
|
+
const [dbError, setDbError] = useState12(null);
|
|
20906
21191
|
const [selectedIdx, setSelectedIdx] = useState12(0);
|
|
20907
21192
|
const [showDetail, setShowDetail] = useState12(false);
|
|
21193
|
+
const [showAddHint, setShowAddHint] = useState12(false);
|
|
20908
21194
|
const orch = useOrchestrator(!demo);
|
|
20909
21195
|
const orchEmployeeMap = new Map(orch.employees.map((e) => [e.name, e]));
|
|
20910
21196
|
const allItems = [...members, ...externals.map((e) => ({ ...e, activity: "", memoryCount: 0 }))];
|
|
@@ -20919,7 +21205,7 @@ function TeamView({ onBack }) {
|
|
|
20919
21205
|
const timer = setInterval(loadTeam, 5e3);
|
|
20920
21206
|
return () => clearInterval(timer);
|
|
20921
21207
|
}, []);
|
|
20922
|
-
use_input_default((
|
|
21208
|
+
use_input_default((input, key) => {
|
|
20923
21209
|
if (showDetail) {
|
|
20924
21210
|
if (key.escape) setShowDetail(false);
|
|
20925
21211
|
return;
|
|
@@ -20928,91 +21214,103 @@ function TeamView({ onBack }) {
|
|
|
20928
21214
|
onBack?.();
|
|
20929
21215
|
return;
|
|
20930
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
|
+
}
|
|
20931
21226
|
if (key.upArrow && selectedIdx > 0) setSelectedIdx(selectedIdx - 1);
|
|
20932
21227
|
if (key.downArrow && selectedIdx < allItems.length - 1) setSelectedIdx(selectedIdx + 1);
|
|
20933
21228
|
if (key.return && allItems.length > 0) setShowDetail(true);
|
|
20934
21229
|
});
|
|
20935
21230
|
async function loadTeam() {
|
|
20936
|
-
|
|
20937
|
-
|
|
20938
|
-
const roster = await loadEmployees2();
|
|
20939
|
-
let memoryCounts = /* @__PURE__ */ new Map();
|
|
20940
|
-
let projectsByEmployee = /* @__PURE__ */ new Map();
|
|
20941
|
-
let currentTaskByEmployee = /* @__PURE__ */ new Map();
|
|
21231
|
+
const { withTrace: withTrace2 } = await Promise.resolve().then(() => (init_telemetry(), telemetry_exports));
|
|
21232
|
+
return withTrace2("tui.team.loadTeam", async () => {
|
|
20942
21233
|
try {
|
|
20943
|
-
const {
|
|
20944
|
-
const
|
|
20945
|
-
|
|
20946
|
-
|
|
20947
|
-
|
|
20948
|
-
|
|
20949
|
-
}
|
|
20950
|
-
|
|
20951
|
-
|
|
20952
|
-
|
|
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,
|
|
20953
21250
|
MAX(CASE WHEN status = 'in_progress' THEN 1 WHEN status = 'open' THEN 2 ELSE 3 END) as urgency
|
|
20954
21251
|
FROM tasks WHERE assigned_to = ? AND status IN ('open','in_progress','done')
|
|
20955
21252
|
GROUP BY project_name ORDER BY urgency ASC LIMIT 5`,
|
|
20956
|
-
|
|
20957
|
-
|
|
20958
|
-
|
|
20959
|
-
|
|
20960
|
-
|
|
20961
|
-
|
|
20962
|
-
|
|
20963
|
-
|
|
20964
|
-
|
|
20965
|
-
|
|
20966
|
-
|
|
20967
|
-
|
|
20968
|
-
|
|
20969
|
-
|
|
20970
|
-
|
|
20971
|
-
|
|
20972
|
-
|
|
20973
|
-
|
|
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
|
+
}
|
|
20974
21272
|
}
|
|
20975
21273
|
}
|
|
21274
|
+
} catch {
|
|
20976
21275
|
}
|
|
20977
|
-
|
|
20978
|
-
|
|
20979
|
-
|
|
20980
|
-
|
|
20981
|
-
|
|
20982
|
-
|
|
20983
|
-
|
|
20984
|
-
|
|
20985
|
-
|
|
20986
|
-
|
|
20987
|
-
|
|
20988
|
-
|
|
20989
|
-
|
|
20990
|
-
|
|
20991
|
-
|
|
20992
|
-
|
|
20993
|
-
|
|
20994
|
-
|
|
20995
|
-
|
|
20996
|
-
|
|
20997
|
-
|
|
20998
|
-
|
|
20999
|
-
|
|
21000
|
-
|
|
21001
|
-
|
|
21002
|
-
|
|
21003
|
-
|
|
21004
|
-
|
|
21005
|
-
|
|
21006
|
-
})));
|
|
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
|
+
}
|
|
21007
21305
|
}
|
|
21306
|
+
} catch {
|
|
21008
21307
|
}
|
|
21009
|
-
} catch {
|
|
21308
|
+
} catch (err) {
|
|
21309
|
+
setDbError(err instanceof Error ? err.message : "Unknown error");
|
|
21310
|
+
} finally {
|
|
21311
|
+
setLoading(false);
|
|
21010
21312
|
}
|
|
21011
|
-
}
|
|
21012
|
-
setDbError(true);
|
|
21013
|
-
} finally {
|
|
21014
|
-
setLoading(false);
|
|
21015
|
-
}
|
|
21313
|
+
});
|
|
21016
21314
|
}
|
|
21017
21315
|
const totalCount = members.length + externals.length;
|
|
21018
21316
|
const selected = allItems[selectedIdx];
|
|
@@ -21029,7 +21327,7 @@ function TeamView({ onBack }) {
|
|
|
21029
21327
|
/* @__PURE__ */ jsx12(Text, { children: " " }),
|
|
21030
21328
|
/* @__PURE__ */ jsxs10(Text, { children: [
|
|
21031
21329
|
"Role: ",
|
|
21032
|
-
/* @__PURE__ */ jsx12(Text, { bold: true, children: selected.role })
|
|
21330
|
+
/* @__PURE__ */ jsx12(Text, { bold: true, color: roleBadgeColor(selected.role), children: selected.role })
|
|
21033
21331
|
] }),
|
|
21034
21332
|
/* @__PURE__ */ jsxs10(Text, { children: [
|
|
21035
21333
|
"Status: ",
|
|
@@ -21058,8 +21356,9 @@ function TeamView({ onBack }) {
|
|
|
21058
21356
|
/* @__PURE__ */ jsx12(Box_default, { borderStyle: "single", borderColor: "#3D3660", paddingX: 1, alignSelf: "flex-start", children: /* @__PURE__ */ jsx12(Text, { bold: true, children: "Team Roster" }) }),
|
|
21059
21357
|
/* @__PURE__ */ jsxs10(Text, { color: "#6B4C9A", children: [
|
|
21060
21358
|
totalCount,
|
|
21061
|
-
" agents |
|
|
21359
|
+
" agents | \u2191\u2193 navigate | Enter details | a add | s sessions"
|
|
21062
21360
|
] }),
|
|
21361
|
+
showAddHint && /* @__PURE__ */ jsx12(Text, { color: "#F5D76E", children: "Run /exe-new-employee <name> from CLI to add an employee." }),
|
|
21063
21362
|
!demo && orch.pendingReviews > 0 && /* @__PURE__ */ jsxs10(Text, { color: "#6B4C9A", children: [
|
|
21064
21363
|
orch.pendingReviews,
|
|
21065
21364
|
" review(s) pending exe attention"
|
|
@@ -21067,7 +21366,10 @@ function TeamView({ onBack }) {
|
|
|
21067
21366
|
/* @__PURE__ */ jsx12(Text, { children: " " }),
|
|
21068
21367
|
/* @__PURE__ */ jsx12(Text, { bold: true, children: "INTERNAL" }),
|
|
21069
21368
|
/* @__PURE__ */ jsx12(Text, { children: " " }),
|
|
21070
|
-
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) => {
|
|
21071
21373
|
const isSelected = i === selectedIdx;
|
|
21072
21374
|
const orchEmp = orchEmployeeMap.get(m.name);
|
|
21073
21375
|
return /* @__PURE__ */ jsxs10(
|
|
@@ -21083,7 +21385,7 @@ function TeamView({ onBack }) {
|
|
|
21083
21385
|
/* @__PURE__ */ jsxs10(Box_default, { gap: 1, children: [
|
|
21084
21386
|
/* @__PURE__ */ jsx12(StatusDot, { status: m.status, showLabel: false }),
|
|
21085
21387
|
/* @__PURE__ */ jsx12(Text, { bold: true, color: isSelected ? "#F5D76E" : "#F0EDE8", children: m.name }),
|
|
21086
|
-
/* @__PURE__ */ jsxs10(Text, { color: isSelected ? "#F5D76E" :
|
|
21388
|
+
/* @__PURE__ */ jsxs10(Text, { color: isSelected ? "#F5D76E" : roleBadgeColor(m.role), children: [
|
|
21087
21389
|
"(",
|
|
21088
21390
|
m.role,
|
|
21089
21391
|
")"
|
|
@@ -21309,6 +21611,26 @@ var init_wiki_client = __esm({
|
|
|
21309
21611
|
import React23, { useState as useState13, useEffect as useEffect15 } from "react";
|
|
21310
21612
|
import TextInput2 from "ink-text-input";
|
|
21311
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
|
+
}
|
|
21312
21634
|
function WikiView({ onBack }) {
|
|
21313
21635
|
const demo = useDemo();
|
|
21314
21636
|
const [activePanel, setActivePanel] = useState13("Workspaces");
|
|
@@ -21319,6 +21641,12 @@ function WikiView({ onBack }) {
|
|
|
21319
21641
|
const [chatHistory, setChatHistory] = useState13([]);
|
|
21320
21642
|
const [chatInput, setChatInput] = useState13("");
|
|
21321
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);
|
|
21322
21650
|
const [loading, setLoading] = useState13(true);
|
|
21323
21651
|
const [connected, setConnected] = useState13(false);
|
|
21324
21652
|
const [wikiUrl, setWikiUrl] = useState13("");
|
|
@@ -21412,6 +21740,55 @@ function WikiView({ onBack }) {
|
|
|
21412
21740
|
setSending(false);
|
|
21413
21741
|
}
|
|
21414
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]);
|
|
21415
21792
|
async function selectWorkspace(idx) {
|
|
21416
21793
|
setSelectedWorkspaceIdx(idx);
|
|
21417
21794
|
const ws = workspaces[idx];
|
|
@@ -21432,6 +21809,32 @@ function WikiView({ onBack }) {
|
|
|
21432
21809
|
}
|
|
21433
21810
|
}
|
|
21434
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
|
+
}
|
|
21435
21838
|
if (chatFocused) {
|
|
21436
21839
|
if (key.escape) {
|
|
21437
21840
|
setChatFocused(false);
|
|
@@ -21443,6 +21846,13 @@ function WikiView({ onBack }) {
|
|
|
21443
21846
|
}
|
|
21444
21847
|
return;
|
|
21445
21848
|
}
|
|
21849
|
+
if (input === "/" && activePanel !== "Chat") {
|
|
21850
|
+
setSearchMode(true);
|
|
21851
|
+
setSearchQuery("");
|
|
21852
|
+
setSearchResults(demo ? DEMO_SEARCH_RESULTS : []);
|
|
21853
|
+
setExpandedResultIdx(null);
|
|
21854
|
+
return;
|
|
21855
|
+
}
|
|
21446
21856
|
if (key.leftArrow) {
|
|
21447
21857
|
const panelIdx = PANELS.indexOf(activePanel);
|
|
21448
21858
|
if (panelIdx === 0) {
|
|
@@ -21520,9 +21930,53 @@ function WikiView({ onBack }) {
|
|
|
21520
21930
|
/* @__PURE__ */ jsx13(Text, { bold: true, children: selectedWs.name })
|
|
21521
21931
|
] }) : null
|
|
21522
21932
|
] }),
|
|
21523
|
-
/* @__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" }),
|
|
21524
21934
|
/* @__PURE__ */ jsx13(Text, { children: " " }),
|
|
21525
|
-
/* @__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: [
|
|
21526
21980
|
/* @__PURE__ */ jsxs11(Box_default, { flexDirection: "column", width: "25%", children: [
|
|
21527
21981
|
/* @__PURE__ */ jsxs11(Text, { bold: true, backgroundColor: panelHeaderBg("Workspaces"), color: panelHeaderColor("Workspaces"), children: [
|
|
21528
21982
|
activePanel === "Workspaces" ? "\u25B8 " : " ",
|
|
@@ -21604,7 +22058,7 @@ function WikiView({ onBack }) {
|
|
|
21604
22058
|
] })
|
|
21605
22059
|
] });
|
|
21606
22060
|
}
|
|
21607
|
-
var PANELS, MAX_VISIBLE_MESSAGES;
|
|
22061
|
+
var PANELS, MAX_VISIBLE_MESSAGES, DEMO_SEARCH_RESULTS;
|
|
21608
22062
|
var init_Wiki = __esm({
|
|
21609
22063
|
async "src/tui/views/Wiki.tsx"() {
|
|
21610
22064
|
"use strict";
|
|
@@ -21613,53 +22067,48 @@ var init_Wiki = __esm({
|
|
|
21613
22067
|
init_demo_data();
|
|
21614
22068
|
PANELS = ["Workspaces", "Documents", "Chat"];
|
|
21615
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
|
+
];
|
|
21616
22077
|
}
|
|
21617
22078
|
});
|
|
21618
22079
|
|
|
21619
22080
|
// src/tui/views/Settings.tsx
|
|
21620
|
-
import React24, { useState as useState14, useEffect as useEffect16 } from "react";
|
|
22081
|
+
import React24, { useState as useState14, useEffect as useEffect16, useCallback as useCallback7 } from "react";
|
|
21621
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
|
+
}
|
|
21622
22087
|
function SettingsView({ onBack }) {
|
|
21623
22088
|
const [providers, setProviders] = useState14([]);
|
|
21624
|
-
const [
|
|
21625
|
-
|
|
21626
|
-
|
|
21627
|
-
|
|
21628
|
-
searchMode: "checking..."
|
|
21629
|
-
});
|
|
21630
|
-
const [runtime, setRuntime] = useState14({
|
|
21631
|
-
consolidation: true,
|
|
21632
|
-
consolidationModel: "...",
|
|
21633
|
-
skillLearning: true,
|
|
21634
|
-
skillThreshold: 3,
|
|
21635
|
-
skillModel: "...",
|
|
21636
|
-
failoverChain: ["anthropic", "opencode", "gemini", "openai"]
|
|
21637
|
-
});
|
|
21638
|
-
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: [] });
|
|
21639
22093
|
const [selectedSection, setSelectedSection] = useState14(0);
|
|
21640
22094
|
const [loading, setLoading] = useState14(true);
|
|
21641
|
-
const
|
|
21642
|
-
|
|
21643
|
-
|
|
21644
|
-
|
|
21645
|
-
|
|
21646
|
-
|
|
21647
|
-
|
|
21648
|
-
|
|
21649
|
-
onBack?.();
|
|
21650
|
-
return;
|
|
21651
|
-
}
|
|
21652
|
-
if (key.upArrow && selectedSection > 0) setSelectedSection(selectedSection - 1);
|
|
21653
|
-
if (key.downArrow && selectedSection < SECTION_NAMES.length - 1) setSelectedSection(selectedSection + 1);
|
|
21654
|
-
});
|
|
21655
|
-
async function loadSettings() {
|
|
21656
|
-
const providerList = [
|
|
21657
|
-
{ name: "Anthropic", configured: !!process.env.ANTHROPIC_API_KEY, detail: process.env.ANTHROPIC_API_KEY ? "ANTHROPIC_API_KEY set" : "not configured" },
|
|
21658
|
-
{ name: "OpenCode", configured: !!process.env.OPENCODE_API_KEY, detail: process.env.OPENCODE_API_KEY ? "OPENCODE_API_KEY set" : "not configured" },
|
|
21659
|
-
{ name: "Gemini", configured: !!process.env.GEMINI_API_KEY, detail: process.env.GEMINI_API_KEY ? "GEMINI_API_KEY set" : "not configured" },
|
|
21660
|
-
{ name: "OpenAI", configured: !!process.env.OPENAI_API_KEY, detail: process.env.OPENAI_API_KEY ? "OPENAI_API_KEY set" : "not configured" },
|
|
21661
|
-
{ 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"]
|
|
21662
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
|
+
});
|
|
21663
22112
|
try {
|
|
21664
22113
|
const { execSync: execSync13 } = await import("child_process");
|
|
21665
22114
|
execSync13("curl -s --max-time 1 http://localhost:11434/api/tags", { timeout: 2e3 });
|
|
@@ -21671,112 +22120,101 @@ function SettingsView({ onBack }) {
|
|
|
21671
22120
|
try {
|
|
21672
22121
|
const { existsSync: existsSync22 } = await import("fs");
|
|
21673
22122
|
const { join } = await import("path");
|
|
21674
|
-
const home = process.env.HOME ?? "";
|
|
21675
|
-
const hasKey = existsSync22(join(home, ".exe-os", "master.key"));
|
|
21676
22123
|
const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
21677
22124
|
const cfg = await loadConfig2();
|
|
21678
|
-
setMemory({
|
|
21679
|
-
encryption: hasKey ? "SQLCipher AES-256" : "not configured",
|
|
21680
|
-
embeddingModel: cfg.modelFile ?? "unknown",
|
|
21681
|
-
cloudSync: cfg.cloud ? "enabled" : "disabled",
|
|
21682
|
-
searchMode: cfg.searchMode ?? "hybrid"
|
|
21683
|
-
});
|
|
21684
|
-
const rawCfg = cfg;
|
|
21685
|
-
const chain = Array.isArray(rawCfg.failoverChain) ? rawCfg.failoverChain : ["anthropic", "opencode", "gemini", "openai"];
|
|
21686
|
-
setRuntime({
|
|
21687
|
-
consolidation: cfg.consolidationEnabled,
|
|
21688
|
-
consolidationModel: cfg.consolidationModel,
|
|
21689
|
-
skillLearning: cfg.skillLearning,
|
|
21690
|
-
skillThreshold: cfg.skillThreshold,
|
|
21691
|
-
skillModel: cfg.skillModel,
|
|
21692
|
-
failoverChain: chain
|
|
21693
|
-
});
|
|
21694
|
-
} catch {
|
|
21695
|
-
}
|
|
21696
|
-
try {
|
|
21697
|
-
const { loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
21698
|
-
const roster = await loadEmployees2();
|
|
21699
|
-
const { existsSync: existsSync22, readFileSync: readFileSync18 } = await import("fs");
|
|
21700
|
-
const { join } = await import("path");
|
|
21701
22125
|
const home = process.env.HOME ?? "";
|
|
21702
|
-
const
|
|
21703
|
-
|
|
21704
|
-
|
|
21705
|
-
|
|
21706
|
-
|
|
21707
|
-
|
|
21708
|
-
|
|
21709
|
-
|
|
21710
|
-
|
|
21711
|
-
}
|
|
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: "" });
|
|
21712
22135
|
}
|
|
21713
|
-
|
|
21714
|
-
|
|
21715
|
-
|
|
21716
|
-
|
|
21717
|
-
}
|
|
21718
|
-
} catch {
|
|
21719
|
-
}
|
|
21720
|
-
try {
|
|
21721
|
-
const { existsSync: existsSync22, readFileSync: readFileSync18 } = await import("fs");
|
|
21722
|
-
const { join } = await import("path");
|
|
21723
|
-
const home = process.env.HOME ?? "";
|
|
21724
|
-
const ccSettingsPath = join(home, ".claude", "settings.json");
|
|
21725
|
-
const installed = existsSync22(ccSettingsPath);
|
|
21726
|
-
let hooksWired = false;
|
|
21727
|
-
if (installed) {
|
|
21728
|
-
try {
|
|
21729
|
-
const settings = JSON.parse(readFileSync18(ccSettingsPath, "utf8"));
|
|
21730
|
-
const hooks = settings.hooks;
|
|
21731
|
-
if (hooks) {
|
|
21732
|
-
hooksWired = Object.values(hooks).flat().some((h) => h.command?.includes("exe-os") || h.command?.includes("exe-mem"));
|
|
21733
|
-
}
|
|
21734
|
-
} catch {
|
|
21735
|
-
}
|
|
22136
|
+
const pidPath = join(home, ".exe-os", "exed.pid");
|
|
22137
|
+
let daemon = "unknown";
|
|
22138
|
+
try {
|
|
22139
|
+
daemon = existsSync22(pidPath) ? "running" : "stopped";
|
|
22140
|
+
} catch {
|
|
21736
22141
|
}
|
|
21737
|
-
|
|
21738
|
-
|
|
21739
|
-
|
|
21740
|
-
|
|
21741
|
-
|
|
21742
|
-
|
|
21743
|
-
|
|
21744
|
-
|
|
21745
|
-
|
|
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 {
|
|
21746
22151
|
try {
|
|
21747
|
-
const
|
|
21748
|
-
|
|
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;
|
|
21749
22156
|
} catch {
|
|
21750
|
-
setLicense({ valid: false, detail: "invalid license file" });
|
|
21751
22157
|
}
|
|
21752
|
-
} else {
|
|
21753
|
-
setLicense({ valid: false, detail: "no license" });
|
|
21754
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
|
+
});
|
|
21755
22166
|
} catch {
|
|
21756
22167
|
}
|
|
21757
22168
|
try {
|
|
21758
|
-
const {
|
|
21759
|
-
const
|
|
21760
|
-
|
|
21761
|
-
|
|
21762
|
-
|
|
21763
|
-
|
|
21764
|
-
|
|
21765
|
-
|
|
21766
|
-
|
|
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
|
+
});
|
|
21767
22179
|
} catch {
|
|
22180
|
+
setLicense({ valid: false, plan: "FREE", expiresAt: null, deviceLimit: 1, employeeLimit: 1, memoryLimit: 5e3 });
|
|
21768
22181
|
}
|
|
21769
|
-
|
|
21770
|
-
|
|
21771
|
-
|
|
21772
|
-
|
|
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;
|
|
21773
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();
|
|
21774
22212
|
return /* @__PURE__ */ jsxs12(Box_default, { flexDirection: "column", flexGrow: 1, paddingX: 1, children: [
|
|
21775
22213
|
/* @__PURE__ */ jsx14(Box_default, { borderStyle: "single", borderColor: "#3D3660", paddingX: 1, alignSelf: "flex-start", children: /* @__PURE__ */ jsx14(Text, { bold: true, children: "Settings" }) }),
|
|
21776
|
-
/* @__PURE__ */ jsx14(Text, { color:
|
|
22214
|
+
/* @__PURE__ */ jsx14(Text, { color: DIM, children: "\u2191\u2193 navigate sections r refresh" }),
|
|
21777
22215
|
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21778
22216
|
loading && /* @__PURE__ */ jsxs12(Fragment5, { children: [
|
|
21779
|
-
/* @__PURE__ */ jsx14(Text, { color:
|
|
22217
|
+
/* @__PURE__ */ jsx14(Text, { color: DIM, children: "Loading settings..." }),
|
|
21780
22218
|
/* @__PURE__ */ jsx14(Text, { children: " " })
|
|
21781
22219
|
] }),
|
|
21782
22220
|
/* @__PURE__ */ jsxs12(Text, { bold: true, backgroundColor: sectionBg(0), color: sectionColor(0), children: [
|
|
@@ -21786,6 +22224,8 @@ function SettingsView({ onBack }) {
|
|
|
21786
22224
|
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21787
22225
|
providers.map((p) => /* @__PURE__ */ jsxs12(Text, { children: [
|
|
21788
22226
|
" ",
|
|
22227
|
+
/* @__PURE__ */ jsx14(Text, { color: statusColor(p.configured), children: statusDot(p.configured) }),
|
|
22228
|
+
" ",
|
|
21789
22229
|
p.name,
|
|
21790
22230
|
": ",
|
|
21791
22231
|
/* @__PURE__ */ jsx14(Text, { color: statusColor(p.configured), children: p.detail })
|
|
@@ -21793,131 +22233,274 @@ function SettingsView({ onBack }) {
|
|
|
21793
22233
|
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21794
22234
|
/* @__PURE__ */ jsxs12(Text, { bold: true, backgroundColor: sectionBg(1), color: sectionColor(1), children: [
|
|
21795
22235
|
sectionMarker(1),
|
|
21796
|
-
"
|
|
22236
|
+
"Cloud Sync"
|
|
21797
22237
|
] }),
|
|
21798
22238
|
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21799
|
-
/* @__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: [
|
|
21800
22257
|
" ",
|
|
21801
|
-
|
|
21802
|
-
|
|
22258
|
+
/* @__PURE__ */ jsx14(Text, { color: DIM, children: statusDot(false) }),
|
|
22259
|
+
" ",
|
|
22260
|
+
/* @__PURE__ */ jsx14(Text, { color: DIM, children: "Not configured \u2014 run /exe-cloud" })
|
|
21803
22261
|
] }),
|
|
21804
|
-
/* @__PURE__ */
|
|
21805
|
-
|
|
21806
|
-
|
|
21807
|
-
|
|
22262
|
+
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
22263
|
+
/* @__PURE__ */ jsxs12(Text, { bold: true, backgroundColor: sectionBg(2), color: sectionColor(2), children: [
|
|
22264
|
+
sectionMarker(2),
|
|
22265
|
+
"License"
|
|
21808
22266
|
] }),
|
|
22267
|
+
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21809
22268
|
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
21810
22269
|
" ",
|
|
21811
|
-
"
|
|
21812
|
-
/* @__PURE__ */ jsx14(Text, { color:
|
|
22270
|
+
"Plan: ",
|
|
22271
|
+
/* @__PURE__ */ jsx14(Text, { color: license.plan === "FREE" ? YELLOW : GREEN, children: license.plan })
|
|
21813
22272
|
] }),
|
|
21814
|
-
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
22273
|
+
license.expiresAt && /* @__PURE__ */ jsxs12(Text, { children: [
|
|
21815
22274
|
" ",
|
|
21816
|
-
"
|
|
21817
|
-
/* @__PURE__ */ jsx14(Text, { color:
|
|
21818
|
-
] }),
|
|
21819
|
-
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21820
|
-
/* @__PURE__ */ jsxs12(Text, { bold: true, backgroundColor: sectionBg(2), color: sectionColor(2), children: [
|
|
21821
|
-
sectionMarker(2),
|
|
21822
|
-
"Runtime"
|
|
22275
|
+
"Expires: ",
|
|
22276
|
+
/* @__PURE__ */ jsx14(Text, { color: GREEN, children: license.expiresAt.split("T")[0] })
|
|
21823
22277
|
] }),
|
|
21824
|
-
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21825
22278
|
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
21826
22279
|
" ",
|
|
21827
|
-
"
|
|
21828
|
-
/* @__PURE__ */ jsx14(Text, { color:
|
|
21829
|
-
" (",
|
|
21830
|
-
runtime.consolidationModel,
|
|
21831
|
-
")"
|
|
22280
|
+
"Devices: ",
|
|
22281
|
+
/* @__PURE__ */ jsx14(Text, { color: GREEN, children: formatLimit(license.deviceLimit) })
|
|
21832
22282
|
] }),
|
|
21833
22283
|
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
21834
22284
|
" ",
|
|
21835
|
-
"
|
|
21836
|
-
/* @__PURE__ */ jsx14(Text, { color:
|
|
21837
|
-
" (threshold: ",
|
|
21838
|
-
runtime.skillThreshold,
|
|
21839
|
-
")"
|
|
22285
|
+
"Employees: ",
|
|
22286
|
+
/* @__PURE__ */ jsx14(Text, { color: GREEN, children: formatLimit(license.employeeLimit) })
|
|
21840
22287
|
] }),
|
|
21841
22288
|
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
21842
22289
|
" ",
|
|
21843
|
-
"
|
|
21844
|
-
/* @__PURE__ */ jsx14(Text, { color:
|
|
22290
|
+
"Memory limit: ",
|
|
22291
|
+
/* @__PURE__ */ jsx14(Text, { color: GREEN, children: formatLimit(license.memoryLimit) })
|
|
21845
22292
|
] }),
|
|
21846
22293
|
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21847
22294
|
/* @__PURE__ */ jsxs12(Text, { bold: true, backgroundColor: sectionBg(3), color: sectionColor(3), children: [
|
|
21848
22295
|
sectionMarker(3),
|
|
21849
|
-
"
|
|
22296
|
+
"System"
|
|
21850
22297
|
] }),
|
|
21851
22298
|
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21852
|
-
|
|
21853
|
-
" ",
|
|
21854
|
-
"Loading..."
|
|
21855
|
-
] }) : employeeModels.length === 0 ? /* @__PURE__ */ jsxs12(Text, { color: "#6B4C9A", children: [
|
|
22299
|
+
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
21856
22300
|
" ",
|
|
21857
|
-
"
|
|
21858
|
-
|
|
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: [
|
|
21859
22306
|
" ",
|
|
21860
|
-
|
|
21861
|
-
|
|
21862
|
-
/* @__PURE__ */ jsx14(Text, { color: "#22C55E", children: e.model }),
|
|
21863
|
-
" ",
|
|
21864
|
-
/* @__PURE__ */ jsxs12(Text, { color: "#6B4C9A", children: [
|
|
21865
|
-
"via ",
|
|
21866
|
-
e.provider
|
|
21867
|
-
] })
|
|
21868
|
-
] }, e.name)),
|
|
21869
|
-
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21870
|
-
/* @__PURE__ */ jsxs12(Text, { bold: true, backgroundColor: sectionBg(4), color: sectionColor(4), children: [
|
|
21871
|
-
sectionMarker(4),
|
|
21872
|
-
"Integrations"
|
|
22307
|
+
"Version: ",
|
|
22308
|
+
/* @__PURE__ */ jsx14(Text, { color: GREEN, children: system.version })
|
|
21873
22309
|
] }),
|
|
21874
|
-
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21875
22310
|
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
21876
22311
|
" ",
|
|
21877
|
-
"
|
|
21878
|
-
/* @__PURE__ */ jsx14(Text, { color:
|
|
21879
|
-
claudeCode.installed && /* @__PURE__ */ jsxs12(Text, { color: claudeCode.hooksWired ? "#22C55E" : "#6B4C9A", children: [
|
|
21880
|
-
" \u2014 hooks ",
|
|
21881
|
-
claudeCode.hooksWired ? "wired" : "not wired"
|
|
21882
|
-
] })
|
|
22312
|
+
"Encryption: ",
|
|
22313
|
+
/* @__PURE__ */ jsx14(Text, { color: system.encryption.includes("AES") ? GREEN : DIM, children: system.encryption })
|
|
21883
22314
|
] }),
|
|
21884
22315
|
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
21885
22316
|
" ",
|
|
21886
|
-
"
|
|
21887
|
-
/* @__PURE__ */ jsx14(Text, { color:
|
|
22317
|
+
"Embedding: ",
|
|
22318
|
+
/* @__PURE__ */ jsx14(Text, { color: GREEN, children: system.embeddingModel })
|
|
21888
22319
|
] }),
|
|
21889
22320
|
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
21890
22321
|
" ",
|
|
21891
|
-
"
|
|
21892
|
-
/* @__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" })
|
|
21893
22343
|
] })
|
|
21894
22344
|
] });
|
|
21895
22345
|
}
|
|
21896
|
-
var SECTION_NAMES;
|
|
22346
|
+
var SECTION_NAMES, GREEN, DIM, YELLOW;
|
|
21897
22347
|
var init_Settings = __esm({
|
|
21898
22348
|
async "src/tui/views/Settings.tsx"() {
|
|
21899
22349
|
"use strict";
|
|
21900
22350
|
await init_ink2();
|
|
21901
|
-
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();
|
|
21902
22485
|
}
|
|
21903
22486
|
});
|
|
21904
22487
|
|
|
21905
22488
|
// src/tui/App.tsx
|
|
21906
22489
|
var App_exports = {};
|
|
21907
|
-
import { useState as
|
|
21908
|
-
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";
|
|
21909
22492
|
function App2() {
|
|
21910
|
-
const [section, setSection] =
|
|
22493
|
+
const [section, setSection] = useState16("command-center");
|
|
21911
22494
|
const { exit } = use_app_default();
|
|
21912
|
-
const [, forceUpdate] =
|
|
21913
|
-
|
|
22495
|
+
const [, forceUpdate] = useState16(0);
|
|
22496
|
+
useEffect18(() => {
|
|
21914
22497
|
const handleResize = () => forceUpdate((n) => n + 1);
|
|
21915
22498
|
process.stdout.on("resize", handleResize);
|
|
21916
22499
|
return () => {
|
|
21917
22500
|
process.stdout.off("resize", handleResize);
|
|
21918
22501
|
};
|
|
21919
22502
|
}, []);
|
|
21920
|
-
useMouseEvent(
|
|
22503
|
+
useMouseEvent(useCallback8((event) => {
|
|
21921
22504
|
if (event.button !== 0) return;
|
|
21922
22505
|
if (event.col <= 26) {
|
|
21923
22506
|
const tabIdx = event.row - 4;
|
|
@@ -21929,22 +22512,33 @@ function App2() {
|
|
|
21929
22512
|
setFocus("content");
|
|
21930
22513
|
}
|
|
21931
22514
|
}, []));
|
|
21932
|
-
const [focus, setFocus] =
|
|
21933
|
-
const [
|
|
21934
|
-
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) => {
|
|
21935
22520
|
setFocusedProject(projectName);
|
|
21936
22521
|
setSection("sessions");
|
|
21937
22522
|
setFocus("content");
|
|
21938
22523
|
}, []);
|
|
21939
|
-
const handleBackToCommandCenter =
|
|
22524
|
+
const handleBackToCommandCenter = useCallback8(() => {
|
|
21940
22525
|
setSection("command-center");
|
|
21941
22526
|
setFocus("sidebar");
|
|
21942
22527
|
}, []);
|
|
21943
22528
|
use_input_default((input, key) => {
|
|
22529
|
+
if (input === "?" || key.shift && input === "/") {
|
|
22530
|
+
setShowHelp((prev) => !prev);
|
|
22531
|
+
return;
|
|
22532
|
+
}
|
|
21944
22533
|
const idx = parseInt(input, 10);
|
|
21945
22534
|
if (idx >= 1 && idx <= SECTIONS.length) {
|
|
21946
22535
|
setSection(SECTIONS[idx - 1].key);
|
|
21947
22536
|
setFocus("sidebar");
|
|
22537
|
+
setShowHelp(false);
|
|
22538
|
+
return;
|
|
22539
|
+
}
|
|
22540
|
+
if (input === "d" && !key.ctrl) {
|
|
22541
|
+
setShowDebug((prev) => !prev);
|
|
21948
22542
|
return;
|
|
21949
22543
|
}
|
|
21950
22544
|
if (input === "q" && !key.ctrl) {
|
|
@@ -21972,27 +22566,37 @@ function App2() {
|
|
|
21972
22566
|
}
|
|
21973
22567
|
}
|
|
21974
22568
|
});
|
|
21975
|
-
const consumeFocusedProject =
|
|
22569
|
+
const consumeFocusedProject = useCallback8(() => {
|
|
21976
22570
|
setFocusedProject(null);
|
|
21977
22571
|
}, []);
|
|
21978
22572
|
const views = {
|
|
21979
|
-
"command-center": /* @__PURE__ */
|
|
21980
|
-
sessions: /* @__PURE__ */
|
|
21981
|
-
tasks: /* @__PURE__ */
|
|
21982
|
-
team: /* @__PURE__ */
|
|
21983
|
-
|
|
21984
|
-
|
|
21985
|
-
|
|
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") })
|
|
21986
22584
|
};
|
|
21987
|
-
return /* @__PURE__ */
|
|
21988
|
-
/* @__PURE__ */
|
|
21989
|
-
/* @__PURE__ */
|
|
21990
|
-
|
|
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]
|
|
21991
22595
|
] }),
|
|
21992
|
-
/* @__PURE__ */
|
|
22596
|
+
/* @__PURE__ */ jsx17(Footer, {})
|
|
21993
22597
|
] }) }) }) });
|
|
21994
22598
|
}
|
|
21995
|
-
var isDemo;
|
|
22599
|
+
var TAB_SHORTCUTS, isDemo;
|
|
21996
22600
|
var init_App2 = __esm({
|
|
21997
22601
|
async "src/tui/App.tsx"() {
|
|
21998
22602
|
"use strict";
|
|
@@ -22010,6 +22614,73 @@ var init_App2 = __esm({
|
|
|
22010
22614
|
await init_Team();
|
|
22011
22615
|
await init_Wiki();
|
|
22012
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
|
+
};
|
|
22013
22684
|
isDemo = process.argv.includes("--demo");
|
|
22014
22685
|
process.stderr.write(`[exe-tui] Terminal: ${TERMINAL_TYPE}
|
|
22015
22686
|
`);
|
|
@@ -22050,7 +22721,7 @@ var init_App2 = __esm({
|
|
|
22050
22721
|
stdin.unref = () => stdin;
|
|
22051
22722
|
}
|
|
22052
22723
|
}
|
|
22053
|
-
render_default(/* @__PURE__ */
|
|
22724
|
+
render_default(/* @__PURE__ */ jsx17(App2, {}));
|
|
22054
22725
|
}
|
|
22055
22726
|
});
|
|
22056
22727
|
|