@mordn/chat-widget 0.9.0 → 0.10.1
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/{chat-store-DdykLpDo.d.mts → chat-store-Dq1Zy_qV.d.mts} +1 -1
- package/dist/{chat-store-DdykLpDo.d.ts → chat-store-Dq1Zy_qV.d.ts} +1 -1
- package/dist/handler-types-Bil94kTX.d.ts +204 -0
- package/dist/handler-types-CCSjDZZ9.d.mts +204 -0
- package/dist/index.d.mts +44 -5
- package/dist/index.d.ts +44 -5
- package/dist/index.js +127 -80
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +127 -81
- package/dist/index.mjs.map +1 -1
- package/dist/models.d.mts +6 -0
- package/dist/models.d.ts +6 -0
- package/dist/models.js +75 -0
- package/dist/models.js.map +1 -0
- package/dist/models.mjs +50 -0
- package/dist/models.mjs.map +1 -0
- package/dist/server/drizzle/index.d.mts +1 -1
- package/dist/server/drizzle/index.d.ts +1 -1
- package/dist/server/hosted/index.d.mts +14 -2
- package/dist/server/hosted/index.d.ts +14 -2
- package/dist/server/hosted/index.js +36 -0
- package/dist/server/hosted/index.js.map +1 -1
- package/dist/server/hosted/index.mjs +35 -0
- package/dist/server/hosted/index.mjs.map +1 -1
- package/dist/server/index.d.mts +6 -180
- package/dist/server/index.d.ts +6 -180
- package/dist/server/index.js +26 -11
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +26 -11
- package/dist/server/index.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +6 -1
package/dist/server/index.d.mts
CHANGED
|
@@ -1,182 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
export {
|
|
3
|
-
import {
|
|
4
|
-
export {
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Public configuration surface for `createChatHandler`.
|
|
9
|
-
*
|
|
10
|
-
* This is the API a host app touches to mount the chat backend. The design
|
|
11
|
-
* follows one rule, derived from auditing a real power-user integration
|
|
12
|
-
* (Jarvis): take away the shared, dangerous-to-get-wrong plumbing; keep every
|
|
13
|
-
* point of genuine per-app variation as an injection point or a hook.
|
|
14
|
-
*
|
|
15
|
-
* Three tiers of override, from "you must" to "you rarely will":
|
|
16
|
-
*
|
|
17
|
-
* REQUIRED injections — no safe default exists:
|
|
18
|
-
* • getUserId (identity; the security boundary)
|
|
19
|
-
*
|
|
20
|
-
* OPTIONAL injections — a default exists, swap to take control:
|
|
21
|
-
* • model (which LLM)
|
|
22
|
-
* • buildTools (your tools, incl. per-request resources)
|
|
23
|
-
* • store (persistence; hosted default)
|
|
24
|
-
* • storage (attachments; hosted default)
|
|
25
|
-
*
|
|
26
|
-
* HOOKS — the loop runs fine without them; override one seam at a time:
|
|
27
|
-
* • buildSystemPrompt, transformMessages, onChatFinish, onError,
|
|
28
|
-
* stopWhen, upload
|
|
29
|
-
*
|
|
30
|
-
* Everything NOT in this file — ownership checks, idempotency, pagination,
|
|
31
|
-
* re-signing, socket teardown, save-on-finish — is owned by the handler and
|
|
32
|
-
* is intentionally not configurable, because getting it wrong is a security
|
|
33
|
-
* or correctness bug, not a preference.
|
|
34
|
-
*/
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Everything a per-request hook/injection needs to know about the current
|
|
38
|
-
* request, assembled by the handler AFTER authentication. Passed to
|
|
39
|
-
* `buildTools`, `model` (when a function), `buildSystemPrompt`, and
|
|
40
|
-
* `transformMessages`.
|
|
41
|
-
*
|
|
42
|
-
* Note `userId` is the server-verified identity — the same value the store
|
|
43
|
-
* and storage are bound to. Hooks can trust it.
|
|
44
|
-
*/
|
|
45
|
-
interface ChatRequestContext {
|
|
46
|
-
/** Server-verified user id. Never client-supplied. */
|
|
47
|
-
userId: string;
|
|
48
|
-
/** The conversation this request targets. */
|
|
49
|
-
conversationId: string;
|
|
50
|
-
/** The raw request, for hooks that need headers/cookies (e.g. an org id). */
|
|
51
|
-
request: Request;
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* What `buildTools` returns. The `cleanup` callback is the critical piece the
|
|
55
|
-
* naive "just return a ToolSet" design misses: tools backed by a per-request
|
|
56
|
-
* resource (an MCP client holding a socket, a DB transaction, a temp scope)
|
|
57
|
-
* MUST be torn down after the stream finishes — exactly once, whether the
|
|
58
|
-
* stream completed, errored, or the client aborted. The handler guarantees
|
|
59
|
-
* that single, correctly-timed call so the host app never leaks sockets.
|
|
60
|
-
*/
|
|
61
|
-
interface BuiltTools {
|
|
62
|
-
tools: ToolSet;
|
|
63
|
-
/**
|
|
64
|
-
* Called exactly once when the request is fully done (success, error, or
|
|
65
|
-
* abort), after the response stream has settled. Optional — omit when your
|
|
66
|
-
* tools hold no per-request resource.
|
|
67
|
-
*/
|
|
68
|
-
cleanup?: () => void | Promise<void>;
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Server-side upload policy. Enforced by the handler's upload route BEFORE
|
|
72
|
-
* any bytes touch storage, so an oversized or disallowed file is rejected
|
|
73
|
-
* with a clean 4xx instead of a framework body-parse failure. The widget's
|
|
74
|
-
* client-side `accept`/`maxBytes` should mirror these, but the SERVER is the
|
|
75
|
-
* source of truth — the client checks are UX, these checks are the boundary.
|
|
76
|
-
*/
|
|
77
|
-
interface UploadPolicy {
|
|
78
|
-
/**
|
|
79
|
-
* Allowed MIME types. An exact-match allow-list (not a prefix match) so
|
|
80
|
-
* `image/svg+xml` can be excluded while `image/png` is allowed. Defaults to
|
|
81
|
-
* a conservative image+pdf set that current vision models accept natively.
|
|
82
|
-
*/
|
|
83
|
-
allowedMediaTypes?: string[];
|
|
84
|
-
/** Per-file size cap in bytes. Defaults to 5 MB. */
|
|
85
|
-
maxBytes?: number;
|
|
86
|
-
}
|
|
87
|
-
interface CreateChatHandlerOptions {
|
|
88
|
-
/**
|
|
89
|
-
* Derive the authenticated user's id from the SERVER session — a verified
|
|
90
|
-
* cookie/JWT, Clerk `auth()`, NextAuth `getServerSession()`,
|
|
91
|
-
* `supabase.auth.getUser()`, etc. Return `null` for an unauthenticated
|
|
92
|
-
* request; the handler responds 401.
|
|
93
|
-
*
|
|
94
|
-
* SECURITY: never read the id from the request body, query string, or a
|
|
95
|
-
* header the browser controls (e.g. `X-User-Id`). Those are forgeable and
|
|
96
|
-
* doing so reintroduces the IDOR this whole design exists to prevent. The
|
|
97
|
-
* handler passes you the `Request` so you can read *verified* cookies — not
|
|
98
|
-
* so you can read a client-asserted id.
|
|
99
|
-
*/
|
|
100
|
-
getUserId: (request: Request) => Promise<string | null> | string | null;
|
|
101
|
-
/**
|
|
102
|
-
* The model to stream from. Either a fixed `LanguageModel` or a function of
|
|
103
|
-
* the request context (for per-user/per-org model selection). Defaults to a
|
|
104
|
-
* sensible current model when omitted.
|
|
105
|
-
*/
|
|
106
|
-
model?: LanguageModel | ((ctx: ChatRequestContext) => LanguageModel | Promise<LanguageModel>);
|
|
107
|
-
/**
|
|
108
|
-
* Build the tool set for this request. Async and context-aware so tools can
|
|
109
|
-
* close over the user and open per-request resources (e.g. an MCP client).
|
|
110
|
-
* Return `{ tools, cleanup }`; the handler calls `cleanup` exactly once when
|
|
111
|
-
* the request settles. Omit for a chat with no tools.
|
|
112
|
-
*/
|
|
113
|
-
buildTools?: (ctx: ChatRequestContext) => Promise<BuiltTools> | BuiltTools;
|
|
114
|
-
/**
|
|
115
|
-
* Persistence backend. Omit to use the hosted/default store. Provide a
|
|
116
|
-
* factory to bring your own DB. The factory is called per request with the
|
|
117
|
-
* server-verified `userId`; the handler never constructs a store with a
|
|
118
|
-
* client-supplied id.
|
|
119
|
-
*/
|
|
120
|
-
store?: ChatStoreFactory;
|
|
121
|
-
/**
|
|
122
|
-
* Attachment storage backend. Omit to use the hosted/default adapter.
|
|
123
|
-
* Provide a factory for BYO storage (S3/R2/own bucket). Same per-request,
|
|
124
|
-
* verified-userId construction as `store`.
|
|
125
|
-
*/
|
|
126
|
-
storage?: StorageAdapterFactory;
|
|
127
|
-
/**
|
|
128
|
-
* Produce the system prompt for this request. Receives the context so it
|
|
129
|
-
* can personalise (e.g. bake in the user's name). Defaults to a generic
|
|
130
|
-
* assistant prompt.
|
|
131
|
-
*/
|
|
132
|
-
buildSystemPrompt?: (ctx: ChatRequestContext) => string | Promise<string>;
|
|
133
|
-
/**
|
|
134
|
-
* Last-chance transform of the model-ready messages before they're sent to
|
|
135
|
-
* the model — after the handler has applied its own sliding-window prune.
|
|
136
|
-
* Use for provider-specific rewrites (e.g. image file-parts → image-parts)
|
|
137
|
-
* or extra capping. Defaults to identity.
|
|
138
|
-
*/
|
|
139
|
-
transformMessages?: (messages: ModelMessage[], ctx: ChatRequestContext) => ModelMessage[] | Promise<ModelMessage[]>;
|
|
140
|
-
/**
|
|
141
|
-
* Called after the assistant turn has been persisted. For telemetry/usage
|
|
142
|
-
* logging. NOT where you save messages — the handler already did that. Any
|
|
143
|
-
* error thrown here is logged and swallowed; it never fails the response
|
|
144
|
-
* (the user already has their answer).
|
|
145
|
-
*/
|
|
146
|
-
onChatFinish?: (info: {
|
|
147
|
-
ctx: ChatRequestContext;
|
|
148
|
-
messages: UIMessage[];
|
|
149
|
-
usage?: unknown;
|
|
150
|
-
providerMetadata?: unknown;
|
|
151
|
-
}) => void | Promise<void>;
|
|
152
|
-
/**
|
|
153
|
-
* Map a stream error to the user-facing string the widget shows. Lets you
|
|
154
|
-
* downgrade benign post-finish teardown noise and localise messages.
|
|
155
|
-
* Defaults to a generic message + server-side error log.
|
|
156
|
-
*/
|
|
157
|
-
onError?: (error: unknown) => string;
|
|
158
|
-
/**
|
|
159
|
-
* When the model may chain tool calls, how long to let it run before it
|
|
160
|
-
* must answer. Defaults to a bounded step count so a misbehaving tool loop
|
|
161
|
-
* can't run forever. Pass any AI SDK `StopCondition`.
|
|
162
|
-
*/
|
|
163
|
-
stopWhen?: StopCondition<ToolSet>;
|
|
164
|
-
/** Server-side upload policy (types + size). See `UploadPolicy`. */
|
|
165
|
-
upload?: UploadPolicy;
|
|
166
|
-
/**
|
|
167
|
-
* How many of the most-recent messages to send to the model (sliding
|
|
168
|
-
* window). Defaults to 30. The handler always prunes; this tunes the
|
|
169
|
-
* window. Older messages stay in the store and in the UI — only the model
|
|
170
|
-
* payload is windowed.
|
|
171
|
-
*/
|
|
172
|
-
maxHistoryMessages?: number;
|
|
173
|
-
/**
|
|
174
|
-
* Defensive per-message character cap applied during pruning so a single
|
|
175
|
-
* giant pasted blob can't dominate the context window. Defaults to 4000.
|
|
176
|
-
* Set to `0` to disable.
|
|
177
|
-
*/
|
|
178
|
-
maxMessageChars?: number;
|
|
179
|
-
}
|
|
1
|
+
export { C as ChatStore, d as ChatStoreFactory, e as ConversationOwnershipError, L as ListMessagesOptions, c as SaveTurnInput, S as StoredAttachment, a as StoredConversation, b as StoredMessage } from '../chat-store-Dq1Zy_qV.mjs';
|
|
2
|
+
export { S as StorageAdapter, a as StorageAdapterFactory, U as UploadInput, b as UploadResult } from '../storage-adapter-DD8uqiAP.mjs';
|
|
3
|
+
import { C as CreateChatHandlerOptions } from '../handler-types-CCSjDZZ9.mjs';
|
|
4
|
+
export { B as BuiltTools, a as ChatRequestContext, H as HostedAgentConfig, U as UploadPolicy } from '../handler-types-CCSjDZZ9.mjs';
|
|
5
|
+
import 'ai';
|
|
180
6
|
|
|
181
7
|
/**
|
|
182
8
|
* createChatHandler — the request router and the "OWN loop".
|
|
@@ -214,4 +40,4 @@ declare function createChatHandler(options: CreateChatHandlerOptions): {
|
|
|
214
40
|
DELETE: (request: Request) => Promise<Response>;
|
|
215
41
|
};
|
|
216
42
|
|
|
217
|
-
export {
|
|
43
|
+
export { CreateChatHandlerOptions, createChatHandler };
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,182 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
export {
|
|
3
|
-
import {
|
|
4
|
-
export {
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Public configuration surface for `createChatHandler`.
|
|
9
|
-
*
|
|
10
|
-
* This is the API a host app touches to mount the chat backend. The design
|
|
11
|
-
* follows one rule, derived from auditing a real power-user integration
|
|
12
|
-
* (Jarvis): take away the shared, dangerous-to-get-wrong plumbing; keep every
|
|
13
|
-
* point of genuine per-app variation as an injection point or a hook.
|
|
14
|
-
*
|
|
15
|
-
* Three tiers of override, from "you must" to "you rarely will":
|
|
16
|
-
*
|
|
17
|
-
* REQUIRED injections — no safe default exists:
|
|
18
|
-
* • getUserId (identity; the security boundary)
|
|
19
|
-
*
|
|
20
|
-
* OPTIONAL injections — a default exists, swap to take control:
|
|
21
|
-
* • model (which LLM)
|
|
22
|
-
* • buildTools (your tools, incl. per-request resources)
|
|
23
|
-
* • store (persistence; hosted default)
|
|
24
|
-
* • storage (attachments; hosted default)
|
|
25
|
-
*
|
|
26
|
-
* HOOKS — the loop runs fine without them; override one seam at a time:
|
|
27
|
-
* • buildSystemPrompt, transformMessages, onChatFinish, onError,
|
|
28
|
-
* stopWhen, upload
|
|
29
|
-
*
|
|
30
|
-
* Everything NOT in this file — ownership checks, idempotency, pagination,
|
|
31
|
-
* re-signing, socket teardown, save-on-finish — is owned by the handler and
|
|
32
|
-
* is intentionally not configurable, because getting it wrong is a security
|
|
33
|
-
* or correctness bug, not a preference.
|
|
34
|
-
*/
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Everything a per-request hook/injection needs to know about the current
|
|
38
|
-
* request, assembled by the handler AFTER authentication. Passed to
|
|
39
|
-
* `buildTools`, `model` (when a function), `buildSystemPrompt`, and
|
|
40
|
-
* `transformMessages`.
|
|
41
|
-
*
|
|
42
|
-
* Note `userId` is the server-verified identity — the same value the store
|
|
43
|
-
* and storage are bound to. Hooks can trust it.
|
|
44
|
-
*/
|
|
45
|
-
interface ChatRequestContext {
|
|
46
|
-
/** Server-verified user id. Never client-supplied. */
|
|
47
|
-
userId: string;
|
|
48
|
-
/** The conversation this request targets. */
|
|
49
|
-
conversationId: string;
|
|
50
|
-
/** The raw request, for hooks that need headers/cookies (e.g. an org id). */
|
|
51
|
-
request: Request;
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* What `buildTools` returns. The `cleanup` callback is the critical piece the
|
|
55
|
-
* naive "just return a ToolSet" design misses: tools backed by a per-request
|
|
56
|
-
* resource (an MCP client holding a socket, a DB transaction, a temp scope)
|
|
57
|
-
* MUST be torn down after the stream finishes — exactly once, whether the
|
|
58
|
-
* stream completed, errored, or the client aborted. The handler guarantees
|
|
59
|
-
* that single, correctly-timed call so the host app never leaks sockets.
|
|
60
|
-
*/
|
|
61
|
-
interface BuiltTools {
|
|
62
|
-
tools: ToolSet;
|
|
63
|
-
/**
|
|
64
|
-
* Called exactly once when the request is fully done (success, error, or
|
|
65
|
-
* abort), after the response stream has settled. Optional — omit when your
|
|
66
|
-
* tools hold no per-request resource.
|
|
67
|
-
*/
|
|
68
|
-
cleanup?: () => void | Promise<void>;
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Server-side upload policy. Enforced by the handler's upload route BEFORE
|
|
72
|
-
* any bytes touch storage, so an oversized or disallowed file is rejected
|
|
73
|
-
* with a clean 4xx instead of a framework body-parse failure. The widget's
|
|
74
|
-
* client-side `accept`/`maxBytes` should mirror these, but the SERVER is the
|
|
75
|
-
* source of truth — the client checks are UX, these checks are the boundary.
|
|
76
|
-
*/
|
|
77
|
-
interface UploadPolicy {
|
|
78
|
-
/**
|
|
79
|
-
* Allowed MIME types. An exact-match allow-list (not a prefix match) so
|
|
80
|
-
* `image/svg+xml` can be excluded while `image/png` is allowed. Defaults to
|
|
81
|
-
* a conservative image+pdf set that current vision models accept natively.
|
|
82
|
-
*/
|
|
83
|
-
allowedMediaTypes?: string[];
|
|
84
|
-
/** Per-file size cap in bytes. Defaults to 5 MB. */
|
|
85
|
-
maxBytes?: number;
|
|
86
|
-
}
|
|
87
|
-
interface CreateChatHandlerOptions {
|
|
88
|
-
/**
|
|
89
|
-
* Derive the authenticated user's id from the SERVER session — a verified
|
|
90
|
-
* cookie/JWT, Clerk `auth()`, NextAuth `getServerSession()`,
|
|
91
|
-
* `supabase.auth.getUser()`, etc. Return `null` for an unauthenticated
|
|
92
|
-
* request; the handler responds 401.
|
|
93
|
-
*
|
|
94
|
-
* SECURITY: never read the id from the request body, query string, or a
|
|
95
|
-
* header the browser controls (e.g. `X-User-Id`). Those are forgeable and
|
|
96
|
-
* doing so reintroduces the IDOR this whole design exists to prevent. The
|
|
97
|
-
* handler passes you the `Request` so you can read *verified* cookies — not
|
|
98
|
-
* so you can read a client-asserted id.
|
|
99
|
-
*/
|
|
100
|
-
getUserId: (request: Request) => Promise<string | null> | string | null;
|
|
101
|
-
/**
|
|
102
|
-
* The model to stream from. Either a fixed `LanguageModel` or a function of
|
|
103
|
-
* the request context (for per-user/per-org model selection). Defaults to a
|
|
104
|
-
* sensible current model when omitted.
|
|
105
|
-
*/
|
|
106
|
-
model?: LanguageModel | ((ctx: ChatRequestContext) => LanguageModel | Promise<LanguageModel>);
|
|
107
|
-
/**
|
|
108
|
-
* Build the tool set for this request. Async and context-aware so tools can
|
|
109
|
-
* close over the user and open per-request resources (e.g. an MCP client).
|
|
110
|
-
* Return `{ tools, cleanup }`; the handler calls `cleanup` exactly once when
|
|
111
|
-
* the request settles. Omit for a chat with no tools.
|
|
112
|
-
*/
|
|
113
|
-
buildTools?: (ctx: ChatRequestContext) => Promise<BuiltTools> | BuiltTools;
|
|
114
|
-
/**
|
|
115
|
-
* Persistence backend. Omit to use the hosted/default store. Provide a
|
|
116
|
-
* factory to bring your own DB. The factory is called per request with the
|
|
117
|
-
* server-verified `userId`; the handler never constructs a store with a
|
|
118
|
-
* client-supplied id.
|
|
119
|
-
*/
|
|
120
|
-
store?: ChatStoreFactory;
|
|
121
|
-
/**
|
|
122
|
-
* Attachment storage backend. Omit to use the hosted/default adapter.
|
|
123
|
-
* Provide a factory for BYO storage (S3/R2/own bucket). Same per-request,
|
|
124
|
-
* verified-userId construction as `store`.
|
|
125
|
-
*/
|
|
126
|
-
storage?: StorageAdapterFactory;
|
|
127
|
-
/**
|
|
128
|
-
* Produce the system prompt for this request. Receives the context so it
|
|
129
|
-
* can personalise (e.g. bake in the user's name). Defaults to a generic
|
|
130
|
-
* assistant prompt.
|
|
131
|
-
*/
|
|
132
|
-
buildSystemPrompt?: (ctx: ChatRequestContext) => string | Promise<string>;
|
|
133
|
-
/**
|
|
134
|
-
* Last-chance transform of the model-ready messages before they're sent to
|
|
135
|
-
* the model — after the handler has applied its own sliding-window prune.
|
|
136
|
-
* Use for provider-specific rewrites (e.g. image file-parts → image-parts)
|
|
137
|
-
* or extra capping. Defaults to identity.
|
|
138
|
-
*/
|
|
139
|
-
transformMessages?: (messages: ModelMessage[], ctx: ChatRequestContext) => ModelMessage[] | Promise<ModelMessage[]>;
|
|
140
|
-
/**
|
|
141
|
-
* Called after the assistant turn has been persisted. For telemetry/usage
|
|
142
|
-
* logging. NOT where you save messages — the handler already did that. Any
|
|
143
|
-
* error thrown here is logged and swallowed; it never fails the response
|
|
144
|
-
* (the user already has their answer).
|
|
145
|
-
*/
|
|
146
|
-
onChatFinish?: (info: {
|
|
147
|
-
ctx: ChatRequestContext;
|
|
148
|
-
messages: UIMessage[];
|
|
149
|
-
usage?: unknown;
|
|
150
|
-
providerMetadata?: unknown;
|
|
151
|
-
}) => void | Promise<void>;
|
|
152
|
-
/**
|
|
153
|
-
* Map a stream error to the user-facing string the widget shows. Lets you
|
|
154
|
-
* downgrade benign post-finish teardown noise and localise messages.
|
|
155
|
-
* Defaults to a generic message + server-side error log.
|
|
156
|
-
*/
|
|
157
|
-
onError?: (error: unknown) => string;
|
|
158
|
-
/**
|
|
159
|
-
* When the model may chain tool calls, how long to let it run before it
|
|
160
|
-
* must answer. Defaults to a bounded step count so a misbehaving tool loop
|
|
161
|
-
* can't run forever. Pass any AI SDK `StopCondition`.
|
|
162
|
-
*/
|
|
163
|
-
stopWhen?: StopCondition<ToolSet>;
|
|
164
|
-
/** Server-side upload policy (types + size). See `UploadPolicy`. */
|
|
165
|
-
upload?: UploadPolicy;
|
|
166
|
-
/**
|
|
167
|
-
* How many of the most-recent messages to send to the model (sliding
|
|
168
|
-
* window). Defaults to 30. The handler always prunes; this tunes the
|
|
169
|
-
* window. Older messages stay in the store and in the UI — only the model
|
|
170
|
-
* payload is windowed.
|
|
171
|
-
*/
|
|
172
|
-
maxHistoryMessages?: number;
|
|
173
|
-
/**
|
|
174
|
-
* Defensive per-message character cap applied during pruning so a single
|
|
175
|
-
* giant pasted blob can't dominate the context window. Defaults to 4000.
|
|
176
|
-
* Set to `0` to disable.
|
|
177
|
-
*/
|
|
178
|
-
maxMessageChars?: number;
|
|
179
|
-
}
|
|
1
|
+
export { C as ChatStore, d as ChatStoreFactory, e as ConversationOwnershipError, L as ListMessagesOptions, c as SaveTurnInput, S as StoredAttachment, a as StoredConversation, b as StoredMessage } from '../chat-store-Dq1Zy_qV.js';
|
|
2
|
+
export { S as StorageAdapter, a as StorageAdapterFactory, U as UploadInput, b as UploadResult } from '../storage-adapter-DD8uqiAP.js';
|
|
3
|
+
import { C as CreateChatHandlerOptions } from '../handler-types-Bil94kTX.js';
|
|
4
|
+
export { B as BuiltTools, a as ChatRequestContext, H as HostedAgentConfig, U as UploadPolicy } from '../handler-types-Bil94kTX.js';
|
|
5
|
+
import 'ai';
|
|
180
6
|
|
|
181
7
|
/**
|
|
182
8
|
* createChatHandler — the request router and the "OWN loop".
|
|
@@ -214,4 +40,4 @@ declare function createChatHandler(options: CreateChatHandlerOptions): {
|
|
|
214
40
|
DELETE: (request: Request) => Promise<Response>;
|
|
215
41
|
};
|
|
216
42
|
|
|
217
|
-
export {
|
|
43
|
+
export { CreateChatHandlerOptions, createChatHandler };
|
package/dist/server/index.js
CHANGED
|
@@ -51,17 +51,23 @@ var DEFAULT_ALLOWED_MEDIA_TYPES = [
|
|
|
51
51
|
];
|
|
52
52
|
var DEFAULT_SYSTEM_PROMPT = "You are a helpful assistant.";
|
|
53
53
|
var KNOWN_SEGMENTS = /* @__PURE__ */ new Set(["upload", "history"]);
|
|
54
|
-
function json(body, status = 200) {
|
|
54
|
+
function json(body, status = 200, extraHeaders) {
|
|
55
55
|
return new Response(JSON.stringify(body), {
|
|
56
56
|
status,
|
|
57
|
-
headers: { "Content-Type": "application/json" }
|
|
57
|
+
headers: { "Content-Type": "application/json", ...extraHeaders }
|
|
58
58
|
});
|
|
59
59
|
}
|
|
60
|
+
function jsonNoStore(body, status = 200) {
|
|
61
|
+
return json(body, status, { "Cache-Control": "no-store, private" });
|
|
62
|
+
}
|
|
60
63
|
function subSegments(url) {
|
|
61
64
|
const parts = url.pathname.split("/").filter(Boolean);
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
for (let i = parts.length - 1; i >= 0; i--) {
|
|
66
|
+
if (KNOWN_SEGMENTS.has(parts[i])) {
|
|
67
|
+
return parts.slice(i);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return [];
|
|
65
71
|
}
|
|
66
72
|
function createChatHandler(options) {
|
|
67
73
|
const {
|
|
@@ -71,6 +77,7 @@ function createChatHandler(options) {
|
|
|
71
77
|
store: storeFactory,
|
|
72
78
|
storage: storageFactory,
|
|
73
79
|
buildSystemPrompt,
|
|
80
|
+
getHostedConfig,
|
|
74
81
|
transformMessages,
|
|
75
82
|
onChatFinish,
|
|
76
83
|
onError,
|
|
@@ -89,11 +96,12 @@ function createChatHandler(options) {
|
|
|
89
96
|
if (storageFactory) return storageFactory(userId);
|
|
90
97
|
return null;
|
|
91
98
|
}
|
|
92
|
-
async function resolveModel(ctx) {
|
|
99
|
+
async function resolveModel(ctx, hostedModel) {
|
|
93
100
|
if (typeof modelOption === "function") return modelOption(ctx);
|
|
94
101
|
if (modelOption) return modelOption;
|
|
102
|
+
if (hostedModel) return hostedModel;
|
|
95
103
|
throw new Error(
|
|
96
|
-
"[chat-widget] No `model` provided. Pass a `model` (a LanguageModel or a function returning one)."
|
|
104
|
+
"[chat-widget] No `model` provided. Pass a `model` (a LanguageModel or a function returning one), or configure one via hosted config."
|
|
97
105
|
);
|
|
98
106
|
}
|
|
99
107
|
async function authenticate(request, conversationId) {
|
|
@@ -134,9 +142,16 @@ function createChatHandler(options) {
|
|
|
134
142
|
if (transformMessages) modelMessages = await transformMessages(modelMessages, ctx);
|
|
135
143
|
const built = buildTools ? await buildTools(ctx) : { tools: {} };
|
|
136
144
|
const tools = built.tools ?? {};
|
|
137
|
-
const
|
|
145
|
+
const hosted = getHostedConfig ? await (async () => {
|
|
146
|
+
try {
|
|
147
|
+
return await getHostedConfig(ctx);
|
|
148
|
+
} catch {
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
})() : null;
|
|
152
|
+
const model = await resolveModel(ctx, hosted?.model);
|
|
138
153
|
const modelLabel = typeof model === "string" ? model : model.modelId;
|
|
139
|
-
const system = buildSystemPrompt ? await buildSystemPrompt(ctx) : DEFAULT_SYSTEM_PROMPT;
|
|
154
|
+
const system = buildSystemPrompt ? await buildSystemPrompt(ctx) : hosted?.systemPrompt ?? DEFAULT_SYSTEM_PROMPT;
|
|
140
155
|
let cleanedUp = false;
|
|
141
156
|
const runCleanup = async (reason) => {
|
|
142
157
|
if (cleanedUp || !built.cleanup) return;
|
|
@@ -213,7 +228,7 @@ function createChatHandler(options) {
|
|
|
213
228
|
if (!ctx) return new Response("Unauthorized", { status: 401 });
|
|
214
229
|
const store = resolveStore(ctx.userId);
|
|
215
230
|
const conversations = await store.listConversations();
|
|
216
|
-
return
|
|
231
|
+
return jsonNoStore({
|
|
217
232
|
conversations: conversations.map((c) => ({
|
|
218
233
|
id: c.id,
|
|
219
234
|
title: c.title,
|
|
@@ -237,7 +252,7 @@ function createChatHandler(options) {
|
|
|
237
252
|
if (!conversation) return json({ error: "Conversation not found" }, 404);
|
|
238
253
|
const messages = await store.listMessages(conversationId, { limit: 100 });
|
|
239
254
|
const rehydrated = storage ? await Promise.all(messages.map((m) => resignMessageAttachments(m, storage))) : messages;
|
|
240
|
-
return
|
|
255
|
+
return jsonNoStore({
|
|
241
256
|
conversation: {
|
|
242
257
|
id: conversation.id,
|
|
243
258
|
title: conversation.title,
|