react-native-debug-toolkit 3.3.8 → 3.5.0
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/lib/commonjs/constants/logLevels.js +19 -0
- package/lib/commonjs/constants/logLevels.js.map +1 -0
- package/lib/commonjs/core/initialize.js +30 -19
- package/lib/commonjs/core/initialize.js.map +1 -1
- package/lib/commonjs/features/console/ConsoleLogTab.js +4 -15
- package/lib/commonjs/features/console/ConsoleLogTab.js.map +1 -1
- package/lib/commonjs/features/console/index.js +15 -8
- package/lib/commonjs/features/console/index.js.map +1 -1
- package/lib/commonjs/features/network/NetworkLogTab.js +91 -93
- package/lib/commonjs/features/network/NetworkLogTab.js.map +1 -1
- package/lib/commonjs/features/network/index.js +7 -4
- package/lib/commonjs/features/network/index.js.map +1 -1
- package/lib/commonjs/features/sessionHistory/SessionHistoryTab.js +1044 -0
- package/lib/commonjs/features/sessionHistory/SessionHistoryTab.js.map +1 -0
- package/lib/commonjs/features/sessionHistory/index.js +103 -0
- package/lib/commonjs/features/sessionHistory/index.js.map +1 -0
- package/lib/commonjs/features/track/index.js +4 -3
- package/lib/commonjs/features/track/index.js.map +1 -1
- package/lib/commonjs/index.js +20 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/ui/DebugView.js +1 -0
- package/lib/commonjs/ui/DebugView.js.map +1 -1
- package/lib/commonjs/ui/panel/DebugPanel.js +67 -34
- package/lib/commonjs/ui/panel/DebugPanel.js.map +1 -1
- package/lib/commonjs/ui/panel/FeatureIntroCard.js +131 -0
- package/lib/commonjs/ui/panel/FeatureIntroCard.js.map +1 -0
- package/lib/commonjs/ui/panel/FeatureRail.js +163 -0
- package/lib/commonjs/ui/panel/FeatureRail.js.map +1 -0
- package/lib/commonjs/ui/panel/FloatPanelView.js +147 -22
- package/lib/commonjs/ui/panel/FloatPanelView.js.map +1 -1
- package/lib/commonjs/ui/panel/buildFeatureSummary.js +207 -0
- package/lib/commonjs/ui/panel/buildFeatureSummary.js.map +1 -0
- package/lib/commonjs/ui/panel/filterFeatureSnapshot.js +43 -0
- package/lib/commonjs/ui/panel/filterFeatureSnapshot.js.map +1 -0
- package/lib/commonjs/ui/theme/colors.js +6 -0
- package/lib/commonjs/ui/theme/colors.js.map +1 -1
- package/lib/commonjs/utils/DaemonClient.js +30 -8
- package/lib/commonjs/utils/DaemonClient.js.map +1 -1
- package/lib/commonjs/utils/SessionManager.js +132 -0
- package/lib/commonjs/utils/SessionManager.js.map +1 -0
- package/lib/commonjs/utils/StorageAdapter.js +104 -0
- package/lib/commonjs/utils/StorageAdapter.js.map +1 -0
- package/lib/commonjs/utils/createChannelFeature.js +22 -5
- package/lib/commonjs/utils/createChannelFeature.js.map +1 -1
- package/lib/commonjs/utils/createPersistedObservableStore.js +14 -8
- package/lib/commonjs/utils/createPersistedObservableStore.js.map +1 -1
- package/lib/commonjs/utils/debugPreferences.js +28 -5
- package/lib/commonjs/utils/debugPreferences.js.map +1 -1
- package/lib/commonjs/utils/deviceReport.js +5 -1
- package/lib/commonjs/utils/deviceReport.js.map +1 -1
- package/lib/commonjs/utils/logRuntime.js +32 -0
- package/lib/commonjs/utils/logRuntime.js.map +1 -0
- package/lib/module/constants/logLevels.js +15 -0
- package/lib/module/constants/logLevels.js.map +1 -0
- package/lib/module/core/initialize.js +30 -19
- package/lib/module/core/initialize.js.map +1 -1
- package/lib/module/features/console/ConsoleLogTab.js +1 -12
- package/lib/module/features/console/ConsoleLogTab.js.map +1 -1
- package/lib/module/features/console/index.js +15 -8
- package/lib/module/features/console/index.js.map +1 -1
- package/lib/module/features/network/NetworkLogTab.js +91 -93
- package/lib/module/features/network/NetworkLogTab.js.map +1 -1
- package/lib/module/features/network/index.js +7 -4
- package/lib/module/features/network/index.js.map +1 -1
- package/lib/module/features/sessionHistory/SessionHistoryTab.js +1039 -0
- package/lib/module/features/sessionHistory/SessionHistoryTab.js.map +1 -0
- package/lib/module/features/sessionHistory/index.js +99 -0
- package/lib/module/features/sessionHistory/index.js.map +1 -0
- package/lib/module/features/track/index.js +4 -3
- package/lib/module/features/track/index.js.map +1 -1
- package/lib/module/index.js +3 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/ui/DebugView.js +1 -0
- package/lib/module/ui/DebugView.js.map +1 -1
- package/lib/module/ui/panel/DebugPanel.js +67 -34
- package/lib/module/ui/panel/DebugPanel.js.map +1 -1
- package/lib/module/ui/panel/FeatureIntroCard.js +126 -0
- package/lib/module/ui/panel/FeatureIntroCard.js.map +1 -0
- package/lib/module/ui/panel/FeatureRail.js +158 -0
- package/lib/module/ui/panel/FeatureRail.js.map +1 -0
- package/lib/module/ui/panel/FloatPanelView.js +148 -23
- package/lib/module/ui/panel/FloatPanelView.js.map +1 -1
- package/lib/module/ui/panel/buildFeatureSummary.js +203 -0
- package/lib/module/ui/panel/buildFeatureSummary.js.map +1 -0
- package/lib/module/ui/panel/filterFeatureSnapshot.js +39 -0
- package/lib/module/ui/panel/filterFeatureSnapshot.js.map +1 -0
- package/lib/module/ui/theme/colors.js +6 -0
- package/lib/module/ui/theme/colors.js.map +1 -1
- package/lib/module/utils/DaemonClient.js +30 -8
- package/lib/module/utils/DaemonClient.js.map +1 -1
- package/lib/module/utils/SessionManager.js +127 -0
- package/lib/module/utils/SessionManager.js.map +1 -0
- package/lib/module/utils/StorageAdapter.js +96 -0
- package/lib/module/utils/StorageAdapter.js.map +1 -0
- package/lib/module/utils/createChannelFeature.js +22 -5
- package/lib/module/utils/createChannelFeature.js.map +1 -1
- package/lib/module/utils/createPersistedObservableStore.js +14 -8
- package/lib/module/utils/createPersistedObservableStore.js.map +1 -1
- package/lib/module/utils/debugPreferences.js +27 -5
- package/lib/module/utils/debugPreferences.js.map +1 -1
- package/lib/module/utils/deviceReport.js +4 -1
- package/lib/module/utils/deviceReport.js.map +1 -1
- package/lib/module/utils/logRuntime.js +26 -0
- package/lib/module/utils/logRuntime.js.map +1 -0
- package/lib/typescript/src/constants/logLevels.d.ts +3 -0
- package/lib/typescript/src/constants/logLevels.d.ts.map +1 -0
- package/lib/typescript/src/core/initialize.d.ts +4 -0
- package/lib/typescript/src/core/initialize.d.ts.map +1 -1
- package/lib/typescript/src/features/console/ConsoleLogTab.d.ts.map +1 -1
- package/lib/typescript/src/features/console/index.d.ts +2 -1
- package/lib/typescript/src/features/console/index.d.ts.map +1 -1
- package/lib/typescript/src/features/network/NetworkLogTab.d.ts.map +1 -1
- package/lib/typescript/src/features/network/index.d.ts +2 -1
- package/lib/typescript/src/features/network/index.d.ts.map +1 -1
- package/lib/typescript/src/features/sessionHistory/SessionHistoryTab.d.ts +20 -0
- package/lib/typescript/src/features/sessionHistory/SessionHistoryTab.d.ts.map +1 -0
- package/lib/typescript/src/features/sessionHistory/index.d.ts +4 -0
- package/lib/typescript/src/features/sessionHistory/index.d.ts.map +1 -0
- package/lib/typescript/src/features/track/index.d.ts +2 -1
- package/lib/typescript/src/features/track/index.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +4 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/types/feature.d.ts +1 -1
- package/lib/typescript/src/types/feature.d.ts.map +1 -1
- package/lib/typescript/src/types/index.d.ts +2 -0
- package/lib/typescript/src/types/index.d.ts.map +1 -1
- package/lib/typescript/src/ui/DebugView.d.ts.map +1 -1
- package/lib/typescript/src/ui/panel/DebugPanel.d.ts +3 -1
- package/lib/typescript/src/ui/panel/DebugPanel.d.ts.map +1 -1
- package/lib/typescript/src/ui/panel/FeatureIntroCard.d.ts +11 -0
- package/lib/typescript/src/ui/panel/FeatureIntroCard.d.ts.map +1 -0
- package/lib/typescript/src/ui/panel/FeatureRail.d.ts +16 -0
- package/lib/typescript/src/ui/panel/FeatureRail.d.ts.map +1 -0
- package/lib/typescript/src/ui/panel/FloatPanelView.d.ts.map +1 -1
- package/lib/typescript/src/ui/panel/buildFeatureSummary.d.ts +13 -0
- package/lib/typescript/src/ui/panel/buildFeatureSummary.d.ts.map +1 -0
- package/lib/typescript/src/ui/panel/filterFeatureSnapshot.d.ts +3 -0
- package/lib/typescript/src/ui/panel/filterFeatureSnapshot.d.ts.map +1 -0
- package/lib/typescript/src/ui/theme/colors.d.ts +5 -0
- package/lib/typescript/src/ui/theme/colors.d.ts.map +1 -1
- package/lib/typescript/src/utils/DaemonClient.d.ts +7 -1
- package/lib/typescript/src/utils/DaemonClient.d.ts.map +1 -1
- package/lib/typescript/src/utils/SessionManager.d.ts +30 -0
- package/lib/typescript/src/utils/SessionManager.d.ts.map +1 -0
- package/lib/typescript/src/utils/StorageAdapter.d.ts +38 -0
- package/lib/typescript/src/utils/StorageAdapter.d.ts.map +1 -0
- package/lib/typescript/src/utils/createChannelFeature.d.ts +2 -0
- package/lib/typescript/src/utils/createChannelFeature.d.ts.map +1 -1
- package/lib/typescript/src/utils/createPersistedObservableStore.d.ts +4 -1
- package/lib/typescript/src/utils/createPersistedObservableStore.d.ts.map +1 -1
- package/lib/typescript/src/utils/debugPreferences.d.ts +1 -3
- package/lib/typescript/src/utils/debugPreferences.d.ts.map +1 -1
- package/lib/typescript/src/utils/deviceReport.d.ts +1 -0
- package/lib/typescript/src/utils/deviceReport.d.ts.map +1 -1
- package/lib/typescript/src/utils/logRuntime.d.ts +13 -0
- package/lib/typescript/src/utils/logRuntime.d.ts.map +1 -0
- package/package.json +9 -1
- package/src/constants/logLevels.ts +13 -0
- package/src/core/initialize.ts +49 -25
- package/src/features/console/ConsoleLogTab.tsx +1 -14
- package/src/features/console/index.ts +18 -8
- package/src/features/network/NetworkLogTab.tsx +61 -71
- package/src/features/network/index.ts +12 -3
- package/src/features/sessionHistory/SessionHistoryTab.tsx +691 -0
- package/src/features/sessionHistory/index.ts +102 -0
- package/src/features/track/index.ts +10 -3
- package/src/index.ts +11 -0
- package/src/types/feature.ts +2 -1
- package/src/types/index.ts +10 -0
- package/src/ui/DebugView.tsx +1 -0
- package/src/ui/panel/DebugPanel.tsx +60 -30
- package/src/ui/panel/FeatureIntroCard.tsx +127 -0
- package/src/ui/panel/FeatureRail.tsx +165 -0
- package/src/ui/panel/FloatPanelView.tsx +154 -15
- package/src/ui/panel/buildFeatureSummary.ts +288 -0
- package/src/ui/panel/filterFeatureSnapshot.ts +51 -0
- package/src/ui/theme/colors.ts +7 -0
- package/src/utils/DaemonClient.ts +33 -5
- package/src/utils/SessionManager.ts +174 -0
- package/src/utils/StorageAdapter.ts +135 -0
- package/src/utils/createChannelFeature.ts +28 -6
- package/src/utils/createPersistedObservableStore.ts +18 -10
- package/src/utils/debugPreferences.ts +38 -7
- package/src/utils/deviceReport.ts +5 -1
- package/src/utils/logRuntime.ts +39 -0
- package/lib/commonjs/ui/panel/FeatureTabBar.js +0 -182
- package/lib/commonjs/ui/panel/FeatureTabBar.js.map +0 -1
- package/lib/module/ui/panel/FeatureTabBar.js +0 -177
- package/lib/module/ui/panel/FeatureTabBar.js.map +0 -1
- package/lib/typescript/src/ui/panel/FeatureTabBar.d.ts +0 -13
- package/lib/typescript/src/ui/panel/FeatureTabBar.d.ts.map +0 -1
- package/src/ui/panel/FeatureTabBar.tsx +0 -204
|
@@ -2,15 +2,20 @@ import React, { Component, useCallback, useEffect, useRef, useState } from 'reac
|
|
|
2
2
|
import {
|
|
3
3
|
View,
|
|
4
4
|
Text,
|
|
5
|
+
TextInput,
|
|
5
6
|
StyleSheet,
|
|
6
7
|
Animated,
|
|
7
8
|
} from 'react-native';
|
|
8
9
|
import type { AnyDebugFeature } from '../../types';
|
|
10
|
+
import { Colors } from '../theme/colors';
|
|
9
11
|
import { getPreference, setPreference, KEYS } from '../../utils/debugPreferences';
|
|
10
12
|
import { FloatIcon } from '../floating/FloatIcon';
|
|
11
13
|
import { DebugPanel } from './DebugPanel';
|
|
12
|
-
import {
|
|
13
|
-
import type {
|
|
14
|
+
import { FeatureRail } from './FeatureRail';
|
|
15
|
+
import type { RailItem } from './FeatureRail';
|
|
16
|
+
import { FeatureIntroCard } from './FeatureIntroCard';
|
|
17
|
+
import { buildFeatureSummary } from './buildFeatureSummary';
|
|
18
|
+
import { filterFeatureSnapshot } from './filterFeatureSnapshot';
|
|
14
19
|
import { resolveStoredTabIndex } from './tabPersistence';
|
|
15
20
|
import { useTabAnimation } from './useTabAnimation';
|
|
16
21
|
|
|
@@ -40,6 +45,57 @@ class DebugErrorBoundary extends Component<
|
|
|
40
45
|
}
|
|
41
46
|
}
|
|
42
47
|
|
|
48
|
+
// ─── Snapshot helpers ──────────────────────────────────
|
|
49
|
+
|
|
50
|
+
function snapshotCount(feature: AnyDebugFeature): number | undefined {
|
|
51
|
+
try {
|
|
52
|
+
const snap = feature.getSnapshot();
|
|
53
|
+
if (Array.isArray(snap)) return snap.length;
|
|
54
|
+
if (snap && typeof snap === 'object') {
|
|
55
|
+
const obj = snap as Record<string, unknown>;
|
|
56
|
+
if (Array.isArray(obj.items)) return obj.items.length;
|
|
57
|
+
if (Array.isArray(obj.logs)) return obj.logs.length;
|
|
58
|
+
if (Array.isArray(obj.entries)) return obj.entries.length;
|
|
59
|
+
if (Array.isArray(obj.environments)) return obj.environments.length;
|
|
60
|
+
}
|
|
61
|
+
} catch { /* ignore */ }
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
interface PanelConnectionStatus {
|
|
66
|
+
label: string;
|
|
67
|
+
color: string;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
interface DevConnectSnapshot {
|
|
71
|
+
isSimulator?: boolean;
|
|
72
|
+
computerHost?: string;
|
|
73
|
+
daemonPort?: string;
|
|
74
|
+
streaming?: boolean;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function buildPanelConnectionStatus(features: AnyDebugFeature[]): PanelConnectionStatus {
|
|
78
|
+
const devConnect = features.find((f) => f.name === 'devConnect');
|
|
79
|
+
if (!devConnect) {
|
|
80
|
+
return { label: 'offline desktop sync unavailable', color: Colors.textLight };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
const snap = (devConnect.getSnapshot() ?? {}) as DevConnectSnapshot;
|
|
85
|
+
const host = snap.isSimulator ? 'localhost' : snap.computerHost?.trim();
|
|
86
|
+
const port = snap.daemonPort?.trim();
|
|
87
|
+
const target = host && port ? `${host}:${port}` : host || (port ? `port ${port}` : 'not configured');
|
|
88
|
+
return {
|
|
89
|
+
label: `${snap.streaming ? 'live' : 'offline'} ${target}`,
|
|
90
|
+
color: snap.streaming ? Colors.success : Colors.textLight,
|
|
91
|
+
};
|
|
92
|
+
} catch {
|
|
93
|
+
return { label: 'offline desktop sync unavailable', color: Colors.textLight };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// ─── Main Component ────────────────────────────────────
|
|
98
|
+
|
|
43
99
|
interface FloatPanelViewProps {
|
|
44
100
|
features: AnyDebugFeature[];
|
|
45
101
|
panelOpen: boolean;
|
|
@@ -50,6 +106,8 @@ interface FloatPanelViewProps {
|
|
|
50
106
|
|
|
51
107
|
export function FloatPanelView({ features, panelOpen, onOpenPanel, onClosePanel, onClearAll }: FloatPanelViewProps) {
|
|
52
108
|
const [activeTab, setActiveTab] = useState(0);
|
|
109
|
+
const [searchQuery, setSearchQuery] = useState('');
|
|
110
|
+
const [filterBad, setFilterBad] = useState(false);
|
|
53
111
|
const tabLoaded = useRef(false);
|
|
54
112
|
|
|
55
113
|
// Restore last tab on mount
|
|
@@ -74,6 +132,8 @@ export function FloatPanelView({ features, panelOpen, onOpenPanel, onClosePanel,
|
|
|
74
132
|
tabCount: features.length,
|
|
75
133
|
onTabChange: useCallback((index: number) => {
|
|
76
134
|
tabLoaded.current = true;
|
|
135
|
+
setSearchQuery('');
|
|
136
|
+
setFilterBad(false);
|
|
77
137
|
setActiveTab(index);
|
|
78
138
|
const featureName = features[index]?.name;
|
|
79
139
|
if (featureName) {
|
|
@@ -115,7 +175,30 @@ export function FloatPanelView({ features, panelOpen, onOpenPanel, onClosePanel,
|
|
|
115
175
|
|
|
116
176
|
// Badge (first feature that returns one)
|
|
117
177
|
const envBadge = features.map((f) => f.badge?.()).find((b) => b != null) ?? null;
|
|
118
|
-
|
|
178
|
+
|
|
179
|
+
// Rail items with counts
|
|
180
|
+
const railItems: RailItem[] = features.map((f) => {
|
|
181
|
+
const b = f.badge?.();
|
|
182
|
+
return { id: f.name, label: f.label, dotColor: b?.color ?? null, count: snapshotCount(f) };
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
const panelConnectionStatus = buildPanelConnectionStatus(features);
|
|
186
|
+
|
|
187
|
+
const handleClearAll = useCallback(() => {
|
|
188
|
+
setSearchQuery('');
|
|
189
|
+
setFilterBad(false);
|
|
190
|
+
onClearAll();
|
|
191
|
+
}, [onClearAll]);
|
|
192
|
+
|
|
193
|
+
// Active feature + summary
|
|
194
|
+
const activeFeature = features[activeTab];
|
|
195
|
+
const activeSnapshot = activeFeature?.getSnapshot();
|
|
196
|
+
const activeSummary = activeFeature ? buildFeatureSummary(activeFeature, activeSnapshot) : null;
|
|
197
|
+
|
|
198
|
+
// Filtered snapshot — reuse activeSnapshot to avoid double getSnapshot()
|
|
199
|
+
const filteredSnapshot = activeFeature
|
|
200
|
+
? filterFeatureSnapshot(activeFeature, activeSnapshot, searchQuery, filterBad ? 'bad' : 'all')
|
|
201
|
+
: null;
|
|
119
202
|
|
|
120
203
|
// Render active feature content
|
|
121
204
|
const renderFeatureContent = () => {
|
|
@@ -124,7 +207,7 @@ export function FloatPanelView({ features, panelOpen, onOpenPanel, onClosePanel,
|
|
|
124
207
|
}
|
|
125
208
|
const feature = features[activeTab];
|
|
126
209
|
if (!feature) return <Text style={styles.emptyText}>Feature not found</Text>;
|
|
127
|
-
const snapshot =
|
|
210
|
+
const snapshot = filteredSnapshot;
|
|
128
211
|
const TabComponent = feature.renderContent;
|
|
129
212
|
if (TabComponent) return <TabComponent snapshot={snapshot} feature={feature} />;
|
|
130
213
|
return (
|
|
@@ -134,6 +217,8 @@ export function FloatPanelView({ features, panelOpen, onOpenPanel, onClosePanel,
|
|
|
134
217
|
);
|
|
135
218
|
};
|
|
136
219
|
|
|
220
|
+
const showSearch = activeSummary ? (activeSummary.count != null && activeSummary.count > 0) : false;
|
|
221
|
+
|
|
137
222
|
return (
|
|
138
223
|
<DebugErrorBoundary onError={onClosePanel}>
|
|
139
224
|
<View style={styles.container} pointerEvents="box-none">
|
|
@@ -141,18 +226,44 @@ export function FloatPanelView({ features, panelOpen, onOpenPanel, onClosePanel,
|
|
|
141
226
|
{panelOpen && (
|
|
142
227
|
<DebugPanel
|
|
143
228
|
onClose={onClosePanel}
|
|
144
|
-
onClearAll={
|
|
229
|
+
onClearAll={handleClearAll}
|
|
230
|
+
syncLabel={panelConnectionStatus.label}
|
|
231
|
+
syncColor={panelConnectionStatus.color}
|
|
145
232
|
>
|
|
146
|
-
<
|
|
147
|
-
|
|
148
|
-
style={
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
233
|
+
<View style={styles.bodyRow}>
|
|
234
|
+
<FeatureRail items={railItems} activeIndex={activeTab} onSelectTab={switchTab} />
|
|
235
|
+
<View style={styles.contentColumn}>
|
|
236
|
+
{activeFeature && activeSummary && (
|
|
237
|
+
<FeatureIntroCard
|
|
238
|
+
title={activeFeature.label}
|
|
239
|
+
summary={activeSummary}
|
|
240
|
+
filterBad={filterBad}
|
|
241
|
+
onFilterBad={setFilterBad}
|
|
242
|
+
/>
|
|
243
|
+
)}
|
|
244
|
+
{showSearch && (
|
|
245
|
+
<View style={styles.toolbar}>
|
|
246
|
+
<TextInput
|
|
247
|
+
style={styles.searchInput}
|
|
248
|
+
placeholder="Search..."
|
|
249
|
+
placeholderTextColor={Colors.textLight}
|
|
250
|
+
value={searchQuery}
|
|
251
|
+
onChangeText={setSearchQuery}
|
|
252
|
+
returnKeyType="search"
|
|
253
|
+
/>
|
|
254
|
+
</View>
|
|
255
|
+
)}
|
|
256
|
+
<Animated.View
|
|
257
|
+
style={[
|
|
258
|
+
styles.contentContainer,
|
|
259
|
+
{ opacity: contentOpacity, transform: [{ translateX: contentTranslateX }] },
|
|
260
|
+
]}
|
|
261
|
+
{...panHandlers}
|
|
262
|
+
>
|
|
263
|
+
{renderFeatureContent()}
|
|
264
|
+
</Animated.View>
|
|
265
|
+
</View>
|
|
266
|
+
</View>
|
|
156
267
|
</DebugPanel>
|
|
157
268
|
)}
|
|
158
269
|
</View>
|
|
@@ -169,6 +280,34 @@ const styles = StyleSheet.create({
|
|
|
169
280
|
bottom: 0,
|
|
170
281
|
zIndex: 999,
|
|
171
282
|
},
|
|
283
|
+
bodyRow: {
|
|
284
|
+
flex: 1,
|
|
285
|
+
flexDirection: 'row',
|
|
286
|
+
},
|
|
287
|
+
contentColumn: {
|
|
288
|
+
flex: 1,
|
|
289
|
+
},
|
|
290
|
+
toolbar: {
|
|
291
|
+
flexDirection: 'row',
|
|
292
|
+
alignItems: 'center',
|
|
293
|
+
gap: 8,
|
|
294
|
+
paddingHorizontal: 10,
|
|
295
|
+
paddingVertical: 8,
|
|
296
|
+
borderBottomWidth: StyleSheet.hairlineWidth,
|
|
297
|
+
borderBottomColor: Colors.border,
|
|
298
|
+
backgroundColor: Colors.background,
|
|
299
|
+
},
|
|
300
|
+
searchInput: {
|
|
301
|
+
flex: 1,
|
|
302
|
+
height: 34,
|
|
303
|
+
borderWidth: 1,
|
|
304
|
+
borderColor: Colors.border,
|
|
305
|
+
borderRadius: 8,
|
|
306
|
+
backgroundColor: Colors.surface,
|
|
307
|
+
paddingHorizontal: 10,
|
|
308
|
+
fontSize: 13,
|
|
309
|
+
color: Colors.text,
|
|
310
|
+
},
|
|
172
311
|
contentContainer: { flex: 1 },
|
|
173
312
|
emptyText: {
|
|
174
313
|
padding: 20,
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import type { AnyDebugFeature } from '../../types';
|
|
2
|
+
|
|
3
|
+
export interface FeatureSummary {
|
|
4
|
+
capabilityText: string;
|
|
5
|
+
count?: number;
|
|
6
|
+
badCount?: number;
|
|
7
|
+
latestLabel?: string;
|
|
8
|
+
statusLabel?: string;
|
|
9
|
+
statusColor?: string;
|
|
10
|
+
filterMode?: 'all' | 'bad';
|
|
11
|
+
supportsBadFilter: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function buildFeatureSummary(
|
|
15
|
+
feature: AnyDebugFeature,
|
|
16
|
+
snapshot: unknown,
|
|
17
|
+
): FeatureSummary {
|
|
18
|
+
const name = feature.name;
|
|
19
|
+
|
|
20
|
+
if (name === 'network') return buildNetworkSummary(snapshot);
|
|
21
|
+
if (name === 'console') return buildConsoleSummary(snapshot);
|
|
22
|
+
if (name === 'navigation') return buildNavigationSummary(snapshot);
|
|
23
|
+
if (name === 'zustand') return buildZustandSummary(snapshot);
|
|
24
|
+
if (name === 'track') return buildTrackSummary(snapshot);
|
|
25
|
+
if (name === 'clipboard') return buildClipboardSummary(snapshot);
|
|
26
|
+
if (name === 'environment') return buildEnvironmentSummary(snapshot);
|
|
27
|
+
if (name === 'devConnect') return buildDevConnectSummary(snapshot);
|
|
28
|
+
if (name === 'sessionHistory') return buildSessionHistorySummary(snapshot);
|
|
29
|
+
if (name === 'thirdPartyLibs') return buildThirdPartyLibsSummary(snapshot);
|
|
30
|
+
if (name === 'native') return buildNativeSummary(snapshot);
|
|
31
|
+
|
|
32
|
+
return buildUnknownSummary(snapshot);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// ─── Per-feature builders ──────────────────────────────
|
|
36
|
+
|
|
37
|
+
interface NetworkItem {
|
|
38
|
+
request?: { method?: string; url?: string };
|
|
39
|
+
response?: { status?: number };
|
|
40
|
+
error?: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function buildNetworkSummary(snapshot: unknown): FeatureSummary {
|
|
44
|
+
const items = asArray(snapshot);
|
|
45
|
+
const count = items.length;
|
|
46
|
+
let badCount = 0;
|
|
47
|
+
let latestLabel: string | undefined;
|
|
48
|
+
|
|
49
|
+
if (count > 0) {
|
|
50
|
+
for (const item of items) {
|
|
51
|
+
const n = item as NetworkItem;
|
|
52
|
+
if (n.error || (n.response?.status ?? 0) >= 400) badCount++;
|
|
53
|
+
}
|
|
54
|
+
const last = items[items.length - 1] as NetworkItem;
|
|
55
|
+
const method = last.request?.method?.toUpperCase() ?? '';
|
|
56
|
+
const url = last.request?.url ?? '';
|
|
57
|
+
const status = last.response?.status;
|
|
58
|
+
const path = extractPath(url);
|
|
59
|
+
latestLabel = [method, path, status].filter(Boolean).join(' ');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
capabilityText: 'HTTP capture, status, duration, request and response body',
|
|
64
|
+
count,
|
|
65
|
+
badCount: badCount > 0 ? badCount : undefined,
|
|
66
|
+
latestLabel,
|
|
67
|
+
supportsBadFilter: count > 0,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
interface ConsoleItem {
|
|
72
|
+
level?: string;
|
|
73
|
+
data?: unknown[];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function buildConsoleSummary(snapshot: unknown): FeatureSummary {
|
|
77
|
+
const items = asArray(snapshot);
|
|
78
|
+
const count = items.length;
|
|
79
|
+
let badCount = 0;
|
|
80
|
+
let latestLabel: string | undefined;
|
|
81
|
+
|
|
82
|
+
if (count > 0) {
|
|
83
|
+
for (const item of items) {
|
|
84
|
+
const lvl = (item as ConsoleItem).level ?? '';
|
|
85
|
+
if (lvl === 'warn' || lvl === 'error' || lvl === 'fatal') badCount++;
|
|
86
|
+
}
|
|
87
|
+
const last = items[items.length - 1] as ConsoleItem;
|
|
88
|
+
latestLabel = formatConsoleMessage(last.data);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
capabilityText: 'Console log capture with level filtering',
|
|
93
|
+
count,
|
|
94
|
+
badCount: badCount > 0 ? badCount : undefined,
|
|
95
|
+
latestLabel,
|
|
96
|
+
supportsBadFilter: count > 0,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
interface NavigationItem {
|
|
101
|
+
from?: string;
|
|
102
|
+
to?: string;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function buildNavigationSummary(snapshot: unknown): FeatureSummary {
|
|
106
|
+
const items = asArray(snapshot);
|
|
107
|
+
const count = items.length;
|
|
108
|
+
let latestLabel: string | undefined;
|
|
109
|
+
|
|
110
|
+
if (count > 0) {
|
|
111
|
+
const last = items[items.length - 1] as NavigationItem;
|
|
112
|
+
const from = last.from ?? '?';
|
|
113
|
+
const to = last.to ?? '?';
|
|
114
|
+
latestLabel = `${from} → ${to}`;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
capabilityText: 'Screen navigation tracking with route history',
|
|
119
|
+
count,
|
|
120
|
+
latestLabel,
|
|
121
|
+
supportsBadFilter: false,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
interface ZustandItem {
|
|
126
|
+
action?: string;
|
|
127
|
+
storeName?: string;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function buildZustandSummary(snapshot: unknown): FeatureSummary {
|
|
131
|
+
const items = asArray(snapshot);
|
|
132
|
+
const count = items.length;
|
|
133
|
+
let latestLabel: string | undefined;
|
|
134
|
+
|
|
135
|
+
if (count > 0) {
|
|
136
|
+
const last = items[items.length - 1] as ZustandItem;
|
|
137
|
+
const parts = [last.action, last.storeName].filter(Boolean);
|
|
138
|
+
latestLabel = parts.join(' @ ') || undefined;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
capabilityText: 'State change tracking for Zustand stores',
|
|
143
|
+
count,
|
|
144
|
+
latestLabel,
|
|
145
|
+
supportsBadFilter: false,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
interface TrackItem {
|
|
150
|
+
eventName?: string;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function buildTrackSummary(snapshot: unknown): FeatureSummary {
|
|
154
|
+
const items = asArray(snapshot);
|
|
155
|
+
const count = items.length;
|
|
156
|
+
let latestLabel: string | undefined;
|
|
157
|
+
|
|
158
|
+
if (count > 0) {
|
|
159
|
+
const last = items[items.length - 1] as TrackItem;
|
|
160
|
+
latestLabel = last.eventName;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return {
|
|
164
|
+
capabilityText: 'Analytics event tracking and inspection',
|
|
165
|
+
count,
|
|
166
|
+
latestLabel,
|
|
167
|
+
supportsBadFilter: false,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function buildClipboardSummary(_snapshot: unknown): FeatureSummary {
|
|
172
|
+
return {
|
|
173
|
+
capabilityText: 'Clipboard event monitoring',
|
|
174
|
+
supportsBadFilter: false,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
interface EnvironmentSnap {
|
|
179
|
+
environments?: Array<{ id: string; label: string }>;
|
|
180
|
+
currentEnvironmentId?: string | null;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function buildEnvironmentSummary(snapshot: unknown): FeatureSummary {
|
|
184
|
+
const env = (snapshot ?? {}) as EnvironmentSnap;
|
|
185
|
+
const envs = env.environments ?? [];
|
|
186
|
+
const current = envs.find((e) => e.id === env.currentEnvironmentId);
|
|
187
|
+
|
|
188
|
+
return {
|
|
189
|
+
capabilityText: 'Environment configuration and switching',
|
|
190
|
+
count: envs.length || undefined,
|
|
191
|
+
latestLabel: current?.label,
|
|
192
|
+
statusLabel: current?.label,
|
|
193
|
+
supportsBadFilter: false,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
interface DevConnectSnap {
|
|
198
|
+
streaming?: boolean;
|
|
199
|
+
computerHost?: string;
|
|
200
|
+
daemonPort?: string;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function buildDevConnectSummary(snapshot: unknown): FeatureSummary {
|
|
204
|
+
const s = (snapshot ?? {}) as DevConnectSnap;
|
|
205
|
+
const host = [s.computerHost, s.daemonPort].filter(Boolean).join(':');
|
|
206
|
+
|
|
207
|
+
return {
|
|
208
|
+
capabilityText: 'Desktop sync with daemon connection',
|
|
209
|
+
statusLabel: host ? `${s.streaming ? 'live' : 'offline'} ${host}` : s.streaming ? 'live' : undefined,
|
|
210
|
+
statusColor: s.streaming ? '#34C759' : undefined,
|
|
211
|
+
supportsBadFilter: false,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
interface SessionHistorySnap {
|
|
216
|
+
sessions?: unknown[];
|
|
217
|
+
currentSessionId?: string;
|
|
218
|
+
logCounts?: Record<string, unknown>;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function buildSessionHistorySummary(snapshot: unknown): FeatureSummary {
|
|
222
|
+
const s = (snapshot ?? {}) as SessionHistorySnap;
|
|
223
|
+
const count = s.sessions?.length;
|
|
224
|
+
return {
|
|
225
|
+
capabilityText: 'Session log recording and replay',
|
|
226
|
+
count: count || undefined,
|
|
227
|
+
latestLabel: s.currentSessionId,
|
|
228
|
+
supportsBadFilter: false,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function buildThirdPartyLibsSummary(snapshot: unknown): FeatureSummary {
|
|
233
|
+
const items = asArray(snapshot);
|
|
234
|
+
return {
|
|
235
|
+
capabilityText: 'Third-party library inspection and management',
|
|
236
|
+
count: items.length || undefined,
|
|
237
|
+
supportsBadFilter: false,
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function buildNativeSummary(snapshot: unknown): FeatureSummary {
|
|
242
|
+
const items = asArray(snapshot);
|
|
243
|
+
let badCount = 0;
|
|
244
|
+
for (const item of items) {
|
|
245
|
+
const lvl = (item as { level?: string }).level ?? '';
|
|
246
|
+
if (lvl === 'warn' || lvl === 'error' || lvl === 'fatal') badCount++;
|
|
247
|
+
}
|
|
248
|
+
return {
|
|
249
|
+
capabilityText: 'Native log capture',
|
|
250
|
+
count: items.length || undefined,
|
|
251
|
+
badCount: badCount > 0 ? badCount : undefined,
|
|
252
|
+
supportsBadFilter: items.length > 0,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function buildUnknownSummary(snapshot: unknown): FeatureSummary {
|
|
257
|
+
const items = asArray(snapshot);
|
|
258
|
+
return {
|
|
259
|
+
capabilityText: `${items.length} item${items.length !== 1 ? 's' : ''} captured`,
|
|
260
|
+
count: items.length || undefined,
|
|
261
|
+
supportsBadFilter: false,
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// ─── Helpers ───────────────────────────────────────────
|
|
266
|
+
|
|
267
|
+
function asArray(snap: unknown): unknown[] {
|
|
268
|
+
if (Array.isArray(snap)) return snap;
|
|
269
|
+
return [];
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function extractPath(url: string): string {
|
|
273
|
+
try {
|
|
274
|
+
const u = new URL(url);
|
|
275
|
+
return u.pathname + u.search;
|
|
276
|
+
} catch {
|
|
277
|
+
return url;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function formatConsoleMessage(data: unknown[] | undefined): string | undefined {
|
|
282
|
+
if (!data || data.length === 0) return undefined;
|
|
283
|
+
const joined = data
|
|
284
|
+
.map((d) => (typeof d === 'string' ? d : JSON.stringify(d)))
|
|
285
|
+
.join(' ')
|
|
286
|
+
.slice(0, 60);
|
|
287
|
+
return joined || undefined;
|
|
288
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { AnyDebugFeature } from '../../types';
|
|
2
|
+
|
|
3
|
+
export function filterFeatureSnapshot(
|
|
4
|
+
feature: AnyDebugFeature,
|
|
5
|
+
snapshot: unknown,
|
|
6
|
+
query: string,
|
|
7
|
+
filterMode: 'all' | 'bad',
|
|
8
|
+
): unknown {
|
|
9
|
+
if (!Array.isArray(snapshot)) return snapshot;
|
|
10
|
+
|
|
11
|
+
const name = feature.name;
|
|
12
|
+
const supportsBad =
|
|
13
|
+
name === 'network' || name === 'console' || name === 'native';
|
|
14
|
+
|
|
15
|
+
return (snapshot as unknown[]).filter((item) => {
|
|
16
|
+
if (filterMode === 'bad' && supportsBad) {
|
|
17
|
+
if (!isBad(name, item as Record<string, unknown>)) return false;
|
|
18
|
+
}
|
|
19
|
+
if (query) {
|
|
20
|
+
const hay = extractSearchableText(item).toLowerCase();
|
|
21
|
+
if (!hay.includes(query.toLowerCase())) return false;
|
|
22
|
+
}
|
|
23
|
+
return true;
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function isBad(
|
|
28
|
+
featureName: string,
|
|
29
|
+
item: Record<string, unknown>,
|
|
30
|
+
): boolean {
|
|
31
|
+
if (featureName === 'network') {
|
|
32
|
+
const resp = item.response as Record<string, unknown> | undefined;
|
|
33
|
+
return !!(item.error || ((resp?.status as number) ?? 0) >= 400);
|
|
34
|
+
}
|
|
35
|
+
// console, native
|
|
36
|
+
const lvl = (item.level as string) ?? '';
|
|
37
|
+
return lvl === 'warn' || lvl === 'error' || lvl === 'fatal';
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function extractSearchableText(item: unknown): string {
|
|
41
|
+
if (item == null) return '';
|
|
42
|
+
if (typeof item === 'string') return item;
|
|
43
|
+
if (typeof item === 'number' || typeof item === 'boolean') return String(item);
|
|
44
|
+
if (Array.isArray(item)) return item.map(extractSearchableText).join(' ');
|
|
45
|
+
const parts: string[] = [];
|
|
46
|
+
for (const val of Object.values(item as Record<string, unknown>)) {
|
|
47
|
+
const t = extractSearchableText(val);
|
|
48
|
+
if (t) parts.push(t);
|
|
49
|
+
}
|
|
50
|
+
return parts.join(' ');
|
|
51
|
+
}
|
package/src/ui/theme/colors.ts
CHANGED
|
@@ -14,6 +14,13 @@ export const Colors = {
|
|
|
14
14
|
|
|
15
15
|
purple: '#AF52DE',
|
|
16
16
|
|
|
17
|
+
// Panel-specific
|
|
18
|
+
railBackground: '#E8EEF6',
|
|
19
|
+
panelDivider: '#CED8E4',
|
|
20
|
+
signalRedBg: '#FFE9E7',
|
|
21
|
+
signalAmberBg: '#FFF1D6',
|
|
22
|
+
signalDefaultBg: '#E7EDF5',
|
|
23
|
+
|
|
17
24
|
get: '#007AFF',
|
|
18
25
|
post: '#34C759',
|
|
19
26
|
put: '#FF9500',
|
|
@@ -56,6 +56,7 @@ export interface ReportToDaemonOptions extends DebugDeviceReportOptions {
|
|
|
56
56
|
endpoint?: string;
|
|
57
57
|
timeoutMs?: number;
|
|
58
58
|
token?: string;
|
|
59
|
+
session?: SessionInfo;
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
export interface ReportResult {
|
|
@@ -89,6 +90,7 @@ type AbortControllerLike = { signal: unknown; abort: () => void };
|
|
|
89
90
|
type AbortControllerCtor = new () => AbortControllerLike;
|
|
90
91
|
|
|
91
92
|
type SendResult = 'ok' | 'retry' | 'auth_failed';
|
|
93
|
+
type SessionProvider = () => SessionInfo;
|
|
92
94
|
|
|
93
95
|
// ---- Constants ----
|
|
94
96
|
|
|
@@ -186,6 +188,7 @@ export class DaemonClient {
|
|
|
186
188
|
private _onEndpointDetected: ((url: string) => void) | undefined;
|
|
187
189
|
private _restorePromise: Promise<void> | null = null;
|
|
188
190
|
private _sessionId: SessionInfo | null = null;
|
|
191
|
+
private _sessionProvider: SessionProvider | null = null;
|
|
189
192
|
private _onConnectionChange: (() => void) | undefined;
|
|
190
193
|
|
|
191
194
|
constructor(options: DaemonClientOptions) {
|
|
@@ -268,9 +271,7 @@ export class DaemonClient {
|
|
|
268
271
|
connect(options: StreamToDaemonOptions = {}): void {
|
|
269
272
|
if (this._stream) return;
|
|
270
273
|
|
|
271
|
-
|
|
272
|
-
this._sessionId = { id: generateSessionId(), startedAt: Date.now() };
|
|
273
|
-
}
|
|
274
|
+
const session = this.resolveSession();
|
|
274
275
|
|
|
275
276
|
const endpoint = options.endpoint || this.resolveEndpoint();
|
|
276
277
|
const reportUrl = buildDaemonUrl(endpoint, '/report');
|
|
@@ -288,7 +289,7 @@ export class DaemonClient {
|
|
|
288
289
|
debounceMs: options.debounceMs || DEFAULT_DEBOUNCE_MS,
|
|
289
290
|
timeoutMs: Math.max(0, options.timeoutMs ?? DEFAULT_TIMEOUT_MS),
|
|
290
291
|
deviceId: null,
|
|
291
|
-
session
|
|
292
|
+
session,
|
|
292
293
|
sending: false,
|
|
293
294
|
debounceTimer: null,
|
|
294
295
|
retryTimer: null,
|
|
@@ -367,6 +368,14 @@ export class DaemonClient {
|
|
|
367
368
|
this._onConnectionChange = callback;
|
|
368
369
|
}
|
|
369
370
|
|
|
371
|
+
setSessionProvider(provider: SessionProvider): void {
|
|
372
|
+
this._sessionProvider = provider;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
clearSessionProvider(): void {
|
|
376
|
+
this._sessionProvider = null;
|
|
377
|
+
}
|
|
378
|
+
|
|
370
379
|
// --- Restore (init-time reconnect) ---
|
|
371
380
|
|
|
372
381
|
async restore(): Promise<void> {
|
|
@@ -411,7 +420,10 @@ export class DaemonClient {
|
|
|
411
420
|
async reportOnce(options: ReportToDaemonOptions = {}): Promise<ReportResult> {
|
|
412
421
|
const endpoint = options.endpoint ?? this.resolveEndpoint();
|
|
413
422
|
const reportUrl = buildDaemonUrl(endpoint, '/report');
|
|
414
|
-
const report = createDebugDeviceReport(
|
|
423
|
+
const report = createDebugDeviceReport({
|
|
424
|
+
...options,
|
|
425
|
+
session: options.session ?? this.resolveSession(),
|
|
426
|
+
});
|
|
415
427
|
const fetchImpl = this.resolveFetch();
|
|
416
428
|
|
|
417
429
|
this.notifyEndpoint(endpoint);
|
|
@@ -475,6 +487,7 @@ export class DaemonClient {
|
|
|
475
487
|
this._streamingEnabled = null;
|
|
476
488
|
this._restorePromise = null;
|
|
477
489
|
this._sessionId = null;
|
|
490
|
+
this._sessionProvider = null;
|
|
478
491
|
}
|
|
479
492
|
|
|
480
493
|
// ---- Private: Transport ----
|
|
@@ -498,6 +511,21 @@ export class DaemonClient {
|
|
|
498
511
|
this._onEndpointDetected?.(url);
|
|
499
512
|
}
|
|
500
513
|
|
|
514
|
+
private resolveSession(): SessionInfo {
|
|
515
|
+
if (this._sessionProvider) {
|
|
516
|
+
try {
|
|
517
|
+
return this._sessionProvider();
|
|
518
|
+
} catch {
|
|
519
|
+
// fall through to internal session
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
if (!this._sessionId) {
|
|
524
|
+
this._sessionId = { id: generateSessionId(), startedAt: Date.now() };
|
|
525
|
+
}
|
|
526
|
+
return this._sessionId;
|
|
527
|
+
}
|
|
528
|
+
|
|
501
529
|
private emitStatus(status: StreamStatus): void {
|
|
502
530
|
try {
|
|
503
531
|
this._stream?.onStatus?.(status);
|