@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
|
@@ -3353,6 +3353,20 @@ async function ensureSchema() {
|
|
|
3353
3353
|
});
|
|
3354
3354
|
} catch {
|
|
3355
3355
|
}
|
|
3356
|
+
try {
|
|
3357
|
+
await client.execute({
|
|
3358
|
+
sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
|
|
3359
|
+
args: []
|
|
3360
|
+
});
|
|
3361
|
+
} catch {
|
|
3362
|
+
}
|
|
3363
|
+
try {
|
|
3364
|
+
await client.execute({
|
|
3365
|
+
sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
|
|
3366
|
+
args: []
|
|
3367
|
+
});
|
|
3368
|
+
} catch {
|
|
3369
|
+
}
|
|
3356
3370
|
await client.executeMultiple(`
|
|
3357
3371
|
CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
|
|
3358
3372
|
content_text,
|
|
@@ -3604,6 +3618,22 @@ async function ensureSchema() {
|
|
|
3604
3618
|
);
|
|
3605
3619
|
} catch {
|
|
3606
3620
|
}
|
|
3621
|
+
for (const col of [
|
|
3622
|
+
"ALTER TABLE memories ADD COLUMN valid_from TEXT",
|
|
3623
|
+
"ALTER TABLE memories ADD COLUMN invalid_at TEXT"
|
|
3624
|
+
]) {
|
|
3625
|
+
try {
|
|
3626
|
+
await client.execute(col);
|
|
3627
|
+
} catch {
|
|
3628
|
+
}
|
|
3629
|
+
}
|
|
3630
|
+
try {
|
|
3631
|
+
await client.execute({
|
|
3632
|
+
sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
|
|
3633
|
+
args: []
|
|
3634
|
+
});
|
|
3635
|
+
} catch {
|
|
3636
|
+
}
|
|
3607
3637
|
try {
|
|
3608
3638
|
await client.execute({
|
|
3609
3639
|
sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
|
|
@@ -3646,6 +3676,13 @@ async function ensureSchema() {
|
|
|
3646
3676
|
} catch {
|
|
3647
3677
|
}
|
|
3648
3678
|
}
|
|
3679
|
+
try {
|
|
3680
|
+
await client.execute({
|
|
3681
|
+
sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
|
|
3682
|
+
args: []
|
|
3683
|
+
});
|
|
3684
|
+
} catch {
|
|
3685
|
+
}
|
|
3649
3686
|
try {
|
|
3650
3687
|
await client.execute({
|
|
3651
3688
|
sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
|
|
@@ -3706,7 +3743,7 @@ import { pathToFileURL as pathToFileURL2 } from "url";
|
|
|
3706
3743
|
import os7 from "os";
|
|
3707
3744
|
import path10 from "path";
|
|
3708
3745
|
import { jwtVerify, importSPKI } from "jose";
|
|
3709
|
-
var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH, PLAN_LIMITS;
|
|
3746
|
+
var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH, API_BASE, PLAN_LIMITS;
|
|
3710
3747
|
var init_license = __esm({
|
|
3711
3748
|
"src/lib/license.ts"() {
|
|
3712
3749
|
"use strict";
|
|
@@ -3714,6 +3751,7 @@ var init_license = __esm({
|
|
|
3714
3751
|
LICENSE_PATH = path10.join(EXE_AI_DIR, "license.key");
|
|
3715
3752
|
CACHE_PATH = path10.join(EXE_AI_DIR, "license-cache.json");
|
|
3716
3753
|
DEVICE_ID_PATH = path10.join(EXE_AI_DIR, "device-id");
|
|
3754
|
+
API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://askexe.com/cloud";
|
|
3717
3755
|
PLAN_LIMITS = {
|
|
3718
3756
|
free: { devices: 1, employees: 1, memories: 5e3 },
|
|
3719
3757
|
pro: { devices: 3, employees: 5, memories: 1e5 },
|
|
@@ -4331,8 +4369,8 @@ ${scopeMismatchWarning}` : scopeMismatchWarning;
|
|
|
4331
4369
|
const complexity = input2.complexity ?? "standard";
|
|
4332
4370
|
const sessionScope = earlySessionScope;
|
|
4333
4371
|
await client.execute({
|
|
4334
|
-
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)
|
|
4335
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
4372
|
+
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)
|
|
4373
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
4336
4374
|
args: [
|
|
4337
4375
|
id,
|
|
4338
4376
|
input2.title,
|
|
@@ -4352,6 +4390,8 @@ ${scopeMismatchWarning}` : scopeMismatchWarning;
|
|
|
4352
4390
|
0,
|
|
4353
4391
|
null,
|
|
4354
4392
|
sessionScope,
|
|
4393
|
+
input2.spawnRuntime ?? null,
|
|
4394
|
+
input2.spawnModel ?? null,
|
|
4355
4395
|
now,
|
|
4356
4396
|
now
|
|
4357
4397
|
]
|
|
@@ -4408,7 +4448,9 @@ ${input2.context}
|
|
|
4408
4448
|
budgetTokens: input2.budgetTokens ?? null,
|
|
4409
4449
|
budgetFallbackModel: input2.budgetFallbackModel ?? null,
|
|
4410
4450
|
tokensUsed: 0,
|
|
4411
|
-
tokensWarnedAt: null
|
|
4451
|
+
tokensWarnedAt: null,
|
|
4452
|
+
spawnRuntime: input2.spawnRuntime ?? null,
|
|
4453
|
+
spawnModel: input2.spawnModel ?? null
|
|
4412
4454
|
};
|
|
4413
4455
|
}
|
|
4414
4456
|
async function listTasks(input2) {
|
|
@@ -4458,7 +4500,9 @@ async function listTasks(input2) {
|
|
|
4458
4500
|
budgetTokens: r.budget_tokens !== null ? Number(r.budget_tokens) : null,
|
|
4459
4501
|
budgetFallbackModel: r.budget_fallback_model !== null ? String(r.budget_fallback_model) : null,
|
|
4460
4502
|
tokensUsed: Number(r.tokens_used ?? 0),
|
|
4461
|
-
tokensWarnedAt: r.tokens_warned_at !== null ? Number(r.tokens_warned_at) : null
|
|
4503
|
+
tokensWarnedAt: r.tokens_warned_at !== null ? Number(r.tokens_warned_at) : null,
|
|
4504
|
+
spawnRuntime: r.spawn_runtime !== null && r.spawn_runtime !== void 0 ? String(r.spawn_runtime) : null,
|
|
4505
|
+
spawnModel: r.spawn_model !== null && r.spawn_model !== void 0 ? String(r.spawn_model) : null
|
|
4462
4506
|
}));
|
|
4463
4507
|
}
|
|
4464
4508
|
function isTmuxSessionAlive(identifier) {
|
|
@@ -5755,6 +5799,8 @@ async function updateTask(input2) {
|
|
|
5755
5799
|
budgetFallbackModel: row.budget_fallback_model !== void 0 && row.budget_fallback_model !== null ? String(row.budget_fallback_model) : null,
|
|
5756
5800
|
tokensUsed: Number(row.tokens_used ?? 0),
|
|
5757
5801
|
tokensWarnedAt: row.tokens_warned_at !== void 0 && row.tokens_warned_at !== null ? Number(row.tokens_warned_at) : null,
|
|
5802
|
+
spawnRuntime: row.spawn_runtime !== void 0 && row.spawn_runtime !== null ? String(row.spawn_runtime) : null,
|
|
5803
|
+
spawnModel: row.spawn_model !== void 0 && row.spawn_model !== null ? String(row.spawn_model) : null,
|
|
5758
5804
|
nextTask
|
|
5759
5805
|
};
|
|
5760
5806
|
}
|
|
@@ -6250,6 +6296,7 @@ function resolveExeSession() {
|
|
|
6250
6296
|
const mySession = getMySession();
|
|
6251
6297
|
if (!mySession) return null;
|
|
6252
6298
|
const fromSessionName = extractRootExe(mySession);
|
|
6299
|
+
let candidate = null;
|
|
6253
6300
|
try {
|
|
6254
6301
|
const key = getSessionKey();
|
|
6255
6302
|
const parentExe = getParentExe(key);
|
|
@@ -6260,13 +6307,47 @@ function resolveExeSession() {
|
|
|
6260
6307
|
`[tmux-routing] WARN: cache says "${fromCache}" but session name says "${fromSessionName}". Trusting session name.
|
|
6261
6308
|
`
|
|
6262
6309
|
);
|
|
6263
|
-
|
|
6310
|
+
candidate = fromSessionName;
|
|
6311
|
+
} else {
|
|
6312
|
+
candidate = fromCache;
|
|
6264
6313
|
}
|
|
6265
|
-
return fromCache;
|
|
6266
6314
|
}
|
|
6267
6315
|
} catch {
|
|
6268
6316
|
}
|
|
6269
|
-
|
|
6317
|
+
if (!candidate) {
|
|
6318
|
+
candidate = fromSessionName ?? mySession;
|
|
6319
|
+
}
|
|
6320
|
+
if (candidate && isRootSession(candidate)) {
|
|
6321
|
+
try {
|
|
6322
|
+
const transport = getTransport();
|
|
6323
|
+
const liveSessions = transport.listSessions();
|
|
6324
|
+
if (!liveSessions.includes(candidate)) {
|
|
6325
|
+
const liveRoots = liveSessions.filter((s) => isRootSession(s));
|
|
6326
|
+
if (liveRoots.length === 1) {
|
|
6327
|
+
process.stderr.write(
|
|
6328
|
+
`[tmux-routing] WARN: resolved session "${candidate}" is dead. Using live coordinator "${liveRoots[0]}".
|
|
6329
|
+
`
|
|
6330
|
+
);
|
|
6331
|
+
return liveRoots[0];
|
|
6332
|
+
} else if (liveRoots.length > 1) {
|
|
6333
|
+
const base = candidate.replace(/\d+$/, "");
|
|
6334
|
+
const match = liveRoots.find((s) => s.startsWith(base));
|
|
6335
|
+
const chosen = match ?? liveRoots[0];
|
|
6336
|
+
process.stderr.write(
|
|
6337
|
+
`[tmux-routing] WARN: resolved session "${candidate}" is dead. ${liveRoots.length} live roots found, using "${chosen}".
|
|
6338
|
+
`
|
|
6339
|
+
);
|
|
6340
|
+
return chosen;
|
|
6341
|
+
}
|
|
6342
|
+
process.stderr.write(
|
|
6343
|
+
`[tmux-routing] WARN: resolved session "${candidate}" is dead and no live coordinator found.
|
|
6344
|
+
`
|
|
6345
|
+
);
|
|
6346
|
+
}
|
|
6347
|
+
} catch {
|
|
6348
|
+
}
|
|
6349
|
+
}
|
|
6350
|
+
return candidate;
|
|
6270
6351
|
}
|
|
6271
6352
|
function isEmployeeAlive(sessionName) {
|
|
6272
6353
|
return getTransport().isAlive(sessionName);
|
|
@@ -6668,7 +6749,12 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
6668
6749
|
}
|
|
6669
6750
|
const spawnCwd = opts?.cwd ?? projectDir;
|
|
6670
6751
|
const useExeAgent = !!(opts?.model && opts?.provider);
|
|
6671
|
-
const
|
|
6752
|
+
const baseRtConfig = getAgentRuntime(employeeName);
|
|
6753
|
+
const agentRtConfig = {
|
|
6754
|
+
...baseRtConfig,
|
|
6755
|
+
...opts?.runtimeOverride ? { runtime: opts.runtimeOverride } : {},
|
|
6756
|
+
...opts?.modelOverride ? { model: opts.modelOverride } : {}
|
|
6757
|
+
};
|
|
6672
6758
|
const useCodex = !useExeAgent && agentRtConfig.runtime === "codex";
|
|
6673
6759
|
const useOpencode = !useExeAgent && !useCodex && agentRtConfig.runtime === "opencode";
|
|
6674
6760
|
const ccProvider = useExeAgent || useCodex || useOpencode ? DEFAULT_PROVIDER : detectActiveProvider();
|
|
@@ -7961,6 +8047,20 @@ var init_platform_procedures = __esm({
|
|
|
7961
8047
|
priority: "p1",
|
|
7962
8048
|
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."
|
|
7963
8049
|
},
|
|
8050
|
+
// --- Tool guidance ---
|
|
8051
|
+
{
|
|
8052
|
+
title: "How to use company_actions \u2014 execute business actions through gateway connectors",
|
|
8053
|
+
domain: "tools",
|
|
8054
|
+
priority: "p2",
|
|
8055
|
+
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."
|
|
8056
|
+
},
|
|
8057
|
+
// --- Release awareness ---
|
|
8058
|
+
{
|
|
8059
|
+
title: "What's New check \u2014 surface new features after update",
|
|
8060
|
+
domain: "support",
|
|
8061
|
+
priority: "p1",
|
|
8062
|
+
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."
|
|
8063
|
+
},
|
|
7964
8064
|
// --- Platform vs Customer ownership ---
|
|
7965
8065
|
{
|
|
7966
8066
|
title: "What the platform provides vs what you customize",
|
|
@@ -8049,13 +8149,13 @@ var init_platform_procedures = __esm({
|
|
|
8049
8149
|
title: "MCP tools \u2014 memory, decision, and search",
|
|
8050
8150
|
domain: "tool-use",
|
|
8051
8151
|
priority: "p1",
|
|
8052
|
-
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.`
|
|
8152
|
+
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.`
|
|
8053
8153
|
},
|
|
8054
8154
|
{
|
|
8055
8155
|
title: "MCP tools \u2014 task orchestration",
|
|
8056
8156
|
domain: "tool-use",
|
|
8057
8157
|
priority: "p1",
|
|
8058
|
-
content:
|
|
8158
|
+
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.`
|
|
8059
8159
|
},
|
|
8060
8160
|
{
|
|
8061
8161
|
title: "MCP tools \u2014 knowledge graph (GraphRAG)",
|
|
@@ -8085,7 +8185,7 @@ var init_platform_procedures = __esm({
|
|
|
8085
8185
|
title: "MCP tools \u2014 admin, config, and operations",
|
|
8086
8186
|
domain: "tool-use",
|
|
8087
8187
|
priority: "p1",
|
|
8088
|
-
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.'
|
|
8188
|
+
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.'
|
|
8089
8189
|
}
|
|
8090
8190
|
];
|
|
8091
8191
|
PLATFORM_PROCEDURE_TITLES = new Set(
|
|
@@ -8769,6 +8869,8 @@ async function writeMemory(record) {
|
|
|
8769
8869
|
source_type: record.source_type ?? null,
|
|
8770
8870
|
tier: record.tier ?? classifyTier(record),
|
|
8771
8871
|
supersedes_id: record.supersedes_id ?? null,
|
|
8872
|
+
valid_from: record.valid_from ?? record.timestamp,
|
|
8873
|
+
invalid_at: record.invalid_at ?? null,
|
|
8772
8874
|
draft: record.draft ? 1 : 0,
|
|
8773
8875
|
memory_type: memoryType,
|
|
8774
8876
|
trajectory: record.trajectory ? JSON.stringify(record.trajectory) : null,
|
|
@@ -8787,7 +8889,8 @@ async function writeMemory(record) {
|
|
|
8787
8889
|
token_cost: record.token_cost ?? null,
|
|
8788
8890
|
audience: record.audience ?? null,
|
|
8789
8891
|
language_type: record.language_type ?? inferLanguageType(record),
|
|
8790
|
-
parent_memory_id: record.parent_memory_id ?? null
|
|
8892
|
+
parent_memory_id: record.parent_memory_id ?? null,
|
|
8893
|
+
procedure_for: record.procedure_for ?? null
|
|
8791
8894
|
};
|
|
8792
8895
|
_pendingRecords.push(dbRow);
|
|
8793
8896
|
orgBus.emit({
|
|
@@ -8842,6 +8945,8 @@ async function flushBatch() {
|
|
|
8842
8945
|
const sourceType = row.source_type ?? null;
|
|
8843
8946
|
const tier = row.tier ?? 3;
|
|
8844
8947
|
const supersedesId = row.supersedes_id ?? null;
|
|
8948
|
+
const validFrom = row.valid_from ?? row.timestamp;
|
|
8949
|
+
const invalidAt = row.invalid_at ?? null;
|
|
8845
8950
|
const draft = row.draft ? 1 : 0;
|
|
8846
8951
|
const memoryType = row.memory_type ?? "raw";
|
|
8847
8952
|
const trajectory = row.trajectory ?? null;
|
|
@@ -8861,15 +8966,16 @@ async function flushBatch() {
|
|
|
8861
8966
|
const audience = row.audience ?? null;
|
|
8862
8967
|
const languageType = row.language_type ?? null;
|
|
8863
8968
|
const parentMemoryId = row.parent_memory_id ?? null;
|
|
8969
|
+
const procedureFor = row.procedure_for ?? null;
|
|
8864
8970
|
const cols = `id, agent_id, agent_role, session_id, timestamp,
|
|
8865
8971
|
tool_name, project_name,
|
|
8866
8972
|
has_error, raw_text, vector, version, task_id, importance, status,
|
|
8867
8973
|
confidence, last_accessed,
|
|
8868
8974
|
workspace_id, document_id, user_id, char_offset, page_number,
|
|
8869
|
-
source_path, source_type, tier, supersedes_id, draft, memory_type, trajectory, content_hash,
|
|
8975
|
+
source_path, source_type, tier, supersedes_id, valid_from, invalid_at, draft, memory_type, trajectory, content_hash,
|
|
8870
8976
|
intent, outcome, domain, referenced_entities, retrieval_count,
|
|
8871
8977
|
chain_position, review_status, context_window_pct, file_paths, commit_hash,
|
|
8872
|
-
duration_ms, token_cost, audience, language_type, parent_memory_id`;
|
|
8978
|
+
duration_ms, token_cost, audience, language_type, parent_memory_id, procedure_for`;
|
|
8873
8979
|
const metaArgs = [
|
|
8874
8980
|
intent,
|
|
8875
8981
|
outcome,
|
|
@@ -8885,7 +8991,8 @@ async function flushBatch() {
|
|
|
8885
8991
|
tokenCost,
|
|
8886
8992
|
audience,
|
|
8887
8993
|
languageType,
|
|
8888
|
-
parentMemoryId
|
|
8994
|
+
parentMemoryId,
|
|
8995
|
+
procedureFor
|
|
8889
8996
|
];
|
|
8890
8997
|
const baseArgs = [
|
|
8891
8998
|
row.id,
|
|
@@ -8914,6 +9021,8 @@ async function flushBatch() {
|
|
|
8914
9021
|
sourceType,
|
|
8915
9022
|
tier,
|
|
8916
9023
|
supersedesId,
|
|
9024
|
+
validFrom,
|
|
9025
|
+
invalidAt,
|
|
8917
9026
|
draft,
|
|
8918
9027
|
memoryType,
|
|
8919
9028
|
trajectory,
|
|
@@ -8921,8 +9030,8 @@ async function flushBatch() {
|
|
|
8921
9030
|
];
|
|
8922
9031
|
return {
|
|
8923
9032
|
sql: hasVector ? `INSERT OR IGNORE INTO memories (${cols})
|
|
8924
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
|
|
8925
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
9033
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
|
|
9034
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
8926
9035
|
args: hasVector ? [...baseArgs, vectorToBlob(row.vector), ...sharedArgs, ...metaArgs] : [...baseArgs, ...sharedArgs, ...metaArgs]
|
|
8927
9036
|
};
|
|
8928
9037
|
};
|
|
@@ -9038,6 +9147,12 @@ async function searchMemories(queryVector, agentId, options) {
|
|
|
9038
9147
|
AND vector IS NOT NULL${statusFilter}${draftFilter}
|
|
9039
9148
|
AND COALESCE(confidence, 0.7) >= 0.3`;
|
|
9040
9149
|
const args = [agentId];
|
|
9150
|
+
if (options?.asOf) {
|
|
9151
|
+
sql += ` AND (valid_from IS NULL OR valid_from <= ?) AND (invalid_at IS NULL OR invalid_at > ?)`;
|
|
9152
|
+
args.push(options.asOf, options.asOf);
|
|
9153
|
+
} else {
|
|
9154
|
+
sql += ` AND invalid_at IS NULL`;
|
|
9155
|
+
}
|
|
9041
9156
|
const scope = buildWikiScopeFilter(options, "");
|
|
9042
9157
|
sql += scope.clause;
|
|
9043
9158
|
args.push(...scope.args);
|
|
@@ -3349,6 +3349,20 @@ async function ensureSchema() {
|
|
|
3349
3349
|
});
|
|
3350
3350
|
} catch {
|
|
3351
3351
|
}
|
|
3352
|
+
try {
|
|
3353
|
+
await client.execute({
|
|
3354
|
+
sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
|
|
3355
|
+
args: []
|
|
3356
|
+
});
|
|
3357
|
+
} catch {
|
|
3358
|
+
}
|
|
3359
|
+
try {
|
|
3360
|
+
await client.execute({
|
|
3361
|
+
sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
|
|
3362
|
+
args: []
|
|
3363
|
+
});
|
|
3364
|
+
} catch {
|
|
3365
|
+
}
|
|
3352
3366
|
await client.executeMultiple(`
|
|
3353
3367
|
CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
|
|
3354
3368
|
content_text,
|
|
@@ -3600,6 +3614,22 @@ async function ensureSchema() {
|
|
|
3600
3614
|
);
|
|
3601
3615
|
} catch {
|
|
3602
3616
|
}
|
|
3617
|
+
for (const col of [
|
|
3618
|
+
"ALTER TABLE memories ADD COLUMN valid_from TEXT",
|
|
3619
|
+
"ALTER TABLE memories ADD COLUMN invalid_at TEXT"
|
|
3620
|
+
]) {
|
|
3621
|
+
try {
|
|
3622
|
+
await client.execute(col);
|
|
3623
|
+
} catch {
|
|
3624
|
+
}
|
|
3625
|
+
}
|
|
3626
|
+
try {
|
|
3627
|
+
await client.execute({
|
|
3628
|
+
sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
|
|
3629
|
+
args: []
|
|
3630
|
+
});
|
|
3631
|
+
} catch {
|
|
3632
|
+
}
|
|
3603
3633
|
try {
|
|
3604
3634
|
await client.execute({
|
|
3605
3635
|
sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
|
|
@@ -3642,6 +3672,13 @@ async function ensureSchema() {
|
|
|
3642
3672
|
} catch {
|
|
3643
3673
|
}
|
|
3644
3674
|
}
|
|
3675
|
+
try {
|
|
3676
|
+
await client.execute({
|
|
3677
|
+
sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
|
|
3678
|
+
args: []
|
|
3679
|
+
});
|
|
3680
|
+
} catch {
|
|
3681
|
+
}
|
|
3645
3682
|
try {
|
|
3646
3683
|
await client.execute({
|
|
3647
3684
|
sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
|
|
@@ -3702,7 +3739,7 @@ import { pathToFileURL as pathToFileURL2 } from "url";
|
|
|
3702
3739
|
import os7 from "os";
|
|
3703
3740
|
import path10 from "path";
|
|
3704
3741
|
import { jwtVerify, importSPKI } from "jose";
|
|
3705
|
-
var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH;
|
|
3742
|
+
var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH, API_BASE;
|
|
3706
3743
|
var init_license = __esm({
|
|
3707
3744
|
"src/lib/license.ts"() {
|
|
3708
3745
|
"use strict";
|
|
@@ -3710,6 +3747,7 @@ var init_license = __esm({
|
|
|
3710
3747
|
LICENSE_PATH = path10.join(EXE_AI_DIR, "license.key");
|
|
3711
3748
|
CACHE_PATH = path10.join(EXE_AI_DIR, "license-cache.json");
|
|
3712
3749
|
DEVICE_ID_PATH = path10.join(EXE_AI_DIR, "device-id");
|
|
3750
|
+
API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://askexe.com/cloud";
|
|
3713
3751
|
}
|
|
3714
3752
|
});
|
|
3715
3753
|
|
|
@@ -3753,6 +3791,9 @@ import { fileURLToPath as fileURLToPath2 } from "url";
|
|
|
3753
3791
|
function getMySession() {
|
|
3754
3792
|
return getTransport().getMySession();
|
|
3755
3793
|
}
|
|
3794
|
+
function isRootSession(name) {
|
|
3795
|
+
return name.length > 0 && !name.includes("-");
|
|
3796
|
+
}
|
|
3756
3797
|
function extractRootExe(name) {
|
|
3757
3798
|
if (!name) return null;
|
|
3758
3799
|
if (!name.includes("-")) return name;
|
|
@@ -3771,6 +3812,7 @@ function resolveExeSession() {
|
|
|
3771
3812
|
const mySession = getMySession();
|
|
3772
3813
|
if (!mySession) return null;
|
|
3773
3814
|
const fromSessionName = extractRootExe(mySession);
|
|
3815
|
+
let candidate = null;
|
|
3774
3816
|
try {
|
|
3775
3817
|
const key = getSessionKey();
|
|
3776
3818
|
const parentExe = getParentExe(key);
|
|
@@ -3781,13 +3823,47 @@ function resolveExeSession() {
|
|
|
3781
3823
|
`[tmux-routing] WARN: cache says "${fromCache}" but session name says "${fromSessionName}". Trusting session name.
|
|
3782
3824
|
`
|
|
3783
3825
|
);
|
|
3784
|
-
|
|
3826
|
+
candidate = fromSessionName;
|
|
3827
|
+
} else {
|
|
3828
|
+
candidate = fromCache;
|
|
3785
3829
|
}
|
|
3786
|
-
return fromCache;
|
|
3787
3830
|
}
|
|
3788
3831
|
} catch {
|
|
3789
3832
|
}
|
|
3790
|
-
|
|
3833
|
+
if (!candidate) {
|
|
3834
|
+
candidate = fromSessionName ?? mySession;
|
|
3835
|
+
}
|
|
3836
|
+
if (candidate && isRootSession(candidate)) {
|
|
3837
|
+
try {
|
|
3838
|
+
const transport = getTransport();
|
|
3839
|
+
const liveSessions = transport.listSessions();
|
|
3840
|
+
if (!liveSessions.includes(candidate)) {
|
|
3841
|
+
const liveRoots = liveSessions.filter((s) => isRootSession(s));
|
|
3842
|
+
if (liveRoots.length === 1) {
|
|
3843
|
+
process.stderr.write(
|
|
3844
|
+
`[tmux-routing] WARN: resolved session "${candidate}" is dead. Using live coordinator "${liveRoots[0]}".
|
|
3845
|
+
`
|
|
3846
|
+
);
|
|
3847
|
+
return liveRoots[0];
|
|
3848
|
+
} else if (liveRoots.length > 1) {
|
|
3849
|
+
const base = candidate.replace(/\d+$/, "");
|
|
3850
|
+
const match = liveRoots.find((s) => s.startsWith(base));
|
|
3851
|
+
const chosen = match ?? liveRoots[0];
|
|
3852
|
+
process.stderr.write(
|
|
3853
|
+
`[tmux-routing] WARN: resolved session "${candidate}" is dead. ${liveRoots.length} live roots found, using "${chosen}".
|
|
3854
|
+
`
|
|
3855
|
+
);
|
|
3856
|
+
return chosen;
|
|
3857
|
+
}
|
|
3858
|
+
process.stderr.write(
|
|
3859
|
+
`[tmux-routing] WARN: resolved session "${candidate}" is dead and no live coordinator found.
|
|
3860
|
+
`
|
|
3861
|
+
);
|
|
3862
|
+
}
|
|
3863
|
+
} catch {
|
|
3864
|
+
}
|
|
3865
|
+
}
|
|
3866
|
+
return candidate;
|
|
3791
3867
|
}
|
|
3792
3868
|
var SPAWN_LOCK_DIR, SESSION_CACHE, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS;
|
|
3793
3869
|
var init_tmux_routing = __esm({
|
|
@@ -5107,6 +5183,20 @@ var init_platform_procedures = __esm({
|
|
|
5107
5183
|
priority: "p1",
|
|
5108
5184
|
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."
|
|
5109
5185
|
},
|
|
5186
|
+
// --- Tool guidance ---
|
|
5187
|
+
{
|
|
5188
|
+
title: "How to use company_actions \u2014 execute business actions through gateway connectors",
|
|
5189
|
+
domain: "tools",
|
|
5190
|
+
priority: "p2",
|
|
5191
|
+
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."
|
|
5192
|
+
},
|
|
5193
|
+
// --- Release awareness ---
|
|
5194
|
+
{
|
|
5195
|
+
title: "What's New check \u2014 surface new features after update",
|
|
5196
|
+
domain: "support",
|
|
5197
|
+
priority: "p1",
|
|
5198
|
+
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."
|
|
5199
|
+
},
|
|
5110
5200
|
// --- Platform vs Customer ownership ---
|
|
5111
5201
|
{
|
|
5112
5202
|
title: "What the platform provides vs what you customize",
|
|
@@ -5195,13 +5285,13 @@ var init_platform_procedures = __esm({
|
|
|
5195
5285
|
title: "MCP tools \u2014 memory, decision, and search",
|
|
5196
5286
|
domain: "tool-use",
|
|
5197
5287
|
priority: "p1",
|
|
5198
|
-
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.`
|
|
5288
|
+
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.`
|
|
5199
5289
|
},
|
|
5200
5290
|
{
|
|
5201
5291
|
title: "MCP tools \u2014 task orchestration",
|
|
5202
5292
|
domain: "tool-use",
|
|
5203
5293
|
priority: "p1",
|
|
5204
|
-
content:
|
|
5294
|
+
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.`
|
|
5205
5295
|
},
|
|
5206
5296
|
{
|
|
5207
5297
|
title: "MCP tools \u2014 knowledge graph (GraphRAG)",
|
|
@@ -5231,7 +5321,7 @@ var init_platform_procedures = __esm({
|
|
|
5231
5321
|
title: "MCP tools \u2014 admin, config, and operations",
|
|
5232
5322
|
domain: "tool-use",
|
|
5233
5323
|
priority: "p1",
|
|
5234
|
-
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.'
|
|
5324
|
+
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.'
|
|
5235
5325
|
}
|
|
5236
5326
|
];
|
|
5237
5327
|
PLATFORM_PROCEDURE_TITLES = new Set(
|
|
@@ -5915,6 +6005,8 @@ async function writeMemory(record) {
|
|
|
5915
6005
|
source_type: record.source_type ?? null,
|
|
5916
6006
|
tier: record.tier ?? classifyTier(record),
|
|
5917
6007
|
supersedes_id: record.supersedes_id ?? null,
|
|
6008
|
+
valid_from: record.valid_from ?? record.timestamp,
|
|
6009
|
+
invalid_at: record.invalid_at ?? null,
|
|
5918
6010
|
draft: record.draft ? 1 : 0,
|
|
5919
6011
|
memory_type: memoryType,
|
|
5920
6012
|
trajectory: record.trajectory ? JSON.stringify(record.trajectory) : null,
|
|
@@ -5933,7 +6025,8 @@ async function writeMemory(record) {
|
|
|
5933
6025
|
token_cost: record.token_cost ?? null,
|
|
5934
6026
|
audience: record.audience ?? null,
|
|
5935
6027
|
language_type: record.language_type ?? inferLanguageType(record),
|
|
5936
|
-
parent_memory_id: record.parent_memory_id ?? null
|
|
6028
|
+
parent_memory_id: record.parent_memory_id ?? null,
|
|
6029
|
+
procedure_for: record.procedure_for ?? null
|
|
5937
6030
|
};
|
|
5938
6031
|
_pendingRecords.push(dbRow);
|
|
5939
6032
|
orgBus.emit({
|
|
@@ -5988,6 +6081,8 @@ async function flushBatch() {
|
|
|
5988
6081
|
const sourceType = row.source_type ?? null;
|
|
5989
6082
|
const tier = row.tier ?? 3;
|
|
5990
6083
|
const supersedesId = row.supersedes_id ?? null;
|
|
6084
|
+
const validFrom = row.valid_from ?? row.timestamp;
|
|
6085
|
+
const invalidAt = row.invalid_at ?? null;
|
|
5991
6086
|
const draft = row.draft ? 1 : 0;
|
|
5992
6087
|
const memoryType = row.memory_type ?? "raw";
|
|
5993
6088
|
const trajectory = row.trajectory ?? null;
|
|
@@ -6007,15 +6102,16 @@ async function flushBatch() {
|
|
|
6007
6102
|
const audience = row.audience ?? null;
|
|
6008
6103
|
const languageType = row.language_type ?? null;
|
|
6009
6104
|
const parentMemoryId = row.parent_memory_id ?? null;
|
|
6105
|
+
const procedureFor = row.procedure_for ?? null;
|
|
6010
6106
|
const cols = `id, agent_id, agent_role, session_id, timestamp,
|
|
6011
6107
|
tool_name, project_name,
|
|
6012
6108
|
has_error, raw_text, vector, version, task_id, importance, status,
|
|
6013
6109
|
confidence, last_accessed,
|
|
6014
6110
|
workspace_id, document_id, user_id, char_offset, page_number,
|
|
6015
|
-
source_path, source_type, tier, supersedes_id, draft, memory_type, trajectory, content_hash,
|
|
6111
|
+
source_path, source_type, tier, supersedes_id, valid_from, invalid_at, draft, memory_type, trajectory, content_hash,
|
|
6016
6112
|
intent, outcome, domain, referenced_entities, retrieval_count,
|
|
6017
6113
|
chain_position, review_status, context_window_pct, file_paths, commit_hash,
|
|
6018
|
-
duration_ms, token_cost, audience, language_type, parent_memory_id`;
|
|
6114
|
+
duration_ms, token_cost, audience, language_type, parent_memory_id, procedure_for`;
|
|
6019
6115
|
const metaArgs = [
|
|
6020
6116
|
intent,
|
|
6021
6117
|
outcome,
|
|
@@ -6031,7 +6127,8 @@ async function flushBatch() {
|
|
|
6031
6127
|
tokenCost,
|
|
6032
6128
|
audience,
|
|
6033
6129
|
languageType,
|
|
6034
|
-
parentMemoryId
|
|
6130
|
+
parentMemoryId,
|
|
6131
|
+
procedureFor
|
|
6035
6132
|
];
|
|
6036
6133
|
const baseArgs = [
|
|
6037
6134
|
row.id,
|
|
@@ -6060,6 +6157,8 @@ async function flushBatch() {
|
|
|
6060
6157
|
sourceType,
|
|
6061
6158
|
tier,
|
|
6062
6159
|
supersedesId,
|
|
6160
|
+
validFrom,
|
|
6161
|
+
invalidAt,
|
|
6063
6162
|
draft,
|
|
6064
6163
|
memoryType,
|
|
6065
6164
|
trajectory,
|
|
@@ -6067,8 +6166,8 @@ async function flushBatch() {
|
|
|
6067
6166
|
];
|
|
6068
6167
|
return {
|
|
6069
6168
|
sql: hasVector ? `INSERT OR IGNORE INTO memories (${cols})
|
|
6070
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
|
|
6071
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
6169
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
|
|
6170
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
6072
6171
|
args: hasVector ? [...baseArgs, vectorToBlob(row.vector), ...sharedArgs, ...metaArgs] : [...baseArgs, ...sharedArgs, ...metaArgs]
|
|
6073
6172
|
};
|
|
6074
6173
|
};
|
|
@@ -6184,6 +6283,12 @@ async function searchMemories(queryVector, agentId, options) {
|
|
|
6184
6283
|
AND vector IS NOT NULL${statusFilter}${draftFilter}
|
|
6185
6284
|
AND COALESCE(confidence, 0.7) >= 0.3`;
|
|
6186
6285
|
const args = [agentId];
|
|
6286
|
+
if (options?.asOf) {
|
|
6287
|
+
sql += ` AND (valid_from IS NULL OR valid_from <= ?) AND (invalid_at IS NULL OR invalid_at > ?)`;
|
|
6288
|
+
args.push(options.asOf, options.asOf);
|
|
6289
|
+
} else {
|
|
6290
|
+
sql += ` AND invalid_at IS NULL`;
|
|
6291
|
+
}
|
|
6187
6292
|
const scope = buildWikiScopeFilter(options, "");
|
|
6188
6293
|
sql += scope.clause;
|
|
6189
6294
|
args.push(...scope.args);
|