happy-imou-cloud 2.0.12 → 2.0.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.
Files changed (35) hide show
  1. package/bin/happy-cloud.mjs +1 -1
  2. package/dist/ConversationHistory-V3VLmjJf.cjs +868 -0
  3. package/dist/ConversationHistory-_ciJNIgH.mjs +856 -0
  4. package/dist/{api-BxXBKBUy.mjs → api-D1meoL-9.mjs} +2 -2
  5. package/dist/{api-B4g8VLUn.cjs → api-DH5-IqeM.cjs} +2 -2
  6. package/dist/{command-CHiLfBa4.mjs → command-CMvWClny.mjs} +3 -3
  7. package/dist/{command-DVt_YmE6.cjs → command-Ch8Dgidj.cjs} +3 -3
  8. package/dist/createKeepAliveController-C5cQlDRr.mjs +51 -0
  9. package/dist/createKeepAliveController-DO8H6d5E.cjs +54 -0
  10. package/dist/{index-CWom7mSf.cjs → index-CryJfCh5.cjs} +10 -11
  11. package/dist/{index-DaAkW0VN.mjs → index-Cxrx9m5D.mjs} +9 -9
  12. package/dist/index.cjs +3 -3
  13. package/dist/index.mjs +3 -3
  14. package/dist/lib.cjs +1 -1
  15. package/dist/lib.mjs +1 -1
  16. package/dist/{persistence-8pNEvzaq.mjs → persistence-9Iu0wGNM.mjs} +1 -1
  17. package/dist/{persistence-DScOANDE.cjs → persistence-Bl3FYvwd.cjs} +1 -1
  18. package/dist/{registerKillSessionHandler-CNNguWyD.mjs → registerKillSessionHandler-BElGmD1E.mjs} +5 -541
  19. package/dist/{registerKillSessionHandler-Dr1inhTc.cjs → registerKillSessionHandler-BjkY-oUn.cjs} +4 -549
  20. package/dist/{runClaude-h-8llTrI.cjs → runClaude-CDZxAF3l.cjs} +129 -630
  21. package/dist/{runClaude-BcvOkIwh.mjs → runClaude-D7dF4RDM.mjs} +126 -627
  22. package/dist/{runCodex-CA58KUHf.cjs → runCodex-Cik8VzFs.cjs} +224 -17
  23. package/dist/{runCodex-ClJUgipy.mjs → runCodex-DnGz1XES.mjs} +213 -6
  24. package/dist/{runGemini-dAr7Gcn8.mjs → runGemini-B8tXMHeL.mjs} +5 -5
  25. package/dist/{runGemini-IFHhFMSU.cjs → runGemini-BM2BQ4I7.cjs} +13 -13
  26. package/package.json +9 -9
  27. package/scripts/build.mjs +66 -66
  28. package/scripts/devtools/README.md +9 -9
  29. package/scripts/e2e/fake-codex-acp-agent.mjs +139 -139
  30. package/scripts/e2e/local-server-session-roundtrip.mjs +1063 -1063
  31. package/scripts/release-smoke.mjs +202 -202
  32. package/dist/BaseReasoningProcessor-BrKUKAOr.cjs +0 -323
  33. package/dist/BaseReasoningProcessor-DrHf5B98.mjs +0 -320
  34. package/dist/ProviderSelectionHandler-BCDvmifJ.cjs +0 -265
  35. package/dist/ProviderSelectionHandler-BuZarTDc.mjs +0 -261
@@ -1,9 +1,9 @@
1
1
  'use strict';
2
2
 
3
3
  var node_crypto = require('node:crypto');
4
- var api = require('./api-B4g8VLUn.cjs');
5
- var registerKillSessionHandler = require('./registerKillSessionHandler-Dr1inhTc.cjs');
6
- var index = require('./index-CWom7mSf.cjs');
4
+ var api = require('./api-DH5-IqeM.cjs');
5
+ var registerKillSessionHandler = require('./registerKillSessionHandler-BjkY-oUn.cjs');
6
+ var index = require('./index-CryJfCh5.cjs');
7
7
  require('cross-spawn');
8
8
  require('@agentclientprotocol/sdk');
