@askexenow/exe-os 0.9.93 → 0.9.94
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 +118 -13
- package/dist/bin/cli.js +1558 -466
- package/dist/bin/customer-readiness.js +51 -0
- package/dist/bin/exe-agent.js +17 -3
- package/dist/bin/exe-assign.js +75 -9
- package/dist/bin/exe-boot.js +111 -12
- package/dist/bin/exe-call.js +17 -3
- package/dist/bin/exe-cloud.js +76 -10
- package/dist/bin/exe-dispatch.js +133 -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 +132 -18
- package/dist/bin/exe-heartbeat.js +118 -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 +118 -13
- package/dist/bin/exe-pending-notifications.js +118 -13
- package/dist/bin/exe-pending-reviews.js +118 -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 +133 -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 +118 -13
- package/dist/bin/exe-support.js +1 -0
- package/dist/bin/exe-team.js +75 -9
- package/dist/bin/git-sweep.js +133 -18
- package/dist/bin/graph-backfill.js +65 -8
- package/dist/bin/graph-export.js +75 -9
- package/dist/bin/intercom-check.js +133 -18
- package/dist/bin/scan-tasks.js +133 -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 +133 -18
- package/dist/hooks/bug-report-worker.js +133 -18
- package/dist/hooks/codex-stop-task-finalizer.js +123 -14
- package/dist/hooks/commit-complete.js +133 -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 +310 -50
- package/dist/hooks/post-tool-combined.js +433 -13
- package/dist/hooks/pre-compact.js +133 -18
- package/dist/hooks/pre-tool-use.js +118 -13
- package/dist/hooks/prompt-submit.js +191 -19
- package/dist/hooks/session-end.js +133 -18
- package/dist/hooks/session-start.js +143 -13
- package/dist/hooks/stop.js +118 -13
- package/dist/hooks/subagent-stop.js +118 -13
- package/dist/hooks/summary-worker.js +96 -7
- package/dist/index.js +133 -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 +913 -42
- package/dist/lib/hybrid-search.js +100 -9
- package/dist/lib/license.js +1 -1
- package/dist/lib/messaging.js +40 -4
- package/dist/lib/schedules.js +54 -3
- package/dist/lib/store.js +75 -9
- package/dist/lib/tasks.js +58 -9
- package/dist/lib/tmux-routing.js +58 -9
- package/dist/mcp/server.js +875 -42
- package/dist/mcp/tools/create-task.js +67 -12
- package/dist/mcp/tools/list-tasks.js +46 -5
- package/dist/mcp/tools/send-message.js +40 -4
- package/dist/mcp/tools/update-task.js +58 -9
- package/dist/runtime/index.js +133 -18
- package/dist/tui/App.js +132 -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 your own memories (semantic + FTS). memory(action="ask_team") / ask_team_memory: search a colleague's memories by agent name. memory(action="store") / store_memory: persist a memory. memory(action="commit") / commit_memory: high-importance memory that survives consolidation. Requires summary. memory(action="search") / search_everything: unified search across memories, tasks, entities, conversations. memory(action="session_context") / get_session_context: temporal memory window. Requires session_id + target_timestamp. memory(action="consolidate") / consolidate_memories: merge duplicate/related memories. memory(action="cardinality") / get_memory_cardinality: count memories per agent. 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.`
|
|
6019
|
+
content: `memory(action="recall") / recall_my_memory: search your own memories (semantic + FTS). Supports as_of param for bi-temporal queries (what did I know at time X?), kind param to filter by memory type (decision, procedure, observation, raw, conversation, behavior). memory(action="ask_team") / ask_team_memory: search a colleague's memories by agent name. memory(action="store") / store_memory: persist a memory. Supports kind param and procedure_for domain tag for procedure-type memories. memory(action="commit") / commit_memory: high-importance memory that survives consolidation. Requires summary. memory(action="search") / search_everything: unified search across memories, tasks, entities, conversations. memory(action="session_context") / get_session_context: temporal memory window. Requires session_id + target_timestamp. memory(action="consolidate") / consolidate_memories: merge duplicate/related memories. memory(action="cardinality") / get_memory_cardinality: count memories per agent. memory(action="supersede") / 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:
|
|
6025
|
+
content: `task(action="create") / create_task: dispatch work (title, assigned_to, context). The ONLY dispatch path. Auto-spawns session. Supports spawn_runtime and spawn_model params to override the agent's default runtime/model for a specific task. 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="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. diagnostics(action="tool_search"): semantic tool discovery \u2014 find relevant MCP tools by natural language query. Returns top-K tools ranked by relevance. diagnostics(action="drift"): identity drift detection \u2014 score how far an agent has drifted from its role identity. Returns drift score + recommendations. 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
|
});
|
|
@@ -12720,6 +12895,7 @@ function resolveExeSession() {
|
|
|
12720
12895
|
const mySession = getMySession();
|
|
12721
12896
|
if (!mySession) return null;
|
|
12722
12897
|
const fromSessionName = extractRootExe(mySession);
|
|
12898
|
+
let candidate = null;
|
|
12723
12899
|
try {
|
|
12724
12900
|
const key = getSessionKey();
|
|
12725
12901
|
const parentExe = getParentExe(key);
|
|
@@ -12730,13 +12906,47 @@ function resolveExeSession() {
|
|
|
12730
12906
|
`[tmux-routing] WARN: cache says "${fromCache}" but session name says "${fromSessionName}". Trusting session name.
|
|
12731
12907
|
`
|
|
12732
12908
|
);
|
|
12733
|
-
|
|
12909
|
+
candidate = fromSessionName;
|
|
12910
|
+
} else {
|
|
12911
|
+
candidate = fromCache;
|
|
12734
12912
|
}
|
|
12735
|
-
return fromCache;
|
|
12736
12913
|
}
|
|
12737
12914
|
} catch {
|
|
12738
12915
|
}
|
|
12739
|
-
|
|
12916
|
+
if (!candidate) {
|
|
12917
|
+
candidate = fromSessionName ?? mySession;
|
|
12918
|
+
}
|
|
12919
|
+
if (candidate && isRootSession(candidate)) {
|
|
12920
|
+
try {
|
|
12921
|
+
const transport = getTransport();
|
|
12922
|
+
const liveSessions = transport.listSessions();
|
|
12923
|
+
if (!liveSessions.includes(candidate)) {
|
|
12924
|
+
const liveRoots = liveSessions.filter((s) => isRootSession(s));
|
|
12925
|
+
if (liveRoots.length === 1) {
|
|
12926
|
+
process.stderr.write(
|
|
12927
|
+
`[tmux-routing] WARN: resolved session "${candidate}" is dead. Using live coordinator "${liveRoots[0]}".
|
|
12928
|
+
`
|
|
12929
|
+
);
|
|
12930
|
+
return liveRoots[0];
|
|
12931
|
+
} else if (liveRoots.length > 1) {
|
|
12932
|
+
const base = candidate.replace(/\d+$/, "");
|
|
12933
|
+
const match = liveRoots.find((s) => s.startsWith(base));
|
|
12934
|
+
const chosen = match ?? liveRoots[0];
|
|
12935
|
+
process.stderr.write(
|
|
12936
|
+
`[tmux-routing] WARN: resolved session "${candidate}" is dead. ${liveRoots.length} live roots found, using "${chosen}".
|
|
12937
|
+
`
|
|
12938
|
+
);
|
|
12939
|
+
return chosen;
|
|
12940
|
+
}
|
|
12941
|
+
process.stderr.write(
|
|
12942
|
+
`[tmux-routing] WARN: resolved session "${candidate}" is dead and no live coordinator found.
|
|
12943
|
+
`
|
|
12944
|
+
);
|
|
12945
|
+
}
|
|
12946
|
+
} catch {
|
|
12947
|
+
}
|
|
12948
|
+
}
|
|
12949
|
+
return candidate;
|
|
12740
12950
|
}
|
|
12741
12951
|
function isEmployeeAlive(sessionName) {
|
|
12742
12952
|
return getTransport().isAlive(sessionName);
|
|
@@ -13138,7 +13348,12 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
13138
13348
|
}
|
|
13139
13349
|
const spawnCwd = opts?.cwd ?? projectDir;
|
|
13140
13350
|
const useExeAgent = !!(opts?.model && opts?.provider);
|
|
13141
|
-
const
|
|
13351
|
+
const baseRtConfig = getAgentRuntime(employeeName);
|
|
13352
|
+
const agentRtConfig = {
|
|
13353
|
+
...baseRtConfig,
|
|
13354
|
+
...opts?.runtimeOverride ? { runtime: opts.runtimeOverride } : {},
|
|
13355
|
+
...opts?.modelOverride ? { model: opts.modelOverride } : {}
|
|
13356
|
+
};
|
|
13142
13357
|
const useCodex = !useExeAgent && agentRtConfig.runtime === "codex";
|
|
13143
13358
|
const useOpencode = !useExeAgent && !useCodex && agentRtConfig.runtime === "opencode";
|
|
13144
13359
|
const ccProvider = useExeAgent || useCodex || useOpencode ? DEFAULT_PROVIDER : detectActiveProvider();
|
|
@@ -13756,8 +13971,8 @@ ${scopeMismatchWarning}` : scopeMismatchWarning;
|
|
|
13756
13971
|
const complexity = input.complexity ?? "standard";
|
|
13757
13972
|
const sessionScope = earlySessionScope;
|
|
13758
13973
|
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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
13974
|
+
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)
|
|
13975
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
13761
13976
|
args: [
|
|
13762
13977
|
id,
|
|
13763
13978
|
input.title,
|
|
@@ -13777,6 +13992,8 @@ ${scopeMismatchWarning}` : scopeMismatchWarning;
|
|
|
13777
13992
|
0,
|
|
13778
13993
|
null,
|
|
13779
13994
|
sessionScope,
|
|
13995
|
+
input.spawnRuntime ?? null,
|
|
13996
|
+
input.spawnModel ?? null,
|
|
13780
13997
|
now2,
|
|
13781
13998
|
now2
|
|
13782
13999
|
]
|
|
@@ -13833,7 +14050,9 @@ ${input.context}
|
|
|
13833
14050
|
budgetTokens: input.budgetTokens ?? null,
|
|
13834
14051
|
budgetFallbackModel: input.budgetFallbackModel ?? null,
|
|
13835
14052
|
tokensUsed: 0,
|
|
13836
|
-
tokensWarnedAt: null
|
|
14053
|
+
tokensWarnedAt: null,
|
|
14054
|
+
spawnRuntime: input.spawnRuntime ?? null,
|
|
14055
|
+
spawnModel: input.spawnModel ?? null
|
|
13837
14056
|
};
|
|
13838
14057
|
}
|
|
13839
14058
|
async function listTasks(input) {
|
|
@@ -13883,7 +14102,9 @@ async function listTasks(input) {
|
|
|
13883
14102
|
budgetTokens: r.budget_tokens !== null ? Number(r.budget_tokens) : null,
|
|
13884
14103
|
budgetFallbackModel: r.budget_fallback_model !== null ? String(r.budget_fallback_model) : null,
|
|
13885
14104
|
tokensUsed: Number(r.tokens_used ?? 0),
|
|
13886
|
-
tokensWarnedAt: r.tokens_warned_at !== null ? Number(r.tokens_warned_at) : null
|
|
14105
|
+
tokensWarnedAt: r.tokens_warned_at !== null ? Number(r.tokens_warned_at) : null,
|
|
14106
|
+
spawnRuntime: r.spawn_runtime !== null && r.spawn_runtime !== void 0 ? String(r.spawn_runtime) : null,
|
|
14107
|
+
spawnModel: r.spawn_model !== null && r.spawn_model !== void 0 ? String(r.spawn_model) : null
|
|
13887
14108
|
}));
|
|
13888
14109
|
}
|
|
13889
14110
|
function isTmuxSessionAlive(identifier) {
|
|
@@ -14833,6 +15054,8 @@ async function updateTask(input) {
|
|
|
14833
15054
|
budgetFallbackModel: row.budget_fallback_model !== void 0 && row.budget_fallback_model !== null ? String(row.budget_fallback_model) : null,
|
|
14834
15055
|
tokensUsed: Number(row.tokens_used ?? 0),
|
|
14835
15056
|
tokensWarnedAt: row.tokens_warned_at !== void 0 && row.tokens_warned_at !== null ? Number(row.tokens_warned_at) : null,
|
|
15057
|
+
spawnRuntime: row.spawn_runtime !== void 0 && row.spawn_runtime !== null ? String(row.spawn_runtime) : null,
|
|
15058
|
+
spawnModel: row.spawn_model !== void 0 && row.spawn_model !== null ? String(row.spawn_model) : null,
|
|
14836
15059
|
nextTask
|
|
14837
15060
|
};
|
|
14838
15061
|
}
|
|
@@ -15572,10 +15795,12 @@ function registerCreateTask(server) {
|
|
|
15572
15795
|
parent_task_id: z12.string().optional().describe("Parent task ID or slug. Links this task as a subtask."),
|
|
15573
15796
|
reviewer: z12.string().optional().describe("Who should review this task when done. Defaults to assigner."),
|
|
15574
15797
|
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")
|
|
15798
|
+
budget_fallback_model: z12.string().optional().describe("Model to route to when budget is exhausted"),
|
|
15799
|
+
spawn_runtime: z12.string().optional().describe("Override runtime for spawned session (e.g., 'claude', 'codex', 'opencode')"),
|
|
15800
|
+
spawn_model: z12.string().optional().describe("Override model for spawned session (e.g., 'claude-sonnet-4.6', 'claude-haiku-4.5')")
|
|
15576
15801
|
}
|
|
15577
15802
|
},
|
|
15578
|
-
async ({ title, assigned_to, project_name, priority, complexity, context, blocked_by, parent_task_id, reviewer, budget_tokens, budget_fallback_model }) => {
|
|
15803
|
+
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
15804
|
if (!isCoordinatorName(assigned_to)) {
|
|
15580
15805
|
const license = getLicenseSync();
|
|
15581
15806
|
if (license.plan === "free") {
|
|
@@ -15603,6 +15828,8 @@ function registerCreateTask(server) {
|
|
|
15603
15828
|
reviewer,
|
|
15604
15829
|
budgetTokens: budget_tokens,
|
|
15605
15830
|
budgetFallbackModel: budget_fallback_model,
|
|
15831
|
+
spawnRuntime: spawn_runtime,
|
|
15832
|
+
spawnModel: spawn_model,
|
|
15606
15833
|
// Skip internal dispatch — we handle it below with autoInstance
|
|
15607
15834
|
// support. Without this, createTask fires dispatchTaskToEmployee
|
|
15608
15835
|
// (no autoInstance) in parallel, racing with our ensureEmployee
|
|
@@ -15640,7 +15867,9 @@ function registerCreateTask(server) {
|
|
|
15640
15867
|
const cfg = loadConfigSync2();
|
|
15641
15868
|
const result3 = ensureEmployee(assigned_to, exeSession, process.cwd(), {
|
|
15642
15869
|
autoInstance: useAutoInstance,
|
|
15643
|
-
maxAutoInstances: useAutoInstance ? cfg.sessionLifecycle.maxAutoInstances : void 0
|
|
15870
|
+
maxAutoInstances: useAutoInstance ? cfg.sessionLifecycle.maxAutoInstances : void 0,
|
|
15871
|
+
runtimeOverride: spawn_runtime ?? void 0,
|
|
15872
|
+
modelOverride: spawn_model ?? void 0
|
|
15644
15873
|
});
|
|
15645
15874
|
switch (result3.status) {
|
|
15646
15875
|
case "intercom_sent":
|
|
@@ -15881,6 +16110,14 @@ function registerGetTask(server) {
|
|
|
15881
16110
|
}
|
|
15882
16111
|
}
|
|
15883
16112
|
}
|
|
16113
|
+
const spawnRuntime = row.spawn_runtime ? String(row.spawn_runtime) : null;
|
|
16114
|
+
const spawnModel = row.spawn_model ? String(row.spawn_model) : null;
|
|
16115
|
+
if (spawnRuntime || spawnModel) {
|
|
16116
|
+
lines.push("");
|
|
16117
|
+
lines.push("**Spawn Override:**");
|
|
16118
|
+
if (spawnRuntime) lines.push(`Runtime: ${spawnRuntime}`);
|
|
16119
|
+
if (spawnModel) lines.push(`Model: ${spawnModel}`);
|
|
16120
|
+
}
|
|
15884
16121
|
if (row.context) {
|
|
15885
16122
|
lines.push("", "## Context", "", contextText);
|
|
15886
16123
|
}
|
|
@@ -16343,6 +16580,8 @@ function registerTask(server) {
|
|
|
16343
16580
|
reviewer: z19.string().optional().describe("Reviewer for action=create"),
|
|
16344
16581
|
budget_tokens: z19.number().optional().describe("Max token budget for action=create"),
|
|
16345
16582
|
budget_fallback_model: z19.string().optional().describe("Fallback model for action=create"),
|
|
16583
|
+
spawn_runtime: z19.string().optional().describe("Override runtime for spawned session (e.g., 'claude', 'codex', 'opencode') for action=create"),
|
|
16584
|
+
spawn_model: z19.string().optional().describe("Override model for spawned session (e.g., 'claude-sonnet-4.6') for action=create"),
|
|
16346
16585
|
status: z19.enum(["open", "in_progress", "done", "needs_review", "blocked", "cancelled", "closed"]).optional().describe("Status for action=update/list/close"),
|
|
16347
16586
|
result: z19.string().optional().describe("Result summary for action=update or action=close"),
|
|
16348
16587
|
step: z19.string().optional().describe("Checkpoint step for action=checkpoint"),
|
|
@@ -30442,6 +30681,15 @@ function registerCreateBugReport(server) {
|
|
|
30442
30681
|
project_name,
|
|
30443
30682
|
send_upstream
|
|
30444
30683
|
}) => {
|
|
30684
|
+
if (!summary || summary.trim().length === 0) {
|
|
30685
|
+
return {
|
|
30686
|
+
content: [{
|
|
30687
|
+
type: "text",
|
|
30688
|
+
text: "Error: summary is required but was empty. If calling via support(action='create_bug'), use 'description' which maps to 'summary'."
|
|
30689
|
+
}],
|
|
30690
|
+
isError: true
|
|
30691
|
+
};
|
|
30692
|
+
}
|
|
30445
30693
|
const { agentId, agentRole } = getActiveAgent();
|
|
30446
30694
|
const id = crypto19.randomUUID();
|
|
30447
30695
|
const version = package_version ?? "unknown";
|
|
@@ -33024,6 +33272,25 @@ function registerSupportConsolidated(server) {
|
|
|
33024
33272
|
const handler = handlers.get(toolName);
|
|
33025
33273
|
if (!handler) return { content: [{ type: "text", text: `Handler not found: ${toolName}` }], isError: true };
|
|
33026
33274
|
const { action: _, ...args } = input;
|
|
33275
|
+
if (action === "create_bug") {
|
|
33276
|
+
if (args.description && !args.summary) {
|
|
33277
|
+
args.summary = args.description;
|
|
33278
|
+
delete args.description;
|
|
33279
|
+
}
|
|
33280
|
+
if (args.steps_to_reproduce && !args.reproduction_steps) {
|
|
33281
|
+
const raw = args.steps_to_reproduce;
|
|
33282
|
+
args.reproduction_steps = raw.split(/\n/).map((s) => s.replace(/^\d+\.\s*/, "").trim()).filter(Boolean);
|
|
33283
|
+
delete args.steps_to_reproduce;
|
|
33284
|
+
}
|
|
33285
|
+
if (args.expected_behavior && !args.expected) {
|
|
33286
|
+
args.expected = args.expected_behavior;
|
|
33287
|
+
delete args.expected_behavior;
|
|
33288
|
+
}
|
|
33289
|
+
if (args.actual_behavior && !args.actual) {
|
|
33290
|
+
args.actual = args.actual_behavior;
|
|
33291
|
+
delete args.actual_behavior;
|
|
33292
|
+
}
|
|
33293
|
+
}
|
|
33027
33294
|
if ((action === "triage_bug" || action === "triage_feature") && args.notes && !args.triage_notes) {
|
|
33028
33295
|
args.triage_notes = args.notes;
|
|
33029
33296
|
delete args.notes;
|
|
@@ -33060,6 +33327,513 @@ var init_support_consolidated = __esm({
|
|
|
33060
33327
|
}
|
|
33061
33328
|
});
|
|
33062
33329
|
|
|
33330
|
+
// src/lib/tool-capability-index.ts
|
|
33331
|
+
var tool_capability_index_exports = {};
|
|
33332
|
+
__export(tool_capability_index_exports, {
|
|
33333
|
+
ToolCapabilityIndex: () => ToolCapabilityIndex,
|
|
33334
|
+
getToolCapabilityIndex: () => getToolCapabilityIndex
|
|
33335
|
+
});
|
|
33336
|
+
function categoryForToolName(toolName, categoryMap) {
|
|
33337
|
+
const normalized = toolName.replace(/[_-]/g, "").toLowerCase();
|
|
33338
|
+
for (const [registerFn, cat] of Object.entries(categoryMap)) {
|
|
33339
|
+
const fnNormalized = registerFn.replace(/^register/, "").toLowerCase();
|
|
33340
|
+
if (fnNormalized === normalized) return cat;
|
|
33341
|
+
}
|
|
33342
|
+
return "unknown";
|
|
33343
|
+
}
|
|
33344
|
+
function extractParamNames(inputSchema) {
|
|
33345
|
+
if (!inputSchema || typeof inputSchema !== "object") return "";
|
|
33346
|
+
return Object.keys(inputSchema).join(", ");
|
|
33347
|
+
}
|
|
33348
|
+
function cosineSimilarity4(a, b) {
|
|
33349
|
+
if (a.length !== b.length || a.length === 0) return 0;
|
|
33350
|
+
let dot = 0, normA = 0, normB = 0;
|
|
33351
|
+
for (let i = 0; i < a.length; i++) {
|
|
33352
|
+
dot += a[i] * b[i];
|
|
33353
|
+
normA += a[i] * a[i];
|
|
33354
|
+
normB += b[i] * b[i];
|
|
33355
|
+
}
|
|
33356
|
+
const denom = Math.sqrt(normA) * Math.sqrt(normB);
|
|
33357
|
+
return denom === 0 ? 0 : dot / denom;
|
|
33358
|
+
}
|
|
33359
|
+
function keywordScore(query, tool) {
|
|
33360
|
+
const words = query.toLowerCase().split(/\s+/).filter((w) => w.length > 2);
|
|
33361
|
+
if (words.length === 0) return 0;
|
|
33362
|
+
const searchText = `${tool.name} ${tool.description} ${tool.category} ${tool.paramSummary}`.toLowerCase();
|
|
33363
|
+
let matches = 0;
|
|
33364
|
+
for (const word of words) {
|
|
33365
|
+
if (searchText.includes(word)) matches++;
|
|
33366
|
+
}
|
|
33367
|
+
return matches / words.length;
|
|
33368
|
+
}
|
|
33369
|
+
function getToolCapabilityIndex() {
|
|
33370
|
+
if (!_instance) {
|
|
33371
|
+
_instance = new ToolCapabilityIndex();
|
|
33372
|
+
}
|
|
33373
|
+
return _instance;
|
|
33374
|
+
}
|
|
33375
|
+
var ALWAYS_ON, ToolCapabilityIndex, _instance;
|
|
33376
|
+
var init_tool_capability_index = __esm({
|
|
33377
|
+
"src/lib/tool-capability-index.ts"() {
|
|
33378
|
+
"use strict";
|
|
33379
|
+
init_memory();
|
|
33380
|
+
ALWAYS_ON = /* @__PURE__ */ new Set([
|
|
33381
|
+
"mcp_ping",
|
|
33382
|
+
"memory",
|
|
33383
|
+
"task",
|
|
33384
|
+
"message",
|
|
33385
|
+
"identity",
|
|
33386
|
+
"diagnostics",
|
|
33387
|
+
"session"
|
|
33388
|
+
]);
|
|
33389
|
+
ToolCapabilityIndex = class {
|
|
33390
|
+
capabilities = [];
|
|
33391
|
+
initialized = false;
|
|
33392
|
+
/**
|
|
33393
|
+
* Build the index by intercepting registerAllTools via a fake McpServer.
|
|
33394
|
+
*
|
|
33395
|
+
* @param registerFn - function that registers tools on a server (e.g. registerAllTools)
|
|
33396
|
+
* @param categoryMap - optional map of registerFnName → category (from tool-gates TOOL_CATEGORIES)
|
|
33397
|
+
*/
|
|
33398
|
+
async buildIndex(registerFn, categoryMap) {
|
|
33399
|
+
const captured = [];
|
|
33400
|
+
const fakeServer = {
|
|
33401
|
+
registerTool(name, config2, _handler) {
|
|
33402
|
+
captured.push({
|
|
33403
|
+
name,
|
|
33404
|
+
description: config2.description ?? "",
|
|
33405
|
+
inputSchema: config2.inputSchema ?? {}
|
|
33406
|
+
});
|
|
33407
|
+
}
|
|
33408
|
+
};
|
|
33409
|
+
registerFn(fakeServer);
|
|
33410
|
+
let embedFn = null;
|
|
33411
|
+
try {
|
|
33412
|
+
const { embed: embed2 } = await Promise.resolve().then(() => (init_embedder(), embedder_exports));
|
|
33413
|
+
const test = await embed2("test");
|
|
33414
|
+
if (test.length === EMBEDDING_DIM) {
|
|
33415
|
+
embedFn = embed2;
|
|
33416
|
+
}
|
|
33417
|
+
} catch {
|
|
33418
|
+
}
|
|
33419
|
+
const capabilities = [];
|
|
33420
|
+
for (const tool of captured) {
|
|
33421
|
+
const paramSummary = extractParamNames(tool.inputSchema);
|
|
33422
|
+
const category = categoryMap ? categoryForToolName(tool.name, categoryMap) : "unknown";
|
|
33423
|
+
const capabilityDoc = `${tool.name}: ${tool.description}. Parameters: ${paramSummary}`;
|
|
33424
|
+
let vector = null;
|
|
33425
|
+
if (embedFn) {
|
|
33426
|
+
try {
|
|
33427
|
+
vector = await embedFn(capabilityDoc.slice(0, 500));
|
|
33428
|
+
} catch {
|
|
33429
|
+
}
|
|
33430
|
+
}
|
|
33431
|
+
capabilities.push({
|
|
33432
|
+
name: tool.name,
|
|
33433
|
+
description: tool.description,
|
|
33434
|
+
category,
|
|
33435
|
+
vector,
|
|
33436
|
+
paramSummary
|
|
33437
|
+
});
|
|
33438
|
+
}
|
|
33439
|
+
this.capabilities = capabilities;
|
|
33440
|
+
this.initialized = true;
|
|
33441
|
+
process.stderr.write(
|
|
33442
|
+
`[tool-capability-index] Indexed ${capabilities.length} tools (${capabilities.filter((c) => c.vector).length} with vectors)
|
|
33443
|
+
`
|
|
33444
|
+
);
|
|
33445
|
+
}
|
|
33446
|
+
/**
|
|
33447
|
+
* Semantic search for tools matching a natural-language query.
|
|
33448
|
+
* Returns tools sorted by relevance, with always-on tools boosted.
|
|
33449
|
+
*/
|
|
33450
|
+
async search(query, limit = 20) {
|
|
33451
|
+
if (!this.initialized || this.capabilities.length === 0) return [];
|
|
33452
|
+
let queryVector = null;
|
|
33453
|
+
try {
|
|
33454
|
+
const { embed: embed2 } = await Promise.resolve().then(() => (init_embedder(), embedder_exports));
|
|
33455
|
+
queryVector = await embed2(query);
|
|
33456
|
+
} catch {
|
|
33457
|
+
}
|
|
33458
|
+
const scored = [];
|
|
33459
|
+
for (const tool of this.capabilities) {
|
|
33460
|
+
let relevance;
|
|
33461
|
+
if (queryVector && tool.vector) {
|
|
33462
|
+
const vecScore = cosineSimilarity4(queryVector, tool.vector);
|
|
33463
|
+
const kwScore = keywordScore(query, tool);
|
|
33464
|
+
relevance = vecScore * 0.8 + kwScore * 0.2;
|
|
33465
|
+
} else {
|
|
33466
|
+
relevance = keywordScore(query, tool);
|
|
33467
|
+
}
|
|
33468
|
+
if (ALWAYS_ON.has(tool.name)) {
|
|
33469
|
+
relevance = Math.max(relevance, 0.5);
|
|
33470
|
+
}
|
|
33471
|
+
scored.push({ ...tool, relevance });
|
|
33472
|
+
}
|
|
33473
|
+
scored.sort((a, b) => b.relevance - a.relevance);
|
|
33474
|
+
return scored.slice(0, limit);
|
|
33475
|
+
}
|
|
33476
|
+
/** Whether the index has been built. */
|
|
33477
|
+
isReady() {
|
|
33478
|
+
return this.initialized;
|
|
33479
|
+
}
|
|
33480
|
+
/** Total number of indexed tools. */
|
|
33481
|
+
get toolCount() {
|
|
33482
|
+
return this.capabilities.length;
|
|
33483
|
+
}
|
|
33484
|
+
};
|
|
33485
|
+
_instance = null;
|
|
33486
|
+
}
|
|
33487
|
+
});
|
|
33488
|
+
|
|
33489
|
+
// src/lib/drift-probes.ts
|
|
33490
|
+
async function getRecentMemories(agentId, limit) {
|
|
33491
|
+
try {
|
|
33492
|
+
const { getClient: getClient2, isInitialized: isInitialized2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
33493
|
+
if (!isInitialized2()) return { count: 0, texts: [] };
|
|
33494
|
+
const client = getClient2();
|
|
33495
|
+
const result3 = await client.execute({
|
|
33496
|
+
sql: `SELECT text FROM memories WHERE agent_id = ? ORDER BY created_at DESC LIMIT ?`,
|
|
33497
|
+
args: [agentId, limit]
|
|
33498
|
+
});
|
|
33499
|
+
const texts = result3.rows.map((r) => String(r.text ?? ""));
|
|
33500
|
+
return { count: texts.length, texts };
|
|
33501
|
+
} catch {
|
|
33502
|
+
return { count: 0, texts: [] };
|
|
33503
|
+
}
|
|
33504
|
+
}
|
|
33505
|
+
async function getDecisionCount(agentId) {
|
|
33506
|
+
try {
|
|
33507
|
+
const { getClient: getClient2, isInitialized: isInitialized2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
33508
|
+
if (!isInitialized2()) return 0;
|
|
33509
|
+
const client = getClient2();
|
|
33510
|
+
const result3 = await client.execute({
|
|
33511
|
+
sql: `SELECT COUNT(*) as cnt FROM memories WHERE agent_id = ? AND memory_type = 'decision'`,
|
|
33512
|
+
args: [agentId]
|
|
33513
|
+
});
|
|
33514
|
+
return Number(result3.rows[0]?.cnt ?? 0);
|
|
33515
|
+
} catch {
|
|
33516
|
+
return 0;
|
|
33517
|
+
}
|
|
33518
|
+
}
|
|
33519
|
+
function probeContinuity(ctx) {
|
|
33520
|
+
const memCount = ctx.recentMemoryCount;
|
|
33521
|
+
let score;
|
|
33522
|
+
let detail;
|
|
33523
|
+
if (memCount >= 20) {
|
|
33524
|
+
score = 95;
|
|
33525
|
+
detail = `${memCount} recent memories \u2014 strong continuity`;
|
|
33526
|
+
} else if (memCount >= 10) {
|
|
33527
|
+
score = 85;
|
|
33528
|
+
detail = `${memCount} recent memories \u2014 adequate continuity`;
|
|
33529
|
+
} else if (memCount >= 3) {
|
|
33530
|
+
score = 70;
|
|
33531
|
+
detail = `${memCount} recent memories \u2014 limited continuity`;
|
|
33532
|
+
} else if (memCount >= 1) {
|
|
33533
|
+
score = 50;
|
|
33534
|
+
detail = `${memCount} recent memories \u2014 weak continuity`;
|
|
33535
|
+
} else {
|
|
33536
|
+
score = 30;
|
|
33537
|
+
detail = "No recent memories \u2014 agent may lack session context";
|
|
33538
|
+
}
|
|
33539
|
+
if (ctx.storedDecisionCount > 0) {
|
|
33540
|
+
score = Math.min(100, score + 5);
|
|
33541
|
+
detail += ` (+${ctx.storedDecisionCount} decisions)`;
|
|
33542
|
+
}
|
|
33543
|
+
return { axis: "continuity", score, detail };
|
|
33544
|
+
}
|
|
33545
|
+
function probeConsistency(ctx) {
|
|
33546
|
+
if (!ctx.identityBody || ctx.recentMemoryTexts.length === 0) {
|
|
33547
|
+
return {
|
|
33548
|
+
axis: "consistency",
|
|
33549
|
+
score: ctx.identityBody ? 80 : 50,
|
|
33550
|
+
detail: ctx.identityBody ? "No memories to check against identity" : "No identity file \u2014 cannot assess consistency"
|
|
33551
|
+
};
|
|
33552
|
+
}
|
|
33553
|
+
const identityTerms = extractKeyTerms(ctx.identityBody);
|
|
33554
|
+
if (identityTerms.length === 0) {
|
|
33555
|
+
return { axis: "consistency", score: 75, detail: "Identity has no extractable key terms" };
|
|
33556
|
+
}
|
|
33557
|
+
const memoryText = ctx.recentMemoryTexts.join(" ").toLowerCase();
|
|
33558
|
+
let matched = 0;
|
|
33559
|
+
for (const term of identityTerms) {
|
|
33560
|
+
if (memoryText.includes(term.toLowerCase())) matched++;
|
|
33561
|
+
}
|
|
33562
|
+
const ratio = matched / identityTerms.length;
|
|
33563
|
+
const score = Math.round(50 + ratio * 50);
|
|
33564
|
+
const detail = `${matched}/${identityTerms.length} identity terms found in recent memories`;
|
|
33565
|
+
return { axis: "consistency", score, detail };
|
|
33566
|
+
}
|
|
33567
|
+
function probeRoleFidelity(ctx) {
|
|
33568
|
+
const flags = [];
|
|
33569
|
+
if (!ctx.identityBody) {
|
|
33570
|
+
return {
|
|
33571
|
+
axis: "role-fidelity",
|
|
33572
|
+
score: 40,
|
|
33573
|
+
detail: `No identity file for ${ctx.agent.name}`
|
|
33574
|
+
};
|
|
33575
|
+
}
|
|
33576
|
+
let score = 100;
|
|
33577
|
+
const identityLower = ctx.identityBody.toLowerCase();
|
|
33578
|
+
const rosterRole = ctx.agent.role.toLowerCase();
|
|
33579
|
+
if (!identityLower.includes(rosterRole)) {
|
|
33580
|
+
score -= 15;
|
|
33581
|
+
flags.push(`Identity does not mention role "${ctx.agent.role}"`);
|
|
33582
|
+
}
|
|
33583
|
+
if (!identityLower.includes(ctx.agent.name.toLowerCase())) {
|
|
33584
|
+
score -= 10;
|
|
33585
|
+
flags.push(`Identity does not mention agent name "${ctx.agent.name}"`);
|
|
33586
|
+
}
|
|
33587
|
+
const hasScopeBoundary = identityLower.includes("do not") || identityLower.includes("don't") || identityLower.includes("not your") || identityLower.includes("outside your") || identityLower.includes("you do not");
|
|
33588
|
+
if (!hasScopeBoundary) {
|
|
33589
|
+
score -= 10;
|
|
33590
|
+
flags.push("Identity lacks explicit scope boundaries (what NOT to do)");
|
|
33591
|
+
}
|
|
33592
|
+
if (ctx.agent.systemPrompt) {
|
|
33593
|
+
const promptTerms = extractKeyTerms(ctx.agent.systemPrompt);
|
|
33594
|
+
const identityText = ctx.identityBody.toLowerCase();
|
|
33595
|
+
let promptMatched = 0;
|
|
33596
|
+
for (const term of promptTerms.slice(0, 20)) {
|
|
33597
|
+
if (identityText.includes(term.toLowerCase())) promptMatched++;
|
|
33598
|
+
}
|
|
33599
|
+
const promptRatio = promptTerms.length > 0 ? promptMatched / Math.min(promptTerms.length, 20) : 1;
|
|
33600
|
+
if (promptRatio < 0.3) {
|
|
33601
|
+
score -= 15;
|
|
33602
|
+
flags.push("Identity content diverges significantly from roster systemPrompt");
|
|
33603
|
+
}
|
|
33604
|
+
}
|
|
33605
|
+
if (ctx.recentMemoryTexts.length > 5) {
|
|
33606
|
+
const roleKeywords = extractRoleKeywords(ctx.agent.role);
|
|
33607
|
+
const memoryText = ctx.recentMemoryTexts.join(" ").toLowerCase();
|
|
33608
|
+
let domainHits = 0;
|
|
33609
|
+
for (const kw of roleKeywords) {
|
|
33610
|
+
if (memoryText.includes(kw)) domainHits++;
|
|
33611
|
+
}
|
|
33612
|
+
const domainRatio = roleKeywords.length > 0 ? domainHits / roleKeywords.length : 1;
|
|
33613
|
+
if (domainRatio < 0.2) {
|
|
33614
|
+
score -= 10;
|
|
33615
|
+
flags.push(`Recent work shows little overlap with ${ctx.agent.role} domain keywords`);
|
|
33616
|
+
}
|
|
33617
|
+
}
|
|
33618
|
+
score = Math.max(0, Math.min(100, score));
|
|
33619
|
+
const detail = flags.length > 0 ? flags.join("; ") : "Identity aligns with roster definition";
|
|
33620
|
+
return { axis: "role-fidelity", score, detail };
|
|
33621
|
+
}
|
|
33622
|
+
function probeWorldModel(ctx) {
|
|
33623
|
+
if (!ctx.identityBody) {
|
|
33624
|
+
return {
|
|
33625
|
+
axis: "world-model",
|
|
33626
|
+
score: 50,
|
|
33627
|
+
detail: "No identity file \u2014 cannot assess org awareness"
|
|
33628
|
+
};
|
|
33629
|
+
}
|
|
33630
|
+
const identityLower = ctx.identityBody.toLowerCase();
|
|
33631
|
+
const flags = [];
|
|
33632
|
+
let score = 100;
|
|
33633
|
+
const otherAgents = ctx.allEmployees.filter((e) => e.name !== ctx.agent.name);
|
|
33634
|
+
let mentionedAgents = 0;
|
|
33635
|
+
for (const other of otherAgents) {
|
|
33636
|
+
if (identityLower.includes(other.name.toLowerCase())) mentionedAgents++;
|
|
33637
|
+
}
|
|
33638
|
+
if (otherAgents.length > 0) {
|
|
33639
|
+
const mentionRatio = mentionedAgents / otherAgents.length;
|
|
33640
|
+
if (mentionRatio < 0.3) {
|
|
33641
|
+
score -= 15;
|
|
33642
|
+
flags.push(`Identity mentions ${mentionedAgents}/${otherAgents.length} team members`);
|
|
33643
|
+
}
|
|
33644
|
+
}
|
|
33645
|
+
const hasReportingChain = identityLower.includes("report") || identityLower.includes("manager") || identityLower.includes("coo") || identityLower.includes("coordinator");
|
|
33646
|
+
if (!hasReportingChain) {
|
|
33647
|
+
score -= 10;
|
|
33648
|
+
flags.push("Identity does not reference reporting chain");
|
|
33649
|
+
}
|
|
33650
|
+
const orgTerms = ["exe-os", "exe-wiki", "exe-crm", "askexe"];
|
|
33651
|
+
let orgMentions = 0;
|
|
33652
|
+
for (const term of orgTerms) {
|
|
33653
|
+
if (identityLower.includes(term)) orgMentions++;
|
|
33654
|
+
}
|
|
33655
|
+
if (orgMentions === 0) {
|
|
33656
|
+
score -= 5;
|
|
33657
|
+
flags.push("Identity does not reference any org products");
|
|
33658
|
+
}
|
|
33659
|
+
score = Math.max(0, Math.min(100, score));
|
|
33660
|
+
const detail = flags.length > 0 ? flags.join("; ") : "Identity reflects org structure";
|
|
33661
|
+
return { axis: "world-model", score, detail };
|
|
33662
|
+
}
|
|
33663
|
+
function extractKeyTerms(text3) {
|
|
33664
|
+
const stopwords = /* @__PURE__ */ new Set([
|
|
33665
|
+
"the",
|
|
33666
|
+
"and",
|
|
33667
|
+
"for",
|
|
33668
|
+
"are",
|
|
33669
|
+
"but",
|
|
33670
|
+
"not",
|
|
33671
|
+
"you",
|
|
33672
|
+
"all",
|
|
33673
|
+
"any",
|
|
33674
|
+
"can",
|
|
33675
|
+
"had",
|
|
33676
|
+
"her",
|
|
33677
|
+
"was",
|
|
33678
|
+
"one",
|
|
33679
|
+
"our",
|
|
33680
|
+
"out",
|
|
33681
|
+
"has",
|
|
33682
|
+
"his",
|
|
33683
|
+
"how",
|
|
33684
|
+
"its",
|
|
33685
|
+
"may",
|
|
33686
|
+
"new",
|
|
33687
|
+
"now",
|
|
33688
|
+
"old",
|
|
33689
|
+
"see",
|
|
33690
|
+
"way",
|
|
33691
|
+
"who",
|
|
33692
|
+
"did",
|
|
33693
|
+
"get",
|
|
33694
|
+
"got",
|
|
33695
|
+
"let",
|
|
33696
|
+
"say",
|
|
33697
|
+
"she",
|
|
33698
|
+
"too",
|
|
33699
|
+
"use",
|
|
33700
|
+
"with",
|
|
33701
|
+
"this",
|
|
33702
|
+
"that",
|
|
33703
|
+
"from",
|
|
33704
|
+
"they",
|
|
33705
|
+
"been",
|
|
33706
|
+
"have",
|
|
33707
|
+
"will",
|
|
33708
|
+
"your",
|
|
33709
|
+
"what",
|
|
33710
|
+
"when",
|
|
33711
|
+
"make",
|
|
33712
|
+
"like",
|
|
33713
|
+
"just",
|
|
33714
|
+
"over",
|
|
33715
|
+
"such",
|
|
33716
|
+
"take",
|
|
33717
|
+
"than",
|
|
33718
|
+
"them",
|
|
33719
|
+
"very",
|
|
33720
|
+
"some",
|
|
33721
|
+
"could",
|
|
33722
|
+
"into",
|
|
33723
|
+
"then",
|
|
33724
|
+
"more",
|
|
33725
|
+
"also",
|
|
33726
|
+
"after",
|
|
33727
|
+
"should",
|
|
33728
|
+
"would",
|
|
33729
|
+
"about",
|
|
33730
|
+
"their",
|
|
33731
|
+
"which",
|
|
33732
|
+
"these",
|
|
33733
|
+
"other",
|
|
33734
|
+
"every",
|
|
33735
|
+
"does",
|
|
33736
|
+
"being",
|
|
33737
|
+
"those",
|
|
33738
|
+
"never",
|
|
33739
|
+
"before",
|
|
33740
|
+
"through"
|
|
33741
|
+
]);
|
|
33742
|
+
const words = text3.replace(/[^\w\s-]/g, " ").split(/\s+/).filter((w) => w.length > 3 && !stopwords.has(w.toLowerCase()));
|
|
33743
|
+
return [...new Set(words.map((w) => w.toLowerCase()))].slice(0, 50);
|
|
33744
|
+
}
|
|
33745
|
+
function extractRoleKeywords(role) {
|
|
33746
|
+
const roleKeywordMap = {
|
|
33747
|
+
"coo": ["coordinate", "review", "status", "team", "task", "priority", "dispatch"],
|
|
33748
|
+
"cto": ["architecture", "code", "technical", "system", "design", "review", "security"],
|
|
33749
|
+
"cmo": ["marketing", "brand", "content", "design", "seo", "social", "campaign"],
|
|
33750
|
+
"principal engineer": ["code", "implement", "test", "fix", "feature", "refactor", "build"],
|
|
33751
|
+
"staff code reviewer": ["review", "code", "quality", "issue", "fix", "pattern"],
|
|
33752
|
+
"content production specialist": ["video", "image", "render", "content", "produce", "media"],
|
|
33753
|
+
"ai product lead": ["competitive", "analysis", "feature", "product", "research", "repo"]
|
|
33754
|
+
};
|
|
33755
|
+
const normalized = role.toLowerCase();
|
|
33756
|
+
return roleKeywordMap[normalized] ?? normalized.split(/\s+/).filter((w) => w.length > 2);
|
|
33757
|
+
}
|
|
33758
|
+
async function runDriftProbes(options = {}) {
|
|
33759
|
+
const employees = loadEmployeesSync();
|
|
33760
|
+
const targetAgents = options.agentId ? employees.filter((e) => e.name === options.agentId) : employees;
|
|
33761
|
+
if (targetAgents.length === 0) {
|
|
33762
|
+
return [];
|
|
33763
|
+
}
|
|
33764
|
+
const axes = options.axes ?? ["continuity", "consistency", "role-fidelity", "world-model"];
|
|
33765
|
+
const results = [];
|
|
33766
|
+
for (const agent of targetAgents) {
|
|
33767
|
+
const identity = getIdentity(agent.name);
|
|
33768
|
+
const { count: memCount, texts: memTexts } = await getRecentMemories(agent.name, 50);
|
|
33769
|
+
const decisionCount = await getDecisionCount(agent.name);
|
|
33770
|
+
const ctx = {
|
|
33771
|
+
agent,
|
|
33772
|
+
identityBody: identity?.body ?? null,
|
|
33773
|
+
identityRole: identity?.frontmatter.role ?? null,
|
|
33774
|
+
recentMemoryCount: memCount,
|
|
33775
|
+
recentMemoryTexts: memTexts,
|
|
33776
|
+
storedDecisionCount: decisionCount,
|
|
33777
|
+
allEmployees: employees
|
|
33778
|
+
};
|
|
33779
|
+
const probes = [];
|
|
33780
|
+
const probeFns = {
|
|
33781
|
+
continuity: probeContinuity,
|
|
33782
|
+
consistency: probeConsistency,
|
|
33783
|
+
"role-fidelity": probeRoleFidelity,
|
|
33784
|
+
"world-model": probeWorldModel
|
|
33785
|
+
};
|
|
33786
|
+
for (const axis of axes) {
|
|
33787
|
+
probes.push(probeFns[axis](ctx));
|
|
33788
|
+
}
|
|
33789
|
+
const scores = {
|
|
33790
|
+
continuity: 0,
|
|
33791
|
+
consistency: 0,
|
|
33792
|
+
"role-fidelity": 0,
|
|
33793
|
+
"world-model": 0
|
|
33794
|
+
};
|
|
33795
|
+
for (const probe of probes) {
|
|
33796
|
+
scores[probe.axis] = probe.score;
|
|
33797
|
+
}
|
|
33798
|
+
const weights = {
|
|
33799
|
+
continuity: 0.2,
|
|
33800
|
+
consistency: 0.2,
|
|
33801
|
+
"role-fidelity": 0.35,
|
|
33802
|
+
"world-model": 0.25
|
|
33803
|
+
};
|
|
33804
|
+
let weightedSum = 0;
|
|
33805
|
+
let weightTotal = 0;
|
|
33806
|
+
for (const axis of axes) {
|
|
33807
|
+
weightedSum += scores[axis] * weights[axis];
|
|
33808
|
+
weightTotal += weights[axis];
|
|
33809
|
+
}
|
|
33810
|
+
const overall = Math.round(weightTotal > 0 ? weightedSum / weightTotal : 0);
|
|
33811
|
+
const flags = [];
|
|
33812
|
+
for (const probe of probes) {
|
|
33813
|
+
if (probe.score < DRIFT_THRESHOLD) {
|
|
33814
|
+
flags.push(`${probe.axis} at ${probe.score}% \u2014 ${probe.detail}`);
|
|
33815
|
+
}
|
|
33816
|
+
}
|
|
33817
|
+
results.push({
|
|
33818
|
+
agent: agent.name,
|
|
33819
|
+
scores,
|
|
33820
|
+
overall,
|
|
33821
|
+
drifting: flags.length > 0,
|
|
33822
|
+
flags
|
|
33823
|
+
});
|
|
33824
|
+
}
|
|
33825
|
+
return results;
|
|
33826
|
+
}
|
|
33827
|
+
var DRIFT_THRESHOLD;
|
|
33828
|
+
var init_drift_probes = __esm({
|
|
33829
|
+
"src/lib/drift-probes.ts"() {
|
|
33830
|
+
"use strict";
|
|
33831
|
+
init_identity();
|
|
33832
|
+
init_employees();
|
|
33833
|
+
DRIFT_THRESHOLD = 80;
|
|
33834
|
+
}
|
|
33835
|
+
});
|
|
33836
|
+
|
|
33063
33837
|
// src/mcp/tools/diagnostics.ts
|
|
33064
33838
|
import { z as z98 } from "zod";
|
|
33065
33839
|
function buildHandlers9() {
|
|
@@ -33075,23 +33849,31 @@ function buildHandlers9() {
|
|
|
33075
33849
|
function registerDiagnostics(server) {
|
|
33076
33850
|
const handlers = buildHandlers9();
|
|
33077
33851
|
const toolNames = Array.from(handlers.keys());
|
|
33078
|
-
|
|
33852
|
+
toolNames.push("tool_search", "drift");
|
|
33079
33853
|
server.registerTool(
|
|
33080
33854
|
"diagnostics",
|
|
33081
33855
|
{
|
|
33082
33856
|
title: "Diagnostics",
|
|
33083
|
-
description: `System diagnostics and admin operations. Actions: ${toolNames.join(", ")}. Covers health checks, update status, cloud status, key management, and
|
|
33857
|
+
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
33858
|
inputSchema: {
|
|
33085
33859
|
action: z98.string().describe(`Diagnostic operation: ${toolNames.join(", ")}`),
|
|
33086
33860
|
// Pass-through params used by various sub-tools
|
|
33861
|
+
agent_id: z98.string().optional().describe("Agent to probe (drift). Defaults to all agents."),
|
|
33087
33862
|
name: z98.string().optional().describe("Employee name (rename_employee)"),
|
|
33088
33863
|
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")
|
|
33864
|
+
query: z98.string().optional().describe("Search/filter query, or natural language for tool_search"),
|
|
33865
|
+
format: z98.string().optional().describe("Output format"),
|
|
33866
|
+
limit: z98.coerce.number().int().min(1).max(100).optional().describe("Max results for tool_search (default 20)")
|
|
33091
33867
|
}
|
|
33092
33868
|
},
|
|
33093
33869
|
async (input, extra) => {
|
|
33094
33870
|
const action = input.action;
|
|
33871
|
+
if (action === "tool_search") {
|
|
33872
|
+
return handleToolSearch(input);
|
|
33873
|
+
}
|
|
33874
|
+
if (action === "drift") {
|
|
33875
|
+
return handleDrift(input);
|
|
33876
|
+
}
|
|
33095
33877
|
const handler = handlers.get(action);
|
|
33096
33878
|
if (!handler) {
|
|
33097
33879
|
return {
|
|
@@ -33104,14 +33886,89 @@ function registerDiagnostics(server) {
|
|
|
33104
33886
|
}
|
|
33105
33887
|
);
|
|
33106
33888
|
}
|
|
33889
|
+
async function handleToolSearch(input) {
|
|
33890
|
+
const query = input.query ?? "";
|
|
33891
|
+
const limit = input.limit ?? 20;
|
|
33892
|
+
if (!query) {
|
|
33893
|
+
return {
|
|
33894
|
+
content: [{ type: "text", text: JSON.stringify({ error: "query is required for tool_search" }) }],
|
|
33895
|
+
isError: true
|
|
33896
|
+
};
|
|
33897
|
+
}
|
|
33898
|
+
const index = getToolCapabilityIndex();
|
|
33899
|
+
if (!index.isReady()) {
|
|
33900
|
+
return {
|
|
33901
|
+
content: [{
|
|
33902
|
+
type: "text",
|
|
33903
|
+
text: JSON.stringify({
|
|
33904
|
+
error: "Tool capability index not initialized yet. It is built asynchronously at daemon boot.",
|
|
33905
|
+
query
|
|
33906
|
+
})
|
|
33907
|
+
}],
|
|
33908
|
+
isError: true
|
|
33909
|
+
};
|
|
33910
|
+
}
|
|
33911
|
+
const results = await index.search(query, limit);
|
|
33912
|
+
const tools = results.map((r) => ({
|
|
33913
|
+
name: r.name,
|
|
33914
|
+
description: r.description,
|
|
33915
|
+
category: r.category,
|
|
33916
|
+
relevance: Math.round(r.relevance * 1e3) / 1e3
|
|
33917
|
+
}));
|
|
33918
|
+
return {
|
|
33919
|
+
content: [{
|
|
33920
|
+
type: "text",
|
|
33921
|
+
text: JSON.stringify({
|
|
33922
|
+
tools,
|
|
33923
|
+
total_tools: index.toolCount,
|
|
33924
|
+
query
|
|
33925
|
+
}, null, 2)
|
|
33926
|
+
}]
|
|
33927
|
+
};
|
|
33928
|
+
}
|
|
33929
|
+
async function handleDrift(input) {
|
|
33930
|
+
const agentId = input.agent_id;
|
|
33931
|
+
const axesRaw = input.query;
|
|
33932
|
+
let axes;
|
|
33933
|
+
if (axesRaw) {
|
|
33934
|
+
const valid = ["continuity", "consistency", "role-fidelity", "world-model"];
|
|
33935
|
+
const parsed = axesRaw.split(",").map((a) => a.trim()).filter((a) => valid.includes(a));
|
|
33936
|
+
if (parsed.length > 0) axes = parsed;
|
|
33937
|
+
}
|
|
33938
|
+
const results = await runDriftProbes({ agentId, axes });
|
|
33939
|
+
if (results.length === 0) {
|
|
33940
|
+
return {
|
|
33941
|
+
content: [{
|
|
33942
|
+
type: "text",
|
|
33943
|
+
text: JSON.stringify({ error: agentId ? `Agent "${agentId}" not found` : "No agents found" })
|
|
33944
|
+
}],
|
|
33945
|
+
isError: true
|
|
33946
|
+
};
|
|
33947
|
+
}
|
|
33948
|
+
return {
|
|
33949
|
+
content: [{
|
|
33950
|
+
type: "text",
|
|
33951
|
+
text: JSON.stringify(results.length === 1 ? results[0] : results, null, 2)
|
|
33952
|
+
}]
|
|
33953
|
+
};
|
|
33954
|
+
}
|
|
33107
33955
|
var init_diagnostics = __esm({
|
|
33108
33956
|
"src/mcp/tools/diagnostics.ts"() {
|
|
33109
33957
|
"use strict";
|
|
33110
33958
|
init_cli_parity();
|
|
33959
|
+
init_tool_capability_index();
|
|
33960
|
+
init_drift_probes();
|
|
33111
33961
|
}
|
|
33112
33962
|
});
|
|
33113
33963
|
|
|
33114
33964
|
// src/mcp/tool-gates.ts
|
|
33965
|
+
var tool_gates_exports = {};
|
|
33966
|
+
__export(tool_gates_exports, {
|
|
33967
|
+
TOOL_CATEGORIES: () => TOOL_CATEGORIES,
|
|
33968
|
+
TOOL_GATES: () => TOOL_GATES,
|
|
33969
|
+
isToolAllowed: () => isToolAllowed,
|
|
33970
|
+
isToolAllowedForPlan: () => isToolAllowedForPlan
|
|
33971
|
+
});
|
|
33115
33972
|
function isToolAllowedForPlan(registerFnName, plan) {
|
|
33116
33973
|
const category = TOOL_CATEGORIES[registerFnName];
|
|
33117
33974
|
if (!category) return true;
|
|
@@ -35478,6 +36335,20 @@ async function startMcpHttpServer() {
|
|
|
35478
36335
|
`
|
|
35479
36336
|
);
|
|
35480
36337
|
}
|
|
36338
|
+
Promise.all([
|
|
36339
|
+
Promise.resolve().then(() => (init_tool_capability_index(), tool_capability_index_exports)),
|
|
36340
|
+
Promise.resolve().then(() => (init_tool_gates(), tool_gates_exports))
|
|
36341
|
+
]).then(async ([{ getToolCapabilityIndex: getToolCapabilityIndex2 }, { TOOL_CATEGORIES: TOOL_CATEGORIES2 }]) => {
|
|
36342
|
+
const gateState = getCachedLicenseGate2();
|
|
36343
|
+
const index = getToolCapabilityIndex2();
|
|
36344
|
+
await index.buildIndex(
|
|
36345
|
+
(fakeServer) => registerAllTools2(fakeServer, gateState.license, gateState.hasKey),
|
|
36346
|
+
TOOL_CATEGORIES2
|
|
36347
|
+
);
|
|
36348
|
+
}).catch((err) => {
|
|
36349
|
+
process.stderr.write(`[exed] Tool capability index failed: ${err.message}
|
|
36350
|
+
`);
|
|
36351
|
+
});
|
|
35481
36352
|
const transports = /* @__PURE__ */ new Map();
|
|
35482
36353
|
const MCP_HTTP_PORT = parseInt(process.env.EXE_MCP_PORT || "48739", 10);
|
|
35483
36354
|
const MCP_SESSION_TTL_MS = parseDurationMs2(process.env.EXE_MCP_SESSION_TTL_MS, 30 * 60 * 1e3, { allowZero: true });
|