happy-imou-cloud 2.1.49 → 2.1.51

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 (55) hide show
  1. package/dist/AcpBackend-CqO3D07V.mjs +2619 -0
  2. package/dist/AcpBackend-XPiTd6ph.cjs +2621 -0
  3. package/dist/{BaseReasoningProcessor-Dn9NcoHz.cjs → BaseReasoningProcessor-BD9tiwep.cjs} +1 -144
  4. package/dist/{BaseReasoningProcessor-CAVeOdyo.mjs → BaseReasoningProcessor-CjlayL2f.mjs} +2 -144
  5. package/dist/ConversationHistory-Bl2doTA-.cjs +780 -0
  6. package/dist/ConversationHistory-CI5bBfuA.mjs +771 -0
  7. package/dist/{ProviderSelectionHandler-BJJc7qOR.cjs → ProviderSelectionHandler-C7GE5QjX.cjs} +6 -6
  8. package/dist/{ProviderSelectionHandler-DIYidT13.mjs → ProviderSelectionHandler-uQ8jzdzr.mjs} +2 -2
  9. package/dist/RuntimeShell-BDt42io_.mjs +252 -0
  10. package/dist/RuntimeShell-D_Te12wq.cjs +258 -0
  11. package/dist/bootstrapManagedProviderSession-Bln-TwyB.cjs +147 -0
  12. package/dist/bootstrapManagedProviderSession-D2Z6YU3n.mjs +145 -0
  13. package/dist/claude-BKNT-2fG.cjs +1080 -0
  14. package/dist/claude-CnN5WCWj.mjs +1073 -0
  15. package/dist/codex-DLGP8WF6.mjs +577 -0
  16. package/dist/codex-Fv2eali8.cjs +582 -0
  17. package/dist/{command-VcH4hbhi.cjs → command-BWPlJyCN.cjs} +16 -8
  18. package/dist/{command-CzfRRhVe.mjs → command-CELwsYoG.mjs} +15 -7
  19. package/dist/config-CFL0Gkqt.cjs +184 -0
  20. package/dist/config-ChSPe7p9.mjs +174 -0
  21. package/dist/createDefaultRuntimeShell-BXu3vCvT.cjs +33 -0
  22. package/dist/createDefaultRuntimeShell-DOg6g3-G.mjs +31 -0
  23. package/dist/cursor-Blq1cHdr.cjs +91 -0
  24. package/dist/cursor-CwPNSy_A.mjs +88 -0
  25. package/dist/future-Dq4Ha1Dn.cjs +24 -0
  26. package/dist/future-xRdLl3vf.mjs +22 -0
  27. package/dist/{index-xa1kwZoj.cjs → index-B_JYgMUS.cjs} +189 -5352
  28. package/dist/{index-7Z93BoVn.mjs → index-CX-F_fuk.mjs} +177 -5331
  29. package/dist/index.cjs +2 -2
  30. package/dist/index.mjs +2 -2
  31. package/dist/installFatalProcessHandlers-0vaw9MAz.mjs +55 -0
  32. package/dist/installFatalProcessHandlers-CyURn5Bp.cjs +57 -0
  33. package/dist/launch-BoCCEd5p.mjs +63 -0
  34. package/dist/launch-wZA5BcvS.cjs +66 -0
  35. package/dist/lib.cjs +2 -3
  36. package/dist/lib.d.cts +20 -17
  37. package/dist/lib.d.mts +20 -17
  38. package/dist/lib.mjs +1 -2
  39. package/dist/resolveCommand-B3BGyBE2.mjs +189 -0
  40. package/dist/resolveCommand-DYMd9PNC.cjs +193 -0
  41. package/dist/{runClaude-zCwRhpOw.mjs → runClaude-Be0myF9k.mjs} +8 -5
  42. package/dist/{runClaude-BBGNmGj6.cjs → runClaude-DZJt5er7.cjs} +46 -43
  43. package/dist/{runCodex-BbgLVjb9.mjs → runCodex-BSnyN4m7.mjs} +226 -117
  44. package/dist/{runCodex-jUU6U2tZ.cjs → runCodex-DTCcGRue.cjs} +269 -160
  45. package/dist/runCursor-Bn1PuwJy.cjs +506 -0
  46. package/dist/runCursor-M6dQ6bGF.mjs +504 -0
  47. package/dist/{runGemini-DcwNsudA.mjs → runGemini-BNm4vYKA.mjs} +279 -5
  48. package/dist/{runGemini-C0NT8MHK.cjs → runGemini-Bn3lFhz6.cjs} +309 -35
  49. package/dist/{registerKillSessionHandler-DLDg2EES.mjs → sessionControl-1bT_7OI6.mjs} +1643 -2405
  50. package/dist/{registerKillSessionHandler-CfCya6si.cjs → sessionControl-flKnQrx0.cjs} +1647 -2417
  51. package/dist/{api-DnqaNvyV.mjs → types-B5vtxa38.mjs} +55 -5
  52. package/dist/{api-D7nAeZi7.cjs → types-CttABk32.cjs} +55 -4
  53. package/package.json +2 -2
  54. package/dist/types-CiliQpqS.mjs +0 -52
  55. package/dist/types-DVk3crez.cjs +0 -54
