@assistant-ui/react-google-adk 0.0.8 → 0.0.11

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 (63) hide show
  1. package/README.md +15 -128
  2. package/dist/AdkClient.d.ts +30 -26
  3. package/dist/AdkClient.d.ts.map +1 -1
  4. package/dist/AdkClient.js +131 -165
  5. package/dist/AdkClient.js.map +1 -1
  6. package/dist/AdkEventAccumulator.d.ts +43 -39
  7. package/dist/AdkEventAccumulator.d.ts.map +1 -1
  8. package/dist/AdkEventAccumulator.js +446 -531
  9. package/dist/AdkEventAccumulator.js.map +1 -1
  10. package/dist/AdkSessionAdapter.d.ts +40 -37
  11. package/dist/AdkSessionAdapter.d.ts.map +1 -1
  12. package/dist/AdkSessionAdapter.js +134 -155
  13. package/dist/AdkSessionAdapter.js.map +1 -1
  14. package/dist/contentToParts.d.ts +6 -2
  15. package/dist/contentToParts.d.ts.map +1 -1
  16. package/dist/contentToParts.js +37 -34
  17. package/dist/contentToParts.js.map +1 -1
  18. package/dist/convertAdkMessages.d.ts +7 -3
  19. package/dist/convertAdkMessages.d.ts.map +1 -1
  20. package/dist/convertAdkMessages.js +93 -86
  21. package/dist/convertAdkMessages.js.map +1 -1
  22. package/dist/hooks.d.ts +38 -34
  23. package/dist/hooks.d.ts.map +1 -1
  24. package/dist/hooks.js +132 -155
  25. package/dist/hooks.js.map +1 -1
  26. package/dist/index.d.ts +10 -11
  27. package/dist/index.js +10 -10
  28. package/dist/server/adkEventStream.d.ts +27 -25
  29. package/dist/server/adkEventStream.d.ts.map +1 -1
  30. package/dist/server/adkEventStream.js +91 -126
  31. package/dist/server/adkEventStream.js.map +1 -1
  32. package/dist/server/createAdkApiRoute.d.ts +26 -23
  33. package/dist/server/createAdkApiRoute.d.ts.map +1 -1
  34. package/dist/server/createAdkApiRoute.js +34 -37
  35. package/dist/server/createAdkApiRoute.js.map +1 -1
  36. package/dist/server/index.d.ts +4 -4
  37. package/dist/server/index.js +4 -4
  38. package/dist/server/parseAdkRequest.d.ts +21 -18
  39. package/dist/server/parseAdkRequest.d.ts.map +1 -1
  40. package/dist/server/parseAdkRequest.js +80 -88
  41. package/dist/server/parseAdkRequest.js.map +1 -1
  42. package/dist/structuredEvents.d.ts +6 -2
  43. package/dist/structuredEvents.d.ts.map +1 -1
  44. package/dist/structuredEvents.js +70 -75
  45. package/dist/structuredEvents.js.map +1 -1
  46. package/dist/types.d.ts +231 -227
  47. package/dist/types.d.ts.map +1 -1
  48. package/dist/types.js +15 -12
  49. package/dist/types.js.map +1 -1
  50. package/dist/useAdkMessages.d.ts +32 -25
  51. package/dist/useAdkMessages.d.ts.map +1 -1
  52. package/dist/useAdkMessages.js +155 -182
  53. package/dist/useAdkMessages.js.map +1 -1
  54. package/dist/useAdkRuntime.d.ts +43 -34
  55. package/dist/useAdkRuntime.d.ts.map +1 -1
  56. package/dist/useAdkRuntime.js +219 -273
  57. package/dist/useAdkRuntime.js.map +1 -1
  58. package/package.json +8 -8
  59. package/src/useAdkRuntime.ts +6 -2
  60. package/dist/index.d.ts.map +0 -1
  61. package/dist/index.js.map +0 -1
  62. package/dist/server/index.d.ts.map +0 -1
  63. package/dist/server/index.js.map +0 -1
package/README.md CHANGED
@@ -1,36 +1,31 @@
1
- # @assistant-ui/react-google-adk
1
+ # `@assistant-ui/react-google-adk`
2
2
 
