@useorgx/openclaw-plugin 0.4.8 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -0
- package/dashboard/dist/assets/BJgZIVUQ.js +53 -0
- package/dashboard/dist/assets/BJgZIVUQ.js.br +0 -0
- package/dashboard/dist/assets/BJgZIVUQ.js.gz +0 -0
- package/dashboard/dist/assets/BXWDRGm-.js +1 -0
- package/dashboard/dist/assets/BXWDRGm-.js.br +0 -0
- package/dashboard/dist/assets/BXWDRGm-.js.gz +0 -0
- package/dashboard/dist/assets/BgOYB78t.js +4 -0
- package/dashboard/dist/assets/BgOYB78t.js.br +0 -0
- package/dashboard/dist/assets/BgOYB78t.js.gz +0 -0
- package/dashboard/dist/assets/C-KIc3Wc.js.br +0 -0
- package/dashboard/dist/assets/C-KIc3Wc.js.gz +0 -0
- package/dashboard/dist/assets/CE38zU4U.js +1 -0
- package/dashboard/dist/assets/CE38zU4U.js.br +0 -0
- package/dashboard/dist/assets/CE38zU4U.js.gz +0 -0
- package/dashboard/dist/assets/CFGKRAzG.js +1 -0
- package/dashboard/dist/assets/CFGKRAzG.js.br +0 -0
- package/dashboard/dist/assets/CFGKRAzG.js.gz +0 -0
- package/dashboard/dist/assets/CGGR2GZh.js +1 -0
- package/dashboard/dist/assets/CGGR2GZh.js.br +0 -0
- package/dashboard/dist/assets/CGGR2GZh.js.gz +0 -0
- package/dashboard/dist/assets/CL_wXqR7.js +1 -0
- package/dashboard/dist/assets/CL_wXqR7.js.br +0 -0
- package/dashboard/dist/assets/CL_wXqR7.js.gz +0 -0
- package/dashboard/dist/assets/CPFiTmlw.js +8 -0
- package/dashboard/dist/assets/CPFiTmlw.js.br +0 -0
- package/dashboard/dist/assets/CPFiTmlw.js.gz +0 -0
- package/dashboard/dist/assets/CZZTvkQZ.js +1 -0
- package/dashboard/dist/assets/CZZTvkQZ.js.br +0 -0
- package/dashboard/dist/assets/CZZTvkQZ.js.gz +0 -0
- package/dashboard/dist/assets/{CpJsfbXo.js → CxQ08qFN.js} +2 -2
- package/dashboard/dist/assets/CxQ08qFN.js.br +0 -0
- package/dashboard/dist/assets/CxQ08qFN.js.gz +0 -0
- package/dashboard/dist/assets/D-bf6hEI.js +213 -0
- package/dashboard/dist/assets/D-bf6hEI.js.br +0 -0
- package/dashboard/dist/assets/D-bf6hEI.js.gz +0 -0
- package/dashboard/dist/assets/DG6y9wJI.js +2 -0
- package/dashboard/dist/assets/DG6y9wJI.js.br +0 -0
- package/dashboard/dist/assets/DG6y9wJI.js.gz +0 -0
- package/dashboard/dist/assets/DNxKz-GV.js +1 -0
- package/dashboard/dist/assets/DNxKz-GV.js.br +0 -0
- package/dashboard/dist/assets/DNxKz-GV.js.gz +0 -0
- package/dashboard/dist/assets/DW_rKUic.js +11 -0
- package/dashboard/dist/assets/DW_rKUic.js.br +0 -0
- package/dashboard/dist/assets/DW_rKUic.js.gz +0 -0
- package/dashboard/dist/assets/DbNoijHm.js +1 -0
- package/dashboard/dist/assets/DbNoijHm.js.br +0 -0
- package/dashboard/dist/assets/DbNoijHm.js.gz +0 -0
- package/dashboard/dist/assets/DjcdE6jC.js +2 -0
- package/dashboard/dist/assets/DjcdE6jC.js.br +0 -0
- package/dashboard/dist/assets/DjcdE6jC.js.gz +0 -0
- package/dashboard/dist/assets/FZYuCDnt.js +1 -0
- package/dashboard/dist/assets/FZYuCDnt.js.br +0 -0
- package/dashboard/dist/assets/FZYuCDnt.js.gz +0 -0
- package/dashboard/dist/assets/PAUiij_z.js +1 -0
- package/dashboard/dist/assets/PAUiij_z.js.br +0 -0
- package/dashboard/dist/assets/PAUiij_z.js.gz +0 -0
- package/dashboard/dist/assets/cNrhgGc1.js +8 -0
- package/dashboard/dist/assets/cNrhgGc1.js.br +0 -0
- package/dashboard/dist/assets/cNrhgGc1.js.gz +0 -0
- package/dashboard/dist/assets/h5biQs2I.css +1 -0
- package/dashboard/dist/assets/h5biQs2I.css.br +0 -0
- package/dashboard/dist/assets/h5biQs2I.css.gz +0 -0
- package/dashboard/dist/assets/ic2FaMnh.js +1 -0
- package/dashboard/dist/assets/ic2FaMnh.js.br +0 -0
- package/dashboard/dist/assets/ic2FaMnh.js.gz +0 -0
- package/dashboard/dist/assets/nByHNHoW.js +1 -0
- package/dashboard/dist/assets/nByHNHoW.js.br +0 -0
- package/dashboard/dist/assets/nByHNHoW.js.gz +0 -0
- package/dashboard/dist/assets/qm8xLgv-.css +1 -0
- package/dashboard/dist/assets/qm8xLgv-.css.br +0 -0
- package/dashboard/dist/assets/qm8xLgv-.css.gz +0 -0
- package/dashboard/dist/assets/tS9mbYZi.js +1 -0
- package/dashboard/dist/assets/tS9mbYZi.js.br +0 -0
- package/dashboard/dist/assets/tS9mbYZi.js.gz +0 -0
- package/dashboard/dist/brand/anthropic-mark.svg.br +0 -0
- package/dashboard/dist/brand/anthropic-mark.svg.gz +0 -0
- package/dashboard/dist/brand/openai-mark.svg.br +0 -0
- package/dashboard/dist/brand/openai-mark.svg.gz +0 -0
- package/dashboard/dist/brand/openclaw-mark.svg.br +0 -0
- package/dashboard/dist/brand/openclaw-mark.svg.gz +0 -0
- package/dashboard/dist/brand/xandy-orchestrator.png +0 -0
- package/dashboard/dist/index.html +7 -5
- package/dashboard/dist/index.html.br +0 -0
- package/dashboard/dist/index.html.gz +0 -0
- package/dist/activity-actor-fields.js +26 -4
- package/dist/activity-store.js +38 -26
- package/dist/agent-context-store.js +84 -42
- package/dist/agent-run-store.js +49 -28
- package/dist/agent-suite.d.ts +9 -0
- package/dist/agent-suite.js +150 -17
- package/dist/artifacts/artifact-domain-schemas.d.ts +66 -0
- package/dist/artifacts/artifact-domain-schemas.js +357 -0
- package/dist/artifacts/register-artifact.d.ts +4 -3
- package/dist/artifacts/register-artifact.js +170 -57
- package/dist/auth/flows.d.ts +47 -0
- package/dist/auth/flows.js +169 -0
- package/dist/auth-store.js +6 -26
- package/dist/byok-store.js +5 -19
- package/dist/chat-store.d.ts +157 -0
- package/dist/chat-store.js +586 -0
- package/dist/cli/orgx.d.ts +66 -0
- package/dist/cli/orgx.js +102 -0
- package/dist/config/refresh.d.ts +32 -0
- package/dist/config/refresh.js +55 -0
- package/dist/config/resolution.d.ts +37 -0
- package/dist/config/resolution.js +178 -0
- package/dist/contracts/client.d.ts +43 -3
- package/dist/contracts/client.js +159 -30
- package/dist/contracts/retro-schema.d.ts +81 -0
- package/dist/contracts/retro-schema.js +80 -0
- package/dist/contracts/shared-types.d.ts +306 -0
- package/dist/contracts/shared-types.js +179 -0
- package/dist/contracts/skill-pack-schema.d.ts +192 -0
- package/dist/contracts/skill-pack-schema.js +180 -0
- package/dist/contracts/types.d.ts +224 -132
- package/dist/contracts/types.js +5 -0
- package/dist/entities/auto-assignment.d.ts +36 -0
- package/dist/entities/auto-assignment.js +141 -0
- package/dist/entity-comment-store.js +5 -25
- package/dist/event-sanitization.d.ts +11 -0
- package/dist/event-sanitization.js +113 -0
- package/dist/fs-utils.js +13 -1
- package/dist/gateway-watchdog.d.ts +5 -0
- package/dist/gateway-watchdog.js +50 -0
- package/dist/hash-utils.d.ts +2 -0
- package/dist/hash-utils.js +12 -0
- package/dist/hooks/post-reporting-event.mjs +1 -5
- package/dist/http/helpers/activity-headline.d.ts +10 -0
- package/dist/http/helpers/activity-headline.js +73 -0
- package/dist/http/helpers/artifact-fallback.d.ts +13 -0
- package/dist/http/helpers/artifact-fallback.js +148 -0
- package/dist/http/helpers/auto-continue-engine.d.ts +486 -0
- package/dist/http/helpers/auto-continue-engine.js +3563 -0
- package/dist/http/helpers/autopilot-operations.d.ts +176 -0
- package/dist/http/helpers/autopilot-operations.js +554 -0
- package/dist/http/helpers/autopilot-runtime.d.ts +43 -0
- package/dist/http/helpers/autopilot-runtime.js +607 -0
- package/dist/http/helpers/autopilot-slice-utils.d.ts +56 -0
- package/dist/http/helpers/autopilot-slice-utils.js +899 -0
- package/dist/http/helpers/decision-mapper.d.ts +52 -0
- package/dist/http/helpers/decision-mapper.js +260 -0
- package/dist/http/helpers/dispatch-lifecycle.d.ts +119 -0
- package/dist/http/helpers/dispatch-lifecycle.js +809 -0
- package/dist/http/helpers/hash-utils.d.ts +1 -0
- package/dist/http/helpers/hash-utils.js +1 -0
- package/dist/http/helpers/kickoff-context.d.ts +12 -0
- package/dist/http/helpers/kickoff-context.js +228 -0
- package/dist/http/helpers/llm-client.d.ts +47 -0
- package/dist/http/helpers/llm-client.js +256 -0
- package/dist/http/helpers/mission-control.d.ts +193 -0
- package/dist/http/helpers/mission-control.js +1383 -0
- package/dist/http/helpers/openclaw-cli.d.ts +37 -0
- package/dist/http/helpers/openclaw-cli.js +283 -0
- package/dist/http/helpers/runtime-sse.d.ts +20 -0
- package/dist/http/helpers/runtime-sse.js +110 -0
- package/dist/http/helpers/sentinel-catalog.d.ts +23 -0
- package/dist/http/helpers/sentinel-catalog.js +193 -0
- package/dist/http/helpers/session-classification.d.ts +9 -0
- package/dist/http/helpers/session-classification.js +564 -0
- package/dist/http/helpers/slice-experience-v2.d.ts +137 -0
- package/dist/http/helpers/slice-experience-v2.js +677 -0
- package/dist/http/helpers/slice-run-projections.d.ts +72 -0
- package/dist/http/helpers/slice-run-projections.js +860 -0
- package/dist/http/helpers/triage-mapper.d.ts +43 -0
- package/dist/http/helpers/triage-mapper.js +549 -0
- package/dist/http/helpers/value-utils.d.ts +6 -0
- package/dist/http/helpers/value-utils.js +72 -0
- package/dist/http/helpers/workspace-scope.d.ts +15 -0
- package/dist/http/helpers/workspace-scope.js +170 -0
- package/dist/http/index.d.ts +88 -0
- package/dist/http/index.js +3610 -0
- package/dist/http/router.d.ts +23 -0
- package/dist/http/router.js +23 -0
- package/dist/http/routes/agent-control.d.ts +79 -0
- package/dist/http/routes/agent-control.js +684 -0
- package/dist/http/routes/agent-suite.d.ts +38 -0
- package/dist/http/routes/agent-suite.js +397 -0
- package/dist/http/routes/agents-catalog.d.ts +40 -0
- package/dist/http/routes/agents-catalog.js +128 -0
- package/dist/http/routes/billing.d.ts +23 -0
- package/dist/http/routes/billing.js +55 -0
- package/dist/http/routes/chat.d.ts +19 -0
- package/dist/http/routes/chat.js +522 -0
- package/dist/http/routes/debug.d.ts +14 -0
- package/dist/http/routes/debug.js +21 -0
- package/dist/http/routes/decision-actions.d.ts +20 -0
- package/dist/http/routes/decision-actions.js +103 -0
- package/dist/http/routes/delegation.d.ts +19 -0
- package/dist/http/routes/delegation.js +32 -0
- package/dist/http/routes/dispatch-gateway-envelope.d.ts +25 -0
- package/dist/http/routes/dispatch-gateway-envelope.js +26 -0
- package/dist/http/routes/entities.d.ts +63 -0
- package/dist/http/routes/entities.js +440 -0
- package/dist/http/routes/entity-dynamic.d.ts +25 -0
- package/dist/http/routes/entity-dynamic.js +191 -0
- package/dist/http/routes/health.d.ts +22 -0
- package/dist/http/routes/health.js +49 -0
- package/dist/http/routes/live-legacy.d.ts +115 -0
- package/dist/http/routes/live-legacy.js +112 -0
- package/dist/http/routes/live-misc.d.ts +81 -0
- package/dist/http/routes/live-misc.js +426 -0
- package/dist/http/routes/live-snapshot.d.ts +136 -0
- package/dist/http/routes/live-snapshot.js +916 -0
- package/dist/http/routes/live-terminal.d.ts +11 -0
- package/dist/http/routes/live-terminal.js +261 -0
- package/dist/http/routes/live-triage.d.ts +61 -0
- package/dist/http/routes/live-triage.js +248 -0
- package/dist/http/routes/mission-control-actions.d.ts +131 -0
- package/dist/http/routes/mission-control-actions.js +1791 -0
- package/dist/http/routes/mission-control-read.d.ts +73 -0
- package/dist/http/routes/mission-control-read.js +1640 -0
- package/dist/http/routes/onboarding.d.ts +34 -0
- package/dist/http/routes/onboarding.js +101 -0
- package/dist/http/routes/realtime-orchestrator.d.ts +10 -0
- package/dist/http/routes/realtime-orchestrator.js +74 -0
- package/dist/http/routes/run-control.d.ts +27 -0
- package/dist/http/routes/run-control.js +96 -0
- package/dist/http/routes/runtime-hooks.d.ts +69 -0
- package/dist/http/routes/runtime-hooks.js +437 -0
- package/dist/http/routes/sentinels-catalog.d.ts +7 -0
- package/dist/http/routes/sentinels-catalog.js +24 -0
- package/dist/http/routes/settings-byok.d.ts +23 -0
- package/dist/http/routes/settings-byok.js +163 -0
- package/dist/http/routes/summary.d.ts +18 -0
- package/dist/http/routes/summary.js +49 -0
- package/dist/http/routes/usage.d.ts +24 -0
- package/dist/http/routes/usage.js +362 -0
- package/dist/http/routes/work-artifacts.d.ts +9 -0
- package/dist/http/routes/work-artifacts.js +55 -0
- package/dist/http/shared-state.d.ts +16 -0
- package/dist/http/shared-state.js +1 -0
- package/dist/http-handler.d.ts +1 -88
- package/dist/http-handler.js +1 -10605
- package/dist/index.js +287 -2284
- package/dist/json-utils.d.ts +1 -0
- package/dist/json-utils.js +8 -0
- package/dist/local-openclaw.js +29 -6
- package/dist/mcp-client-setup.js +3 -3
- package/dist/mcp-http-handler.js +33 -59
- package/dist/next-up-queue-store.d.ts +16 -1
- package/dist/next-up-queue-store.js +93 -25
- package/dist/outbox.d.ts +5 -0
- package/dist/outbox.js +113 -9
- package/dist/paths.js +24 -5
- package/dist/reporting/rollups.d.ts +53 -0
- package/dist/reporting/rollups.js +148 -0
- package/dist/retro/domain-templates.d.ts +45 -0
- package/dist/retro/domain-templates.js +297 -0
- package/dist/retro/quality-rubric.d.ts +33 -0
- package/dist/retro/quality-rubric.js +213 -0
- package/dist/runtime-cleanup.d.ts +18 -0
- package/dist/runtime-cleanup.js +87 -0
- package/dist/runtime-instance-store.js +5 -31
- package/dist/services/background.d.ts +34 -0
- package/dist/services/background.js +45 -0
- package/dist/services/experiment-randomization.d.ts +21 -0
- package/dist/services/experiment-randomization.js +63 -0
- package/dist/services/instrumentation.d.ts +29 -0
- package/dist/services/instrumentation.js +136 -0
- package/dist/skill-pack-state.d.ts +36 -5
- package/dist/skill-pack-state.js +273 -29
- package/dist/snapshot-store.js +5 -25
- package/dist/stores/json-store.d.ts +11 -0
- package/dist/stores/json-store.js +42 -0
- package/dist/sync/local-agent-telemetry.d.ts +13 -0
- package/dist/sync/local-agent-telemetry.js +128 -0
- package/dist/sync/outbox-replay.d.ts +55 -0
- package/dist/sync/outbox-replay.js +621 -0
- package/dist/team-context-store.d.ts +23 -0
- package/dist/team-context-store.js +116 -0
- package/dist/telemetry/posthog.js +4 -2
- package/dist/tools/core-tools.d.ts +72 -0
- package/dist/tools/core-tools.js +2270 -0
- package/dist/types.d.ts +2 -0
- package/dist/types.js +2 -0
- package/dist/worker-supervisor.js +23 -0
- package/package.json +14 -4
- package/dashboard/dist/assets/B3ziCA02.js +0 -8
- package/dashboard/dist/assets/BNeJ0kpF.js +0 -1
- package/dashboard/dist/assets/BzkiMPmM.js +0 -215
- package/dashboard/dist/assets/CUV9IHHi.js +0 -1
- package/dashboard/dist/assets/Ie7d9Iq2.css +0 -1
- package/dashboard/dist/assets/sAhvFnpk.js +0 -4
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Router } from "../router.js";
|
|
2
|
+
type JsonRecord = Record<string, unknown>;
|
|
3
|
+
type ReadSkillPackStateFn = typeof import("../../skill-pack-state.js").readSkillPackState;
|
|
4
|
+
type UpdateSkillPackPolicyFn = typeof import("../../skill-pack-state.js").updateSkillPackPolicy;
|
|
5
|
+
type RollbackSkillPackPolicyFn = typeof import("../../skill-pack-state.js").rollbackSkillPackPolicy;
|
|
6
|
+
type ComputeOrgxAgentSuitePlanFn = typeof import("../../agent-suite.js").computeOrgxAgentSuitePlan;
|
|
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;
|
|
10
|
+
type OrgxSkillPackOverrides = import("../../agent-suite.js").OrgxSkillPackOverrides;
|
|
11
|
+
type RegisterAgentSuiteRoutesDeps<TReq, TRes> = {
|
|
12
|
+
pluginVersion: string | null | undefined;
|
|
13
|
+
telemetryDistinctId: string;
|
|
14
|
+
parseJsonRequest: (req: TReq) => Promise<JsonRecord>;
|
|
15
|
+
resolveSkillPackOverrides: (input: {
|
|
16
|
+
force?: boolean;
|
|
17
|
+
}) => Promise<OrgxSkillPackOverrides | null>;
|
|
18
|
+
readSkillPackState: ReadSkillPackStateFn;
|
|
19
|
+
computeOrgxAgentSuitePlan: ComputeOrgxAgentSuitePlanFn;
|
|
20
|
+
applyOrgxAgentSuitePlan: ApplyOrgxAgentSuitePlanFn;
|
|
21
|
+
generateAgentSuiteOperationId: () => string;
|
|
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>;
|
|
29
|
+
posthogCapture: (input: {
|
|
30
|
+
event: string;
|
|
31
|
+
distinctId: string;
|
|
32
|
+
properties: Record<string, unknown>;
|
|
33
|
+
}) => Promise<unknown>;
|
|
34
|
+
sendJson: (res: TRes, status: number, payload: unknown) => void;
|
|
35
|
+
safeErrorMessage: (err: unknown) => string;
|
|
36
|
+
};
|
|
37
|
+
export declare function registerAgentSuiteRoutes<TReq, TRes>(router: Router<Record<string, never>, TReq, TRes>, deps: RegisterAgentSuiteRoutesDeps<TReq, TRes>): void;
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
function getPluginVersion(pluginVersion) {
|
|
2
|
+
const normalized = (pluginVersion ?? "").trim();
|
|
3
|
+
return normalized.length > 0 ? normalized : null;
|
|
4
|
+
}
|
|
5
|
+
function toRecord(value) {
|
|
6
|
+
return value && typeof value === "object" && !Array.isArray(value)
|
|
7
|
+
? value
|
|
8
|
+
: {};
|
|
9
|
+
}
|
|
10
|
+
function readBoolean(payload, ...keys) {
|
|
11
|
+
for (const key of keys) {
|
|
12
|
+
const value = payload[key];
|
|
13
|
+
if (typeof value === "boolean") {
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
function computeUpdateAvailable(state) {
|
|
20
|
+
return Boolean(state.remote?.checksum &&
|
|
21
|
+
state.pack?.checksum &&
|
|
22
|
+
state.remote.checksum !== state.pack.checksum);
|
|
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 normalizeRuntimeSettingsPatch(payload) {
|
|
44
|
+
const runtime = toRecord(payload.runtime_settings ?? payload.runtimeSettings);
|
|
45
|
+
const patch = {};
|
|
46
|
+
const decisionV2Enabled = readOptionalBoolean(runtime, "decision_v2_enabled", "decisionV2Enabled");
|
|
47
|
+
if (typeof decisionV2Enabled === "boolean") {
|
|
48
|
+
patch.decision_v2_enabled = decisionV2Enabled;
|
|
49
|
+
}
|
|
50
|
+
const decisionDedupeEnabled = readOptionalBoolean(runtime, "decision_dedupe_enabled", "decisionDedupeEnabled");
|
|
51
|
+
if (typeof decisionDedupeEnabled === "boolean") {
|
|
52
|
+
patch.decision_dedupe_enabled = decisionDedupeEnabled;
|
|
53
|
+
}
|
|
54
|
+
const decisionEvidenceRequiredForBlocking = readOptionalBoolean(runtime, "decision_evidence_required_for_blocking", "decisionEvidenceRequiredForBlocking");
|
|
55
|
+
if (typeof decisionEvidenceRequiredForBlocking === "boolean") {
|
|
56
|
+
patch.decision_evidence_required_for_blocking =
|
|
57
|
+
decisionEvidenceRequiredForBlocking;
|
|
58
|
+
}
|
|
59
|
+
const decisionAutoResolveGuardedEnabled = readOptionalBoolean(runtime, "decision_auto_resolve_guarded_enabled", "decisionAutoResolveGuardedEnabled");
|
|
60
|
+
if (typeof decisionAutoResolveGuardedEnabled === "boolean") {
|
|
61
|
+
patch.decision_auto_resolve_guarded_enabled =
|
|
62
|
+
decisionAutoResolveGuardedEnabled;
|
|
63
|
+
}
|
|
64
|
+
const customRunInstructions = toOptionalString(runtime.custom_run_instructions ?? runtime.customRunInstructions);
|
|
65
|
+
if (typeof customRunInstructions === "string") {
|
|
66
|
+
patch.custom_run_instructions = customRunInstructions.slice(0, 4000);
|
|
67
|
+
}
|
|
68
|
+
return patch;
|
|
69
|
+
}
|
|
70
|
+
function buildRuntimeSettingsFallbackEnvelope(workspaceId) {
|
|
71
|
+
const normalizedWorkspaceId = typeof workspaceId === "string" && workspaceId.trim().length > 0
|
|
72
|
+
? workspaceId.trim()
|
|
73
|
+
: null;
|
|
74
|
+
return {
|
|
75
|
+
ok: true,
|
|
76
|
+
workspace_id: normalizedWorkspaceId,
|
|
77
|
+
command_center_id: normalizedWorkspaceId,
|
|
78
|
+
project_id: normalizedWorkspaceId,
|
|
79
|
+
agents: [],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
export function registerAgentSuiteRoutes(router, deps) {
|
|
83
|
+
async function renderStatus(res) {
|
|
84
|
+
try {
|
|
85
|
+
// Resolve skill pack overrides opportunistically; fallback to builtins.
|
|
86
|
+
let skillPack = null;
|
|
87
|
+
try {
|
|
88
|
+
skillPack = await deps.resolveSkillPackOverrides({});
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
// Ignore resolver errors and use local defaults.
|
|
92
|
+
}
|
|
93
|
+
const state = deps.readSkillPackState();
|
|
94
|
+
const plan = deps.computeOrgxAgentSuitePlan({
|
|
95
|
+
packVersion: deps.pluginVersion || "0.0.0",
|
|
96
|
+
skillPack,
|
|
97
|
+
skillPackRemote: state.remote,
|
|
98
|
+
skillPackPolicy: state.policy,
|
|
99
|
+
skillPackUpdateAvailable: computeUpdateAvailable(state),
|
|
100
|
+
});
|
|
101
|
+
deps.sendJson(res, 200, {
|
|
102
|
+
ok: true,
|
|
103
|
+
data: plan,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
deps.sendJson(res, 500, {
|
|
108
|
+
ok: false,
|
|
109
|
+
error: deps.safeErrorMessage(err),
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
router.add("GET", "agent-suite/status", async ({ res }) => renderStatus(res), "Agent suite installation status");
|
|
114
|
+
router.add("HEAD", "agent-suite/status", async ({ res }) => renderStatus(res), "Agent suite installation status (HEAD)");
|
|
115
|
+
router.add("GET", "agent-suite/runtime-settings", async ({ req, res }) => {
|
|
116
|
+
const requestUrl = new URL(String(req.url ?? "/"), "http://localhost");
|
|
117
|
+
const workspaceId = toOptionalUuid(requestUrl.searchParams.get("workspace_id") ??
|
|
118
|
+
requestUrl.searchParams.get("workspaceId") ??
|
|
119
|
+
requestUrl.searchParams.get("command_center_id") ??
|
|
120
|
+
requestUrl.searchParams.get("commandCenterId") ??
|
|
121
|
+
requestUrl.searchParams.get("project_id"));
|
|
122
|
+
try {
|
|
123
|
+
const response = await deps.fetchAgentRuntimeSettings({
|
|
124
|
+
workspaceId: workspaceId ?? null,
|
|
125
|
+
});
|
|
126
|
+
if (!response?.ok) {
|
|
127
|
+
deps.sendJson(res, 200, {
|
|
128
|
+
ok: true,
|
|
129
|
+
data: {
|
|
130
|
+
...buildRuntimeSettingsFallbackEnvelope(workspaceId ?? null),
|
|
131
|
+
warning: response?.error ?? "Failed to load agent runtime settings",
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
deps.sendJson(res, 200, {
|
|
137
|
+
ok: true,
|
|
138
|
+
data: response,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
catch (err) {
|
|
142
|
+
deps.sendJson(res, 200, {
|
|
143
|
+
ok: true,
|
|
144
|
+
data: {
|
|
145
|
+
...buildRuntimeSettingsFallbackEnvelope(workspaceId ?? null),
|
|
146
|
+
warning: deps.safeErrorMessage(err),
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}, "List agent runtime settings");
|
|
151
|
+
router.add("PATCH", "agent-suite/runtime-settings", async ({ req, res }) => {
|
|
152
|
+
try {
|
|
153
|
+
const payload = toRecord(await deps.parseJsonRequest(req));
|
|
154
|
+
const agentId = toOptionalString(payload.agent_id ?? payload.agentId)?.trim();
|
|
155
|
+
if (!agentId) {
|
|
156
|
+
deps.sendJson(res, 400, {
|
|
157
|
+
ok: false,
|
|
158
|
+
error: "agent_id is required",
|
|
159
|
+
});
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
const runtimeSettingsPatch = normalizeRuntimeSettingsPatch(payload);
|
|
163
|
+
if (Object.keys(runtimeSettingsPatch).length === 0) {
|
|
164
|
+
deps.sendJson(res, 400, {
|
|
165
|
+
ok: false,
|
|
166
|
+
error: "runtime_settings must include at least one mutable field",
|
|
167
|
+
});
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
const workspaceId = toOptionalUuid(payload.workspace_id ??
|
|
171
|
+
payload.workspaceId ??
|
|
172
|
+
payload.command_center_id ??
|
|
173
|
+
payload.commandCenterId ??
|
|
174
|
+
payload.project_id ??
|
|
175
|
+
payload.projectId);
|
|
176
|
+
const response = await deps.updateAgentRuntimeSettings({
|
|
177
|
+
agent_id: agentId,
|
|
178
|
+
...(workspaceId
|
|
179
|
+
? {
|
|
180
|
+
workspace_id: workspaceId,
|
|
181
|
+
command_center_id: workspaceId,
|
|
182
|
+
}
|
|
183
|
+
: {}),
|
|
184
|
+
runtime_settings: runtimeSettingsPatch,
|
|
185
|
+
});
|
|
186
|
+
if (!response?.ok) {
|
|
187
|
+
deps.sendJson(res, 502, {
|
|
188
|
+
ok: false,
|
|
189
|
+
error: response?.error ?? "Failed to update agent runtime settings",
|
|
190
|
+
});
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
deps.sendJson(res, 200, {
|
|
194
|
+
ok: true,
|
|
195
|
+
data: response,
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
catch (err) {
|
|
199
|
+
deps.sendJson(res, 500, {
|
|
200
|
+
ok: false,
|
|
201
|
+
error: deps.safeErrorMessage(err),
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
}, "Update agent runtime settings");
|
|
205
|
+
router.add("*", "agent-suite/runtime-settings", ({ res }) => {
|
|
206
|
+
deps.sendJson(res, 405, {
|
|
207
|
+
ok: false,
|
|
208
|
+
error: "Use GET/PATCH /orgx/api/agent-suite/runtime-settings",
|
|
209
|
+
});
|
|
210
|
+
}, "Reject unsupported methods for agent-suite/runtime-settings");
|
|
211
|
+
router.add("POST", "agent-suite/install", async ({ req, res }) => {
|
|
212
|
+
try {
|
|
213
|
+
const payload = toRecord(await deps.parseJsonRequest(req));
|
|
214
|
+
const dryRun = readBoolean(payload, "dryRun", "dry_run");
|
|
215
|
+
const forceSkillPack = readBoolean(payload, "forceSkillPack", "force_skill_pack");
|
|
216
|
+
const skillPack = await deps.resolveSkillPackOverrides({ force: forceSkillPack });
|
|
217
|
+
const state = deps.readSkillPackState();
|
|
218
|
+
const plan = deps.computeOrgxAgentSuitePlan({
|
|
219
|
+
packVersion: deps.pluginVersion || "0.0.0",
|
|
220
|
+
skillPack,
|
|
221
|
+
skillPackRemote: state.remote,
|
|
222
|
+
skillPackPolicy: state.policy,
|
|
223
|
+
skillPackUpdateAvailable: computeUpdateAvailable(state),
|
|
224
|
+
});
|
|
225
|
+
const result = deps.applyOrgxAgentSuitePlan({ plan, dryRun, skillPack });
|
|
226
|
+
const counts = {
|
|
227
|
+
create: 0,
|
|
228
|
+
update: 0,
|
|
229
|
+
noop: 0,
|
|
230
|
+
conflict: 0,
|
|
231
|
+
};
|
|
232
|
+
for (const entry of result.plan.workspaceFiles ?? []) {
|
|
233
|
+
if (entry.action in counts) {
|
|
234
|
+
counts[entry.action] += 1;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
void deps
|
|
238
|
+
.posthogCapture({
|
|
239
|
+
event: "openclaw_agent_suite_install",
|
|
240
|
+
distinctId: deps.telemetryDistinctId,
|
|
241
|
+
properties: {
|
|
242
|
+
plugin_version: getPluginVersion(deps.pluginVersion),
|
|
243
|
+
dry_run: Boolean(dryRun),
|
|
244
|
+
applied: Boolean(result.applied),
|
|
245
|
+
openclaw_config_updated: Boolean(result.plan.openclawConfigWouldUpdate),
|
|
246
|
+
added_agents_count: result.plan.openclawConfigAddedAgents.length,
|
|
247
|
+
files_create: counts.create,
|
|
248
|
+
files_update: counts.update,
|
|
249
|
+
files_noop: counts.noop,
|
|
250
|
+
files_conflict: counts.conflict,
|
|
251
|
+
skill_pack_source: result.plan.skillPack?.source ?? null,
|
|
252
|
+
skill_pack_checksum: result.plan.skillPack?.checksum ?? null,
|
|
253
|
+
skill_pack_version: result.plan.skillPack?.version ?? null,
|
|
254
|
+
},
|
|
255
|
+
})
|
|
256
|
+
.catch(() => {
|
|
257
|
+
// best effort
|
|
258
|
+
});
|
|
259
|
+
deps.sendJson(res, 200, {
|
|
260
|
+
ok: true,
|
|
261
|
+
operationId: deps.generateAgentSuiteOperationId(),
|
|
262
|
+
dryRun,
|
|
263
|
+
applied: result.applied,
|
|
264
|
+
data: result.plan,
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
catch (err) {
|
|
268
|
+
void deps
|
|
269
|
+
.posthogCapture({
|
|
270
|
+
event: "openclaw_agent_suite_install_failed",
|
|
271
|
+
distinctId: deps.telemetryDistinctId,
|
|
272
|
+
properties: {
|
|
273
|
+
plugin_version: getPluginVersion(deps.pluginVersion),
|
|
274
|
+
error: deps.safeErrorMessage(err),
|
|
275
|
+
},
|
|
276
|
+
})
|
|
277
|
+
.catch(() => {
|
|
278
|
+
// best effort
|
|
279
|
+
});
|
|
280
|
+
deps.sendJson(res, 500, {
|
|
281
|
+
ok: false,
|
|
282
|
+
error: deps.safeErrorMessage(err),
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
}, "Install managed OrgX agent suite");
|
|
286
|
+
router.add("*", "agent-suite/install", ({ res }) => {
|
|
287
|
+
deps.sendJson(res, 405, {
|
|
288
|
+
ok: false,
|
|
289
|
+
error: "Use POST /orgx/api/agent-suite/install",
|
|
290
|
+
});
|
|
291
|
+
}, "Reject unsupported methods for agent-suite/install");
|
|
292
|
+
router.add("GET", "skill-pack/policy", ({ res }) => {
|
|
293
|
+
const state = deps.readSkillPackState();
|
|
294
|
+
deps.sendJson(res, 200, {
|
|
295
|
+
ok: true,
|
|
296
|
+
data: {
|
|
297
|
+
policy: state.policy,
|
|
298
|
+
audit: state.audit,
|
|
299
|
+
pack: state.pack,
|
|
300
|
+
remote: state.remote,
|
|
301
|
+
updateAvailable: computeUpdateAvailable(state),
|
|
302
|
+
lastCheckedAt: state.lastCheckedAt,
|
|
303
|
+
lastError: state.lastError,
|
|
304
|
+
},
|
|
305
|
+
});
|
|
306
|
+
}, "Read skill-pack policy");
|
|
307
|
+
router.add("POST", "skill-pack/policy", async ({ req, res }) => {
|
|
308
|
+
try {
|
|
309
|
+
const payload = toRecord(await deps.parseJsonRequest(req));
|
|
310
|
+
const frozenRaw = payload.frozen;
|
|
311
|
+
const frozen = typeof frozenRaw === "boolean" ? frozenRaw : undefined;
|
|
312
|
+
const pinToCurrent = readBoolean(payload, "pinToCurrent", "pin_to_current");
|
|
313
|
+
const clearPin = readBoolean(payload, "clearPin", "clear_pin");
|
|
314
|
+
const changedByRaw = payload.changedBy ?? payload.changed_by;
|
|
315
|
+
const changedBy = typeof changedByRaw === "string" ? changedByRaw : undefined;
|
|
316
|
+
const reasonRaw = payload.reason;
|
|
317
|
+
const reason = typeof reasonRaw === "string" ? reasonRaw : undefined;
|
|
318
|
+
const actionRaw = payload.action;
|
|
319
|
+
const action = typeof actionRaw === "string" ? actionRaw.trim().toLowerCase() : "";
|
|
320
|
+
const rollbackToAuditIdRaw = payload.rollbackToAuditId ?? payload.rollback_to_audit_id;
|
|
321
|
+
const rollbackToAuditId = toOptionalString(rollbackToAuditIdRaw)?.trim() || undefined;
|
|
322
|
+
const pinnedChecksumRaw = payload.pinnedChecksum ?? payload.pinned_checksum;
|
|
323
|
+
const pinnedChecksum = typeof pinnedChecksumRaw === "string"
|
|
324
|
+
? pinnedChecksumRaw
|
|
325
|
+
: pinnedChecksumRaw === null
|
|
326
|
+
? null
|
|
327
|
+
: undefined;
|
|
328
|
+
const hasFrozen = typeof frozen === "boolean";
|
|
329
|
+
const hasPinnedChecksum = typeof pinnedChecksum === "string" || pinnedChecksum === null;
|
|
330
|
+
const hasPinToCurrent = pinToCurrent === true;
|
|
331
|
+
const hasClearPin = clearPin === true;
|
|
332
|
+
const isRollback = action === "rollback" || typeof rollbackToAuditId === "string";
|
|
333
|
+
if (action.length > 0 && action !== "rollback") {
|
|
334
|
+
throw new Error("action must be 'rollback' when provided.");
|
|
335
|
+
}
|
|
336
|
+
if (hasPinToCurrent && hasClearPin) {
|
|
337
|
+
throw new Error("pinToCurrent and clearPin cannot both be true.");
|
|
338
|
+
}
|
|
339
|
+
if (typeof pinnedChecksum === "string" && !pinnedChecksum.trim()) {
|
|
340
|
+
throw new Error("pinnedChecksum must be a non-empty string when provided.");
|
|
341
|
+
}
|
|
342
|
+
if (isRollback) {
|
|
343
|
+
if (hasFrozen || hasPinnedChecksum || hasPinToCurrent || hasClearPin) {
|
|
344
|
+
throw new Error("Rollback requests cannot include update fields (frozen, pinnedChecksum, pinToCurrent, clearPin).");
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
else if (!hasFrozen && !hasPinnedChecksum && !hasPinToCurrent && !hasClearPin) {
|
|
348
|
+
throw new Error("Include at least one mutable field: frozen, pinnedChecksum, pinToCurrent, or clearPin.");
|
|
349
|
+
}
|
|
350
|
+
const state = isRollback
|
|
351
|
+
? deps.rollbackSkillPackPolicy({
|
|
352
|
+
auditId: rollbackToAuditId,
|
|
353
|
+
changedBy,
|
|
354
|
+
reason,
|
|
355
|
+
})
|
|
356
|
+
: deps.updateSkillPackPolicy({
|
|
357
|
+
frozen,
|
|
358
|
+
pinToCurrent,
|
|
359
|
+
clearPin,
|
|
360
|
+
pinnedChecksum: typeof pinnedChecksum === "string" ? pinnedChecksum.trim() : pinnedChecksum,
|
|
361
|
+
changedBy,
|
|
362
|
+
reason,
|
|
363
|
+
});
|
|
364
|
+
void deps
|
|
365
|
+
.posthogCapture({
|
|
366
|
+
event: "openclaw_skill_pack_policy_updated",
|
|
367
|
+
distinctId: deps.telemetryDistinctId,
|
|
368
|
+
properties: {
|
|
369
|
+
plugin_version: getPluginVersion(deps.pluginVersion),
|
|
370
|
+
frozen: state.policy.frozen,
|
|
371
|
+
pinned_checksum_prefix: state.policy.pinnedChecksum
|
|
372
|
+
? state.policy.pinnedChecksum.slice(0, 12)
|
|
373
|
+
: null,
|
|
374
|
+
},
|
|
375
|
+
})
|
|
376
|
+
.catch(() => {
|
|
377
|
+
// best effort
|
|
378
|
+
});
|
|
379
|
+
deps.sendJson(res, 200, {
|
|
380
|
+
ok: true,
|
|
381
|
+
data: {
|
|
382
|
+
policy: state.policy,
|
|
383
|
+
audit: state.audit,
|
|
384
|
+
},
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
catch (err) {
|
|
388
|
+
deps.sendJson(res, 400, { ok: false, error: deps.safeErrorMessage(err) });
|
|
389
|
+
}
|
|
390
|
+
}, "Update skill-pack policy");
|
|
391
|
+
router.add("*", "skill-pack/policy", ({ res }) => {
|
|
392
|
+
deps.sendJson(res, 405, {
|
|
393
|
+
ok: false,
|
|
394
|
+
error: "Use GET/POST /orgx/api/skill-pack/policy",
|
|
395
|
+
});
|
|
396
|
+
}, "Reject unsupported methods for skill-pack/policy");
|
|
397
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Router } from "../router.js";
|
|
2
|
+
type OpenClawAgentEntry = {
|
|
3
|
+
id?: string;
|
|
4
|
+
name?: string;
|
|
5
|
+
workspace?: string;
|
|
6
|
+
model?: string;
|
|
7
|
+
isDefault?: boolean;
|
|
8
|
+
};
|
|
9
|
+
type LocalAgentSnapshot = {
|
|
10
|
+
id: string;
|
|
11
|
+
status: string;
|
|
12
|
+
currentTask: string | null;
|
|
13
|
+
runId: string | null;
|
|
14
|
+
startedAt: string | null;
|
|
15
|
+
blockers: string[];
|
|
16
|
+
};
|
|
17
|
+
type LocalSnapshot = {
|
|
18
|
+
agents: LocalAgentSnapshot[];
|
|
19
|
+
};
|
|
20
|
+
type AgentRun = {
|
|
21
|
+
agentId: string;
|
|
22
|
+
startedAt: string | null;
|
|
23
|
+
status: string;
|
|
24
|
+
};
|
|
25
|
+
type AgentRunStoreSnapshot = {
|
|
26
|
+
runs: Record<string, AgentRun & Record<string, unknown>>;
|
|
27
|
+
};
|
|
28
|
+
type AgentContextStoreSnapshot = {
|
|
29
|
+
agents: Record<string, unknown>;
|
|
30
|
+
};
|
|
31
|
+
type AgentsCatalogDeps<TRes> = {
|
|
32
|
+
listAgents: () => Promise<OpenClawAgentEntry[]>;
|
|
33
|
+
loadLocalSnapshot: () => Promise<LocalSnapshot | null>;
|
|
34
|
+
readAgentContexts: () => AgentContextStoreSnapshot;
|
|
35
|
+
readAgentRuns: () => AgentRunStoreSnapshot;
|
|
36
|
+
sendJson: (res: TRes, status: number, payload: unknown) => void;
|
|
37
|
+
safeErrorMessage: (err: unknown) => string;
|
|
38
|
+
};
|
|
39
|
+
export declare function registerAgentsCatalogRoutes<TReq, TRes>(router: Router<Record<string, never>, TReq, TRes>, deps: AgentsCatalogDeps<TRes>): void;
|
|
40
|
+
export {};
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
export function registerAgentsCatalogRoutes(router, deps) {
|
|
2
|
+
async function handle(res) {
|
|
3
|
+
try {
|
|
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
|
+
}
|
|
21
|
+
const localById = new Map();
|
|
22
|
+
if (localAgents.length > 0) {
|
|
23
|
+
for (const agent of localAgents) {
|
|
24
|
+
localById.set(agent.id, {
|
|
25
|
+
status: agent.status,
|
|
26
|
+
currentTask: agent.currentTask,
|
|
27
|
+
runId: agent.runId,
|
|
28
|
+
startedAt: agent.startedAt,
|
|
29
|
+
blockers: agent.blockers,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
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
|
+
}
|
|
47
|
+
const latestRunByAgent = new Map();
|
|
48
|
+
const openclawById = new Map();
|
|
49
|
+
for (const run of Object.values(runs)) {
|
|
50
|
+
if (!run || typeof run !== "object")
|
|
51
|
+
continue;
|
|
52
|
+
const agentId = typeof run.agentId === "string" ? run.agentId.trim() : "";
|
|
53
|
+
if (!agentId)
|
|
54
|
+
continue;
|
|
55
|
+
const existing = latestRunByAgent.get(agentId);
|
|
56
|
+
const nextTs = Date.parse(run.startedAt ?? "");
|
|
57
|
+
const existingTs = existing ? Date.parse(existing.startedAt ?? "") : 0;
|
|
58
|
+
if (!existing) {
|
|
59
|
+
latestRunByAgent.set(agentId, run);
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
const existingRunning = existing.status === "running";
|
|
63
|
+
const nextRunning = run.status === "running";
|
|
64
|
+
if (nextRunning && !existingRunning) {
|
|
65
|
+
latestRunByAgent.set(agentId, run);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (nextRunning === existingRunning && nextTs > existingTs) {
|
|
69
|
+
latestRunByAgent.set(agentId, run);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
for (const entry of openclawAgents) {
|
|
73
|
+
const id = typeof entry.id === "string" ? entry.id.trim() : "";
|
|
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
|
|
93
|
+
? entry.name.trim()
|
|
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);
|
|
99
|
+
return {
|
|
100
|
+
id: agentId,
|
|
101
|
+
name,
|
|
102
|
+
workspace: typeof entry?.workspace === "string" ? entry.workspace : null,
|
|
103
|
+
model: typeof entry?.model === "string" ? entry.model : null,
|
|
104
|
+
isDefault: Boolean(entry?.isDefault),
|
|
105
|
+
status: local?.status ?? null,
|
|
106
|
+
currentTask: local?.currentTask ?? null,
|
|
107
|
+
runId: local?.runId ?? null,
|
|
108
|
+
startedAt: local?.startedAt ?? null,
|
|
109
|
+
blockers: local?.blockers ?? [],
|
|
110
|
+
context,
|
|
111
|
+
run,
|
|
112
|
+
};
|
|
113
|
+
});
|
|
114
|
+
deps.sendJson(res, 200, {
|
|
115
|
+
generatedAt: new Date().toISOString(),
|
|
116
|
+
agents,
|
|
117
|
+
...(warnings.length > 0 ? { warnings } : {}),
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
deps.sendJson(res, 500, {
|
|
122
|
+
error: deps.safeErrorMessage(err),
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
router.add("GET", "agents/catalog", async ({ res }) => handle(res), "Agent catalog");
|
|
127
|
+
router.add("HEAD", "agents/catalog", async ({ res }) => handle(res), "Agent catalog (HEAD)");
|
|
128
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { BillingCheckoutRequest } from "../../types.js";
|
|
2
|
+
import type { Router } from "../router.js";
|
|
3
|
+
type JsonRecord = Record<string, unknown>;
|
|
4
|
+
type BillingClientLike = {
|
|
5
|
+
getBaseUrl: () => string;
|
|
6
|
+
getBillingStatus: () => Promise<unknown>;
|
|
7
|
+
createBillingCheckout: (input: BillingCheckoutRequest) => Promise<{
|
|
8
|
+
url?: string | null;
|
|
9
|
+
checkout_url?: string | null;
|
|
10
|
+
}>;
|
|
11
|
+
createBillingPortal: () => Promise<{
|
|
12
|
+
url?: string | null;
|
|
13
|
+
}>;
|
|
14
|
+
};
|
|
15
|
+
type RegisterBillingRoutesDeps<TReq, TRes> = {
|
|
16
|
+
client: BillingClientLike;
|
|
17
|
+
parseJsonRequest: (req: TReq) => Promise<JsonRecord>;
|
|
18
|
+
pickString: (input: JsonRecord, keys: string[]) => string | null;
|
|
19
|
+
sendJson: (res: TRes, status: number, payload: unknown) => void;
|
|
20
|
+
safeErrorMessage: (err: unknown) => string;
|
|
21
|
+
};
|
|
22
|
+
export declare function registerBillingRoutes<TReq, TRes>(router: Router<Record<string, never>, TReq, TRes>, deps: RegisterBillingRoutesDeps<TReq, TRes>): void;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export function registerBillingRoutes(router, deps) {
|
|
2
|
+
router.add("GET", "billing/status", async ({ res }) => {
|
|
3
|
+
try {
|
|
4
|
+
const status = await deps.client.getBillingStatus();
|
|
5
|
+
deps.sendJson(res, 200, { ok: true, data: status });
|
|
6
|
+
}
|
|
7
|
+
catch (err) {
|
|
8
|
+
deps.sendJson(res, 200, { ok: false, error: deps.safeErrorMessage(err) });
|
|
9
|
+
}
|
|
10
|
+
}, "Get billing plan/status");
|
|
11
|
+
router.add("POST", "billing/checkout", async ({ req, res }) => {
|
|
12
|
+
const basePricingUrl = `${deps.client.getBaseUrl().replace(/\/+$/, "")}/pricing`;
|
|
13
|
+
try {
|
|
14
|
+
const payload = await deps.parseJsonRequest(req);
|
|
15
|
+
const planIdRaw = (deps.pickString(payload, ["planId", "plan_id", "plan"]) ?? "starter")
|
|
16
|
+
.trim()
|
|
17
|
+
.toLowerCase();
|
|
18
|
+
const billingCycleRaw = (deps.pickString(payload, ["billingCycle", "billing_cycle"]) ?? "monthly")
|
|
19
|
+
.trim()
|
|
20
|
+
.toLowerCase();
|
|
21
|
+
const planId = planIdRaw === "team" || planIdRaw === "enterprise" ? planIdRaw : "starter";
|
|
22
|
+
const billingCycle = billingCycleRaw === "annual" ? "annual" : "monthly";
|
|
23
|
+
const result = await deps.client.createBillingCheckout({
|
|
24
|
+
planId,
|
|
25
|
+
billingCycle,
|
|
26
|
+
});
|
|
27
|
+
const url = result?.url ?? result?.checkout_url ?? null;
|
|
28
|
+
deps.sendJson(res, 200, { ok: true, data: { url: url ?? basePricingUrl } });
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
// If remote billing endpoints are unavailable, degrade gracefully.
|
|
32
|
+
deps.sendJson(res, 200, { ok: true, data: { url: basePricingUrl } });
|
|
33
|
+
}
|
|
34
|
+
}, "Create billing checkout session");
|
|
35
|
+
router.add("POST", "billing/portal", async ({ res }) => {
|
|
36
|
+
const basePricingUrl = `${deps.client.getBaseUrl().replace(/\/+$/, "")}/pricing`;
|
|
37
|
+
try {
|
|
38
|
+
const result = await deps.client.createBillingPortal();
|
|
39
|
+
const url = result?.url ?? null;
|
|
40
|
+
deps.sendJson(res, 200, { ok: true, data: { url: url ?? basePricingUrl } });
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
deps.sendJson(res, 200, { ok: true, data: { url: basePricingUrl } });
|
|
44
|
+
}
|
|
45
|
+
}, "Create billing portal session");
|
|
46
|
+
router.add("*", "billing/status", ({ res }) => {
|
|
47
|
+
deps.sendJson(res, 405, { ok: false, error: "Method not allowed" });
|
|
48
|
+
}, "Reject unsupported methods for billing/status");
|
|
49
|
+
router.add("*", "billing/checkout", ({ res }) => {
|
|
50
|
+
deps.sendJson(res, 405, { ok: false, error: "Method not allowed" });
|
|
51
|
+
}, "Reject unsupported methods for billing/checkout");
|
|
52
|
+
router.add("*", "billing/portal", ({ res }) => {
|
|
53
|
+
deps.sendJson(res, 405, { ok: false, error: "Method not allowed" });
|
|
54
|
+
}, "Reject unsupported methods for billing/portal");
|
|
55
|
+
}
|