@agenticprimitives/a2a 0.0.0-alpha.1
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/CLAUDE.md +67 -0
- package/LICENSE +21 -0
- package/README.md +50 -0
- package/dist/agent.d.ts +114 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +191 -0
- package/dist/agent.js.map +1 -0
- package/dist/auth.d.ts +55 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +116 -0
- package/dist/auth.js.map +1 -0
- package/dist/client.d.ts +41 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +43 -0
- package/dist/client.js.map +1 -0
- package/dist/cloudflare/index.d.ts +7 -0
- package/dist/cloudflare/index.d.ts.map +1 -0
- package/dist/cloudflare/index.js +39 -0
- package/dist/cloudflare/index.js.map +1 -0
- package/dist/discovery.d.ts +29 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/discovery.js +22 -0
- package/dist/discovery.js.map +1 -0
- package/dist/grant.d.ts +29 -0
- package/dist/grant.d.ts.map +1 -0
- package/dist/grant.js +29 -0
- package/dist/grant.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/jsonrpc.d.ts +25 -0
- package/dist/jsonrpc.d.ts.map +1 -0
- package/dist/jsonrpc.js +52 -0
- package/dist/jsonrpc.js.map +1 -0
- package/dist/push.d.ts +28 -0
- package/dist/push.d.ts.map +1 -0
- package/dist/push.js +39 -0
- package/dist/push.js.map +1 -0
- package/dist/runtime.d.ts +53 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +154 -0
- package/dist/runtime.js.map +1 -0
- package/dist/skill-handler.d.ts +88 -0
- package/dist/skill-handler.d.ts.map +1 -0
- package/dist/skill-handler.js +32 -0
- package/dist/skill-handler.js.map +1 -0
- package/dist/sse.d.ts +9 -0
- package/dist/sse.d.ts.map +1 -0
- package/dist/sse.js +18 -0
- package/dist/sse.js.map +1 -0
- package/dist/task-store.d.ts +16 -0
- package/dist/task-store.d.ts.map +1 -0
- package/dist/task-store.js +34 -0
- package/dist/task-store.js.map +1 -0
- package/dist/types.d.ts +80 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -0
- package/package.json +65 -0
- package/spec.md +4 -0
package/dist/push.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// Signed push delivery (spec 269 FR-5.2 / SR-5). On a terminal state the assignee SA signs a canonical
|
|
2
|
+
// envelope and POSTs it to the sender-registered webhook; the receiver independently verifies the
|
|
3
|
+
// assignee's signature + dedupes on (taskId, state). Signing + the HTTP POST are INJECTED (the package
|
|
4
|
+
// holds no keys + no transport); the assignee signer MUST be a KMS/session signer (SR-8), never a raw key.
|
|
5
|
+
import { keccak256, encodeAbiParameters, toBytes } from 'viem';
|
|
6
|
+
/** Canonical digest the assignee signs (binds task, state, artifact set, timestamp). */
|
|
7
|
+
export function hashPushPayload(p) {
|
|
8
|
+
return keccak256(encodeAbiParameters([{ type: 'bytes32' }, { type: 'bytes32' }, { type: 'bytes32[]' }, { type: 'uint256' }], [p.taskId, keccak256(toBytes(p.state)), p.artifactIds, BigInt(p.ts)]));
|
|
9
|
+
}
|
|
10
|
+
/** Build + sign + best-effort-POST the terminal push, with bounded retry. Returns whether it was
|
|
11
|
+
* delivered. A no-op (false) when the task has no `pushConfig`. */
|
|
12
|
+
export async function deliverPush(record, sign, send, now, retries = 2) {
|
|
13
|
+
if (!record.pushConfig?.url)
|
|
14
|
+
return false;
|
|
15
|
+
const payload = {
|
|
16
|
+
taskId: record.task.taskId,
|
|
17
|
+
state: record.task.state,
|
|
18
|
+
artifactIds: record.task.artifactIds,
|
|
19
|
+
ts: Math.floor(now / 1000),
|
|
20
|
+
};
|
|
21
|
+
const signature = await sign(hashPushPayload(payload));
|
|
22
|
+
const envelope = { payload, signature, token: record.pushConfig.token };
|
|
23
|
+
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
24
|
+
try {
|
|
25
|
+
await send(record.pushConfig.url, envelope);
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
if (attempt === retries)
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
/** Receiver-side verification: the assignee SA signed this envelope over the recomputed digest. */
|
|
36
|
+
export async function verifyPushEnvelope(envelope, assigneeSA, verify) {
|
|
37
|
+
return verify(assigneeSA, hashPushPayload(envelope.payload), envelope.signature);
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=push.js.map
|
package/dist/push.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push.js","sourceRoot":"","sources":["../src/push.ts"],"names":[],"mappings":"AAAA,uGAAuG;AACvG,kGAAkG;AAClG,uGAAuG;AACvG,2GAA2G;AAC3G,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,OAAO,EAA0B,MAAM,MAAM,CAAC;AAmBvF,wFAAwF;AACxF,MAAM,UAAU,eAAe,CAAC,CAAc;IAC5C,OAAO,SAAS,CACd,mBAAmB,CACjB,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EACtF,CAAC,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CACrE,CACF,CAAC;AACJ,CAAC;AAOD;oEACoE;AACpE,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAkB,EAClB,IAAoB,EACpB,IAAgB,EAChB,GAAW,EACX,OAAO,GAAG,CAAC;IAEX,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG;QAAE,OAAO,KAAK,CAAC;IAC1C,MAAM,OAAO,GAAgB;QAC3B,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM;QAC1B,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK;QACxB,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW;QACpC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC;KAC3B,CAAC;IACF,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;IACvD,MAAM,QAAQ,GAAiB,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IACtF,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC;QACpD,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;YAC5C,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,OAAO,KAAK,OAAO;gBAAE,OAAO,KAAK,CAAC;QACxC,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,mGAAmG;AACnG,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,QAAsB,EACtB,UAAmB,EACnB,MAA2E;IAE3E,OAAO,MAAM,CAAC,UAAU,EAAE,eAAe,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;AACnF,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { type HandoffPolicy } from '@agenticprimitives/fulfillment';
|
|
2
|
+
import type { Address, Hex } from '@agenticprimitives/types';
|
|
3
|
+
import type { Delegation } from '@agenticprimitives/delegation';
|
|
4
|
+
import type { TaskRecord, TaskState, TaskEvent, A2aMessage } from './types.js';
|
|
5
|
+
import { isTerminal } from './types.js';
|
|
6
|
+
import { type SkillContext, type SkillHandler } from './skill-handler.js';
|
|
7
|
+
/** Build a fresh `submitted` task record from a verified inbound message + grant. */
|
|
8
|
+
export declare function newTaskRecord(args: {
|
|
9
|
+
taskId: Hex;
|
|
10
|
+
principal: Address;
|
|
11
|
+
assignee: Address;
|
|
12
|
+
sender: Address;
|
|
13
|
+
skill: string;
|
|
14
|
+
delegation: Delegation;
|
|
15
|
+
inbound: A2aMessage;
|
|
16
|
+
permissionGrantRef: Hex;
|
|
17
|
+
inputHash: Hex;
|
|
18
|
+
now: number;
|
|
19
|
+
deadline?: number;
|
|
20
|
+
maxRetries?: number;
|
|
21
|
+
parentCaseId?: Hex;
|
|
22
|
+
}): TaskRecord;
|
|
23
|
+
export type TransitionResult = {
|
|
24
|
+
ok: true;
|
|
25
|
+
record: TaskRecord;
|
|
26
|
+
event: TaskEvent;
|
|
27
|
+
} | {
|
|
28
|
+
ok: false;
|
|
29
|
+
reason: string;
|
|
30
|
+
};
|
|
31
|
+
/** Apply a state transition, fail-closed via the fulfillment transition table. Bumps `rev` + emits the
|
|
32
|
+
* status event. Does NOT persist — the caller writes the returned record to the TaskStore. */
|
|
33
|
+
export declare function applyTransition(record: TaskRecord, to: TaskState, opts?: {
|
|
34
|
+
now: number;
|
|
35
|
+
error?: string;
|
|
36
|
+
}): TransitionResult;
|
|
37
|
+
/**
|
|
38
|
+
* Dispatch a `submitted` task: reject if the skill is unknown; otherwise move it to `working`, run the
|
|
39
|
+
* handler, and map the outcome to the next state. Returns the final record + the ordered events. The
|
|
40
|
+
* caller (alarm loop) persists the record and fans the events to streams/push. `makeContext` wires the
|
|
41
|
+
* per-task vault / mcp / emitArtifact (W4) — the runtime stays transport-agnostic.
|
|
42
|
+
*/
|
|
43
|
+
export declare function dispatchTask(record: TaskRecord, registry: Map<string, SkillHandler>, makeContext: (record: TaskRecord) => Omit<SkillContext, 'requestAuth' | 'requestHandoff' | 'principal' | 'sender' | 'taskId' | 'skill'> & {
|
|
44
|
+
input: unknown;
|
|
45
|
+
delegation: Delegation;
|
|
46
|
+
}, now: number, opts?: {
|
|
47
|
+
handoffPolicy?: HandoffPolicy;
|
|
48
|
+
}): Promise<{
|
|
49
|
+
record: TaskRecord;
|
|
50
|
+
events: TaskEvent[];
|
|
51
|
+
}>;
|
|
52
|
+
export { isTerminal };
|
|
53
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAKA,OAAO,EAAuC,KAAK,aAAa,EAAE,MAAM,gCAAgC,CAAC;AACzG,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC/E,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAkC,KAAK,YAAY,EAAE,KAAK,YAAY,EAAoB,MAAM,oBAAoB,CAAC;AAE5H,qFAAqF;AACrF,wBAAgB,aAAa,CAAC,IAAI,EAAE;IAClC,MAAM,EAAE,GAAG,CAAC;IACZ,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,UAAU,CAAC;IACvB,OAAO,EAAE,UAAU,CAAC;IACpB,kBAAkB,EAAE,GAAG,CAAC;IACxB,SAAS,EAAE,GAAG,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,GAAG,CAAC;CACpB,GAAG,UAAU,CAuBb;AAED,MAAM,MAAM,gBAAgB,GACxB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,SAAS,CAAA;CAAE,GAClD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAElC;+FAC+F;AAC/F,wBAAgB,eAAe,CAC7B,MAAM,EAAE,UAAU,EAClB,EAAE,EAAE,SAAS,EACb,IAAI,GAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAe,GACjD,gBAAgB,CAalB;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,UAAU,EAClB,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,EACnC,WAAW,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC,YAAY,EAAE,aAAa,GAAG,gBAAgB,GAAG,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,UAAU,CAAA;CAAE,EACpL,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,aAAa,CAAA;CAAE,GACvC,OAAO,CAAC;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,SAAS,EAAE,CAAA;CAAE,CAAC,CAkFtD;AAED,OAAO,EAAE,UAAU,EAAE,CAAC"}
|
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
// The Task runtime (spec 269 §3). Pure lifecycle logic over the fulfillment Task state machine: create a
|
|
2
|
+
// submitted task, validate every transition via canTaskTransition (fail-closed), and dispatch a working
|
|
3
|
+
// task to its skill handler — mapping the handler result (or AuthRequired / unknown-skill / throw) onto
|
|
4
|
+
// the next state. Storage + delivery are the caller's job (the TaskStore port + the JSON-RPC layer); this
|
|
5
|
+
// module never blocks on I/O beyond the handler it's given, and emits the events the stream/push paths use.
|
|
6
|
+
import { canTaskTransition, isHandoffAllowed } from '@agenticprimitives/fulfillment';
|
|
7
|
+
import { isTerminal } from './types.js';
|
|
8
|
+
import { AuthRequired, HandoffRequested } from './skill-handler.js';
|
|
9
|
+
/** Build a fresh `submitted` task record from a verified inbound message + grant. */
|
|
10
|
+
export function newTaskRecord(args) {
|
|
11
|
+
return {
|
|
12
|
+
task: {
|
|
13
|
+
taskId: args.taskId,
|
|
14
|
+
parentCaseId: args.parentCaseId,
|
|
15
|
+
state: 'submitted',
|
|
16
|
+
assignee: args.assignee,
|
|
17
|
+
assigneeKind: 'agent',
|
|
18
|
+
inputHash: args.inputHash,
|
|
19
|
+
artifactIds: [],
|
|
20
|
+
deadline: args.deadline,
|
|
21
|
+
maxRetries: args.maxRetries ?? 0,
|
|
22
|
+
permissionGrantRef: args.permissionGrantRef,
|
|
23
|
+
},
|
|
24
|
+
principal: args.principal,
|
|
25
|
+
sender: args.sender,
|
|
26
|
+
skill: args.skill,
|
|
27
|
+
delegation: args.delegation,
|
|
28
|
+
inbound: [args.inbound],
|
|
29
|
+
artifacts: [],
|
|
30
|
+
rev: 1,
|
|
31
|
+
updatedAt: args.now,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/** Apply a state transition, fail-closed via the fulfillment transition table. Bumps `rev` + emits the
|
|
35
|
+
* status event. Does NOT persist — the caller writes the returned record to the TaskStore. */
|
|
36
|
+
export function applyTransition(record, to, opts = { now: 0 }) {
|
|
37
|
+
const from = record.task.state;
|
|
38
|
+
if (from === to)
|
|
39
|
+
return { ok: false, reason: `already in ${to}` };
|
|
40
|
+
if (!canTaskTransition(from, to))
|
|
41
|
+
return { ok: false, reason: `illegal transition ${from} -> ${to}` };
|
|
42
|
+
const rev = record.rev + 1;
|
|
43
|
+
const next = {
|
|
44
|
+
...record,
|
|
45
|
+
task: { ...record.task, state: to },
|
|
46
|
+
error: to === 'failed' ? opts.error : record.error,
|
|
47
|
+
rev,
|
|
48
|
+
updatedAt: opts.now,
|
|
49
|
+
};
|
|
50
|
+
return { ok: true, record: next, event: { kind: 'task.status', taskId: record.task.taskId, state: to, rev } };
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Dispatch a `submitted` task: reject if the skill is unknown; otherwise move it to `working`, run the
|
|
54
|
+
* handler, and map the outcome to the next state. Returns the final record + the ordered events. The
|
|
55
|
+
* caller (alarm loop) persists the record and fans the events to streams/push. `makeContext` wires the
|
|
56
|
+
* per-task vault / mcp / emitArtifact (W4) — the runtime stays transport-agnostic.
|
|
57
|
+
*/
|
|
58
|
+
export async function dispatchTask(record, registry, makeContext, now, opts) {
|
|
59
|
+
const events = [];
|
|
60
|
+
if (record.task.state !== 'submitted') {
|
|
61
|
+
return { record, events };
|
|
62
|
+
}
|
|
63
|
+
const handler = registry.get(record.skill);
|
|
64
|
+
if (!handler) {
|
|
65
|
+
const rejected = applyTransition(record, 'rejected', { now, error: `unknown skill: ${record.skill}` });
|
|
66
|
+
if (rejected.ok) {
|
|
67
|
+
events.push(rejected.event);
|
|
68
|
+
return { record: { ...rejected.record, error: `unknown skill: ${record.skill}` }, events };
|
|
69
|
+
}
|
|
70
|
+
return { record, events };
|
|
71
|
+
}
|
|
72
|
+
const working = applyTransition(record, 'working', { now });
|
|
73
|
+
if (!working.ok)
|
|
74
|
+
return { record, events };
|
|
75
|
+
let cur = working.record;
|
|
76
|
+
events.push(working.event);
|
|
77
|
+
const base = makeContext(cur);
|
|
78
|
+
const ctx = {
|
|
79
|
+
...base,
|
|
80
|
+
taskId: cur.task.taskId,
|
|
81
|
+
principal: cur.principal,
|
|
82
|
+
sender: cur.sender,
|
|
83
|
+
requestAuth: (reason) => {
|
|
84
|
+
throw new AuthRequired(reason);
|
|
85
|
+
},
|
|
86
|
+
requestHandoff: (req) => {
|
|
87
|
+
throw new HandoffRequested(req);
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
let result;
|
|
91
|
+
try {
|
|
92
|
+
result = await handler.handle(ctx);
|
|
93
|
+
}
|
|
94
|
+
catch (e) {
|
|
95
|
+
if (e instanceof AuthRequired) {
|
|
96
|
+
const auth = applyTransition(cur, 'auth-required', { now });
|
|
97
|
+
if (auth.ok) {
|
|
98
|
+
events.push(auth.event);
|
|
99
|
+
return { record: auth.record, events };
|
|
100
|
+
}
|
|
101
|
+
return { record: cur, events };
|
|
102
|
+
}
|
|
103
|
+
if (e instanceof HandoffRequested) {
|
|
104
|
+
// FR-3.6 / FLF-INV-09 — gate the reassignment on the agent's HandoffPolicy + the hop budget;
|
|
105
|
+
// fail-closed: no policy, a disallowed target, or an exhausted hop budget rejects the task.
|
|
106
|
+
const req = e.request;
|
|
107
|
+
const hops = (cur.hopCount ?? 0) + 1;
|
|
108
|
+
const ok = opts?.handoffPolicy
|
|
109
|
+
&& isHandoffAllowed(opts.handoffPolicy, req.target, req.targetClass)
|
|
110
|
+
&& hops <= opts.handoffPolicy.maxHopCount;
|
|
111
|
+
if (!ok) {
|
|
112
|
+
// The handler is mid-processing (`working`), so the illegal handoff fails the task (working→failed;
|
|
113
|
+
// working→rejected is not a legal transition). Fail-closed.
|
|
114
|
+
const reason = `handoff not permitted: ${req.target}${req.targetClass ? ` (${req.targetClass})` : ''}`;
|
|
115
|
+
const fail = applyTransition(cur, 'failed', { now, error: reason });
|
|
116
|
+
if (fail.ok) {
|
|
117
|
+
events.push(fail.event);
|
|
118
|
+
return { record: { ...fail.record, error: reason }, events };
|
|
119
|
+
}
|
|
120
|
+
return { record: cur, events };
|
|
121
|
+
}
|
|
122
|
+
// The local agent's part is done; record the handoff for the transport to deliver to the target,
|
|
123
|
+
// which re-verifies the (possibly re-scoped) delegation on receipt.
|
|
124
|
+
const done = applyTransition(cur, 'completed', { now });
|
|
125
|
+
if (done.ok) {
|
|
126
|
+
events.push(done.event);
|
|
127
|
+
return { record: { ...done.record, handoff: req, hopCount: hops }, events };
|
|
128
|
+
}
|
|
129
|
+
return { record: cur, events };
|
|
130
|
+
}
|
|
131
|
+
const failed = applyTransition(cur, 'failed', { now, error: e instanceof Error ? e.message : String(e) });
|
|
132
|
+
if (failed.ok) {
|
|
133
|
+
events.push(failed.event);
|
|
134
|
+
return { record: failed.record, events };
|
|
135
|
+
}
|
|
136
|
+
return { record: cur, events };
|
|
137
|
+
}
|
|
138
|
+
const t = applyTransition(cur, result.state, { now, error: result.error });
|
|
139
|
+
if (!t.ok) {
|
|
140
|
+
const failed = applyTransition(cur, 'failed', { now, error: `handler returned illegal state ${result.state}` });
|
|
141
|
+
if (failed.ok) {
|
|
142
|
+
events.push(failed.event);
|
|
143
|
+
return { record: failed.record, events };
|
|
144
|
+
}
|
|
145
|
+
return { record: cur, events };
|
|
146
|
+
}
|
|
147
|
+
cur = result.state === 'completed' && result.artifactIds
|
|
148
|
+
? { ...t.record, task: { ...t.record.task, artifactIds: result.artifactIds } }
|
|
149
|
+
: t.record;
|
|
150
|
+
events.push(t.event);
|
|
151
|
+
return { record: cur, events };
|
|
152
|
+
}
|
|
153
|
+
export { isTerminal };
|
|
154
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { Address, Hex } from '@agenticprimitives/types';
|
|
2
|
+
import type { Delegation } from '@agenticprimitives/delegation';
|
|
3
|
+
import type { VaultRef } from './types.js';
|
|
4
|
+
/** Minimal vault seam — the consumer wires demo-mcp vault read/write over a delegation. FR-3.4: a handler
|
|
5
|
+
* delivers a result into ANOTHER principal's vault by passing a `delegation` THAT principal granted
|
|
6
|
+
* (delegator == the record owner); the consumer routes it through `callMcpToolViaDelegation` so demo-mcp
|
|
7
|
+
* keys the record by that principal. Omit `delegation` to read/write the agent's own (assignee) store. */
|
|
8
|
+
export interface VaultClient {
|
|
9
|
+
read(ref: VaultRef, opts?: {
|
|
10
|
+
delegation?: Delegation;
|
|
11
|
+
}): Promise<unknown>;
|
|
12
|
+
write(args: {
|
|
13
|
+
owner: Address;
|
|
14
|
+
recordType: string;
|
|
15
|
+
data: unknown;
|
|
16
|
+
delegation?: Delegation;
|
|
17
|
+
}): Promise<VaultRef>;
|
|
18
|
+
}
|
|
19
|
+
/** Minimal MCP seam — call a tool via the delegation token (reuses the a2a→mcp leg, W4). */
|
|
20
|
+
export interface McpClient {
|
|
21
|
+
callTool(args: {
|
|
22
|
+
tool: string;
|
|
23
|
+
toolArgs?: Record<string, unknown>;
|
|
24
|
+
}): Promise<unknown>;
|
|
25
|
+
}
|
|
26
|
+
/** Thrown by `requestAuth` to suspend a task pending a fresh/again-scoped delegation (FR-3.5). The
|
|
27
|
+
* dispatcher catches it and transitions the task to `auth-required`. */
|
|
28
|
+
export declare class AuthRequired extends Error {
|
|
29
|
+
readonly authReason: string;
|
|
30
|
+
constructor(authReason: string);
|
|
31
|
+
}
|
|
32
|
+
/** The reassignment a handler requests via `requestHandoff` (FR-3.6). The target agent re-verifies the
|
|
33
|
+
* (possibly re-scoped) delegation when it receives the handed-off task. */
|
|
34
|
+
export interface HandoffRequest {
|
|
35
|
+
/** The agent SA to reassign to. */
|
|
36
|
+
target: Address;
|
|
37
|
+
/** The target's agent class (checked against `HandoffPolicy.allowedAgentClasses`). */
|
|
38
|
+
targetClass?: string;
|
|
39
|
+
/** The skill the target should run (defaults to the current task's skill). */
|
|
40
|
+
skill?: string;
|
|
41
|
+
reason?: string;
|
|
42
|
+
}
|
|
43
|
+
/** Thrown by `requestHandoff` to reassign a task to another agent (FR-3.6). The dispatcher gates it on
|
|
44
|
+
* `isHandoffAllowed(handoffPolicy, …)` + the hop budget, then records the handoff for the transport to
|
|
45
|
+
* deliver. A disallowed handoff `rejects` the task — fail-closed (FLF-INV-09). */
|
|
46
|
+
export declare class HandoffRequested extends Error {
|
|
47
|
+
readonly request: HandoffRequest;
|
|
48
|
+
constructor(request: HandoffRequest);
|
|
49
|
+
}
|
|
50
|
+
export interface SkillContext {
|
|
51
|
+
taskId: Hex;
|
|
52
|
+
/** On whose behalf the sender acts (delegation.delegator). */
|
|
53
|
+
principal: Address;
|
|
54
|
+
/** The submitting agent SA (delegation.delegate). */
|
|
55
|
+
sender: Address;
|
|
56
|
+
/** The input body (already read from the vault by the runtime). */
|
|
57
|
+
input: unknown;
|
|
58
|
+
/** The verified, captured grant. */
|
|
59
|
+
delegation: Delegation;
|
|
60
|
+
vault: VaultClient;
|
|
61
|
+
mcp: McpClient;
|
|
62
|
+
/** Emit a result artifact: the runtime writes the body to the ASSIGNEE's vault (A2A-INV-04), computes
|
|
63
|
+
* the bodyHash, records the ref, and returns the artifactId. Only the hash/ref travel in task state. */
|
|
64
|
+
emitArtifact(a: {
|
|
65
|
+
artifactKind: string;
|
|
66
|
+
body: unknown;
|
|
67
|
+
bodyContentType?: string;
|
|
68
|
+
disclosurePolicy?: string;
|
|
69
|
+
caseId?: Hex;
|
|
70
|
+
}): Promise<Hex>;
|
|
71
|
+
/** Suspend pending a fresh grant — throws `AuthRequired`. */
|
|
72
|
+
requestAuth(reason: string): never;
|
|
73
|
+
/** Reassign the task to another agent (FR-3.6) — throws `HandoffRequested`. The dispatcher gates it on
|
|
74
|
+
* the agent's `HandoffPolicy`; a disallowed target rejects the task. */
|
|
75
|
+
requestHandoff(req: HandoffRequest): never;
|
|
76
|
+
}
|
|
77
|
+
export interface SkillResult {
|
|
78
|
+
state: 'completed' | 'failed' | 'input-required';
|
|
79
|
+
artifactIds?: Hex[];
|
|
80
|
+
error?: string;
|
|
81
|
+
}
|
|
82
|
+
export interface SkillHandler {
|
|
83
|
+
skill: string;
|
|
84
|
+
handle(ctx: SkillContext): Promise<SkillResult>;
|
|
85
|
+
}
|
|
86
|
+
/** Index handlers by skill name; reject duplicate registrations. */
|
|
87
|
+
export declare function buildSkillRegistry(handlers: SkillHandler[]): Map<string, SkillHandler>;
|
|
88
|
+
//# sourceMappingURL=skill-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-handler.d.ts","sourceRoot":"","sources":["../src/skill-handler.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C;;;2GAG2G;AAC3G,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,UAAU,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1E,KAAK,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC;QAAC,UAAU,CAAC,EAAE,UAAU,CAAA;KAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CAChH;AAED,4FAA4F;AAC5F,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACxF;AAED;yEACyE;AACzE,qBAAa,YAAa,SAAQ,KAAK;aACT,UAAU,EAAE,MAAM;gBAAlB,UAAU,EAAE,MAAM;CAI/C;AAED;4EAC4E;AAC5E,MAAM,WAAW,cAAc;IAC7B,mCAAmC;IACnC,MAAM,EAAE,OAAO,CAAC;IAChB,sFAAsF;IACtF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;mFAEmF;AACnF,qBAAa,gBAAiB,SAAQ,KAAK;aACb,OAAO,EAAE,cAAc;gBAAvB,OAAO,EAAE,cAAc;CAIpD;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,GAAG,CAAC;IACZ,8DAA8D;IAC9D,SAAS,EAAE,OAAO,CAAC;IACnB,qDAAqD;IACrD,MAAM,EAAE,OAAO,CAAC;IAChB,mEAAmE;IACnE,KAAK,EAAE,OAAO,CAAC;IACf,oCAAoC;IACpC,UAAU,EAAE,UAAU,CAAC;IACvB,KAAK,EAAE,WAAW,CAAC;IACnB,GAAG,EAAE,SAAS,CAAC;IACf;6GACyG;IACzG,YAAY,CAAC,CAAC,EAAE;QACd,YAAY,EAAE,MAAM,CAAC;QACrB,IAAI,EAAE,OAAO,CAAC;QACd,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,MAAM,CAAC,EAAE,GAAG,CAAC;KACd,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACjB,6DAA6D;IAC7D,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC;IACnC;6EACyE;IACzE,cAAc,CAAC,GAAG,EAAE,cAAc,GAAG,KAAK,CAAC;CAC5C;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,WAAW,GAAG,QAAQ,GAAG,gBAAgB,CAAC;IACjD,WAAW,CAAC,EAAE,GAAG,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CACjD;AAED,oEAAoE;AACpE,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAOtF"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** Thrown by `requestAuth` to suspend a task pending a fresh/again-scoped delegation (FR-3.5). The
|
|
2
|
+
* dispatcher catches it and transitions the task to `auth-required`. */
|
|
3
|
+
export class AuthRequired extends Error {
|
|
4
|
+
authReason;
|
|
5
|
+
constructor(authReason) {
|
|
6
|
+
super(`auth-required: ${authReason}`);
|
|
7
|
+
this.authReason = authReason;
|
|
8
|
+
this.name = 'AuthRequired';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/** Thrown by `requestHandoff` to reassign a task to another agent (FR-3.6). The dispatcher gates it on
|
|
12
|
+
* `isHandoffAllowed(handoffPolicy, …)` + the hop budget, then records the handoff for the transport to
|
|
13
|
+
* deliver. A disallowed handoff `rejects` the task — fail-closed (FLF-INV-09). */
|
|
14
|
+
export class HandoffRequested extends Error {
|
|
15
|
+
request;
|
|
16
|
+
constructor(request) {
|
|
17
|
+
super(`handoff-requested: ${request.target}`);
|
|
18
|
+
this.request = request;
|
|
19
|
+
this.name = 'HandoffRequested';
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/** Index handlers by skill name; reject duplicate registrations. */
|
|
23
|
+
export function buildSkillRegistry(handlers) {
|
|
24
|
+
const reg = new Map();
|
|
25
|
+
for (const h of handlers) {
|
|
26
|
+
if (reg.has(h.skill))
|
|
27
|
+
throw new Error(`duplicate skill handler: ${h.skill}`);
|
|
28
|
+
reg.set(h.skill, h);
|
|
29
|
+
}
|
|
30
|
+
return reg;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=skill-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-handler.js","sourceRoot":"","sources":["../src/skill-handler.ts"],"names":[],"mappings":"AAsBA;yEACyE;AACzE,MAAM,OAAO,YAAa,SAAQ,KAAK;IACT;IAA5B,YAA4B,UAAkB;QAC5C,KAAK,CAAC,kBAAkB,UAAU,EAAE,CAAC,CAAC;QADZ,eAAU,GAAV,UAAU,CAAQ;QAE5C,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF;AAcD;;mFAEmF;AACnF,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IACb;IAA5B,YAA4B,OAAuB;QACjD,KAAK,CAAC,sBAAsB,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QADpB,YAAO,GAAP,OAAO,CAAgB;QAEjD,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AAyCD,oEAAoE;AACpE,MAAM,UAAU,kBAAkB,CAAC,QAAwB;IACzD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAwB,CAAC;IAC5C,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QAC7E,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACtB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
package/dist/sse.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { TaskEvent } from './types.js';
|
|
2
|
+
export declare const SSE_HEADERS: Record<string, string>;
|
|
3
|
+
/** Serialize a task event as an SSE frame: `event: <kind>` + `data: <json>`. */
|
|
4
|
+
export declare function formatSseEvent(event: TaskEvent): string;
|
|
5
|
+
/** An SSE keep-alive comment frame. */
|
|
6
|
+
export declare function formatSseComment(text?: string): string;
|
|
7
|
+
/** Whether a stream should close after this event (terminal task states end the stream). */
|
|
8
|
+
export declare function isStreamEnd(event: TaskEvent): boolean;
|
|
9
|
+
//# sourceMappingURL=sse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../src/sse.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAI9C,CAAC;AAEF,gFAAgF;AAChF,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAEvD;AAED,uCAAuC;AACvC,wBAAgB,gBAAgB,CAAC,IAAI,SAAe,GAAG,MAAM,CAE5D;AAED,4FAA4F;AAC5F,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAErD"}
|
package/dist/sse.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export const SSE_HEADERS = {
|
|
2
|
+
'content-type': 'text/event-stream',
|
|
3
|
+
'cache-control': 'no-cache',
|
|
4
|
+
connection: 'keep-alive',
|
|
5
|
+
};
|
|
6
|
+
/** Serialize a task event as an SSE frame: `event: <kind>` + `data: <json>`. */
|
|
7
|
+
export function formatSseEvent(event) {
|
|
8
|
+
return `event: ${event.kind}\ndata: ${JSON.stringify(event)}\n\n`;
|
|
9
|
+
}
|
|
10
|
+
/** An SSE keep-alive comment frame. */
|
|
11
|
+
export function formatSseComment(text = 'keep-alive') {
|
|
12
|
+
return `: ${text}\n\n`;
|
|
13
|
+
}
|
|
14
|
+
/** Whether a stream should close after this event (terminal task states end the stream). */
|
|
15
|
+
export function isStreamEnd(event) {
|
|
16
|
+
return event.kind === 'task.status' && (event.state === 'completed' || event.state === 'failed' || event.state === 'canceled' || event.state === 'rejected');
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=sse.js.map
|
package/dist/sse.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse.js","sourceRoot":"","sources":["../src/sse.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,WAAW,GAA2B;IACjD,cAAc,EAAE,mBAAmB;IACnC,eAAe,EAAE,UAAU;IAC3B,UAAU,EAAE,YAAY;CACzB,CAAC;AAEF,gFAAgF;AAChF,MAAM,UAAU,cAAc,CAAC,KAAgB;IAC7C,OAAO,UAAU,KAAK,CAAC,IAAI,WAAW,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC;AACpE,CAAC;AAED,uCAAuC;AACvC,MAAM,UAAU,gBAAgB,CAAC,IAAI,GAAG,YAAY;IAClD,OAAO,KAAK,IAAI,MAAM,CAAC;AACzB,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,WAAW,CAAC,KAAgB;IAC1C,OAAO,KAAK,CAAC,IAAI,KAAK,aAAa,IAAI,CAAC,KAAK,CAAC,KAAK,KAAK,WAAW,IAAI,KAAK,CAAC,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,KAAK,KAAK,UAAU,IAAI,KAAK,CAAC,KAAK,KAAK,UAAU,CAAC,CAAC;AAC/J,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Hex } from '@agenticprimitives/types';
|
|
2
|
+
import type { TaskRecord } from './types.js';
|
|
3
|
+
export interface TaskStore {
|
|
4
|
+
/** Persist (insert or replace) a task record. */
|
|
5
|
+
put(record: TaskRecord): Promise<void>;
|
|
6
|
+
/** Load a task record, or null if unknown. */
|
|
7
|
+
get(taskId: Hex): Promise<TaskRecord | null>;
|
|
8
|
+
/** Task ids in a non-terminal state that are due for processing (drives the alarm loop). */
|
|
9
|
+
listDue(now: number): Promise<Hex[]>;
|
|
10
|
+
/** Single-use message-id reservation (FR-4.3 inbound replay guard). Returns false if already seen. */
|
|
11
|
+
reserveMessageId(messageId: Hex, ttlSec: number): Promise<boolean>;
|
|
12
|
+
}
|
|
13
|
+
/** Reference in-memory TaskStore — used by the test harness + non-Worker consumers. NOT for production
|
|
14
|
+
* (no cross-isolate durability); the Cloudflare DO adapter is the durable implementation. */
|
|
15
|
+
export declare function createInMemoryTaskStore(): TaskStore;
|
|
16
|
+
//# sourceMappingURL=task-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-store.d.ts","sourceRoot":"","sources":["../src/task-store.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,WAAW,SAAS;IACxB,iDAAiD;IACjD,GAAG,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,8CAA8C;IAC9C,GAAG,CAAC,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IAC7C,4FAA4F;IAC5F,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACrC,sGAAsG;IACtG,gBAAgB,CAAC,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACpE;AAED;8FAC8F;AAC9F,wBAAgB,uBAAuB,IAAI,SAAS,CA2BnD"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** Reference in-memory TaskStore — used by the test harness + non-Worker consumers. NOT for production
|
|
2
|
+
* (no cross-isolate durability); the Cloudflare DO adapter is the durable implementation. */
|
|
3
|
+
export function createInMemoryTaskStore() {
|
|
4
|
+
const tasks = new Map();
|
|
5
|
+
const seen = new Map(); // messageId -> expiry (sec)
|
|
6
|
+
const due = new Set();
|
|
7
|
+
return {
|
|
8
|
+
async put(record) {
|
|
9
|
+
tasks.set(record.task.taskId.toLowerCase(), record);
|
|
10
|
+
const key = record.task.taskId.toLowerCase();
|
|
11
|
+
if (record.task.state === 'submitted' || record.task.state === 'working')
|
|
12
|
+
due.add(key);
|
|
13
|
+
else
|
|
14
|
+
due.delete(key);
|
|
15
|
+
},
|
|
16
|
+
async get(taskId) {
|
|
17
|
+
return tasks.get(taskId.toLowerCase()) ?? null;
|
|
18
|
+
},
|
|
19
|
+
async listDue() {
|
|
20
|
+
return [...due];
|
|
21
|
+
},
|
|
22
|
+
async reserveMessageId(messageId, ttlSec) {
|
|
23
|
+
const key = messageId.toLowerCase();
|
|
24
|
+
const exp = seen.get(key);
|
|
25
|
+
// `now` is injected by callers in tests; here we approximate with a monotonic-free check: a present
|
|
26
|
+
// entry means used. (The durable adapter uses KV TTL.)
|
|
27
|
+
if (exp !== undefined)
|
|
28
|
+
return false;
|
|
29
|
+
seen.set(key, ttlSec);
|
|
30
|
+
return true;
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=task-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-store.js","sourceRoot":"","sources":["../src/task-store.ts"],"names":[],"mappings":"AAiBA;8FAC8F;AAC9F,MAAM,UAAU,uBAAuB;IACrC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC5C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC,CAAC,4BAA4B;IACpE,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,OAAO;QACL,KAAK,CAAC,GAAG,CAAC,MAAM;YACd,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,MAAM,CAAC,CAAC;YACpD,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,KAAK,WAAW,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,KAAK,SAAS;gBAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;;gBAClF,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACvB,CAAC;QACD,KAAK,CAAC,GAAG,CAAC,MAAM;YACd,OAAO,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,IAAI,IAAI,CAAC;QACjD,CAAC;QACD,KAAK,CAAC,OAAO;YACX,OAAO,CAAC,GAAG,GAAG,CAAU,CAAC;QAC3B,CAAC;QACD,KAAK,CAAC,gBAAgB,CAAC,SAAS,EAAE,MAAM;YACtC,MAAM,GAAG,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC;YACpC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC1B,oGAAoG;YACpG,uDAAuD;YACvD,IAAI,GAAG,KAAK,SAAS;gBAAE,OAAO,KAAK,CAAC;YACpC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YACtB,OAAO,IAAI,CAAC;QACd,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { Address, Hex } from '@agenticprimitives/types';
|
|
2
|
+
import type { Delegation } from '@agenticprimitives/delegation';
|
|
3
|
+
import type { Task, TaskState, Artifact } from '@agenticprimitives/fulfillment';
|
|
4
|
+
import type { HandoffRequest } from './skill-handler.js';
|
|
5
|
+
export type { Task, TaskState, Artifact };
|
|
6
|
+
/** A2A-INV-04 — message/artifact bodies are vault records, never inline. A ref names where to read the
|
|
7
|
+
* body (the assignee's per-agent demo-mcp vault namespace). The hash binds the content. */
|
|
8
|
+
export interface VaultRef {
|
|
9
|
+
/** SA whose vault namespace holds the record (the assignee). */
|
|
10
|
+
owner: Address;
|
|
11
|
+
/** demo-mcp record type, e.g. `a2a:msg:<taskId>` / `a2a:artifact:<artifactId>`. */
|
|
12
|
+
recordType: string;
|
|
13
|
+
}
|
|
14
|
+
/** An inbound A2A message (the request that creates a task, or a follow-up on a thread). Signed by the
|
|
15
|
+
* sender; the body is a VaultRef, the hash binds it. */
|
|
16
|
+
export interface A2aMessage {
|
|
17
|
+
messageId: Hex;
|
|
18
|
+
threadId?: string;
|
|
19
|
+
/** The SA that sent it (the delegation's delegate / requester). */
|
|
20
|
+
sender: Address;
|
|
21
|
+
/** The requested skill (dispatched by name; unknown → task rejected). */
|
|
22
|
+
skill: string;
|
|
23
|
+
/** Where the input body lives + its hash. */
|
|
24
|
+
bodyRef: VaultRef;
|
|
25
|
+
bodyHash: Hex;
|
|
26
|
+
/** Sender signature over the canonical message (A2A-INV-01). */
|
|
27
|
+
signature: Hex;
|
|
28
|
+
createdAt: number;
|
|
29
|
+
}
|
|
30
|
+
/** An A2A artifact = a fulfillment Artifact plus the vault ref to its body. */
|
|
31
|
+
export interface A2aArtifact extends Artifact {
|
|
32
|
+
bodyRef: VaultRef;
|
|
33
|
+
}
|
|
34
|
+
/** The full per-task record the runtime persists (answers tasks/get + resumes after eviction). */
|
|
35
|
+
export interface TaskRecord {
|
|
36
|
+
task: Task;
|
|
37
|
+
/** The principal the sender acts FOR (the delegation's delegator) — what withDelegation keys on. */
|
|
38
|
+
principal: Address;
|
|
39
|
+
/** The SA that submitted the task (the delegate). */
|
|
40
|
+
sender: Address;
|
|
41
|
+
skill: string;
|
|
42
|
+
/** The verified, captured grant — handed to the skill handler + re-checked on revocation (FR-3.3/FR-4.6). */
|
|
43
|
+
delegation: Delegation;
|
|
44
|
+
inbound: A2aMessage[];
|
|
45
|
+
artifacts: A2aArtifact[];
|
|
46
|
+
/** Webhook registered via tasks/pushNotificationConfig/set; signed push fires here on terminal state. */
|
|
47
|
+
pushConfig?: PushConfig;
|
|
48
|
+
/** FR-3.6 — set when a handler reassigned this task (policy-gated). The transport delivers a
|
|
49
|
+
* message/send to `handoff.target`, which re-verifies the delegation. */
|
|
50
|
+
handoff?: HandoffRequest;
|
|
51
|
+
/** Number of hand-offs this task has been through — checked against `HandoffPolicy.maxHopCount`. */
|
|
52
|
+
hopCount?: number;
|
|
53
|
+
/** Last error on a `failed` transition, surfaced to tasks/get. */
|
|
54
|
+
error?: string;
|
|
55
|
+
/** Monotonic version, bumped on every mutation — drives stream/idempotency. */
|
|
56
|
+
rev: number;
|
|
57
|
+
updatedAt: number;
|
|
58
|
+
}
|
|
59
|
+
/** Push webhook config (FR-5.2). */
|
|
60
|
+
export interface PushConfig {
|
|
61
|
+
url: string;
|
|
62
|
+
token?: string;
|
|
63
|
+
}
|
|
64
|
+
/** Stream/push event emitted on each task mutation. */
|
|
65
|
+
export type TaskEvent = {
|
|
66
|
+
kind: 'task.status';
|
|
67
|
+
taskId: Hex;
|
|
68
|
+
state: TaskState;
|
|
69
|
+
rev: number;
|
|
70
|
+
error?: string;
|
|
71
|
+
} | {
|
|
72
|
+
kind: 'task.artifact';
|
|
73
|
+
taskId: Hex;
|
|
74
|
+
artifactId: Hex;
|
|
75
|
+
rev: number;
|
|
76
|
+
};
|
|
77
|
+
/** Terminal states — no further transitions; delivery (push) fires here. */
|
|
78
|
+
export declare const TERMINAL_STATES: ReadonlySet<TaskState>;
|
|
79
|
+
export declare function isTerminal(state: TaskState): boolean;
|
|
80
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAChF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;AAE1C;4FAC4F;AAC5F,MAAM,WAAW,QAAQ;IACvB,gEAAgE;IAChE,KAAK,EAAE,OAAO,CAAC;IACf,mFAAmF;IACnF,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;yDACyD;AACzD,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,GAAG,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,MAAM,EAAE,OAAO,CAAC;IAChB,yEAAyE;IACzE,KAAK,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,OAAO,EAAE,QAAQ,CAAC;IAClB,QAAQ,EAAE,GAAG,CAAC;IACd,gEAAgE;IAChE,SAAS,EAAE,GAAG,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,+EAA+E;AAC/E,MAAM,WAAW,WAAY,SAAQ,QAAQ;IAC3C,OAAO,EAAE,QAAQ,CAAC;CACnB;AAED,kGAAkG;AAClG,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,IAAI,CAAC;IACX,oGAAoG;IACpG,SAAS,EAAE,OAAO,CAAC;IACnB,qDAAqD;IACrD,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,6GAA6G;IAC7G,UAAU,EAAE,UAAU,CAAC;IACvB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,SAAS,EAAE,WAAW,EAAE,CAAC;IACzB,yGAAyG;IACzG,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB;8EAC0E;IAC1E,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,oGAAoG;IACpG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,oCAAoC;AACpC,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,uDAAuD;AACvD,MAAM,MAAM,SAAS,GACjB;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,GAAG,CAAC;IAAC,KAAK,EAAE,SAAS,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GACnF;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,MAAM,EAAE,GAAG,CAAC;IAAC,UAAU,EAAE,GAAG,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzE,4EAA4E;AAC5E,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,SAAS,CAKjD,CAAC;AAEH,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAEpD"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Terminal states — no further transitions; delivery (push) fires here. */
|
|
2
|
+
export const TERMINAL_STATES = new Set([
|
|
3
|
+
'completed',
|
|
4
|
+
'failed',
|
|
5
|
+
'canceled',
|
|
6
|
+
'rejected',
|
|
7
|
+
]);
|
|
8
|
+
export function isTerminal(state) {
|
|
9
|
+
return TERMINAL_STATES.has(state);
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AA8EA,4EAA4E;AAC5E,MAAM,CAAC,MAAM,eAAe,GAA2B,IAAI,GAAG,CAAY;IACxE,WAAW;IACX,QAAQ;IACR,UAAU;IACV,UAAU;CACX,CAAC,CAAC;AAEH,MAAM,UAAU,UAAU,CAAC,KAAgB;IACzC,OAAO,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AACpC,CAAC"}
|