@agent-platform/ui 0.0.12 → 0.0.14

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 (113) hide show
  1. package/README.md +27 -10
  2. package/dist/index.d.ts +35 -2
  3. package/dist/index.js +2510 -3
  4. package/dist/styles/agent-ui.css +1226 -0
  5. package/dist/styles/globals.css +18 -1188
  6. package/dist/styles/theme.css +34 -0
  7. package/package.json +14 -8
  8. package/dist/components/agent/agent-container-model.d.ts +0 -19
  9. package/dist/components/agent/agent-container-model.js +0 -17
  10. package/dist/components/agent/agent-container-state.d.ts +0 -2
  11. package/dist/components/agent/agent-container-state.js +0 -52
  12. package/dist/components/agent/agent-container-view.d.ts +0 -20
  13. package/dist/components/agent/agent-container-view.js +0 -19
  14. package/dist/components/agent/agent-container-view.test.d.ts +0 -1
  15. package/dist/components/agent/agent-container-view.test.js +0 -16
  16. package/dist/components/agent/agent-container.d.ts +0 -3
  17. package/dist/components/agent/agent-container.js +0 -24
  18. package/dist/components/agent/agent-greeting.d.ts +0 -3
  19. package/dist/components/agent/agent-greeting.js +0 -7
  20. package/dist/components/agent/agent-header.d.ts +0 -3
  21. package/dist/components/agent/agent-header.js +0 -9
  22. package/dist/components/agent/agent-home-card.d.ts +0 -3
  23. package/dist/components/agent/agent-home-card.js +0 -7
  24. package/dist/components/agent/agent-home-cards.d.ts +0 -9
  25. package/dist/components/agent/agent-home-cards.js +0 -13
  26. package/dist/components/agent/agent-input.d.ts +0 -3
  27. package/dist/components/agent/agent-input.js +0 -51
  28. package/dist/components/agent/agent-popup-widget.d.ts +0 -15
  29. package/dist/components/agent/agent-popup-widget.js +0 -49
  30. package/dist/components/agent/agent-screen.d.ts +0 -5
  31. package/dist/components/agent/agent-screen.js +0 -9
  32. package/dist/components/agent/approval-ui-model.d.ts +0 -18
  33. package/dist/components/agent/approval-ui-model.js +0 -27
  34. package/dist/components/agent/approval-ui-model.test.d.ts +0 -1
  35. package/dist/components/agent/approval-ui-model.test.js +0 -39
  36. package/dist/components/agent/defaults.d.ts +0 -5
  37. package/dist/components/agent/defaults.js +0 -12
  38. package/dist/components/agent/index.d.ts +0 -3
  39. package/dist/components/agent/index.js +0 -1
  40. package/dist/components/agent/input-mode.d.ts +0 -5
  41. package/dist/components/agent/input-mode.js +0 -9
  42. package/dist/components/agent/message/index.d.ts +0 -8
  43. package/dist/components/agent/message/index.js +0 -4
  44. package/dist/components/agent/message/markdown.d.ts +0 -6
  45. package/dist/components/agent/message/markdown.js +0 -66
  46. package/dist/components/agent/message/message-item.d.ts +0 -7
  47. package/dist/components/agent/message/message-item.js +0 -24
  48. package/dist/components/agent/message/message-list.d.ts +0 -8
  49. package/dist/components/agent/message/message-list.js +0 -20
  50. package/dist/components/agent/message/message-loading.d.ts +0 -4
  51. package/dist/components/agent/message/message-loading.js +0 -10
  52. package/dist/components/agent/message/tool-call-card.d.ts +0 -9
  53. package/dist/components/agent/message/tool-call-card.js +0 -26
  54. package/dist/components/agent/message/utils.d.ts +0 -8
  55. package/dist/components/agent/message/utils.js +0 -21
  56. package/dist/components/agent/provider/agent-context.d.ts +0 -4
  57. package/dist/components/agent/provider/agent-context.js +0 -13
  58. package/dist/components/agent/provider/agent-provider.d.ts +0 -10
  59. package/dist/components/agent/provider/agent-provider.js +0 -40
  60. package/dist/components/agent/provider/index.d.ts +0 -4
  61. package/dist/components/agent/provider/index.js +0 -2
  62. package/dist/components/agent/provider/parse-sse-buffer.d.ts +0 -9
  63. package/dist/components/agent/provider/parse-sse-buffer.js +0 -23
  64. package/dist/components/agent/provider/runtime-config.d.ts +0 -5
  65. package/dist/components/agent/provider/runtime-config.js +0 -24
  66. package/dist/components/agent/provider/types.d.ts +0 -66
  67. package/dist/components/agent/provider/types.js +0 -1
  68. package/dist/components/agent/provider/use-agent-chat.d.ts +0 -6
  69. package/dist/components/agent/provider/use-agent-chat.js +0 -493
  70. package/dist/components/agent/tool-approval-panel.d.ts +0 -9
  71. package/dist/components/agent/tool-approval-panel.js +0 -11
  72. package/dist/components/agent/types.d.ts +0 -44
  73. package/dist/components/agent/types.js +0 -1
  74. package/dist/components/index.d.ts +0 -7
  75. package/dist/components/index.js +0 -9
  76. package/dist/components/ui/badge.d.ts +0 -9
  77. package/dist/components/ui/badge.js +0 -24
  78. package/dist/components/ui/button.d.ts +0 -10
  79. package/dist/components/ui/button.js +0 -35
  80. package/dist/components/ui/card.d.ts +0 -9
  81. package/dist/components/ui/card.js +0 -24
  82. package/dist/components/ui/input.d.ts +0 -3
  83. package/dist/components/ui/input.js +0 -6
  84. package/dist/components/ui/label.d.ts +0 -4
  85. package/dist/components/ui/label.js +0 -7
  86. package/dist/components/ui/separator.d.ts +0 -4
  87. package/dist/components/ui/separator.js +0 -8
  88. package/dist/components/ui/textarea.d.ts +0 -3
  89. package/dist/components/ui/textarea.js +0 -6
  90. package/dist/lib/index.d.ts +0 -1
  91. package/dist/lib/index.js +0 -1
  92. package/dist/lib/utils.d.ts +0 -2
  93. package/dist/lib/utils.js +0 -5
  94. package/dist/modules/agent/agent.repository.d.ts +0 -58
  95. package/dist/modules/agent/agent.repository.js +0 -235
  96. package/dist/modules/agent/agent.repository.test.d.ts +0 -1
  97. package/dist/modules/agent/agent.repository.test.js +0 -64
  98. package/dist/modules/agent/domain/chat-state.d.ts +0 -64
  99. package/dist/modules/agent/domain/chat-state.js +0 -148
  100. package/dist/modules/agent/domain/chat-state.test.d.ts +0 -1
  101. package/dist/modules/agent/domain/chat-state.test.js +0 -72
  102. package/dist/modules/agent/use-agent-chat.d.ts +0 -6
  103. package/dist/modules/agent/use-agent-chat.js +0 -106
  104. package/dist/modules/agent/usecases/process-stream.d.ts +0 -26
  105. package/dist/modules/agent/usecases/process-stream.js +0 -112
  106. package/dist/modules/agent/usecases/process-stream.test.d.ts +0 -1
  107. package/dist/modules/agent/usecases/process-stream.test.js +0 -91
  108. package/dist/modules/agent/usecases/send-message.d.ts +0 -21
  109. package/dist/modules/agent/usecases/send-message.js +0 -298
  110. package/dist/modules/agent/usecases/send-message.test.d.ts +0 -1
  111. package/dist/modules/agent/usecases/send-message.test.js +0 -257
  112. package/dist/styles/ensure-styles.d.ts +0 -21
  113. package/dist/styles/ensure-styles.js +0 -22
