@usecontextlayer/pi-durable-assistant-ui 1.0.0 → 2.0.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 +37 -52
- package/dist/attachments.d.ts +2 -2
- package/dist/attachments.d.ts.map +1 -1
- package/dist/attachments.js +1 -1
- package/dist/client.d.ts +42 -13
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +112 -41
- package/dist/conversation.d.ts +44 -0
- package/dist/conversation.d.ts.map +1 -0
- package/dist/conversation.js +149 -0
- package/dist/index.d.ts +8 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -4
- package/dist/metadata.d.ts +1 -2
- package/dist/metadata.d.ts.map +1 -1
- package/dist/metadata.js +0 -1
- package/dist/projection.d.ts +16 -2
- package/dist/projection.d.ts.map +1 -1
- package/dist/projection.js +41 -17
- package/dist/thread-list.d.ts +6 -0
- package/dist/thread-list.d.ts.map +1 -0
- package/dist/thread-list.js +39 -0
- package/dist/use-pi-durable-runtime.d.ts +22 -0
- package/dist/use-pi-durable-runtime.d.ts.map +1 -0
- package/dist/use-pi-durable-runtime.js +95 -0
- package/package.json +7 -6
- package/dist/store.d.ts +0 -57
- package/dist/store.d.ts.map +0 -1
- package/dist/store.js +0 -261
- package/dist/use-pi-runtime.d.ts +0 -17
- package/dist/use-pi-runtime.d.ts.map +0 -1
- package/dist/use-pi-runtime.js +0 -49
package/dist/store.d.ts
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import type { ConversationId, ConversationRecord, EntryId, SubmissionDraft, SubmissionRecord, TranscriptView } from "@earendil-works/pi-durable";
|
|
2
|
-
import type { AppendMessage, ThreadMessageLike } from "@assistant-ui/react";
|
|
3
|
-
import type { PiClient, PiConnectionState, SerializedConversationCreateOptions, SerializedAgentChange } from "./client.js";
|
|
4
|
-
import type { ConversationMetadata, ConversationMetadataPatch } from "./metadata.js";
|
|
5
|
-
export interface PiRuntimeState {
|
|
6
|
-
readonly conversations: readonly ConversationRecord[];
|
|
7
|
-
readonly selectedId: ConversationId | undefined;
|
|
8
|
-
readonly view: TranscriptView | undefined;
|
|
9
|
-
readonly messages: readonly ThreadMessageLike[];
|
|
10
|
-
readonly isLoading: boolean;
|
|
11
|
-
readonly isRunning: boolean;
|
|
12
|
-
readonly connection: PiConnectionState;
|
|
13
|
-
readonly error: Error | undefined;
|
|
14
|
-
readonly hasEarlier: boolean;
|
|
15
|
-
readonly metadata: Readonly<Record<string, ConversationMetadata>>;
|
|
16
|
-
}
|
|
17
|
-
export interface PiRuntimeStoreOptions {
|
|
18
|
-
initialConversationId?: ConversationId;
|
|
19
|
-
pageSize?: number;
|
|
20
|
-
}
|
|
21
|
-
/** A disposable client view of Pi, not a second durable conversation store. */
|
|
22
|
-
export declare class PiRuntimeStore {
|
|
23
|
-
#private;
|
|
24
|
-
readonly client: PiClient;
|
|
25
|
-
constructor(client: PiClient, options?: PiRuntimeStoreOptions);
|
|
26
|
-
getSnapshot: () => PiRuntimeState;
|
|
27
|
-
subscribe: (listener: () => void) => (() => void);
|
|
28
|
-
start: () => void;
|
|
29
|
-
stop: () => void;
|
|
30
|
-
refreshConversations: () => Promise<void>;
|
|
31
|
-
selectConversation: (id: ConversationId) => void;
|
|
32
|
-
createConversation: (options?: SerializedConversationCreateOptions) => Promise<ConversationRecord>;
|
|
33
|
-
refreshMetadata: (id?: ConversationId | undefined) => Promise<void>;
|
|
34
|
-
updateMetadata: (id: ConversationId, patch: ConversationMetadataPatch) => Promise<void>;
|
|
35
|
-
renameConversation: (id: ConversationId, title: string) => Promise<void>;
|
|
36
|
-
archiveConversation: (id: ConversationId) => Promise<void>;
|
|
37
|
-
unarchiveConversation: (id: ConversationId) => Promise<void>;
|
|
38
|
-
setFeedback: (entryId: EntryId, rating: "positive" | "negative" | null) => Promise<void>;
|
|
39
|
-
submitFeedback: (messageId: string, rating: "positive" | "negative") => void;
|
|
40
|
-
submit: (submission: SubmissionDraft) => Promise<SubmissionRecord>;
|
|
41
|
-
continue: () => Promise<SubmissionRecord>;
|
|
42
|
-
steer: (content: Extract<SubmissionDraft, {
|
|
43
|
-
type: "input";
|
|
44
|
-
}>["content"]) => Promise<SubmissionRecord>;
|
|
45
|
-
abortSubmission: (id: SubmissionRecord["id"]) => Promise<"aborted" | "already_placed" | "not_found" | "settled">;
|
|
46
|
-
/** Retrying an edit creates a native fork and records an immutable context replacement there. */
|
|
47
|
-
edit: (message: AppendMessage) => Promise<void>;
|
|
48
|
-
/** Keep the answer in original history; the fork omits it from its next model context. */
|
|
49
|
-
regenerate: (parentId: string | null) => Promise<void>;
|
|
50
|
-
cancel: () => Promise<void>;
|
|
51
|
-
configure: (change: SerializedAgentChange) => Promise<void>;
|
|
52
|
-
reset: (handoff?: string) => Promise<void>;
|
|
53
|
-
compact: (instructions?: string) => Promise<import("@earendil-works/pi-durable").TaskId<import("@earendil-works/pi-durable").CompactionResult>>;
|
|
54
|
-
forkAt: (at: EntryId) => Promise<ConversationRecord>;
|
|
55
|
-
loadEarlier: () => Promise<void>;
|
|
56
|
-
}
|
|
57
|
-
//# sourceMappingURL=store.d.ts.map
|
package/dist/store.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
|
package/dist/store.js
DELETED
|
@@ -1,261 +0,0 @@
|
|
|
1
|
-
import { BACKGROUND_CONTEXT, withAbortSignal } from "@earendil-works/chord/context";
|
|
2
|
-
import { ConversationTranscript } from "@earendil-works/pi-durable";
|
|
3
|
-
import { conversationLiveState, entryIdFromMessageId, isForegroundRunning, projectConversation, toPiUserInput } from "./projection.js";
|
|
4
|
-
function runtimeSnapshot(source) {
|
|
5
|
-
const { view } = source;
|
|
6
|
-
return {
|
|
7
|
-
...source,
|
|
8
|
-
messages: view ? projectConversation(view, source.metadata[String(view.conversation.id)]) : [],
|
|
9
|
-
isRunning: view ? isForegroundRunning(view) : false,
|
|
10
|
-
hasEarlier: view?.items[0]?.kind === "earlier",
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
|
-
/** A disposable client view of Pi, not a second durable conversation store. */
|
|
14
|
-
export class PiRuntimeStore {
|
|
15
|
-
client;
|
|
16
|
-
#options;
|
|
17
|
-
#listeners = new Set();
|
|
18
|
-
#transcripts = new Map();
|
|
19
|
-
#views = new Map();
|
|
20
|
-
#filling = new Map();
|
|
21
|
-
#disconnect;
|
|
22
|
-
#selection = new AbortController();
|
|
23
|
-
#started = false;
|
|
24
|
-
#state;
|
|
25
|
-
constructor(client, options = {}) {
|
|
26
|
-
this.client = client;
|
|
27
|
-
this.#options = options;
|
|
28
|
-
this.#state = runtimeSnapshot({ conversations: [], selectedId: options.initialConversationId, view: undefined, isLoading: false, connection: "idle", error: undefined, metadata: {} });
|
|
29
|
-
}
|
|
30
|
-
getSnapshot = () => this.#state;
|
|
31
|
-
subscribe = (listener) => {
|
|
32
|
-
this.#listeners.add(listener);
|
|
33
|
-
return () => this.#listeners.delete(listener);
|
|
34
|
-
};
|
|
35
|
-
#set(patch) {
|
|
36
|
-
const next = { ...this.#state, ...patch };
|
|
37
|
-
this.#state = next.view === this.#state.view && next.metadata === this.#state.metadata ? next : runtimeSnapshot(next);
|
|
38
|
-
for (const listener of this.#listeners)
|
|
39
|
-
listener();
|
|
40
|
-
}
|
|
41
|
-
#report(cause) {
|
|
42
|
-
this.#set({ error: cause instanceof Error ? cause : new Error(String(cause)), isLoading: false });
|
|
43
|
-
}
|
|
44
|
-
#transcript(id) {
|
|
45
|
-
let transcript = this.#transcripts.get(id);
|
|
46
|
-
if (!transcript) {
|
|
47
|
-
transcript = new ConversationTranscript((query, limit, context) => this.client.entries(id, query, limit, undefined, context.abortSignal), { pageSize: this.#options.pageSize });
|
|
48
|
-
this.#transcripts.set(id, transcript);
|
|
49
|
-
}
|
|
50
|
-
return transcript;
|
|
51
|
-
}
|
|
52
|
-
#show(id, view) {
|
|
53
|
-
this.#views.set(id, view);
|
|
54
|
-
if (this.#state.selectedId !== id)
|
|
55
|
-
return;
|
|
56
|
-
this.#set({ view, isLoading: false, error: undefined });
|
|
57
|
-
}
|
|
58
|
-
start = () => {
|
|
59
|
-
if (this.#started)
|
|
60
|
-
return;
|
|
61
|
-
this.#started = true;
|
|
62
|
-
if (this.#state.selectedId !== undefined)
|
|
63
|
-
this.selectConversation(this.#state.selectedId);
|
|
64
|
-
void this.refreshConversations().catch((error) => this.#report(error));
|
|
65
|
-
};
|
|
66
|
-
stop = () => {
|
|
67
|
-
this.#started = false;
|
|
68
|
-
this.#disconnect?.();
|
|
69
|
-
this.#disconnect = undefined;
|
|
70
|
-
this.#selection.abort();
|
|
71
|
-
};
|
|
72
|
-
refreshConversations = async () => {
|
|
73
|
-
const load = async () => {
|
|
74
|
-
const conversations = [];
|
|
75
|
-
let cursor;
|
|
76
|
-
do {
|
|
77
|
-
const page = await this.client.listConversations({}, 100, cursor);
|
|
78
|
-
conversations.push(...page.items);
|
|
79
|
-
cursor = page.next;
|
|
80
|
-
} while (cursor);
|
|
81
|
-
return conversations;
|
|
82
|
-
};
|
|
83
|
-
const [conversations, loaded] = await Promise.all([load(), this.client.listMetadata?.()]);
|
|
84
|
-
this.#set({ conversations, ...(loaded ? { metadata: loaded } : {}) });
|
|
85
|
-
if (this.#started && this.#state.selectedId === undefined && conversations[0])
|
|
86
|
-
this.selectConversation(conversations[0].id);
|
|
87
|
-
};
|
|
88
|
-
selectConversation = (id) => {
|
|
89
|
-
this.#disconnect?.();
|
|
90
|
-
this.#selection.abort();
|
|
91
|
-
this.#selection = new AbortController();
|
|
92
|
-
const cached = this.#views.get(id);
|
|
93
|
-
this.#set({ selectedId: id, view: cached, isLoading: !cached, error: undefined, connection: "connecting" });
|
|
94
|
-
if (!this.#started)
|
|
95
|
-
return;
|
|
96
|
-
const transcript = this.#transcript(id);
|
|
97
|
-
this.#disconnect = this.client.watch(id, (view) => {
|
|
98
|
-
const previous = this.#views.get(id);
|
|
99
|
-
this.#show(id, transcript.merge(view));
|
|
100
|
-
if (previous && conversationLiveState(previous).run && !conversationLiveState(view).run)
|
|
101
|
-
void this.refreshConversations().catch((cause) => this.#report(cause));
|
|
102
|
-
const signal = this.#selection.signal;
|
|
103
|
-
void this.#fillGaps(id).catch((cause) => { if (!signal.aborted && this.#state.selectedId === id)
|
|
104
|
-
this.#report(cause); });
|
|
105
|
-
}, {
|
|
106
|
-
window: () => transcript.resume,
|
|
107
|
-
onConnection: (connection) => {
|
|
108
|
-
if (this.#state.selectedId !== id)
|
|
109
|
-
return;
|
|
110
|
-
const becameConnected = connection === "connected" && this.#state.connection !== "connected";
|
|
111
|
-
this.#set({ connection });
|
|
112
|
-
if (becameConnected)
|
|
113
|
-
void this.refreshMetadata(id).catch((cause) => this.#report(cause));
|
|
114
|
-
},
|
|
115
|
-
onError: (error) => { if (this.#state.selectedId === id)
|
|
116
|
-
this.#report(error); },
|
|
117
|
-
});
|
|
118
|
-
};
|
|
119
|
-
createConversation = async (options) => {
|
|
120
|
-
this.#set({ isLoading: true, error: undefined });
|
|
121
|
-
try {
|
|
122
|
-
const conversation = await this.client.createConversation(options);
|
|
123
|
-
this.#set({ conversations: [conversation, ...this.#state.conversations.filter((item) => item.id !== conversation.id)] });
|
|
124
|
-
this.selectConversation(conversation.id);
|
|
125
|
-
return conversation;
|
|
126
|
-
}
|
|
127
|
-
catch (cause) {
|
|
128
|
-
this.#report(cause);
|
|
129
|
-
throw cause;
|
|
130
|
-
}
|
|
131
|
-
};
|
|
132
|
-
#setMetadata(id, metadata) {
|
|
133
|
-
this.#set({ metadata: { ...this.#state.metadata, [String(id)]: metadata } });
|
|
134
|
-
}
|
|
135
|
-
refreshMetadata = async (id = this.#state.selectedId) => {
|
|
136
|
-
if (id === undefined || !this.client.getMetadata)
|
|
137
|
-
return;
|
|
138
|
-
this.#setMetadata(id, await this.client.getMetadata(id));
|
|
139
|
-
};
|
|
140
|
-
updateMetadata = async (id, patch) => {
|
|
141
|
-
if (!this.client.updateMetadata)
|
|
142
|
-
throw new Error("This Pi host does not expose conversation metadata");
|
|
143
|
-
this.#setMetadata(id, await this.client.updateMetadata(id, patch));
|
|
144
|
-
};
|
|
145
|
-
renameConversation = (id, title) => this.updateMetadata(id, { title });
|
|
146
|
-
archiveConversation = (id) => this.updateMetadata(id, { archived: true });
|
|
147
|
-
unarchiveConversation = (id) => this.updateMetadata(id, { archived: false });
|
|
148
|
-
setFeedback = async (entryId, rating) => {
|
|
149
|
-
const id = this.#state.selectedId;
|
|
150
|
-
if (id === undefined)
|
|
151
|
-
throw new Error("Select a conversation before leaving feedback");
|
|
152
|
-
if (!this.client.setFeedback)
|
|
153
|
-
throw new Error("This Pi host does not expose feedback");
|
|
154
|
-
this.#setMetadata(id, await this.client.setFeedback(id, entryId, rating));
|
|
155
|
-
};
|
|
156
|
-
submitFeedback = (messageId, rating) => {
|
|
157
|
-
void this.setFeedback(entryIdFromMessageId(messageId), rating).catch((cause) => this.#report(cause));
|
|
158
|
-
};
|
|
159
|
-
submit = async (submission) => {
|
|
160
|
-
const id = this.#state.selectedId ?? (await this.createConversation()).id;
|
|
161
|
-
return this.client.submit(id, submission);
|
|
162
|
-
};
|
|
163
|
-
continue = () => this.submit({ type: "continue" });
|
|
164
|
-
steer = (content) => this.submit({ type: "input", content, whenBusy: "steer" });
|
|
165
|
-
abortSubmission = async (id) => {
|
|
166
|
-
if (!this.client.abortSubmission)
|
|
167
|
-
throw new Error("This Pi host does not expose submission withdrawal");
|
|
168
|
-
return this.client.abortSubmission(id);
|
|
169
|
-
};
|
|
170
|
-
/** Retrying an edit creates a native fork and records an immutable context replacement there. */
|
|
171
|
-
edit = async (message) => {
|
|
172
|
-
if (!message.sourceId)
|
|
173
|
-
throw new Error("An edit must identify its original message");
|
|
174
|
-
const target = entryIdFromMessageId(message.sourceId);
|
|
175
|
-
const content = toPiUserInput(message);
|
|
176
|
-
await this.forkAt(target);
|
|
177
|
-
await this.submit({ type: "write", entry: { kind: "assistant-ui.context-edit", edits: [{ target, action: "replace", messages: [{ role: "user", content, timestamp: Date.now() }] }] } });
|
|
178
|
-
await this.continue();
|
|
179
|
-
};
|
|
180
|
-
/** Keep the answer in original history; the fork omits it from its next model context. */
|
|
181
|
-
regenerate = async (parentId) => {
|
|
182
|
-
const index = parentId === null ? -1 : this.#state.messages.findIndex((message) => message.id === parentId);
|
|
183
|
-
if (parentId !== null && index === -1)
|
|
184
|
-
throw new Error(`Parent message ${parentId} is not loaded`);
|
|
185
|
-
const answer = this.#state.messages[index + 1];
|
|
186
|
-
if (!answer?.id || answer.role !== "assistant")
|
|
187
|
-
throw new Error("No committed assistant response follows this message");
|
|
188
|
-
const target = entryIdFromMessageId(answer.id);
|
|
189
|
-
await this.forkAt(target);
|
|
190
|
-
await this.submit({ type: "write", entry: { kind: "assistant-ui.context-edit", edits: [{ target, action: "omit" }] } });
|
|
191
|
-
await this.continue();
|
|
192
|
-
};
|
|
193
|
-
cancel = async () => {
|
|
194
|
-
const id = this.#state.selectedId;
|
|
195
|
-
if (id === undefined)
|
|
196
|
-
return;
|
|
197
|
-
if (!this.client.abort)
|
|
198
|
-
throw new Error("This Pi host does not expose conversation cancellation");
|
|
199
|
-
await this.client.abort(id);
|
|
200
|
-
};
|
|
201
|
-
configure = async (change) => {
|
|
202
|
-
const id = this.#state.selectedId;
|
|
203
|
-
if (id === undefined)
|
|
204
|
-
throw new Error("Select a conversation before configuring it");
|
|
205
|
-
if (!this.client.configure)
|
|
206
|
-
throw new Error("This Pi host does not expose configuration");
|
|
207
|
-
await this.client.configure(id, change);
|
|
208
|
-
};
|
|
209
|
-
reset = async (handoff) => {
|
|
210
|
-
const id = this.#state.selectedId;
|
|
211
|
-
if (id === undefined)
|
|
212
|
-
return;
|
|
213
|
-
if (!this.client.reset)
|
|
214
|
-
throw new Error("This Pi host does not expose reset");
|
|
215
|
-
await this.client.reset(id, handoff);
|
|
216
|
-
};
|
|
217
|
-
compact = async (instructions) => {
|
|
218
|
-
const id = this.#state.selectedId;
|
|
219
|
-
if (id === undefined)
|
|
220
|
-
throw new Error("Select a conversation before compacting it");
|
|
221
|
-
if (!this.client.compact)
|
|
222
|
-
throw new Error("This Pi host does not expose compaction");
|
|
223
|
-
return this.client.compact(id, instructions);
|
|
224
|
-
};
|
|
225
|
-
forkAt = async (at) => {
|
|
226
|
-
const id = this.#state.selectedId;
|
|
227
|
-
if (id === undefined)
|
|
228
|
-
throw new Error("Select a conversation before forking it");
|
|
229
|
-
if (!this.client.fork)
|
|
230
|
-
throw new Error("This Pi host does not expose forks");
|
|
231
|
-
const conversation = await this.client.fork(id, at);
|
|
232
|
-
this.#set({ conversations: [conversation, ...this.#state.conversations] });
|
|
233
|
-
this.selectConversation(conversation.id);
|
|
234
|
-
return conversation;
|
|
235
|
-
};
|
|
236
|
-
loadEarlier = async () => {
|
|
237
|
-
const id = this.#state.selectedId;
|
|
238
|
-
if (id === undefined)
|
|
239
|
-
return;
|
|
240
|
-
const view = await this.#transcript(id).loadEarlier(withAbortSignal(this.#selection.signal, BACKGROUND_CONTEXT));
|
|
241
|
-
this.#show(id, view);
|
|
242
|
-
};
|
|
243
|
-
#fillGaps(id) {
|
|
244
|
-
const previous = this.#filling.get(id);
|
|
245
|
-
if (previous)
|
|
246
|
-
return previous;
|
|
247
|
-
const signal = this.#selection.signal;
|
|
248
|
-
const run = async () => {
|
|
249
|
-
while (!signal.aborted) {
|
|
250
|
-
const gap = this.#views.get(id)?.items.find((item) => item.kind === "gap");
|
|
251
|
-
if (!gap || gap.kind !== "gap")
|
|
252
|
-
return;
|
|
253
|
-
const view = await this.#transcript(id).fillGap(gap, withAbortSignal(signal, BACKGROUND_CONTEXT));
|
|
254
|
-
this.#show(id, view);
|
|
255
|
-
}
|
|
256
|
-
};
|
|
257
|
-
const pending = run().finally(() => this.#filling.delete(id));
|
|
258
|
-
this.#filling.set(id, pending);
|
|
259
|
-
return pending;
|
|
260
|
-
}
|
|
261
|
-
}
|
package/dist/use-pi-runtime.d.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { type AttachmentAdapter, type DictationAdapter, type FeedbackAdapter, type SpeechSynthesisAdapter } from "@assistant-ui/react";
|
|
2
|
-
import type { PiClient } from "./client.js";
|
|
3
|
-
import { PiRuntimeStore, type PiRuntimeStoreOptions } from "./store.js";
|
|
4
|
-
export interface UsePiRuntimeOptions extends PiRuntimeStoreOptions {
|
|
5
|
-
client: PiClient;
|
|
6
|
-
whenBusy?: "followUp" | "steer" | "reject";
|
|
7
|
-
attachments?: AttachmentAdapter;
|
|
8
|
-
speech?: SpeechSynthesisAdapter;
|
|
9
|
-
dictation?: DictationAdapter;
|
|
10
|
-
feedback?: FeedbackAdapter;
|
|
11
|
-
}
|
|
12
|
-
export declare function usePiRuntime({ client, initialConversationId, pageSize, whenBusy, attachments, speech, dictation, feedback }: UsePiRuntimeOptions): {
|
|
13
|
-
runtime: import("@assistant-ui/react").AssistantRuntime;
|
|
14
|
-
state: import("./store.js").PiRuntimeState;
|
|
15
|
-
actions: PiRuntimeStore;
|
|
16
|
-
};
|
|
17
|
-
//# sourceMappingURL=use-pi-runtime.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-pi-runtime.d.ts","sourceRoot":"","sources":["../src/use-pi-runtime.ts"],"names":[],"mappings":"AACA,OAAO,EAA2B,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,KAAK,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAEhK,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAIxE,MAAM,WAAW,mBAAoB,SAAQ,qBAAqB;IAChE,MAAM,EAAE,QAAQ,CAAC;IACjB,QAAQ,CAAC,EAAE,UAAU,GAAG,OAAO,GAAG,QAAQ,CAAC;IAC3C,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,MAAM,CAAC,EAAE,sBAAsB,CAAC;IAChC,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B;AAED,wBAAgB,YAAY,CAAC,EAAE,MAAM,EAAE,qBAAqB,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,mBAAmB;;;;EA2ChJ"}
|
package/dist/use-pi-runtime.js
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { useEffect, useMemo, useSyncExternalStore } from "react";
|
|
2
|
-
import { useExternalStoreRuntime } from "@assistant-ui/react";
|
|
3
|
-
import { PiRuntimeStore } from "./store.js";
|
|
4
|
-
import { toPiUserInput } from "./projection.js";
|
|
5
|
-
import { EMPTY_CONVERSATION_METADATA } from "./metadata.js";
|
|
6
|
-
export function usePiRuntime({ client, initialConversationId, pageSize, whenBusy, attachments, speech, dictation, feedback }) {
|
|
7
|
-
const store = useMemo(() => new PiRuntimeStore(client, { initialConversationId, pageSize }), [client, pageSize]);
|
|
8
|
-
useEffect(() => { store.start(); return store.stop; }, [store]);
|
|
9
|
-
const state = useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);
|
|
10
|
-
const metadata = state.metadata[String(state.selectedId)] ?? EMPTY_CONVERSATION_METADATA;
|
|
11
|
-
const nativeFeedback = useMemo(() => client.setFeedback ? {
|
|
12
|
-
submit: ({ message, type }) => store.submitFeedback(message.id, type),
|
|
13
|
-
} : undefined, [client, store]);
|
|
14
|
-
const threads = state.conversations.map((conversation) => {
|
|
15
|
-
const details = state.metadata[String(conversation.id)] ?? EMPTY_CONVERSATION_METADATA;
|
|
16
|
-
const item = { id: String(conversation.id), title: details.title ?? `Conversation ${conversation.id}` };
|
|
17
|
-
return details.archived ? { ...item, status: "archived" } : { ...item, status: "regular" };
|
|
18
|
-
});
|
|
19
|
-
const runtime = useExternalStoreRuntime({
|
|
20
|
-
messages: state.messages,
|
|
21
|
-
convertMessage: (message) => message,
|
|
22
|
-
isRunning: state.isRunning,
|
|
23
|
-
isLoading: state.isLoading,
|
|
24
|
-
hasEarlier: state.hasEarlier,
|
|
25
|
-
onLoadEarlier: store.loadEarlier,
|
|
26
|
-
onNew: async (message) => { await store.submit({ type: "input", content: toPiUserInput(message), whenBusy }); },
|
|
27
|
-
onCancel: client.abort ? store.cancel : undefined,
|
|
28
|
-
onEdit: client.fork ? store.edit : undefined,
|
|
29
|
-
onReload: client.fork ? store.regenerate : undefined,
|
|
30
|
-
suggestions: metadata.suggestions.map((prompt) => ({ prompt })),
|
|
31
|
-
adapters: {
|
|
32
|
-
attachments,
|
|
33
|
-
speech,
|
|
34
|
-
dictation,
|
|
35
|
-
feedback: feedback ?? nativeFeedback,
|
|
36
|
-
threadList: {
|
|
37
|
-
threadId: state.selectedId === undefined ? undefined : String(state.selectedId),
|
|
38
|
-
threads: threads.filter((thread) => thread.status === "regular"),
|
|
39
|
-
archivedThreads: threads.filter((thread) => thread.status === "archived"),
|
|
40
|
-
onSwitchToThread: (id) => store.selectConversation(Number(id)),
|
|
41
|
-
onSwitchToNewThread: async () => { await store.createConversation(); },
|
|
42
|
-
onRename: client.updateMetadata ? (id, title) => store.renameConversation(Number(id), title) : undefined,
|
|
43
|
-
onArchive: client.updateMetadata ? (id) => store.archiveConversation(Number(id)) : undefined,
|
|
44
|
-
onUnarchive: client.updateMetadata ? (id) => store.unarchiveConversation(Number(id)) : undefined,
|
|
45
|
-
},
|
|
46
|
-
},
|
|
47
|
-
});
|
|
48
|
-
return { runtime, state, actions: store };
|
|
49
|
-
}
|