@frontera-sdk/chat 1.52.45 → 1.52.47

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.
Files changed (51) hide show
  1. package/dist/auth.d.ts +20 -0
  2. package/dist/auth.js +11 -0
  3. package/dist/callback-page.d.ts +49 -0
  4. package/dist/callback-page.js +84 -0
  5. package/dist/chat-client.d.ts +221 -0
  6. package/dist/chat-client.js +5 -0
  7. package/dist/chat-errors.d.ts +30 -0
  8. package/dist/chat-errors.js +3 -0
  9. package/dist/chunk-CMMWTCYS.js +116 -0
  10. package/dist/chunk-KZEGEV3P.js +35 -0
  11. package/dist/chunk-LS26G2N6.js +120 -0
  12. package/dist/chunk-RLHHRJWS.js +371 -0
  13. package/dist/chunk-UCUVHMJC.js +62 -0
  14. package/dist/chunk-VWUR3ECR.js +115 -0
  15. package/dist/chunk-W25Q2DQA.js +32 -0
  16. package/dist/chunk-YKQ5Z5EK.js +32 -0
  17. package/dist/connect-popup.d.ts +150 -0
  18. package/dist/connect-popup.js +138 -0
  19. package/dist/doctor.d.ts +71 -0
  20. package/dist/doctor.js +3 -0
  21. package/dist/element.d.ts +23 -0
  22. package/dist/element.js +175 -0
  23. package/dist/frontera-chat.iife.js +27 -0
  24. package/dist/hooks.d.ts +88 -0
  25. package/dist/hooks.js +3 -0
  26. package/dist/provider.d.ts +20 -0
  27. package/dist/provider.js +13 -0
  28. package/dist/public-chat.d.ts +50 -0
  29. package/dist/public-chat.js +6 -0
  30. package/dist/public-token.d.ts +46 -0
  31. package/dist/public-token.js +3 -0
  32. package/dist/reply-text.d.ts +25 -0
  33. package/dist/reply-text.js +3 -0
  34. package/dist/stream.d.ts +25 -0
  35. package/dist/stream.js +3 -0
  36. package/dist/token-session.d.ts +66 -0
  37. package/dist/token-session.js +99 -0
  38. package/dist/transport.d.ts +60 -0
  39. package/dist/transport.js +103 -0
  40. package/dist/types.d.ts +361 -0
  41. package/dist/types.js +3 -0
  42. package/dist/ui-stream.d.ts +25 -0
  43. package/dist/ui-stream.js +26 -0
  44. package/package.json +70 -30
  45. package/src/chat-errors.ts +43 -0
  46. package/src/element.ts +201 -0
  47. package/src/frontera-chat.global.ts +13 -0
  48. package/src/public-chat.ts +154 -0
  49. package/src/public-token.ts +36 -4
  50. package/src/reply-text.ts +49 -0
  51. package/src/transport.ts +7 -1
