@useorgx/openclaw-plugin 0.7.11 → 0.7.16

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 (198) hide show
  1. package/README.md +94 -122
  2. package/dashboard/dist/assets/8pbG6uLK.js +1 -0
  3. package/dashboard/dist/assets/8pbG6uLK.js.br +0 -0
  4. package/dashboard/dist/assets/8pbG6uLK.js.gz +0 -0
  5. package/dashboard/dist/assets/B1LENRC8.js +212 -0
  6. package/dashboard/dist/assets/B1LENRC8.js.br +0 -0
  7. package/dashboard/dist/assets/B1LENRC8.js.gz +0 -0
  8. package/dashboard/dist/assets/{tcEHYcbW.js → BCudUvwg.js} +1 -1
  9. package/dashboard/dist/assets/BCudUvwg.js.br +0 -0
  10. package/dashboard/dist/assets/BCudUvwg.js.gz +0 -0
  11. package/dashboard/dist/assets/{Du1wfrXa.js → BM75sh1f.js} +2 -2
  12. package/dashboard/dist/assets/BM75sh1f.js.br +0 -0
  13. package/dashboard/dist/assets/BM75sh1f.js.gz +0 -0
  14. package/dashboard/dist/assets/BV0BcV1u.js +53 -0
  15. package/dashboard/dist/assets/BV0BcV1u.js.br +0 -0
  16. package/dashboard/dist/assets/BV0BcV1u.js.gz +0 -0
  17. package/dashboard/dist/assets/BYVYH9CH.js +1 -0
  18. package/dashboard/dist/assets/BYVYH9CH.js.br +0 -0
  19. package/dashboard/dist/assets/BYVYH9CH.js.gz +0 -0
  20. package/dashboard/dist/assets/BjK42gtU.js +1 -0
  21. package/dashboard/dist/assets/BjK42gtU.js.br +0 -0
  22. package/dashboard/dist/assets/BjK42gtU.js.gz +0 -0
  23. package/dashboard/dist/assets/BkMrrjAv.js +1 -0
  24. package/dashboard/dist/assets/BkMrrjAv.js.br +0 -0
  25. package/dashboard/dist/assets/BkMrrjAv.js.gz +0 -0
  26. package/dashboard/dist/assets/BpF7v1Dk.js +1 -0
  27. package/dashboard/dist/assets/BpF7v1Dk.js.br +0 -0
  28. package/dashboard/dist/assets/BpF7v1Dk.js.gz +0 -0
  29. package/dashboard/dist/assets/{AqVoI3SF.js → Bv_86bUY.js} +1 -1
  30. package/dashboard/dist/assets/Bv_86bUY.js.br +0 -0
  31. package/dashboard/dist/assets/Bv_86bUY.js.gz +0 -0
  32. package/dashboard/dist/assets/C-MOJWHs.js +1 -0
  33. package/dashboard/dist/assets/C-MOJWHs.js.br +0 -0
  34. package/dashboard/dist/assets/C-MOJWHs.js.gz +0 -0
  35. package/dashboard/dist/assets/C3PrI8L7.js +1 -0
  36. package/dashboard/dist/assets/C3PrI8L7.js.br +0 -0
  37. package/dashboard/dist/assets/C3PrI8L7.js.gz +0 -0
  38. package/dashboard/dist/assets/{CD-q5mdP.js → C6AqbA9J.js} +1 -1
  39. package/dashboard/dist/assets/C6AqbA9J.js.br +0 -0
  40. package/dashboard/dist/assets/C6AqbA9J.js.gz +0 -0
  41. package/dashboard/dist/assets/CSlBSRyv.js +1 -0
  42. package/dashboard/dist/assets/CSlBSRyv.js.br +0 -0
  43. package/dashboard/dist/assets/CSlBSRyv.js.gz +0 -0
  44. package/dashboard/dist/assets/{beHYBbh6.js → CUXb_4F3.js} +2 -2
  45. package/dashboard/dist/assets/CUXb_4F3.js.br +0 -0
  46. package/dashboard/dist/assets/CUXb_4F3.js.gz +0 -0
  47. package/dashboard/dist/assets/Cn8sRTkO.js +1 -0
  48. package/dashboard/dist/assets/Cn8sRTkO.js.br +0 -0
  49. package/dashboard/dist/assets/Cn8sRTkO.js.gz +0 -0
  50. package/dashboard/dist/assets/D5IgXoTj.js +1 -0
  51. package/dashboard/dist/assets/D5IgXoTj.js.br +0 -0
  52. package/dashboard/dist/assets/D5IgXoTj.js.gz +0 -0
  53. package/dashboard/dist/assets/DMKyYAtD.js +1 -0
  54. package/dashboard/dist/assets/DMKyYAtD.js.br +0 -0
  55. package/dashboard/dist/assets/DMKyYAtD.js.gz +0 -0
  56. package/dashboard/dist/assets/{DCP-C7fn.js → DXzpQUC0.js} +1 -1
  57. package/dashboard/dist/assets/DXzpQUC0.js.br +0 -0
  58. package/dashboard/dist/assets/DXzpQUC0.js.gz +0 -0
  59. package/dashboard/dist/assets/Dj2k1r16.js +8 -0
  60. package/dashboard/dist/assets/Dj2k1r16.js.br +0 -0
  61. package/dashboard/dist/assets/Dj2k1r16.js.gz +0 -0
  62. package/dashboard/dist/assets/JDPvhd68.js +1 -0
  63. package/dashboard/dist/assets/JDPvhd68.js.br +0 -0
  64. package/dashboard/dist/assets/JDPvhd68.js.gz +0 -0
  65. package/dashboard/dist/assets/R6N_VVqm.js +1 -0
  66. package/dashboard/dist/assets/R6N_VVqm.js.br +0 -0
  67. package/dashboard/dist/assets/R6N_VVqm.js.gz +0 -0
  68. package/dashboard/dist/assets/cEP7N1dn.js +1 -0
  69. package/dashboard/dist/assets/cEP7N1dn.js.br +0 -0
  70. package/dashboard/dist/assets/cEP7N1dn.js.gz +0 -0
  71. package/dashboard/dist/assets/cX2e-TLi.js +1 -0
  72. package/dashboard/dist/assets/cX2e-TLi.js.br +0 -0
  73. package/dashboard/dist/assets/cX2e-TLi.js.gz +0 -0
  74. package/dashboard/dist/assets/eeHXe_OQ.js +9 -0
  75. package/dashboard/dist/assets/eeHXe_OQ.js.br +0 -0
  76. package/dashboard/dist/assets/eeHXe_OQ.js.gz +0 -0
  77. package/dashboard/dist/assets/iLnvdWmW.css +1 -0
  78. package/dashboard/dist/assets/iLnvdWmW.css.br +0 -0
  79. package/dashboard/dist/assets/iLnvdWmW.css.gz +0 -0
  80. package/dashboard/dist/assets/konqMbVI.js +1 -0
  81. package/dashboard/dist/assets/konqMbVI.js.br +0 -0
  82. package/dashboard/dist/assets/konqMbVI.js.gz +0 -0
  83. package/dashboard/dist/assets/wc6cgXzV.js +1 -0
  84. package/dashboard/dist/assets/wc6cgXzV.js.br +0 -0
  85. package/dashboard/dist/assets/wc6cgXzV.js.gz +0 -0
  86. package/dashboard/dist/brand/control-tower.png +0 -0
  87. package/dashboard/dist/brand/design-codex.png +0 -0
  88. package/dashboard/dist/brand/engineering-autopilot.png +0 -0
  89. package/dashboard/dist/brand/launch-captain.png +0 -0
  90. package/dashboard/dist/brand/orgx-logo.png +0 -0
  91. package/dashboard/dist/brand/pipeline-intelligence.png +0 -0
  92. package/dashboard/dist/brand/product-orchestrator.png +0 -0
  93. package/dashboard/dist/brand/xandy-orchestrator.png +0 -0
  94. package/dashboard/dist/index.html +8 -6
  95. package/dashboard/dist/index.html.br +0 -0
  96. package/dashboard/dist/index.html.gz +0 -0
  97. package/dist/hash-utils.d.ts +1 -0
  98. package/dist/hash-utils.js +4 -0
  99. package/dist/http/helpers/auto-continue-engine.d.ts +15 -0
  100. package/dist/http/helpers/auto-continue-engine.js +289 -67
  101. package/dist/http/helpers/autopilot-slice-utils.js +112 -66
  102. package/dist/http/helpers/hash-utils.d.ts +1 -1
  103. package/dist/http/helpers/hash-utils.js +1 -1
  104. package/dist/http/helpers/mission-control.d.ts +3 -0
  105. package/dist/http/helpers/mission-control.js +43 -9
  106. package/dist/http/helpers/queue-constants.d.ts +37 -0
  107. package/dist/http/helpers/queue-constants.js +34 -0
  108. package/dist/http/helpers/slice-experience-v2.js +2 -5
  109. package/dist/http/helpers/slice-run-projections.js +2 -5
  110. package/dist/http/helpers/value-utils.d.ts +1 -1
  111. package/dist/http/helpers/value-utils.js +5 -2
  112. package/dist/http/helpers/workspace-scope.js +4 -3
  113. package/dist/http/index.js +104 -61
  114. package/dist/http/routes/chat.d.ts +1 -1
  115. package/dist/http/routes/chat.js +3 -23
  116. package/dist/http/routes/entities.js +60 -2
  117. package/dist/http/routes/entity-dynamic.js +49 -9
  118. package/dist/http/routes/live-snapshot.d.ts +10 -1
  119. package/dist/http/routes/live-snapshot.js +15 -26
  120. package/dist/http/routes/mission-control-actions.d.ts +6 -0
  121. package/dist/http/routes/mission-control-actions.js +35 -18
  122. package/dist/http/routes/mission-control-read.js +4 -107
  123. package/dist/lib/type-coercion.d.ts +10 -0
  124. package/dist/lib/type-coercion.js +82 -0
  125. package/dist/mcp-http-handler.js +14 -2
  126. package/dist/openclaw.plugin.json +1 -1
  127. package/dist/services/experiment-randomization.js +9 -2
  128. package/openclaw.plugin.json +1 -1
  129. package/package.json +3 -2
  130. package/dashboard/dist/assets/AqVoI3SF.js.br +0 -0
  131. package/dashboard/dist/assets/AqVoI3SF.js.gz +0 -0
  132. package/dashboard/dist/assets/BC4WvnHJ.js +0 -1
  133. package/dashboard/dist/assets/BC4WvnHJ.js.br +0 -0
  134. package/dashboard/dist/assets/BC4WvnHJ.js.gz +0 -0
  135. package/dashboard/dist/assets/BG5mwTkg.js +0 -1
  136. package/dashboard/dist/assets/BG5mwTkg.js.br +0 -0
  137. package/dashboard/dist/assets/BG5mwTkg.js.gz +0 -0
  138. package/dashboard/dist/assets/BJgZIVUQ.js +0 -53
  139. package/dashboard/dist/assets/BJgZIVUQ.js.br +0 -0
  140. package/dashboard/dist/assets/BJgZIVUQ.js.gz +0 -0
  141. package/dashboard/dist/assets/BNh-XYPV.js +0 -1
  142. package/dashboard/dist/assets/BNh-XYPV.js.br +0 -0
  143. package/dashboard/dist/assets/BNh-XYPV.js.gz +0 -0
  144. package/dashboard/dist/assets/BTAEErUY.js +0 -1
  145. package/dashboard/dist/assets/BTAEErUY.js.br +0 -0
  146. package/dashboard/dist/assets/BTAEErUY.js.gz +0 -0
  147. package/dashboard/dist/assets/BepW_590.js +0 -1
  148. package/dashboard/dist/assets/BepW_590.js.br +0 -0
  149. package/dashboard/dist/assets/BepW_590.js.gz +0 -0
  150. package/dashboard/dist/assets/BerAfzjq.js +0 -1
  151. package/dashboard/dist/assets/BerAfzjq.js.br +0 -0
  152. package/dashboard/dist/assets/BerAfzjq.js.gz +0 -0
  153. package/dashboard/dist/assets/Bp3N-QL5.js +0 -212
  154. package/dashboard/dist/assets/Bp3N-QL5.js.br +0 -0
  155. package/dashboard/dist/assets/Bp3N-QL5.js.gz +0 -0
  156. package/dashboard/dist/assets/C-KIc3Wc.js +0 -1
  157. package/dashboard/dist/assets/C-KIc3Wc.js.br +0 -0
  158. package/dashboard/dist/assets/C-KIc3Wc.js.gz +0 -0
  159. package/dashboard/dist/assets/C3dZRz9P.css +0 -1
  160. package/dashboard/dist/assets/C3dZRz9P.css.br +0 -0
  161. package/dashboard/dist/assets/C3dZRz9P.css.gz +0 -0
  162. package/dashboard/dist/assets/CD-q5mdP.js.br +0 -0
  163. package/dashboard/dist/assets/CD-q5mdP.js.gz +0 -0
  164. package/dashboard/dist/assets/CL_wXqR7.js +0 -1
  165. package/dashboard/dist/assets/CL_wXqR7.js.br +0 -0
  166. package/dashboard/dist/assets/CL_wXqR7.js.gz +0 -0
  167. package/dashboard/dist/assets/CdvjC9G9.js +0 -1
  168. package/dashboard/dist/assets/CdvjC9G9.js.br +0 -0
  169. package/dashboard/dist/assets/CdvjC9G9.js.gz +0 -0
  170. package/dashboard/dist/assets/Ck2agw-s.js +0 -1
  171. package/dashboard/dist/assets/Ck2agw-s.js.br +0 -0
  172. package/dashboard/dist/assets/Ck2agw-s.js.gz +0 -0
  173. package/dashboard/dist/assets/CxQ08qFN.js +0 -9
  174. package/dashboard/dist/assets/CxQ08qFN.js.br +0 -0
  175. package/dashboard/dist/assets/CxQ08qFN.js.gz +0 -0
  176. package/dashboard/dist/assets/D2CH1H6k.js +0 -1
  177. package/dashboard/dist/assets/D2CH1H6k.js.br +0 -0
  178. package/dashboard/dist/assets/D2CH1H6k.js.gz +0 -0
  179. package/dashboard/dist/assets/D9esz7jd.js +0 -1
  180. package/dashboard/dist/assets/D9esz7jd.js.br +0 -0
  181. package/dashboard/dist/assets/D9esz7jd.js.gz +0 -0
  182. package/dashboard/dist/assets/DCP-C7fn.js.br +0 -0
  183. package/dashboard/dist/assets/DCP-C7fn.js.gz +0 -0
  184. package/dashboard/dist/assets/DJASCd69.js +0 -1
  185. package/dashboard/dist/assets/DJASCd69.js.br +0 -0
  186. package/dashboard/dist/assets/DJASCd69.js.gz +0 -0
  187. package/dashboard/dist/assets/Dm9AybAp.js +0 -1
  188. package/dashboard/dist/assets/Dm9AybAp.js.br +0 -0
  189. package/dashboard/dist/assets/Dm9AybAp.js.gz +0 -0
  190. package/dashboard/dist/assets/Du1wfrXa.js.br +0 -0
  191. package/dashboard/dist/assets/Du1wfrXa.js.gz +0 -0
  192. package/dashboard/dist/assets/beHYBbh6.js.br +0 -0
  193. package/dashboard/dist/assets/beHYBbh6.js.gz +0 -0
  194. package/dashboard/dist/assets/cNrhgGc1.js +0 -8
  195. package/dashboard/dist/assets/cNrhgGc1.js.br +0 -0
  196. package/dashboard/dist/assets/cNrhgGc1.js.gz +0 -0
  197. package/dashboard/dist/assets/tcEHYcbW.js.br +0 -0
  198. package/dashboard/dist/assets/tcEHYcbW.js.gz +0 -0
