@nextclaw/ui 0.12.20-beta.3 → 0.12.20-beta.5

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 (59) hide show
  1. package/CHANGELOG.md +124 -0
  2. package/dist/assets/api-Dai6UR3J.js +15 -0
  3. package/dist/assets/app-manager-provider-BZr5VxCe.js +1 -0
  4. package/dist/assets/{app-navigation.config-BOVDFMnp.js → app-navigation.config-BjIj_FLm.js} +1 -1
  5. package/dist/assets/channels-list-page-L6FFtRYn.js +8 -0
  6. package/dist/assets/{chat-ahMH_i_K.js → chat-ZQIVJChB.js} +6 -6
  7. package/dist/assets/{chat-page-BxlXY-MB.js → chat-page-CR1yI96r.js} +1 -1
  8. package/dist/assets/desktop-update-config-AXzb7OEa.js +1 -0
  9. package/dist/assets/{dialog-csshWetU.js → dialog-DgybjpeU.js} +1 -1
  10. package/dist/assets/{dist-Bl94Ahwx.js → dist-CxcPOISF.js} +1 -1
  11. package/dist/assets/{es2015-JCM5-KtW.js → es2015-BVRlEE06.js} +1 -1
  12. package/dist/assets/index-B7RsQ-ne.js +2 -0
  13. package/dist/assets/marketplace-page-Bj55-6F2.js +1 -0
  14. package/dist/assets/{marketplace-page-DxlxHCFm.js → marketplace-page-ClRW-W3g.js} +2 -2
  15. package/dist/assets/mcp-marketplace-page-DtngnIi0.js +40 -0
  16. package/dist/assets/mcp-marketplace-page-_Wu2VnHy.js +1 -0
  17. package/dist/assets/{model-config-PccJ9XyH.js → model-config-D_y8F0j6.js} +1 -1
  18. package/dist/assets/{notice-card-CCgk6FvF.js → notice-card-uzwjFyML.js} +1 -1
  19. package/dist/assets/{popover-YAsxDBhY.js → popover-C8tMB7tR.js} +1 -1
  20. package/dist/assets/{provider-scoped-model-input-CzpF7cug.js → provider-scoped-model-input-ORZutTDv.js} +1 -1
  21. package/dist/assets/{providers-list-8qDMER8o.js → providers-list-DSc3d8me.js} +1 -1
  22. package/dist/assets/remote-rWiu3cys.js +1 -0
  23. package/dist/assets/runtime-config-page-B4uSax1I.js +1 -0
  24. package/dist/assets/{search-config-D3a65l3r.js → search-config-CaqqlsdW.js} +1 -1
  25. package/dist/assets/{secrets-config-CoMlR_7i.js → secrets-config-llf5ROde.js} +2 -2
  26. package/dist/assets/{select-DIZrwsKU.js → select-uO-zhYsH.js} +1 -1
  27. package/dist/assets/{sessions-config-page-QjH5tgjr.js → sessions-config-page-BqOXte9x.js} +2 -2
  28. package/dist/assets/{setting-row-DiQyrE81.js → setting-row-BIiXR4hx.js} +1 -1
  29. package/dist/assets/{tag-chip-C3wDBe_-.js → tag-chip-DVbgpsYW.js} +1 -1
  30. package/dist/assets/{theme-provider-W704JWF8.js → theme-provider-BU77FNSB.js} +1 -1
  31. package/dist/assets/{tooltip-Dq5Xehpk.js → tooltip-CvAtG-kT.js} +1 -1
  32. package/dist/assets/use-config-D2QgG7qc.js +1 -0
  33. package/dist/assets/{use-confirm-dialog-DBoV5n5P.js → use-confirm-dialog-BBClFV8E.js} +1 -1
  34. package/dist/assets/{use-infinite-scroll-loader-JAicqVC5.js → use-infinite-scroll-loader-CWzpUecQ.js} +1 -1
  35. package/dist/assets/{use-viewport-layout-BX3XqzJ4.js → use-viewport-layout-C6EN0_eq.js} +1 -1
  36. package/dist/index.html +15 -15
  37. package/package.json +9 -9
  38. package/src/app/hooks/use-app-event-consumers.ts +89 -0
  39. package/src/app/index.tsx +2 -2
  40. package/src/features/channels/components/config/channel-form.tsx +7 -9
  41. package/src/features/system-status/components/desktop-update-config.test.tsx +25 -1
  42. package/src/features/system-status/components/desktop-update-config.tsx +0 -7
  43. package/src/features/system-status/managers/runtime-update.manager.ts +18 -20
  44. package/src/shared/lib/transport/transport.types.ts +2 -2
  45. package/tsconfig.json +2 -1
  46. package/vite.config.ts +4 -2
  47. package/vitest.config.ts +4 -2
  48. package/dist/assets/api-BcqDx0tm.js +0 -15
  49. package/dist/assets/app-manager-provider-DVYBjif-.js +0 -1
  50. package/dist/assets/channels-list-page-CsoI4OJm.js +0 -8
  51. package/dist/assets/desktop-update-config-CD6-2PfI.js +0 -1
  52. package/dist/assets/index-CM-57d8J.js +0 -2
  53. package/dist/assets/marketplace-page-DJGDpTAo.js +0 -1
  54. package/dist/assets/mcp-marketplace-page-5UjYRWOR.js +0 -40
  55. package/dist/assets/mcp-marketplace-page-C1XaHZZO.js +0 -1
  56. package/dist/assets/remote-D4TtLPAp.js +0 -1
  57. package/dist/assets/runtime-config-page-DWJHrV7H.js +0 -1
  58. package/dist/assets/use-config-BQJjq1mP.js +0 -1
  59. package/src/app/hooks/use-realtime-query-bridge.ts +0 -105
