@reticlehq/browser 3.6.0 → 3.8.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 +64 -0
- package/dist/actions/action-report.js +87 -0
- package/dist/actions/actions-dom.d.ts +5 -0
- package/dist/actions/actions-dom.js +32 -4
- package/dist/actions/actions-press.d.ts +1 -0
- package/dist/actions/actions-press.js +25 -1
- package/dist/actions/actions.d.ts +2 -37
- package/dist/actions/actions.js +56 -80
- package/dist/actions/appeared-text.js +5 -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 +4 -1
- package/dist/actions/danger-context.js +45 -4
- package/dist/actions/value-input.d.ts +1 -0
- package/dist/actions/value-input.js +11 -0
- 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 +49 -17
- package/dist/connect-options.d.ts +12 -1
- package/dist/connect-options.js +18 -1
- package/dist/dom/a11y.d.ts +2 -0
- package/dist/dom/a11y.js +353 -80
- package/dist/dom/addressing/coverage-markers.d.ts +6 -0
- package/dist/dom/addressing/coverage-markers.js +13 -0
- package/dist/dom/chart.d.ts +3 -2
- package/dist/dom/chart.js +3 -2
- package/dist/dom/dom-ignore.d.ts +8 -0
- package/dist/dom/dom-ignore.js +57 -2
- 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.d.ts +2 -1
- package/dist/dom/query.js +163 -38
- package/dist/dom/render-page.d.ts +12 -0
- package/dist/dom/render-page.js +135 -0
- 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 +135 -36
- 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/index.d.ts +2 -1
- package/dist/index.js +5 -0
- 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 +96 -32
- package/dist/observers/field.d.ts +11 -0
- package/dist/observers/field.js +116 -30
- 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 +8 -1
- package/dist/observers/network.js +82 -13
- package/dist/observers/perf.js +53 -1
- package/dist/observers/route.d.ts +2 -0
- package/dist/observers/route.js +39 -9
- 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 +12 -4
- package/dist/presenter/chrome/presenter-report-copy.js +12 -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 +25 -4
- package/dist/presenter/presenter-chat-views.js +339 -72
- package/dist/presenter/presenter-config.d.ts +3 -0
- package/dist/presenter/presenter-config.js +2 -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 +3 -2
- package/dist/presenter/presenter-frame.js +31 -24
- package/dist/presenter/presenter-harness-row.d.ts +56 -0
- package/dist/presenter/presenter-harness-row.js +170 -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 +23 -22
- package/dist/presenter/presenter-report.js +29 -13
- package/dist/presenter/presenter-run-state.js +2 -1
- package/dist/presenter/presenter-settings-styles.js +8 -4
- package/dist/presenter/presenter-settings.d.ts +4 -4
- package/dist/presenter/presenter-settings.js +66 -28
- package/dist/presenter/presenter-shell-styles.js +12 -3
- package/dist/presenter/presenter-shell.d.ts +11 -3
- package/dist/presenter/presenter-shell.js +60 -22
- 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 +107 -25
- package/dist/registry/declared-platform.js +2 -0
- package/dist/registry/store-adapters.d.ts +5 -2
- package/dist/registry/store-adapters.js +40 -10
- package/dist/reticle-inject.js +771 -703
- package/dist/reticle.d.ts +4 -2
- package/dist/reticle.js +72 -8
- 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 +4 -2
- package/dist/storage-keys.js +8 -3
- 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 +23 -3
- package/dist/transport/unreachable-message.d.ts +1 -1
- package/dist/transport/unreachable-message.js +3 -5
- package/package.json +6 -2
- package/dist/presenter/carousel/offer-card.d.ts +0 -21
- package/dist/presenter/carousel/offer-card.js +0 -56
|
@@ -13,7 +13,7 @@ export declare const REPORT_TEXT: {
|
|
|
13
13
|
readonly GLOBAL: "All projects";
|
|
14
14
|
readonly GLOBAL_TITLE: "Every project on this computer";
|
|
15
15
|
readonly SCOPE_LABEL: "Show impact for";
|
|
16
|
-
readonly
|
|
16
|
+
readonly heroDefects: (n: number) => string;
|
|
17
17
|
readonly VERDICTS: "Verdicts";
|
|
18
18
|
readonly PASSED: "passed";
|
|
19
19
|
readonly FAILED: "failed";
|
|
@@ -35,17 +35,25 @@ export declare const REPORT_TEXT: {
|
|
|
35
35
|
readonly DEFECTS_SEE_ALL_TITLE: "Sign up free, link this project, and see every bug Reticle caught";
|
|
36
36
|
readonly DEFECT_LINK_TITLE: "Open on the dashboard to triage or push to GitHub";
|
|
37
37
|
readonly LOCAL_ONLY: "This record stops at this machine.";
|
|
38
|
-
readonly LOCAL_ONLY_ACTION: "reticle
|
|
38
|
+
readonly LOCAL_ONLY_ACTION: "reticle connect";
|
|
39
39
|
readonly LOCAL_ONLY_TAIL: "keeps it, and lets a team see it.";
|
|
40
40
|
readonly UNLINKED: "Signed in, but this repo is not linked.";
|
|
41
|
-
readonly UNLINKED_ACTION: "reticle
|
|
41
|
+
readonly UNLINKED_ACTION: "reticle connect";
|
|
42
42
|
readonly UNLINKED_TAIL: "sends this record to your workspace.";
|
|
43
43
|
readonly DEFECTS_NONE: "Nothing has failed a declared consequence yet.";
|
|
44
44
|
readonly EMPTY: "Nothing recorded yet. Drive the app once and this fills in.";
|
|
45
45
|
readonly SHARE: "Share";
|
|
46
46
|
readonly COPY: "Copy";
|
|
47
47
|
readonly COPIED: "Copied";
|
|
48
|
-
readonly
|
|
48
|
+
readonly SEE_RUN: "See it in your dashboard";
|
|
49
|
+
readonly KEY_REFUSED: "Key refused";
|
|
50
|
+
readonly NOT_SENT: "not synced";
|
|
51
|
+
readonly NOT_SENT_HELP: "Runs saved on this machine but not on your dashboard yet. Run reticle connect in this project to send them.";
|
|
52
|
+
readonly COPY_PROMPT: "Copy prompt for your coding agent";
|
|
53
|
+
readonly SHARE_LABEL: "Share";
|
|
54
|
+
readonly POST_X: "X";
|
|
55
|
+
readonly POST_IN: "LinkedIn";
|
|
56
|
+
readonly REFER: "Invite a friend";
|
|
49
57
|
};
|
|
50
58
|
export declare function compactNumber(n: number): string;
|
|
51
59
|
export declare function compactDuration(ms: number): string;
|
|
@@ -14,7 +14,7 @@ export const REPORT_TEXT = {
|
|
|
14
14
|
GLOBAL: 'All projects',
|
|
15
15
|
GLOBAL_TITLE: 'Every project on this computer',
|
|
16
16
|
SCOPE_LABEL: 'Show impact for',
|
|
17
|
-
|
|
17
|
+
heroDefects: (n) => `failed check${1 === n ? '' : 's'} caught before you shipped`,
|
|
18
18
|
VERDICTS: 'Verdicts',
|
|
19
19
|
PASSED: 'passed',
|
|
20
20
|
FAILED: 'failed',
|
|
@@ -36,17 +36,25 @@ export const REPORT_TEXT = {
|
|
|
36
36
|
DEFECTS_SEE_ALL_TITLE: 'Sign up free, link this project, and see every bug Reticle caught',
|
|
37
37
|
DEFECT_LINK_TITLE: 'Open on the dashboard to triage or push to GitHub',
|
|
38
38
|
LOCAL_ONLY: 'This record stops at this machine.',
|
|
39
|
-
LOCAL_ONLY_ACTION: 'reticle
|
|
39
|
+
LOCAL_ONLY_ACTION: 'reticle connect',
|
|
40
40
|
LOCAL_ONLY_TAIL: 'keeps it, and lets a team see it.',
|
|
41
41
|
UNLINKED: 'Signed in, but this repo is not linked.',
|
|
42
|
-
UNLINKED_ACTION: 'reticle
|
|
42
|
+
UNLINKED_ACTION: 'reticle connect',
|
|
43
43
|
UNLINKED_TAIL: 'sends this record to your workspace.',
|
|
44
44
|
DEFECTS_NONE: 'Nothing has failed a declared consequence yet.',
|
|
45
45
|
EMPTY: 'Nothing recorded yet. Drive the app once and this fills in.',
|
|
46
46
|
SHARE: 'Share',
|
|
47
47
|
COPY: 'Copy',
|
|
48
48
|
COPIED: 'Copied',
|
|
49
|
-
|
|
49
|
+
SEE_RUN: 'See it in your dashboard',
|
|
50
|
+
KEY_REFUSED: 'Key refused',
|
|
51
|
+
NOT_SENT: 'not synced',
|
|
52
|
+
NOT_SENT_HELP: 'Runs saved on this machine but not on your dashboard yet. Run reticle connect in this project to send them.',
|
|
53
|
+
COPY_PROMPT: 'Copy prompt for your coding agent',
|
|
54
|
+
SHARE_LABEL: 'Share',
|
|
55
|
+
POST_X: 'X',
|
|
56
|
+
POST_IN: 'LinkedIn',
|
|
57
|
+
REFER: 'Invite a friend',
|
|
50
58
|
};
|
|
51
59
|
export function compactNumber(n) {
|
|
52
60
|
if (n < 1000)
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { HUD_KEYED_ATTRS, isHudControl } from '@reticlehq/core/hud';
|
|
2
|
-
import { HudPanel, HudToggle, HudView } from '@reticlehq/core';
|
|
2
|
+
import { HudPanel, HudPromptSurface, HudToggle, HudView } from '@reticlehq/core';
|
|
3
3
|
import { isReticleUi } from '../dom/dom-ignore.js';
|
|
4
4
|
import { nativeSetTimeout } from '../timers/native/native-timers.js';
|
|
5
5
|
import { CHAT_ATTR, MIN_ATTR, REPORT_ATTR, SETTINGS_ATTR } from './presenter-config.js';
|
|
6
6
|
import { CAROUSEL_SLIDE_ATTR } from './carousel/carousel.js';
|
|
7
|
+
import { ACCOUNT_MENU_ATTR, ACCOUNT_SIGNIN_ATTR, TEAM_SAVE_ATTR } from './presenter-account.js';
|
|
8
|
+
import { HARNESS_LINK_ATTR } from './presenter-harness-row.js';
|
|
9
|
+
import { RAIL_SIGNIN_ATTR } from './presenter-frame.js';
|
|
7
10
|
const PREFIX = 'data-reticle-';
|
|
8
11
|
const PAGE_OPEN_ATTR = 'data-reticle-page-open';
|
|
9
12
|
const TOGGLE_ROLES = new Set(['switch', 'checkbox']);
|
|
@@ -30,6 +33,14 @@ function controlOf(path) {
|
|
|
30
33
|
return undefined;
|
|
31
34
|
}
|
|
32
35
|
function viewOf(root) {
|
|
36
|
+
const page = pageOf(root);
|
|
37
|
+
if (HudView.BUBBLE === page.view)
|
|
38
|
+
return page;
|
|
39
|
+
return null === root.querySelector(`[${ACCOUNT_MENU_ATTR}]:not([hidden])`)
|
|
40
|
+
? page
|
|
41
|
+
: { view: page.view, panel: HudPanel.ACCOUNT };
|
|
42
|
+
}
|
|
43
|
+
function pageOf(root) {
|
|
33
44
|
if ('1' === root.getAttribute(MIN_ATTR))
|
|
34
45
|
return { view: HudView.BUBBLE, panel: HudPanel.NONE };
|
|
35
46
|
if ('1' === root.getAttribute(SETTINGS_ATTR)) {
|
|
@@ -43,10 +54,30 @@ function viewOf(root) {
|
|
|
43
54
|
return { view: HudView.EXPANDED, panel: HudPanel.FLOWS };
|
|
44
55
|
if ('annotations' === page)
|
|
45
56
|
return { view: HudView.EXPANDED, panel: HudPanel.NOTES };
|
|
57
|
+
if ('harness' === page)
|
|
58
|
+
return { view: HudView.EXPANDED, panel: HudPanel.HARNESS };
|
|
46
59
|
if ('1' === root.getAttribute(CHAT_ATTR))
|
|
47
60
|
return { view: HudView.EXPANDED, panel: HudPanel.CHAT };
|
|
48
61
|
return { view: HudView.COLLAPSED, panel: HudPanel.NONE };
|
|
49
62
|
}
|
|
63
|
+
const PROMPTS = [
|
|
64
|
+
{
|
|
65
|
+
surface: HudPromptSurface.RAIL,
|
|
66
|
+
selector: `[${RAIL_SIGNIN_ATTR}]`,
|
|
67
|
+
shown: (at) => HudPanel.CHAT === at.panel,
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
surface: HudPromptSurface.HARNESS,
|
|
71
|
+
selector: `[data-reticle-page-panel="harness"] :is([${ACCOUNT_SIGNIN_ATTR}],[${HARNESS_LINK_ATTR}])`,
|
|
72
|
+
shown: (at) => HudPanel.HARNESS === at.panel,
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
surface: HudPromptSurface.HEADER,
|
|
76
|
+
selector: `[${TEAM_SAVE_ATTR}]`,
|
|
77
|
+
shown: (at) => HudView.BUBBLE !== at.view,
|
|
78
|
+
},
|
|
79
|
+
];
|
|
80
|
+
const visible = (el) => null === el.closest('[hidden]');
|
|
50
81
|
export function installHudTelemetry(doc, root, report) {
|
|
51
82
|
const send = (use) => {
|
|
52
83
|
try {
|
|
@@ -91,9 +122,27 @@ export function installHudTelemetry(doc, root, report) {
|
|
|
91
122
|
lastSlide = slide;
|
|
92
123
|
send({ slide });
|
|
93
124
|
};
|
|
94
|
-
const
|
|
95
|
-
|
|
125
|
+
const prompted = new Set();
|
|
126
|
+
const onPrompt = () => {
|
|
127
|
+
const at = viewOf(root);
|
|
128
|
+
for (const prompt of PROMPTS) {
|
|
129
|
+
if (prompted.has(prompt.surface) || !prompt.shown(at))
|
|
130
|
+
continue;
|
|
131
|
+
const el = root.querySelector(prompt.selector);
|
|
132
|
+
if (null === el || !visible(el))
|
|
133
|
+
continue;
|
|
134
|
+
prompted.add(prompt.surface);
|
|
135
|
+
send({ prompt: prompt.surface });
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
const inside = new MutationObserver(() => {
|
|
139
|
+
onSlide();
|
|
140
|
+
onChange();
|
|
141
|
+
onPrompt();
|
|
142
|
+
});
|
|
143
|
+
inside.observe(root, {
|
|
96
144
|
subtree: true,
|
|
145
|
+
childList: true,
|
|
97
146
|
attributes: true,
|
|
98
147
|
attributeFilter: ['data-active', 'hidden'],
|
|
99
148
|
});
|
|
@@ -102,15 +151,17 @@ export function installHudTelemetry(doc, root, report) {
|
|
|
102
151
|
onChange();
|
|
103
152
|
if (0 < records.length)
|
|
104
153
|
onSlide();
|
|
154
|
+
onPrompt();
|
|
105
155
|
});
|
|
106
156
|
observer.observe(root, {
|
|
107
157
|
attributes: true,
|
|
108
158
|
attributeFilter: [MIN_ATTR, CHAT_ATTR, SETTINGS_ATTR, REPORT_ATTR, PAGE_OPEN_ATTR],
|
|
109
159
|
});
|
|
110
160
|
onChange();
|
|
161
|
+
onPrompt();
|
|
111
162
|
return () => {
|
|
112
163
|
doc.removeEventListener('click', onPress, true);
|
|
113
164
|
observer.disconnect();
|
|
114
|
-
|
|
165
|
+
inside.disconnect();
|
|
115
166
|
};
|
|
116
167
|
}
|
|
@@ -36,7 +36,7 @@ export const ACCOUNT_CSS = `
|
|
|
36
36
|
.reticle-account-trigger[aria-expanded="true"]{box-shadow:0 0 0 2px rgba(255,255,255,.28);}
|
|
37
37
|
|
|
38
38
|
.reticle-account-signin{
|
|
39
|
-
border:none;border-radius:6px;padding:2px 9px;cursor:pointer;font:inherit;font-size:
|
|
39
|
+
border:none;border-radius:6px;padding:2px 9px;cursor:pointer;font:inherit;font-size:11px;
|
|
40
40
|
background:rgba(255,255,255,.06);color:rgba(255,255,255,.75);transition:background .12s,color .12s;}
|
|
41
41
|
.reticle-account-signin:hover{background:rgba(255,255,255,.12);color:#fff;}
|
|
42
42
|
|
|
@@ -64,7 +64,7 @@ export const ACCOUNT_CSS = `
|
|
|
64
64
|
font-size:11.5px;font-weight:600;color:rgba(255,255,255,.95);
|
|
65
65
|
overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
|
|
66
66
|
.reticle-account-email{
|
|
67
|
-
font-size:
|
|
67
|
+
font-size:11px;color:rgba(255,255,255,.55);
|
|
68
68
|
overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
|
|
69
69
|
|
|
70
70
|
.reticle-account-rows{
|
|
@@ -90,7 +90,7 @@ export const ACCOUNT_CSS = `
|
|
|
90
90
|
/* The unlinked hint is a sentence, not a verb: it wraps rather than truncating, because a clipped
|
|
91
91
|
instruction is worse than a tall menu. */
|
|
92
92
|
.reticle-account-action--hint{
|
|
93
|
-
color:rgba(255,255,255,.5);font-size:
|
|
93
|
+
color:rgba(255,255,255,.5);font-size:11px;line-height:1.35;white-space:normal;cursor:pointer;}
|
|
94
94
|
|
|
95
95
|
.reticle-account-dashboard{
|
|
96
96
|
display:inline-flex;align-items:center;justify-content:center;
|
|
@@ -1,14 +1,23 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type AccountState, type HarnessConfig } from '@reticlehq/core';
|
|
2
2
|
export declare const ACCOUNT_ROOT_ATTR = "data-reticle-account";
|
|
3
3
|
export declare const ACCOUNT_SIGNIN_ATTR = "data-reticle-account-signin";
|
|
4
4
|
export declare const SYNC_BTN_ATTR = "data-reticle-sync-now";
|
|
5
5
|
export declare const ACCOUNT_TRIGGER_ATTR = "data-reticle-account-trigger";
|
|
6
6
|
export declare const ACCOUNT_MENU_ATTR = "data-reticle-account-menu";
|
|
7
7
|
export declare const ACCOUNT_SIGNOUT_ATTR = "data-reticle-account-signout";
|
|
8
|
+
export declare const TEAM_OPEN_ATTR = "data-reticle-team-open";
|
|
9
|
+
export declare const TEAM_SAVE_ATTR = "data-reticle-team-save";
|
|
10
|
+
export declare const TEAM_SLOT_ATTR = "data-reticle-team";
|
|
11
|
+
export declare const TEAM_TEXT: {
|
|
12
|
+
readonly OPEN: "Open on dashboard ↗";
|
|
13
|
+
readonly OPEN_TITLE: "This project's runs, kept for your team on the Reticle dashboard";
|
|
14
|
+
readonly SAVE_LINK: "Save runs for your team";
|
|
15
|
+
readonly SAVE_TITLE: `Keep every run, flow and Harness result on a dashboard your team shares. On Reticle, ${string}.`;
|
|
16
|
+
};
|
|
8
17
|
export declare const ACCOUNT_TEXT: {
|
|
9
18
|
readonly SIGNED_OUT: "Sign in";
|
|
10
|
-
readonly SIGNIN_TITLE: "Sign in through your browser. Also copies `reticle
|
|
11
|
-
readonly SIGNIN_COMMAND: "reticle
|
|
19
|
+
readonly SIGNIN_TITLE: "Sign in through your browser. Also copies `reticle connect`, for a terminal";
|
|
20
|
+
readonly SIGNIN_COMMAND: "reticle connect";
|
|
12
21
|
readonly DASHBOARD_TITLE: "Open this project on the dashboard";
|
|
13
22
|
readonly SYNC_TITLE: "Push to the dashboard now, instead of waiting for the next sync";
|
|
14
23
|
readonly COPIED: "Copied";
|
|
@@ -17,8 +26,8 @@ export declare const ACCOUNT_TEXT: {
|
|
|
17
26
|
readonly TRIGGER_TITLE: "Your Reticle account";
|
|
18
27
|
readonly SIGNED_IN_AS: "Signed in";
|
|
19
28
|
readonly DASHBOARD_ACTION: "Open dashboard";
|
|
20
|
-
readonly LINK_HINT: "Not linked — run `reticle
|
|
21
|
-
readonly LINK_COMMAND: "reticle
|
|
29
|
+
readonly LINK_HINT: "Not linked — run `reticle connect` to keep a record on the dashboard";
|
|
30
|
+
readonly LINK_COMMAND: "reticle connect";
|
|
22
31
|
readonly SIGNOUT_ACTION: "Copy sign-out command";
|
|
23
32
|
readonly SIGNOUT_TITLE: "Copy `reticle logout` to run in your terminal";
|
|
24
33
|
readonly SIGNOUT_COMMAND: "reticle logout";
|
|
@@ -27,15 +36,28 @@ export declare const ACCOUNT_TEXT: {
|
|
|
27
36
|
readonly HOST_LABEL: "Host";
|
|
28
37
|
readonly VERDICTS_LABEL: "Verdicts";
|
|
29
38
|
readonly DEFECTS_LABEL: "Defects found";
|
|
39
|
+
readonly PLAN_LABEL: "Plan";
|
|
40
|
+
readonly CREDITS_LABEL: "Credits";
|
|
41
|
+
readonly HARNESS_RUNS_LABEL: "Harness runs";
|
|
42
|
+
readonly MEMORY_LABEL: "Memory";
|
|
43
|
+
readonly ON_PLATFORM_LABEL: "Runs on dashboard";
|
|
30
44
|
};
|
|
31
45
|
export interface AccountDetails {
|
|
32
46
|
projectName?: string | undefined;
|
|
33
47
|
dashboardUrl?: string | undefined;
|
|
34
48
|
verdicts?: number | undefined;
|
|
35
49
|
defects?: number | undefined;
|
|
50
|
+
plan?: string | undefined;
|
|
51
|
+
credits?: string | undefined;
|
|
52
|
+
harnessRuns?: string | undefined;
|
|
53
|
+
memory?: string | undefined;
|
|
54
|
+
onPlatform?: string | undefined;
|
|
36
55
|
}
|
|
37
56
|
export declare function accountInitials(org: string | undefined): string;
|
|
38
57
|
export declare function accountControlHtml(account: AccountState | undefined, details?: AccountDetails, offerSignIn?: boolean): string;
|
|
58
|
+
export declare function platformDetails(config: HarnessConfig | undefined, sync: Readonly<Record<string, unknown>> | undefined): Pick<AccountDetails, 'plan' | 'credits' | 'harnessRuns' | 'memory' | 'onPlatform'>;
|
|
59
|
+
export declare function teamLinkHtml(account: AccountState | undefined, dashboardUrl: string | undefined): string;
|
|
60
|
+
export declare function paintAccountSlot(slot: HTMLElement, html: string): void;
|
|
39
61
|
export declare function accountCapsuleHtml(account: AccountState | undefined, dashboardUrl?: string, offerSignIn?: boolean): string;
|
|
40
62
|
export declare function syncButtonHtml(dashboardUrl: string | undefined): string;
|
|
41
63
|
export declare function mountAccountControl(root: HTMLElement, onSignIn?: () => void): () => void;
|
|
@@ -1,15 +1,27 @@
|
|
|
1
|
+
import { CreditKind } from '@reticlehq/core';
|
|
2
|
+
import { TRIAL_OFFER } from '@reticlehq/core/hud';
|
|
1
3
|
import { hiIconHtml, PRESENTER_ICON_SIZE, PresenterIcon } from './icons/presenter-icons.js';
|
|
2
4
|
import { esc, isSafeDashboardUrl } from './chrome/presenter-safe-html.js';
|
|
5
|
+
import { morphHtml } from './chrome/presenter-morph.js';
|
|
3
6
|
export const ACCOUNT_ROOT_ATTR = 'data-reticle-account';
|
|
4
7
|
export const ACCOUNT_SIGNIN_ATTR = 'data-reticle-account-signin';
|
|
5
8
|
export const SYNC_BTN_ATTR = 'data-reticle-sync-now';
|
|
6
9
|
export const ACCOUNT_TRIGGER_ATTR = 'data-reticle-account-trigger';
|
|
7
10
|
export const ACCOUNT_MENU_ATTR = 'data-reticle-account-menu';
|
|
8
11
|
export const ACCOUNT_SIGNOUT_ATTR = 'data-reticle-account-signout';
|
|
12
|
+
export const TEAM_OPEN_ATTR = 'data-reticle-team-open';
|
|
13
|
+
export const TEAM_SAVE_ATTR = 'data-reticle-team-save';
|
|
14
|
+
export const TEAM_SLOT_ATTR = 'data-reticle-team';
|
|
15
|
+
export const TEAM_TEXT = {
|
|
16
|
+
OPEN: 'Open on dashboard ↗',
|
|
17
|
+
OPEN_TITLE: "This project's runs, kept for your team on the Reticle dashboard",
|
|
18
|
+
SAVE_LINK: 'Save runs for your team',
|
|
19
|
+
SAVE_TITLE: `Keep every run, flow and Harness result on a dashboard your team shares. On Reticle, ${TRIAL_OFFER}.`,
|
|
20
|
+
};
|
|
9
21
|
export const ACCOUNT_TEXT = {
|
|
10
22
|
SIGNED_OUT: 'Sign in',
|
|
11
|
-
SIGNIN_TITLE: 'Sign in through your browser. Also copies `reticle
|
|
12
|
-
SIGNIN_COMMAND: 'reticle
|
|
23
|
+
SIGNIN_TITLE: 'Sign in through your browser. Also copies `reticle connect`, for a terminal',
|
|
24
|
+
SIGNIN_COMMAND: 'reticle connect',
|
|
13
25
|
DASHBOARD_TITLE: 'Open this project on the dashboard',
|
|
14
26
|
SYNC_TITLE: 'Push to the dashboard now, instead of waiting for the next sync',
|
|
15
27
|
COPIED: 'Copied',
|
|
@@ -18,8 +30,8 @@ export const ACCOUNT_TEXT = {
|
|
|
18
30
|
TRIGGER_TITLE: 'Your Reticle account',
|
|
19
31
|
SIGNED_IN_AS: 'Signed in',
|
|
20
32
|
DASHBOARD_ACTION: 'Open dashboard',
|
|
21
|
-
LINK_HINT: 'Not linked — run `reticle
|
|
22
|
-
LINK_COMMAND: 'reticle
|
|
33
|
+
LINK_HINT: 'Not linked — run `reticle connect` to keep a record on the dashboard',
|
|
34
|
+
LINK_COMMAND: 'reticle connect',
|
|
23
35
|
SIGNOUT_ACTION: 'Copy sign-out command',
|
|
24
36
|
SIGNOUT_TITLE: 'Copy `reticle logout` to run in your terminal',
|
|
25
37
|
SIGNOUT_COMMAND: 'reticle logout',
|
|
@@ -28,6 +40,11 @@ export const ACCOUNT_TEXT = {
|
|
|
28
40
|
HOST_LABEL: 'Host',
|
|
29
41
|
VERDICTS_LABEL: 'Verdicts',
|
|
30
42
|
DEFECTS_LABEL: 'Defects found',
|
|
43
|
+
PLAN_LABEL: 'Plan',
|
|
44
|
+
CREDITS_LABEL: 'Credits',
|
|
45
|
+
HARNESS_RUNS_LABEL: 'Harness runs',
|
|
46
|
+
MEMORY_LABEL: 'Memory',
|
|
47
|
+
ON_PLATFORM_LABEL: 'Runs on dashboard',
|
|
31
48
|
};
|
|
32
49
|
const ACCOUNT_COPIED_MS = 1200;
|
|
33
50
|
export function accountInitials(org) {
|
|
@@ -70,12 +87,20 @@ function accountMenuHtml(account, details) {
|
|
|
70
87
|
`<span class="reticle-account-org">${org.length > 0 ? esc(org) : ACCOUNT_TEXT.SIGNED_IN_AS}</span>` +
|
|
71
88
|
(account.email !== undefined && account.email.length > 0
|
|
72
89
|
? `<span class="reticle-account-email" title="${esc(account.email)}">${esc(account.email)}</span>`
|
|
73
|
-
:
|
|
90
|
+
:
|
|
91
|
+
org.length > 0
|
|
92
|
+
? `<span class="reticle-account-email">${ACCOUNT_TEXT.SIGNED_IN_AS}</span>`
|
|
93
|
+
: '') +
|
|
74
94
|
`</span></div>`;
|
|
75
95
|
const rows = detailRow(ACCOUNT_TEXT.HOST_LABEL, account.host) +
|
|
76
96
|
detailRow(ACCOUNT_TEXT.PROJECT_LABEL, details.projectName) +
|
|
77
97
|
detailRow(ACCOUNT_TEXT.VERDICTS_LABEL, details.verdicts !== undefined ? String(details.verdicts) : undefined) +
|
|
78
|
-
detailRow(ACCOUNT_TEXT.DEFECTS_LABEL, details.defects !== undefined ? String(details.defects) : undefined)
|
|
98
|
+
detailRow(ACCOUNT_TEXT.DEFECTS_LABEL, details.defects !== undefined ? String(details.defects) : undefined) +
|
|
99
|
+
detailRow(ACCOUNT_TEXT.ON_PLATFORM_LABEL, details.onPlatform) +
|
|
100
|
+
detailRow(ACCOUNT_TEXT.PLAN_LABEL, details.plan) +
|
|
101
|
+
detailRow(ACCOUNT_TEXT.CREDITS_LABEL, details.credits) +
|
|
102
|
+
detailRow(ACCOUNT_TEXT.HARNESS_RUNS_LABEL, details.harnessRuns) +
|
|
103
|
+
detailRow(ACCOUNT_TEXT.MEMORY_LABEL, details.memory);
|
|
79
104
|
const linked = details.dashboardUrl !== undefined && isSafeDashboardUrl(details.dashboardUrl);
|
|
80
105
|
const dashboard = linked
|
|
81
106
|
? `<a class="reticle-account-action" data-reticle-account-dashboard href="${esc(details.dashboardUrl ?? '')}" target="_blank" rel="noreferrer noopener" title="${ACCOUNT_TEXT.DASHBOARD_TITLE}">${hiIconHtml(PresenterIcon.VIEW, PRESENTER_ICON_SIZE.HELP)}<span>${ACCOUNT_TEXT.DASHBOARD_ACTION}</span></a>`
|
|
@@ -88,6 +113,58 @@ function accountMenuHtml(account, details) {
|
|
|
88
113
|
`<div class="reticle-account-actions">${dashboard}${signOut}</div>` +
|
|
89
114
|
`</div>`);
|
|
90
115
|
}
|
|
116
|
+
const PLAN_NAME = {
|
|
117
|
+
[CreditKind.FREE]: 'Free',
|
|
118
|
+
[CreditKind.TRIAL]: 'Trial',
|
|
119
|
+
[CreditKind.PAID]: 'Pro',
|
|
120
|
+
};
|
|
121
|
+
const plural = (n, one, many) => `${String(n)} ${1 === n ? one : many}`;
|
|
122
|
+
export function platformDetails(config, sync) {
|
|
123
|
+
const plan = config?.plan;
|
|
124
|
+
const onPlatform = sync?.['onPlatform'];
|
|
125
|
+
return {
|
|
126
|
+
...(plan === undefined
|
|
127
|
+
? {}
|
|
128
|
+
: {
|
|
129
|
+
plan: [
|
|
130
|
+
PLAN_NAME[plan.kind],
|
|
131
|
+
plan.daysLeft === undefined ? '' : `${plural(plan.daysLeft, 'day', 'days')} left`,
|
|
132
|
+
plan.seats === undefined ? '' : plural(plan.seats, 'seat', 'seats'),
|
|
133
|
+
]
|
|
134
|
+
.filter((part) => part.length > 0)
|
|
135
|
+
.join(' · '),
|
|
136
|
+
}),
|
|
137
|
+
...(config?.credits === undefined
|
|
138
|
+
? {}
|
|
139
|
+
: {
|
|
140
|
+
credits: `${Math.max(0, config.credits.limit - config.credits.used).toLocaleString('en-US')} of ${config.credits.limit.toLocaleString('en-US')} left`,
|
|
141
|
+
}),
|
|
142
|
+
...(config?.harnessRuns === undefined ? {} : { harnessRuns: String(config.harnessRuns) }),
|
|
143
|
+
...(config?.memoryEntries === undefined
|
|
144
|
+
? {}
|
|
145
|
+
: { memory: plural(config.memoryEntries, 'entry', 'entries') }),
|
|
146
|
+
...('number' === typeof onPlatform ? { onPlatform: String(onPlatform) } : {}),
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
export function teamLinkHtml(account, dashboardUrl) {
|
|
150
|
+
if (account === undefined || !account.signedIn)
|
|
151
|
+
return '';
|
|
152
|
+
if (dashboardUrl !== undefined && isSafeDashboardUrl(dashboardUrl))
|
|
153
|
+
return `<a ${TEAM_OPEN_ATTR} class="reticle-team-link" href="${esc(dashboardUrl)}" target="_blank" rel="noreferrer noopener" title="${esc(TEAM_TEXT.OPEN_TITLE)}">${TEAM_TEXT.OPEN}</a>`;
|
|
154
|
+
return `<button type="button" ${TEAM_SAVE_ATTR} class="reticle-team-link" title="${esc(TEAM_TEXT.SAVE_TITLE)}"><span>${TEAM_TEXT.SAVE_LINK}</span></button>`;
|
|
155
|
+
}
|
|
156
|
+
export function paintAccountSlot(slot, html) {
|
|
157
|
+
const open = null !== slot.querySelector(`[${ACCOUNT_MENU_ATTR}]:not([hidden])`);
|
|
158
|
+
morphHtml(slot, html);
|
|
159
|
+
if (!open)
|
|
160
|
+
return;
|
|
161
|
+
const menu = slot.querySelector(`[${ACCOUNT_MENU_ATTR}]`);
|
|
162
|
+
if (null === menu)
|
|
163
|
+
return;
|
|
164
|
+
menu.removeAttribute('hidden');
|
|
165
|
+
menu.setAttribute('aria-hidden', 'false');
|
|
166
|
+
slot.querySelector(`[${ACCOUNT_TRIGGER_ATTR}]`)?.setAttribute('aria-expanded', 'true');
|
|
167
|
+
}
|
|
91
168
|
export function accountCapsuleHtml(account, dashboardUrl, offerSignIn = false) {
|
|
92
169
|
return accountControlHtml(account, { dashboardUrl }, offerSignIn);
|
|
93
170
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type AgentLink } from '@reticlehq/core';
|
|
2
|
+
export declare const AGENT_LINK_HTML: string;
|
|
3
|
+
export declare const AGENT_LINK_CSS = "\n[data-reticle-chat-panel] .reticle-agent-spot{flex:none;display:flex;flex-direction:column;gap:3px;}\n[data-reticle-chat-panel] .reticle-agent-spot[hidden]{display:none;}\n[data-reticle-chat-panel] .reticle-agent-row{display:flex;align-items:center;gap:8px;min-width:0;min-height:30px;padding:0 var(--reticle-hud-space-2);}\n[data-reticle-chat-panel] .reticle-agent-dot{flex:none;width:7px;height:7px;border-radius:50%;background:var(--reticle-hud-text-faint);}\n[data-reticle-chat-panel] .reticle-agent-row[data-connected=\"1\"] .reticle-agent-dot{background:#4ade80;box-shadow:0 0 0 3px rgba(74,222,128,.15);}\n[data-reticle-chat-panel] .reticle-agent-said{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--reticle-hud-size-sm);color:var(--reticle-hud-text-muted);}\n[data-reticle-chat-panel] .reticle-agent-copy:focus-visible{outline:2px solid var(--reticle-hud-brand);outline-offset:0;}\n[data-reticle-chat-panel] .reticle-agent-copy{flex:none;height:22px;padding:0 9px;border:1px solid var(--reticle-hud-border-strong);border-radius:11px;background:transparent;color:var(--reticle-hud-text);font:inherit;font-size:11px;font-weight:600;cursor:pointer;white-space:nowrap;}\n[data-reticle-chat-panel] .reticle-agent-copy:hover{border-color:var(--reticle-hud-brand);color:var(--reticle-hud-brand);}\n[data-reticle-chat-panel] .reticle-agent-copy[hidden]{display:none;}\n";
|
|
4
|
+
export declare class AgentLinkView {
|
|
5
|
+
#private;
|
|
6
|
+
mount(root: HTMLElement, signal: AbortSignal): void;
|
|
7
|
+
teardown(): void;
|
|
8
|
+
paint(link: AgentLink | undefined): void;
|
|
9
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import {} from '@reticlehq/core';
|
|
2
|
+
import { REPORT_TEXT } from './chrome/presenter-report-copy.js';
|
|
3
|
+
const COPIED_FLASH_MS = 1600;
|
|
4
|
+
const TEXT = {
|
|
5
|
+
NONE: 'No coding agent connected',
|
|
6
|
+
named: (names) => `${names} connected`,
|
|
7
|
+
COPY: 'Copy prompt',
|
|
8
|
+
prompt: (url) => `Use Reticle to check ${url} in my running app, then tell me the verdict.`,
|
|
9
|
+
};
|
|
10
|
+
export const AGENT_LINK_HTML = `<div data-reticle-agent-spot class="reticle-agent-spot" hidden>
|
|
11
|
+
<div class="reticle-agent-row"><span data-reticle-agent-dot class="reticle-agent-dot" aria-hidden="true"></span><span data-reticle-agent-said class="reticle-agent-said">${TEXT.NONE}</span><button type="button" data-reticle-agent-copy class="reticle-agent-copy" aria-label="${REPORT_TEXT.COPY_PROMPT}" title="${REPORT_TEXT.COPY_PROMPT}">${TEXT.COPY}</button></div>
|
|
12
|
+
</div>`;
|
|
13
|
+
export const AGENT_LINK_CSS = `
|
|
14
|
+
[data-reticle-chat-panel] .reticle-agent-spot{flex:none;display:flex;flex-direction:column;gap:3px;}
|
|
15
|
+
[data-reticle-chat-panel] .reticle-agent-spot[hidden]{display:none;}
|
|
16
|
+
[data-reticle-chat-panel] .reticle-agent-row{display:flex;align-items:center;gap:8px;min-width:0;min-height:30px;padding:0 var(--reticle-hud-space-2);}
|
|
17
|
+
[data-reticle-chat-panel] .reticle-agent-dot{flex:none;width:7px;height:7px;border-radius:50%;background:var(--reticle-hud-text-faint);}
|
|
18
|
+
[data-reticle-chat-panel] .reticle-agent-row[data-connected="1"] .reticle-agent-dot{background:#4ade80;box-shadow:0 0 0 3px rgba(74,222,128,.15);}
|
|
19
|
+
[data-reticle-chat-panel] .reticle-agent-said{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--reticle-hud-size-sm);color:var(--reticle-hud-text-muted);}
|
|
20
|
+
[data-reticle-chat-panel] .reticle-agent-copy:focus-visible{outline:2px solid var(--reticle-hud-brand);outline-offset:0;}
|
|
21
|
+
[data-reticle-chat-panel] .reticle-agent-copy{flex:none;height:22px;padding:0 9px;border:1px solid var(--reticle-hud-border-strong);border-radius:11px;background:transparent;color:var(--reticle-hud-text);font:inherit;font-size:11px;font-weight:600;cursor:pointer;white-space:nowrap;}
|
|
22
|
+
[data-reticle-chat-panel] .reticle-agent-copy:hover{border-color:var(--reticle-hud-brand);color:var(--reticle-hud-brand);}
|
|
23
|
+
[data-reticle-chat-panel] .reticle-agent-copy[hidden]{display:none;}
|
|
24
|
+
`;
|
|
25
|
+
export class AgentLinkView {
|
|
26
|
+
#root;
|
|
27
|
+
mount(root, signal) {
|
|
28
|
+
this.#root = root;
|
|
29
|
+
root.querySelector('[data-reticle-agent-copy]')?.addEventListener('click', (event) => {
|
|
30
|
+
const button = event.currentTarget;
|
|
31
|
+
void navigator.clipboard
|
|
32
|
+
?.writeText(TEXT.prompt(location.href))
|
|
33
|
+
.catch(() => undefined)
|
|
34
|
+
.finally(() => {
|
|
35
|
+
if (!(button instanceof HTMLElement))
|
|
36
|
+
return;
|
|
37
|
+
button.textContent = REPORT_TEXT.COPIED;
|
|
38
|
+
window.setTimeout(() => (button.textContent = REPORT_TEXT.COPY_PROMPT), COPIED_FLASH_MS);
|
|
39
|
+
});
|
|
40
|
+
}, { signal });
|
|
41
|
+
}
|
|
42
|
+
teardown() {
|
|
43
|
+
this.#root = undefined;
|
|
44
|
+
}
|
|
45
|
+
paint(link) {
|
|
46
|
+
const root = this.#root;
|
|
47
|
+
const spot = root?.querySelector('[data-reticle-agent-spot]');
|
|
48
|
+
if (root === undefined || null === spot || spot === undefined)
|
|
49
|
+
return;
|
|
50
|
+
spot.hidden = link === undefined;
|
|
51
|
+
if (link === undefined)
|
|
52
|
+
return;
|
|
53
|
+
const connected = 0 < link.agents.length;
|
|
54
|
+
spot.querySelector('.reticle-agent-row')?.setAttribute('data-connected', connected ? '1' : '0');
|
|
55
|
+
const said = spot.querySelector('[data-reticle-agent-said]');
|
|
56
|
+
if (said !== null)
|
|
57
|
+
said.textContent = connected ? TEXT.named(link.agents.join(', ')) : TEXT.NONE;
|
|
58
|
+
const copy = spot.querySelector('[data-reticle-agent-copy]');
|
|
59
|
+
if (copy !== null)
|
|
60
|
+
copy.hidden = connected;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -1,21 +1,42 @@
|
|
|
1
|
-
import { type AccountState, type HarnessConfig } from '@reticlehq/core';
|
|
1
|
+
import { type AccountState, type HarnessConfig, type AgentLink, type HarnessDrive, type LastDrive } from '@reticlehq/core';
|
|
2
2
|
import type { AnnotationItem } from '../review/annotator.js';
|
|
3
|
-
export type ChatView = 'activity' | 'flows' | 'annotations';
|
|
3
|
+
export type ChatView = 'activity' | 'flows' | 'annotations' | 'harness';
|
|
4
4
|
export declare function platformBase(config: HarnessConfig | undefined, account: AccountState): string;
|
|
5
|
-
export
|
|
5
|
+
export interface HudDriveHost {
|
|
6
|
+
run(persona?: string): void;
|
|
7
|
+
stop(): void;
|
|
8
|
+
setHarness(on: boolean): void;
|
|
9
|
+
link(): void;
|
|
10
|
+
}
|
|
11
|
+
export declare const CHAT_VIEWS_HTML: string;
|
|
6
12
|
export declare const FLOWS_PAGE_HTML: string;
|
|
13
|
+
export declare const NAV_LABEL: {
|
|
14
|
+
readonly LOG: "Log";
|
|
15
|
+
readonly FLOWS: "Flows";
|
|
16
|
+
readonly NOTES: "Notes";
|
|
17
|
+
readonly IMPACT: "Impact";
|
|
18
|
+
readonly HARNESS: "Harness";
|
|
19
|
+
readonly SETTINGS: "Settings";
|
|
20
|
+
readonly HIDE: "Hide";
|
|
21
|
+
};
|
|
22
|
+
export declare const navLabelHtml: (text: string) => string;
|
|
7
23
|
export declare const CHAT_VIEWS_NAV_HTML: string;
|
|
24
|
+
export declare const HARNESS_PAGE_HTML: string;
|
|
8
25
|
export declare const ANNOTATIONS_HTML: string;
|
|
9
26
|
export declare const CHAT_VIEWS_CSS: string;
|
|
10
27
|
export declare class ChatViews {
|
|
11
28
|
#private;
|
|
12
|
-
constructor(
|
|
29
|
+
constructor(onImpact: () => void, onOpenChat: (view: ChatView) => void, drive?: HudDriveHost);
|
|
13
30
|
mount(root: HTMLElement): void;
|
|
14
31
|
teardown(): void;
|
|
15
32
|
open(view: ChatView): void;
|
|
16
33
|
closePage(): void;
|
|
34
|
+
setProjectId(projectId: string | undefined): void;
|
|
35
|
+
paintAgent(link: AgentLink | undefined): void;
|
|
17
36
|
paintAccount(account: AccountState | undefined): void;
|
|
37
|
+
paintDrive(drive: HarnessDrive | undefined, last?: LastDrive): void;
|
|
18
38
|
paintHarness(config: HarnessConfig | undefined): void;
|
|
19
39
|
paintImpact(verdicts: number): void;
|
|
40
|
+
setImpactOpen(open: boolean): void;
|
|
20
41
|
paintAnnotations(items: readonly AnnotationItem[]): void;
|
|
21
42
|
}
|