@reticlehq/browser 3.6.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 +12 -0
- package/dist/actions/actions-press.d.ts +1 -0
- package/dist/actions/actions-press.js +25 -1
- package/dist/actions/actions.d.ts +1 -37
- package/dist/actions/actions.js +24 -66
- package/dist/actions/appeared-text.js +3 -0
- package/dist/actions/danger-context.d.ts +2 -0
- package/dist/actions/danger-context.js +28 -2
- 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/dom/a11y.js +251 -10
- package/dist/dom/addressing/coverage-markers.d.ts +6 -0
- package/dist/dom/addressing/coverage-markers.js +13 -0
- package/dist/dom/dom-ignore.d.ts +2 -0
- package/dist/dom/dom-ignore.js +15 -2
- package/dist/dom/query.d.ts +1 -1
- package/dist/dom/query.js +78 -16
- package/dist/dom/render-page.d.ts +12 -0
- package/dist/dom/render-page.js +135 -0
- package/dist/dom/snapshot.js +55 -7
- package/dist/observers/dom.js +32 -16
- package/dist/observers/field.js +3 -21
- package/dist/observers/network.js +56 -7
- package/dist/observers/perf.js +53 -1
- package/dist/observers/route.js +6 -5
- package/dist/presenter/carousel/carousel.js +2 -7
- package/dist/presenter/carousel/panel-slides.d.ts +2 -4
- package/dist/presenter/carousel/panel-slides.js +17 -15
- package/dist/presenter/chrome/log-memory.d.ts +1 -0
- package/dist/presenter/chrome/presenter-log.d.ts +7 -0
- package/dist/presenter/chrome/presenter-log.js +48 -8
- 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 +17 -4
- package/dist/presenter/chrome/presenter-report-copy.js +26 -4
- package/dist/presenter/hud-telemetry.js +55 -4
- package/dist/presenter/presenter-account-styles.js +3 -3
- package/dist/presenter/presenter-account.d.ts +27 -5
- package/dist/presenter/presenter-account.js +83 -6
- 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 +27 -5
- package/dist/presenter/presenter-chat-views.js +312 -72
- package/dist/presenter/presenter-config.d.ts +2 -0
- package/dist/presenter/presenter-config.js +1 -0
- package/dist/presenter/presenter-controls.d.ts +0 -1
- package/dist/presenter/presenter-controls.js +13 -91
- package/dist/presenter/presenter-design-tokens.js +1 -1
- package/dist/presenter/presenter-frame.d.ts +1 -1
- package/dist/presenter/presenter-frame.js +8 -10
- 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.js +25 -24
- package/dist/presenter/presenter-report-styles.js +40 -22
- package/dist/presenter/presenter-report.d.ts +2 -1
- package/dist/presenter/presenter-report.js +83 -17
- package/dist/presenter/presenter-settings-styles.js +8 -4
- package/dist/presenter/presenter-settings.d.ts +7 -6
- package/dist/presenter/presenter-settings.js +75 -34
- package/dist/presenter/presenter-shell-styles.js +12 -3
- package/dist/presenter/presenter-shell.d.ts +10 -4
- package/dist/presenter/presenter-shell.js +31 -23
- package/dist/presenter/presenter-styles.js +0 -2
- package/dist/presenter/presenter-workspace.js +10 -3
- package/dist/presenter/presenter.d.ts +3 -2
- package/dist/presenter/presenter.js +81 -20
- package/dist/registry/declared-platform.js +2 -0
- package/dist/reticle-inject.js +777 -700
- package/dist/reticle.js +36 -2
- package/dist/storage-keys.d.ts +3 -2
- package/dist/storage-keys.js +7 -3
- 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 +2 -2
- package/dist/presenter/carousel/offer-card.d.ts +0 -21
- package/dist/presenter/carousel/offer-card.js +0 -56
|
@@ -1,15 +1,24 @@
|
|
|
1
|
-
import { DEFAULT_PLATFORM_URL } from '@reticlehq/core';
|
|
1
|
+
import { DEFAULT_PLATFORM_URL, } from '@reticlehq/core';
|
|
2
|
+
import { PLAN_HTML } from './presenter-plan.js';
|
|
2
3
|
import { marksForAgent } from '../review/marks-for-agent.js';
|
|
3
4
|
import { ANNOTATE_BTN_ATTR, CHAT_TOGGLE_ATTR, CLEAR_MARKS_ATTR, MARKERS_BTN_ATTR, } from './presenter-config.js';
|
|
4
5
|
import { hiIconHtml, hiToggleIconHtml, PRESENTER_ICON_SIZE, PresenterIcon, } from './icons/presenter-icons.js';
|
|
5
6
|
import { HUD_GLASS_PAINT } from './chrome/presenter-hud-chrome.js';
|
|
6
|
-
import {
|
|
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';
|
|
7
9
|
import { esc, isSafeDashboardUrl } from './chrome/presenter-safe-html.js';
|
|
8
|
-
import {
|
|
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'];
|
|
9
16
|
const HISTORY_KEY = ReticleStorageKey.ANNOTATION_HISTORY;
|
|
10
17
|
const HISTORY_LIMIT = 200;
|
|
11
|
-
const HARNESS_SETUP_PATH = '/settings?group=project
|
|
18
|
+
const HARNESS_SETUP_PATH = '/settings?group=project';
|
|
19
|
+
const HARNESS_SETUP_HASH = '#model';
|
|
12
20
|
const HARNESS_PLAN_PATH = '/settings?group=billing';
|
|
21
|
+
const HARNESS_STARTING_MS = 20_000;
|
|
13
22
|
export function platformBase(config, account) {
|
|
14
23
|
const base = [config?.platformUrl, account.host].find((url) => url !== undefined && isSafeDashboardUrl(url));
|
|
15
24
|
return esc((base ?? DEFAULT_PLATFORM_URL).replace(/\/+$/, ''));
|
|
@@ -37,6 +46,21 @@ function readHistory() {
|
|
|
37
46
|
return [];
|
|
38
47
|
}
|
|
39
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
|
+
}
|
|
40
64
|
function saveHistory(items) {
|
|
41
65
|
try {
|
|
42
66
|
localStorage.setItem(HISTORY_KEY, JSON.stringify(items.slice(0, HISTORY_LIMIT)));
|
|
@@ -44,31 +68,52 @@ function saveHistory(items) {
|
|
|
44
68
|
catch {
|
|
45
69
|
}
|
|
46
70
|
}
|
|
47
|
-
export const CHAT_VIEWS_HTML =
|
|
71
|
+
export const CHAT_VIEWS_HTML = `${AGENT_LINK_HTML}
|
|
48
72
|
<div data-reticle-harness-spot class="reticle-harness-spot" hidden></div>`;
|
|
49
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>
|
|
50
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>
|
|
51
75
|
<div data-reticle-all-flows class="reticle-all-flows"></div>
|
|
52
76
|
</section>`;
|
|
53
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>`;
|
|
54
89
|
export const CHAT_VIEWS_NAV_HTML = `<nav class="reticle-chat-nav" aria-label="Reticle views">
|
|
55
|
-
<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)}</button>
|
|
56
|
-
<button type="button" data-reticle-chat-view-btn="
|
|
57
|
-
<button type="button" data-reticle-chat-view-btn="
|
|
58
|
-
<button type="button" data-reticle-chat-
|
|
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>
|
|
59
95
|
</nav>`;
|
|
60
96
|
const ANNOTATION_ACTION_ICON_SIZE = PRESENTER_ICON_SIZE.TOOLBAR;
|
|
61
97
|
const markersLabel = 'Show note markers on the page';
|
|
62
98
|
const clearLabel = 'Clear notes from this page';
|
|
63
99
|
const copyAllLabel = 'Copy all notes';
|
|
64
100
|
const NOTES_TEXT = {
|
|
101
|
+
SUBTITLE: 'Feedback for your agent',
|
|
102
|
+
SUBTITLE_FULL: 'Pin feedback on the page for your agent',
|
|
65
103
|
PAGE_EMPTY: 'No notes on this page',
|
|
66
104
|
PAGE_HINT: 'Select Add notes, then click anything on the page to pin feedback for your agent.',
|
|
67
105
|
HISTORY_EMPTY: 'No saved notes yet',
|
|
68
106
|
HISTORY_HINT: 'Notes from every page you annotate are kept here.',
|
|
69
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>`;
|
|
70
115
|
export const ANNOTATIONS_HTML = `<section data-reticle-page-panel="annotations" class="reticle-page-panel reticle-annotations-view" role="region" aria-label="Notes" hidden>
|
|
71
|
-
<div class="reticle-page-heading"><span class="reticle-page-titles"><strong>Notes</strong><span class="reticle-page-subtitle"
|
|
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>
|
|
72
117
|
<div class="reticle-annotations-tabs" role="group" aria-label="Notes lists">
|
|
73
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>
|
|
74
119
|
<div data-reticle-current-annotation-actions class="reticle-annotation-actions" aria-label="Current page note actions">
|
|
@@ -80,28 +125,32 @@ export const ANNOTATIONS_HTML = `<section data-reticle-page-panel="annotations"
|
|
|
80
125
|
<div data-reticle-annotation-list class="reticle-annotation-list"></div>
|
|
81
126
|
</section>`;
|
|
82
127
|
export const CHAT_VIEWS_CSS = `
|
|
83
|
-
|
|
84
|
-
[data-reticle-chat-panel]
|
|
85
|
-
[data-reticle-
|
|
86
|
-
|
|
87
|
-
[data-reticle-
|
|
88
|
-
[data-reticle-
|
|
89
|
-
[data-reticle-
|
|
90
|
-
[data-reticle-
|
|
91
|
-
[data-reticle-
|
|
92
|
-
[data-reticle-chat-panel] .reticle-harness-switch[aria-checked="true"]::after{transform:translateX(12px);}
|
|
93
|
-
[data-reticle-chat-panel] .reticle-harness-switch:disabled{opacity:.45;cursor:not-allowed;}
|
|
94
|
-
[data-reticle-chat-panel] .reticle-harness-link{flex:none;color:var(--reticle-hud-brand);font-size:var(--reticle-hud-size-xs);font-weight:600;text-decoration:none;white-space:nowrap;}
|
|
95
|
-
[data-reticle-chat-panel] .reticle-harness-link:hover{text-decoration:underline;}
|
|
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;}
|
|
96
137
|
[data-reticle-hud] .reticle-chat-nav{display:contents;}
|
|
97
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;}
|
|
98
139
|
[data-reticle-hud] .reticle-chat-nav button:hover{background:var(--reticle-hud-hover);color:var(--reticle-hud-text);}
|
|
99
|
-
[data-reticle-hud] .reticle-chat-nav button[data-
|
|
100
|
-
|
|
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;}
|
|
101
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;}
|
|
102
148
|
[data-reticle-hud] .reticle-chat-nav .reticle-nav-count:empty{display:none;}
|
|
103
|
-
[data-reticle-hud] .reticle-chat-nav .reticle-nav-count:not(:empty){
|
|
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;}
|
|
104
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;}
|
|
105
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;}
|
|
106
155
|
[data-reticle-page-panel][hidden]{display:none!important;}
|
|
107
156
|
[data-reticle-page-open="annotations"] [data-reticle-page-panel="annotations"],[data-reticle-page-open="flows"] [data-reticle-page-panel="flows"]{display:flex;}
|
|
@@ -110,7 +159,7 @@ export const CHAT_VIEWS_CSS = `
|
|
|
110
159
|
.reticle-page-heading strong{font-size:12px;font-weight:600;}
|
|
111
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;}
|
|
112
161
|
.reticle-page-heading button:hover{background:var(--reticle-hud-hover);color:var(--reticle-hud-text);}
|
|
113
|
-
.reticle-page-subtitle{flex:none;padding:5px 12px;border-bottom:1px solid var(--reticle-hud-border);color:var(--reticle-hud-text-muted);font-size:
|
|
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;}
|
|
114
163
|
.reticle-page-panel .reticle-all-flows,.reticle-page-panel .reticle-annotation-list{flex:1;min-height:0;overflow-y:auto;}
|
|
115
164
|
[data-reticle-page-panel="annotations"] .reticle-annotations-tabs{flex:none;}
|
|
116
165
|
[data-reticle-page-panel="annotations"] .reticle-annotation-list{flex:1;}
|
|
@@ -135,27 +184,59 @@ export const CHAT_VIEWS_CSS = `
|
|
|
135
184
|
[data-reticle-page-panel="annotations"] .reticle-annotation-content{flex:1;min-width:0;}
|
|
136
185
|
[data-reticle-page-panel="annotations"] .reticle-annotation-content strong{display:block;font-size:11px;font-weight:600;overflow-wrap:anywhere;}
|
|
137
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;}
|
|
138
|
-
[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:
|
|
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;}
|
|
139
188
|
[data-reticle-page-panel="annotations"] .reticle-annotation-item button:hover{color:#fff;background:rgba(255,255,255,.1);}
|
|
140
|
-
`;
|
|
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
|
+
}
|
|
141
209
|
export class ChatViews {
|
|
142
210
|
#root;
|
|
143
|
-
#view =
|
|
211
|
+
#view = readViewMemory().view;
|
|
212
|
+
#refocusRun = readViewMemory().runFocused;
|
|
213
|
+
#runFocused = false;
|
|
144
214
|
#annotationTab = 'current';
|
|
145
215
|
#current = [];
|
|
146
216
|
#history = readHistory();
|
|
147
217
|
#account;
|
|
148
218
|
#harness;
|
|
149
|
-
#
|
|
219
|
+
#gate;
|
|
150
220
|
#verdicts = 0;
|
|
151
|
-
#
|
|
221
|
+
#impactOpen = false;
|
|
152
222
|
#onImpact;
|
|
153
223
|
#onOpenChat;
|
|
154
224
|
#listeners;
|
|
155
|
-
|
|
156
|
-
|
|
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) {
|
|
157
237
|
this.#onImpact = onImpact;
|
|
158
238
|
this.#onOpenChat = onOpenChat;
|
|
239
|
+
this.#drive = drive;
|
|
159
240
|
}
|
|
160
241
|
mount(root) {
|
|
161
242
|
this.#root = root;
|
|
@@ -169,20 +250,85 @@ export class ChatViews {
|
|
|
169
250
|
root
|
|
170
251
|
.querySelector('[data-reticle-chat-impact]')
|
|
171
252
|
?.addEventListener('click', () => this.#onImpact(), { signal });
|
|
172
|
-
|
|
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) => {
|
|
173
316
|
const target = event.target;
|
|
174
|
-
if (!(target instanceof
|
|
175
|
-
null === target.closest('[data-reticle-harness-switch]'))
|
|
317
|
+
if (!(target instanceof HTMLSelectElement))
|
|
176
318
|
return;
|
|
177
|
-
const
|
|
178
|
-
if (
|
|
319
|
+
const pick = knownPick(target.value);
|
|
320
|
+
if (pick === undefined)
|
|
179
321
|
return;
|
|
180
|
-
|
|
181
|
-
this.#
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
this.#onHarness(enabled);
|
|
322
|
+
this.#personaPick = pick;
|
|
323
|
+
savePick(this.#projectId, pick);
|
|
324
|
+
this.#paintHarness();
|
|
325
|
+
this.#root?.querySelector(`#${PERSONA_PICK_ID}`)?.focus();
|
|
185
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);
|
|
186
332
|
root.querySelectorAll('[data-reticle-annotation-tab]').forEach((button) => button.addEventListener('click', () => {
|
|
187
333
|
this.#annotationTab =
|
|
188
334
|
'history' === button.getAttribute('data-reticle-annotation-tab')
|
|
@@ -214,20 +360,36 @@ export class ChatViews {
|
|
|
214
360
|
if (item !== undefined)
|
|
215
361
|
this.#copy([item], 'pageUrl' in item ? item.pageUrl : location.href);
|
|
216
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 });
|
|
217
368
|
this.open(this.#view);
|
|
218
369
|
this.#paintHarness();
|
|
219
370
|
this.paintImpact(this.#verdicts);
|
|
220
371
|
this.#paintAnnotations();
|
|
221
372
|
}
|
|
222
373
|
teardown() {
|
|
374
|
+
this.#markStarting(false);
|
|
223
375
|
this.#listeners?.abort();
|
|
224
376
|
this.#listeners = undefined;
|
|
225
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 });
|
|
226
387
|
}
|
|
227
388
|
open(view) {
|
|
228
|
-
if (view !== 'activity' && view
|
|
389
|
+
if (view !== 'activity' && !PAGE_VIEWS.includes(view))
|
|
229
390
|
return;
|
|
230
391
|
this.#view = view;
|
|
392
|
+
rememberView({ view, runFocused: this.#runFocused });
|
|
231
393
|
const root = this.#root;
|
|
232
394
|
if (root === undefined)
|
|
233
395
|
return;
|
|
@@ -257,24 +419,78 @@ export class ChatViews {
|
|
|
257
419
|
panel.hidden = true;
|
|
258
420
|
});
|
|
259
421
|
this.#view = 'activity';
|
|
422
|
+
rememberView({ view: 'activity', runFocused: false });
|
|
260
423
|
root.querySelectorAll('[data-reticle-chat-view-btn]').forEach((button) => {
|
|
261
424
|
button.removeAttribute('aria-current');
|
|
262
425
|
});
|
|
263
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
|
+
}
|
|
264
437
|
paintAccount(account) {
|
|
265
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;
|
|
266
442
|
this.#paintHarness();
|
|
267
443
|
}
|
|
268
|
-
|
|
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;
|
|
269
469
|
this.#harness = config;
|
|
270
|
-
this.#
|
|
470
|
+
this.#gate = gate;
|
|
271
471
|
this.#paintHarness();
|
|
272
472
|
}
|
|
273
473
|
paintImpact(verdicts) {
|
|
274
474
|
this.#verdicts = verdicts;
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
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);
|
|
278
494
|
}
|
|
279
495
|
paintAnnotations(items) {
|
|
280
496
|
this.#current = [...items];
|
|
@@ -294,34 +510,58 @@ export class ChatViews {
|
|
|
294
510
|
this.#paintAnnotations();
|
|
295
511
|
}
|
|
296
512
|
#paintHarness() {
|
|
297
|
-
const
|
|
298
|
-
|
|
513
|
+
const root = this.#root;
|
|
514
|
+
const spot = root?.querySelector('[data-reticle-harness-spot]');
|
|
515
|
+
if (root === undefined || null === spot || spot === undefined)
|
|
299
516
|
return;
|
|
300
517
|
const account = this.#account;
|
|
301
518
|
const config = this.#harness;
|
|
302
|
-
if (account === undefined || !account.signedIn) {
|
|
303
|
-
spot.hidden = true;
|
|
304
|
-
return;
|
|
305
|
-
}
|
|
306
519
|
spot.hidden = false;
|
|
307
|
-
const base = platformBase(config, account);
|
|
308
|
-
const
|
|
309
|
-
const
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
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;
|
|
315
539
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
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;
|
|
324
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) : '';
|
|
325
565
|
}
|
|
326
566
|
#visibleAnnotations() {
|
|
327
567
|
return 'history' === this.#annotationTab ? this.#history : this.#current;
|
|
@@ -18,6 +18,7 @@ export interface PresenterOptions {
|
|
|
18
18
|
idleNoticeMs?: number;
|
|
19
19
|
idleEndMs?: number;
|
|
20
20
|
sessionId?: string;
|
|
21
|
+
projectId?: string;
|
|
21
22
|
narrationDwellMs?: number;
|
|
22
23
|
border?: BorderMode;
|
|
23
24
|
logMax?: number;
|
|
@@ -43,6 +44,7 @@ export declare const ACT_STRIP: {
|
|
|
43
44
|
readonly STOPPED_PREFIX: "stopped · ";
|
|
44
45
|
readonly NOW: "now";
|
|
45
46
|
readonly SINCE_LAST: " since last action";
|
|
47
|
+
readonly harnessTesting: (steps: number) => string;
|
|
46
48
|
};
|
|
47
49
|
export declare const IDLE_END_MS = 300000;
|
|
48
50
|
export declare const IDLE_END_MIN_MS = 5000;
|
|
@@ -25,6 +25,7 @@ export const ACT_STRIP = {
|
|
|
25
25
|
STOPPED_PREFIX: 'stopped · ',
|
|
26
26
|
NOW: 'now',
|
|
27
27
|
SINCE_LAST: ' since last action',
|
|
28
|
+
harnessTesting: (steps) => `Testing · Harness · ${String(steps)} step${1 === steps ? '' : 's'}`,
|
|
28
29
|
};
|
|
29
30
|
export const IDLE_END_MS = 300_000;
|
|
30
31
|
export const IDLE_END_MIN_MS = 5_000;
|
|
@@ -6,7 +6,6 @@ export declare const CONTROLS_CSS: string;
|
|
|
6
6
|
export declare const CONTROLS_STATUS_HTML: string;
|
|
7
7
|
export declare const CONTROLS_BANNER_HTML = "<div data-reticle-banner class=\"reticle-banner\">Session ended</div>";
|
|
8
8
|
export declare const CONTROLS_MARKS_HTML: string;
|
|
9
|
-
export declare const CONTROLS_FLOWS_HTML: string;
|
|
10
9
|
export declare const CONTROLS_FOOT_HTML: string;
|
|
11
10
|
interface ControlPanelHost {
|
|
12
11
|
emit: (kind: HumanControlKind, text?: string) => void;
|