@useorgx/openclaw-plugin 0.7.8 → 0.7.15
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.
- package/README.md +94 -122
- package/dashboard/dist/assets/0RUEVzJa.js +1 -0
- package/dashboard/dist/assets/0RUEVzJa.js.br +0 -0
- package/dashboard/dist/assets/0RUEVzJa.js.gz +0 -0
- package/dashboard/dist/assets/3TtV4moZ.js +1 -0
- package/dashboard/dist/assets/3TtV4moZ.js.br +0 -0
- package/dashboard/dist/assets/3TtV4moZ.js.gz +0 -0
- package/dashboard/dist/assets/3VwNyxUf.js +1 -0
- package/dashboard/dist/assets/3VwNyxUf.js.br +0 -0
- package/dashboard/dist/assets/3VwNyxUf.js.gz +0 -0
- package/dashboard/dist/assets/{DpuQm1oF.js → 7DhYqBrM.js} +2 -2
- package/dashboard/dist/assets/7DhYqBrM.js.br +0 -0
- package/dashboard/dist/assets/7DhYqBrM.js.gz +0 -0
- package/dashboard/dist/assets/{tcEHYcbW.js → BCudUvwg.js} +1 -1
- package/dashboard/dist/assets/BCudUvwg.js.br +0 -0
- package/dashboard/dist/assets/BCudUvwg.js.gz +0 -0
- package/dashboard/dist/assets/BV0BcV1u.js +53 -0
- package/dashboard/dist/assets/BV0BcV1u.js.br +0 -0
- package/dashboard/dist/assets/BV0BcV1u.js.gz +0 -0
- package/dashboard/dist/assets/BVvffj0x.js +1 -0
- package/dashboard/dist/assets/BVvffj0x.js.br +0 -0
- package/dashboard/dist/assets/BVvffj0x.js.gz +0 -0
- package/dashboard/dist/assets/BiOgVMED.js +1 -0
- package/dashboard/dist/assets/BiOgVMED.js.br +0 -0
- package/dashboard/dist/assets/BiOgVMED.js.gz +0 -0
- package/dashboard/dist/assets/BjK42gtU.js +1 -0
- package/dashboard/dist/assets/BjK42gtU.js.br +0 -0
- package/dashboard/dist/assets/BjK42gtU.js.gz +0 -0
- package/dashboard/dist/assets/C-MOJWHs.js +1 -0
- package/dashboard/dist/assets/C-MOJWHs.js.br +0 -0
- package/dashboard/dist/assets/C-MOJWHs.js.gz +0 -0
- package/dashboard/dist/assets/C91KLKit.js +1 -0
- package/dashboard/dist/assets/C91KLKit.js.br +0 -0
- package/dashboard/dist/assets/C91KLKit.js.gz +0 -0
- package/dashboard/dist/assets/{CnitK1MX.js → C9fvfXmS.js} +1 -1
- package/dashboard/dist/assets/C9fvfXmS.js.br +0 -0
- package/dashboard/dist/assets/C9fvfXmS.js.gz +0 -0
- package/dashboard/dist/assets/CFZ4Swr5.js +1 -0
- package/dashboard/dist/assets/CFZ4Swr5.js.br +0 -0
- package/dashboard/dist/assets/CFZ4Swr5.js.gz +0 -0
- package/dashboard/dist/assets/{77gGFBt6.js → CGj8kRhg.js} +1 -1
- package/dashboard/dist/assets/CGj8kRhg.js.br +0 -0
- package/dashboard/dist/assets/CGj8kRhg.js.gz +0 -0
- package/dashboard/dist/assets/CJjEAGFN.js +1 -0
- package/dashboard/dist/assets/CJjEAGFN.js.br +0 -0
- package/dashboard/dist/assets/CJjEAGFN.js.gz +0 -0
- package/dashboard/dist/assets/CKrH5fYO.js +1 -0
- package/dashboard/dist/assets/CKrH5fYO.js.br +0 -0
- package/dashboard/dist/assets/CKrH5fYO.js.gz +0 -0
- package/dashboard/dist/assets/CMTTPXch.js +1 -0
- package/dashboard/dist/assets/CMTTPXch.js.br +0 -0
- package/dashboard/dist/assets/CMTTPXch.js.gz +0 -0
- package/dashboard/dist/assets/CSlBSRyv.js +1 -0
- package/dashboard/dist/assets/CSlBSRyv.js.br +0 -0
- package/dashboard/dist/assets/CSlBSRyv.js.gz +0 -0
- package/dashboard/dist/assets/CnPC783_.js +1 -0
- package/dashboard/dist/assets/CnPC783_.js.br +0 -0
- package/dashboard/dist/assets/CnPC783_.js.gz +0 -0
- package/dashboard/dist/assets/Ctw95IkC.js +1 -0
- package/dashboard/dist/assets/Ctw95IkC.js.br +0 -0
- package/dashboard/dist/assets/Ctw95IkC.js.gz +0 -0
- package/dashboard/dist/assets/DHz-aQPw.js +1 -0
- package/dashboard/dist/assets/DHz-aQPw.js.br +0 -0
- package/dashboard/dist/assets/DHz-aQPw.js.gz +0 -0
- package/dashboard/dist/assets/DNX2foSJ.css +1 -0
- package/dashboard/dist/assets/DNX2foSJ.css.br +0 -0
- package/dashboard/dist/assets/DNX2foSJ.css.gz +0 -0
- package/dashboard/dist/assets/Dj2k1r16.js +8 -0
- package/dashboard/dist/assets/Dj2k1r16.js.br +0 -0
- package/dashboard/dist/assets/Dj2k1r16.js.gz +0 -0
- package/dashboard/dist/assets/DxUw4FMR.js +212 -0
- package/dashboard/dist/assets/DxUw4FMR.js.br +0 -0
- package/dashboard/dist/assets/DxUw4FMR.js.gz +0 -0
- package/dashboard/dist/assets/T2NFtzAv.js +1 -0
- package/dashboard/dist/assets/T2NFtzAv.js.br +0 -0
- package/dashboard/dist/assets/T2NFtzAv.js.gz +0 -0
- package/dashboard/dist/assets/cX2e-TLi.js +1 -0
- package/dashboard/dist/assets/cX2e-TLi.js.br +0 -0
- package/dashboard/dist/assets/cX2e-TLi.js.gz +0 -0
- package/dashboard/dist/assets/eeHXe_OQ.js +9 -0
- package/dashboard/dist/assets/eeHXe_OQ.js.br +0 -0
- package/dashboard/dist/assets/eeHXe_OQ.js.gz +0 -0
- package/dashboard/dist/assets/{DxKG5zy8.js → gZr_xKlA.js} +2 -2
- package/dashboard/dist/assets/gZr_xKlA.js.br +0 -0
- package/dashboard/dist/assets/gZr_xKlA.js.gz +0 -0
- package/dashboard/dist/brand/control-tower.png +0 -0
- package/dashboard/dist/brand/design-codex.png +0 -0
- package/dashboard/dist/brand/engineering-autopilot.png +0 -0
- package/dashboard/dist/brand/launch-captain.png +0 -0
- package/dashboard/dist/brand/orgx-logo.png +0 -0
- package/dashboard/dist/brand/pipeline-intelligence.png +0 -0
- package/dashboard/dist/brand/product-orchestrator.png +0 -0
- package/dashboard/dist/brand/xandy-orchestrator.png +0 -0
- package/dashboard/dist/index.html +8 -6
- package/dashboard/dist/index.html.br +0 -0
- package/dashboard/dist/index.html.gz +0 -0
- package/dist/hash-utils.d.ts +1 -0
- package/dist/hash-utils.js +4 -0
- package/dist/http/helpers/auto-continue-engine.d.ts +36 -0
- package/dist/http/helpers/auto-continue-engine.js +198 -75
- package/dist/http/helpers/autopilot-runtime.d.ts +1 -0
- package/dist/http/helpers/autopilot-runtime.js +31 -3
- package/dist/http/helpers/autopilot-slice-utils.d.ts +10 -0
- package/dist/http/helpers/autopilot-slice-utils.js +158 -54
- package/dist/http/helpers/hash-utils.d.ts +1 -1
- package/dist/http/helpers/hash-utils.js +1 -1
- package/dist/http/helpers/humanize-slice-failure.d.ts +35 -0
- package/dist/http/helpers/humanize-slice-failure.js +137 -0
- package/dist/http/helpers/mission-control.d.ts +1 -0
- package/dist/http/helpers/mission-control.js +73 -7
- package/dist/http/helpers/queue-constants.d.ts +37 -0
- package/dist/http/helpers/queue-constants.js +34 -0
- package/dist/http/helpers/slice-experience-v2.js +2 -5
- package/dist/http/helpers/slice-run-projections.js +2 -5
- package/dist/http/helpers/workspace-scope.js +4 -3
- package/dist/http/index.js +166 -63
- package/dist/http/routes/chat.js +1 -21
- package/dist/http/routes/live-misc.js +9 -2
- package/dist/http/routes/live-snapshot.js +14 -27
- package/dist/http/routes/mission-control-actions.js +7 -18
- package/dist/http/routes/mission-control-read.d.ts +1 -0
- package/dist/http/routes/mission-control-read.js +14 -56
- package/dist/index.d.ts +8 -1
- package/dist/index.js +21 -1
- package/dist/lib/type-coercion.d.ts +10 -0
- package/dist/lib/type-coercion.js +82 -0
- package/dist/mcp-http-handler.js +14 -2
- package/dist/openclaw.plugin.json +1 -1
- package/dist/services/experiment-randomization.js +9 -2
- package/dist/tools/core-tools.d.ts +27 -0
- package/dist/tools/core-tools.js +89 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +3 -2
- package/dashboard/dist/assets/77gGFBt6.js.br +0 -0
- package/dashboard/dist/assets/77gGFBt6.js.gz +0 -0
- package/dashboard/dist/assets/BBpTN_SR.js +0 -1
- package/dashboard/dist/assets/BBpTN_SR.js.br +0 -0
- package/dashboard/dist/assets/BBpTN_SR.js.gz +0 -0
- package/dashboard/dist/assets/BJgZIVUQ.js +0 -53
- package/dashboard/dist/assets/BJgZIVUQ.js.br +0 -0
- package/dashboard/dist/assets/BJgZIVUQ.js.gz +0 -0
- package/dashboard/dist/assets/BTAEErUY.js +0 -1
- package/dashboard/dist/assets/BTAEErUY.js.br +0 -0
- package/dashboard/dist/assets/BTAEErUY.js.gz +0 -0
- package/dashboard/dist/assets/BVShoyjA.js +0 -1
- package/dashboard/dist/assets/BVShoyjA.js.br +0 -0
- package/dashboard/dist/assets/BVShoyjA.js.gz +0 -0
- package/dashboard/dist/assets/BgcAY5rE.js +0 -1
- package/dashboard/dist/assets/BgcAY5rE.js.br +0 -0
- package/dashboard/dist/assets/BgcAY5rE.js.gz +0 -0
- package/dashboard/dist/assets/C-KIc3Wc.js +0 -1
- package/dashboard/dist/assets/C-KIc3Wc.js.br +0 -0
- package/dashboard/dist/assets/C-KIc3Wc.js.gz +0 -0
- package/dashboard/dist/assets/C-PAoJF-.js +0 -1
- package/dashboard/dist/assets/C-PAoJF-.js.br +0 -0
- package/dashboard/dist/assets/C-PAoJF-.js.gz +0 -0
- package/dashboard/dist/assets/C0nA-iUG.js +0 -1
- package/dashboard/dist/assets/C0nA-iUG.js.br +0 -0
- package/dashboard/dist/assets/C0nA-iUG.js.gz +0 -0
- package/dashboard/dist/assets/C6GO-FKy.js +0 -1
- package/dashboard/dist/assets/C6GO-FKy.js.br +0 -0
- package/dashboard/dist/assets/C6GO-FKy.js.gz +0 -0
- package/dashboard/dist/assets/CFwPph5U.js +0 -1
- package/dashboard/dist/assets/CFwPph5U.js.br +0 -0
- package/dashboard/dist/assets/CFwPph5U.js.gz +0 -0
- package/dashboard/dist/assets/CL_wXqR7.js +0 -1
- package/dashboard/dist/assets/CL_wXqR7.js.br +0 -0
- package/dashboard/dist/assets/CL_wXqR7.js.gz +0 -0
- package/dashboard/dist/assets/CPjsbbgZ.js +0 -212
- package/dashboard/dist/assets/CPjsbbgZ.js.br +0 -0
- package/dashboard/dist/assets/CPjsbbgZ.js.gz +0 -0
- package/dashboard/dist/assets/CSr2ZnTV.js +0 -1
- package/dashboard/dist/assets/CSr2ZnTV.js.br +0 -0
- package/dashboard/dist/assets/CSr2ZnTV.js.gz +0 -0
- package/dashboard/dist/assets/CgQDT6yL.js +0 -1
- package/dashboard/dist/assets/CgQDT6yL.js.br +0 -0
- package/dashboard/dist/assets/CgQDT6yL.js.gz +0 -0
- package/dashboard/dist/assets/CnitK1MX.js.br +0 -0
- package/dashboard/dist/assets/CnitK1MX.js.gz +0 -0
- package/dashboard/dist/assets/CxQ08qFN.js +0 -9
- package/dashboard/dist/assets/CxQ08qFN.js.br +0 -0
- package/dashboard/dist/assets/CxQ08qFN.js.gz +0 -0
- package/dashboard/dist/assets/D7DHFX0D.js +0 -1
- package/dashboard/dist/assets/D7DHFX0D.js.br +0 -0
- package/dashboard/dist/assets/D7DHFX0D.js.gz +0 -0
- package/dashboard/dist/assets/DEip7uko.js +0 -1
- package/dashboard/dist/assets/DEip7uko.js.br +0 -0
- package/dashboard/dist/assets/DEip7uko.js.gz +0 -0
- package/dashboard/dist/assets/DHUSLc01.css +0 -1
- package/dashboard/dist/assets/DHUSLc01.css.br +0 -0
- package/dashboard/dist/assets/DHUSLc01.css.gz +0 -0
- package/dashboard/dist/assets/DOFL9l8s.js +0 -1
- package/dashboard/dist/assets/DOFL9l8s.js.br +0 -0
- package/dashboard/dist/assets/DOFL9l8s.js.gz +0 -0
- package/dashboard/dist/assets/DpuQm1oF.js.br +0 -0
- package/dashboard/dist/assets/DpuQm1oF.js.gz +0 -0
- package/dashboard/dist/assets/DxKG5zy8.js.br +0 -0
- package/dashboard/dist/assets/DxKG5zy8.js.gz +0 -0
- package/dashboard/dist/assets/cNrhgGc1.js +0 -8
- package/dashboard/dist/assets/cNrhgGc1.js.br +0 -0
- package/dashboard/dist/assets/cNrhgGc1.js.gz +0 -0
- package/dashboard/dist/assets/tcEHYcbW.js.br +0 -0
- package/dashboard/dist/assets/tcEHYcbW.js.gz +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { resolveWorkspaceScope as resolveCanonicalWorkspaceScope } from "../helpers/workspace-scope.js";
|
|
3
|
+
import { asRecord, asString, asStringArray } from "../../lib/type-coercion.js";
|
|
3
4
|
import { buildDispatchGatewayEnvelope } from "./dispatch-gateway-envelope.js";
|
|
4
5
|
const PLAY_QUEUE_LOOKUP_TIMEOUT_MS = (() => {
|
|
5
6
|
const raw = process.env.ORGX_PLAY_QUEUE_LOOKUP_TIMEOUT_MS;
|
|
@@ -194,24 +195,7 @@ function shouldResetTaskStatus(status, states) {
|
|
|
194
195
|
}
|
|
195
196
|
return false;
|
|
196
197
|
}
|
|
197
|
-
|
|
198
|
-
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
199
|
-
return null;
|
|
200
|
-
return value;
|
|
201
|
-
}
|
|
202
|
-
function asString(value) {
|
|
203
|
-
if (typeof value !== "string")
|
|
204
|
-
return null;
|
|
205
|
-
const trimmed = value.trim();
|
|
206
|
-
return trimmed.length > 0 ? trimmed : null;
|
|
207
|
-
}
|
|
208
|
-
function asStringArray(value) {
|
|
209
|
-
if (!Array.isArray(value))
|
|
210
|
-
return [];
|
|
211
|
-
return value
|
|
212
|
-
.map((entry) => asString(entry))
|
|
213
|
-
.filter((entry) => Boolean(entry));
|
|
214
|
-
}
|
|
198
|
+
// asRecord, asString, asStringArray imported from ../../lib/type-coercion.js
|
|
215
199
|
function parseCycleGraphNodes(graph) {
|
|
216
200
|
const root = asRecord(graph);
|
|
217
201
|
const rawNodes = Array.isArray(root?.nodes) ? root.nodes : [];
|
|
@@ -456,6 +440,7 @@ export function registerMissionControlActionsRoutes(router, deps) {
|
|
|
456
440
|
ignoreSpawnGuardRateLimit: ignoreSpawnGuardRateLimit === true,
|
|
457
441
|
scope,
|
|
458
442
|
});
|
|
443
|
+
deps.clearNextUpQueueCache(initiativeId);
|
|
459
444
|
const dispatchId = randomUUID();
|
|
460
445
|
const playDispatchEnvelope = (dispatchMode) => buildDispatchGatewayEnvelope({
|
|
461
446
|
dispatchId,
|
|
@@ -1593,6 +1578,7 @@ export function registerMissionControlActionsRoutes(router, deps) {
|
|
|
1593
1578
|
ignoreSpawnGuardRateLimit: ignoreSpawnGuardRateLimit === true,
|
|
1594
1579
|
scope: startScope,
|
|
1595
1580
|
});
|
|
1581
|
+
deps.clearNextUpQueueCache(initiativeId);
|
|
1596
1582
|
const dispatchEnvelope = buildDispatchGatewayEnvelope({
|
|
1597
1583
|
dispatchMode: "server",
|
|
1598
1584
|
route: "mission-control.auto-continue.start",
|
|
@@ -1643,6 +1629,7 @@ export function registerMissionControlActionsRoutes(router, deps) {
|
|
|
1643
1629
|
// best effort
|
|
1644
1630
|
}
|
|
1645
1631
|
}
|
|
1632
|
+
deps.clearNextUpQueueCache(initiativeId);
|
|
1646
1633
|
deps.sendJson(res, 200, { ok: true, run });
|
|
1647
1634
|
}
|
|
1648
1635
|
catch (err) {
|
|
@@ -1664,10 +1651,12 @@ export function registerMissionControlActionsRoutes(router, deps) {
|
|
|
1664
1651
|
return;
|
|
1665
1652
|
}
|
|
1666
1653
|
await deps.tickAutoContinueRun(run);
|
|
1654
|
+
deps.clearNextUpQueueCache(initiativeId);
|
|
1667
1655
|
deps.sendJson(res, 200, { ok: true, initiativeId, run });
|
|
1668
1656
|
return;
|
|
1669
1657
|
}
|
|
1670
1658
|
await deps.tickAllAutoContinue();
|
|
1659
|
+
deps.clearNextUpQueueCache(null);
|
|
1671
1660
|
deps.sendJson(res, 200, { ok: true });
|
|
1672
1661
|
}
|
|
1673
1662
|
catch (err) {
|
|
@@ -1,34 +1,7 @@
|
|
|
1
1
|
import { listBuiltInSentinels } from "../helpers/sentinel-catalog.js";
|
|
2
2
|
import { resolveWorkspaceScope, workspaceScopeFromHeaders, } from "../helpers/workspace-scope.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
return null;
|
|
6
|
-
return value;
|
|
7
|
-
}
|
|
8
|
-
function asString(value) {
|
|
9
|
-
if (typeof value !== "string")
|
|
10
|
-
return null;
|
|
11
|
-
const trimmed = value.trim();
|
|
12
|
-
return trimmed.length > 0 ? trimmed : null;
|
|
13
|
-
}
|
|
14
|
-
function asArray(value) {
|
|
15
|
-
if (Array.isArray(value))
|
|
16
|
-
return value;
|
|
17
|
-
if (typeof value !== "string")
|
|
18
|
-
return [];
|
|
19
|
-
const trimmed = value.trim();
|
|
20
|
-
try {
|
|
21
|
-
const parsed = JSON.parse(trimmed);
|
|
22
|
-
if (Array.isArray(parsed))
|
|
23
|
-
return parsed;
|
|
24
|
-
if (parsed && typeof parsed === "object")
|
|
25
|
-
return [parsed];
|
|
26
|
-
return [];
|
|
27
|
-
}
|
|
28
|
-
catch {
|
|
29
|
-
return [];
|
|
30
|
-
}
|
|
31
|
-
}
|
|
3
|
+
import { asRecord, asString, asNumber, asArray, asStringArray, } from "../../lib/type-coercion.js";
|
|
4
|
+
// asRecord, asString, asArray, asNumber, asStringArray imported from ../../lib/type-coercion.js
|
|
32
5
|
function normalizeRunnerValue(value) {
|
|
33
6
|
const raw = asString(value);
|
|
34
7
|
if (!raw)
|
|
@@ -105,29 +78,7 @@ function mergeRunnerAgents(...groups) {
|
|
|
105
78
|
}
|
|
106
79
|
return output;
|
|
107
80
|
}
|
|
108
|
-
|
|
109
|
-
if (typeof value === "number" && Number.isFinite(value))
|
|
110
|
-
return value;
|
|
111
|
-
if (typeof value === "string" && value.trim().length > 0) {
|
|
112
|
-
const parsed = Number(value);
|
|
113
|
-
if (Number.isFinite(parsed))
|
|
114
|
-
return parsed;
|
|
115
|
-
}
|
|
116
|
-
return null;
|
|
117
|
-
}
|
|
118
|
-
function asStringArray(value) {
|
|
119
|
-
const entries = asArray(value);
|
|
120
|
-
if (entries.length === 0)
|
|
121
|
-
return [];
|
|
122
|
-
const values = [];
|
|
123
|
-
for (const entry of entries) {
|
|
124
|
-
const normalized = asString(entry);
|
|
125
|
-
if (!normalized)
|
|
126
|
-
continue;
|
|
127
|
-
values.push(normalized);
|
|
128
|
-
}
|
|
129
|
-
return dedupeStrings(values);
|
|
130
|
-
}
|
|
81
|
+
// asNumber, asStringArray imported from ../../lib/type-coercion.js
|
|
131
82
|
function isCanonicalAllScopeMismatch(canonicalRecord, useAllScope) {
|
|
132
83
|
if (!useAllScope)
|
|
133
84
|
return false;
|
|
@@ -838,11 +789,18 @@ export function registerMissionControlReadRoutes(router, deps) {
|
|
|
838
789
|
const sendRouteException = (res, location, err) => {
|
|
839
790
|
sendRouteError(res, 500, location, deps.safeErrorMessage(err));
|
|
840
791
|
};
|
|
841
|
-
async function renderAutoContinueStatus(query, res) {
|
|
792
|
+
async function renderAutoContinueStatus(query, res, headerScope) {
|
|
793
|
+
const workspaceScope = resolveWorkspaceScope(query, headerScope, {
|
|
794
|
+
allowProjectScope: false,
|
|
795
|
+
});
|
|
796
|
+
if (workspaceScope.error) {
|
|
797
|
+
sendRouteError(res, 400, "mission-control.read.auto-continue.status.validation", workspaceScope.error);
|
|
798
|
+
return;
|
|
799
|
+
}
|
|
842
800
|
const initiativeId = query.get("initiative_id") ?? query.get("initiativeId") ?? "";
|
|
843
801
|
const id = initiativeId.trim();
|
|
844
802
|
if (!id) {
|
|
845
|
-
sendRouteError(res, 400, "mission-control.read.auto-continue.status.validation", "
|
|
803
|
+
sendRouteError(res, 400, "mission-control.read.auto-continue.status.validation", "initiativeId is required");
|
|
846
804
|
return;
|
|
847
805
|
}
|
|
848
806
|
const run = deps.autoContinueRuns.get(id) ?? null;
|
|
@@ -1743,8 +1701,8 @@ export function registerMissionControlReadRoutes(router, deps) {
|
|
|
1743
1701
|
items,
|
|
1744
1702
|
});
|
|
1745
1703
|
}
|
|
1746
|
-
router.add("GET", "mission-control/auto-continue/status", async ({ query, res }) => renderAutoContinueStatus(query, res), "Get auto-continue status for an initiative");
|
|
1747
|
-
router.add("HEAD", "mission-control/auto-continue/status", async ({ query, res }) => renderAutoContinueStatus(query, res), "Get auto-continue status for an initiative (HEAD)");
|
|
1704
|
+
router.add("GET", "mission-control/auto-continue/status", async ({ query, res, req }) => renderAutoContinueStatus(query, res, workspaceScopeFromHeaders(req?.headers)), "Get auto-continue status for an initiative");
|
|
1705
|
+
router.add("HEAD", "mission-control/auto-continue/status", async ({ query, res, req }) => renderAutoContinueStatus(query, res, workspaceScopeFromHeaders(req?.headers)), "Get auto-continue status for an initiative (HEAD)");
|
|
1748
1706
|
router.add("GET", "mission-control/graph", async ({ query, res }) => renderMissionControlGraph(query, res), "Get mission-control dependency graph");
|
|
1749
1707
|
router.add("HEAD", "mission-control/graph", async ({ query, res }) => renderMissionControlGraph(query, res), "Get mission-control dependency graph (HEAD)");
|
|
1750
1708
|
router.add("GET", "mission-control/next-up", async ({ query, res, req }) => renderNextUpQueue(query, res, workspaceScopeFromHeaders(req?.headers)), "Get next-up queue");
|
package/dist/index.d.ts
CHANGED
|
@@ -48,7 +48,14 @@ export interface PluginAPI {
|
|
|
48
48
|
}) => void, options?: {
|
|
49
49
|
commands?: string[];
|
|
50
50
|
}) => void;
|
|
51
|
-
|
|
51
|
+
registerHttpRoute?: (route: {
|
|
52
|
+
path: string;
|
|
53
|
+
auth: "gateway" | "plugin";
|
|
54
|
+
match?: "exact" | "prefix";
|
|
55
|
+
handler: unknown;
|
|
56
|
+
replaceExisting?: boolean;
|
|
57
|
+
}) => void;
|
|
58
|
+
registerHttpHandler?: (handler: unknown) => void;
|
|
52
59
|
}
|
|
53
60
|
export interface ToolResult {
|
|
54
61
|
content: Array<{
|
package/dist/index.js
CHANGED
|
@@ -1430,7 +1430,27 @@ export default function register(api) {
|
|
|
1430
1430
|
return true;
|
|
1431
1431
|
return await httpHandler(req, res);
|
|
1432
1432
|
};
|
|
1433
|
-
api.
|
|
1433
|
+
if (typeof api.registerHttpRoute === "function") {
|
|
1434
|
+
api.registerHttpRoute({
|
|
1435
|
+
path: "/orgx",
|
|
1436
|
+
auth: "plugin",
|
|
1437
|
+
match: "prefix",
|
|
1438
|
+
handler: compositeHttpHandler,
|
|
1439
|
+
});
|
|
1440
|
+
api.registerHttpRoute({
|
|
1441
|
+
path: "/workspace-hub",
|
|
1442
|
+
auth: "plugin",
|
|
1443
|
+
match: "prefix",
|
|
1444
|
+
handler: compositeHttpHandler,
|
|
1445
|
+
});
|
|
1446
|
+
}
|
|
1447
|
+
else if (typeof api.registerHttpHandler === "function") {
|
|
1448
|
+
// Backward compatibility for OpenClaw builds before route-based plugin HTTP registration.
|
|
1449
|
+
api.registerHttpHandler(compositeHttpHandler);
|
|
1450
|
+
}
|
|
1451
|
+
else {
|
|
1452
|
+
throw new Error("OpenClaw plugin API does not expose an HTTP registration method.");
|
|
1453
|
+
}
|
|
1434
1454
|
api.log?.info?.("[orgx] Plugin registered", {
|
|
1435
1455
|
baseUrl: config.baseUrl,
|
|
1436
1456
|
hasApiKey: !!config.apiKey,
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Safely cast unknown to a Record, or null if not a plain object. */
|
|
2
|
+
export declare function asRecord(value: unknown): Record<string, unknown> | null;
|
|
3
|
+
/** Safely cast unknown to a trimmed non-empty string, or null. */
|
|
4
|
+
export declare function asString(value: unknown): string | null;
|
|
5
|
+
/** Safely cast unknown to a finite number, or null. */
|
|
6
|
+
export declare function asNumber(value: unknown): number | null;
|
|
7
|
+
/** Safely cast unknown to an array. Attempts JSON parse for string values. */
|
|
8
|
+
export declare function asArray(value: unknown): unknown[];
|
|
9
|
+
/** Extract a deduplicated string array from unknown. */
|
|
10
|
+
export declare function asStringArray(value: unknown): string[];
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Shared type-coercion helpers for safe parsing of unknown API data.
|
|
3
|
+
// Previously duplicated across 20+ files.
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
/** Safely cast unknown to a Record, or null if not a plain object. */
|
|
6
|
+
export function asRecord(value) {
|
|
7
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
8
|
+
return null;
|
|
9
|
+
const proto = Object.getPrototypeOf(value);
|
|
10
|
+
if (proto !== Object.prototype && proto !== null)
|
|
11
|
+
return null;
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
/** Safely cast unknown to a trimmed non-empty string, or null. */
|
|
15
|
+
export function asString(value) {
|
|
16
|
+
if (typeof value !== "string")
|
|
17
|
+
return null;
|
|
18
|
+
const trimmed = value.trim();
|
|
19
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
20
|
+
}
|
|
21
|
+
/** Safely cast unknown to a finite number, or null. */
|
|
22
|
+
export function asNumber(value) {
|
|
23
|
+
if (typeof value === "number" && Number.isFinite(value))
|
|
24
|
+
return value;
|
|
25
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
26
|
+
const parsed = Number(value);
|
|
27
|
+
if (Number.isFinite(parsed))
|
|
28
|
+
return parsed;
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
/** Safely cast unknown to an array. Attempts JSON parse for string values. */
|
|
33
|
+
export function asArray(value) {
|
|
34
|
+
if (Array.isArray(value))
|
|
35
|
+
return value;
|
|
36
|
+
if (asRecord(value))
|
|
37
|
+
return [value];
|
|
38
|
+
if (typeof value !== "string")
|
|
39
|
+
return [];
|
|
40
|
+
const trimmed = value.trim();
|
|
41
|
+
try {
|
|
42
|
+
const parsed = JSON.parse(trimmed);
|
|
43
|
+
if (Array.isArray(parsed))
|
|
44
|
+
return parsed;
|
|
45
|
+
if (asRecord(parsed))
|
|
46
|
+
return [parsed];
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/** Extract a deduplicated string array from unknown. */
|
|
54
|
+
export function asStringArray(value) {
|
|
55
|
+
const entries = asArray(value);
|
|
56
|
+
if (entries.length === 0) {
|
|
57
|
+
const scalar = asString(value);
|
|
58
|
+
if (!scalar)
|
|
59
|
+
return [];
|
|
60
|
+
const fallbackEntries = scalar.includes(",") ? scalar.split(",") : [scalar];
|
|
61
|
+
const seenFallback = new Set();
|
|
62
|
+
const fallbackValues = [];
|
|
63
|
+
for (const entry of fallbackEntries) {
|
|
64
|
+
const normalized = asString(entry);
|
|
65
|
+
if (!normalized || seenFallback.has(normalized))
|
|
66
|
+
continue;
|
|
67
|
+
seenFallback.add(normalized);
|
|
68
|
+
fallbackValues.push(normalized);
|
|
69
|
+
}
|
|
70
|
+
return fallbackValues;
|
|
71
|
+
}
|
|
72
|
+
const seen = new Set();
|
|
73
|
+
const values = [];
|
|
74
|
+
for (const entry of entries) {
|
|
75
|
+
const normalized = asString(entry);
|
|
76
|
+
if (!normalized || seen.has(normalized))
|
|
77
|
+
continue;
|
|
78
|
+
seen.add(normalized);
|
|
79
|
+
values.push(normalized);
|
|
80
|
+
}
|
|
81
|
+
return values;
|
|
82
|
+
}
|
package/dist/mcp-http-handler.js
CHANGED
|
@@ -136,6 +136,13 @@ async function readRequestBodyBuffer(req) {
|
|
|
136
136
|
return Buffer.from("", "utf8");
|
|
137
137
|
return await new Promise((resolve) => {
|
|
138
138
|
const chunks = [];
|
|
139
|
+
let settled = false;
|
|
140
|
+
const settle = () => {
|
|
141
|
+
if (settled)
|
|
142
|
+
return;
|
|
143
|
+
settled = true;
|
|
144
|
+
resolve(Buffer.concat(chunks));
|
|
145
|
+
};
|
|
139
146
|
const onData = (chunk) => {
|
|
140
147
|
if (typeof chunk === "string") {
|
|
141
148
|
chunks.push(Buffer.from(chunk, "utf8"));
|
|
@@ -147,9 +154,14 @@ async function readRequestBodyBuffer(req) {
|
|
|
147
154
|
chunks.push(Buffer.from(chunk));
|
|
148
155
|
}
|
|
149
156
|
};
|
|
150
|
-
const onEnd = () =>
|
|
151
|
-
const onError = () =>
|
|
157
|
+
const onEnd = () => settle();
|
|
158
|
+
const onError = () => settle();
|
|
152
159
|
req.on?.("data", onData);
|
|
160
|
+
if (typeof req.once === "function") {
|
|
161
|
+
req.once("end", onEnd);
|
|
162
|
+
req.once("error", onError);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
153
165
|
req.on?.("end", onEnd);
|
|
154
166
|
req.on?.("error", onError);
|
|
155
167
|
});
|
|
@@ -23,8 +23,13 @@ function normalizeArms(arms) {
|
|
|
23
23
|
if (!Array.isArray(arms) || arms.length === 0) {
|
|
24
24
|
throw new Error("arms must include at least one entry");
|
|
25
25
|
}
|
|
26
|
+
const seenIds = new Set();
|
|
26
27
|
const sanitized = arms.map((arm, index) => {
|
|
27
28
|
const id = sanitizeIdentifier(arm?.id, `arms[${index}].id`);
|
|
29
|
+
if (seenIds.has(id)) {
|
|
30
|
+
throw new Error(`arms[${index}].id must be unique`);
|
|
31
|
+
}
|
|
32
|
+
seenIds.add(id);
|
|
28
33
|
const weight = Number.isFinite(arm?.weight) ? Number(arm.weight) : Number.NaN;
|
|
29
34
|
if (!Number.isFinite(weight) || weight <= 0) {
|
|
30
35
|
throw new Error(`arms[${index}].weight must be > 0`);
|
|
@@ -58,6 +63,8 @@ function sanitizeIdentifier(value, field) {
|
|
|
58
63
|
return trimmed;
|
|
59
64
|
}
|
|
60
65
|
function bucketFromHash(hash) {
|
|
61
|
-
|
|
62
|
-
|
|
66
|
+
// Keep only 53 high-order bits from the 56-bit hex prefix.
|
|
67
|
+
const first56Bits = parseInt(hash.slice(0, 14), 16);
|
|
68
|
+
const first53Bits = Math.floor(first56Bits / 8);
|
|
69
|
+
return first53Bits / (MAX_UINT53 + 1);
|
|
63
70
|
}
|
|
@@ -68,5 +68,32 @@ export interface RegisterCoreToolsDeps {
|
|
|
68
68
|
auditId?: string;
|
|
69
69
|
}) => import("../skill-pack-state.js").SkillPackState;
|
|
70
70
|
randomUUID?: () => string;
|
|
71
|
+
sessionStore?: {
|
|
72
|
+
workstreamSessionStore: Map<string, {
|
|
73
|
+
sessionId: string;
|
|
74
|
+
workstreamId: string;
|
|
75
|
+
initiativeId: string;
|
|
76
|
+
sourceClient: string;
|
|
77
|
+
capturedAt: string;
|
|
78
|
+
fromRunId: string;
|
|
79
|
+
}>;
|
|
80
|
+
getWorkstreamSession: (workstreamId: string) => {
|
|
81
|
+
sessionId: string;
|
|
82
|
+
workstreamId: string;
|
|
83
|
+
initiativeId: string;
|
|
84
|
+
sourceClient: string;
|
|
85
|
+
capturedAt: string;
|
|
86
|
+
fromRunId: string;
|
|
87
|
+
} | null;
|
|
88
|
+
setWorkstreamSession: (workstreamId: string, entry: {
|
|
89
|
+
sessionId: string;
|
|
90
|
+
workstreamId: string;
|
|
91
|
+
initiativeId: string;
|
|
92
|
+
sourceClient: string;
|
|
93
|
+
capturedAt: string;
|
|
94
|
+
fromRunId: string;
|
|
95
|
+
}) => void;
|
|
96
|
+
clearWorkstreamSession: (initiativeId: string) => void;
|
|
97
|
+
};
|
|
71
98
|
}
|
|
72
99
|
export declare function registerCoreTools(deps: RegisterCoreToolsDeps): Map<string, RegisteredTool>;
|
package/dist/tools/core-tools.js
CHANGED
|
@@ -2266,5 +2266,94 @@ export function registerCoreTools(deps) {
|
|
|
2266
2266
|
}
|
|
2267
2267
|
},
|
|
2268
2268
|
}, { optional: true });
|
|
2269
|
+
// --- orgx_agent_sessions ---
|
|
2270
|
+
registerMcpTool({
|
|
2271
|
+
name: "orgx_agent_sessions",
|
|
2272
|
+
description: "List active CLI session IDs stored for workstreams. Used for session resume support.",
|
|
2273
|
+
parameters: {
|
|
2274
|
+
type: "object",
|
|
2275
|
+
properties: {
|
|
2276
|
+
initiativeId: {
|
|
2277
|
+
type: "string",
|
|
2278
|
+
description: "Optional initiative ID filter.",
|
|
2279
|
+
},
|
|
2280
|
+
},
|
|
2281
|
+
additionalProperties: false,
|
|
2282
|
+
},
|
|
2283
|
+
async execute(_callId, params = {}) {
|
|
2284
|
+
const store = deps.sessionStore;
|
|
2285
|
+
if (!store) {
|
|
2286
|
+
return text("Session store not available.");
|
|
2287
|
+
}
|
|
2288
|
+
const entries = [];
|
|
2289
|
+
for (const [, entry] of store.workstreamSessionStore.entries()) {
|
|
2290
|
+
if (params.initiativeId && entry.initiativeId !== params.initiativeId)
|
|
2291
|
+
continue;
|
|
2292
|
+
entries.push({ ...entry });
|
|
2293
|
+
}
|
|
2294
|
+
return json("Agent sessions:", {
|
|
2295
|
+
count: entries.length,
|
|
2296
|
+
sessions: entries,
|
|
2297
|
+
});
|
|
2298
|
+
},
|
|
2299
|
+
}, { optional: true });
|
|
2300
|
+
// --- orgx_resume_agent_session ---
|
|
2301
|
+
registerMcpTool({
|
|
2302
|
+
name: "orgx_resume_agent_session",
|
|
2303
|
+
description: "Store or update a CLI session ID for a workstream so the next slice resumes it.",
|
|
2304
|
+
parameters: {
|
|
2305
|
+
type: "object",
|
|
2306
|
+
properties: {
|
|
2307
|
+
workstreamId: { type: "string", description: "Workstream UUID" },
|
|
2308
|
+
sessionId: { type: "string", description: "CLI session UUID to resume" },
|
|
2309
|
+
initiativeId: { type: "string", description: "Initiative UUID" },
|
|
2310
|
+
sourceClient: { type: "string", description: "Source client (codex, claude-code)" },
|
|
2311
|
+
},
|
|
2312
|
+
required: ["workstreamId", "sessionId", "initiativeId"],
|
|
2313
|
+
additionalProperties: false,
|
|
2314
|
+
},
|
|
2315
|
+
async execute(_callId, params = { workstreamId: "", sessionId: "", initiativeId: "" }) {
|
|
2316
|
+
const store = deps.sessionStore;
|
|
2317
|
+
if (!store) {
|
|
2318
|
+
return text("Session store not available.");
|
|
2319
|
+
}
|
|
2320
|
+
if (!params.workstreamId || !params.sessionId || !params.initiativeId) {
|
|
2321
|
+
return text("Missing required parameters: workstreamId, sessionId, initiativeId.");
|
|
2322
|
+
}
|
|
2323
|
+
store.setWorkstreamSession(params.workstreamId, {
|
|
2324
|
+
sessionId: params.sessionId,
|
|
2325
|
+
workstreamId: params.workstreamId,
|
|
2326
|
+
initiativeId: params.initiativeId,
|
|
2327
|
+
sourceClient: params.sourceClient ?? "unknown",
|
|
2328
|
+
capturedAt: new Date().toISOString(),
|
|
2329
|
+
fromRunId: "manual",
|
|
2330
|
+
});
|
|
2331
|
+
return text(`Session ${params.sessionId} stored for workstream ${params.workstreamId}.`);
|
|
2332
|
+
},
|
|
2333
|
+
}, { optional: true });
|
|
2334
|
+
// --- orgx_clear_agent_session ---
|
|
2335
|
+
registerMcpTool({
|
|
2336
|
+
name: "orgx_clear_agent_session",
|
|
2337
|
+
description: "Clear stored CLI session IDs for an initiative (forces fresh sessions on next dispatch).",
|
|
2338
|
+
parameters: {
|
|
2339
|
+
type: "object",
|
|
2340
|
+
properties: {
|
|
2341
|
+
initiativeId: { type: "string", description: "Initiative UUID" },
|
|
2342
|
+
},
|
|
2343
|
+
required: ["initiativeId"],
|
|
2344
|
+
additionalProperties: false,
|
|
2345
|
+
},
|
|
2346
|
+
async execute(_callId, params = { initiativeId: "" }) {
|
|
2347
|
+
const store = deps.sessionStore;
|
|
2348
|
+
if (!store) {
|
|
2349
|
+
return text("Session store not available.");
|
|
2350
|
+
}
|
|
2351
|
+
if (!params.initiativeId) {
|
|
2352
|
+
return text("Missing required parameter: initiativeId.");
|
|
2353
|
+
}
|
|
2354
|
+
store.clearWorkstreamSession(params.initiativeId);
|
|
2355
|
+
return text(`Sessions cleared for initiative ${params.initiativeId}.`);
|
|
2356
|
+
},
|
|
2357
|
+
}, { optional: true });
|
|
2269
2358
|
return mcpToolRegistry;
|
|
2270
2359
|
}
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@useorgx/openclaw-plugin",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.15",
|
|
4
4
|
"description": "OrgX plugin for OpenClaw — agent orchestration, quality gates, model routing, and live dashboard",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
"verify:iwmt-cascade": "npm run build:core && node ./scripts/verify-iwmt-cascade-e2e.mjs",
|
|
53
53
|
"verify:live-ui:p0": "node ./scripts/agent-browser-live-ui-p0-audit.mjs",
|
|
54
54
|
"verify:conduit-mcp": "node ./scripts/verify-conduit-mcp.mjs",
|
|
55
|
+
"verify:repo-hygiene": "node ./scripts/verify-repo-hygiene.mjs",
|
|
55
56
|
"dev:main": "node ./scripts/dev-main-sync.mjs",
|
|
56
57
|
"e2e:auto-continue": "node ./scripts/e2e-auto-continue.mjs",
|
|
57
58
|
"e2e:agent-suite": "npm run build:core && node ./scripts/e2e-agent-suite-kickoff-3x.mjs",
|
|
@@ -94,7 +95,7 @@
|
|
|
94
95
|
},
|
|
95
96
|
"repository": {
|
|
96
97
|
"type": "git",
|
|
97
|
-
"url": "https://github.com/useorgx/openclaw-plugin.git"
|
|
98
|
+
"url": "git+https://github.com/useorgx/openclaw-plugin.git"
|
|
98
99
|
},
|
|
99
100
|
"homepage": "https://useorgx.com",
|
|
100
101
|
"bugs": {
|
|
Binary file
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as l,a as c}from"./cNrhgGc1.js";import{b as g}from"./CPjsbbgZ.js";function f({authToken:s=null,embedMode:o=!1,enabled:n=!0}={}){var a;const i=l.useMemo(()=>["usage-control-plane",{authToken:s,embedMode:o}],[s,o]),e=c({queryKey:i,enabled:n,queryFn:async()=>{const t=await fetch("/orgx/api/usage/control-plane/summary",{headers:g({authToken:s,embedMode:o})}),r=await t.json().catch(()=>null);if(!t.ok){const u=(r&&typeof r=="object"&&"error"in r&&typeof r.error=="string"?r.error:null)??(r&&typeof r=="object"&&"message"in r&&typeof r.message=="string"?r.message:null)??`Failed to load usage summary (${t.status})`;throw new Error(u)}if(!r||typeof r!="object"||!("generatedAt"in r))throw new Error("Usage summary response is missing required fields.");return r},refetchInterval:6e4});return{summary:e.data??null,isLoading:e.isLoading,isFetching:e.isFetching,error:((a=e.error)==null?void 0:a.message)??null,refetch:e.refetch}}export{f as u};
|
|
Binary file
|
|
Binary file
|