@positronic/cli 0.0.55 → 0.0.57

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 (94) hide show
  1. package/dist/src/cli.js +142 -2
  2. package/dist/src/commands/auth.js +98 -0
  3. package/dist/src/commands/brain.js +3 -2
  4. package/dist/src/commands/helpers.js +48 -10
  5. package/dist/src/commands/project-config-manager.js +119 -0
  6. package/dist/src/commands/users.js +91 -0
  7. package/dist/src/components/agent-chat-view.js +125 -0
  8. package/dist/src/components/auth-list.js +56 -0
  9. package/dist/src/components/auth-login.js +209 -0
  10. package/dist/src/components/auth-logout.js +75 -0
  11. package/dist/src/components/auth-status.js +88 -0
  12. package/dist/src/components/brain-run.js +287 -254
  13. package/dist/src/components/brain-top-table.js +4 -0
  14. package/dist/src/components/event-detail.js +364 -0
  15. package/dist/src/components/events-view.js +379 -0
  16. package/dist/src/components/state-view.js +52 -0
  17. package/dist/src/components/top-navigator.js +80 -6
  18. package/dist/src/components/types.js +1 -0
  19. package/dist/src/components/users-create.js +293 -0
  20. package/dist/src/components/users-delete.js +294 -0
  21. package/dist/src/components/users-keys-add.js +156 -0
  22. package/dist/src/components/users-keys-list.js +119 -0
  23. package/dist/src/components/users-keys-remove.js +299 -0
  24. package/dist/src/components/users-list.js +109 -0
  25. package/dist/src/components/watch-keyboard.js +136 -0
  26. package/dist/src/components/watch-machine.js +573 -0
  27. package/dist/src/components/watch-resolver.js +3 -2
  28. package/dist/src/components/watch.js +390 -36
  29. package/dist/src/hooks/useApi.js +80 -42
  30. package/dist/src/lib/request-signer.js +208 -0
  31. package/dist/src/lib/ssh-key-utils.js +212 -0
  32. package/dist/src/utils/agent-utils.js +107 -0
  33. package/dist/types/cli.d.ts.map +1 -1
  34. package/dist/types/commands/auth.d.ts +36 -0
  35. package/dist/types/commands/auth.d.ts.map +1 -0
  36. package/dist/types/commands/brain.d.ts +2 -1
  37. package/dist/types/commands/brain.d.ts.map +1 -1
  38. package/dist/types/commands/helpers.d.ts.map +1 -1
  39. package/dist/types/commands/project-config-manager.d.ts +43 -0
  40. package/dist/types/commands/project-config-manager.d.ts.map +1 -1
  41. package/dist/types/commands/users.d.ts +33 -0
  42. package/dist/types/commands/users.d.ts.map +1 -0
  43. package/dist/types/components/agent-chat-view.d.ts +12 -0
  44. package/dist/types/components/agent-chat-view.d.ts.map +1 -0
  45. package/dist/types/components/auth-list.d.ts +7 -0
  46. package/dist/types/components/auth-list.d.ts.map +1 -0
  47. package/dist/types/components/auth-login.d.ts +9 -0
  48. package/dist/types/components/auth-login.d.ts.map +1 -0
  49. package/dist/types/components/auth-logout.d.ts +8 -0
  50. package/dist/types/components/auth-logout.d.ts.map +1 -0
  51. package/dist/types/components/auth-status.d.ts +7 -0
  52. package/dist/types/components/auth-status.d.ts.map +1 -0
  53. package/dist/types/components/brain-run.d.ts +11 -1
  54. package/dist/types/components/brain-run.d.ts.map +1 -1
  55. package/dist/types/components/brain-top-table.d.ts.map +1 -1
  56. package/dist/types/components/event-detail.d.ts +10 -0
  57. package/dist/types/components/event-detail.d.ts.map +1 -0
  58. package/dist/types/components/events-view.d.ts +13 -0
  59. package/dist/types/components/events-view.d.ts.map +1 -0
  60. package/dist/types/components/state-view.d.ts +13 -0
  61. package/dist/types/components/state-view.d.ts.map +1 -0
  62. package/dist/types/components/top-navigator.d.ts.map +1 -1
  63. package/dist/types/components/types.d.ts +11 -0
  64. package/dist/types/components/types.d.ts.map +1 -0
  65. package/dist/types/components/users-create.d.ts +6 -0
  66. package/dist/types/components/users-create.d.ts.map +1 -0
  67. package/dist/types/components/users-delete.d.ts +7 -0
  68. package/dist/types/components/users-delete.d.ts.map +1 -0
  69. package/dist/types/components/users-keys-add.d.ts +8 -0
  70. package/dist/types/components/users-keys-add.d.ts.map +1 -0
  71. package/dist/types/components/users-keys-list.d.ts +6 -0
  72. package/dist/types/components/users-keys-list.d.ts.map +1 -0
  73. package/dist/types/components/users-keys-remove.d.ts +8 -0
  74. package/dist/types/components/users-keys-remove.d.ts.map +1 -0
  75. package/dist/types/components/users-list.d.ts +2 -0
  76. package/dist/types/components/users-list.d.ts.map +1 -0
  77. package/dist/types/components/watch-keyboard.d.ts +56 -0
  78. package/dist/types/components/watch-keyboard.d.ts.map +1 -0
  79. package/dist/types/components/watch-machine.d.ts +171 -0
  80. package/dist/types/components/watch-machine.d.ts.map +1 -0
  81. package/dist/types/components/watch-resolver.d.ts +2 -1
  82. package/dist/types/components/watch-resolver.d.ts.map +1 -1
  83. package/dist/types/components/watch.d.ts +2 -1
  84. package/dist/types/components/watch.d.ts.map +1 -1
  85. package/dist/types/hooks/useApi.d.ts.map +1 -1
  86. package/dist/types/hooks/useBrainMachine.d.ts +9 -3
  87. package/dist/types/hooks/useBrainMachine.d.ts.map +1 -1
  88. package/dist/types/lib/request-signer.d.ts +51 -0
  89. package/dist/types/lib/request-signer.d.ts.map +1 -0
  90. package/dist/types/lib/ssh-key-utils.d.ts +45 -0
  91. package/dist/types/lib/ssh-key-utils.d.ts.map +1 -0
  92. package/dist/types/utils/agent-utils.d.ts +20 -0
  93. package/dist/types/utils/agent-utils.d.ts.map +1 -0
  94. package/package.json +7 -4
