@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
@@ -1,8 +1,10 @@
1
- import type { Message, Usage, MuleResume } from "@fungi.computer/mule/effect";
1
+ import type { Usage, MuleResume } from "@fungi.computer/mule/effect";
2
2
  import * as Schema from "effect/Schema";
3
3
  import type { ModelPreference } from "../model-preference.js";
4
+ import type { ModelMessage } from "../../client.js";
4
5
  import type { AcceptedWork } from "../client-boundary.js";
5
6
  import type { Json } from "../../extensions.js";
7
+ import { ShiitakeError } from "../../errors.js";
6
8
  import type { SqliteOwner } from "../contracts.js";
7
9
  import { type CompactionTrigger, type StoredSessionEntry } from "./session-entry.js";
8
10
  import type { VerifiedAgentReply } from "./agent-reply.js";
@@ -96,7 +98,7 @@ export type PreparedSessionRun = Readonly<{
96
98
  }>;
97
99
  }>;
98
100
  modelPreference: ModelPreference | null;
99
- messages: readonly Message[];
101
+ messages: readonly ModelMessage[];
100
102
  /**
101
103
  * Context rows, not the whole lineage: the latest compaction's kept window
102
104
  * through this work, after the few older facts that still decide it.
@@ -129,11 +131,13 @@ export type AppendCompactionInput = Readonly<{
129
131
  sessionId: string;
130
132
  expectedLeafId: string;
131
133
  workId: string;
132
- firstKeptEntryId: string;
134
+ head: string;
133
135
  summary: string;
134
136
  tokensBefore: number;
135
137
  usage: Usage;
136
138
  contextRevision: string;
139
+ /** The archive owner's receipt, stored in the entry that commits. */
140
+ receipt?: string;
137
141
  details?: Readonly<{
138
142
  readFiles: readonly string[];
139
143
  modifiedFiles: readonly string[];
@@ -188,6 +192,17 @@ export type ForkSessionAtInput = SelectSessionBranchInput;
188
192
  export declare function hasStoredSession(owner: SqliteOwner, sessionId: string): boolean;
189
193
  /** Read one retained Session entry by its globally unique row identity. */
190
194
  export declare function readSessionEntryById(owner: SqliteOwner, id: string): StoredSessionRow | undefined;
195
+ /** Host-owned metadata identity, interpreted by SQLite's JSON decoder only. */
196
+ export type AdmissionIdentity = Readonly<{
197
+ path: string;
198
+ value: string;
199
+ }>;
200
+ /** Extract the host-selected principal without giving the engine domain grammar. */
201
+ export declare function readAdmissionIdentity(owner: SqliteOwner, path: string, meta: Json | undefined): AdmissionIdentity;
202
+ /** Immutable admission author check; used before every exact cancellation, including replay. */
203
+ export declare function assertAdmissionIdentity(owner: SqliteOwner, sessionId: string, commandId: string, identity: AdmissionIdentity): void;
204
+ /** Read just one newest admission; FIFO execution and oldest-first paging are unchanged. */
205
+ export declare function readNewestPendingSessionCommand(owner: SqliteOwner, sessionId: string, identity?: AdmissionIdentity): StoredCommandAdmission | undefined;
191
206
  /** Read waiting admission facts without consulting or recreating scheduler order. */
192
207
  export declare function readPendingSessionCommands(owner: SqliteOwner, sessionId: string, limit: number, only?: "all" | "prompts"): {
193
208
  commands: Readonly<{
@@ -208,13 +223,14 @@ export declare function hasPendingSessionSteer(owner: SqliteOwner, sessionId: st
208
223
  export declare function takePendingSessionControls(owner: SqliteOwner, sessionId: string, delivery: "steer" | "followUp", targetWorkId: string): readonly Readonly<{
209
224
  workId: string;
210
225
  requestId: string;
211
- message: Message;
226
+ message: ModelMessage;
212
227
  }>[];
213
228
  /** Settle controls delivered by one parent run, exactly once per request. */
214
229
  export declare function settleSessionControls(owner: SqliteOwner, input: Readonly<{
215
230
  sessionId: string;
216
231
  parentWorkId: string;
217
232
  outcome: "completed" | "cancelled" | "failed" | "interrupted";
233
+ diagnostic: string | undefined;
218
234
  enqueue: EnqueueAcceptedWork;
219
235
  }>): void;
220
236
  /** Read one stable private command admission by accepted work identity. */
@@ -249,6 +265,22 @@ export declare function deleteStoredSession(owner: SqliteOwner, input: Readonly<
249
265
  assertIdleSession: (queue: string) => void;
250
266
  recordInboxDeletion: (sessionId: string) => void;
251
267
  }>): boolean;
268
+ /**
269
+ * The refusal of every read of, and write to, a Session the lineage audit
270
+ * found broken. Work settled for it carries `diagnostic`, a bounded form of
271
+ * the message that still names the Session and its reset.
272
+ */
273
+ export declare class BrokenSessionError extends ShiitakeError {
274
+ readonly store: string;
275
+ readonly sessionId: string;
276
+ constructor(store: string, sessionId: string, message: string);
277
+ get diagnostic(): string;
278
+ }
279
+ /**
280
+ * Whether the lineage audit refused this Session. Settlement asks before it
281
+ * records anything in the Session, which it can no longer write.
282
+ */
283
+ export declare function sessionLineageRefused(owner: SqliteOwner, sessionId: string): boolean;
252
284
  /** Create the retained Session schema and private creation/admission receipts. */
253
285
  export declare function prepareSessionStore(owner: SqliteOwner): void;
254
286
  /** Read the nullable preference at exactly this selected lineage. */
@@ -283,25 +315,25 @@ export declare function appendSessionEntry(owner: SqliteOwner, input: AppendSess
283
315
  export declare function completeSessionLeaf(owner: SqliteOwner, input: CompleteSessionLeafInput): StoredSessionRow;
284
316
  /** Rows one bounded lineage read decodes at once. */
285
317
  export declare const lineageRowLimit = 200;
286
- /**
287
- * Stored bytes one model context read may decode: the retained storage
288
- * plane's `LLM_CONTEXT_BYTES`, now a typed refusal rather than a silent
289
- * truncation, because a truncated context would change the model's input.
290
- */
291
- export declare const contextByteLimit: number;
292
318
  /**
293
319
  * Root-to-tip walks carry identities only (the 2026-08-15 connection-plane
294
320
  * law); entry data is read afterwards for exactly the rows a reader needs.
295
321
  * The selected walk drops streaming placeholders after walking; the fork walk
296
322
  * stops at them, as a fork copies only complete history.
323
+ * Each walk descends from the tip only while it is above a floor sequence,
324
+ * so a reader of recent rows never visits the history behind them. The
325
+ * selected walk steps only to an older parent, so it ends without
326
+ * deduplicating; the fork walk keeps every link for its whole-lineage check.
297
327
  */
298
328
  declare const lineageWalks: {
299
- readonly selected: "WITH RECURSIVE branch (id, parent_id, sequence, state) AS (\n SELECT id, parent_id, sequence, state\n FROM session_entries\n WHERE session_id = ? AND id = ?\n UNION\n SELECT parent.id, parent.parent_id, parent.sequence, parent.state\n FROM session_entries AS parent\n JOIN branch AS child ON parent.id = child.parent_id\n WHERE parent.session_id = ?\n )";
300
- readonly fork: "WITH RECURSIVE branch (id, parent_id, sequence, state) AS (\n SELECT id, parent_id, sequence, state\n FROM session_entries\n WHERE session_id = ? AND id = ? AND state != 'streaming'\n UNION\n SELECT parent.id, parent.parent_id, parent.sequence, parent.state\n FROM session_entries AS parent\n JOIN branch AS child ON parent.id = child.parent_id\n WHERE parent.session_id = ? AND parent.state != 'streaming'\n )";
329
+ readonly selected: "WITH RECURSIVE branch (id, parent_id, sequence, state) AS (\n SELECT id, parent_id, sequence, state\n FROM session_entries\n WHERE session_id = ? AND id = ?\n UNION ALL\n SELECT parent.id, parent.parent_id, parent.sequence, parent.state\n FROM session_entries AS parent\n JOIN branch AS child ON parent.id = child.parent_id\n WHERE parent.session_id = ? AND child.sequence > ?\n AND +parent.sequence < child.sequence\n )";
330
+ readonly fork: "WITH RECURSIVE branch (id, parent_id, sequence, state) AS (\n SELECT id, parent_id, sequence, state\n FROM session_entries\n WHERE session_id = ? AND id = ? AND state != 'streaming'\n UNION\n SELECT parent.id, parent.parent_id, parent.sequence, parent.state\n FROM session_entries AS parent\n JOIN branch AS child ON parent.id = child.parent_id\n WHERE parent.session_id = ? AND child.sequence > ?\n AND parent.state != 'streaming'\n )";
301
331
  };
302
332
  /**
303
- * One validated root-to-tip lineage, located in SQL without decoding its
304
- * rows. Readers take bounded windows of it by sequence.
333
+ * One root-to-tip lineage. Its integrity is enforced where entries are
334
+ * written (`guardSessionLineage`), so locating it reads only its tip and its
335
+ * root; readers take bounded windows of it by sequence, walking down from the
336
+ * tip only as far as their floor.
305
337
  */
306
338
  export type SessionLineage = Readonly<{
307
339
  sessionId: string;
@@ -313,7 +345,11 @@ export type SessionLineage = Readonly<{
313
345
  newestId: string;
314
346
  newestSequence: number;
315
347
  }>;
316
- /** Locate the selected lineage; undefined when the Session has no leaf. */
348
+ /**
349
+ * Locate a selected lineage from its two ends; undefined when the Session
350
+ * has no leaf. The guards make a Session's one complete root the root of
351
+ * every lineage in it, so neither end needs a walk.
352
+ */
317
353
  export declare function readSessionLineage(owner: SqliteOwner, input: ReadSelectedPathInput): SessionLineage | undefined;
318
354
  export type LineageWindowInput = Readonly<{
319
355
  /** Exclusive lower sequence bound; omitted starts at the root. */
@@ -343,15 +379,16 @@ export declare function lineageEntrySequence(owner: SqliteOwner, lineage: Sessio
343
379
  export type LineageWorkFacts = Readonly<{
344
380
  /** Works whose command entry lies on the lineage. */
345
381
  commands: ReadonlySet<string>;
346
- /** Newest failure text each work recorded on the lineage. */
382
+ /** Newest owner-produced terminal diagnostic on the lineage. */
347
383
  diagnostics: ReadonlyMap<string, string>;
348
384
  /** Host metadata of the cancellation that ended each work. */
349
385
  cancellations: ReadonlyMap<string, Json>;
350
386
  }>;
351
387
  /**
352
- * Look up, across the whole lineage, only the facts of the given works. A
353
- * diagnostic is the newest of an assistant error, a final retry error or a
354
- * work terminal's diagnostic; only that text is extracted, never the message.
388
+ * Look up, on the lineage, only the facts of the given works. Diagnostics come
389
+ * only from owned terminal fields, never provider message or retry text. The works'
390
+ * indexes give their oldest row, and the walks stop just below it, so a page
391
+ * of recent works never visits older history.
355
392
  */
356
393
  export declare function readLineageWorkFacts(owner: SqliteOwner, lineage: SessionLineage, workIds: ReadonlySet<string>): LineageWorkFacts;
357
394
  /**
@@ -363,7 +400,12 @@ export declare function readLineageWorkFacts(owner: SqliteOwner, lineage: Sessio
363
400
  export declare function readSelectedPath(owner: SqliteOwner, input: ReadSelectedPathInput): readonly StoredSessionRow[];
364
401
  /**
365
402
  * Context rows of the current selected lineage for one accepted work, or,
366
- * without a work, the settled context the next run starts from.
403
+ * without a work, the settled context the next run starts from: the kept
404
+ * window through the tip, preceded only by the older facts that still decide
405
+ * it. Those are cancellations that withdrew a command inside the window, and
406
+ * earlier compactions of the active work, whose recovery runs at most once.
407
+ * The read is bounded by the kept window and its deciding facts, not by the
408
+ * history a compaction cut.
367
409
  */
368
410
  export declare function readSessionContextPath(owner: SqliteOwner, input: Readonly<{
369
411
  sessionId: string;
@@ -371,22 +413,56 @@ export declare function readSessionContextPath(owner: SqliteOwner, input: Readon
371
413
  }>): readonly StoredSessionRow[];
372
414
  /** Work cancelled before delivery stays in history but never enters model context. */
373
415
  export declare function withdrawnWorkIds(path: readonly StoredSessionRow[]): ReadonlySet<string>;
374
- export declare function buildSessionContext(path: readonly StoredSessionRow[], activeWorkId?: string): readonly Message[];
416
+ export declare function buildSessionContext(path: readonly StoredSessionRow[], activeWorkId?: string): readonly ModelMessage[];
375
417
  /** Prepare one accepted command against its frozen selected lineage. */
376
418
  export declare function prepareSessionRun(owner: SqliteOwner, input: PrepareSessionRunInput): PreparedSessionRun;
419
+ /**
420
+ * Whether a summary whose first kept entry is `head` still fits the selected
421
+ * lineage (Pi Durable §6). It is stale when `head` is not on the selected
422
+ * lineage or sits before the current context start, where a later compaction
423
+ * already cut; placing it would bring cut history back. One bounded read.
424
+ */
425
+ export declare function compactionHeadState(owner: SqliteOwner, input: Readonly<{
426
+ sessionId: string;
427
+ head: string;
428
+ }>): "current" | "stale";
377
429
  /** One compaction that committed nothing, recorded so clients show the result. */
378
430
  export type CompactionNoticeInput = Readonly<{
379
431
  sessionId: string;
380
432
  workId: string;
381
433
  trigger: CompactionTrigger;
382
- result: "nothing_to_compact" | "failed";
383
- /** Bounded, display-safe reason; only a failure carries one. */
434
+ }> & (Readonly<{
435
+ result: "nothing_to_compact";
436
+ /** Bounded, display-safe notice diagnostic. */
384
437
  diagnostic?: string | undefined;
385
- }>;
438
+ }> | Readonly<{
439
+ result: "failed";
440
+ /** Bounded, display-safe reason for the failure. */
441
+ diagnostic?: string | undefined;
442
+ /** Known completed summary spend, even if its handoff failed. */
443
+ usage?: Usage | undefined;
444
+ }> | Readonly<{
445
+ /** A finished summary dropped because its head moved. */
446
+ result: "stale";
447
+ /** What the dropped summary cost, so its spend is not lost. */
448
+ usage?: Usage | undefined;
449
+ }> | Readonly<{
450
+ /** A finished summary dropped because, placed, it would not fit. */
451
+ result: "insufficient";
452
+ /** What the dropped summary cost, so its spend is not lost. */
453
+ usage?: Usage | undefined;
454
+ }>);
386
455
  /** Append one compaction notice on the selected lineage. */
387
456
  export declare function appendCompactionNoticeOwned(owner: SqliteOwner, input: CompactionNoticeInput): StoredSessionRow;
388
457
  /** Atomically append one compaction transition using the selected leaf CAS. */
389
458
  export declare function appendCompactionTransitionOwned(owner: SqliteOwner, input: AppendCompactionInput): StoredSessionRow;
459
+ /**
460
+ * Place a summary selected before now (a background compaction): the head
461
+ * check of `compactionHeadState` and the leaf CAS in one transaction, so a
462
+ * head that moved after any earlier check still makes it `stale` (Pi
463
+ * Durable §6). A stale summary writes nothing.
464
+ */
465
+ export declare function placeCompactionTransitionOwned(owner: SqliteOwner, input: AppendCompactionInput): StoredSessionRow | "stale";
390
466
  /**
391
467
  * Write one decoded admission (a prompt or a compaction request) and its one
392
468
  * durable work pointer.
@@ -397,6 +473,10 @@ export declare function appendCompactionTransitionOwned(owner: SqliteOwner, inpu
397
473
  * verified reply and origin) is unchanged.
398
474
  */
399
475
  export declare function acceptSessionCommandOwned(owner: SqliteOwner, sessionId: string, input: AcceptedWork, meta: Json | undefined, origin: AdmissionOrigin, contract: RunContract, enqueue: EnqueueAcceptedWork | undefined, targetWorkId?: string, reply?: VerifiedAgentReply): AcceptedSessionCommand;
476
+ /** Called only in the admission door's transaction, shared by admission and withdrawal. */
477
+ export declare function assertSessionRequestNotWithdrawn(owner: SqliteOwner, sessionId: string, requestId: string): void;
478
+ /** An admitted request wins; otherwise its key becomes a durable admission fence. */
479
+ export declare function withdrawSessionRequestOwned(owner: SqliteOwner, sessionId: string, requestId: string): import("../../client.js").WithdrawResult;
400
480
  /** Cancel the running turn and every waiting admission in one owner transaction. */
401
481
  export declare function acceptSessionAbort(owner: SqliteOwner, sessionId: string, readQueueHead: () => SessionQueueHead, record: RecordAcceptedCancellation, meta?: Json): AcceptedSessionCancellation | undefined;
402
482
  /**