package/dist/index.html CHANGED
@@ -78,21 +78,21 @@
78
78
  })();
79
79
  </script>
80
80
  <title>NextClaw</title>
81
- <script type="module" crossorigin src="/assets/index-CM-57d8J.js"></script>
81
+ <script type="module" crossorigin src="/assets/index-B7RsQ-ne.js"></script>
82
82
  <link rel="modulepreload" crossorigin href="/assets/i18n-C5Mibli1.js">
83
83
  <link rel="modulepreload" crossorigin href="/assets/chunk-JZWAC4HX-u4uYphxM.js">
84
- <link rel="modulepreload" crossorigin href="/assets/api-BcqDx0tm.js">
85
- <link rel="modulepreload" crossorigin href="/assets/es2015-JCM5-KtW.js">
84
+ <link rel="modulepreload" crossorigin href="/assets/api-Dai6UR3J.js">
85
+ <link rel="modulepreload" crossorigin href="/assets/es2015-BVRlEE06.js">
86
86
  <link rel="modulepreload" crossorigin href="/assets/createLucideIcon-BZkY6emz.js">
87
- <link rel="modulepreload" crossorigin href="/assets/select-DIZrwsKU.js">
88
- <link rel="modulepreload" crossorigin href="/assets/dist-Bl94Ahwx.js">
87
+ <link rel="modulepreload" crossorigin href="/assets/select-uO-zhYsH.js">
88
+ <link rel="modulepreload" crossorigin href="/assets/dist-CxcPOISF.js">
89
89
  <link rel="modulepreload" crossorigin href="/assets/x-DpTzXQcX.js">
90
- <link rel="modulepreload" crossorigin href="/assets/dialog-csshWetU.js">
91
- <link rel="modulepreload" crossorigin href="/assets/popover-YAsxDBhY.js">
92
- <link rel="modulepreload" crossorigin href="/assets/tooltip-Dq5Xehpk.js">
90
+ <link rel="modulepreload" crossorigin href="/assets/dialog-DgybjpeU.js">
91
+ <link rel="modulepreload" crossorigin href="/assets/popover-C8tMB7tR.js">
92
+ <link rel="modulepreload" crossorigin href="/assets/tooltip-CvAtG-kT.js">
93
93
  <link rel="modulepreload" crossorigin href="/assets/refresh-cw-BxojR62w.js">
