@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
@@ -1,41 +1,43 @@
1
- import { chmodSync, existsSync, mkdirSync, readFileSync, } from "node:fs";
1
+ import { existsSync, readFileSync, } from "node:fs";
2
2
  import { Buffer } from "node:buffer";
3
3
  import { enrichActivityActorFieldsList } from "./activity-actor-fields.js";
4
+ import { shouldHideActivityItem } from "./event-sanitization.js";
4
5
  import { getOrgxPluginConfigDir, getOrgxPluginConfigPath } from "./paths.js";
5
- import { backupCorruptFileSync, writeJsonFileAtomicSync } from "./fs-utils.js";
6
+ import { backupCorruptFileSync, writeFileAtomicSync } from "./fs-utils.js";
7
+ import { ensureStoreDirSync, parseJsonSafe } from "./stores/json-store.js";
6
8
  const STORE_VERSION = 1;
7
9
  const STORE_FILENAME = "activity-store.json";
8
- const MAX_ITEMS = 50_000;
9
- const RETENTION_DAYS = 45;
10
- const FLUSH_DEBOUNCE_MS = 1_250;
10
+ const MAX_ITEMS = 10_000;
11
+ const RETENTION_DAYS = 14;
12
+ const FLUSH_DEBOUNCE_MS = 3_000;
11
13
  let cached = null;
12
14
  function ensureDir() {
13
- const dir = getOrgxPluginConfigDir();
14
- mkdirSync(dir, { recursive: true, mode: 0o700 });
15
- try {
16
- chmodSync(dir, 0o700);
17
- }
18
- catch {
19
- // best effort
20
- }
15
+ ensureStoreDirSync(getOrgxPluginConfigDir());
21
16
  }
22
17
  function storePath() {
23
18
  return getOrgxPluginConfigPath(STORE_FILENAME);
24
19
  }
25
- function parseJson(value) {
26
- try {
27
- return JSON.parse(value);
28
- }
29
- catch {
30
- return null;
31
- }
32
- }
33
20
  function toEpoch(value) {
34
21
  if (!value)
35
22
  return 0;
36
23
  const parsed = Date.parse(value);
37
24
  return Number.isFinite(parsed) ? parsed : 0;
38
25
  }
26
+ function shallowMetadataEqual(a, b) {
27
+ if (a == null && b == null)
28
+ return true;
29
+ if (a == null || b == null)
30
+ return false;
31
+ const keysA = Object.keys(a);
32
+ const keysB = Object.keys(b);
33
+ if (keysA.length !== keysB.length)
34
+ return false;
35
+ for (const key of keysA) {
36
+ if (a[key] !== b[key])
37
+ return false;
38
+ }
39
+ return true;
40
+ }
39
41
  function compareActivity(a, b) {
40
42
  const delta = toEpoch(b.timestamp) - toEpoch(a.timestamp);
41
43
  if (delta !== 0)
@@ -61,6 +63,8 @@ function normalizeItems(source) {
61
63
  continue;
62
64
  if (epoch < cutoffEpoch)
63
65
  continue;
66
+ if (shouldHideActivityItem(item))
67
+ continue;
64
68
  byId.set(id, item);
65
69
  }
66
70
  return enrichActivityActorFieldsList(Array.from(byId.values()))
@@ -75,7 +79,7 @@ function readPersistedStore() {
75
79
  }
76
80
  try {
77
81
  const raw = readFileSync(file, "utf8");
78
- const parsed = parseJson(raw);
82
+ const parsed = parseJsonSafe(raw);
79
83
  if (!parsed || parsed.version !== STORE_VERSION || !Array.isArray(parsed.items)) {
80
84
  backupCorruptFileSync(file);
81
85
  return { version: STORE_VERSION, updatedAt: new Date().toISOString(), items: [] };
@@ -151,7 +155,7 @@ function scheduleFlush(state) {
151
155
  updatedAt: state.storeUpdatedAt,
152
156
  items: state.items,
153
157
  };
154
- writeJsonFileAtomicSync(storePath(), payload, 0o600);
158
+ writeFileAtomicSync(storePath(), JSON.stringify(payload), { mode: 0o600 });
155
159
  }, FLUSH_DEBOUNCE_MS);
156
160
  state.flushTimer.unref?.();
157
161
  }
