@rivus/agent 0.13.2 → 0.14.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.
Files changed (46) hide show
  1. package/README.md +17 -18
  2. package/dist/acp.d.ts +40 -40
  3. package/dist/acp.js +71 -31
  4. package/dist/bootstrap/pi-feishu.d.ts +20 -0
  5. package/dist/bootstrap/pi-feishu.js +596 -0
  6. package/dist/{agent-loop.d.ts → chunks/agent-loop.d.ts} +293 -44
  7. package/dist/chunks/agent-loop.js +1272 -0
  8. package/dist/chunks/api.d.ts +70 -0
  9. package/dist/chunks/api.js +471 -0
  10. package/dist/{rivus-plugin.d.ts → chunks/api2.d.ts} +271 -120
  11. package/dist/chunks/api2.js +1331 -0
  12. package/dist/chunks/api3.d.ts +402 -0
  13. package/dist/chunks/index.d.ts +3662 -0
  14. package/dist/chunks/module.js +267 -0
  15. package/dist/chunks/pi-skill-tool.js +460 -0
  16. package/dist/chunks/pi-tool-proxy.d.ts +188 -0
  17. package/dist/chunks/pi.js +329 -0
  18. package/dist/{rivus-daemon-cli.js → chunks/rivus-daemon-cli.js} +2197 -1526
  19. package/dist/{rivus-plugin-testkit.d.ts → chunks/rivus-plugin-testkit.d.ts} +1 -1
  20. package/dist/{rivus-plugin-testkit.js → chunks/rivus-plugin-testkit.js} +11 -3
  21. package/dist/chunks/sha256-digest.js +12 -0
  22. package/dist/chunks/spi.d.ts +1 -0
  23. package/dist/chunks/spi.js +2 -0
  24. package/dist/chunks/src.js +9897 -0
  25. package/dist/cli.js +604 -95
  26. package/dist/index.d.ts +8 -3645
  27. package/dist/index.js +9 -10483
  28. package/dist/mcp.d.ts +3 -38
  29. package/dist/mcp.js +4 -114
  30. package/dist/pi.d.ts +95 -9
  31. package/dist/pi.js +3 -146
  32. package/dist/testing/index.d.ts +1 -1
  33. package/dist/testing/index.js +1 -1
  34. package/examples/pi-feishu-deployment.bootstrap.ts +45 -54
  35. package/examples/pi-feishu.bootstrap.ts +53 -37
  36. package/examples/rivus-starter.plugin.mjs +3 -1
  37. package/package.json +12 -14
  38. package/dist/agent-loop.js +0 -121
  39. package/dist/agent-memory.d.ts +0 -100
  40. package/dist/agent-memory.js +0 -114
  41. package/dist/background-session-authority.js +0 -224
  42. package/dist/background-session-input.js +0 -45
  43. package/dist/background-session-service.d.ts +0 -291
  44. package/dist/pi-tool-proxy.d.ts +0 -197
  45. package/dist/rivus-plugin-registry.js +0 -215
  46. package/dist/tool-input-digest.js +0 -128
