@useorgx/openclaw-plugin 0.4.8 → 0.4.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/dashboard/dist/assets/B5NEElEI.css +1 -0
  2. package/dashboard/dist/assets/BhapSNAs.js +215 -0
  3. package/dashboard/dist/assets/{BNeJ0kpF.js → iFdvE7lx.js} +1 -1
  4. package/dashboard/dist/assets/{CUV9IHHi.js → jRJsmpYM.js} +1 -1
  5. package/dashboard/dist/index.html +2 -2
  6. package/dist/activity-store.js +4 -18
  7. package/dist/agent-context-store.js +5 -25
  8. package/dist/agent-run-store.js +5 -25
  9. package/dist/agent-suite.js +1 -8
  10. package/dist/auth/flows.d.ts +47 -0
  11. package/dist/auth/flows.js +169 -0
  12. package/dist/auth-store.js +6 -26
  13. package/dist/byok-store.js +5 -19
  14. package/dist/cli/orgx.d.ts +66 -0
  15. package/dist/cli/orgx.js +91 -0
  16. package/dist/config/refresh.d.ts +32 -0
  17. package/dist/config/refresh.js +55 -0
  18. package/dist/config/resolution.d.ts +37 -0
  19. package/dist/config/resolution.js +178 -0
  20. package/dist/contracts/shared-types.d.ts +147 -0
  21. package/dist/contracts/shared-types.js +3 -0
  22. package/dist/contracts/types.d.ts +1 -134
  23. package/dist/contracts/types.js +5 -0
  24. package/dist/entities/auto-assignment.d.ts +36 -0
  25. package/dist/entities/auto-assignment.js +115 -0
  26. package/dist/entity-comment-store.js +5 -25
  27. package/dist/hash-utils.d.ts +2 -0
  28. package/dist/hash-utils.js +12 -0
  29. package/dist/http/helpers/activity-headline.d.ts +10 -0
  30. package/dist/http/helpers/activity-headline.js +192 -0
  31. package/dist/http/helpers/artifact-fallback.d.ts +13 -0
  32. package/dist/http/helpers/artifact-fallback.js +148 -0
  33. package/dist/http/helpers/auto-continue-engine.d.ts +298 -0
  34. package/dist/http/helpers/auto-continue-engine.js +1218 -0
  35. package/dist/http/helpers/autopilot-operations.d.ts +157 -0
  36. package/dist/http/helpers/autopilot-operations.js +403 -0
  37. package/dist/http/helpers/autopilot-runtime.d.ts +42 -0
  38. package/dist/http/helpers/autopilot-runtime.js +319 -0
  39. package/dist/http/helpers/autopilot-slice-utils.d.ts +38 -0
  40. package/dist/http/helpers/autopilot-slice-utils.js +476 -0
  41. package/dist/http/helpers/decision-mapper.d.ts +12 -0
  42. package/dist/http/helpers/decision-mapper.js +44 -0
  43. package/dist/http/helpers/dispatch-lifecycle.d.ts +102 -0
  44. package/dist/http/helpers/dispatch-lifecycle.js +604 -0
  45. package/dist/http/helpers/hash-utils.d.ts +1 -0
  46. package/dist/http/helpers/hash-utils.js +1 -0
  47. package/dist/http/helpers/kickoff-context.d.ts +12 -0
  48. package/dist/http/helpers/kickoff-context.js +154 -0
  49. package/dist/http/helpers/mission-control.d.ts +94 -0
  50. package/dist/http/helpers/mission-control.js +894 -0
  51. package/dist/http/helpers/openclaw-cli.d.ts +37 -0
  52. package/dist/http/helpers/openclaw-cli.js +283 -0
  53. package/dist/http/helpers/runtime-sse.d.ts +20 -0
  54. package/dist/http/helpers/runtime-sse.js +110 -0
  55. package/dist/http/helpers/value-utils.d.ts +6 -0
  56. package/dist/http/helpers/value-utils.js +67 -0
  57. package/dist/http/index.d.ts +88 -0
  58. package/dist/http/index.js +2353 -0
  59. package/dist/http/router.d.ts +23 -0
  60. package/dist/http/router.js +23 -0
  61. package/dist/http/routes/agent-control.d.ts +79 -0
  62. package/dist/http/routes/agent-control.js +684 -0
  63. package/dist/http/routes/agent-suite.d.ts +29 -0
  64. package/dist/http/routes/agent-suite.js +198 -0
  65. package/dist/http/routes/agents-catalog.d.ts +40 -0
  66. package/dist/http/routes/agents-catalog.js +83 -0
  67. package/dist/http/routes/billing.d.ts +23 -0
  68. package/dist/http/routes/billing.js +55 -0
  69. package/dist/http/routes/debug.d.ts +14 -0
  70. package/dist/http/routes/debug.js +21 -0
  71. package/dist/http/routes/decision-actions.d.ts +13 -0
  72. package/dist/http/routes/decision-actions.js +66 -0
  73. package/dist/http/routes/delegation.d.ts +19 -0
  74. package/dist/http/routes/delegation.js +32 -0
  75. package/dist/http/routes/entities.d.ts +47 -0
  76. package/dist/http/routes/entities.js +152 -0
  77. package/dist/http/routes/entity-dynamic.d.ts +25 -0
  78. package/dist/http/routes/entity-dynamic.js +191 -0
  79. package/dist/http/routes/health.d.ts +22 -0
  80. package/dist/http/routes/health.js +49 -0
  81. package/dist/http/routes/live-legacy.d.ts +110 -0
  82. package/dist/http/routes/live-legacy.js +598 -0
  83. package/dist/http/routes/live-misc.d.ts +69 -0
  84. package/dist/http/routes/live-misc.js +206 -0
  85. package/dist/http/routes/live-snapshot.d.ts +90 -0
  86. package/dist/http/routes/live-snapshot.js +297 -0
  87. package/dist/http/routes/mission-control-actions.d.ts +83 -0
  88. package/dist/http/routes/mission-control-actions.js +541 -0
  89. package/dist/http/routes/mission-control-read.d.ts +28 -0
  90. package/dist/http/routes/mission-control-read.js +67 -0
  91. package/dist/http/routes/onboarding.d.ts +34 -0
  92. package/dist/http/routes/onboarding.js +101 -0
  93. package/dist/http/routes/run-control.d.ts +24 -0
  94. package/dist/http/routes/run-control.js +86 -0
  95. package/dist/http/routes/runtime-hooks.d.ts +69 -0
  96. package/dist/http/routes/runtime-hooks.js +437 -0
  97. package/dist/http/routes/settings-byok.d.ts +23 -0
  98. package/dist/http/routes/settings-byok.js +163 -0
  99. package/dist/http/routes/summary.d.ts +18 -0
  100. package/dist/http/routes/summary.js +42 -0
  101. package/dist/http/routes/work-artifacts.d.ts +9 -0
  102. package/dist/http/routes/work-artifacts.js +36 -0
  103. package/dist/http/shared-state.d.ts +16 -0
  104. package/dist/http/shared-state.js +1 -0
  105. package/dist/http-handler.d.ts +1 -88
  106. package/dist/http-handler.js +1 -10605
  107. package/dist/index.js +108 -2243
  108. package/dist/json-utils.d.ts +1 -0
  109. package/dist/json-utils.js +8 -0
  110. package/dist/next-up-queue-store.js +4 -18
  111. package/dist/runtime-instance-store.js +5 -31
  112. package/dist/services/background.d.ts +23 -0
  113. package/dist/services/background.js +23 -0
  114. package/dist/services/instrumentation.d.ts +29 -0
  115. package/dist/services/instrumentation.js +136 -0
  116. package/dist/snapshot-store.js +5 -25
  117. package/dist/stores/json-store.d.ts +11 -0
  118. package/dist/stores/json-store.js +42 -0
  119. package/dist/sync/outbox-replay.d.ts +55 -0
  120. package/dist/sync/outbox-replay.js +514 -0
  121. package/dist/tools/core-tools.d.ts +76 -0
  122. package/dist/tools/core-tools.js +1005 -0
  123. package/package.json +1 -1
  124. package/dashboard/dist/assets/BzkiMPmM.js +0 -215
  125. package/dashboard/dist/assets/Ie7d9Iq2.css +0 -1
