@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,15 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { type ToolDisclosureState } from "../core/tool-groups.js";
|
|
3
|
+
import type { TimelineItem as TimelineRow, ToolItem } from "../store/types.js";
|
|
4
|
+
import { type ToggleToolDisclosure } from "./ToolGroup.js";
|
|
5
|
+
export declare const TimelineItem: import("react").NamedExoticComponent<Readonly<{
|
|
6
|
+
item: TimelineRow;
|
|
7
|
+
onDismissFailed?: ((requestId: string) => void) | undefined;
|
|
8
|
+
renderToolActions?: ((item: ToolItem) => ReactNode) | undefined;
|
|
9
|
+
renderAssistantAttachment?: ((text: string) => ReactNode) | undefined;
|
|
10
|
+
formatAssistantText?: ((text: string) => string) | undefined;
|
|
11
|
+
/** View-only open state for tool groups and calls. */
|
|
12
|
+
toolDisclosure?: ToolDisclosureState | undefined;
|
|
13
|
+
/** Flip one tool group or call. */
|
|
14
|
+
onToggleTool?: ToggleToolDisclosure | undefined;
|
|
15
|
+
}>>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { memo } from "react";
|
|
3
|
+
import { initialToolDisclosure, } from "../core/tool-groups.js";
|
|
4
|
+
import { assistantMessageVisible } from "../core/assistant-visibility.js";
|
|
5
|
+
import { formatTokenCount } from "../core/format-context.js";
|
|
6
|
+
import { ChatMessage } from "./ChatMessage.js";
|
|
7
|
+
import { ToolGroup } from "./ToolGroup.js";
|
|
8
|
+
const ignoreToggle = () => undefined;
|
|
9
|
+
export const TimelineItem = memo(function TimelineItem({ item, onDismissFailed, renderToolActions, renderAssistantAttachment, formatAssistantText, toolDisclosure = initialToolDisclosure, onToggleTool = ignoreToggle, }) {
|
|
10
|
+
switch (item.kind) {
|
|
11
|
+
case "user_message": {
|
|
12
|
+
const requestId = item.requestId;
|
|
13
|
+
const dismissAction = requestId === undefined || onDismissFailed === undefined ? null : (_jsx("button", { "aria-label": "Dismiss failed prompt", className: "btn btn-ghost btn-xs", onClick: () => {
|
|
14
|
+
onDismissFailed(requestId);
|
|
15
|
+
}, type: "button", children: "Dismiss" }));
|
|
16
|
+
return (_jsxs(_Fragment, { children: [item.author ? (_jsx("div", { className: "px-3 text-xs text-dim", "data-author": item.author.id, children: item.author.name })) : null, _jsx(ChatMessage, { pending: item.status !== "confirmed", speaker: "user", children: item.text }), item.status === "failed" ? (_jsxs("div", { className: "flex items-center gap-2 px-3 text-xs text-error", role: "alert", children: [_jsx("span", { children: "Your prompt didn\u2019t make it through." }), dismissAction] })) : null] }));
|
|
17
|
+
}
|
|
18
|
+
case "assistant_message":
|
|
19
|
+
if (!assistantMessageVisible(item))
|
|
20
|
+
return null;
|
|
21
|
+
return (_jsxs(_Fragment, { children: [item.author ? (_jsx("div", { className: "px-3 text-xs text-dim", "data-author": item.author.id, children: item.author.name })) : null, _jsx(ChatMessage, { isError: item.isError === true, pending: item.pending, speaker: "agent", ...(item.thinking ? { thinking: item.thinking } : {}), children: formatAssistantText?.(item.text) ?? item.text }), !item.pending && !item.isError
|
|
22
|
+
? renderAssistantAttachment?.(item.text)
|
|
23
|
+
: null] }));
|
|
24
|
+
case "tool_group":
|
|
25
|
+
return (_jsx(ToolGroup, { disclosure: toolDisclosure, group: item, onToggle: onToggleTool, renderToolActions: renderToolActions }));
|
|
26
|
+
case "compaction_divider":
|
|
27
|
+
return (_jsx("div", { className: "divider text-dim my-2 text-xs", role: "separator", children: item.tokensAfter === null
|
|
28
|
+
? "compacted · the agent’s memory starts below"
|
|
29
|
+
: `compacted ${formatTokenCount(item.tokensBefore)} → ${formatTokenCount(item.tokensAfter)}` }));
|
|
30
|
+
case "compaction_notice":
|
|
31
|
+
return (_jsxs("div", { className: `px-3 text-xs ${item.result === "failed" ? "text-error" : "text-dim"}`, role: "status", children: ["\u00B7", " ", item.result === "failed"
|
|
32
|
+
? "compaction failed"
|
|
33
|
+
: "nothing to compact", item.diagnostic === null ? "" : `: ${item.diagnostic}`] }));
|
|
34
|
+
}
|
|
35
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { type ToolDisclosureState } from "../core/tool-groups.js";
|
|
3
|
+
import type { ToolGroupItem, ToolItem } from "../store/types.js";
|
|
4
|
+
/** Flip one group or call; the caller owns the view-only disclosure state. */
|
|
5
|
+
export type ToggleToolDisclosure = (id: string, defaultOpen: boolean) => void;
|
|
6
|
+
/** Recent finished calls, or a live group, with reader-owned disclosure. */
|
|
7
|
+
export declare const ToolGroup: import("react").NamedExoticComponent<Readonly<{
|
|
8
|
+
group: ToolGroupItem;
|
|
9
|
+
disclosure: ToolDisclosureState;
|
|
10
|
+
onToggle: ToggleToolDisclosure;
|
|
11
|
+
renderToolActions?: ((item: ToolItem) => ReactNode) | undefined;
|
|
12
|
+
}>>;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { Badge } from "@fungi.computer/caps/components/badge";
|
|
3
|
+
import { DiffView } from "@fungi.computer/caps/components/diff-view";
|
|
4
|
+
import { Disclosure } from "@fungi.computer/caps/components/disclosure";
|
|
5
|
+
import { Status } from "@fungi.computer/caps/components/status";
|
|
6
|
+
import { Sigil } from "@fungi.computer/sigils";
|
|
7
|
+
import { memo } from "react";
|
|
8
|
+
import { disclosureOpen, toolCallDefaultOpen, toolGroupDefaultOpen, visibleToolCalls, } from "../core/tool-groups.js";
|
|
9
|
+
import { formatToolDuration, toolStatusTone as statusTone, toolKindSigils, } from "../core/tool-view.js";
|
|
10
|
+
import { CodeBlock } from "./CodeBlock.js";
|
|
11
|
+
/** Items beyond a section's preview, unless the reader asked for all. */
|
|
12
|
+
function visible(items, preview, full) {
|
|
13
|
+
return full || items.length <= preview
|
|
14
|
+
? { shown: items, hidden: 0 }
|
|
15
|
+
: { shown: items.slice(0, preview), hidden: items.length - preview };
|
|
16
|
+
}
|
|
17
|
+
function ShowMore({ hidden, onShowAll, }) {
|
|
18
|
+
if (hidden === 0)
|
|
19
|
+
return null;
|
|
20
|
+
return (_jsxs("button", { className: "btn btn-ghost btn-xs text-dim", onClick: onShowAll, type: "button", children: ["Show ", String(hidden), " more lines"] }));
|
|
21
|
+
}
|
|
22
|
+
const monoBlock = "not-prose m-0 overflow-x-auto rounded-lg border border-base-300 bg-base-200 px-sm py-xs font-mono text-[10px] leading-relaxed";
|
|
23
|
+
function SectionView({ section, full, onShowAll, }) {
|
|
24
|
+
switch (section.kind) {
|
|
25
|
+
case "diff": {
|
|
26
|
+
const { shown, hidden } = visible(section.lines, section.preview, full);
|
|
27
|
+
return (_jsxs("div", { className: "not-prose", children: [_jsx(DiffView, { hiddenLines: 0, lines: shown }), _jsx(ShowMore, { hidden: hidden, onShowAll: onShowAll })] }));
|
|
28
|
+
}
|
|
29
|
+
case "excerpt": {
|
|
30
|
+
const { shown, hidden } = visible(section.lines, section.preview, full);
|
|
31
|
+
return (_jsxs("div", { children: [_jsx("pre", { className: monoBlock, "data-parakeet-section": "excerpt", children: shown.map((line, index) => (_jsxs("span", { className: "block whitespace-pre", children: [line.number === undefined ? null : (_jsx("span", { className: "text-dim mr-sm inline-block w-8 select-none text-right", children: String(line.number) })), line.text] }, String(index)))) }), _jsx(ShowMore, { hidden: hidden, onShowAll: onShowAll })] }));
|
|
32
|
+
}
|
|
33
|
+
case "matches": {
|
|
34
|
+
const { shown, hidden } = visible(section.matches, section.preview, full);
|
|
35
|
+
return (_jsxs("div", { children: [_jsx("pre", { className: monoBlock, "data-parakeet-section": "matches", children: shown.map((match, index) => (_jsxs("span", { className: "block whitespace-pre", children: [match.location === "" ? null : (_jsx("span", { className: "text-info mr-sm", children: match.location })), match.text] }, String(index)))) }), _jsx(ShowMore, { hidden: hidden, onShowAll: onShowAll })] }));
|
|
36
|
+
}
|
|
37
|
+
case "command":
|
|
38
|
+
case "script": {
|
|
39
|
+
const { shown, hidden } = visible(section.lines, section.preview, full);
|
|
40
|
+
return (_jsxs("div", { children: [_jsx("pre", { className: monoBlock, "data-parakeet-section": section.kind, children: shown.map((line, index) => (_jsxs("span", { className: "block whitespace-pre", children: [section.kind === "command" && index === 0 ? (_jsx("span", { className: "text-dim select-none", children: "$ " })) : null, line] }, String(index)))) }), _jsx(ShowMore, { hidden: hidden, onShowAll: onShowAll })] }));
|
|
41
|
+
}
|
|
42
|
+
case "output": {
|
|
43
|
+
const { shown, hidden } = visible(section.lines, section.preview, full);
|
|
44
|
+
return (_jsxs("div", { children: [_jsx("pre", { className: monoBlock, "data-parakeet-section": "output", children: shown.map((line, index) => (_jsxs("span", { className: line.stream === "stderr"
|
|
45
|
+
? "block whitespace-pre text-error"
|
|
46
|
+
: "block whitespace-pre", "data-stream": line.stream, children: [line.stream === "stderr" ? (_jsx("span", { className: "select-none", children: "\u258D" })) : null, line.text] }, String(index)))) }), _jsx(ShowMore, { hidden: hidden, onShowAll: onShowAll })] }));
|
|
47
|
+
}
|
|
48
|
+
case "text": {
|
|
49
|
+
const { shown, hidden } = visible(section.lines, section.preview, full);
|
|
50
|
+
return (_jsxs("div", { children: [_jsx(CodeBlock, { className: "overflow-hidden rounded-lg", content: shown.join("\n"), header: section.label, ...(section.language === undefined
|
|
51
|
+
? {}
|
|
52
|
+
: { language: section.language }) }), _jsx(ShowMore, { hidden: hidden, onShowAll: onShowAll })] }));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function CallBody({ call, tool, disclosure, onToggle, }) {
|
|
57
|
+
const fullId = `${call.id}:full`;
|
|
58
|
+
const full = disclosureOpen(disclosure, fullId, false);
|
|
59
|
+
const showAll = () => {
|
|
60
|
+
onToggle(fullId, false);
|
|
61
|
+
};
|
|
62
|
+
return (_jsxs("div", { className: "space-y-1.5 py-1.5 pr-2", "data-parakeet-call-body": true, children: [call.error === undefined ? null : (_jsx("p", { className: "not-prose m-0 font-mono text-[11px] text-error", role: "alert", children: call.error })), call.sections.map((section, index) => (_jsx(SectionView, { full: full, onShowAll: showAll, section: section }, `${section.kind}:${String(index)}`))), tool?.result?.content
|
|
63
|
+
.filter((part) => part.type === "image")
|
|
64
|
+
.map((part, index) => (_jsx("img", { alt: "Tool result", className: "max-w-full", src: `data:${part.mimeType};base64,${part.data}`, style: { maxHeight: 400 } }, `${call.id}-image-${String(index)}`)))] }));
|
|
65
|
+
}
|
|
66
|
+
function CallRow({ call, tool, disclosureId, size, disclosure, onToggle, renderToolActions, }) {
|
|
67
|
+
const defaultOpen = toolCallDefaultOpen(call);
|
|
68
|
+
const open = disclosureOpen(disclosure, disclosureId, defaultOpen);
|
|
69
|
+
const running = call.status === "running";
|
|
70
|
+
return (_jsxs("div", { "data-parakeet-call": call.kind, "data-status": call.status, children: [_jsx(Disclosure, { leading: _jsx(Sigil, { name: toolKindSigils[call.kind], size: 16 }), onOpenChange: () => {
|
|
71
|
+
onToggle(disclosureId, defaultOpen);
|
|
72
|
+
}, open: open, size: size, summary: _jsxs(_Fragment, { children: [_jsx("span", { className: "text-base-content", children: running ? call.activeVerb : call.verb }), " ", _jsx("span", { className: "font-mono", children: call.label })] }), tone: call.status === "error" ? "error" : "neutral", trailing: _jsxs(_Fragment, { children: [call.exitCode === undefined ? null : (_jsxs(Badge, { size: "sm", tone: "error", children: ["exit ", String(call.exitCode)] })), call.durationMs === undefined ? null : (_jsx("span", { children: formatToolDuration(call.durationMs) })), _jsx(Status, { motion: running ? "bounce" : "none", title: call.status === "unknown" ? "result unavailable" : call.status, tone: statusTone(call.status) })] }), children: _jsx(CallBody, { call: call, disclosure: disclosure, onToggle: onToggle, tool: tool }) }), call.status === "completed" && tool?.result !== undefined
|
|
73
|
+
? renderToolActions?.(tool)
|
|
74
|
+
: null] }));
|
|
75
|
+
}
|
|
76
|
+
/** Recent finished calls, or a live group, with reader-owned disclosure. */
|
|
77
|
+
export const ToolGroup = memo(function ToolGroup({ group, disclosure, onToggle, renderToolActions, }) {
|
|
78
|
+
const defaultOpen = toolGroupDefaultOpen(group);
|
|
79
|
+
const open = disclosureOpen(disclosure, group.id, defaultOpen);
|
|
80
|
+
const running = group.status === "running";
|
|
81
|
+
const active = group.active;
|
|
82
|
+
const single = group.calls.length === 1 ? group.calls[0] : undefined;
|
|
83
|
+
if (single !== undefined)
|
|
84
|
+
return (_jsx("div", { className: "px-1", children: _jsx(CallRow, { call: single, disclosure: disclosure, disclosureId: single.id, onToggle: onToggle, renderToolActions: renderToolActions, size: "row", tool: group.tools[0] }) }));
|
|
85
|
+
return (_jsxs("div", { className: "px-1", children: [_jsx(Disclosure, { className: "[&>.caps-disclosure-panel]:hidden", leading: _jsx(Sigil, { name: "list", size: 16 }), onOpenChange: () => {
|
|
86
|
+
onToggle(group.id, defaultOpen);
|
|
87
|
+
}, open: open, summary: running && active !== undefined ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "text-base-content", children: active.activeVerb }), " ", _jsx("span", { className: "font-mono", children: active.label }), " \u00B7", " ", String(group.calls.length), " ", group.calls.length === 1 ? "call" : "calls"] })) : (_jsxs("span", { className: "text-base-content", children: [group.summary, " \u00B7 ", String(group.calls.length), " ", group.calls.length === 1 ? "call" : "calls"] })), tone: group.status === "error" ? "error" : "neutral", trailing: _jsxs(_Fragment, { children: [group.failedCount > 0 ? (_jsxs("span", { className: "text-error", children: [String(group.failedCount), " failed"] })) : null, group.durationMs === undefined ? null : (_jsx("span", { children: formatToolDuration(group.durationMs) })), _jsx(Status, { motion: running ? "bounce" : "none", title: group.status === "unknown" ? "result unavailable" : group.status, tone: statusTone(group.status) })] }) }), visibleToolCalls(group, open).map((call) => (_jsx(CallRow, { call: call, disclosure: disclosure, disclosureId: call.id, onToggle: onToggle, renderToolActions: renderToolActions, size: "row", tool: group.tools.find((tool) => tool.id === call.id) }, call.id))), group.status === "completed" && group.calls.length > 3 ? (_jsx("button", { "aria-expanded": open, className: "btn btn-ghost btn-xs text-dim", onClick: () => {
|
|
88
|
+
onToggle(group.id, defaultOpen);
|
|
89
|
+
}, type: "button", children: open ? "Show less" : `Show all ${String(group.calls.length)} calls` })) : null] }));
|
|
90
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type SessionViewState } from "../core/session-view-state.js";
|
|
2
|
+
/** A queued Session reports the executor fact; stopping a turn leaves its queue intact. */
|
|
3
|
+
export declare function WaitingNotice({ waiting, }: Readonly<{
|
|
4
|
+
waiting: Extract<SessionViewState, {
|
|
5
|
+
kind: "queued";
|
|
6
|
+
}> | null;
|
|
7
|
+
}>): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { queuedSessionLabel, } from "../core/session-view-state.js";
|
|
3
|
+
/** A queued Session reports the executor fact; stopping a turn leaves its queue intact. */
|
|
4
|
+
export function WaitingNotice({ waiting, }) {
|
|
5
|
+
if (waiting === null)
|
|
6
|
+
return null;
|
|
7
|
+
return (_jsx("div", { role: "status", className: "flex items-center justify-between gap-2 px-3 py-1.5 text-xs text-dim", "data-parakeet-waiting": "waiting", children: _jsx("span", { children: queuedSessionLabel(waiting) }) }));
|
|
8
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Avatar } from "@fungi.computer/sprite/avatar";
|
|
2
|
+
import type { AvatarPresentation as SpriteAvatarPresentation } from "@fungi.computer/sprite";
|
|
3
|
+
/**
|
|
4
|
+
* Sprite props for one Agent's avatar, independent of the live `activity` a
|
|
5
|
+
* host drives moment to moment. Unlike the Sprite service's own
|
|
6
|
+
* `AvatarPresentation`, these are never optional: every Agent record carries
|
|
7
|
+
* a complete avatar.
|
|
8
|
+
*/
|
|
9
|
+
export type AvatarSpriteProps = {
|
|
10
|
+
readonly src: SpriteAvatarPresentation["src"];
|
|
11
|
+
readonly appearance: NonNullable<SpriteAvatarPresentation["appearance"]>;
|
|
12
|
+
readonly expression: NonNullable<SpriteAvatarPresentation["expression"]>;
|
|
13
|
+
readonly renderStyle: NonNullable<SpriteAvatarPresentation["renderStyle"]>;
|
|
14
|
+
};
|
|
15
|
+
/** Map an Agent's avatar to Sprite props. */
|
|
16
|
+
export declare function avatarPresentation(avatar: Avatar): AvatarSpriteProps;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createSprite } from "@fungi.computer/sprite";
|
|
2
|
+
/** The one Sprite service Parakeet's mascot components share. */
|
|
3
|
+
export const shiitakeSprite = createSprite({
|
|
4
|
+
characters: {
|
|
5
|
+
mushroom: async () => (await import("@fungi.computer/sprite-zdog/mushroom")).default,
|
|
6
|
+
cat: async () => (await import("@fungi.computer/sprite-zdog/cat")).default,
|
|
7
|
+
burger: async () => (await import("@fungi.computer/sprite-zdog/burger")).default,
|
|
8
|
+
},
|
|
9
|
+
});
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { type ParakeetAuthorOf } from "./core/author-labels.js";
|
|
2
|
+
import { type PromptDelivery, type SessionContext, type SessionExtensionSlots, type SessionPendingPrompts } from "@fungi.computer/shiitake/client";
|
|
3
|
+
import type { ClientEntryV1 } from "@fungi.computer/shiitake/client-entry";
|
|
4
|
+
import { type ClientContribution } from "./core/client-contributions.js";
|
|
5
|
+
import { type ParakeetInteractions } from "./commands/interactions.js";
|
|
6
|
+
import type { WhistleExecutionOutcome } from "@fungi.computer/whistle";
|
|
7
|
+
import { type ReactNode } from "react";
|
|
8
|
+
import { type SessionViewState } from "./core/session-view-state.js";
|
|
9
|
+
import type { ParakeetSession } from "./session.js";
|
|
10
|
+
import type { TimelineItem } from "./store/types.js";
|
|
11
|
+
/** Stable model identity presented by the current Session. */
|
|
12
|
+
export type ParakeetModel = Readonly<{
|
|
13
|
+
/** Provider model identifier. */
|
|
14
|
+
model: string;
|
|
15
|
+
/** Provider identifier. */
|
|
16
|
+
provider: string;
|
|
17
|
+
}>;
|
|
18
|
+
/** Aggregate usage presented by the current Session timeline. */
|
|
19
|
+
export type ParakeetUsage = Readonly<{
|
|
20
|
+
/** Accumulated provider cost. */
|
|
21
|
+
cost: number;
|
|
22
|
+
/** Accumulated token count. */
|
|
23
|
+
tokens: number;
|
|
24
|
+
}>;
|
|
25
|
+
/** Conversation activity presented by Parakeet. */
|
|
26
|
+
export type ParakeetStatus = "connecting" | "cancelling" | "error" | "idle" | "queued" | "retrying" | "sending" | "streaming" | "thinking" | "disconnected";
|
|
27
|
+
/** Owner activity with the connection states shown while observation opens. */
|
|
28
|
+
export type ParakeetSessionViewState = SessionViewState | Readonly<{
|
|
29
|
+
/** Session observation is opening. */
|
|
30
|
+
kind: "connecting";
|
|
31
|
+
}> | Readonly<{
|
|
32
|
+
/** Session observation is unavailable. */
|
|
33
|
+
kind: "disconnected";
|
|
34
|
+
/** Reason suitable for presentation. */
|
|
35
|
+
cause: string;
|
|
36
|
+
}>;
|
|
37
|
+
/** Health of the current Session observation. */
|
|
38
|
+
export type ParakeetObservation = Readonly<{
|
|
39
|
+
/** Observation is opening. */
|
|
40
|
+
status: "connecting";
|
|
41
|
+
}> | Readonly<{
|
|
42
|
+
/** Observation is current. */
|
|
43
|
+
status: "live";
|
|
44
|
+
}> | Readonly<{
|
|
45
|
+
/** Observation failed and can be reopened. */
|
|
46
|
+
status: "unavailable";
|
|
47
|
+
/** Sanitized reason suitable for presentation. */
|
|
48
|
+
reason: string;
|
|
49
|
+
}>;
|
|
50
|
+
/** Stable history and replaceable work rendered by a conversation client. */
|
|
51
|
+
export type TimelineController = Readonly<{
|
|
52
|
+
/** Durable-backed rows whose identity is stable across progress revisions. */
|
|
53
|
+
settled: readonly TimelineItem[];
|
|
54
|
+
/** Replaceable progress, queued, and optimistic rows. */
|
|
55
|
+
tail: readonly TimelineItem[];
|
|
56
|
+
/** Last actually rendered durable row for each loaded command. */
|
|
57
|
+
commandAnchors: ReadonlyMap<string, string>;
|
|
58
|
+
/** Current owner-admitted prompts, independent of the visible history page. */
|
|
59
|
+
queued: SessionPendingPrompts;
|
|
60
|
+
/** Whether more admitted prompts exist beyond this projection. */
|
|
61
|
+
pendingHasMore: boolean;
|
|
62
|
+
/** Whether older history remains, unloaded, before `settled[0]`. */
|
|
63
|
+
hasMoreHistory: boolean;
|
|
64
|
+
/** An older history page is currently loading. */
|
|
65
|
+
loadingOlderHistory: boolean;
|
|
66
|
+
/** Load the next older history page; a no-op while one is in flight. */
|
|
67
|
+
loadOlderHistory: () => void;
|
|
68
|
+
/** Whether a newer evicted page lies beyond the retained history window. */
|
|
69
|
+
hasNewerHistory: boolean;
|
|
70
|
+
/** Refetch the nearest newer page after browsing backward. */
|
|
71
|
+
loadNewerHistory: () => void;
|
|
72
|
+
/** Keep the currently read page visible while the live tail advances. */
|
|
73
|
+
pinVisibleHistory: () => void;
|
|
74
|
+
/** Return to the live page and release paged history. */
|
|
75
|
+
jumpToLatest: () => void;
|
|
76
|
+
/** Newest durable assistant model identity. */
|
|
77
|
+
model?: ParakeetModel | undefined;
|
|
78
|
+
/** Accumulated durable usage. */
|
|
79
|
+
usage?: ParakeetUsage | undefined;
|
|
80
|
+
}>;
|
|
81
|
+
/** Draft and prompt operations for the current conversation. */
|
|
82
|
+
export type ComposerController = Readonly<{
|
|
83
|
+
/** Stop the current turn. Queued prompts keep draining; the draft is unchanged. */
|
|
84
|
+
cancel: () => Promise<void>;
|
|
85
|
+
/** Current local input. */
|
|
86
|
+
draft: string;
|
|
87
|
+
/** Typed reason the latest prompt did not complete. */
|
|
88
|
+
failure: "admission" | "failed" | "cancelled" | "interrupted" | undefined;
|
|
89
|
+
/** Current send could not enter the bounded local admission queue. */
|
|
90
|
+
admissionError: "queue_full" | undefined;
|
|
91
|
+
/** Retry the exact most recent failed prompt. */
|
|
92
|
+
retry: () => void;
|
|
93
|
+
/** Remove one failed local admission from this conversation. */
|
|
94
|
+
dismissFailed: (requestId: string) => void;
|
|
95
|
+
/** Submit the current draft with the requested delivery intent. */
|
|
96
|
+
send: (delivery?: PromptDelivery) => void;
|
|
97
|
+
/**
|
|
98
|
+
* Run a host command, such as Whistle slash dispatch, for the current draft.
|
|
99
|
+
* Parakeet clears the draft only when the command handled it without
|
|
100
|
+
* declining (a refused replacement keeps the text) and the draft was
|
|
101
|
+
* not edited while the command ran. The callback can consume that exact
|
|
102
|
+
* draft on dispatch when the command definition requests it.
|
|
103
|
+
*/
|
|
104
|
+
submitCommand: (run: (draft: string, consumeDraft: () => void) => Promise<WhistleExecutionOutcome | undefined>) => Promise<WhistleExecutionOutcome | undefined>;
|
|
105
|
+
/** Replace the local input. */
|
|
106
|
+
setDraft: (value: string) => void;
|
|
107
|
+
}>;
|
|
108
|
+
/** Session activity, observation, and Agent-lifetime controls. */
|
|
109
|
+
export type StatusController = Readonly<{
|
|
110
|
+
/** Owner-issued identity of the running or queued Session command. */
|
|
111
|
+
commandId: string | undefined;
|
|
112
|
+
/** Health of the shared Session observation. */
|
|
113
|
+
observation: ParakeetObservation;
|
|
114
|
+
/** Reopen the shared Session observation. */
|
|
115
|
+
reconnect: () => Promise<ParakeetReconnectOutcome>;
|
|
116
|
+
/** Current conversation activity. */
|
|
117
|
+
status: ParakeetStatus;
|
|
118
|
+
/** Owner state, or a typed client connection state when the owner is unreachable. */
|
|
119
|
+
viewState: ParakeetSessionViewState;
|
|
120
|
+
/** Context use as the Session's compaction measures it, once known. */
|
|
121
|
+
context: SessionContext | undefined;
|
|
122
|
+
}>;
|
|
123
|
+
/** Result of retrying the shared Session observation. */
|
|
124
|
+
export type ParakeetReconnectOutcome = Readonly<{
|
|
125
|
+
/** No reconnect was needed. */
|
|
126
|
+
kind: "nothing_to_reconnect";
|
|
127
|
+
/** Existing observation state. */
|
|
128
|
+
state: "connected" | "connecting";
|
|
129
|
+
}> | Readonly<{
|
|
130
|
+
/** Session observation reopened. */
|
|
131
|
+
kind: "reconnected";
|
|
132
|
+
}> | Readonly<{
|
|
133
|
+
/** Reopening failed. */
|
|
134
|
+
kind: "failed";
|
|
135
|
+
/** Reason suitable for presentation. */
|
|
136
|
+
cause: string;
|
|
137
|
+
}>;
|
|
138
|
+
/** Own one renderer-neutral conversation scope over the existing query cache. */
|
|
139
|
+
export declare function ParakeetProvider({ children, session, clients, interactionStore, authorOf, }: Readonly<{
|
|
140
|
+
children: ReactNode;
|
|
141
|
+
session: ParakeetSession;
|
|
142
|
+
clients?: readonly ClientEntryV1[] | undefined;
|
|
143
|
+
interactionStore?: ParakeetInteractions | undefined;
|
|
144
|
+
/**
|
|
145
|
+
* Read the author to show from a message's opaque host metadata. Absent,
|
|
146
|
+
* lines show no author.
|
|
147
|
+
*/
|
|
148
|
+
authorOf?: ParakeetAuthorOf | undefined;
|
|
149
|
+
}>): import("react/jsx-runtime").JSX.Element;
|
|
150
|
+
/** Read stable history and replaceable live work. */
|
|
151
|
+
export declare function useTimeline(): TimelineController;
|
|
152
|
+
/** Read and mutate the current conversation draft and prompt. */
|
|
153
|
+
export declare function useComposer(): ComposerController;
|
|
154
|
+
/** Dismiss a failed prompt without subscribing the timeline to composer edits. */
|
|
155
|
+
export declare function useDismissFailedPrompt(): (requestId: string) => void;
|
|
156
|
+
/** The Session this conversation observes. */
|
|
157
|
+
export declare function useParakeetSession(): ParakeetSession;
|
|
158
|
+
/** Read the Session's extension slots, including advertised command catalogs. */
|
|
159
|
+
export declare function useExtensionSlots(): SessionExtensionSlots;
|
|
160
|
+
/** Read Session activity and operate its observation. */
|
|
161
|
+
export declare function useStatus(): StatusController;
|
|
162
|
+
/** Presentation admitted once from the selected Session's already observed slots. */
|
|
163
|
+
export declare function useClientContributions(): readonly ClientContribution[];
|
|
164
|
+
/** The selected Session's ordinary command interaction owner. */
|
|
165
|
+
export declare function useParakeetInteractions(): ParakeetInteractions;
|