@nextclaw/ui 0.11.0 → 0.11.1

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 (82) hide show
  1. package/CHANGELOG.md +8 -2
  2. package/dist/assets/{ChannelsList-BqsOYnXz.js → ChannelsList-CVPqrxns.js} +4 -4
  3. package/dist/assets/ChatPage-BO1VUrAY.js +37 -0
  4. package/dist/assets/{DocBrowser-BmL0QXBZ.js → DocBrowser-FBwg8iji.js} +1 -1
  5. package/dist/assets/{LogoBadge-C1HiPZPf.js → LogoBadge-BCmJfRT8.js} +1 -1
  6. package/dist/assets/MarketplacePage-DWxXUOCx.js +49 -0
  7. package/dist/assets/{McpMarketplacePage-CLHFnNBd.js → McpMarketplacePage-Bth9X_hu.js} +2 -2
  8. package/dist/assets/{ModelConfig-LQSR58tc.js → ModelConfig-PkSp_ioc.js} +1 -1
  9. package/dist/assets/ProvidersList-DVDge8wa.js +1 -0
  10. package/dist/assets/RemoteAccessPage-BVkzfEaL.js +1 -0
  11. package/dist/assets/RuntimeConfig-ByJs3khh.js +1 -0
  12. package/dist/assets/{SearchConfig-Chzo_JGs.js → SearchConfig-KZUAqYJN.js} +1 -1
  13. package/dist/assets/{SecretsConfig-CEIbjZYA.js → SecretsConfig-qwB_Y_Ka.js} +2 -2
  14. package/dist/assets/SessionsConfig-CGCl4UTr.js +2 -0
  15. package/dist/assets/index-CrilScMo.css +1 -0
  16. package/dist/assets/{index-j6A_-1b6.js → index-D41ntvb7.js} +6 -6
  17. package/dist/assets/{label-GACO2RzW.js → label-7JEFhkur.js} +1 -1
  18. package/dist/assets/ncp-session-adapter-BOqhkrc-.js +1 -0
  19. package/dist/assets/{page-layout-DjXaK3A3.js → page-layout-B7q511TE.js} +1 -1
  20. package/dist/assets/popover-CywJGmPr.js +1 -0
  21. package/dist/assets/security-config-zi2UxN5r.js +1 -0
  22. package/dist/assets/skeleton-qUJZQ03S.js +1 -0
  23. package/dist/assets/{status-dot-IWEBezqb.js → status-dot-BilwNdTT.js} +1 -1
  24. package/dist/assets/{switch-DCHAJSrA.js → switch-BLp2Pno1.js} +1 -1
  25. package/dist/assets/tabs-custom-CgIdQMGC.js +1 -0
  26. package/dist/assets/useConfirmDialog-BitswAkv.js +1 -0
  27. package/dist/assets/{vendor-CNhxtHCf.js → vendor-D_JxmsLV.js} +87 -87
  28. package/dist/index.html +3 -3
  29. package/package.json +4 -4
  30. package/src/App.test.tsx +42 -10
  31. package/src/App.tsx +5 -40
  32. package/src/api/api-base.test.ts +37 -0
  33. package/src/api/api-base.ts +0 -4
  34. package/src/api/config.ts +2 -270
  35. package/src/api/types.ts +0 -117
  36. package/src/components/chat/ChatPage.tsx +1 -11
  37. package/src/components/chat/ChatSidebar.test.tsx +1 -50
  38. package/src/components/chat/ChatSidebar.tsx +0 -5
  39. package/src/components/chat/README.md +2 -0
  40. package/src/components/chat/chat-attachment-upload-limit.test.ts +41 -0
  41. package/src/components/chat/chat-session-display.ts +9 -0
  42. package/src/components/chat/chat-session-label.service.ts +3 -12
  43. package/src/components/chat/chat-session-preference-sync.test.ts +10 -13
  44. package/src/components/chat/chat-stream/types.ts +4 -57
  45. package/src/components/chat/ncp/NcpChatPage.tsx +3 -3
  46. package/src/components/chat/useHydratedNcpAgent.test.tsx +77 -0
  47. package/src/components/config/README.md +2 -0
  48. package/src/components/config/SessionsConfig.tsx +152 -132
  49. package/src/hooks/use-auth.test.ts +3 -3
  50. package/src/hooks/use-auth.ts +16 -4
  51. package/src/hooks/use-realtime-query-bridge.ts +0 -24
  52. package/src/hooks/useConfig.ts +10 -137
  53. package/src/lib/session-run-status.ts +1 -63
  54. package/src/vite-env.d.ts +1 -0
  55. package/vite.config.ts +4 -4
  56. package/dist/assets/ChatPage-CJBYKR-Y.js +0 -38
  57. package/dist/assets/MarketplacePage-BIRP0NRS.js +0 -49
  58. package/dist/assets/ProvidersList-CwI-mxah.js +0 -1
  59. package/dist/assets/RemoteAccessPage-Cw5BqZb6.js +0 -1
  60. package/dist/assets/RuntimeConfig-DbowSRAb.js +0 -1
  61. package/dist/assets/SessionsConfig-BR8GfGWL.js +0 -2
  62. package/dist/assets/chat-message-CPG7zxRR.js +0 -3
  63. package/dist/assets/index-kaPUhd-8.css +0 -1
  64. package/dist/assets/popover-DTaFiTmU.js +0 -1
  65. package/dist/assets/security-config-Dk-yoKvK.js +0 -1
  66. package/dist/assets/skeleton-Dm2xOBSA.js +0 -1
  67. package/dist/assets/tabs-custom-DKSbDSB9.js +0 -1
  68. package/dist/assets/useConfirmDialog-ByJ8A8n7.js +0 -1
  69. package/src/api/config.stream.test.ts +0 -115
  70. package/src/components/chat/chat-chain.test.ts +0 -22
  71. package/src/components/chat/chat-chain.ts +0 -23
  72. package/src/components/chat/chat-page-data.ts +0 -171
  73. package/src/components/chat/chat-page-runtime.ts +0 -190
  74. package/src/components/chat/chat-stream/nextbot-parsers.ts +0 -52
  75. package/src/components/chat/chat-stream/nextbot-runtime-agent.ts +0 -413
  76. package/src/components/chat/chat-stream/stream-event-adapter.ts +0 -98
  77. package/src/components/chat/chat-stream/transport.ts +0 -253
  78. package/src/components/chat/legacy/LegacyChatPage.tsx +0 -223
  79. package/src/components/chat/managers/chat-input.manager.ts +0 -228
  80. package/src/components/chat/managers/chat-thread.manager.ts +0 -87
  81. package/src/components/chat/presenter/chat.presenter.ts +0 -32
  82. package/src/components/chat/useChatRuntimeController.ts +0 -134
