@grackle-ai/ahp 0.131.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 (153) hide show
  1. package/dist/index.d.ts +23 -0
  2. package/dist/index.d.ts.map +1 -0
  3. package/dist/index.js +23 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/vendor/ahp/action-origin.generated.d.ts +33 -0
  6. package/dist/vendor/ahp/action-origin.generated.d.ts.map +1 -0
  7. package/dist/vendor/ahp/action-origin.generated.js +71 -0
  8. package/dist/vendor/ahp/action-origin.generated.js.map +1 -0
  9. package/dist/vendor/ahp/actions.d.ts +14 -0
  10. package/dist/vendor/ahp/actions.d.ts.map +1 -0
  11. package/dist/vendor/ahp/actions.js +15 -0
  12. package/dist/vendor/ahp/actions.js.map +1 -0
  13. package/dist/vendor/ahp/channels-changeset/actions.d.ts +87 -0
  14. package/dist/vendor/ahp/channels-changeset/actions.d.ts.map +1 -0
  15. package/dist/vendor/ahp/channels-changeset/actions.js +9 -0
  16. package/dist/vendor/ahp/channels-changeset/actions.js.map +1 -0
  17. package/dist/vendor/ahp/channels-changeset/commands.d.ts +103 -0
  18. package/dist/vendor/ahp/channels-changeset/commands.d.ts.map +1 -0
  19. package/dist/vendor/ahp/channels-changeset/commands.js +22 -0
  20. package/dist/vendor/ahp/channels-changeset/commands.js.map +1 -0
  21. package/dist/vendor/ahp/channels-changeset/reducer.d.ts +18 -0
  22. package/dist/vendor/ahp/channels-changeset/reducer.d.ts.map +1 -0
  23. package/dist/vendor/ahp/channels-changeset/reducer.js +65 -0
  24. package/dist/vendor/ahp/channels-changeset/reducer.js.map +1 -0
  25. package/dist/vendor/ahp/channels-changeset/state.d.ts +155 -0
  26. package/dist/vendor/ahp/channels-changeset/state.d.ts.map +1 -0
  27. package/dist/vendor/ahp/channels-changeset/state.js +39 -0
  28. package/dist/vendor/ahp/channels-changeset/state.js.map +1 -0
  29. package/dist/vendor/ahp/channels-otlp/notifications.d.ts +121 -0
  30. package/dist/vendor/ahp/channels-otlp/notifications.d.ts.map +1 -0
  31. package/dist/vendor/ahp/channels-otlp/notifications.js +11 -0
  32. package/dist/vendor/ahp/channels-otlp/notifications.js.map +1 -0
  33. package/dist/vendor/ahp/channels-otlp/state.d.ts +65 -0
  34. package/dist/vendor/ahp/channels-otlp/state.d.ts.map +1 -0
  35. package/dist/vendor/ahp/channels-otlp/state.js +10 -0
  36. package/dist/vendor/ahp/channels-otlp/state.js.map +1 -0
  37. package/dist/vendor/ahp/channels-root/actions.d.ts +62 -0
  38. package/dist/vendor/ahp/channels-root/actions.d.ts.map +1 -0
  39. package/dist/vendor/ahp/channels-root/actions.js +8 -0
  40. package/dist/vendor/ahp/channels-root/actions.js.map +1 -0
  41. package/dist/vendor/ahp/channels-root/commands.d.ts +172 -0
  42. package/dist/vendor/ahp/channels-root/commands.d.ts.map +1 -0
  43. package/dist/vendor/ahp/channels-root/commands.js +10 -0
  44. package/dist/vendor/ahp/channels-root/commands.js.map +1 -0
  45. package/dist/vendor/ahp/channels-root/notifications.d.ts +136 -0
  46. package/dist/vendor/ahp/channels-root/notifications.d.ts.map +1 -0
  47. package/dist/vendor/ahp/channels-root/notifications.js +9 -0
  48. package/dist/vendor/ahp/channels-root/notifications.js.map +1 -0
  49. package/dist/vendor/ahp/channels-root/reducer.d.ts +12 -0
  50. package/dist/vendor/ahp/channels-root/reducer.d.ts.map +1 -0
  51. package/dist/vendor/ahp/channels-root/reducer.js +36 -0
  52. package/dist/vendor/ahp/channels-root/reducer.js.map +1 -0
  53. package/dist/vendor/ahp/channels-root/state.d.ts +123 -0
  54. package/dist/vendor/ahp/channels-root/state.d.ts.map +1 -0
  55. package/dist/vendor/ahp/channels-root/state.js +19 -0
  56. package/dist/vendor/ahp/channels-root/state.js.map +1 -0
  57. package/dist/vendor/ahp/channels-session/actions.d.ts +736 -0
  58. package/dist/vendor/ahp/channels-session/actions.d.ts.map +1 -0
  59. package/dist/vendor/ahp/channels-session/actions.js +8 -0
  60. package/dist/vendor/ahp/channels-session/actions.js.map +1 -0
  61. package/dist/vendor/ahp/channels-session/commands.d.ts +261 -0
  62. package/dist/vendor/ahp/channels-session/commands.d.ts.map +1 -0
  63. package/dist/vendor/ahp/channels-session/commands.js +23 -0
  64. package/dist/vendor/ahp/channels-session/commands.js.map +1 -0
  65. package/dist/vendor/ahp/channels-session/reducer.d.ts +14 -0
  66. package/dist/vendor/ahp/channels-session/reducer.d.ts.map +1 -0
  67. package/dist/vendor/ahp/channels-session/reducer.js +703 -0
  68. package/dist/vendor/ahp/channels-session/reducer.js.map +1 -0
  69. package/dist/vendor/ahp/channels-session/state.d.ts +1217 -0
  70. package/dist/vendor/ahp/channels-session/state.d.ts.map +1 -0
  71. package/dist/vendor/ahp/channels-session/state.js +229 -0
  72. package/dist/vendor/ahp/channels-session/state.js.map +1 -0
  73. package/dist/vendor/ahp/channels-terminal/actions.d.ts +185 -0
  74. package/dist/vendor/ahp/channels-terminal/actions.d.ts.map +1 -0
  75. package/dist/vendor/ahp/channels-terminal/actions.js +8 -0
  76. package/dist/vendor/ahp/channels-terminal/actions.js.map +1 -0
  77. package/dist/vendor/ahp/channels-terminal/commands.d.ts +50 -0
  78. package/dist/vendor/ahp/channels-terminal/commands.d.ts.map +1 -0
  79. package/dist/vendor/ahp/channels-terminal/commands.js +8 -0
  80. package/dist/vendor/ahp/channels-terminal/commands.js.map +1 -0
  81. package/dist/vendor/ahp/channels-terminal/reducer.d.ts +12 -0
  82. package/dist/vendor/ahp/channels-terminal/reducer.d.ts.map +1 -0
  83. package/dist/vendor/ahp/channels-terminal/reducer.js +80 -0
  84. package/dist/vendor/ahp/channels-terminal/reducer.js.map +1 -0
  85. package/dist/vendor/ahp/channels-terminal/state.d.ts +151 -0
  86. package/dist/vendor/ahp/channels-terminal/state.d.ts.map +1 -0
  87. package/dist/vendor/ahp/channels-terminal/state.js +18 -0
  88. package/dist/vendor/ahp/channels-terminal/state.js.map +1 -0
  89. package/dist/vendor/ahp/commands.d.ts +14 -0
  90. package/dist/vendor/ahp/commands.d.ts.map +1 -0
  91. package/dist/vendor/ahp/commands.js +15 -0
  92. package/dist/vendor/ahp/commands.js.map +1 -0
  93. package/dist/vendor/ahp/common/actions.d.ts +107 -0
  94. package/dist/vendor/ahp/common/actions.d.ts.map +1 -0
  95. package/dist/vendor/ahp/common/actions.js +77 -0
  96. package/dist/vendor/ahp/common/actions.js.map +1 -0
  97. package/dist/vendor/ahp/common/commands.d.ts +594 -0
  98. package/dist/vendor/ahp/common/commands.d.ts.map +1 -0
  99. package/dist/vendor/ahp/common/commands.js +32 -0
  100. package/dist/vendor/ahp/common/commands.js.map +1 -0
  101. package/dist/vendor/ahp/common/errors.d.ts +184 -0
  102. package/dist/vendor/ahp/common/errors.d.ts.map +1 -0
  103. package/dist/vendor/ahp/common/errors.js +82 -0
  104. package/dist/vendor/ahp/common/errors.js.map +1 -0
  105. package/dist/vendor/ahp/common/messages.d.ts +330 -0
  106. package/dist/vendor/ahp/common/messages.d.ts.map +1 -0
  107. package/dist/vendor/ahp/common/messages.js +11 -0
  108. package/dist/vendor/ahp/common/messages.js.map +1 -0
  109. package/dist/vendor/ahp/common/notifications.d.ts +58 -0
  110. package/dist/vendor/ahp/common/notifications.d.ts.map +1 -0
  111. package/dist/vendor/ahp/common/notifications.js +20 -0
  112. package/dist/vendor/ahp/common/notifications.js.map +1 -0
  113. package/dist/vendor/ahp/common/reducer-helpers.d.ts +24 -0
  114. package/dist/vendor/ahp/common/reducer-helpers.d.ts.map +1 -0
  115. package/dist/vendor/ahp/common/reducer-helpers.js +31 -0
  116. package/dist/vendor/ahp/common/reducer-helpers.js.map +1 -0
  117. package/dist/vendor/ahp/common/state.d.ts +286 -0
  118. package/dist/vendor/ahp/common/state.d.ts.map +1 -0
  119. package/dist/vendor/ahp/common/state.js +11 -0
  120. package/dist/vendor/ahp/common/state.js.map +1 -0
  121. package/dist/vendor/ahp/errors.d.ts +8 -0
  122. package/dist/vendor/ahp/errors.d.ts.map +1 -0
  123. package/dist/vendor/ahp/errors.js +9 -0
  124. package/dist/vendor/ahp/errors.js.map +1 -0
  125. package/dist/vendor/ahp/index.d.ts +24 -0
  126. package/dist/vendor/ahp/index.d.ts.map +1 -0
  127. package/dist/vendor/ahp/index.js +21 -0
  128. package/dist/vendor/ahp/index.js.map +1 -0
  129. package/dist/vendor/ahp/messages.d.ts +8 -0
  130. package/dist/vendor/ahp/messages.d.ts.map +1 -0
  131. package/dist/vendor/ahp/messages.js +9 -0
  132. package/dist/vendor/ahp/messages.js.map +1 -0
  133. package/dist/vendor/ahp/notifications.d.ts +11 -0
  134. package/dist/vendor/ahp/notifications.d.ts.map +1 -0
  135. package/dist/vendor/ahp/notifications.js +12 -0
  136. package/dist/vendor/ahp/notifications.js.map +1 -0
  137. package/dist/vendor/ahp/reducers.d.ts +12 -0
  138. package/dist/vendor/ahp/reducers.d.ts.map +1 -0
  139. package/dist/vendor/ahp/reducers.js +13 -0
  140. package/dist/vendor/ahp/reducers.js.map +1 -0
  141. package/dist/vendor/ahp/state.d.ts +15 -0
  142. package/dist/vendor/ahp/state.d.ts.map +1 -0
  143. package/dist/vendor/ahp/state.js +16 -0
  144. package/dist/vendor/ahp/state.js.map +1 -0
  145. package/dist/vendor/ahp/version/message-checks.d.ts +15 -0
  146. package/dist/vendor/ahp/version/message-checks.d.ts.map +1 -0
  147. package/dist/vendor/ahp/version/message-checks.js +16 -0
  148. package/dist/vendor/ahp/version/message-checks.js.map +1 -0
  149. package/dist/vendor/ahp/version/registry.d.ts +56 -0
  150. package/dist/vendor/ahp/version/registry.d.ts.map +1 -0
  151. package/dist/vendor/ahp/version/registry.js +138 -0
  152. package/dist/vendor/ahp/version/registry.js.map +1 -0
  153. package/package.json +47 -0
