@useorgx/openclaw-plugin 0.4.8 → 0.7.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.
Files changed (284) hide show
  1. package/README.md +35 -0
  2. package/dashboard/dist/assets/BJgZIVUQ.js +53 -0
  3. package/dashboard/dist/assets/BJgZIVUQ.js.br +0 -0
  4. package/dashboard/dist/assets/BJgZIVUQ.js.gz +0 -0
  5. package/dashboard/dist/assets/BXWDRGm-.js +1 -0
  6. package/dashboard/dist/assets/BXWDRGm-.js.br +0 -0
  7. package/dashboard/dist/assets/BXWDRGm-.js.gz +0 -0
  8. package/dashboard/dist/assets/BgOYB78t.js +4 -0
  9. package/dashboard/dist/assets/BgOYB78t.js.br +0 -0
  10. package/dashboard/dist/assets/BgOYB78t.js.gz +0 -0
  11. package/dashboard/dist/assets/C-KIc3Wc.js.br +0 -0
  12. package/dashboard/dist/assets/C-KIc3Wc.js.gz +0 -0
  13. package/dashboard/dist/assets/CE38zU4U.js +1 -0
  14. package/dashboard/dist/assets/CE38zU4U.js.br +0 -0
  15. package/dashboard/dist/assets/CE38zU4U.js.gz +0 -0
  16. package/dashboard/dist/assets/CFGKRAzG.js +1 -0
  17. package/dashboard/dist/assets/CFGKRAzG.js.br +0 -0
  18. package/dashboard/dist/assets/CFGKRAzG.js.gz +0 -0
  19. package/dashboard/dist/assets/CGGR2GZh.js +1 -0
  20. package/dashboard/dist/assets/CGGR2GZh.js.br +0 -0
  21. package/dashboard/dist/assets/CGGR2GZh.js.gz +0 -0
  22. package/dashboard/dist/assets/CL_wXqR7.js +1 -0
  23. package/dashboard/dist/assets/CL_wXqR7.js.br +0 -0
  24. package/dashboard/dist/assets/CL_wXqR7.js.gz +0 -0
  25. package/dashboard/dist/assets/CPFiTmlw.js +8 -0
  26. package/dashboard/dist/assets/CPFiTmlw.js.br +0 -0
  27. package/dashboard/dist/assets/CPFiTmlw.js.gz +0 -0
  28. package/dashboard/dist/assets/CZZTvkQZ.js +1 -0
  29. package/dashboard/dist/assets/CZZTvkQZ.js.br +0 -0
  30. package/dashboard/dist/assets/CZZTvkQZ.js.gz +0 -0
  31. package/dashboard/dist/assets/{CpJsfbXo.js → CxQ08qFN.js} +2 -2
  32. package/dashboard/dist/assets/CxQ08qFN.js.br +0 -0
  33. package/dashboard/dist/assets/CxQ08qFN.js.gz +0 -0
  34. package/dashboard/dist/assets/D-bf6hEI.js +213 -0
  35. package/dashboard/dist/assets/D-bf6hEI.js.br +0 -0
  36. package/dashboard/dist/assets/D-bf6hEI.js.gz +0 -0
  37. package/dashboard/dist/assets/DG6y9wJI.js +2 -0
  38. package/dashboard/dist/assets/DG6y9wJI.js.br +0 -0
  39. package/dashboard/dist/assets/DG6y9wJI.js.gz +0 -0
  40. package/dashboard/dist/assets/DNxKz-GV.js +1 -0
  41. package/dashboard/dist/assets/DNxKz-GV.js.br +0 -0
  42. package/dashboard/dist/assets/DNxKz-GV.js.gz +0 -0
  43. package/dashboard/dist/assets/DW_rKUic.js +11 -0
  44. package/dashboard/dist/assets/DW_rKUic.js.br +0 -0
  45. package/dashboard/dist/assets/DW_rKUic.js.gz +0 -0
  46. package/dashboard/dist/assets/DbNoijHm.js +1 -0
  47. package/dashboard/dist/assets/DbNoijHm.js.br +0 -0
  48. package/dashboard/dist/assets/DbNoijHm.js.gz +0 -0
  49. package/dashboard/dist/assets/DjcdE6jC.js +2 -0
  50. package/dashboard/dist/assets/DjcdE6jC.js.br +0 -0
  51. package/dashboard/dist/assets/DjcdE6jC.js.gz +0 -0
  52. package/dashboard/dist/assets/FZYuCDnt.js +1 -0
  53. package/dashboard/dist/assets/FZYuCDnt.js.br +0 -0
  54. package/dashboard/dist/assets/FZYuCDnt.js.gz +0 -0
  55. package/dashboard/dist/assets/PAUiij_z.js +1 -0
  56. package/dashboard/dist/assets/PAUiij_z.js.br +0 -0
  57. package/dashboard/dist/assets/PAUiij_z.js.gz +0 -0
  58. package/dashboard/dist/assets/cNrhgGc1.js +8 -0
  59. package/dashboard/dist/assets/cNrhgGc1.js.br +0 -0
  60. package/dashboard/dist/assets/cNrhgGc1.js.gz +0 -0
  61. package/dashboard/dist/assets/h5biQs2I.css +1 -0
  62. package/dashboard/dist/assets/h5biQs2I.css.br +0 -0
  63. package/dashboard/dist/assets/h5biQs2I.css.gz +0 -0
  64. package/dashboard/dist/assets/ic2FaMnh.js +1 -0
  65. package/dashboard/dist/assets/ic2FaMnh.js.br +0 -0
  66. package/dashboard/dist/assets/ic2FaMnh.js.gz +0 -0
  67. package/dashboard/dist/assets/nByHNHoW.js +1 -0
  68. package/dashboard/dist/assets/nByHNHoW.js.br +0 -0
  69. package/dashboard/dist/assets/nByHNHoW.js.gz +0 -0
  70. package/dashboard/dist/assets/qm8xLgv-.css +1 -0
  71. package/dashboard/dist/assets/qm8xLgv-.css.br +0 -0
  72. package/dashboard/dist/assets/qm8xLgv-.css.gz +0 -0
  73. package/dashboard/dist/assets/tS9mbYZi.js +1 -0
  74. package/dashboard/dist/assets/tS9mbYZi.js.br +0 -0
  75. package/dashboard/dist/assets/tS9mbYZi.js.gz +0 -0
  76. package/dashboard/dist/brand/anthropic-mark.svg.br +0 -0
  77. package/dashboard/dist/brand/anthropic-mark.svg.gz +0 -0
  78. package/dashboard/dist/brand/openai-mark.svg.br +0 -0
  79. package/dashboard/dist/brand/openai-mark.svg.gz +0 -0
  80. package/dashboard/dist/brand/openclaw-mark.svg.br +0 -0
  81. package/dashboard/dist/brand/openclaw-mark.svg.gz +0 -0
  82. package/dashboard/dist/brand/xandy-orchestrator.png +0 -0
  83. package/dashboard/dist/index.html +7 -5
  84. package/dashboard/dist/index.html.br +0 -0
  85. package/dashboard/dist/index.html.gz +0 -0
  86. package/dist/activity-actor-fields.js +26 -4
  87. package/dist/activity-store.js +38 -26
  88. package/dist/agent-context-store.js +84 -42
  89. package/dist/agent-run-store.js +49 -28
  90. package/dist/agent-suite.d.ts +9 -0
  91. package/dist/agent-suite.js +150 -17
  92. package/dist/artifacts/artifact-domain-schemas.d.ts +66 -0
  93. package/dist/artifacts/artifact-domain-schemas.js +357 -0
  94. package/dist/artifacts/register-artifact.d.ts +4 -3
  95. package/dist/artifacts/register-artifact.js +170 -57
  96. package/dist/auth/flows.d.ts +47 -0
  97. package/dist/auth/flows.js +169 -0
  98. package/dist/auth-store.js +6 -26
  99. package/dist/byok-store.js +5 -19
  100. package/dist/chat-store.d.ts +157 -0
  101. package/dist/chat-store.js +586 -0
  102. package/dist/cli/orgx.d.ts +66 -0
  103. package/dist/cli/orgx.js +102 -0
  104. package/dist/config/refresh.d.ts +32 -0
  105. package/dist/config/refresh.js +55 -0
  106. package/dist/config/resolution.d.ts +37 -0
  107. package/dist/config/resolution.js +178 -0
  108. package/dist/contracts/client.d.ts +43 -3
  109. package/dist/contracts/client.js +159 -30
  110. package/dist/contracts/retro-schema.d.ts +81 -0
  111. package/dist/contracts/retro-schema.js +80 -0
  112. package/dist/contracts/shared-types.d.ts +306 -0
  113. package/dist/contracts/shared-types.js +179 -0
  114. package/dist/contracts/skill-pack-schema.d.ts +192 -0
  115. package/dist/contracts/skill-pack-schema.js +180 -0
  116. package/dist/contracts/types.d.ts +224 -132
  117. package/dist/contracts/types.js +5 -0
  118. package/dist/entities/auto-assignment.d.ts +36 -0
  119. package/dist/entities/auto-assignment.js +141 -0
  120. package/dist/entity-comment-store.js +5 -25
  121. package/dist/event-sanitization.d.ts +11 -0
  122. package/dist/event-sanitization.js +113 -0
  123. package/dist/fs-utils.js +13 -1
  124. package/dist/gateway-watchdog.d.ts +5 -0
  125. package/dist/gateway-watchdog.js +50 -0
  126. package/dist/hash-utils.d.ts +2 -0
  127. package/dist/hash-utils.js +12 -0
  128. package/dist/hooks/post-reporting-event.mjs +1 -5
  129. package/dist/http/helpers/activity-headline.d.ts +10 -0
  130. package/dist/http/helpers/activity-headline.js +73 -0
  131. package/dist/http/helpers/artifact-fallback.d.ts +13 -0
  132. package/dist/http/helpers/artifact-fallback.js +148 -0
  133. package/dist/http/helpers/auto-continue-engine.d.ts +486 -0
  134. package/dist/http/helpers/auto-continue-engine.js +3563 -0
  135. package/dist/http/helpers/autopilot-operations.d.ts +176 -0
  136. package/dist/http/helpers/autopilot-operations.js +554 -0
  137. package/dist/http/helpers/autopilot-runtime.d.ts +43 -0
  138. package/dist/http/helpers/autopilot-runtime.js +607 -0
  139. package/dist/http/helpers/autopilot-slice-utils.d.ts +56 -0
  140. package/dist/http/helpers/autopilot-slice-utils.js +899 -0
  141. package/dist/http/helpers/decision-mapper.d.ts +52 -0
  142. package/dist/http/helpers/decision-mapper.js +260 -0
  143. package/dist/http/helpers/dispatch-lifecycle.d.ts +119 -0
  144. package/dist/http/helpers/dispatch-lifecycle.js +809 -0
  145. package/dist/http/helpers/hash-utils.d.ts +1 -0
  146. package/dist/http/helpers/hash-utils.js +1 -0
  147. package/dist/http/helpers/kickoff-context.d.ts +12 -0
  148. package/dist/http/helpers/kickoff-context.js +228 -0
  149. package/dist/http/helpers/llm-client.d.ts +47 -0
  150. package/dist/http/helpers/llm-client.js +256 -0
  151. package/dist/http/helpers/mission-control.d.ts +193 -0
  152. package/dist/http/helpers/mission-control.js +1383 -0
  153. package/dist/http/helpers/openclaw-cli.d.ts +37 -0
  154. package/dist/http/helpers/openclaw-cli.js +283 -0
  155. package/dist/http/helpers/runtime-sse.d.ts +20 -0
  156. package/dist/http/helpers/runtime-sse.js +110 -0
  157. package/dist/http/helpers/sentinel-catalog.d.ts +23 -0
  158. package/dist/http/helpers/sentinel-catalog.js +193 -0
  159. package/dist/http/helpers/session-classification.d.ts +9 -0
  160. package/dist/http/helpers/session-classification.js +564 -0
  161. package/dist/http/helpers/slice-experience-v2.d.ts +137 -0
  162. package/dist/http/helpers/slice-experience-v2.js +677 -0
  163. package/dist/http/helpers/slice-run-projections.d.ts +72 -0
  164. package/dist/http/helpers/slice-run-projections.js +860 -0
  165. package/dist/http/helpers/triage-mapper.d.ts +43 -0
  166. package/dist/http/helpers/triage-mapper.js +549 -0
  167. package/dist/http/helpers/value-utils.d.ts +6 -0
  168. package/dist/http/helpers/value-utils.js +72 -0
  169. package/dist/http/helpers/workspace-scope.d.ts +15 -0
  170. package/dist/http/helpers/workspace-scope.js +170 -0
  171. package/dist/http/index.d.ts +88 -0
  172. package/dist/http/index.js +3610 -0
  173. package/dist/http/router.d.ts +23 -0
  174. package/dist/http/router.js +23 -0
  175. package/dist/http/routes/agent-control.d.ts +79 -0
  176. package/dist/http/routes/agent-control.js +684 -0
  177. package/dist/http/routes/agent-suite.d.ts +38 -0
  178. package/dist/http/routes/agent-suite.js +397 -0
  179. package/dist/http/routes/agents-catalog.d.ts +40 -0
  180. package/dist/http/routes/agents-catalog.js +128 -0
  181. package/dist/http/routes/billing.d.ts +23 -0
  182. package/dist/http/routes/billing.js +55 -0
  183. package/dist/http/routes/chat.d.ts +19 -0
  184. package/dist/http/routes/chat.js +522 -0
  185. package/dist/http/routes/debug.d.ts +14 -0
  186. package/dist/http/routes/debug.js +21 -0
  187. package/dist/http/routes/decision-actions.d.ts +20 -0
  188. package/dist/http/routes/decision-actions.js +103 -0
  189. package/dist/http/routes/delegation.d.ts +19 -0
  190. package/dist/http/routes/delegation.js +32 -0
  191. package/dist/http/routes/dispatch-gateway-envelope.d.ts +25 -0
  192. package/dist/http/routes/dispatch-gateway-envelope.js +26 -0
  193. package/dist/http/routes/entities.d.ts +63 -0
  194. package/dist/http/routes/entities.js +440 -0
  195. package/dist/http/routes/entity-dynamic.d.ts +25 -0
  196. package/dist/http/routes/entity-dynamic.js +191 -0
  197. package/dist/http/routes/health.d.ts +22 -0
  198. package/dist/http/routes/health.js +49 -0
  199. package/dist/http/routes/live-legacy.d.ts +115 -0
  200. package/dist/http/routes/live-legacy.js +112 -0
  201. package/dist/http/routes/live-misc.d.ts +81 -0
  202. package/dist/http/routes/live-misc.js +426 -0
  203. package/dist/http/routes/live-snapshot.d.ts +136 -0
  204. package/dist/http/routes/live-snapshot.js +916 -0
  205. package/dist/http/routes/live-terminal.d.ts +11 -0
  206. package/dist/http/routes/live-terminal.js +261 -0
  207. package/dist/http/routes/live-triage.d.ts +61 -0
  208. package/dist/http/routes/live-triage.js +248 -0
  209. package/dist/http/routes/mission-control-actions.d.ts +131 -0
  210. package/dist/http/routes/mission-control-actions.js +1791 -0
  211. package/dist/http/routes/mission-control-read.d.ts +73 -0
  212. package/dist/http/routes/mission-control-read.js +1640 -0
  213. package/dist/http/routes/onboarding.d.ts +34 -0
  214. package/dist/http/routes/onboarding.js +101 -0
  215. package/dist/http/routes/realtime-orchestrator.d.ts +10 -0
  216. package/dist/http/routes/realtime-orchestrator.js +74 -0
  217. package/dist/http/routes/run-control.d.ts +27 -0
  218. package/dist/http/routes/run-control.js +96 -0
  219. package/dist/http/routes/runtime-hooks.d.ts +69 -0
  220. package/dist/http/routes/runtime-hooks.js +437 -0
  221. package/dist/http/routes/sentinels-catalog.d.ts +7 -0
  222. package/dist/http/routes/sentinels-catalog.js +24 -0
  223. package/dist/http/routes/settings-byok.d.ts +23 -0
  224. package/dist/http/routes/settings-byok.js +163 -0
  225. package/dist/http/routes/summary.d.ts +18 -0
  226. package/dist/http/routes/summary.js +49 -0
  227. package/dist/http/routes/usage.d.ts +24 -0
  228. package/dist/http/routes/usage.js +362 -0
  229. package/dist/http/routes/work-artifacts.d.ts +9 -0
  230. package/dist/http/routes/work-artifacts.js +55 -0
  231. package/dist/http/shared-state.d.ts +16 -0
  232. package/dist/http/shared-state.js +1 -0
  233. package/dist/http-handler.d.ts +1 -88
  234. package/dist/http-handler.js +1 -10605
  235. package/dist/index.js +287 -2284
  236. package/dist/json-utils.d.ts +1 -0
  237. package/dist/json-utils.js +8 -0
  238. package/dist/local-openclaw.js +29 -6
  239. package/dist/mcp-client-setup.js +3 -3
  240. package/dist/mcp-http-handler.js +33 -59
  241. package/dist/next-up-queue-store.d.ts +16 -1
  242. package/dist/next-up-queue-store.js +93 -25
  243. package/dist/outbox.d.ts +5 -0
  244. package/dist/outbox.js +113 -9
  245. package/dist/paths.js +24 -5
  246. package/dist/reporting/rollups.d.ts +53 -0
  247. package/dist/reporting/rollups.js +148 -0
  248. package/dist/retro/domain-templates.d.ts +45 -0
  249. package/dist/retro/domain-templates.js +297 -0
  250. package/dist/retro/quality-rubric.d.ts +33 -0
  251. package/dist/retro/quality-rubric.js +213 -0
  252. package/dist/runtime-cleanup.d.ts +18 -0
  253. package/dist/runtime-cleanup.js +87 -0
  254. package/dist/runtime-instance-store.js +5 -31
  255. package/dist/services/background.d.ts +34 -0
  256. package/dist/services/background.js +45 -0
  257. package/dist/services/experiment-randomization.d.ts +21 -0
  258. package/dist/services/experiment-randomization.js +63 -0
  259. package/dist/services/instrumentation.d.ts +29 -0
  260. package/dist/services/instrumentation.js +136 -0
  261. package/dist/skill-pack-state.d.ts +36 -5
  262. package/dist/skill-pack-state.js +273 -29
  263. package/dist/snapshot-store.js +5 -25
  264. package/dist/stores/json-store.d.ts +11 -0
  265. package/dist/stores/json-store.js +42 -0
  266. package/dist/sync/local-agent-telemetry.d.ts +13 -0
  267. package/dist/sync/local-agent-telemetry.js +128 -0
  268. package/dist/sync/outbox-replay.d.ts +55 -0
  269. package/dist/sync/outbox-replay.js +621 -0
  270. package/dist/team-context-store.d.ts +23 -0
  271. package/dist/team-context-store.js +116 -0
  272. package/dist/telemetry/posthog.js +4 -2
  273. package/dist/tools/core-tools.d.ts +72 -0
  274. package/dist/tools/core-tools.js +2270 -0
  275. package/dist/types.d.ts +2 -0
  276. package/dist/types.js +2 -0
  277. package/dist/worker-supervisor.js +23 -0
  278. package/package.json +14 -4
  279. package/dashboard/dist/assets/B3ziCA02.js +0 -8
  280. package/dashboard/dist/assets/BNeJ0kpF.js +0 -1
  281. package/dashboard/dist/assets/BzkiMPmM.js +0 -215
  282. package/dashboard/dist/assets/CUV9IHHi.js +0 -1
  283. package/dashboard/dist/assets/Ie7d9Iq2.css +0 -1
  284. package/dashboard/dist/assets/sAhvFnpk.js +0 -4
