@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,136 @@
1
+ import { posthogCapture } from "../telemetry/posthog.js";
2
+ export function instrumentPluginApi(input) {
3
+ const registerTool = input.api.registerTool.bind(input.api);
4
+ input.api.registerTool = (tool, options) => {
5
+ const toolName = tool.name;
6
+ const optional = Boolean(options?.optional);
7
+ registerTool({
8
+ ...tool,
9
+ execute: async (callId, params) => {
10
+ const startedAt = Date.now();
11
+ void posthogCapture({
12
+ event: "openclaw_tool_called",
13
+ distinctId: input.installationId,
14
+ properties: {
15
+ tool_name: toolName,
16
+ tool_optional: optional,
17
+ call_id: callId,
18
+ plugin_version: input.pluginVersion,
19
+ },
20
+ }).catch(() => {
21
+ // best effort
22
+ });
23
+ try {
24
+ const result = await tool.execute(callId, params);
25
+ const durationMs = Date.now() - startedAt;
26
+ void posthogCapture({
27
+ event: "openclaw_tool_succeeded",
28
+ distinctId: input.installationId,
29
+ properties: {
30
+ tool_name: toolName,
31
+ tool_optional: optional,
32
+ call_id: callId,
33
+ duration_ms: durationMs,
34
+ plugin_version: input.pluginVersion,
35
+ },
36
+ }).catch(() => {
37
+ // best effort
38
+ });
39
+ return result;
40
+ }
41
+ catch (err) {
42
+ const durationMs = Date.now() - startedAt;
43
+ void posthogCapture({
44
+ event: "openclaw_tool_failed",
45
+ distinctId: input.installationId,
46
+ properties: {
47
+ tool_name: toolName,
48
+ tool_optional: optional,
49
+ call_id: callId,
50
+ duration_ms: durationMs,
51
+ plugin_version: input.pluginVersion,
52
+ error: input.toErrorMessage(err),
53
+ },
54
+ }).catch(() => {
55
+ // best effort
56
+ });
57
+ throw err;
58
+ }
59
+ },
60
+ }, options);
61
+ };
62
+ const registerService = input.api.registerService.bind(input.api);
63
+ input.api.registerService = (service) => {
64
+ registerService({
65
+ ...service,
66
+ start: async () => {
67
+ const startedAt = Date.now();
68
+ try {
69
+ await service.start();
70
+ const durationMs = Date.now() - startedAt;
71
+ void posthogCapture({
72
+ event: "openclaw_service_started",
73
+ distinctId: input.installationId,
74
+ properties: {
75
+ service_id: service.id,
76
+ duration_ms: durationMs,
77
+ plugin_version: input.pluginVersion,
78
+ },
79
+ }).catch(() => {
80
+ // best effort
81
+ });
82
+ }
83
+ catch (err) {
84
+ const durationMs = Date.now() - startedAt;
85
+ void posthogCapture({
86
+ event: "openclaw_service_start_failed",
87
+ distinctId: input.installationId,
88
+ properties: {
89
+ service_id: service.id,
90
+ duration_ms: durationMs,
91
+ plugin_version: input.pluginVersion,
92
+ error: input.toErrorMessage(err),
93
+ },
94
+ }).catch(() => {
95
+ // best effort
96
+ });
97
+ throw err;
98
+ }
99
+ },
100
+ stop: async () => {
101
+ const startedAt = Date.now();
102
+ try {
103
+ await service.stop();
104
+ const durationMs = Date.now() - startedAt;
105
+ void posthogCapture({
106
+ event: "openclaw_service_stopped",
107
+ distinctId: input.installationId,
108
+ properties: {
109
+ service_id: service.id,
110
+ duration_ms: durationMs,
111
+ plugin_version: input.pluginVersion,
112
+ },
113
+ }).catch(() => {
114
+ // best effort
115
+ });
116
+ }
117
+ catch (err) {
118
+ const durationMs = Date.now() - startedAt;
119
+ void posthogCapture({
120
+ event: "openclaw_service_stop_failed",
121
+ distinctId: input.installationId,
122
+ properties: {
123
+ service_id: service.id,
124
+ duration_ms: durationMs,
125
+ plugin_version: input.pluginVersion,
126
+ error: input.toErrorMessage(err),
127
+ },
128
+ }).catch(() => {
129
+ // best effort
130
+ });
131
+ throw err;
132
+ }
133
+ },
134
+ });
135
+ };
136
+ }
@@ -1,15 +1,32 @@
1
1
  import type { SkillPack } from "./contracts/types.js";
