@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
@@ -2,8 +2,11 @@ import type { Router } from "../router.js";
2
2
  type JsonRecord = Record<string, unknown>;
3
3
  type ReadSkillPackStateFn = typeof import("../../skill-pack-state.js").readSkillPackState;
4
4
  type UpdateSkillPackPolicyFn = typeof import("../../skill-pack-state.js").updateSkillPackPolicy;
5
+ type RollbackSkillPackPolicyFn = typeof import("../../skill-pack-state.js").rollbackSkillPackPolicy;
5
6
  type ComputeOrgxAgentSuitePlanFn = typeof import("../../agent-suite.js").computeOrgxAgentSuitePlan;
6
7
  type ApplyOrgxAgentSuitePlanFn = typeof import("../../agent-suite.js").applyOrgxAgentSuitePlan;
8
+ type ClientRuntimeSettingsResponse = import("../../contracts/types.js").ClientRuntimeSettingsResponse;
9
+ type ClientRuntimeSettingsUpdateRequest = import("../../contracts/types.js").ClientRuntimeSettingsUpdateRequest;
7
10
  type OrgxSkillPackOverrides = import("../../agent-suite.js").OrgxSkillPackOverrides;
8
11
  type RegisterAgentSuiteRoutesDeps<TReq, TRes> = {
9
12
  pluginVersion: string | null | undefined;
@@ -17,6 +20,12 @@ type RegisterAgentSuiteRoutesDeps<TReq, TRes> = {
17
20
  applyOrgxAgentSuitePlan: ApplyOrgxAgentSuitePlanFn;
18
21
  generateAgentSuiteOperationId: () => string;
19
22
  updateSkillPackPolicy: UpdateSkillPackPolicyFn;
23
+ rollbackSkillPackPolicy: RollbackSkillPackPolicyFn;
24
+ fetchAgentRuntimeSettings: (input?: {
25
+ workspaceId?: string | null;
26
+ projectId?: string | null;
27
+ }) => Promise<ClientRuntimeSettingsResponse>;
28
+ updateAgentRuntimeSettings: (payload: ClientRuntimeSettingsUpdateRequest) => Promise<ClientRuntimeSettingsResponse>;
20
29
  posthogCapture: (input: {
21
30
  event: string;
22
31
  distinctId: string;
@@ -21,6 +21,151 @@ function computeUpdateAvailable(state) {
21
21
  state.pack?.checksum &&
22
22
  state.remote.checksum !== state.pack.checksum);
23
23
  }
24
+ function toOptionalString(value) {
25
+ return typeof value === "string" ? value : undefined;
26
+ }
27
+ const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
28
+ function toOptionalUuid(value) {
29
+ if (typeof value !== "string")
30
+ return undefined;
31
+ const trimmed = value.trim();
32
+ return UUID_RE.test(trimmed) ? trimmed : undefined;
33
+ }
34
+ function readOptionalBoolean(payload, ...keys) {
35
+ for (const key of keys) {
36
+ const value = payload[key];
37
+ if (typeof value === "boolean") {
38
+ return value;
39
+ }
40
+ }
41
+ return undefined;
42
+ }
43
+ function readOptionalInteger(payload, options, ...keys) {
44
+ for (const key of keys) {
45
+ const raw = payload[key];
46
+ let parsed = Number.NaN;
47
+ if (typeof raw === "number") {
48
+ parsed = raw;
49
+ }
50
+ else if (typeof raw === "string") {
51
+ const trimmed = raw.trim();
52
+ if (/^[+-]?\d+$/.test(trimmed)) {
53
+ parsed = Number.parseInt(trimmed, 10);
54
+ }
55
+ }
56
+ if (!Number.isFinite(parsed))
57
+ continue;
58
+ const normalized = Math.max(options.min, Math.min(options.max, Math.floor(parsed)));
59
+ return normalized;
60
+ }
61
+ return undefined;
62
+ }
63
+ function readOptionalAction(payload, ...keys) {
64
+ for (const key of keys) {
65
+ const raw = payload[key];
66
+ if (typeof raw !== "string")
67
+ continue;
68
+ const normalized = raw.trim().toLowerCase();
69
+ if (normalized === "approve" || normalized === "reject") {
70
+ return normalized;
71
+ }
72
+ }
73
+ return undefined;
74
+ }
75
+ function readOptionalPolicy(payload, ...keys) {
76
+ for (const key of keys) {
77
+ const raw = payload[key];
78
+ if (typeof raw !== "string")
79
+ continue;
80
+ const normalized = raw.trim().toLowerCase();
81
+ if (normalized === "contextual" ||
82
+ normalized === "approve_non_blocking" ||
83
+ normalized === "defer_non_blocking") {
84
+ return normalized;
85
+ }
86
+ }
87
+ return undefined;
88
+ }
89
+ function readOptionalBlockingBehavior(payload, ...keys) {
90
+ for (const key of keys) {
91
+ const raw = payload[key];
92
+ if (typeof raw !== "string")
93
+ continue;
94
+ const normalized = raw.trim().toLowerCase();
95
+ if (normalized === "require_human" ||
96
+ normalized === "guarded_auto_resolve_then_human") {
97
+ return normalized;
98
+ }
99
+ }
100
+ return undefined;
101
+ }
102
+ function normalizeRuntimeSettingsPatch(payload) {
103
+ const runtime = toRecord(payload.runtime_settings ?? payload.runtimeSettings);
104
+ const patch = {};
105
+ const decisionV2Enabled = readOptionalBoolean(runtime, "decision_v2_enabled", "decisionV2Enabled");
106
+ if (typeof decisionV2Enabled === "boolean") {
107
+ patch.decision_v2_enabled = decisionV2Enabled;
108
+ }
109
+ const decisionDedupeEnabled = readOptionalBoolean(runtime, "decision_dedupe_enabled", "decisionDedupeEnabled");
110
+ if (typeof decisionDedupeEnabled === "boolean") {
111
+ patch.decision_dedupe_enabled = decisionDedupeEnabled;
112
+ }
113
+ const decisionEvidenceRequiredForBlocking = readOptionalBoolean(runtime, "decision_evidence_required_for_blocking", "decisionEvidenceRequiredForBlocking");
114
+ if (typeof decisionEvidenceRequiredForBlocking === "boolean") {
115
+ patch.decision_evidence_required_for_blocking =
116
+ decisionEvidenceRequiredForBlocking;
117
+ }
118
+ const decisionAutoResolveGuardedEnabled = readOptionalBoolean(runtime, "decision_auto_resolve_guarded_enabled", "decisionAutoResolveGuardedEnabled");
119
+ if (typeof decisionAutoResolveGuardedEnabled === "boolean") {
120
+ patch.decision_auto_resolve_guarded_enabled =
121
+ decisionAutoResolveGuardedEnabled;
122
+ }
123
+ const questionAutoAnswerEnabled = readOptionalBoolean(runtime, "question_auto_answer_enabled", "questionAutoAnswerEnabled");
124
+ if (typeof questionAutoAnswerEnabled === "boolean") {
125
+ patch.question_auto_answer_enabled = questionAutoAnswerEnabled;
126
+ }
127
+ const questionAutoAnswerDelaySeconds = readOptionalInteger(runtime, { min: 1, max: 900 }, "question_auto_answer_delay_seconds", "questionAutoAnswerDelaySeconds");
128
+ if (typeof questionAutoAnswerDelaySeconds === "number") {
129
+ patch.question_auto_answer_delay_seconds = questionAutoAnswerDelaySeconds;
130
+ }
131
+ const questionAutoAnswerAction = readOptionalAction(runtime, "question_auto_answer_action", "questionAutoAnswerAction");
132
+ if (questionAutoAnswerAction) {
133
+ patch.question_auto_answer_action = questionAutoAnswerAction;
134
+ }
135
+ const questionAutoAnswerTimeoutSec = readOptionalInteger(runtime, { min: 10, max: 3600 }, "question_auto_answer_timeout_sec", "questionAutoAnswerTimeoutSec");
136
+ if (typeof questionAutoAnswerTimeoutSec === "number") {
137
+ patch.question_auto_answer_timeout_sec = questionAutoAnswerTimeoutSec;
138
+ }
139
+ const questionAutoAnswerPolicy = readOptionalPolicy(runtime, "question_auto_answer_policy", "questionAutoAnswerPolicy");
140
+ if (questionAutoAnswerPolicy) {
141
+ patch.question_auto_answer_policy = questionAutoAnswerPolicy;
142
+ }
143
+ const questionBlockingBehavior = readOptionalBlockingBehavior(runtime, "question_blocking_behavior", "questionBlockingBehavior");
144
+ if (questionBlockingBehavior) {
145
+ patch.question_blocking_behavior = questionBlockingBehavior;
146
+ }
147
+ const questionPolicyVersion = readOptionalInteger(runtime, { min: 1, max: 10 }, "question_policy_version", "questionPolicyVersion");
148
+ if (typeof questionPolicyVersion === "number") {
149
+ patch.question_policy_version = questionPolicyVersion;
150
+ }
151
+ const customRunInstructions = toOptionalString(runtime.custom_run_instructions ?? runtime.customRunInstructions);
152
+ if (typeof customRunInstructions === "string") {
153
+ patch.custom_run_instructions = customRunInstructions.slice(0, 4000);
154
+ }
155
+ return patch;
156
+ }
157
+ function buildRuntimeSettingsFallbackEnvelope(workspaceId) {
158
+ const normalizedWorkspaceId = typeof workspaceId === "string" && workspaceId.trim().length > 0
159
+ ? workspaceId.trim()
160
+ : null;
161
+ return {
162
+ ok: true,
163
+ workspace_id: normalizedWorkspaceId,
164
+ command_center_id: normalizedWorkspaceId,
165
+ project_id: normalizedWorkspaceId,
166
+ agents: [],
167
+ };
168
+ }
24
169
  export function registerAgentSuiteRoutes(router, deps) {
25
170
  async function renderStatus(res) {
26
171
  try {
@@ -54,6 +199,102 @@ export function registerAgentSuiteRoutes(router, deps) {
54
199
  }
55
200
  router.add("GET", "agent-suite/status", async ({ res }) => renderStatus(res), "Agent suite installation status");
56
201
  router.add("HEAD", "agent-suite/status", async ({ res }) => renderStatus(res), "Agent suite installation status (HEAD)");
202
+ router.add("GET", "agent-suite/runtime-settings", async ({ req, res }) => {
203
+ const requestUrl = new URL(String(req.url ?? "/"), "http://localhost");
204
+ const workspaceId = toOptionalUuid(requestUrl.searchParams.get("workspace_id") ??
205
+ requestUrl.searchParams.get("workspaceId") ??
206
+ requestUrl.searchParams.get("command_center_id") ??
207
+ requestUrl.searchParams.get("commandCenterId") ??
208
+ requestUrl.searchParams.get("project_id"));
209
+ try {
210
+ const response = await deps.fetchAgentRuntimeSettings({
211
+ workspaceId: workspaceId ?? null,
212
+ });
213
+ if (!response?.ok) {
214
+ deps.sendJson(res, 200, {
215
+ ok: true,
216
+ data: {
217
+ ...buildRuntimeSettingsFallbackEnvelope(workspaceId ?? null),
218
+ warning: response?.error ?? "Failed to load agent runtime settings",
219
+ },
220
+ });
221
+ return;
222
+ }
223
+ deps.sendJson(res, 200, {
224
+ ok: true,
225
+ data: response,
226
+ });
227
+ }
228
+ catch (err) {
229
+ deps.sendJson(res, 200, {
230
+ ok: true,
231
+ data: {
232
+ ...buildRuntimeSettingsFallbackEnvelope(workspaceId ?? null),
233
+ warning: deps.safeErrorMessage(err),
234
+ },
235
+ });
236
+ }
237
+ }, "List agent runtime settings");
238
+ router.add("PATCH", "agent-suite/runtime-settings", async ({ req, res }) => {
239
+ try {
240
+ const payload = toRecord(await deps.parseJsonRequest(req));
241
+ const agentId = toOptionalString(payload.agent_id ?? payload.agentId)?.trim();
242
+ if (!agentId) {
243
+ deps.sendJson(res, 400, {
244
+ ok: false,
245
+ error: "agent_id is required",
246
+ });
247
+ return;
248
+ }
249
+ const runtimeSettingsPatch = normalizeRuntimeSettingsPatch(payload);
250
+ if (Object.keys(runtimeSettingsPatch).length === 0) {
251
+ deps.sendJson(res, 400, {
252
+ ok: false,
253
+ error: "runtime_settings must include at least one mutable field",
254
+ });
255
+ return;
256
+ }
257
+ const workspaceId = toOptionalUuid(payload.workspace_id ??
258
+ payload.workspaceId ??
259
+ payload.command_center_id ??
260
+ payload.commandCenterId ??
261
+ payload.project_id ??
262
+ payload.projectId);
263
+ const response = await deps.updateAgentRuntimeSettings({
264
+ agent_id: agentId,
265
+ ...(workspaceId
266
+ ? {
267
+ workspace_id: workspaceId,
268
+ command_center_id: workspaceId,
269
+ }
270
+ : {}),
271
+ runtime_settings: runtimeSettingsPatch,
272
+ });
273
+ if (!response?.ok) {
274
+ deps.sendJson(res, 502, {
275
+ ok: false,
276
+ error: response?.error ?? "Failed to update agent runtime settings",
277
+ });
278
+ return;
279
+ }
280
+ deps.sendJson(res, 200, {
281
+ ok: true,
282
+ data: response,
283
+ });
284
+ }
285
+ catch (err) {
286
+ deps.sendJson(res, 500, {
287
+ ok: false,
288
+ error: deps.safeErrorMessage(err),
289
+ });
290
+ }
291
+ }, "Update agent runtime settings");
292
+ router.add("*", "agent-suite/runtime-settings", ({ res }) => {
293
+ deps.sendJson(res, 405, {
294
+ ok: false,
295
+ error: "Use GET/PATCH /orgx/api/agent-suite/runtime-settings",
296
+ });
297
+ }, "Reject unsupported methods for agent-suite/runtime-settings");
57
298
  router.add("POST", "agent-suite/install", async ({ req, res }) => {
58
299
  try {
59
300
  const payload = toRecord(await deps.parseJsonRequest(req));
@@ -141,6 +382,7 @@ export function registerAgentSuiteRoutes(router, deps) {
141
382
  ok: true,
142
383
  data: {
143
384
  policy: state.policy,
385
+ audit: state.audit,
144
386
  pack: state.pack,
145
387
  remote: state.remote,
146
388
  updateAvailable: computeUpdateAvailable(state),
@@ -156,18 +398,56 @@ export function registerAgentSuiteRoutes(router, deps) {
156
398
  const frozen = typeof frozenRaw === "boolean" ? frozenRaw : undefined;
157
399
  const pinToCurrent = readBoolean(payload, "pinToCurrent", "pin_to_current");
158
400
  const clearPin = readBoolean(payload, "clearPin", "clear_pin");
159
- const pinnedChecksumRaw = payload.pinnedChecksum;
401
+ const changedByRaw = payload.changedBy ?? payload.changed_by;
402
+ const changedBy = typeof changedByRaw === "string" ? changedByRaw : undefined;
403
+ const reasonRaw = payload.reason;
404
+ const reason = typeof reasonRaw === "string" ? reasonRaw : undefined;
405
+ const actionRaw = payload.action;
406
+ const action = typeof actionRaw === "string" ? actionRaw.trim().toLowerCase() : "";
407
+ const rollbackToAuditIdRaw = payload.rollbackToAuditId ?? payload.rollback_to_audit_id;
408
+ const rollbackToAuditId = toOptionalString(rollbackToAuditIdRaw)?.trim() || undefined;
409
+ const pinnedChecksumRaw = payload.pinnedChecksum ?? payload.pinned_checksum;
160
410
  const pinnedChecksum = typeof pinnedChecksumRaw === "string"
161
411
  ? pinnedChecksumRaw
162
412
  : pinnedChecksumRaw === null
163
413
  ? null
164
414
  : undefined;
165
- const state = deps.updateSkillPackPolicy({
166
- frozen,
167
- pinToCurrent,
168
- clearPin,
169
- pinnedChecksum,
170
- });
415
+ const hasFrozen = typeof frozen === "boolean";
416
+ const hasPinnedChecksum = typeof pinnedChecksum === "string" || pinnedChecksum === null;
417
+ const hasPinToCurrent = pinToCurrent === true;
418
+ const hasClearPin = clearPin === true;
419
+ const isRollback = action === "rollback" || typeof rollbackToAuditId === "string";
420
+ if (action.length > 0 && action !== "rollback") {
421
+ throw new Error("action must be 'rollback' when provided.");
422
+ }
423
+ if (hasPinToCurrent && hasClearPin) {
424
+ throw new Error("pinToCurrent and clearPin cannot both be true.");
425
+ }
426
+ if (typeof pinnedChecksum === "string" && !pinnedChecksum.trim()) {
427
+ throw new Error("pinnedChecksum must be a non-empty string when provided.");
428
+ }
429
+ if (isRollback) {
430
+ if (hasFrozen || hasPinnedChecksum || hasPinToCurrent || hasClearPin) {
431
+ throw new Error("Rollback requests cannot include update fields (frozen, pinnedChecksum, pinToCurrent, clearPin).");
432
+ }
433
+ }
434
+ else if (!hasFrozen && !hasPinnedChecksum && !hasPinToCurrent && !hasClearPin) {
435
+ throw new Error("Include at least one mutable field: frozen, pinnedChecksum, pinToCurrent, or clearPin.");
436
+ }
437
+ const state = isRollback
438
+ ? deps.rollbackSkillPackPolicy({
439
+ auditId: rollbackToAuditId,
440
+ changedBy,
441
+ reason,
442
+ })
443
+ : deps.updateSkillPackPolicy({
444
+ frozen,
445
+ pinToCurrent,
446
+ clearPin,
447
+ pinnedChecksum: typeof pinnedChecksum === "string" ? pinnedChecksum.trim() : pinnedChecksum,
448
+ changedBy,
449
+ reason,
450
+ });
171
451
  void deps
172
452
  .posthogCapture({
173
453
  event: "openclaw_skill_pack_policy_updated",
@@ -183,7 +463,13 @@ export function registerAgentSuiteRoutes(router, deps) {
183
463
  .catch(() => {
184
464
  // best effort
185
465
  });
186
- deps.sendJson(res, 200, { ok: true, data: state.policy });
466
+ deps.sendJson(res, 200, {
467
+ ok: true,
468
+ data: {
469
+ policy: state.policy,
470
+ audit: state.audit,
471
+ },
472
+ });
187
473
  }
188
474
  catch (err) {
189
475
  deps.sendJson(res, 400, { ok: false, error: deps.safeErrorMessage(err) });
@@ -1,13 +1,26 @@
1
1
  export function registerAgentsCatalogRoutes(router, deps) {
2
2
  async function handle(res) {
3
3
  try {
4
- const [openclawAgents, localSnapshot] = await Promise.all([
5
- deps.listAgents(),
6
- deps.loadLocalSnapshot(),
7
- ]);
4
+ let openclawAgents = [];
5
+ let openclawAgentsError = null;
6
+ try {
7
+ const fetched = await deps.listAgents();
8
+ openclawAgents = Array.isArray(fetched) ? fetched : [];
9
+ }
10
+ catch (err) {
11
+ openclawAgentsError = deps.safeErrorMessage(err);
12
+ }
13
+ const localSnapshot = await deps.loadLocalSnapshot().catch(() => null);
14
+ const localAgents = Array.isArray(localSnapshot?.agents)
15
+ ? localSnapshot.agents
16
+ : [];
17
+ const warnings = [];
18
+ if (openclawAgentsError) {
19
+ warnings.push(`openclaw agent discovery unavailable: ${openclawAgentsError}`);
20
+ }
8
21
  const localById = new Map();
9
- if (localSnapshot) {
10
- for (const agent of localSnapshot.agents) {
22
+ if (localAgents.length > 0) {
23
+ for (const agent of localAgents) {
11
24
  localById.set(agent.id, {
12
25
  status: agent.status,
13
26
  currentTask: agent.currentTask,
@@ -17,9 +30,22 @@ export function registerAgentsCatalogRoutes(router, deps) {
17
30
  });
18
31
  }
19
32
  }
20
- const contexts = deps.readAgentContexts().agents;
21
- const runs = deps.readAgentRuns().runs;
33
+ let contexts = {};
34
+ try {
35
+ contexts = deps.readAgentContexts().agents ?? {};
36
+ }
37
+ catch (err) {
38
+ warnings.push(`agent context snapshot unavailable: ${deps.safeErrorMessage(err)}`);
39
+ }
40
+ let runs = {};
41
+ try {
42
+ runs = deps.readAgentRuns().runs ?? {};
43
+ }
44
+ catch (err) {
45
+ warnings.push(`agent run snapshot unavailable: ${deps.safeErrorMessage(err)}`);
46
+ }
22
47
  const latestRunByAgent = new Map();
48
+ const openclawById = new Map();
23
49
  for (const run of Object.values(runs)) {
24
50
  if (!run || typeof run !== "object")
25
51
  continue;
@@ -43,21 +69,39 @@ export function registerAgentsCatalogRoutes(router, deps) {
43
69
  latestRunByAgent.set(agentId, run);
44
70
  }
45
71
  }
46
- const agents = openclawAgents.map((entry) => {
72
+ for (const entry of openclawAgents) {
47
73
  const id = typeof entry.id === "string" ? entry.id.trim() : "";
48
- const name = typeof entry.name === "string" && entry.name.trim().length > 0
74
+ if (!id)
75
+ continue;
76
+ openclawById.set(id, entry);
77
+ }
78
+ const candidateAgentIds = new Set();
79
+ for (const id of openclawById.keys())
80
+ candidateAgentIds.add(id);
81
+ for (const id of localById.keys())
82
+ candidateAgentIds.add(id);
83
+ for (const id of Object.keys(contexts ?? {})) {
84
+ const normalized = id.trim();
85
+ if (normalized)
86
+ candidateAgentIds.add(normalized);
87
+ }
88
+ for (const id of latestRunByAgent.keys())
89
+ candidateAgentIds.add(id);
90
+ const agents = [...candidateAgentIds].sort((a, b) => a.localeCompare(b)).map((agentId) => {
91
+ const entry = openclawById.get(agentId) ?? null;
92
+ const name = typeof entry?.name === "string" && entry.name.trim().length > 0
49
93
  ? entry.name.trim()
50
- : id || "unknown";
51
- const local = id ? localById.get(id) ?? null : null;
52
- const context = id ? contexts[id] ?? null : null;
53
- const runFromSession = id && local?.runId ? runs[local.runId] ?? null : null;
54
- const run = runFromSession ?? (id ? latestRunByAgent.get(id) ?? null : null);
94
+ : agentId || "unknown";
95
+ const local = localById.get(agentId) ?? null;
96
+ const context = contexts[agentId] ?? null;
97
+ const runFromSession = local?.runId ? runs[local.runId] ?? null : null;
98
+ const run = runFromSession ?? (latestRunByAgent.get(agentId) ?? null);
55
99
  return {
56
- id,
100
+ id: agentId,
57
101
  name,
58
- workspace: typeof entry.workspace === "string" ? entry.workspace : null,
59
- model: typeof entry.model === "string" ? entry.model : null,
60
- isDefault: Boolean(entry.isDefault),
102
+ workspace: typeof entry?.workspace === "string" ? entry.workspace : null,
103
+ model: typeof entry?.model === "string" ? entry.model : null,
104
+ isDefault: Boolean(entry?.isDefault),
61
105
  status: local?.status ?? null,
62
106
  currentTask: local?.currentTask ?? null,
63
107
  runId: local?.runId ?? null,
@@ -70,6 +114,7 @@ export function registerAgentsCatalogRoutes(router, deps) {
70
114
  deps.sendJson(res, 200, {
71
115
  generatedAt: new Date().toISOString(),
72
116
  agents,
117
+ ...(warnings.length > 0 ? { warnings } : {}),
73
118
  });
74
119
  }
75
120
  catch (err) {
@@ -0,0 +1,19 @@
1
+ import type { Router } from "../router.js";
2
+ type JsonRecord = Record<string, unknown>;
3
+ type RegisterChatRoutesDeps<TReq, TRes> = {
4
+ parseJsonRequest: (req: TReq) => Promise<JsonRecord>;
5
+ pickString: (input: Record<string, unknown>, keys: string[]) => string | null;
6
+ parsePositiveInt: (raw: string | null, fallback: number) => number;
7
+ emitActivitySafe?: (input: {
8
+ initiativeId: string | null;
9
+ sourceClient?: string;
10
+ message: string;
11
+ phase: "intent" | "execution" | "blocked" | "review" | "handoff" | "completed";
12
+ progressPct?: number;
13
+ metadata?: Record<string, unknown>;
14
+ }) => Promise<unknown>;
15
+ sendJson: (res: TRes, status: number, payload: unknown) => void;
16
+ safeErrorMessage: (err: unknown) => string;
17
+ };
18
+ export declare function registerChatRoutes<TReq, TRes>(router: Router<Record<string, never>, TReq, TRes>, deps: RegisterChatRoutesDeps<TReq, TRes>): void;
19
+ export {};