@reticlehq/browser 3.5.0 → 3.7.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/dist/actions/action-report.d.ts +54 -0
- package/dist/actions/action-report.js +60 -0
- package/dist/actions/actions-dom.d.ts +1 -0
- package/dist/actions/actions-dom.js +56 -43
- package/dist/actions/actions-press.d.ts +11 -4
- package/dist/actions/actions-press.js +132 -17
- package/dist/actions/actions.d.ts +1 -35
- package/dist/actions/actions.js +32 -65
- package/dist/actions/appeared-text.js +3 -0
- package/dist/actions/danger-context.d.ts +2 -0
- package/dist/actions/danger-context.js +29 -3
- package/dist/actions/value-input.d.ts +1 -0
- package/dist/actions/value-input.js +11 -0
- package/dist/commands/commands.js +4 -0
- package/dist/connect-options.d.ts +1 -0
- package/dist/dom/a11y.js +264 -14
- package/dist/dom/addressing/coverage-markers.d.ts +6 -0
- package/dist/dom/addressing/coverage-markers.js +13 -0
- package/dist/dom/addressing/refs.js +2 -1
- package/dist/dom/addressing/testid-attr.d.ts +4 -0
- package/dist/dom/addressing/testid-attr.js +14 -0
- package/dist/dom/dom-ignore.d.ts +2 -0
- package/dist/dom/dom-ignore.js +15 -2
- package/dist/dom/query.d.ts +2 -1
- package/dist/dom/query.js +116 -27
- package/dist/dom/render-page.d.ts +12 -0
- package/dist/dom/render-page.js +135 -0
- package/dist/dom/snapshot.js +56 -7
- package/dist/observers/departure.js +51 -9
- package/dist/observers/dom.js +35 -18
- package/dist/observers/field.js +5 -21
- package/dist/observers/health.js +63 -2
- package/dist/observers/network-stream.d.ts +1 -1
- package/dist/observers/network-stream.js +3 -3
- package/dist/observers/network.js +57 -8
- package/dist/observers/perf.js +53 -1
- package/dist/observers/route.js +6 -5
- package/dist/observers/storage.js +6 -1
- package/dist/presenter/carousel/carousel.d.ts +5 -2
- package/dist/presenter/carousel/carousel.js +30 -8
- package/dist/presenter/carousel/panel-slides.d.ts +3 -4
- package/dist/presenter/carousel/panel-slides.js +48 -9
- package/dist/presenter/carousel/talk-card.d.ts +1 -1
- package/dist/presenter/chrome/log-kinds.d.ts +5 -0
- package/dist/presenter/chrome/log-kinds.js +1 -0
- package/dist/presenter/chrome/log-memory.d.ts +13 -0
- package/dist/presenter/chrome/log-memory.js +39 -0
- package/dist/presenter/chrome/presenter-hud-chrome.d.ts +1 -0
- package/dist/presenter/chrome/presenter-hud-chrome.js +7 -1
- package/dist/presenter/chrome/presenter-log.d.ts +12 -4
- package/dist/presenter/chrome/presenter-log.js +100 -10
- package/dist/presenter/chrome/presenter-morph.d.ts +1 -0
- package/dist/presenter/chrome/presenter-morph.js +34 -0
- package/dist/presenter/chrome/presenter-report-copy.d.ts +28 -5
- package/dist/presenter/chrome/presenter-report-copy.js +40 -5
- package/dist/presenter/hud-telemetry.js +83 -3
- package/dist/presenter/icons/presenter-heroicons-data.d.ts +1 -0
- package/dist/presenter/icons/presenter-heroicons-data.js +4 -3
- package/dist/presenter/icons/presenter-icons.d.ts +2 -0
- package/dist/presenter/icons/presenter-icons.js +2 -0
- package/dist/presenter/presenter-account-styles.js +3 -3
- package/dist/presenter/presenter-account.d.ts +31 -8
- package/dist/presenter/presenter-account.js +105 -15
- package/dist/presenter/presenter-agent-link.d.ts +9 -0
- package/dist/presenter/presenter-agent-link.js +62 -0
- package/dist/presenter/presenter-chat-views.d.ts +43 -0
- package/dist/presenter/presenter-chat-views.js +622 -0
- package/dist/presenter/presenter-config.d.ts +5 -2
- package/dist/presenter/presenter-config.js +5 -3
- package/dist/presenter/presenter-controls.d.ts +3 -2
- package/dist/presenter/presenter-controls.js +163 -61
- package/dist/presenter/presenter-design-tokens.d.ts +1 -0
- package/dist/presenter/presenter-design-tokens.js +34 -0
- package/dist/presenter/presenter-dock-layout.js +1 -1
- package/dist/presenter/presenter-frame.d.ts +12 -0
- package/dist/presenter/presenter-frame.js +187 -0
- package/dist/presenter/presenter-harness-row.d.ts +67 -0
- package/dist/presenter/presenter-harness-row.js +209 -0
- package/dist/presenter/presenter-personas.d.ts +35 -0
- package/dist/presenter/presenter-personas.js +95 -0
- package/dist/presenter/presenter-plan.d.ts +10 -0
- package/dist/presenter/presenter-plan.js +186 -0
- package/dist/presenter/presenter-report-styles.js +46 -21
- package/dist/presenter/presenter-report.d.ts +2 -1
- package/dist/presenter/presenter-report.js +123 -20
- package/dist/presenter/presenter-settings-styles.js +18 -4
- package/dist/presenter/presenter-settings.d.ts +8 -2
- package/dist/presenter/presenter-settings.js +134 -33
- package/dist/presenter/presenter-shell-styles.js +48 -42
- package/dist/presenter/presenter-shell.d.ts +17 -4
- package/dist/presenter/presenter-shell.js +139 -79
- package/dist/presenter/presenter-styles.js +9 -3
- package/dist/presenter/presenter-workspace.js +10 -3
- package/dist/presenter/presenter.d.ts +6 -4
- package/dist/presenter/presenter.js +171 -22
- package/dist/presenter/tour/tour.d.ts +4 -1
- package/dist/presenter/tour/tour.js +6 -4
- package/dist/recorder/recorder.js +2 -2
- package/dist/registry/auto-testids.js +3 -4
- package/dist/registry/declared-platform.js +4 -0
- package/dist/reticle-inject.js +938 -494
- package/dist/reticle.d.ts +10 -1
- package/dist/reticle.js +109 -11
- package/dist/review/annotator-styles.d.ts +1 -1
- package/dist/review/annotator.d.ts +7 -0
- package/dist/review/annotator.js +20 -2
- package/dist/review/mark-anchor.js +2 -2
- package/dist/session-continuity.js +2 -1
- package/dist/storage-keys.d.ts +15 -0
- package/dist/storage-keys.js +21 -0
- package/dist/transport/transport.js +5 -3
- package/dist/transport/unreachable-message.d.ts +1 -1
- package/dist/transport/unreachable-message.js +3 -5
- package/package.json +3 -2
- package/dist/presenter/carousel/offer-card.d.ts +0 -21
- package/dist/presenter/carousel/offer-card.js +0 -55
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ReticleStorageKey } from '../storage-keys.js';
|
|
1
2
|
export const BorderMode = { SESSION: 'session', BUSY: 'busy' };
|
|
2
3
|
export const DEFAULT_BORDER_MODE = BorderMode.SESSION;
|
|
3
4
|
export const DATA_BUSY = 'data-busy';
|
|
@@ -24,6 +25,7 @@ export const ACT_STRIP = {
|
|
|
24
25
|
STOPPED_PREFIX: 'stopped · ',
|
|
25
26
|
NOW: 'now',
|
|
26
27
|
SINCE_LAST: ' since last action',
|
|
28
|
+
harnessTesting: (steps) => `Testing · Harness · ${String(steps)} step${1 === steps ? '' : 's'}`,
|
|
27
29
|
};
|
|
28
30
|
export const IDLE_END_MS = 300_000;
|
|
29
31
|
export const IDLE_END_MIN_MS = 5_000;
|
|
@@ -60,8 +62,8 @@ export const SETTINGS_BTN_ATTR = 'data-reticle-settings-btn';
|
|
|
60
62
|
export const SETTINGS_PANEL_ATTR = 'data-reticle-settings-panel';
|
|
61
63
|
export const SETTINGS_CLOSE_ATTR = 'data-reticle-settings-close';
|
|
62
64
|
export const SETTING_KEY_ATTR = 'data-reticle-setting';
|
|
63
|
-
export const SETTINGS_STORAGE_KEY =
|
|
64
|
-
export const MINIMISED_STORAGE_KEY =
|
|
65
|
+
export const SETTINGS_STORAGE_KEY = ReticleStorageKey.PRESENTER_SETTINGS;
|
|
66
|
+
export const MINIMISED_STORAGE_KEY = ReticleStorageKey.PRESENTER_MINIMISED;
|
|
65
67
|
export const AMBIENT_GLOW_ATTR = 'data-reticle-ambient-glow';
|
|
66
68
|
export const LIVENESS_ATTR = 'data-reticle-live';
|
|
67
69
|
export const BLOCK_ATTR = 'data-reticle-block';
|
|
@@ -74,6 +76,6 @@ export const HUD_POS_X_VAR = '--reticle-hud-x';
|
|
|
74
76
|
export const HUD_POS_Y_VAR = '--reticle-hud-y';
|
|
75
77
|
export const HUD_DRAG_THRESHOLD_PX = 4;
|
|
76
78
|
export const HUD_DOCK_MARGIN_PX = 8;
|
|
77
|
-
export const HUD_DRAG_IGNORE_SEL = '[data-reticle-pause], [data-reticle-annotate-btn], [data-reticle-markers-btn], [data-reticle-clear-marks], [data-reticle-copy-marks], [data-reticle-end], [data-reticle-min-btn], [data-reticle-settings-btn], [data-reticle-settings-panel], [data-reticle-report-btn], [data-reticle-report-panel], [data-reticle-chat-panel], [data-reticle-chat-toggle], [data-reticle-workspace-btn], [data-reticle-workspace-menu], [data-reticle-copy], [data-reticle-export], input, textarea, select, a, .reticle-head-ctl, [data-reticle-tally], .reticle-maxhint';
|
|
79
|
+
export const HUD_DRAG_IGNORE_SEL = '[data-reticle-pause], [data-reticle-annotate-btn], [data-reticle-markers-btn], [data-reticle-clear-marks], [data-reticle-copy-marks], [data-reticle-end], [data-reticle-min-btn], [data-reticle-settings-btn], [data-reticle-settings-panel], [data-reticle-report-btn], [data-reticle-report-panel], [data-reticle-chat-panel], [data-reticle-chat-toggle], [data-reticle-workspace-btn], [data-reticle-workspace-menu], [data-reticle-copy], [data-reticle-export], .reticle-toolbar-chrome button, .reticle-toolbar-actions button, input, textarea, select, a, .reticle-head-ctl, [data-reticle-tally], .reticle-maxhint';
|
|
78
80
|
export const THROTTLED_ATTR = 'data-reticle-throttled';
|
|
79
81
|
export const Z_HUD_TOOLTIP = 100;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { HumanControlKind, PresenterTone, SessionState } from '@reticlehq/core';
|
|
2
2
|
export type { ControlIntent, ControlHandler } from './presenter-config.js';
|
|
3
3
|
export declare const ENDED_FADE_MS = 4000;
|
|
4
|
+
export declare function flowTitle(name: string): string;
|
|
4
5
|
export declare const CONTROLS_CSS: string;
|
|
5
|
-
export declare const
|
|
6
|
+
export declare const CONTROLS_STATUS_HTML: string;
|
|
6
7
|
export declare const CONTROLS_BANNER_HTML = "<div data-reticle-banner class=\"reticle-banner\">Session ended</div>";
|
|
7
8
|
export declare const CONTROLS_MARKS_HTML: string;
|
|
8
|
-
export declare const CONTROLS_FLOWS_HTML = "<div data-reticle-flows class=\"reticle-flows\"><span class=\"reticle-flows-cap\">Replay a flow</span></div>";
|
|
9
9
|
export declare const CONTROLS_FOOT_HTML: string;
|
|
10
10
|
interface ControlPanelHost {
|
|
11
11
|
emit: (kind: HumanControlKind, text?: string) => void;
|
|
@@ -21,6 +21,7 @@ export declare class ControlPanel {
|
|
|
21
21
|
get state(): SessionState;
|
|
22
22
|
mount(root: HTMLElement, glow: HTMLElement | undefined): void;
|
|
23
23
|
teardown(): void;
|
|
24
|
+
setFlowProgress(args: Record<string, unknown>): void;
|
|
24
25
|
setFlows(flows: unknown): void;
|
|
25
26
|
refilterFlows(): void;
|
|
26
27
|
setState(state: SessionState, text?: string, tone?: PresenterTone): void;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readTestId, testIdSelector } from '../dom/addressing/testid-attr.js';
|
|
2
|
+
import { FlowProgressStatus, HumanControlKind, PresenterTone, SessionState, } from '@reticlehq/core';
|
|
2
3
|
import { nativeSetTimeout, nativeClearTimeout } from '../timers/native/native-timers.js';
|
|
3
|
-
import {
|
|
4
|
-
import { PresenterIcon, PRESENTER_ICON_SIZE, hiIcon, hiIconHtml
|
|
4
|
+
import { COPY_MARKS_ATTR, MARKS_ROW_ATTR } from './presenter-config.js';
|
|
5
|
+
import { PresenterIcon, PRESENTER_ICON_SIZE, hiIcon, hiIconHtml } from './icons/presenter-icons.js';
|
|
5
6
|
import { getPresenterSettings } from './presenter-settings.js';
|
|
6
7
|
import { mountWorkspaceSelector, workspaceRowHtml } from './presenter-workspace.js';
|
|
8
|
+
import { CHAT_VIEWS_HTML } from './presenter-chat-views.js';
|
|
7
9
|
const DATA_RETICLE_STATE = 'data-reticle-state';
|
|
8
10
|
const DATA_RETICLE_TONE = 'data-reticle-tone';
|
|
9
11
|
const DATA_ON = 'data-on';
|
|
@@ -18,25 +20,55 @@ const PAUSED_BADGE_TEXT = 'PAUSED';
|
|
|
18
20
|
const ENDED_BANNER_TEXT = 'Session ended';
|
|
19
21
|
const COPY_LABEL = 'Copy run';
|
|
20
22
|
const EXPORT_LABEL = 'Export';
|
|
21
|
-
const
|
|
23
|
+
const PROGRESS_LINGER_MS = 6000;
|
|
24
|
+
const PROGRESS_GLYPH = {
|
|
25
|
+
[FlowProgressStatus.PLAYING]: '⏵',
|
|
26
|
+
[FlowProgressStatus.PASSED]: '✓',
|
|
27
|
+
[FlowProgressStatus.FAILED]: '✗',
|
|
28
|
+
};
|
|
29
|
+
function parseFlowProgress(args) {
|
|
30
|
+
const { name, done, total, status } = args;
|
|
31
|
+
if ('string' !== typeof name || 'number' !== typeof done || 'number' !== typeof total)
|
|
32
|
+
return undefined;
|
|
33
|
+
if (!Object.values(FlowProgressStatus).includes(status))
|
|
34
|
+
return undefined;
|
|
35
|
+
return { name, done, total, status: status };
|
|
36
|
+
}
|
|
22
37
|
const COPIED_TEXT = 'Copied ✓';
|
|
23
38
|
const RUN_FILENAME = 'reticle-run.json';
|
|
24
39
|
export const ENDED_FADE_MS = 4000;
|
|
40
|
+
const FLOW_TEXT = {
|
|
41
|
+
REPLAYABLE: 'Replay without an agent',
|
|
42
|
+
ELSEWHERE: 'Starts on another page',
|
|
43
|
+
EMPTY_TITLE: 'No saved flows yet',
|
|
44
|
+
EMPTY_HINT: 'Every journey your agent verifies is saved here, ready to replay in one click.',
|
|
45
|
+
};
|
|
46
|
+
export function flowTitle(name) {
|
|
47
|
+
const words = name.replace(/[-_]+/g, ' ').trim();
|
|
48
|
+
return 0 === words.length ? name : words.charAt(0).toUpperCase() + words.slice(1);
|
|
49
|
+
}
|
|
25
50
|
export const CONTROLS_CSS = `
|
|
26
|
-
[data-reticle-chat-panel] [data-reticle-foot]{flex:none;padding:
|
|
51
|
+
[data-reticle-chat-panel] [data-reticle-foot]{flex:none;padding:6px 10px 8px;border-top:1px solid rgba(255,255,255,.07);
|
|
27
52
|
background:linear-gradient(180deg,rgba(0,0,0,.35) 0%,rgba(0,0,0,.55) 100%);pointer-events:auto;}
|
|
53
|
+
[data-reticle-chat-panel] .reticle-foot-workspace-row{display:flex;flex-wrap:wrap;align-items:center;min-width:0;}
|
|
28
54
|
[data-reticle-chat-panel] .reticle-hud-log-well{margin:0 0 4px;}
|
|
29
55
|
[data-reticle-chat-panel] .reticle-workspace-wrap{position:relative;align-self:flex-start;max-width:100%;}
|
|
56
|
+
[data-reticle-chat-panel] .reticle-workspace-wrap[hidden]{display:none;}
|
|
30
57
|
[data-reticle-chat-panel] .reticle-workspace{
|
|
31
58
|
display:inline-flex;align-items:center;gap:5px;max-width:100%;padding:3px 8px 3px 6px;border-radius:999px;cursor:pointer;
|
|
32
59
|
border:1px solid rgba(255,255,255,.1);background:rgba(255,255,255,.04);color:rgba(255,255,255,.78);
|
|
33
60
|
font:inherit;font-size:11px;font-weight:500;line-height:1.2;
|
|
34
61
|
box-shadow:inset 0 1px 0 rgba(255,255,255,.05);transition:background .15s,border-color .15s,color .15s;}
|
|
62
|
+
[data-reticle-chat-panel] .reticle-workspace-k{color:var(--reticle-hud-text-faint);font-weight:400;}
|
|
35
63
|
[data-reticle-chat-panel] .reticle-workspace:hover{background:rgba(255,255,255,.07);border-color:rgba(255,255,255,.14);color:#fff;}
|
|
36
64
|
[data-reticle-chat-panel] .reticle-workspace[aria-expanded="true"]{background:rgba(255,255,255,.08);border-color:rgba(255,255,255,.16);color:#fff;}
|
|
37
65
|
[data-reticle-chat-panel] .reticle-workspace-icon,
|
|
38
66
|
[data-reticle-chat-panel] .reticle-workspace-caret{display:inline-flex;align-items:center;opacity:.72;flex:none;}
|
|
39
67
|
[data-reticle-chat-panel] .reticle-workspace-name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:min(200px,calc(100vw - 120px));}
|
|
68
|
+
@media (max-width:480px){
|
|
69
|
+
[data-reticle-chat-panel] .reticle-workspace-wrap{flex:none;}
|
|
70
|
+
[data-reticle-chat-panel] .reticle-workspace-name{max-width:88px;}
|
|
71
|
+
}
|
|
40
72
|
[data-reticle-chat-panel] .reticle-workspace[aria-expanded="true"] .reticle-workspace-caret{transform:rotate(180deg);}
|
|
41
73
|
[data-reticle-chat-panel] .reticle-workspace-caret{transition:transform .18s ease;}
|
|
42
74
|
[data-reticle-chat-panel] .reticle-workspace-menu{
|
|
@@ -51,7 +83,7 @@ export const CONTROLS_CSS = `
|
|
|
51
83
|
[data-reticle-chat-panel] .reticle-workspace-menu-head{
|
|
52
84
|
display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:8px;}
|
|
53
85
|
[data-reticle-chat-panel] .reticle-workspace-menu-title{
|
|
54
|
-
color:rgba(255,255,255,.42);font-size:
|
|
86
|
+
color:rgba(255,255,255,.42);font-size:11px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;}
|
|
55
87
|
[data-reticle-chat-panel] .reticle-workspace-copy{
|
|
56
88
|
display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;padding:0;border:none;border-radius:6px;
|
|
57
89
|
background:rgba(255,255,255,.06);color:rgba(255,255,255,.7);cursor:pointer;line-height:0;transition:background .12s,color .12s;}
|
|
@@ -65,9 +97,9 @@ export const CONTROLS_CSS = `
|
|
|
65
97
|
[data-reticle-chat-panel] .reticle-workspace-menu-row{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;padding:4px 0;}
|
|
66
98
|
[data-reticle-chat-panel] .reticle-workspace-menu-k{flex:none;color:rgba(255,255,255,.42);}
|
|
67
99
|
[data-reticle-chat-panel] .reticle-workspace-menu-v{min-width:0;text-align:right;color:rgba(255,255,255,.9);font-weight:500;word-break:break-all;}
|
|
68
|
-
[data-reticle-chat-panel] .reticle-banner{display:none;flex:none;align-items:center;gap:8px;padding:
|
|
69
|
-
font-size:12px;font-weight:
|
|
70
|
-
[data-reticle-overlay][data-reticle-state="ended"] [data-reticle-chat-panel] .reticle-banner{display:
|
|
100
|
+
[data-reticle-chat-panel] .reticle-banner{display:none;flex:none;align-items:center;gap:8px;min-height:38px;box-sizing:border-box;padding:8px 14px;
|
|
101
|
+
color:var(--reticle-hud-text);font-size:12px;font-weight:600;border-bottom:1px solid var(--reticle-hud-border);background:var(--reticle-hud-inset);line-height:1.35;}
|
|
102
|
+
[data-reticle-overlay][data-reticle-state="ended"] [data-reticle-chat-panel] .reticle-banner{display:flex;}
|
|
71
103
|
[data-reticle-overlay][data-reticle-state="paused"] [data-reticle-glow][data-on="1"]{
|
|
72
104
|
box-shadow:inset 0 0 0 2px rgba(255,255,255,.2);}
|
|
73
105
|
[data-reticle-overlay][data-reticle-state="ended"] [data-reticle-glow][data-on="1"]{
|
|
@@ -87,13 +119,19 @@ export const CONTROLS_CSS = `
|
|
|
87
119
|
[data-reticle-overlay][data-reticle-tone="ask"] [data-reticle-glow][data-on="1"],
|
|
88
120
|
[data-reticle-overlay][data-reticle-tone="warn"] [data-reticle-glow][data-on="1"]{
|
|
89
121
|
box-shadow:inset 0 0 0 2px rgba(255,255,255,.22);}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
[data-reticle-chat-panel] .reticle-
|
|
94
|
-
|
|
95
|
-
[data-reticle-chat-panel] .reticle-
|
|
96
|
-
|
|
122
|
+
/* A replay the person started: the chip becomes a player, its bar filling step by step. */
|
|
123
|
+
[data-reticle-chat-panel] :is(.reticle-flow,.reticle-flow-row)[data-state]{position:relative;overflow:hidden;
|
|
124
|
+
border-color:color-mix(in srgb,var(--reticle-c-active) 55%,transparent);color:var(--reticle-fg);}
|
|
125
|
+
[data-reticle-chat-panel] :is(.reticle-flow,.reticle-flow-row)[data-state]::after{content:"";position:absolute;left:0;bottom:0;height:2px;
|
|
126
|
+
width:var(--reticle-flow-progress,4%);background:var(--reticle-c-active);transition:width .25s var(--reticle-hud-ease,ease);}
|
|
127
|
+
[data-reticle-chat-panel] :is(.reticle-flow,.reticle-flow-row)[data-state="playing"]::after{animation:reticle-flow-pulse 1.2s ease-in-out infinite;}
|
|
128
|
+
@keyframes reticle-flow-pulse{50%{opacity:.55}}
|
|
129
|
+
[data-reticle-chat-panel] :is(.reticle-flow,.reticle-flow-row)[data-state="passed"]::after{background:#4ade80;}
|
|
130
|
+
[data-reticle-chat-panel] :is(.reticle-flow,.reticle-flow-row)[data-state="failed"]::after{background:#f87171;}
|
|
131
|
+
[data-reticle-chat-panel] .reticle-all-flows{flex:1;min-height:0;overflow-y:auto;padding:8px 12px;display:flex;flex-direction:column;align-items:stretch;gap:5px;}
|
|
132
|
+
[data-reticle-chat-panel] .reticle-all-flows .reticle-flow{width:100%;height:auto;min-height:32px;text-align:left;justify-content:flex-start;}
|
|
133
|
+
[data-reticle-chat-panel] .reticle-all-flows .reticle-flow:disabled{opacity:.45;cursor:not-allowed;}
|
|
134
|
+
[data-reticle-chat-panel] .reticle-flows-empty{padding:25px 8px;color:var(--reticle-faint);font-size:11px;text-align:center;}
|
|
97
135
|
[data-reticle-chat-panel] .reticle-flow{pointer-events:auto;cursor:pointer;display:inline-flex;align-items:center;gap:5px;height:24px;padding:0 10px;
|
|
98
136
|
border-radius:7px;border:1px solid var(--reticle-line);background:rgba(255,255,255,.04);color:var(--reticle-muted);
|
|
99
137
|
font-family:var(--reticle-font);font-size:11px;font-weight:500;transition:background .15s,color .15s,border-color .15s,transform .1s;}
|
|
@@ -122,35 +160,12 @@ function paintPauseBtn(btn, paused) {
|
|
|
122
160
|
btn.classList.toggle('reticle-tb-btn--primary', paused);
|
|
123
161
|
btn.setAttribute('data-active', paused ? '1' : '0');
|
|
124
162
|
}
|
|
125
|
-
const CHAT_LABEL = 'Agent chat';
|
|
126
|
-
const MARKERS_LABEL = 'Hide markers';
|
|
127
|
-
const CLEAR_MARKS_LABEL = 'Clear all';
|
|
128
163
|
const COPY_MARKS_LABEL = 'Copy for your agent';
|
|
129
164
|
const TB = PRESENTER_ICON_SIZE.TOOLBAR;
|
|
130
|
-
|
|
131
|
-
const shortcut = kbd === undefined ? '' : `<span class="reticle-tb-kbd">${kbd}</span>`;
|
|
132
|
-
return `<div class="reticle-tb-wrap">${btn}<span class="reticle-tb-tip">${tip}${shortcut}</span></div>`;
|
|
133
|
-
}
|
|
134
|
-
function pauseToolbarHtml() {
|
|
135
|
-
const btn = `<button type="button" data-reticle-pause class="reticle-tb-btn" title="${CONTROL_LABEL.PAUSE}" aria-label="${CONTROL_LABEL.PAUSE}">${hiIconHtml(PresenterIcon.PAUSE, TB)}</button>`;
|
|
136
|
-
const badge = `<span data-reticle-badge class="reticle-pause-badge">${PAUSED_BADGE_TEXT}</span>`;
|
|
137
|
-
const tip = `<span class="reticle-tb-tip">${CONTROL_LABEL.PAUSE}</span>`;
|
|
138
|
-
return `<div class="reticle-tb-wrap reticle-tb-wrap--pause">${btn}${badge}${tip}</div>`;
|
|
139
|
-
}
|
|
140
|
-
export const CONTROLS_TOOLBAR_HTML = [
|
|
141
|
-
pauseToolbarHtml(),
|
|
142
|
-
tbWrap(`<button type="button" ${CHAT_TOGGLE_ATTR} class="reticle-tb-btn reticle-tb-btn--toggle" title="${CHAT_LABEL}" aria-label="${CHAT_LABEL}" aria-pressed="false" data-active="0">${hiToggleIconHtml(PresenterIcon.MESSAGE, TB)}</button>`, CHAT_LABEL),
|
|
143
|
-
tbWrap(`<button type="button" ${MARKERS_BTN_ATTR} class="reticle-tb-btn reticle-tb-btn--toggle" title="${MARKERS_LABEL}" aria-label="${MARKERS_LABEL}" aria-pressed="false" data-active="0" disabled>${hiToggleIconHtml(PresenterIcon.VIEW, TB)}</button>`, MARKERS_LABEL, 'H'),
|
|
144
|
-
tbWrap(`<button type="button" data-reticle-end class="reticle-tb-btn" title="${CONTROL_LABEL.END}" aria-label="${CONTROL_LABEL.END}">${hiIconHtml(PresenterIcon.STOP, TB)}</button>`, CONTROL_LABEL.END),
|
|
145
|
-
tbWrap(`<button type="button" ${CLEAR_MARKS_ATTR} class="reticle-tb-btn" title="${CLEAR_MARKS_LABEL}" aria-label="${CLEAR_MARKS_LABEL}" data-danger disabled>${hiIconHtml(PresenterIcon.TRASH, TB)}</button>`, CLEAR_MARKS_LABEL, 'X'),
|
|
146
|
-
`<button type="button" data-reticle-copy class="reticle-tb-btn reticle-tb-btn--export" title="${COPY_LABEL}" aria-label="${COPY_LABEL}" hidden>${hiIconHtml(PresenterIcon.COPY, TB)}</button>`,
|
|
147
|
-
`<button type="button" data-reticle-export class="reticle-tb-btn reticle-tb-btn--export" title="${EXPORT_LABEL}" aria-label="${EXPORT_LABEL}" hidden>${hiIconHtml(PresenterIcon.DOWNLOAD, TB)}</button>`,
|
|
148
|
-
'<span data-reticle-export-msg class="reticle-export-msg" aria-live="polite"></span>',
|
|
149
|
-
].join('');
|
|
165
|
+
export const CONTROLS_STATUS_HTML = `<button type="button" data-reticle-pause class="reticle-status-btn" title="${CONTROL_LABEL.PAUSE}" aria-label="${CONTROL_LABEL.PAUSE}">${hiIconHtml(PresenterIcon.PAUSE, TB)}</button><span data-reticle-badge class="reticle-pause-badge">${PAUSED_BADGE_TEXT}</span><button type="button" data-reticle-end class="reticle-status-btn reticle-status-stop" title="${CONTROL_LABEL.END}" aria-label="${CONTROL_LABEL.END}">${hiIconHtml(PresenterIcon.STOP, TB)}</button><button type="button" data-reticle-copy class="reticle-status-btn" title="${COPY_LABEL}" aria-label="${COPY_LABEL}" hidden>${hiIconHtml(PresenterIcon.COPY, TB)}</button><button type="button" data-reticle-export class="reticle-status-btn" title="${EXPORT_LABEL}" aria-label="${EXPORT_LABEL}" hidden>${hiIconHtml(PresenterIcon.DOWNLOAD, TB)}</button><span data-reticle-export-msg class="reticle-export-msg" aria-live="polite"></span>`;
|
|
150
166
|
export const CONTROLS_BANNER_HTML = `<div data-reticle-banner class="reticle-banner">${ENDED_BANNER_TEXT}</div>`;
|
|
151
167
|
export const CONTROLS_MARKS_HTML = `<div ${MARKS_ROW_ATTR} class="reticle-marks-row" hidden><span data-reticle-marks-text class="reticle-marks-text"></span><button type="button" ${COPY_MARKS_ATTR} class="reticle-marks-copy" title="${COPY_MARKS_LABEL}">${hiIconHtml(PresenterIcon.COPY, PRESENTER_ICON_SIZE.HELP)}<span>${COPY_MARKS_LABEL}</span></button></div>`;
|
|
152
|
-
export const
|
|
153
|
-
export const CONTROLS_FOOT_HTML = `<div data-reticle-foot><div class="reticle-foot-stack">${workspaceRowHtml()}</div></div>`;
|
|
168
|
+
export const CONTROLS_FOOT_HTML = `<div data-reticle-foot><div class="reticle-foot-stack">${CHAT_VIEWS_HTML}<div class="reticle-foot-workspace-row">${workspaceRowHtml()}</div></div></div>`;
|
|
154
169
|
function queryControlRefs(root) {
|
|
155
170
|
return {
|
|
156
171
|
pauseBtn: root.querySelector('[data-reticle-pause]') ?? undefined,
|
|
@@ -159,7 +174,7 @@ function queryControlRefs(root) {
|
|
|
159
174
|
copyBtn: root.querySelector('[data-reticle-copy]') ?? undefined,
|
|
160
175
|
exportBtn: root.querySelector('[data-reticle-export]') ?? undefined,
|
|
161
176
|
exportMsg: root.querySelector('[data-reticle-export-msg]') ?? undefined,
|
|
162
|
-
|
|
177
|
+
allFlows: root.querySelector('[data-reticle-all-flows]') ?? undefined,
|
|
163
178
|
};
|
|
164
179
|
}
|
|
165
180
|
export class ControlPanel {
|
|
@@ -170,13 +185,15 @@ export class ControlPanel {
|
|
|
170
185
|
copyBtn: undefined,
|
|
171
186
|
exportBtn: undefined,
|
|
172
187
|
exportMsg: undefined,
|
|
173
|
-
|
|
188
|
+
allFlows: undefined,
|
|
174
189
|
};
|
|
175
190
|
#state = SessionState.ACTIVE;
|
|
176
191
|
#fadeTimer;
|
|
177
192
|
#root;
|
|
178
193
|
#glow;
|
|
179
194
|
#flowItems = [];
|
|
195
|
+
#progress;
|
|
196
|
+
#progressTimer;
|
|
180
197
|
#workspaceTeardown;
|
|
181
198
|
#listeners;
|
|
182
199
|
#host;
|
|
@@ -198,18 +215,23 @@ export class ControlPanel {
|
|
|
198
215
|
}
|
|
199
216
|
this.#refs.pauseBtn?.addEventListener('click', () => this.#onPauseToggle(), { signal });
|
|
200
217
|
this.#refs.endBtn?.addEventListener('click', () => this.#onEnd(), { signal });
|
|
201
|
-
|
|
218
|
+
const onReplay = (e) => {
|
|
202
219
|
const target = e.target;
|
|
203
220
|
if (!(target instanceof HTMLElement))
|
|
204
221
|
return;
|
|
205
|
-
const
|
|
206
|
-
if (
|
|
222
|
+
const button = target.closest('[data-reticle-replay]');
|
|
223
|
+
if (null === button || button.disabled)
|
|
224
|
+
return;
|
|
225
|
+
const name = button.getAttribute('data-reticle-replay');
|
|
226
|
+
if (name !== null && name.length > 0) {
|
|
207
227
|
this.#host.emit(HumanControlKind.REPLAY, name);
|
|
208
228
|
}
|
|
209
|
-
}
|
|
229
|
+
};
|
|
230
|
+
this.#refs.allFlows?.addEventListener('click', onReplay, { signal });
|
|
210
231
|
this.#refs.copyBtn?.addEventListener('click', () => this.#onCopy(), { signal });
|
|
211
232
|
this.#refs.exportBtn?.addEventListener('click', () => this.#onExport(), { signal });
|
|
212
233
|
this.#workspaceTeardown = mountWorkspaceSelector(root);
|
|
234
|
+
this.#renderFlows();
|
|
213
235
|
this.setState(SessionState.ACTIVE);
|
|
214
236
|
}
|
|
215
237
|
#runJson() {
|
|
@@ -264,6 +286,50 @@ export class ControlPanel {
|
|
|
264
286
|
this.#host.emit(HumanControlKind.END);
|
|
265
287
|
this.setState(SessionState.ENDED);
|
|
266
288
|
}
|
|
289
|
+
setFlowProgress(args) {
|
|
290
|
+
const progress = parseFlowProgress(args);
|
|
291
|
+
if (progress === undefined)
|
|
292
|
+
return;
|
|
293
|
+
this.#progress = progress;
|
|
294
|
+
if (this.#progressTimer !== undefined)
|
|
295
|
+
nativeClearTimeout(this.#progressTimer);
|
|
296
|
+
this.#progressTimer =
|
|
297
|
+
FlowProgressStatus.PLAYING === progress.status
|
|
298
|
+
? undefined
|
|
299
|
+
: nativeSetTimeout(() => {
|
|
300
|
+
this.#progress = undefined;
|
|
301
|
+
this.#paintProgress();
|
|
302
|
+
}, PROGRESS_LINGER_MS);
|
|
303
|
+
this.#paintProgress();
|
|
304
|
+
}
|
|
305
|
+
#paintProgress() {
|
|
306
|
+
const progress = this.#progress;
|
|
307
|
+
{
|
|
308
|
+
for (const btn of this.#refs.allFlows?.querySelectorAll('[data-reticle-replay]') ?? []) {
|
|
309
|
+
const name = btn.getAttribute('data-reticle-replay') ?? '';
|
|
310
|
+
const mine = progress !== undefined && progress.name === name;
|
|
311
|
+
if (!mine) {
|
|
312
|
+
btn.removeAttribute('data-state');
|
|
313
|
+
btn.style.removeProperty('--reticle-flow-progress');
|
|
314
|
+
if (btn.classList.contains('reticle-flow'))
|
|
315
|
+
btn.textContent = `▶ ${name}`;
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
const share = 0 < progress.total ? Math.round((100 * progress.done) / progress.total) : 4;
|
|
319
|
+
btn.setAttribute('data-state', progress.status);
|
|
320
|
+
btn.style.setProperty('--reticle-flow-progress', `${String(Math.max(4, share))}%`);
|
|
321
|
+
const glyph = PROGRESS_GLYPH[progress.status];
|
|
322
|
+
if (btn.classList.contains('reticle-flow'))
|
|
323
|
+
btn.textContent = `${glyph} ${name}`;
|
|
324
|
+
const play = btn.querySelector('.reticle-flow-play');
|
|
325
|
+
if (play !== null)
|
|
326
|
+
play.textContent = glyph;
|
|
327
|
+
const meta = btn.querySelector('.reticle-flow-meta');
|
|
328
|
+
if (meta !== null && 0 < progress.total)
|
|
329
|
+
meta.textContent = `Step ${String(progress.done)} of ${String(progress.total)}`;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
267
333
|
setFlows(flows) {
|
|
268
334
|
const list = Array.isArray(flows) ? flows : [];
|
|
269
335
|
this.#flowItems = list
|
|
@@ -276,7 +342,12 @@ export class ControlPanel {
|
|
|
276
342
|
if (typeof name !== 'string' || 0 === name.length)
|
|
277
343
|
return null;
|
|
278
344
|
const start = rec['start'];
|
|
279
|
-
|
|
345
|
+
const createdAt = rec['createdAt'];
|
|
346
|
+
return {
|
|
347
|
+
name,
|
|
348
|
+
...('string' === typeof start && start.length > 0 ? { start } : {}),
|
|
349
|
+
...('number' === typeof createdAt && Number.isFinite(createdAt) ? { createdAt } : {}),
|
|
350
|
+
};
|
|
280
351
|
}
|
|
281
352
|
return null;
|
|
282
353
|
})
|
|
@@ -287,22 +358,53 @@ export class ControlPanel {
|
|
|
287
358
|
this.#renderFlows();
|
|
288
359
|
}
|
|
289
360
|
#renderFlows() {
|
|
290
|
-
const
|
|
291
|
-
if (
|
|
361
|
+
const all = this.#refs.allFlows;
|
|
362
|
+
if (all === undefined)
|
|
292
363
|
return;
|
|
293
|
-
const doc =
|
|
294
|
-
const testids = new Set(Array.from(doc.querySelectorAll(
|
|
295
|
-
const
|
|
296
|
-
|
|
297
|
-
|
|
364
|
+
const doc = all.ownerDocument;
|
|
365
|
+
const testids = new Set(Array.from(doc.querySelectorAll(testIdSelector())).map((n) => readTestId(n)));
|
|
366
|
+
const playable = (f) => f.start === undefined || testids.has(f.start);
|
|
367
|
+
all.replaceChildren();
|
|
368
|
+
const addRow = (container, flow, enabled) => {
|
|
298
369
|
const btn = doc.createElement('button');
|
|
299
370
|
btn.type = 'button';
|
|
300
|
-
btn.className = 'reticle-flow';
|
|
371
|
+
btn.className = 'reticle-flow-row';
|
|
301
372
|
btn.setAttribute('data-reticle-replay', flow.name);
|
|
302
|
-
btn.
|
|
303
|
-
|
|
373
|
+
btn.title = flow.name;
|
|
374
|
+
btn.disabled = !enabled;
|
|
375
|
+
const play = doc.createElement('span');
|
|
376
|
+
play.className = 'reticle-flow-play';
|
|
377
|
+
play.setAttribute('aria-hidden', 'true');
|
|
378
|
+
play.textContent = '▶';
|
|
379
|
+
const text = doc.createElement('span');
|
|
380
|
+
text.className = 'reticle-flow-text';
|
|
381
|
+
const name = doc.createElement('span');
|
|
382
|
+
name.className = 'reticle-flow-name';
|
|
383
|
+
name.textContent = flowTitle(flow.name);
|
|
384
|
+
const meta = doc.createElement('span');
|
|
385
|
+
meta.className = 'reticle-flow-meta';
|
|
386
|
+
meta.textContent = enabled ? FLOW_TEXT.REPLAYABLE : FLOW_TEXT.ELSEWHERE;
|
|
387
|
+
text.append(name, meta);
|
|
388
|
+
btn.append(play, text);
|
|
389
|
+
container.appendChild(btn);
|
|
390
|
+
};
|
|
391
|
+
{
|
|
392
|
+
if (0 === this.#flowItems.length) {
|
|
393
|
+
const empty = doc.createElement('div');
|
|
394
|
+
empty.className = 'reticle-flows-empty';
|
|
395
|
+
const title = doc.createElement('strong');
|
|
396
|
+
title.textContent = FLOW_TEXT.EMPTY_TITLE;
|
|
397
|
+
const hint = doc.createElement('span');
|
|
398
|
+
hint.textContent = FLOW_TEXT.EMPTY_HINT;
|
|
399
|
+
empty.append(title, hint);
|
|
400
|
+
all.appendChild(empty);
|
|
401
|
+
}
|
|
402
|
+
else {
|
|
403
|
+
for (const flow of [...this.#flowItems].sort((a, b) => (b.createdAt ?? 0) - (a.createdAt ?? 0)))
|
|
404
|
+
addRow(all, flow, playable(flow));
|
|
405
|
+
}
|
|
304
406
|
}
|
|
305
|
-
|
|
407
|
+
this.#paintProgress();
|
|
306
408
|
}
|
|
307
409
|
setState(state, text, tone) {
|
|
308
410
|
this.#state = state;
|
|
@@ -320,10 +422,10 @@ export class ControlPanel {
|
|
|
320
422
|
const ended = state === SessionState.ENDED;
|
|
321
423
|
if (refs.pauseBtn !== undefined) {
|
|
322
424
|
paintPauseBtn(refs.pauseBtn, state === SessionState.PAUSED);
|
|
323
|
-
refs.pauseBtn.
|
|
425
|
+
refs.pauseBtn.hidden = ended;
|
|
324
426
|
}
|
|
325
427
|
if (refs.endBtn !== undefined)
|
|
326
|
-
refs.endBtn.
|
|
428
|
+
refs.endBtn.hidden = ended;
|
|
327
429
|
if (refs.copyBtn !== undefined) {
|
|
328
430
|
if (ended)
|
|
329
431
|
refs.copyBtn.removeAttribute('hidden');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const PRESENTER_DESIGN_TOKENS_CSS: string;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export const PRESENTER_DESIGN_TOKENS_CSS = `
|
|
2
|
+
[data-reticle-overlay]{
|
|
3
|
+
--reticle-hud-space-0:0px;
|
|
4
|
+
--reticle-hud-space-1:4px;
|
|
5
|
+
--reticle-hud-space-2:8px;
|
|
6
|
+
--reticle-hud-space-3:12px;
|
|
7
|
+
--reticle-hud-space-4:16px;
|
|
8
|
+
--reticle-hud-radius-sm:6px;
|
|
9
|
+
--reticle-hud-radius-md:10px;
|
|
10
|
+
--reticle-hud-radius-lg:14px;
|
|
11
|
+
--reticle-hud-radius-pill:9999px;
|
|
12
|
+
--reticle-hud-size-xs:11px;
|
|
13
|
+
--reticle-hud-size-sm:12px;
|
|
14
|
+
--reticle-hud-size-base:13px;
|
|
15
|
+
--reticle-hud-icon-size:18px;
|
|
16
|
+
--reticle-hud-control-size:36px;
|
|
17
|
+
--reticle-hud-control-gap:4px;
|
|
18
|
+
/* Compact: the HUD sits over the user's own app. 400×560 covered too much of it. */
|
|
19
|
+
--reticle-hud-dock-width:320px;
|
|
20
|
+
--reticle-hud-panel-height:440px;
|
|
21
|
+
--reticle-hud-ground:#0b0b0c;
|
|
22
|
+
--reticle-hud-surface:#151417;
|
|
23
|
+
--reticle-hud-inset:#232227;
|
|
24
|
+
--reticle-hud-hover:#1e1d22;
|
|
25
|
+
--reticle-hud-border:#29282d;
|
|
26
|
+
--reticle-hud-border-strong:#3a3941;
|
|
27
|
+
--reticle-hud-text:#f5f3ef;
|
|
28
|
+
--reticle-hud-text-muted:#a6a29a;
|
|
29
|
+
--reticle-hud-text-faint:#8b867d;
|
|
30
|
+
--reticle-hud-brand:#f0872e;
|
|
31
|
+
--reticle-hud-brand-soft:#2a1b0d;
|
|
32
|
+
--reticle-hud-ease:cubic-bezier(.4,0,.2,1);
|
|
33
|
+
}
|
|
34
|
+
`;
|
|
@@ -5,7 +5,7 @@ const DOCK_PANEL_GAP_PX = 8;
|
|
|
5
5
|
const DOCK_SETTINGS_GAP_PX = 12;
|
|
6
6
|
const HUD_BAR_HEIGHT_PX = 44;
|
|
7
7
|
const CHAT_MIN_HEIGHT_PX = 160;
|
|
8
|
-
const CHAT_DEFAULT_MAX_HEIGHT_PX =
|
|
8
|
+
const CHAT_DEFAULT_MAX_HEIGHT_PX = 440;
|
|
9
9
|
const SETTINGS_DEFAULT_MAX_HEIGHT_PX = 520;
|
|
10
10
|
const SETTINGS_MIN_HEIGHT_PX = 200;
|
|
11
11
|
function unionRects(rects) {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AccountState } from '@reticlehq/core';
|
|
2
|
+
export declare const RAIL_ATTR = "data-reticle-rail";
|
|
3
|
+
export declare const RAIL_SIGNIN_ATTR = "data-reticle-rail-signin";
|
|
4
|
+
export declare const RAIL_PROMO_ATTR = "data-reticle-rail-promo";
|
|
5
|
+
export declare const RAIL_TEXT: {
|
|
6
|
+
readonly TITLE: "Sign in to try Reticle Harness";
|
|
7
|
+
readonly DETAIL: "Free Harness credits to start.";
|
|
8
|
+
readonly CTA: "Sign in";
|
|
9
|
+
};
|
|
10
|
+
export declare const RAIL_HTML: string;
|
|
11
|
+
export declare function paintRail(root: HTMLElement, account: AccountState | undefined): void;
|
|
12
|
+
export declare const FRAME_CSS: string;
|