@@ -0,0 +1,573 @@
1
+ /**
2
+ * State machine for the Watch component.
3
+ *
4
+ * This machine handles UI navigation and async operations for the watch view.
5
+ * The brain execution tracking (useBrainMachine) and EventSource connection
6
+ * remain separate concerns.
7
+ */ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
8
+ try {
9
+ var info = gen[key](arg);
10
+ var value = info.value;
11
+ } catch (error) {
12
+ reject(error);
13
+ return;
14
+ }
15
+ if (info.done) {
16
+ resolve(value);
17
+ } else {
18
+ Promise.resolve(value).then(_next, _throw);
19
+ }
20
+ }
21
+ function _async_to_generator(fn) {
22
+ return function() {
23
+ var self = this, args = arguments;
24
+ return new Promise(function(resolve, reject) {
25
+ var gen = fn.apply(self, args);
26
+ function _next(value) {
27
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
28
+ }
29
+ function _throw(err) {
30
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
31
+ }
32
+ _next(undefined);
33
+ });
34
+ };
35
+ }
36
+ function _define_property(obj, key, value) {
37
+ if (key in obj) {
38
+ Object.defineProperty(obj, key, {
39
+ value: value,
40
+ enumerable: true,
41
+ configurable: true,
42
+ writable: true
43
+ });
44
+ } else {
45
+ obj[key] = value;
46
+ }
47
+ return obj;
48
+ }
49
+ function _object_spread(target) {
50
+ for(var i = 1; i < arguments.length; i++){
51
+ var source = arguments[i] != null ? arguments[i] : {};
52
+ var ownKeys = Object.keys(source);
53
+ if (typeof Object.getOwnPropertySymbols === "function") {
54
+ ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
55
+ return Object.getOwnPropertyDescriptor(source, sym).enumerable;
56
+ }));
57
+ }
58
+ ownKeys.forEach(function(key) {
59
+ _define_property(target, key, source[key]);
60
+ });
61
+ }
62
+ return target;
63
+ }
64
+ function ownKeys(object, enumerableOnly) {
65
+ var keys = Object.keys(object);
66
+ if (Object.getOwnPropertySymbols) {
67
+ var symbols = Object.getOwnPropertySymbols(object);
68
+ if (enumerableOnly) {
69
+ symbols = symbols.filter(function(sym) {
70
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
71
+ });
72
+ }
73
+ keys.push.apply(keys, symbols);
74
+ }
75
+ return keys;
76
+ }
77
+ function _object_spread_props(target, source) {
78
+ source = source != null ? source : {};
79
+ if (Object.getOwnPropertyDescriptors) {
80
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
81
+ } else {
82
+ ownKeys(Object(source)).forEach(function(key) {
83
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
84
+ });
85
+ }
86
+ return target;
87
+ }
88
+ function _ts_generator(thisArg, body) {
89
+ var f, y, t, _ = {
90
+ label: 0,
91
+ sent: function() {
92
+ if (t[0] & 1) throw t[1];
93
+ return t[1];
94
+ },
95
+ trys: [],
96
+ ops: []
97
+ }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
98
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() {
99
+ return this;
100
+ }), g;
101
+ function verb(n) {
102
+ return function(v) {
103
+ return step([
104
+ n,
105
+ v
106
+ ]);
107
+ };
108
+ }
109
+ function step(op) {
110
+ if (f) throw new TypeError("Generator is already executing.");
111
+ while(g && (g = 0, op[0] && (_ = 0)), _)try {
112
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
113
+ if (y = 0, t) op = [
114
+ op[0] & 2,
115
+ t.value
116
+ ];
117
+ switch(op[0]){
118
+ case 0:
119
+ case 1:
120
+ t = op;
121
+ break;
122
+ case 4:
123
+ _.label++;
124
+ return {
125
+ value: op[1],
126
+ done: false
127
+ };
128
+ case 5:
129
+ _.label++;
130
+ y = op[1];
131
+ op = [
132
+ 0
133
+ ];
134
+ continue;
135
+ case 7:
136
+ op = _.ops.pop();
137
+ _.trys.pop();
138
+ continue;
139
+ default:
140
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
141
+ _ = 0;
142
+ continue;
143
+ }
144
+ if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
145
+ _.label = op[1];
146
+ break;
147
+ }
148
+ if (op[0] === 6 && _.label < t[1]) {
149
+ _.label = t[1];
150
+ t = op;
151
+ break;
152
+ }
153
+ if (t && _.label < t[2]) {
154
+ _.label = t[2];
155
+ _.ops.push(op);
156
+ break;
157
+ }
158
+ if (t[2]) _.ops.pop();
159
+ _.trys.pop();
160
+ continue;
161
+ }
162
+ op = body.call(thisArg, _);
163
+ } catch (e) {
164
+ op = [
165
+ 6,
166
+ e
167
+ ];
168
+ y = 0;
169
+ } finally{
170
+ f = t = 0;
171
+ }
172
+ if (op[0] & 5) throw op[1];
173
+ return {
174
+ value: op[0] ? op[1] : void 0,
175
+ done: true
176
+ };
177
+ }
178
+ }
179
+ import { useMemo } from 'react';
180
+ import * as robot3 from 'robot3';
181
+ import { useMachine } from 'react-robot';
182
+ import { apiClient } from '../commands/helpers.js';
183
+ var createMachine = robot3.createMachine, state = robot3.state, transition = robot3.transition, reduce = robot3.reduce, invoke = robot3.invoke, immediate = robot3.immediate, guard = robot3.guard;
184
+ // ============================================================================
185
+ // Reducers
186
+ // ============================================================================
187
+ var setStateForStateView = reduce(function(ctx, param) {
188
+ var stateSnapshot = param.stateSnapshot, stateTitle = param.stateTitle, fromView = param.fromView;
189
+ return _object_spread_props(_object_spread({}, ctx), {
190
+ stateSnapshot: stateSnapshot,
191
+ stateTitle: stateTitle,
192
+ stateScrollOffset: 0,
193
+ previousView: fromView
194
+ });
195
+ });
196
+ var clearStateSnapshot = reduce(function(ctx) {
197
+ return _object_spread_props(_object_spread({}, ctx), {
198
+ stateSnapshot: null
199
+ });
200
+ });
201
+ var setAgentForChat = reduce(function(ctx, param) {
202
+ var selectedAgentId = param.selectedAgentId, fromView = param.fromView;
203
+ return _object_spread_props(_object_spread({}, ctx), {
204
+ selectedAgentId: selectedAgentId !== null && selectedAgentId !== void 0 ? selectedAgentId : null,
205
+ agentChatScrollOffset: 0,
206
+ previousView: fromView
207
+ });
208
+ });
209
+ var clearSelectedAgent = reduce(function(ctx) {
210
+ return _object_spread_props(_object_spread({}, ctx), {
211
+ selectedAgentId: null
212
+ });
213
+ });
214
+ var setPreviousViewForMessage = reduce(function(ctx, param) {
215
+ var fromView = param.fromView;
216
+ return _object_spread_props(_object_spread({}, ctx), {
217
+ previousView: fromView
218
+ });
219
+ });
220
+ var setEventsSelectedIndex = reduce(function(ctx, param) {
221
+ var index = param.index;
222
+ return _object_spread_props(_object_spread({}, ctx), {
223
+ eventsSelectedIndex: index
224
+ });
225
+ });
226
+ var setStateScrollOffset = reduce(function(ctx, param) {
227
+ var offset = param.offset;
228
+ return _object_spread_props(_object_spread({}, ctx), {
229
+ stateScrollOffset: offset
230
+ });
231
+ });
232
+ var setAgentChatScrollOffset = reduce(function(ctx, param) {
233
+ var offset = param.offset;
234
+ return _object_spread_props(_object_spread({}, ctx), {
235
+ agentChatScrollOffset: offset
236
+ });
237
+ });
238
+ var selectAgentFromPicker = reduce(function(ctx, param) {
239
+ var agentId = param.agentId;
240
+ return _object_spread_props(_object_spread({}, ctx), {
241
+ selectedAgentId: agentId,
242
+ agentChatScrollOffset: 0
243
+ });
244
+ });
245
+ var markKilled = reduce(function(ctx) {
246
+ return _object_spread_props(_object_spread({}, ctx), {
247
+ isKilled: true
248
+ });
249
+ });
250
+ var setKillError = reduce(function(ctx, param) {
251
+ var error = param.error;
252
+ return _object_spread_props(_object_spread({}, ctx), {
253
+ killError: error
254
+ });
255
+ });
256
+ var setPauseMessage = reduce(function(ctx) {
257
+ return _object_spread_props(_object_spread({}, ctx), {
258
+ pauseResumeMessage: 'Pause signal sent'
259
+ });
260
+ });
261
+ var setResumeMessage = reduce(function(ctx) {
262
+ return _object_spread_props(_object_spread({}, ctx), {
263
+ pauseResumeMessage: 'Resume signal sent'
264
+ });
265
+ });
266
+ var clearPauseResumeMessage = reduce(function(ctx) {
267
+ return _object_spread_props(_object_spread({}, ctx), {
268
+ pauseResumeMessage: null
269
+ });
270
+ });
271
+ var setMessageText = reduce(function(ctx, param) {
272
+ var text = param.text;
273
+ return _object_spread_props(_object_spread({}, ctx), {
274
+ messageText: text
275
+ });
276
+ });
277
+ var clearMessageText = reduce(function(ctx) {
278
+ return _object_spread_props(_object_spread({}, ctx), {
279
+ messageText: ''
280
+ });
281
+ });
282
+ var setMessageSuccess = reduce(function(ctx) {
283
+ return _object_spread_props(_object_spread({}, ctx), {
284
+ messageFeedback: 'success',
285
+ messageText: ''
286
+ });
287
+ });
288
+ var setMessageError = reduce(function(ctx) {
289
+ return _object_spread_props(_object_spread({}, ctx), {
290
+ messageFeedback: 'error'
291
+ });
292
+ });
293
+ var clearMessageFeedback = reduce(function(ctx) {
294
+ return _object_spread_props(_object_spread({}, ctx), {
295
+ messageFeedback: null
296
+ });
297
+ });
298
+ // ============================================================================
299
+ // Guards
300
+ // ============================================================================
301
+ var previousViewIsProgress = guard(function(ctx) {
302
+ return ctx.previousView === 'progress';
303
+ });
304
+ var hasSelectedAgent = guard(function(ctx) {
305
+ return ctx.selectedAgentId !== null;
306
+ });
307
+ // ============================================================================
308
+ // Async operation functions
309
+ // ============================================================================
310
+ var sendKillRequest = function(ctx) {
311
+ return _async_to_generator(function() {
312
+ var response;
313
+ return _ts_generator(this, function(_state) {
314
+ switch(_state.label){
315
+ case 0:
316
+ return [
317
+ 4,
318
+ apiClient.fetch("/brains/runs/".concat(ctx.runId), {
319
+ method: 'DELETE'
320
+ })
321
+ ];
322
+ case 1:
323
+ response = _state.sent();
324
+ if (!response.ok) {
325
+ throw new Error("Failed to kill brain: ".concat(response.status));
326
+ }
327
+ return [
328
+ 2,
329
+ response
330
+ ];
331
+ }
332
+ });
333
+ })();
334
+ };
335
+ var sendPauseSignal = function(ctx) {
336
+ return _async_to_generator(function() {
337
+ var response;
338
+ return _ts_generator(this, function(_state) {
339
+ switch(_state.label){
340
+ case 0:
341
+ return [
342
+ 4,
343
+ apiClient.fetch("/brains/runs/".concat(ctx.runId, "/signals"), {
344
+ method: 'POST',
345
+ headers: {
346
+ 'Content-Type': 'application/json'
347
+ },
348
+ body: JSON.stringify({
349
+ type: 'PAUSE'
350
+ })
351
+ })
352
+ ];
353
+ case 1:
354
+ response = _state.sent();
355
+ if (response.status !== 202) {
356
+ throw new Error("Failed to pause: ".concat(response.status));
357
+ }
358
+ return [
359
+ 2,
360
+ response
361
+ ];
362
+ }
363
+ });
364
+ })();
365
+ };
366
+ var sendResumeSignal = function(ctx) {
367
+ return _async_to_generator(function() {
368
+ var response;
369
+ return _ts_generator(this, function(_state) {
370
+ switch(_state.label){
371
+ case 0:
372
+ return [
373
+ 4,
374
+ apiClient.fetch("/brains/runs/".concat(ctx.runId, "/signals"), {
375
+ method: 'POST',
376
+ headers: {
377
+ 'Content-Type': 'application/json'
378
+ },
379
+ body: JSON.stringify({
380
+ type: 'RESUME'
381
+ })
382
+ })
383
+ ];
384
+ case 1:
385
+ response = _state.sent();
386
+ if (response.status !== 202) {
387
+ throw new Error("Failed to resume: ".concat(response.status));
388
+ }
389
+ return [
390
+ 2,
391
+ response
392
+ ];
393
+ }
394
+ });
395
+ })();
396
+ };
397
+ var sendUserMessage = function(ctx) {
398
+ return _async_to_generator(function() {
399
+ var text, response;
400
+ return _ts_generator(this, function(_state) {
401
+ switch(_state.label){
402
+ case 0:
403
+ text = ctx.messageText.trim();
404
+ if (!text) {
405
+ throw new Error('Message is empty');
406
+ }
407
+ return [
408
+ 4,
409
+ apiClient.fetch("/brains/runs/".concat(ctx.runId, "/signals"), {
410
+ method: 'POST',
411
+ headers: {
412
+ 'Content-Type': 'application/json'
413
+ },
414
+ body: JSON.stringify({
415
+ type: 'USER_MESSAGE',
416
+ content: text
417
+ })
418
+ })
419
+ ];
420
+ case 1:
421
+ response = _state.sent();
422
+ if (response.status !== 202) {
423
+ throw new Error("Failed to send message: ".concat(response.status));
424
+ }
425
+ return [
426
+ 2,
427
+ response
428
+ ];
429
+ }
430
+ });
431
+ })();
432
+ };
433
+ // ============================================================================
434
+ // State Machine Definition
435
+ // ============================================================================
436
+ var createWatchMachine = function(runId) {
437
+ var startWithEvents = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : false;
438
+ return createMachine(startWithEvents ? 'events' : 'progress', {
439
+ // Main view states
440
+ progress: state(transition('GO_TO_EVENTS', 'events'), transition('GO_TO_STATE', 'state', setStateForStateView), transition('GO_TO_AGENTS', 'route-agents', setAgentForChat), transition('GO_TO_MESSAGE_INPUT', 'message-input', setPreviousViewForMessage), transition('INITIATE_KILL', 'confirming-kill'), transition('PAUSE', 'pausing'), transition('RESUME', 'resuming')),
441
+ events: state(transition('GO_TO_PROGRESS', 'progress'), transition('GO_TO_STATE', 'state', setStateForStateView), transition('GO_TO_AGENTS', 'route-agents', setAgentForChat), transition('GO_TO_MESSAGE_INPUT', 'message-input', setPreviousViewForMessage), transition('INITIATE_KILL', 'confirming-kill'), transition('PAUSE', 'pausing'), transition('RESUME', 'resuming'), transition('SET_EVENTS_SELECTED_INDEX', 'events', setEventsSelectedIndex)),
442
+ state: state(transition('GO_BACK', 'route-back', clearStateSnapshot), transition('SET_STATE_SCROLL_OFFSET', 'state', setStateScrollOffset)),
443
+ // Routing state to determine where to go back
444
+ 'route-back': state(immediate('progress', previousViewIsProgress), immediate('events')),
445
+ // Routing state to determine if we show picker or go directly to chat
446
+ 'route-agents': state(immediate('agent-chat', hasSelectedAgent), immediate('agent-picker')),
447
+ 'agent-picker': state(transition('GO_BACK', 'route-back'), transition('AGENT_SELECTED', 'agent-chat', selectAgentFromPicker)),
448
+ 'agent-chat': state(transition('GO_BACK', 'route-back', clearSelectedAgent), transition('SET_AGENT_CHAT_SCROLL_OFFSET', 'agent-chat', setAgentChatScrollOffset)),
449
+ // Message input and sending
450
+ 'message-input': state(transition('GO_BACK', 'route-back', clearMessageText), transition('SET_MESSAGE_TEXT', 'message-input', setMessageText), transition('SEND_MESSAGE', 'sending-message')),
451
+ 'sending-message': invoke(sendUserMessage, transition('done', 'message-sent', setMessageSuccess), transition('error', 'message-error', setMessageError)),
452
+ 'message-sent': state(transition('CLEAR_FEEDBACK', 'route-back', clearMessageFeedback)),
453
+ 'message-error': state(transition('CLEAR_FEEDBACK', 'message-input', clearMessageFeedback), transition('GO_BACK', 'route-back', clearMessageText)),
454
+ // Kill flow
455
+ 'confirming-kill': state(transition('CONFIRM_KILL', 'killing'), transition('CANCEL_KILL', 'progress')),
456
+ killing: invoke(sendKillRequest, transition('done', 'killed', markKilled), transition('error', 'kill-error', setKillError)),
457
+ killed: state(// Can still navigate after kill
458
+ transition('GO_TO_EVENTS', 'events'), transition('GO_TO_STATE', 'state', setStateForStateView), transition('GO_TO_AGENTS', 'route-agents', setAgentForChat)),
459
+ 'kill-error': state(// Can retry kill or navigate
460
+ transition('INITIATE_KILL', 'confirming-kill'), transition('GO_TO_EVENTS', 'events'), transition('GO_TO_STATE', 'state', setStateForStateView), transition('GO_TO_AGENTS', 'route-agents', setAgentForChat)),
461
+ // Pause flow
462
+ pausing: invoke(sendPauseSignal, transition('done', 'pause-sent', setPauseMessage), transition('error', 'progress')),
463
+ 'pause-sent': state(transition('CLEAR_PAUSE_RESUME_MESSAGE', 'progress', clearPauseResumeMessage), // Allow navigation while showing message
464
+ transition('GO_TO_EVENTS', 'events', clearPauseResumeMessage), transition('GO_TO_STATE', 'state', setStateForStateView), transition('GO_TO_AGENTS', 'route-agents', setAgentForChat)),
465
+ // Resume flow
466
+ resuming: invoke(sendResumeSignal, transition('done', 'resume-sent', setResumeMessage), transition('error', 'progress')),
467
+ 'resume-sent': state(transition('CLEAR_PAUSE_RESUME_MESSAGE', 'progress', clearPauseResumeMessage), // Allow navigation while showing message
468
+ transition('GO_TO_EVENTS', 'events', clearPauseResumeMessage), transition('GO_TO_STATE', 'state', setStateForStateView), transition('GO_TO_AGENTS', 'route-agents', setAgentForChat))
469
+ }, function() {
470
+ return {
471
+ runId: runId,
472
+ previousView: 'progress',
473
+ stateSnapshot: null,
474
+ stateTitle: '',
475
+ stateScrollOffset: 0,
476
+ selectedAgentId: null,
477
+ agentChatScrollOffset: 0,
478
+ eventsSelectedIndex: null,
479
+ killError: null,
480
+ isKilled: false,
481
+ pauseResumeMessage: null,
482
+ messageText: '',
483
+ messageFeedback: null
484
+ };
485
+ });
486
+ };
487
+ // ============================================================================
488
+ // Helper to map machine state to ViewMode
489
+ // ============================================================================
490
+ /**
491
+ * Map machine state name to ViewMode for rendering.
492
+ * The machine has routing/async states that need to be mapped to display views.
493
+ */ export function machineStateToViewMode(stateName) {
494
+ switch(stateName){
495
+ case 'progress':
496
+ case 'confirming-kill':
497
+ case 'killing':
498
+ case 'killed':
499
+ case 'kill-error':
500
+ case 'pausing':
501
+ case 'pause-sent':
502
+ case 'resuming':
503
+ case 'resume-sent':
504
+ return 'progress';
505
+ case 'events':
506
+ return 'events';
507
+ case 'state':
508
+ return 'state';
509
+ case 'agent-picker':
510
+ case 'route-agents':
511
+ return 'agent-picker';
512
+ case 'agent-chat':
513
+ return 'agent-chat';
514
+ case 'message-input':
515
+ case 'sending-message':
516
+ case 'message-sent':
517
+ case 'message-error':
518
+ return 'message-input';
519
+ case 'route-back':
520
+ // Transient state, treat as progress
521
+ return 'progress';
522
+ default:
523
+ return 'progress';
524
+ }
525
+ }
526
+ /**
527
+ * Check if the machine is in a "confirming kill" state.
528
+ */ export function isConfirmingKill(stateName) {
529
+ return stateName === 'confirming-kill';
530
+ }
531
+ /**
532
+ * Check if the machine is in a "killing" state.
533
+ */ export function isKillingState(stateName) {
534
+ return stateName === 'killing';
535
+ }
536
+ /**
537
+ * Check if the machine is in a "killed" state.
538
+ */ export function isKilledState(stateName) {
539
+ return stateName === 'killed' || stateName === 'kill-error';
540
+ }
541
+ /**
542
+ * Check if the machine is in a "pausing" state.
543
+ */ export function isPausingState(stateName) {
544
+ return stateName === 'pausing';
545
+ }
546
+ /**
547
+ * Check if the machine is in a "resuming" state.
548
+ */ export function isResumingState(stateName) {
549
+ return stateName === 'resuming';
550
+ }
551
+ /**
552
+ * Check if the machine is in a "sending message" state.
553
+ */ export function isSendingMessageState(stateName) {
554
+ return stateName === 'sending-message';
555
+ }
556
+ // ============================================================================
557
+ // React Hook
558
+ // ============================================================================
559
+ /**
560
+ * React hook for the watch UI state machine.
561
+ * Creates a fresh machine when runId changes.
562
+ */ export function useWatchMachine(runId) {
563
+ var startWithEvents = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : false;
564
+ var machine = useMemo(function() {
565
+ return createWatchMachine(runId, startWithEvents);
566
+ }, [
567
+ runId,
568
+ startWithEvents
569
+ ]);
570
+ return useMachine(machine);
571
+ }
572
+ // Export the machine creator for testing
573
+ export { createWatchMachine };
@@ -521,7 +521,7 @@ var createResolverMachine = function(identifier) {
521
521
  * 2. If no brain matches, try as a run ID
522
522
  * 3. If neither works, show an error
523
523
  */ export var WatchResolver = function(param) {
524
- var identifier = param.identifier;
524
+ var identifier = param.identifier, startWithEvents = param.startWithEvents;
525
525
  var machine = useMemo(function() {
526
526
  return createResolverMachine(identifier);
527
527
  }, [
@@ -584,7 +584,8 @@ var createResolverMachine = function(identifier) {
584
584
  }) : null;
585
585
  case 'resolved':
586
586
  return resolvedRunId ? /*#__PURE__*/ React.createElement(Watch, {
587
- runId: resolvedRunId
587
+ runId: resolvedRunId,
588
+ startWithEvents: startWithEvents
588
589
  }) : null;
589
590
  default:
590
591
  return null;