agent-bridge-abweb 1.0.8 → 1.0.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.
@@ -5,7 +5,7 @@ const node_fs_1 = require("node:fs");
5
5
  const node_path_1 = require("node:path");
6
6
  const MANIFEST = {
7
7
  id: "abweb",
8
- version: "1.0.7",
8
+ version: "1.0.9",
9
9
  displayName: "Agent Bridge Web",
10
10
  entry: "dist/index.js",
11
11
  apiVersion: "1",
@@ -308,6 +308,8 @@
308
308
  const status = document.createElement("span");
309
309
  status.className = `status status-${plugin.status}`;
310
310
  status.textContent = plugin.status;
311
+ if (plugin.type === "agent")
312
+ type.textContent += ` · ${{ cli: "CLI", cdp: "CDP" }[plugin.manifest?.executionMode ?? ""] ?? "未声明"}`;
311
313
  const dependencies = Object.entries(plugin.manifest?.dependencies ?? {});
312
314
  if (dependencies.length) {
313
315
  const detail = document.createElement("small");
@@ -340,6 +342,8 @@
340
342
  }
341
343
  const controls = document.createElement("td");
342
344
  controls.className = "controls";
345
+ if (plugin.manifest?.executionMode === "cli")
346
+ controls.append(button("配置", `配置 ${plugin.id}`, () => configureCli(plugin)));
343
347
  if (pluginVersions[plugin.id]?.state === "update-available" && plugin.path.includes("node_modules")) {
344
348
  controlsUpgrade(plugin.id);
345
349
  controls.append(button("下载", `下载 ${plugin.id}`, async () => { await request(`/api/plugins/${encodeURIComponent(plugin.id)}/download`, "POST", { packageName: plugin.packageName, version: pluginVersions[plugin.id]?.latestVersion }); await load(); }));
@@ -367,6 +371,36 @@
367
371
  pluginsNode.append(row);
368
372
  }
369
373
  }
