@earendil-works/pi-durable 0.0.1 → 0.86.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 +13 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/memory-storage.d.ts +37 -0
- package/dist/memory-storage.d.ts.map +1 -0
- package/dist/memory-storage.js +322 -0
- package/dist/memory-storage.js.map +1 -0
- package/dist/types.d.ts +312 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/docs/chord-delta-findings.md +358 -0
- package/docs/pico-v5-chord-usage.md +384 -0
- package/docs/pico-v5-handoff.md +341 -0
- package/docs/pico-v5.md +2031 -0
- package/package.json +50 -23
- package/index.js +0 -1
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
import type { Context, JsonValue } from "@earendil-works/chord";
|
|
2
|
+
import type { Message } from "@earendil-works/pi-ai";
|
|
3
|
+
/** Session-global identifier shared by every durable record table. */
|
|
4
|
+
export type Id = number;
|
|
5
|
+
/** Monotonic sequence assigned to one atomic storage commit. */
|
|
6
|
+
export type Seq = number;
|
|
7
|
+
/** The root conversation always uses this reserved ID. */
|
|
8
|
+
export declare const ROOT_CONVERSATION_ID: Id;
|
|
9
|
+
/** JSON-safe error snapshot persisted instead of a runtime `Error` object. */
|
|
10
|
+
export type StoredError = {
|
|
11
|
+
readonly message: string;
|
|
12
|
+
/** Optional structured diagnostic data for inspection or recovery. */
|
|
13
|
+
readonly detail?: JsonValue;
|
|
14
|
+
};
|
|
15
|
+
/** Immutable identity, history ancestry, and task ownership of a transcript scope. */
|
|
16
|
+
export type ConversationRecord = {
|
|
17
|
+
readonly id: Id;
|
|
18
|
+
/** Fork source and inclusive parent entry through which history is inherited. */
|
|
19
|
+
readonly parent?: {
|
|
20
|
+
readonly conversationId: Id;
|
|
21
|
+
readonly at: Id;
|
|
22
|
+
};
|
|
23
|
+
/** Creator edge used for authorization, subtree abort, and subtree idle waits. */
|
|
24
|
+
readonly owner?: {
|
|
25
|
+
readonly conversationId: Id;
|
|
26
|
+
readonly taskId: Id;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
/** An immutable override of one visible entry's contribution to model context. */
|
|
30
|
+
export type ContextEdit = {
|
|
31
|
+
/** Entry whose model messages are omitted or replaced. */
|
|
32
|
+
readonly target: Id;
|
|
33
|
+
} & ({
|
|
34
|
+
readonly action: "omit";
|
|
35
|
+
readonly messages?: never;
|
|
36
|
+
} | {
|
|
37
|
+
readonly action: "replace";
|
|
38
|
+
/** Messages contributed instead of the target entry's model messages. */
|
|
39
|
+
readonly messages: readonly Message[];
|
|
40
|
+
});
|
|
41
|
+
/** Immutable transcript event with separate model-facing and application-facing payloads. */
|
|
42
|
+
export type EntryRecord = {
|
|
43
|
+
readonly id: Id;
|
|
44
|
+
readonly conversationId: Id;
|
|
45
|
+
/** Application-defined entry discriminator. */
|
|
46
|
+
readonly kind: string;
|
|
47
|
+
/** Messages contributed to model context; absent for display or bookkeeping entries. */
|
|
48
|
+
readonly model?: readonly Message[];
|
|
49
|
+
/** JSON payload consumed by views, plugins, or bookkeeping logic. */
|
|
50
|
+
readonly data?: JsonValue;
|
|
51
|
+
/** First entry in the active context selected by this entry. */
|
|
52
|
+
readonly head?: Id;
|
|
53
|
+
/** Context-only overrides of earlier visible entries. */
|
|
54
|
+
readonly edits?: readonly ContextEdit[];
|
|
55
|
+
/** Task that appended this entry, when it was produced by durable work. */
|
|
56
|
+
readonly byTaskId?: Id;
|
|
57
|
+
};
|
|
58
|
+
/** Entry content supplied before the Session assigns identity and task attribution. */
|
|
59
|
+
export type EntryDraft = Omit<EntryRecord, "id" | "conversationId" | "byTaskId" | "head"> & {
|
|
60
|
+
/** `"self"` starts active context at the newly assigned entry ID. */
|
|
61
|
+
readonly head?: Id | "self";
|
|
62
|
+
};
|
|
63
|
+
/** Identity fields shared by every input lifecycle state. */
|
|
64
|
+
type InputBase = {
|
|
65
|
+
readonly id: Id;
|
|
66
|
+
readonly conversationId: Id;
|
|
67
|
+
/** Host-provided deduplication key, scoped to the conversation. */
|
|
68
|
+
readonly requestId?: string;
|
|
69
|
+
};
|
|
70
|
+
/** Durable lifecycle of one admitted host input and the handle waiting for it. */
|
|
71
|
+
export type Input = InputBase & ({
|
|
72
|
+
/** Admitted but not yet represented in the transcript. */
|
|
73
|
+
readonly status: "queued";
|
|
74
|
+
readonly entry?: never;
|
|
75
|
+
readonly answer?: never;
|
|
76
|
+
readonly reason?: never;
|
|
77
|
+
readonly detail?: never;
|
|
78
|
+
} | {
|
|
79
|
+
/** Added to the transcript and owned by an active turn. */
|
|
80
|
+
readonly status: "placed";
|
|
81
|
+
/** User transcript entry created when this input was placed. */
|
|
82
|
+
readonly entry: Id;
|
|
83
|
+
readonly answer?: never;
|
|
84
|
+
readonly reason?: never;
|
|
85
|
+
readonly detail?: never;
|
|
86
|
+
} | {
|
|
87
|
+
/** Successfully settled with a durable transcript result. */
|
|
88
|
+
readonly status: "done";
|
|
89
|
+
/** User or passive-write transcript entry created when this input was placed. */
|
|
90
|
+
readonly entry: Id;
|
|
91
|
+
/** Assistant answer entry; absent for a completed passive write. */
|
|
92
|
+
readonly answer?: Id;
|
|
93
|
+
readonly reason?: never;
|
|
94
|
+
readonly detail?: never;
|
|
95
|
+
} | {
|
|
96
|
+
/** Terminal input that can no longer receive an answer. */
|
|
97
|
+
readonly status: "unanswered";
|
|
98
|
+
/** Present when the input was placed before becoming unanswered. */
|
|
99
|
+
readonly entry?: Id;
|
|
100
|
+
readonly answer?: never;
|
|
101
|
+
/** Stable machine-readable explanation such as `"aborted"` or `"stale"`. */
|
|
102
|
+
readonly reason: string;
|
|
103
|
+
/** Optional structured diagnostic data. */
|
|
104
|
+
readonly detail?: JsonValue;
|
|
105
|
+
});
|
|
106
|
+
/** Durable reason and optional result recorded when a task becomes terminal. */
|
|
107
|
+
export type TaskOutcome<R> = {
|
|
108
|
+
readonly status: "completed";
|
|
109
|
+
readonly result: R;
|
|
110
|
+
readonly error?: never;
|
|
111
|
+
readonly reason?: never;
|
|
112
|
+
}
|
|
113
|
+
/** Expected task or domain failure explicitly committed by its implementation. */
|
|
114
|
+
| {
|
|
115
|
+
readonly status: "failed";
|
|
116
|
+
readonly error: StoredError;
|
|
117
|
+
readonly result?: R;
|
|
118
|
+
readonly reason?: never;
|
|
119
|
+
}
|
|
120
|
+
/** Explicit cancellation handled by the task's abort protocol. */
|
|
121
|
+
| {
|
|
122
|
+
readonly status: "aborted";
|
|
123
|
+
readonly reason?: string;
|
|
124
|
+
readonly result?: R;
|
|
125
|
+
readonly error?: never;
|
|
126
|
+
}
|
|
127
|
+
/** Task that cannot resume because its definition or migration is unavailable. */
|
|
128
|
+
| {
|
|
129
|
+
readonly status: "orphaned";
|
|
130
|
+
readonly reason: string;
|
|
131
|
+
readonly result?: never;
|
|
132
|
+
readonly error?: never;
|
|
133
|
+
}
|
|
134
|
+
/** Runtime-detected contract failure, such as an uncaught throw or no durable progress. */
|
|
135
|
+
| {
|
|
136
|
+
readonly status: "faulted";
|
|
137
|
+
readonly error: StoredError;
|
|
138
|
+
readonly result?: never;
|
|
139
|
+
readonly reason?: never;
|
|
140
|
+
};
|
|
141
|
+
/** Complete durable execution state of a task. */
|
|
142
|
+
export type TaskState<S, R> = {
|
|
143
|
+
/** Eligible for scheduling when its dependencies are terminal. */
|
|
144
|
+
readonly status: "pending";
|
|
145
|
+
/** Complete durable state from which execution resumes. */
|
|
146
|
+
readonly checkpoint: S;
|
|
147
|
+
readonly outcome?: never;
|
|
148
|
+
} | {
|
|
149
|
+
/** Reserved by one in-memory task invocation. */
|
|
150
|
+
readonly status: "running";
|
|
151
|
+
/** Complete durable state from which execution resumes. */
|
|
152
|
+
readonly checkpoint: S;
|
|
153
|
+
readonly outcome?: never;
|
|
154
|
+
} | {
|
|
155
|
+
/** Permanently settled durable result receipt. */
|
|
156
|
+
readonly status: "terminal";
|
|
157
|
+
readonly checkpoint?: never;
|
|
158
|
+
readonly outcome: TaskOutcome<R>;
|
|
159
|
+
};
|
|
160
|
+
/** Identity, definition, and scheduling fields shared by every task state. */
|
|
161
|
+
type TaskRecordBase<I> = {
|
|
162
|
+
readonly id: Id;
|
|
163
|
+
readonly conversationId: Id;
|
|
164
|
+
/** Registered task definition name. */
|
|
165
|
+
readonly kind: string;
|
|
166
|
+
/** Definition version used to migrate live input and checkpoints. */
|
|
167
|
+
readonly version: number;
|
|
168
|
+
/** Original task input retained while the task is live or terminal. */
|
|
169
|
+
readonly input: I;
|
|
170
|
+
/** Tasks that must be terminal before ordinary execution may begin. */
|
|
171
|
+
readonly after: readonly Id[];
|
|
172
|
+
/** Whether this task is excluded from ordinary idle waits and conversation aborts. */
|
|
173
|
+
readonly background: boolean;
|
|
174
|
+
/** Durable abort mark checked before run-mode progress is committed. */
|
|
175
|
+
readonly abortRequested: boolean;
|
|
176
|
+
};
|
|
177
|
+
/** Complete replacement record for one durable task state machine. */
|
|
178
|
+
export type TaskRecord<I, S, R> = TaskRecordBase<I> & ({
|
|
179
|
+
readonly state: Extract<TaskState<S, R>, {
|
|
180
|
+
readonly status: "pending" | "running";
|
|
181
|
+
}>;
|
|
182
|
+
/** Small first-writer-wins values retained while the task is live. */
|
|
183
|
+
readonly memos?: Readonly<Record<string, JsonValue>>;
|
|
184
|
+
} | {
|
|
185
|
+
readonly state: Extract<TaskState<S, R>, {
|
|
186
|
+
readonly status: "terminal";
|
|
187
|
+
}>;
|
|
188
|
+
readonly memos?: never;
|
|
189
|
+
});
|
|
190
|
+
/** Persisted lifecycle record for one create-to-retire document incarnation. */
|
|
191
|
+
export type DocumentRecord = {
|
|
192
|
+
/** Unique incarnation ID; never reused when the same logical document is recreated. */
|
|
193
|
+
readonly id: Id;
|
|
194
|
+
/** Registered document kind. */
|
|
195
|
+
readonly kind: string;
|
|
196
|
+
/** Family member key; absent for singleton documents. */
|
|
197
|
+
readonly key?: string;
|
|
198
|
+
/** Commit that created the incarnation, stamped by storage. */
|
|
199
|
+
readonly createdAt: Seq;
|
|
200
|
+
/** Commit that retired the incarnation; absent while it is current. */
|
|
201
|
+
readonly retiredAt?: Seq;
|
|
202
|
+
} & ({
|
|
203
|
+
readonly scope: {
|
|
204
|
+
readonly kind: "session";
|
|
205
|
+
};
|
|
206
|
+
readonly history?: never;
|
|
207
|
+
readonly fork?: never;
|
|
208
|
+
} | ({
|
|
209
|
+
readonly scope: {
|
|
210
|
+
readonly kind: "conversation";
|
|
211
|
+
readonly conversationId: Id;
|
|
212
|
+
};
|
|
213
|
+
} & ({
|
|
214
|
+
/** Retain only current state. */
|
|
215
|
+
readonly history: "latest";
|
|
216
|
+
/** Initialize a fork from current source state or the definition's initial value. */
|
|
217
|
+
readonly fork: "current" | "initial";
|
|
218
|
+
} | {
|
|
219
|
+
/** Retain history needed for as-of reads. */
|
|
220
|
+
readonly history: "rewindable";
|
|
221
|
+
/** Initialize a fork at its cutoff, from current state, or from the initial value. */
|
|
222
|
+
readonly fork: "asOf" | "current" | "initial";
|
|
223
|
+
})) | {
|
|
224
|
+
readonly scope: {
|
|
225
|
+
readonly kind: "task";
|
|
226
|
+
readonly taskId: Id;
|
|
227
|
+
};
|
|
228
|
+
readonly history?: never;
|
|
229
|
+
readonly fork?: never;
|
|
230
|
+
});
|
|
231
|
+
/** Fields supplied when storage creates and stamps a new `DocumentRecord`. */
|
|
232
|
+
export type DocumentCreate = DocumentRecord extends infer Record ? Record extends DocumentRecord ? Omit<Record, "createdAt" | "retiredAt"> : never : never;
|
|
233
|
+
/** One ordered scan result and its optional continuation state. */
|
|
234
|
+
export type Page<T, C> = {
|
|
235
|
+
readonly items: readonly T[];
|
|
236
|
+
readonly next?: C;
|
|
237
|
+
};
|
|
238
|
+
/** Backend-owned JSON continuation state that callers only round-trip to the same scan. */
|
|
239
|
+
export type Cursor = Readonly<Record<string, JsonValue>>;
|
|
240
|
+
/** Inclusive ID bounds for a newest-first scan of one conversation's fork-aware history. */
|
|
241
|
+
export type EntryQuery = {
|
|
242
|
+
readonly conversationId: Id;
|
|
243
|
+
/** Oldest entry ID that may be returned. */
|
|
244
|
+
readonly minEntryId?: Id;
|
|
245
|
+
/** Newest entry ID that may be returned. */
|
|
246
|
+
readonly maxEntryId?: Id;
|
|
247
|
+
};
|
|
248
|
+
/** Optional filters for an ordered scan of durable task records. */
|
|
249
|
+
export type TaskQuery = {
|
|
250
|
+
readonly conversationId?: Id;
|
|
251
|
+
readonly kind?: string;
|
|
252
|
+
readonly status?: "pending" | "running" | "terminal";
|
|
253
|
+
readonly abortRequested?: boolean;
|
|
254
|
+
readonly background?: boolean;
|
|
255
|
+
};
|
|
256
|
+
/** One table mutation in an atomic storage commit; task and input writes replace whole records. */
|
|
257
|
+
export type StorageWrite = {
|
|
258
|
+
readonly type: "conversation";
|
|
259
|
+
readonly value: ConversationRecord;
|
|
260
|
+
} | {
|
|
261
|
+
readonly type: "entry";
|
|
262
|
+
readonly value: EntryRecord;
|
|
263
|
+
} | {
|
|
264
|
+
readonly type: "task";
|
|
265
|
+
readonly value: TaskRecord<JsonValue, JsonValue, JsonValue>;
|
|
266
|
+
} | {
|
|
267
|
+
readonly type: "input";
|
|
268
|
+
readonly value: Input;
|
|
269
|
+
};
|
|
270
|
+
/**
|
|
271
|
+
* Atomic persistence boundary for Session records.
|
|
272
|
+
*
|
|
273
|
+
* Storage trusts the owning Session to supply semantically valid records, references,
|
|
274
|
+
* ancestry, and transitions. Implementations enforce atomicity, global ID ownership,
|
|
275
|
+
* immutable conversation/entry creation, and detached values; Session serializes commits.
|
|
276
|
+
*/
|
|
277
|
+
export interface Storage {
|
|
278
|
+
/** Atomically persist one batch and return the sequence assigned to that commit. */
|
|
279
|
+
commit(writes: readonly StorageWrite[], context: Context): Promise<Seq>;
|
|
280
|
+
/** Return a fresh candidate from the Session-global record ID namespace. */
|
|
281
|
+
mintId(): Id;
|
|
282
|
+
/** Look up one conversation by exact ID. */
|
|
283
|
+
conversation(id: Id, context: Context): Promise<ConversationRecord | undefined>;
|
|
284
|
+
/** Scan conversations in ascending ID order. */
|
|
285
|
+
scanConversations(cursor: Cursor | undefined, limit: number, context: Context): Promise<Page<ConversationRecord, Cursor>>;
|
|
286
|
+
/** Look up one global entry and the sequence of the commit that persisted it. */
|
|
287
|
+
entry(id: Id, context: Context): Promise<{
|
|
288
|
+
readonly entry: EntryRecord;
|
|
289
|
+
readonly commitSeq: Seq;
|
|
290
|
+
} | undefined>;
|
|
291
|
+
/**
|
|
292
|
+
* Return the newest visible entry with a `head` at or below the optional inclusive cutoff.
|
|
293
|
+
* The returned entry is the marker; its `head` value is the range's actual lower bound.
|
|
294
|
+
*/
|
|
295
|
+
findLatestHeadMarker(conversationId: Id, atOrBeforeEntryId: Id | undefined, context: Context): Promise<(EntryRecord & {
|
|
296
|
+
readonly head: Id;
|
|
297
|
+
}) | undefined>;
|
|
298
|
+
/** Scan the inclusive visible range newest-first, returning at most `limit` entries. */
|
|
299
|
+
scanEntries(query: EntryQuery, cursor: Cursor | undefined, limit: number, context: Context): Promise<Page<EntryRecord, Cursor>>;
|
|
300
|
+
/** Look up the latest complete record for one task. */
|
|
301
|
+
task(id: Id, context: Context): Promise<TaskRecord<JsonValue, JsonValue, JsonValue> | undefined>;
|
|
302
|
+
/** Scan task records matching every supplied filter. */
|
|
303
|
+
scanTasks(query: TaskQuery, cursor: Cursor | undefined, limit: number, context: Context): Promise<Page<TaskRecord<JsonValue, JsonValue, JsonValue>, Cursor>>;
|
|
304
|
+
/** Look up the latest complete record for one admitted input. */
|
|
305
|
+
input(id: Id, context: Context): Promise<Input | undefined>;
|
|
306
|
+
/** Find an input by its conversation-scoped host deduplication key. */
|
|
307
|
+
inputByRequest(conversationId: Id, requestId: string, context: Context): Promise<Input | undefined>;
|
|
308
|
+
/** Release backend resources; all later operations must reject. */
|
|
309
|
+
close(context: Context): Promise<void>;
|
|
310
|
+
}
|
|
311
|
+
export {};
|
|
312
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Context, JsonValue } from \"@earendil-works/chord\";\nimport type { Message } from \"@earendil-works/pi-ai\";\n\n/** Session-global identifier shared by every durable record table. */\nexport type Id = number;\n\n/** Monotonic sequence assigned to one atomic storage commit. */\nexport type Seq = number;\n\n/** The root conversation always uses this reserved ID. */\nexport const ROOT_CONVERSATION_ID: Id = 1;\n\n/** JSON-safe error snapshot persisted instead of a runtime `Error` object. */\nexport type StoredError = {\n\treadonly message: string;\n\t/** Optional structured diagnostic data for inspection or recovery. */\n\treadonly detail?: JsonValue;\n};\n\n/** Immutable identity, history ancestry, and task ownership of a transcript scope. */\nexport type ConversationRecord = {\n\treadonly id: Id;\n\t/** Fork source and inclusive parent entry through which history is inherited. */\n\treadonly parent?: {\n\t\treadonly conversationId: Id;\n\t\treadonly at: Id;\n\t};\n\t/** Creator edge used for authorization, subtree abort, and subtree idle waits. */\n\treadonly owner?: {\n\t\treadonly conversationId: Id;\n\t\treadonly taskId: Id;\n\t};\n};\n\n/** An immutable override of one visible entry's contribution to model context. */\nexport type ContextEdit = {\n\t/** Entry whose model messages are omitted or replaced. */\n\treadonly target: Id;\n} & (\n\t| {\n\t\t\treadonly action: \"omit\";\n\t\t\treadonly messages?: never;\n\t }\n\t| {\n\t\t\treadonly action: \"replace\";\n\t\t\t/** Messages contributed instead of the target entry's model messages. */\n\t\t\treadonly messages: readonly Message[];\n\t }\n);\n\n/** Immutable transcript event with separate model-facing and application-facing payloads. */\nexport type EntryRecord = {\n\treadonly id: Id;\n\treadonly conversationId: Id;\n\t/** Application-defined entry discriminator. */\n\treadonly kind: string;\n\t/** Messages contributed to model context; absent for display or bookkeeping entries. */\n\treadonly model?: readonly Message[];\n\t/** JSON payload consumed by views, plugins, or bookkeeping logic. */\n\treadonly data?: JsonValue;\n\t/** First entry in the active context selected by this entry. */\n\treadonly head?: Id;\n\t/** Context-only overrides of earlier visible entries. */\n\treadonly edits?: readonly ContextEdit[];\n\t/** Task that appended this entry, when it was produced by durable work. */\n\treadonly byTaskId?: Id;\n};\n\n/** Entry content supplied before the Session assigns identity and task attribution. */\nexport type EntryDraft = Omit<EntryRecord, \"id\" | \"conversationId\" | \"byTaskId\" | \"head\"> & {\n\t/** `\"self\"` starts active context at the newly assigned entry ID. */\n\treadonly head?: Id | \"self\";\n};\n\n/** Identity fields shared by every input lifecycle state. */\ntype InputBase = {\n\treadonly id: Id;\n\treadonly conversationId: Id;\n\t/** Host-provided deduplication key, scoped to the conversation. */\n\treadonly requestId?: string;\n};\n\n/** Durable lifecycle of one admitted host input and the handle waiting for it. */\nexport type Input = InputBase &\n\t(\n\t\t| {\n\t\t\t\t/** Admitted but not yet represented in the transcript. */\n\t\t\t\treadonly status: \"queued\";\n\t\t\t\treadonly entry?: never;\n\t\t\t\treadonly answer?: never;\n\t\t\t\treadonly reason?: never;\n\t\t\t\treadonly detail?: never;\n\t\t }\n\t\t| {\n\t\t\t\t/** Added to the transcript and owned by an active turn. */\n\t\t\t\treadonly status: \"placed\";\n\t\t\t\t/** User transcript entry created when this input was placed. */\n\t\t\t\treadonly entry: Id;\n\t\t\t\treadonly answer?: never;\n\t\t\t\treadonly reason?: never;\n\t\t\t\treadonly detail?: never;\n\t\t }\n\t\t| {\n\t\t\t\t/** Successfully settled with a durable transcript result. */\n\t\t\t\treadonly status: \"done\";\n\t\t\t\t/** User or passive-write transcript entry created when this input was placed. */\n\t\t\t\treadonly entry: Id;\n\t\t\t\t/** Assistant answer entry; absent for a completed passive write. */\n\t\t\t\treadonly answer?: Id;\n\t\t\t\treadonly reason?: never;\n\t\t\t\treadonly detail?: never;\n\t\t }\n\t\t| {\n\t\t\t\t/** Terminal input that can no longer receive an answer. */\n\t\t\t\treadonly status: \"unanswered\";\n\t\t\t\t/** Present when the input was placed before becoming unanswered. */\n\t\t\t\treadonly entry?: Id;\n\t\t\t\treadonly answer?: never;\n\t\t\t\t/** Stable machine-readable explanation such as `\"aborted\"` or `\"stale\"`. */\n\t\t\t\treadonly reason: string;\n\t\t\t\t/** Optional structured diagnostic data. */\n\t\t\t\treadonly detail?: JsonValue;\n\t\t }\n\t);\n\n/** Durable reason and optional result recorded when a task becomes terminal. */\nexport type TaskOutcome<R> =\n\t| {\n\t\t\treadonly status: \"completed\";\n\t\t\treadonly result: R;\n\t\t\treadonly error?: never;\n\t\t\treadonly reason?: never;\n\t }\n\t/** Expected task or domain failure explicitly committed by its implementation. */\n\t| {\n\t\t\treadonly status: \"failed\";\n\t\t\treadonly error: StoredError;\n\t\t\treadonly result?: R;\n\t\t\treadonly reason?: never;\n\t }\n\t/** Explicit cancellation handled by the task's abort protocol. */\n\t| {\n\t\t\treadonly status: \"aborted\";\n\t\t\treadonly reason?: string;\n\t\t\treadonly result?: R;\n\t\t\treadonly error?: never;\n\t }\n\t/** Task that cannot resume because its definition or migration is unavailable. */\n\t| {\n\t\t\treadonly status: \"orphaned\";\n\t\t\treadonly reason: string;\n\t\t\treadonly result?: never;\n\t\t\treadonly error?: never;\n\t }\n\t/** Runtime-detected contract failure, such as an uncaught throw or no durable progress. */\n\t| {\n\t\t\treadonly status: \"faulted\";\n\t\t\treadonly error: StoredError;\n\t\t\treadonly result?: never;\n\t\t\treadonly reason?: never;\n\t };\n\n/** Complete durable execution state of a task. */\nexport type TaskState<S, R> =\n\t| {\n\t\t\t/** Eligible for scheduling when its dependencies are terminal. */\n\t\t\treadonly status: \"pending\";\n\t\t\t/** Complete durable state from which execution resumes. */\n\t\t\treadonly checkpoint: S;\n\t\t\treadonly outcome?: never;\n\t }\n\t| {\n\t\t\t/** Reserved by one in-memory task invocation. */\n\t\t\treadonly status: \"running\";\n\t\t\t/** Complete durable state from which execution resumes. */\n\t\t\treadonly checkpoint: S;\n\t\t\treadonly outcome?: never;\n\t }\n\t| {\n\t\t\t/** Permanently settled durable result receipt. */\n\t\t\treadonly status: \"terminal\";\n\t\t\treadonly checkpoint?: never;\n\t\t\treadonly outcome: TaskOutcome<R>;\n\t };\n\n/** Identity, definition, and scheduling fields shared by every task state. */\ntype TaskRecordBase<I> = {\n\treadonly id: Id;\n\treadonly conversationId: Id;\n\t/** Registered task definition name. */\n\treadonly kind: string;\n\t/** Definition version used to migrate live input and checkpoints. */\n\treadonly version: number;\n\t/** Original task input retained while the task is live or terminal. */\n\treadonly input: I;\n\t/** Tasks that must be terminal before ordinary execution may begin. */\n\treadonly after: readonly Id[];\n\t/** Whether this task is excluded from ordinary idle waits and conversation aborts. */\n\treadonly background: boolean;\n\t/** Durable abort mark checked before run-mode progress is committed. */\n\treadonly abortRequested: boolean;\n};\n\n/** Complete replacement record for one durable task state machine. */\nexport type TaskRecord<I, S, R> = TaskRecordBase<I> &\n\t(\n\t\t| {\n\t\t\t\treadonly state: Extract<TaskState<S, R>, { readonly status: \"pending\" | \"running\" }>;\n\t\t\t\t/** Small first-writer-wins values retained while the task is live. */\n\t\t\t\treadonly memos?: Readonly<Record<string, JsonValue>>;\n\t\t }\n\t\t| {\n\t\t\t\treadonly state: Extract<TaskState<S, R>, { readonly status: \"terminal\" }>;\n\t\t\t\treadonly memos?: never;\n\t\t }\n\t);\n\n/** Persisted lifecycle record for one create-to-retire document incarnation. */\nexport type DocumentRecord = {\n\t/** Unique incarnation ID; never reused when the same logical document is recreated. */\n\treadonly id: Id;\n\t/** Registered document kind. */\n\treadonly kind: string;\n\t/** Family member key; absent for singleton documents. */\n\treadonly key?: string;\n\t/** Commit that created the incarnation, stamped by storage. */\n\treadonly createdAt: Seq;\n\t/** Commit that retired the incarnation; absent while it is current. */\n\treadonly retiredAt?: Seq;\n} & (\n\t| {\n\t\t\treadonly scope: { readonly kind: \"session\" };\n\t\t\treadonly history?: never;\n\t\t\treadonly fork?: never;\n\t }\n\t| ({ readonly scope: { readonly kind: \"conversation\"; readonly conversationId: Id } } & (\n\t\t\t| {\n\t\t\t\t\t/** Retain only current state. */\n\t\t\t\t\treadonly history: \"latest\";\n\t\t\t\t\t/** Initialize a fork from current source state or the definition's initial value. */\n\t\t\t\t\treadonly fork: \"current\" | \"initial\";\n\t\t\t }\n\t\t\t| {\n\t\t\t\t\t/** Retain history needed for as-of reads. */\n\t\t\t\t\treadonly history: \"rewindable\";\n\t\t\t\t\t/** Initialize a fork at its cutoff, from current state, or from the initial value. */\n\t\t\t\t\treadonly fork: \"asOf\" | \"current\" | \"initial\";\n\t\t\t }\n\t ))\n\t| {\n\t\t\treadonly scope: { readonly kind: \"task\"; readonly taskId: Id };\n\t\t\treadonly history?: never;\n\t\t\treadonly fork?: never;\n\t }\n);\n\n/** Fields supplied when storage creates and stamps a new `DocumentRecord`. */\nexport type DocumentCreate = DocumentRecord extends infer Record\n\t? Record extends DocumentRecord\n\t\t? Omit<Record, \"createdAt\" | \"retiredAt\">\n\t\t: never\n\t: never;\n\n/** One ordered scan result and its optional continuation state. */\nexport type Page<T, C> = {\n\treadonly items: readonly T[];\n\treadonly next?: C;\n};\n\n/** Backend-owned JSON continuation state that callers only round-trip to the same scan. */\nexport type Cursor = Readonly<Record<string, JsonValue>>;\n\n/** Inclusive ID bounds for a newest-first scan of one conversation's fork-aware history. */\nexport type EntryQuery = {\n\treadonly conversationId: Id;\n\t/** Oldest entry ID that may be returned. */\n\treadonly minEntryId?: Id;\n\t/** Newest entry ID that may be returned. */\n\treadonly maxEntryId?: Id;\n};\n\n/** Optional filters for an ordered scan of durable task records. */\nexport type TaskQuery = {\n\treadonly conversationId?: Id;\n\treadonly kind?: string;\n\treadonly status?: \"pending\" | \"running\" | \"terminal\";\n\treadonly abortRequested?: boolean;\n\treadonly background?: boolean;\n};\n\n/** One table mutation in an atomic storage commit; task and input writes replace whole records. */\nexport type StorageWrite =\n\t| { readonly type: \"conversation\"; readonly value: ConversationRecord }\n\t| { readonly type: \"entry\"; readonly value: EntryRecord }\n\t| { readonly type: \"task\"; readonly value: TaskRecord<JsonValue, JsonValue, JsonValue> }\n\t| { readonly type: \"input\"; readonly value: Input };\n\n/**\n * Atomic persistence boundary for Session records.\n *\n * Storage trusts the owning Session to supply semantically valid records, references,\n * ancestry, and transitions. Implementations enforce atomicity, global ID ownership,\n * immutable conversation/entry creation, and detached values; Session serializes commits.\n */\nexport interface Storage {\n\t/** Atomically persist one batch and return the sequence assigned to that commit. */\n\tcommit(writes: readonly StorageWrite[], context: Context): Promise<Seq>;\n\n\t/** Return a fresh candidate from the Session-global record ID namespace. */\n\tmintId(): Id;\n\n\t/** Look up one conversation by exact ID. */\n\tconversation(id: Id, context: Context): Promise<ConversationRecord | undefined>;\n\n\t/** Scan conversations in ascending ID order. */\n\tscanConversations(\n\t\tcursor: Cursor | undefined,\n\t\tlimit: number,\n\t\tcontext: Context,\n\t): Promise<Page<ConversationRecord, Cursor>>;\n\n\t/** Look up one global entry and the sequence of the commit that persisted it. */\n\tentry(id: Id, context: Context): Promise<{ readonly entry: EntryRecord; readonly commitSeq: Seq } | undefined>;\n\n\t/**\n\t * Return the newest visible entry with a `head` at or below the optional inclusive cutoff.\n\t * The returned entry is the marker; its `head` value is the range's actual lower bound.\n\t */\n\tfindLatestHeadMarker(\n\t\tconversationId: Id,\n\t\tatOrBeforeEntryId: Id | undefined,\n\t\tcontext: Context,\n\t): Promise<(EntryRecord & { readonly head: Id }) | undefined>;\n\n\t/** Scan the inclusive visible range newest-first, returning at most `limit` entries. */\n\tscanEntries(\n\t\tquery: EntryQuery,\n\t\tcursor: Cursor | undefined,\n\t\tlimit: number,\n\t\tcontext: Context,\n\t): Promise<Page<EntryRecord, Cursor>>;\n\n\t/** Look up the latest complete record for one task. */\n\ttask(id: Id, context: Context): Promise<TaskRecord<JsonValue, JsonValue, JsonValue> | undefined>;\n\n\t/** Scan task records matching every supplied filter. */\n\tscanTasks(\n\t\tquery: TaskQuery,\n\t\tcursor: Cursor | undefined,\n\t\tlimit: number,\n\t\tcontext: Context,\n\t): Promise<Page<TaskRecord<JsonValue, JsonValue, JsonValue>, Cursor>>;\n\n\t/** Look up the latest complete record for one admitted input. */\n\tinput(id: Id, context: Context): Promise<Input | undefined>;\n\n\t/** Find an input by its conversation-scoped host deduplication key. */\n\tinputByRequest(conversationId: Id, requestId: string, context: Context): Promise<Input | undefined>;\n\n\t/** Release backend resources; all later operations must reject. */\n\tclose(context: Context): Promise<void>;\n}\n"]}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AASA,0DAA0D;AAC1D,MAAM,CAAC,MAAM,oBAAoB,GAAO,CAAC,CAAC","sourcesContent":["import type { Context, JsonValue } from \"@earendil-works/chord\";\nimport type { Message } from \"@earendil-works/pi-ai\";\n\n/** Session-global identifier shared by every durable record table. */\nexport type Id = number;\n\n/** Monotonic sequence assigned to one atomic storage commit. */\nexport type Seq = number;\n\n/** The root conversation always uses this reserved ID. */\nexport const ROOT_CONVERSATION_ID: Id = 1;\n\n/** JSON-safe error snapshot persisted instead of a runtime `Error` object. */\nexport type StoredError = {\n\treadonly message: string;\n\t/** Optional structured diagnostic data for inspection or recovery. */\n\treadonly detail?: JsonValue;\n};\n\n/** Immutable identity, history ancestry, and task ownership of a transcript scope. */\nexport type ConversationRecord = {\n\treadonly id: Id;\n\t/** Fork source and inclusive parent entry through which history is inherited. */\n\treadonly parent?: {\n\t\treadonly conversationId: Id;\n\t\treadonly at: Id;\n\t};\n\t/** Creator edge used for authorization, subtree abort, and subtree idle waits. */\n\treadonly owner?: {\n\t\treadonly conversationId: Id;\n\t\treadonly taskId: Id;\n\t};\n};\n\n/** An immutable override of one visible entry's contribution to model context. */\nexport type ContextEdit = {\n\t/** Entry whose model messages are omitted or replaced. */\n\treadonly target: Id;\n} & (\n\t| {\n\t\t\treadonly action: \"omit\";\n\t\t\treadonly messages?: never;\n\t }\n\t| {\n\t\t\treadonly action: \"replace\";\n\t\t\t/** Messages contributed instead of the target entry's model messages. */\n\t\t\treadonly messages: readonly Message[];\n\t }\n);\n\n/** Immutable transcript event with separate model-facing and application-facing payloads. */\nexport type EntryRecord = {\n\treadonly id: Id;\n\treadonly conversationId: Id;\n\t/** Application-defined entry discriminator. */\n\treadonly kind: string;\n\t/** Messages contributed to model context; absent for display or bookkeeping entries. */\n\treadonly model?: readonly Message[];\n\t/** JSON payload consumed by views, plugins, or bookkeeping logic. */\n\treadonly data?: JsonValue;\n\t/** First entry in the active context selected by this entry. */\n\treadonly head?: Id;\n\t/** Context-only overrides of earlier visible entries. */\n\treadonly edits?: readonly ContextEdit[];\n\t/** Task that appended this entry, when it was produced by durable work. */\n\treadonly byTaskId?: Id;\n};\n\n/** Entry content supplied before the Session assigns identity and task attribution. */\nexport type EntryDraft = Omit<EntryRecord, \"id\" | \"conversationId\" | \"byTaskId\" | \"head\"> & {\n\t/** `\"self\"` starts active context at the newly assigned entry ID. */\n\treadonly head?: Id | \"self\";\n};\n\n/** Identity fields shared by every input lifecycle state. */\ntype InputBase = {\n\treadonly id: Id;\n\treadonly conversationId: Id;\n\t/** Host-provided deduplication key, scoped to the conversation. */\n\treadonly requestId?: string;\n};\n\n/** Durable lifecycle of one admitted host input and the handle waiting for it. */\nexport type Input = InputBase &\n\t(\n\t\t| {\n\t\t\t\t/** Admitted but not yet represented in the transcript. */\n\t\t\t\treadonly status: \"queued\";\n\t\t\t\treadonly entry?: never;\n\t\t\t\treadonly answer?: never;\n\t\t\t\treadonly reason?: never;\n\t\t\t\treadonly detail?: never;\n\t\t }\n\t\t| {\n\t\t\t\t/** Added to the transcript and owned by an active turn. */\n\t\t\t\treadonly status: \"placed\";\n\t\t\t\t/** User transcript entry created when this input was placed. */\n\t\t\t\treadonly entry: Id;\n\t\t\t\treadonly answer?: never;\n\t\t\t\treadonly reason?: never;\n\t\t\t\treadonly detail?: never;\n\t\t }\n\t\t| {\n\t\t\t\t/** Successfully settled with a durable transcript result. */\n\t\t\t\treadonly status: \"done\";\n\t\t\t\t/** User or passive-write transcript entry created when this input was placed. */\n\t\t\t\treadonly entry: Id;\n\t\t\t\t/** Assistant answer entry; absent for a completed passive write. */\n\t\t\t\treadonly answer?: Id;\n\t\t\t\treadonly reason?: never;\n\t\t\t\treadonly detail?: never;\n\t\t }\n\t\t| {\n\t\t\t\t/** Terminal input that can no longer receive an answer. */\n\t\t\t\treadonly status: \"unanswered\";\n\t\t\t\t/** Present when the input was placed before becoming unanswered. */\n\t\t\t\treadonly entry?: Id;\n\t\t\t\treadonly answer?: never;\n\t\t\t\t/** Stable machine-readable explanation such as `\"aborted\"` or `\"stale\"`. */\n\t\t\t\treadonly reason: string;\n\t\t\t\t/** Optional structured diagnostic data. */\n\t\t\t\treadonly detail?: JsonValue;\n\t\t }\n\t);\n\n/** Durable reason and optional result recorded when a task becomes terminal. */\nexport type TaskOutcome<R> =\n\t| {\n\t\t\treadonly status: \"completed\";\n\t\t\treadonly result: R;\n\t\t\treadonly error?: never;\n\t\t\treadonly reason?: never;\n\t }\n\t/** Expected task or domain failure explicitly committed by its implementation. */\n\t| {\n\t\t\treadonly status: \"failed\";\n\t\t\treadonly error: StoredError;\n\t\t\treadonly result?: R;\n\t\t\treadonly reason?: never;\n\t }\n\t/** Explicit cancellation handled by the task's abort protocol. */\n\t| {\n\t\t\treadonly status: \"aborted\";\n\t\t\treadonly reason?: string;\n\t\t\treadonly result?: R;\n\t\t\treadonly error?: never;\n\t }\n\t/** Task that cannot resume because its definition or migration is unavailable. */\n\t| {\n\t\t\treadonly status: \"orphaned\";\n\t\t\treadonly reason: string;\n\t\t\treadonly result?: never;\n\t\t\treadonly error?: never;\n\t }\n\t/** Runtime-detected contract failure, such as an uncaught throw or no durable progress. */\n\t| {\n\t\t\treadonly status: \"faulted\";\n\t\t\treadonly error: StoredError;\n\t\t\treadonly result?: never;\n\t\t\treadonly reason?: never;\n\t };\n\n/** Complete durable execution state of a task. */\nexport type TaskState<S, R> =\n\t| {\n\t\t\t/** Eligible for scheduling when its dependencies are terminal. */\n\t\t\treadonly status: \"pending\";\n\t\t\t/** Complete durable state from which execution resumes. */\n\t\t\treadonly checkpoint: S;\n\t\t\treadonly outcome?: never;\n\t }\n\t| {\n\t\t\t/** Reserved by one in-memory task invocation. */\n\t\t\treadonly status: \"running\";\n\t\t\t/** Complete durable state from which execution resumes. */\n\t\t\treadonly checkpoint: S;\n\t\t\treadonly outcome?: never;\n\t }\n\t| {\n\t\t\t/** Permanently settled durable result receipt. */\n\t\t\treadonly status: \"terminal\";\n\t\t\treadonly checkpoint?: never;\n\t\t\treadonly outcome: TaskOutcome<R>;\n\t };\n\n/** Identity, definition, and scheduling fields shared by every task state. */\ntype TaskRecordBase<I> = {\n\treadonly id: Id;\n\treadonly conversationId: Id;\n\t/** Registered task definition name. */\n\treadonly kind: string;\n\t/** Definition version used to migrate live input and checkpoints. */\n\treadonly version: number;\n\t/** Original task input retained while the task is live or terminal. */\n\treadonly input: I;\n\t/** Tasks that must be terminal before ordinary execution may begin. */\n\treadonly after: readonly Id[];\n\t/** Whether this task is excluded from ordinary idle waits and conversation aborts. */\n\treadonly background: boolean;\n\t/** Durable abort mark checked before run-mode progress is committed. */\n\treadonly abortRequested: boolean;\n};\n\n/** Complete replacement record for one durable task state machine. */\nexport type TaskRecord<I, S, R> = TaskRecordBase<I> &\n\t(\n\t\t| {\n\t\t\t\treadonly state: Extract<TaskState<S, R>, { readonly status: \"pending\" | \"running\" }>;\n\t\t\t\t/** Small first-writer-wins values retained while the task is live. */\n\t\t\t\treadonly memos?: Readonly<Record<string, JsonValue>>;\n\t\t }\n\t\t| {\n\t\t\t\treadonly state: Extract<TaskState<S, R>, { readonly status: \"terminal\" }>;\n\t\t\t\treadonly memos?: never;\n\t\t }\n\t);\n\n/** Persisted lifecycle record for one create-to-retire document incarnation. */\nexport type DocumentRecord = {\n\t/** Unique incarnation ID; never reused when the same logical document is recreated. */\n\treadonly id: Id;\n\t/** Registered document kind. */\n\treadonly kind: string;\n\t/** Family member key; absent for singleton documents. */\n\treadonly key?: string;\n\t/** Commit that created the incarnation, stamped by storage. */\n\treadonly createdAt: Seq;\n\t/** Commit that retired the incarnation; absent while it is current. */\n\treadonly retiredAt?: Seq;\n} & (\n\t| {\n\t\t\treadonly scope: { readonly kind: \"session\" };\n\t\t\treadonly history?: never;\n\t\t\treadonly fork?: never;\n\t }\n\t| ({ readonly scope: { readonly kind: \"conversation\"; readonly conversationId: Id } } & (\n\t\t\t| {\n\t\t\t\t\t/** Retain only current state. */\n\t\t\t\t\treadonly history: \"latest\";\n\t\t\t\t\t/** Initialize a fork from current source state or the definition's initial value. */\n\t\t\t\t\treadonly fork: \"current\" | \"initial\";\n\t\t\t }\n\t\t\t| {\n\t\t\t\t\t/** Retain history needed for as-of reads. */\n\t\t\t\t\treadonly history: \"rewindable\";\n\t\t\t\t\t/** Initialize a fork at its cutoff, from current state, or from the initial value. */\n\t\t\t\t\treadonly fork: \"asOf\" | \"current\" | \"initial\";\n\t\t\t }\n\t ))\n\t| {\n\t\t\treadonly scope: { readonly kind: \"task\"; readonly taskId: Id };\n\t\t\treadonly history?: never;\n\t\t\treadonly fork?: never;\n\t }\n);\n\n/** Fields supplied when storage creates and stamps a new `DocumentRecord`. */\nexport type DocumentCreate = DocumentRecord extends infer Record\n\t? Record extends DocumentRecord\n\t\t? Omit<Record, \"createdAt\" | \"retiredAt\">\n\t\t: never\n\t: never;\n\n/** One ordered scan result and its optional continuation state. */\nexport type Page<T, C> = {\n\treadonly items: readonly T[];\n\treadonly next?: C;\n};\n\n/** Backend-owned JSON continuation state that callers only round-trip to the same scan. */\nexport type Cursor = Readonly<Record<string, JsonValue>>;\n\n/** Inclusive ID bounds for a newest-first scan of one conversation's fork-aware history. */\nexport type EntryQuery = {\n\treadonly conversationId: Id;\n\t/** Oldest entry ID that may be returned. */\n\treadonly minEntryId?: Id;\n\t/** Newest entry ID that may be returned. */\n\treadonly maxEntryId?: Id;\n};\n\n/** Optional filters for an ordered scan of durable task records. */\nexport type TaskQuery = {\n\treadonly conversationId?: Id;\n\treadonly kind?: string;\n\treadonly status?: \"pending\" | \"running\" | \"terminal\";\n\treadonly abortRequested?: boolean;\n\treadonly background?: boolean;\n};\n\n/** One table mutation in an atomic storage commit; task and input writes replace whole records. */\nexport type StorageWrite =\n\t| { readonly type: \"conversation\"; readonly value: ConversationRecord }\n\t| { readonly type: \"entry\"; readonly value: EntryRecord }\n\t| { readonly type: \"task\"; readonly value: TaskRecord<JsonValue, JsonValue, JsonValue> }\n\t| { readonly type: \"input\"; readonly value: Input };\n\n/**\n * Atomic persistence boundary for Session records.\n *\n * Storage trusts the owning Session to supply semantically valid records, references,\n * ancestry, and transitions. Implementations enforce atomicity, global ID ownership,\n * immutable conversation/entry creation, and detached values; Session serializes commits.\n */\nexport interface Storage {\n\t/** Atomically persist one batch and return the sequence assigned to that commit. */\n\tcommit(writes: readonly StorageWrite[], context: Context): Promise<Seq>;\n\n\t/** Return a fresh candidate from the Session-global record ID namespace. */\n\tmintId(): Id;\n\n\t/** Look up one conversation by exact ID. */\n\tconversation(id: Id, context: Context): Promise<ConversationRecord | undefined>;\n\n\t/** Scan conversations in ascending ID order. */\n\tscanConversations(\n\t\tcursor: Cursor | undefined,\n\t\tlimit: number,\n\t\tcontext: Context,\n\t): Promise<Page<ConversationRecord, Cursor>>;\n\n\t/** Look up one global entry and the sequence of the commit that persisted it. */\n\tentry(id: Id, context: Context): Promise<{ readonly entry: EntryRecord; readonly commitSeq: Seq } | undefined>;\n\n\t/**\n\t * Return the newest visible entry with a `head` at or below the optional inclusive cutoff.\n\t * The returned entry is the marker; its `head` value is the range's actual lower bound.\n\t */\n\tfindLatestHeadMarker(\n\t\tconversationId: Id,\n\t\tatOrBeforeEntryId: Id | undefined,\n\t\tcontext: Context,\n\t): Promise<(EntryRecord & { readonly head: Id }) | undefined>;\n\n\t/** Scan the inclusive visible range newest-first, returning at most `limit` entries. */\n\tscanEntries(\n\t\tquery: EntryQuery,\n\t\tcursor: Cursor | undefined,\n\t\tlimit: number,\n\t\tcontext: Context,\n\t): Promise<Page<EntryRecord, Cursor>>;\n\n\t/** Look up the latest complete record for one task. */\n\ttask(id: Id, context: Context): Promise<TaskRecord<JsonValue, JsonValue, JsonValue> | undefined>;\n\n\t/** Scan task records matching every supplied filter. */\n\tscanTasks(\n\t\tquery: TaskQuery,\n\t\tcursor: Cursor | undefined,\n\t\tlimit: number,\n\t\tcontext: Context,\n\t): Promise<Page<TaskRecord<JsonValue, JsonValue, JsonValue>, Cursor>>;\n\n\t/** Look up the latest complete record for one admitted input. */\n\tinput(id: Id, context: Context): Promise<Input | undefined>;\n\n\t/** Find an input by its conversation-scoped host deduplication key. */\n\tinputByRequest(conversationId: Id, requestId: string, context: Context): Promise<Input | undefined>;\n\n\t/** Release backend resources; all later operations must reject. */\n\tclose(context: Context): Promise<void>;\n}\n"]}
|