@tylerl0706/ahpx 0.2.10 → 0.2.13

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.
@@ -20,6 +20,7 @@ var ActionType = /* @__PURE__ */ ((ActionType2) => {
20
20
  ActionType2["SessionToolCallConfirmed"] = "session/toolCallConfirmed";
21
21
  ActionType2["SessionToolCallComplete"] = "session/toolCallComplete";
22
22
  ActionType2["SessionToolCallResultConfirmed"] = "session/toolCallResultConfirmed";
23
+ ActionType2["SessionToolCallContentChanged"] = "session/toolCallContentChanged";
23
24
  ActionType2["SessionTurnComplete"] = "session/turnComplete";
24
25
  ActionType2["SessionTurnCancelled"] = "session/turnCancelled";
25
26
  ActionType2["SessionError"] = "session/error";
@@ -33,9 +34,24 @@ var ActionType = /* @__PURE__ */ ((ActionType2) => {
33
34
  ActionType2["SessionPendingMessageSet"] = "session/pendingMessageSet";
34
35
  ActionType2["SessionPendingMessageRemoved"] = "session/pendingMessageRemoved";
35
36
  ActionType2["SessionQueuedMessagesReordered"] = "session/queuedMessagesReordered";
37
+ ActionType2["SessionInputRequested"] = "session/inputRequested";
38
+ ActionType2["SessionInputAnswerChanged"] = "session/inputAnswerChanged";
39
+ ActionType2["SessionInputCompleted"] = "session/inputCompleted";
36
40
  ActionType2["SessionCustomizationsChanged"] = "session/customizationsChanged";
37
41
  ActionType2["SessionCustomizationToggled"] = "session/customizationToggled";
38
42
  ActionType2["SessionTruncated"] = "session/truncated";
43
+ ActionType2["SessionIsReadChanged"] = "session/isReadChanged";
44
+ ActionType2["SessionIsDoneChanged"] = "session/isDoneChanged";
45
+ ActionType2["SessionDiffsChanged"] = "session/diffsChanged";
46
+ ActionType2["RootTerminalsChanged"] = "root/terminalsChanged";
47
+ ActionType2["TerminalData"] = "terminal/data";
48
+ ActionType2["TerminalInput"] = "terminal/input";
49
+ ActionType2["TerminalResized"] = "terminal/resized";
50
+ ActionType2["TerminalClaimed"] = "terminal/claimed";
51
+ ActionType2["TerminalTitleChanged"] = "terminal/titleChanged";
52
+ ActionType2["TerminalCwdChanged"] = "terminal/cwdChanged";
53
+ ActionType2["TerminalExited"] = "terminal/exited";
54
+ ActionType2["TerminalCleared"] = "terminal/cleared";
39
55
  return ActionType2;
40
56
  })(ActionType || {});
41
57
 
@@ -48,6 +64,7 @@ var AuthRequiredReason = /* @__PURE__ */ ((AuthRequiredReason2) => {
48
64
  var NotificationType = /* @__PURE__ */ ((NotificationType2) => {
49
65
  NotificationType2["SessionAdded"] = "notify/sessionAdded";
50
66
  NotificationType2["SessionRemoved"] = "notify/sessionRemoved";
67
+ NotificationType2["SessionSummaryChanged"] = "notify/sessionSummaryChanged";
51
68
  NotificationType2["AuthRequired"] = "notify/authRequired";
52
69
  return NotificationType2;
53
70
  })(NotificationType || {});
@@ -170,11 +187,41 @@ var SessionLifecycle = /* @__PURE__ */ ((SessionLifecycle2) => {
170
187
  return SessionLifecycle2;
171
188
  })(SessionLifecycle || {});
172
189
  var SessionStatus = /* @__PURE__ */ ((SessionStatus2) => {
173
- SessionStatus2["Idle"] = "idle";
174
- SessionStatus2["InProgress"] = "in-progress";
175
- SessionStatus2["Error"] = "error";
190
+ SessionStatus2[SessionStatus2["Idle"] = 1] = "Idle";
191
+ SessionStatus2[SessionStatus2["Error"] = 2] = "Error";
192
+ SessionStatus2[SessionStatus2["InProgress"] = 8] = "InProgress";
193
+ SessionStatus2[SessionStatus2["InputNeeded"] = 24] = "InputNeeded";
176
194
  return SessionStatus2;
177
195
  })(SessionStatus || {});
196
+ var SessionInputResponseKind = /* @__PURE__ */ ((SessionInputResponseKind2) => {
197
+ SessionInputResponseKind2["Accept"] = "accept";
198
+ SessionInputResponseKind2["Decline"] = "decline";
199
+ SessionInputResponseKind2["Cancel"] = "cancel";
200
+ return SessionInputResponseKind2;
201
+ })(SessionInputResponseKind || {});
202
+ var SessionInputQuestionKind = /* @__PURE__ */ ((SessionInputQuestionKind2) => {
203
+ SessionInputQuestionKind2["Text"] = "text";
204
+ SessionInputQuestionKind2["Number"] = "number";
205
+ SessionInputQuestionKind2["Integer"] = "integer";
206
+ SessionInputQuestionKind2["Boolean"] = "boolean";
207
+ SessionInputQuestionKind2["SingleSelect"] = "single-select";
208
+ SessionInputQuestionKind2["MultiSelect"] = "multi-select";
209
+ return SessionInputQuestionKind2;
210
+ })(SessionInputQuestionKind || {});
211
+ var SessionInputAnswerValueKind = /* @__PURE__ */ ((SessionInputAnswerValueKind2) => {
212
+ SessionInputAnswerValueKind2["Text"] = "text";
213
+ SessionInputAnswerValueKind2["Number"] = "number";
214
+ SessionInputAnswerValueKind2["Boolean"] = "boolean";
215
+ SessionInputAnswerValueKind2["Selected"] = "selected";
216
+ SessionInputAnswerValueKind2["SelectedMany"] = "selected-many";
217
+ return SessionInputAnswerValueKind2;
218
+ })(SessionInputAnswerValueKind || {});
219
+ var SessionInputAnswerState = /* @__PURE__ */ ((SessionInputAnswerState2) => {
220
+ SessionInputAnswerState2["Draft"] = "draft";
221
+ SessionInputAnswerState2["Submitted"] = "submitted";
222
+ SessionInputAnswerState2["Skipped"] = "skipped";
223
+ return SessionInputAnswerState2;
224
+ })(SessionInputAnswerState || {});
178
225
  var TurnState = /* @__PURE__ */ ((TurnState2) => {
179
226
  TurnState2["Complete"] = "complete";
180
227
  TurnState2["Cancelled"] = "cancelled";
@@ -220,15 +267,15 @@ var ToolResultContentType = /* @__PURE__ */ ((ToolResultContentType2) => {
220
267
  ToolResultContentType2["EmbeddedResource"] = "embeddedResource";
221
268
  ToolResultContentType2["Resource"] = "resource";
222
269
  ToolResultContentType2["FileEdit"] = "fileEdit";
270
+ ToolResultContentType2["Terminal"] = "terminal";
271
+ ToolResultContentType2["Subagent"] = "subagent";
223
272
  return ToolResultContentType2;
224
273
  })(ToolResultContentType || {});
225
- var CustomizationStatus = /* @__PURE__ */ ((CustomizationStatus2) => {
226
- CustomizationStatus2["Loading"] = "loading";
227
- CustomizationStatus2["Loaded"] = "loaded";
228
- CustomizationStatus2["Degraded"] = "degraded";
229
- CustomizationStatus2["Error"] = "error";
230
- return CustomizationStatus2;
231
- })(CustomizationStatus || {});
274
+ var TerminalClaimKind = /* @__PURE__ */ ((TerminalClaimKind2) => {
275
+ TerminalClaimKind2["Client"] = "client";
276
+ TerminalClaimKind2["Session"] = "session";
277
+ return TerminalClaimKind2;
278
+ })(TerminalClaimKind || {});
232
279
 
233
280
  // src/client/session-handle.ts
234
281
  import { randomUUID } from "crypto";
@@ -413,9 +460,13 @@ var SessionHandle = class extends EventEmitter2 {
413
460
  error
414
461
  });
415
462
  };
463
+ const onError = (err) => {
464
+ finish("error", err.message);
465
+ };
416
466
  const cleanup = () => {
417
467
  if (timer !== void 0) clearTimeout(timer);
418
468
  this.removeListener("action", onAction);
469
+ this.removeListener("error", onError);
419
470
  this._activeTurnId = void 0;
420
471
  };
421
472
  if (options?.timeout) {
@@ -433,6 +484,7 @@ var SessionHandle = class extends EventEmitter2 {
433
484
  }, options.timeout);
434
485
  }
435
486
  this.on("action", onAction);
487
+ this.on("error", onError);
436
488
  this.client.dispatchAction({
437
489
  type: "session/turnStarted" /* SessionTurnStarted */,
438
490
  session: this.uri,
@@ -481,6 +533,7 @@ var SessionHandle = class extends EventEmitter2 {
481
533
  var IS_CLIENT_DISPATCHABLE = {
482
534
  ["root/agentsChanged" /* RootAgentsChanged */]: false,
483
535
  ["root/activeSessionsChanged" /* RootActiveSessionsChanged */]: false,
536
+ ["root/terminalsChanged" /* RootTerminalsChanged */]: false,
484
537
  ["session/ready" /* SessionReady */]: false,
485
538
  ["session/creationFailed" /* SessionCreationFailed */]: false,
486
539
  ["session/turnStarted" /* SessionTurnStarted */]: true,
@@ -492,6 +545,7 @@ var IS_CLIENT_DISPATCHABLE = {
492
545
  ["session/toolCallConfirmed" /* SessionToolCallConfirmed */]: true,
493
546
  ["session/toolCallComplete" /* SessionToolCallComplete */]: true,
494
547
  ["session/toolCallResultConfirmed" /* SessionToolCallResultConfirmed */]: true,
548
+ ["session/toolCallContentChanged" /* SessionToolCallContentChanged */]: false,
495
549
  ["session/turnComplete" /* SessionTurnComplete */]: false,
496
550
  ["session/turnCancelled" /* SessionTurnCancelled */]: true,
497
551
  ["session/error" /* SessionError */]: false,
@@ -505,9 +559,23 @@ var IS_CLIENT_DISPATCHABLE = {
505
559
  ["session/pendingMessageSet" /* SessionPendingMessageSet */]: true,
506
560
  ["session/pendingMessageRemoved" /* SessionPendingMessageRemoved */]: true,
507
561
  ["session/queuedMessagesReordered" /* SessionQueuedMessagesReordered */]: true,
562
+ ["session/inputRequested" /* SessionInputRequested */]: false,
563
+ ["session/inputAnswerChanged" /* SessionInputAnswerChanged */]: true,
564
+ ["session/inputCompleted" /* SessionInputCompleted */]: true,
508
565
  ["session/customizationsChanged" /* SessionCustomizationsChanged */]: false,
509
566
  ["session/customizationToggled" /* SessionCustomizationToggled */]: true,
510
- ["session/truncated" /* SessionTruncated */]: true
567
+ ["session/truncated" /* SessionTruncated */]: true,
568
+ ["session/isReadChanged" /* SessionIsReadChanged */]: true,
569
+ ["session/isDoneChanged" /* SessionIsDoneChanged */]: true,
570
+ ["session/diffsChanged" /* SessionDiffsChanged */]: false,
571
+ ["terminal/data" /* TerminalData */]: false,
572
+ ["terminal/input" /* TerminalInput */]: true,
573
+ ["terminal/resized" /* TerminalResized */]: true,
574
+ ["terminal/claimed" /* TerminalClaimed */]: true,
575
+ ["terminal/titleChanged" /* TerminalTitleChanged */]: true,
576
+ ["terminal/cwdChanged" /* TerminalCwdChanged */]: false,
577
+ ["terminal/exited" /* TerminalExited */]: false,
578
+ ["terminal/cleared" /* TerminalCleared */]: true
511
579
  };
512
580
 
513
581
  // src/protocol/reducers.ts
@@ -524,7 +592,34 @@ function tcBase(tc) {
524
592
  _meta: tc._meta
525
593
  };
526
594
  }
527
- function endTurn(state, turnId, turnState, summaryStatus, error) {
595
+ function hasPendingToolCallConfirmation(state) {
596
+ if (!state.activeTurn) {
597
+ return false;
598
+ }
599
+ return state.activeTurn.responseParts.some(
600
+ (part) => part.kind === "toolCall" /* ToolCall */ && (part.toolCall.status === "pending-confirmation" /* PendingConfirmation */ || part.toolCall.status === "pending-result-confirmation" /* PendingResultConfirmation */)
601
+ );
602
+ }
603
+ function summaryStatus(state, terminalStatus) {
604
+ if (terminalStatus) {
605
+ return terminalStatus;
606
+ }
607
+ if ((state.inputRequests?.length ?? 0) > 0 || hasPendingToolCallConfirmation(state)) {
608
+ return 24 /* InputNeeded */;
609
+ }
610
+ if (state.activeTurn) {
611
+ return 8 /* InProgress */;
612
+ }
613
+ return 1 /* Idle */;
614
+ }
615
+ function refreshSummaryStatus(state) {
616
+ const status = summaryStatus(state);
617
+ if (status === state.summary.status) {
618
+ return state;
619
+ }
620
+ return { ...state, summary: { ...state.summary, status } };
621
+ }
622
+ function endTurn(state, turnId, turnState, terminalStatus, error) {
528
623
  if (!state.activeTurn || state.activeTurn.id !== turnId) {
529
624
  return state;
530
625
  }
@@ -556,13 +651,31 @@ function endTurn(state, turnId, turnState, summaryStatus, error) {
556
651
  state: turnState,
557
652
  error
558
653
  };
559
- return {
654
+ const next = {
560
655
  ...state,
561
656
  turns: [...state.turns, turn],
562
657
  activeTurn: void 0,
563
- summary: { ...state.summary, status: summaryStatus, modifiedAt: Date.now() }
658
+ summary: { ...state.summary, modifiedAt: Date.now() }
659
+ };
660
+ delete next.inputRequests;
661
+ return {
662
+ ...next,
663
+ summary: { ...next.summary, status: summaryStatus(next, terminalStatus) }
564
664
  };
565
665
  }
666
+ function upsertInputRequest(state, request) {
667
+ const existing = state.inputRequests ?? [];
668
+ const idx = existing.findIndex((r) => r.id === request.id);
669
+ const inputRequests = [...existing];
670
+ if (idx >= 0) {
671
+ const answers = request.answers ?? inputRequests[idx].answers;
672
+ inputRequests[idx] = { ...request, answers };
673
+ } else {
674
+ inputRequests.push(request);
675
+ }
676
+ const next = { ...state, inputRequests };
677
+ return { ...next, summary: { ...next.summary, status: summaryStatus(next), modifiedAt: Date.now(), isRead: false } };
678
+ }
566
679
  function updateToolCallInParts(state, turnId, toolCallId, updater) {
567
680
  const activeTurn = state.activeTurn;
568
681
  if (!activeTurn || activeTurn.id !== turnId) {
@@ -618,6 +731,8 @@ function rootReducer(state, action, log7) {
618
731
  return { ...state, agents: action.agents };
619
732
  case "root/activeSessionsChanged" /* RootActiveSessionsChanged */:
620
733
  return { ...state, activeSessions: action.activeSessions };
734
+ case "root/terminalsChanged" /* RootTerminalsChanged */:
735
+ return { ...state, terminals: action.terminals };
621
736
  default:
622
737
  softAssertNever(action, log7);
623
738
  return state;
@@ -630,7 +745,7 @@ function sessionReducer(state, action, log7) {
630
745
  return {
631
746
  ...state,
632
747
  lifecycle: "ready" /* Ready */,
633
- summary: { ...state.summary, status: "idle" /* Idle */ }
748
+ summary: { ...state.summary, status: 1 /* Idle */ }
634
749
  };
635
750
  case "session/creationFailed" /* SessionCreationFailed */:
636
751
  return {
@@ -642,7 +757,6 @@ function sessionReducer(state, action, log7) {
642
757
  case "session/turnStarted" /* SessionTurnStarted */: {
643
758
  let next = {
644
759
  ...state,
645
- summary: { ...state.summary, status: "in-progress" /* InProgress */, modifiedAt: Date.now() },
646
760
  activeTurn: {
647
761
  id: action.turnId,
648
762
  userMessage: action.userMessage,
@@ -650,6 +764,10 @@ function sessionReducer(state, action, log7) {
650
764
  usage: void 0
651
765
  }
652
766
  };
767
+ next = {
768
+ ...next,
769
+ summary: { ...next.summary, status: summaryStatus(next), modifiedAt: Date.now(), isRead: false }
770
+ };
653
771
  if (action.queuedMessageId) {
654
772
  if (next.steeringMessage?.id === action.queuedMessageId) {
655
773
  next = { ...next, steeringMessage: void 0 };
@@ -661,41 +779,17 @@ function sessionReducer(state, action, log7) {
661
779
  }
662
780
  return next;
663
781
  }
664
- case "session/delta" /* SessionDelta */: {
665
- const updated = updateResponsePart(state, action.turnId, action.partId, (part) => {
782
+ case "session/delta" /* SessionDelta */:
783
+ return updateResponsePart(state, action.turnId, action.partId, (part) => {
666
784
  if (part.kind === "markdown" /* Markdown */) {
667
785
  return { ...part, content: part.content + action.content };
668
786
  }
669
787
  return part;
670
788
  });
671
- if (updated === state && state.activeTurn && state.activeTurn.id === action.turnId) {
672
- return {
673
- ...state,
674
- activeTurn: {
675
- ...state.activeTurn,
676
- responseParts: [
677
- ...state.activeTurn.responseParts,
678
- { kind: "markdown" /* Markdown */, id: action.partId, content: action.content }
679
- ]
680
- }
681
- };
682
- }
683
- return updated;
684
- }
685
- case "session/responsePart" /* SessionResponsePart */: {
789
+ case "session/responsePart" /* SessionResponsePart */:
686
790
  if (!state.activeTurn || state.activeTurn.id !== action.turnId) {
687
791
  return state;
688
792
  }
689
- const newPartId = action.part.kind === "toolCall" /* ToolCall */ ? action.part.toolCall.toolCallId : "id" in action.part ? action.part.id : void 0;
690
- if (newPartId !== void 0) {
691
- const exists = state.activeTurn.responseParts.some((p) => {
692
- const id = p.kind === "toolCall" /* ToolCall */ ? p.toolCall.toolCallId : "id" in p ? p.id : void 0;
693
- return id === newPartId;
694
- });
695
- if (exists) {
696
- return state;
697
- }
698
- }
699
793
  return {
700
794
  ...state,
701
795
  activeTurn: {
@@ -703,13 +797,12 @@ function sessionReducer(state, action, log7) {
703
797
  responseParts: [...state.activeTurn.responseParts, action.part]
704
798
  }
705
799
  };
706
- }
707
800
  case "session/turnComplete" /* SessionTurnComplete */:
708
- return endTurn(state, action.turnId, "complete" /* Complete */, "idle" /* Idle */);
801
+ return endTurn(state, action.turnId, "complete" /* Complete */);
709
802
  case "session/turnCancelled" /* SessionTurnCancelled */:
710
- return endTurn(state, action.turnId, "cancelled" /* Cancelled */, "idle" /* Idle */);
803
+ return endTurn(state, action.turnId, "cancelled" /* Cancelled */);
711
804
  case "session/error" /* SessionError */:
712
- return endTurn(state, action.turnId, "error" /* Error */, "error" /* Error */, action.error);
805
+ return endTurn(state, action.turnId, "error" /* Error */, 2 /* Error */, action.error);
713
806
  // ── Tool Call State Machine ───────────────────────────────────────────
714
807
  case "session/toolCallStart" /* SessionToolCallStart */:
715
808
  if (!state.activeTurn || state.activeTurn.id !== action.turnId) {
@@ -747,7 +840,7 @@ function sessionReducer(state, action, log7) {
747
840
  };
748
841
  });
749
842
  case "session/toolCallReady" /* SessionToolCallReady */:
750
- return updateToolCallInParts(state, action.turnId, action.toolCallId, (tc) => {
843
+ return refreshSummaryStatus(updateToolCallInParts(state, action.turnId, action.toolCallId, (tc) => {
751
844
  if (tc.status !== "streaming" /* Streaming */ && tc.status !== "running" /* Running */) {
752
845
  return tc;
753
846
  }
@@ -768,9 +861,9 @@ function sessionReducer(state, action, log7) {
768
861
  toolInput: action.toolInput,
769
862
  confirmationTitle: action.confirmationTitle
770
863
  };
771
- });
864
+ }));
772
865
  case "session/toolCallConfirmed" /* SessionToolCallConfirmed */:
773
- return updateToolCallInParts(state, action.turnId, action.toolCallId, (tc) => {
866
+ return refreshSummaryStatus(updateToolCallInParts(state, action.turnId, action.toolCallId, (tc) => {
774
867
  if (tc.status !== "pending-confirmation" /* PendingConfirmation */) {
775
868
  return tc;
776
869
  }
@@ -793,9 +886,9 @@ function sessionReducer(state, action, log7) {
793
886
  reasonMessage: action.reasonMessage,
794
887
  userSuggestion: action.userSuggestion
795
888
  };
796
- });
889
+ }));
797
890
  case "session/toolCallComplete" /* SessionToolCallComplete */:
798
- return updateToolCallInParts(state, action.turnId, action.toolCallId, (tc) => {
891
+ return refreshSummaryStatus(updateToolCallInParts(state, action.turnId, action.toolCallId, (tc) => {
799
892
  if (tc.status !== "running" /* Running */ && tc.status !== "pending-confirmation" /* PendingConfirmation */) {
800
893
  return tc;
801
894
  }
@@ -819,9 +912,9 @@ function sessionReducer(state, action, log7) {
819
912
  confirmed,
820
913
  ...action.result
821
914
  };
822
- });
915
+ }));
823
916
  case "session/toolCallResultConfirmed" /* SessionToolCallResultConfirmed */:
824
- return updateToolCallInParts(state, action.turnId, action.toolCallId, (tc) => {
917
+ return refreshSummaryStatus(updateToolCallInParts(state, action.turnId, action.toolCallId, (tc) => {
825
918
  if (tc.status !== "pending-result-confirmation" /* PendingResultConfirmation */) {
826
919
  return tc;
827
920
  }
@@ -847,6 +940,16 @@ function sessionReducer(state, action, log7) {
847
940
  toolInput: tc.toolInput,
848
941
  reason: "result-denied" /* ResultDenied */
849
942
  };
943
+ }));
944
+ case "session/toolCallContentChanged" /* SessionToolCallContentChanged */:
945
+ return updateToolCallInParts(state, action.turnId, action.toolCallId, (tc) => {
946
+ if (tc.status !== "running" /* Running */) {
947
+ return tc;
948
+ }
949
+ return {
950
+ ...tc,
951
+ content: action.content
952
+ };
850
953
  });
851
954
  // ── Metadata ──────────────────────────────────────────────────────────
852
955
  case "session/titleChanged" /* SessionTitleChanged */:
@@ -874,6 +977,21 @@ function sessionReducer(state, action, log7) {
874
977
  ...state,
875
978
  summary: { ...state.summary, model: action.model, modifiedAt: Date.now() }
876
979
  };
980
+ case "session/isReadChanged" /* SessionIsReadChanged */:
981
+ return {
982
+ ...state,
983
+ summary: { ...state.summary, isRead: action.isRead }
984
+ };
985
+ case "session/isDoneChanged" /* SessionIsDoneChanged */:
986
+ return {
987
+ ...state,
988
+ summary: { ...state.summary, isDone: action.isDone }
989
+ };
990
+ case "session/diffsChanged" /* SessionDiffsChanged */:
991
+ return {
992
+ ...state,
993
+ summary: { ...state.summary, diffs: action.diffs }
994
+ };
877
995
  case "session/serverToolsChanged" /* SessionServerToolsChanged */:
878
996
  return { ...state, serverTools: action.tools };
879
997
  case "session/activeClientChanged" /* SessionActiveClientChanged */:
@@ -917,11 +1035,62 @@ function sessionReducer(state, action, log7) {
917
1035
  }
918
1036
  turns = state.turns.slice(0, idx + 1);
919
1037
  }
920
- return {
1038
+ const next = {
921
1039
  ...state,
922
1040
  turns,
923
1041
  activeTurn: void 0,
924
- summary: { ...state.summary, status: "idle" /* Idle */, modifiedAt: Date.now() }
1042
+ summary: { ...state.summary, modifiedAt: Date.now() }
1043
+ };
1044
+ delete next.inputRequests;
1045
+ return {
1046
+ ...next,
1047
+ summary: { ...next.summary, status: summaryStatus(next) }
1048
+ };
1049
+ }
1050
+ // ── Session Input Requests ─────────────────────────────────────────────
1051
+ case "session/inputRequested" /* SessionInputRequested */:
1052
+ return upsertInputRequest(state, action.request);
1053
+ case "session/inputAnswerChanged" /* SessionInputAnswerChanged */: {
1054
+ const existing = state.inputRequests;
1055
+ const idx = existing?.findIndex((request2) => request2.id === action.requestId) ?? -1;
1056
+ if (!existing || idx < 0) {
1057
+ return state;
1058
+ }
1059
+ const request = existing[idx];
1060
+ const answers = { ...request.answers ?? {} };
1061
+ if (action.answer === void 0) {
1062
+ delete answers[action.questionId];
1063
+ } else {
1064
+ answers[action.questionId] = action.answer;
1065
+ }
1066
+ const updated = [...existing];
1067
+ updated[idx] = {
1068
+ ...request,
1069
+ answers: Object.keys(answers).length > 0 ? answers : void 0
1070
+ };
1071
+ return {
1072
+ ...state,
1073
+ inputRequests: updated,
1074
+ summary: { ...state.summary, modifiedAt: Date.now() }
1075
+ };
1076
+ }
1077
+ case "session/inputCompleted" /* SessionInputCompleted */: {
1078
+ const existing = state.inputRequests;
1079
+ if (!existing?.some((request) => request.id === action.requestId)) {
1080
+ return state;
1081
+ }
1082
+ const inputRequests = existing.filter((request) => request.id !== action.requestId);
1083
+ const next = {
1084
+ ...state
1085
+ };
1086
+ if (inputRequests.length > 0) {
1087
+ next.inputRequests = inputRequests;
1088
+ } else {
1089
+ delete next.inputRequests;
1090
+ }
1091
+ return {
1092
+ ...next,
1093
+ summary: { ...next.summary, status: summaryStatus(next), modifiedAt: Date.now() }
925
1094
  };
926
1095
  }
927
1096
  // ── Pending Messages ──────────────────────────────────────────────────
@@ -979,12 +1148,41 @@ function sessionReducer(state, action, log7) {
979
1148
  return state;
980
1149
  }
981
1150
  }
1151
+ function terminalReducer(state, action, log7) {
1152
+ switch (action.type) {
1153
+ case "terminal/data" /* TerminalData */:
1154
+ return { ...state, content: state.content + action.data };
1155
+ case "terminal/input" /* TerminalInput */:
1156
+ return state;
1157
+ case "terminal/resized" /* TerminalResized */:
1158
+ return { ...state, cols: action.cols, rows: action.rows };
1159
+ case "terminal/claimed" /* TerminalClaimed */:
1160
+ return { ...state, claim: action.claim };
1161
+ case "terminal/titleChanged" /* TerminalTitleChanged */:
1162
+ return { ...state, title: action.title };
1163
+ case "terminal/cwdChanged" /* TerminalCwdChanged */:
1164
+ return { ...state, cwd: action.cwd };
1165
+ case "terminal/exited" /* TerminalExited */:
1166
+ return { ...state, exitCode: action.exitCode };
1167
+ case "terminal/cleared" /* TerminalCleared */:
1168
+ return { ...state, content: "" };
1169
+ default:
1170
+ softAssertNever(action, log7);
1171
+ return state;
1172
+ }
1173
+ }
982
1174
 
983
1175
  // src/client/state.ts
984
- var ROOT_ACTION_TYPES = /* @__PURE__ */ new Set(["root/agentsChanged" /* RootAgentsChanged */, "root/activeSessionsChanged" /* RootActiveSessionsChanged */]);
1176
+ var ROOT_ACTION_TYPES = /* @__PURE__ */ new Set([
1177
+ "root/agentsChanged" /* RootAgentsChanged */,
1178
+ "root/activeSessionsChanged" /* RootActiveSessionsChanged */,
1179
+ "root/terminalsChanged" /* RootTerminalsChanged */
1180
+ ]);
1181
+ var TERMINAL_ACTION_PREFIX = "terminal/";
985
1182
  var StateMirror = class {
986
1183
  rootState = { agents: [] };
987
1184
  sessions = /* @__PURE__ */ new Map();
1185
+ terminals = /* @__PURE__ */ new Map();
988
1186
  serverSeq = 0;
989
1187
  pendingActions = /* @__PURE__ */ new Map();
990
1188
  /** Current root state (agents, active session count). */
@@ -1003,6 +1201,19 @@ var StateMirror = class {
1003
1201
  get sessionUris() {
1004
1202
  return [...this.sessions.keys()];
1005
1203
  }
1204
+ /** Get a terminal state by URI. */
1205
+ getTerminal(uri) {
1206
+ return this.terminals.get(uri);
1207
+ }
1208
+ /** All tracked terminal URIs. */
1209
+ get terminalUris() {
1210
+ return [...this.terminals.keys()];
1211
+ }
1212
+ /** Remove a terminal from tracking. */
1213
+ removeTerminal(uri) {
1214
+ this.terminals.delete(uri);
1215
+ this.pendingActions.delete(uri);
1216
+ }
1006
1217
  /**
1007
1218
  * Load a snapshot (from initialize, reconnect, or subscribe).
1008
1219
  * After registering a session, replays any actions that arrived before the snapshot.
@@ -1031,6 +1242,24 @@ var StateMirror = class {
1031
1242
  }
1032
1243
  }
1033
1244
  }
1245
+ } else if ("claim" in snapshot.state) {
1246
+ const terminalState = snapshot.state;
1247
+ this.terminals.set(snapshot.resource, terminalState);
1248
+ const buffered = this.pendingActions.get(snapshot.resource);
1249
+ if (buffered) {
1250
+ this.pendingActions.delete(snapshot.resource);
1251
+ for (const env of buffered) {
1252
+ if (env.serverSeq > snapshot.fromSeq) {
1253
+ const current = this.terminals.get(snapshot.resource);
1254
+ if (current) {
1255
+ this.terminals.set(
1256
+ snapshot.resource,
1257
+ terminalReducer(current, env.action)
1258
+ );
1259
+ }
1260
+ }
1261
+ }
1262
+ }
1034
1263
  }
1035
1264
  }
1036
1265
  /**
@@ -1041,6 +1270,22 @@ var StateMirror = class {
1041
1270
  const action = envelope.action;
1042
1271
  if (ROOT_ACTION_TYPES.has(action.type)) {
1043
1272
  this.rootState = rootReducer(this.rootState, action);
1273
+ } else if (action.type.startsWith(TERMINAL_ACTION_PREFIX)) {
1274
+ const terminalAction = action;
1275
+ const terminalUri = terminalAction.terminal;
1276
+ if (terminalUri) {
1277
+ const current = this.terminals.get(terminalUri);
1278
+ if (current) {
1279
+ this.terminals.set(terminalUri, terminalReducer(current, terminalAction));
1280
+ } else {
1281
+ let buffer = this.pendingActions.get(terminalUri);
1282
+ if (!buffer) {
1283
+ buffer = [];
1284
+ this.pendingActions.set(terminalUri, buffer);
1285
+ }
1286
+ buffer.push(envelope);
1287
+ }
1288
+ }
1044
1289
  } else {
1045
1290
  const sessionAction = action;
1046
1291
  const sessionUri = sessionAction.session;
@@ -1334,6 +1579,7 @@ var ACTION_INTRODUCED_IN = {
1334
1579
  ["session/toolCallConfirmed" /* SessionToolCallConfirmed */]: 1,
1335
1580
  ["session/toolCallComplete" /* SessionToolCallComplete */]: 1,
1336
1581
  ["session/toolCallResultConfirmed" /* SessionToolCallResultConfirmed */]: 1,
1582
+ ["session/toolCallContentChanged" /* SessionToolCallContentChanged */]: 1,
1337
1583
  ["session/turnComplete" /* SessionTurnComplete */]: 1,
1338
1584
  ["session/turnCancelled" /* SessionTurnCancelled */]: 1,
1339
1585
  ["session/error" /* SessionError */]: 1,
@@ -1347,13 +1593,29 @@ var ACTION_INTRODUCED_IN = {
1347
1593
  ["session/pendingMessageSet" /* SessionPendingMessageSet */]: 1,
1348
1594
  ["session/pendingMessageRemoved" /* SessionPendingMessageRemoved */]: 1,
1349
1595
  ["session/queuedMessagesReordered" /* SessionQueuedMessagesReordered */]: 1,
1596
+ ["session/inputRequested" /* SessionInputRequested */]: 1,
1597
+ ["session/inputAnswerChanged" /* SessionInputAnswerChanged */]: 1,
1598
+ ["session/inputCompleted" /* SessionInputCompleted */]: 1,
1350
1599
  ["session/customizationsChanged" /* SessionCustomizationsChanged */]: 1,
1351
1600
  ["session/customizationToggled" /* SessionCustomizationToggled */]: 1,
1352
- ["session/truncated" /* SessionTruncated */]: 1
1601
+ ["session/truncated" /* SessionTruncated */]: 1,
1602
+ ["session/isReadChanged" /* SessionIsReadChanged */]: 1,
1603
+ ["session/isDoneChanged" /* SessionIsDoneChanged */]: 1,
1604
+ ["session/diffsChanged" /* SessionDiffsChanged */]: 1,
1605
+ ["root/terminalsChanged" /* RootTerminalsChanged */]: 1,
1606
+ ["terminal/data" /* TerminalData */]: 1,
1607
+ ["terminal/input" /* TerminalInput */]: 1,
1608
+ ["terminal/resized" /* TerminalResized */]: 1,
1609
+ ["terminal/claimed" /* TerminalClaimed */]: 1,
1610
+ ["terminal/titleChanged" /* TerminalTitleChanged */]: 1,
1611
+ ["terminal/cwdChanged" /* TerminalCwdChanged */]: 1,
1612
+ ["terminal/exited" /* TerminalExited */]: 1,
1613
+ ["terminal/cleared" /* TerminalCleared */]: 1
1353
1614
  };
1354
1615
  var NOTIFICATION_INTRODUCED_IN = {
1355
1616
  ["notify/sessionAdded" /* SessionAdded */]: 1,
1356
1617
  ["notify/sessionRemoved" /* SessionRemoved */]: 1,
1618
+ ["notify/sessionSummaryChanged" /* SessionSummaryChanged */]: 1,
1357
1619
  ["notify/authRequired" /* AuthRequired */]: 1
1358
1620
  };
1359
1621
 
@@ -1510,6 +1772,28 @@ var AhpClient = class extends EventEmitter4 {
1510
1772
  this._sessions.delete(sessionUri);
1511
1773
  return result;
1512
1774
  }
1775
+ /**
1776
+ * Create a new terminal on the server.
1777
+ */
1778
+ async createTerminal(terminalUri, claim, options) {
1779
+ this.ensureConnected();
1780
+ return this.protocol.request("createTerminal", {
1781
+ terminal: terminalUri,
1782
+ claim,
1783
+ ...options
1784
+ });
1785
+ }
1786
+ /**
1787
+ * Dispose a terminal and kill its process if still running.
1788
+ */
1789
+ async disposeTerminal(terminalUri) {
1790
+ this.ensureConnected();
1791
+ const result = await this.protocol.request("disposeTerminal", {
1792
+ terminal: terminalUri
1793
+ });
1794
+ this._state.removeTerminal(terminalUri);
1795
+ return result;
1796
+ }
1513
1797
  /**
1514
1798
  * List all sessions on the server.
1515
1799
  */
@@ -2470,6 +2754,10 @@ export {
2470
2754
  PendingMessageKind,
2471
2755
  SessionLifecycle,
2472
2756
  SessionStatus,
2757
+ SessionInputResponseKind,
2758
+ SessionInputQuestionKind,
2759
+ SessionInputAnswerValueKind,
2760
+ SessionInputAnswerState,
2473
2761
  TurnState,
2474
2762
  AttachmentType,
2475
2763
  ResponsePartKind,
@@ -2477,8 +2765,9 @@ export {
2477
2765
  ToolCallConfirmationReason,
2478
2766
  ToolCallCancellationReason,
2479
2767
  ToolResultContentType,
2480
- CustomizationStatus,
2768
+ TerminalClaimKind,
2481
2769
  SessionHandle,
2770
+ terminalReducer,
2482
2771
  StateMirror,
2483
2772
  Transport,
2484
2773
  ActiveClientManager,