374
+ let configuringCli = "";
375
+ async function configureCli(plugin) {
376
+ const config = await request(`/api/plugins/${encodeURIComponent(plugin.id)}/config`);
377
+ configuringCli = plugin.id;
378
+ node("#cli-config-title").textContent = `${plugin.displayName} 配置`;
379
+ node("#cli-config-cwd").value = config.cwd ?? "";
380
+ node("#cli-config-executable").value = config.executablePath ?? "";
381
+ node("#cli-config-timeout").value = String(config.timeoutMs ?? 240000);
382
+ node("#cli-config-error").hidden = true;
383
+ node("#cli-config-dialog").showModal();
384
+ }
385
+ node("#cli-config-cancel").onclick = () => node("#cli-config-dialog").close();
386
+ node("#cli-config-form").onsubmit = event => {
387
+ event.preventDefault();
388
+ const save = node("#cli-config-save");
389
+ save.disabled = true;
390
+ void request(`/api/plugins/${encodeURIComponent(configuringCli)}/config`, "PATCH", {
391
+ cwd: node("#cli-config-cwd").value.trim(),
392
+ executablePath: node("#cli-config-executable").value.trim(),
393
+ timeoutMs: Number(node("#cli-config-timeout").value),
394
+ }).then(() => {
395
+ node("#cli-config-dialog").close();
396
+ showResult("CLI 配置已保存", "请启动插件,然后在 Channel 设置中关联 AID。", false);
397
+ return load(false);
398
+ }).catch(cause => {
399
+ const detail = node("#cli-config-error");
400
+ detail.textContent = String(cause);
401
+ detail.hidden = false;
402
+ }).finally(() => { save.disabled = false; });
403
+ };
370
404
  function renderMessages(messages) {
371
405
  messagesNode.replaceChildren();
372
406
  messagesEmpty.hidden = messages.length > 0;
@@ -1,5 +1,5 @@
1
1
  (() => {
2
- type Plugin = { id: string; displayName: string; version: string; status: string; type?: string; capabilities?: string[]; error?: string; path: string; packageName?: string; publisher?: string; trusted?: boolean; autoUpdate?: boolean; dependencyStatus?: string[]; manifest?: { dependencies?: Record<string, string>; managementPage?: string; clientDownloadUrl?: string } };
2
+ type Plugin = { id: string; displayName: string; version: string; status: string; type?: string; capabilities?: string[]; error?: string; path: string; packageName?: string; publisher?: string; trusted?: boolean; autoUpdate?: boolean; dependencyStatus?: string[]; manifest?: { executionMode?: "cli" | "cdp"; dependencies?: Record<string, string>; managementPage?: string; clientDownloadUrl?: string } };
3
3
  const node = <T extends HTMLElement>(selector: string): T => document.querySelector<T>(selector)!;
4
4
  const pluginsNode = node<HTMLTableSectionElement>("#plugins");
5
5
  const messagesNode = node<HTMLTableSectionElement>("#messages");
@@ -194,6 +194,7 @@
194
194
  const version = document.createElement("td"); version.textContent = `v${plugin.version}`;
195
195
  const state = document.createElement("td");
196
196
  const status = document.createElement("span"); status.className = `status status-${plugin.status}`; status.textContent = plugin.status;
197
+ if (plugin.type === "agent") type.textContent += ` · ${({ cli: "CLI", cdp: "CDP" } as Record<string, string>)[plugin.manifest?.executionMode ?? ""] ?? "未声明"}`;
197
198
  const dependencies = Object.entries(plugin.manifest?.dependencies ?? {});
198
199
  if (dependencies.length) { const detail = document.createElement("small"); detail.className = "muted plugin-id"; detail.textContent = `依赖:${dependencies.map(([id, range]) => `${id} ${range}`).join(";")}`; name.append(detail); }
199
200
  state.append(status);
@@ -205,6 +206,7 @@
205
206
  link.textContent = "下载客户端"; state.append(link);
206
207
  }
207
208
  const controls = document.createElement("td"); controls.className = "controls";
209
+ if (plugin.manifest?.executionMode === "cli") controls.append(button("配置", `配置 ${plugin.id}`, () => configureCli(plugin)));
208
210
  if (pluginVersions[plugin.id]?.state === "update-available" && plugin.path.includes("node_modules")) { controlsUpgrade(plugin.id); controls.append(button("下载", `下载 ${plugin.id}`, async () => { await request(`/api/plugins/${encodeURIComponent(plugin.id)}/download`, "POST", { packageName: plugin.packageName, version: pluginVersions[plugin.id]?.latestVersion }); await load(); })); }
209
211
  for (const [label, action] of [["启动", "start"], ["停止", "stop"], ["重载", "reload"]]) {
210
212
  controls.append(button(label, `${label} ${plugin.id}`, async () => { await request(`/api/plugins/${encodeURIComponent(plugin.id)}/${action}`, "POST"); await load(); }));
@@ -217,6 +219,33 @@
217
219
  }
218
220
  if (!items.length) { const row = document.createElement("tr"); const cell = document.createElement("td"); cell.colSpan = 5; cell.textContent = "暂无插件"; row.append(cell); pluginsNode.append(row); }
219
221
  }
222
+ let configuringCli = "";
223
+ async function configureCli(plugin: Plugin): Promise<void> {
224
+ const config = await request(`/api/plugins/${encodeURIComponent(plugin.id)}/config`);
225
+ configuringCli = plugin.id;
226
+ node<HTMLElement>("#cli-config-title").textContent = `${plugin.displayName} 配置`;
227
+ node<HTMLInputElement>("#cli-config-cwd").value = config.cwd ?? "";
228
+ node<HTMLInputElement>("#cli-config-executable").value = config.executablePath ?? "";
229
+ node<HTMLInputElement>("#cli-config-timeout").value = String(config.timeoutMs ?? 240000);
230
+ node<HTMLElement>("#cli-config-error").hidden = true;
231
+ node<HTMLDialogElement>("#cli-config-dialog").showModal();
232
+ }
233
+ node<HTMLButtonElement>("#cli-config-cancel").onclick = () => node<HTMLDialogElement>("#cli-config-dialog").close();
234
+ node<HTMLFormElement>("#cli-config-form").onsubmit = event => {
235
+ event.preventDefault();
236
+ const save = node<HTMLButtonElement>("#cli-config-save"); save.disabled = true;
237
+ void request(`/api/plugins/${encodeURIComponent(configuringCli)}/config`, "PATCH", {
238
+ cwd: node<HTMLInputElement>("#cli-config-cwd").value.trim(),
239
+ executablePath: node<HTMLInputElement>("#cli-config-executable").value.trim(),
240
+ timeoutMs: Number(node<HTMLInputElement>("#cli-config-timeout").value),
241
+ }).then(() => {
242
+ node<HTMLDialogElement>("#cli-config-dialog").close();
243
+ showResult("CLI 配置已保存", "请启动插件,然后在 Channel 设置中关联 AID。", false);
244
+ return load(false);
245
+ }).catch(cause => {
246
+ const detail = node<HTMLElement>("#cli-config-error"); detail.textContent = String(cause); detail.hidden = false;
247
+ }).finally(() => { save.disabled = false; });
248
+ };
220
249
  function renderMessages(messages: Array<{ time: string; pluginId: string; direction: "request" | "reply" | "error"; text: string; peer?: string; agentAid?: string }>): void {
221
250
  messagesNode.replaceChildren();
222
251
  messagesEmpty.hidden = messages.length > 0;
@@ -21,6 +21,16 @@
21
21
  <div id="logs-panel" role="tabpanel" aria-labelledby="logs-tab" hidden><section><div class="section-heading"><h2>运行日志</h2><button id="logs-refresh" type="button">刷新日志</button></div><div class="table-scroll"><table><thead><tr><th>时间</th><th>级别</th><th>来源</th><th>消息</th><th>详细字段</th></tr></thead><tbody id="logs"></tbody></table></div><p id="logs-empty" class="muted" hidden>暂无运行日志</p><div class="section-heading"><button id="logs-prev" type="button">上一页</button><span id="logs-page" class="muted">第 1 页</span><button id="logs-next" type="button">下一页</button></div></section></div>
22
22
  <p id="error" class="error" role="alert" hidden></p>
23
23
  </main>
24
+ <dialog id="cli-config-dialog" aria-labelledby="cli-config-title">
25
+ <h2 id="cli-config-title">CLI 配置</h2><p class="muted">沿用后台运行用户的 CLI 登录、默认模型及权限。AID 请在 Channel 设置关联。</p>
26
+ <form id="cli-config-form">
27
+ <label for="cli-config-cwd">工作目录(必填,绝对路径)</label><input id="cli-config-cwd" required placeholder="C:\Users\用户名\projects\demo">
28
+ <label for="cli-config-executable">CLI 程序路径(可选,留空使用 PATH)</label><input id="cli-config-executable" placeholder="例如 C:\Users\用户名\AppData\Roaming\npm\codex.cmd">
29
+ <label for="cli-config-timeout">任务超时(毫秒)</label><input id="cli-config-timeout" type="number" min="1" max="2147483647" required value="240000">
30
+ <p id="cli-config-error" class="error" role="alert" hidden></p>
31
+ <div><button id="cli-config-save" type="submit">保存配置</button><button id="cli-config-cancel" type="button">取消</button></div>
32
+ </form>
33
+ </dialog>
24
34
  <dialog id="operation-result" aria-labelledby="operation-result-title" aria-describedby="operation-result-message">
25
35
  <h2 id="operation-result-title">操作结果</h2><p id="operation-result-message"></p><button id="operation-result-close" type="button" autofocus>确定</button>
26
36
  </dialog>
@@ -60,3 +60,6 @@ th:nth-child(1) { width: 145px; } th:nth-child(2) { width: 100px; } th:nth-child
60
60
  #operation-result { width: min(520px, calc(100% - 32px)); border: 1px solid #bfc9c5; border-radius: 8px; padding: 24px; }
61
61
  #operation-result::backdrop { background: rgb(0 0 0 / 35%); }
62
62
  #operation-result-message { white-space: pre-wrap; overflow-wrap: anywhere; margin: 16px 0; }
63
+
64
+ #cli-config-form { display: grid; min-width: min(70vw, 480px); }
65
+ #cli-config-form input { width: 100%; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-bridge-abweb",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "agent-bridge 的网页管理插件。",
5
5
  "keywords": [
6
6
  "mu-agent-bridge-plugin",
package/plugin.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "abweb",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "type": "management",
5
5
  "displayName": "Agent Bridge Web",
6
6
  "entry": "dist/src-ts/plugins/abweb/index.js",