@amaster.ai/copilot-client 1.0.0-beta.0 → 1.0.0-beta.10

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/README.md CHANGED
@@ -1,337 +1,135 @@
1
1
  # @amaster.ai/copilot-client
2
2
 
3
- AI copilot client with full A2A Agent-to-Agent protocol support and streaming chat capabilities.
3
+ A2A to A2UI conversion SDK for Copilot API.
4
4
 
5
- ## Features
5
+ ## Overview
6
6
 
7
- - 💬 **Streaming Chat**: Real-time streaming responses with SSE
8
- - 🔄 **Task Management**: Cancel, monitor, and resubscribe to tasks
9
- - 🤖 **Multi-turn Conversations**: Support for conversation history
10
- - 🎯 **A2A Protocol**: Full JSON-RPC 2.0 implementation
11
- - 📡 **Auto Context**: Automatically extracts app context from URL
12
- - 🌳 **Tree-shakeable**: ESM/CJS builds with TypeScript support
7
+ This SDK converts [A2A protocol](https://github.com/google-a2a/A2A) responses from Copilot Agent to [A2UI](https://a2ui.org/) format for rendering.
13
8
 
14
- ## Installation
15
-
16
- ```bash
17
- pnpm add @amaster.ai/copilot-client @amaster.ai/http-client axios @a2a-js/sdk eventsource-parser
18
9
  ```
19
-
20
- ## Quick Start
21
-
22
- ```typescript
23
- import { createCopilotClient } from "@amaster.ai/copilot-client";
24
-
25
- const copilot = createCopilotClient();
26
-
27
- // Stream chat responses
28
- for await (const chunk of copilot.chat([
29
- { role: "user", content: "Hello, how are you?" }
30
- ])) {
31
- console.log(chunk.text); // Print each chunk as it arrives
32
-
33
- if (chunk.isFinal) {
34
- console.log("Chat completed with status:", chunk.status);
35
- }
36
- }
10
+ ┌─────────────────┐ ┌───────────────────────────┐ ┌─────────────────┐
11
+ │ Your App │ │ copilot-client │ │ Copilot Agent │
12
+ │ │ │ │ │ (A2A Server) │
13
+ │ ChatMessage ──────────► A2A Request ───────────────► │
14
+ │ │ │ │ │ │
15
+ │ │ │ ┌───────────────────┐ │ │ A2A Response │
16
+ ServerToClient │ │ │ A2A A2UI │ │ │ parts[]: │
17
+ │ Message[] ◄──────────────│ Conversion │◄────────── - TextPart │
18
+ │ │ │ │ │ │ │ │ - FilePart │
19
+ │ │ │ │ │ TextPart Text │ │ │ - DataPart │
20
+ │ │ │ │ │ FilePart Image │ │ │ │
21
+ │ ▼ │ │ │ DataPart → pass │ │ │ │
22
+ @a2ui/lit │ │ └───────────────────┘ │ └─────────────────┘
23
+ Renderer │ └───────────────────────────┘
24
+ └─────────────────┘
37
25
  ```
38
26
 
39
- ## Architecture
40
-
41
- This client implements the **A2A (Agent-to-Agent)** protocol for AI interactions:
27
+ **A2A → A2UI Conversion:**
42
28
 
43
- - **JSON-RPC 2.0**: Standard protocol for method calls
44
- - **Server-Sent Events (SSE)**: Streaming responses
45
- - **Task-based**: Each conversation is a trackable task
46
- - **Context-aware**: Automatically links to app context
29
+ - `TextPart` A2UI `Text` component
30
+ - `FilePart` (image) A2UI `Image` component
31
+ - `DataPart` (thought) A2UI `Card` with `Text` (💭 subject + description)
32
+ - `DataPart` (toolCall) A2UI `Card` with `Icon` + `Text` (tool name + status)
33
+ - `DataPart` (mimeType: `application/json+a2ui`) → pass through as-is
47
34
 
48
- ## API Reference
49
-
50
- ### `chat(messages, options?)`
51
-
52
- Stream chat responses using simplified API.
53
-
54
- **Parameters:**
55
- - `messages`: Array of chat messages
56
- - `options`: Optional configuration
57
- - `taskId`: Continue an existing task (optional)
58
-
59
- **Returns:** `AsyncGenerator<ChatChunk>`
35
+ ## Installation
60
36
 
61
- ```typescript
62
- const messages = [
63
- { role: "system", content: "You are a helpful assistant" },
64
- { role: "user", content: "What is TypeScript?" },
65
- ];
66
-
67
- for await (const chunk of copilot.chat(messages)) {
68
- process.stdout.write(chunk.text); // Stream output
69
-
70
- // chunk.status: Current state (RUNNING, SUCCEEDED, FAILED, CANCELLED)
71
- // chunk.isFinal: true when chat is complete
72
- }
37
+ ```bash
38
+ pnpm add @amaster.ai/copilot-client
73
39
  ```
74
40
 
75
- ### Types
76
-
77
- ```typescript
78
- interface ChatMessage {
79
- role: "system" | "user" | "assistant";
80
- content: string;
81
- }
82
-
83
- interface ChatChunk {
84
- taskId: string; // Unique task identifier
85
- text: string; // Chunk of response text
86
- status: TaskState; // RUNNING | SUCCEEDED | FAILED | CANCELLED
87
- isFinal: boolean | undefined; // Whether this is the final chunk
88
- }
89
-
90
- interface ChatOptions {
91
- taskId?: string; // Optional: provide your own task ID to resume
92
- }
41
+ ### Peer Dependencies
93
42
 
94
- type TaskState = "RUNNING" | "SUCCEEDED" | "FAILED" | "CANCELLED";
43
+ ```bash
44
+ pnpm add @a2a-js/sdk @a2ui/lit
95
45
  ```
96
46
 
97
- ### `cancelChat(taskId)`
98
-
99
- Cancel an ongoing chat task.
47
+ ## Usage
100
48
 
101
49
  ```typescript
102
- const taskId = "task-123";
103
- const result = await copilot.cancelChat(taskId);
50
+ import { createCopilotA2UIClient, Data } from "@amaster.ai/copilot-client";
104
51
 
105
- if (result.data) {
106
- console.log("Chat cancelled successfully");
107
- }
108
- ```
52
+ const client = createCopilotA2UIClient();
109
53
 
110
- ### `getChatStatus(taskId)`
54
+ // Create A2UI message processor
55
+ const processor = Data.createSignalA2uiMessageProcessor();
111
56
 
112
- Get current status of a chat task.
57
+ // Stream and render
58
+ for await (const messages of client.chat([{ role: "user", content: "Hello" }])) {
59
+ // messages is ServerToClientMessage[] (A2UI standard type)
60
+ processor.processMessages(messages);
113
61
 
114
- ```typescript
115
- const result = await copilot.getChatStatus("task-123");
116
-
117
- if (result.data) {
118
- console.log("Task status:", result.data.result.status.state);
62
+ const surfaces = processor.getSurfaces();
63
+ for (const [surfaceId, surface] of surfaces.entries()) {
64
+ // Render with @a2ui/lit
65
+ }
119
66
  }
120
67
  ```
121
68
 
122
- ## Usage Examples
69
+ ## API
123
70
 
124
- ### Multi-turn Conversation
71
+ ### `createCopilotA2UIClient(http?)`
125
72
 
126
- ```typescript
127
- const messages: ChatMessage[] = [];
73
+ Creates a Copilot A2UI client.
128
74
 
129
- // First message
130
- messages.push({ role: "user", content: "What is React?" });
75
+ ### `client.chat(messages, options?)`
131
76
 
132
- let response = "";
133
- for await (const chunk of copilot.chat(messages)) {
134
- response += chunk.text;
135
- }
77
+ Streams A2UI messages converted from A2A response.
136
78
 
137
- messages.push({ role: "assistant", content: response });
138
-
139
- // Follow-up message
140
- messages.push({ role: "user", content: "Can you give me an example?" });
141
-
142
- response = "";
143
- for await (const chunk of copilot.chat(messages)) {
144
- response += chunk.text;
145
- }
146
- ```
147
-
148
- ### With System Prompt
149
-
150
- ```typescript
151
- const messages = [
152
- {
153
- role: "system",
154
- content: "You are a coding assistant specialized in TypeScript."
155
- },
156
- {
157
- role: "user",
158
- content: "How do I define an interface?"
159
- },
160
- ];
161
-
162
- for await (const chunk of copilot.chat(messages)) {
163
- console.log(chunk.text);
164
- }
165
- ```
166
-
167
- ### Resume Existing Task
79
+ **Returns:** `AsyncGenerator<ServerToClientMessage[]>`
168
80
 
169
81
  ```typescript
170
- // Start a chat
171
- let taskId: string;
172
- for await (const chunk of copilot.chat([
173
- { role: "user", content: "Tell me a long story" }
174
- ])) {
175
- taskId = chunk.taskId;
176
- console.log(chunk.text);
82
+ interface ChatMessage {
83
+ role: "system" | "user" | "assistant";
84
+ content: string | MessageContent[];
177
85
  }
178
86
 
179
- // Later, continue the same task
180
- for await (const chunk of copilot.chat([
181
- { role: "user", content: "What happened next?" }
182
- ], { taskId })) {
183
- console.log(chunk.text);
87
+ interface ChatOptions {
88
+ taskId?: string;
184
89
  }
185
90
  ```
186
91
 
187
- ### Cancel Long-running Chat
92
+ ### `client.cancelChat(taskId)`
188
93
 
189
- ```typescript
190
- let taskId: string;
191
-
192
- const chatPromise = (async () => {
193
- for await (const chunk of copilot.chat(
194
- [{ role: "user", content: "Write a long essay" }]
195
- )) {
196
- taskId = chunk.taskId;
197
- console.log(chunk.text);
198
- }
199
- })();
94
+ Cancels an ongoing chat task.
200
95
 
201
- // Cancel after 5 seconds
202
- setTimeout(async () => {
203
- if (taskId) {
204
- await copilot.cancelChat(taskId);
205
- console.log("Chat cancelled");
206
- }
207
- }, 5000);
208
- ```
96
+ ### `client.getChatStatus(taskId)`
209
97
 
210
- ### React Integration
98
+ Gets the current status of a chat task.
211
99
 
212
- ```typescript
213
- import { useState } from "react";
214
- import { createCopilotClient } from "@amaster.ai/copilot-client";
215
-
216
- const copilot = createCopilotClient();
217
-
218
- function ChatComponent() {
219
- const [message, setMessage] = useState("");
220
- const [response, setResponse] = useState("");
221
- const [isLoading, setIsLoading] = useState(false);
222
- const [taskId, setTaskId] = useState<string>();
223
-
224
- const handleSend = async () => {
225
- setIsLoading(true);
226
- setResponse("");
227
-
228
- try {
229
- for await (const chunk of copilot.chat([
230
- { role: "user", content: message }
231
- ])) {
232
- setTaskId(chunk.taskId);
233
- setResponse(prev => prev + chunk.text);
234
- }
235
- } finally {
236
- setIsLoading(false);
237
- }
238
- };
239
-
240
- const handleCancel = async () => {
241
- if (taskId) {
242
- await copilot.cancelChat(taskId);
243
- setIsLoading(false);
244
- }
245
- };
246
-
247
- return (
248
- <div>
249
- <input
250
- value={message}
251
- onChange={e => setMessage(e.target.value)}
252
- disabled={isLoading}
253
- />
254
- <button onClick={handleSend} disabled={isLoading}>
255
- Send
256
- </button>
257
- {isLoading && (
258
- <button onClick={handleCancel}>Cancel</button>
259
- )}
260
- <div>{response}</div>
261
- </div>
262
- );
263
- }
264
- ```
265
-
266
- ## Custom HTTP Client
267
-
268
- You can provide your own pre-configured HTTP client:
100
+ ## Multimodal Input
269
101
 
270
102
  ```typescript
271
- import { createHttpClient } from "@amaster.ai/http-client";
272
- import axios from "axios";
273
-
274
- // Configure axios instance
275
- const axiosInstance = axios.create({
276
- baseURL: "https://api.example.com",
277
- timeout: 30000,
278
- headers: {
279
- "X-Custom-Header": "value"
280
- }
281
- });
282
-
283
- // Create HTTP client with custom axios
284
- const httpClient = createHttpClient(axiosInstance);
285
-
286
- // Create copilot client with custom HTTP client
287
- const copilot = createCopilotClient(httpClient);
103
+ // Text
104
+ { role: "user", content: "Hello" }
105
+
106
+ // Image
107
+ { role: "user", content: [
108
+ { type: "text", text: "What's this?" },
109
+ { type: "image", url: "https://..." }
110
+ ]}
111
+
112
+ // File
113
+ { role: "user", content: [
114
+ { type: "file", url: "https://...", name: "doc.pdf" }
115
+ ]}
288
116
  ```
289
117
 
290
- ## Error Handling
118
+ ## Types
119
+
120
+ All output types are standard A2UI types from `@a2ui/lit`:
291
121
 
292
122
  ```typescript
293
- try {
294
- for await (const chunk of copilot.chat([
295
- { role: "user", content: "Hello" }
296
- ])) {
297
- console.log(chunk.text);
298
-
299
- // Check for errors in status
300
- if (chunk.status === "FAILED" && chunk.isFinal) {
301
- console.error("Chat failed");
302
- break;
303
- }
304
- }
305
- } catch (error) {
306
- console.error("Chat error:", error);
307
- }
123
+ import type { ServerToClientMessage, Surface, MessageProcessor } from "@amaster.ai/copilot-client";
124
+ import { Data, Types } from "@amaster.ai/copilot-client";
308
125
  ```
309
126
 
310
- ## How It Works
311
-
312
- ### A2A Protocol
313
-
314
- The client implements the A2A (Agent-to-Agent) protocol using JSON-RPC 2.0:
315
-
316
- 1. **Message Streaming**: `method: "message/stream"` - Send message and receive streaming response
317
- 2. **Task Cancellation**: `method: "tasks/cancel"` - Cancel an ongoing task
318
- 3. **Task Status**: `method: "tasks/get"` - Get task status
319
- 4. **Task Resubscription**: Reconnect to an existing task stream
320
-
321
- ### Auto Context Extraction
322
-
323
- The client automatically extracts `contextId` from:
324
- 1. URL path: `/app/{app_id}/...`
325
- 2. Domain subdomain: `{app_id}-{env}.amaster.local`
326
-
327
- This links conversations to the current app context.
328
-
329
- ### SSE Streaming
127
+ ## References
330
128
 
331
- Uses `eventsource-parser` for robust SSE parsing:
332
- - Handles reconnections
333
- - Parses JSON payloads
334
- - Manages stream lifecycle
129
+ - [A2UI Documentation](https://a2ui.org/)
130
+ - [A2UI Components](https://a2ui.org/reference/components/)
131
+ - [A2UI Messages](https://a2ui.org/reference/messages/)
132
+ - [A2A Protocol](https://github.com/google-a2a/A2A)
335
133
 
336
134
  ## License
337
135
 
package/dist/index.cjs CHANGED
@@ -1,237 +1,3 @@
1
- 'use strict';
2
-
3
- var sdk = require('@a2a-js/sdk');
4
- var eventsourceParser = require('eventsource-parser');
5
- var httpClient = require('@amaster.ai/http-client');
6
-
7
- // src/copilot-client.ts
8
- function generateUUID() {
9
- if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
10
- return crypto.randomUUID();
11
- }
12
- if (typeof crypto !== "undefined" && typeof crypto.getRandomValues === "function") {
13
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
14
- const randomValues = crypto.getRandomValues(new Uint8Array(1));
15
- const r = (randomValues[0] ?? 0) % 16;
16
- const v = c === "x" ? r : r & 3 | 8;
17
- return v.toString(16);
18
- });
19
- }
20
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
21
- const r = Math.random() * 16 | 0;
22
- const v = c === "x" ? r : r & 3 | 8;
23
- return v.toString(16);
24
- });
25
- }
26
- function extractAppIdFromUrl() {
27
- if (typeof window === "undefined") {
28
- return null;
29
- }
30
- try {
31
- const url = window.location.href;
32
- const pathMatch = /\/app\/([\da-f-]+)(?:\/|$)/.exec(url);
33
- if (pathMatch && pathMatch[1]) {
34
- return pathMatch[1];
35
- }
36
- const hostname = window.location.hostname;
37
- const domainMatch = /^([\da-f-]+)(?:-[^.]+)?\.amaster\.(?:local|ai)$/.exec(hostname);
38
- if (domainMatch && domainMatch[1]) {
39
- return domainMatch[1];
40
- }
41
- return null;
42
- } catch {
43
- return null;
44
- }
45
- }
46
- async function* streamSSEResponse(response) {
47
- if (!response.body) {
48
- return;
49
- }
50
- const reader = response.body.getReader();
51
- const decoder = new TextDecoder();
52
- const queue = [];
53
- const parser = eventsourceParser.createParser({
54
- onEvent: (event) => {
55
- try {
56
- queue.push(JSON.parse(event.data));
57
- } catch {
58
- }
59
- }
60
- });
61
- try {
62
- while (true) {
63
- const { done, value } = await reader.read();
64
- if (done) {
65
- break;
66
- }
67
- parser.feed(decoder.decode(value, { stream: true }));
68
- while (queue.length > 0) {
69
- const item = queue.shift();
70
- if (item) {
71
- yield item;
72
- }
73
- }
74
- }
75
- } finally {
76
- reader.releaseLock();
77
- }
78
- }
79
- function extractTextFromResponse(response) {
80
- if ("error" in response) {
81
- return "";
82
- }
83
- const result = response.result;
84
- if (!result) {
85
- return "";
86
- }
87
- if ("kind" in result && result.kind === "status-update") {
88
- const parts = result.status?.message?.parts;
89
- if (!parts) {
90
- return "";
91
- }
92
- return parts.filter((part) => part.kind === "text").map((part) => part.text).join("");
93
- }
94
- return "";
95
- }
96
- function parseChunk(response) {
97
- if ("error" in response) {
98
- return null;
99
- }
100
- const result = response.result;
101
- if (!result) {
102
- return null;
103
- }
104
- if ("kind" in result && result.kind === "status-update") {
105
- return {
106
- taskId: result.taskId,
107
- text: extractTextFromResponse(response),
108
- status: result.status.state,
109
- isFinal: result.final ?? false
110
- };
111
- }
112
- return null;
113
- }
114
- function createCopilotClient(http = httpClient.createHttpClient()) {
115
- const baseUrl = "/api/proxy/builtin/platform/copilot";
116
- const internal = {
117
- getAgentCard() {
118
- return http.request({
119
- url: `${baseUrl}/${sdk.AGENT_CARD_PATH}`,
120
- method: "GET"
121
- });
122
- },
123
- sendMessage(request) {
124
- return http.request({
125
- url: baseUrl,
126
- method: "POST",
127
- data: request
128
- });
129
- },
130
- async *sendMessageStream(request) {
131
- try {
132
- const response = await fetch(baseUrl, {
133
- method: "POST",
134
- headers: {
135
- "Content-Type": "application/json"
136
- },
137
- credentials: "include",
138
- body: JSON.stringify(request)
139
- });
140
- if (!response.ok) {
141
- throw new Error(`Stream request failed: ${response.statusText}`);
142
- }
143
- yield* streamSSEResponse(response);
144
- } catch {
145
- }
146
- },
147
- cancelTask(request) {
148
- return http.request({
149
- url: baseUrl,
150
- method: "POST",
151
- data: request
152
- });
153
- },
154
- getTask(request) {
155
- return http.request({
156
- url: baseUrl,
157
- method: "POST",
158
- data: request
159
- });
160
- },
161
- async *resubscribeTask(request) {
162
- try {
163
- const response = await fetch(baseUrl, {
164
- method: "POST",
165
- headers: {
166
- "Content-Type": "application/json"
167
- },
168
- credentials: "include",
169
- body: JSON.stringify(request)
170
- });
171
- if (!response.ok) {
172
- throw new Error(`Stream request failed: ${response.statusText}`);
173
- }
174
- yield* streamSSEResponse(response);
175
- } catch {
176
- }
177
- },
178
- // ============ Simplified API Implementation ============
179
- async *chat(messages, options = {}) {
180
- const { taskId } = options;
181
- const systemMsg = messages.find((m) => m.role === "system");
182
- const nonSystemMsgs = messages.filter((m) => m.role !== "system");
183
- const lastUserMsg = nonSystemMsgs[nonSystemMsgs.length - 1];
184
- const request = {
185
- jsonrpc: "2.0",
186
- id: generateUUID(),
187
- method: "message/stream",
188
- params: {
189
- message: {
190
- contextId: extractAppIdFromUrl() || generateUUID(),
191
- kind: "message",
192
- messageId: generateUUID(),
193
- role: "user",
194
- parts: [{ kind: "text", text: lastUserMsg?.content ?? "" }],
195
- ...taskId && { taskId },
196
- ...systemMsg && {
197
- metadata: { systemPrompt: systemMsg.content }
198
- }
199
- }
200
- }
201
- };
202
- for await (const response of this.sendMessageStream(request)) {
203
- const chunk = parseChunk(response);
204
- if (chunk) {
205
- yield chunk;
206
- }
207
- }
208
- },
209
- cancelChat(taskId) {
210
- const request = {
211
- jsonrpc: "2.0",
212
- id: generateUUID(),
213
- method: "tasks/cancel",
214
- params: { id: taskId }
215
- };
216
- return this.cancelTask(request);
217
- },
218
- getChatStatus(taskId) {
219
- const request = {
220
- jsonrpc: "2.0",
221
- id: generateUUID(),
222
- method: "tasks/get",
223
- params: { id: taskId }
224
- };
225
- return this.getTask(request);
226
- }
227
- };
228
- return {
229
- chat: internal.chat.bind(internal),
230
- cancelChat: internal.cancelChat.bind(internal),
231
- getChatStatus: internal.getChatStatus.bind(internal)
232
- };
233
- }
234
-
235
- exports.createCopilotClient = createCopilotClient;
236
- //# sourceMappingURL=index.cjs.map
1
+ 'use strict';var httpClient=require('@amaster.ai/http-client'),eventsourceParser=require('eventsource-parser'),_0_8=require('@a2ui/lit/0.8');function l(){let t=typeof globalThis<"u"?globalThis.crypto:void 0;return t&&typeof t.randomUUID=="function"?t.randomUUID():t&&typeof t.getRandomValues=="function"?"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let n=(t.getRandomValues(new Uint8Array(1))[0]??0)%16;return (e==="x"?n:n&3|8).toString(16)}):"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let i=Math.random()*16|0;return (e==="x"?i:i&3|8).toString(16)})}function h(){if(typeof window>"u")return null;try{let t=window.location.href,e=/\/app\/([\da-f-]+)(?:\/|$)/.exec(t);if(e&&e[1])return e[1];let i=window.location.hostname,n=/^([\da-f-]+)(?:-[^.]+)?\.[\w-]+\.(?:local|ai)$/.exec(i);return n&&n[1]?n[1]:null}catch{return null}}function S(t){return typeof t=="string"?[{kind:"text",text:t}]:t.map(e=>{switch(e.type){case "text":return {kind:"text",text:e.text};case "image":return e.data?{kind:"file",file:{bytes:e.data,mimeType:e.mimeType||"image/png"}}:e.url?{kind:"file",file:{uri:e.url,mimeType:e.mimeType||"image/png"}}:null;case "file":return e.data?{kind:"file",file:{bytes:e.data,...e.mimeType&&{mimeType:e.mimeType},...e.name&&{name:e.name}}}:e.url?{kind:"file",file:{uri:e.url,...e.mimeType&&{mimeType:e.mimeType},...e.name&&{name:e.name}}}:null;default:return null}}).filter(e=>e!==null)}function M(t){return typeof t=="string"?t:t.filter(e=>e.type==="text").map(e=>e.text).join(`
2
+ `)}var k="application/json+a2ui",R="main",A=0;function p(t){return `${t}-${++A}`}function d(t,e){let i=p("text");return {surfaceUpdate:{surfaceId:e,components:[{id:i,component:{Text:{text:{literalString:t},usageHint:"body"}}}]}}}function I(t,e){let i=t.mimeType||"";if(!i.startsWith("image/"))return null;let n=p("image"),s=t.uri||(t.bytes?`data:${i};base64,${t.bytes}`:null);return s?{surfaceUpdate:{surfaceId:e,components:[{id:n,component:{Image:{url:{literalString:s}}}}]}}:null}function U(t,e){if(!t.subject&&!t.description)return null;let i=p("thought"),n=[];n.push({id:i,component:{Card:{child:`${i}-content`}}});let s=[];return t.subject&&s.push(`${i}-subject`),t.description&&s.push(`${i}-desc`),n.push({id:`${i}-content`,component:{Column:{children:{explicitList:s}}}}),t.subject&&n.push({id:`${i}-subject`,component:{Text:{text:{literalString:`\u{1F4AD} ${t.subject}`},usageHint:"h4"}}}),t.description&&n.push({id:`${i}-desc`,component:{Text:{text:{literalString:t.description},usageHint:"caption"}}}),{surfaceUpdate:{surfaceId:e,components:n}}}function b(t,e){let i=t.tool?.displayName||t.tool?.name||t.request?.name||"Tool",n=t.status||"running",s=p("tool"),r=[];r.push({id:s,component:{Card:{child:`${s}-row`}}}),r.push({id:`${s}-row`,component:{Row:{alignment:"center",children:{explicitList:[`${s}-icon`,`${s}-info`]}}}});let o=n==="completed"?"check_circle":n==="failed"?"error":"build";r.push({id:`${s}-icon`,component:{Icon:{name:{literalString:o}}}}),r.push({id:`${s}-info`,component:{Column:{children:{explicitList:[`${s}-name`,`${s}-status`]}}}}),r.push({id:`${s}-name`,component:{Text:{text:{literalString:i},usageHint:"body"}}});let a=n==="completed"?"\u2713 Completed":n==="failed"?"\u2717 Failed":n==="pending"?"\u23F3 Pending...":"\u2699\uFE0F Running...";return r.push({id:`${s}-status`,component:{Text:{text:{literalString:a},usageHint:"caption"}}}),{surfaceUpdate:{surfaceId:e,components:r}}}var u={THOUGHT:"thought",TOOL_CALL_UPDATE:"tool-call-update",TOOL_CALL_CONFIRMATION:"tool-call-confirmation",TEXT_CONTENT:"text-content"};function w(t,e,i=R){let n=[];for(let s of t)if(s.kind==="text")n.push(d(s.text,i));else if(s.kind==="file"&&"file"in s){let r=s.file,o=I(r,i);o&&n.push(o);}else if(s.kind==="data"){let r=s.data;if(s.metadata?.mimeType===k)n.push(r);else if(e===u.THOUGHT){let o=r;if(o.subject){let a=U(o,i);a&&n.push(a);}else o.description&&n.push(d(o.description,i));}else if(e===u.TOOL_CALL_UPDATE||e===u.TOOL_CALL_CONFIRMATION){let o=b(r,i);o&&n.push(o);}else if(e===u.TEXT_CONTENT){let o=r;o.description&&n.push(d(o.description,i));}}return n}function O(t){if("error"in t)return [];let e=t.result;if(!e||!("kind"in e)||e.kind!=="status-update")return [];let i=e.status?.message?.parts;if(!i||i.length===0)return [];let s=e.metadata?.coderAgent?.kind;return w(i,s)}async function*v(t){if(!t.body)return;let e=t.body.getReader(),i=new TextDecoder,n=[],s=eventsourceParser.createParser({onEvent:r=>{try{n.push(JSON.parse(r.data));}catch{}}});try{for(;;){let{done:r,value:o}=await e.read();if(r)break;for(s.feed(i.decode(o,{stream:!0}));n.length>0;){let a=n.shift();a&&(yield a);}}}finally{e.releaseLock();}}function $(t=httpClient.createHttpClient()){let e="/api/proxy/builtin/platform/copilot";async function*i(n){try{let s=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify(n)});if(!s.ok)throw new Error(`Stream request failed: ${s.statusText}`);yield*v(s);}catch{}}return {async*chat(n,s={}){let{taskId:r}=s,o=n.find(c=>c.role==="system"),a=n.filter(c=>c.role!=="system"),m=a[a.length-1],f=m?S(m.content):[{kind:"text",text:""}],g=o?M(o.content):void 0,T={jsonrpc:"2.0",id:l(),method:"message/stream",params:{message:{contextId:h()||l(),kind:"message",messageId:l(),role:"user",parts:f,...r&&{taskId:r},...g&&{metadata:{systemPrompt:g}}}}};for await(let c of i(T)){let x=O(c);x.length>0&&(yield x);}},cancelChat(n){let s={jsonrpc:"2.0",id:l(),method:"tasks/cancel",params:{id:n}};return t.request({url:e,method:"POST",data:s})},getChatStatus(n){let s={jsonrpc:"2.0",id:l(),method:"tasks/get",params:{id:n}};return t.request({url:e,method:"POST",data:s})}}}Object.defineProperty(exports,"Data",{enumerable:true,get:function(){return _0_8.Data}});Object.defineProperty(exports,"Types",{enumerable:true,get:function(){return _0_8.Types}});exports.createCopilotA2UIClient=$;//# sourceMappingURL=index.cjs.map
237
3
  //# sourceMappingURL=index.cjs.map