@portablecore/chat-runtime 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/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/sse-client.d.ts +25 -0
- package/dist/sse-client.d.ts.map +1 -0
- package/dist/sse-client.js +177 -0
- package/dist/sse-client.js.map +1 -0
- package/dist/use-chat-runtime.d.ts +67 -0
- package/dist/use-chat-runtime.d.ts.map +1 -0
- package/dist/use-chat-runtime.js +274 -0
- package/dist/use-chat-runtime.js.map +1 -0
- package/dist/use-skill-indicators.d.ts +51 -0
- package/dist/use-skill-indicators.d.ts.map +1 -0
- package/dist/use-skill-indicators.js +90 -0
- package/dist/use-skill-indicators.js.map +1 -0
- package/dist/use-streaming-message.d.ts +29 -0
- package/dist/use-streaming-message.d.ts.map +1 -0
- package/dist/use-streaming-message.js +73 -0
- package/dist/use-streaming-message.js.map +1 -0
- package/package.json +42 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @portablecore/chat-runtime
|
|
3
|
+
*
|
|
4
|
+
* Headless chat runtime for Portable platforms.
|
|
5
|
+
* SSE streaming, message state management, and lifecycle hooks.
|
|
6
|
+
*
|
|
7
|
+
* No UI components — compose with @portablecore/chat for the full
|
|
8
|
+
* unified chat experience, or use these primitives directly for
|
|
9
|
+
* custom surfaces.
|
|
10
|
+
*/
|
|
11
|
+
export { useChatRuntime } from "./use-chat-runtime.js";
|
|
12
|
+
export type { UseChatRuntimeOptions, ChatRuntime, PersistMessageResult, } from "./use-chat-runtime.js";
|
|
13
|
+
export { useStreamingMessage } from "./use-streaming-message.js";
|
|
14
|
+
export type { UseStreamingMessageReturn } from "./use-streaming-message.js";
|
|
15
|
+
export { useSkillIndicators } from "./use-skill-indicators.js";
|
|
16
|
+
export type { UseSkillIndicatorsReturn, SkillThinkingStage, ActiveSkillState, SkillConfig, SkillResultEntry, } from "./use-skill-indicators.js";
|
|
17
|
+
export { parseSseStream, fetchWithRetry } from "./sse-client.js";
|
|
18
|
+
export type { SseEvent, SseThinkingEvent, SseSkillStartEvent, SseSkillResultEvent, SseTextEvent, SseReplaceContentEvent, SseDoneEvent, SseErrorEvent, SseFirstResponseEvent, LiteMessage, } from "@portablecore/types/chat";
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,YAAY,EACV,qBAAqB,EACrB,WAAW,EACX,oBAAoB,GACrB,MAAM,uBAAuB,CAAA;AAG9B,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AAChE,YAAY,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAA;AAG3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAC9D,YAAY,EACV,wBAAwB,EACxB,kBAAkB,EAClB,gBAAgB,EAChB,WAAW,EACX,gBAAgB,GACjB,MAAM,2BAA2B,CAAA;AAGlC,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAGhE,YAAY,EACV,QAAQ,EACR,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,YAAY,EACZ,sBAAsB,EACtB,YAAY,EACZ,aAAa,EACb,qBAAqB,EACrB,WAAW,GACZ,MAAM,0BAA0B,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @portablecore/chat-runtime
|
|
4
|
+
*
|
|
5
|
+
* Headless chat runtime for Portable platforms.
|
|
6
|
+
* SSE streaming, message state management, and lifecycle hooks.
|
|
7
|
+
*
|
|
8
|
+
* No UI components — compose with @portablecore/chat for the full
|
|
9
|
+
* unified chat experience, or use these primitives directly for
|
|
10
|
+
* custom surfaces.
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.fetchWithRetry = exports.parseSseStream = exports.useSkillIndicators = exports.useStreamingMessage = exports.useChatRuntime = void 0;
|
|
14
|
+
// Headless chat hook
|
|
15
|
+
var use_chat_runtime_js_1 = require("./use-chat-runtime.js");
|
|
16
|
+
Object.defineProperty(exports, "useChatRuntime", { enumerable: true, get: function () { return use_chat_runtime_js_1.useChatRuntime; } });
|
|
17
|
+
// RAF-batched streaming message accumulator
|
|
18
|
+
var use_streaming_message_js_1 = require("./use-streaming-message.js");
|
|
19
|
+
Object.defineProperty(exports, "useStreamingMessage", { enumerable: true, get: function () { return use_streaming_message_js_1.useStreamingMessage; } });
|
|
20
|
+
// Skill and thinking indicator state
|
|
21
|
+
var use_skill_indicators_js_1 = require("./use-skill-indicators.js");
|
|
22
|
+
Object.defineProperty(exports, "useSkillIndicators", { enumerable: true, get: function () { return use_skill_indicators_js_1.useSkillIndicators; } });
|
|
23
|
+
// SSE client
|
|
24
|
+
var sse_client_js_1 = require("./sse-client.js");
|
|
25
|
+
Object.defineProperty(exports, "parseSseStream", { enumerable: true, get: function () { return sse_client_js_1.parseSseStream; } });
|
|
26
|
+
Object.defineProperty(exports, "fetchWithRetry", { enumerable: true, get: function () { return sse_client_js_1.fetchWithRetry; } });
|
|
27
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;AAEH,qBAAqB;AACrB,6DAAsD;AAA7C,qHAAA,cAAc,OAAA;AAOvB,4CAA4C;AAC5C,uEAAgE;AAAvD,+HAAA,mBAAmB,OAAA;AAG5B,qCAAqC;AACrC,qEAA8D;AAArD,6HAAA,kBAAkB,OAAA;AAS3B,aAAa;AACb,iDAAgE;AAAvD,+GAAA,cAAc,OAAA;AAAE,+GAAA,cAAc,OAAA"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSE Client — Stream parsing and fetch utilities
|
|
3
|
+
*
|
|
4
|
+
* Shared utilities for connecting to /api/chat/stream endpoints
|
|
5
|
+
* and parsing Server-Sent Events into typed SseEvent objects.
|
|
6
|
+
*
|
|
7
|
+
* Both full chat and lite chat surfaces consume this same parser.
|
|
8
|
+
* Each surface handles only the events it cares about.
|
|
9
|
+
*/
|
|
10
|
+
import type { SseEvent } from "@portablecore/types/chat";
|
|
11
|
+
/**
|
|
12
|
+
* Async generator that reads an SSE response body and yields typed SseEvent objects.
|
|
13
|
+
*
|
|
14
|
+
* Uses double-newline as event boundaries. Handles partial chunk buffering.
|
|
15
|
+
*
|
|
16
|
+
* Abort: pass an AbortSignal to the fetch call. When aborted, reader.read()
|
|
17
|
+
* rejects with AbortError, propagating to the consumer's catch block.
|
|
18
|
+
*/
|
|
19
|
+
export declare function parseSseStream(response: Response): AsyncGenerator<SseEvent>;
|
|
20
|
+
/**
|
|
21
|
+
* Fetch wrapper with single retry for transient network failures.
|
|
22
|
+
* Does NOT retry on AbortError (user-initiated cancellation).
|
|
23
|
+
*/
|
|
24
|
+
export declare function fetchWithRetry(url: string, options: RequestInit, maxRetries?: number): Promise<Response>;
|
|
25
|
+
//# sourceMappingURL=sse-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse-client.d.ts","sourceRoot":"","sources":["../src/sse-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAyFxD;;;;;;;GAOG;AACH,wBAAuB,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,cAAc,CAAC,QAAQ,CAAC,CAsDlF;AAMD;;;GAGG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,WAAW,EACpB,UAAU,SAAI,GACb,OAAO,CAAC,QAAQ,CAAC,CAoBnB"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* SSE Client — Stream parsing and fetch utilities
|
|
4
|
+
*
|
|
5
|
+
* Shared utilities for connecting to /api/chat/stream endpoints
|
|
6
|
+
* and parsing Server-Sent Events into typed SseEvent objects.
|
|
7
|
+
*
|
|
8
|
+
* Both full chat and lite chat surfaces consume this same parser.
|
|
9
|
+
* Each surface handles only the events it cares about.
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.parseSseStream = parseSseStream;
|
|
13
|
+
exports.fetchWithRetry = fetchWithRetry;
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// SSE Stream Parser
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
/**
|
|
18
|
+
* Parse a single SSE data line into a typed SseEvent.
|
|
19
|
+
* Returns null for non-data lines or unparseable content.
|
|
20
|
+
*/
|
|
21
|
+
function parseSseLine(line) {
|
|
22
|
+
if (!line.startsWith("data: "))
|
|
23
|
+
return null;
|
|
24
|
+
try {
|
|
25
|
+
const data = JSON.parse(line.slice(6));
|
|
26
|
+
if (data.thinking) {
|
|
27
|
+
return {
|
|
28
|
+
type: "thinking",
|
|
29
|
+
stage: data.thinking.stage,
|
|
30
|
+
detail: data.thinking.detail,
|
|
31
|
+
showIcon: data.thinking.showIcon,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
if (data.skill_start) {
|
|
35
|
+
return {
|
|
36
|
+
type: "skill_start",
|
|
37
|
+
skillSlug: data.skill_start.skillSlug,
|
|
38
|
+
skillName: data.skill_start.skillName,
|
|
39
|
+
contextualMessage: data.skill_start.contextualMessage,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
if (data.skill_result) {
|
|
43
|
+
return {
|
|
44
|
+
type: "skill_result",
|
|
45
|
+
skillSlug: data.skill_result.skillSlug,
|
|
46
|
+
skillName: data.skill_result.skillName,
|
|
47
|
+
success: data.skill_result.success,
|
|
48
|
+
error: data.skill_result.error,
|
|
49
|
+
duration_ms: data.skill_result.duration_ms,
|
|
50
|
+
citations: data.skill_result.citations,
|
|
51
|
+
sources: data.skill_result.sources,
|
|
52
|
+
locations: data.skill_result.locations,
|
|
53
|
+
booking_links: data.skill_result.booking_links,
|
|
54
|
+
documents: data.skill_result.documents,
|
|
55
|
+
notion_results: data.skill_result.notion_results,
|
|
56
|
+
craft_results: data.skill_result.craft_results,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
if (data.first_response) {
|
|
60
|
+
return {
|
|
61
|
+
type: "first_response",
|
|
62
|
+
messageId: data.first_response.messageId,
|
|
63
|
+
content: data.first_response.content,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
if (data.replace_content !== undefined) {
|
|
67
|
+
return { type: "replace_content" };
|
|
68
|
+
}
|
|
69
|
+
if (data.text) {
|
|
70
|
+
return { type: "text", text: data.text };
|
|
71
|
+
}
|
|
72
|
+
if (data.done) {
|
|
73
|
+
return {
|
|
74
|
+
type: "done",
|
|
75
|
+
messageId: data.messageId,
|
|
76
|
+
provider: data.provider,
|
|
77
|
+
model: data.model,
|
|
78
|
+
skill_usage: data.skill_usage,
|
|
79
|
+
expert_suggestion: data.expert_suggestion,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
if (data.error) {
|
|
83
|
+
return { type: "error", error: data.error };
|
|
84
|
+
}
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Async generator that reads an SSE response body and yields typed SseEvent objects.
|
|
93
|
+
*
|
|
94
|
+
* Uses double-newline as event boundaries. Handles partial chunk buffering.
|
|
95
|
+
*
|
|
96
|
+
* Abort: pass an AbortSignal to the fetch call. When aborted, reader.read()
|
|
97
|
+
* rejects with AbortError, propagating to the consumer's catch block.
|
|
98
|
+
*/
|
|
99
|
+
async function* parseSseStream(response) {
|
|
100
|
+
const reader = response.body?.getReader();
|
|
101
|
+
if (!reader) {
|
|
102
|
+
throw new Error("No response body");
|
|
103
|
+
}
|
|
104
|
+
const decoder = new TextDecoder();
|
|
105
|
+
let buffer = "";
|
|
106
|
+
try {
|
|
107
|
+
while (true) {
|
|
108
|
+
const { done, value } = await reader.read();
|
|
109
|
+
if (done)
|
|
110
|
+
break;
|
|
111
|
+
buffer += decoder.decode(value, { stream: true });
|
|
112
|
+
const events = buffer.split("\n\n");
|
|
113
|
+
buffer = events.pop() || "";
|
|
114
|
+
for (const rawEvent of events) {
|
|
115
|
+
const parsed = parseSseLine(rawEvent.trim());
|
|
116
|
+
if (parsed) {
|
|
117
|
+
yield parsed;
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
for (const line of rawEvent.split("\n")) {
|
|
121
|
+
const lineParsed = parseSseLine(line.trim());
|
|
122
|
+
if (lineParsed) {
|
|
123
|
+
yield lineParsed;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (buffer.trim()) {
|
|
130
|
+
buffer += decoder.decode();
|
|
131
|
+
const remaining = buffer.split("\n\n");
|
|
132
|
+
for (const rawEvent of remaining) {
|
|
133
|
+
const parsed = parseSseLine(rawEvent.trim());
|
|
134
|
+
if (parsed) {
|
|
135
|
+
yield parsed;
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
for (const line of rawEvent.split("\n")) {
|
|
139
|
+
const lineParsed = parseSseLine(line.trim());
|
|
140
|
+
if (lineParsed) {
|
|
141
|
+
yield lineParsed;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
finally {
|
|
149
|
+
reader.releaseLock();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
// ---------------------------------------------------------------------------
|
|
153
|
+
// Fetch with Retry
|
|
154
|
+
// ---------------------------------------------------------------------------
|
|
155
|
+
/**
|
|
156
|
+
* Fetch wrapper with single retry for transient network failures.
|
|
157
|
+
* Does NOT retry on AbortError (user-initiated cancellation).
|
|
158
|
+
*/
|
|
159
|
+
async function fetchWithRetry(url, options, maxRetries = 1) {
|
|
160
|
+
let lastError = null;
|
|
161
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
162
|
+
try {
|
|
163
|
+
return await fetch(url, options);
|
|
164
|
+
}
|
|
165
|
+
catch (err) {
|
|
166
|
+
lastError = err instanceof Error ? err : new Error(String(err));
|
|
167
|
+
if (lastError.name === "AbortError") {
|
|
168
|
+
throw lastError;
|
|
169
|
+
}
|
|
170
|
+
if (attempt < maxRetries) {
|
|
171
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
throw lastError || new Error("Fetch failed after retries");
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=sse-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse-client.js","sourceRoot":"","sources":["../src/sse-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { LiteMessage, SseEvent } from "@portablecore/types/chat";
|
|
2
|
+
/** Result of persisting a user message. */
|
|
3
|
+
export interface PersistMessageResult {
|
|
4
|
+
/** Persisted message ID, or null on failure */
|
|
5
|
+
id: string | null;
|
|
6
|
+
/** Sender's user ID, or null if unavailable */
|
|
7
|
+
userId: string | null;
|
|
8
|
+
}
|
|
9
|
+
export interface UseChatRuntimeOptions {
|
|
10
|
+
/** Current chat ID. Can be null initially (lazy creation). */
|
|
11
|
+
chatId: string | null;
|
|
12
|
+
/** Expert to stream responses from. */
|
|
13
|
+
expertId: string;
|
|
14
|
+
/**
|
|
15
|
+
* Persist a user message before streaming. Platform-specific.
|
|
16
|
+
* Expert: saves to Supabase messages table.
|
|
17
|
+
* Team: saves to Team's local messages table.
|
|
18
|
+
* If omitted, no local persistence (stream endpoint handles it).
|
|
19
|
+
*/
|
|
20
|
+
persistMessage?: (chatId: string, content: string) => Promise<PersistMessageResult>;
|
|
21
|
+
/** Display name of the sender (for multi-human chat context). */
|
|
22
|
+
senderName?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Pre-warmed context from useChatWarmup. Passed through to the stream endpoint.
|
|
25
|
+
*/
|
|
26
|
+
warmContext?: any;
|
|
27
|
+
/**
|
|
28
|
+
* Streaming API endpoint. Defaults to "/api/chat/stream".
|
|
29
|
+
*/
|
|
30
|
+
streamEndpoint?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Extra parameters merged into the stream POST body.
|
|
33
|
+
* Use for surface-specific fields (provider overrides, voice mode, etc.).
|
|
34
|
+
*/
|
|
35
|
+
streamBody?: Record<string, unknown>;
|
|
36
|
+
/**
|
|
37
|
+
* Callback for SSE events. Called for EVERY event so the surface
|
|
38
|
+
* has full visibility (thinking indicators, skill results, etc.).
|
|
39
|
+
*/
|
|
40
|
+
onEvent?: (event: SseEvent) => void;
|
|
41
|
+
}
|
|
42
|
+
export interface ChatRuntime {
|
|
43
|
+
/** Current messages in the conversation. */
|
|
44
|
+
messages: LiteMessage[];
|
|
45
|
+
/** Whether an expert response is currently streaming. */
|
|
46
|
+
streaming: boolean;
|
|
47
|
+
/** Whether a user message is being saved (before streaming starts). */
|
|
48
|
+
sending: boolean;
|
|
49
|
+
/** First Responder → full response transition. */
|
|
50
|
+
frTransitioning: boolean;
|
|
51
|
+
/** Expert is executing a skill mid-stream. */
|
|
52
|
+
skillTransitioning: boolean;
|
|
53
|
+
/** The resolved chat ID. */
|
|
54
|
+
chatId: string | null;
|
|
55
|
+
/**
|
|
56
|
+
* Send a message: persist the user message, then stream the expert response.
|
|
57
|
+
* @param content - The message text.
|
|
58
|
+
* @param chatIdOverride - Optional chat ID override for first-send case.
|
|
59
|
+
*/
|
|
60
|
+
send: (content: string, chatIdOverride?: string) => Promise<void>;
|
|
61
|
+
/** Abort the in-flight stream. Preserves any partial response. */
|
|
62
|
+
abort: () => void;
|
|
63
|
+
/** Clear all messages from the runtime state. */
|
|
64
|
+
clear: () => void;
|
|
65
|
+
}
|
|
66
|
+
export declare function useChatRuntime(options: UseChatRuntimeOptions): ChatRuntime;
|
|
67
|
+
//# sourceMappingURL=use-chat-runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-chat-runtime.d.ts","sourceRoot":"","sources":["../src/use-chat-runtime.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAMrE,2CAA2C;AAC3C,MAAM,WAAW,oBAAoB;IACnC,+CAA+C;IAC/C,EAAE,EAAE,MAAM,GAAG,IAAI,CAAA;IACjB,+CAA+C;IAC/C,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CACtB;AAED,MAAM,WAAW,qBAAqB;IACpC,8DAA8D;IAC9D,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,uCAAuC;IACvC,QAAQ,EAAE,MAAM,CAAA;IAChB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,oBAAoB,CAAC,CAAA;IACnF,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;OAEG;IAEH,WAAW,CAAC,EAAE,GAAG,CAAA;IACjB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACpC;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAA;CACpC;AAED,MAAM,WAAW,WAAW;IAC1B,4CAA4C;IAC5C,QAAQ,EAAE,WAAW,EAAE,CAAA;IACvB,yDAAyD;IACzD,SAAS,EAAE,OAAO,CAAA;IAClB,uEAAuE;IACvE,OAAO,EAAE,OAAO,CAAA;IAChB,kDAAkD;IAClD,eAAe,EAAE,OAAO,CAAA;IACxB,8CAA8C;IAC9C,kBAAkB,EAAE,OAAO,CAAA;IAC3B,4BAA4B;IAC5B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB;;;;OAIG;IACH,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACjE,kEAAkE;IAClE,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,iDAAiD;IACjD,KAAK,EAAE,MAAM,IAAI,CAAA;CAClB;AAMD,wBAAgB,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,WAAW,CAkU1E"}
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.useChatRuntime = useChatRuntime;
|
|
5
|
+
/**
|
|
6
|
+
* useChatRuntime — Headless chat lifecycle hook
|
|
7
|
+
*
|
|
8
|
+
* Manages the chat lifecycle without any UI: message state, streaming,
|
|
9
|
+
* persistence, and abort. Surfaces compose this hook with their own
|
|
10
|
+
* UI components and surface-specific features.
|
|
11
|
+
*
|
|
12
|
+
* Platform-specific concerns (message persistence, auth) are handled
|
|
13
|
+
* via callbacks rather than direct Supabase coupling.
|
|
14
|
+
*
|
|
15
|
+
* Usage:
|
|
16
|
+
* const chat = useChatRuntime({ chatId, expertId, ... })
|
|
17
|
+
* chat.messages // LiteMessage[]
|
|
18
|
+
* chat.streaming // boolean
|
|
19
|
+
* chat.send(content) // Save user message + trigger expert stream
|
|
20
|
+
* chat.abort() // Cancel in-flight stream
|
|
21
|
+
*/
|
|
22
|
+
const react_1 = require("react");
|
|
23
|
+
const sse_client_js_1 = require("./sse-client.js");
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
// Hook
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
function useChatRuntime(options) {
|
|
28
|
+
const { chatId: externalChatId, expertId, persistMessage, senderName, warmContext, streamEndpoint = "/api/chat/stream", streamBody, onEvent, } = options;
|
|
29
|
+
// ---- State ----
|
|
30
|
+
const [messages, setMessages] = (0, react_1.useState)([]);
|
|
31
|
+
const [streaming, setStreaming] = (0, react_1.useState)(false);
|
|
32
|
+
const [sending, setSending] = (0, react_1.useState)(false);
|
|
33
|
+
const [frTransitioning, setFrTransitioning] = (0, react_1.useState)(false);
|
|
34
|
+
const frTransitioningRef = (0, react_1.useRef)(false);
|
|
35
|
+
const [skillTransitioning, setSkillTransitioning] = (0, react_1.useState)(false);
|
|
36
|
+
const skillTransitioningRef = (0, react_1.useRef)(false);
|
|
37
|
+
const [chatId, setChatId] = (0, react_1.useState)(externalChatId);
|
|
38
|
+
(0, react_1.useEffect)(() => {
|
|
39
|
+
if (externalChatId) {
|
|
40
|
+
setChatId(externalChatId);
|
|
41
|
+
}
|
|
42
|
+
}, [externalChatId]);
|
|
43
|
+
// ---- Refs ----
|
|
44
|
+
const abortRef = (0, react_1.useRef)(null);
|
|
45
|
+
const pendingText = (0, react_1.useRef)("");
|
|
46
|
+
const rafId = (0, react_1.useRef)(null);
|
|
47
|
+
const streamTempId = (0, react_1.useRef)(null);
|
|
48
|
+
const onEventRef = (0, react_1.useRef)(onEvent);
|
|
49
|
+
(0, react_1.useEffect)(() => {
|
|
50
|
+
onEventRef.current = onEvent;
|
|
51
|
+
}, [onEvent]);
|
|
52
|
+
// ---- RAF Batching ----
|
|
53
|
+
const flushContent = (0, react_1.useCallback)(() => {
|
|
54
|
+
rafId.current = null;
|
|
55
|
+
const text = pendingText.current;
|
|
56
|
+
const tempId = streamTempId.current;
|
|
57
|
+
if (!text || !tempId)
|
|
58
|
+
return;
|
|
59
|
+
pendingText.current = "";
|
|
60
|
+
setMessages((prev) => prev.map((m) => (m.id === tempId ? { ...m, content: m.content + text } : m)));
|
|
61
|
+
}, []);
|
|
62
|
+
const scheduleFlush = (0, react_1.useCallback)((text) => {
|
|
63
|
+
pendingText.current += text;
|
|
64
|
+
if (rafId.current === null) {
|
|
65
|
+
rafId.current = requestAnimationFrame(flushContent);
|
|
66
|
+
}
|
|
67
|
+
}, [flushContent]);
|
|
68
|
+
const forceFlush = (0, react_1.useCallback)(() => {
|
|
69
|
+
if (rafId.current !== null) {
|
|
70
|
+
cancelAnimationFrame(rafId.current);
|
|
71
|
+
rafId.current = null;
|
|
72
|
+
}
|
|
73
|
+
const text = pendingText.current;
|
|
74
|
+
const tempId = streamTempId.current;
|
|
75
|
+
if (text && tempId) {
|
|
76
|
+
pendingText.current = "";
|
|
77
|
+
setMessages((prev) => prev.map((m) => (m.id === tempId ? { ...m, content: m.content + text } : m)));
|
|
78
|
+
}
|
|
79
|
+
}, []);
|
|
80
|
+
(0, react_1.useEffect)(() => {
|
|
81
|
+
return () => {
|
|
82
|
+
if (rafId.current !== null) {
|
|
83
|
+
cancelAnimationFrame(rafId.current);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}, []);
|
|
87
|
+
// ---- Stream ----
|
|
88
|
+
const streamResponse = (0, react_1.useCallback)(async (activeChatId, userMessage, userMessageId, senderUserId) => {
|
|
89
|
+
setStreaming(true);
|
|
90
|
+
const tempId = `stream-${Date.now()}`;
|
|
91
|
+
streamTempId.current = tempId;
|
|
92
|
+
pendingText.current = "";
|
|
93
|
+
setMessages((prev) => [
|
|
94
|
+
...prev,
|
|
95
|
+
{
|
|
96
|
+
id: tempId,
|
|
97
|
+
role: "assistant",
|
|
98
|
+
content: "",
|
|
99
|
+
streaming: true,
|
|
100
|
+
createdAt: new Date().toISOString(),
|
|
101
|
+
},
|
|
102
|
+
]);
|
|
103
|
+
const controller = new AbortController();
|
|
104
|
+
abortRef.current = controller;
|
|
105
|
+
try {
|
|
106
|
+
const response = await fetch(streamEndpoint, {
|
|
107
|
+
method: "POST",
|
|
108
|
+
headers: { "Content-Type": "application/json" },
|
|
109
|
+
body: JSON.stringify({
|
|
110
|
+
chatId: activeChatId,
|
|
111
|
+
expertId,
|
|
112
|
+
message: userMessage,
|
|
113
|
+
userMessageId,
|
|
114
|
+
senderName,
|
|
115
|
+
senderUserId,
|
|
116
|
+
warmContext: warmContext || undefined,
|
|
117
|
+
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
118
|
+
...streamBody,
|
|
119
|
+
}),
|
|
120
|
+
signal: controller.signal,
|
|
121
|
+
});
|
|
122
|
+
if (!response.ok || !response.body) {
|
|
123
|
+
setMessages((prev) => prev.map((m) => m.id === tempId
|
|
124
|
+
? { ...m, content: "Something went wrong. Try again.", streaming: false }
|
|
125
|
+
: m));
|
|
126
|
+
setStreaming(false);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
for await (const event of (0, sse_client_js_1.parseSseStream)(response)) {
|
|
130
|
+
onEventRef.current?.(event);
|
|
131
|
+
switch (event.type) {
|
|
132
|
+
case "first_response": {
|
|
133
|
+
forceFlush();
|
|
134
|
+
pendingText.current = "";
|
|
135
|
+
const frTarget = streamTempId.current || tempId;
|
|
136
|
+
setMessages((prev) => prev.map((m) => (m.id === frTarget ? { ...m, content: m.content + "\n\n" } : m)));
|
|
137
|
+
frTransitioningRef.current = true;
|
|
138
|
+
setFrTransitioning(true);
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
case "replace_content": {
|
|
142
|
+
forceFlush();
|
|
143
|
+
pendingText.current = "";
|
|
144
|
+
const replaceTarget = streamTempId.current || tempId;
|
|
145
|
+
setMessages((prev) => prev.filter((m) => m.id !== replaceTarget));
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
case "skill_start": {
|
|
149
|
+
skillTransitioningRef.current = true;
|
|
150
|
+
setSkillTransitioning(true);
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
case "text": {
|
|
154
|
+
if (frTransitioningRef.current) {
|
|
155
|
+
frTransitioningRef.current = false;
|
|
156
|
+
setFrTransitioning(false);
|
|
157
|
+
}
|
|
158
|
+
if (skillTransitioningRef.current) {
|
|
159
|
+
skillTransitioningRef.current = false;
|
|
160
|
+
setSkillTransitioning(false);
|
|
161
|
+
}
|
|
162
|
+
scheduleFlush(event.text);
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
case "done": {
|
|
166
|
+
forceFlush();
|
|
167
|
+
const remainingText = pendingText.current;
|
|
168
|
+
pendingText.current = "";
|
|
169
|
+
const finalMessageId = event.messageId;
|
|
170
|
+
const doneTarget = streamTempId.current || tempId;
|
|
171
|
+
setMessages((prev) => prev.map((m) => m.id === doneTarget
|
|
172
|
+
? {
|
|
173
|
+
...m,
|
|
174
|
+
id: finalMessageId || doneTarget,
|
|
175
|
+
content: m.content + remainingText,
|
|
176
|
+
streaming: false,
|
|
177
|
+
}
|
|
178
|
+
: m));
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
case "error": {
|
|
182
|
+
forceFlush();
|
|
183
|
+
pendingText.current = "";
|
|
184
|
+
const errorTarget = streamTempId.current || tempId;
|
|
185
|
+
setMessages((prev) => prev.map((m) => m.id === errorTarget
|
|
186
|
+
? { ...m, content: m.content || event.error, streaming: false }
|
|
187
|
+
: m));
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
setMessages((prev) => prev.map((m) => (m.streaming ? { ...m, streaming: false } : m)));
|
|
193
|
+
}
|
|
194
|
+
catch (err) {
|
|
195
|
+
if (err.name !== "AbortError") {
|
|
196
|
+
setMessages((prev) => prev.map((m) => m.id === tempId
|
|
197
|
+
? { ...m, content: "Connection lost. Try again.", streaming: false }
|
|
198
|
+
: m));
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
finally {
|
|
202
|
+
if (rafId.current !== null) {
|
|
203
|
+
cancelAnimationFrame(rafId.current);
|
|
204
|
+
rafId.current = null;
|
|
205
|
+
}
|
|
206
|
+
pendingText.current = "";
|
|
207
|
+
streamTempId.current = null;
|
|
208
|
+
setStreaming(false);
|
|
209
|
+
frTransitioningRef.current = false;
|
|
210
|
+
setFrTransitioning(false);
|
|
211
|
+
skillTransitioningRef.current = false;
|
|
212
|
+
setSkillTransitioning(false);
|
|
213
|
+
abortRef.current = null;
|
|
214
|
+
}
|
|
215
|
+
}, [expertId, senderName, warmContext, streamEndpoint, streamBody, scheduleFlush, forceFlush]);
|
|
216
|
+
// ---- Public API ----
|
|
217
|
+
const send = (0, react_1.useCallback)(async (content, chatIdOverride) => {
|
|
218
|
+
const activeChatId = chatIdOverride || chatId;
|
|
219
|
+
if (!content.trim() || sending || streaming || !activeChatId)
|
|
220
|
+
return;
|
|
221
|
+
if (chatIdOverride && chatIdOverride !== chatId) {
|
|
222
|
+
setChatId(chatIdOverride);
|
|
223
|
+
}
|
|
224
|
+
setSending(true);
|
|
225
|
+
const userTempId = `user-${Date.now()}`;
|
|
226
|
+
setMessages((prev) => [
|
|
227
|
+
...prev,
|
|
228
|
+
{ id: userTempId, role: "user", content, createdAt: new Date().toISOString() },
|
|
229
|
+
]);
|
|
230
|
+
try {
|
|
231
|
+
let savedId = null;
|
|
232
|
+
let senderUserId = null;
|
|
233
|
+
if (persistMessage) {
|
|
234
|
+
const result = await persistMessage(activeChatId, content);
|
|
235
|
+
savedId = result.id;
|
|
236
|
+
senderUserId = result.userId;
|
|
237
|
+
}
|
|
238
|
+
if (savedId) {
|
|
239
|
+
setMessages((prev) => prev.map((m) => (m.id === userTempId ? { ...m, id: savedId } : m)));
|
|
240
|
+
}
|
|
241
|
+
setSending(false);
|
|
242
|
+
await streamResponse(activeChatId, content, savedId, senderUserId);
|
|
243
|
+
}
|
|
244
|
+
catch (err) {
|
|
245
|
+
console.error("[ChatRuntime] Error in send:", err);
|
|
246
|
+
setSending(false);
|
|
247
|
+
}
|
|
248
|
+
}, [chatId, sending, streaming, persistMessage, streamResponse]);
|
|
249
|
+
const abort = (0, react_1.useCallback)(() => {
|
|
250
|
+
if (abortRef.current) {
|
|
251
|
+
abortRef.current.abort();
|
|
252
|
+
abortRef.current = null;
|
|
253
|
+
}
|
|
254
|
+
forceFlush();
|
|
255
|
+
pendingText.current = "";
|
|
256
|
+
setMessages((prev) => prev.map((m) => (m.streaming ? { ...m, streaming: false } : m)));
|
|
257
|
+
setStreaming(false);
|
|
258
|
+
}, [forceFlush]);
|
|
259
|
+
const clear = (0, react_1.useCallback)(() => {
|
|
260
|
+
setMessages([]);
|
|
261
|
+
}, []);
|
|
262
|
+
return {
|
|
263
|
+
messages,
|
|
264
|
+
streaming,
|
|
265
|
+
sending,
|
|
266
|
+
frTransitioning,
|
|
267
|
+
skillTransitioning,
|
|
268
|
+
chatId,
|
|
269
|
+
send,
|
|
270
|
+
abort,
|
|
271
|
+
clear,
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
//# sourceMappingURL=use-chat-runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-chat-runtime.js","sourceRoot":"","sources":["../src/use-chat-runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { SseEvent } from "@portablecore/types/chat";
|
|
2
|
+
/** Thinking stage for the ThinkingIndicator component. */
|
|
3
|
+
export interface SkillThinkingStage {
|
|
4
|
+
stage: "memories" | "knowledge" | "context" | "skills" | "thinking";
|
|
5
|
+
detail?: string;
|
|
6
|
+
showIcon?: boolean;
|
|
7
|
+
}
|
|
8
|
+
/** Active skill indicator state for the SkillIndicator component. */
|
|
9
|
+
export interface ActiveSkillState {
|
|
10
|
+
slug: string;
|
|
11
|
+
name: string;
|
|
12
|
+
showSkillPill?: boolean;
|
|
13
|
+
skillPillText?: string | null;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Minimal skill config needed by the hook.
|
|
17
|
+
* Consumer passes their full skill array; only these fields are read.
|
|
18
|
+
*/
|
|
19
|
+
export interface SkillConfig {
|
|
20
|
+
slug: string;
|
|
21
|
+
showSkillPill: boolean;
|
|
22
|
+
skillPillText: string | null;
|
|
23
|
+
}
|
|
24
|
+
/** Accumulated skill result entry from streaming. */
|
|
25
|
+
export interface SkillResultEntry {
|
|
26
|
+
skill_slug: string;
|
|
27
|
+
skill_name: string;
|
|
28
|
+
invoked_at: string;
|
|
29
|
+
duration_ms: number;
|
|
30
|
+
citations?: any[];
|
|
31
|
+
sources?: any[];
|
|
32
|
+
locations?: any[];
|
|
33
|
+
booking_links?: any[];
|
|
34
|
+
documents?: any[];
|
|
35
|
+
}
|
|
36
|
+
export interface UseSkillIndicatorsReturn {
|
|
37
|
+
/** Currently active skill (for skill pill indicator). Null when idle. */
|
|
38
|
+
activeSkill: ActiveSkillState | null;
|
|
39
|
+
/** Accumulated thinking stages for the current response. */
|
|
40
|
+
thinkingStages: SkillThinkingStage[];
|
|
41
|
+
/** Ref to accumulated skill results for the current response. */
|
|
42
|
+
pendingSkillResults: React.MutableRefObject<SkillResultEntry[]>;
|
|
43
|
+
/** Process a thinking, skill_start, or skill_result SSE event. */
|
|
44
|
+
handleEvent: (event: SseEvent) => void;
|
|
45
|
+
/** Clear thinking stages only. */
|
|
46
|
+
clearThinking: () => void;
|
|
47
|
+
/** Reset all indicator state. */
|
|
48
|
+
reset: () => void;
|
|
49
|
+
}
|
|
50
|
+
export declare function useSkillIndicators(chatSkills: SkillConfig[]): UseSkillIndicatorsReturn;
|
|
51
|
+
//# sourceMappingURL=use-skill-indicators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-skill-indicators.d.ts","sourceRoot":"","sources":["../src/use-skill-indicators.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAMxD,0DAA0D;AAC1D,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,UAAU,GAAG,WAAW,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,CAAA;IACnE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,qEAAqE;AACrE,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,aAAa,EAAE,OAAO,CAAA;IACtB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;CAC7B;AAED,qDAAqD;AACrD,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IAEnB,SAAS,CAAC,EAAE,GAAG,EAAE,CAAA;IACjB,OAAO,CAAC,EAAE,GAAG,EAAE,CAAA;IACf,SAAS,CAAC,EAAE,GAAG,EAAE,CAAA;IACjB,aAAa,CAAC,EAAE,GAAG,EAAE,CAAA;IACrB,SAAS,CAAC,EAAE,GAAG,EAAE,CAAA;CAElB;AAED,MAAM,WAAW,wBAAwB;IACvC,yEAAyE;IACzE,WAAW,EAAE,gBAAgB,GAAG,IAAI,CAAA;IACpC,4DAA4D;IAC5D,cAAc,EAAE,kBAAkB,EAAE,CAAA;IACpC,iEAAiE;IACjE,mBAAmB,EAAE,KAAK,CAAC,gBAAgB,CAAC,gBAAgB,EAAE,CAAC,CAAA;IAC/D,kEAAkE;IAClE,WAAW,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAA;IACtC,kCAAkC;IAClC,aAAa,EAAE,MAAM,IAAI,CAAA;IACzB,iCAAiC;IACjC,KAAK,EAAE,MAAM,IAAI,CAAA;CAClB;AAMD,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,WAAW,EAAE,GAAG,wBAAwB,CA6EtF"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.useSkillIndicators = useSkillIndicators;
|
|
5
|
+
/**
|
|
6
|
+
* useSkillIndicators — Skill and thinking indicator state management
|
|
7
|
+
*
|
|
8
|
+
* Manages UI state for cognition indicators (thinking stages) and
|
|
9
|
+
* skill execution indicators (active skill pill, pending results).
|
|
10
|
+
*
|
|
11
|
+
* Handles three SSE event types:
|
|
12
|
+
* - thinking → append to thinking stages
|
|
13
|
+
* - skill_start → show skill pill (if configured), clear thinking stages
|
|
14
|
+
* - skill_result → accumulate results, clear skill pill
|
|
15
|
+
*/
|
|
16
|
+
const react_1 = require("react");
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// Hook
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
function useSkillIndicators(chatSkills) {
|
|
21
|
+
const [activeSkill, setActiveSkill] = (0, react_1.useState)(null);
|
|
22
|
+
const [thinkingStages, setThinkingStages] = (0, react_1.useState)([]);
|
|
23
|
+
const pendingSkillResults = (0, react_1.useRef)([]);
|
|
24
|
+
const chatSkillsRef = (0, react_1.useRef)(chatSkills);
|
|
25
|
+
(0, react_1.useEffect)(() => {
|
|
26
|
+
chatSkillsRef.current = chatSkills;
|
|
27
|
+
}, [chatSkills]);
|
|
28
|
+
const handleEvent = (0, react_1.useCallback)((event) => {
|
|
29
|
+
switch (event.type) {
|
|
30
|
+
case "thinking": {
|
|
31
|
+
setThinkingStages((prev) => [
|
|
32
|
+
...prev,
|
|
33
|
+
{
|
|
34
|
+
stage: event.stage,
|
|
35
|
+
detail: event.detail,
|
|
36
|
+
showIcon: event.showIcon,
|
|
37
|
+
},
|
|
38
|
+
]);
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
case "skill_start": {
|
|
42
|
+
const displayName = event.contextualMessage || event.skillName;
|
|
43
|
+
const skillInfo = chatSkillsRef.current.find((s) => s.slug === event.skillSlug);
|
|
44
|
+
const shouldShowPill = skillInfo?.showSkillPill ?? true;
|
|
45
|
+
if (shouldShowPill) {
|
|
46
|
+
setThinkingStages([]);
|
|
47
|
+
setActiveSkill({
|
|
48
|
+
slug: event.skillSlug,
|
|
49
|
+
name: displayName,
|
|
50
|
+
showSkillPill: true,
|
|
51
|
+
skillPillText: skillInfo?.skillPillText ?? null,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
case "skill_result": {
|
|
57
|
+
pendingSkillResults.current.push({
|
|
58
|
+
skill_slug: event.skillSlug,
|
|
59
|
+
skill_name: event.skillName,
|
|
60
|
+
invoked_at: new Date().toISOString(),
|
|
61
|
+
duration_ms: event.duration_ms || 0,
|
|
62
|
+
citations: event.citations,
|
|
63
|
+
sources: event.sources,
|
|
64
|
+
locations: event.locations,
|
|
65
|
+
booking_links: event.booking_links,
|
|
66
|
+
documents: event.documents,
|
|
67
|
+
});
|
|
68
|
+
setActiveSkill(null);
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}, []);
|
|
73
|
+
const clearThinking = (0, react_1.useCallback)(() => {
|
|
74
|
+
setThinkingStages([]);
|
|
75
|
+
}, []);
|
|
76
|
+
const reset = (0, react_1.useCallback)(() => {
|
|
77
|
+
setActiveSkill(null);
|
|
78
|
+
setThinkingStages([]);
|
|
79
|
+
pendingSkillResults.current = [];
|
|
80
|
+
}, []);
|
|
81
|
+
return {
|
|
82
|
+
activeSkill,
|
|
83
|
+
thinkingStages,
|
|
84
|
+
pendingSkillResults,
|
|
85
|
+
handleEvent,
|
|
86
|
+
clearThinking,
|
|
87
|
+
reset,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=use-skill-indicators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-skill-indicators.js","sourceRoot":"","sources":["../src/use-skill-indicators.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** Minimal message shape required by the streaming engine. */
|
|
2
|
+
interface StreamableMessage {
|
|
3
|
+
id: string;
|
|
4
|
+
content: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* The setMessages updater. Works with React.Dispatch<SetStateAction<M[]>>
|
|
8
|
+
* for any message type extending StreamableMessage.
|
|
9
|
+
*/
|
|
10
|
+
type MessageUpdater<M extends StreamableMessage> = (updater: (prev: M[]) => M[]) => void;
|
|
11
|
+
export interface UseStreamingMessageReturn {
|
|
12
|
+
/**
|
|
13
|
+
* Ref tracking the ID of the message currently being streamed into.
|
|
14
|
+
* Set by the caller before streaming starts; read by RAF callbacks.
|
|
15
|
+
*/
|
|
16
|
+
streamingMessageId: React.MutableRefObject<string | null>;
|
|
17
|
+
/**
|
|
18
|
+
* Append a text chunk. Chunks are accumulated and flushed at 60fps.
|
|
19
|
+
*/
|
|
20
|
+
updateStreamingMessage: (content: string) => void;
|
|
21
|
+
/**
|
|
22
|
+
* Force-flush buffered text immediately.
|
|
23
|
+
* Call before changing streamingMessageId or cleaning up.
|
|
24
|
+
*/
|
|
25
|
+
flushPendingContent: () => void;
|
|
26
|
+
}
|
|
27
|
+
export declare function useStreamingMessage<M extends StreamableMessage>(setMessages: MessageUpdater<M>): UseStreamingMessageReturn;
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=use-streaming-message.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-streaming-message.d.ts","sourceRoot":"","sources":["../src/use-streaming-message.ts"],"names":[],"mappings":"AAqBA,8DAA8D;AAC9D,UAAU,iBAAiB;IACzB,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;;GAGG;AACH,KAAK,cAAc,CAAC,CAAC,SAAS,iBAAiB,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,KAAK,IAAI,CAAA;AAExF,MAAM,WAAW,yBAAyB;IACxC;;;OAGG;IACH,kBAAkB,EAAE,KAAK,CAAC,gBAAgB,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IACzD;;OAEG;IACH,sBAAsB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IACjD;;;OAGG;IACH,mBAAmB,EAAE,MAAM,IAAI,CAAA;CAChC;AAMD,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,iBAAiB,EAC7D,WAAW,EAAE,cAAc,CAAC,CAAC,CAAC,GAC7B,yBAAyB,CAkE3B"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.useStreamingMessage = useStreamingMessage;
|
|
5
|
+
/**
|
|
6
|
+
* useStreamingMessage — RAF-batched streaming text accumulator
|
|
7
|
+
*
|
|
8
|
+
* Provides low-level plumbing for appending streamed text chunks
|
|
9
|
+
* to a message list at 60fps. Used by both useChatRuntime (lite)
|
|
10
|
+
* and the full ChatInterface.
|
|
11
|
+
*
|
|
12
|
+
* The hook owns:
|
|
13
|
+
* - streamingMessageId ref: which message is currently being streamed into
|
|
14
|
+
* - updateStreamingMessage(text): accumulates text, flushes via RAF
|
|
15
|
+
* - flushPendingContent(): force-flush before ID swaps or cleanup
|
|
16
|
+
*/
|
|
17
|
+
const react_1 = require("react");
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
// Hook
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
function useStreamingMessage(setMessages) {
|
|
22
|
+
const streamingMessageId = (0, react_1.useRef)(null);
|
|
23
|
+
const pendingContent = (0, react_1.useRef)("");
|
|
24
|
+
const rafId = (0, react_1.useRef)(null);
|
|
25
|
+
const flushPendingContent = (0, react_1.useCallback)(() => {
|
|
26
|
+
if (rafId.current !== null) {
|
|
27
|
+
cancelAnimationFrame(rafId.current);
|
|
28
|
+
rafId.current = null;
|
|
29
|
+
}
|
|
30
|
+
if (pendingContent.current && streamingMessageId.current) {
|
|
31
|
+
const contentToAdd = pendingContent.current;
|
|
32
|
+
const messageId = streamingMessageId.current;
|
|
33
|
+
pendingContent.current = "";
|
|
34
|
+
setMessages((prev) => prev.map((m) => {
|
|
35
|
+
if (m.id === messageId) {
|
|
36
|
+
return { ...m, content: m.content + contentToAdd };
|
|
37
|
+
}
|
|
38
|
+
return m;
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
41
|
+
}, [setMessages]);
|
|
42
|
+
const updateStreamingMessage = (0, react_1.useCallback)((content) => {
|
|
43
|
+
if (!streamingMessageId.current)
|
|
44
|
+
return;
|
|
45
|
+
pendingContent.current += content;
|
|
46
|
+
if (rafId.current === null) {
|
|
47
|
+
rafId.current = requestAnimationFrame(() => {
|
|
48
|
+
const contentToAdd = pendingContent.current;
|
|
49
|
+
pendingContent.current = "";
|
|
50
|
+
rafId.current = null;
|
|
51
|
+
setMessages((prev) => prev.map((m) => {
|
|
52
|
+
if (m.id === streamingMessageId.current) {
|
|
53
|
+
return { ...m, content: m.content + contentToAdd };
|
|
54
|
+
}
|
|
55
|
+
return m;
|
|
56
|
+
}));
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}, [setMessages]);
|
|
60
|
+
(0, react_1.useEffect)(() => {
|
|
61
|
+
return () => {
|
|
62
|
+
if (rafId.current !== null) {
|
|
63
|
+
cancelAnimationFrame(rafId.current);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
}, []);
|
|
67
|
+
return {
|
|
68
|
+
streamingMessageId,
|
|
69
|
+
updateStreamingMessage,
|
|
70
|
+
flushPendingContent,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=use-streaming-message.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-streaming-message.js","sourceRoot":"","sources":["../src/use-streaming-message.ts"],"names":[],"mappings":"AAAA,YAAY,CAAA;;;AAsDZ,kDAoEC;AAxHD;;;;;;;;;;;GAWG;AAEH,iCAAsD;AAmCtD,8EAA8E;AAC9E,OAAO;AACP,8EAA8E;AAE9E,SAAgB,mBAAmB,CACjC,WAA8B;IAE9B,MAAM,kBAAkB,GAAG,IAAA,cAAM,EAAgB,IAAI,CAAC,CAAA;IACtD,MAAM,cAAc,GAAG,IAAA,cAAM,EAAC,EAAE,CAAC,CAAA;IACjC,MAAM,KAAK,GAAG,IAAA,cAAM,EAAgB,IAAI,CAAC,CAAA;IAEzC,MAAM,mBAAmB,GAAG,IAAA,mBAAW,EAAC,GAAG,EAAE;QAC3C,IAAI,KAAK,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;YAC3B,oBAAoB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;YACnC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAA;QACtB,CAAC;QAED,IAAI,cAAc,CAAC,OAAO,IAAI,kBAAkB,CAAC,OAAO,EAAE,CAAC;YACzD,MAAM,YAAY,GAAG,cAAc,CAAC,OAAO,CAAA;YAC3C,MAAM,SAAS,GAAG,kBAAkB,CAAC,OAAO,CAAA;YAC5C,cAAc,CAAC,OAAO,GAAG,EAAE,CAAA;YAE3B,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE,CACnB,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBACb,IAAI,CAAC,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;oBACvB,OAAO,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,GAAG,YAAY,EAAE,CAAA;gBACpD,CAAC;gBACD,OAAO,CAAC,CAAA;YACV,CAAC,CAAC,CACH,CAAA;QACH,CAAC;IACH,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAA;IAEjB,MAAM,sBAAsB,GAAG,IAAA,mBAAW,EACxC,CAAC,OAAe,EAAE,EAAE;QAClB,IAAI,CAAC,kBAAkB,CAAC,OAAO;YAAE,OAAM;QAEvC,cAAc,CAAC,OAAO,IAAI,OAAO,CAAA;QAEjC,IAAI,KAAK,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;YAC3B,KAAK,CAAC,OAAO,GAAG,qBAAqB,CAAC,GAAG,EAAE;gBACzC,MAAM,YAAY,GAAG,cAAc,CAAC,OAAO,CAAA;gBAC3C,cAAc,CAAC,OAAO,GAAG,EAAE,CAAA;gBAC3B,KAAK,CAAC,OAAO,GAAG,IAAI,CAAA;gBAEpB,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE,CACnB,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;oBACb,IAAI,CAAC,CAAC,EAAE,KAAK,kBAAkB,CAAC,OAAO,EAAE,CAAC;wBACxC,OAAO,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,GAAG,YAAY,EAAE,CAAA;oBACpD,CAAC;oBACD,OAAO,CAAC,CAAA;gBACV,CAAC,CAAC,CACH,CAAA;YACH,CAAC,CAAC,CAAA;QACJ,CAAC;IACH,CAAC,EACD,CAAC,WAAW,CAAC,CACd,CAAA;IAED,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,OAAO,GAAG,EAAE;YACV,IAAI,KAAK,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;gBAC3B,oBAAoB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;YACrC,CAAC;QACH,CAAC,CAAA;IACH,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,OAAO;QACL,kBAAkB;QAClB,sBAAsB;QACtB,mBAAmB;KACpB,CAAA;AACH,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@portablecore/chat-runtime",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Headless chat runtime for Portable platforms — SSE streaming, message state, and lifecycle hooks",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"default": "./dist/index.js"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
"keywords": [
|
|
17
|
+
"portable",
|
|
18
|
+
"chat",
|
|
19
|
+
"runtime",
|
|
20
|
+
"sse",
|
|
21
|
+
"streaming"
|
|
22
|
+
],
|
|
23
|
+
"author": "Portable",
|
|
24
|
+
"license": "UNLICENSED",
|
|
25
|
+
"peerDependencies": {
|
|
26
|
+
"react": ">=18.0.0"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"typescript": "^5.3.0",
|
|
30
|
+
"@types/react": "^18.0.0",
|
|
31
|
+
"react": "^18.0.0"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@portablecore/types": "0.10.0"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsc",
|
|
38
|
+
"dev": "tsc --watch",
|
|
39
|
+
"clean": "rm -rf dist",
|
|
40
|
+
"typecheck": "tsc --noEmit"
|
|
41
|
+
}
|
|
42
|
+
}
|