94
- <link rel="modulepreload" crossorigin href="/assets/use-config-BQJjq1mP.js">
95
- <link rel="modulepreload" crossorigin href="/assets/theme-provider-W704JWF8.js">
94
+ <link rel="modulepreload" crossorigin href="/assets/use-config-D2QgG7qc.js">
95
+ <link rel="modulepreload" crossorigin href="/assets/theme-provider-BU77FNSB.js">
96
96
  <link rel="modulepreload" crossorigin href="/assets/search-vChioOoe.js">
97
97
  <link rel="modulepreload" crossorigin href="/assets/book-open-DgLqYpNY.js">
98
98
  <link rel="modulepreload" crossorigin href="/assets/external-link-Sw3ah_JD.js">
@@ -107,16 +107,16 @@
107
107
  <link rel="modulepreload" crossorigin href="/assets/doc-browser-context-DfLHAWbG.js">
108
108
  <link rel="modulepreload" crossorigin href="/assets/doc-browser-CzCV73NJ.js">
109
109
  <link rel="modulepreload" crossorigin href="/assets/doc-browser-BUlCkZo2.js">
110
- <link rel="modulepreload" crossorigin href="/assets/use-viewport-layout-BX3XqzJ4.js">
110
+ <link rel="modulepreload" crossorigin href="/assets/use-viewport-layout-C6EN0_eq.js">
111
111
  <link rel="modulepreload" crossorigin href="/assets/logo-badge-BQgKnVtz.js">
112
112
  <link rel="modulepreload" crossorigin href="/assets/skeleton-CFQRIUzt.js">
113
- <link rel="modulepreload" crossorigin href="/assets/chat-ahMH_i_K.js">
113
+ <link rel="modulepreload" crossorigin href="/assets/chat-ZQIVJChB.js">
114
114
  <link rel="modulepreload" crossorigin href="/assets/key-round-CnI1mc9F.js">
115
115
  <link rel="modulepreload" crossorigin href="/assets/message-square-D6Z4NwpG.js">
116
- <link rel="modulepreload" crossorigin href="/assets/app-navigation.config-BOVDFMnp.js">
117
- <link rel="modulepreload" crossorigin href="/assets/notice-card-CCgk6FvF.js">
116
+ <link rel="modulepreload" crossorigin href="/assets/app-navigation.config-BjIj_FLm.js">
117
+ <link rel="modulepreload" crossorigin href="/assets/notice-card-uzwjFyML.js">
118
118
  <link rel="modulepreload" crossorigin href="/assets/status-dot-Dv_hiUVa.js">
119
- <link rel="modulepreload" crossorigin href="/assets/app-manager-provider-DVYBjif-.js">
119
+ <link rel="modulepreload" crossorigin href="/assets/app-manager-provider-BZr5VxCe.js">
120
120
  <link rel="stylesheet" crossorigin href="/assets/index-D8MKmXtO.css">
121
121
  </head>
122
122
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/ui",
3
- "version": "0.12.20-beta.3",
3
+ "version": "0.12.20-beta.5",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -28,14 +28,14 @@
28
28
  "tailwind-merge": "^2.5.4",
29
29
  "zod": "^3.23.8",
30
30
  "zustand": "^5.0.2",
