@nelsonlongxiang/dsh-open-a2a-net 0.6.37 → 0.6.38
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 +3 -3
- package/README_zh.md +3 -3
- package/cli/a2a.mjs +34 -4
- package/lib/canvas-discovery.js +29 -0
- package/lib/client.js +63 -63
- package/lib/direct-forward.js +49 -27
- package/lib/faces/admin.js +10 -0
- package/lib/faces/wire.js +18 -5
- package/lib/index.js +77 -14
- package/lib/origin-claim.js +1 -1
- package/lib/peer-directory.js +1 -1
- package/lib/skill/references/cli.md +7 -3
- package/lib/skill/references/pitfalls.md +1 -1
- package/lib/skill/references/setup.md +5 -9
- package/lib/task-auth.js +1 -1
- package/lib/task-ledger-rows.js +32 -4
- package/lib/task-ledger.js +11 -5
- package/lib/tools/info.js +12 -5
- package/lib/types/canvas-discovery.d.ts +20 -0
- package/lib/types/direct-forward.d.ts +9 -0
- package/lib/types/faces/admin.d.ts +10 -0
- package/lib/types/faces/wire.d.ts +3 -1
- package/lib/types/index.d.ts +1 -1
- package/lib/types/origin-claim.d.ts +4 -1
- package/lib/types/task-auth.d.ts +2 -0
- package/lib/types/task-ledger-rows.d.ts +16 -5
- package/lib/types/task-ledger.d.ts +3 -0
- package/lib/types/tools/info.d.ts +3 -0
- package/package.json +1 -1
|
@@ -70,6 +70,10 @@ export interface AdminFaceDeps extends Pick<CanvasNotifyDeps, 'verifyOriginClaim
|
|
|
70
70
|
}>;
|
|
71
71
|
readonly layoutStore: LayoutStore;
|
|
72
72
|
readonly taskLedger: TaskLedger;
|
|
73
|
+
readonly enforceRefused?: {
|
|
74
|
+
reason: string;
|
|
75
|
+
blockers: readonly string[];
|
|
76
|
+
};
|
|
73
77
|
/** #114 S6: observe (lazily) and return the /state `authorization` block. */
|
|
74
78
|
readonly authorizationView: () => unknown;
|
|
75
79
|
readonly idempotencyStore: IdempotencyStore;
|
|
@@ -140,6 +144,12 @@ export interface AdminFaceDeps extends Pick<CanvasNotifyDeps, 'verifyOriginClaim
|
|
|
140
144
|
readonly legacyInboundCount: number;
|
|
141
145
|
readonly unboundInboundCount: number;
|
|
142
146
|
readonly boundMissInboundCount: number;
|
|
147
|
+
readonly boundMissRecent: ReadonlyArray<{
|
|
148
|
+
caller: string;
|
|
149
|
+
audience: string;
|
|
150
|
+
count: number;
|
|
151
|
+
lastAt: number;
|
|
152
|
+
}>;
|
|
143
153
|
readonly ownCardUrl: string;
|
|
144
154
|
ownerSeatNames: Record<string, string>;
|
|
145
155
|
ownerAllowlist: string[];
|
|
@@ -131,6 +131,7 @@ export interface WireDeps {
|
|
|
131
131
|
readonly rawBody?: Uint8Array;
|
|
132
132
|
}) => Promise<OriginClaimResult>;
|
|
133
133
|
readonly forwardDirect: (request: ForwardRequest) => Promise<A2aRouteResult>;
|
|
134
|
+
readonly diagnoseCanvas: (team: string, reason: string, caller?: string) => Promise<string>;
|
|
134
135
|
readonly remoteCliProof: (handle: string, claim: Extract<OriginClaimResult, {
|
|
135
136
|
ok: true;
|
|
136
137
|
}>) => Promise<RemoteCliProof | undefined>;
|
|
@@ -169,6 +170,7 @@ export interface WireDeps {
|
|
|
169
170
|
/** gh#224: refuses a new delivery once the target already owes `targetQueueCap` receipts. */
|
|
170
171
|
readonly refuseIfQueueFull: (caller: string, message: string, team: string, taskId: string, mailbox: boolean, res: ServerResponse) => boolean;
|
|
171
172
|
/** Settles a receipt; returns the enforce refusal of the row its header names (#139), if any. */
|
|
173
|
+
readonly waitForForwardBirth: (message: string) => Promise<void>;
|
|
172
174
|
readonly settleAndAnnounce: (message: string, settler?: Settler) => SettlementRefusal | undefined;
|
|
173
175
|
readonly touchWakeDemand: () => void;
|
|
174
176
|
readonly session: string;
|
|
@@ -199,7 +201,7 @@ export interface WireDeps {
|
|
|
199
201
|
readonly nativeTeamsRound: (prepared: Extract<NativePrepared, {
|
|
200
202
|
ok: true;
|
|
201
203
|
}>, team: string, caller: string, message: string, taskId: string | undefined, proofClause: string, external?: AbortSignal, proofHeader?: (team: string, taskId: string, from: string, proofClause: string) => string) => Promise<NativeRoundOutcome>;
|
|
202
|
-
readonly routeIntoAgent: (team: string, message: string, caller: string, taskId?: string, proofClause?: string, directHeader?: (from: string) => string) => Promise<RouteOutcome>;
|
|
204
|
+
readonly routeIntoAgent: (team: string, message: string, caller: string, taskId?: string, proofClause?: string, directHeader?: (from: string) => string, localFrom?: string, onSteered?: (target: Agent, floor: number) => void) => Promise<RouteOutcome>;
|
|
203
205
|
}
|
|
204
206
|
/**
|
|
205
207
|
* #187: what a verified claim may vouch for at settlement. The signing key always (the card was
|
package/lib/types/index.d.ts
CHANGED
|
@@ -91,7 +91,7 @@ export interface Config {
|
|
|
91
91
|
* (which is left untouched). Inbound faces keep answering. Default false.
|
|
92
92
|
*/
|
|
93
93
|
readonly isolated: boolean;
|
|
94
|
-
/** Forward online local CLI deliveries one hop after a local miss. Default
|
|
94
|
+
/** Forward online local CLI deliveries one hop after a local miss. Default on from 0.6.38; explicit false opts out. */
|
|
95
95
|
readonly forwardDirect: boolean;
|
|
96
96
|
/** Human-facing name published on the agent card. */
|
|
97
97
|
readonly agentName: string;
|
|
@@ -117,7 +117,10 @@ export declare function verifyOriginClaim(req: IncomingMessage, d: {
|
|
|
117
117
|
/** Count one accepted unbound envelope (the drain gauge). */
|
|
118
118
|
readonly onUnbound: () => void;
|
|
119
119
|
/** Count one bound form that missed and fell back to the unbound one. */
|
|
120
|
-
readonly onBoundMiss?: (
|
|
120
|
+
readonly onBoundMiss?: (miss: {
|
|
121
|
+
readonly caller: string;
|
|
122
|
+
readonly audience: string;
|
|
123
|
+
}) => void;
|
|
121
124
|
/** A loopback arrival is an audience of its own (default); off when originClaimUrl declares a tunnel or proxy. */
|
|
122
125
|
readonly loopbackArrival?: boolean;
|
|
123
126
|
readonly now: number;
|
package/lib/types/task-auth.d.ts
CHANGED
|
@@ -232,6 +232,8 @@ export interface SettlementRow {
|
|
|
232
232
|
readonly peerHost?: string;
|
|
233
233
|
/** #139: the member that actually received the task (canvas and bare-zone deliveries). */
|
|
234
234
|
readonly deliveredTo?: string;
|
|
235
|
+
readonly forwarded?: true;
|
|
236
|
+
readonly receiverMembers?: readonly string[];
|
|
235
237
|
}
|
|
236
238
|
/** Facts from outside the row. */
|
|
237
239
|
export interface SettlementFacts {
|
|
@@ -96,31 +96,36 @@ export declare function withAuth(raw: unknown, entry: {
|
|
|
96
96
|
direction?: unknown;
|
|
97
97
|
team?: unknown;
|
|
98
98
|
peer?: unknown;
|
|
99
|
+
forwarded?: unknown;
|
|
100
|
+
sender?: unknown;
|
|
99
101
|
}, now: number): {
|
|
100
102
|
auth?: TaskAuthorization;
|
|
101
103
|
};
|
|
102
104
|
/** Routing and answer facts copied unchanged between a row and its archive entry. */
|
|
103
|
-
export declare function routingOf(row: Pick<TaskRecord, 'peerKey' | 'peerHost' | 'deliveredTo' | 'forwarded' | 'answeredAt'>): Pick<TaskRecord, 'peerKey' | 'peerHost' | 'deliveredTo' | 'forwarded' | 'answeredAt'>;
|
|
105
|
+
export declare function routingOf(row: Pick<TaskRecord, 'peerKey' | 'peerHost' | 'deliveredTo' | 'forwarded' | 'answeredAt' | 'receiverMembers'>): Pick<TaskRecord, 'peerKey' | 'peerHost' | 'deliveredTo' | 'forwarded' | 'answeredAt' | 'receiverMembers'>;
|
|
104
106
|
/** #139: what an outbound row is born with besides its sender. */
|
|
105
107
|
export interface OutboundBirth {
|
|
106
108
|
readonly forwarded?: true;
|
|
107
|
-
/**
|
|
109
|
+
/** Local-candidate admission, or a forwarded online CLI's verified wire admission. */
|
|
108
110
|
readonly auth?: TaskAuthorization;
|
|
109
111
|
readonly peerKey?: string;
|
|
110
112
|
readonly peerHost?: string;
|
|
111
113
|
readonly deliveredTo?: string;
|
|
114
|
+
/** Verified selected peer canvas membership at dispatch; actual deliveredTo remains stricter when available. */
|
|
115
|
+
readonly receiverMembers?: readonly string[];
|
|
112
116
|
}
|
|
113
117
|
/** The facts of one outbound birth that fit the row (see {@link withRouting} for the same shape on restore). */
|
|
114
|
-
export declare function birthFacts(peer: string, birth: OutboundBirth | undefined): Pick<TaskRecord, 'auth' | 'peerKey' | 'peerHost' | 'deliveredTo' | 'forwarded'>;
|
|
118
|
+
export declare function birthFacts(peer: string, birth: OutboundBirth | undefined, team?: string, sender?: Sender, now?: number, warn?: (message: string) => void): Pick<TaskRecord, 'auth' | 'peerKey' | 'peerHost' | 'deliveredTo' | 'forwarded' | 'receiverMembers'>;
|
|
115
119
|
/** Bound on a persisted routing fact; anything longer (or empty, or not a string) is dropped on restore. */
|
|
116
120
|
export declare const ROUTING_FACT_CAP = 256;
|
|
121
|
+
export declare function parseReceiverMembers(value: unknown, warn?: (message: string) => void): readonly string[] | undefined;
|
|
117
122
|
/**
|
|
118
123
|
* #139: restore-side allowlist for the routing facts. Each is kept only in
|
|
119
124
|
* its shape — a non-empty string within the cap — and the peer facts only on
|
|
120
125
|
* a remote outbound row; anything else is dropped (the row survives as one
|
|
121
126
|
* born before the fields, judged by current membership and origin).
|
|
122
127
|
*/
|
|
123
|
-
export declare function withRouting(entry: Record<string, unknown
|
|
128
|
+
export declare function withRouting(entry: Record<string, unknown>, warn?: (message: string) => void): Pick<TaskRecord, 'peerKey' | 'peerHost' | 'deliveredTo' | 'forwarded' | 'answeredAt' | 'receiverMembers'>;
|
|
124
129
|
/** One tracked outbound task still in the owed book (unsettled). */
|
|
125
130
|
export interface TaskRecord {
|
|
126
131
|
readonly taskId: string;
|
|
@@ -164,6 +169,8 @@ export interface TaskRecord {
|
|
|
164
169
|
readonly peerHost?: string;
|
|
165
170
|
/** #139: the member that actually received the task (canvas / bare-zone deliveries). */
|
|
166
171
|
readonly deliveredTo?: string;
|
|
172
|
+
/** Verified selected peer canvas membership at dispatch; actual deliveredTo remains stricter when available. */
|
|
173
|
+
readonly receiverMembers?: readonly string[];
|
|
167
174
|
/** Local target has produced an answer; still owed until receipt delivery/settlement, but no longer queued. */
|
|
168
175
|
answeredAt?: number;
|
|
169
176
|
status: TaskStatus;
|
|
@@ -221,6 +228,8 @@ export interface ArchivedRecord {
|
|
|
221
228
|
readonly peerKey?: string;
|
|
222
229
|
readonly peerHost?: string;
|
|
223
230
|
readonly deliveredTo?: string;
|
|
231
|
+
/** Verified selected peer canvas membership at dispatch; actual deliveredTo remains stricter when available. */
|
|
232
|
+
readonly receiverMembers?: readonly string[];
|
|
224
233
|
/** Local answer time retained as audit metadata, independent of resolution time. */
|
|
225
234
|
readonly answeredAt?: number;
|
|
226
235
|
/** #114 S4: who settled the row (receipt and echo ends), and their chain role. */
|
|
@@ -252,6 +261,8 @@ export interface CancelledResult extends AbandonResult {
|
|
|
252
261
|
}
|
|
253
262
|
/** Per-instance knobs; defaults come from the exported constants. */
|
|
254
263
|
export interface TaskLedgerOptions {
|
|
264
|
+
/** Invalid persisted member entries are dropped individually and reported without their content. */
|
|
265
|
+
warn?: (message: string) => void;
|
|
255
266
|
/** Stale-TTL override (tests inject short windows); defaults to {@link TASK_STALE_TTL_MS}. */
|
|
256
267
|
staleTtlMs?: number;
|
|
257
268
|
/** Archive capacity override; defaults to {@link ARCHIVE_CAP}. */
|
|
@@ -331,7 +342,7 @@ export declare const SETTLEMENT_REFUSAL_CAP = 64;
|
|
|
331
342
|
export interface SettlementJudge {
|
|
332
343
|
readonly enforce: boolean;
|
|
333
344
|
readonly settler: SettlementRefusalRecord['settler'];
|
|
334
|
-
check(row: Pick<TaskRecord, 'team' | 'peer' | 'direction' | 'auth' | 'peerKey' | 'peerHost' | 'deliveredTo'>, echo: boolean): SettlementVerdict;
|
|
345
|
+
check(row: Pick<TaskRecord, 'team' | 'peer' | 'direction' | 'auth' | 'peerKey' | 'peerHost' | 'deliveredTo' | 'forwarded' | 'receiverMembers'>, echo: boolean): SettlementVerdict;
|
|
335
346
|
}
|
|
336
347
|
/** Restore-side allowlist for settledBy: whole or nothing. */
|
|
337
348
|
export declare function withSettledBy(raw: unknown): {
|
|
@@ -44,6 +44,7 @@ export declare class TaskLedger {
|
|
|
44
44
|
private readonly archiveCap;
|
|
45
45
|
/** Injectable clock (option `now`). */
|
|
46
46
|
private readonly now;
|
|
47
|
+
private readonly warn;
|
|
47
48
|
/**
|
|
48
49
|
* @param path - persistence file (`<dsh-home>/a2a/tasks.json`); empty = no persistence.
|
|
49
50
|
* @param options - TTL/capacity overrides; defaults come from the exported constants.
|
|
@@ -55,6 +56,8 @@ export declare class TaskLedger {
|
|
|
55
56
|
* @returns the owed-book records.
|
|
56
57
|
*/
|
|
57
58
|
list(): readonly TaskRecord[];
|
|
59
|
+
/** #275: old forwarded canvas debts cannot be safely upgraded by inventing receiver authority. */
|
|
60
|
+
settlementEnforceBlockers(): string[];
|
|
58
61
|
/**
|
|
59
62
|
* The settled archive, most recently resolved first. Rows land here the
|
|
60
63
|
* moment their receipt correlates and stay until the archive cap evicts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nelsonlongxiang/dsh-open-a2a-net",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.38",
|
|
4
4
|
"description": "Open A2A network plugin for DeepSeek Harness: signed agent cards, decentralized peer/zone discovery, direct routing model tools, and joinable session nodes with a sidebar control",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|