@askexenow/exe-os 0.9.93 → 0.9.95
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/deploy/compose/docker-compose.yml +1 -0
- package/dist/bin/agentic-ontology-backfill.js +65 -8
- package/dist/bin/agentic-reflection-backfill.js +54 -3
- package/dist/bin/agentic-semantic-label.js +54 -3
- package/dist/bin/backfill-conversations.js +69 -9
- package/dist/bin/backfill-responses.js +69 -9
- package/dist/bin/backfill-vectors.js +54 -3
- package/dist/bin/bulk-sync-postgres.js +66 -8
- package/dist/bin/cleanup-stale-review-tasks.js +121 -13
- package/dist/bin/cli.js +1561 -466
- package/dist/bin/customer-readiness.js +61 -0
- package/dist/bin/exe-agent.js +17 -3
- package/dist/bin/exe-assign.js +75 -9
- package/dist/bin/exe-boot.js +114 -12
- package/dist/bin/exe-call.js +17 -3
- package/dist/bin/exe-cloud.js +76 -10
- package/dist/bin/exe-dispatch.js +136 -18
- package/dist/bin/exe-doctor.js +75 -9
- package/dist/bin/exe-export-behaviors.js +75 -9
- package/dist/bin/exe-forget.js +94 -9
- package/dist/bin/exe-gateway.js +135 -18
- package/dist/bin/exe-heartbeat.js +121 -13
- package/dist/bin/exe-kill.js +75 -9
- package/dist/bin/exe-launch-agent.js +75 -9
- package/dist/bin/exe-new-employee.js +18 -4
- package/dist/bin/exe-pending-messages.js +121 -13
- package/dist/bin/exe-pending-notifications.js +121 -13
- package/dist/bin/exe-pending-reviews.js +121 -13
- package/dist/bin/exe-rename.js +75 -9
- package/dist/bin/exe-review.js +75 -9
- package/dist/bin/exe-search.js +100 -9
- package/dist/bin/exe-session-cleanup.js +136 -18
- package/dist/bin/exe-settings.js +1 -0
- package/dist/bin/exe-start-codex.js +65 -8
- package/dist/bin/exe-start-opencode.js +65 -8
- package/dist/bin/exe-status.js +121 -13
- package/dist/bin/exe-support.js +1 -0
- package/dist/bin/exe-team.js +75 -9
- package/dist/bin/git-sweep.js +136 -18
- package/dist/bin/graph-backfill.js +65 -8
- package/dist/bin/graph-export.js +75 -9
- package/dist/bin/intercom-check.js +136 -18
- package/dist/bin/scan-tasks.js +136 -18
- package/dist/bin/setup.js +55 -4
- package/dist/bin/shard-migrate.js +65 -8
- package/dist/bin/stack-update.js +5 -6
- package/dist/bin/update.js +1 -1
- package/dist/gateway/index.js +136 -18
- package/dist/hooks/bug-report-worker.js +136 -18
- package/dist/hooks/codex-stop-task-finalizer.js +126 -14
- package/dist/hooks/commit-complete.js +136 -18
- package/dist/hooks/error-recall.js +100 -9
- package/dist/hooks/ingest.js +75 -9
- package/dist/hooks/instructions-loaded.js +75 -9
- package/dist/hooks/notification.js +75 -9
- package/dist/hooks/post-compact.js +313 -50
- package/dist/hooks/post-tool-combined.js +436 -13
- package/dist/hooks/pre-compact.js +136 -18
- package/dist/hooks/pre-tool-use.js +121 -13
- package/dist/hooks/prompt-submit.js +194 -19
- package/dist/hooks/session-end.js +136 -18
- package/dist/hooks/session-start.js +146 -13
- package/dist/hooks/stop.js +121 -13
- package/dist/hooks/subagent-stop.js +121 -13
- package/dist/hooks/summary-worker.js +99 -7
- package/dist/index.js +136 -18
- package/dist/lib/cloud-sync.js +38 -0
- package/dist/lib/consolidation.js +3 -1
- package/dist/lib/database.js +37 -0
- package/dist/lib/db.js +37 -0
- package/dist/lib/device-registry.js +37 -0
- package/dist/lib/employee-templates.js +17 -3
- package/dist/lib/exe-daemon.js +916 -42
- package/dist/lib/hybrid-search.js +100 -9
- package/dist/lib/license.js +1 -1
- package/dist/lib/messaging.js +43 -4
- package/dist/lib/schedules.js +54 -3
- package/dist/lib/store.js +75 -9
- package/dist/lib/tasks.js +61 -9
- package/dist/lib/tmux-routing.js +61 -9
- package/dist/mcp/server.js +878 -42
- package/dist/mcp/tools/create-task.js +70 -12
- package/dist/mcp/tools/list-tasks.js +49 -5
- package/dist/mcp/tools/send-message.js +43 -4
- package/dist/mcp/tools/update-task.js +61 -9
- package/dist/runtime/index.js +136 -18
- package/dist/tui/App.js +135 -18
- package/package.json +1 -1
|
@@ -2775,6 +2775,20 @@ async function ensureSchema() {
|
|
|
2775
2775
|
});
|
|
2776
2776
|
} catch {
|
|
2777
2777
|
}
|
|
2778
|
+
try {
|
|
2779
|
+
await client.execute({
|
|
2780
|
+
sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
|
|
2781
|
+
args: []
|
|
2782
|
+
});
|
|
2783
|
+
} catch {
|
|
2784
|
+
}
|
|
2785
|
+
try {
|
|
2786
|
+
await client.execute({
|
|
2787
|
+
sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
|
|
2788
|
+
args: []
|
|
2789
|
+
});
|
|
2790
|
+
} catch {
|
|
2791
|
+
}
|
|
2778
2792
|
await client.executeMultiple(`
|
|
2779
2793
|
CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
|
|
2780
2794
|
content_text,
|
|
@@ -3026,6 +3040,22 @@ async function ensureSchema() {
|
|
|
3026
3040
|
);
|
|
3027
3041
|
} catch {
|
|
3028
3042
|
}
|
|
3043
|
+
for (const col of [
|
|
3044
|
+
"ALTER TABLE memories ADD COLUMN valid_from TEXT",
|
|
3045
|
+
"ALTER TABLE memories ADD COLUMN invalid_at TEXT"
|
|
3046
|
+
]) {
|
|
3047
|
+
try {
|
|
3048
|
+
await client.execute(col);
|
|
3049
|
+
} catch {
|
|
3050
|
+
}
|
|
3051
|
+
}
|
|
3052
|
+
try {
|
|
3053
|
+
await client.execute({
|
|
3054
|
+
sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
|
|
3055
|
+
args: []
|
|
3056
|
+
});
|
|
3057
|
+
} catch {
|
|
3058
|
+
}
|
|
3029
3059
|
try {
|
|
3030
3060
|
await client.execute({
|
|
3031
3061
|
sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
|
|
@@ -3068,6 +3098,13 @@ async function ensureSchema() {
|
|
|
3068
3098
|
} catch {
|
|
3069
3099
|
}
|
|
3070
3100
|
}
|
|
3101
|
+
try {
|
|
3102
|
+
await client.execute({
|
|
3103
|
+
sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
|
|
3104
|
+
args: []
|
|
3105
|
+
});
|
|
3106
|
+
} catch {
|
|
3107
|
+
}
|
|
3071
3108
|
try {
|
|
3072
3109
|
await client.execute({
|
|
3073
3110
|
sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
|
|
@@ -3412,7 +3449,7 @@ import { pathToFileURL as pathToFileURL2 } from "url";
|
|
|
3412
3449
|
import os7 from "os";
|
|
3413
3450
|
import path9 from "path";
|
|
3414
3451
|
import { jwtVerify, importSPKI } from "jose";
|
|
3415
|
-
var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH;
|
|
3452
|
+
var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH, API_BASE;
|
|
3416
3453
|
var init_license = __esm({
|
|
3417
3454
|
"src/lib/license.ts"() {
|
|
3418
3455
|
"use strict";
|
|
@@ -3420,6 +3457,7 @@ var init_license = __esm({
|
|
|
3420
3457
|
LICENSE_PATH = path9.join(EXE_AI_DIR, "license.key");
|
|
3421
3458
|
CACHE_PATH = path9.join(EXE_AI_DIR, "license-cache.json");
|
|
3422
3459
|
DEVICE_ID_PATH = path9.join(EXE_AI_DIR, "device-id");
|
|
3460
|
+
API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://askexe.com/cloud";
|
|
3423
3461
|
}
|
|
3424
3462
|
});
|
|
3425
3463
|
|
|
@@ -3463,6 +3501,9 @@ import { fileURLToPath as fileURLToPath2 } from "url";
|
|
|
3463
3501
|
function getMySession() {
|
|
3464
3502
|
return getTransport().getMySession();
|
|
3465
3503
|
}
|
|
3504
|
+
function isRootSession(name) {
|
|
3505
|
+
return name.length > 0 && !name.includes("-");
|
|
3506
|
+
}
|
|
3466
3507
|
function extractRootExe(name) {
|
|
3467
3508
|
if (!name) return null;
|
|
3468
3509
|
if (!name.includes("-")) return name;
|
|
@@ -3478,9 +3519,13 @@ function getParentExe(sessionKey) {
|
|
|
3478
3519
|
}
|
|
3479
3520
|
}
|
|
3480
3521
|
function resolveExeSession() {
|
|
3522
|
+
if (process.env.EXE_SESSION_NAME) {
|
|
3523
|
+
return extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
|
|
3524
|
+
}
|
|
3481
3525
|
const mySession = getMySession();
|
|
3482
3526
|
if (!mySession) return null;
|
|
3483
3527
|
const fromSessionName = extractRootExe(mySession);
|
|
3528
|
+
let candidate = null;
|
|
3484
3529
|
try {
|
|
3485
3530
|
const key = getSessionKey();
|
|
3486
3531
|
const parentExe = getParentExe(key);
|
|
@@ -3491,13 +3536,47 @@ function resolveExeSession() {
|
|
|
3491
3536
|
`[tmux-routing] WARN: cache says "${fromCache}" but session name says "${fromSessionName}". Trusting session name.
|
|
3492
3537
|
`
|
|
3493
3538
|
);
|
|
3494
|
-
|
|
3539
|
+
candidate = fromSessionName;
|
|
3540
|
+
} else {
|
|
3541
|
+
candidate = fromCache;
|
|
3495
3542
|
}
|
|
3496
|
-
return fromCache;
|
|
3497
3543
|
}
|
|
3498
3544
|
} catch {
|
|
3499
3545
|
}
|
|
3500
|
-
|
|
3546
|
+
if (!candidate) {
|
|
3547
|
+
candidate = fromSessionName ?? mySession;
|
|
3548
|
+
}
|
|
3549
|
+
if (candidate && isRootSession(candidate)) {
|
|
3550
|
+
try {
|
|
3551
|
+
const transport = getTransport();
|
|
3552
|
+
const liveSessions = transport.listSessions();
|
|
3553
|
+
if (!liveSessions.includes(candidate)) {
|
|
3554
|
+
const liveRoots = liveSessions.filter((s) => isRootSession(s));
|
|
3555
|
+
if (liveRoots.length === 1) {
|
|
3556
|
+
process.stderr.write(
|
|
3557
|
+
`[tmux-routing] WARN: resolved session "${candidate}" is dead. Using live coordinator "${liveRoots[0]}".
|
|
3558
|
+
`
|
|
3559
|
+
);
|
|
3560
|
+
return liveRoots[0];
|
|
3561
|
+
} else if (liveRoots.length > 1) {
|
|
3562
|
+
const base = candidate.replace(/\d+$/, "");
|
|
3563
|
+
const match = liveRoots.find((s) => s.startsWith(base));
|
|
3564
|
+
const chosen = match ?? liveRoots[0];
|
|
3565
|
+
process.stderr.write(
|
|
3566
|
+
`[tmux-routing] WARN: resolved session "${candidate}" is dead. ${liveRoots.length} live roots found, using "${chosen}".
|
|
3567
|
+
`
|
|
3568
|
+
);
|
|
3569
|
+
return chosen;
|
|
3570
|
+
}
|
|
3571
|
+
process.stderr.write(
|
|
3572
|
+
`[tmux-routing] WARN: resolved session "${candidate}" is dead and no live coordinator found.
|
|
3573
|
+
`
|
|
3574
|
+
);
|
|
3575
|
+
}
|
|
3576
|
+
} catch {
|
|
3577
|
+
}
|
|
3578
|
+
}
|
|
3579
|
+
return candidate;
|
|
3501
3580
|
}
|
|
3502
3581
|
var SPAWN_LOCK_DIR, SESSION_CACHE, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS;
|
|
3503
3582
|
var init_tmux_routing = __esm({
|
|
@@ -4633,6 +4712,20 @@ var init_platform_procedures = __esm({
|
|
|
4633
4712
|
priority: "p1",
|
|
4634
4713
|
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."
|
|
4635
4714
|
},
|
|
4715
|
+
// --- Tool guidance ---
|
|
4716
|
+
{
|
|
4717
|
+
title: "How to use company_actions \u2014 execute business actions through gateway connectors",
|
|
4718
|
+
domain: "tools",
|
|
4719
|
+
priority: "p2",
|
|
4720
|
+
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."
|
|
4721
|
+
},
|
|
4722
|
+
// --- Release awareness ---
|
|
4723
|
+
{
|
|
4724
|
+
title: "What's New check \u2014 surface new features after update",
|
|
4725
|
+
domain: "support",
|
|
4726
|
+
priority: "p1",
|
|
4727
|
+
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."
|
|
4728
|
+
},
|
|
4636
4729
|
// --- Platform vs Customer ownership ---
|
|
4637
4730
|
{
|
|
4638
4731
|
title: "What the platform provides vs what you customize",
|
|
@@ -4721,13 +4814,13 @@ var init_platform_procedures = __esm({
|
|
|
4721
4814
|
title: "MCP tools \u2014 memory, decision, and search",
|
|
4722
4815
|
domain: "tool-use",
|
|
4723
4816
|
priority: "p1",
|
|
4724
|
-
content: `memory(action="recall") / recall_my_memory: search
|
|
4817
|
+
content: `memory(action="recall") / recall_my_memory: search memories (semantic + FTS). Params: as_of (bi-temporal \u2014 what did I know at time X?), kind (decision|procedure|observation|raw|conversation|behavior), retrieval_mode (all|decisions_only|procedures_only|operational|recent_high_value). memory(action="ask_team") / ask_team_memory: search a colleague's memories. memory(action="store") / store_memory: persist a memory. Params: kind, procedure_for (domain tag for procedures). memory(action="commit") / commit_memory: high-importance, survives consolidation. Requires summary. memory(action="search") / search_everything: unified search across memories, tasks, entities, conversations. memory(action="session_context") / get_session_context: temporal window. Requires session_id + target_timestamp. memory(action="get_by_id"): fetch one memory by UUID with full untruncated text. memory(action="consolidate") / consolidate_memories: merge duplicate/related memories. memory(action="cardinality") / get_memory_cardinality: count memories per agent. memory(action="supersede"): replace an old memory with a new version (old_id + new text). decision(action="store") / store_decision: record an architectural decision (domain, decision, rationale). decision(action="get") / get_decision: retrieve a past decision by domain or query.`
|
|
4725
4818
|
},
|
|
4726
4819
|
{
|
|
4727
4820
|
title: "MCP tools \u2014 task orchestration",
|
|
4728
4821
|
domain: "tool-use",
|
|
4729
4822
|
priority: "p1",
|
|
4730
|
-
content: 'task(action="create") / create_task: dispatch work (title, assigned_to, context). The ONLY dispatch path. Auto-spawns session. task(action="list") / list_tasks: query tasks by status, assignee, project. task(action="get") / get_task: fetch full task details by task_id. task(action="update") / update_task: change status (in_progress, done, blocked, cancelled) + result summary. task(action="close") / close_task: finalize a reviewed task (COO only). task(action="checkpoint") / checkpoint_task: save progress state for crash recovery. task(action="resume") / resume_employee: re-spawn an employee session for an existing task.'
|
|
4823
|
+
content: 'task(action="create") / create_task: dispatch work (title, assigned_to, context). The ONLY dispatch path. Auto-spawns session. Params: blocked_by (task ID for dependency), parent_task_id (subtask hierarchy), reviewer, complexity (routine|standard|complex|critical), budget_tokens (max token cap), budget_fallback_model, spawn_runtime (override runtime: claude|codex|opencode), spawn_model (override model). task(action="list") / list_tasks: query tasks by status, assignee, project. task(action="get") / get_task: fetch full task details by task_id. task(action="update") / update_task: change status (in_progress, done, blocked, cancelled) + result summary. task(action="close") / close_task: finalize a reviewed task (COO only). task(action="checkpoint") / checkpoint_task: save progress state for crash recovery. task(action="resume") / resume_employee: re-spawn an employee session for an existing task.'
|
|
4731
4824
|
},
|
|
4732
4825
|
{
|
|
4733
4826
|
title: "MCP tools \u2014 knowledge graph (GraphRAG)",
|
|
@@ -4757,7 +4850,7 @@ var init_platform_procedures = __esm({
|
|
|
4757
4850
|
title: "MCP tools \u2014 admin, config, and operations",
|
|
4758
4851
|
domain: "tool-use",
|
|
4759
4852
|
priority: "p1",
|
|
4760
|
-
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.'
|
|
4853
|
+
content: 'config(action="list_employees"): view roster. config(action="set_agent_config"): view or change per-agent runtime + model. Call with no args to show all agents. config(action="agent_spend"): token usage per agent. config(action="daemon_health"): check exed status. config(action="license_status"): check license. config(action="cloud_sync"): force sync. Supports cloud_action param: status|sync|reupload. config(action="memory_audit"): health check (dupes, null vectors). config(action="run_consolidation"): trigger memory consolidation. config(action="worker_gate"): check spawn slot availability \u2014 alive/stale/reserved counts vs max. Use before dispatching. config(action="auto_wake_status"): orphaned tasks, blocked tasks, auto-wake retry status. config(action="orchestration_phase"): view/change org phase (phase_1_coo|phase_2_executives|phase_3_parallel_org). config(action="company_procedure", subaction="store|list|deactivate"): manage company procedures. config(action="global_procedure"): list all procedures (platform + company). config(action="create_trigger|list_triggers"): scheduled agent jobs. config(action="export_orchestration|import_orchestration"): portable org state. diagnostics(action="healthcheck|doctor|status_brief|check_update|cloud_status"): system diagnostics. diagnostics(action="pending_work_summary"): pending reviews + messages + notifications in one call. diagnostics(action="rename_employee"): rename an agent across all systems (roster, identity, DB, symlinks). diagnostics(action="tool_search"): semantic tool discovery \u2014 find relevant MCP tools by natural language query. diagnostics(action="drift"): identity drift detection \u2014 score how far an agent has drifted from its role. mcp_ping(): daemon health + license status + tool usage stats.'
|
|
4761
4854
|
}
|
|
4762
4855
|
];
|
|
4763
4856
|
PLATFORM_PROCEDURE_TITLES = new Set(
|
|
@@ -5441,6 +5534,8 @@ async function writeMemory(record) {
|
|
|
5441
5534
|
source_type: record.source_type ?? null,
|
|
5442
5535
|
tier: record.tier ?? classifyTier(record),
|
|
5443
5536
|
supersedes_id: record.supersedes_id ?? null,
|
|
5537
|
+
valid_from: record.valid_from ?? record.timestamp,
|
|
5538
|
+
invalid_at: record.invalid_at ?? null,
|
|
5444
5539
|
draft: record.draft ? 1 : 0,
|
|
5445
5540
|
memory_type: memoryType,
|
|
5446
5541
|
trajectory: record.trajectory ? JSON.stringify(record.trajectory) : null,
|
|
@@ -5459,7 +5554,8 @@ async function writeMemory(record) {
|
|
|
5459
5554
|
token_cost: record.token_cost ?? null,
|
|
5460
5555
|
audience: record.audience ?? null,
|
|
5461
5556
|
language_type: record.language_type ?? inferLanguageType(record),
|
|
5462
|
-
parent_memory_id: record.parent_memory_id ?? null
|
|
5557
|
+
parent_memory_id: record.parent_memory_id ?? null,
|
|
5558
|
+
procedure_for: record.procedure_for ?? null
|
|
5463
5559
|
};
|
|
5464
5560
|
_pendingRecords.push(dbRow);
|
|
5465
5561
|
orgBus.emit({
|
|
@@ -5514,6 +5610,8 @@ async function flushBatch() {
|
|
|
5514
5610
|
const sourceType = row.source_type ?? null;
|
|
5515
5611
|
const tier = row.tier ?? 3;
|
|
5516
5612
|
const supersedesId = row.supersedes_id ?? null;
|
|
5613
|
+
const validFrom = row.valid_from ?? row.timestamp;
|
|
5614
|
+
const invalidAt = row.invalid_at ?? null;
|
|
5517
5615
|
const draft = row.draft ? 1 : 0;
|
|
5518
5616
|
const memoryType = row.memory_type ?? "raw";
|
|
5519
5617
|
const trajectory = row.trajectory ?? null;
|
|
@@ -5533,15 +5631,16 @@ async function flushBatch() {
|
|
|
5533
5631
|
const audience = row.audience ?? null;
|
|
5534
5632
|
const languageType = row.language_type ?? null;
|
|
5535
5633
|
const parentMemoryId = row.parent_memory_id ?? null;
|
|
5634
|
+
const procedureFor = row.procedure_for ?? null;
|
|
5536
5635
|
const cols = `id, agent_id, agent_role, session_id, timestamp,
|
|
5537
5636
|
tool_name, project_name,
|
|
5538
5637
|
has_error, raw_text, vector, version, task_id, importance, status,
|
|
5539
5638
|
confidence, last_accessed,
|
|
5540
5639
|
workspace_id, document_id, user_id, char_offset, page_number,
|
|
5541
|
-
source_path, source_type, tier, supersedes_id, draft, memory_type, trajectory, content_hash,
|
|
5640
|
+
source_path, source_type, tier, supersedes_id, valid_from, invalid_at, draft, memory_type, trajectory, content_hash,
|
|
5542
5641
|
intent, outcome, domain, referenced_entities, retrieval_count,
|
|
5543
5642
|
chain_position, review_status, context_window_pct, file_paths, commit_hash,
|
|
5544
|
-
duration_ms, token_cost, audience, language_type, parent_memory_id`;
|
|
5643
|
+
duration_ms, token_cost, audience, language_type, parent_memory_id, procedure_for`;
|
|
5545
5644
|
const metaArgs = [
|
|
5546
5645
|
intent,
|
|
5547
5646
|
outcome,
|
|
@@ -5557,7 +5656,8 @@ async function flushBatch() {
|
|
|
5557
5656
|
tokenCost,
|
|
5558
5657
|
audience,
|
|
5559
5658
|
languageType,
|
|
5560
|
-
parentMemoryId
|
|
5659
|
+
parentMemoryId,
|
|
5660
|
+
procedureFor
|
|
5561
5661
|
];
|
|
5562
5662
|
const baseArgs = [
|
|
5563
5663
|
row.id,
|
|
@@ -5586,6 +5686,8 @@ async function flushBatch() {
|
|
|
5586
5686
|
sourceType,
|
|
5587
5687
|
tier,
|
|
5588
5688
|
supersedesId,
|
|
5689
|
+
validFrom,
|
|
5690
|
+
invalidAt,
|
|
5589
5691
|
draft,
|
|
5590
5692
|
memoryType,
|
|
5591
5693
|
trajectory,
|
|
@@ -5593,8 +5695,8 @@ async function flushBatch() {
|
|
|
5593
5695
|
];
|
|
5594
5696
|
return {
|
|
5595
5697
|
sql: hasVector ? `INSERT OR IGNORE INTO memories (${cols})
|
|
5596
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
|
|
5597
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
5698
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
|
|
5699
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
5598
5700
|
args: hasVector ? [...baseArgs, vectorToBlob(row.vector), ...sharedArgs, ...metaArgs] : [...baseArgs, ...sharedArgs, ...metaArgs]
|
|
5599
5701
|
};
|
|
5600
5702
|
};
|
|
@@ -5710,6 +5812,12 @@ async function searchMemories(queryVector, agentId, options) {
|
|
|
5710
5812
|
AND vector IS NOT NULL${statusFilter}${draftFilter}
|
|
5711
5813
|
AND COALESCE(confidence, 0.7) >= 0.3`;
|
|
5712
5814
|
const args = [agentId];
|
|
5815
|
+
if (options?.asOf) {
|
|
5816
|
+
sql += ` AND (valid_from IS NULL OR valid_from <= ?) AND (invalid_at IS NULL OR invalid_at > ?)`;
|
|
5817
|
+
args.push(options.asOf, options.asOf);
|
|
5818
|
+
} else {
|
|
5819
|
+
sql += ` AND invalid_at IS NULL`;
|
|
5820
|
+
}
|
|
5713
5821
|
const scope = buildWikiScopeFilter(options, "");
|
|
5714
5822
|
sql += scope.clause;
|
|
5715
5823
|
args.push(...scope.args);
|
|
@@ -2776,6 +2776,20 @@ async function ensureSchema() {
|
|
|
2776
2776
|
});
|
|
2777
2777
|
} catch {
|
|
2778
2778
|
}
|
|
2779
|
+
try {
|
|
2780
|
+
await client.execute({
|
|
2781
|
+
sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
|
|
2782
|
+
args: []
|
|
2783
|
+
});
|
|
2784
|
+
} catch {
|
|
2785
|
+
}
|
|
2786
|
+
try {
|
|
2787
|
+
await client.execute({
|
|
2788
|
+
sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
|
|
2789
|
+
args: []
|
|
2790
|
+
});
|
|
2791
|
+
} catch {
|
|
2792
|
+
}
|
|
2779
2793
|
await client.executeMultiple(`
|
|
2780
2794
|
CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
|
|
2781
2795
|
content_text,
|
|
@@ -3027,6 +3041,22 @@ async function ensureSchema() {
|
|
|
3027
3041
|
);
|
|
3028
3042
|
} catch {
|
|
3029
3043
|
}
|
|
3044
|
+
for (const col of [
|
|
3045
|
+
"ALTER TABLE memories ADD COLUMN valid_from TEXT",
|
|
3046
|
+
"ALTER TABLE memories ADD COLUMN invalid_at TEXT"
|
|
3047
|
+
]) {
|
|
3048
|
+
try {
|
|
3049
|
+
await client.execute(col);
|
|
3050
|
+
} catch {
|
|
3051
|
+
}
|
|
3052
|
+
}
|
|
3053
|
+
try {
|
|
3054
|
+
await client.execute({
|
|
3055
|
+
sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
|
|
3056
|
+
args: []
|
|
3057
|
+
});
|
|
3058
|
+
} catch {
|
|
3059
|
+
}
|
|
3030
3060
|
try {
|
|
3031
3061
|
await client.execute({
|
|
3032
3062
|
sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
|
|
@@ -3069,6 +3099,13 @@ async function ensureSchema() {
|
|
|
3069
3099
|
} catch {
|
|
3070
3100
|
}
|
|
3071
3101
|
}
|
|
3102
|
+
try {
|
|
3103
|
+
await client.execute({
|
|
3104
|
+
sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
|
|
3105
|
+
args: []
|
|
3106
|
+
});
|
|
3107
|
+
} catch {
|
|
3108
|
+
}
|
|
3072
3109
|
try {
|
|
3073
3110
|
await client.execute({
|
|
3074
3111
|
sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
|
|
@@ -3413,7 +3450,7 @@ import { pathToFileURL as pathToFileURL2 } from "url";
|
|
|
3413
3450
|
import os7 from "os";
|
|
3414
3451
|
import path9 from "path";
|
|
3415
3452
|
import { jwtVerify, importSPKI } from "jose";
|
|
3416
|
-
var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH;
|
|
3453
|
+
var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH, API_BASE;
|
|
3417
3454
|
var init_license = __esm({
|
|
3418
3455
|
"src/lib/license.ts"() {
|
|
3419
3456
|
"use strict";
|
|
@@ -3421,6 +3458,7 @@ var init_license = __esm({
|
|
|
3421
3458
|
LICENSE_PATH = path9.join(EXE_AI_DIR, "license.key");
|
|
3422
3459
|
CACHE_PATH = path9.join(EXE_AI_DIR, "license-cache.json");
|
|
3423
3460
|
DEVICE_ID_PATH = path9.join(EXE_AI_DIR, "device-id");
|
|
3461
|
+
API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://askexe.com/cloud";
|
|
3424
3462
|
}
|
|
3425
3463
|
});
|
|
3426
3464
|
|
|
@@ -3464,6 +3502,9 @@ import { fileURLToPath as fileURLToPath2 } from "url";
|
|
|
3464
3502
|
function getMySession() {
|
|
3465
3503
|
return getTransport().getMySession();
|
|
3466
3504
|
}
|
|
3505
|
+
function isRootSession(name) {
|
|
3506
|
+
return name.length > 0 && !name.includes("-");
|
|
3507
|
+
}
|
|
3467
3508
|
function extractRootExe(name) {
|
|
3468
3509
|
if (!name) return null;
|
|
3469
3510
|
if (!name.includes("-")) return name;
|
|
@@ -3479,9 +3520,13 @@ function getParentExe(sessionKey) {
|
|
|
3479
3520
|
}
|
|
3480
3521
|
}
|
|
3481
3522
|
function resolveExeSession() {
|
|
3523
|
+
if (process.env.EXE_SESSION_NAME) {
|
|
3524
|
+
return extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
|
|
3525
|
+
}
|
|
3482
3526
|
const mySession = getMySession();
|
|
3483
3527
|
if (!mySession) return null;
|
|
3484
3528
|
const fromSessionName = extractRootExe(mySession);
|
|
3529
|
+
let candidate = null;
|
|
3485
3530
|
try {
|
|
3486
3531
|
const key = getSessionKey();
|
|
3487
3532
|
const parentExe = getParentExe(key);
|
|
@@ -3492,13 +3537,47 @@ function resolveExeSession() {
|
|
|
3492
3537
|
`[tmux-routing] WARN: cache says "${fromCache}" but session name says "${fromSessionName}". Trusting session name.
|
|
3493
3538
|
`
|
|
3494
3539
|
);
|
|
3495
|
-
|
|
3540
|
+
candidate = fromSessionName;
|
|
3541
|
+
} else {
|
|
3542
|
+
candidate = fromCache;
|
|
3496
3543
|
}
|
|
3497
|
-
return fromCache;
|
|
3498
3544
|
}
|
|
3499
3545
|
} catch {
|
|
3500
3546
|
}
|
|
3501
|
-
|
|
3547
|
+
if (!candidate) {
|
|
3548
|
+
candidate = fromSessionName ?? mySession;
|
|
3549
|
+
}
|
|
3550
|
+
if (candidate && isRootSession(candidate)) {
|
|
3551
|
+
try {
|
|
3552
|
+
const transport = getTransport();
|
|
3553
|
+
const liveSessions = transport.listSessions();
|
|
3554
|
+
if (!liveSessions.includes(candidate)) {
|
|
3555
|
+
const liveRoots = liveSessions.filter((s) => isRootSession(s));
|
|
3556
|
+
if (liveRoots.length === 1) {
|
|
3557
|
+
process.stderr.write(
|
|
3558
|
+
`[tmux-routing] WARN: resolved session "${candidate}" is dead. Using live coordinator "${liveRoots[0]}".
|
|
3559
|
+
`
|
|
3560
|
+
);
|
|
3561
|
+
return liveRoots[0];
|
|
3562
|
+
} else if (liveRoots.length > 1) {
|
|
3563
|
+
const base = candidate.replace(/\d+$/, "");
|
|
3564
|
+
const match = liveRoots.find((s) => s.startsWith(base));
|
|
3565
|
+
const chosen = match ?? liveRoots[0];
|
|
3566
|
+
process.stderr.write(
|
|
3567
|
+
`[tmux-routing] WARN: resolved session "${candidate}" is dead. ${liveRoots.length} live roots found, using "${chosen}".
|
|
3568
|
+
`
|
|
3569
|
+
);
|
|
3570
|
+
return chosen;
|
|
3571
|
+
}
|
|
3572
|
+
process.stderr.write(
|
|
3573
|
+
`[tmux-routing] WARN: resolved session "${candidate}" is dead and no live coordinator found.
|
|
3574
|
+
`
|
|
3575
|
+
);
|
|
3576
|
+
}
|
|
3577
|
+
} catch {
|
|
3578
|
+
}
|
|
3579
|
+
}
|
|
3580
|
+
return candidate;
|
|
3502
3581
|
}
|
|
3503
3582
|
var SPAWN_LOCK_DIR, SESSION_CACHE, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS;
|
|
3504
3583
|
var init_tmux_routing = __esm({
|
|
@@ -4699,6 +4778,20 @@ var init_platform_procedures = __esm({
|
|
|
4699
4778
|
priority: "p1",
|
|
4700
4779
|
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."
|
|
4701
4780
|
},
|
|
4781
|
+
// --- Tool guidance ---
|
|
4782
|
+
{
|
|
4783
|
+
title: "How to use company_actions \u2014 execute business actions through gateway connectors",
|
|
4784
|
+
domain: "tools",
|
|
4785
|
+
priority: "p2",
|
|
4786
|
+
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."
|
|
4787
|
+
},
|
|
4788
|
+
// --- Release awareness ---
|
|
4789
|
+
{
|
|
4790
|
+
title: "What's New check \u2014 surface new features after update",
|
|
4791
|
+
domain: "support",
|
|
4792
|
+
priority: "p1",
|
|
4793
|
+
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."
|
|
4794
|
+
},
|
|
4702
4795
|
// --- Platform vs Customer ownership ---
|
|
4703
4796
|
{
|
|
4704
4797
|
title: "What the platform provides vs what you customize",
|
|
@@ -4787,13 +4880,13 @@ var init_platform_procedures = __esm({
|
|
|
4787
4880
|
title: "MCP tools \u2014 memory, decision, and search",
|
|
4788
4881
|
domain: "tool-use",
|
|
4789
4882
|
priority: "p1",
|
|
4790
|
-
content: `memory(action="recall") / recall_my_memory: search
|
|
4883
|
+
content: `memory(action="recall") / recall_my_memory: search memories (semantic + FTS). Params: as_of (bi-temporal \u2014 what did I know at time X?), kind (decision|procedure|observation|raw|conversation|behavior), retrieval_mode (all|decisions_only|procedures_only|operational|recent_high_value). memory(action="ask_team") / ask_team_memory: search a colleague's memories. memory(action="store") / store_memory: persist a memory. Params: kind, procedure_for (domain tag for procedures). memory(action="commit") / commit_memory: high-importance, survives consolidation. Requires summary. memory(action="search") / search_everything: unified search across memories, tasks, entities, conversations. memory(action="session_context") / get_session_context: temporal window. Requires session_id + target_timestamp. memory(action="get_by_id"): fetch one memory by UUID with full untruncated text. memory(action="consolidate") / consolidate_memories: merge duplicate/related memories. memory(action="cardinality") / get_memory_cardinality: count memories per agent. memory(action="supersede"): replace an old memory with a new version (old_id + new text). decision(action="store") / store_decision: record an architectural decision (domain, decision, rationale). decision(action="get") / get_decision: retrieve a past decision by domain or query.`
|
|
4791
4884
|
},
|
|
4792
4885
|
{
|
|
4793
4886
|
title: "MCP tools \u2014 task orchestration",
|
|
4794
4887
|
domain: "tool-use",
|
|
4795
4888
|
priority: "p1",
|
|
4796
|
-
content: 'task(action="create") / create_task: dispatch work (title, assigned_to, context). The ONLY dispatch path. Auto-spawns session. task(action="list") / list_tasks: query tasks by status, assignee, project. task(action="get") / get_task: fetch full task details by task_id. task(action="update") / update_task: change status (in_progress, done, blocked, cancelled) + result summary. task(action="close") / close_task: finalize a reviewed task (COO only). task(action="checkpoint") / checkpoint_task: save progress state for crash recovery. task(action="resume") / resume_employee: re-spawn an employee session for an existing task.'
|
|
4889
|
+
content: 'task(action="create") / create_task: dispatch work (title, assigned_to, context). The ONLY dispatch path. Auto-spawns session. Params: blocked_by (task ID for dependency), parent_task_id (subtask hierarchy), reviewer, complexity (routine|standard|complex|critical), budget_tokens (max token cap), budget_fallback_model, spawn_runtime (override runtime: claude|codex|opencode), spawn_model (override model). task(action="list") / list_tasks: query tasks by status, assignee, project. task(action="get") / get_task: fetch full task details by task_id. task(action="update") / update_task: change status (in_progress, done, blocked, cancelled) + result summary. task(action="close") / close_task: finalize a reviewed task (COO only). task(action="checkpoint") / checkpoint_task: save progress state for crash recovery. task(action="resume") / resume_employee: re-spawn an employee session for an existing task.'
|
|
4797
4890
|
},
|
|
4798
4891
|
{
|
|
4799
4892
|
title: "MCP tools \u2014 knowledge graph (GraphRAG)",
|
|
@@ -4823,7 +4916,7 @@ var init_platform_procedures = __esm({
|
|
|
4823
4916
|
title: "MCP tools \u2014 admin, config, and operations",
|
|
4824
4917
|
domain: "tool-use",
|
|
4825
4918
|
priority: "p1",
|
|
4826
|
-
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.'
|
|
4919
|
+
content: 'config(action="list_employees"): view roster. config(action="set_agent_config"): view or change per-agent runtime + model. Call with no args to show all agents. config(action="agent_spend"): token usage per agent. config(action="daemon_health"): check exed status. config(action="license_status"): check license. config(action="cloud_sync"): force sync. Supports cloud_action param: status|sync|reupload. config(action="memory_audit"): health check (dupes, null vectors). config(action="run_consolidation"): trigger memory consolidation. config(action="worker_gate"): check spawn slot availability \u2014 alive/stale/reserved counts vs max. Use before dispatching. config(action="auto_wake_status"): orphaned tasks, blocked tasks, auto-wake retry status. config(action="orchestration_phase"): view/change org phase (phase_1_coo|phase_2_executives|phase_3_parallel_org). config(action="company_procedure", subaction="store|list|deactivate"): manage company procedures. config(action="global_procedure"): list all procedures (platform + company). config(action="create_trigger|list_triggers"): scheduled agent jobs. config(action="export_orchestration|import_orchestration"): portable org state. diagnostics(action="healthcheck|doctor|status_brief|check_update|cloud_status"): system diagnostics. diagnostics(action="pending_work_summary"): pending reviews + messages + notifications in one call. diagnostics(action="rename_employee"): rename an agent across all systems (roster, identity, DB, symlinks). diagnostics(action="tool_search"): semantic tool discovery \u2014 find relevant MCP tools by natural language query. diagnostics(action="drift"): identity drift detection \u2014 score how far an agent has drifted from its role. mcp_ping(): daemon health + license status + tool usage stats.'
|
|
4827
4920
|
}
|
|
4828
4921
|
];
|
|
4829
4922
|
PLATFORM_PROCEDURE_TITLES = new Set(
|
|
@@ -5507,6 +5600,8 @@ async function writeMemory(record) {
|
|
|
5507
5600
|
source_type: record.source_type ?? null,
|
|
5508
5601
|
tier: record.tier ?? classifyTier(record),
|
|
5509
5602
|
supersedes_id: record.supersedes_id ?? null,
|
|
5603
|
+
valid_from: record.valid_from ?? record.timestamp,
|
|
5604
|
+
invalid_at: record.invalid_at ?? null,
|
|
5510
5605
|
draft: record.draft ? 1 : 0,
|
|
5511
5606
|
memory_type: memoryType,
|
|
5512
5607
|
trajectory: record.trajectory ? JSON.stringify(record.trajectory) : null,
|
|
@@ -5525,7 +5620,8 @@ async function writeMemory(record) {
|
|
|
5525
5620
|
token_cost: record.token_cost ?? null,
|
|
5526
5621
|
audience: record.audience ?? null,
|
|
5527
5622
|
language_type: record.language_type ?? inferLanguageType(record),
|
|
5528
|
-
parent_memory_id: record.parent_memory_id ?? null
|
|
5623
|
+
parent_memory_id: record.parent_memory_id ?? null,
|
|
5624
|
+
procedure_for: record.procedure_for ?? null
|
|
5529
5625
|
};
|
|
5530
5626
|
_pendingRecords.push(dbRow);
|
|
5531
5627
|
orgBus.emit({
|
|
@@ -5580,6 +5676,8 @@ async function flushBatch() {
|
|
|
5580
5676
|
const sourceType = row.source_type ?? null;
|
|
5581
5677
|
const tier = row.tier ?? 3;
|
|
5582
5678
|
const supersedesId = row.supersedes_id ?? null;
|
|
5679
|
+
const validFrom = row.valid_from ?? row.timestamp;
|
|
5680
|
+
const invalidAt = row.invalid_at ?? null;
|
|
5583
5681
|
const draft = row.draft ? 1 : 0;
|
|
5584
5682
|
const memoryType = row.memory_type ?? "raw";
|
|
5585
5683
|
const trajectory = row.trajectory ?? null;
|
|
@@ -5599,15 +5697,16 @@ async function flushBatch() {
|
|
|
5599
5697
|
const audience = row.audience ?? null;
|
|
5600
5698
|
const languageType = row.language_type ?? null;
|
|
5601
5699
|
const parentMemoryId = row.parent_memory_id ?? null;
|
|
5700
|
+
const procedureFor = row.procedure_for ?? null;
|
|
5602
5701
|
const cols = `id, agent_id, agent_role, session_id, timestamp,
|
|
5603
5702
|
tool_name, project_name,
|
|
5604
5703
|
has_error, raw_text, vector, version, task_id, importance, status,
|
|
5605
5704
|
confidence, last_accessed,
|
|
5606
5705
|
workspace_id, document_id, user_id, char_offset, page_number,
|
|
5607
|
-
source_path, source_type, tier, supersedes_id, draft, memory_type, trajectory, content_hash,
|
|
5706
|
+
source_path, source_type, tier, supersedes_id, valid_from, invalid_at, draft, memory_type, trajectory, content_hash,
|
|
5608
5707
|
intent, outcome, domain, referenced_entities, retrieval_count,
|
|
5609
5708
|
chain_position, review_status, context_window_pct, file_paths, commit_hash,
|
|
5610
|
-
duration_ms, token_cost, audience, language_type, parent_memory_id`;
|
|
5709
|
+
duration_ms, token_cost, audience, language_type, parent_memory_id, procedure_for`;
|
|
5611
5710
|
const metaArgs = [
|
|
5612
5711
|
intent,
|
|
5613
5712
|
outcome,
|
|
@@ -5623,7 +5722,8 @@ async function flushBatch() {
|
|
|
5623
5722
|
tokenCost,
|
|
5624
5723
|
audience,
|
|
5625
5724
|
languageType,
|
|
5626
|
-
parentMemoryId
|
|
5725
|
+
parentMemoryId,
|
|
5726
|
+
procedureFor
|
|
5627
5727
|
];
|
|
5628
5728
|
const baseArgs = [
|
|
5629
5729
|
row.id,
|
|
@@ -5652,6 +5752,8 @@ async function flushBatch() {
|
|
|
5652
5752
|
sourceType,
|
|
5653
5753
|
tier,
|
|
5654
5754
|
supersedesId,
|
|
5755
|
+
validFrom,
|
|
5756
|
+
invalidAt,
|
|
5655
5757
|
draft,
|
|
5656
5758
|
memoryType,
|
|
5657
5759
|
trajectory,
|
|
@@ -5659,8 +5761,8 @@ async function flushBatch() {
|
|
|
5659
5761
|
];
|
|
5660
5762
|
return {
|
|
5661
5763
|
sql: hasVector ? `INSERT OR IGNORE INTO memories (${cols})
|
|
5662
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
|
|
5663
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
5764
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
|
|
5765
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
5664
5766
|
args: hasVector ? [...baseArgs, vectorToBlob(row.vector), ...sharedArgs, ...metaArgs] : [...baseArgs, ...sharedArgs, ...metaArgs]
|
|
5665
5767
|
};
|
|
5666
5768
|
};
|
|
@@ -5776,6 +5878,12 @@ async function searchMemories(queryVector, agentId, options) {
|
|
|
5776
5878
|
AND vector IS NOT NULL${statusFilter}${draftFilter}
|
|
5777
5879
|
AND COALESCE(confidence, 0.7) >= 0.3`;
|
|
5778
5880
|
const args = [agentId];
|
|
5881
|
+
if (options?.asOf) {
|
|
5882
|
+
sql += ` AND (valid_from IS NULL OR valid_from <= ?) AND (invalid_at IS NULL OR invalid_at > ?)`;
|
|
5883
|
+
args.push(options.asOf, options.asOf);
|
|
5884
|
+
} else {
|
|
5885
|
+
sql += ` AND invalid_at IS NULL`;
|
|
5886
|
+
}
|
|
5779
5887
|
const scope = buildWikiScopeFilter(options, "");
|
|
5780
5888
|
sql += scope.clause;
|
|
5781
5889
|
args.push(...scope.args);
|