31
- "@nextclaw/client-sdk": "0.1.1-beta.3",
32
- "@nextclaw/kernel": "0.1.2-beta.3",
33
- "@nextclaw/ncp-http-agent-client": "0.3.18-beta.2",
34
- "@nextclaw/ncp": "0.5.6-beta.1",
35
- "@nextclaw/server": "0.12.13-beta.3",
36
- "@nextclaw/agent-chat-ui": "0.3.13-beta.1",
37
- "@nextclaw/agent-chat": "0.1.11-beta.1",
38
- "@nextclaw/ncp-react": "0.4.26-beta.2"
31
+ "@nextclaw/agent-chat": "0.1.11-beta.3",
32
+ "@nextclaw/agent-chat-ui": "0.3.13-beta.3",
33
+ "@nextclaw/client-sdk": "0.1.1-beta.5",
34
+ "@nextclaw/kernel": "0.1.2-beta.5",
35
+ "@nextclaw/ncp": "0.5.6-beta.3",
36
+ "@nextclaw/ncp-http-agent-client": "0.3.18-beta.4",
37
+ "@nextclaw/server": "0.12.13-beta.5",
38
+ "@nextclaw/ncp-react": "0.4.26-beta.4"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@testing-library/react": "^16.3.0",
@@ -0,0 +1,89 @@
1
+ import { useEffect, useRef } from 'react';
2
+ import { eventKeys } from '@nextclaw/kernel';
3
+ import { applyNcpSessionRealtimeEvent, nextclawClient } from '@/shared/lib/api';
4
+ import { runtimeUpdateManager, systemStatusManager } from '@/features/system-status';
5
+ import type { QueryClient } from '@tanstack/react-query';
6
+
7
+ function shouldInvalidateConfigQuery(configPath: string) {
8
+ const normalized = configPath.trim().toLowerCase();
9
+ if (!normalized) {
10
+ return true;
11
+ }
12
+ if (normalized.startsWith('plugins') || normalized.startsWith('skills')) {
13
+ return false;
14
+ }
15
+ return true;
16
+ }
17
+
18
+ function invalidateMarketplaceQueries(queryClient: QueryClient | undefined, configPath: string): void {
19
+ if (configPath.startsWith('plugins')) {
20
+ queryClient?.invalidateQueries({ queryKey: ['ncp-session-types'] });
21
+ queryClient?.invalidateQueries({ queryKey: ['marketplace-installed', 'plugin'] });
22
+ queryClient?.invalidateQueries({ queryKey: ['marketplace-items'] });
23
+ }
24
+ if (configPath.startsWith('mcp')) {
25
+ queryClient?.invalidateQueries({ queryKey: ['marketplace-mcp-installed'] });
26
+ queryClient?.invalidateQueries({ queryKey: ['marketplace-mcp-items'] });
27
+ queryClient?.invalidateQueries({ queryKey: ['marketplace-mcp-doctor'] });
28
+ }
29
+ }
30
+
31
+ function handleConfigUpdatedEvent(queryClient: QueryClient | undefined, path: string): void {
32
+ if (queryClient && shouldInvalidateConfigQuery(path)) {
33
+ queryClient.invalidateQueries({ queryKey: ['config'] });
34
+ }
35
+ invalidateMarketplaceQueries(queryClient, path);
36
+ }
37
+
38
+ export function useAppEventConsumers(queryClient?: QueryClient) {
39
+ const shouldResyncSessionsRef = useRef(false);
40
+
41
+ useEffect(() => {
42
+ const unsubscribeConnectionOpen = nextclawClient.eventBus.on(eventKeys.connectionOpen, () => {
43
+ systemStatusManager.handleConnectionRestored();
44
+ void runtimeUpdateManager.refreshAfterRealtimeReconnect();
45
+ if (shouldResyncSessionsRef.current) {
46
+ shouldResyncSessionsRef.current = false;
47
+ queryClient?.invalidateQueries({ queryKey: ['ncp-sessions'] });
48
+ }
49
+ });
50
+ const unsubscribeConnectionClose = nextclawClient.eventBus.on(eventKeys.connectionClose, () => {
51
+ systemStatusManager.handleConnectionInterrupted(null);
52
+ shouldResyncSessionsRef.current = true;
53
+ });
54
+ const unsubscribeConnectionError = nextclawClient.eventBus.on(eventKeys.connectionError, (payload) => {
55
+ systemStatusManager.handleConnectionInterrupted(payload?.message ?? null);
56
+ shouldResyncSessionsRef.current = true;
57
+ });
58
+ const unsubscribeConfigUpdated = nextclawClient.eventBus.on(eventKeys.configUpdated, ({ path }) => {
59
+ handleConfigUpdatedEvent(queryClient, path);
60
+ });
61
+ const unsubscribeRuntimeUpdate = nextclawClient.eventBus.on(eventKeys.runtimeUpdateSnapshot, (snapshot) => {
62
+ runtimeUpdateManager.reportSnapshot(snapshot);
63
+ });
64
+ const unsubscribeSessionRunStatus = nextclawClient.eventBus.on(eventKeys.sessionRunStatus, (payload) => {
65
+ applyNcpSessionRealtimeEvent(queryClient, { type: 'session.run-status', payload });
66
+ });
67
+ const unsubscribeSessionSummaryUpsert = nextclawClient.eventBus.on(eventKeys.sessionSummaryUpsert, (payload) => {
68
+ applyNcpSessionRealtimeEvent(queryClient, { type: 'session.summary.upsert', payload });
69
+ });
70
+ const unsubscribeSessionSummaryDelete = nextclawClient.eventBus.on(eventKeys.sessionSummaryDelete, (payload) => {
71
+ applyNcpSessionRealtimeEvent(queryClient, { type: 'session.summary.delete', payload });
72
+ });
73
+ const unsubscribeError = nextclawClient.eventBus.on(eventKeys.error, (payload) => {
74
+ console.error('Realtime transport error:', payload.message);
75
+ });
76
+
77
+ return () => {
78
+ unsubscribeConnectionOpen();
79
+ unsubscribeConnectionClose();
80
+ unsubscribeConnectionError();
81
+ unsubscribeConfigUpdated();
82
+ unsubscribeRuntimeUpdate();
83
+ unsubscribeSessionRunStatus();
84
+ unsubscribeSessionSummaryUpsert();
85
+ unsubscribeSessionSummaryDelete();
86
+ unsubscribeError();
87
+ };
88
+ }, [queryClient]);
89
+ }
package/src/app/index.tsx CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  isTransientAuthStatusBootstrapError,
16
16
  useAuthStatus,
