@fungi.computer/shiitake 0.1.0 → 0.3.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 (112) hide show
  1. package/README.md +155 -34
  2. package/dist/agent-control.d.ts +78 -11
  3. package/dist/agent-control.js +273 -70
  4. package/dist/client-entry.d.ts +15 -8
  5. package/dist/client-entry.js +7 -5
  6. package/dist/client-wire.d.ts +24 -8
  7. package/dist/client-wire.js +53 -11
  8. package/dist/client.d.ts +56 -11
  9. package/dist/client.js +1 -1
  10. package/dist/cloudflare.d.ts +42 -23
  11. package/dist/cloudflare.js +76 -54
  12. package/dist/cold-sessions.d.ts +28 -0
  13. package/dist/cold-sessions.js +1 -0
  14. package/dist/delegation.d.ts +214 -0
  15. package/dist/delegation.js +319 -0
  16. package/dist/effect.d.ts +1 -1
  17. package/dist/errors.d.ts +2 -2
  18. package/dist/errors.js +2 -2
  19. package/dist/extension-contract.d.ts +10 -2
  20. package/dist/extensions.d.ts +6 -2
  21. package/dist/fleet.d.ts +52 -34
  22. package/dist/fleet.js +101 -63
  23. package/dist/hosted.js +1 -0
  24. package/dist/http-routes.d.ts +106 -22
  25. package/dist/http-routes.js +18 -1
  26. package/dist/index.d.ts +3 -2
  27. package/dist/internal/accepted-run-executor.d.ts +5 -0
  28. package/dist/internal/accepted-run-executor.js +10 -4
  29. package/dist/internal/admission-door.d.ts +3 -0
  30. package/dist/internal/admission-door.js +12 -2
  31. package/dist/internal/client-boundary.js +7 -1
  32. package/dist/internal/compaction/compaction-slot.d.ts +36 -0
  33. package/dist/internal/compaction/compaction-slot.js +41 -0
  34. package/dist/internal/compaction/compaction.d.ts +7 -4
  35. package/dist/internal/compaction/compaction.js +59 -30
  36. package/dist/internal/compaction/session-compaction.d.ts +8 -16
  37. package/dist/internal/compaction/session-compaction.js +358 -119
  38. package/dist/internal/compaction/settings.js +5 -0
  39. package/dist/internal/compaction/utils.d.ts +19 -16
  40. package/dist/internal/compaction/utils.js +30 -84
  41. package/dist/internal/contracts.d.ts +40 -13
  42. package/dist/internal/coordinator.js +28 -10
  43. package/dist/internal/effect-client.d.ts +4 -2
  44. package/dist/internal/effect-client.js +29 -0
  45. package/dist/internal/effect-contracts.d.ts +17 -4
  46. package/dist/internal/extension-runtime.d.ts +5 -0
  47. package/dist/internal/extension-runtime.js +184 -89
  48. package/dist/internal/host-meta.d.ts +7 -0
  49. package/dist/internal/model-acquisition.js +7 -1
  50. package/dist/internal/model-preference.d.ts +2 -0
  51. package/dist/internal/model-preference.js +2 -1
  52. package/dist/internal/promise-facade.js +4 -16
  53. package/dist/internal/run-failure-reason.d.ts +10 -0
  54. package/dist/internal/run-failure-reason.js +19 -0
  55. package/dist/internal/run-scope.d.ts +4 -1
  56. package/dist/internal/run-scope.js +38 -5
  57. package/dist/internal/runtime-coordinator.d.ts +2 -1
  58. package/dist/internal/runtime-coordinator.js +65 -4
  59. package/dist/internal/runtime-core.js +1 -0
  60. package/dist/internal/runtime-reconciliation.js +42 -6
  61. package/dist/internal/session-context.d.ts +1 -2
  62. package/dist/internal/session-context.js +8 -30
  63. package/dist/internal/session-status.d.ts +2 -1
  64. package/dist/internal/session-status.js +4 -1
  65. package/dist/internal/woodstock/client-projection.d.ts +6 -5
  66. package/dist/internal/woodstock/client-projection.js +79 -53
  67. package/dist/internal/woodstock/cold-sessions.d.ts +4 -0
  68. package/dist/internal/woodstock/cold-sessions.js +90 -0
  69. package/dist/internal/woodstock/extension-store.d.ts +2 -0
  70. package/dist/internal/woodstock/extension-store.js +4 -0
  71. package/dist/internal/woodstock/fleet-store.d.ts +3 -3
  72. package/dist/internal/woodstock/fleet-store.js +16 -11
  73. package/dist/internal/woodstock/index.d.ts +11 -3
  74. package/dist/internal/woodstock/index.js +33 -14
  75. package/dist/internal/woodstock/progress.d.ts +14 -1
  76. package/dist/internal/woodstock/progress.js +97 -19
  77. package/dist/internal/woodstock/run-recovery.js +6 -4
  78. package/dist/internal/woodstock/session-attention.d.ts +1 -1
  79. package/dist/internal/woodstock/session-attention.js +2 -2
  80. package/dist/internal/woodstock/session-entry.d.ts +109 -42
  81. package/dist/internal/woodstock/session-entry.js +63 -20
  82. package/dist/internal/woodstock/session-inbox.js +2 -0
  83. package/dist/internal/woodstock/session-store.d.ts +104 -24
  84. package/dist/internal/woodstock/session-store.js +937 -246
  85. package/dist/internal/woodstock/storage-admission.d.ts +8 -8
  86. package/dist/internal/woodstock/storage-admission.js +8 -34
  87. package/dist/internal/woodstock/storage-conformance.d.ts +15 -0
  88. package/dist/internal/woodstock/storage-conformance.js +489 -0
  89. package/dist/model-preference.d.ts +2 -2
  90. package/dist/model-preference.js +2 -2
  91. package/dist/node.js +1 -1
  92. package/dist/remote-client.js +8 -1
  93. package/dist/session-attention.d.ts +8 -1
  94. package/dist/session-attention.js +6 -1
  95. package/dist/testing.js +1 -0
  96. package/docs/api/README.md +18 -16
  97. package/docs/api/agent-control.md +172 -2
  98. package/docs/api/client-entry.md +26 -10
  99. package/docs/api/client.md +153 -37
  100. package/docs/api/cloudflare.md +76 -23
  101. package/docs/api/delegation.md +485 -0
  102. package/docs/api/effect.md +20 -2
  103. package/docs/api/extensions.md +21 -9
  104. package/docs/api/fleet.md +149 -122
  105. package/docs/api/http.md +4 -1
  106. package/docs/api/index.md +116 -20
  107. package/docs/api/internal/woodstock/storage-conformance.md +81 -0
  108. package/docs/api/model-preference.md +17 -0
  109. package/docs/api/testing.md +16 -4
  110. package/package.json +26 -14
  111. package/dist/internal/browser-sessions.d.ts +0 -31
  112. package/dist/internal/browser-sessions.js +0 -173