@@ -0,0 +1,460 @@
1
+ import { b as restrictMemoryScopesForAudience } from "./api.js";
2
+ import { n as createRandomId, t as createSha256Digest } from "./sha256-digest.js";
3
+ import { Effect } from "effect";
4
+ import { Unsafe } from "typebox";
5
+ //#region src/modules/tool-execution/domain/authority/invocation-authority.ts
6
+ var InvalidInvocationAuthority = class extends Error {
7
+ name = "InvalidInvocationAuthority";
8
+ };
9
+ function normalizeInvocationAuthority(authority) {
10
+ if (!authority.sourceMessageId.trim()) throw new InvalidInvocationAuthority("invocation authority requires a trusted source message id");
11
+ if (authority.endpointId !== void 0 && !authority.endpointId.trim()) throw new InvalidInvocationAuthority("invocation authority requires a trusted endpoint id");
12
+ const memory = authority.memory ? Object.freeze({
13
+ ...authority.memory,
14
+ scopes: Object.freeze(restrictMemoryScopesForAudience(authority.memory.scopes, authority.memory.audience))
15
+ }) : void 0;
16
+ return Object.freeze({
17
+ ...authority,
18
+ ...authority.allowedActorOpenIds ? { allowedActorOpenIds: Object.freeze([...authority.allowedActorOpenIds]) } : {},
19
+ toolGrantSet: Object.freeze({
20
+ revision: authority.toolGrantSet.revision,
21
+ toolIds: Object.freeze([...authority.toolGrantSet.toolIds])
22
+ }),
23
+ ...memory ? { memory } : {}
24
+ });
25
+ }
26
+ //#endregion
27
+ //#region src/modules/tool-execution/domain/authority/tool-risk.ts
28
+ function requiresToolApproval(risk) {
29
+ return risk === "irreversible" || risk === "host-control";
30
+ }
31
+ //#endregion
32
+ //#region src/modules/tool-execution/application/authority/invocation-authority-registry.ts
33
+ const authorities = /* @__PURE__ */ new WeakMap();
34
+ function createInvocationAuthority(authority) {
35
+ const reference = Object.freeze({ id: `authority:${createRandomId()}` });
36
+ authorities.set(reference, normalizeInvocationAuthority(authority));
37
+ return reference;
38
+ }
39
+ function resolveInvocationAuthority(reference) {
40
+ const authority = authorities.get(reference);
41
+ if (!authority) throw new InvalidInvocationAuthority("invocation authority was not issued by this host");
42
+ return authority;
43
+ }
44
+ //#endregion
45
+ //#region src/modules/tool-execution/domain/input/stable-tool-input.ts
46
+ var InvalidStableJson = class extends Error {
47
+ name = "InvalidStableJson";
48
+ };
49
+ var InvalidToolInput = class extends InvalidStableJson {
50
+ name = "InvalidToolInput";
51
+ };
52
+ function createStableToolInputDigest(input, digest) {
53
+ let canonical;
54
+ try {
55
+ canonical = normalizeStableJson(input);
56
+ } catch (error) {
57
+ if (error instanceof InvalidStableJson) throw new InvalidToolInput(error.message);
58
+ throw error;
59
+ }
60
+ return digest(JSON.stringify(canonical));
61
+ }
62
+ function normalizeStableJson(value) {
63
+ return canonicalize(value, /* @__PURE__ */ new Set());
64
+ }
65
+ function canonicalize(value, ancestors) {
66
+ if (value === null || typeof value === "string" || typeof value === "boolean") return value;
67
+ if (typeof value === "number") {
68
+ if (!Number.isFinite(value)) throw new InvalidStableJson("stable JSON numbers must be finite");
69
+ return Object.is(value, -0) ? 0 : value;
70
+ }
71
+ if (typeof value !== "object") throw new InvalidStableJson("value must contain only stable JSON values");
72
+ if (ancestors.has(value)) throw new InvalidStableJson("stable JSON must not contain cycles");
73
+ ancestors.add(value);
74
+ try {
75
+ if (Array.isArray(value)) return Array.from({ length: value.length }, (_, index) => {
76
+ if (!Object.hasOwn(value, index)) throw new InvalidStableJson("stable JSON arrays must not contain holes");
77
+ return canonicalize(value[index], ancestors);
78
+ });
79
+ const prototype = Object.getPrototypeOf(value);
80
+ if (prototype !== Object.prototype && prototype !== null) throw new InvalidStableJson("stable JSON objects must be plain objects");
81
+ return Object.fromEntries(Object.entries(value).sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0).map(([key, entry]) => [key, canonicalize(entry, ancestors)]));
82
+ } finally {
83
+ ancestors.delete(value);
84
+ }
85
+ }
86
+ //#endregion
87
+ //#region src/modules/tool-execution/domain/operation/tool-operation.ts
88
+ var ToolOperationTransitionDenied = class extends Error {
89
+ name = "ToolOperationTransitionDenied";
90
+ };
91
+ function beginToolOperation(current, operationId, binding) {
92
+ if (!current) return {
93
+ record: {
94
+ binding,
95
+ operationId,
96
+ revision: 1,
97
+ state: { status: "pending" }
98
+ },
99
+ status: "acquired"
100
+ };
101
+ if (!isSameToolOperationBinding(current.binding, binding)) return {
102
+ reason: "operation id is bound to another invocation",
103
+ status: "blocked"
104
+ };
105
+ switch (current.state.status) {
106
+ case "completed": return {
107
+ result: structuredClone(current.state.result),
108
+ status: "completed"
109
+ };
110
+ case "aborted": return {
111
+ record: {
112
+ binding: current.binding,
113
+ operationId: current.operationId,
114
+ revision: current.revision + 1,
115
+ state: { status: "pending" }
116
+ },
117
+ status: "acquired"
118
+ };
119
+ case "pending": return {
120
+ reason: "operation is already in progress",
121
+ status: "blocked"
122
+ };
123
+ case "reconciliation-required": return {
124
+ reason: current.state.reason,
125
+ status: "blocked"
126
+ };
127
+ }
128
+ }
129
+ function inspectToolOperation(current, binding) {
130
+ if (!current || current.state.status === "aborted" && isSameToolOperationBinding(current.binding, binding)) return { status: "missing" };
131
+ if (!isSameToolOperationBinding(current.binding, binding)) return {
132
+ reason: "operation id is bound to another invocation",
133
+ status: "blocked"
134
+ };
135
+ return current.state.status === "completed" ? {
136
+ result: structuredClone(current.state.result),
137
+ status: "completed"
138
+ } : {
139
+ reason: current.state.status === "reconciliation-required" ? current.state.reason : "operation is already in progress",
140
+ status: "blocked"
141
+ };
142
+ }
143
+ function completeToolOperation(current, operationId, binding, result) {
144
+ return transitionPending(current, operationId, binding, {
145
+ result: normalizeStableJson(result),
146
+ status: "completed"
147
+ });
148
+ }
149
+ function abortToolOperation(current, operationId, binding) {
150
+ return transitionPending(current, operationId, binding, { status: "aborted" });
151
+ }
152
+ function requireToolOperationReconciliation(current, operationId, binding, reason) {
153
+ return transitionPending(current, operationId, binding, {
154
+ reason,
155
+ status: "reconciliation-required"
156
+ });
157
+ }
158
+ function reconcileToolOperation(current, input) {
159
+ if (!current || current.state.status !== "reconciliation-required" || current.revision !== input.expectedRevision) throw new ToolOperationTransitionDenied(`tool operation is not the expected reconciliation revision: ${input.operationId}`);
160
+ const action = normalizeReconciliationAction(input.action);
161
+ const result = input.outcome.status === "applied" ? normalizeStableJson(input.outcome.result) : void 0;
162
+ return {
163
+ ...current,
164
+ reconciliation: {
165
+ ...action,
166
+ outcome: input.outcome.status
167
+ },
168
+ revision: current.revision + 1,
169
+ state: input.outcome.status === "applied" ? {
170
+ result,
171
+ status: "completed"
172
+ } : { status: "aborted" }
173
+ };
174
+ }
175
+ function recoverInterruptedToolOperation(record) {
176
+ if (record.state.status !== "pending") return record;
177
+ return {
178
+ ...record,
179
+ revision: record.revision + 1,
180
+ state: {
181
+ reason: "process exited before the tool outcome was durably recorded",
182
+ status: "reconciliation-required"
183
+ }
184
+ };
185
+ }
186
+ function isSameToolOperationBinding(left, right) {
187
+ return left.agentId === right.agentId && left.inputDigest === right.inputDigest && left.instanceId === right.instanceId && left.sourceMessageId === right.sourceMessageId && left.toolId === right.toolId && left.toolVersion === right.toolVersion;
188
+ }
189
+ function isValidToolOperationTransition(previous, next) {
190
+ if (!isSameToolOperationBinding(previous.binding, next.binding)) return false;
191
+ switch (previous.state.status) {
192
+ case "pending": return [
193
+ "completed",
194
+ "reconciliation-required",
195
+ "aborted"
196
+ ].includes(next.state.status) && isSameReconciliation(previous.reconciliation, next.reconciliation);
197
+ case "aborted": return next.state.status === "pending" && next.reconciliation === void 0;
198
+ case "completed": return false;
199
+ case "reconciliation-required": return (next.state.status === "completed" || next.state.status === "aborted") && next.reconciliation !== void 0 && isValidReconciliation(next.reconciliation) && next.reconciliation.outcome === (next.state.status === "completed" ? "applied" : "not-applied") && !isSameReconciliation(previous.reconciliation, next.reconciliation);
200
+ }
201
+ }
202
+ function transitionPending(current, operationId, binding, state) {
203
+ if (!current || current.state.status !== "pending" || !isSameToolOperationBinding(current.binding, binding)) throw new ToolOperationTransitionDenied(`tool operation is not held by this invocation: ${operationId}`);
204
+ return {
205
+ ...current,
206
+ revision: current.revision + 1,
207
+ state
208
+ };
209
+ }
210
+ function normalizeReconciliationAction(action) {
211
+ const actorId = action.actorId.trim();
212
+ const note = action.note.trim();
213
+ if (!actorId) throw new ToolOperationTransitionDenied("recovery actor must not be empty");
214
+ if (!note) throw new ToolOperationTransitionDenied("recovery note must not be empty");
215
+ if (!Number.isFinite(Date.parse(action.at))) throw new ToolOperationTransitionDenied("recovery timestamp must be an ISO timestamp");
216
+ return Object.freeze({
217
+ actorId,
218
+ at: action.at,
219
+ note
220
+ });
221
+ }
222
+ function isValidReconciliation(value) {
223
+ return value.actorId.trim().length > 0 && Number.isFinite(Date.parse(value.at)) && value.note.trim().length > 0 && (value.outcome === "applied" || value.outcome === "not-applied");
224
+ }
225
+ function isSameReconciliation(left, right) {
226
+ if (left === void 0 || right === void 0) return left === right;
227
+ return left.actorId === right.actorId && left.at === right.at && left.note === right.note && left.outcome === right.outcome;
228
+ }
229
+ //#endregion
230
+ //#region src/modules/tool-execution/application/operation/tool-operation-ledger.ts
231
+ function createToolOperationLedger(options = {}) {
232
+ const records = new Map(options.initial?.map((record) => [record.operationId, structuredClone(record)]) ?? []);
233
+ const exclusive = Effect.unsafeMakeSemaphore(1).withPermits(1);
234
+ const save = (record) => {
235
+ const snapshot = structuredClone(record);
236
+ return (options.persist ? options.persist(snapshot) : Effect.void).pipe(Effect.tap(() => Effect.sync(() => {
237
+ records.set(snapshot.operationId, structuredClone(snapshot));
238
+ })));
239
+ };
240
+ const transition = (operationId, next) => exclusive(Effect.gen(function* () {
241
+ const record = yield* Effect.try({
242
+ catch: (error) => error,
243
+ try: () => next(records.get(operationId))
244
+ });
245
+ yield* save(record);
246
+ }));
247
+ return {
248
+ abort: (operationId, binding) => transition(operationId, (current) => abortToolOperation(current, operationId, binding)),
249
+ begin: (operationId, binding) => exclusive(Effect.gen(function* () {
250
+ const decision = beginToolOperation(records.get(operationId), operationId, binding);
251
+ if (decision.status !== "acquired") return decision;
252
+ yield* save(decision.record);
253
+ return { status: "acquired" };
254
+ })),
255
+ complete: (operationId, binding, result) => transition(operationId, (current) => completeToolOperation(current, operationId, binding, result)),
256
+ inspect: (operationId, binding) => exclusive(Effect.sync(() => inspectToolOperation(records.get(operationId), binding))),
257
+ reconciliationRequired: () => [...records.values()].filter((record) => record.state.status === "reconciliation-required").map((record) => structuredClone(record)),
258
+ reconcile: (input) => exclusive(Effect.gen(function* () {
259
+ const record = yield* Effect.try({
260
+ catch: (error) => error,
261
+ try: () => reconcileToolOperation(records.get(input.operationId), input)
262
+ });
263
+ yield* save(record);
264
+ return structuredClone(record);
265
+ })),
266
+ requireReconciliation: (operationId, binding, reason) => transition(operationId, (current) => requireToolOperationReconciliation(current, operationId, binding, reason)),
267
+ unresolvedForSource: (sourceMessageId) => [...records.values()].filter((record) => record.binding.sourceMessageId === sourceMessageId && (record.state.status === "pending" || record.state.status === "reconciliation-required")).map((record) => structuredClone(record))
268
+ };
269
+ }
270
+ //#endregion
271
+ //#region src/modules/tool-execution/application/brokerage/tool-input-digest.ts
272
+ function createToolInputDigest(input) {
273
+ return createStableToolInputDigest(input, createSha256Digest);
274
+ }
275
+ //#endregion
276
+ //#region src/modules/tool-execution/application/brokerage/tool-broker-ports.ts
277
+ var ToolExecutorInputRejected = class extends Error {
278
+ name = "ToolExecutorInputRejected";
279
+ };
280
+ //#endregion
281
+ //#region src/modules/tool-execution/application/brokerage/tool-broker.ts
282
+ var ToolInvocationDenied = class extends Error {
283
+ name = "ToolInvocationDenied";
284
+ };
285
+ function createToolBroker(options) {
286
+ const operations = options.operations ?? createToolOperationLedger();
287
+ const hostTools = new Map(options.hostTools?.map((tool) => [tool.id, tool]) ?? []);
288
+ if (hostTools.size !== (options.hostTools?.length ?? 0)) throw new ToolInvocationDenied("duplicate Host Tool id");
289
+ return { execute: (request) => Effect.gen(function* () {
290
+ const prepared = yield* Effect.try({
291
+ catch: (error) => error,
292
+ try: () => prepareInvocation(options.catalog, hostTools, request)
293
+ });
294
+ const policy = yield* options.policy.current();
295
+ if (policy.revokedToolIds.includes(request.toolId)) return yield* Effect.fail(new ToolInvocationDenied(`tool has been revoked: ${request.toolId}`));
296
+ if (prepared.tool.idempotency === "required" && !request.operationId) return yield* Effect.fail(new ToolInvocationDenied(`tool requires a stable operation id: ${request.toolId}`));
297
+ if (requiresToolApproval(prepared.tool.risk) && !request.operationId) return yield* Effect.fail(new ToolInvocationDenied(`tool approval requires a stable operation id: ${request.toolId}`));
298
+ if (requiresToolApproval(prepared.tool.risk) && !request.approvalId) return yield* Effect.fail(new ToolInvocationDenied(`tool requires trusted approval: ${request.toolId}`));
299
+ const binding = yield* Effect.try({
300
+ catch: (error) => error,
301
+ try: () => createOperationBinding(prepared.authority, prepared.tool, request)
302
+ });
303
+ const context = createExecutionContext(prepared.authority, request, policy.epoch, prepared.tool);
304
+ const replayCompleted = (result) => replay(prepared.tool, request.input, result, context);
305
+ if (request.operationId) {
306
+ const inspected = yield* operations.inspect(request.operationId, binding);
307
+ if (inspected.status === "completed") return yield* replayCompleted(inspected.result);
308
+ if (inspected.status === "blocked") return yield* Effect.fail(new ToolInvocationDenied(`tool operation is fenced: ${inspected.reason}`));
309
+ }
310
+ if (requiresToolApproval(prepared.tool.risk)) {
311
+ if (!(yield* options.approvals.consume({
312
+ agentId: prepared.authority.agentId,
313
+ approvalId: request.approvalId,
314
+ callId: request.callId,
315
+ inputDigest: binding.inputDigest,
316
+ instanceId: prepared.authority.instanceId,
317
+ operationId: request.operationId,
318
+ risk: prepared.tool.risk,
319
+ runId: prepared.authority.runId,
320
+ sessionKey: prepared.authority.sessionKey,
321
+ tenantKey: prepared.authority.tenantKey,
322
+ toolId: request.toolId,
323
+ toolVersion: prepared.tool.version
324
+ }))) return yield* Effect.fail(new ToolInvocationDenied(`tool approval is invalid or already consumed: ${request.toolId}`));
325
+ }
326
+ if (request.operationId) {
327
+ const reservation = yield* operations.begin(request.operationId, binding);
328
+ if (reservation.status === "completed") return yield* replayCompleted(reservation.result);
329
+ if (reservation.status === "blocked") return yield* Effect.fail(new ToolInvocationDenied(`tool operation is fenced: ${reservation.reason}`));
330
+ }
331
+ return yield* Effect.gen(function* () {
332
+ const result = yield* (yield* Effect.try({
333
+ catch: (error) => error,
334
+ try: () => prepared.tool.createExecutor({
335
+ toolId: prepared.tool.id,
336
+ toolVersion: prepared.tool.version
337
+ })
338
+ })).execute(request.input, context);
339
+ if (request.operationId) yield* operations.complete(request.operationId, binding, result);
340
+ return result;
341
+ }).pipe(Effect.catchAll((error) => {
342
+ if (!request.operationId) return Effect.fail(error);
343
+ return (prepared.tool.risk === "observe" || error instanceof ToolExecutorInputRejected ? operations.abort(request.operationId, binding) : operations.requireReconciliation(request.operationId, binding, error instanceof Error ? error.message : String(error))).pipe(Effect.zipRight(Effect.fail(error)));
344
+ }));
345
+ }) };
346
+ }
347
+ function prepareInvocation(catalog, hostTools, request) {
348
+ const authority = resolveInvocationAuthority(request.authority);
349
+ if (!authority.toolGrantSet.toolIds.includes(request.toolId)) throw new ToolInvocationDenied(`tool is not granted for this run: ${request.toolId}`);
350
+ const tool = hostTools.get(request.toolId) ?? catalog.snapshot().tools.find(({ id }) => id === request.toolId);
351
+ if (!tool) throw new ToolInvocationDenied(`tool is not present in the trusted catalog: ${request.toolId}`);
352
+ if (tool.version !== request.version) throw new ToolInvocationDenied(`tool version mismatch for ${request.toolId}: expected ${tool.version}`);
353
+ return {
354
+ authority,
355
+ tool
356
+ };
357
+ }
358
+ function createOperationBinding(authority, tool, request) {
359
+ let inputDigest;
360
+ try {
361
+ inputDigest = createToolInputDigest(request.input);
362
+ } catch (error) {
363
+ if (error instanceof InvalidToolInput) throw new ToolInvocationDenied(`tool input is not stable JSON: ${request.toolId}`);
364
+ throw error;
365
+ }
366
+ return {
367
+ agentId: authority.agentId,
368
+ inputDigest,
369
+ instanceId: authority.instanceId,
370
+ sourceMessageId: authority.sourceMessageId,
371
+ toolId: tool.id,
372
+ toolVersion: tool.version
373
+ };
374
+ }
375
+ function createExecutionContext(authority, request, policyEpoch, tool) {
376
+ return Object.freeze({
377
+ agentId: authority.agentId,
378
+ callId: request.callId,
379
+ instanceId: authority.instanceId,
380
+ ...authority.memory ? { memory: authority.memory } : {},
381
+ ...request.operationId ? { operationId: request.operationId } : {},
382
+ policyEpoch,
383
+ runId: authority.runId,
384
+ sessionKey: authority.sessionKey,
385
+ toolId: tool.id,
386
+ toolVersion: tool.version,
387
+ ...authority.endpointId ? { origin: Object.freeze({
388
+ ...authority.allowedActorOpenIds ? { allowedActorOpenIds: authority.allowedActorOpenIds } : { allowedActorOpenIds: Object.freeze([]) },
389
+ endpointId: authority.endpointId,
390
+ tenantKey: authority.tenantKey,
391
+ ...authority.conversationId ? { conversationId: authority.conversationId } : {}
392
+ }) } : {},
393
+ ...authority.sourceMessageId ? { sourceMessageId: authority.sourceMessageId } : {}
394
+ });
395
+ }
396
+ function replay(tool, input, result, context) {
397
+ if (!tool.replayCompleted) return Effect.succeed(result);
398
+ return Effect.try({
399
+ catch: (error) => error,
400
+ try: () => tool.replayCompleted(input, result, context)
401
+ }).pipe(Effect.flatMap((effect) => effect));
402
+ }
403
+ //#endregion
404
+ //#region src/adapters/pi/skills/pi-skill-tool.ts
405
+ const PI_SKILL_READER_TOOL_NAME = "rivus_read_skill";
406
+ function createPiSkillRuntime(skills) {
407
+ if (skills.length === 0) return Object.freeze({ prompt: "" });
408
+ const skillsById = new Map(skills.map((skill) => [skill.id, skill]));
409
+ const prompt = [
410
+ "Granted Skills are versioned instructions loaded on demand.",
411
+ `Before following a Skill, call ${PI_SKILL_READER_TOOL_NAME} with its exact ID and follow the returned content.`,
412
+ "Granted Skill catalog:",
413
+ ...skills.map((skill) => `- ${skill.id} | ${skill.title} | v${skill.version} | ${skill.digest}`)
414
+ ].join("\n");
415
+ const tool = {
416
+ description: "Read the full versioned instructions for one Skill granted to this Agent Runtime.",
417
+ execute: async (_callId, input) => {
418
+ const skillId = readSkillId(input);
419
+ const skill = skillsById.get(skillId);
420
+ if (!skill) throw new Error(`Skill is not granted: ${skillId}`);
421
+ const details = {
422
+ contentLength: skill.content.length,
423
+ digest: skill.digest,
424
+ skillId: skill.id,
425
+ title: skill.title,
426
+ version: skill.version
427
+ };
428
+ return {
429
+ content: [{
430
+ text: skill.content,
431
+ type: "text"
432
+ }],
433
+ details
434
+ };
435
+ },
436
+ executionMode: "sequential",
437
+ label: "Read granted Skill",
438
+ name: PI_SKILL_READER_TOOL_NAME,
439
+ parameters: Unsafe({
440
+ additionalProperties: false,
441
+ properties: { skillId: {
442
+ description: "Exact Skill ID from the granted Skill catalog.",
443
+ type: "string"
444
+ } },
445
+ required: ["skillId"],
446
+ type: "object"
447
+ }),
448
+ promptSnippet: `${PI_SKILL_READER_TOOL_NAME}: read one granted Skill by exact ID`
449
+ };
450
+ return Object.freeze({
451
+ prompt,
452
+ tool
453
+ });
454
+ }
455
+ function readSkillId(input) {
456
+ if (input === null || typeof input !== "object" || Array.isArray(input) || typeof input.skillId !== "string") throw new Error("Skill reader input requires a string skillId");
457
+ return input.skillId;
458
+ }
459
+ //#endregion
460
+ export { ToolExecutorInputRejected as a, isValidToolOperationTransition as c, InvalidToolInput as d, normalizeStableJson as f, InvalidInvocationAuthority as g, requiresToolApproval as h, createToolBroker as i, recoverInterruptedToolOperation as l, resolveInvocationAuthority as m, createPiSkillRuntime as n, createToolInputDigest as o, createInvocationAuthority as p, ToolInvocationDenied as r, createToolOperationLedger as s, PI_SKILL_READER_TOOL_NAME as t, InvalidStableJson as u };
@@ -0,0 +1,188 @@
1
+ import { o as AgentMemoryAuthority } from "./api.js";
2
+ import { ot as RivusToolRisk, rt as RivusToolGrantSet } from "./api2.js";
3
+ import { Effect } from "effect";
4
+ import { TSchema } from "typebox";
5
+
6
+ //#region src/modules/tool-execution/domain/authority/invocation-authority.d.ts
7
+ interface InvocationAuthorityRef {
8
+ readonly id: string;
9
+ }
10
+ interface InvocationAuthority {
11
+ readonly agentId: string;
12
+ readonly allowedActorOpenIds?: ReadonlyArray<string>;
13
+ readonly conversationId?: string;
14
+ readonly endpointId?: string;
15
+ readonly instanceId: string;
16
+ readonly memory?: AgentMemoryAuthority;
17
+ readonly runId: string;
18
+ readonly sessionKey: string;
19
+ readonly sourceMessageId: string;
20
+ readonly tenantKey: string;
21
+ readonly toolGrantSet: RivusToolGrantSet;
22
+ }
23
+ declare class InvalidInvocationAuthority extends Error {
24
+ readonly name = "InvalidInvocationAuthority";
25
+ }
26
+ //#endregion
27
+ //#region src/modules/tool-execution/domain/authority/tool-risk.d.ts
28
+ declare function requiresToolApproval(risk: RivusToolRisk): boolean;
29
+ //#endregion
30
+ //#region src/modules/tool-execution/domain/operation/tool-operation.d.ts
31
+ interface ToolOperationBinding {
32
+ readonly agentId: string;
33
+ readonly inputDigest: string;
34
+ readonly instanceId: string;
35
+ readonly sourceMessageId: string;
36
+ readonly toolId: string;
37
+ readonly toolVersion: string;
38
+ }
39
+ type ToolOperationState = {
40
+ readonly status: "pending";
41
+ } | {
42
+ readonly result: unknown;
43
+ readonly status: "completed";
44
+ } | {
45
+ readonly reason: string;
46
+ readonly status: "reconciliation-required";
47
+ } | {
48
+ readonly status: "aborted";
49
+ };
50
+ interface ToolOperationReconciliationAction {
51
+ readonly actorId: string;
52
+ readonly at: string;
53
+ readonly note: string;
54
+ }
55
+ interface ToolOperationReconciliation extends ToolOperationReconciliationAction {
56
+ readonly outcome: "applied" | "not-applied";
57
+ }
58
+ interface ToolOperationRecord {
59
+ readonly binding: ToolOperationBinding;
60
+ readonly operationId: string;
61
+ readonly reconciliation?: ToolOperationReconciliation;
62
+ readonly revision: number;
63
+ readonly state: ToolOperationState;
64
+ }
65
+ type ToolOperationReconciliationOutcome = {
66
+ readonly result: unknown;
67
+ readonly status: "applied";
68
+ } | {
69
+ readonly status: "not-applied";
70
+ };
71
+ type ToolOperationBeginResult = {
72
+ readonly status: "acquired";
73
+ } | {
74
+ readonly result: unknown;
75
+ readonly status: "completed";
76
+ } | {
77
+ readonly status: "blocked";
78
+ readonly reason: string;
79
+ };
80
+ type ToolOperationInspectResult = {
81
+ readonly status: "missing";
82
+ } | {
83
+ readonly result: unknown;
84
+ readonly status: "completed";
85
+ } | {
86
+ readonly status: "blocked";
87
+ readonly reason: string;
88
+ };
89
+ //#endregion
90
+ //#region src/modules/tool-execution/application/authority/invocation-authority-registry.d.ts
91
+ declare function createInvocationAuthority(authority: InvocationAuthority): InvocationAuthorityRef;
92
+ //#endregion
93
+ //#region src/modules/tool-execution/application/brokerage/tool-broker-ports.d.ts
94
+ interface AuthorizationPolicyState {
95
+ readonly epoch: number;
96
+ readonly revokedToolIds: ReadonlyArray<string>;
97
+ }
98
+ interface ToolApprovalRequest {
99
+ readonly approvalId: string;
100
+ readonly agentId: string;
101
+ readonly instanceId: string;
102
+ readonly inputDigest: string;
103
+ readonly operationId: string;
104
+ readonly runId: string;
105
+ readonly sessionKey: string;
106
+ readonly tenantKey: string;
107
+ readonly callId: string;
108
+ readonly toolId: string;
109
+ readonly toolVersion: string;
110
+ readonly risk: RivusToolRisk;
111
+ }
112
+ //#endregion
113
+ //#region src/modules/tool-execution/application/brokerage/tool-broker.d.ts
114
+ interface ToolExecutionRequest {
115
+ readonly approvalId?: string;
116
+ readonly authority: InvocationAuthorityRef;
117
+ readonly callId: string;
118
+ readonly input: unknown;
119
+ readonly operationId?: string;
120
+ readonly toolId: string;
121
+ readonly version: string;
122
+ }
123
+ declare class ToolInvocationDenied extends Error {
124
+ readonly name = "ToolInvocationDenied";
125
+ }
126
+ //#endregion
127
+ //#region src/modules/tool-execution/domain/input/stable-tool-input.d.ts
128
+ declare class InvalidStableJson extends Error {
129
+ readonly name: string;
130
+ }
131
+ declare class InvalidToolInput extends InvalidStableJson {
132
+ readonly name = "InvalidToolInput";
133
+ }
134
+ declare function normalizeStableJson(value: unknown): unknown;
135
+ //#endregion
136
+ //#region src/modules/tool-execution/application/brokerage/tool-input-digest.d.ts
137
+ declare function createToolInputDigest(input: unknown): string;
138
+ //#endregion
139
+ //#region src/adapters/pi/tool-execution/pi-tool-definition.d.ts
140
+ type PiToolContent = {
141
+ readonly text: string;
142
+ readonly textSignature?: string;
143
+ readonly type: "text";
144
+ } | {
145
+ readonly data: string;
146
+ readonly mimeType: string;
147
+ readonly type: "image";
148
+ };
149
+ interface PiToolResult<TDetails = unknown> {
150
+ readonly content: PiToolContent[];
151
+ readonly details: TDetails;
152
+ readonly terminate?: boolean;
153
+ }
154
+ interface PiToolDefinition<TDetails = unknown> {
155
+ readonly description: string;
156
+ readonly execute: (toolCallId: string, params: unknown, signal?: AbortSignal, onUpdate?: (result: PiToolResult<TDetails>) => void, context?: unknown) => Promise<PiToolResult<TDetails>>;
157
+ readonly executionMode?: "parallel" | "sequential";
158
+ readonly label: string;
159
+ readonly name: string;
160
+ readonly parameters: TSchema;
161
+ readonly promptGuidelines?: string[];
162
+ readonly promptSnippet?: string;
163
+ }
164
+ //#endregion
165
+ //#region src/adapters/pi/tool-execution/pi-tool-proxy.d.ts
166
+ interface PiToolApprovalRequest {
167
+ readonly agentId: string;
168
+ readonly allowedActorOpenIds: ReadonlyArray<string>;
169
+ readonly approvalId: string;
170
+ readonly callId: string;
171
+ readonly endpointId: string;
172
+ readonly inputDigest: string;
173
+ readonly instanceId: string;
174
+ readonly operationId: string;
175
+ readonly risk: RivusToolRisk;
176
+ readonly runId: string;
177
+ readonly sessionKey: string;
178
+ readonly signal?: AbortSignal;
179
+ readonly sourceMessageId: string;
180
+ readonly tenantKey: string;
181
+ readonly toolId: string;
182
+ readonly toolVersion: string;
183
+ }
184
+ interface PiToolApprovalGateway {
185
+ requestApproval(request: PiToolApprovalRequest): Promise<void>;
186
+ }
187
+ //#endregion
188
+ export { InvalidInvocationAuthority as C, requiresToolApproval as S, InvocationAuthorityRef as T, ToolOperationInspectResult as _, PiToolResult as a, ToolOperationRecord as b, InvalidToolInput as c, ToolInvocationDenied as d, AuthorizationPolicyState as f, ToolOperationBinding as g, ToolOperationBeginResult as h, PiToolDefinition as i, normalizeStableJson as l, createInvocationAuthority as m, PiToolApprovalRequest as n, createToolInputDigest as o, ToolApprovalRequest as p, PiToolContent as r, InvalidStableJson as s, PiToolApprovalGateway as t, ToolExecutionRequest as u, ToolOperationReconciliation as v, InvocationAuthority as w, ToolOperationState as x, ToolOperationReconciliationOutcome as y };