17
17
  } from "@/hooks/use-auth";
18
- import { useRealtimeQueryBridge } from "@/hooks/use-realtime-query-bridge";
18
+ import { useAppEventConsumers } from "@/app/hooks/use-app-event-consumers";
19
19
  import {
20
20
  PwaInstallBanner,
21
21
  PwaUpdateBanner,
@@ -212,7 +212,7 @@ function ProtectedRoutes() {
212
212
  }
213
213
 
214
214
  function ProtectedApp() {
215
- useRealtimeQueryBridge(appQueryClient);
215
+ useAppEventConsumers(appQueryClient);
216
216
  useSystemStatusSources();
217
217
  useEffect(() => {
218
218
  void runtimeUpdateManager.start();
@@ -1,5 +1,6 @@
1
1
  import { useMemo, useState, useSyncExternalStore } from 'react';
2
2
  import type { Dispatch, FormEvent, SetStateAction } from 'react';
3
+ import { eventKeys } from '@nextclaw/kernel';
3
4
  import { BookOpen, ChevronDown } from 'lucide-react';
4
5
  import { toast } from 'sonner';
5
6
  import { LogoBadge } from '@/shared/components/common/logo-badge';
@@ -77,20 +78,17 @@ function ensureChannelApplySubscription() {
77
78
  if (channelApplyUnsubscribe) {
78
79
  return;
79
80
  }
80
- channelApplyUnsubscribe = nextclawClient.realtime.subscribe((event) => {
81
- if (event.type !== 'channel.config.apply-status') {
82
- return;
83
- }
81
+ channelApplyUnsubscribe = nextclawClient.eventBus.on(eventKeys.channelConfigApplyStatus, (payload) => {
84
82
  channelApplySnapshots.set(
85
- event.payload.channel,
86
- event.payload.status === 'started'
83
+ payload.channel,
84
+ payload.status === 'started'
87
85
  ? { status: 'applying' }
88
- : event.payload.status === 'succeeded'
86
+ : payload.status === 'succeeded'
89
87
  ? { status: 'applied' }
90
- : { status: 'failed', message: event.payload.message }
88
+ : { status: 'failed', message: payload.message }
91
89
  );
92
90
  channelApplyListeners.forEach((listener) => listener());
93
- }).close;
91
+ });
94
92
  }
95
93
 
96
94
  function subscribeChannelApplyStore(listener: () => void) {
@@ -79,7 +79,8 @@ describe('DesktopUpdateConfig', () => {
79
79
  it('renders current channel information and beta guidance', () => {
80
80
  render(<DesktopUpdateConfig />);
81
81
 
82
- expect(mocks.start).toHaveBeenCalledTimes(1);
82
+ expect(mocks.start).not.toHaveBeenCalled();
83
+ expect(mocks.stop).not.toHaveBeenCalled();
83
84
  expect(screen.getByText('版本更新')).toBeTruthy();
84
85
  expect(screen.getByText('宿主版本')).toBeTruthy();
85
86
  expect(screen.getByText('当前更新通道')).toBeTruthy();
@@ -98,4 +99,27 @@ describe('DesktopUpdateConfig', () => {
98
99
 
99
100
  expect(mocks.updateChannel).toHaveBeenCalledWith('stable');
100
101
  });
102
+
103
+ it('renders runtime download progress from the shared store', () => {
104
+ useRuntimeUpdateStore.setState((state) => ({
105
+ ...state,
106
+ busyAction: 'downloading',
107
+ snapshot: state.snapshot
108
+ ? {
109
+ ...state.snapshot,
110
+ status: 'downloading',
111
+ progress: {
112
+ downloadedBytes: 50,
113
+ totalBytes: 100,
114
+ percent: 50
115
+ }
116
+ }
117
+ : null
118
+ }));
119
+
120
+ render(<DesktopUpdateConfig />);
121
+
122
+ expect(screen.getByText('正在下载 50%')).toBeTruthy();
123
+ expect(screen.getByText('50 B / 100 B')).toBeTruthy();
124
+ });
101
125
  });
@@ -1,5 +1,4 @@
1
1
  import type { UpdateSnapshot } from '@nextclaw/kernel';
2
- import { useEffect } from 'react';
3
2
  import { runtimeUpdateManager, useRuntimeUpdateStore } from '@/features/system-status';
4
3
  import { Button } from '@/shared/components/ui/button';
5
4
  import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/shared/components/ui/card';
@@ -134,12 +133,6 @@ function RuntimeUpdateUnavailableState() {
134
133
 
135
134
  export function DesktopUpdateConfig() {
136
135
  const { supported, initialized, busyAction, snapshot } = useRuntimeUpdateStore();
137
- useEffect(() => {
138
- void runtimeUpdateManager.start();
139
- return () => {
140
- runtimeUpdateManager.stop();
141
- };
142
- }, []);
143
136
  if (!initialized) {
144
137
  return <div className="p-8 text-gray-400">{t('loading')}</div>;
145
138
  }
@@ -25,8 +25,6 @@ interface HostRuntimeUpdateSourceContract extends RuntimeUpdateSourceBase {
25
25
  kind: 'runtime-host';
26
26
  }
27
27
 
28
- const RUNTIME_HOST_POLL_INTERVAL_MS = 1000;
29
-
30
28
  type RuntimeUpdateSource = DesktopBridgeRuntimeUpdateSourceContract | HostRuntimeUpdateSourceContract;
31
29
 
32
30
  class DesktopBridgeRuntimeUpdateSource implements DesktopBridgeRuntimeUpdateSourceContract {
@@ -93,7 +91,6 @@ class HostRuntimeUpdateSource implements HostRuntimeUpdateSourceContract {
93
91
 
94
92
  export class RuntimeUpdateManager {
95
93
  private unsubscribe: (() => void) | null = null;
96
- private pollingTimer: number | null = null;
97
94
  private subscriptionCount = 0;
98
95
  private source: RuntimeUpdateSource | null = null;
99
96
 
@@ -120,10 +117,6 @@ export class RuntimeUpdateManager {
120
117
  });
121
118
  }
122
119
 
123
- if (source.kind === 'runtime-host') {
124
- this.ensurePolling();
125
- }
126
-
127
120
  useRuntimeUpdateStore.setState({
128
121
  supported: true,
129
122
  initialized: false
@@ -160,13 +153,27 @@ export class RuntimeUpdateManager {
160
153
  }
161
154
  this.unsubscribe?.();
162
155
  this.unsubscribe = null;
163
- if (this.pollingTimer !== null && typeof window !== 'undefined') {
164
- window.clearInterval(this.pollingTimer);
165
- }
166
- this.pollingTimer = null;
167
156
  this.source = null;
168
157
  };
169
158
 
159
+ reportSnapshot = (snapshot: UpdateSnapshot): void => {
160
+ if (this.source?.kind === 'desktop-bridge') {
161
+ return;
162
+ }
163
+ useRuntimeUpdateStore.setState({
164
+ supported: true,
165
+ initialized: true,
166
+ snapshot
167
+ });
168
+ };
169
+
170
+ refreshAfterRealtimeReconnect = async (): Promise<void> => {
171
+ if (this.source?.kind !== 'runtime-host') {
172
+ return;
173
+ }
174
+ await this.refreshSnapshot();
175
+ };
176
+
170
177
  checkForUpdates = async () => {
171
178
  let snapshot: UpdateSnapshot;
172
179
  try {
@@ -249,15 +256,6 @@ export class RuntimeUpdateManager {
249
256
  toast.success(t('runtimeUpdatesChannelChanged').replace('{channel}', this.getChannelLabel(channel)));
250
257
  };
251
258
 
252
- private ensurePolling = () => {
253
- if (this.pollingTimer !== null || typeof window === 'undefined') {
254
- return;
255
- }
256
- this.pollingTimer = window.setInterval(() => {
257
- void this.refreshSnapshot();
258
- }, RUNTIME_HOST_POLL_INTERVAL_MS);
259
- };
260
-
261
259
  private refreshSnapshot = async () => {
262
260
  if (!this.source || this.source.kind !== 'runtime-host') {
263
261
  return;
@@ -1,4 +1,4 @@
1
- import type { UiServerEvent } from '@nextclaw/server';
1
+ import type { AppEvent as KernelAppEvent } from '@nextclaw/kernel';
2
2
 
3
3
  export type RequestMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
4
4
 
@@ -30,7 +30,7 @@ export type StreamSession<TFinal = unknown> = {
30
30
  };
31
31
 
32
32
  export type AppEvent =
33
- | UiServerEvent
33
+ | KernelAppEvent
34
34
  | { type: 'connection.open'; payload?: Record<string, never> }
35
35
  | { type: 'connection.close'; payload?: Record<string, never> }
36
36
  | { type: 'connection.error'; payload?: { message?: string } };
package/tsconfig.json CHANGED
@@ -28,12 +28,13 @@
28
28
  "@/components/providers/I18nProvider": ["./src/app/components/i18n-provider.tsx"],
29
29
  "@/components/providers/ThemeProvider": ["./src/app/components/theme-provider.tsx"],
30
30
  "@/hooks/use-auth": ["./src/features/account/hooks/use-auth.ts"],
31
- "@/hooks/use-realtime-query-bridge": ["./src/app/hooks/use-realtime-query-bridge.ts"],
31
+ "@/hooks/use-app-event-consumers": ["./src/app/hooks/use-app-event-consumers.ts"],
32
32
  "@/pwa/components/pwa-install-entry": ["./src/features/pwa/components/pwa-install-entry.tsx"],
33
33
  "@/pwa/register-pwa": ["./src/features/pwa/managers/pwa-bootstrap.manager.ts"],
34
34
  "@/*": ["./src/*"],
35
35
  "@nextclaw/agent-chat": ["../nextclaw-agent-chat/src/index.ts"],
36
36
  "@nextclaw/agent-chat-ui": ["../nextclaw-agent-chat-ui/src/index.ts"],
37
+ "@nextclaw/client-sdk": ["../nextclaw-client-sdk/src/index.ts"],
37
38
  "@nextclaw/kernel": ["../nextclaw-kernel/src/index.ts"],
38
39
  "@nextclaw/ncp": ["../ncp-packages/nextclaw-ncp/src/index.ts"],
39
40
  "@nextclaw/ncp-http-agent-client": ["../ncp-packages/nextclaw-ncp-http-agent-client/src/index.ts"],
package/vite.config.ts CHANGED
@@ -26,12 +26,14 @@ export default defineConfig({
26
26
  '@/components/providers/I18nProvider': path.resolve(__dirname, './src/app/components/i18n-provider.tsx'),
27
27
  '@/components/providers/ThemeProvider': path.resolve(__dirname, './src/app/components/theme-provider.tsx'),
28
28
  '@/hooks/use-auth': path.resolve(__dirname, './src/features/account/hooks/use-auth.ts'),
29
- '@/hooks/use-realtime-query-bridge': path.resolve(__dirname, './src/app/hooks/use-realtime-query-bridge.ts'),
29
+ '@/hooks/use-app-event-consumers': path.resolve(__dirname, './src/app/hooks/use-app-event-consumers.ts'),
30
30
  '@/pwa/components/pwa-install-entry': path.resolve(__dirname, './src/features/pwa/components/pwa-install-entry.tsx'),
31
31
  '@/pwa/register-pwa': path.resolve(__dirname, './src/features/pwa/managers/pwa-bootstrap.manager.ts'),
32
32
  '@': path.resolve(__dirname, './src'),
33
33
  '@nextclaw/agent-chat': path.resolve(__dirname, '../nextclaw-agent-chat/src/index.ts'),
34
- '@nextclaw/agent-chat-ui': path.resolve(__dirname, '../nextclaw-agent-chat-ui/src/index.ts')
34
+ '@nextclaw/agent-chat-ui': path.resolve(__dirname, '../nextclaw-agent-chat-ui/src/index.ts'),
35
+ '@nextclaw/client-sdk': path.resolve(__dirname, '../nextclaw-client-sdk/src/index.ts'),
36
+ '@nextclaw/kernel': path.resolve(__dirname, '../nextclaw-kernel/src/index.ts')
35
37
  }
36
38
  },
37
39
  server: {
package/vitest.config.ts CHANGED
@@ -21,11 +21,13 @@ export default defineConfig({
21
21
  '@/components/providers/I18nProvider': path.resolve(__dirname, './src/app/components/i18n-provider.tsx'),
22
22
  '@/components/providers/ThemeProvider': path.resolve(__dirname, './src/app/components/theme-provider.tsx'),
23
23
  '@/hooks/use-auth': path.resolve(__dirname, './src/features/account/hooks/use-auth.ts'),
24
- '@/hooks/use-realtime-query-bridge': path.resolve(__dirname, './src/app/hooks/use-realtime-query-bridge.ts'),
24
+ '@/hooks/use-app-event-consumers': path.resolve(__dirname, './src/app/hooks/use-app-event-consumers.ts'),
25
25
  '@/pwa/components/pwa-install-entry': path.resolve(__dirname, './src/features/pwa/components/pwa-install-entry.tsx'),
26
26
  '@/pwa/register-pwa': path.resolve(__dirname, './src/features/pwa/managers/pwa-bootstrap.manager.ts'),
27
27
  '@': path.resolve(__dirname, './src'),
28
- '@nextclaw/agent-chat': path.resolve(__dirname, '../nextclaw-agent-chat/src/index.ts')
28
+ '@nextclaw/agent-chat': path.resolve(__dirname, '../nextclaw-agent-chat/src/index.ts'),
29
+ '@nextclaw/client-sdk': path.resolve(__dirname, '../nextclaw-client-sdk/src/index.ts'),
30
+ '@nextclaw/kernel': path.resolve(__dirname, '../nextclaw-kernel/src/index.ts')
29
31
  }
30
32
  },
31
33
  test: {