@fungi.computer/shiitake 0.3.1 → 0.5.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.
Files changed (63) hide show
  1. package/README.md +19 -18
  2. package/dist/agent-control.d.ts +24 -19
  3. package/dist/agent-control.js +69 -128
  4. package/dist/client-wire.d.ts +12 -3
  5. package/dist/client-wire.js +33 -8
  6. package/dist/client.d.ts +34 -3
  7. package/dist/client.js +1 -1
  8. package/dist/cloudflare.d.ts +3 -1
  9. package/dist/cloudflare.js +2 -2
  10. package/dist/delegation.d.ts +151 -17
  11. package/dist/delegation.js +174 -41
  12. package/dist/effect.d.ts +1 -1
  13. package/dist/fleet.d.ts +37 -10
  14. package/dist/fleet.js +217 -48
  15. package/dist/http-routes.d.ts +84 -12
  16. package/dist/http-routes.js +15 -1
  17. package/dist/index.d.ts +2 -2
  18. package/dist/internal/admission-door.d.ts +2 -0
  19. package/dist/internal/admission-door.js +9 -2
  20. package/dist/internal/client-boundary.d.ts +10 -0
  21. package/dist/internal/client-boundary.js +10 -0
  22. package/dist/internal/compaction/compaction.js +1 -1
  23. package/dist/internal/contracts.d.ts +2 -0
  24. package/dist/internal/coordinator.d.ts +3 -1
  25. package/dist/internal/coordinator.js +98 -13
  26. package/dist/internal/effect-client.d.ts +3 -1
  27. package/dist/internal/effect-client.js +3 -2
  28. package/dist/internal/effect-contracts.d.ts +6 -2
  29. package/dist/internal/model-acquisition.js +2 -0
  30. package/dist/internal/observation-kernel.d.ts +8 -4
  31. package/dist/internal/observation-kernel.js +44 -9
  32. package/dist/internal/promise-facade.d.ts +1 -1
  33. package/dist/internal/promise-facade.js +1 -1
  34. package/dist/internal/run-scope.js +37 -8
  35. package/dist/internal/runtime-coordinator.d.ts +5 -0
  36. package/dist/internal/runtime-coordinator.js +8 -4
  37. package/dist/internal/runtime-core.d.ts +2 -1
  38. package/dist/internal/runtime-core.js +6 -1
  39. package/dist/internal/session-context.d.ts +1 -1
  40. package/dist/internal/session-context.js +84 -13
  41. package/dist/internal/woodstock/agent-reply.d.ts +7 -2
  42. package/dist/internal/woodstock/agent-reply.js +22 -13
  43. package/dist/internal/woodstock/fleet-store.d.ts +4 -2
  44. package/dist/internal/woodstock/fleet-store.js +70 -6
  45. package/dist/internal/woodstock/index.d.ts +2 -0
  46. package/dist/internal/woodstock/index.js +11 -5
  47. package/dist/internal/woodstock/run-recovery.js +4 -1
  48. package/dist/internal/woodstock/session-entry.d.ts +13 -3
  49. package/dist/internal/woodstock/session-entry.js +1 -0
  50. package/dist/internal/woodstock/session-store.d.ts +4 -0
  51. package/dist/internal/woodstock/session-store.js +26 -19
  52. package/dist/remote-client.js +5 -1
  53. package/dist/testing.d.ts +5 -2
  54. package/dist/testing.js +4 -2
  55. package/docs/api/agent-control.md +18 -12
  56. package/docs/api/client.md +78 -0
  57. package/docs/api/delegation.md +72 -55
  58. package/docs/api/effect.md +5 -0
  59. package/docs/api/fleet.md +23 -23
  60. package/docs/api/http.md +2 -1
  61. package/docs/api/index.md +13 -0
  62. package/docs/api/testing.md +3 -3
  63. package/package.json +9 -8
