@ryubyte/dsh-a2a 0.1.2 → 0.1.4

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/lib/client.js CHANGED
@@ -54,6 +54,10 @@ window.__ModuleLoader__.load({
54
54
  const [tab, setTab] = (0, react.useState)("out");
55
55
  /** connection ids whose skill list is expanded in the outbound tab. */
56
56
  const [expanded, setExpanded] = (0, react.useState)(/* @__PURE__ */ new Set());
57
+ /** Optional bearer token for the add-agent form (outbound). */
58
+ const [addToken, setAddToken] = (0, react.useState)("");
59
+ /** Inbound authToken input (serve tab); empty string means "clear". */
60
+ const [authInput, setAuthInput] = (0, react.useState)("");
57
61
  const refresh = async () => {
58
62
  try {
59
63
  setError(null);
@@ -101,7 +105,8 @@ window.__ModuleLoader__.load({
101
105
  headers: { "content-type": "application/json" },
102
106
  body: JSON.stringify({
103
107
  action: "discover-agent",
104
- agentCardUrl: u
108
+ agentCardUrl: u,
109
+ bearerToken: addToken.trim() || void 0
105
110
  })
106
111
  })).json();
107
112
  if (!body.ok || !body.message) {
@@ -118,9 +123,13 @@ window.__ModuleLoader__.load({
118
123
  const doConnect = async () => {
119
124
  if (!discovered) return;
120
125
  const n = discovered.name.trim() || "remote";
121
- await act("add-agent", n, { agentCardUrl: discovered.agentCardUrl });
126
+ await act("add-agent", n, {
127
+ agentCardUrl: discovered.agentCardUrl,
128
+ bearerToken: addToken.trim() || void 0
129
+ });
122
130
  if (!busy) {
123
131
  setAddUrl("");
132
+ setAddToken("");
124
133
  setDiscovered(null);
125
134
  }
126
135
  };
@@ -196,7 +205,25 @@ window.__ModuleLoader__.load({
196
205
  flex: 1,
197
206
  minWidth: 260
198
207
  }
199
- }), actionBtn("导入", false, () => void doDiscover(), discovering || !addUrl.trim())), discovering ? (0, react.createElement)("div", { style: {
208
+ }), actionBtn("导入", false, () => void doDiscover(), discovering || !addUrl.trim())), (0, react.createElement)("div", { style: {
209
+ display: "flex",
210
+ alignItems: "center",
211
+ gap: 8,
212
+ flexWrap: "wrap"
213
+ } }, (0, react.createElement)("input", {
214
+ type: "password",
215
+ placeholder: "Bearer Token(可选,发送为 Authorization: Bearer …)",
216
+ value: addToken,
217
+ onChange: (e) => setAddToken(e.target.value),
218
+ style: {
219
+ ...inputStyle,
220
+ flex: 1,
221
+ minWidth: 260
222
+ }
223
+ })), (0, react.createElement)("div", { style: {
224
+ fontSize: 11.5,
225
+ color: "var(--dsw-alias-label-tertiary, #999)"
226
+ } }, "若远程 Agent 需要鉴权,填入 token;导入与后续调用都会带上。token 会明文存入 a2a.json。"), discovering ? (0, react.createElement)("div", { style: {
200
227
  fontSize: 13,
201
228
  color: "var(--dsw-alias-label-tertiary, #999)"
202
229
  } }, "正在读取 Agent Card…") : discovered ? (0, react.createElement)("div", { style: {
@@ -243,7 +270,7 @@ window.__ModuleLoader__.load({
243
270
  display: "flex",
244
271
  gap: 8,
245
272
  marginTop: 2
246
- } }, actionBtn("连接", true, () => void doConnect(), busy === "add-agent"), actionBtn("取消", false, () => {
273
+ } }, actionBtn("连接", true, () => void doConnect(), busy?.startsWith("add-agent:") ?? false), actionBtn("取消", false, () => {
247
274
  setDiscovered(null);
248
275
  setAddUrl("");
249
276
  }, false))) : (0, react.createElement)("div", { style: {
@@ -263,7 +290,7 @@ window.__ModuleLoader__.load({
263
290
  } }, sec("A2A 服务(本 DSH 作为 Agent 对外)", 0), stateDot(serve.enabled ? "connected" : "disconnected"), (0, react.createElement)("span", { style: {
264
291
  fontSize: 12.5,
265
292
  color: serve.enabled ? "#2e7d32" : "#9e9e9e"
266
- } }, serve.enabled ? "运行中" : "已下线"), (0, react.createElement)("span", { style: { marginLeft: "auto" } }, serve.enabled ? actionBtn("下线", false, () => void act("server-disable", ""), busy === "server-disable") : actionBtn("上线", true, () => void act("server-enable", ""), busy === "server-enable"))), (0, react.createElement)("div", { style: {
293
+ } }, serve.enabled ? "运行中" : "已下线"), (0, react.createElement)("span", { style: { marginLeft: "auto" } }, serve.enabled ? actionBtn("下线", false, () => void act("server-disable", ""), busy === "server-disable:") : actionBtn("上线", true, () => void act("server-enable", ""), busy === "server-enable:"))), (0, react.createElement)("div", { style: {
267
294
  display: "flex",
268
295
  flexDirection: "column",
269
296
  gap: 6
@@ -301,13 +328,7 @@ window.__ModuleLoader__.load({
301
328
  fontSize: 12.5,
302
329
  color: "var(--dsw-alias-label-primary, #222)"
303
330
  }
304
- }, `• ${s.name}${s.description ? ` — ${s.description}` : ""}`))) : null), serve.enabled && !serve.customExecutor ? (0, react.createElement)("div", { style: {
305
- fontSize: 12,
306
- color: "var(--dsw-warning, #b26a00)",
307
- background: "rgba(178,106,0,.08)",
308
- borderRadius: 6,
309
- padding: "6px 10px"
310
- } }, "⚠ 默认 executor 会执行 shell 命令。生产环境请通过配置指定受限的 execute 实现。") : null) : null, tab === "in" ? (0, react.createElement)("div", { style: {
331
+ }, `• ${s.name}${s.description ? ` — ${s.description}` : ""}`))) : null), serve.enabled ? executorNote(serve) : null, serve.enabled ? authControl(serve, busy, act, authInput, setAuthInput) : null) : null, tab === "in" ? (0, react.createElement)("div", { style: {
311
332
  display: "flex",
312
333
  flexDirection: "column",
313
334
  gap: 10
@@ -557,6 +578,83 @@ window.__ModuleLoader__.load({
557
578
  }
558
579
  }, label);
559
580
  }
581
+ /**
582
+ * A semantically-correct note about how inbound tasks are executed. Dispatches
583
+ * on the `executor` field; falls back to the legacy `customExecutor` boolean
584
+ * for snapshots from an older host that didn't send `executor`.
585
+ */
586
+ function executorNote(serve) {
587
+ const kind = serve.executor ?? (serve.customExecutor ? "custom" : void 0);
588
+ if (kind === "custom") return null;
589
+ if (kind === "dsh-agent") return (0, react.createElement)("div", { style: {
590
+ fontSize: 12,
591
+ color: "var(--dsw-alias-label-secondary, #666)",
592
+ background: "rgba(74,125,255,.08)",
593
+ borderRadius: 6,
594
+ padding: "6px 10px"
595
+ } }, "ℹ 入站任务由本 DSH 的 agent 会话执行,按 A2A contextId 一个对话一个会话。");
596
+ if (kind === "none") return (0, react.createElement)("div", { style: {
597
+ fontSize: 12,
598
+ color: "var(--dsw-warning, #b26a00)",
599
+ background: "rgba(178,106,0,.08)",
600
+ borderRadius: 6,
601
+ padding: "6px 10px"
602
+ } }, "⚠ 未配置 executor,且未检测到可用的 agent 循环:入站任务会被拒绝。通过配置注入 execute,或加载 agent-loop 插件。");
603
+ return null;
604
+ }
605
+ /**
606
+ * Inbound bearer-token control for the serve tab: shows whether the endpoint is
607
+ * token-gated, and lets the operator set or clear the shared token. The token
608
+ * value is never read back from the host — only whether one is configured.
609
+ */
610
+ function authControl(serve, busy, act, authInput, setAuthInput) {
611
+ return (0, react.createElement)("div", { style: {
612
+ display: "flex",
613
+ flexDirection: "column",
614
+ gap: 6,
615
+ marginTop: 4
616
+ } }, (0, react.createElement)("div", { style: {
617
+ display: "flex",
618
+ alignItems: "center",
619
+ gap: 8
620
+ } }, (0, react.createElement)("span", { style: {
621
+ fontSize: 12.5,
622
+ fontWeight: 600,
623
+ color: "var(--dsw-alias-label-primary, #222)"
624
+ } }, "入站鉴权"), stateDot(serve.authConfigured ? "connected" : "disabled"), (0, react.createElement)("span", { style: {
625
+ fontSize: 12,
626
+ color: serve.authConfigured ? "#2e7d32" : "#9e9e9e"
627
+ } }, serve.authConfigured ? "已启用 Bearer 鉴权" : "未鉴权(任何客户端可调用)")), (0, react.createElement)("div", { style: {
628
+ display: "flex",
629
+ alignItems: "center",
630
+ gap: 8,
631
+ flexWrap: "wrap"
632
+ } }, (0, react.createElement)("input", {
633
+ type: "password",
634
+ placeholder: serve.authConfigured ? "输入新 token 以替换" : "设置 Bearer Token 以开启鉴权",
635
+ value: authInput,
636
+ onChange: (e) => setAuthInput(e.target.value),
637
+ style: {
638
+ padding: "4px 8px",
639
+ fontSize: 13,
640
+ borderRadius: 6,
641
+ border: "1px solid var(--dsw-alias-border-l2, rgba(127,127,127,.3))",
642
+ background: "var(--dsw-alias-fill-l1, rgba(127,127,127,.06))",
643
+ color: "var(--dsw-alias-label-primary, #222)",
644
+ flex: 1,
645
+ minWidth: 220
646
+ }
647
+ }), actionBtn("保存", true, () => {
648
+ act("set-server-auth", "", { authToken: authInput.trim() });
649
+ setAuthInput("");
650
+ }, busy === "set-server-auth:" || !authInput.trim()), serve.authConfigured ? actionBtn("清除", false, () => {
651
+ act("set-server-auth", "", { authToken: "" });
652
+ setAuthInput("");
653
+ }, busy === "set-server-auth:") : null), (0, react.createElement)("div", { style: {
654
+ fontSize: 11.5,
655
+ color: "var(--dsw-alias-label-tertiary, #999)"
656
+ } }, "token 会明文存入 a2a.json,重启后仍生效。设置后,入站 JSON-RPC 请求需带 Authorization: Bearer <token>。"));
657
+ }
560
658
  function inboundRow(p, busy, act) {
561
659
  return (0, react.createElement)("tr", { key: p.id }, (0, react.createElement)("td", { style: tdStyle }, p.label), (0, react.createElement)("td", { style: {
562
660
  ...tdStyle,