@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,621 @@
1
+ import { registerArtifact } from "../artifacts/register-artifact.js";
2
+ import { appendOutboxDeadLetter, readOutbox, readOutboxSummary, replaceOutbox, } from "../outbox.js";
3
+ import { extractProgressOutboxMessage } from "../reporting/outbox-replay.js";
4
+ import { RETRO_ARTIFACT_SCHEMA_VERSION } from "../contracts/retro-schema.js";
5
+ import { classifyOutboxReplaySkip } from "../event-sanitization.js";
6
+ const OUTBOX_MAX_REPLAY_FAILURES = (() => {
7
+ const raw = Number(process.env.ORGX_OUTBOX_MAX_REPLAY_FAILURES ?? "");
8
+ if (!Number.isFinite(raw))
9
+ return 3;
10
+ return Math.max(1, Math.min(20, Math.floor(raw)));
11
+ })();
12
+ export function createOutboxReplayer(deps) {
13
+ const { client, logger, toErrorMessage, stableHash, resolveReportingContext, pickStringField, pickStringArrayField, toReportingPhase, parseRetroEntityType, isUuid, } = deps;
14
+ async function replayOutboxEvent(event) {
15
+ const payload = event.payload ?? {};
16
+ function normalizeRunFields(context) {
17
+ // We prefer correlation IDs for replay because many local adapters use UUID-like
18
+ // session IDs that do *not* exist as server-side run IDs.
19
+ if (context.correlationId) {
20
+ return { run_id: undefined, correlation_id: context.correlationId };
21
+ }
22
+ if (context.runId) {
23
+ return {
24
+ run_id: undefined,
25
+ correlation_id: `openclaw_run_${stableHash(context.runId).slice(0, 24)}`,
26
+ };
27
+ }
28
+ return { run_id: undefined, correlation_id: undefined };
29
+ }
30
+ function normalizeRetro(payload) {
31
+ const retro = payload.retro && typeof payload.retro === "object" && !Array.isArray(payload.retro)
32
+ ? payload.retro
33
+ : null;
34
+ const trimAndClamp = (value, maxLength) => value.trim().slice(0, maxLength);
35
+ const summary = retro && typeof retro.summary === "string"
36
+ ? trimAndClamp(retro.summary, 4000)
37
+ : "";
38
+ if (!retro || !summary) {
39
+ return null;
40
+ }
41
+ const normalizeStringList = (value) => {
42
+ if (!Array.isArray(value))
43
+ return undefined;
44
+ const normalized = value
45
+ .filter((item) => typeof item === "string")
46
+ .map((item) => trimAndClamp(item, 1000))
47
+ .filter((item) => item.length > 0)
48
+ .slice(0, 25);
49
+ return normalized.length > 0 ? normalized : undefined;
50
+ };
51
+ const pickRetroStringList = (snakeCaseKey, camelCaseKey) => normalizeStringList(retro[snakeCaseKey]) ?? normalizeStringList(retro[camelCaseKey]);
52
+ const followUpsRaw = Array.isArray(retro.follow_ups)
53
+ ? retro.follow_ups
54
+ : Array.isArray(retro.followUps)
55
+ ? retro.followUps
56
+ : [];
57
+ const followUps = [];
58
+ for (const candidate of followUpsRaw) {
59
+ if (!candidate || typeof candidate !== "object" || Array.isArray(candidate)) {
60
+ continue;
61
+ }
62
+ const title = typeof candidate.title === "string"
63
+ ? trimAndClamp(candidate.title, 500)
64
+ : "";
65
+ if (!title) {
66
+ continue;
67
+ }
68
+ const priorityRaw = typeof candidate.priority === "string"
69
+ ? candidate.priority.trim().toLowerCase()
70
+ : "";
71
+ const priority = priorityRaw === "p0" || priorityRaw === "p1" || priorityRaw === "p2"
72
+ ? priorityRaw
73
+ : undefined;
74
+ const reason = typeof candidate.reason === "string"
75
+ ? trimAndClamp(candidate.reason, 2000)
76
+ : "";
77
+ const normalizedFollowUp = { title };
78
+ if (priority) {
79
+ normalizedFollowUp.priority = priority;
80
+ }
81
+ if (reason) {
82
+ normalizedFollowUp.reason = reason;
83
+ }
84
+ followUps.push(normalizedFollowUp);
85
+ if (followUps.length >= 25) {
86
+ break;
87
+ }
88
+ }
89
+ const signals = retro.signals && typeof retro.signals === "object" && !Array.isArray(retro.signals)
90
+ ? retro.signals
91
+ : undefined;
92
+ return {
93
+ schema_version: RETRO_ARTIFACT_SCHEMA_VERSION,
94
+ summary,
95
+ what_went_well: pickRetroStringList("what_went_well", "whatWentWell"),
96
+ what_went_wrong: pickRetroStringList("what_went_wrong", "whatWentWrong"),
97
+ decisions: pickRetroStringList("decisions", "keyDecisions"),
98
+ follow_ups: followUps.length > 0 ? followUps : undefined,
99
+ signals,
100
+ };
101
+ }
102
+ if (event.type === "progress") {
103
+ const message = extractProgressOutboxMessage(payload);
104
+ if (!message) {
105
+ logger.warn?.("[orgx] Dropping invalid progress outbox event", {
106
+ eventId: event.id,
107
+ });
108
+ return;
109
+ }
110
+ const context = resolveReportingContext(payload);
111
+ if (!context.ok) {
112
+ throw new Error(context.error);
113
+ }
114
+ const rawPhase = pickStringField(payload, "phase") ?? "implementing";
115
+ const progressPct = typeof payload.progress_pct === "number"
116
+ ? payload.progress_pct
117
+ : typeof payload.progressPct === "number"
118
+ ? payload.progressPct
119
+ : undefined;
120
+ const phase = rawPhase === "intent" ||
121
+ rawPhase === "execution" ||
122
+ rawPhase === "blocked" ||
123
+ rawPhase === "review" ||
124
+ rawPhase === "handoff" ||
125
+ rawPhase === "completed"
126
+ ? rawPhase
127
+ : toReportingPhase(rawPhase, progressPct);
128
+ const metaRaw = payload.metadata;
129
+ const meta = metaRaw && typeof metaRaw === "object" && !Array.isArray(metaRaw)
130
+ ? metaRaw
131
+ : {};
132
+ const baseMetadata = {
133
+ ...meta,
134
+ source: "orgx_openclaw_outbox_replay",
135
+ outbox_event_id: event.id,
136
+ };
137
+ let emitPayload = {
138
+ initiative_id: context.value.initiativeId,
139
+ run_id: context.value.runId,
140
+ correlation_id: context.value.correlationId,
141
+ source_client: context.value.sourceClient,
142
+ message,
143
+ phase,
144
+ progress_pct: progressPct,
145
+ level: pickStringField(payload, "level"),
146
+ next_step: pickStringField(payload, "next_step") ??
147
+ pickStringField(payload, "nextStep") ??
148
+ undefined,
149
+ metadata: baseMetadata,
150
+ };
151
+ try {
152
+ await client.emitActivity(emitPayload);
153
+ }
154
+ catch (err) {
155
+ // Some locally-buffered events carry a UUID that *looks* like an OrgX run_id
156
+ // but was only ever used as a local correlation/grouping key. If OrgX
157
+ // doesn't recognize it, retry by treating it as correlation_id so OrgX can
158
+ // create/attach a run deterministically.
159
+ const msg = toErrorMessage(err);
160
+ if (emitPayload.run_id &&
161
+ /(?:^|\b)404\b/.test(msg) &&
162
+ /\brun\b/i.test(msg) &&
163
+ /not found/i.test(msg)) {
164
+ const replayCorrelationId = `openclaw_run_${stableHash(emitPayload.run_id).slice(0, 24)}`;
165
+ await client.emitActivity({
166
+ ...emitPayload,
167
+ run_id: undefined,
168
+ correlation_id: replayCorrelationId,
169
+ metadata: {
170
+ ...(emitPayload.metadata ?? {}),
171
+ replay_run_id_as_correlation: true,
172
+ },
173
+ });
174
+ }
175
+ else {
176
+ throw err;
177
+ }
178
+ }
179
+ return;
180
+ }
181
+ if (event.type === "decision") {
182
+ const question = pickStringField(payload, "question");
183
+ if (!question) {
184
+ logger.warn?.("[orgx] Dropping invalid decision outbox event", {
185
+ eventId: event.id,
186
+ });
187
+ return;
188
+ }
189
+ const context = resolveReportingContext(payload);
190
+ if (!context.ok) {
191
+ throw new Error(context.error);
192
+ }
193
+ const runFields = normalizeRunFields({
194
+ runId: context.value.runId,
195
+ correlationId: context.value.correlationId,
196
+ });
197
+ // Payloads should include a stable idempotency_key when enqueued, but older
198
+ // events may not. Derive a deterministic fallback so outbox replay won't
199
+ // double-create the same remote decision.
200
+ const fallbackKey = stableHash(JSON.stringify({
201
+ t: "decision",
202
+ initiative_id: context.value.initiativeId,
203
+ run_id: context.value.runId ?? null,
204
+ correlation_id: context.value.correlationId ?? null,
205
+ question,
206
+ })).slice(0, 24);
207
+ const resolvedIdempotencyKey = pickStringField(payload, "idempotency_key") ??
208
+ pickStringField(payload, "idempotencyKey") ??
209
+ `openclaw:decision:${fallbackKey}`;
210
+ await client.applyChangeset({
211
+ initiative_id: context.value.initiativeId,
212
+ run_id: runFields.run_id,
213
+ correlation_id: runFields.correlation_id,
214
+ source_client: context.value.sourceClient,
215
+ idempotency_key: resolvedIdempotencyKey,
216
+ operations: [
217
+ {
218
+ op: "decision.create",
219
+ title: question,
220
+ summary: pickStringField(payload, "context") ?? undefined,
221
+ urgency: pickStringField(payload, "urgency") ?? "medium",
222
+ options: pickStringArrayField(payload, "options"),
223
+ blocking: typeof payload.blocking === "boolean" ? payload.blocking : true,
224
+ },
225
+ ],
226
+ });
227
+ return;
228
+ }
229
+ if (event.type === "changeset") {
230
+ const context = resolveReportingContext(payload);
231
+ if (!context.ok) {
232
+ throw new Error(context.error);
233
+ }
234
+ const runFields = normalizeRunFields({
235
+ runId: context.value.runId,
236
+ correlationId: context.value.correlationId,
237
+ });
238
+ const operations = Array.isArray(payload.operations)
239
+ ? payload.operations
240
+ : [];
241
+ if (operations.length === 0) {
242
+ logger.warn?.("[orgx] Dropping invalid changeset outbox event", {
243
+ eventId: event.id,
244
+ });
245
+ return;
246
+ }
247
+ // Status updates are the most common offline replay payload, and `updateEntity`
248
+ // is the most widely supported primitive across OrgX deployments. Prefer it
249
+ // when the changeset contains only simple status mutations.
250
+ const statusOps = operations
251
+ .map((op) => {
252
+ if (!op || typeof op !== "object")
253
+ return null;
254
+ const record = op;
255
+ const kind = typeof record.op === "string" ? record.op.trim() : "";
256
+ if (kind === "task.update") {
257
+ const taskId = typeof record.task_id === "string" ? record.task_id.trim() : "";
258
+ const statusRaw = typeof record.status === "string" ? record.status.trim() : "";
259
+ const normalized = statusRaw.toLowerCase().replace(/\s+/g, "_");
260
+ const status = normalized === "completed" || normalized === "complete" || normalized === "finished"
261
+ ? "done"
262
+ : normalized === "inprogress"
263
+ ? "in_progress"
264
+ : normalized;
265
+ if (!taskId || !status)
266
+ return null;
267
+ return { type: "task", id: taskId, status };
268
+ }
269
+ if (kind === "milestone.update") {
270
+ const milestoneId = typeof record.milestone_id === "string" ? record.milestone_id.trim() : "";
271
+ const statusRaw = typeof record.status === "string" ? record.status.trim() : "";
272
+ const normalized = statusRaw.toLowerCase().replace(/\s+/g, "_");
273
+ const status = normalized === "done" || normalized === "complete" || normalized === "finished"
274
+ ? "completed"
275
+ : normalized === "inprogress"
276
+ ? "in_progress"
277
+ : normalized === "todo" || normalized === "not_started" || normalized === "pending"
278
+ ? "planned"
279
+ : normalized === "blocked" || normalized === "stuck"
280
+ ? "at_risk"
281
+ : normalized;
282
+ if (!milestoneId || !status)
283
+ return null;
284
+ return { type: "milestone", id: milestoneId, status };
285
+ }
286
+ return null;
287
+ })
288
+ .filter((item) => Boolean(item));
289
+ if (statusOps.length === operations.length) {
290
+ for (const op of statusOps) {
291
+ await client.updateEntity(op.type, op.id, { status: op.status });
292
+ }
293
+ return;
294
+ }
295
+ // Payloads should include a stable idempotency_key when enqueued, but older
296
+ // events may not. Derive a deterministic fallback so outbox replay won't
297
+ // double-create the same remote change.
298
+ const fallbackKey = stableHash(JSON.stringify({
299
+ t: "changeset",
300
+ initiative_id: context.value.initiativeId,
301
+ run_id: context.value.runId ?? null,
302
+ correlation_id: context.value.correlationId ?? null,
303
+ operations,
304
+ })).slice(0, 24);
305
+ const resolvedIdempotencyKey = pickStringField(payload, "idempotency_key") ??
306
+ pickStringField(payload, "idempotencyKey") ??
307
+ `openclaw:changeset:${fallbackKey}`;
308
+ await client.applyChangeset({
309
+ initiative_id: context.value.initiativeId,
310
+ run_id: runFields.run_id,
311
+ correlation_id: runFields.correlation_id,
312
+ source_client: context.value.sourceClient,
313
+ idempotency_key: resolvedIdempotencyKey,
314
+ operations,
315
+ });
316
+ return;
317
+ }
318
+ if (event.type === "outcome") {
319
+ const context = resolveReportingContext(payload);
320
+ if (!context.ok) {
321
+ throw new Error(context.error);
322
+ }
323
+ const runFields = normalizeRunFields({
324
+ runId: context.value.runId,
325
+ correlationId: context.value.correlationId,
326
+ });
327
+ const executionId = pickStringField(payload, "execution_id") ??
328
+ pickStringField(payload, "executionId");
329
+ const executionType = pickStringField(payload, "execution_type") ??
330
+ pickStringField(payload, "executionType");
331
+ const agentId = pickStringField(payload, "agent_id") ??
332
+ pickStringField(payload, "agentId");
333
+ const success = typeof payload.success === "boolean"
334
+ ? payload.success
335
+ : null;
336
+ if (!executionId || !executionType || !agentId || success === null) {
337
+ logger.warn?.("[orgx] Dropping invalid outcome outbox event", {
338
+ eventId: event.id,
339
+ });
340
+ return;
341
+ }
342
+ const metaRaw = payload.metadata;
343
+ const meta = metaRaw && typeof metaRaw === "object" && !Array.isArray(metaRaw)
344
+ ? metaRaw
345
+ : {};
346
+ await client.recordRunOutcome({
347
+ initiative_id: context.value.initiativeId,
348
+ run_id: runFields.run_id,
349
+ correlation_id: runFields.correlation_id,
350
+ source_client: context.value.sourceClient,
351
+ execution_id: executionId,
352
+ execution_type: executionType,
353
+ agent_id: agentId,
354
+ task_type: pickStringField(payload, "task_type") ??
355
+ pickStringField(payload, "taskType") ??
356
+ undefined,
357
+ domain: pickStringField(payload, "domain") ?? undefined,
358
+ started_at: pickStringField(payload, "started_at") ??
359
+ pickStringField(payload, "startedAt") ??
360
+ undefined,
361
+ completed_at: pickStringField(payload, "completed_at") ??
362
+ pickStringField(payload, "completedAt") ??
363
+ undefined,
364
+ inputs: payload.inputs && typeof payload.inputs === "object"
365
+ ? payload.inputs
366
+ : undefined,
367
+ outputs: payload.outputs && typeof payload.outputs === "object"
368
+ ? payload.outputs
369
+ : undefined,
370
+ steps: Array.isArray(payload.steps)
371
+ ? payload.steps
372
+ : undefined,
373
+ success,
374
+ quality_score: typeof payload.quality_score === "number"
375
+ ? payload.quality_score
376
+ : typeof payload.qualityScore === "number"
377
+ ? payload.qualityScore
378
+ : undefined,
379
+ duration_vs_estimate: typeof payload.duration_vs_estimate === "number"
380
+ ? payload.duration_vs_estimate
381
+ : typeof payload.durationVsEstimate === "number"
382
+ ? payload.durationVsEstimate
383
+ : undefined,
384
+ cost_vs_budget: typeof payload.cost_vs_budget === "number"
385
+ ? payload.cost_vs_budget
386
+ : typeof payload.costVsBudget === "number"
387
+ ? payload.costVsBudget
388
+ : undefined,
389
+ human_interventions: typeof payload.human_interventions === "number"
390
+ ? payload.human_interventions
391
+ : typeof payload.humanInterventions === "number"
392
+ ? payload.humanInterventions
393
+ : undefined,
394
+ user_satisfaction: typeof payload.user_satisfaction === "number"
395
+ ? payload.user_satisfaction
396
+ : typeof payload.userSatisfaction === "number"
397
+ ? payload.userSatisfaction
398
+ : undefined,
399
+ errors: Array.isArray(payload.errors)
400
+ ? payload.errors.filter((e) => typeof e === "string")
401
+ : undefined,
402
+ metadata: {
403
+ ...meta,
404
+ source: "orgx_openclaw_outbox_replay",
405
+ outbox_event_id: event.id,
406
+ },
407
+ });
408
+ return;
409
+ }
410
+ if (event.type === "retro") {
411
+ const context = resolveReportingContext(payload);
412
+ if (!context.ok) {
413
+ throw new Error(context.error);
414
+ }
415
+ const runFields = normalizeRunFields({
416
+ runId: context.value.runId,
417
+ correlationId: context.value.correlationId,
418
+ });
419
+ const normalizedRetro = normalizeRetro(payload);
420
+ if (!normalizedRetro) {
421
+ logger.warn?.("[orgx] Dropping invalid retro outbox event", {
422
+ eventId: event.id,
423
+ });
424
+ return;
425
+ }
426
+ const entityTypeRaw = pickStringField(payload, "entity_type") ??
427
+ pickStringField(payload, "entityType");
428
+ const parsedEntityType = parseRetroEntityType(entityTypeRaw) ?? null;
429
+ // Server-side enum parity can lag behind local clients. Only attach to the
430
+ // entity types that are guaranteed to exist today.
431
+ const entityType = parsedEntityType === "initiative" || parsedEntityType === "task"
432
+ ? parsedEntityType
433
+ : null;
434
+ const entityIdRaw = pickStringField(payload, "entity_id") ??
435
+ pickStringField(payload, "entityId") ??
436
+ null;
437
+ const entityId = isUuid(entityIdRaw ?? undefined) ? entityIdRaw : null;
438
+ await client.recordRunRetro({
439
+ initiative_id: context.value.initiativeId,
440
+ run_id: runFields.run_id,
441
+ correlation_id: runFields.correlation_id,
442
+ source_client: context.value.sourceClient,
443
+ entity_type: entityType && entityId ? entityType : undefined,
444
+ entity_id: entityType && entityId ? entityId : undefined,
445
+ title: pickStringField(payload, "title") ?? undefined,
446
+ idempotency_key: pickStringField(payload, "idempotency_key") ??
447
+ pickStringField(payload, "idempotencyKey") ??
448
+ undefined,
449
+ retro: normalizedRetro,
450
+ markdown: pickStringField(payload, "markdown") ?? undefined,
451
+ });
452
+ return;
453
+ }
454
+ if (event.type === "artifact") {
455
+ // Artifacts are first-class UX loop closure (activity stream + entity modals).
456
+ // Try to persist upstream; if this fails, keep the event queued for retry.
457
+ const payload = event.payload && typeof event.payload === "object" && !Array.isArray(event.payload)
458
+ ? event.payload
459
+ : {};
460
+ const name = pickStringField(payload, "name") ?? pickStringField(payload, "title") ?? "";
461
+ const artifactType = pickStringField(payload, "artifact_type") ?? "other";
462
+ const entityType = pickStringField(payload, "entity_type") ?? "";
463
+ const entityId = pickStringField(payload, "entity_id") ?? "";
464
+ const artifactId = pickStringField(payload, "artifact_id") ?? null;
465
+ const description = pickStringField(payload, "description") ?? undefined;
466
+ const externalUrl = pickStringField(payload, "url") ?? pickStringField(payload, "artifact_url") ?? null;
467
+ const content = pickStringField(payload, "content") ?? pickStringField(payload, "preview_markdown") ?? null;
468
+ const confidenceRaw = payload.confidence_score;
469
+ const confidenceScore = typeof confidenceRaw === "number" &&
470
+ Number.isFinite(confidenceRaw) &&
471
+ confidenceRaw >= 0 &&
472
+ confidenceRaw <= 1
473
+ ? confidenceRaw
474
+ : null;
475
+ const allowedEntityType = entityType === "initiative" ||
476
+ entityType === "milestone" ||
477
+ entityType === "task" ||
478
+ entityType === "decision" ||
479
+ entityType === "project"
480
+ ? entityType
481
+ : null;
482
+ if (!allowedEntityType || !entityId.trim() || !name.trim()) {
483
+ logger.warn?.("[orgx] Dropping invalid artifact outbox event", {
484
+ eventId: event.id,
485
+ entityType,
486
+ entityId,
487
+ });
488
+ return;
489
+ }
490
+ const result = await registerArtifact(client, client.getBaseUrl(), {
491
+ artifact_id: artifactId,
492
+ entity_type: allowedEntityType,
493
+ entity_id: entityId,
494
+ name: name.trim(),
495
+ artifact_type: artifactType.trim() || "other",
496
+ confidence_score: confidenceScore,
497
+ description,
498
+ external_url: externalUrl,
499
+ preview_markdown: content,
500
+ status: "draft",
501
+ metadata: {
502
+ source: "outbox_replay",
503
+ outbox_event_id: event.id,
504
+ confidence_score: confidenceScore,
505
+ ...(payload.metadata && typeof payload.metadata === "object" && !Array.isArray(payload.metadata)
506
+ ? payload.metadata
507
+ : {}),
508
+ },
509
+ validate_persistence: process.env.ORGX_VALIDATE_ARTIFACT_PERSISTENCE === "1",
510
+ });
511
+ if (!result.ok) {
512
+ throw new Error(result.persistence.last_error ?? "artifact registration failed");
513
+ }
514
+ return;
515
+ }
516
+ }
517
+ async function flushOutboxQueues() {
518
+ const attemptAt = new Date().toISOString();
519
+ deps.writeOutboxReplayState({
520
+ ...deps.readOutboxReplayState(),
521
+ status: "running",
522
+ lastReplayAttemptAt: attemptAt,
523
+ lastReplayError: null,
524
+ });
525
+ let hadReplayFailure = false;
526
+ let lastReplayError = null;
527
+ // Outbox files are keyed by *session id* (e.g. initiative/run correlation),
528
+ // not by event type.
529
+ const outboxSummary = await readOutboxSummary();
530
+ const queues = Object.entries(outboxSummary.pendingByQueue)
531
+ .filter(([, count]) => typeof count === "number" && count > 0)
532
+ .map(([queueId]) => queueId)
533
+ .sort();
534
+ for (const queue of queues) {
535
+ const pending = await readOutbox(queue);
536
+ if (pending.length === 0) {
537
+ continue;
538
+ }
539
+ const remaining = [];
540
+ for (const event of pending) {
541
+ const skipReason = classifyOutboxReplaySkip(event);
542
+ if (skipReason) {
543
+ await appendOutboxDeadLetter(queue, event, `dropped_before_replay:${skipReason}`, null);
544
+ logger.warn?.("[orgx] Dropping non-replayable outbox event", {
545
+ queue,
546
+ eventId: event.id,
547
+ reason: skipReason,
548
+ });
549
+ continue;
550
+ }
551
+ try {
552
+ await replayOutboxEvent(event);
553
+ }
554
+ catch (err) {
555
+ hadReplayFailure = true;
556
+ lastReplayError = toErrorMessage(err);
557
+ const nextFailures = typeof event.replayFailures === "number" && Number.isFinite(event.replayFailures)
558
+ ? Math.max(0, Math.floor(event.replayFailures)) + 1
559
+ : 1;
560
+ if (nextFailures >= OUTBOX_MAX_REPLAY_FAILURES) {
561
+ await appendOutboxDeadLetter(queue, {
562
+ ...event,
563
+ replayFailures: nextFailures,
564
+ lastReplayError,
565
+ lastReplayAt: new Date().toISOString(),
566
+ }, "max_replay_failures", lastReplayError);
567
+ logger.warn?.("[orgx] Dead-lettering outbox event after max replay failures", {
568
+ queue,
569
+ eventId: event.id,
570
+ failures: nextFailures,
571
+ maxFailures: OUTBOX_MAX_REPLAY_FAILURES,
572
+ error: lastReplayError,
573
+ });
574
+ continue;
575
+ }
576
+ remaining.push({
577
+ ...event,
578
+ replayFailures: nextFailures,
579
+ lastReplayError,
580
+ lastReplayAt: new Date().toISOString(),
581
+ });
582
+ logger.warn?.("[orgx] Outbox replay failed", {
583
+ queue,
584
+ eventId: event.id,
585
+ replayFailures: nextFailures,
586
+ error: lastReplayError,
587
+ });
588
+ }
589
+ }
590
+ await replaceOutbox(queue, remaining);
591
+ const replayedCount = pending.length - remaining.length;
592
+ if (replayedCount > 0) {
593
+ logger.info?.("[orgx] Replayed buffered outbox events", {
594
+ queue,
595
+ replayed: replayedCount,
596
+ remaining: remaining.length,
597
+ });
598
+ }
599
+ }
600
+ if (hadReplayFailure) {
601
+ deps.writeOutboxReplayState({
602
+ ...deps.readOutboxReplayState(),
603
+ status: "error",
604
+ lastReplayFailureAt: new Date().toISOString(),
605
+ lastReplayError,
606
+ });
607
+ }
608
+ else {
609
+ deps.writeOutboxReplayState({
610
+ ...deps.readOutboxReplayState(),
611
+ status: "success",
612
+ lastReplaySuccessAt: new Date().toISOString(),
613
+ lastReplayError: null,
614
+ });
615
+ }
616
+ }
617
+ return {
618
+ replayOutboxEvent,
619
+ flushOutboxQueues,
620
+ };
621
+ }
@@ -0,0 +1,23 @@
1
+ export type TeamCompletion = {
2
+ domain: string;
3
+ task_title: string;
4
+ summary: string;
5
+ key_outputs?: string[];
6
+ completed_at: string;
7
+ };
8
+ export type TeamDecision = {
9
+ title: string;
10
+ resolution: string;
11
+ affected_domains?: string[];
12
+ resolved_at: string;
13
+ };
14
+ type PersistedTeamContext = {
15
+ updatedAt: string;
16
+ recent_completions: TeamCompletion[];
17
+ recent_decisions: TeamDecision[];
18
+ };
19
+ export declare function readTeamContext(initiativeId: string): PersistedTeamContext;
20
+ export declare function appendTeamCompletion(initiativeId: string, completion: TeamCompletion): void;
21
+ export declare function appendTeamDecision(initiativeId: string, decision: TeamDecision): void;
22
+ export declare function clearTeamContext(initiativeId?: string): void;
23
+ export {};