@@ -172,6 +176,8 @@ export function appendActivityItems(items) {
172
176
  continue;
173
177
  if (!Number.isFinite(Date.parse(item.timestamp)))
174
178
  continue;
179
+ if (shouldHideActivityItem(item))
180
+ continue;
175
181
  const id = item.id.trim();
176
182
  const existing = state.byId.get(id);
177
183
  if (!existing) {
@@ -189,7 +195,7 @@ export function appendActivityItems(items) {
189
195
  (existing.executorAgentId ?? null) !== (item.executorAgentId ?? null) ||
190
196
  (existing.executorAgentName ?? null) !== (item.executorAgentName ?? null) ||
191
197
  existing.summary !== item.summary ||
192
- JSON.stringify(existing.metadata ?? null) !== JSON.stringify(item.metadata ?? null)) {
198
+ !shallowMetadataEqual(existing.metadata, item.metadata)) {
193
199
  state.byId.set(id, item);
194
200
  updated += 1;
195
201
  }
@@ -197,8 +203,14 @@ export function appendActivityItems(items) {
197
203
  if (appended === 0 && updated === 0) {
198
204
  return { appended: 0, updated: 0, total: state.items.length };
199
205
  }
200
- // Rebuild sorted list from map. This is O(n) but bounded by MAX_ITEMS.
201
- state.items = normalizeItems(Array.from(state.byId.values()));
206
+ // Rebuild sorted list from map, bounded by MAX_ITEMS.
207
+ // Skip full normalizeItems (enrichment + dedup) for small batches — items are already validated above.
208
+ if (appended + updated > 50) {
209
+ state.items = normalizeItems(Array.from(state.byId.values()));
210
+ }
211
+ else {
212
+ state.items = Array.from(state.byId.values()).sort(compareActivity).slice(0, MAX_ITEMS);
213
+ }
202
214
  state.byId = new Map(state.items.map((item) => [item.id, item]));
203
215
  state.dirty = true;
204
216
  scheduleFlush(state);
@@ -1,8 +1,73 @@
1
- import { chmodSync, existsSync, mkdirSync, readFileSync, 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
  const MAX_AGENTS = 120;
5
6
  const MAX_RUNS = 480;
7
+ function timestampSortValue(value) {
8
+ const parsed = Date.parse(value);
9
+ return Number.isFinite(parsed) ? parsed : 0;
10
+ }
11
+ function isRecord(value) {
12
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
13
+ }
14
+ function asOptionalString(value) {
15
+ if (typeof value !== "string")
16
+ return null;
17
+ const trimmed = value.trim();
18
+ return trimmed.length > 0 ? trimmed : null;
19
+ }
20
+ function asTimestamp(value) {
21
+ if (typeof value === "string" && value.trim().length > 0)
22
+ return value;
23
+ return new Date().toISOString();
24
+ }
25
+ function normalizeAgentContextsMap(input) {
26
+ if (!isRecord(input))
27
+ return {};
28
+ const normalized = {};
29
+ for (const [key, value] of Object.entries(input)) {
30
+ if (!isRecord(value))
31
+ continue;
32
+ const hasExplicitAgentId = Object.prototype.hasOwnProperty.call(value, "agentId");
33
+ const id = hasExplicitAgentId ? asOptionalString(value.agentId) : asOptionalString(key);
34
+ if (!id)
35
+ continue;
36
+ normalized[id] = {
37
+ agentId: id,
38
+ initiativeId: asOptionalString(value.initiativeId),
39
+ initiativeTitle: asOptionalString(value.initiativeTitle),
40
+ workstreamId: asOptionalString(value.workstreamId),
41
+ taskId: asOptionalString(value.taskId),
42
+ updatedAt: asTimestamp(value.updatedAt),
43
+ };
44
+ }
45
+ return normalized;
46
+ }
47
+ function normalizeRunContextsMap(input) {
48
+ if (!isRecord(input))
49
+ return {};
50
+ const normalized = {};
51
+ for (const [key, value] of Object.entries(input)) {
52
+ if (!isRecord(value))
53
+ continue;
54
+ const hasExplicitRunId = Object.prototype.hasOwnProperty.call(value, "runId");
55
+ const runId = hasExplicitRunId ? asOptionalString(value.runId) : asOptionalString(key);
56
+ const agentId = asOptionalString(value.agentId);
57
+ if (!runId || !agentId)
58
+ continue;
59
+ normalized[runId] = {
60
+ runId,
61
+ agentId,
62
+ initiativeId: asOptionalString(value.initiativeId),
63
+ initiativeTitle: asOptionalString(value.initiativeTitle),
64
+ workstreamId: asOptionalString(value.workstreamId),
65
+ taskId: asOptionalString(value.taskId),
66
+ updatedAt: asTimestamp(value.updatedAt),
67
+ };
68
+ }
69
+ return normalized;
70
+ }
6
71
  function contextDir() {
7
72
  return getOrgxPluginConfigDir();
8
73
  }
@@ -10,42 +75,27 @@ function contextFile() {
10
75
  return getOrgxPluginConfigPath("agent-contexts.json");
11
76
  }
12
77
  function ensureContextDir() {
13
- const dir = contextDir();
14
- mkdirSync(dir, { recursive: true, mode: 0o700 });
15
- try {
16
- chmodSync(dir, 0o700);
17
- }
18
- catch {
19
- // best effort
20
- }
21
- }
22
- function parseJson(value) {
23
- try {
24
- return JSON.parse(value);
25
- }
26
- catch {
27
- return null;
28
- }
78
+ ensureStoreDirSync(contextDir());
29
79
  }
30
80
  function normalizeContext(input) {
31
81
  return {
32
82
  agentId: input.agentId.trim(),
33
- initiativeId: input.initiativeId ?? null,
34
- initiativeTitle: input.initiativeTitle ?? null,
35
- workstreamId: input.workstreamId ?? null,
36
- taskId: input.taskId ?? null,
37
- updatedAt: input.updatedAt,
83
+ initiativeId: asOptionalString(input.initiativeId),
84
+ initiativeTitle: asOptionalString(input.initiativeTitle),
85
+ workstreamId: asOptionalString(input.workstreamId),
86
+ taskId: asOptionalString(input.taskId),
87
+ updatedAt: asTimestamp(input.updatedAt),
38
88
  };
39
89
  }
40
90
  function normalizeRunContext(input) {
41
91
  return {
42
92
  runId: input.runId.trim(),
43
93
  agentId: input.agentId.trim(),
44
- initiativeId: input.initiativeId ?? null,
45
- initiativeTitle: input.initiativeTitle ?? null,
46
- workstreamId: input.workstreamId ?? null,
47
- taskId: input.taskId ?? null,
48
- updatedAt: input.updatedAt,
94
+ initiativeId: asOptionalString(input.initiativeId),
95
+ initiativeTitle: asOptionalString(input.initiativeTitle),
96
+ workstreamId: asOptionalString(input.workstreamId),
97
+ taskId: asOptionalString(input.taskId),
98
+ updatedAt: asTimestamp(input.updatedAt),
49
99
  };
50
100
  }
51
101
  export function readAgentContexts() {
@@ -55,17 +105,15 @@ export function readAgentContexts() {
55
105
  return { updatedAt: new Date().toISOString(), agents: {}, runs: {} };
56
106
  }
57
107
  const raw = readFileSync(file, "utf8");
58
- const parsed = parseJson(raw);
108
+ const parsed = parseJsonSafe(raw);
59
109
  if (!parsed || typeof parsed !== "object") {
60
110
  backupCorruptFileSync(file);
61
111
  return { updatedAt: new Date().toISOString(), agents: {}, runs: {} };
62
112
  }
63
- const agents = parsed.agents && typeof parsed.agents === "object" ? parsed.agents : {};
64
- const runs = parsed.runs && typeof parsed.runs === "object" ? parsed.runs : {};
113
+ const agents = normalizeAgentContextsMap(parsed.agents);
114
+ const runs = normalizeRunContextsMap(parsed.runs);
65
115
  return {
66
- updatedAt: typeof parsed.updatedAt === "string"
67
- ? parsed.updatedAt
68
- : new Date().toISOString(),
116
+ updatedAt: asTimestamp(parsed.updatedAt),
69
117
  agents: agents,
70
118
  runs: runs,
71
119
  };
@@ -109,7 +157,7 @@ export function upsertAgentContext(input) {
109
157
  // Prune if the file grows unbounded (rare).
110
158
  const values = Object.values(next.agents);
111
159
  if (values.length > MAX_AGENTS) {
112
- values.sort((a, b) => Date.parse(b.updatedAt) - Date.parse(a.updatedAt));
160
+ values.sort((a, b) => timestampSortValue(b.updatedAt) - timestampSortValue(a.updatedAt));
113
161
  const keep = new Set(values.slice(0, MAX_AGENTS).map((c) => c.agentId));
114
162
  for (const key of Object.keys(next.agents)) {
115
163
  if (!keep.has(key)) {
@@ -144,7 +192,7 @@ export function upsertRunContext(input) {
144
192
  next.updatedAt = new Date().toISOString();
145
193
  const values = Object.values(next.runs);
146
194
  if (values.length > MAX_RUNS) {
147
- values.sort((a, b) => Date.parse(b.updatedAt) - Date.parse(a.updatedAt));
195
+ values.sort((a, b) => timestampSortValue(b.updatedAt) - timestampSortValue(a.updatedAt));
148
196
  const keep = new Set(values.slice(0, MAX_RUNS).map((c) => c.runId));
149
197
  for (const key of Object.keys(next.runs)) {
150
198
  if (!keep.has(key)) {
@@ -157,11 +205,5 @@ export function upsertRunContext(input) {
157
205
  return next;
158
206
  }
159
207
  export function clearAgentContexts() {
160
- const file = contextFile();
161
- try {
162
- rmSync(file, { force: true });
163
- }
164
- catch {
165
- // best effort
166
- }
208
+ clearStoreFileSync(contextFile());
167
209
  }
@@ -1,6 +1,7 @@
1
- import { chmodSync, existsSync, mkdirSync, readFileSync, 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
  const MAX_RUNS = 240;
5
6
  function runDir() {
6
7
  return getOrgxPluginConfigDir();
@@ -9,22 +10,7 @@ function runFile() {
9
10
  return getOrgxPluginConfigPath("agent-runs.json");
10
11
  }
11
12
  function ensureRunDir() {
12
- const dir = runDir();
13
- mkdirSync(dir, { recursive: true, mode: 0o700 });
14
- try {
15
- chmodSync(dir, 0o700);
16
- }
17
- catch {
18
- // best effort
19
- }
20
- }
21
- function parseJson(value) {
22
- try {
23
- return JSON.parse(value);
24
- }
25
- catch {
26
- return null;
27
- }
13
+ ensureStoreDirSync(runDir());
28
14
  }
29
15
  function normalizeNullableString(value) {
30
16
  if (typeof value !== "string")
@@ -32,7 +18,24 @@ function normalizeNullableString(value) {
32
18
  const trimmed = value.trim();
33
19
  return trimmed.length > 0 ? trimmed : null;
34
20
  }
21
+ function normalizeTimestamp(value, fallback) {
22
+ if (typeof value !== "string")
23
+ return fallback;
24
+ const trimmed = value.trim();
25
+ if (!trimmed)
26
+ return fallback;
27
+ return Number.isFinite(Date.parse(trimmed)) ? trimmed : fallback;
28
+ }
29
+ function normalizeNullableTimestamp(value) {
30
+ if (typeof value !== "string")
31
+ return null;
32
+ const trimmed = value.trim();
33
+ if (!trimmed)
34
+ return null;
35
+ return Number.isFinite(Date.parse(trimmed)) ? trimmed : null;
36
+ }
35
37
  function normalizeRecord(input) {
38
+ const now = new Date().toISOString();
36
39
  return {
37
40
  runId: input.runId.trim(),
38
41
  agentId: input.agentId.trim(),
@@ -44,8 +47,8 @@ function normalizeRecord(input) {
44
47
  initiativeTitle: normalizeNullableString(input.initiativeTitle),
45
48
  workstreamId: normalizeNullableString(input.workstreamId),
46
49
  taskId: normalizeNullableString(input.taskId),
47
- startedAt: input.startedAt,
48
- stoppedAt: input.stoppedAt ?? null,
50
+ startedAt: normalizeTimestamp(input.startedAt, now),
51
+ stoppedAt: normalizeNullableTimestamp(input.stoppedAt),
49
52
  status: input.status === "stopped" ? "stopped" : "running",
50
53
  };
51
54
  }
@@ -56,15 +59,39 @@ export function readAgentRuns() {
56
59
  return { updatedAt: new Date().toISOString(), runs: {} };
57
60
  }
58
61
  const raw = readFileSync(file, "utf8");
59
- const parsed = parseJson(raw);
62
+ const parsed = parseJsonSafe(raw);
60
63
  if (!parsed || typeof parsed !== "object") {
61
64
  backupCorruptFileSync(file);
62
65
  return { updatedAt: new Date().toISOString(), runs: {} };
63
66
  }
64
67
  const runs = parsed.runs && typeof parsed.runs === "object" ? parsed.runs : {};
68
+ const normalizedRuns = {};
69
+ for (const [runKey, runValue] of Object.entries(runs)) {
70
+ if (!runValue || typeof runValue !== "object")
71
+ continue;
72
+ const input = runValue;
73
+ const normalized = normalizeRecord({
74
+ runId: typeof input.runId === "string" ? input.runId : runKey,
75
+ agentId: typeof input.agentId === "string" ? input.agentId : "",
76
+ pid: typeof input.pid === "number" ? input.pid : null,
77
+ message: typeof input.message === "string" ? input.message : null,
78
+ provider: typeof input.provider === "string" ? input.provider : null,
79
+ model: typeof input.model === "string" ? input.model : null,
80
+ initiativeId: typeof input.initiativeId === "string" ? input.initiativeId : null,
81
+ initiativeTitle: typeof input.initiativeTitle === "string" ? input.initiativeTitle : null,
82
+ workstreamId: typeof input.workstreamId === "string" ? input.workstreamId : null,
83
+ taskId: typeof input.taskId === "string" ? input.taskId : null,
84
+ startedAt: typeof input.startedAt === "string" ? input.startedAt : "",
85
+ stoppedAt: typeof input.stoppedAt === "string" ? input.stoppedAt : null,
86
+ status: input.status === "stopped" ? "stopped" : "running",
87
+ });
88
+ if (!normalized.runId || !normalized.agentId)
89
+ continue;
90
+ normalizedRuns[normalized.runId] = normalized;
91
+ }
65
92
  return {
66
93
  updatedAt: typeof parsed.updatedAt === "string" ? parsed.updatedAt : new Date().toISOString(),
67
- runs: runs,
94
+ runs: normalizedRuns,
68
95
  };
69
96
  }
70
97
  catch {
@@ -148,11 +175,5 @@ export function markAgentRunStopped(runId) {
148
175
  return updated ? normalizeRecord(updated) : null;
149
176
  }
150
177
  export function clearAgentRuns() {
151
- const file = runFile();
152
- try {
153
- rmSync(file, { force: true });
154
- }
155
- catch {
156
- // best effort
157
- }
178
+ clearStoreFileSync(runFile());
158
179
  }
@@ -4,6 +4,7 @@ export type OrgxSuiteAgentSpec = {
4
4
  name: string;
5
5
  domain: OrgxSuiteDomain;
6
6
  };
7
+ export type OrgxAgentConfigHealthStatus = "healthy" | "needs_apply" | "conflict";
7
8
  export declare const ORGX_AGENT_SUITE_PACK_ID = "orgx-agent-suite";
8
9
  export declare const ORGX_AGENT_SUITE_AGENTS: OrgxSuiteAgentSpec[];
9
10
  declare const SUITE_FILES: readonly ["AGENTS.md", "TOOLS.md", "IDENTITY.md", "SKILL.md", "SOUL.md", "USER.md", "HEARTBEAT.md"];
@@ -47,6 +48,14 @@ export type OrgxAgentSuiteStatus = {
47
48
  workspace: string;
48
49
  configuredInOpenclaw: boolean;
49
50
  workspaceExists: boolean;
51
+ configHealth: {
52
+ status: OrgxAgentConfigHealthStatus;
53
+ lastChangedAt: string | null;
54
+ evalPassRate: number;
55
+ totalChecks: number;
56
+ passedChecks: number;
57
+ failedChecks: number;
58
+ };
50
59
  }>;
51
60
  };
52
61
  export type OrgxAgentSuitePlan = OrgxAgentSuiteStatus & {