forge-openclaw-plugin 0.2.19 → 0.2.21
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 +133 -2
- package/dist/assets/board-_C6oMy5w.js +6 -0
- package/dist/assets/{board-8L3uX7_O.js.map → board-_C6oMy5w.js.map} +1 -1
- package/dist/assets/index-B4A6TooJ.js +63 -0
- package/dist/assets/index-B4A6TooJ.js.map +1 -0
- package/dist/assets/index-D6Xs_2mo.css +1 -0
- package/dist/assets/{motion-1GAqqi8M.js → motion-D4sZgCHd.js} +2 -2
- package/dist/assets/{motion-1GAqqi8M.js.map → motion-D4sZgCHd.js.map} +1 -1
- package/dist/assets/{table-DBGlgRjk.js → table-BWzTaky1.js} +2 -2
- package/dist/assets/{table-DBGlgRjk.js.map → table-BWzTaky1.js.map} +1 -1
- package/dist/assets/{ui-iTluWjC4.js → ui-BzK4azQb.js} +7 -7
- package/dist/assets/{ui-iTluWjC4.js.map → ui-BzK4azQb.js.map} +1 -1
- package/dist/assets/vendor-DT3pnAKJ.css +1 -0
- package/dist/assets/vendor-De38P6YR.js +729 -0
- package/dist/assets/vendor-De38P6YR.js.map +1 -0
- package/dist/assets/viz-C6hfyqzu.js +34 -0
- package/dist/assets/viz-C6hfyqzu.js.map +1 -0
- package/dist/index.html +9 -9
- package/dist/openclaw/parity.d.ts +1 -1
- package/dist/openclaw/parity.js +29 -2
- package/dist/openclaw/routes.js +207 -24
- package/dist/openclaw/tools.js +324 -35
- package/dist/server/app.js +2080 -92
- package/dist/server/db.js +3 -0
- package/dist/server/health.js +1284 -0
- package/dist/server/managers/platform/background-job-manager.js +138 -2
- package/dist/server/managers/platform/llm-manager.js +126 -0
- package/dist/server/managers/platform/openai-responses-provider.js +773 -0
- package/dist/server/managers/runtime.js +6 -1
- package/dist/server/openapi.js +718 -0
- package/dist/server/preferences-seeds.js +409 -0
- package/dist/server/preferences-types.js +368 -0
- package/dist/server/psyche-types.js +42 -18
- package/dist/server/repositories/activity-events.js +53 -4
- package/dist/server/repositories/calendar.js +89 -15
- package/dist/server/repositories/collaboration.js +8 -3
- package/dist/server/repositories/diagnostic-logs.js +243 -0
- package/dist/server/repositories/entity-ownership.js +92 -0
- package/dist/server/repositories/goals.js +7 -2
- package/dist/server/repositories/habits.js +122 -16
- package/dist/server/repositories/notes.js +119 -41
- package/dist/server/repositories/preferences.js +1765 -0
- package/dist/server/repositories/projects.js +18 -7
- package/dist/server/repositories/psyche.js +84 -27
- package/dist/server/repositories/rewards.js +112 -4
- package/dist/server/repositories/strategies.js +450 -0
- package/dist/server/repositories/tags.js +11 -6
- package/dist/server/repositories/task-runs.js +10 -2
- package/dist/server/repositories/tasks.js +99 -17
- package/dist/server/repositories/users.js +417 -0
- package/dist/server/repositories/wiki-memory.js +3366 -0
- package/dist/server/services/context.js +20 -18
- package/dist/server/services/dashboard.js +29 -6
- package/dist/server/services/entity-crud.js +21 -3
- package/dist/server/services/insights.js +9 -7
- package/dist/server/services/projects.js +2 -1
- package/dist/server/services/psyche.js +10 -9
- package/dist/server/types.js +594 -30
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/server/migrations/015_multi_user_and_strategies.sql +244 -0
- package/server/migrations/016_health_companion.sql +158 -0
- package/server/migrations/016_strategy_contracts_and_user_graph.sql +22 -0
- package/server/migrations/017_preferences.sql +131 -0
- package/server/migrations/018_preference_catalogs.sql +31 -0
- package/server/migrations/019_wiki_memory.sql +255 -0
- package/server/migrations/020_wiki_page_hierarchy.sql +11 -0
- package/server/migrations/021_hide_evidence_from_wiki_index.sql +3 -0
- package/server/migrations/022_wiki_ingest_background.sql +85 -0
- package/server/migrations/023_diagnostic_logs.sql +28 -0
- package/skills/forge-openclaw/SKILL.md +126 -34
- package/skills/forge-openclaw/entity_conversation_playbooks.md +337 -0
- package/skills/forge-openclaw/psyche_entity_playbooks.md +404 -0
- package/dist/assets/board-8L3uX7_O.js +0 -6
- package/dist/assets/index-Cj1IBH_w.js +0 -36
- package/dist/assets/index-Cj1IBH_w.js.map +0 -1
- package/dist/assets/index-DQT6EbuS.css +0 -1
- package/dist/assets/vendor-BvM2F9Dp.js +0 -503
- package/dist/assets/vendor-BvM2F9Dp.js.map +0 -1
- package/dist/assets/vendor-CRS-psbw.css +0 -1
- package/dist/assets/viz-CNeunkfu.js +0 -34
- package/dist/assets/viz-CNeunkfu.js.map +0 -1
package/dist/index.html
CHANGED
|
@@ -13,15 +13,15 @@
|
|
|
13
13
|
/>
|
|
14
14
|
<link rel="icon" type="image/png" href="/forge/assets/favicon-BCHm9dUV.ico" />
|
|
15
15
|
<link rel="alternate icon" href="/forge/assets/favicon-BCHm9dUV.ico" />
|
|
16
|
-
<script type="module" crossorigin src="/forge/assets/index-
|
|
17
|
-
<link rel="modulepreload" crossorigin href="/forge/assets/
|
|
18
|
-
<link rel="modulepreload" crossorigin href="/forge/assets/
|
|
19
|
-
<link rel="modulepreload" crossorigin href="/forge/assets/ui-
|
|
20
|
-
<link rel="modulepreload" crossorigin href="/forge/assets/
|
|
21
|
-
<link rel="modulepreload" crossorigin href="/forge/assets/
|
|
22
|
-
<link rel="modulepreload" crossorigin href="/forge/assets/board-
|
|
23
|
-
<link rel="stylesheet" crossorigin href="/forge/assets/vendor-
|
|
24
|
-
<link rel="stylesheet" crossorigin href="/forge/assets/index-
|
|
16
|
+
<script type="module" crossorigin src="/forge/assets/index-B4A6TooJ.js"></script>
|
|
17
|
+
<link rel="modulepreload" crossorigin href="/forge/assets/viz-C6hfyqzu.js">
|
|
18
|
+
<link rel="modulepreload" crossorigin href="/forge/assets/vendor-De38P6YR.js">
|
|
19
|
+
<link rel="modulepreload" crossorigin href="/forge/assets/ui-BzK4azQb.js">
|
|
20
|
+
<link rel="modulepreload" crossorigin href="/forge/assets/motion-D4sZgCHd.js">
|
|
21
|
+
<link rel="modulepreload" crossorigin href="/forge/assets/table-BWzTaky1.js">
|
|
22
|
+
<link rel="modulepreload" crossorigin href="/forge/assets/board-_C6oMy5w.js">
|
|
23
|
+
<link rel="stylesheet" crossorigin href="/forge/assets/vendor-DT3pnAKJ.css">
|
|
24
|
+
<link rel="stylesheet" crossorigin href="/forge/assets/index-D6Xs_2mo.css">
|
|
25
25
|
</head>
|
|
26
26
|
<body class="bg-canvas text-ink antialiased">
|
|
27
27
|
<div id="root"></div>
|
|
@@ -2,7 +2,7 @@ export type ApiRouteKey = `${Uppercase<string>} ${string}`;
|
|
|
2
2
|
export type ForgeSupportedPluginApiRoute = {
|
|
3
3
|
method: Uppercase<string>;
|
|
4
4
|
path: string;
|
|
5
|
-
purpose: "diagnostics" | "overview" | "operator_context" | "onboarding" | "psyche" | "xp" | "weekly_review" | "entities" | "work" | "insights";
|
|
5
|
+
purpose: "diagnostics" | "overview" | "operator_context" | "onboarding" | "psyche" | "xp" | "weekly_review" | "entities" | "work" | "insights" | "wiki" | "health";
|
|
6
6
|
};
|
|
7
7
|
export declare const FORGE_SUPPORTED_PLUGIN_API_ROUTES: ForgeSupportedPluginApiRoute[];
|
|
8
8
|
export declare function makeApiRouteKey(method: string, path: string): ApiRouteKey;
|
package/dist/openclaw/parity.js
CHANGED
|
@@ -1,11 +1,34 @@
|
|
|
1
1
|
export const FORGE_SUPPORTED_PLUGIN_API_ROUTES = [
|
|
2
2
|
{ method: "GET", path: "/api/v1/health", purpose: "diagnostics" },
|
|
3
|
+
{
|
|
4
|
+
method: "GET",
|
|
5
|
+
path: "/api/v1/users/directory",
|
|
6
|
+
purpose: "operator_context"
|
|
7
|
+
},
|
|
3
8
|
{ method: "GET", path: "/api/v1/operator/overview", purpose: "overview" },
|
|
4
|
-
{
|
|
9
|
+
{
|
|
10
|
+
method: "GET",
|
|
11
|
+
path: "/api/v1/operator/context",
|
|
12
|
+
purpose: "operator_context"
|
|
13
|
+
},
|
|
5
14
|
{ method: "GET", path: "/api/v1/agents/onboarding", purpose: "onboarding" },
|
|
6
15
|
{ method: "GET", path: "/api/v1/psyche/overview", purpose: "psyche" },
|
|
7
16
|
{ method: "GET", path: "/api/v1/metrics/xp", purpose: "xp" },
|
|
8
17
|
{ method: "GET", path: "/api/v1/reviews/weekly", purpose: "weekly_review" },
|
|
18
|
+
{ method: "GET", path: "/api/v1/wiki/settings", purpose: "wiki" },
|
|
19
|
+
{ method: "GET", path: "/api/v1/wiki/pages", purpose: "wiki" },
|
|
20
|
+
{ method: "GET", path: "/api/v1/wiki/pages/:id", purpose: "wiki" },
|
|
21
|
+
{ method: "GET", path: "/api/v1/wiki/health", purpose: "wiki" },
|
|
22
|
+
{ method: "POST", path: "/api/v1/wiki/search", purpose: "wiki" },
|
|
23
|
+
{ method: "POST", path: "/api/v1/wiki/pages", purpose: "wiki" },
|
|
24
|
+
{ method: "PATCH", path: "/api/v1/wiki/pages/:id", purpose: "wiki" },
|
|
25
|
+
{ method: "POST", path: "/api/v1/wiki/sync", purpose: "wiki" },
|
|
26
|
+
{ method: "POST", path: "/api/v1/wiki/reindex", purpose: "wiki" },
|
|
27
|
+
{ method: "POST", path: "/api/v1/wiki/ingest-jobs", purpose: "wiki" },
|
|
28
|
+
{ method: "GET", path: "/api/v1/health/sleep", purpose: "health" },
|
|
29
|
+
{ method: "PATCH", path: "/api/v1/health/sleep/:id", purpose: "health" },
|
|
30
|
+
{ method: "GET", path: "/api/v1/health/fitness", purpose: "health" },
|
|
31
|
+
{ method: "PATCH", path: "/api/v1/health/workouts/:id", purpose: "health" },
|
|
9
32
|
{ method: "POST", path: "/api/v1/entities/search", purpose: "entities" },
|
|
10
33
|
{ method: "POST", path: "/api/v1/entities/create", purpose: "entities" },
|
|
11
34
|
{ method: "POST", path: "/api/v1/entities/update", purpose: "entities" },
|
|
@@ -15,7 +38,11 @@ export const FORGE_SUPPORTED_PLUGIN_API_ROUTES = [
|
|
|
15
38
|
{ method: "POST", path: "/api/v1/work-adjustments", purpose: "work" },
|
|
16
39
|
{ method: "POST", path: "/api/v1/tasks/:id/runs", purpose: "work" },
|
|
17
40
|
{ method: "GET", path: "/api/v1/task-runs", purpose: "work" },
|
|
18
|
-
{
|
|
41
|
+
{
|
|
42
|
+
method: "POST",
|
|
43
|
+
path: "/api/v1/task-runs/:id/heartbeat",
|
|
44
|
+
purpose: "work"
|
|
45
|
+
},
|
|
19
46
|
{ method: "POST", path: "/api/v1/task-runs/:id/focus", purpose: "work" },
|
|
20
47
|
{ method: "POST", path: "/api/v1/task-runs/:id/complete", purpose: "work" },
|
|
21
48
|
{ method: "POST", path: "/api/v1/task-runs/:id/release", purpose: "work" },
|
package/dist/openclaw/routes.js
CHANGED
|
@@ -54,7 +54,9 @@ async function forwardOperation(request, response, config, operation, match, url
|
|
|
54
54
|
if (operation.requiresToken) {
|
|
55
55
|
requireApiToken(config);
|
|
56
56
|
}
|
|
57
|
-
const body = operation.requestBody === "json"
|
|
57
|
+
const body = operation.requestBody === "json"
|
|
58
|
+
? await readJsonRequestBody(request, { emptyObject: true })
|
|
59
|
+
: undefined;
|
|
58
60
|
const result = await callConfiguredForgeApi(config, {
|
|
59
61
|
method: operation.method,
|
|
60
62
|
path: operation.target(match, url),
|
|
@@ -83,7 +85,9 @@ async function handleGroup(request, response, config, group) {
|
|
|
83
85
|
}
|
|
84
86
|
const matchedOperation = matchingOperations.find((entry) => entry.operation.method === method);
|
|
85
87
|
if (!matchedOperation) {
|
|
86
|
-
methodNotAllowed(response, [
|
|
88
|
+
methodNotAllowed(response, [
|
|
89
|
+
...new Set(matchingOperations.map((entry) => entry.operation.method))
|
|
90
|
+
]);
|
|
87
91
|
return;
|
|
88
92
|
}
|
|
89
93
|
await forwardOperation(request, response, config, matchedOperation.operation, matchedOperation.match, url);
|
|
@@ -95,7 +99,9 @@ async function handleGroup(request, response, config, group) {
|
|
|
95
99
|
const exact = (path, operation) => ({
|
|
96
100
|
path,
|
|
97
101
|
match: "exact",
|
|
98
|
-
operations: [
|
|
102
|
+
operations: [
|
|
103
|
+
{ ...operation, pattern: new RegExp(`^${path.replaceAll("/", "\\/")}$`) }
|
|
104
|
+
]
|
|
99
105
|
});
|
|
100
106
|
export const FORGE_PLUGIN_ROUTE_GROUPS = [
|
|
101
107
|
exact("/forge/v1/health", {
|
|
@@ -118,6 +124,11 @@ export const FORGE_PLUGIN_ROUTE_GROUPS = [
|
|
|
118
124
|
upstreamPath: "/api/v1/agents/onboarding",
|
|
119
125
|
target: (_match, url) => passthroughSearch("/api/v1/agents/onboarding", url)
|
|
120
126
|
}),
|
|
127
|
+
exact("/forge/v1/users/directory", {
|
|
128
|
+
method: "GET",
|
|
129
|
+
upstreamPath: "/api/v1/users/directory",
|
|
130
|
+
target: (_match, url) => passthroughSearch("/api/v1/users/directory", url)
|
|
131
|
+
}),
|
|
121
132
|
exact("/forge/v1/psyche/overview", {
|
|
122
133
|
method: "GET",
|
|
123
134
|
upstreamPath: "/api/v1/psyche/overview",
|
|
@@ -133,6 +144,26 @@ export const FORGE_PLUGIN_ROUTE_GROUPS = [
|
|
|
133
144
|
upstreamPath: "/api/v1/reviews/weekly",
|
|
134
145
|
target: (_match, url) => passthroughSearch("/api/v1/reviews/weekly", url)
|
|
135
146
|
}),
|
|
147
|
+
exact("/forge/v1/wiki/settings", {
|
|
148
|
+
method: "GET",
|
|
149
|
+
upstreamPath: "/api/v1/wiki/settings",
|
|
150
|
+
target: (_match, url) => passthroughSearch("/api/v1/wiki/settings", url)
|
|
151
|
+
}),
|
|
152
|
+
exact("/forge/v1/wiki/health", {
|
|
153
|
+
method: "GET",
|
|
154
|
+
upstreamPath: "/api/v1/wiki/health",
|
|
155
|
+
target: (_match, url) => passthroughSearch("/api/v1/wiki/health", url)
|
|
156
|
+
}),
|
|
157
|
+
exact("/forge/v1/health/sleep", {
|
|
158
|
+
method: "GET",
|
|
159
|
+
upstreamPath: "/api/v1/health/sleep",
|
|
160
|
+
target: (_match, url) => passthroughSearch("/api/v1/health/sleep", url)
|
|
161
|
+
}),
|
|
162
|
+
exact("/forge/v1/health/fitness", {
|
|
163
|
+
method: "GET",
|
|
164
|
+
upstreamPath: "/api/v1/health/fitness",
|
|
165
|
+
target: (_match, url) => passthroughSearch("/api/v1/health/fitness", url)
|
|
166
|
+
}),
|
|
136
167
|
exact("/forge/v1/operator/log-work", {
|
|
137
168
|
method: "POST",
|
|
138
169
|
upstreamPath: "/api/v1/operator/log-work",
|
|
@@ -154,6 +185,100 @@ export const FORGE_PLUGIN_ROUTE_GROUPS = [
|
|
|
154
185
|
requiresToken: true,
|
|
155
186
|
target: (_match, url) => passthroughSearch("/api/v1/insights", url)
|
|
156
187
|
}),
|
|
188
|
+
{
|
|
189
|
+
path: "/forge/v1/wiki/pages",
|
|
190
|
+
match: "prefix",
|
|
191
|
+
operations: [
|
|
192
|
+
{
|
|
193
|
+
method: "GET",
|
|
194
|
+
pattern: /^\/forge\/v1\/wiki\/pages$/,
|
|
195
|
+
upstreamPath: "/api/v1/wiki/pages",
|
|
196
|
+
target: (_match, url) => passthroughSearch("/api/v1/wiki/pages", url)
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
method: "POST",
|
|
200
|
+
pattern: /^\/forge\/v1\/wiki\/pages$/,
|
|
201
|
+
upstreamPath: "/api/v1/wiki/pages",
|
|
202
|
+
requestBody: "json",
|
|
203
|
+
requiresToken: true,
|
|
204
|
+
target: (_match, url) => passthroughSearch("/api/v1/wiki/pages", url)
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
method: "GET",
|
|
208
|
+
pattern: /^\/forge\/v1\/wiki\/pages\/([^/]+)$/,
|
|
209
|
+
upstreamPath: "/api/v1/wiki/pages/:id",
|
|
210
|
+
target: (match, url) => passthroughSearch(`/api/v1/wiki/pages/${match[1]}`, url)
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
method: "PATCH",
|
|
214
|
+
pattern: /^\/forge\/v1\/wiki\/pages\/([^/]+)$/,
|
|
215
|
+
upstreamPath: "/api/v1/wiki/pages/:id",
|
|
216
|
+
requestBody: "json",
|
|
217
|
+
requiresToken: true,
|
|
218
|
+
target: (match, url) => passthroughSearch(`/api/v1/wiki/pages/${match[1]}`, url)
|
|
219
|
+
}
|
|
220
|
+
]
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
path: "/forge/v1/wiki",
|
|
224
|
+
match: "prefix",
|
|
225
|
+
operations: [
|
|
226
|
+
{
|
|
227
|
+
method: "POST",
|
|
228
|
+
pattern: /^\/forge\/v1\/wiki\/search$/,
|
|
229
|
+
upstreamPath: "/api/v1/wiki/search",
|
|
230
|
+
requestBody: "json",
|
|
231
|
+
requiresToken: true,
|
|
232
|
+
target: (_match, url) => passthroughSearch("/api/v1/wiki/search", url)
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
method: "POST",
|
|
236
|
+
pattern: /^\/forge\/v1\/wiki\/sync$/,
|
|
237
|
+
upstreamPath: "/api/v1/wiki/sync",
|
|
238
|
+
requestBody: "json",
|
|
239
|
+
requiresToken: true,
|
|
240
|
+
target: (_match, url) => passthroughSearch("/api/v1/wiki/sync", url)
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
method: "POST",
|
|
244
|
+
pattern: /^\/forge\/v1\/wiki\/reindex$/,
|
|
245
|
+
upstreamPath: "/api/v1/wiki/reindex",
|
|
246
|
+
requestBody: "json",
|
|
247
|
+
requiresToken: true,
|
|
248
|
+
target: (_match, url) => passthroughSearch("/api/v1/wiki/reindex", url)
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
method: "POST",
|
|
252
|
+
pattern: /^\/forge\/v1\/wiki\/ingest-jobs$/,
|
|
253
|
+
upstreamPath: "/api/v1/wiki/ingest-jobs",
|
|
254
|
+
requestBody: "json",
|
|
255
|
+
requiresToken: true,
|
|
256
|
+
target: (_match, url) => passthroughSearch("/api/v1/wiki/ingest-jobs", url)
|
|
257
|
+
}
|
|
258
|
+
]
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
path: "/forge/v1/health",
|
|
262
|
+
match: "prefix",
|
|
263
|
+
operations: [
|
|
264
|
+
{
|
|
265
|
+
method: "PATCH",
|
|
266
|
+
pattern: /^\/forge\/v1\/health\/sleep\/([^/]+)$/,
|
|
267
|
+
upstreamPath: "/api/v1/health/sleep/:id",
|
|
268
|
+
requestBody: "json",
|
|
269
|
+
requiresToken: true,
|
|
270
|
+
target: (match, url) => passthroughSearch(`/api/v1/health/sleep/${match[1]}`, url)
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
method: "PATCH",
|
|
274
|
+
pattern: /^\/forge\/v1\/health\/workouts\/([^/]+)$/,
|
|
275
|
+
upstreamPath: "/api/v1/health/workouts/:id",
|
|
276
|
+
requestBody: "json",
|
|
277
|
+
requiresToken: true,
|
|
278
|
+
target: (match, url) => passthroughSearch(`/api/v1/health/workouts/${match[1]}`, url)
|
|
279
|
+
}
|
|
280
|
+
]
|
|
281
|
+
},
|
|
157
282
|
{
|
|
158
283
|
path: "/forge/v1/entities",
|
|
159
284
|
match: "prefix",
|
|
@@ -264,17 +389,28 @@ export const FORGE_PLUGIN_ROUTE_GROUPS = [
|
|
|
264
389
|
})
|
|
265
390
|
];
|
|
266
391
|
export function collectMirroredApiRouteKeys() {
|
|
267
|
-
return new Set(FORGE_PLUGIN_ROUTE_GROUPS.flatMap((group) => group.operations.flatMap((operation) =>
|
|
392
|
+
return new Set(FORGE_PLUGIN_ROUTE_GROUPS.flatMap((group) => group.operations.flatMap((operation) => "upstreamPath" in operation
|
|
393
|
+
? [makeApiRouteKey(operation.method, operation.upstreamPath)]
|
|
394
|
+
: [])));
|
|
268
395
|
}
|
|
269
396
|
export function buildRouteParityReport(pathMap) {
|
|
270
397
|
const mirrored = collectMirroredApiRouteKeys();
|
|
271
398
|
const supported = collectSupportedPluginApiRouteKeys();
|
|
272
399
|
const openApiRoutes = new Set(Object.entries(pathMap)
|
|
273
400
|
.flatMap(([path, methods]) => Object.keys(methods).map((method) => makeApiRouteKey(method, path)))
|
|
274
|
-
.filter((key) => key.startsWith("GET /api/v1") ||
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
401
|
+
.filter((key) => key.startsWith("GET /api/v1") ||
|
|
402
|
+
key.startsWith("POST /api/v1") ||
|
|
403
|
+
key.startsWith("PATCH /api/v1") ||
|
|
404
|
+
key.startsWith("DELETE /api/v1")));
|
|
405
|
+
const missingFromPlugin = [...supported]
|
|
406
|
+
.filter((key) => !mirrored.has(key))
|
|
407
|
+
.sort();
|
|
408
|
+
const missingFromOpenApi = [...supported]
|
|
409
|
+
.filter((key) => !openApiRoutes.has(key))
|
|
410
|
+
.sort();
|
|
411
|
+
const unexpectedMirrors = [...mirrored]
|
|
412
|
+
.filter((key) => !supported.has(key))
|
|
413
|
+
.sort();
|
|
278
414
|
return {
|
|
279
415
|
supported: [...supported].sort(),
|
|
280
416
|
mirrored: [...mirrored].sort(),
|
|
@@ -311,7 +447,11 @@ async function runReadOnly(config, path) {
|
|
|
311
447
|
}
|
|
312
448
|
async function runRouteCheck(config) {
|
|
313
449
|
const openapi = await runReadOnly(config, "/api/v1/openapi.json");
|
|
314
|
-
const pathMap = typeof openapi === "object" &&
|
|
450
|
+
const pathMap = typeof openapi === "object" &&
|
|
451
|
+
openapi !== null &&
|
|
452
|
+
"paths" in openapi &&
|
|
453
|
+
typeof openapi.paths === "object" &&
|
|
454
|
+
openapi.paths !== null
|
|
315
455
|
? openapi.paths
|
|
316
456
|
: {};
|
|
317
457
|
return buildRouteParityReport(pathMap);
|
|
@@ -324,13 +464,21 @@ async function runDoctor(config) {
|
|
|
324
464
|
runRouteCheck(config),
|
|
325
465
|
resolveForgeUiUrl(config)
|
|
326
466
|
]);
|
|
327
|
-
const overviewBody = typeof overview === "object" &&
|
|
467
|
+
const overviewBody = typeof overview === "object" &&
|
|
468
|
+
overview !== null &&
|
|
469
|
+
"overview" in overview &&
|
|
470
|
+
typeof overview.overview === "object" &&
|
|
471
|
+
overview.overview !== null
|
|
328
472
|
? overview.overview
|
|
329
473
|
: null;
|
|
330
|
-
const capabilities = overviewBody &&
|
|
474
|
+
const capabilities = overviewBody &&
|
|
475
|
+
typeof overviewBody.capabilities === "object" &&
|
|
476
|
+
overviewBody.capabilities !== null
|
|
331
477
|
? overviewBody.capabilities
|
|
332
478
|
: null;
|
|
333
|
-
const overviewWarnings = Array.isArray(overviewBody?.warnings)
|
|
479
|
+
const overviewWarnings = Array.isArray(overviewBody?.warnings)
|
|
480
|
+
? overviewBody.warnings.filter((entry) => typeof entry === "string")
|
|
481
|
+
: [];
|
|
334
482
|
const warnings = [];
|
|
335
483
|
const canBootstrap = canBootstrapOperatorSession(config.baseUrl);
|
|
336
484
|
if (config.apiToken.trim().length === 0 && canBootstrap) {
|
|
@@ -375,29 +523,64 @@ async function runDoctor(config) {
|
|
|
375
523
|
}
|
|
376
524
|
export function registerForgePluginCli(api, config) {
|
|
377
525
|
api.registerCli?.(({ program }) => {
|
|
378
|
-
const command = program
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
command
|
|
382
|
-
|
|
383
|
-
|
|
526
|
+
const command = program
|
|
527
|
+
.command("forge")
|
|
528
|
+
.description("Inspect and operate Forge through the OpenClaw plugin");
|
|
529
|
+
command
|
|
530
|
+
.command("health")
|
|
531
|
+
.description("Check Forge health")
|
|
532
|
+
.action(createCliAction(config, "/api/v1/health"));
|
|
533
|
+
command
|
|
534
|
+
.command("overview")
|
|
535
|
+
.description("Fetch the one-shot Forge operator overview")
|
|
536
|
+
.action(createCliAction(config, "/api/v1/operator/overview"));
|
|
537
|
+
command
|
|
538
|
+
.command("onboarding")
|
|
539
|
+
.description("Print the Forge agent onboarding contract")
|
|
540
|
+
.action(createCliAction(config, "/api/v1/agents/onboarding"));
|
|
541
|
+
command
|
|
542
|
+
.command("ui")
|
|
543
|
+
.description("Print the Forge UI entrypoint")
|
|
544
|
+
.action(async () => {
|
|
545
|
+
console.log(JSON.stringify({
|
|
546
|
+
webAppUrl: await resolveForgeUiUrl(config),
|
|
547
|
+
pluginUiRoute: "/forge/v1/ui"
|
|
548
|
+
}, null, 2));
|
|
384
549
|
});
|
|
385
|
-
command
|
|
550
|
+
command
|
|
551
|
+
.command("start")
|
|
552
|
+
.description("Start the local Forge runtime when it is managed by the OpenClaw plugin")
|
|
553
|
+
.action(async () => {
|
|
386
554
|
console.log(JSON.stringify(await startForgeRuntime(config), null, 2));
|
|
387
555
|
});
|
|
388
|
-
command
|
|
556
|
+
command
|
|
557
|
+
.command("stop")
|
|
558
|
+
.description("Stop the local Forge runtime when it was auto-started by the OpenClaw plugin")
|
|
559
|
+
.action(async () => {
|
|
389
560
|
console.log(JSON.stringify(await stopForgeRuntime(config), null, 2));
|
|
390
561
|
});
|
|
391
|
-
command
|
|
562
|
+
command
|
|
563
|
+
.command("restart")
|
|
564
|
+
.description("Restart the local Forge runtime when it is managed by the OpenClaw plugin")
|
|
565
|
+
.action(async () => {
|
|
392
566
|
console.log(JSON.stringify(await restartForgeRuntime(config), null, 2));
|
|
393
567
|
});
|
|
394
|
-
command
|
|
568
|
+
command
|
|
569
|
+
.command("status")
|
|
570
|
+
.description("Report whether the local Forge runtime is running and whether it is plugin-managed")
|
|
571
|
+
.action(async () => {
|
|
395
572
|
console.log(JSON.stringify(await getForgeRuntimeStatus(config), null, 2));
|
|
396
573
|
});
|
|
397
|
-
command
|
|
574
|
+
command
|
|
575
|
+
.command("doctor")
|
|
576
|
+
.description("Run plugin connectivity and curated route diagnostics")
|
|
577
|
+
.action(async () => {
|
|
398
578
|
console.log(JSON.stringify(await runDoctor(config), null, 2));
|
|
399
579
|
});
|
|
400
|
-
command
|
|
580
|
+
command
|
|
581
|
+
.command("route-check")
|
|
582
|
+
.description("Compare curated plugin route coverage against the live Forge OpenAPI paths")
|
|
583
|
+
.action(async () => {
|
|
401
584
|
console.log(JSON.stringify(await runRouteCheck(config), null, 2));
|
|
402
585
|
});
|
|
403
586
|
}, { commands: ["forge"] });
|