@hansenexus/hud 0.3.0 → 0.4.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/README.md +186 -4
- package/dist/access-CNvJOwKM.d.ts +54 -0
- package/dist/capabilities-CjulXFQX.js +189 -0
- package/dist/{define-hud-BHQR8Lbv.d.ts → define-hud-BBzsSl8b.d.ts} +6 -1
- package/dist/env-DfxpPfs9.js +28 -0
- package/dist/env-vEjyJfPW.d.ts +17 -0
- package/dist/force-state-BaqWsmrf.js +153 -0
- package/dist/force-state-CCqoTfVB.d.ts +23 -0
- package/dist/handler-WmE4Lu7l.d.ts +39 -0
- package/dist/index-BYsdS-7d.d.ts +55 -0
- package/dist/index.d.ts +6 -36
- package/dist/index.js +119 -202
- package/dist/marker-C66LxOhJ.d.ts +9 -0
- package/dist/marker-CMrvxPmS.d.ts +12 -0
- package/dist/marker-DjeGvL-F.js +9 -0
- package/dist/marker-uZYPOJ4M.js +12 -0
- package/dist/markers.d.ts +3 -0
- package/dist/markers.js +3 -0
- package/dist/next.d.ts +3 -18
- package/dist/next.js +3 -28
- package/dist/payload-CLKDVZWl.d.ts +68 -0
- package/dist/plugins/access/server.d.ts +122 -0
- package/dist/plugins/access/server.js +339 -0
- package/dist/plugins/access.d.ts +41 -0
- package/dist/plugins/access.js +250 -0
- package/dist/plugins/agent/server.d.ts +129 -0
- package/dist/plugins/agent/server.js +429 -0
- package/dist/plugins/agent.d.ts +37 -0
- package/dist/plugins/agent.js +411 -0
- package/dist/plugins/design.d.ts +125 -0
- package/dist/plugins/design.js +619 -0
- package/dist/plugins/observe.d.ts +64 -0
- package/dist/plugins/observe.js +617 -0
- package/dist/plugins/ops/server.d.ts +82 -0
- package/dist/plugins/ops/server.js +380 -0
- package/dist/plugins/ops.d.ts +26 -0
- package/dist/plugins/ops.js +362 -0
- package/dist/plugins/vitals.js +3 -86
- package/dist/{plugins-1QmTmZyL.d.ts → plugins-CQ_0w1ot.d.ts} +39 -1
- package/dist/{plugins-CzUiTn_r.js → plugins-DVy_vaYr.js} +3 -1
- package/dist/review.d.ts +181 -0
- package/dist/review.js +1017 -0
- package/dist/selector-NSYSe7AZ.js +28 -0
- package/dist/server.d.ts +3 -39
- package/dist/server.js +1 -1
- package/dist/shortcut-U6ftVY06.js +222 -0
- package/dist/state-boundary.d.ts +26 -0
- package/dist/state-boundary.js +61 -0
- package/dist/styles--slk86ZQ.js +332 -0
- package/dist/types-DADBRiGk.d.ts +50 -0
- package/dist/types-QJUajwWq.js +35 -0
- package/dist/types-f3jlNxzw.d.ts +92 -0
- package/dist/vitals-panel-Dvc5dnR-.js +87 -0
- package/package.json +23 -3
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
import { i as parseShortcut, l as useGrab, n as isApplePlatform, s as matchComponentHints, t as formatShortcut } from "../shortcut-U6ftVY06.js";
|
|
2
|
+
import { i as definePlugin, n as HudApiError } from "../plugins-DVy_vaYr.js";
|
|
3
|
+
import { useCallback, useEffect, useState, useSyncExternalStore } from "react";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
//#region src/plugins/agent/styles.ts
|
|
6
|
+
/**
|
|
7
|
+
* The agent panels' styles. Each panel renders them in a `<style>` inside the
|
|
8
|
+
* HUD's shadow root, so the plugin brings its CSS without touching core's.
|
|
9
|
+
*/
|
|
10
|
+
const AGENT_CSS = `
|
|
11
|
+
.agent { display: grid; gap: 10px; }
|
|
12
|
+
.agent-row { display: flex; align-items: center; gap: 8px; }
|
|
13
|
+
.agent-grow { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
14
|
+
.agent-muted { color: var(--hud-fg-muted); }
|
|
15
|
+
.agent-mono { font-family: var(--hud-mono); font-size: 11px; }
|
|
16
|
+
.hud .agent-btn {
|
|
17
|
+
padding: 3px 10px;
|
|
18
|
+
border: 1px solid var(--hud-border);
|
|
19
|
+
border-radius: 6px;
|
|
20
|
+
background: var(--hud-bg-subtle);
|
|
21
|
+
}
|
|
22
|
+
.hud .agent-btn[data-primary] { background: var(--hud-accent); color: var(--hud-accent-fg); border-color: transparent; }
|
|
23
|
+
.hud .agent-btn:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
24
|
+
.agent-card {
|
|
25
|
+
display: grid;
|
|
26
|
+
gap: 2px;
|
|
27
|
+
padding: 6px 8px;
|
|
28
|
+
border: 1px solid var(--hud-border);
|
|
29
|
+
border-radius: 6px;
|
|
30
|
+
background: var(--hud-bg-subtle);
|
|
31
|
+
}
|
|
32
|
+
.agent textarea {
|
|
33
|
+
font: inherit;
|
|
34
|
+
color: inherit;
|
|
35
|
+
background: var(--hud-bg);
|
|
36
|
+
border: 1px solid var(--hud-border);
|
|
37
|
+
border-radius: 6px;
|
|
38
|
+
padding: 6px 8px;
|
|
39
|
+
min-height: 56px;
|
|
40
|
+
resize: vertical;
|
|
41
|
+
}
|
|
42
|
+
.agent fieldset { border: 0; margin: 0; padding: 0; display: grid; gap: 4px; }
|
|
43
|
+
.agent label.agent-target { display: flex; gap: 6px; align-items: flex-start; cursor: pointer; }
|
|
44
|
+
.agent label.agent-target[data-disabled] { opacity: 0.55; cursor: not-allowed; }
|
|
45
|
+
.agent-list { display: grid; gap: 4px; margin: 0; padding: 0; list-style: none; }
|
|
46
|
+
.agent-badge {
|
|
47
|
+
flex: none;
|
|
48
|
+
padding: 0 6px;
|
|
49
|
+
border-radius: 999px;
|
|
50
|
+
border: 1px solid currentColor;
|
|
51
|
+
font-size: 10px;
|
|
52
|
+
line-height: 16px;
|
|
53
|
+
color: var(--hud-fg-muted);
|
|
54
|
+
}
|
|
55
|
+
.agent-badge[data-status="running"], .agent-badge[data-status="dispatched"] { color: var(--hud-good); }
|
|
56
|
+
.agent-badge[data-status="sending"], .agent-badge[data-status="queued"] { color: var(--hud-warn); }
|
|
57
|
+
.agent-badge[data-status="failed"] { color: var(--hud-poor); }
|
|
58
|
+
.agent details pre { max-height: 160px; overflow: auto; margin: 4px 0 0; font-size: 10px; }
|
|
59
|
+
`;
|
|
60
|
+
//#endregion
|
|
61
|
+
//#region src/plugins/agent/dispatch-panel.tsx
|
|
62
|
+
/**
|
|
63
|
+
* Runs dispatched from this page. It outlives the panel (closing it unmounts
|
|
64
|
+
* the component), so it lives with the plugin instance.
|
|
65
|
+
*/
|
|
66
|
+
function createRunLog() {
|
|
67
|
+
let runs = [];
|
|
68
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
69
|
+
const set = (next) => {
|
|
70
|
+
runs = next;
|
|
71
|
+
for (const listener of listeners) listener();
|
|
72
|
+
};
|
|
73
|
+
return {
|
|
74
|
+
get: () => runs,
|
|
75
|
+
subscribe: (listener) => {
|
|
76
|
+
listeners.add(listener);
|
|
77
|
+
return () => listeners.delete(listener);
|
|
78
|
+
},
|
|
79
|
+
add: (run) => set([run, ...runs].slice(0, 20)),
|
|
80
|
+
update: (id, patch) => set(runs.map((run) => run.id === id ? {
|
|
81
|
+
...run,
|
|
82
|
+
...patch
|
|
83
|
+
} : run))
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function errorText(error) {
|
|
87
|
+
if (error instanceof HudApiError) return error.body?.error ?? `HTTP ${error.status}`;
|
|
88
|
+
return error instanceof Error ? error.message : String(error);
|
|
89
|
+
}
|
|
90
|
+
function DispatchPanel({ ctx, log, componentHints }) {
|
|
91
|
+
const { grabbing, payload } = useGrab(ctx.grab);
|
|
92
|
+
const runs = useSyncExternalStore(log.subscribe, log.get, log.get);
|
|
93
|
+
const [targets, setTargets] = useState(null);
|
|
94
|
+
const [targetsError, setTargetsError] = useState(null);
|
|
95
|
+
const [target, setTarget] = useState(null);
|
|
96
|
+
const [note, setNote] = useState("");
|
|
97
|
+
useEffect(() => {
|
|
98
|
+
let cancelled = false;
|
|
99
|
+
ctx.api("/targets").then((list) => {
|
|
100
|
+
if (cancelled) return;
|
|
101
|
+
setTargets(list);
|
|
102
|
+
setTarget((current) => current ?? list.find((t) => t.available)?.id ?? null);
|
|
103
|
+
}).catch((error) => {
|
|
104
|
+
if (!cancelled) setTargetsError(errorText(error));
|
|
105
|
+
});
|
|
106
|
+
return () => {
|
|
107
|
+
cancelled = true;
|
|
108
|
+
};
|
|
109
|
+
}, [ctx]);
|
|
110
|
+
const hints = payload ? matchComponentHints(componentHints, payload.route, payload.anchor.label) : [];
|
|
111
|
+
const canSend = target !== null && (payload !== null || note.trim() !== "");
|
|
112
|
+
async function send() {
|
|
113
|
+
if (!target || !canSend) return;
|
|
114
|
+
const id = `${Date.now()}`;
|
|
115
|
+
const title = [payload?.anchor.label, note.trim().split("\n")[0]].filter(Boolean).join(" · ");
|
|
116
|
+
const body = {
|
|
117
|
+
target,
|
|
118
|
+
note,
|
|
119
|
+
payload,
|
|
120
|
+
hints
|
|
121
|
+
};
|
|
122
|
+
log.add({
|
|
123
|
+
id,
|
|
124
|
+
title: title || "dispatch",
|
|
125
|
+
target,
|
|
126
|
+
status: "sending"
|
|
127
|
+
});
|
|
128
|
+
ctx.grab.clear();
|
|
129
|
+
setNote("");
|
|
130
|
+
try {
|
|
131
|
+
const receipt = await ctx.api("/dispatch", {
|
|
132
|
+
method: "POST",
|
|
133
|
+
headers: { "content-type": "application/json" },
|
|
134
|
+
body: JSON.stringify(body)
|
|
135
|
+
});
|
|
136
|
+
log.update(id, {
|
|
137
|
+
status: "dispatched",
|
|
138
|
+
detail: [receipt.runId, receipt.detail].filter(Boolean).join(" · ")
|
|
139
|
+
});
|
|
140
|
+
} catch (error) {
|
|
141
|
+
log.update(id, {
|
|
142
|
+
status: "failed",
|
|
143
|
+
detail: errorText(error)
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
148
|
+
className: "agent",
|
|
149
|
+
children: [
|
|
150
|
+
/* @__PURE__ */ jsx("style", { children: AGENT_CSS }),
|
|
151
|
+
payload ? /* @__PURE__ */ jsxs("div", {
|
|
152
|
+
className: "agent-card",
|
|
153
|
+
children: [
|
|
154
|
+
/* @__PURE__ */ jsxs("div", {
|
|
155
|
+
className: "agent-row",
|
|
156
|
+
children: [/* @__PURE__ */ jsxs("strong", {
|
|
157
|
+
className: "agent-grow",
|
|
158
|
+
title: payload.anchor.label,
|
|
159
|
+
children: [payload.component ? `<${payload.component.name}> ` : "", payload.anchor.label]
|
|
160
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
161
|
+
type: "button",
|
|
162
|
+
className: "agent-btn",
|
|
163
|
+
"aria-label": "Discard grab",
|
|
164
|
+
onClick: ctx.grab.clear,
|
|
165
|
+
children: "✕"
|
|
166
|
+
})]
|
|
167
|
+
}),
|
|
168
|
+
payload.component?.source && /* @__PURE__ */ jsx("span", {
|
|
169
|
+
className: "agent-mono agent-muted",
|
|
170
|
+
children: payload.component.source
|
|
171
|
+
}),
|
|
172
|
+
/* @__PURE__ */ jsxs("span", {
|
|
173
|
+
className: "agent-mono agent-muted agent-grow",
|
|
174
|
+
title: payload.anchor.selector,
|
|
175
|
+
children: [
|
|
176
|
+
payload.route,
|
|
177
|
+
" · ",
|
|
178
|
+
payload.anchor.selector || payload.anchor.tag
|
|
179
|
+
]
|
|
180
|
+
}),
|
|
181
|
+
/* @__PURE__ */ jsxs("details", { children: [/* @__PURE__ */ jsx("summary", {
|
|
182
|
+
className: "agent-muted",
|
|
183
|
+
children: "Payload"
|
|
184
|
+
}), /* @__PURE__ */ jsx("pre", {
|
|
185
|
+
className: "agent-mono",
|
|
186
|
+
children: JSON.stringify({
|
|
187
|
+
...payload,
|
|
188
|
+
hints
|
|
189
|
+
}, null, 2)
|
|
190
|
+
})] })
|
|
191
|
+
]
|
|
192
|
+
}) : /* @__PURE__ */ jsxs("div", {
|
|
193
|
+
className: "agent-row",
|
|
194
|
+
children: [/* @__PURE__ */ jsx("button", {
|
|
195
|
+
type: "button",
|
|
196
|
+
className: "agent-btn",
|
|
197
|
+
"data-primary": "",
|
|
198
|
+
"aria-pressed": grabbing,
|
|
199
|
+
onClick: grabbing ? ctx.grab.cancel : ctx.grab.start,
|
|
200
|
+
children: grabbing ? "Cancel grab" : "⌖ Grab element"
|
|
201
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
202
|
+
className: "agent-muted",
|
|
203
|
+
children: [
|
|
204
|
+
"or ",
|
|
205
|
+
formatShortcut(parseShortcut("mod+shift+g"), isApplePlatform()),
|
|
206
|
+
", then click anything on the page"
|
|
207
|
+
]
|
|
208
|
+
})]
|
|
209
|
+
}),
|
|
210
|
+
/* @__PURE__ */ jsx("textarea", {
|
|
211
|
+
"aria-label": "Instruction",
|
|
212
|
+
placeholder: "Instruction, e.g. the CTA feels heavy, try the ghost variant",
|
|
213
|
+
value: note,
|
|
214
|
+
onChange: (e) => setNote(e.target.value)
|
|
215
|
+
}),
|
|
216
|
+
targetsError && /* @__PURE__ */ jsxs("p", {
|
|
217
|
+
className: "empty",
|
|
218
|
+
children: ["Targets unavailable: ", targetsError]
|
|
219
|
+
}),
|
|
220
|
+
targets && targets.length === 0 && /* @__PURE__ */ jsx("p", {
|
|
221
|
+
className: "empty",
|
|
222
|
+
children: "No dispatch provider configured on the server."
|
|
223
|
+
}),
|
|
224
|
+
targets && targets.length > 0 && /* @__PURE__ */ jsx("fieldset", { children: targets.map((t) => /* @__PURE__ */ jsxs("label", {
|
|
225
|
+
className: "agent-target",
|
|
226
|
+
...t.available ? {} : { "data-disabled": "" },
|
|
227
|
+
children: [/* @__PURE__ */ jsx("input", {
|
|
228
|
+
type: "radio",
|
|
229
|
+
name: "agent-target",
|
|
230
|
+
checked: target === t.id,
|
|
231
|
+
disabled: !t.available,
|
|
232
|
+
onChange: () => setTarget(t.id)
|
|
233
|
+
}), /* @__PURE__ */ jsxs("span", { children: [
|
|
234
|
+
/* @__PURE__ */ jsx("span", { children: t.label }),
|
|
235
|
+
/* @__PURE__ */ jsx("br", {}),
|
|
236
|
+
/* @__PURE__ */ jsx("span", {
|
|
237
|
+
className: "agent-muted",
|
|
238
|
+
children: t.available ? t.description ?? t.id : t.reason
|
|
239
|
+
})
|
|
240
|
+
] })]
|
|
241
|
+
}, t.id)) }),
|
|
242
|
+
/* @__PURE__ */ jsx("div", {
|
|
243
|
+
className: "agent-row",
|
|
244
|
+
children: /* @__PURE__ */ jsx("button", {
|
|
245
|
+
type: "button",
|
|
246
|
+
className: "agent-btn",
|
|
247
|
+
"data-primary": "",
|
|
248
|
+
disabled: !canSend,
|
|
249
|
+
onClick: send,
|
|
250
|
+
children: "Dispatch"
|
|
251
|
+
})
|
|
252
|
+
}),
|
|
253
|
+
runs.length > 0 && /* @__PURE__ */ jsx("ul", {
|
|
254
|
+
className: "agent-list",
|
|
255
|
+
"aria-label": "Dispatched runs",
|
|
256
|
+
children: runs.map((run) => /* @__PURE__ */ jsxs("li", {
|
|
257
|
+
className: "agent-row agent-mono",
|
|
258
|
+
children: [
|
|
259
|
+
/* @__PURE__ */ jsx("span", {
|
|
260
|
+
className: "agent-badge",
|
|
261
|
+
"data-status": run.status,
|
|
262
|
+
children: run.status
|
|
263
|
+
}),
|
|
264
|
+
/* @__PURE__ */ jsx("span", {
|
|
265
|
+
className: "agent-grow",
|
|
266
|
+
title: run.title,
|
|
267
|
+
children: run.title
|
|
268
|
+
}),
|
|
269
|
+
/* @__PURE__ */ jsxs("span", {
|
|
270
|
+
className: "agent-muted agent-grow",
|
|
271
|
+
title: run.detail,
|
|
272
|
+
children: [run.target, run.detail ? ` · ${run.detail}` : ""]
|
|
273
|
+
})
|
|
274
|
+
]
|
|
275
|
+
}, run.id))
|
|
276
|
+
})
|
|
277
|
+
]
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
//#endregion
|
|
281
|
+
//#region src/plugins/agent/sessions-panel.tsx
|
|
282
|
+
function age(iso) {
|
|
283
|
+
if (!iso) return "";
|
|
284
|
+
const seconds = Math.max(0, Math.round((Date.now() - Date.parse(iso)) / 1e3));
|
|
285
|
+
if (seconds < 60) return `${seconds}s`;
|
|
286
|
+
if (seconds < 3600) return `${Math.round(seconds / 60)}m`;
|
|
287
|
+
if (seconds < 86400) return `${Math.round(seconds / 3600)}h`;
|
|
288
|
+
return `${Math.round(seconds / 86400)}d`;
|
|
289
|
+
}
|
|
290
|
+
function SessionRow({ session }) {
|
|
291
|
+
return /* @__PURE__ */ jsxs("li", {
|
|
292
|
+
className: "agent-row agent-mono",
|
|
293
|
+
title: session.detail ?? session.id,
|
|
294
|
+
children: [
|
|
295
|
+
/* @__PURE__ */ jsx("span", {
|
|
296
|
+
className: "agent-badge",
|
|
297
|
+
"data-status": session.status,
|
|
298
|
+
children: session.status
|
|
299
|
+
}),
|
|
300
|
+
/* @__PURE__ */ jsx("span", {
|
|
301
|
+
className: "agent-grow",
|
|
302
|
+
children: session.title
|
|
303
|
+
}),
|
|
304
|
+
/* @__PURE__ */ jsxs("span", {
|
|
305
|
+
className: "agent-muted",
|
|
306
|
+
children: [
|
|
307
|
+
session.provider,
|
|
308
|
+
" ",
|
|
309
|
+
age(session.updatedAt ?? session.startedAt)
|
|
310
|
+
]
|
|
311
|
+
})
|
|
312
|
+
]
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
function SessionsPanel({ ctx, intervalMs }) {
|
|
316
|
+
const [data, setData] = useState(null);
|
|
317
|
+
const [error, setError] = useState(null);
|
|
318
|
+
const load = useCallback(async () => {
|
|
319
|
+
try {
|
|
320
|
+
setData(await ctx.api("/sessions"));
|
|
321
|
+
setError(null);
|
|
322
|
+
} catch (e) {
|
|
323
|
+
setError(e instanceof HudApiError ? `HTTP ${e.status}` : String(e));
|
|
324
|
+
}
|
|
325
|
+
}, [ctx]);
|
|
326
|
+
useEffect(() => {
|
|
327
|
+
load();
|
|
328
|
+
const timer = setInterval(() => {
|
|
329
|
+
if (!document.hidden) load();
|
|
330
|
+
}, intervalMs);
|
|
331
|
+
return () => clearInterval(timer);
|
|
332
|
+
}, [load, intervalMs]);
|
|
333
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
334
|
+
className: "agent",
|
|
335
|
+
children: [
|
|
336
|
+
/* @__PURE__ */ jsx("style", { children: AGENT_CSS }),
|
|
337
|
+
/* @__PURE__ */ jsxs("div", {
|
|
338
|
+
className: "agent-row",
|
|
339
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
340
|
+
className: "agent-grow agent-muted",
|
|
341
|
+
children: data ? `${data.sessions.length} sessions` : "Loading…"
|
|
342
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
343
|
+
type: "button",
|
|
344
|
+
className: "agent-btn",
|
|
345
|
+
onClick: () => void load(),
|
|
346
|
+
children: "Refresh"
|
|
347
|
+
})]
|
|
348
|
+
}),
|
|
349
|
+
error && /* @__PURE__ */ jsxs("p", {
|
|
350
|
+
className: "empty",
|
|
351
|
+
children: ["Sessions unavailable: ", error]
|
|
352
|
+
}),
|
|
353
|
+
data?.errors.map((e) => /* @__PURE__ */ jsxs("p", {
|
|
354
|
+
className: "empty",
|
|
355
|
+
children: [
|
|
356
|
+
e.provider,
|
|
357
|
+
": ",
|
|
358
|
+
e.error
|
|
359
|
+
]
|
|
360
|
+
}, e.provider)),
|
|
361
|
+
data && data.sessions.length === 0 && /* @__PURE__ */ jsx("p", {
|
|
362
|
+
className: "empty",
|
|
363
|
+
children: "No sessions."
|
|
364
|
+
}),
|
|
365
|
+
data && data.sessions.length > 0 && /* @__PURE__ */ jsx("ul", {
|
|
366
|
+
className: "agent-list",
|
|
367
|
+
"aria-label": "Agent sessions",
|
|
368
|
+
children: data.sessions.map((session) => /* @__PURE__ */ jsx(SessionRow, { session }, `${session.provider}:${session.id}`))
|
|
369
|
+
})
|
|
370
|
+
]
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
//#endregion
|
|
374
|
+
//#region src/plugins/agent/index.tsx
|
|
375
|
+
/**
|
|
376
|
+
* Dispatch panel: the last grab plus an instruction, sent to one of the
|
|
377
|
+
* server's providers (`hermes()`, `claudeCode()`). Mount the server half from
|
|
378
|
+
* `@hansenexus/hud/plugins/agent/server` in the catch-all route.
|
|
379
|
+
*/
|
|
380
|
+
function agentDispatch({ componentHints, openOnGrab = true } = {}) {
|
|
381
|
+
const log = createRunLog();
|
|
382
|
+
function Panel({ ctx }) {
|
|
383
|
+
return /* @__PURE__ */ jsx(DispatchPanel, {
|
|
384
|
+
ctx,
|
|
385
|
+
log,
|
|
386
|
+
componentHints
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
return definePlugin({
|
|
390
|
+
id: "agent-dispatch",
|
|
391
|
+
title: "Dispatch",
|
|
392
|
+
panel: Panel,
|
|
393
|
+
...openOnGrab ? { onGrab: (_payload, ctx) => ctx.open() } : {}
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
/** Sessions panel: runs and sessions of every provider that lists them. */
|
|
397
|
+
function agentSessions({ intervalMs = 1e4 } = {}) {
|
|
398
|
+
function Panel({ ctx }) {
|
|
399
|
+
return /* @__PURE__ */ jsx(SessionsPanel, {
|
|
400
|
+
ctx,
|
|
401
|
+
intervalMs
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
return definePlugin({
|
|
405
|
+
id: "agent-sessions",
|
|
406
|
+
title: "Sessions",
|
|
407
|
+
panel: Panel
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
//#endregion
|
|
411
|
+
export { agentDispatch, agentSessions };
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { c as HudPluginProps } from "../plugins-CQ_0w1ot.js";
|
|
2
|
+
import { i as ForcedState, n as FORCE_STATE_MARKER, r as FORCE_STATE_PARAM, t as FORCED_STATES } from "../force-state-CCqoTfVB.js";
|
|
3
|
+
//#region src/plugins/design/force-state-panel.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Pill content: how many boundaries are forced, by toggle or param. Uses the
|
|
6
|
+
* core `.dot`, since the plugin stylesheet only loads with the panel.
|
|
7
|
+
*/
|
|
8
|
+
declare function ForceStatePill(): import("react").JSX.Element;
|
|
9
|
+
/**
|
|
10
|
+
* Toggles every mounted `StateBoundary` between its real state and a forced
|
|
11
|
+
* loading, empty or error. Toggles live in memory: a reload returns every
|
|
12
|
+
* boundary to auto, so a forgotten toggle cannot outlive the page.
|
|
13
|
+
*/
|
|
14
|
+
declare function ForceStatePanel(): import("react").JSX.Element;
|
|
15
|
+
//#endregion
|
|
16
|
+
//#region src/plugins/design/tokens.d.ts
|
|
17
|
+
interface HudTokenDescriptor {
|
|
18
|
+
/** CSS custom property, including the leading dashes (e.g. `--primary`). */
|
|
19
|
+
cssVar: string;
|
|
20
|
+
/** Short display label; defaults to the var name without its leading dashes. */
|
|
21
|
+
label?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Scope attribute the design system hangs its tokens on, with an optional
|
|
25
|
+
* value: `{ attribute: "data-theme", value: "brand" }` matches
|
|
26
|
+
* `[data-theme="brand"] { --primary: … }`. Omit for `:root`-scoped tokens.
|
|
27
|
+
*/
|
|
28
|
+
interface HudTokenScope {
|
|
29
|
+
attribute: string;
|
|
30
|
+
value?: string;
|
|
31
|
+
}
|
|
32
|
+
interface HudTokenGroup {
|
|
33
|
+
label: string;
|
|
34
|
+
/** Var names (`"--primary"`) or descriptors with a label. */
|
|
35
|
+
tokens: readonly (string | HudTokenDescriptor)[];
|
|
36
|
+
scope?: HudTokenScope;
|
|
37
|
+
}
|
|
38
|
+
/** What an app tells the Tokens panel about its design system. */
|
|
39
|
+
interface HudTokensAdapter {
|
|
40
|
+
groups: readonly HudTokenGroup[];
|
|
41
|
+
/** Where the tokens live, shown as a hint (e.g. `src/app/globals.css`). */
|
|
42
|
+
sourceHint?: string;
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region src/plugins/design/variants-panel.d.ts
|
|
46
|
+
interface HudVariantCategory {
|
|
47
|
+
id: string;
|
|
48
|
+
name: string;
|
|
49
|
+
/** Registry status: "active" renders as votable, "decided" as settled. */
|
|
50
|
+
status: string;
|
|
51
|
+
alternativeCount: number;
|
|
52
|
+
/** Domain bucket (marketing, admin, shared …) for grouping. Default "shared". */
|
|
53
|
+
domain?: string;
|
|
54
|
+
}
|
|
55
|
+
interface HudGenerateRequest {
|
|
56
|
+
/** Repo-relative component path. */
|
|
57
|
+
path: string;
|
|
58
|
+
brief: string;
|
|
59
|
+
count: number;
|
|
60
|
+
}
|
|
61
|
+
interface HudGenerateResult {
|
|
62
|
+
ok: boolean;
|
|
63
|
+
/** Where the queued brief landed, on success. */
|
|
64
|
+
markerPath?: string;
|
|
65
|
+
error?: string;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* What an app tells the Variants panel about its variant registry. The HUD
|
|
69
|
+
* owns no registry: an app maps its own (a static list, or a loader against
|
|
70
|
+
* hn-monorepo#2552's variant groups) onto this shape.
|
|
71
|
+
*/
|
|
72
|
+
interface HudVariantsAdapter {
|
|
73
|
+
/** The categories, or a loader the panel calls each time it opens. */
|
|
74
|
+
categories: readonly HudVariantCategory[] | (() => Promise<readonly HudVariantCategory[]>);
|
|
75
|
+
/** Deep link to the full review dashboard, where voting happens. */
|
|
76
|
+
reviewHref?: string;
|
|
77
|
+
/** Deep link for one category's drill-in page. */
|
|
78
|
+
categoryHref?: (categoryId: string) => string;
|
|
79
|
+
/** Opens an in-page preview for a category; wins over `categoryHref`. */
|
|
80
|
+
openPreview?: (categoryId: string) => void;
|
|
81
|
+
/**
|
|
82
|
+
* Queues a variant-generation brief. Shown only when the tier grants
|
|
83
|
+
* `variants.generate`. The human stays in the loop: queue, not dispatch.
|
|
84
|
+
*/
|
|
85
|
+
generate?: (request: HudGenerateRequest) => Promise<HudGenerateResult>;
|
|
86
|
+
}
|
|
87
|
+
//#endregion
|
|
88
|
+
//#region src/plugins/design/index.d.ts
|
|
89
|
+
/**
|
|
90
|
+
* Live swatches of the host app's design tokens. Values are read from the
|
|
91
|
+
* host document, outside the HUD's shadow root, so scoped and themed tokens
|
|
92
|
+
* show what the page actually renders. Client only.
|
|
93
|
+
*/
|
|
94
|
+
export declare function tokens(adapter: HudTokensAdapter): {
|
|
95
|
+
readonly id: "tokens";
|
|
96
|
+
readonly title: "Tokens";
|
|
97
|
+
readonly panel: () => import("react").JSX.Element;
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* The app's variant categories and the generate-brief queue, over an adapter
|
|
101
|
+
* onto the app's own registry. Generating needs `variants.generate`. Client only.
|
|
102
|
+
*/
|
|
103
|
+
export declare function variants(adapter: HudVariantsAdapter): {
|
|
104
|
+
readonly id: "variants";
|
|
105
|
+
readonly title: "Variants";
|
|
106
|
+
readonly panel: ({ ctx }: HudPluginProps) => import("react").JSX.Element;
|
|
107
|
+
};
|
|
108
|
+
/**
|
|
109
|
+
* Forces the page's `StateBoundary`s (`@hansenexus/hud/state-boundary`) to
|
|
110
|
+
* loading, empty or error. The pill shows how many are forced. Client only.
|
|
111
|
+
*/
|
|
112
|
+
export declare function forceState(): {
|
|
113
|
+
readonly id: "states";
|
|
114
|
+
readonly title: "States";
|
|
115
|
+
readonly capability: "state.force";
|
|
116
|
+
readonly pill: typeof ForceStatePill;
|
|
117
|
+
readonly panel: typeof ForceStatePanel;
|
|
118
|
+
readonly commands: readonly [{
|
|
119
|
+
readonly id: "reset";
|
|
120
|
+
readonly title: "Reset forced states";
|
|
121
|
+
readonly run: () => void;
|
|
122
|
+
}];
|
|
123
|
+
};
|
|
124
|
+
//#endregion
|
|
125
|
+
export { FORCED_STATES, FORCE_STATE_MARKER, FORCE_STATE_PARAM, type ForcedState, type HudGenerateRequest, type HudGenerateResult, type HudTokenDescriptor, type HudTokenGroup, type HudTokenScope, type HudTokensAdapter, type HudVariantCategory, type HudVariantsAdapter };
|