@workerdeck/ui 0.15.0 → 0.16.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 (65) hide show
  1. package/README.md +53 -0
  2. package/build/{SessionPanel-J2U8v88q.d.mts → SessionPanel-B9CHoq8x.d.mts} +158 -21
  3. package/build/{SessionPanel-DI1NO4l8.mjs → SessionPanel-DII9MmQ8.mjs} +4254 -1661
  4. package/build/SessionPanel-DII9MmQ8.mjs.map +1 -0
  5. package/build/{format-ljc3lKpA.d.mts → format-DfI_je9S.d.mts} +1 -1
  6. package/build/format.d.mts +39 -4
  7. package/build/format.mjs +2 -118
  8. package/build/index.d.mts +442 -45
  9. package/build/index.mjs +105 -2
  10. package/build/index.mjs.map +1 -1
  11. package/build/status-Ydzi7n6j.mjs +143 -0
  12. package/build/status-Ydzi7n6j.mjs.map +1 -0
  13. package/build/workspace.d.mts +9 -1
  14. package/build/workspace.mjs +108 -5
  15. package/build/workspace.mjs.map +1 -1
  16. package/package.json +14 -7
  17. package/src/components/agent/Composer.tsx +189 -89
  18. package/src/components/agent/Conversation.tsx +12 -12
  19. package/src/components/agent/FileCard.tsx +0 -26
  20. package/src/components/agent/FileTree.tsx +9 -8
  21. package/src/components/agent/Loader.tsx +22 -72
  22. package/src/components/agent/Message.tsx +11 -46
  23. package/src/components/agent/PermissionPrompt.tsx +0 -92
  24. package/src/components/agent/QuestionPrompt.tsx +0 -122
  25. package/src/components/agent/Reasoning.tsx +5 -19
  26. package/src/components/agent/Response.tsx +1 -132
  27. package/src/components/agent/SessionPanel.tsx +224 -28
  28. package/src/components/agent/SessionWorkspace.tsx +29 -0
  29. package/src/components/agent/StatusBar.tsx +20 -4
  30. package/src/components/agent/ToolCallCard.tsx +17 -111
  31. package/src/components/agent/Transcript.tsx +710 -203
  32. package/src/components/agent/UsageDialog.tsx +20 -106
  33. package/src/components/agent/UsageMeters.tsx +133 -0
  34. package/src/components/agent/pulse.tsx +3 -2
  35. package/src/components/agent/transcript-rows.ts +82 -0
  36. package/src/components/agent/transcript-variant.tsx +29 -51
  37. package/src/components/agent/use-height-epoch.ts +60 -0
  38. package/src/components/agent/use-path-links.ts +147 -0
  39. package/src/components/agent/use-transcript-jumps.ts +190 -0
  40. package/src/components/prompt-area/cursor-helpers.ts +65 -0
  41. package/src/components/prompt-area/use-prompt-area.ts +16 -10
  42. package/src/components/terminal/PermissionPrompt.tsx +119 -0
  43. package/src/components/terminal/QuestionPrompt.tsx +322 -0
  44. package/src/components/terminal/StatusLine.tsx +159 -0
  45. package/src/components/terminal/TerminalTranscript.tsx +147 -0
  46. package/src/components/terminal/affordances.tsx +118 -0
  47. package/src/components/terminal/diff.tsx +130 -0
  48. package/src/components/terminal/height.ts +727 -0
  49. package/src/components/terminal/items.tsx +449 -0
  50. package/src/components/terminal/markdown.tsx +191 -0
  51. package/src/components/terminal/press.tsx +120 -0
  52. package/src/components/terminal/prompt.tsx +343 -0
  53. package/src/components/terminal/result-preview.ts +72 -0
  54. package/src/components/terminal/row.tsx +132 -0
  55. package/src/components/terminal/scrubber.tsx +663 -0
  56. package/src/components/terminal/surface.tsx +80 -0
  57. package/src/components/terminal/tool-run.ts +91 -0
  58. package/src/index.ts +34 -0
  59. package/src/lib/status.ts +59 -3
  60. package/src/lib/tool-icon.ts +14 -0
  61. package/src/styles/terminal.css +1011 -0
  62. package/src/styles/theme.css +41 -0
  63. package/build/SessionPanel-DI1NO4l8.mjs.map +0 -1
  64. package/build/format.mjs.map +0 -1
  65. package/src/components/agent/line-prompt.tsx +0 -249
