@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
|
@@ -0,0 +1,622 @@
|
|
|
1
|
+
import { DEFAULT_PLATFORM_URL, } from '@reticlehq/core';
|
|
2
|
+
import { PLAN_HTML } from './presenter-plan.js';
|
|
3
|
+
import { marksForAgent } from '../review/marks-for-agent.js';
|
|
4
|
+
import { ANNOTATE_BTN_ATTR, CHAT_TOGGLE_ATTR, CLEAR_MARKS_ATTR, MARKERS_BTN_ATTR, } from './presenter-config.js';
|
|
5
|
+
import { hiIconHtml, hiToggleIconHtml, PRESENTER_ICON_SIZE, PresenterIcon, } from './icons/presenter-icons.js';
|
|
6
|
+
import { HUD_GLASS_PAINT } from './chrome/presenter-hud-chrome.js';
|
|
7
|
+
import { LAST_ACTOR_ATTR, LOG_ACTOR } from './chrome/presenter-log.js';
|
|
8
|
+
import { HARNESS_COPY_PROMPT_ATTR, HARNESS_LINK_ATTR, HARNESS_LOG_ATTR, HARNESS_OPEN_ATTR, HARNESS_ROW_TEXT, HARNESS_SWITCH_ON_ATTR, HARNESS_TOGGLE_ATTR, creditsShort, harnessFootHtml, harnessRowHtml, HARNESS_ROW_CSS, } from './presenter-harness-row.js';
|
|
9
|
+
import { esc, isSafeDashboardUrl } from './chrome/presenter-safe-html.js';
|
|
10
|
+
import { morphHtml } from './chrome/presenter-morph.js';
|
|
11
|
+
import { IMPACT_SEEN_KEY_PREFIX, ReticleStorageKey } from '../storage-keys.js';
|
|
12
|
+
import { DEFAULT_PERSONA, PERSONA_PICK_ID, knownPick, personaText, readPick, savePick, } from './presenter-personas.js';
|
|
13
|
+
import { AGENT_LINK_CSS, AGENT_LINK_HTML, AgentLinkView } from './presenter-agent-link.js';
|
|
14
|
+
import { ACCOUNT_SIGNIN_ATTR, TEAM_SAVE_ATTR, TEAM_SLOT_ATTR } from './presenter-account.js';
|
|
15
|
+
const PAGE_VIEWS = ['flows', 'annotations', 'harness'];
|
|
16
|
+
const HISTORY_KEY = ReticleStorageKey.ANNOTATION_HISTORY;
|
|
17
|
+
const HISTORY_LIMIT = 200;
|
|
18
|
+
const HARNESS_SETUP_PATH = '/settings?group=project';
|
|
19
|
+
const HARNESS_SETUP_HASH = '#model';
|
|
20
|
+
const HARNESS_PLAN_PATH = '/settings?group=billing';
|
|
21
|
+
const HARNESS_STARTING_MS = 20_000;
|
|
22
|
+
export function platformBase(config, account) {
|
|
23
|
+
const base = [config?.platformUrl, account.host].find((url) => url !== undefined && isSafeDashboardUrl(url));
|
|
24
|
+
return esc((base ?? DEFAULT_PLATFORM_URL).replace(/\/+$/, ''));
|
|
25
|
+
}
|
|
26
|
+
function isHistoricalAnnotation(item) {
|
|
27
|
+
if ('object' !== typeof item || null === item)
|
|
28
|
+
return false;
|
|
29
|
+
const value = item;
|
|
30
|
+
return ('string' === typeof value.id &&
|
|
31
|
+
'string' === typeof value.note &&
|
|
32
|
+
'string' === typeof value.label &&
|
|
33
|
+
'string' === typeof value.anchor &&
|
|
34
|
+
'string' === typeof value.route &&
|
|
35
|
+
'number' === typeof value.createdAt &&
|
|
36
|
+
'string' === typeof value.pageUrl);
|
|
37
|
+
}
|
|
38
|
+
function readHistory() {
|
|
39
|
+
try {
|
|
40
|
+
const parsed = JSON.parse(localStorage.getItem(HISTORY_KEY) ?? '[]');
|
|
41
|
+
if (!Array.isArray(parsed))
|
|
42
|
+
return [];
|
|
43
|
+
return parsed.filter(isHistoricalAnnotation).slice(0, HISTORY_LIMIT);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function readImpactSeen(projectId) {
|
|
50
|
+
try {
|
|
51
|
+
return Number(localStorage.getItem(`${IMPACT_SEEN_KEY_PREFIX}${projectId ?? ''}`) ?? 0) || 0;
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function saveImpactSeen(projectId, verdicts) {
|
|
58
|
+
try {
|
|
59
|
+
localStorage.setItem(`${IMPACT_SEEN_KEY_PREFIX}${projectId ?? ''}`, String(verdicts));
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function saveHistory(items) {
|
|
65
|
+
try {
|
|
66
|
+
localStorage.setItem(HISTORY_KEY, JSON.stringify(items.slice(0, HISTORY_LIMIT)));
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
export const CHAT_VIEWS_HTML = `${AGENT_LINK_HTML}
|
|
72
|
+
<div data-reticle-harness-spot class="reticle-harness-spot" hidden></div>`;
|
|
73
|
+
export const FLOWS_PAGE_HTML = `<section data-reticle-page-panel="flows" class="reticle-page-panel reticle-flows-view" role="region" aria-label="Saved Flows" hidden>
|
|
74
|
+
<div class="reticle-page-heading"><span class="reticle-page-titles"><strong>Saved flows</strong><span class="reticle-page-subtitle">Journeys your agent verified, replayable here</span></span><button type="button" data-reticle-page-close aria-label="Close Saved Flows" title="Close">×</button></div>
|
|
75
|
+
<div data-reticle-all-flows class="reticle-all-flows"></div>
|
|
76
|
+
</section>`;
|
|
77
|
+
const NAV_ICON_SIZE = PRESENTER_ICON_SIZE.NAV;
|
|
78
|
+
export const NAV_LABEL = {
|
|
79
|
+
LOG: 'Log',
|
|
80
|
+
FLOWS: 'Flows',
|
|
81
|
+
NOTES: 'Notes',
|
|
82
|
+
IMPACT: 'Impact',
|
|
83
|
+
HARNESS: 'Harness',
|
|
84
|
+
SETTINGS: 'Settings',
|
|
85
|
+
HIDE: 'Hide',
|
|
86
|
+
};
|
|
87
|
+
const IMPACT_ARIA = { SEEN: 'Open Impact', NEW: 'Open Impact, new results' };
|
|
88
|
+
export const navLabelHtml = (text) => `<span class="reticle-nav-label">${text}</span>`;
|
|
89
|
+
export const CHAT_VIEWS_NAV_HTML = `<nav class="reticle-chat-nav" aria-label="Reticle views">
|
|
90
|
+
<button type="button" ${CHAT_TOGGLE_ATTR} data-reticle-chat-view-btn="activity" aria-label="Agent log" title="Agent log" aria-current="page">${hiIconHtml(PresenterIcon.MESSAGE, NAV_ICON_SIZE)}${navLabelHtml(NAV_LABEL.LOG)}</button>
|
|
91
|
+
<button type="button" data-reticle-chat-view-btn="harness" aria-label="${HARNESS_ROW_TEXT.PAGE_TITLE}" title="${HARNESS_ROW_TEXT.PAGE_TITLE}" hidden>${hiIconHtml(PresenterIcon.PLAY, NAV_ICON_SIZE)}${navLabelHtml(NAV_LABEL.HARNESS)}</button>
|
|
92
|
+
<button type="button" data-reticle-chat-view-btn="flows" aria-label="Saved flows" title="Saved flows">${hiIconHtml(PresenterIcon.LAYOUT, NAV_ICON_SIZE)}${navLabelHtml(NAV_LABEL.FLOWS)}</button>
|
|
93
|
+
<button type="button" data-reticle-chat-view-btn="annotations" aria-label="Notes" title="Notes">${hiIconHtml(PresenterIcon.NOTES, NAV_ICON_SIZE)}<span class="reticle-nav-label">${NAV_LABEL.NOTES}<span data-reticle-note-count class="reticle-nav-count" hidden></span></span></button>
|
|
94
|
+
<button type="button" data-reticle-chat-impact class="reticle-chat-impact" aria-label="${IMPACT_ARIA.SEEN}" title="Impact">${hiIconHtml(PresenterIcon.CHART, NAV_ICON_SIZE)}${navLabelHtml(NAV_LABEL.IMPACT)}<span data-reticle-impact-dot class="reticle-nav-dot" aria-hidden="true" hidden></span></button>
|
|
95
|
+
</nav>`;
|
|
96
|
+
const ANNOTATION_ACTION_ICON_SIZE = PRESENTER_ICON_SIZE.TOOLBAR;
|
|
97
|
+
const markersLabel = 'Show note markers on the page';
|
|
98
|
+
const clearLabel = 'Clear notes from this page';
|
|
99
|
+
const copyAllLabel = 'Copy all notes';
|
|
100
|
+
const NOTES_TEXT = {
|
|
101
|
+
SUBTITLE: 'Feedback for your agent',
|
|
102
|
+
SUBTITLE_FULL: 'Pin feedback on the page for your agent',
|
|
103
|
+
PAGE_EMPTY: 'No notes on this page',
|
|
104
|
+
PAGE_HINT: 'Select Add notes, then click anything on the page to pin feedback for your agent.',
|
|
105
|
+
HISTORY_EMPTY: 'No saved notes yet',
|
|
106
|
+
HISTORY_HINT: 'Notes from every page you annotate are kept here.',
|
|
107
|
+
};
|
|
108
|
+
export const HARNESS_PAGE_HTML = `<section data-reticle-page-panel="harness" class="reticle-page-panel reticle-harness-page" role="region" aria-label="${HARNESS_ROW_TEXT.PAGE_TITLE}" hidden>
|
|
109
|
+
<div class="reticle-page-heading"><span class="reticle-page-titles"><strong>${HARNESS_ROW_TEXT.PAGE_TITLE}</strong><span class="reticle-page-subtitle">${HARNESS_ROW_TEXT.PAGE_SUBTITLE}</span></span><button type="button" data-reticle-page-close aria-label="Close ${HARNESS_ROW_TEXT.PAGE_TITLE}" title="Close">×</button></div>
|
|
110
|
+
<div data-reticle-harness-page class="reticle-harness-body"></div>
|
|
111
|
+
${PLAN_HTML}
|
|
112
|
+
<div ${HARNESS_LOG_ATTR} ${LAST_ACTOR_ATTR}="${LOG_ACTOR.HARNESS}" class="reticle-harness-log" aria-live="polite" aria-label="${HARNESS_ROW_TEXT.LOG_LABEL}"></div>
|
|
113
|
+
<p data-reticle-harness-page-meta class="reticle-foot-meta"></p>
|
|
114
|
+
</section>`;
|
|
115
|
+
export const ANNOTATIONS_HTML = `<section data-reticle-page-panel="annotations" class="reticle-page-panel reticle-annotations-view" role="region" aria-label="Notes" hidden>
|
|
116
|
+
<div class="reticle-page-heading"><span class="reticle-page-titles"><strong>Notes</strong><span class="reticle-page-subtitle" title="${NOTES_TEXT.SUBTITLE_FULL}">${NOTES_TEXT.SUBTITLE}</span></span><button type="button" ${ANNOTATE_BTN_ATTR} class="reticle-add-notes reticle-primary-btn" title="Add notes" aria-label="Add notes" aria-pressed="false" data-active="0"><span class="reticle-add-notes-icon">${hiIconHtml(PresenterIcon.ANNOTATE, PRESENTER_ICON_SIZE.TOOLBAR)}</span><span data-reticle-notes-toggle-label>Add notes</span></button><button type="button" data-reticle-page-close aria-label="Close Notes" title="Close">×</button></div>
|
|
117
|
+
<div class="reticle-annotations-tabs" role="group" aria-label="Notes lists">
|
|
118
|
+
<span class="reticle-segmented"><button type="button" data-reticle-annotation-tab="current" aria-pressed="true">This page</button><button type="button" data-reticle-annotation-tab="history" aria-pressed="false">History</button></span>
|
|
119
|
+
<div data-reticle-current-annotation-actions class="reticle-annotation-actions" aria-label="Current page note actions">
|
|
120
|
+
<button type="button" ${MARKERS_BTN_ATTR} class="reticle-annotation-icon-btn reticle-annotation-marker-toggle" title="${markersLabel}" aria-label="${markersLabel}" aria-pressed="false" data-active="0" disabled>${hiToggleIconHtml(PresenterIcon.VIEW, ANNOTATION_ACTION_ICON_SIZE)}</button>
|
|
121
|
+
<button type="button" ${CLEAR_MARKS_ATTR} class="reticle-annotation-icon-btn" title="${clearLabel}" aria-label="${clearLabel}" disabled>${hiIconHtml(PresenterIcon.TRASH, ANNOTATION_ACTION_ICON_SIZE)}</button>
|
|
122
|
+
</div>
|
|
123
|
+
<button type="button" data-reticle-copy-all-notes class="reticle-annotation-icon-btn reticle-copy-all" title="${copyAllLabel}" aria-label="${copyAllLabel}">${hiIconHtml(PresenterIcon.COPY, ANNOTATION_ACTION_ICON_SIZE)}</button>
|
|
124
|
+
</div>
|
|
125
|
+
<div data-reticle-annotation-list class="reticle-annotation-list"></div>
|
|
126
|
+
</section>`;
|
|
127
|
+
export const CHAT_VIEWS_CSS = `
|
|
128
|
+
${HARNESS_ROW_CSS}
|
|
129
|
+
${HARNESS_ROW_CSS.replaceAll('[data-reticle-chat-panel]', '[data-reticle-page-panel="harness"]')}
|
|
130
|
+
[data-reticle-page-panel="harness"] .reticle-harness-body{flex:none;display:flex;flex-direction:column;gap:var(--reticle-hud-space-2);padding:var(--reticle-hud-space-3);}
|
|
131
|
+
/* The run as it happens, then its result: the Harness's rows only, scrolling under the controls. */
|
|
132
|
+
[data-reticle-page-panel="harness"] .reticle-harness-log{flex:1;min-height:0;overflow-y:auto;padding:0 var(--reticle-hud-space-3) var(--reticle-hud-space-2);}
|
|
133
|
+
[data-reticle-page-panel="harness"] .reticle-harness-log:empty::before{content:"${HARNESS_ROW_TEXT.LOG_EMPTY}";display:block;padding:var(--reticle-hud-space-2) 0;color:var(--reticle-hud-text-faint);font-size:11px;}
|
|
134
|
+
[data-reticle-page-panel="harness"] .reticle-foot-meta{flex:none;padding:0 var(--reticle-hud-space-3) var(--reticle-hud-space-3);}
|
|
135
|
+
[data-reticle-page-open="harness"] [data-reticle-page-panel="harness"]{display:flex;}
|
|
136
|
+
[data-reticle-page-open="harness"] [data-reticle-chat-panel]{display:none!important;}
|
|
137
|
+
[data-reticle-hud] .reticle-chat-nav{display:contents;}
|
|
138
|
+
[data-reticle-hud] .reticle-chat-nav button{position:relative;width:var(--reticle-hud-control-size);height:var(--reticle-hud-control-size);justify-self:center;display:inline-flex;align-items:center;justify-content:center;border:0;border-radius:var(--reticle-hud-radius-md);padding:0;background:transparent;color:var(--reticle-hud-text-muted);cursor:pointer;}
|
|
139
|
+
[data-reticle-hud] .reticle-chat-nav button:hover{background:var(--reticle-hud-hover);color:var(--reticle-hud-text);}
|
|
140
|
+
[data-reticle-hud] .reticle-chat-nav button[aria-current="page"],[data-reticle-hud] .reticle-chat-nav button[data-active="1"]{background:transparent;color:var(--reticle-hud-text);}
|
|
141
|
+
/* The page you are on: a short straight bar under its name, nothing louder. */
|
|
142
|
+
[data-reticle-hud] .reticle-toolbar-chrome :is(.reticle-chat-nav button[aria-current="page"],.reticle-chat-nav button[data-active="1"],.reticle-tb-btn[data-active="1"])::after{content:"";position:absolute;left:50%;bottom:1px;width:16px;height:2px;border-radius:1px;transform:translateX(-50%);background:currentColor;}
|
|
143
|
+
[data-reticle-hud] .reticle-chat-nav .reticle-hi-icon{opacity:.92;}
|
|
144
|
+
[data-reticle-hud] .reticle-chat-nav button[hidden]{display:none;}
|
|
145
|
+
/* An icon with its name under it, small: every page says what it is without a hover. */
|
|
146
|
+
[data-reticle-hud] .reticle-toolbar-chrome .reticle-chat-nav button{flex-direction:column;gap:2px;width:100%;height:auto;min-height:42px;padding:4px 0 3px;}
|
|
147
|
+
[data-reticle-hud] .reticle-nav-label{display:block;font-size:9px;line-height:1;font-weight:500;letter-spacing:.01em;color:inherit;white-space:nowrap;}
|
|
148
|
+
[data-reticle-hud] .reticle-chat-nav .reticle-nav-count:empty{display:none;}
|
|
149
|
+
[data-reticle-hud] .reticle-chat-nav .reticle-nav-count:not(:empty){margin-left:3px;font-variant-numeric:tabular-nums;color:var(--reticle-hud-brand);font-weight:600;}
|
|
150
|
+
[data-reticle-hud] .reticle-chat-nav .reticle-nav-count[hidden]{display:none;}
|
|
151
|
+
/* New results since Impact was last opened: a dot on the icon's corner, out of the flow, so no number can push the label. */
|
|
152
|
+
[data-reticle-hud] .reticle-chat-nav .reticle-nav-dot{position:absolute;top:4px;left:calc(50% + 5px);width:7px;height:7px;border-radius:50%;background:var(--reticle-hud-brand);box-shadow:0 0 0 2px var(--reticle-hud-surface);pointer-events:none;}
|
|
153
|
+
[data-reticle-hud] .reticle-chat-nav .reticle-nav-dot[hidden]{display:none;}
|
|
154
|
+
[data-reticle-page-panel]{position:absolute;right:0;left:auto;bottom:calc(100% + 8px);z-index:6;box-sizing:border-box;width:var(--reticle-dock-w);max-width:min(var(--reticle-dock-w),calc(100vw - 16px));height:min(var(--reticle-chat-max-h,var(--reticle-chat-h)),calc(100vh - 120px));max-height:min(var(--reticle-chat-max-h,var(--reticle-chat-h)),calc(100vh - 120px));flex-direction:column;overflow:hidden;border-radius:var(--reticle-hud-radius-lg);${HUD_GLASS_PAINT}color:var(--reticle-hud-text);font-size:13px;line-height:1.5;pointer-events:auto;text-align:left;}
|
|
155
|
+
[data-reticle-page-panel][hidden]{display:none!important;}
|
|
156
|
+
[data-reticle-page-open="annotations"] [data-reticle-page-panel="annotations"],[data-reticle-page-open="flows"] [data-reticle-page-panel="flows"]{display:flex;}
|
|
157
|
+
[data-reticle-page-open="annotations"] [data-reticle-chat-panel],[data-reticle-page-open="flows"] [data-reticle-chat-panel]{display:none!important;}
|
|
158
|
+
[data-reticle-page-heading],.reticle-page-heading{display:flex;align-items:center;justify-content:space-between;min-height:42px;box-sizing:border-box;padding:7px 12px;border-bottom:1px solid var(--reticle-hud-border);}
|
|
159
|
+
.reticle-page-heading strong{font-size:12px;font-weight:600;}
|
|
160
|
+
.reticle-page-heading button{width:26px;height:26px;border:0;border-radius:6px;background:transparent;color:var(--reticle-hud-text-muted);font:inherit;font-size:19px;line-height:1;cursor:pointer;}
|
|
161
|
+
.reticle-page-heading button:hover{background:var(--reticle-hud-hover);color:var(--reticle-hud-text);}
|
|
162
|
+
.reticle-page-subtitle{flex:none;padding:5px 12px;border-bottom:1px solid var(--reticle-hud-border);color:var(--reticle-hud-text-muted);font-size:11px;}
|
|
163
|
+
.reticle-page-panel .reticle-all-flows,.reticle-page-panel .reticle-annotation-list{flex:1;min-height:0;overflow-y:auto;}
|
|
164
|
+
[data-reticle-page-panel="annotations"] .reticle-annotations-tabs{flex:none;}
|
|
165
|
+
[data-reticle-page-panel="annotations"] .reticle-annotation-list{flex:1;}
|
|
166
|
+
[data-reticle-chat-panel] .reticle-marks-row{display:none !important;}
|
|
167
|
+
[data-reticle-page-panel="annotations"] .reticle-annotations-tabs{display:flex;align-items:center;gap:2px;min-height:var(--reticle-hud-control-size);padding:var(--reticle-hud-space-1) var(--reticle-hud-space-2);border-bottom:1px solid var(--reticle-hud-border);}
|
|
168
|
+
[data-reticle-page-panel="annotations"] .reticle-annotations-tabs button{border:0;border-radius:var(--reticle-hud-radius-sm);background:transparent;color:var(--reticle-hud-text-muted);padding:var(--reticle-hud-space-1) var(--reticle-hud-space-2);font:inherit;font-size:var(--reticle-hud-size-xs);cursor:pointer;}
|
|
169
|
+
[data-reticle-page-panel="annotations"] .reticle-annotations-tabs button[aria-pressed="true"]{background:var(--reticle-hud-inset);color:var(--reticle-hud-text);}
|
|
170
|
+
[data-reticle-page-panel="annotations"] .reticle-annotations-tabs .reticle-add-notes{display:inline-flex;align-items:center;gap:4px;margin-left:5px;padding:5px 7px;border:1px solid var(--reticle-hud-border-strong);background:var(--reticle-hud-inset);color:var(--reticle-hud-text);font-weight:600;white-space:nowrap;}
|
|
171
|
+
[data-reticle-page-panel="annotations"] .reticle-annotations-tabs .reticle-add-notes[data-active="1"]{border-color:var(--reticle-accent);background:var(--reticle-accent-soft);color:var(--reticle-accent);}
|
|
172
|
+
[data-reticle-page-panel="annotations"] .reticle-add-notes-icon{display:inline-flex;align-items:center;}
|
|
173
|
+
[data-reticle-page-panel="annotations"] .reticle-annotations-tabs .reticle-copy-all{margin-left:auto;color:var(--reticle-hud-brand);white-space:nowrap;}
|
|
174
|
+
[data-reticle-page-panel="annotations"] .reticle-annotation-actions{display:flex;align-items:center;gap:0;margin-left:0;}
|
|
175
|
+
[data-reticle-page-panel="annotations"] .reticle-annotation-actions[hidden]{display:none;}
|
|
176
|
+
[data-reticle-page-panel="annotations"] .reticle-annotation-icon-btn{width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center;border:0;border-radius:var(--reticle-hud-radius-sm);background:transparent;color:var(--reticle-hud-text-muted);cursor:pointer;}
|
|
177
|
+
[data-reticle-page-panel="annotations"] .reticle-annotation-icon-btn .reticle-hi-icon--solid{opacity:0;}
|
|
178
|
+
[data-reticle-page-panel="annotations"] .reticle-annotation-icon-btn:hover:not(:disabled){color:var(--reticle-hud-text);background:var(--reticle-hud-hover);}
|
|
179
|
+
[data-reticle-page-panel="annotations"] .reticle-annotation-icon-btn[data-active="1"]{color:var(--reticle-accent);background:var(--reticle-accent-soft);border-color:color-mix(in srgb,var(--reticle-accent) 40%,transparent);}
|
|
180
|
+
[data-reticle-page-panel="annotations"] .reticle-annotation-icon-btn:disabled{opacity:.35;cursor:not-allowed;}
|
|
181
|
+
[data-reticle-page-panel="annotations"] .reticle-annotation-list{flex:1;min-height:0;overflow-y:auto;padding:var(--reticle-hud-space-2) var(--reticle-hud-space-3);}
|
|
182
|
+
[data-reticle-page-panel="annotations"] .reticle-annotation-empty{padding:var(--reticle-hud-space-4) var(--reticle-hud-space-2);text-align:center;color:var(--reticle-hud-text-muted);font-size:var(--reticle-hud-size-sm);}
|
|
183
|
+
[data-reticle-page-panel="annotations"] .reticle-annotation-item{display:flex;align-items:start;gap:var(--reticle-hud-space-2);padding:var(--reticle-hud-space-2) 2px;border-bottom:1px solid var(--reticle-hud-border);}
|
|
184
|
+
[data-reticle-page-panel="annotations"] .reticle-annotation-content{flex:1;min-width:0;}
|
|
185
|
+
[data-reticle-page-panel="annotations"] .reticle-annotation-content strong{display:block;font-size:11px;font-weight:600;overflow-wrap:anywhere;}
|
|
186
|
+
[data-reticle-page-panel="annotations"] .reticle-annotation-content span{display:block;margin-top:3px;font-size:var(--reticle-hud-size-xs);color:var(--reticle-hud-text-muted);overflow-wrap:anywhere;}
|
|
187
|
+
[data-reticle-page-panel="annotations"] .reticle-annotation-item button{flex:none;border:1px solid var(--reticle-line);border-radius:6px;background:rgba(255,255,255,.04);color:var(--reticle-muted);font:inherit;font-size:11px;padding:4px 6px;cursor:pointer;}
|
|
188
|
+
[data-reticle-page-panel="annotations"] .reticle-annotation-item button:hover{color:#fff;background:rgba(255,255,255,.1);}
|
|
189
|
+
${AGENT_LINK_CSS}`;
|
|
190
|
+
const RUN_CONTROL = '[data-reticle-harness-page] :is([data-reticle-harness-run],[data-reticle-harness-stop])';
|
|
191
|
+
function readViewMemory() {
|
|
192
|
+
try {
|
|
193
|
+
const raw = JSON.parse(globalThis.sessionStorage.getItem(ReticleStorageKey.PRESENTER_VIEW) ?? '{}');
|
|
194
|
+
const r = (null !== raw && 'object' === typeof raw ? raw : {});
|
|
195
|
+
const view = PAGE_VIEWS.find((v) => v === r.view) ?? 'activity';
|
|
196
|
+
return { view, runFocused: true === r.runFocused };
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
return { view: 'activity', runFocused: false };
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
function rememberView(memory) {
|
|
203
|
+
try {
|
|
204
|
+
globalThis.sessionStorage.setItem(ReticleStorageKey.PRESENTER_VIEW, JSON.stringify(memory));
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
export class ChatViews {
|
|
210
|
+
#root;
|
|
211
|
+
#view = readViewMemory().view;
|
|
212
|
+
#refocusRun = readViewMemory().runFocused;
|
|
213
|
+
#runFocused = false;
|
|
214
|
+
#annotationTab = 'current';
|
|
215
|
+
#current = [];
|
|
216
|
+
#history = readHistory();
|
|
217
|
+
#account;
|
|
218
|
+
#harness;
|
|
219
|
+
#gate;
|
|
220
|
+
#verdicts = 0;
|
|
221
|
+
#impactOpen = false;
|
|
222
|
+
#onImpact;
|
|
223
|
+
#onOpenChat;
|
|
224
|
+
#listeners;
|
|
225
|
+
#drive;
|
|
226
|
+
#driving;
|
|
227
|
+
#projectId;
|
|
228
|
+
#personaPick = DEFAULT_PERSONA;
|
|
229
|
+
#customPersona = '';
|
|
230
|
+
#harnessHtml = '';
|
|
231
|
+
#harnessPageHtml = '';
|
|
232
|
+
#linking = false;
|
|
233
|
+
#agent = new AgentLinkView();
|
|
234
|
+
#startedAs;
|
|
235
|
+
#starting;
|
|
236
|
+
constructor(onImpact, onOpenChat, drive) {
|
|
237
|
+
this.#onImpact = onImpact;
|
|
238
|
+
this.#onOpenChat = onOpenChat;
|
|
239
|
+
this.#drive = drive;
|
|
240
|
+
}
|
|
241
|
+
mount(root) {
|
|
242
|
+
this.#root = root;
|
|
243
|
+
this.#listeners = new AbortController();
|
|
244
|
+
const signal = this.#listeners.signal;
|
|
245
|
+
root.querySelectorAll('[data-reticle-chat-view-btn]').forEach((button) => button.addEventListener('click', () => {
|
|
246
|
+
const view = button.getAttribute('data-reticle-chat-view-btn');
|
|
247
|
+
this.#onOpenChat(view);
|
|
248
|
+
this.open(view);
|
|
249
|
+
}, { signal }));
|
|
250
|
+
root
|
|
251
|
+
.querySelector('[data-reticle-chat-impact]')
|
|
252
|
+
?.addEventListener('click', () => this.#onImpact(), { signal });
|
|
253
|
+
const onHarnessClick = (event) => {
|
|
254
|
+
const target = event.target;
|
|
255
|
+
if (!(target instanceof Element))
|
|
256
|
+
return;
|
|
257
|
+
if (null !== target.closest(`[${HARNESS_OPEN_ATTR}]`)) {
|
|
258
|
+
this.#onOpenChat('harness');
|
|
259
|
+
this.open('harness');
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
if (null !== target.closest(`[${HARNESS_SWITCH_ON_ATTR}]`)) {
|
|
263
|
+
this.#drive?.setHarness(true);
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
const toggle = target.closest(`[${HARNESS_TOGGLE_ATTR}]`);
|
|
267
|
+
if (null !== toggle) {
|
|
268
|
+
const on = 'true' !== toggle.getAttribute('aria-checked');
|
|
269
|
+
toggle.setAttribute('aria-checked', String(on));
|
|
270
|
+
this.#drive?.setHarness(on);
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
const linkButton = target.closest(`[${HARNESS_LINK_ATTR}],[${TEAM_SAVE_ATTR}]:not([${ACCOUNT_SIGNIN_ATTR}])`);
|
|
274
|
+
if (null !== linkButton) {
|
|
275
|
+
if (linkButton.disabled)
|
|
276
|
+
return;
|
|
277
|
+
this.#linking = true;
|
|
278
|
+
this.#drive?.link();
|
|
279
|
+
this.#paintHarness();
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
const run = target.closest('[data-reticle-harness-run]');
|
|
283
|
+
if (null !== run) {
|
|
284
|
+
if (run.disabled)
|
|
285
|
+
return;
|
|
286
|
+
this.#startedAs = this.#personaPick;
|
|
287
|
+
this.#markStarting(true);
|
|
288
|
+
this.#drive?.run(personaText(this.#personaPick, this.#customPersona));
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
if (null !== target.closest('[data-reticle-harness-stop]')) {
|
|
292
|
+
this.#drive?.stop();
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
const copy = target.closest(`[${HARNESS_COPY_PROMPT_ATTR}]`);
|
|
296
|
+
if (null !== copy) {
|
|
297
|
+
const prompt = this.#gate?.prompt;
|
|
298
|
+
if (prompt !== undefined)
|
|
299
|
+
void navigator.clipboard
|
|
300
|
+
?.writeText(prompt)
|
|
301
|
+
.then(() => (copy.textContent = HARNESS_ROW_TEXT.COPIED))
|
|
302
|
+
.catch(() => undefined);
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
root
|
|
306
|
+
.querySelector('[data-reticle-harness-spot]')
|
|
307
|
+
?.addEventListener('click', onHarnessClick, { signal });
|
|
308
|
+
root
|
|
309
|
+
.querySelector('[data-reticle-harness-page]')
|
|
310
|
+
?.addEventListener('click', onHarnessClick, { signal });
|
|
311
|
+
root
|
|
312
|
+
.querySelector(`[${TEAM_SLOT_ATTR}]`)
|
|
313
|
+
?.addEventListener('click', onHarnessClick, { signal });
|
|
314
|
+
const spot = root.querySelector('[data-reticle-harness-page]');
|
|
315
|
+
spot?.addEventListener('change', (event) => {
|
|
316
|
+
const target = event.target;
|
|
317
|
+
if (!(target instanceof HTMLSelectElement))
|
|
318
|
+
return;
|
|
319
|
+
const pick = knownPick(target.value);
|
|
320
|
+
if (pick === undefined)
|
|
321
|
+
return;
|
|
322
|
+
this.#personaPick = pick;
|
|
323
|
+
savePick(this.#projectId, pick);
|
|
324
|
+
this.#paintHarness();
|
|
325
|
+
this.#root?.querySelector(`#${PERSONA_PICK_ID}`)?.focus();
|
|
326
|
+
}, { signal });
|
|
327
|
+
spot?.addEventListener('input', (event) => {
|
|
328
|
+
if (event.target instanceof HTMLInputElement)
|
|
329
|
+
this.#customPersona = event.target.value;
|
|
330
|
+
}, { signal });
|
|
331
|
+
this.#agent.mount(root, signal);
|
|
332
|
+
root.querySelectorAll('[data-reticle-annotation-tab]').forEach((button) => button.addEventListener('click', () => {
|
|
333
|
+
this.#annotationTab =
|
|
334
|
+
'history' === button.getAttribute('data-reticle-annotation-tab')
|
|
335
|
+
? 'history'
|
|
336
|
+
: 'current';
|
|
337
|
+
this.#paintAnnotations();
|
|
338
|
+
}, { signal }));
|
|
339
|
+
root.querySelector('[data-reticle-annotate-btn]')?.addEventListener('click', () => {
|
|
340
|
+
this.#annotationTab = 'current';
|
|
341
|
+
this.#paintAnnotations();
|
|
342
|
+
}, { signal });
|
|
343
|
+
root
|
|
344
|
+
.querySelector('[data-reticle-copy-all-notes]')
|
|
345
|
+
?.addEventListener('click', () => this.#copyAll(), { signal });
|
|
346
|
+
root
|
|
347
|
+
.querySelectorAll('[data-reticle-page-close]')
|
|
348
|
+
.forEach((button) => button.addEventListener('click', () => this.closePage(), { signal }));
|
|
349
|
+
root.querySelector('[data-reticle-annotation-list]')?.addEventListener('click', (event) => {
|
|
350
|
+
const target = event.target;
|
|
351
|
+
if (!(target instanceof Element))
|
|
352
|
+
return;
|
|
353
|
+
const button = target.closest('[data-reticle-copy-note]');
|
|
354
|
+
if (null === button)
|
|
355
|
+
return;
|
|
356
|
+
const index = Number(button.getAttribute('data-reticle-copy-note'));
|
|
357
|
+
if (!Number.isInteger(index))
|
|
358
|
+
return;
|
|
359
|
+
const item = this.#visibleAnnotations()[index];
|
|
360
|
+
if (item !== undefined)
|
|
361
|
+
this.#copy([item], 'pageUrl' in item ? item.pageUrl : location.href);
|
|
362
|
+
}, { signal });
|
|
363
|
+
root.addEventListener('focusin', (event) => this.#noteRunFocus(event.target instanceof Element && event.target.matches(RUN_CONTROL)), { signal });
|
|
364
|
+
root.addEventListener('focusout', (event) => {
|
|
365
|
+
const next = event.relatedTarget;
|
|
366
|
+
this.#noteRunFocus(next instanceof Element && next.matches(RUN_CONTROL));
|
|
367
|
+
}, { signal });
|
|
368
|
+
this.open(this.#view);
|
|
369
|
+
this.#paintHarness();
|
|
370
|
+
this.paintImpact(this.#verdicts);
|
|
371
|
+
this.#paintAnnotations();
|
|
372
|
+
}
|
|
373
|
+
teardown() {
|
|
374
|
+
this.#markStarting(false);
|
|
375
|
+
this.#listeners?.abort();
|
|
376
|
+
this.#listeners = undefined;
|
|
377
|
+
this.#root = undefined;
|
|
378
|
+
this.#harnessHtml = '';
|
|
379
|
+
this.#harnessPageHtml = '';
|
|
380
|
+
this.#agent.teardown();
|
|
381
|
+
}
|
|
382
|
+
#noteRunFocus(on) {
|
|
383
|
+
if (on === this.#runFocused)
|
|
384
|
+
return;
|
|
385
|
+
this.#runFocused = on;
|
|
386
|
+
rememberView({ view: this.#view, runFocused: on });
|
|
387
|
+
}
|
|
388
|
+
open(view) {
|
|
389
|
+
if (view !== 'activity' && !PAGE_VIEWS.includes(view))
|
|
390
|
+
return;
|
|
391
|
+
this.#view = view;
|
|
392
|
+
rememberView({ view, runFocused: this.#runFocused });
|
|
393
|
+
const root = this.#root;
|
|
394
|
+
if (root === undefined)
|
|
395
|
+
return;
|
|
396
|
+
if ('activity' === view)
|
|
397
|
+
root.removeAttribute('data-reticle-page-open');
|
|
398
|
+
else
|
|
399
|
+
root.setAttribute('data-reticle-page-open', view);
|
|
400
|
+
const chat = root.querySelector('[data-reticle-chat-panel]');
|
|
401
|
+
if (chat !== null)
|
|
402
|
+
chat.hidden = view !== 'activity';
|
|
403
|
+
root.querySelectorAll('[data-reticle-page-panel]').forEach((panel) => {
|
|
404
|
+
panel.hidden = panel.getAttribute('data-reticle-page-panel') !== view;
|
|
405
|
+
});
|
|
406
|
+
this.#root?.querySelectorAll('[data-reticle-chat-view-btn]').forEach((button) => {
|
|
407
|
+
if (button.getAttribute('data-reticle-chat-view-btn') === view)
|
|
408
|
+
button.setAttribute('aria-current', 'page');
|
|
409
|
+
else
|
|
410
|
+
button.removeAttribute('aria-current');
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
closePage() {
|
|
414
|
+
const root = this.#root;
|
|
415
|
+
if (root === undefined)
|
|
416
|
+
return;
|
|
417
|
+
root.removeAttribute('data-reticle-page-open');
|
|
418
|
+
root.querySelectorAll('[data-reticle-page-panel]').forEach((panel) => {
|
|
419
|
+
panel.hidden = true;
|
|
420
|
+
});
|
|
421
|
+
this.#view = 'activity';
|
|
422
|
+
rememberView({ view: 'activity', runFocused: false });
|
|
423
|
+
root.querySelectorAll('[data-reticle-chat-view-btn]').forEach((button) => {
|
|
424
|
+
button.removeAttribute('aria-current');
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
setProjectId(projectId) {
|
|
428
|
+
this.#projectId = projectId;
|
|
429
|
+
this.#personaPick = readPick(projectId);
|
|
430
|
+
this.#paintHarness();
|
|
431
|
+
this.#paintImpactDot();
|
|
432
|
+
}
|
|
433
|
+
paintAgent(link) {
|
|
434
|
+
this.#agent.paint(link);
|
|
435
|
+
this.#paintMeta();
|
|
436
|
+
}
|
|
437
|
+
paintAccount(account) {
|
|
438
|
+
this.#account = account;
|
|
439
|
+
const nav = this.#root?.querySelector('[data-reticle-chat-view-btn="harness"]');
|
|
440
|
+
if (nav !== null && nav !== undefined)
|
|
441
|
+
nav.hidden = true !== account?.signedIn;
|
|
442
|
+
this.#paintHarness();
|
|
443
|
+
}
|
|
444
|
+
paintDrive(drive) {
|
|
445
|
+
this.#driving = drive;
|
|
446
|
+
if (drive !== undefined)
|
|
447
|
+
this.#markStarting(false);
|
|
448
|
+
else if (this.#starting === undefined)
|
|
449
|
+
this.#startedAs = undefined;
|
|
450
|
+
this.#paintHarness();
|
|
451
|
+
}
|
|
452
|
+
#markStarting(on) {
|
|
453
|
+
if (this.#starting !== undefined)
|
|
454
|
+
clearTimeout(this.#starting);
|
|
455
|
+
this.#starting = on
|
|
456
|
+
? setTimeout(() => {
|
|
457
|
+
this.#starting = undefined;
|
|
458
|
+
if (this.#driving === undefined)
|
|
459
|
+
this.#startedAs = undefined;
|
|
460
|
+
this.#paintHarness();
|
|
461
|
+
}, HARNESS_STARTING_MS)
|
|
462
|
+
: undefined;
|
|
463
|
+
if (on)
|
|
464
|
+
this.#paintHarness();
|
|
465
|
+
}
|
|
466
|
+
paintHarness(config, gate) {
|
|
467
|
+
if (config !== undefined)
|
|
468
|
+
this.#linking = false;
|
|
469
|
+
this.#harness = config;
|
|
470
|
+
this.#gate = gate;
|
|
471
|
+
this.#paintHarness();
|
|
472
|
+
}
|
|
473
|
+
paintImpact(verdicts) {
|
|
474
|
+
this.#verdicts = verdicts;
|
|
475
|
+
if (this.#impactOpen)
|
|
476
|
+
saveImpactSeen(this.#projectId, verdicts);
|
|
477
|
+
this.#paintImpactDot();
|
|
478
|
+
}
|
|
479
|
+
setImpactOpen(open) {
|
|
480
|
+
this.#impactOpen = open;
|
|
481
|
+
if (open)
|
|
482
|
+
saveImpactSeen(this.#projectId, this.#verdicts);
|
|
483
|
+
this.#paintImpactDot();
|
|
484
|
+
}
|
|
485
|
+
#paintImpactDot() {
|
|
486
|
+
const button = this.#root?.querySelector('[data-reticle-chat-impact]');
|
|
487
|
+
const dot = button?.querySelector('[data-reticle-impact-dot]');
|
|
488
|
+
if (button === undefined || null === button || dot === undefined || null === dot)
|
|
489
|
+
return;
|
|
490
|
+
const seen = this.#impactOpen ? this.#verdicts : readImpactSeen(this.#projectId);
|
|
491
|
+
const fresh = seen !== undefined && this.#verdicts > seen;
|
|
492
|
+
dot.hidden = !fresh;
|
|
493
|
+
button.setAttribute('aria-label', fresh ? IMPACT_ARIA.NEW : IMPACT_ARIA.SEEN);
|
|
494
|
+
}
|
|
495
|
+
paintAnnotations(items) {
|
|
496
|
+
this.#current = [...items];
|
|
497
|
+
const pageUrl = location.href;
|
|
498
|
+
const byId = new Map(this.#history.map((item) => [item.id, item]));
|
|
499
|
+
for (const item of items)
|
|
500
|
+
byId.set(item.id, { ...item, pageUrl });
|
|
501
|
+
this.#history = [...byId.values()]
|
|
502
|
+
.sort((a, b) => b.createdAt - a.createdAt)
|
|
503
|
+
.slice(0, HISTORY_LIMIT);
|
|
504
|
+
saveHistory(this.#history);
|
|
505
|
+
const count = this.#root?.querySelector('[data-reticle-note-count]');
|
|
506
|
+
if (count !== null && count !== undefined) {
|
|
507
|
+
count.hidden = 0 === items.length;
|
|
508
|
+
count.textContent = String(items.length);
|
|
509
|
+
}
|
|
510
|
+
this.#paintAnnotations();
|
|
511
|
+
}
|
|
512
|
+
#paintHarness() {
|
|
513
|
+
const root = this.#root;
|
|
514
|
+
const spot = root?.querySelector('[data-reticle-harness-spot]');
|
|
515
|
+
if (root === undefined || null === spot || spot === undefined)
|
|
516
|
+
return;
|
|
517
|
+
const account = this.#account;
|
|
518
|
+
const config = this.#harness;
|
|
519
|
+
spot.hidden = false;
|
|
520
|
+
const base = platformBase(config, account ?? { signedIn: false });
|
|
521
|
+
const project = this.#projectId === undefined ? '' : `&project=${encodeURIComponent(this.#projectId)}`;
|
|
522
|
+
const state = {
|
|
523
|
+
account,
|
|
524
|
+
config,
|
|
525
|
+
gate: this.#gate,
|
|
526
|
+
drive: this.#driving,
|
|
527
|
+
canDrive: this.#drive !== undefined,
|
|
528
|
+
pick: this.#personaPick,
|
|
529
|
+
startedAs: this.#startedAs,
|
|
530
|
+
setupUrl: `${base}${HARNESS_SETUP_PATH}${project}${HARNESS_SETUP_HASH}`,
|
|
531
|
+
planUrl: `${base}${HARNESS_PLAN_PATH}`,
|
|
532
|
+
linking: this.#linking,
|
|
533
|
+
starting: this.#starting !== undefined && this.#driving === undefined,
|
|
534
|
+
};
|
|
535
|
+
const foot = harnessFootHtml(state);
|
|
536
|
+
if (foot !== this.#harnessHtml) {
|
|
537
|
+
morphHtml(spot, foot);
|
|
538
|
+
this.#harnessHtml = foot;
|
|
539
|
+
}
|
|
540
|
+
if (account !== undefined && !account.signedIn && 'harness' === this.#view)
|
|
541
|
+
this.closePage();
|
|
542
|
+
const page = root.querySelector('[data-reticle-harness-page]');
|
|
543
|
+
if (page !== null) {
|
|
544
|
+
const body = harnessRowHtml(state);
|
|
545
|
+
if (body !== this.#harnessPageHtml) {
|
|
546
|
+
morphHtml(page, body);
|
|
547
|
+
this.#harnessPageHtml = body;
|
|
548
|
+
}
|
|
549
|
+
const control = this.#refocusRun ? page.querySelector(RUN_CONTROL) : null;
|
|
550
|
+
if (null !== control && 'harness' === this.#view) {
|
|
551
|
+
this.#refocusRun = false;
|
|
552
|
+
control.focus();
|
|
553
|
+
}
|
|
554
|
+
const custom = page.querySelector('[data-reticle-harness-persona]');
|
|
555
|
+
if (custom !== null && custom.value !== this.#customPersona)
|
|
556
|
+
custom.value = this.#customPersona;
|
|
557
|
+
}
|
|
558
|
+
this.#paintMeta();
|
|
559
|
+
}
|
|
560
|
+
#paintMeta() {
|
|
561
|
+
const signedIn = true === this.#account?.signedIn;
|
|
562
|
+
const pageMeta = this.#root?.querySelector('[data-reticle-harness-page-meta]');
|
|
563
|
+
if (pageMeta !== null && pageMeta !== undefined)
|
|
564
|
+
pageMeta.textContent = signedIn ? creditsShort(this.#harness?.credits) : '';
|
|
565
|
+
}
|
|
566
|
+
#visibleAnnotations() {
|
|
567
|
+
return 'history' === this.#annotationTab ? this.#history : this.#current;
|
|
568
|
+
}
|
|
569
|
+
#paintAnnotations() {
|
|
570
|
+
const root = this.#root;
|
|
571
|
+
if (root === undefined)
|
|
572
|
+
return;
|
|
573
|
+
const actions = root.querySelector('[data-reticle-current-annotation-actions]');
|
|
574
|
+
if (actions !== null)
|
|
575
|
+
actions.hidden = 'history' === this.#annotationTab;
|
|
576
|
+
root
|
|
577
|
+
.querySelectorAll('[data-reticle-annotation-tab]')
|
|
578
|
+
.forEach((button) => button.setAttribute('aria-pressed', String(button.getAttribute('data-reticle-annotation-tab') === this.#annotationTab)));
|
|
579
|
+
const list = root.querySelector('[data-reticle-annotation-list]');
|
|
580
|
+
if (null === list)
|
|
581
|
+
return;
|
|
582
|
+
list.replaceChildren();
|
|
583
|
+
const items = this.#visibleAnnotations();
|
|
584
|
+
if (0 === items.length) {
|
|
585
|
+
const empty = document.createElement('div');
|
|
586
|
+
empty.className = 'reticle-annotation-empty';
|
|
587
|
+
const title = document.createElement('strong');
|
|
588
|
+
const hint = document.createElement('span');
|
|
589
|
+
const history = 'history' === this.#annotationTab;
|
|
590
|
+
title.textContent = history ? NOTES_TEXT.HISTORY_EMPTY : NOTES_TEXT.PAGE_EMPTY;
|
|
591
|
+
hint.textContent = history ? NOTES_TEXT.HISTORY_HINT : NOTES_TEXT.PAGE_HINT;
|
|
592
|
+
empty.append(title, hint);
|
|
593
|
+
list.appendChild(empty);
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
items.forEach((item, index) => {
|
|
597
|
+
const row = document.createElement('div');
|
|
598
|
+
row.className = 'reticle-annotation-item';
|
|
599
|
+
const content = document.createElement('div');
|
|
600
|
+
content.className = 'reticle-annotation-content';
|
|
601
|
+
const note = document.createElement('strong');
|
|
602
|
+
note.textContent = item.note;
|
|
603
|
+
const where = document.createElement('span');
|
|
604
|
+
where.textContent = `${item.label} · ${item.route}${item.source === undefined ? '' : ` · ${item.source}`}`;
|
|
605
|
+
content.append(note, where);
|
|
606
|
+
const copy = document.createElement('button');
|
|
607
|
+
copy.type = 'button';
|
|
608
|
+
copy.textContent = 'Copy';
|
|
609
|
+
copy.setAttribute('data-reticle-copy-note', String(index));
|
|
610
|
+
row.append(content, copy);
|
|
611
|
+
list.appendChild(row);
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
#copyAll() {
|
|
615
|
+
const items = this.#visibleAnnotations();
|
|
616
|
+
if (items.length > 0)
|
|
617
|
+
this.#copy(items, 'history' === this.#annotationTab ? location.origin : location.href);
|
|
618
|
+
}
|
|
619
|
+
#copy(items, pageUrl) {
|
|
620
|
+
void navigator.clipboard?.writeText(marksForAgent(items, pageUrl)).catch(() => undefined);
|
|
621
|
+
}
|
|
622
|
+
}
|
|
@@ -10,6 +10,7 @@ export declare const BUSY_ON = "1";
|
|
|
10
10
|
export declare const BUSY_OFF = "0";
|
|
11
11
|
export interface PresenterOptions {
|
|
12
12
|
paceMs?: number;
|
|
13
|
+
onKill?: () => void;
|
|
13
14
|
now?: () => number;
|
|
14
15
|
idleAfterMs?: number;
|
|
15
16
|
glowFadeMs?: number;
|
|
@@ -17,6 +18,7 @@ export interface PresenterOptions {
|
|
|
17
18
|
idleNoticeMs?: number;
|
|
18
19
|
idleEndMs?: number;
|
|
19
20
|
sessionId?: string;
|
|
21
|
+
projectId?: string;
|
|
20
22
|
narrationDwellMs?: number;
|
|
21
23
|
border?: BorderMode;
|
|
22
24
|
logMax?: number;
|
|
@@ -42,6 +44,7 @@ export declare const ACT_STRIP: {
|
|
|
42
44
|
readonly STOPPED_PREFIX: "stopped · ";
|
|
43
45
|
readonly NOW: "now";
|
|
44
46
|
readonly SINCE_LAST: " since last action";
|
|
47
|
+
readonly harnessTesting: (steps: number) => string;
|
|
45
48
|
};
|
|
46
49
|
export declare const IDLE_END_MS = 300000;
|
|
47
50
|
export declare const IDLE_END_MIN_MS = 5000;
|
|
@@ -81,8 +84,8 @@ export declare const SETTINGS_BTN_ATTR = "data-reticle-settings-btn";
|
|
|
81
84
|
export declare const SETTINGS_PANEL_ATTR = "data-reticle-settings-panel";
|
|
82
85
|
export declare const SETTINGS_CLOSE_ATTR = "data-reticle-settings-close";
|
|
83
86
|
export declare const SETTING_KEY_ATTR = "data-reticle-setting";
|
|
84
|
-
export declare const SETTINGS_STORAGE_KEY
|
|
85
|
-
export declare const MINIMISED_STORAGE_KEY
|
|
87
|
+
export declare const SETTINGS_STORAGE_KEY: "reticle-presenter-settings";
|
|
88
|
+
export declare const MINIMISED_STORAGE_KEY: "reticle-presenter-minimised";
|
|
86
89
|
export declare const AMBIENT_GLOW_ATTR = "data-reticle-ambient-glow";
|
|
87
90
|
export declare const LIVENESS_ATTR = "data-reticle-live";
|
|
88
91
|
export declare const BLOCK_ATTR = "data-reticle-block";
|