@@ -0,0 +1,703 @@
1
+ /* eslint-disable -- vendored third-party code, see SOURCE.md */
2
+ /**
3
+ * Session Channel Reducer — Pure reducer for `SessionState`, including all
4
+ * session-internal helpers (turn lifecycle, tool call transitions, pending
5
+ * messages, input requests).
6
+ *
7
+ * @module channels-session/reducer
8
+ */
9
+ import { ActionType } from '../common/actions.js';
10
+ import { SessionLifecycle, SessionStatus, TurnState, ToolCallStatus, ToolCallConfirmationReason, ToolCallCancellationReason, ResponsePartKind, PendingMessageKind, } from './state.js';
11
+ import { softAssertNever } from '../common/reducer-helpers.js';
12
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
13
+ /** Extracts the common base fields shared by all tool call lifecycle states. */
14
+ function tcBase(tc) {
15
+ return {
16
+ toolCallId: tc.toolCallId,
17
+ toolName: tc.toolName,
18
+ displayName: tc.displayName,
19
+ toolClientId: tc.toolClientId,
20
+ _meta: tc._meta,
21
+ };
22
+ }
23
+ /** Resolves a selected option from the confirmation options array by ID. */
24
+ function resolveSelectedOption(options, id) {
25
+ if (!id || !options) {
26
+ return undefined;
27
+ }
28
+ return options.find(o => o.id === id);
29
+ }
30
+ /** Returns `true` if the active turn has any tool call awaiting user confirmation. */
31
+ function hasPendingToolCallConfirmation(state) {
32
+ if (!state.activeTurn) {
33
+ return false;
34
+ }
35
+ return state.activeTurn.responseParts.some(part => part.kind === ResponsePartKind.ToolCall
36
+ && (part.toolCall.status === ToolCallStatus.PendingConfirmation
37
+ || part.toolCall.status === ToolCallStatus.PendingResultConfirmation));
38
+ }
39
+ /** Bitmask covering the mutually-exclusive activity bits (bits 0–4). */
40
+ const STATUS_ACTIVITY_MASK = (1 << 5) - 1;
41
+ /** Sets or clears a metadata flag on a status value. */
42
+ function withStatusFlag(status, flag, set) {
43
+ return set ? status | flag : status & ~flag;
44
+ }
45
+ /** Derives the summary status from live session work, preserving orthogonal flags. */
46
+ function summaryStatus(state, terminalStatus) {
47
+ let activity;
48
+ if (terminalStatus) {
49
+ activity = terminalStatus;
50
+ }
51
+ else if ((state.inputRequests?.length ?? 0) > 0 || hasPendingToolCallConfirmation(state)) {
52
+ activity = SessionStatus.InputNeeded;
53
+ }
54
+ else if (state.activeTurn) {
55
+ activity = SessionStatus.InProgress;
56
+ }
57
+ else {
58
+ activity = SessionStatus.Idle;
59
+ }
60
+ return state.summary.status & ~STATUS_ACTIVITY_MASK | activity;
61
+ }
62
+ /**
63
+ * Returns a state with `summary.status` recomputed. Use this after reducers
64
+ * that change data which feeds into {@link summaryStatus} (e.g. tool call
65
+ * lifecycle transitions that may enter or leave a pending-confirmation state).
66
+ */
67
+ function refreshSummaryStatus(state) {
68
+ const status = summaryStatus(state);
69
+ if (status === state.summary.status) {
70
+ return state;
71
+ }
72
+ return { ...state, summary: { ...state.summary, status } };
73
+ }
74
+ /**
75
+ * Ends the active turn, finalizing it into a completed turn record.
76
+ *
77
+ * Tool call parts with non-terminal states are forced to cancelled.
78
+ * Pending permissions are stripped from tool call parts.
79
+ */
80
+ function endTurn(state, turnId, turnState, terminalStatus, error) {
81
+ if (!state.activeTurn || state.activeTurn.id !== turnId) {
82
+ return state;
83
+ }
84
+ const active = state.activeTurn;
85
+ const responseParts = active.responseParts.map(part => {
86
+ if (part.kind !== ResponsePartKind.ToolCall) {
87
+ return part;
88
+ }
89
+ const tc = part.toolCall;
90
+ if (tc.status === ToolCallStatus.Completed || tc.status === ToolCallStatus.Cancelled) {
91
+ return part;
92
+ }
93
+ // Force non-terminal tool calls into cancelled state
94
+ return {
95
+ kind: ResponsePartKind.ToolCall,
96
+ toolCall: {
97
+ status: ToolCallStatus.Cancelled,
98
+ ...tcBase(tc),
99
+ invocationMessage: tc.status === ToolCallStatus.Streaming ? (tc.invocationMessage ?? '') : tc.invocationMessage,
100
+ toolInput: tc.status === ToolCallStatus.Streaming ? undefined : tc.toolInput,
101
+ reason: ToolCallCancellationReason.Skipped,
102
+ },
103
+ };
104
+ });
105
+ const turn = {
106
+ id: active.id,
107
+ userMessage: active.userMessage,
108
+ responseParts,
109
+ usage: active.usage,
110
+ state: turnState,
111
+ error,
112
+ };
113
+ const next = {
114
+ ...state,
115
+ turns: [...state.turns, turn],
116
+ activeTurn: undefined,
117
+ summary: { ...state.summary, modifiedAt: Date.now() },
118
+ };
119
+ delete next.inputRequests;
120
+ return {
121
+ ...next,
122
+ summary: { ...next.summary, status: summaryStatus(next, terminalStatus) },
123
+ };
124
+ }
125
+ function upsertInputRequest(state, request) {
126
+ const existing = state.inputRequests ?? [];
127
+ const idx = existing.findIndex(r => r.id === request.id);
128
+ const inputRequests = [...existing];
129
+ if (idx >= 0) {
130
+ const answers = request.answers ?? inputRequests[idx].answers;
131
+ inputRequests[idx] = { ...request, answers };
132
+ }
133
+ else {
134
+ inputRequests.push(request);
135
+ }
136
+ const next = { ...state, inputRequests };
137
+ return { ...next, summary: { ...next.summary, status: withStatusFlag(summaryStatus(next), SessionStatus.IsRead, false), modifiedAt: Date.now() } };
138
+ }
139
+ /**
140
+ * Immutably updates the tool call inside a `ToolCall` response part in the
141
+ * active turn's `responseParts` array. Returns `state` unchanged if the
142
+ * active turn or tool call doesn't match.
143
+ */
144
+ function updateToolCallInParts(state, turnId, toolCallId, updater) {
145
+ const activeTurn = state.activeTurn;
146
+ if (!activeTurn || activeTurn.id !== turnId) {
147
+ return state;
148
+ }
149
+ let found = false;
150
+ const responseParts = activeTurn.responseParts.map(part => {
151
+ if (part.kind === ResponsePartKind.ToolCall && part.toolCall.toolCallId === toolCallId) {
152
+ const updated = updater(part.toolCall);
153
+ if (updated === part.toolCall) {
154
+ return part;
155
+ }
156
+ found = true;
157
+ return { ...part, toolCall: updated };
158
+ }
159
+ return part;
160
+ });
161
+ if (!found) {
162
+ return state;
163
+ }
164
+ return {
165
+ ...state,
166
+ activeTurn: { ...activeTurn, responseParts },
167
+ };
168
+ }
169
+ /**
170
+ * Immutably updates a response part by `partId` in the active turn.
171
+ * For markdown/reasoning parts, matches on `id`. For tool call parts,
172
+ * matches on `toolCall.toolCallId`.
173
+ */
174
+ function updateResponsePart(state, turnId, partId, updater) {
175
+ const activeTurn = state.activeTurn;
176
+ if (!activeTurn || activeTurn.id !== turnId) {
177
+ return state;
178
+ }
179
+ let found = false;
180
+ const responseParts = activeTurn.responseParts.map(part => {
181
+ if (!found) {
182
+ const id = part.kind === ResponsePartKind.ToolCall
183
+ ? part.toolCall.toolCallId
184
+ : 'id' in part ? part.id : undefined;
185
+ if (id === partId) {
186
+ found = true;
187
+ return updater(part);
188
+ }
189
+ }
190
+ return part;
191
+ });
192
+ if (!found) {
193
+ return state;
194
+ }
195
+ return {
196
+ ...state,
197
+ activeTurn: { ...activeTurn, responseParts },
198
+ };
199
+ }
200
+ // ─── Session Reducer ─────────────────────────────────────────────────────────
201
+ /**
202
+ * Pure reducer for session state. Handles all {@link SessionAction} variants.
203
+ */
204
+ export function sessionReducer(state, action, log) {
205
+ switch (action.type) {
206
+ // ── Lifecycle ──────────────────────────────────────────────────────────
207
+ case ActionType.SessionReady:
208
+ return {
209
+ ...state,
210
+ lifecycle: SessionLifecycle.Ready,
211
+ summary: { ...state.summary, status: SessionStatus.Idle },
212
+ };
213
+ case ActionType.SessionCreationFailed:
214
+ return {
215
+ ...state,
216
+ lifecycle: SessionLifecycle.CreationFailed,
217
+ creationError: action.error,
218
+ };
219
+ // ── Turn Lifecycle ────────────────────────────────────────────────────
220
+ case ActionType.SessionTurnStarted: {
221
+ let next = {
222
+ ...state,
223
+ activeTurn: {
224
+ id: action.turnId,
225
+ userMessage: action.userMessage,
226
+ responseParts: [],
227
+ usage: undefined,
228
+ },
229
+ };
230
+ next = {
231
+ ...next,
232
+ summary: { ...next.summary, status: withStatusFlag(summaryStatus(next), SessionStatus.IsRead, false), modifiedAt: Date.now() },
233
+ };
234
+ // If this turn was auto-started from a pending message, remove it
235
+ if (action.queuedMessageId) {
236
+ if (next.steeringMessage?.id === action.queuedMessageId) {
237
+ next = { ...next, steeringMessage: undefined };
238
+ }
239
+ if (next.queuedMessages) {
240
+ const filtered = next.queuedMessages.filter(m => m.id !== action.queuedMessageId);
241
+ next = { ...next, queuedMessages: filtered.length > 0 ? filtered : undefined };
242
+ }
243
+ }
244
+ return next;
245
+ }
246
+ case ActionType.SessionDelta:
247
+ return updateResponsePart(state, action.turnId, action.partId, part => {
248
+ if (part.kind === ResponsePartKind.Markdown) {
249
+ return { ...part, content: part.content + action.content };
250
+ }
251
+ return part;
252
+ });
253
+ case ActionType.SessionResponsePart:
254
+ if (!state.activeTurn || state.activeTurn.id !== action.turnId) {
255
+ return state;
256
+ }
257
+ return {
258
+ ...state,
259
+ activeTurn: {
260
+ ...state.activeTurn,
261
+ responseParts: [...state.activeTurn.responseParts, action.part],
262
+ },
263
+ };
264
+ case ActionType.SessionTurnComplete:
265
+ return endTurn(state, action.turnId, TurnState.Complete);
266
+ case ActionType.SessionTurnCancelled:
267
+ return endTurn(state, action.turnId, TurnState.Cancelled);
268
+ case ActionType.SessionError:
269
+ return endTurn(state, action.turnId, TurnState.Error, SessionStatus.Error, action.error);
270
+ // ── Tool Call State Machine ───────────────────────────────────────────
271
+ case ActionType.SessionToolCallStart:
272
+ if (!state.activeTurn || state.activeTurn.id !== action.turnId) {
273
+ return state;
274
+ }
275
+ return {
276
+ ...state,
277
+ activeTurn: {
278
+ ...state.activeTurn,
279
+ responseParts: [
280
+ ...state.activeTurn.responseParts,
281
+ {
282
+ kind: ResponsePartKind.ToolCall,
283
+ toolCall: {
284
+ toolCallId: action.toolCallId,
285
+ toolName: action.toolName,
286
+ displayName: action.displayName,
287
+ toolClientId: action.toolClientId,
288
+ _meta: action._meta,
289
+ status: ToolCallStatus.Streaming,
290
+ },
291
+ },
292
+ ],
293
+ },
294
+ };
295
+ case ActionType.SessionToolCallDelta:
296
+ return updateToolCallInParts(state, action.turnId, action.toolCallId, tc => {
297
+ if (tc.status !== ToolCallStatus.Streaming) {
298
+ return tc;
299
+ }
300
+ return {
301
+ ...tc,
302
+ partialInput: (tc.partialInput ?? '') + action.content,
303
+ invocationMessage: action.invocationMessage ?? tc.invocationMessage,
304
+ };
305
+ });
306
+ case ActionType.SessionToolCallReady:
307
+ return refreshSummaryStatus(updateToolCallInParts(state, action.turnId, action.toolCallId, tc => {
308
+ if (tc.status !== ToolCallStatus.Streaming && tc.status !== ToolCallStatus.Running) {
309
+ return tc;
310
+ }
311
+ const base = tcBase(tc);
312
+ if (action.confirmed) {
313
+ return {
314
+ status: ToolCallStatus.Running,
315
+ ...base,
316
+ invocationMessage: action.invocationMessage,
317
+ toolInput: action.toolInput,
318
+ confirmed: action.confirmed,
319
+ };
320
+ }
321
+ return {
322
+ status: ToolCallStatus.PendingConfirmation,
323
+ ...base,
324
+ invocationMessage: action.invocationMessage,
325
+ toolInput: action.toolInput,
326
+ confirmationTitle: action.confirmationTitle,
327
+ edits: action.edits,
328
+ editable: action.editable,
329
+ ...(action.options ? { options: action.options } : {}),
330
+ };
331
+ }));
332
+ case ActionType.SessionToolCallConfirmed:
333
+ return refreshSummaryStatus(updateToolCallInParts(state, action.turnId, action.toolCallId, tc => {
334
+ if (tc.status !== ToolCallStatus.PendingConfirmation) {
335
+ return tc;
336
+ }
337
+ const base = tcBase(tc);
338
+ const selectedOption = resolveSelectedOption(tc.options, action.selectedOptionId);
339
+ if (action.approved) {
340
+ return {
341
+ status: ToolCallStatus.Running,
342
+ ...base,
343
+ invocationMessage: tc.invocationMessage,
344
+ toolInput: action.editedToolInput ?? tc.toolInput,
345
+ confirmed: action.confirmed,
346
+ ...(selectedOption ? { selectedOption } : {}),
347
+ };
348
+ }
349
+ return {
350
+ status: ToolCallStatus.Cancelled,
351
+ ...base,
352
+ invocationMessage: tc.invocationMessage,
353
+ toolInput: tc.toolInput,
354
+ reason: action.reason,
355
+ reasonMessage: action.reasonMessage,
356
+ userSuggestion: action.userSuggestion,
357
+ ...(selectedOption ? { selectedOption } : {}),
358
+ };
359
+ }));
360
+ case ActionType.SessionToolCallComplete:
361
+ return refreshSummaryStatus(updateToolCallInParts(state, action.turnId, action.toolCallId, tc => {
362
+ if (tc.status !== ToolCallStatus.Running && tc.status !== ToolCallStatus.PendingConfirmation) {
363
+ return tc;
364
+ }
365
+ const base = tcBase(tc);
366
+ const confirmed = tc.status === ToolCallStatus.Running
367
+ ? tc.confirmed
368
+ : ToolCallConfirmationReason.NotNeeded;
369
+ const selectedOption = tc.status === ToolCallStatus.Running
370
+ ? tc.selectedOption
371
+ : undefined;
372
+ if (action.requiresResultConfirmation) {
373
+ return {
374
+ status: ToolCallStatus.PendingResultConfirmation,
375
+ ...base,
376
+ invocationMessage: tc.invocationMessage,
377
+ toolInput: tc.toolInput,
378
+ confirmed,
379
+ ...(selectedOption ? { selectedOption } : {}),
380
+ ...action.result,
381
+ };
382
+ }
383
+ return {
384
+ status: ToolCallStatus.Completed,
385
+ ...base,
386
+ invocationMessage: tc.invocationMessage,
387
+ toolInput: tc.toolInput,
388
+ confirmed,
389
+ ...(selectedOption ? { selectedOption } : {}),
390
+ ...action.result,
391
+ };
392
+ }));
393
+ case ActionType.SessionToolCallResultConfirmed:
394
+ return refreshSummaryStatus(updateToolCallInParts(state, action.turnId, action.toolCallId, tc => {
395
+ if (tc.status !== ToolCallStatus.PendingResultConfirmation) {
396
+ return tc;
397
+ }
398
+ const base = tcBase(tc);
399
+ if (action.approved) {
400
+ return {
401
+ status: ToolCallStatus.Completed,
402
+ ...base,
403
+ invocationMessage: tc.invocationMessage,
404
+ toolInput: tc.toolInput,
405
+ confirmed: tc.confirmed,
406
+ ...(tc.selectedOption ? { selectedOption: tc.selectedOption } : {}),
407
+ success: tc.success,
408
+ pastTenseMessage: tc.pastTenseMessage,
409
+ content: tc.content,
410
+ structuredContent: tc.structuredContent,
411
+ error: tc.error,
412
+ };
413
+ }
414
+ return {
415
+ status: ToolCallStatus.Cancelled,
416
+ ...base,
417
+ invocationMessage: tc.invocationMessage,
418
+ toolInput: tc.toolInput,
419
+ reason: ToolCallCancellationReason.ResultDenied,
420
+ ...(tc.selectedOption ? { selectedOption: tc.selectedOption } : {}),
421
+ };
422
+ }));
423
+ case ActionType.SessionToolCallContentChanged:
424
+ return updateToolCallInParts(state, action.turnId, action.toolCallId, tc => {
425
+ if (tc.status !== ToolCallStatus.Running) {
426
+ return tc;
427
+ }
428
+ return {
429
+ ...tc,
430
+ content: action.content,
431
+ };
432
+ });
433
+ // ── Metadata ──────────────────────────────────────────────────────────
434
+ case ActionType.SessionTitleChanged:
435
+ return {
436
+ ...state,
437
+ summary: { ...state.summary, title: action.title, modifiedAt: Date.now() },
438
+ };
439
+ case ActionType.SessionUsage:
440
+ if (!state.activeTurn || state.activeTurn.id !== action.turnId) {
441
+ return state;
442
+ }
443
+ return {
444
+ ...state,
445
+ activeTurn: { ...state.activeTurn, usage: action.usage },
446
+ };
447
+ case ActionType.SessionReasoning:
448
+ return updateResponsePart(state, action.turnId, action.partId, part => {
449
+ if (part.kind === ResponsePartKind.Reasoning) {
450
+ return { ...part, content: part.content + action.content };
451
+ }
452
+ return part;
453
+ });
454
+ case ActionType.SessionModelChanged:
455
+ return {
456
+ ...state,
457
+ summary: { ...state.summary, model: action.model, modifiedAt: Date.now() },
458
+ };
459
+ case ActionType.SessionAgentChanged:
460
+ return {
461
+ ...state,
462
+ summary: { ...state.summary, agent: action.agent, modifiedAt: Date.now() },
463
+ };
464
+ case ActionType.SessionIsReadChanged:
465
+ return {
466
+ ...state,
467
+ summary: { ...state.summary, status: withStatusFlag(state.summary.status, SessionStatus.IsRead, action.isRead) },
468
+ };
469
+ case ActionType.SessionIsArchivedChanged:
470
+ return {
471
+ ...state,
472
+ summary: { ...state.summary, status: withStatusFlag(state.summary.status, SessionStatus.IsArchived, action.isArchived) },
473
+ };
474
+ case ActionType.SessionActivityChanged:
475
+ return {
476
+ ...state,
477
+ summary: { ...state.summary, activity: action.activity },
478
+ };
479
+ case ActionType.SessionChangesetsChanged: {
480
+ const { changesets: _omit, ...summaryWithoutChangesets } = state.summary;
481
+ const newSummary = action.changesets
482
+ ? { ...summaryWithoutChangesets, changesets: action.changesets }
483
+ : summaryWithoutChangesets;
484
+ return { ...state, summary: newSummary };
485
+ }
486
+ case ActionType.SessionConfigChanged:
487
+ if (!state.config) {
488
+ return state;
489
+ }
490
+ return {
491
+ ...state,
492
+ config: {
493
+ ...state.config,
494
+ values: action.replace ? { ...action.config } : { ...state.config.values, ...action.config },
495
+ },
496
+ summary: {
497
+ ...state.summary,
498
+ modifiedAt: Date.now(),
499
+ },
500
+ };
501
+ case ActionType.SessionMetaChanged:
502
+ return { ...state, _meta: action._meta };
503
+ case ActionType.SessionServerToolsChanged:
504
+ return { ...state, serverTools: action.tools };
505
+ case ActionType.SessionActiveClientChanged:
506
+ return {
507
+ ...state,
508
+ activeClient: action.activeClient ?? undefined,
509
+ };
510
+ case ActionType.SessionActiveClientToolsChanged:
511
+ if (!state.activeClient) {
512
+ return state;
513
+ }
514
+ return {
515
+ ...state,
516
+ activeClient: { ...state.activeClient, tools: action.tools },
517
+ };
518
+ // ── Customizations ──────────────────────────────────────────────────
519
+ case ActionType.SessionCustomizationsChanged:
520
+ return { ...state, customizations: action.customizations };
521
+ case ActionType.SessionCustomizationToggled: {
522
+ const list = state.customizations;
523
+ if (!list) {
524
+ return state;
525
+ }
526
+ const idx = list.findIndex(c => c.customization.uri === action.uri);
527
+ if (idx < 0) {
528
+ return state;
529
+ }
530
+ const updated = [...list];
531
+ updated[idx] = { ...list[idx], enabled: action.enabled };
532
+ return { ...state, customizations: updated };
533
+ }
534
+ case ActionType.SessionCustomizationUpdated: {
535
+ const list = state.customizations ?? [];
536
+ const idx = list.findIndex(c => c.customization.uri === action.customization.uri);
537
+ if (idx < 0) {
538
+ const inserted = {
539
+ customization: action.customization,
540
+ enabled: action.enabled ?? false,
541
+ };
542
+ if (action.status !== undefined) {
543
+ inserted.status = action.status;
544
+ }
545
+ if (action.statusMessage !== undefined) {
546
+ inserted.statusMessage = action.statusMessage;
547
+ }
548
+ if (action.agents !== undefined) {
549
+ inserted.agents = action.agents;
550
+ }
551
+ return { ...state, customizations: [...list, inserted] };
552
+ }
553
+ const updated = [...list];
554
+ const next = { ...list[idx], customization: action.customization };
555
+ if (action.enabled !== undefined) {
556
+ next.enabled = action.enabled;
557
+ }
558
+ if (action.status !== undefined) {
559
+ next.status = action.status;
560
+ }
561
+ if (action.statusMessage !== undefined) {
562
+ next.statusMessage = action.statusMessage;
563
+ }
564
+ if (action.agents !== undefined) {
565
+ next.agents = action.agents;
566
+ }
567
+ updated[idx] = next;
568
+ return { ...state, customizations: updated };
569
+ }
570
+ // ── Truncation ────────────────────────────────────────────────────────
571
+ case ActionType.SessionTruncated: {
572
+ let turns;
573
+ if (action.turnId === undefined) {
574
+ turns = [];
575
+ }
576
+ else {
577
+ const idx = state.turns.findIndex(t => t.id === action.turnId);
578
+ if (idx < 0) {
579
+ return state;
580
+ }
581
+ turns = state.turns.slice(0, idx + 1);
582
+ }
583
+ const next = {
584
+ ...state,
585
+ turns,
586
+ activeTurn: undefined,
587
+ summary: { ...state.summary, modifiedAt: Date.now() },
588
+ };
589
+ delete next.inputRequests;
590
+ return {
591
+ ...next,
592
+ summary: { ...next.summary, status: summaryStatus(next) },
593
+ };
594
+ }
595
+ // ── Session Input Requests ─────────────────────────────────────────────
596
+ case ActionType.SessionInputRequested:
597
+ return upsertInputRequest(state, action.request);
598
+ case ActionType.SessionInputAnswerChanged: {
599
+ const existing = state.inputRequests;
600
+ const idx = existing?.findIndex(request => request.id === action.requestId) ?? -1;
601
+ if (!existing || idx < 0) {
602
+ return state;
603
+ }
604
+ const request = existing[idx];
605
+ const answers = { ...(request.answers ?? {}) };
606
+ if (action.answer === undefined) {
607
+ delete answers[action.questionId];
608
+ }
609
+ else {
610
+ answers[action.questionId] = action.answer;
611
+ }
612
+ const updated = [...existing];
613
+ updated[idx] = {
614
+ ...request,
615
+ answers: Object.keys(answers).length > 0 ? answers : undefined,
616
+ };
617
+ return {
618
+ ...state,
619
+ inputRequests: updated,
620
+ summary: { ...state.summary, modifiedAt: Date.now() },
621
+ };
622
+ }
623
+ case ActionType.SessionInputCompleted: {
624
+ const existing = state.inputRequests;
625
+ if (!existing?.some(request => request.id === action.requestId)) {
626
+ return state;
627
+ }
628
+ const inputRequests = existing.filter(request => request.id !== action.requestId);
629
+ const next = {
630
+ ...state,
631
+ };
632
+ if (inputRequests.length > 0) {
633
+ next.inputRequests = inputRequests;
634
+ }
635
+ else {
636
+ delete next.inputRequests;
637
+ }
638
+ return {
639
+ ...next,
640
+ summary: { ...next.summary, status: summaryStatus(next), modifiedAt: Date.now() },
641
+ };
642
+ }
643
+ // ── Pending Messages ──────────────────────────────────────────────────
644
+ case ActionType.SessionPendingMessageSet: {
645
+ const entry = { id: action.id, userMessage: action.userMessage };
646
+ if (action.kind === PendingMessageKind.Steering) {
647
+ return { ...state, steeringMessage: entry };
648
+ }
649
+ const existing = state.queuedMessages ?? [];
650
+ const idx = existing.findIndex(m => m.id === action.id);
651
+ if (idx >= 0) {
652
+ const updated = [...existing];
653
+ updated[idx] = entry;
654
+ return { ...state, queuedMessages: updated };
655
+ }
656
+ return { ...state, queuedMessages: [...existing, entry] };
657
+ }
658
+ case ActionType.SessionPendingMessageRemoved: {
659
+ if (action.kind === PendingMessageKind.Steering) {
660
+ if (!state.steeringMessage || state.steeringMessage.id !== action.id) {
661
+ return state;
662
+ }
663
+ return { ...state, steeringMessage: undefined };
664
+ }
665
+ const existing = state.queuedMessages;
666
+ if (!existing) {
667
+ return state;
668
+ }
669
+ const filtered = existing.filter(m => m.id !== action.id);
670
+ return filtered.length === existing.length
671
+ ? state
672
+ : { ...state, queuedMessages: filtered.length > 0 ? filtered : undefined };
673
+ }
674
+ case ActionType.SessionQueuedMessagesReordered: {
675
+ const existing = state.queuedMessages;
676
+ if (!existing) {
677
+ return state;
678
+ }
679
+ const byId = new Map(existing.map(m => [m.id, m]));
680
+ const ordered = new Set();
681
+ const reordered = action.order
682
+ .filter(id => {
683
+ if (byId.has(id) && !ordered.has(id)) {
684
+ ordered.add(id);
685
+ return true;
686
+ }
687
+ return false;
688
+ })
689
+ .map(id => byId.get(id));
690
+ // Append any messages not mentioned in order, preserving original order
691
+ for (const m of existing) {
692
+ if (!ordered.has(m.id)) {
693
+ reordered.push(m);
694
+ }
695
+ }
696
+ return { ...state, queuedMessages: reordered };
697
+ }
698
+ default:
699
+ softAssertNever(action, log);
700
+ return state;
701
+ }
702
+ }
703
+ //# sourceMappingURL=reducer.js.map