@useorgx/openclaw-plugin 0.4.9 → 0.7.2

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 (224) hide show
  1. package/README.md +77 -11
  2. package/dashboard/dist/assets/6mILZQ2a.js +1 -0
  3. package/dashboard/dist/assets/6mILZQ2a.js.br +0 -0
  4. package/dashboard/dist/assets/6mILZQ2a.js.gz +0 -0
  5. package/dashboard/dist/assets/8dksYiq4.js +2 -0
  6. package/dashboard/dist/assets/8dksYiq4.js.br +0 -0
  7. package/dashboard/dist/assets/8dksYiq4.js.gz +0 -0
  8. package/dashboard/dist/assets/B5zYRHc3.js +1 -0
  9. package/dashboard/dist/assets/B5zYRHc3.js.br +0 -0
  10. package/dashboard/dist/assets/B5zYRHc3.js.gz +0 -0
  11. package/dashboard/dist/assets/B6wPWJ35.js +1 -0
  12. package/dashboard/dist/assets/B6wPWJ35.js.br +0 -0
  13. package/dashboard/dist/assets/B6wPWJ35.js.gz +0 -0
  14. package/dashboard/dist/assets/BJgZIVUQ.js +53 -0
  15. package/dashboard/dist/assets/BJgZIVUQ.js.br +0 -0
  16. package/dashboard/dist/assets/BJgZIVUQ.js.gz +0 -0
  17. package/dashboard/dist/assets/BWEwjt1W.js +1 -0
  18. package/dashboard/dist/assets/BWEwjt1W.js.br +0 -0
  19. package/dashboard/dist/assets/BWEwjt1W.js.gz +0 -0
  20. package/dashboard/dist/assets/BgOYB78t.js +4 -0
  21. package/dashboard/dist/assets/BgOYB78t.js.br +0 -0
  22. package/dashboard/dist/assets/BgOYB78t.js.gz +0 -0
  23. package/dashboard/dist/assets/BzRbDCAD.css +1 -0
  24. package/dashboard/dist/assets/BzRbDCAD.css.br +0 -0
  25. package/dashboard/dist/assets/BzRbDCAD.css.gz +0 -0
  26. package/dashboard/dist/assets/C-KIc3Wc.js.br +0 -0
  27. package/dashboard/dist/assets/C-KIc3Wc.js.gz +0 -0
  28. package/dashboard/dist/assets/C8uM3AX8.js +1 -0
  29. package/dashboard/dist/assets/C8uM3AX8.js.br +0 -0
  30. package/dashboard/dist/assets/C8uM3AX8.js.gz +0 -0
  31. package/dashboard/dist/assets/C9jy61eu.js +212 -0
  32. package/dashboard/dist/assets/C9jy61eu.js.br +0 -0
  33. package/dashboard/dist/assets/C9jy61eu.js.gz +0 -0
  34. package/dashboard/dist/assets/CC63EwFD.js +1 -0
  35. package/dashboard/dist/assets/CC63EwFD.js.br +0 -0
  36. package/dashboard/dist/assets/CC63EwFD.js.gz +0 -0
  37. package/dashboard/dist/assets/CL_wXqR7.js +1 -0
  38. package/dashboard/dist/assets/CL_wXqR7.js.br +0 -0
  39. package/dashboard/dist/assets/CL_wXqR7.js.gz +0 -0
  40. package/dashboard/dist/assets/CZaT3ob_.js +1 -0
  41. package/dashboard/dist/assets/CZaT3ob_.js.br +0 -0
  42. package/dashboard/dist/assets/CZaT3ob_.js.gz +0 -0
  43. package/dashboard/dist/assets/CgaottFX.js +1 -0
  44. package/dashboard/dist/assets/CgaottFX.js.br +0 -0
  45. package/dashboard/dist/assets/CgaottFX.js.gz +0 -0
  46. package/dashboard/dist/assets/{CpJsfbXo.js → CxQ08qFN.js} +2 -2
  47. package/dashboard/dist/assets/CxQ08qFN.js.br +0 -0
  48. package/dashboard/dist/assets/CxQ08qFN.js.gz +0 -0
  49. package/dashboard/dist/assets/CzCxAZlW.js +1 -0
  50. package/dashboard/dist/assets/CzCxAZlW.js.br +0 -0
  51. package/dashboard/dist/assets/CzCxAZlW.js.gz +0 -0
  52. package/dashboard/dist/assets/D3iMTYEj.js +1 -0
  53. package/dashboard/dist/assets/D3iMTYEj.js.br +0 -0
  54. package/dashboard/dist/assets/D3iMTYEj.js.gz +0 -0
  55. package/dashboard/dist/assets/D8JNX8kq.js +2 -0
  56. package/dashboard/dist/assets/D8JNX8kq.js.br +0 -0
  57. package/dashboard/dist/assets/D8JNX8kq.js.gz +0 -0
  58. package/dashboard/dist/assets/DnA8dpj6.js +1 -0
  59. package/dashboard/dist/assets/DnA8dpj6.js.br +0 -0
  60. package/dashboard/dist/assets/DnA8dpj6.js.gz +0 -0
  61. package/dashboard/dist/assets/IUexzymk.js +1 -0
  62. package/dashboard/dist/assets/IUexzymk.js.br +0 -0
  63. package/dashboard/dist/assets/IUexzymk.js.gz +0 -0
  64. package/dashboard/dist/assets/cNrhgGc1.js +8 -0
  65. package/dashboard/dist/assets/cNrhgGc1.js.br +0 -0
  66. package/dashboard/dist/assets/cNrhgGc1.js.gz +0 -0
  67. package/dashboard/dist/assets/ic2FaMnh.js +1 -0
  68. package/dashboard/dist/assets/ic2FaMnh.js.br +0 -0
  69. package/dashboard/dist/assets/ic2FaMnh.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/rttbDbEx.js +1 -0
  74. package/dashboard/dist/assets/rttbDbEx.js.br +0 -0
  75. package/dashboard/dist/assets/rttbDbEx.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 +34 -8
  88. package/dist/agent-context-store.js +79 -17
  89. package/dist/agent-run-store.js +44 -3
  90. package/dist/agent-suite.d.ts +9 -0
  91. package/dist/agent-suite.js +149 -9
  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/chat-store.d.ts +157 -0
  97. package/dist/chat-store.js +586 -0
  98. package/dist/cli/orgx.js +11 -0
  99. package/dist/contracts/client.d.ts +43 -3
  100. package/dist/contracts/client.js +159 -30
  101. package/dist/contracts/practice-exercise-schema.d.ts +216 -0
  102. package/dist/contracts/practice-exercise-schema.js +314 -0
  103. package/dist/contracts/retro-schema.d.ts +81 -0
  104. package/dist/contracts/retro-schema.js +80 -0
  105. package/dist/contracts/shared-types.d.ts +159 -0
  106. package/dist/contracts/shared-types.js +199 -1
  107. package/dist/contracts/skill-pack-schema.d.ts +192 -0
  108. package/dist/contracts/skill-pack-schema.js +180 -0
  109. package/dist/contracts/types.d.ts +247 -2
  110. package/dist/entities/auto-assignment.js +43 -17
  111. package/dist/event-sanitization.d.ts +11 -0
  112. package/dist/event-sanitization.js +113 -0
  113. package/dist/gateway-watchdog.d.ts +5 -0
  114. package/dist/gateway-watchdog.js +50 -0
  115. package/dist/hooks/post-reporting-event.mjs +1 -5
  116. package/dist/http/helpers/activity-headline.js +13 -132
  117. package/dist/http/helpers/auto-continue-engine.d.ts +198 -10
  118. package/dist/http/helpers/auto-continue-engine.js +3145 -186
  119. package/dist/http/helpers/autopilot-operations.d.ts +19 -0
  120. package/dist/http/helpers/autopilot-operations.js +182 -31
  121. package/dist/http/helpers/autopilot-runtime.d.ts +1 -0
  122. package/dist/http/helpers/autopilot-runtime.js +328 -25
  123. package/dist/http/helpers/autopilot-slice-utils.d.ts +18 -0
  124. package/dist/http/helpers/autopilot-slice-utils.js +514 -93
  125. package/dist/http/helpers/decision-mapper.d.ts +40 -0
  126. package/dist/http/helpers/decision-mapper.js +223 -7
  127. package/dist/http/helpers/dispatch-lifecycle.d.ts +19 -2
  128. package/dist/http/helpers/dispatch-lifecycle.js +242 -37
  129. package/dist/http/helpers/kickoff-context.js +104 -0
  130. package/dist/http/helpers/llm-client.d.ts +47 -0
  131. package/dist/http/helpers/llm-client.js +256 -0
  132. package/dist/http/helpers/mission-control.d.ts +102 -3
  133. package/dist/http/helpers/mission-control.js +498 -9
  134. package/dist/http/helpers/sentinel-catalog.d.ts +23 -0
  135. package/dist/http/helpers/sentinel-catalog.js +193 -0
  136. package/dist/http/helpers/session-classification.d.ts +9 -0
  137. package/dist/http/helpers/session-classification.js +564 -0
  138. package/dist/http/helpers/slice-experience-v2.d.ts +137 -0
  139. package/dist/http/helpers/slice-experience-v2.js +677 -0
  140. package/dist/http/helpers/slice-run-projections.d.ts +72 -0
  141. package/dist/http/helpers/slice-run-projections.js +877 -0
  142. package/dist/http/helpers/triage-mapper.d.ts +43 -0
  143. package/dist/http/helpers/triage-mapper.js +549 -0
  144. package/dist/http/helpers/value-utils.js +7 -2
  145. package/dist/http/helpers/workspace-scope.d.ts +15 -0
  146. package/dist/http/helpers/workspace-scope.js +170 -0
  147. package/dist/http/index.js +1420 -105
  148. package/dist/http/routes/agent-suite.d.ts +9 -0
  149. package/dist/http/routes/agent-suite.js +294 -8
  150. package/dist/http/routes/agents-catalog.js +64 -19
  151. package/dist/http/routes/chat.d.ts +19 -0
  152. package/dist/http/routes/chat.js +522 -0
  153. package/dist/http/routes/decision-actions.d.ts +8 -1
  154. package/dist/http/routes/decision-actions.js +42 -5
  155. package/dist/http/routes/dispatch-gateway-envelope.d.ts +25 -0
  156. package/dist/http/routes/dispatch-gateway-envelope.js +26 -0
  157. package/dist/http/routes/entities.d.ts +16 -0
  158. package/dist/http/routes/entities.js +232 -6
  159. package/dist/http/routes/live-legacy.d.ts +5 -0
  160. package/dist/http/routes/live-legacy.js +23 -509
  161. package/dist/http/routes/live-misc.d.ts +12 -0
  162. package/dist/http/routes/live-misc.js +251 -31
  163. package/dist/http/routes/live-snapshot.d.ts +49 -2
  164. package/dist/http/routes/live-snapshot.js +653 -23
  165. package/dist/http/routes/live-terminal.d.ts +11 -0
  166. package/dist/http/routes/live-terminal.js +154 -0
  167. package/dist/http/routes/live-triage.d.ts +61 -0
  168. package/dist/http/routes/live-triage.js +192 -0
  169. package/dist/http/routes/mission-control-actions.d.ts +49 -1
  170. package/dist/http/routes/mission-control-actions.js +1246 -84
  171. package/dist/http/routes/mission-control-read.d.ts +48 -3
  172. package/dist/http/routes/mission-control-read.js +1658 -20
  173. package/dist/http/routes/realtime-orchestrator.d.ts +10 -0
  174. package/dist/http/routes/realtime-orchestrator.js +74 -0
  175. package/dist/http/routes/run-control.d.ts +5 -2
  176. package/dist/http/routes/run-control.js +10 -0
  177. package/dist/http/routes/sentinels-catalog.d.ts +7 -0
  178. package/dist/http/routes/sentinels-catalog.js +24 -0
  179. package/dist/http/routes/summary.js +10 -3
  180. package/dist/http/routes/usage.d.ts +24 -0
  181. package/dist/http/routes/usage.js +362 -0
  182. package/dist/http/routes/work-artifacts.js +28 -9
  183. package/dist/index.js +165 -27
  184. package/dist/local-openclaw.js +29 -6
  185. package/dist/mcp-client-setup.js +3 -3
  186. package/dist/mcp-http-handler.d.ts +3 -0
  187. package/dist/mcp-http-handler.js +34 -60
  188. package/dist/next-up-queue-store.d.ts +16 -1
  189. package/dist/next-up-queue-store.js +89 -7
  190. package/dist/outbox.d.ts +5 -0
  191. package/dist/outbox.js +113 -9
  192. package/dist/paths.js +36 -5
  193. package/dist/reporting/rollups.d.ts +41 -0
  194. package/dist/reporting/rollups.js +113 -0
  195. package/dist/retro/domain-templates.d.ts +45 -0
  196. package/dist/retro/domain-templates.js +297 -0
  197. package/dist/retro/quality-rubric.d.ts +33 -0
  198. package/dist/retro/quality-rubric.js +213 -0
  199. package/dist/runtime-cleanup.d.ts +18 -0
  200. package/dist/runtime-cleanup.js +87 -0
  201. package/dist/services/background.d.ts +11 -0
  202. package/dist/services/background.js +22 -0
  203. package/dist/services/experiment-randomization.d.ts +21 -0
  204. package/dist/services/experiment-randomization.js +63 -0
  205. package/dist/skill-pack-state.d.ts +36 -5
  206. package/dist/skill-pack-state.js +273 -29
  207. package/dist/sync/local-agent-telemetry.d.ts +13 -0
  208. package/dist/sync/local-agent-telemetry.js +128 -0
  209. package/dist/sync/outbox-replay.js +131 -24
  210. package/dist/team-context-store.d.ts +23 -0
  211. package/dist/team-context-store.js +116 -0
  212. package/dist/telemetry/posthog.js +4 -2
  213. package/dist/tools/core-tools.d.ts +10 -14
  214. package/dist/tools/core-tools.js +1289 -24
  215. package/dist/types.d.ts +2 -0
  216. package/dist/types.js +2 -0
  217. package/dist/worker-supervisor.js +23 -0
  218. package/package.json +20 -6
  219. package/dashboard/dist/assets/B3ziCA02.js +0 -8
  220. package/dashboard/dist/assets/B5NEElEI.css +0 -1
  221. package/dashboard/dist/assets/BhapSNAs.js +0 -215
  222. package/dashboard/dist/assets/iFdvE7lx.js +0 -1
  223. package/dashboard/dist/assets/jRJsmpYM.js +0 -1
  224. package/dashboard/dist/assets/sAhvFnpk.js +0 -4