9
9
  require('ps-list');
@@ -14,7 +14,7 @@ require('child_process');
14
14
  require('node:fs');
15
15
  require('node:path');
16
16
  require('node:os');
17
- require('./persistence-DScOANDE.cjs');
17
+ require('./persistence-Bl3FYvwd.cjs');
18
18
  require('node:fs/promises');
19
19
  require('fs/promises');
20
20
  require('crypto');
@@ -26,8 +26,8 @@ require('tweetnacl');
26
26
  require('open');
27
27
  var React = require('react');
28
28
  var ink = require('ink');
29
- var ProviderSelectionHandler = require('./ProviderSelectionHandler-BCDvmifJ.cjs');
30
- var BaseReasoningProcessor = require('./BaseReasoningProcessor-BrKUKAOr.cjs');
29
+ var createKeepAliveController = require('./createKeepAliveController-DO8H6d5E.cjs');
30
+ var ConversationHistory = require('./ConversationHistory-V3VLmjJf.cjs');
31
31
  require('socket.io-client');
32
32
  require('zod');
33
33
  require('expo-server-sdk');
@@ -146,7 +146,7 @@ class CodexSession {
146
146
  this.queue = opts.messageQueue;
147
147
  this.codexArgs = opts.codexArgs;
148
148
  this.onModeChangeCallback = opts.onModeChange;
149
- this.keepAliveController = ProviderSelectionHandler.createKeepAliveController({
149
+ this.keepAliveController = createKeepAliveController.createKeepAliveController({
150
150
  initialMode: this.mode,
151
151
  initialThinking: this.thinking,
152
152
  send: (thinking, mode) => {
@@ -316,7 +316,7 @@ const CodexDisplay = ({ messageBuffer, logPath, onExit, title }) => {
316
316
  ));
317
317
  };
318
318
 
319
- class CodexPermissionHandler extends registerKillSessionHandler.BasePermissionHandler {
319
+ class CodexPermissionHandler extends ConversationHistory.BasePermissionHandler {
320
320
  constructor(session) {
321
321
  super(session);
322
322
  }
@@ -335,13 +335,220 @@ class CodexPermissionHandler extends registerKillSessionHandler.BasePermissionHa
335
335
  }
336
336
  }
337
337
 
338
- class CodexSelectionHandler extends ProviderSelectionHandler.ProviderSelectionHandler {
338
+ class ProviderSelectionHandler {
339
+ pendingRequests = /* @__PURE__ */ new Map();
340
+ session;
341
+ providerLabel;
342
+ constructor(session, providerLabel) {
343
+ this.session = session;
344
+ this.providerLabel = providerLabel;
345
+ this.setupRpcHandler();
346
+ }
347
+ updateSession(newSession) {
348
+ this.session = newSession;
349
+ this.setupRpcHandler();
350
+ }
351
+ async requestSelection(request) {
352
+ return new Promise((resolve, reject) => {
353
+ const pending = {
354
+ resolve,
355
+ reject,
356
+ request
357
+ };
358
+ pending.timeoutHandle = setTimeout(() => {
359
+ this.handleSelectionTimeout(request.id, pending);
360
+ }, ConversationHistory.getPendingInteractionTimeoutMs());
361
+ this.pendingRequests.set(request.id, pending);
362
+ this.session.updateAgentState((currentState) => ({
363
+ ...currentState,
364
+ requests: {
365
+ ...currentState.requests,
366
+ [request.id]: {
367
+ tool: "AskUserQuestion",
368
+ arguments: {
369
+ requestKind: "selection",
370
+ questions: [
371
+ {
372
+ header: this.providerLabel,
373
+ question: request.message,
374
+ multiSelect: false,
375
+ options: request.options.map((option) => ({
376
+ label: option.label,
377
+ description: option.description || option.optionId,
378
+ optionId: option.optionId
379
+ }))
380
+ }
381
+ ]
382
+ },
383
+ createdAt: Date.now(),
384
+ requestKind: "selection",
385
+ options: request.options,
386
+ defaultOptionId: request.defaultOptionId
387
+ }
388
+ }
389
+ }));
390
+ api.logger.debug(`[${this.providerLabel}] Selection request sent (${request.id}) with ${request.options.length} options`);
391
+ });
392
+ }
393
+ hasPendingRequests() {
394
+ return this.pendingRequests.size > 0;
395
+ }
396
+ supersedePendingRequests(reason = ConversationHistory.INTERACTION_SUPERSEDED_ERROR) {
397
+ const pendingSnapshot = Array.from(this.pendingRequests.entries());
398
+ if (pendingSnapshot.length === 0) {
399
+ return 0;
400
+ }
401
+ this.pendingRequests.clear();
402
+ const completedAt = Date.now();
403
+ for (const [, pending] of pendingSnapshot) {
404
+ this.clearPendingRequestTimeout(pending);
405
+ pending.reject(new Error(reason));
406
+ }
407
+ this.session.updateAgentState((currentState) => {
408
+ const requests = { ...currentState.requests || {} };
409
+ const completedRequests = { ...currentState.completedRequests || {} };
410
+ for (const [id, request] of Object.entries(requests)) {
411
+ if (request.requestKind !== "selection") {
412
+ continue;
413
+ }
414
+ completedRequests[id] = {
415
+ ...request,
416
+ completedAt,
417
+ status: "canceled",
418
+ reason,
419
+ requestKind: "selection"
420
+ };
421
+ delete requests[id];
422
+ }
423
+ return {
424
+ ...currentState,
425
+ requests,
426
+ completedRequests
427
+ };
428
+ });
429
+ api.logger.debug(`[${this.providerLabel}] Superseded ${pendingSnapshot.length} pending selection request(s)`);
430
+ return pendingSnapshot.length;
431
+ }
432
+ reset(reason = "Session reset") {
433
+ const pendingSnapshot = Array.from(this.pendingRequests.entries());
434
+ this.pendingRequests.clear();
435
+ for (const [, pending] of pendingSnapshot) {
436
+ this.clearPendingRequestTimeout(pending);
437
+ pending.reject(new Error(reason));
438
+ }
439
+ this.session.updateAgentState((currentState) => {
440
+ const requests = { ...currentState.requests || {} };
441
+ const completedRequests = { ...currentState.completedRequests || {} };
442
+ for (const [id, request] of Object.entries(requests)) {
443
+ if (request.requestKind !== "selection") {
444
+ continue;
445
+ }
446
+ completedRequests[id] = {
447
+ ...request,
448
+ completedAt: Date.now(),
449
+ status: "canceled",
450
+ reason,
451
+ requestKind: "selection"
452
+ };
453
+ delete requests[id];
454
+ }
455
+ return {
456
+ ...currentState,
457
+ requests,
458
+ completedRequests
459
+ };
460
+ });
461
+ }
462
+ setupRpcHandler() {
463
+ this.session.rpcHandlerManager.registerHandler("selection", async (response) => {
464
+ const pending = this.pendingRequests.get(response.id);
465
+ if (!pending) {
466
+ api.logger.debug(`[${this.providerLabel}] Selection request not found or already resolved`);
467
+ return;
468
+ }
469
+ this.pendingRequests.delete(response.id);
470
+ this.clearPendingRequestTimeout(pending);
471
+ pending.resolve(response);
472
+ this.session.updateAgentState((currentState) => {
473
+ const request = currentState.requests?.[response.id];
474
+ if (!request) {
475
+ return currentState;
476
+ }
477
+ const { [response.id]: _, ...remainingRequests } = currentState.requests || {};
478
+ return {
479
+ ...currentState,
480
+ requests: remainingRequests,
481
+ completedRequests: {
482
+ ...currentState.completedRequests,
483
+ [response.id]: {
484
+ ...request,
485
+ completedAt: Date.now(),
486
+ status: "approved",
487
+ requestKind: "selection",
488
+ selectedOptionId: response.optionId
489
+ }
490
+ }
491
+ };
492
+ });
493
+ });
494
+ }
495
+ clearPendingRequestTimeout(pending) {
496
+ if (pending?.timeoutHandle) {
497
+ clearTimeout(pending.timeoutHandle);
498
+ pending.timeoutHandle = void 0;
499
+ }
500
+ }
501
+ handleSelectionTimeout(requestId, pending) {
502
+ const active = this.pendingRequests.get(requestId);
503
+ if (!active || active !== pending) {
504
+ return;
505
+ }
506
+ this.pendingRequests.delete(requestId);
507
+ this.clearPendingRequestTimeout(active);
508
+ active.reject(new Error(ConversationHistory.INTERACTION_TIMED_OUT_ERROR));
509
+ this.session.updateAgentState((currentState) => {
510
+ const request = currentState.requests?.[requestId] || {
511
+ tool: "AskUserQuestion",
512
+ arguments: {
513
+ requestKind: "selection",
514
+ questions: []
515
+ },
516
+ createdAt: Date.now(),
517
+ requestKind: "selection",
518
+ options: active.request.options,
519
+ defaultOptionId: active.request.defaultOptionId
520
+ };
521
+ const { [requestId]: _, ...remainingRequests } = currentState.requests || {};
522
+ return {
523
+ ...currentState,
524
+ requests: remainingRequests,
525
+ completedRequests: {
526
+ ...currentState.completedRequests,
527
+ [requestId]: {
528
+ ...request,
529
+ completedAt: Date.now(),
530
+ status: "canceled",
531
+ reason: ConversationHistory.INTERACTION_TIMED_OUT_ERROR,
532
+ requestKind: "selection"
533
+ }
534
+ }
535
+ };
536
+ });
537
+ this.session.sendSessionEvent({
538
+ type: "message",
539
+ message: "Pending interaction timed out waiting for a response. Send a new message to continue."
540
+ });
541
+ api.logger.debug(`[${this.providerLabel}] Selection request timed out (${requestId})`);
542
+ }
543
+ }
544
+
545
+ class CodexSelectionHandler extends ProviderSelectionHandler {
339
546
  constructor(session) {
340
547
  super(session, "Codex");
341
548
  }
342
549
  }
343
550
 
344
- class ReasoningProcessor extends BaseReasoningProcessor.BaseReasoningProcessor {
551
+ class ReasoningProcessor extends ConversationHistory.BaseReasoningProcessor {
345
552
  getToolName() {
346
553
  return "CodexReasoning";
347
554
  }
@@ -492,7 +699,7 @@ async function codexRemoteLauncher(session) {
492
699
  let currentThinkingMessageId = null;
493
700
  const permissionHandler = new CodexPermissionHandler(session.client);
494
701
  const selectionHandler = new CodexSelectionHandler(session.client);
495
- const conversationHistory = new registerKillSessionHandler.ConversationHistory({ maxMessages: 20, maxCharacters: 5e4 });
702
+ const conversationHistory = new ConversationHistory.ConversationHistory({ maxMessages: 20, maxCharacters: 5e4 });
496
703
  const reasoningProcessor = new ReasoningProcessor((message) => {
497
704
  session.runtimeSession.sendCodexMessage(message);
498
705
  });
@@ -586,7 +793,7 @@ async function codexRemoteLauncher(session) {
586
793
  };
587
794
  const setupRuntimeMessageHandler = (activeRuntimeHandle) => {
588
795
  const forwardAgentMessage = (agentMessage) => {
589
- registerKillSessionHandler.forwardAgentMessageToProviderSession(agentMessage, {
796
+ ConversationHistory.forwardAgentMessageToProviderSession(agentMessage, {
590
797
  provider: "codex",
591
798
  send: (body) => session.runtimeSession.sendCodexMessage(body),
592
799
  toolResultType: "tool-call-result"
@@ -652,7 +859,7 @@ async function codexRemoteLauncher(session) {
652
859
  return;
653
860
  }
654
861
  case "tool-result": {
655
- const isError = registerKillSessionHandler.inferToolResultError(msg.result);
862
+ const isError = ConversationHistory.inferToolResultError(msg.result);
656
863
  const resultText = index.truncateDisplayMessage(msg.result, 200) || (isError ? "Unknown error" : "");
657
864
  messageBuffer.addMessage(
658
865
  `${isError ? "Error:" : "Result:"} ${resultText}`.trim(),
@@ -739,7 +946,7 @@ async function codexRemoteLauncher(session) {
739
946
  if (!validation.ok) {
740
947
  throw new Error(validation.errorMessage);
741
948
  }
742
- const { session: nextRuntimeHandle } = await registerKillSessionHandler.launchRuntimeHandleWithFactoryResult({
949
+ const { session: nextRuntimeHandle } = await ConversationHistory.launchRuntimeHandleWithFactoryResult({
743
950
  provider: "codex",
744
951
  cwd: session.path,
745
952
  createBackendResult: (opts) => index.createCodexBackend({
@@ -874,7 +1081,7 @@ async function codexRemoteLauncher(session) {
874
1081
  }
875
1082
  conversationHistory.addUserMessage(message.message);
876
1083
  await activeRuntimeHandle.sendPrompt(promptToSend);
877
- await registerKillSessionHandler.waitForResponseCompleteWithAbort(activeRuntimeHandle.backend, turnSignal);
1084
+ await ConversationHistory.waitForResponseCompleteWithAbort(activeRuntimeHandle.backend, turnSignal);
878
1085
  reasoningProcessor.completeCurrent();
879
1086
  shouldCommitAccumulatedResponse = true;
880
1087
  shouldInjectHistoryOnNextSession = false;
@@ -959,7 +1166,7 @@ async function codexLoop(opts) {
959
1166
  await codexRemoteLauncher(opts.session);
960
1167
  return { type: "exit", value: 0 };
961
1168
  };
962
- return await ProviderSelectionHandler.runModeLoop({
1169
+ return await createKeepAliveController.runModeLoop({
963
1170
  startingMode: displayMode,
964
1171
  notifyInitialMode: true,
965
1172
  onModeChange: async (mode) => {
@@ -1025,7 +1232,7 @@ async function runCodex(opts) {
1025
1232
  }
1026
1233
  let sessionClient;
1027
1234
  let codexSession = null;
1028
- const { metadata, session: initialSession, reconnectionHandle } = await BaseReasoningProcessor.bootstrapManagedProviderSession({
1235
+ const { metadata, session: initialSession, reconnectionHandle } = await ConversationHistory.bootstrapManagedProviderSession({
1029
1236
  api: api$1,
1030
1237
  sessionTag,
1031
1238
  flavor: "codex",
@@ -1,7 +1,7 @@
1
1
  import { randomUUID } from 'node:crypto';
2
- import { l as logger, b as connectionState, A as ApiClient } from './api-BxXBKBUy.mjs';
3
- import { B as BasePermissionHandler, h as hashObject, d as MessageBuffer, C as ConversationHistory$1, w as waitForResponseCompleteWithAbort, r as registerKillSessionHandler, l as launchRuntimeHandleWithFactoryResult, i as inferToolResultError, j as forwardAgentMessageToProviderSession, f as closeProviderSession, e as ensureManagedProviderMachine, M as MissingMachineIdError, b as MessageQueue2, s as syncControlledByUserState } from './registerKillSessionHandler-CNNguWyD.mjs';
4
- import { f as formatDisplayMessage, v as validateCodexAcpSpawn, d as createCodexBackend, t as truncateDisplayMessage, b as stopCaffeinate } from './index-DaAkW0VN.mjs';
2
+ import { l as logger, b as connectionState, A as ApiClient } from './api-D1meoL-9.mjs';
3
+ import { h as hashObject, b as MessageBuffer, r as registerKillSessionHandler, c as closeProviderSession, e as ensureManagedProviderMachine, M as MissingMachineIdError, a as MessageQueue2, s as syncControlledByUserState } from './registerKillSessionHandler-BElGmD1E.mjs';
4
+ import { f as formatDisplayMessage, v as validateCodexAcpSpawn, d as createCodexBackend, t as truncateDisplayMessage, b as stopCaffeinate } from './index-Cxrx9m5D.mjs';
5
5
  import 'cross-spawn';
6
6
  import '@agentclientprotocol/sdk';
7
7
  import 'ps-list';
@@ -12,7 +12,7 @@ import 'child_process';
12
12
  import 'node:fs';
13
13
  import 'node:path';
14
14
  import 'node:os';
15
- import './persistence-8pNEvzaq.mjs';
15
+ import './persistence-9Iu0wGNM.mjs';
16
16
  import 'node:fs/promises';
17
17
  import 'fs/promises';
18
18
  import 'crypto';
@@ -24,8 +24,8 @@ import 'tweetnacl';
24
24
  import 'open';
25
25
  import React, { useState, useRef, useEffect, useCallback } from 'react';
26
26
  import { useStdout, useInput, Box, Text, render } from 'ink';
27
- import { c as createKeepAliveController, P as ProviderSelectionHandler, r as runModeLoop } from './ProviderSelectionHandler-BuZarTDc.mjs';
28
- import { B as BaseReasoningProcessor, b as bootstrapManagedProviderSession } from './BaseReasoningProcessor-DrHf5B98.mjs';
27
+ import { c as createKeepAliveController, r as runModeLoop } from './createKeepAliveController-C5cQlDRr.mjs';
28
+ import { B as BasePermissionHandler, g as getPendingInteractionTimeoutMs, I as INTERACTION_SUPERSEDED_ERROR, c as INTERACTION_TIMED_OUT_ERROR, a as BaseReasoningProcessor, C as ConversationHistory$1, w as waitForResponseCompleteWithAbort, l as launchRuntimeHandleWithFactoryResult, i as inferToolResultError, f as forwardAgentMessageToProviderSession, b as bootstrapManagedProviderSession } from './ConversationHistory-_ciJNIgH.mjs';
29
29
  import 'socket.io-client';
30
30
  import 'zod';
31
31
  import 'expo-server-sdk';
@@ -333,6 +333,213 @@ class CodexPermissionHandler extends BasePermissionHandler {
333
333
  }
334
334
  }
335
335
 
336
+ class ProviderSelectionHandler {
337
+ pendingRequests = /* @__PURE__ */ new Map();
338
+ session;
339
+ providerLabel;
340
+ constructor(session, providerLabel) {
341
+ this.session = session;
342
+ this.providerLabel = providerLabel;
343
+ this.setupRpcHandler();
344
+ }
345
+ updateSession(newSession) {
346
+ this.session = newSession;
347
+ this.setupRpcHandler();
348
+ }
349
+ async requestSelection(request) {
350
+ return new Promise((resolve, reject) => {
351
+ const pending = {
352
+ resolve,
353
+ reject,
354
+ request
355
+ };
356
+ pending.timeoutHandle = setTimeout(() => {
357
+ this.handleSelectionTimeout(request.id, pending);
358
+ }, getPendingInteractionTimeoutMs());
359
+ this.pendingRequests.set(request.id, pending);
360
+ this.session.updateAgentState((currentState) => ({
361
+ ...currentState,
362
+ requests: {
363
+ ...currentState.requests,
364
+ [request.id]: {
365
+ tool: "AskUserQuestion",
366
+ arguments: {
367
+ requestKind: "selection",
368
+ questions: [
369
+ {
370
+ header: this.providerLabel,
371
+ question: request.message,
372
+ multiSelect: false,
373
+ options: request.options.map((option) => ({
374
+ label: option.label,
375
+ description: option.description || option.optionId,
376
+ optionId: option.optionId
377
+ }))
378
+ }
379
+ ]
380
+ },
381
+ createdAt: Date.now(),
382
+ requestKind: "selection",
383
+ options: request.options,
384
+ defaultOptionId: request.defaultOptionId
385
+ }
386
+ }
387
+ }));
388
+ logger.debug(`[${this.providerLabel}] Selection request sent (${request.id}) with ${request.options.length} options`);
389
+ });
390
+ }
391
+ hasPendingRequests() {
392
+ return this.pendingRequests.size > 0;
393
+ }
394
+ supersedePendingRequests(reason = INTERACTION_SUPERSEDED_ERROR) {
395
+ const pendingSnapshot = Array.from(this.pendingRequests.entries());
396
+ if (pendingSnapshot.length === 0) {
397
+ return 0;
398
+ }
399
+ this.pendingRequests.clear();
400
+ const completedAt = Date.now();
401
+ for (const [, pending] of pendingSnapshot) {
402
+ this.clearPendingRequestTimeout(pending);
403
+ pending.reject(new Error(reason));
404
+ }
405
+ this.session.updateAgentState((currentState) => {
406
+ const requests = { ...currentState.requests || {} };
407
+ const completedRequests = { ...currentState.completedRequests || {} };
408
+ for (const [id, request] of Object.entries(requests)) {
409
+ if (request.requestKind !== "selection") {
410
+ continue;
411
+ }
412
+ completedRequests[id] = {
413
+ ...request,
414
+ completedAt,
415
+ status: "canceled",
416
+ reason,
417
+ requestKind: "selection"
418
+ };
419
+ delete requests[id];
420
+ }
421
+ return {
422
+ ...currentState,
423
+ requests,
424
+ completedRequests
425
+ };
426
+ });
427
+ logger.debug(`[${this.providerLabel}] Superseded ${pendingSnapshot.length} pending selection request(s)`);
428
+ return pendingSnapshot.length;
429
+ }
430
+ reset(reason = "Session reset") {
431
+ const pendingSnapshot = Array.from(this.pendingRequests.entries());
432
+ this.pendingRequests.clear();
433
+ for (const [, pending] of pendingSnapshot) {
434
+ this.clearPendingRequestTimeout(pending);
435
+ pending.reject(new Error(reason));
436
+ }
437
+ this.session.updateAgentState((currentState) => {
438
+ const requests = { ...currentState.requests || {} };
439
+ const completedRequests = { ...currentState.completedRequests || {} };
440
+ for (const [id, request] of Object.entries(requests)) {
441
+ if (request.requestKind !== "selection") {
442
+ continue;
443
+ }
444
+ completedRequests[id] = {
445
+ ...request,
446
+ completedAt: Date.now(),
447
+ status: "canceled",
448
+ reason,
449
+ requestKind: "selection"
450
+ };
451
+ delete requests[id];
452
+ }
453
+ return {
454
+ ...currentState,
455
+ requests,
456
+ completedRequests
457
+ };
458
+ });
459
+ }
460
+ setupRpcHandler() {
461
+ this.session.rpcHandlerManager.registerHandler("selection", async (response) => {
462
+ const pending = this.pendingRequests.get(response.id);
463
+ if (!pending) {
464
+ logger.debug(`[${this.providerLabel}] Selection request not found or already resolved`);
465
+ return;
466
+ }
467
+ this.pendingRequests.delete(response.id);
468
+ this.clearPendingRequestTimeout(pending);
469
+ pending.resolve(response);
470
+ this.session.updateAgentState((currentState) => {
471
+ const request = currentState.requests?.[response.id];
472
+ if (!request) {
473
+ return currentState;
474
+ }
475
+ const { [response.id]: _, ...remainingRequests } = currentState.requests || {};
476
+ return {
477
+ ...currentState,
478
+ requests: remainingRequests,
479
+ completedRequests: {
480
+ ...currentState.completedRequests,
481
+ [response.id]: {
482
+ ...request,
483
+ completedAt: Date.now(),
484
+ status: "approved",
485
+ requestKind: "selection",
486
+ selectedOptionId: response.optionId
487
+ }
488
+ }
489
+ };
490
+ });
491
+ });
492
+ }
493
+ clearPendingRequestTimeout(pending) {
494
+ if (pending?.timeoutHandle) {
495
+ clearTimeout(pending.timeoutHandle);
496
+ pending.timeoutHandle = void 0;
497
+ }
498
+ }
499
+ handleSelectionTimeout(requestId, pending) {
500
+ const active = this.pendingRequests.get(requestId);
501
+ if (!active || active !== pending) {
502
+ return;
503
+ }
504
+ this.pendingRequests.delete(requestId);
505
+ this.clearPendingRequestTimeout(active);
506
+ active.reject(new Error(INTERACTION_TIMED_OUT_ERROR));
507
+ this.session.updateAgentState((currentState) => {
508
+ const request = currentState.requests?.[requestId] || {
509
+ tool: "AskUserQuestion",
510
+ arguments: {
511
+ requestKind: "selection",
512
+ questions: []
513
+ },
514
+ createdAt: Date.now(),
515
+ requestKind: "selection",
516
+ options: active.request.options,
517
+ defaultOptionId: active.request.defaultOptionId
518
+ };
519
+ const { [requestId]: _, ...remainingRequests } = currentState.requests || {};
520
+ return {
521
+ ...currentState,
522
+ requests: remainingRequests,
523
+ completedRequests: {
524
+ ...currentState.completedRequests,
525
+ [requestId]: {
526
+ ...request,
527
+ completedAt: Date.now(),
528
+ status: "canceled",
529
+ reason: INTERACTION_TIMED_OUT_ERROR,
530
+ requestKind: "selection"
531
+ }
532
+ }
533
+ };
534
+ });
535
+ this.session.sendSessionEvent({
536
+ type: "message",
537
+ message: "Pending interaction timed out waiting for a response. Send a new message to continue."
538
+ });
539
+ logger.debug(`[${this.providerLabel}] Selection request timed out (${requestId})`);
540
+ }
541
+ }
542
+
336
543
  class CodexSelectionHandler extends ProviderSelectionHandler {
337
544
  constructor(session) {
338
545
  super(session, "Codex");
@@ -1,10 +1,10 @@
1
1
  import { useStdout, useInput, Box, Text, render } from 'ink';
2
2
  import React, { useState, useRef, useEffect, useCallback } from 'react';
3
3
  import { randomUUID } from 'node:crypto';
4
- import { l as logger, b as connectionState, A as ApiClient } from './api-BxXBKBUy.mjs';
5
- import { B as BasePermissionHandler, C as ConversationHistory$1, e as ensureManagedProviderMachine, M as MissingMachineIdError, s as syncControlledByUserState, b as MessageQueue2, h as hashObject, d as MessageBuffer, r as registerKillSessionHandler, w as waitForResponseCompleteWithAbort, f as closeProviderSession, l as launchRuntimeHandleWithFactoryResult, i as inferToolResultError, j as forwardAgentMessageToProviderSession } from './registerKillSessionHandler-CNNguWyD.mjs';
6
- import { g as getInitialGeminiModel, r as readGeminiLocalConfig, G as GEMINI_MODEL_ENV, s as saveGeminiModelToConfig, a as createGeminiBackend, b as stopCaffeinate } from './index-DaAkW0VN.mjs';
7
- import { B as BaseReasoningProcessor, b as bootstrapManagedProviderSession } from './BaseReasoningProcessor-DrHf5B98.mjs';
4
+ import { l as logger, b as connectionState, A as ApiClient } from './api-D1meoL-9.mjs';
5
+ import { e as ensureManagedProviderMachine, M as MissingMachineIdError, s as syncControlledByUserState, a as MessageQueue2, h as hashObject, b as MessageBuffer, r as registerKillSessionHandler, c as closeProviderSession } from './registerKillSessionHandler-BElGmD1E.mjs';
6
+ import { g as getInitialGeminiModel, r as readGeminiLocalConfig, G as GEMINI_MODEL_ENV, s as saveGeminiModelToConfig, a as createGeminiBackend, b as stopCaffeinate } from './index-Cxrx9m5D.mjs';
7
+ import { B as BasePermissionHandler, a as BaseReasoningProcessor, C as ConversationHistory$1, b as bootstrapManagedProviderSession, w as waitForResponseCompleteWithAbort, l as launchRuntimeHandleWithFactoryResult, i as inferToolResultError, f as forwardAgentMessageToProviderSession } from './ConversationHistory-_ciJNIgH.mjs';
8
8
  import 'cross-spawn';
9
9
  import '@agentclientprotocol/sdk';
10
10
  import 'ps-list';
@@ -13,7 +13,7 @@ import 'node:path';
13
13
  import 'node:os';
14
14
  import 'tweetnacl';
15
15
  import 'axios';
16
- import './persistence-8pNEvzaq.mjs';
16
+ import './persistence-9Iu0wGNM.mjs';
17
17
  import 'open';
18
18
  import 'chalk';
19
19
  import 'fs';