@loopingai/core 0.1.1 → 0.2.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 +131 -15
- package/dist/a2a/card.d.ts +35 -0
- package/dist/a2a/card.d.ts.map +1 -1
- package/dist/a2a/card.js +41 -3
- package/dist/a2a/card.js.map +1 -1
- package/dist/a2a/context.d.ts +9 -3
- package/dist/a2a/context.d.ts.map +1 -1
- package/dist/a2a/context.js +11 -4
- package/dist/a2a/context.js.map +1 -1
- package/dist/a2a/index.d.ts +1 -1
- package/dist/a2a/index.d.ts.map +1 -1
- package/dist/a2a/index.js +1 -1
- package/dist/a2a/index.js.map +1 -1
- package/dist/a2a/notify.d.ts +11 -2
- package/dist/a2a/notify.d.ts.map +1 -1
- package/dist/a2a/notify.js +12 -3
- package/dist/a2a/notify.js.map +1 -1
- package/dist/a2a/verify.d.ts +23 -2
- package/dist/a2a/verify.d.ts.map +1 -1
- package/dist/a2a/verify.js +26 -3
- package/dist/a2a/verify.js.map +1 -1
- package/dist/agent/history.d.ts +15 -0
- package/dist/agent/history.d.ts.map +1 -1
- package/dist/agent/history.js +17 -0
- package/dist/agent/history.js.map +1 -1
- package/dist/agent/index.d.ts +1 -1
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js +1 -1
- package/dist/agent/index.js.map +1 -1
- package/dist/contract/index.d.ts +1 -1
- package/dist/contract/index.d.ts.map +1 -1
- package/dist/contract/index.js.map +1 -1
- package/dist/contract/plugin.d.ts +86 -3
- package/dist/contract/plugin.d.ts.map +1 -1
- package/dist/contract/plugin.js.map +1 -1
- package/dist/db/db.d.ts +32 -14
- package/dist/db/db.d.ts.map +1 -1
- package/dist/db/db.js.map +1 -1
- package/dist/env.d.ts +10 -2
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +10 -2
- package/dist/env.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/runtime/index.d.ts +28 -3
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +39 -3
- package/dist/runtime/index.js.map +1 -1
- package/dist/subagent/workspace.d.ts +21 -0
- package/dist/subagent/workspace.d.ts.map +1 -1
- package/dist/subagent/workspace.js +80 -5
- package/dist/subagent/workspace.js.map +1 -1
- package/dist/testing/auth.d.ts +23 -0
- package/dist/testing/auth.d.ts.map +1 -1
- package/dist/testing/auth.js +11 -3
- package/dist/testing/auth.js.map +1 -1
- package/dist/testing/fixtures.d.ts +21 -0
- package/dist/testing/fixtures.d.ts.map +1 -1
- package/dist/testing/fixtures.js +21 -0
- package/dist/testing/fixtures.js.map +1 -1
- package/dist/testing/node.d.ts +23 -0
- package/dist/testing/node.d.ts.map +1 -1
- package/dist/testing/node.js +23 -0
- package/dist/testing/node.js.map +1 -1
- package/dist/testing/vcr-spec.d.ts +4 -4
- package/dist/testing/vcr-spec.d.ts.map +1 -1
- package/dist/testing/vcr-spec.js +32 -11
- package/dist/testing/vcr-spec.js.map +1 -1
- package/dist/worker/index.d.ts +142 -3
- package/dist/worker/index.d.ts.map +1 -1
- package/dist/worker/index.js +152 -29
- package/dist/worker/index.js.map +1 -1
- package/package.json +12 -4
package/README.md
CHANGED
|
@@ -68,22 +68,84 @@ const manifest = {
|
|
|
68
68
|
|
|
69
69
|
export default {
|
|
70
70
|
fetch: createA2AWorker({
|
|
71
|
-
|
|
72
|
-
//
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
71
|
+
// The stub card at /.well-known/agent-card.json. It describes the origin,
|
|
72
|
+
// not an agent — see below.
|
|
73
|
+
manifest: hostManifest,
|
|
74
|
+
tenants: {
|
|
75
|
+
"my-agent": {
|
|
76
|
+
manifest,
|
|
77
|
+
// One DO instance per verified caller — this is what makes a task
|
|
78
|
+
// unreachable from any other caller by construction.
|
|
79
|
+
resolveAgent: (identity) =>
|
|
80
|
+
env.MY_AGENT.get(env.MY_AGENT.idFromName(identity.key!)),
|
|
81
|
+
// Must be idempotent: the gateway retries dispatch.
|
|
82
|
+
startTurn: async (turn) => {
|
|
83
|
+
await env.TURN_WORKFLOW.create({ id: turn.messageId, params: turn });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
79
86
|
}
|
|
80
87
|
})
|
|
81
88
|
} satisfies ExportedHandler<Env>;
|
|
82
89
|
```
|
|
83
90
|
|
|
84
|
-
That handler serves three routes: the public JWKS, a **signed** AgentCard at
|
|
85
|
-
`/.well-known/agent-card.json`, and gateway-authenticated JSON-RPC. Every POST is
|
|
86
|
-
|
|
91
|
+
That handler serves three routes: the public JWKS, a **signed** stub AgentCard at
|
|
92
|
+
`/.well-known/agent-card.json`, and gateway-authenticated JSON-RPC. Every POST is verified
|
|
93
|
+
before a Durable Object is ever addressed.
|
|
94
|
+
|
|
95
|
+
#### Agents are tenants
|
|
96
|
+
|
|
97
|
+
Agents are keyed by **tenant id**, and one is required on every request — there is no
|
|
98
|
+
default agent and no implicit routing. This is the A2A mechanism for exactly this case:
|
|
99
|
+
`AgentInterface.tenant` is _"an opaque string used for routing requests to a specific agent
|
|
100
|
+
or tenant when multiple agents are served behind a single A2A endpoint"_, and §8.3.2
|
|
101
|
+
requires a client to send the value the interface it selected declared.
|
|
102
|
+
|
|
103
|
+
So one origin serves any number of agents over **one endpoint, one signing key and one
|
|
104
|
+
card** at the well-known path. It works the same for one agent as for twenty; nothing about
|
|
105
|
+
the shape changes.
|
|
106
|
+
|
|
107
|
+
The card is the reason it has to be this way rather than a path prefix per agent. Its
|
|
108
|
+
location is a **well-known URI**, which RFC 8615 defines per-authority, so exactly one card
|
|
109
|
+
per origin is discoverable at the path A2A registered with IANA. A gateway resolving
|
|
110
|
+
`/.well-known/agent-card.json` against the origin finds that one card whatever prefix an
|
|
111
|
+
agent is mounted behind — and pins its key for all of them.
|
|
112
|
+
|
|
113
|
+
Which is why the card served there is a **stub**: it describes the deployment, advertises
|
|
114
|
+
the endpoint and `extendedAgentCard`, and names no tenant. A tenant's real card — its name,
|
|
115
|
+
skills and signature — comes from `GetExtendedAgentCard`, the spec's own tenant-aware card
|
|
116
|
+
method:
|
|
117
|
+
|
|
118
|
+
```jsonc
|
|
119
|
+
// POST /a2a
|
|
120
|
+
{
|
|
121
|
+
"jsonrpc": "2.0",
|
|
122
|
+
"id": 1,
|
|
123
|
+
"method": "GetExtendedAgentCard",
|
|
124
|
+
"params": { "tenant": "my-agent" }
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
A card carries one interface entry and clients take the first, so the stub cannot list its
|
|
129
|
+
siblings — put their names in `description` for a human, and register them out of band.
|
|
130
|
+
|
|
131
|
+
Two independent checks keep one tenant's traffic out of another's:
|
|
132
|
+
|
|
133
|
+
| check | proves |
|
|
134
|
+
| ------------ | -------------------------------------------- |
|
|
135
|
+
| `aud` | the token was minted for **this deployment** |
|
|
136
|
+
| tenant claim | …and for **this agent on it** |
|
|
137
|
+
|
|
138
|
+
The second is load-bearing. Every tenant shares one endpoint and therefore one audience, so
|
|
139
|
+
the audience cannot distinguish them: without the claim, `tenant` would be an
|
|
140
|
+
unauthenticated field in the request body and a token minted for one agent could be replayed
|
|
141
|
+
against any sibling. A token carrying no tenant claim is rejected rather than treated as a
|
|
142
|
+
wildcard.
|
|
143
|
+
|
|
144
|
+
> **Breaking.** Requires a gateway that mints both the endpoint audience and the tenant
|
|
145
|
+
> claim, and registers agents with a tenant id — looping-gateway
|
|
146
|
+
> [#62](https://github.com/Looping-AI/looping-gateway/pull/62). The two sides do not
|
|
147
|
+
> interoperate across this change in either direction, so they deploy together and
|
|
148
|
+
> registered agents are re-registered.
|
|
87
149
|
|
|
88
150
|
### 3. Build the runtime in your Durable Object
|
|
89
151
|
|
|
@@ -207,10 +269,40 @@ its cause.
|
|
|
207
269
|
The contract is **additive-only within a major**: new capabilities arrive as optional
|
|
208
270
|
fields on `AgentPlugin`.
|
|
209
271
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
272
|
+
### Plugin-owned tables
|
|
273
|
+
|
|
274
|
+
A plugin owns its tables outright, through `store: PluginStore` — but it must stay out of
|
|
275
|
+
core's migration journal. `drizzle-orm/durable-sqlite/migrator` keeps one flat integer
|
|
276
|
+
journal and one global `__drizzle_migrations` table, and two independently-versioned
|
|
277
|
+
packages cannot share that index space.
|
|
278
|
+
|
|
279
|
+
That is a prohibition on exactly **one import**, not on drizzle. The query builder holds
|
|
280
|
+
no journal and no connection state, so a plugin declares its tables with `sqliteTable`,
|
|
281
|
+
writes idempotent DDL in `ensureTables`, and queries through its own handle:
|
|
282
|
+
|
|
283
|
+
```ts
|
|
284
|
+
export const scrapes = sqliteTable("scraper_scrapes", { url: text("url").primaryKey() });
|
|
285
|
+
|
|
286
|
+
store: {
|
|
287
|
+
plugin: "scraper",
|
|
288
|
+
version: 1,
|
|
289
|
+
// Re-run on every hibernation wake-up, so it must be idempotent.
|
|
290
|
+
ensureTables: (sql) => sql.exec(`CREATE TABLE IF NOT EXISTS scraper_scrapes (…)`)
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// …and anywhere the plugin queries:
|
|
294
|
+
const db = drizzle(storage, { schema: { scrapes } });
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
Core records each store's version in a `plugin_migrations` row, so `ensureTables` receives
|
|
298
|
+
the version last seen on disk and an upgrade path can branch on it.
|
|
299
|
+
|
|
300
|
+
### Session hooks
|
|
301
|
+
|
|
302
|
+
`onMessagesDisplaced` hands over the raw messages a compaction is about to fold into a
|
|
303
|
+
summary. Core performs the compaction, so core announces the loss; it neither stores the
|
|
304
|
+
messages nor knows who wants them. An episodic-memory plugin, an audit log, and a
|
|
305
|
+
cold-storage dump all want exactly this callback, and each gets it:
|
|
214
306
|
|
|
215
307
|
```ts
|
|
216
308
|
// in your DO, wiring the runtime's fan-out into the session
|
|
@@ -224,6 +316,30 @@ Best-effort in both directions — a listener that throws never aborts compactio
|
|
|
224
316
|
must still shorten when a side store is down), and the fan-out is `Promise.allSettled`, so
|
|
225
317
|
one plugin's outage cannot cost another its notification.
|
|
226
318
|
|
|
319
|
+
`shouldHandleTurn` is the other side of the session: a gate that decides whether a turn
|
|
320
|
+
runs at all, before the loop builds or calls anything. An agent that sees every message in
|
|
321
|
+
its channels is mostly seeing messages that are not for it, and asking a model already
|
|
322
|
+
trying to be helpful to stay quiet degrades _invisibly_ — failing to call a decline-tool
|
|
323
|
+
looks identical to deciding not to. Every declaring plugin is consulted and the answers are
|
|
324
|
+
AND-ed, so any one gate may decline.
|
|
325
|
+
|
|
326
|
+
```ts
|
|
327
|
+
if (!(await this.runtime.shouldHandleTurn({ history }))) return; // declined
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
It **fails open**: a gate that throws is counted as `true`. The two mistakes are not
|
|
331
|
+
symmetric — a wrong reply is noise the user can see and ignore, while a wrong silence is
|
|
332
|
+
invisible to the person who needed an answer.
|
|
333
|
+
|
|
334
|
+
### The workspace backend
|
|
335
|
+
|
|
336
|
+
Core declares the `WorkspaceBacking` shape and enforces the caps, but ships no backend —
|
|
337
|
+
the predecessor's was `@cloudflare/shell`, which is experimental, and an agent that never
|
|
338
|
+
delegates file work should not carry it. A plugin supplies one via `workspaceBacking`; at
|
|
339
|
+
most one may, and an agent that installs none gets `memoryWorkspaceBacking`. So
|
|
340
|
+
`runtime.workspaceBacking` is always defined and your `SubagentRuntime` never needs a null
|
|
341
|
+
check.
|
|
342
|
+
|
|
227
343
|
---
|
|
228
344
|
|
|
229
345
|
## Testing
|
package/dist/a2a/card.d.ts
CHANGED
|
@@ -33,6 +33,18 @@ export interface BuildCardOptions {
|
|
|
33
33
|
origin: string;
|
|
34
34
|
/** Path this agent answers JSON-RPC on. Defaults to {@link A2A_RPC_PATH}. */
|
|
35
35
|
rpcPath?: string;
|
|
36
|
+
/**
|
|
37
|
+
* The tenant this card describes, advertised on its interface entry.
|
|
38
|
+
*
|
|
39
|
+
* Several agents share one endpoint here, so `tenant` is what says *which*
|
|
40
|
+
* one — A2A spec §8.3.2 requires a client to echo the declared value on every
|
|
41
|
+
* request, and this Worker refuses a request that does not.
|
|
42
|
+
*
|
|
43
|
+
* Omitted for the **root stub card**, which describes the origin rather than
|
|
44
|
+
* any agent: it advertises the endpoint and `extendedAgentCard`, and a caller
|
|
45
|
+
* reaches a real agent by asking for its tenant.
|
|
46
|
+
*/
|
|
47
|
+
tenant?: string;
|
|
36
48
|
/**
|
|
37
49
|
* Advertise the gateway's Bearer-JWT scheme in `securitySchemes`.
|
|
38
50
|
*
|
|
@@ -93,6 +105,29 @@ export declare function buildBaseCard(manifest: AgentManifest, opts: BuildCardOp
|
|
|
93
105
|
* (Trust-On-First-Use).
|
|
94
106
|
*/
|
|
95
107
|
export declare function signCard(card: AgentCard, cfg: CardSigningConfig): Promise<WireAgentCard>;
|
|
108
|
+
/**
|
|
109
|
+
* The same signature, attached to the **in-memory** card instead of the wire
|
|
110
|
+
* one — for a caller that hands the card to something which will encode it
|
|
111
|
+
* itself.
|
|
112
|
+
*
|
|
113
|
+
* That caller is `GetExtendedAgentCard`. The SDK's JSON-RPC transport runs
|
|
114
|
+
* `AgentCard.toJSON()` over whatever the extended-card provider returns, so
|
|
115
|
+
* returning {@link signCard}'s wire card means `toJSON` runs over a document
|
|
116
|
+
* that has already been encoded. For most cards that is a no-op and looks fine
|
|
117
|
+
* — which is the trap. `securitySchemes` is a protobuf *oneof*: encoding it
|
|
118
|
+
* twice collapses `{ gatewayJwt: { httpAuthSecurityScheme: … } }` to
|
|
119
|
+
* `{ gatewayJwt: {} }`, the served document stops matching the one that was
|
|
120
|
+
* signed, and every signature verification fails.
|
|
121
|
+
*
|
|
122
|
+
* So the double encode is latent today only because
|
|
123
|
+
* {@link BuildCardOptions.advertiseSecuritySchemes} defaults to `false`; it
|
|
124
|
+
* would surface the day that flag is flipped, as a signature failure with
|
|
125
|
+
* nothing pointing back here. Returning the in-memory card lets the SDK do the
|
|
126
|
+
* single encode the signature was computed over, and is correct either way.
|
|
127
|
+
*
|
|
128
|
+
* `card.spec.ts` pins both halves.
|
|
129
|
+
*/
|
|
130
|
+
export declare function signCardInPlace(card: AgentCard, cfg: CardSigningConfig): Promise<AgentCard>;
|
|
96
131
|
/**
|
|
97
132
|
* The card's protobuf-JSON encoding. Typed back as `AgentCard` for the SDK
|
|
98
133
|
* signer, which is generic over "the document to canonicalize" rather than over
|
package/dist/a2a/card.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"card.d.ts","sourceRoot":"","sources":["../../src/a2a/card.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AAChC,OAAO,EAEL,SAAS,EAEV,MAAM,aAAa,CAAC;AAKrB,iFAAiF;AACjF,eAAO,MAAM,YAAY,SAAS,CAAC;AAEnC;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,GAAG,IAAI,CAC9B,SAAS,EACP,MAAM,GACN,aAAa,GACb,SAAS,GACT,cAAc,GACd,mBAAmB,GACnB,oBAAoB,GACpB,QAAQ,CACX,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEpD,MAAM,WAAW,iBAAiB;IAChC,4DAA4D;IAC5D,UAAU,EAAE,GAAG,GAAG;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAClC,wEAAwE;IACxE,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,gBAAgB;IAC/B,6EAA6E;IAC7E,MAAM,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,wBAAwB,CAAC,EAAE,OAAO,CAAC;CACpC;AAUD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,aAAa,EACvB,IAAI,EAAE,gBAAgB,GACrB,SAAS,
|
|
1
|
+
{"version":3,"file":"card.d.ts","sourceRoot":"","sources":["../../src/a2a/card.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AAChC,OAAO,EAEL,SAAS,EAEV,MAAM,aAAa,CAAC;AAKrB,iFAAiF;AACjF,eAAO,MAAM,YAAY,SAAS,CAAC;AAEnC;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,GAAG,IAAI,CAC9B,SAAS,EACP,MAAM,GACN,aAAa,GACb,SAAS,GACT,cAAc,GACd,mBAAmB,GACnB,oBAAoB,GACpB,QAAQ,CACX,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEpD,MAAM,WAAW,iBAAiB;IAChC,4DAA4D;IAC5D,UAAU,EAAE,GAAG,GAAG;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAClC,wEAAwE;IACxE,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,gBAAgB;IAC/B,6EAA6E;IAC7E,MAAM,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;;;;OAUG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,wBAAwB,CAAC,EAAE,OAAO,CAAC;CACpC;AAUD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,aAAa,EACvB,IAAI,EAAE,gBAAgB,GACrB,SAAS,CA6CX;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,SAAS,EACf,GAAG,EAAE,iBAAiB,GACrB,OAAO,CAAC,aAAa,CAAC,CASxB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,SAAS,EACf,GAAG,EAAE,iBAAiB,GACrB,OAAO,CAAC,SAAS,CAAC,CAGpB;AAED;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,SAAS,CAEnD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAI5E;AAED,iFAAiF;AACjF,wBAAgB,cAAc,CAAC,UAAU,EAAE,GAAG,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG;IACjE,IAAI,EAAE,GAAG,EAAE,CAAC;CACb,CAIA"}
|
package/dist/a2a/card.js
CHANGED
|
@@ -24,14 +24,26 @@ export function buildBaseCard(manifest, opts) {
|
|
|
24
24
|
const rpcPath = opts.rpcPath ?? A2A_RPC_PATH;
|
|
25
25
|
return {
|
|
26
26
|
...manifest,
|
|
27
|
+
capabilities: {
|
|
28
|
+
// `extensions` is required on the proto type but absent from most
|
|
29
|
+
// hand-written manifests, so it is defaulted before the spread rather
|
|
30
|
+
// than after — a manifest that declares extensions keeps them.
|
|
31
|
+
extensions: [],
|
|
32
|
+
...manifest.capabilities,
|
|
33
|
+
// Forced on, not inherited from the manifest: an agent here is *only*
|
|
34
|
+
// reachable as a tenant, and its card *only* through
|
|
35
|
+
// `GetExtendedAgentCard`. The SDK gates that method on this flag, reading
|
|
36
|
+
// it off whichever card the request handler was built with (spec §3.3.4 —
|
|
37
|
+
// it MUST return `UnsupportedOperationError` when unset), so every card
|
|
38
|
+
// this Worker serves has to carry it, the stub and the tenants alike.
|
|
39
|
+
extendedAgentCard: true
|
|
40
|
+
},
|
|
27
41
|
supportedInterfaces: [
|
|
28
42
|
{
|
|
29
43
|
url: `${opts.origin}${rpcPath}`,
|
|
30
44
|
protocolBinding: "JSONRPC",
|
|
31
45
|
protocolVersion: A2A_PROTOCOL_VERSION,
|
|
32
|
-
|
|
33
|
-
// protocol-level tenant slot goes unused.
|
|
34
|
-
tenant: ""
|
|
46
|
+
tenant: opts.tenant ?? ""
|
|
35
47
|
}
|
|
36
48
|
],
|
|
37
49
|
provider: undefined,
|
|
@@ -82,6 +94,32 @@ export async function signCard(card, cfg) {
|
|
|
82
94
|
const signed = await sign(wireCard(card));
|
|
83
95
|
return signed;
|
|
84
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* The same signature, attached to the **in-memory** card instead of the wire
|
|
99
|
+
* one — for a caller that hands the card to something which will encode it
|
|
100
|
+
* itself.
|
|
101
|
+
*
|
|
102
|
+
* That caller is `GetExtendedAgentCard`. The SDK's JSON-RPC transport runs
|
|
103
|
+
* `AgentCard.toJSON()` over whatever the extended-card provider returns, so
|
|
104
|
+
* returning {@link signCard}'s wire card means `toJSON` runs over a document
|
|
105
|
+
* that has already been encoded. For most cards that is a no-op and looks fine
|
|
106
|
+
* — which is the trap. `securitySchemes` is a protobuf *oneof*: encoding it
|
|
107
|
+
* twice collapses `{ gatewayJwt: { httpAuthSecurityScheme: … } }` to
|
|
108
|
+
* `{ gatewayJwt: {} }`, the served document stops matching the one that was
|
|
109
|
+
* signed, and every signature verification fails.
|
|
110
|
+
*
|
|
111
|
+
* So the double encode is latent today only because
|
|
112
|
+
* {@link BuildCardOptions.advertiseSecuritySchemes} defaults to `false`; it
|
|
113
|
+
* would surface the day that flag is flipped, as a signature failure with
|
|
114
|
+
* nothing pointing back here. Returning the in-memory card lets the SDK do the
|
|
115
|
+
* single encode the signature was computed over, and is correct either way.
|
|
116
|
+
*
|
|
117
|
+
* `card.spec.ts` pins both halves.
|
|
118
|
+
*/
|
|
119
|
+
export async function signCardInPlace(card, cfg) {
|
|
120
|
+
const signed = await signCard(card, cfg);
|
|
121
|
+
return { ...card, signatures: signed.signatures };
|
|
122
|
+
}
|
|
85
123
|
/**
|
|
86
124
|
* The card's protobuf-JSON encoding. Typed back as `AgentCard` for the SDK
|
|
87
125
|
* signer, which is generic over "the document to canonicalize" rather than over
|
package/dist/a2a/card.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"card.js","sourceRoot":"","sources":["../../src/a2a/card.ts"],"names":[],"mappings":"AACA,OAAO,EACL,oBAAoB,EACpB,SAAS,EACT,0BAA0B,EAC3B,MAAM,aAAa,CAAC;AAErB,+EAA+E;AAC/E,MAAM,GAAG,GAAG,OAAO,CAAC;AAEpB,iFAAiF;AACjF,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"card.js","sourceRoot":"","sources":["../../src/a2a/card.ts"],"names":[],"mappings":"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"}
|
package/dist/a2a/context.d.ts
CHANGED
|
@@ -5,10 +5,16 @@ import type { GatewayIdentity } from "./verify.js";
|
|
|
5
5
|
* stashes the raw headers in the context's state bag, so an executor can reach
|
|
6
6
|
* them the same way it would under the Express binding.
|
|
7
7
|
*
|
|
8
|
-
* `tenant`
|
|
9
|
-
*
|
|
8
|
+
* `tenant` names which agent on this origin the call is for. The SDK's
|
|
9
|
+
* `JsonRpcTransportHandler` would also lift it off `params.tenant` on its own,
|
|
10
|
+
* but only when the context arrives without one — so passing it here is not
|
|
11
|
+
* redundant: this Worker has already parsed, authorized and routed on the
|
|
12
|
+
* tenant before a handler exists to receive the context, and setting it keeps
|
|
13
|
+
* the value the executor and task store see identical to the one that chose
|
|
14
|
+
* them. It is also what reaches the extended-card provider, which the SDK calls
|
|
15
|
+
* with the context alone.
|
|
10
16
|
*/
|
|
11
|
-
export declare function buildCallContext(request: Request, identity: GatewayIdentity): ServerCallContext;
|
|
17
|
+
export declare function buildCallContext(request: Request, identity: GatewayIdentity, tenant: string): ServerCallContext;
|
|
12
18
|
/** Echo back the extensions the handler actually activated (spec §14.2.2). */
|
|
13
19
|
export declare function extensionHeaders(context: ServerCallContext): HeadersInit;
|
|
14
20
|
//# sourceMappingURL=context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/a2a/context.ts"],"names":[],"mappings":"AAKA,OAAO,EAGL,KAAK,iBAAiB,EAEvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AA6BnD
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/a2a/context.ts"],"names":[],"mappings":"AAKA,OAAO,EAGL,KAAK,iBAAiB,EAEvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AA6BnD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,eAAe,EACzB,MAAM,EAAE,MAAM,GACb,iBAAiB,CAanB;AAED,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,GAAG,WAAW,CAIxE"}
|
package/dist/a2a/context.js
CHANGED
|
@@ -31,10 +31,16 @@ class GatewayUser {
|
|
|
31
31
|
* stashes the raw headers in the context's state bag, so an executor can reach
|
|
32
32
|
* them the same way it would under the Express binding.
|
|
33
33
|
*
|
|
34
|
-
* `tenant`
|
|
35
|
-
*
|
|
34
|
+
* `tenant` names which agent on this origin the call is for. The SDK's
|
|
35
|
+
* `JsonRpcTransportHandler` would also lift it off `params.tenant` on its own,
|
|
36
|
+
* but only when the context arrives without one — so passing it here is not
|
|
37
|
+
* redundant: this Worker has already parsed, authorized and routed on the
|
|
38
|
+
* tenant before a handler exists to receive the context, and setting it keeps
|
|
39
|
+
* the value the executor and task store see identical to the one that chose
|
|
40
|
+
* them. It is also what reaches the extended-card provider, which the SDK calls
|
|
41
|
+
* with the context alone.
|
|
36
42
|
*/
|
|
37
|
-
export function buildCallContext(request, identity) {
|
|
43
|
+
export function buildCallContext(request, identity, tenant) {
|
|
38
44
|
const headers = {};
|
|
39
45
|
for (const [name, value] of request.headers)
|
|
40
46
|
headers[name] = value;
|
|
@@ -42,7 +48,8 @@ export function buildCallContext(request, identity) {
|
|
|
42
48
|
extensions: Extensions.parseServiceParameter(request.headers.get(HTTP_EXTENSION_HEADER) ?? undefined),
|
|
43
49
|
user: new GatewayUser(identity),
|
|
44
50
|
headers,
|
|
45
|
-
requestedVersion: request.headers.get(A2A_VERSION_HEADER) ?? undefined
|
|
51
|
+
requestedVersion: request.headers.get(A2A_VERSION_HEADER) ?? undefined,
|
|
52
|
+
tenant
|
|
46
53
|
});
|
|
47
54
|
}
|
|
48
55
|
/** Echo back the extensions the handler actually activated (spec §14.2.2). */
|
package/dist/a2a/context.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/a2a/context.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,UAAU,EACV,qBAAqB,EACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,+BAA+B,EAIhC,MAAM,oBAAoB,CAAC;AAG5B;;;;;;GAMG;AAEH;;;;;GAKG;AACH,MAAM,WAAW;IACc;IAA7B,YAA6B,QAAyB;QAAzB,aAAQ,GAAR,QAAQ,CAAiB;IAAG,CAAC;IAE1D,IAAI,eAAe;QACjB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,QAAQ;QACV,yEAAyE;QACzE,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,IAAI,EAAE,CAAC;IACjC,CAAC;CACF;AAED
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/a2a/context.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,UAAU,EACV,qBAAqB,EACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,+BAA+B,EAIhC,MAAM,oBAAoB,CAAC;AAG5B;;;;;;GAMG;AAEH;;;;;GAKG;AACH,MAAM,WAAW;IACc;IAA7B,YAA6B,QAAyB;QAAzB,aAAQ,GAAR,QAAQ,CAAiB;IAAG,CAAC;IAE1D,IAAI,eAAe;QACjB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,QAAQ;QACV,yEAAyE;QACzE,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,IAAI,EAAE,CAAC;IACjC,CAAC;CACF;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,gBAAgB,CAC9B,OAAgB,EAChB,QAAyB,EACzB,MAAc;IAEd,MAAM,OAAO,GAAmB,EAAE,CAAC;IACnC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,OAAO,CAAC,OAAO;QAAE,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;IAEnE,OAAO,+BAA+B,CAAC;QACrC,UAAU,EAAE,UAAU,CAAC,qBAAqB,CAC1C,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,IAAI,SAAS,CACxD;QACD,IAAI,EAAE,IAAI,WAAW,CAAC,QAAQ,CAAC;QAC/B,OAAO;QACP,gBAAgB,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,SAAS;QACtE,MAAM;KACP,CAAC,CAAC;AACL,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,gBAAgB,CAAC,OAA0B;IACzD,MAAM,SAAS,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAC9C,IAAI,CAAC,SAAS,EAAE,MAAM;QAAE,OAAO,EAAE,CAAC;IAClC,OAAO,EAAE,CAAC,qBAAqB,CAAC,EAAE,UAAU,CAAC,kBAAkB,CAAC,SAAS,CAAC,EAAE,CAAC;AAC/E,CAAC"}
|
package/dist/a2a/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* narrowed task types that survive Durable Object RPC. Nothing here knows what an
|
|
7
7
|
* agent *does* — past {@link A2AExecutor} everything is plain strings.
|
|
8
8
|
*/
|
|
9
|
-
export { IDENTITY_CLAIM, GatewayAuthError, bearerToken, normalizeGatewayOrigins, verifyGatewayToken, type GatewayIdentity, type VerifyOptions } from "./verify.js";
|
|
9
|
+
export { IDENTITY_CLAIM, TENANT_CLAIM, GatewayAuthError, bearerToken, normalizeGatewayOrigins, verifyGatewayToken, type GatewayIdentity, type VerifyOptions } from "./verify.js";
|
|
10
10
|
export { A2A_RPC_PATH, buildBaseCard, signCard, wireCard, parsePrivateJwk, publicCardJwks, type AgentManifest, type BuildCardOptions, type CardSigningConfig, type WireAgentCard } from "./card.js";
|
|
11
11
|
export { NOTIFICATION_TOKEN_HEADER, buildSubmittedTask, buildWorkingTask, buildCompletedTask, buildFailedTask, buildNoReplyCompletedTask, signCallbackJwt, postNotification } from "./notify.js";
|
|
12
12
|
export { taskStateLabel, type PlainArtifact, type PlainMessage, type PlainPart, type PlainStatus, type PlainTask } from "./task.js";
|
package/dist/a2a/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/a2a/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,uBAAuB,EACvB,kBAAkB,EAClB,KAAK,eAAe,EACpB,KAAK,aAAa,EACnB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,eAAe,EACf,cAAc,EACd,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EACnB,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,yBAAyB,EACzB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,yBAAyB,EACzB,eAAe,EACf,gBAAgB,EACjB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,cAAc,EACd,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,SAAS,EACf,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,QAAQ,EACR,SAAS,EACT,MAAM,EACN,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,sBAAsB,EACvB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAElE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,mBAAmB,EACnB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,WAAW,EACjB,MAAM,eAAe,CAAC;AAEvB,YAAY,EACV,aAAa,EACb,SAAS,EACT,YAAY,EACZ,aAAa,EACd,MAAM,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/a2a/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,WAAW,EACX,uBAAuB,EACvB,kBAAkB,EAClB,KAAK,eAAe,EACpB,KAAK,aAAa,EACnB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,eAAe,EACf,cAAc,EACd,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EACnB,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,yBAAyB,EACzB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,yBAAyB,EACzB,eAAe,EACf,gBAAgB,EACjB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,cAAc,EACd,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,SAAS,EACf,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,QAAQ,EACR,SAAS,EACT,MAAM,EACN,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,sBAAsB,EACvB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAElE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,mBAAmB,EACnB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,WAAW,EACjB,MAAM,eAAe,CAAC;AAEvB,YAAY,EACV,aAAa,EACb,SAAS,EACT,YAAY,EACZ,aAAa,EACd,MAAM,iBAAiB,CAAC"}
|
package/dist/a2a/index.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* narrowed task types that survive Durable Object RPC. Nothing here knows what an
|
|
7
7
|
* agent *does* — past {@link A2AExecutor} everything is plain strings.
|
|
8
8
|
*/
|
|
9
|
-
export { IDENTITY_CLAIM, GatewayAuthError, bearerToken, normalizeGatewayOrigins, verifyGatewayToken } from "./verify.js";
|
|
9
|
+
export { IDENTITY_CLAIM, TENANT_CLAIM, GatewayAuthError, bearerToken, normalizeGatewayOrigins, verifyGatewayToken } from "./verify.js";
|
|
10
10
|
export { A2A_RPC_PATH, buildBaseCard, signCard, wireCard, parsePrivateJwk, publicCardJwks } from "./card.js";
|
|
11
11
|
export { NOTIFICATION_TOKEN_HEADER, buildSubmittedTask, buildWorkingTask, buildCompletedTask, buildFailedTask, buildNoReplyCompletedTask, signCallbackJwt, postNotification } from "./notify.js";
|
|
12
12
|
export { taskStateLabel } from "./task.js";
|
package/dist/a2a/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/a2a/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,uBAAuB,EACvB,kBAAkB,EAGnB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,eAAe,EACf,cAAc,EAKf,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,yBAAyB,EACzB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,yBAAyB,EACzB,eAAe,EACf,gBAAgB,EACjB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,cAAc,EAMf,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,QAAQ,EACR,SAAS,EACT,MAAM,EACN,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,sBAAsB,EACvB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAElE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,mBAAmB,EAIpB,MAAM,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/a2a/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,WAAW,EACX,uBAAuB,EACvB,kBAAkB,EAGnB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,eAAe,EACf,cAAc,EAKf,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,yBAAyB,EACzB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,yBAAyB,EACzB,eAAe,EACf,gBAAgB,EACjB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,cAAc,EAMf,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,QAAQ,EACR,SAAS,EACT,MAAM,EACN,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,sBAAsB,EACvB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAElE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,mBAAmB,EAIpB,MAAM,eAAe,CAAC"}
|
package/dist/a2a/notify.d.ts
CHANGED
|
@@ -29,10 +29,19 @@ export declare function buildNoReplyCompletedTask(taskId: string, contextId: str
|
|
|
29
29
|
/**
|
|
30
30
|
* A non-terminal `working` Task snapshot carrying an intermediate content message.
|
|
31
31
|
* Streamed live from the DO as the tool loop emits content before the final reply.
|
|
32
|
-
*
|
|
32
|
+
*
|
|
33
|
+
* `messageId` is derived from `${taskId}:${key}` — stable across re-runs (see
|
|
33
34
|
* {@link agentTextMessage}) so the gateway dedupes correctly on workflow replay.
|
|
35
|
+
*
|
|
36
|
+
* `key` is a **semantic** string, not a step counter, and the distinction is
|
|
37
|
+
* load-bearing: an agent that runs several rounds per task emits progress from
|
|
38
|
+
* each, so a bare index makes round 0's third step and round 1's third step the
|
|
39
|
+
* same message to the gateway — it dedupes the second away and the user watches
|
|
40
|
+
* a task go quiet. A caller that genuinely has one flat sequence can pass
|
|
41
|
+
* `String(i)`; one with rounds should key on both (`r1:step:3`), and milestones
|
|
42
|
+
* on what they are (`ack:1`).
|
|
34
43
|
*/
|
|
35
|
-
export declare function buildWorkingTask(taskId: string, contextId: string, text: string,
|
|
44
|
+
export declare function buildWorkingTask(taskId: string, contextId: string, text: string, key: string): PlainTask;
|
|
36
45
|
/**
|
|
37
46
|
* The terminal `completed` Task POSTed to the gateway callback. The `messageId` is
|
|
38
47
|
* deterministic (`${taskId}:final`, not a fresh UUID) because this is built in the
|
package/dist/a2a/notify.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notify.d.ts","sourceRoot":"","sources":["../../src/a2a/notify.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,GAAG,EAAE,MAAM,MAAM,CAAC;AACzC,OAAO,EAAa,KAAK,IAAI,EAAE,MAAM,aAAa,CAAC;AAGnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAqB3C;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,6BAA6B,CAAC;AAqCpE;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,SAAS,CAEX;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,SAAS,CAEX;AAwBD
|
|
1
|
+
{"version":3,"file":"notify.d.ts","sourceRoot":"","sources":["../../src/a2a/notify.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,GAAG,EAAE,MAAM,MAAM,CAAC;AACzC,OAAO,EAAa,KAAK,IAAI,EAAE,MAAM,aAAa,CAAC;AAGnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAqB3C;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,6BAA6B,CAAC;AAqCpE;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,SAAS,CAEX;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,SAAS,CAEX;AAwBD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,GACV,SAAS,CAQX;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GACZ,SAAS,CAQX;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,GACX,SAAS,CAQX;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,UAAU,EAAE,GAAG,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,EACjC,IAAI,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACjC,OAAO,CAAC,MAAM,CAAC,CAOjB;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,IAAI,GACT,OAAO,CAAC,QAAQ,CAAC,CAanB"}
|
package/dist/a2a/notify.js
CHANGED
|
@@ -94,11 +94,20 @@ function buildTaskUpdate(taskId, contextId, state, text, messageId) {
|
|
|
94
94
|
/**
|
|
95
95
|
* A non-terminal `working` Task snapshot carrying an intermediate content message.
|
|
96
96
|
* Streamed live from the DO as the tool loop emits content before the final reply.
|
|
97
|
-
*
|
|
97
|
+
*
|
|
98
|
+
* `messageId` is derived from `${taskId}:${key}` — stable across re-runs (see
|
|
98
99
|
* {@link agentTextMessage}) so the gateway dedupes correctly on workflow replay.
|
|
100
|
+
*
|
|
101
|
+
* `key` is a **semantic** string, not a step counter, and the distinction is
|
|
102
|
+
* load-bearing: an agent that runs several rounds per task emits progress from
|
|
103
|
+
* each, so a bare index makes round 0's third step and round 1's third step the
|
|
104
|
+
* same message to the gateway — it dedupes the second away and the user watches
|
|
105
|
+
* a task go quiet. A caller that genuinely has one flat sequence can pass
|
|
106
|
+
* `String(i)`; one with rounds should key on both (`r1:step:3`), and milestones
|
|
107
|
+
* on what they are (`ack:1`).
|
|
99
108
|
*/
|
|
100
|
-
export function buildWorkingTask(taskId, contextId, text,
|
|
101
|
-
return buildTaskUpdate(taskId, contextId, TaskState.TASK_STATE_WORKING, text, `${taskId}:${
|
|
109
|
+
export function buildWorkingTask(taskId, contextId, text, key) {
|
|
110
|
+
return buildTaskUpdate(taskId, contextId, TaskState.TASK_STATE_WORKING, text, `${taskId}:${key}`);
|
|
102
111
|
}
|
|
103
112
|
/**
|
|
104
113
|
* The terminal `completed` Task POSTed to the gateway callback. The `messageId` is
|
package/dist/a2a/notify.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notify.js","sourceRoot":"","sources":["../../src/a2a/notify.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAY,MAAM,MAAM,CAAC;AACzC,OAAO,EAAE,SAAS,EAAa,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAG9C;;;;;;;;;;;;;;GAcG;AAEH,+DAA+D;AAC/D,MAAM,GAAG,GAAG,OAAO,CAAC;AAEpB;;;;;GAKG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,0BAA0B,CAAC;AAEpE;;;GAGG;AACH,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEhC;;;;;;GAMG;AACH,MAAM,eAAe,GAAG,IAAI,4BAA4B,EAAE,CAAC;AAE3D,4FAA4F;AAC5F,SAAS,aAAa,CACpB,MAAc,EACd,SAAiB,EACjB,KAAgB;IAEhB,OAAO;QACL,EAAE,EAAE,MAAM;QACV,SAAS;QACT,MAAM,EAAE;YACN,KAAK;YACL,OAAO,EAAE,SAAS;YAClB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC;QACD,SAAS,EAAE,EAAE;QACb,OAAO,EAAE,EAAE;QACX,QAAQ,EAAE,SAAS;KACpB,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAChC,MAAc,EACd,SAAiB;IAEjB,OAAO,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,CAAC,oBAAoB,CAAC,CAAC;AAC1E,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,yBAAyB,CACvC,MAAc,EACd,SAAiB;IAEjB,OAAO,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,CAAC,oBAAoB,CAAC,CAAC;AAC1E,CAAC;AAED;;;;GAIG;AACH,SAAS,eAAe,CACtB,MAAc,EACd,SAAiB,EACjB,KAAgB,EAChB,IAAY,EACZ,SAAiB;IAEjB,MAAM,IAAI,GAAG,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;IACrD,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,gBAAgB,CAAC;QACrC,SAAS;QACT,IAAI;QACJ,SAAS;QACT,MAAM;KACP,CAAC,CAAC;IACH,OAAO,IAAI,CAAC;AACd,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"notify.js","sourceRoot":"","sources":["../../src/a2a/notify.ts"],"names":[],"mappings":"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"}
|
package/dist/a2a/verify.d.ts
CHANGED
|
@@ -6,7 +6,20 @@ import { type JWTPayload } from "jose";
|
|
|
6
6
|
* isn't behind looping-gateway; the default is the Looping namespace so an
|
|
7
7
|
* agent built on this package needs no configuration to interoperate.
|
|
8
8
|
*/
|
|
9
|
-
export declare const IDENTITY_CLAIM = "https://
|
|
9
|
+
export declare const IDENTITY_CLAIM = "https://loopingai.org/identity";
|
|
10
|
+
/**
|
|
11
|
+
* Default namespaced claim naming the **tenant** the gateway minted this token
|
|
12
|
+
* for — which of the agents on this origin it authorizes the call to reach.
|
|
13
|
+
*
|
|
14
|
+
* Several agents share one endpoint, so they also share an `aud`: the audience
|
|
15
|
+
* proves the token was minted for *this deployment*, and can say nothing about
|
|
16
|
+
* which agent on it. This claim is the only thing that can, which is why the
|
|
17
|
+
* Worker refuses a token that omits it rather than falling back to a default.
|
|
18
|
+
* Without it `tenant` would be an unauthenticated field in the request body,
|
|
19
|
+
* and a token legitimately issued for one agent could be replayed against any
|
|
20
|
+
* of its siblings.
|
|
21
|
+
*/
|
|
22
|
+
export declare const TENANT_CLAIM = "https://loopingai.org/tenant";
|
|
10
23
|
/**
|
|
11
24
|
* The gateway-agent instance identity forwarded by the gateway — i.e. which
|
|
12
25
|
* registered agent instance dispatched this call, not the human end user.
|
|
@@ -41,6 +54,8 @@ export interface VerifyOptions {
|
|
|
41
54
|
audience: string;
|
|
42
55
|
/** Claim carrying the caller identity. Defaults to {@link IDENTITY_CLAIM}. */
|
|
43
56
|
identityClaim?: string;
|
|
57
|
+
/** Claim carrying the authorized tenant. Defaults to {@link TENANT_CLAIM}. */
|
|
58
|
+
tenantClaim?: string;
|
|
44
59
|
}
|
|
45
60
|
/**
|
|
46
61
|
* Normalize configured gateway origins to the HTTPS origins emitted in gateway
|
|
@@ -49,16 +64,22 @@ export interface VerifyOptions {
|
|
|
49
64
|
*/
|
|
50
65
|
export declare function normalizeGatewayOrigins(origins: string[]): string[];
|
|
51
66
|
/**
|
|
52
|
-
* Verify a gateway JWT and return its payload
|
|
67
|
+
* Verify a gateway JWT and return its payload, parsed identity and authorized
|
|
68
|
+
* tenant.
|
|
53
69
|
*
|
|
54
70
|
* The `jku` JWK Set URL is read directly from the token's protected header
|
|
55
71
|
* (RFC 7515 §4.1.2) and validated against the allowlist before fetching, so no
|
|
56
72
|
* separate JWKS URL configuration is needed on the remote side.
|
|
57
73
|
*
|
|
74
|
+
* `tenant` is returned rather than enforced: this function stays a pure
|
|
75
|
+
* signature/origin question, and only the caller knows which tenant the request
|
|
76
|
+
* actually addressed. {@link createA2AWorker} compares the two.
|
|
77
|
+
*
|
|
58
78
|
* Throws {@link GatewayAuthError} on any failure.
|
|
59
79
|
*/
|
|
60
80
|
export declare function verifyGatewayToken(token: string, opts: VerifyOptions): Promise<{
|
|
61
81
|
payload: JWTPayload;
|
|
62
82
|
identity: GatewayIdentity;
|
|
83
|
+
tenant: string;
|
|
63
84
|
}>;
|
|
64
85
|
//# sourceMappingURL=verify.d.ts.map
|
package/dist/a2a/verify.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/a2a/verify.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,UAAU,EAChB,MAAM,MAAM,CAAC;AAyBd;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,
|
|
1
|
+
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/a2a/verify.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,UAAU,EAChB,MAAM,MAAM,CAAC;AAyBd;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,mCAAmC,CAAC;AAE/D;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,YAAY,iCAAiC,CAAC;AAE3D;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,eAAe;IAC9B,yDAAyD;IACzD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,oEAAoE;AACpE,qBAAa,gBAAiB,SAAQ,KAAK;gBAC7B,OAAO,EAAE,MAAM;CAI5B;AAcD,wEAAwE;AACxE,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAI3D;AAED,MAAM,WAAW,aAAa;IAC5B,iFAAiF;IACjF,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAenE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC;IACT,OAAO,EAAE,UAAU,CAAC;IACpB,QAAQ,EAAE,eAAe,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC,CA8CD"}
|
package/dist/a2a/verify.js
CHANGED
|
@@ -27,7 +27,20 @@ const ALG = "EdDSA";
|
|
|
27
27
|
* isn't behind looping-gateway; the default is the Looping namespace so an
|
|
28
28
|
* agent built on this package needs no configuration to interoperate.
|
|
29
29
|
*/
|
|
30
|
-
export const IDENTITY_CLAIM = "https://
|
|
30
|
+
export const IDENTITY_CLAIM = "https://loopingai.org/identity";
|
|
31
|
+
/**
|
|
32
|
+
* Default namespaced claim naming the **tenant** the gateway minted this token
|
|
33
|
+
* for — which of the agents on this origin it authorizes the call to reach.
|
|
34
|
+
*
|
|
35
|
+
* Several agents share one endpoint, so they also share an `aud`: the audience
|
|
36
|
+
* proves the token was minted for *this deployment*, and can say nothing about
|
|
37
|
+
* which agent on it. This claim is the only thing that can, which is why the
|
|
38
|
+
* Worker refuses a token that omits it rather than falling back to a default.
|
|
39
|
+
* Without it `tenant` would be an unauthenticated field in the request body,
|
|
40
|
+
* and a token legitimately issued for one agent could be replayed against any
|
|
41
|
+
* of its siblings.
|
|
42
|
+
*/
|
|
43
|
+
export const TENANT_CLAIM = "https://loopingai.org/tenant";
|
|
31
44
|
/** Thrown when a gateway token is missing or fails verification. */
|
|
32
45
|
export class GatewayAuthError extends Error {
|
|
33
46
|
constructor(message) {
|
|
@@ -73,12 +86,17 @@ export function normalizeGatewayOrigins(origins) {
|
|
|
73
86
|
});
|
|
74
87
|
}
|
|
75
88
|
/**
|
|
76
|
-
* Verify a gateway JWT and return its payload
|
|
89
|
+
* Verify a gateway JWT and return its payload, parsed identity and authorized
|
|
90
|
+
* tenant.
|
|
77
91
|
*
|
|
78
92
|
* The `jku` JWK Set URL is read directly from the token's protected header
|
|
79
93
|
* (RFC 7515 §4.1.2) and validated against the allowlist before fetching, so no
|
|
80
94
|
* separate JWKS URL configuration is needed on the remote side.
|
|
81
95
|
*
|
|
96
|
+
* `tenant` is returned rather than enforced: this function stays a pure
|
|
97
|
+
* signature/origin question, and only the caller knows which tenant the request
|
|
98
|
+
* actually addressed. {@link createA2AWorker} compares the two.
|
|
99
|
+
*
|
|
82
100
|
* Throws {@link GatewayAuthError} on any failure.
|
|
83
101
|
*/
|
|
84
102
|
export async function verifyGatewayToken(token, opts) {
|
|
@@ -111,7 +129,12 @@ export async function verifyGatewayToken(token, opts) {
|
|
|
111
129
|
});
|
|
112
130
|
const claim = opts.identityClaim ?? IDENTITY_CLAIM;
|
|
113
131
|
const identity = payload[claim] ?? {};
|
|
114
|
-
|
|
132
|
+
const tenant = payload[opts.tenantClaim ?? TENANT_CLAIM];
|
|
133
|
+
return {
|
|
134
|
+
payload,
|
|
135
|
+
identity,
|
|
136
|
+
tenant: typeof tenant === "string" ? tenant : ""
|
|
137
|
+
};
|
|
115
138
|
}
|
|
116
139
|
catch (err) {
|
|
117
140
|
if (err instanceof GatewayAuthError)
|
package/dist/a2a/verify.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/a2a/verify.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,SAAS,EACT,qBAAqB,EACrB,SAAS,EAEV,MAAM,MAAM,CAAC;AAEd;;;;;;;;;;;;;;;;;;GAkBG;AAEH,+DAA+D;AAC/D,MAAM,GAAG,GAAG,OAAO,CAAC;AAEpB;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,
|
|
1
|
+
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/a2a/verify.ts"],"names":[],"mappings":"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"}
|