@@ -0,0 +1,128 @@
1
+ const KNOWN_DOMAINS = [
2
+ "engineering",
3
+ "product",
4
+ "design",
5
+ "marketing",
6
+ "sales",
7
+ "operations",
8
+ "orchestration",
9
+ ];
10
+ const IDLE_MIRROR_MAX_AGE_MS = 24 * 60 * 60 * 1000;
11
+ function inferDomainFromAgentId(agentId) {
12
+ const normalized = agentId.trim().toLowerCase();
13
+ for (const domain of KNOWN_DOMAINS) {
14
+ if (normalized.includes(domain))
15
+ return domain;
16
+ }
17
+ return "operations";
18
+ }
19
+ function inferNameFromAgentId(agentId) {
20
+ const cleaned = agentId
21
+ .trim()
22
+ .replace(/[_-]+/g, " ")
23
+ .replace(/\s+/g, " ");
24
+ if (!cleaned)
25
+ return "Local Agent";
26
+ return cleaned
27
+ .split(" ")
28
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
29
+ .join(" ");
30
+ }
31
+ function toEpoch(value) {
32
+ const epoch = Date.parse(value);
33
+ return Number.isFinite(epoch) ? epoch : 0;
34
+ }
35
+ function normalizeMirror(input) {
36
+ const id = typeof input.id === "string" ? input.id.trim() : "";
37
+ if (!id)
38
+ return null;
39
+ const status = input.status === "active" || input.status === "throttled" ? input.status : "idle";
40
+ const name = typeof input.name === "string" && input.name.trim().length > 0
41
+ ? input.name.trim()
42
+ : inferNameFromAgentId(id);
43
+ const domain = typeof input.domain === "string" && input.domain.trim().length > 0
44
+ ? input.domain.trim()
45
+ : inferDomainFromAgentId(id);
46
+ return {
47
+ id,
48
+ name,
49
+ domain,
50
+ status,
51
+ currentTask: input.currentTask,
52
+ lastActive: input.lastActive,
53
+ };
54
+ }
55
+ export function buildLocalAgentMirrorsFromSnapshot(input) {
56
+ const latestByAgent = new Map();
57
+ for (const source of input.agents ?? []) {
58
+ const normalized = normalizeMirror(source);
59
+ if (!normalized)
60
+ continue;
61
+ const previous = latestByAgent.get(normalized.id);
62
+ if (!previous ||
63
+ toEpoch(normalized.lastActive ?? "") >= toEpoch(previous.lastActive ?? "")) {
64
+ latestByAgent.set(normalized.id, normalized);
65
+ }
66
+ }
67
+ return Array.from(latestByAgent.values()).sort((a, b) => a.id.localeCompare(b.id));
68
+ }
69
+ /**
70
+ * Derive live local agent states from active OpenClaw runs so sync can mirror
71
+ * local runtime telemetry into OrgX.
72
+ */
73
+ export function buildLocalSyncAgentsFromRuns(input) {
74
+ const latestRunningByAgent = new Map();
75
+ const latestStoppedByAgent = new Map();
76
+ const mergedByAgent = new Map();
77
+ const now = Date.now();
78
+ for (const mirror of buildLocalAgentMirrorsFromSnapshot({ agents: input.mirrors })) {
79
+ mergedByAgent.set(mirror.id, mirror);
80
+ }
81
+ for (const run of Object.values(input.runs ?? {})) {
82
+ if (!run)
83
+ continue;
84
+ const agentId = run.agentId?.trim();
85
+ if (!agentId)
86
+ continue;
87
+ const isRunning = run.status === "running";
88
+ const index = isRunning ? latestRunningByAgent : latestStoppedByAgent;
89
+ const runTimestamp = isRunning ? toEpoch(run.startedAt) : toEpoch(run.stoppedAt ?? run.startedAt);
90
+ const previous = index.get(agentId);
91
+ const previousTimestamp = previous
92
+ ? toEpoch(previous.status === "running" ? previous.startedAt : previous.stoppedAt ?? previous.startedAt)
93
+ : 0;
94
+ if (!previous || runTimestamp >= previousTimestamp) {
95
+ index.set(agentId, run);
96
+ }
97
+ }
98
+ for (const [agentId, run] of latestRunningByAgent) {
99
+ mergedByAgent.set(agentId, {
100
+ id: agentId,
101
+ name: inferNameFromAgentId(agentId),
102
+ domain: inferDomainFromAgentId(agentId),
103
+ status: "active",
104
+ currentTask: run.taskId ?? undefined,
105
+ lastActive: run.startedAt,
106
+ });
107
+ }
108
+ for (const [agentId, run] of latestStoppedByAgent) {
109
+ if (latestRunningByAgent.has(agentId))
110
+ continue;
111
+ const lastActive = run.stoppedAt ?? run.startedAt;
112
+ const idleAgeMs = now - toEpoch(lastActive);
113
+ if (!Number.isFinite(idleAgeMs) || idleAgeMs < 0 || idleAgeMs > IDLE_MIRROR_MAX_AGE_MS) {
114
+ continue;
115
+ }
116
+ const existing = mergedByAgent.get(agentId);
117
+ if (existing && toEpoch(existing.lastActive ?? "") > toEpoch(lastActive))
118
+ continue;
119
+ mergedByAgent.set(agentId, {
120
+ id: agentId,
121
+ name: existing?.name ?? inferNameFromAgentId(agentId),
122
+ domain: existing?.domain ?? inferDomainFromAgentId(agentId),
123
+ status: "idle",
124
+ lastActive,
125
+ });
126
+ }
127
+ return Array.from(mergedByAgent.values()).sort((a, b) => a.id.localeCompare(b.id));
128
+ }
@@ -1,6 +1,14 @@
1
1
  import { registerArtifact } from "../artifacts/register-artifact.js";