package/dist/index.html CHANGED
@@ -6,9 +6,9 @@
6
6
  <link rel="icon" type="image/svg+xml" href="/logo.svg" />
7
7
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8
8
  <title>NextClaw</title>
9
- <script type="module" crossorigin src="/assets/index-j6A_-1b6.js"></script>
10
- <link rel="modulepreload" crossorigin href="/assets/vendor-CNhxtHCf.js">
11
- <link rel="stylesheet" crossorigin href="/assets/index-kaPUhd-8.css">
9
+ <script type="module" crossorigin src="/assets/index-D41ntvb7.js"></script>
10
+ <link rel="modulepreload" crossorigin href="/assets/vendor-D_JxmsLV.js">
11
+ <link rel="stylesheet" crossorigin href="/assets/index-CrilScMo.css">
12
12
  </head>
13
13
 
14
14
  <body>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/ui",
3
- "version": "0.11.0",
3
+ "version": "0.11.1",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -28,11 +28,11 @@
28
28
  "tailwind-merge": "^2.5.4",
29
29
  "zod": "^3.23.8",
30
30
  "zustand": "^5.0.2",
31
- "@nextclaw/ncp": "0.4.0",
32
- "@nextclaw/ncp-react": "0.4.0",
31
+ "@nextclaw/agent-chat": "0.1.3",
33
32
  "@nextclaw/ncp-http-agent-client": "0.3.4",
34
33
  "@nextclaw/agent-chat-ui": "0.2.5",
35
- "@nextclaw/agent-chat": "0.1.3"
34
+ "@nextclaw/ncp": "0.4.0",
35
+ "@nextclaw/ncp-react": "0.4.1"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@testing-library/react": "^16.3.0",
package/src/App.test.tsx CHANGED
@@ -1,41 +1,73 @@
1
1
  import { render, screen } from '@testing-library/react';
2
2
  import userEvent from '@testing-library/user-event';
3
3
  import { beforeEach, describe, expect, it, vi } from 'vitest';
