simple-ai-sdk 1.1.3 → 1.1.5
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/client/manager.d.ts +4 -4
- package/dist/client/manager.d.ts.map +1 -1
- package/dist/client/manager.js +18 -14
- package/dist/client/types.d.ts +3 -2
- package/dist/client/types.d.ts.map +1 -1
- package/dist/client/useChatSession.d.ts.map +1 -1
- package/dist/client/useChatSession.js +2 -2
- package/dist/shared/error-utils.d.ts +2 -1
- package/dist/shared/error-utils.d.ts.map +1 -1
- package/dist/spec.md +11 -5
- package/package.json +1 -1
package/dist/client/manager.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ChatSession, OnChatFinishCallback, SetMessagesOptions, StreamManagerListener, StreamManagerState } from "./types.js";
|
|
1
|
+
import type { ChatSession, OnChatFinishCallback, SetMessagesOptions, SetMessagesUpdater, StreamManagerListener, StreamManagerState } from "./types.js";
|
|
2
2
|
import type { Message, JSONValue } from "../shared/index.js";
|
|
3
3
|
export interface IStreamManager {
|
|
4
4
|
subscribe(listener: StreamManagerListener): () => void;
|
|
@@ -33,10 +33,10 @@ export interface IStreamManager {
|
|
|
33
33
|
*/
|
|
34
34
|
touchSession(sessionId: string): void;
|
|
35
35
|
/**
|
|
36
|
-
* API 呼び出しを行わず、指定セッションの messages
|
|
36
|
+
* API 呼び出しを行わず、指定セッションの messages を更新する。
|
|
37
37
|
* - messagesVersion は内部でインクリメントされる。
|
|
38
38
|
*/
|
|
39
|
-
setMessages(sessionId: string,
|
|
39
|
+
setMessages(sessionId: string, updater: SetMessagesUpdater, options?: SetMessagesOptions): void;
|
|
40
40
|
streamChat(sessionId: string, messages: Message[], options: {
|
|
41
41
|
api: string;
|
|
42
42
|
body?: Record<string, JSONValue>;
|
|
@@ -117,7 +117,7 @@ declare class StreamManager implements IStreamManager {
|
|
|
117
117
|
api: string;
|
|
118
118
|
body?: Record<string, JSONValue>;
|
|
119
119
|
}): Promise<void>;
|
|
120
|
-
setMessages(sessionId: string,
|
|
120
|
+
setMessages(sessionId: string, updater: SetMessagesUpdater, options?: SetMessagesOptions): void;
|
|
121
121
|
stopStream(sessionId: string): void;
|
|
122
122
|
stopAllStreams(): void;
|
|
123
123
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/client/manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,oBAAoB,EAEpB,kBAAkB,EAClB,qBAAqB,EACrB,kBAAkB,EACnB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAEV,OAAO,EACP,SAAS,EAEV,MAAM,oBAAoB,CAAC;AAK5B,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,QAAQ,EAAE,qBAAqB,GAAG,MAAM,IAAI,CAAC;IACvD,WAAW,IAAI,kBAAkB,CAAC;IAClC;;;OAGG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAAC;IACvD,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAClE;;;;OAIG;IACH,kBAAkB,CAChB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,oBAAoB,GAAG,SAAS,GACxC,IAAI,CAAC;IACR;;OAEG;IACH,iBAAiB,CACf,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,SAAS,GAC5C,IAAI,CAAC;IACR;;OAEG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC;;OAEG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC;;;OAGG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC;;;OAGG;IACH,WAAW,CACT,SAAS,EAAE,MAAM,EACjB,
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/client/manager.ts"],"names":[],"mappings":"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"}
|
package/dist/client/manager.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { generateMessageId } from "../shared/generate-id.js";
|
|
2
|
-
import { isAbortError } from "../shared/error-utils.js";
|
|
2
|
+
import { ChatError, isAbortError } from "../shared/error-utils.js";
|
|
3
3
|
class StreamManager {
|
|
4
4
|
state = {
|
|
5
5
|
sessions: new Map(),
|
|
@@ -540,7 +540,8 @@ class StreamManager {
|
|
|
540
540
|
// - コメント行(先頭 ':')は無視
|
|
541
541
|
// - event: が無い場合はデフォルトの 'message' を想定するが、本実装ではサーバ仕様に合わせ 'chunk' 等のみ処理
|
|
542
542
|
// - 末尾が改行で終わらない場合でも、ループ終了時に最後のイベントをフラッシュする
|
|
543
|
-
let
|
|
543
|
+
let errorHandled = false; // 意図: error イベント処理後に通常完了経路や catch を踏まないためのフラグ
|
|
544
|
+
let doneReceived = false; // 意図: success は明示的な done イベント受信時のみに限定する
|
|
544
545
|
let shouldTerminate = false; // 意図: done/error 受信時にループ終了を指示
|
|
545
546
|
const flushEvent = () => {
|
|
546
547
|
if (dataLines.length === 0 && !eventName)
|
|
@@ -618,7 +619,7 @@ class StreamManager {
|
|
|
618
619
|
nextAssistantMessageId: null,
|
|
619
620
|
}, true);
|
|
620
621
|
this.deliverOrQueueError(sessionId, err);
|
|
621
|
-
|
|
622
|
+
errorHandled = true;
|
|
622
623
|
shouldTerminate = true;
|
|
623
624
|
break;
|
|
624
625
|
}
|
|
@@ -629,6 +630,7 @@ class StreamManager {
|
|
|
629
630
|
let finishedReason = null;
|
|
630
631
|
if (isDonePayload(parsed))
|
|
631
632
|
finishedReason = toChatFinishReason(parsed.finished_reason);
|
|
633
|
+
doneReceived = true;
|
|
632
634
|
this.updateSession(sessionId, {
|
|
633
635
|
status: "ready",
|
|
634
636
|
abortController: null,
|
|
@@ -695,20 +697,23 @@ class StreamManager {
|
|
|
695
697
|
catch {
|
|
696
698
|
/* noop */
|
|
697
699
|
}
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
700
|
+
const latestId = this.streamIds.get(sessionId);
|
|
701
|
+
if (latestId !== streamId)
|
|
702
|
+
return;
|
|
703
|
+
if (!errorHandled && !doneReceived) {
|
|
704
|
+
const err = new ChatError("unexpected_eof", "Stream ended before done event");
|
|
701
705
|
this.updateSession(sessionId, {
|
|
702
|
-
status: "
|
|
706
|
+
status: "error",
|
|
707
|
+
error: err,
|
|
703
708
|
abortController: null,
|
|
704
709
|
finishedReason: null,
|
|
705
710
|
nextAssistantMessageId: null,
|
|
706
|
-
}, true);
|
|
707
|
-
this.
|
|
711
|
+
}, true);
|
|
712
|
+
this.deliverOrQueueError(sessionId, err);
|
|
708
713
|
}
|
|
709
714
|
}
|
|
710
715
|
catch (error) {
|
|
711
|
-
// 意図:
|
|
716
|
+
// 意図: SSE の error イベントはここに到達しないため、ここは接続エラーや中断のみ
|
|
712
717
|
if (isAbortError(error)) {
|
|
713
718
|
// 既に stopStream() 等で aborted 済みであれば二重更新を避ける
|
|
714
719
|
const s = this.state.sessions.get(sessionId);
|
|
@@ -739,13 +744,12 @@ class StreamManager {
|
|
|
739
744
|
}
|
|
740
745
|
}
|
|
741
746
|
}
|
|
742
|
-
setMessages(sessionId,
|
|
747
|
+
setMessages(sessionId, updater, options) {
|
|
743
748
|
const session = this.state.sessions.get(sessionId);
|
|
744
749
|
if (!session) {
|
|
745
|
-
|
|
746
|
-
this.initSession(sessionId, messages);
|
|
747
|
-
return;
|
|
750
|
+
throw new Error(`Session not initialized: ${sessionId}`);
|
|
748
751
|
}
|
|
752
|
+
const messages = updater(session.messages);
|
|
749
753
|
const shouldReset = options?.resetStatus &&
|
|
750
754
|
session.status !== "streaming" &&
|
|
751
755
|
session.status !== "submitted";
|
package/dist/client/types.d.ts
CHANGED
|
@@ -76,6 +76,7 @@ export type SetMessagesOptions = {
|
|
|
76
76
|
*/
|
|
77
77
|
resetStatus?: boolean;
|
|
78
78
|
};
|
|
79
|
+
export type SetMessagesUpdater = (prev: Message[]) => Message[];
|
|
79
80
|
export type ReloadMessage = (params?: {
|
|
80
81
|
body?: SendMessageReqBody;
|
|
81
82
|
}) => Promise<void>;
|
|
@@ -102,10 +103,10 @@ export type UseChatSessionReturn = {
|
|
|
102
103
|
status: ChatStatus;
|
|
103
104
|
error: Error | null;
|
|
104
105
|
/**
|
|
105
|
-
* API 呼び出しを行わず、現在のセッションの messages
|
|
106
|
+
* API 呼び出しを行わず、現在のセッションの messages を即時更新する。
|
|
106
107
|
* - 内部的に messagesVersion がインクリメントされる。
|
|
107
108
|
*/
|
|
108
|
-
setMessages: (
|
|
109
|
+
setMessages: (updater: SetMessagesUpdater, options?: SetMessagesOptions) => void;
|
|
109
110
|
sendMessage: (content: string, params?: SendMessageOptions) => Promise<void>;
|
|
110
111
|
reload: ReloadMessage;
|
|
111
112
|
stop: () => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/client/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE9E,MAAM,MAAM,UAAU,GAClB,OAAO,GACP,WAAW,GACX,WAAW,GACX,OAAO,GACP,SAAS,CAAC;AAEd,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB;;;OAGG;IACH,QAAQ,EAAE,KAAK,CAAC,eAAe,CAAC,CAAC;IACjC;;;;OAIG;IACH,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC;;OAEG;IACH,cAAc,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACxC;;;;;OAKG;IACH,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,eAAe,EAAE,eAAe,GAAG,IAAI,CAAC;IACxC,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;AAEzD,MAAM,MAAM,mBAAmB,GAAG;IAChC,cAAc,EAAE,gBAAgB,CAAC;IACjC;;;OAGG;IACH,QAAQ,EAAE,KAAK,CAAC,eAAe,CAAC,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,CACjC,QAAQ,EAAE,OAAO,EAAE,EACnB,OAAO,EAAE,mBAAmB,KACzB,IAAI,CAAC;AAEV,MAAM,MAAM,qBAAqB,GAAG;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,eAAe,CAAC,EAAE,OAAO,EAAE,CAAC;IAC5B;;;;;OAKG;IACH,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,oBAAoB,CAAC;CAMjC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAE3D,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAC1B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,CAAC,MAAM,CAAC,EAAE;IACpC,IAAI,CAAC,EAAE,kBAAkB,CAAC;CAC3B,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAEpB,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB;;OAEG;IACH,QAAQ,EAAE,KAAK,CAAC,eAAe,CAAC,CAAC;IACjC;;;OAGG;IACH,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC;;OAEG;IACH,cAAc,EAAE,gBAAgB,CAAC;IACjC;;;OAGG;IACH,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB;;;OAGG;IACH,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/client/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useChatSession.d.ts","sourceRoot":"","sources":["../../src/client/useChatSession.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,qBAAqB,EACrB,oBAAoB,
|
|
1
|
+
{"version":3,"file":"useChatSession.d.ts","sourceRoot":"","sources":["../../src/client/useChatSession.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,qBAAqB,EACrB,oBAAoB,EAKrB,MAAM,YAAY,CAAC;AAKpB,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,qBAAqB,GAC7B,oBAAoB,CAgMtB"}
|
|
@@ -106,8 +106,8 @@ export function useChatSession(sessionId, options) {
|
|
|
106
106
|
const stopAll = useCallback(() => {
|
|
107
107
|
manager.stopAllStreams();
|
|
108
108
|
}, [manager]);
|
|
109
|
-
const setMessages = useCallback((
|
|
110
|
-
manager.setMessages(sessionId,
|
|
109
|
+
const setMessages = useCallback((updater, options) => {
|
|
110
|
+
manager.setMessages(sessionId, updater, options);
|
|
111
111
|
}, [manager, sessionId]);
|
|
112
112
|
const lastMessage = session.messages.at(-1);
|
|
113
113
|
const lastMessageRole = lastMessage?.role;
|
|
@@ -3,8 +3,9 @@ export declare function isAbortError(e: unknown): boolean;
|
|
|
3
3
|
* - `content_filter`: The content was filtered by the content filter.
|
|
4
4
|
* - `aborted`: The request was aborted, likely by the user.
|
|
5
5
|
* - `no_response`: The model did not return a response. (not loading or streaming && last message is by the user)
|
|
6
|
+
* - `unexpected_eof`: The stream ended before a terminal `done` event arrived.
|
|
6
7
|
*/
|
|
7
|
-
export type ChatErrorCode = "content_filter" | "aborted" | "no_response";
|
|
8
|
+
export type ChatErrorCode = "content_filter" | "aborted" | "no_response" | "unexpected_eof";
|
|
8
9
|
export declare class ChatError extends Error {
|
|
9
10
|
readonly code: ChatErrorCode;
|
|
10
11
|
constructor(code: ChatErrorCode, message?: string);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-utils.d.ts","sourceRoot":"","sources":["../../src/shared/error-utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAYhD;AAED
|
|
1
|
+
{"version":3,"file":"error-utils.d.ts","sourceRoot":"","sources":["../../src/shared/error-utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAYhD;AAED;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GACrB,gBAAgB,GAChB,SAAS,GACT,aAAa,GACb,gBAAgB,CAAC;AAErB,qBAAa,SAAU,SAAQ,KAAK;IAClC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;gBAEjB,IAAI,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,MAAM;CAKlD"}
|
package/dist/spec.md
CHANGED
|
@@ -95,6 +95,8 @@ export type CustomDataValue = JSONArray | JSONObject
|
|
|
95
95
|
- `event: error` → `{ message: string, code?: string }`
|
|
96
96
|
- `event: done` → `{ finished_reason: "length" | "stop" | "content_filter" | null }`
|
|
97
97
|
|
|
98
|
+
クライアントの完了判定は `done` イベント受信時のみ成功です。`error` も `done` もないまま接続が EOF した場合、クライアントは成功扱いせず `ChatError("unexpected_eof")` として `status: "error"` に遷移します。このとき、途中まで受信した assistant テキストは保持されます。
|
|
99
|
+
|
|
98
100
|
|
|
99
101
|
---
|
|
100
102
|
|
|
@@ -398,14 +400,17 @@ type UseChatSessionReturn = {
|
|
|
398
400
|
status: ChatStatus
|
|
399
401
|
/**
|
|
400
402
|
* 既知ケースでは ChatError が入る(Error のサブクラス)。
|
|
401
|
-
* - code: "content_filter" | "aborted" | "no_response"
|
|
403
|
+
* - code: "content_filter" | "aborted" | "no_response" | "unexpected_eof"
|
|
402
404
|
*/
|
|
403
405
|
error: Error | null
|
|
404
406
|
/**
|
|
405
|
-
* API を呼ばずに現在のセッションの messages
|
|
407
|
+
* API を呼ばずに現在のセッションの messages を即時更新する。
|
|
406
408
|
* 内部的に messagesVersion がインクリメントされる。
|
|
407
409
|
*/
|
|
408
|
-
setMessages: (
|
|
410
|
+
setMessages: (
|
|
411
|
+
updater: (prev: Message[]) => Message[],
|
|
412
|
+
options?: { resetStatus?: boolean }
|
|
413
|
+
) => void
|
|
409
414
|
sendMessage: (content: string, params?: { body?: Record<string, JSONValue>; dropFromMessageId?: string }) => Promise<void>
|
|
410
415
|
reload: (params?: { body?: Record<string, JSONValue> }) => Promise<void>
|
|
411
416
|
stop: () => void
|
|
@@ -438,9 +443,10 @@ await Promise.all([
|
|
|
438
443
|
- `reload` は **最後の user 以降** を削除して再送します(再試行・プロンプト修正に有用)。
|
|
439
444
|
- `stop` は現在のストリームを中断します。
|
|
440
445
|
- `stopAll` はアクティブな全ストリーム(submitted/streaming 状態)を中断します。ページ離脱やグローバルなキャンセルボタンで利用できます。
|
|
441
|
-
- `setMessages` は **API 呼び出しを行わず**、現在のセッションの `messages`
|
|
446
|
+
- `setMessages` は **API 呼び出しを行わず**、現在のセッションの `messages` を即時更新します。`updater(prev)` は常にその時点の最新 `messages` を受け取り、戻り値が同一参照でも `messagesVersion` はインクリメントされます。UI に即時反映されます。
|
|
442
447
|
- 通常は `status` を変更しません(例: ローカルでの編集や一時的な整形結果の反映に使用)。
|
|
443
448
|
- `options.resetStatus` を指定すると `status/error/finishedReason/nextAssistantMessageId` を初期化します(`submitted/streaming` 中は無視)。
|
|
449
|
+
- 未初期化のセッションに対して呼ぶと `Error("Session not initialized: <sessionId>")` を投げます。自動初期化は行いません。
|
|
444
450
|
- **SPA 内のページ遷移ではストリーム継続**。Provider 配下から外れても、再マウント時に最新スナップショットを購読し直します。
|
|
445
451
|
- **セッション数制限**: メモリ使用量を抑えるため、最大セッション数を制限(デフォルト: 5)。上限に達すると LRU 方式で最も古いセッションを自動削除。ストリーミング中のセッションは削除対象から優先的に除外。
|
|
446
452
|
- **メモ化のコツ**: ストリーミング中は各チャンクで `messages` 参照が更新されるため、`useMemo(..., [messages])` で確実に再評価されます。より厳密な制御が必要な場合は `messagesVersion` を依存に加えることもできます。
|
|
@@ -453,7 +459,7 @@ await Promise.all([
|
|
|
453
459
|
- 完了時は常に最新を呼ぶ: ストリーム完了時は常に最新の `onFinish` が呼ばれます。コンポーネントがアンマウント済み(購読 0)でも呼ばれます。
|
|
454
460
|
- `onFinish` の `details.metadata` は、そのストリーム中に受信したメタデータの最新スナップショットです。
|
|
455
461
|
- 複数購読時の優先: 同一 `sessionId` を複数コンポーネントが使用する場合、最後に登録された `onFinish` が有効です。
|
|
456
|
-
- `onError`
|
|
462
|
+
- `onError` もセッション単位で「最新のみ」を保持し、エラー時は常にその最新ハンドラを呼びます。`done` なし EOF では `ChatError("unexpected_eof")` が渡され、`onFinish` は呼ばれません。
|
|
457
463
|
|
|
458
464
|
|
|
459
465
|
### ページ遷移前のセッション事前準備(`usePrefetchChatSession`)
|