@hansenexus/hud 0.1.0 → 0.2.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.
Files changed (91) hide show
  1. package/README.md +42 -23
  2. package/dist/index.d.ts +39 -0
  3. package/dist/index.js +399 -0
  4. package/package.json +45 -136
  5. package/chunk-0cj8dkk7.js +0 -127
  6. package/chunk-1atxwdhw.js +0 -48
  7. package/chunk-24vrg16w.js +0 -39
  8. package/chunk-3j9sm249.js +0 -26
  9. package/chunk-50pq4sg6.js +0 -41
  10. package/chunk-5gtx3pza.js +0 -9
  11. package/chunk-6gw4x08j.js +0 -264
  12. package/chunk-6jt8yg4m.js +0 -117
  13. package/chunk-71se605m.js +0 -85
  14. package/chunk-82nm9wcg.js +0 -316
  15. package/chunk-8tam7r3h.js +0 -68
  16. package/chunk-babjpqkb.js +0 -52
  17. package/chunk-c5y856ad.js +0 -98
  18. package/chunk-ghxh8926.js +0 -172
  19. package/chunk-hc2g0n35.js +0 -24
  20. package/chunk-k0vr8dsy.js +0 -179
  21. package/chunk-k50yfp5d.js +0 -166
  22. package/chunk-kyeb6qeq.js +0 -95
  23. package/chunk-msqkkqw7.js +0 -140
  24. package/chunk-nm82wr8r.js +0 -58
  25. package/chunk-r06bpmy6.js +0 -79
  26. package/chunk-t9eh4t0b.js +0 -89
  27. package/chunk-tf774c4w.js +0 -115
  28. package/chunk-v086j53b.js +0 -19
  29. package/chunk-wspz08q7.js +0 -67
  30. package/chunk-xezxydm3.js +0 -47
  31. package/chunk-xjn0896g.js +0 -574
  32. package/chunk-xztw0xyt.js +0 -113
  33. package/chunk-zzrpd92r.js +0 -172
  34. package/core/access.d.mts +0 -53
  35. package/core/access.js +0 -27
  36. package/core/api-types.d.mts +0 -146
  37. package/core/api-types.js +0 -9
  38. package/core/capabilities.d.mts +0 -27
  39. package/core/capabilities.js +0 -14
  40. package/core/capture-buffer.d.mts +0 -37
  41. package/core/capture-buffer.js +0 -9
  42. package/core/force-state.d.mts +0 -68
  43. package/core/force-state.js +0 -21
  44. package/core/mock-cookie.d.mts +0 -30
  45. package/core/mock-cookie.js +0 -15
  46. package/core/types.d.mts +0 -59
  47. package/core/types.js +0 -9
  48. package/hud-provider.d.mts +0 -38
  49. package/hud-provider.js +0 -15
  50. package/hud.d.mts +0 -15
  51. package/hud.js +0 -18
  52. package/index.d.mts +0 -94
  53. package/index.js +0 -170
  54. package/lazy-panel.d.mts +0 -28
  55. package/lazy-panel.js +0 -11
  56. package/panels/cicd-panel.d.mts +0 -9
  57. package/panels/cicd-panel.js +0 -13
  58. package/panels/debug-info-panel.d.mts +0 -21
  59. package/panels/debug-info-panel.js +0 -9
  60. package/panels/dispatch-panel.d.mts +0 -10
  61. package/panels/dispatch-panel.js +0 -14
  62. package/panels/env-info-panel.d.mts +0 -9
  63. package/panels/env-info-panel.js +0 -12
  64. package/panels/feature-flags-panel.d.mts +0 -26
  65. package/panels/feature-flags-panel.js +0 -9
  66. package/panels/force-state-panel.d.mts +0 -11
  67. package/panels/force-state-panel.js +0 -113
  68. package/panels/info-row.d.mts +0 -21
  69. package/panels/info-row.js +0 -14
  70. package/panels/mock-seed-panel.d.mts +0 -15
  71. package/panels/mock-seed-panel.js +0 -14
  72. package/panels/network-console-panel.d.mts +0 -6
  73. package/panels/network-console-panel.js +0 -9
  74. package/panels/role-switcher-panel.d.mts +0 -28
  75. package/panels/role-switcher-panel.js +0 -9
  76. package/panels/sessions-panel.d.mts +0 -6
  77. package/panels/sessions-panel.js +0 -13
  78. package/panels/tokens-panel.d.mts +0 -38
  79. package/panels/tokens-panel.js +0 -9
  80. package/panels/unlock-panel.d.mts +0 -33
  81. package/panels/unlock-panel.js +0 -14
  82. package/panels/variants-panel.d.mts +0 -51
  83. package/panels/variants-panel.js +0 -12
  84. package/panels/vitals-panel.d.mts +0 -11
  85. package/panels/vitals-panel.js +0 -15
  86. package/server/guard.d.mts +0 -42
  87. package/server/guard.js +0 -12
  88. package/server/unlock.d.mts +0 -28
  89. package/server/unlock.js +0 -108
  90. package/state-boundary.d.mts +0 -25
  91. package/state-boundary.js +0 -54
