@agentdeck/bridge 0.2.3 → 1.0.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 (185) hide show
  1. package/assets/fm-helper/agentdeck-fm-helper +0 -0
  2. package/dist/apme/collector.d.ts +4 -0
  3. package/dist/apme/collector.d.ts.map +1 -1
  4. package/dist/apme/collector.js +1 -0
  5. package/dist/apme/collector.js.map +1 -1
  6. package/dist/apme/dashboard-html.d.ts.map +1 -1
  7. package/dist/apme/dashboard-html.js +30 -0
  8. package/dist/apme/dashboard-html.js.map +1 -1
  9. package/dist/apme/http.d.ts.map +1 -1
  10. package/dist/apme/http.js +9 -0
  11. package/dist/apme/http.js.map +1 -1
  12. package/dist/apme/index.d.ts.map +1 -1
  13. package/dist/apme/index.js +14 -3
  14. package/dist/apme/index.js.map +1 -1
  15. package/dist/apme/judge-detect.d.ts +26 -0
  16. package/dist/apme/judge-detect.d.ts.map +1 -0
  17. package/dist/apme/judge-detect.js +69 -0
  18. package/dist/apme/judge-detect.js.map +1 -0
  19. package/dist/apme/runner.d.ts +7 -0
  20. package/dist/apme/runner.d.ts.map +1 -1
  21. package/dist/apme/runner.js +188 -33
  22. package/dist/apme/runner.js.map +1 -1
  23. package/dist/apme/settings.d.ts +10 -8
  24. package/dist/apme/settings.d.ts.map +1 -1
  25. package/dist/apme/settings.js +11 -16
  26. package/dist/apme/settings.js.map +1 -1
  27. package/dist/awaiting-overlay.d.ts +17 -4
  28. package/dist/awaiting-overlay.d.ts.map +1 -1
  29. package/dist/awaiting-overlay.js +39 -8
  30. package/dist/awaiting-overlay.js.map +1 -1
  31. package/dist/bridge-core.d.ts +10 -0
  32. package/dist/bridge-core.d.ts.map +1 -1
  33. package/dist/bridge-core.js +50 -0
  34. package/dist/bridge-core.js.map +1 -1
  35. package/dist/claude-permission-rules.d.ts +55 -0
  36. package/dist/claude-permission-rules.d.ts.map +1 -0
  37. package/dist/claude-permission-rules.js +197 -0
  38. package/dist/claude-permission-rules.js.map +1 -0
  39. package/dist/cli.d.ts.map +1 -1
  40. package/dist/cli.js +10 -1
  41. package/dist/cli.js.map +1 -1
  42. package/dist/d200h/hid-protocol.d.ts +62 -0
  43. package/dist/d200h/hid-protocol.d.ts.map +1 -0
  44. package/dist/d200h/hid-protocol.js +124 -0
  45. package/dist/d200h/hid-protocol.js.map +1 -0
  46. package/dist/d200h/image-renderer.d.ts +24 -0
  47. package/dist/d200h/image-renderer.d.ts.map +1 -0
  48. package/dist/d200h/image-renderer.js +321 -0
  49. package/dist/d200h/image-renderer.js.map +1 -0
  50. package/dist/daemon-server.d.ts.map +1 -1
  51. package/dist/daemon-server.js +374 -26
  52. package/dist/daemon-server.js.map +1 -1
  53. package/dist/daemon.js +1 -1
  54. package/dist/esp32-serial.d.ts +30 -0
  55. package/dist/esp32-serial.d.ts.map +1 -1
  56. package/dist/esp32-serial.js +148 -11
  57. package/dist/esp32-serial.js.map +1 -1
  58. package/dist/fallback-task-timeline.d.ts.map +1 -1
  59. package/dist/fallback-task-timeline.js +9 -2
  60. package/dist/fallback-task-timeline.js.map +1 -1
  61. package/dist/hook-server.d.ts.map +1 -1
  62. package/dist/hook-server.js +6 -5
  63. package/dist/hook-server.js.map +1 -1
  64. package/dist/idotmatrix/idotmatrix-daemon-sync.js +2 -2
  65. package/dist/idotmatrix/idotmatrix-daemon-sync.js.map +1 -1
  66. package/dist/index.d.ts.map +1 -1
  67. package/dist/index.js +2 -0
  68. package/dist/index.js.map +1 -1
  69. package/dist/logger.d.ts +3 -1
  70. package/dist/logger.d.ts.map +1 -1
  71. package/dist/logger.js +6 -2
  72. package/dist/logger.js.map +1 -1
  73. package/dist/model-catalog.d.ts +1 -1
  74. package/dist/model-catalog.d.ts.map +1 -1
  75. package/dist/model-catalog.js +2 -4
  76. package/dist/model-catalog.js.map +1 -1
  77. package/dist/modules/d200h-module.d.ts +65 -0
  78. package/dist/modules/d200h-module.d.ts.map +1 -0
  79. package/dist/modules/d200h-module.js +495 -0
  80. package/dist/modules/d200h-module.js.map +1 -0
  81. package/dist/modules/d200h-renderer.d.ts +7 -0
  82. package/dist/modules/d200h-renderer.d.ts.map +1 -0
  83. package/dist/modules/d200h-renderer.js +321 -0
  84. package/dist/modules/d200h-renderer.js.map +1 -0
  85. package/dist/modules/trmnl-module.d.ts +38 -0
  86. package/dist/modules/trmnl-module.d.ts.map +1 -0
  87. package/dist/modules/trmnl-module.js +111 -0
  88. package/dist/modules/trmnl-module.js.map +1 -0
  89. package/dist/observed-steering.d.ts +93 -0
  90. package/dist/observed-steering.d.ts.map +1 -0
  91. package/dist/observed-steering.js +247 -0
  92. package/dist/observed-steering.js.map +1 -0
  93. package/dist/opencode-steering.d.ts +36 -0
  94. package/dist/opencode-steering.d.ts.map +1 -0
  95. package/dist/opencode-steering.js +84 -0
  96. package/dist/opencode-steering.js.map +1 -0
  97. package/dist/output-parser.d.ts.map +1 -1
  98. package/dist/output-parser.js +48 -10
  99. package/dist/output-parser.js.map +1 -1
  100. package/dist/passive-observer.d.ts +6 -0
  101. package/dist/passive-observer.d.ts.map +1 -1
  102. package/dist/passive-observer.js +31 -1
  103. package/dist/passive-observer.js.map +1 -1
  104. package/dist/permission-resolver.d.ts +13 -5
  105. package/dist/permission-resolver.d.ts.map +1 -1
  106. package/dist/permission-resolver.js +18 -9
  107. package/dist/permission-resolver.js.map +1 -1
  108. package/dist/pixoo/micro-glyphs.d.ts +10 -41
  109. package/dist/pixoo/micro-glyphs.d.ts.map +1 -1
  110. package/dist/pixoo/micro-glyphs.js +130 -263
  111. package/dist/pixoo/micro-glyphs.js.map +1 -1
  112. package/dist/pixoo/official-dot-glyphs.generated.d.ts +8 -0
  113. package/dist/pixoo/official-dot-glyphs.generated.d.ts.map +1 -0
  114. package/dist/pixoo/official-dot-glyphs.generated.js +247 -0
  115. package/dist/pixoo/official-dot-glyphs.generated.js.map +1 -0
  116. package/dist/pixoo/pixoo-bridge.d.ts +14 -6
  117. package/dist/pixoo/pixoo-bridge.d.ts.map +1 -1
  118. package/dist/pixoo/pixoo-bridge.js +63 -39
  119. package/dist/pixoo/pixoo-bridge.js.map +1 -1
  120. package/dist/pixoo/pixoo-renderer.d.ts +21 -2
  121. package/dist/pixoo/pixoo-renderer.d.ts.map +1 -1
  122. package/dist/pixoo/pixoo-renderer.js +401 -132
  123. package/dist/pixoo/pixoo-renderer.js.map +1 -1
  124. package/dist/pixoo/pixoo-sprites.d.ts +24 -0
  125. package/dist/pixoo/pixoo-sprites.d.ts.map +1 -1
  126. package/dist/pixoo/pixoo-sprites.js +108 -0
  127. package/dist/pixoo/pixoo-sprites.js.map +1 -1
  128. package/dist/review-runner.d.ts +113 -0
  129. package/dist/review-runner.d.ts.map +1 -0
  130. package/dist/review-runner.js +428 -0
  131. package/dist/review-runner.js.map +1 -0
  132. package/dist/session-aggregator.d.ts +8 -0
  133. package/dist/session-aggregator.d.ts.map +1 -1
  134. package/dist/session-aggregator.js.map +1 -1
  135. package/dist/session-focus-relay.d.ts.map +1 -1
  136. package/dist/session-focus-relay.js +7 -1
  137. package/dist/session-focus-relay.js.map +1 -1
  138. package/dist/session-registry.d.ts +3 -0
  139. package/dist/session-registry.d.ts.map +1 -1
  140. package/dist/session-registry.js +3 -0
  141. package/dist/session-registry.js.map +1 -1
  142. package/dist/timeline-store.d.ts +49 -0
  143. package/dist/timeline-store.d.ts.map +1 -1
  144. package/dist/timeline-store.js +175 -7
  145. package/dist/timeline-store.js.map +1 -1
  146. package/dist/trmnl/byos-server.d.ts +39 -0
  147. package/dist/trmnl/byos-server.d.ts.map +1 -0
  148. package/dist/trmnl/byos-server.js +301 -0
  149. package/dist/trmnl/byos-server.js.map +1 -0
  150. package/dist/trmnl/frame-cache.d.ts +37 -0
  151. package/dist/trmnl/frame-cache.d.ts.map +1 -0
  152. package/dist/trmnl/frame-cache.js +157 -0
  153. package/dist/trmnl/frame-cache.js.map +1 -0
  154. package/dist/trmnl/image-renderer.d.ts +27 -0
  155. package/dist/trmnl/image-renderer.d.ts.map +1 -0
  156. package/dist/trmnl/image-renderer.js +235 -0
  157. package/dist/trmnl/image-renderer.js.map +1 -0
  158. package/dist/trmnl/trmnl-settings.d.ts +96 -0
  159. package/dist/trmnl/trmnl-settings.d.ts.map +1 -0
  160. package/dist/trmnl/trmnl-settings.js +177 -0
  161. package/dist/trmnl/trmnl-settings.js.map +1 -0
  162. package/dist/trmnl/trmnl-telemetry.d.ts +47 -0
  163. package/dist/trmnl/trmnl-telemetry.d.ts.map +1 -0
  164. package/dist/trmnl/trmnl-telemetry.js +56 -0
  165. package/dist/trmnl/trmnl-telemetry.js.map +1 -0
  166. package/dist/tui/dashboard.d.ts.map +1 -1
  167. package/dist/tui/dashboard.js +14 -4
  168. package/dist/tui/dashboard.js.map +1 -1
  169. package/dist/tui/renderer.d.ts.map +1 -1
  170. package/dist/tui/renderer.js +63 -13
  171. package/dist/tui/renderer.js.map +1 -1
  172. package/dist/tui/terrarium.d.ts.map +1 -1
  173. package/dist/tui/terrarium.js +7 -2
  174. package/dist/tui/terrarium.js.map +1 -1
  175. package/dist/usage-event.d.ts.map +1 -1
  176. package/dist/usage-event.js +25 -2
  177. package/dist/usage-event.js.map +1 -1
  178. package/dist/version-check.d.ts.map +1 -1
  179. package/dist/version-check.js +1 -17
  180. package/dist/version-check.js.map +1 -1
  181. package/dist/ws-server.d.ts +0 -7
  182. package/dist/ws-server.d.ts.map +1 -1
  183. package/dist/ws-server.js +5 -20
  184. package/dist/ws-server.js.map +1 -1
  185. package/package.json +4 -4