@@ -1,493 +0,0 @@
1
- 'use client';
2
- import { useCallback, useRef, useState } from 'react';
3
- import { parseSSEBuffer } from './parse-sse-buffer';
4
- /** クライアントツール自動継続の最大回数 */
5
- const MAX_CONTINUE_ROUNDS = 10;
6
- function isLikelyJwtToken(token) {
7
- const normalized = token.startsWith('Bearer ') ? token.slice(7) : token;
8
- return normalized.split('.').length === 3;
9
- }
10
- function normalizeErrorMessage(error) {
11
- if (typeof error === 'string' && error.trim().length > 0)
12
- return error;
13
- if (typeof error === 'object' &&
14
- error !== null &&
15
- 'message' in error &&
16
- typeof error.message === 'string') {
17
- return error.message;
18
- }
19
- if (error !== undefined) {
20
- try {
21
- return JSON.stringify(error);
22
- }
23
- catch {
24
- return String(error);
25
- }
26
- }
27
- return 'Unknown error';
28
- }
29
- // --- イベントハンドラ ---
30
- function handleTextDelta(text, accumulatedText, toolCalls, assistantMessageId, setMessages) {
31
- const newText = accumulatedText + text;
32
- setMessages((prev) => {
33
- const updated = [...prev];
34
- const idx = updated.findIndex((m) => m.id === assistantMessageId);
35
- const existing = idx >= 0 ? updated[idx] : undefined;
36
- if (existing) {
37
- const content = [{ type: 'text', text: newText }];
38
- for (const tc of toolCalls) {
39
- content.push({ type: 'tool-call', toolCall: tc });
40
- }
41
- updated[idx] = { id: existing.id, role: existing.role, content, isStreaming: true };
42
- }
43
- return updated;
44
- });
45
- return newText;
46
- }
47
- function handleToolCall(tc, accumulatedText, toolCalls, assistantMessageId, setMessages, setPendingToolCalls) {
48
- toolCalls.push(tc);
49
- setPendingToolCalls((prev) => {
50
- const newMap = new Map(prev);
51
- newMap.set(tc.toolCallId, { toolCall: tc, status: 'pending' });
52
- return newMap;
53
- });
54
- setMessages((prev) => {
55
- const updated = [...prev];
56
- const idx = updated.findIndex((m) => m.id === assistantMessageId);
57
- const existing = idx >= 0 ? updated[idx] : undefined;
58
- if (existing) {
59
- const content = [];
60
- if (accumulatedText) {
61
- content.push({ type: 'text', text: accumulatedText });
62
- }
63
- for (const t of toolCalls) {
64
- content.push({ type: 'tool-call', toolCall: t });
65
- }
66
- updated[idx] = { id: existing.id, role: existing.role, content, isStreaming: true };
67
- }
68
- return updated;
69
- });
70
- }
71
- function handleToolResult(tr, serverResolvedToolIds, setPendingToolCalls) {
72
- serverResolvedToolIds.add(tr.toolCallId);
73
- setPendingToolCalls((prev) => {
74
- const newMap = new Map(prev);
75
- const state = newMap.get(tr.toolCallId);
76
- if (state) {
77
- newMap.set(tr.toolCallId, {
78
- ...state,
79
- status: tr.isError ? 'error' : 'completed',
80
- result: tr.result,
81
- error: tr.isError ? normalizeErrorMessage(tr.result) : undefined,
82
- });
83
- }
84
- return newMap;
85
- });
86
- }
87
- function handleFinish(assistantMessageId, setMessages) {
88
- setMessages((prev) => {
89
- const updated = [...prev];
90
- const idx = updated.findIndex((m) => m.id === assistantMessageId);
91
- const existing = idx >= 0 ? updated[idx] : undefined;
92
- if (existing) {
93
- updated[idx] = {
94
- id: existing.id,
95
- role: existing.role,
96
- content: existing.content,
97
- isStreaming: false,
98
- };
99
- }
100
- return updated;
101
- });
102
- }
103
- // --- メインフック ---
104
- /**
105
- * apiEndpointからAPIを実行
106
- */
107
- async function executeApiEndpoint(toolCall, apiBaseUrl, authHeaders) {
108
- console.log('[executeApiEndpoint] ─────────────────────────────────────────');
109
- console.log('[executeApiEndpoint] toolCall:', JSON.stringify(toolCall, null, 2));
110
- const { apiEndpoint, input } = toolCall;
111
- if (!apiEndpoint) {
112
- console.log('[executeApiEndpoint] ERROR: No API endpoint defined');
113
- return { output: 'No API endpoint defined for this tool', isError: true };
114
- }
115
- console.log('[executeApiEndpoint] apiEndpoint:', JSON.stringify(apiEndpoint, null, 2));
116
- console.log('[executeApiEndpoint] input:', JSON.stringify(input, null, 2));
117
- const inputData = (input ?? {});
118
- let path = apiEndpoint.path;
119
- // パスパラメータを置換 (e.g., /candidates/{id} -> /candidates/123)
120
- const pathParamRegex = /\{(\w+)\}/g;
121
- let match;
122
- const usedParams = new Set();
123
- // biome-ignore lint/suspicious/noAssignInExpressions: 標準的なパターン
124
- while ((match = pathParamRegex.exec(apiEndpoint.path)) !== null) {
125
- const paramName = match[1];
126
- if (!paramName)
127
- continue;
128
- const value = inputData[paramName];
129
- if (value !== undefined) {
130
- path = path.replace(`{${paramName}}`, encodeURIComponent(String(value)));
131
- usedParams.add(paramName);
132
- }
133
- }
134
- // クエリパラメータを構築 (GET/DELETE時)
135
- let url = `${apiBaseUrl}${path}`;
136
- const queryParams = {};
137
- const bodyData = {};
138
- for (const [key, value] of Object.entries(inputData)) {
139
- if (usedParams.has(key) || value === undefined)
140
- continue;
141
- if (['GET', 'DELETE'].includes(apiEndpoint.method)) {
142
- queryParams[key] = String(value);
143
- }
144
- else {
145
- bodyData[key] = value;
146
- }
147
- }
148
- const queryString = new URLSearchParams(queryParams).toString();
149
- if (queryString)
150
- url += `?${queryString}`;
151
- console.log('[executeApiEndpoint] Final URL:', url);
152
- console.log('[executeApiEndpoint] Method:', apiEndpoint.method);
153
- console.log('[executeApiEndpoint] Query params:', JSON.stringify(queryParams, null, 2));
154
- console.log('[executeApiEndpoint] Body data:', JSON.stringify(bodyData, null, 2));
155
- try {
156
- const fetchOptions = {
157
- method: apiEndpoint.method,
158
- headers: {
159
- 'Content-Type': 'application/json',
160
- ...authHeaders,
161
- },
162
- credentials: 'include',
163
- };
164
- if (['POST', 'PUT', 'PATCH'].includes(apiEndpoint.method) && Object.keys(bodyData).length > 0) {
165
- fetchOptions.body = JSON.stringify(bodyData);
166
- console.log('[executeApiEndpoint] Request body:', fetchOptions.body);
167
- }
168
- console.log('[executeApiEndpoint] Sending request...');
169
- const response = await fetch(url, fetchOptions);
170
- const text = await response.text();
171
- console.log('[executeApiEndpoint] Response status:', response.status);
172
- console.log('[executeApiEndpoint] Response text:', text.slice(0, 500));
173
- let data;
174
- try {
175
- data = JSON.parse(text);
176
- }
177
- catch {
178
- data = { raw: text, status: response.status };
179
- }
180
- if (!response.ok) {
181
- return { output: data, isError: true };
182
- }
183
- return { output: data };
184
- }
185
- catch (e) {
186
- return {
187
- output: e instanceof Error ? e.message : 'Network error',
188
- isError: true,
189
- };
190
- }
191
- }
192
- export function useAgentChatInternal(options) {
193
- const { config } = options;
194
- const { endpoint, agentId = 'assistant', apiBaseUrl, executeClientTool, onError, authToken, getAuthToken, getAgentHeaders, disableToolApiAuthHeader = false, } = config;
195
- const [messages, setMessages] = useState([]);
196
- const [threadId, setThreadId] = useState(null);
197
- const [isLoading, setIsLoading] = useState(false);
198
- const [error, setError] = useState(null);
199
- const [pendingToolCalls, setPendingToolCalls] = useState(new Map());
200
- const abortControllerRef = useRef(null);
201
- const buildAgentHeaders = useCallback(async () => {
202
- const headers = { 'Content-Type': 'application/json' };
203
- const token = getAuthToken ? await getAuthToken() : authToken;
204
- console.log('[buildAgentHeaders] Building headers for agent request: ', token ? 'with auth' : 'no auth');
205
- if (token) {
206
- headers['Authorization'] = token.startsWith('Bearer ') ? token : `Bearer ${token}`;
207
- }
208
- const customHeaders = getAgentHeaders ? await getAgentHeaders() : undefined;
209
- if (customHeaders) {
210
- for (const [key, value] of Object.entries(customHeaders)) {
211
- if (value) {
212
- headers[key] = value;
213
- }
214
- }
215
- }
216
- return headers;
217
- }, [authToken, getAuthToken, getAgentHeaders]);
218
- const handleError = useCallback((errorInput) => {
219
- const errorMessage = normalizeErrorMessage(errorInput);
220
- setError(errorMessage);
221
- onError?.(errorMessage);
222
- }, [onError]);
223
- const processStream = useCallback(async (response, assistantMessageId, onThreadId) => {
224
- const reader = response.body?.getReader();
225
- if (!reader)
226
- return { clientToolResults: [], clientToolCalls: [] };
227
- const decoder = new TextDecoder();
228
- let buffer = '';
229
- let accumulatedText = '';
230
- const toolCalls = [];
231
- const serverResolvedToolIds = new Set();
232
- const clientToolResults = [];
233
- try {
234
- while (true) {
235
- const { done, value } = await reader.read();
236
- if (done)
237
- break;
238
- buffer += decoder.decode(value, { stream: true });
239
- const { events, remaining } = parseSSEBuffer(buffer);
240
- buffer = remaining;
241
- for (const event of events) {
242
- switch (event.type) {
243
- case 'thread-id':
244
- onThreadId?.(event.payload.threadId);
245
- break;
246
- case 'text-delta':
247
- accumulatedText = handleTextDelta(event.payload.text, accumulatedText, toolCalls, assistantMessageId, setMessages);
248
- break;
249
- case 'tool-call':
250
- console.log('[processStream] Received tool-call event:', JSON.stringify(event.payload, null, 2));
251
- handleToolCall(event.payload, accumulatedText, toolCalls, assistantMessageId, setMessages, setPendingToolCalls);
252
- break;
253
- case 'tool-result':
254
- handleToolResult(event.payload, serverResolvedToolIds, setPendingToolCalls);
255
- break;
256
- case 'finish':
257
- handleFinish(assistantMessageId, setMessages);
258
- break;
259
- case 'error':
260
- handleError(event.payload.error);
261
- break;
262
- }
263
- }
264
- }
265
- }
266
- finally {
267
- reader.releaseLock();
268
- }
269
- // クライアントツール実行
270
- // apiBaseUrl + apiEndpointがあれば自動実行、なければ従来のexecuteClientTool
271
- console.log('[processStream] ═════════════════════════════════════════');
272
- console.log('[processStream] Client tool execution phase');
273
- console.log('[processStream] Total tool calls received:', toolCalls.length);
274
- console.log('[processStream] Server resolved tool IDs:', Array.from(serverResolvedToolIds));
275
- console.log('[processStream] apiBaseUrl:', apiBaseUrl);
276
- const executedClientToolCalls = [];
277
- const unresolvedCalls = toolCalls.filter((tc) => !serverResolvedToolIds.has(tc.toolCallId));
278
- console.log('[processStream] Unresolved calls (to execute on client):', unresolvedCalls.length);
279
- for (const tc of unresolvedCalls) {
280
- console.log('[processStream] - toolName:', tc.toolName, 'toolCallId:', tc.toolCallId);
281
- console.log('[processStream] input:', JSON.stringify(tc.input, null, 2));
282
- console.log('[processStream] apiEndpoint:', JSON.stringify(tc.apiEndpoint, null, 2));
283
- }
284
- // 認証ヘッダーを構築
285
- const toolApiHeaders = {};
286
- if (!disableToolApiAuthHeader) {
287
- const token = getAuthToken ? await getAuthToken() : authToken;
288
- // Tool APIはcredentials: 'include'でCookie送信されるため、
289
- // 非JWT(例: ANON_KEY)はAuthorizationヘッダーに載せずCookie認証を優先する。
290
- if (token && isLikelyJwtToken(token)) {
291
- toolApiHeaders['Authorization'] = token.startsWith('Bearer ') ? token : `Bearer ${token}`;
292
- }
293
- }
294
- for (const tc of unresolvedCalls) {
295
- // apiBaseUrlとapiEndpointがある場合は自動実行
296
- const canAutoExecute = Boolean(tc.apiEndpoint);
297
- // 従来のexecuteClientToolがある場合はそれを使用
298
- const canLegacyExecute = executeClientTool;
299
- if (!canAutoExecute && !canLegacyExecute) {
300
- // 実行手段がない場合はスキップ
301
- continue;
302
- }
303
- executedClientToolCalls.push(tc);
304
- setPendingToolCalls((prev) => {
305
- const newMap = new Map(prev);
306
- const state = newMap.get(tc.toolCallId);
307
- if (state) {
308
- newMap.set(tc.toolCallId, { ...state, status: 'executing' });
309
- }
310
- return newMap;
311
- });
312
- try {
313
- let result;
314
- if (canAutoExecute) {
315
- // 新しい自動実行パス
316
- result = await executeApiEndpoint(tc, apiBaseUrl, toolApiHeaders);
317
- }
318
- else if (canLegacyExecute) {
319
- // 従来のexecuteClientToolを使用(後方互換性)
320
- result = await executeClientTool(tc);
321
- }
322
- else {
323
- result = { output: 'No execution method available', isError: true };
324
- }
325
- const isError = result.isError ?? false;
326
- setPendingToolCalls((prev) => {
327
- const newMap = new Map(prev);
328
- newMap.set(tc.toolCallId, {
329
- toolCall: tc,
330
- status: isError ? 'error' : 'completed',
331
- result: result.output,
332
- error: isError ? normalizeErrorMessage(result.output) : undefined,
333
- });
334
- return newMap;
335
- });
336
- clientToolResults.push({ toolCallId: tc.toolCallId, result: result.output, isError });
337
- }
338
- catch (e) {
339
- const errorMsg = e instanceof Error ? e.message : 'Unknown error';
340
- setPendingToolCalls((prev) => {
341
- const newMap = new Map(prev);
342
- newMap.set(tc.toolCallId, { toolCall: tc, status: 'error', error: errorMsg });
343
- return newMap;
344
- });
345
- clientToolResults.push({ toolCallId: tc.toolCallId, result: errorMsg, isError: true });
346
- }
347
- }
348
- return { clientToolResults, clientToolCalls: executedClientToolCalls };
349
- }, [apiBaseUrl, executeClientTool, authToken, getAuthToken, disableToolApiAuthHeader, handleError]);
350
- const sendMessage = useCallback(async (message) => {
351
- if (!message.trim() || isLoading)
352
- return;
353
- setIsLoading(true);
354
- setError(null);
355
- const userMessageId = `user-${Date.now()}`;
356
- const userMessage = {
357
- id: userMessageId,
358
- role: 'user',
359
- content: [{ type: 'text', text: message }],
360
- };
361
- setMessages((prev) => [...prev, userMessage]);
362
- const assistantMessageId = `assistant-${Date.now()}`;
363
- const assistantMessage = {
364
- id: assistantMessageId,
365
- role: 'assistant',
366
- content: [],
367
- isStreaming: true,
368
- };
369
- setMessages((prev) => [...prev, assistantMessage]);
370
- try {
371
- abortControllerRef.current = new AbortController();
372
- const headers = await buildAgentHeaders();
373
- const response = await fetch(`${endpoint}/chat`, {
374
- method: 'POST',
375
- headers,
376
- credentials: 'include',
377
- body: JSON.stringify({ threadId, message, agentId }),
378
- signal: abortControllerRef.current.signal,
379
- });
380
- if (!response.ok) {
381
- let errorMessage = 'Failed to send message';
382
- try {
383
- const contentType = response.headers.get('content-type');
384
- if (contentType?.includes('application/json')) {
385
- const errorData = await response.json();
386
- errorMessage =
387
- typeof errorData?.error === 'string'
388
- ? errorData.error
389
- : typeof errorData?.message === 'string'
390
- ? errorData.message
391
- : errorMessage;
392
- }
393
- }
394
- catch (e) {
395
- console.warn('Failed to parse error response:', e);
396
- }
397
- throw new Error(errorMessage);
398
- }
399
- let streamResult = await processStream(response, assistantMessageId, setThreadId);
400
- // ツール継続ループ
401
- let continueRound = 0;
402
- while (streamResult.clientToolResults.length > 0 && continueRound < MAX_CONTINUE_ROUNDS) {
403
- continueRound++;
404
- const continueMessageId = `assistant-${Date.now()}-${continueRound}`;
405
- setMessages((prev) => [
406
- ...prev,
407
- { id: continueMessageId, role: 'assistant', content: [], isStreaming: true },
408
- ]);
409
- const continueHeaders = await buildAgentHeaders();
410
- const continueResponse = await fetch(`${endpoint}/chat/continue`, {
411
- method: 'POST',
412
- headers: continueHeaders,
413
- credentials: 'include',
414
- body: JSON.stringify({
415
- threadId,
416
- agentId,
417
- toolResults: streamResult.clientToolResults,
418
- toolCalls: streamResult.clientToolCalls.map((tc) => ({
419
- toolCallId: tc.toolCallId,
420
- toolName: tc.toolName,
421
- args: tc.input,
422
- })),
423
- }),
424
- signal: abortControllerRef.current?.signal,
425
- });
426
- if (!continueResponse.ok) {
427
- throw new Error('Failed to continue agent after tool execution');
428
- }
429
- streamResult = await processStream(continueResponse, continueMessageId, setThreadId);
430
- }
431
- if (continueRound >= MAX_CONTINUE_ROUNDS && streamResult.clientToolResults.length > 0) {
432
- handleError('Tool execution loop exceeded maximum rounds');
433
- }
434
- }
435
- catch (e) {
436
- if (e instanceof Error && e.name === 'AbortError')
437
- return;
438
- handleError(e);
439
- }
440
- finally {
441
- setIsLoading(false);
442
- abortControllerRef.current = null;
443
- }
444
- }, [isLoading, threadId, endpoint, agentId, processStream, handleError, buildAgentHeaders]);
445
- const loadThread = useCallback(async (loadThreadId) => {
446
- setIsLoading(true);
447
- setError(null);
448
- try {
449
- const threadHeaders = await buildAgentHeaders();
450
- const response = await fetch(`${endpoint}/threads/${loadThreadId}/messages`, {
451
- headers: threadHeaders,
452
- credentials: 'include',
453
- });
454
- if (!response.ok) {
455
- throw new Error('Failed to load thread');
456
- }
457
- const data = await response.json();
458
- setThreadId(loadThreadId);
459
- setMessages(data.messages?.map((m) => ({
460
- id: m.id,
461
- role: m.role,
462
- content: m.content,
463
- isStreaming: false,
464
- })) || []);
465
- }
466
- catch (e) {
467
- setError(normalizeErrorMessage(e));
468
- }
469
- finally {
470
- setIsLoading(false);
471
- }
472
- }, [endpoint, buildAgentHeaders]);
473
- const clearChat = useCallback(() => {
474
- if (abortControllerRef.current) {
475
- abortControllerRef.current.abort();
476
- }
477
- setMessages([]);
478
- setThreadId(null);
479
- setError(null);
480
- setPendingToolCalls(new Map());
481
- }, []);
482
- return {
483
- messages,
484
- threadId,
485
- isLoading,
486
- error,
487
- pendingToolCalls: Array.from(pendingToolCalls.values()),
488
- sendMessage,
489
- loadThread,
490
- clearChat,
491
- config,
492
- };
493
- }
@@ -1,9 +0,0 @@
1
- import type { ActiveToolApprovalRequest, ToolApprovalLabels } from './provider/types';
2
- interface ToolApprovalPanelProps {
3
- activeApprovalRequest: ActiveToolApprovalRequest | null;
4
- approveToolCall: () => void;
5
- rejectToolCall: () => void;
6
- toolApprovalLabels?: ToolApprovalLabels;
7
- }
8
- declare function ToolApprovalPanel({ activeApprovalRequest, approveToolCall, rejectToolCall, toolApprovalLabels, }: ToolApprovalPanelProps): import("react/jsx-runtime").JSX.Element;
9
- export { ToolApprovalPanel };
@@ -1,11 +0,0 @@
1
- 'use client';
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { cn } from '../../lib/utils';
4
- import { Button } from '../ui/button';
5
- import { resolveToolApprovalLabels, resolveToolApprovalPanelState } from './approval-ui-model';
6
- function ToolApprovalPanel({ activeApprovalRequest, approveToolCall, rejectToolCall, toolApprovalLabels, }) {
7
- const approvalLabels = resolveToolApprovalLabels(toolApprovalLabels);
8
- const panelState = resolveToolApprovalPanelState(activeApprovalRequest);
9
- return (_jsx("div", { "data-slot": "agent-tool-approval", className: "w-full border-t border-border bg-muted px-3 pb-3 pt-2", children: _jsxs("div", { "data-state": panelState.isActionable ? 'actionable' : 'idle', className: cn('flex flex-col gap-2 rounded-lg border border-border bg-primary-foreground p-3 shadow-sm', !panelState.isActionable && 'opacity-75'), children: [_jsx("div", { className: "text-sm font-bold text-foreground text-balance", children: approvalLabels.title }), _jsxs("div", { className: "flex flex-col gap-2 pt-1", children: [_jsx(Button, { type: "button", variant: "outline", onClick: approveToolCall, disabled: !panelState.isActionable, className: "justify-start", children: approvalLabels.approveButton }), _jsx(Button, { type: "button", variant: "outline", onClick: rejectToolCall, disabled: !panelState.isActionable, className: "justify-start", children: approvalLabels.rejectButton })] })] }) }));
10
- }
11
- export { ToolApprovalPanel };
@@ -1,44 +0,0 @@
1
- import type { ReactNode } from 'react';
2
- export interface AgentHeaderProps {
3
- historyLabel?: string;
4
- onHistoryClick?: () => void;
5
- onSettingsClick?: () => void;
6
- onNewChatClick?: () => void;
7
- newChatLabel?: string;
8
- settingsAriaLabel?: string;
9
- className?: string;
10
- }
11
- export interface AgentGreetingProps {
12
- greeting?: string;
13
- subtext?: string;
14
- className?: string;
15
- }
16
- export interface AgentHomeCardProps {
17
- id: string;
18
- icon: ReactNode;
19
- title: string;
20
- description: string;
21
- onClick?: () => void;
22
- className?: string;
23
- }
24
- export interface AgentInputProps {
25
- value?: string;
26
- onChange?: (value: string) => void;
27
- onSend?: (message: string) => void;
28
- onAttach?: () => void;
29
- placeholder?: string;
30
- disabled?: boolean;
31
- isLoading?: boolean;
32
- className?: string;
33
- }
34
- export interface AgentContainerProps {
35
- cards?: AgentHomeCardProps[];
36
- onCardClick?: (cardId: string) => void;
37
- /**
38
- * ツール名→日本語ラベルのマッピング
39
- * DEFAULT_TOOL_NAME_LABELSとマージされる
40
- */
41
- toolNameLabels?: Record<string, string>;
42
- inputProps?: Omit<AgentInputProps, 'className'>;
43
- className?: string;
44
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,7 +0,0 @@
1
- export * from './ui/button';
2
- export * from './ui/input';
3
- export * from './ui/label';
4
- export * from './ui/card';
5
- export * from './ui/badge';
6
- export * from './ui/separator';
7
- export * from './agent';
@@ -1,9 +0,0 @@
1
- // UI Components
2
- export * from './ui/button';
3
- export * from './ui/input';
4
- export * from './ui/label';
5
- export * from './ui/card';
6
- export * from './ui/badge';
7
- export * from './ui/separator';
8
- // Agent Components
9
- export * from './agent';
@@ -1,9 +0,0 @@
1
- import * as React from "react";
2
- import { type VariantProps } from "class-variance-authority";
3
- declare const badgeVariants: (props?: ({
4
- variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | null | undefined;
5
- } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
- declare function Badge({ className, variant, asChild, ...props }: React.ComponentProps<"span"> & VariantProps<typeof badgeVariants> & {
7
- asChild?: boolean;
8
- }): import("react/jsx-runtime").JSX.Element;
9
- export { Badge, badgeVariants };
@@ -1,24 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { cva } from "class-variance-authority";
3
- import { Slot } from "radix-ui";
4
- import { cn } from "../../lib/utils";
5
- const badgeVariants = cva("inline-flex items-center justify-center rounded-full border border-transparent px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden", {
6
- variants: {
7
- variant: {
8
- default: "bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
9
- secondary: "bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
10
- destructive: "bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
11
- outline: "border-border text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
12
- ghost: "[a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
13
- link: "text-primary underline-offset-4 [a&]:hover:underline",
14
- },
15
- },
16
- defaultVariants: {
17
- variant: "default",
18
- },
19
- });
20
- function Badge({ className, variant = "default", asChild = false, ...props }) {
21
- const Comp = asChild ? Slot.Root : "span";
22
- return (_jsx(Comp, { "data-slot": "badge", "data-variant": variant, className: cn(badgeVariants({ variant }), className), ...props }));
23
- }
24
- export { Badge, badgeVariants };
@@ -1,10 +0,0 @@
1
- import { type VariantProps } from 'class-variance-authority';
2
- import type * as React from 'react';
3
- declare const buttonVariants: (props?: ({
4
- variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | null | undefined;
5
- size?: "default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
6
- } & import("class-variance-authority/types").ClassProp) | undefined) => string;
7
- declare function Button({ className, variant, size, asChild, ...props }: React.ComponentProps<'button'> & VariantProps<typeof buttonVariants> & {
8
- asChild?: boolean;
9
- }): import("react/jsx-runtime").JSX.Element;
10
- export { Button, buttonVariants };
@@ -1,35 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { cva } from 'class-variance-authority';
3
- import { Slot } from 'radix-ui';
4
- import { cn } from '../../lib/utils';
5
- const buttonVariants = cva("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", {
6
- variants: {
7
- variant: {
8
- default: 'bg-primary text-primary-foreground hover:bg-primary/90',
9
- destructive: 'bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
10
- outline: 'border bg-background hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50',
11
- secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
12
- ghost: 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
13
- link: 'text-primary underline-offset-4 hover:underline',
14
- },
15
- size: {
16
- default: 'h-10 px-4 py-2 has-[>svg]:px-3',
17
- xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",
18
- sm: 'h-9 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5',
19
- lg: 'h-11 rounded-md px-6 has-[>svg]:px-4',
20
- icon: 'size-10',
21
- 'icon-xs': "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3",
22
- 'icon-sm': "size-8 rounded-md [&_svg:not([class*='size-'])]:size-4",
23
- 'icon-lg': "size-10 rounded-md [&_svg:not([class*='size-'])]:size-5",
24
- },
25
- },
26
- defaultVariants: {
27
- variant: 'default',
28
- size: 'default',
29
- },
30
- });
31
- function Button({ className, variant = 'default', size = 'default', asChild = false, ...props }) {
32
- const Comp = asChild ? Slot.Root : 'button';
33
- return (_jsx(Comp, { "data-slot": "button", "data-variant": variant, "data-size": size, className: cn(buttonVariants({ variant, size, className })), ...props }));
34
- }
35
- export { Button, buttonVariants };