@@ -70,13 +70,18 @@ declare const StoredSessionEntrySchema: Schema.Union<readonly [Schema.Struct<{
70
70
  readonly kind: Schema.Literal<"command">;
71
71
  readonly meta: Schema.optionalKey<Schema.Codec<import("../../extensions.js").Json, import("../../extensions.js").Json, never, never>>;
72
72
  /** Present only when the host admitted this line as a verified Agent reply. */
73
- readonly reply: Schema.optionalKey<Schema.Struct<{
73
+ readonly reply: Schema.optionalKey<Schema.Union<readonly [Schema.Struct<{
74
74
  readonly commandId: Schema.String;
75
75
  readonly outcome: Schema.Literals<readonly ["completed", "failed", "interrupted", "cancelled", "outcome_unknown"]>;
76
76
  readonly diagnostic: Schema.optionalKey<Schema.String>;
77
77
  readonly agentId: Schema.String;
78
78
  readonly sessionId: Schema.String;
79
- }>>;
79
+ }>, Schema.Struct<{
80
+ readonly outcome: Schema.Literal<"undeliverable">;
81
+ readonly reason: Schema.Literals<readonly ["recipient_offline", "recipient_left"]>;
82
+ readonly agentId: Schema.String;
83
+ readonly sessionId: Schema.optionalKey<Schema.String>;
84
+ }>]>>;
80
85
  readonly delivery: Schema.optionalKey<Schema.Literals<readonly ["steer", "followUp"]>>;
81
86
  readonly requestId: Schema.String;
82
87
  readonly targetWorkId: Schema.optionalKey<Schema.String>;
@@ -357,6 +362,11 @@ export declare function decodeStoredSessionEntry(value: string): Result.Result<{
357
362
  readonly outcome: "completed" | "failed" | "cancelled" | "interrupted" | "outcome_unknown";
358
363
  readonly agentId: string;
359
364
  readonly diagnostic?: string;
365
+ } | {
366
+ readonly reason: "recipient_offline" | "recipient_left";
367
+ readonly outcome: "undeliverable";
368
+ readonly agentId: string;
369
+ readonly sessionId?: string;
360
370
  };
361
371
  readonly targetWorkId?: string;
362
372
  } | {
@@ -513,8 +523,8 @@ export declare function decodeStoredSessionEntry(value: string): Result.Result<{
513
523
  readonly workId: string;
514
524
  readonly result: "failed";
515
525
  readonly trigger: "manual" | "threshold" | "overflow";
516
- readonly usage?: Usage;
517
526
  readonly diagnostic?: string;
527
+ readonly usage?: Usage;
518
528
  } | {
519
529
  readonly kind: "compaction_notice";
520
530
  readonly workId: string;
@@ -147,6 +147,7 @@ const assistantMessage = Schema.Struct({
147
147
  data: Schema.optionalKey(jsonValue),
148
148
  })),
149
149
  errorMessage: Schema.optionalKey(Schema.String),
150
+ providerError: Schema.optionalKey(Schema.String),
150
151
  rawStopReason: Schema.optionalKey(Schema.String),
151
152
  providerThinkingLevel: Schema.optionalKey(Schema.String),
152
153
  endTurn: Schema.optionalKey(Schema.Boolean),
@@ -254,6 +254,10 @@ export declare function readActiveToolForWork(owner: SqliteOwner, sessionId: str
254
254
  export declare function createStoredSession(owner: SqliteOwner, requestId: string,
255
255
  /** Refuses a new Session under storage pressure; replays skip it. */
256
256
  admitNew: () => void): string;
257
+ /** Reserve a Session while the caller owns the enclosing SQLite transaction. */
258
+ export declare function createStoredSessionWithinTransaction(owner: SqliteOwner, requestId: string,
259
+ /** Refuses a new Session under storage pressure; replays skip it. */
260
+ admitNew: () => void): string;
257
261
  /**
258
262
  * Permanently remove one idle Session: its entries, command admissions,
259
263
  * creation receipt and inbox row, so a retried creation request reserves a
@@ -790,23 +790,27 @@ function ensureSession(owner, sessionId) {
790
790
  export function createStoredSession(owner, requestId,
791
791
  /** Refuses a new Session under storage pressure; replays skip it. */
792
792
  admitNew) {
793
- return owner.transactionSync(() => {
794
- const existing = owner.sql
795
- .exec("SELECT session_id FROM session_creation_receipts WHERE request_id = ?", requestId)
796
- .toArray();
797
- const first = existing[0];
798
- if (first !== undefined) {
799
- const decoded = decodeSessionCreationReceiptRow(first);
800
- if (decoded._tag === "Failure")
801
- throw unavailable("Session creation receipt is invalid");
802
- return decoded.success.session_id;
803
- }
804
- admitNew();
805
- const sessionId = sessionIds.session.generate();
806
- ensureSession(owner, sessionId);
807
- owner.sql.exec("INSERT INTO session_creation_receipts (request_id, session_id) VALUES (?, ?)", requestId, sessionId);
808
- return sessionId;
809
- });
793
+ return owner.transactionSync(() => createStoredSessionWithinTransaction(owner, requestId, admitNew));
794
+ }
795
+ /** Reserve a Session while the caller owns the enclosing SQLite transaction. */
796
+ export function createStoredSessionWithinTransaction(owner, requestId,
797
+ /** Refuses a new Session under storage pressure; replays skip it. */
798
+ admitNew) {
799
+ const existing = owner.sql
800
+ .exec("SELECT session_id FROM session_creation_receipts WHERE request_id = ?", requestId)
801
+ .toArray();
802
+ const first = existing[0];
803
+ if (first !== undefined) {
804
+ const decoded = decodeSessionCreationReceiptRow(first);
805
+ if (decoded._tag === "Failure")
806
+ throw unavailable("Session creation receipt is invalid");
807
+ return decoded.success.session_id;
808
+ }
809
+ admitNew();
810
+ const sessionId = sessionIds.session.generate();
811
+ ensureSession(owner, sessionId);
812
+ owner.sql.exec("INSERT INTO session_creation_receipts (request_id, session_id) VALUES (?, ?)", requestId, sessionId);
813
+ return sessionId;
810
814
  }
811
815
  /**
812
816
  * Permanently remove one idle Session: its entries, command admissions,
@@ -2280,9 +2284,12 @@ reply) {
2280
2284
  function sameReply(left, right) {
2281
2285
  return (left?.agentId === right?.agentId &&
2282
2286
  left?.sessionId === right?.sessionId &&
2283
- left?.commandId === right?.commandId &&
2284
2287
  left?.outcome === right?.outcome &&
2285
- left?.diagnostic === right?.diagnostic);
2288
+ (left?.outcome === "undeliverable"
2289
+ ? right?.outcome === "undeliverable" && left.reason === right.reason
2290
+ : right?.outcome !== "undeliverable" &&
2291
+ left?.commandId === right?.commandId &&
2292
+ left?.diagnostic === right?.diagnostic));
2286
2293
  }
2287
2294
  /**
2288
2295
  * Write one decoded admission (a prompt or a compaction request) and its one
@@ -10,7 +10,7 @@ import * as Schema from "effect/Schema";
10
10
  import * as Scope from "effect/Scope";
11
11
  import * as Sink from "effect/Sink";
12
12
  import * as Stream from "effect/Stream";
13
- import { parseAccepted, parseWithdrawResult, parseCancelResult, parseLatestPendingPrompt, parseForkedSession, parseCreatedSession, parseDeletedSession, parseExtensionOutput, parseExtensionStatus, parseExtensionStatuses, parseSessionFrame, parseSessionSnapshot, parseSessionSummaryPage, parseShiitakeError, } from "./client-wire.js";
13
+ import { parseAccepted, parseCommandSettlement, parseWithdrawResult, parseCancelResult, parseLatestPendingPrompt, parseForkedSession, parseCreatedSession, parseDeletedSession, parseExtensionOutput, parseExtensionStatus, parseExtensionStatuses, parseSessionFrame, parseSessionSnapshot, parseSessionSummaryPage, parseShiitakeError, } from "./client-wire.js";
14
14
  import { ShiitakeError } from "./errors.js";
15
15
  import { decodeClientReadOptions, decodeClientSessionCreationRequestId, decodeClientPageCursor, decodeClientSessionId, decodeClientSubscribeOptions, } from "./internal/client-boundary.js";
16
16
  import { toPromiseAgent } from "./internal/effect-client.js";
@@ -248,6 +248,10 @@ function makeRemoteEffectAgent(options) {
248
248
  params.set("includeSandboxFailures", "true");
249
249
  return request((signal) => fetch(`${addressedUrl}?${params.toString()}`, { signal }), parseSessionSnapshot, "Session read");
250
250
  })),
251
+ readSettlement: (commandId, timeoutMs = 0) => ensureOpen.pipe(Effect.andThen(request((signal) => fetch(`${addressedUrl}/settlement?${new URLSearchParams({
252
+ commandId,
253
+ timeoutMs: String(timeoutMs),
254
+ }).toString()}`, { signal }), parseCommandSettlement, "Command settlement"))),
251
255
  subscribe: (input) => Stream.unwrap(ensureOpen.pipe(Effect.andThen(Effect.try({
252
256
  try: () => decodeClientSubscribeOptions(input),
253
257
  catch: (error) => error instanceof ShiitakeError
package/dist/testing.d.ts CHANGED
@@ -40,8 +40,11 @@ export type MemoryHost = Readonly<{
40
40
  agent: ShiitakeOwnerAgent;
41
41
  /** Invoke one canonical reconciliation tick; no timer runs in the background. */
42
42
  reconcile: () => Promise<void>;
43
- /** Drain pending Agent work with a 1–1,000 tick budget (default 1,000). */
44
- settle: (sessionId: string, maxTicks?: number) => Promise<SessionSnapshot>;
43
+ /** Drain pending Agent work with a 1–1,000 tick budget (default 1,000).
44
+ * The optional test hook runs after pending work ends, before the snapshot
45
+ * context read, so load tests can end a timed turn at the terminal.
46
+ */
47
+ settle: (sessionId: string, maxTicks?: number, beforeRead?: () => Promise<void>) => Promise<SessionSnapshot>;
45
48
  /** Close the Agent and only the database owned by this helper. */
46
49
  close: () => Promise<void>;
47
50
  }>;
package/dist/testing.js CHANGED
@@ -176,12 +176,14 @@ export async function memoryHost(options = {}) {
176
176
  return {
177
177
  agent,
178
178
  reconcile: async () => requireBound().reconcile(),
179
- settle: async (sessionId, maxTicks) => {
179
+ settle: async (sessionId, maxTicks, beforeRead) => {
180
180
  const budget = settlementBudgetSchema.parse(maxTicks);
181
181
  for (let tick = 0; tick < budget; tick += 1) {
182
182
  const host = requireBound();
183
- if (!(await host.pendingWork()).pending)
183
+ if (!(await host.pendingWork()).pending) {
184
+ await beforeRead?.();
184
185
  return agent.session(sessionId).read();
186
+ }
185
187
  await host.reconcile();
186
188
  }
187
189
  throw new Error(`Memory host did not settle within ${String(budget)} reconciliation ticks`);
@@ -219,7 +219,12 @@ Host-only identity and admitted command metadata for one delegated send.
219
219
  ```ts
220
220
  type AgentControlDirectory = Readonly<{
221
221
  list: (signal, options?) => Promise<readonly AgentControlAgent[]>;
222
- send?: (input, sourceSessionId, signal, invocation?) => Promise<Accepted>;
222
+ send?: (
223
+ input,
224
+ sourceSessionId,
225
+ signal,
226
+ invocation?,
227
+ ) => Promise<Accepted | Held>;
223
228
  recall?: (input, sourceSessionId, signal) => Promise<CancelResult>;
224
229
  create?: (input, signal) => Promise<AgentControlAgent>;
225
230
  setModel?: (input, signal) => Promise<void>;
@@ -262,10 +267,10 @@ report back, its store predates the current schema, or the Agent is archived.
262
267
 
263
268
  ## Functions
264
269
 
265
- ### waitForAgentTerminal()
270
+ ### waitForAgentSettlement()
266
271
 
267
272
  ```ts
268
- function waitForAgentTerminal(
273
+ function waitForAgentSettlement(
269
274
  session,
270
275
  commandId,
271
276
  timeoutMs,
@@ -273,16 +278,16 @@ function waitForAgentTerminal(
273
278
  startedAt?,
274
279
  ): Promise<
275
280
  Readonly<{
276
- commandId: string;
277
- outcome: "completed" | "failed" | "cancelled" | "interrupted";
278
- sequence: number;
279
- diagnostic: string | null;
280
- meta?: Json;
281
+ acceptedSender: string | null;
282
+ terminal: SessionTerminal;
283
+ content: string;
284
+ usage: readonly Pick<AssistantMessage, "model" | "provider" | "usage">[];
285
+ toolCalls: number;
281
286
  }>
282
287
  >;
283
288
  ```
284
289
 
285
- Observe one durable terminal; timeout or abort closes observation, not the work.
290
+ Await one exact durable terminal without opening a transcript observation.
286
291
 
287
292
  #### Parameters
288
293
 
@@ -296,9 +301,10 @@ Observe one durable terminal; timeout or abort closes observation, not the work.
296
301
 
297
302
  #### Returns
298
303
 
299
- `Promise`\<`Readonly`\<\{ `commandId`: `string`; `outcome`: `"completed"` \|
300
- `"failed"` \| `"cancelled"` \| `"interrupted"`; `sequence`: `number`;
301
- `diagnostic`: `string` \| `null`; `meta?`: [`Json`](extensions.md#json); \}\>\>
304
+ `Promise`\<`Readonly`\<\{ `acceptedSender`: `string` \| `null`; `terminal`:
305
+ [`SessionTerminal`](client.md#sessionterminal); `content`: `string`; `usage`:
306
+ readonly `Pick`\<`AssistantMessage`, `"model"` \| `"provider"` \| `"usage"`\>[];
307
+ `toolCalls`: `number`; \}\>\>
302
308
 
303
309
  ---
304
310
 
@@ -23,6 +23,30 @@ Semantic acknowledgement returned after one durable acceptance commit.
23
23
 
24
24
  ---
25
25
 
26
+ ### Held
27
+
28
+ ```ts
29
+ type Held = Readonly<{
30
+ status: "held";
31
+ reason: "recipient_offline";
32
+ message: "waiting: recipient offline";
33
+ }>;
34
+ ```
35
+
36
+ Durable relay custody, not acceptance of a command by the recipient.
37
+
38
+ ---
39
+
40
+ ### DelegationReceipt
41
+
42
+ ```ts
43
+ type DelegationReceipt = Accepted | Held;
44
+ ```
45
+
46
+ A delegation send can be accepted by the Agent or held by its relay.
47
+
48
+ ---
49
+
26
50
  ### TooLate
27
51
 
28
52
  ```ts
@@ -581,6 +605,10 @@ Bounded Session baseline at one opaque owner cursor.
581
605
 
582
606
  ```ts
583
607
  type SessionFrame =
608
+ | Readonly<{
609
+ kind: "activity";
610
+ activity: SessionActivity;
611
+ }>
584
612
  | Readonly<{
585
613
  kind: "tool_output";
586
614
  toolOutput: readonly SessionToolOutput[];
@@ -686,6 +714,10 @@ type ShiitakeSession = Readonly<{
686
714
  set: (preference) => Promise<void>;
687
715
  }>;
688
716
  read: (input?) => Promise<SessionSnapshot>;
717
+ readSettlement: (
718
+ commandId,
719
+ options?,
720
+ ) => Promise<CommandSettlement | undefined>;
689
721
  subscribe: (input) => AsyncIterable<SessionFrame>;
690
722
  watch: (input?) => Promise<SessionWatch>;
691
723
  }>;
@@ -924,8 +956,48 @@ const AcceptedSchema: Schema.Codec<Accepted>;
924
956
 
925
957
  Decode a durable command acceptance value at an RPC boundary.
926
958
 
959
+ ---
960
+
961
+ ### HeldSchema
962
+
963
+ ```ts
964
+ const HeldSchema: Schema.Codec<Held>;
965
+ ```
966
+
967
+ Parse the relay's custody acknowledgment without implying Agent acceptance.
968
+
969
+ ---
970
+
971
+ ### DelegationReceiptSchema
972
+
973
+ ```ts
974
+ const DelegationReceiptSchema: Schema.Codec<DelegationReceipt>;
975
+ ```
976
+
977
+ A delegated send is accepted by its owner or held in durable mail custody.
978
+
927
979
  ## Functions
928
980
 
981
+ ### parseDelegationReceipt()
982
+
983
+ ```ts
984
+ function parseDelegationReceipt(value): DelegationReceipt;
985
+ ```
986
+
987
+ Decode one delegated send's acceptance or durable-custody result.
988
+
989
+ #### Parameters
990
+
991
+ | Parameter | Type |
992
+ | --------- | -------- |
993
+ | `value` | `string` |
994
+
995
+ #### Returns
996
+
997
+ [`DelegationReceipt`](#delegationreceipt)
998
+
999
+ ---
1000
+
929
1001
  ### parseWithdrawResult()
930
1002
 
931
1003
  ```ts
@@ -1145,6 +1217,12 @@ Connect to a remotely hosted Shiitake agent.
1145
1217
 
1146
1218
  ## References
1147
1219
 
1220
+ ### CommandSettlement
1221
+
1222
+ Re-exports [CommandSettlement](index.md#commandsettlement)
1223
+
1224
+ ---
1225
+
1148
1226
  ### parseForkedSession
1149
1227
 
1150
1228
  Re-exports [parseForkedSession](index.md#parseforkedsession)
@@ -24,9 +24,9 @@ new AgentDelegation(deps): AgentDelegation;
24
24
 
25
25
  ###### Parameters
26
26
 
27
- | Parameter | Type |
28
- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
29
- | `deps` | `Readonly`\<\{ `storage`: `WatchdogSqliteOwner`; `expiresAt`: () => `number`; `identity`: () => \| [`DelegationIdentity`](#delegationidentity) \| `null` \| `Promise`\<[`DelegationIdentity`](#delegationidentity) \| `null`\>; `directory`: () => [`AgentControlDirectory`](agent-control.md#agentcontroldirectory); `deliver`: (`mail`) => `Promise`\<[`Accepted`](client.md#accepted)\>; `prepare`: (`mail`) => `Promise`\<`void`\>; `accept`: (`mail`, `reply?`) => `Promise`\<[`Accepted`](client.md#accepted)\>; \}\> |
27
+ | Parameter | Type |
28
+ | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
29
+ | `deps` | `Readonly`\<\{ `storage`: `WatchdogSqliteOwner`; `expiresAt`: () => `number`; `identity`: () => \| [`DelegationIdentity`](#delegationidentity) \| `null` \| `Promise`\<[`DelegationIdentity`](#delegationidentity) \| `null`\>; `directory`: () => [`AgentControlDirectory`](agent-control.md#agentcontroldirectory); `deliver`: (`mail`) => `Promise`\<[`DelegationReceipt`](client.md#delegationreceipt)\>; `prepare`: (`mail`) => `Promise`\<`void`\>; `accept`: (`mail`, `reply?`) => `Promise`\<[`Accepted`](client.md#accepted)\>; \}\> |
30
30
 
31
31
  ###### Returns
32
32
 
@@ -79,10 +79,7 @@ send(
79
79
  sourceSessionId,
80
80
  signal,
81
81
  invocation?
82
- ): Promise<Readonly<{
83
- status: "accepted";
84
- commandId: string;
85
- }>>;
82
+ ): Promise<DelegationReceipt>;
86
83
  ```
87
84
 
88
85
  Delegate work to an in-scope Agent: steer its Session, or start fleet
@@ -99,7 +96,7 @@ correspondence.
99
96
 
100
97
  ###### Returns
101
98
 
102
- `Promise`\<`Readonly`\<\{ `status`: `"accepted"`; `commandId`: `string`; \}\>\>
99
+ `Promise`\<[`DelegationReceipt`](client.md#delegationreceipt)\>
103
100
 
104
101
  ##### recall()
105
102
 
@@ -205,13 +202,10 @@ new AgentMail(deps): AgentMail;
205
202
  ##### send()
206
203
 
207
204
  ```ts
208
- send(mail): Promise<Readonly<{
209
- status: "accepted";
210
- commandId: string;
211
- }>>;
205
+ send(mail): Promise<DelegationReceipt>;
212
206
  ```
213
207
 
214
- Submit one mail and return the recipient's Accepted receipt.
208
+ Submit one mail and return recipient acceptance or relay-held custody.
215
209
 
216
210
  ###### Parameters
217
211
 
@@ -221,7 +215,7 @@ Submit one mail and return the recipient's Accepted receipt.
221
215
 
222
216
  ###### Returns
223
217
 
224
- `Promise`\<`Readonly`\<\{ `status`: `"accepted"`; `commandId`: `string`; \}\>\>
218
+ `Promise`\<[`DelegationReceipt`](client.md#delegationreceipt)\>
225
219
 
226
220
  ##### mailRoom()
227
221
 
@@ -297,11 +291,11 @@ link routes Agent work without owning Shiitake's grammar.
297
291
 
298
292
  #### Type Declaration
299
293
 
300
- | Name | Type | Description |
301
- | ------------------- | ------------------------------------------------------------------- | ----------------------------------------------------------------------- |
302
- | `sessionCreation()` | (`body`) => \| `Readonly`\<\{ `requestId`: `string`; \}\> \| `null` | The Session-creation intent, or null when the body is not one. |
303
- | `settlement()` | (`encoded`) => [`CommandSettlement`](index.md#commandsettlement) | One serialized settlement from a hosted or machine-homed Agent. |
304
- | `accepted()` | (`receipt`) => `void` | Throws unless an acknowledgment carries a well-formed Accepted receipt. |
294
+ | Name | Type | Description |
295
+ | ------------------- | ------------------------------------------------------------------- | -------------------------------------------------------------------------- |
296
+ | `sessionCreation()` | (`body`) => \| `Readonly`\<\{ `requestId`: `string`; \}\> \| `null` | The Session-creation intent, or null when the body is not one. |
297
+ | `settlement()` | (`encoded`) => [`CommandSettlement`](index.md#commandsettlement) | One serialized settlement from a hosted or machine-homed Agent. |
298
+ | `accepted()` | (`receipt`) => `void` | Throws unless an acknowledgment carries a valid acceptance or Held result. |
305
299
 
306
300
  ## Functions
307
301
 
@@ -324,11 +318,15 @@ function agentMailRoute(namespace, replySettlement): PostRoute<AgentMailAddress,
324
318
  content: string;
325
319
  createdAt: number;
326
320
  meta?: Json | undefined;
327
- reply?: {
321
+ reply?: | {
328
322
  commandId: string;
329
323
  outcome: "completed" | "failed" | "cancelled" | "interrupted" | "outcome_unknown";
330
324
  diagnostic?: string;
331
- };
325
+ }
326
+ | {
327
+ outcome: "undeliverable";
328
+ reason: "recipient_offline" | "recipient_left";
329
+ };
332
330
  }, {
333
331
  key: string;
334
332
  to: {
@@ -345,11 +343,15 @@ function agentMailRoute(namespace, replySettlement): PostRoute<AgentMailAddress,
345
343
  content: string;
346
344
  createdAt: number;
347
345
  meta?: Json | undefined;
348
- reply?: {
346
+ reply?: | {
349
347
  commandId: string;
350
348
  outcome: "completed" | "failed" | "cancelled" | "interrupted" | "outcome_unknown";
351
349
  diagnostic?: string;
352
- };
350
+ }
351
+ | {
352
+ outcome: "undeliverable";
353
+ reason: "recipient_offline" | "recipient_left";
354
+ };
353
355
  }, AgentMailAddress, {
354
356
  key: string;
355
357
  to: {
@@ -366,11 +368,15 @@ function agentMailRoute(namespace, replySettlement): PostRoute<AgentMailAddress,
366
368
  content: string;
367
369
  createdAt: number;
368
370
  meta?: Json | undefined;
369
- reply?: {
371
+ reply?: | {
370
372
  commandId: string;
371
373
  outcome: "completed" | "failed" | "cancelled" | "interrupted" | "outcome_unknown";
372
374
  diagnostic?: string;
373
- };
375
+ }
376
+ | {
377
+ outcome: "undeliverable";
378
+ reason: "recipient_offline" | "recipient_left";
379
+ };
374
380
  }, {
375
381
  key: string;
376
382
  to: {
@@ -387,13 +393,18 @@ function agentMailRoute(namespace, replySettlement): PostRoute<AgentMailAddress,
387
393
  content: string;
388
394
  createdAt: number;
389
395
  meta?: Json | undefined;
390
- reply?: {
396
+ reply?: | {
391
397
  commandId: string;
392
398
  outcome: "completed" | "failed" | "cancelled" | "interrupted" | "outcome_unknown";
393
399
  diagnostic?: string;
394
- };
400
+ }
401
+ | {
402
+ outcome: "undeliverable";
403
+ reason: "recipient_offline" | "recipient_left";
404
+ };
395
405
  }> & Omit<Readonly<{
396
406
  addressKind: string;
407
+ deadlineMs?: number;
397
408
  address: Codec<unknown, unknown>;
398
409
  event: Codec<unknown, unknown>;
399
410
  encodeEnvelope: (envelope) => object;
@@ -432,35 +443,41 @@ retries.
432
443
  `agentId`: `string`; `sessionId`: `string`; \}; `from`: \{ `kind`: `"agent"`;
433
444
  `agentId`: `string`; `sessionId`: `string`; \}; `replyTo`: readonly `object`[];
434
445
  `content`: `string`; `createdAt`: `number`; `meta?`: Json \| undefined;
435
- `reply?`: \{ `commandId`: `string`; `outcome`: `"completed"` \| `"failed"` \|
446
+ `reply?`: \| \{ `commandId`: `string`; `outcome`: `"completed"` \| `"failed"` \|
447
+ `"cancelled"` \| `"interrupted"` \| `"outcome_unknown"`; `diagnostic?`:
448
+ `string`; \} \| \{ `outcome`: `"undeliverable"`; `reason`: `"recipient_offline"`
449
+ \| `"recipient_left"`; \}; \}, \{ `key`: `string`; `to`: \{ `kind`: `"agent"`;
450
+ `agentId`: `string`; `sessionId`: `string`; \}; `from`: \{ `kind`: `"agent"`;
451
+ `agentId`: `string`; `sessionId`: `string`; \}; `replyTo`: readonly `object`[];
452
+ `content`: `string`; `createdAt`: `number`; `meta?`: Json \| undefined;
453
+ `reply?`: \| \{ `commandId`: `string`; `outcome`: `"completed"` \| `"failed"` \|
436
454
  `"cancelled"` \| `"interrupted"` \| `"outcome_unknown"`; `diagnostic?`:
437
- `string`; \}; \}, \{ `key`: `string`; `to`: \{ `kind`: `"agent"`; `agentId`:
438
- `string`; `sessionId`: `string`; \}; `from`: \{ `kind`: `"agent"`; `agentId`:
439
- `string`; `sessionId`: `string`; \}; `replyTo`: readonly `object`[]; `content`:
440
- `string`; `createdAt`: `number`; `meta?`: Json \| undefined; `reply?`: \{
441
- `commandId`: `string`; `outcome`: `"completed"` \| `"failed"` \| `"cancelled"`
442
- \| `"interrupted"` \| `"outcome_unknown"`; `diagnostic?`: `string`; \}; \},
443
- `AgentMailAddress`, \{ `key`: `string`; `to`: \{ `kind`: `"agent"`; `agentId`:
444
- `string`; `sessionId`: `string`; \}; `from`: \{ `kind`: `"agent"`; `agentId`:
445
- `string`; `sessionId`: `string`; \}; `replyTo`: readonly `object`[]; `content`:
446
- `string`; `createdAt`: `number`; `meta?`: Json \| undefined; `reply?`: \{
447
- `commandId`: `string`; `outcome`: `"completed"` \| `"failed"` \| `"cancelled"`
448
- \| `"interrupted"` \| `"outcome_unknown"`; `diagnostic?`: `string`; \}; \}, \{
449
- `key`: `string`; `to`: \{ `kind`: `"agent"`; `agentId`: `string`; `sessionId`:
450
- `string`; \}; `from`: \{ `kind`: `"agent"`; `agentId`: `string`; `sessionId`:
451
- `string`; \}; `replyTo`: readonly `object`[]; `content`: `string`; `createdAt`:
452
- `number`; `meta?`: Json \| undefined; `reply?`: \{ `commandId`: `string`;
453
- `outcome`: `"completed"` \| `"failed"` \| `"cancelled"` \| `"interrupted"` \|
454
- `"outcome_unknown"`; `diagnostic?`: `string`; \}; \}\> & `Omit`\<`Readonly`\<\{
455
- `addressKind`: `string`; `address`: `Codec`\<`unknown`, `unknown`\>; `event`:
456
- `Codec`\<`unknown`, `unknown`\>; `encodeEnvelope`: (`envelope`) => `object`;
457
- `parseDelivery`: (`envelope`) => `object`; `prepareEnvelope?`: (`envelope`,
458
- `signal`) => `Promise`\<\{ `key`: `string`; `kind`: `string`; `address`:
459
- `unknown`; `event`: `unknown`; \}\>; `recordDelivered?`: (`envelope`) => `void`;
460
- `nameOf`: (`envelope`) => `string`; `namespace`: `Readonly`\<\{ `getByName`:
461
- (`name`) => `Readonly`\<\{ `deliver`: (`envelope`) => `Promise`\<...\>; \}\>;
462
- \}\>; `recordCursor?`: (`envelope`, `cursor`) => `void`; `recordRefused?`:
463
- (`envelope`) => `void`; \}\>, `"event"` \| `"address"`\>
455
+ `string`; \} \| \{ `outcome`: `"undeliverable"`; `reason`: `"recipient_offline"`
456
+ \| `"recipient_left"`; \}; \}, `AgentMailAddress`, \{ `key`: `string`; `to`: \{
457
+ `kind`: `"agent"`; `agentId`: `string`; `sessionId`: `string`; \}; `from`: \{
458
+ `kind`: `"agent"`; `agentId`: `string`; `sessionId`: `string`; \}; `replyTo`:
459
+ readonly `object`[]; `content`: `string`; `createdAt`: `number`; `meta?`: Json
460
+ \| undefined; `reply?`: \| \{ `commandId`: `string`; `outcome`: `"completed"` \|
461
+ `"failed"` \| `"cancelled"` \| `"interrupted"` \| `"outcome_unknown"`;
462
+ `diagnostic?`: `string`; \} \| \{ `outcome`: `"undeliverable"`; `reason`:
463
+ `"recipient_offline"` \| `"recipient_left"`; \}; \}, \{ `key`: `string`; `to`:
464
+ \{ `kind`: `"agent"`; `agentId`: `string`; `sessionId`: `string`; \}; `from`: \{
465
+ `kind`: `"agent"`; `agentId`: `string`; `sessionId`: `string`; \}; `replyTo`:
466
+ readonly `object`[]; `content`: `string`; `createdAt`: `number`; `meta?`: Json
467
+ \| undefined; `reply?`: \| \{ `commandId`: `string`; `outcome`: `"completed"` \|
468
+ `"failed"` \| `"cancelled"` \| `"interrupted"` \| `"outcome_unknown"`;
469
+ `diagnostic?`: `string`; \} \| \{ `outcome`: `"undeliverable"`; `reason`:
470
+ `"recipient_offline"` \| `"recipient_left"`; \}; \}\> & `Omit`\<`Readonly`\<\{
471
+ `addressKind`: `string`; `deadlineMs?`: `number`; `address`: `Codec`\<`unknown`,
472
+ `unknown`\>; `event`: `Codec`\<`unknown`, `unknown`\>; `encodeEnvelope`:
473
+ (`envelope`) => `object`; `parseDelivery`: (`envelope`) => `object`;
474
+ `prepareEnvelope?`: (`envelope`, `signal`) => `Promise`\<\{ `key`: `string`;
475
+ `kind`: `string`; `address`: `unknown`; `event`: `unknown`; \}\>;
476
+ `recordDelivered?`: (`envelope`) => `void`; `nameOf`: (`envelope`) => `string`;
477
+ `namespace`: `Readonly`\<\{ `getByName`: (`name`) => `Readonly`\<\{ `deliver`:
478
+ (`envelope`) => `Promise`\<...\>; \}\>; \}\>; `recordCursor?`: (`envelope`,
479
+ `cursor`) => `void`; `recordRefused?`: (`envelope`) => `void`; \}\>, `"event"`
480
+ \| `"address"`\>
464
481
 
465
482
  ---
466
483
 
@@ -36,6 +36,7 @@ type ModelAcquisitionEffect = Readonly<{
36
36
  retryAfterMs?: (message) => number | undefined;
37
37
  retryable: (message) => boolean;
38
38
  failureReason?: (message) => string | undefined;
39
+ providerError?: (message) => string | undefined;
39
40
  release: Effect.Effect<void, ShiitakeError>;
40
41
  }>;
41
42
  ```
@@ -322,6 +323,10 @@ type ShiitakeEffectSession = Readonly<{
322
323
  set: (preference) => Effect.Effect<void, ShiitakeError>;
323
324
  }>;
324
325
  read: (input?) => Effect.Effect<SessionSnapshot, ShiitakeError>;
326
+ readSettlement: (
327
+ commandId,
328
+ timeoutMs?,
329
+ ) => Effect.Effect<CommandSettlement | undefined, ShiitakeError>;
325
330
  subscribe: (input) => Stream.Stream<SessionFrame, ShiitakeError>;
326
331
  watch: (input?) => Effect.Effect<ShiitakeEffectWatch, ShiitakeError>;
327
332
  }>;