@hanphone/dsh-a2a 0.2.0 → 0.3.1

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 (78) hide show
  1. package/README.md +106 -106
  2. package/README.zh.md +50 -74
  3. package/cordis.patch.yml +4 -7
  4. package/lib/client.js +186 -73
  5. package/lib/index.js +1275 -868
  6. package/lib/types/api.d.ts +30 -23
  7. package/lib/types/api.d.ts.map +1 -1
  8. package/lib/types/api.js +56 -23
  9. package/lib/types/api.js.map +1 -1
  10. package/lib/types/client/index.d.ts +50 -19
  11. package/lib/types/client/index.d.ts.map +1 -1
  12. package/lib/types/commands.d.ts +4 -2
  13. package/lib/types/commands.d.ts.map +1 -1
  14. package/lib/types/commands.js +59 -46
  15. package/lib/types/commands.js.map +1 -1
  16. package/lib/types/events.d.ts +32 -9
  17. package/lib/types/events.d.ts.map +1 -1
  18. package/lib/types/index.d.ts +21 -32
  19. package/lib/types/index.d.ts.map +1 -1
  20. package/lib/types/index.js +177 -272
  21. package/lib/types/index.js.map +1 -1
  22. package/lib/types/outbound/calls.d.ts.map +1 -1
  23. package/lib/types/outbound/calls.js +8 -6
  24. package/lib/types/outbound/calls.js.map +1 -1
  25. package/lib/types/protocol.d.ts +174 -109
  26. package/lib/types/protocol.d.ts.map +1 -1
  27. package/lib/types/protocol.js +58 -34
  28. package/lib/types/protocol.js.map +1 -1
  29. package/lib/types/server/a2a-server.d.ts +4 -0
  30. package/lib/types/server/a2a-server.d.ts.map +1 -1
  31. package/lib/types/server/a2a-server.js +6 -2
  32. package/lib/types/server/a2a-server.js.map +1 -1
  33. package/lib/types/server/card.d.ts +6 -30
  34. package/lib/types/server/card.d.ts.map +1 -1
  35. package/lib/types/server/card.js +13 -49
  36. package/lib/types/server/card.js.map +1 -1
  37. package/lib/types/server/exec/agent-runtime.d.ts +20 -0
  38. package/lib/types/server/exec/agent-runtime.d.ts.map +1 -1
  39. package/lib/types/server/exec/agent-runtime.js +2 -1
  40. package/lib/types/server/exec/agent-runtime.js.map +1 -1
  41. package/lib/types/server/routes.d.ts +5 -1
  42. package/lib/types/server/routes.d.ts.map +1 -1
  43. package/lib/types/server/routes.js +9 -5
  44. package/lib/types/server/routes.js.map +1 -1
  45. package/lib/types/server/store.d.ts +32 -0
  46. package/lib/types/server/store.d.ts.map +1 -1
  47. package/lib/types/server/store.js +10 -0
  48. package/lib/types/server/store.js.map +1 -1
  49. package/lib/types/servers/inbound-manager.d.ts +154 -0
  50. package/lib/types/servers/inbound-manager.d.ts.map +1 -0
  51. package/lib/types/servers/inbound-manager.js +335 -0
  52. package/lib/types/servers/inbound-manager.js.map +1 -0
  53. package/lib/types/servers/outbound-manager.d.ts +129 -0
  54. package/lib/types/servers/outbound-manager.d.ts.map +1 -0
  55. package/lib/types/servers/outbound-manager.js +238 -0
  56. package/lib/types/servers/outbound-manager.js.map +1 -0
  57. package/lib/types/service.d.ts +104 -40
  58. package/lib/types/service.d.ts.map +1 -1
  59. package/lib/types/service.js +36 -27
  60. package/lib/types/service.js.map +1 -1
  61. package/package.json +2 -2
  62. package/src/api.ts +65 -53
  63. package/src/client/index.ts +272 -148
  64. package/src/commands.ts +59 -43
  65. package/src/events.ts +14 -7
  66. package/src/index.ts +203 -310
  67. package/src/outbound/calls.ts +8 -6
  68. package/src/protocol.ts +204 -95
  69. package/src/server/a2a-server.ts +9 -2
  70. package/src/server/card.ts +13 -62
  71. package/src/server/exec/agent-runtime.ts +20 -2
  72. package/src/server/routes.ts +6 -4
  73. package/src/server/store.ts +42 -3
  74. package/src/servers/inbound-manager.ts +416 -0
  75. package/src/servers/outbound-manager.ts +289 -0
  76. package/src/service.ts +125 -40
  77. package/lib/tsconfig.client.tsbuildinfo +0 -1
  78. package/lib/tsconfig.tsbuildinfo +0 -1
