galaxy-opc-plugin 0.2.8 → 0.3.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/package.json +1 -1
- package/src/api/companies.ts +5 -9
- package/src/api/dashboard.ts +37 -16
- package/src/api/routes.ts +0 -2
- package/src/web/config-ui-patches.ts +3 -3
- package/src/web/config-ui.ts +37 -41
- package/src/web/landing-page.ts +5 -9
package/package.json
CHANGED
package/src/api/companies.ts
CHANGED
|
@@ -208,21 +208,17 @@ export function registerCompanyRoutes(api: OpenClawPluginApi, db: OpcDatabase, g
|
|
|
208
208
|
|
|
209
209
|
const apiAny = api as unknown as {
|
|
210
210
|
registerHttpHandler?: (h: (req: IncomingMessage, res: ServerResponse) => Promise<boolean> | boolean) => void;
|
|
211
|
-
registerHttpRoute?: (r: { path: string
|
|
211
|
+
registerHttpRoute?: (r: { path: string; handler: (req: IncomingMessage, res: ServerResponse) => Promise<boolean | void> | boolean | void; auth: string; match?: string }) => void;
|
|
212
212
|
};
|
|
213
213
|
|
|
214
214
|
if (typeof apiAny.registerHttpHandler === "function") {
|
|
215
215
|
apiAny.registerHttpHandler(handler);
|
|
216
216
|
} else if (typeof apiAny.registerHttpRoute === "function") {
|
|
217
217
|
apiAny.registerHttpRoute({
|
|
218
|
-
path:
|
|
219
|
-
handler
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
res.writeHead(404, { "Content-Type": "application/json; charset=utf-8" });
|
|
223
|
-
res.end(JSON.stringify({ error: "Not found" }));
|
|
224
|
-
}
|
|
225
|
-
},
|
|
218
|
+
path: "/opc/api/companies",
|
|
219
|
+
handler,
|
|
220
|
+
auth: "gateway",
|
|
221
|
+
match: "prefix",
|
|
226
222
|
});
|
|
227
223
|
} else {
|
|
228
224
|
throw new Error("No compatible HTTP registration API found on OpenClaw plugin API");
|
package/src/api/dashboard.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* POST /opc/admin/api/alerts/:id/dismiss — 忽略预警
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
9
10
|
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
10
11
|
import type { OpcDatabase } from "../db/index.js";
|
|
11
12
|
import {
|
|
@@ -60,10 +61,14 @@ interface TodoRow {
|
|
|
60
61
|
* 注册 Dashboard API 路由
|
|
61
62
|
*/
|
|
62
63
|
export function registerDashboardApiRoutes(api: OpenClawPluginApi, db: OpcDatabase): void {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
const handler = async (req: IncomingMessage, res: ServerResponse): Promise<boolean> => {
|
|
65
|
+
const rawUrl = req.url ?? "";
|
|
66
|
+
const urlObj = new URL(rawUrl, "http://localhost");
|
|
67
|
+
const pathname = urlObj.pathname;
|
|
68
|
+
const method = req.method?.toUpperCase() ?? "GET";
|
|
69
|
+
|
|
70
|
+
// GET /opc/admin/api/dashboard
|
|
71
|
+
if (pathname === "/opc/admin/api/dashboard" && method === "GET") {
|
|
67
72
|
try {
|
|
68
73
|
const data = getDashboardData(db);
|
|
69
74
|
const html = generateDashboardHtml(data);
|
|
@@ -73,22 +78,19 @@ export function registerDashboardApiRoutes(api: OpenClawPluginApi, db: OpcDataba
|
|
|
73
78
|
res.writeHead(500, { "Content-Type": "application/json; charset=utf-8" });
|
|
74
79
|
res.end(JSON.stringify({ error: err instanceof Error ? err.message : String(err) }));
|
|
75
80
|
}
|
|
76
|
-
|
|
77
|
-
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
78
83
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
handler: async (req, res) => {
|
|
84
|
+
// POST /opc/admin/api/alerts/:id/dismiss
|
|
85
|
+
const alertMatch = pathname.match(/^\/opc\/admin\/api\/alerts\/([^/]+)\/dismiss$/);
|
|
86
|
+
if (alertMatch && method === "POST") {
|
|
83
87
|
try {
|
|
84
|
-
const
|
|
85
|
-
const pathParts = url.pathname.split("/");
|
|
86
|
-
const alertId = pathParts[pathParts.length - 2]; // .../alerts/{id}/dismiss
|
|
88
|
+
const alertId = alertMatch[1];
|
|
87
89
|
|
|
88
90
|
if (!alertId) {
|
|
89
91
|
res.writeHead(400, { "Content-Type": "application/json; charset=utf-8" });
|
|
90
92
|
res.end(JSON.stringify({ error: "Missing alert ID" }));
|
|
91
|
-
return;
|
|
93
|
+
return true;
|
|
92
94
|
}
|
|
93
95
|
|
|
94
96
|
const now = new Date().toISOString();
|
|
@@ -109,8 +111,27 @@ export function registerDashboardApiRoutes(api: OpenClawPluginApi, db: OpcDataba
|
|
|
109
111
|
res.writeHead(500, { "Content-Type": "application/json; charset=utf-8" });
|
|
110
112
|
res.end(JSON.stringify({ error: err instanceof Error ? err.message : String(err) }));
|
|
111
113
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return false;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const apiAny = api as unknown as {
|
|
121
|
+
registerHttpHandler?: (h: (req: IncomingMessage, res: ServerResponse) => Promise<boolean> | boolean) => void;
|
|
122
|
+
registerHttpRoute?: (r: { path: string; handler: (req: IncomingMessage, res: ServerResponse) => Promise<boolean | void> | boolean | void; auth: string; match?: string }) => void;
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
if (typeof apiAny.registerHttpHandler === "function") {
|
|
126
|
+
apiAny.registerHttpHandler(handler);
|
|
127
|
+
} else if (typeof apiAny.registerHttpRoute === "function") {
|
|
128
|
+
apiAny.registerHttpRoute({
|
|
129
|
+
path: "/opc/admin/api",
|
|
130
|
+
handler,
|
|
131
|
+
auth: "gateway",
|
|
132
|
+
match: "prefix",
|
|
133
|
+
});
|
|
134
|
+
}
|
|
114
135
|
}
|
|
115
136
|
|
|
116
137
|
/**
|
package/src/api/routes.ts
CHANGED
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
6
6
|
import type { OpcDatabase } from "../db/index.js";
|
|
7
7
|
import { registerCompanyRoutes } from "./companies.js";
|
|
8
|
-
import { registerDashboardApiRoutes } from "./dashboard.js";
|
|
9
8
|
|
|
10
9
|
/**
|
|
11
10
|
* 从 OpenClaw 配置中读取 gateway auth token。
|
|
@@ -26,6 +25,5 @@ export function registerHttpRoutes(api: OpenClawPluginApi, db: OpcDatabase): voi
|
|
|
26
25
|
const gatewayToken = getGatewayToken(api);
|
|
27
26
|
|
|
28
27
|
registerCompanyRoutes(api, db, gatewayToken);
|
|
29
|
-
registerDashboardApiRoutes(api, db);
|
|
30
28
|
api.logger.info("opc: 已注册 HTTP API 路由");
|
|
31
29
|
}
|
|
@@ -72,7 +72,7 @@ export function registerConfigUiRoutes(api: OpenClawPluginApi, db: OpcDatabase,
|
|
|
72
72
|
|
|
73
73
|
// GET /opc/admin/api/payments/:id
|
|
74
74
|
api.registerHttpRoute({
|
|
75
|
-
path:
|
|
75
|
+
path: '/opc/admin/api/payments',
|
|
76
76
|
handler: async (req, res) => {
|
|
77
77
|
const match = req.url?.match(/^\/opc\/admin\/api\/payments\/([^/]+)$/);
|
|
78
78
|
if (!match) {
|
|
@@ -135,7 +135,7 @@ export function registerConfigUiRoutes(api: OpenClawPluginApi, db: OpcDatabase,
|
|
|
135
135
|
|
|
136
136
|
// PUT /opc/admin/api/payments/:id - 更新收付款
|
|
137
137
|
api.registerHttpRoute({
|
|
138
|
-
path:
|
|
138
|
+
path: '/opc/admin/api/payments',
|
|
139
139
|
handler: async (req, res) => {
|
|
140
140
|
if (req.method !== 'PUT') return false;
|
|
141
141
|
|
|
@@ -180,7 +180,7 @@ export function registerConfigUiRoutes(api: OpenClawPluginApi, db: OpcDatabase,
|
|
|
180
180
|
|
|
181
181
|
// POST /opc/admin/api/payments/:id/record - 记账
|
|
182
182
|
api.registerHttpRoute({
|
|
183
|
-
path:
|
|
183
|
+
path: '/opc/admin/api/payments',
|
|
184
184
|
handler: async (req, res) => {
|
|
185
185
|
if (req.method !== 'POST') return false;
|
|
186
186
|
|
package/src/web/config-ui.ts
CHANGED
|
@@ -3123,32 +3123,32 @@ function getCanvasJs(): string {
|
|
|
3123
3123
|
|
|
3124
3124
|
/* ── Route registration ───────────────────────────────────── */
|
|
3125
3125
|
|
|
3126
|
-
export function registerConfigUi(api: OpenClawPluginApi, db: OpcDatabase, gatewayToken?: string): void {
|
|
3126
|
+
export function registerConfigUi(api: OpenClawPluginApi, db: OpcDatabase, gatewayToken?: string): void {
|
|
3127
3127
|
// 注册 Dashboard API 路由
|
|
3128
3128
|
registerDashboardApiRoutes(api, db);
|
|
3129
3129
|
|
|
3130
|
-
const handler = async (req: IncomingMessage, res: ServerResponse): Promise<boolean> => {
|
|
3130
|
+
const handler = async (req: IncomingMessage, res: ServerResponse): Promise<boolean> => {
|
|
3131
3131
|
const rawUrl = req.url ?? "";
|
|
3132
3132
|
const urlObj = new URL(rawUrl, "http://localhost");
|
|
3133
3133
|
const pathname = urlObj.pathname;
|
|
3134
3134
|
const method = req.method?.toUpperCase() ?? "GET";
|
|
3135
3135
|
|
|
3136
|
-
if (!pathname.startsWith("/opc/admin")) {
|
|
3137
|
-
return false;
|
|
3138
|
-
}
|
|
3139
|
-
|
|
3140
|
-
// Normalize accidental SPA deep-links (e.g. /opc/admin/chat) back to OPC admin root.
|
|
3141
|
-
// Without this, users may land on OpenClaw's default chat UI and think OPC admin failed to load.
|
|
3142
|
-
if (
|
|
3143
|
-
!pathname.startsWith("/opc/admin/api/")
|
|
3144
|
-
&& pathname !== "/opc/admin"
|
|
3145
|
-
&& pathname !== "/opc/admin/"
|
|
3146
|
-
) {
|
|
3147
|
-
const tokenParam = gatewayToken ? `?token=${encodeURIComponent(gatewayToken)}` : "";
|
|
3148
|
-
res.writeHead(302, { Location: `/opc/admin${tokenParam}` });
|
|
3149
|
-
res.end();
|
|
3150
|
-
return true;
|
|
3151
|
-
}
|
|
3136
|
+
if (!pathname.startsWith("/opc/admin")) {
|
|
3137
|
+
return false;
|
|
3138
|
+
}
|
|
3139
|
+
|
|
3140
|
+
// Normalize accidental SPA deep-links (e.g. /opc/admin/chat) back to OPC admin root.
|
|
3141
|
+
// Without this, users may land on OpenClaw's default chat UI and think OPC admin failed to load.
|
|
3142
|
+
if (
|
|
3143
|
+
!pathname.startsWith("/opc/admin/api/")
|
|
3144
|
+
&& pathname !== "/opc/admin"
|
|
3145
|
+
&& pathname !== "/opc/admin/"
|
|
3146
|
+
) {
|
|
3147
|
+
const tokenParam = gatewayToken ? `?token=${encodeURIComponent(gatewayToken)}` : "";
|
|
3148
|
+
res.writeHead(302, { Location: `/opc/admin${tokenParam}` });
|
|
3149
|
+
res.end();
|
|
3150
|
+
return true;
|
|
3151
|
+
}
|
|
3152
3152
|
|
|
3153
3153
|
// API 端点需要认证
|
|
3154
3154
|
if (pathname.startsWith("/opc/admin/api/") && gatewayToken) {
|
|
@@ -4169,29 +4169,25 @@ export function registerConfigUi(api: OpenClawPluginApi, db: OpcDatabase, gatewa
|
|
|
4169
4169
|
res.end(JSON.stringify({ error: err instanceof Error ? err.message : String(err) }));
|
|
4170
4170
|
return true;
|
|
4171
4171
|
}
|
|
4172
|
-
};
|
|
4173
|
-
|
|
4174
|
-
const apiAny = api as unknown as {
|
|
4175
|
-
registerHttpHandler?: (h: (req: IncomingMessage, res: ServerResponse) => Promise<boolean> | boolean) => void;
|
|
4176
|
-
registerHttpRoute?: (r: { path: string
|
|
4177
|
-
};
|
|
4178
|
-
|
|
4179
|
-
if (typeof apiAny.registerHttpHandler === "function") {
|
|
4180
|
-
apiAny.registerHttpHandler(handler);
|
|
4181
|
-
} else if (typeof apiAny.registerHttpRoute === "function") {
|
|
4182
|
-
apiAny.registerHttpRoute({
|
|
4183
|
-
path:
|
|
4184
|
-
handler
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
});
|
|
4192
|
-
} else {
|
|
4193
|
-
throw new Error("No compatible HTTP registration API found on OpenClaw plugin API");
|
|
4194
|
-
}
|
|
4172
|
+
};
|
|
4173
|
+
|
|
4174
|
+
const apiAny = api as unknown as {
|
|
4175
|
+
registerHttpHandler?: (h: (req: IncomingMessage, res: ServerResponse) => Promise<boolean> | boolean) => void;
|
|
4176
|
+
registerHttpRoute?: (r: { path: string; handler: (req: IncomingMessage, res: ServerResponse) => Promise<boolean | void> | boolean | void; auth: string; match?: string }) => void;
|
|
4177
|
+
};
|
|
4178
|
+
|
|
4179
|
+
if (typeof apiAny.registerHttpHandler === "function") {
|
|
4180
|
+
apiAny.registerHttpHandler(handler);
|
|
4181
|
+
} else if (typeof apiAny.registerHttpRoute === "function") {
|
|
4182
|
+
apiAny.registerHttpRoute({
|
|
4183
|
+
path: "/opc/admin",
|
|
4184
|
+
handler,
|
|
4185
|
+
auth: "gateway",
|
|
4186
|
+
match: "prefix",
|
|
4187
|
+
});
|
|
4188
|
+
} else {
|
|
4189
|
+
throw new Error("No compatible HTTP registration API found on OpenClaw plugin API");
|
|
4190
|
+
}
|
|
4195
4191
|
|
|
4196
4192
|
api.logger.info("opc: 已注册配置管理 UI (/opc/admin)");
|
|
4197
4193
|
}
|
package/src/web/landing-page.ts
CHANGED
|
@@ -317,21 +317,17 @@ export function registerLandingPage(api: OpenClawPluginApi): void {
|
|
|
317
317
|
|
|
318
318
|
const apiAny = api as unknown as {
|
|
319
319
|
registerHttpHandler?: (h: (req: IncomingMessage, res: ServerResponse) => Promise<boolean> | boolean) => void;
|
|
320
|
-
registerHttpRoute?: (r: { path: string
|
|
320
|
+
registerHttpRoute?: (r: { path: string; handler: (req: IncomingMessage, res: ServerResponse) => Promise<boolean | void> | boolean | void; auth: string; match?: string }) => void;
|
|
321
321
|
};
|
|
322
322
|
|
|
323
323
|
if (typeof apiAny.registerHttpHandler === "function") {
|
|
324
324
|
apiAny.registerHttpHandler(handler);
|
|
325
325
|
} else if (typeof apiAny.registerHttpRoute === "function") {
|
|
326
326
|
apiAny.registerHttpRoute({
|
|
327
|
-
path:
|
|
328
|
-
handler
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" });
|
|
332
|
-
res.end("Not found");
|
|
333
|
-
}
|
|
334
|
-
},
|
|
327
|
+
path: "/",
|
|
328
|
+
handler,
|
|
329
|
+
auth: "plugin",
|
|
330
|
+
match: "prefix",
|
|
335
331
|
});
|
|
336
332
|
} else {
|
|
337
333
|
throw new Error("No compatible HTTP registration API found on OpenClaw plugin API");
|