@@ -0,0 +1,152 @@
1
+ export function registerEntitiesRoutes(router, deps) {
2
+ router.add("POST", "entities", async ({ req, res }) => {
3
+ try {
4
+ const payload = await deps.parseJsonRequest(req);
5
+ const type = deps.pickString(payload, ["type"]);
6
+ const title = deps.pickString(payload, ["title", "name"]);
7
+ if (!type || !title) {
8
+ deps.sendJson(res, 400, {
9
+ error: "Both 'type' and 'title' are required.",
10
+ });
11
+ return;
12
+ }
13
+ const data = deps.normalizeEntityMutationPayload({ ...payload, title });
14
+ delete data.type;
15
+ let entity = await deps.client.createEntity(type, data);
16
+ let autoAssignment = null;
17
+ if (type === "initiative" || type === "workstream") {
18
+ const entityRecord = entity;
19
+ autoAssignment = await deps.resolveAutoAssignments({
20
+ entityId: String(entityRecord.id ?? ""),
21
+ entityType: type,
22
+ initiativeId: type === "initiative"
23
+ ? String(entityRecord.id ?? "")
24
+ : deps.pickString(data, ["initiative_id", "initiativeId"]),
25
+ title: deps.pickString(entityRecord, ["title", "name"]) ?? title ?? "Untitled",
26
+ summary: deps.pickString(entityRecord, ["summary", "description", "context"]) ?? null,
27
+ });
28
+ if (autoAssignment.updated_entity) {
29
+ entity = autoAssignment.updated_entity;
30
+ }
31
+ }
32
+ deps.sendJson(res, 201, { ok: true, entity, auto_assignment: autoAssignment });
33
+ }
34
+ catch (err) {
35
+ deps.sendJson(res, 500, {
36
+ error: deps.safeErrorMessage(err),
37
+ });
38
+ }
39
+ }, "Create entity");
40
+ router.add("PATCH", "entities", async ({ req, res }) => {
41
+ let payload = {};
42
+ let type = null;
43
+ let id = null;
44
+ let requestedStatus = null;
45
+ try {
46
+ payload = await deps.parseJsonRequest(req);
47
+ type = deps.pickString(payload, ["type"]);
48
+ id = deps.pickString(payload, ["id"]);
49
+ requestedStatus = deps.pickString(payload, ["status"]);
50
+ if (!type || !id) {
51
+ deps.sendJson(res, 400, {
52
+ error: "Both 'type' and 'id' are required for PATCH.",
53
+ });
54
+ return;
55
+ }
56
+ const updates = { ...payload };
57
+ delete updates.type;
58
+ delete updates.id;
59
+ const normalizedType = type.trim().toLowerCase();
60
+ const normalizedUpdates = deps.normalizeEntityMutationPayload(updates);
61
+ const entity = await deps.client.updateEntity(type, id, normalizedUpdates);
62
+ if (normalizedType === "initiative") {
63
+ deps.clearLocalInitiativeStatusOverride(id);
64
+ }
65
+ deps.sendJson(res, 200, { ok: true, entity });
66
+ }
67
+ catch (err) {
68
+ if (type?.trim().toLowerCase() === "initiative" &&
69
+ id &&
70
+ requestedStatus &&
71
+ deps.isUnauthorizedOrgxError(err)) {
72
+ deps.setLocalInitiativeStatusOverride(id, requestedStatus);
73
+ deps.sendJson(res, 200, {
74
+ ok: true,
75
+ localFallback: true,
76
+ warning: deps.safeErrorMessage(err),
77
+ entity: {
78
+ id,
79
+ type,
80
+ status: requestedStatus,
81
+ },
82
+ });
83
+ return;
84
+ }
85
+ deps.sendJson(res, 500, {
86
+ error: deps.safeErrorMessage(err),
87
+ });
88
+ }
89
+ }, "Update entity");
90
+ async function renderEntityList(query, res) {
91
+ const type = query.get("type");
92
+ if (!type) {
93
+ deps.sendJson(res, 400, {
94
+ error: "Query parameter 'type' is required for GET /entities.",
95
+ });
96
+ return;
97
+ }
98
+ const status = query.get("status") ?? undefined;
99
+ const initiativeId = query.get("initiative_id") ?? undefined;
100
+ const limit = query.get("limit") ? Number(query.get("limit")) : undefined;
101
+ try {
102
+ const data = await deps.client.listEntities(type, {
103
+ status,
104
+ initiative_id: initiativeId,
105
+ limit: Number.isFinite(limit) ? limit : undefined,
106
+ });
107
+ if (type.trim().toLowerCase() === "initiative") {
108
+ const payload = data;
109
+ const rows = Array.isArray(payload.data)
110
+ ? payload.data.filter((row) => Boolean(row && typeof row === "object"))
111
+ : [];
112
+ deps.sendJson(res, 200, {
113
+ ...payload,
114
+ data: deps.applyLocalInitiativeOverrides(rows),
115
+ });
116
+ return;
117
+ }
118
+ deps.sendJson(res, 200, data);
119
+ }
120
+ catch (err) {
121
+ if (type.trim().toLowerCase() === "initiative" && deps.isUnauthorizedOrgxError(err)) {
122
+ const snapshotInitiatives = deps
123
+ .formatInitiatives(deps.getSnapshot())
124
+ .map((item) => ({
125
+ id: item.id,
126
+ title: item.title,
127
+ name: item.title,
128
+ summary: null,
129
+ status: item.status,
130
+ progress_pct: item.progress ?? null,
131
+ created_at: null,
132
+ updated_at: null,
133
+ }))
134
+ .filter((item) => (initiativeId ? item.id === initiativeId : true));
135
+ deps.sendJson(res, 200, {
136
+ data: deps.applyLocalInitiativeOverrides(snapshotInitiatives),
137
+ localFallback: true,
138
+ warning: deps.safeErrorMessage(err),
139
+ });
140
+ return;
141
+ }
142
+ deps.sendJson(res, 500, {
143
+ error: deps.safeErrorMessage(err),
144
+ });
145
+ }
146
+ }
147
+ router.add("GET", "entities", async ({ query, res }) => renderEntityList(query, res), "List entities");
148
+ router.add("HEAD", "entities", async ({ query, res }) => renderEntityList(query, res), "List entities (HEAD)");
149
+ router.add("*", "entities", ({ res }) => {
150
+ deps.sendJson(res, 405, { error: "Method not allowed" });
151
+ }, "Reject unsupported methods for entities");
152
+ }
@@ -0,0 +1,25 @@
1
+ import type { Router } from "../router.js";
2
+ type JsonRecord = Record<string, unknown>;
3
+ type RegisterEntityDynamicRoutesDeps<TReq, TRes> = {
4
+ parseJsonRequest: (req: TReq) => Promise<JsonRecord>;
5
+ pickString: (input: Record<string, unknown>, keys: string[]) => string | null;
6
+ rawRequest: (method: "GET" | "POST" | "PATCH" | "PUT" | "DELETE", path: string, body?: unknown) => Promise<unknown>;
7
+ listEntityComments: (entityType: string, entityId: string) => unknown[];
8
+ mergeEntityComments: (remote: unknown, local: unknown[]) => unknown[];
9
+ appendEntityComment: (input: {
10
+ entityType: string;
11
+ entityId: string;
12
+ body: string;
13
+ commentType: string;
14
+ severity: string;
15
+ tags: unknown;
16
+ }) => unknown;
17
+ updateEntity: (type: string, id: string, updates: Record<string, unknown>) => Promise<unknown>;
18
+ setLocalInitiativeStatusOverride: (initiativeId: string, status: string) => void;
19
+ clearLocalInitiativeStatusOverride: (initiativeId: string) => void;
20
+ isUnauthorizedOrgxError: (err: unknown) => boolean;
21
+ sendJson: (res: TRes, status: number, payload: unknown) => void;
22
+ safeErrorMessage: (err: unknown) => string;
23
+ };
24
+ export declare function registerEntityDynamicRoutes<TReq, TRes>(router: Router<Record<string, never>, TReq, TRes>, deps: RegisterEntityDynamicRoutesDeps<TReq, TRes>): void;
25
+ export {};
@@ -0,0 +1,191 @@
1
+ export function registerEntityDynamicRoutes(router, deps) {
2
+ router.add("*", "entities/*", async ({ req, res, path }) => {
3
+ const method = (req.method ?? "GET").toUpperCase();
4
+ const entityCommentsMatch = path.match(/^entities\/([^/]+)\/([^/]+)\/comments$/);
5
+ if (entityCommentsMatch) {
6
+ if (method !== "GET" && method !== "POST") {
7
+ deps.sendJson(res, 405, { error: "Method not allowed" });
8
+ return;
9
+ }
10
+ try {
11
+ const entityType = decodeURIComponent(entityCommentsMatch[1]);
12
+ const entityId = decodeURIComponent(entityCommentsMatch[2]);
13
+ if (!entityType || !entityId) {
14
+ deps.sendJson(res, 400, {
15
+ ok: false,
16
+ error: "entity type and id are required",
17
+ });
18
+ return;
19
+ }
20
+ const commentsPath = `/api/entities/${encodeURIComponent(entityType)}/${encodeURIComponent(entityId)}/comments`;
21
+ if (method === "GET") {
22
+ const local = deps.listEntityComments(entityType, entityId);
23
+ try {
24
+ const data = (await deps.rawRequest("GET", commentsPath));
25
+ const comments = deps.mergeEntityComments(data?.comments, local);
26
+ if (data && typeof data === "object") {
27
+ deps.sendJson(res, 200, { ...data, comments });
28
+ }
29
+ else {
30
+ deps.sendJson(res, 200, { status: "success", comments, nextCursor: null });
31
+ }
32
+ }
33
+ catch (err) {
34
+ deps.sendJson(res, 200, {
35
+ status: "success",
36
+ comments: local,
37
+ nextCursor: null,
38
+ localFallback: true,
39
+ warning: deps.safeErrorMessage(err),
40
+ });
41
+ }
42
+ return;
43
+ }
44
+ const payload = await deps.parseJsonRequest(req);
45
+ const body = deps.pickString(payload, ["body", "comment", "text", "message"]) ?? "";
46
+ if (!body.trim()) {
47
+ deps.sendJson(res, 400, { ok: false, error: "comment body is required" });
48
+ return;
49
+ }
50
+ const commentType = deps.pickString(payload, ["comment_type", "commentType", "type"]) ?? "note";
51
+ const severity = deps.pickString(payload, ["severity", "level"]) ?? "info";
52
+ const tags = payload.tags;
53
+ const normalizedPayload = {
54
+ body,
55
+ comment_type: commentType,
56
+ severity,
57
+ tags,
58
+ parent_comment_id: null,
59
+ };
60
+ try {
61
+ const data = await deps.rawRequest("POST", commentsPath, normalizedPayload);
62
+ deps.sendJson(res, 200, data);
63
+ }
64
+ catch (err) {
65
+ const warning = deps.safeErrorMessage(err);
66
+ try {
67
+ const comment = deps.appendEntityComment({
68
+ entityType,
69
+ entityId,
70
+ body,
71
+ commentType,
72
+ severity,
73
+ tags,
74
+ });
75
+ deps.sendJson(res, 200, {
76
+ status: "success",
77
+ comment,
78
+ localFallback: true,
79
+ warning,
80
+ });
81
+ }
82
+ catch (localErr) {
83
+ deps.sendJson(res, 500, {
84
+ ok: false,
85
+ error: warning || "Unable to save comment",
86
+ localError: deps.safeErrorMessage(localErr),
87
+ });
88
+ }
89
+ }
90
+ }
91
+ catch (err) {
92
+ deps.sendJson(res, 500, { ok: false, error: deps.safeErrorMessage(err) });
93
+ }
94
+ return;
95
+ }
96
+ const entityActionMatch = path.match(/^entities\/([^/]+)\/([^/]+)\/([^/]+)$/);
97
+ if (entityActionMatch) {
98
+ if (method !== "POST") {
99
+ deps.sendJson(res, 405, { error: "Method not allowed" });
100
+ return;
101
+ }
102
+ try {
103
+ const entityType = decodeURIComponent(entityActionMatch[1]);
104
+ const entityId = decodeURIComponent(entityActionMatch[2]);
105
+ const entityAction = decodeURIComponent(entityActionMatch[3]);
106
+ const payload = await deps.parseJsonRequest(req);
107
+ const normalizedEntityType = entityType.trim().toLowerCase();
108
+ if (entityAction === "delete") {
109
+ const deleteStatus = normalizedEntityType === "initiative" ? "archived" : "deleted";
110
+ try {
111
+ const entity = await deps.updateEntity(entityType, entityId, {
112
+ status: deleteStatus,
113
+ });
114
+ if (normalizedEntityType === "initiative") {
115
+ deps.clearLocalInitiativeStatusOverride(entityId);
116
+ }
117
+ deps.sendJson(res, 200, { ok: true, entity, deletedAsStatus: deleteStatus });
118
+ }
119
+ catch (err) {
120
+ if (normalizedEntityType === "initiative" &&
121
+ deps.isUnauthorizedOrgxError(err)) {
122
+ deps.setLocalInitiativeStatusOverride(entityId, deleteStatus);
123
+ deps.sendJson(res, 200, {
124
+ ok: true,
125
+ localFallback: true,
126
+ warning: deps.safeErrorMessage(err),
127
+ entity: {
128
+ id: entityId,
129
+ type: entityType,
130
+ status: deleteStatus,
131
+ },
132
+ deletedAsStatus: deleteStatus,
133
+ });
134
+ return;
135
+ }
136
+ throw err;
137
+ }
138
+ return;
139
+ }
140
+ const statusMap = {
141
+ start: "in_progress",
142
+ complete: "done",
143
+ block: "blocked",
144
+ unblock: "in_progress",
145
+ pause: "paused",
146
+ resume: "active",
147
+ };
148
+ const newStatus = statusMap[entityAction];
149
+ if (!newStatus) {
150
+ deps.sendJson(res, 400, {
151
+ error: `Unknown entity action: ${entityAction}`,
152
+ });
153
+ return;
154
+ }
155
+ try {
156
+ const entity = await deps.updateEntity(entityType, entityId, {
157
+ status: newStatus,
158
+ ...(payload.force ? { force: true } : {}),
159
+ });
160
+ if (normalizedEntityType === "initiative") {
161
+ deps.clearLocalInitiativeStatusOverride(entityId);
162
+ }
163
+ deps.sendJson(res, 200, { ok: true, entity });
164
+ }
165
+ catch (err) {
166
+ if (normalizedEntityType === "initiative" &&
167
+ deps.isUnauthorizedOrgxError(err)) {
168
+ deps.setLocalInitiativeStatusOverride(entityId, newStatus);
169
+ deps.sendJson(res, 200, {
170
+ ok: true,
171
+ localFallback: true,
172
+ warning: deps.safeErrorMessage(err),
173
+ entity: {
174
+ id: entityId,
175
+ type: entityType,
176
+ status: newStatus,
177
+ },
178
+ });
179
+ return;
180
+ }
181
+ throw err;
182
+ }
183
+ }
184
+ catch (err) {
185
+ deps.sendJson(res, 500, { error: deps.safeErrorMessage(err) });
186
+ }
187
+ return;
188
+ }
189
+ deps.sendJson(res, 404, { error: "Unknown API endpoint" });
190
+ }, "Dynamic entity comments/actions");
191
+ }
@@ -0,0 +1,22 @@
1
+ import type { Router } from "../router.js";
2
+ type HealthDiagnostics = {
3
+ getHealth?: (input: {
4
+ probeRemote: boolean;
5
+ }) => Promise<unknown>;
6
+ };
7
+ type HealthRouteDeps<TRes> = {
8
+ diagnostics?: HealthDiagnostics;
9
+ readOutboxSummary: () => Promise<{
10
+ pendingTotal: number;
11
+ pendingByQueue: Record<string, number>;
12
+ oldestEventAt: string | null;
13
+ newestEventAt: string | null;
14
+ }>;
15
+ parseBooleanQuery: (value: string | null) => boolean;
16
+ baseUrl: string;
17
+ hasApiKey: boolean;
18
+ sendJson: (res: TRes, status: number, payload: unknown) => void;
19
+ safeErrorMessage: (err: unknown) => string;
20
+ };
21
+ export declare function registerHealthRoutes<TReq, TRes>(router: Router<Record<string, never>, TReq, TRes>, deps: HealthRouteDeps<TRes>): void;
22
+ export {};
@@ -0,0 +1,49 @@
1
+ export function registerHealthRoutes(router, deps) {
2
+ async function handleHealth(query, res) {
3
+ const probeRemote = deps.parseBooleanQuery(query.get("probe") ?? query.get("probe_remote"));
4
+ try {
5
+ if (deps.diagnostics?.getHealth) {
6
+ const health = await deps.diagnostics.getHealth({ probeRemote });
7
+ deps.sendJson(res, 200, health);
8
+ return;
9
+ }
10
+ const outbox = await deps.readOutboxSummary();
11
+ deps.sendJson(res, 200, {
12
+ ok: true,
13
+ status: "ok",
14
+ generatedAt: new Date().toISOString(),
15
+ checks: [],
16
+ plugin: {
17
+ baseUrl: deps.baseUrl,
18
+ },
19
+ auth: {
20
+ hasApiKey: deps.hasApiKey,
21
+ },
22
+ outbox: {
23
+ pendingTotal: outbox.pendingTotal,
24
+ pendingByQueue: outbox.pendingByQueue,
25
+ oldestEventAt: outbox.oldestEventAt,
26
+ newestEventAt: outbox.newestEventAt,
27
+ replayStatus: "idle",
28
+ lastReplayAttemptAt: null,
29
+ lastReplaySuccessAt: null,
30
+ lastReplayFailureAt: null,
31
+ lastReplayError: null,
32
+ },
33
+ remote: {
34
+ enabled: false,
35
+ reachable: null,
36
+ latencyMs: null,
37
+ error: null,
38
+ },
39
+ });
40
+ }
41
+ catch (err) {
42
+ deps.sendJson(res, 500, {
43
+ error: deps.safeErrorMessage(err),
44
+ });
45
+ }
46
+ }
47
+ router.add("GET", "health", async ({ query, res }) => handleHealth(query, res), "Health summary");
48
+ router.add("HEAD", "health", async ({ query, res }) => handleHealth(query, res), "Health summary (HEAD)");
49
+ }
@@ -0,0 +1,110 @@
1
+ import type { LiveActivityItem, SessionTreeResponse } from "../../types.js";
2
+ import type { RuntimeInstanceRecord } from "../../runtime-instance-store.js";
3
+ import type { AgentLaunchContext, RunLaunchContext } from "../../agent-context-store.js";
4
+ import type { Router } from "../router.js";
5
+ type LocalSnapshot = Awaited<ReturnType<typeof import("../../local-openclaw.js").loadLocalOpenClawSnapshot>>;
6
+ type AgentContextBundle = {
7
+ agents: Record<string, AgentLaunchContext>;
8
+ runs?: Record<string, RunLaunchContext>;
9
+ };
10
+ type LocalLiveActivity = {
11
+ activities: LiveActivityItem[];
12
+ total: number;
13
+ };
14
+ type LiveActivityPage = {
15
+ activities: LiveActivityItem[];
16
+ cursor?: string | null;
17
+ nextCursor?: string | null;
18
+ prevCursor?: string | null;
19
+ hasMore?: boolean;
20
+ };
21
+ type LiveSessionsResponse = SessionTreeResponse;
22
+ type LiveActivityResponse = {
23
+ activities: LiveActivityItem[];
24
+ total?: number;
25
+ } & Record<string, unknown>;
26
+ type RouteReqLike = {
27
+ on?: (event: string, listener: () => void) => void;
28
+ };
29
+ type RouteResLike = {
30
+ write?: (chunk: string | Buffer) => boolean | void;
31
+ writeHead: (statusCode: number, headers?: Record<string, string>) => unknown;
32
+ end: (chunk?: string | Buffer) => void;
33
+ writableEnded?: boolean;
34
+ on?: (event: string, listener: () => void) => void;
35
+ once?: (event: string, listener: () => void) => void;
36
+ };
37
+ type RegisterLiveLegacyRoutesDeps<TRes extends RouteResLike> = {
38
+ getLiveSessions: (input: {
39
+ initiative: string | null;
40
+ limit: number | undefined;
41
+ }) => Promise<LiveSessionsResponse>;
42
+ getLiveActivity: (input: {
43
+ run: string | null;
44
+ since: string | null;
45
+ limit: number | undefined;
46
+ }) => Promise<LiveActivityResponse>;
47
+ listRuntimeInstances: (input: {
48
+ limit: number;
49
+ }) => RuntimeInstanceRecord[];
50
+ injectRuntimeInstancesAsSessions: (input: SessionTreeResponse, instances: RuntimeInstanceRecord[]) => SessionTreeResponse;
51
+ enrichSessionsWithRuntime: (input: SessionTreeResponse, instances: RuntimeInstanceRecord[]) => SessionTreeResponse;
52
+ loadLocalOpenClawSnapshot: (limit: number) => Promise<LocalSnapshot>;
53
+ toLocalSessionTree: (snapshot: LocalSnapshot, limit?: number) => SessionTreeResponse;
54
+ readAgentContexts: () => AgentContextBundle;
55
+ applyAgentContextsToSessionTree: (input: SessionTreeResponse, contexts: {
56
+ agents: Record<string, AgentLaunchContext>;
57
+ runs: Record<string, RunLaunchContext>;
58
+ }) => SessionTreeResponse;
59
+ listActivityPage: (input: {
60
+ limit: number;
61
+ runId: string | null;
62
+ since: string | null;
63
+ until: string | null;
64
+ cursor: string | null;
65
+ }) => LiveActivityPage;
66
+ applyAgentContextsToActivity: (input: LiveActivityItem[], contexts: {
67
+ agents: Record<string, AgentLaunchContext>;
68
+ runs: Record<string, RunLaunchContext>;
69
+ }) => LiveActivityItem[];
70
+ appendActivityItems: (items: LiveActivityItem[]) => void;
71
+ activityWarmByKey: Map<string, number>;
72
+ activityWarmThrottleMs: number;
73
+ outboxReadAllItems: () => Promise<LiveActivityItem[]>;
74
+ toLocalLiveActivity: (snapshot: LocalSnapshot, limit?: number) => Promise<LocalLiveActivity>;
75
+ loadLocalTurnDetail: (input: {
76
+ turnId: string;
77
+ sessionKey: string | null;
78
+ runId: string | null;
79
+ }) => Promise<Record<string, unknown> | null>;
80
+ sendJson: (res: TRes, status: number, payload: unknown) => void;
81
+ safeErrorMessage: (err: unknown) => string;
82
+ sendHtml: (res: TRes, status: number, html: string) => void;
83
+ resolveFilesystemOpenPath: (rawPath: string) => string;
84
+ escapeHtml: (value: string) => string;
85
+ statSync: (path: string) => {
86
+ isDirectory: () => boolean;
87
+ isFile: () => boolean;
88
+ size: number;
89
+ };
90
+ readdirSync: (path: string) => string[];
91
+ existsSync: (path: string) => boolean;
92
+ resolvePath: (...segments: string[]) => string;
93
+ readFilePreview: (path: string, totalBytes: number) => {
94
+ previewBuffer: Buffer;
95
+ truncated: boolean;
96
+ };
97
+ filePreviewMaxBytes: number;
98
+ filePreviewMaxDirEntries: number;
99
+ securityHeaders: Record<string, string>;
100
+ corsHeaders: Record<string, string>;
101
+ config: {
102
+ baseUrl: string;
103
+ apiKey: string;
104
+ userId: string;
105
+ };
106
+ isUserScopedApiKey: (apiKey: string) => boolean;
107
+ streamIdleTimeoutMs: number;
108
+ };
109
+ export declare function registerLiveLegacyRoutes<TReq extends RouteReqLike, TRes extends RouteResLike>(router: Router<Record<string, never>, TReq, TRes>, deps: RegisterLiveLegacyRoutesDeps<TRes>): void;
110
+ export {};