@askexenow/exe-os 0.9.60 → 0.9.62
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/stack-manifests/v0.9.json +62 -13
- package/dist/bin/backfill-conversations.js +282 -7
- package/dist/bin/backfill-responses.js +282 -7
- package/dist/bin/backfill-vectors.js +119 -7
- package/dist/bin/cc-doctor.js +376 -0
- package/dist/bin/cleanup-stale-review-tasks.js +282 -7
- package/dist/bin/cli.js +455 -77
- package/dist/bin/customer-readiness.js +33 -0
- package/dist/bin/exe-agent-config.js +2 -2
- package/dist/bin/exe-agent.js +3 -3
- package/dist/bin/exe-assign.js +282 -7
- package/dist/bin/exe-boot.js +125 -13
- package/dist/bin/exe-call.js +3 -3
- package/dist/bin/exe-cloud.js +2 -2
- package/dist/bin/exe-dispatch.js +282 -7
- package/dist/bin/exe-doctor.js +119 -7
- package/dist/bin/exe-export-behaviors.js +282 -7
- package/dist/bin/exe-forget.js +336 -7
- package/dist/bin/exe-gateway.js +282 -7
- package/dist/bin/exe-heartbeat.js +284 -9
- package/dist/bin/exe-kill.js +282 -7
- package/dist/bin/exe-launch-agent.js +282 -7
- package/dist/bin/exe-link.js +121 -9
- package/dist/bin/exe-new-employee.js +50 -21
- package/dist/bin/exe-pending-messages.js +282 -7
- package/dist/bin/exe-pending-notifications.js +282 -7
- package/dist/bin/exe-pending-reviews.js +282 -7
- package/dist/bin/exe-rename.js +282 -7
- package/dist/bin/exe-review.js +282 -7
- package/dist/bin/exe-search.js +306 -8
- package/dist/bin/exe-session-cleanup.js +282 -7
- package/dist/bin/exe-settings.js +2 -2
- package/dist/bin/exe-start-codex.js +326 -21
- package/dist/bin/exe-start-opencode.js +304 -10
- package/dist/bin/exe-status.js +282 -7
- package/dist/bin/exe-team.js +282 -7
- package/dist/bin/git-sweep.js +282 -7
- package/dist/bin/graph-backfill.js +282 -7
- package/dist/bin/graph-export.js +282 -7
- package/dist/bin/install.js +58 -33
- package/dist/bin/intercom-check.js +282 -7
- package/dist/bin/pre-build-guard.js +98 -0
- package/dist/bin/scan-tasks.js +282 -7
- package/dist/bin/setup.js +122 -10
- package/dist/bin/shard-migrate.js +282 -7
- package/dist/bin/stack-update.js +79 -11
- package/dist/bin/update.js +2 -2
- package/dist/gateway/index.js +288 -13
- package/dist/hooks/bug-report-worker.js +282 -7
- package/dist/hooks/codex-stop-task-finalizer.js +282 -7
- package/dist/hooks/commit-complete.js +282 -7
- package/dist/hooks/error-recall.js +306 -8
- package/dist/hooks/exe-heartbeat-hook.js +2 -2
- package/dist/hooks/ingest-worker.js +2 -2
- package/dist/hooks/ingest.js +282 -7
- package/dist/hooks/instructions-loaded.js +282 -7
- package/dist/hooks/notification.js +282 -7
- package/dist/hooks/post-compact.js +282 -7
- package/dist/hooks/post-tool-combined.js +306 -8
- package/dist/hooks/pre-compact.js +282 -7
- package/dist/hooks/pre-tool-use.js +282 -7
- package/dist/hooks/prompt-submit.js +306 -8
- package/dist/hooks/session-end.js +282 -7
- package/dist/hooks/session-start.js +308 -10
- package/dist/hooks/stop.js +282 -7
- package/dist/hooks/subagent-stop.js +282 -7
- package/dist/hooks/summary-worker.js +125 -13
- package/dist/index.js +288 -13
- package/dist/lib/agent-config.js +2 -2
- package/dist/lib/cloud-sync.js +121 -9
- package/dist/lib/config.js +2 -2
- package/dist/lib/consolidation.js +2 -2
- package/dist/lib/database.js +115 -3
- package/dist/lib/db-daemon-client.js +2 -2
- package/dist/lib/db.js +115 -3
- package/dist/lib/device-registry.js +115 -3
- package/dist/lib/embedder.js +2 -2
- package/dist/lib/employee-templates.js +3 -3
- package/dist/lib/employees.js +2 -2
- package/dist/lib/exe-daemon-client.js +2 -2
- package/dist/lib/exe-daemon.js +339 -31
- package/dist/lib/hybrid-search.js +306 -8
- package/dist/lib/identity.js +2 -2
- package/dist/lib/license.js +2 -2
- package/dist/lib/messaging.js +2 -2
- package/dist/lib/reminders.js +2 -2
- package/dist/lib/schedules.js +119 -7
- package/dist/lib/skill-learning.js +2 -2
- package/dist/lib/store.js +282 -7
- package/dist/lib/task-router.js +2 -2
- package/dist/lib/tasks.js +2 -2
- package/dist/lib/tmux-routing.js +2 -2
- package/dist/lib/token-spend.js +2 -2
- package/dist/mcp/server.js +339 -31
- package/dist/mcp/tools/complete-reminder.js +2 -2
- package/dist/mcp/tools/create-reminder.js +2 -2
- package/dist/mcp/tools/create-task.js +2 -2
- package/dist/mcp/tools/deactivate-behavior.js +2 -2
- package/dist/mcp/tools/list-reminders.js +2 -2
- package/dist/mcp/tools/list-tasks.js +2 -2
- package/dist/mcp/tools/send-message.js +2 -2
- package/dist/mcp/tools/update-task.js +2 -2
- package/dist/runtime/index.js +282 -7
- package/dist/tui/App.js +290 -15
- package/package.json +3 -2
- package/stack.release.json +23 -7
|
@@ -116,6 +116,39 @@ test("No hardcoded 'yoshi'/'mari' in runtime task routing", () => {
|
|
|
116
116
|
if (router.includes('"mari"') || router.includes("'mari'")) return "Hardcoded 'mari' in task-router.ts";
|
|
117
117
|
return true;
|
|
118
118
|
});
|
|
119
|
+
test("Build output \u2014 referenced standalone dist/bin scripts are explicit tsup entries", () => {
|
|
120
|
+
const pkg = JSON.parse(readSrc("package.json"));
|
|
121
|
+
const tsup = readSrc("tsup.config.ts");
|
|
122
|
+
const commandDocs = execSync(
|
|
123
|
+
`grep -Rho "dist/bin/[A-Za-z0-9._-]*.js" src/commands package.json 2>/dev/null || true`,
|
|
124
|
+
{ encoding: "utf8", cwd: ROOT }
|
|
125
|
+
).trim().split("\n").filter(Boolean);
|
|
126
|
+
const refs = /* @__PURE__ */ new Set();
|
|
127
|
+
for (const value of Object.values(pkg.bin ?? {})) {
|
|
128
|
+
const match = value.match(/dist\/bin\/([^\/]+)\.js$/);
|
|
129
|
+
if (match?.[1]) refs.add(match[1]);
|
|
130
|
+
}
|
|
131
|
+
for (const script of Object.values(pkg.scripts ?? {})) {
|
|
132
|
+
for (const match of script.matchAll(/dist\/bin\/([A-Za-z0-9._-]+)\.js/g)) {
|
|
133
|
+
if (match[1]) refs.add(match[1]);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
for (const ref of commandDocs) {
|
|
137
|
+
const match = ref.match(/dist\/bin\/([A-Za-z0-9._-]+)\.js$/);
|
|
138
|
+
if (match?.[1]) refs.add(match[1]);
|
|
139
|
+
}
|
|
140
|
+
const missing = [...refs].filter((name) => !tsup.includes(`"bin/${name}"`));
|
|
141
|
+
if (missing.length > 0) return `Missing tsup bin entries: ${missing.join(", ")}`;
|
|
142
|
+
return true;
|
|
143
|
+
});
|
|
144
|
+
test("Providers \u2014 active code imports lib/providers, not gateway/providers", () => {
|
|
145
|
+
const hits = execSync(
|
|
146
|
+
`grep -R "gateway/providers" -n src --include="*.ts" --include="*.tsx" || true`,
|
|
147
|
+
{ encoding: "utf8", cwd: ROOT }
|
|
148
|
+
).trim().split("\n").filter(Boolean).filter((line) => !line.includes("src/gateway/providers/") && !line.includes("src/bin/customer-readiness.ts"));
|
|
149
|
+
if (hits.length > 0) return `Deprecated provider imports: ${hits.slice(0, 3).join("; ")}`;
|
|
150
|
+
return true;
|
|
151
|
+
});
|
|
119
152
|
console.log(`
|
|
120
153
|
\x1B[1m${pass + fail} tests: ${pass} passed, ${fail} failed\x1B[0m
|
|
121
154
|
`);
|
package/dist/bin/exe-agent.js
CHANGED
|
@@ -69,8 +69,8 @@ var init_config = __esm({
|
|
|
69
69
|
rerankerAutoTrigger: {
|
|
70
70
|
enabled: true,
|
|
71
71
|
broadQueryMinCardinality: 5e4,
|
|
72
|
-
fetchTopK:
|
|
73
|
-
returnTopK:
|
|
72
|
+
fetchTopK: 200,
|
|
73
|
+
returnTopK: 20
|
|
74
74
|
}
|
|
75
75
|
},
|
|
76
76
|
graphRagEnabled: true,
|
|
@@ -1462,7 +1462,7 @@ var PLATFORM_PROCEDURES = [
|
|
|
1462
1462
|
title: "MCP tools \u2014 advanced (triggers, skills, orchestration)",
|
|
1463
1463
|
domain: "tool-use",
|
|
1464
1464
|
priority: "p1",
|
|
1465
|
-
content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done.
|
|
1465
|
+
content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. company_procedure: manage customer-owned company procedures (Layer 0; actions: store, list, deactivate). Legacy aliases: global_procedure, store_global_procedure, list_global_procedures, deactivate_global_procedure."
|
|
1466
1466
|
}
|
|
1467
1467
|
];
|
|
1468
1468
|
var PLATFORM_PROCEDURE_TITLES = new Set(
|
package/dist/bin/exe-assign.js
CHANGED
|
@@ -192,8 +192,8 @@ var init_config = __esm({
|
|
|
192
192
|
rerankerAutoTrigger: {
|
|
193
193
|
enabled: true,
|
|
194
194
|
broadQueryMinCardinality: 5e4,
|
|
195
|
-
fetchTopK:
|
|
196
|
-
returnTopK:
|
|
195
|
+
fetchTopK: 200,
|
|
196
|
+
returnTopK: 20
|
|
197
197
|
}
|
|
198
198
|
},
|
|
199
199
|
graphRagEnabled: true,
|
|
@@ -2439,7 +2439,7 @@ async function ensureSchema() {
|
|
|
2439
2439
|
ON session_kills(agent_id);
|
|
2440
2440
|
`);
|
|
2441
2441
|
await client.execute(`
|
|
2442
|
-
CREATE TABLE IF NOT EXISTS
|
|
2442
|
+
CREATE TABLE IF NOT EXISTS company_procedures (
|
|
2443
2443
|
id TEXT PRIMARY KEY,
|
|
2444
2444
|
title TEXT NOT NULL,
|
|
2445
2445
|
content TEXT NOT NULL,
|
|
@@ -2450,6 +2450,73 @@ async function ensureSchema() {
|
|
|
2450
2450
|
updated_at TEXT NOT NULL
|
|
2451
2451
|
)
|
|
2452
2452
|
`);
|
|
2453
|
+
const legacyProcedureObject = await client.execute({
|
|
2454
|
+
sql: "SELECT type FROM sqlite_master WHERE name = 'global_procedures'",
|
|
2455
|
+
args: []
|
|
2456
|
+
});
|
|
2457
|
+
const legacyProcedureType = legacyProcedureObject.rows[0]?.type == null ? null : String(legacyProcedureObject.rows[0].type);
|
|
2458
|
+
if (legacyProcedureType === "table") {
|
|
2459
|
+
await client.execute(`
|
|
2460
|
+
INSERT OR IGNORE INTO company_procedures
|
|
2461
|
+
(id, title, content, priority, domain, active, created_at, updated_at)
|
|
2462
|
+
SELECT id, title, content, priority, domain, active, created_at, updated_at
|
|
2463
|
+
FROM global_procedures
|
|
2464
|
+
`);
|
|
2465
|
+
await client.executeMultiple(`
|
|
2466
|
+
CREATE TRIGGER IF NOT EXISTS global_procedures_mirror_insert
|
|
2467
|
+
AFTER INSERT ON global_procedures
|
|
2468
|
+
BEGIN
|
|
2469
|
+
INSERT OR IGNORE INTO company_procedures
|
|
2470
|
+
(id, title, content, priority, domain, active, created_at, updated_at)
|
|
2471
|
+
VALUES
|
|
2472
|
+
(NEW.id, NEW.title, NEW.content, NEW.priority, NEW.domain, NEW.active, NEW.created_at, NEW.updated_at);
|
|
2473
|
+
END;
|
|
2474
|
+
|
|
2475
|
+
CREATE TRIGGER IF NOT EXISTS global_procedures_mirror_update
|
|
2476
|
+
AFTER UPDATE ON global_procedures
|
|
2477
|
+
BEGIN
|
|
2478
|
+
UPDATE company_procedures
|
|
2479
|
+
SET title = NEW.title,
|
|
2480
|
+
content = NEW.content,
|
|
2481
|
+
priority = NEW.priority,
|
|
2482
|
+
domain = NEW.domain,
|
|
2483
|
+
active = NEW.active,
|
|
2484
|
+
created_at = NEW.created_at,
|
|
2485
|
+
updated_at = NEW.updated_at
|
|
2486
|
+
WHERE id = OLD.id;
|
|
2487
|
+
END;
|
|
2488
|
+
`);
|
|
2489
|
+
} else {
|
|
2490
|
+
await client.execute(`
|
|
2491
|
+
CREATE VIEW IF NOT EXISTS global_procedures AS
|
|
2492
|
+
SELECT id, title, content, priority, domain, active, created_at, updated_at
|
|
2493
|
+
FROM company_procedures
|
|
2494
|
+
`);
|
|
2495
|
+
await client.executeMultiple(`
|
|
2496
|
+
CREATE TRIGGER IF NOT EXISTS global_procedures_insert
|
|
2497
|
+
INSTEAD OF INSERT ON global_procedures
|
|
2498
|
+
BEGIN
|
|
2499
|
+
INSERT INTO company_procedures
|
|
2500
|
+
(id, title, content, priority, domain, active, created_at, updated_at)
|
|
2501
|
+
VALUES
|
|
2502
|
+
(NEW.id, NEW.title, NEW.content, NEW.priority, NEW.domain, NEW.active, NEW.created_at, NEW.updated_at);
|
|
2503
|
+
END;
|
|
2504
|
+
|
|
2505
|
+
CREATE TRIGGER IF NOT EXISTS global_procedures_update
|
|
2506
|
+
INSTEAD OF UPDATE ON global_procedures
|
|
2507
|
+
BEGIN
|
|
2508
|
+
UPDATE company_procedures
|
|
2509
|
+
SET title = NEW.title,
|
|
2510
|
+
content = NEW.content,
|
|
2511
|
+
priority = NEW.priority,
|
|
2512
|
+
domain = NEW.domain,
|
|
2513
|
+
active = NEW.active,
|
|
2514
|
+
created_at = NEW.created_at,
|
|
2515
|
+
updated_at = NEW.updated_at
|
|
2516
|
+
WHERE id = OLD.id;
|
|
2517
|
+
END;
|
|
2518
|
+
`);
|
|
2519
|
+
}
|
|
2453
2520
|
await client.executeMultiple(`
|
|
2454
2521
|
CREATE TABLE IF NOT EXISTS conversations (
|
|
2455
2522
|
id TEXT PRIMARY KEY,
|
|
@@ -2589,6 +2656,51 @@ async function ensureSchema() {
|
|
|
2589
2656
|
VALUES (new.rowid, new.content_text, new.sender_name, new.agent_response);
|
|
2590
2657
|
END;
|
|
2591
2658
|
`);
|
|
2659
|
+
await client.executeMultiple(`
|
|
2660
|
+
CREATE TABLE IF NOT EXISTS memory_cards (
|
|
2661
|
+
id TEXT PRIMARY KEY,
|
|
2662
|
+
memory_id TEXT NOT NULL,
|
|
2663
|
+
agent_id TEXT NOT NULL,
|
|
2664
|
+
session_id TEXT NOT NULL,
|
|
2665
|
+
project_name TEXT,
|
|
2666
|
+
timestamp TEXT NOT NULL,
|
|
2667
|
+
card_type TEXT NOT NULL,
|
|
2668
|
+
subject TEXT,
|
|
2669
|
+
predicate TEXT,
|
|
2670
|
+
object TEXT,
|
|
2671
|
+
content TEXT NOT NULL,
|
|
2672
|
+
source_ref TEXT,
|
|
2673
|
+
confidence REAL DEFAULT 0.6,
|
|
2674
|
+
active INTEGER DEFAULT 1,
|
|
2675
|
+
created_at TEXT NOT NULL
|
|
2676
|
+
);
|
|
2677
|
+
|
|
2678
|
+
CREATE INDEX IF NOT EXISTS idx_memory_cards_agent
|
|
2679
|
+
ON memory_cards(agent_id, active, timestamp);
|
|
2680
|
+
|
|
2681
|
+
CREATE INDEX IF NOT EXISTS idx_memory_cards_memory
|
|
2682
|
+
ON memory_cards(memory_id);
|
|
2683
|
+
|
|
2684
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS memory_cards_fts
|
|
2685
|
+
USING fts5(content, subject, predicate, object, content='memory_cards', content_rowid='rowid');
|
|
2686
|
+
|
|
2687
|
+
CREATE TRIGGER IF NOT EXISTS memory_cards_fts_ai AFTER INSERT ON memory_cards BEGIN
|
|
2688
|
+
INSERT INTO memory_cards_fts(rowid, content, subject, predicate, object)
|
|
2689
|
+
VALUES (new.rowid, new.content, new.subject, new.predicate, new.object);
|
|
2690
|
+
END;
|
|
2691
|
+
|
|
2692
|
+
CREATE TRIGGER IF NOT EXISTS memory_cards_fts_ad AFTER DELETE ON memory_cards BEGIN
|
|
2693
|
+
INSERT INTO memory_cards_fts(memory_cards_fts, rowid, content, subject, predicate, object)
|
|
2694
|
+
VALUES('delete', old.rowid, old.content, old.subject, old.predicate, old.object);
|
|
2695
|
+
END;
|
|
2696
|
+
|
|
2697
|
+
CREATE TRIGGER IF NOT EXISTS memory_cards_fts_au AFTER UPDATE ON memory_cards BEGIN
|
|
2698
|
+
INSERT INTO memory_cards_fts(memory_cards_fts, rowid, content, subject, predicate, object)
|
|
2699
|
+
VALUES('delete', old.rowid, old.content, old.subject, old.predicate, old.object);
|
|
2700
|
+
INSERT INTO memory_cards_fts(rowid, content, subject, predicate, object)
|
|
2701
|
+
VALUES (new.rowid, new.content, new.subject, new.predicate, new.object);
|
|
2702
|
+
END;
|
|
2703
|
+
`);
|
|
2592
2704
|
try {
|
|
2593
2705
|
await client.execute({
|
|
2594
2706
|
sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
|
|
@@ -3326,7 +3438,7 @@ var init_platform_procedures = __esm({
|
|
|
3326
3438
|
title: "MCP tools \u2014 advanced (triggers, skills, orchestration)",
|
|
3327
3439
|
domain: "tool-use",
|
|
3328
3440
|
priority: "p1",
|
|
3329
|
-
content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done.
|
|
3441
|
+
content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. company_procedure: manage customer-owned company procedures (Layer 0; actions: store, list, deactivate). Legacy aliases: global_procedure, store_global_procedure, list_global_procedures, deactivate_global_procedure."
|
|
3330
3442
|
}
|
|
3331
3443
|
];
|
|
3332
3444
|
PLATFORM_PROCEDURE_TITLES = new Set(
|
|
@@ -3347,7 +3459,7 @@ import { randomUUID as randomUUID3 } from "crypto";
|
|
|
3347
3459
|
async function loadGlobalProcedures() {
|
|
3348
3460
|
const client = getClient();
|
|
3349
3461
|
const result = await client.execute({
|
|
3350
|
-
sql: "SELECT * FROM
|
|
3462
|
+
sql: "SELECT * FROM company_procedures WHERE active = 1 ORDER BY priority ASC, created_at ASC",
|
|
3351
3463
|
args: []
|
|
3352
3464
|
});
|
|
3353
3465
|
const allRows = result.rows;
|
|
@@ -3376,7 +3488,7 @@ async function storeGlobalProcedure(input) {
|
|
|
3376
3488
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3377
3489
|
const client = getClient();
|
|
3378
3490
|
await client.execute({
|
|
3379
|
-
sql: `INSERT INTO
|
|
3491
|
+
sql: `INSERT INTO company_procedures (id, title, content, priority, domain, active, created_at, updated_at)
|
|
3380
3492
|
VALUES (?, ?, ?, ?, ?, 1, ?, ?)`,
|
|
3381
3493
|
args: [id, input.title, input.content, input.priority ?? "p0", input.domain ?? null, now, now]
|
|
3382
3494
|
});
|
|
@@ -3387,7 +3499,7 @@ async function deactivateGlobalProcedure(id) {
|
|
|
3387
3499
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3388
3500
|
const client = getClient();
|
|
3389
3501
|
const result = await client.execute({
|
|
3390
|
-
sql: "UPDATE
|
|
3502
|
+
sql: "UPDATE company_procedures SET active = 0, updated_at = ? WHERE id = ?",
|
|
3391
3503
|
args: [now, id]
|
|
3392
3504
|
});
|
|
3393
3505
|
await loadGlobalProcedures();
|
|
@@ -3406,6 +3518,164 @@ ${p.content}`).join("\n\n");
|
|
|
3406
3518
|
}
|
|
3407
3519
|
});
|
|
3408
3520
|
|
|
3521
|
+
// src/lib/memory-cards.ts
|
|
3522
|
+
var memory_cards_exports = {};
|
|
3523
|
+
__export(memory_cards_exports, {
|
|
3524
|
+
extractMemoryCards: () => extractMemoryCards,
|
|
3525
|
+
insertMemoryCardsForBatch: () => insertMemoryCardsForBatch,
|
|
3526
|
+
searchMemoryCards: () => searchMemoryCards
|
|
3527
|
+
});
|
|
3528
|
+
import { createHash as createHash2 } from "crypto";
|
|
3529
|
+
function stableId(memoryId, type, content) {
|
|
3530
|
+
return createHash2("sha256").update(`${memoryId}:${type}:${content}`).digest("hex").slice(0, 32);
|
|
3531
|
+
}
|
|
3532
|
+
function cleanText(text) {
|
|
3533
|
+
return text.replace(/```[\s\S]*?```/g, " ").replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
3534
|
+
}
|
|
3535
|
+
function splitSentences(text) {
|
|
3536
|
+
return cleanText(text).split(/(?<=[.!?])\s+|\n+/).map((s) => s.trim()).filter((s) => s.length >= 24 && s.length <= MAX_SENTENCE_CHARS);
|
|
3537
|
+
}
|
|
3538
|
+
function inferCardType(sentence, toolName) {
|
|
3539
|
+
const lower = sentence.toLowerCase();
|
|
3540
|
+
if (toolName === "store_decision" || /\b(decided|decision|adr|approved|rejected)\b/.test(lower)) return "decision";
|
|
3541
|
+
if (/\b(prefers|preference|likes|dislikes|wants|doesn't want|does not want)\b/.test(lower)) return "preference";
|
|
3542
|
+
if (/\b(changed|updated|replaced|now|no longer|instead|supersedes)\b/.test(lower)) return "belief_update";
|
|
3543
|
+
if (toolName && ["Read", "Write", "Edit", "Bash"].includes(toolName)) return "code";
|
|
3544
|
+
if (/\b(meeting|deadline|shipped|launched|completed|failed|blocked|assigned|created)\b/.test(lower)) return "event";
|
|
3545
|
+
return "fact";
|
|
3546
|
+
}
|
|
3547
|
+
function extractSubject(sentence, agentId) {
|
|
3548
|
+
const explicit = sentence.match(/\b([A-Z][a-zA-Z0-9_-]{2,}(?:\s+[A-Z][a-zA-Z0-9_-]{2,})?)\b/);
|
|
3549
|
+
return explicit?.[1] ?? agentId;
|
|
3550
|
+
}
|
|
3551
|
+
function predicateFor(type) {
|
|
3552
|
+
switch (type) {
|
|
3553
|
+
case "preference":
|
|
3554
|
+
return "prefers";
|
|
3555
|
+
case "belief_update":
|
|
3556
|
+
return "updated";
|
|
3557
|
+
case "decision":
|
|
3558
|
+
return "decided";
|
|
3559
|
+
case "event":
|
|
3560
|
+
return "happened";
|
|
3561
|
+
case "code":
|
|
3562
|
+
return "implemented";
|
|
3563
|
+
default:
|
|
3564
|
+
return "states";
|
|
3565
|
+
}
|
|
3566
|
+
}
|
|
3567
|
+
function extractMemoryCards(row) {
|
|
3568
|
+
const sentences = splitSentences(row.raw_text);
|
|
3569
|
+
const cards = [];
|
|
3570
|
+
for (const sentence of sentences) {
|
|
3571
|
+
const type = inferCardType(sentence, row.tool_name);
|
|
3572
|
+
const subject = extractSubject(sentence, row.agent_id);
|
|
3573
|
+
const content = sentence.length > MAX_SENTENCE_CHARS ? `${sentence.slice(0, MAX_SENTENCE_CHARS - 1)}\u2026` : sentence;
|
|
3574
|
+
cards.push({
|
|
3575
|
+
id: stableId(row.id, type, content),
|
|
3576
|
+
memory_id: row.id,
|
|
3577
|
+
agent_id: row.agent_id,
|
|
3578
|
+
session_id: row.session_id,
|
|
3579
|
+
project_name: row.project_name ?? null,
|
|
3580
|
+
timestamp: row.timestamp,
|
|
3581
|
+
card_type: type,
|
|
3582
|
+
subject,
|
|
3583
|
+
predicate: predicateFor(type),
|
|
3584
|
+
object: content,
|
|
3585
|
+
content,
|
|
3586
|
+
source_ref: row.id,
|
|
3587
|
+
confidence: type === "fact" ? 0.55 : 0.65
|
|
3588
|
+
});
|
|
3589
|
+
if (cards.length >= MAX_CARDS_PER_MEMORY) break;
|
|
3590
|
+
}
|
|
3591
|
+
return cards;
|
|
3592
|
+
}
|
|
3593
|
+
async function insertMemoryCardsForBatch(rows) {
|
|
3594
|
+
const cards = rows.flatMap(extractMemoryCards);
|
|
3595
|
+
if (cards.length === 0) return 0;
|
|
3596
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3597
|
+
const client = getClient();
|
|
3598
|
+
const stmts = cards.map((card) => ({
|
|
3599
|
+
sql: `INSERT OR IGNORE INTO memory_cards
|
|
3600
|
+
(id, memory_id, agent_id, session_id, project_name, timestamp, card_type,
|
|
3601
|
+
subject, predicate, object, content, source_ref, confidence, active, created_at)
|
|
3602
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?)`,
|
|
3603
|
+
args: [
|
|
3604
|
+
card.id,
|
|
3605
|
+
card.memory_id,
|
|
3606
|
+
card.agent_id,
|
|
3607
|
+
card.session_id,
|
|
3608
|
+
card.project_name,
|
|
3609
|
+
card.timestamp,
|
|
3610
|
+
card.card_type,
|
|
3611
|
+
card.subject,
|
|
3612
|
+
card.predicate,
|
|
3613
|
+
card.object,
|
|
3614
|
+
card.content,
|
|
3615
|
+
card.source_ref,
|
|
3616
|
+
card.confidence,
|
|
3617
|
+
now
|
|
3618
|
+
]
|
|
3619
|
+
}));
|
|
3620
|
+
await client.batch(stmts, "write");
|
|
3621
|
+
return cards.length;
|
|
3622
|
+
}
|
|
3623
|
+
function buildMatchExpr(queryText) {
|
|
3624
|
+
const terms = queryText.toLowerCase().split(/\s+/).filter((t) => t.length >= 3).map((t) => t.replace(/[^a-z0-9_]/g, "")).filter((t) => t.length >= 3).slice(0, 12);
|
|
3625
|
+
if (terms.length === 0) return null;
|
|
3626
|
+
return terms.map((t) => `${t}*`).join(terms.length >= 3 ? " AND " : " OR ");
|
|
3627
|
+
}
|
|
3628
|
+
async function searchMemoryCards(queryText, agentId, options) {
|
|
3629
|
+
const limit = options?.limit ?? 10;
|
|
3630
|
+
const matchExpr = buildMatchExpr(queryText);
|
|
3631
|
+
if (!matchExpr) return [];
|
|
3632
|
+
let sql = `SELECT c.id, c.memory_id, c.agent_id, c.session_id, c.project_name,
|
|
3633
|
+
c.timestamp, c.card_type, c.content, c.source_ref, c.confidence
|
|
3634
|
+
FROM memory_cards c
|
|
3635
|
+
JOIN memory_cards_fts fts ON c.rowid = fts.rowid
|
|
3636
|
+
WHERE memory_cards_fts MATCH ?
|
|
3637
|
+
AND c.agent_id = ?
|
|
3638
|
+
AND COALESCE(c.active, 1) = 1`;
|
|
3639
|
+
const args = [matchExpr, agentId];
|
|
3640
|
+
if (options?.projectName) {
|
|
3641
|
+
sql += ` AND c.project_name = ?`;
|
|
3642
|
+
args.push(options.projectName);
|
|
3643
|
+
}
|
|
3644
|
+
if (options?.since) {
|
|
3645
|
+
sql += ` AND c.timestamp >= ?`;
|
|
3646
|
+
args.push(options.since);
|
|
3647
|
+
}
|
|
3648
|
+
sql += ` ORDER BY rank LIMIT ?`;
|
|
3649
|
+
args.push(limit);
|
|
3650
|
+
const result = await getClient().execute({ sql, args });
|
|
3651
|
+
return result.rows.map((row) => ({
|
|
3652
|
+
id: `card:${String(row.id)}`,
|
|
3653
|
+
agent_id: String(row.agent_id),
|
|
3654
|
+
agent_role: "memory_card",
|
|
3655
|
+
session_id: String(row.session_id),
|
|
3656
|
+
timestamp: String(row.timestamp),
|
|
3657
|
+
tool_name: `memory_card:${String(row.card_type)}`,
|
|
3658
|
+
project_name: row.project_name == null ? "" : String(row.project_name),
|
|
3659
|
+
has_error: false,
|
|
3660
|
+
raw_text: `[${String(row.card_type)}] ${String(row.content)}
|
|
3661
|
+
Source memory: ${String(row.source_ref ?? row.memory_id)}`,
|
|
3662
|
+
vector: [],
|
|
3663
|
+
importance: 6,
|
|
3664
|
+
status: "active",
|
|
3665
|
+
confidence: Number(row.confidence ?? 0.6),
|
|
3666
|
+
last_accessed: String(row.timestamp)
|
|
3667
|
+
}));
|
|
3668
|
+
}
|
|
3669
|
+
var MAX_CARDS_PER_MEMORY, MAX_SENTENCE_CHARS;
|
|
3670
|
+
var init_memory_cards = __esm({
|
|
3671
|
+
"src/lib/memory-cards.ts"() {
|
|
3672
|
+
"use strict";
|
|
3673
|
+
init_database();
|
|
3674
|
+
MAX_CARDS_PER_MEMORY = 6;
|
|
3675
|
+
MAX_SENTENCE_CHARS = 360;
|
|
3676
|
+
}
|
|
3677
|
+
});
|
|
3678
|
+
|
|
3409
3679
|
// src/bin/exe-assign.ts
|
|
3410
3680
|
init_employees();
|
|
3411
3681
|
|
|
@@ -4342,6 +4612,11 @@ async function flushBatch() {
|
|
|
4342
4612
|
const globalClient = getClient();
|
|
4343
4613
|
const globalStmts = batch.map(buildStmt);
|
|
4344
4614
|
await globalClient.batch(globalStmts, "write");
|
|
4615
|
+
try {
|
|
4616
|
+
const { insertMemoryCardsForBatch: insertMemoryCardsForBatch2 } = await Promise.resolve().then(() => (init_memory_cards(), memory_cards_exports));
|
|
4617
|
+
await insertMemoryCardsForBatch2(batch);
|
|
4618
|
+
} catch {
|
|
4619
|
+
}
|
|
4345
4620
|
schedulePostWriteMemoryHygiene(batch.map((row) => row.id));
|
|
4346
4621
|
_pendingRecords.splice(0, batch.length);
|
|
4347
4622
|
try {
|
package/dist/bin/exe-boot.js
CHANGED
|
@@ -258,8 +258,8 @@ var init_config = __esm({
|
|
|
258
258
|
rerankerAutoTrigger: {
|
|
259
259
|
enabled: true,
|
|
260
260
|
broadQueryMinCardinality: 5e4,
|
|
261
|
-
fetchTopK:
|
|
262
|
-
returnTopK:
|
|
261
|
+
fetchTopK: 200,
|
|
262
|
+
returnTopK: 20
|
|
263
263
|
}
|
|
264
264
|
},
|
|
265
265
|
graphRagEnabled: true,
|
|
@@ -2581,7 +2581,7 @@ async function ensureSchema() {
|
|
|
2581
2581
|
ON session_kills(agent_id);
|
|
2582
2582
|
`);
|
|
2583
2583
|
await client.execute(`
|
|
2584
|
-
CREATE TABLE IF NOT EXISTS
|
|
2584
|
+
CREATE TABLE IF NOT EXISTS company_procedures (
|
|
2585
2585
|
id TEXT PRIMARY KEY,
|
|
2586
2586
|
title TEXT NOT NULL,
|
|
2587
2587
|
content TEXT NOT NULL,
|
|
@@ -2592,6 +2592,73 @@ async function ensureSchema() {
|
|
|
2592
2592
|
updated_at TEXT NOT NULL
|
|
2593
2593
|
)
|
|
2594
2594
|
`);
|
|
2595
|
+
const legacyProcedureObject = await client.execute({
|
|
2596
|
+
sql: "SELECT type FROM sqlite_master WHERE name = 'global_procedures'",
|
|
2597
|
+
args: []
|
|
2598
|
+
});
|
|
2599
|
+
const legacyProcedureType = legacyProcedureObject.rows[0]?.type == null ? null : String(legacyProcedureObject.rows[0].type);
|
|
2600
|
+
if (legacyProcedureType === "table") {
|
|
2601
|
+
await client.execute(`
|
|
2602
|
+
INSERT OR IGNORE INTO company_procedures
|
|
2603
|
+
(id, title, content, priority, domain, active, created_at, updated_at)
|
|
2604
|
+
SELECT id, title, content, priority, domain, active, created_at, updated_at
|
|
2605
|
+
FROM global_procedures
|
|
2606
|
+
`);
|
|
2607
|
+
await client.executeMultiple(`
|
|
2608
|
+
CREATE TRIGGER IF NOT EXISTS global_procedures_mirror_insert
|
|
2609
|
+
AFTER INSERT ON global_procedures
|
|
2610
|
+
BEGIN
|
|
2611
|
+
INSERT OR IGNORE INTO company_procedures
|
|
2612
|
+
(id, title, content, priority, domain, active, created_at, updated_at)
|
|
2613
|
+
VALUES
|
|
2614
|
+
(NEW.id, NEW.title, NEW.content, NEW.priority, NEW.domain, NEW.active, NEW.created_at, NEW.updated_at);
|
|
2615
|
+
END;
|
|
2616
|
+
|
|
2617
|
+
CREATE TRIGGER IF NOT EXISTS global_procedures_mirror_update
|
|
2618
|
+
AFTER UPDATE ON global_procedures
|
|
2619
|
+
BEGIN
|
|
2620
|
+
UPDATE company_procedures
|
|
2621
|
+
SET title = NEW.title,
|
|
2622
|
+
content = NEW.content,
|
|
2623
|
+
priority = NEW.priority,
|
|
2624
|
+
domain = NEW.domain,
|
|
2625
|
+
active = NEW.active,
|
|
2626
|
+
created_at = NEW.created_at,
|
|
2627
|
+
updated_at = NEW.updated_at
|
|
2628
|
+
WHERE id = OLD.id;
|
|
2629
|
+
END;
|
|
2630
|
+
`);
|
|
2631
|
+
} else {
|
|
2632
|
+
await client.execute(`
|
|
2633
|
+
CREATE VIEW IF NOT EXISTS global_procedures AS
|
|
2634
|
+
SELECT id, title, content, priority, domain, active, created_at, updated_at
|
|
2635
|
+
FROM company_procedures
|
|
2636
|
+
`);
|
|
2637
|
+
await client.executeMultiple(`
|
|
2638
|
+
CREATE TRIGGER IF NOT EXISTS global_procedures_insert
|
|
2639
|
+
INSTEAD OF INSERT ON global_procedures
|
|
2640
|
+
BEGIN
|
|
2641
|
+
INSERT INTO company_procedures
|
|
2642
|
+
(id, title, content, priority, domain, active, created_at, updated_at)
|
|
2643
|
+
VALUES
|
|
2644
|
+
(NEW.id, NEW.title, NEW.content, NEW.priority, NEW.domain, NEW.active, NEW.created_at, NEW.updated_at);
|
|
2645
|
+
END;
|
|
2646
|
+
|
|
2647
|
+
CREATE TRIGGER IF NOT EXISTS global_procedures_update
|
|
2648
|
+
INSTEAD OF UPDATE ON global_procedures
|
|
2649
|
+
BEGIN
|
|
2650
|
+
UPDATE company_procedures
|
|
2651
|
+
SET title = NEW.title,
|
|
2652
|
+
content = NEW.content,
|
|
2653
|
+
priority = NEW.priority,
|
|
2654
|
+
domain = NEW.domain,
|
|
2655
|
+
active = NEW.active,
|
|
2656
|
+
created_at = NEW.created_at,
|
|
2657
|
+
updated_at = NEW.updated_at
|
|
2658
|
+
WHERE id = OLD.id;
|
|
2659
|
+
END;
|
|
2660
|
+
`);
|
|
2661
|
+
}
|
|
2595
2662
|
await client.executeMultiple(`
|
|
2596
2663
|
CREATE TABLE IF NOT EXISTS conversations (
|
|
2597
2664
|
id TEXT PRIMARY KEY,
|
|
@@ -2731,6 +2798,51 @@ async function ensureSchema() {
|
|
|
2731
2798
|
VALUES (new.rowid, new.content_text, new.sender_name, new.agent_response);
|
|
2732
2799
|
END;
|
|
2733
2800
|
`);
|
|
2801
|
+
await client.executeMultiple(`
|
|
2802
|
+
CREATE TABLE IF NOT EXISTS memory_cards (
|
|
2803
|
+
id TEXT PRIMARY KEY,
|
|
2804
|
+
memory_id TEXT NOT NULL,
|
|
2805
|
+
agent_id TEXT NOT NULL,
|
|
2806
|
+
session_id TEXT NOT NULL,
|
|
2807
|
+
project_name TEXT,
|
|
2808
|
+
timestamp TEXT NOT NULL,
|
|
2809
|
+
card_type TEXT NOT NULL,
|
|
2810
|
+
subject TEXT,
|
|
2811
|
+
predicate TEXT,
|
|
2812
|
+
object TEXT,
|
|
2813
|
+
content TEXT NOT NULL,
|
|
2814
|
+
source_ref TEXT,
|
|
2815
|
+
confidence REAL DEFAULT 0.6,
|
|
2816
|
+
active INTEGER DEFAULT 1,
|
|
2817
|
+
created_at TEXT NOT NULL
|
|
2818
|
+
);
|
|
2819
|
+
|
|
2820
|
+
CREATE INDEX IF NOT EXISTS idx_memory_cards_agent
|
|
2821
|
+
ON memory_cards(agent_id, active, timestamp);
|
|
2822
|
+
|
|
2823
|
+
CREATE INDEX IF NOT EXISTS idx_memory_cards_memory
|
|
2824
|
+
ON memory_cards(memory_id);
|
|
2825
|
+
|
|
2826
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS memory_cards_fts
|
|
2827
|
+
USING fts5(content, subject, predicate, object, content='memory_cards', content_rowid='rowid');
|
|
2828
|
+
|
|
2829
|
+
CREATE TRIGGER IF NOT EXISTS memory_cards_fts_ai AFTER INSERT ON memory_cards BEGIN
|
|
2830
|
+
INSERT INTO memory_cards_fts(rowid, content, subject, predicate, object)
|
|
2831
|
+
VALUES (new.rowid, new.content, new.subject, new.predicate, new.object);
|
|
2832
|
+
END;
|
|
2833
|
+
|
|
2834
|
+
CREATE TRIGGER IF NOT EXISTS memory_cards_fts_ad AFTER DELETE ON memory_cards BEGIN
|
|
2835
|
+
INSERT INTO memory_cards_fts(memory_cards_fts, rowid, content, subject, predicate, object)
|
|
2836
|
+
VALUES('delete', old.rowid, old.content, old.subject, old.predicate, old.object);
|
|
2837
|
+
END;
|
|
2838
|
+
|
|
2839
|
+
CREATE TRIGGER IF NOT EXISTS memory_cards_fts_au AFTER UPDATE ON memory_cards BEGIN
|
|
2840
|
+
INSERT INTO memory_cards_fts(memory_cards_fts, rowid, content, subject, predicate, object)
|
|
2841
|
+
VALUES('delete', old.rowid, old.content, old.subject, old.predicate, old.object);
|
|
2842
|
+
INSERT INTO memory_cards_fts(rowid, content, subject, predicate, object)
|
|
2843
|
+
VALUES (new.rowid, new.content, new.subject, new.predicate, new.object);
|
|
2844
|
+
END;
|
|
2845
|
+
`);
|
|
2734
2846
|
try {
|
|
2735
2847
|
await client.execute({
|
|
2736
2848
|
sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
|
|
@@ -3053,7 +3165,7 @@ var init_platform_procedures = __esm({
|
|
|
3053
3165
|
title: "MCP tools \u2014 advanced (triggers, skills, orchestration)",
|
|
3054
3166
|
domain: "tool-use",
|
|
3055
3167
|
priority: "p1",
|
|
3056
|
-
content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done.
|
|
3168
|
+
content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. company_procedure: manage customer-owned company procedures (Layer 0; actions: store, list, deactivate). Legacy aliases: global_procedure, store_global_procedure, list_global_procedures, deactivate_global_procedure."
|
|
3057
3169
|
}
|
|
3058
3170
|
];
|
|
3059
3171
|
PLATFORM_PROCEDURE_TITLES = new Set(
|
|
@@ -3074,7 +3186,7 @@ import { randomUUID as randomUUID2 } from "crypto";
|
|
|
3074
3186
|
async function loadGlobalProcedures() {
|
|
3075
3187
|
const client = getClient();
|
|
3076
3188
|
const result = await client.execute({
|
|
3077
|
-
sql: "SELECT * FROM
|
|
3189
|
+
sql: "SELECT * FROM company_procedures WHERE active = 1 ORDER BY priority ASC, created_at ASC",
|
|
3078
3190
|
args: []
|
|
3079
3191
|
});
|
|
3080
3192
|
const allRows = result.rows;
|
|
@@ -3103,7 +3215,7 @@ async function storeGlobalProcedure(input) {
|
|
|
3103
3215
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3104
3216
|
const client = getClient();
|
|
3105
3217
|
await client.execute({
|
|
3106
|
-
sql: `INSERT INTO
|
|
3218
|
+
sql: `INSERT INTO company_procedures (id, title, content, priority, domain, active, created_at, updated_at)
|
|
3107
3219
|
VALUES (?, ?, ?, ?, ?, 1, ?, ?)`,
|
|
3108
3220
|
args: [id, input.title, input.content, input.priority ?? "p0", input.domain ?? null, now, now]
|
|
3109
3221
|
});
|
|
@@ -3114,7 +3226,7 @@ async function deactivateGlobalProcedure(id) {
|
|
|
3114
3226
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3115
3227
|
const client = getClient();
|
|
3116
3228
|
const result = await client.execute({
|
|
3117
|
-
sql: "UPDATE
|
|
3229
|
+
sql: "UPDATE company_procedures SET active = 0, updated_at = ? WHERE id = ?",
|
|
3118
3230
|
args: [now, id]
|
|
3119
3231
|
});
|
|
3120
3232
|
await loadGlobalProcedures();
|
|
@@ -9332,12 +9444,12 @@ async function cloudSync(config) {
|
|
|
9332
9444
|
try {
|
|
9333
9445
|
await cloudPushGlobalProcedures(config);
|
|
9334
9446
|
} catch (err) {
|
|
9335
|
-
logError(`[cloud-sync]
|
|
9447
|
+
logError(`[cloud-sync] Company procedures push: ${err instanceof Error ? err.message : String(err)}`);
|
|
9336
9448
|
}
|
|
9337
9449
|
try {
|
|
9338
9450
|
await cloudPullGlobalProcedures(config);
|
|
9339
9451
|
} catch (err) {
|
|
9340
|
-
logError(`[cloud-sync]
|
|
9452
|
+
logError(`[cloud-sync] Company procedures pull: ${err instanceof Error ? err.message : String(err)}`);
|
|
9341
9453
|
}
|
|
9342
9454
|
const countRows = async (sql) => {
|
|
9343
9455
|
try {
|
|
@@ -9746,12 +9858,12 @@ async function cloudPullBlob(route, config) {
|
|
|
9746
9858
|
}
|
|
9747
9859
|
async function cloudPushGlobalProcedures(config) {
|
|
9748
9860
|
const client = getClient();
|
|
9749
|
-
const result = await client.execute("SELECT * FROM
|
|
9861
|
+
const result = await client.execute("SELECT * FROM company_procedures LIMIT 1000");
|
|
9750
9862
|
const rows = result.rows;
|
|
9751
9863
|
const { ok } = await cloudPushBlob(
|
|
9752
9864
|
"/sync/push-global-procedures",
|
|
9753
9865
|
rows,
|
|
9754
|
-
"
|
|
9866
|
+
"last_company_procedures_push_version",
|
|
9755
9867
|
config
|
|
9756
9868
|
);
|
|
9757
9869
|
return ok;
|
|
@@ -9764,7 +9876,7 @@ async function cloudPullGlobalProcedures(config) {
|
|
|
9764
9876
|
if (!remoteProcs || remoteProcs.length === 0) return { pulled: 0 };
|
|
9765
9877
|
const client = getClient();
|
|
9766
9878
|
const stmts = remoteProcs.map((p) => ({
|
|
9767
|
-
sql: `INSERT INTO
|
|
9879
|
+
sql: `INSERT INTO company_procedures
|
|
9768
9880
|
(id, title, content, priority, domain, active, created_at, updated_at)
|
|
9769
9881
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
9770
9882
|
ON CONFLICT(id) DO UPDATE SET
|
|
@@ -9774,7 +9886,7 @@ async function cloudPullGlobalProcedures(config) {
|
|
|
9774
9886
|
domain = excluded.domain,
|
|
9775
9887
|
active = excluded.active,
|
|
9776
9888
|
updated_at = excluded.updated_at
|
|
9777
|
-
WHERE excluded.updated_at >
|
|
9889
|
+
WHERE excluded.updated_at > company_procedures.updated_at`,
|
|
9778
9890
|
args: [
|
|
9779
9891
|
sqlSafe(p.id),
|
|
9780
9892
|
sqlSafe(p.title),
|