package/dist/fleet.js CHANGED
@@ -18,7 +18,7 @@ export const agentActionSchema = z.enum([
18
18
  "delegate",
19
19
  ]);
20
20
  /** Attribution supplied by the admitting host, without Team semantics. */
21
- export const agentProvenanceSchema = z.strictObject({
21
+ export const agentProvenanceSchema = z.lazy(() => z.strictObject({
22
22
  actor: identity,
23
23
  workflowRunId: identity.optional(),
24
24
  /** Host fingerprint of the enclosing model program, frozen with replay input. */
@@ -29,9 +29,9 @@ export const agentProvenanceSchema = z.strictObject({
29
29
  session: z
30
30
  .strictObject({ agentId: identity, sessionId: identity })
31
31
  .optional(),
32
- });
32
+ }));
33
33
  /** Fleet authority is supplied, never looked up in host policy. */
34
- export const agentGrantSchema = z.strictObject({
34
+ export const agentGrantSchema = z.lazy(() => z.strictObject({
35
35
  agents: z.union([z.literal("all"), z.array(identity)]),
36
36
  actions: z.array(agentActionSchema).max(5),
37
37
  expiresAt: z.number().int().nonnegative(),
@@ -39,7 +39,7 @@ export const agentGrantSchema = z.strictObject({
39
39
  meta: z.json().optional(),
40
40
  /** Delegation abuse bound; inherited paths may only narrow it. */
41
41
  maxDepth: z.number().int().min(1).max(8).optional(),
42
- });
42
+ }));
43
43
  /** Refusal of supplied authority; no host policy lookup is performed. */
44
44
  export class AgentGrantError extends Error {
45
45
  reason;
@@ -67,30 +67,32 @@ export const agentIds = defineIdFamily({
67
67
  version: 1,
68
68
  kinds: { agent: { prefix: "agent" } },
69
69
  });
70
- const agentRowSchema = z.strictObject({
70
+ const agentRowSchema = z.lazy(() => z.strictObject({
71
71
  agent_id: z.string(),
72
72
  name: z.string(),
73
73
  actor_user_id: z.string(),
74
+ created_by: z.string().min(1).max(256).nullable(),
74
75
  created_at: z.number().int().nonnegative(),
75
76
  updated_at: z.number().int().nonnegative(),
76
- });
77
- const receiptRowSchema = z.strictObject({
77
+ }));
78
+ const receiptRowSchema = z.lazy(() => z.strictObject({
78
79
  request_id: z.string(),
79
80
  actor_user_id: z.string(),
80
81
  name: z.string(),
81
82
  agent_id: z.string(),
82
83
  computer_mode: z.string().min(1).max(4096),
83
- });
84
+ }));
84
85
  /** Stable replay input; configuration is an opaque host creation choice. */
85
- export const agentCreationSchema = z.strictObject({
86
+ export const agentCreationSchema = z.lazy(() => z.strictObject({
86
87
  name: z.string().min(1).max(256),
87
88
  requestId: z.string().min(1).max(256),
88
89
  configuration: z.string().min(1).max(4096),
89
- });
90
+ createdBy: z.string().min(1).max(256).nullable().optional(),
91
+ }));
90
92
  /** Owner-only rename input: an Agent's new display name. */
91
- export const agentRenameSchema = z.strictObject({
93
+ export const agentRenameSchema = z.lazy(() => z.strictObject({
92
94
  name: z.string().min(1).max(256),
93
- });
95
+ }));
94
96
  /** Directory input, replay or storage refusal. */
95
97
  export class DirectoryError extends Error {
96
98
  status;
@@ -110,6 +112,7 @@ function asDirectoryAgent(row) {
110
112
  throw new DirectoryError(503, "partial_init");
111
113
  return Object.freeze({
112
114
  agentId: agent.value,
115
+ createdBy: parsed.data.created_by,
113
116
  name: parsed.data.name,
114
117
  createdAt: parsed.data.created_at,
115
118
  updatedAt: parsed.data.updated_at,
@@ -142,6 +145,8 @@ export function createAgentDirectory(sql) {
142
145
  const existing = readStored(agentId.value);
143
146
  if (existing === null)
144
147
  throw new DirectoryError(503, "partial_init");
148
+ if (existing.createdBy !== (command.createdBy ?? null))
149
+ throw new DirectoryError(409, "request_conflict");
145
150
  return existing;
146
151
  }
147
152
  return null;
@@ -165,7 +170,7 @@ export function createAgentDirectory(sql) {
165
170
  throw new DirectoryError(409, "name_taken");
166
171
  const agentId = agentIds.agent.generate();
167
172
  const now = Date.now();
168
- store.reserve(agentId, command.name, actorUserId, now, command.requestId, command.configuration);
173
+ store.reserve(agentId, command.name, actorUserId, now, command.requestId, command.configuration, command.createdBy ?? null);
169
174
  const created = readStored(agentId);
170
175
  if (created === null)
171
176
  throw new DirectoryError(503, "partial_init");
@@ -247,7 +252,7 @@ export function createAgentDirectory(sql) {
247
252
  };
248
253
  }
249
254
  /** Replay identity and work, with the parent supplied exclusively by the grant. */
250
- export const agentDelegationTaskSchema = z.strictObject({
255
+ export const agentDelegationTaskSchema = z.lazy(() => z.strictObject({
251
256
  requestId: identity,
252
257
  agentId: identity,
253
258
  sessionId: identity.optional(),
@@ -255,9 +260,10 @@ export const agentDelegationTaskSchema = z.strictObject({
255
260
  .string()
256
261
  .min(1)
257
262
  .max(256 * 1024),
258
- });
263
+ }));
259
264
  /** Exact host facts encoded over internal transports, without transcript content. */
260
265
  export const commandSettlementSchema = Schema.Struct({
266
+ acceptedSender: Schema.NullOr(Schema.String),
261
267
  terminal: SessionTerminalSchema,
262
268
  content: Schema.String,
263
269
  usage: Schema.Array(Schema.Struct({ provider: Schema.String, model: Schema.String, usage })),
@@ -287,7 +293,7 @@ export async function delegationProvenance(session, toolCallCode) {
287
293
  * stay on that reply's own line and never travel onward.
288
294
  */
289
295
  export function delegationSendMeta(sender, invocationMeta) {
290
- const author = authorMeta(sender);
296
+ const author = authorMeta({ ...sender, kind: "agent" });
291
297
  const inherited = invocationMeta === undefined
292
298
  ? undefined
293
299
  : FungiMessageMetaSchema.parse(invocationMeta).delegation;
@@ -307,7 +313,11 @@ export function delegationSendMeta(sender, invocationMeta) {
307
313
  */
308
314
  export function delegationReplyMeta(delegation, replierName) {
309
315
  return {
310
- ...authorMeta({ id: delegation.reply.agentId, name: replierName }),
316
+ ...authorMeta({
317
+ id: delegation.reply.agentId,
318
+ name: replierName,
319
+ kind: "agent",
320
+ }),
311
321
  delegation: {
312
322
  ancestors: [...delegation.ancestors],
313
323
  maxDepth: delegation.maxDepth,
@@ -318,24 +328,18 @@ export function delegationReplyMeta(delegation, replierName) {
318
328
  const delegationMetadata = z.object({
319
329
  delegation: FungiMessageMetaSchema.shape.delegation,
320
330
  });
321
- const delegationRowSchema = z.strictObject({
331
+ const delegationRowSchema = z.lazy(() => z.strictObject({
322
332
  input: z.string(),
323
333
  mail: z.string(),
324
334
  receipt: z.string().nullable(),
325
- });
335
+ }));
326
336
  const decodeMail = Schema.decodeUnknownSync(Schema.fromJsonString(BirdDogMailSchema));
327
- const recipientRowSchema = z.strictObject({
328
- agent_id: identity,
329
- session_id: identity,
330
- sent_at: z.number().int().nonnegative(),
331
- total: z.number().int().nonnegative(),
332
- });
333
337
  /**
334
- * Hosted BirdDog submission and Pending observation. The durable row freezes
338
+ * BirdDog submission and reply authentication. The durable row freezes
335
339
  * correspondence before transport; an ambiguous delivery reuses that exact mail.
336
340
  * Shiitake owns work deduplication, execution and settlement; Post owns replies.
337
341
  */
338
- export function createFleetDelegation(options) {
342
+ export function createFleetCorrespondence(options) {
339
343
  const store = createFleetDelegationStore(options.storage);
340
344
  function read(requestId) {
341
345
  const row = store.read(requestId);
@@ -357,7 +361,8 @@ export function createFleetDelegation(options) {
357
361
  : undefined;
358
362
  const ancestors = inherited?.ancestors ?? [];
359
363
  const maxDepth = Math.min(grant.maxDepth ?? 8, inherited?.maxDepth ?? 8);
360
- if (ancestors.includes(task.agentId) || parent.agentId === task.agentId)
364
+ // Ancestry bounds work depth; it does not remove authorized peer targets.
365
+ if (parent.agentId === task.agentId)
361
366
  throw new AgentGrantError("delegation_loop");
362
367
  if (ancestors.length >= maxDepth)
363
368
  throw new AgentGrantError("delegation_depth");
@@ -413,22 +418,6 @@ export function createFleetDelegation(options) {
413
418
  store.recordReceipt(task.requestId, JSON.stringify(receipt));
414
419
  return receipt;
415
420
  }
416
- async function delegate(grant, task) {
417
- const accepted = await start(grant, task);
418
- const row = read(task.requestId);
419
- if (row === undefined)
420
- throw new DirectoryError(503, "partial_init");
421
- const mail = decodeMail(row.mail);
422
- const settlement = await options.readSettlement(mail.to.agentId, mail.to.sessionId, accepted.commandId);
423
- return settlement === undefined
424
- ? pending(1000)
425
- : {
426
- kind: "settled",
427
- agentId: mail.to.agentId,
428
- sessionId: mail.to.sessionId,
429
- ...settlement,
430
- };
431
- }
432
421
  /**
433
422
  * Authenticate one arriving reply against the frozen mail this owner sent.
434
423
  * It must be BirdDog's single reply key for that mail, mirror its sender and
@@ -470,30 +459,79 @@ export function createFleetDelegation(options) {
470
459
  reply,
471
460
  };
472
461
  }
462
+ /** Read only the existing acceptance receipt; do not reserve or deliver mail. */
463
+ function receipt(requestId) {
464
+ const encoded = read(requestId)?.receipt;
465
+ return encoded === undefined || encoded === null
466
+ ? undefined
467
+ : parseAccepted(encoded);
468
+ }
469
+ return {
470
+ /** Submit frozen mail or reuse its recorded Session admission receipt. */
471
+ start,
472
+ /** Match a reply to frozen mail and restore the caller's delegation path. */
473
+ authenticateReply,
474
+ /** Read an existing acceptance receipt without reserving or delivering mail. */
475
+ receipt,
476
+ };
477
+ }
478
+ /** Local hosts may observe exact work directly; remote correspondence never pulls it. */
479
+ export function createFleetDelegation(options) {
480
+ const correspondence = createFleetCorrespondence(options);
481
+ const store = createFleetDelegationStore(options.storage);
482
+ async function delegate(grant, task) {
483
+ const accepted = await correspondence.start(grant, task);
484
+ const raw = store.read(task.requestId);
485
+ if (raw === undefined)
486
+ throw new DirectoryError(503, "partial_init");
487
+ const mail = decodeMail(delegationRowSchema.parse(raw).mail);
488
+ const settlement = await options.readSettlement(mail.to.agentId, mail.to.sessionId, accepted.commandId);
489
+ return settlement === undefined
490
+ ? pending(1000)
491
+ : {
492
+ kind: "settled",
493
+ agentId: mail.to.agentId,
494
+ sessionId: mail.to.sessionId,
495
+ ...settlement,
496
+ };
497
+ }
473
498
  /**
474
- * The distinct Agents one parent Session sent work to, newest send first,
475
- * with how many more exist past `limit`. Read-only over the frozen mail.
499
+ * The newest delegation this owner sent whose work has not settled at its
500
+ * target, so the owner is still waiting for a reply; undefined when none.
476
501
  */
477
- function recipients(parent, limit) {
478
- const rows = store
479
- .recipients(parent.agentId, parent.sessionId, limit)
480
- .map((row) => recipientRowSchema.parse(row));
481
- return {
482
- recipients: rows.map((row) => ({
483
- agentId: row.agent_id,
484
- sessionId: row.session_id,
485
- sentAt: row.sent_at,
486
- })),
487
- more: Math.max(0, (rows[0]?.total ?? 0) - rows.length),
488
- };
502
+ async function outstanding() {
503
+ for (const raw of store.sent()) {
504
+ const row = delegationRowSchema.parse(raw);
505
+ if (row.receipt === null)
506
+ continue;
507
+ const { to } = decodeMail(row.mail);
508
+ const { commandId } = parseAccepted(row.receipt);
509
+ const target = {
510
+ agentId: to.agentId,
511
+ sessionId: to.sessionId,
512
+ commandId,
513
+ };
514
+ let settlement;
515
+ try {
516
+ settlement = await options.readSettlement(to.agentId, to.sessionId, commandId);
517
+ }
518
+ catch (cause) {
519
+ // Work whose state cannot be read is still owed; say why.
520
+ return {
521
+ ...target,
522
+ unreadable: cause instanceof Error ? cause.message : "unreadable",
523
+ };
524
+ }
525
+ if (settlement === undefined)
526
+ return target;
527
+ }
528
+ return undefined;
489
529
  }
490
530
  return {
531
+ /** The delegated work this owner still waits on, if any. */
532
+ outstanding,
491
533
  /** Authenticate a reply against its frozen mail and restore the caller's path. */
492
- authenticateReply,
493
- /** One grouped read of the Agents a parent Session sent work to. */
494
- recipients,
495
- /** Submit once and return the existing Shiitake admission receipt. */
496
- start,
534
+ ...correspondence,
497
535
  /** Submit or poll the exact turn, yielding Agar Pending until settled. */
498
536
  delegate,
499
537
  };
package/dist/hosted.js CHANGED
@@ -169,6 +169,7 @@ function hostedPort(manifest, revision, grants) {
169
169
  clear: () => Effect.fail(unavailable("Attention")),
170
170
  }),
171
171
  hasPendingSteer: () => Effect.fail(unavailable("Steering")),
172
+ sessionPosition: () => Effect.fail(unavailable("Session timeline")),
172
173
  hasSuccessfulToolResult: () => Effect.fail(unavailable("A tool result")),
173
174
  observe: () => Effect.die(unavailable("Observation")),
174
175
  transact: () => Effect.fail(new ShiitakeError("extensions", "rejected", "A hosted extension has no Agent transaction")),
@@ -42,7 +42,7 @@ export declare function createShiitakeHttpRoutes(resolveSession: ShiitakeSession
42
42
  };
43
43
  };
44
44
  output: {
45
- readonly cause: "closed" | "conflict" | "incompatible" | "invalid" | "rejected" | "unavailable" | "storage_pressure" | "context_too_large";
45
+ readonly cause: "closed" | "conflict" | "incompatible" | "invalid" | "rejected" | "unavailable" | "state_reset_required" | "storage_pressure";
46
46
  readonly _tag: "ShiitakeError";
47
47
  readonly boundary: "contract" | "extensions" | "instructions" | "model" | "runtime" | "store" | "tools";
48
48
  readonly message: string;
@@ -109,7 +109,7 @@ export declare function createShiitakeHttpRoutes(resolveSession: ShiitakeSession
109
109
  };
110
110
  };
111
111
  output: {
112
- readonly cause: "closed" | "conflict" | "incompatible" | "invalid" | "rejected" | "unavailable" | "storage_pressure" | "context_too_large";
112
+ readonly cause: "closed" | "conflict" | "incompatible" | "invalid" | "rejected" | "unavailable" | "state_reset_required" | "storage_pressure";
113
113
  readonly _tag: "ShiitakeError";
114
114
  readonly boundary: "contract" | "extensions" | "instructions" | "model" | "runtime" | "store" | "tools";
115
115
  readonly message: string;
@@ -150,7 +150,7 @@ export declare function createShiitakeHttpRoutes(resolveSession: ShiitakeSession
150
150
  $get: {
151
151
  input: {};
152
152
  output: {
153
- readonly cause: "closed" | "conflict" | "incompatible" | "invalid" | "rejected" | "unavailable" | "storage_pressure" | "context_too_large";
153
+ readonly cause: "closed" | "conflict" | "incompatible" | "invalid" | "rejected" | "unavailable" | "state_reset_required" | "storage_pressure";
154
154
  readonly _tag: "ShiitakeError";
155
155
  readonly boundary: "contract" | "extensions" | "instructions" | "model" | "runtime" | "store" | "tools";
156
156
  readonly message: string;
@@ -178,6 +178,34 @@ export declare function createShiitakeHttpRoutes(resolveSession: ShiitakeSession
178
178
  status: 200;
179
179
  };
180
180
  };
181
+ } & {
182
+ "/sessions/:sessionId/pending/latest": {
183
+ $get: {
184
+ input: {
185
+ param: {
186
+ sessionId: string;
187
+ };
188
+ };
189
+ output: {
190
+ readonly requestId: string;
191
+ readonly meta?: any;
192
+ readonly origin?: {
193
+ readonly extensionId: string;
194
+ readonly correlation: string | null;
195
+ } | undefined;
196
+ readonly commandId: string;
197
+ readonly text: string;
198
+ readonly images?: readonly {
199
+ readonly type: "image";
200
+ readonly data: string;
201
+ readonly mimeType: string;
202
+ }[] | undefined;
203
+ readonly delivery: import("./client.js").PromptDelivery;
204
+ } | null;
205
+ outputFormat: "json";
206
+ status: 200;
207
+ };
208
+ };
181
209
  } & {
182
210
  "/sessions/:sessionId/model-preference": {
183
211
  $get: {
@@ -210,7 +238,7 @@ export declare function createShiitakeHttpRoutes(resolveSession: ShiitakeSession
210
238
  };
211
239
  };
212
240
  output: {
213
- readonly cause: "closed" | "conflict" | "incompatible" | "invalid" | "rejected" | "unavailable" | "storage_pressure" | "context_too_large";
241
+ readonly cause: "closed" | "conflict" | "incompatible" | "invalid" | "rejected" | "unavailable" | "state_reset_required" | "storage_pressure";
214
242
  readonly _tag: "ShiitakeError";
215
243
  readonly boundary: "contract" | "extensions" | "instructions" | "model" | "runtime" | "store" | "tools";
216
244
  readonly message: string;
@@ -235,6 +263,47 @@ export declare function createShiitakeHttpRoutes(resolveSession: ShiitakeSession
235
263
  status: 204;
236
264
  };
237
265
  };
266
+ } & {
267
+ "/sessions/:sessionId/withdraw": {
268
+ $post: {
269
+ input: {
270
+ json: {
271
+ readonly requestId: string;
272
+ };
273
+ } & {
274
+ param: {
275
+ sessionId: string;
276
+ };
277
+ };
278
+ output: {
279
+ readonly cause: "closed" | "conflict" | "incompatible" | "invalid" | "rejected" | "unavailable" | "state_reset_required" | "storage_pressure";
280
+ readonly _tag: "ShiitakeError";
281
+ readonly boundary: "contract" | "extensions" | "instructions" | "model" | "runtime" | "store" | "tools";
282
+ readonly message: string;
283
+ readonly requestId?: string | undefined;
284
+ };
285
+ outputFormat: "json";
286
+ status: 400;
287
+ } | {
288
+ input: {
289
+ json: {
290
+ readonly requestId: string;
291
+ };
292
+ } & {
293
+ param: {
294
+ sessionId: string;
295
+ };
296
+ };
297
+ output: {
298
+ readonly status: "accepted";
299
+ readonly commandId: string;
300
+ } | {
301
+ readonly status: "unknown";
302
+ };
303
+ outputFormat: "json";
304
+ status: 200;
305
+ };
306
+ };
238
307
  } & {
239
308
  "/sessions/:sessionId/command": {
240
309
  $post: {
@@ -282,7 +351,7 @@ export declare function createShiitakeHttpRoutes(resolveSession: ShiitakeSession
282
351
  };
283
352
  };
284
353
  output: {
285
- readonly cause: "closed" | "conflict" | "incompatible" | "invalid" | "rejected" | "unavailable" | "storage_pressure" | "context_too_large";
354
+ readonly cause: "closed" | "conflict" | "incompatible" | "invalid" | "rejected" | "unavailable" | "state_reset_required" | "storage_pressure";
286
355
  readonly _tag: "ShiitakeError";
287
356
  readonly boundary: "contract" | "extensions" | "instructions" | "model" | "runtime" | "store" | "tools";
288
357
  readonly message: string;
@@ -384,6 +453,8 @@ export declare function createShiitakeHttpRoutes(resolveSession: ShiitakeSession
384
453
  output: {
385
454
  readonly status: "accepted";
386
455
  readonly commandId: string;
456
+ } | {
457
+ readonly status: "unknown";
387
458
  } | {
388
459
  readonly status: "too_late";
389
460
  readonly commandId: string;
@@ -409,7 +480,7 @@ export declare function createShiitakeHttpRoutes(resolveSession: ShiitakeSession
409
480
  };
410
481
  };
411
482
  output: {
412
- readonly cause: "closed" | "conflict" | "incompatible" | "invalid" | "rejected" | "unavailable" | "storage_pressure" | "context_too_large";
483
+ readonly cause: "closed" | "conflict" | "incompatible" | "invalid" | "rejected" | "unavailable" | "state_reset_required" | "storage_pressure";
413
484
  readonly _tag: "ShiitakeError";
414
485
  readonly boundary: "contract" | "extensions" | "instructions" | "model" | "runtime" | "store" | "tools";
415
486
  readonly message: string;
@@ -435,7 +506,9 @@ export declare function createShiitakeHttpRoutes(resolveSession: ShiitakeSession
435
506
  readonly hasMore: boolean;
436
507
  readonly oldestCursor?: string | null | undefined;
437
508
  readonly messages: readonly {
509
+ readonly requestId?: string | undefined;
438
510
  readonly meta?: any;
511
+ readonly data?: any;
439
512
  readonly origin?: {
440
513
  readonly extensionId: string;
441
514
  readonly correlation: string | null;
@@ -499,6 +572,7 @@ export declare function createShiitakeHttpRoutes(resolveSession: ShiitakeSession
499
572
  };
500
573
  thoughtSignature?: string | undefined;
501
574
  namespace?: string | undefined;
575
+ argumentsError?: string | undefined;
502
576
  } | {
503
577
  type: "thinking";
504
578
  thinking: string;
@@ -555,20 +629,10 @@ export declare function createShiitakeHttpRoutes(resolveSession: ShiitakeSession
555
629
  rawStopReason?: string | undefined;
556
630
  endTurn?: boolean | undefined;
557
631
  timestamp: number;
632
+ durationMs?: number | undefined;
558
633
  } | {
559
- role: "toolResult";
560
634
  toolCallId: string;
561
- toolName: string;
562
- content: ({
563
- type: "text";
564
- text: string;
565
- textSignature?: string | undefined;
566
- } | {
567
- type: "image";
568
- data: string;
569
- mimeType: string;
570
- })[];
571
- details?: any;
635
+ role: "toolResult";
572
636
  usage?: {
573
637
  input: number;
574
638
  output: number;
@@ -585,6 +649,18 @@ export declare function createShiitakeHttpRoutes(resolveSession: ShiitakeSession
585
649
  total: number;
586
650
  };
587
651
  } | undefined;
652
+ content: ({
653
+ type: "text";
654
+ text: string;
655
+ textSignature?: string | undefined;
656
+ } | {
657
+ type: "image";
658
+ data: string;
659
+ mimeType: string;
660
+ })[];
661
+ timestamp: number;
662
+ durationMs?: number | undefined;
663
+ toolName: string;
588
664
  nestedCalls?: {
589
665
  calls: {
590
666
  id: string;
@@ -600,7 +676,6 @@ export declare function createShiitakeHttpRoutes(resolveSession: ShiitakeSession
600
676
  complete: boolean;
601
677
  } | undefined;
602
678
  isError: boolean;
603
- timestamp: number;
604
679
  };
605
680
  }[];
606
681
  readonly terminals: readonly {
@@ -623,7 +698,7 @@ export declare function createShiitakeHttpRoutes(resolveSession: ShiitakeSession
623
698
  readonly sequence: number;
624
699
  readonly at: number;
625
700
  readonly trigger: import("./client.js").SessionCompactionTrigger;
626
- readonly result: "nothing_to_compact" | "failed";
701
+ readonly result: "nothing_to_compact" | "failed" | "stale" | "insufficient";
627
702
  readonly diagnostic: string | null;
628
703
  }[] | undefined;
629
704
  readonly sandboxFailures?: readonly {
@@ -632,7 +707,7 @@ export declare function createShiitakeHttpRoutes(resolveSession: ShiitakeSession
632
707
  readonly executionId: string;
633
708
  readonly adapter: string;
634
709
  readonly buildSha: string | null;
635
- readonly tag: "Unknown" | "SourceInvalid" | "GuestThrew" | "DeadlineExceeded" | "Cancelled" | "DispatchLost" | "SandboxCrashed" | "BadResponse" | "ResultTooLarge" | "ResultNotJson" | "CapabilityFailed";
710
+ readonly tag: "Unknown" | "SourceInvalid" | "GuestThrew" | "DeadlineExceeded" | "SandboxBusy" | "Cancelled" | "DispatchLost" | "SandboxCrashed" | "BadResponse" | "ResultTooLarge" | "ResultNotJson" | "CapabilityFailed";
636
711
  readonly fields: {
637
712
  readonly [x: string]: any;
638
713
  };
@@ -641,6 +716,7 @@ export declare function createShiitakeHttpRoutes(resolveSession: ShiitakeSession
641
716
  readonly pending: {
642
717
  readonly total: number;
643
718
  readonly prompts: readonly {
719
+ readonly requestId: string;
644
720
  readonly meta?: any;
645
721
  readonly origin?: {
646
722
  readonly extensionId: string;
@@ -698,6 +774,13 @@ export declare function createShiitakeHttpRoutes(resolveSession: ShiitakeSession
698
774
  readonly textTruncated: boolean;
699
775
  readonly thinkingTruncated: boolean;
700
776
  } | null;
777
+ readonly toolOutput: readonly {
778
+ readonly toolCallId: string;
779
+ readonly revision: number;
780
+ readonly tail: string;
781
+ readonly droppedBytes: number;
782
+ readonly totalBytes: number;
783
+ }[];
701
784
  readonly extensions: {
702
785
  readonly [x: string]: {
703
786
  readonly status: "running";
@@ -717,6 +800,7 @@ export declare function createShiitakeHttpRoutes(resolveSession: ShiitakeSession
717
800
  readonly since: number;
718
801
  readonly extensionId: string;
719
802
  readonly expiresAt?: number | undefined;
803
+ readonly inbox?: false | undefined;
720
804
  }[];
721
805
  readonly context?: {
722
806
  readonly tokens: number;
@@ -759,7 +843,7 @@ export declare function createShiitakeHttpRoutes(resolveSession: ShiitakeSession
759
843
  };
760
844
  };
761
845
  output: {
762
- readonly cause: "closed" | "conflict" | "incompatible" | "invalid" | "rejected" | "unavailable" | "storage_pressure" | "context_too_large";
846
+ readonly cause: "closed" | "conflict" | "incompatible" | "invalid" | "rejected" | "unavailable" | "state_reset_required" | "storage_pressure";
763
847
  readonly _tag: "ShiitakeError";
764
848
  readonly boundary: "contract" | "extensions" | "instructions" | "model" | "runtime" | "store" | "tools";
765
849
  readonly message: string;
@@ -171,6 +171,10 @@ export function createShiitakeHttpRoutes(resolveSession, listSessions, createSes
171
171
  }
172
172
  const page = await listSessions(cursor);
173
173
  return context.json(page, 200);
174
+ })
175
+ .get("/sessions/:sessionId/pending/latest", async (context) => {
176
+ const session = await resolveSession(decodeClientSessionId(context.req.param("sessionId")), context.get("shiitakeMeta"));
177
+ return context.json(await session.latestPending(), 200);
174
178
  })
175
179
  .get("/sessions/:sessionId/model-preference", async (context) => {
176
180
  const session = await resolveSession(decodeClientSessionId(context.req.param("sessionId")), context.get("shiitakeMeta"));
@@ -187,6 +191,15 @@ export function createShiitakeHttpRoutes(resolveSession, listSessions, createSes
187
191
  const session = await resolveSession(decodeClientSessionId(context.req.param("sessionId")), context.get("shiitakeMeta"));
188
192
  await session.modelPreference.set(context.req.valid("json"));
189
193
  return context.body(null, 204);
194
+ })
195
+ .post("/sessions/:sessionId/withdraw", validator("json", (value, context) => {
196
+ const decoded = decodeClientSessionCreationRequest(value);
197
+ if (decoded._tag === "Failure")
198
+ return context.json(toShiitakeErrorWire(invalidRequest("Withdrawal request is invalid")), 400);
199
+ return decoded.success;
200
+ }), async (context) => {
201
+ const session = await resolveSession(decodeClientSessionId(context.req.param("sessionId")), context.get("shiitakeMeta"));
202
+ return context.json(await session.withdraw(context.req.valid("json").requestId), 200);
190
203
  })
191
204
  .post("/sessions/:sessionId/command", validator("json", (value, context) => {
192
205
  const decoded = decodeClientSessionCommandRequest(value);
@@ -238,5 +251,9 @@ export function createShiitakeHttpRoutes(resolveSession, listSessions, createSes
238
251
  includeSandboxFailures: query.includeSandboxFailures === "true",
239
252
  }));
240
253
  })
241
- .onError((error, context) => context.json(toShiitakeErrorWire(error), 503));
254
+ .onError((error, context) => context.json(toShiitakeErrorWire(error), error instanceof ShiitakeError &&
255
+ error.boundary === "runtime" &&
256
+ error.cause === "rejected"
257
+ ? 403
258
+ : 503));
242
259
  }
package/dist/index.d.ts CHANGED
@@ -5,9 +5,10 @@ import type { VerifiedAgentReply } from "./internal/woodstock/index.js";
5
5
  import type { BirdDogEffect } from "@fungi.computer/bird-dog/effect";
6
6
  import type { Accepted } from "./client.js";
7
7
  import type { ShiitakeOptions, ShiitakeOwnerAgent } from "./internal/contracts.js";
8
- export type { AbortCommand, AgentExtensionControls, BranchCommand, CompactCommand, CancelCommand, CancelResult, Accepted, ForkCommand, ForkedSession, PromptCommand, PromptDelivery, SendOptions, ReadOptions, SessionCommand, SessionCommandHandler, SessionExtensionControls, SessionExtensionSlots, SessionFrame, SessionMessage, SessionProgress, SessionContext, SessionSnapshot, SessionInboxState, SessionSummary, SessionSummaryPage, SessionSummaryRow, SessionActivity, AgentRunningWork, SessionTerminal, SessionCompactionMarker, SessionCompactionNotice, SessionCompactionTrigger, ShiitakeEventSourceConstructor, SessionWatch, ShiitakeAgent, ShiitakeSession, SubscribeOptions, TooLate, WatchOptions, } from "./client.js";
8
+ export type { AbortCommand, AgentExtensionControls, BranchCommand, CompactCommand, CancelCommand, CancelResult, Accepted, ForkCommand, ForkedSession, OperatorCommand, TitleCommand, PromptCommand, PromptDelivery, SendOptions, ReadOptions, SessionCommand, SessionCommandHandler, SessionExtensionControls, SessionExtensionSlots, SessionFrame, SessionMessage, SessionProgress, SessionToolOutput, SessionContext, SessionSnapshot, SessionInboxState, SessionSummary, SessionSummaryPage, SessionSummaryRow, SessionActivity, AgentRunningWork, SessionTerminal, SessionCompactionMarker, SessionCompactionNotice, SessionCompactionTrigger, ShiitakeEventSourceConstructor, SessionWatch, ShiitakeAgent, ShiitakeSession, SubscribeOptions, TooLate, UnknownRequest, WatchOptions, } from "./client.js";
9
+ export type { ColdSessionPage, ColdSessionPageRequest, ColdSessionRow, } from "./cold-sessions.js";
9
10
  export { parseForkedSession, parseSessionFrame, parseSessionSnapshot, } from "./client.js";
10
- export type { InstructionSnapshot, InstructionSource, ModelAcquisition, ModelDescription, ModelSource, RuntimeHost, RuntimePendingWork, SqliteCursor, SqliteOwner, SqliteValue, SqliteRow, StorageBudget, CompactionBudget, CompactionOptions, GrantsDelivery, GrantsDeliveryResult, ShiitakeOptions, ShiitakeOwnerAgent, ToolAccess, HostMetaOptions, StandardHostMetaResult, StandardHostMetaSchema, ToolSource, } from "./internal/contracts.js";
11
+ export type { InstructionSnapshot, InstructionSource, ModelAcquisition, ModelDescription, ModelSource, RuntimeHost, RuntimePendingWork, SqliteCursor, SqliteOwner, SqliteValue, SqliteRow, StoragePressureCheck, CompactionBudget, CompactionOptions, GrantsDelivery, GrantsDeliveryResult, ShiitakeOptions, ShiitakeOwnerAgent, ToolAccess, HostMetaOptions, StandardHostMetaResult, StandardHostMetaSchema, ToolSource, } from "./internal/contracts.js";
11
12
  export type { BorrowedCompactionViewV0, CompactionHandoffErrorV0, CompactionHandoffResultV0, CompactionHandoffV0, ExtensionCapabilityV0, ExtensionGrantV0, ExtensionRosterV0, ExtensionSlotV0, ExtensionStatusV0, RosteredExtensionV0, } from "./extensions.js";
12
13
  export { ShiitakeError, type ShiitakeErrorBoundary, type ShiitakeErrorCause, } from "./errors.js";
13
14
  /** Public construction namespace for the Promise-facing durable harness. */
@@ -18,6 +18,11 @@ export declare function executeAcceptedRun(options: ShiitakeEffectOptions, coreD
18
18
  readonly kind: "outcome_unknown";
19
19
  } | {
20
20
  kind: "failed" | "cancelled";
21
+ reason?: never;
21
22
  } | {
22
23
  kind: "completed";
24
+ reason?: never;
25
+ } | {
26
+ kind: "failed";
27
+ reason: string;
23
28
  }, never, never>;