@agentium/transport 3.1.2 → 4.0.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 +227 -1
- package/dist/a2a/a2a-server.d.ts.map +1 -1
- package/dist/a2a/durable-v1-server.d.ts +17 -0
- package/dist/a2a/durable-v1-server.d.ts.map +1 -0
- package/dist/a2a/types.d.ts +2 -0
- package/dist/a2a/types.d.ts.map +1 -1
- package/dist/a2a/v1-server.d.ts +27 -0
- package/dist/a2a/v1-server.d.ts.map +1 -0
- package/dist/durable/protocol-host.d.ts +56 -0
- package/dist/durable/protocol-host.d.ts.map +1 -0
- package/dist/express/admin-router.d.ts.map +1 -1
- package/dist/express/durable-router.d.ts +18 -0
- package/dist/express/durable-router.d.ts.map +1 -0
- package/dist/express/file-upload.d.ts +3 -1
- package/dist/express/file-upload.d.ts.map +1 -1
- package/dist/express/rbac-middleware.d.ts +4 -0
- package/dist/express/rbac-middleware.d.ts.map +1 -1
- package/dist/express/router-factory.d.ts.map +1 -1
- package/dist/express/types.d.ts +35 -1
- package/dist/express/types.d.ts.map +1 -1
- package/dist/index.cjs +4347 -2808
- package/dist/index.d.ts +12 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4319 -2764
- package/dist/mcp/durable-task-handler.d.ts +24 -0
- package/dist/mcp/durable-task-handler.d.ts.map +1 -0
- package/dist/socketio/gateway.d.ts +1 -1
- package/dist/socketio/gateway.d.ts.map +1 -1
- package/dist/socketio/types.d.ts +27 -2
- package/dist/socketio/types.d.ts.map +1 -1
- package/dist/socketio/voice-gateway.d.ts +5 -0
- package/dist/socketio/voice-gateway.d.ts.map +1 -1
- package/dist/sse-event-log.d.ts.map +1 -1
- package/dist/text-stream.d.ts +33 -0
- package/dist/text-stream.d.ts.map +1 -0
- package/package.json +21 -10
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ const agent = new Agent({
|
|
|
23
23
|
model: openai("gpt-4o"),
|
|
24
24
|
});
|
|
25
25
|
|
|
26
|
-
app.use("/api", createAgentRouter({ agents: { assistant: agent } }));
|
|
26
|
+
app.use("/api", createAgentRouter({ security: { mode: "local" }, agents: { assistant: agent } }));
|
|
27
27
|
app.listen(3000);
|
|
28
28
|
```
|
|
29
29
|
|
|
@@ -48,3 +48,229 @@ Join the conversation on [Discord](https://discord.gg/T86SJshP).
|
|
|
48
48
|
## License
|
|
49
49
|
|
|
50
50
|
MIT
|
|
51
|
+
|
|
52
|
+
## Authenticated HTTP hosting
|
|
53
|
+
|
|
54
|
+
`createAgentRouter` now requires an explicit identity resolver and resource authorizer whenever
|
|
55
|
+
JWT or RBAC is configured. Scope checks alone do not establish session, checkpoint, or approval
|
|
56
|
+
ownership. Authenticated configuration missing either hook throws during router creation.
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
app.use("/api", createAgentRouter({
|
|
60
|
+
agents: { assistant: agent },
|
|
61
|
+
registry: false,
|
|
62
|
+
jwt: { secret: process.env.JWT_SECRET! },
|
|
63
|
+
rbac: {},
|
|
64
|
+
security: {
|
|
65
|
+
mode: "authenticated",
|
|
66
|
+
resolveIdentity: (claims) => {
|
|
67
|
+
const verified = claims as { sub?: string; tenant?: string };
|
|
68
|
+
return verified.sub
|
|
69
|
+
? { userId: verified.sub, tenantId: verified.tenant }
|
|
70
|
+
: null;
|
|
71
|
+
},
|
|
72
|
+
authorizeResource: async ({ identity, operation, resource }) => {
|
|
73
|
+
// Application-owned implementation; use authoritative records and default-deny.
|
|
74
|
+
// session:create must atomically bind this new ID before resolving true.
|
|
75
|
+
return ownership.authorizeAndBind({ identity, operation, resource });
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
}));
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The `ownership` service above is an application dependency, not a provided in-memory store.
|
|
82
|
+
It must return `false` for unknown or unmigrated ownerless records. Do not infer ownership
|
|
83
|
+
from a request body, checkpoint contents, or possession of an ID. Store session IDs globally
|
|
84
|
+
uniquely and check both the intended actor and tenant according to your application's policy.
|
|
85
|
+
For new executions, the router generates a UUID and waits for `session:create` to persist
|
|
86
|
+
its owner binding; failure prevents Agent/Team/Workflow execution. A supplied session ID
|
|
87
|
+
requires `session:use` and cannot implicitly claim an existing or unknown session. The selected
|
|
88
|
+
ID is returned in `X-Agentium-Session-Id`, including for streaming requests.
|
|
89
|
+
|
|
90
|
+
Host authentication middleware in `middleware` runs before JWT/RBAC and may populate `req.user`
|
|
91
|
+
from credentials it verifies itself. `resolveIdentity` receives only that verified value.
|
|
92
|
+
Authenticated body `userId`/`tenantId` values must match the resolved identity if supplied;
|
|
93
|
+
execution and correction handlers use the resolved values. Multipart run requests perform
|
|
94
|
+
identity and ownership checks after parsing their fields and before Agent execution.
|
|
95
|
+
Do not configure middleware that copies unverified request claims into `req.user`.
|
|
96
|
+
|
|
97
|
+
The resource authorizer receives these operations:
|
|
98
|
+
|
|
99
|
+
| Operation | Resource and required host decision |
|
|
100
|
+
| --- | --- |
|
|
101
|
+
| `session:create`, `session:use` | Session ID and agent/team/workflow name; atomically bind a new ID or verify existing ownership. |
|
|
102
|
+
| `run:use`, `checkpoints:list` | Run ID and agent name; verify ownership before correction association or checkpoint listing. |
|
|
103
|
+
| `checkpoint:restore` | Checkpoint ID and agent name; verify authoritative ownership before rollback. |
|
|
104
|
+
| `approval:read`, `approval:approve`, `approval:deny` | Request ID; verify ownership. Pending lists and SSE events are filtered individually. |
|
|
105
|
+
| `correction:create` | Agent name and requested `scope`; authorize correction visibility. Referenced run/session IDs are checked separately. |
|
|
106
|
+
| `schedules:list` | Entire schedule collection; allow only callers entitled to see all returned schedules. |
|
|
107
|
+
| `schedule:create`, `schedule:delete` | Schedule ID; authorize creation or deletion. Creation grants management authority for that ID, including replacement and all configured scheduler targets. |
|
|
108
|
+
| `admin:get`, `admin:post`, `admin:put`, `admin:patch`, `admin:delete` | Full admin path; authorize administration at that path. |
|
|
109
|
+
|
|
110
|
+
Do not grant collection/admin/scheduler management operations to users needing only per-item
|
|
111
|
+
or restricted-target access; use a dedicated host endpoint until those APIs offer narrower
|
|
112
|
+
contracts. Successful scope checks, including `admin:*`, never bypass resource authorization.
|
|
113
|
+
This hook does not migrate the underlying storage to a multi-tenant schema.
|
|
114
|
+
|
|
115
|
+
RBAC now explicitly covers approvals, corrections, checkpoints/rollback, schedules, metrics,
|
|
116
|
+
tool listings, discovery and nested admin routes. Unknown routes return 403, including for
|
|
117
|
+
administrators, until registered in `rbac.defaultScopes`. An explicit empty scope array means
|
|
118
|
+
"any authenticated identity". `rbac.agentScopes` applies before Express route parameters are
|
|
119
|
+
populated. Optional `rbac.publicRoutes`, such as `["GET /agents"]`, permits intentionally public
|
|
120
|
+
listings or documentation. Resource control routes still require verified identity/ownership.
|
|
121
|
+
Swagger paths need an explicit public route or a `defaultScopes` entry when RBAC is enabled.
|
|
122
|
+
|
|
123
|
+
Every router now requires an explicit `security` option. For a trusted local application, use
|
|
124
|
+
`security: { mode: "local" }`. For hosted use, select `mode: "authenticated"` and provide both
|
|
125
|
+
identity and resource authorization hooks. Omitting security or choosing an unknown mode fails
|
|
126
|
+
before discovery, middleware setup, or optional dependency loading. Local mode cannot be combined
|
|
127
|
+
with JWT/RBAC; configuration never silently downgrades authentication. The text Socket.IO gateway has the explicit contract below. Standalone admin routers and A2A servers retain their own deployment authorization.
|
|
128
|
+
|
|
129
|
+
Team and Workflow HTTP routes enforce session ownership before calling their runtime. Their internal Agent delegation now carries tenant/user/run lineage, cancellation and execution policy. Custom workflow callbacks remain trusted host code; route authorization does not sandbox them.
|
|
130
|
+
|
|
131
|
+
### Text gateway security and connection ownership
|
|
132
|
+
|
|
133
|
+
`createAgentGateway` also requires `security: { mode: "local" }` for trusted local usage. `authMiddleware` requires authenticated mode; it cannot silently select a local gateway. For hosted Socket.IO, middleware verifies credentials and stores trusted state in `socket.data`. Middleware must call `next`; synchronous throws and returned promise rejections deny access with a generic error. Admission waits for any returned promise to settle, and duplicate `next` calls cannot admit twice. The gateway re-resolves identity and calls the host authorizer for every run, cancellation, discovery or tool lookup:
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
createAgentGateway({
|
|
137
|
+
io,
|
|
138
|
+
registry: false,
|
|
139
|
+
agents: { assistant: agent },
|
|
140
|
+
authMiddleware: verifySocketCredentials, // host function populating socket.data
|
|
141
|
+
security: {
|
|
142
|
+
mode: "authenticated",
|
|
143
|
+
resolveIdentity: (verifiedState) => identityFromVerifiedState(verifiedState),
|
|
144
|
+
authorizeResource: ({ identity, operation, resource }) =>
|
|
145
|
+
authorizeSocketResource(identity, operation, resource),
|
|
146
|
+
},
|
|
147
|
+
maxConcurrentRuns: 4,
|
|
148
|
+
maxOutputBytes: 256 * 1024,
|
|
149
|
+
textStream: { maxFrameBytes: 256 * 1024, maxBufferedBytes: 256 * 1024, writeTimeoutMs: 10_000 },
|
|
150
|
+
});
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
`authorizeResource` must return exactly `true` to allow a resource. `execute` checks the named Agent, Team or Workflow. `session:create` must atomically bind the server-generated opaque session ID to the verified actor/tenant before returning; `session:use` must reject unknown, ownerless or other-tenant IDs. ID possession conveys no authority. Discovery calls `discover` separately for each named Agent, Team, Workflow or tool and omits denied entries. `run:cancel` applies after the gateway checks that the run belongs to this socket and its current verified actor. Never derive this policy from a client room or client identity claim.
|
|
154
|
+
|
|
155
|
+
Authenticated run payloads reject `userId`, `tenantId`, `runId`, `room` and `apiKey`. Handshake keys are not forwarded to providers in authenticated mode. Credentials come from host-configured runtime/provider objects. Client `sessionId` is only an ownership-checked reference. Local mode retains per-run API keys; new sessions are generated rather than using socket IDs.
|
|
156
|
+
|
|
157
|
+
Existing `agent.run`, `team.run`, `agent.chunk`, `agent.tool.call`, `agent.tool.done`, `agent.done` and `agent.error` names remain. `workflow.run` is available for workflows supplied through `serve` or the registry. Every admitted execution receives a generated `runId`; run events include `runId` and, after ownership binding, `sessionId`. The additive `agent.started` event supplies both IDs before runtime work starts. Concurrent clients must correlate events by `runId`. Send `run.cancel` with `{ runId }`; its acknowledgement is `cancellation_requested`, and an error terminal is emitted only after runtime/iterator cleanup settles.
|
|
158
|
+
|
|
159
|
+
Ordinary text HTTP and socket runs are connection-owned. Disconnect aborts their signal, initiates iterator return, and prevents late results. Agent/Team SSE uses one shared writer, waits for Node drain before pulling the next chunk, bounds individual encoded frames and queued bytes (256 KiB each by default), and applies a 10-second drain deadline. Socket output is serialized per connection, with the same configurable bounds and Engine.IO transport readiness; final collected Agent text has its own byte cap. Slow or oversized output cancels production; if a bounded terminal cannot be delivered, the connection closes. Configure the Socket.IO server's `maxHttpBufferSize`, HTTP body limits and deployment connection/time limits separately.
|
|
160
|
+
|
|
161
|
+
Cancellation is cooperative: arbitrary host callbacks cannot be force-killed, and disconnect does not undo effects. Cleanup promises are observed; no terminal success is published while owned work is unresolved. Durable task watchers retain their separate persisted lifetime. The in-memory `SSEEventLog` only provides process-local replay and does not persist execution; multiline strings are encoded as separate SSE data lines and event names reject line injection.
|
|
162
|
+
|
|
163
|
+
Multipart uploads bound file count/size plus text field count/size (`maxFields: 32`, `maxFieldSize: 64 KiB` defaults). The selected patched Multer peer is required even when only local fixtures are used; transport limits do not repair a vulnerable installed parser. Aborted and malformed upload tests use small local requests and assert completion, bounded limits and released file buffers.
|
|
164
|
+
|
|
165
|
+
### Voice gateway acknowledgement migration
|
|
166
|
+
|
|
167
|
+
Voice gateways now reserve pending connections, cancel disconnected setup, and bound queued output. Auth middleware establishes identity in `socket.data.auth`; client user/session/key overrides are ignored when authentication is enabled. The client must acknowledge `voice.audio` sequence numbers through `voice.playback.ack`, clear playback on `voice.clear`, and send `voice.playback.complete` only after a generation has actually played. Defaults are 256 KiB per frame, 1 MiB pending output, and a 10-second acknowledgement deadline. Missing acknowledgements terminate the session rather than growing buffers. See the [voice guide](../core/src/voice/README.md) for the event contract, format negotiation and playback-confirmed history.
|
|
168
|
+
|
|
169
|
+
## A2A 1.0 and legacy migration
|
|
170
|
+
|
|
171
|
+
Install the optional `@a2a-js/sdk` peer (tested with 1.3.0). `createA2AV1Server` uses A2A1.0 JSON-RPC and `/.well-known/agent-card.json`; `A2AV1Client` is exported by core. The older `createA2AServer` / `A2ARemoteAgent` implementation remains available. Use `createA2AServer` for its server export; the redundant server alias has been removed. The client also has the explicit `A2ALegacyRemoteAgent` name. Mount the legacy endpoint separately during migration.
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
import { createA2AV1Server } from "@agentium/transport";
|
|
175
|
+
|
|
176
|
+
await createA2AV1Server(app, {
|
|
177
|
+
agents: { assistant },
|
|
178
|
+
url: "https://agents.example/rpc",
|
|
179
|
+
audience: "agentium-service",
|
|
180
|
+
authenticate: async (request, audience) => {
|
|
181
|
+
// Host verifier validates signature, issuer, expiry and this audience.
|
|
182
|
+
const claims = await verifyAccessToken(request.headers.authorization, audience);
|
|
183
|
+
return claims ? { tenantId: claims.tenantId, userId: claims.subject } : null;
|
|
184
|
+
},
|
|
185
|
+
maxTasks: 10_000,
|
|
186
|
+
maxHistoryMessages: 128,
|
|
187
|
+
});
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Verified tenant and actor own tasks. Body tenant overrides cannot change that identity. Text, structured JSON and PNG/JPEG/WebP raw bytes or HTTP(S) image references are accepted. Inline image URLs should use the raw-byte part instead; local paths and other URL schemes are rejected. The host remains responsible for remote media access policy in its model adapter. A structured Agent result becomes a typed artifact. `completionState` maps domain-specific results to input-required or authentication-required interruptions.
|
|
191
|
+
|
|
192
|
+
Cancellation waits for owned Agent work to settle before reporting canceled; late success cannot overwrite it. A non-cooperative callback may delay acknowledgment. Capacity is enforced before task admission and in the backing store, with bounded history and one active writer per identity/session. Exhaustion rejects new work; retention is process-local and is reset on restart, with no durable recovery claim.
|
|
193
|
+
|
|
194
|
+
The client restricts credential-bearing discovery/requests to the configured origin, rejects redirects and supports per-call abort while sharing discovery. Paid providers are not required for the protocol conformance tests. Legacy clients propagate cancellation and close SSE readers on early exit; legacy streaming servers abort work on disconnect, bound outgoing buffering, and cap process-local tasks with `maxTasks`. Failed Agent outputs stay failed. Legacy authentication and task-owner isolation remain host middleware responsibilities; use the 1.0 adapter for built-in verified ownership.
|
|
195
|
+
|
|
196
|
+
## Durable task control and event replay
|
|
197
|
+
|
|
198
|
+
`createDurableTaskRouter({supervisor, records, authenticate, authorize, wake})` serves already-admitted durable tasks. Mount it under an application-owned prefix. The supervisor and record service must share the same `JournaledDurableTaskStore` instance. Host authentication supplies tenant/actor identity, and authorization rechecks current grants on every request. These routes return 404 for inaccessible tasks and keep inputs, action arguments, internal failure text and blob keys private.
|
|
199
|
+
|
|
200
|
+
- `GET /:taskId` returns task ID, state, revision and update timestamp.
|
|
201
|
+
- `POST /:taskId/cancel` persists cancellation, then invokes the host wake callback. Its 202 response reports the current state and `deliveryPending` if delivery failed. Retry wake through host recovery; cancellation is acknowledged only after reconciliation/settlement.
|
|
202
|
+
- `GET /:taskId/events` returns one bounded SSE replay batch and closes. Reconnect with `Last-Event-ID`; malformed cursors return 400, retention/future-cursor gaps return 409 with retained bounds. Authentication and policy are checked again on reconnect. Event data is intended for the owning actor; apply any required content redaction before appending it.
|
|
203
|
+
|
|
204
|
+
The router is an Agentium control API, separate from the named A2A/MCP wire adapters. It does not claim that an existing process-local protocol server becomes restart-safe when mounted beside it.
|
|
205
|
+
|
|
206
|
+
## Durable A2A and MCP Tasks bridges
|
|
207
|
+
|
|
208
|
+
`createDurableA2AV1Server` and `createDurableMCPTaskHandler` are opt-in adapters over the same durable supervisor. They do not use the ordinary A2A server's process-local task store. Install the optional peers `@a2a-js/sdk` (tested at **1.3.0**) and/or `@modelcontextprotocol/server` (tested at **2.3.0**). Construction dynamically loads only the selected SDK; importing the package does not connect to a database or protocol server.
|
|
209
|
+
|
|
210
|
+
Both adapters require a `DurableProtocolHost`: `supervisor`, `admit`, `authorize`, and `wake`. Authentication additionally verifies credentials for an explicit audience and returns `{tenantId, actorId}`. Every task lookup checks both fields and current host policy. `authorize` receives `read`, `cancel`, `input`, or `wake`; missing callbacks fail construction. Protocol metadata never supplies identity, policy revisions, grants, manifests, or driver registrations.
|
|
211
|
+
|
|
212
|
+
```ts
|
|
213
|
+
import { DurableActionLedger } from "@agentium/core";
|
|
214
|
+
import {
|
|
215
|
+
createDurableA2AV1Server,
|
|
216
|
+
createDurableMCPTaskHandler,
|
|
217
|
+
type DurableProtocolHost,
|
|
218
|
+
} from "@agentium/transport";
|
|
219
|
+
|
|
220
|
+
const host: DurableProtocolHost = {
|
|
221
|
+
supervisor,
|
|
222
|
+
async admit(identity, payload) {
|
|
223
|
+
// Application service: validate current policy, select registered driver,
|
|
224
|
+
// bind identity/manifest/input/budget/grant refs, and persist atomically.
|
|
225
|
+
// For retries, deduplicate A2A messageId and any application idempotency key.
|
|
226
|
+
return admission.persist(identity, payload);
|
|
227
|
+
},
|
|
228
|
+
authorize: (identity, task, operation) => policy.authorize(identity, task, operation),
|
|
229
|
+
wake: (key) => durableQueue.wake(key),
|
|
230
|
+
async respond(identity, task, response) {
|
|
231
|
+
// Your human-consent service must reject automated/model-originated approval.
|
|
232
|
+
await consent.verify(identity, task, response);
|
|
233
|
+
await DurableActionLedger.decide(supervisor.store,
|
|
234
|
+
{ tenantId: identity.tenantId, taskId: task.id },
|
|
235
|
+
{ ...response, actorId: identity.actorId });
|
|
236
|
+
},
|
|
237
|
+
// Only public text/JSON leaves the host. Resolve artifact references with
|
|
238
|
+
// DurableRunRecords and the same verified identity before projecting output.
|
|
239
|
+
output: (identity, task) => publicResults.read(identity, task),
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
app.use(await createDurableA2AV1Server({
|
|
243
|
+
...host,
|
|
244
|
+
name: "assistant",
|
|
245
|
+
url: "https://agents.example/rpc",
|
|
246
|
+
audience: "agentium-service",
|
|
247
|
+
authenticate: (request, audience) => auth.verify(request.headers.authorization, audience),
|
|
248
|
+
}));
|
|
249
|
+
|
|
250
|
+
const mcp = await createDurableMCPTaskHandler({
|
|
251
|
+
...host,
|
|
252
|
+
name: "assistant",
|
|
253
|
+
audience: "agentium-service",
|
|
254
|
+
authenticate: (request, audience) => auth.verify(request.headers.get("authorization"), audience),
|
|
255
|
+
tools: [{ name: "research", inputSchema: {
|
|
256
|
+
type: "object", properties: { query: { type: "string" } },
|
|
257
|
+
required: ["query"], additionalProperties: false,
|
|
258
|
+
} }],
|
|
259
|
+
});
|
|
260
|
+
// Mount mcp.fetch(request) using your runtime's web-standard Request/Response adapter.
|
|
261
|
+
// On shutdown: await mcp.close().
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
`admission`, `policy`, `consent`, `auth`, `publicResults`, and `durableQueue` above are host services, not implicit Agentium globals. Admission must complete persistence before returning `{tenantId, taskId}`. The bridge verifies that record's owner before responding and separately authorizes wake delivery. A failed queue delivery does not erase the admitted task, approval decision, or cancellation intent; the host must retry delivery. For a Mongo-backed deployment use the durable store's majority/CAS adapter, not a generic `StorageDriver`. In-memory stores keep their non-durable capability flag.
|
|
265
|
+
|
|
266
|
+
A2A supports **1.0 JSON-RPC `SendMessage`, `GetTask`, and `CancelTask`** with text/JSON input and projected text/JSON artifacts. The card advertises `streaming: false` and `pushNotifications: false`; streaming, subscriptions, task listing, extended cards, and push configuration are rejected. New context IDs come from admission. Existing-task input is one JSON part `{approvalId, preparedHash, approved}`; it must match an outstanding durable approval. Default blocking `SendMessage` waits for a terminal/interrupted state. `configuration.returnImmediately: true` returns the admitted task immediately; the default 30-second wait limit raises a protocol error containing the task ID, leaving the task available through `GetTask`. `CancelTask` reports canceled only after supervisor acknowledgement; a timeout reports pending cancellation as an error, and `GetTask` remains working with `metadata.cancellationRequested` until acknowledged.
|
|
267
|
+
|
|
268
|
+
MCP supports **2026-07-28** HTTP framing and the [`io.modelcontextprotocol/tasks` extension](https://modelcontextprotocol.github.io/ext-tasks/specification/2026-07-28/tasks.html). The official SDK handles discovery/tool listing and schema validation; this adapter implements `tools/call`, `tasks/get`, `tasks/update`, and `tasks/cancel`. Each modern request must have the validated protocol envelope, matching protocol/method/name headers, and the Tasks capability. A missing capability, unsupported revision, unsupported method, or invalid argument is rejected before admission. Polling is supported; task notifications/subscriptions, task listing, legacy task shapes, and legacy HTTP sessions are not. Named ordinary/legacy adapters remain separate and unchanged.
|
|
269
|
+
|
|
270
|
+
A pending human decision maps to `input_required` with a stable approval ID and prepared digest. MCP input responses use `{[approvalId]: {action: "accept", content: {approved, preparedHash}}}`; decline/cancel deny the approval. Already answered or unknown keys are ignored, and `respond` must be installed explicitly. Approved/denied input awaiting worker pickup returns working. MCP cancellation acknowledges persisted intent with `resultType: "complete"`; polling remains working until cancellation is acknowledged. Completed projections may set `isError: true` for a domain/tool error while remaining protocol-completed. Internal execution failures expose only a generic protocol error; stored failure text stays private.
|
|
271
|
+
|
|
272
|
+
Request and projected task payloads are bounded to 64 KiB, with depth/node limits. A2A messages accept at most 32 parts; MCP exposes at most 128 distinct tools. Files, raw media, arbitrary artifact URLs, internal inputs/action arguments, and blob keys are never automatically serialized. Larger results require a host-owned retrieval API. The host supplies request rate/concurrency limits and task retention; MCP returns `ttlMs: null` because this bridge does not own expiration. Durable SSE event replay is provided by `createDurableTaskRouter`, separately from these polling protocol endpoints.
|
|
273
|
+
|
|
274
|
+
For MCP client recovery, `MCPV2ToolProvider.exportTaskReference(handle, ctx)` produces a credential-free reference for host-owned storage. After client restart, `resumeTask(reference, ctx)` verifies the provider/endpoint and tenant/user/session identity, fetches the remote task under current credentials, and returns a fresh local handle for the new run. HTTP Tasks and explicit tenant/user identity are required. Do not expose references or approval controls as ordinary model tools.
|
|
275
|
+
|
|
276
|
+
Local HTTP fixtures exercise the actual pinned SDKs, ownership, negotiation, approval digest binding, cancellation, projected artifacts, and compatibility with the existing adapters. The opt-in `AGENTIUM_DURABLE_MONGO_TEST=1` fixture creates a random isolated database, closes the original store, recreates protocol servers over a new store client, and verifies approval/completion/cancellation reads. These are scoped interoperability checks for the implemented methods, not full protocol certification, external deployment approval, or exactly-once execution guarantees.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"a2a-server.d.ts","sourceRoot":"","sources":["../../src/a2a/a2a-server.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"a2a-server.d.ts","sourceRoot":"","sources":["../../src/a2a/a2a-server.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAyGnD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAyCtE"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { DurableReader } from "@agentium/core";
|
|
2
|
+
import type { Request, Router } from "express";
|
|
3
|
+
import { type DurableProtocolHost } from "../durable/protocol-host.js";
|
|
4
|
+
export interface DurableA2AV1ServerOptions extends DurableProtocolHost {
|
|
5
|
+
name: string;
|
|
6
|
+
/** Absolute public JSON-RPC URL; mount the returned router at its origin. */
|
|
7
|
+
url: string;
|
|
8
|
+
audience: string;
|
|
9
|
+
authenticate(request: Request, audience: string): Promise<DurableReader | null>;
|
|
10
|
+
cardPath?: string;
|
|
11
|
+
/** Blocking SendMessage waits only this long; timeout does not cancel admitted work. */
|
|
12
|
+
waitTimeoutMs?: number;
|
|
13
|
+
pollIntervalMs?: number;
|
|
14
|
+
}
|
|
15
|
+
/** Optional A2A 1.0 JSON-RPC bridge. Polling only; all state remains in the durable store. */
|
|
16
|
+
export declare function createDurableA2AV1Server(options: DurableA2AV1ServerOptions): Promise<Router>;
|
|
17
|
+
//# sourceMappingURL=durable-v1-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"durable-v1-server.d.ts","sourceRoot":"","sources":["../../src/a2a/durable-v1-server.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAqB,MAAM,gBAAgB,CAAC;AACvE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAIL,KAAK,mBAAmB,EAUzB,MAAM,6BAA6B,CAAC;AAErC,MAAM,WAAW,yBAA0B,SAAQ,mBAAmB;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,6EAA6E;IAC7E,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wFAAwF;IACxF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,8FAA8F;AAC9F,wBAAsB,wBAAwB,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,MAAM,CAAC,CAmSlG"}
|
package/dist/a2a/types.d.ts
CHANGED
package/dist/a2a/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/a2a/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAE5C,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE;QACT,YAAY,EAAE,MAAM,CAAC;QACrB,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC;IACF,OAAO,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/a2a/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAE5C,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE;QACT,YAAY,EAAE,MAAM,CAAC;QACrB,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC;IACF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { A2AV1Card, Agent, RunOutput } from "@agentium/core";
|
|
2
|
+
import type { Express, Request } from "express";
|
|
3
|
+
export interface A2AV1Identity {
|
|
4
|
+
tenantId: string;
|
|
5
|
+
userId: string;
|
|
6
|
+
}
|
|
7
|
+
export interface A2AV1ServerOptions {
|
|
8
|
+
agents: Record<string, Pick<Agent, "name" | "run">>;
|
|
9
|
+
/** Absolute URL of this JSON-RPC endpoint. */
|
|
10
|
+
url: string;
|
|
11
|
+
basePath?: string;
|
|
12
|
+
cardPath?: string;
|
|
13
|
+
/** Passed to the host verifier; the verifier must validate token audience. */
|
|
14
|
+
audience: string;
|
|
15
|
+
authenticate: (request: Request, audience: string) => Promise<A2AV1Identity | null>;
|
|
16
|
+
maxTasks?: number;
|
|
17
|
+
/** Local history retention and follow-up admission bound; default 128. */
|
|
18
|
+
maxHistoryMessages?: number;
|
|
19
|
+
/** Domain-specific interrupted results remain distinguishable from success. */
|
|
20
|
+
completionState?: (output: RunOutput) => "TASK_STATE_COMPLETED" | "TASK_STATE_INPUT_REQUIRED" | "TASK_STATE_AUTH_REQUIRED" | "TASK_STATE_FAILED";
|
|
21
|
+
}
|
|
22
|
+
/** A2A 1.0 JSON-RPC using the optional official SDK. Local task state is
|
|
23
|
+
* process-local and ownership-scoped; this adapter does not promise recovery. */
|
|
24
|
+
export declare function createA2AV1Server(app: Express, options: A2AV1ServerOptions): Promise<{
|
|
25
|
+
card: A2AV1Card;
|
|
26
|
+
}>;
|
|
27
|
+
//# sourceMappingURL=v1-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v1-server.d.ts","sourceRoot":"","sources":["../../src/a2a/v1-server.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,KAAK,EAAkB,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAClF,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEhD,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AACD,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC;IACpD,8CAA8C;IAC9C,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8EAA8E;IAC9E,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IACpF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,+EAA+E;IAC/E,eAAe,CAAC,EAAE,CAChB,MAAM,EAAE,SAAS,KACd,sBAAsB,GAAG,2BAA2B,GAAG,0BAA0B,GAAG,mBAAmB,CAAC;CAC9G;AAED;iFACiF;AACjF,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC,CA4R/G"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { DurableJSON, DurableReader, DurableTaskKey, DurableTaskRecord, DurableTaskSupervisor } from "@agentium/core";
|
|
2
|
+
export type DurableProtocolPart = {
|
|
3
|
+
text: string;
|
|
4
|
+
} | {
|
|
5
|
+
data: DurableJSON;
|
|
6
|
+
};
|
|
7
|
+
export type DurableProtocolAdmission = {
|
|
8
|
+
protocol: "a2a-1.0";
|
|
9
|
+
name: string;
|
|
10
|
+
messageId: string;
|
|
11
|
+
parts: DurableProtocolPart[];
|
|
12
|
+
} | {
|
|
13
|
+
protocol: "mcp-2026-07-28";
|
|
14
|
+
name: string;
|
|
15
|
+
arguments: Record<string, DurableJSON>;
|
|
16
|
+
};
|
|
17
|
+
export interface DurableProtocolApprovalResponse {
|
|
18
|
+
approvalId: string;
|
|
19
|
+
preparedHash: string;
|
|
20
|
+
approved: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface DurableProtocolOutput {
|
|
23
|
+
text?: string;
|
|
24
|
+
data?: DurableJSON;
|
|
25
|
+
/** A completed tool result can contain a domain error without becoming a protocol failure. */
|
|
26
|
+
isError?: boolean;
|
|
27
|
+
}
|
|
28
|
+
/** Trusted admission boundary; protocol payloads cannot select identity, policy or grants. */
|
|
29
|
+
export interface DurableProtocolHost {
|
|
30
|
+
supervisor: DurableTaskSupervisor;
|
|
31
|
+
/** Persist an owned task before returning. Mint/validate immutable refs and deduplicate message IDs here. */
|
|
32
|
+
admit(identity: DurableReader, input: DurableProtocolAdmission): Promise<DurableTaskKey>;
|
|
33
|
+
authorize(identity: DurableReader, task: Readonly<DurableTaskRecord>, operation: "read" | "cancel" | "input" | "wake"): Promise<boolean>;
|
|
34
|
+
/** Re-deliver a persisted task to its registered driver. Failure leaves it available for host recovery. */
|
|
35
|
+
wake(key: DurableTaskKey): Promise<unknown>;
|
|
36
|
+
/** Explicit trusted human-consent channel. Persist via DurableActionLedger.decide; never trust tool text. */
|
|
37
|
+
respond?(identity: DurableReader, task: Readonly<DurableTaskRecord>, response: DurableProtocolApprovalResponse): Promise<void>;
|
|
38
|
+
/** Return only authorized public output. Resolve artifacts through DurableRunRecords; no automatic URLs. */
|
|
39
|
+
output?(identity: DurableReader, task: Readonly<DurableTaskRecord>): Promise<DurableProtocolOutput>;
|
|
40
|
+
}
|
|
41
|
+
export declare class DurableProtocolError extends Error {
|
|
42
|
+
readonly code: "invalid" | "not-found" | "unsupported";
|
|
43
|
+
constructor(code: "invalid" | "not-found" | "unsupported", message: string);
|
|
44
|
+
}
|
|
45
|
+
export declare function protocolId(value: unknown): string;
|
|
46
|
+
/** Bounds both recursion and encoded size before host callbacks. Rejects unsafe/non-JSON values. */
|
|
47
|
+
export declare function protocolJSON(value: unknown, maxBytes?: number): DurableJSON;
|
|
48
|
+
export declare function protocolObject(value: unknown): Record<string, DurableJSON>;
|
|
49
|
+
export declare function assertProtocolHost(host: DurableProtocolHost): void;
|
|
50
|
+
export declare function ownedTask(host: DurableProtocolHost, identity: DurableReader, id: string, operation?: Parameters<DurableProtocolHost["authorize"]>[2]): Promise<DurableTaskRecord>;
|
|
51
|
+
export declare function wakeTask(host: DurableProtocolHost, identity: DurableReader, id: string): Promise<void>;
|
|
52
|
+
export declare function admitTask(host: DurableProtocolHost, identity: DurableReader, input: DurableProtocolAdmission): Promise<DurableTaskRecord>;
|
|
53
|
+
export declare function pendingApprovals(task: DurableTaskRecord, identity: DurableReader): import("@agentium/core").DurableApproval[];
|
|
54
|
+
export declare function respondToApproval(host: DurableProtocolHost, identity: DurableReader, taskId: string, response: DurableProtocolApprovalResponse): Promise<void>;
|
|
55
|
+
export declare function publicOutput(host: DurableProtocolHost, identity: DurableReader, task: DurableTaskRecord): Promise<DurableProtocolOutput>;
|
|
56
|
+
//# sourceMappingURL=protocol-host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol-host.d.ts","sourceRoot":"","sources":["../../src/durable/protocol-host.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin-router.d.ts","sourceRoot":"","sources":["../../src/express/admin-router.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"admin-router.d.ts","sourceRoot":"","sources":["../../src/express/admin-router.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAI9C,MAAM,WAAW,kBAAkB;IACjC,oEAAoE;IACpE,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB;;;;OAIG;IACH,UAAU,CAAC,EAAE,GAAG,EAAE,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,CAAC,EAAE,kBAAkB;;;EA6J1D"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type DurableReader, type DurableRunRecords, type DurableTaskKey, type DurableTaskRecord, type DurableTaskSupervisor } from "@agentium/core";
|
|
2
|
+
import type { Request, Router } from "express";
|
|
3
|
+
export interface DurableTaskRouterOptions {
|
|
4
|
+
supervisor: DurableTaskSupervisor;
|
|
5
|
+
records: DurableRunRecords;
|
|
6
|
+
/** Verify credentials/audience. Returned identity must never come from body/query claims. */
|
|
7
|
+
authenticate: (request: Request) => Promise<DurableReader | null>;
|
|
8
|
+
/** Recheck current host policy/grants on every request, including event reconnections. */
|
|
9
|
+
authorize: (identity: DurableReader, task: Readonly<DurableTaskRecord>, operation: "read" | "cancel") => Promise<boolean>;
|
|
10
|
+
/** Re-deliver cancellation to a worker. Cancellation remains persisted if Redis is unavailable. */
|
|
11
|
+
wake: (key: DurableTaskKey) => Promise<unknown>;
|
|
12
|
+
}
|
|
13
|
+
/** Authenticated control and bounded replay for tasks already admitted by the host.
|
|
14
|
+
* Event responses close after the retained batch; reconnect with Last-Event-ID.
|
|
15
|
+
* This is an Agentium endpoint, not an A2A or MCP wire-protocol endpoint.
|
|
16
|
+
*/
|
|
17
|
+
export declare function createDurableTaskRouter(options: DurableTaskRouterOptions): Router;
|
|
18
|
+
//# sourceMappingURL=durable-router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"durable-router.d.ts","sourceRoot":"","sources":["../../src/express/durable-router.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC3B,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,OAAO,EAAY,MAAM,EAAE,MAAM,SAAS,CAAC;AAEzD,MAAM,WAAW,wBAAwB;IACvC,UAAU,EAAE,qBAAqB,CAAC;IAClC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,6FAA6F;IAC7F,YAAY,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IAClE,0FAA0F;IAC1F,SAAS,EAAE,CACT,QAAQ,EAAE,aAAa,EACvB,IAAI,EAAE,QAAQ,CAAC,iBAAiB,CAAC,EACjC,SAAS,EAAE,MAAM,GAAG,QAAQ,KACzB,OAAO,CAAC,OAAO,CAAC,CAAC;IACtB,mGAAmG;IACnG,IAAI,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACjD;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,wBAAwB,GAAG,MAAM,CA4FjF"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
export interface FileUploadOptions {
|
|
2
2
|
maxFileSize?: number;
|
|
3
3
|
maxFiles?: number;
|
|
4
|
+
maxFields?: number;
|
|
5
|
+
maxFieldSize?: number;
|
|
4
6
|
allowedMimeTypes?: string[];
|
|
5
7
|
}
|
|
6
|
-
export declare function createFileUploadMiddleware(opts?: FileUploadOptions): any;
|
|
8
|
+
export declare function createFileUploadMiddleware(opts?: FileUploadOptions): (req: any, res: any, next: (error?: unknown) => void) => void;
|
|
7
9
|
export declare function filesToContentParts(files: any[]): any[];
|
|
8
10
|
export declare function buildMultiModalInput(body: any, files?: any[]): string | any[];
|
|
9
11
|
//# sourceMappingURL=file-upload.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-upload.d.ts","sourceRoot":"","sources":["../../src/express/file-upload.ts"],"names":[],"mappings":"AAwBA,MAAM,WAAW,iBAAiB;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,wBAAgB,0BAA0B,CAAC,IAAI,GAAE,iBAAsB,
|
|
1
|
+
{"version":3,"file":"file-upload.d.ts","sourceRoot":"","sources":["../../src/express/file-upload.ts"],"names":[],"mappings":"AAwBA,MAAM,WAAW,iBAAiB;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,wBAAgB,0BAA0B,CAAC,IAAI,GAAE,iBAAsB,IAgC7D,KAAK,GAAG,EAAE,KAAK,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,IAAI,UAU5D;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,GAAG,EAAE,CAcvD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,EAAE,GAAG,EAAE,GAAG,MAAM,GAAG,GAAG,EAAE,CAY7E"}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
export interface RbacConfig {
|
|
2
2
|
scopeField?: string;
|
|
3
|
+
/** Override an exact route pattern. Empty scopes explicitly permit authenticated access. */
|
|
3
4
|
defaultScopes?: Record<string, string[]>;
|
|
4
5
|
agentScopes?: Record<string, string[]>;
|
|
6
|
+
/** Explicit routes accessible without authentication. Use only for intentionally public endpoints. */
|
|
7
|
+
publicRoutes?: string[];
|
|
5
8
|
}
|
|
9
|
+
export declare function routeMatches(actual: string, pattern: string): boolean;
|
|
6
10
|
export declare function createRbacMiddleware(config?: RbacConfig): (req: any, res: any, next: any) => any;
|
|
7
11
|
//# sourceMappingURL=rbac-middleware.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rbac-middleware.d.ts","sourceRoot":"","sources":["../../src/express/rbac-middleware.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"rbac-middleware.d.ts","sourceRoot":"","sources":["../../src/express/rbac-middleware.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4FAA4F;IAC5F,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACvC,sGAAsG;IACtG,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAmCD,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAOrE;AAED,wBAAgB,oBAAoB,CAAC,MAAM,GAAE,UAAe,IAGlD,KAAK,GAAG,EAAE,KAAK,GAAG,EAAE,MAAM,GAAG,SAyBtC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router-factory.d.ts","sourceRoot":"","sources":["../../src/express/router-factory.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"router-factory.d.ts","sourceRoot":"","sources":["../../src/express/router-factory.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAyC,aAAa,EAAE,MAAM,YAAY,CAAC;AA2GvF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,aAAa,OAksBpD"}
|
package/dist/express/types.d.ts
CHANGED
|
@@ -22,7 +22,39 @@ export interface SwaggerOptions {
|
|
|
22
22
|
/** Path to serve the raw OpenAPI JSON spec. Default: "/docs/spec.json" */
|
|
23
23
|
specPath?: string;
|
|
24
24
|
}
|
|
25
|
+
/** Identity derived only from credentials verified by host middleware or JWT. */
|
|
26
|
+
export interface HostedIdentity {
|
|
27
|
+
userId: string;
|
|
28
|
+
tenantId?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface HostedResourceRequest {
|
|
31
|
+
identity: Readonly<HostedIdentity>;
|
|
32
|
+
operation: string;
|
|
33
|
+
resource: {
|
|
34
|
+
kind: "session" | "run" | "approval" | "checkpoint" | "correction" | "schedule" | "admin";
|
|
35
|
+
id?: string;
|
|
36
|
+
agentName?: string;
|
|
37
|
+
/** Requested correction visibility, for host policy evaluation. */
|
|
38
|
+
scope?: string;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export type HostedSecurityOptions = {
|
|
42
|
+
mode: "local";
|
|
43
|
+
} | {
|
|
44
|
+
mode: "authenticated";
|
|
45
|
+
/** Receives req.user after trusted middleware/JWT verification; never the request body. */
|
|
46
|
+
resolveIdentity: (verifiedClaims: unknown) => HostedIdentity | null | Promise<HostedIdentity | null>;
|
|
47
|
+
/**
|
|
48
|
+
* Check authoritative owner records. Unknown/ownerless records MUST return false.
|
|
49
|
+
* session:create MUST atomically bind this new opaque ID to identity before returning true.
|
|
50
|
+
* Collection operations grant access to the entire collection; deny when that is inappropriate.
|
|
51
|
+
* Scopes (including admin:*) never bypass this authorization.
|
|
52
|
+
*/
|
|
53
|
+
authorizeResource: (request: HostedResourceRequest) => boolean | Promise<boolean>;
|
|
54
|
+
};
|
|
25
55
|
export interface RouterOptions {
|
|
56
|
+
/** Required explicit boundary. JWT/RBAC require authenticated mode and both host hooks. */
|
|
57
|
+
security: HostedSecurityOptions;
|
|
26
58
|
/**
|
|
27
59
|
* Use a Registry for live auto-discovery. The router creates dynamic routes
|
|
28
60
|
* that resolve agents/teams/workflows at request time — any instance created
|
|
@@ -32,7 +64,7 @@ export interface RouterOptions {
|
|
|
32
64
|
* Pass `false` to disable registry-based routing entirely (use explicit maps only).
|
|
33
65
|
*
|
|
34
66
|
* @example
|
|
35
|
-
* createAgentRouter({ cors: true });
|
|
67
|
+
* createAgentRouter({ security: { mode: "local" }, cors: true });
|
|
36
68
|
* new Agent({ name: "bot", model: openai("gpt-4o") }); // immediately routable
|
|
37
69
|
*/
|
|
38
70
|
registry?: Registry | false;
|
|
@@ -47,6 +79,8 @@ export interface RouterOptions {
|
|
|
47
79
|
middleware?: any[];
|
|
48
80
|
/** Swagger / OpenAPI configuration */
|
|
49
81
|
swagger?: SwaggerOptions;
|
|
82
|
+
/** Connection-owned text response limits. */
|
|
83
|
+
textStream?: import("../text-stream.js").TextStreamLimits;
|
|
50
84
|
/** File upload configuration for multi-modal inputs */
|
|
51
85
|
fileUpload?: boolean | FileUploadOptions;
|
|
52
86
|
/** CORS configuration. Pass true or '*' for permissive, a string for a single origin, or an array for multiple origins. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/express/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACjH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,WAAW,cAAc;IAC7B,iDAAiD;IACjD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yBAAyB;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+BAA+B;IAC/B,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACvD,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;IAC5B;;;OAGG;IACH,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,GAAG,aAAa,CAAC,CAAC;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1C,UAAU,CAAC,EAAE,GAAG,EAAE,CAAC;IACnB,sCAAsC;IACtC,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,uDAAuD;IACvD,UAAU,CAAC,EAAE,OAAO,GAAG,iBAAiB,CAAC;IACzC,2HAA2H;IAC3H,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC;IACnC,oGAAoG;IACpG,SAAS,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;IAC1D,yFAAyF;IACzF,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,yFAAyF;IACzF,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;IACrB;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,GAAG;QAAE,UAAU,CAAC,EAAE,UAAU,CAAC;QAAC,UAAU,CAAC,EAAE,GAAG,EAAE,CAAA;KAAE,CAAC;IAClE;;;OAGG;IACH,SAAS,CAAC,EAAE,GAAG,CAAC;IAChB;;OAEG;IACH,eAAe,CAAC,EAAE,GAAG,CAAC;IACtB;;;OAGG;IACH,GAAG,CAAC,EAAE,OAAO,qBAAqB,EAAE,SAAS,CAAC;IAC9C;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,sBAAsB,EAAE,UAAU,CAAC;CAClD"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/express/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACjH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,WAAW,cAAc;IAC7B,iDAAiD;IACjD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yBAAyB;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+BAA+B;IAC/B,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACvD,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,iFAAiF;AACjF,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE;QACR,IAAI,EAAE,SAAS,GAAG,KAAK,GAAG,UAAU,GAAG,YAAY,GAAG,YAAY,GAAG,UAAU,GAAG,OAAO,CAAC;QAC1F,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,mEAAmE;QACnE,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,MAAM,MAAM,qBAAqB,GAC7B;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IACE,IAAI,EAAE,eAAe,CAAC;IACtB,2FAA2F;IAC3F,eAAe,EAAE,CAAC,cAAc,EAAE,OAAO,KAAK,cAAc,GAAG,IAAI,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IACrG;;;;;OAKG;IACH,iBAAiB,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACnF,CAAC;AAEN,MAAM,WAAW,aAAa;IAC5B,2FAA2F;IAC3F,QAAQ,EAAE,qBAAqB,CAAC;IAChC;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;IAC5B;;;OAGG;IACH,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,GAAG,aAAa,CAAC,CAAC;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1C,UAAU,CAAC,EAAE,GAAG,EAAE,CAAC;IACnB,sCAAsC;IACtC,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,6CAA6C;IAC7C,UAAU,CAAC,EAAE,OAAO,mBAAmB,EAAE,gBAAgB,CAAC;IAC1D,uDAAuD;IACvD,UAAU,CAAC,EAAE,OAAO,GAAG,iBAAiB,CAAC;IACzC,2HAA2H;IAC3H,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC;IACnC,oGAAoG;IACpG,SAAS,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;IAC1D,yFAAyF;IACzF,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,yFAAyF;IACzF,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;IACrB;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,GAAG;QAAE,UAAU,CAAC,EAAE,UAAU,CAAC;QAAC,UAAU,CAAC,EAAE,GAAG,EAAE,CAAA;KAAE,CAAC;IAClE;;;OAGG;IACH,SAAS,CAAC,EAAE,GAAG,CAAC;IAChB;;OAEG;IACH,eAAe,CAAC,EAAE,GAAG,CAAC;IACtB;;;OAGG;IACH,GAAG,CAAC,EAAE,OAAO,qBAAqB,EAAE,SAAS,CAAC;IAC9C;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,sBAAsB,EAAE,UAAU,CAAC;CAClD"}
|