opensteer 0.9.2 → 0.9.4
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/README.md +158 -165
- package/dist/{chunk-HD6KVZ42.js → chunk-GEUHKPC2.js} +46 -16
- package/dist/chunk-GEUHKPC2.js.map +1 -0
- package/dist/{chunk-2TIVULZY.js → chunk-GSCQQKZZ.js} +53 -9
- package/dist/chunk-GSCQQKZZ.js.map +1 -0
- package/dist/{chunk-KPYLS2KQ.js → chunk-HQCMXRBE.js} +5 -4
- package/dist/chunk-HQCMXRBE.js.map +1 -0
- package/dist/{chunk-BMPUL66S.js → chunk-T5P2QGZ3.js} +58 -53
- package/dist/chunk-T5P2QGZ3.js.map +1 -0
- package/dist/{chunk-FIMNKEG5.js → chunk-ZRF7WMS3.js} +4 -4
- package/dist/{chunk-FIMNKEG5.js.map → chunk-ZRF7WMS3.js.map} +1 -1
- package/dist/cli/bin.cjs +160 -72
- package/dist/cli/bin.cjs.map +1 -1
- package/dist/cli/bin.js +17 -7
- package/dist/cli/bin.js.map +1 -1
- package/dist/index.cjs +149 -69
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -2
- package/dist/index.d.ts +19 -2
- package/dist/index.js +4 -4
- package/dist/local-view/public/assets/app.css +219 -55
- package/dist/local-view/public/assets/app.js +58 -2
- package/dist/local-view/public/index.html +101 -26
- package/dist/local-view/serve-entry.cjs +106 -57
- package/dist/local-view/serve-entry.cjs.map +1 -1
- package/dist/local-view/serve-entry.js +2 -2
- package/dist/opensteer-PJI7VUIT.js +6 -0
- package/dist/{opensteer-MIQ43CY4.js.map → opensteer-PJI7VUIT.js.map} +1 -1
- package/dist/{session-control-IFE3IPS3.js → session-control-M3JD7ZKA.js} +4 -4
- package/dist/{session-control-IFE3IPS3.js.map → session-control-M3JD7ZKA.js.map} +1 -1
- package/package.json +5 -5
- package/skills/opensteer/SKILL.md +7 -8
- package/skills/recorder/SKILL.md +43 -48
- package/dist/chunk-2TIVULZY.js.map +0 -1
- package/dist/chunk-BMPUL66S.js.map +0 -1
- package/dist/chunk-HD6KVZ42.js.map +0 -1
- package/dist/chunk-KPYLS2KQ.js.map +0 -1
- package/dist/opensteer-MIQ43CY4.js +0 -6
- package/skills/recorder/references/recorder-reference.md +0 -71
package/dist/index.d.cts
CHANGED
|
@@ -1637,6 +1637,14 @@ interface OpensteerAttachBrowserOptions {
|
|
|
1637
1637
|
}
|
|
1638
1638
|
type OpensteerBrowserMode = "temporary" | "persistent";
|
|
1639
1639
|
type OpensteerBrowserOptions = OpensteerBrowserMode | OpensteerAttachBrowserOptions;
|
|
1640
|
+
interface OpensteerHumanizeOptions {
|
|
1641
|
+
/** Interpolate mouse paths with curves and jitter before clicks/scrolls. */
|
|
1642
|
+
readonly mouse?: boolean;
|
|
1643
|
+
/** Realistic per-character typing cadence with key hold duration. */
|
|
1644
|
+
readonly keyboard?: boolean;
|
|
1645
|
+
/** Break large scrolls into discrete wheel ticks with delays. */
|
|
1646
|
+
readonly scroll?: boolean;
|
|
1647
|
+
}
|
|
1640
1648
|
interface OpensteerBrowserContextOptions {
|
|
1641
1649
|
readonly ignoreHTTPSErrors?: boolean;
|
|
1642
1650
|
readonly locale?: string;
|
|
@@ -1651,6 +1659,12 @@ interface OpensteerBrowserContextOptions {
|
|
|
1651
1659
|
readonly reducedMotion?: "reduce" | "no-preference";
|
|
1652
1660
|
readonly colorScheme?: "light" | "dark" | "no-preference";
|
|
1653
1661
|
readonly stealthProfile?: OpensteerStealthProfileInput;
|
|
1662
|
+
/**
|
|
1663
|
+
* Enable human-like interaction patterns for mouse, keyboard, and scroll
|
|
1664
|
+
* events. When `true` (the default), all sub-options are enabled. Pass
|
|
1665
|
+
* `false` to disable, or an object to control individual categories.
|
|
1666
|
+
*/
|
|
1667
|
+
readonly humanize?: boolean | OpensteerHumanizeOptions;
|
|
1654
1668
|
}
|
|
1655
1669
|
interface OpensteerStealthProfileInput {
|
|
1656
1670
|
readonly id?: string;
|
|
@@ -2958,6 +2972,8 @@ declare function createOpensteerExtractionDescriptorStore(options: {
|
|
|
2958
2972
|
}): OpensteerExtractionDescriptorStore;
|
|
2959
2973
|
declare function parseExtractionDescriptorRecord(record: DescriptorRecord): OpensteerExtractionDescriptorRecord | undefined;
|
|
2960
2974
|
|
|
2975
|
+
type OpensteerEnvironment = Record<string, string | undefined>;
|
|
2976
|
+
|
|
2961
2977
|
declare const OPENSTEER_ENGINE_NAMES: readonly ["playwright", "abp"];
|
|
2962
2978
|
type OpensteerEngineName = (typeof OPENSTEER_ENGINE_NAMES)[number];
|
|
2963
2979
|
declare const DEFAULT_OPENSTEER_ENGINE: OpensteerEngineName;
|
|
@@ -3006,6 +3022,7 @@ interface OpensteerBrowserManagerOptions {
|
|
|
3006
3022
|
readonly rootPath?: string;
|
|
3007
3023
|
readonly workspace?: string;
|
|
3008
3024
|
readonly engineName?: OpensteerEngineName;
|
|
3025
|
+
readonly environment?: OpensteerEnvironment;
|
|
3009
3026
|
readonly browser?: OpensteerBrowserOptions;
|
|
3010
3027
|
readonly launch?: OpensteerBrowserLaunchOptions;
|
|
3011
3028
|
readonly context?: OpensteerBrowserContextOptions;
|
|
@@ -3139,6 +3156,7 @@ interface OpensteerRuntimeOptions {
|
|
|
3139
3156
|
readonly rootDir?: string;
|
|
3140
3157
|
readonly rootPath?: string;
|
|
3141
3158
|
readonly engineName?: OpensteerEngineName;
|
|
3159
|
+
readonly environment?: OpensteerEnvironment;
|
|
3142
3160
|
readonly browser?: OpensteerBrowserOptions;
|
|
3143
3161
|
readonly launch?: OpensteerBrowserLaunchOptions;
|
|
3144
3162
|
readonly context?: OpensteerBrowserContextOptions;
|
|
@@ -3157,6 +3175,7 @@ interface OpensteerSessionRuntimeOptions {
|
|
|
3157
3175
|
readonly rootDir?: string;
|
|
3158
3176
|
readonly rootPath?: string;
|
|
3159
3177
|
readonly engineName?: OpensteerEngineName;
|
|
3178
|
+
readonly environment?: OpensteerEnvironment;
|
|
3160
3179
|
readonly browser?: OpensteerBrowserOptions;
|
|
3161
3180
|
readonly launch?: OpensteerBrowserLaunchOptions;
|
|
3162
3181
|
readonly context?: OpensteerBrowserContextOptions;
|
|
@@ -3287,8 +3306,6 @@ declare class Opensteer {
|
|
|
3287
3306
|
private requireOwnedInstrumentationRuntime;
|
|
3288
3307
|
}
|
|
3289
3308
|
|
|
3290
|
-
type OpensteerEnvironment = Record<string, string | undefined>;
|
|
3291
|
-
|
|
3292
3309
|
interface OpensteerCloudConfig {
|
|
3293
3310
|
readonly apiKey: string;
|
|
3294
3311
|
readonly baseUrl: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -1637,6 +1637,14 @@ interface OpensteerAttachBrowserOptions {
|
|
|
1637
1637
|
}
|
|
1638
1638
|
type OpensteerBrowserMode = "temporary" | "persistent";
|
|
1639
1639
|
type OpensteerBrowserOptions = OpensteerBrowserMode | OpensteerAttachBrowserOptions;
|
|
1640
|
+
interface OpensteerHumanizeOptions {
|
|
1641
|
+
/** Interpolate mouse paths with curves and jitter before clicks/scrolls. */
|
|
1642
|
+
readonly mouse?: boolean;
|
|
1643
|
+
/** Realistic per-character typing cadence with key hold duration. */
|
|
1644
|
+
readonly keyboard?: boolean;
|
|
1645
|
+
/** Break large scrolls into discrete wheel ticks with delays. */
|
|
1646
|
+
readonly scroll?: boolean;
|
|
1647
|
+
}
|
|
1640
1648
|
interface OpensteerBrowserContextOptions {
|
|
1641
1649
|
readonly ignoreHTTPSErrors?: boolean;
|
|
1642
1650
|
readonly locale?: string;
|
|
@@ -1651,6 +1659,12 @@ interface OpensteerBrowserContextOptions {
|
|
|
1651
1659
|
readonly reducedMotion?: "reduce" | "no-preference";
|
|
1652
1660
|
readonly colorScheme?: "light" | "dark" | "no-preference";
|
|
1653
1661
|
readonly stealthProfile?: OpensteerStealthProfileInput;
|
|
1662
|
+
/**
|
|
1663
|
+
* Enable human-like interaction patterns for mouse, keyboard, and scroll
|
|
1664
|
+
* events. When `true` (the default), all sub-options are enabled. Pass
|
|
1665
|
+
* `false` to disable, or an object to control individual categories.
|
|
1666
|
+
*/
|
|
1667
|
+
readonly humanize?: boolean | OpensteerHumanizeOptions;
|
|
1654
1668
|
}
|
|
1655
1669
|
interface OpensteerStealthProfileInput {
|
|
1656
1670
|
readonly id?: string;
|
|
@@ -2958,6 +2972,8 @@ declare function createOpensteerExtractionDescriptorStore(options: {
|
|
|
2958
2972
|
}): OpensteerExtractionDescriptorStore;
|
|
2959
2973
|
declare function parseExtractionDescriptorRecord(record: DescriptorRecord): OpensteerExtractionDescriptorRecord | undefined;
|
|
2960
2974
|
|
|
2975
|
+
type OpensteerEnvironment = Record<string, string | undefined>;
|
|
2976
|
+
|
|
2961
2977
|
declare const OPENSTEER_ENGINE_NAMES: readonly ["playwright", "abp"];
|
|
2962
2978
|
type OpensteerEngineName = (typeof OPENSTEER_ENGINE_NAMES)[number];
|
|
2963
2979
|
declare const DEFAULT_OPENSTEER_ENGINE: OpensteerEngineName;
|
|
@@ -3006,6 +3022,7 @@ interface OpensteerBrowserManagerOptions {
|
|
|
3006
3022
|
readonly rootPath?: string;
|
|
3007
3023
|
readonly workspace?: string;
|
|
3008
3024
|
readonly engineName?: OpensteerEngineName;
|
|
3025
|
+
readonly environment?: OpensteerEnvironment;
|
|
3009
3026
|
readonly browser?: OpensteerBrowserOptions;
|
|
3010
3027
|
readonly launch?: OpensteerBrowserLaunchOptions;
|
|
3011
3028
|
readonly context?: OpensteerBrowserContextOptions;
|
|
@@ -3139,6 +3156,7 @@ interface OpensteerRuntimeOptions {
|
|
|
3139
3156
|
readonly rootDir?: string;
|
|
3140
3157
|
readonly rootPath?: string;
|
|
3141
3158
|
readonly engineName?: OpensteerEngineName;
|
|
3159
|
+
readonly environment?: OpensteerEnvironment;
|
|
3142
3160
|
readonly browser?: OpensteerBrowserOptions;
|
|
3143
3161
|
readonly launch?: OpensteerBrowserLaunchOptions;
|
|
3144
3162
|
readonly context?: OpensteerBrowserContextOptions;
|
|
@@ -3157,6 +3175,7 @@ interface OpensteerSessionRuntimeOptions {
|
|
|
3157
3175
|
readonly rootDir?: string;
|
|
3158
3176
|
readonly rootPath?: string;
|
|
3159
3177
|
readonly engineName?: OpensteerEngineName;
|
|
3178
|
+
readonly environment?: OpensteerEnvironment;
|
|
3160
3179
|
readonly browser?: OpensteerBrowserOptions;
|
|
3161
3180
|
readonly launch?: OpensteerBrowserLaunchOptions;
|
|
3162
3181
|
readonly context?: OpensteerBrowserContextOptions;
|
|
@@ -3287,8 +3306,6 @@ declare class Opensteer {
|
|
|
3287
3306
|
private requireOwnedInstrumentationRuntime;
|
|
3288
3307
|
}
|
|
3289
3308
|
|
|
3290
|
-
type OpensteerEnvironment = Record<string, string | undefined>;
|
|
3291
|
-
|
|
3292
3309
|
interface OpensteerCloudConfig {
|
|
3293
3310
|
readonly apiKey: string;
|
|
3294
3311
|
readonly baseUrl: string;
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import './chunk-KCINASQC.js';
|
|
2
|
-
export { Opensteer } from './chunk-
|
|
3
|
-
export { CloudSessionProxy, DEFERRED_MATCH_ATTR_KEYS, ElementPathError, MATCH_ATTRIBUTE_PRIORITY, OPENSTEER_DOM_ACTION_BRIDGE_SYMBOL, OpensteerCloudClient, OpensteerRuntime, OpensteerSessionRuntime, STABLE_PRIMARY_ATTR_KEYS, assertProviderSupportsEngine, buildArrayFieldPathCandidates, buildDomDescriptorKey, buildDomDescriptorPayload, buildDomDescriptorVersion, buildPathCandidates, buildPathSelectorHint, buildSegmentSelector, cloneElementPath, cloneReplayElementPath, cloneStructuralElementAnchor, createDomDescriptorStore, createDomRuntime, createOpensteerExtractionDescriptorStore, createOpensteerSemanticRuntime, defaultFallbackPolicy, defaultPolicy, defaultRetryPolicy, defaultSettlePolicy, defaultTimeoutPolicy, delayWithSignal, dispatchSemanticOperation, hashDomDescriptorPersist, isCurrentUrlField, isValidCssAttributeKey, normalizeExtractedValue, normalizeOpensteerProviderMode, parseDomDescriptorRecord, parseExtractionDescriptorRecord, resolveCloudConfig, resolveDomActionBridge, resolveExtractedValueInContext, resolveOpensteerProvider, resolveOpensteerRuntimeConfig, runWithPolicyTimeout, sanitizeElementPath, sanitizeReplayElementPath, sanitizeStructuralElementAnchor, settleWithPolicy, shouldKeepAttributeForPath } from './chunk-
|
|
4
|
-
export { DEFAULT_OPENSTEER_ENGINE, OPENSTEER_ENGINE_NAMES, OPENSTEER_FILESYSTEM_WORKSPACE_LAYOUT, OPENSTEER_FILESYSTEM_WORKSPACE_VERSION, OpensteerBrowserManager, createArtifactStore, createFilesystemOpensteerWorkspace, createObservationStore, manifestToExternalBinaryLocation, normalizeObservabilityConfig, normalizeOpensteerEngineName, normalizeWorkspaceId, resolveFilesystemWorkspacePath, resolveOpensteerEngineName } from './chunk-
|
|
5
|
-
export { OpensteerAttachAmbiguousError, clearPersistedSessionRecord, discoverLocalCdpBrowsers, inspectCdpEndpoint, listLocalChromeProfiles, readPersistedCloudSessionRecord, readPersistedLocalBrowserSessionRecord, readPersistedSessionRecord, resolveCloudSessionRecordPath, resolveLiveSessionRecordPath, resolveLocalSessionRecordPath, writePersistedSessionRecord } from './chunk-
|
|
2
|
+
export { Opensteer } from './chunk-HQCMXRBE.js';
|
|
3
|
+
export { CloudSessionProxy, DEFERRED_MATCH_ATTR_KEYS, ElementPathError, MATCH_ATTRIBUTE_PRIORITY, OPENSTEER_DOM_ACTION_BRIDGE_SYMBOL, OpensteerCloudClient, OpensteerRuntime, OpensteerSessionRuntime, STABLE_PRIMARY_ATTR_KEYS, assertProviderSupportsEngine, buildArrayFieldPathCandidates, buildDomDescriptorKey, buildDomDescriptorPayload, buildDomDescriptorVersion, buildPathCandidates, buildPathSelectorHint, buildSegmentSelector, cloneElementPath, cloneReplayElementPath, cloneStructuralElementAnchor, createDomDescriptorStore, createDomRuntime, createOpensteerExtractionDescriptorStore, createOpensteerSemanticRuntime, defaultFallbackPolicy, defaultPolicy, defaultRetryPolicy, defaultSettlePolicy, defaultTimeoutPolicy, delayWithSignal, dispatchSemanticOperation, hashDomDescriptorPersist, isCurrentUrlField, isValidCssAttributeKey, normalizeExtractedValue, normalizeOpensteerProviderMode, parseDomDescriptorRecord, parseExtractionDescriptorRecord, resolveCloudConfig, resolveDomActionBridge, resolveExtractedValueInContext, resolveOpensteerProvider, resolveOpensteerRuntimeConfig, runWithPolicyTimeout, sanitizeElementPath, sanitizeReplayElementPath, sanitizeStructuralElementAnchor, settleWithPolicy, shouldKeepAttributeForPath } from './chunk-GEUHKPC2.js';
|
|
4
|
+
export { DEFAULT_OPENSTEER_ENGINE, OPENSTEER_ENGINE_NAMES, OPENSTEER_FILESYSTEM_WORKSPACE_LAYOUT, OPENSTEER_FILESYSTEM_WORKSPACE_VERSION, OpensteerBrowserManager, createArtifactStore, createFilesystemOpensteerWorkspace, createObservationStore, manifestToExternalBinaryLocation, normalizeObservabilityConfig, normalizeOpensteerEngineName, normalizeWorkspaceId, resolveFilesystemWorkspacePath, resolveOpensteerEngineName } from './chunk-GSCQQKZZ.js';
|
|
5
|
+
export { OpensteerAttachAmbiguousError, clearPersistedSessionRecord, discoverLocalCdpBrowsers, inspectCdpEndpoint, listLocalChromeProfiles, readPersistedCloudSessionRecord, readPersistedLocalBrowserSessionRecord, readPersistedSessionRecord, resolveCloudSessionRecordPath, resolveLiveSessionRecordPath, resolveLocalSessionRecordPath, writePersistedSessionRecord } from './chunk-T5P2QGZ3.js';
|
|
6
6
|
//# sourceMappingURL=index.js.map
|
|
7
7
|
//# sourceMappingURL=index.js.map
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
--accent-foreground: #000000;
|
|
17
17
|
--destructive: #ef4444;
|
|
18
18
|
--ring: rgba(255, 255, 255, 0.4);
|
|
19
|
+
--top-bar-height: 44px;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
/* ─── Reset ─── */
|
|
@@ -34,14 +35,7 @@ body {
|
|
|
34
35
|
overflow: hidden;
|
|
35
36
|
background: var(--background);
|
|
36
37
|
color: var(--foreground);
|
|
37
|
-
font-family:
|
|
38
|
-
Inter,
|
|
39
|
-
ui-sans-serif,
|
|
40
|
-
system-ui,
|
|
41
|
-
-apple-system,
|
|
42
|
-
BlinkMacSystemFont,
|
|
43
|
-
"Segoe UI",
|
|
44
|
-
sans-serif;
|
|
38
|
+
font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", system-ui, sans-serif;
|
|
45
39
|
font-size: 14px;
|
|
46
40
|
line-height: 1.5;
|
|
47
41
|
-webkit-font-smoothing: antialiased;
|
|
@@ -124,34 +118,78 @@ button {
|
|
|
124
118
|
height: 100vh;
|
|
125
119
|
min-height: 0;
|
|
126
120
|
display: flex;
|
|
121
|
+
flex-direction: column;
|
|
127
122
|
overflow: hidden;
|
|
128
123
|
}
|
|
129
124
|
|
|
130
|
-
/* ───
|
|
125
|
+
/* ─── Top Bar ─── */
|
|
131
126
|
|
|
132
|
-
.
|
|
133
|
-
|
|
127
|
+
.top-bar {
|
|
128
|
+
height: var(--top-bar-height);
|
|
134
129
|
flex-shrink: 0;
|
|
135
130
|
display: flex;
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
131
|
+
align-items: center;
|
|
132
|
+
gap: 12px;
|
|
133
|
+
padding: 0 16px;
|
|
139
134
|
background: var(--surface);
|
|
135
|
+
border-bottom: 1px solid var(--border);
|
|
136
|
+
z-index: 50;
|
|
137
|
+
position: relative;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.drawer-toggle {
|
|
141
|
+
position: relative;
|
|
142
|
+
display: inline-flex;
|
|
143
|
+
align-items: center;
|
|
144
|
+
justify-content: center;
|
|
145
|
+
width: 32px;
|
|
146
|
+
height: 32px;
|
|
147
|
+
border: none;
|
|
148
|
+
border-radius: 6px;
|
|
149
|
+
background: transparent;
|
|
150
|
+
color: var(--muted-foreground);
|
|
151
|
+
padding: 0;
|
|
152
|
+
flex-shrink: 0;
|
|
153
|
+
transition:
|
|
154
|
+
background 150ms ease,
|
|
155
|
+
color 150ms ease;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.drawer-toggle:hover {
|
|
159
|
+
background: var(--muted);
|
|
160
|
+
color: var(--foreground);
|
|
140
161
|
}
|
|
141
162
|
|
|
142
|
-
.
|
|
163
|
+
.drawer-toggle:active {
|
|
164
|
+
background: var(--border-strong);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.session-count-badge {
|
|
168
|
+
position: absolute;
|
|
169
|
+
top: 1px;
|
|
170
|
+
right: 1px;
|
|
171
|
+
min-width: 16px;
|
|
172
|
+
height: 16px;
|
|
173
|
+
border-radius: 8px;
|
|
174
|
+
background: var(--accent);
|
|
175
|
+
color: var(--accent-foreground);
|
|
176
|
+
font-size: 9px;
|
|
177
|
+
font-weight: 600;
|
|
143
178
|
display: flex;
|
|
144
179
|
align-items: center;
|
|
145
|
-
justify-content:
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
180
|
+
justify-content: center;
|
|
181
|
+
padding: 0 4px;
|
|
182
|
+
line-height: 1;
|
|
183
|
+
pointer-events: none;
|
|
149
184
|
}
|
|
150
185
|
|
|
186
|
+
/* ─── Brand ─── */
|
|
187
|
+
|
|
151
188
|
.brand-row {
|
|
152
189
|
display: inline-flex;
|
|
153
190
|
align-items: center;
|
|
154
191
|
gap: 8px;
|
|
192
|
+
flex-shrink: 0;
|
|
155
193
|
}
|
|
156
194
|
|
|
157
195
|
.brand-icon {
|
|
@@ -182,6 +220,80 @@ button {
|
|
|
182
220
|
letter-spacing: 0.04em;
|
|
183
221
|
}
|
|
184
222
|
|
|
223
|
+
.top-bar-divider {
|
|
224
|
+
width: 1px;
|
|
225
|
+
height: 20px;
|
|
226
|
+
background: var(--border-strong);
|
|
227
|
+
flex-shrink: 0;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/* ─── Active Session Indicator ─── */
|
|
231
|
+
|
|
232
|
+
.active-session-indicator {
|
|
233
|
+
display: inline-flex;
|
|
234
|
+
align-items: center;
|
|
235
|
+
gap: 8px;
|
|
236
|
+
border: 1px solid var(--border);
|
|
237
|
+
border-radius: 8px;
|
|
238
|
+
background: var(--surface-elevated);
|
|
239
|
+
color: var(--foreground);
|
|
240
|
+
padding: 5px 12px;
|
|
241
|
+
font-size: 12px;
|
|
242
|
+
font-weight: 500;
|
|
243
|
+
white-space: nowrap;
|
|
244
|
+
overflow: hidden;
|
|
245
|
+
max-width: 300px;
|
|
246
|
+
transition:
|
|
247
|
+
background 150ms ease,
|
|
248
|
+
border-color 150ms ease;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.active-session-indicator:hover {
|
|
252
|
+
background: var(--surface-raised);
|
|
253
|
+
border-color: var(--border-strong);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.active-session-indicator:active {
|
|
257
|
+
background: rgba(255, 255, 255, 0.08);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.active-session-dot {
|
|
261
|
+
flex-shrink: 0;
|
|
262
|
+
width: 6px;
|
|
263
|
+
height: 6px;
|
|
264
|
+
border-radius: 50%;
|
|
265
|
+
background: var(--muted-foreground);
|
|
266
|
+
opacity: 0.4;
|
|
267
|
+
transition: all 200ms ease;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.active-session-dot.is-active {
|
|
271
|
+
background: #28c840;
|
|
272
|
+
opacity: 1;
|
|
273
|
+
animation: pulse-dot 1.5s ease-in-out infinite;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.active-session-label {
|
|
277
|
+
overflow: hidden;
|
|
278
|
+
text-overflow: ellipsis;
|
|
279
|
+
white-space: nowrap;
|
|
280
|
+
min-width: 0;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.active-session-chevron {
|
|
284
|
+
flex-shrink: 0;
|
|
285
|
+
color: var(--muted-foreground);
|
|
286
|
+
opacity: 0.5;
|
|
287
|
+
transition: transform 200ms ease;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
.top-bar-spacer {
|
|
291
|
+
flex: 1;
|
|
292
|
+
min-width: 0;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/* ─── View Toggle ─── */
|
|
296
|
+
|
|
185
297
|
.local-view-toggle {
|
|
186
298
|
flex-shrink: 0;
|
|
187
299
|
height: 26px;
|
|
@@ -211,52 +323,100 @@ button {
|
|
|
211
323
|
opacity: 0.6;
|
|
212
324
|
}
|
|
213
325
|
|
|
214
|
-
/* ───
|
|
326
|
+
/* ─── Session Drawer ─── */
|
|
215
327
|
|
|
216
|
-
.
|
|
217
|
-
|
|
218
|
-
|
|
328
|
+
.drawer-backdrop {
|
|
329
|
+
position: fixed;
|
|
330
|
+
top: var(--top-bar-height);
|
|
331
|
+
left: 0;
|
|
332
|
+
right: 0;
|
|
333
|
+
bottom: 0;
|
|
334
|
+
background: rgba(0, 0, 0, 0.5);
|
|
335
|
+
backdrop-filter: blur(4px);
|
|
336
|
+
-webkit-backdrop-filter: blur(4px);
|
|
337
|
+
opacity: 0;
|
|
338
|
+
pointer-events: none;
|
|
339
|
+
transition: opacity 280ms ease;
|
|
340
|
+
z-index: 90;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
.drawer-backdrop.is-visible {
|
|
344
|
+
opacity: 1;
|
|
345
|
+
pointer-events: auto;
|
|
219
346
|
}
|
|
220
347
|
|
|
221
|
-
.
|
|
348
|
+
.session-drawer {
|
|
349
|
+
position: fixed;
|
|
350
|
+
top: var(--top-bar-height);
|
|
351
|
+
left: 0;
|
|
352
|
+
bottom: 0;
|
|
353
|
+
width: 320px;
|
|
222
354
|
display: flex;
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
355
|
+
flex-direction: column;
|
|
356
|
+
background: var(--surface);
|
|
357
|
+
border-right: 1px solid var(--border);
|
|
358
|
+
transform: translateX(-100%);
|
|
359
|
+
transition:
|
|
360
|
+
transform 280ms cubic-bezier(0, 0, 0.2, 1),
|
|
361
|
+
box-shadow 280ms ease;
|
|
362
|
+
z-index: 100;
|
|
363
|
+
overflow: hidden;
|
|
227
364
|
}
|
|
228
365
|
|
|
229
|
-
.
|
|
230
|
-
|
|
366
|
+
.session-drawer.is-open {
|
|
367
|
+
transform: translateX(0);
|
|
368
|
+
box-shadow: 8px 0 32px rgba(0, 0, 0, 0.4);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
.drawer-header {
|
|
372
|
+
display: flex;
|
|
373
|
+
align-items: center;
|
|
374
|
+
justify-content: space-between;
|
|
375
|
+
padding: 14px 16px;
|
|
376
|
+
border-bottom: 1px solid var(--border);
|
|
377
|
+
flex-shrink: 0;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
.drawer-title {
|
|
381
|
+
font-size: 13px;
|
|
382
|
+
font-weight: 600;
|
|
383
|
+
color: var(--foreground);
|
|
384
|
+
letter-spacing: 0.02em;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
.drawer-close {
|
|
388
|
+
display: inline-flex;
|
|
389
|
+
align-items: center;
|
|
390
|
+
justify-content: center;
|
|
391
|
+
width: 28px;
|
|
392
|
+
height: 28px;
|
|
231
393
|
border: none;
|
|
232
394
|
border-radius: 6px;
|
|
233
|
-
padding: 6px 12px;
|
|
234
|
-
font-size: 12px;
|
|
235
|
-
font-weight: 500;
|
|
236
|
-
color: var(--muted-foreground);
|
|
237
395
|
background: transparent;
|
|
238
|
-
|
|
396
|
+
color: var(--muted-foreground);
|
|
397
|
+
padding: 0;
|
|
398
|
+
transition:
|
|
399
|
+
background 150ms ease,
|
|
400
|
+
color 150ms ease;
|
|
239
401
|
}
|
|
240
402
|
|
|
241
|
-
.
|
|
242
|
-
background:
|
|
403
|
+
.drawer-close:hover {
|
|
404
|
+
background: var(--muted);
|
|
243
405
|
color: var(--foreground);
|
|
244
406
|
}
|
|
245
407
|
|
|
246
|
-
.
|
|
247
|
-
background: var(--
|
|
248
|
-
color: var(--foreground);
|
|
249
|
-
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
|
|
408
|
+
.drawer-close:active {
|
|
409
|
+
background: var(--border-strong);
|
|
250
410
|
}
|
|
251
411
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
.sidebar-scroll {
|
|
412
|
+
.drawer-scroll {
|
|
255
413
|
flex: 1;
|
|
256
414
|
min-height: 0;
|
|
257
415
|
overflow-y: auto;
|
|
258
416
|
}
|
|
259
417
|
|
|
418
|
+
/* ─── Session List ─── */
|
|
419
|
+
|
|
260
420
|
.session-list {
|
|
261
421
|
display: flex;
|
|
262
422
|
flex-direction: column;
|
|
@@ -383,7 +543,7 @@ button {
|
|
|
383
543
|
display: flex;
|
|
384
544
|
align-items: flex-start;
|
|
385
545
|
justify-content: center;
|
|
386
|
-
padding:
|
|
546
|
+
padding: 16px;
|
|
387
547
|
min-height: 0;
|
|
388
548
|
overflow: hidden;
|
|
389
549
|
}
|
|
@@ -750,21 +910,25 @@ button {
|
|
|
750
910
|
/* ─── Responsive ─── */
|
|
751
911
|
|
|
752
912
|
@media (max-width: 768px) {
|
|
753
|
-
.
|
|
754
|
-
|
|
913
|
+
.session-drawer {
|
|
914
|
+
width: 100%;
|
|
755
915
|
}
|
|
756
916
|
|
|
757
|
-
.
|
|
758
|
-
|
|
759
|
-
border-right: none;
|
|
760
|
-
border-bottom: 1px solid var(--border);
|
|
917
|
+
.viewer-area {
|
|
918
|
+
padding: 8px;
|
|
761
919
|
}
|
|
920
|
+
}
|
|
762
921
|
|
|
763
|
-
|
|
764
|
-
|
|
922
|
+
@media (max-width: 640px) {
|
|
923
|
+
.brand-name {
|
|
924
|
+
display: none;
|
|
765
925
|
}
|
|
766
926
|
|
|
767
|
-
.
|
|
768
|
-
|
|
927
|
+
.top-bar-divider {
|
|
928
|
+
display: none;
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
.active-session-indicator {
|
|
932
|
+
max-width: 180px;
|
|
769
933
|
}
|
|
770
934
|
}
|
|
@@ -956,6 +956,7 @@ class LocalViewApp {
|
|
|
956
956
|
this.layoutFrame = null;
|
|
957
957
|
this.lastBrowserFrameWidth = null;
|
|
958
958
|
this.lastStreamAspect = null;
|
|
959
|
+
this.drawerOpen = false;
|
|
959
960
|
|
|
960
961
|
this.viewerAreaEl = document.querySelector(".viewer-area");
|
|
961
962
|
this.browserFrameEl = document.querySelector(".browser-frame");
|
|
@@ -978,6 +979,14 @@ class LocalViewApp {
|
|
|
978
979
|
this.newTabButtonEl = document.getElementById("new-tab-button");
|
|
979
980
|
this.closeBrowserButtonEl = document.getElementById("close-browser-button");
|
|
980
981
|
this.stopViewButtonEl = document.getElementById("stop-view-button");
|
|
982
|
+
this.drawerToggleEl = document.getElementById("drawer-toggle");
|
|
983
|
+
this.drawerCloseEl = document.getElementById("drawer-close");
|
|
984
|
+
this.drawerBackdropEl = document.getElementById("drawer-backdrop");
|
|
985
|
+
this.sessionDrawerEl = document.getElementById("session-drawer");
|
|
986
|
+
this.activeSessionIndicatorEl = document.getElementById("active-session-indicator");
|
|
987
|
+
this.activeSessionLabelEl = document.getElementById("active-session-label");
|
|
988
|
+
this.activeSessionDotEl = document.getElementById("active-session-dot");
|
|
989
|
+
this.sessionCountBadgeEl = document.getElementById("session-count-badge");
|
|
981
990
|
|
|
982
991
|
this.stream = new LocalBrowserStream(() => this.render());
|
|
983
992
|
this.cdp = new LocalCdpConnection(() => this.render());
|
|
@@ -1007,6 +1016,30 @@ class LocalViewApp {
|
|
|
1007
1016
|
}
|
|
1008
1017
|
}
|
|
1009
1018
|
|
|
1019
|
+
openDrawer() {
|
|
1020
|
+
this.drawerOpen = true;
|
|
1021
|
+
this.sessionDrawerEl.classList.add("is-open");
|
|
1022
|
+
this.drawerBackdropEl.classList.add("is-visible");
|
|
1023
|
+
this.drawerToggleEl.setAttribute("aria-expanded", "true");
|
|
1024
|
+
this.activeSessionIndicatorEl.setAttribute("aria-expanded", "true");
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
closeDrawer() {
|
|
1028
|
+
this.drawerOpen = false;
|
|
1029
|
+
this.sessionDrawerEl.classList.remove("is-open");
|
|
1030
|
+
this.drawerBackdropEl.classList.remove("is-visible");
|
|
1031
|
+
this.drawerToggleEl.setAttribute("aria-expanded", "false");
|
|
1032
|
+
this.activeSessionIndicatorEl.setAttribute("aria-expanded", "false");
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
toggleDrawer() {
|
|
1036
|
+
if (this.drawerOpen) {
|
|
1037
|
+
this.closeDrawer();
|
|
1038
|
+
} else {
|
|
1039
|
+
this.openDrawer();
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1010
1043
|
bindUi() {
|
|
1011
1044
|
window.addEventListener("hashchange", () => {
|
|
1012
1045
|
const hashSessionId = resolveSelectedSessionIdFromHash();
|
|
@@ -1015,12 +1048,24 @@ class LocalViewApp {
|
|
|
1015
1048
|
}
|
|
1016
1049
|
});
|
|
1017
1050
|
|
|
1051
|
+
this.drawerToggleEl.addEventListener("click", () => this.toggleDrawer());
|
|
1052
|
+
this.drawerCloseEl.addEventListener("click", () => this.closeDrawer());
|
|
1053
|
+
this.drawerBackdropEl.addEventListener("click", () => this.closeDrawer());
|
|
1054
|
+
this.activeSessionIndicatorEl.addEventListener("click", () => this.toggleDrawer());
|
|
1055
|
+
|
|
1056
|
+
document.addEventListener("keydown", (event) => {
|
|
1057
|
+
if (event.key === "Escape" && this.drawerOpen) {
|
|
1058
|
+
this.closeDrawer();
|
|
1059
|
+
}
|
|
1060
|
+
});
|
|
1061
|
+
|
|
1018
1062
|
this.sessionListEl.addEventListener("click", (event) => {
|
|
1019
1063
|
const button = event.target.closest("button[data-session-id]");
|
|
1020
1064
|
if (!button) {
|
|
1021
1065
|
return;
|
|
1022
1066
|
}
|
|
1023
1067
|
this.selectSession(button.dataset.sessionId ?? null);
|
|
1068
|
+
this.closeDrawer();
|
|
1024
1069
|
});
|
|
1025
1070
|
|
|
1026
1071
|
this.tabStripEl.addEventListener("click", (event) => {
|
|
@@ -1182,10 +1227,10 @@ class LocalViewApp {
|
|
|
1182
1227
|
);
|
|
1183
1228
|
|
|
1184
1229
|
this.viewerSurfaceEl.addEventListener("keydown", (event) => {
|
|
1185
|
-
|
|
1186
|
-
if (!payload) {
|
|
1230
|
+
if (event.key === "Escape" && this.drawerOpen) {
|
|
1187
1231
|
return;
|
|
1188
1232
|
}
|
|
1233
|
+
const payload = createCdpKeyDownPayload(event);
|
|
1189
1234
|
event.preventDefault();
|
|
1190
1235
|
void this.dispatchPointerCommand("Input.dispatchKeyEvent", payload);
|
|
1191
1236
|
});
|
|
@@ -1460,6 +1505,17 @@ class LocalViewApp {
|
|
|
1460
1505
|
}
|
|
1461
1506
|
|
|
1462
1507
|
renderSessions() {
|
|
1508
|
+
const activeSession = this.sessions.find((s) => s.sessionId === this.selectedSessionId) ?? null;
|
|
1509
|
+
this.activeSessionLabelEl.textContent = activeSession
|
|
1510
|
+
? activeSession.label
|
|
1511
|
+
: "No session selected";
|
|
1512
|
+
this.activeSessionDotEl.className = activeSession
|
|
1513
|
+
? "active-session-dot is-active"
|
|
1514
|
+
: "active-session-dot";
|
|
1515
|
+
const sessionCount = this.sessions.length;
|
|
1516
|
+
this.sessionCountBadgeEl.textContent = String(sessionCount);
|
|
1517
|
+
this.sessionCountBadgeEl.hidden = sessionCount === 0;
|
|
1518
|
+
|
|
1463
1519
|
this.sessionListEl.textContent = "";
|
|
1464
1520
|
if (this.sessions.length === 0) {
|
|
1465
1521
|
const empty = document.createElement("div");
|