@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.
- package/CHANGELOG.md +124 -0
- package/dist/assets/api-Dai6UR3J.js +15 -0
- package/dist/assets/app-manager-provider-BZr5VxCe.js +1 -0
- package/dist/assets/{app-navigation.config-BOVDFMnp.js → app-navigation.config-BjIj_FLm.js} +1 -1
- package/dist/assets/channels-list-page-L6FFtRYn.js +8 -0
- package/dist/assets/{chat-ahMH_i_K.js → chat-ZQIVJChB.js} +6 -6
- package/dist/assets/{chat-page-BxlXY-MB.js → chat-page-CR1yI96r.js} +1 -1
- package/dist/assets/desktop-update-config-AXzb7OEa.js +1 -0
- package/dist/assets/{dialog-csshWetU.js → dialog-DgybjpeU.js} +1 -1
- package/dist/assets/{dist-Bl94Ahwx.js → dist-CxcPOISF.js} +1 -1
- package/dist/assets/{es2015-JCM5-KtW.js → es2015-BVRlEE06.js} +1 -1
- package/dist/assets/index-B7RsQ-ne.js +2 -0
- package/dist/assets/marketplace-page-Bj55-6F2.js +1 -0
- package/dist/assets/{marketplace-page-DxlxHCFm.js → marketplace-page-ClRW-W3g.js} +2 -2
- package/dist/assets/mcp-marketplace-page-DtngnIi0.js +40 -0
- package/dist/assets/mcp-marketplace-page-_Wu2VnHy.js +1 -0
- package/dist/assets/{model-config-PccJ9XyH.js → model-config-D_y8F0j6.js} +1 -1
- package/dist/assets/{notice-card-CCgk6FvF.js → notice-card-uzwjFyML.js} +1 -1
- package/dist/assets/{popover-YAsxDBhY.js → popover-C8tMB7tR.js} +1 -1
- package/dist/assets/{provider-scoped-model-input-CzpF7cug.js → provider-scoped-model-input-ORZutTDv.js} +1 -1
- package/dist/assets/{providers-list-8qDMER8o.js → providers-list-DSc3d8me.js} +1 -1
- package/dist/assets/remote-rWiu3cys.js +1 -0
- package/dist/assets/runtime-config-page-B4uSax1I.js +1 -0
- package/dist/assets/{search-config-D3a65l3r.js → search-config-CaqqlsdW.js} +1 -1
- package/dist/assets/{secrets-config-CoMlR_7i.js → secrets-config-llf5ROde.js} +2 -2
- package/dist/assets/{select-DIZrwsKU.js → select-uO-zhYsH.js} +1 -1
- package/dist/assets/{sessions-config-page-QjH5tgjr.js → sessions-config-page-BqOXte9x.js} +2 -2
- package/dist/assets/{setting-row-DiQyrE81.js → setting-row-BIiXR4hx.js} +1 -1
- package/dist/assets/{tag-chip-C3wDBe_-.js → tag-chip-DVbgpsYW.js} +1 -1
- package/dist/assets/{theme-provider-W704JWF8.js → theme-provider-BU77FNSB.js} +1 -1
- package/dist/assets/{tooltip-Dq5Xehpk.js → tooltip-CvAtG-kT.js} +1 -1
- package/dist/assets/use-config-D2QgG7qc.js +1 -0
- package/dist/assets/{use-confirm-dialog-DBoV5n5P.js → use-confirm-dialog-BBClFV8E.js} +1 -1
- package/dist/assets/{use-infinite-scroll-loader-JAicqVC5.js → use-infinite-scroll-loader-CWzpUecQ.js} +1 -1
- package/dist/assets/{use-viewport-layout-BX3XqzJ4.js → use-viewport-layout-C6EN0_eq.js} +1 -1
- package/dist/index.html +15 -15
- package/package.json +9 -9
- package/src/app/hooks/use-app-event-consumers.ts +89 -0
- package/src/app/index.tsx +2 -2
- package/src/features/channels/components/config/channel-form.tsx +7 -9
- package/src/features/system-status/components/desktop-update-config.test.tsx +25 -1
- package/src/features/system-status/components/desktop-update-config.tsx +0 -7
- package/src/features/system-status/managers/runtime-update.manager.ts +18 -20
- package/src/shared/lib/transport/transport.types.ts +2 -2
- package/tsconfig.json +2 -1
- package/vite.config.ts +4 -2
- package/vitest.config.ts +4 -2
- package/dist/assets/api-BcqDx0tm.js +0 -15
- package/dist/assets/app-manager-provider-DVYBjif-.js +0 -1
- package/dist/assets/channels-list-page-CsoI4OJm.js +0 -8
- package/dist/assets/desktop-update-config-CD6-2PfI.js +0 -1
- package/dist/assets/index-CM-57d8J.js +0 -2
- package/dist/assets/marketplace-page-DJGDpTAo.js +0 -1
- package/dist/assets/mcp-marketplace-page-5UjYRWOR.js +0 -40
- package/dist/assets/mcp-marketplace-page-C1XaHZZO.js +0 -1
- package/dist/assets/remote-D4TtLPAp.js +0 -1
- package/dist/assets/runtime-config-page-DWJHrV7H.js +0 -1
- package/dist/assets/use-config-BQJjq1mP.js +0 -1
- 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-
|
|
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-
|
|
85
|
-
<link rel="modulepreload" crossorigin href="/assets/es2015-
|
|
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-
|
|
88
|
-
<link rel="modulepreload" crossorigin href="/assets/dist-
|
|
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-
|
|
91
|
-
<link rel="modulepreload" crossorigin href="/assets/popover-
|
|
92
|
-
<link rel="modulepreload" crossorigin href="/assets/tooltip-
|
|
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-
|
|
95
|
-
<link rel="modulepreload" crossorigin href="/assets/theme-provider-
|
|
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-
|
|
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-
|
|
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-
|
|
117
|
-
<link rel="modulepreload" crossorigin href="/assets/notice-card-
|
|
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-
|
|
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
|
+
"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/
|
|
32
|
-
"@nextclaw/
|
|
33
|
-
"@nextclaw/
|
|
34
|
-
"@nextclaw/
|
|
35
|
-
"@nextclaw/
|
|
36
|
-
"@nextclaw/agent-
|
|
37
|
-
"@nextclaw/
|
|
38
|
-
"@nextclaw/ncp-react": "0.4.26-beta.
|
|
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 {
|
|
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
|
-
|
|
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.
|
|
81
|
-
if (event.type !== 'channel.config.apply-status') {
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
81
|
+
channelApplyUnsubscribe = nextclawClient.eventBus.on(eventKeys.channelConfigApplyStatus, (payload) => {
|
|
84
82
|
channelApplySnapshots.set(
|
|
85
|
-
|
|
86
|
-
|
|
83
|
+
payload.channel,
|
|
84
|
+
payload.status === 'started'
|
|
87
85
|
? { status: 'applying' }
|
|
88
|
-
:
|
|
86
|
+
: payload.status === 'succeeded'
|
|
89
87
|
? { status: 'applied' }
|
|
90
|
-
: { status: 'failed', message:
|
|
88
|
+
: { status: 'failed', message: payload.message }
|
|
91
89
|
);
|
|
92
90
|
channelApplyListeners.forEach((listener) => listener());
|
|
93
|
-
})
|
|
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).
|
|
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 {
|
|
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
|
-
|
|
|
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-
|
|
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-
|
|
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-
|
|
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: {
|