package/lib/client.js CHANGED
@@ -17,7 +17,7 @@ window.__ModuleLoader__.load({
17
17
  .dsh-a2a-panel { display: flex; flex-direction: column; gap: 16px; padding: 12px 0; }
18
18
  .dsh-a2a-card { border: 1px solid var(--dsw-alias-border, #d0d7de); border-radius: 8px; padding: 12px 14px; }
19
19
  .dsh-a2a-card h3 { margin: 0 0 8px; font-size: 14px; }
20
- .dsh-a2a-row { display: flex; align-items: center; gap: 8px; margin: 4px 0; }
20
+ .dsh-a2a-row { display: flex; align-items: center; gap: 8px; margin: 4px 0; flex-wrap: wrap; }
21
21
  .dsh-a2a-row .muted { color: var(--dsw-alias-text-secondary, #59636e); font-size: 12px; }
22
22
  .dsh-a2a-row button { padding: 2px 10px; border-radius: 6px; border: 1px solid var(--dsw-alias-border, #d0d7de); background: transparent; cursor: pointer; }
23
23
  .dsh-a2a-row button.primary { background: var(--dsw-alias-accent, #0f6); color: var(--dsw-alias-bg, #fff); border-color: transparent; }
@@ -25,10 +25,13 @@ window.__ModuleLoader__.load({
25
25
  .dsh-a2a-state.ok { background: #1a7f3722; color: #1a7f37; }
26
26
  .dsh-a2a-state.bad { background: #d1242f22; color: #d1242f; }
27
27
  .dsh-a2a-form { display: flex; gap: 6px; margin: 8px 0; flex-wrap: wrap; }
28
- .dsh-a2a-form input { padding: 4px 8px; border-radius: 6px; border: 1px solid var(--dsw-alias-border, #d0d7de); background: transparent; color: inherit; }
28
+ .dsh-a2a-form input, .dsh-a2a-form select, .dsh-a2a-form textarea { padding: 4px 8px; border-radius: 6px; border: 1px solid var(--dsw-alias-border, #d0d7de); background: transparent; color: inherit; }
29
+ .dsh-a2a-form textarea { font-family: inherit; width: 100%; min-height: 64px; resize: vertical; }
29
30
  .dsh-a2a-table { width: 100%; border-collapse: collapse; font-size: 13px; }
30
- .dsh-a2a-table th, .dsh-a2a-table td { text-align: left; padding: 4px 8px; border-bottom: 1px solid var(--dsw-alias-border, #d0d7de); }
31
+ .dsh-a2a-table th, .dsh-a2a-table td { text-align: left; padding: 4px 8px; border-bottom: 1px solid var(--dsw-alias-border, #d0d7de); vertical-align: top; }
32
+ .dsh-a2a-skill { display: inline-block; margin: 1px 4px 1px 0; padding: 0 6px; border-radius: 10px; background: #6e778122; font-size: 12px; }
31
33
  .dsh-a2a-error { color: #d1242f; font-size: 12px; }
34
+ .dsh-a2a-hint { color: var(--dsw-alias-text-secondary, #59636e); font-size: 12px; margin: 2px 0 6px; }
32
35
  `;
33
36
  document.head.appendChild(tag);
34
37
  return () => tag.remove();
@@ -48,6 +51,11 @@ window.__ModuleLoader__.load({
48
51
  if (!res.ok) throw new Error(`snapshot HTTP ${res.status}`);
49
52
  return await res.json();
50
53
  }
54
+ async function fetchPresets() {
55
+ const res = await fetch("/a2a/api/presets", { headers: { accept: "application/json" } });
56
+ if (!res.ok) return [];
57
+ return await res.json();
58
+ }
51
59
  async function postControl(payload) {
52
60
  const res = await fetch("/a2a/api", {
53
61
  method: "POST",
@@ -61,27 +69,32 @@ window.__ModuleLoader__.load({
61
69
  }
62
70
  function A2aSection(_props) {
63
71
  const [snap, setSnap] = (0, react.useState)(void 0);
72
+ const [presets, setPresets] = (0, react.useState)([]);
64
73
  const [error, setError] = (0, react.useState)(void 0);
65
- const [agentName, setAgentName] = (0, react.useState)("");
66
- const [agentUrl, setAgentUrl] = (0, react.useState)("");
67
74
  const [busy, setBusy] = (0, react.useState)(false);
68
- const [editing, setEditing] = (0, react.useState)(false);
69
- const [idName, setIdName] = (0, react.useState)("");
70
- const [idDescription, setIdDescription] = (0, react.useState)("");
71
- const [idVersion, setIdVersion] = (0, react.useState)("");
75
+ const [editingIn, setEditingIn] = (0, react.useState)(void 0);
76
+ const [inName, setInName] = (0, react.useState)("");
77
+ const [inDesc, setInDesc] = (0, react.useState)("");
78
+ const [inVersion, setInVersion] = (0, react.useState)("1.0.0");
79
+ const [inPreset, setInPreset] = (0, react.useState)("");
80
+ const [inAuthEnv, setInAuthEnv] = (0, react.useState)("");
81
+ const [outName, setOutName] = (0, react.useState)("");
82
+ const [outUrl, setOutUrl] = (0, react.useState)("");
83
+ const [outPreset, setOutPreset] = (0, react.useState)("");
84
+ const [outTokenEnv, setOutTokenEnv] = (0, react.useState)("");
85
+ const [outTimeout, setOutTimeout] = (0, react.useState)("60000");
72
86
  (0, react.useEffect)(() => {
73
87
  let alive = true;
74
88
  const tick = async () => {
75
89
  try {
76
- const next = await fetchSnapshot();
90
+ const [next, presetRows] = await Promise.all([fetchSnapshot(), fetchPresets()]);
77
91
  if (alive) {
78
92
  setSnap(next);
93
+ setPresets(presetRows);
94
+ const def = presetRows.find((p) => p.isDefault)?.id;
95
+ setInPreset((current) => current === "" && def !== void 0 ? def : current);
96
+ setOutPreset((current) => current === "" && def !== void 0 ? def : current);
79
97
  setError(void 0);
80
- if (!editing) {
81
- setIdName(next.server.name ?? "");
82
- setIdDescription(next.server.description ?? "");
83
- setIdVersion(next.server.version ?? "");
84
- }
85
98
  }
86
99
  } catch (err) {
87
100
  if (alive) setError(err.message);
@@ -106,97 +119,197 @@ window.__ModuleLoader__.load({
106
119
  setBusy(false);
107
120
  }
108
121
  };
109
- const server = snap?.server;
110
- const agents = snap?.agents ?? [];
122
+ const startCreateInbound = () => {
123
+ setEditingIn(void 0);
124
+ setInName("");
125
+ setInDesc("");
126
+ setInVersion("1.0.0");
127
+ setInPreset(presets.find((p) => p.isDefault)?.id ?? "");
128
+ setInAuthEnv("");
129
+ };
130
+ const submitInbound = () => {
131
+ if (!inName.trim()) return;
132
+ if (editingIn !== void 0) {
133
+ control({
134
+ action: "inbound.update",
135
+ id: editingIn,
136
+ name: inName.trim(),
137
+ description: inDesc.trim(),
138
+ version: inVersion.trim() || "1.0.0",
139
+ ...inPreset !== "" ? { preset: inPreset } : {},
140
+ ...inAuthEnv.trim() !== "" ? { authTokenEnv: inAuthEnv.trim() } : {}
141
+ }).then(() => setEditingIn(void 0));
142
+ return;
143
+ }
144
+ control({
145
+ action: "inbound.create",
146
+ name: inName.trim(),
147
+ description: inDesc.trim() || "An A2A inbound server",
148
+ version: inVersion.trim() || "1.0.0",
149
+ ...inPreset !== "" ? { preset: inPreset } : {},
150
+ ...inAuthEnv.trim() !== "" ? { authTokenEnv: inAuthEnv.trim() } : {}
151
+ }).then(() => startCreateInbound());
152
+ };
153
+ const beginEditInbound = (v) => {
154
+ setEditingIn(v.id);
155
+ setInName(v.name);
156
+ setInDesc(v.description);
157
+ setInVersion(v.version);
158
+ setInPreset(v.preset ?? presets.find((p) => p.isDefault)?.id ?? "");
159
+ setInAuthEnv(v.authTokenEnv ?? "");
160
+ };
161
+ const submitOutbound = () => {
162
+ if (!outName.trim() || !outUrl.trim()) return;
163
+ const timeout = Number.parseInt(outTimeout, 10);
164
+ control({
165
+ action: "outbound.create",
166
+ name: outName.trim(),
167
+ agentCardUrl: outUrl.trim(),
168
+ ...outPreset !== "" ? { preset: outPreset } : {},
169
+ ...outTokenEnv.trim() !== "" ? { bearerTokenEnv: outTokenEnv.trim() } : {},
170
+ ...Number.isFinite(timeout) && timeout > 0 ? { timeoutMs: timeout } : {}
171
+ }).then(() => {
172
+ setOutName("");
173
+ setOutUrl("");
174
+ setOutPreset(presets.find((p) => p.isDefault)?.id ?? "");
175
+ setOutTokenEnv("");
176
+ });
177
+ };
111
178
  const inbounds = snap?.inbounds ?? [];
179
+ const outbounds = snap?.outbounds ?? [];
180
+ const peers = snap?.peers ?? [];
112
181
  const tasks = snap?.tasks ?? [];
113
- return (0, react.createElement)("div", { className: "dsh-a2a-panel" }, error !== void 0 ? (0, react.createElement)("div", { className: "dsh-a2a-error" }, error) : null, (0, react.createElement)("div", { className: "dsh-a2a-card" }, (0, react.createElement)("h3", null, "入站 Server"), server === void 0 ? (0, react.createElement)("div", { className: "muted" }, "加载中…") : (0, react.createElement)("div", { className: "dsh-a2a-row" }, (0, react.createElement)("span", { className: `dsh-a2a-state ${server.enabled ? "ok" : "bad"}` }, server.enabled ? "已启用" : "已停用"), (0, react.createElement)("button", {
114
- className: server.enabled ? "" : "primary",
182
+ return (0, react.createElement)("div", { className: "dsh-a2a-panel" }, error !== void 0 ? (0, react.createElement)("div", { className: "dsh-a2a-error" }, error) : null, (0, react.createElement)("div", { className: "dsh-a2a-card" }, (0, react.createElement)("h3", null, `入站 Servers(${inbounds.length})`), inbounds.length === 0 ? (0, react.createElement)("div", { className: "muted" }, "还没有入站 server。创建一个即可对外发布 A2A 端点。") : (0, react.createElement)("table", { className: "dsh-a2a-table" }, (0, react.createElement)("thead", null, (0, react.createElement)("tr", null, (0, react.createElement)("th", null, "名称 / 端点"), (0, react.createElement)("th", null, "Preset"), (0, react.createElement)("th", null, "技能宣告"), (0, react.createElement)("th", null, "状态"), (0, react.createElement)("th", null, "操作"))), (0, react.createElement)("tbody", null, ...inbounds.map((v) => (0, react.createElement)("tr", { key: v.id }, (0, react.createElement)("td", null, (0, react.createElement)("div", null, v.name), (0, react.createElement)("div", { className: "muted" }, `${v.endpointPath} · ${v.cardUrl ?? v.cardPath}`), v.authTokenEnv !== void 0 && v.authTokenEnv !== "" ? (0, react.createElement)("div", { className: "muted" }, `鉴权: $${v.authTokenEnv}`) : null), (0, react.createElement)("td", null, v.preset ?? (0, react.createElement)("span", { className: "muted" }, "默认")), (0, react.createElement)("td", null, (0, react.createElement)("div", null, ...v.skills.map((s) => (0, react.createElement)("span", {
183
+ className: "dsh-a2a-skill",
184
+ key: s.id,
185
+ title: s.description ?? ""
186
+ }, s.name)))), (0, react.createElement)("td", null, (0, react.createElement)("span", { className: `dsh-a2a-state ${v.enabled ? "ok" : "bad"}` }, v.enabled ? "运行中" : "已停用")), (0, react.createElement)("td", null, (0, react.createElement)("button", {
187
+ disabled: busy,
188
+ onClick: () => void control({
189
+ action: v.enabled ? "inbound.disable" : "inbound.enable",
190
+ id: v.id
191
+ })
192
+ }, v.enabled ? "停用" : "启用"), " ", (0, react.createElement)("button", {
193
+ disabled: busy,
194
+ onClick: () => beginEditInbound(v)
195
+ }, "编辑"), " ", (0, react.createElement)("button", {
115
196
  disabled: busy,
116
- onClick: () => void control({ action: server.enabled ? "server.disable" : "server.enable" })
117
- }, server.enabled ? "停用" : "启用")), server !== void 0 && server.enabled ? (0, react.createElement)("div", { className: "dsh-a2a-row muted" }, `AgentCard: ${server.cardUrl ?? "(n/a)"} · 技能: ${server.skills.join(", ") || "(chat)"}`) : null), (0, react.createElement)("div", { className: "dsh-a2a-card" }, server === void 0 || server.configured === false ? (0, react.createElement)("h3", null, "服务身份(首次配置)") : (0, react.createElement)("h3", null, "服务身份"), (0, react.createElement)("form", {
197
+ onClick: () => void control({
198
+ action: "inbound.remove",
199
+ id: v.id
200
+ })
201
+ }, "删除")))))), (0, react.createElement)("h3", { style: { marginTop: "12px" } }, editingIn !== void 0 ? "编辑入站 Server" : "新建入站 Server"), (0, react.createElement)("form", {
118
202
  className: "dsh-a2a-form",
119
203
  onSubmit: (ev) => {
120
204
  ev.preventDefault();
121
- control({
122
- action: "identity.update",
123
- name: idName,
124
- description: idDescription,
125
- version: idVersion
126
- }).then(() => {
127
- setEditing(false);
128
- });
205
+ submitInbound();
129
206
  }
130
207
  }, (0, react.createElement)("input", {
131
- value: idVersion,
132
- placeholder: "版本",
133
- onChange: (e) => setIdVersion(e.target.value),
134
- style: { width: "60px" }
135
- }), (0, react.createElement)("input", {
136
- value: idName,
137
- placeholder: "服务名称",
138
- onChange: (e) => setIdName(e.target.value),
139
- style: { width: "160px" }
208
+ value: inName,
209
+ placeholder: "名称",
210
+ onChange: (e) => setInName(e.target.value)
140
211
  }), (0, react.createElement)("input", {
141
- value: idDescription,
142
- placeholder: "服务描述",
143
- onChange: (e) => setIdDescription(e.target.value),
144
- style: { width: "260px" }
212
+ value: inVersion,
213
+ placeholder: "版本",
214
+ onChange: (e) => setInVersion(e.target.value),
215
+ style: { width: "70px" }
216
+ }), (0, react.createElement)("select", {
217
+ value: inPreset,
218
+ onChange: (e) => setInPreset(e.target.value)
219
+ }, ...presets.map((p) => (0, react.createElement)("option", {
220
+ value: p.id,
221
+ key: p.id,
222
+ title: p.description ?? p.id
223
+ }, p.name ?? p.id))), (0, react.createElement)("input", {
224
+ value: inAuthEnv,
225
+ placeholder: "鉴权 env 变量名(可选)",
226
+ onChange: (e) => setInAuthEnv(e.target.value)
227
+ })), (0, react.createElement)("form", {
228
+ className: "dsh-a2a-form",
229
+ onSubmit: (ev) => {
230
+ ev.preventDefault();
231
+ submitInbound();
232
+ },
233
+ style: { alignItems: "flex-end" }
234
+ }, (0, react.createElement)("input", {
235
+ value: inDesc,
236
+ placeholder: "描述",
237
+ onChange: (e) => setInDesc(e.target.value),
238
+ style: {
239
+ flex: 1,
240
+ minWidth: "260px"
241
+ }
145
242
  }), (0, react.createElement)("button", {
146
243
  type: "submit",
147
244
  className: "primary",
148
- disabled: busy
149
- }, "保存身份")), (0, react.createElement)("div", { className: "dsh-a2a-row muted" }, "名称、描述、版本即刻重建 AgentCard;技能始终从工具注册表派生。")), (0, react.createElement)("div", { className: "dsh-a2a-card" }, (0, react.createElement)("h3", null, `入站连接(${inbounds.length})`), inbounds.length === 0 ? (0, react.createElement)("div", { className: "muted" }, "当前无远程对端正在调用本服务。") : (0, react.createElement)("table", { className: "dsh-a2a-table" }, (0, react.createElement)("thead", null, (0, react.createElement)("tr", null, (0, react.createElement)("th", null, "来源"), (0, react.createElement)("th", null, "任务"), (0, react.createElement)("th", null, "流式"), (0, react.createElement)("th", null, "首次 / 最近"), (0, react.createElement)("th", null, "操作"))), (0, react.createElement)("tbody", null, ...inbounds.map((p) => (0, react.createElement)("tr", { key: p.id }, (0, react.createElement)("td", null, p.source ?? p.label), (0, react.createElement)("td", null, `${p.taskCount}(活跃 ${p.activeTaskIds.length})`), (0, react.createElement)("td", null, p.streaming ? "●" : "—"), (0, react.createElement)("td", null, (0, react.createElement)("span", { className: "muted" }, `${p.firstSeen ?? ""} / ${p.lastSeen ?? ""}`)), (0, react.createElement)("td", null, (0, react.createElement)("button", {
245
+ disabled: busy || !inName.trim()
246
+ }, editingIn !== void 0 ? "保存修改" : "创建 Server"), editingIn !== void 0 ? (0, react.createElement)("button", {
247
+ type: "button",
150
248
  disabled: busy,
151
- onClick: () => void control({
152
- action: "inbound.close",
153
- id: p.id
154
- })
155
- }, "关闭"))))))), (0, react.createElement)("div", { className: "dsh-a2a-card" }, (0, react.createElement)("h3", null, `出站 Agents(${agents.length})`), agents.length === 0 ? (0, react.createElement)("div", { className: "muted" }, "未配置远程 agent。") : (0, react.createElement)("table", { className: "dsh-a2a-table" }, (0, react.createElement)("thead", null, (0, react.createElement)("tr", null, (0, react.createElement)("th", null, "名称"), (0, react.createElement)("th", null, "状态"), (0, react.createElement)("th", null, "工具"), (0, react.createElement)("th", null, "操作"))), (0, react.createElement)("tbody", null, ...agents.map((a) => (0, react.createElement)("tr", { key: a.id }, (0, react.createElement)("td", null, (0, react.createElement)("div", null, a.name), (0, react.createElement)("div", { className: "muted" }, a.agentCardUrl), a.lastError !== void 0 ? (0, react.createElement)("div", { className: "dsh-a2a-error" }, a.lastError) : null), (0, react.createElement)("td", null, (0, react.createElement)("span", { className: `dsh-a2a-state ${a.state === "connected" ? "ok" : "bad"}` }, a.state)), (0, react.createElement)("td", null, `${a.toolCount} / ${a.skillCount}`), (0, react.createElement)("td", null, (0, react.createElement)("button", {
249
+ onClick: () => startCreateInbound()
250
+ }, "取消") : null), (0, react.createElement)("div", { className: "dsh-a2a-hint" }, "该 server 绑定的 preset 决定其技能(一切皆插件):AgentCard 技能 = 该 preset 可用的模型技能,创建后自动派生。")), (0, react.createElement)("div", { className: "dsh-a2a-card" }, (0, react.createElement)("h3", null, `出站 Servers(${outbounds.length})`), outbounds.length === 0 ? (0, react.createElement)("div", { className: "muted" }, "还没有出站 server。添加一个远端 A2A 连接即可把其技能注册为模型工具。") : (0, react.createElement)("table", { className: "dsh-a2a-table" }, (0, react.createElement)("thead", null, (0, react.createElement)("tr", null, (0, react.createElement)("th", null, "名称 / 远端"), (0, react.createElement)("th", null, "Preset"), (0, react.createElement)("th", null, "状态"), (0, react.createElement)("th", null, "工具"), (0, react.createElement)("th", null, "操作"))), (0, react.createElement)("tbody", null, ...outbounds.map((v) => (0, react.createElement)("tr", { key: v.id }, (0, react.createElement)("td", null, (0, react.createElement)("div", null, v.name), (0, react.createElement)("div", { className: "muted" }, v.agentCardUrl), v.lastError !== void 0 ? (0, react.createElement)("div", { className: "dsh-a2a-error" }, v.lastError) : null), (0, react.createElement)("td", null, v.preset ?? (0, react.createElement)("span", { className: "muted" }, "默认")), (0, react.createElement)("td", null, (0, react.createElement)("span", { className: `dsh-a2a-state ${v.state === "connected" ? "ok" : "bad"}` }, v.state === "connected" ? "已连接" : v.state)), (0, react.createElement)("td", null, `${v.toolCount} / ${v.skillCount}`), (0, react.createElement)("td", null, (0, react.createElement)("button", {
156
251
  disabled: busy,
157
252
  onClick: () => void control({
158
- action: a.enabled ? "agent.disable" : "agent.enable",
159
- id: a.id
253
+ action: v.enabled ? "outbound.disable" : "outbound.enable",
254
+ id: v.id
160
255
  })
161
- }, a.enabled ? "停用" : "启用"), " ", (0, react.createElement)("button", {
256
+ }, v.enabled ? "停用" : "启用"), " ", (0, react.createElement)("button", {
162
257
  disabled: busy,
163
258
  onClick: () => void control({
164
- action: "agent.refresh",
165
- id: a.id
259
+ action: "outbound.refresh",
260
+ id: v.id
166
261
  })
167
262
  }, "刷新"), " ", (0, react.createElement)("button", {
168
263
  disabled: busy,
169
264
  onClick: () => void control({
170
- action: "agent.remove",
171
- id: a.id
265
+ action: "outbound.remove",
266
+ id: v.id
172
267
  })
173
- }, "删除")))))), (0, react.createElement)("form", {
268
+ }, "删除")))))), (0, react.createElement)("h3", { style: { marginTop: "12px" } }, "新建出站 Server"), (0, react.createElement)("form", {
174
269
  className: "dsh-a2a-form",
175
270
  onSubmit: (ev) => {
176
271
  ev.preventDefault();
177
- if (!agentName.trim() || !agentUrl.trim()) return;
178
- control({
179
- action: "agent.add",
180
- name: agentName.trim(),
181
- agentCardUrl: agentUrl.trim()
182
- }).then(() => {
183
- setAgentName("");
184
- setAgentUrl("");
185
- });
272
+ submitOutbound();
186
273
  }
187
274
  }, (0, react.createElement)("input", {
188
- value: agentName,
275
+ value: outName,
189
276
  placeholder: "名称",
190
- onChange: (e) => setAgentName(e.target.value)
277
+ onChange: (e) => setOutName(e.target.value)
191
278
  }), (0, react.createElement)("input", {
192
- value: agentUrl,
193
- placeholder: "AgentCard URL",
194
- onChange: (e) => setAgentUrl(e.target.value)
279
+ value: outUrl,
280
+ placeholder: "远端 AgentCard URL",
281
+ onChange: (e) => setOutUrl(e.target.value),
282
+ style: {
283
+ flex: 1,
284
+ minWidth: "240px"
285
+ }
286
+ }), (0, react.createElement)("select", {
287
+ value: outPreset,
288
+ onChange: (e) => setOutPreset(e.target.value)
289
+ }, ...presets.map((p) => (0, react.createElement)("option", {
290
+ value: p.id,
291
+ key: p.id,
292
+ title: p.description ?? p.id
293
+ }, p.name ?? p.id))), (0, react.createElement)("input", {
294
+ value: outTokenEnv,
295
+ placeholder: "Bearer env 变量名(可选)",
296
+ onChange: (e) => setOutTokenEnv(e.target.value)
297
+ }), (0, react.createElement)("input", {
298
+ value: outTimeout,
299
+ placeholder: "超时 ms",
300
+ onChange: (e) => setOutTimeout(e.target.value),
301
+ style: { width: "90px" }
195
302
  }), (0, react.createElement)("button", {
196
303
  type: "submit",
197
304
  className: "primary",
198
- disabled: busy
199
- }, "添加 Agent"))), (0, react.createElement)("div", { className: "dsh-a2a-card" }, (0, react.createElement)("h3", null, `任务(${tasks.length})`), tasks.length === 0 ? (0, react.createElement)("div", { className: "muted" }, "暂无任务。") : (0, react.createElement)("table", { className: "dsh-a2a-table" }, (0, react.createElement)("thead", null, (0, react.createElement)("tr", null, (0, react.createElement)("th", null, "ID"), (0, react.createElement)("th", null, "技能"), (0, react.createElement)("th", null, "状态"), (0, react.createElement)("th", null, "操作"))), (0, react.createElement)("tbody", null, ...tasks.slice(-20).reverse().map((t) => (0, react.createElement)("tr", { key: t.id }, (0, react.createElement)("td", null, (0, react.createElement)("span", { className: "muted" }, t.id)), (0, react.createElement)("td", null, t.metadata?.skill ?? "-"), (0, react.createElement)("td", null, t.status?.state ?? "-"), (0, react.createElement)("td", null, (0, react.createElement)("button", {
305
+ disabled: busy || !outName.trim() || !outUrl.trim()
306
+ }, "添加出站 Server"))), (0, react.createElement)("div", { className: "dsh-a2a-card" }, (0, react.createElement)("h3", null, `入站连接(${peers.length})`), peers.length === 0 ? (0, react.createElement)("div", { className: "muted" }, "当前无远程对端正在调用本服务。") : (0, react.createElement)("table", { className: "dsh-a2a-table" }, (0, react.createElement)("thead", null, (0, react.createElement)("tr", null, (0, react.createElement)("th", null, "来源"), (0, react.createElement)("th", null, "任务"), (0, react.createElement)("th", null, "流式"), (0, react.createElement)("th", null, "首次 / 最近"), (0, react.createElement)("th", null, "操作"))), (0, react.createElement)("tbody", null, ...peers.map((p) => (0, react.createElement)("tr", { key: p.id }, (0, react.createElement)("td", null, p.source ?? p.label), (0, react.createElement)("td", null, `${p.taskCount}(活跃 ${p.activeTaskIds.length})`), (0, react.createElement)("td", null, p.streaming ? "" : "—"), (0, react.createElement)("td", null, (0, react.createElement)("span", { className: "muted" }, `${p.firstSeen ?? ""} / ${p.lastSeen ?? ""}`)), (0, react.createElement)("td", null, (0, react.createElement)("button", {
307
+ disabled: busy,
308
+ onClick: () => void control({
309
+ action: "inbound.close",
310
+ id: p.id
311
+ })
312
+ }, "关闭"))))))), (0, react.createElement)("div", { className: "dsh-a2a-card" }, (0, react.createElement)("h3", null, `任务(${tasks.length})`), tasks.length === 0 ? (0, react.createElement)("div", { className: "muted" }, "暂无任务。") : (0, react.createElement)("table", { className: "dsh-a2a-table" }, (0, react.createElement)("thead", null, (0, react.createElement)("tr", null, (0, react.createElement)("th", null, "ID"), (0, react.createElement)("th", null, "技能"), (0, react.createElement)("th", null, "状态"), (0, react.createElement)("th", null, "操作"))), (0, react.createElement)("tbody", null, ...tasks.slice(-20).reverse().map((t) => (0, react.createElement)("tr", { key: t.id }, (0, react.createElement)("td", null, (0, react.createElement)("span", { className: "muted" }, t.id)), (0, react.createElement)("td", null, t.metadata?.skill ?? "-"), (0, react.createElement)("td", null, t.status?.state ?? "-"), (0, react.createElement)("td", null, (0, react.createElement)("button", {
200
313
  disabled: busy,
201
314
  onClick: () => void control({
202
315
  action: "task.cancel",