package/chunk-6gw4x08j.js DELETED
@@ -1,264 +0,0 @@
1
- import {
2
- bridgeFetch,
3
- getBridgeInfo
4
- } from "./chunk-50pq4sg6.js";
5
- import {
6
- clearGrabbedPayload,
7
- getGrabberState,
8
- startGrab,
9
- subscribeGrabber,
10
- useDevDrawer
11
- } from "./chunk-82nm9wcg.js";
12
- import {
13
- useHud
14
- } from "./chunk-wspz08q7.js";
15
- import {
16
- LoadingSpinner,
17
- PanelSection
18
- } from "./chunk-kyeb6qeq.js";
19
- import {
20
- Badge,
21
- Button
22
- } from "./chunk-xztw0xyt.js";
23
-
24
- // panels/dispatch-panel.tsx
25
- import { Crosshair, Send, X } from "lucide-react";
26
- import { useEffect, useMemo, useState, useSyncExternalStore } from "react";
27
- import { jsx, jsxs } from "react/jsx-runtime";
28
- "use client";
29
- function DispatchPanel() {
30
- const { config } = useHud();
31
- const { closeDrawer } = useDevDrawer();
32
- const grabber = useSyncExternalStore(subscribeGrabber, getGrabberState, getGrabberState);
33
- const [bridge, setBridge] = useState(undefined);
34
- const [target, setTarget] = useState("docket");
35
- const [note, setNote] = useState("");
36
- const [runs, setRuns] = useState([]);
37
- const apiBase = config.apiBase ?? "/api/hud";
38
- useEffect(() => {
39
- let cancelled = false;
40
- getBridgeInfo(apiBase).then((info) => {
41
- if (cancelled)
42
- return;
43
- setBridge(info);
44
- if (!info)
45
- setTarget("hermes");
46
- });
47
- return () => {
48
- cancelled = true;
49
- };
50
- }, [apiBase]);
51
- const payload = grabber.payload;
52
- const targets = useMemo(() => [
53
- {
54
- id: "docket",
55
- label: "Local Claude session (docket)",
56
- detail: "worktree + claude -p via the bridge — events land on the docket board",
57
- enabled: bridge != null,
58
- disabledReason: "bridge not reachable (run `bun hud:bridge` in the repo)"
59
- },
60
- {
61
- id: "queue",
62
- label: "Queue marker (.claude/queue)",
63
- detail: "human in the loop — the next Claude session picks it up",
64
- enabled: bridge != null,
65
- disabledReason: "bridge not reachable"
66
- },
67
- {
68
- id: "hermes",
69
- label: "Hermes (remote)",
70
- detail: "via the console hub → hermes-dispatch workflow, tier balanced",
71
- enabled: true,
72
- disabledReason: ""
73
- }
74
- ], [bridge]);
75
- async function send() {
76
- if (!payload)
77
- return;
78
- const title = `${payload.anchor.label} — ${note.slice(0, 60) || "hud dispatch"}`;
79
- const localId = `local-${Date.now()}`;
80
- setRuns((prev) => [{ id: localId, title, target, status: "sending" }, ...prev]);
81
- clearGrabbedPayload();
82
- setNote("");
83
- try {
84
- let res;
85
- if (target === "hermes") {
86
- res = await fetch(`${apiBase}/dispatch`, {
87
- method: "POST",
88
- headers: { "Content-Type": "application/json", "x-hud-internal": "1" },
89
- body: JSON.stringify({ target, note, payload })
90
- });
91
- } else {
92
- if (!bridge)
93
- throw new Error("bridge not reachable");
94
- res = await bridgeFetch(bridge, "/dispatch", {
95
- method: "POST",
96
- body: JSON.stringify({ target, note, payload })
97
- });
98
- }
99
- const body = await res.json();
100
- setRuns((prev) => prev.map((run) => run.id === localId ? {
101
- ...run,
102
- status: body.ok ? "dispatched" : "failed",
103
- detail: body.runId ?? body.markerPath ?? body.error
104
- } : run));
105
- } catch (error) {
106
- setRuns((prev) => prev.map((run) => run.id === localId ? {
107
- ...run,
108
- status: "failed",
109
- detail: error instanceof Error ? error.message : "dispatch failed"
110
- } : run));
111
- }
112
- }
113
- return /* @__PURE__ */ jsxs("div", {
114
- className: "space-y-4",
115
- children: [
116
- !payload && /* @__PURE__ */ jsx(PanelSection, {
117
- icon: Crosshair,
118
- title: "Grab an element",
119
- children: /* @__PURE__ */ jsxs("div", {
120
- className: "px-2",
121
- children: [
122
- /* @__PURE__ */ jsxs(Button, {
123
- size: "sm",
124
- className: "h-7 text-xs",
125
- onClick: () => {
126
- closeDrawer();
127
- startGrab();
128
- },
129
- children: [
130
- /* @__PURE__ */ jsx(Crosshair, {
131
- className: "mr-1.5 h-3.5 w-3.5"
132
- }),
133
- "Grab element"
134
- ]
135
- }),
136
- /* @__PURE__ */ jsx("p", {
137
- className: "mt-2 text-[10px] text-muted-foreground/60",
138
- children: "Click any element on the page — selector, source hints, recent errors, and vitals become the dispatch payload."
139
- })
140
- ]
141
- })
142
- }),
143
- payload && /* @__PURE__ */ jsx(PanelSection, {
144
- icon: Send,
145
- title: "Dispatch",
146
- children: /* @__PURE__ */ jsxs("div", {
147
- className: "space-y-2 px-2",
148
- children: [
149
- /* @__PURE__ */ jsx(PayloadPreview, {
150
- payload,
151
- onDiscard: clearGrabbedPayload
152
- }),
153
- /* @__PURE__ */ jsx("textarea", {
154
- value: note,
155
- onChange: (e) => setNote(e.target.value),
156
- placeholder: "Instruction, e.g.: button feels heavy — try a ghost variant",
157
- className: "min-h-[52px] w-full rounded-md border bg-muted/20 p-2 font-mono text-[11px] outline-none focus:ring-1 focus:ring-ring"
158
- }),
159
- /* @__PURE__ */ jsx("div", {
160
- className: "space-y-1",
161
- children: targets.map((t) => /* @__PURE__ */ jsxs("label", {
162
- className: `flex cursor-pointer items-start gap-2 rounded-md border p-2 ${target === t.id ? "border-primary/60 bg-muted/30" : "border-border/50"} ${t.enabled ? "" : "cursor-not-allowed opacity-50"}`,
163
- children: [
164
- /* @__PURE__ */ jsx("input", {
165
- type: "radio",
166
- name: "hud-dispatch-target",
167
- checked: target === t.id,
168
- disabled: !t.enabled,
169
- onChange: () => setTarget(t.id),
170
- className: "mt-0.5"
171
- }),
172
- /* @__PURE__ */ jsxs("span", {
173
- children: [
174
- /* @__PURE__ */ jsx("span", {
175
- className: "block text-xs font-medium",
176
- children: t.label
177
- }),
178
- /* @__PURE__ */ jsx("span", {
179
- className: "block text-[10px] text-muted-foreground",
180
- children: t.enabled ? t.detail : t.disabledReason
181
- })
182
- ]
183
- })
184
- ]
185
- }, t.id))
186
- }),
187
- /* @__PURE__ */ jsxs(Button, {
188
- size: "sm",
189
- className: "h-7 text-xs",
190
- onClick: send,
191
- children: [
192
- /* @__PURE__ */ jsx(Send, {
193
- className: "mr-1.5 h-3 w-3"
194
- }),
195
- "Dispatch"
196
- ]
197
- })
198
- ]
199
- })
200
- }),
201
- bridge === undefined && /* @__PURE__ */ jsx(LoadingSpinner, {}),
202
- runs.length > 0 && /* @__PURE__ */ jsx(PanelSection, {
203
- title: "Dispatched from this session",
204
- children: runs.map((run) => /* @__PURE__ */ jsxs("div", {
205
- className: "flex items-center gap-2 px-2 py-1 font-mono text-[10.5px]",
206
- children: [
207
- /* @__PURE__ */ jsx(Badge, {
208
- variant: "outline",
209
- className: `h-4 px-1.5 text-[9px] ${run.status === "dispatched" ? "text-emerald-500" : run.status === "failed" ? "text-red-500" : "text-amber-500"}`,
210
- children: run.status
211
- }),
212
- /* @__PURE__ */ jsx("span", {
213
- className: "min-w-0 flex-1 truncate",
214
- children: run.title
215
- }),
216
- /* @__PURE__ */ jsx("span", {
217
- className: "text-muted-foreground/60",
218
- children: run.target
219
- }),
220
- run.detail && /* @__PURE__ */ jsx("span", {
221
- className: "max-w-[180px] truncate text-muted-foreground/60",
222
- title: run.detail,
223
- children: run.detail
224
- })
225
- ]
226
- }, run.id))
227
- })
228
- ]
229
- });
230
- }
231
- function PayloadPreview({
232
- payload,
233
- onDiscard
234
- }) {
235
- return /* @__PURE__ */ jsxs("div", {
236
- className: "rounded-md border bg-muted/20 p-2",
237
- children: [
238
- /* @__PURE__ */ jsxs("div", {
239
- className: "flex items-center gap-2",
240
- children: [
241
- /* @__PURE__ */ jsx("span", {
242
- className: "min-w-0 flex-1 truncate font-mono text-[11px]",
243
- children: payload.anchor.label
244
- }),
245
- /* @__PURE__ */ jsx(Button, {
246
- variant: "ghost",
247
- size: "icon",
248
- className: "h-5 w-5",
249
- onClick: onDiscard,
250
- children: /* @__PURE__ */ jsx(X, {
251
- className: "h-3 w-3"
252
- })
253
- })
254
- ]
255
- }),
256
- /* @__PURE__ */ jsx("pre", {
257
- className: "mt-1 max-h-40 overflow-auto text-[9.5px] leading-relaxed text-muted-foreground",
258
- children: JSON.stringify(payload, null, 2)
259
- })
260
- ]
261
- });
262
- }
263
-
264
- export { DispatchPanel };
package/chunk-6jt8yg4m.js DELETED
@@ -1,117 +0,0 @@
1
- import {
2
- LoadingSpinner,
3
- PanelSection
4
- } from "./chunk-kyeb6qeq.js";
5
- import {
6
- Badge,
7
- Button
8
- } from "./chunk-xztw0xyt.js";
9
-
10
- // panels/role-switcher-panel.tsx
11
- import { Check, Shield, User } from "lucide-react";
12
- import { useState } from "react";
13
- import { jsx, jsxs } from "react/jsx-runtime";
14
- "use client";
15
- function RoleSwitcherPanel({ adapter }) {
16
- const { roles, currentRoleId, currentUserLabel, isLoading = false, onSwitch } = adapter;
17
- const [switching, setSwitching] = useState(false);
18
- const [error, setError] = useState(null);
19
- async function handleSwitch(roleId) {
20
- if (roleId === currentRoleId)
21
- return;
22
- setSwitching(true);
23
- setError(null);
24
- try {
25
- await onSwitch(roleId);
26
- } catch (err) {
27
- setError(err instanceof Error ? err.message : "Role switch failed");
28
- } finally {
29
- setSwitching(false);
30
- }
31
- }
32
- if (isLoading)
33
- return /* @__PURE__ */ jsx(LoadingSpinner, {});
34
- const current = roles.find((role) => role.id === currentRoleId);
35
- return /* @__PURE__ */ jsxs("div", {
36
- className: "space-y-4",
37
- children: [
38
- /* @__PURE__ */ jsx(PanelSection, {
39
- icon: Shield,
40
- title: "Current Role",
41
- children: /* @__PURE__ */ jsxs("div", {
42
- className: "border bg-muted/30 px-3 py-2",
43
- children: [
44
- /* @__PURE__ */ jsxs("div", {
45
- className: "flex items-center gap-2",
46
- children: [
47
- /* @__PURE__ */ jsx(User, {
48
- className: "h-4 w-4 text-muted-foreground"
49
- }),
50
- /* @__PURE__ */ jsx("span", {
51
- className: "text-sm font-medium",
52
- children: currentUserLabel ?? "Unknown"
53
- })
54
- ]
55
- }),
56
- /* @__PURE__ */ jsx(Badge, {
57
- variant: "outline",
58
- className: `mt-1 ${current?.badgeClassName ?? ""}`,
59
- children: current?.label ?? currentRoleId ?? "—"
60
- })
61
- ]
62
- })
63
- }),
64
- /* @__PURE__ */ jsx(PanelSection, {
65
- title: "Switch Role",
66
- children: roles.map((role) => {
67
- const isCurrent = role.id === currentRoleId;
68
- return /* @__PURE__ */ jsxs(Button, {
69
- variant: "ghost",
70
- size: "sm",
71
- disabled: isCurrent || switching,
72
- className: "w-full justify-between text-xs",
73
- onClick: () => handleSwitch(role.id),
74
- children: [
75
- /* @__PURE__ */ jsxs("div", {
76
- className: "flex items-center gap-2",
77
- children: [
78
- /* @__PURE__ */ jsx("span", {
79
- className: `h-2 w-2 rounded-full ${isCurrent ? "bg-primary" : "bg-muted-foreground/30"}`
80
- }),
81
- /* @__PURE__ */ jsx("span", {
82
- children: role.label
83
- })
84
- ]
85
- }),
86
- /* @__PURE__ */ jsxs("div", {
87
- className: "flex items-center gap-1.5",
88
- children: [
89
- role.level !== undefined && /* @__PURE__ */ jsxs("span", {
90
- className: "text-[10px] text-muted-foreground",
91
- children: [
92
- "Lvl ",
93
- role.level
94
- ]
95
- }),
96
- isCurrent && /* @__PURE__ */ jsx(Check, {
97
- className: "h-3 w-3 text-primary"
98
- })
99
- ]
100
- })
101
- ]
102
- }, role.id);
103
- })
104
- }),
105
- error && /* @__PURE__ */ jsx("p", {
106
- className: "px-2 text-[10px] text-destructive",
107
- children: error
108
- }),
109
- /* @__PURE__ */ jsx("p", {
110
- className: "text-[10px] text-muted-foreground/60",
111
- children: "Role changes take effect immediately. Use this for testing role-based access."
112
- })
113
- ]
114
- });
115
- }
116
-
117
- export { RoleSwitcherPanel };
package/chunk-71se605m.js DELETED
@@ -1,85 +0,0 @@
1
- import {
2
- LoadingSpinner
3
- } from "./chunk-kyeb6qeq.js";
4
- import {
5
- Badge,
6
- Switch
7
- } from "./chunk-xztw0xyt.js";
8
-
9
- // panels/feature-flags-panel.tsx
10
- import { Flag } from "lucide-react";
11
- import { jsx, jsxs } from "react/jsx-runtime";
12
- "use client";
13
- function FeatureFlagsPanel({ adapter }) {
14
- const { flags, isLoading = false, onToggle } = adapter;
15
- if (isLoading)
16
- return /* @__PURE__ */ jsx(LoadingSpinner, {});
17
- const categories = [...new Set(flags.map((flag) => flag.category ?? "general"))];
18
- return /* @__PURE__ */ jsxs("div", {
19
- className: "space-y-4",
20
- children: [
21
- categories.map((category) => /* @__PURE__ */ jsxs("div", {
22
- children: [
23
- /* @__PURE__ */ jsxs("h4", {
24
- className: "mb-2 flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground",
25
- children: [
26
- /* @__PURE__ */ jsx(Flag, {
27
- className: "h-3 w-3"
28
- }),
29
- category
30
- ]
31
- }),
32
- /* @__PURE__ */ jsx("div", {
33
- className: "space-y-1",
34
- children: flags.filter((flag) => (flag.category ?? "general") === category).map((flag) => /* @__PURE__ */ jsx(FlagRow, {
35
- flag,
36
- onToggle: () => void onToggle(flag.id)
37
- }, flag.id))
38
- })
39
- ]
40
- }, category)),
41
- flags.length === 0 && /* @__PURE__ */ jsx("p", {
42
- className: "px-2 text-[10px] text-muted-foreground/60",
43
- children: "No flags registered."
44
- })
45
- ]
46
- });
47
- }
48
- function FlagRow({ flag, onToggle }) {
49
- const isOverridden = flag.enabled !== flag.defaultValue;
50
- return /* @__PURE__ */ jsxs("div", {
51
- className: "flex items-center justify-between px-2 py-1.5 hover:bg-muted/50",
52
- children: [
53
- /* @__PURE__ */ jsxs("div", {
54
- className: "min-w-0 flex-1",
55
- children: [
56
- /* @__PURE__ */ jsxs("div", {
57
- className: "flex items-center gap-1.5",
58
- children: [
59
- /* @__PURE__ */ jsx("span", {
60
- className: "text-xs font-medium",
61
- children: flag.label
62
- }),
63
- isOverridden && /* @__PURE__ */ jsx(Badge, {
64
- variant: "outline",
65
- className: "h-4 border-amber-500/50 px-1 text-[9px] text-amber-500",
66
- children: "overridden"
67
- })
68
- ]
69
- }),
70
- flag.description && /* @__PURE__ */ jsx("p", {
71
- className: "truncate text-[10px] text-muted-foreground",
72
- children: flag.description
73
- })
74
- ]
75
- }),
76
- /* @__PURE__ */ jsx(Switch, {
77
- checked: flag.enabled,
78
- onCheckedChange: onToggle,
79
- className: "ml-2 shrink-0"
80
- })
81
- ]
82
- });
83
- }
84
-
85
- export { FeatureFlagsPanel };