@adonis-agora/agent 0.12.0 → 0.13.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/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # @adonis-agora/agent
2
2
 
3
+ ## 0.13.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`b684986`](https://github.com/DavideCarvalho/adonis-agent/commit/b68498606a02e82dc92d01a7aa139eb6ba752bee) - Add a framework-agnostic browser client and a React hook for the chat SSE endpoints.
8
+
9
+ Consuming the agent's SSE envelope (`POST /agent/chat` → `event: meta` / `data: {delta}` / `event: component` / `event: done`) and reconnecting a dropped stream used to be re-implemented by hand in every app. Two new entry points move that logic into the package, next to the server that emits the envelope:
10
+
11
+ - **`@adonis-agora/agent/client`** — zero-dependency, isomorphic. `createAgentChatClient({ basePath, fetch, getHeaders, resume })` returns `send()` / `resume()` that post a turn, parse the envelope, capture the run id, and — when the connection drops before `done` — re-attach to `GET /agent/chat/:runId/stream` (which replays the whole stream from the start and follows live) with backoff, until the run finishes or the retry budget is exhausted. The run is durable and keeps executing server-side across the drop, so no tokens are lost. Also exports the parsing primitives (`parseSseEvent`, `decodeFrame`, `foldPart`, `readSseStream`) and `AgentChatDisconnectedError` (which carries the partial parts).
12
+ - **`@adonis-agora/agent/react`** — `useAgentChat({ ...clientOptions, buildBody })` returning `{ messages, status, error, send, cancel }`, a thin state wrapper over the client. `react` is a new optional peer dependency.
13
+
3
14
  ## 0.12.0
4
15
 
5
16
  ### Minor Changes
