@askexenow/exe-os 0.9.294 → 0.9.296
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/cloudflared/config.yml.example +14 -9
- package/deploy/compose/docker-compose.yml +86 -8
- package/deploy/compose/sso-edge/default.conf.template +87 -0
- package/deploy/compose/sso-edge/entrypoint.sh +23 -0
- package/deploy/compose/sso-edge/sso-redirect.conf +63 -0
- package/deploy/stack-manifests/v0.9.json +2 -2
- package/dist/active-agent-AFX2FODG.js +28 -0
- package/dist/active-agent-E2IJA7YX.js +27 -0
- package/dist/agentic-ontology-A2YUZK5O.js +25 -0
- package/dist/assets/com.askexe.exed.plist +4 -1
- package/dist/backfill-metadata-OC7EOD5U.js +600 -0
- package/dist/behaviors-H5ZOVHDH.js +46 -0
- package/dist/bin/agentic-ontology-backfill.js +5 -5
- package/dist/bin/agentic-reflection-backfill.js +6 -6
- package/dist/bin/agentic-semantic-label.js +5 -5
- package/dist/bin/backfill-conversations.js +6 -6
- package/dist/bin/backfill-responses.js +6 -6
- package/dist/bin/backfill-vectors.js +8 -8
- package/dist/bin/bulk-sync-postgres.js +7 -7
- package/dist/bin/cc-doctor.js +4 -4
- package/dist/bin/cleanup-stale-review-tasks.js +11 -11
- package/dist/bin/cli.js +16 -16
- package/dist/bin/deferred-daemon-restart.js +1 -1
- package/dist/bin/exe-agent-config.js +2 -2
- package/dist/bin/exe-agent.js +4 -4
- package/dist/bin/exe-assign.js +8 -8
- package/dist/bin/exe-boot.js +21 -18
- package/dist/bin/exe-call.js +4 -4
- package/dist/bin/exe-cloud.js +7 -7
- package/dist/bin/exe-dispatch.js +11 -11
- package/dist/bin/exe-doctor.js +3 -2
- package/dist/bin/exe-export-behaviors.js +7 -7
- package/dist/bin/exe-forget.js +6 -6
- package/dist/bin/exe-gateway.js +7 -7
- package/dist/bin/exe-healthcheck.js +6 -4
- package/dist/bin/exe-heartbeat.js +11 -11
- package/dist/bin/exe-kill.js +14 -14
- package/dist/bin/exe-launch-agent.js +18 -18
- package/dist/bin/exe-new-employee.js +6 -6
- package/dist/bin/exe-pending-messages.js +12 -12
- package/dist/bin/exe-pending-notifications.js +11 -11
- package/dist/bin/exe-pending-reviews.js +11 -11
- package/dist/bin/exe-rename.js +4 -4
- package/dist/bin/exe-review.js +13 -13
- package/dist/bin/exe-search.js +5 -5
- package/dist/bin/exe-session-cleanup.js +16 -16
- package/dist/bin/exe-settings.js +39 -9
- package/dist/bin/exe-start-codex.js +11 -11
- package/dist/bin/exe-start-opencode.js +8 -8
- package/dist/bin/exe-status.js +12 -12
- package/dist/bin/exe-team.js +3 -3
- package/dist/bin/git-sweep.js +12 -12
- package/dist/bin/graph-backfill.js +4 -4
- package/dist/bin/graph-export.js +5 -5
- package/dist/bin/import-history.js +7 -7
- package/dist/bin/install-launchd.js +13 -6
- package/dist/bin/install.js +26 -14
- package/dist/bin/intercom-check.js +4 -4
- package/dist/bin/mcp-sessions.js +2 -2
- package/dist/bin/orchestration-metrics.js +4 -4
- package/dist/bin/postgres-agentic-reflection-backfill.js +2 -2
- package/dist/bin/postgres-agentic-semantic-backfill.js +1 -1
- package/dist/bin/scan-tasks.js +11 -11
- package/dist/bin/setup.js +1 -1
- package/dist/bin/shard-migrate.js +4 -4
- package/dist/bin/stack-update.js +2 -2
- package/dist/bin/vps-health-gate.js +1 -1
- package/dist/capability-cards-4USI7CUW.js +89 -0
- package/dist/capacity-monitor-WLCBTEYR.js +51 -0
- package/dist/catchup-brief-ZR3NX6LZ.js +175 -0
- package/dist/chunk-22TVSRQQ.js +226 -0
- package/dist/chunk-2E43UXRH.js +395 -0
- package/dist/chunk-2PIGT6UJ.js +460 -0
- package/dist/chunk-3XTMW2MZ.js +535 -0
- package/dist/chunk-465PQFTH.js +262 -0
- package/dist/chunk-5CCXU2AW.js +129 -0
- package/dist/chunk-5D6MPWR7.js +1094 -0
- package/dist/chunk-5Q4MR6SL.js +123 -0
- package/dist/chunk-6327RBWR.js +345 -0
- package/dist/chunk-6MZZREZY.js +199 -0
- package/dist/chunk-7DI2Q4O5.js +1186 -0
- package/dist/chunk-7PW5VNIY.js +122 -0
- package/dist/chunk-7T7Y56HW.js +43 -0
- package/dist/chunk-7UHCWCLT.js +128 -0
- package/dist/chunk-A2ZUMF6L.js +1350 -0
- package/dist/chunk-AKV44JEH.js +185 -0
- package/dist/chunk-ANHWGX5N.js +735 -0
- package/dist/chunk-BQ3P4TKD.js +97 -0
- package/dist/chunk-BUZMT3KZ.js +604 -0
- package/dist/chunk-C2SBESBO.js +210 -0
- package/dist/chunk-CLSXZUZW.js +51 -0
- package/dist/chunk-CONHLVAR.js +1079 -0
- package/dist/chunk-D3WTZPFX.js +456 -0
- package/dist/chunk-DE6SOIYL.js +197 -0
- package/dist/chunk-EIVNMA3Q.js +284 -0
- package/dist/chunk-EJIF4FNT.js +12 -0
- package/dist/chunk-FDFOW564.js +171 -0
- package/dist/chunk-GZUBJ5EC.js +127 -0
- package/dist/chunk-HGZITN22.js +105 -0
- package/dist/chunk-HSRKDU6X.js +362 -0
- package/dist/chunk-IIEN2PHV.js +85 -0
- package/dist/chunk-JQ56VLMM.js +567 -0
- package/dist/chunk-JVHHXRFY.js +280 -0
- package/dist/chunk-JXCXGZ3S.js +55 -0
- package/dist/chunk-K5ZO532Q.js +4388 -0
- package/dist/chunk-K6CAAMXF.js +97 -0
- package/dist/chunk-KA26YTNU.js +81 -0
- package/dist/chunk-KMUW5C3R.js +381 -0
- package/dist/chunk-KOO3J5PV.js +20 -0
- package/dist/chunk-LSV7OFIH.js +290 -0
- package/dist/chunk-LSVFDVNY.js +1158 -0
- package/dist/chunk-LXDQTW32.js +230 -0
- package/dist/chunk-MEP7OUVZ.js +181 -0
- package/dist/chunk-MN2B2LKS.js +240 -0
- package/dist/chunk-N2EAYPYQ.js +1352 -0
- package/dist/chunk-N7I2A667.js +70 -0
- package/dist/chunk-NLZHVIOP.js +630 -0
- package/dist/chunk-NUH5TRZL.js +227 -0
- package/dist/chunk-OAHEIH3G.js +167 -0
- package/dist/chunk-OBHRQGCK.js +58 -0
- package/dist/chunk-ODFA7B2V.js +54 -0
- package/dist/chunk-OSNUP45F.js +731 -0
- package/dist/chunk-OTPRHBTO.js +33 -0
- package/dist/chunk-P6MUA4QU.js +157 -0
- package/dist/chunk-PGIOFKSK.js +2093 -0
- package/dist/chunk-PSE7VHWK.js +50 -0
- package/dist/chunk-QIFUVZFW.js +331 -0
- package/dist/chunk-RDPXKTVK.js +221 -0
- package/dist/chunk-RKYTYJGB.js +76 -0
- package/dist/chunk-RXLR6EFM.js +348 -0
- package/dist/chunk-SDB67PQJ.js +159 -0
- package/dist/chunk-SF2T7MP3.js +402 -0
- package/dist/chunk-SLU3FRFQ.js +2133 -0
- package/dist/chunk-SNDZJ5IV.js +214 -0
- package/dist/chunk-STEEAABW.js +448 -0
- package/dist/chunk-TUTWNHIQ.js +244 -0
- package/dist/chunk-UDP35QBR.js +30 -0
- package/dist/chunk-UKFHNJBI.js +85 -0
- package/dist/chunk-VC2DTK2X.js +382 -0
- package/dist/chunk-VRRAE5JX.js +836 -0
- package/dist/chunk-VVJTBQPR.js +38 -0
- package/dist/chunk-W3EQ362K.js +581 -0
- package/dist/chunk-WHIXIFHC.js +2242 -0
- package/dist/chunk-WRNGJJNR.js +377 -0
- package/dist/chunk-WUKHLCBE.js +3313 -0
- package/dist/chunk-WVPLHGDG.js +150 -0
- package/dist/chunk-XJZBSTL5.js +204 -0
- package/dist/chunk-Y3PMNUM5.js +304 -0
- package/dist/chunk-YHVS4QOV.js +14597 -0
- package/dist/chunk-YJ2OYAOC.js +668 -0
- package/dist/chunk-YYAD2GXX.js +128 -0
- package/dist/chunk-ZQML7EWE.js +333 -0
- package/dist/co-activation-XJLH46OX.js +74 -0
- package/dist/co-occurrence-GNN2X526.js +95 -0
- package/dist/code-context-index-OCPRLFG5.js +30 -0
- package/dist/core-memory-J4W2IYOF.js +110 -0
- package/dist/crdt-sync-QCBTSHIH.js +33 -0
- package/dist/crm-webhook-EM442VUW.js +10 -0
- package/dist/cto-delegation-gate-MLJMVHBK.js +280 -0
- package/dist/daemon-orchestration-2VNLZVTW.js +139 -0
- package/dist/db-backup-VUGFTPJ4.js +43 -0
- package/dist/doc-graph-extractor-PNRSFPSS.js +133 -0
- package/dist/dreaming-SK5VEQRF.js +34 -0
- package/dist/entity-boost-TQWWJUC2.js +375 -0
- package/dist/exe-drift-N34UPO7S.js +70 -0
- package/dist/exe-export-KACBKGVV.js +77 -0
- package/dist/exe-import-GXGDWACG.js +80 -0
- package/dist/exe-key-XPDOZBWW.js +673 -0
- package/dist/exe-snapshot-32GQKGQ5.js +338 -0
- package/dist/fast-db-init-F3TDD5VV.js +7 -0
- package/dist/gateway/index.js +8 -8
- package/dist/git-staleness-J45WNYRF.js +112 -0
- package/dist/git-task-sweep-BTGVQPFB.js +42 -0
- package/dist/global-procedures-6JCQWU4D.js +22 -0
- package/dist/graph-auto-extract-3ZQNXTPC.js +183 -0
- package/dist/hooks/bug-report-worker.js +13 -13
- package/dist/hooks/codex-stop-task-finalizer.js +13 -13
- package/dist/hooks/commit-complete.js +13 -13
- package/dist/hooks/error-recall.js +6 -6
- package/dist/hooks/exe-heartbeat-hook.js +3 -3
- package/dist/hooks/ingest-worker.js +3 -3
- package/dist/hooks/ingest.js +6 -6
- package/dist/hooks/instructions-loaded.js +4 -4
- package/dist/hooks/manifest.json +20 -20
- package/dist/hooks/notification.js +4 -4
- package/dist/hooks/post-compact.js +12 -12
- package/dist/hooks/post-tool-combined.js +6 -6
- package/dist/hooks/pre-compact.js +16 -16
- package/dist/hooks/pre-tool-use.js +16 -16
- package/dist/hooks/prompt-submit.js +24 -24
- package/dist/hooks/session-end.js +21 -21
- package/dist/hooks/session-start.js +12 -12
- package/dist/hooks/stop.js +19 -19
- package/dist/hooks/subagent-stop.js +12 -12
- package/dist/hooks/summary-worker.js +19 -19
- package/dist/index.js +19 -19
- package/dist/installer-5VPFY7SB.js +298 -0
- package/dist/installer-OENFPMA2.js +344 -0
- package/dist/installer-OIX4QOG5.js +40 -0
- package/dist/lib/cloud-sync.js +7 -7
- package/dist/lib/consolidation.js +6 -5
- package/dist/lib/database.js +2 -2
- package/dist/lib/db-daemon-client.js +2 -2
- package/dist/lib/db.js +2 -2
- package/dist/lib/embed-worker.js +1 -0
- package/dist/lib/embedder.js +7 -3
- package/dist/lib/employee-templates.js +4 -4
- package/dist/lib/employees.js +2 -2
- package/dist/lib/exe-daemon-client.js +2 -2
- package/dist/lib/exe-daemon.js +160 -79
- package/dist/lib/hybrid-search.js +5 -5
- package/dist/lib/identity.js +2 -2
- package/dist/lib/messaging.js +11 -11
- package/dist/lib/reminders.js +3 -3
- package/dist/lib/schedules.js +5 -5
- package/dist/lib/session-registry.js +4 -4
- package/dist/lib/skill-learning.js +6 -6
- package/dist/lib/store.js +4 -4
- package/dist/lib/task-router.js +3 -3
- package/dist/lib/tasks.js +12 -12
- package/dist/lib/tmux-routing.js +12 -10
- package/dist/lib/tmux-transport.js +1 -1
- package/dist/lib/token-spend.js +3 -3
- package/dist/lib/transport.js +2 -2
- package/dist/mcp/register-tools.js +62 -61
- package/dist/mcp/server.js +63 -62
- package/dist/mcp/tools/complete-reminder.js +4 -4
- package/dist/mcp/tools/create-reminder.js +4 -4
- package/dist/mcp/tools/create-task.js +14 -14
- package/dist/mcp/tools/deactivate-behavior.js +7 -7
- package/dist/mcp/tools/list-reminders.js +4 -4
- package/dist/mcp/tools/list-tasks.js +14 -14
- package/dist/mcp/tools/send-message.js +13 -13
- package/dist/mcp/tools/update-task.js +13 -13
- package/dist/mcp-http-config-PQTOLCTP.js +29 -0
- package/dist/memory-cards-4RVDZIY2.js +180 -0
- package/dist/memory-graph-extractor-L6YC7G4M.js +22 -0
- package/dist/memory-poisoning-defense-4YVJYH4G.js +224 -0
- package/dist/memory-queue-client-MVAUOZNJ.js +16 -0
- package/dist/memory-reflection-SHHDQNOH.js +244 -0
- package/dist/message-queue-client-DCKZT6X2.js +92 -0
- package/dist/notifications-JFR3G42W.js +47 -0
- package/dist/orchestration-events-MGCGPTDN.js +27 -0
- package/dist/orchestrator-DAFL2YZB.js +35 -0
- package/dist/pipeline-router-WWSZVPCH.js +15 -0
- package/dist/plan-limits-C7XCSDZC.js +28 -0
- package/dist/project-boot-N3NTBVLE.js +299 -0
- package/dist/projection-worker-MTPAPCWX.js +1084 -0
- package/dist/prospective-memory-BTIVUJSB.js +232 -0
- package/dist/reranker-UA6WVESJ.js +19 -0
- package/dist/retrieval-health-7XNZJEBF.js +12 -0
- package/dist/review-polling-4ALGMXC3.js +126 -0
- package/dist/runtime/index.js +13 -13
- package/dist/self-query-router-MROFQLQB.js +192 -0
- package/dist/session-events-CK44XOU4.js +38 -0
- package/dist/session-kill-telemetry-MT6ITDOG.js +31 -0
- package/dist/session-scope-3XDBWV65.js +88 -0
- package/dist/setup-wizard-X6DOD7MC.js +12 -0
- package/dist/skill-refinement-G2CCY3GM.js +159 -0
- package/dist/stack-update-JF7F56AS.js +84 -0
- package/dist/steward-gate-YF2CYXE7.js +15 -0
- package/dist/task-enforcement-YN6HK7NE.js +506 -0
- package/dist/task-scope-CVK6ISCZ.js +37 -0
- package/dist/tasks-crud-NTNET4JE.js +79 -0
- package/dist/tasks-notify-4LJVFPCV.js +40 -0
- package/dist/tasks-review-3V4WOIRG.js +49 -0
- package/dist/telemetry-upload-5PNUKGTM.js +741 -0
- package/dist/token-budget-E46G7ZAQ.js +86 -0
- package/dist/tool-capability-index-JDSMKJER.js +10 -0
- package/dist/tool-telemetry-J3NLS3LJ.js +17 -0
- package/dist/tui/App.js +18 -18
- package/dist/tui-data-6DOMUUCM.js +260 -0
- package/dist/wiki-acl-5UK37LKF.js +111 -0
- package/dist/worker-gate-FM7AEC7G.js +21 -0
- package/dist/workflow-engine-2EDUHUIY.js +28 -0
- package/dist/worktree-7YKKJIYR.js +28 -0
- package/dist/worktree-sweep-C3ELFGDN.js +21 -0
- package/package.json +1 -1
- package/release-notes.json +88 -88
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import {
|
|
2
|
+
sendMessage
|
|
3
|
+
} from "./chunk-6327RBWR.js";
|
|
4
|
+
import {
|
|
5
|
+
getActiveAgent
|
|
6
|
+
} from "./chunk-AKV44JEH.js";
|
|
7
|
+
|
|
8
|
+
// src/mcp/tools/send-message.ts
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
function registerSendMessage(server) {
|
|
11
|
+
server.registerTool(
|
|
12
|
+
"send_message",
|
|
13
|
+
{
|
|
14
|
+
title: "Send Message",
|
|
15
|
+
description: "Send a structured message to another agent. Messages are queued and delivered via intercom. NOTE: messages are fire-and-forget \u2014 do NOT use for actionable work dispatch. Use create_task instead to assign work to employees.",
|
|
16
|
+
inputSchema: {
|
|
17
|
+
target_agent: z.string().describe("Recipient agent name"),
|
|
18
|
+
content: z.string().describe("Message content"),
|
|
19
|
+
target_project: z.string().optional().describe("Project context (optional)"),
|
|
20
|
+
priority: z.enum(["normal", "urgent"]).default("normal").describe("Message priority (default: normal)"),
|
|
21
|
+
target_device: z.string().optional().describe("Target device ID for cross-machine delivery (default: local)")
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
async ({ target_agent, content, target_project, priority, target_device }) => {
|
|
25
|
+
const { agentId } = getActiveAgent();
|
|
26
|
+
const msg = await sendMessage({
|
|
27
|
+
fromAgent: agentId,
|
|
28
|
+
targetAgent: target_agent,
|
|
29
|
+
targetProject: target_project,
|
|
30
|
+
targetDevice: target_device,
|
|
31
|
+
content,
|
|
32
|
+
priority
|
|
33
|
+
});
|
|
34
|
+
const statusText = msg.status === "delivered" ? "delivered" : msg.status === "failed" ? `failed: ${msg.failureReason}` : "queued (pending delivery)";
|
|
35
|
+
return {
|
|
36
|
+
content: [
|
|
37
|
+
{
|
|
38
|
+
type: "text",
|
|
39
|
+
text: `Message sent to ${target_agent}: ${statusText}
|
|
40
|
+
ID: ${msg.id}`
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export {
|
|
49
|
+
registerSendMessage
|
|
50
|
+
};
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
import {
|
|
2
|
+
vectorToSqlLiteral
|
|
3
|
+
} from "./chunk-VRRAE5JX.js";
|
|
4
|
+
import {
|
|
5
|
+
blobToVector
|
|
6
|
+
} from "./chunk-OTVEIJUQ.js";
|
|
7
|
+
import {
|
|
8
|
+
getClient
|
|
9
|
+
} from "./chunk-WUKHLCBE.js";
|
|
10
|
+
|
|
11
|
+
// src/lib/behaviors.ts
|
|
12
|
+
import crypto from "crypto";
|
|
13
|
+
var GHOST_BEHAVIOR_SQL = "(id IS NULL OR trim(coalesce(content, '')) = '' OR (content = '(empty)' AND coalesce(agent_id, '') = 'unknown'))";
|
|
14
|
+
function isGhostBehaviorRow(row) {
|
|
15
|
+
const id = row.id;
|
|
16
|
+
if (id === null || id === void 0 || String(id).trim() === "") return true;
|
|
17
|
+
const content = typeof row.content === "string" ? row.content : row.content == null ? "" : String(row.content);
|
|
18
|
+
if (content.trim() === "") return true;
|
|
19
|
+
const agent = typeof row.agent_id === "string" ? row.agent_id : row.agent_id == null ? "" : String(row.agent_id);
|
|
20
|
+
if (content === "(empty)" && agent === "unknown") return true;
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
function formatReflexContent(trigger, action) {
|
|
24
|
+
return `\u26A1 REFLEX: When ${trigger} \u2192 ${action}. Decide whether to act.`;
|
|
25
|
+
}
|
|
26
|
+
function isReflexBehavior(behavior) {
|
|
27
|
+
return behavior.domain === "reflex";
|
|
28
|
+
}
|
|
29
|
+
async function storeReflexBehavior(opts) {
|
|
30
|
+
const content = formatReflexContent(opts.trigger, opts.action);
|
|
31
|
+
return storeBehavior({
|
|
32
|
+
agentId: opts.agentId,
|
|
33
|
+
content,
|
|
34
|
+
domain: "reflex",
|
|
35
|
+
projectName: opts.projectName,
|
|
36
|
+
priority: "p0",
|
|
37
|
+
// Always injected — impossible to miss
|
|
38
|
+
deviceScoped: opts.deviceScoped ?? false
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
async function storeBehavior(opts) {
|
|
42
|
+
const trimmedContent = (opts.content ?? "").trim();
|
|
43
|
+
if (trimmedContent.length === 0) {
|
|
44
|
+
throw new Error(
|
|
45
|
+
"[behaviors] Refusing to store a behavior with empty content (ghost-row guard)."
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
const trimmedAgent = (opts.agentId ?? "").trim();
|
|
49
|
+
if (trimmedAgent.length === 0) {
|
|
50
|
+
throw new Error(
|
|
51
|
+
"[behaviors] Refusing to store a behavior with empty agent_id (ghost-row guard)."
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
const { loadEmployeesSync, baseAgentName } = await import("./lib/employees.js");
|
|
56
|
+
const roster = loadEmployeesSync();
|
|
57
|
+
if (roster.length > 0) {
|
|
58
|
+
const base = baseAgentName(opts.agentId, roster);
|
|
59
|
+
if (!roster.some((e) => e.name === opts.agentId || e.name === base)) {
|
|
60
|
+
process.stderr.write(
|
|
61
|
+
`[behaviors] WARNING: Agent "${opts.agentId}" not found in roster. Storing behavior anyway \u2014 may be orphaned.
|
|
62
|
+
`
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
} catch {
|
|
67
|
+
}
|
|
68
|
+
const client = getClient();
|
|
69
|
+
const id = crypto.randomUUID();
|
|
70
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
71
|
+
const duplicate = await client.execute({
|
|
72
|
+
sql: `SELECT id FROM behaviors
|
|
73
|
+
WHERE agent_id = ?
|
|
74
|
+
AND COALESCE(domain, '') = COALESCE(?, '')
|
|
75
|
+
AND COALESCE(project_name, '') = COALESCE(?, '')
|
|
76
|
+
AND active = 1
|
|
77
|
+
AND lower(trim(content)) = lower(trim(?))
|
|
78
|
+
ORDER BY updated_at DESC
|
|
79
|
+
LIMIT 1`,
|
|
80
|
+
args: [trimmedAgent, opts.domain ?? null, opts.projectName ?? null, trimmedContent]
|
|
81
|
+
});
|
|
82
|
+
const existingId = duplicate.rows[0]?.id;
|
|
83
|
+
if (existingId) return String(existingId);
|
|
84
|
+
let vector = null;
|
|
85
|
+
if (!process.env.VITEST) {
|
|
86
|
+
try {
|
|
87
|
+
const { embed } = await import("./lib/embedder.js");
|
|
88
|
+
const vec = await embed(trimmedContent);
|
|
89
|
+
vector = new Float32Array(vec);
|
|
90
|
+
} catch {
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
let createdByDevice = null;
|
|
94
|
+
try {
|
|
95
|
+
const { loadDeviceId } = await import("./lib/license.js");
|
|
96
|
+
createdByDevice = loadDeviceId() ?? null;
|
|
97
|
+
} catch {
|
|
98
|
+
}
|
|
99
|
+
const createdByAgent = process.env.AGENT_ID ?? null;
|
|
100
|
+
const sourceSessionId = process.env.CLAUDE_SESSION_ID ?? process.env.SESSION_ID ?? null;
|
|
101
|
+
let deviceId = null;
|
|
102
|
+
if (opts.deviceScoped) {
|
|
103
|
+
try {
|
|
104
|
+
const { loadDeviceId } = await import("./lib/license.js");
|
|
105
|
+
deviceId = loadDeviceId() ?? null;
|
|
106
|
+
} catch {
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
await client.execute({
|
|
110
|
+
sql: `INSERT INTO behaviors (id, agent_id, project_name, domain, priority, content, active, created_at, updated_at, vector, created_by_agent, created_by_device, source_session_id, device_id)
|
|
111
|
+
VALUES (?, ?, ?, ?, ?, ?, 1, ?, ?, ?, ?, ?, ?, ?)`,
|
|
112
|
+
args: [id, trimmedAgent, opts.projectName ?? null, opts.domain ?? null, opts.priority ?? "p1", trimmedContent, now, now, vector ? vectorToSqlLiteral(vector) : null, createdByAgent, createdByDevice, sourceSessionId, deviceId]
|
|
113
|
+
});
|
|
114
|
+
return id;
|
|
115
|
+
}
|
|
116
|
+
async function listBehaviors(agentId, projectName, limit = 30) {
|
|
117
|
+
const client = getClient();
|
|
118
|
+
let currentDeviceId = null;
|
|
119
|
+
try {
|
|
120
|
+
const { loadDeviceId } = await import("./lib/license.js");
|
|
121
|
+
currentDeviceId = loadDeviceId() ?? null;
|
|
122
|
+
} catch {
|
|
123
|
+
}
|
|
124
|
+
const result = await client.execute({
|
|
125
|
+
sql: `SELECT id, agent_id, project_name, domain, priority, content, active, created_at, updated_at, vector, created_by_agent, created_by_device, source_session_id, device_id
|
|
126
|
+
FROM behaviors
|
|
127
|
+
WHERE agent_id = ? AND active = 1
|
|
128
|
+
AND id IS NOT NULL AND trim(coalesce(content, '')) != ''
|
|
129
|
+
AND (project_name IS NULL OR project_name = ?)
|
|
130
|
+
AND (device_id IS NULL OR device_id = ?)
|
|
131
|
+
ORDER BY
|
|
132
|
+
CASE WHEN priority = 'p0' THEN 0
|
|
133
|
+
WHEN priority = 'p1' THEN 1
|
|
134
|
+
ELSE 2 END,
|
|
135
|
+
CASE
|
|
136
|
+
WHEN lower(coalesce(domain, '')) IN ('identity', 'title', 'role') THEN 0
|
|
137
|
+
WHEN lower(content) LIKE '%identity%' THEN 0
|
|
138
|
+
WHEN lower(content) LIKE '%title%' THEN 0
|
|
139
|
+
WHEN lower(content) LIKE '%who are you%' THEN 0
|
|
140
|
+
ELSE 1
|
|
141
|
+
END,
|
|
142
|
+
updated_at DESC
|
|
143
|
+
LIMIT ?`,
|
|
144
|
+
args: [agentId, projectName ?? "", currentDeviceId ?? "", limit]
|
|
145
|
+
});
|
|
146
|
+
return result.rows.map((r) => ({
|
|
147
|
+
id: String(r.id),
|
|
148
|
+
agent_id: String(r.agent_id),
|
|
149
|
+
project_name: r.project_name ? String(r.project_name) : null,
|
|
150
|
+
domain: r.domain ? String(r.domain) : null,
|
|
151
|
+
priority: String(r.priority || "p1"),
|
|
152
|
+
content: String(r.content),
|
|
153
|
+
active: Number(r.active),
|
|
154
|
+
created_at: String(r.created_at),
|
|
155
|
+
updated_at: String(r.updated_at),
|
|
156
|
+
vector: r.vector ? blobToVector(r.vector) : null,
|
|
157
|
+
created_by_agent: r.created_by_agent ? String(r.created_by_agent) : null,
|
|
158
|
+
created_by_device: r.created_by_device ? String(r.created_by_device) : null,
|
|
159
|
+
source_session_id: r.source_session_id ? String(r.source_session_id) : null,
|
|
160
|
+
device_id: r.device_id ? String(r.device_id) : null
|
|
161
|
+
}));
|
|
162
|
+
}
|
|
163
|
+
async function listBehaviorsByDomain(agentId, domain) {
|
|
164
|
+
const client = getClient();
|
|
165
|
+
const result = await client.execute({
|
|
166
|
+
sql: `SELECT id, agent_id, project_name, domain, priority, content, active, created_at, updated_at, vector
|
|
167
|
+
FROM behaviors
|
|
168
|
+
WHERE agent_id = ? AND domain = ? AND active = 1`,
|
|
169
|
+
args: [agentId, domain]
|
|
170
|
+
});
|
|
171
|
+
return result.rows.map((r) => ({
|
|
172
|
+
id: String(r.id),
|
|
173
|
+
agent_id: String(r.agent_id),
|
|
174
|
+
project_name: r.project_name ? String(r.project_name) : null,
|
|
175
|
+
domain: r.domain ? String(r.domain) : null,
|
|
176
|
+
priority: String(r.priority || "p1"),
|
|
177
|
+
content: String(r.content),
|
|
178
|
+
active: Number(r.active),
|
|
179
|
+
created_at: String(r.created_at),
|
|
180
|
+
updated_at: String(r.updated_at),
|
|
181
|
+
vector: r.vector ? blobToVector(r.vector) : null,
|
|
182
|
+
created_by_agent: r.created_by_agent ? String(r.created_by_agent) : null,
|
|
183
|
+
created_by_device: r.created_by_device ? String(r.created_by_device) : null,
|
|
184
|
+
source_session_id: r.source_session_id ? String(r.source_session_id) : null,
|
|
185
|
+
device_id: r.device_id ? String(r.device_id) : null
|
|
186
|
+
}));
|
|
187
|
+
}
|
|
188
|
+
async function listBehaviorsSince(agentId, sinceIso, projectName, limit = 15) {
|
|
189
|
+
const client = getClient();
|
|
190
|
+
let currentDeviceId = null;
|
|
191
|
+
try {
|
|
192
|
+
const { loadDeviceId } = await import("./lib/license.js");
|
|
193
|
+
currentDeviceId = loadDeviceId() ?? null;
|
|
194
|
+
} catch {
|
|
195
|
+
}
|
|
196
|
+
const result = await client.execute({
|
|
197
|
+
sql: `SELECT id, agent_id, project_name, domain, priority, content, active, created_at, updated_at, vector, created_by_agent, created_by_device, source_session_id, device_id
|
|
198
|
+
FROM behaviors
|
|
199
|
+
WHERE agent_id = ? AND active = 1
|
|
200
|
+
AND id IS NOT NULL AND trim(coalesce(content, '')) != ''
|
|
201
|
+
AND (project_name IS NULL OR project_name = ?)
|
|
202
|
+
AND (device_id IS NULL OR device_id = ?)
|
|
203
|
+
AND (created_at > ? OR updated_at > ?)
|
|
204
|
+
ORDER BY
|
|
205
|
+
CASE WHEN priority = 'p0' THEN 0
|
|
206
|
+
WHEN priority = 'p1' THEN 1
|
|
207
|
+
ELSE 2 END,
|
|
208
|
+
updated_at DESC
|
|
209
|
+
LIMIT ?`,
|
|
210
|
+
args: [agentId, projectName ?? "", currentDeviceId ?? "", sinceIso, sinceIso, limit]
|
|
211
|
+
});
|
|
212
|
+
return result.rows.map((r) => ({
|
|
213
|
+
id: String(r.id),
|
|
214
|
+
agent_id: String(r.agent_id),
|
|
215
|
+
project_name: r.project_name ? String(r.project_name) : null,
|
|
216
|
+
domain: r.domain ? String(r.domain) : null,
|
|
217
|
+
priority: String(r.priority || "p1"),
|
|
218
|
+
content: String(r.content),
|
|
219
|
+
active: Number(r.active),
|
|
220
|
+
created_at: String(r.created_at),
|
|
221
|
+
updated_at: String(r.updated_at),
|
|
222
|
+
vector: r.vector ? blobToVector(r.vector) : null,
|
|
223
|
+
created_by_agent: r.created_by_agent ? String(r.created_by_agent) : null,
|
|
224
|
+
created_by_device: r.created_by_device ? String(r.created_by_device) : null,
|
|
225
|
+
source_session_id: r.source_session_id ? String(r.source_session_id) : null,
|
|
226
|
+
device_id: r.device_id ? String(r.device_id) : null
|
|
227
|
+
}));
|
|
228
|
+
}
|
|
229
|
+
async function listSharedSkills(currentAgentId, projectName, limit = 30) {
|
|
230
|
+
const client = getClient();
|
|
231
|
+
let currentDeviceId = null;
|
|
232
|
+
try {
|
|
233
|
+
const { loadDeviceId } = await import("./lib/license.js");
|
|
234
|
+
currentDeviceId = loadDeviceId() ?? null;
|
|
235
|
+
} catch {
|
|
236
|
+
}
|
|
237
|
+
const result = await client.execute({
|
|
238
|
+
sql: `SELECT id, agent_id, project_name, domain, priority, content, active, created_at, updated_at, vector, created_by_agent, created_by_device, source_session_id, device_id
|
|
239
|
+
FROM behaviors
|
|
240
|
+
WHERE domain = 'skill' AND active = 1
|
|
241
|
+
AND id IS NOT NULL AND trim(coalesce(content, '')) != ''
|
|
242
|
+
AND (project_name IS NULL OR project_name = ?)
|
|
243
|
+
AND (device_id IS NULL OR device_id = ?)
|
|
244
|
+
ORDER BY
|
|
245
|
+
CASE WHEN agent_id = ? THEN 0 ELSE 1 END,
|
|
246
|
+
updated_at DESC
|
|
247
|
+
LIMIT ?`,
|
|
248
|
+
args: [projectName ?? "", currentDeviceId ?? "", currentAgentId, limit]
|
|
249
|
+
});
|
|
250
|
+
return result.rows.map((r) => ({
|
|
251
|
+
id: String(r.id),
|
|
252
|
+
agent_id: String(r.agent_id),
|
|
253
|
+
project_name: r.project_name ? String(r.project_name) : null,
|
|
254
|
+
domain: r.domain ? String(r.domain) : null,
|
|
255
|
+
priority: String(r.priority || "p1"),
|
|
256
|
+
content: String(r.content),
|
|
257
|
+
active: Number(r.active),
|
|
258
|
+
created_at: String(r.created_at),
|
|
259
|
+
updated_at: String(r.updated_at),
|
|
260
|
+
vector: r.vector ? blobToVector(r.vector) : null,
|
|
261
|
+
created_by_agent: r.created_by_agent ? String(r.created_by_agent) : null,
|
|
262
|
+
created_by_device: r.created_by_device ? String(r.created_by_device) : null,
|
|
263
|
+
source_session_id: r.source_session_id ? String(r.source_session_id) : null,
|
|
264
|
+
device_id: r.device_id ? String(r.device_id) : null,
|
|
265
|
+
shared: String(r.agent_id) !== currentAgentId
|
|
266
|
+
}));
|
|
267
|
+
}
|
|
268
|
+
async function bulkPurgeGhostBehaviors(opts) {
|
|
269
|
+
const client = getClient();
|
|
270
|
+
const batchSize = Math.min(Math.max(opts?.batchSize ?? 5e3, 1), 5e4);
|
|
271
|
+
const maxBatches = Math.max(opts?.maxBatches ?? 1e6, 1);
|
|
272
|
+
let deleted = 0;
|
|
273
|
+
let batches = 0;
|
|
274
|
+
while (batches < maxBatches) {
|
|
275
|
+
const res = await client.execute({
|
|
276
|
+
sql: `DELETE FROM behaviors
|
|
277
|
+
WHERE rowid IN (
|
|
278
|
+
SELECT rowid FROM behaviors
|
|
279
|
+
WHERE ${GHOST_BEHAVIOR_SQL}
|
|
280
|
+
LIMIT ?
|
|
281
|
+
)`,
|
|
282
|
+
args: [batchSize]
|
|
283
|
+
});
|
|
284
|
+
const n = res.rowsAffected ?? 0;
|
|
285
|
+
batches += 1;
|
|
286
|
+
deleted += n;
|
|
287
|
+
opts?.onProgress?.(deleted, batches);
|
|
288
|
+
if (n < batchSize) break;
|
|
289
|
+
}
|
|
290
|
+
let vacuumed = false;
|
|
291
|
+
if (opts?.vacuum && deleted > 0) {
|
|
292
|
+
try {
|
|
293
|
+
await client.execute("VACUUM");
|
|
294
|
+
vacuumed = true;
|
|
295
|
+
} catch {
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
return { deleted, batches, vacuumed };
|
|
299
|
+
}
|
|
300
|
+
async function deactivateBehavior(id) {
|
|
301
|
+
const client = getClient();
|
|
302
|
+
const result = await client.execute({
|
|
303
|
+
sql: `UPDATE behaviors SET active = 0, updated_at = ? WHERE id = ? AND active = 1`,
|
|
304
|
+
args: [(/* @__PURE__ */ new Date()).toISOString(), id]
|
|
305
|
+
});
|
|
306
|
+
return (result.rowsAffected ?? 0) > 0;
|
|
307
|
+
}
|
|
308
|
+
async function reactivateBehavior(id) {
|
|
309
|
+
const client = getClient();
|
|
310
|
+
const result = await client.execute({
|
|
311
|
+
sql: `UPDATE behaviors SET active = 1, updated_at = ? WHERE id = ? AND active = 0`,
|
|
312
|
+
args: [(/* @__PURE__ */ new Date()).toISOString(), id]
|
|
313
|
+
});
|
|
314
|
+
return (result.rowsAffected ?? 0) > 0;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
export {
|
|
318
|
+
GHOST_BEHAVIOR_SQL,
|
|
319
|
+
isGhostBehaviorRow,
|
|
320
|
+
formatReflexContent,
|
|
321
|
+
isReflexBehavior,
|
|
322
|
+
storeReflexBehavior,
|
|
323
|
+
storeBehavior,
|
|
324
|
+
listBehaviors,
|
|
325
|
+
listBehaviorsByDomain,
|
|
326
|
+
listBehaviorsSince,
|
|
327
|
+
listSharedSkills,
|
|
328
|
+
bulkPurgeGhostBehaviors,
|
|
329
|
+
deactivateBehavior,
|
|
330
|
+
reactivateBehavior
|
|
331
|
+
};
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
// src/lib/crdt-sync.ts
|
|
2
|
+
import * as Y from "yjs";
|
|
3
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, unlinkSync } from "fs";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import { homedir } from "os";
|
|
6
|
+
var DEFAULT_STATE_PATH = path.join(homedir(), ".exe-os", "crdt-state.bin");
|
|
7
|
+
var _statePathOverride = null;
|
|
8
|
+
function getStatePath() {
|
|
9
|
+
return _statePathOverride ?? DEFAULT_STATE_PATH;
|
|
10
|
+
}
|
|
11
|
+
function _setStatePath(p) {
|
|
12
|
+
_statePathOverride = p;
|
|
13
|
+
}
|
|
14
|
+
var doc = null;
|
|
15
|
+
function initCrdtDoc() {
|
|
16
|
+
if (doc) return doc;
|
|
17
|
+
doc = new Y.Doc();
|
|
18
|
+
const sp = getStatePath();
|
|
19
|
+
if (existsSync(sp)) {
|
|
20
|
+
try {
|
|
21
|
+
const state = readFileSync(sp);
|
|
22
|
+
Y.applyUpdate(doc, new Uint8Array(state));
|
|
23
|
+
} catch {
|
|
24
|
+
console.warn("[crdt-sync] WARN: corrupted state file, rebuilding from DB");
|
|
25
|
+
try {
|
|
26
|
+
unlinkSync(sp);
|
|
27
|
+
} catch {
|
|
28
|
+
}
|
|
29
|
+
rebuildFromDb().catch((err) => {
|
|
30
|
+
console.warn("[crdt-sync] rebuild from DB failed:", err);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
doc.on("update", () => {
|
|
35
|
+
persistState();
|
|
36
|
+
});
|
|
37
|
+
return doc;
|
|
38
|
+
}
|
|
39
|
+
function getMemoriesMap() {
|
|
40
|
+
const d = initCrdtDoc();
|
|
41
|
+
return d.getMap("memories");
|
|
42
|
+
}
|
|
43
|
+
function getBehaviorsMap() {
|
|
44
|
+
const d = initCrdtDoc();
|
|
45
|
+
return d.getMap("behaviors");
|
|
46
|
+
}
|
|
47
|
+
function applyRemoteUpdate(update) {
|
|
48
|
+
const d = initCrdtDoc();
|
|
49
|
+
Y.applyUpdate(d, update);
|
|
50
|
+
}
|
|
51
|
+
function getFullState() {
|
|
52
|
+
const d = initCrdtDoc();
|
|
53
|
+
return Y.encodeStateAsUpdate(d);
|
|
54
|
+
}
|
|
55
|
+
function getDiffUpdate(remoteStateVector) {
|
|
56
|
+
const d = initCrdtDoc();
|
|
57
|
+
return Y.encodeStateAsUpdate(d, remoteStateVector);
|
|
58
|
+
}
|
|
59
|
+
function getStateVector() {
|
|
60
|
+
const d = initCrdtDoc();
|
|
61
|
+
return Y.encodeStateVector(d);
|
|
62
|
+
}
|
|
63
|
+
function importExistingMemories(memories) {
|
|
64
|
+
const map = getMemoriesMap();
|
|
65
|
+
const d = initCrdtDoc();
|
|
66
|
+
let imported = 0;
|
|
67
|
+
d.transact(() => {
|
|
68
|
+
for (const mem of memories) {
|
|
69
|
+
if (!mem.id) continue;
|
|
70
|
+
if (map.has(mem.id)) continue;
|
|
71
|
+
const entry = new Y.Map();
|
|
72
|
+
entry.set("id", mem.id);
|
|
73
|
+
entry.set("agent_id", mem.agent_id ?? null);
|
|
74
|
+
entry.set("agent_role", mem.agent_role ?? null);
|
|
75
|
+
entry.set("session_id", mem.session_id ?? null);
|
|
76
|
+
entry.set("timestamp", mem.timestamp ?? null);
|
|
77
|
+
entry.set("tool_name", mem.tool_name ?? null);
|
|
78
|
+
entry.set("project_name", mem.project_name ?? null);
|
|
79
|
+
entry.set("has_error", mem.has_error ?? 0);
|
|
80
|
+
entry.set("raw_text", mem.raw_text ?? "");
|
|
81
|
+
entry.set("version", mem.version ?? 0);
|
|
82
|
+
entry.set("author_device_id", mem.author_device_id ?? null);
|
|
83
|
+
entry.set("scope", mem.scope ?? "business");
|
|
84
|
+
map.set(mem.id, entry);
|
|
85
|
+
imported++;
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
return imported;
|
|
89
|
+
}
|
|
90
|
+
function importExistingBehaviors(behaviors) {
|
|
91
|
+
const map = getBehaviorsMap();
|
|
92
|
+
const d = initCrdtDoc();
|
|
93
|
+
let imported = 0;
|
|
94
|
+
d.transact(() => {
|
|
95
|
+
for (const beh of behaviors) {
|
|
96
|
+
if (!beh.id) continue;
|
|
97
|
+
if (map.has(beh.id)) continue;
|
|
98
|
+
const entry = new Y.Map();
|
|
99
|
+
entry.set("id", beh.id);
|
|
100
|
+
entry.set("agent_id", beh.agent_id ?? null);
|
|
101
|
+
entry.set("project_name", beh.project_name ?? null);
|
|
102
|
+
entry.set("domain", beh.domain ?? null);
|
|
103
|
+
entry.set("content", beh.content ?? null);
|
|
104
|
+
entry.set("active", beh.active ?? 1);
|
|
105
|
+
entry.set("priority", beh.priority ?? "p1");
|
|
106
|
+
entry.set("created_at", beh.created_at ?? null);
|
|
107
|
+
entry.set("updated_at", beh.updated_at ?? null);
|
|
108
|
+
map.set(beh.id, entry);
|
|
109
|
+
imported++;
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
return imported;
|
|
113
|
+
}
|
|
114
|
+
function readAllMemories() {
|
|
115
|
+
const map = getMemoriesMap();
|
|
116
|
+
const records = [];
|
|
117
|
+
map.forEach((entry, id) => {
|
|
118
|
+
records.push({
|
|
119
|
+
id,
|
|
120
|
+
agent_id: entry.get("agent_id"),
|
|
121
|
+
agent_role: entry.get("agent_role"),
|
|
122
|
+
session_id: entry.get("session_id"),
|
|
123
|
+
timestamp: entry.get("timestamp"),
|
|
124
|
+
tool_name: entry.get("tool_name"),
|
|
125
|
+
project_name: entry.get("project_name"),
|
|
126
|
+
has_error: entry.get("has_error"),
|
|
127
|
+
raw_text: entry.get("raw_text"),
|
|
128
|
+
version: entry.get("version"),
|
|
129
|
+
author_device_id: entry.get("author_device_id"),
|
|
130
|
+
scope: entry.get("scope"),
|
|
131
|
+
session_scope: entry.get("session_scope")
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
return records;
|
|
135
|
+
}
|
|
136
|
+
function readAllBehaviors() {
|
|
137
|
+
const map = getBehaviorsMap();
|
|
138
|
+
const records = [];
|
|
139
|
+
map.forEach((entry, id) => {
|
|
140
|
+
records.push({
|
|
141
|
+
id,
|
|
142
|
+
agent_id: entry.get("agent_id"),
|
|
143
|
+
project_name: entry.get("project_name"),
|
|
144
|
+
domain: entry.get("domain"),
|
|
145
|
+
content: entry.get("content"),
|
|
146
|
+
active: entry.get("active"),
|
|
147
|
+
priority: entry.get("priority"),
|
|
148
|
+
created_at: entry.get("created_at"),
|
|
149
|
+
updated_at: entry.get("updated_at")
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
return records;
|
|
153
|
+
}
|
|
154
|
+
function onUpdate(callback) {
|
|
155
|
+
const d = initCrdtDoc();
|
|
156
|
+
const handler = (update) => callback(update);
|
|
157
|
+
d.on("update", handler);
|
|
158
|
+
return () => d.off("update", handler);
|
|
159
|
+
}
|
|
160
|
+
function persistState() {
|
|
161
|
+
if (!doc) return;
|
|
162
|
+
try {
|
|
163
|
+
const sp = getStatePath();
|
|
164
|
+
const dir = path.dirname(sp);
|
|
165
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
166
|
+
const state = Y.encodeStateAsUpdate(doc);
|
|
167
|
+
writeFileSync(sp, Buffer.from(state));
|
|
168
|
+
} catch {
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
function isCrdtSyncEnabled() {
|
|
172
|
+
return process.env.EXE_CRDT_SYNC === "1";
|
|
173
|
+
}
|
|
174
|
+
async function rebuildFromDb() {
|
|
175
|
+
const { getClient } = await import("./lib/database.js");
|
|
176
|
+
const client = getClient();
|
|
177
|
+
const result = await client.execute(
|
|
178
|
+
"SELECT id, agent_id, agent_role, session_id, timestamp, tool_name, project_name, has_error, raw_text, version, author_device_id, scope, session_scope FROM memories"
|
|
179
|
+
);
|
|
180
|
+
const memories = result.rows.map((row) => ({
|
|
181
|
+
id: String(row.id),
|
|
182
|
+
agent_id: row.agent_id,
|
|
183
|
+
agent_role: row.agent_role,
|
|
184
|
+
session_id: row.session_id,
|
|
185
|
+
timestamp: row.timestamp,
|
|
186
|
+
tool_name: row.tool_name,
|
|
187
|
+
project_name: row.project_name,
|
|
188
|
+
has_error: row.has_error,
|
|
189
|
+
raw_text: row.raw_text,
|
|
190
|
+
version: row.version,
|
|
191
|
+
author_device_id: row.author_device_id,
|
|
192
|
+
scope: row.scope,
|
|
193
|
+
session_scope: row.session_scope
|
|
194
|
+
}));
|
|
195
|
+
const count = importExistingMemories(memories);
|
|
196
|
+
persistState();
|
|
197
|
+
return count;
|
|
198
|
+
}
|
|
199
|
+
function destroyCrdtDoc() {
|
|
200
|
+
if (doc) {
|
|
201
|
+
doc.destroy();
|
|
202
|
+
doc = null;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export {
|
|
207
|
+
_setStatePath,
|
|
208
|
+
initCrdtDoc,
|
|
209
|
+
applyRemoteUpdate,
|
|
210
|
+
getFullState,
|
|
211
|
+
getDiffUpdate,
|
|
212
|
+
getStateVector,
|
|
213
|
+
importExistingMemories,
|
|
214
|
+
importExistingBehaviors,
|
|
215
|
+
readAllMemories,
|
|
216
|
+
readAllBehaviors,
|
|
217
|
+
onUpdate,
|
|
218
|
+
isCrdtSyncEnabled,
|
|
219
|
+
rebuildFromDb,
|
|
220
|
+
destroyCrdtDoc
|
|
221
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import {
|
|
2
|
+
fastDbInit
|
|
3
|
+
} from "./chunk-KA26YTNU.js";
|
|
4
|
+
import {
|
|
5
|
+
sessionScopeFilter
|
|
6
|
+
} from "./chunk-K5ZO532Q.js";
|
|
7
|
+
import {
|
|
8
|
+
formatStatusAll,
|
|
9
|
+
formatStatusDeep,
|
|
10
|
+
getEmployeeStatuses,
|
|
11
|
+
inTmux
|
|
12
|
+
} from "./chunk-SSTLTIF3.js";
|
|
13
|
+
import {
|
|
14
|
+
getClient,
|
|
15
|
+
isCoordinatorRole,
|
|
16
|
+
loadEmployees
|
|
17
|
+
} from "./chunk-WUKHLCBE.js";
|
|
18
|
+
import {
|
|
19
|
+
isMainModule
|
|
20
|
+
} from "./chunk-6Y4B3QF6.js";
|
|
21
|
+
|
|
22
|
+
// src/bin/exe-status.ts
|
|
23
|
+
async function status(targetEmployee) {
|
|
24
|
+
if (!inTmux()) {
|
|
25
|
+
return "Not in a tmux session. Start tmux first: tmux new-session -s work";
|
|
26
|
+
}
|
|
27
|
+
const employees = await loadEmployees();
|
|
28
|
+
const names = employees.filter((e) => !isCoordinatorRole(e.role)).map((e) => e.name);
|
|
29
|
+
const roles = new Map(employees.map((e) => [e.name, e.role ?? ""]));
|
|
30
|
+
await fastDbInit();
|
|
31
|
+
const client = getClient();
|
|
32
|
+
const taskMap = /* @__PURE__ */ new Map();
|
|
33
|
+
try {
|
|
34
|
+
const esScope = sessionScopeFilter();
|
|
35
|
+
const result = await client.execute({
|
|
36
|
+
sql: `SELECT assigned_to, title, priority FROM tasks
|
|
37
|
+
WHERE status = 'in_progress'${esScope.sql}
|
|
38
|
+
ORDER BY priority ASC, created_at ASC`,
|
|
39
|
+
args: [...esScope.args]
|
|
40
|
+
});
|
|
41
|
+
for (const row of result.rows) {
|
|
42
|
+
const assignee = String(row.assigned_to);
|
|
43
|
+
if (!taskMap.has(assignee)) {
|
|
44
|
+
taskMap.set(assignee, {
|
|
45
|
+
title: String(row.title),
|
|
46
|
+
priority: String(row.priority)
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
} catch {
|
|
51
|
+
}
|
|
52
|
+
if (targetEmployee) {
|
|
53
|
+
if (!names.includes(targetEmployee)) {
|
|
54
|
+
return `Employee "${targetEmployee}" not found. Available: ${names.join(", ")}`;
|
|
55
|
+
}
|
|
56
|
+
const statuses2 = getEmployeeStatuses([targetEmployee]);
|
|
57
|
+
const s = statuses2[0];
|
|
58
|
+
return formatStatusDeep(s, taskMap.get(targetEmployee), roles.get(targetEmployee) ?? "");
|
|
59
|
+
}
|
|
60
|
+
const statuses = getEmployeeStatuses(names);
|
|
61
|
+
return formatStatusAll(statuses, taskMap, roles);
|
|
62
|
+
}
|
|
63
|
+
if (isMainModule(import.meta.url)) {
|
|
64
|
+
const target = process.argv[2];
|
|
65
|
+
status(target).then((output) => {
|
|
66
|
+
process.stdout.write(output + "\n");
|
|
67
|
+
}).catch((err) => {
|
|
68
|
+
process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
|
|
69
|
+
`);
|
|
70
|
+
process.exit(1);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export {
|
|
75
|
+
status
|
|
76
|
+
};
|