@@ -0,0 +1,321 @@
1
+ /**
2
+ * D200H framebuffer renderer — renders AgentDeck 14-key dashboard
3
+ * Screen: 960×540 logical (landscape), fb0: 540×960 with 90° CW rotation
4
+ * Transform: screen(sx,sy) → fb(sy, 959-sx)
5
+ * Layout: 3 rows × 5 cols, row2 col3+4 merged = 14 keys
6
+ */
7
+ import { execSync } from 'child_process';
8
+ import { writeFileSync } from 'fs';
9
+ import { tmpdir } from 'os';
10
+ import { join } from 'path';
11
+ import { debug } from '../logger.js';
12
+ const TAG = 'd200h-render';
13
+ // Screen dimensions (logical, after rotation)
14
+ const SW = 960;
15
+ const SH = 540;
16
+ // Framebuffer dimensions (physical)
17
+ const FBW = 540;
18
+ const FBH = 960;
19
+ // Double buffer
20
+ const FB_SIZE = FBW * FBH * 2 * 4; // 2 pages, BGRA32
21
+ const PAGE_SIZE = FBW * FBH * 4;
22
+ // Key grid: 3 rows × 5 cols
23
+ const COLS = 5;
24
+ const ROWS = 3;
25
+ const COL_W = Math.floor(SW / COLS); // 192
26
+ const ROW_H = Math.floor(SH / ROWS); // 180
27
+ const GAP = 3;
28
+ const D200H_SERIAL = '0123456789ABCDEF';
29
+ // Colors (BGRA format)
30
+ const COLOR_BG = [20, 20, 25, 255]; // dark background
31
+ const COLOR_IDLE = [60, 50, 40, 255]; // slate
32
+ const COLOR_PROCESSING = [160, 80, 20, 255]; // blue (BGRA: high B)
33
+ const COLOR_AWAITING = [30, 140, 200, 255]; // amber
34
+ const COLOR_ERROR = [40, 40, 180, 255]; // red
35
+ const COLOR_TEXT = [220, 220, 220, 255]; // light gray
36
+ const COLOR_DIM = [120, 120, 120, 255]; // dim text
37
+ const COLOR_ACCENT = [200, 140, 40, 255]; // accent blue
38
+ const COLOR_GREEN = [60, 180, 60, 255]; // green
39
+ const COLOR_BAR_BG = [50, 50, 55, 255]; // gauge background
40
+ const COLOR_BAR_5H = [180, 160, 40, 255]; // 5h gauge color
41
+ const COLOR_BAR_7D = [160, 80, 40, 255]; // 7d gauge color
42
+ // 3×5 bitmap font — full alphanumeric (lowercase rendered, input lowercased)
43
+ const FONT_3X5 = {
44
+ '0': [0b111, 0b101, 0b101, 0b101, 0b111],
45
+ '1': [0b010, 0b110, 0b010, 0b010, 0b111],
46
+ '2': [0b111, 0b001, 0b111, 0b100, 0b111],
47
+ '3': [0b111, 0b001, 0b111, 0b001, 0b111],
48
+ '4': [0b101, 0b101, 0b111, 0b001, 0b001],
49
+ '5': [0b111, 0b100, 0b111, 0b001, 0b111],
50
+ '6': [0b111, 0b100, 0b111, 0b101, 0b111],
51
+ '7': [0b111, 0b001, 0b010, 0b010, 0b010],
52
+ '8': [0b111, 0b101, 0b111, 0b101, 0b111],
53
+ '9': [0b111, 0b101, 0b111, 0b001, 0b111],
54
+ 'a': [0b010, 0b101, 0b111, 0b101, 0b101],
55
+ 'b': [0b110, 0b101, 0b110, 0b101, 0b110],
56
+ 'c': [0b011, 0b100, 0b100, 0b100, 0b011],
57
+ 'd': [0b110, 0b101, 0b101, 0b101, 0b110],
58
+ 'e': [0b111, 0b100, 0b110, 0b100, 0b111],
59
+ 'f': [0b111, 0b100, 0b110, 0b100, 0b100],
60
+ 'g': [0b011, 0b100, 0b101, 0b101, 0b011],
61
+ 'h': [0b101, 0b101, 0b111, 0b101, 0b101],
62
+ 'i': [0b111, 0b010, 0b010, 0b010, 0b111],
63
+ 'j': [0b001, 0b001, 0b001, 0b101, 0b010],
64
+ 'k': [0b101, 0b110, 0b100, 0b110, 0b101],
65
+ 'l': [0b100, 0b100, 0b100, 0b100, 0b111],
66
+ 'm': [0b101, 0b111, 0b111, 0b101, 0b101],
67
+ 'n': [0b101, 0b111, 0b111, 0b111, 0b101],
68
+ 'o': [0b010, 0b101, 0b101, 0b101, 0b010],
69
+ 'p': [0b110, 0b101, 0b110, 0b100, 0b100],
70
+ 'q': [0b010, 0b101, 0b101, 0b110, 0b011],
71
+ 'r': [0b110, 0b101, 0b110, 0b101, 0b101],
72
+ 's': [0b011, 0b100, 0b010, 0b001, 0b110],
73
+ 't': [0b111, 0b010, 0b010, 0b010, 0b010],
74
+ 'u': [0b101, 0b101, 0b101, 0b101, 0b011],
75
+ 'v': [0b101, 0b101, 0b101, 0b101, 0b010],
76
+ 'w': [0b101, 0b101, 0b111, 0b111, 0b101],
77
+ 'x': [0b101, 0b101, 0b010, 0b101, 0b101],
78
+ 'y': [0b101, 0b101, 0b010, 0b010, 0b010],
79
+ 'z': [0b111, 0b001, 0b010, 0b100, 0b111],
80
+ '%': [0b101, 0b001, 0b010, 0b100, 0b101],
81
+ '.': [0b000, 0b000, 0b000, 0b000, 0b010],
82
+ ',': [0b000, 0b000, 0b000, 0b010, 0b100],
83
+ ':': [0b000, 0b010, 0b000, 0b010, 0b000],
84
+ '-': [0b000, 0b000, 0b111, 0b000, 0b000],
85
+ '_': [0b000, 0b000, 0b000, 0b000, 0b111],
86
+ '/': [0b001, 0b001, 0b010, 0b100, 0b100],
87
+ '$': [0b011, 0b110, 0b010, 0b011, 0b110],
88
+ ' ': [0b000, 0b000, 0b000, 0b000, 0b000],
89
+ };
90
+ const KEY_DEFS = [
91
+ // Row 0: Mode, Session, Usage, Quick1, Quick2
92
+ { id: 0, col: 0, row: 0, colSpan: 1, label: 'MODE', type: 'action' },
93
+ { id: 1, col: 1, row: 0, colSpan: 1, label: 'SESSION', type: 'info' },
94
+ { id: 2, col: 2, row: 0, colSpan: 1, label: 'USAGE', type: 'info' },
95
+ { id: 3, col: 3, row: 0, colSpan: 1, label: 'QA 1', type: 'action' },
96
+ { id: 4, col: 4, row: 0, colSpan: 1, label: 'QA 2', type: 'action' },
97
+ // Row 1: Quick3, Quick4, Model, 5h Rate, 7d Rate
98
+ { id: 5, col: 0, row: 1, colSpan: 1, label: 'QA 3', type: 'action' },
99
+ { id: 6, col: 1, row: 1, colSpan: 1, label: 'QA 4', type: 'action' },
100
+ { id: 7, col: 2, row: 1, colSpan: 1, label: 'MODEL', type: 'info' },
101
+ { id: 8, col: 3, row: 1, colSpan: 1, label: '5h', type: 'info' },
102
+ { id: 9, col: 4, row: 1, colSpan: 1, label: '7d', type: 'info' },
103
+ // Row 2: Stop, Tokens, Cost, Info (merged 2-wide)
104
+ { id: 10, col: 0, row: 2, colSpan: 1, label: 'STOP', type: 'action' },
105
+ { id: 11, col: 1, row: 2, colSpan: 1, label: 'TOKENS', type: 'info' },
106
+ { id: 12, col: 2, row: 2, colSpan: 1, label: 'COST', type: 'info' },
107
+ { id: 13, col: 3, row: 2, colSpan: 2, label: 'INFO', type: 'info' },
108
+ ];
109
+ /** Cached framebuffer */
110
+ let fbBuffer = null;
111
+ let lastRenderHash = '';
112
+ const tmpPath = join(tmpdir(), 'd200h_fb.raw');
113
+ function setPixel(fb, sx, sy, color) {
114
+ // Screen(sx,sy) → fb(sy, 959-sx)
115
+ const fx = sy;
116
+ const fy = 959 - sx;
117
+ if (fx < 0 || fx >= FBW || fy < 0 || fy >= FBH)
118
+ return;
119
+ const offset = (fy * FBW + fx) * 4;
120
+ fb[offset] = color[0]; // B
121
+ fb[offset + 1] = color[1]; // G
122
+ fb[offset + 2] = color[2]; // R
123
+ fb[offset + 3] = color[3]; // A
124
+ }
125
+ function fillRect(fb, x1, y1, x2, y2, color) {
126
+ for (let sy = Math.max(0, y1); sy < Math.min(SH, y2); sy++) {
127
+ for (let sx = Math.max(0, x1); sx < Math.min(SW, x2); sx++) {
128
+ setPixel(fb, sx, sy, color);
129
+ }
130
+ }
131
+ }
132
+ function drawText(fb, x, y, text, scale, color) {
133
+ let cx = x;
134
+ for (const ch of text.toLowerCase()) {
135
+ const glyph = FONT_3X5[ch];
136
+ if (!glyph) {
137
+ cx += 4 * scale;
138
+ continue;
139
+ }
140
+ for (let dy = 0; dy < 5; dy++) {
141
+ for (let dx = 0; dx < 3; dx++) {
142
+ if (glyph[dy] & (1 << (2 - dx))) {
143
+ for (let ssy = 0; ssy < scale; ssy++) {
144
+ for (let ssx = 0; ssx < scale; ssx++) {
145
+ setPixel(fb, cx + dx * scale + ssx, y + dy * scale + ssy, color);
146
+ }
147
+ }
148
+ }
149
+ }
150
+ }
151
+ cx += 4 * scale;
152
+ }
153
+ }
154
+ function drawTextCentered(fb, cx, cy, text, scale, color) {
155
+ const textW = text.length * 4 * scale;
156
+ const textH = 5 * scale;
157
+ drawText(fb, cx - Math.floor(textW / 2), cy - Math.floor(textH / 2), text, scale, color);
158
+ }
159
+ function drawGauge(fb, x, y, w, h, percent, barColor) {
160
+ fillRect(fb, x, y, x + w, y + h, COLOR_BAR_BG);
161
+ const filled = Math.floor(w * Math.min(100, Math.max(0, percent)) / 100);
162
+ fillRect(fb, x, y, x + filled, y + h, barColor);
163
+ }
164
+ function parseState(evt) {
165
+ return {
166
+ state: evt?.state ?? 'DISCONNECTED',
167
+ projectName: evt?.projectName ?? '',
168
+ modelName: evt?.modelName ?? '',
169
+ agentType: evt?.agentType ?? 'claude-code',
170
+ mode: evt?.mode ?? 'default',
171
+ fiveHourPercent: typeof evt?.fiveHourPercent === 'number' ? evt.fiveHourPercent : undefined,
172
+ sevenDayPercent: typeof evt?.sevenDayPercent === 'number' ? evt.sevenDayPercent : undefined,
173
+ totalTokens: evt?.totalTokens ?? 0,
174
+ totalCost: evt?.totalCost ?? 0,
175
+ options: (evt?.options ?? []).map((o) => o?.label ?? o ?? ''),
176
+ currentTool: evt?.currentTool ?? '',
177
+ };
178
+ }
179
+ function stateColor(state) {
180
+ switch (state) {
181
+ case 'PROCESSING': return COLOR_PROCESSING;
182
+ case 'AWAITING_PERMISSION':
183
+ case 'AWAITING_INPUT':
184
+ case 'AWAITING_PROMPT': return COLOR_AWAITING;
185
+ case 'ERROR': return COLOR_ERROR;
186
+ default: return COLOR_IDLE;
187
+ }
188
+ }
189
+ /** Render a single key to the framebuffer */
190
+ function renderKey(fb, key, state) {
191
+ const x1 = key.col * COL_W + GAP;
192
+ const y1 = key.row * ROW_H + GAP;
193
+ const x2 = (key.col + key.colSpan) * COL_W - GAP;
194
+ const y2 = (key.row + 1) * ROW_H - GAP;
195
+ const cx = Math.floor((x1 + x2) / 2);
196
+ const cy = Math.floor((y1 + y2) / 2);
197
+ switch (key.id) {
198
+ case 0: // MODE
199
+ fillRect(fb, x1, y1, x2, y2, COLOR_IDLE);
200
+ drawTextCentered(fb, cx, cy - 16, 'mode', 3, COLOR_DIM);
201
+ drawTextCentered(fb, cx, cy + 10, state.mode, 3, COLOR_TEXT);
202
+ break;
203
+ case 1: // SESSION
204
+ fillRect(fb, x1, y1, x2, y2, stateColor(state.state));
205
+ drawTextCentered(fb, cx, cy - 20, state.projectName.slice(0, 10), 3, COLOR_TEXT);
206
+ drawTextCentered(fb, cx, cy + 5, state.state.slice(0, 12).toLowerCase(), 2, COLOR_DIM);
207
+ break;
208
+ case 2: // USAGE
209
+ fillRect(fb, x1, y1, x2, y2, COLOR_IDLE);
210
+ drawTextCentered(fb, cx, cy - 16, 'usage', 3, COLOR_DIM);
211
+ break;
212
+ case 3:
213
+ case 4:
214
+ case 5:
215
+ case 6: { // Quick Actions
216
+ const qaIdx = key.id <= 4 ? key.id - 3 : key.id - 3;
217
+ const label = state.options[qaIdx] ?? '';
218
+ if (label) {
219
+ fillRect(fb, x1, y1, x2, y2, COLOR_ACCENT);
220
+ drawTextCentered(fb, cx, cy, label.slice(0, 10), 3, COLOR_TEXT);
221
+ }
222
+ else {
223
+ fillRect(fb, x1, y1, x2, y2, COLOR_IDLE);
224
+ drawTextCentered(fb, cx, cy, key.label, 2, COLOR_DIM);
225
+ }
226
+ break;
227
+ }
228
+ case 7: // MODEL
229
+ fillRect(fb, x1, y1, x2, y2, COLOR_IDLE);
230
+ drawTextCentered(fb, cx, cy - 12, 'model', 2, COLOR_DIM);
231
+ drawTextCentered(fb, cx, cy + 8, state.modelName.slice(0, 10), 3, COLOR_TEXT);
232
+ break;
233
+ case 8: // 5h Rate
234
+ fillRect(fb, x1, y1, x2, y2, COLOR_IDLE);
235
+ drawTextCentered(fb, cx, y1 + 20, '5h', 2, COLOR_DIM);
236
+ if (state.fiveHourPercent != null) {
237
+ drawGauge(fb, x1 + 10, cy - 4, x2 - x1 - 20, 12, state.fiveHourPercent, COLOR_BAR_5H);
238
+ drawTextCentered(fb, cx, y2 - 25, `${Math.round(state.fiveHourPercent)}%`, 3, COLOR_TEXT);
239
+ }
240
+ break;
241
+ case 9: // 7d Rate
242
+ fillRect(fb, x1, y1, x2, y2, COLOR_IDLE);
243
+ drawTextCentered(fb, cx, y1 + 20, '7d', 2, COLOR_DIM);
244
+ if (state.sevenDayPercent != null) {
245
+ drawGauge(fb, x1 + 10, cy - 4, x2 - x1 - 20, 12, state.sevenDayPercent, COLOR_BAR_7D);
246
+ drawTextCentered(fb, cx, y2 - 25, `${Math.round(state.sevenDayPercent)}%`, 3, COLOR_TEXT);
247
+ }
248
+ break;
249
+ case 10: // STOP
250
+ fillRect(fb, x1, y1, x2, y2, state.state === 'PROCESSING' ? COLOR_ERROR : COLOR_IDLE);
251
+ drawTextCentered(fb, cx, cy, 'stop', 3, state.state === 'PROCESSING' ? COLOR_TEXT : COLOR_DIM);
252
+ break;
253
+ case 11: // TOKENS
254
+ fillRect(fb, x1, y1, x2, y2, COLOR_IDLE);
255
+ drawTextCentered(fb, cx, cy - 12, 'tokens', 2, COLOR_DIM);
256
+ const tk = state.totalTokens > 1000 ? `${(state.totalTokens / 1000).toFixed(0)}k` : `${state.totalTokens}`;
257
+ drawTextCentered(fb, cx, cy + 10, tk, 3, COLOR_TEXT);
258
+ break;
259
+ case 12: // COST
260
+ fillRect(fb, x1, y1, x2, y2, COLOR_IDLE);
261
+ drawTextCentered(fb, cx, cy - 12, 'cost', 2, COLOR_DIM);
262
+ drawTextCentered(fb, cx, cy + 10, `${state.totalCost.toFixed(2)}`, 3, COLOR_GREEN);
263
+ break;
264
+ case 13: // INFO (merged)
265
+ fillRect(fb, x1, y1, x2, y2, COLOR_IDLE);
266
+ if (state.currentTool) {
267
+ drawTextCentered(fb, cx, cy - 12, 'tool', 2, COLOR_DIM);
268
+ drawTextCentered(fb, cx, cy + 10, state.currentTool.slice(0, 18), 2, COLOR_TEXT);
269
+ }
270
+ else {
271
+ drawTextCentered(fb, cx, cy - 12, state.agentType, 2, COLOR_DIM);
272
+ drawTextCentered(fb, cx, cy + 10, 'agentdeck', 3, COLOR_ACCENT);
273
+ }
274
+ break;
275
+ }
276
+ }
277
+ /** Render full dashboard and return raw BGRA framebuffer */
278
+ export function renderDashboard(stateEvt) {
279
+ const fb = Buffer.alloc(FB_SIZE, 0);
280
+ const state = parseState(stateEvt);
281
+ // Fill background
282
+ for (let sy = 0; sy < SH; sy++) {
283
+ for (let sx = 0; sx < SW; sx++) {
284
+ setPixel(fb, sx, sy, COLOR_BG);
285
+ }
286
+ }
287
+ // Render all 14 keys
288
+ for (const key of KEY_DEFS) {
289
+ renderKey(fb, key, state);
290
+ }
291
+ return fb;
292
+ }
293
+ /** Push framebuffer to D200H via ADB */
294
+ export function pushToDevice(fb) {
295
+ try {
296
+ writeFileSync(tmpPath, fb);
297
+ execSync(`adb -s ${D200H_SERIAL} push ${tmpPath} /tmp/agentdeck.raw`, {
298
+ stdio: 'pipe',
299
+ timeout: 5000,
300
+ });
301
+ execSync(`adb -s ${D200H_SERIAL} shell "cat /tmp/agentdeck.raw > /dev/fb0"`, {
302
+ stdio: 'pipe',
303
+ timeout: 3000,
304
+ });
305
+ return true;
306
+ }
307
+ catch (err) {
308
+ debug(TAG, `push failed: ${err}`);
309
+ return false;
310
+ }
311
+ }
312
+ /** Render and push dashboard to D200H */
313
+ export function updateD200hDisplay(stateEvt) {
314
+ const hash = JSON.stringify(stateEvt?.state) + JSON.stringify(stateEvt?.fiveHourPercent);
315
+ if (hash === lastRenderHash)
316
+ return; // skip if unchanged
317
+ lastRenderHash = hash;
318
+ const fb = renderDashboard(stateEvt);
319
+ pushToDevice(fb);
320
+ }
321
+ //# sourceMappingURL=d200h-renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"d200h-renderer.js","sourceRoot":"","sources":["../../src/modules/d200h-renderer.ts"],"names":[],"mappings":"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E,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * TRMNL device module — keeps the BYOS frame cache fresh.
3
+ *
4
+ * TRMNL is a WiFi e-ink display that PULLS rendered images from a server on its
5
+ * own schedule (the BYOS /api/display contract), so unlike Pixoo/D200H this
6
+ * module never pushes to hardware. It only subscribes to AgentDeck state
7
+ * broadcasts and re-renders the cached 800×480 1-bit frame when the visual state
8
+ * changes; the daemon's HTTP routes (bridge/src/trmnl/byos-server.ts) serve that
9
+ * frame when a device polls.
10
+ *
11
+ * Rendering is gated on a device being registered (or `trmnl.enabled`) so a
12
+ * machine with no TRMNL panel does no extra rasterization. The gate is refreshed
13
+ * from settings on a short interval and immediately when a device enrolls.
14
+ */
15
+ import type { DeviceModule, BridgeContext } from './types.js';
16
+ export declare class TrmnlModule implements DeviceModule {
17
+ readonly name = "trmnl";
18
+ private lastState;
19
+ private lastUsage;
20
+ private lastSessions;
21
+ private gateActive;
22
+ private gateTimer;
23
+ shouldActivate(config: 'auto' | boolean): Promise<boolean>;
24
+ start(ctx: BridgeContext): Promise<void>;
25
+ stop(): Promise<void>;
26
+ statusSnapshot(): Record<string, unknown>;
27
+ /** Re-read settings to decide whether rendering is worthwhile. */
28
+ private refreshGate;
29
+ private render;
30
+ /**
31
+ * Combine the latest state_update + usage_update + sessions into one render
32
+ * event. usage_update is spread last so its 5H/7D + reset fields win. No time
33
+ * component is added: the frame hash must change only on real visual change so
34
+ * a real TRMNL can skip the (battery + flaky-WiFi) re-download otherwise.
35
+ */
36
+ private buildRenderState;
37
+ }
38
+ //# sourceMappingURL=trmnl-module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trmnl-module.d.ts","sourceRoot":"","sources":["../../src/modules/trmnl-module.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAgB9D,qBAAa,WAAY,YAAW,YAAY;IAC9C,QAAQ,CAAC,IAAI,WAAW;IAExB,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAA+C;IAE1D,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAQ1D,KAAK,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBxC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAO3B,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAoBzC,kEAAkE;IAClE,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,MAAM;IAWd;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;CAYzB"}
@@ -0,0 +1,111 @@
1
+ import { initTrmnlRenderer, isTrmnlResvgLoaded } from '../trmnl/image-renderer.js';
2
+ import { refreshTrmnlFrame, setTrmnlState, getTrmnlFrameKeys, getTrmnlActivity } from '../trmnl/frame-cache.js';
3
+ import { loadTrmnlConfig, effectiveRefreshRate } from '../trmnl/trmnl-settings.js';
4
+ import { getTelemetryHealth } from '../trmnl/trmnl-telemetry.js';
5
+ import { debug } from '../logger.js';
6
+ const TAG = 'trmnl';
7
+ const GATE_REFRESH_MS = 30_000;
8
+ function isControllableOrObserved(session) {
9
+ // TRMNL is a read-only dashboard — show every live session (controllable or
10
+ // observed), unlike D200H which filters to controllable for its buttons.
11
+ return !!session && session.alive !== false;
12
+ }
13
+ export class TrmnlModule {
14
+ name = 'trmnl';
15
+ lastState = null;
16
+ lastUsage = null;
17
+ lastSessions = [];
18
+ gateActive = false;
19
+ gateTimer = null;
20
+ async shouldActivate(config) {
21
+ if (config === false)
22
+ return false;
23
+ if (config === true)
24
+ return true;
25
+ // auto: active if a device is registered or the user forced it on.
26
+ const cfg = loadTrmnlConfig();
27
+ return cfg.enabled || cfg.devices.length > 0;
28
+ }
29
+ async start(ctx) {
30
+ await initTrmnlRenderer();
31
+ this.refreshGate();
32
+ this.gateTimer = setInterval(() => this.refreshGate(), GATE_REFRESH_MS);
33
+ ctx.wsServer.onBroadcast((evt) => {
34
+ if (evt?.type === 'state_update') {
35
+ this.lastState = evt;
36
+ this.render();
37
+ }
38
+ else if (evt?.type === 'usage_update') {
39
+ // state_update never carries usage; the 5H/7D gauges + token/cost footer
40
+ // only exist on usage_update (same as Pixoo/ESP32). Without this the panel
41
+ // renders a confident 0% forever.
42
+ this.lastUsage = evt;
43
+ this.render();
44
+ }
45
+ else if (evt?.type === 'sessions_list') {
46
+ this.lastSessions = (evt.sessions ?? []).filter(isControllableOrObserved);
47
+ this.render();
48
+ }
49
+ });
50
+ debug(TAG, `started (resvg=${isTrmnlResvgLoaded()}, gate=${this.gateActive})`);
51
+ }
52
+ async stop() {
53
+ if (this.gateTimer) {
54
+ clearInterval(this.gateTimer);
55
+ this.gateTimer = null;
56
+ }
57
+ }
58
+ statusSnapshot() {
59
+ const cfg = loadTrmnlConfig();
60
+ const activeResolutions = getTrmnlFrameKeys();
61
+ const activity = getTrmnlActivity();
62
+ const currentRefreshRate = effectiveRefreshRate(cfg, activity);
63
+ return {
64
+ resvgLoaded: isTrmnlResvgLoaded(),
65
+ gateActive: this.gateActive,
66
+ enabled: cfg.enabled,
67
+ deviceCount: cfg.devices.length,
68
+ refreshRate: cfg.refreshRate,
69
+ refreshActive: cfg.refreshActive,
70
+ currentRefreshRate,
71
+ activeResolutions,
72
+ frameCount: activeResolutions.length,
73
+ // Health uses the current adaptive cadence so "stale" tracks real expectations.
74
+ telemetry: getTelemetryHealth(currentRefreshRate),
75
+ };
76
+ }
77
+ /** Re-read settings to decide whether rendering is worthwhile. */
78
+ refreshGate() {
79
+ const cfg = loadTrmnlConfig();
80
+ this.gateActive = cfg.enabled || cfg.devices.length > 0;
81
+ }
82
+ render() {
83
+ const evt = this.buildRenderState();
84
+ if (!this.gateActive) {
85
+ // No device yet — remember the state so the frame is correct the instant a
86
+ // device enrolls (byos-server forces a render then), but skip rasterizing.
87
+ setTrmnlState(evt);
88
+ return;
89
+ }
90
+ refreshTrmnlFrame(evt);
91
+ }
92
+ /**
93
+ * Combine the latest state_update + usage_update + sessions into one render
94
+ * event. usage_update is spread last so its 5H/7D + reset fields win. No time
95
+ * component is added: the frame hash must change only on real visual change so
96
+ * a real TRMNL can skip the (battery + flaky-WiFi) re-download otherwise.
97
+ */
98
+ buildRenderState() {
99
+ const u = this.lastUsage ?? {};
100
+ // Usage is "known" only when the hub actually has subscription quota (the
101
+ // gauges are meaningful); otherwise the layout renders "—" instead of 0%.
102
+ const usageKnown = u.fiveHourPercent != null || u.sevenDayPercent != null;
103
+ return {
104
+ ...(this.lastState ?? {}),
105
+ ...u,
106
+ usageKnown,
107
+ allSessions: this.lastSessions,
108
+ };
109
+ }
110
+ }
111
+ //# sourceMappingURL=trmnl-module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trmnl-module.js","sourceRoot":"","sources":["../../src/modules/trmnl-module.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Steering state for observed (direct `claude`, no PTY) sessions.
3
+ *
4
+ * The daemon cannot type into an observed session's terminal, but Claude Code
5
+ * hooks form a synchronous RPC channel that supports three steering
6
+ * primitives, all resolved here:
7
+ *
8
+ * 1. Device approval — a held PreToolUse response (permission-resolver.ts)
9
+ * answers a genuine permission prompt with allow/deny. Gate eligibility
10
+ * is decided by `shouldHoldPreToolUse` below (precision-first: every
11
+ * uncertainty resolves to "don't hold" — see claude-permission-rules.ts).
12
+ * 2. Soft STOP — a stop flag consumed by the next PreToolUse, which returns
13
+ * `deny` with an instruction to halt. Not an instant Ctrl+C (pure text
14
+ * generation runs to the next tool call), but a real stop at the next
15
+ * tool boundary.
16
+ * 3. Turn-end directives — prompts queued while the session is processing,
17
+ * delivered by the Stop hook as `{decision:'block', reason}` so Claude
18
+ * continues with the queued instruction instead of ending the turn.
19
+ * Bounded by design: each Stop drains at most one directive, the queue
20
+ * is hard-capped, and an empty queue always lets the turn end (no
21
+ * stop_hook_active loop).
22
+ *
23
+ * Keyed by the Claude session UUID (same key as awaiting-overlay.ts). Lives
24
+ * outside the state machine for the same reason: per-session attribution.
25
+ */
26
+ /** Bash signature = first two command tokens (the granularity of Claude's own
27
+ * "always allow `git push`"-style session approvals); other tools = tool name. */
28
+ export declare function gateSignature(tool: string, toolInput: Record<string, unknown> | undefined): string;
29
+ /** Human-readable question for the gate's awaiting overlay — device-native
30
+ * semantics ("Allow Bash: git push …?"), never a fabricated mirror of the
31
+ * TUI prompt's option labels. Overlay caps length at 120 chars. */
32
+ export declare function buildGateQuestion(tool: string, toolInput?: Record<string, unknown>): string;
33
+ export declare function requestStop(sid: string): void;
34
+ export declare function clearStop(sid: string): boolean;
35
+ export declare function isStopRequested(sid: string): boolean;
36
+ /** One-shot consume by the PreToolUse deny path. */
37
+ export declare function consumeStop(sid: string): boolean;
38
+ export declare const STOP_DENY_REASON: string;
39
+ export declare function queueDirective(sid: string, text: string): boolean;
40
+ /** Pop exactly one directive (Stop hook drains one per turn end). A pending
41
+ * STOP outranks directives: stopping wins, the queue is discarded. */
42
+ export declare function takeDirective(sid: string): string | undefined;
43
+ export declare function queuedDirectiveCount(sid: string): number;
44
+ /** User re-engaged in the terminal — their own prompt supersedes anything the
45
+ * deck queued, and a pending STOP is moot. */
46
+ export declare function clearOnUserPrompt(sid: string): boolean;
47
+ export declare function clearSession(sid: string): void;
48
+ export interface HoldDecision {
49
+ hold: boolean;
50
+ requestId?: string;
51
+ reason: string;
52
+ }
53
+ export interface HoldContext {
54
+ sessionId: string;
55
+ tool: string;
56
+ toolInput: Record<string, unknown> | undefined;
57
+ permissionMode: string | undefined;
58
+ cwd: string | undefined;
59
+ /** Connected dashboard clients that could answer — no client, no hold. */
60
+ clientCount: number;
61
+ enabled: boolean;
62
+ }
63
+ /**
64
+ * Should this PreToolUse be held for device approval? Precision-first: hold
65
+ * ONLY when every check says Claude would genuinely prompt the user. Any
66
+ * uncertainty → pass through untouched (Claude's normal flow, zero latency).
67
+ */
68
+ export declare function shouldHoldPreToolUse(ctx: HoldContext): HoldDecision;
69
+ /** The held gate resolved (device decision, timeout, sweep). `undecided` marks
70
+ * a pass-through release, which arms the auto-approval learner below. */
71
+ export declare function gateReleased(sid: string, requestId: string, opts: {
72
+ undecided: boolean;
73
+ tool: string;
74
+ toolInput?: Record<string, unknown>;
75
+ }): void;
76
+ /** A permission_prompt Notification arrived — every recent undecided release
77
+ * was a GENUINE prompt, so nothing should be learned as auto-approved. */
78
+ export declare function notePermissionPromptShown(sid: string): void;
79
+ /**
80
+ * PostToolUse arrived. If a recent undecided release matches this tool and no
81
+ * permission_prompt Notification came in between, Claude auto-approved it
82
+ * (session-scoped "always allow" we cannot read) — suppress the signature so
83
+ * it is never held again this session.
84
+ */
85
+ export declare function noteToolEnd(sid: string, tool: string | undefined): void;
86
+ /** Enrichment snapshot for sessions_list (devices render STOPPING / queue badges). */
87
+ export declare function steeringSnapshot(sid: string): {
88
+ stopRequested: boolean;
89
+ queuedDirectives: number;
90
+ };
91
+ /** Test helper. */
92
+ export declare function _resetSteering(): void;
93
+ //# sourceMappingURL=observed-steering.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observed-steering.d.ts","sourceRoot":"","sources":["../src/observed-steering.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AA4CH;mFACmF;AACnF,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,MAAM,CAMlG;AAED;;oEAEoE;AACpE,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAK3F;AAID,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAG7C;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAK9C;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAQpD;AAED,oDAAoD;AACpD,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAKhD;AAED,eAAO,MAAM,gBAAgB,QAGuC,CAAC;AAIrE,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAUjE;AAED;uEACuE;AACvE,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAU7D;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAMxD;AAED;+CAC+C;AAC/C,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAOtD;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAE9C;AAID,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IAC/C,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,0EAA0E;IAC1E,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,WAAW,GAAG,YAAY,CAqBnE;AAED;0EAC0E;AAC1E,wBAAgB,YAAY,CAC1B,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAC9E,IAAI,CAYN;AAED;2EAC2E;AAC3E,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAG3D;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAevE;AAED,sFAAsF;AACtF,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,aAAa,EAAE,OAAO,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,CAKlG;AAED,mBAAmB;AACnB,wBAAgB,cAAc,IAAI,IAAI,CAErC"}