4
+ import { MemoryRouter } from 'react-router-dom';
5
+ import { I18nProvider } from '@/components/providers/I18nProvider';
6
+ import { ThemeProvider } from '@/components/providers/ThemeProvider';
4
7
  import AppContent from '@/App';
5
8
 
6
9
  const mocks = vi.hoisted(() => ({
7
10
  refetch: vi.fn(),
8
- useAuthStatus: vi.fn()
11
+ useAuthStatus: vi.fn(),
12
+ isTransientAuthStatusBootstrapError: vi.fn()
9
13
  }));
10
14
 
11
15
  vi.mock('@/hooks/use-auth', () => ({
12
- useAuthStatus: mocks.useAuthStatus
16
+ useAuthStatus: mocks.useAuthStatus,
17
+ isTransientAuthStatusBootstrapError: mocks.isTransientAuthStatusBootstrapError
13
18
  }));
14
19
 
15
20
  describe('App auth bootstrap', () => {
21
+ function renderApp() {
22
+ return render(
23
+ <ThemeProvider>
24
+ <I18nProvider>
25
+ <MemoryRouter initialEntries={['/chat']}>
26
+ <AppContent />
27
+ </MemoryRouter>
28
+ </I18nProvider>
29
+ </ThemeProvider>
30
+ );
31
+ }
32
+
16
33
  beforeEach(() => {
17
34
  mocks.refetch.mockReset();
18
35
  mocks.useAuthStatus.mockReset();
36
+ mocks.isTransientAuthStatusBootstrapError.mockReset();
37
+ mocks.isTransientAuthStatusBootstrapError.mockReturnValue(false);
38
+ vi.useRealTimers();
19
39
  });
20
40
 
21
- it('shows an actionable error state instead of staying blank when auth bootstrap fails', async () => {
22
- const user = userEvent.setup();
41
+ it('does not block the app shell for transient bootstrap failures', () => {
42
+ mocks.isTransientAuthStatusBootstrapError.mockReturnValue(true);
23
43
  mocks.useAuthStatus.mockReturnValue({
24
44
  isLoading: false,
25
45
  isError: true,
26
46
  isRefetching: false,
27
- error: new Error('Timed out waiting for remote request response after 5000ms: GET /api/auth/status'),
47
+ error: new Error('Failed to fetch'),
28
48
  refetch: mocks.refetch,
29
49
  data: undefined
30
50
  });
31
51
 
32
- render(<AppContent />);
52
+ renderApp();
53
+
54
+ expect(screen.queryByRole('heading', { name: /waiting for the local ui service to start/i })).toBeNull();
55
+ expect(screen.queryByText('Failed to fetch')).toBeNull();
56
+ });
33
57
 
34
- expect(screen.getByRole('heading', { name: /load authentication status/i })).toBeTruthy();
35
- expect(screen.getByText('Timed out waiting for remote request response after 5000ms: GET /api/auth/status')).toBeTruthy();
58
+ it('does not block the app shell for stable auth bootstrap failures', async () => {
59
+ mocks.useAuthStatus.mockReturnValue({
60
+ isLoading: false,
61
+ isError: true,
62
+ isRefetching: false,
63
+ error: new Error('Authentication required.'),
64
+ refetch: mocks.refetch,
65
+ data: undefined
66
+ });
36
67
 
37
- await user.click(screen.getByRole('button', { name: /retry/i }));
68
+ renderApp();
38
69
 
39
- expect(mocks.refetch).toHaveBeenCalledTimes(1);
70
+ expect(screen.queryByRole('heading', { name: /load authentication status/i })).toBeNull();
71
+ expect(screen.queryByText('Authentication required.')).toBeNull();
40
72
  });
41
73
  });
package/src/App.tsx CHANGED
@@ -3,10 +3,8 @@ import { QueryClientProvider } from '@tanstack/react-query';
3
3
  import { AccountPanel } from '@/account/components/account-panel';
4
4
  import { appQueryClient } from '@/app-query-client';
5
5
  import { LoginPage } from '@/components/auth/login-page';
6
- import { Button } from '@/components/ui/button';
7
6
  import { AppLayout } from '@/components/layout/AppLayout';
8
- import { useAuthStatus } from '@/hooks/use-auth';
9
- import { t } from '@/lib/i18n';
7
+ import { isTransientAuthStatusBootstrapError, useAuthStatus } from '@/hooks/use-auth';
10
8
  import { useRealtimeQueryBridge } from '@/hooks/use-realtime-query-bridge';
11
9
  import { AppPresenterProvider } from '@/presenter/app-presenter-context';
12
10
  import { Toaster } from 'sonner';
@@ -33,29 +31,6 @@ function LazyRoute({ children }: { children: JSX.Element }) {
33
31
  return <Suspense fallback={<RouteFallback />}>{children}</Suspense>;
34
32
  }
35
33
 
36
- function AuthBootstrapErrorState(props: {
37
- message: string;
38
- retrying: boolean;
39
- onRetry: () => void;
40
- }) {
41
- return (
42
- <main className="flex min-h-screen items-center justify-center bg-secondary px-6 py-10">
43
- <div className="w-full max-w-lg rounded-3xl border border-gray-200 bg-white p-8 shadow-card">
44
- <p className="text-xs font-semibold uppercase tracking-[0.24em] text-gray-500">{t('authBrand')}</p>
45
- <h1 className="mt-3 text-2xl font-semibold text-gray-900">{t('authStatusLoadFailed')}</h1>
46
- <p className="mt-3 text-sm leading-6 text-gray-600">
47
- {props.message}
48
- </p>
49
- <div className="mt-6 flex gap-3">
50
- <Button onClick={props.onRetry} disabled={props.retrying}>
51
- {t('authRetryStatus')}
52
- </Button>
53
- </div>
54
- </div>
55
- </main>
56
- );
57
- }
58
-
59
34
  function ProtectedApp() {
60
35
  useRealtimeQueryBridge(appQueryClient);
61
36
 
@@ -95,21 +70,11 @@ function ProtectedApp() {
95
70
 
96
71
  function AuthGate() {
97
72
  const authStatus = useAuthStatus();
73
+ const isTransientBootstrapFailure =
74
+ authStatus.isError && isTransientAuthStatusBootstrapError(authStatus.error);
98
75
 
99
- if (authStatus.isLoading && !authStatus.isError) {
100
- return <RouteFallback />;
101
- }
102
-
103
- if (authStatus.isError) {
104
- return (
105
- <AuthBootstrapErrorState
106
- message={authStatus.error instanceof Error ? authStatus.error.message : t('authStatusLoadFailed')}
107
- retrying={authStatus.isRefetching}
108
- onRetry={() => {
109
- void authStatus.refetch();
110
- }}
111
- />
112
- );
76
+ if ((authStatus.isLoading && !authStatus.isError) || isTransientBootstrapFailure || authStatus.isError) {
77
+ return <ProtectedApp />;
113
78
  }
114
79
 
115
80
  if (authStatus.data?.enabled && !authStatus.data.authenticated) {
@@ -0,0 +1,37 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
2
+
3
+ describe('API_BASE', () => {
4
+ beforeEach(() => {
5
+ vi.resetModules();
6
+ });
7
+
8
+ afterEach(() => {
9
+ vi.unstubAllEnvs();
10
+ vi.unstubAllGlobals();
11
+ });
12
+
13
+ it('prefers explicit VITE_API_BASE when provided', async () => {
14
+ vi.stubEnv('VITE_API_BASE', 'https://api.example.com/');
15
+ vi.stubGlobal('window', {
16
+ location: {
17
+ origin: 'https://remote.claw.cool'
18
+ }
19
+ });
20
+
21
+ const { API_BASE } = await import('@/api/api-base');
22
+
23
+ expect(API_BASE).toBe('https://api.example.com');
24
+ });
25
+
26
+ it('falls back to window origin when no explicit API base is configured', async () => {
27
+ vi.stubGlobal('window', {
28
+ location: {
29
+ origin: 'https://remote.claw.cool'
30
+ }
31
+ });
32
+
33
+ const { API_BASE } = await import('@/api/api-base');
34
+
35
+ expect(API_BASE).toBe('https://remote.claw.cool');
36
+ });
37
+ });
@@ -10,7 +10,3 @@ export const API_BASE = (() => {
10
10
  }
11
11
  return DEFAULT_API_BASE;
12
12
  })();
13
-
14
- if (import.meta.env.DEV && !import.meta.env.VITE_API_BASE) {
15
- console.warn('VITE_API_BASE is not set; falling back to window origin.');
16
- }
package/src/api/config.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { api } from './client';
2
- import { appClient } from '@/transport';
3
2
  import type {
4
3
  AuthEnabledUpdateRequest,
5
4
  AuthLoginRequest,
@@ -30,22 +29,7 @@ import type {
30
29
  SecretsView,
31
30
  ConfigActionExecuteRequest,
32
31
  ConfigActionExecuteResult,
33
- SessionsListView,
34
- SessionHistoryView,
35
- SessionPatchUpdate,
36
- ChatTurnRequest,
37
- ChatTurnView,
38
- ChatTurnStreamDeltaEvent,
39
- ChatTurnStreamErrorEvent,
40
- ChatTurnStreamReadyEvent,
41
- ChatTurnStreamSessionEvent,
42
- ChatCapabilitiesView,
43
32
  ChatSessionTypesView,
44
- ChatTurnStopRequest,
45
- ChatTurnStopResult,
46
- ChatRunListView,
47
- ChatRunState,
48
- ChatRunView,
49
33
  CronListView,
50
34
  CronEnableRequest,
51
35
  CronRunRequest,
@@ -53,8 +37,8 @@ import type {
53
37
  } from './types';
54
38
 
55
39
  // GET /api/auth/status
56
- export async function fetchAuthStatus(): Promise<AuthStatusView> {
57
- const response = await api.get<AuthStatusView>('/api/auth/status', { timeoutMs: 5_000 });
40
+ export async function fetchAuthStatus(options: { timeoutMs?: number } = {}): Promise<AuthStatusView> {
41
+ const response = await api.get<AuthStatusView>('/api/auth/status', { timeoutMs: options.timeoutMs ?? 5_000 });
58
42
  if (!response.ok) {
59
43
  throw new Error(response.error.message);
60
44
  }
@@ -317,216 +301,6 @@ export async function executeConfigAction(
317
301
  return response.data;
318
302
  }
319
303
 
320
-
321
- // GET /api/sessions
322
- export async function fetchSessions(params?: { q?: string; limit?: number; activeMinutes?: number }): Promise<SessionsListView> {
323
- const query = new URLSearchParams();
324
- if (params?.q?.trim()) {
325
- query.set('q', params.q.trim());
326
- }
327
- if (typeof params?.limit === 'number' && Number.isFinite(params.limit)) {
328
- query.set('limit', String(Math.max(0, Math.trunc(params.limit))));
329
- }
330
- if (typeof params?.activeMinutes === 'number' && Number.isFinite(params.activeMinutes)) {
331
- query.set('activeMinutes', String(Math.max(0, Math.trunc(params.activeMinutes))));
332
- }
333
- const suffix = query.toString();
334
- const response = await api.get<SessionsListView>(suffix ? '/api/sessions?' + suffix : '/api/sessions');
335
- if (!response.ok) {
336
- throw new Error(response.error.message);
337
- }
338
- return response.data;
339
- }
340
-
341
- // GET /api/sessions/:key/history
342
- export async function fetchSessionHistory(key: string, limit = 200): Promise<SessionHistoryView> {
343
- const response = await api.get<SessionHistoryView>(`/api/sessions/${encodeURIComponent(key)}/history?limit=${Math.max(1, Math.trunc(limit))}`);
344
- if (!response.ok) {
345
- throw new Error(response.error.message);
346
- }
347
- return response.data;
348
- }
349
-
350
- // PUT /api/sessions/:key
351
- export async function updateSession(
352
- key: string,
353
- data: SessionPatchUpdate
354
- ): Promise<SessionHistoryView> {
355
- const response = await api.put<SessionHistoryView>(`/api/sessions/${encodeURIComponent(key)}`, data);
356
- if (!response.ok) {
357
- throw new Error(response.error.message);
358
- }
359
- return response.data;
360
- }
361
-
362
- // DELETE /api/sessions/:key
363
- export async function deleteSession(key: string): Promise<{ deleted: boolean }> {
364
- const response = await api.delete<{ deleted: boolean }>(`/api/sessions/${encodeURIComponent(key)}`);
365
- if (!response.ok) {
366
- throw new Error(response.error.message);
367
- }
368
- return response.data;
369
- }
370
-
371
- // POST /api/chat/turn
372
- export async function sendChatTurn(data: ChatTurnRequest): Promise<ChatTurnView> {
373
- const response = await api.post<ChatTurnView>('/api/chat/turn', data);
374
- if (!response.ok) {
375
- throw new Error(response.error.message);
376
- }
377
- return response.data;
378
- }
379
-
380
- async function readSseStream(params: {
381
- path: string;
382
- method: 'GET' | 'POST';
383
- body?: unknown;
384
- signal?: AbortSignal;
385
- onReady: (event: ChatTurnStreamReadyEvent) => void;
386
- onDelta: (event: ChatTurnStreamDeltaEvent) => void;
387
- onSessionEvent: (event: ChatTurnStreamSessionEvent) => void;
388
- }): Promise<{ sessionKey: string; reply: string }> {
389
- let finalResult: { sessionKey: string; reply: string } | null = null;
390
- let readySessionKey = '';
391
-
392
- const session = appClient.openStream<ChatTurnView>({
393
- method: params.method,
394
- path: params.path,
395
- ...(params.body !== undefined ? { body: params.body } : {}),
396
- signal: params.signal,
397
- onEvent: (event) => {
398
- if (event.name === 'ready') {
399
- const ready = (event.payload ?? {}) as ChatTurnStreamReadyEvent;
400
- if (typeof ready.sessionKey === 'string' && ready.sessionKey.trim()) {
401
- readySessionKey = ready.sessionKey;
402
- }
403
- params.onReady(ready);
404
- return;
405
- }
406
-
407
- if (event.name === 'delta') {
408
- params.onDelta((event.payload ?? { delta: '' }) as ChatTurnStreamDeltaEvent);
409
- return;
410
- }
411
-
412
- if (event.name === 'session_event') {
413
- params.onSessionEvent({ data: event.payload as ChatTurnStreamSessionEvent['data'] });
414
- return;
415
- }
416
-
417
- if (event.name === 'final') {
418
- const result = event.payload as ChatTurnView;
419
- finalResult = {
420
- sessionKey: typeof result?.sessionKey === 'string' && result.sessionKey.trim()
421
- ? result.sessionKey
422
- : readySessionKey,
423
- reply: typeof result?.reply === 'string' ? result.reply : ''
424
- };
425
- return;
426
- }
427
-
428
- if (event.name === 'error') {
429
- const errorPayload = (event.payload ?? {}) as ChatTurnStreamErrorEvent;
430
- throw new Error((errorPayload.message ?? '').trim() || 'chat stream failed');
431
- }
432
- }
433
- });
434
-
435
- const result = await session.finished;
436
- if (finalResult) {
437
- return finalResult;
438
- }
439
- if (readySessionKey) {
440
- return {
441
- sessionKey: readySessionKey,
442
- reply: typeof result?.reply === 'string' ? result.reply : ''
443
- };
444
- }
445
- if (typeof result?.sessionKey === 'string' && result.sessionKey.trim()) {
446
- return {
447
- sessionKey: result.sessionKey,
448
- reply: typeof result?.reply === 'string' ? result.reply : ''
449
- };
450
- }
451
- throw new Error('chat stream ended without final event');
452
- }
453
-
454
- // POST /api/chat/turn/stream
455
- export async function sendChatTurnStream(
456
- data: ChatTurnRequest,
457
- params: {
458
- signal?: AbortSignal;
459
- onReady: (event: ChatTurnStreamReadyEvent) => void;
460
- onDelta: (event: ChatTurnStreamDeltaEvent) => void;
461
- onSessionEvent: (event: ChatTurnStreamSessionEvent) => void;
462
- }
463
- ): Promise<{ sessionKey: string; reply: string }> {
464
- return readSseStream({
465
- path: '/api/chat/turn/stream',
466
- method: 'POST',
467
- body: data,
468
- signal: params.signal,
469
- onReady: params.onReady,
470
- onDelta: params.onDelta,
471
- onSessionEvent: params.onSessionEvent
472
- });
473
- }
474
-
475
- // GET /api/chat/runs/:runId/stream
476
- export async function streamChatRun(
477
- data: {
478
- runId: string;
479
- fromEventIndex?: number;
480
- },
481
- params: {
482
- signal?: AbortSignal;
483
- onReady: (event: ChatTurnStreamReadyEvent) => void;
484
- onDelta: (event: ChatTurnStreamDeltaEvent) => void;
485
- onSessionEvent: (event: ChatTurnStreamSessionEvent) => void;
486
- }
487
- ): Promise<{ sessionKey: string; reply: string }> {
488
- const query = new URLSearchParams();
489
- if (typeof data.fromEventIndex === 'number' && Number.isFinite(data.fromEventIndex)) {
490
- query.set('fromEventIndex', String(Math.max(0, Math.trunc(data.fromEventIndex))));
491
- }
492
- const suffix = query.toString();
493
- const path = `/api/chat/runs/${encodeURIComponent(data.runId)}/stream${suffix ? `?${suffix}` : ''}`;
494
- return readSseStream({
495
- path,
496
- method: 'GET',
497
- signal: params.signal,
498
- onReady: params.onReady,
499
- onDelta: params.onDelta,
500
- onSessionEvent: params.onSessionEvent
501
- });
502
- }
503
-
504
- // GET /api/chat/capabilities
505
- export async function fetchChatCapabilities(params?: { sessionKey?: string; agentId?: string }): Promise<ChatCapabilitiesView> {
506
- const query = new URLSearchParams();
507
- if (params?.sessionKey?.trim()) {
508
- query.set('sessionKey', params.sessionKey.trim());
509
- }
510
- if (params?.agentId?.trim()) {
511
- query.set('agentId', params.agentId.trim());
512
- }
513
- const suffix = query.toString();
514
- const response = await api.get<ChatCapabilitiesView>(suffix ? `/api/chat/capabilities?${suffix}` : '/api/chat/capabilities');
515
- if (!response.ok) {
516
- throw new Error(response.error.message);
517
- }
518
- return response.data;
519
- }
520
-
521
- // GET /api/chat/session-types
522
- export async function fetchChatSessionTypes(): Promise<ChatSessionTypesView> {
523
- const response = await api.get<ChatSessionTypesView>('/api/chat/session-types');
524
- if (!response.ok) {
525
- throw new Error(response.error.message);
526
- }
527
- return response.data;
528
- }
529
-
530
304
  // GET /api/ncp/session-types
531
305
  export async function fetchNcpChatSessionTypes(): Promise<ChatSessionTypesView> {
532
306
  const response = await api.get<ChatSessionTypesView>('/api/ncp/session-types');
@@ -536,48 +310,6 @@ export async function fetchNcpChatSessionTypes(): Promise<ChatSessionTypesView>
536
310
  return response.data;
537
311
  }
538
312
 
539
- // POST /api/chat/turn/stop
540
- export async function stopChatTurn(data: ChatTurnStopRequest): Promise<ChatTurnStopResult> {
541
- const response = await api.post<ChatTurnStopResult>('/api/chat/turn/stop', data);
542
- if (!response.ok) {
543
- throw new Error(response.error.message);
544
- }
545
- return response.data;
546
- }
547
-
548
- // GET /api/chat/runs
549
- export async function fetchChatRuns(params?: {
550
- sessionKey?: string;
551
- states?: ChatRunState[];
552
- limit?: number;
553
- }): Promise<ChatRunListView> {
554
- const query = new URLSearchParams();
555
- if (params?.sessionKey?.trim()) {
556
- query.set('sessionKey', params.sessionKey.trim());
557
- }
558
- if (Array.isArray(params?.states) && params.states.length > 0) {
559
- query.set('states', params.states.join(','));
560
- }
561
- if (typeof params?.limit === 'number' && Number.isFinite(params.limit)) {
562
- query.set('limit', String(Math.max(0, Math.trunc(params.limit))));
563
- }
564
- const suffix = query.toString();
565
- const response = await api.get<ChatRunListView>(suffix ? `/api/chat/runs?${suffix}` : '/api/chat/runs');
566
- if (!response.ok) {
567
- throw new Error(response.error.message);
568
- }
569
- return response.data;
570
- }
571
-
572
- // GET /api/chat/runs/:runId
573
- export async function fetchChatRun(runId: string): Promise<ChatRunView> {
574
- const response = await api.get<ChatRunView>(`/api/chat/runs/${encodeURIComponent(runId)}`);
575
- if (!response.ok) {
576
- throw new Error(response.error.message);
577
- }
578
- return response.data;
579
- }
580
-
581
313
  // GET /api/cron
582
314
  export async function fetchCronJobs(params?: { all?: boolean }): Promise<CronListView> {
583
315
  const query = new URLSearchParams();
package/src/api/types.ts CHANGED
@@ -211,11 +211,6 @@ export type SessionEntryView = {
211
211
  lastTimestamp?: string;
212
212
  };
213
213
 
214
- export type SessionsListView = {
215
- sessions: SessionEntryView[];
216
- total: number;
217
- };
218
-
219
214
  export type SessionMessageView = {
220
215
  role: string;
221
216
  content: unknown;
@@ -233,17 +228,6 @@ export type SessionEventView = {
233
228
  message?: SessionMessageView;
234
229
  };
235
230
 
236
- export type SessionHistoryView = {
237
- key: string;
238
- totalMessages: number;
239
- totalEvents: number;
240
- sessionType: string;
241
- sessionTypeMutable: boolean;
242
- metadata: Record<string, unknown>;
243
- messages: SessionMessageView[];
244
- events: SessionEventView[];
245
- };
246
-
247
231
  export type NcpSessionSummaryView = NcpSessionSummary;
248
232
 
249
233
  export type NcpSessionsListView = {
@@ -282,112 +266,12 @@ export type SessionPatchUpdate = {
282
266
  clearHistory?: boolean;
283
267
  };
284
268
 
285
- export type ChatTurnRequest = {
286
- message: string;
287
- sessionKey?: string;
288
- agentId?: string;
289
- channel?: string;
290
- chatId?: string;
291
- model?: string;
292
- metadata?: Record<string, unknown>;
293
- };
294
-
295
- export type ChatTurnView = {
296
- reply: string;
297
- sessionKey: string;
298
- agentId?: string;
299
- model?: string;
300
- requestedAt: string;
301
- completedAt: string;
302
- durationMs: number;
303
- };
304
-
305
- export type ChatTurnStreamReadyEvent = {
306
- sessionKey: string;
307
- requestedAt?: string;
308
- runId?: string;
309
- stopSupported?: boolean;
310
- stopReason?: string;
311
- };
312
-
313
269
  export type {
314
270
  ChatSessionTypeCtaView,
315
271
  ChatSessionTypeOptionView,
316
272
  ChatSessionTypesView,
317
273
  } from './chat-session-type.types';
318
274
 
319
- export type ChatTurnStreamDeltaEvent = {
320
- delta: string;
321
- };
322
-
323
- export type ChatTurnStreamSessionEvent = {
324
- data: SessionEventView;
325
- };
326
-
327
- export type ChatTurnStreamErrorEvent = {
328
- code?: string;
329
- message?: string;
330
- };
331
-
332
- export type ChatCapabilitiesView = {
333
- stopSupported: boolean;
334
- stopReason?: string;
335
- };
336
-
337
- export type ChatCommandOptionView = {
338
- name: string;
339
- description: string;
340
- type: 'string' | 'boolean' | 'number';
341
- required?: boolean;
342
- };
343
-
344
- export type ChatCommandView = {
345
- name: string;
346
- description: string;
347
- options?: ChatCommandOptionView[];
348
- };
349
-
350
- export type ChatCommandsView = {
351
- commands: ChatCommandView[];
352
- total: number;
353
- };
354
-
355
- export type ChatTurnStopRequest = {
356
- runId: string;
357
- sessionKey?: string;
358
- agentId?: string;
359
- };
360
-
361
- export type ChatTurnStopResult = {
362
- stopped: boolean;
363
- runId: string;
364
- sessionKey?: string;
365
- reason?: string;
366
- };
367
-
368
- export type ChatRunState = 'queued' | 'running' | 'completed' | 'failed' | 'aborted';
369
-
370
- export type ChatRunView = {
371
- runId: string;
372
- sessionKey: string;
373
- agentId?: string;
374
- model?: string;
375
- state: ChatRunState;
376
- requestedAt: string;
377
- startedAt?: string;
378
- completedAt?: string;
379
- stopSupported: boolean;
380
- stopReason?: string;
381
- error?: string;
382
- reply?: string;
383
- eventCount: number;
384
- };
385
-
386
- export type ChatRunListView = {
387
- runs: ChatRunView[];
388
- total: number;
389
- };
390
-
391
275
  export type CronScheduleView =
392
276
  | { kind: "at"; atMs?: number | null }
393
277
  | { kind: "every"; everyMs?: number | null }
@@ -684,7 +568,6 @@ export type ConfigActionExecuteResult = {
684
568
  // WebSocket events
685
569
  export type WsEvent =
686
570
  | { type: 'config.updated'; payload: { path: string } }
687
- | { type: 'run.updated'; payload: { run: ChatRunView } }
688
571
  | { type: 'session.updated'; payload: { sessionKey: string } }
689
572
  | { type: 'config.reload.started'; payload?: Record<string, unknown> }
690
573
  | { type: 'config.reload.finished'; payload?: Record<string, unknown> }