@askexenow/exe-os 0.9.111 → 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 +62 -12
- package/dist/bin/agentic-reflection-backfill.js +37 -2
- package/dist/bin/agentic-semantic-label.js +37 -2
- package/dist/bin/backfill-conversations.js +61 -11
- package/dist/bin/backfill-responses.js +62 -12
- package/dist/bin/backfill-vectors.js +37 -2
- package/dist/bin/bulk-sync-postgres.js +63 -13
- package/dist/bin/cleanup-stale-review-tasks.js +83 -16
- package/dist/bin/cli.js +312 -80
- package/dist/bin/exe-agent-config.js +7 -1
- package/dist/bin/exe-agent.js +29 -3
- package/dist/bin/exe-assign.js +62 -12
- package/dist/bin/exe-boot.js +500 -151
- package/dist/bin/exe-call.js +46 -5
- package/dist/bin/exe-cloud.js +101 -16
- package/dist/bin/exe-dispatch.js +827 -27
- package/dist/bin/exe-doctor.js +61 -11
- package/dist/bin/exe-export-behaviors.js +67 -14
- package/dist/bin/exe-forget.js +62 -12
- package/dist/bin/exe-gateway.js +147 -27
- package/dist/bin/exe-heartbeat.js +83 -16
- package/dist/bin/exe-kill.js +62 -12
- package/dist/bin/exe-launch-agent.js +83 -15
- package/dist/bin/exe-new-employee.js +176 -8
- package/dist/bin/exe-pending-messages.js +83 -16
- package/dist/bin/exe-pending-notifications.js +83 -16
- package/dist/bin/exe-pending-reviews.js +83 -16
- package/dist/bin/exe-rename.js +62 -12
- package/dist/bin/exe-review.js +62 -12
- package/dist/bin/exe-search.js +62 -12
- package/dist/bin/exe-session-cleanup.js +949 -149
- package/dist/bin/exe-settings.js +10 -4
- package/dist/bin/exe-start-codex.js +537 -248
- package/dist/bin/exe-start-opencode.js +547 -168
- package/dist/bin/exe-status.js +83 -16
- package/dist/bin/exe-support.js +1 -1
- package/dist/bin/exe-team.js +62 -12
- package/dist/bin/git-sweep.js +827 -27
- package/dist/bin/graph-backfill.js +62 -12
- package/dist/bin/graph-export.js +62 -12
- package/dist/bin/install.js +62 -4
- package/dist/bin/intercom-check.js +949 -149
- package/dist/bin/pre-publish.js +14 -2
- package/dist/bin/scan-tasks.js +827 -27
- package/dist/bin/setup.js +99 -14
- package/dist/bin/shard-migrate.js +62 -12
- package/dist/bin/stack-update.js +1 -1
- package/dist/bin/update.js +3 -3
- package/dist/gateway/index.js +586 -26
- package/dist/hooks/bug-report-worker.js +586 -26
- package/dist/hooks/codex-stop-task-finalizer.js +977 -143
- package/dist/hooks/commit-complete.js +827 -27
- package/dist/hooks/error-recall.js +62 -12
- package/dist/hooks/ingest.js +4579 -249
- package/dist/hooks/instructions-loaded.js +62 -12
- package/dist/hooks/notification.js +62 -12
- package/dist/hooks/post-compact.js +83 -16
- package/dist/hooks/post-tool-combined.js +83 -16
- package/dist/hooks/pre-compact.js +907 -107
- package/dist/hooks/pre-tool-use.js +98 -16
- package/dist/hooks/prompt-submit.js +596 -30
- package/dist/hooks/session-end.js +909 -112
- package/dist/hooks/session-start.js +112 -17
- package/dist/hooks/stop.js +82 -15
- package/dist/hooks/subagent-stop.js +83 -16
- package/dist/hooks/summary-worker.js +81 -8
- package/dist/index.js +595 -29
- package/dist/lib/agent-config.js +16 -1
- package/dist/lib/cloud-sync.js +45 -1
- package/dist/lib/consolidation.js +16 -1
- package/dist/lib/database.js +23 -0
- package/dist/lib/db.js +23 -0
- package/dist/lib/device-registry.js +23 -0
- package/dist/lib/employee-templates.js +30 -4
- package/dist/lib/employees.js +16 -1
- package/dist/lib/exe-daemon.js +482 -52
- package/dist/lib/hybrid-search.js +62 -12
- package/dist/lib/license.js +3 -3
- package/dist/lib/messaging.js +21 -4
- package/dist/lib/schedules.js +37 -2
- package/dist/lib/skill-learning.js +910 -41
- package/dist/lib/status-brief.js +14 -1
- package/dist/lib/store.js +62 -12
- package/dist/lib/tasks.js +843 -93
- package/dist/lib/tmux-routing.js +766 -16
- package/dist/mcp/server.js +238 -41
- package/dist/mcp/tools/create-task.js +525 -15
- 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 +840 -93
- package/dist/runtime/index.js +913 -107
- package/dist/tui/App.js +227 -58
- 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) => ({
|
|
@@ -4692,6 +4739,13 @@ async function ensureSchema() {
|
|
|
4692
4739
|
} catch (e) {
|
|
4693
4740
|
logCatchDebug("migration", e);
|
|
4694
4741
|
}
|
|
4742
|
+
for (const col of ["created_by_agent TEXT", "created_by_device TEXT", "source_session_id TEXT"]) {
|
|
4743
|
+
try {
|
|
4744
|
+
await client.execute({ sql: `ALTER TABLE behaviors ADD COLUMN ${col}`, args: [] });
|
|
4745
|
+
} catch (e) {
|
|
4746
|
+
logCatchDebug("migration", e);
|
|
4747
|
+
}
|
|
4748
|
+
}
|
|
4695
4749
|
try {
|
|
4696
4750
|
await client.execute({
|
|
4697
4751
|
sql: `ALTER TABLE tasks ADD COLUMN blocked_by TEXT`,
|
|
@@ -5908,6 +5962,22 @@ async function ensureSchema() {
|
|
|
5908
5962
|
} catch (e) {
|
|
5909
5963
|
logCatchDebug("migration", e);
|
|
5910
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
|
+
}
|
|
5911
5981
|
}
|
|
5912
5982
|
async function disposeDatabase() {
|
|
5913
5983
|
if (_walCheckpointTimer) {
|
|
@@ -6453,7 +6523,7 @@ async function assertVpsLicense(opts) {
|
|
|
6453
6523
|
}
|
|
6454
6524
|
if (!transientFailure) {
|
|
6455
6525
|
throw new Error(
|
|
6456
|
-
"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."
|
|
6457
6527
|
);
|
|
6458
6528
|
}
|
|
6459
6529
|
const fresh = await getCachedLicense();
|
|
@@ -6490,7 +6560,7 @@ async function assertVpsLicense(opts) {
|
|
|
6490
6560
|
} catch {
|
|
6491
6561
|
}
|
|
6492
6562
|
throw new Error(
|
|
6493
|
-
`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.`
|
|
6494
6564
|
);
|
|
6495
6565
|
}
|
|
6496
6566
|
function startLicenseRevalidation(intervalMs = 36e5) {
|
|
@@ -6522,7 +6592,7 @@ var init_license = __esm({
|
|
|
6522
6592
|
LICENSE_PATH = path13.join(EXE_AI_DIR, "license.key");
|
|
6523
6593
|
CACHE_PATH = path13.join(EXE_AI_DIR, "license-cache.json");
|
|
6524
6594
|
DEVICE_ID_PATH = path13.join(EXE_AI_DIR, "device-id");
|
|
6525
|
-
API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://askexe.com
|
|
6595
|
+
API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://cloud.askexe.com";
|
|
6526
6596
|
RETRY_DELAY_MS = 500;
|
|
6527
6597
|
LICENSE_PUBLIC_KEY_PEM = `-----BEGIN PUBLIC KEY-----
|
|
6528
6598
|
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeHztAMOpR/ZMh+rWuOASjEZ54CGY
|
|
@@ -7325,6 +7395,27 @@ async function cloudSync(config) {
|
|
|
7325
7395
|
if (stmts.length > 0) await client.batch(stmts, "write");
|
|
7326
7396
|
pulled = pullResult.records.length;
|
|
7327
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
|
+
}
|
|
7328
7419
|
const stmts = pullResult.records.map((rec) => ({
|
|
7329
7420
|
sql: `INSERT OR REPLACE INTO memories
|
|
7330
7421
|
(id, agent_id, agent_role, session_id, timestamp,
|
|
@@ -9082,11 +9173,17 @@ var init_platform_procedures = __esm({
|
|
|
9082
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."
|
|
9083
9174
|
},
|
|
9084
9175
|
{
|
|
9085
|
-
title: "
|
|
9176
|
+
title: "Orchestration phase guidance \u2014 recommend, never trap",
|
|
9086
9177
|
domain: "workflow",
|
|
9087
9178
|
priority: "p1",
|
|
9088
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."
|
|
9089
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
|
+
},
|
|
9090
9187
|
{
|
|
9091
9188
|
title: "Single dispatch path \u2014 create_task only",
|
|
9092
9189
|
domain: "workflow",
|
|
@@ -9120,6 +9217,12 @@ var init_platform_procedures = __esm({
|
|
|
9120
9217
|
priority: "p0",
|
|
9121
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."
|
|
9122
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
|
+
},
|
|
9123
9226
|
{
|
|
9124
9227
|
title: "Customer patch triage \u2014 upstream bug vs customization",
|
|
9125
9228
|
domain: "support",
|
|
@@ -9271,7 +9374,7 @@ var init_platform_procedures = __esm({
|
|
|
9271
9374
|
title: "MCP tool dispatch \u2014 all tools use action parameter",
|
|
9272
9375
|
domain: "tool-use",
|
|
9273
9376
|
priority: "p0",
|
|
9274
|
-
content: 'exe-os MCP tools
|
|
9377
|
+
content: 'exe-os MCP tools use consolidated action-based dispatch by default (19 tools). Call domain tools with an action parameter: memory(action="recall"), task(action="create"), config(action="list_employees"), etc. Legacy mode (108 separate tools like recall_my_memory, create_task) is still available via EXE_MCP_TOOL_SURFACE=legacy but will be removed in a future version. If you see specific tool names, call them directly \u2014 both surfaces are identical. Consolidated is the default and recommended surface.'
|
|
9275
9378
|
},
|
|
9276
9379
|
{
|
|
9277
9380
|
title: "MCP tools \u2014 memory, decision, and search",
|
|
@@ -9405,10 +9508,24 @@ function stableId(memoryId, type, content) {
|
|
|
9405
9508
|
return createHash3("sha256").update(`${memoryId}:${type}:${content}`).digest("hex").slice(0, 32);
|
|
9406
9509
|
}
|
|
9407
9510
|
function cleanText(text) {
|
|
9408
|
-
|
|
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;
|
|
9409
9517
|
}
|
|
9410
|
-
function
|
|
9411
|
-
|
|
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;
|
|
9412
9529
|
}
|
|
9413
9530
|
function inferCardType(sentence, toolName) {
|
|
9414
9531
|
const lower = sentence.toLowerCase();
|
|
@@ -9440,12 +9557,12 @@ function predicateFor(type) {
|
|
|
9440
9557
|
}
|
|
9441
9558
|
}
|
|
9442
9559
|
function extractMemoryCards(row) {
|
|
9443
|
-
const
|
|
9560
|
+
const segments = splitSegments(row.raw_text);
|
|
9444
9561
|
const cards = [];
|
|
9445
|
-
for (const sentence of
|
|
9562
|
+
for (const sentence of segments) {
|
|
9446
9563
|
const type = inferCardType(sentence, row.tool_name);
|
|
9447
9564
|
const subject = extractSubject(sentence, row.agent_id);
|
|
9448
|
-
const content = sentence.length >
|
|
9565
|
+
const content = sentence.length > MAX_SEGMENT_CHARS ? `${sentence.slice(0, MAX_SEGMENT_CHARS - 1)}\u2026` : sentence;
|
|
9449
9566
|
cards.push({
|
|
9450
9567
|
id: stableId(row.id, type, content),
|
|
9451
9568
|
memory_id: row.id,
|
|
@@ -9541,13 +9658,14 @@ Source memory: ${String(row.source_ref ?? row.memory_id)}`,
|
|
|
9541
9658
|
last_accessed: String(row.timestamp)
|
|
9542
9659
|
}));
|
|
9543
9660
|
}
|
|
9544
|
-
var MAX_CARDS_PER_MEMORY,
|
|
9661
|
+
var MAX_CARDS_PER_MEMORY, MAX_SEGMENT_CHARS, MIN_SEGMENT_CHARS;
|
|
9545
9662
|
var init_memory_cards = __esm({
|
|
9546
9663
|
"src/lib/memory-cards.ts"() {
|
|
9547
9664
|
"use strict";
|
|
9548
9665
|
init_database();
|
|
9549
|
-
MAX_CARDS_PER_MEMORY =
|
|
9550
|
-
|
|
9666
|
+
MAX_CARDS_PER_MEMORY = 8;
|
|
9667
|
+
MAX_SEGMENT_CHARS = 500;
|
|
9668
|
+
MIN_SEGMENT_CHARS = 20;
|
|
9551
9669
|
}
|
|
9552
9670
|
});
|
|
9553
9671
|
|
|
@@ -10638,7 +10756,7 @@ async function setupMode() {
|
|
|
10638
10756
|
rl.close();
|
|
10639
10757
|
return;
|
|
10640
10758
|
}
|
|
10641
|
-
const endpoint = await ask(rl, " Endpoint [https://askexe.com
|
|
10759
|
+
const endpoint = await ask(rl, " Endpoint [https://cloud.askexe.com]: ") || "https://cloud.askexe.com";
|
|
10642
10760
|
console.log(" Validating...");
|
|
10643
10761
|
try {
|
|
10644
10762
|
assertSecureEndpoint(endpoint);
|
|
@@ -10704,6 +10822,14 @@ async function setupMode() {
|
|
|
10704
10822
|
}
|
|
10705
10823
|
console.log("");
|
|
10706
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("");
|
|
10707
10833
|
console.log(BAR);
|
|
10708
10834
|
console.log(latestConfig.cloud?.apiKey ? " Setup complete. Cloud sync is connected." : " Setup complete. Cloud sync is not configured yet.");
|
|
10709
10835
|
console.log(BAR);
|
|
@@ -10795,7 +10921,13 @@ async function statusMode() {
|
|
|
10795
10921
|
console.log("");
|
|
10796
10922
|
if (key) {
|
|
10797
10923
|
const fingerprint = key.toString("hex").slice(0, 8);
|
|
10798
|
-
|
|
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}`);
|
|
10799
10931
|
} else {
|
|
10800
10932
|
console.log(" Encryption key: \u2717 not found \u2014 run /exe-setup");
|
|
10801
10933
|
}
|
|
@@ -12284,17 +12416,14 @@ var backfill_metadata_exports = {};
|
|
|
12284
12416
|
__export(backfill_metadata_exports, {
|
|
12285
12417
|
backfillMetadata: () => backfillMetadata
|
|
12286
12418
|
});
|
|
12287
|
-
function roleAgentMarkers(role
|
|
12419
|
+
function roleAgentMarkers(role) {
|
|
12288
12420
|
try {
|
|
12289
12421
|
const employees = loadEmployeesSync();
|
|
12290
|
-
const
|
|
12291
|
-
|
|
12292
|
-
if (configuredName) {
|
|
12293
|
-
return [configuredName];
|
|
12294
|
-
}
|
|
12422
|
+
const names = getEmployeeNamesByRole(employees, role).map((n) => n.toLowerCase().trim()).filter(Boolean);
|
|
12423
|
+
if (names.length > 0) return names;
|
|
12295
12424
|
} catch {
|
|
12296
12425
|
}
|
|
12297
|
-
return [
|
|
12426
|
+
return [];
|
|
12298
12427
|
}
|
|
12299
12428
|
function mentionsAgentMarker(text, markers) {
|
|
12300
12429
|
return markers.some(
|
|
@@ -12853,8 +12982,8 @@ var init_backfill_metadata = __esm({
|
|
|
12853
12982
|
VALID_LANGUAGE_TYPES = /* @__PURE__ */ new Set(["code", "prose", "mixed", "json", "sql"]);
|
|
12854
12983
|
MAX_TEXT_LENGTH = 2e3;
|
|
12855
12984
|
BATCH_SLEEP_MS = 1e3;
|
|
12856
|
-
MARKETING_AGENT_MARKERS = roleAgentMarkers("CMO"
|
|
12857
|
-
RESEARCH_AGENT_MARKERS = roleAgentMarkers("AI Product Lead"
|
|
12985
|
+
MARKETING_AGENT_MARKERS = roleAgentMarkers("CMO");
|
|
12986
|
+
RESEARCH_AGENT_MARKERS = roleAgentMarkers("AI Product Lead");
|
|
12858
12987
|
if (isMainModule(import.meta.url)) {
|
|
12859
12988
|
const options = parseArgs2(process.argv.slice(2));
|
|
12860
12989
|
backfillMetadata(options).then((result) => {
|
|
@@ -14334,6 +14463,19 @@ async function resolveTask(client, identifier, scopeSession) {
|
|
|
14334
14463
|
args: [identifier, ...scope.args]
|
|
14335
14464
|
});
|
|
14336
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
|
+
}
|
|
14337
14479
|
result = await client.execute({
|
|
14338
14480
|
sql: `SELECT * FROM tasks WHERE task_file LIKE ?${scope.sql}`,
|
|
14339
14481
|
args: [`%${identifier}%`, ...scope.args]
|
|
@@ -15188,12 +15330,13 @@ async function cascadeUnblock(taskId, baseDir, now2) {
|
|
|
15188
15330
|
WHERE blocked_by = ? AND status = 'blocked'`,
|
|
15189
15331
|
args: [now2, taskId]
|
|
15190
15332
|
});
|
|
15191
|
-
if (
|
|
15192
|
-
|
|
15193
|
-
|
|
15194
|
-
|
|
15195
|
-
|
|
15196
|
-
|
|
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) {
|
|
15197
15340
|
for (const ur of unblockedRows.rows) {
|
|
15198
15341
|
try {
|
|
15199
15342
|
const ubFile = path32.join(baseDir, String(ur.task_file));
|
|
@@ -15205,6 +15348,19 @@ async function cascadeUnblock(taskId, baseDir, now2) {
|
|
|
15205
15348
|
}
|
|
15206
15349
|
}
|
|
15207
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
|
+
}
|
|
15208
15364
|
}
|
|
15209
15365
|
async function findNextTask(assignedTo) {
|
|
15210
15366
|
const client = getClient();
|
|
@@ -15414,6 +15570,15 @@ var init_embedder = __esm({
|
|
|
15414
15570
|
// src/lib/behaviors.ts
|
|
15415
15571
|
import crypto10 from "crypto";
|
|
15416
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
|
+
}
|
|
15417
15582
|
const client = getClient();
|
|
15418
15583
|
const id = crypto10.randomUUID();
|
|
15419
15584
|
const now2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -15424,10 +15589,18 @@ async function storeBehavior(opts) {
|
|
|
15424
15589
|
vector = new Float32Array(vec);
|
|
15425
15590
|
} catch {
|
|
15426
15591
|
}
|
|
15592
|
+
let createdByDevice = null;
|
|
15593
|
+
try {
|
|
15594
|
+
const { loadDeviceId: loadDeviceId2 } = await Promise.resolve().then(() => (init_license(), license_exports));
|
|
15595
|
+
createdByDevice = loadDeviceId2() ?? null;
|
|
15596
|
+
} catch {
|
|
15597
|
+
}
|
|
15598
|
+
const createdByAgent = process.env.AGENT_ID ?? null;
|
|
15599
|
+
const sourceSessionId = process.env.CLAUDE_SESSION_ID ?? process.env.SESSION_ID ?? null;
|
|
15427
15600
|
await client.execute({
|
|
15428
|
-
sql: `INSERT INTO behaviors (id, agent_id, project_name, domain, priority, content, active, created_at, updated_at, vector)
|
|
15429
|
-
VALUES (?, ?, ?, ?, ?, ?, 1, ?, ?, ?)`,
|
|
15430
|
-
args: [id, opts.agentId, opts.projectName ?? null, opts.domain ?? null, opts.priority ?? "p1", opts.content, now2, now2, vector ? vector.buffer : null]
|
|
15601
|
+
sql: `INSERT INTO behaviors (id, agent_id, project_name, domain, priority, content, active, created_at, updated_at, vector, created_by_agent, created_by_device, source_session_id)
|
|
15602
|
+
VALUES (?, ?, ?, ?, ?, ?, 1, ?, ?, ?, ?, ?, ?)`,
|
|
15603
|
+
args: [id, opts.agentId, opts.projectName ?? null, opts.domain ?? null, opts.priority ?? "p1", opts.content, now2, now2, vector ? vector.buffer : null, createdByAgent, createdByDevice, sourceSessionId]
|
|
15431
15604
|
});
|
|
15432
15605
|
return id;
|
|
15433
15606
|
}
|
|
@@ -15859,6 +16032,12 @@ async function updateTask(input) {
|
|
|
15859
16032
|
}
|
|
15860
16033
|
}
|
|
15861
16034
|
}
|
|
16035
|
+
if (input.status === "cancelled") {
|
|
16036
|
+
try {
|
|
16037
|
+
await cascadeUnblock(taskId, input.baseDir, now2);
|
|
16038
|
+
} catch {
|
|
16039
|
+
}
|
|
16040
|
+
}
|
|
15862
16041
|
if ((input.status === "done" || input.status === "closed") && !isCoordinatorName(String(row.assigned_to)) && !process.env.VITEST) {
|
|
15863
16042
|
Promise.resolve().then(() => (init_skill_learning(), skill_learning_exports)).then(
|
|
15864
16043
|
({ captureAndLearn: captureAndLearn2 }) => captureAndLearn2({
|
|
@@ -16390,11 +16569,12 @@ function getDispatchedBy(sessionKey) {
|
|
|
16390
16569
|
}
|
|
16391
16570
|
}
|
|
16392
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
|
+
}
|
|
16393
16576
|
const mySession = getMySession();
|
|
16394
16577
|
if (!mySession) {
|
|
16395
|
-
if (process.env.EXE_SESSION_NAME) {
|
|
16396
|
-
return extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
|
|
16397
|
-
}
|
|
16398
16578
|
return null;
|
|
16399
16579
|
}
|
|
16400
16580
|
const fromSessionName = extractRootExe(mySession);
|
|
@@ -16409,6 +16589,10 @@ function resolveExeSession() {
|
|
|
16409
16589
|
`[tmux-routing] WARN: cache says "${fromCache}" but session name says "${fromSessionName}". Trusting session name.
|
|
16410
16590
|
`
|
|
16411
16591
|
);
|
|
16592
|
+
try {
|
|
16593
|
+
registerParentExe(key, fromSessionName);
|
|
16594
|
+
} catch {
|
|
16595
|
+
}
|
|
16412
16596
|
candidate = fromSessionName;
|
|
16413
16597
|
} else {
|
|
16414
16598
|
candidate = fromCache;
|
|
@@ -17567,9 +17751,23 @@ __export(employee_templates_exports, {
|
|
|
17567
17751
|
function getSessionPrompt(storedPrompt) {
|
|
17568
17752
|
const markerIndex = storedPrompt.indexOf(PROCEDURES_MARKER);
|
|
17569
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
|
+
}
|
|
17570
17768
|
const rolePrompt = withoutProcedures.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, "").replace(/<!--[\s\S]*?-->/g, "").trimStart();
|
|
17571
17769
|
const globalBlock = getGlobalProceduresBlock();
|
|
17572
|
-
return `${globalBlock}${rolePrompt}
|
|
17770
|
+
return `${globalBlock}${titlePrefix}${rolePrompt}
|
|
17573
17771
|
${BASE_OPERATING_PROCEDURES}`;
|
|
17574
17772
|
}
|
|
17575
17773
|
function buildCustomEmployeePrompt(name, role) {
|
|
@@ -17588,7 +17786,7 @@ function personalizePrompt(prompt, templateName, actualName) {
|
|
|
17588
17786
|
return prompt.replace(new RegExp(`\\bYou are ${escaped}\\b`, "g"), `You are ${actualName}`);
|
|
17589
17787
|
}
|
|
17590
17788
|
function renderClientCOOTemplate(vars) {
|
|
17591
|
-
const resolved = { ...vars, title: vars.title || "Chief
|
|
17789
|
+
const resolved = { ...vars, title: vars.title || "Chief of Staff" };
|
|
17592
17790
|
for (const key of CLIENT_COO_PLACEHOLDERS) {
|
|
17593
17791
|
const value = resolved[key];
|
|
17594
17792
|
if (typeof value !== "string" || value.length === 0) {
|
|
@@ -20312,7 +20510,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
20312
20510
|
log("");
|
|
20313
20511
|
const apiKey = await ask3(rl, "Cloud API key (starts with exe_sk_): ");
|
|
20314
20512
|
if (apiKey && apiKey.startsWith("exe_sk_")) {
|
|
20315
|
-
const cloudEndpoint = "https://askexe.com
|
|
20513
|
+
const cloudEndpoint = "https://cloud.askexe.com";
|
|
20316
20514
|
const cloudCfg = { apiKey, endpoint: cloudEndpoint };
|
|
20317
20515
|
const earlyConfig = await loadConfig();
|
|
20318
20516
|
earlyConfig.cloud = cloudCfg;
|
|
@@ -20412,7 +20610,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
20412
20610
|
log("");
|
|
20413
20611
|
const existingKey = await ask3(rl, "Paste your Exe OS license key, or press Enter to start as a free user: ");
|
|
20414
20612
|
if (existingKey && existingKey.startsWith("exe_sk_")) {
|
|
20415
|
-
const cloudEndpoint = "https://askexe.com
|
|
20613
|
+
const cloudEndpoint = "https://cloud.askexe.com";
|
|
20416
20614
|
try {
|
|
20417
20615
|
const { loadDeviceId: loadDeviceId2 } = await Promise.resolve().then(() => (init_license(), license_exports));
|
|
20418
20616
|
const deviceId = loadDeviceId2();
|
|
@@ -20437,7 +20635,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
20437
20635
|
}
|
|
20438
20636
|
} catch {
|
|
20439
20637
|
log("Could not validate key \u2014 saving it and proceeding.");
|
|
20440
|
-
cloudConfig = { apiKey: existingKey, endpoint: "https://askexe.com
|
|
20638
|
+
cloudConfig = { apiKey: existingKey, endpoint: "https://cloud.askexe.com" };
|
|
20441
20639
|
const { saveLicense: saveLicense3, mirrorLicenseKey: mirrorLicenseKey3 } = await Promise.resolve().then(() => (init_license(), license_exports));
|
|
20442
20640
|
saveLicense3(existingKey);
|
|
20443
20641
|
mirrorLicenseKey3(existingKey);
|
|
@@ -20449,7 +20647,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
20449
20647
|
const deviceId = loadDeviceId2();
|
|
20450
20648
|
let res;
|
|
20451
20649
|
try {
|
|
20452
|
-
res = await fetch("https://askexe.com/
|
|
20650
|
+
res = await fetch("https://cloud.askexe.com/auth/auto-provision", {
|
|
20453
20651
|
method: "POST",
|
|
20454
20652
|
headers: { "Content-Type": "application/json" },
|
|
20455
20653
|
body: JSON.stringify({ deviceId }),
|
|
@@ -20457,7 +20655,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
20457
20655
|
});
|
|
20458
20656
|
} catch {
|
|
20459
20657
|
await new Promise((r) => setTimeout(r, 500));
|
|
20460
|
-
res = await fetch("https://askexe.com/
|
|
20658
|
+
res = await fetch("https://cloud.askexe.com/auth/auto-provision", {
|
|
20461
20659
|
method: "POST",
|
|
20462
20660
|
headers: { "Content-Type": "application/json" },
|
|
20463
20661
|
body: JSON.stringify({ deviceId }),
|
|
@@ -20467,7 +20665,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
20467
20665
|
if (res.ok) {
|
|
20468
20666
|
const data = await res.json();
|
|
20469
20667
|
if (data.apiKey) {
|
|
20470
|
-
cloudConfig = { apiKey: data.apiKey, endpoint: "https://askexe.com
|
|
20668
|
+
cloudConfig = { apiKey: data.apiKey, endpoint: "https://cloud.askexe.com" };
|
|
20471
20669
|
const { saveLicense: saveLicense3, mirrorLicenseKey: mirrorLicenseKey3 } = await Promise.resolve().then(() => (init_license(), license_exports));
|
|
20472
20670
|
saveLicense3(data.apiKey);
|
|
20473
20671
|
mirrorLicenseKey3(data.apiKey);
|
|
@@ -33127,7 +33325,7 @@ function useOrchestrator(enabled = true) {
|
|
|
33127
33325
|
const [pendingReviews, setPendingReviews] = useState8(0);
|
|
33128
33326
|
const [isLoading, setIsLoading] = useState8(true);
|
|
33129
33327
|
const orchestratorRef = useRef5(null);
|
|
33130
|
-
const exeSessionRef = useRef5("
|
|
33328
|
+
const exeSessionRef = useRef5("");
|
|
33131
33329
|
const coordinatorNameRef = useRef5(DEFAULT_COORDINATOR_TEMPLATE_NAME);
|
|
33132
33330
|
useEffect10(() => {
|
|
33133
33331
|
if (!enabled) return;
|
|
@@ -33724,6 +33922,8 @@ var tui_data_exports = {};
|
|
|
33724
33922
|
__export(tui_data_exports, {
|
|
33725
33923
|
loadMemoryDashboard: () => loadMemoryDashboard,
|
|
33726
33924
|
loadTaskList: () => loadTaskList,
|
|
33925
|
+
loadTeamBadgeCounts: () => loadTeamBadgeCounts,
|
|
33926
|
+
loadTeamDetailMetrics: () => loadTeamDetailMetrics,
|
|
33727
33927
|
loadTeamMetrics: () => loadTeamMetrics,
|
|
33728
33928
|
searchWikiMemoryRows: () => searchWikiMemoryRows
|
|
33729
33929
|
});
|
|
@@ -33752,16 +33952,20 @@ async function loadMemoryDashboard(limit) {
|
|
|
33752
33952
|
}))
|
|
33753
33953
|
};
|
|
33754
33954
|
}
|
|
33755
|
-
async function
|
|
33955
|
+
async function loadTeamBadgeCounts() {
|
|
33756
33956
|
const client = getClient();
|
|
33757
33957
|
const memoryCounts = /* @__PURE__ */ new Map();
|
|
33758
|
-
const projectsByEmployee = /* @__PURE__ */ new Map();
|
|
33759
|
-
const currentTaskByEmployee = /* @__PURE__ */ new Map();
|
|
33760
|
-
const scope = sessionScopeFilter();
|
|
33761
33958
|
const memResult = await client.execute("SELECT agent_id, COUNT(*) as cnt FROM memories GROUP BY agent_id");
|
|
33762
33959
|
for (const row of memResult.rows) {
|
|
33763
33960
|
memoryCounts.set(String(row.agent_id), Number(row.cnt));
|
|
33764
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();
|
|
33765
33969
|
for (const employeeName of employeeNames) {
|
|
33766
33970
|
const [projectResult, taskResult] = await Promise.all([
|
|
33767
33971
|
client.execute({
|
|
@@ -33794,6 +33998,13 @@ async function loadTeamMetrics(employeeNames) {
|
|
|
33794
33998
|
currentTaskByEmployee.set(employeeName, String(taskResult.rows[0].title));
|
|
33795
33999
|
}
|
|
33796
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
|
+
]);
|
|
33797
34008
|
return { memoryCounts, projectsByEmployee, currentTaskByEmployee };
|
|
33798
34009
|
}
|
|
33799
34010
|
async function loadTaskList() {
|
|
@@ -35049,6 +35260,8 @@ function TeamView({ onBack, onViewSessions }) {
|
|
|
35049
35260
|
const [members, setMembers] = useState12([]);
|
|
35050
35261
|
const [externals, setExternals] = useState12([]);
|
|
35051
35262
|
const [loading, setLoading] = useState12(!demo);
|
|
35263
|
+
const [badgeInFlight, setBadgeInFlight] = useState12(!demo);
|
|
35264
|
+
const [detailInFlight, setDetailInFlight] = useState12(!demo);
|
|
35052
35265
|
const [dbError, setDbError] = useState12(null);
|
|
35053
35266
|
const [selectedIdx, setSelectedIdx] = useState12(0);
|
|
35054
35267
|
const [showDetail, setShowDetail] = useState12(false);
|
|
@@ -35061,6 +35274,8 @@ function TeamView({ onBack, onViewSessions }) {
|
|
|
35061
35274
|
setMembers(DEMO_EMPLOYEES.map((e) => ({ ...e })));
|
|
35062
35275
|
setExternals(DEMO_EXTERNAL_AGENTS);
|
|
35063
35276
|
setLoading(false);
|
|
35277
|
+
setBadgeInFlight(false);
|
|
35278
|
+
setDetailInFlight(false);
|
|
35064
35279
|
return;
|
|
35065
35280
|
}
|
|
35066
35281
|
loadTeam();
|
|
@@ -35099,33 +35314,48 @@ function TeamView({ onBack, onViewSessions }) {
|
|
|
35099
35314
|
let projectsByEmployee = /* @__PURE__ */ new Map();
|
|
35100
35315
|
let currentTaskByEmployee = /* @__PURE__ */ new Map();
|
|
35101
35316
|
try {
|
|
35102
|
-
const {
|
|
35103
|
-
|
|
35104
|
-
|
|
35105
|
-
|
|
35106
|
-
|
|
35107
|
-
|
|
35108
|
-
|
|
35109
|
-
|
|
35110
|
-
|
|
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;
|
|
35111
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);
|
|
35112
35357
|
} catch {
|
|
35113
35358
|
}
|
|
35114
|
-
const teamData = roster.map((emp) => {
|
|
35115
|
-
const agentSt = getAgentStatus(emp.name);
|
|
35116
|
-
return {
|
|
35117
|
-
name: emp.name,
|
|
35118
|
-
role: emp.role,
|
|
35119
|
-
status: agentSt.label,
|
|
35120
|
-
activity: agentSt.label === "active" ? "Processing..." : "",
|
|
35121
|
-
memoryCount: memoryCounts.get(emp.name) ?? 0,
|
|
35122
|
-
projects: projectsByEmployee.get(emp.name),
|
|
35123
|
-
currentTask: currentTaskByEmployee.get(emp.name),
|
|
35124
|
-
sessionName: agentSt.session
|
|
35125
|
-
};
|
|
35126
|
-
});
|
|
35127
|
-
setMembers(teamData);
|
|
35128
|
-
setDbError(null);
|
|
35129
35359
|
try {
|
|
35130
35360
|
const { existsSync: existsSync44, readFileSync: readFileSync39 } = await import("fs");
|
|
35131
35361
|
const { join: join2 } = await import("path");
|
|
@@ -35147,6 +35377,8 @@ function TeamView({ onBack, onViewSessions }) {
|
|
|
35147
35377
|
setDbError(err instanceof Error ? err.message : "Unknown error");
|
|
35148
35378
|
} finally {
|
|
35149
35379
|
setLoading(false);
|
|
35380
|
+
setBadgeInFlight(false);
|
|
35381
|
+
setDetailInFlight(false);
|
|
35150
35382
|
}
|
|
35151
35383
|
});
|
|
35152
35384
|
}
|
|
@@ -35201,6 +35433,8 @@ function TeamView({ onBack, onViewSessions }) {
|
|
|
35201
35433
|
orch.pendingReviews,
|
|
35202
35434
|
" review(s) pending coordinator attention"
|
|
35203
35435
|
] }),
|
|
35436
|
+
badgeInFlight && /* @__PURE__ */ jsx12(Text, { color: "#F5D76E", children: " Loading memory counts..." }),
|
|
35437
|
+
detailInFlight && /* @__PURE__ */ jsx12(Text, { color: "#6B4C9A", children: " Loading employee details..." }),
|
|
35204
35438
|
/* @__PURE__ */ jsx12(Text, { children: " " }),
|
|
35205
35439
|
/* @__PURE__ */ jsx12(Text, { bold: true, children: "INTERNAL" }),
|
|
35206
35440
|
/* @__PURE__ */ jsx12(Text, { children: " " }),
|
|
@@ -35289,7 +35523,6 @@ function TeamView({ onBack, onViewSessions }) {
|
|
|
35289
35523
|
}) })
|
|
35290
35524
|
] });
|
|
35291
35525
|
}
|
|
35292
|
-
var DEPRECATED_PROJECTS;
|
|
35293
35526
|
var init_Team = __esm({
|
|
35294
35527
|
async "src/tui/views/Team.tsx"() {
|
|
35295
35528
|
"use strict";
|
|
@@ -35299,7 +35532,6 @@ var init_Team = __esm({
|
|
|
35299
35532
|
init_demo_data();
|
|
35300
35533
|
init_useOrchestrator();
|
|
35301
35534
|
init_agent_status();
|
|
35302
|
-
DEPRECATED_PROJECTS = /* @__PURE__ */ new Set(["exe-ai-employees"]);
|
|
35303
35535
|
}
|
|
35304
35536
|
});
|
|
35305
35537
|
|