@reticlehq/browser 3.7.0 → 3.8.1
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 +10 -0
- package/dist/actions/action-report.js +59 -14
- package/dist/actions/actions-dom.d.ts +4 -0
- package/dist/actions/actions-dom.js +20 -4
- package/dist/actions/actions.d.ts +1 -0
- package/dist/actions/actions.js +94 -46
- package/dist/actions/appeared-text.js +2 -2
- package/dist/actions/click-target.d.ts +1 -0
- package/dist/actions/click-target.js +14 -0
- package/dist/actions/danger-context.d.ts +2 -1
- package/dist/actions/danger-context.js +43 -17
- package/dist/actions/scroll.d.ts +2 -0
- package/dist/actions/scroll.js +10 -2
- package/dist/activate.d.ts +14 -0
- package/dist/activate.js +43 -0
- package/dist/busy.d.ts +3 -0
- package/dist/busy.js +42 -0
- package/dist/commands/commands.js +45 -17
- package/dist/connect-options.d.ts +12 -1
- package/dist/connect-options.js +18 -1
- package/dist/dom/a11y.d.ts +0 -2
- package/dist/dom/a11y.js +103 -363
- package/dist/dom/chart.d.ts +3 -2
- package/dist/dom/chart.js +3 -2
- package/dist/dom/dom-ignore.d.ts +6 -0
- package/dist/dom/dom-ignore.js +60 -5
- package/dist/dom/layout-audit.d.ts +15 -0
- package/dist/dom/layout-audit.js +208 -0
- package/dist/dom/paint-context.d.ts +15 -0
- package/dist/dom/paint-context.js +78 -0
- package/dist/dom/query-finders.d.ts +6 -0
- package/dist/dom/query-finders.js +216 -0
- package/dist/dom/query.d.ts +1 -1
- package/dist/dom/query.js +154 -227
- package/dist/dom/shadow-registry.d.ts +1 -0
- package/dist/dom/shadow-registry.js +27 -0
- package/dist/dom/snapshot.d.ts +5 -0
- package/dist/dom/snapshot.js +87 -35
- package/dist/dom/stable-selector.d.ts +1 -0
- package/dist/dom/stable-selector.js +19 -0
- package/dist/dom/text-match.d.ts +12 -0
- package/dist/dom/text-match.js +115 -0
- package/dist/dom/theme.d.ts +1 -0
- package/dist/dom/theme.js +21 -9
- package/dist/dom/virtualized.js +5 -1
- package/dist/dom/visibility.d.ts +7 -0
- package/dist/dom/visibility.js +322 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +7 -1
- package/dist/observers/blind-spots.js +3 -2
- package/dist/observers/canvas.d.ts +18 -0
- package/dist/observers/canvas.js +76 -0
- package/dist/observers/dom.js +68 -19
- package/dist/observers/field.d.ts +11 -0
- package/dist/observers/field.js +117 -13
- package/dist/observers/install-all.js +4 -0
- package/dist/observers/media.d.ts +2 -0
- package/dist/observers/media.js +32 -0
- package/dist/observers/net-detail/network-body.d.ts +2 -0
- package/dist/observers/net-detail/network-body.js +36 -9
- package/dist/observers/net-detail/network-event-stream.d.ts +5 -0
- package/dist/observers/net-detail/network-event-stream.js +55 -0
- package/dist/observers/net-detail/network-frames.d.ts +2 -0
- package/dist/observers/net-detail/network-frames.js +39 -0
- package/dist/observers/net-detail/network-response-body.d.ts +3 -0
- package/dist/observers/net-detail/network-response-body.js +97 -0
- package/dist/observers/network.js +111 -101
- package/dist/observers/route.d.ts +2 -0
- package/dist/observers/route.js +33 -4
- package/dist/presenter/chrome/presenter-report-copy.d.ts +0 -5
- package/dist/presenter/chrome/presenter-report-copy.js +0 -14
- package/dist/presenter/hud-telemetry.js +1 -1
- package/dist/presenter/presenter-chat-views.d.ts +3 -4
- package/dist/presenter/presenter-chat-views.js +47 -20
- package/dist/presenter/presenter-config.d.ts +1 -0
- package/dist/presenter/presenter-config.js +1 -0
- package/dist/presenter/presenter-frame.d.ts +3 -2
- package/dist/presenter/presenter-frame.js +24 -15
- package/dist/presenter/presenter-harness-row.d.ts +4 -15
- package/dist/presenter/presenter-harness-row.js +11 -50
- package/dist/presenter/presenter-report-styles.js +0 -17
- package/dist/presenter/presenter-report.d.ts +1 -2
- package/dist/presenter/presenter-report.js +4 -54
- package/dist/presenter/presenter-run-state.js +2 -1
- package/dist/presenter/presenter-settings.d.ts +2 -3
- package/dist/presenter/presenter-settings.js +14 -17
- package/dist/presenter/presenter-shell.d.ts +6 -4
- package/dist/presenter/presenter-shell.js +37 -7
- package/dist/presenter/presenter.js +32 -11
- package/dist/registry/store-adapters.d.ts +5 -2
- package/dist/registry/store-adapters.js +40 -10
- package/dist/reticle-inject.js +700 -645
- package/dist/reticle.d.ts +4 -2
- package/dist/reticle.js +36 -6
- package/dist/security/page-location.d.ts +2 -0
- package/dist/security/page-location.js +7 -0
- package/dist/security/serialization.js +1 -1
- package/dist/storage-keys.d.ts +1 -0
- package/dist/storage-keys.js +1 -0
- package/dist/timers/native/native-timers.d.ts +1 -0
- package/dist/timers/native/native-timers.js +5 -0
- package/dist/transport/transport.d.ts +1 -0
- package/dist/transport/transport.js +18 -0
- package/package.json +6 -2
|
@@ -5,7 +5,7 @@ import { ANNOTATE_BTN_ATTR, CHAT_TOGGLE_ATTR, CLEAR_MARKS_ATTR, MARKERS_BTN_ATTR
|
|
|
5
5
|
import { hiIconHtml, hiToggleIconHtml, PRESENTER_ICON_SIZE, PresenterIcon, } from './icons/presenter-icons.js';
|
|
6
6
|
import { HUD_GLASS_PAINT } from './chrome/presenter-hud-chrome.js';
|
|
7
7
|
import { LAST_ACTOR_ATTR, LOG_ACTOR } from './chrome/presenter-log.js';
|
|
8
|
-
import {
|
|
8
|
+
import { 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
9
|
import { esc, isSafeDashboardUrl } from './chrome/presenter-safe-html.js';
|
|
10
10
|
import { morphHtml } from './chrome/presenter-morph.js';
|
|
11
11
|
import { IMPACT_SEEN_KEY_PREFIX, ReticleStorageKey } from '../storage-keys.js';
|
|
@@ -20,9 +20,19 @@ const HARNESS_SETUP_HASH = '#model';
|
|
|
20
20
|
const HARNESS_PLAN_PATH = '/settings?group=billing';
|
|
21
21
|
const HARNESS_STARTING_MS = 20_000;
|
|
22
22
|
export function platformBase(config, account) {
|
|
23
|
-
const base = [config?.platformUrl, account.host].find((url) => url !== undefined && isSafeDashboardUrl(url));
|
|
23
|
+
const base = [consoleOrigin(config?.planUrl), config?.platformUrl, account.host].find((url) => url !== undefined && isSafeDashboardUrl(url));
|
|
24
24
|
return esc((base ?? DEFAULT_PLATFORM_URL).replace(/\/+$/, ''));
|
|
25
25
|
}
|
|
26
|
+
function consoleOrigin(planUrl) {
|
|
27
|
+
if (planUrl === undefined || !isSafeDashboardUrl(planUrl))
|
|
28
|
+
return undefined;
|
|
29
|
+
try {
|
|
30
|
+
return new URL(planUrl).origin;
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
26
36
|
function isHistoricalAnnotation(item) {
|
|
27
37
|
if ('object' !== typeof item || null === item)
|
|
28
38
|
return false;
|
|
@@ -216,7 +226,6 @@ export class ChatViews {
|
|
|
216
226
|
#history = readHistory();
|
|
217
227
|
#account;
|
|
218
228
|
#harness;
|
|
219
|
-
#gate;
|
|
220
229
|
#verdicts = 0;
|
|
221
230
|
#impactOpen = false;
|
|
222
231
|
#onImpact;
|
|
@@ -230,9 +239,13 @@ export class ChatViews {
|
|
|
230
239
|
#harnessHtml = '';
|
|
231
240
|
#harnessPageHtml = '';
|
|
232
241
|
#linking = false;
|
|
242
|
+
#linkTimer;
|
|
233
243
|
#agent = new AgentLinkView();
|
|
234
244
|
#startedAs;
|
|
245
|
+
#last;
|
|
235
246
|
#starting;
|
|
247
|
+
#lastSeq;
|
|
248
|
+
#pressedAfter;
|
|
236
249
|
constructor(onImpact, onOpenChat, drive) {
|
|
237
250
|
this.#onImpact = onImpact;
|
|
238
251
|
this.#onOpenChat = onOpenChat;
|
|
@@ -275,6 +288,13 @@ export class ChatViews {
|
|
|
275
288
|
if (linkButton.disabled)
|
|
276
289
|
return;
|
|
277
290
|
this.#linking = true;
|
|
291
|
+
if (this.#linkTimer !== undefined)
|
|
292
|
+
clearTimeout(this.#linkTimer);
|
|
293
|
+
this.#linkTimer = setTimeout(() => {
|
|
294
|
+
this.#linkTimer = undefined;
|
|
295
|
+
this.#linking = false;
|
|
296
|
+
this.#paintHarness();
|
|
297
|
+
}, HARNESS_STARTING_MS);
|
|
278
298
|
this.#drive?.link();
|
|
279
299
|
this.#paintHarness();
|
|
280
300
|
return;
|
|
@@ -284,6 +304,7 @@ export class ChatViews {
|
|
|
284
304
|
if (run.disabled)
|
|
285
305
|
return;
|
|
286
306
|
this.#startedAs = this.#personaPick;
|
|
307
|
+
this.#pressedAfter = this.#lastSeq;
|
|
287
308
|
this.#markStarting(true);
|
|
288
309
|
this.#drive?.run(personaText(this.#personaPick, this.#customPersona));
|
|
289
310
|
return;
|
|
@@ -292,15 +313,6 @@ export class ChatViews {
|
|
|
292
313
|
this.#drive?.stop();
|
|
293
314
|
return;
|
|
294
315
|
}
|
|
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
316
|
};
|
|
305
317
|
root
|
|
306
318
|
.querySelector('[data-reticle-harness-spot]')
|
|
@@ -441,11 +453,21 @@ export class ChatViews {
|
|
|
441
453
|
nav.hidden = true !== account?.signedIn;
|
|
442
454
|
this.#paintHarness();
|
|
443
455
|
}
|
|
444
|
-
paintDrive(drive) {
|
|
456
|
+
paintDrive(drive, last) {
|
|
445
457
|
this.#driving = drive;
|
|
446
|
-
|
|
458
|
+
const runUrl = last?.runUrl !== undefined && isSafeDashboardUrl(last.runUrl) ? esc(last.runUrl) : undefined;
|
|
459
|
+
this.#last =
|
|
460
|
+
last === undefined
|
|
461
|
+
? undefined
|
|
462
|
+
: {
|
|
463
|
+
...(runUrl === undefined ? {} : { runUrl }),
|
|
464
|
+
...(last.said === undefined ? {} : { said: last.said }),
|
|
465
|
+
};
|
|
466
|
+
this.#lastSeq = last?.seq;
|
|
467
|
+
const answered = last?.seq !== undefined && last.seq !== this.#pressedAfter && this.#starting !== undefined;
|
|
468
|
+
if (drive !== undefined || answered)
|
|
447
469
|
this.#markStarting(false);
|
|
448
|
-
|
|
470
|
+
if (drive === undefined && this.#starting === undefined)
|
|
449
471
|
this.#startedAs = undefined;
|
|
450
472
|
this.#paintHarness();
|
|
451
473
|
}
|
|
@@ -463,11 +485,14 @@ export class ChatViews {
|
|
|
463
485
|
if (on)
|
|
464
486
|
this.#paintHarness();
|
|
465
487
|
}
|
|
466
|
-
paintHarness(config
|
|
467
|
-
if (config !== undefined)
|
|
488
|
+
paintHarness(config) {
|
|
489
|
+
if (config !== undefined) {
|
|
468
490
|
this.#linking = false;
|
|
491
|
+
if (this.#linkTimer !== undefined)
|
|
492
|
+
clearTimeout(this.#linkTimer);
|
|
493
|
+
this.#linkTimer = undefined;
|
|
494
|
+
}
|
|
469
495
|
this.#harness = config;
|
|
470
|
-
this.#gate = gate;
|
|
471
496
|
this.#paintHarness();
|
|
472
497
|
}
|
|
473
498
|
paintImpact(verdicts) {
|
|
@@ -522,15 +547,17 @@ export class ChatViews {
|
|
|
522
547
|
const state = {
|
|
523
548
|
account,
|
|
524
549
|
config,
|
|
525
|
-
gate: this.#gate,
|
|
526
550
|
drive: this.#driving,
|
|
527
551
|
canDrive: this.#drive !== undefined,
|
|
528
552
|
pick: this.#personaPick,
|
|
529
553
|
startedAs: this.#startedAs,
|
|
530
554
|
setupUrl: `${base}${HARNESS_SETUP_PATH}${project}${HARNESS_SETUP_HASH}`,
|
|
531
|
-
planUrl:
|
|
555
|
+
planUrl: config?.planUrl !== undefined && isSafeDashboardUrl(config.planUrl)
|
|
556
|
+
? esc(config.planUrl)
|
|
557
|
+
: `${base}${HARNESS_PLAN_PATH}`,
|
|
532
558
|
linking: this.#linking,
|
|
533
559
|
starting: this.#starting !== undefined && this.#driving === undefined,
|
|
560
|
+
...(this.#last === undefined ? {} : { last: this.#last }),
|
|
534
561
|
};
|
|
535
562
|
const foot = harnessFootHtml(state);
|
|
536
563
|
if (foot !== this.#harnessHtml) {
|
|
@@ -86,6 +86,7 @@ export declare const SETTINGS_CLOSE_ATTR = "data-reticle-settings-close";
|
|
|
86
86
|
export declare const SETTING_KEY_ATTR = "data-reticle-setting";
|
|
87
87
|
export declare const SETTINGS_STORAGE_KEY: "reticle-presenter-settings";
|
|
88
88
|
export declare const MINIMISED_STORAGE_KEY: "reticle-presenter-minimised";
|
|
89
|
+
export declare const OPEN_STORAGE_KEY: "reticle-presenter-open";
|
|
89
90
|
export declare const AMBIENT_GLOW_ATTR = "data-reticle-ambient-glow";
|
|
90
91
|
export declare const LIVENESS_ATTR = "data-reticle-live";
|
|
91
92
|
export declare const BLOCK_ATTR = "data-reticle-block";
|
|
@@ -64,6 +64,7 @@ export const SETTINGS_CLOSE_ATTR = 'data-reticle-settings-close';
|
|
|
64
64
|
export const SETTING_KEY_ATTR = 'data-reticle-setting';
|
|
65
65
|
export const SETTINGS_STORAGE_KEY = ReticleStorageKey.PRESENTER_SETTINGS;
|
|
66
66
|
export const MINIMISED_STORAGE_KEY = ReticleStorageKey.PRESENTER_MINIMISED;
|
|
67
|
+
export const OPEN_STORAGE_KEY = ReticleStorageKey.PRESENTER_OPEN;
|
|
67
68
|
export const AMBIENT_GLOW_ATTR = 'data-reticle-ambient-glow';
|
|
68
69
|
export const LIVENESS_ATTR = 'data-reticle-live';
|
|
69
70
|
export const BLOCK_ATTR = 'data-reticle-block';
|
|
@@ -4,9 +4,10 @@ export declare const RAIL_SIGNIN_ATTR = "data-reticle-rail-signin";
|
|
|
4
4
|
export declare const RAIL_PROMO_ATTR = "data-reticle-rail-promo";
|
|
5
5
|
export declare const RAIL_TEXT: {
|
|
6
6
|
readonly TITLE: "Sign in to try Reticle Harness";
|
|
7
|
-
readonly DETAIL: "Free
|
|
7
|
+
readonly DETAIL: "Free credits to start.";
|
|
8
8
|
readonly CTA: "Sign in";
|
|
9
9
|
};
|
|
10
|
-
export declare const
|
|
10
|
+
export declare const RAIL_SIGNIN_HTML: string;
|
|
11
|
+
export declare const RAIL_HTML = "<div data-reticle-rail class=\"reticle-rail\" role=\"complementary\" aria-label=\"Reticle\">\n <div data-reticle-rail-promo class=\"reticle-rail-promo\"></div>\n</div>";
|
|
11
12
|
export declare function paintRail(root: HTMLElement, account: AccountState | undefined): void;
|
|
12
13
|
export declare const FRAME_CSS: string;
|
|
@@ -9,24 +9,25 @@ const PAGE_PANEL_ATTR = 'data-reticle-page-panel';
|
|
|
9
9
|
const OVERLAY = 'data-reticle-overlay';
|
|
10
10
|
export const RAIL_TEXT = {
|
|
11
11
|
TITLE: 'Sign in to try Reticle Harness',
|
|
12
|
-
DETAIL: 'Free
|
|
12
|
+
DETAIL: 'Free credits to start.',
|
|
13
13
|
CTA: 'Sign in',
|
|
14
14
|
};
|
|
15
|
-
export const
|
|
16
|
-
<div ${RAIL_SIGNIN_ATTR} class="reticle-rail-signin" hidden>
|
|
15
|
+
export const RAIL_SIGNIN_HTML = `<div ${RAIL_SIGNIN_ATTR} class="reticle-rail-signin" hidden>
|
|
17
16
|
<span class="reticle-rail-copy"><strong>${RAIL_TEXT.TITLE}</strong><span>${RAIL_TEXT.DETAIL}</span></span>
|
|
18
17
|
<button type="button" ${ACCOUNT_SIGNIN_ATTR} class="reticle-rail-cta" title="${ACCOUNT_TEXT.SIGNIN_TITLE}">${RAIL_TEXT.CTA}</button>
|
|
19
|
-
</div
|
|
18
|
+
</div>`;
|
|
19
|
+
export const RAIL_HTML = `<div ${RAIL_ATTR} class="reticle-rail" role="complementary" aria-label="Reticle">
|
|
20
20
|
<div ${RAIL_PROMO_ATTR} class="reticle-rail-promo"></div>
|
|
21
21
|
</div>`;
|
|
22
22
|
export function paintRail(root, account) {
|
|
23
23
|
const signin = root.querySelector(`[${RAIL_SIGNIN_ATTR}]`);
|
|
24
|
-
const
|
|
24
|
+
const rail = root.querySelector(`[${RAIL_ATTR}]`);
|
|
25
25
|
const signedOut = account !== undefined && !account.signedIn;
|
|
26
26
|
if (signin !== null)
|
|
27
27
|
signin.hidden = !signedOut;
|
|
28
|
-
if (
|
|
29
|
-
|
|
28
|
+
if (rail !== null) {
|
|
29
|
+
rail.hidden = signedOut;
|
|
30
|
+
}
|
|
30
31
|
}
|
|
31
32
|
const PAGES = `:is([${CHAT_PANEL_ATTR}],[${PAGE_PANEL_ATTR}],[${REPORT_PANEL_ATTR}],[${SETTINGS_PANEL_ATTR}])`;
|
|
32
33
|
const ANY_OPEN = `[${OVERLAY}][${MIN_ATTR}="0"]:is([${CHAT_ATTR}="1"],[${PAGE_OPEN_ATTR}],[${REPORT_ATTR}="1"],[${SETTINGS_ATTR}="1"])`;
|
|
@@ -158,18 +159,26 @@ ${BELOW} ${PAGES}{bottom:auto;top:calc(100% + 8px + var(--reticle-rail-h) + var(
|
|
|
158
159
|
pointer-events:auto;}
|
|
159
160
|
${BELOW} [${RAIL_ATTR}]{bottom:auto;top:calc(100% + 8px);}
|
|
160
161
|
${ANY_OPEN} [${RAIL_ATTR}]{display:flex;}
|
|
162
|
+
${ANY_OPEN} [${RAIL_ATTR}][hidden]{display:none;}
|
|
163
|
+
/* No rail, no gap for it: the page sits straight above the toolbar. */
|
|
164
|
+
[${DOCK_ATTR}]:has(> [${RAIL_ATTR}][hidden]){--reticle-rail-h:0px;--reticle-frame-gap:0px;}
|
|
161
165
|
/* The capsule and the rail share a slot: the capsule is for "nothing open", the rail for "a page is". */
|
|
162
166
|
${ANY_OPEN} [${CHAT_PILL_ATTR}]{display:none !important;}
|
|
163
167
|
[${RAIL_ATTR}] > [hidden]{display:none !important;}
|
|
164
|
-
[${RAIL_ATTR}] .reticle-rail-
|
|
165
|
-
|
|
166
|
-
[${
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
168
|
+
[${RAIL_ATTR}] .reticle-rail-promo{flex:1;min-width:0;}
|
|
169
|
+
/* The sign-in ask: one row in the Agent Log, above its footer. */
|
|
170
|
+
[${RAIL_SIGNIN_ATTR}]{display:flex;flex:none;align-items:center;gap:var(--reticle-hud-space-3);
|
|
171
|
+
margin:0 var(--reticle-hud-space-3) var(--reticle-hud-space-2);padding:var(--reticle-hud-space-2) var(--reticle-hud-space-3);
|
|
172
|
+
border:1px solid color-mix(in srgb,var(--reticle-hud-brand) 30%,var(--reticle-hud-border));border-radius:var(--reticle-hud-radius-md);
|
|
173
|
+
background:linear-gradient(135deg,var(--reticle-hud-brand-soft),transparent 65%);}
|
|
174
|
+
[${RAIL_SIGNIN_ATTR}][hidden]{display:none;}
|
|
175
|
+
[${RAIL_SIGNIN_ATTR}] .reticle-rail-copy{display:flex;flex:1;min-width:0;flex-direction:column;line-height:1.3;}
|
|
176
|
+
[${RAIL_SIGNIN_ATTR}] .reticle-rail-copy strong{font-size:var(--reticle-hud-size-sm);font-weight:600;}
|
|
177
|
+
[${RAIL_SIGNIN_ATTR}] .reticle-rail-copy span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--reticle-hud-size-xs);color:var(--reticle-hud-text-muted);}
|
|
178
|
+
[${RAIL_SIGNIN_ATTR}] .reticle-rail-cta{flex:none;height:28px;padding:0 var(--reticle-hud-space-3);border:0;border-radius:var(--reticle-hud-radius-pill);
|
|
170
179
|
background:var(--reticle-hud-brand);color:#160b02;font:inherit;font-size:var(--reticle-hud-size-sm);font-weight:700;cursor:pointer;}
|
|
171
|
-
[${
|
|
172
|
-
[${
|
|
180
|
+
[${RAIL_SIGNIN_ATTR}] .reticle-rail-cta:hover{filter:brightness(1.08);}
|
|
181
|
+
[${RAIL_SIGNIN_ATTR}] .reticle-rail-cta:focus-visible{outline:2px solid var(--reticle-hud-text);outline-offset:2px;}
|
|
173
182
|
/* The promo: one line of copy, its link, and dots. The carousel draws no frame of its own here. */
|
|
174
183
|
[${RAIL_ATTR}] .reticle-carousel{margin:0;padding:0;border:0;background:none;}
|
|
175
184
|
[${RAIL_ATTR}] .reticle-carousel-track{height:32px;overflow:hidden;}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type AccountState, type HarnessConfig, type HarnessDrive } from '@reticlehq/core';
|
|
1
|
+
import { type AccountState, type HarnessConfig, type HarnessDrive, type LastDrive } from '@reticlehq/core';
|
|
2
2
|
import { type Credits } from '@reticlehq/core/hud';
|
|
3
3
|
export declare const HARNESS_ROW_TEXT: {
|
|
4
4
|
readonly RUN: "Run Harness";
|
|
@@ -10,13 +10,10 @@ export declare const HARNESS_ROW_TEXT: {
|
|
|
10
10
|
readonly LINK: "Link this project";
|
|
11
11
|
readonly LINKING: "Linking…";
|
|
12
12
|
readonly NOT_ENTITLED: "Harness is not on your plan";
|
|
13
|
-
readonly NO_CREDITS: "No
|
|
13
|
+
readonly NO_CREDITS: "No credits left";
|
|
14
14
|
readonly NO_PROVIDER: "No model provider set";
|
|
15
15
|
readonly OFF: "Harness is off";
|
|
16
|
-
readonly canSwitchOn: (percent: number) => string;
|
|
17
16
|
readonly TURN_ON: "Switch on";
|
|
18
|
-
readonly COPY_PROMPT: "Copy setup prompt";
|
|
19
|
-
readonly COPIED: "Copied";
|
|
20
17
|
readonly SET_UP: "Set up ↗";
|
|
21
18
|
readonly PLANS: "See plans ↗";
|
|
22
19
|
readonly PLAN: "Plan ↗";
|
|
@@ -29,29 +26,20 @@ export declare const HARNESS_ROW_TEXT: {
|
|
|
29
26
|
readonly FOOT_NO_CREDITS: "No credits";
|
|
30
27
|
readonly FOOT_NOT_ENTITLED: "Not on your plan";
|
|
31
28
|
readonly FOOT_NO_PROVIDER: "No model provider";
|
|
32
|
-
readonly footSetup: (percent: number) => string;
|
|
33
29
|
readonly PAGE_TITLE: "Reticle Harness";
|
|
34
30
|
readonly LOG_LABEL: "What the Harness did";
|
|
35
31
|
readonly LOG_EMPTY: "Runs show here, step by step.";
|
|
36
32
|
readonly PAGE_SUBTITLE: "Tests your app by itself";
|
|
33
|
+
readonly RESULT: "See the result ↗";
|
|
37
34
|
};
|
|
38
35
|
export declare const HARNESS_SWITCH_ON_ATTR = "data-reticle-harness-switch";
|
|
39
36
|
export declare const HARNESS_LINK_ATTR = "data-reticle-harness-link";
|
|
40
37
|
export declare const HARNESS_OPEN_ATTR = "data-reticle-harness-open";
|
|
41
38
|
export declare const HARNESS_LOG_ATTR = "data-reticle-harness-log";
|
|
42
39
|
export declare const HARNESS_TOGGLE_ATTR = "data-reticle-harness-toggle";
|
|
43
|
-
export declare const HARNESS_COPY_PROMPT_ATTR = "data-reticle-harness-copy-prompt";
|
|
44
|
-
export interface HarnessGateView {
|
|
45
|
-
percent: number;
|
|
46
|
-
unlocked: boolean;
|
|
47
|
-
reason?: string;
|
|
48
|
-
prompt?: string;
|
|
49
|
-
}
|
|
50
|
-
export declare function harnessGateIn(instrumentation: Readonly<Record<string, unknown>> | undefined, config?: HarnessConfig): HarnessGateView | undefined;
|
|
51
40
|
export interface HarnessRowState {
|
|
52
41
|
account: AccountState | undefined;
|
|
53
42
|
config: HarnessConfig | undefined;
|
|
54
|
-
gate?: HarnessGateView | undefined;
|
|
55
43
|
drive: HarnessDrive | undefined;
|
|
56
44
|
canDrive: boolean;
|
|
57
45
|
pick: string;
|
|
@@ -60,6 +48,7 @@ export interface HarnessRowState {
|
|
|
60
48
|
planUrl: string;
|
|
61
49
|
linking?: boolean;
|
|
62
50
|
starting?: boolean;
|
|
51
|
+
last?: LastDrive;
|
|
63
52
|
}
|
|
64
53
|
export declare function creditsShort(credits: Credits | undefined): string;
|
|
65
54
|
export declare function harnessFootHtml(s: HarnessRowState): string;
|
|
@@ -13,13 +13,10 @@ export const HARNESS_ROW_TEXT = {
|
|
|
13
13
|
LINK: 'Link this project',
|
|
14
14
|
LINKING: 'Linking…',
|
|
15
15
|
NOT_ENTITLED: 'Harness is not on your plan',
|
|
16
|
-
NO_CREDITS: 'No
|
|
16
|
+
NO_CREDITS: 'No credits left',
|
|
17
17
|
NO_PROVIDER: 'No model provider set',
|
|
18
18
|
OFF: 'Harness is off',
|
|
19
|
-
canSwitchOn: (percent) => `Setup score ${String(percent)}%. Harness is off.`,
|
|
20
19
|
TURN_ON: 'Switch on',
|
|
21
|
-
COPY_PROMPT: 'Copy setup prompt',
|
|
22
|
-
COPIED: 'Copied',
|
|
23
20
|
SET_UP: 'Set up ↗',
|
|
24
21
|
PLANS: 'See plans ↗',
|
|
25
22
|
PLAN: 'Plan ↗',
|
|
@@ -32,50 +29,17 @@ export const HARNESS_ROW_TEXT = {
|
|
|
32
29
|
FOOT_NO_CREDITS: 'No credits',
|
|
33
30
|
FOOT_NOT_ENTITLED: 'Not on your plan',
|
|
34
31
|
FOOT_NO_PROVIDER: 'No model provider',
|
|
35
|
-
footSetup: (percent) => `Setup ${String(percent)}% · needs 80%`,
|
|
36
32
|
PAGE_TITLE: 'Reticle Harness',
|
|
37
33
|
LOG_LABEL: 'What the Harness did',
|
|
38
34
|
LOG_EMPTY: 'Runs show here, step by step.',
|
|
39
35
|
PAGE_SUBTITLE: 'Tests your app by itself',
|
|
36
|
+
RESULT: 'See the result ↗',
|
|
40
37
|
};
|
|
41
38
|
export const HARNESS_SWITCH_ON_ATTR = 'data-reticle-harness-switch';
|
|
42
39
|
export const HARNESS_LINK_ATTR = 'data-reticle-harness-link';
|
|
43
40
|
export const HARNESS_OPEN_ATTR = 'data-reticle-harness-open';
|
|
44
41
|
export const HARNESS_LOG_ATTR = 'data-reticle-harness-log';
|
|
45
42
|
export const HARNESS_TOGGLE_ATTR = 'data-reticle-harness-toggle';
|
|
46
|
-
export const HARNESS_COPY_PROMPT_ATTR = 'data-reticle-harness-copy-prompt';
|
|
47
|
-
export function harnessGateIn(instrumentation, config) {
|
|
48
|
-
const local = localGateIn(instrumentation);
|
|
49
|
-
const platform = config?.gate;
|
|
50
|
-
if (platform === undefined)
|
|
51
|
-
return local;
|
|
52
|
-
const prompt = platform.prompt ?? local?.prompt;
|
|
53
|
-
const reason = platform.unlocked ? undefined : (platform.reason ?? local?.reason);
|
|
54
|
-
return {
|
|
55
|
-
percent: platform.percent ?? local?.percent ?? 0,
|
|
56
|
-
unlocked: platform.unlocked,
|
|
57
|
-
...(reason === undefined ? {} : { reason }),
|
|
58
|
-
...(prompt === undefined ? {} : { prompt }),
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
function localGateIn(instrumentation) {
|
|
62
|
-
const raw = instrumentation?.['harnessGate'];
|
|
63
|
-
if ('object' !== typeof raw || null === raw)
|
|
64
|
-
return undefined;
|
|
65
|
-
const gate = raw;
|
|
66
|
-
const percent = gate['percent'];
|
|
67
|
-
const unlocked = gate['unlocked'];
|
|
68
|
-
if ('number' !== typeof percent || 'boolean' !== typeof unlocked)
|
|
69
|
-
return undefined;
|
|
70
|
-
const reason = gate['reason'];
|
|
71
|
-
const prompt = instrumentation?.['prompt'];
|
|
72
|
-
return {
|
|
73
|
-
percent: Math.round(percent),
|
|
74
|
-
unlocked,
|
|
75
|
-
...('string' === typeof reason ? { reason } : {}),
|
|
76
|
-
...('string' === typeof prompt ? { prompt } : {}),
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
43
|
const row = (inner) => `<div class="reticle-harness-row">${inner}</div>`;
|
|
80
44
|
const wrapRow = (inner) => `<div class="reticle-harness-row reticle-harness-row-wrap">${inner}</div>`;
|
|
81
45
|
const said = (text) => `<span class="reticle-harness-said">${text}</span>`;
|
|
@@ -99,9 +63,6 @@ function creditsUsedRow(credits, planUrl) {
|
|
|
99
63
|
function footState(s) {
|
|
100
64
|
if (true === s.starting)
|
|
101
65
|
return HARNESS_ROW_TEXT.STARTING;
|
|
102
|
-
const gate = s.gate;
|
|
103
|
-
if (gate !== undefined && !gate.unlocked && gate.reason !== undefined)
|
|
104
|
-
return HARNESS_ROW_TEXT.footSetup(gate.percent);
|
|
105
66
|
const config = s.config;
|
|
106
67
|
if (config === undefined)
|
|
107
68
|
return HARNESS_ROW_TEXT.FOOT_LINK;
|
|
@@ -120,8 +81,6 @@ function switchable(s) {
|
|
|
120
81
|
const config = s.config;
|
|
121
82
|
if (config === undefined)
|
|
122
83
|
return false;
|
|
123
|
-
if (s.gate !== undefined && !s.gate.unlocked && s.gate.reason !== undefined)
|
|
124
|
-
return false;
|
|
125
84
|
if (config.credits !== undefined && creditsSpent(config.credits))
|
|
126
85
|
return false;
|
|
127
86
|
return config.harnessEntitled && false !== config.providerReady;
|
|
@@ -146,11 +105,6 @@ export function harnessRowHtml(s) {
|
|
|
146
105
|
return wrapRow(`${said(HARNESS_ROW_TEXT.SIGNED_OUT)}<button type="button" ${ACCOUNT_SIGNIN_ATTR} class="reticle-harness-link">${HARNESS_ROW_TEXT.SIGN_IN}</button>`);
|
|
147
106
|
if (s.drive !== undefined && s.canDrive)
|
|
148
107
|
return (runRow(said(HARNESS_ROW_TEXT.driving(s.startedAs === undefined ? undefined : personaLabel(s.startedAs), s.drive.steps)), STOP_BUTTON) + personaCustomHtml(s.pick, true));
|
|
149
|
-
const gate = s.gate;
|
|
150
|
-
if (gate !== undefined && !gate.unlocked && gate.reason !== undefined)
|
|
151
|
-
return wrapRow(`${said(esc(gate.reason))}${gate.prompt === undefined
|
|
152
|
-
? ''
|
|
153
|
-
: `<button type="button" ${HARNESS_COPY_PROMPT_ATTR} class="reticle-harness-link">${HARNESS_ROW_TEXT.COPY_PROMPT}</button>`}`);
|
|
154
108
|
const config = s.config;
|
|
155
109
|
if (config === undefined)
|
|
156
110
|
return wrapRow(`${said(HARNESS_ROW_TEXT.UNLINKED)}<button type="button" ${HARNESS_LINK_ATTR} class="reticle-harness-run"${true === s.linking ? ' disabled' : ''}>${true === s.linking ? HARNESS_ROW_TEXT.LINKING : HARNESS_ROW_TEXT.LINK}</button>`);
|
|
@@ -161,11 +115,18 @@ export function harnessRowHtml(s) {
|
|
|
161
115
|
if (false === config.providerReady)
|
|
162
116
|
return row(`${said(HARNESS_ROW_TEXT.NO_PROVIDER)}${link(s.setupUrl, HARNESS_ROW_TEXT.SET_UP)}`);
|
|
163
117
|
if (!config.harnessEnabled)
|
|
164
|
-
return row(`${said(
|
|
118
|
+
return row(`${said(HARNESS_ROW_TEXT.OFF)}<button type="button" ${HARNESS_SWITCH_ON_ATTR} class="reticle-harness-run">${HARNESS_ROW_TEXT.TURN_ON}</button>`);
|
|
165
119
|
if (!s.canDrive)
|
|
166
120
|
return '';
|
|
167
121
|
const starting = true === s.starting;
|
|
168
|
-
return (runRow(personaPickHtml(s.pick, starting), `<button type="button" data-reticle-harness-run class="reticle-harness-run"${starting ? ' disabled' : ''}>${starting ? HARNESS_ROW_TEXT.STARTING : HARNESS_ROW_TEXT.RUN}</button>`) +
|
|
122
|
+
return (runRow(personaPickHtml(s.pick, starting), `<button type="button" data-reticle-harness-run class="reticle-harness-run"${starting ? ' disabled' : ''}>${starting ? HARNESS_ROW_TEXT.STARTING : HARNESS_ROW_TEXT.RUN}</button>`) +
|
|
123
|
+
personaCustomHtml(s.pick, starting) +
|
|
124
|
+
(starting ? '' : lastRowHtml(s.last)));
|
|
125
|
+
}
|
|
126
|
+
function lastRowHtml(last) {
|
|
127
|
+
if (last === undefined || (last.said === undefined && last.runUrl === undefined))
|
|
128
|
+
return '';
|
|
129
|
+
return wrapRow(`${last.said === undefined ? '' : said(esc(last.said))}${last.runUrl === undefined ? '' : link(last.runUrl, HARNESS_ROW_TEXT.RESULT)}`);
|
|
169
130
|
}
|
|
170
131
|
export const HARNESS_ROW_CSS = `
|
|
171
132
|
[data-reticle-chat-panel] .reticle-harness-spot{flex:none;display:flex;flex-direction:column;gap:4px;}
|
|
@@ -56,23 +56,6 @@ export const REPORT_CSS = `
|
|
|
56
56
|
[${REPORT_PANEL_ATTR}] .reticle-report-coverage{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 10px;margin-bottom:12px;padding:8px 10px;border:1px solid var(--reticle-hud-border);border-radius:var(--reticle-hud-radius-sm,8px);}
|
|
57
57
|
[${REPORT_PANEL_ATTR}] .reticle-report-coverage-value{font-size:18px;font-weight:600;font-variant-numeric:tabular-nums;color:var(--reticle-hud-text);}
|
|
58
58
|
[${REPORT_PANEL_ATTR}] .reticle-report-coverage-levels{display:flex;flex-wrap:wrap;gap:4px 10px;width:100%;font-size:11px;color:var(--reticle-faint);font-variant-numeric:tabular-nums;}
|
|
59
|
-
[${REPORT_PANEL_ATTR}] .reticle-report-instrumentation{margin-bottom:12px;padding:10px;border:1px solid var(--reticle-hud-border);border-radius:var(--reticle-hud-radius-md);}
|
|
60
|
-
[${REPORT_PANEL_ATTR}] .reticle-report-instrumentation-head{display:flex;align-items:baseline;justify-content:space-between;gap:8px;}
|
|
61
|
-
[${REPORT_PANEL_ATTR}] .reticle-report-instrumentation-head .reticle-report-section{margin-bottom:0;}
|
|
62
|
-
[${REPORT_PANEL_ATTR}] .reticle-report-instrumentation-value{font-size:13px;font-weight:600;font-variant-numeric:tabular-nums;color:var(--reticle-hud-text);}
|
|
63
|
-
[${REPORT_PANEL_ATTR}] .reticle-report-caps{display:grid;grid-template-columns:1fr 1fr;gap:4px 10px;margin:8px 0 0;padding:0;list-style:none;}
|
|
64
|
-
[${REPORT_PANEL_ATTR}] .reticle-report-cap{display:flex;flex-wrap:wrap;align-items:baseline;gap:0 6px;min-width:0;font-size:11px;line-height:1.4;color:var(--reticle-muted);}
|
|
65
|
-
[${REPORT_PANEL_ATTR}] .reticle-report-cap-mark{flex:none;width:10px;text-align:center;}
|
|
66
|
-
[${REPORT_PANEL_ATTR}] .reticle-report-cap-name{flex:1;min-width:0;}
|
|
67
|
-
[${REPORT_PANEL_ATTR}] .reticle-report-cap[data-state="seen"] .reticle-report-cap-mark{color:#86efac;}
|
|
68
|
-
[${REPORT_PANEL_ATTR}] .reticle-report-cap[data-state="missing"]{grid-column:1/-1;color:var(--reticle-hud-text);}
|
|
69
|
-
[${REPORT_PANEL_ATTR}] .reticle-report-cap[data-state="missing"] .reticle-report-cap-mark{color:#fca5a5;}
|
|
70
|
-
[${REPORT_PANEL_ATTR}] .reticle-report-cap[data-state="unseen"]{color:var(--reticle-faint);}
|
|
71
|
-
[${REPORT_PANEL_ATTR}] .reticle-report-cap-cost{flex-basis:100%;padding-left:16px;color:var(--reticle-faint);}
|
|
72
|
-
[${REPORT_PANEL_ATTR}] .reticle-report-caps-note{display:block;margin-top:6px;color:var(--reticle-faint);font-size:11px;}
|
|
73
|
-
[${REPORT_PANEL_ATTR}] .reticle-report-copy-prompt{display:block;width:100%;margin-top:10px;padding:6px 10px;border:1px solid color-mix(in srgb,var(--reticle-hud-brand) 50%,transparent);
|
|
74
|
-
border-radius:var(--reticle-hud-radius-sm);background:var(--reticle-hud-brand-soft);color:var(--reticle-hud-brand);font:inherit;font-size:12px;font-weight:600;cursor:pointer;}
|
|
75
|
-
[${REPORT_PANEL_ATTR}] .reticle-report-copy-prompt:hover{filter:brightness(1.15);}
|
|
76
59
|
[${REPORT_PANEL_ATTR}] .reticle-report-verdict{
|
|
77
60
|
flex:1;padding:5px 8px;border-radius:8px;font-size:11px;text-align:center;
|
|
78
61
|
background:rgba(255,255,255,.05);color:var(--reticle-muted);}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { type AccountState, type ImpactScope, type ImpactSnapshot } from '@reticlehq/core';
|
|
2
2
|
export declare function reportPanelHtml(): string;
|
|
3
|
-
export declare function
|
|
4
|
-
export declare function reportBodyHtml(scope: ImpactScope, dashboardUrl?: string, account?: AccountState, projectName?: string, coverage?: Readonly<Record<string, number>>, sync?: Readonly<Record<string, unknown>>, instrumentation?: Readonly<Record<string, unknown>>): string;
|
|
3
|
+
export declare function reportBodyHtml(scope: ImpactScope, dashboardUrl?: string, account?: AccountState, projectName?: string, coverage?: Readonly<Record<string, number>>, sync?: Readonly<Record<string, unknown>>): string;
|
|
5
4
|
interface ReportHost {
|
|
6
5
|
onBeforeOpen?: () => void;
|
|
7
6
|
onSyncNow?: () => void;
|
|
@@ -4,7 +4,7 @@ import { HUD_SURFACE_CLASS } from './chrome/presenter-hud-chrome.js';
|
|
|
4
4
|
import { esc, isSafeDashboardUrl } from './chrome/presenter-safe-html.js';
|
|
5
5
|
import { ACCOUNT_SIGNIN_ATTR, ACCOUNT_TEXT, SYNC_BTN_ATTR, accountControlHtml, syncButtonHtml, } from './presenter-account.js';
|
|
6
6
|
import { REPORT_PANEL_ATTR, REPORT_ATTR, REPORT_CLOSE_ATTR } from './presenter-config.js';
|
|
7
|
-
import { REPORT_LINKS, REPORT_TEXT, buildLinkedInShareUrl, buildReferralText, buildShareText, buildXShareUrl, compactDuration, compactNumber, COVERAGE_LEVELS,
|
|
7
|
+
import { REPORT_LINKS, REPORT_TEXT, buildLinkedInShareUrl, buildReferralText, buildShareText, buildXShareUrl, compactDuration, compactNumber, COVERAGE_LEVELS, } from './chrome/presenter-report-copy.js';
|
|
8
8
|
const SCOPE_ATTR = 'data-reticle-report-scope';
|
|
9
9
|
const SCOPE = { PROJECT: 'project', MACHINE: 'machine' };
|
|
10
10
|
const SHARE_X_ATTR = 'data-reticle-share-x';
|
|
@@ -119,49 +119,6 @@ function syncStatusHtml(sync) {
|
|
|
119
119
|
: '';
|
|
120
120
|
return `<span class="reticle-sync-status" data-reticle-sync-status="${esc(String(status))}" title="${esc(said)}">${label}</span>${seeRun}`;
|
|
121
121
|
}
|
|
122
|
-
const capabilityWords = (name) => 'string' === typeof name ? esc(CAPABILITY_WORDS[name] ?? name) : undefined;
|
|
123
|
-
function capabilityItem(state, name, cost = '') {
|
|
124
|
-
const mark = 'seen' === state ? '✓' : 'missing' === state ? '✕' : '○';
|
|
125
|
-
const why = '' === cost ? '' : `<span class="reticle-report-cap-cost">${cost}</span>`;
|
|
126
|
-
return `<li class="reticle-report-cap" data-state="${state}"><span class="reticle-report-cap-mark" aria-hidden="true">${mark}</span><span class="reticle-report-cap-name">${name}</span>${why}</li>`;
|
|
127
|
-
}
|
|
128
|
-
export function instrumentationHtml(instrumentation) {
|
|
129
|
-
if (instrumentation === undefined)
|
|
130
|
-
return '';
|
|
131
|
-
const covered = instrumentation['covered'];
|
|
132
|
-
const total = instrumentation['total'];
|
|
133
|
-
if ('number' !== typeof covered || 'number' !== typeof total)
|
|
134
|
-
return '';
|
|
135
|
-
const list = (key) => {
|
|
136
|
-
const value = instrumentation[key];
|
|
137
|
-
return Array.isArray(value) ? value : [];
|
|
138
|
-
};
|
|
139
|
-
const seen = list('seen').flatMap((n) => {
|
|
140
|
-
const name = capabilityWords(n);
|
|
141
|
-
return name === undefined ? [] : [capabilityItem('seen', name)];
|
|
142
|
-
});
|
|
143
|
-
const missing = list('missing').flatMap((m) => {
|
|
144
|
-
if ('object' !== typeof m || null === m)
|
|
145
|
-
return [];
|
|
146
|
-
const gap = m;
|
|
147
|
-
const name = capabilityWords(gap['capability']);
|
|
148
|
-
const cost = 'string' === typeof gap['cost'] ? esc(gap['cost']) : '';
|
|
149
|
-
return name === undefined ? [] : [capabilityItem('missing', name, cost)];
|
|
150
|
-
});
|
|
151
|
-
const unseen = list('notSeenYet').flatMap((n) => {
|
|
152
|
-
const name = capabilityWords(n);
|
|
153
|
-
return name === undefined ? [] : [capabilityItem('unseen', name)];
|
|
154
|
-
});
|
|
155
|
-
const items = [...missing, ...seen, ...unseen];
|
|
156
|
-
const caps = 0 === items.length
|
|
157
|
-
? ''
|
|
158
|
-
: `<ul class="reticle-report-caps">${items.join('')}</ul>${0 === unseen.length ? '' : `<span class="reticle-report-caps-note">○ ${REPORT_TEXT.NOT_SEEN_YET}</span>`}`;
|
|
159
|
-
const copy = 'string' === typeof instrumentation['prompt']
|
|
160
|
-
? `<button type="button" class="reticle-report-copy-prompt" ${COPY_PROMPT_ATTR}>${REPORT_TEXT.COPY_PROMPT}</button>`
|
|
161
|
-
: '';
|
|
162
|
-
return `<div class="reticle-report-instrumentation" title="${REPORT_TEXT.INSTRUMENTATION_HELP}"><div class="reticle-report-instrumentation-head"><span class="reticle-report-section">${REPORT_TEXT.INSTRUMENTATION}</span><span class="reticle-report-instrumentation-value">${REPORT_TEXT.covered(Math.round(covered), Math.round(total))}</span></div>${caps}${copy}</div>`;
|
|
163
|
-
}
|
|
164
|
-
const COPY_PROMPT_ATTR = 'data-reticle-copy-prompt';
|
|
165
122
|
function coverageHtml(coverage) {
|
|
166
123
|
if (coverage === undefined)
|
|
167
124
|
return '';
|
|
@@ -175,7 +132,7 @@ function coverageHtml(coverage) {
|
|
|
175
132
|
.join('');
|
|
176
133
|
return `<div class="reticle-report-coverage" title="${REPORT_TEXT.COVERAGE_HELP}"><span class="reticle-report-section">${REPORT_TEXT.COVERAGE}</span><span class="reticle-report-coverage-value">${head}</span><div class="reticle-report-coverage-levels">${rows}</div></div>`;
|
|
177
134
|
}
|
|
178
|
-
export function reportBodyHtml(scope, dashboardUrl, account, projectName, coverage, sync
|
|
135
|
+
export function reportBodyHtml(scope, dashboardUrl, account, projectName, coverage, sync) {
|
|
179
136
|
const c = scope.counts;
|
|
180
137
|
if (0 === c.calls)
|
|
181
138
|
return `<p class="reticle-report-empty">${REPORT_TEXT.EMPTY}</p>`;
|
|
@@ -199,7 +156,7 @@ export function reportBodyHtml(scope, dashboardUrl, account, projectName, covera
|
|
|
199
156
|
card(compactDuration(scope.savings.minutes.value * 60_000), REPORT_TEXT.SAVED_MINUTES, scope.savings.minutes.basis),
|
|
200
157
|
].join('');
|
|
201
158
|
const identity = `<div class="reticle-report-identity">${accountControlHtml(account, { dashboardUrl, projectName, verdicts: c.verdicts, defects: c.failed })}${syncButtonHtml(dashboardUrl)}${syncStatusHtml(sync)}</div>`;
|
|
202
|
-
return `<div class="reticle-report-top">${streak}${identity}</div>${hero}${verdicts}${
|
|
159
|
+
return `<div class="reticle-report-top">${streak}${identity}</div>${hero}${verdicts}${coverageHtml(coverage)}<div class="reticle-report-grid">${cards}</div>${defects(scope, dashboardUrl)}${chart(scope)}${localOnly(scope, dashboardUrl, account)}`;
|
|
203
160
|
}
|
|
204
161
|
function localOnly(scope, dashboardUrl, account) {
|
|
205
162
|
if (dashboardUrl !== undefined)
|
|
@@ -271,13 +228,6 @@ export class PresenterReport {
|
|
|
271
228
|
void this.#copy(ACCOUNT_TEXT.SIGNIN_COMMAND, signin);
|
|
272
229
|
return;
|
|
273
230
|
}
|
|
274
|
-
const copyPrompt = target.closest(`[${COPY_PROMPT_ATTR}]`);
|
|
275
|
-
const prompt = this.#snapshot?.instrumentation?.['prompt'];
|
|
276
|
-
if (copyPrompt !== null && 'string' === typeof prompt) {
|
|
277
|
-
e.stopPropagation();
|
|
278
|
-
void this.#copy(prompt, copyPrompt);
|
|
279
|
-
return;
|
|
280
|
-
}
|
|
281
231
|
const sync = target.closest(`[${SYNC_BTN_ATTR}]`);
|
|
282
232
|
if (sync !== null) {
|
|
283
233
|
e.stopPropagation();
|
|
@@ -340,7 +290,7 @@ export class PresenterReport {
|
|
|
340
290
|
this.#body.innerHTML =
|
|
341
291
|
scope === undefined
|
|
342
292
|
? `<p class="reticle-report-empty">${REPORT_TEXT.EMPTY}</p>`
|
|
343
|
-
: reportBodyHtml(scope, this.#snapshot?.dashboardUrl, this.#snapshot?.account, this.#snapshot?.projectName, this.#global ? undefined : this.#snapshot?.coverage, this.#global ? undefined : this.#snapshot?.sync
|
|
293
|
+
: reportBodyHtml(scope, this.#snapshot?.dashboardUrl, this.#snapshot?.account, this.#snapshot?.projectName, this.#global ? undefined : this.#snapshot?.coverage, this.#global ? undefined : this.#snapshot?.sync);
|
|
344
294
|
}
|
|
345
295
|
#openShare(url) {
|
|
346
296
|
window.open(url, '_blank', 'noopener,noreferrer');
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { SessionState } from '@reticlehq/core';
|
|
2
|
+
import { pageHref } from '../security/page-location.js';
|
|
2
3
|
import { LOG_KIND, LOG_RESULT } from './chrome/presenter-log.js';
|
|
3
4
|
import { getCapabilities } from '../registry/capabilities.js';
|
|
4
5
|
export function buildRunState(input) {
|
|
@@ -20,7 +21,7 @@ export function buildRunState(input) {
|
|
|
20
21
|
}
|
|
21
22
|
return {
|
|
22
23
|
session: input.sessionId,
|
|
23
|
-
url: 'undefined' === typeof location ? '' :
|
|
24
|
+
url: 'undefined' === typeof location ? '' : pageHref(),
|
|
24
25
|
state: input.state,
|
|
25
26
|
startedMs: start,
|
|
26
27
|
durationMs: Math.max(0, (input.endMs ?? input.now) - start),
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { HarnessConfig } from '@reticlehq/core';
|
|
2
|
-
import type { HarnessGateView } from './presenter-harness-row.js';
|
|
3
2
|
import { SETTINGS_CSS } from './presenter-settings-styles.js';
|
|
4
3
|
import { type Credits } from '@reticlehq/core/hud';
|
|
5
4
|
import type { AccountState } from '@reticlehq/core';
|
|
@@ -45,7 +44,7 @@ export declare function loadPresenterSettings(): PresenterSettings;
|
|
|
45
44
|
export declare const SETTINGS_ACCOUNT_ATTR = "data-reticle-settings-account";
|
|
46
45
|
export declare const HARNESS_LOCKED_HELP = "The Harness is not available to this workspace right now: see Plan in your Reticle dashboard.";
|
|
47
46
|
export declare function creditsLeft(credits: Credits | undefined): string;
|
|
48
|
-
export declare function paintHarnessRow(root: ParentNode, config: HarnessConfig | undefined
|
|
47
|
+
export declare function paintHarnessRow(root: ParentNode, config: HarnessConfig | undefined): void;
|
|
49
48
|
export declare function paintSettingsAccount(root: HTMLElement, account: AccountState | undefined, dashboardUrl: string | undefined, details?: AccountDetails): void;
|
|
50
49
|
export declare function paintSdkVersion(root: ParentNode, version: string | undefined): void;
|
|
51
50
|
export declare function settingsPanelHtml(): string;
|
|
@@ -63,7 +62,7 @@ export declare class PresenterSettingsPanel {
|
|
|
63
62
|
constructor(host?: SettingsHost);
|
|
64
63
|
contains(node: Node): boolean;
|
|
65
64
|
mount(root: HTMLElement): void;
|
|
66
|
-
paintHarness(config: HarnessConfig | undefined
|
|
65
|
+
paintHarness(config: HarnessConfig | undefined): void;
|
|
67
66
|
teardown(): void;
|
|
68
67
|
isOpen(): boolean;
|
|
69
68
|
open(): void;
|