@earendil-works/pi-agent-core 0.85.0 → 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 +16 -6
- package/dist/agent-loop.d.ts.map +1 -1
- package/dist/agent-loop.js +64 -22
- package/dist/agent-loop.js.map +1 -1
- package/dist/agent.d.ts +5 -3
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +15 -6
- package/dist/agent.js.map +1 -1
- package/dist/harness/config.d.ts +1 -1
- package/dist/harness/config.d.ts.map +1 -1
- package/dist/harness/config.js +10 -2
- package/dist/harness/config.js.map +1 -1
- package/dist/harness/env/nodejs.d.ts +2 -1
- package/dist/harness/env/nodejs.d.ts.map +1 -1
- package/dist/harness/env/nodejs.js +98 -27
- package/dist/harness/env/nodejs.js.map +1 -1
- package/dist/harness/execution/tools.d.ts +1 -1
- package/dist/harness/execution/tools.d.ts.map +1 -1
- package/dist/harness/execution/tools.js +0 -2
- package/dist/harness/execution/tools.js.map +1 -1
- package/dist/harness/messages.d.ts.map +1 -1
- package/dist/harness/messages.js +1 -0
- package/dist/harness/messages.js.map +1 -1
- package/dist/harness/pico3/bash.d.ts +10 -0
- package/dist/harness/pico3/bash.d.ts.map +1 -0
- package/dist/harness/pico3/bash.js +25 -0
- package/dist/harness/pico3/bash.js.map +1 -0
- package/dist/harness/pico3/bounded.d.ts +21 -0
- package/dist/harness/pico3/bounded.d.ts.map +1 -0
- package/dist/harness/pico3/bounded.js +98 -0
- package/dist/harness/pico3/bounded.js.map +1 -0
- package/dist/harness/pico3/chord.d.ts +41 -0
- package/dist/harness/pico3/chord.d.ts.map +1 -0
- package/dist/harness/pico3/chord.js +130 -0
- package/dist/harness/pico3/chord.js.map +1 -0
- package/dist/harness/pico3/context.d.ts +16 -0
- package/dist/harness/pico3/context.d.ts.map +1 -0
- package/dist/harness/pico3/context.js +88 -0
- package/dist/harness/pico3/context.js.map +1 -0
- package/dist/harness/pico3/harness.d.ts +197 -0
- package/dist/harness/pico3/harness.d.ts.map +1 -0
- package/dist/harness/pico3/harness.js +654 -0
- package/dist/harness/pico3/harness.js.map +1 -0
- package/dist/harness/pico3/hooks.d.ts +10 -0
- package/dist/harness/pico3/hooks.d.ts.map +1 -0
- package/dist/harness/pico3/hooks.js +33 -0
- package/dist/harness/pico3/hooks.js.map +1 -0
- package/dist/harness/pico3/index.d.ts +19 -0
- package/dist/harness/pico3/index.d.ts.map +1 -0
- package/dist/harness/pico3/index.js +15 -0
- package/dist/harness/pico3/index.js.map +1 -0
- package/dist/harness/pico3/jsonl.d.ts +58 -0
- package/dist/harness/pico3/jsonl.d.ts.map +1 -0
- package/dist/harness/pico3/jsonl.js +325 -0
- package/dist/harness/pico3/jsonl.js.map +1 -0
- package/dist/harness/pico3/kinds/collapse.d.ts +49 -0
- package/dist/harness/pico3/kinds/collapse.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/collapse.js +191 -0
- package/dist/harness/pico3/kinds/collapse.js.map +1 -0
- package/dist/harness/pico3/kinds/entries.d.ts +78 -0
- package/dist/harness/pico3/kinds/entries.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/entries.js +13 -0
- package/dist/harness/pico3/kinds/entries.js.map +1 -0
- package/dist/harness/pico3/kinds/frames.d.ts +9 -0
- package/dist/harness/pico3/kinds/frames.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/frames.js +75 -0
- package/dist/harness/pico3/kinds/frames.js.map +1 -0
- package/dist/harness/pico3/kinds/generation.d.ts +94 -0
- package/dist/harness/pico3/kinds/generation.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/generation.js +504 -0
- package/dist/harness/pico3/kinds/generation.js.map +1 -0
- package/dist/harness/pico3/kinds/job.d.ts +44 -0
- package/dist/harness/pico3/kinds/job.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/job.js +143 -0
- package/dist/harness/pico3/kinds/job.js.map +1 -0
- package/dist/harness/pico3/kinds/plugin.d.ts +15 -0
- package/dist/harness/pico3/kinds/plugin.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/plugin.js +35 -0
- package/dist/harness/pico3/kinds/plugin.js.map +1 -0
- package/dist/harness/pico3/kinds/post-tools.d.ts +22 -0
- package/dist/harness/pico3/kinds/post-tools.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/post-tools.js +145 -0
- package/dist/harness/pico3/kinds/post-tools.js.map +1 -0
- package/dist/harness/pico3/kinds/task-api.d.ts +3 -0
- package/dist/harness/pico3/kinds/task-api.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/task-api.js +45 -0
- package/dist/harness/pico3/kinds/task-api.js.map +1 -0
- package/dist/harness/pico3/kinds/tool.d.ts +43 -0
- package/dist/harness/pico3/kinds/tool.d.ts.map +1 -0
- package/dist/harness/pico3/kinds/tool.js +373 -0
- package/dist/harness/pico3/kinds/tool.js.map +1 -0
- package/dist/harness/pico3/membrane.d.ts +23 -0
- package/dist/harness/pico3/membrane.d.ts.map +1 -0
- package/dist/harness/pico3/membrane.js +141 -0
- package/dist/harness/pico3/membrane.js.map +1 -0
- package/dist/harness/pico3/memory.d.ts +53 -0
- package/dist/harness/pico3/memory.d.ts.map +1 -0
- package/dist/harness/pico3/memory.js +264 -0
- package/dist/harness/pico3/memory.js.map +1 -0
- package/dist/harness/pico3/scheduler.d.ts +46 -0
- package/dist/harness/pico3/scheduler.d.ts.map +1 -0
- package/dist/harness/pico3/scheduler.js +438 -0
- package/dist/harness/pico3/scheduler.js.map +1 -0
- package/dist/harness/pico3/session.d.ts +263 -0
- package/dist/harness/pico3/session.d.ts.map +1 -0
- package/dist/harness/pico3/session.js +1347 -0
- package/dist/harness/pico3/session.js.map +1 -0
- package/dist/harness/pico3/system.d.ts +126 -0
- package/dist/harness/pico3/system.d.ts.map +1 -0
- package/dist/harness/pico3/system.js +244 -0
- package/dist/harness/pico3/system.js.map +1 -0
- package/dist/harness/pico3/types.d.ts +973 -0
- package/dist/harness/pico3/types.d.ts.map +1 -0
- package/dist/harness/pico3/types.js +96 -0
- package/dist/harness/pico3/types.js.map +1 -0
- package/dist/harness/pico3/view.d.ts +34 -0
- package/dist/harness/pico3/view.d.ts.map +1 -0
- package/dist/harness/pico3/view.js +417 -0
- package/dist/harness/pico3/view.js.map +1 -0
- package/dist/harness/runtime/drive/boundary.d.ts.map +1 -1
- package/dist/harness/runtime/drive/boundary.js +6 -3
- package/dist/harness/runtime/drive/boundary.js.map +1 -1
- package/dist/harness/runtime/drive/response.d.ts.map +1 -1
- package/dist/harness/runtime/drive/response.js +4 -4
- package/dist/harness/runtime/drive/response.js.map +1 -1
- package/dist/harness/runtime/drive/retry.d.ts +2 -2
- package/dist/harness/runtime/drive/retry.d.ts.map +1 -1
- package/dist/harness/runtime/drive/retry.js +3 -6
- package/dist/harness/runtime/drive/retry.js.map +1 -1
- package/dist/harness/runtime/drive/structural.d.ts.map +1 -1
- package/dist/harness/runtime/drive/structural.js +5 -5
- package/dist/harness/runtime/drive/structural.js.map +1 -1
- package/dist/harness/runtime/drive/tool-placement.d.ts.map +1 -1
- package/dist/harness/runtime/drive/tool-placement.js +2 -27
- package/dist/harness/runtime/drive/tool-placement.js.map +1 -1
- package/dist/harness/runtime/drive/tools.d.ts.map +1 -1
- package/dist/harness/runtime/drive/tools.js.map +1 -1
- package/dist/harness/session/fork-policy.d.ts +20 -12
- package/dist/harness/session/fork-policy.d.ts.map +1 -1
- package/dist/harness/session/fork-policy.js +45 -12
- package/dist/harness/session/fork-policy.js.map +1 -1
- package/dist/harness/session/fork.d.ts +0 -2
- package/dist/harness/session/fork.d.ts.map +1 -1
- package/dist/harness/session/fork.js +20 -68
- package/dist/harness/session/fork.js.map +1 -1
- package/dist/harness/session/in-memory-storage-state.d.ts +5 -5
- package/dist/harness/session/in-memory-storage-state.d.ts.map +1 -1
- package/dist/harness/session/in-memory-storage-state.js +99 -39
- package/dist/harness/session/in-memory-storage-state.js.map +1 -1
- package/dist/harness/session/index.d.ts +1 -1
- package/dist/harness/session/index.d.ts.map +1 -1
- package/dist/harness/session/index.js +1 -1
- package/dist/harness/session/index.js.map +1 -1
- package/dist/harness/session/jsonl/fork.d.ts +38 -0
- package/dist/harness/session/jsonl/fork.d.ts.map +1 -0
- package/dist/harness/session/jsonl/fork.js +264 -0
- package/dist/harness/session/jsonl/fork.js.map +1 -0
- package/dist/harness/session/jsonl/io.d.ts +14 -0
- package/dist/harness/session/jsonl/io.d.ts.map +1 -0
- package/dist/harness/session/jsonl/io.js +86 -0
- package/dist/harness/session/jsonl/io.js.map +1 -0
- package/dist/harness/session/jsonl/legacy-v3.d.ts +33 -8
- package/dist/harness/session/jsonl/legacy-v3.d.ts.map +1 -1
- package/dist/harness/session/jsonl/legacy-v3.js +285 -206
- package/dist/harness/session/jsonl/legacy-v3.js.map +1 -1
- package/dist/harness/session/jsonl/repo.d.ts +2 -1
- package/dist/harness/session/jsonl/repo.d.ts.map +1 -1
- package/dist/harness/session/jsonl/repo.js +36 -20
- package/dist/harness/session/jsonl/repo.js.map +1 -1
- package/dist/harness/session/jsonl/storage.d.ts +4 -5
- package/dist/harness/session/jsonl/storage.d.ts.map +1 -1
- package/dist/harness/session/jsonl/storage.js +39 -113
- package/dist/harness/session/jsonl/storage.js.map +1 -1
- package/dist/harness/session/memory.d.ts +3 -5
- package/dist/harness/session/memory.d.ts.map +1 -1
- package/dist/harness/session/memory.js +9 -14
- package/dist/harness/session/memory.js.map +1 -1
- package/dist/harness/session/testing/conformance/session-repo.d.ts +2 -0
- package/dist/harness/session/testing/conformance/session-repo.d.ts.map +1 -1
- package/dist/harness/session/testing/conformance/session-repo.js +220 -1
- package/dist/harness/session/testing/conformance/session-repo.js.map +1 -1
- package/dist/harness/session/testing/index.d.ts +1 -1
- package/dist/harness/session/testing/index.d.ts.map +1 -1
- package/dist/harness/session/testing/index.js +1 -1
- package/dist/harness/session/testing/index.js.map +1 -1
- package/dist/harness/session/types.d.ts +1 -0
- package/dist/harness/session/types.d.ts.map +1 -1
- package/dist/harness/session/types.js.map +1 -1
- package/dist/harness/types.d.ts +14 -0
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/proxy.d.ts +2 -2
- package/dist/proxy.d.ts.map +1 -1
- package/dist/proxy.js.map +1 -1
- package/dist/types.d.ts +30 -14
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +10 -6
|
@@ -0,0 +1,973 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* harness-v3 — records, documents, storage, kinds, transactions, runtime, tools, hooks.
|
|
3
|
+
*
|
|
4
|
+
* Durable model: four tables (conversations, entries, tasks, inputs) and three documents
|
|
5
|
+
* (session, per-conversation rewindable, per-conversation sticky). Every durable position
|
|
6
|
+
* is strict JSON (`JsonValue`); nothing durable is `unknown`.
|
|
7
|
+
*
|
|
8
|
+
* Single process. A storage path has one owning process and one owning Session at a time.
|
|
9
|
+
* Two processes opening the same JSONL directory is unsupported.
|
|
10
|
+
*/
|
|
11
|
+
import type { JsonValue as ChordJsonValue, Context, JsonRepresentation } from "@earendil-works/chord";
|
|
12
|
+
import type { Op } from "@earendil-works/chord/delta";
|
|
13
|
+
import type { Api, AssistantMessage, AssistantMessageEvent, DeferredHandle, ImageContent, Message as ModelMessage, Model as ModelOf, TextContent, ToolCall, ToolResultMessage, UserMessage } from "@earendil-works/pi-ai";
|
|
14
|
+
import type { Static, TSchema } from "typebox";
|
|
15
|
+
import type { ThinkingLevel } from "../../types.ts";
|
|
16
|
+
import type { SectionRegistry, SectionSeed, ToolRegistry } from "./system.ts";
|
|
17
|
+
export type JsonPrimitive = string | number | boolean | null;
|
|
18
|
+
export type JsonValue = ChordJsonValue;
|
|
19
|
+
/** Optional properties represent absent keys; committed values are normalized through JSON serialization. */
|
|
20
|
+
export type JsonObject = {
|
|
21
|
+
[key: string]: JsonValue;
|
|
22
|
+
};
|
|
23
|
+
/** Coerce an in-memory value (e.g. a pi-ai message) to its stored representation. */
|
|
24
|
+
export declare const toStored: <T>(value: T) => JsonRepresentation<T>;
|
|
25
|
+
/**
|
|
26
|
+
* The JSON representation of a value: what survives `JSON.parse(JSON.stringify(v))`.
|
|
27
|
+
* Optional keys stay optional; `undefined` values vanish; functions are never durable.
|
|
28
|
+
* Use for imported pi-ai types at durable positions.
|
|
29
|
+
*/
|
|
30
|
+
export type Stored<T> = JsonRepresentation<T>;
|
|
31
|
+
export type Id = number;
|
|
32
|
+
export type Seq = number;
|
|
33
|
+
/** Compile-time assertion helper. */
|
|
34
|
+
export type Assert<T extends true> = T;
|
|
35
|
+
/** True iff T is strict JSON (structurally). */
|
|
36
|
+
export type IsJson<T> = [T] extends [JsonValue] ? true : false;
|
|
37
|
+
export interface Conversation {
|
|
38
|
+
readonly id: Id;
|
|
39
|
+
readonly parent?: {
|
|
40
|
+
readonly conversationId: Id;
|
|
41
|
+
readonly at: Id;
|
|
42
|
+
};
|
|
43
|
+
readonly owner?: Id;
|
|
44
|
+
/** §8.1 section seed: applied by preparation while the conversation has no local managed entry. Private: not in ConversationView. */
|
|
45
|
+
readonly sections?: readonly SectionSeed[];
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* System instructions and the tool loadout ride inside `messages` (pi-ai PR #9116, shimmed
|
|
49
|
+
* here until it lands): a SystemMessage at its historical position.
|
|
50
|
+
*/
|
|
51
|
+
export interface SystemMessage {
|
|
52
|
+
role: "system";
|
|
53
|
+
content: string;
|
|
54
|
+
toolsAdded?: {
|
|
55
|
+
name: string;
|
|
56
|
+
description: string;
|
|
57
|
+
parameters: TSchema;
|
|
58
|
+
}[];
|
|
59
|
+
toolsRemoved?: {
|
|
60
|
+
name: string;
|
|
61
|
+
}[];
|
|
62
|
+
timestamp: number;
|
|
63
|
+
}
|
|
64
|
+
export type Message = ModelMessage | SystemMessage;
|
|
65
|
+
export type StoredMessage = Stored<Message>;
|
|
66
|
+
export type Model = ModelOf<Api>;
|
|
67
|
+
export interface ContextEdit {
|
|
68
|
+
readonly target: Id;
|
|
69
|
+
readonly action: "omit" | "replace";
|
|
70
|
+
readonly messages?: readonly StoredMessage[];
|
|
71
|
+
}
|
|
72
|
+
export interface Entry {
|
|
73
|
+
readonly id: Id;
|
|
74
|
+
readonly conversationId: Id;
|
|
75
|
+
readonly kind: string;
|
|
76
|
+
readonly model?: readonly StoredMessage[];
|
|
77
|
+
readonly data?: JsonObject;
|
|
78
|
+
readonly head?: Id;
|
|
79
|
+
readonly edits?: readonly ContextEdit[];
|
|
80
|
+
readonly byTaskId?: Id;
|
|
81
|
+
}
|
|
82
|
+
export type NewEntry = Omit<Entry, "id" | "conversationId" | "byTaskId" | "head"> & {
|
|
83
|
+
readonly head?: Id | "self";
|
|
84
|
+
};
|
|
85
|
+
/** A typed witness for an entry kind: `is()` narrows, and typed writes take `EntryInput<E>`. */
|
|
86
|
+
export interface EntryKind<E extends Entry = Entry> {
|
|
87
|
+
readonly kind: string;
|
|
88
|
+
is(entry: Entry | undefined): entry is E;
|
|
89
|
+
}
|
|
90
|
+
export type EntryInput<E extends Entry> = Omit<E, "id" | "conversationId" | "kind" | "byTaskId" | "head"> & (E extends {
|
|
91
|
+
readonly head: Id;
|
|
92
|
+
} ? {
|
|
93
|
+
readonly head: Id | "self";
|
|
94
|
+
} : {
|
|
95
|
+
readonly head?: never;
|
|
96
|
+
});
|
|
97
|
+
export declare function defineEntry<E extends Entry>(kind: string): EntryKind<E>;
|
|
98
|
+
export type Checkpoint = JsonObject & {
|
|
99
|
+
readonly phase: string;
|
|
100
|
+
};
|
|
101
|
+
export type Completion<R extends JsonValue = JsonValue, F extends JsonValue = JsonValue> = {
|
|
102
|
+
readonly status: "completed";
|
|
103
|
+
readonly result: R;
|
|
104
|
+
} | {
|
|
105
|
+
readonly status: "failed";
|
|
106
|
+
readonly failure: F;
|
|
107
|
+
};
|
|
108
|
+
export type Outcome<R extends JsonValue = JsonValue, F extends JsonValue = JsonValue, A extends JsonValue = JsonValue> = Completion<R, F> | {
|
|
109
|
+
readonly status: "aborted";
|
|
110
|
+
readonly result: A;
|
|
111
|
+
} | {
|
|
112
|
+
readonly status: "orphaned";
|
|
113
|
+
}
|
|
114
|
+
/** The kind broke its contract (a handler threw or returned an invalid shape). Not one of its declared failures. */
|
|
115
|
+
| {
|
|
116
|
+
readonly status: "faulted";
|
|
117
|
+
readonly error: string;
|
|
118
|
+
};
|
|
119
|
+
export interface Task<I extends JsonValue = JsonValue, C extends Checkpoint = Checkpoint> {
|
|
120
|
+
readonly id: Id;
|
|
121
|
+
readonly conversationId: Id;
|
|
122
|
+
readonly kind: string;
|
|
123
|
+
readonly input: I;
|
|
124
|
+
readonly status: "pending" | "running" | "terminal";
|
|
125
|
+
readonly checkpoint?: C;
|
|
126
|
+
readonly abort?: true;
|
|
127
|
+
readonly outcome?: Outcome;
|
|
128
|
+
readonly after: readonly Id[];
|
|
129
|
+
readonly owns: readonly Id[];
|
|
130
|
+
readonly background?: true;
|
|
131
|
+
}
|
|
132
|
+
export type TaskPatch = {
|
|
133
|
+
readonly id: Id;
|
|
134
|
+
} & Partial<Omit<Pick<Task, "status" | "checkpoint" | "abort" | "outcome" | "owns">, "checkpoint">> & {
|
|
135
|
+
checkpoint?: Checkpoint | null;
|
|
136
|
+
};
|
|
137
|
+
export interface Input {
|
|
138
|
+
readonly id: Id;
|
|
139
|
+
readonly conversationId: Id;
|
|
140
|
+
readonly requestId?: string;
|
|
141
|
+
readonly status: "queued" | "placed" | "done" | "unanswered";
|
|
142
|
+
readonly entry?: Id;
|
|
143
|
+
readonly answer?: Id;
|
|
144
|
+
readonly reason?: "aborted" | "stale" | "terminated" | "failed";
|
|
145
|
+
readonly detail?: string;
|
|
146
|
+
}
|
|
147
|
+
export type ModelRef = {
|
|
148
|
+
provider: string;
|
|
149
|
+
modelId: string;
|
|
150
|
+
};
|
|
151
|
+
export type RetryPolicy = {
|
|
152
|
+
enabled: boolean;
|
|
153
|
+
maxRetries: number;
|
|
154
|
+
baseDelayMs: number;
|
|
155
|
+
maxAgentDelayMs?: number;
|
|
156
|
+
};
|
|
157
|
+
/** One running tool call, at the index of its call in the assistant message. */
|
|
158
|
+
export type ToolSlot = {
|
|
159
|
+
callId: string;
|
|
160
|
+
name: string;
|
|
161
|
+
args: JsonValue;
|
|
162
|
+
status: "pending" | "running" | "done" | "error" | "aborted";
|
|
163
|
+
waitingOn?: string;
|
|
164
|
+
output?: string;
|
|
165
|
+
progress?: string;
|
|
166
|
+
details?: JsonValue;
|
|
167
|
+
continuedBy?: Id;
|
|
168
|
+
entry?: Id;
|
|
169
|
+
/** Private task-lifetime coordination state. Never projected into ConversationView. */
|
|
170
|
+
memos?: {
|
|
171
|
+
[key: string]: JsonValue;
|
|
172
|
+
};
|
|
173
|
+
};
|
|
174
|
+
/** The current turn, shaped for rendering. Reset when a generation starts; cleared when the turn ends. */
|
|
175
|
+
export type TurnState = {
|
|
176
|
+
message?: Stored<AssistantMessage>;
|
|
177
|
+
tools: ToolSlot[];
|
|
178
|
+
};
|
|
179
|
+
/** Private durable namespace slices stored in authoritative documents. */
|
|
180
|
+
export type PluginSlices = {
|
|
181
|
+
[namespace: string]: JsonObject;
|
|
182
|
+
};
|
|
183
|
+
/** Rewound by forks: forks see the state as of their fork point. Core config fields come from the built-in kinds' declarations. */
|
|
184
|
+
export type RewindableState = {
|
|
185
|
+
model?: ModelRef;
|
|
186
|
+
thinkingLevel: ThinkingLevel;
|
|
187
|
+
selectedTools: string[];
|
|
188
|
+
profile: string;
|
|
189
|
+
threshold: number;
|
|
190
|
+
keepRecent: number;
|
|
191
|
+
plugins: PluginSlices;
|
|
192
|
+
[key: string]: JsonValue | undefined;
|
|
193
|
+
};
|
|
194
|
+
/** The present. Never folded historically; truncated to its last base. */
|
|
195
|
+
export type StickyState = {
|
|
196
|
+
retry: RetryPolicy;
|
|
197
|
+
steeringMode: "all" | "one-at-a-time";
|
|
198
|
+
followUpMode: "all" | "one-at-a-time";
|
|
199
|
+
inbox: QueuedInput[];
|
|
200
|
+
turn: TurnState;
|
|
201
|
+
tasks: {
|
|
202
|
+
[taskId: string]: JsonObject;
|
|
203
|
+
};
|
|
204
|
+
plugins: PluginSlices;
|
|
205
|
+
[key: string]: JsonValue | undefined;
|
|
206
|
+
};
|
|
207
|
+
export type SessionState = {
|
|
208
|
+
plugins: PluginSlices;
|
|
209
|
+
[key: string]: JsonValue | undefined;
|
|
210
|
+
};
|
|
211
|
+
export type QueuedInput = {
|
|
212
|
+
id: Id;
|
|
213
|
+
mode: "steer" | "followUp";
|
|
214
|
+
input: Stored<UserInput>;
|
|
215
|
+
} | {
|
|
216
|
+
id: Id;
|
|
217
|
+
mode: "write";
|
|
218
|
+
entry: Stored<NewEntry>;
|
|
219
|
+
};
|
|
220
|
+
export type DocRef = {
|
|
221
|
+
doc: "session";
|
|
222
|
+
} | {
|
|
223
|
+
doc: "rewindable";
|
|
224
|
+
conversationId: Id;
|
|
225
|
+
} | {
|
|
226
|
+
doc: "sticky";
|
|
227
|
+
conversationId: Id;
|
|
228
|
+
};
|
|
229
|
+
export type NamespaceDefaults<T extends JsonObject> = {
|
|
230
|
+
readonly rewindable?: Partial<T>;
|
|
231
|
+
readonly sticky?: Partial<T>;
|
|
232
|
+
readonly session?: Partial<T>;
|
|
233
|
+
};
|
|
234
|
+
/** Current process authority for one durable namespace string. */
|
|
235
|
+
export interface Namespace<T extends JsonObject = JsonObject> {
|
|
236
|
+
readonly id: string;
|
|
237
|
+
/** Type-only invariant marker. */
|
|
238
|
+
readonly valueType?: (value: T) => T;
|
|
239
|
+
unregister(): void;
|
|
240
|
+
}
|
|
241
|
+
/** Internal erased registration paired with the public namespace token. */
|
|
242
|
+
export interface NamespaceRegistration {
|
|
243
|
+
readonly token: object;
|
|
244
|
+
readonly defaults: {
|
|
245
|
+
readonly rewindable: JsonObject;
|
|
246
|
+
readonly sticky: JsonObject;
|
|
247
|
+
readonly session: JsonObject;
|
|
248
|
+
};
|
|
249
|
+
readonly routes: ReadonlyMap<string, DocRef["doc"]>;
|
|
250
|
+
readonly project?: (slice: Readonly<JsonObject>) => JsonValue;
|
|
251
|
+
}
|
|
252
|
+
/** First writer wins, including when the stored winner is null. */
|
|
253
|
+
export declare function memoOnce<T extends JsonValue>(slot: JsonObject, key: string, candidate: T): T;
|
|
254
|
+
type UnionToIntersection<U> = (U extends unknown ? (x: U) => void : never) extends (x: infer I) => void ? I : never;
|
|
255
|
+
/** A declared slice; the undeclared `ConfigShape` (index signature) counts as no keys. */
|
|
256
|
+
type Declared<S> = string extends keyof S ? object : S;
|
|
257
|
+
type RewindableOf<K> = K extends unknown ? ConfigOf<K> extends {
|
|
258
|
+
readonly rewindable: infer RC;
|
|
259
|
+
} ? Declared<RC> : object : never;
|
|
260
|
+
type StickyOf<K> = K extends unknown ? ConfigOf<K> extends {
|
|
261
|
+
readonly sticky: infer SC;
|
|
262
|
+
} ? Declared<SC> : object : never;
|
|
263
|
+
export type ConfigOfKinds<Ks extends readonly AnyKind[]> = UnionToIntersection<RewindableOf<Ks[number]> | StickyOf<Ks[number]>> extends infer M ? {
|
|
264
|
+
[K in keyof M]: M[K];
|
|
265
|
+
} : never;
|
|
266
|
+
type KeysOfKind<K> = (keyof RewindableOf<K> | keyof StickyOf<K>) & string;
|
|
267
|
+
type IsUnion<U, C = U> = U extends unknown ? ([C] extends [U] ? false : true) : never;
|
|
268
|
+
/** The kinds declaring `Key`. */
|
|
269
|
+
type Owners<Ks extends readonly AnyKind[], Key extends string> = {
|
|
270
|
+
[I in keyof Ks]: Key extends KeysOfKind<Ks[I]> ? Ks[I] : never;
|
|
271
|
+
}[number];
|
|
272
|
+
type AllKeys<Ks extends readonly AnyKind[]> = {
|
|
273
|
+
[I in keyof Ks]: KeysOfKind<Ks[I]>;
|
|
274
|
+
}[number];
|
|
275
|
+
type ClashingKeys<Ks extends readonly AnyKind[]> = {
|
|
276
|
+
[Key in AllKeys<Ks>]: true extends IsUnion<Owners<Ks, Key>> ? Key : never;
|
|
277
|
+
}[AllKeys<Ks>];
|
|
278
|
+
/** `true` iff no two kinds declare the same config key. Asserted at open at compile time and at runtime. */
|
|
279
|
+
export type DisjointConfig<Ks extends readonly AnyKind[]> = [ClashingKeys<Ks>] extends [never] ? true : false;
|
|
280
|
+
export interface ConfigFacade<Cfg extends object> {
|
|
281
|
+
get(ctx: Context): Promise<Readonly<Cfg>>;
|
|
282
|
+
/** One commit, routed to the declaring documents. */
|
|
283
|
+
set(patch: {
|
|
284
|
+
[K in keyof Cfg]?: Cfg[K];
|
|
285
|
+
}, ctx: Context): Promise<void>;
|
|
286
|
+
/** Delete persisted overrides. Declared defaults become visible; `model` becomes absent. */
|
|
287
|
+
reset(keys: readonly (keyof Cfg)[], ctx: Context): Promise<void>;
|
|
288
|
+
}
|
|
289
|
+
export type Write = {
|
|
290
|
+
type: "conversation";
|
|
291
|
+
conversation: Conversation;
|
|
292
|
+
} | {
|
|
293
|
+
type: "entry";
|
|
294
|
+
entry: Entry;
|
|
295
|
+
} | {
|
|
296
|
+
type: "task";
|
|
297
|
+
task: Task;
|
|
298
|
+
} | {
|
|
299
|
+
type: "task.patch";
|
|
300
|
+
patch: TaskPatch;
|
|
301
|
+
} | {
|
|
302
|
+
type: "input";
|
|
303
|
+
input: Input;
|
|
304
|
+
} | {
|
|
305
|
+
type: "doc";
|
|
306
|
+
ref: DocRef;
|
|
307
|
+
ops: Op[];
|
|
308
|
+
};
|
|
309
|
+
export interface EntryScan {
|
|
310
|
+
conversationId: Id;
|
|
311
|
+
kind?: string;
|
|
312
|
+
withHead?: boolean;
|
|
313
|
+
before?: Id;
|
|
314
|
+
limit: number;
|
|
315
|
+
}
|
|
316
|
+
export interface TaskScan {
|
|
317
|
+
conversationId?: Id;
|
|
318
|
+
status?: Task["status"][];
|
|
319
|
+
kind?: string;
|
|
320
|
+
}
|
|
321
|
+
export interface Storage {
|
|
322
|
+
/** Persist one batch atomically: all or nothing. Returns the commit sequence. */
|
|
323
|
+
commit(writes: readonly Write[], ctx: Context): Promise<Seq>;
|
|
324
|
+
mintId(): Id;
|
|
325
|
+
conversation(id: Id, ctx: Context): Promise<Conversation | undefined>;
|
|
326
|
+
conversations(ctx: Context): Promise<Conversation[]>;
|
|
327
|
+
entries(ids: readonly Id[], ctx: Context): Promise<Map<Id, Entry>>;
|
|
328
|
+
/** Newest-first, fork-aware: this conversation's entries, then the parent's up to the fork point, and so on. */
|
|
329
|
+
scanEntries(scan: EntryScan, ctx: Context): Promise<Entry[]>;
|
|
330
|
+
task(id: Id, ctx: Context): Promise<Task | undefined>;
|
|
331
|
+
scanTasks(scan: TaskScan, ctx: Context): Promise<Task[]>;
|
|
332
|
+
input(id: Id, ctx: Context): Promise<Input | undefined>;
|
|
333
|
+
inputByRequest(conversationId: Id, requestId: string, ctx: Context): Promise<Input | undefined>;
|
|
334
|
+
doc(ref: DocRef, ctx: Context): Promise<JsonObject | undefined>;
|
|
335
|
+
/** Rewindable doc as of the atomic commit containing entry `at` (fork inheritance). See "commit-granular history". */
|
|
336
|
+
docAsOf(conversationId: Id, at: Id, ctx: Context): Promise<JsonObject | undefined>;
|
|
337
|
+
/** Rewrite a doc log from its last base. */
|
|
338
|
+
truncate(ref: DocRef, ctx: Context): Promise<void>;
|
|
339
|
+
close(ctx: Context): Promise<void>;
|
|
340
|
+
}
|
|
341
|
+
/** A hook may synchronously or asynchronously omit its replacement value. */
|
|
342
|
+
export type HookResult<T> = T | void | Promise<T | void>;
|
|
343
|
+
export interface HookApi {
|
|
344
|
+
readonly kind: string;
|
|
345
|
+
readonly taskId: Id;
|
|
346
|
+
readonly conversationId: Id;
|
|
347
|
+
}
|
|
348
|
+
/** Kept as the concise name used by existing kind hook declarations. */
|
|
349
|
+
export type HookInfo = HookApi;
|
|
350
|
+
export interface HookBinding<H extends object> {
|
|
351
|
+
readonly handlers: Partial<H>;
|
|
352
|
+
readonly namespace: Namespace;
|
|
353
|
+
readonly api: HookApi;
|
|
354
|
+
}
|
|
355
|
+
export interface HookRunner<H extends object> {
|
|
356
|
+
handlers(): readonly HookBinding<H>[];
|
|
357
|
+
/** Call `fn` on each handler; `onValue` sees non-undefined results and may return true to stop. A throwing handler is reported and skipped. */
|
|
358
|
+
each<V>(ctx: Context, fn: (handlers: Partial<H>, api: HookApi) => HookResult<V>, onValue?: (v: V) => unknown): Promise<void>;
|
|
359
|
+
}
|
|
360
|
+
/** What a phase handler returns: advance to a checkpoint, or finish. A builder runs on the line and may terminalize or ask to retry. */
|
|
361
|
+
export type Step<C extends Checkpoint, R extends JsonValue, F extends JsonValue, Tx extends TaskTx = TaskTx> = {
|
|
362
|
+
readonly next: C | ((tx: Tx, current: Task, ctx: Context) => C | Completion<R, F> | "retry" | Promise<C | Completion<R, F> | "retry">);
|
|
363
|
+
} | {
|
|
364
|
+
readonly done: Closure<R, F, Tx>;
|
|
365
|
+
};
|
|
366
|
+
export type Closure<R extends JsonValue, F extends JsonValue, Tx extends TaskTx = TaskTx> = (tx: Tx, current: Task, ctx: Context) => Completion<R, F> | Promise<Completion<R, F>>;
|
|
367
|
+
export type AbortClosure<A extends JsonValue, Tx extends TaskTx = TaskTx> = (tx: Tx, current: Task, ctx: Context) => A | Promise<A>;
|
|
368
|
+
export type CheckpointAt<C extends Checkpoint, P extends C["phase"]> = Extract<C, {
|
|
369
|
+
readonly phase: P;
|
|
370
|
+
}>;
|
|
371
|
+
export type PhaseHandler<I extends JsonValue, C extends Checkpoint, P extends C["phase"], R extends JsonValue, F extends JsonValue, H extends object, Tx extends TaskTx = TaskTx> = (task: Task<I, CheckpointAt<C, P>> & {
|
|
372
|
+
readonly checkpoint: CheckpointAt<C, P>;
|
|
373
|
+
}, rt: Runtime<H, Tx>, ctx: Context) => Promise<Step<C, R, F, Tx>>;
|
|
374
|
+
/** A config slice: JSON values; a key whose default is `undefined` is optional (only `model` among the built-ins). */
|
|
375
|
+
export type ConfigShape = {
|
|
376
|
+
[key: string]: JsonValue | undefined;
|
|
377
|
+
};
|
|
378
|
+
/** Per-kind configuration: defaults, split by document. Keys across all kinds must be disjoint. */
|
|
379
|
+
export interface KindConfig<RC extends ConfigShape = ConfigShape, SC extends ConfigShape = ConfigShape> {
|
|
380
|
+
readonly rewindable?: RC;
|
|
381
|
+
readonly sticky?: SC;
|
|
382
|
+
}
|
|
383
|
+
/** Phantom carrier so `TaskOf<K>` etc. can read a kind's types back out. Never set at runtime. */
|
|
384
|
+
export interface KindTypes<I extends JsonValue, C extends Checkpoint, R extends JsonValue, F extends JsonValue, A extends JsonValue, H extends object, Cfg extends KindConfig, S extends JsonObject> {
|
|
385
|
+
input: I;
|
|
386
|
+
checkpoint: C;
|
|
387
|
+
result: R;
|
|
388
|
+
failure: F;
|
|
389
|
+
aborted: A;
|
|
390
|
+
hooks: H;
|
|
391
|
+
config: Cfg;
|
|
392
|
+
slot: S;
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* A task kind. `initial` runs when there is no checkpoint; `phases` is exhaustive over
|
|
396
|
+
* `C["phase"]`. Phases named in `inflight` are written by a handler immediately before an
|
|
397
|
+
* external effect and are entered by the scheduler only after reopen; a `next` transition
|
|
398
|
+
* into one is rejected as a contract fault.
|
|
399
|
+
*/
|
|
400
|
+
export interface Kind<I extends JsonValue = JsonValue, C extends Checkpoint = Checkpoint, R extends JsonValue = JsonValue, F extends JsonValue = JsonValue, A extends JsonValue = JsonValue, H extends object = object, Cfg extends KindConfig = KindConfig, S extends JsonObject = JsonObject, Tx extends TaskTx = TaskTx> {
|
|
401
|
+
readonly types?: KindTypes<I, C, R, F, A, H, Cfg, S>;
|
|
402
|
+
readonly name: string;
|
|
403
|
+
/** A turn kind makes the conversation busy for admission. */
|
|
404
|
+
readonly turn?: boolean;
|
|
405
|
+
readonly config?: Cfg;
|
|
406
|
+
/** Live slot (`sticky.tasks[id]`) initializer. */
|
|
407
|
+
readonly slot?: (input: I) => S;
|
|
408
|
+
/** Rendering projection for a non-turn task. Raw checkpoints and slots are never published. */
|
|
409
|
+
readonly describe?: (task: Task<I, C> & {
|
|
410
|
+
readonly slot?: Readonly<S>;
|
|
411
|
+
}) => JsonValue;
|
|
412
|
+
readonly inflight?: readonly C["phase"][];
|
|
413
|
+
initial(task: Task<I, never> & {
|
|
414
|
+
readonly checkpoint?: undefined;
|
|
415
|
+
}, rt: Runtime<H, Tx>, ctx: Context): Promise<Step<C, R, F, Tx>>;
|
|
416
|
+
readonly phases: {
|
|
417
|
+
readonly [P in C["phase"]]: PhaseHandler<I, C, P, R, F, H, Tx>;
|
|
418
|
+
};
|
|
419
|
+
abort(task: Task<I, C>, rt: Runtime<H, Tx>, ctx: Context): Promise<AbortClosure<A, Tx>>;
|
|
420
|
+
}
|
|
421
|
+
/** Internal kind type for fixed core machinery. */
|
|
422
|
+
export type CoreKind<I extends JsonValue, C extends Checkpoint, R extends JsonValue, F extends JsonValue, A extends JsonValue, H extends object = object, Cfg extends KindConfig = KindConfig, S extends JsonObject = JsonObject> = Kind<I, C, R, F, A, H, Cfg, S, CoreTx>;
|
|
423
|
+
/** Author an ordinary kind. Names may not begin with `pi.`. */
|
|
424
|
+
export declare function defineTask<I extends JsonValue, C extends Checkpoint, R extends JsonValue, F extends JsonValue, A extends JsonValue, H extends object = object, Cfg extends KindConfig = KindConfig, S extends JsonObject = JsonObject>(definition: Kind<I, C, R, F, A, H, Cfg, S>): Kind<I, C, R, F, A, H, Cfg, S>;
|
|
425
|
+
/**
|
|
426
|
+
* The erased kind the kernel stores. Handlers are invoked through `KindAdapter`, the one
|
|
427
|
+
* place a concrete `Kind<…>` is narrowed to this and its outputs are validated.
|
|
428
|
+
*/
|
|
429
|
+
export interface AnyKind {
|
|
430
|
+
readonly types?: unknown;
|
|
431
|
+
readonly name: string;
|
|
432
|
+
readonly turn?: boolean;
|
|
433
|
+
readonly config?: KindConfig;
|
|
434
|
+
readonly slot?: (input: never) => JsonObject;
|
|
435
|
+
readonly describe?: unknown;
|
|
436
|
+
readonly inflight?: readonly string[];
|
|
437
|
+
readonly initial: unknown;
|
|
438
|
+
readonly phases: {
|
|
439
|
+
readonly [phase: string]: unknown;
|
|
440
|
+
};
|
|
441
|
+
readonly abort: unknown;
|
|
442
|
+
}
|
|
443
|
+
export interface TaskRef<K extends AnyKind = AnyKind> {
|
|
444
|
+
readonly id: Id;
|
|
445
|
+
readonly kind: K;
|
|
446
|
+
}
|
|
447
|
+
export interface EntryRef<E extends Entry = Entry> {
|
|
448
|
+
readonly id: Id;
|
|
449
|
+
readonly kind: EntryKind<E>;
|
|
450
|
+
}
|
|
451
|
+
type TypesOf<K> = K extends {
|
|
452
|
+
types?: infer T;
|
|
453
|
+
} ? NonNullable<T> : never;
|
|
454
|
+
export type TaskOf<K> = TypesOf<K> extends KindTypes<infer I, infer C, infer R, infer F, infer A, object, KindConfig, JsonObject> ? Omit<Task<I, C>, "outcome"> & {
|
|
455
|
+
readonly outcome?: Outcome<R, F, A>;
|
|
456
|
+
} : never;
|
|
457
|
+
export type InputOf<K> = TypesOf<K> extends KindTypes<infer I, Checkpoint, JsonValue, JsonValue, JsonValue, object, KindConfig, JsonObject> ? I : never;
|
|
458
|
+
export type HooksOf<K> = TypesOf<K> extends KindTypes<JsonValue, Checkpoint, JsonValue, JsonValue, JsonValue, infer H, KindConfig, JsonObject> ? H : never;
|
|
459
|
+
export type ConfigOf<K> = TypesOf<K> extends KindTypes<JsonValue, Checkpoint, JsonValue, JsonValue, JsonValue, object, infer Cfg, JsonObject> ? Cfg : never;
|
|
460
|
+
export type SlotOf<K> = TypesOf<K> extends KindTypes<JsonValue, Checkpoint, JsonValue, JsonValue, JsonValue, object, KindConfig, infer S> ? S : never;
|
|
461
|
+
export type TaskSpec = {
|
|
462
|
+
kind: string;
|
|
463
|
+
conversationId?: Id;
|
|
464
|
+
input: JsonValue;
|
|
465
|
+
after?: Id[];
|
|
466
|
+
background?: true;
|
|
467
|
+
};
|
|
468
|
+
export interface ConversationSpec {
|
|
469
|
+
parent?: {
|
|
470
|
+
conversationId: Id;
|
|
471
|
+
at: Id | "start";
|
|
472
|
+
};
|
|
473
|
+
rewindable?: Partial<RewindableState>;
|
|
474
|
+
sticky?: Partial<StickyState>;
|
|
475
|
+
sections?: readonly SectionSeed[];
|
|
476
|
+
}
|
|
477
|
+
export interface OwnedConversationSpec {
|
|
478
|
+
inherit?: boolean;
|
|
479
|
+
rewindable?: Partial<RewindableState>;
|
|
480
|
+
sticky?: Partial<StickyState>;
|
|
481
|
+
}
|
|
482
|
+
export type UserInput = string | UserMessage["content"];
|
|
483
|
+
export interface SendInput {
|
|
484
|
+
content: UserInput;
|
|
485
|
+
requestId?: string;
|
|
486
|
+
whenBusy?: "steer" | "followUp" | "reject";
|
|
487
|
+
}
|
|
488
|
+
export type ContextView = {
|
|
489
|
+
head: Entry | undefined;
|
|
490
|
+
entries: Entry[];
|
|
491
|
+
messages: StoredMessage[];
|
|
492
|
+
};
|
|
493
|
+
export type GenerationStatus = {
|
|
494
|
+
stage: "waiting";
|
|
495
|
+
on: "compaction";
|
|
496
|
+
} | {
|
|
497
|
+
stage: "preparing";
|
|
498
|
+
} | {
|
|
499
|
+
stage: "requesting";
|
|
500
|
+
attempt: number;
|
|
501
|
+
} | {
|
|
502
|
+
stage: "streaming";
|
|
503
|
+
attempt: number;
|
|
504
|
+
} | {
|
|
505
|
+
stage: "retrying";
|
|
506
|
+
attempt: number;
|
|
507
|
+
retryAt: number;
|
|
508
|
+
lastError: string;
|
|
509
|
+
} | {
|
|
510
|
+
stage: "deferred";
|
|
511
|
+
attempt: number;
|
|
512
|
+
pollAt: number;
|
|
513
|
+
};
|
|
514
|
+
export interface TurnView {
|
|
515
|
+
inputs: Id[];
|
|
516
|
+
generation?: GenerationStatus;
|
|
517
|
+
message?: Stored<AssistantMessage>;
|
|
518
|
+
tools: Omit<ToolSlot, "memos">[];
|
|
519
|
+
}
|
|
520
|
+
export interface ConversationView {
|
|
521
|
+
conversation: Omit<Conversation, "sections">;
|
|
522
|
+
entries: Entry[];
|
|
523
|
+
config: {
|
|
524
|
+
[key: string]: JsonValue | undefined;
|
|
525
|
+
};
|
|
526
|
+
inbox: QueuedInput[];
|
|
527
|
+
turn?: TurnView;
|
|
528
|
+
compaction?: {
|
|
529
|
+
taskId: Id;
|
|
530
|
+
reason: "threshold" | "manual" | "overflow";
|
|
531
|
+
stage: "summarizing" | "retrying";
|
|
532
|
+
attempt: number;
|
|
533
|
+
retryAt?: number;
|
|
534
|
+
};
|
|
535
|
+
tasks: {
|
|
536
|
+
[taskId: string]: {
|
|
537
|
+
kind: string;
|
|
538
|
+
background?: true;
|
|
539
|
+
marked?: true;
|
|
540
|
+
status: JsonValue;
|
|
541
|
+
};
|
|
542
|
+
};
|
|
543
|
+
plugins: {
|
|
544
|
+
[namespace: string]: JsonValue;
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
export type ViewEvent = {
|
|
548
|
+
type: "entry.added";
|
|
549
|
+
entry: Entry;
|
|
550
|
+
} | {
|
|
551
|
+
type: "head.moved";
|
|
552
|
+
entry: Entry;
|
|
553
|
+
} | {
|
|
554
|
+
type: "turn.started";
|
|
555
|
+
inputs: Id[];
|
|
556
|
+
} | {
|
|
557
|
+
type: "turn.ended";
|
|
558
|
+
inputs: Id[];
|
|
559
|
+
status: "done";
|
|
560
|
+
answer: Id;
|
|
561
|
+
} | {
|
|
562
|
+
type: "turn.ended";
|
|
563
|
+
inputs: Id[];
|
|
564
|
+
status: "unanswered";
|
|
565
|
+
reason: "terminated" | "aborted" | "failed" | "stale";
|
|
566
|
+
detail?: string;
|
|
567
|
+
} | {
|
|
568
|
+
type: "input.queued";
|
|
569
|
+
input: Id;
|
|
570
|
+
mode: "steer" | "followUp" | "write";
|
|
571
|
+
} | {
|
|
572
|
+
type: "input.placed";
|
|
573
|
+
input: Id;
|
|
574
|
+
entry: Id;
|
|
575
|
+
} | {
|
|
576
|
+
type: "input.aborted";
|
|
577
|
+
input: Id;
|
|
578
|
+
} | {
|
|
579
|
+
type: "generation.started";
|
|
580
|
+
taskId: Id;
|
|
581
|
+
attempt: number;
|
|
582
|
+
} | {
|
|
583
|
+
type: "generation.retrying";
|
|
584
|
+
taskId: Id;
|
|
585
|
+
attempt: number;
|
|
586
|
+
retryAt: number;
|
|
587
|
+
error: string;
|
|
588
|
+
} | {
|
|
589
|
+
type: "generation.deferred";
|
|
590
|
+
taskId: Id;
|
|
591
|
+
pollAt: number;
|
|
592
|
+
} | {
|
|
593
|
+
type: "generation.completed";
|
|
594
|
+
taskId: Id;
|
|
595
|
+
entry: Id;
|
|
596
|
+
toolCalls: number;
|
|
597
|
+
} | {
|
|
598
|
+
type: "generation.failed";
|
|
599
|
+
taskId: Id;
|
|
600
|
+
reason: "provider" | "overflow" | "retries_exhausted" | "no_model";
|
|
601
|
+
detail: string;
|
|
602
|
+
entry?: Id;
|
|
603
|
+
} | {
|
|
604
|
+
type: "tool.waiting";
|
|
605
|
+
taskId: Id;
|
|
606
|
+
callId: string;
|
|
607
|
+
on: string;
|
|
608
|
+
} | {
|
|
609
|
+
type: "tool.started";
|
|
610
|
+
taskId: Id;
|
|
611
|
+
callId: string;
|
|
612
|
+
name: string;
|
|
613
|
+
} | {
|
|
614
|
+
type: "tool.finished";
|
|
615
|
+
taskId: Id;
|
|
616
|
+
callId: string;
|
|
617
|
+
entry: Id;
|
|
618
|
+
isError: boolean;
|
|
619
|
+
control?: ToolControl;
|
|
620
|
+
} | {
|
|
621
|
+
type: "tool.aborted";
|
|
622
|
+
taskId: Id;
|
|
623
|
+
callId: string;
|
|
624
|
+
entry: Id;
|
|
625
|
+
} | {
|
|
626
|
+
type: "compaction.started";
|
|
627
|
+
taskId: Id;
|
|
628
|
+
reason: "threshold" | "manual" | "overflow";
|
|
629
|
+
through: Id;
|
|
630
|
+
} | {
|
|
631
|
+
type: "compaction.retrying";
|
|
632
|
+
taskId: Id;
|
|
633
|
+
attempt: number;
|
|
634
|
+
retryAt: number;
|
|
635
|
+
error: string;
|
|
636
|
+
} | {
|
|
637
|
+
type: "compaction.finished";
|
|
638
|
+
taskId: Id;
|
|
639
|
+
summary: Id;
|
|
640
|
+
} | {
|
|
641
|
+
type: "compaction.failed";
|
|
642
|
+
taskId: Id;
|
|
643
|
+
reason: "stale" | "declined" | "provider" | "retries_exhausted" | "no_model";
|
|
644
|
+
detail: string;
|
|
645
|
+
} | {
|
|
646
|
+
type: "task.started";
|
|
647
|
+
taskId: Id;
|
|
648
|
+
kind: string;
|
|
649
|
+
background?: true;
|
|
650
|
+
} | {
|
|
651
|
+
type: "task.ended";
|
|
652
|
+
taskId: Id;
|
|
653
|
+
kind: string;
|
|
654
|
+
outcome: "completed" | "failed" | "aborted" | "orphaned" | "faulted";
|
|
655
|
+
} | {
|
|
656
|
+
type: "config.changed";
|
|
657
|
+
keys: string[];
|
|
658
|
+
} | {
|
|
659
|
+
type: "warning";
|
|
660
|
+
source: string;
|
|
661
|
+
message: string;
|
|
662
|
+
} | {
|
|
663
|
+
type: `plugin.${string}`;
|
|
664
|
+
data: JsonValue;
|
|
665
|
+
};
|
|
666
|
+
export interface Envelope {
|
|
667
|
+
readonly revision: number;
|
|
668
|
+
readonly ops: Op[];
|
|
669
|
+
readonly events: ViewEvent[];
|
|
670
|
+
}
|
|
671
|
+
/** Reads available to every view. Scans reject after a same-batch write to their domain (`ReadAfterWrite`). */
|
|
672
|
+
export interface TxReads {
|
|
673
|
+
conversation(id: Id): Promise<Conversation | undefined>;
|
|
674
|
+
entry(id: Id): Promise<Entry | undefined>;
|
|
675
|
+
entry<E extends Entry>(kind: EntryKind<E>, id: Id): Promise<E | undefined>;
|
|
676
|
+
entries(ids: readonly Id[]): Promise<Map<Id, Entry>>;
|
|
677
|
+
newestEntry(conversationId: Id, opts?: {
|
|
678
|
+
kind?: string;
|
|
679
|
+
withHead?: boolean;
|
|
680
|
+
}): Promise<Entry | undefined>;
|
|
681
|
+
newestEntry<E extends Entry>(conversationId: Id, kind: EntryKind<E>): Promise<E | undefined>;
|
|
682
|
+
scanEntries(scan: EntryScan): Promise<Entry[]>;
|
|
683
|
+
context(conversationId: Id, at?: Id): Promise<ContextView>;
|
|
684
|
+
task(id: Id): Promise<Task | undefined>;
|
|
685
|
+
task<K extends AnyKind>(ref: TaskRef<K>): Promise<TaskOf<K> | undefined>;
|
|
686
|
+
tasks(scan: TaskScan): Promise<Task[]>;
|
|
687
|
+
input(id: Id): Promise<Input | undefined>;
|
|
688
|
+
rewindableAsOf(conversationId: Id, at: Id): Promise<RewindableState | undefined>;
|
|
689
|
+
/** Plain copies. Document proxies cannot escape a transaction. */
|
|
690
|
+
snapshot(ref: {
|
|
691
|
+
doc: "rewindable";
|
|
692
|
+
conversationId: Id;
|
|
693
|
+
}): RewindableState;
|
|
694
|
+
snapshot(ref: {
|
|
695
|
+
doc: "sticky";
|
|
696
|
+
conversationId: Id;
|
|
697
|
+
}): StickyState;
|
|
698
|
+
snapshot(ref: {
|
|
699
|
+
doc: "session";
|
|
700
|
+
}): SessionState;
|
|
701
|
+
}
|
|
702
|
+
interface SharedTx extends TxReads {
|
|
703
|
+
plugins<T extends JsonObject>(namespace: Namespace<T>): T;
|
|
704
|
+
emit<T extends JsonObject>(namespace: Namespace<T>, name: string, data: JsonValue): void;
|
|
705
|
+
config(conversationId: Id): {
|
|
706
|
+
get<K extends string>(key: K): JsonValue | undefined;
|
|
707
|
+
};
|
|
708
|
+
/** Passive entry: queued when busy, appended when idle. Returns the input id. */
|
|
709
|
+
write(conversationId: Id, entry: NewEntry): Promise<Id>;
|
|
710
|
+
write<E extends Entry>(conversationId: Id, kind: EntryKind<E>, entry: EntryInput<E>): Promise<Id>;
|
|
711
|
+
createTask<K extends AnyKind>(kind: K, input: InputOf<K>, opts?: {
|
|
712
|
+
conversationId?: Id;
|
|
713
|
+
background?: true;
|
|
714
|
+
after?: Id[];
|
|
715
|
+
}): TaskRef<K>;
|
|
716
|
+
createConversation(spec: ConversationSpec): Id;
|
|
717
|
+
}
|
|
718
|
+
/** What the host gets. */
|
|
719
|
+
export interface HostTx extends SharedTx {
|
|
720
|
+
/** Config through the facade; raw core fields are not exposed to the host tx. */
|
|
721
|
+
config(conversationId: Id): {
|
|
722
|
+
get<K extends string>(key: K): JsonValue | undefined;
|
|
723
|
+
set(key: string, value: JsonValue): void;
|
|
724
|
+
reset(key: string): void;
|
|
725
|
+
};
|
|
726
|
+
}
|
|
727
|
+
/** What an ordinary task gets: scoped shared operations plus its own checkpoint and slot. */
|
|
728
|
+
export interface TaskTx extends SharedTx {
|
|
729
|
+
checkpoint<C extends Checkpoint>(value: C): void;
|
|
730
|
+
slot<K extends AnyKind>(ref: TaskRef<K>): SlotOf<K>;
|
|
731
|
+
/** Create a conversation this task owns. `parent` must be in the task's subtree. */
|
|
732
|
+
createConversation(spec: ConversationSpec): Id;
|
|
733
|
+
}
|
|
734
|
+
/** Internal full authority for the fixed turn machinery. Never handed to ordinary kinds or the host. */
|
|
735
|
+
export interface CoreTx extends TaskTx {
|
|
736
|
+
emit<T extends JsonObject>(namespace: Namespace<T>, name: string, data: JsonValue): void;
|
|
737
|
+
emit(event: ViewEvent): void;
|
|
738
|
+
rewindable(conversationId: Id): RewindableState;
|
|
739
|
+
sticky(conversationId: Id): StickyState;
|
|
740
|
+
session(): SessionState;
|
|
741
|
+
toolSlot(task: {
|
|
742
|
+
conversationId: Id;
|
|
743
|
+
input: {
|
|
744
|
+
index: number;
|
|
745
|
+
};
|
|
746
|
+
}): ToolSlot;
|
|
747
|
+
appendEntry(conversationId: Id, entry: NewEntry): Id;
|
|
748
|
+
appendEntry<E extends Entry>(conversationId: Id, kind: EntryKind<E>, entry: EntryInput<E>): EntryRef<E>;
|
|
749
|
+
createTask(spec: TaskSpec): Id;
|
|
750
|
+
createTask<K extends AnyKind>(kind: K, input: InputOf<K>, opts?: {
|
|
751
|
+
conversationId?: Id;
|
|
752
|
+
background?: true;
|
|
753
|
+
after?: Id[];
|
|
754
|
+
}): TaskRef<K>;
|
|
755
|
+
send(conversationId: Id, input: SendInput): Promise<Id>;
|
|
756
|
+
resolveInputs(ids: readonly Id[], resolution: {
|
|
757
|
+
status: "done";
|
|
758
|
+
answer: Id;
|
|
759
|
+
} | {
|
|
760
|
+
status: "unanswered";
|
|
761
|
+
reason: NonNullable<Input["reason"]>;
|
|
762
|
+
detail?: string;
|
|
763
|
+
}): Promise<void>;
|
|
764
|
+
/** Inbox placement at a safe boundary. `headBoundary`: the newest head as the caller knows it (including a same-batch self-head it appended). */
|
|
765
|
+
boundary(conversationId: Id, at: "postTools" | "final", headBoundary: Id | undefined): Promise<{
|
|
766
|
+
triggers: Id[];
|
|
767
|
+
terminated: boolean;
|
|
768
|
+
}>;
|
|
769
|
+
/** Internal owned-conversation path. Sanitizes caller overrides while preserving inherited rewindable namespace slices. */
|
|
770
|
+
createOwnedConversation(ownerTaskId: Id, sourceConversationId: Id, spec: OwnedConversationSpec): Promise<Id>;
|
|
771
|
+
/** Internal host-fork path for an already validated historical snapshot. */
|
|
772
|
+
createForkConversation(spec: ConversationSpec): Id;
|
|
773
|
+
markTask(id: Id): void;
|
|
774
|
+
}
|
|
775
|
+
/** Thrown when a scan-shaped read follows a same-batch write to its domain. Poisons the transaction. */
|
|
776
|
+
export declare class ReadAfterWrite extends Error {
|
|
777
|
+
constructor(read: string, write: string);
|
|
778
|
+
}
|
|
779
|
+
export interface RequestOptions {
|
|
780
|
+
messages: StoredMessage[];
|
|
781
|
+
thinkingLevel: ThinkingLevel;
|
|
782
|
+
}
|
|
783
|
+
export interface Models {
|
|
784
|
+
resolve(ref: ModelRef): Model | undefined;
|
|
785
|
+
stream(model: Model, request: RequestOptions, ctx: Context): AsyncIterable<AssistantMessageEvent>;
|
|
786
|
+
fetchDeferred(model: Model, handle: DeferredHandle, ctx: Context): Promise<AssistantMessage | {
|
|
787
|
+
deferred: DeferredHandle;
|
|
788
|
+
}>;
|
|
789
|
+
cancelDeferred(model: Model, handle: DeferredHandle, ctx: Context): Promise<void>;
|
|
790
|
+
}
|
|
791
|
+
export interface Runtime<H extends object = object, Tx extends TaskTx = TaskTx> {
|
|
792
|
+
readonly taskId: Id;
|
|
793
|
+
readonly conversationId: Id;
|
|
794
|
+
readonly kind: AnyKind;
|
|
795
|
+
commit<T>(fn: (tx: Tx, current: Task, ctx: Context) => T | Promise<T>, ctx: Context): Promise<T>;
|
|
796
|
+
readonly hooks: HookRunner<H>;
|
|
797
|
+
readonly models: Models;
|
|
798
|
+
readonly tools: ReadonlyMap<string, ToolDeclaration>;
|
|
799
|
+
readonly registries: {
|
|
800
|
+
sections: SectionRegistry;
|
|
801
|
+
tools: ToolRegistry;
|
|
802
|
+
};
|
|
803
|
+
readonly kinds: ReadonlyMap<string, AnyKind>;
|
|
804
|
+
readonly processHost: ProcessHost | undefined;
|
|
805
|
+
readonly plugins: ReadonlyMap<string, PluginHandler>;
|
|
806
|
+
now(): number;
|
|
807
|
+
sleep(untilMs: number, ctx: Context): Promise<void>;
|
|
808
|
+
waitForInput(id: Id, ctx: Context): Promise<Input>;
|
|
809
|
+
waitForTask(id: Id, ctx: Context): Promise<Task>;
|
|
810
|
+
abortTask(id: Id, ctx: Context): Promise<"marked" | "terminal">;
|
|
811
|
+
abortConversation(id: Id, ctx: Context): Promise<void>;
|
|
812
|
+
createOwnedConversation(spec: OwnedConversationSpec, ctx: Context): Promise<Id>;
|
|
813
|
+
/** Admission for a conversation owned by this task; the runtime verifies ownership before invoking the kernel. */
|
|
814
|
+
sendOwned(conversationId: Id, input: SendInput, ctx: Context): Promise<Id>;
|
|
815
|
+
context(conversationId: Id, at: Id | undefined, ctx: Context): Promise<ContextView>;
|
|
816
|
+
newestEntry(conversationId: Id, opts: {
|
|
817
|
+
kind?: string;
|
|
818
|
+
withHead?: boolean;
|
|
819
|
+
}, ctx: Context): Promise<Entry | undefined>;
|
|
820
|
+
rewindable(conversationId: Id, ctx: Context): Promise<RewindableState>;
|
|
821
|
+
sticky(conversationId: Id, ctx: Context): Promise<StickyState>;
|
|
822
|
+
rewindableAsOf(conversationId: Id, at: Id, ctx: Context): Promise<RewindableState | undefined>;
|
|
823
|
+
}
|
|
824
|
+
export type ToolControl = {
|
|
825
|
+
terminate?: true;
|
|
826
|
+
handoff?: string;
|
|
827
|
+
addTools?: string[];
|
|
828
|
+
};
|
|
829
|
+
export interface ToolDiagnostic {
|
|
830
|
+
severity: "info" | "warn" | "error";
|
|
831
|
+
message: string;
|
|
832
|
+
code?: string;
|
|
833
|
+
}
|
|
834
|
+
export interface ToolResult {
|
|
835
|
+
/** Omit when the tool streamed through `api.stream`: the bounded stream is the content. */
|
|
836
|
+
content?: (TextContent | ImageContent)[];
|
|
837
|
+
isError?: boolean;
|
|
838
|
+
details?: JsonValue;
|
|
839
|
+
diagnostics?: ToolDiagnostic[];
|
|
840
|
+
control?: ToolControl;
|
|
841
|
+
}
|
|
842
|
+
export interface ToolDeclaration<P extends TSchema = TSchema> {
|
|
843
|
+
readonly name: string;
|
|
844
|
+
readonly description: string;
|
|
845
|
+
readonly parameters: P;
|
|
846
|
+
readonly replay?: "safe" | "unsafe";
|
|
847
|
+
readonly output?: {
|
|
848
|
+
maxBytes?: number;
|
|
849
|
+
maxLines?: number;
|
|
850
|
+
retain?: "head" | "tail";
|
|
851
|
+
};
|
|
852
|
+
execute(args: Static<P>, api: ToolApi, ctx: Context): Promise<ToolResult>;
|
|
853
|
+
}
|
|
854
|
+
/** Erased declaration held by the registry. */
|
|
855
|
+
export type AnyToolDeclaration = ToolDeclaration<TSchema>;
|
|
856
|
+
/** The narrow handle a task gets to a conversation it owns. */
|
|
857
|
+
export interface OwnedConversation {
|
|
858
|
+
readonly id: Id;
|
|
859
|
+
send(input: SendInput, ctx: Context): Promise<{
|
|
860
|
+
id: Id;
|
|
861
|
+
wait(ctx: Context): Promise<Input>;
|
|
862
|
+
result(ctx: Context): Promise<Input | undefined>;
|
|
863
|
+
}>;
|
|
864
|
+
abort(ctx: Context): Promise<void>;
|
|
865
|
+
}
|
|
866
|
+
export interface BeforeToolApi extends HookApi {
|
|
867
|
+
readonly callId: string;
|
|
868
|
+
waiting(ctx: Context): Promise<void>;
|
|
869
|
+
memo<T extends JsonValue>(name: string, candidate: T, ctx: Context): Promise<T>;
|
|
870
|
+
memo<T extends JsonValue>(name: string, ctx: Context): Promise<T | undefined>;
|
|
871
|
+
emit(name: string, data: JsonValue, ctx: Context): Promise<void>;
|
|
872
|
+
}
|
|
873
|
+
export interface ToolApi {
|
|
874
|
+
readonly taskId: Id;
|
|
875
|
+
readonly conversationId: Id;
|
|
876
|
+
readonly callId: string;
|
|
877
|
+
/** Pipe raw output here. The kernel bounds it per the declaration, flushes it on a throttle, and uses it as the result content unless the tool returns its own. Synchronous. */
|
|
878
|
+
stream(chunk: string | Uint8Array): void;
|
|
879
|
+
/** Mutate the live slot's free fields (`progress`, `details`, `continuedBy`). Identity fields are protected. */
|
|
880
|
+
progress(update: (slot: Pick<ToolSlot, "progress" | "details" | "continuedBy">) => void, ctx: Context): Promise<void>;
|
|
881
|
+
memo<T extends JsonValue>(name: string, candidate: T, ctx: Context): Promise<T>;
|
|
882
|
+
memo<T extends JsonValue>(name: string, ctx: Context): Promise<T | undefined>;
|
|
883
|
+
conversation(spec: OwnedConversationSpec, ctx: Context): Promise<OwnedConversation>;
|
|
884
|
+
task<K extends AnyKind>(kind: K, input: InputOf<K>, opts: {
|
|
885
|
+
background?: true;
|
|
886
|
+
after?: Id[];
|
|
887
|
+
}, ctx: Context): Promise<TaskRef<K>>;
|
|
888
|
+
getTask<K extends AnyKind>(ref: TaskRef<K>, ctx: Context): Promise<TaskOf<K> | undefined>;
|
|
889
|
+
waitForTask<K extends AnyKind>(ref: TaskRef<K>, ctx: Context): Promise<TaskOf<K>>;
|
|
890
|
+
/** Snapshot of another task's live slot (in this task's conversation or subtree). */
|
|
891
|
+
slot<K extends AnyKind>(ref: TaskRef<K>, ctx: Context): Promise<SlotOf<K> | undefined>;
|
|
892
|
+
}
|
|
893
|
+
export interface ProcessSpec {
|
|
894
|
+
command: string;
|
|
895
|
+
args: string[];
|
|
896
|
+
cwd: string;
|
|
897
|
+
env?: {
|
|
898
|
+
[key: string]: string;
|
|
899
|
+
};
|
|
900
|
+
}
|
|
901
|
+
export type ProcessStatus = {
|
|
902
|
+
status: "running";
|
|
903
|
+
stdout: string;
|
|
904
|
+
stderr: string;
|
|
905
|
+
droppedStdout: number;
|
|
906
|
+
droppedStderr: number;
|
|
907
|
+
} | {
|
|
908
|
+
status: "exited";
|
|
909
|
+
exitCode: number;
|
|
910
|
+
stdout: string;
|
|
911
|
+
stderr: string;
|
|
912
|
+
droppedStdout: number;
|
|
913
|
+
droppedStderr: number;
|
|
914
|
+
} | {
|
|
915
|
+
status: "unknown";
|
|
916
|
+
};
|
|
917
|
+
export interface ProcessHost {
|
|
918
|
+
start(key: string, spec: ProcessSpec, ctx: Context): Promise<void>;
|
|
919
|
+
status(key: string, ctx: Context): Promise<ProcessStatus>;
|
|
920
|
+
kill(key: string, signal: "SIGTERM" | "SIGKILL", ctx: Context): Promise<void>;
|
|
921
|
+
}
|
|
922
|
+
export type PluginHandler = (input: JsonValue, api: ToolApi, ctx: Context) => Promise<JsonValue>;
|
|
923
|
+
/** An unforgeable capability: only the scheduler creates these, one per invocation. */
|
|
924
|
+
export declare class InvocationToken {
|
|
925
|
+
#private;
|
|
926
|
+
readonly taskId: Id;
|
|
927
|
+
readonly mode: "run" | "abort";
|
|
928
|
+
constructor(taskId: Id, mode: "run" | "abort");
|
|
929
|
+
get alive(): boolean;
|
|
930
|
+
/** Called by the scheduler when the invocation returns. */
|
|
931
|
+
revoke(): void;
|
|
932
|
+
}
|
|
933
|
+
export type Invoker = {
|
|
934
|
+
readonly type: "host";
|
|
935
|
+
readonly conversationId?: Id;
|
|
936
|
+
}
|
|
937
|
+
/** Harness internals acting with core authority (send, reset, abort, retire). Never exported. */
|
|
938
|
+
| {
|
|
939
|
+
readonly type: "kernel";
|
|
940
|
+
readonly conversationId?: Id;
|
|
941
|
+
} | {
|
|
942
|
+
readonly type: "task";
|
|
943
|
+
readonly token: InvocationToken;
|
|
944
|
+
readonly id: Id;
|
|
945
|
+
readonly conversationId: Id;
|
|
946
|
+
readonly kind: AnyKind;
|
|
947
|
+
readonly core: boolean;
|
|
948
|
+
readonly mode: "run" | "abort";
|
|
949
|
+
};
|
|
950
|
+
export declare class Forbidden extends Error {
|
|
951
|
+
constructor(what: string);
|
|
952
|
+
}
|
|
953
|
+
export declare class ConversationBusy extends Error {
|
|
954
|
+
constructor(id: Id);
|
|
955
|
+
}
|
|
956
|
+
export declare class GenerationInProgress extends Error {
|
|
957
|
+
constructor(id: Id);
|
|
958
|
+
}
|
|
959
|
+
export declare class CollapseInProgress extends Error {
|
|
960
|
+
constructor(id: Id);
|
|
961
|
+
}
|
|
962
|
+
export declare class Faulted extends Error {
|
|
963
|
+
constructor(cause: unknown);
|
|
964
|
+
}
|
|
965
|
+
export declare class Closed extends Error {
|
|
966
|
+
constructor();
|
|
967
|
+
}
|
|
968
|
+
export declare class TaskContractFault extends Error {
|
|
969
|
+
constructor(kind: string, what: string);
|
|
970
|
+
}
|
|
971
|
+
export type { ToolCall, ToolResultMessage, AssistantMessage, UserMessage, DeferredHandle, ThinkingLevel };
|
|
972
|
+
export type RequestMessage = StoredMessage;
|
|
973
|
+
//# sourceMappingURL=types.d.ts.map
|