2
- import { readOutbox, readOutboxSummary, replaceOutbox } from "../outbox.js";
2
+ import { appendOutboxDeadLetter, readOutbox, readOutboxSummary, replaceOutbox, } from "../outbox.js";
3
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
+ })();
4
12
  export function createOutboxReplayer(deps) {
5
13
  const { client, logger, toErrorMessage, stableHash, resolveReportingContext, pickStringField, pickStringArrayField, toReportingPhase, parseRetroEntityType, isUuid, } = deps;
6
14
  async function replayOutboxEvent(event) {
@@ -19,6 +27,78 @@ export function createOutboxReplayer(deps) {
19
27
  }
20
28
  return { run_id: undefined, correlation_id: undefined };
21
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
+ }
22
102
  if (event.type === "progress") {
23
103
  const message = extractProgressOutboxMessage(payload);
24
104
  if (!message) {
@@ -68,20 +148,6 @@ export function createOutboxReplayer(deps) {
68
148
  undefined,
69
149
  metadata: baseMetadata,
70
150
  };
71
- // Locally-buffered progress events often store a local UUID in run_id. OrgX may reject
72
- // unknown run IDs on replay; prefer a deterministic non-UUID correlation key instead.
73
- if (emitPayload.run_id && !emitPayload.correlation_id) {
74
- const replayCorrelationId = `openclaw_run_${stableHash(emitPayload.run_id).slice(0, 24)}`;
75
- emitPayload = {
76
- ...emitPayload,
77
- run_id: undefined,
78
- correlation_id: replayCorrelationId,
79
- metadata: {
80
- ...(emitPayload.metadata ?? {}),
81
- replay_run_id_as_correlation: true,
82
- },
83
- };
84
- }
85
151
  try {
86
152
  await client.emitActivity(emitPayload);
87
153
  }
@@ -92,8 +158,8 @@ export function createOutboxReplayer(deps) {
92
158
  // create/attach a run deterministically.
93
159
  const msg = toErrorMessage(err);
94
160
  if (emitPayload.run_id &&
95
- /^404\\b/.test(msg) &&
96
- /\\brun\\b/i.test(msg) &&
161
+ /(?:^|\b)404\b/.test(msg) &&
162
+ /\brun\b/i.test(msg) &&
97
163
  /not found/i.test(msg)) {
98
164
  const replayCorrelationId = `openclaw_run_${stableHash(emitPayload.run_id).slice(0, 24)}`;
99
165
  await client.emitActivity({
@@ -350,11 +416,8 @@ export function createOutboxReplayer(deps) {
350
416
  runId: context.value.runId,
351
417
  correlationId: context.value.correlationId,
352
418
  });
353
- const retro = payload.retro && typeof payload.retro === "object" && !Array.isArray(payload.retro)
354
- ? payload.retro
355
- : null;
356
- const summary = retro && typeof retro.summary === "string" ? retro.summary.trim() : "";
357
- if (!retro || !summary) {
419
+ const normalizedRetro = normalizeRetro(payload);
420
+ if (!normalizedRetro) {
358
421
  logger.warn?.("[orgx] Dropping invalid retro outbox event", {
359
422
  eventId: event.id,
360
423
  });
@@ -383,7 +446,7 @@ export function createOutboxReplayer(deps) {
383
446
  idempotency_key: pickStringField(payload, "idempotency_key") ??
384
447
  pickStringField(payload, "idempotencyKey") ??
385
448
  undefined,
386
- retro: retro,
449
+ retro: normalizedRetro,
387
450
  markdown: pickStringField(payload, "markdown") ?? undefined,
388
451
  });
389
452
  return;
@@ -402,6 +465,13 @@ export function createOutboxReplayer(deps) {
402
465
  const description = pickStringField(payload, "description") ?? undefined;
403
466
  const externalUrl = pickStringField(payload, "url") ?? pickStringField(payload, "artifact_url") ?? null;
404
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;
405
475
  const allowedEntityType = entityType === "initiative" ||
406
476
  entityType === "milestone" ||
407
477
  entityType === "task" ||
@@ -423,6 +493,7 @@ export function createOutboxReplayer(deps) {
423
493
  entity_id: entityId,
424
494
  name: name.trim(),
425
495
  artifact_type: artifactType.trim() || "other",
496
+ confidence_score: confidenceScore,
426
497
  description,
427
498
  external_url: externalUrl,
428
499
  preview_markdown: content,
@@ -430,6 +501,7 @@ export function createOutboxReplayer(deps) {
430
501
  metadata: {
431
502
  source: "outbox_replay",
432
503
  outbox_event_id: event.id,
504
+ confidence_score: confidenceScore,
433
505
  ...(payload.metadata && typeof payload.metadata === "object" && !Array.isArray(payload.metadata)
434
506
  ? payload.metadata
435
507
  : {}),
@@ -466,16 +538,51 @@ export function createOutboxReplayer(deps) {
466
538
  }
467
539
  const remaining = [];
468
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
+ }
469
551
  try {
470
552
  await replayOutboxEvent(event);
471
553
  }
472
554
  catch (err) {
473
555
  hadReplayFailure = true;
474
556
  lastReplayError = toErrorMessage(err);
475
- remaining.push(event);
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
+ });
476
582
  logger.warn?.("[orgx] Outbox replay failed", {
477
583
  queue,
478
584
  eventId: event.id,
585
+ replayFailures: nextFailures,
479
586
  error: lastReplayError,
480
587
  });
481
588
  }
@@ -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 {};
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Team Context Store — Local cache for cross-agent awareness.
3
+ *
4
+ * Persists recent slice completions and decisions per initiative so the
5
+ * auto-continue engine can provide degraded team context when the server
6
+ * is unreachable (offline fallback for KickoffContext.team_context).
7
+ *
8
+ * Follows the same patterns as agent-context-store.ts: bounded store,
9
+ * atomic writes, corrupt file recovery.
10
+ */
11
+ import { existsSync, readFileSync } from "node:fs";
12
+ import { getOrgxPluginConfigDir, getOrgxPluginConfigPath } from "./paths.js";
13
+ import { backupCorruptFileSync, writeJsonFileAtomicSync } from "./fs-utils.js";
14
+ import { clearStoreFileSync, ensureStoreDirSync, parseJsonSafe, } from "./stores/json-store.js";
15
+ const MAX_COMPLETIONS = 20;
16
+ const MAX_DECISIONS = 20;
17
+ const MAX_INITIATIVES = 50;
18
+ function storeDir() {
19
+ return getOrgxPluginConfigDir();
20
+ }
21
+ function storeFile() {
22
+ return getOrgxPluginConfigPath("team-context.json");
23
+ }
24
+ function emptyContext() {
25
+ return { updatedAt: new Date().toISOString(), recent_completions: [], recent_decisions: [] };
26
+ }
27
+ function emptyIndex() {
28
+ return { initiatives: {} };
29
+ }
30
+ function isValidIndex(value) {
31
+ if (!value || typeof value !== "object")
32
+ return false;
33
+ const record = value;
34
+ return record.initiatives !== undefined && typeof record.initiatives === "object";
35
+ }
36
+ function readIndex() {
37
+ const file = storeFile();
38
+ try {
39
+ if (!existsSync(file))
40
+ return emptyIndex();
41
+ const raw = readFileSync(file, "utf8");
42
+ const parsed = parseJsonSafe(raw);
43
+ if (!isValidIndex(parsed)) {
44
+ backupCorruptFileSync(file);
45
+ return emptyIndex();
46
+ }
47
+ return parsed;
48
+ }
49
+ catch {
50
+ return emptyIndex();
51
+ }
52
+ }
53
+ function writeIndex(index) {
54
+ ensureStoreDirSync(storeDir());
55
+ // Prune if too many initiatives.
56
+ const keys = Object.keys(index.initiatives);
57
+ if (keys.length > MAX_INITIATIVES) {
58
+ const sorted = keys
59
+ .map((k) => ({ key: k, updatedAt: index.initiatives[k]?.updatedAt ?? "" }))
60
+ .sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
61
+ const keep = new Set(sorted.slice(0, MAX_INITIATIVES).map((e) => e.key));
62
+ for (const key of keys) {
63
+ if (!keep.has(key))
64
+ delete index.initiatives[key];
65
+ }
66
+ }
67
+ writeJsonFileAtomicSync(storeFile(), index, 0o600);
68
+ }
69
+ export function readTeamContext(initiativeId) {
70
+ const id = initiativeId.trim();
71
+ if (!id)
72
+ return emptyContext();
73
+ const index = readIndex();
74
+ const ctx = index.initiatives[id];
75
+ return ctx ?? emptyContext();
76
+ }
77
+ export function appendTeamCompletion(initiativeId, completion) {
78
+ const id = initiativeId.trim();
79
+ if (!id)
80
+ return;
81
+ const index = readIndex();
82
+ const ctx = index.initiatives[id] ?? emptyContext();
83
+ ctx.recent_completions.push(completion);
84
+ if (ctx.recent_completions.length > MAX_COMPLETIONS) {
85
+ ctx.recent_completions = ctx.recent_completions.slice(-MAX_COMPLETIONS);
86
+ }
87
+ ctx.updatedAt = new Date().toISOString();
88
+ index.initiatives[id] = ctx;
89
+ writeIndex(index);
90
+ }
91
+ export function appendTeamDecision(initiativeId, decision) {
92
+ const id = initiativeId.trim();
93
+ if (!id)
94
+ return;
95
+ const index = readIndex();
96
+ const ctx = index.initiatives[id] ?? emptyContext();
97
+ ctx.recent_decisions.push(decision);
98
+ if (ctx.recent_decisions.length > MAX_DECISIONS) {
99
+ ctx.recent_decisions = ctx.recent_decisions.slice(-MAX_DECISIONS);
100
+ }
101
+ ctx.updatedAt = new Date().toISOString();
102
+ index.initiatives[id] = ctx;
103
+ writeIndex(index);
104
+ }
105
+ export function clearTeamContext(initiativeId) {
106
+ if (!initiativeId) {
107
+ clearStoreFileSync(storeFile());
108
+ return;
109
+ }
110
+ const id = initiativeId.trim();
111
+ if (!id)
112
+ return;
113
+ const index = readIndex();
114
+ delete index.initiatives[id];
115
+ writeIndex(index);
116
+ }
@@ -1,4 +1,3 @@
1
- const POSTHOG_DEFAULT_API_KEY = "phc_s4KPgkYEFZgvkMYw4zXG41H5FN6haVwbEWPYHfNjxOc";
2
1
  const POSTHOG_DEFAULT_HOST = "https://us.i.posthog.com";
3
2
  function isTruthyEnv(value) {
4
3
  if (!value)
@@ -15,6 +14,9 @@ function isTruthyEnv(value) {
15
14
  }
16
15
  }
17
16
  export function isOrgxTelemetryDisabled() {
17
+ const explicitEnable = isTruthyEnv(process.env.ORGX_TELEMETRY_ENABLED);
18
+ if (!explicitEnable)
19
+ return true;
18
20
  return (isTruthyEnv(process.env.ORGX_TELEMETRY_DISABLED) ||
19
21
  isTruthyEnv(process.env.OPENCLAW_TELEMETRY_DISABLED) ||
20
22
  isTruthyEnv(process.env.POSTHOG_DISABLED));
@@ -28,7 +30,7 @@ export function resolvePosthogApiKey() {
28
30
  const trimmed = fromEnv.trim();
29
31
  if (trimmed)
30
32
  return trimmed;
31
- return POSTHOG_DEFAULT_API_KEY;
33
+ return null;
32
34
  }
33
35
  export function resolvePosthogHost() {
34
36
  const fromEnv = process.env.ORGX_POSTHOG_HOST ??
@@ -57,20 +57,16 @@ export interface RegisterCoreToolsDeps {
57
57
  ok: false;
58
58
  error: string;
59
59
  };
60
- readSkillPackState: () => {
61
- pack?: {
62
- name?: string | null;
63
- version?: string | null;
64
- checksum?: string | null;
65
- } | null;
66
- overrides?: {
67
- source?: string | null;
68
- name?: string | null;
69
- version?: string | null;
70
- checksum?: string | null;
71
- } | null;
72
- etag?: string | null;
73
- };
60
+ readSkillPackState: () => import("../skill-pack-state.js").SkillPackState;
61
+ updateSkillPackPolicy: (input: {
62
+ frozen?: boolean;
63
+ pinnedChecksum?: string | null;
64
+ pinToCurrent?: boolean;
65
+ clearPin?: boolean;
66
+ }) => import("../skill-pack-state.js").SkillPackState;
67
+ rollbackSkillPackPolicy: (input?: {
68
+ auditId?: string;
69
+ }) => import("../skill-pack-state.js").SkillPackState;
74
70
  randomUUID?: () => string;
75
71
  }
76
72
  export declare function registerCoreTools(deps: RegisterCoreToolsDeps): Map<string, RegisteredTool>;