@fungi.computer/shiitake 0.2.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.
- package/README.md +155 -34
- package/dist/agent-control.d.ts +77 -5
- package/dist/agent-control.js +271 -65
- package/dist/client-entry.d.ts +15 -8
- package/dist/client-entry.js +7 -5
- package/dist/client-wire.d.ts +24 -8
- package/dist/client-wire.js +53 -11
- package/dist/client.d.ts +56 -11
- package/dist/client.js +1 -1
- package/dist/cloudflare.d.ts +42 -23
- package/dist/cloudflare.js +76 -54
- package/dist/cold-sessions.d.ts +28 -0
- package/dist/cold-sessions.js +1 -0
- package/dist/delegation.d.ts +214 -0
- package/dist/delegation.js +319 -0
- package/dist/effect.d.ts +1 -1
- package/dist/errors.d.ts +2 -2
- package/dist/errors.js +2 -2
- package/dist/extension-contract.d.ts +10 -2
- package/dist/extensions.d.ts +6 -2
- package/dist/fleet.d.ts +43 -9
- package/dist/fleet.js +88 -25
- package/dist/hosted.js +1 -0
- package/dist/http-routes.d.ts +106 -22
- package/dist/http-routes.js +18 -1
- package/dist/index.d.ts +3 -2
- package/dist/internal/accepted-run-executor.d.ts +5 -0
- package/dist/internal/accepted-run-executor.js +10 -4
- package/dist/internal/admission-door.d.ts +3 -0
- package/dist/internal/admission-door.js +12 -2
- package/dist/internal/client-boundary.js +7 -1
- package/dist/internal/compaction/compaction-slot.d.ts +36 -0
- package/dist/internal/compaction/compaction-slot.js +41 -0
- package/dist/internal/compaction/compaction.d.ts +7 -4
- package/dist/internal/compaction/compaction.js +59 -30
- package/dist/internal/compaction/session-compaction.d.ts +8 -16
- package/dist/internal/compaction/session-compaction.js +358 -119
- package/dist/internal/compaction/settings.js +5 -0
- package/dist/internal/compaction/utils.d.ts +19 -16
- package/dist/internal/compaction/utils.js +30 -84
- package/dist/internal/contracts.d.ts +40 -13
- package/dist/internal/coordinator.js +28 -10
- package/dist/internal/effect-client.d.ts +4 -2
- package/dist/internal/effect-client.js +29 -0
- package/dist/internal/effect-contracts.d.ts +17 -4
- package/dist/internal/extension-runtime.d.ts +5 -0
- package/dist/internal/extension-runtime.js +184 -89
- package/dist/internal/host-meta.d.ts +7 -0
- package/dist/internal/model-acquisition.js +7 -1
- package/dist/internal/model-preference.d.ts +2 -0
- package/dist/internal/model-preference.js +2 -1
- package/dist/internal/promise-facade.js +4 -16
- package/dist/internal/run-failure-reason.d.ts +10 -0
- package/dist/internal/run-failure-reason.js +19 -0
- package/dist/internal/run-scope.d.ts +4 -1
- package/dist/internal/run-scope.js +38 -5
- package/dist/internal/runtime-coordinator.d.ts +2 -1
- package/dist/internal/runtime-coordinator.js +65 -4
- package/dist/internal/runtime-core.js +1 -0
- package/dist/internal/runtime-reconciliation.js +42 -6
- package/dist/internal/session-context.d.ts +1 -2
- package/dist/internal/session-context.js +8 -30
- package/dist/internal/session-status.d.ts +2 -1
- package/dist/internal/session-status.js +4 -1
- package/dist/internal/woodstock/client-projection.d.ts +6 -5
- package/dist/internal/woodstock/client-projection.js +79 -53
- package/dist/internal/woodstock/cold-sessions.d.ts +4 -0
- package/dist/internal/woodstock/cold-sessions.js +90 -0
- package/dist/internal/woodstock/extension-store.d.ts +2 -0
- package/dist/internal/woodstock/extension-store.js +4 -0
- package/dist/internal/woodstock/fleet-store.d.ts +5 -1
- package/dist/internal/woodstock/fleet-store.js +17 -5
- package/dist/internal/woodstock/index.d.ts +11 -3
- package/dist/internal/woodstock/index.js +33 -14
- package/dist/internal/woodstock/progress.d.ts +14 -1
- package/dist/internal/woodstock/progress.js +97 -19
- package/dist/internal/woodstock/run-recovery.js +6 -4
- package/dist/internal/woodstock/session-attention.d.ts +1 -1
- package/dist/internal/woodstock/session-attention.js +2 -2
- package/dist/internal/woodstock/session-entry.d.ts +109 -42
- package/dist/internal/woodstock/session-entry.js +63 -20
- package/dist/internal/woodstock/session-inbox.js +2 -0
- package/dist/internal/woodstock/session-store.d.ts +104 -24
- package/dist/internal/woodstock/session-store.js +937 -246
- package/dist/internal/woodstock/storage-admission.d.ts +8 -8
- package/dist/internal/woodstock/storage-admission.js +8 -34
- package/dist/internal/woodstock/storage-conformance.d.ts +15 -0
- package/dist/internal/woodstock/storage-conformance.js +489 -0
- package/dist/model-preference.d.ts +2 -2
- package/dist/model-preference.js +2 -2
- package/dist/node.js +1 -1
- package/dist/remote-client.js +8 -1
- package/dist/session-attention.d.ts +8 -1
- package/dist/session-attention.js +6 -1
- package/dist/testing.js +1 -0
- package/docs/api/README.md +18 -16
- package/docs/api/agent-control.md +171 -1
- package/docs/api/client-entry.md +26 -10
- package/docs/api/client.md +153 -37
- package/docs/api/cloudflare.md +76 -23
- package/docs/api/delegation.md +485 -0
- package/docs/api/effect.md +20 -2
- package/docs/api/extensions.md +21 -9
- package/docs/api/fleet.md +159 -104
- package/docs/api/http.md +4 -1
- package/docs/api/index.md +116 -20
- package/docs/api/internal/woodstock/storage-conformance.md +81 -0
- package/docs/api/model-preference.md +17 -0
- package/docs/api/testing.md +16 -4
- package/package.json +26 -14
- package/dist/internal/browser-sessions.d.ts +0 -31
- package/dist/internal/browser-sessions.js +0 -173
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import type * as Fiber from "effect/Fiber";
|
|
3
|
+
import * as Scope from "effect/Scope";
|
|
4
|
+
import type { SqliteOwner } from "../contracts.js";
|
|
5
|
+
/**
|
|
6
|
+
* An owner's one compaction slot (background compaction design §5). From
|
|
7
|
+
* claim until release it holds the only extra decoded copy of a
|
|
8
|
+
* conversation the owner may have: the summary fiber while it runs, then the
|
|
9
|
+
* summary it hands back. Every other trigger joins it instead of starting a
|
|
10
|
+
* second one. Process memory only: a crash loses it, unwritten.
|
|
11
|
+
*
|
|
12
|
+
* Deliberate Shiitake difference, not Pi parity: Pi Durable's background
|
|
13
|
+
* compaction is a durable task that survives a Conversation abort and
|
|
14
|
+
* resumes after a crash, and Pi does not join triggers into one. Ours is
|
|
15
|
+
* scoped to the run and single-flight; that is what bounds an owner to one
|
|
16
|
+
* extra copy of one conversation.
|
|
17
|
+
*/
|
|
18
|
+
export type CompactionSlot<A, E> = {
|
|
19
|
+
fiber: Fiber.Fiber<void, E> | undefined;
|
|
20
|
+
summary: A | undefined;
|
|
21
|
+
};
|
|
22
|
+
/** Whether a compaction already holds this owner's slot. */
|
|
23
|
+
export declare function slotTaken(owner: SqliteOwner): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Claim the owner's slot and fork `work` into `scope`, which interrupts it
|
|
26
|
+
* when the run ends. The release finalizer is registered before the fiber
|
|
27
|
+
* or the slot entry exist, and the entry is written in the same synchronous
|
|
28
|
+
* step that receives the fiber, so an interrupt anywhere leaves no entry.
|
|
29
|
+
* `work` hands its summary back through the slot, never through the fiber's
|
|
30
|
+
* exit, so releasing the slot makes the summary unreachable.
|
|
31
|
+
*/
|
|
32
|
+
export declare function claimSlot<A, E>(owner: SqliteOwner, scope: Scope.Scope, work: (handBack: (summary: A) => void) => Effect.Effect<void, E>): Effect.Effect<CompactionSlot<A, E>>;
|
|
33
|
+
/** Take the finished summary out of the slot, which no longer reaches it. */
|
|
34
|
+
export declare function takeSummary<A, E>(slot: CompactionSlot<A, E>): A | undefined;
|
|
35
|
+
/** Drop every reference the slot holds and free it, however it settled. */
|
|
36
|
+
export declare function releaseSlot<A, E>(owner: SqliteOwner, slot: CompactionSlot<A, E>): void;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import * as Scope from "effect/Scope";
|
|
3
|
+
const slots = new WeakMap();
|
|
4
|
+
/** Whether a compaction already holds this owner's slot. */
|
|
5
|
+
export function slotTaken(owner) {
|
|
6
|
+
return slots.has(owner);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Claim the owner's slot and fork `work` into `scope`, which interrupts it
|
|
10
|
+
* when the run ends. The release finalizer is registered before the fiber
|
|
11
|
+
* or the slot entry exist, and the entry is written in the same synchronous
|
|
12
|
+
* step that receives the fiber, so an interrupt anywhere leaves no entry.
|
|
13
|
+
* `work` hands its summary back through the slot, never through the fiber's
|
|
14
|
+
* exit, so releasing the slot makes the summary unreachable.
|
|
15
|
+
*/
|
|
16
|
+
export function claimSlot(owner, scope, work) {
|
|
17
|
+
const slot = { fiber: undefined, summary: undefined };
|
|
18
|
+
const task = work((summary) => {
|
|
19
|
+
slot.summary = summary;
|
|
20
|
+
});
|
|
21
|
+
return Scope.addFinalizer(scope, Effect.sync(() => {
|
|
22
|
+
releaseSlot(owner, slot);
|
|
23
|
+
})).pipe(Effect.andThen(Effect.forkIn(task, scope)), Effect.map((fiber) => {
|
|
24
|
+
slot.fiber = fiber;
|
|
25
|
+
slots.set(owner, slot);
|
|
26
|
+
return slot;
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
/** Take the finished summary out of the slot, which no longer reaches it. */
|
|
30
|
+
export function takeSummary(slot) {
|
|
31
|
+
const summary = slot.summary;
|
|
32
|
+
slot.summary = undefined;
|
|
33
|
+
return summary;
|
|
34
|
+
}
|
|
35
|
+
/** Drop every reference the slot holds and free it, however it settled. */
|
|
36
|
+
export function releaseSlot(owner, slot) {
|
|
37
|
+
slot.fiber = undefined;
|
|
38
|
+
slot.summary = undefined;
|
|
39
|
+
if (slots.get(owner) === slot)
|
|
40
|
+
slots.delete(owner);
|
|
41
|
+
}
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
* Pi v0.84.4 semantic compaction, adapted only at Woodstock's entry boundary.
|
|
3
3
|
* The retained preparation/result vocabulary is intentionally visible here;
|
|
4
4
|
* Shiitake supplies native Message values and its selected model stream.
|
|
5
|
+
* Range selection follows Pi Durable spec §8.7 (`earendil-works/pi` at
|
|
6
|
+
* 8efd314f) and token estimates are pi-ai's own.
|
|
5
7
|
*/
|
|
6
8
|
import type { Api, Model, Usage } from "@earendil-works/pi-ai";
|
|
7
9
|
import type { MuleStreamFunction } from "@fungi.computer/mule/effect";
|
|
@@ -16,9 +18,10 @@ export type CompactionSourceEntry = Readonly<{
|
|
|
16
18
|
}> | Readonly<{
|
|
17
19
|
id: string;
|
|
18
20
|
kind: "compaction";
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
/** Pi's entry head: the first entry the summary keeps. */
|
|
22
|
+
head: string;
|
|
23
|
+
/** Pi's entry model message: the summary the model reads. */
|
|
24
|
+
model: import("@earendil-works/pi-ai").UserMessage;
|
|
22
25
|
usage: Usage;
|
|
23
26
|
details?: Readonly<{
|
|
24
27
|
readFiles: readonly string[];
|
|
@@ -51,4 +54,4 @@ export declare function prepareCompaction(entries: readonly CompactionSourceEntr
|
|
|
51
54
|
export declare function compact(preparation: CompactionPreparation, model: Model<Api>, streamFn?: MuleStreamFunction,
|
|
52
55
|
/** A manual compaction's focus, appended to the history summary prompt. */
|
|
53
56
|
instructions?: string): Effect.Effect<CompactionResult, ShiitakeError>;
|
|
54
|
-
export declare function borrowedView(preparation: CompactionPreparation, result: CompactionResult, contextRevision: string): BorrowedCompactionViewV0;
|
|
57
|
+
export declare function borrowedView(preparation: CompactionPreparation, result: CompactionResult, sessionId: string, contextRevision: string): BorrowedCompactionViewV0;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
// Leaf helpers, not Pi's root entry, which also evaluates its validators.
|
|
2
|
+
import { estimateContextTokens, estimateMessageTokens, } from "@earendil-works/pi-ai/utils/estimate";
|
|
2
3
|
import { retryAssistantCall } from "@earendil-works/pi-ai/utils/retry";
|
|
3
4
|
import { contentText } from "@earendil-works/pi-ai/utils/text";
|
|
4
5
|
import { normalizeContext } from "@earendil-works/pi-ai/utils/transcript";
|
|
5
6
|
import { uuidv7 } from "@earendil-works/pi-ai/utils/uuid";
|
|
6
7
|
import * as Effect from "effect/Effect";
|
|
7
8
|
import { ShiitakeError } from "../../errors.js";
|
|
8
|
-
import { computeFileLists, createFileOps, extractFileOpsFromMessage, formatFileOperations, serializeConversation, SUMMARIZATION_PROMPT, SUMMARIZATION_SYSTEM_PROMPT, TURN_PREFIX_SUMMARIZATION_PROMPT, UPDATE_SUMMARIZATION_PROMPT,
|
|
9
|
+
import { computeFileLists, createFileOps, extractFileOpsFromMessage, formatFileOperations, serializeConversation, SUMMARIZATION_PROMPT, SUMMARIZATION_SYSTEM_PROMPT, TURN_PREFIX_SUMMARIZATION_PROMPT, UPDATE_SUMMARIZATION_PROMPT, compactionSummaryText, summaryFailure, } from "./utils.js";
|
|
9
10
|
/** A summary is a model call: its bounded provider message is shown. */
|
|
10
11
|
function failure(message) {
|
|
11
12
|
return new ShiitakeError("model", "rejected", message);
|
|
@@ -41,14 +42,11 @@ function contextMessages(entries) {
|
|
|
41
42
|
const latestCompaction = latest;
|
|
42
43
|
const keptIndex = latestCompaction === undefined
|
|
43
44
|
? 0
|
|
44
|
-
: Math.max(0, entries.findIndex(({ id }) => id === latestCompaction.
|
|
45
|
+
: Math.max(0, entries.findIndex(({ id }) => id === latestCompaction.head));
|
|
45
46
|
const messages = entries.flatMap((entry, index) => entry.kind === "message" && index >= keptIndex ? [entry.message] : []);
|
|
46
47
|
if (latestCompaction === undefined)
|
|
47
48
|
return messages;
|
|
48
|
-
return [
|
|
49
|
-
compactionSummaryMessage(latestCompaction.summary, latestCompaction.timestamp),
|
|
50
|
-
...messages,
|
|
51
|
-
];
|
|
49
|
+
return [latestCompaction.model, ...messages];
|
|
52
50
|
}
|
|
53
51
|
function extractFileOperations(messages, entries, previousIndex) {
|
|
54
52
|
const fileOps = createFileOps();
|
|
@@ -63,35 +61,65 @@ function extractFileOperations(messages, entries, previousIndex) {
|
|
|
63
61
|
extractFileOpsFromMessage(message, fileOps);
|
|
64
62
|
return fileOps;
|
|
65
63
|
}
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
/**
|
|
65
|
+
* Whether a result for one of `calls` follows `from` before the next assistant
|
|
66
|
+
* message, so a user message there sits between a tool call and its result.
|
|
67
|
+
*/
|
|
68
|
+
function resultFollows(entries, from, endIndex, calls) {
|
|
69
|
+
for (let index = from; index < endIndex; index += 1) {
|
|
70
|
+
const entry = entries[index];
|
|
71
|
+
if (entry?.kind !== "message")
|
|
72
|
+
continue;
|
|
73
|
+
if (entry.message.role === "assistant")
|
|
74
|
+
return false;
|
|
75
|
+
if (entry.message.role === "toolResult" &&
|
|
76
|
+
calls.has(entry.message.toolCallId))
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Pi Durable §8.7 rule 1: cut candidates are user and assistant messages.
|
|
83
|
+
* Tool results and system messages never are, so a kept assistant message
|
|
84
|
+
* keeps its tool results; a user message is not one while a result for a call
|
|
85
|
+
* of the assistant before it still follows it.
|
|
86
|
+
*/
|
|
87
|
+
function cutPoints(entries, startIndex, endIndex) {
|
|
88
|
+
const points = [];
|
|
89
|
+
let openCalls = new Set();
|
|
90
|
+
for (let index = startIndex; index < endIndex; index += 1) {
|
|
91
|
+
const entry = entries[index];
|
|
92
|
+
if (entry?.kind !== "message")
|
|
93
|
+
continue;
|
|
94
|
+
const message = entry.message;
|
|
95
|
+
if (message.role === "assistant") {
|
|
96
|
+
points.push(index);
|
|
97
|
+
openCalls = new Set(message.content.flatMap((block) => block.type === "toolCall" ? [block.id] : []));
|
|
98
|
+
}
|
|
99
|
+
else if (message.role === "user" &&
|
|
100
|
+
!resultFollows(entries, index + 1, endIndex, openCalls))
|
|
101
|
+
points.push(index);
|
|
102
|
+
}
|
|
103
|
+
return points;
|
|
68
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* Pi Durable §8.7 rules 2-3: walk newest to oldest adding each message's
|
|
107
|
+
* estimate; where the sum reaches `keepRecentTokens`, cut at the first
|
|
108
|
+
* candidate at or after that entry, or the newest candidate when none
|
|
109
|
+
* follows. Nothing is compacted while the sum never reaches it.
|
|
110
|
+
*/
|
|
69
111
|
function selectCutIndex(entries, startIndex, endIndex, keepRecentTokens) {
|
|
70
|
-
const points = entries
|
|
71
|
-
index >= startIndex &&
|
|
72
|
-
index < endIndex &&
|
|
73
|
-
isCutPoint(entry.message)
|
|
74
|
-
? [index]
|
|
75
|
-
: []);
|
|
76
|
-
const firstPoint = points[0];
|
|
77
|
-
if (firstPoint === undefined)
|
|
78
|
-
return undefined;
|
|
112
|
+
const points = cutPoints(entries, startIndex, endIndex);
|
|
79
113
|
let accumulated = 0;
|
|
80
|
-
let cut = firstPoint;
|
|
81
114
|
for (let index = endIndex - 1; index >= startIndex; index -= 1) {
|
|
82
115
|
const entry = entries[index];
|
|
83
116
|
if (entry?.kind !== "message")
|
|
84
117
|
continue;
|
|
85
|
-
accumulated +=
|
|
86
|
-
if (accumulated >= keepRecentTokens)
|
|
87
|
-
|
|
88
|
-
// their tool call (the last cut point), never fall back to the start.
|
|
89
|
-
cut =
|
|
90
|
-
points.find((candidate) => candidate >= index) ?? points.at(-1) ?? cut;
|
|
91
|
-
break;
|
|
92
|
-
}
|
|
118
|
+
accumulated += estimateMessageTokens(entry.message);
|
|
119
|
+
if (accumulated >= keepRecentTokens)
|
|
120
|
+
return points.find((candidate) => candidate >= index) ?? points.at(-1);
|
|
93
121
|
}
|
|
94
|
-
return
|
|
122
|
+
return undefined;
|
|
95
123
|
}
|
|
96
124
|
function classifyCut(entries, startIndex, cut) {
|
|
97
125
|
const cutEntry = entries[cut];
|
|
@@ -132,9 +160,9 @@ export function prepareCompaction(entries, settings) {
|
|
|
132
160
|
for (let index = entries.length - 1; index >= 0; index -= 1) {
|
|
133
161
|
const entry = entries[index];
|
|
134
162
|
if (entry?.kind === "compaction") {
|
|
135
|
-
previousSummary = entry.
|
|
163
|
+
previousSummary = compactionSummaryText(entry.model);
|
|
136
164
|
previousIndex = index;
|
|
137
|
-
const kept = entries.findIndex((candidate) => candidate.id === entry.
|
|
165
|
+
const kept = entries.findIndex((candidate) => candidate.id === entry.head);
|
|
138
166
|
boundaryStart = kept >= 0 ? kept : index + 1;
|
|
139
167
|
break;
|
|
140
168
|
}
|
|
@@ -281,8 +309,9 @@ instructions) {
|
|
|
281
309
|
catch: (error) => failure(error instanceof Error ? error.message : String(error)),
|
|
282
310
|
});
|
|
283
311
|
}
|
|
284
|
-
export function borrowedView(preparation, result, contextRevision) {
|
|
312
|
+
export function borrowedView(preparation, result, sessionId, contextRevision) {
|
|
285
313
|
return {
|
|
314
|
+
sessionId,
|
|
286
315
|
messagesToSummarize: preparation.messagesToSummarize,
|
|
287
316
|
turnPrefixMessages: preparation.turnPrefixMessages,
|
|
288
317
|
result,
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { type Message, type Model, type Api, type MuleRunOutcome, type MuleStreamFunction } from "@fungi.computer/mule/effect";
|
|
2
2
|
import * as Effect from "effect/Effect";
|
|
3
|
+
import type * as Scope from "effect/Scope";
|
|
3
4
|
import type { CompactionHandoffV0 } from "../../extensions.js";
|
|
4
5
|
import { ShiitakeError } from "../../errors.js";
|
|
6
|
+
import { type CompactionResult } from "./compaction.js";
|
|
5
7
|
import { type CompactionSettings } from "./utils.js";
|
|
6
8
|
import { type StoredSessionRow } from "../woodstock/index.js";
|
|
7
9
|
import type { SqliteOwner } from "../contracts.js";
|
|
8
10
|
declare const commitFailures: {
|
|
9
11
|
readonly handoff: "The compaction handoff failed; the conversation context is unchanged";
|
|
12
|
+
readonly handoffResult: "The compaction handoff failed: it returned an invalid result; the conversation context is unchanged";
|
|
10
13
|
readonly conflict: "The Session changed during compaction; the conversation context is unchanged";
|
|
11
14
|
};
|
|
12
15
|
/**
|
|
@@ -15,7 +18,8 @@ declare const commitFailures: {
|
|
|
15
18
|
*/
|
|
16
19
|
export declare class CompactionCommitError extends ShiitakeError {
|
|
17
20
|
readonly phase: keyof typeof commitFailures;
|
|
18
|
-
|
|
21
|
+
readonly usage?: CompactionResult["usage"] | undefined;
|
|
22
|
+
constructor(phase: keyof typeof commitFailures, usage?: CompactionResult["usage"] | undefined);
|
|
19
23
|
get diagnostic(): string;
|
|
20
24
|
}
|
|
21
25
|
/**
|
|
@@ -39,22 +43,10 @@ export type SessionCompactionInput = Readonly<{
|
|
|
39
43
|
run: (messages: readonly Message[], betweenTurns: BetweenTurns) => Effect.Effect<MuleRunOutcome, ShiitakeError>;
|
|
40
44
|
}>;
|
|
41
45
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
* A provider's reported usage measures the context it actually read, so it
|
|
46
|
-
* is authoritative only while nothing has reshaped that context since. Once
|
|
47
|
-
* a compaction lands, every kept message's own usage figure is stale: it
|
|
48
|
-
* priced the pre-compaction history, not the summary that replaced it. The
|
|
49
|
-
* one safe fallback is a fresh chars/4 estimate of every message still in
|
|
50
|
-
* view, the same method `tokensAfterCompaction` uses when it records the
|
|
51
|
-
* marker's own `tokensAfter` at commit time; trailing-after-usage alone
|
|
52
|
-
* would undercount (even to zero, when the kept tail's own reply is the
|
|
53
|
-
* newest message and nothing followed it).
|
|
46
|
+
* Compose the retained pre-run, between-turn and post-run compaction phases.
|
|
47
|
+
* A background compaction is a child fiber in the run's own scope.
|
|
54
48
|
*/
|
|
55
|
-
export declare function
|
|
56
|
-
/** Compose the retained pre-run, between-turn and post-run compaction phases. */
|
|
57
|
-
export declare function runWithCompaction(input: SessionCompactionInput): Effect.Effect<MuleRunOutcome, ShiitakeError>;
|
|
49
|
+
export declare function runWithCompaction(input: SessionCompactionInput): Effect.Effect<MuleRunOutcome, ShiitakeError, Scope.Scope>;
|
|
58
50
|
/** What a manual compaction did; a failure is the Effect's error. */
|
|
59
51
|
export type ManualCompactionOutcome = "compacted" | "nothing_to_compact";
|
|
60
52
|
/**
|