@@ -56,4 +56,4 @@ declare function toolInputPreview(input: unknown, max?: number): string;
56
56
  declare function friendlyModel(id: string | undefined): string | undefined;
57
57
  //#endregion
58
58
  export { formatDuration as a, formatRelativeTime as c, rateLimitWindowSeconds as d, toolInputPreview as f, formatCountdown as i, formatTokens as l, formatBytes as n, formatRateLimitWindow as o, formatCost as r, formatRateLimitWindowLong as s, formatAgoPrecise as t, friendlyModel as u };
59
- //# sourceMappingURL=format-ljc3lKpA.d.mts.map
59
+ //# sourceMappingURL=format-DfI_je9S.d.mts.map
@@ -1,4 +1,4 @@
1
- import { a as formatDuration, c as formatRelativeTime, d as rateLimitWindowSeconds, f as toolInputPreview, i as formatCountdown, l as formatTokens, n as formatBytes, o as formatRateLimitWindow, r as formatCost, s as formatRateLimitWindowLong, t as formatAgoPrecise, u as friendlyModel } from "./format-ljc3lKpA.mjs";
1
+ import { a as formatDuration, c as formatRelativeTime, d as rateLimitWindowSeconds, f as toolInputPreview, i as formatCountdown, l as formatTokens, n as formatBytes, o as formatRateLimitWindow, r as formatCost, s as formatRateLimitWindowLong, t as formatAgoPrecise, u as friendlyModel } from "./format-DfI_je9S.mjs";
2
2
  import { ContextUsage, ModelOption, RateLimitInfo, SessionStatus } from "@workerdeck/protocol";
3
3
 
4
4
  //#region src/lib/status.d.ts