@@ -159,7 +159,57 @@ export function ensureAutopilotSliceSchemaPath(schemaFilename) {
159
159
  }
160
160
  export function parseSliceResult(raw) {
161
161
  const allowedStatuses = new Set(["completed", "blocked", "needs_decision", "error"]);
162
+ const normalizeStatusValue = (value) => {
163
+ if (typeof value !== "string")
164
+ return "";
165
+ const normalized = value.trim().toLowerCase();
166
+ return allowedStatuses.has(normalized) ? normalized : "";
167
+ };
162
168
  const stripUtf8Bom = (text) => text.replace(/^\uFEFF/, "");
169
+ const extractTopLevelObjects = (text) => {
170
+ let inString = false;
171
+ let escaped = false;
172
+ let depth = 0;
173
+ let start = -1;
174
+ const objects = [];
175
+ for (let i = 0; i < text.length; i += 1) {
176
+ const ch = text[i];
177
+ if (inString) {
178
+ if (escaped) {
179
+ escaped = false;
180
+ continue;
181
+ }
182
+ if (ch === "\\") {
183
+ escaped = true;
184
+ continue;
185
+ }
186
+ if (ch === "\"") {
187
+ inString = false;
188
+ }
189
+ continue;
190
+ }
191
+ if (ch === "\"") {
192
+ inString = true;
193
+ continue;
194
+ }
195
+ if (ch === "{") {
196
+ if (depth === 0)
197
+ start = i;
198
+ depth += 1;
199
+ continue;
200
+ }
201
+ if (ch === "}") {
202
+ if (depth <= 0)
203
+ continue;
204
+ depth -= 1;
205
+ if (depth === 0 && start >= 0) {
206
+ objects.push(text.slice(start, i + 1));
207
+ start = -1;
208
+ }
209
+ }
210
+ }
211
+ return objects;
212
+ };
163
213
  const extractMarkdownJsonFences = (text) => {
164
214
  const matches = text.matchAll(/```(?:json)?\s*([\s\S]*?)\s*```/gi);
165
215
  const fences = [];
@@ -192,13 +242,20 @@ export function parseSliceResult(raw) {
192
242
  return normalizeSliceResult(parsedInner);
193
243
  }
194
244
  }
245
+ const objectCandidates = extractTopLevelObjects(normalized);
246
+ for (let i = objectCandidates.length - 1; i >= 0; i -= 1) {
247
+ const parsedObject = parseJsonSafe(stripUtf8Bom(objectCandidates[i]));
248
+ if (parsedObject && typeof parsedObject === "object" && isLikelySliceResult(parsedObject)) {
249
+ return normalizeSliceResult(parsedObject);
250
+ }
251
+ }
195
252
  return null;
196
253
  };