@@ -0,0 +1,437 @@
1
+ import { backupCorruptFileSync, writeFileAtomicSync } from "../../fs-utils.js";
2
+ import { readOpenClawGatewayPort, readOpenClawSettingsSnapshot } from "../../openclaw-settings.js";
3
+ import { getOrgxPluginConfigDir } from "../../paths.js";
4
+ import { existsSync, mkdirSync, readFileSync } from "node:fs";
5
+ import { dirname, join, resolve } from "node:path";
6
+ import { homedir } from "node:os";
7
+ import { fileURLToPath } from "node:url";
8
+ export function registerRuntimeHookRoutes(router, deps) {
9
+ async function renderRuntimeHookConfig(res) {
10
+ try {
11
+ const snapshot = readOpenClawSettingsSnapshot();
12
+ const port = readOpenClawGatewayPort(snapshot.raw);
13
+ const runtimeHookUrl = `http://127.0.0.1:${port}/orgx/api/hooks/runtime`;
14
+ const hookToken = deps.resolveRuntimeHookToken();
15
+ const hooksDir = join(getOrgxPluginConfigDir(), "hooks");
16
+ const hookScriptPath = join(hooksDir, "post-reporting-event.mjs");
17
+ const hookScriptInstalled = existsSync(hookScriptPath);
18
+ const codexHome = (process.env.CODEX_HOME ?? "").trim();
19
+ const codexCandidates = [
20
+ codexHome ? join(codexHome, "config.toml") : null,
21
+ join(homedir(), ".codex", "config.toml"),
22
+ join(homedir(), ".config", "codex", "config.toml"),
23
+ ].filter(Boolean);
24
+ const codexConfigPath = codexCandidates.find((candidate) => existsSync(candidate)) ??
25
+ (codexCandidates[0] ?? null);
26
+ let codexInstalled = false;
27
+ let codexHasNotify = false;
28
+ if (codexConfigPath && existsSync(codexConfigPath)) {
29
+ const raw = readFileSync(codexConfigPath, "utf8");
30
+ codexHasNotify = /^\s*notify\s*=/m.test(raw);
31
+ codexInstalled =
32
+ raw.includes("post-reporting-event.mjs") && raw.includes("--source_client=codex");
33
+ }
34
+ const codexNotifyConflict = Boolean(codexHasNotify && !codexInstalled);
35
+ const claudeCandidates = [
36
+ join(homedir(), ".claude", "settings.json"),
37
+ join(homedir(), ".config", "claude", "settings.json"),
38
+ ];
39
+ const claudeSettingsPath = claudeCandidates.find((candidate) => existsSync(candidate)) ?? claudeCandidates[0];
40
+ let claudeInstalled = false;
41
+ if (claudeSettingsPath && existsSync(claudeSettingsPath)) {
42
+ const raw = readFileSync(claudeSettingsPath, "utf8");
43
+ claudeInstalled =
44
+ raw.includes("post-reporting-event.mjs") &&
45
+ raw.includes("--source_client=claude-code");
46
+ }
47
+ deps.sendJson(res, 200, {
48
+ ok: true,
49
+ runtimeHookUrl,
50
+ hookToken,
51
+ hookTokenHint: deps.maskSecret(hookToken),
52
+ paths: {
53
+ hookScriptPath,
54
+ codexConfigPath,
55
+ claudeSettingsPath,
56
+ },
57
+ installed: {
58
+ hookScript: hookScriptInstalled,
59
+ codex: codexInstalled,
60
+ claudeCode: claudeInstalled,
61
+ },
62
+ conflicts: {
63
+ codexNotify: codexNotifyConflict,
64
+ },
65
+ });
66
+ }
67
+ catch (err) {
68
+ deps.sendJson(res, 500, {
69
+ ok: false,
70
+ error: deps.safeErrorMessage(err),
71
+ });
72
+ }
73
+ }
74
+ router.add("GET", "hooks/runtime/config", async ({ res }) => renderRuntimeHookConfig(res), "Get runtime hook wiring config");
75
+ router.add("HEAD", "hooks/runtime/config", async ({ res }) => renderRuntimeHookConfig(res), "Get runtime hook wiring config (HEAD)");
76
+ router.add("POST", "hooks/runtime/setup", async ({ req, res }) => {
77
+ try {
78
+ const payloadRecord = await deps.parseJsonRequest(req);
79
+ const requestedTargets = Array.isArray(payloadRecord.targets)
80
+ ? payloadRecord.targets
81
+ : [];
82
+ const requested = requestedTargets
83
+ .map((value) => typeof value === "string" ? value.trim().toLowerCase() : "")
84
+ .filter((value) => value.length > 0);
85
+ const targets = new Set();
86
+ for (const value of requested) {
87
+ if (value === "codex")
88
+ targets.add("codex");
89
+ if (value === "claude" || value === "claude-code" || value === "claude_code") {
90
+ targets.add("claude-code");
91
+ }
92
+ }
93
+ if (targets.size === 0) {
94
+ targets.add("codex");
95
+ targets.add("claude-code");
96
+ }
97
+ const snapshot = readOpenClawSettingsSnapshot();
98
+ const port = readOpenClawGatewayPort(snapshot.raw);
99
+ const runtimeHookUrl = `http://127.0.0.1:${port}/orgx/api/hooks/runtime`;
100
+ const hookToken = deps.resolveRuntimeHookToken();
101
+ const hooksDir = join(getOrgxPluginConfigDir(), "hooks");
102
+ mkdirSync(hooksDir, { recursive: true, mode: 0o700 });
103
+ const hookScriptPath = join(hooksDir, "post-reporting-event.mjs");
104
+ const handlerFilename = fileURLToPath(import.meta.url);
105
+ const distDir = resolve(join(handlerFilename, ".."));
106
+ const bundledScriptPath = resolve(distDir, "hooks", "post-reporting-event.mjs");
107
+ const fallbackScriptPath = resolve(distDir, "..", "templates", "hooks", "scripts", "post-reporting-event.mjs");
108
+ let scriptContent = "";
109
+ let hookScriptSourcePath = bundledScriptPath;
110
+ try {
111
+ scriptContent = readFileSync(bundledScriptPath, "utf8");
112
+ }
113
+ catch {
114
+ hookScriptSourcePath = fallbackScriptPath;
115
+ scriptContent = readFileSync(fallbackScriptPath, "utf8");
116
+ }
117
+ writeFileAtomicSync(hookScriptPath, scriptContent, {
118
+ mode: 0o700,
119
+ encoding: "utf8",
120
+ });
121
+ const result = {
122
+ ok: true,
123
+ runtimeHookUrl,
124
+ hookTokenHint: deps.maskSecret(hookToken),
125
+ hookScriptPath,
126
+ hookScriptSourcePath,
127
+ targets: {
128
+ codex: targets.has("codex"),
129
+ claudeCode: targets.has("claude-code"),
130
+ },
131
+ codex: {
132
+ path: null,
133
+ installed: false,
134
+ conflict: false,
135
+ },
136
+ claudeCode: {
137
+ path: null,
138
+ installed: false,
139
+ },
140
+ };
141
+ if (targets.has("codex")) {
142
+ const codexHome = (process.env.CODEX_HOME ?? "").trim();
143
+ const codexCandidates = [
144
+ codexHome ? join(codexHome, "config.toml") : null,
145
+ join(homedir(), ".codex", "config.toml"),
146
+ join(homedir(), ".config", "codex", "config.toml"),
147
+ ].filter(Boolean);
148
+ const codexConfigPath = codexCandidates.find((candidate) => existsSync(candidate)) ??
149
+ codexCandidates[0];
150
+ result.codex.path = codexConfigPath;
151
+ const notifySnippet = [
152
+ "",
153
+ "# OrgX runtime telemetry (installed by OpenClaw plugin)",
154
+ "notify = [",
155
+ ' "node",',
156
+ ` "${hookScriptPath}",`,
157
+ ' "--event=heartbeat",',
158
+ ' "--source_client=codex",',
159
+ ' "--phase=execution",',
160
+ ' "--message=Codex heartbeat",',
161
+ ` "--runtime_hook_url=${runtimeHookUrl}",`,
162
+ ` "--hook_token=${hookToken}",`,
163
+ "]",
164
+ "",
165
+ ].join("\n");
166
+ if (!existsSync(codexConfigPath)) {
167
+ mkdirSync(dirname(codexConfigPath), { recursive: true, mode: 0o700 });
168
+ const initial = [
169
+ "# Codex config.toml",
170
+ "# Auto-generated OrgX hook wiring (safe to edit).",
171
+ notifySnippet.trimEnd(),
172
+ "",
173
+ ].join("\n");
174
+ writeFileAtomicSync(codexConfigPath, initial, {
175
+ mode: 0o600,
176
+ encoding: "utf8",
177
+ });
178
+ result.codex.installed = true;
179
+ }
180
+ else {
181
+ const raw = readFileSync(codexConfigPath, "utf8");
182
+ const alreadyInstalled = raw.includes("post-reporting-event.mjs") &&
183
+ raw.includes("--source_client=codex");
184
+ const hasNotify = /^\s*notify\s*=/m.test(raw);
185
+ if (alreadyInstalled) {
186
+ result.codex.installed = true;
187
+ }
188
+ else if (hasNotify) {
189
+ result.codex.conflict = true;
190
+ }
191
+ else {
192
+ const next = raw.replace(/\s*$/, "") + notifySnippet;
193
+ writeFileAtomicSync(codexConfigPath, next, {
194
+ mode: 0o600,
195
+ encoding: "utf8",
196
+ });
197
+ result.codex.installed = true;
198
+ }
199
+ }
200
+ }
201
+ if (targets.has("claude-code")) {
202
+ const claudeCandidates = [
203
+ join(homedir(), ".claude", "settings.json"),
204
+ join(homedir(), ".config", "claude", "settings.json"),
205
+ ];
206
+ const claudeSettingsPath = claudeCandidates.find((candidate) => existsSync(candidate)) ??
207
+ claudeCandidates[0];
208
+ result.claudeCode.path = claudeSettingsPath;
209
+ mkdirSync(dirname(claudeSettingsPath), { recursive: true, mode: 0o700 });
210
+ let settings = {};
211
+ if (existsSync(claudeSettingsPath)) {
212
+ const raw = readFileSync(claudeSettingsPath, "utf8");
213
+ const parsed = deps.parseJsonSafe(raw);
214
+ if (!parsed) {
215
+ backupCorruptFileSync(claudeSettingsPath);
216
+ }
217
+ else {
218
+ settings = parsed;
219
+ }
220
+ }
221
+ const hooksRoot = settings.hooks &&
222
+ typeof settings.hooks === "object" &&
223
+ !Array.isArray(settings.hooks)
224
+ ? settings.hooks
225
+ : {};
226
+ settings.hooks = hooksRoot;
227
+ const ensureClaudeHook = (hookName, matcher, command) => {
228
+ const list = Array.isArray(hooksRoot[hookName])
229
+ ? hooksRoot[hookName]
230
+ : [];
231
+ let rule = list.find((entry) => entry &&
232
+ typeof entry === "object" &&
233
+ entry.matcher === matcher);
234
+ if (!rule) {
235
+ rule = { matcher, hooks: [] };
236
+ list.push(rule);
237
+ }
238
+ if (!Array.isArray(rule.hooks)) {
239
+ rule.hooks = [];
240
+ }
241
+ const hooks = rule.hooks;
242
+ const already = hooks.some((entry) => entry &&
243
+ entry.type === "command" &&
244
+ typeof entry.command === "string" &&
245
+ entry.command.includes("post-reporting-event.mjs") &&
246
+ entry.command.includes(command));
247
+ if (!already) {
248
+ hooks.push({ type: "command", command });
249
+ }
250
+ hooksRoot[hookName] = list;
251
+ };
252
+ const baseArgs = `--runtime_hook_url=${runtimeHookUrl} --hook_token=${hookToken}`;
253
+ const startCmd = `node ${hookScriptPath} --event=session_start --source_client=claude-code --phase=intent --message=\"Claude session started\" ${baseArgs}`;
254
+ const toolCmd = `node ${hookScriptPath} --event=task_update --source_client=claude-code --phase=execution --message=\"Claude tool completed\" ${baseArgs}`;
255
+ const stopCmd = `node ${hookScriptPath} --event=session_stop --source_client=claude-code --phase=completed --message=\"Claude session completed\" ${baseArgs}`;
256
+ ensureClaudeHook("SessionStart", "", startCmd);
257
+ ensureClaudeHook("PostToolUse", "Write|Edit|Bash", toolCmd);
258
+ ensureClaudeHook("Stop", "", stopCmd);
259
+ writeFileAtomicSync(claudeSettingsPath, `${JSON.stringify(settings, null, 2)}\n`, {
260
+ mode: 0o600,
261
+ encoding: "utf8",
262
+ });
263
+ result.claudeCode.installed = true;
264
+ }
265
+ deps.sendJson(res, 200, result);
266
+ }
267
+ catch (err) {
268
+ deps.sendJson(res, 500, {
269
+ ok: false,
270
+ error: deps.safeErrorMessage(err),
271
+ });
272
+ }
273
+ }, "Install runtime hooks for Codex/Claude Code");
274
+ router.add("*", "hooks/runtime/setup", ({ res }) => {
275
+ deps.sendJson(res, 405, {
276
+ ok: false,
277
+ error: "Use POST /orgx/api/hooks/runtime/setup",
278
+ });
279
+ }, "Reject unsupported methods for hooks/runtime/setup");
280
+ async function renderRuntimeStream(req, res) {
281
+ const write = res.write?.bind(res);
282
+ if (!write) {
283
+ deps.sendJson(res, 501, { ok: false, error: "Streaming not supported" });
284
+ return;
285
+ }
286
+ res.writeHead(200, {
287
+ "Content-Type": "text/event-stream; charset=utf-8",
288
+ "Cache-Control": "no-cache, no-transform",
289
+ Connection: "keep-alive",
290
+ ...deps.securityHeaders,
291
+ ...deps.corsHeaders,
292
+ });
293
+ const subscriberId = deps.randomUUID();
294
+ const subscriber = {
295
+ id: subscriberId,
296
+ write: (chunk) => write(chunk) !== false,
297
+ end: () => {
298
+ if (!res.writableEnded) {
299
+ res.end();
300
+ }
301
+ },
302
+ };
303
+ deps.runtimeStreamSubscribers.set(subscriberId, subscriber);
304
+ deps.ensureRuntimeStreamTimers();
305
+ try {
306
+ const initial = deps.listRuntimeInstances({ limit: 320 });
307
+ deps.writeRuntimeSseEvent(subscriber, "runtime.updated", initial);
308
+ }
309
+ catch {
310
+ // ignore
311
+ }
312
+ const close = () => {
313
+ deps.runtimeStreamSubscribers.delete(subscriberId);
314
+ try {
315
+ subscriber.end();
316
+ }
317
+ catch {
318
+ // ignore
319
+ }
320
+ if (deps.runtimeStreamSubscribers.size === 0) {
321
+ deps.stopRuntimeStreamTimers();
322
+ }
323
+ };
324
+ req.on?.("close", close);
325
+ req.on?.("aborted", close);
326
+ res.on?.("close", close);
327
+ res.on?.("finish", close);
328
+ }
329
+ router.add("GET", "hooks/runtime/stream", async ({ req, res }) => renderRuntimeStream(req, res), "Subscribe to runtime stream");
330
+ router.add("HEAD", "hooks/runtime/stream", async ({ req, res }) => renderRuntimeStream(req, res), "Subscribe to runtime stream (HEAD)");
331
+ router.add("POST", "hooks/runtime", async ({ req, query, res }) => {
332
+ const reqWithHeaders = req;
333
+ const expectedHookToken = deps.resolveRuntimeHookToken();
334
+ const providedHookToken = deps.pickHeaderString(reqWithHeaders.headers ?? {}, [
335
+ "x-orgx-hook-token",
336
+ "x-hook-token",
337
+ ]) ??
338
+ query.get("hook_token") ??
339
+ query.get("token");
340
+ if (!providedHookToken || providedHookToken.trim() !== expectedHookToken) {
341
+ deps.sendJson(res, 401, {
342
+ ok: false,
343
+ error: "Invalid hook token",
344
+ });
345
+ return;
346
+ }
347
+ try {
348
+ const payloadRecord = await deps.parseJsonRequest(req);
349
+ const payload = {
350
+ source_client: deps.pickString(payloadRecord, ["source_client", "sourceClient"]) ?? "unknown",
351
+ event: deps.pickString(payloadRecord, ["event", "hook_event"]) ?? "heartbeat",
352
+ run_id: deps.pickString(payloadRecord, [
353
+ "run_id",
354
+ "runId",
355
+ "session_id",
356
+ "sessionId",
357
+ ]),
358
+ correlation_id: deps.pickString(payloadRecord, ["correlation_id", "correlationId"]),
359
+ initiative_id: deps.pickString(payloadRecord, ["initiative_id", "initiativeId"]),
360
+ workstream_id: deps.pickString(payloadRecord, ["workstream_id", "workstreamId"]),
361
+ task_id: deps.pickString(payloadRecord, ["task_id", "taskId"]),
362
+ agent_id: deps.pickString(payloadRecord, ["agent_id", "agentId"]),
363
+ agent_name: deps.pickString(payloadRecord, ["agent_name", "agentName"]),
364
+ phase: deps.pickString(payloadRecord, ["phase"]),
365
+ progress_pct: deps.pickNumber(payloadRecord, ["progress_pct", "progressPct"]) ?? null,
366
+ message: deps.pickString(payloadRecord, ["message", "summary"]),
367
+ metadata: payloadRecord.metadata && typeof payloadRecord.metadata === "object"
368
+ ? payloadRecord.metadata
369
+ : null,
370
+ timestamp: deps.pickString(payloadRecord, ["timestamp", "time", "ts"]),
371
+ };
372
+ const instance = deps.upsertRuntimeInstanceFromHook(payload);
373
+ deps.broadcastRuntimeSse("runtime.updated", instance);
374
+ deps.clearSnapshotResponseCache();
375
+ const fallbackPhaseByEvent = {
376
+ session_start: "intent",
377
+ heartbeat: "execution",
378
+ progress: "execution",
379
+ task_update: "execution",
380
+ session_stop: "completed",
381
+ error: "blocked",
382
+ };
383
+ const phase = deps.normalizeHookPhase(payload.phase ?? fallbackPhaseByEvent[instance.event] ?? "execution");
384
+ const level = instance.event === "error" ? "error" : phase === "blocked" ? "warn" : "info";
385
+ const message = payload.message ?? `${instance.displayName} ${instance.event.replace(/_/g, " ")}`;
386
+ let forwarded = false;
387
+ let forwardError = null;
388
+ if (instance.initiativeId) {
389
+ try {
390
+ await deps.emitActivity({
391
+ initiative_id: instance.initiativeId,
392
+ run_id: instance.runId ?? undefined,
393
+ correlation_id: instance.runId
394
+ ? undefined
395
+ : (instance.correlationId ?? undefined),
396
+ source_client: deps.normalizeRuntimeSourceForReporting(instance.sourceClient),
397
+ message,
398
+ phase,
399
+ progress_pct: instance.progressPct ?? undefined,
400
+ level,
401
+ metadata: {
402
+ source: "runtime_hook_relay",
403
+ hook_event: instance.event,
404
+ instance_id: instance.id,
405
+ runtime_client: instance.sourceClient,
406
+ task_id: instance.taskId,
407
+ workstream_id: instance.workstreamId,
408
+ ...(instance.metadata ?? {}),
409
+ },
410
+ });
411
+ forwarded = true;
412
+ }
413
+ catch (err) {
414
+ forwardError = deps.safeErrorMessage(err);
415
+ }
416
+ }
417
+ deps.sendJson(res, 200, {
418
+ ok: true,
419
+ instance_id: instance.id,
420
+ state: instance.state,
421
+ last_seen_at: instance.lastHeartbeatAt ?? instance.lastEventAt,
422
+ run_id: instance.runId ?? null,
423
+ forwarded,
424
+ forward_error: forwardError,
425
+ });
426
+ }
427
+ catch (err) {
428
+ deps.sendJson(res, 500, {
429
+ ok: false,
430
+ error: deps.safeErrorMessage(err),
431
+ });
432
+ }
433
+ }, "Ingest runtime hook events");
434
+ router.add("*", "hooks/runtime", ({ res }) => {
435
+ deps.sendJson(res, 405, { ok: false, error: "Use POST /orgx/api/hooks/runtime" });
436
+ }, "Reject unsupported methods for hooks/runtime");
437
+ }
@@ -0,0 +1,7 @@
1
+ import type { Router } from "../router.js";
2
+ type SentinelsCatalogDeps<TRes> = {
3
+ sendJson: (res: TRes, status: number, payload: unknown) => void;
4
+ safeErrorMessage: (err: unknown) => string;
5
+ };
6
+ export declare function registerSentinelsCatalogRoutes<TReq, TRes>(router: Router<Record<string, never>, TReq, TRes>, deps: SentinelsCatalogDeps<TRes>): void;
7
+ export {};
@@ -0,0 +1,24 @@
1
+ import { listBuiltInSentinels } from "../helpers/sentinel-catalog.js";
2
+ export function registerSentinelsCatalogRoutes(router, deps) {
3
+ async function handle(res, domain) {
4
+ try {
5
+ const sentinels = listBuiltInSentinels({ domain });
6
+ deps.sendJson(res, 200, {
7
+ generatedAt: new Date().toISOString(),
8
+ domain: domain ?? null,
9
+ sentinels,
10
+ });
11
+ }
12
+ catch (err) {
13
+ deps.sendJson(res, 500, {
14
+ error: deps.safeErrorMessage(err),
15
+ });
16
+ }
17
+ }
18
+ router.add("GET", "sentinels/catalog", async ({ query, res }) => {
19
+ return handle(res, query?.get("domain") ?? undefined);
20
+ }, "Sentinel catalog");
21
+ router.add("HEAD", "sentinels/catalog", async ({ query, res }) => {
22
+ return handle(res, query?.get("domain") ?? undefined);
23
+ }, "Sentinel catalog (HEAD)");
24
+ }
@@ -0,0 +1,23 @@
1
+ import type { ByokKeysRecord } from "../../byok-store.js";
2
+ import type { Router } from "../router.js";
3
+ type JsonRecord = Record<string, unknown>;
4
+ type RegisterSettingsByokRoutesDeps<TReq, TRes> = {
5
+ parseJsonRequest: (req: TReq) => Promise<JsonRecord>;
6
+ readByokKeys: () => ByokKeysRecord | null;
7
+ writeByokKeys: (input: Partial<ByokKeysRecord>) => ByokKeysRecord;
8
+ maskSecret: (value: string | null) => string | null;
9
+ listAgents: () => Promise<Array<{
10
+ id?: string;
11
+ isDefault?: boolean;
12
+ }>>;
13
+ listOpenClawProviderModels: (input: {
14
+ agentId: string;
15
+ provider: "openai" | "anthropic" | "openrouter";
16
+ }) => Promise<Array<{
17
+ key: string;
18
+ }>>;
19
+ sendJson: (res: TRes, status: number, payload: unknown) => void;
20
+ safeErrorMessage: (err: unknown) => string;
21
+ };
22
+ export declare function registerSettingsByokRoutes<TReq, TRes>(router: Router<Record<string, never>, TReq, TRes>, deps: RegisterSettingsByokRoutesDeps<TReq, TRes>): void;
23
+ export {};
@@ -0,0 +1,163 @@
1
+ function readEnvByokKeys() {
2
+ return {
3
+ openai: process.env.OPENAI_API_KEY ?? null,
4
+ anthropic: process.env.ANTHROPIC_API_KEY ?? null,
5
+ openrouter: process.env.OPENROUTER_API_KEY ?? null,
6
+ };
7
+ }
8
+ export function registerSettingsByokRoutes(router, deps) {
9
+ async function renderByokSettings(req, method, res) {
10
+ const stored = deps.readByokKeys();
11
+ const envKeys = readEnvByokKeys();
12
+ const effectiveOpenai = stored?.openaiApiKey ?? envKeys.openai ?? null;
13
+ const effectiveAnthropic = stored?.anthropicApiKey ?? envKeys.anthropic ?? null;
14
+ const effectiveOpenrouter = stored?.openrouterApiKey ?? envKeys.openrouter ?? null;
15
+ const toProvider = (input) => {
16
+ const hasStored = typeof input.storedValue === "string" && input.storedValue.trim().length > 0;
17
+ const hasEnv = typeof input.envValue === "string" && input.envValue.trim().length > 0;
18
+ const source = hasStored ? "stored" : hasEnv ? "env" : "none";
19
+ return {
20
+ configured: Boolean(input.effective && input.effective.trim().length > 0),
21
+ source,
22
+ masked: deps.maskSecret(input.effective),
23
+ };
24
+ };
25
+ if (method === "POST") {
26
+ try {
27
+ const payload = await deps.parseJsonRequest(req);
28
+ const updates = {};
29
+ const setIfPresent = (key, aliases) => {
30
+ for (const alias of aliases) {
31
+ if (!Object.prototype.hasOwnProperty.call(payload, alias))
32
+ continue;
33
+ const raw = payload[alias];
34
+ if (raw === null || typeof raw === "string") {
35
+ updates[key] = raw;
36
+ return;
37
+ }
38
+ }
39
+ };
40
+ setIfPresent("openaiApiKey", [
41
+ "openaiApiKey",
42
+ "openai_api_key",
43
+ "openaiKey",
44
+ "openai_key",
45
+ ]);
46
+ setIfPresent("anthropicApiKey", [
47
+ "anthropicApiKey",
48
+ "anthropic_api_key",
49
+ "anthropicKey",
50
+ "anthropic_key",
51
+ ]);
52
+ setIfPresent("openrouterApiKey", [
53
+ "openrouterApiKey",
54
+ "openrouter_api_key",
55
+ "openrouterKey",
56
+ "openrouter_key",
57
+ ]);
58
+ const saved = deps.writeByokKeys(updates);
59
+ const nextEffectiveOpenai = saved.openaiApiKey ?? envKeys.openai ?? null;
60
+ const nextEffectiveAnthropic = saved.anthropicApiKey ?? envKeys.anthropic ?? null;
61
+ const nextEffectiveOpenrouter = saved.openrouterApiKey ?? envKeys.openrouter ?? null;
62
+ deps.sendJson(res, 200, {
63
+ ok: true,
64
+ updatedAt: saved.updatedAt,
65
+ providers: {
66
+ openai: toProvider({
67
+ storedValue: saved.openaiApiKey,
68
+ envValue: envKeys.openai,
69
+ effective: nextEffectiveOpenai,
70
+ }),
71
+ anthropic: toProvider({
72
+ storedValue: saved.anthropicApiKey,
73
+ envValue: envKeys.anthropic,
74
+ effective: nextEffectiveAnthropic,
75
+ }),
76
+ openrouter: toProvider({
77
+ storedValue: saved.openrouterApiKey,
78
+ envValue: envKeys.openrouter,
79
+ effective: nextEffectiveOpenrouter,
80
+ }),
81
+ },
82
+ });
83
+ }
84
+ catch (err) {
85
+ deps.sendJson(res, 500, { ok: false, error: deps.safeErrorMessage(err) });
86
+ }
87
+ return;
88
+ }
89
+ deps.sendJson(res, 200, {
90
+ ok: true,
91
+ updatedAt: stored?.updatedAt ?? null,
92
+ providers: {
93
+ openai: toProvider({
94
+ storedValue: stored?.openaiApiKey,
95
+ envValue: envKeys.openai,
96
+ effective: effectiveOpenai,
97
+ }),
98
+ anthropic: toProvider({
99
+ storedValue: stored?.anthropicApiKey,
100
+ envValue: envKeys.anthropic,
101
+ effective: effectiveAnthropic,
102
+ }),
103
+ openrouter: toProvider({
104
+ storedValue: stored?.openrouterApiKey,
105
+ envValue: envKeys.openrouter,
106
+ effective: effectiveOpenrouter,
107
+ }),
108
+ },
109
+ });
110
+ }
111
+ async function renderByokHealth(query, res) {
112
+ let agentId = (query.get("agentId") ?? query.get("agent_id") ?? "").trim();
113
+ if (!agentId) {
114
+ try {
115
+ const agents = await deps.listAgents();
116
+ const defaultAgent = agents.find((entry) => Boolean(entry.isDefault)) ?? agents[0] ?? null;
117
+ const candidate = defaultAgent && typeof defaultAgent.id === "string"
118
+ ? defaultAgent.id.trim()
119
+ : "";
120
+ if (candidate)
121
+ agentId = candidate;
122
+ }
123
+ catch {
124
+ // ignore
125
+ }
126
+ }
127
+ if (!agentId)
128
+ agentId = "main";
129
+ const providers = {};
130
+ for (const provider of ["openai", "anthropic", "openrouter"]) {
131
+ try {
132
+ const models = await deps.listOpenClawProviderModels({ agentId, provider });
133
+ providers[provider] = {
134
+ ok: true,
135
+ modelCount: models.length,
136
+ sample: models.slice(0, 4).map((model) => model.key),
137
+ };
138
+ }
139
+ catch (err) {
140
+ providers[provider] = {
141
+ ok: false,
142
+ error: deps.safeErrorMessage(err),
143
+ };
144
+ }
145
+ }
146
+ deps.sendJson(res, 200, {
147
+ ok: true,
148
+ agentId,
149
+ providers,
150
+ });
151
+ }
152
+ router.add("GET", "settings/byok", async ({ req, res }) => renderByokSettings(req, "GET", res), "Read BYOK settings");
153
+ router.add("POST", "settings/byok", async ({ req, res }) => renderByokSettings(req, "POST", res), "Write BYOK settings");
154
+ router.add("HEAD", "settings/byok", async ({ req, res }) => renderByokSettings(req, "GET", res), "Read BYOK settings (HEAD)");
155
+ router.add("GET", "settings/byok/health", async ({ query, res }) => renderByokHealth(query, res), "Probe BYOK provider health");
156
+ router.add("HEAD", "settings/byok/health", async ({ query, res }) => renderByokHealth(query, res), "Probe BYOK provider health (HEAD)");
157
+ router.add("*", "settings/byok", ({ res }) => {
158
+ deps.sendJson(res, 405, { ok: false, error: "Method not allowed" });
159
+ }, "Reject unsupported methods for settings/byok");
160
+ router.add("*", "settings/byok/health", ({ res }) => {
161
+ deps.sendJson(res, 405, { ok: false, error: "Method not allowed" });
162
+ }, "Reject unsupported methods for settings/byok/health");
163
+ }
@@ -0,0 +1,18 @@
1
+ import type { OrgSnapshot } from "../../types.js";
2
+ import type { Router } from "../router.js";
3
+ type SummaryRoutesDeps<TRes> = {
4
+ getSnapshot: () => OrgSnapshot | null;
5
+ getOrgSnapshot: () => Promise<OrgSnapshot>;
6
+ sendJson: (res: TRes, status: number, payload: unknown) => void;
7
+ writeHead: (res: TRes, status: number, headers: Record<string, string>) => void;
8
+ end: (res: TRes) => void;
9
+ securityHeaders: Record<string, string>;
10
+ corsHeaders: Record<string, string>;
11
+ formatStatus: (snapshot: OrgSnapshot | null) => unknown;
12
+ formatAgents: (snapshot: OrgSnapshot | null) => unknown;
13
+ formatActivity: (snapshot: OrgSnapshot | null) => unknown;
14
+ formatInitiatives: (snapshot: OrgSnapshot | null) => unknown;
15
+ getOnboardingState: () => Promise<unknown>;
16
+ };
17
+ export declare function registerSummaryRoutes<TReq, TRes>(router: Router<Record<string, never>, TReq, TRes>, deps: SummaryRoutesDeps<TRes>): void;
18
+ export {};