@tekmidian/pai 0.41.0 → 0.42.0
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/dist/aibroker-client-BP74gGwD.mjs +215 -0
- package/dist/aibroker-client-BP74gGwD.mjs.map +1 -0
- package/dist/aibroker-client-C6m71p6O.mjs +3 -0
- package/dist/{auto-route-BwzmlW3W.mjs → auto-route-_5zzJz5q.mjs} +2 -2
- package/dist/{auto-route-BwzmlW3W.mjs.map → auto-route-_5zzJz5q.mjs.map} +1 -1
- package/dist/{chain-zMjCDW-R.mjs → chain-DGXNoTwc.mjs} +70 -329
- package/dist/chain-DGXNoTwc.mjs.map +1 -0
- package/dist/cli/index.mjs +12 -10
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli/program.mjs +12 -10
- package/dist/{clusters-DRHhfli9.mjs → clusters-j0ZuNYp9.mjs} +1 -1
- package/dist/{clusters-DRHhfli9.mjs.map → clusters-j0ZuNYp9.mjs.map} +1 -1
- package/dist/{config-D1G9IFpn.mjs → config-B64vFg14.mjs} +3 -50
- package/dist/config-B64vFg14.mjs.map +1 -0
- package/dist/{config-DD52BPB-.mjs → config-C_ErGddD.mjs} +1 -1
- package/dist/{config-Dl8lT4Lu.mjs → config-DgzR5sfb.mjs} +2 -2
- package/dist/{config-Dl8lT4Lu.mjs.map → config-DgzR5sfb.mjs.map} +1 -1
- package/dist/{context-handover-cache-C6_rs7JT.mjs → context-handover-cache-dUnSZwaA.mjs} +4 -4
- package/dist/{context-handover-cache-C6_rs7JT.mjs.map → context-handover-cache-dUnSZwaA.mjs.map} +1 -1
- package/dist/daemon/index.mjs +13 -12
- package/dist/daemon/index.mjs.map +1 -1
- package/dist/daemon-CKBkhOsZ.mjs +23 -0
- package/dist/{daemon-CpdVUnl_.mjs → daemon-DsvP8KMy.mjs} +357 -27
- package/dist/daemon-DsvP8KMy.mjs.map +1 -0
- package/dist/daemon-mcp/index.mjs +10 -6
- package/dist/daemon-mcp/index.mjs.map +1 -1
- package/dist/detector-C-7KRi42.mjs +5 -0
- package/dist/{detector-smpCm7ku.mjs → detector-C73Nxm94.mjs} +1 -1
- package/dist/{detector-smpCm7ku.mjs.map → detector-C73Nxm94.mjs.map} +1 -1
- package/dist/{factory-Bc5EyN54.mjs → factory-DEb9NmHJ.mjs} +7 -7
- package/dist/{factory-Bc5EyN54.mjs.map → factory-DEb9NmHJ.mjs.map} +1 -1
- package/dist/factory-Dbo8yNPi.mjs +3 -0
- package/dist/{fallback-CgQ_x4I7.mjs → fallback-5UJO-RyX.mjs} +5 -4
- package/dist/{fallback-CgQ_x4I7.mjs.map → fallback-5UJO-RyX.mjs.map} +1 -1
- package/dist/hooks/worker-status-line.mjs +9 -4
- package/dist/hooks/worker-status-line.mjs.map +3 -3
- package/dist/hooks/worker-supervision.mjs +593 -0
- package/dist/hooks/worker-supervision.mjs.map +7 -0
- package/dist/{indexer-backend-rohVVKrA.mjs → indexer-backend-BPTzKFZU.mjs} +1 -1
- package/dist/{indexer-backend-rohVVKrA.mjs.map → indexer-backend-BPTzKFZU.mjs.map} +1 -1
- package/dist/{ipc-client-C7AVpsyv.mjs → ipc-client-BmypMNYk.mjs} +2 -2
- package/dist/{ipc-client-C7AVpsyv.mjs.map → ipc-client-BmypMNYk.mjs.map} +1 -1
- package/dist/{kg-entity-DbOMPdF9.mjs → kg-entity-r8duqhi9.mjs} +1 -1
- package/dist/{kg-entity-DbOMPdF9.mjs.map → kg-entity-r8duqhi9.mjs.map} +1 -1
- package/dist/{latent-ideas-iNp5s55R.mjs → latent-ideas-CtSca4qG.mjs} +2 -2
- package/dist/{latent-ideas-iNp5s55R.mjs.map → latent-ideas-CtSca4qG.mjs.map} +1 -1
- package/dist/{link-boost-NNzADHX_.mjs → link-boost-Bucnz3n8.mjs} +1 -1
- package/dist/{link-boost-NNzADHX_.mjs.map → link-boost-Bucnz3n8.mjs.map} +1 -1
- package/dist/{main-resolver-CM1IHbuu.mjs → main-resolver-BgIrC-D9.mjs} +4 -214
- package/dist/main-resolver-BgIrC-D9.mjs.map +1 -0
- package/dist/main-resolver-DXGuygFG.mjs +7 -0
- package/dist/{neighborhood-AGL7oXQ2.mjs → neighborhood-CM7Jgb51.mjs} +1 -1
- package/dist/{neighborhood-AGL7oXQ2.mjs.map → neighborhood-CM7Jgb51.mjs.map} +1 -1
- package/dist/{note-context-BHwYpSFf.mjs → note-context-DCwE2A-M.mjs} +1 -1
- package/dist/{note-context-BHwYpSFf.mjs.map → note-context-DCwE2A-M.mjs.map} +1 -1
- package/dist/{planner-DsmMRIZR.mjs → planner-BLDJt3ZS.mjs} +6 -5
- package/dist/{planner-DsmMRIZR.mjs.map → planner-BLDJt3ZS.mjs.map} +1 -1
- package/dist/{postgres-Dwxe290H.mjs → postgres-CtOzfoQU.mjs} +1 -1
- package/dist/{postgres-Dwxe290H.mjs.map → postgres-CtOzfoQU.mjs.map} +1 -1
- package/dist/{program-Bed-Pd-8.mjs → program-CruRnLtc.mjs} +36 -33
- package/dist/{program-Bed-Pd-8.mjs.map → program-CruRnLtc.mjs.map} +1 -1
- package/dist/query-feedback-DGoVRaWD.mjs +3 -0
- package/dist/{query-feedback-DZfjI34w.mjs → query-feedback-Dqz-HC__.mjs} +1 -1
- package/dist/{query-feedback-DZfjI34w.mjs.map → query-feedback-Dqz-HC__.mjs.map} +1 -1
- package/dist/router-BTIGZR2_.mjs +3 -0
- package/dist/{router-DHracTUC.mjs → router-DD6D4j31.mjs} +1 -1
- package/dist/{router-DHracTUC.mjs.map → router-DD6D4j31.mjs.map} +1 -1
- package/dist/runtime-paths-rni52zHX.mjs +50 -0
- package/dist/runtime-paths-rni52zHX.mjs.map +1 -0
- package/dist/scope-NIwCGxRI.mjs +351 -0
- package/dist/scope-NIwCGxRI.mjs.map +1 -0
- package/dist/{server-BOuAOj9b.mjs → server-Cp7tNzNC.mjs} +19 -2
- package/dist/server-Cp7tNzNC.mjs.map +1 -0
- package/dist/skills/Worker/SKILL.md +3 -0
- package/dist/{sources-ju6AA7lL.mjs → sources-CS43CpuS.mjs} +1 -1
- package/dist/{sources-ju6AA7lL.mjs.map → sources-CS43CpuS.mjs.map} +1 -1
- package/dist/{sqlite-kFZeWCJ2.mjs → sqlite-Cq3gJcq9.mjs} +1 -1
- package/dist/{sqlite-kFZeWCJ2.mjs.map → sqlite-Cq3gJcq9.mjs.map} +1 -1
- package/dist/{state-ahFAbD8b.mjs → state-BTa10SOM.mjs} +1 -1
- package/dist/{state-ahFAbD8b.mjs.map → state-BTa10SOM.mjs.map} +1 -1
- package/dist/{state-DH_mp5Xe.mjs → state-RXepvbnO.mjs} +1 -1
- package/dist/{themes-DqhNUUQk.mjs → themes-B7h9YDiy.mjs} +1 -1
- package/dist/{themes-DqhNUUQk.mjs.map → themes-B7h9YDiy.mjs.map} +1 -1
- package/dist/{tools-COna9vZR.mjs → tools-BW3NLMPk.mjs} +1 -1
- package/dist/{tools-CMlHa9lZ.mjs → tools-LlzcV_eK.mjs} +14 -14
- package/dist/{tools-CMlHa9lZ.mjs.map → tools-LlzcV_eK.mjs.map} +1 -1
- package/dist/{trace-DTP6k4B_.mjs → trace-u4hT-pLD.mjs} +1 -1
- package/dist/{trace-DTP6k4B_.mjs.map → trace-u4hT-pLD.mjs.map} +1 -1
- package/dist/{vault-indexer-YMH22mLU.mjs → vault-indexer-mata9S7b.mjs} +1 -1
- package/dist/{vault-indexer-YMH22mLU.mjs.map → vault-indexer-mata9S7b.mjs.map} +1 -1
- package/dist/{work-queue-worker-B3nl8yyn.mjs → work-queue-worker-7Vkli4Yh.mjs} +4 -4
- package/dist/{work-queue-worker-B3nl8yyn.mjs.map → work-queue-worker-7Vkli4Yh.mjs.map} +1 -1
- package/dist/work-queue-worker-D1p2V-ae.mjs +14 -0
- package/dist/{zettelkasten-DDvKRm2V.mjs → zettelkasten-F0D_XfQ4.mjs} +3 -3
- package/dist/{zettelkasten-DDvKRm2V.mjs.map → zettelkasten-F0D_XfQ4.mjs.map} +1 -1
- package/docs/commands/worker.md +1 -1
- package/docs/worker.md +40 -0
- package/package.json +1 -1
- package/plugins/productivity/hooks/hooks.json +5 -0
- package/src/hooks/ts/user-prompt/worker-supervision.ts +123 -0
- package/dist/chain-zMjCDW-R.mjs.map +0 -1
- package/dist/config-D1G9IFpn.mjs.map +0 -1
- package/dist/daemon-BSL9sXxm.mjs +0 -22
- package/dist/daemon-CpdVUnl_.mjs.map +0 -1
- package/dist/detector-BLVOCiJ_.mjs +0 -5
- package/dist/factory-C7ua_3ik.mjs +0 -3
- package/dist/main-resolver-CM1IHbuu.mjs.map +0 -1
- package/dist/main-resolver-E5WlilhM.mjs +0 -6
- package/dist/query-feedback-CGcEiGtY.mjs +0 -3
- package/dist/router-CAtyVQud.mjs +0 -3
- package/dist/server-BOuAOj9b.mjs.map +0 -1
- package/dist/work-queue-worker-BM1GcAAq.mjs +0 -14
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/daemon/index.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * PAI Daemon — Entry point\n *\n * Commands:\n * serve — Start the PAI daemon (foreground, managed by launchd in production)\n * status — Query daemon status via IPC\n * index — Trigger an immediate index run via IPC\n */\n\nimport { Command } from \"commander\";\nimport { loadConfig, ensureConfigDir } from \"./config.js\";\nimport { serve } from \"./daemon.js\";\nimport { PaiClient } from \"./ipc-client.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"pai-daemon\")\n .description(\"PAI Daemon — background service for PAI Knowledge OS\")\n .version(\"0.1.0\");\n\n// ---------------------------------------------------------------------------\n// serve\n// ---------------------------------------------------------------------------\n\nprogram\n .command(\"serve\")\n .description(\"Start the PAI daemon in the foreground\")\n .action(async () => {\n ensureConfigDir();\n const config = loadConfig();\n await serve(config);\n });\n\n// ---------------------------------------------------------------------------\n// status\n// ---------------------------------------------------------------------------\n\nprogram\n .command(\"status\")\n .description(\"Query the running daemon status\")\n .action(async () => {\n const config = loadConfig();\n const client = new PaiClient(config.socketPath);\n\n try {\n const status = await client.status();\n console.log(JSON.stringify(status, null, 2));\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n console.error(`Error: ${msg}`);\n process.exit(1);\n }\n });\n\n// ---------------------------------------------------------------------------\n// index\n// ---------------------------------------------------------------------------\n\nprogram\n .command(\"index\")\n .description(\"Trigger an immediate index run in the running daemon\")\n .action(async () => {\n const config = loadConfig();\n const client = new PaiClient(config.socketPath);\n\n try {\n await client.triggerIndex();\n console.log(\"Index triggered. Check daemon logs for progress.\");\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n console.error(`Error: ${msg}`);\n process.exit(1);\n }\n });\n\n// ---------------------------------------------------------------------------\n// Parse\n// ---------------------------------------------------------------------------\n\nprogram.parse(process.argv);\n\nif (process.argv.length <= 2) {\n program.help();\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/daemon/index.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * PAI Daemon — Entry point\n *\n * Commands:\n * serve — Start the PAI daemon (foreground, managed by launchd in production)\n * status — Query daemon status via IPC\n * index — Trigger an immediate index run via IPC\n */\n\nimport { Command } from \"commander\";\nimport { loadConfig, ensureConfigDir } from \"./config.js\";\nimport { serve } from \"./daemon.js\";\nimport { PaiClient } from \"./ipc-client.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"pai-daemon\")\n .description(\"PAI Daemon — background service for PAI Knowledge OS\")\n .version(\"0.1.0\");\n\n// ---------------------------------------------------------------------------\n// serve\n// ---------------------------------------------------------------------------\n\nprogram\n .command(\"serve\")\n .description(\"Start the PAI daemon in the foreground\")\n .action(async () => {\n ensureConfigDir();\n const config = loadConfig();\n await serve(config);\n });\n\n// ---------------------------------------------------------------------------\n// status\n// ---------------------------------------------------------------------------\n\nprogram\n .command(\"status\")\n .description(\"Query the running daemon status\")\n .action(async () => {\n const config = loadConfig();\n const client = new PaiClient(config.socketPath);\n\n try {\n const status = await client.status();\n console.log(JSON.stringify(status, null, 2));\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n console.error(`Error: ${msg}`);\n process.exit(1);\n }\n });\n\n// ---------------------------------------------------------------------------\n// index\n// ---------------------------------------------------------------------------\n\nprogram\n .command(\"index\")\n .description(\"Trigger an immediate index run in the running daemon\")\n .action(async () => {\n const config = loadConfig();\n const client = new PaiClient(config.socketPath);\n\n try {\n await client.triggerIndex();\n console.log(\"Index triggered. Check daemon logs for progress.\");\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n console.error(`Error: ${msg}`);\n process.exit(1);\n }\n });\n\n// ---------------------------------------------------------------------------\n// Parse\n// ---------------------------------------------------------------------------\n\nprogram.parse(process.argv);\n\nif (process.argv.length <= 2) {\n program.help();\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAeA,MAAM,UAAU,IAAI,SAAS;AAE7B,QACG,KAAK,aAAa,CAClB,YAAY,uDAAuD,CACnE,QAAQ,QAAQ;AAMnB,QACG,QAAQ,QAAQ,CAChB,YAAY,yCAAyC,CACrD,OAAO,YAAY;AAClB,kBAAiB;AAEjB,OAAM,MADS,YAAY,CACR;EACnB;AAMJ,QACG,QAAQ,SAAS,CACjB,YAAY,kCAAkC,CAC9C,OAAO,YAAY;CAElB,MAAM,SAAS,IAAI,UADJ,YAAY,CACS,WAAW;AAE/C,KAAI;EACF,MAAM,SAAS,MAAM,OAAO,QAAQ;AACpC,UAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;UACrC,GAAG;EACV,MAAM,MAAM,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE;AACtD,UAAQ,MAAM,UAAU,MAAM;AAC9B,UAAQ,KAAK,EAAE;;EAEjB;AAMJ,QACG,QAAQ,QAAQ,CAChB,YAAY,uDAAuD,CACnE,OAAO,YAAY;CAElB,MAAM,SAAS,IAAI,UADJ,YAAY,CACS,WAAW;AAE/C,KAAI;AACF,QAAM,OAAO,cAAc;AAC3B,UAAQ,IAAI,mDAAmD;UACxD,GAAG;EACV,MAAM,MAAM,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE;AACtD,UAAQ,MAAM,UAAU,MAAM;AAC9B,UAAQ,KAAK,EAAE;;EAEjB;AAMJ,QAAQ,MAAM,QAAQ,KAAK;AAE3B,IAAI,QAAQ,KAAK,UAAU,EACzB,SAAQ,MAAM"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import "./db-Ca5qfsMC.mjs";
|
|
2
|
+
import "./utils-9Err2RBW.mjs";
|
|
3
|
+
import "./migrate-Cjzeefn9.mjs";
|
|
4
|
+
import "./db-a1ixZQjr.mjs";
|
|
5
|
+
import "./helpers-IjZkXBhj.mjs";
|
|
6
|
+
import "./sync-BWbe8JTg.mjs";
|
|
7
|
+
import "./embeddings-DOLZnT1X.mjs";
|
|
8
|
+
import "./search-Rpk1cSBC.mjs";
|
|
9
|
+
import "./context-handover-cache-dUnSZwaA.mjs";
|
|
10
|
+
import "./indexer-D7MvSQPY.mjs";
|
|
11
|
+
import "./config-B64vFg14.mjs";
|
|
12
|
+
import "./factory-DEb9NmHJ.mjs";
|
|
13
|
+
import "./config-DgzR5sfb.mjs";
|
|
14
|
+
import "./server-Cp7tNzNC.mjs";
|
|
15
|
+
import "./scope-NIwCGxRI.mjs";
|
|
16
|
+
import { t as serve } from "./daemon-DsvP8KMy.mjs";
|
|
17
|
+
import "./state-BTa10SOM.mjs";
|
|
18
|
+
import "./router-DD6D4j31.mjs";
|
|
19
|
+
import "./tools-LlzcV_eK.mjs";
|
|
20
|
+
import "./detector-C73Nxm94.mjs";
|
|
21
|
+
import "./work-queue-worker-7Vkli4Yh.mjs";
|
|
22
|
+
|
|
23
|
+
export { serve };
|
|
@@ -3,15 +3,19 @@ import { t as openFederation } from "./db-a1ixZQjr.mjs";
|
|
|
3
3
|
import { d as sha256 } from "./helpers-IjZkXBhj.mjs";
|
|
4
4
|
import { n as indexAll } from "./sync-BWbe8JTg.mjs";
|
|
5
5
|
import { t as configureEmbeddingModel } from "./embeddings-DOLZnT1X.mjs";
|
|
6
|
-
import { l as DEFAULT_NOTIFICATION_CONFIG, n as CONFIG_FILE, t as CONFIG_DIR } from "./config-
|
|
7
|
-
import { n as getBackendOutage, t as createStorageBackend } from "./factory-
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { t as
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
6
|
+
import { l as DEFAULT_NOTIFICATION_CONFIG, n as CONFIG_FILE, t as CONFIG_DIR } from "./config-B64vFg14.mjs";
|
|
7
|
+
import { n as getBackendOutage, t as createStorageBackend } from "./factory-DEb9NmHJ.mjs";
|
|
8
|
+
import { m as readWorkersSection } from "./config-DgzR5sfb.mjs";
|
|
9
|
+
import { _ as workersLogDir } from "./server-Cp7tNzNC.mjs";
|
|
10
|
+
import { d as alive, g as loadStatuses, n as itermForClaudeSession, v as nowStamp } from "./scope-NIwCGxRI.mjs";
|
|
11
|
+
import { C as setStorageBackend, D as storageBackend, E as startTime, O as vaultIndexInProgress, S as setStartTime, T as shutdownRequested, _ as setLastIndexTime, a as indexSchedulerTimer, b as setRegistryDb, c as lastVaultIndexTime, d as setDaemonConfig, f as setEmbedInProgress, g as setLastEmbedTime, h as setIndexSchedulerTimer, i as indexInProgress, l as notificationConfig, m as setIndexInProgress, n as embedInProgress, o as lastEmbedTime, p as setEmbedSchedulerTimer, r as embedSchedulerTimer, s as lastIndexTime, t as daemonConfig, u as registryDb, v as setLastVaultIndexTime, w as setVaultIndexInProgress, x as setShutdownRequested, y as setNotificationConfig } from "./state-BTa10SOM.mjs";
|
|
12
|
+
import { t as routeNotification } from "./router-DD6D4j31.mjs";
|
|
13
|
+
import { C as toolProjectInfo, D as toolMemoryGet, O as toolMemorySearch, S as toolProjectHealth, T as toolProjectTodo, a as toolMemoryWakeup, b as toolSessionRoute, i as toolMemoryTaxonomy, n as toolMemoryFeedback, t as toolMemoryKgSearch, v as toolRegistrySearch, w as toolProjectList, x as toolProjectDetect, y as toolSessionList } from "./tools-LlzcV_eK.mjs";
|
|
14
|
+
import { t as detectTopicShift } from "./detector-C73Nxm94.mjs";
|
|
15
|
+
import { a as enqueue, i as stopWorker, n as notifyNewWork, o as getStats, r as startWorker, s as loadQueue } from "./work-queue-worker-7Vkli4Yh.mjs";
|
|
16
|
+
import { appendFileSync, existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
|
|
14
17
|
import { setPriority } from "node:os";
|
|
18
|
+
import { dirname, join } from "node:path";
|
|
15
19
|
import { connect, createServer } from "node:net";
|
|
16
20
|
|
|
17
21
|
//#region src/notifications/config.ts
|
|
@@ -83,6 +87,295 @@ function patchNotificationConfig(patch) {
|
|
|
83
87
|
return current;
|
|
84
88
|
}
|
|
85
89
|
|
|
90
|
+
//#endregion
|
|
91
|
+
//#region src/workers/supervision.ts
|
|
92
|
+
/**
|
|
93
|
+
* supervision.ts — daemon-side worker supervision, event push not polling.
|
|
94
|
+
*
|
|
95
|
+
* An orchestrating session must keep an eye on its workers without sleeping
|
|
96
|
+
* (the Worker skill forbids busy-waiting), the same way the AIBroker daemon
|
|
97
|
+
* keeps an eye on sessions. The PAI daemon already runs all day; this module
|
|
98
|
+
* gives it a tick that watches every worker's status file and pushes one-line
|
|
99
|
+
* events to the owning session when something happens:
|
|
100
|
+
*
|
|
101
|
+
* finished — the run ended clean (state done, rc 0)
|
|
102
|
+
* failed — the run ended badly (state failed/killed/lost, or rc != 0,
|
|
103
|
+
* or the runner pid vanished while state was still running)
|
|
104
|
+
* stalled — state running, runner alive, but no new turn for longer than
|
|
105
|
+
* the stall threshold (PAI_WORKER_STALL_MINUTES, default 10)
|
|
106
|
+
*
|
|
107
|
+
* Delivery, in order of preference, never both counted as required:
|
|
108
|
+
* 1. AIBroker `send_to_session` into the orchestrator's terminal — the
|
|
109
|
+
* one-line Agentish-style notification, arriving as a user turn without
|
|
110
|
+
* the orchestrator asking for it. Needs the iTerm identity of the owner,
|
|
111
|
+
* which the status line bridges into the session map (see scope.ts).
|
|
112
|
+
* 2. An append-only event file, <logDir>/supervision/<owner>.events, one
|
|
113
|
+
* JSON line per event. The UserPromptSubmit hook
|
|
114
|
+
* (src/hooks/ts/user-prompt/worker-supervision.ts) surfaces undelivered
|
|
115
|
+
* lines into the session that owns them, so the events reach the model
|
|
116
|
+
* on its next turn even with AIBroker absent.
|
|
117
|
+
*
|
|
118
|
+
* Exactly-once: every event carries a deterministic id and the set of
|
|
119
|
+
* delivered ids per worker is persisted (<logDir>/supervision/state.json), so
|
|
120
|
+
* a daemon restart replays nothing. A first run with no state adopts every
|
|
121
|
+
* already-terminal worker as delivered — supervision reports transitions it
|
|
122
|
+
* observes, not history. Chain stages are separate workers with their own
|
|
123
|
+
* status files and are supervised individually.
|
|
124
|
+
*
|
|
125
|
+
* No model is ever called from here — this is daemon code, and it must stay
|
|
126
|
+
* that way: supervision that bills tokens to watch tokens is a bug.
|
|
127
|
+
*/
|
|
128
|
+
/**
|
|
129
|
+
* The owning session of a worker, or null when nobody claims it (and so
|
|
130
|
+
* nothing to notify): the spawner's claude session id first — that is what
|
|
131
|
+
* the hook knows a session by — else the AIBroker iTerm uuid.
|
|
132
|
+
*/
|
|
133
|
+
function ownershipKey(s) {
|
|
134
|
+
if (s.spawnerSession) return s.spawnerSession;
|
|
135
|
+
if (s.session?.id) return s.session.id;
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
const TERMINAL = [
|
|
139
|
+
"done",
|
|
140
|
+
"failed",
|
|
141
|
+
"killed",
|
|
142
|
+
"lost"
|
|
143
|
+
];
|
|
144
|
+
function isTerminal(s) {
|
|
145
|
+
return TERMINAL.includes(s.state);
|
|
146
|
+
}
|
|
147
|
+
/** Age of a "YYYY-MM-DD HH:MM:SS" stamp in ms, NaN-safe (unparsable → 0). */
|
|
148
|
+
function ageMs(ts, now) {
|
|
149
|
+
const t = Date.parse(ts.replace(" ", "T"));
|
|
150
|
+
if (Number.isNaN(t)) return 0;
|
|
151
|
+
return Math.max(0, now.getTime() - t);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* The stall threshold in minutes from PAI_WORKER_STALL_MINUTES (default 10).
|
|
155
|
+
* Anything unparsible or non-positive falls back to the default — a broken
|
|
156
|
+
* value must not turn supervision off or make it fire every tick.
|
|
157
|
+
*/
|
|
158
|
+
const DEFAULT_STALL_MINUTES = 10;
|
|
159
|
+
function stallMinutesFromEnv(env = process.env) {
|
|
160
|
+
const raw = env.PAI_WORKER_STALL_MINUTES;
|
|
161
|
+
if (raw === void 0 || raw === "") return DEFAULT_STALL_MINUTES;
|
|
162
|
+
const n = Number(raw);
|
|
163
|
+
return Number.isFinite(n) && n > 0 ? n : DEFAULT_STALL_MINUTES;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Event id: `<worker>#<kind>` for the once-per-run terminal kinds, and
|
|
167
|
+
* `<worker>#stalled@<turns>` for stalls — the turn count re-arms the id, so a
|
|
168
|
+
* worker that resumes and stalls again gets a second event while a restart
|
|
169
|
+
* cannot replay the first.
|
|
170
|
+
*/
|
|
171
|
+
function eventId(worker, kind, turns = 0) {
|
|
172
|
+
return kind === "stalled" ? `${worker}#stalled@${turns}` : `${worker}#${kind}`;
|
|
173
|
+
}
|
|
174
|
+
/** One event's one-liner — the exact line the orchestrator reads. */
|
|
175
|
+
function eventText(kind, s, rc, stalledMin) {
|
|
176
|
+
const tail = `- see pai worker replay ${s.id}`;
|
|
177
|
+
if (kind === "finished") return `worker ${s.id} ${s.label} finished rc=0 ${tail}`;
|
|
178
|
+
if (kind === "stalled") return `worker ${s.id} ${s.label} stalled ${stalledMin}m no turns ${tail}`;
|
|
179
|
+
const why = rc === null ? "runner gone" : `rc=${rc}`;
|
|
180
|
+
return `worker ${s.id} ${s.label} failed ${why} ${tail}`;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Detect conditions across a ledger snapshot. Pure: statuses in, events out;
|
|
184
|
+
* dedup against delivered ids is the caller's job (see filterUndelivered).
|
|
185
|
+
* Workers without an owning session are skipped — nobody to notify.
|
|
186
|
+
*/
|
|
187
|
+
function detectSupervisionEvents(statuses, opts) {
|
|
188
|
+
const isAlive = opts.isAlive ?? alive;
|
|
189
|
+
const deadGraceMs = opts.deadGraceMs ?? 15e3;
|
|
190
|
+
const out = [];
|
|
191
|
+
for (const s of statuses) {
|
|
192
|
+
const session = ownershipKey(s);
|
|
193
|
+
if (!session) continue;
|
|
194
|
+
let kind = null;
|
|
195
|
+
let rc = null;
|
|
196
|
+
let stalledMin = null;
|
|
197
|
+
if (isTerminal(s)) if (s.state === "done" && (s.rc ?? 0) === 0) {
|
|
198
|
+
kind = "finished";
|
|
199
|
+
rc = 0;
|
|
200
|
+
} else {
|
|
201
|
+
kind = "failed";
|
|
202
|
+
rc = s.state === "lost" ? null : s.rc;
|
|
203
|
+
}
|
|
204
|
+
else if (!isAlive(s.pid) && ageMs(s.updated, opts.now) > deadGraceMs) {
|
|
205
|
+
kind = "failed";
|
|
206
|
+
rc = null;
|
|
207
|
+
} else if (ageMs(s.updated, opts.now) > opts.stallMs) {
|
|
208
|
+
kind = "stalled";
|
|
209
|
+
stalledMin = Math.floor(ageMs(s.updated, opts.now) / 6e4);
|
|
210
|
+
}
|
|
211
|
+
if (!kind) continue;
|
|
212
|
+
out.push({
|
|
213
|
+
id: eventId(s.id, kind, s.turns),
|
|
214
|
+
ts: nowStamp(opts.now),
|
|
215
|
+
kind,
|
|
216
|
+
worker: s.id,
|
|
217
|
+
label: s.label,
|
|
218
|
+
session,
|
|
219
|
+
rc,
|
|
220
|
+
stalledMin,
|
|
221
|
+
text: eventText(kind, s, rc, stalledMin)
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
return out;
|
|
225
|
+
}
|
|
226
|
+
/** Cap on remembered workers: terminal and delivered is history, not state. */
|
|
227
|
+
const MAX_REMEMBERED_WORKERS = 500;
|
|
228
|
+
function supervisionDirPath(logDir) {
|
|
229
|
+
return join(logDir, "supervision");
|
|
230
|
+
}
|
|
231
|
+
function supervisionStatePath(logDir) {
|
|
232
|
+
return join(supervisionDirPath(logDir), "state.json");
|
|
233
|
+
}
|
|
234
|
+
function supervisionEventsPath(logDir, session) {
|
|
235
|
+
return join(supervisionDirPath(logDir), `${session}.events`);
|
|
236
|
+
}
|
|
237
|
+
/** Receipts of events already pushed into a terminal, one event id per line. */
|
|
238
|
+
function supervisionPushedPath(logDir, session) {
|
|
239
|
+
return join(supervisionDirPath(logDir), `${session}.pushed`);
|
|
240
|
+
}
|
|
241
|
+
function loadSupervisionState(path) {
|
|
242
|
+
if (!existsSync(path)) return {
|
|
243
|
+
state: { delivered: {} },
|
|
244
|
+
fresh: true
|
|
245
|
+
};
|
|
246
|
+
try {
|
|
247
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
248
|
+
if (parsed && typeof parsed === "object" && typeof parsed.delivered === "object") return {
|
|
249
|
+
state: parsed,
|
|
250
|
+
fresh: false
|
|
251
|
+
};
|
|
252
|
+
} catch {}
|
|
253
|
+
return {
|
|
254
|
+
state: { delivered: {} },
|
|
255
|
+
fresh: true
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
function saveSupervisionState(path, state) {
|
|
259
|
+
const dir = dirname(path);
|
|
260
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
261
|
+
const tmp = `${path}.tmp`;
|
|
262
|
+
writeFileSync(tmp, JSON.stringify(state), "utf8");
|
|
263
|
+
renameSync(tmp, path);
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Drop workers the ledger no longer lists and cap the rest (newest ids last —
|
|
267
|
+
* worker ids sort chronologically), so the persisted state stays bounded.
|
|
268
|
+
*/
|
|
269
|
+
function pruneState(state, statuses) {
|
|
270
|
+
const present = new Set(statuses.map((s) => s.id));
|
|
271
|
+
const kept = Object.entries(state.delivered).filter(([id]) => present.has(id)).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).slice(-MAX_REMEMBERED_WORKERS);
|
|
272
|
+
return { delivered: Object.fromEntries(kept) };
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* First run: adopt every already-terminal worker as delivered. Supervision
|
|
276
|
+
* reports the transitions it observes from now on, never a replay of every
|
|
277
|
+
* worker that ever finished before it started.
|
|
278
|
+
*/
|
|
279
|
+
function baselineState(statuses) {
|
|
280
|
+
const delivered = {};
|
|
281
|
+
for (const s of statuses) {
|
|
282
|
+
if (!isTerminal(s) || !ownershipKey(s)) continue;
|
|
283
|
+
delivered[s.id] = [eventId(s.id, "finished"), eventId(s.id, "failed")];
|
|
284
|
+
}
|
|
285
|
+
return { delivered };
|
|
286
|
+
}
|
|
287
|
+
/** The events whose ids the state has not seen yet. */
|
|
288
|
+
function filterUndelivered(events, state) {
|
|
289
|
+
return events.filter((e) => !(state.delivered[e.worker] ?? []).includes(e.id));
|
|
290
|
+
}
|
|
291
|
+
function markDelivered(state, events) {
|
|
292
|
+
for (const e of events) {
|
|
293
|
+
const ids = state.delivered[e.worker] ?? [];
|
|
294
|
+
if (!ids.includes(e.id)) ids.push(e.id);
|
|
295
|
+
state.delivered[e.worker] = ids;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Default push: AIBroker `send_to_session` into the orchestrator's terminal,
|
|
300
|
+
* using the iTerm uuid the worker recorded (`session.id`) or the one the
|
|
301
|
+
* session map bridges for the spawner's claude session. A timeout still
|
|
302
|
+
* delivered (see aibroker-client) counts as delivered; every failure is
|
|
303
|
+
* reported as not-delivered so only the event file carries the event.
|
|
304
|
+
*/
|
|
305
|
+
const aibrokerPush = async (logDir, target, ev) => {
|
|
306
|
+
const iterm = target.iterm ?? (target.claudeSession ? itermForClaudeSession(logDir, target.claudeSession) : null);
|
|
307
|
+
if (!iterm) return false;
|
|
308
|
+
try {
|
|
309
|
+
const { sendToSession } = await import("./aibroker-client-C6m71p6O.mjs");
|
|
310
|
+
const r = await sendToSession(iterm, ev.text);
|
|
311
|
+
return r.ok || r.timedOut === true;
|
|
312
|
+
} catch {
|
|
313
|
+
return false;
|
|
314
|
+
}
|
|
315
|
+
};
|
|
316
|
+
function appendEventFile(logDir, ev) {
|
|
317
|
+
const path = supervisionEventsPath(logDir, ev.session);
|
|
318
|
+
const dir = supervisionDirPath(logDir);
|
|
319
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
320
|
+
appendFileSync(path, JSON.stringify(ev) + "\n", "utf8");
|
|
321
|
+
}
|
|
322
|
+
/** Record that an event reached its owner's terminal — the hook then skips it. */
|
|
323
|
+
function appendPushReceipt(logDir, ev) {
|
|
324
|
+
try {
|
|
325
|
+
appendFileSync(supervisionPushedPath(logDir, ev.session), `${ev.id}\n`, "utf8");
|
|
326
|
+
} catch {}
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* One supervision pass over the ledger: detect, append each new event to its
|
|
330
|
+
* owner's event file, push it best effort, persist the delivered ids. The
|
|
331
|
+
* event file is the durable record — an event is marked delivered only after
|
|
332
|
+
* its line landed there, so a failed tick retries, a repeated one replays
|
|
333
|
+
* nothing.
|
|
334
|
+
*/
|
|
335
|
+
async function runSupervisionTick(logDir, opts = {}) {
|
|
336
|
+
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
337
|
+
const statuses = opts.statuses ?? loadStatuses(logDir);
|
|
338
|
+
const statePath = supervisionStatePath(logDir);
|
|
339
|
+
const loaded = loadSupervisionState(statePath);
|
|
340
|
+
let state = loaded.state;
|
|
341
|
+
if (loaded.fresh) state = baselineState(statuses);
|
|
342
|
+
const pending = filterUndelivered(detectSupervisionEvents(statuses, {
|
|
343
|
+
stallMs: opts.stallMs ?? DEFAULT_STALL_MINUTES * 6e4,
|
|
344
|
+
now,
|
|
345
|
+
...opts.isAlive ? { isAlive: opts.isAlive } : {}
|
|
346
|
+
}), state);
|
|
347
|
+
const written = [];
|
|
348
|
+
for (const ev of pending) {
|
|
349
|
+
appendEventFile(logDir, ev);
|
|
350
|
+
written.push(ev);
|
|
351
|
+
}
|
|
352
|
+
const push = opts.push ?? aibrokerPush;
|
|
353
|
+
const pushed = [];
|
|
354
|
+
for (const ev of written) {
|
|
355
|
+
const owner = statuses.find((s) => s.id === ev.worker);
|
|
356
|
+
const target = {
|
|
357
|
+
claudeSession: owner?.spawnerSession ?? null,
|
|
358
|
+
iterm: owner?.session?.id ?? null
|
|
359
|
+
};
|
|
360
|
+
let ok = false;
|
|
361
|
+
try {
|
|
362
|
+
ok = await push(logDir, target, ev);
|
|
363
|
+
} catch {
|
|
364
|
+
ok = false;
|
|
365
|
+
}
|
|
366
|
+
if (ok) {
|
|
367
|
+
pushed.push(ev);
|
|
368
|
+
appendPushReceipt(logDir, ev);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
markDelivered(state, written);
|
|
372
|
+
saveSupervisionState(statePath, pruneState(state, statuses));
|
|
373
|
+
return {
|
|
374
|
+
events: written,
|
|
375
|
+
pushed
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
|
|
86
379
|
//#endregion
|
|
87
380
|
//#region src/daemon/daemon/scheduler.ts
|
|
88
381
|
/**
|
|
@@ -110,7 +403,7 @@ async function runIndex() {
|
|
|
110
403
|
try {
|
|
111
404
|
process.stderr.write("[pai-daemon] Starting scheduled index run...\n");
|
|
112
405
|
if (storageBackend.backendType === "sqlite") {
|
|
113
|
-
const { SQLiteBackend } = await import("./sqlite-
|
|
406
|
+
const { SQLiteBackend } = await import("./sqlite-Cq3gJcq9.mjs");
|
|
114
407
|
if (storageBackend instanceof SQLiteBackend) {
|
|
115
408
|
const { projects, result } = await indexAll(storageBackend.getRawDb(), registryDb);
|
|
116
409
|
const elapsed = Date.now() - t0;
|
|
@@ -118,7 +411,7 @@ async function runIndex() {
|
|
|
118
411
|
process.stderr.write(`[pai-daemon] Index complete: ${projects} projects, ${result.filesProcessed} files, ${result.chunksCreated} chunks (${elapsed}ms)\n`);
|
|
119
412
|
}
|
|
120
413
|
} else {
|
|
121
|
-
const { indexAllWithBackend } = await import("./indexer-backend-
|
|
414
|
+
const { indexAllWithBackend } = await import("./indexer-backend-BPTzKFZU.mjs");
|
|
122
415
|
const { projects, result } = await indexAllWithBackend(storageBackend, registryDb);
|
|
123
416
|
const elapsed = Date.now() - t0;
|
|
124
417
|
setLastIndexTime(Date.now());
|
|
@@ -145,7 +438,7 @@ async function runVaultIndex() {
|
|
|
145
438
|
process.stderr.write("[pai-daemon] Index/embed in progress, deferring vault index.\n");
|
|
146
439
|
return;
|
|
147
440
|
}
|
|
148
|
-
const { lastVaultIndexTime } = await import("./state-
|
|
441
|
+
const { lastVaultIndexTime } = await import("./state-RXepvbnO.mjs");
|
|
149
442
|
if (lastVaultIndexTime > 0 && Date.now() - lastVaultIndexTime < VAULT_INDEX_MIN_INTERVAL_MS) return;
|
|
150
443
|
let vaultProjectId = daemonConfig.vaultProjectId;
|
|
151
444
|
if (!vaultProjectId) {
|
|
@@ -157,7 +450,7 @@ async function runVaultIndex() {
|
|
|
157
450
|
const t0 = Date.now();
|
|
158
451
|
process.stderr.write("[pai-daemon] Starting vault index run...\n");
|
|
159
452
|
try {
|
|
160
|
-
const { indexVault } = await import("./vault-indexer-
|
|
453
|
+
const { indexVault } = await import("./vault-indexer-mata9S7b.mjs");
|
|
161
454
|
const r = await indexVault(storageBackend, vaultProjectId, daemonConfig.vaultPath);
|
|
162
455
|
const elapsed = Date.now() - t0;
|
|
163
456
|
setLastVaultIndexTime(Date.now());
|
|
@@ -228,11 +521,11 @@ async function runEmbed() {
|
|
|
228
521
|
const rows = registryDb.prepare("SELECT id, slug FROM projects WHERE status = 'active'").all();
|
|
229
522
|
for (const r of rows) projectNames.set(r.id, r.slug);
|
|
230
523
|
} catch {}
|
|
231
|
-
const { embedChunksWithBackend } = await import("./indexer-backend-
|
|
524
|
+
const { embedChunksWithBackend } = await import("./indexer-backend-BPTzKFZU.mjs");
|
|
232
525
|
const count = await embedChunksWithBackend(storageBackend, () => shutdownRequested, projectNames, { maxMillis: 24e4 });
|
|
233
526
|
let vaultEmbedCount = 0;
|
|
234
527
|
if (daemonConfig.vaultPath) try {
|
|
235
|
-
const { SQLiteBackend } = await import("./sqlite-
|
|
528
|
+
const { SQLiteBackend } = await import("./sqlite-Cq3gJcq9.mjs");
|
|
236
529
|
const { openFederation } = await import("./db-O-cyAPfS.mjs");
|
|
237
530
|
const federationDb = openFederation();
|
|
238
531
|
const vaultSqliteBackend = new SQLiteBackend(federationDb);
|
|
@@ -292,17 +585,53 @@ const REGISTRY_SCAN_STARTUP_DELAY_MS = 1e4;
|
|
|
292
585
|
function startRegistryScanScheduler() {
|
|
293
586
|
process.stderr.write("[pai-daemon] Registry scan scheduler: every 30min (first in 10s)\n");
|
|
294
587
|
setTimeout(() => {
|
|
295
|
-
import("./work-queue-worker-
|
|
588
|
+
import("./work-queue-worker-D1p2V-ae.mjs").then(({ enqueueRegistryScan }) => enqueueRegistryScan()).catch((e) => {
|
|
296
589
|
process.stderr.write(`[pai-daemon] Startup registry scan error: ${e}\n`);
|
|
297
590
|
});
|
|
298
591
|
}, REGISTRY_SCAN_STARTUP_DELAY_MS);
|
|
299
592
|
const timer = setInterval(() => {
|
|
300
|
-
import("./work-queue-worker-
|
|
593
|
+
import("./work-queue-worker-D1p2V-ae.mjs").then(({ enqueueRegistryScan }) => enqueueRegistryScan()).catch((e) => {
|
|
301
594
|
process.stderr.write(`[pai-daemon] Scheduled registry scan error: ${e}\n`);
|
|
302
595
|
});
|
|
303
596
|
}, REGISTRY_SCAN_INTERVAL_MS);
|
|
304
597
|
if (timer.unref) timer.unref();
|
|
305
598
|
}
|
|
599
|
+
/** How often the daemon looks at the worker ledger for supervision events. */
|
|
600
|
+
const SUPERVISION_TICK_MS = 3e4;
|
|
601
|
+
/** First supervision pass waits for the first statuses to exist at all. */
|
|
602
|
+
const SUPERVISION_STARTUP_DELAY_MS = 15e3;
|
|
603
|
+
/**
|
|
604
|
+
* Start the worker supervisor: one tick every 30 s over the workers ledger
|
|
605
|
+
* (src/workers/supervision.ts) that pushes finished/failed/stalled events to
|
|
606
|
+
* the owning session — the daemon-side replacement for orchestrator polling.
|
|
607
|
+
* Daemon code only: no model call has any business being here, and none is
|
|
608
|
+
* made. Disabled workers disable the supervisor with it.
|
|
609
|
+
*/
|
|
610
|
+
function startWorkerSupervisor() {
|
|
611
|
+
let enabled = false;
|
|
612
|
+
try {
|
|
613
|
+
enabled = readWorkersSection().workers.enabled;
|
|
614
|
+
} catch (e) {
|
|
615
|
+
process.stderr.write(`[pai-daemon] Worker supervisor: not started (${e instanceof Error ? e.message : String(e)})\n`);
|
|
616
|
+
return;
|
|
617
|
+
}
|
|
618
|
+
if (!enabled) {
|
|
619
|
+
process.stderr.write("[pai-daemon] Worker supervisor: disabled (workers are off)\n");
|
|
620
|
+
return;
|
|
621
|
+
}
|
|
622
|
+
const tick = () => {
|
|
623
|
+
runSupervisionTick(workersLogDir(readWorkersSection().workers), { stallMs: stallMinutesFromEnv() * 6e4 }).then((r) => {
|
|
624
|
+
for (const ev of r.events) process.stderr.write(`[pai-daemon] Supervision: ${ev.text}\n`);
|
|
625
|
+
}).catch((e) => {
|
|
626
|
+
process.stderr.write(`[pai-daemon] Supervision tick error: ${e instanceof Error ? e.message : String(e)}\n`);
|
|
627
|
+
});
|
|
628
|
+
};
|
|
629
|
+
const first = setTimeout(tick, SUPERVISION_STARTUP_DELAY_MS);
|
|
630
|
+
if (first.unref) first.unref();
|
|
631
|
+
const timer = setInterval(tick, SUPERVISION_TICK_MS);
|
|
632
|
+
if (timer.unref) timer.unref();
|
|
633
|
+
process.stderr.write(`[pai-daemon] Worker supervisor: every ${Math.round(SUPERVISION_TICK_MS / 1e3)}s\n`);
|
|
634
|
+
}
|
|
306
635
|
|
|
307
636
|
//#endregion
|
|
308
637
|
//#region src/observations/store.ts
|
|
@@ -607,7 +936,7 @@ async function dispatchTool(method, params) {
|
|
|
607
936
|
case "zettel_themes":
|
|
608
937
|
case "zettel_god_notes":
|
|
609
938
|
case "zettel_communities": {
|
|
610
|
-
const { toolZettelExplore, toolZettelHealth, toolZettelSurprise, toolZettelSuggest, toolZettelConverse, toolZettelThemes, toolZettelGodNotes, toolZettelCommunities } = await import("./tools-
|
|
939
|
+
const { toolZettelExplore, toolZettelHealth, toolZettelSurprise, toolZettelSuggest, toolZettelConverse, toolZettelThemes, toolZettelGodNotes, toolZettelCommunities } = await import("./tools-BW3NLMPk.mjs");
|
|
611
940
|
switch (method) {
|
|
612
941
|
case "zettel_explore": return toolZettelExplore(storageBackend, p);
|
|
613
942
|
case "zettel_health": return toolZettelHealth(storageBackend, p);
|
|
@@ -621,27 +950,27 @@ async function dispatchTool(method, params) {
|
|
|
621
950
|
break;
|
|
622
951
|
}
|
|
623
952
|
case "graph_clusters": {
|
|
624
|
-
const { handleGraphClusters } = await import("./clusters-
|
|
953
|
+
const { handleGraphClusters } = await import("./clusters-j0ZuNYp9.mjs");
|
|
625
954
|
return handleGraphClusters(storageBackend.getPool?.() ?? null, storageBackend, p);
|
|
626
955
|
}
|
|
627
956
|
case "graph_neighborhood": {
|
|
628
|
-
const { handleGraphNeighborhood } = await import("./neighborhood-
|
|
957
|
+
const { handleGraphNeighborhood } = await import("./neighborhood-CM7Jgb51.mjs");
|
|
629
958
|
return handleGraphNeighborhood(storageBackend.getPool?.() ?? null, storageBackend, p);
|
|
630
959
|
}
|
|
631
960
|
case "graph_note_context": {
|
|
632
|
-
const { handleGraphNoteContext } = await import("./note-context-
|
|
961
|
+
const { handleGraphNoteContext } = await import("./note-context-DCwE2A-M.mjs");
|
|
633
962
|
return handleGraphNoteContext(storageBackend.getPool?.() ?? null, storageBackend, p);
|
|
634
963
|
}
|
|
635
964
|
case "graph_trace": {
|
|
636
|
-
const { handleGraphTrace } = await import("./trace-
|
|
965
|
+
const { handleGraphTrace } = await import("./trace-u4hT-pLD.mjs");
|
|
637
966
|
return handleGraphTrace(storageBackend, p);
|
|
638
967
|
}
|
|
639
968
|
case "graph_latent_ideas": {
|
|
640
|
-
const { handleGraphLatentIdeas } = await import("./latent-ideas-
|
|
969
|
+
const { handleGraphLatentIdeas } = await import("./latent-ideas-CtSca4qG.mjs");
|
|
641
970
|
return handleGraphLatentIdeas(storageBackend, p);
|
|
642
971
|
}
|
|
643
972
|
case "idea_materialize": {
|
|
644
|
-
const { handleIdeaMaterialize } = await import("./latent-ideas-
|
|
973
|
+
const { handleIdeaMaterialize } = await import("./latent-ideas-CtSca4qG.mjs");
|
|
645
974
|
if (!daemonConfig.vaultPath) throw new Error("idea_materialize requires vaultPath to be configured in the daemon config");
|
|
646
975
|
return handleIdeaMaterialize(p, daemonConfig.vaultPath);
|
|
647
976
|
}
|
|
@@ -649,7 +978,7 @@ async function dispatchTool(method, params) {
|
|
|
649
978
|
case "kg_query":
|
|
650
979
|
case "kg_invalidate":
|
|
651
980
|
case "kg_contradictions": {
|
|
652
|
-
const { toolKgAdd, toolKgQuery, toolKgInvalidate, toolKgContradictions } = await import("./tools-
|
|
981
|
+
const { toolKgAdd, toolKgQuery, toolKgInvalidate, toolKgContradictions } = await import("./tools-BW3NLMPk.mjs");
|
|
653
982
|
const pgPool = storageBackend.getPool?.() ?? null;
|
|
654
983
|
if (!pgPool) throw new Error(`${method} requires a Postgres storage backend`);
|
|
655
984
|
switch (method) {
|
|
@@ -661,7 +990,7 @@ async function dispatchTool(method, params) {
|
|
|
661
990
|
break;
|
|
662
991
|
}
|
|
663
992
|
case "memory_tunnels": {
|
|
664
|
-
const { toolMemoryTunnels } = await import("./tools-
|
|
993
|
+
const { toolMemoryTunnels } = await import("./tools-BW3NLMPk.mjs");
|
|
665
994
|
return toolMemoryTunnels(registryDb, storageBackend, p);
|
|
666
995
|
}
|
|
667
996
|
case "memory_feedback": {
|
|
@@ -1312,7 +1641,7 @@ async function serve(config) {
|
|
|
1312
1641
|
process.stderr.write("[pai-daemon] Starting daemon...\n");
|
|
1313
1642
|
process.stderr.write(`[pai-daemon] Socket: ${config.socketPath}\n`);
|
|
1314
1643
|
process.stderr.write(`[pai-daemon] Storage backend: ${config.storageBackend}\n`);
|
|
1315
|
-
const { notificationConfig } = await import("./state-
|
|
1644
|
+
const { notificationConfig } = await import("./state-RXepvbnO.mjs");
|
|
1316
1645
|
process.stderr.write(`[pai-daemon] Notification mode: ${notificationConfig.mode}\n`);
|
|
1317
1646
|
try {
|
|
1318
1647
|
setPriority(process.pid, 10);
|
|
@@ -1328,6 +1657,7 @@ async function serve(config) {
|
|
|
1328
1657
|
}
|
|
1329
1658
|
const server = await startIpcServer(config.socketPath);
|
|
1330
1659
|
startRegistryScanScheduler();
|
|
1660
|
+
startWorkerSupervisor();
|
|
1331
1661
|
createStorageBackend(config, { waitForPostgres: true }).then((backend) => {
|
|
1332
1662
|
setStorageBackend(backend);
|
|
1333
1663
|
process.stderr.write(`[pai-daemon] Federation backend: ${backend.backendType}\n`);
|
|
@@ -1376,4 +1706,4 @@ async function serve(config) {
|
|
|
1376
1706
|
|
|
1377
1707
|
//#endregion
|
|
1378
1708
|
export { serve as t };
|
|
1379
|
-
//# sourceMappingURL=daemon-
|
|
1709
|
+
//# sourceMappingURL=daemon-DsvP8KMy.mjs.map
|