@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,49 @@
|
|
|
1
|
+
export function registerSummaryRoutes(router, deps) {
|
|
2
|
+
const sendDeprecated = (res, endpoint, replacement) => {
|
|
3
|
+
deps.sendJson(res, 410, {
|
|
4
|
+
error: `${endpoint} is deprecated`,
|
|
5
|
+
replacement,
|
|
6
|
+
required_scope: "workspace_id",
|
|
7
|
+
});
|
|
8
|
+
};
|
|
9
|
+
router.add("HEAD", "status", async ({ res }) => {
|
|
10
|
+
let snapshot = deps.getSnapshot();
|
|
11
|
+
if (!snapshot) {
|
|
12
|
+
try {
|
|
13
|
+
snapshot = await deps.getOrgSnapshot();
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
// use null snapshot
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
deps.writeHead(res, snapshot ? 200 : 503, {
|
|
20
|
+
...deps.securityHeaders,
|
|
21
|
+
...deps.corsHeaders,
|
|
22
|
+
});
|
|
23
|
+
deps.end(res);
|
|
24
|
+
}, "Status probe (HEAD)");
|
|
25
|
+
router.add("GET", "status", async ({ res }) => {
|
|
26
|
+
let snapshot = deps.getSnapshot();
|
|
27
|
+
if (!snapshot) {
|
|
28
|
+
try {
|
|
29
|
+
snapshot = await deps.getOrgSnapshot();
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// use null snapshot
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
deps.sendJson(res, 200, deps.formatStatus(snapshot));
|
|
36
|
+
}, "Status snapshot");
|
|
37
|
+
router.add("GET", "agents", ({ res }) => {
|
|
38
|
+
sendDeprecated(res, "/orgx/api/agents", "/orgx/api/live/agents");
|
|
39
|
+
}, "Agent summary");
|
|
40
|
+
router.add("GET", "activity", ({ res }) => {
|
|
41
|
+
sendDeprecated(res, "/orgx/api/activity", "/orgx/api/live/snapshot");
|
|
42
|
+
}, "Activity summary");
|
|
43
|
+
router.add("GET", "initiatives", ({ res }) => {
|
|
44
|
+
sendDeprecated(res, "/orgx/api/initiatives", "/orgx/api/live/initiatives");
|
|
45
|
+
}, "Initiatives summary");
|
|
46
|
+
router.add("GET", "onboarding", async ({ res }) => {
|
|
47
|
+
deps.sendJson(res, 200, await deps.getOnboardingState());
|
|
48
|
+
}, "Legacy onboarding state endpoint");
|
|
49
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { LiveActivityItem, UsageControlPlaneSummary } from "../../types.js";
|
|
2
|
+
import type { Router } from "../router.js";
|
|
3
|
+
type UsageClientLike = {
|
|
4
|
+
getUsageControlPlaneSummary: () => Promise<UsageControlPlaneSummary>;
|
|
5
|
+
};
|
|
6
|
+
type UsageRoutesDeps<TRes> = {
|
|
7
|
+
client: UsageClientLike;
|
|
8
|
+
listActivityPage: (input: {
|
|
9
|
+
limit: number;
|
|
10
|
+
runId?: string | null;
|
|
11
|
+
since?: string | null;
|
|
12
|
+
until?: string | null;
|
|
13
|
+
cursor?: string | null;
|
|
14
|
+
}) => {
|
|
15
|
+
activities: LiveActivityItem[];
|
|
16
|
+
nextCursor: string | null;
|
|
17
|
+
total: number;
|
|
18
|
+
};
|
|
19
|
+
sendJson: (res: TRes, status: number, payload: unknown) => void;
|
|
20
|
+
safeErrorMessage: (err: unknown) => string;
|
|
21
|
+
now?: () => Date;
|
|
22
|
+
};
|
|
23
|
+
export declare function registerUsageRoutes<TReq, TRes>(router: Router<Record<string, never>, TReq, TRes>, deps: UsageRoutesDeps<TRes>): void;
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
const DAY_MS = 24 * 60 * 60_000;
|
|
2
|
+
const MAX_ACTIVITY_PAGES = 12;
|
|
3
|
+
const PAGE_LIMIT = 500;
|
|
4
|
+
function clampInt(value, min, max) {
|
|
5
|
+
if (!Number.isFinite(value))
|
|
6
|
+
return min;
|
|
7
|
+
const rounded = Math.floor(value);
|
|
8
|
+
if (rounded < min)
|
|
9
|
+
return min;
|
|
10
|
+
if (rounded > max)
|
|
11
|
+
return max;
|
|
12
|
+
return rounded;
|
|
13
|
+
}
|
|
14
|
+
function toEpoch(value) {
|
|
15
|
+
if (!value)
|
|
16
|
+
return 0;
|
|
17
|
+
const parsed = Date.parse(value);
|
|
18
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
19
|
+
}
|
|
20
|
+
function toNumber(value) {
|
|
21
|
+
if (typeof value === "number" && Number.isFinite(value))
|
|
22
|
+
return value;
|
|
23
|
+
if (typeof value === "string") {
|
|
24
|
+
const parsed = Number(value);
|
|
25
|
+
if (Number.isFinite(parsed))
|
|
26
|
+
return parsed;
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
function normalizeText(value) {
|
|
31
|
+
if (typeof value !== "string")
|
|
32
|
+
return null;
|
|
33
|
+
const trimmed = value.trim();
|
|
34
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
35
|
+
}
|
|
36
|
+
function asRecord(value) {
|
|
37
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
38
|
+
return null;
|
|
39
|
+
return value;
|
|
40
|
+
}
|
|
41
|
+
function pickMetadataNumber(metadata, keys) {
|
|
42
|
+
if (!metadata)
|
|
43
|
+
return null;
|
|
44
|
+
for (const key of keys) {
|
|
45
|
+
const parsed = toNumber(metadata[key]);
|
|
46
|
+
if (parsed !== null)
|
|
47
|
+
return parsed;
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
function pickMetadataString(metadata, keys) {
|
|
52
|
+
if (!metadata)
|
|
53
|
+
return null;
|
|
54
|
+
for (const key of keys) {
|
|
55
|
+
const normalized = normalizeText(metadata[key]);
|
|
56
|
+
if (normalized)
|
|
57
|
+
return normalized;
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
function roundInt(value) {
|
|
62
|
+
if (!Number.isFinite(value))
|
|
63
|
+
return 0;
|
|
64
|
+
return Math.max(0, Math.round(value));
|
|
65
|
+
}
|
|
66
|
+
function addToBucket(map, key, runRef, tokens, minutes, costCents) {
|
|
67
|
+
const normalizedKey = key.trim() || "unknown";
|
|
68
|
+
const bucket = map.get(normalizedKey) ??
|
|
69
|
+
{
|
|
70
|
+
runs: new Set(),
|
|
71
|
+
tokens: 0,
|
|
72
|
+
minutes: 0,
|
|
73
|
+
costCents: 0,
|
|
74
|
+
};
|
|
75
|
+
bucket.runs.add(runRef);
|
|
76
|
+
bucket.tokens += tokens;
|
|
77
|
+
bucket.minutes += minutes;
|
|
78
|
+
bucket.costCents += costCents;
|
|
79
|
+
map.set(normalizedKey, bucket);
|
|
80
|
+
}
|
|
81
|
+
function mapToBreakdownBuckets(map, labelTransform) {
|
|
82
|
+
return Array.from(map.entries())
|
|
83
|
+
.map(([key, value]) => ({
|
|
84
|
+
key,
|
|
85
|
+
label: labelTransform ? labelTransform(key) : key,
|
|
86
|
+
runs: value.runs.size,
|
|
87
|
+
tokens: roundInt(value.tokens),
|
|
88
|
+
minutes: roundInt(value.minutes),
|
|
89
|
+
costCents: roundInt(value.costCents),
|
|
90
|
+
}))
|
|
91
|
+
.sort((a, b) => {
|
|
92
|
+
if (b.runs !== a.runs)
|
|
93
|
+
return b.runs - a.runs;
|
|
94
|
+
return b.tokens - a.tokens;
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
function startOfMonthUtc(now) {
|
|
98
|
+
return new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1));
|
|
99
|
+
}
|
|
100
|
+
function startOfNextMonthUtc(now) {
|
|
101
|
+
return new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth() + 1, 1));
|
|
102
|
+
}
|
|
103
|
+
function capitalizeLabel(input) {
|
|
104
|
+
const normalized = input.trim();
|
|
105
|
+
if (!normalized)
|
|
106
|
+
return "Unknown";
|
|
107
|
+
return normalized
|
|
108
|
+
.split(/[\s_-]+/g)
|
|
109
|
+
.map((part) => part.length > 0 ? `${part[0].toUpperCase()}${part.slice(1).toLowerCase()}` : part)
|
|
110
|
+
.join(" ");
|
|
111
|
+
}
|
|
112
|
+
function buildLocalSummary(input) {
|
|
113
|
+
const periodStartIso = input.periodStart.toISOString();
|
|
114
|
+
const periodEndIso = input.periodEnd.toISOString();
|
|
115
|
+
const nowEpoch = input.now.getTime();
|
|
116
|
+
const startEpoch = input.periodStart.getTime();
|
|
117
|
+
const endEpoch = input.periodEnd.getTime();
|
|
118
|
+
const daysTotal = Math.max(1, Math.round((endEpoch - startEpoch) / DAY_MS));
|
|
119
|
+
const elapsedWindow = Math.max(0, nowEpoch - startEpoch);
|
|
120
|
+
const daysElapsed = clampInt(Math.floor(elapsedWindow / DAY_MS) + 1, 1, daysTotal);
|
|
121
|
+
const daysRemaining = Math.max(0, daysTotal - daysElapsed);
|
|
122
|
+
const runIds = new Set();
|
|
123
|
+
let totalTokens = 0;
|
|
124
|
+
let totalMinutes = 0;
|
|
125
|
+
let totalCostCents = 0;
|
|
126
|
+
let usedFallbackMinutes = false;
|
|
127
|
+
const sourceClientBuckets = new Map();
|
|
128
|
+
const providerBuckets = new Map();
|
|
129
|
+
const modelBuckets = new Map();
|
|
130
|
+
const executionTargetBuckets = new Map();
|
|
131
|
+
for (const item of input.activities) {
|
|
132
|
+
const timestampEpoch = toEpoch(item.timestamp);
|
|
133
|
+
if (!timestampEpoch || timestampEpoch < startEpoch || timestampEpoch >= endEpoch)
|
|
134
|
+
continue;
|
|
135
|
+
const metadata = asRecord(item.metadata);
|
|
136
|
+
const runId = normalizeText(item.runId) ??
|
|
137
|
+
pickMetadataString(metadata, ["run_id", "runId", "correlation_id", "correlationId"]) ??
|
|
138
|
+
item.id;
|
|
139
|
+
runIds.add(runId);
|
|
140
|
+
const rawTokens = pickMetadataNumber(metadata, [
|
|
141
|
+
"tokens_used",
|
|
142
|
+
"tokensUsed",
|
|
143
|
+
"total_tokens",
|
|
144
|
+
"totalTokens",
|
|
145
|
+
"auto_continue_tokens_used",
|
|
146
|
+
]) ?? 0;
|
|
147
|
+
const rawMinutes = pickMetadataNumber(metadata, [
|
|
148
|
+
"duration_minutes",
|
|
149
|
+
"durationMinutes",
|
|
150
|
+
"elapsed_minutes",
|
|
151
|
+
"elapsedMinutes",
|
|
152
|
+
"minutes",
|
|
153
|
+
]) ??
|
|
154
|
+
(() => {
|
|
155
|
+
const durationMs = pickMetadataNumber(metadata, ["duration_ms", "durationMs", "elapsed_ms"]);
|
|
156
|
+
return durationMs !== null ? durationMs / 60_000 : null;
|
|
157
|
+
})();
|
|
158
|
+
const minutes = rawMinutes !== null ? Math.max(0, rawMinutes) : 0;
|
|
159
|
+
if (rawMinutes === null)
|
|
160
|
+
usedFallbackMinutes = true;
|
|
161
|
+
const rawCostCents = pickMetadataNumber(metadata, ["cost_cents", "costCents"]) ??
|
|
162
|
+
(() => {
|
|
163
|
+
const costUsd = pickMetadataNumber(metadata, ["cost_usd", "costUsd"]);
|
|
164
|
+
return costUsd !== null ? costUsd * 100 : null;
|
|
165
|
+
})() ??
|
|
166
|
+
0;
|
|
167
|
+
const tokens = Math.max(0, rawTokens);
|
|
168
|
+
const costCents = Math.max(0, rawCostCents);
|
|
169
|
+
totalTokens += tokens;
|
|
170
|
+
totalMinutes += minutes;
|
|
171
|
+
totalCostCents += costCents;
|
|
172
|
+
const sourceClient = pickMetadataString(metadata, ["source_client", "sourceClient", "runtime_source", "runtimeSource"]) ??
|
|
173
|
+
normalizeText(item.runtimeClient) ??
|
|
174
|
+
"unknown";
|
|
175
|
+
const provider = pickMetadataString(metadata, ["provider", "runtime_provider", "runtimeProvider"]) ??
|
|
176
|
+
normalizeText(item.runtimeProvider) ??
|
|
177
|
+
"unknown";
|
|
178
|
+
const model = pickMetadataString(metadata, ["model", "model_id", "modelId"]) ?? "unknown";
|
|
179
|
+
const executionTarget = pickMetadataString(metadata, ["execution_target", "executionTarget", "executor"]) ??
|
|
180
|
+
"unknown";
|
|
181
|
+
addToBucket(sourceClientBuckets, sourceClient, runId, tokens, minutes, costCents);
|
|
182
|
+
addToBucket(providerBuckets, provider, runId, tokens, minutes, costCents);
|
|
183
|
+
addToBucket(modelBuckets, model, runId, tokens, minutes, costCents);
|
|
184
|
+
addToBucket(executionTargetBuckets, executionTarget, runId, tokens, minutes, costCents);
|
|
185
|
+
}
|
|
186
|
+
if (usedFallbackMinutes && runIds.size > 0 && totalMinutes === 0) {
|
|
187
|
+
totalMinutes = runIds.size * 4;
|
|
188
|
+
input.warnings.push("Agent minutes are estimated from run volume because duration telemetry was unavailable.");
|
|
189
|
+
}
|
|
190
|
+
const scale = daysElapsed > 0 ? daysTotal / daysElapsed : 1;
|
|
191
|
+
const predictedRuns = roundInt(runIds.size * scale);
|
|
192
|
+
const predictedMinutes = roundInt(totalMinutes * scale);
|
|
193
|
+
const predictedTokens = roundInt(totalTokens * scale);
|
|
194
|
+
const predictedCostCents = roundInt(totalCostCents * scale);
|
|
195
|
+
const confidence = Math.max(0.4, Math.min(0.95, daysElapsed / Math.max(daysTotal, 1)));
|
|
196
|
+
return {
|
|
197
|
+
generatedAt: new Date().toISOString(),
|
|
198
|
+
period: {
|
|
199
|
+
start: periodStartIso,
|
|
200
|
+
end: periodEndIso,
|
|
201
|
+
daysTotal,
|
|
202
|
+
daysElapsed,
|
|
203
|
+
daysRemaining,
|
|
204
|
+
},
|
|
205
|
+
plan: {
|
|
206
|
+
id: "local_estimate",
|
|
207
|
+
name: "Local Runtime Estimate",
|
|
208
|
+
allowsOverage: true,
|
|
209
|
+
includedBudgetCents: 0,
|
|
210
|
+
overageBudgetCents: 0,
|
|
211
|
+
agentRunsLimit: 0,
|
|
212
|
+
agentMinutesLimit: 0,
|
|
213
|
+
scaffoldsLimit: 0,
|
|
214
|
+
},
|
|
215
|
+
actual: {
|
|
216
|
+
agentRuns: runIds.size,
|
|
217
|
+
agentMinutes: roundInt(totalMinutes),
|
|
218
|
+
tokens: roundInt(totalTokens),
|
|
219
|
+
costCents: roundInt(totalCostCents),
|
|
220
|
+
scaffoldsUsed: 0,
|
|
221
|
+
scaffoldsRemaining: 0,
|
|
222
|
+
},
|
|
223
|
+
predicted: {
|
|
224
|
+
agentRuns: predictedRuns,
|
|
225
|
+
agentMinutes: predictedMinutes,
|
|
226
|
+
tokens: predictedTokens,
|
|
227
|
+
costCents: predictedCostCents,
|
|
228
|
+
confidence: Number(confidence.toFixed(2)),
|
|
229
|
+
method: "local_linear_projection",
|
|
230
|
+
remainingAgentRuns: Math.max(0, predictedRuns - runIds.size),
|
|
231
|
+
remainingAgentMinutes: Math.max(0, predictedMinutes - roundInt(totalMinutes)),
|
|
232
|
+
remainingTokens: Math.max(0, predictedTokens - roundInt(totalTokens)),
|
|
233
|
+
remainingCostCents: Math.max(0, predictedCostCents - roundInt(totalCostCents)),
|
|
234
|
+
},
|
|
235
|
+
utilization: {
|
|
236
|
+
runsPct: null,
|
|
237
|
+
minutesPct: null,
|
|
238
|
+
budgetPct: null,
|
|
239
|
+
},
|
|
240
|
+
headroom: {
|
|
241
|
+
agentRunsRemaining: 0,
|
|
242
|
+
agentMinutesRemaining: 0,
|
|
243
|
+
budgetRemainingCents: 0,
|
|
244
|
+
},
|
|
245
|
+
risk: "safe",
|
|
246
|
+
breakdown: {
|
|
247
|
+
sourceClient: mapToBreakdownBuckets(sourceClientBuckets, capitalizeLabel),
|
|
248
|
+
provider: mapToBreakdownBuckets(providerBuckets, capitalizeLabel),
|
|
249
|
+
model: mapToBreakdownBuckets(modelBuckets, (key) => key),
|
|
250
|
+
executionTarget: mapToBreakdownBuckets(executionTargetBuckets, capitalizeLabel),
|
|
251
|
+
},
|
|
252
|
+
velocity: {
|
|
253
|
+
windowDays: daysElapsed,
|
|
254
|
+
dailyAvgRuns: Number((runIds.size / Math.max(daysElapsed, 1)).toFixed(2)),
|
|
255
|
+
dailyAvgMinutes: Number((totalMinutes / Math.max(daysElapsed, 1)).toFixed(2)),
|
|
256
|
+
dailyAvgTokens: Number((totalTokens / Math.max(daysElapsed, 1)).toFixed(2)),
|
|
257
|
+
dailyAvgCostCents: Number((totalCostCents / Math.max(daysElapsed, 1)).toFixed(2)),
|
|
258
|
+
},
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
function collectLocalActivities(deps, input) {
|
|
262
|
+
const merged = [];
|
|
263
|
+
let cursor = null;
|
|
264
|
+
for (let page = 0; page < MAX_ACTIVITY_PAGES; page += 1) {
|
|
265
|
+
const result = deps.listActivityPage({
|
|
266
|
+
limit: PAGE_LIMIT,
|
|
267
|
+
since: input.sinceIso,
|
|
268
|
+
until: input.untilIso,
|
|
269
|
+
cursor,
|
|
270
|
+
});
|
|
271
|
+
if (Array.isArray(result.activities) && result.activities.length > 0) {
|
|
272
|
+
merged.push(...result.activities);
|
|
273
|
+
}
|
|
274
|
+
if (!result.nextCursor || result.nextCursor === cursor)
|
|
275
|
+
break;
|
|
276
|
+
cursor = result.nextCursor;
|
|
277
|
+
}
|
|
278
|
+
return merged;
|
|
279
|
+
}
|
|
280
|
+
async function resolveUsageSummary(deps) {
|
|
281
|
+
try {
|
|
282
|
+
const summary = await deps.client.getUsageControlPlaneSummary();
|
|
283
|
+
return {
|
|
284
|
+
summary,
|
|
285
|
+
source: "cloud",
|
|
286
|
+
warnings: [],
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
catch (err) {
|
|
290
|
+
const warnings = [
|
|
291
|
+
`Cloud usage endpoint unavailable (${deps.safeErrorMessage(err)}). Showing local estimate.`,
|
|
292
|
+
];
|
|
293
|
+
const now = deps.now ? deps.now() : new Date();
|
|
294
|
+
const periodStart = startOfMonthUtc(now);
|
|
295
|
+
const periodEnd = startOfNextMonthUtc(now);
|
|
296
|
+
const activities = collectLocalActivities(deps, {
|
|
297
|
+
sinceIso: periodStart.toISOString(),
|
|
298
|
+
untilIso: periodEnd.toISOString(),
|
|
299
|
+
});
|
|
300
|
+
const summary = buildLocalSummary({
|
|
301
|
+
activities,
|
|
302
|
+
periodStart,
|
|
303
|
+
periodEnd,
|
|
304
|
+
now,
|
|
305
|
+
warnings,
|
|
306
|
+
});
|
|
307
|
+
return {
|
|
308
|
+
summary,
|
|
309
|
+
source: "local_estimate",
|
|
310
|
+
warnings,
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
export function registerUsageRoutes(router, deps) {
|
|
315
|
+
router.add("GET", "usage/control-plane/summary", async ({ res }) => {
|
|
316
|
+
const resolved = await resolveUsageSummary(deps);
|
|
317
|
+
deps.sendJson(res, 200, {
|
|
318
|
+
...resolved.summary,
|
|
319
|
+
source: resolved.source,
|
|
320
|
+
warnings: resolved.warnings,
|
|
321
|
+
});
|
|
322
|
+
}, "Usage control-plane summary");
|
|
323
|
+
router.add("GET", "usage/unified", async ({ res }) => {
|
|
324
|
+
const resolved = await resolveUsageSummary(deps);
|
|
325
|
+
deps.sendJson(res, 200, {
|
|
326
|
+
generatedAt: resolved.summary.generatedAt,
|
|
327
|
+
period: resolved.summary.period,
|
|
328
|
+
plan: resolved.summary.plan,
|
|
329
|
+
actual: resolved.summary.actual,
|
|
330
|
+
predicted: resolved.summary.predicted,
|
|
331
|
+
headroom: resolved.summary.headroom,
|
|
332
|
+
utilization: resolved.summary.utilization,
|
|
333
|
+
risk: resolved.summary.risk,
|
|
334
|
+
breakdown: resolved.summary.breakdown,
|
|
335
|
+
velocity: resolved.summary.velocity,
|
|
336
|
+
source: resolved.source,
|
|
337
|
+
warnings: resolved.warnings,
|
|
338
|
+
});
|
|
339
|
+
}, "Usage unified summary");
|
|
340
|
+
router.add("GET", "usage/forecast", async ({ res }) => {
|
|
341
|
+
const resolved = await resolveUsageSummary(deps);
|
|
342
|
+
deps.sendJson(res, 200, {
|
|
343
|
+
generatedAt: resolved.summary.generatedAt,
|
|
344
|
+
period: resolved.summary.period,
|
|
345
|
+
predicted: resolved.summary.predicted,
|
|
346
|
+
risk: resolved.summary.risk,
|
|
347
|
+
headroom: resolved.summary.headroom,
|
|
348
|
+
utilization: resolved.summary.utilization,
|
|
349
|
+
source: resolved.source,
|
|
350
|
+
warnings: resolved.warnings,
|
|
351
|
+
});
|
|
352
|
+
}, "Usage forecast summary");
|
|
353
|
+
router.add("*", "usage/control-plane/summary", ({ res }) => {
|
|
354
|
+
deps.sendJson(res, 405, { ok: false, error: "Method not allowed" });
|
|
355
|
+
}, "Reject unsupported methods for usage/control-plane/summary");
|
|
356
|
+
router.add("*", "usage/unified", ({ res }) => {
|
|
357
|
+
deps.sendJson(res, 405, { ok: false, error: "Method not allowed" });
|
|
358
|
+
}, "Reject unsupported methods for usage/unified");
|
|
359
|
+
router.add("*", "usage/forecast", ({ res }) => {
|
|
360
|
+
deps.sendJson(res, 405, { ok: false, error: "Method not allowed" });
|
|
361
|
+
}, "Reject unsupported methods for usage/forecast");
|
|
362
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Router } from "../router.js";
|
|
2
|
+
type RegisterWorkArtifactsRoutesDeps<TRes> = {
|
|
3
|
+
rawRequest: (method: "GET" | "POST" | "PATCH" | "PUT" | "DELETE", path: string, body?: unknown) => Promise<unknown>;
|
|
4
|
+
buildLocalArtifactDetailFallback: (artifactId: string, warning: string) => Record<string, unknown> | null;
|
|
5
|
+
sendJson: (res: TRes, status: number, payload: unknown) => void;
|
|
6
|
+
safeErrorMessage: (err: unknown) => string;
|
|
7
|
+
};
|
|
8
|
+
export declare function registerWorkArtifactsRoutes<TReq, TRes>(router: Router<Record<string, never>, TReq, TRes>, deps: RegisterWorkArtifactsRoutesDeps<TRes>): void;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export function registerWorkArtifactsRoutes(router, deps) {
|
|
2
|
+
router.add("GET", "work-artifacts/by-entity", async ({ query, res }) => {
|
|
3
|
+
const qs = query.toString();
|
|
4
|
+
try {
|
|
5
|
+
const path = `/api/client/artifacts/by-entity${qs ? `?${qs}` : ""}`;
|
|
6
|
+
const data = await deps.rawRequest("GET", path);
|
|
7
|
+
deps.sendJson(res, 200, data);
|
|
8
|
+
}
|
|
9
|
+
catch (err) {
|
|
10
|
+
const warning = deps.safeErrorMessage(err);
|
|
11
|
+
try {
|
|
12
|
+
const fallbackPath = `/api/work-artifacts/by-entity${qs ? `?${qs}` : ""}`;
|
|
13
|
+
const fallback = await deps.rawRequest("GET", fallbackPath);
|
|
14
|
+
deps.sendJson(res, 200, fallback);
|
|
15
|
+
}
|
|
16
|
+
catch (fallbackErr) {
|
|
17
|
+
deps.sendJson(res, 502, {
|
|
18
|
+
error: deps.safeErrorMessage(fallbackErr),
|
|
19
|
+
warning,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}, "Work artifacts by entity");
|
|
24
|
+
router.add("GET", "artifacts/*", async ({ path, res }) => {
|
|
25
|
+
const artifactDetailMatch = path.match(/^artifacts\/([^/]+)$/);
|
|
26
|
+
if (!artifactDetailMatch) {
|
|
27
|
+
deps.sendJson(res, 404, { error: "Unknown API endpoint" });
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const artifactId = decodeURIComponent(artifactDetailMatch[1]);
|
|
31
|
+
try {
|
|
32
|
+
const upstreamPath = `/api/client/artifacts/${encodeURIComponent(artifactId)}`;
|
|
33
|
+
const data = await deps.rawRequest("GET", upstreamPath);
|
|
34
|
+
deps.sendJson(res, 200, data);
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
const warning = deps.safeErrorMessage(err);
|
|
38
|
+
try {
|
|
39
|
+
const legacyPath = `/api/artifacts/${encodeURIComponent(artifactId)}`;
|
|
40
|
+
const legacyData = await deps.rawRequest("GET", legacyPath);
|
|
41
|
+
deps.sendJson(res, 200, legacyData);
|
|
42
|
+
}
|
|
43
|
+
catch (legacyErr) {
|
|
44
|
+
const legacyWarning = `${warning}; legacy route failed: ${deps.safeErrorMessage(legacyErr)}`;
|
|
45
|
+
const fallback = deps.buildLocalArtifactDetailFallback(artifactId, legacyWarning);
|
|
46
|
+
if (fallback) {
|
|
47
|
+
deps.sendJson(res, 200, fallback);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
deps.sendJson(res, 502, { error: legacyWarning });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}, "Artifact detail");
|
|
55
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { OutboxAdapter } from "../adapters/outbox.js";
|
|
2
|
+
import type { OrgXClient } from "../api.js";
|
|
3
|
+
import type { OrgXConfig, OrgSnapshot } from "../types.js";
|
|
4
|
+
/**
|
|
5
|
+
* SharedState is the dependency bag used by extracted HTTP route modules.
|
|
6
|
+
* Start intentionally small and widen as route groups are migrated.
|
|
7
|
+
*/
|
|
8
|
+
export interface SharedState {
|
|
9
|
+
client: OrgXClient;
|
|
10
|
+
config: OrgXConfig;
|
|
11
|
+
outbox: OutboxAdapter;
|
|
12
|
+
getCachedSnapshot: () => OrgSnapshot | null;
|
|
13
|
+
doSync: () => Promise<void>;
|
|
14
|
+
tickAllAutoContinue: () => Promise<void>;
|
|
15
|
+
[key: string]: unknown;
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/http-handler.d.ts
CHANGED
|
@@ -1,88 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* HTTP Handler — Serves the React dashboard SPA and API proxy endpoints.
|
|
3
|
-
*
|
|
4
|
-
* Registered at the `/orgx` prefix. Handles:
|
|
5
|
-
* /orgx/live → dashboard SPA (index.html)
|
|
6
|
-
* /orgx/live/assets/* → static assets (JS, CSS, images)
|
|
7
|
-
* /orgx/api/status → org status summary
|
|
8
|
-
* /orgx/api/agents → agent states
|
|
9
|
-
* /orgx/api/activity → activity feed
|
|
10
|
-
* /orgx/api/initiatives → initiative data
|
|
11
|
-
* /orgx/api/health → plugin diagnostics + outbox/sync status
|
|
12
|
-
* /orgx/api/onboarding → onboarding / config state
|
|
13
|
-
* /orgx/api/agent-suite/status → suite provisioning plan (OpenClaw-local)
|
|
14
|
-
* /orgx/api/agent-suite/install → install/update suite (OpenClaw-local)
|
|
15
|
-
* /orgx/api/delegation/preflight → delegation preflight
|
|
16
|
-
* /orgx/api/runs/:id/checkpoints → list/create checkpoints
|
|
17
|
-
* /orgx/api/runs/:id/checkpoints/:checkpointId/restore → restore checkpoint
|
|
18
|
-
* /orgx/api/runs/:id/actions/:action → run control action
|
|
19
|
-
*/
|
|
20
|
-
import type { OrgXClient } from "./api.js";
|
|
21
|
-
import type { OnboardingState, OrgXConfig, OrgSnapshot } from "./types.js";
|
|
22
|
-
import { type OutboxAdapter } from "./adapters/outbox.js";
|
|
23
|
-
type OpenClawAdapter = {
|
|
24
|
-
listAgents?: () => Promise<Array<Record<string, unknown>>>;
|
|
25
|
-
spawnAgentTurn?: (input: {
|
|
26
|
-
agentId: string;
|
|
27
|
-
sessionId: string;
|
|
28
|
-
message: string;
|
|
29
|
-
thinking?: string | null;
|
|
30
|
-
}) => {
|
|
31
|
-
pid: number | null;
|
|
32
|
-
};
|
|
33
|
-
stopDetachedProcess?: (pid: number) => Promise<{
|
|
34
|
-
stopped: boolean;
|
|
35
|
-
wasRunning: boolean;
|
|
36
|
-
}>;
|
|
37
|
-
isPidAlive?: (pid: number) => boolean;
|
|
38
|
-
};
|
|
39
|
-
interface PluginRequest {
|
|
40
|
-
method?: string;
|
|
41
|
-
url?: string;
|
|
42
|
-
headers: Record<string, string | string[] | undefined>;
|
|
43
|
-
body?: unknown;
|
|
44
|
-
on?: (event: string, listener: (...args: unknown[]) => void) => void;
|
|
45
|
-
once?: (event: string, listener: (...args: unknown[]) => void) => void;
|
|
46
|
-
}
|
|
47
|
-
interface PluginResponse {
|
|
48
|
-
writeHead(status: number, headers?: Record<string, string>): void;
|
|
49
|
-
end(body?: string | Buffer): void;
|
|
50
|
-
write?(chunk: string | Buffer): boolean | void;
|
|
51
|
-
on?: (event: string, listener: (...args: unknown[]) => void) => void;
|
|
52
|
-
once?: (event: string, listener: (...args: unknown[]) => void) => void;
|
|
53
|
-
writableEnded?: boolean;
|
|
54
|
-
}
|
|
55
|
-
interface OnboardingController {
|
|
56
|
-
getState: () => OnboardingState;
|
|
57
|
-
startPairing: (input: {
|
|
58
|
-
openclawVersion?: string;
|
|
59
|
-
platform?: string;
|
|
60
|
-
deviceName?: string;
|
|
61
|
-
}) => Promise<{
|
|
62
|
-
pairingId: string;
|
|
63
|
-
connectUrl: string;
|
|
64
|
-
expiresAt: string;
|
|
65
|
-
pollIntervalMs: number;
|
|
66
|
-
state: OnboardingState;
|
|
67
|
-
}>;
|
|
68
|
-
getStatus: () => Promise<OnboardingState>;
|
|
69
|
-
submitManualKey: (input: {
|
|
70
|
-
apiKey: string;
|
|
71
|
-
userId?: string;
|
|
72
|
-
}) => Promise<OnboardingState>;
|
|
73
|
-
disconnect: () => Promise<OnboardingState>;
|
|
74
|
-
}
|
|
75
|
-
interface DiagnosticsProvider {
|
|
76
|
-
getHealth?: (input?: {
|
|
77
|
-
probeRemote?: boolean;
|
|
78
|
-
}) => Promise<unknown>;
|
|
79
|
-
}
|
|
80
|
-
export declare function createHttpHandler(config: OrgXConfig & {
|
|
81
|
-
dashboardEnabled?: boolean;
|
|
82
|
-
pluginVersion?: string;
|
|
83
|
-
installationId?: string | null;
|
|
84
|
-
}, client: OrgXClient, getSnapshot: () => OrgSnapshot | null, onboarding: OnboardingController, diagnostics?: DiagnosticsProvider, adapters?: {
|
|
85
|
-
outbox?: OutboxAdapter;
|
|
86
|
-
openclaw?: OpenClawAdapter;
|
|
87
|
-
}): (req: PluginRequest, res: PluginResponse) => Promise<boolean>;
|
|
88
|
-
export {};
|
|
1
|
+
export { createHttpHandler } from "./http/index.js";
|