@fungi.computer/parakeet 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +186 -2
- package/dist/account-commands.d.ts +102 -0
- package/dist/account-commands.js +239 -0
- package/dist/agent-head.d.ts +4 -0
- package/dist/agent-head.js +2 -0
- package/dist/client-contributions.d.ts +20 -0
- package/dist/client-contributions.js +41 -0
- package/dist/commands/advertised.d.ts +23 -0
- package/dist/commands/advertised.js +72 -0
- package/dist/commands/builtins.d.ts +14 -0
- package/dist/commands/builtins.js +91 -0
- package/dist/commands/hints.d.ts +36 -0
- package/dist/commands/hints.js +64 -0
- package/dist/commands/interactions.d.ts +55 -0
- package/dist/commands/interactions.js +101 -0
- package/dist/commands/run.d.ts +12 -0
- package/dist/commands/run.js +64 -0
- package/dist/commands/slash.d.ts +126 -0
- package/dist/commands/slash.js +190 -0
- package/dist/commands/use-slash-commands.d.ts +57 -0
- package/dist/commands/use-slash-commands.js +207 -0
- package/dist/components/AgentHead.d.ts +22 -0
- package/dist/components/AgentHead.js +20 -0
- package/dist/components/ChatComposer.d.ts +43 -0
- package/dist/components/ChatComposer.js +209 -0
- package/dist/components/ChatMessage.d.ts +8 -0
- package/dist/components/ChatMessage.js +16 -0
- package/dist/components/ClientRows.d.ts +11 -0
- package/dist/components/ClientRows.js +46 -0
- package/dist/components/CodeBlock.d.ts +11 -0
- package/dist/components/CodeBlock.js +38 -0
- package/dist/components/InteractionPanel.d.ts +15 -0
- package/dist/components/InteractionPanel.js +42 -0
- package/dist/components/MarkdownRenderer.d.ts +6 -0
- package/dist/components/MarkdownRenderer.js +48 -0
- package/dist/components/RunFailureNotice.d.ts +7 -0
- package/dist/components/RunFailureNotice.js +13 -0
- package/dist/components/ShiitakeAvatar.d.ts +21 -0
- package/dist/components/ShiitakeAvatar.js +22 -0
- package/dist/components/SlashMenu.d.ts +8 -0
- package/dist/components/SlashMenu.js +50 -0
- package/dist/components/ThinkingBlock.d.ts +3 -0
- package/dist/components/ThinkingBlock.js +18 -0
- package/dist/components/TimelineItem.d.ts +15 -0
- package/dist/components/TimelineItem.js +35 -0
- package/dist/components/ToolGroup.d.ts +12 -0
- package/dist/components/ToolGroup.js +90 -0
- package/dist/components/WaitingNotice.d.ts +7 -0
- package/dist/components/WaitingNotice.js +8 -0
- package/dist/components/avatar-presentation.d.ts +16 -0
- package/dist/components/avatar-presentation.js +9 -0
- package/dist/components/sprite-service.d.ts +2 -0
- package/dist/components/sprite-service.js +9 -0
- package/dist/conversation.d.ts +165 -0
- package/dist/conversation.js +762 -0
- package/dist/core/assistant-visibility.d.ts +3 -0
- package/dist/core/assistant-visibility.js +4 -0
- package/dist/core/author-labels.d.ts +16 -0
- package/dist/core/author-labels.js +16 -0
- package/dist/core/build-timeline.d.ts +36 -0
- package/dist/core/build-timeline.js +328 -0
- package/dist/core/client-actions.d.ts +35 -0
- package/dist/core/client-actions.js +128 -0
- package/dist/core/client-contributions.d.ts +24 -0
- package/dist/core/client-contributions.js +115 -0
- package/dist/core/client-timeline.d.ts +33 -0
- package/dist/core/client-timeline.js +72 -0
- package/dist/core/format-context.d.ts +11 -0
- package/dist/core/format-context.js +20 -0
- package/dist/core/format-tokens.d.ts +2 -0
- package/dist/core/format-tokens.js +6 -0
- package/dist/core/model-identity.d.ts +3 -0
- package/dist/core/model-identity.js +7 -0
- package/dist/core/session-projection.d.ts +11 -0
- package/dist/core/session-projection.js +191 -0
- package/dist/core/session-query.d.ts +118 -0
- package/dist/core/session-query.js +187 -0
- package/dist/core/session-view-state.d.ts +66 -0
- package/dist/core/session-view-state.js +114 -0
- package/dist/core/tool-contract.d.ts +15 -0
- package/dist/core/tool-contract.js +3 -0
- package/dist/core/tool-groups.d.ts +36 -0
- package/dist/core/tool-groups.js +151 -0
- package/dist/core/tool-view.d.ts +182 -0
- package/dist/core/tool-view.js +618 -0
- package/dist/headless.d.ts +28 -0
- package/dist/headless.js +24 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +4 -0
- package/dist/lib/failure.d.ts +2 -0
- package/dist/lib/failure.js +9 -0
- package/dist/markdown.d.ts +3 -0
- package/dist/markdown.js +6 -0
- package/dist/model-commands.d.ts +44 -0
- package/dist/model-commands.js +232 -0
- package/dist/parakeet.d.ts +77 -0
- package/dist/parakeet.js +276 -0
- package/dist/provider-choices.d.ts +8 -0
- package/dist/provider-choices.js +46 -0
- package/dist/reload-command.d.ts +43 -0
- package/dist/reload-command.js +72 -0
- package/dist/session-commands.d.ts +53 -0
- package/dist/session-commands.js +259 -0
- package/dist/session.d.ts +24 -0
- package/dist/session.js +1 -0
- package/dist/store/types.d.ts +163 -0
- package/dist/store/types.js +1 -0
- package/dist/styles.css +19129 -0
- package/docs/api/README.md +15 -0
- package/docs/api/commands/slash.md +321 -0
- package/docs/api/headless.md +2510 -0
- package/docs/api/index.md +1249 -0
- package/package.json +79 -3
- package/src/styles.css +272 -0
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import { nanoid } from "@fungi.computer/cairn";
|
|
2
|
+
import { ShiitakeError } from "@fungi.computer/shiitake";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { buildDurableTimeline } from "./core/build-timeline.js";
|
|
5
|
+
import { sessionActivityStatus, sessionViewState, } from "./core/session-view-state.js";
|
|
6
|
+
/** A choice prompt holds at most 256 options; the default read already bounds this. */
|
|
7
|
+
const maxForkOptions = 200;
|
|
8
|
+
const queueArguments = z.discriminatedUnion("action", [
|
|
9
|
+
z.strictObject({ action: z.literal("list") }),
|
|
10
|
+
z.strictObject({ action: z.literal("editLast") }),
|
|
11
|
+
]);
|
|
12
|
+
const queueArgumentsSchema = z
|
|
13
|
+
.record(z.string(), z.json())
|
|
14
|
+
.parse(structuredClone(z.toJSONSchema(queueArguments)));
|
|
15
|
+
/** The owner's bound for one user-set Session title, in code points. */
|
|
16
|
+
const maxTitleLength = 120;
|
|
17
|
+
const nameArguments = z
|
|
18
|
+
.strictObject({ title: z.string() })
|
|
19
|
+
.optional()
|
|
20
|
+
.transform((value) => value?.title.trim().replaceAll(/\s+/gu, " ") ?? "");
|
|
21
|
+
/** The owner's bound for one compaction focus, in UTF-16 units. */
|
|
22
|
+
const maxCompactionInstructions = 4_096;
|
|
23
|
+
const compactArguments = z
|
|
24
|
+
.strictObject({ instructions: z.string() })
|
|
25
|
+
.optional()
|
|
26
|
+
.transform((value) => value?.instructions.trim() ?? "");
|
|
27
|
+
/** Tell the human, when one is present, and return the same text. */
|
|
28
|
+
function tell(interaction, message) {
|
|
29
|
+
interaction?.notify({ type: "info", message });
|
|
30
|
+
return message;
|
|
31
|
+
}
|
|
32
|
+
/** Contribute the shared Session command vocabulary to one Whistle host. */
|
|
33
|
+
export function contributeSessionCommands(commands, session, options) {
|
|
34
|
+
const unavailable = (name) => {
|
|
35
|
+
throw new Error(`${name} is unavailable in this host.`);
|
|
36
|
+
};
|
|
37
|
+
const contribution = {
|
|
38
|
+
sourceId: options.sourceId,
|
|
39
|
+
namespace: options.namespace,
|
|
40
|
+
commands: [
|
|
41
|
+
{
|
|
42
|
+
id: "session",
|
|
43
|
+
title: "Session status",
|
|
44
|
+
category: "Advanced",
|
|
45
|
+
projections: {
|
|
46
|
+
help: { order: 1 },
|
|
47
|
+
palette: { order: 1 },
|
|
48
|
+
slash: { aliases: ["session"], order: 1 },
|
|
49
|
+
},
|
|
50
|
+
handler: async ({ interaction }) => {
|
|
51
|
+
const snapshot = await session.read();
|
|
52
|
+
return tell(interaction, `Session ${snapshot.sessionId} is ${sessionActivityStatus(sessionViewState(snapshot))}; ${String(snapshot.pending.prompts.length)} queued prompt${snapshot.pending.prompts.length === 1 ? "" : "s"}.`);
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
id: "queue",
|
|
57
|
+
title: "Queued prompts",
|
|
58
|
+
category: "Advanced",
|
|
59
|
+
projections: {
|
|
60
|
+
help: { order: 3 },
|
|
61
|
+
palette: { order: 3 },
|
|
62
|
+
slash: {
|
|
63
|
+
aliases: ["queue"],
|
|
64
|
+
order: 3,
|
|
65
|
+
arguments: {
|
|
66
|
+
hint: "list | edit-last",
|
|
67
|
+
words: [
|
|
68
|
+
{
|
|
69
|
+
word: "list",
|
|
70
|
+
description: "List accepted queued prompts",
|
|
71
|
+
arguments: { action: "list" },
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
word: "edit-last",
|
|
75
|
+
description: "Return the last queued prompt to the composer",
|
|
76
|
+
arguments: { action: "editLast" },
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
action: { inputSchema: queueArgumentsSchema },
|
|
83
|
+
handler: async ({ arguments: rawArguments, interaction, }) => {
|
|
84
|
+
const args = queueArguments.safeParse(rawArguments ?? { action: "list" });
|
|
85
|
+
if (!args.success)
|
|
86
|
+
throw new Error("/queue requires list or editLast.");
|
|
87
|
+
const snapshot = await session.read();
|
|
88
|
+
if (args.data.action === "list") {
|
|
89
|
+
const prompts = snapshot.pending.prompts;
|
|
90
|
+
const settled = snapshot.terminals.map((terminal) => `${terminal.outcome} · ${terminal.commandId}`);
|
|
91
|
+
tell(interaction, prompts.length === 0 && settled.length === 0
|
|
92
|
+
? "No queued prompts."
|
|
93
|
+
: [
|
|
94
|
+
...prompts.map((prompt, index) => `${String(index + 1)}. queued · accepted: ${prompt.text}`),
|
|
95
|
+
...settled,
|
|
96
|
+
...(snapshot.pending.hasMore === true
|
|
97
|
+
? ["More accepted prompts are waiting outside this view."]
|
|
98
|
+
: []),
|
|
99
|
+
].join("\n"));
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (snapshot.pending.hasMore === true)
|
|
103
|
+
throw new Error("The queue view is incomplete; refresh it before editing the last prompt.");
|
|
104
|
+
const prompt = [...snapshot.pending.prompts]
|
|
105
|
+
.reverse()
|
|
106
|
+
.find((candidate) => candidate.delivery === "followUp");
|
|
107
|
+
if (prompt === undefined)
|
|
108
|
+
throw new Error("There is no queued follow-up to edit.");
|
|
109
|
+
if (session.cancel === undefined)
|
|
110
|
+
throw new Error("Queue editing is unavailable in this host.");
|
|
111
|
+
if (options.onEditQueued === undefined)
|
|
112
|
+
throw new Error("Editing queued prompts is unavailable in this host.");
|
|
113
|
+
if (options.canEditQueued?.() === false)
|
|
114
|
+
throw new Error("Clear or submit the current draft before editing a queued prompt.");
|
|
115
|
+
const withdrawn = await session.cancel({
|
|
116
|
+
commandId: prompt.commandId,
|
|
117
|
+
onlyIfPending: true,
|
|
118
|
+
});
|
|
119
|
+
if (withdrawn.status === "too_late")
|
|
120
|
+
throw new Error("That queued prompt has already started; it can no longer be edited.");
|
|
121
|
+
options.onEditQueued(prompt.text);
|
|
122
|
+
tell(interaction, "Queued prompt returned to the composer for editing.");
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
id: "resume",
|
|
127
|
+
title: "Resume a conversation",
|
|
128
|
+
category: "Conversation",
|
|
129
|
+
projections: {
|
|
130
|
+
help: { order: 5 },
|
|
131
|
+
palette: { order: 5 },
|
|
132
|
+
slash: { aliases: ["resume"], order: 5 },
|
|
133
|
+
},
|
|
134
|
+
handler: async () => {
|
|
135
|
+
if (!options.sessionResumeAvailable ||
|
|
136
|
+
options.sessionResume === undefined) {
|
|
137
|
+
unavailable("/resume");
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
await options.sessionResume();
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
id: "fork",
|
|
145
|
+
title: "Fork conversation",
|
|
146
|
+
category: "Conversation",
|
|
147
|
+
projections: {
|
|
148
|
+
help: { order: 7 },
|
|
149
|
+
palette: { order: 7 },
|
|
150
|
+
slash: { aliases: ["fork"], order: 7 },
|
|
151
|
+
},
|
|
152
|
+
handler: async ({ interaction }) => {
|
|
153
|
+
if (!options.forkAvailable || options.onForked === undefined) {
|
|
154
|
+
unavailable("/fork");
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
const snapshot = await session.read();
|
|
158
|
+
if (sessionActivityStatus(sessionViewState(snapshot)) !== "idle")
|
|
159
|
+
throw new Error("Wait for the current run to finish, then fork.");
|
|
160
|
+
const candidates = buildDurableTimeline(snapshot.messages ?? [], snapshot.compactions ?? []).items.filter((item) => item.kind === "user_message");
|
|
161
|
+
if (candidates.length === 0)
|
|
162
|
+
throw new Error("No messages to fork from.");
|
|
163
|
+
if (interaction === undefined)
|
|
164
|
+
throw new Error("Forking a Session needs a person.");
|
|
165
|
+
const ordered = [...candidates].reverse().slice(0, maxForkOptions);
|
|
166
|
+
const answer = await interaction.prompt({
|
|
167
|
+
type: "choice",
|
|
168
|
+
message: "Fork from message",
|
|
169
|
+
options: ordered.map((item) => ({
|
|
170
|
+
value: item.id,
|
|
171
|
+
label: item.text.slice(0, 100) || "(empty message)",
|
|
172
|
+
})),
|
|
173
|
+
});
|
|
174
|
+
let forked;
|
|
175
|
+
try {
|
|
176
|
+
forked = await session.command({ type: "fork", entryId: answer });
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
if (error instanceof ShiitakeError) {
|
|
180
|
+
if (error.boundary === "runtime" && error.cause === "conflict")
|
|
181
|
+
throw new Error("Wait for the current run to finish, then fork.", { cause: error });
|
|
182
|
+
if (error.boundary === "store" && error.cause === "unavailable")
|
|
183
|
+
throw new Error("That message is no longer available to fork from.", { cause: error });
|
|
184
|
+
if (error.boundary === "runtime" && error.cause === "rejected")
|
|
185
|
+
throw new Error("This Session is bound to a channel and cannot be forked.", { cause: error });
|
|
186
|
+
}
|
|
187
|
+
throw error;
|
|
188
|
+
}
|
|
189
|
+
await options.onForked(forked.sessionId);
|
|
190
|
+
tell(interaction, "Forked into a new Session.");
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
id: "compact",
|
|
195
|
+
title: "Compact conversation",
|
|
196
|
+
category: "Conversation",
|
|
197
|
+
description: "Summarize older context now; optional text sets its focus",
|
|
198
|
+
projections: {
|
|
199
|
+
help: { order: 8 },
|
|
200
|
+
palette: { order: 8 },
|
|
201
|
+
slash: {
|
|
202
|
+
aliases: ["compact"],
|
|
203
|
+
order: 8,
|
|
204
|
+
arguments: {
|
|
205
|
+
hint: "[instructions]",
|
|
206
|
+
text: { field: "instructions", arguments: {} },
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
handler: async ({ arguments: input, interaction, }) => {
|
|
211
|
+
const parsed = compactArguments.safeParse(input);
|
|
212
|
+
if (!parsed.success)
|
|
213
|
+
throw new Error("Use /compact, or /compact <what to focus on>.");
|
|
214
|
+
const instructions = parsed.data;
|
|
215
|
+
if (instructions.length > maxCompactionInstructions)
|
|
216
|
+
throw new Error(`Compaction instructions are at most ${String(maxCompactionInstructions)} characters.`);
|
|
217
|
+
// One request id per invocation; the owner replays a retried one.
|
|
218
|
+
await session.command(instructions.length === 0
|
|
219
|
+
? { type: "compact", requestId: nanoid() }
|
|
220
|
+
: { type: "compact", requestId: nanoid(), instructions });
|
|
221
|
+
return tell(interaction, "Compaction queued; it runs after any current work.");
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
id: "name",
|
|
226
|
+
title: "Name conversation",
|
|
227
|
+
category: "Conversation",
|
|
228
|
+
description: "Set the conversation title; no text restores it",
|
|
229
|
+
projections: {
|
|
230
|
+
help: { order: 9 },
|
|
231
|
+
palette: { order: 9 },
|
|
232
|
+
slash: {
|
|
233
|
+
aliases: ["name"],
|
|
234
|
+
order: 9,
|
|
235
|
+
arguments: {
|
|
236
|
+
hint: "[title]",
|
|
237
|
+
text: { field: "title", arguments: {} },
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
handler: async ({ arguments: input, interaction, }) => {
|
|
242
|
+
const parsed = nameArguments.safeParse(input);
|
|
243
|
+
if (!parsed.success)
|
|
244
|
+
throw new Error("Use /name <title>, or /name to clear it.");
|
|
245
|
+
const text = parsed.data;
|
|
246
|
+
if (Array.from(text).length > maxTitleLength)
|
|
247
|
+
throw new Error(`A conversation title is at most ${String(maxTitleLength)} characters.`);
|
|
248
|
+
const title = text.length === 0 ? null : text;
|
|
249
|
+
await session.command({ type: "title", title });
|
|
250
|
+
await options.onTitled?.(title);
|
|
251
|
+
return tell(interaction, title === null
|
|
252
|
+
? "Conversation title cleared; it follows the first prompt again."
|
|
253
|
+
: `Conversation named "${title}".`);
|
|
254
|
+
},
|
|
255
|
+
},
|
|
256
|
+
],
|
|
257
|
+
};
|
|
258
|
+
return commands.contribute(contribution);
|
|
259
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ShiitakeSession, Accepted, CancelResult, ForkedSession, PromptCommand, CompactCommand, CancelCommand, AbortCommand, BranchCommand, OperatorCommand, TitleCommand, ForkCommand, SessionCommand } from "@fungi.computer/shiitake/client";
|
|
2
|
+
/** A prompt may be recorded for a human without admitting Agent work. */
|
|
3
|
+
export type ParakeetPromptResult = Accepted | Readonly<{
|
|
4
|
+
/** The owner stored this prompt without starting Agent work. */
|
|
5
|
+
status: "recorded";
|
|
6
|
+
}>;
|
|
7
|
+
/** Session commands preserve their owner results, including held visitor lines. */
|
|
8
|
+
export type ParakeetSessionCommand = {
|
|
9
|
+
/** Admit Agent work or record a prompt held for a human reply. */
|
|
10
|
+
(input: PromptCommand | CompactCommand): Promise<ParakeetPromptResult>;
|
|
11
|
+
/** Cancel the named queued or running command. */
|
|
12
|
+
(input: CancelCommand): Promise<CancelResult>;
|
|
13
|
+
/** Forward an owner-supported Session control command. */
|
|
14
|
+
(input: AbortCommand | BranchCommand | OperatorCommand | TitleCommand): Promise<undefined>;
|
|
15
|
+
/** Return the owner-issued address of a forked Session. */
|
|
16
|
+
(input: ForkCommand): Promise<ForkedSession>;
|
|
17
|
+
/** Dispatch a typed command without inventing an admission result. */
|
|
18
|
+
(input: SessionCommand): Promise<ParakeetPromptResult | CancelResult | ForkedSession | undefined>;
|
|
19
|
+
};
|
|
20
|
+
/** The exact Shiitake operations consumed by the retained conversation UI. */
|
|
21
|
+
export type ParakeetSession = Readonly<Pick<ShiitakeSession, "address" | "extension" | "read" | "watch"> & {
|
|
22
|
+
/** Submit commands through this Session's admitted owner boundary. */
|
|
23
|
+
command: ParakeetSessionCommand;
|
|
24
|
+
}>;
|
package/dist/session.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import type { ParakeetAuthor } from "../core/author-labels.js";
|
|
2
|
+
import type { PromptDelivery, SessionCompactionTrigger, SessionMessage } from "@fungi.computer/shiitake/client";
|
|
3
|
+
import type { ToolArguments } from "../core/tool-contract.js";
|
|
4
|
+
import type { ToolCallView } from "../core/tool-view.js";
|
|
5
|
+
/** Exact Pi tool result joined to its tool call by the timeline projection. */
|
|
6
|
+
export type ToolResultMessage = Extract<SessionMessage["value"], {
|
|
7
|
+
role: "toolResult";
|
|
8
|
+
}>;
|
|
9
|
+
/** One user prompt projected into the conversation timeline. */
|
|
10
|
+
export type UserMessageItem = Readonly<{
|
|
11
|
+
/** The author the host read from the message metadata, apart from its text. */
|
|
12
|
+
author?: ParakeetAuthor | undefined;
|
|
13
|
+
/** Durable extension producer, separate from host author attribution. */
|
|
14
|
+
origin?: SessionMessage["origin"];
|
|
15
|
+
/** Stable rendered-item identity. */
|
|
16
|
+
id: string;
|
|
17
|
+
/** User-message timeline discriminator. */
|
|
18
|
+
kind: "user_message";
|
|
19
|
+
/**
|
|
20
|
+
* Client identity of a prompt this composer submitted. It stays the same from
|
|
21
|
+
* submit through queued to durable, so renderers key the row by it; it also
|
|
22
|
+
* names a failed admission to retry or dismiss.
|
|
23
|
+
*/
|
|
24
|
+
requestId?: string;
|
|
25
|
+
/** Owner-issued work identity once the prompt is admitted. */
|
|
26
|
+
commandId?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Whether admission is pending/accepted, the owner reports queued, or it
|
|
29
|
+
* failed/settled. Only `confirmed` means the Agent has taken the prompt.
|
|
30
|
+
*/
|
|
31
|
+
status: "pending" | "accepted" | "queued" | "failed" | "confirmed";
|
|
32
|
+
/** Delivery intent while this accepted input waits for consumption. */
|
|
33
|
+
delivery?: PromptDelivery;
|
|
34
|
+
/** Admission failure presented by the headless composer. */
|
|
35
|
+
error?: string;
|
|
36
|
+
/** When the prompt was sent, in milliseconds since the epoch, once known. */
|
|
37
|
+
at?: number;
|
|
38
|
+
/** Prompt text. */
|
|
39
|
+
text: string;
|
|
40
|
+
}>;
|
|
41
|
+
/** One locally submitted prompt before the Session projection catches up. */
|
|
42
|
+
export type LocalPromptAdmission = Readonly<{
|
|
43
|
+
/** Caller idempotency key, retained across retries. */
|
|
44
|
+
requestId: string;
|
|
45
|
+
/** Owner-issued identity after successful admission. */
|
|
46
|
+
commandId?: string;
|
|
47
|
+
/** Prompt content sent to the Session. */
|
|
48
|
+
content: string;
|
|
49
|
+
/** Existing Session delivery intent. */
|
|
50
|
+
delivery: PromptDelivery;
|
|
51
|
+
/** Current local admission result. */
|
|
52
|
+
status: "admitting" | "accepted" | "failed";
|
|
53
|
+
/** User-presentable admission error when status is failed. */
|
|
54
|
+
error?: string;
|
|
55
|
+
}>;
|
|
56
|
+
/** One assistant message projected from exact stored Pi content. */
|
|
57
|
+
export type AssistantMessageItem = Readonly<{
|
|
58
|
+
/** The author of a human reply carried as assistant text, as the host read it. */
|
|
59
|
+
author?: ParakeetAuthor | undefined;
|
|
60
|
+
/** Stable rendered-item identity. */
|
|
61
|
+
id: string;
|
|
62
|
+
/** Assistant-message timeline discriminator. */
|
|
63
|
+
kind: "assistant_message";
|
|
64
|
+
/** Whether the assistant message terminated with an error. */
|
|
65
|
+
isError?: boolean;
|
|
66
|
+
/** Whether replaceable progress is still contributing to this message. */
|
|
67
|
+
pending: boolean;
|
|
68
|
+
/** When the reply was written, in milliseconds since the epoch, once known. */
|
|
69
|
+
at?: number;
|
|
70
|
+
/** Assistant-visible response text. */
|
|
71
|
+
text: string;
|
|
72
|
+
/** Assistant reasoning text, when supplied by the model. */
|
|
73
|
+
thinking?: string;
|
|
74
|
+
/** Usage carried by the exact assistant message. */
|
|
75
|
+
usage?: Readonly<{
|
|
76
|
+
/** Provider cost of this assistant message. */
|
|
77
|
+
cost: number;
|
|
78
|
+
/** Tokens consumed by this assistant message. */
|
|
79
|
+
tokens: number;
|
|
80
|
+
}>;
|
|
81
|
+
}>;
|
|
82
|
+
/** One Pi tool call joined with its corresponding tool result. */
|
|
83
|
+
export type ToolItem = Readonly<{
|
|
84
|
+
/** Canonically parsed JSON arguments supplied to the tool. */
|
|
85
|
+
args: Readonly<ToolArguments>;
|
|
86
|
+
/** Stable tool-call identity. */
|
|
87
|
+
id: string;
|
|
88
|
+
/** Tool timeline discriminator. */
|
|
89
|
+
kind: "tool";
|
|
90
|
+
/** Pi tool name. */
|
|
91
|
+
name: string;
|
|
92
|
+
/** Exact joined Pi tool result, when one has completed. */
|
|
93
|
+
result?: ToolResultMessage;
|
|
94
|
+
/** Timestamp of the assistant message that issued the call. */
|
|
95
|
+
startedAt?: number;
|
|
96
|
+
/** Owner-confirmed activity or result; unknown when neither is available. */
|
|
97
|
+
status: "completed" | "error" | "running" | "unknown";
|
|
98
|
+
}>;
|
|
99
|
+
/**
|
|
100
|
+
* One maximal run of consecutive tool calls between conversation rows. A lone
|
|
101
|
+
* call is a group of one. Grouping is computed once by the headless projection.
|
|
102
|
+
*/
|
|
103
|
+
export type ToolGroupItem = Readonly<{
|
|
104
|
+
/** Running call whose live line the collapsed header shows. */
|
|
105
|
+
active?: ToolCallView | undefined;
|
|
106
|
+
/** Renderer-neutral view of each call, in call order. */
|
|
107
|
+
calls: readonly ToolCallView[];
|
|
108
|
+
/** First call to last result, once no call is running. */
|
|
109
|
+
durationMs?: number | undefined;
|
|
110
|
+
/** Calls whose joined result reports an error. */
|
|
111
|
+
failedCount: number;
|
|
112
|
+
/** Stable identity derived from the first call, kept as calls append. */
|
|
113
|
+
id: string;
|
|
114
|
+
/** Tool-group timeline discriminator. */
|
|
115
|
+
kind: "tool_group";
|
|
116
|
+
/** `running` for owner-confirmed work; unknown when a result is unavailable. */
|
|
117
|
+
status: "completed" | "error" | "running" | "unknown";
|
|
118
|
+
/** One-line summary from typed kinds, e.g. `Read 3 files, ran 2 commands`. */
|
|
119
|
+
summary: string;
|
|
120
|
+
/** Exact joined calls, in call order. */
|
|
121
|
+
tools: readonly ToolItem[];
|
|
122
|
+
}>;
|
|
123
|
+
/**
|
|
124
|
+
* One compaction boundary rendered as a divider: a full-width rule with a
|
|
125
|
+
* short label, never a chat bubble. Everything above it was summarized away;
|
|
126
|
+
* the agent's live context starts at the row immediately below it.
|
|
127
|
+
* @inline
|
|
128
|
+
*/
|
|
129
|
+
export type CompactionDividerItem = Readonly<{
|
|
130
|
+
/** Stable rendered-item identity, from the durable compaction entry. */
|
|
131
|
+
id: string;
|
|
132
|
+
/** Compaction-divider timeline discriminator. */
|
|
133
|
+
kind: "compaction_divider";
|
|
134
|
+
/** When the compaction ran, in milliseconds since the epoch. */
|
|
135
|
+
at: number;
|
|
136
|
+
/** Estimated context tokens the compaction started from. */
|
|
137
|
+
tokensBefore: number;
|
|
138
|
+
/** Estimated context tokens right after it; null for older compactions. */
|
|
139
|
+
tokensAfter: number | null;
|
|
140
|
+
}>;
|
|
141
|
+
/**
|
|
142
|
+
* A compaction that changed nothing, rendered as a short notice at its own
|
|
143
|
+
* place in the timeline: never a chat bubble, never a context edit.
|
|
144
|
+
* @inline
|
|
145
|
+
*/
|
|
146
|
+
export type CompactionNoticeItem = Readonly<{
|
|
147
|
+
/** Stable rendered-item identity, from the durable notice entry. */
|
|
148
|
+
id: string;
|
|
149
|
+
/** Compaction-notice timeline discriminator. */
|
|
150
|
+
kind: "compaction_notice";
|
|
151
|
+
/** When it was recorded, in milliseconds since the epoch. */
|
|
152
|
+
at: number;
|
|
153
|
+
/** What started it: the user, the context threshold, or an overflow. */
|
|
154
|
+
trigger: SessionCompactionTrigger;
|
|
155
|
+
/** What the compaction did: nothing to summarize, or a failure. */
|
|
156
|
+
result: "nothing_to_compact" | "failed";
|
|
157
|
+
/** A failure's bounded reason; null for "nothing to compact". */
|
|
158
|
+
diagnostic: string | null;
|
|
159
|
+
}>;
|
|
160
|
+
/** Stable row grammar rendered by Parakeet's timeline. */
|
|
161
|
+
export type TimelineItem = AssistantMessageItem | CompactionDividerItem | CompactionNoticeItem | ToolGroupItem | UserMessageItem;
|
|
162
|
+
/** Projection-internal rows before consecutive calls are grouped. */
|
|
163
|
+
export type ProjectedItem = AssistantMessageItem | CompactionDividerItem | CompactionNoticeItem | ToolItem | UserMessageItem;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|