@askexenow/exe-os 0.8.41 → 0.8.43
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 +1345 -660
- package/dist/bin/exe-agent.js +20 -1
- package/dist/bin/exe-assign.js +1503 -1343
- package/dist/bin/exe-boot.js +2518 -1798
- package/dist/bin/exe-call.js +39 -1
- package/dist/bin/exe-cloud.js +15 -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 +2500 -1877
- 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 +28 -2
- package/dist/bin/exe-new-employee.js +25 -3
- 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 +62 -26
- 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 +1439 -815
- 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 +1714 -1537
- package/dist/hooks/prompt-submit.js +2658 -1113
- package/dist/hooks/response-ingest-worker.js +170 -6
- 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 +179 -7
- package/dist/index.js +278 -100
- package/dist/lib/cloud-sync.js +28 -2
- 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/license.js +15 -1
- 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 +1825 -1138
- 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 +1452 -644
- 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;
|
|
@@ -4652,7 +4805,21 @@ function getCacheAgeMs() {
|
|
|
4652
4805
|
}
|
|
4653
4806
|
}
|
|
4654
4807
|
async function checkLicense() {
|
|
4655
|
-
|
|
4808
|
+
let key = loadLicense();
|
|
4809
|
+
if (!key) {
|
|
4810
|
+
try {
|
|
4811
|
+
const configPath = path11.join(EXE_AI_DIR, "config.json");
|
|
4812
|
+
if (existsSync10(configPath)) {
|
|
4813
|
+
const raw = JSON.parse(readFileSync6(configPath, "utf8"));
|
|
4814
|
+
const cloud = raw.cloud;
|
|
4815
|
+
if (cloud?.apiKey) {
|
|
4816
|
+
key = cloud.apiKey;
|
|
4817
|
+
saveLicense(key);
|
|
4818
|
+
}
|
|
4819
|
+
}
|
|
4820
|
+
} catch {
|
|
4821
|
+
}
|
|
4822
|
+
}
|
|
4656
4823
|
if (!key) return FREE_LICENSE;
|
|
4657
4824
|
const cached = await getCachedLicense();
|
|
4658
4825
|
if (cached && getCacheAgeMs() < CACHE_MAX_AGE_MS) return cached;
|
|
@@ -12309,6 +12476,73 @@ var init_Sidebar = __esm({
|
|
|
12309
12476
|
}
|
|
12310
12477
|
});
|
|
12311
12478
|
|
|
12479
|
+
// src/lib/telemetry.ts
|
|
12480
|
+
var telemetry_exports = {};
|
|
12481
|
+
__export(telemetry_exports, {
|
|
12482
|
+
instrumentServer: () => instrumentServer,
|
|
12483
|
+
withTrace: () => withTrace
|
|
12484
|
+
});
|
|
12485
|
+
async function ensureInit() {
|
|
12486
|
+
if (initialized || !ENABLED) return;
|
|
12487
|
+
initialized = true;
|
|
12488
|
+
try {
|
|
12489
|
+
const { NodeSDK } = await import("@opentelemetry/sdk-node");
|
|
12490
|
+
const { ConsoleSpanExporter } = await import("@opentelemetry/sdk-trace-base");
|
|
12491
|
+
const sdk = new NodeSDK({
|
|
12492
|
+
serviceName: "exe-os",
|
|
12493
|
+
traceExporter: new ConsoleSpanExporter()
|
|
12494
|
+
});
|
|
12495
|
+
sdk.start();
|
|
12496
|
+
process.stderr.write("[exe-os] OpenTelemetry tracing enabled\n");
|
|
12497
|
+
} catch (err) {
|
|
12498
|
+
process.stderr.write(
|
|
12499
|
+
`[exe-os] OpenTelemetry init failed: ${err instanceof Error ? err.message : String(err)}
|
|
12500
|
+
`
|
|
12501
|
+
);
|
|
12502
|
+
}
|
|
12503
|
+
}
|
|
12504
|
+
async function withTrace(toolName, fn) {
|
|
12505
|
+
if (!ENABLED) return fn();
|
|
12506
|
+
await ensureInit();
|
|
12507
|
+
const { trace, SpanStatusCode } = await import("@opentelemetry/api");
|
|
12508
|
+
const tracer = trace.getTracer("exe-os", "1.0.0");
|
|
12509
|
+
return tracer.startActiveSpan(`mcp.tool.${toolName}`, async (span) => {
|
|
12510
|
+
span.setAttribute("mcp.tool.name", toolName);
|
|
12511
|
+
try {
|
|
12512
|
+
const result = await fn();
|
|
12513
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
12514
|
+
return result;
|
|
12515
|
+
} catch (err) {
|
|
12516
|
+
span.setStatus({
|
|
12517
|
+
code: SpanStatusCode.ERROR,
|
|
12518
|
+
message: err instanceof Error ? err.message : String(err)
|
|
12519
|
+
});
|
|
12520
|
+
span.recordException(
|
|
12521
|
+
err instanceof Error ? err : new Error(String(err))
|
|
12522
|
+
);
|
|
12523
|
+
throw err;
|
|
12524
|
+
} finally {
|
|
12525
|
+
span.end();
|
|
12526
|
+
}
|
|
12527
|
+
});
|
|
12528
|
+
}
|
|
12529
|
+
function instrumentServer(server) {
|
|
12530
|
+
if (!ENABLED) return;
|
|
12531
|
+
const original = server.registerTool.bind(server);
|
|
12532
|
+
server.registerTool = (name, config, handler) => {
|
|
12533
|
+
const traced = async (...args2) => withTrace(name, () => handler(...args2));
|
|
12534
|
+
return original(name, config, traced);
|
|
12535
|
+
};
|
|
12536
|
+
}
|
|
12537
|
+
var ENABLED, initialized;
|
|
12538
|
+
var init_telemetry = __esm({
|
|
12539
|
+
"src/lib/telemetry.ts"() {
|
|
12540
|
+
"use strict";
|
|
12541
|
+
ENABLED = process.env.EXE_TELEMETRY === "1";
|
|
12542
|
+
initialized = false;
|
|
12543
|
+
}
|
|
12544
|
+
});
|
|
12545
|
+
|
|
12312
12546
|
// src/lib/tmux-status.ts
|
|
12313
12547
|
var tmux_status_exports = {};
|
|
12314
12548
|
__export(tmux_status_exports, {
|
|
@@ -12603,61 +12837,64 @@ function Footer() {
|
|
|
12603
12837
|
return () => clearInterval(timer);
|
|
12604
12838
|
}, []);
|
|
12605
12839
|
async function loadFooterData() {
|
|
12606
|
-
|
|
12607
|
-
|
|
12608
|
-
|
|
12609
|
-
|
|
12610
|
-
const
|
|
12611
|
-
|
|
12840
|
+
const { withTrace: withTrace2 } = await Promise.resolve().then(() => (init_telemetry(), telemetry_exports));
|
|
12841
|
+
return withTrace2("tui.footer.loadData", async () => {
|
|
12842
|
+
try {
|
|
12843
|
+
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
12844
|
+
const client = getClient2();
|
|
12845
|
+
if (client) {
|
|
12846
|
+
const result = await client.execute("SELECT COUNT(*) as cnt FROM memories");
|
|
12847
|
+
setMemoryCount(Number(result.rows[0]?.cnt ?? 0));
|
|
12848
|
+
}
|
|
12849
|
+
} catch {
|
|
12612
12850
|
}
|
|
12613
|
-
|
|
12614
|
-
|
|
12615
|
-
|
|
12616
|
-
|
|
12617
|
-
|
|
12618
|
-
|
|
12619
|
-
|
|
12620
|
-
|
|
12621
|
-
|
|
12622
|
-
|
|
12851
|
+
try {
|
|
12852
|
+
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
12853
|
+
const client = getClient2();
|
|
12854
|
+
if (client) {
|
|
12855
|
+
const result = await client.execute(
|
|
12856
|
+
"SELECT COUNT(*) as cnt FROM tasks WHERE status IN ('open','in_progress')"
|
|
12857
|
+
);
|
|
12858
|
+
setTaskCount(Number(result.rows[0]?.cnt ?? 0));
|
|
12859
|
+
}
|
|
12860
|
+
} catch {
|
|
12623
12861
|
}
|
|
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 {
|
|
12862
|
+
try {
|
|
12863
|
+
const { existsSync: existsSync22 } = await import("fs");
|
|
12864
|
+
const { join } = await import("path");
|
|
12865
|
+
const home = process.env.HOME ?? "";
|
|
12866
|
+
const pidPath = join(home, ".exe-os", "exed.pid");
|
|
12867
|
+
setDaemon(existsSync22(pidPath) ? "running" : "stopped");
|
|
12868
|
+
} catch {
|
|
12869
|
+
setDaemon("unknown");
|
|
12870
|
+
}
|
|
12871
|
+
try {
|
|
12872
|
+
const { checkLicense: checkLicense2 } = await Promise.resolve().then(() => (init_license(), license_exports));
|
|
12873
|
+
const license = await checkLicense2();
|
|
12874
|
+
setPlan(license.plan);
|
|
12875
|
+
} catch {
|
|
12876
|
+
setPlan("free");
|
|
12877
|
+
}
|
|
12878
|
+
try {
|
|
12879
|
+
const { listTmuxSessions: listTmuxSessions2, inTmux: inTmux2 } = await Promise.resolve().then(() => (init_tmux_status(), tmux_status_exports));
|
|
12880
|
+
if (inTmux2()) {
|
|
12881
|
+
const allSessions = listTmuxSessions2();
|
|
12882
|
+
setSessions(allSessions.length);
|
|
12883
|
+
if (!currentSession) {
|
|
12884
|
+
try {
|
|
12885
|
+
const { execSync: execSync13 } = await import("child_process");
|
|
12886
|
+
const name = execSync13("tmux display-message -p '#{session_name}' 2>/dev/null", {
|
|
12887
|
+
encoding: "utf8",
|
|
12888
|
+
timeout: 2e3
|
|
12889
|
+
}).trim();
|
|
12890
|
+
if (name) setCurrentSession(name);
|
|
12891
|
+
} catch {
|
|
12892
|
+
}
|
|
12656
12893
|
}
|
|
12657
12894
|
}
|
|
12895
|
+
} catch {
|
|
12658
12896
|
}
|
|
12659
|
-
}
|
|
12660
|
-
}
|
|
12897
|
+
});
|
|
12661
12898
|
}
|
|
12662
12899
|
return /* @__PURE__ */ jsxs3(Box_default, { flexDirection: "column", children: [
|
|
12663
12900
|
/* @__PURE__ */ jsx5(Text, { color: "#3D3660", children: "\u2500".repeat(process.stdout.columns || 120) }),
|
|
@@ -12698,6 +12935,8 @@ function Footer() {
|
|
|
12698
12935
|
] }),
|
|
12699
12936
|
/* @__PURE__ */ jsx5(Text, { color: "#6B4C9A", children: "1-7 navigate" }),
|
|
12700
12937
|
/* @__PURE__ */ jsx5(Text, { color: "#3D3660", children: "\u2502" }),
|
|
12938
|
+
/* @__PURE__ */ jsx5(Text, { color: "#6B4C9A", children: "d debug" }),
|
|
12939
|
+
/* @__PURE__ */ jsx5(Text, { color: "#3D3660", children: "\u2502" }),
|
|
12701
12940
|
/* @__PURE__ */ jsx5(Text, { color: "#6B4C9A", children: "q quit" })
|
|
12702
12941
|
] })
|
|
12703
12942
|
] })
|
|
@@ -14346,7 +14585,7 @@ var init_anthropic = __esm({
|
|
|
14346
14585
|
|
|
14347
14586
|
// src/gateway/providers/openai-compat.ts
|
|
14348
14587
|
import OpenAI from "openai";
|
|
14349
|
-
import { randomUUID as
|
|
14588
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
14350
14589
|
var OpenAICompatProvider;
|
|
14351
14590
|
var init_openai_compat = __esm({
|
|
14352
14591
|
"src/gateway/providers/openai-compat.ts"() {
|
|
@@ -14463,7 +14702,7 @@ var init_openai_compat = __esm({
|
|
|
14463
14702
|
}
|
|
14464
14703
|
content.push({
|
|
14465
14704
|
type: "tool_use",
|
|
14466
|
-
id: call.id ??
|
|
14705
|
+
id: call.id ?? randomUUID4(),
|
|
14467
14706
|
name: fn.name,
|
|
14468
14707
|
input
|
|
14469
14708
|
});
|
|
@@ -15537,7 +15776,7 @@ function CommandCenterView({
|
|
|
15537
15776
|
setAgentConfig({
|
|
15538
15777
|
provider,
|
|
15539
15778
|
model,
|
|
15540
|
-
systemPrompt: "You are an AI assistant in the exe-os TUI. Help the user with their questions. Be concise.",
|
|
15779
|
+
systemPrompt: getSessionPrompt("You are an AI assistant in the exe-os TUI. Help the user with their questions. Be concise."),
|
|
15541
15780
|
tools: registry,
|
|
15542
15781
|
hooks: createDefaultHooks2(),
|
|
15543
15782
|
permissions,
|
|
@@ -15658,6 +15897,7 @@ function CommandCenterView({
|
|
|
15658
15897
|
employeeCount: p.employees.length,
|
|
15659
15898
|
activeCount: p.employees.filter((e) => e.status === "active").length,
|
|
15660
15899
|
memoryCount: p.employees.length * 4e3,
|
|
15900
|
+
openTaskCount: Math.floor(p.employees.length * 1.5),
|
|
15661
15901
|
status: p.employees.some((e) => e.status === "active") ? "active" : "idle",
|
|
15662
15902
|
type: p.projectName.startsWith("exe-") ? "code" : "automation",
|
|
15663
15903
|
recentTasks: DEMO_RECENT_TASKS[p.projectName] ?? []
|
|
@@ -15669,6 +15909,7 @@ function CommandCenterView({
|
|
|
15669
15909
|
employeeCount: 0,
|
|
15670
15910
|
activeCount: 0,
|
|
15671
15911
|
memoryCount: 0,
|
|
15912
|
+
openTaskCount: 0,
|
|
15672
15913
|
status: "offline",
|
|
15673
15914
|
type: "reference",
|
|
15674
15915
|
recentTasks: []
|
|
@@ -15683,182 +15924,122 @@ function CommandCenterView({
|
|
|
15683
15924
|
return () => clearInterval(timer);
|
|
15684
15925
|
}, []);
|
|
15685
15926
|
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();
|
|
15927
|
+
const { withTrace: withTrace2 } = await Promise.resolve().then(() => (init_telemetry(), telemetry_exports));
|
|
15928
|
+
return withTrace2("tui.commandCenter.loadData", async () => {
|
|
15706
15929
|
try {
|
|
15707
15930
|
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
15931
|
+
const { listSessions: listSessions2 } = await Promise.resolve().then(() => (init_session_registry(), session_registry_exports));
|
|
15932
|
+
const { listTmuxSessions: listTmuxSessions2, inTmux: inTmux2 } = await Promise.resolve().then(() => (init_tmux_status(), tmux_status_exports));
|
|
15933
|
+
const { loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
15934
|
+
const { existsSync: existsSync22 } = await import("fs");
|
|
15935
|
+
const { join } = await import("path");
|
|
15708
15936
|
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
|
-
}
|
|
15937
|
+
if (!client) {
|
|
15938
|
+
setDbError(true);
|
|
15939
|
+
return;
|
|
15726
15940
|
}
|
|
15727
|
-
|
|
15728
|
-
|
|
15729
|
-
|
|
15730
|
-
|
|
15731
|
-
|
|
15941
|
+
const dbProjects = await client.execute(
|
|
15942
|
+
`SELECT DISTINCT project_name FROM memories WHERE project_name IS NOT NULL AND project_name != ''
|
|
15943
|
+
UNION
|
|
15944
|
+
SELECT DISTINCT project_name FROM tasks WHERE project_name IS NOT NULL AND project_name != ''
|
|
15945
|
+
ORDER BY project_name`
|
|
15946
|
+
);
|
|
15947
|
+
const projectNames = dbProjects.rows.map((r) => String(r.project_name));
|
|
15948
|
+
const memResult = await client.execute(
|
|
15949
|
+
"SELECT project_name, COUNT(*) as cnt FROM memories WHERE project_name IS NOT NULL GROUP BY project_name"
|
|
15950
|
+
);
|
|
15951
|
+
const memoryCounts = /* @__PURE__ */ new Map();
|
|
15952
|
+
for (const row of memResult.rows) {
|
|
15953
|
+
memoryCounts.set(String(row.project_name), Number(row.cnt));
|
|
15954
|
+
}
|
|
15955
|
+
const taskCountResult = await client.execute(
|
|
15956
|
+
"SELECT project_name, COUNT(*) as cnt FROM tasks WHERE status IN ('open', 'in_progress') AND project_name IS NOT NULL GROUP BY project_name"
|
|
15957
|
+
);
|
|
15958
|
+
const openTaskCounts = /* @__PURE__ */ new Map();
|
|
15959
|
+
for (const row of taskCountResult.rows) {
|
|
15960
|
+
openTaskCounts.set(String(row.project_name), Number(row.cnt));
|
|
15961
|
+
}
|
|
15962
|
+
const recentResult = await client.execute(
|
|
15963
|
+
"SELECT project_name, title FROM tasks WHERE status = 'done' AND project_name IS NOT NULL ORDER BY updated_at DESC LIMIT 30"
|
|
15964
|
+
);
|
|
15965
|
+
const recentTasksByProject = /* @__PURE__ */ new Map();
|
|
15966
|
+
for (const row of recentResult.rows) {
|
|
15967
|
+
const name = String(row.project_name);
|
|
15968
|
+
const tasks = recentTasksByProject.get(name) ?? [];
|
|
15969
|
+
if (tasks.length < 3) tasks.push(String(row.title));
|
|
15970
|
+
recentTasksByProject.set(name, tasks);
|
|
15971
|
+
}
|
|
15972
|
+
const registry = listSessions2();
|
|
15973
|
+
const tmuxSessions = inTmux2() ? new Set(listTmuxSessions2()) : /* @__PURE__ */ new Set();
|
|
15974
|
+
const roster = await loadEmployees2();
|
|
15732
15975
|
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
|
-
});
|
|
15976
|
+
const projectSessions = /* @__PURE__ */ new Map();
|
|
15977
|
+
for (const entry of registry) {
|
|
15978
|
+
if (entry.agentId === "exe" && tmuxSessions.has(entry.windowName)) {
|
|
15979
|
+
const projName = entry.projectDir.split("/").filter(Boolean).pop() ?? "";
|
|
15980
|
+
if (projName) {
|
|
15981
|
+
projectSessions.set(projName, { exeSession: entry.windowName, projectDir: entry.projectDir });
|
|
15982
|
+
}
|
|
15808
15983
|
}
|
|
15809
15984
|
}
|
|
15810
|
-
|
|
15811
|
-
|
|
15812
|
-
|
|
15813
|
-
|
|
15814
|
-
|
|
15815
|
-
|
|
15816
|
-
|
|
15817
|
-
|
|
15818
|
-
|
|
15819
|
-
|
|
15820
|
-
|
|
15821
|
-
|
|
15822
|
-
|
|
15985
|
+
const projectList = [];
|
|
15986
|
+
for (const name of projectNames) {
|
|
15987
|
+
const session = projectSessions.get(name);
|
|
15988
|
+
const exeSession = session?.exeSession ?? "";
|
|
15989
|
+
const projectDir = session?.projectDir ?? "";
|
|
15990
|
+
let activeCount = 0;
|
|
15991
|
+
if (exeSession && tmuxSessions.has(exeSession)) {
|
|
15992
|
+
activeCount = 1;
|
|
15993
|
+
for (const empName of employeeNames) {
|
|
15994
|
+
if (tmuxSessions.has(`${empName}-${exeSession}`)) activeCount++;
|
|
15995
|
+
}
|
|
15996
|
+
}
|
|
15997
|
+
const memoryCount = memoryCounts.get(name) ?? 0;
|
|
15998
|
+
const openTaskCount = openTaskCounts.get(name) ?? 0;
|
|
15999
|
+
const hasGit = projectDir ? existsSync22(join(projectDir, ".git")) : false;
|
|
16000
|
+
const type = hasGit ? "code" : memoryCount > 0 ? "code" : "automation";
|
|
16001
|
+
projectList.push({
|
|
16002
|
+
projectName: name,
|
|
16003
|
+
exeSession,
|
|
16004
|
+
projectDir,
|
|
16005
|
+
employeeCount: activeCount,
|
|
16006
|
+
activeCount,
|
|
16007
|
+
memoryCount,
|
|
16008
|
+
openTaskCount,
|
|
16009
|
+
status: activeCount > 0 ? "active" : "idle",
|
|
16010
|
+
type,
|
|
16011
|
+
recentTasks: recentTasksByProject.get(name) ?? []
|
|
16012
|
+
});
|
|
16013
|
+
}
|
|
16014
|
+
projectList.sort((a, b) => {
|
|
16015
|
+
if (a.activeCount > 0 && b.activeCount === 0) return -1;
|
|
16016
|
+
if (a.activeCount === 0 && b.activeCount > 0) return 1;
|
|
16017
|
+
return b.memoryCount - a.memoryCount;
|
|
15823
16018
|
});
|
|
15824
|
-
|
|
15825
|
-
|
|
15826
|
-
|
|
15827
|
-
|
|
15828
|
-
|
|
15829
|
-
|
|
15830
|
-
|
|
15831
|
-
setHealth((h) => ({ ...h, memories: Number(result.rows[0]?.cnt ?? 0) }));
|
|
16019
|
+
setProjects(projectList);
|
|
16020
|
+
const totalResult = await client.execute("SELECT COUNT(*) as cnt FROM memories");
|
|
16021
|
+
setHealth((h) => ({ ...h, memories: Number(totalResult.rows[0]?.cnt ?? 0) }));
|
|
16022
|
+
try {
|
|
16023
|
+
const pidPath = join(process.env.HOME ?? "", ".exe-os", "exed.pid");
|
|
16024
|
+
setHealth((h) => ({ ...h, daemon: existsSync22(pidPath) ? "running" : "stopped" }));
|
|
16025
|
+
} catch {
|
|
15832
16026
|
}
|
|
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
|
-
}
|
|
16027
|
+
const activityResult = await client.execute(
|
|
16028
|
+
"SELECT agent_id, tool_name, project_name, created_at, text FROM memories ORDER BY created_at DESC LIMIT 20"
|
|
16029
|
+
);
|
|
16030
|
+
if (activityResult.rows.length > 0) {
|
|
16031
|
+
setActivity(activityResult.rows.slice(0, 8).map((r) => ({
|
|
16032
|
+
time: new Date(String(r.created_at)).toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit", hour12: false }),
|
|
16033
|
+
agent: String(r.agent_id ?? "system"),
|
|
16034
|
+
action: String(r.text ?? "").slice(0, 60)
|
|
16035
|
+
})));
|
|
15854
16036
|
}
|
|
15855
16037
|
} catch {
|
|
16038
|
+
setDbError(true);
|
|
16039
|
+
} finally {
|
|
16040
|
+
setLoading(false);
|
|
15856
16041
|
}
|
|
15857
|
-
}
|
|
15858
|
-
setDbError(true);
|
|
15859
|
-
} finally {
|
|
15860
|
-
setLoading(false);
|
|
15861
|
-
}
|
|
16042
|
+
});
|
|
15862
16043
|
}
|
|
15863
16044
|
const daemonColor = health.daemon === "running" ? "green" : health.daemon === "stopped" ? "red" : "gray";
|
|
15864
16045
|
const handleChatSubmit = useCallback4((value) => {
|
|
@@ -15950,7 +16131,7 @@ function CommandCenterView({
|
|
|
15950
16131
|
] }),
|
|
15951
16132
|
/* @__PURE__ */ jsx7(Text, { color: "#6B4C9A", children: "\u2191\u2193 navigate | c to chat | Enter to open | Escape to detach" }),
|
|
15952
16133
|
/* @__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: "
|
|
16134
|
+
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
16135
|
const sections = [];
|
|
15955
16136
|
let currentProjects = [];
|
|
15956
16137
|
let sectionKey = 0;
|
|
@@ -15980,9 +16161,9 @@ function CommandCenterView({
|
|
|
15980
16161
|
] })
|
|
15981
16162
|
] }),
|
|
15982
16163
|
/* @__PURE__ */ jsxs5(Text, { color: isSelected ? "#F0EDE8" : "#6B4C9A", children: [
|
|
15983
|
-
entry.
|
|
16164
|
+
entry.openTaskCount,
|
|
15984
16165
|
" ",
|
|
15985
|
-
entry.
|
|
16166
|
+
entry.openTaskCount === 1 ? "task" : "tasks",
|
|
15986
16167
|
" \xB7 ",
|
|
15987
16168
|
entry.memoryCount.toLocaleString(),
|
|
15988
16169
|
" memories"
|
|
@@ -16060,6 +16241,7 @@ var init_CommandCenter = __esm({
|
|
|
16060
16241
|
init_DemoContext();
|
|
16061
16242
|
init_demo_data();
|
|
16062
16243
|
init_useAgentLoop();
|
|
16244
|
+
init_employee_templates();
|
|
16063
16245
|
}
|
|
16064
16246
|
});
|
|
16065
16247
|
|
|
@@ -16184,7 +16366,7 @@ var init_TmuxPane = __esm({
|
|
|
16184
16366
|
});
|
|
16185
16367
|
|
|
16186
16368
|
// src/lib/task-router.ts
|
|
16187
|
-
import { randomUUID as
|
|
16369
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
16188
16370
|
function resolveBloomRouting(complexity, config = DEFAULT_BLOOM_CONFIG) {
|
|
16189
16371
|
const tier = config.complexityToTier[complexity];
|
|
16190
16372
|
const rule = config.tierRules[tier];
|
|
@@ -16836,9 +17018,15 @@ async function createTaskCore(input) {
|
|
|
16836
17018
|
}
|
|
16837
17019
|
}
|
|
16838
17020
|
const complexity = input.complexity ?? "standard";
|
|
17021
|
+
let sessionScope = null;
|
|
17022
|
+
try {
|
|
17023
|
+
const { resolveExeSession: resolveExeSession2 } = await Promise.resolve().then(() => (init_tmux_routing(), tmux_routing_exports));
|
|
17024
|
+
sessionScope = resolveExeSession2();
|
|
17025
|
+
} catch {
|
|
17026
|
+
}
|
|
16839
17027
|
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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
17028
|
+
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)
|
|
17029
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
16842
17030
|
args: [
|
|
16843
17031
|
id,
|
|
16844
17032
|
input.title,
|
|
@@ -16857,6 +17045,7 @@ async function createTaskCore(input) {
|
|
|
16857
17045
|
input.budgetFallbackModel ?? null,
|
|
16858
17046
|
0,
|
|
16859
17047
|
null,
|
|
17048
|
+
sessionScope,
|
|
16860
17049
|
now,
|
|
16861
17050
|
now
|
|
16862
17051
|
]
|
|
@@ -16901,6 +17090,15 @@ async function listTasks(input) {
|
|
|
16901
17090
|
conditions.push("priority = ?");
|
|
16902
17091
|
args2.push(input.priority);
|
|
16903
17092
|
}
|
|
17093
|
+
try {
|
|
17094
|
+
const { resolveExeSession: resolveExeSession2 } = await Promise.resolve().then(() => (init_tmux_routing(), tmux_routing_exports));
|
|
17095
|
+
const session = resolveExeSession2();
|
|
17096
|
+
if (session) {
|
|
17097
|
+
conditions.push("(session_scope IS NULL OR session_scope = ?)");
|
|
17098
|
+
args2.push(session);
|
|
17099
|
+
}
|
|
17100
|
+
} catch {
|
|
17101
|
+
}
|
|
16904
17102
|
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
16905
17103
|
const result = await client.execute({
|
|
16906
17104
|
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 +17463,7 @@ var init_tasks_review = __esm({
|
|
|
17265
17463
|
init_tasks_crud();
|
|
17266
17464
|
init_tmux_routing();
|
|
17267
17465
|
init_session_key();
|
|
17466
|
+
init_state_bus();
|
|
17268
17467
|
}
|
|
17269
17468
|
});
|
|
17270
17469
|
|
|
@@ -17429,13 +17628,12 @@ function assertSessionScope(actionType, targetProject) {
|
|
|
17429
17628
|
};
|
|
17430
17629
|
}
|
|
17431
17630
|
process.stderr.write(
|
|
17432
|
-
`[session-scope]
|
|
17631
|
+
`[session-scope] BLOCKED cross-project ${actionType}: session project="${currentProject}" \u2260 target project="${targetProject}"
|
|
17433
17632
|
`
|
|
17434
17633
|
);
|
|
17435
17634
|
return {
|
|
17436
|
-
allowed:
|
|
17437
|
-
|
|
17438
|
-
reason: "cross_session_granted",
|
|
17635
|
+
allowed: false,
|
|
17636
|
+
reason: "cross_session_denied",
|
|
17439
17637
|
currentProject,
|
|
17440
17638
|
targetProject,
|
|
17441
17639
|
targetSession: findSessionForProject(targetProject)?.windowName
|
|
@@ -17461,8 +17659,9 @@ async function dispatchTaskToEmployee(input) {
|
|
|
17461
17659
|
try {
|
|
17462
17660
|
const { assertSessionScope: assertSessionScope2 } = (init_session_scope(), __toCommonJS(session_scope_exports));
|
|
17463
17661
|
const check = assertSessionScope2("dispatch_task", input.projectName);
|
|
17464
|
-
if (check.reason === "
|
|
17662
|
+
if (check.reason === "cross_session_denied") {
|
|
17465
17663
|
crossProject = true;
|
|
17664
|
+
return { dispatched: "skipped", crossProject: true };
|
|
17466
17665
|
}
|
|
17467
17666
|
} catch {
|
|
17468
17667
|
}
|
|
@@ -17925,6 +18124,13 @@ async function updateTask(input) {
|
|
|
17925
18124
|
await cascadeUnblock(taskId, input.baseDir, now);
|
|
17926
18125
|
} catch {
|
|
17927
18126
|
}
|
|
18127
|
+
orgBus.emit({
|
|
18128
|
+
type: "task_completed",
|
|
18129
|
+
taskId,
|
|
18130
|
+
employee: String(row.assigned_to),
|
|
18131
|
+
result: input.result ?? "",
|
|
18132
|
+
timestamp: now
|
|
18133
|
+
});
|
|
17928
18134
|
if (row.parent_task_id) {
|
|
17929
18135
|
try {
|
|
17930
18136
|
await checkSubtaskCompletion(String(row.parent_task_id), String(row.project_name));
|
|
@@ -17992,6 +18198,7 @@ var init_tasks = __esm({
|
|
|
17992
18198
|
init_database();
|
|
17993
18199
|
init_config();
|
|
17994
18200
|
init_notifications();
|
|
18201
|
+
init_state_bus();
|
|
17995
18202
|
init_tasks_crud();
|
|
17996
18203
|
init_tasks_review();
|
|
17997
18204
|
init_tasks_crud();
|
|
@@ -18382,8 +18589,28 @@ function getMySession() {
|
|
|
18382
18589
|
return getTransport().getMySession();
|
|
18383
18590
|
}
|
|
18384
18591
|
function employeeSessionName(employee, exeSession, instance) {
|
|
18592
|
+
if (!/^exe\d+$/.test(exeSession)) {
|
|
18593
|
+
const root = extractRootExe(exeSession);
|
|
18594
|
+
if (root) {
|
|
18595
|
+
process.stderr.write(
|
|
18596
|
+
`[tmux-routing] WARN: exeSession="${exeSession}" is not a root exe session, using "${root}" instead
|
|
18597
|
+
`
|
|
18598
|
+
);
|
|
18599
|
+
exeSession = root;
|
|
18600
|
+
} else {
|
|
18601
|
+
throw new Error(
|
|
18602
|
+
`Invalid exeSession "${exeSession}" \u2014 must be a root exe session (e.g., "exe1"), not an agent session`
|
|
18603
|
+
);
|
|
18604
|
+
}
|
|
18605
|
+
}
|
|
18385
18606
|
const suffix = instance != null && instance > 0 ? String(instance) : "";
|
|
18386
|
-
|
|
18607
|
+
const name = `${employee}${suffix}-${exeSession}`;
|
|
18608
|
+
if (!VALID_SESSION_NAME.test(name)) {
|
|
18609
|
+
throw new Error(
|
|
18610
|
+
`Invalid session name "${name}" \u2014 must match {agent}-exe{N} or {agent}{instance}-exe{N}`
|
|
18611
|
+
);
|
|
18612
|
+
}
|
|
18613
|
+
return name;
|
|
18387
18614
|
}
|
|
18388
18615
|
function parseParentExe(sessionName, agentId) {
|
|
18389
18616
|
const escaped = agentId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -18623,10 +18850,26 @@ function ensureEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
18623
18850
|
error: `Error: pass employee name ('${bare}'), not session name ('${employeeName}')`
|
|
18624
18851
|
};
|
|
18625
18852
|
}
|
|
18626
|
-
|
|
18627
|
-
|
|
18628
|
-
|
|
18629
|
-
|
|
18853
|
+
if (!/^exe\d+$/.test(exeSession)) {
|
|
18854
|
+
const root = extractRootExe(exeSession);
|
|
18855
|
+
if (root) {
|
|
18856
|
+
process.stderr.write(
|
|
18857
|
+
`[ensureEmployee] WARN: caller passed exeSession="${exeSession}" (not a root exe). Auto-correcting to "${root}".
|
|
18858
|
+
`
|
|
18859
|
+
);
|
|
18860
|
+
exeSession = root;
|
|
18861
|
+
} else {
|
|
18862
|
+
return {
|
|
18863
|
+
status: "failed",
|
|
18864
|
+
sessionName: "",
|
|
18865
|
+
error: `Invalid exeSession "${exeSession}" \u2014 must be a root exe session (e.g., "exe1")`
|
|
18866
|
+
};
|
|
18867
|
+
}
|
|
18868
|
+
}
|
|
18869
|
+
let effectiveInstance = opts?.instance;
|
|
18870
|
+
if (effectiveInstance === void 0 && opts?.autoInstance) {
|
|
18871
|
+
const free = findFreeInstance(
|
|
18872
|
+
employeeName,
|
|
18630
18873
|
exeSession,
|
|
18631
18874
|
opts.maxAutoInstances ?? 10
|
|
18632
18875
|
);
|
|
@@ -18869,7 +19112,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
18869
19112
|
releaseSpawnLock2(sessionName);
|
|
18870
19113
|
return { sessionName };
|
|
18871
19114
|
}
|
|
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;
|
|
19115
|
+
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
19116
|
var init_tmux_routing = __esm({
|
|
18874
19117
|
"src/lib/tmux-routing.ts"() {
|
|
18875
19118
|
"use strict";
|
|
@@ -18884,6 +19127,7 @@ var init_tmux_routing = __esm({
|
|
|
18884
19127
|
SPAWN_LOCK_DIR = path30.join(os10.homedir(), ".exe-os", "spawn-locks");
|
|
18885
19128
|
SESSION_CACHE = path30.join(os10.homedir(), ".exe-os", "session-cache");
|
|
18886
19129
|
BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
|
|
19130
|
+
VALID_SESSION_NAME = /^[a-z]+-exe\d+$|^[a-z]+\d+-exe\d+$/;
|
|
18887
19131
|
VERIFY_PANE_LINES = 200;
|
|
18888
19132
|
INTERCOM_DEBOUNCE_MS = 3e4;
|
|
18889
19133
|
INTERCOM_LOG2 = path30.join(os10.homedir(), ".exe-os", "intercom.log");
|
|
@@ -19290,6 +19534,7 @@ function SessionsView({
|
|
|
19290
19534
|
const [viewingEmployee, setViewingEmployee] = useState9(null);
|
|
19291
19535
|
const [viewingProject, setViewingProject] = useState9(null);
|
|
19292
19536
|
const [loading, setLoading] = useState9(!demo);
|
|
19537
|
+
const [sessionError, setSessionError] = useState9(null);
|
|
19293
19538
|
const [tmuxAvailable, setTmuxAvailable] = useState9(true);
|
|
19294
19539
|
const orch = useOrchestrator(!demo);
|
|
19295
19540
|
const [carouselEmployees, setCarouselEmployees] = useState9([]);
|
|
@@ -19465,111 +19710,116 @@ function SessionsView({
|
|
|
19465
19710
|
return ACTIVE_PANE_PATTERN.test(lines.join("\n")) ? "active" : "idle";
|
|
19466
19711
|
}
|
|
19467
19712
|
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();
|
|
19713
|
+
const { withTrace: withTrace2 } = await Promise.resolve().then(() => (init_telemetry(), telemetry_exports));
|
|
19714
|
+
return withTrace2("tui.sessions.loadSessions", async () => {
|
|
19480
19715
|
try {
|
|
19481
|
-
const
|
|
19482
|
-
|
|
19483
|
-
|
|
19484
|
-
});
|
|
19485
|
-
|
|
19486
|
-
|
|
19487
|
-
|
|
19488
|
-
|
|
19716
|
+
const { listSessions: listSessions2 } = await Promise.resolve().then(() => (init_session_registry(), session_registry_exports));
|
|
19717
|
+
const { listTmuxSessions: listTmuxSessions2, inTmux: inTmux2, capturePaneLines: capturePaneLines2, parseActivity: parseActivity2 } = await Promise.resolve().then(() => (init_tmux_status(), tmux_status_exports));
|
|
19718
|
+
const { loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
19719
|
+
const { execSync: execSync13 } = await import("child_process");
|
|
19720
|
+
if (!inTmux2()) {
|
|
19721
|
+
setTmuxAvailable(false);
|
|
19722
|
+
setProjects([]);
|
|
19723
|
+
return;
|
|
19724
|
+
}
|
|
19725
|
+
setTmuxAvailable(true);
|
|
19726
|
+
const attachedMap = /* @__PURE__ */ new Map();
|
|
19727
|
+
try {
|
|
19728
|
+
const out = execSync13("tmux list-sessions -F '#{session_name}:#{session_attached}' 2>/dev/null", {
|
|
19729
|
+
encoding: "utf8",
|
|
19730
|
+
timeout: 3e3
|
|
19731
|
+
});
|
|
19732
|
+
for (const line of out.trim().split("\n").filter(Boolean)) {
|
|
19733
|
+
const sepIdx = line.lastIndexOf(":");
|
|
19734
|
+
if (sepIdx > 0) {
|
|
19735
|
+
attachedMap.set(line.slice(0, sepIdx), line.slice(sepIdx + 1) === "1");
|
|
19736
|
+
}
|
|
19489
19737
|
}
|
|
19738
|
+
} catch {
|
|
19490
19739
|
}
|
|
19491
|
-
|
|
19492
|
-
|
|
19493
|
-
|
|
19494
|
-
|
|
19495
|
-
|
|
19496
|
-
|
|
19497
|
-
|
|
19498
|
-
if (entry.agentId === "exe" && tmuxSessions.has(entry.windowName)) {
|
|
19499
|
-
exeSessions.set(entry.windowName, entry.projectDir);
|
|
19500
|
-
}
|
|
19501
|
-
}
|
|
19502
|
-
for (const s of tmuxSessions) {
|
|
19503
|
-
if (/^exe\d+$/.test(s) && !exeSessions.has(s)) {
|
|
19504
|
-
exeSessions.set(s, "");
|
|
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
|
-
};
|
|
19740
|
+
const registry = listSessions2();
|
|
19741
|
+
const tmuxSessions = new Set(listTmuxSessions2());
|
|
19742
|
+
const roster = await loadEmployees2();
|
|
19743
|
+
const exeSessions = /* @__PURE__ */ new Map();
|
|
19744
|
+
for (const entry of registry) {
|
|
19745
|
+
if (entry.agentId === "exe" && tmuxSessions.has(entry.windowName)) {
|
|
19746
|
+
exeSessions.set(entry.windowName, entry.projectDir);
|
|
19531
19747
|
}
|
|
19532
|
-
|
|
19748
|
+
}
|
|
19749
|
+
for (const s of tmuxSessions) {
|
|
19750
|
+
if (/^exe\d+$/.test(s) && !exeSessions.has(s)) {
|
|
19751
|
+
exeSessions.set(s, "");
|
|
19752
|
+
}
|
|
19753
|
+
}
|
|
19754
|
+
const projectList = [];
|
|
19755
|
+
for (const [exeSession, projectDir] of exeSessions) {
|
|
19756
|
+
const projectName = projectDir.split("/").filter(Boolean).pop() ?? exeSession;
|
|
19757
|
+
const exeHasSession = tmuxSessions.has(exeSession);
|
|
19758
|
+
let exeStatus = "offline";
|
|
19759
|
+
let exeActivity = "";
|
|
19760
|
+
if (exeHasSession) {
|
|
19761
|
+
const exeLines = capturePaneLines2(exeSession, 10);
|
|
19762
|
+
exeStatus = statusFromPaneLines(exeLines);
|
|
19763
|
+
exeActivity = exeLines.length > 0 ? parseActivity2(exeLines) : "";
|
|
19764
|
+
}
|
|
19765
|
+
const employeeEntries = roster.filter((e) => e.name !== "exe").map((emp) => {
|
|
19766
|
+
const sessionName = `${emp.name}-${exeSession}`;
|
|
19767
|
+
const hasSession = tmuxSessions.has(sessionName);
|
|
19768
|
+
const isCrashed = !hasSession && orch.crashedSessions.includes(emp.name);
|
|
19769
|
+
if (isCrashed) {
|
|
19770
|
+
return {
|
|
19771
|
+
name: emp.name,
|
|
19772
|
+
role: emp.role,
|
|
19773
|
+
status: "crashed",
|
|
19774
|
+
sessionName,
|
|
19775
|
+
activity: "Dead session \u2014 has open tasks",
|
|
19776
|
+
attached: false
|
|
19777
|
+
};
|
|
19778
|
+
}
|
|
19779
|
+
if (!hasSession) {
|
|
19780
|
+
return {
|
|
19781
|
+
name: emp.name,
|
|
19782
|
+
role: emp.role,
|
|
19783
|
+
status: "offline",
|
|
19784
|
+
sessionName,
|
|
19785
|
+
activity: "",
|
|
19786
|
+
attached: false
|
|
19787
|
+
};
|
|
19788
|
+
}
|
|
19789
|
+
const lines = capturePaneLines2(sessionName, 10);
|
|
19533
19790
|
return {
|
|
19534
19791
|
name: emp.name,
|
|
19535
19792
|
role: emp.role,
|
|
19536
|
-
status:
|
|
19793
|
+
status: statusFromPaneLines(lines),
|
|
19537
19794
|
sessionName,
|
|
19538
|
-
activity: "",
|
|
19539
|
-
attached: false
|
|
19795
|
+
activity: lines.length > 0 ? parseActivity2(lines) : "",
|
|
19796
|
+
attached: attachedMap.get(sessionName) ?? false
|
|
19540
19797
|
};
|
|
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: [] });
|
|
19798
|
+
});
|
|
19799
|
+
const employees = [
|
|
19800
|
+
{
|
|
19801
|
+
name: "exe",
|
|
19802
|
+
role: "COO",
|
|
19803
|
+
status: exeStatus,
|
|
19804
|
+
sessionName: exeSession,
|
|
19805
|
+
activity: exeActivity,
|
|
19806
|
+
attached: attachedMap.get(exeSession) ?? false
|
|
19807
|
+
},
|
|
19808
|
+
...employeeEntries
|
|
19809
|
+
];
|
|
19810
|
+
projectList.push({ projectName, exeSession, projectDir, employees });
|
|
19811
|
+
}
|
|
19812
|
+
if (projectList.length === 0) {
|
|
19813
|
+
projectList.push({ projectName: "(no active sessions)", exeSession: "", projectDir: "", employees: [] });
|
|
19814
|
+
}
|
|
19815
|
+
setProjects(projectList);
|
|
19816
|
+
setSessionError(null);
|
|
19817
|
+
} catch (err) {
|
|
19818
|
+
setSessionError(err instanceof Error ? err.message : "Failed to query sessions.");
|
|
19819
|
+
} finally {
|
|
19820
|
+
setLoading(false);
|
|
19567
19821
|
}
|
|
19568
|
-
|
|
19569
|
-
} catch {
|
|
19570
|
-
} finally {
|
|
19571
|
-
setLoading(false);
|
|
19572
|
-
}
|
|
19822
|
+
});
|
|
19573
19823
|
}
|
|
19574
19824
|
if (viewingEmployee) {
|
|
19575
19825
|
const inCarousel = carouselEmployees.length > 0;
|
|
@@ -19651,7 +19901,10 @@ function SessionsView({
|
|
|
19651
19901
|
] })
|
|
19652
19902
|
] }),
|
|
19653
19903
|
/* @__PURE__ */ jsx9(Text, { children: " " }),
|
|
19654
|
-
loading ? /* @__PURE__ */ jsx9(Text, { color: "#6B4C9A", children: "Loading sessions..." }) :
|
|
19904
|
+
loading ? /* @__PURE__ */ jsx9(Text, { color: "#6B4C9A", children: "Loading sessions..." }) : sessionError ? /* @__PURE__ */ jsxs7(Text, { color: "#C91B00", children: [
|
|
19905
|
+
"Failed to query sessions: ",
|
|
19906
|
+
sessionError
|
|
19907
|
+
] }) : !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
19908
|
const isSelected = i === selectedIdx;
|
|
19656
19909
|
const marker = isSelected ? "\u25B8 " : " ";
|
|
19657
19910
|
if (item.type === "project") {
|
|
@@ -19752,7 +20005,7 @@ function TasksView({ onBack }) {
|
|
|
19752
20005
|
const demo = useDemo();
|
|
19753
20006
|
const [allTasks, setAllTasks] = useState10([]);
|
|
19754
20007
|
const [loading, setLoading] = useState10(!demo);
|
|
19755
|
-
const [dbError, setDbError] = useState10(
|
|
20008
|
+
const [dbError, setDbError] = useState10(null);
|
|
19756
20009
|
const [selectedTask, setSelectedTask] = useState10(0);
|
|
19757
20010
|
const [showDetail, setShowDetail] = useState10(false);
|
|
19758
20011
|
const [statusFilter, setStatusFilter] = useState10("all");
|
|
@@ -19824,40 +20077,43 @@ function TasksView({ onBack }) {
|
|
|
19824
20077
|
}
|
|
19825
20078
|
});
|
|
19826
20079
|
async function loadTasks() {
|
|
19827
|
-
|
|
19828
|
-
|
|
19829
|
-
|
|
19830
|
-
|
|
19831
|
-
const
|
|
19832
|
-
|
|
20080
|
+
const { withTrace: withTrace2 } = await Promise.resolve().then(() => (init_telemetry(), telemetry_exports));
|
|
20081
|
+
return withTrace2("tui.tasks.loadTasks", async () => {
|
|
20082
|
+
try {
|
|
20083
|
+
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
20084
|
+
const client = getClient2();
|
|
20085
|
+
if (client) {
|
|
20086
|
+
const result = await client.execute(
|
|
20087
|
+
`SELECT id, title, priority, assigned_to, assigned_by, status, project_name, created_at, result
|
|
19833
20088
|
FROM tasks
|
|
19834
20089
|
ORDER BY
|
|
19835
20090
|
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
20091
|
CASE priority WHEN 'p0' THEN 0 WHEN 'p1' THEN 1 WHEN 'p2' THEN 2 ELSE 3 END,
|
|
19837
20092
|
created_at DESC`
|
|
19838
|
-
|
|
19839
|
-
|
|
19840
|
-
|
|
19841
|
-
|
|
19842
|
-
|
|
19843
|
-
|
|
19844
|
-
|
|
19845
|
-
|
|
19846
|
-
|
|
19847
|
-
|
|
19848
|
-
|
|
19849
|
-
|
|
19850
|
-
|
|
19851
|
-
|
|
19852
|
-
|
|
19853
|
-
|
|
19854
|
-
|
|
20093
|
+
);
|
|
20094
|
+
setAllTasks(
|
|
20095
|
+
result.rows.map((r) => ({
|
|
20096
|
+
id: String(r.id ?? ""),
|
|
20097
|
+
priority: String(r.priority ?? "p2").toUpperCase(),
|
|
20098
|
+
title: String(r.title ?? ""),
|
|
20099
|
+
assignee: String(r.assigned_to ?? ""),
|
|
20100
|
+
assignedBy: String(r.assigned_by ?? ""),
|
|
20101
|
+
status: String(r.status ?? "open"),
|
|
20102
|
+
project: String(r.project_name ?? ""),
|
|
20103
|
+
createdAt: String(r.created_at ?? ""),
|
|
20104
|
+
result: String(r.result ?? "")
|
|
20105
|
+
}))
|
|
20106
|
+
);
|
|
20107
|
+
setDbError(null);
|
|
20108
|
+
} else {
|
|
20109
|
+
setDbError("Database client not initialized. Run exe-os setup.");
|
|
20110
|
+
}
|
|
20111
|
+
} catch (err) {
|
|
20112
|
+
setDbError(err instanceof Error ? err.message : "Unknown error");
|
|
20113
|
+
} finally {
|
|
20114
|
+
setLoading(false);
|
|
19855
20115
|
}
|
|
19856
|
-
}
|
|
19857
|
-
setDbError(true);
|
|
19858
|
-
} finally {
|
|
19859
|
-
setLoading(false);
|
|
19860
|
-
}
|
|
20116
|
+
});
|
|
19861
20117
|
}
|
|
19862
20118
|
const selected = taskRows[selectedTask]?.task;
|
|
19863
20119
|
if (showDetail && selected) {
|
|
@@ -19924,7 +20180,10 @@ function TasksView({ onBack }) {
|
|
|
19924
20180
|
filterLabel
|
|
19925
20181
|
] }),
|
|
19926
20182
|
/* @__PURE__ */ jsx10(Text, { children: " " }),
|
|
19927
|
-
loading ? /* @__PURE__ */ jsx10(Text, { color: "#6B4C9A", children: "Loading tasks..." }) : dbError ? /* @__PURE__ */
|
|
20183
|
+
loading ? /* @__PURE__ */ jsx10(Text, { color: "#6B4C9A", children: "Loading tasks..." }) : dbError ? /* @__PURE__ */ jsxs8(Text, { color: "#C91B00", children: [
|
|
20184
|
+
"Failed to load tasks: ",
|
|
20185
|
+
dbError
|
|
20186
|
+
] }) : 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
20187
|
if (row.type === "header") {
|
|
19929
20188
|
return /* @__PURE__ */ jsxs8(Box_default, { marginTop: i > 0 ? 1 : 0, children: [
|
|
19930
20189
|
/* @__PURE__ */ jsx10(Text, { bold: true, color: "#F0EDE8", children: row.project }),
|
|
@@ -20611,6 +20870,31 @@ function GatewayView({ onBack }) {
|
|
|
20611
20870
|
/* @__PURE__ */ jsx11(Text, { color: "#6B4C9A", children: "Loading gateway status..." })
|
|
20612
20871
|
] });
|
|
20613
20872
|
}
|
|
20873
|
+
if (!gateway.running && gateway.gatewayUrl && connectionStatus === "disconnected") {
|
|
20874
|
+
return /* @__PURE__ */ jsxs9(Box_default, { flexDirection: "column", flexGrow: 1, paddingX: 1, children: [
|
|
20875
|
+
/* @__PURE__ */ jsx11(Box_default, { borderStyle: "single", borderColor: "#3D3660", paddingX: 1, alignSelf: "flex-start", children: /* @__PURE__ */ jsx11(Text, { bold: true, children: "Gateway Monitor" }) }),
|
|
20876
|
+
/* @__PURE__ */ jsx11(Text, { children: " " }),
|
|
20877
|
+
/* @__PURE__ */ jsx11(Text, { color: "#C91B00", children: "Gateway connection failed." }),
|
|
20878
|
+
/* @__PURE__ */ jsx11(Text, { children: " " }),
|
|
20879
|
+
/* @__PURE__ */ jsxs9(Text, { color: "#6B4C9A", children: [
|
|
20880
|
+
"Gateway URL: ",
|
|
20881
|
+
/* @__PURE__ */ jsx11(Text, { color: "#F0EDE8", children: gateway.gatewayUrl })
|
|
20882
|
+
] }),
|
|
20883
|
+
/* @__PURE__ */ jsxs9(Text, { color: "#6B4C9A", children: [
|
|
20884
|
+
"Process: ",
|
|
20885
|
+
/* @__PURE__ */ jsx11(Text, { color: "#C91B00", children: "not running" })
|
|
20886
|
+
] }),
|
|
20887
|
+
/* @__PURE__ */ jsx11(Text, { children: " " }),
|
|
20888
|
+
/* @__PURE__ */ jsxs9(Text, { color: "#6B4C9A", children: [
|
|
20889
|
+
"Start the gateway: ",
|
|
20890
|
+
/* @__PURE__ */ jsx11(Text, { bold: true, children: "exe-os gateway" })
|
|
20891
|
+
] }),
|
|
20892
|
+
/* @__PURE__ */ jsxs9(Text, { color: "#6B4C9A", children: [
|
|
20893
|
+
"Or check your config: ",
|
|
20894
|
+
/* @__PURE__ */ jsx11(Text, { bold: true, children: "~/.exe-os/gateway.json" })
|
|
20895
|
+
] })
|
|
20896
|
+
] });
|
|
20897
|
+
}
|
|
20614
20898
|
if (!gateway.running && gateway.adapters.length === 0 && !gateway.gatewayUrl) {
|
|
20615
20899
|
return /* @__PURE__ */ jsxs9(Box_default, { flexDirection: "column", flexGrow: 1, paddingX: 1, children: [
|
|
20616
20900
|
/* @__PURE__ */ jsx11(Box_default, { borderStyle: "single", borderColor: "#3D3660", paddingX: 1, alignSelf: "flex-start", children: /* @__PURE__ */ jsx11(Text, { bold: true, children: "Gateway Monitor" }) }),
|
|
@@ -20897,14 +21181,30 @@ var init_agent_status = __esm({
|
|
|
20897
21181
|
// src/tui/views/Team.tsx
|
|
20898
21182
|
import React22, { useState as useState12, useEffect as useEffect14 } from "react";
|
|
20899
21183
|
import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
20900
|
-
function
|
|
21184
|
+
function roleBadgeColor(role) {
|
|
21185
|
+
switch (role.toLowerCase()) {
|
|
21186
|
+
case "coo":
|
|
21187
|
+
return "#F5D76E";
|
|
21188
|
+
// gold
|
|
21189
|
+
case "cto":
|
|
21190
|
+
return "#3B82F6";
|
|
21191
|
+
// blue
|
|
21192
|
+
case "cmo":
|
|
21193
|
+
return "#6B4C9A";
|
|
21194
|
+
// purple
|
|
21195
|
+
default:
|
|
21196
|
+
return "#F0EDE8";
|
|
21197
|
+
}
|
|
21198
|
+
}
|
|
21199
|
+
function TeamView({ onBack, onViewSessions }) {
|
|
20901
21200
|
const demo = useDemo();
|
|
20902
21201
|
const [members, setMembers] = useState12([]);
|
|
20903
21202
|
const [externals, setExternals] = useState12([]);
|
|
20904
21203
|
const [loading, setLoading] = useState12(!demo);
|
|
20905
|
-
const [dbError, setDbError] = useState12(
|
|
21204
|
+
const [dbError, setDbError] = useState12(null);
|
|
20906
21205
|
const [selectedIdx, setSelectedIdx] = useState12(0);
|
|
20907
21206
|
const [showDetail, setShowDetail] = useState12(false);
|
|
21207
|
+
const [showAddHint, setShowAddHint] = useState12(false);
|
|
20908
21208
|
const orch = useOrchestrator(!demo);
|
|
20909
21209
|
const orchEmployeeMap = new Map(orch.employees.map((e) => [e.name, e]));
|
|
20910
21210
|
const allItems = [...members, ...externals.map((e) => ({ ...e, activity: "", memoryCount: 0 }))];
|
|
@@ -20919,7 +21219,7 @@ function TeamView({ onBack }) {
|
|
|
20919
21219
|
const timer = setInterval(loadTeam, 5e3);
|
|
20920
21220
|
return () => clearInterval(timer);
|
|
20921
21221
|
}, []);
|
|
20922
|
-
use_input_default((
|
|
21222
|
+
use_input_default((input, key) => {
|
|
20923
21223
|
if (showDetail) {
|
|
20924
21224
|
if (key.escape) setShowDetail(false);
|
|
20925
21225
|
return;
|
|
@@ -20928,91 +21228,103 @@ function TeamView({ onBack }) {
|
|
|
20928
21228
|
onBack?.();
|
|
20929
21229
|
return;
|
|
20930
21230
|
}
|
|
21231
|
+
if (input === "a") {
|
|
21232
|
+
setShowAddHint(true);
|
|
21233
|
+
setTimeout(() => setShowAddHint(false), 3e3);
|
|
21234
|
+
return;
|
|
21235
|
+
}
|
|
21236
|
+
if (input === "s" && selected) {
|
|
21237
|
+
onViewSessions?.(selected.name);
|
|
21238
|
+
return;
|
|
21239
|
+
}
|
|
20931
21240
|
if (key.upArrow && selectedIdx > 0) setSelectedIdx(selectedIdx - 1);
|
|
20932
21241
|
if (key.downArrow && selectedIdx < allItems.length - 1) setSelectedIdx(selectedIdx + 1);
|
|
20933
21242
|
if (key.return && allItems.length > 0) setShowDetail(true);
|
|
20934
21243
|
});
|
|
20935
21244
|
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();
|
|
21245
|
+
const { withTrace: withTrace2 } = await Promise.resolve().then(() => (init_telemetry(), telemetry_exports));
|
|
21246
|
+
return withTrace2("tui.team.loadTeam", async () => {
|
|
20942
21247
|
try {
|
|
20943
|
-
const {
|
|
20944
|
-
const
|
|
20945
|
-
|
|
20946
|
-
|
|
20947
|
-
|
|
20948
|
-
|
|
20949
|
-
}
|
|
20950
|
-
|
|
20951
|
-
|
|
20952
|
-
|
|
21248
|
+
const { loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
21249
|
+
const roster = await loadEmployees2();
|
|
21250
|
+
let memoryCounts = /* @__PURE__ */ new Map();
|
|
21251
|
+
let projectsByEmployee = /* @__PURE__ */ new Map();
|
|
21252
|
+
let currentTaskByEmployee = /* @__PURE__ */ new Map();
|
|
21253
|
+
try {
|
|
21254
|
+
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
21255
|
+
const client = getClient2();
|
|
21256
|
+
if (client) {
|
|
21257
|
+
const memResult = await client.execute("SELECT agent_id, COUNT(*) as cnt FROM memories GROUP BY agent_id");
|
|
21258
|
+
for (const row of memResult.rows) {
|
|
21259
|
+
memoryCounts.set(String(row.agent_id), Number(row.cnt));
|
|
21260
|
+
}
|
|
21261
|
+
for (const emp of roster) {
|
|
21262
|
+
const projResult = await client.execute({
|
|
21263
|
+
sql: `SELECT DISTINCT project_name,
|
|
20953
21264
|
MAX(CASE WHEN status = 'in_progress' THEN 1 WHEN status = 'open' THEN 2 ELSE 3 END) as urgency
|
|
20954
21265
|
FROM tasks WHERE assigned_to = ? AND status IN ('open','in_progress','done')
|
|
20955
21266
|
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
|
-
|
|
21267
|
+
args: [emp.name]
|
|
21268
|
+
});
|
|
21269
|
+
const projects = projResult.rows.filter((r) => !DEPRECATED_PROJECTS.has(String(r.project_name))).map((r) => {
|
|
21270
|
+
const urgency = Number(r.urgency);
|
|
21271
|
+
let pStatus = "idle";
|
|
21272
|
+
if (urgency === 1) pStatus = "active";
|
|
21273
|
+
else if (urgency === 2) pStatus = "has_tasks";
|
|
21274
|
+
return { name: String(r.project_name), status: pStatus };
|
|
21275
|
+
});
|
|
21276
|
+
if (projects.length > 0) projectsByEmployee.set(emp.name, projects);
|
|
21277
|
+
}
|
|
21278
|
+
for (const emp of roster) {
|
|
21279
|
+
const taskResult = await client.execute({
|
|
21280
|
+
sql: "SELECT title FROM tasks WHERE assigned_to = ? AND status = 'in_progress' ORDER BY updated_at DESC LIMIT 1",
|
|
21281
|
+
args: [emp.name]
|
|
21282
|
+
});
|
|
21283
|
+
if (taskResult.rows.length > 0) {
|
|
21284
|
+
currentTaskByEmployee.set(emp.name, String(taskResult.rows[0].title));
|
|
21285
|
+
}
|
|
20974
21286
|
}
|
|
20975
21287
|
}
|
|
21288
|
+
} catch {
|
|
20976
21289
|
}
|
|
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
|
-
})));
|
|
21290
|
+
const teamData = roster.map((emp) => {
|
|
21291
|
+
const agentSt = getAgentStatus(emp.name);
|
|
21292
|
+
return {
|
|
21293
|
+
name: emp.name,
|
|
21294
|
+
role: emp.role,
|
|
21295
|
+
status: agentSt.label,
|
|
21296
|
+
activity: agentSt.label === "active" ? "Processing..." : "",
|
|
21297
|
+
memoryCount: memoryCounts.get(emp.name) ?? 0,
|
|
21298
|
+
projects: projectsByEmployee.get(emp.name),
|
|
21299
|
+
currentTask: currentTaskByEmployee.get(emp.name),
|
|
21300
|
+
sessionName: agentSt.session
|
|
21301
|
+
};
|
|
21302
|
+
});
|
|
21303
|
+
setMembers(teamData);
|
|
21304
|
+
setDbError(null);
|
|
21305
|
+
try {
|
|
21306
|
+
const { existsSync: existsSync22, readFileSync: readFileSync18 } = await import("fs");
|
|
21307
|
+
const { join } = await import("path");
|
|
21308
|
+
const home = process.env.HOME ?? "";
|
|
21309
|
+
const gatewayConfig = join(home, ".exe-os", "gateway.json");
|
|
21310
|
+
if (existsSync22(gatewayConfig)) {
|
|
21311
|
+
const raw = JSON.parse(readFileSync18(gatewayConfig, "utf8"));
|
|
21312
|
+
if (raw.agents && raw.agents.length > 0) {
|
|
21313
|
+
setExternals(raw.agents.map((a) => ({
|
|
21314
|
+
name: a.name,
|
|
21315
|
+
role: a.role ?? "external agent",
|
|
21316
|
+
status: "offline"
|
|
21317
|
+
})));
|
|
21318
|
+
}
|
|
21007
21319
|
}
|
|
21320
|
+
} catch {
|
|
21008
21321
|
}
|
|
21009
|
-
} catch {
|
|
21322
|
+
} catch (err) {
|
|
21323
|
+
setDbError(err instanceof Error ? err.message : "Unknown error");
|
|
21324
|
+
} finally {
|
|
21325
|
+
setLoading(false);
|
|
21010
21326
|
}
|
|
21011
|
-
}
|
|
21012
|
-
setDbError(true);
|
|
21013
|
-
} finally {
|
|
21014
|
-
setLoading(false);
|
|
21015
|
-
}
|
|
21327
|
+
});
|
|
21016
21328
|
}
|
|
21017
21329
|
const totalCount = members.length + externals.length;
|
|
21018
21330
|
const selected = allItems[selectedIdx];
|
|
@@ -21029,7 +21341,7 @@ function TeamView({ onBack }) {
|
|
|
21029
21341
|
/* @__PURE__ */ jsx12(Text, { children: " " }),
|
|
21030
21342
|
/* @__PURE__ */ jsxs10(Text, { children: [
|
|
21031
21343
|
"Role: ",
|
|
21032
|
-
/* @__PURE__ */ jsx12(Text, { bold: true, children: selected.role })
|
|
21344
|
+
/* @__PURE__ */ jsx12(Text, { bold: true, color: roleBadgeColor(selected.role), children: selected.role })
|
|
21033
21345
|
] }),
|
|
21034
21346
|
/* @__PURE__ */ jsxs10(Text, { children: [
|
|
21035
21347
|
"Status: ",
|
|
@@ -21058,8 +21370,9 @@ function TeamView({ onBack }) {
|
|
|
21058
21370
|
/* @__PURE__ */ jsx12(Box_default, { borderStyle: "single", borderColor: "#3D3660", paddingX: 1, alignSelf: "flex-start", children: /* @__PURE__ */ jsx12(Text, { bold: true, children: "Team Roster" }) }),
|
|
21059
21371
|
/* @__PURE__ */ jsxs10(Text, { color: "#6B4C9A", children: [
|
|
21060
21372
|
totalCount,
|
|
21061
|
-
" agents |
|
|
21373
|
+
" agents | \u2191\u2193 navigate | Enter details | a add | s sessions"
|
|
21062
21374
|
] }),
|
|
21375
|
+
showAddHint && /* @__PURE__ */ jsx12(Text, { color: "#F5D76E", children: "Run /exe-new-employee <name> from CLI to add an employee." }),
|
|
21063
21376
|
!demo && orch.pendingReviews > 0 && /* @__PURE__ */ jsxs10(Text, { color: "#6B4C9A", children: [
|
|
21064
21377
|
orch.pendingReviews,
|
|
21065
21378
|
" review(s) pending exe attention"
|
|
@@ -21067,7 +21380,10 @@ function TeamView({ onBack }) {
|
|
|
21067
21380
|
/* @__PURE__ */ jsx12(Text, { children: " " }),
|
|
21068
21381
|
/* @__PURE__ */ jsx12(Text, { bold: true, children: "INTERNAL" }),
|
|
21069
21382
|
/* @__PURE__ */ jsx12(Text, { children: " " }),
|
|
21070
|
-
loading ? /* @__PURE__ */ jsx12(Text, { color: "#6B4C9A", children: " Loading
|
|
21383
|
+
loading ? /* @__PURE__ */ jsx12(Text, { color: "#6B4C9A", children: " Loading employee roster..." }) : dbError ? /* @__PURE__ */ jsxs10(Text, { color: "#C91B00", children: [
|
|
21384
|
+
" Failed to load roster: ",
|
|
21385
|
+
dbError
|
|
21386
|
+
] }) : 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
21387
|
const isSelected = i === selectedIdx;
|
|
21072
21388
|
const orchEmp = orchEmployeeMap.get(m.name);
|
|
21073
21389
|
return /* @__PURE__ */ jsxs10(
|
|
@@ -21083,7 +21399,7 @@ function TeamView({ onBack }) {
|
|
|
21083
21399
|
/* @__PURE__ */ jsxs10(Box_default, { gap: 1, children: [
|
|
21084
21400
|
/* @__PURE__ */ jsx12(StatusDot, { status: m.status, showLabel: false }),
|
|
21085
21401
|
/* @__PURE__ */ jsx12(Text, { bold: true, color: isSelected ? "#F5D76E" : "#F0EDE8", children: m.name }),
|
|
21086
|
-
/* @__PURE__ */ jsxs10(Text, { color: isSelected ? "#F5D76E" :
|
|
21402
|
+
/* @__PURE__ */ jsxs10(Text, { color: isSelected ? "#F5D76E" : roleBadgeColor(m.role), children: [
|
|
21087
21403
|
"(",
|
|
21088
21404
|
m.role,
|
|
21089
21405
|
")"
|
|
@@ -21309,6 +21625,26 @@ var init_wiki_client = __esm({
|
|
|
21309
21625
|
import React23, { useState as useState13, useEffect as useEffect15 } from "react";
|
|
21310
21626
|
import TextInput2 from "ink-text-input";
|
|
21311
21627
|
import { Fragment as Fragment4, jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
21628
|
+
function agentColor(agentId) {
|
|
21629
|
+
switch (agentId.toLowerCase()) {
|
|
21630
|
+
case "exe":
|
|
21631
|
+
return "#F5D76E";
|
|
21632
|
+
case "yoshi":
|
|
21633
|
+
return "#3B82F6";
|
|
21634
|
+
case "mari":
|
|
21635
|
+
return "#6B4C9A";
|
|
21636
|
+
default:
|
|
21637
|
+
return "#F0EDE8";
|
|
21638
|
+
}
|
|
21639
|
+
}
|
|
21640
|
+
function formatTimeAgo(iso) {
|
|
21641
|
+
const diff2 = Date.now() - new Date(iso).getTime();
|
|
21642
|
+
const hours = Math.floor(diff2 / 36e5);
|
|
21643
|
+
if (hours < 1) return "just now";
|
|
21644
|
+
if (hours < 24) return `${hours}h ago`;
|
|
21645
|
+
const days = Math.floor(hours / 24);
|
|
21646
|
+
return `${days}d ago`;
|
|
21647
|
+
}
|
|
21312
21648
|
function WikiView({ onBack }) {
|
|
21313
21649
|
const demo = useDemo();
|
|
21314
21650
|
const [activePanel, setActivePanel] = useState13("Workspaces");
|
|
@@ -21319,6 +21655,12 @@ function WikiView({ onBack }) {
|
|
|
21319
21655
|
const [chatHistory, setChatHistory] = useState13([]);
|
|
21320
21656
|
const [chatInput, setChatInput] = useState13("");
|
|
21321
21657
|
const [chatFocused, setChatFocused] = useState13(false);
|
|
21658
|
+
const [searchMode, setSearchMode] = useState13(false);
|
|
21659
|
+
const [searchQuery, setSearchQuery] = useState13("");
|
|
21660
|
+
const [searchResults, setSearchResults] = useState13([]);
|
|
21661
|
+
const [searchLoading, setSearchLoading] = useState13(false);
|
|
21662
|
+
const [selectedResultIdx, setSelectedResultIdx] = useState13(0);
|
|
21663
|
+
const [expandedResultIdx, setExpandedResultIdx] = useState13(null);
|
|
21322
21664
|
const [loading, setLoading] = useState13(true);
|
|
21323
21665
|
const [connected, setConnected] = useState13(false);
|
|
21324
21666
|
const [wikiUrl, setWikiUrl] = useState13("");
|
|
@@ -21412,6 +21754,55 @@ function WikiView({ onBack }) {
|
|
|
21412
21754
|
setSending(false);
|
|
21413
21755
|
}
|
|
21414
21756
|
}
|
|
21757
|
+
async function searchMemories2(query) {
|
|
21758
|
+
if (!query.trim()) {
|
|
21759
|
+
setSearchResults([]);
|
|
21760
|
+
return;
|
|
21761
|
+
}
|
|
21762
|
+
if (demo) {
|
|
21763
|
+
const q = query.toLowerCase();
|
|
21764
|
+
setSearchResults(
|
|
21765
|
+
DEMO_SEARCH_RESULTS.filter((r) => r.rawText.toLowerCase().includes(q))
|
|
21766
|
+
);
|
|
21767
|
+
return;
|
|
21768
|
+
}
|
|
21769
|
+
setSearchLoading(true);
|
|
21770
|
+
try {
|
|
21771
|
+
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
21772
|
+
const client = getClient2();
|
|
21773
|
+
const result = await client.execute({
|
|
21774
|
+
sql: `SELECT id, agent_id, raw_text, timestamp, project_name
|
|
21775
|
+
FROM memories
|
|
21776
|
+
WHERE raw_text LIKE ? AND COALESCE(status, 'active') = 'active'
|
|
21777
|
+
ORDER BY timestamp DESC LIMIT 20`,
|
|
21778
|
+
args: [`%${query}%`]
|
|
21779
|
+
});
|
|
21780
|
+
setSearchResults(
|
|
21781
|
+
result.rows.map((r) => ({
|
|
21782
|
+
id: String(r.id),
|
|
21783
|
+
agentId: String(r.agent_id),
|
|
21784
|
+
rawText: String(r.raw_text),
|
|
21785
|
+
timestamp: String(r.timestamp),
|
|
21786
|
+
projectName: String(r.project_name ?? "")
|
|
21787
|
+
}))
|
|
21788
|
+
);
|
|
21789
|
+
} catch {
|
|
21790
|
+
setSearchResults([]);
|
|
21791
|
+
} finally {
|
|
21792
|
+
setSearchLoading(false);
|
|
21793
|
+
}
|
|
21794
|
+
}
|
|
21795
|
+
useEffect15(() => {
|
|
21796
|
+
if (!searchMode) return;
|
|
21797
|
+
const timer = setTimeout(() => {
|
|
21798
|
+
searchMemories2(searchQuery);
|
|
21799
|
+
}, 300);
|
|
21800
|
+
return () => clearTimeout(timer);
|
|
21801
|
+
}, [searchQuery, searchMode]);
|
|
21802
|
+
useEffect15(() => {
|
|
21803
|
+
setSelectedResultIdx(0);
|
|
21804
|
+
setExpandedResultIdx(null);
|
|
21805
|
+
}, [searchResults]);
|
|
21415
21806
|
async function selectWorkspace(idx) {
|
|
21416
21807
|
setSelectedWorkspaceIdx(idx);
|
|
21417
21808
|
const ws = workspaces[idx];
|
|
@@ -21432,6 +21823,32 @@ function WikiView({ onBack }) {
|
|
|
21432
21823
|
}
|
|
21433
21824
|
}
|
|
21434
21825
|
use_input_default((input, key) => {
|
|
21826
|
+
if (searchMode && !chatFocused) {
|
|
21827
|
+
if (key.escape) {
|
|
21828
|
+
setSearchMode(false);
|
|
21829
|
+
setSearchQuery("");
|
|
21830
|
+
setSearchResults([]);
|
|
21831
|
+
setExpandedResultIdx(null);
|
|
21832
|
+
return;
|
|
21833
|
+
}
|
|
21834
|
+
if (key.upArrow && selectedResultIdx > 0) {
|
|
21835
|
+
setSelectedResultIdx(selectedResultIdx - 1);
|
|
21836
|
+
setExpandedResultIdx(null);
|
|
21837
|
+
return;
|
|
21838
|
+
}
|
|
21839
|
+
if (key.downArrow && selectedResultIdx < searchResults.length - 1) {
|
|
21840
|
+
setSelectedResultIdx(selectedResultIdx + 1);
|
|
21841
|
+
setExpandedResultIdx(null);
|
|
21842
|
+
return;
|
|
21843
|
+
}
|
|
21844
|
+
if (key.return && searchResults.length > 0) {
|
|
21845
|
+
setExpandedResultIdx(
|
|
21846
|
+
expandedResultIdx === selectedResultIdx ? null : selectedResultIdx
|
|
21847
|
+
);
|
|
21848
|
+
return;
|
|
21849
|
+
}
|
|
21850
|
+
return;
|
|
21851
|
+
}
|
|
21435
21852
|
if (chatFocused) {
|
|
21436
21853
|
if (key.escape) {
|
|
21437
21854
|
setChatFocused(false);
|
|
@@ -21443,6 +21860,13 @@ function WikiView({ onBack }) {
|
|
|
21443
21860
|
}
|
|
21444
21861
|
return;
|
|
21445
21862
|
}
|
|
21863
|
+
if (input === "/" && activePanel !== "Chat") {
|
|
21864
|
+
setSearchMode(true);
|
|
21865
|
+
setSearchQuery("");
|
|
21866
|
+
setSearchResults(demo ? DEMO_SEARCH_RESULTS : []);
|
|
21867
|
+
setExpandedResultIdx(null);
|
|
21868
|
+
return;
|
|
21869
|
+
}
|
|
21446
21870
|
if (key.leftArrow) {
|
|
21447
21871
|
const panelIdx = PANELS.indexOf(activePanel);
|
|
21448
21872
|
if (panelIdx === 0) {
|
|
@@ -21520,9 +21944,53 @@ function WikiView({ onBack }) {
|
|
|
21520
21944
|
/* @__PURE__ */ jsx13(Text, { bold: true, children: selectedWs.name })
|
|
21521
21945
|
] }) : null
|
|
21522
21946
|
] }),
|
|
21523
|
-
/* @__PURE__ */ jsx13(Text, { color: "#6B4C9A", children: "\u2190\u2192 switch panels | \u2191\u2193 navigate | /
|
|
21947
|
+
/* @__PURE__ */ jsx13(Text, { color: "#6B4C9A", children: "\u2190\u2192 switch panels | \u2191\u2193 navigate | / search memories | Enter select" }),
|
|
21524
21948
|
/* @__PURE__ */ jsx13(Text, { children: " " }),
|
|
21525
|
-
/* @__PURE__ */ jsxs11(Box_default, {
|
|
21949
|
+
searchMode ? /* @__PURE__ */ jsxs11(Box_default, { flexDirection: "column", flexGrow: 1, children: [
|
|
21950
|
+
/* @__PURE__ */ jsxs11(Box_default, { paddingX: 1, children: [
|
|
21951
|
+
/* @__PURE__ */ jsx13(Text, { color: "#F5D76E", children: "Search: " }),
|
|
21952
|
+
/* @__PURE__ */ jsx13(
|
|
21953
|
+
TextInput2,
|
|
21954
|
+
{
|
|
21955
|
+
value: searchQuery,
|
|
21956
|
+
onChange: setSearchQuery,
|
|
21957
|
+
placeholder: "search memories...",
|
|
21958
|
+
focus: true
|
|
21959
|
+
}
|
|
21960
|
+
),
|
|
21961
|
+
/* @__PURE__ */ jsx13(Text, { color: "#6B4C9A", children: " (esc to close)" })
|
|
21962
|
+
] }),
|
|
21963
|
+
/* @__PURE__ */ jsx13(Text, { children: " " }),
|
|
21964
|
+
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) => {
|
|
21965
|
+
const isSelected = i === selectedResultIdx;
|
|
21966
|
+
const isExpanded = i === expandedResultIdx;
|
|
21967
|
+
const snippet = result.rawText.slice(0, 80);
|
|
21968
|
+
return /* @__PURE__ */ jsxs11(Box_default, { flexDirection: "column", children: [
|
|
21969
|
+
/* @__PURE__ */ jsxs11(
|
|
21970
|
+
Text,
|
|
21971
|
+
{
|
|
21972
|
+
backgroundColor: isSelected ? "#6B4C9A" : void 0,
|
|
21973
|
+
color: isSelected ? "#F5D76E" : void 0,
|
|
21974
|
+
children: [
|
|
21975
|
+
" ",
|
|
21976
|
+
/* @__PURE__ */ jsx13(Text, { color: isSelected ? "#F5D76E" : agentColor(result.agentId), bold: true, children: result.agentId.padEnd(8) }),
|
|
21977
|
+
/* @__PURE__ */ jsxs11(Text, { color: isSelected ? "#F5D76E" : "#F0EDE8", children: [
|
|
21978
|
+
snippet,
|
|
21979
|
+
result.rawText.length > 80 ? "..." : ""
|
|
21980
|
+
] }),
|
|
21981
|
+
" ",
|
|
21982
|
+
/* @__PURE__ */ jsx13(Text, { color: isSelected ? "#F5D76E" : "#3D3660", dimColor: !isSelected, children: formatTimeAgo(result.timestamp) })
|
|
21983
|
+
]
|
|
21984
|
+
}
|
|
21985
|
+
),
|
|
21986
|
+
isExpanded ? /* @__PURE__ */ jsx13(Box_default, { paddingX: 4, marginBottom: 1, children: /* @__PURE__ */ jsx13(Text, { color: "#F0EDE8", wrap: "wrap", children: result.rawText }) }) : null
|
|
21987
|
+
] }, result.id);
|
|
21988
|
+
}),
|
|
21989
|
+
searchResults.length > 0 ? /* @__PURE__ */ jsxs11(Fragment4, { children: [
|
|
21990
|
+
/* @__PURE__ */ jsx13(Text, { children: " " }),
|
|
21991
|
+
/* @__PURE__ */ jsx13(Text, { color: "#3D3660", children: " \u2191\u2193 navigate | Enter expand | Esc close" })
|
|
21992
|
+
] }) : null
|
|
21993
|
+
] }) : /* @__PURE__ */ jsxs11(Box_default, { flexGrow: 1, gap: 1, children: [
|
|
21526
21994
|
/* @__PURE__ */ jsxs11(Box_default, { flexDirection: "column", width: "25%", children: [
|
|
21527
21995
|
/* @__PURE__ */ jsxs11(Text, { bold: true, backgroundColor: panelHeaderBg("Workspaces"), color: panelHeaderColor("Workspaces"), children: [
|
|
21528
21996
|
activePanel === "Workspaces" ? "\u25B8 " : " ",
|
|
@@ -21604,7 +22072,7 @@ function WikiView({ onBack }) {
|
|
|
21604
22072
|
] })
|
|
21605
22073
|
] });
|
|
21606
22074
|
}
|
|
21607
|
-
var PANELS, MAX_VISIBLE_MESSAGES;
|
|
22075
|
+
var PANELS, MAX_VISIBLE_MESSAGES, DEMO_SEARCH_RESULTS;
|
|
21608
22076
|
var init_Wiki = __esm({
|
|
21609
22077
|
async "src/tui/views/Wiki.tsx"() {
|
|
21610
22078
|
"use strict";
|
|
@@ -21613,53 +22081,48 @@ var init_Wiki = __esm({
|
|
|
21613
22081
|
init_demo_data();
|
|
21614
22082
|
PANELS = ["Workspaces", "Documents", "Chat"];
|
|
21615
22083
|
MAX_VISIBLE_MESSAGES = 12;
|
|
22084
|
+
DEMO_SEARCH_RESULTS = [
|
|
22085
|
+
{ 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" },
|
|
22086
|
+
{ 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" },
|
|
22087
|
+
{ 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" },
|
|
22088
|
+
{ 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" },
|
|
22089
|
+
{ 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" }
|
|
22090
|
+
];
|
|
21616
22091
|
}
|
|
21617
22092
|
});
|
|
21618
22093
|
|
|
21619
22094
|
// src/tui/views/Settings.tsx
|
|
21620
|
-
import React24, { useState as useState14, useEffect as useEffect16 } from "react";
|
|
22095
|
+
import React24, { useState as useState14, useEffect as useEffect16, useCallback as useCallback7 } from "react";
|
|
21621
22096
|
import { Fragment as Fragment5, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
22097
|
+
function maskSecret(value) {
|
|
22098
|
+
if (value.length <= 10) return "****";
|
|
22099
|
+
return `${value.slice(0, 6)}...${value.slice(-4)}`;
|
|
22100
|
+
}
|
|
21622
22101
|
function SettingsView({ onBack }) {
|
|
21623
22102
|
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([]);
|
|
22103
|
+
const [cloud, setCloud] = useState14({ configured: false, endpoint: "", apiKey: "" });
|
|
22104
|
+
const [license, setLicense] = useState14({ valid: false, plan: "checking...", expiresAt: null, deviceLimit: 0, employeeLimit: 0, memoryLimit: 0 });
|
|
22105
|
+
const [system, setSystem] = useState14({ daemon: "unknown", version: "...", dbPath: "...", embeddingModel: "...", encryption: "checking..." });
|
|
22106
|
+
const [gateway, setGateway] = useState14({ adapters: [] });
|
|
21639
22107
|
const [selectedSection, setSelectedSection] = useState14(0);
|
|
21640
22108
|
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" }
|
|
22109
|
+
const loadSettings = useCallback7(async () => {
|
|
22110
|
+
setLoading(true);
|
|
22111
|
+
const envKeys = [
|
|
22112
|
+
["Anthropic", "ANTHROPIC_API_KEY"],
|
|
22113
|
+
["OpenCode", "OPENCODE_API_KEY"],
|
|
22114
|
+
["Gemini", "GEMINI_API_KEY"],
|
|
22115
|
+
["OpenAI", "OPENAI_API_KEY"],
|
|
22116
|
+
["Chutes", "CHUTES_API_KEY"]
|
|
21662
22117
|
];
|
|
22118
|
+
const providerList = envKeys.map(([name, envVar]) => {
|
|
22119
|
+
const val = process.env[envVar];
|
|
22120
|
+
return {
|
|
22121
|
+
name,
|
|
22122
|
+
configured: !!val,
|
|
22123
|
+
detail: val ? maskSecret(val) : "not configured"
|
|
22124
|
+
};
|
|
22125
|
+
});
|
|
21663
22126
|
try {
|
|
21664
22127
|
const { execSync: execSync13 } = await import("child_process");
|
|
21665
22128
|
execSync13("curl -s --max-time 1 http://localhost:11434/api/tags", { timeout: 2e3 });
|
|
@@ -21671,112 +22134,101 @@ function SettingsView({ onBack }) {
|
|
|
21671
22134
|
try {
|
|
21672
22135
|
const { existsSync: existsSync22 } = await import("fs");
|
|
21673
22136
|
const { join } = await import("path");
|
|
21674
|
-
const home = process.env.HOME ?? "";
|
|
21675
|
-
const hasKey = existsSync22(join(home, ".exe-os", "master.key"));
|
|
21676
22137
|
const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
21677
22138
|
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
22139
|
const home = process.env.HOME ?? "";
|
|
21702
|
-
const
|
|
21703
|
-
|
|
21704
|
-
|
|
21705
|
-
|
|
21706
|
-
|
|
21707
|
-
|
|
21708
|
-
|
|
21709
|
-
|
|
21710
|
-
|
|
21711
|
-
}
|
|
22140
|
+
const hasKey = existsSync22(join(home, ".exe-os", "master.key"));
|
|
22141
|
+
if (cfg.cloud) {
|
|
22142
|
+
setCloud({
|
|
22143
|
+
configured: true,
|
|
22144
|
+
endpoint: cfg.cloud.endpoint,
|
|
22145
|
+
apiKey: maskSecret(cfg.cloud.apiKey)
|
|
22146
|
+
});
|
|
22147
|
+
} else {
|
|
22148
|
+
setCloud({ configured: false, endpoint: "", apiKey: "" });
|
|
21712
22149
|
}
|
|
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
|
-
}
|
|
22150
|
+
const pidPath = join(home, ".exe-os", "exed.pid");
|
|
22151
|
+
let daemon = "unknown";
|
|
22152
|
+
try {
|
|
22153
|
+
daemon = existsSync22(pidPath) ? "running" : "stopped";
|
|
22154
|
+
} catch {
|
|
21736
22155
|
}
|
|
21737
|
-
|
|
21738
|
-
|
|
21739
|
-
|
|
21740
|
-
|
|
21741
|
-
|
|
21742
|
-
|
|
21743
|
-
|
|
21744
|
-
|
|
21745
|
-
|
|
22156
|
+
let version = "unknown";
|
|
22157
|
+
try {
|
|
22158
|
+
const { readFileSync: readFileSync18 } = await import("fs");
|
|
22159
|
+
const { createRequire } = await import("module");
|
|
22160
|
+
const require2 = createRequire(import.meta.url);
|
|
22161
|
+
const pkgPath = require2.resolve("@askexenow/exe-os/package.json");
|
|
22162
|
+
const pkg = JSON.parse(readFileSync18(pkgPath, "utf8"));
|
|
22163
|
+
version = pkg.version;
|
|
22164
|
+
} catch {
|
|
21746
22165
|
try {
|
|
21747
|
-
const
|
|
21748
|
-
|
|
22166
|
+
const { readFileSync: readFileSync18 } = await import("fs");
|
|
22167
|
+
const { join: joinPath } = await import("path");
|
|
22168
|
+
const pkg = JSON.parse(readFileSync18(joinPath(process.cwd(), "package.json"), "utf8"));
|
|
22169
|
+
version = pkg.version;
|
|
21749
22170
|
} catch {
|
|
21750
|
-
setLicense({ valid: false, detail: "invalid license file" });
|
|
21751
22171
|
}
|
|
21752
|
-
} else {
|
|
21753
|
-
setLicense({ valid: false, detail: "no license" });
|
|
21754
22172
|
}
|
|
22173
|
+
setSystem({
|
|
22174
|
+
daemon,
|
|
22175
|
+
version,
|
|
22176
|
+
dbPath: cfg.dbPath,
|
|
22177
|
+
embeddingModel: cfg.modelFile ?? "unknown",
|
|
22178
|
+
encryption: hasKey ? "SQLCipher AES-256" : "not configured"
|
|
22179
|
+
});
|
|
21755
22180
|
} catch {
|
|
21756
22181
|
}
|
|
21757
22182
|
try {
|
|
21758
|
-
const {
|
|
21759
|
-
const
|
|
21760
|
-
|
|
21761
|
-
|
|
21762
|
-
|
|
21763
|
-
|
|
21764
|
-
|
|
21765
|
-
|
|
21766
|
-
|
|
22183
|
+
const { checkLicense: checkLicense2 } = await Promise.resolve().then(() => (init_license(), license_exports));
|
|
22184
|
+
const lic = await checkLicense2();
|
|
22185
|
+
setLicense({
|
|
22186
|
+
valid: lic.valid,
|
|
22187
|
+
plan: lic.plan.toUpperCase(),
|
|
22188
|
+
expiresAt: lic.expiresAt,
|
|
22189
|
+
deviceLimit: lic.deviceLimit,
|
|
22190
|
+
employeeLimit: lic.employeeLimit,
|
|
22191
|
+
memoryLimit: lic.memoryLimit
|
|
22192
|
+
});
|
|
21767
22193
|
} catch {
|
|
22194
|
+
setLicense({ valid: false, plan: "FREE", expiresAt: null, deviceLimit: 1, employeeLimit: 1, memoryLimit: 5e3 });
|
|
21768
22195
|
}
|
|
21769
|
-
|
|
21770
|
-
|
|
21771
|
-
|
|
21772
|
-
|
|
22196
|
+
const gatewayAdapters = [
|
|
22197
|
+
{ name: "WhatsApp", configured: !!process.env.WHATSAPP_API_TOKEN || !!process.env.WHATSAPP_PHONE_NUMBER_ID },
|
|
22198
|
+
{ name: "Telegram", configured: !!process.env.TELEGRAM_BOT_TOKEN },
|
|
22199
|
+
{ name: "Discord", configured: !!process.env.DISCORD_BOT_TOKEN },
|
|
22200
|
+
{ name: "Slack", configured: !!process.env.SLACK_BOT_TOKEN }
|
|
22201
|
+
];
|
|
22202
|
+
setGateway({ adapters: gatewayAdapters });
|
|
22203
|
+
setLoading(false);
|
|
22204
|
+
}, []);
|
|
22205
|
+
useEffect16(() => {
|
|
22206
|
+
loadSettings();
|
|
22207
|
+
}, [loadSettings]);
|
|
22208
|
+
use_input_default((input, key) => {
|
|
22209
|
+
if (key.leftArrow) {
|
|
22210
|
+
onBack?.();
|
|
22211
|
+
return;
|
|
22212
|
+
}
|
|
22213
|
+
if (key.upArrow && selectedSection > 0) setSelectedSection(selectedSection - 1);
|
|
22214
|
+
if (key.downArrow && selectedSection < SECTION_NAMES.length - 1) setSelectedSection(selectedSection + 1);
|
|
22215
|
+
if (input === "r") {
|
|
22216
|
+
loadSettings();
|
|
22217
|
+
}
|
|
22218
|
+
});
|
|
22219
|
+
const statusDot = (ok) => ok ? "\u2022" : "\u2022";
|
|
22220
|
+
const statusColor = (ok) => ok ? GREEN : DIM;
|
|
22221
|
+
const sectionColor = (idx) => selectedSection === idx ? YELLOW : void 0;
|
|
22222
|
+
const sectionBg = (idx) => selectedSection === idx ? DIM : void 0;
|
|
21773
22223
|
const sectionMarker = (idx) => selectedSection === idx ? "\u25B8 " : " ";
|
|
22224
|
+
const anyGateway = gateway.adapters.some((a) => a.configured);
|
|
22225
|
+
const formatLimit = (n) => n === -1 ? "unlimited" : n.toLocaleString();
|
|
21774
22226
|
return /* @__PURE__ */ jsxs12(Box_default, { flexDirection: "column", flexGrow: 1, paddingX: 1, children: [
|
|
21775
22227
|
/* @__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:
|
|
22228
|
+
/* @__PURE__ */ jsx14(Text, { color: DIM, children: "\u2191\u2193 navigate sections r refresh" }),
|
|
21777
22229
|
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21778
22230
|
loading && /* @__PURE__ */ jsxs12(Fragment5, { children: [
|
|
21779
|
-
/* @__PURE__ */ jsx14(Text, { color:
|
|
22231
|
+
/* @__PURE__ */ jsx14(Text, { color: DIM, children: "Loading settings..." }),
|
|
21780
22232
|
/* @__PURE__ */ jsx14(Text, { children: " " })
|
|
21781
22233
|
] }),
|
|
21782
22234
|
/* @__PURE__ */ jsxs12(Text, { bold: true, backgroundColor: sectionBg(0), color: sectionColor(0), children: [
|
|
@@ -21786,6 +22238,8 @@ function SettingsView({ onBack }) {
|
|
|
21786
22238
|
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21787
22239
|
providers.map((p) => /* @__PURE__ */ jsxs12(Text, { children: [
|
|
21788
22240
|
" ",
|
|
22241
|
+
/* @__PURE__ */ jsx14(Text, { color: statusColor(p.configured), children: statusDot(p.configured) }),
|
|
22242
|
+
" ",
|
|
21789
22243
|
p.name,
|
|
21790
22244
|
": ",
|
|
21791
22245
|
/* @__PURE__ */ jsx14(Text, { color: statusColor(p.configured), children: p.detail })
|
|
@@ -21793,131 +22247,274 @@ function SettingsView({ onBack }) {
|
|
|
21793
22247
|
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21794
22248
|
/* @__PURE__ */ jsxs12(Text, { bold: true, backgroundColor: sectionBg(1), color: sectionColor(1), children: [
|
|
21795
22249
|
sectionMarker(1),
|
|
21796
|
-
"
|
|
22250
|
+
"Cloud Sync"
|
|
21797
22251
|
] }),
|
|
21798
22252
|
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21799
|
-
/* @__PURE__ */ jsxs12(
|
|
22253
|
+
cloud.configured ? /* @__PURE__ */ jsxs12(Fragment5, { children: [
|
|
22254
|
+
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
22255
|
+
" ",
|
|
22256
|
+
/* @__PURE__ */ jsx14(Text, { color: GREEN, children: statusDot(true) }),
|
|
22257
|
+
" Status: ",
|
|
22258
|
+
/* @__PURE__ */ jsx14(Text, { color: GREEN, children: "connected" })
|
|
22259
|
+
] }),
|
|
22260
|
+
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
22261
|
+
" ",
|
|
22262
|
+
"Endpoint: ",
|
|
22263
|
+
/* @__PURE__ */ jsx14(Text, { color: GREEN, children: cloud.endpoint })
|
|
22264
|
+
] }),
|
|
22265
|
+
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
22266
|
+
" ",
|
|
22267
|
+
"API key: ",
|
|
22268
|
+
/* @__PURE__ */ jsx14(Text, { color: DIM, children: cloud.apiKey })
|
|
22269
|
+
] })
|
|
22270
|
+
] }) : /* @__PURE__ */ jsxs12(Text, { children: [
|
|
21800
22271
|
" ",
|
|
21801
|
-
|
|
21802
|
-
|
|
22272
|
+
/* @__PURE__ */ jsx14(Text, { color: DIM, children: statusDot(false) }),
|
|
22273
|
+
" ",
|
|
22274
|
+
/* @__PURE__ */ jsx14(Text, { color: DIM, children: "Not configured \u2014 run /exe-cloud" })
|
|
21803
22275
|
] }),
|
|
21804
|
-
/* @__PURE__ */
|
|
21805
|
-
|
|
21806
|
-
|
|
21807
|
-
|
|
22276
|
+
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
22277
|
+
/* @__PURE__ */ jsxs12(Text, { bold: true, backgroundColor: sectionBg(2), color: sectionColor(2), children: [
|
|
22278
|
+
sectionMarker(2),
|
|
22279
|
+
"License"
|
|
21808
22280
|
] }),
|
|
22281
|
+
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21809
22282
|
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
21810
22283
|
" ",
|
|
21811
|
-
"
|
|
21812
|
-
/* @__PURE__ */ jsx14(Text, { color:
|
|
22284
|
+
"Plan: ",
|
|
22285
|
+
/* @__PURE__ */ jsx14(Text, { color: license.plan === "FREE" ? YELLOW : GREEN, children: license.plan })
|
|
21813
22286
|
] }),
|
|
21814
|
-
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
22287
|
+
license.expiresAt && /* @__PURE__ */ jsxs12(Text, { children: [
|
|
21815
22288
|
" ",
|
|
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"
|
|
22289
|
+
"Expires: ",
|
|
22290
|
+
/* @__PURE__ */ jsx14(Text, { color: GREEN, children: license.expiresAt.split("T")[0] })
|
|
21823
22291
|
] }),
|
|
21824
|
-
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21825
22292
|
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
21826
22293
|
" ",
|
|
21827
|
-
"
|
|
21828
|
-
/* @__PURE__ */ jsx14(Text, { color:
|
|
21829
|
-
" (",
|
|
21830
|
-
runtime.consolidationModel,
|
|
21831
|
-
")"
|
|
22294
|
+
"Devices: ",
|
|
22295
|
+
/* @__PURE__ */ jsx14(Text, { color: GREEN, children: formatLimit(license.deviceLimit) })
|
|
21832
22296
|
] }),
|
|
21833
22297
|
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
21834
22298
|
" ",
|
|
21835
|
-
"
|
|
21836
|
-
/* @__PURE__ */ jsx14(Text, { color:
|
|
21837
|
-
" (threshold: ",
|
|
21838
|
-
runtime.skillThreshold,
|
|
21839
|
-
")"
|
|
22299
|
+
"Employees: ",
|
|
22300
|
+
/* @__PURE__ */ jsx14(Text, { color: GREEN, children: formatLimit(license.employeeLimit) })
|
|
21840
22301
|
] }),
|
|
21841
22302
|
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
21842
22303
|
" ",
|
|
21843
|
-
"
|
|
21844
|
-
/* @__PURE__ */ jsx14(Text, { color:
|
|
22304
|
+
"Memory limit: ",
|
|
22305
|
+
/* @__PURE__ */ jsx14(Text, { color: GREEN, children: formatLimit(license.memoryLimit) })
|
|
21845
22306
|
] }),
|
|
21846
22307
|
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21847
22308
|
/* @__PURE__ */ jsxs12(Text, { bold: true, backgroundColor: sectionBg(3), color: sectionColor(3), children: [
|
|
21848
22309
|
sectionMarker(3),
|
|
21849
|
-
"
|
|
22310
|
+
"System"
|
|
21850
22311
|
] }),
|
|
21851
22312
|
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21852
|
-
|
|
21853
|
-
" ",
|
|
21854
|
-
"Loading..."
|
|
21855
|
-
] }) : employeeModels.length === 0 ? /* @__PURE__ */ jsxs12(Text, { color: "#6B4C9A", children: [
|
|
22313
|
+
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
21856
22314
|
" ",
|
|
21857
|
-
"
|
|
21858
|
-
|
|
22315
|
+
/* @__PURE__ */ jsx14(Text, { color: system.daemon === "running" ? GREEN : DIM, children: statusDot(system.daemon === "running") }),
|
|
22316
|
+
" Daemon: ",
|
|
22317
|
+
/* @__PURE__ */ jsx14(Text, { color: system.daemon === "running" ? GREEN : DIM, children: system.daemon })
|
|
22318
|
+
] }),
|
|
22319
|
+
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
21859
22320
|
" ",
|
|
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"
|
|
22321
|
+
"Version: ",
|
|
22322
|
+
/* @__PURE__ */ jsx14(Text, { color: GREEN, children: system.version })
|
|
21873
22323
|
] }),
|
|
21874
|
-
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
21875
22324
|
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
21876
22325
|
" ",
|
|
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
|
-
] })
|
|
22326
|
+
"Encryption: ",
|
|
22327
|
+
/* @__PURE__ */ jsx14(Text, { color: system.encryption.includes("AES") ? GREEN : DIM, children: system.encryption })
|
|
21883
22328
|
] }),
|
|
21884
22329
|
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
21885
22330
|
" ",
|
|
21886
|
-
"
|
|
21887
|
-
/* @__PURE__ */ jsx14(Text, { color:
|
|
22331
|
+
"Embedding: ",
|
|
22332
|
+
/* @__PURE__ */ jsx14(Text, { color: GREEN, children: system.embeddingModel })
|
|
21888
22333
|
] }),
|
|
21889
22334
|
/* @__PURE__ */ jsxs12(Text, { children: [
|
|
21890
22335
|
" ",
|
|
21891
|
-
"
|
|
21892
|
-
/* @__PURE__ */ jsx14(Text, { color:
|
|
22336
|
+
"DB path: ",
|
|
22337
|
+
/* @__PURE__ */ jsx14(Text, { color: DIM, children: system.dbPath })
|
|
22338
|
+
] }),
|
|
22339
|
+
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
22340
|
+
/* @__PURE__ */ jsxs12(Text, { bold: true, backgroundColor: sectionBg(4), color: sectionColor(4), children: [
|
|
22341
|
+
sectionMarker(4),
|
|
22342
|
+
"Gateway"
|
|
22343
|
+
] }),
|
|
22344
|
+
/* @__PURE__ */ jsx14(Text, { children: " " }),
|
|
22345
|
+
anyGateway ? gateway.adapters.map((a) => /* @__PURE__ */ jsxs12(Text, { children: [
|
|
22346
|
+
" ",
|
|
22347
|
+
/* @__PURE__ */ jsx14(Text, { color: statusColor(a.configured), children: statusDot(a.configured) }),
|
|
22348
|
+
" ",
|
|
22349
|
+
a.name,
|
|
22350
|
+
": ",
|
|
22351
|
+
/* @__PURE__ */ jsx14(Text, { color: statusColor(a.configured), children: a.configured ? "configured" : "not configured" })
|
|
22352
|
+
] }, a.name)) : /* @__PURE__ */ jsxs12(Text, { children: [
|
|
22353
|
+
" ",
|
|
22354
|
+
/* @__PURE__ */ jsx14(Text, { color: DIM, children: statusDot(false) }),
|
|
22355
|
+
" ",
|
|
22356
|
+
/* @__PURE__ */ jsx14(Text, { color: DIM, children: "No gateway configured" })
|
|
21893
22357
|
] })
|
|
21894
22358
|
] });
|
|
21895
22359
|
}
|
|
21896
|
-
var SECTION_NAMES;
|
|
22360
|
+
var SECTION_NAMES, GREEN, DIM, YELLOW;
|
|
21897
22361
|
var init_Settings = __esm({
|
|
21898
22362
|
async "src/tui/views/Settings.tsx"() {
|
|
21899
22363
|
"use strict";
|
|
21900
22364
|
await init_ink2();
|
|
21901
|
-
SECTION_NAMES = ["Providers", "
|
|
22365
|
+
SECTION_NAMES = ["Providers", "Cloud Sync", "License", "System", "Gateway"];
|
|
22366
|
+
GREEN = "#22C55E";
|
|
22367
|
+
DIM = "#6B4C9A";
|
|
22368
|
+
YELLOW = "#F5D76E";
|
|
22369
|
+
}
|
|
22370
|
+
});
|
|
22371
|
+
|
|
22372
|
+
// src/tui/views/DebugPanel.tsx
|
|
22373
|
+
import React25, { useState as useState15, useEffect as useEffect17 } from "react";
|
|
22374
|
+
import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
22375
|
+
function formatEvent(e) {
|
|
22376
|
+
switch (e.type) {
|
|
22377
|
+
case "task_completed":
|
|
22378
|
+
return `${e.employee}: "${e.result.slice(0, 60)}"`;
|
|
22379
|
+
case "review_created":
|
|
22380
|
+
return `${e.employee} \u2192 ${e.reviewer}`;
|
|
22381
|
+
case "employee_status":
|
|
22382
|
+
return `${e.employee}: ${e.status}`;
|
|
22383
|
+
case "memory_stored":
|
|
22384
|
+
return `${e.agentId} [${e.project}]`;
|
|
22385
|
+
case "session_started":
|
|
22386
|
+
return `${e.employee} (${e.sessionId.slice(0, 8)})`;
|
|
22387
|
+
case "session_ended":
|
|
22388
|
+
return `${e.employee} (${e.sessionId.slice(0, 8)})`;
|
|
22389
|
+
case "gateway_message":
|
|
22390
|
+
return `${e.platform}/${e.senderId} \u2192 ${e.botId}`;
|
|
22391
|
+
}
|
|
22392
|
+
}
|
|
22393
|
+
function DebugPanel() {
|
|
22394
|
+
const [events, setEvents] = useState15([]);
|
|
22395
|
+
useEffect17(() => {
|
|
22396
|
+
let counter = 0;
|
|
22397
|
+
const handler = (event) => {
|
|
22398
|
+
setEvents((prev) => {
|
|
22399
|
+
const next = [...prev, { event, id: counter++ }];
|
|
22400
|
+
return next.slice(-MAX_EVENTS);
|
|
22401
|
+
});
|
|
22402
|
+
};
|
|
22403
|
+
orgBus.onAny(handler);
|
|
22404
|
+
return () => {
|
|
22405
|
+
orgBus.offAny(handler);
|
|
22406
|
+
};
|
|
22407
|
+
}, []);
|
|
22408
|
+
return /* @__PURE__ */ jsxs13(Box_default, { flexDirection: "column", borderStyle: "single", borderColor: "#6B4C9A", flexGrow: 1, paddingX: 1, children: [
|
|
22409
|
+
/* @__PURE__ */ jsx15(Text, { bold: true, color: "#F5D76E", children: "Debug \u2014 Live Events" }),
|
|
22410
|
+
/* @__PURE__ */ jsx15(Text, { color: "#3D3660", children: "\u2500".repeat(40) }),
|
|
22411
|
+
events.length === 0 ? /* @__PURE__ */ jsx15(Text, { color: "#3D3660", children: "Waiting for events..." }) : events.slice(-DISPLAY_EVENTS).map(({ event, id }) => {
|
|
22412
|
+
const time = event.timestamp?.slice(11, 19) ?? "??:??:??";
|
|
22413
|
+
const color = EVENT_COLORS[event.type] ?? "#6B4C9A";
|
|
22414
|
+
const summary = formatEvent(event);
|
|
22415
|
+
return /* @__PURE__ */ jsxs13(Text, { color, children: [
|
|
22416
|
+
"[",
|
|
22417
|
+
time,
|
|
22418
|
+
"] ",
|
|
22419
|
+
event.type,
|
|
22420
|
+
" \u2014 ",
|
|
22421
|
+
summary
|
|
22422
|
+
] }, id);
|
|
22423
|
+
})
|
|
22424
|
+
] });
|
|
22425
|
+
}
|
|
22426
|
+
var MAX_EVENTS, DISPLAY_EVENTS, EVENT_COLORS;
|
|
22427
|
+
var init_DebugPanel = __esm({
|
|
22428
|
+
async "src/tui/views/DebugPanel.tsx"() {
|
|
22429
|
+
"use strict";
|
|
22430
|
+
await init_ink2();
|
|
22431
|
+
init_state_bus();
|
|
22432
|
+
MAX_EVENTS = 50;
|
|
22433
|
+
DISPLAY_EVENTS = 20;
|
|
22434
|
+
EVENT_COLORS = {
|
|
22435
|
+
task_completed: "#22C55E",
|
|
22436
|
+
review_created: "#F59E0B",
|
|
22437
|
+
employee_status: "#3B82F6",
|
|
22438
|
+
memory_stored: "#8B5CF6",
|
|
22439
|
+
session_started: "#06B6D4",
|
|
22440
|
+
session_ended: "#EF4444",
|
|
22441
|
+
gateway_message: "#EC4899"
|
|
22442
|
+
};
|
|
22443
|
+
}
|
|
22444
|
+
});
|
|
22445
|
+
|
|
22446
|
+
// src/tui/components/HelpOverlay.tsx
|
|
22447
|
+
import React26 from "react";
|
|
22448
|
+
import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
22449
|
+
function HelpOverlay({ tabName, shortcuts }) {
|
|
22450
|
+
return /* @__PURE__ */ jsxs14(
|
|
22451
|
+
Box_default,
|
|
22452
|
+
{
|
|
22453
|
+
flexDirection: "column",
|
|
22454
|
+
borderStyle: "double",
|
|
22455
|
+
borderColor: "#6B4C9A",
|
|
22456
|
+
paddingX: 2,
|
|
22457
|
+
paddingY: 1,
|
|
22458
|
+
width: 50,
|
|
22459
|
+
alignSelf: "center",
|
|
22460
|
+
children: [
|
|
22461
|
+
/* @__PURE__ */ jsxs14(Text, { bold: true, color: "#F5D76E", children: [
|
|
22462
|
+
"Keyboard Shortcuts \u2014 ",
|
|
22463
|
+
tabName
|
|
22464
|
+
] }),
|
|
22465
|
+
/* @__PURE__ */ jsx16(Text, { children: " " }),
|
|
22466
|
+
shortcuts.map((s, i) => /* @__PURE__ */ jsxs14(Box_default, { gap: 1, children: [
|
|
22467
|
+
/* @__PURE__ */ jsx16(Text, { color: "#F5D76E", bold: true, children: s.key.padEnd(10) }),
|
|
22468
|
+
/* @__PURE__ */ jsx16(Text, { color: "#F0EDE8", children: s.description })
|
|
22469
|
+
] }, i)),
|
|
22470
|
+
/* @__PURE__ */ jsx16(Text, { children: " " }),
|
|
22471
|
+
/* @__PURE__ */ jsx16(Text, { bold: true, color: "#F5D76E", children: "Global" }),
|
|
22472
|
+
/* @__PURE__ */ jsx16(Text, { children: " " }),
|
|
22473
|
+
/* @__PURE__ */ jsxs14(Box_default, { gap: 1, children: [
|
|
22474
|
+
/* @__PURE__ */ jsx16(Text, { color: "#F5D76E", bold: true, children: "1-7".padEnd(10) }),
|
|
22475
|
+
/* @__PURE__ */ jsx16(Text, { color: "#F0EDE8", children: "Switch tabs" })
|
|
22476
|
+
] }),
|
|
22477
|
+
/* @__PURE__ */ jsxs14(Box_default, { gap: 1, children: [
|
|
22478
|
+
/* @__PURE__ */ jsx16(Text, { color: "#F5D76E", bold: true, children: "q".padEnd(10) }),
|
|
22479
|
+
/* @__PURE__ */ jsx16(Text, { color: "#F0EDE8", children: "Quit" })
|
|
22480
|
+
] }),
|
|
22481
|
+
/* @__PURE__ */ jsxs14(Box_default, { gap: 1, children: [
|
|
22482
|
+
/* @__PURE__ */ jsx16(Text, { color: "#F5D76E", bold: true, children: "?".padEnd(10) }),
|
|
22483
|
+
/* @__PURE__ */ jsx16(Text, { color: "#F0EDE8", children: "Toggle this help" })
|
|
22484
|
+
] }),
|
|
22485
|
+
/* @__PURE__ */ jsxs14(Box_default, { gap: 1, children: [
|
|
22486
|
+
/* @__PURE__ */ jsx16(Text, { color: "#F5D76E", bold: true, children: "Esc".padEnd(10) }),
|
|
22487
|
+
/* @__PURE__ */ jsx16(Text, { color: "#F0EDE8", children: "Back to sidebar" })
|
|
22488
|
+
] }),
|
|
22489
|
+
/* @__PURE__ */ jsx16(Text, { children: " " }),
|
|
22490
|
+
/* @__PURE__ */ jsx16(Text, { color: "#6B4C9A", children: "Press ? to close" })
|
|
22491
|
+
]
|
|
22492
|
+
}
|
|
22493
|
+
);
|
|
22494
|
+
}
|
|
22495
|
+
var init_HelpOverlay = __esm({
|
|
22496
|
+
async "src/tui/components/HelpOverlay.tsx"() {
|
|
22497
|
+
"use strict";
|
|
22498
|
+
await init_ink2();
|
|
21902
22499
|
}
|
|
21903
22500
|
});
|
|
21904
22501
|
|
|
21905
22502
|
// src/tui/App.tsx
|
|
21906
22503
|
var App_exports = {};
|
|
21907
|
-
import { useState as
|
|
21908
|
-
import { jsx as
|
|
22504
|
+
import { useState as useState16, useEffect as useEffect18, useCallback as useCallback8 } from "react";
|
|
22505
|
+
import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
21909
22506
|
function App2() {
|
|
21910
|
-
const [section, setSection] =
|
|
22507
|
+
const [section, setSection] = useState16("command-center");
|
|
21911
22508
|
const { exit } = use_app_default();
|
|
21912
|
-
const [, forceUpdate] =
|
|
21913
|
-
|
|
22509
|
+
const [, forceUpdate] = useState16(0);
|
|
22510
|
+
useEffect18(() => {
|
|
21914
22511
|
const handleResize = () => forceUpdate((n) => n + 1);
|
|
21915
22512
|
process.stdout.on("resize", handleResize);
|
|
21916
22513
|
return () => {
|
|
21917
22514
|
process.stdout.off("resize", handleResize);
|
|
21918
22515
|
};
|
|
21919
22516
|
}, []);
|
|
21920
|
-
useMouseEvent(
|
|
22517
|
+
useMouseEvent(useCallback8((event) => {
|
|
21921
22518
|
if (event.button !== 0) return;
|
|
21922
22519
|
if (event.col <= 26) {
|
|
21923
22520
|
const tabIdx = event.row - 4;
|
|
@@ -21929,22 +22526,33 @@ function App2() {
|
|
|
21929
22526
|
setFocus("content");
|
|
21930
22527
|
}
|
|
21931
22528
|
}, []));
|
|
21932
|
-
const [focus, setFocus] =
|
|
21933
|
-
const [
|
|
21934
|
-
const
|
|
22529
|
+
const [focus, setFocus] = useState16("sidebar");
|
|
22530
|
+
const [showDebug, setShowDebug] = useState16(false);
|
|
22531
|
+
const [showHelp, setShowHelp] = useState16(false);
|
|
22532
|
+
const [focusedProject, setFocusedProject] = useState16(null);
|
|
22533
|
+
const handleSelectProject = useCallback8((projectName) => {
|
|
21935
22534
|
setFocusedProject(projectName);
|
|
21936
22535
|
setSection("sessions");
|
|
21937
22536
|
setFocus("content");
|
|
21938
22537
|
}, []);
|
|
21939
|
-
const handleBackToCommandCenter =
|
|
22538
|
+
const handleBackToCommandCenter = useCallback8(() => {
|
|
21940
22539
|
setSection("command-center");
|
|
21941
22540
|
setFocus("sidebar");
|
|
21942
22541
|
}, []);
|
|
21943
22542
|
use_input_default((input, key) => {
|
|
22543
|
+
if (input === "?" || key.shift && input === "/") {
|
|
22544
|
+
setShowHelp((prev) => !prev);
|
|
22545
|
+
return;
|
|
22546
|
+
}
|
|
21944
22547
|
const idx = parseInt(input, 10);
|
|
21945
22548
|
if (idx >= 1 && idx <= SECTIONS.length) {
|
|
21946
22549
|
setSection(SECTIONS[idx - 1].key);
|
|
21947
22550
|
setFocus("sidebar");
|
|
22551
|
+
setShowHelp(false);
|
|
22552
|
+
return;
|
|
22553
|
+
}
|
|
22554
|
+
if (input === "d" && !key.ctrl) {
|
|
22555
|
+
setShowDebug((prev) => !prev);
|
|
21948
22556
|
return;
|
|
21949
22557
|
}
|
|
21950
22558
|
if (input === "q" && !key.ctrl) {
|
|
@@ -21972,27 +22580,37 @@ function App2() {
|
|
|
21972
22580
|
}
|
|
21973
22581
|
}
|
|
21974
22582
|
});
|
|
21975
|
-
const consumeFocusedProject =
|
|
22583
|
+
const consumeFocusedProject = useCallback8(() => {
|
|
21976
22584
|
setFocusedProject(null);
|
|
21977
22585
|
}, []);
|
|
21978
22586
|
const views = {
|
|
21979
|
-
"command-center": /* @__PURE__ */
|
|
21980
|
-
sessions: /* @__PURE__ */
|
|
21981
|
-
tasks: /* @__PURE__ */
|
|
21982
|
-
team: /* @__PURE__ */
|
|
21983
|
-
|
|
21984
|
-
|
|
21985
|
-
|
|
22587
|
+
"command-center": /* @__PURE__ */ jsx17(CommandCenterView, { onSelectProject: handleSelectProject, isFocused: focus === "content" && section === "command-center", onBack: () => setFocus("sidebar") }),
|
|
22588
|
+
sessions: /* @__PURE__ */ jsx17(SessionsView, { initialProject: focusedProject, onConsumeInitialProject: consumeFocusedProject, onBackToCommandCenter: handleBackToCommandCenter, onBack: () => setFocus("sidebar") }),
|
|
22589
|
+
tasks: /* @__PURE__ */ jsx17(TasksView, { onBack: () => setFocus("sidebar") }),
|
|
22590
|
+
team: /* @__PURE__ */ jsx17(TeamView, { onBack: () => setFocus("sidebar"), onViewSessions: (name) => {
|
|
22591
|
+
setFocusedProject(name);
|
|
22592
|
+
setSection("sessions");
|
|
22593
|
+
setFocus("content");
|
|
22594
|
+
} }),
|
|
22595
|
+
gateway: /* @__PURE__ */ jsx17(GatewayView, { onBack: () => setFocus("sidebar") }),
|
|
22596
|
+
wiki: /* @__PURE__ */ jsx17(WikiView, { onBack: () => setFocus("sidebar") }),
|
|
22597
|
+
settings: /* @__PURE__ */ jsx17(SettingsView, { onBack: () => setFocus("sidebar") })
|
|
21986
22598
|
};
|
|
21987
|
-
return /* @__PURE__ */
|
|
21988
|
-
/* @__PURE__ */
|
|
21989
|
-
/* @__PURE__ */
|
|
21990
|
-
|
|
22599
|
+
return /* @__PURE__ */ jsx17(ErrorBoundary2, { children: /* @__PURE__ */ jsx17(AlternateScreen, { children: /* @__PURE__ */ jsx17(DemoProvider, { demo: isDemo, children: /* @__PURE__ */ jsxs15(Box_default, { flexDirection: "column", flexGrow: 1, children: [
|
|
22600
|
+
/* @__PURE__ */ jsxs15(Box_default, { flexGrow: 1, children: [
|
|
22601
|
+
/* @__PURE__ */ jsx17(Sidebar, { active: section, onSelect: setSection, onQuit: exit, focused: focus === "sidebar" }),
|
|
22602
|
+
showHelp ? /* @__PURE__ */ jsx17(
|
|
22603
|
+
HelpOverlay,
|
|
22604
|
+
{
|
|
22605
|
+
tabName: TAB_SHORTCUTS[section].name,
|
|
22606
|
+
shortcuts: TAB_SHORTCUTS[section].shortcuts
|
|
22607
|
+
}
|
|
22608
|
+
) : showDebug ? /* @__PURE__ */ jsx17(DebugPanel, {}) : views[section]
|
|
21991
22609
|
] }),
|
|
21992
|
-
/* @__PURE__ */
|
|
22610
|
+
/* @__PURE__ */ jsx17(Footer, {})
|
|
21993
22611
|
] }) }) }) });
|
|
21994
22612
|
}
|
|
21995
|
-
var isDemo;
|
|
22613
|
+
var TAB_SHORTCUTS, isDemo;
|
|
21996
22614
|
var init_App2 = __esm({
|
|
21997
22615
|
async "src/tui/App.tsx"() {
|
|
21998
22616
|
"use strict";
|
|
@@ -22010,6 +22628,73 @@ var init_App2 = __esm({
|
|
|
22010
22628
|
await init_Team();
|
|
22011
22629
|
await init_Wiki();
|
|
22012
22630
|
await init_Settings();
|
|
22631
|
+
await init_DebugPanel();
|
|
22632
|
+
await init_HelpOverlay();
|
|
22633
|
+
TAB_SHORTCUTS = {
|
|
22634
|
+
"command-center": {
|
|
22635
|
+
name: "Command Center",
|
|
22636
|
+
shortcuts: [
|
|
22637
|
+
{ key: "\u2191\u2193", description: "Navigate projects" },
|
|
22638
|
+
{ key: "Enter", description: "Select project" },
|
|
22639
|
+
{ key: "/", description: "Enter chat mode" },
|
|
22640
|
+
{ key: "n", description: "New task" }
|
|
22641
|
+
]
|
|
22642
|
+
},
|
|
22643
|
+
sessions: {
|
|
22644
|
+
name: "Sessions",
|
|
22645
|
+
shortcuts: [
|
|
22646
|
+
{ key: "\u2191\u2193", description: "Navigate sessions" },
|
|
22647
|
+
{ key: "Enter", description: "View session output" },
|
|
22648
|
+
{ key: "k", description: "Kill session" },
|
|
22649
|
+
{ key: "r", description: "Restart agent" }
|
|
22650
|
+
]
|
|
22651
|
+
},
|
|
22652
|
+
tasks: {
|
|
22653
|
+
name: "Tasks",
|
|
22654
|
+
shortcuts: [
|
|
22655
|
+
{ key: "\u2191\u2193", description: "Navigate tasks" },
|
|
22656
|
+
{ key: "Enter", description: "View task detail" },
|
|
22657
|
+
{ key: "n", description: "Create new task" },
|
|
22658
|
+
{ key: "f", description: "Cycle status filter" },
|
|
22659
|
+
{ key: "p", description: "Filter by priority" }
|
|
22660
|
+
]
|
|
22661
|
+
},
|
|
22662
|
+
team: {
|
|
22663
|
+
name: "Team",
|
|
22664
|
+
shortcuts: [
|
|
22665
|
+
{ key: "\u2191\u2193", description: "Navigate employees" },
|
|
22666
|
+
{ key: "Enter", description: "View detail" },
|
|
22667
|
+
{ key: "a", description: "Add employee" },
|
|
22668
|
+
{ key: "s", description: "View sessions" }
|
|
22669
|
+
]
|
|
22670
|
+
},
|
|
22671
|
+
gateway: {
|
|
22672
|
+
name: "Gateway",
|
|
22673
|
+
shortcuts: [
|
|
22674
|
+
{ key: "\u2191\u2193", description: "Navigate sections" },
|
|
22675
|
+
{ key: "f", description: "Cycle platform filter" },
|
|
22676
|
+
{ key: "\u2192", description: "Next conversation" },
|
|
22677
|
+
{ key: "r", description: "Reconnect" }
|
|
22678
|
+
]
|
|
22679
|
+
},
|
|
22680
|
+
wiki: {
|
|
22681
|
+
name: "Wiki",
|
|
22682
|
+
shortcuts: [
|
|
22683
|
+
{ key: "\u2190\u2192", description: "Switch panels" },
|
|
22684
|
+
{ key: "\u2191\u2193", description: "Navigate items" },
|
|
22685
|
+
{ key: "/", description: "Search memories" },
|
|
22686
|
+
{ key: "Enter", description: "Select" }
|
|
22687
|
+
]
|
|
22688
|
+
},
|
|
22689
|
+
settings: {
|
|
22690
|
+
name: "Settings",
|
|
22691
|
+
shortcuts: [
|
|
22692
|
+
{ key: "\u2191\u2193", description: "Navigate sections" },
|
|
22693
|
+
{ key: "Enter", description: "Edit setting" },
|
|
22694
|
+
{ key: "r", description: "Refresh status" }
|
|
22695
|
+
]
|
|
22696
|
+
}
|
|
22697
|
+
};
|
|
22013
22698
|
isDemo = process.argv.includes("--demo");
|
|
22014
22699
|
process.stderr.write(`[exe-tui] Terminal: ${TERMINAL_TYPE}
|
|
22015
22700
|
`);
|
|
@@ -22050,7 +22735,7 @@ var init_App2 = __esm({
|
|
|
22050
22735
|
stdin.unref = () => stdin;
|
|
22051
22736
|
}
|
|
22052
22737
|
}
|
|
22053
|
-
render_default(/* @__PURE__ */
|
|
22738
|
+
render_default(/* @__PURE__ */ jsx17(App2, {}));
|
|
22054
22739
|
}
|
|
22055
22740
|
});
|
|
22056
22741
|
|