@@ -0,0 +1,90 @@
1
+ import { type ChatFrame, type ChatPart } from './sse.js';
2
+ /**
3
+ * Body of `POST /agent/chat` (shape accepted by the provider → `AgentService.chat`). `message` is
4
+ * required; everything else is optional context. `pageContext` reaches the tools' ctx (not the model
5
+ * prompt) and is rebuilt from each turn's input, so send it on every message, not just the first.
6
+ */
7
+ export interface AgentChatRequestBody {
8
+ message: string;
9
+ threadId?: string;
10
+ agent?: string;
11
+ persona?: string;
12
+ pageContext?: {
13
+ kind?: string;
14
+ [key: string]: unknown;
15
+ };
16
+ attachments?: unknown[];
17
+ }
18
+ /** Options for {@link createAgentChatClient}. */
19
+ export interface AgentChatClientOptions {
20
+ /**
21
+ * Base path the provider mounted its routes under (`POST {basePath}/chat`,
22
+ * `GET {basePath}/chat/:runId/stream`). Defaults to `/agent`.
23
+ */
24
+ basePath?: string;
25
+ /** `fetch` implementation to use. Defaults to `globalThis.fetch`. */
26
+ fetch?: typeof fetch;
27
+ /**
28
+ * Extra headers merged into every request — e.g. an anti-CSRF token (`{ 'X-XSRF-TOKEN': ... }`).
29
+ * Called per request so a rotating token is always read fresh.
30
+ */
31
+ getHeaders?: () => Record<string, string>;
32
+ /** Reconnection policy for a dropped stream, or `false` to disable and fail on the first drop. */
33
+ resume?: AgentChatResumeOptions | false;
34
+ }
35
+ /** Reconnection policy: how many times to re-attach, and the backoff before each attempt. */
36
+ export interface AgentChatResumeOptions {
37
+ /** Max consecutive re-attach attempts before giving up. Defaults to 6. */
38
+ maxAttempts?: number;
39
+ /** Backoff before attempt `n` (1-based), in ms. Defaults to `min(400 * n, 3000)`. */
40
+ backoffMs?: (attempt: number) => number;
41
+ }
42
+ /** Callbacks fired while a stream is consumed. All optional. */
43
+ export interface AgentChatHandlers {
44
+ /** The assistant message's parts so far, rebuilt on every frame (safe to render directly). */
45
+ onParts?: (parts: ChatPart[]) => void;
46
+ /** Each decoded renderable/control frame, in wire order. */
47
+ onFrame?: (frame: ChatFrame) => void;
48
+ /** The run id, as soon as it is known (response header, then the `meta` frame). */
49
+ onRunId?: (runId: string) => void;
50
+ /** The thread id, as soon as it is known. */
51
+ onThreadId?: (threadId: string) => void;
52
+ }
53
+ /** Arguments to {@link AgentChatClient.send}. */
54
+ export interface AgentChatSendOptions extends AgentChatHandlers {
55
+ body: AgentChatRequestBody;
56
+ signal?: AbortSignal;
57
+ }
58
+ /** The settled result of a completed chat turn. */
59
+ export interface AgentChatResult {
60
+ runId?: string;
61
+ threadId?: string;
62
+ parts: ChatPart[];
63
+ }
64
+ /**
65
+ * Thrown when a run's stream dropped and could not be resumed within the retry budget. Carries the
66
+ * partial parts received so far (and the ids) so a consumer can keep what streamed and surface a
67
+ * "couldn't finish, try again" state instead of losing the message.
68
+ */
69
+ export declare class AgentChatDisconnectedError extends Error {
70
+ readonly runId: string | undefined;
71
+ readonly threadId: string | undefined;
72
+ readonly parts: ChatPart[];
73
+ constructor(runId: string | undefined, threadId: string | undefined, parts: ChatPart[]);
74
+ }
75
+ /**
76
+ * A framework-agnostic client for the agent chat SSE endpoints. `send` posts a turn and streams the
77
+ * reply; if the connection drops before the run finishes, it re-attaches to
78
+ * `GET {basePath}/chat/:runId/stream` — which replays the whole stream from the start and follows live
79
+ * — with backoff, until the run emits `done` or the retry budget is exhausted. The run itself is
80
+ * durable and keeps executing server-side across the drop, so no tokens are lost.
81
+ */
82
+ export interface AgentChatClient {
83
+ send(options: AgentChatSendOptions): Promise<AgentChatResult>;
84
+ /** Re-attach to an already-started run (e.g. after a fresh page load) and stream it to completion. */
85
+ resume(runId: string, options?: AgentChatHandlers & {
86
+ signal?: AbortSignal;
87
+ }): Promise<AgentChatResult>;
88
+ }
89
+ export declare function createAgentChatClient(options?: AgentChatClientOptions): AgentChatClient;
90
+ //# sourceMappingURL=chat-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-client.d.ts","sourceRoot":"","sources":["../../../src/client/chat-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,QAAQ,EAAwC,MAAM,UAAU,CAAC;AAE/F;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IACxD,WAAW,CAAC,EAAE,OAAO,EAAE,CAAC;CACzB;AAED,iDAAiD;AACjD,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,kGAAkG;IAClG,MAAM,CAAC,EAAE,sBAAsB,GAAG,KAAK,CAAC;CACzC;AAED,6FAA6F;AAC7F,MAAM,WAAW,sBAAsB;IACrC,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qFAAqF;IACrF,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;CACzC;AAED,gEAAgE;AAChE,MAAM,WAAW,iBAAiB;IAChC,8FAA8F;IAC9F,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,IAAI,CAAC;IACtC,4DAA4D;IAC5D,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IACrC,mFAAmF;IACnF,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,6CAA6C;IAC7C,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAED,iDAAiD;AACjD,MAAM,WAAW,oBAAqB,SAAQ,iBAAiB;IAC7D,IAAI,EAAE,oBAAoB,CAAC;IAC3B,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,mDAAmD;AACnD,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB;AAED;;;;GAIG;AACH,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC;gBACf,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE;CAOvF;AAiCD;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IAC9D,sGAAsG;IACtG,MAAM,CACJ,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,iBAAiB,GAAG;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GACrD,OAAO,CAAC,eAAe,CAAC,CAAC;CAC7B;AAED,wBAAgB,qBAAqB,CAAC,OAAO,GAAE,sBAA2B,GAAG,eAAe,CAmL3F"}
@@ -0,0 +1,204 @@
1
+ import { decodeFrame, foldPart, readSseStream } from './sse.js';
2
+ /**
3
+ * Thrown when a run's stream dropped and could not be resumed within the retry budget. Carries the
4
+ * partial parts received so far (and the ids) so a consumer can keep what streamed and surface a
5
+ * "couldn't finish, try again" state instead of losing the message.
6
+ */
7
+ export class AgentChatDisconnectedError extends Error {
8
+ runId;
9
+ threadId;
10
+ parts;
11
+ constructor(runId, threadId, parts) {
12
+ super('The agent stream dropped and could not be resumed.');
13
+ this.name = 'AgentChatDisconnectedError';
14
+ this.runId = runId;
15
+ this.threadId = threadId;
16
+ this.parts = parts;
17
+ }
18
+ }
19
+ const DEFAULT_MAX_ATTEMPTS = 6;
20
+ function defaultBackoff(attempt) {
21
+ return Math.min(400 * attempt, 3000);
22
+ }
23
+ /** An `AbortError`-shaped error without depending on `DOMException` (kept Node/browser portable). */
24
+ function abortError() {
25
+ const error = new Error('Aborted');
26
+ error.name = 'AbortError';
27
+ return error;
28
+ }
29
+ function delay(ms, signal) {
30
+ return new Promise((resolve, reject) => {
31
+ if (signal?.aborted) {
32
+ reject(abortError());
33
+ return;
34
+ }
35
+ const timer = setTimeout(resolve, ms);
36
+ signal?.addEventListener('abort', () => {
37
+ clearTimeout(timer);
38
+ reject(abortError());
39
+ }, { once: true });
40
+ });
41
+ }
42
+ export function createAgentChatClient(options = {}) {
43
+ const basePath = (options.basePath ?? '/agent').replace(/\/$/, '');
44
+ const fetchImpl = options.fetch ?? globalThis.fetch;
45
+ const resumeCfg = options.resume;
46
+ const maxAttempts = resumeCfg === false ? 0 : (resumeCfg?.maxAttempts ?? DEFAULT_MAX_ATTEMPTS);
47
+ const backoff = (resumeCfg === false ? undefined : resumeCfg?.backoffMs) ?? defaultBackoff;
48
+ function headers(base) {
49
+ return { ...base, ...(options.getHeaders?.() ?? {}) };
50
+ }
51
+ /**
52
+ * Drains one SSE stream, folding renderable frames into a fresh parts array (a re-attach replays
53
+ * from the start, so rebuilding from `[]` yields the complete message without duplicating). Returns
54
+ * whether the stream ended with `done` (the run finished) vs. was cut short.
55
+ */
56
+ async function consume(body, sink) {
57
+ let parts = [];
58
+ for await (const event of readSseStream(body)) {
59
+ const frame = decodeFrame(event);
60
+ if (!frame) {
61
+ continue;
62
+ }
63
+ sink.handlers.onFrame?.(frame);
64
+ if (frame.type === 'done') {
65
+ return true;
66
+ }
67
+ if (frame.type === 'meta') {
68
+ if (frame.runId) {
69
+ sink.handlers.onRunId?.(frame.runId);
70
+ }
71
+ if (frame.threadId) {
72
+ sink.handlers.onThreadId?.(frame.threadId);
73
+ }
74
+ continue;
75
+ }
76
+ parts = foldPart(parts, frame);
77
+ sink.onParts(parts);
78
+ }
79
+ return false;
80
+ }
81
+ /**
82
+ * Runs the re-attach loop from a known `runId` until the run emits `done` or the retry budget is
83
+ * exhausted. Shared by `send` (after the POST drops) and `resume` (from a cold start).
84
+ */
85
+ async function reattach(runId, signal, sink) {
86
+ let attempt = 0;
87
+ let sawDone = false;
88
+ while (!sawDone && !signal?.aborted && attempt < maxAttempts) {
89
+ attempt += 1;
90
+ await delay(backoff(attempt), signal);
91
+ try {
92
+ const response = await fetchImpl(`${basePath}/chat/${runId}/stream`, {
93
+ method: 'GET',
94
+ credentials: 'include',
95
+ ...(signal ? { signal } : {}),
96
+ headers: headers({ Accept: 'text/event-stream' }),
97
+ });
98
+ if (!response.ok || !response.body) {
99
+ continue;
100
+ }
101
+ attempt = 0; // Reconnected: reset the budget; only the next drop counts again.
102
+ sawDone = await consume(response.body, sink);
103
+ }
104
+ catch (error) {
105
+ if (signal?.aborted) {
106
+ throw error;
107
+ }
108
+ // Dropped again — loop retries until the budget is spent.
109
+ }
110
+ }
111
+ return sawDone;
112
+ }
113
+ async function send(sendOptions) {
114
+ const { body, signal } = sendOptions;
115
+ let runId;
116
+ let threadId;
117
+ let lastParts = [];
118
+ const handlers = {
119
+ ...sendOptions,
120
+ onRunId: (id) => {
121
+ runId = id;
122
+ sendOptions.onRunId?.(id);
123
+ },
124
+ onThreadId: (id) => {
125
+ threadId = id;
126
+ sendOptions.onThreadId?.(id);
127
+ },
128
+ };
129
+ const onParts = (parts) => {
130
+ lastParts = parts;
131
+ sendOptions.onParts?.(parts);
132
+ };
133
+ const sink = { onParts, handlers };
134
+ const response = await fetchImpl(`${basePath}/chat`, {
135
+ method: 'POST',
136
+ credentials: 'include',
137
+ ...(signal ? { signal } : {}),
138
+ headers: headers({ 'Content-Type': 'application/json', Accept: 'text/event-stream' }),
139
+ body: JSON.stringify(body),
140
+ });
141
+ if (!response.ok || !response.body) {
142
+ throw new Error(`Failed to start agent chat (HTTP ${response.status}).`);
143
+ }
144
+ // The provider sets these before any byte; capture the runId now so a mid-stream drop (before the
145
+ // `meta` frame) can still re-attach.
146
+ const headerRunId = response.headers.get('X-Agent-Run-Id');
147
+ if (headerRunId) {
148
+ runId = headerRunId;
149
+ sendOptions.onRunId?.(headerRunId);
150
+ }
151
+ const headerThreadId = response.headers.get('X-Agent-Thread-Id');
152
+ if (headerThreadId) {
153
+ threadId = headerThreadId;
154
+ sendOptions.onThreadId?.(headerThreadId);
155
+ }
156
+ let sawDone;
157
+ try {
158
+ sawDone = await consume(response.body, sink);
159
+ }
160
+ catch (error) {
161
+ if (signal?.aborted) {
162
+ throw error;
163
+ }
164
+ sawDone = false; // Fall through to the re-attach loop instead of surfacing the drop as an error.
165
+ }
166
+ if (!sawDone && runId) {
167
+ sawDone = await reattach(runId, signal, sink);
168
+ }
169
+ if (!sawDone) {
170
+ throw new AgentChatDisconnectedError(runId, threadId, lastParts);
171
+ }
172
+ return {
173
+ parts: lastParts,
174
+ ...(runId !== undefined ? { runId } : {}),
175
+ ...(threadId !== undefined ? { threadId } : {}),
176
+ };
177
+ }
178
+ async function resume(runId, resumeOptions = {}) {
179
+ let threadId;
180
+ let lastParts = [];
181
+ const handlers = {
182
+ ...resumeOptions,
183
+ onThreadId: (id) => {
184
+ threadId = id;
185
+ resumeOptions.onThreadId?.(id);
186
+ },
187
+ };
188
+ const onParts = (parts) => {
189
+ lastParts = parts;
190
+ resumeOptions.onParts?.(parts);
191
+ };
192
+ const sawDone = await reattach(runId, resumeOptions.signal, { onParts, handlers });
193
+ if (!sawDone) {
194
+ throw new AgentChatDisconnectedError(runId, threadId, lastParts);
195
+ }
196
+ return {
197
+ runId,
198
+ parts: lastParts,
199
+ ...(threadId !== undefined ? { threadId } : {}),
200
+ };
201
+ }
202
+ return { send, resume };
203
+ }
204
+ //# sourceMappingURL=chat-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-client.js","sourceRoot":"","sources":["../../../src/client/chat-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { type ChatFrame, type ChatPart, type SseEvent, decodeFrame, foldPart, parseSseEvent, readSseStream, } from './sse.js';
2
+ export { type AgentChatClient, type AgentChatClientOptions, type AgentChatHandlers, type AgentChatRequestBody, type AgentChatResult, type AgentChatResumeOptions, type AgentChatSendOptions, AgentChatDisconnectedError, createAgentChatClient, } from './chat-client.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,QAAQ,EACb,WAAW,EACX,QAAQ,EACR,aAAa,EACb,aAAa,GACd,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { decodeFrame, foldPart, parseSseEvent, readSseStream, } from './sse.js';
2
+ export { AgentChatDisconnectedError, createAgentChatClient, } from './chat-client.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,WAAW,EACX,QAAQ,EACR,aAAa,EACb,aAAa,GACd,MAAM,UAAU,CAAC;AAClB,OAAO,EAQL,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Client-side counterpart to {@link import('../sse.js').frameToSse}: parses the provider's SSE
3
+ * envelope back into typed frames the browser can render. Kept framework-agnostic (no React, no
4
+ * Adonis) so any consumer — a React hook, a Vue composable, a plain fetch loop — decodes the wire
5
+ * format the same way, and so the envelope stays owned by the package that emits it.
6
+ *
7
+ * Wire format (see `frameToSse` + the provider's `#pipe`):
8
+ * - `event: meta\ndata: {runId,threadId}` — sent once, first, before any token
9
+ * - `data: {"delta":"..."}` — a text chunk (default event, no `event:` line)
10
+ * - `event: component\ndata: {name,data}` — a rendered component
11
+ * - `event: done\ndata: {}` — the run's stream finished
12
+ */
13
+ /** A rendered part of an assistant message: streamed text, or a named component with its props. */
14
+ export type ChatPart = {
15
+ type: 'text';
16
+ text: string;
17
+ } | {
18
+ type: 'component';
19
+ name: string;
20
+ data: unknown;
21
+ };
22
+ /** A decoded stream frame — the typed form of one SSE event. */
23
+ export type ChatFrame = {
24
+ type: 'text';
25
+ delta: string;
26
+ } | {
27
+ type: 'component';
28
+ name: string;
29
+ data: unknown;
30
+ } | {
31
+ type: 'meta';
32
+ runId?: string;
33
+ threadId?: string;
34
+ } | {
35
+ type: 'done';
36
+ };
37
+ /** One raw SSE event: the `event:` name (default `message`) and the joined `data:` payload. */
38
+ export interface SseEvent {
39
+ event: string;
40
+ data: string;
41
+ }
42
+ /**
43
+ * Parses one raw SSE frame (the text between `\n\n` separators, without them) into `{event, data}`.
44
+ * A frame with no `data:` line (e.g. a `:` keep-alive comment) returns `null`.
45
+ */
46
+ export declare function parseSseEvent(frame: string): SseEvent | null;
47
+ /**
48
+ * Decodes a parsed {@link SseEvent} into a typed {@link ChatFrame}, or `null` when the payload is
49
+ * malformed (non-JSON, or missing required fields) so callers can skip it without crashing.
50
+ */
51
+ export declare function decodeFrame(event: SseEvent): ChatFrame | null;
52
+ /**
53
+ * Folds a renderable {@link ChatFrame} (text or component) into the message's parts, concatenating
54
+ * consecutive text deltas into the trailing text part and appending components in order. `meta`/`done`
55
+ * frames are control frames and are ignored here. Returns a new array (never mutates the input).
56
+ */
57
+ export declare function foldPart(parts: ChatPart[], frame: ChatFrame): ChatPart[];
58
+ /**
59
+ * Reads a byte {@link ReadableStream} (a `fetch` `response.body`) as a sequence of raw SSE events,
60
+ * splitting on the `\n\n` frame separator and buffering partial frames across chunks. Yields only
61
+ * frames that carry a `data:` payload (keep-alives are dropped).
62
+ */
63
+ export declare function readSseStream(body: ReadableStream<Uint8Array>): AsyncGenerator<SseEvent>;
64
+ //# sourceMappingURL=sse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../../../src/client/sse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,mGAAmG;AACnG,MAAM,MAAM,QAAQ,GAChB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAEvD,gEAAgE;AAChE,MAAM,MAAM,SAAS,GACjB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAClD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAErB,+FAA+F;AAC/F,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAc5D;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,IAAI,CAsC7D;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,SAAS,GAAG,QAAQ,EAAE,CAYxE;AAED;;;;GAIG;AACH,wBAAuB,aAAa,CAAC,IAAI,EAAE,cAAc,CAAC,UAAU,CAAC,GAAG,cAAc,CAAC,QAAQ,CAAC,CAyB/F"}
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Client-side counterpart to {@link import('../sse.js').frameToSse}: parses the provider's SSE
3
+ * envelope back into typed frames the browser can render. Kept framework-agnostic (no React, no
4
+ * Adonis) so any consumer — a React hook, a Vue composable, a plain fetch loop — decodes the wire
5
+ * format the same way, and so the envelope stays owned by the package that emits it.
6
+ *
7
+ * Wire format (see `frameToSse` + the provider's `#pipe`):
8
+ * - `event: meta\ndata: {runId,threadId}` — sent once, first, before any token
9
+ * - `data: {"delta":"..."}` — a text chunk (default event, no `event:` line)
10
+ * - `event: component\ndata: {name,data}` — a rendered component
11
+ * - `event: done\ndata: {}` — the run's stream finished
12
+ */
13
+ /**
14
+ * Parses one raw SSE frame (the text between `\n\n` separators, without them) into `{event, data}`.
15
+ * A frame with no `data:` line (e.g. a `:` keep-alive comment) returns `null`.
16
+ */
17
+ export function parseSseEvent(frame) {
18
+ let event = 'message';
19
+ const dataLines = [];
20
+ for (const line of frame.split('\n')) {
21
+ if (line.startsWith('event:')) {
22
+ event = line.slice('event:'.length).trim();
23
+ }
24
+ else if (line.startsWith('data:')) {
25
+ dataLines.push(line.slice('data:'.length).trim());
26
+ }
27
+ }
28
+ if (dataLines.length === 0) {
29
+ return null;
30
+ }
31
+ return { event, data: dataLines.join('\n') };
32
+ }
33
+ /**
34
+ * Decodes a parsed {@link SseEvent} into a typed {@link ChatFrame}, or `null` when the payload is
35
+ * malformed (non-JSON, or missing required fields) so callers can skip it without crashing.
36
+ */
37
+ export function decodeFrame(event) {
38
+ if (event.event === 'done') {
39
+ return { type: 'done' };
40
+ }
41
+ if (event.event === 'meta') {
42
+ try {
43
+ const parsed = JSON.parse(event.data);
44
+ return {
45
+ type: 'meta',
46
+ ...(typeof parsed?.runId === 'string' ? { runId: parsed.runId } : {}),
47
+ ...(typeof parsed?.threadId === 'string' ? { threadId: parsed.threadId } : {}),
48
+ };
49
+ }
50
+ catch {
51
+ return null;
52
+ }
53
+ }
54
+ if (event.event === 'component') {
55
+ try {
56
+ const parsed = JSON.parse(event.data);
57
+ if (typeof parsed?.name !== 'string') {
58
+ return null;
59
+ }
60
+ return { type: 'component', name: parsed.name, data: parsed.data };
61
+ }
62
+ catch {
63
+ return null;
64
+ }
65
+ }
66
+ // Default event: a text delta.
67
+ try {
68
+ const parsed = JSON.parse(event.data);
69
+ const delta = parsed?.delta;
70
+ if (typeof delta !== 'string' || delta.length === 0) {
71
+ return null;
72
+ }
73
+ return { type: 'text', delta };
74
+ }
75
+ catch {
76
+ return null;
77
+ }
78
+ }
79
+ /**
80
+ * Folds a renderable {@link ChatFrame} (text or component) into the message's parts, concatenating
81
+ * consecutive text deltas into the trailing text part and appending components in order. `meta`/`done`
82
+ * frames are control frames and are ignored here. Returns a new array (never mutates the input).
83
+ */
84
+ export function foldPart(parts, frame) {
85
+ if (frame.type === 'component') {
86
+ return [...parts, { type: 'component', name: frame.name, data: frame.data }];
87
+ }
88
+ if (frame.type === 'text') {
89
+ const last = parts[parts.length - 1];
90
+ if (last && last.type === 'text') {
91
+ return [...parts.slice(0, -1), { type: 'text', text: last.text + frame.delta }];
92
+ }
93
+ return [...parts, { type: 'text', text: frame.delta }];
94
+ }
95
+ return parts;
96
+ }
97
+ /**
98
+ * Reads a byte {@link ReadableStream} (a `fetch` `response.body`) as a sequence of raw SSE events,
99
+ * splitting on the `\n\n` frame separator and buffering partial frames across chunks. Yields only
100
+ * frames that carry a `data:` payload (keep-alives are dropped).
101
+ */
102
+ export async function* readSseStream(body) {
103
+ const reader = body.getReader();
104
+ const decoder = new TextDecoder();
105
+ let buffer = '';
106
+ try {
107
+ for (;;) {
108
+ const { value, done } = await reader.read();
109
+ if (done) {
110
+ break;
111
+ }
112
+ buffer += decoder.decode(value, { stream: true });
113
+ let separatorIndex = buffer.indexOf('\n\n');
114
+ while (separatorIndex !== -1) {
115
+ const frame = buffer.slice(0, separatorIndex);
116
+ buffer = buffer.slice(separatorIndex + 2);
117
+ const parsed = parseSseEvent(frame);
118
+ if (parsed) {
119
+ yield parsed;
120
+ }
121
+ separatorIndex = buffer.indexOf('\n\n');
122
+ }
123
+ }
124
+ }
125
+ finally {
126
+ reader.releaseLock();
127
+ }
128
+ }
129
+ //# sourceMappingURL=sse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sse.js","sourceRoot":"","sources":["../../../src/client/sse.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- export declare const VERSION = "0.12.0";
1
+ export declare const VERSION = "0.13.0";
2
2
  export * from './types.js';
3
3
  export * from './spi/tool.js';
4
4
  export * from './base-tool.js';
package/dist/src/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export const VERSION = '0.12.0';
1
+ export const VERSION = '0.13.0';
2
2
  export * from './types.js';
3
3
  export * from './spi/tool.js';
4
4
  export * from './base-tool.js';
@@ -0,0 +1,2 @@
1
+ export { type AgentChatMessage, type AgentChatStatus, type UseAgentChatOptions, type UseAgentChatResult, useAgentChat, } from './use-agent-chat.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/react/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,YAAY,GACb,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { useAgentChat, } from './use-agent-chat.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/react/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,YAAY,GACb,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,33 @@
1
+ import { type AgentChatClientOptions, type AgentChatRequestBody, type ChatPart } from '../client/index.js';
2
+ /** A message in the chat transcript — the user's text, or the assistant's streamed parts. */
3
+ export interface AgentChatMessage {
4
+ id: string;
5
+ role: 'user' | 'assistant';
6
+ parts: ChatPart[];
7
+ /** `true` while this assistant message is still receiving stream frames. */
8
+ streaming?: boolean;
9
+ }
10
+ export type AgentChatStatus = 'idle' | 'streaming' | 'error';
11
+ export interface UseAgentChatOptions extends AgentChatClientOptions {
12
+ /**
13
+ * Builds the request body for a typed message. Defaults to `{ message }`. Override to attach
14
+ * `pageContext`, `agent`, `persona`, etc. The `threadId` is injected by the hook after the first
15
+ * turn, so a custom `buildBody` should NOT set it.
16
+ */
17
+ buildBody?: (message: string) => AgentChatRequestBody;
18
+ }
19
+ export interface UseAgentChatResult {
20
+ messages: AgentChatMessage[];
21
+ status: AgentChatStatus;
22
+ error: string | null;
23
+ send: (text: string) => Promise<void>;
24
+ cancel: () => void;
25
+ }
26
+ /**
27
+ * React binding over {@link createAgentChatClient}: owns the transcript, thread id, and streaming
28
+ * status, and drives one `AbortController` per turn. Reconnection (re-attach on a dropped stream) is
29
+ * handled by the client — the hook just renders whatever parts it reports. Pass client options
30
+ * (`basePath`, `fetch`, `getHeaders`, `resume`) straight through.
31
+ */
32
+ export declare function useAgentChat(options?: UseAgentChatOptions): UseAgentChatResult;
33
+ //# sourceMappingURL=use-agent-chat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-agent-chat.d.ts","sourceRoot":"","sources":["../../../src/react/use-agent-chat.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,sBAAsB,EAE3B,KAAK,oBAAoB,EACzB,KAAK,QAAQ,EAEd,MAAM,oBAAoB,CAAC;AAE5B,6FAA6F;AAC7F,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,4EAA4E;IAC5E,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,WAAW,GAAG,OAAO,CAAC;AAE7D,MAAM,WAAW,mBAAoB,SAAQ,sBAAsB;IACjE;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,oBAAoB,CAAC;CACvD;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,MAAM,EAAE,eAAe,CAAC;IACxB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB;AAQD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,mBAAwB,GAAG,kBAAkB,CAgHlF"}
@@ -0,0 +1,103 @@
1
+ import { useCallback, useEffect, useRef, useState } from 'react';
2
+ import { AgentChatDisconnectedError, createAgentChatClient, } from '../client/index.js';
3
+ function randomId() {
4
+ return (globalThis.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(36).slice(2)}`);
5
+ }
6
+ /**
7
+ * React binding over {@link createAgentChatClient}: owns the transcript, thread id, and streaming
8
+ * status, and drives one `AbortController` per turn. Reconnection (re-attach on a dropped stream) is
9
+ * handled by the client — the hook just renders whatever parts it reports. Pass client options
10
+ * (`basePath`, `fetch`, `getHeaders`, `resume`) straight through.
11
+ */
12
+ export function useAgentChat(options = {}) {
13
+ const { buildBody, ...clientOptions } = options;
14
+ const [messages, setMessages] = useState([]);
15
+ const [status, setStatus] = useState('idle');
16
+ const [error, setError] = useState(null);
17
+ const threadIdRef = useRef(undefined);
18
+ const abortRef = useRef(null);
19
+ const streamingIdRef = useRef(null);
20
+ // Keep one client instance stable across renders; the latest options ride on a ref so option
21
+ // changes take effect on the next send without re-creating the client.
22
+ const optionsRef = useRef(clientOptions);
23
+ optionsRef.current = clientOptions;
24
+ const buildBodyRef = useRef(buildBody);
25
+ buildBodyRef.current = buildBody;
26
+ const clientRef = useRef(createAgentChatClient({
27
+ ...clientOptions,
28
+ getHeaders: () => optionsRef.current.getHeaders?.() ?? {},
29
+ }));
30
+ useEffect(() => {
31
+ return () => {
32
+ abortRef.current?.abort();
33
+ };
34
+ }, []);
35
+ const send = useCallback(async (text) => {
36
+ const trimmed = text.trim();
37
+ if (!trimmed || streamingIdRef.current) {
38
+ return;
39
+ }
40
+ setError(null);
41
+ const userMessage = {
42
+ id: randomId(),
43
+ role: 'user',
44
+ parts: [{ type: 'text', text: trimmed }],
45
+ };
46
+ const assistantId = randomId();
47
+ setMessages((prev) => [
48
+ ...prev,
49
+ userMessage,
50
+ { id: assistantId, role: 'assistant', parts: [], streaming: true },
51
+ ]);
52
+ setStatus('streaming');
53
+ const controller = new AbortController();
54
+ abortRef.current = controller;
55
+ streamingIdRef.current = assistantId;
56
+ const applyParts = (parts) => setMessages((prev) => prev.map((message) => (message.id === assistantId ? { ...message, parts } : message)));
57
+ const stopStreaming = () => setMessages((prev) => prev.map((message) => message.id === assistantId ? { ...message, streaming: false } : message));
58
+ const body = {
59
+ ...(buildBodyRef.current?.(trimmed) ?? { message: trimmed }),
60
+ ...(threadIdRef.current ? { threadId: threadIdRef.current } : {}),
61
+ };
62
+ try {
63
+ await clientRef.current.send({
64
+ body,
65
+ signal: controller.signal,
66
+ onParts: applyParts,
67
+ onThreadId: (id) => {
68
+ threadIdRef.current = id;
69
+ },
70
+ });
71
+ stopStreaming();
72
+ setStatus('idle');
73
+ }
74
+ catch (caught) {
75
+ if (controller.signal.aborted) {
76
+ return;
77
+ }
78
+ // Keep whatever streamed before the drop so the user doesn't lose a long answer.
79
+ if (caught instanceof AgentChatDisconnectedError && caught.parts.length > 0) {
80
+ applyParts(caught.parts);
81
+ }
82
+ stopStreaming();
83
+ setError(caught instanceof Error ? caught.message : 'Failed to reach the agent.');
84
+ setStatus('error');
85
+ }
86
+ finally {
87
+ abortRef.current = null;
88
+ streamingIdRef.current = null;
89
+ }
90
+ }, []);
91
+ const cancel = useCallback(() => {
92
+ abortRef.current?.abort();
93
+ abortRef.current = null;
94
+ const streamingId = streamingIdRef.current;
95
+ if (streamingId) {
96
+ setMessages((prev) => prev.map((message) => message.id === streamingId ? { ...message, streaming: false } : message));
97
+ streamingIdRef.current = null;
98
+ }
99
+ setStatus('idle');
100
+ }, []);
101
+ return { messages, status, error, send, cancel };
102
+ }
103
+ //# sourceMappingURL=use-agent-chat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-agent-chat.js","sourceRoot":"","sources":["../../../src/react/use-agent-chat.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adonis-agora/agent",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "description": "Governed, durable-backed AI agent (chat + tool-calling + governance) for AdonisJS — part of the Agora ecosystem.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -77,6 +77,16 @@
77
77
  "types": "./dist/src/telescope/index.d.ts",
78
78
  "import": "./dist/src/telescope/index.js",
79
79
  "default": "./dist/src/telescope/index.js"
80
+ },
81
+ "./client": {
82
+ "types": "./dist/src/client/index.d.ts",
83
+ "import": "./dist/src/client/index.js",
84
+ "default": "./dist/src/client/index.js"
85
+ },
86
+ "./react": {
87
+ "types": "./dist/src/react/index.d.ts",
88
+ "import": "./dist/src/react/index.js",
89
+ "default": "./dist/src/react/index.js"
80
90
  }
81
91
  },
82
92
  "files": [
@@ -99,9 +109,13 @@
99
109
  "@adonisjs/redis": "^9.2.0",
100
110
  "ai": "^7.0.0",
101
111
  "node-sql-parser": "^5.3.0",
112
+ "react": "^18.0.0 || ^19.0.0",
102
113
  "zod": "^3.23.0 || ^4.0.0"
103
114
  },
104
115
  "peerDependenciesMeta": {
116
+ "react": {
117
+ "optional": true
118
+ },
105
119
  "node-sql-parser": {
106
120
  "optional": true
107
121
  },
@@ -142,10 +156,12 @@
142
156
  "@adonisjs/core": "^7.3.0",
143
157
  "@adonisjs/lucid": "^22.4.0",
144
158
  "@types/node": "^22.0.0",
159
+ "@types/react": "^19.0.0",
145
160
  "ai": "^7.0.0",
146
161
  "better-sqlite3": "^11.0.0",
147
162
  "luxon": "^3.4.0",
148
163
  "node-sql-parser": "^5.3.0",
164
+ "react": "^19.0.0",
149
165
  "typescript": "^5.4.0",
150
166
  "vitest": "^3.0.0",
151
167
  "zod": "^3.25.0"