197
254
  const isLikelySliceResult = (value) => {
198
255
  if (!value || typeof value !== "object")
199
256
  return false;
200
257
  const record = value;
201
- const status = typeof record.status === "string" ? record.status : "";
258
+ const status = normalizeStatusValue(record.status);
202
259
  const workstreamId = typeof record.workstream_id === "string" ? record.workstream_id : "";
203
260
  const summary = typeof record.summary === "string" ? record.summary : "";
204
261
  return (allowedStatuses.has(status) &&
@@ -207,10 +264,13 @@ export function parseSliceResult(raw) {
207
264
  };
208
265
  const normalizeSliceResult = (value) => {
209
266
  const record = value;
210
- const status = typeof record.status === "string" ? record.status : "";
267
+ const status = normalizeStatusValue(record.status);
211
268
  const decisions = record.decisions_needed;
212
269
  let changed = false;
213
- let nextRecord = record;
270
+ let nextRecord = status ? { ...record, status } : record;
271
+ if (status && record.status !== status) {
272
+ changed = true;
273
+ }
214
274
  if (Array.isArray(decisions)) {
215
275
  const normalized = decisions.map((decision) => {
216
276
  if (!decision || typeof decision !== "object")
@@ -275,7 +335,11 @@ export function parseSliceResult(raw) {
275
335
  const record = value;
276
336
  const parseEmbeddedText = (candidate) => {
277
337
  if (typeof candidate === "string") {
278
- return parseSliceJsonText(candidate);
338
+ const direct = parseSliceJsonText(candidate);
339
+ if (direct)
340
+ return direct;
341
+ // Some envelopes embed worker logs/prose with a trailing JSON object.
342
+ return parseSliceResult(candidate);
279
343
  }
280
344
  if (Array.isArray(candidate)) {
281
345
  for (let i = candidate.length - 1; i >= 0; i -= 1) {
@@ -288,12 +352,6 @@ export function parseSliceResult(raw) {
288
352
  if (!candidate || typeof candidate !== "object")
289
353
  return null;
290
354
  const candidateRecord = candidate;
291
- if (typeof candidateRecord.value === "string") {
292
- return parseSliceJsonText(candidateRecord.value);
293
- }
294
- if (typeof candidateRecord.text === "string") {
295
- return parseSliceJsonText(candidateRecord.text);
296
- }
297
355
  const fromValue = parseEmbeddedText(candidateRecord.value);
298
356
  if (fromValue)
299
357
  return fromValue;
@@ -392,50 +450,6 @@ export function parseSliceResult(raw) {
392
450
  if (directTextParsed && typeof directTextParsed === "object")
393
451
  return directTextParsed;
394
452
  // Tolerant parse: extract the last complete top-level JSON object from mixed logs.
395
- const extractTopLevelObjects = (text) => {
396
- let inString = false;
397
- let escaped = false;
398
- let depth = 0;
399
- let start = -1;
400
- const objects = [];
401
- for (let i = 0; i < text.length; i += 1) {
402
- const ch = text[i];
403
- if (inString) {
404
- if (escaped) {
405
- escaped = false;
406
- continue;
407
- }
408
- if (ch === "\\") {
409
- escaped = true;
410
- continue;
411
- }
412
- if (ch === "\"") {
413
- inString = false;
414
- }
415
- continue;
416
- }
417
- if (ch === "\"") {
418
- inString = true;
419
- continue;
420
- }
421
- if (ch === "{") {
422
- if (depth === 0)
423
- start = i;
424
- depth += 1;
425
- continue;
426
- }
427
- if (ch === "}") {
428
- if (depth <= 0)
429
- continue;
430
- depth -= 1;
431
- if (depth === 0 && start >= 0) {
432
- objects.push(text.slice(start, i + 1));
433
- start = -1;
434
- }
435
- }
436
- }
437
- return objects;
438
- };
439
453
  const candidates = extractTopLevelObjects(trimmed);
440
454
  for (let i = candidates.length - 1; i >= 0; i -= 1) {
441
455
  const candidate = candidates[i];
@@ -481,24 +495,56 @@ const UUID_RE = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i;
481
495
  export function extractSessionIdFromOutput(raw, _sourceClient) {
482
496
  if (!raw || typeof raw !== "string")
483
497
  return null;
498
+ const extractUuid = (value) => {
499
+ const match = value.trim().match(UUID_RE);
500
+ return match?.[0] ?? null;
501
+ };
502
+ const findSessionId = (candidate) => {
503
+ if (!candidate)
504
+ return null;
505
+ if (typeof candidate === "string") {
506
+ const parsedCandidate = parseJsonSafe(candidate.trim());
507
+ if (parsedCandidate)
508
+ return findSessionId(parsedCandidate);
509
+ return null;
510
+ }
511
+ if (Array.isArray(candidate)) {
512
+ for (const item of candidate) {
513
+ const found = findSessionId(item);
514
+ if (found)
515
+ return found;
516
+ }
517
+ return null;
518
+ }
519
+ if (typeof candidate !== "object")
520
+ return null;
521
+ const record = candidate;
522
+ for (const key of ["session_id", "sessionId", "conversation_id"]) {
523
+ const value = record[key];
524
+ if (typeof value === "string") {
525
+ const uuid = extractUuid(value);
526
+ if (uuid)
527
+ return uuid;
528
+ }
529
+ }
530
+ return (findSessionId(record.value) ??
531
+ findSessionId(record.text) ??
532
+ findSessionId(record.content) ??
533
+ findSessionId(record.output_text) ??
534
+ null);
535
+ };
484
536
  const parsed = parseJsonSafe(raw.trim());
485
537
  if (parsed && typeof parsed === "object") {
486
- // Walk common envelope shapes: top-level, result, structured_output, final_output
487
- const candidates = [
538
+ const found = findSessionId([
488
539
  parsed,
489
540
  parsed.result,
490
541
  parsed.structured_output,
491
542
  parsed.final_output,
492
- ];
493
- for (const obj of candidates) {
494
- if (!obj || typeof obj !== "object")
495
- continue;
496
- const record = obj;
497
- for (const key of ["session_id", "sessionId", "conversation_id"]) {
498
- const value = record[key];
499
- if (typeof value === "string" && UUID_RE.test(value))
500
- return value.trim();
501
- }
543
+ parsed.output_text,
544
+ parsed.output,
545
+ ]);
546
+ if (found) {
547
+ return found;
502
548
  }
503
549
  }
504
550
  // Fallback: scan raw text for session_id: <uuid> pattern
@@ -1 +1 @@
1
- export { idempotencyKey, stableHash } from "../../hash-utils.js";
1
+ export { deterministicActivityId, idempotencyKey, stableHash } from "../../hash-utils.js";
@@ -1 +1 @@
1
- export { idempotencyKey, stableHash } from "../../hash-utils.js";
1
+ export { deterministicActivityId, idempotencyKey, stableHash } from "../../hash-utils.js";
@@ -87,7 +87,10 @@ export declare const DEFAULT_TOKEN_BUDGET_ASSUMPTIONS: {
87
87
  export declare function pickStringArray(record: Record<string, unknown>, keys: string[]): string[];
88
88
  export declare function dedupeStrings(items: string[]): string[];
89
89
  export declare function isTodoStatus(status: string): boolean;
90
+ export declare function isPausedStatus(status: string): boolean;
91
+ export declare function isBlockedStatus(status: string): boolean;
90
92
  export declare function isInProgressStatus(status: string): boolean;
93
+ export declare function deriveInitiativeLifecycleStatus(currentStatus: string, childStatuses: string[]): string;
91
94
  export declare function isDispatchableWorkstreamStatus(status: string): boolean;
92
95
  export declare function isDoneStatus(status: string): boolean;
93
96
  export declare function listEntitiesSafe(client: OrgXClient, type: MissionControlNodeType, filters: Record<string, unknown>): Promise<{
@@ -79,6 +79,9 @@ export function safeErrorMessage(err) {
79
79
  const sanitized = stripStructuredNoise(normalizedMessage);
80
80
  const normalized = sanitized.toLowerCase();
81
81
  if (normalized.length > 0) {
82
+ if (normalized.includes("relation does not exist")) {
83
+ return sanitized;
84
+ }
82
85
  if (normalized.includes("internal_error") || normalized.includes("internal server error")) {
83
86
  return "temporary server issue";
84
87
  }
@@ -634,6 +637,18 @@ export function isTodoStatus(status) {
634
637
  normalized === "backlog" ||
635
638
  normalized === "pending");
636
639
  }
640
+ export function isPausedStatus(status) {
641
+ const normalized = status.toLowerCase();
642
+ return (normalized === "paused" ||
643
+ normalized === "idle" ||
644
+ normalized === "hold" ||
645
+ normalized === "on_hold" ||
646
+ normalized === "waiting");
647
+ }
648
+ export function isBlockedStatus(status) {
649
+ const normalized = status.toLowerCase();
650
+ return normalized === "blocked" || normalized === "at_risk" || normalized === "needs_input";
651
+ }
637
652
  export function isInProgressStatus(status) {
638
653
  const normalized = status.toLowerCase();
639
654
  return (normalized === "in_progress" ||
@@ -641,6 +656,30 @@ export function isInProgressStatus(status) {
641
656
  normalized === "running" ||
642
657
  normalized === "queued");
643
658
  }
659
+ export function deriveInitiativeLifecycleStatus(currentStatus, childStatuses) {
660
+ const normalizedCurrent = currentStatus.toLowerCase();
661
+ if (!childStatuses.length)
662
+ return currentStatus;
663
+ const hasInProgressChildren = childStatuses.some((status) => isInProgressStatus(status));
664
+ const hasRemainingChildren = childStatuses.some((status) => !isDoneStatus(status));
665
+ const hasBlockedChildren = childStatuses.some((status) => isBlockedStatus(status));
666
+ const hasPausedChildren = childStatuses.some((status) => isPausedStatus(status));
667
+ const hasTodoChildren = childStatuses.some((status) => isTodoStatus(status));
668
+ const isActiveLikeCurrent = normalizedCurrent === "active" ||
669
+ normalizedCurrent === "running" ||
670
+ normalizedCurrent === "in_progress" ||
671
+ normalizedCurrent === "queued";
672
+ if (!hasInProgressChildren && isActiveLikeCurrent && hasRemainingChildren) {
673
+ if (hasBlockedChildren && !hasPausedChildren && !hasTodoChildren) {
674
+ return "blocked";
675
+ }
676
+ return "paused";
677
+ }
678
+ if (hasInProgressChildren && (normalizedCurrent === "paused" || normalizedCurrent === "idle")) {
679
+ return "active";
680
+ }
681
+ return currentStatus;
682
+ }
644
683
  export function isDispatchableWorkstreamStatus(status) {
645
684
  const normalized = status.toLowerCase();
646
685
  if (!normalized)
@@ -705,10 +744,10 @@ export async function listEntitiesSafe(client, type, filters) {
705
744
  }
706
745
  }
707
746
  export async function buildMissionControlGraph(client, initiativeId, options) {
747
+ const degraded = [];
708
748
  if (!UUID_RE.test(initiativeId)) {
709
- throw new Error(`buildMissionControlGraph: initiativeId must be a UUID, got "${initiativeId}"`);
749
+ degraded.push(`initiative id "${initiativeId}" is non-UUID; using compatibility graph lookup`);
710
750
  }
711
- const degraded = [];
712
751
  const preloadedInitiative = options?.initiativeEntity ?? null;
713
752
  const [initiativeResult, workstreamResult, milestoneResult, taskResult] = await Promise.all([
714
753
  preloadedInitiative
@@ -886,13 +925,8 @@ export async function buildMissionControlGraph(client, initiativeId, options) {
886
925
  }
887
926
  }
888
927
  const taskNodesOnly = nodes.filter((node) => node.type === "task");
889
- const hasActiveTasks = taskNodesOnly.some((node) => isInProgressStatus(node.status));
890
- const hasTodoTasks = taskNodesOnly.some((node) => isTodoStatus(node.status));
891
- if (initiativeNode.status.toLowerCase() === "active" &&
892
- !hasActiveTasks &&
893
- hasTodoTasks) {
894
- initiativeNode.status = "paused";
895
- }
928
+ const lifecycleChildren = taskNodesOnly.length > 0 ? taskNodesOnly : workstreamNodes;
929
+ initiativeNode.status = deriveInitiativeLifecycleStatus(initiativeNode.status, lifecycleChildren.map((node) => node.status));
896
930
  const nodeById = new Map(nodes.map((node) => [node.id, node]));
897
931
  const taskIsReady = (task) => task.dependencyIds.every((depId) => {
898
932
  const dependency = nodeById.get(depId);
@@ -0,0 +1,37 @@
1
+ /** Queue state for next-up items (workstream-level). */
2
+ export declare const QueueState: {
3
+ readonly QUEUED: "queued";
4
+ readonly RUNNING: "running";
5
+ readonly BLOCKED: "blocked";
6
+ readonly IDLE: "idle";
7
+ /** Used only in the API normalization layer (mission-control-read.ts). */
8
+ readonly COMPLETED: "completed";
9
+ };
10
+ /** Core queue states used by the queue builder (excludes "completed"). */
11
+ export type CoreQueueState = "queued" | "running" | "blocked" | "idle";
12
+ /** Extended queue state including API-only values. */
13
+ export type QueueStateValue = (typeof QueueState)[keyof typeof QueueState];
14
+ /** Auto-continue lane state (per-workstream within a run). */
15
+ export declare const LaneState: {
16
+ readonly IDLE: "idle";
17
+ readonly RUNNING: "running";
18
+ readonly BLOCKED: "blocked";
19
+ readonly WAITING_DEPENDENCY: "waiting_dependency";
20
+ readonly RATE_LIMITED: "rate_limited";
21
+ readonly COMPLETED: "completed";
22
+ };
23
+ export type LaneStateValue = (typeof LaneState)[keyof typeof LaneState];
24
+ /** Auto-continue run status. */
25
+ export declare const RunStatus: {
26
+ readonly RUNNING: "running";
27
+ readonly STOPPING: "stopping";
28
+ readonly STOPPED: "stopped";
29
+ };
30
+ export type RunStatusValue = (typeof RunStatus)[keyof typeof RunStatus];
31
+ /** Runner source — how the agent was assigned. */
32
+ export declare const RunnerSource: {
33
+ readonly ASSIGNED: "assigned";
34
+ readonly INFERRED: "inferred";
35
+ readonly FALLBACK: "fallback";
36
+ };
37
+ export type RunnerSourceValue = (typeof RunnerSource)[keyof typeof RunnerSource];
@@ -0,0 +1,34 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Canonical state constants for queue, lane, and related enumerations.
3
+ // Use these instead of raw string literals throughout the codebase.
4
+ // ---------------------------------------------------------------------------
5
+ /** Queue state for next-up items (workstream-level). */
6
+ export const QueueState = {
7
+ QUEUED: "queued",
8
+ RUNNING: "running",
9
+ BLOCKED: "blocked",
10
+ IDLE: "idle",
11
+ /** Used only in the API normalization layer (mission-control-read.ts). */
12
+ COMPLETED: "completed",
13
+ };
14
+ /** Auto-continue lane state (per-workstream within a run). */
15
+ export const LaneState = {
16
+ IDLE: "idle",
17
+ RUNNING: "running",
18
+ BLOCKED: "blocked",
19
+ WAITING_DEPENDENCY: "waiting_dependency",
20
+ RATE_LIMITED: "rate_limited",
21
+ COMPLETED: "completed",
22
+ };
23
+ /** Auto-continue run status. */
24
+ export const RunStatus = {
25
+ RUNNING: "running",
26
+ STOPPING: "stopping",
27
+ STOPPED: "stopped",
28
+ };
29
+ /** Runner source — how the agent was assigned. */
30
+ export const RunnerSource = {
31
+ ASSIGNED: "assigned",
32
+ INFERRED: "inferred",
33
+ FALLBACK: "fallback",
34
+ };
@@ -1,10 +1,7 @@
1
+ import { asRecord } from "../../lib/type-coercion.js";
1
2
  const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
2
3
  const GENERIC_ACTOR_IDS = new Set(["main", "unknown", "system", "openclaw", "orgx"]);
3
- function asRecord(value) {
4
- if (!value || typeof value !== "object" || Array.isArray(value))
5
- return null;
6
- return value;
7
- }
4
+ // asRecord imported from ../../lib/type-coercion.js
8
5
  function normalizeText(value) {
9
6
  if (typeof value !== "string")
10
7
  return null;
@@ -1,3 +1,4 @@
1
+ import { asRecord } from "../../lib/type-coercion.js";
1
2
  const TERMINAL_STATES = new Set([
2
3
  "completed",
3
4
  "needs_review",
@@ -5,11 +6,7 @@ const TERMINAL_STATES = new Set([
5
6
  "archived",
6
7
  ]);
7
8
  const RUN_LIKE_STATUS = new Set(["dispatching", "running"]);
8
- function asRecord(value) {
9
- if (!value || typeof value !== "object" || Array.isArray(value))
10
- return null;
11
- return value;
12
- }
9
+ // asRecord imported from ../../lib/type-coercion.js
13
10
  function normalizeText(value) {
14
11
  if (typeof value !== "string")
15
12
  return null;
@@ -2,5 +2,5 @@ export declare function pickString(record: Record<string, unknown>, keys: string
2
2
  export declare function pickNumber(record: Record<string, unknown>, keys: string[]): number | null;
3
3
  export declare function pickHeaderString(headers: Record<string, string | string[] | undefined>, keys: string[]): string | null;
4
4
  export declare function toIsoString(value: string | null): string | null;
5
- export declare function parsePositiveInt(raw: string | null, fallback: number): number;
5
+ export declare function parsePositiveInt(raw: string | null, fallback: number, max?: number): number;
6
6
  export declare function parseBooleanQuery(raw: string | null): boolean;
@@ -48,7 +48,7 @@ export function toIsoString(value) {
48
48
  return null;
49
49
  return new Date(parsed).toISOString();
50
50
  }
51
- export function parsePositiveInt(raw, fallback) {
51
+ export function parsePositiveInt(raw, fallback, max = Number.POSITIVE_INFINITY) {
52
52
  if (!raw)
53
53
  return fallback;
54
54
  const normalized = raw.trim();
@@ -59,7 +59,10 @@ export function parsePositiveInt(raw, fallback) {
59
59
  return fallback;
60
60
  // Offset-like parameters may intentionally allow zero when fallback is zero.
61
61
  const minimum = fallback <= 0 ? 0 : 1;
62
- return Math.max(minimum, Math.floor(parsed));
62
+ const clamped = Math.max(minimum, Math.floor(parsed));
63
+ if (!Number.isFinite(max))
64
+ return clamped;
65
+ return Math.min(clamped, Math.max(minimum, Math.floor(max)));
63
66
  }
64
67
  export function parseBooleanQuery(raw) {
65
68
  if (!raw)
@@ -70,20 +70,21 @@ export function workspaceScopeFromHeaders(headers) {
70
70
  "x-orgx-command-center-id",
71
71
  "x_orgx_command_center_id",
72
72
  ]);
73
+ const centerId = readScopeValue(headers, ["center"]);
73
74
  if (workspaceId && commandCenterId && workspaceId !== commandCenterId) {
74
75
  return {
75
76
  workspace_id: workspaceId,
76
77
  command_center_id: commandCenterId,
77
- center: workspaceId,
78
+ center: centerId ?? workspaceId,
78
79
  };
79
80
  }
80
- const canonical = workspaceId ?? commandCenterId;
81
+ const canonical = workspaceId ?? commandCenterId ?? centerId;
81
82
  if (!canonical)
82
83
  return null;
83
84
  return {
84
85
  workspace_id: canonical,
85
86
  command_center_id: canonical,
86
- center: canonical,
87
+ center: centerId ?? canonical,
87
88
  };
88
89
  }
89
90
  function mergeCandidates(payloadCandidates, queryCandidates) {