@@ -0,0 +1,780 @@
1
+ 'use strict';
2
+
3
+ var RuntimeShell = require('./RuntimeShell-D_Te12wq.cjs');
4
+ var sessionControl = require('./sessionControl-flKnQrx0.cjs');
5
+ var persistence = require('./types-CttABk32.cjs');
6
+
7
+ async function launchRuntimeHandleWithFactoryResult(opts) {
8
+ const shell = opts.shell ?? new RuntimeShell.RuntimeShell();
9
+ let factoryResult;
10
+ const session = await shell.launch({
11
+ provider: opts.provider,
12
+ cwd: opts.cwd,
13
+ env: opts.env,
14
+ createBackend: (factoryOpts) => {
15
+ factoryResult = opts.createBackendResult(factoryOpts);
16
+ return factoryResult.backend;
17
+ }
18
+ });
19
+ if (factoryResult === void 0) {
20
+ throw new Error(`Runtime provider "${opts.provider}" did not create a backend result`);
21
+ }
22
+ return {
23
+ session,
24
+ factoryResult
25
+ };
26
+ }
27
+
28
+ const SESSION_LABEL_MAX_LENGTH = 60;
29
+ const TITLE_MAX_LENGTH = 80;
30
+ const BODY_MAX_LENGTH = 140;
31
+ function isRecord$1(value) {
32
+ return !!value && typeof value === "object" && !Array.isArray(value);
33
+ }
34
+ function normalizeText(value) {
35
+ if (typeof value !== "string") {
36
+ return null;
37
+ }
38
+ const normalized = value.replace(/\s+/g, " ").trim();
39
+ return normalized.length > 0 ? normalized : null;
40
+ }
41
+ function truncateText(value, maxLength) {
42
+ if (value.length <= maxLength) {
43
+ return value;
44
+ }
45
+ return `${value.slice(0, maxLength - 1).trimEnd()}\u2026`;
46
+ }
47
+ function toProviderKey(providerLabel) {
48
+ const normalized = normalizeText(providerLabel)?.toLowerCase();
49
+ if (!normalized) {
50
+ return "unknown";
51
+ }
52
+ if (normalized === "claude" || normalized === "claude code" || normalized === "cloud code") {
53
+ return "claude";
54
+ }
55
+ if (normalized === "codex") {
56
+ return "codex";
57
+ }
58
+ if (normalized === "gemini") {
59
+ return "gemini";
60
+ }
61
+ return normalized.replace(/\s+/g, "-");
62
+ }
63
+ function deriveNotificationProviderLabel(providerLabel) {
64
+ const normalized = normalizeText(providerLabel)?.toLowerCase();
65
+ if (!normalized) {
66
+ return "Agent";
67
+ }
68
+ if (normalized === "claude" || normalized === "claude code" || normalized === "cloud code") {
69
+ return "Claude";
70
+ }
71
+ if (normalized === "codex") {
72
+ return "Codex";
73
+ }
74
+ if (normalized === "gemini") {
75
+ return "Gemini";
76
+ }
77
+ return normalizeText(providerLabel) ?? "Agent";
78
+ }
79
+ function buildNotificationTitle(sessionLabel, providerLabel, actionLabel) {
80
+ const providerDisplayLabel = deriveNotificationProviderLabel(providerLabel);
81
+ const suffix = ` \xB7 ${providerDisplayLabel} \xB7 ${actionLabel}`;
82
+ const maxSessionLength = Math.max(12, TITLE_MAX_LENGTH - suffix.length);
83
+ return `${truncateText(sessionLabel, maxSessionLength)}${suffix}`;
84
+ }
85
+ function derivePathLabel(path) {
86
+ const normalized = normalizeText(path);
87
+ if (!normalized) {
88
+ return null;
89
+ }
90
+ const segments = normalized.split(/[\\/]+/).filter(Boolean);
91
+ return segments[segments.length - 1] ?? normalized;
92
+ }
93
+ function deriveHomeLabel(homeSlug) {
94
+ const normalized = normalizeText(homeSlug);
95
+ if (!normalized) {
96
+ return null;
97
+ }
98
+ return normalized.replace(/[_-]+/g, " ");
99
+ }
100
+ function deriveNotificationSessionLabel(metadata, providerLabel) {
101
+ const label = normalizeText(metadata?.name) ?? normalizeText(metadata?.summary?.text) ?? deriveHomeLabel(metadata?.happyOrg?.specialistHome?.homeSlug) ?? derivePathLabel(metadata?.path) ?? normalizeText(providerLabel) ?? "Session";
102
+ return truncateText(label, SESSION_LABEL_MAX_LENGTH);
103
+ }
104
+ function deriveNotificationSummary(candidates, fallback, sessionLabel) {
105
+ for (const candidate of candidates) {
106
+ const normalized = normalizeText(candidate);
107
+ if (!normalized) {
108
+ continue;
109
+ }
110
+ const truncated = truncateText(normalized, BODY_MAX_LENGTH);
111
+ if (truncated.toLowerCase() !== sessionLabel.toLowerCase()) {
112
+ return truncated;
113
+ }
114
+ }
115
+ return truncateText(fallback, BODY_MAX_LENGTH);
116
+ }
117
+ function cleanExtraData(extraData) {
118
+ return Object.fromEntries(
119
+ Object.entries(extraData).filter(([, value]) => {
120
+ if (value === null || value === void 0) {
121
+ return false;
122
+ }
123
+ if (typeof value === "string") {
124
+ return value.trim().length > 0;
125
+ }
126
+ return true;
127
+ })
128
+ );
129
+ }
130
+ function buildRouteData(opts) {
131
+ const taskContext = opts.metadata?.happyOrg?.taskContext ?? null;
132
+ const routeTaskId = opts.report?.taskId ?? taskContext?.taskId ?? null;
133
+ const routePositionId = opts.report?.positionId ?? taskContext?.positionId ?? null;
134
+ const routeSessionId = normalizeText(opts.sessionId);
135
+ const data = {
136
+ notificationKind: opts.notificationKind,
137
+ provider: toProviderKey(opts.providerLabel)
138
+ };
139
+ if (opts.routePreference === "session" && routeSessionId) {
140
+ data.sessionId = routeSessionId;
141
+ } else if (routeTaskId) {
142
+ data.taskId = routeTaskId;
143
+ } else if (routeSessionId) {
144
+ data.sessionId = routeSessionId;
145
+ } else if (routePositionId) {
146
+ data.positionId = routePositionId;
147
+ }
148
+ Object.assign(data, cleanExtraData({
149
+ contextTaskId: data.taskId ? null : routeTaskId,
150
+ contextPositionId: data.positionId ? null : routePositionId,
151
+ memberAgentId: opts.report?.memberAgentId ?? taskContext?.memberAgentId ?? null,
152
+ supervisorAgentId: opts.report?.supervisorAgentId ?? taskContext?.supervisorAgentId ?? null
153
+ }));
154
+ if (opts.extraData) {
155
+ Object.assign(data, cleanExtraData(opts.extraData));
156
+ }
157
+ return data;
158
+ }
159
+ function humanizeToolName(toolName) {
160
+ const normalized = normalizeText(toolName);
161
+ if (!normalized) {
162
+ return "continue";
163
+ }
164
+ const replacements = {
165
+ bash: "run a command",
166
+ execute: "run a command",
167
+ read: "read a file",
168
+ write: "write a file",
169
+ edit: "edit a file",
170
+ multiedit: "edit files",
171
+ patch: "apply a patch",
172
+ fetch: "fetch a page",
173
+ search: "search the web"
174
+ };
175
+ const replacement = replacements[normalized.toLowerCase()];
176
+ if (replacement) {
177
+ return replacement;
178
+ }
179
+ return normalized.replace(/[_-]+/g, " ");
180
+ }
181
+ function extractPermissionRequestPushContext(message) {
182
+ const payload = isRecord$1(message.payload) ? message.payload : null;
183
+ const toolName = normalizeText(payload?.toolName) ?? normalizeText(message.reason);
184
+ const payloadDescription = normalizeText(payload?.description);
185
+ const reasonDescription = normalizeText(message.reason);
186
+ let description = payloadDescription;
187
+ if (!description && reasonDescription && reasonDescription.toLowerCase() !== (toolName ?? "").toLowerCase()) {
188
+ description = reasonDescription;
189
+ }
190
+ if (description && toolName && description.toLowerCase() === toolName.toLowerCase()) {
191
+ description = null;
192
+ }
193
+ return {
194
+ requestId: message.id,
195
+ toolName,
196
+ description
197
+ };
198
+ }
199
+ function buildReadyPushNotification(opts) {
200
+ const sessionLabel = deriveNotificationSessionLabel(opts.metadata, opts.providerLabel);
201
+ const providerDisplayLabel = deriveNotificationProviderLabel(opts.providerLabel);
202
+ return {
203
+ title: buildNotificationTitle(sessionLabel, opts.providerLabel, "Ready"),
204
+ body: truncateText(`${providerDisplayLabel} is waiting for your next message`, BODY_MAX_LENGTH),
205
+ data: buildRouteData({
206
+ ...opts,
207
+ notificationKind: "ready",
208
+ routePreference: "session"
209
+ })
210
+ };
211
+ }
212
+ function buildPermissionPushNotification(opts) {
213
+ const sessionLabel = deriveNotificationSessionLabel(opts.metadata, opts.providerLabel);
214
+ const providerDisplayLabel = deriveNotificationProviderLabel(opts.providerLabel);
215
+ const fallback = `${providerDisplayLabel} needs your approval to ${humanizeToolName(opts.toolName)}`;
216
+ const body = deriveNotificationSummary([opts.description], fallback, sessionLabel);
217
+ return {
218
+ title: buildNotificationTitle(sessionLabel, opts.providerLabel, "Permission needed"),
219
+ body,
220
+ data: buildRouteData({
221
+ ...opts,
222
+ notificationKind: "permission_request",
223
+ routePreference: "session",
224
+ extraData: {
225
+ requestId: opts.requestId,
226
+ tool: opts.toolName ?? null,
227
+ ...opts.extraData
228
+ }
229
+ })
230
+ };
231
+ }
232
+ function buildTurnResultPushNotification(opts) {
233
+ const sessionLabel = deriveNotificationSessionLabel(opts.metadata, opts.providerLabel);
234
+ const providerDisplayLabel = deriveNotificationProviderLabel(opts.providerLabel);
235
+ const report = opts.report ?? null;
236
+ const explicitSummary = normalizeText(report?.summary) ?? normalizeText(opts.responseText);
237
+ if (!explicitSummary) {
238
+ return null;
239
+ }
240
+ const fallback = `${providerDisplayLabel} has a new result ready`;
241
+ const body = deriveNotificationSummary(
242
+ [
243
+ explicitSummary
244
+ ],
245
+ fallback,
246
+ sessionLabel
247
+ );
248
+ const action = report?.turnStatus === "task_complete" ? "Task complete" : "New result";
249
+ return {
250
+ title: buildNotificationTitle(sessionLabel, opts.providerLabel, action),
251
+ body,
252
+ data: buildRouteData({
253
+ ...opts,
254
+ report,
255
+ notificationKind: "turn_result",
256
+ routePreference: "session",
257
+ extraData: {
258
+ turnStatus: report?.turnStatus ?? "turn_update"
259
+ }
260
+ })
261
+ };
262
+ }
263
+
264
+ const DEFAULT_MAX_MESSAGES = 200;
265
+ const DEFAULT_MAX_CHARACTERS = 1e5;
266
+ const DEFAULT_MAX_MESSAGE_CHARACTERS = 8e3;
267
+ const TRUNCATION_PREFIX = "...\n";
268
+ class MessageBuffer {
269
+ messages = [];
270
+ listeners = [];
271
+ nextId = 1;
272
+ enabled;
273
+ maxMessages;
274
+ maxCharacters;
275
+ maxMessageCharacters;
276
+ constructor(options = {}) {
277
+ this.enabled = options.enabled ?? true;
278
+ this.maxMessages = Math.max(1, options.maxMessages ?? DEFAULT_MAX_MESSAGES);
279
+ this.maxCharacters = Math.max(1, options.maxCharacters ?? DEFAULT_MAX_CHARACTERS);
280
+ this.maxMessageCharacters = Math.max(1, options.maxMessageCharacters ?? DEFAULT_MAX_MESSAGE_CHARACTERS);
281
+ }
282
+ addMessage(content, type = "assistant") {
283
+ const id = `msg-${this.nextId++}`;
284
+ if (!this.enabled) {
285
+ return id;
286
+ }
287
+ const message = {
288
+ id,
289
+ timestamp: /* @__PURE__ */ new Date(),
290
+ content: this.normalizeContent(content),
291
+ type
292
+ };
293
+ this.messages.push(message);
294
+ this.trimMessages();
295
+ this.notifyListeners();
296
+ return message.id;
297
+ }
298
+ updateMessage(id, content, options = {}) {
299
+ if (!this.enabled) {
300
+ return false;
301
+ }
302
+ const index = this.messages.findIndex((message) => message.id === id);
303
+ if (index === -1) {
304
+ return false;
305
+ }
306
+ const normalizedContent = this.normalizeContent(content);
307
+ const previous = this.messages[index];
308
+ this.messages[index] = {
309
+ ...previous,
310
+ content: this.truncateContent(options.mode === "replace" ? normalizedContent : previous.content + normalizedContent)
311
+ };
312
+ this.trimMessages();
313
+ this.notifyListeners();
314
+ return true;
315
+ }
316
+ removeMessage(id) {
317
+ if (!this.enabled) {
318
+ return false;
319
+ }
320
+ const index = this.messages.findIndex((message) => message.id === id);
321
+ if (index === -1) {
322
+ return false;
323
+ }
324
+ this.messages.splice(index, 1);
325
+ this.notifyListeners();
326
+ return true;
327
+ }
328
+ /**
329
+ * Update the last message of a specific type by appending content to it
330
+ * Useful for streaming responses where deltas should accumulate in one message
331
+ */
332
+ updateLastMessage(contentDelta, type = "assistant") {
333
+ if (!this.enabled) {
334
+ return;
335
+ }
336
+ const normalizedDelta = this.normalizeContent(contentDelta);
337
+ for (let i = this.messages.length - 1; i >= 0; i--) {
338
+ if (this.messages[i].type === type) {
339
+ const oldMessage = this.messages[i];
340
+ const updatedMessage = {
341
+ ...oldMessage,
342
+ content: this.truncateContent(oldMessage.content + normalizedDelta)
343
+ };
344
+ this.messages[i] = updatedMessage;
345
+ this.trimMessages();
346
+ this.notifyListeners();
347
+ return;
348
+ }
349
+ }
350
+ this.addMessage(normalizedDelta, type);
351
+ }
352
+ /**
353
+ * Remove the last message of a specific type
354
+ * Useful for removing placeholder messages like "Thinking..." when actual response starts
355
+ */
356
+ removeLastMessage(type) {
357
+ if (!this.enabled) {
358
+ return false;
359
+ }
360
+ for (let i = this.messages.length - 1; i >= 0; i--) {
361
+ if (this.messages[i].type === type) {
362
+ this.messages.splice(i, 1);
363
+ this.notifyListeners();
364
+ return true;
365
+ }
366
+ }
367
+ return false;
368
+ }
369
+ getMessages() {
370
+ return [...this.messages];
371
+ }
372
+ clear() {
373
+ this.messages = [];
374
+ this.nextId = 1;
375
+ if (!this.enabled) {
376
+ return;
377
+ }
378
+ this.notifyListeners();
379
+ }
380
+ onUpdate(listener) {
381
+ if (!this.enabled) {
382
+ return () => {
383
+ };
384
+ }
385
+ this.listeners.push(listener);
386
+ return () => {
387
+ const index = this.listeners.indexOf(listener);
388
+ if (index > -1) {
389
+ this.listeners.splice(index, 1);
390
+ }
391
+ };
392
+ }
393
+ normalizeContent(content) {
394
+ return this.truncateContent(RuntimeShell.formatDisplayMessage(content));
395
+ }
396
+ truncateContent(content) {
397
+ if (content.length <= this.maxMessageCharacters) {
398
+ return content;
399
+ }
400
+ const tailLength = Math.max(0, this.maxMessageCharacters - TRUNCATION_PREFIX.length);
401
+ return `${TRUNCATION_PREFIX}${content.slice(content.length - tailLength)}`;
402
+ }
403
+ trimMessages() {
404
+ while (this.messages.length > this.maxMessages) {
405
+ this.messages.shift();
406
+ }
407
+ let totalCharacters = this.messages.reduce((sum, message) => sum + message.content.length, 0);
408
+ while (totalCharacters > this.maxCharacters && this.messages.length > 1) {
409
+ const removed = this.messages.shift();
410
+ if (removed) {
411
+ totalCharacters -= removed.content.length;
412
+ }
413
+ }
414
+ }
415
+ notifyListeners() {
416
+ const messages = this.getMessages();
417
+ this.listeners.forEach((listener) => listener(messages));
418
+ }
419
+ }
420
+
421
+ function isRecord(value) {
422
+ return typeof value === "object" && value !== null && !Array.isArray(value);
423
+ }
424
+ function hasClaudeCompatibilityShadow(value) {
425
+ if (!isRecord(value)) {
426
+ return false;
427
+ }
428
+ if (typeof value.happyCompatibilityShadow === "string" && value.happyCompatibilityShadow.trim()) {
429
+ return true;
430
+ }
431
+ const message = value.message;
432
+ if (!isRecord(message) || !Array.isArray(message.content)) {
433
+ return false;
434
+ }
435
+ return message.content.some((block) => isRecord(block) && typeof block.happyCompatibilityShadow === "string" && block.happyCompatibilityShadow.trim().length > 0);
436
+ }
437
+ function createSessionTranscriptInkRenderer(opts) {
438
+ const streamedAssistantMessages = /* @__PURE__ */ new Map();
439
+ const renderBufferedText = (text, type, streamMetadata) => {
440
+ const normalizedText = text.trim();
441
+ if (!normalizedText) {
442
+ return;
443
+ }
444
+ const streamKey = typeof streamMetadata?.messageId === "string" ? streamMetadata.messageId : typeof streamMetadata?.id === "string" ? streamMetadata.id : null;
445
+ const phase = typeof streamMetadata?.phase === "string" ? streamMetadata.phase : null;
446
+ const updateMode = streamMetadata?.mode === "replace" || phase === "commit" ? "replace" : "append";
447
+ if (phase === "abort") {
448
+ if (streamKey) {
449
+ const bufferedId = streamedAssistantMessages.get(streamKey);
450
+ if (bufferedId) {
451
+ opts.messageBuffer.removeMessage(bufferedId);
452
+ streamedAssistantMessages.delete(streamKey);
453
+ }
454
+ }
455
+ return;
456
+ }
457
+ if (!streamKey) {
458
+ opts.messageBuffer.addMessage(normalizedText, type);
459
+ return;
460
+ }
461
+ const existingBufferedId = streamedAssistantMessages.get(streamKey);
462
+ if (!existingBufferedId) {
463
+ const nextBufferedId = opts.messageBuffer.addMessage(normalizedText, type);
464
+ if (phase !== "commit") {
465
+ streamedAssistantMessages.set(streamKey, nextBufferedId);
466
+ }
467
+ return;
468
+ }
469
+ const updated = opts.messageBuffer.updateMessage(existingBufferedId, normalizedText, {
470
+ mode: updateMode
471
+ });
472
+ if (!updated) {
473
+ const nextBufferedId = opts.messageBuffer.addMessage(normalizedText, type);
474
+ if (phase !== "commit") {
475
+ streamedAssistantMessages.set(streamKey, nextBufferedId);
476
+ }
477
+ return;
478
+ }
479
+ if (phase === "commit") {
480
+ streamedAssistantMessages.delete(streamKey);
481
+ }
482
+ };
483
+ const renderStructuredAgentPayload = (payload) => {
484
+ if (!isRecord(payload) || typeof payload.type !== "string") {
485
+ return;
486
+ }
487
+ switch (payload.type) {
488
+ case "message":
489
+ case "reasoning": {
490
+ if (typeof payload.message !== "string") {
491
+ return;
492
+ }
493
+ renderBufferedText(
494
+ payload.message,
495
+ payload.type === "reasoning" ? "status" : "assistant",
496
+ payload
497
+ );
498
+ return;
499
+ }
500
+ case "thinking": {
501
+ if (typeof payload.text === "string" && payload.text.trim()) {
502
+ opts.messageBuffer.addMessage(`[Thinking] ${payload.text.trim()}`, "status");
503
+ }
504
+ return;
505
+ }
506
+ case "tool-call": {
507
+ const name = typeof payload.name === "string" ? payload.name : typeof payload.toolName === "string" ? payload.toolName : "tool";
508
+ const inputPreview = RuntimeShell.truncateDisplayMessage(
509
+ isRecord(payload.input) || Array.isArray(payload.input) ? JSON.stringify(payload.input) : payload.input,
510
+ 120
511
+ );
512
+ opts.messageBuffer.addMessage(
513
+ `Executing: ${name}${inputPreview ? ` ${inputPreview}` : ""}`,
514
+ "tool"
515
+ );
516
+ return;
517
+ }
518
+ case "tool-result":
519
+ case "tool-call-result": {
520
+ const resultValue = Object.prototype.hasOwnProperty.call(payload, "output") ? payload.output : payload.result;
521
+ const resultPreview = RuntimeShell.truncateDisplayMessage(resultValue, 200);
522
+ const prefix = payload.isError ? "Error:" : "Result:";
523
+ opts.messageBuffer.addMessage(
524
+ resultPreview ? `${prefix} ${resultPreview}` : "Tool completed",
525
+ payload.isError ? "status" : "result"
526
+ );
527
+ return;
528
+ }
529
+ case "file-edit":
530
+ case "fs-edit": {
531
+ const description = typeof payload.description === "string" ? payload.description : "File edit";
532
+ opts.messageBuffer.addMessage(`File edit: ${description}`, "tool");
533
+ return;
534
+ }
535
+ case "terminal-output": {
536
+ if (typeof payload.data !== "string") {
537
+ return;
538
+ }
539
+ const preview = sessionControl.renderTerminalOutputPreview(payload.data);
540
+ if (preview) {
541
+ opts.messageBuffer.addMessage(preview, "result");
542
+ }
543
+ return;
544
+ }
545
+ case "permission-request": {
546
+ const toolName = typeof payload.toolName === "string" ? payload.toolName : "tool";
547
+ opts.messageBuffer.addMessage(`Permission requested: ${toolName}`, "status");
548
+ return;
549
+ }
550
+ case "exec-approval-request": {
551
+ opts.messageBuffer.addMessage("Exec approval requested", "status");
552
+ return;
553
+ }
554
+ case "patch-apply-begin": {
555
+ opts.messageBuffer.addMessage("Applying patch...", "tool");
556
+ return;
557
+ }
558
+ case "patch-apply-end": {
559
+ const completionMessage = payload.success === false ? RuntimeShell.truncateDisplayMessage(payload.stderr, 200) || "Patch failed" : RuntimeShell.truncateDisplayMessage(payload.stdout, 200) || "Patch applied";
560
+ opts.messageBuffer.addMessage(completionMessage, payload.success === false ? "status" : "result");
561
+ return;
562
+ }
563
+ case "event": {
564
+ if (payload.name === "thinking" && isRecord(payload.payload) && typeof payload.payload.text === "string" && payload.payload.text.trim()) {
565
+ opts.messageBuffer.addMessage(`[Thinking] ${payload.payload.text.trim()}`, "status");
566
+ }
567
+ return;
568
+ }
569
+ case "task_started":
570
+ case "task_complete":
571
+ case "turn_aborted":
572
+ case "turn-report":
573
+ case "token_count":
574
+ case "token-count":
575
+ return;
576
+ default:
577
+ return;
578
+ }
579
+ };
580
+ const renderLegacyClaudeOutput = (payload) => {
581
+ if (!isRecord(payload) || hasClaudeCompatibilityShadow(payload)) {
582
+ return;
583
+ }
584
+ if (payload.type === "summary" && typeof payload.summary === "string" && payload.summary.trim()) {
585
+ opts.messageBuffer.addMessage(payload.summary.trim(), "result");
586
+ return;
587
+ }
588
+ if (payload.type !== "assistant") {
589
+ return;
590
+ }
591
+ const message = isRecord(payload.message) ? payload.message : null;
592
+ const content = message?.content;
593
+ if (typeof content === "string" && content.trim()) {
594
+ opts.messageBuffer.addMessage(content.trim(), "assistant");
595
+ return;
596
+ }
597
+ if (!Array.isArray(content)) {
598
+ return;
599
+ }
600
+ for (const block of content) {
601
+ if (!isRecord(block) || typeof block.type !== "string") {
602
+ continue;
603
+ }
604
+ if (block.type === "thinking" && typeof block.thinking === "string" && block.thinking.trim()) {
605
+ opts.messageBuffer.addMessage(`[Thinking] ${block.thinking.trim()}`, "status");
606
+ continue;
607
+ }
608
+ if (block.type === "text" && typeof block.text === "string" && block.text.trim()) {
609
+ opts.messageBuffer.addMessage(block.text.trim(), "assistant");
610
+ continue;
611
+ }
612
+ if (block.type === "tool_use") {
613
+ const toolName = typeof block.name === "string" ? block.name : "tool";
614
+ const inputPreview = RuntimeShell.truncateDisplayMessage(
615
+ isRecord(block.input) || Array.isArray(block.input) ? JSON.stringify(block.input) : block.input,
616
+ 120
617
+ );
618
+ opts.messageBuffer.addMessage(
619
+ `Executing: ${toolName}${inputPreview ? ` ${inputPreview}` : ""}`,
620
+ "tool"
621
+ );
622
+ }
623
+ }
624
+ };
625
+ const renderSessionEvent = (payload) => {
626
+ if (!isRecord(payload) || typeof payload.type !== "string") {
627
+ return;
628
+ }
629
+ switch (payload.type) {
630
+ case "message":
631
+ if (typeof payload.message === "string" && payload.message.trim()) {
632
+ opts.messageBuffer.addMessage(payload.message.trim(), "status");
633
+ }
634
+ return;
635
+ case "switch":
636
+ if (payload.mode === "local" || payload.mode === "remote") {
637
+ opts.messageBuffer.addMessage(`Mode switched to ${payload.mode}`, "status");
638
+ }
639
+ return;
640
+ case "permission-mode-changed":
641
+ if (typeof payload.mode === "string" && payload.mode.trim()) {
642
+ opts.messageBuffer.addMessage(`Permission mode: ${payload.mode}`, "status");
643
+ }
644
+ return;
645
+ case "ready":
646
+ return;
647
+ default:
648
+ return;
649
+ }
650
+ };
651
+ return (transcriptMessage) => {
652
+ if (transcriptMessage.message.role === "user") {
653
+ const text = transcriptMessage.message.content.text.trim();
654
+ if (text) {
655
+ opts.messageBuffer.addMessage(text, "user");
656
+ }
657
+ return;
658
+ }
659
+ switch (transcriptMessage.message.content.type) {
660
+ case "output":
661
+ renderLegacyClaudeOutput(transcriptMessage.message.content.data);
662
+ return;
663
+ case "codex":
664
+ renderStructuredAgentPayload(transcriptMessage.message.content.data);
665
+ return;
666
+ case "acp":
667
+ renderStructuredAgentPayload(transcriptMessage.message.content.data);
668
+ return;
669
+ case "event":
670
+ renderSessionEvent(transcriptMessage.message.content.data);
671
+ return;
672
+ default:
673
+ opts.messageBuffer.addMessage(RuntimeShell.formatDisplayMessage(transcriptMessage.message), "status");
674
+ }
675
+ };
676
+ }
677
+
678
+ let ConversationHistory$1 = class ConversationHistory {
679
+ messages = [];
680
+ maxMessages;
681
+ maxCharacters;
682
+ constructor(options = {}) {
683
+ this.maxMessages = options.maxMessages ?? 20;
684
+ this.maxCharacters = options.maxCharacters ?? 5e4;
685
+ }
686
+ isDuplicate(role, content) {
687
+ if (this.messages.length === 0) {
688
+ return false;
689
+ }
690
+ for (let index = this.messages.length - 1; index >= 0; index -= 1) {
691
+ const message = this.messages[index];
692
+ if (message.role !== role) {
693
+ continue;
694
+ }
695
+ const normalizedIncoming = content.trim().replace(/\s+/g, " ");
696
+ const normalizedExisting = message.content.replace(/\s+/g, " ");
697
+ return normalizedIncoming === normalizedExisting;
698
+ }
699
+ return false;
700
+ }
701
+ addUserMessage(content) {
702
+ this.addMessage("user", content);
703
+ }
704
+ addAssistantMessage(content) {
705
+ this.addMessage("assistant", content);
706
+ }
707
+ hasHistory() {
708
+ return this.messages.length > 0;
709
+ }
710
+ size() {
711
+ return this.messages.length;
712
+ }
713
+ clear() {
714
+ this.messages = [];
715
+ persistence.logger.debug("[ConversationHistory] History cleared");
716
+ }
717
+ getContextForNewSession(prefixMessage = "Continue from the prior session using the conversation below as context.") {
718
+ if (this.messages.length === 0) {
719
+ return "";
720
+ }
721
+ const formattedMessages = this.messages.map((message) => {
722
+ const role = message.role === "user" ? "User" : "Assistant";
723
+ const content = message.content.length > 2e3 ? `${message.content.slice(0, 2e3)}... [truncated]` : message.content;
724
+ return `${role}: ${content}`;
725
+ }).join("\n\n");
726
+ return [
727
+ "[PREVIOUS CONVERSATION CONTEXT]",
728
+ prefixMessage,
729
+ "",
730
+ formattedMessages,
731
+ "",
732
+ "[END OF PREVIOUS CONTEXT]",
733
+ ""
734
+ ].join("\n");
735
+ }
736
+ getSummary() {
737
+ const totalChars = this.messages.reduce((sum, message) => sum + message.content.length, 0);
738
+ const userCount = this.messages.filter((message) => message.role === "user").length;
739
+ const assistantCount = this.messages.filter((message) => message.role === "assistant").length;
740
+ return `${this.messages.length} messages (${userCount} user, ${assistantCount} assistant), ${totalChars} chars`;
741
+ }
742
+ addMessage(role, content) {
743
+ const trimmedContent = content.trim();
744
+ if (!trimmedContent) {
745
+ return;
746
+ }
747
+ if (this.isDuplicate(role, trimmedContent)) {
748
+ persistence.logger.debug(`[ConversationHistory] Skipping duplicate ${role} message (${trimmedContent.length} chars)`);
749
+ return;
750
+ }
751
+ this.messages.push({
752
+ role,
753
+ content: trimmedContent,
754
+ timestamp: Date.now()
755
+ });
756
+ this.trimHistory();
757
+ persistence.logger.debug(`[ConversationHistory] Added ${role} message (${trimmedContent.length} chars), total: ${this.messages.length}`);
758
+ }
759
+ trimHistory() {
760
+ while (this.messages.length > this.maxMessages) {
761
+ this.messages.shift();
762
+ }
763
+ let totalChars = this.messages.reduce((sum, message) => sum + message.content.length, 0);
764
+ while (totalChars > this.maxCharacters && this.messages.length > 1) {
765
+ const removed = this.messages.shift();
766
+ if (removed) {
767
+ totalChars -= removed.content.length;
768
+ }
769
+ }
770
+ }
771
+ };
772
+
773
+ exports.ConversationHistory = ConversationHistory$1;
774
+ exports.MessageBuffer = MessageBuffer;
775
+ exports.buildPermissionPushNotification = buildPermissionPushNotification;
776
+ exports.buildReadyPushNotification = buildReadyPushNotification;
777
+ exports.buildTurnResultPushNotification = buildTurnResultPushNotification;
778
+ exports.createSessionTranscriptInkRenderer = createSessionTranscriptInkRenderer;
779
+ exports.extractPermissionRequestPushContext = extractPermissionRequestPushContext;
780
+ exports.launchRuntimeHandleWithFactoryResult = launchRuntimeHandleWithFactoryResult;