@farmslot/adapter-web 0.16.0 → 0.17.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/CHANGELOG.md +4 -0
- package/package.json +4 -4
- package/src/web-dapp/lib/hud.mjs +28 -25
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,10 @@ All notable changes to `@farmslot/adapter-web` are tracked here.
|
|
|
6
6
|
|
|
7
7
|
- Active-development baseline; add user-facing changes here before release or package publication.
|
|
8
8
|
|
|
9
|
+
## 0.17.0 - 2026-10-20
|
|
10
|
+
|
|
11
|
+
- The web-dapp HUD shows the current intent as a 16px main line with no RUN badge, whole in a 500px card that grows instead of clipping it, and the step that just finished as one muted `✓`/`✗` line. A finished run reads `Recipe passed` or `Recipe failed` in the outcome colour.
|
|
12
|
+
|
|
9
13
|
## 0.16.0 - 2026-10-19
|
|
10
14
|
|
|
11
15
|
- Align with `@farmslot/protocol` 0.59.0, `@farmslot/adapter-sdk` 0.24.0 and `@farmslot/recipe-runner` 0.45.0.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farmslot/adapter-web",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"description": "Web platform adapter for Farmslot recipes: resolve and launch an isolated Chromium, own its CDP port, load unpacked extensions, and keep macOS focus.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"exports": {
|
|
@@ -83,9 +83,9 @@
|
|
|
83
83
|
"prepublishOnly": "node ../../scripts/quality/check-farmslot-package-readiness.mjs --publish --packages @farmslot/adapter-web"
|
|
84
84
|
},
|
|
85
85
|
"dependencies": {
|
|
86
|
-
"@farmslot/adapter-sdk": "0.
|
|
87
|
-
"@farmslot/protocol": "0.
|
|
88
|
-
"@farmslot/recipe-runner": "0.
|
|
86
|
+
"@farmslot/adapter-sdk": "0.25.0",
|
|
87
|
+
"@farmslot/protocol": "0.60.0",
|
|
88
|
+
"@farmslot/recipe-runner": "0.46.0",
|
|
89
89
|
"ws": "^8.18.0"
|
|
90
90
|
},
|
|
91
91
|
"devDependencies": {
|
package/src/web-dapp/lib/hud.mjs
CHANGED
|
@@ -14,7 +14,11 @@ import { readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs';
|
|
|
14
14
|
import path from 'node:path';
|
|
15
15
|
|
|
16
16
|
import {
|
|
17
|
+
HUD_COLORS,
|
|
18
|
+
HUD_FINISHED_FONT_SIZE,
|
|
19
|
+
HUD_FINISHED_LINE_HEIGHT,
|
|
17
20
|
HUD_PANEL_BOUNDS,
|
|
21
|
+
hudFinishedLine,
|
|
18
22
|
hudIntentDisplay,
|
|
19
23
|
hudPlacement,
|
|
20
24
|
hudSecondaryText,
|
|
@@ -33,7 +37,7 @@ function progressOf(raw) {
|
|
|
33
37
|
}
|
|
34
38
|
|
|
35
39
|
// Fold one app.hud node into the previous state. A running node becomes the
|
|
36
|
-
// current step; a pass/fail node also becomes the "
|
|
40
|
+
// current step; a pass/fail node also becomes the "just finished" line, and the
|
|
37
41
|
// recipe-complete node closes the run.
|
|
38
42
|
export function nextHudState(prior, node = {}, nodeId = '') {
|
|
39
43
|
// A finished run's HUD stays up until the next run's first update replaces it.
|
|
@@ -98,30 +102,34 @@ export function clearHudState(runtimeDir) {
|
|
|
98
102
|
rmSync(hudFile(runtimeDir), { force: true });
|
|
99
103
|
}
|
|
100
104
|
|
|
105
|
+
// The card grows with the intent: nothing clips, clamps or ellipsizes it.
|
|
101
106
|
const STYLE = `
|
|
102
107
|
:host { all: initial; }
|
|
103
|
-
.hud { position: fixed; top: 220px; left: 12px; z-index: 2147483647; width: ${HUD_PANEL_BOUNDS.card.maxWidth}px; max-width: calc(100vw - 24px);
|
|
108
|
+
.hud { position: fixed; top: 220px; left: 12px; z-index: 2147483647; width: ${HUD_PANEL_BOUNDS.card.maxWidth}px; max-width: calc(100vw - 24px);
|
|
104
109
|
box-sizing: border-box; padding: 8px 10px; border-radius: 8px; border: 1px solid rgba(255,255,255,.18);
|
|
105
110
|
background: rgba(16,18,24,.82); color: #f2f4f7; font: 12px/1.35 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
106
111
|
pointer-events: none; user-select: none; box-shadow: 0 4px 16px rgba(0,0,0,.35); }
|
|
107
|
-
.row { display: flex; gap: 6px; align-items: baseline; }
|
|
112
|
+
.row { display: flex; gap: 6px; align-items: baseline; font-size: 11px; color: ${HUD_COLORS.muted}; }
|
|
108
113
|
.title { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; }
|
|
109
|
-
.step {
|
|
110
|
-
.intent { margin-top: 4px; }
|
|
111
|
-
.
|
|
112
|
-
.
|
|
113
|
-
.
|
|
114
|
-
.fail {
|
|
115
|
-
.
|
|
116
|
-
|
|
114
|
+
.step { font-variant-numeric: tabular-nums; }
|
|
115
|
+
.intent { margin-top: 4px; color: #fff; }
|
|
116
|
+
.intent.pass { color: ${HUD_COLORS.pass}; }
|
|
117
|
+
.intent.fail { color: ${HUD_COLORS.fail}; }
|
|
118
|
+
.last { margin-top: 4px; font-size: ${HUD_FINISHED_FONT_SIZE}px; line-height: ${HUD_FINISHED_LINE_HEIGHT}px; color: ${HUD_COLORS.muted}; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
119
|
+
.last.fail { color: ${HUD_COLORS.fail}; }
|
|
120
|
+
.error { margin-top: 2px; font-size: ${HUD_FINISHED_FONT_SIZE}px; line-height: ${HUD_FINISHED_LINE_HEIGHT}px; color: #ffb4b4;
|
|
121
|
+
display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
|
|
117
122
|
`;
|
|
118
123
|
|
|
119
124
|
// A self-contained page expression: draws (or clears, for null) the HUD when
|
|
120
125
|
// the document is on the selected origin, and skips an unchanged state/layout.
|
|
121
126
|
// The wallet screenshot consumer uses bottom-dock to keep footer controls clear.
|
|
122
127
|
export function hudRenderExpression(state, appOrigin, { layout = 'card' } = {}) {
|
|
128
|
+
const finished =
|
|
129
|
+
state && !state.finished ? hudFinishedLine(state.last, state.current?.nodeId) : null;
|
|
123
130
|
return `(() => {
|
|
124
131
|
const state = ${JSON.stringify(state ?? null)};
|
|
132
|
+
const finished = ${JSON.stringify(finished)};
|
|
125
133
|
const layout = ${JSON.stringify(layout)};
|
|
126
134
|
const docked = layout === 'bottom-dock';
|
|
127
135
|
if (location.origin !== ${JSON.stringify(String(appOrigin).replace(/\/$/u, ''))}) return { hud: false, reason: 'not-app-origin' };
|
|
@@ -148,7 +156,7 @@ export function hudRenderExpression(state, appOrigin, { layout = 'card' } = {})
|
|
|
148
156
|
const style = el('style', null, ${JSON.stringify(STYLE)});
|
|
149
157
|
const box = el('div', 'hud');
|
|
150
158
|
if (docked) {
|
|
151
|
-
Object.assign(box.style, { top: 'auto', bottom: '0', left: '0', right: '0', width: '100vw', maxWidth: 'none',
|
|
159
|
+
Object.assign(box.style, { top: 'auto', bottom: '0', left: '0', right: '0', width: '100vw', maxWidth: 'none', borderRadius: '0', padding: '5px 8px' });
|
|
152
160
|
} else if (state.position) {
|
|
153
161
|
box.style.top = state.position === 'top' ? '12px' : 'auto';
|
|
154
162
|
box.style.bottom = state.position === 'bottom' ? '12px' : 'auto';
|
|
@@ -160,21 +168,16 @@ export function hudRenderExpression(state, appOrigin, { layout = 'card' } = {})
|
|
|
160
168
|
if (progress) head.append(el('span', 'step', 'step ' + progress.current + '/' + progress.total));
|
|
161
169
|
box.append(head);
|
|
162
170
|
if (state.current) {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
const
|
|
166
|
-
const intent = el('
|
|
171
|
+
// A failing step stays the main line, in the fail colour, rather than repeating below.
|
|
172
|
+
const failing = state.last && state.last.status === 'fail' && state.last.nodeId === state.current.nodeId;
|
|
173
|
+
const tone = state.finished || (failing ? 'fail' : '');
|
|
174
|
+
const intent = el('div', tone ? 'intent ' + tone : 'intent', state.current.intent);
|
|
175
|
+
Object.assign(intent.style, intentStyle);
|
|
167
176
|
intent.setAttribute('data-farmslot-hud-intent', '');
|
|
168
|
-
|
|
169
|
-
box.append(line);
|
|
177
|
+
box.append(intent);
|
|
170
178
|
}
|
|
171
|
-
if (
|
|
172
|
-
|
|
173
|
-
Object.assign(line.style, intentStyle);
|
|
174
|
-
line.append(el('span', 'badge ' + state.last.status, state.last.status.toUpperCase()), ' ', state.last.intent);
|
|
175
|
-
box.append(line);
|
|
176
|
-
}
|
|
177
|
-
if (state.last && state.last.error) box.append(el('div', 'last error', state.last.error));
|
|
179
|
+
if (finished) box.append(el('div', 'last ' + finished.tone, finished.text));
|
|
180
|
+
if (state.last && state.last.error) box.append(el('div', 'error', state.last.error));
|
|
178
181
|
root.append(style, box);
|
|
179
182
|
document.documentElement.append(host);
|
|
180
183
|
let height;
|