@askexenow/exe-os 0.9.112 → 0.9.113
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/README.md +9 -7
- package/dist/bin/agentic-ontology-backfill.js +54 -11
- package/dist/bin/agentic-reflection-backfill.js +29 -1
- package/dist/bin/agentic-semantic-label.js +29 -1
- package/dist/bin/backfill-conversations.js +53 -10
- package/dist/bin/backfill-responses.js +54 -11
- package/dist/bin/backfill-vectors.js +29 -1
- package/dist/bin/bulk-sync-postgres.js +55 -12
- package/dist/bin/cleanup-stale-review-tasks.js +75 -15
- package/dist/bin/cli.js +293 -76
- package/dist/bin/exe-agent-config.js +7 -1
- package/dist/bin/exe-agent.js +28 -2
- package/dist/bin/exe-assign.js +54 -11
- package/dist/bin/exe-boot.js +481 -147
- package/dist/bin/exe-call.js +45 -4
- package/dist/bin/exe-cloud.js +93 -15
- package/dist/bin/exe-dispatch.js +369 -24
- package/dist/bin/exe-doctor.js +53 -10
- package/dist/bin/exe-export-behaviors.js +54 -11
- package/dist/bin/exe-forget.js +54 -11
- package/dist/bin/exe-gateway.js +128 -23
- package/dist/bin/exe-heartbeat.js +75 -15
- package/dist/bin/exe-kill.js +54 -11
- package/dist/bin/exe-launch-agent.js +70 -12
- package/dist/bin/exe-new-employee.js +175 -7
- package/dist/bin/exe-pending-messages.js +75 -15
- package/dist/bin/exe-pending-notifications.js +75 -15
- package/dist/bin/exe-pending-reviews.js +75 -15
- package/dist/bin/exe-rename.js +54 -11
- package/dist/bin/exe-review.js +54 -11
- package/dist/bin/exe-search.js +54 -11
- package/dist/bin/exe-session-cleanup.js +491 -146
- package/dist/bin/exe-settings.js +10 -4
- package/dist/bin/exe-start-codex.js +524 -245
- package/dist/bin/exe-start-opencode.js +534 -165
- package/dist/bin/exe-status.js +75 -15
- package/dist/bin/exe-support.js +1 -1
- package/dist/bin/exe-team.js +54 -11
- package/dist/bin/git-sweep.js +369 -24
- package/dist/bin/graph-backfill.js +54 -11
- package/dist/bin/graph-export.js +54 -11
- package/dist/bin/install.js +62 -4
- package/dist/bin/intercom-check.js +491 -146
- package/dist/bin/pre-publish.js +13 -1
- package/dist/bin/scan-tasks.js +369 -24
- package/dist/bin/setup.js +91 -13
- package/dist/bin/shard-migrate.js +54 -11
- package/dist/bin/stack-update.js +1 -1
- package/dist/bin/update.js +3 -3
- package/dist/gateway/index.js +128 -23
- package/dist/hooks/bug-report-worker.js +128 -23
- package/dist/hooks/codex-stop-task-finalizer.js +512 -140
- package/dist/hooks/commit-complete.js +369 -24
- package/dist/hooks/error-recall.js +54 -11
- package/dist/hooks/ingest.js +4575 -252
- package/dist/hooks/instructions-loaded.js +54 -11
- package/dist/hooks/notification.js +54 -11
- package/dist/hooks/post-compact.js +75 -15
- package/dist/hooks/post-tool-combined.js +75 -15
- package/dist/hooks/pre-compact.js +449 -104
- package/dist/hooks/pre-tool-use.js +90 -15
- package/dist/hooks/prompt-submit.js +129 -24
- package/dist/hooks/session-end.js +451 -109
- package/dist/hooks/session-start.js +104 -16
- package/dist/hooks/stop.js +74 -14
- package/dist/hooks/subagent-stop.js +75 -15
- package/dist/hooks/summary-worker.js +73 -7
- package/dist/index.js +128 -23
- package/dist/lib/agent-config.js +16 -1
- package/dist/lib/cloud-sync.js +38 -1
- package/dist/lib/consolidation.js +16 -1
- package/dist/lib/database.js +16 -0
- package/dist/lib/db.js +16 -0
- package/dist/lib/device-registry.js +16 -0
- package/dist/lib/employee-templates.js +29 -3
- package/dist/lib/employees.js +16 -1
- package/dist/lib/exe-daemon.js +268 -42
- package/dist/lib/hybrid-search.js +54 -11
- package/dist/lib/license.js +3 -3
- package/dist/lib/messaging.js +21 -4
- package/dist/lib/schedules.js +29 -1
- package/dist/lib/skill-learning.js +458 -70
- package/dist/lib/status-brief.js +14 -1
- package/dist/lib/store.js +54 -11
- package/dist/lib/tasks.js +393 -91
- package/dist/lib/tmux-routing.js +316 -14
- package/dist/mcp/server.js +169 -30
- package/dist/mcp/tools/create-task.js +75 -13
- package/dist/mcp/tools/deactivate-behavior.js +33 -24
- package/dist/mcp/tools/list-tasks.js +21 -4
- package/dist/mcp/tools/send-message.js +21 -4
- package/dist/mcp/tools/update-task.js +390 -91
- package/dist/runtime/index.js +446 -101
- package/dist/tui/App.js +208 -54
- package/package.json +1 -1
package/dist/bin/cli.js
CHANGED
|
@@ -369,6 +369,7 @@ __export(agent_config_exports, {
|
|
|
369
369
|
getAgentRuntime: () => getAgentRuntime,
|
|
370
370
|
loadAgentConfig: () => loadAgentConfig,
|
|
371
371
|
saveAgentConfig: () => saveAgentConfig,
|
|
372
|
+
setAgentMcps: () => setAgentMcps,
|
|
372
373
|
setAgentRuntime: () => setAgentRuntime
|
|
373
374
|
});
|
|
374
375
|
import { readFileSync as readFileSync2, writeFileSync, existsSync as existsSync3 } from "fs";
|
|
@@ -395,7 +396,7 @@ function getAgentRuntime(agentId) {
|
|
|
395
396
|
if (orgDefault) return orgDefault;
|
|
396
397
|
return { runtime: DEFAULT_RUNTIME, model: DEFAULT_MODELS[DEFAULT_RUNTIME] };
|
|
397
398
|
}
|
|
398
|
-
function setAgentRuntime(agentId, runtime, model, reasoning_effort) {
|
|
399
|
+
function setAgentRuntime(agentId, runtime, model, reasoning_effort, mcps) {
|
|
399
400
|
const knownModels = KNOWN_RUNTIMES[runtime];
|
|
400
401
|
if (!knownModels) {
|
|
401
402
|
return {
|
|
@@ -410,12 +411,26 @@ function setAgentRuntime(agentId, runtime, model, reasoning_effort) {
|
|
|
410
411
|
};
|
|
411
412
|
}
|
|
412
413
|
const config = loadAgentConfig();
|
|
414
|
+
const existing = config[agentId];
|
|
413
415
|
const entry = { runtime, model };
|
|
414
416
|
if (reasoning_effort) entry.reasoning_effort = reasoning_effort;
|
|
417
|
+
if (mcps !== void 0) {
|
|
418
|
+
entry.mcps = mcps.includes("exe-os") ? mcps : ["exe-os", ...mcps];
|
|
419
|
+
} else if (existing?.mcps) {
|
|
420
|
+
entry.mcps = existing.mcps;
|
|
421
|
+
}
|
|
415
422
|
config[agentId] = entry;
|
|
416
423
|
saveAgentConfig(config);
|
|
417
424
|
return { ok: true };
|
|
418
425
|
}
|
|
426
|
+
function setAgentMcps(agentId, mcps) {
|
|
427
|
+
const config = loadAgentConfig();
|
|
428
|
+
const existing = config[agentId] ?? getAgentRuntime(agentId);
|
|
429
|
+
existing.mcps = mcps.includes("exe-os") ? mcps : ["exe-os", ...mcps];
|
|
430
|
+
config[agentId] = existing;
|
|
431
|
+
saveAgentConfig(config);
|
|
432
|
+
return { ok: true };
|
|
433
|
+
}
|
|
419
434
|
function clearAgentRuntime(agentId) {
|
|
420
435
|
const config = loadAgentConfig();
|
|
421
436
|
delete config[agentId];
|
|
@@ -842,6 +857,16 @@ import { chmodSync as chmodSync2, existsSync as existsSync7, mkdirSync as mkdirS
|
|
|
842
857
|
import { randomBytes } from "crypto";
|
|
843
858
|
import path6 from "path";
|
|
844
859
|
import os5 from "os";
|
|
860
|
+
function resolveDefaultAgentId() {
|
|
861
|
+
if (process.env.AGENT_ID && process.env.AGENT_ID !== "default") return process.env.AGENT_ID;
|
|
862
|
+
try {
|
|
863
|
+
const { loadEmployeesSync: loadEmployeesSync2 } = (init_employees(), __toCommonJS(employees_exports));
|
|
864
|
+
const coo = loadEmployeesSync2().find((e) => e.role === "COO");
|
|
865
|
+
if (coo) return coo.name;
|
|
866
|
+
} catch {
|
|
867
|
+
}
|
|
868
|
+
return "exe";
|
|
869
|
+
}
|
|
845
870
|
function mcpHttpPort() {
|
|
846
871
|
return process.env.EXE_MCP_PORT || DEFAULT_MCP_HTTP_PORT;
|
|
847
872
|
}
|
|
@@ -871,11 +896,14 @@ function readOrCreateDaemonToken(homeDir = os5.homedir()) {
|
|
|
871
896
|
function buildMcpHttpHeaders(homeDir = os5.homedir(), opts = {}) {
|
|
872
897
|
const agentId = opts.useShellPlaceholders ? "${AGENT_ID:-exe}" : opts.agentId ?? DEFAULT_MCP_HTTP_AGENT_ID;
|
|
873
898
|
const agentRole = opts.useShellPlaceholders ? "${AGENT_ROLE:-COO}" : opts.agentRole ?? DEFAULT_MCP_HTTP_AGENT_ROLE;
|
|
874
|
-
|
|
899
|
+
const sessionName = opts.useShellPlaceholders ? "$(tmux display-message -p '#{session_name}' 2>/dev/null || echo '')" : process.env.EXE_SESSION_NAME ?? "";
|
|
900
|
+
const headers = {
|
|
875
901
|
Authorization: `Bearer ${readOrCreateDaemonToken(homeDir)}`,
|
|
876
902
|
"X-Agent-Id": agentId,
|
|
877
903
|
"X-Agent-Role": agentRole
|
|
878
904
|
};
|
|
905
|
+
if (sessionName) headers["X-Exe-Session"] = sessionName;
|
|
906
|
+
return headers;
|
|
879
907
|
}
|
|
880
908
|
function buildClaudeHttpMcpEntry(homeDir = os5.homedir()) {
|
|
881
909
|
return {
|
|
@@ -889,12 +917,15 @@ var init_mcp_http_config = __esm({
|
|
|
889
917
|
"src/adapters/mcp-http-config.ts"() {
|
|
890
918
|
"use strict";
|
|
891
919
|
DEFAULT_MCP_HTTP_PORT = "48739";
|
|
892
|
-
DEFAULT_MCP_HTTP_AGENT_ID =
|
|
920
|
+
DEFAULT_MCP_HTTP_AGENT_ID = resolveDefaultAgentId();
|
|
893
921
|
DEFAULT_MCP_HTTP_AGENT_ROLE = "COO";
|
|
894
922
|
}
|
|
895
923
|
});
|
|
896
924
|
|
|
897
925
|
// src/adapters/runtime-hook-manifest.ts
|
|
926
|
+
function isLegacyHomeDirHookCommand(command) {
|
|
927
|
+
return LEGACY_HOME_DIR_HOOK_PATTERNS.some((pattern) => command.includes(pattern));
|
|
928
|
+
}
|
|
898
929
|
function commandHasAnyMarker(command, markers) {
|
|
899
930
|
return markers.some((marker) => command.includes(marker));
|
|
900
931
|
}
|
|
@@ -904,7 +935,7 @@ function isLegacySplitPostToolCommand(command) {
|
|
|
904
935
|
function textHasLegacySplitPostToolHook(text) {
|
|
905
936
|
return [EXE_HOOK_FILES.ingest, EXE_HOOK_FILES.errorRecall, EXE_HOOK_FILES.ingestWorker].some((file) => text.includes(file));
|
|
906
937
|
}
|
|
907
|
-
var EXE_HOOK_FILES, EXE_HOOKS, EXE_HOOK_MANIFEST, LEGACY_SPLIT_POST_TOOL_HOOK_MARKERS;
|
|
938
|
+
var EXE_HOOK_FILES, EXE_HOOKS, EXE_HOOK_MANIFEST, LEGACY_SPLIT_POST_TOOL_HOOK_MARKERS, LEGACY_HOME_DIR_HOOK_PATTERNS;
|
|
908
939
|
var init_runtime_hook_manifest = __esm({
|
|
909
940
|
"src/adapters/runtime-hook-manifest.ts"() {
|
|
910
941
|
"use strict";
|
|
@@ -1043,6 +1074,14 @@ var init_runtime_hook_manifest = __esm({
|
|
|
1043
1074
|
"dist/hooks/error-recall.js",
|
|
1044
1075
|
"dist/hooks/ingest-worker.js"
|
|
1045
1076
|
];
|
|
1077
|
+
LEGACY_HOME_DIR_HOOK_PATTERNS = [
|
|
1078
|
+
".exe-os/hooks/",
|
|
1079
|
+
// Old hook storage path (pre-npm-package era)
|
|
1080
|
+
"log-prefix.js",
|
|
1081
|
+
// Removed hook from early versions
|
|
1082
|
+
"approval-bridge.log"
|
|
1083
|
+
// Removed log redirect from early versions
|
|
1084
|
+
];
|
|
1046
1085
|
}
|
|
1047
1086
|
});
|
|
1048
1087
|
|
|
@@ -1522,6 +1561,14 @@ async function mergeHooks(packageRoot, homeDir = os6.homedir()) {
|
|
|
1522
1561
|
];
|
|
1523
1562
|
let added = 0;
|
|
1524
1563
|
let skipped = 0;
|
|
1564
|
+
for (const eventKey of Object.keys(settings.hooks)) {
|
|
1565
|
+
const groups = settings.hooks[eventKey];
|
|
1566
|
+
if (!Array.isArray(groups)) continue;
|
|
1567
|
+
settings.hooks[eventKey] = groups.map((g) => ({
|
|
1568
|
+
...g,
|
|
1569
|
+
hooks: g.hooks.filter((h) => !isLegacyHomeDirHookCommand(h.command))
|
|
1570
|
+
})).filter((g) => g.hooks.length > 0);
|
|
1571
|
+
}
|
|
1525
1572
|
const postToolGroups = settings.hooks["PostToolUse"];
|
|
1526
1573
|
if (Array.isArray(postToolGroups)) {
|
|
1527
1574
|
settings.hooks["PostToolUse"] = postToolGroups.map((g) => ({
|
|
@@ -5915,6 +5962,22 @@ async function ensureSchema() {
|
|
|
5915
5962
|
} catch (e) {
|
|
5916
5963
|
logCatchDebug("migration", e);
|
|
5917
5964
|
}
|
|
5965
|
+
try {
|
|
5966
|
+
await client.execute({
|
|
5967
|
+
sql: `ALTER TABLE memories ADD COLUMN visibility TEXT DEFAULT 'private'`,
|
|
5968
|
+
args: []
|
|
5969
|
+
});
|
|
5970
|
+
} catch (e) {
|
|
5971
|
+
logCatchDebug("migration", e);
|
|
5972
|
+
}
|
|
5973
|
+
try {
|
|
5974
|
+
await client.execute({
|
|
5975
|
+
sql: `ALTER TABLE memories ADD COLUMN strength REAL DEFAULT 1.0`,
|
|
5976
|
+
args: []
|
|
5977
|
+
});
|
|
5978
|
+
} catch (e) {
|
|
5979
|
+
logCatchDebug("migration", e);
|
|
5980
|
+
}
|
|
5918
5981
|
}
|
|
5919
5982
|
async function disposeDatabase() {
|
|
5920
5983
|
if (_walCheckpointTimer) {
|
|
@@ -6460,7 +6523,7 @@ async function assertVpsLicense(opts) {
|
|
|
6460
6523
|
}
|
|
6461
6524
|
if (!transientFailure) {
|
|
6462
6525
|
throw new Error(
|
|
6463
|
-
"License validation failed: unknown backend state. Restore network connectivity to https://askexe.com
|
|
6526
|
+
"License validation failed: unknown backend state. Restore network connectivity to https://cloud.askexe.com and retry."
|
|
6464
6527
|
);
|
|
6465
6528
|
}
|
|
6466
6529
|
const fresh = await getCachedLicense();
|
|
@@ -6497,7 +6560,7 @@ async function assertVpsLicense(opts) {
|
|
|
6497
6560
|
} catch {
|
|
6498
6561
|
}
|
|
6499
6562
|
throw new Error(
|
|
6500
|
-
`License validation unreachable for more than ${graceDays} days. Restore network connectivity to https://askexe.com
|
|
6563
|
+
`License validation unreachable for more than ${graceDays} days. Restore network connectivity to https://cloud.askexe.com and retry. This VPS image refuses to boot after the offline grace window.`
|
|
6501
6564
|
);
|
|
6502
6565
|
}
|
|
6503
6566
|
function startLicenseRevalidation(intervalMs = 36e5) {
|
|
@@ -6529,7 +6592,7 @@ var init_license = __esm({
|
|
|
6529
6592
|
LICENSE_PATH = path13.join(EXE_AI_DIR, "license.key");
|
|
6530
6593
|
CACHE_PATH = path13.join(EXE_AI_DIR, "license-cache.json");
|
|
6531
6594
|
DEVICE_ID_PATH = path13.join(EXE_AI_DIR, "device-id");
|
|
6532
|
-
API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://askexe.com
|
|
6595
|
+
API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://cloud.askexe.com";
|
|
6533
6596
|
RETRY_DELAY_MS = 500;
|
|
6534
6597
|
LICENSE_PUBLIC_KEY_PEM = `-----BEGIN PUBLIC KEY-----
|
|
6535
6598
|
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeHztAMOpR/ZMh+rWuOASjEZ54CGY
|
|
@@ -7332,6 +7395,27 @@ async function cloudSync(config) {
|
|
|
7332
7395
|
if (stmts.length > 0) await client.batch(stmts, "write");
|
|
7333
7396
|
pulled = pullResult.records.length;
|
|
7334
7397
|
} else {
|
|
7398
|
+
try {
|
|
7399
|
+
const incomingIds = pullResult.records.map((r) => sqlSafe(r.id));
|
|
7400
|
+
if (incomingIds.length > 0) {
|
|
7401
|
+
const ph = incomingIds.map(() => "?").join(",");
|
|
7402
|
+
const existing = await client.execute({
|
|
7403
|
+
sql: `SELECT id, version, timestamp FROM memories WHERE id IN (${ph})`,
|
|
7404
|
+
args: incomingIds
|
|
7405
|
+
});
|
|
7406
|
+
const localMap = new Map(existing.rows.map((r) => [String(r.id), r]));
|
|
7407
|
+
for (const rec of pullResult.records) {
|
|
7408
|
+
const local = localMap.get(String(rec.id));
|
|
7409
|
+
if (local && Number(local.version) > 0 && Number(local.version) !== Number(rec.version ?? 0)) {
|
|
7410
|
+
process.stderr.write(
|
|
7411
|
+
`[cloud-sync] CONFLICT: memory ${String(rec.id).slice(0, 8)} \u2014 local v${local.version} vs remote v${rec.version ?? 0}. Remote wins (LWW).
|
|
7412
|
+
`
|
|
7413
|
+
);
|
|
7414
|
+
}
|
|
7415
|
+
}
|
|
7416
|
+
}
|
|
7417
|
+
} catch {
|
|
7418
|
+
}
|
|
7335
7419
|
const stmts = pullResult.records.map((rec) => ({
|
|
7336
7420
|
sql: `INSERT OR REPLACE INTO memories
|
|
7337
7421
|
(id, agent_id, agent_role, session_id, timestamp,
|
|
@@ -9089,11 +9173,17 @@ var init_platform_procedures = __esm({
|
|
|
9089
9173
|
content: "Founder -> coordinator (the executive agent, internally routed as 'COO') -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the coordinator does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
|
|
9090
9174
|
},
|
|
9091
9175
|
{
|
|
9092
|
-
title: "
|
|
9176
|
+
title: "Orchestration phase guidance \u2014 recommend, never trap",
|
|
9093
9177
|
domain: "workflow",
|
|
9094
9178
|
priority: "p1",
|
|
9095
9179
|
content: "New customers start best in Phase 1: founder \u2194 coordinator/Chief of Staff, building company context. Suggest Phase 2 executives when domain work repeats; suggest Phase 3 parallel execution only when review/permission gates are ready. This is guidance, not a blocker: users may jump phases anytime. Never overwrite their phase, role titles, identities, or custom org design."
|
|
9096
9180
|
},
|
|
9181
|
+
{
|
|
9182
|
+
title: "Routing slot vs display title \u2014 internal 'coo' is plumbing, not your name",
|
|
9183
|
+
domain: "identity",
|
|
9184
|
+
priority: "p0",
|
|
9185
|
+
content: "These procedures reference 'COO' as a shorthand for the coordinator role. This is an INTERNAL routing slot used by exe-os code (chain-of-command checks, dispatch logic, session detection). It is NOT your display title. Your actual title comes from your identity file's `title:` field \u2014 that is what you use externally: introductions, sign-offs, team comms, and any user-facing text. If your identity says `title: AI Chief of Staff`, you are the AI Chief of Staff. The routing slot stays `role: coo` for code compatibility \u2014 never rename it, but also never introduce yourself as 'COO' unless your identity file explicitly says so. The founder chose your title; respect it."
|
|
9186
|
+
},
|
|
9097
9187
|
{
|
|
9098
9188
|
title: "Single dispatch path \u2014 create_task only",
|
|
9099
9189
|
domain: "workflow",
|
|
@@ -9127,6 +9217,12 @@ var init_platform_procedures = __esm({
|
|
|
9127
9217
|
priority: "p0",
|
|
9128
9218
|
content: "NEVER: (1) Access the database directly \u2014 it's SQLCipher encrypted, always fails. Use MCP tools only. (2) Manually spawn tmux sessions \u2014 create_task handles it. (3) Run git checkout main \u2014 agents work in worktrees. (4) Modify another agent's in-progress task. (5) Push to remote \u2014 the COO reviews and pushes. (6) Skip update_task(done) \u2014 it's the ONLY way your work gets reviewed. (7) Run git init."
|
|
9129
9219
|
},
|
|
9220
|
+
{
|
|
9221
|
+
title: "Destructive operations \u2014 mandatory reviewer gate",
|
|
9222
|
+
domain: "security",
|
|
9223
|
+
priority: "p0",
|
|
9224
|
+
content: "Before ANY destructive operation (delete, remove, overwrite, drop, reset, force-push, truncate), you MUST: (1) Have your full task spec accessible \u2014 if you cannot read it, STOP and report to your reviewer. Never improvise destructive actions. (2) Confirm with your reviewer (assigned_by or COO) before executing. (3) If the task spec explicitly authorizes the operation, proceed \u2014 but log it. Violation = immediate task failure. This applies to ALL agents regardless of role."
|
|
9225
|
+
},
|
|
9130
9226
|
{
|
|
9131
9227
|
title: "Customer patch triage \u2014 upstream bug vs customization",
|
|
9132
9228
|
domain: "support",
|
|
@@ -9412,10 +9508,24 @@ function stableId(memoryId, type, content) {
|
|
|
9412
9508
|
return createHash3("sha256").update(`${memoryId}:${type}:${content}`).digest("hex").slice(0, 32);
|
|
9413
9509
|
}
|
|
9414
9510
|
function cleanText(text) {
|
|
9415
|
-
|
|
9511
|
+
let cleaned = text.replace(
|
|
9512
|
+
/```(\w*)\n(.*?)(?:\n[\s\S]*?)```/g,
|
|
9513
|
+
(_m, lang, firstLine) => `[code${lang ? `:${lang}` : ""}] ${firstLine.trim()}`
|
|
9514
|
+
);
|
|
9515
|
+
cleaned = cleaned.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
9516
|
+
return cleaned;
|
|
9416
9517
|
}
|
|
9417
|
-
function
|
|
9418
|
-
|
|
9518
|
+
function splitSegments(text) {
|
|
9519
|
+
const cleaned = cleanText(text);
|
|
9520
|
+
const segments = cleaned.split(/(?<=[.!?:;])\s+|\n{2,}|(?<=\))\s+(?=[A-Z])|\s*[|│]\s*/).map((s) => s.trim()).filter((s) => s.length >= MIN_SEGMENT_CHARS && s.length <= MAX_SEGMENT_CHARS);
|
|
9521
|
+
if (segments.length === 0 && cleaned.length >= MIN_SEGMENT_CHARS) {
|
|
9522
|
+
const lines = cleaned.split(/\n+/).map((l) => l.trim()).filter((l) => l.length >= MIN_SEGMENT_CHARS && l.length <= MAX_SEGMENT_CHARS);
|
|
9523
|
+
if (lines.length > 0) return lines;
|
|
9524
|
+
if (cleaned.length >= MIN_SEGMENT_CHARS) {
|
|
9525
|
+
return [cleaned.slice(0, MAX_SEGMENT_CHARS)];
|
|
9526
|
+
}
|
|
9527
|
+
}
|
|
9528
|
+
return segments;
|
|
9419
9529
|
}
|
|
9420
9530
|
function inferCardType(sentence, toolName) {
|
|
9421
9531
|
const lower = sentence.toLowerCase();
|
|
@@ -9447,12 +9557,12 @@ function predicateFor(type) {
|
|
|
9447
9557
|
}
|
|
9448
9558
|
}
|
|
9449
9559
|
function extractMemoryCards(row) {
|
|
9450
|
-
const
|
|
9560
|
+
const segments = splitSegments(row.raw_text);
|
|
9451
9561
|
const cards = [];
|
|
9452
|
-
for (const sentence of
|
|
9562
|
+
for (const sentence of segments) {
|
|
9453
9563
|
const type = inferCardType(sentence, row.tool_name);
|
|
9454
9564
|
const subject = extractSubject(sentence, row.agent_id);
|
|
9455
|
-
const content = sentence.length >
|
|
9565
|
+
const content = sentence.length > MAX_SEGMENT_CHARS ? `${sentence.slice(0, MAX_SEGMENT_CHARS - 1)}\u2026` : sentence;
|
|
9456
9566
|
cards.push({
|
|
9457
9567
|
id: stableId(row.id, type, content),
|
|
9458
9568
|
memory_id: row.id,
|
|
@@ -9548,13 +9658,14 @@ Source memory: ${String(row.source_ref ?? row.memory_id)}`,
|
|
|
9548
9658
|
last_accessed: String(row.timestamp)
|
|
9549
9659
|
}));
|
|
9550
9660
|
}
|
|
9551
|
-
var MAX_CARDS_PER_MEMORY,
|
|
9661
|
+
var MAX_CARDS_PER_MEMORY, MAX_SEGMENT_CHARS, MIN_SEGMENT_CHARS;
|
|
9552
9662
|
var init_memory_cards = __esm({
|
|
9553
9663
|
"src/lib/memory-cards.ts"() {
|
|
9554
9664
|
"use strict";
|
|
9555
9665
|
init_database();
|
|
9556
|
-
MAX_CARDS_PER_MEMORY =
|
|
9557
|
-
|
|
9666
|
+
MAX_CARDS_PER_MEMORY = 8;
|
|
9667
|
+
MAX_SEGMENT_CHARS = 500;
|
|
9668
|
+
MIN_SEGMENT_CHARS = 20;
|
|
9558
9669
|
}
|
|
9559
9670
|
});
|
|
9560
9671
|
|
|
@@ -10645,7 +10756,7 @@ async function setupMode() {
|
|
|
10645
10756
|
rl.close();
|
|
10646
10757
|
return;
|
|
10647
10758
|
}
|
|
10648
|
-
const endpoint = await ask(rl, " Endpoint [https://askexe.com
|
|
10759
|
+
const endpoint = await ask(rl, " Endpoint [https://cloud.askexe.com]: ") || "https://cloud.askexe.com";
|
|
10649
10760
|
console.log(" Validating...");
|
|
10650
10761
|
try {
|
|
10651
10762
|
assertSecureEndpoint(endpoint);
|
|
@@ -10711,6 +10822,14 @@ async function setupMode() {
|
|
|
10711
10822
|
}
|
|
10712
10823
|
console.log("");
|
|
10713
10824
|
}
|
|
10825
|
+
try {
|
|
10826
|
+
const keyInfo = await getKeyStorageInfo();
|
|
10827
|
+
if (keyInfo.kind !== "missing") {
|
|
10828
|
+
console.log(` \u2713 Encryption key: ${keyInfo.note}`);
|
|
10829
|
+
}
|
|
10830
|
+
} catch {
|
|
10831
|
+
}
|
|
10832
|
+
console.log("");
|
|
10714
10833
|
console.log(BAR);
|
|
10715
10834
|
console.log(latestConfig.cloud?.apiKey ? " Setup complete. Cloud sync is connected." : " Setup complete. Cloud sync is not configured yet.");
|
|
10716
10835
|
console.log(BAR);
|
|
@@ -10802,7 +10921,13 @@ async function statusMode() {
|
|
|
10802
10921
|
console.log("");
|
|
10803
10922
|
if (key) {
|
|
10804
10923
|
const fingerprint = key.toString("hex").slice(0, 8);
|
|
10805
|
-
|
|
10924
|
+
let storageNote = "";
|
|
10925
|
+
try {
|
|
10926
|
+
const keyInfo = await getKeyStorageInfo();
|
|
10927
|
+
if (keyInfo.kind !== "missing") storageNote = ` [${keyInfo.note}]`;
|
|
10928
|
+
} catch {
|
|
10929
|
+
}
|
|
10930
|
+
console.log(` Encryption key: \u2713 present (${fingerprint}...)${storageNote}`);
|
|
10806
10931
|
} else {
|
|
10807
10932
|
console.log(" Encryption key: \u2717 not found \u2014 run /exe-setup");
|
|
10808
10933
|
}
|
|
@@ -12291,17 +12416,14 @@ var backfill_metadata_exports = {};
|
|
|
12291
12416
|
__export(backfill_metadata_exports, {
|
|
12292
12417
|
backfillMetadata: () => backfillMetadata
|
|
12293
12418
|
});
|
|
12294
|
-
function roleAgentMarkers(role
|
|
12419
|
+
function roleAgentMarkers(role) {
|
|
12295
12420
|
try {
|
|
12296
12421
|
const employees = loadEmployeesSync();
|
|
12297
|
-
const
|
|
12298
|
-
|
|
12299
|
-
if (configuredName) {
|
|
12300
|
-
return [configuredName];
|
|
12301
|
-
}
|
|
12422
|
+
const names = getEmployeeNamesByRole(employees, role).map((n) => n.toLowerCase().trim()).filter(Boolean);
|
|
12423
|
+
if (names.length > 0) return names;
|
|
12302
12424
|
} catch {
|
|
12303
12425
|
}
|
|
12304
|
-
return [
|
|
12426
|
+
return [];
|
|
12305
12427
|
}
|
|
12306
12428
|
function mentionsAgentMarker(text, markers) {
|
|
12307
12429
|
return markers.some(
|
|
@@ -12860,8 +12982,8 @@ var init_backfill_metadata = __esm({
|
|
|
12860
12982
|
VALID_LANGUAGE_TYPES = /* @__PURE__ */ new Set(["code", "prose", "mixed", "json", "sql"]);
|
|
12861
12983
|
MAX_TEXT_LENGTH = 2e3;
|
|
12862
12984
|
BATCH_SLEEP_MS = 1e3;
|
|
12863
|
-
MARKETING_AGENT_MARKERS = roleAgentMarkers("CMO"
|
|
12864
|
-
RESEARCH_AGENT_MARKERS = roleAgentMarkers("AI Product Lead"
|
|
12985
|
+
MARKETING_AGENT_MARKERS = roleAgentMarkers("CMO");
|
|
12986
|
+
RESEARCH_AGENT_MARKERS = roleAgentMarkers("AI Product Lead");
|
|
12865
12987
|
if (isMainModule(import.meta.url)) {
|
|
12866
12988
|
const options = parseArgs2(process.argv.slice(2));
|
|
12867
12989
|
backfillMetadata(options).then((result) => {
|
|
@@ -14341,6 +14463,19 @@ async function resolveTask(client, identifier, scopeSession) {
|
|
|
14341
14463
|
args: [identifier, ...scope.args]
|
|
14342
14464
|
});
|
|
14343
14465
|
if (result.rows.length === 1) return result.rows[0];
|
|
14466
|
+
if (/^[a-f0-9]{7,12}$/i.test(identifier)) {
|
|
14467
|
+
result = await client.execute({
|
|
14468
|
+
sql: `SELECT * FROM tasks WHERE id LIKE ?`,
|
|
14469
|
+
args: [`${identifier}%`]
|
|
14470
|
+
});
|
|
14471
|
+
if (result.rows.length === 1) return result.rows[0];
|
|
14472
|
+
if (result.rows.length > 1) {
|
|
14473
|
+
const matches = result.rows.map((r) => `${String(r.id)} "${String(r.title)}" (${String(r.status)})`).join(", ");
|
|
14474
|
+
throw new Error(
|
|
14475
|
+
`Multiple tasks match short-ID "${identifier}": ${matches}. Use a longer prefix to disambiguate.`
|
|
14476
|
+
);
|
|
14477
|
+
}
|
|
14478
|
+
}
|
|
14344
14479
|
result = await client.execute({
|
|
14345
14480
|
sql: `SELECT * FROM tasks WHERE task_file LIKE ?${scope.sql}`,
|
|
14346
14481
|
args: [`%${identifier}%`, ...scope.args]
|
|
@@ -15195,12 +15330,13 @@ async function cascadeUnblock(taskId, baseDir, now2) {
|
|
|
15195
15330
|
WHERE blocked_by = ? AND status = 'blocked'`,
|
|
15196
15331
|
args: [now2, taskId]
|
|
15197
15332
|
});
|
|
15198
|
-
if (
|
|
15199
|
-
|
|
15200
|
-
|
|
15201
|
-
|
|
15202
|
-
|
|
15203
|
-
|
|
15333
|
+
if (unblocked.rowsAffected === 0) return;
|
|
15334
|
+
const ubScope = sessionScopeFilter();
|
|
15335
|
+
const unblockedRows = await client.execute({
|
|
15336
|
+
sql: `SELECT id, title, assigned_to, priority, task_file FROM tasks WHERE blocked_by IS NULL AND updated_at = ?${ubScope.sql}`,
|
|
15337
|
+
args: [now2, ...ubScope.args]
|
|
15338
|
+
});
|
|
15339
|
+
if (baseDir) {
|
|
15204
15340
|
for (const ur of unblockedRows.rows) {
|
|
15205
15341
|
try {
|
|
15206
15342
|
const ubFile = path32.join(baseDir, String(ur.task_file));
|
|
@@ -15212,6 +15348,19 @@ async function cascadeUnblock(taskId, baseDir, now2) {
|
|
|
15212
15348
|
}
|
|
15213
15349
|
}
|
|
15214
15350
|
}
|
|
15351
|
+
if (unblockedRows.rows.length > 0 && !process.env.VITEST) {
|
|
15352
|
+
try {
|
|
15353
|
+
const { queueIntercom: queueIntercom2 } = await Promise.resolve().then(() => (init_intercom_queue(), intercom_queue_exports));
|
|
15354
|
+
const dispatched = /* @__PURE__ */ new Set();
|
|
15355
|
+
for (const ur of unblockedRows.rows) {
|
|
15356
|
+
const assignee = String(ur.assigned_to);
|
|
15357
|
+
if (dispatched.has(assignee)) continue;
|
|
15358
|
+
dispatched.add(assignee);
|
|
15359
|
+
queueIntercom2(`${assignee}`, `unblocked: "${String(ur.title)}" is now ready`);
|
|
15360
|
+
}
|
|
15361
|
+
} catch {
|
|
15362
|
+
}
|
|
15363
|
+
}
|
|
15215
15364
|
}
|
|
15216
15365
|
async function findNextTask(assignedTo) {
|
|
15217
15366
|
const client = getClient();
|
|
@@ -15421,6 +15570,15 @@ var init_embedder = __esm({
|
|
|
15421
15570
|
// src/lib/behaviors.ts
|
|
15422
15571
|
import crypto10 from "crypto";
|
|
15423
15572
|
async function storeBehavior(opts) {
|
|
15573
|
+
try {
|
|
15574
|
+
const { loadEmployeesSync: loadEmployeesSync2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
15575
|
+
const roster = loadEmployeesSync2();
|
|
15576
|
+
if (roster.length > 0 && !roster.some((e) => e.name === opts.agentId)) {
|
|
15577
|
+
throw new Error(`Agent "${opts.agentId}" not found in roster. Cannot store behavior for unregistered agent.`);
|
|
15578
|
+
}
|
|
15579
|
+
} catch (e) {
|
|
15580
|
+
if (e instanceof Error && e.message.includes("not found in roster")) throw e;
|
|
15581
|
+
}
|
|
15424
15582
|
const client = getClient();
|
|
15425
15583
|
const id = crypto10.randomUUID();
|
|
15426
15584
|
const now2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -15874,6 +16032,12 @@ async function updateTask(input) {
|
|
|
15874
16032
|
}
|
|
15875
16033
|
}
|
|
15876
16034
|
}
|
|
16035
|
+
if (input.status === "cancelled") {
|
|
16036
|
+
try {
|
|
16037
|
+
await cascadeUnblock(taskId, input.baseDir, now2);
|
|
16038
|
+
} catch {
|
|
16039
|
+
}
|
|
16040
|
+
}
|
|
15877
16041
|
if ((input.status === "done" || input.status === "closed") && !isCoordinatorName(String(row.assigned_to)) && !process.env.VITEST) {
|
|
15878
16042
|
Promise.resolve().then(() => (init_skill_learning(), skill_learning_exports)).then(
|
|
15879
16043
|
({ captureAndLearn: captureAndLearn2 }) => captureAndLearn2({
|
|
@@ -16405,11 +16569,12 @@ function getDispatchedBy(sessionKey) {
|
|
|
16405
16569
|
}
|
|
16406
16570
|
}
|
|
16407
16571
|
function resolveExeSession() {
|
|
16572
|
+
if (process.env.EXE_SESSION_NAME) {
|
|
16573
|
+
const fromEnv = extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
|
|
16574
|
+
if (fromEnv) return fromEnv;
|
|
16575
|
+
}
|
|
16408
16576
|
const mySession = getMySession();
|
|
16409
16577
|
if (!mySession) {
|
|
16410
|
-
if (process.env.EXE_SESSION_NAME) {
|
|
16411
|
-
return extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
|
|
16412
|
-
}
|
|
16413
16578
|
return null;
|
|
16414
16579
|
}
|
|
16415
16580
|
const fromSessionName = extractRootExe(mySession);
|
|
@@ -16424,6 +16589,10 @@ function resolveExeSession() {
|
|
|
16424
16589
|
`[tmux-routing] WARN: cache says "${fromCache}" but session name says "${fromSessionName}". Trusting session name.
|
|
16425
16590
|
`
|
|
16426
16591
|
);
|
|
16592
|
+
try {
|
|
16593
|
+
registerParentExe(key, fromSessionName);
|
|
16594
|
+
} catch {
|
|
16595
|
+
}
|
|
16427
16596
|
candidate = fromSessionName;
|
|
16428
16597
|
} else {
|
|
16429
16598
|
candidate = fromCache;
|
|
@@ -17582,9 +17751,23 @@ __export(employee_templates_exports, {
|
|
|
17582
17751
|
function getSessionPrompt(storedPrompt) {
|
|
17583
17752
|
const markerIndex = storedPrompt.indexOf(PROCEDURES_MARKER);
|
|
17584
17753
|
const withoutProcedures = markerIndex >= 0 ? storedPrompt.slice(0, markerIndex).trimEnd() : storedPrompt;
|
|
17754
|
+
let titlePrefix = "";
|
|
17755
|
+
const frontmatterMatch = withoutProcedures.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
17756
|
+
if (frontmatterMatch) {
|
|
17757
|
+
const titleMatch = frontmatterMatch[1].match(/^title:\s*(.+)$/m);
|
|
17758
|
+
const roleMatch = frontmatterMatch[1].match(/^role:\s*(.+)$/m);
|
|
17759
|
+
if (titleMatch) {
|
|
17760
|
+
const title = titleMatch[1].trim();
|
|
17761
|
+
const role = roleMatch ? roleMatch[1].trim() : "";
|
|
17762
|
+
if (title && role && title.toLowerCase() !== role.toLowerCase()) {
|
|
17763
|
+
titlePrefix = `## Your Identity
|
|
17764
|
+
You are **${title}** (specialist). `;
|
|
17765
|
+
}
|
|
17766
|
+
}
|
|
17767
|
+
}
|
|
17585
17768
|
const rolePrompt = withoutProcedures.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, "").replace(/<!--[\s\S]*?-->/g, "").trimStart();
|
|
17586
17769
|
const globalBlock = getGlobalProceduresBlock();
|
|
17587
|
-
return `${globalBlock}${rolePrompt}
|
|
17770
|
+
return `${globalBlock}${titlePrefix}${rolePrompt}
|
|
17588
17771
|
${BASE_OPERATING_PROCEDURES}`;
|
|
17589
17772
|
}
|
|
17590
17773
|
function buildCustomEmployeePrompt(name, role) {
|
|
@@ -17603,7 +17786,7 @@ function personalizePrompt(prompt, templateName, actualName) {
|
|
|
17603
17786
|
return prompt.replace(new RegExp(`\\bYou are ${escaped}\\b`, "g"), `You are ${actualName}`);
|
|
17604
17787
|
}
|
|
17605
17788
|
function renderClientCOOTemplate(vars) {
|
|
17606
|
-
const resolved = { ...vars, title: vars.title || "Chief
|
|
17789
|
+
const resolved = { ...vars, title: vars.title || "Chief of Staff" };
|
|
17607
17790
|
for (const key of CLIENT_COO_PLACEHOLDERS) {
|
|
17608
17791
|
const value = resolved[key];
|
|
17609
17792
|
if (typeof value !== "string" || value.length === 0) {
|
|
@@ -20327,7 +20510,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
20327
20510
|
log("");
|
|
20328
20511
|
const apiKey = await ask3(rl, "Cloud API key (starts with exe_sk_): ");
|
|
20329
20512
|
if (apiKey && apiKey.startsWith("exe_sk_")) {
|
|
20330
|
-
const cloudEndpoint = "https://askexe.com
|
|
20513
|
+
const cloudEndpoint = "https://cloud.askexe.com";
|
|
20331
20514
|
const cloudCfg = { apiKey, endpoint: cloudEndpoint };
|
|
20332
20515
|
const earlyConfig = await loadConfig();
|
|
20333
20516
|
earlyConfig.cloud = cloudCfg;
|
|
@@ -20427,7 +20610,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
20427
20610
|
log("");
|
|
20428
20611
|
const existingKey = await ask3(rl, "Paste your Exe OS license key, or press Enter to start as a free user: ");
|
|
20429
20612
|
if (existingKey && existingKey.startsWith("exe_sk_")) {
|
|
20430
|
-
const cloudEndpoint = "https://askexe.com
|
|
20613
|
+
const cloudEndpoint = "https://cloud.askexe.com";
|
|
20431
20614
|
try {
|
|
20432
20615
|
const { loadDeviceId: loadDeviceId2 } = await Promise.resolve().then(() => (init_license(), license_exports));
|
|
20433
20616
|
const deviceId = loadDeviceId2();
|
|
@@ -20452,7 +20635,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
20452
20635
|
}
|
|
20453
20636
|
} catch {
|
|
20454
20637
|
log("Could not validate key \u2014 saving it and proceeding.");
|
|
20455
|
-
cloudConfig = { apiKey: existingKey, endpoint: "https://askexe.com
|
|
20638
|
+
cloudConfig = { apiKey: existingKey, endpoint: "https://cloud.askexe.com" };
|
|
20456
20639
|
const { saveLicense: saveLicense3, mirrorLicenseKey: mirrorLicenseKey3 } = await Promise.resolve().then(() => (init_license(), license_exports));
|
|
20457
20640
|
saveLicense3(existingKey);
|
|
20458
20641
|
mirrorLicenseKey3(existingKey);
|
|
@@ -20464,7 +20647,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
20464
20647
|
const deviceId = loadDeviceId2();
|
|
20465
20648
|
let res;
|
|
20466
20649
|
try {
|
|
20467
|
-
res = await fetch("https://askexe.com/
|
|
20650
|
+
res = await fetch("https://cloud.askexe.com/auth/auto-provision", {
|
|
20468
20651
|
method: "POST",
|
|
20469
20652
|
headers: { "Content-Type": "application/json" },
|
|
20470
20653
|
body: JSON.stringify({ deviceId }),
|
|
@@ -20472,7 +20655,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
20472
20655
|
});
|
|
20473
20656
|
} catch {
|
|
20474
20657
|
await new Promise((r) => setTimeout(r, 500));
|
|
20475
|
-
res = await fetch("https://askexe.com/
|
|
20658
|
+
res = await fetch("https://cloud.askexe.com/auth/auto-provision", {
|
|
20476
20659
|
method: "POST",
|
|
20477
20660
|
headers: { "Content-Type": "application/json" },
|
|
20478
20661
|
body: JSON.stringify({ deviceId }),
|
|
@@ -20482,7 +20665,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
20482
20665
|
if (res.ok) {
|
|
20483
20666
|
const data = await res.json();
|
|
20484
20667
|
if (data.apiKey) {
|
|
20485
|
-
cloudConfig = { apiKey: data.apiKey, endpoint: "https://askexe.com
|
|
20668
|
+
cloudConfig = { apiKey: data.apiKey, endpoint: "https://cloud.askexe.com" };
|
|
20486
20669
|
const { saveLicense: saveLicense3, mirrorLicenseKey: mirrorLicenseKey3 } = await Promise.resolve().then(() => (init_license(), license_exports));
|
|
20487
20670
|
saveLicense3(data.apiKey);
|
|
20488
20671
|
mirrorLicenseKey3(data.apiKey);
|
|
@@ -33142,7 +33325,7 @@ function useOrchestrator(enabled = true) {
|
|
|
33142
33325
|
const [pendingReviews, setPendingReviews] = useState8(0);
|
|
33143
33326
|
const [isLoading, setIsLoading] = useState8(true);
|
|
33144
33327
|
const orchestratorRef = useRef5(null);
|
|
33145
|
-
const exeSessionRef = useRef5("
|
|
33328
|
+
const exeSessionRef = useRef5("");
|
|
33146
33329
|
const coordinatorNameRef = useRef5(DEFAULT_COORDINATOR_TEMPLATE_NAME);
|
|
33147
33330
|
useEffect10(() => {
|
|
33148
33331
|
if (!enabled) return;
|
|
@@ -33739,6 +33922,8 @@ var tui_data_exports = {};
|
|
|
33739
33922
|
__export(tui_data_exports, {
|
|
33740
33923
|
loadMemoryDashboard: () => loadMemoryDashboard,
|
|
33741
33924
|
loadTaskList: () => loadTaskList,
|
|
33925
|
+
loadTeamBadgeCounts: () => loadTeamBadgeCounts,
|
|
33926
|
+
loadTeamDetailMetrics: () => loadTeamDetailMetrics,
|
|
33742
33927
|
loadTeamMetrics: () => loadTeamMetrics,
|
|
33743
33928
|
searchWikiMemoryRows: () => searchWikiMemoryRows
|
|
33744
33929
|
});
|
|
@@ -33767,16 +33952,20 @@ async function loadMemoryDashboard(limit) {
|
|
|
33767
33952
|
}))
|
|
33768
33953
|
};
|
|
33769
33954
|
}
|
|
33770
|
-
async function
|
|
33955
|
+
async function loadTeamBadgeCounts() {
|
|
33771
33956
|
const client = getClient();
|
|
33772
33957
|
const memoryCounts = /* @__PURE__ */ new Map();
|
|
33773
|
-
const projectsByEmployee = /* @__PURE__ */ new Map();
|
|
33774
|
-
const currentTaskByEmployee = /* @__PURE__ */ new Map();
|
|
33775
|
-
const scope = sessionScopeFilter();
|
|
33776
33958
|
const memResult = await client.execute("SELECT agent_id, COUNT(*) as cnt FROM memories GROUP BY agent_id");
|
|
33777
33959
|
for (const row of memResult.rows) {
|
|
33778
33960
|
memoryCounts.set(String(row.agent_id), Number(row.cnt));
|
|
33779
33961
|
}
|
|
33962
|
+
return memoryCounts;
|
|
33963
|
+
}
|
|
33964
|
+
async function loadTeamDetailMetrics(employeeNames) {
|
|
33965
|
+
const client = getClient();
|
|
33966
|
+
const projectsByEmployee = /* @__PURE__ */ new Map();
|
|
33967
|
+
const currentTaskByEmployee = /* @__PURE__ */ new Map();
|
|
33968
|
+
const scope = sessionScopeFilter();
|
|
33780
33969
|
for (const employeeName of employeeNames) {
|
|
33781
33970
|
const [projectResult, taskResult] = await Promise.all([
|
|
33782
33971
|
client.execute({
|
|
@@ -33809,6 +33998,13 @@ async function loadTeamMetrics(employeeNames) {
|
|
|
33809
33998
|
currentTaskByEmployee.set(employeeName, String(taskResult.rows[0].title));
|
|
33810
33999
|
}
|
|
33811
34000
|
}
|
|
34001
|
+
return { projectsByEmployee, currentTaskByEmployee };
|
|
34002
|
+
}
|
|
34003
|
+
async function loadTeamMetrics(employeeNames) {
|
|
34004
|
+
const [memoryCounts, { projectsByEmployee, currentTaskByEmployee }] = await Promise.all([
|
|
34005
|
+
loadTeamBadgeCounts(),
|
|
34006
|
+
loadTeamDetailMetrics(employeeNames)
|
|
34007
|
+
]);
|
|
33812
34008
|
return { memoryCounts, projectsByEmployee, currentTaskByEmployee };
|
|
33813
34009
|
}
|
|
33814
34010
|
async function loadTaskList() {
|
|
@@ -35064,6 +35260,8 @@ function TeamView({ onBack, onViewSessions }) {
|
|
|
35064
35260
|
const [members, setMembers] = useState12([]);
|
|
35065
35261
|
const [externals, setExternals] = useState12([]);
|
|
35066
35262
|
const [loading, setLoading] = useState12(!demo);
|
|
35263
|
+
const [badgeInFlight, setBadgeInFlight] = useState12(!demo);
|
|
35264
|
+
const [detailInFlight, setDetailInFlight] = useState12(!demo);
|
|
35067
35265
|
const [dbError, setDbError] = useState12(null);
|
|
35068
35266
|
const [selectedIdx, setSelectedIdx] = useState12(0);
|
|
35069
35267
|
const [showDetail, setShowDetail] = useState12(false);
|
|
@@ -35076,6 +35274,8 @@ function TeamView({ onBack, onViewSessions }) {
|
|
|
35076
35274
|
setMembers(DEMO_EMPLOYEES.map((e) => ({ ...e })));
|
|
35077
35275
|
setExternals(DEMO_EXTERNAL_AGENTS);
|
|
35078
35276
|
setLoading(false);
|
|
35277
|
+
setBadgeInFlight(false);
|
|
35278
|
+
setDetailInFlight(false);
|
|
35079
35279
|
return;
|
|
35080
35280
|
}
|
|
35081
35281
|
loadTeam();
|
|
@@ -35114,33 +35314,48 @@ function TeamView({ onBack, onViewSessions }) {
|
|
|
35114
35314
|
let projectsByEmployee = /* @__PURE__ */ new Map();
|
|
35115
35315
|
let currentTaskByEmployee = /* @__PURE__ */ new Map();
|
|
35116
35316
|
try {
|
|
35117
|
-
const {
|
|
35118
|
-
|
|
35119
|
-
|
|
35120
|
-
|
|
35121
|
-
|
|
35122
|
-
|
|
35123
|
-
|
|
35124
|
-
|
|
35125
|
-
|
|
35317
|
+
const { loadTeamBadgeCounts: loadTeamBadgeCounts2, loadTeamDetailMetrics: loadTeamDetailMetrics2 } = await Promise.resolve().then(() => (init_tui_data(), tui_data_exports));
|
|
35318
|
+
setBadgeInFlight(true);
|
|
35319
|
+
const badgeCountsPromise = loadTeamBadgeCounts2();
|
|
35320
|
+
const detailsPromise = loadTeamDetailMetrics2(roster.map((emp) => emp.name));
|
|
35321
|
+
memoryCounts = await badgeCountsPromise;
|
|
35322
|
+
setBadgeInFlight(false);
|
|
35323
|
+
const initialMembers = roster.map((emp) => {
|
|
35324
|
+
const agentSt = getAgentStatus(emp.name);
|
|
35325
|
+
return {
|
|
35326
|
+
name: emp.name,
|
|
35327
|
+
role: emp.role,
|
|
35328
|
+
status: agentSt.label,
|
|
35329
|
+
activity: agentSt.label === "active" ? "Processing..." : "",
|
|
35330
|
+
memoryCount: memoryCounts.get(emp.name) ?? 0,
|
|
35331
|
+
projects: void 0,
|
|
35332
|
+
currentTask: void 0,
|
|
35333
|
+
sessionName: agentSt.session
|
|
35334
|
+
};
|
|
35335
|
+
});
|
|
35336
|
+
setMembers(initialMembers);
|
|
35337
|
+
setDetailInFlight(true);
|
|
35338
|
+
const teamMetrics = await detailsPromise;
|
|
35339
|
+
projectsByEmployee = teamMetrics.projectsByEmployee;
|
|
35126
35340
|
currentTaskByEmployee = teamMetrics.currentTaskByEmployee;
|
|
35341
|
+
setDetailInFlight(false);
|
|
35342
|
+
const finalMembers = roster.map((emp) => {
|
|
35343
|
+
const agentSt = getAgentStatus(emp.name);
|
|
35344
|
+
return {
|
|
35345
|
+
name: emp.name,
|
|
35346
|
+
role: emp.role,
|
|
35347
|
+
status: agentSt.label,
|
|
35348
|
+
activity: agentSt.label === "active" ? "Processing..." : "",
|
|
35349
|
+
memoryCount: memoryCounts.get(emp.name) ?? 0,
|
|
35350
|
+
projects: projectsByEmployee.get(emp.name),
|
|
35351
|
+
currentTask: currentTaskByEmployee.get(emp.name),
|
|
35352
|
+
sessionName: agentSt.session
|
|
35353
|
+
};
|
|
35354
|
+
});
|
|
35355
|
+
setMembers(finalMembers);
|
|
35356
|
+
setDbError(null);
|
|
35127
35357
|
} catch {
|
|
35128
35358
|
}
|
|
35129
|
-
const teamData = roster.map((emp) => {
|
|
35130
|
-
const agentSt = getAgentStatus(emp.name);
|
|
35131
|
-
return {
|
|
35132
|
-
name: emp.name,
|
|
35133
|
-
role: emp.role,
|
|
35134
|
-
status: agentSt.label,
|
|
35135
|
-
activity: agentSt.label === "active" ? "Processing..." : "",
|
|
35136
|
-
memoryCount: memoryCounts.get(emp.name) ?? 0,
|
|
35137
|
-
projects: projectsByEmployee.get(emp.name),
|
|
35138
|
-
currentTask: currentTaskByEmployee.get(emp.name),
|
|
35139
|
-
sessionName: agentSt.session
|
|
35140
|
-
};
|
|
35141
|
-
});
|
|
35142
|
-
setMembers(teamData);
|
|
35143
|
-
setDbError(null);
|
|
35144
35359
|
try {
|
|
35145
35360
|
const { existsSync: existsSync44, readFileSync: readFileSync39 } = await import("fs");
|
|
35146
35361
|
const { join: join2 } = await import("path");
|
|
@@ -35162,6 +35377,8 @@ function TeamView({ onBack, onViewSessions }) {
|
|
|
35162
35377
|
setDbError(err instanceof Error ? err.message : "Unknown error");
|
|
35163
35378
|
} finally {
|
|
35164
35379
|
setLoading(false);
|
|
35380
|
+
setBadgeInFlight(false);
|
|
35381
|
+
setDetailInFlight(false);
|
|
35165
35382
|
}
|
|
35166
35383
|
});
|
|
35167
35384
|
}
|
|
@@ -35216,6 +35433,8 @@ function TeamView({ onBack, onViewSessions }) {
|
|
|
35216
35433
|
orch.pendingReviews,
|
|
35217
35434
|
" review(s) pending coordinator attention"
|
|
35218
35435
|
] }),
|
|
35436
|
+
badgeInFlight && /* @__PURE__ */ jsx12(Text, { color: "#F5D76E", children: " Loading memory counts..." }),
|
|
35437
|
+
detailInFlight && /* @__PURE__ */ jsx12(Text, { color: "#6B4C9A", children: " Loading employee details..." }),
|
|
35219
35438
|
/* @__PURE__ */ jsx12(Text, { children: " " }),
|
|
35220
35439
|
/* @__PURE__ */ jsx12(Text, { bold: true, children: "INTERNAL" }),
|
|
35221
35440
|
/* @__PURE__ */ jsx12(Text, { children: " " }),
|
|
@@ -35304,7 +35523,6 @@ function TeamView({ onBack, onViewSessions }) {
|
|
|
35304
35523
|
}) })
|
|
35305
35524
|
] });
|
|
35306
35525
|
}
|
|
35307
|
-
var DEPRECATED_PROJECTS;
|
|
35308
35526
|
var init_Team = __esm({
|
|
35309
35527
|
async "src/tui/views/Team.tsx"() {
|
|
35310
35528
|
"use strict";
|
|
@@ -35314,7 +35532,6 @@ var init_Team = __esm({
|
|
|
35314
35532
|
init_demo_data();
|
|
35315
35533
|
init_useOrchestrator();
|
|
35316
35534
|
init_agent_status();
|
|
35317
|
-
DEPRECATED_PROJECTS = /* @__PURE__ */ new Set(["exe-ai-employees"]);
|
|
35318
35535
|
}
|
|
35319
35536
|
});
|
|
35320
35537
|
|