2
2
  import type { OrgxSkillPackOverrides } from "./agent-suite.js";
3
+ export type SkillPackPolicy = {
4
+ frozen: boolean;
5
+ pinnedChecksum: string | null;
6
+ };
7
+ export type SkillPackPolicyDiff = {
8
+ field: "policy.frozen" | "policy.pinnedChecksum";
9
+ before: boolean | string | null;
10
+ after: boolean | string | null;
11
+ };
12
+ export type SkillPackPolicyAuditEntry = {
13
+ id: string;
14
+ changedAt: string;
15
+ changedBy: string;
16
+ action: "policy.update" | "policy.rollback";
17
+ reason: string | null;
18
+ rollbackOfAuditId: string | null;
19
+ diff: SkillPackPolicyDiff[];
20
+ beforePolicy: SkillPackPolicy;
21
+ afterPolicy: SkillPackPolicy;
22
+ };
3
23
  export type SkillPackState = {
4
24
  version: 1;
5
25
  updatedAt: string;
6
26
  lastCheckedAt: string | null;
7
27
  lastError: string | null;
8
28
  etag: string | null;
9
- policy: {
10
- frozen: boolean;
11
- pinnedChecksum: string | null;
12
- };
29
+ policy: SkillPackPolicy;
13
30
  pack: {
14
31
  name: string;
15
32
  version: string;
@@ -23,6 +40,9 @@ export type SkillPackState = {
23
40
  updated_at: string | null;
24
41
  } | null;
25
42
  overrides: OrgxSkillPackOverrides | null;
43
+ audit: {
44
+ entries: SkillPackPolicyAuditEntry[];
45
+ };
26
46
  };
27
47
  export declare function readSkillPackState(input?: {
28
48
  openclawDir?: string;
@@ -36,11 +56,22 @@ export declare function updateSkillPackPolicy(input: {
36
56
  pinnedChecksum?: string | null;
37
57
  pinToCurrent?: boolean;
38
58
  clearPin?: boolean;
59
+ changedBy?: string;
60
+ reason?: string;
61
+ }): SkillPackState;
62
+ export declare function rollbackSkillPackPolicy(input?: {
63
+ openclawDir?: string;
64
+ auditId?: string;
65
+ changedBy?: string;
66
+ reason?: string;
39
67
  }): SkillPackState;
40
68
  export declare function toOrgxSkillPackOverrides(input: {
41
69
  pack: SkillPack;
42
70
  etag: string | null;
43
- }): OrgxSkillPackOverrides;
71
+ }): {
72
+ overrides: OrgxSkillPackOverrides;
73
+ validationErrors: string[];
74
+ };
44
75
  export declare function refreshSkillPackState(input: {
45
76
  getSkillPack: (args: {
46
77
  name?: string;
@@ -2,8 +2,10 @@ import { existsSync, readFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import { writeFileAtomicSync } from "./fs-utils.js";
4
4
  import { getOpenClawDir } from "./paths.js";
5
+ import { validateOpenClawSkillPackManifest } from "./contracts/skill-pack-schema.js";
5
6
  const STORE_VERSION = 1;
6
7
  const STATE_FILENAME = "orgx-skill-pack-state.json";
8
+ const AUDIT_HISTORY_LIMIT = 50;
7
9
  function nowIso() {
8
10
  return new Date().toISOString();
9
11
  }
@@ -16,6 +18,94 @@ function coerceString(value) {
16
18
  function statePath(openclawDir) {
17
19
  return join(openclawDir, STATE_FILENAME);
18
20
  }
21
+ function clonePolicy(input) {
22
+ return {
23
+ frozen: Boolean(input.frozen),
24
+ pinnedChecksum: coerceString(input.pinnedChecksum),
25
+ };
26
+ }
27
+ function normalizeChangedBy(input) {
28
+ if (typeof input !== "string")
29
+ return "unknown";
30
+ const value = input.trim();
31
+ return value.length > 0 ? value : "unknown";
32
+ }
33
+ function normalizeReason(input) {
34
+ return typeof input === "string" && input.trim().length > 0 ? input.trim() : null;
35
+ }
36
+ function nextAuditId() {
37
+ return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
38
+ }
39
+ function computePolicyDiff(before, after) {
40
+ const diff = [];
41
+ if (before.frozen !== after.frozen) {
42
+ diff.push({
43
+ field: "policy.frozen",
44
+ before: before.frozen,
45
+ after: after.frozen,
46
+ });
47
+ }
48
+ if (before.pinnedChecksum !== after.pinnedChecksum) {
49
+ diff.push({
50
+ field: "policy.pinnedChecksum",
51
+ before: before.pinnedChecksum,
52
+ after: after.pinnedChecksum,
53
+ });
54
+ }
55
+ return diff;
56
+ }
57
+ function appendPolicyAuditEntry(entries, entry) {
58
+ return [entry, ...entries].slice(0, AUDIT_HISTORY_LIMIT);
59
+ }
60
+ function parseAuditEntries(raw) {
61
+ if (!Array.isArray(raw))
62
+ return [];
63
+ const entries = [];
64
+ for (const candidate of raw) {
65
+ if (!isRecord(candidate))
66
+ continue;
67
+ const beforePolicyRaw = isRecord(candidate.beforePolicy) ? candidate.beforePolicy : null;
68
+ const afterPolicyRaw = isRecord(candidate.afterPolicy) ? candidate.afterPolicy : null;
69
+ if (!beforePolicyRaw || !afterPolicyRaw)
70
+ continue;
71
+ const diffRaw = Array.isArray(candidate.diff) ? candidate.diff : [];
72
+ const diff = [];
73
+ for (const diffEntry of diffRaw) {
74
+ if (!isRecord(diffEntry))
75
+ continue;
76
+ const field = diffEntry.field;
77
+ if (field !== "policy.frozen" && field !== "policy.pinnedChecksum")
78
+ continue;
79
+ diff.push({
80
+ field,
81
+ before: typeof diffEntry.before === "boolean" || diffEntry.before === null
82
+ ? diffEntry.before
83
+ : coerceString(diffEntry.before),
84
+ after: typeof diffEntry.after === "boolean" || diffEntry.after === null
85
+ ? diffEntry.after
86
+ : coerceString(diffEntry.after),
87
+ });
88
+ }
89
+ entries.push({
90
+ id: coerceString(candidate.id) ?? nextAuditId(),
91
+ changedAt: coerceString(candidate.changedAt) ?? nowIso(),
92
+ changedBy: normalizeChangedBy(candidate.changedBy),
93
+ action: candidate.action === "policy.rollback" ? "policy.rollback" : "policy.update",
94
+ reason: normalizeReason(candidate.reason),
95
+ rollbackOfAuditId: coerceString(candidate.rollbackOfAuditId),
96
+ diff,
97
+ beforePolicy: {
98
+ frozen: Boolean(beforePolicyRaw.frozen),
99
+ pinnedChecksum: coerceString(beforePolicyRaw.pinnedChecksum),
100
+ },
101
+ afterPolicy: {
102
+ frozen: Boolean(afterPolicyRaw.frozen),
103
+ pinnedChecksum: coerceString(afterPolicyRaw.pinnedChecksum),
104
+ },
105
+ });
106
+ }
107
+ return entries.slice(0, AUDIT_HISTORY_LIMIT);
108
+ }
19
109
  export function readSkillPackState(input) {
20
110
  const openclawDir = input?.openclawDir ?? getOpenClawDir();
21
111
  const path = statePath(openclawDir);
@@ -29,6 +119,7 @@ export function readSkillPackState(input) {
29
119
  pack: null,
30
120
  remote: null,
31
121
  overrides: null,
122
+ audit: { entries: [] },
32
123
  };
33
124
  try {
34
125
  if (!existsSync(path))
@@ -43,6 +134,7 @@ export function readSkillPackState(input) {
43
134
  const pack = isRecord(parsed.pack) ? parsed.pack : null;
44
135
  const remote = isRecord(parsed.remote) ? parsed.remote : null;
45
136
  const overrides = isRecord(parsed.overrides) ? parsed.overrides : null;
137
+ const audit = isRecord(parsed.audit) ? parsed.audit : null;
46
138
  return {
47
139
  version: STORE_VERSION,
48
140
  updatedAt: coerceString(parsed.updatedAt) ?? nowIso(),
@@ -72,6 +164,9 @@ export function readSkillPackState(input) {
72
164
  overrides: overrides
73
165
  ? overrides
74
166
  : null,
167
+ audit: {
168
+ entries: parseAuditEntries(audit?.entries),
169
+ },
75
170
  };
76
171
  }
77
172
  catch {
@@ -88,7 +183,12 @@ export function writeSkillPackState(state, input) {
88
183
  }
89
184
  export function updateSkillPackPolicy(input) {
90
185
  const prev = readSkillPackState({ openclawDir: input.openclawDir });
186
+ const beforePolicy = clonePolicy(prev.policy);
91
187
  const nextPolicy = { ...prev.policy };
188
+ const activeChecksum = prev.pack?.checksum ?? null;
189
+ const remoteChecksum = prev.remote?.checksum ?? null;
190
+ const hasInactiveRemoteCandidate = Boolean(remoteChecksum && remoteChecksum !== activeChecksum);
191
+ const blockedByActivationValidation = hasInactiveRemoteCandidate && hasActivationValidationFailure(prev.lastError);
92
192
  if (typeof input.frozen === "boolean") {
93
193
  nextPolicy.frozen = input.frozen;
94
194
  }
@@ -96,10 +196,20 @@ export function updateSkillPackPolicy(input) {
96
196
  nextPolicy.pinnedChecksum = null;
97
197
  }
98
198
  else if (input.pinToCurrent) {
199
+ if (blockedByActivationValidation) {
200
+ throw new Error("Cannot pin_to_current: remote config failed eval/manifest checks and is not active.");
201
+ }
99
202
  nextPolicy.pinnedChecksum = prev.pack?.checksum ?? prev.remote?.checksum ?? null;
100
203
  }
101
204
  else if (typeof input.pinnedChecksum === "string") {
102
- nextPolicy.pinnedChecksum = input.pinnedChecksum.trim() || null;
205
+ const requestedChecksum = input.pinnedChecksum.trim() || null;
206
+ if (requestedChecksum &&
207
+ remoteChecksum &&
208
+ requestedChecksum === remoteChecksum &&
209
+ blockedByActivationValidation) {
210
+ throw new Error("Cannot pin checksum to remote config: eval/manifest checks are failing for that candidate.");
211
+ }
212
+ nextPolicy.pinnedChecksum = requestedChecksum;
103
213
  }
104
214
  else if (input.pinnedChecksum === null) {
105
215
  nextPolicy.pinnedChecksum = null;
@@ -109,48 +219,155 @@ export function updateSkillPackPolicy(input) {
109
219
  updatedAt: nowIso(),
110
220
  policy: nextPolicy,
111
221
  };
222
+ const diff = computePolicyDiff(beforePolicy, next.policy);
223
+ if (diff.length > 0) {
224
+ const entry = {
225
+ id: nextAuditId(),
226
+ changedAt: next.updatedAt,
227
+ changedBy: normalizeChangedBy(input.changedBy),
228
+ action: "policy.update",
229
+ reason: normalizeReason(input.reason),
230
+ rollbackOfAuditId: null,
231
+ diff,
232
+ beforePolicy,
233
+ afterPolicy: clonePolicy(next.policy),
234
+ };
235
+ next.audit = {
236
+ entries: appendPolicyAuditEntry(prev.audit.entries, entry),
237
+ };
238
+ }
112
239
  writeSkillPackState(next, { openclawDir: input.openclawDir });
113
240
  return next;
114
241
  }
242
+ export function rollbackSkillPackPolicy(input) {
243
+ const prev = readSkillPackState({ openclawDir: input?.openclawDir });
244
+ const normalizedAuditId = typeof input?.auditId === "string" && input.auditId.trim().length > 0
245
+ ? input.auditId.trim()
246
+ : null;
247
+ const target = normalizedAuditId
248
+ ? prev.audit.entries.find((entry) => entry.id === normalizedAuditId) ?? null
249
+ : prev.audit.entries[0] ?? null;
250
+ if (!target) {
251
+ throw new Error("No policy audit entry available for rollback");
252
+ }
253
+ const beforePolicy = clonePolicy(prev.policy);
254
+ const afterPolicy = clonePolicy(target.beforePolicy);
255
+ const diff = computePolicyDiff(beforePolicy, afterPolicy);
256
+ if (diff.length === 0) {
257
+ return prev;
258
+ }
259
+ const changedAt = nowIso();
260
+ const rollbackEntry = {
261
+ id: nextAuditId(),
262
+ changedAt,
263
+ changedBy: normalizeChangedBy(input?.changedBy),
264
+ action: "policy.rollback",
265
+ reason: normalizeReason(input?.reason) ?? `Rollback to audit ${target.id}`,
266
+ rollbackOfAuditId: target.id,
267
+ diff,
268
+ beforePolicy,
269
+ afterPolicy,
270
+ };
271
+ const next = {
272
+ ...prev,
273
+ updatedAt: changedAt,
274
+ policy: afterPolicy,
275
+ audit: {
276
+ entries: appendPolicyAuditEntry(prev.audit.entries, rollbackEntry),
277
+ },
278
+ };
279
+ writeSkillPackState(next, { openclawDir: input?.openclawDir });
280
+ return next;
281
+ }
115
282
  function asRecord(value) {
116
283
  return isRecord(value) ? value : null;
117
284
  }
118
- function parseOpenclawSkillOverridesFromManifest(manifest) {
119
- const root = manifest ?? {};
285
+ function asBoolean(value) {
286
+ return typeof value === "boolean" ? value : null;
287
+ }
288
+ function asFiniteNumber(value) {
289
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
290
+ }
291
+ function normalizeStatus(value) {
292
+ if (typeof value !== "string")
293
+ return null;
294
+ const normalized = value.trim().toLowerCase().replace(/[\s-]+/g, "_");
295
+ return normalized.length > 0 ? normalized : null;
296
+ }
297
+ function hasActivationValidationFailure(lastError) {
298
+ if (!lastError)
299
+ return false;
300
+ const normalized = lastError.toLowerCase();
301
+ return (normalized.includes("eval framework checks did not pass") ||
302
+ normalized.includes("eval gate blocked activation") ||
303
+ normalized.includes("manifest validation errors"));
304
+ }
305
+ function evalGateErrorForPack(pack) {
306
+ const manifest = asRecord(pack.manifest);
307
+ if (!manifest) {
308
+ return "SkillPack eval framework checks did not pass: missing manifest object";
309
+ }
120
310
  const candidates = [
121
- asRecord(root.openclaw_skills),
122
- asRecord(root.openclawSkills),
123
- asRecord(asRecord(root.openclaw)?.skills),
124
- ].filter(Boolean);
125
- const out = {};
311
+ { label: "eval_framework", value: asRecord(manifest.eval_framework) },
312
+ { label: "evalFramework", value: asRecord(manifest.evalFramework) },
313
+ { label: "evaluation_result", value: asRecord(manifest.evaluation_result) },
314
+ { label: "evaluationResult", value: asRecord(manifest.evaluationResult) },
315
+ { label: "evaluation", value: asRecord(manifest.evaluation) },
316
+ { label: "quality_gate", value: asRecord(manifest.quality_gate) },
317
+ { label: "qualityGate", value: asRecord(manifest.qualityGate) },
318
+ ];
126
319
  for (const candidate of candidates) {
127
- for (const [k, v] of Object.entries(candidate)) {
128
- if (typeof v !== "string")
129
- continue;
130
- const key = k.trim().toLowerCase();
131
- if (!key)
132
- continue;
133
- out[key] = v;
320
+ if (!candidate.value)
321
+ continue;
322
+ const passed = asBoolean(candidate.value.passed) ??
323
+ asBoolean(candidate.value.ok) ??
324
+ asBoolean(candidate.value.success) ??
325
+ asBoolean(candidate.value.allowed);
326
+ if (passed != null) {
327
+ return passed
328
+ ? null
329
+ : `SkillPack eval framework checks did not pass: ${candidate.label}.passed=false`;
330
+ }
331
+ const status = normalizeStatus(candidate.value.status);
332
+ if (status) {
333
+ const passStatuses = new Set(["pass", "passed", "ok", "success", "approved", "green"]);
334
+ const failStatuses = new Set(["fail", "failed", "rejected", "error", "blocked", "red"]);
335
+ if (passStatuses.has(status))
336
+ return null;
337
+ if (failStatuses.has(status)) {
338
+ return `SkillPack eval framework checks did not pass: ${candidate.label}.status=${status}`;
339
+ }
340
+ }
341
+ const checksTotal = asFiniteNumber(candidate.value.checks_total) ??
342
+ asFiniteNumber(candidate.value.total_checks);
343
+ const checksPassed = asFiniteNumber(candidate.value.checks_passed) ??
344
+ asFiniteNumber(candidate.value.passed_checks);
345
+ if (checksTotal != null && checksPassed != null && checksTotal > 0) {
346
+ return checksPassed >= checksTotal
347
+ ? null
348
+ : `SkillPack eval framework checks did not pass: ${candidate.label}.checks=${checksPassed}/${checksTotal}`;
134
349
  }
135
350
  }
136
- return out;
351
+ return "SkillPack eval framework checks did not pass: missing pass signal in manifest";
137
352
  }
138
353
  export function toOrgxSkillPackOverrides(input) {
139
- const manifest = asRecord(input.pack.manifest) ?? {};
140
- const rawOverrides = parseOpenclawSkillOverridesFromManifest(manifest);
354
+ const manifest = asRecord(input.pack.manifest);
355
+ const validation = validateOpenClawSkillPackManifest(manifest ?? {});
141
356
  const openclaw_skills = {};
142
- for (const [k, v] of Object.entries(rawOverrides)) {
143
- // Domains are normalized to lowercase keys in the manifest.
357
+ for (const [k, v] of Object.entries(validation.openclaw_skills)) {
144
358
  openclaw_skills[k] = v;
145
359
  }
146
360
  return {
147
- source: "server",
148
- name: input.pack.name,
149
- version: input.pack.version,
150
- checksum: input.pack.checksum,
151
- etag: input.etag,
152
- updated_at: input.pack.updated_at ?? null,
153
- openclaw_skills,
361
+ overrides: {
362
+ source: "server",
363
+ name: input.pack.name,
364
+ version: input.pack.version,
365
+ checksum: input.pack.checksum,
366
+ etag: input.etag,
367
+ updated_at: input.pack.updated_at ?? null,
368
+ openclaw_skills,
369
+ },
370
+ validationErrors: validation.errors,
154
371
  };
155
372
  }
156
373
  export async function refreshSkillPackState(input) {
@@ -201,7 +418,33 @@ export async function refreshSkillPackState(input) {
201
418
  writeSkillPackState(next, { openclawDir: input.openclawDir });
202
419
  return { state: next, changed: false };
203
420
  }
204
- const overrides = toOrgxSkillPackOverrides({ pack: result.pack, etag: result.etag ?? null });
421
+ const { overrides, validationErrors } = toOrgxSkillPackOverrides({
422
+ pack: result.pack,
423
+ etag: result.etag ?? null,
424
+ });
425
+ const evalGateError = evalGateErrorForPack(result.pack);
426
+ const activationErrors = [];
427
+ if (validationErrors.length > 0) {
428
+ activationErrors.push(`SkillPack manifest validation errors: ${validationErrors.join("; ")}`);
429
+ }
430
+ if (evalGateError) {
431
+ activationErrors.push(evalGateError);
432
+ }
433
+ const activationValidationError = activationErrors.length > 0 ? activationErrors.join(" | ") : null;
434
+ // Guardrail: never activate a config that fails eval/manifest validation.
435
+ // Keep it staged in `remote` + `lastError` so operators can inspect/fix it.
436
+ if (activationValidationError) {
437
+ const next = {
438
+ ...prev,
439
+ updatedAt: nowIso(),
440
+ lastCheckedAt: nowIso(),
441
+ lastError: activationValidationError,
442
+ etag: result.etag ?? prev.etag,
443
+ remote: remoteMeta,
444
+ };
445
+ writeSkillPackState(next, { openclawDir: input.openclawDir });
446
+ return { state: next, changed: false };
447
+ }
205
448
  const next = {
206
449
  version: STORE_VERSION,
207
450
  updatedAt: nowIso(),
@@ -217,6 +460,7 @@ export async function refreshSkillPackState(input) {
217
460
  },
218
461
  remote: remoteMeta,
219
462
  overrides,
463
+ audit: prev.audit,
220
464
  };
221
465
  writeSkillPackState(next, { openclawDir: input.openclawDir });
222
466
  return { state: next, changed: prev.pack?.checksum !== next.pack?.checksum };
@@ -225,7 +469,7 @@ export async function refreshSkillPackState(input) {
225
469
  ...prev,
226
470
  updatedAt: nowIso(),
227
471
  lastCheckedAt: nowIso(),
228
- lastError: !result.ok ? result.error : prev.lastError,
472
+ lastError: result.ok === false ? result.error : prev.lastError,
229
473
  };
230
474
  writeSkillPackState(next, { openclawDir: input.openclawDir });
231
475
  return { state: next, changed: false };
@@ -1,6 +1,7 @@
1
- import { mkdirSync, readFileSync, chmodSync, existsSync, rmSync } from 'node:fs';
1
+ import { existsSync, readFileSync } from "node:fs";
2
2
  import { getOrgxPluginConfigDir, getOrgxPluginConfigPath } from './paths.js';
3
3
  import { backupCorruptFileSync, writeJsonFileAtomicSync } from './fs-utils.js';
4
+ import { clearStoreFileSync, ensureStoreDirSync, parseJsonSafe, } from "./stores/json-store.js";
4
5
  function snapshotDir() {
5
6
  return getOrgxPluginConfigDir();
6
7
  }
@@ -8,22 +9,7 @@ function snapshotFile() {
8
9
  return getOrgxPluginConfigPath('snapshot.json');
9
10
  }
10
11
  function ensureSnapshotDir() {
11
- const dir = snapshotDir();
12
- mkdirSync(dir, { recursive: true, mode: 0o700 });
13
- try {
14
- chmodSync(dir, 0o700);
15
- }
16
- catch {
17
- // best effort
18
- }
19
- }
20
- function parseJson(value) {
21
- try {
22
- return JSON.parse(value);
23
- }
24
- catch {
25
- return null;
26
- }
12
+ ensureStoreDirSync(snapshotDir());
27
13
  }
28
14
  export function readPersistedSnapshot() {
29
15
  const file = snapshotFile();
@@ -31,7 +17,7 @@ export function readPersistedSnapshot() {
31
17
  if (!existsSync(file))
32
18
  return null;
33
19
  const raw = readFileSync(file, 'utf8');
34
- const parsed = parseJson(raw);
20
+ const parsed = parseJsonSafe(raw);
35
21
  if (!parsed) {
36
22
  backupCorruptFileSync(file);
37
23
  return null;
@@ -57,11 +43,5 @@ export function writePersistedSnapshot(snapshot) {
57
43
  return record;
58
44
  }
59
45
  export function clearPersistedSnapshot() {
60
- const file = snapshotFile();
61
- try {
62
- rmSync(file, { force: true });
63
- }
64
- catch {
65
- // best effort
66
- }
46
+ clearStoreFileSync(snapshotFile());
67
47
  }
@@ -0,0 +1,11 @@
1
+ import { parseJsonSafe } from "../json-utils.js";
2
+ export declare function ensureStoreDirSync(dir: string): void;
3
+ export { parseJsonSafe };
4
+ export declare function readJsonFileOrDefault<T>(input: {
5
+ file: string;
6
+ fallback: () => T;
7
+ isValid?: (value: unknown) => value is T;
8
+ backupOnInvalid?: boolean;
9
+ }): T;
10
+ export declare function writeJsonStoreFileSync(file: string, data: unknown, mode?: number): void;
11
+ export declare function clearStoreFileSync(file: string): void;