@harrylabsj/kiwi 0.7.4 → 0.7.6
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/dist/a2a/client/client.d.ts +7 -2
- package/dist/a2a/client/client.js +34 -5
- package/dist/a2a/client/client.js.map +1 -1
- package/dist/a2a/client/index.d.ts +1 -1
- package/dist/a2a/client/index.js.map +1 -1
- package/dist/a2a/client/jsonrpc.js +2 -1
- package/dist/a2a/client/jsonrpc.js.map +1 -1
- package/dist/a2a/client/parse.js +6 -2
- package/dist/a2a/client/parse.js.map +1 -1
- package/dist/a2a/client/types.d.ts +11 -0
- package/dist/a2a/client/url-policy.js +29 -0
- package/dist/a2a/client/url-policy.js.map +1 -1
- package/dist/a2a/node.d.ts +10 -0
- package/dist/a2a/node.js +91 -14
- package/dist/a2a/node.js.map +1 -1
- package/dist/a2a/server/card.d.ts +6 -0
- package/dist/a2a/server/card.js +55 -1
- package/dist/a2a/server/card.js.map +1 -1
- package/dist/a2a/server/errors.d.ts +12 -2
- package/dist/a2a/server/errors.js +13 -2
- package/dist/a2a/server/errors.js.map +1 -1
- package/dist/a2a/server/generic-responder.d.ts +48 -0
- package/dist/a2a/server/generic-responder.js +57 -0
- package/dist/a2a/server/generic-responder.js.map +1 -0
- package/dist/a2a/server/index.d.ts +2 -0
- package/dist/a2a/server/index.js +2 -0
- package/dist/a2a/server/index.js.map +1 -1
- package/dist/a2a/server/merchant-handler.d.ts +12 -1
- package/dist/a2a/server/merchant-handler.js +96 -22
- package/dist/a2a/server/merchant-handler.js.map +1 -1
- package/dist/a2a/server/pipeline.d.ts +28 -0
- package/dist/a2a/server/pipeline.js +66 -3
- package/dist/a2a/server/pipeline.js.map +1 -1
- package/dist/a2a/server/server.d.ts +12 -0
- package/dist/a2a/server/server.js +255 -11
- package/dist/a2a/server/server.js.map +1 -1
- package/dist/a2a/server/task-registry.d.ts +8 -0
- package/dist/a2a/server/task-registry.js +17 -0
- package/dist/a2a/server/task-registry.js.map +1 -1
- package/dist/a2a/server/throttle.d.ts +13 -0
- package/dist/a2a/server/throttle.js +41 -1
- package/dist/a2a/server/throttle.js.map +1 -1
- package/dist/a2a/server/types.d.ts +14 -1
- package/dist/a2a/signing-key.d.ts +55 -0
- package/dist/a2a/signing-key.js +142 -0
- package/dist/a2a/signing-key.js.map +1 -0
- package/dist/a2a/v1/headers.d.ts +33 -0
- package/dist/a2a/v1/headers.js +56 -0
- package/dist/a2a/v1/headers.js.map +1 -0
- package/dist/a2a/v1/methods.d.ts +52 -0
- package/dist/a2a/v1/methods.js +75 -0
- package/dist/a2a/v1/methods.js.map +1 -0
- package/dist/a2a/v1/part.d.ts +48 -0
- package/dist/a2a/v1/part.js +63 -0
- package/dist/a2a/v1/part.js.map +1 -0
- package/dist/a2a/v1/types.d.ts +94 -0
- package/dist/a2a/v1/types.js +62 -0
- package/dist/a2a/v1/types.js.map +1 -0
- package/dist/agent/buyer/buyer-tools.js +92 -19
- package/dist/agent/buyer/buyer-tools.js.map +1 -1
- package/dist/agent/buyer/search-loop.js +17 -2
- package/dist/agent/buyer/search-loop.js.map +1 -1
- package/dist/agent/buyer/types.js +4 -1
- package/dist/agent/buyer/types.js.map +1 -1
- package/dist/agent/kernel.js +70 -25
- package/dist/agent/kernel.js.map +1 -1
- package/dist/agent/merchant/action-candidate.d.ts +10 -0
- package/dist/agent/merchant/action-candidate.js +36 -4
- package/dist/agent/merchant/action-candidate.js.map +1 -1
- package/dist/agent/merchant/merchant-client.d.ts +4 -1
- package/dist/agent/merchant/merchant-client.js +41 -29
- package/dist/agent/merchant/merchant-client.js.map +1 -1
- package/dist/agent/negotiation-chat.d.ts +11 -0
- package/dist/agent/negotiation-chat.js +15 -0
- package/dist/agent/negotiation-chat.js.map +1 -1
- package/dist/agent/system-prompt.js +1 -1
- package/dist/agent/system-prompt.js.map +1 -1
- package/dist/agent/write-gate.d.ts +4 -0
- package/dist/agent/write-gate.js +9 -3
- package/dist/agent/write-gate.js.map +1 -1
- package/dist/cli.d.ts +7 -0
- package/dist/cli.js +51 -7
- package/dist/cli.js.map +1 -1
- package/dist/commerce/data-source.d.ts +11 -1
- package/dist/commerce/data-source.js.map +1 -1
- package/dist/commerce/shopping-cli-source.js +10 -0
- package/dist/commerce/shopping-cli-source.js.map +1 -1
- package/dist/config/profile.d.ts +2 -0
- package/dist/config/profile.js +21 -7
- package/dist/config/profile.js.map +1 -1
- package/dist/counterparty/a2a-direct/index.d.ts +4 -0
- package/dist/counterparty/a2a-direct/index.js +5 -0
- package/dist/counterparty/a2a-direct/index.js.map +1 -1
- package/dist/demo/demo-runner.d.ts +81 -0
- package/dist/demo/demo-runner.js +344 -0
- package/dist/demo/demo-runner.js.map +1 -0
- package/dist/discovery/agent-card/types.d.ts +3 -0
- package/dist/discovery/agent-card/validate.js +7 -0
- package/dist/discovery/agent-card/validate.js.map +1 -1
- package/dist/discovery/catalog-source/register.d.ts +5 -1
- package/dist/discovery/catalog-source/register.js +14 -3
- package/dist/discovery/catalog-source/register.js.map +1 -1
- package/dist/discovery/resolve.js +3 -0
- package/dist/discovery/resolve.js.map +1 -1
- package/dist/discovery/ucp/resolver.d.ts +2 -0
- package/dist/discovery/ucp/resolver.js +3 -1
- package/dist/discovery/ucp/resolver.js.map +1 -1
- package/dist/handoff/ledger.js +23 -5
- package/dist/handoff/ledger.js.map +1 -1
- package/dist/handoff/order-record.js +26 -4
- package/dist/handoff/order-record.js.map +1 -1
- package/dist/handoff/transaction.js +13 -3
- package/dist/handoff/transaction.js.map +1 -1
- package/dist/negotiation/lease/store.js +14 -4
- package/dist/negotiation/lease/store.js.map +1 -1
- package/dist/negotiation/state/phase.js +12 -0
- package/dist/negotiation/state/phase.js.map +1 -1
- package/dist/net/safe-http.js +9 -1
- package/dist/net/safe-http.js.map +1 -1
- package/dist/operator/controller.d.ts +3 -0
- package/dist/operator/controller.js +18 -5
- package/dist/operator/controller.js.map +1 -1
- package/dist/product-buyer.d.ts +5 -0
- package/dist/product-buyer.js +1 -1
- package/dist/product-buyer.js.map +1 -1
- package/dist/product-cli.d.ts +10 -3
- package/dist/product-cli.js +13 -5
- package/dist/product-cli.js.map +1 -1
- package/dist/product-init.d.ts +6 -0
- package/dist/product-init.js +1 -1
- package/dist/product-init.js.map +1 -1
- package/dist/supervisor/manage.d.ts +5 -1
- package/dist/supervisor/manage.js +100 -9
- package/dist/supervisor/manage.js.map +1 -1
- package/dist/trust/identity/auth-verifier.d.ts +8 -0
- package/dist/trust/identity/auth-verifier.js +14 -0
- package/dist/trust/identity/auth-verifier.js.map +1 -1
- package/dist/weixin/credentials.js +15 -4
- package/dist/weixin/credentials.js.map +1 -1
- package/dist/weixin/ilink-client.d.ts +9 -0
- package/dist/weixin/ilink-client.js +46 -0
- package/dist/weixin/ilink-client.js.map +1 -1
- package/dist/weixin/login.js +5 -2
- package/dist/weixin/login.js.map +1 -1
- package/examples/profiles/merchant.deepseek.yaml +1 -0
- package/examples/profiles/merchant.fake.yaml +1 -0
- package/examples/profiles/merchant.local.yaml +1 -0
- package/package.json +8 -3
|
@@ -22,6 +22,14 @@ export declare class TaskRegistry {
|
|
|
22
22
|
private readonly tasks;
|
|
23
23
|
set(taskId: string, task: A2ATask): void;
|
|
24
24
|
get(taskId: string): A2ATask | null;
|
|
25
|
+
/** 全部在内存中的任务(issue 10 / TCK CORE-LIST:ListTasks)。 */
|
|
26
|
+
list(): A2ATask[];
|
|
27
|
+
/** 取消(issue 10 / TCK CORE-CANCEL):非终态 → canceled;未知 → not_found;
|
|
28
|
+
* 终态 → not_cancelable。 */
|
|
29
|
+
cancel(taskId: string): {
|
|
30
|
+
ok: boolean;
|
|
31
|
+
outcome: "canceled" | "not_found" | "not_cancelable";
|
|
32
|
+
};
|
|
25
33
|
/**
|
|
26
34
|
* 从 Ledger 还原任务视图:扫描事件,命中 remote_task_id === taskId 的首条
|
|
27
35
|
* 记录,返回最小 A2ATask(id + status.state)。结果不依赖内存状态。
|
|
@@ -42,6 +42,23 @@ export class TaskRegistry {
|
|
|
42
42
|
const task = this.tasks.get(taskId);
|
|
43
43
|
return task === undefined ? null : task;
|
|
44
44
|
}
|
|
45
|
+
/** 全部在内存中的任务(issue 10 / TCK CORE-LIST:ListTasks)。 */
|
|
46
|
+
list() {
|
|
47
|
+
return [...this.tasks.values()];
|
|
48
|
+
}
|
|
49
|
+
/** 取消(issue 10 / TCK CORE-CANCEL):非终态 → canceled;未知 → not_found;
|
|
50
|
+
* 终态 → not_cancelable。 */
|
|
51
|
+
cancel(taskId) {
|
|
52
|
+
const task = this.tasks.get(taskId);
|
|
53
|
+
if (task === undefined)
|
|
54
|
+
return { ok: false, outcome: "not_found" };
|
|
55
|
+
const state = task.status.state;
|
|
56
|
+
if (state === "completed" || state === "canceled" || state === "failed") {
|
|
57
|
+
return { ok: false, outcome: "not_cancelable" };
|
|
58
|
+
}
|
|
59
|
+
this.tasks.set(taskId, { ...task, status: { ...task.status, state: "canceled" } });
|
|
60
|
+
return { ok: true, outcome: "canceled" };
|
|
61
|
+
}
|
|
45
62
|
/**
|
|
46
63
|
* 从 Ledger 还原任务视图:扫描事件,命中 remote_task_id === taskId 的首条
|
|
47
64
|
* 记录,返回最小 A2ATask(id + status.state)。结果不依赖内存状态。
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-registry.js","sourceRoot":"","sources":["../../../src/a2a/server/task-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;;GAQG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,yCAAyC,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAIrD,MAAM,UAAU,SAAS;IACvB,OAAO,QAAQ,MAAM,EAAE,EAAE,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,OAAO,MAAM,EAAE,EAAE,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAK,eAAqC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC7F,CAAC;AAED,MAAM,OAAO,YAAY;IACN,KAAK,GAAG,IAAI,GAAG,EAAmB,CAAC;IAEpD,GAAG,CAAC,MAAc,EAAE,IAAa;QAC/B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,GAAG,CAAC,MAAc;QAChB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACpC,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1C,CAAC;IAED;;;;OAIG;IACH,iBAAiB,CAAC,MAAmB,EAAE,MAAc;QACnD,KAAK,MAAM,aAAa,IAAI,MAAM,CAAC,gBAAgB,EAAE,EAAE,CAAC;YACtD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;gBACjD,IAAI,KAAK,CAAC,cAAc,KAAK,MAAM;oBAAE,SAAS;gBAC9C,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;gBAC9E,MAAM,KAAK,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;gBACtE,IAAI,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC5B,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC;gBAC3C,CAAC;gBACD,6CAA6C;gBAC7C,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
|
|
1
|
+
{"version":3,"file":"task-registry.js","sourceRoot":"","sources":["../../../src/a2a/server/task-registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -57,6 +57,8 @@ export type ThrottleTierTable = Record<TrustLevel, TrustTierLimits>;
|
|
|
57
57
|
export declare const DEFAULT_THROTTLE_TIERS: ThrottleTierTable;
|
|
58
58
|
export declare const DEFAULT_WINDOW_MS = 60000;
|
|
59
59
|
export declare const DEFAULT_UNVERIFIED_SCALE = 0.5;
|
|
60
|
+
/** 审查 K-L3:限流 Map 全量清扫周期(毫秒,默认 60s)。 */
|
|
61
|
+
export declare const THROTTLE_SWEEP_INTERVAL_MS = 60000;
|
|
60
62
|
export interface ThrottleOptions {
|
|
61
63
|
/** 滑动窗口(毫秒,默认 60_000)。 */
|
|
62
64
|
windowMs?: number;
|
|
@@ -67,6 +69,8 @@ export interface ThrottleOptions {
|
|
|
67
69
|
* 默认 0.5 —— 匿名来源限额严格于验签身份(§31 identity cycling 缓解)。
|
|
68
70
|
*/
|
|
69
71
|
unverifiedIdentityScale?: number;
|
|
72
|
+
/** 限流 Map 清扫周期(毫秒,默认 60s;测试可注入短周期)。 */
|
|
73
|
+
sweepIntervalMs?: number;
|
|
70
74
|
/** 时钟(unix 毫秒);可注入便于确定性测试。默认 Date.now。 */
|
|
71
75
|
now?: () => number;
|
|
72
76
|
}
|
|
@@ -119,6 +123,8 @@ export declare class A2AServerThrottle {
|
|
|
119
123
|
private readonly malformedWindow;
|
|
120
124
|
/** per-identity 主键 → 当前在途任务数。 */
|
|
121
125
|
private readonly inflight;
|
|
126
|
+
private readonly sweepIntervalMs;
|
|
127
|
+
private lastSweepAt;
|
|
122
128
|
constructor(options?: ThrottleOptions);
|
|
123
129
|
/**
|
|
124
130
|
* per-identity 主键:验签身份用 identity;未验签用 remoteAddress(identity
|
|
@@ -136,6 +142,11 @@ export declare class A2AServerThrottle {
|
|
|
136
142
|
private windowEntries;
|
|
137
143
|
private exceedsLimit;
|
|
138
144
|
private record;
|
|
145
|
+
/** 审查 K-L3:全量清扫已过期窗口的键——windowEntries 只在再次访问该键时
|
|
146
|
+
* 修剪,一次性身份轮换的键永不再次访问、永久残留(长驻服务内存无界增长)。
|
|
147
|
+
* 每 sweepIntervalMs 调一次,Map 有界于「最近活跃身份」。 */
|
|
148
|
+
private sweep;
|
|
149
|
+
private sweepIfDue;
|
|
139
150
|
/**
|
|
140
151
|
* 限流判定(consume:允许的请求计入各自窗口)。判定顺序:malformed budget 阻断 →
|
|
141
152
|
* per-identity → per-domain。拒绝携带档位 retry_after。
|
|
@@ -151,4 +162,6 @@ export declare class A2AServerThrottle {
|
|
|
151
162
|
/** 释放在途任务槽(请求处理结束时由 pipeline 调用,幂等)。 */
|
|
152
163
|
leaveTask(req: ThrottleRequest): void;
|
|
153
164
|
private isMalformedBlocked;
|
|
165
|
+
/** 诊断:当前 identity 窗口键数(审查 K-L3 内存有界性验证/监控用)。 */
|
|
166
|
+
get debugIdentityWindowSize(): number;
|
|
154
167
|
}
|
|
@@ -71,6 +71,8 @@ export const DEFAULT_THROTTLE_TIERS = {
|
|
|
71
71
|
};
|
|
72
72
|
export const DEFAULT_WINDOW_MS = 60_000;
|
|
73
73
|
export const DEFAULT_UNVERIFIED_SCALE = 0.5;
|
|
74
|
+
/** 审查 K-L3:限流 Map 全量清扫周期(毫秒,默认 60s)。 */
|
|
75
|
+
export const THROTTLE_SWEEP_INTERVAL_MS = 60_000;
|
|
74
76
|
// ---------------------------------------------------------------------------
|
|
75
77
|
// 工具
|
|
76
78
|
// ---------------------------------------------------------------------------
|
|
@@ -126,11 +128,17 @@ export class A2AServerThrottle {
|
|
|
126
128
|
malformedWindow = new Map();
|
|
127
129
|
/** per-identity 主键 → 当前在途任务数。 */
|
|
128
130
|
inflight = new Map();
|
|
131
|
+
sweepIntervalMs;
|
|
132
|
+
lastSweepAt = 0;
|
|
129
133
|
constructor(options = {}) {
|
|
130
134
|
this.windowMs = options.windowMs ?? DEFAULT_WINDOW_MS;
|
|
131
135
|
if (!Number.isFinite(this.windowMs) || this.windowMs <= 0) {
|
|
132
136
|
throw new TypeError("A2AServerThrottle: windowMs must be a positive number");
|
|
133
137
|
}
|
|
138
|
+
this.sweepIntervalMs = options.sweepIntervalMs ?? THROTTLE_SWEEP_INTERVAL_MS;
|
|
139
|
+
if (!Number.isFinite(this.sweepIntervalMs) || this.sweepIntervalMs <= 0) {
|
|
140
|
+
throw new TypeError("A2AServerThrottle: sweepIntervalMs must be a positive number");
|
|
141
|
+
}
|
|
134
142
|
this.unverifiedScale = options.unverifiedIdentityScale ?? DEFAULT_UNVERIFIED_SCALE;
|
|
135
143
|
if (!Number.isFinite(this.unverifiedScale) ||
|
|
136
144
|
this.unverifiedScale <= 0 ||
|
|
@@ -201,14 +209,41 @@ export class A2AServerThrottle {
|
|
|
201
209
|
arr.push(now);
|
|
202
210
|
map.set(key, arr);
|
|
203
211
|
}
|
|
212
|
+
/** 审查 K-L3:全量清扫已过期窗口的键——windowEntries 只在再次访问该键时
|
|
213
|
+
* 修剪,一次性身份轮换的键永不再次访问、永久残留(长驻服务内存无界增长)。
|
|
214
|
+
* 每 sweepIntervalMs 调一次,Map 有界于「最近活跃身份」。 */
|
|
215
|
+
sweep(now) {
|
|
216
|
+
const cutoff = now - this.windowMs;
|
|
217
|
+
for (const map of [this.identityWindow, this.domainWindow, this.malformedWindow]) {
|
|
218
|
+
for (const [key, arr] of map) {
|
|
219
|
+
let start = 0;
|
|
220
|
+
while (start < arr.length && arr[start] <= cutoff)
|
|
221
|
+
start += 1;
|
|
222
|
+
if (start === 0)
|
|
223
|
+
continue;
|
|
224
|
+
const kept = arr.slice(start);
|
|
225
|
+
if (kept.length === 0)
|
|
226
|
+
map.delete(key);
|
|
227
|
+
else
|
|
228
|
+
map.set(key, kept);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
sweepIfDue(now) {
|
|
233
|
+
if (now - this.lastSweepAt >= this.sweepIntervalMs) {
|
|
234
|
+
this.lastSweepAt = now;
|
|
235
|
+
this.sweep(now);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
204
238
|
// -- 公开判定 --------------------------------------------------------------
|
|
205
239
|
/**
|
|
206
240
|
* 限流判定(consume:允许的请求计入各自窗口)。判定顺序:malformed budget 阻断 →
|
|
207
241
|
* per-identity → per-domain。拒绝携带档位 retry_after。
|
|
208
242
|
*/
|
|
209
243
|
check(req) {
|
|
210
|
-
const tier = this.resolveTier(req);
|
|
211
244
|
const now = this.now();
|
|
245
|
+
this.sweepIfDue(now); // 审查 K-L3:限流 Map 有界
|
|
246
|
+
const tier = this.resolveTier(req);
|
|
212
247
|
const idKey = this.identityKeyOf(req);
|
|
213
248
|
if (this.isMalformedBlocked(idKey, tier.malformedBudget, now)) {
|
|
214
249
|
return {
|
|
@@ -251,6 +286,7 @@ export class A2AServerThrottle {
|
|
|
251
286
|
*/
|
|
252
287
|
recordMalformed(req) {
|
|
253
288
|
const now = this.now();
|
|
289
|
+
this.sweepIfDue(now); // 审查 K-L3
|
|
254
290
|
this.record(this.malformedWindow, this.identityKeyOf(req), now);
|
|
255
291
|
if (req.domain !== undefined) {
|
|
256
292
|
this.record(this.malformedWindow, this.domainKeyOf(req.domain), now);
|
|
@@ -285,5 +321,9 @@ export class A2AServerThrottle {
|
|
|
285
321
|
isMalformedBlocked(key, budget, now) {
|
|
286
322
|
return this.windowEntries(this.malformedWindow, key, now).length >= budget;
|
|
287
323
|
}
|
|
324
|
+
/** 诊断:当前 identity 窗口键数(审查 K-L3 内存有界性验证/监控用)。 */
|
|
325
|
+
get debugIdentityWindowSize() {
|
|
326
|
+
return this.identityWindow.size;
|
|
327
|
+
}
|
|
288
328
|
}
|
|
289
329
|
//# sourceMappingURL=throttle.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"throttle.js","sourceRoot":"","sources":["../../../src/a2a/server/throttle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,YAAY,GAEb,MAAM,sCAAsC,CAAC;AAuB9C,kCAAkC;AAClC,MAAM,CAAC,MAAM,sBAAsB,GAAsB;IACvD,EAAE,EAAE;QACF,yBAAyB,EAAE,EAAE;QAC7B,uBAAuB,EAAE,EAAE;QAC3B,kBAAkB,EAAE,CAAC;QACrB,eAAe,EAAE,CAAC;QAClB,iBAAiB,EAAE,CAAC;KACrB;IACD,EAAE,EAAE;QACF,yBAAyB,EAAE,EAAE;QAC7B,uBAAuB,EAAE,EAAE;QAC3B,kBAAkB,EAAE,CAAC;QACrB,eAAe,EAAE,CAAC;QAClB,iBAAiB,EAAE,CAAC;KACrB;IACD,EAAE,EAAE;QACF,yBAAyB,EAAE,EAAE;QAC7B,uBAAuB,EAAE,GAAG;QAC5B,kBAAkB,EAAE,CAAC;QACrB,eAAe,EAAE,EAAE;QACnB,iBAAiB,EAAE,CAAC;KACrB;IACD,EAAE,EAAE;QACF,yBAAyB,EAAE,GAAG;QAC9B,uBAAuB,EAAE,GAAG;QAC5B,kBAAkB,EAAE,EAAE;QACtB,eAAe,EAAE,EAAE;QACnB,iBAAiB,EAAE,CAAC;KACrB;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC;AACxC,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"throttle.js","sourceRoot":"","sources":["../../../src/a2a/server/throttle.ts"],"names":[],"mappings":"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"}
|
|
@@ -34,6 +34,7 @@ import type { LedgerStore } from "../../negotiation/ledger/index.js";
|
|
|
34
34
|
import type { UcpPublishOptions } from "./ucp.js";
|
|
35
35
|
import type { A2AServerThrottle, ThrottleOptions } from "./throttle.js";
|
|
36
36
|
import type { TrustLevel } from "../../trust/identity/trust-policy.js";
|
|
37
|
+
import type { GenericMessageResponder } from "./generic-responder.js";
|
|
37
38
|
/** Agent Card 本地配置(基线 §26 / 子规范 §24.1 Discovery)。 */
|
|
38
39
|
export interface AgentCardConfig {
|
|
39
40
|
/** Agent 名称。 */
|
|
@@ -57,10 +58,17 @@ export interface AgentCardConfig {
|
|
|
57
58
|
negotiationExtensionUri?: string;
|
|
58
59
|
/** 附加技能声明(可选)。 */
|
|
59
60
|
skills?: AgentSkill[];
|
|
60
|
-
/**
|
|
61
|
+
/**
|
|
62
|
+
* 安全方案声明(仅元数据,不得含 secret;不变量 24)。
|
|
63
|
+
* Issue 16 B:HTTP Message Signature 模式可携带该节点的公开签名密钥
|
|
64
|
+
* (keyid / publicKeyPem / algorithm),供对端解析本节点出站签名。
|
|
65
|
+
*/
|
|
61
66
|
securityScheme?: {
|
|
62
67
|
name: string;
|
|
63
68
|
type: string;
|
|
69
|
+
keyid?: string;
|
|
70
|
+
publicKeyPem?: string;
|
|
71
|
+
algorithm?: string;
|
|
64
72
|
};
|
|
65
73
|
}
|
|
66
74
|
/** card 配置可静态提供,也可用 provider 函数(测试/部署时 baseUrl 动态确定)。 */
|
|
@@ -188,4 +196,9 @@ export interface A2AServerOptions {
|
|
|
188
196
|
* 传 ThrottleOptions 由 server 构造;也可直接注入 A2AServerThrottle 实例(测试用)。
|
|
189
197
|
*/
|
|
190
198
|
throttle?: ThrottleOptions | A2AServerThrottle;
|
|
199
|
+
/**
|
|
200
|
+
* 通用(非 KNP)A2A 消息响应器(issue 10 / TCK)。缺省用 spec 一致的回显;
|
|
201
|
+
* conformance SUT 注入 TCK 参考场景(messageId 前缀路由)。
|
|
202
|
+
*/
|
|
203
|
+
genericResponder?: GenericMessageResponder;
|
|
191
204
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2026 harrylabsj
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import { HttpMessageSigner } from "../trust/identity/index.js";
|
|
17
|
+
import type { KeyResolver, SigningKey } from "../trust/identity/index.js";
|
|
18
|
+
export declare const A2A_SIGNING_KEY_FILE = "a2a-signing-key.json";
|
|
19
|
+
export interface A2aSigningIdentity {
|
|
20
|
+
keyid: string;
|
|
21
|
+
algorithm: "ed25519";
|
|
22
|
+
/** PKCS8 私钥 PEM(0600 落盘,绝不进 card / transcript)。 */
|
|
23
|
+
privateKeyPem: string;
|
|
24
|
+
/** SPKI 公钥 PEM(可发布进 agent card securitySchemes)。 */
|
|
25
|
+
publicKeyPem: string;
|
|
26
|
+
/** Ed25519 raw 公钥(32B)。 */
|
|
27
|
+
publicKeyRaw: Buffer;
|
|
28
|
+
}
|
|
29
|
+
/** 生成新的 Ed25519 签名身份(keyid = 调用方指定的稳定身份键)。 */
|
|
30
|
+
export declare function generateA2aSigningIdentity(keyid: string): A2aSigningIdentity;
|
|
31
|
+
/** 加载或生成节点签名身份(幂等;已存在则读回,避免重启换钥)。 */
|
|
32
|
+
export declare function loadOrCreateA2aSigningIdentity(dataDir: string, keyid: string): A2aSigningIdentity;
|
|
33
|
+
/** 由节点身份构造出站签名器(HttpMessageSigner 即 A2AOutboundSigner 形状)。 */
|
|
34
|
+
export declare function createA2aOutboundSigner(identity: A2aSigningIdentity): HttpMessageSigner;
|
|
35
|
+
/** 从签名密钥 JSON 文件加载身份(与 loadOrCreateA2aSigningIdentity 同形状)。 */
|
|
36
|
+
export declare function loadA2aSigningIdentityFromFile(file: string): A2aSigningIdentity;
|
|
37
|
+
/** 出站签名器:显式 signer 优先,否则读 `KIWI_A2A_SIGNING_KEY_FILE` env。 */
|
|
38
|
+
export declare function resolveOutboundSigner(explicit?: A2AOutboundSignerLike): HttpMessageSigner | undefined;
|
|
39
|
+
/** A2AOutboundSigner 的结构形状(避免与 client 类型循环依赖)。 */
|
|
40
|
+
export interface A2AOutboundSignerLike {
|
|
41
|
+
readonly keyid: string;
|
|
42
|
+
sign(input: {
|
|
43
|
+
method: string;
|
|
44
|
+
url: string;
|
|
45
|
+
body: Buffer;
|
|
46
|
+
headers: Record<string, string>;
|
|
47
|
+
}): Record<string, string>;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* 构造入站签名验证用的 keyid→公钥 resolver。
|
|
51
|
+
* 未知 keyid → undefined(匿名请求按 T0 放行,签名请求身份不可解析则拒绝)。
|
|
52
|
+
*/
|
|
53
|
+
export declare function resolveA2aSignatureResolver(own: A2aSigningIdentity, extraKeys?: SigningKey[]): KeyResolver;
|
|
54
|
+
/** Agent Card 的 securitySchemes 条目(对端据此解析本节点公钥)。 */
|
|
55
|
+
export declare function a2aSignatureSecurityScheme(identity: A2aSigningIdentity): Record<string, unknown>;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2026 harrylabsj
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* A2A 节点签名身份(Issue 16 B / KIWI_A2A_AUTH=signature,RFC 9421)。
|
|
18
|
+
*
|
|
19
|
+
* 设计意图:**任何 kiwi buyer 都能和任何 kiwi merchant 沟通**(无预共享密钥)。
|
|
20
|
+
* 每个 agent 持有自己的 Ed25519 密钥对:
|
|
21
|
+
* - 出站:`HttpMessageSigner` 用私钥对每请求签名(content-digest / signature-input / signature);
|
|
22
|
+
* - 入站:`HttpMessageSignatureVerifier` 用 keyid→公钥(resolver)验签。
|
|
23
|
+
* 默认信任策略**匿名 T0 放行**——签名基建未就绪时匿名仍可磋商;签名请求获更高信任。
|
|
24
|
+
*
|
|
25
|
+
* 密钥持久化在节点数据目录 `<dataDir>/a2a-signing-key.json`(0600)。
|
|
26
|
+
*/
|
|
27
|
+
import { createPublicKey, generateKeyPairSync } from "node:crypto";
|
|
28
|
+
import { mkdirSync, readFileSync, writeFileSync, existsSync } from "node:fs";
|
|
29
|
+
import path from "node:path";
|
|
30
|
+
import { HttpMessageSigner } from "../trust/identity/index.js";
|
|
31
|
+
export const A2A_SIGNING_KEY_FILE = "a2a-signing-key.json";
|
|
32
|
+
/** 生成新的 Ed25519 签名身份(keyid = 调用方指定的稳定身份键)。 */
|
|
33
|
+
export function generateA2aSigningIdentity(keyid) {
|
|
34
|
+
const { publicKey, privateKey } = generateKeyPairSync("ed25519");
|
|
35
|
+
const publicKeyPem = publicKey.export({ type: "spki", format: "pem" }).toString();
|
|
36
|
+
const privateKeyPem = privateKey.export({ type: "pkcs8", format: "pem" }).toString();
|
|
37
|
+
const raw = createPublicKey(publicKeyPem).export({ type: "spki", format: "der" });
|
|
38
|
+
return {
|
|
39
|
+
keyid,
|
|
40
|
+
algorithm: "ed25519",
|
|
41
|
+
privateKeyPem,
|
|
42
|
+
publicKeyPem,
|
|
43
|
+
// Ed25519 SPKI DER = 32-byte 前缀(12) + raw(32)。取末 32B。
|
|
44
|
+
publicKeyRaw: Buffer.from(raw.subarray(raw.length - 32)),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/** 加载或生成节点签名身份(幂等;已存在则读回,避免重启换钥)。 */
|
|
48
|
+
export function loadOrCreateA2aSigningIdentity(dataDir, keyid) {
|
|
49
|
+
const file = path.join(dataDir, A2A_SIGNING_KEY_FILE);
|
|
50
|
+
if (existsSync(file)) {
|
|
51
|
+
const parsed = JSON.parse(readFileSync(file, "utf8"));
|
|
52
|
+
if (typeof parsed.keyid !== "string" ||
|
|
53
|
+
parsed.algorithm !== "ed25519" ||
|
|
54
|
+
typeof parsed.privateKeyPem !== "string" ||
|
|
55
|
+
typeof parsed.publicKeyPem !== "string") {
|
|
56
|
+
throw new Error(`A2A 签名密钥文件 ${file} 形状非法(fail-closed)`);
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
keyid: parsed.keyid,
|
|
60
|
+
algorithm: "ed25519",
|
|
61
|
+
privateKeyPem: parsed.privateKeyPem,
|
|
62
|
+
publicKeyPem: parsed.publicKeyPem,
|
|
63
|
+
publicKeyRaw: Buffer.from(parsed.publicKeyRaw ?? "", "base64"),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
const identity = generateA2aSigningIdentity(keyid);
|
|
67
|
+
mkdirSync(dataDir, { recursive: true, mode: 0o700 });
|
|
68
|
+
writeFileSync(file, JSON.stringify({
|
|
69
|
+
keyid: identity.keyid,
|
|
70
|
+
algorithm: identity.algorithm,
|
|
71
|
+
privateKeyPem: identity.privateKeyPem,
|
|
72
|
+
publicKeyPem: identity.publicKeyPem,
|
|
73
|
+
publicKeyRaw: identity.publicKeyRaw.toString("base64"),
|
|
74
|
+
created_at: new Date().toISOString(),
|
|
75
|
+
}, null, 2), { mode: 0o600 });
|
|
76
|
+
return identity;
|
|
77
|
+
}
|
|
78
|
+
/** 由节点身份构造出站签名器(HttpMessageSigner 即 A2AOutboundSigner 形状)。 */
|
|
79
|
+
export function createA2aOutboundSigner(identity) {
|
|
80
|
+
return new HttpMessageSigner({
|
|
81
|
+
keyid: identity.keyid,
|
|
82
|
+
algorithm: identity.algorithm,
|
|
83
|
+
privateKey: identity.privateKeyPem,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
/** 从签名密钥 JSON 文件加载身份(与 loadOrCreateA2aSigningIdentity 同形状)。 */
|
|
87
|
+
export function loadA2aSigningIdentityFromFile(file) {
|
|
88
|
+
const parsed = JSON.parse(readFileSync(file, "utf8"));
|
|
89
|
+
if (typeof parsed.keyid !== "string" ||
|
|
90
|
+
parsed.algorithm !== "ed25519" ||
|
|
91
|
+
typeof parsed.privateKeyPem !== "string" ||
|
|
92
|
+
typeof parsed.publicKeyPem !== "string") {
|
|
93
|
+
throw new Error(`A2A 签名密钥文件 ${file} 形状非法(fail-closed)`);
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
keyid: parsed.keyid,
|
|
97
|
+
algorithm: "ed25519",
|
|
98
|
+
privateKeyPem: parsed.privateKeyPem,
|
|
99
|
+
publicKeyPem: parsed.publicKeyPem,
|
|
100
|
+
publicKeyRaw: Buffer.from(parsed.publicKeyRaw ?? "", "base64"),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/** 出站签名器:显式 signer 优先,否则读 `KIWI_A2A_SIGNING_KEY_FILE` env。 */
|
|
104
|
+
export function resolveOutboundSigner(explicit) {
|
|
105
|
+
if (explicit !== undefined)
|
|
106
|
+
return explicit;
|
|
107
|
+
const file = (process.env.KIWI_A2A_SIGNING_KEY_FILE ?? "").trim();
|
|
108
|
+
if (file === "")
|
|
109
|
+
return undefined;
|
|
110
|
+
return createA2aOutboundSigner(loadA2aSigningIdentityFromFile(file));
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* 构造入站签名验证用的 keyid→公钥 resolver。
|
|
114
|
+
* 未知 keyid → undefined(匿名请求按 T0 放行,签名请求身份不可解析则拒绝)。
|
|
115
|
+
*/
|
|
116
|
+
export function resolveA2aSignatureResolver(own, extraKeys = []) {
|
|
117
|
+
const ownKey = {
|
|
118
|
+
keyid: own.keyid,
|
|
119
|
+
algorithm: own.algorithm,
|
|
120
|
+
publicKeyPem: own.publicKeyPem,
|
|
121
|
+
publicKeyRaw: own.publicKeyRaw,
|
|
122
|
+
};
|
|
123
|
+
const byId = new Map([[own.keyid, ownKey]]);
|
|
124
|
+
for (const key of extraKeys) {
|
|
125
|
+
if (key.keyid === own.keyid)
|
|
126
|
+
continue;
|
|
127
|
+
byId.set(key.keyid, key);
|
|
128
|
+
}
|
|
129
|
+
return (keyid) => byId.get(keyid);
|
|
130
|
+
}
|
|
131
|
+
/** Agent Card 的 securitySchemes 条目(对端据此解析本节点公钥)。 */
|
|
132
|
+
export function a2aSignatureSecurityScheme(identity) {
|
|
133
|
+
return {
|
|
134
|
+
"kiwi-signature": {
|
|
135
|
+
type: "kiwi-http-message-signature",
|
|
136
|
+
keyid: identity.keyid,
|
|
137
|
+
algorithm: "ed25519",
|
|
138
|
+
publicKeyPem: identity.publicKeyPem,
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=signing-key.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signing-key.js","sourceRoot":"","sources":["../../src/a2a/signing-key.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2026 harrylabsj
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
export declare const A2A_VERSION_HEADER = "A2A-Version";
|
|
17
|
+
export declare const A2A_EXTENSIONS_HEADER = "A2A-Extensions";
|
|
18
|
+
/** 支持的最高协议版本(本实现)。 */
|
|
19
|
+
export declare const SUPPORTED_A2A_VERSION = "1.0";
|
|
20
|
+
/** KNP extension path(与 Agent Card 声明单一来源)。 */
|
|
21
|
+
export declare const KNP_EXTENSION_PATH = "/a2a/extensions/negotiation/1.0";
|
|
22
|
+
/** 解析 `A2A-Version` 头:空/缺省 → undefined;否则 trim 后返回。 */
|
|
23
|
+
export declare function parseVersion(header: string | undefined): string | undefined;
|
|
24
|
+
/** 解析 `A2A-Extensions` 头:逗号分隔 URI,去空白,过滤空。 */
|
|
25
|
+
export declare function parseExtensions(header: string | undefined): string[];
|
|
26
|
+
/**
|
|
27
|
+
* 激活/拒绝扩展(fail-closed):
|
|
28
|
+
* - 请求声明了服务器**不支持的扩展** → 抛错(未知扩展拒绝);
|
|
29
|
+
* - 支持集内含 KNP extension path → `knpActive: true`。
|
|
30
|
+
*/
|
|
31
|
+
export declare function activateKnp(extensions: string[], supportedUris: ReadonlySet<string>): {
|
|
32
|
+
knpActive: boolean;
|
|
33
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2026 harrylabsj
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* A2A 请求头(issue 05):`A2A-Version` 解析/校验、`A2A-Extensions` 激活 KNP /
|
|
18
|
+
* 未知扩展 fail-closed。KNP extension path 与 Card 声明单一来源
|
|
19
|
+
* (`discovery/agent-card/types.ts` 的 `KIWI_NEGOTIATION_EXTENSION_PATH`)。
|
|
20
|
+
*/
|
|
21
|
+
import { KIWI_NEGOTIATION_EXTENSION_PATH } from "../../discovery/agent-card/index.js";
|
|
22
|
+
export const A2A_VERSION_HEADER = "A2A-Version";
|
|
23
|
+
export const A2A_EXTENSIONS_HEADER = "A2A-Extensions";
|
|
24
|
+
/** 支持的最高协议版本(本实现)。 */
|
|
25
|
+
export const SUPPORTED_A2A_VERSION = "1.0";
|
|
26
|
+
/** KNP extension path(与 Agent Card 声明单一来源)。 */
|
|
27
|
+
export const KNP_EXTENSION_PATH = KIWI_NEGOTIATION_EXTENSION_PATH;
|
|
28
|
+
/** 解析 `A2A-Version` 头:空/缺省 → undefined;否则 trim 后返回。 */
|
|
29
|
+
export function parseVersion(header) {
|
|
30
|
+
if (header === undefined)
|
|
31
|
+
return undefined;
|
|
32
|
+
const v = header.trim();
|
|
33
|
+
return v === "" ? undefined : v;
|
|
34
|
+
}
|
|
35
|
+
/** 解析 `A2A-Extensions` 头:逗号分隔 URI,去空白,过滤空。 */
|
|
36
|
+
export function parseExtensions(header) {
|
|
37
|
+
if (header === undefined || header.trim() === "")
|
|
38
|
+
return [];
|
|
39
|
+
return header
|
|
40
|
+
.split(",")
|
|
41
|
+
.map((s) => s.trim())
|
|
42
|
+
.filter((s) => s !== "");
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* 激活/拒绝扩展(fail-closed):
|
|
46
|
+
* - 请求声明了服务器**不支持的扩展** → 抛错(未知扩展拒绝);
|
|
47
|
+
* - 支持集内含 KNP extension path → `knpActive: true`。
|
|
48
|
+
*/
|
|
49
|
+
export function activateKnp(extensions, supportedUris) {
|
|
50
|
+
const unknown = extensions.filter((uri) => !supportedUris.has(uri));
|
|
51
|
+
if (unknown.length > 0) {
|
|
52
|
+
throw new Error(`unsupported A2A extension(s): ${unknown.join(", ")}`);
|
|
53
|
+
}
|
|
54
|
+
return { knpActive: extensions.some((uri) => uri.endsWith(KNP_EXTENSION_PATH)) };
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=headers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headers.js","sourceRoot":"","sources":["../../../src/a2a/v1/headers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;;GAIG;AAEH,OAAO,EAAE,+BAA+B,EAAE,MAAM,qCAAqC,CAAC;AAEtF,MAAM,CAAC,MAAM,kBAAkB,GAAG,aAAa,CAAC;AAChD,MAAM,CAAC,MAAM,qBAAqB,GAAG,gBAAgB,CAAC;AACtD,sBAAsB;AACtB,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,CAAC;AAE3C,+CAA+C;AAC/C,MAAM,CAAC,MAAM,kBAAkB,GAAG,+BAA+B,CAAC;AAElE,uDAAuD;AACvD,MAAM,UAAU,YAAY,CAAC,MAA0B;IACrD,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC3C,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IACxB,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAClC,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,eAAe,CAAC,MAA0B;IACxD,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,EAAE,CAAC;IAC5D,OAAO,MAAM;SACV,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;AAC7B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW,CACzB,UAAoB,EACpB,aAAkC;IAElC,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IACpE,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,iCAAiC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzE,CAAC;IACD,OAAO,EAAE,SAAS,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC;AACnF,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2026 harrylabsj
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* A2A JSON-RPC 方法名(issue 03)。
|
|
18
|
+
*
|
|
19
|
+
* 1.0 方法名与 0.3 legacy 不同:`SendMessage` vs `message/send`、`GetTask` vs
|
|
20
|
+
* `tasks/get` 等。本文件是方法名 + v1↔legacy 映射的单一来源——声明门禁
|
|
21
|
+
* (tests/a2a-version-declaration.test.ts)与双栈 client/server 都从这读取。
|
|
22
|
+
*/
|
|
23
|
+
/** A2A 1.0 方法名常量。 */
|
|
24
|
+
export declare const METHOD_SEND_MESSAGE = "SendMessage";
|
|
25
|
+
export declare const METHOD_GET_TASK = "GetTask";
|
|
26
|
+
export declare const METHOD_LIST_TASKS = "ListTasks";
|
|
27
|
+
export declare const METHOD_CANCEL_TASK = "CancelTask";
|
|
28
|
+
export declare const METHOD_SUBSCRIBE_TO_TASK = "SubscribeToTask";
|
|
29
|
+
/** A2A 1.0: GetExtendedAgentCard(issue 10 / TCK CARD-EXT-001)。 */
|
|
30
|
+
export declare const METHOD_GET_EXTENDED_AGENT_CARD = "GetExtendedAgentCard";
|
|
31
|
+
/** A2A 1.0: SendStreamingMessage(issue 10 / TCK JSONRPC-SSE-002:不支持流式 → -32004)。 */
|
|
32
|
+
export declare const METHOD_SEND_STREAMING_MESSAGE = "SendStreamingMessage";
|
|
33
|
+
/** A2A 1.0 push 通知配置方法(issue 10 / TCK JSONRPC-SSE-002:不支持推送 → -32003)。 */
|
|
34
|
+
export declare const METHOD_CREATE_PUSH_CONFIG = "CreateTaskPushNotificationConfig";
|
|
35
|
+
export declare const METHOD_GET_PUSH_CONFIG = "GetTaskPushNotificationConfig";
|
|
36
|
+
export declare const METHOD_LIST_PUSH_CONFIGS = "ListTaskPushNotificationConfigs";
|
|
37
|
+
export declare const METHOD_DELETE_PUSH_CONFIG = "DeleteTaskPushNotificationConfig";
|
|
38
|
+
/** A2A 0.3 legacy 方法名常量。 */
|
|
39
|
+
export declare const LEGACY_METHOD_SEND_MESSAGE = "message/send";
|
|
40
|
+
export declare const LEGACY_METHOD_GET_TASK = "tasks/get";
|
|
41
|
+
/** 1.0 → legacy 映射(1.0 方法名 → 0.3 方法名)。 */
|
|
42
|
+
export declare const V1_TO_LEGACY: Readonly<Record<string, string>>;
|
|
43
|
+
/** legacy → 1.0 映射(0.3 方法名 → 1.0 方法名)。 */
|
|
44
|
+
export declare const LEGACY_TO_V1: Readonly<Record<string, string>>;
|
|
45
|
+
/** 全部 1.0 方法名集合。 */
|
|
46
|
+
export declare const V1_METHODS: ReadonlySet<string>;
|
|
47
|
+
/** 全部 0.3 legacy 方法名集合。 */
|
|
48
|
+
export declare const LEGACY_METHODS: ReadonlySet<string>;
|
|
49
|
+
/** 给定方法名是否为 1.0 方法。 */
|
|
50
|
+
export declare function isV1Method(method: string): boolean;
|
|
51
|
+
/** 给定方法名是否为 0.3 legacy 方法。 */
|
|
52
|
+
export declare function isLegacyMethod(method: string): boolean;
|