@askexenow/exe-os 0.9.93 → 0.9.95
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/deploy/compose/docker-compose.yml +1 -0
- package/dist/bin/agentic-ontology-backfill.js +65 -8
- package/dist/bin/agentic-reflection-backfill.js +54 -3
- package/dist/bin/agentic-semantic-label.js +54 -3
- package/dist/bin/backfill-conversations.js +69 -9
- package/dist/bin/backfill-responses.js +69 -9
- package/dist/bin/backfill-vectors.js +54 -3
- package/dist/bin/bulk-sync-postgres.js +66 -8
- package/dist/bin/cleanup-stale-review-tasks.js +121 -13
- package/dist/bin/cli.js +1561 -466
- package/dist/bin/customer-readiness.js +61 -0
- package/dist/bin/exe-agent.js +17 -3
- package/dist/bin/exe-assign.js +75 -9
- package/dist/bin/exe-boot.js +114 -12
- package/dist/bin/exe-call.js +17 -3
- package/dist/bin/exe-cloud.js +76 -10
- package/dist/bin/exe-dispatch.js +136 -18
- package/dist/bin/exe-doctor.js +75 -9
- package/dist/bin/exe-export-behaviors.js +75 -9
- package/dist/bin/exe-forget.js +94 -9
- package/dist/bin/exe-gateway.js +135 -18
- package/dist/bin/exe-heartbeat.js +121 -13
- package/dist/bin/exe-kill.js +75 -9
- package/dist/bin/exe-launch-agent.js +75 -9
- package/dist/bin/exe-new-employee.js +18 -4
- package/dist/bin/exe-pending-messages.js +121 -13
- package/dist/bin/exe-pending-notifications.js +121 -13
- package/dist/bin/exe-pending-reviews.js +121 -13
- package/dist/bin/exe-rename.js +75 -9
- package/dist/bin/exe-review.js +75 -9
- package/dist/bin/exe-search.js +100 -9
- package/dist/bin/exe-session-cleanup.js +136 -18
- package/dist/bin/exe-settings.js +1 -0
- package/dist/bin/exe-start-codex.js +65 -8
- package/dist/bin/exe-start-opencode.js +65 -8
- package/dist/bin/exe-status.js +121 -13
- package/dist/bin/exe-support.js +1 -0
- package/dist/bin/exe-team.js +75 -9
- package/dist/bin/git-sweep.js +136 -18
- package/dist/bin/graph-backfill.js +65 -8
- package/dist/bin/graph-export.js +75 -9
- package/dist/bin/intercom-check.js +136 -18
- package/dist/bin/scan-tasks.js +136 -18
- package/dist/bin/setup.js +55 -4
- package/dist/bin/shard-migrate.js +65 -8
- package/dist/bin/stack-update.js +5 -6
- package/dist/bin/update.js +1 -1
- package/dist/gateway/index.js +136 -18
- package/dist/hooks/bug-report-worker.js +136 -18
- package/dist/hooks/codex-stop-task-finalizer.js +126 -14
- package/dist/hooks/commit-complete.js +136 -18
- package/dist/hooks/error-recall.js +100 -9
- package/dist/hooks/ingest.js +75 -9
- package/dist/hooks/instructions-loaded.js +75 -9
- package/dist/hooks/notification.js +75 -9
- package/dist/hooks/post-compact.js +313 -50
- package/dist/hooks/post-tool-combined.js +436 -13
- package/dist/hooks/pre-compact.js +136 -18
- package/dist/hooks/pre-tool-use.js +121 -13
- package/dist/hooks/prompt-submit.js +194 -19
- package/dist/hooks/session-end.js +136 -18
- package/dist/hooks/session-start.js +146 -13
- package/dist/hooks/stop.js +121 -13
- package/dist/hooks/subagent-stop.js +121 -13
- package/dist/hooks/summary-worker.js +99 -7
- package/dist/index.js +136 -18
- package/dist/lib/cloud-sync.js +38 -0
- package/dist/lib/consolidation.js +3 -1
- package/dist/lib/database.js +37 -0
- package/dist/lib/db.js +37 -0
- package/dist/lib/device-registry.js +37 -0
- package/dist/lib/employee-templates.js +17 -3
- package/dist/lib/exe-daemon.js +916 -42
- package/dist/lib/hybrid-search.js +100 -9
- package/dist/lib/license.js +1 -1
- package/dist/lib/messaging.js +43 -4
- package/dist/lib/schedules.js +54 -3
- package/dist/lib/store.js +75 -9
- package/dist/lib/tasks.js +61 -9
- package/dist/lib/tmux-routing.js +61 -9
- package/dist/mcp/server.js +878 -42
- package/dist/mcp/tools/create-task.js +70 -12
- package/dist/mcp/tools/list-tasks.js +49 -5
- package/dist/mcp/tools/send-message.js +43 -4
- package/dist/mcp/tools/update-task.js +61 -9
- package/dist/runtime/index.js +136 -18
- package/dist/tui/App.js +135 -18
- package/package.json +1 -1
package/dist/lib/exe-daemon.js
CHANGED
|
@@ -3175,6 +3175,20 @@ async function ensureSchema() {
|
|
|
3175
3175
|
});
|
|
3176
3176
|
} catch {
|
|
3177
3177
|
}
|
|
3178
|
+
try {
|
|
3179
|
+
await client.execute({
|
|
3180
|
+
sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
|
|
3181
|
+
args: []
|
|
3182
|
+
});
|
|
3183
|
+
} catch {
|
|
3184
|
+
}
|
|
3185
|
+
try {
|
|
3186
|
+
await client.execute({
|
|
3187
|
+
sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
|
|
3188
|
+
args: []
|
|
3189
|
+
});
|
|
3190
|
+
} catch {
|
|
3191
|
+
}
|
|
3178
3192
|
await client.executeMultiple(`
|
|
3179
3193
|
CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
|
|
3180
3194
|
content_text,
|
|
@@ -3426,6 +3440,22 @@ async function ensureSchema() {
|
|
|
3426
3440
|
);
|
|
3427
3441
|
} catch {
|
|
3428
3442
|
}
|
|
3443
|
+
for (const col of [
|
|
3444
|
+
"ALTER TABLE memories ADD COLUMN valid_from TEXT",
|
|
3445
|
+
"ALTER TABLE memories ADD COLUMN invalid_at TEXT"
|
|
3446
|
+
]) {
|
|
3447
|
+
try {
|
|
3448
|
+
await client.execute(col);
|
|
3449
|
+
} catch {
|
|
3450
|
+
}
|
|
3451
|
+
}
|
|
3452
|
+
try {
|
|
3453
|
+
await client.execute({
|
|
3454
|
+
sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
|
|
3455
|
+
args: []
|
|
3456
|
+
});
|
|
3457
|
+
} catch {
|
|
3458
|
+
}
|
|
3429
3459
|
try {
|
|
3430
3460
|
await client.execute({
|
|
3431
3461
|
sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
|
|
@@ -3468,6 +3498,13 @@ async function ensureSchema() {
|
|
|
3468
3498
|
} catch {
|
|
3469
3499
|
}
|
|
3470
3500
|
}
|
|
3501
|
+
try {
|
|
3502
|
+
await client.execute({
|
|
3503
|
+
sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
|
|
3504
|
+
args: []
|
|
3505
|
+
});
|
|
3506
|
+
} catch {
|
|
3507
|
+
}
|
|
3471
3508
|
try {
|
|
3472
3509
|
await client.execute({
|
|
3473
3510
|
sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
|
|
@@ -5877,6 +5914,20 @@ var init_platform_procedures = __esm({
|
|
|
5877
5914
|
priority: "p1",
|
|
5878
5915
|
content: "Once per session (COO boot only, never repeat), call list_my_feature_requests to check if any previously filed feature requests have been shipped by AskExe. If any request has status 'shipped' with a shipped_version, surface it to the founder immediately: '\u{1F680} N feature(s) shipped \u2014 run exe-os update to get version X.Y.Z'. This is a one-time check at boot, not a recurring poll. If no requests exist or none are shipped, skip silently. If the MCP tool is unavailable or the network call fails, skip silently \u2014 this is informational, not blocking."
|
|
5879
5916
|
},
|
|
5917
|
+
// --- Tool guidance ---
|
|
5918
|
+
{
|
|
5919
|
+
title: "How to use company_actions \u2014 execute business actions through gateway connectors",
|
|
5920
|
+
domain: "tools",
|
|
5921
|
+
priority: "p2",
|
|
5922
|
+
content: "The company_actions tool executes business actions through gateway connectors (e.g. send WhatsApp, trigger workflows, update CRM). It routes through the exe-gateway on the VPS. Actions are defined by the customer's gateway configuration \u2014 each connector (WhatsApp, Shopify, email, etc.) exposes specific actions. Use query_company_brain to find available data first, then company_actions to act on it. Requires gateway auth token. Read-only founders should NOT use this \u2014 it mutates external state."
|
|
5923
|
+
},
|
|
5924
|
+
// --- Release awareness ---
|
|
5925
|
+
{
|
|
5926
|
+
title: "What's New check \u2014 surface new features after update",
|
|
5927
|
+
domain: "support",
|
|
5928
|
+
priority: "p1",
|
|
5929
|
+
content: "Once per session (COO boot only, never repeat), check if the installed exe-os version is newer than the last session. If it is, read the bundled release-notes.json (at the package root) and surface a brief summary to the founder: 'Updated to exe-os vX.Y.Z \u2014 N new features, M fixes.' List the top 3 features by name. This helps the founder know what they got from the update. If release-notes.json doesn't exist or the version hasn't changed, skip silently. Never repeat this check in the same session."
|
|
5930
|
+
},
|
|
5880
5931
|
// --- Platform vs Customer ownership ---
|
|
5881
5932
|
{
|
|
5882
5933
|
title: "What the platform provides vs what you customize",
|
|
@@ -5965,13 +6016,13 @@ var init_platform_procedures = __esm({
|
|
|
5965
6016
|
title: "MCP tools \u2014 memory, decision, and search",
|
|
5966
6017
|
domain: "tool-use",
|
|
5967
6018
|
priority: "p1",
|
|
5968
|
-
content: `memory(action="recall") / recall_my_memory: search
|
|
6019
|
+
content: `memory(action="recall") / recall_my_memory: search memories (semantic + FTS). Params: as_of (bi-temporal \u2014 what did I know at time X?), kind (decision|procedure|observation|raw|conversation|behavior), retrieval_mode (all|decisions_only|procedures_only|operational|recent_high_value). memory(action="ask_team") / ask_team_memory: search a colleague's memories. memory(action="store") / store_memory: persist a memory. Params: kind, procedure_for (domain tag for procedures). memory(action="commit") / commit_memory: high-importance, survives consolidation. Requires summary. memory(action="search") / search_everything: unified search across memories, tasks, entities, conversations. memory(action="session_context") / get_session_context: temporal window. Requires session_id + target_timestamp. memory(action="get_by_id"): fetch one memory by UUID with full untruncated text. memory(action="consolidate") / consolidate_memories: merge duplicate/related memories. memory(action="cardinality") / get_memory_cardinality: count memories per agent. memory(action="supersede"): replace an old memory with a new version (old_id + new text). decision(action="store") / store_decision: record an architectural decision (domain, decision, rationale). decision(action="get") / get_decision: retrieve a past decision by domain or query.`
|
|
5969
6020
|
},
|
|
5970
6021
|
{
|
|
5971
6022
|
title: "MCP tools \u2014 task orchestration",
|
|
5972
6023
|
domain: "tool-use",
|
|
5973
6024
|
priority: "p1",
|
|
5974
|
-
content: 'task(action="create") / create_task: dispatch work (title, assigned_to, context). The ONLY dispatch path. Auto-spawns session. task(action="list") / list_tasks: query tasks by status, assignee, project. task(action="get") / get_task: fetch full task details by task_id. task(action="update") / update_task: change status (in_progress, done, blocked, cancelled) + result summary. task(action="close") / close_task: finalize a reviewed task (COO only). task(action="checkpoint") / checkpoint_task: save progress state for crash recovery. task(action="resume") / resume_employee: re-spawn an employee session for an existing task.'
|
|
6025
|
+
content: 'task(action="create") / create_task: dispatch work (title, assigned_to, context). The ONLY dispatch path. Auto-spawns session. Params: blocked_by (task ID for dependency), parent_task_id (subtask hierarchy), reviewer, complexity (routine|standard|complex|critical), budget_tokens (max token cap), budget_fallback_model, spawn_runtime (override runtime: claude|codex|opencode), spawn_model (override model). task(action="list") / list_tasks: query tasks by status, assignee, project. task(action="get") / get_task: fetch full task details by task_id. task(action="update") / update_task: change status (in_progress, done, blocked, cancelled) + result summary. task(action="close") / close_task: finalize a reviewed task (COO only). task(action="checkpoint") / checkpoint_task: save progress state for crash recovery. task(action="resume") / resume_employee: re-spawn an employee session for an existing task.'
|
|
5975
6026
|
},
|
|
5976
6027
|
{
|
|
5977
6028
|
title: "MCP tools \u2014 knowledge graph (GraphRAG)",
|
|
@@ -6001,7 +6052,7 @@ var init_platform_procedures = __esm({
|
|
|
6001
6052
|
title: "MCP tools \u2014 admin, config, and operations",
|
|
6002
6053
|
domain: "tool-use",
|
|
6003
6054
|
priority: "p1",
|
|
6004
|
-
content: 'config(action="list_employees"): view roster. config(action="agent_spend"): token usage per agent. config(action="daemon_health"): check exed status. config(action="license_status"): check license. config(action="cloud_sync"): force sync. config(action="memory_audit"): health check (dupes, null vectors). config(action="run_consolidation"): trigger memory consolidation. config(action="company_procedure", subaction="store|list|deactivate"): manage company procedures. config(action="global_procedure"): list all procedures (platform + company). config(action="create_trigger|list_triggers"): scheduled agent jobs. config(action="export_orchestration|import_orchestration"): portable org state. diagnostics(action="healthcheck|doctor|status_brief|check_update|cloud_status"): system diagnostics. mcp_ping(): daemon health + license status + tool usage stats.'
|
|
6055
|
+
content: 'config(action="list_employees"): view roster. config(action="set_agent_config"): view or change per-agent runtime + model. Call with no args to show all agents. config(action="agent_spend"): token usage per agent. config(action="daemon_health"): check exed status. config(action="license_status"): check license. config(action="cloud_sync"): force sync. Supports cloud_action param: status|sync|reupload. config(action="memory_audit"): health check (dupes, null vectors). config(action="run_consolidation"): trigger memory consolidation. config(action="worker_gate"): check spawn slot availability \u2014 alive/stale/reserved counts vs max. Use before dispatching. config(action="auto_wake_status"): orphaned tasks, blocked tasks, auto-wake retry status. config(action="orchestration_phase"): view/change org phase (phase_1_coo|phase_2_executives|phase_3_parallel_org). config(action="company_procedure", subaction="store|list|deactivate"): manage company procedures. config(action="global_procedure"): list all procedures (platform + company). config(action="create_trigger|list_triggers"): scheduled agent jobs. config(action="export_orchestration|import_orchestration"): portable org state. diagnostics(action="healthcheck|doctor|status_brief|check_update|cloud_status"): system diagnostics. diagnostics(action="pending_work_summary"): pending reviews + messages + notifications in one call. diagnostics(action="rename_employee"): rename an agent across all systems (roster, identity, DB, symlinks). diagnostics(action="tool_search"): semantic tool discovery \u2014 find relevant MCP tools by natural language query. diagnostics(action="drift"): identity drift detection \u2014 score how far an agent has drifted from its role. mcp_ping(): daemon health + license status + tool usage stats.'
|
|
6005
6056
|
}
|
|
6006
6057
|
];
|
|
6007
6058
|
PLATFORM_PROCEDURE_TITLES = new Set(
|
|
@@ -6417,6 +6468,8 @@ async function writeMemory(record) {
|
|
|
6417
6468
|
source_type: record.source_type ?? null,
|
|
6418
6469
|
tier: record.tier ?? classifyTier(record),
|
|
6419
6470
|
supersedes_id: record.supersedes_id ?? null,
|
|
6471
|
+
valid_from: record.valid_from ?? record.timestamp,
|
|
6472
|
+
invalid_at: record.invalid_at ?? null,
|
|
6420
6473
|
draft: record.draft ? 1 : 0,
|
|
6421
6474
|
memory_type: memoryType,
|
|
6422
6475
|
trajectory: record.trajectory ? JSON.stringify(record.trajectory) : null,
|
|
@@ -6435,7 +6488,8 @@ async function writeMemory(record) {
|
|
|
6435
6488
|
token_cost: record.token_cost ?? null,
|
|
6436
6489
|
audience: record.audience ?? null,
|
|
6437
6490
|
language_type: record.language_type ?? inferLanguageType(record),
|
|
6438
|
-
parent_memory_id: record.parent_memory_id ?? null
|
|
6491
|
+
parent_memory_id: record.parent_memory_id ?? null,
|
|
6492
|
+
procedure_for: record.procedure_for ?? null
|
|
6439
6493
|
};
|
|
6440
6494
|
_pendingRecords.push(dbRow);
|
|
6441
6495
|
orgBus.emit({
|
|
@@ -6490,6 +6544,8 @@ async function flushBatch() {
|
|
|
6490
6544
|
const sourceType = row.source_type ?? null;
|
|
6491
6545
|
const tier = row.tier ?? 3;
|
|
6492
6546
|
const supersedesId = row.supersedes_id ?? null;
|
|
6547
|
+
const validFrom = row.valid_from ?? row.timestamp;
|
|
6548
|
+
const invalidAt = row.invalid_at ?? null;
|
|
6493
6549
|
const draft = row.draft ? 1 : 0;
|
|
6494
6550
|
const memoryType = row.memory_type ?? "raw";
|
|
6495
6551
|
const trajectory = row.trajectory ?? null;
|
|
@@ -6509,15 +6565,16 @@ async function flushBatch() {
|
|
|
6509
6565
|
const audience = row.audience ?? null;
|
|
6510
6566
|
const languageType = row.language_type ?? null;
|
|
6511
6567
|
const parentMemoryId = row.parent_memory_id ?? null;
|
|
6568
|
+
const procedureFor = row.procedure_for ?? null;
|
|
6512
6569
|
const cols = `id, agent_id, agent_role, session_id, timestamp,
|
|
6513
6570
|
tool_name, project_name,
|
|
6514
6571
|
has_error, raw_text, vector, version, task_id, importance, status,
|
|
6515
6572
|
confidence, last_accessed,
|
|
6516
6573
|
workspace_id, document_id, user_id, char_offset, page_number,
|
|
6517
|
-
source_path, source_type, tier, supersedes_id, draft, memory_type, trajectory, content_hash,
|
|
6574
|
+
source_path, source_type, tier, supersedes_id, valid_from, invalid_at, draft, memory_type, trajectory, content_hash,
|
|
6518
6575
|
intent, outcome, domain, referenced_entities, retrieval_count,
|
|
6519
6576
|
chain_position, review_status, context_window_pct, file_paths, commit_hash,
|
|
6520
|
-
duration_ms, token_cost, audience, language_type, parent_memory_id`;
|
|
6577
|
+
duration_ms, token_cost, audience, language_type, parent_memory_id, procedure_for`;
|
|
6521
6578
|
const metaArgs = [
|
|
6522
6579
|
intent,
|
|
6523
6580
|
outcome,
|
|
@@ -6533,7 +6590,8 @@ async function flushBatch() {
|
|
|
6533
6590
|
tokenCost,
|
|
6534
6591
|
audience,
|
|
6535
6592
|
languageType,
|
|
6536
|
-
parentMemoryId
|
|
6593
|
+
parentMemoryId,
|
|
6594
|
+
procedureFor
|
|
6537
6595
|
];
|
|
6538
6596
|
const baseArgs = [
|
|
6539
6597
|
row.id,
|
|
@@ -6562,6 +6620,8 @@ async function flushBatch() {
|
|
|
6562
6620
|
sourceType,
|
|
6563
6621
|
tier,
|
|
6564
6622
|
supersedesId,
|
|
6623
|
+
validFrom,
|
|
6624
|
+
invalidAt,
|
|
6565
6625
|
draft,
|
|
6566
6626
|
memoryType,
|
|
6567
6627
|
trajectory,
|
|
@@ -6569,8 +6629,8 @@ async function flushBatch() {
|
|
|
6569
6629
|
];
|
|
6570
6630
|
return {
|
|
6571
6631
|
sql: hasVector ? `INSERT OR IGNORE INTO memories (${cols})
|
|
6572
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
|
|
6573
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
6632
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
|
|
6633
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
6574
6634
|
args: hasVector ? [...baseArgs, vectorToBlob(row.vector), ...sharedArgs, ...metaArgs] : [...baseArgs, ...sharedArgs, ...metaArgs]
|
|
6575
6635
|
};
|
|
6576
6636
|
};
|
|
@@ -6686,6 +6746,12 @@ async function searchMemories(queryVector, agentId, options) {
|
|
|
6686
6746
|
AND vector IS NOT NULL${statusFilter}${draftFilter}
|
|
6687
6747
|
AND COALESCE(confidence, 0.7) >= 0.3`;
|
|
6688
6748
|
const args = [agentId];
|
|
6749
|
+
if (options?.asOf) {
|
|
6750
|
+
sql += ` AND (valid_from IS NULL OR valid_from <= ?) AND (invalid_at IS NULL OR invalid_at > ?)`;
|
|
6751
|
+
args.push(options.asOf, options.asOf);
|
|
6752
|
+
} else {
|
|
6753
|
+
sql += ` AND invalid_at IS NULL`;
|
|
6754
|
+
}
|
|
6689
6755
|
const scope = buildWikiScopeFilter(options, "");
|
|
6690
6756
|
sql += scope.clause;
|
|
6691
6757
|
args.push(...scope.args);
|
|
@@ -8157,6 +8223,19 @@ __export(hybrid_search_exports, {
|
|
|
8157
8223
|
rrfMerge: () => rrfMerge,
|
|
8158
8224
|
rrfMergeMulti: () => rrfMergeMulti
|
|
8159
8225
|
});
|
|
8226
|
+
function buildTemporalFilter(options, columnPrefix) {
|
|
8227
|
+
const asOf = options?.asOf;
|
|
8228
|
+
if (asOf) {
|
|
8229
|
+
return {
|
|
8230
|
+
clause: ` AND (${columnPrefix}valid_from IS NULL OR ${columnPrefix}valid_from <= ?) AND (${columnPrefix}invalid_at IS NULL OR ${columnPrefix}invalid_at > ?)`,
|
|
8231
|
+
args: [asOf, asOf]
|
|
8232
|
+
};
|
|
8233
|
+
}
|
|
8234
|
+
return {
|
|
8235
|
+
clause: ` AND ${columnPrefix}invalid_at IS NULL`,
|
|
8236
|
+
args: []
|
|
8237
|
+
};
|
|
8238
|
+
}
|
|
8160
8239
|
function appendMemoryTypeFilter(sql, args, column, options) {
|
|
8161
8240
|
if (options?.memoryTypes && options.memoryTypes.length > 0) {
|
|
8162
8241
|
const uniqueTypes = [...new Set(options.memoryTypes)];
|
|
@@ -8389,6 +8468,9 @@ async function estimateCardinality(agentId, options) {
|
|
|
8389
8468
|
AND COALESCE(status, 'active') = 'active'
|
|
8390
8469
|
AND COALESCE(confidence, 0.7) >= 0.3`;
|
|
8391
8470
|
const args = [agentId];
|
|
8471
|
+
const temporal = buildTemporalFilter(options, "");
|
|
8472
|
+
sql += temporal.clause;
|
|
8473
|
+
args.push(...temporal.args);
|
|
8392
8474
|
const rawVisibility = buildRawVisibilityFilter(options, "");
|
|
8393
8475
|
sql += rawVisibility.clause;
|
|
8394
8476
|
args.push(...rawVisibility.args);
|
|
@@ -8517,6 +8599,9 @@ async function ftsQuery(client, matchExpr, agentId, options, limit) {
|
|
|
8517
8599
|
AND m.agent_id = ?${statusFilter}${draftFilter}
|
|
8518
8600
|
AND COALESCE(m.confidence, 0.7) >= 0.3`;
|
|
8519
8601
|
const args = [matchExpr, agentId];
|
|
8602
|
+
const temporal = buildTemporalFilter(options, "m.");
|
|
8603
|
+
sql += temporal.clause;
|
|
8604
|
+
args.push(...temporal.args);
|
|
8520
8605
|
const scope = buildWikiScopeFilter(options, "m.");
|
|
8521
8606
|
sql += scope.clause;
|
|
8522
8607
|
args.push(...scope.args);
|
|
@@ -8629,6 +8714,9 @@ async function recentRecords(agentId, options, limit, textFilter) {
|
|
|
8629
8714
|
WHERE agent_id = ?${statusFilter}${draftFilter}
|
|
8630
8715
|
AND COALESCE(confidence, 0.7) >= 0.3`;
|
|
8631
8716
|
const args = [agentId];
|
|
8717
|
+
const temporal = buildTemporalFilter(options, "");
|
|
8718
|
+
sql += temporal.clause;
|
|
8719
|
+
args.push(...temporal.args);
|
|
8632
8720
|
const scope = buildWikiScopeFilter(options, "");
|
|
8633
8721
|
sql += scope.clause;
|
|
8634
8722
|
args.push(...scope.args);
|
|
@@ -8729,6 +8817,9 @@ async function trajectoryBypass(queryText, agentId, options, limit) {
|
|
|
8729
8817
|
AND json_extract(trajectory, '$.tool') = ?
|
|
8730
8818
|
AND agent_id = ?${statusFilter}${draftFilter}`;
|
|
8731
8819
|
const args = [toolName, agentId];
|
|
8820
|
+
const temporal = buildTemporalFilter(options, "");
|
|
8821
|
+
sql += temporal.clause;
|
|
8822
|
+
args.push(...temporal.args);
|
|
8732
8823
|
const rawVisibility = buildRawVisibilityFilter(options, "");
|
|
8733
8824
|
sql += rawVisibility.clause;
|
|
8734
8825
|
args.push(...rawVisibility.args);
|
|
@@ -9110,7 +9201,11 @@ function registerRecallMyMemory(server) {
|
|
|
9110
9201
|
include_source: z.boolean().optional().default(false).describe(
|
|
9111
9202
|
"When true, attach parent document metadata (filename, mime, source_type) to each result. Default false."
|
|
9112
9203
|
),
|
|
9113
|
-
retrieval_mode: z.enum(RETRIEVAL_MODES).optional().default("all").describe(`Typed retrieval mode. ${formatRetrievalModes()}`)
|
|
9204
|
+
retrieval_mode: z.enum(RETRIEVAL_MODES).optional().default("all").describe(`Typed retrieval mode. ${formatRetrievalModes()}`),
|
|
9205
|
+
kind: z.string().optional().describe(
|
|
9206
|
+
"Filter by memory_type: decision, procedure, observation, raw, conversation, behavior."
|
|
9207
|
+
),
|
|
9208
|
+
as_of: z.string().optional().describe("ISO 8601 timestamp for time-travel query. Returns facts valid at that point in time.")
|
|
9114
9209
|
}
|
|
9115
9210
|
},
|
|
9116
9211
|
async ({
|
|
@@ -9127,7 +9222,9 @@ function registerRecallMyMemory(server) {
|
|
|
9127
9222
|
workspace_id,
|
|
9128
9223
|
user_id,
|
|
9129
9224
|
include_source,
|
|
9130
|
-
retrieval_mode
|
|
9225
|
+
retrieval_mode,
|
|
9226
|
+
kind,
|
|
9227
|
+
as_of
|
|
9131
9228
|
}) => {
|
|
9132
9229
|
try {
|
|
9133
9230
|
if (!recent && !query) {
|
|
@@ -9147,7 +9244,9 @@ function registerRecallMyMemory(server) {
|
|
|
9147
9244
|
workspaceId: workspace_id,
|
|
9148
9245
|
includeSource: include_source,
|
|
9149
9246
|
includeDrafts: true,
|
|
9150
|
-
...user_id !== void 0 ? { userId: user_id } : {}
|
|
9247
|
+
...user_id !== void 0 ? { userId: user_id } : {},
|
|
9248
|
+
...kind ? { memoryType: kind } : {},
|
|
9249
|
+
...as_of ? { asOf: as_of } : {}
|
|
9151
9250
|
}, retrieval_mode);
|
|
9152
9251
|
let results;
|
|
9153
9252
|
if (recent) {
|
|
@@ -9612,7 +9711,7 @@ var init_license = __esm({
|
|
|
9612
9711
|
LICENSE_PATH = path17.join(EXE_AI_DIR, "license.key");
|
|
9613
9712
|
CACHE_PATH = path17.join(EXE_AI_DIR, "license-cache.json");
|
|
9614
9713
|
DEVICE_ID_PATH = path17.join(EXE_AI_DIR, "device-id");
|
|
9615
|
-
API_BASE = "https://askexe.com/cloud";
|
|
9714
|
+
API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://askexe.com/cloud";
|
|
9616
9715
|
RETRY_DELAY_MS = 500;
|
|
9617
9716
|
LICENSE_PUBLIC_KEY_PEM = `-----BEGIN PUBLIC KEY-----
|
|
9618
9717
|
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeHztAMOpR/ZMh+rWuOASjEZ54CGY
|
|
@@ -9784,10 +9883,12 @@ function registerStoreMemory(server) {
|
|
|
9784
9883
|
project_name: z3.string().optional().describe("Project name"),
|
|
9785
9884
|
has_error: z3.boolean().optional().default(false).describe("Whether this memory is error-related"),
|
|
9786
9885
|
source_path: z3.string().optional().describe("Original file path, URL, or document reference"),
|
|
9787
|
-
source_type: z3.string().optional().describe("Content type: text, pdf, image, audio, video, url, document")
|
|
9886
|
+
source_type: z3.string().optional().describe("Content type: text, pdf, image, audio, video, url, document"),
|
|
9887
|
+
kind: z3.string().optional().describe("Memory type: decision, procedure, observation, raw, conversation, behavior"),
|
|
9888
|
+
procedure_for: z3.string().optional().describe("Domain this procedure applies to (only for kind='procedure')")
|
|
9788
9889
|
}
|
|
9789
9890
|
},
|
|
9790
|
-
async ({ text: text3, query, tool_name, project_name, has_error, source_path, source_type }) => {
|
|
9891
|
+
async ({ text: text3, query, tool_name, project_name, has_error, source_path, source_type, kind, procedure_for }) => {
|
|
9791
9892
|
const resolvedText = text3 ?? query;
|
|
9792
9893
|
if (!resolvedText) {
|
|
9793
9894
|
return {
|
|
@@ -9832,7 +9933,9 @@ function registerStoreMemory(server) {
|
|
|
9832
9933
|
raw_text: resolvedText,
|
|
9833
9934
|
vector,
|
|
9834
9935
|
source_path: source_path ?? null,
|
|
9835
|
-
source_type: source_type ?? null
|
|
9936
|
+
source_type: source_type ?? null,
|
|
9937
|
+
memory_type: kind ?? void 0,
|
|
9938
|
+
procedure_for: kind === "procedure" ? procedure_for ?? null : null
|
|
9836
9939
|
});
|
|
9837
9940
|
await flushBatch();
|
|
9838
9941
|
if (needsBackfill) {
|
|
@@ -10133,9 +10236,9 @@ function truncate(text3, max) {
|
|
|
10133
10236
|
const marker = ` \u2026 [truncated; +${text3.length - max} chars]`;
|
|
10134
10237
|
return text3.slice(0, Math.max(0, max - marker.length)) + marker;
|
|
10135
10238
|
}
|
|
10136
|
-
async function searchMemories2(query, agentId, limit) {
|
|
10239
|
+
async function searchMemories2(query, agentId, limit, memoryType) {
|
|
10137
10240
|
const { hybridSearch: hybridSearch2 } = await Promise.resolve().then(() => (init_hybrid_search(), hybrid_search_exports));
|
|
10138
|
-
const results = await hybridSearch2(query, agentId, { limit });
|
|
10241
|
+
const results = await hybridSearch2(query, agentId, { limit, memoryType });
|
|
10139
10242
|
return results.map((r, i) => ({
|
|
10140
10243
|
source: "memory",
|
|
10141
10244
|
score: 1 - i / Math.max(results.length, 1),
|
|
@@ -10259,7 +10362,7 @@ async function unifiedSearch(query, agentId, opts) {
|
|
|
10259
10362
|
const perSourceLimit = Math.max(Math.ceil(limit * 1.5), 5);
|
|
10260
10363
|
const promises = [];
|
|
10261
10364
|
if (sources.includes("memory")) {
|
|
10262
|
-
promises.push(searchMemories2(query, agentId, perSourceLimit));
|
|
10365
|
+
promises.push(searchMemories2(query, agentId, perSourceLimit, opts?.memoryType));
|
|
10263
10366
|
}
|
|
10264
10367
|
if (sources.includes("conversations")) {
|
|
10265
10368
|
promises.push(searchConversations(query, perSourceLimit));
|
|
@@ -10303,7 +10406,8 @@ function registerSearchEverything(server) {
|
|
|
10303
10406
|
sources: z5.array(z5.enum(["memory", "conversations", "wiki"])).optional().describe(
|
|
10304
10407
|
"Which sources to search (default: all). Options: memory, conversations, wiki"
|
|
10305
10408
|
),
|
|
10306
|
-
limit: z5.coerce.number().int().min(1).max(50).optional().default(10).describe("Max results to return (default 10, max 50)")
|
|
10409
|
+
limit: z5.coerce.number().int().min(1).max(50).optional().default(10).describe("Max results to return (default 10, max 50)"),
|
|
10410
|
+
kind: z5.string().optional().describe("Filter memories by memory_type: decision, procedure, observation, raw, conversation, behavior.")
|
|
10307
10411
|
}
|
|
10308
10412
|
},
|
|
10309
10413
|
async (params) => {
|
|
@@ -10312,7 +10416,8 @@ function registerSearchEverything(server) {
|
|
|
10312
10416
|
const sources = params.sources;
|
|
10313
10417
|
const results = await unifiedSearch(params.query, agentId, {
|
|
10314
10418
|
limit: params.limit,
|
|
10315
|
-
sources
|
|
10419
|
+
sources,
|
|
10420
|
+
memoryType: params.kind
|
|
10316
10421
|
});
|
|
10317
10422
|
if (results.length === 0) {
|
|
10318
10423
|
return {
|
|
@@ -10558,6 +10663,7 @@ async function selectUnconsolidated(client, limit = 200) {
|
|
|
10558
10663
|
sql: `SELECT id, agent_id, project_name, tool_name, raw_text, timestamp
|
|
10559
10664
|
FROM memories
|
|
10560
10665
|
WHERE consolidated = 0
|
|
10666
|
+
AND COALESCE(memory_type, 'raw') != 'procedure'
|
|
10561
10667
|
ORDER BY timestamp DESC
|
|
10562
10668
|
LIMIT ?`,
|
|
10563
10669
|
args: [limit]
|
|
@@ -10901,7 +11007,8 @@ async function isUserIdle(client, idleMinutes = 30) {
|
|
|
10901
11007
|
async function countUnconsolidated(client) {
|
|
10902
11008
|
const result3 = await client.execute({
|
|
10903
11009
|
sql: `SELECT COUNT(*) as cnt FROM memories
|
|
10904
|
-
WHERE consolidated = 0
|
|
11010
|
+
WHERE consolidated = 0
|
|
11011
|
+
AND COALESCE(memory_type, 'raw') != 'procedure'`,
|
|
10905
11012
|
args: []
|
|
10906
11013
|
});
|
|
10907
11014
|
return Number(result3.rows[0]?.cnt ?? 0);
|
|
@@ -11138,15 +11245,74 @@ function buildLegacyMemoryHandlers() {
|
|
|
11138
11245
|
registerGetMemoryCardinality(localServer);
|
|
11139
11246
|
return tools;
|
|
11140
11247
|
}
|
|
11248
|
+
async function handleSupersede(input) {
|
|
11249
|
+
const oldId = input.old_id;
|
|
11250
|
+
const text3 = input.text ?? input.query;
|
|
11251
|
+
if (!oldId || !text3) {
|
|
11252
|
+
return errorResult('memory action "supersede" requires old_id and text');
|
|
11253
|
+
}
|
|
11254
|
+
try {
|
|
11255
|
+
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
11256
|
+
const { getActiveAgent: getActiveAgent2 } = await Promise.resolve().then(() => (init_active_agent(), active_agent_exports));
|
|
11257
|
+
const { writeMemory: writeMemory2, flushBatch: flushBatch2 } = await Promise.resolve().then(() => (init_store(), store_exports));
|
|
11258
|
+
const { randomUUID: randomUUID12 } = await import("crypto");
|
|
11259
|
+
const client = getClient2();
|
|
11260
|
+
const now2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
11261
|
+
const oldRow = await client.execute({
|
|
11262
|
+
sql: `SELECT id, agent_id, agent_role, project_name FROM memories WHERE id = ?`,
|
|
11263
|
+
args: [oldId]
|
|
11264
|
+
});
|
|
11265
|
+
if (oldRow.rows.length === 0) {
|
|
11266
|
+
return errorResult(`Memory not found: ${oldId}`);
|
|
11267
|
+
}
|
|
11268
|
+
await client.execute({
|
|
11269
|
+
sql: `UPDATE memories SET invalid_at = ? WHERE id = ?`,
|
|
11270
|
+
args: [now2, oldId]
|
|
11271
|
+
});
|
|
11272
|
+
const { agentId, agentRole } = getActiveAgent2();
|
|
11273
|
+
const sessionId = process.env.SESSION_ID ?? "manual";
|
|
11274
|
+
const { getProjectName: getProjectName2 } = await Promise.resolve().then(() => (init_project_name(), project_name_exports));
|
|
11275
|
+
const projectName = input.project_name ?? getProjectName2(process.cwd());
|
|
11276
|
+
const newId = randomUUID12();
|
|
11277
|
+
await writeMemory2({
|
|
11278
|
+
id: newId,
|
|
11279
|
+
agent_id: agentId,
|
|
11280
|
+
agent_role: agentRole,
|
|
11281
|
+
session_id: sessionId,
|
|
11282
|
+
timestamp: now2,
|
|
11283
|
+
tool_name: "manual",
|
|
11284
|
+
project_name: projectName,
|
|
11285
|
+
has_error: false,
|
|
11286
|
+
raw_text: text3,
|
|
11287
|
+
vector: null,
|
|
11288
|
+
valid_from: now2,
|
|
11289
|
+
supersedes_id: oldId,
|
|
11290
|
+
importance: 7,
|
|
11291
|
+
memory_type: "adr"
|
|
11292
|
+
});
|
|
11293
|
+
await flushBatch2();
|
|
11294
|
+
return {
|
|
11295
|
+
content: [{
|
|
11296
|
+
type: "text",
|
|
11297
|
+
text: `Superseded memory ${oldId.slice(0, 8)}\u2026 \u2192 new memory ${newId.slice(0, 8)}\u2026
|
|
11298
|
+
Old memory invalid_at set to ${now2}.
|
|
11299
|
+
New memory id: ${newId}`
|
|
11300
|
+
}]
|
|
11301
|
+
};
|
|
11302
|
+
} catch (err) {
|
|
11303
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
11304
|
+
return errorResult(`Supersede failed: ${msg}`);
|
|
11305
|
+
}
|
|
11306
|
+
}
|
|
11141
11307
|
function registerMemory(server) {
|
|
11142
11308
|
const legacyTools = buildLegacyMemoryHandlers();
|
|
11143
11309
|
server.registerTool(
|
|
11144
11310
|
"memory",
|
|
11145
11311
|
{
|
|
11146
11312
|
title: "Memory",
|
|
11147
|
-
description: "Consolidated memory domain tool. Actions: recall, ask_team, store, commit, search, session_context, get_by_id, consolidate, cardinality. Legacy memory tools remain available during migration.",
|
|
11313
|
+
description: "Consolidated memory domain tool. Actions: recall, ask_team, store, commit, search, session_context, get_by_id, consolidate, cardinality, supersede. Legacy memory tools remain available during migration.",
|
|
11148
11314
|
inputSchema: {
|
|
11149
|
-
action: z10.enum(["recall", "ask_team", "store", "commit", "search", "session_context", "consolidate", "cardinality"]).describe("Memory operation to perform"),
|
|
11315
|
+
action: z10.enum(["recall", "ask_team", "store", "commit", "search", "session_context", "consolidate", "cardinality", "supersede"]).describe("Memory operation to perform"),
|
|
11150
11316
|
query: z10.string().optional().describe("Search query. Also accepted as store text alias."),
|
|
11151
11317
|
text: z10.string().optional().describe("Memory text for action=store"),
|
|
11152
11318
|
summary: z10.string().optional().describe("High-importance summary for action=commit"),
|
|
@@ -11179,7 +11345,11 @@ function registerMemory(server) {
|
|
|
11179
11345
|
window_size: z10.number().optional().describe("Window size for action=session_context"),
|
|
11180
11346
|
max_clusters: z10.coerce.number().optional().describe("Max clusters for action=consolidate"),
|
|
11181
11347
|
model: z10.string().optional().describe("Model for action=consolidate"),
|
|
11182
|
-
agent_id: z10.string().optional().describe("Agent filter for action=cardinality")
|
|
11348
|
+
agent_id: z10.string().optional().describe("Agent filter for action=cardinality"),
|
|
11349
|
+
kind: z10.string().optional().describe("Filter by memory_type: decision, procedure, observation, raw, conversation, behavior. For action=recall and action=search."),
|
|
11350
|
+
procedure_for: z10.string().optional().describe("Domain this procedure applies to (only for storing procedure-type memories)."),
|
|
11351
|
+
as_of: z10.string().optional().describe("ISO 8601 timestamp for time-travel query. Returns facts valid at that point in time. For action=recall."),
|
|
11352
|
+
old_id: z10.string().optional().describe("UUID of memory to supersede. For action=supersede.")
|
|
11183
11353
|
}
|
|
11184
11354
|
},
|
|
11185
11355
|
async (input, extra) => {
|
|
@@ -11188,6 +11358,9 @@ function registerMemory(server) {
|
|
|
11188
11358
|
if (!legacyToolName) {
|
|
11189
11359
|
return errorResult(`Unknown memory action: ${String(input.action)}`);
|
|
11190
11360
|
}
|
|
11361
|
+
if (action === "supersede") {
|
|
11362
|
+
return handleSupersede(input);
|
|
11363
|
+
}
|
|
11191
11364
|
const { action: _action, ...legacyArgs } = input;
|
|
11192
11365
|
const missing = missingRequiredFields(legacyArgs, REQUIRED_FIELDS[action]);
|
|
11193
11366
|
if (missing.length > 0) {
|
|
@@ -11256,7 +11429,8 @@ var init_memory2 = __esm({
|
|
|
11256
11429
|
session_context: "get_session_context",
|
|
11257
11430
|
get_by_id: "get_memory_by_id",
|
|
11258
11431
|
consolidate: "consolidate_memories",
|
|
11259
|
-
cardinality: "get_memory_cardinality"
|
|
11432
|
+
cardinality: "get_memory_cardinality",
|
|
11433
|
+
supersede: "__inline_supersede__"
|
|
11260
11434
|
};
|
|
11261
11435
|
REQUIRED_FIELDS = {
|
|
11262
11436
|
recall: [],
|
|
@@ -11267,7 +11441,8 @@ var init_memory2 = __esm({
|
|
|
11267
11441
|
session_context: ["session_id", "target_timestamp"],
|
|
11268
11442
|
get_by_id: ["id"],
|
|
11269
11443
|
consolidate: [],
|
|
11270
|
-
cardinality: []
|
|
11444
|
+
cardinality: [],
|
|
11445
|
+
supersede: ["old_id", "text"]
|
|
11271
11446
|
};
|
|
11272
11447
|
}
|
|
11273
11448
|
});
|
|
@@ -12717,9 +12892,13 @@ function getDispatchedBy(sessionKey) {
|
|
|
12717
12892
|
}
|
|
12718
12893
|
}
|
|
12719
12894
|
function resolveExeSession() {
|
|
12895
|
+
if (process.env.EXE_SESSION_NAME) {
|
|
12896
|
+
return extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
|
|
12897
|
+
}
|
|
12720
12898
|
const mySession = getMySession();
|
|
12721
12899
|
if (!mySession) return null;
|
|
12722
12900
|
const fromSessionName = extractRootExe(mySession);
|
|
12901
|
+
let candidate = null;
|
|
12723
12902
|
try {
|
|
12724
12903
|
const key = getSessionKey();
|
|
12725
12904
|
const parentExe = getParentExe(key);
|
|
@@ -12730,13 +12909,47 @@ function resolveExeSession() {
|
|
|
12730
12909
|
`[tmux-routing] WARN: cache says "${fromCache}" but session name says "${fromSessionName}". Trusting session name.
|
|
12731
12910
|
`
|
|
12732
12911
|
);
|
|
12733
|
-
|
|
12912
|
+
candidate = fromSessionName;
|
|
12913
|
+
} else {
|
|
12914
|
+
candidate = fromCache;
|
|
12734
12915
|
}
|
|
12735
|
-
return fromCache;
|
|
12736
12916
|
}
|
|
12737
12917
|
} catch {
|
|
12738
12918
|
}
|
|
12739
|
-
|
|
12919
|
+
if (!candidate) {
|
|
12920
|
+
candidate = fromSessionName ?? mySession;
|
|
12921
|
+
}
|
|
12922
|
+
if (candidate && isRootSession(candidate)) {
|
|
12923
|
+
try {
|
|
12924
|
+
const transport = getTransport();
|
|
12925
|
+
const liveSessions = transport.listSessions();
|
|
12926
|
+
if (!liveSessions.includes(candidate)) {
|
|
12927
|
+
const liveRoots = liveSessions.filter((s) => isRootSession(s));
|
|
12928
|
+
if (liveRoots.length === 1) {
|
|
12929
|
+
process.stderr.write(
|
|
12930
|
+
`[tmux-routing] WARN: resolved session "${candidate}" is dead. Using live coordinator "${liveRoots[0]}".
|
|
12931
|
+
`
|
|
12932
|
+
);
|
|
12933
|
+
return liveRoots[0];
|
|
12934
|
+
} else if (liveRoots.length > 1) {
|
|
12935
|
+
const base = candidate.replace(/\d+$/, "");
|
|
12936
|
+
const match = liveRoots.find((s) => s.startsWith(base));
|
|
12937
|
+
const chosen = match ?? liveRoots[0];
|
|
12938
|
+
process.stderr.write(
|
|
12939
|
+
`[tmux-routing] WARN: resolved session "${candidate}" is dead. ${liveRoots.length} live roots found, using "${chosen}".
|
|
12940
|
+
`
|
|
12941
|
+
);
|
|
12942
|
+
return chosen;
|
|
12943
|
+
}
|
|
12944
|
+
process.stderr.write(
|
|
12945
|
+
`[tmux-routing] WARN: resolved session "${candidate}" is dead and no live coordinator found.
|
|
12946
|
+
`
|
|
12947
|
+
);
|
|
12948
|
+
}
|
|
12949
|
+
} catch {
|
|
12950
|
+
}
|
|
12951
|
+
}
|
|
12952
|
+
return candidate;
|
|
12740
12953
|
}
|
|
12741
12954
|
function isEmployeeAlive(sessionName) {
|
|
12742
12955
|
return getTransport().isAlive(sessionName);
|
|
@@ -13138,7 +13351,12 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
13138
13351
|
}
|
|
13139
13352
|
const spawnCwd = opts?.cwd ?? projectDir;
|
|
13140
13353
|
const useExeAgent = !!(opts?.model && opts?.provider);
|
|
13141
|
-
const
|
|
13354
|
+
const baseRtConfig = getAgentRuntime(employeeName);
|
|
13355
|
+
const agentRtConfig = {
|
|
13356
|
+
...baseRtConfig,
|
|
13357
|
+
...opts?.runtimeOverride ? { runtime: opts.runtimeOverride } : {},
|
|
13358
|
+
...opts?.modelOverride ? { model: opts.modelOverride } : {}
|
|
13359
|
+
};
|
|
13142
13360
|
const useCodex = !useExeAgent && agentRtConfig.runtime === "codex";
|
|
13143
13361
|
const useOpencode = !useExeAgent && !useCodex && agentRtConfig.runtime === "opencode";
|
|
13144
13362
|
const ccProvider = useExeAgent || useCodex || useOpencode ? DEFAULT_PROVIDER : detectActiveProvider();
|
|
@@ -13756,8 +13974,8 @@ ${scopeMismatchWarning}` : scopeMismatchWarning;
|
|
|
13756
13974
|
const complexity = input.complexity ?? "standard";
|
|
13757
13975
|
const sessionScope = earlySessionScope;
|
|
13758
13976
|
await client.execute({
|
|
13759
|
-
sql: `INSERT INTO tasks (id, title, assigned_to, assigned_by, project_name, priority, status, task_file, blocked_by, parent_task_id, reviewer, context, complexity, budget_tokens, budget_fallback_model, tokens_used, tokens_warned_at, session_scope, created_at, updated_at)
|
|
13760
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
13977
|
+
sql: `INSERT INTO tasks (id, title, assigned_to, assigned_by, project_name, priority, status, task_file, blocked_by, parent_task_id, reviewer, context, complexity, budget_tokens, budget_fallback_model, tokens_used, tokens_warned_at, session_scope, spawn_runtime, spawn_model, created_at, updated_at)
|
|
13978
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
13761
13979
|
args: [
|
|
13762
13980
|
id,
|
|
13763
13981
|
input.title,
|
|
@@ -13777,6 +13995,8 @@ ${scopeMismatchWarning}` : scopeMismatchWarning;
|
|
|
13777
13995
|
0,
|
|
13778
13996
|
null,
|
|
13779
13997
|
sessionScope,
|
|
13998
|
+
input.spawnRuntime ?? null,
|
|
13999
|
+
input.spawnModel ?? null,
|
|
13780
14000
|
now2,
|
|
13781
14001
|
now2
|
|
13782
14002
|
]
|
|
@@ -13833,7 +14053,9 @@ ${input.context}
|
|
|
13833
14053
|
budgetTokens: input.budgetTokens ?? null,
|
|
13834
14054
|
budgetFallbackModel: input.budgetFallbackModel ?? null,
|
|
13835
14055
|
tokensUsed: 0,
|
|
13836
|
-
tokensWarnedAt: null
|
|
14056
|
+
tokensWarnedAt: null,
|
|
14057
|
+
spawnRuntime: input.spawnRuntime ?? null,
|
|
14058
|
+
spawnModel: input.spawnModel ?? null
|
|
13837
14059
|
};
|
|
13838
14060
|
}
|
|
13839
14061
|
async function listTasks(input) {
|
|
@@ -13883,7 +14105,9 @@ async function listTasks(input) {
|
|
|
13883
14105
|
budgetTokens: r.budget_tokens !== null ? Number(r.budget_tokens) : null,
|
|
13884
14106
|
budgetFallbackModel: r.budget_fallback_model !== null ? String(r.budget_fallback_model) : null,
|
|
13885
14107
|
tokensUsed: Number(r.tokens_used ?? 0),
|
|
13886
|
-
tokensWarnedAt: r.tokens_warned_at !== null ? Number(r.tokens_warned_at) : null
|
|
14108
|
+
tokensWarnedAt: r.tokens_warned_at !== null ? Number(r.tokens_warned_at) : null,
|
|
14109
|
+
spawnRuntime: r.spawn_runtime !== null && r.spawn_runtime !== void 0 ? String(r.spawn_runtime) : null,
|
|
14110
|
+
spawnModel: r.spawn_model !== null && r.spawn_model !== void 0 ? String(r.spawn_model) : null
|
|
13887
14111
|
}));
|
|
13888
14112
|
}
|
|
13889
14113
|
function isTmuxSessionAlive(identifier) {
|
|
@@ -14833,6 +15057,8 @@ async function updateTask(input) {
|
|
|
14833
15057
|
budgetFallbackModel: row.budget_fallback_model !== void 0 && row.budget_fallback_model !== null ? String(row.budget_fallback_model) : null,
|
|
14834
15058
|
tokensUsed: Number(row.tokens_used ?? 0),
|
|
14835
15059
|
tokensWarnedAt: row.tokens_warned_at !== void 0 && row.tokens_warned_at !== null ? Number(row.tokens_warned_at) : null,
|
|
15060
|
+
spawnRuntime: row.spawn_runtime !== void 0 && row.spawn_runtime !== null ? String(row.spawn_runtime) : null,
|
|
15061
|
+
spawnModel: row.spawn_model !== void 0 && row.spawn_model !== null ? String(row.spawn_model) : null,
|
|
14836
15062
|
nextTask
|
|
14837
15063
|
};
|
|
14838
15064
|
}
|
|
@@ -15572,10 +15798,12 @@ function registerCreateTask(server) {
|
|
|
15572
15798
|
parent_task_id: z12.string().optional().describe("Parent task ID or slug. Links this task as a subtask."),
|
|
15573
15799
|
reviewer: z12.string().optional().describe("Who should review this task when done. Defaults to assigner."),
|
|
15574
15800
|
budget_tokens: z12.number().optional().describe("Max tokens allowed for this task (null = unlimited)"),
|
|
15575
|
-
budget_fallback_model: z12.string().optional().describe("Model to route to when budget is exhausted")
|
|
15801
|
+
budget_fallback_model: z12.string().optional().describe("Model to route to when budget is exhausted"),
|
|
15802
|
+
spawn_runtime: z12.string().optional().describe("Override runtime for spawned session (e.g., 'claude', 'codex', 'opencode')"),
|
|
15803
|
+
spawn_model: z12.string().optional().describe("Override model for spawned session (e.g., 'claude-sonnet-4.6', 'claude-haiku-4.5')")
|
|
15576
15804
|
}
|
|
15577
15805
|
},
|
|
15578
|
-
async ({ title, assigned_to, project_name, priority, complexity, context, blocked_by, parent_task_id, reviewer, budget_tokens, budget_fallback_model }) => {
|
|
15806
|
+
async ({ title, assigned_to, project_name, priority, complexity, context, blocked_by, parent_task_id, reviewer, budget_tokens, budget_fallback_model, spawn_runtime, spawn_model }) => {
|
|
15579
15807
|
if (!isCoordinatorName(assigned_to)) {
|
|
15580
15808
|
const license = getLicenseSync();
|
|
15581
15809
|
if (license.plan === "free") {
|
|
@@ -15603,6 +15831,8 @@ function registerCreateTask(server) {
|
|
|
15603
15831
|
reviewer,
|
|
15604
15832
|
budgetTokens: budget_tokens,
|
|
15605
15833
|
budgetFallbackModel: budget_fallback_model,
|
|
15834
|
+
spawnRuntime: spawn_runtime,
|
|
15835
|
+
spawnModel: spawn_model,
|
|
15606
15836
|
// Skip internal dispatch — we handle it below with autoInstance
|
|
15607
15837
|
// support. Without this, createTask fires dispatchTaskToEmployee
|
|
15608
15838
|
// (no autoInstance) in parallel, racing with our ensureEmployee
|
|
@@ -15640,7 +15870,9 @@ function registerCreateTask(server) {
|
|
|
15640
15870
|
const cfg = loadConfigSync2();
|
|
15641
15871
|
const result3 = ensureEmployee(assigned_to, exeSession, process.cwd(), {
|
|
15642
15872
|
autoInstance: useAutoInstance,
|
|
15643
|
-
maxAutoInstances: useAutoInstance ? cfg.sessionLifecycle.maxAutoInstances : void 0
|
|
15873
|
+
maxAutoInstances: useAutoInstance ? cfg.sessionLifecycle.maxAutoInstances : void 0,
|
|
15874
|
+
runtimeOverride: spawn_runtime ?? void 0,
|
|
15875
|
+
modelOverride: spawn_model ?? void 0
|
|
15644
15876
|
});
|
|
15645
15877
|
switch (result3.status) {
|
|
15646
15878
|
case "intercom_sent":
|
|
@@ -15881,6 +16113,14 @@ function registerGetTask(server) {
|
|
|
15881
16113
|
}
|
|
15882
16114
|
}
|
|
15883
16115
|
}
|
|
16116
|
+
const spawnRuntime = row.spawn_runtime ? String(row.spawn_runtime) : null;
|
|
16117
|
+
const spawnModel = row.spawn_model ? String(row.spawn_model) : null;
|
|
16118
|
+
if (spawnRuntime || spawnModel) {
|
|
16119
|
+
lines.push("");
|
|
16120
|
+
lines.push("**Spawn Override:**");
|
|
16121
|
+
if (spawnRuntime) lines.push(`Runtime: ${spawnRuntime}`);
|
|
16122
|
+
if (spawnModel) lines.push(`Model: ${spawnModel}`);
|
|
16123
|
+
}
|
|
15884
16124
|
if (row.context) {
|
|
15885
16125
|
lines.push("", "## Context", "", contextText);
|
|
15886
16126
|
}
|
|
@@ -16343,6 +16583,8 @@ function registerTask(server) {
|
|
|
16343
16583
|
reviewer: z19.string().optional().describe("Reviewer for action=create"),
|
|
16344
16584
|
budget_tokens: z19.number().optional().describe("Max token budget for action=create"),
|
|
16345
16585
|
budget_fallback_model: z19.string().optional().describe("Fallback model for action=create"),
|
|
16586
|
+
spawn_runtime: z19.string().optional().describe("Override runtime for spawned session (e.g., 'claude', 'codex', 'opencode') for action=create"),
|
|
16587
|
+
spawn_model: z19.string().optional().describe("Override model for spawned session (e.g., 'claude-sonnet-4.6') for action=create"),
|
|
16346
16588
|
status: z19.enum(["open", "in_progress", "done", "needs_review", "blocked", "cancelled", "closed"]).optional().describe("Status for action=update/list/close"),
|
|
16347
16589
|
result: z19.string().optional().describe("Result summary for action=update or action=close"),
|
|
16348
16590
|
step: z19.string().optional().describe("Checkpoint step for action=checkpoint"),
|
|
@@ -30442,6 +30684,15 @@ function registerCreateBugReport(server) {
|
|
|
30442
30684
|
project_name,
|
|
30443
30685
|
send_upstream
|
|
30444
30686
|
}) => {
|
|
30687
|
+
if (!summary || summary.trim().length === 0) {
|
|
30688
|
+
return {
|
|
30689
|
+
content: [{
|
|
30690
|
+
type: "text",
|
|
30691
|
+
text: "Error: summary is required but was empty. If calling via support(action='create_bug'), use 'description' which maps to 'summary'."
|
|
30692
|
+
}],
|
|
30693
|
+
isError: true
|
|
30694
|
+
};
|
|
30695
|
+
}
|
|
30445
30696
|
const { agentId, agentRole } = getActiveAgent();
|
|
30446
30697
|
const id = crypto19.randomUUID();
|
|
30447
30698
|
const version = package_version ?? "unknown";
|
|
@@ -33024,6 +33275,25 @@ function registerSupportConsolidated(server) {
|
|
|
33024
33275
|
const handler = handlers.get(toolName);
|
|
33025
33276
|
if (!handler) return { content: [{ type: "text", text: `Handler not found: ${toolName}` }], isError: true };
|
|
33026
33277
|
const { action: _, ...args } = input;
|
|
33278
|
+
if (action === "create_bug") {
|
|
33279
|
+
if (args.description && !args.summary) {
|
|
33280
|
+
args.summary = args.description;
|
|
33281
|
+
delete args.description;
|
|
33282
|
+
}
|
|
33283
|
+
if (args.steps_to_reproduce && !args.reproduction_steps) {
|
|
33284
|
+
const raw = args.steps_to_reproduce;
|
|
33285
|
+
args.reproduction_steps = raw.split(/\n/).map((s) => s.replace(/^\d+\.\s*/, "").trim()).filter(Boolean);
|
|
33286
|
+
delete args.steps_to_reproduce;
|
|
33287
|
+
}
|
|
33288
|
+
if (args.expected_behavior && !args.expected) {
|
|
33289
|
+
args.expected = args.expected_behavior;
|
|
33290
|
+
delete args.expected_behavior;
|
|
33291
|
+
}
|
|
33292
|
+
if (args.actual_behavior && !args.actual) {
|
|
33293
|
+
args.actual = args.actual_behavior;
|
|
33294
|
+
delete args.actual_behavior;
|
|
33295
|
+
}
|
|
33296
|
+
}
|
|
33027
33297
|
if ((action === "triage_bug" || action === "triage_feature") && args.notes && !args.triage_notes) {
|
|
33028
33298
|
args.triage_notes = args.notes;
|
|
33029
33299
|
delete args.notes;
|
|
@@ -33060,6 +33330,513 @@ var init_support_consolidated = __esm({
|
|
|
33060
33330
|
}
|
|
33061
33331
|
});
|
|
33062
33332
|
|
|
33333
|
+
// src/lib/tool-capability-index.ts
|
|
33334
|
+
var tool_capability_index_exports = {};
|
|
33335
|
+
__export(tool_capability_index_exports, {
|
|
33336
|
+
ToolCapabilityIndex: () => ToolCapabilityIndex,
|
|
33337
|
+
getToolCapabilityIndex: () => getToolCapabilityIndex
|
|
33338
|
+
});
|
|
33339
|
+
function categoryForToolName(toolName, categoryMap) {
|
|
33340
|
+
const normalized = toolName.replace(/[_-]/g, "").toLowerCase();
|
|
33341
|
+
for (const [registerFn, cat] of Object.entries(categoryMap)) {
|
|
33342
|
+
const fnNormalized = registerFn.replace(/^register/, "").toLowerCase();
|
|
33343
|
+
if (fnNormalized === normalized) return cat;
|
|
33344
|
+
}
|
|
33345
|
+
return "unknown";
|
|
33346
|
+
}
|
|
33347
|
+
function extractParamNames(inputSchema) {
|
|
33348
|
+
if (!inputSchema || typeof inputSchema !== "object") return "";
|
|
33349
|
+
return Object.keys(inputSchema).join(", ");
|
|
33350
|
+
}
|
|
33351
|
+
function cosineSimilarity4(a, b) {
|
|
33352
|
+
if (a.length !== b.length || a.length === 0) return 0;
|
|
33353
|
+
let dot = 0, normA = 0, normB = 0;
|
|
33354
|
+
for (let i = 0; i < a.length; i++) {
|
|
33355
|
+
dot += a[i] * b[i];
|
|
33356
|
+
normA += a[i] * a[i];
|
|
33357
|
+
normB += b[i] * b[i];
|
|
33358
|
+
}
|
|
33359
|
+
const denom = Math.sqrt(normA) * Math.sqrt(normB);
|
|
33360
|
+
return denom === 0 ? 0 : dot / denom;
|
|
33361
|
+
}
|
|
33362
|
+
function keywordScore(query, tool) {
|
|
33363
|
+
const words = query.toLowerCase().split(/\s+/).filter((w) => w.length > 2);
|
|
33364
|
+
if (words.length === 0) return 0;
|
|
33365
|
+
const searchText = `${tool.name} ${tool.description} ${tool.category} ${tool.paramSummary}`.toLowerCase();
|
|
33366
|
+
let matches = 0;
|
|
33367
|
+
for (const word of words) {
|
|
33368
|
+
if (searchText.includes(word)) matches++;
|
|
33369
|
+
}
|
|
33370
|
+
return matches / words.length;
|
|
33371
|
+
}
|
|
33372
|
+
function getToolCapabilityIndex() {
|
|
33373
|
+
if (!_instance) {
|
|
33374
|
+
_instance = new ToolCapabilityIndex();
|
|
33375
|
+
}
|
|
33376
|
+
return _instance;
|
|
33377
|
+
}
|
|
33378
|
+
var ALWAYS_ON, ToolCapabilityIndex, _instance;
|
|
33379
|
+
var init_tool_capability_index = __esm({
|
|
33380
|
+
"src/lib/tool-capability-index.ts"() {
|
|
33381
|
+
"use strict";
|
|
33382
|
+
init_memory();
|
|
33383
|
+
ALWAYS_ON = /* @__PURE__ */ new Set([
|
|
33384
|
+
"mcp_ping",
|
|
33385
|
+
"memory",
|
|
33386
|
+
"task",
|
|
33387
|
+
"message",
|
|
33388
|
+
"identity",
|
|
33389
|
+
"diagnostics",
|
|
33390
|
+
"session"
|
|
33391
|
+
]);
|
|
33392
|
+
ToolCapabilityIndex = class {
|
|
33393
|
+
capabilities = [];
|
|
33394
|
+
initialized = false;
|
|
33395
|
+
/**
|
|
33396
|
+
* Build the index by intercepting registerAllTools via a fake McpServer.
|
|
33397
|
+
*
|
|
33398
|
+
* @param registerFn - function that registers tools on a server (e.g. registerAllTools)
|
|
33399
|
+
* @param categoryMap - optional map of registerFnName → category (from tool-gates TOOL_CATEGORIES)
|
|
33400
|
+
*/
|
|
33401
|
+
async buildIndex(registerFn, categoryMap) {
|
|
33402
|
+
const captured = [];
|
|
33403
|
+
const fakeServer = {
|
|
33404
|
+
registerTool(name, config2, _handler) {
|
|
33405
|
+
captured.push({
|
|
33406
|
+
name,
|
|
33407
|
+
description: config2.description ?? "",
|
|
33408
|
+
inputSchema: config2.inputSchema ?? {}
|
|
33409
|
+
});
|
|
33410
|
+
}
|
|
33411
|
+
};
|
|
33412
|
+
registerFn(fakeServer);
|
|
33413
|
+
let embedFn = null;
|
|
33414
|
+
try {
|
|
33415
|
+
const { embed: embed2 } = await Promise.resolve().then(() => (init_embedder(), embedder_exports));
|
|
33416
|
+
const test = await embed2("test");
|
|
33417
|
+
if (test.length === EMBEDDING_DIM) {
|
|
33418
|
+
embedFn = embed2;
|
|
33419
|
+
}
|
|
33420
|
+
} catch {
|
|
33421
|
+
}
|
|
33422
|
+
const capabilities = [];
|
|
33423
|
+
for (const tool of captured) {
|
|
33424
|
+
const paramSummary = extractParamNames(tool.inputSchema);
|
|
33425
|
+
const category = categoryMap ? categoryForToolName(tool.name, categoryMap) : "unknown";
|
|
33426
|
+
const capabilityDoc = `${tool.name}: ${tool.description}. Parameters: ${paramSummary}`;
|
|
33427
|
+
let vector = null;
|
|
33428
|
+
if (embedFn) {
|
|
33429
|
+
try {
|
|
33430
|
+
vector = await embedFn(capabilityDoc.slice(0, 500));
|
|
33431
|
+
} catch {
|
|
33432
|
+
}
|
|
33433
|
+
}
|
|
33434
|
+
capabilities.push({
|
|
33435
|
+
name: tool.name,
|
|
33436
|
+
description: tool.description,
|
|
33437
|
+
category,
|
|
33438
|
+
vector,
|
|
33439
|
+
paramSummary
|
|
33440
|
+
});
|
|
33441
|
+
}
|
|
33442
|
+
this.capabilities = capabilities;
|
|
33443
|
+
this.initialized = true;
|
|
33444
|
+
process.stderr.write(
|
|
33445
|
+
`[tool-capability-index] Indexed ${capabilities.length} tools (${capabilities.filter((c) => c.vector).length} with vectors)
|
|
33446
|
+
`
|
|
33447
|
+
);
|
|
33448
|
+
}
|
|
33449
|
+
/**
|
|
33450
|
+
* Semantic search for tools matching a natural-language query.
|
|
33451
|
+
* Returns tools sorted by relevance, with always-on tools boosted.
|
|
33452
|
+
*/
|
|
33453
|
+
async search(query, limit = 20) {
|
|
33454
|
+
if (!this.initialized || this.capabilities.length === 0) return [];
|
|
33455
|
+
let queryVector = null;
|
|
33456
|
+
try {
|
|
33457
|
+
const { embed: embed2 } = await Promise.resolve().then(() => (init_embedder(), embedder_exports));
|
|
33458
|
+
queryVector = await embed2(query);
|
|
33459
|
+
} catch {
|
|
33460
|
+
}
|
|
33461
|
+
const scored = [];
|
|
33462
|
+
for (const tool of this.capabilities) {
|
|
33463
|
+
let relevance;
|
|
33464
|
+
if (queryVector && tool.vector) {
|
|
33465
|
+
const vecScore = cosineSimilarity4(queryVector, tool.vector);
|
|
33466
|
+
const kwScore = keywordScore(query, tool);
|
|
33467
|
+
relevance = vecScore * 0.8 + kwScore * 0.2;
|
|
33468
|
+
} else {
|
|
33469
|
+
relevance = keywordScore(query, tool);
|
|
33470
|
+
}
|
|
33471
|
+
if (ALWAYS_ON.has(tool.name)) {
|
|
33472
|
+
relevance = Math.max(relevance, 0.5);
|
|
33473
|
+
}
|
|
33474
|
+
scored.push({ ...tool, relevance });
|
|
33475
|
+
}
|
|
33476
|
+
scored.sort((a, b) => b.relevance - a.relevance);
|
|
33477
|
+
return scored.slice(0, limit);
|
|
33478
|
+
}
|
|
33479
|
+
/** Whether the index has been built. */
|
|
33480
|
+
isReady() {
|
|
33481
|
+
return this.initialized;
|
|
33482
|
+
}
|
|
33483
|
+
/** Total number of indexed tools. */
|
|
33484
|
+
get toolCount() {
|
|
33485
|
+
return this.capabilities.length;
|
|
33486
|
+
}
|
|
33487
|
+
};
|
|
33488
|
+
_instance = null;
|
|
33489
|
+
}
|
|
33490
|
+
});
|
|
33491
|
+
|
|
33492
|
+
// src/lib/drift-probes.ts
|
|
33493
|
+
async function getRecentMemories(agentId, limit) {
|
|
33494
|
+
try {
|
|
33495
|
+
const { getClient: getClient2, isInitialized: isInitialized2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
33496
|
+
if (!isInitialized2()) return { count: 0, texts: [] };
|
|
33497
|
+
const client = getClient2();
|
|
33498
|
+
const result3 = await client.execute({
|
|
33499
|
+
sql: `SELECT text FROM memories WHERE agent_id = ? ORDER BY created_at DESC LIMIT ?`,
|
|
33500
|
+
args: [agentId, limit]
|
|
33501
|
+
});
|
|
33502
|
+
const texts = result3.rows.map((r) => String(r.text ?? ""));
|
|
33503
|
+
return { count: texts.length, texts };
|
|
33504
|
+
} catch {
|
|
33505
|
+
return { count: 0, texts: [] };
|
|
33506
|
+
}
|
|
33507
|
+
}
|
|
33508
|
+
async function getDecisionCount(agentId) {
|
|
33509
|
+
try {
|
|
33510
|
+
const { getClient: getClient2, isInitialized: isInitialized2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
33511
|
+
if (!isInitialized2()) return 0;
|
|
33512
|
+
const client = getClient2();
|
|
33513
|
+
const result3 = await client.execute({
|
|
33514
|
+
sql: `SELECT COUNT(*) as cnt FROM memories WHERE agent_id = ? AND memory_type = 'decision'`,
|
|
33515
|
+
args: [agentId]
|
|
33516
|
+
});
|
|
33517
|
+
return Number(result3.rows[0]?.cnt ?? 0);
|
|
33518
|
+
} catch {
|
|
33519
|
+
return 0;
|
|
33520
|
+
}
|
|
33521
|
+
}
|
|
33522
|
+
function probeContinuity(ctx) {
|
|
33523
|
+
const memCount = ctx.recentMemoryCount;
|
|
33524
|
+
let score;
|
|
33525
|
+
let detail;
|
|
33526
|
+
if (memCount >= 20) {
|
|
33527
|
+
score = 95;
|
|
33528
|
+
detail = `${memCount} recent memories \u2014 strong continuity`;
|
|
33529
|
+
} else if (memCount >= 10) {
|
|
33530
|
+
score = 85;
|
|
33531
|
+
detail = `${memCount} recent memories \u2014 adequate continuity`;
|
|
33532
|
+
} else if (memCount >= 3) {
|
|
33533
|
+
score = 70;
|
|
33534
|
+
detail = `${memCount} recent memories \u2014 limited continuity`;
|
|
33535
|
+
} else if (memCount >= 1) {
|
|
33536
|
+
score = 50;
|
|
33537
|
+
detail = `${memCount} recent memories \u2014 weak continuity`;
|
|
33538
|
+
} else {
|
|
33539
|
+
score = 30;
|
|
33540
|
+
detail = "No recent memories \u2014 agent may lack session context";
|
|
33541
|
+
}
|
|
33542
|
+
if (ctx.storedDecisionCount > 0) {
|
|
33543
|
+
score = Math.min(100, score + 5);
|
|
33544
|
+
detail += ` (+${ctx.storedDecisionCount} decisions)`;
|
|
33545
|
+
}
|
|
33546
|
+
return { axis: "continuity", score, detail };
|
|
33547
|
+
}
|
|
33548
|
+
function probeConsistency(ctx) {
|
|
33549
|
+
if (!ctx.identityBody || ctx.recentMemoryTexts.length === 0) {
|
|
33550
|
+
return {
|
|
33551
|
+
axis: "consistency",
|
|
33552
|
+
score: ctx.identityBody ? 80 : 50,
|
|
33553
|
+
detail: ctx.identityBody ? "No memories to check against identity" : "No identity file \u2014 cannot assess consistency"
|
|
33554
|
+
};
|
|
33555
|
+
}
|
|
33556
|
+
const identityTerms = extractKeyTerms(ctx.identityBody);
|
|
33557
|
+
if (identityTerms.length === 0) {
|
|
33558
|
+
return { axis: "consistency", score: 75, detail: "Identity has no extractable key terms" };
|
|
33559
|
+
}
|
|
33560
|
+
const memoryText = ctx.recentMemoryTexts.join(" ").toLowerCase();
|
|
33561
|
+
let matched = 0;
|
|
33562
|
+
for (const term of identityTerms) {
|
|
33563
|
+
if (memoryText.includes(term.toLowerCase())) matched++;
|
|
33564
|
+
}
|
|
33565
|
+
const ratio = matched / identityTerms.length;
|
|
33566
|
+
const score = Math.round(50 + ratio * 50);
|
|
33567
|
+
const detail = `${matched}/${identityTerms.length} identity terms found in recent memories`;
|
|
33568
|
+
return { axis: "consistency", score, detail };
|
|
33569
|
+
}
|
|
33570
|
+
function probeRoleFidelity(ctx) {
|
|
33571
|
+
const flags = [];
|
|
33572
|
+
if (!ctx.identityBody) {
|
|
33573
|
+
return {
|
|
33574
|
+
axis: "role-fidelity",
|
|
33575
|
+
score: 40,
|
|
33576
|
+
detail: `No identity file for ${ctx.agent.name}`
|
|
33577
|
+
};
|
|
33578
|
+
}
|
|
33579
|
+
let score = 100;
|
|
33580
|
+
const identityLower = ctx.identityBody.toLowerCase();
|
|
33581
|
+
const rosterRole = ctx.agent.role.toLowerCase();
|
|
33582
|
+
if (!identityLower.includes(rosterRole)) {
|
|
33583
|
+
score -= 15;
|
|
33584
|
+
flags.push(`Identity does not mention role "${ctx.agent.role}"`);
|
|
33585
|
+
}
|
|
33586
|
+
if (!identityLower.includes(ctx.agent.name.toLowerCase())) {
|
|
33587
|
+
score -= 10;
|
|
33588
|
+
flags.push(`Identity does not mention agent name "${ctx.agent.name}"`);
|
|
33589
|
+
}
|
|
33590
|
+
const hasScopeBoundary = identityLower.includes("do not") || identityLower.includes("don't") || identityLower.includes("not your") || identityLower.includes("outside your") || identityLower.includes("you do not");
|
|
33591
|
+
if (!hasScopeBoundary) {
|
|
33592
|
+
score -= 10;
|
|
33593
|
+
flags.push("Identity lacks explicit scope boundaries (what NOT to do)");
|
|
33594
|
+
}
|
|
33595
|
+
if (ctx.agent.systemPrompt) {
|
|
33596
|
+
const promptTerms = extractKeyTerms(ctx.agent.systemPrompt);
|
|
33597
|
+
const identityText = ctx.identityBody.toLowerCase();
|
|
33598
|
+
let promptMatched = 0;
|
|
33599
|
+
for (const term of promptTerms.slice(0, 20)) {
|
|
33600
|
+
if (identityText.includes(term.toLowerCase())) promptMatched++;
|
|
33601
|
+
}
|
|
33602
|
+
const promptRatio = promptTerms.length > 0 ? promptMatched / Math.min(promptTerms.length, 20) : 1;
|
|
33603
|
+
if (promptRatio < 0.3) {
|
|
33604
|
+
score -= 15;
|
|
33605
|
+
flags.push("Identity content diverges significantly from roster systemPrompt");
|
|
33606
|
+
}
|
|
33607
|
+
}
|
|
33608
|
+
if (ctx.recentMemoryTexts.length > 5) {
|
|
33609
|
+
const roleKeywords = extractRoleKeywords(ctx.agent.role);
|
|
33610
|
+
const memoryText = ctx.recentMemoryTexts.join(" ").toLowerCase();
|
|
33611
|
+
let domainHits = 0;
|
|
33612
|
+
for (const kw of roleKeywords) {
|
|
33613
|
+
if (memoryText.includes(kw)) domainHits++;
|
|
33614
|
+
}
|
|
33615
|
+
const domainRatio = roleKeywords.length > 0 ? domainHits / roleKeywords.length : 1;
|
|
33616
|
+
if (domainRatio < 0.2) {
|
|
33617
|
+
score -= 10;
|
|
33618
|
+
flags.push(`Recent work shows little overlap with ${ctx.agent.role} domain keywords`);
|
|
33619
|
+
}
|
|
33620
|
+
}
|
|
33621
|
+
score = Math.max(0, Math.min(100, score));
|
|
33622
|
+
const detail = flags.length > 0 ? flags.join("; ") : "Identity aligns with roster definition";
|
|
33623
|
+
return { axis: "role-fidelity", score, detail };
|
|
33624
|
+
}
|
|
33625
|
+
function probeWorldModel(ctx) {
|
|
33626
|
+
if (!ctx.identityBody) {
|
|
33627
|
+
return {
|
|
33628
|
+
axis: "world-model",
|
|
33629
|
+
score: 50,
|
|
33630
|
+
detail: "No identity file \u2014 cannot assess org awareness"
|
|
33631
|
+
};
|
|
33632
|
+
}
|
|
33633
|
+
const identityLower = ctx.identityBody.toLowerCase();
|
|
33634
|
+
const flags = [];
|
|
33635
|
+
let score = 100;
|
|
33636
|
+
const otherAgents = ctx.allEmployees.filter((e) => e.name !== ctx.agent.name);
|
|
33637
|
+
let mentionedAgents = 0;
|
|
33638
|
+
for (const other of otherAgents) {
|
|
33639
|
+
if (identityLower.includes(other.name.toLowerCase())) mentionedAgents++;
|
|
33640
|
+
}
|
|
33641
|
+
if (otherAgents.length > 0) {
|
|
33642
|
+
const mentionRatio = mentionedAgents / otherAgents.length;
|
|
33643
|
+
if (mentionRatio < 0.3) {
|
|
33644
|
+
score -= 15;
|
|
33645
|
+
flags.push(`Identity mentions ${mentionedAgents}/${otherAgents.length} team members`);
|
|
33646
|
+
}
|
|
33647
|
+
}
|
|
33648
|
+
const hasReportingChain = identityLower.includes("report") || identityLower.includes("manager") || identityLower.includes("coo") || identityLower.includes("coordinator");
|
|
33649
|
+
if (!hasReportingChain) {
|
|
33650
|
+
score -= 10;
|
|
33651
|
+
flags.push("Identity does not reference reporting chain");
|
|
33652
|
+
}
|
|
33653
|
+
const orgTerms = ["exe-os", "exe-wiki", "exe-crm", "askexe"];
|
|
33654
|
+
let orgMentions = 0;
|
|
33655
|
+
for (const term of orgTerms) {
|
|
33656
|
+
if (identityLower.includes(term)) orgMentions++;
|
|
33657
|
+
}
|
|
33658
|
+
if (orgMentions === 0) {
|
|
33659
|
+
score -= 5;
|
|
33660
|
+
flags.push("Identity does not reference any org products");
|
|
33661
|
+
}
|
|
33662
|
+
score = Math.max(0, Math.min(100, score));
|
|
33663
|
+
const detail = flags.length > 0 ? flags.join("; ") : "Identity reflects org structure";
|
|
33664
|
+
return { axis: "world-model", score, detail };
|
|
33665
|
+
}
|
|
33666
|
+
function extractKeyTerms(text3) {
|
|
33667
|
+
const stopwords = /* @__PURE__ */ new Set([
|
|
33668
|
+
"the",
|
|
33669
|
+
"and",
|
|
33670
|
+
"for",
|
|
33671
|
+
"are",
|
|
33672
|
+
"but",
|
|
33673
|
+
"not",
|
|
33674
|
+
"you",
|
|
33675
|
+
"all",
|
|
33676
|
+
"any",
|
|
33677
|
+
"can",
|
|
33678
|
+
"had",
|
|
33679
|
+
"her",
|
|
33680
|
+
"was",
|
|
33681
|
+
"one",
|
|
33682
|
+
"our",
|
|
33683
|
+
"out",
|
|
33684
|
+
"has",
|
|
33685
|
+
"his",
|
|
33686
|
+
"how",
|
|
33687
|
+
"its",
|
|
33688
|
+
"may",
|
|
33689
|
+
"new",
|
|
33690
|
+
"now",
|
|
33691
|
+
"old",
|
|
33692
|
+
"see",
|
|
33693
|
+
"way",
|
|
33694
|
+
"who",
|
|
33695
|
+
"did",
|
|
33696
|
+
"get",
|
|
33697
|
+
"got",
|
|
33698
|
+
"let",
|
|
33699
|
+
"say",
|
|
33700
|
+
"she",
|
|
33701
|
+
"too",
|
|
33702
|
+
"use",
|
|
33703
|
+
"with",
|
|
33704
|
+
"this",
|
|
33705
|
+
"that",
|
|
33706
|
+
"from",
|
|
33707
|
+
"they",
|
|
33708
|
+
"been",
|
|
33709
|
+
"have",
|
|
33710
|
+
"will",
|
|
33711
|
+
"your",
|
|
33712
|
+
"what",
|
|
33713
|
+
"when",
|
|
33714
|
+
"make",
|
|
33715
|
+
"like",
|
|
33716
|
+
"just",
|
|
33717
|
+
"over",
|
|
33718
|
+
"such",
|
|
33719
|
+
"take",
|
|
33720
|
+
"than",
|
|
33721
|
+
"them",
|
|
33722
|
+
"very",
|
|
33723
|
+
"some",
|
|
33724
|
+
"could",
|
|
33725
|
+
"into",
|
|
33726
|
+
"then",
|
|
33727
|
+
"more",
|
|
33728
|
+
"also",
|
|
33729
|
+
"after",
|
|
33730
|
+
"should",
|
|
33731
|
+
"would",
|
|
33732
|
+
"about",
|
|
33733
|
+
"their",
|
|
33734
|
+
"which",
|
|
33735
|
+
"these",
|
|
33736
|
+
"other",
|
|
33737
|
+
"every",
|
|
33738
|
+
"does",
|
|
33739
|
+
"being",
|
|
33740
|
+
"those",
|
|
33741
|
+
"never",
|
|
33742
|
+
"before",
|
|
33743
|
+
"through"
|
|
33744
|
+
]);
|
|
33745
|
+
const words = text3.replace(/[^\w\s-]/g, " ").split(/\s+/).filter((w) => w.length > 3 && !stopwords.has(w.toLowerCase()));
|
|
33746
|
+
return [...new Set(words.map((w) => w.toLowerCase()))].slice(0, 50);
|
|
33747
|
+
}
|
|
33748
|
+
function extractRoleKeywords(role) {
|
|
33749
|
+
const roleKeywordMap = {
|
|
33750
|
+
"coo": ["coordinate", "review", "status", "team", "task", "priority", "dispatch"],
|
|
33751
|
+
"cto": ["architecture", "code", "technical", "system", "design", "review", "security"],
|
|
33752
|
+
"cmo": ["marketing", "brand", "content", "design", "seo", "social", "campaign"],
|
|
33753
|
+
"principal engineer": ["code", "implement", "test", "fix", "feature", "refactor", "build"],
|
|
33754
|
+
"staff code reviewer": ["review", "code", "quality", "issue", "fix", "pattern"],
|
|
33755
|
+
"content production specialist": ["video", "image", "render", "content", "produce", "media"],
|
|
33756
|
+
"ai product lead": ["competitive", "analysis", "feature", "product", "research", "repo"]
|
|
33757
|
+
};
|
|
33758
|
+
const normalized = role.toLowerCase();
|
|
33759
|
+
return roleKeywordMap[normalized] ?? normalized.split(/\s+/).filter((w) => w.length > 2);
|
|
33760
|
+
}
|
|
33761
|
+
async function runDriftProbes(options = {}) {
|
|
33762
|
+
const employees = loadEmployeesSync();
|
|
33763
|
+
const targetAgents = options.agentId ? employees.filter((e) => e.name === options.agentId) : employees;
|
|
33764
|
+
if (targetAgents.length === 0) {
|
|
33765
|
+
return [];
|
|
33766
|
+
}
|
|
33767
|
+
const axes = options.axes ?? ["continuity", "consistency", "role-fidelity", "world-model"];
|
|
33768
|
+
const results = [];
|
|
33769
|
+
for (const agent of targetAgents) {
|
|
33770
|
+
const identity = getIdentity(agent.name);
|
|
33771
|
+
const { count: memCount, texts: memTexts } = await getRecentMemories(agent.name, 50);
|
|
33772
|
+
const decisionCount = await getDecisionCount(agent.name);
|
|
33773
|
+
const ctx = {
|
|
33774
|
+
agent,
|
|
33775
|
+
identityBody: identity?.body ?? null,
|
|
33776
|
+
identityRole: identity?.frontmatter.role ?? null,
|
|
33777
|
+
recentMemoryCount: memCount,
|
|
33778
|
+
recentMemoryTexts: memTexts,
|
|
33779
|
+
storedDecisionCount: decisionCount,
|
|
33780
|
+
allEmployees: employees
|
|
33781
|
+
};
|
|
33782
|
+
const probes = [];
|
|
33783
|
+
const probeFns = {
|
|
33784
|
+
continuity: probeContinuity,
|
|
33785
|
+
consistency: probeConsistency,
|
|
33786
|
+
"role-fidelity": probeRoleFidelity,
|
|
33787
|
+
"world-model": probeWorldModel
|
|
33788
|
+
};
|
|
33789
|
+
for (const axis of axes) {
|
|
33790
|
+
probes.push(probeFns[axis](ctx));
|
|
33791
|
+
}
|
|
33792
|
+
const scores = {
|
|
33793
|
+
continuity: 0,
|
|
33794
|
+
consistency: 0,
|
|
33795
|
+
"role-fidelity": 0,
|
|
33796
|
+
"world-model": 0
|
|
33797
|
+
};
|
|
33798
|
+
for (const probe of probes) {
|
|
33799
|
+
scores[probe.axis] = probe.score;
|
|
33800
|
+
}
|
|
33801
|
+
const weights = {
|
|
33802
|
+
continuity: 0.2,
|
|
33803
|
+
consistency: 0.2,
|
|
33804
|
+
"role-fidelity": 0.35,
|
|
33805
|
+
"world-model": 0.25
|
|
33806
|
+
};
|
|
33807
|
+
let weightedSum = 0;
|
|
33808
|
+
let weightTotal = 0;
|
|
33809
|
+
for (const axis of axes) {
|
|
33810
|
+
weightedSum += scores[axis] * weights[axis];
|
|
33811
|
+
weightTotal += weights[axis];
|
|
33812
|
+
}
|
|
33813
|
+
const overall = Math.round(weightTotal > 0 ? weightedSum / weightTotal : 0);
|
|
33814
|
+
const flags = [];
|
|
33815
|
+
for (const probe of probes) {
|
|
33816
|
+
if (probe.score < DRIFT_THRESHOLD) {
|
|
33817
|
+
flags.push(`${probe.axis} at ${probe.score}% \u2014 ${probe.detail}`);
|
|
33818
|
+
}
|
|
33819
|
+
}
|
|
33820
|
+
results.push({
|
|
33821
|
+
agent: agent.name,
|
|
33822
|
+
scores,
|
|
33823
|
+
overall,
|
|
33824
|
+
drifting: flags.length > 0,
|
|
33825
|
+
flags
|
|
33826
|
+
});
|
|
33827
|
+
}
|
|
33828
|
+
return results;
|
|
33829
|
+
}
|
|
33830
|
+
var DRIFT_THRESHOLD;
|
|
33831
|
+
var init_drift_probes = __esm({
|
|
33832
|
+
"src/lib/drift-probes.ts"() {
|
|
33833
|
+
"use strict";
|
|
33834
|
+
init_identity();
|
|
33835
|
+
init_employees();
|
|
33836
|
+
DRIFT_THRESHOLD = 80;
|
|
33837
|
+
}
|
|
33838
|
+
});
|
|
33839
|
+
|
|
33063
33840
|
// src/mcp/tools/diagnostics.ts
|
|
33064
33841
|
import { z as z98 } from "zod";
|
|
33065
33842
|
function buildHandlers9() {
|
|
@@ -33075,23 +33852,31 @@ function buildHandlers9() {
|
|
|
33075
33852
|
function registerDiagnostics(server) {
|
|
33076
33853
|
const handlers = buildHandlers9();
|
|
33077
33854
|
const toolNames = Array.from(handlers.keys());
|
|
33078
|
-
|
|
33855
|
+
toolNames.push("tool_search", "drift");
|
|
33079
33856
|
server.registerTool(
|
|
33080
33857
|
"diagnostics",
|
|
33081
33858
|
{
|
|
33082
33859
|
title: "Diagnostics",
|
|
33083
|
-
description: `System diagnostics and admin operations. Actions: ${toolNames.join(", ")}. Covers health checks, update status, cloud status, key management, and
|
|
33860
|
+
description: `System diagnostics and admin operations. Actions: ${toolNames.join(", ")}. Covers health checks, update status, cloud status, key management, employee rename, semantic tool discovery (tool_search), and identity drift detection (drift).`,
|
|
33084
33861
|
inputSchema: {
|
|
33085
33862
|
action: z98.string().describe(`Diagnostic operation: ${toolNames.join(", ")}`),
|
|
33086
33863
|
// Pass-through params used by various sub-tools
|
|
33864
|
+
agent_id: z98.string().optional().describe("Agent to probe (drift). Defaults to all agents."),
|
|
33087
33865
|
name: z98.string().optional().describe("Employee name (rename_employee)"),
|
|
33088
33866
|
new_name: z98.string().optional().describe("New employee name (rename_employee)"),
|
|
33089
|
-
query: z98.string().optional().describe("Search/filter query"),
|
|
33090
|
-
format: z98.string().optional().describe("Output format")
|
|
33867
|
+
query: z98.string().optional().describe("Search/filter query, or natural language for tool_search"),
|
|
33868
|
+
format: z98.string().optional().describe("Output format"),
|
|
33869
|
+
limit: z98.coerce.number().int().min(1).max(100).optional().describe("Max results for tool_search (default 20)")
|
|
33091
33870
|
}
|
|
33092
33871
|
},
|
|
33093
33872
|
async (input, extra) => {
|
|
33094
33873
|
const action = input.action;
|
|
33874
|
+
if (action === "tool_search") {
|
|
33875
|
+
return handleToolSearch(input);
|
|
33876
|
+
}
|
|
33877
|
+
if (action === "drift") {
|
|
33878
|
+
return handleDrift(input);
|
|
33879
|
+
}
|
|
33095
33880
|
const handler = handlers.get(action);
|
|
33096
33881
|
if (!handler) {
|
|
33097
33882
|
return {
|
|
@@ -33104,14 +33889,89 @@ function registerDiagnostics(server) {
|
|
|
33104
33889
|
}
|
|
33105
33890
|
);
|
|
33106
33891
|
}
|
|
33892
|
+
async function handleToolSearch(input) {
|
|
33893
|
+
const query = input.query ?? "";
|
|
33894
|
+
const limit = input.limit ?? 20;
|
|
33895
|
+
if (!query) {
|
|
33896
|
+
return {
|
|
33897
|
+
content: [{ type: "text", text: JSON.stringify({ error: "query is required for tool_search" }) }],
|
|
33898
|
+
isError: true
|
|
33899
|
+
};
|
|
33900
|
+
}
|
|
33901
|
+
const index = getToolCapabilityIndex();
|
|
33902
|
+
if (!index.isReady()) {
|
|
33903
|
+
return {
|
|
33904
|
+
content: [{
|
|
33905
|
+
type: "text",
|
|
33906
|
+
text: JSON.stringify({
|
|
33907
|
+
error: "Tool capability index not initialized yet. It is built asynchronously at daemon boot.",
|
|
33908
|
+
query
|
|
33909
|
+
})
|
|
33910
|
+
}],
|
|
33911
|
+
isError: true
|
|
33912
|
+
};
|
|
33913
|
+
}
|
|
33914
|
+
const results = await index.search(query, limit);
|
|
33915
|
+
const tools = results.map((r) => ({
|
|
33916
|
+
name: r.name,
|
|
33917
|
+
description: r.description,
|
|
33918
|
+
category: r.category,
|
|
33919
|
+
relevance: Math.round(r.relevance * 1e3) / 1e3
|
|
33920
|
+
}));
|
|
33921
|
+
return {
|
|
33922
|
+
content: [{
|
|
33923
|
+
type: "text",
|
|
33924
|
+
text: JSON.stringify({
|
|
33925
|
+
tools,
|
|
33926
|
+
total_tools: index.toolCount,
|
|
33927
|
+
query
|
|
33928
|
+
}, null, 2)
|
|
33929
|
+
}]
|
|
33930
|
+
};
|
|
33931
|
+
}
|
|
33932
|
+
async function handleDrift(input) {
|
|
33933
|
+
const agentId = input.agent_id;
|
|
33934
|
+
const axesRaw = input.query;
|
|
33935
|
+
let axes;
|
|
33936
|
+
if (axesRaw) {
|
|
33937
|
+
const valid = ["continuity", "consistency", "role-fidelity", "world-model"];
|
|
33938
|
+
const parsed = axesRaw.split(",").map((a) => a.trim()).filter((a) => valid.includes(a));
|
|
33939
|
+
if (parsed.length > 0) axes = parsed;
|
|
33940
|
+
}
|
|
33941
|
+
const results = await runDriftProbes({ agentId, axes });
|
|
33942
|
+
if (results.length === 0) {
|
|
33943
|
+
return {
|
|
33944
|
+
content: [{
|
|
33945
|
+
type: "text",
|
|
33946
|
+
text: JSON.stringify({ error: agentId ? `Agent "${agentId}" not found` : "No agents found" })
|
|
33947
|
+
}],
|
|
33948
|
+
isError: true
|
|
33949
|
+
};
|
|
33950
|
+
}
|
|
33951
|
+
return {
|
|
33952
|
+
content: [{
|
|
33953
|
+
type: "text",
|
|
33954
|
+
text: JSON.stringify(results.length === 1 ? results[0] : results, null, 2)
|
|
33955
|
+
}]
|
|
33956
|
+
};
|
|
33957
|
+
}
|
|
33107
33958
|
var init_diagnostics = __esm({
|
|
33108
33959
|
"src/mcp/tools/diagnostics.ts"() {
|
|
33109
33960
|
"use strict";
|
|
33110
33961
|
init_cli_parity();
|
|
33962
|
+
init_tool_capability_index();
|
|
33963
|
+
init_drift_probes();
|
|
33111
33964
|
}
|
|
33112
33965
|
});
|
|
33113
33966
|
|
|
33114
33967
|
// src/mcp/tool-gates.ts
|
|
33968
|
+
var tool_gates_exports = {};
|
|
33969
|
+
__export(tool_gates_exports, {
|
|
33970
|
+
TOOL_CATEGORIES: () => TOOL_CATEGORIES,
|
|
33971
|
+
TOOL_GATES: () => TOOL_GATES,
|
|
33972
|
+
isToolAllowed: () => isToolAllowed,
|
|
33973
|
+
isToolAllowedForPlan: () => isToolAllowedForPlan
|
|
33974
|
+
});
|
|
33115
33975
|
function isToolAllowedForPlan(registerFnName, plan) {
|
|
33116
33976
|
const category = TOOL_CATEGORIES[registerFnName];
|
|
33117
33977
|
if (!category) return true;
|
|
@@ -35478,6 +36338,20 @@ async function startMcpHttpServer() {
|
|
|
35478
36338
|
`
|
|
35479
36339
|
);
|
|
35480
36340
|
}
|
|
36341
|
+
Promise.all([
|
|
36342
|
+
Promise.resolve().then(() => (init_tool_capability_index(), tool_capability_index_exports)),
|
|
36343
|
+
Promise.resolve().then(() => (init_tool_gates(), tool_gates_exports))
|
|
36344
|
+
]).then(async ([{ getToolCapabilityIndex: getToolCapabilityIndex2 }, { TOOL_CATEGORIES: TOOL_CATEGORIES2 }]) => {
|
|
36345
|
+
const gateState = getCachedLicenseGate2();
|
|
36346
|
+
const index = getToolCapabilityIndex2();
|
|
36347
|
+
await index.buildIndex(
|
|
36348
|
+
(fakeServer) => registerAllTools2(fakeServer, gateState.license, gateState.hasKey),
|
|
36349
|
+
TOOL_CATEGORIES2
|
|
36350
|
+
);
|
|
36351
|
+
}).catch((err) => {
|
|
36352
|
+
process.stderr.write(`[exed] Tool capability index failed: ${err.message}
|
|
36353
|
+
`);
|
|
36354
|
+
});
|
|
35481
36355
|
const transports = /* @__PURE__ */ new Map();
|
|
35482
36356
|
const MCP_HTTP_PORT = parseInt(process.env.EXE_MCP_PORT || "48739", 10);
|
|
35483
36357
|
const MCP_SESSION_TTL_MS = parseDurationMs2(process.env.EXE_MCP_SESSION_TTL_MS, 30 * 60 * 1e3, { allowZero: true });
|