3
- Google ADK (Agent Development Kit) adapter for [assistant-ui](https://www.assistant-ui.com/).
4
-
5
- Connects Google ADK JS agents to assistant-ui's React runtime with streaming, tool calls, multi-agent support, tool confirmations, auth flows, and session state management.
3
+ [Google ADK](https://github.com/google/adk-js) (Agent Development Kit) integration for `@assistant-ui/react`. Connects ADK JS agents to the assistant-ui runtime with streaming, tool calls, multi-agent support, tool confirmations, auth flows, and session-state management.
6
4
 
7
5
  ## Installation
8
6
 
9
- ```sh
10
- npm install @assistant-ui/react @assistant-ui/react-google-adk
7
+ ```bash
8
+ npm install @assistant-ui/react @assistant-ui/react-google-adk @google/adk
11
9
  ```
12
10
 
13
- ## Quick Start
14
-
15
- ### Proxy Mode (with a Next.js API Route)
11
+ ## Usage
16
12
 
17
- **Server** (`app/api/adk/route.ts`):
13
+ The recommended setup proxies through your own API route:
18
14
 
19
- ```typescript
15
+ ```ts
16
+ // app/api/adk/route.ts
20
17
  import { createAdkApiRoute } from "@assistant-ui/react-google-adk/server";
21
18
  import { runner } from "./agent";
22
19
 
23
20
  export const POST = createAdkApiRoute({
24
21
  runner,
25
22
  userId: "default-user",
26
- sessionId: (req) =>
27
- new URL(req.url).searchParams.get("sessionId") ?? "default",
23
+ sessionId: (req) => new URL(req.url).searchParams.get("sessionId") ?? "default",
28
24
  });
29
25
  ```
30
26
 
31
- **Client:**
32
-
33
27
  ```tsx
28
+ // client component
34
29
  import { useAdkRuntime, createAdkStream } from "@assistant-ui/react-google-adk";
35
30
 
36
31
  const runtime = useAdkRuntime({
@@ -38,119 +33,11 @@ const runtime = useAdkRuntime({
38
33
  });
39
34
  ```
40
35
 
41
- ### Direct Mode (connecting to an ADK server)
42
-
43
- ```tsx
44
- import {
45
- useAdkRuntime,
46
- createAdkStream,
47
- createAdkSessionAdapter,
48
- } from "@assistant-ui/react-google-adk";
49
-
50
- const { adapter, load } = createAdkSessionAdapter({
51
- apiUrl: "http://localhost:8000",
52
- appName: "my-app",
53
- userId: "user-1",
54
- });
55
-
56
- const runtime = useAdkRuntime({
57
- stream: createAdkStream({
58
- api: "http://localhost:8000",
59
- appName: "my-app",
60
- userId: "user-1",
61
- }),
62
- sessionAdapter: adapter,
63
- load,
64
- });
65
- ```
66
-
67
- ## API Reference
68
-
69
- ### Client Exports
70
-
71
- #### `createAdkStream(options)`
72
-
73
- Creates an `AdkStreamCallback` that connects to an ADK endpoint via SSE.
74
-
75
- | Option | Type | Description |
76
- |--------|------|-------------|
77
- | `api` | `string` | URL to POST to (proxy route or ADK server base URL) |
78
- | `appName` | `string?` | ADK app name (enables direct mode when set) |
79
- | `userId` | `string?` | ADK user ID (required with `appName`) |
80
- | `headers` | `Record<string, string> \| (() => ...)` | Static or dynamic request headers |
81
-
82
- #### `createAdkSessionAdapter(options)`
83
-
84
- Creates a `RemoteThreadListAdapter` backed by ADK's session REST API.
85
-
86
- Returns `{ adapter, load }` where `load` reconstructs messages from session events.
87
-
88
- | Option | Type | Description |
89
- |--------|------|-------------|
90
- | `apiUrl` | `string` | ADK server base URL |
91
- | `appName` | `string` | ADK app name |
92
- | `userId` | `string` | ADK user ID |
93
- | `headers` | `Record<string, string> \| (() => ...)` | Static or dynamic request headers |
94
-
95
- #### `useAdkRuntime(options)`
96
-
97
- Main hook that creates a full `AssistantRuntime`.
98
-
99
- | Option | Type | Description |
100
- |--------|------|-------------|
101
- | `stream` | `AdkStreamCallback` | Stream callback (use `createAdkStream`) |
102
- | `sessionAdapter` | `RemoteThreadListAdapter?` | Alternative to `cloud` for thread persistence |
103
- | `cloud` | `AssistantCloud?` | Cloud adapter for thread persistence |
104
- | `load` | `(threadId: string) => Promise<{messages}>` | Load thread history |
105
- | `autoCancelPendingToolCalls` | `boolean?` | Auto-cancel pending tools on new message (default: true) |
106
- | `unstable_allowCancellation` | `boolean?` | Enable stream cancellation |
107
- | `getCheckpointId` | `(threadId, messages) => Promise<string?>` | Enable edit/reload |
108
- | `adapters` | `{attachments?, speech?, feedback?}` | Optional adapters |
109
- | `eventHandlers` | `{onError?, onCustomEvent?, onAgentTransfer?}` | Event callbacks |
110
-
111
- ### Hooks
112
-
113
- | Hook | Description |
114
- |------|-------------|
115
- | `useAdkAgentInfo()` | Current agent name and branch path |
116
- | `useAdkSessionState()` | Accumulated session state delta |
117
- | `useAdkSend()` | Send raw ADK messages |
118
- | `useAdkLongRunningToolIds()` | Pending tool IDs awaiting input |
119
- | `useAdkToolConfirmations()` | Tool confirmation requests |
120
- | `useAdkAuthRequests()` | Auth credential requests |
121
- | `useAdkArtifacts()` | Artifact delta (filename → version) |
122
- | `useAdkEscalation()` | Escalation flag |
123
- | `useAdkMessageMetadata()` | Per-message grounding/citation/usage |
124
-
125
- ### Server Exports (`/server`)
126
-
127
- #### `createAdkApiRoute(options)`
128
-
129
- One-liner API route handler combining request parsing and SSE streaming.
130
-
131
- | Option | Type | Description |
132
- |--------|------|-------------|
133
- | `runner` | `AdkRunner` | ADK Runner instance |
134
- | `userId` | `string \| (req) => string` | Static or dynamic user ID |
135
- | `sessionId` | `string \| (req) => string` | Static or dynamic session ID |
136
- | `onError` | `(error) => void` | Error handler |
137
-
138
- #### `adkEventStream(events, options?)`
139
-
140
- Converts an ADK event async generator into an SSE `Response`.
141
-
142
- #### `parseAdkRequest(request)`
143
-
144
- Parses an incoming HTTP request into a structured ADK request.
145
-
146
- #### `toAdkContent(parsed)`
147
-
148
- Converts a parsed request into a Google GenAI `Content` object.
149
-
150
- ## Documentation
36
+ Or connect directly to an ADK server with `createAdkSessionAdapter`; see the docs for the full setup and option reference.
151
37
 
152
- See the [full documentation](https://www.assistant-ui.com/docs/runtimes/google-adk) for setup guides, advanced APIs, and examples.
38
+ ## See also
153
39
 
154
- ## License
40
+ - `@assistant-ui/react-langgraph` for LangGraph SDK agents.
41
+ - `@assistant-ui/react-ag-ui` for the AG-UI protocol.
155
42
 
156
- MIT
43
+ Full reference for client hooks (`useAdkAgentInfo`, `useAdkSessionState`, `useAdkToolConfirmations`, `useAdkAuthRequests`, etc.), server exports, and direct mode at [assistant-ui.com/docs/runtimes/google-adk](https://www.assistant-ui.com/docs/runtimes/google-adk).
@@ -1,28 +1,30 @@
1
- import type { AdkStreamCallback } from "./types.js";
2
- export type CreateAdkStreamOptions = {
3
- /**
4
- * URL to POST to. Either a proxy route (e.g. "/api/adk") or
5
- * an ADK server base URL (e.g. "http://localhost:8000").
6
- *
7
- * When `appName` and `userId` are provided, POSTs to `${api}/run_sse`
8
- * in ADK-native format. Otherwise POSTs directly to `api` in proxy format
9
- * (compatible with `parseAdkRequest`).
10
- */
11
- api: string;
12
- /**
13
- * ADK application name. When provided along with `userId`,
14
- * enables direct connection to an ADK server.
15
- */
16
- appName?: string | undefined;
17
- /**
18
- * ADK user ID. Required when `appName` is provided.
19
- */
20
- userId?: string | undefined;
21
- /**
22
- * Extra headers to send with every request.
23
- * Can be a static object or an async function for dynamic auth tokens.
24
- */
25
- headers?: Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>) | undefined;
1
+ import { AdkStreamCallback } from "./types.js";
2
+
3
+ //#region src/AdkClient.d.ts
4
+ type CreateAdkStreamOptions = {
5
+ /**
6
+ * URL to POST to. Either a proxy route (e.g. "/api/adk") or
7
+ * an ADK server base URL (e.g. "http://localhost:8000").
8
+ *
9
+ * When `appName` and `userId` are provided, POSTs to `${api}/run_sse`
10
+ * in ADK-native format. Otherwise POSTs directly to `api` in proxy format
11
+ * (compatible with `parseAdkRequest`).
12
+ */
13
+ api: string;
14
+ /**
15
+ * ADK application name. When provided along with `userId`,
16
+ * enables direct connection to an ADK server.
17
+ */
18
+ appName?: string | undefined;
19
+ /**
20
+ * ADK user ID. Required when `appName` is provided.
21
+ */
22
+ userId?: string | undefined;
23
+ /**
24
+ * Extra headers to send with every request.
25
+ * Can be a static object or an async function for dynamic auth tokens.
26
+ */
27
+ headers?: Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>) | undefined;
26
28
  };
27
29
  /**
28
30
  * Creates an `AdkStreamCallback` that connects to an ADK endpoint.
@@ -41,5 +43,7 @@ export type CreateAdkStreamOptions = {
41
43
  * });
42
44
  * ```
43
45
  */
44
- export declare function createAdkStream(options: CreateAdkStreamOptions): AdkStreamCallback;
46
+ declare function createAdkStream(options: CreateAdkStreamOptions): AdkStreamCallback;
47
+ //#endregion
48
+ export { CreateAdkStreamOptions, createAdkStream };
45
49
  //# sourceMappingURL=AdkClient.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AdkClient.d.ts","sourceRoot":"","sources":["../src/AdkClient.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAIV,iBAAiB,EAClB,mBAAgB;AAEjB,MAAM,MAAM,sBAAsB,GAAG;IACnC;;;;;;;OAOG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAE7B;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAE5B;;;OAGG;IACH,OAAO,CAAC,EACJ,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACtB,CAAC,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,GAChE,SAAS,CAAC;CACf,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,sBAAsB,GAC9B,iBAAiB,CA0CnB"}
1
+ {"version":3,"file":"AdkClient.d.ts","names":[],"sources":["../src/AdkClient.ts"],"mappings":";;;KAQY,sBAAA;;AAAZ;;;;;;;EASE,GAAA;EAmB2C;;;;EAb3C,OAAA;EAYI;;;EAPJ,MAAA;EAQkD;AAAA;AAqBpD;;EAvBE,OAAA,GACI,MAAA,0BACO,MAAA,mBAAyB,OAAA,CAAQ,MAAA;AAAA;;;;;AAuB1B;;;;;;;;;;;;;iBAFJ,eAAA,CACd,OAAA,EAAS,sBAAA,GACR,iBAAiB"}
package/dist/AdkClient.js CHANGED
@@ -1,179 +1,145 @@
1
1
  import { contentToParts } from "./contentToParts.js";
2
+ //#region src/AdkClient.ts
2
3
  /**
3
- * Creates an `AdkStreamCallback` that connects to an ADK endpoint.
4
- *
5
- * @example Proxy mode (with a Next.js API route)
6
- * ```ts
7
- * const stream = createAdkStream({ api: "/api/adk" });
8
- * ```
9
- *
10
- * @example Direct mode (connecting to ADK server)
11
- * ```ts
12
- * const stream = createAdkStream({
13
- * api: "http://localhost:8000",
14
- * appName: "my-app",
15
- * userId: "user-1",
16
- * });
17
- * ```
18
- */
19
- export function createAdkStream(options) {
20
- const isDirect = options.appName != null;
21
- return async function* (messages, config) {
22
- const headers = await resolveHeaders(options.headers);
23
- let url;
24
- let body;
25
- if (isDirect) {
26
- // Direct mode: POST to ADK server's /run_sse
27
- url = `${options.api}/run_sse`;
28
- const { externalId } = await config.initialize();
29
- body = {
30
- appName: options.appName,
31
- userId: options.userId,
32
- sessionId: externalId,
33
- newMessage: messagesToContent(messages),
34
- streaming: true,
35
- ...(config.stateDelta != null && { stateDelta: config.stateDelta }),
36
- };
37
- }
38
- else {
39
- // Proxy mode: POST in parseAdkRequest-compatible format
40
- url = options.api;
41
- body = messagesToProxyBody(messages, config);
42
- }
43
- const response = await fetch(url, {
44
- method: "POST",
45
- headers: { "Content-Type": "application/json", ...headers },
46
- body: JSON.stringify(body),
47
- signal: config.abortSignal,
48
- });
49
- if (!response.ok) {
50
- throw new Error(`ADK request failed: ${response.status} ${response.statusText}`);
51
- }
52
- yield* parseSSEResponse(response);
53
- };
4
+ * Creates an `AdkStreamCallback` that connects to an ADK endpoint.
5
+ *
6
+ * @example Proxy mode (with a Next.js API route)
7
+ * ```ts
8
+ * const stream = createAdkStream({ api: "/api/adk" });
9
+ * ```
10
+ *
11
+ * @example Direct mode (connecting to ADK server)
12
+ * ```ts
13
+ * const stream = createAdkStream({
14
+ * api: "http://localhost:8000",
15
+ * appName: "my-app",
16
+ * userId: "user-1",
17
+ * });
18
+ * ```
19
+ */
20
+ function createAdkStream(options) {
21
+ const isDirect = options.appName != null;
22
+ return async function* (messages, config) {
23
+ const headers = await resolveHeaders(options.headers);
24
+ let url;
25
+ let body;
26
+ if (isDirect) {
27
+ url = `${options.api}/run_sse`;
28
+ const { externalId } = await config.initialize();
29
+ body = {
30
+ appName: options.appName,
31
+ userId: options.userId,
32
+ sessionId: externalId,
33
+ newMessage: messagesToContent(messages),
34
+ streaming: true,
35
+ ...config.stateDelta != null && { stateDelta: config.stateDelta }
36
+ };
37
+ } else {
38
+ url = options.api;
39
+ body = messagesToProxyBody(messages, config);
40
+ }
41
+ const response = await fetch(url, {
42
+ method: "POST",
43
+ headers: {
44
+ "Content-Type": "application/json",
45
+ ...headers
46
+ },
47
+ body: JSON.stringify(body),
48
+ signal: config.abortSignal
49
+ });
50
+ if (!response.ok) throw new Error(`ADK request failed: ${response.status} ${response.statusText}`);
51
+ yield* parseSSEResponse(response);
52
+ };
54
53
  }
55
- // ── Internal helpers ──
56
54
  async function resolveHeaders(headers) {
57
- if (!headers)
58
- return {};
59
- if (typeof headers === "function")
60
- return await headers();
61
- return headers;
55
+ if (!headers) return {};
56
+ if (typeof headers === "function") return await headers();
57
+ return headers;
62
58
  }
63
59
  /**
64
- * Converts AdkMessage[] (new messages) into ADK Content format
65
- * for the direct `/run_sse` endpoint.
66
- */
60
+ * Converts AdkMessage[] (new messages) into ADK Content format
61
+ * for the direct `/run_sse` endpoint.
62
+ */
67
63
  function messagesToContent(messages) {
68
- const parts = [];
69
- for (const msg of messages) {
70
- if (msg.type === "human") {
71
- for (const part of contentToParts(msg.content)) {
72
- parts.push(part);
73
- }
74
- }
75
- else if (msg.type === "tool") {
76
- let response;
77
- try {
78
- response = JSON.parse(msg.content);
79
- }
80
- catch {
81
- response = msg.content;
82
- }
83
- parts.push({
84
- functionResponse: {
85
- name: msg.name,
86
- id: msg.tool_call_id,
87
- response,
88
- },
89
- });
90
- }
91
- }
92
- if (parts.length === 0) {
93
- parts.push({ text: "" });
94
- }
95
- return { role: "user", parts };
64
+ const parts = [];
65
+ for (const msg of messages) if (msg.type === "human") for (const part of contentToParts(msg.content)) parts.push(part);
66
+ else if (msg.type === "tool") {
67
+ let response;
68
+ try {
69
+ response = JSON.parse(msg.content);
70
+ } catch {
71
+ response = msg.content;
72
+ }
73
+ parts.push({ functionResponse: {
74
+ name: msg.name,
75
+ id: msg.tool_call_id,
76
+ response
77
+ } });
78
+ }
79
+ if (parts.length === 0) parts.push({ text: "" });
80
+ return {
81
+ role: "user",
82
+ parts
83
+ };
96
84
  }
97
85
  /**
98
- * Converts AdkMessage[] into the proxy request body format
99
- * (compatible with `parseAdkRequest`).
100
- */
86
+ * Converts AdkMessage[] into the proxy request body format
87
+ * (compatible with `parseAdkRequest`).
88
+ */
101
89
  function messagesToProxyBody(messages, config) {
102
- const body = {};
103
- if (config.runConfig != null)
104
- body.runConfig = config.runConfig;
105
- if (config.checkpointId != null)
106
- body.checkpointId = config.checkpointId;
107
- if (config.stateDelta != null)
108
- body.stateDelta = config.stateDelta;
109
- // Check if there's a tool result
110
- const toolMsg = messages.find((m) => m.type === "tool");
111
- if (toolMsg && toolMsg.type === "tool") {
112
- // If there are also other messages (e.g. cancellations), send as parts
113
- if (messages.length > 1) {
114
- body.parts = messagesToContent(messages).parts;
115
- return body;
116
- }
117
- let result;
118
- try {
119
- result = JSON.parse(toolMsg.content);
120
- }
121
- catch {
122
- result = toolMsg.content;
123
- }
124
- body.type = "tool-result";
125
- body.toolCallId = toolMsg.tool_call_id;
126
- body.toolName = toolMsg.name;
127
- body.result = result;
128
- body.isError = toolMsg.status === "error";
129
- return body;
130
- }
131
- // Human message(s) - possibly with cancellation tool results prepended
132
- if (messages.length === 1 && messages[0].type === "human") {
133
- const msg = messages[0];
134
- if (typeof msg.content === "string") {
135
- body.message = msg.content;
136
- }
137
- else {
138
- body.parts = contentToParts(msg.content);
139
- }
140
- return body;
141
- }
142
- // Multiple messages (e.g. cancellations + human): send as parts array
143
- body.parts = messagesToContent(messages).parts;
144
- return body;
90
+ const body = {};
91
+ if (config.runConfig != null) body.runConfig = config.runConfig;
92
+ if (config.checkpointId != null) body.checkpointId = config.checkpointId;
93
+ if (config.stateDelta != null) body.stateDelta = config.stateDelta;
94
+ const toolMsg = messages.find((m) => m.type === "tool");
95
+ if (toolMsg && toolMsg.type === "tool") {
96
+ if (messages.length > 1) {
97
+ body.parts = messagesToContent(messages).parts;
98
+ return body;
99
+ }
100
+ let result;
101
+ try {
102
+ result = JSON.parse(toolMsg.content);
103
+ } catch {
104
+ result = toolMsg.content;
105
+ }
106
+ body.type = "tool-result";
107
+ body.toolCallId = toolMsg.tool_call_id;
108
+ body.toolName = toolMsg.name;
109
+ body.result = result;
110
+ body.isError = toolMsg.status === "error";
111
+ return body;
112
+ }
113
+ if (messages.length === 1 && messages[0].type === "human") {
114
+ const msg = messages[0];
115
+ if (typeof msg.content === "string") body.message = msg.content;
116
+ else body.parts = contentToParts(msg.content);
117
+ return body;
118
+ }
119
+ body.parts = messagesToContent(messages).parts;
120
+ return body;
145
121
  }
146
122
  async function* parseSSEResponse(response) {
147
- const reader = response.body.getReader();
148
- const decoder = new TextDecoder();
149
- let buffer = "";
150
- try {
151
- while (true) {
152
- const { done, value } = await reader.read();
153
- if (done)
154
- break;
155
- buffer += decoder.decode(value, { stream: true });
156
- const parts = buffer.split("\n\n");
157
- buffer = parts.pop() ?? "";
158
- for (const part of parts) {
159
- for (const line of part.split("\n")) {
160
- if (line.startsWith("data: ")) {
161
- yield JSON.parse(line.slice(6));
162
- }
163
- }
164
- }
165
- }
166
- // Handle remaining buffer
167
- if (buffer.trim()) {
168
- for (const line of buffer.split("\n")) {
169
- if (line.startsWith("data: ")) {
170
- yield JSON.parse(line.slice(6));
171
- }
172
- }
173
- }
174
- }
175
- finally {
176
- reader.releaseLock();
177
- }
123
+ const reader = response.body.getReader();
124
+ const decoder = new TextDecoder();
125
+ let buffer = "";
126
+ try {
127
+ while (true) {
128
+ const { done, value } = await reader.read();
129
+ if (done) break;
130
+ buffer += decoder.decode(value, { stream: true });
131
+ const parts = buffer.split("\n\n");
132
+ buffer = parts.pop() ?? "";
133
+ for (const part of parts) for (const line of part.split("\n")) if (line.startsWith("data: ")) yield JSON.parse(line.slice(6));
134
+ }
135
+ if (buffer.trim()) {
136
+ for (const line of buffer.split("\n")) if (line.startsWith("data: ")) yield JSON.parse(line.slice(6));
137
+ }
138
+ } finally {
139
+ reader.releaseLock();
140
+ }
178
141
  }
142
+ //#endregion
143
+ export { createAdkStream };
144
+
179
145
  //# sourceMappingURL=AdkClient.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AdkClient.js","sourceRoot":"","sources":["../src/AdkClient.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AdkClient.js","names":[],"sources":["../src/AdkClient.ts"],"sourcesContent":["import { contentToParts } from \"./contentToParts\";\nimport type {\n AdkEvent,\n AdkEventPart,\n AdkMessage,\n AdkStreamCallback,\n} from \"./types\";\n\nexport type CreateAdkStreamOptions = {\n /**\n * URL to POST to. Either a proxy route (e.g. \"/api/adk\") or\n * an ADK server base URL (e.g. \"http://localhost:8000\").\n *\n * When `appName` and `userId` are provided, POSTs to `${api}/run_sse`\n * in ADK-native format. Otherwise POSTs directly to `api` in proxy format\n * (compatible with `parseAdkRequest`).\n */\n api: string;\n\n /**\n * ADK application name. When provided along with `userId`,\n * enables direct connection to an ADK server.\n */\n appName?: string | undefined;\n\n /**\n * ADK user ID. Required when `appName` is provided.\n */\n userId?: string | undefined;\n\n /**\n * Extra headers to send with every request.\n * Can be a static object or an async function for dynamic auth tokens.\n */\n headers?:\n | Record<string, string>\n | (() => Record<string, string> | Promise<Record<string, string>>)\n | undefined;\n};\n\n/**\n * Creates an `AdkStreamCallback` that connects to an ADK endpoint.\n *\n * @example Proxy mode (with a Next.js API route)\n * ```ts\n * const stream = createAdkStream({ api: \"/api/adk\" });\n * ```\n *\n * @example Direct mode (connecting to ADK server)\n * ```ts\n * const stream = createAdkStream({\n * api: \"http://localhost:8000\",\n * appName: \"my-app\",\n * userId: \"user-1\",\n * });\n * ```\n */\nexport function createAdkStream(\n options: CreateAdkStreamOptions,\n): AdkStreamCallback {\n const isDirect = options.appName != null;\n\n return async function* (messages, config) {\n const headers = await resolveHeaders(options.headers);\n\n let url: string;\n let body: unknown;\n\n if (isDirect) {\n // Direct mode: POST to ADK server's /run_sse\n url = `${options.api}/run_sse`;\n const { externalId } = await config.initialize();\n body = {\n appName: options.appName,\n userId: options.userId,\n sessionId: externalId,\n newMessage: messagesToContent(messages),\n streaming: true,\n ...(config.stateDelta != null && { stateDelta: config.stateDelta }),\n };\n } else {\n // Proxy mode: POST in parseAdkRequest-compatible format\n url = options.api;\n body = messagesToProxyBody(messages, config);\n }\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...headers },\n body: JSON.stringify(body),\n signal: config.abortSignal,\n });\n\n if (!response.ok) {\n throw new Error(\n `ADK request failed: ${response.status} ${response.statusText}`,\n );\n }\n\n yield* parseSSEResponse(response);\n };\n}\n\n// ── Internal helpers ──\n\nasync function resolveHeaders(\n headers:\n | Record<string, string>\n | (() => Record<string, string> | Promise<Record<string, string>>)\n | undefined,\n): Promise<Record<string, string>> {\n if (!headers) return {};\n if (typeof headers === \"function\") return await headers();\n return headers;\n}\n\n/**\n * Converts AdkMessage[] (new messages) into ADK Content format\n * for the direct `/run_sse` endpoint.\n */\nfunction messagesToContent(messages: AdkMessage[]): {\n role: string;\n parts: AdkEventPart[];\n} {\n const parts: AdkEventPart[] = [];\n\n for (const msg of messages) {\n if (msg.type === \"human\") {\n for (const part of contentToParts(msg.content)) {\n parts.push(part);\n }\n } else if (msg.type === \"tool\") {\n let response: unknown;\n try {\n response = JSON.parse(msg.content);\n } catch {\n response = msg.content;\n }\n parts.push({\n functionResponse: {\n name: msg.name,\n id: msg.tool_call_id,\n response,\n },\n });\n }\n }\n\n if (parts.length === 0) {\n parts.push({ text: \"\" });\n }\n\n return { role: \"user\", parts };\n}\n\n/**\n * Converts AdkMessage[] into the proxy request body format\n * (compatible with `parseAdkRequest`).\n */\nfunction messagesToProxyBody(\n messages: AdkMessage[],\n config: {\n runConfig?: unknown;\n checkpointId?: string | undefined;\n stateDelta?: Record<string, unknown> | undefined;\n },\n): Record<string, unknown> {\n const body: Record<string, unknown> = {};\n\n if (config.runConfig != null) body.runConfig = config.runConfig;\n if (config.checkpointId != null) body.checkpointId = config.checkpointId;\n if (config.stateDelta != null) body.stateDelta = config.stateDelta;\n\n // Check if there's a tool result\n const toolMsg = messages.find((m) => m.type === \"tool\");\n if (toolMsg && toolMsg.type === \"tool\") {\n // If there are also other messages (e.g. cancellations), send as parts\n if (messages.length > 1) {\n body.parts = messagesToContent(messages).parts;\n return body;\n }\n\n let result: unknown;\n try {\n result = JSON.parse(toolMsg.content);\n } catch {\n result = toolMsg.content;\n }\n body.type = \"tool-result\";\n body.toolCallId = toolMsg.tool_call_id;\n body.toolName = toolMsg.name;\n body.result = result;\n body.isError = toolMsg.status === \"error\";\n return body;\n }\n\n // Human message(s) - possibly with cancellation tool results prepended\n if (messages.length === 1 && messages[0]!.type === \"human\") {\n const msg = messages[0]!;\n if (typeof msg.content === \"string\") {\n body.message = msg.content;\n } else {\n body.parts = contentToParts(msg.content);\n }\n return body;\n }\n\n // Multiple messages (e.g. cancellations + human): send as parts array\n body.parts = messagesToContent(messages).parts;\n return body;\n}\n\nasync function* parseSSEResponse(response: Response): AsyncGenerator<AdkEvent> {\n const reader = response.body!.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const parts = buffer.split(\"\\n\\n\");\n buffer = parts.pop() ?? \"\";\n\n for (const part of parts) {\n for (const line of part.split(\"\\n\")) {\n if (line.startsWith(\"data: \")) {\n yield JSON.parse(line.slice(6)) as AdkEvent;\n }\n }\n }\n }\n\n // Handle remaining buffer\n if (buffer.trim()) {\n for (const line of buffer.split(\"\\n\")) {\n if (line.startsWith(\"data: \")) {\n yield JSON.parse(line.slice(6)) as AdkEvent;\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n}\n"],"mappings":"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"}