@@ -36,13 +36,48 @@ type StatusReadings = {
36
36
  declare function statusPresentation(vitals: StatusReadings | undefined): StatusPresentation;
37
37
  /** 0–100 → the colour a meter wears. One pair of thresholds for every surface. */
38
38
  declare function meterSeverity(pct: number | undefined): StatusSeverity;
39
+ /**
40
+ * The three *lanes* a plan-usage reading can occupy, and the whole reason this
41
+ * is a rule rather than a per-client `if`.
42
+ *
43
+ * The CLI reports one window per limit (`five_hour`, `seven_day`, and a
44
+ * `seven_day_<model>` bucket per model-scoped limit — `seven_day_opus`,
45
+ * `seven_day_sonnet`, and whatever `model_scoped` names next). A surface with
46
+ * one slot shows the fullest of them, which is why `tightestWindow` exists —
47
+ * but that answers "what is closest to blocking me", not "how much of *this
48
+ * session's* budget have I spent", and those are different questions a reader
49
+ * asks at different times. A weekly window at 71% will win the single slot over
50
+ * a five-hour window at 60% every time, so the reading you actually watch while
51
+ * working is the one you can never see.
52
+ *
53
+ * Hence three lanes, each independently showable:
54
+ *
55
+ * - `'session'` — the five-hour window. The one that resets while you work.
56
+ * - `'weekly'` — the plain seven-day window, the account-wide ceiling.
57
+ * - `'model'` — the fullest of the *model-scoped* weekly buckets. Deliberately
58
+ * not a named model: which models have their own bucket is the plan's
59
+ * business and changes without notice, so a client that hardcoded
60
+ * `seven_day_opus` would show nothing the month it becomes something else.
61
+ * The label comes from the key, so this lane names whatever it found.
62
+ */
63
+ type UsageLane = 'session' | 'weekly' | 'model';
64
+ /** The window a lane points at, or `undefined` when this account has none. */
65
+ declare function usageWindow(rateLimits: Record<string, RateLimitInfo> | undefined, lane: UsageLane): {
66
+ key: string;
67
+ info: RateLimitInfo;
68
+ } | undefined;
39
69
  /** The rate-limit window that gets the one visible slot: whichever is fullest,
40
- * since the binding constraint is the one worth glancing at. */
70
+ * since the binding constraint is the one worth glancing at. Still the right
71
+ * rule for a surface with exactly one slot; {@link usageWindow} is for one with
72
+ * three. */
41
73
  declare function tightestWindow(rateLimits: Record<string, RateLimitInfo> | undefined): {
42
74
  key: string;
43
75
  info: RateLimitInfo;
44
76
  } | undefined;
45
- /** A rate-limit window's key, named for a human. */
77
+ /** A rate-limit window's key, named for a human. A model-scoped bucket is named
78
+ * for its model alone (`seven_day_fable` → "Fable"): the lane it sits in
79
+ * already says weekly, and "Seven day fable" in a status bar is three words to
80
+ * say one. */
46
81
  declare function windowLabel(key: string): string;
47
82
  type ModelReadings = {
48
83
  model?: string;
@@ -62,5 +97,5 @@ declare function modelLabel(vitals: ModelReadings | undefined): string;
62
97
  * from one place so a panel and a status bar never disagree. */
63
98
  declare function contextSeverity(usage: ContextUsage | undefined): StatusSeverity;
64
99
  //#endregion
65
- export { ModelReadings, StatusPresentation, StatusReadings, StatusSeverity, contextSeverity, currentModel, formatAgoPrecise, formatBytes, formatCost, formatCountdown, formatDuration, formatRateLimitWindow, formatRateLimitWindowLong, formatRelativeTime, formatTokens, friendlyModel, meterSeverity, modelLabel, rateLimitWindowSeconds, statusPresentation, tightestWindow, toolInputPreview, windowLabel };
100
+ export { ModelReadings, StatusPresentation, StatusReadings, StatusSeverity, UsageLane, contextSeverity, currentModel, formatAgoPrecise, formatBytes, formatCost, formatCountdown, formatDuration, formatRateLimitWindow, formatRateLimitWindowLong, formatRelativeTime, formatTokens, friendlyModel, meterSeverity, modelLabel, rateLimitWindowSeconds, statusPresentation, tightestWindow, toolInputPreview, usageWindow, windowLabel };
66
101
  //# sourceMappingURL=format.d.mts.map
package/build/format.mjs CHANGED
@@ -1,119 +1,3 @@
1
1
  import { a as formatDuration, c as formatRelativeTime, d as rateLimitWindowSeconds, f as toolInputPreview, i as formatCountdown, l as formatTokens, n as formatBytes, o as formatRateLimitWindow, r as formatCost, s as formatRateLimitWindowLong, t as formatAgoPrecise, u as friendlyModel } from "./format-DqR56Y8l.mjs";
2
- //#region src/lib/status.ts
3
- const STATUS_META = {
4
- starting: {
5
- icon: "loading~spin",
6
- label: "Starting",
7
- severity: "none"
8
- },
9
- running: {
10
- icon: "loading~spin",
11
- label: "Running",
12
- severity: "none"
13
- },
14
- awaiting_approval: {
15
- icon: "warning",
16
- label: "Needs approval",
17
- severity: "warning"
18
- },
19
- idle: {
20
- icon: "check",
21
- label: "Idle",
22
- severity: "none"
23
- },
24
- parked: {
25
- icon: "debug-pause",
26
- label: "Parked",
27
- severity: "none"
28
- },
29
- failed: {
30
- icon: "error",
31
- label: "Failed",
32
- severity: "error"
33
- },
34
- closed: {
35
- icon: "circle-slash",
36
- label: "Closed",
37
- severity: "none"
38
- }
39
- };
40
- /**
41
- * The status slot, connection first. A session status held over a dead socket is
42
- * the last thing we heard, not the current state — so a lost link takes the slot
43
- * rather than letting "Running" imply a turn is still streaming.
44
- */
45
- function statusPresentation(vitals) {
46
- if (!vitals) return {
47
- icon: "hubot",
48
- label: "Connecting…",
49
- severity: "none"
50
- };
51
- if (vitals.connection === "offline") return {
52
- icon: "debug-disconnect",
53
- label: "Offline",
54
- severity: "error"
55
- };
56
- if (vitals.connection === "reconnecting") return {
57
- icon: "sync~spin",
58
- label: "Reconnecting…",
59
- severity: "warning"
60
- };
61
- return STATUS_META[vitals.status] ?? {
62
- icon: "hubot",
63
- label: vitals.status,
64
- severity: "none"
65
- };
66
- }
67
- /** 0–100 → the colour a meter wears. One pair of thresholds for every surface. */
68
- function meterSeverity(pct) {
69
- if (pct === void 0) return "none";
70
- if (pct >= 95) return "error";
71
- if (pct >= 80) return "warning";
72
- return "none";
73
- }
74
- /** The rate-limit window that gets the one visible slot: whichever is fullest,
75
- * since the binding constraint is the one worth glancing at. */
76
- function tightestWindow(rateLimits) {
77
- const entries = Object.entries(rateLimits ?? {});
78
- if (entries.length === 0) return void 0;
79
- let best;
80
- for (const [key, info] of entries) if ((info.status === "rejected" ? Number.POSITIVE_INFINITY : info.utilization ?? -1) > (best === void 0 ? Number.NEGATIVE_INFINITY : best.info.status === "rejected" ? Number.POSITIVE_INFINITY : best.info.utilization ?? -1)) best = {
81
- key,
82
- info
83
- };
84
- return best;
85
- }
86
- /** A rate-limit window's key, named for a human. */
87
- function windowLabel(key) {
88
- if (key === "five_hour") return "Session";
89
- if (key === "seven_day") return "Weekly";
90
- return key.replaceAll("_", " ");
91
- }
92
- /**
93
- * The catalog row a session is actually running, or `undefined` for a model the
94
- * list doesn't name. Matched leniently: a session reports the *resolved* id
95
- * (`claude-sonnet-5`) where the row may be keyed on the alias (`sonnet`), and
96
- * either can carry a `[1m]` context-window suffix.
97
- */
98
- function currentModel(vitals) {
99
- const id = vitals?.model;
100
- if (!id) return void 0;
101
- const bare = (value) => value.replace(/\[.*\]$/, "");
102
- const wanted = bare(id);
103
- return vitals.models.find((m) => bare(m.value) === wanted || m.resolvedModel && bare(m.resolvedModel) === wanted);
104
- }
105
- /** A session's model, named the way the picker names it. Falls back to the raw
106
- * id, and to "Default" while the session is on the CLI's own pick. */
107
- function modelLabel(vitals) {
108
- if (!vitals?.model) return "Default";
109
- return currentModel(vitals)?.displayName ?? vitals.model;
110
- }
111
- /** Context percentage as its meter severity — the reading and the colour come
112
- * from one place so a panel and a status bar never disagree. */
113
- function contextSeverity(usage) {
114
- return meterSeverity(usage?.percentage);
115
- }
116
- //#endregion
117
- export { contextSeverity, currentModel, formatAgoPrecise, formatBytes, formatCost, formatCountdown, formatDuration, formatRateLimitWindow, formatRateLimitWindowLong, formatRelativeTime, formatTokens, friendlyModel, meterSeverity, modelLabel, rateLimitWindowSeconds, statusPresentation, tightestWindow, toolInputPreview, windowLabel };
118
-
119
- //# sourceMappingURL=format.mjs.map
2
+ import { a as statusPresentation, c as windowLabel, i as modelLabel, n as currentModel, o as tightestWindow, r as meterSeverity, s as usageWindow, t as contextSeverity } from "./status-Ydzi7n6j.mjs";
3
+ export { contextSeverity, currentModel, formatAgoPrecise, formatBytes, formatCost, formatCountdown, formatDuration, formatRateLimitWindow, formatRateLimitWindowLong, formatRelativeTime, formatTokens, friendlyModel, meterSeverity, modelLabel, rateLimitWindowSeconds, statusPresentation, tightestWindow, toolInputPreview, usageWindow, windowLabel };