@hanphone/dsh-a2a 0.2.0 → 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/README.md +101 -106
- package/README.zh.md +50 -74
- package/cordis.patch.yml +4 -7
- package/lib/client.js +217 -73
- package/lib/index.js +1258 -867
- package/lib/types/api.d.ts +40 -23
- package/lib/types/api.d.ts.map +1 -1
- package/lib/types/api.js +58 -23
- package/lib/types/api.js.map +1 -1
- package/lib/types/client/index.d.ts +50 -19
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/commands.d.ts +4 -2
- package/lib/types/commands.d.ts.map +1 -1
- package/lib/types/commands.js +59 -46
- package/lib/types/commands.js.map +1 -1
- package/lib/types/events.d.ts +32 -9
- package/lib/types/events.d.ts.map +1 -1
- package/lib/types/index.d.ts +21 -32
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +173 -272
- package/lib/types/index.js.map +1 -1
- package/lib/types/outbound/calls.d.ts.map +1 -1
- package/lib/types/outbound/calls.js +8 -6
- package/lib/types/outbound/calls.js.map +1 -1
- package/lib/types/protocol.d.ts +174 -109
- package/lib/types/protocol.d.ts.map +1 -1
- package/lib/types/protocol.js +58 -34
- package/lib/types/protocol.js.map +1 -1
- package/lib/types/server/a2a-server.d.ts +4 -0
- package/lib/types/server/a2a-server.d.ts.map +1 -1
- package/lib/types/server/a2a-server.js +6 -2
- package/lib/types/server/a2a-server.js.map +1 -1
- package/lib/types/server/card.d.ts +6 -30
- package/lib/types/server/card.d.ts.map +1 -1
- package/lib/types/server/card.js +13 -49
- package/lib/types/server/card.js.map +1 -1
- package/lib/types/server/exec/agent-runtime.d.ts +3 -0
- package/lib/types/server/exec/agent-runtime.d.ts.map +1 -1
- package/lib/types/server/exec/agent-runtime.js +2 -1
- package/lib/types/server/exec/agent-runtime.js.map +1 -1
- package/lib/types/server/routes.d.ts +5 -1
- package/lib/types/server/routes.d.ts.map +1 -1
- package/lib/types/server/routes.js +9 -5
- package/lib/types/server/routes.js.map +1 -1
- package/lib/types/server/store.d.ts +35 -1
- package/lib/types/server/store.d.ts.map +1 -1
- package/lib/types/server/store.js +10 -0
- package/lib/types/server/store.js.map +1 -1
- package/lib/types/servers/inbound-manager.d.ts +131 -0
- package/lib/types/servers/inbound-manager.d.ts.map +1 -0
- package/lib/types/servers/inbound-manager.js +312 -0
- package/lib/types/servers/inbound-manager.js.map +1 -0
- package/lib/types/servers/outbound-manager.d.ts +129 -0
- package/lib/types/servers/outbound-manager.d.ts.map +1 -0
- package/lib/types/servers/outbound-manager.js +238 -0
- package/lib/types/servers/outbound-manager.js.map +1 -0
- package/lib/types/service.d.ts +106 -40
- package/lib/types/service.d.ts.map +1 -1
- package/lib/types/service.js +36 -27
- package/lib/types/service.js.map +1 -1
- package/package.json +2 -2
- package/src/api.ts +67 -53
- package/src/client/index.ts +309 -148
- package/src/commands.ts +59 -43
- package/src/events.ts +14 -7
- package/src/index.ts +199 -310
- package/src/outbound/calls.ts +8 -6
- package/src/protocol.ts +204 -95
- package/src/server/a2a-server.ts +9 -2
- package/src/server/card.ts +13 -62
- package/src/server/exec/agent-runtime.ts +5 -2
- package/src/server/routes.ts +6 -4
- package/src/server/store.ts +45 -4
- package/src/servers/inbound-manager.ts +385 -0
- package/src/servers/outbound-manager.ts +289 -0
- package/src/service.ts +125 -40
- package/lib/tsconfig.client.tsbuildinfo +0 -1
- 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",
|
|
@@ -59,29 +67,53 @@ window.__ModuleLoader__.load({
|
|
|
59
67
|
message: `HTTP ${res.status}`
|
|
60
68
|
}));
|
|
61
69
|
}
|
|
70
|
+
/** One skill declaration per line: `id|name|description` (name/description default to id). */
|
|
71
|
+
function parseSkills(text) {
|
|
72
|
+
const lines = text.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
73
|
+
if (lines.length === 0) return void 0;
|
|
74
|
+
return lines.map((line) => {
|
|
75
|
+
const [id, name, ...descParts] = line.split("|").map((p) => p.trim());
|
|
76
|
+
const skillId = id ?? "";
|
|
77
|
+
return {
|
|
78
|
+
id: skillId,
|
|
79
|
+
name: name && name.length > 0 ? name : skillId,
|
|
80
|
+
...descParts.length > 0 || (descParts[0]?.length ?? 0) > 0 ? { description: descParts.join("|") } : {}
|
|
81
|
+
};
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
function skillsToText(skills) {
|
|
85
|
+
return skills.map((s) => [
|
|
86
|
+
s.id,
|
|
87
|
+
s.name,
|
|
88
|
+
s.description
|
|
89
|
+
].filter((p) => p !== void 0 && p.length > 0).join("|")).join("\n");
|
|
90
|
+
}
|
|
62
91
|
function A2aSection(_props) {
|
|
63
92
|
const [snap, setSnap] = (0, react.useState)(void 0);
|
|
93
|
+
const [presets, setPresets] = (0, react.useState)([]);
|
|
64
94
|
const [error, setError] = (0, react.useState)(void 0);
|
|
65
|
-
const [agentName, setAgentName] = (0, react.useState)("");
|
|
66
|
-
const [agentUrl, setAgentUrl] = (0, react.useState)("");
|
|
67
95
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
68
|
-
const [
|
|
69
|
-
const [
|
|
70
|
-
const [
|
|
71
|
-
const [
|
|
96
|
+
const [editingIn, setEditingIn] = (0, react.useState)(void 0);
|
|
97
|
+
const [inName, setInName] = (0, react.useState)("");
|
|
98
|
+
const [inDesc, setInDesc] = (0, react.useState)("");
|
|
99
|
+
const [inVersion, setInVersion] = (0, react.useState)("1.0.0");
|
|
100
|
+
const [inPreset, setInPreset] = (0, react.useState)("");
|
|
101
|
+
const [inAuthEnv, setInAuthEnv] = (0, react.useState)("");
|
|
102
|
+
const [inSkills, setInSkills] = (0, react.useState)("");
|
|
103
|
+
const [outName, setOutName] = (0, react.useState)("");
|
|
104
|
+
const [outUrl, setOutUrl] = (0, react.useState)("");
|
|
105
|
+
const [outPreset, setOutPreset] = (0, react.useState)("");
|
|
106
|
+
const [outTokenEnv, setOutTokenEnv] = (0, react.useState)("");
|
|
107
|
+
const [outTimeout, setOutTimeout] = (0, react.useState)("60000");
|
|
72
108
|
(0, react.useEffect)(() => {
|
|
73
109
|
let alive = true;
|
|
74
110
|
const tick = async () => {
|
|
75
111
|
try {
|
|
76
|
-
const next = await fetchSnapshot();
|
|
112
|
+
const [next, presetRows] = await Promise.all([fetchSnapshot(), fetchPresets()]);
|
|
77
113
|
if (alive) {
|
|
78
114
|
setSnap(next);
|
|
115
|
+
setPresets(presetRows);
|
|
79
116
|
setError(void 0);
|
|
80
|
-
if (!editing) {
|
|
81
|
-
setIdName(next.server.name ?? "");
|
|
82
|
-
setIdDescription(next.server.description ?? "");
|
|
83
|
-
setIdVersion(next.server.version ?? "");
|
|
84
|
-
}
|
|
85
117
|
}
|
|
86
118
|
} catch (err) {
|
|
87
119
|
if (alive) setError(err.message);
|
|
@@ -106,97 +138,209 @@ window.__ModuleLoader__.load({
|
|
|
106
138
|
setBusy(false);
|
|
107
139
|
}
|
|
108
140
|
};
|
|
109
|
-
const
|
|
110
|
-
|
|
141
|
+
const startCreateInbound = () => {
|
|
142
|
+
setEditingIn(void 0);
|
|
143
|
+
setInName("");
|
|
144
|
+
setInDesc("");
|
|
145
|
+
setInVersion("1.0.0");
|
|
146
|
+
setInPreset("");
|
|
147
|
+
setInAuthEnv("");
|
|
148
|
+
setInSkills("");
|
|
149
|
+
};
|
|
150
|
+
const submitInbound = () => {
|
|
151
|
+
if (!inName.trim()) return;
|
|
152
|
+
const skills = parseSkills(inSkills);
|
|
153
|
+
if (editingIn !== void 0) {
|
|
154
|
+
control({
|
|
155
|
+
action: "inbound.update",
|
|
156
|
+
id: editingIn,
|
|
157
|
+
name: inName.trim(),
|
|
158
|
+
description: inDesc.trim(),
|
|
159
|
+
version: inVersion.trim() || "1.0.0",
|
|
160
|
+
...inPreset !== "" ? { preset: inPreset } : {},
|
|
161
|
+
...inAuthEnv.trim() !== "" ? { authTokenEnv: inAuthEnv.trim() } : {},
|
|
162
|
+
...skills !== void 0 ? { skills } : {}
|
|
163
|
+
}).then(() => setEditingIn(void 0));
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
control({
|
|
167
|
+
action: "inbound.create",
|
|
168
|
+
name: inName.trim(),
|
|
169
|
+
description: inDesc.trim() || "An A2A inbound server",
|
|
170
|
+
version: inVersion.trim() || "1.0.0",
|
|
171
|
+
...inPreset !== "" ? { preset: inPreset } : {},
|
|
172
|
+
...inAuthEnv.trim() !== "" ? { authTokenEnv: inAuthEnv.trim() } : {},
|
|
173
|
+
...skills !== void 0 ? { skills } : {}
|
|
174
|
+
}).then(() => startCreateInbound());
|
|
175
|
+
};
|
|
176
|
+
const beginEditInbound = (v) => {
|
|
177
|
+
setEditingIn(v.id);
|
|
178
|
+
setInName(v.name);
|
|
179
|
+
setInDesc(v.description);
|
|
180
|
+
setInVersion(v.version);
|
|
181
|
+
setInPreset(v.preset ?? "");
|
|
182
|
+
setInAuthEnv(v.authTokenEnv ?? "");
|
|
183
|
+
setInSkills(skillsToText(v.skills));
|
|
184
|
+
};
|
|
185
|
+
const submitOutbound = () => {
|
|
186
|
+
if (!outName.trim() || !outUrl.trim()) return;
|
|
187
|
+
const timeout = Number.parseInt(outTimeout, 10);
|
|
188
|
+
control({
|
|
189
|
+
action: "outbound.create",
|
|
190
|
+
name: outName.trim(),
|
|
191
|
+
agentCardUrl: outUrl.trim(),
|
|
192
|
+
...outPreset !== "" ? { preset: outPreset } : {},
|
|
193
|
+
...outTokenEnv.trim() !== "" ? { bearerTokenEnv: outTokenEnv.trim() } : {},
|
|
194
|
+
...Number.isFinite(timeout) && timeout > 0 ? { timeoutMs: timeout } : {}
|
|
195
|
+
}).then(() => {
|
|
196
|
+
setOutName("");
|
|
197
|
+
setOutUrl("");
|
|
198
|
+
setOutPreset("");
|
|
199
|
+
setOutTokenEnv("");
|
|
200
|
+
});
|
|
201
|
+
};
|
|
111
202
|
const inbounds = snap?.inbounds ?? [];
|
|
203
|
+
const outbounds = snap?.outbounds ?? [];
|
|
204
|
+
const peers = snap?.peers ?? [];
|
|
112
205
|
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,
|
|
114
|
-
className:
|
|
206
|
+
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", {
|
|
207
|
+
className: "dsh-a2a-skill",
|
|
208
|
+
key: s.id,
|
|
209
|
+
title: s.description ?? ""
|
|
210
|
+
}, 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", {
|
|
115
211
|
disabled: busy,
|
|
116
|
-
onClick: () => void control({
|
|
117
|
-
|
|
212
|
+
onClick: () => void control({
|
|
213
|
+
action: v.enabled ? "inbound.disable" : "inbound.enable",
|
|
214
|
+
id: v.id
|
|
215
|
+
})
|
|
216
|
+
}, v.enabled ? "停用" : "启用"), " ", (0, react.createElement)("button", {
|
|
217
|
+
disabled: busy,
|
|
218
|
+
onClick: () => beginEditInbound(v)
|
|
219
|
+
}, "编辑"), " ", (0, react.createElement)("button", {
|
|
220
|
+
disabled: busy,
|
|
221
|
+
onClick: () => void control({
|
|
222
|
+
action: "inbound.remove",
|
|
223
|
+
id: v.id
|
|
224
|
+
})
|
|
225
|
+
}, "删除")))))), (0, react.createElement)("h3", { style: { marginTop: "12px" } }, editingIn !== void 0 ? "编辑入站 Server" : "新建入站 Server"), (0, react.createElement)("form", {
|
|
118
226
|
className: "dsh-a2a-form",
|
|
119
227
|
onSubmit: (ev) => {
|
|
120
228
|
ev.preventDefault();
|
|
121
|
-
|
|
122
|
-
action: "identity.update",
|
|
123
|
-
name: idName,
|
|
124
|
-
description: idDescription,
|
|
125
|
-
version: idVersion
|
|
126
|
-
}).then(() => {
|
|
127
|
-
setEditing(false);
|
|
128
|
-
});
|
|
229
|
+
submitInbound();
|
|
129
230
|
}
|
|
130
231
|
}, (0, react.createElement)("input", {
|
|
131
|
-
value:
|
|
132
|
-
placeholder: "
|
|
133
|
-
onChange: (e) =>
|
|
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" }
|
|
232
|
+
value: inName,
|
|
233
|
+
placeholder: "名称",
|
|
234
|
+
onChange: (e) => setInName(e.target.value)
|
|
140
235
|
}), (0, react.createElement)("input", {
|
|
141
|
-
value:
|
|
142
|
-
placeholder: "
|
|
143
|
-
onChange: (e) =>
|
|
144
|
-
style: { width: "
|
|
236
|
+
value: inVersion,
|
|
237
|
+
placeholder: "版本",
|
|
238
|
+
onChange: (e) => setInVersion(e.target.value),
|
|
239
|
+
style: { width: "70px" }
|
|
240
|
+
}), (0, react.createElement)("select", {
|
|
241
|
+
value: inPreset,
|
|
242
|
+
onChange: (e) => setInPreset(e.target.value)
|
|
243
|
+
}, (0, react.createElement)("option", { value: "" }, "Preset(默认)"), ...presets.map((p) => (0, react.createElement)("option", {
|
|
244
|
+
value: p.id,
|
|
245
|
+
key: p.id
|
|
246
|
+
}, `${p.name ?? p.id}${p.isDefault ? "(默认)" : ""}`))), (0, react.createElement)("input", {
|
|
247
|
+
value: inAuthEnv,
|
|
248
|
+
placeholder: "鉴权 env 变量名(可选)",
|
|
249
|
+
onChange: (e) => setInAuthEnv(e.target.value)
|
|
250
|
+
})), (0, react.createElement)("form", {
|
|
251
|
+
className: "dsh-a2a-form",
|
|
252
|
+
onSubmit: (ev) => {
|
|
253
|
+
ev.preventDefault();
|
|
254
|
+
submitInbound();
|
|
255
|
+
}
|
|
256
|
+
}, (0, react.createElement)("textarea", {
|
|
257
|
+
value: inSkills,
|
|
258
|
+
placeholder: "技能宣告(每行 id|名称|描述,留空默认取 preset 名)",
|
|
259
|
+
onChange: (e) => setInSkills(e.target.value)
|
|
260
|
+
})), (0, react.createElement)("form", {
|
|
261
|
+
className: "dsh-a2a-form",
|
|
262
|
+
onSubmit: (ev) => {
|
|
263
|
+
ev.preventDefault();
|
|
264
|
+
submitInbound();
|
|
265
|
+
}
|
|
266
|
+
}, (0, react.createElement)("input", {
|
|
267
|
+
value: inDesc,
|
|
268
|
+
placeholder: "描述",
|
|
269
|
+
onChange: (e) => setInDesc(e.target.value),
|
|
270
|
+
style: {
|
|
271
|
+
flex: 1,
|
|
272
|
+
minWidth: "260px"
|
|
273
|
+
}
|
|
145
274
|
}), (0, react.createElement)("button", {
|
|
146
275
|
type: "submit",
|
|
147
276
|
className: "primary",
|
|
148
|
-
disabled: busy
|
|
149
|
-
},
|
|
277
|
+
disabled: busy || !inName.trim()
|
|
278
|
+
}, editingIn !== void 0 ? "保存修改" : "创建 Server"), editingIn !== void 0 ? (0, react.createElement)("button", {
|
|
279
|
+
type: "button",
|
|
150
280
|
disabled: busy,
|
|
151
|
-
onClick: () =>
|
|
152
|
-
|
|
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", {
|
|
281
|
+
onClick: () => startCreateInbound()
|
|
282
|
+
}, "取消") : null), (0, react.createElement)("div", { className: "dsh-a2a-hint" }, "技能宣告由创建者输入,默认取所绑定的 preset 展示名(无 preset 时为内置 chat)。")), (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
283
|
disabled: busy,
|
|
157
284
|
onClick: () => void control({
|
|
158
|
-
action:
|
|
159
|
-
id:
|
|
285
|
+
action: v.enabled ? "outbound.disable" : "outbound.enable",
|
|
286
|
+
id: v.id
|
|
160
287
|
})
|
|
161
|
-
},
|
|
288
|
+
}, v.enabled ? "停用" : "启用"), " ", (0, react.createElement)("button", {
|
|
162
289
|
disabled: busy,
|
|
163
290
|
onClick: () => void control({
|
|
164
|
-
action: "
|
|
165
|
-
id:
|
|
291
|
+
action: "outbound.refresh",
|
|
292
|
+
id: v.id
|
|
166
293
|
})
|
|
167
294
|
}, "刷新"), " ", (0, react.createElement)("button", {
|
|
168
295
|
disabled: busy,
|
|
169
296
|
onClick: () => void control({
|
|
170
|
-
action: "
|
|
171
|
-
id:
|
|
297
|
+
action: "outbound.remove",
|
|
298
|
+
id: v.id
|
|
172
299
|
})
|
|
173
|
-
}, "删除")))))), (0, react.createElement)("form", {
|
|
300
|
+
}, "删除")))))), (0, react.createElement)("h3", { style: { marginTop: "12px" } }, "新建出站 Server"), (0, react.createElement)("form", {
|
|
174
301
|
className: "dsh-a2a-form",
|
|
175
302
|
onSubmit: (ev) => {
|
|
176
303
|
ev.preventDefault();
|
|
177
|
-
|
|
178
|
-
control({
|
|
179
|
-
action: "agent.add",
|
|
180
|
-
name: agentName.trim(),
|
|
181
|
-
agentCardUrl: agentUrl.trim()
|
|
182
|
-
}).then(() => {
|
|
183
|
-
setAgentName("");
|
|
184
|
-
setAgentUrl("");
|
|
185
|
-
});
|
|
304
|
+
submitOutbound();
|
|
186
305
|
}
|
|
187
306
|
}, (0, react.createElement)("input", {
|
|
188
|
-
value:
|
|
307
|
+
value: outName,
|
|
189
308
|
placeholder: "名称",
|
|
190
|
-
onChange: (e) =>
|
|
309
|
+
onChange: (e) => setOutName(e.target.value)
|
|
310
|
+
}), (0, react.createElement)("input", {
|
|
311
|
+
value: outUrl,
|
|
312
|
+
placeholder: "远端 AgentCard URL",
|
|
313
|
+
onChange: (e) => setOutUrl(e.target.value),
|
|
314
|
+
style: {
|
|
315
|
+
flex: 1,
|
|
316
|
+
minWidth: "240px"
|
|
317
|
+
}
|
|
318
|
+
}), (0, react.createElement)("select", {
|
|
319
|
+
value: outPreset,
|
|
320
|
+
onChange: (e) => setOutPreset(e.target.value)
|
|
321
|
+
}, (0, react.createElement)("option", { value: "" }, "Preset(默认)"), ...presets.map((p) => (0, react.createElement)("option", {
|
|
322
|
+
value: p.id,
|
|
323
|
+
key: p.id
|
|
324
|
+
}, `${p.name ?? p.id}${p.isDefault ? "(默认)" : ""}`))), (0, react.createElement)("input", {
|
|
325
|
+
value: outTokenEnv,
|
|
326
|
+
placeholder: "Bearer env 变量名(可选)",
|
|
327
|
+
onChange: (e) => setOutTokenEnv(e.target.value)
|
|
191
328
|
}), (0, react.createElement)("input", {
|
|
192
|
-
value:
|
|
193
|
-
placeholder: "
|
|
194
|
-
onChange: (e) =>
|
|
329
|
+
value: outTimeout,
|
|
330
|
+
placeholder: "超时 ms",
|
|
331
|
+
onChange: (e) => setOutTimeout(e.target.value),
|
|
332
|
+
style: { width: "90px" }
|
|
195
333
|
}), (0, react.createElement)("button", {
|
|
196
334
|
type: "submit",
|
|
197
335
|
className: "primary",
|
|
198
|
-
disabled: busy
|
|
199
|
-
}, "
|
|
336
|
+
disabled: busy || !outName.trim() || !outUrl.trim()
|
|
337
|
+
}, "添加出站 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", {
|
|
338
|
+
disabled: busy,
|
|
339
|
+
onClick: () => void control({
|
|
340
|
+
action: "inbound.close",
|
|
341
|
+
id: p.id
|
|
342
|
+
})
|
|
343
|
+
}, "关闭"))))))), (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
344
|
disabled: busy,
|
|
201
345
|
onClick: () => void control({
|
|
202
346
|
action: "task.cancel",
|