package/dist/auth.d.ts ADDED
@@ -0,0 +1,20 @@
1
+ import { FronteraClient } from '@frontera-sdk/core/client';
2
+ import { ExchangeTokenRequest, ChatToken } from './types.js';
3
+
4
+ /**
5
+ * Exchange an agent API key (`sak_`) plus your user's identity for a
6
+ * short-lived scoped chat token (`cht_`). Server-side only: the client passed
7
+ * here must carry the `sak_` credential, which must never reach a browser.
8
+ *
9
+ * The token is safe to hand to your frontend — it is scoped to one workspace,
10
+ * one agent and one external user, and Sebati enforces session isolation per
11
+ * external user.
12
+ *
13
+ * Requires a deployment with the `/v1/chat-tokens` endpoint; older deployments
14
+ * answer 404, surfaced as a `FronteraError` with code `NOT_FOUND`.
15
+ */
16
+ declare function exchangeChatToken(client: FronteraClient, request: ExchangeTokenRequest): Promise<ChatToken>;
17
+ /** A client that authenticates with the exchanged end-user token. */
18
+ declare function withChatToken(client: FronteraClient, token: ChatToken): FronteraClient;
19
+
20
+ export { exchangeChatToken, withChatToken };
package/dist/auth.js ADDED
@@ -0,0 +1,11 @@
1
+ // src/auth.ts
2
+ function exchangeChatToken(client, request) {
3
+ return client.request("/v1/chat-tokens", { method: "POST", body: request });
4
+ }
5
+ function withChatToken(client, token) {
6
+ return client.withCredential({ kind: "token", token: token.token });
7
+ }
8
+
9
+ export { exchangeChatToken, withChatToken };
10
+ //# sourceMappingURL=auth.js.map
11
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1,49 @@
1
+ /**
2
+ * The OAuth callback page, as a string of HTML.
3
+ *
4
+ * The callback has to live on YOUR domain — a provider only authorises
5
+ * redirect URIs under a domain its project owner has verified — so this is one
6
+ * page every integration must host, and the only page in the whole flow they
7
+ * cannot get from us pre-built. What it does is small and entirely mechanical:
8
+ * take `code` and `state` off its own URL and hand them back to the chat.
9
+ *
10
+ * So we ship the mechanism instead of the instructions. Any JS server can
11
+ * serve this — a Next route handler, Express, Hono, Fastify, Workers, Bun,
12
+ * Deno — and a backend in another language can serve the same markup as a
13
+ * static file (`bunx frontera-chat-callback > callback.html`, or copy it from
14
+ * the docs).
15
+ *
16
+ * No import runs on the page itself: the script is inlined, because a callback
17
+ * page that has to load a bundle is a callback page that can fail to load one
18
+ * while holding an authorization code.
19
+ */
20
+ interface ConnectCallbackPageOptions {
21
+ /**
22
+ * Origin allowed to receive the code in popup mode. Defaults to the page's
23
+ * own origin, correct when the chat and the callback are the same app.
24
+ *
25
+ * Never `'*'`. The message carries an authorization code, and any page that
26
+ * can guess your callback could otherwise listen for it.
27
+ */
28
+ targetOrigin?: string;
29
+ /** Shown while the page does its work. Replace it to match your product. */
30
+ message?: string;
31
+ /** Fallback when a redirect return has no stored address. Defaults to `/`. */
32
+ fallbackReturnTo?: string;
33
+ }
34
+ declare function renderConnectCallbackPage(options?: ConnectCallbackPageOptions): string;
35
+ /**
36
+ * A `Response` carrying the page, for any runtime with the Fetch API.
37
+ *
38
+ * ```ts
39
+ * // Next.js — app/oauth/callback/route.ts
40
+ * export const GET = () => connectCallbackResponse()
41
+ * ```
42
+ *
43
+ * `no-store` matters: this page is only ever loaded with a single-use code in
44
+ * the query string, and a cached copy is a stale code waiting to confuse
45
+ * someone.
46
+ */
47
+ declare function connectCallbackResponse(options?: ConnectCallbackPageOptions): Response;
48
+
49
+ export { type ConnectCallbackPageOptions, connectCallbackResponse, renderConnectCallbackPage };
@@ -0,0 +1,84 @@
1
+ // src/callback-page.ts
2
+ var DEFAULT_MESSAGE = "Finishing up\u2026";
3
+ function jsLiteral(value) {
4
+ return JSON.stringify(value).replace(/</g, "\\u003c");
5
+ }
6
+ function renderConnectCallbackPage(options = {}) {
7
+ const targetOrigin = options.targetOrigin ? jsLiteral(options.targetOrigin) : "location.origin";
8
+ const fallback = jsLiteral(options.fallbackReturnTo ?? "/");
9
+ const message = (options.message ?? DEFAULT_MESSAGE).replace(
10
+ /[<>&]/g,
11
+ (c) => c === "<" ? "&lt;" : c === ">" ? "&gt;" : "&amp;"
12
+ );
13
+ return `<!doctype html>
14
+ <html lang="en">
15
+ <head>
16
+ <meta charset="utf-8">
17
+ <meta name="viewport" content="width=device-width, initial-scale=1">
18
+ <meta name="robots" content="noindex">
19
+ <title>Connecting\u2026</title>
20
+ <style>
21
+ body {
22
+ margin: 0; min-height: 100vh;
23
+ display: flex; align-items: center; justify-content: center;
24
+ font: 15px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
25
+ color: #16201f; background: #fbfbfa;
26
+ }
27
+ @media (prefers-color-scheme: dark) { body { color: #e6ecea; background: #0e1413; } }
28
+ p { opacity: .7; }
29
+ </style>
30
+ </head>
31
+ <body>
32
+ <p>${message}</p>
33
+ <script>
34
+ (function () {
35
+ var params = new URLSearchParams(location.search);
36
+ var payload = {
37
+ type: 'frontera:oauth-callback',
38
+ code: params.get('code') || undefined,
39
+ state: params.get('state') || undefined,
40
+ error: params.get('error') || undefined
41
+ };
42
+
43
+ // Popup: hand the result to the window that opened us, then get out of the
44
+ // way. The origin is pinned \u2014 this message carries an authorization code.
45
+ if (window.opener) {
46
+ try { window.opener.postMessage(payload, ${targetOrigin}); } catch (e) {}
47
+ window.close();
48
+ return;
49
+ }
50
+
51
+ // Redirected tab \u2014 the normal path on mobile, where popups are blocked. The
52
+ // chat parked its return address before leaving, because the redirect URI is
53
+ // registered with the provider and cannot carry one.
54
+ var returnTo = ${fallback};
55
+ try {
56
+ var pending = JSON.parse(sessionStorage.getItem('frontera:connect-pending') || 'null');
57
+ if (pending && pending.returnTo) returnTo = pending.returnTo;
58
+ } catch (e) {}
59
+
60
+ var target = new URL(returnTo, location.origin);
61
+ if (payload.code) target.searchParams.set('frontera_code', payload.code);
62
+ if (payload.state) target.searchParams.set('frontera_state', payload.state);
63
+ if (payload.error) target.searchParams.set('frontera_error', payload.error);
64
+ location.replace(target.toString());
65
+ })();
66
+ <\/script>
67
+ </body>
68
+ </html>`;
69
+ }
70
+ function connectCallbackResponse(options = {}) {
71
+ return new Response(renderConnectCallbackPage(options), {
72
+ headers: {
73
+ "content-type": "text/html; charset=utf-8",
74
+ "cache-control": "no-store",
75
+ // The page is not meant to be embedded, and framing it would put an
76
+ // authorization code inside someone else's document.
77
+ "x-frame-options": "DENY"
78
+ }
79
+ });
80
+ }
81
+
82
+ export { connectCallbackResponse, renderConnectCallbackPage };
83
+ //# sourceMappingURL=callback-page.js.map
84
+ //# sourceMappingURL=callback-page.js.map
@@ -0,0 +1,221 @@
1
+ import { FronteraClient } from '@frontera-sdk/core/client';
2
+ import { ChatStreamOptions } from './stream.js';
3
+ import { ChatClientOptions, StartChatRequest, StartChatResult, PendingApproval, ApprovalDecision, StartAppConnectionRequest, StartAppConnectionResult, CompleteAppConnectionRequest, CompleteAppConnectionResult, ResumeToolCallResult, ChatAgent, UploadedFile, Paginated, ChatArtifact, ArtifactVersionMeta, ListSessionsQuery, Session, CreateSessionRequest, SessionMessage, UpdateSessionRequest } from './types.js';
4
+
5
+ /**
6
+ * Domain client for the chat surface, in the mould of `BlueprintClient`: one
7
+ * thin method per endpoint over a `FronteraClient`.
8
+ *
9
+ * `authorizeConversation` exists because under API-key auth the SERVER SKIPS
10
+ * conversation ownership checks — any conversation id under the key's agent is
11
+ * accepted. A backend serving several of its own users must therefore gate
12
+ * conversation access itself; wiring that gate in here means every access path
13
+ * goes through it. Methods throw `FronteraError` code `FORBIDDEN_LOCAL` when
14
+ * the callback denies. Under an end-user `cht_` token the server enforces
15
+ * isolation and the callback is unnecessary.
16
+ */
17
+ declare class ChatClient {
18
+ private readonly client;
19
+ private readonly options;
20
+ constructor(client: FronteraClient, options?: ChatClientOptions);
21
+ private authorize;
22
+ /** Start (or continue) a run. See `stream.ts` for stream semantics. */
23
+ startChat(request: StartChatRequest, options?: ChatStreamOptions): Promise<StartChatResult>;
24
+ /**
25
+ * Re-attach to a run's stream. Run ids are capabilities: they only leave the
26
+ * server through a response the caller was already authorized to receive, so
27
+ * there is no conversation gate here — treat them accordingly.
28
+ */
29
+ resumeStream(runId: string, options?: {
30
+ startIndex?: number;
31
+ } & ChatStreamOptions): Promise<Response>;
32
+ cancelRun(runId: string): Promise<{
33
+ success: true;
34
+ }>;
35
+ steerRun(runId: string, message: string): Promise<{
36
+ success: true;
37
+ }>;
38
+ /**
39
+ * The tool calls this conversation has parked, waiting on a person.
40
+ *
41
+ * Poll or call this on mount: a run blocked on an approval stays blocked
42
+ * across a page reload, and the `tool-approval-request` chunk that announced
43
+ * it is not replayed by a fresh `useChat`. Without reading them back, the
44
+ * conversation looks like an agent that stopped for no reason.
45
+ *
46
+ * End-user (`cht_`) tokens only — see `respondToApproval`.
47
+ */
48
+ listPendingApprovals(conversationId: string): Promise<PendingApproval[]>;
49
+ /**
50
+ * Approve or deny a parked tool call, releasing (or refusing) the run.
51
+ *
52
+ * Requires an end-user `cht_` token: the decision is recorded against the
53
+ * person who made it, and an `sak_` key is one credential shared by every
54
+ * user of your product — there is nobody it could be deciding as, so the
55
+ * server answers 403 (`FORBIDDEN`). An integration that wants its agent to
56
+ * act unattended sets the agent's approval mode to `auto` instead.
57
+ *
58
+ * Deciding twice is not an error: the first decision wins and this reports
59
+ * the settled status. A lapsed request answers `expired`.
60
+ */
61
+ respondToApproval(approvalId: string, decision: ApprovalDecision): Promise<{
62
+ id: string;
63
+ status: string;
64
+ }>;
65
+ /**
66
+ * Begin connecting the end user's own account for a parked `needs_connect`
67
+ * call, and get the URL to send them to.
68
+ *
69
+ * Three things must line up before this answers, and all three are one-time
70
+ * setup rather than per-user work:
71
+ * 1. the workspace has ITS OWN OAuth client for the provider (the
72
+ * deployment-managed one cannot serve this — your users are authorising
73
+ * your application, and only its owner can register your callback);
74
+ * 2. `redirectUri` is registered with that client AND on the workspace's
75
+ * embed allowlist;
76
+ * 3. the install allows external users, and this user's token carries the
77
+ * `plugin-connect` capability you granted when you minted it.
78
+ *
79
+ * Open the returned `authUrl` in a popup. Your callback receives `code` and
80
+ * `state` — hand them to `completeAppConnection`, then `resumeToolCall`.
81
+ */
82
+ startAppConnection(request: StartAppConnectionRequest): Promise<StartAppConnectionResult>;
83
+ /**
84
+ * Finish a connect from the code your own callback received.
85
+ *
86
+ * `state` is signed by us and names the install, the user and the redirect
87
+ * URI, so none of the three can be swapped between the authorize request and
88
+ * this call. Pass it back exactly as it arrived.
89
+ */
90
+ completeAppConnection(request: CompleteAppConnectionRequest): Promise<CompleteAppConnectionResult>;
91
+ /**
92
+ * Re-run the tool call that was waiting on the connection.
93
+ *
94
+ * Not optional: the agent is blocked on a tool RESULT, not on an account, so
95
+ * a connect without this leaves the conversation exactly as stuck as before.
96
+ */
97
+ resumeToolCall(pendingToolCallId: string): Promise<ResumeToolCallResult>;
98
+ /**
99
+ * The agents this credential may talk to — what an agent picker renders.
100
+ *
101
+ * Scoped to the credential, so a token bound to one agent lists exactly that
102
+ * agent while a workspace-wide token lists them all. The Console listing is
103
+ * session-only and returns configuration an end user has no business seeing,
104
+ * which is why this exists separately.
105
+ */
106
+ listAgents(): Promise<ChatAgent[]>;
107
+ /**
108
+ * Upload a file for this user, then reference the result in
109
+ * `startChat({ fileAttachments: [uploaded] })`.
110
+ *
111
+ * A chat-scoped route, not the platform's `/v1/upload`: that one authorises
112
+ * through workspace membership, which an end user of a customer's product
113
+ * does not have and should not need.
114
+ */
115
+ upload(file: File | Blob, filename?: string): Promise<UploadedFile>;
116
+ /**
117
+ * A live URL for a stored upload.
118
+ *
119
+ * The URL saved on a message is presigned and expires about an hour after
120
+ * upload, so anything rendered later re-signs from the stored path — without
121
+ * this, attachments in yesterday's messages become broken images.
122
+ */
123
+ signUpload(storagePath: string): Promise<string>;
124
+ /** The artifacts this user owns — documents, decks and images the agent made. */
125
+ listArtifacts(query?: {
126
+ search?: string;
127
+ limit?: number;
128
+ cursor?: string;
129
+ }): Promise<Paginated<ChatArtifact>>;
130
+ getArtifact(id: string): Promise<ChatArtifact>;
131
+ /**
132
+ * The artifact's contents as TEXT.
133
+ *
134
+ * Only for artifacts that are text — markdown, csv, code. Reading a PNG or a
135
+ * spreadsheet through here destroys it: `.text()` decodes the bytes as UTF-8,
136
+ * and every byte that is not valid UTF-8 becomes a replacement character on
137
+ * the way. Use `getArtifactFile` for anything binary.
138
+ */
139
+ getArtifactContent(id: string): Promise<string>;
140
+ /**
141
+ * The artifact's raw bytes, with the server's own content type.
142
+ *
143
+ * The Blob carries the type the route reported rather than one guessed from
144
+ * the format, so an <img> or a PDF reader gets what it needs without the
145
+ * caller restating it — and a wrong guess here is an image that silently
146
+ * will not display.
147
+ */
148
+ getArtifactFile(id: string): Promise<Blob>;
149
+ /**
150
+ * A PDF rendering of an artifact a browser cannot open itself.
151
+ *
152
+ * `.docx` and `.pptx` are bytes with no source to fall back on, so the
153
+ * service renders a PDF beside them and this returns it — displaying one
154
+ * without shipping an OOXML reader.
155
+ *
156
+ * Only artifacts with `previewKey` set have one; anything else answers 404
157
+ * as `NOT_FOUND`. Check the field before asking, or catch it.
158
+ */
159
+ /**
160
+ * Save an edit made in the viewer — a sheet cell, a document's text.
161
+ *
162
+ * Produces a new REVISION rather than overwriting: the service re-renders to
163
+ * a versioned storage key and bumps the version, so the artifact keeps the
164
+ * history an edit implies.
165
+ */
166
+ updateArtifact(id: string, patch: {
167
+ content: string;
168
+ title?: string;
169
+ }): Promise<ChatArtifact>;
170
+ /** One revision's content — what the inline "viewing v1" panel shows. */
171
+ getArtifactVersion(id: string, version: number): Promise<ChatArtifact>;
172
+ /**
173
+ * Roll back to a revision.
174
+ *
175
+ * Writes a new revision holding the old content — nothing is deleted, so a
176
+ * restore made in error is itself undoable.
177
+ */
178
+ restoreArtifactVersion(id: string, version: number): Promise<ChatArtifact>;
179
+ /** Revisions of one artifact, newest first. Metadata only. */
180
+ listArtifactVersions(id: string): Promise<ArtifactVersionMeta[]>;
181
+ /**
182
+ * The rendition of a PAST version, for the viewer's version picker.
183
+ *
184
+ * Separate from `getArtifactPreview` rather than an optional argument: the
185
+ * current preview lives at a different path, and a version of `0` or `NaN`
186
+ * silently falling back to "current" is how a reader ends up looking at
187
+ * today's document under yesterday's heading.
188
+ */
189
+ getArtifactVersionPreview(id: string, version: number): Promise<Blob>;
190
+ getArtifactPreview(id: string): Promise<Blob>;
191
+ listSessions(query?: ListSessionsQuery): Promise<Paginated<Session>>;
192
+ createSession(request?: CreateSessionRequest): Promise<Session>;
193
+ getSession(id: string): Promise<Session>;
194
+ getMessages(id: string, options?: {
195
+ limit?: number;
196
+ }): Promise<SessionMessage[]>;
197
+ /**
198
+ * Rename, pin, or restatus a conversation.
199
+ *
200
+ * Answers `{ success: true }` rather than the updated row — the service
201
+ * confirms the write and nothing more. Typed as what actually arrives: a
202
+ * `Session` here would be a promise the server never made, and the first
203
+ * caller to read `.title` off it would get `undefined` with no explanation.
204
+ * Re-read with `getSession` when you need the new state.
205
+ */
206
+ updateSession(id: string, patch: UpdateSessionRequest): Promise<{
207
+ success: boolean;
208
+ }>;
209
+ deleteSession(id: string): Promise<void>;
210
+ forkSession(id: string, messageId: string): Promise<Session>;
211
+ /** Returns the export as a raw string — this route has no JSON envelope. */
212
+ exportSession(id: string, format: string): Promise<string>;
213
+ getFollowUps(conversationId: string, messageId: string): Promise<{
214
+ suggestions: unknown[];
215
+ }>;
216
+ getMessageMetadata(conversationId: string, messageId: string): Promise<{
217
+ metadata: unknown;
218
+ }>;
219
+ }
220
+
221
+ export { ChatClient };
@@ -0,0 +1,5 @@
1
+ export { ChatClient } from './chunk-RLHHRJWS.js';
2
+ import './chunk-VWUR3ECR.js';
3
+ import './chunk-KZEGEV3P.js';
4
+ //# sourceMappingURL=chat-client.js.map
5
+ //# sourceMappingURL=chat-client.js.map
@@ -0,0 +1,30 @@
1
+ /**
2
+ * The error codes a chat integration meets, and what each means for the
3
+ * person chatting (Forge improvement plan L4: the codes were found by reading
4
+ * the package source). Every SDK call throws `FronteraError`; branch on its
5
+ * `code`. The service can add codes, so treat one not listed here as
6
+ * `INTERNAL_ERROR`.
7
+ */
8
+ declare const CHAT_ERROR_CODES: {
9
+ readonly UNAUTHORIZED: "The key or token was not accepted: it is disabled, removed, mistyped or expired. Mint a new token; if that fails too, check the key.";
10
+ readonly FORBIDDEN: "The credential may not do this: the page is not on the key’s allowed websites, or a visitor asked for something a public chat cannot do.";
11
+ readonly NOT_FOUND: "The conversation or run is not this credential’s, or no longer exists.";
12
+ readonly VALIDATION_ERROR: "The request was malformed, for example an empty message or more than five messages.";
13
+ readonly RATE_LIMITED: "Too many messages or new chats in a short time. Wait the number of seconds the message names, then try again.";
14
+ readonly QUOTA_EXCEEDED: "The organization’s usage limit is reached. An administrator raises it.";
15
+ readonly SERVICE_UNAVAILABLE: "The platform can’t take the request right now. Try again shortly.";
16
+ readonly INTERNAL_ERROR: "Something failed on the platform. Try again; if it keeps failing, the message names what to report.";
17
+ readonly PROTOCOL_ERROR: "The response wasn’t a chat stream: the API origin is likely wrong, or a proxy changed the response.";
18
+ readonly FORBIDDEN_LOCAL: "Your own `authorizeConversation` callback denied access to the conversation.";
19
+ readonly CONFIG_MISSING: "The client has no API origin or credential.";
20
+ };
21
+ type ChatErrorCode = keyof typeof CHAT_ERROR_CODES;
22
+ /** The code of any thrown value, `INTERNAL_ERROR` for one that isn't a `FronteraError` (a network failure included). */
23
+ declare function chatErrorCode(err: unknown): ChatErrorCode;
24
+ /**
25
+ * What to show a website visitor for an error: the platform's own message for
26
+ * a limit (it names the wait), plain words otherwise. Never the raw response.
27
+ */
28
+ declare function visitorErrorWords(err: unknown): string;
29
+
30
+ export { CHAT_ERROR_CODES, type ChatErrorCode, chatErrorCode, visitorErrorWords };
@@ -0,0 +1,3 @@
1
+ export { CHAT_ERROR_CODES, chatErrorCode, visitorErrorWords } from './chunk-YKQ5Z5EK.js';
2
+ //# sourceMappingURL=chat-errors.js.map
3
+ //# sourceMappingURL=chat-errors.js.map
@@ -0,0 +1,116 @@
1
+ import { createContext, useContext } from 'react';
2
+ import { useQuery, useQueryClient, useMutation } from '@tanstack/react-query';
3
+
4
+ // src/hooks.ts
5
+ var chatKeys = {
6
+ all: ["chat"],
7
+ sessions: (query) => ["chat", "sessions", JSON.stringify(query ?? {})],
8
+ session: (id) => ["chat", "session", id],
9
+ messages: (id) => ["chat", "messages", id],
10
+ followUps: (conversationId, messageId) => ["chat", "follow-ups", conversationId, messageId],
11
+ approvals: (conversationId) => ["chat", "approvals", conversationId]
12
+ };
13
+ var FronteraChatContext = createContext(null);
14
+ function useChatClient() {
15
+ const client = useContext(FronteraChatContext);
16
+ if (!client) {
17
+ throw new Error(
18
+ "No ChatClient in context. Wrap the tree in FronteraChatContext.Provider \u2014 in a Frontera app, add chatProvider to createFronteraApp providers."
19
+ );
20
+ }
21
+ return client;
22
+ }
23
+ function useSessions(query, options = {}) {
24
+ const client = useChatClient();
25
+ return useQuery({
26
+ queryKey: chatKeys.sessions(query),
27
+ queryFn: () => client.listSessions(query),
28
+ ...options
29
+ });
30
+ }
31
+ function useSession(id, options = {}) {
32
+ const client = useChatClient();
33
+ return useQuery({
34
+ queryKey: chatKeys.session(id),
35
+ queryFn: () => client.getSession(id),
36
+ ...options
37
+ });
38
+ }
39
+ function useSessionMessages(id, options = {}) {
40
+ const client = useChatClient();
41
+ return useQuery({
42
+ queryKey: chatKeys.messages(id),
43
+ queryFn: () => client.getMessages(id),
44
+ ...options
45
+ });
46
+ }
47
+ function useFollowUps(conversationId, messageId, options = {}) {
48
+ const client = useChatClient();
49
+ return useQuery({
50
+ queryKey: chatKeys.followUps(conversationId, messageId),
51
+ queryFn: () => client.getFollowUps(conversationId, messageId),
52
+ ...options
53
+ });
54
+ }
55
+ function useCreateSession(options = {}) {
56
+ const client = useChatClient();
57
+ const queryClient = useQueryClient();
58
+ return useMutation({
59
+ mutationFn: (request) => client.createSession(request),
60
+ ...options,
61
+ onSuccess: (data, variables, context, mutation) => {
62
+ void queryClient.invalidateQueries({ queryKey: chatKeys.all });
63
+ return options.onSuccess?.(data, variables, context, mutation);
64
+ }
65
+ });
66
+ }
67
+ function useUpdateSession(options = {}) {
68
+ const client = useChatClient();
69
+ const queryClient = useQueryClient();
70
+ return useMutation({
71
+ mutationFn: ({ id, patch }) => client.updateSession(id, patch),
72
+ ...options,
73
+ onSuccess: (data, variables, context, mutation) => {
74
+ void queryClient.invalidateQueries({ queryKey: chatKeys.session(variables.id) });
75
+ void queryClient.invalidateQueries({ queryKey: chatKeys.all });
76
+ return options.onSuccess?.(data, variables, context, mutation);
77
+ }
78
+ });
79
+ }
80
+ function usePendingApprovals(conversationId, options = {}) {
81
+ const client = useChatClient();
82
+ return useQuery({
83
+ queryKey: chatKeys.approvals(conversationId),
84
+ queryFn: () => client.listPendingApprovals(conversationId),
85
+ enabled: Boolean(conversationId),
86
+ refetchInterval: 5e3,
87
+ ...options
88
+ });
89
+ }
90
+ function useRespondToApproval(conversationId, options = {}) {
91
+ const client = useChatClient();
92
+ const queryClient = useQueryClient();
93
+ return useMutation({
94
+ mutationFn: ({ approvalId, decision }) => client.respondToApproval(approvalId, decision),
95
+ ...options,
96
+ onSuccess: (data, variables, context, mutation) => {
97
+ void queryClient.invalidateQueries({ queryKey: chatKeys.approvals(conversationId) });
98
+ return options.onSuccess?.(data, variables, context, mutation);
99
+ }
100
+ });
101
+ }
102
+ function useCancelRun(options = {}) {
103
+ const client = useChatClient();
104
+ return useMutation({ mutationFn: (runId) => client.cancelRun(runId), ...options });
105
+ }
106
+ function useSteerRun(options = {}) {
107
+ const client = useChatClient();
108
+ return useMutation({
109
+ mutationFn: ({ runId, message }) => client.steerRun(runId, message),
110
+ ...options
111
+ });
112
+ }
113
+
114
+ export { FronteraChatContext, chatKeys, useCancelRun, useChatClient, useCreateSession, useFollowUps, usePendingApprovals, useRespondToApproval, useSession, useSessionMessages, useSessions, useSteerRun, useUpdateSession };
115
+ //# sourceMappingURL=chunk-CMMWTCYS.js.map
116
+ //# sourceMappingURL=chunk-CMMWTCYS.js.map
@@ -0,0 +1,35 @@
1
+ import { FronteraError } from '@frontera-sdk/core/errors';
2
+
3
+ // src/stream.ts
4
+ async function startChat(client, request, options = {}) {
5
+ const response = await client.requestRaw("/v1/chat", {
6
+ method: "POST",
7
+ body: request,
8
+ signal: options.signal
9
+ });
10
+ const conversationId = response.headers.get("x-conversation-id");
11
+ const runId = response.headers.get("x-workflow-run-id");
12
+ if (!conversationId || !runId) {
13
+ throw new FronteraError("chat response is missing run identification headers", {
14
+ code: "PROTOCOL_ERROR",
15
+ status: response.status
16
+ });
17
+ }
18
+ return {
19
+ conversationId,
20
+ runId,
21
+ runtime: response.headers.get("x-agent-runtime") ?? "pi",
22
+ quotaWarning: response.headers.get("x-quota-warning") ?? void 0,
23
+ response
24
+ };
25
+ }
26
+ async function resumeStream(client, runId, options = {}) {
27
+ return client.requestRaw(`/v1/chat/${encodeURIComponent(runId)}/stream`, {
28
+ query: { startIndex: options.startIndex },
29
+ signal: options.signal
30
+ });
31
+ }
32
+
33
+ export { resumeStream, startChat };
34
+ //# sourceMappingURL=chunk-KZEGEV3P.js.map
35
+ //# sourceMappingURL=chunk-KZEGEV3P.js.map