longer-agent 0.1.1 → 0.1.3

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 (134) hide show
  1. package/README.md +74 -178
  2. package/README.zh-CN.md +74 -178
  3. package/agent_templates/executor/agent.yaml +1 -0
  4. package/agent_templates/executor/system_prompt.md +1 -1
  5. package/agent_templates/explorer/agent.yaml +1 -0
  6. package/agent_templates/explorer/system_prompt.md +1 -1
  7. package/agent_templates/main/agent.yaml +1 -0
  8. package/agent_templates/main/system_prompt.md +3 -2
  9. package/dist/agents/tool-loop.d.ts.map +1 -1
  10. package/dist/agents/tool-loop.js +6 -0
  11. package/dist/agents/tool-loop.js.map +1 -1
  12. package/dist/auth/openai-oauth.d.ts.map +1 -1
  13. package/dist/auth/openai-oauth.js +6 -10
  14. package/dist/auth/openai-oauth.js.map +1 -1
  15. package/dist/cli.d.ts +1 -2
  16. package/dist/cli.d.ts.map +1 -1
  17. package/dist/cli.js +81 -60
  18. package/dist/cli.js.map +1 -1
  19. package/dist/commands.d.ts +6 -1
  20. package/dist/commands.d.ts.map +1 -1
  21. package/dist/commands.js +115 -27
  22. package/dist/commands.js.map +1 -1
  23. package/dist/config.d.ts +19 -26
  24. package/dist/config.d.ts.map +1 -1
  25. package/dist/config.js +80 -120
  26. package/dist/config.js.map +1 -1
  27. package/dist/dotenv.d.ts +18 -0
  28. package/dist/dotenv.d.ts.map +1 -0
  29. package/dist/dotenv.js +91 -0
  30. package/dist/dotenv.js.map +1 -0
  31. package/dist/home-path.d.ts +3 -0
  32. package/dist/home-path.d.ts.map +1 -0
  33. package/dist/home-path.js +7 -0
  34. package/dist/home-path.js.map +1 -0
  35. package/dist/index.d.ts +6 -2
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +10 -2
  38. package/dist/index.js.map +1 -1
  39. package/dist/init-wizard.d.ts +2 -3
  40. package/dist/init-wizard.d.ts.map +1 -1
  41. package/dist/init-wizard.js +349 -145
  42. package/dist/init-wizard.js.map +1 -1
  43. package/dist/log-projection.d.ts.map +1 -1
  44. package/dist/log-projection.js +71 -12
  45. package/dist/log-projection.js.map +1 -1
  46. package/dist/managed-provider-credentials.d.ts +23 -0
  47. package/dist/managed-provider-credentials.d.ts.map +1 -0
  48. package/dist/managed-provider-credentials.js +56 -0
  49. package/dist/managed-provider-credentials.js.map +1 -0
  50. package/dist/mcp-client.d.ts.map +1 -1
  51. package/dist/mcp-client.js +2 -1
  52. package/dist/mcp-client.js.map +1 -1
  53. package/dist/mcp-config.d.ts +13 -0
  54. package/dist/mcp-config.d.ts.map +1 -0
  55. package/dist/mcp-config.js +64 -0
  56. package/dist/mcp-config.js.map +1 -0
  57. package/dist/model-discovery.d.ts +20 -0
  58. package/dist/model-discovery.d.ts.map +1 -0
  59. package/dist/model-discovery.js +47 -0
  60. package/dist/model-discovery.js.map +1 -0
  61. package/dist/model-selection.d.ts +1 -1
  62. package/dist/model-selection.d.ts.map +1 -1
  63. package/dist/model-selection.js +20 -10
  64. package/dist/model-selection.js.map +1 -1
  65. package/dist/persistence.d.ts +14 -1
  66. package/dist/persistence.d.ts.map +1 -1
  67. package/dist/persistence.js +12 -8
  68. package/dist/persistence.js.map +1 -1
  69. package/dist/provider-credential-flow.d.ts +28 -0
  70. package/dist/provider-credential-flow.d.ts.map +1 -0
  71. package/dist/provider-credential-flow.js +112 -0
  72. package/dist/provider-credential-flow.js.map +1 -0
  73. package/dist/provider-presets.d.ts +4 -0
  74. package/dist/provider-presets.d.ts.map +1 -1
  75. package/dist/provider-presets.js +26 -9
  76. package/dist/provider-presets.js.map +1 -1
  77. package/dist/providers/registry.d.ts.map +1 -1
  78. package/dist/providers/registry.js +3 -2
  79. package/dist/providers/registry.js.map +1 -1
  80. package/dist/session.d.ts +6 -17
  81. package/dist/session.d.ts.map +1 -1
  82. package/dist/session.js +82 -216
  83. package/dist/session.js.map +1 -1
  84. package/dist/settings.d.ts +8 -27
  85. package/dist/settings.d.ts.map +1 -1
  86. package/dist/settings.js +4 -108
  87. package/dist/settings.js.map +1 -1
  88. package/dist/templates/loader.d.ts.map +1 -1
  89. package/dist/templates/loader.js +2 -0
  90. package/dist/templates/loader.js.map +1 -1
  91. package/dist/tools/basic.d.ts +2 -2
  92. package/dist/tools/basic.d.ts.map +1 -1
  93. package/dist/tools/basic.js +54 -7
  94. package/dist/tools/basic.js.map +1 -1
  95. package/dist/tools/comm.d.ts.map +1 -1
  96. package/dist/tools/comm.js +8 -7
  97. package/dist/tools/comm.js.map +1 -1
  98. package/dist/tui/app.d.ts.map +1 -1
  99. package/dist/tui/app.js +176 -39
  100. package/dist/tui/app.js.map +1 -1
  101. package/dist/tui/components/command-prompt-panel.d.ts +22 -0
  102. package/dist/tui/components/command-prompt-panel.d.ts.map +1 -0
  103. package/dist/tui/components/command-prompt-panel.js +26 -0
  104. package/dist/tui/components/command-prompt-panel.js.map +1 -0
  105. package/dist/tui/components/input-panel.d.ts.map +1 -1
  106. package/dist/tui/components/input-panel.js +8 -6
  107. package/dist/tui/components/input-panel.js.map +1 -1
  108. package/dist/tui/components/logo-panel.d.ts.map +1 -1
  109. package/dist/tui/components/logo-panel.js +2 -4
  110. package/dist/tui/components/logo-panel.js.map +1 -1
  111. package/dist/tui/components/plan-panel.d.ts +3 -1
  112. package/dist/tui/components/plan-panel.d.ts.map +1 -1
  113. package/dist/tui/components/plan-panel.js +15 -2
  114. package/dist/tui/components/plan-panel.js.map +1 -1
  115. package/dist/tui/components/status-bar.d.ts.map +1 -1
  116. package/dist/tui/components/status-bar.js +17 -4
  117. package/dist/tui/components/status-bar.js.map +1 -1
  118. package/dist/tui/status-bar-model-name.d.ts +2 -0
  119. package/dist/tui/status-bar-model-name.d.ts.map +1 -0
  120. package/dist/tui/status-bar-model-name.js +81 -0
  121. package/dist/tui/status-bar-model-name.js.map +1 -0
  122. package/dist/update-check.d.ts +19 -0
  123. package/dist/update-check.d.ts.map +1 -0
  124. package/dist/update-check.js +116 -0
  125. package/dist/update-check.js.map +1 -0
  126. package/dist/version.d.ts +2 -0
  127. package/dist/version.d.ts.map +1 -0
  128. package/dist/version.js +7 -0
  129. package/dist/version.js.map +1 -0
  130. package/package.json +9 -5
  131. package/prompts/tools/plan.md +11 -240
  132. package/prompts/tools/summarize_context.md +1 -1
  133. package/prompts/tools/time.md +6 -0
  134. package/configExample.yaml +0 -83
package/dist/tui/app.js CHANGED
@@ -30,6 +30,7 @@ import { LogoPanel } from "./components/logo-panel.js";
30
30
  import { StatusBar } from "./components/status-bar.js";
31
31
  import { ConversationPanel } from "./components/conversation-panel.js";
32
32
  import { AskPanel } from "./components/ask-panel.js";
33
+ import { CommandPromptPanel, } from "./components/command-prompt-panel.js";
33
34
  import { PlanPanel } from "./components/plan-panel.js";
34
35
  import { InputPanel } from "./components/input-panel.js";
35
36
  import { InputProtocolParser } from "./input/protocol.js";
@@ -37,8 +38,8 @@ import { mapInputEventToCommand } from "./input/keymap.js";
37
38
  import { withValueAndCursor, insertText, moveLeft, moveRight, moveWordLeft, moveWordRight, moveHome, moveEnd, deleteBackward, deleteForward, deleteWordBackward, deleteWordForward, deleteToLineStart, deleteToLineEnd, } from "./input/editor-state.js";
38
39
  import { saveLog } from "../persistence.js";
39
40
  import { isCommandExitSignal } from "../commands.js";
40
- import { formatDisplayModelName } from "../config.js";
41
41
  import { projectToTuiEntries } from "../log-projection.js";
42
+ import { formatStatusBarModelName } from "./status-bar-model-name.js";
42
43
  // ------------------------------------------------------------------
43
44
  // Goodbye messages
44
45
  // ------------------------------------------------------------------
@@ -48,6 +49,7 @@ const GOODBYE_MESSAGES = [
48
49
  "Peace out!", "So long!", "Off I go!", "Later, gator!",
49
50
  ];
50
51
  const CUSTOM_EMPTY_HINT = 'Custom answer is empty. Please enter an answer first, or choose "Discuss further" instead.';
52
+ const ACTIVITY_DETAIL_FALLBACK_MS = 3000;
51
53
  // ------------------------------------------------------------------
52
54
  // Clipboard helper
53
55
  // ------------------------------------------------------------------
@@ -119,17 +121,21 @@ export function App({ session, commandRegistry, store, onProgressCallback, }) {
119
121
  const [reviewMode, setReviewMode] = useState(false);
120
122
  // Plan panel state
121
123
  const [planCheckpoints, setPlanCheckpoints] = useState(null);
124
+ const [commandPrompt, setCommandPrompt] = useState(null);
122
125
  const cancelledRef = useRef(false);
123
126
  const lastCtrlCRef = useRef(0);
124
127
  const abortControllerRef = useRef(null);
125
128
  const inputPanelRef = useRef(null);
126
129
  const shortcutParserRef = useRef(new InputProtocolParser());
127
130
  const shortcutDecoderRef = useRef(new StringDecoder("utf8"));
131
+ const activityFallbackTimerRef = useRef(null);
132
+ const activityFallbackSeqRef = useRef(0);
128
133
  const inputHintTimerRef = useRef(null);
129
134
  const markdownModeInitializedRef = useRef(false);
130
135
  const runTurnRef = useRef(null);
131
136
  const runManualSummarizeRef = useRef(null);
132
137
  const runManualCompactRef = useRef(null);
138
+ const commandPromptResolveRef = useRef(null);
133
139
  // Raw mode
134
140
  useEffect(() => {
135
141
  if (!isRawModeSupported)
@@ -202,12 +208,41 @@ export function App({ session, commandRegistry, store, onProgressCallback, }) {
202
208
  }, []);
203
209
  useEffect(() => {
204
210
  return () => {
211
+ if (activityFallbackTimerRef.current) {
212
+ clearTimeout(activityFallbackTimerRef.current);
213
+ activityFallbackTimerRef.current = null;
214
+ }
205
215
  if (inputHintTimerRef.current) {
206
216
  clearTimeout(inputHintTimerRef.current);
207
217
  inputHintTimerRef.current = null;
208
218
  }
209
219
  };
210
220
  }, []);
221
+ const clearActivityFallback = useCallback(() => {
222
+ activityFallbackSeqRef.current += 1;
223
+ if (activityFallbackTimerRef.current) {
224
+ clearTimeout(activityFallbackTimerRef.current);
225
+ activityFallbackTimerRef.current = null;
226
+ }
227
+ }, []);
228
+ const setStableActivity = useCallback((phase) => {
229
+ clearActivityFallback();
230
+ setActivityPhase(phase);
231
+ setActivityToolName(undefined);
232
+ }, [clearActivityFallback]);
233
+ const setTransientActivity = useCallback((phase) => {
234
+ clearActivityFallback();
235
+ const seq = activityFallbackSeqRef.current;
236
+ setActivityPhase(phase);
237
+ setActivityToolName(undefined);
238
+ activityFallbackTimerRef.current = setTimeout(() => {
239
+ if (activityFallbackSeqRef.current !== seq)
240
+ return;
241
+ activityFallbackTimerRef.current = null;
242
+ setActivityPhase("working");
243
+ setActivityToolName(undefined);
244
+ }, ACTIVITY_DETAIL_FALLBACK_MS);
245
+ }, [clearActivityFallback]);
211
246
  useEffect(() => {
212
247
  if (!markdownModeInitializedRef.current) {
213
248
  markdownModeInitializedRef.current = true;
@@ -215,6 +250,44 @@ export function App({ session, commandRegistry, store, onProgressCallback, }) {
215
250
  }
216
251
  showInputHint(markdownMode === "raw" ? "Markdown raw: ON" : "Markdown raw: OFF");
217
252
  }, [markdownMode, showInputHint]);
253
+ const resolveCommandPrompt = useCallback((value) => {
254
+ const resolve = commandPromptResolveRef.current;
255
+ commandPromptResolveRef.current = null;
256
+ setCommandPrompt(null);
257
+ resolve?.(value);
258
+ }, []);
259
+ const promptSelect = useCallback((request) => {
260
+ return new Promise((resolve) => {
261
+ commandPromptResolveRef.current = resolve;
262
+ setCommandPrompt({
263
+ kind: "select",
264
+ message: request.message,
265
+ options: request.options,
266
+ selected: 0,
267
+ });
268
+ });
269
+ }, []);
270
+ const promptSecret = useCallback((request) => {
271
+ return new Promise((resolve) => {
272
+ commandPromptResolveRef.current = resolve;
273
+ setCommandPrompt({
274
+ kind: "secret",
275
+ message: request.message,
276
+ value: "",
277
+ cursor: 0,
278
+ allowEmpty: request.allowEmpty,
279
+ error: null,
280
+ });
281
+ });
282
+ }, []);
283
+ useEffect(() => {
284
+ return () => {
285
+ if (commandPromptResolveRef.current) {
286
+ commandPromptResolveRef.current(undefined);
287
+ commandPromptResolveRef.current = null;
288
+ }
289
+ };
290
+ }, []);
218
291
  useEffect(() => {
219
292
  setAskSelectionIndex(0);
220
293
  setCurrentQuestionIndex(0);
@@ -252,8 +325,7 @@ export function App({ session, commandRegistry, store, onProgressCallback, }) {
252
325
  const controller = new AbortController();
253
326
  abortControllerRef.current = controller;
254
327
  setProcessing(true);
255
- setActivityPhase("working");
256
- setActivityToolName(undefined);
328
+ setStableActivity("working");
257
329
  setStatusError(false);
258
330
  try {
259
331
  await session.resumePendingTurn({ signal: controller.signal });
@@ -261,8 +333,7 @@ export function App({ session, commandRegistry, store, onProgressCallback, }) {
261
333
  autoSave();
262
334
  return;
263
335
  }
264
- setActivityPhase("idle");
265
- setActivityToolName(undefined);
336
+ setStableActivity("idle");
266
337
  setContextTokens(session.lastInputTokens);
267
338
  setCacheReadTokens(session.lastCacheReadTokens ?? 0);
268
339
  setPendingAsk(session.getPendingAsk?.() ?? null);
@@ -275,6 +346,7 @@ export function App({ session, commandRegistry, store, onProgressCallback, }) {
275
346
  }
276
347
  const msg = err instanceof Error ? err.message : String(err);
277
348
  session.appendErrorMessage?.(msg, "resume_pending_turn");
349
+ clearActivityFallback();
278
350
  setStatusError(true);
279
351
  }
280
352
  finally {
@@ -284,7 +356,7 @@ export function App({ session, commandRegistry, store, onProgressCallback, }) {
284
356
  setProcessing(false);
285
357
  }
286
358
  }
287
- }, [session, autoSave]);
359
+ }, [session, autoSave, setStableActivity, clearActivityFallback]);
288
360
  // Wire incremental save callback into Session
289
361
  useEffect(() => {
290
362
  session.onSaveRequest = autoSave;
@@ -334,12 +406,12 @@ export function App({ session, commandRegistry, store, onProgressCallback, }) {
334
406
  // Reset token count on /new
335
407
  setContextTokens(0);
336
408
  setCacheReadTokens(0);
337
- setActivityPhase("idle");
338
- setActivityToolName(undefined);
409
+ setStableActivity("idle");
339
410
  setStatusError(false);
340
411
  setPendingAsk(null);
341
412
  setAskError(null);
342
413
  setHideProgress(false);
414
+ setPlanCheckpoints(null);
343
415
  },
344
416
  exit: performExit,
345
417
  onTurnRequested: (content) => {
@@ -351,8 +423,10 @@ export function App({ session, commandRegistry, store, onProgressCallback, }) {
351
423
  onManualCompactRequested: (instruction) => {
352
424
  runManualCompactRef.current?.(instruction);
353
425
  },
426
+ promptSelect,
427
+ promptSecret,
354
428
  };
355
- }, [session, store, commandRegistry, autoSave, performExit, showInputHint]);
429
+ }, [session, store, commandRegistry, autoSave, performExit, showInputHint, promptSelect, promptSecret, setStableActivity]);
356
430
  // ------------------------------------------------------------------
357
431
  // Progress callback (streaming)
358
432
  // ------------------------------------------------------------------
@@ -364,20 +438,16 @@ export function App({ session, commandRegistry, store, onProgressCallback, }) {
364
438
  if (!hasSubAgentId) {
365
439
  switch (event.action) {
366
440
  case "reasoning_chunk":
367
- setActivityPhase("thinking");
368
- setActivityToolName(undefined);
441
+ setTransientActivity("thinking");
369
442
  break;
370
443
  case "text_chunk":
371
- setActivityPhase("generating");
372
- setActivityToolName(undefined);
444
+ setTransientActivity("generating");
373
445
  break;
374
446
  case "tool_call":
375
- setActivityPhase("tool_calling");
376
- setActivityToolName(event.extra?.["tool"] ?? undefined);
447
+ setStableActivity("working");
377
448
  break;
378
449
  case "agent_no_reply":
379
- setActivityPhase("waiting");
380
- setActivityToolName(undefined);
450
+ setStableActivity("waiting");
381
451
  break;
382
452
  case "agent_end":
383
453
  setContextTokens(session.lastInputTokens);
@@ -395,8 +465,7 @@ export function App({ session, commandRegistry, store, onProgressCallback, }) {
395
465
  const ask = event.extra?.["ask"] ?? session.getPendingAsk?.() ?? null;
396
466
  setPendingAsk(ask);
397
467
  setAskError(null);
398
- setActivityPhase("waiting");
399
- setActivityToolName(undefined);
468
+ setStableActivity("waiting");
400
469
  return;
401
470
  }
402
471
  if (event.action === "ask_resolved") {
@@ -415,7 +484,7 @@ export function App({ session, commandRegistry, store, onProgressCallback, }) {
415
484
  setPlanCheckpoints(null);
416
485
  return;
417
486
  }
418
- }, [session]);
487
+ }, [session, setStableActivity, setTransientActivity]);
419
488
  // Register progress callback on mount
420
489
  useEffect(() => {
421
490
  onProgressCallback(handleProgress);
@@ -428,8 +497,7 @@ export function App({ session, commandRegistry, store, onProgressCallback, }) {
428
497
  const controller = new AbortController();
429
498
  abortControllerRef.current = controller;
430
499
  setProcessing(true);
431
- setActivityPhase("working");
432
- setActivityToolName(undefined);
500
+ setStableActivity("working");
433
501
  setStatusError(false);
434
502
  try {
435
503
  await session.turn(userInput, { signal: controller.signal });
@@ -437,8 +505,7 @@ export function App({ session, commandRegistry, store, onProgressCallback, }) {
437
505
  autoSave();
438
506
  return;
439
507
  }
440
- setActivityPhase("idle");
441
- setActivityToolName(undefined);
508
+ setStableActivity("idle");
442
509
  setContextTokens(session.lastInputTokens);
443
510
  setCacheReadTokens(session.lastCacheReadTokens ?? 0);
444
511
  setPendingAsk(session.getPendingAsk?.() ?? null);
@@ -451,6 +518,7 @@ export function App({ session, commandRegistry, store, onProgressCallback, }) {
451
518
  }
452
519
  const msg = err instanceof Error ? err.message : String(err);
453
520
  session.appendErrorMessage?.(msg, "turn");
521
+ clearActivityFallback();
454
522
  setStatusError(true);
455
523
  setPendingAsk(session.getPendingAsk?.() ?? null);
456
524
  }
@@ -461,7 +529,7 @@ export function App({ session, commandRegistry, store, onProgressCallback, }) {
461
529
  setProcessing(false);
462
530
  }
463
531
  }
464
- }, [session, autoSave]);
532
+ }, [session, autoSave, setStableActivity, clearActivityFallback]);
465
533
  runTurnRef.current = runTurn;
466
534
  const runManualSummarize = useCallback(async (instruction) => {
467
535
  if (typeof session.runManualSummarize !== "function") {
@@ -472,8 +540,7 @@ export function App({ session, commandRegistry, store, onProgressCallback, }) {
472
540
  const controller = new AbortController();
473
541
  abortControllerRef.current = controller;
474
542
  setProcessing(true);
475
- setActivityPhase("working");
476
- setActivityToolName(undefined);
543
+ setStableActivity("working");
477
544
  setStatusError(false);
478
545
  try {
479
546
  await session.runManualSummarize(instruction, { signal: controller.signal });
@@ -481,8 +548,7 @@ export function App({ session, commandRegistry, store, onProgressCallback, }) {
481
548
  autoSave();
482
549
  return;
483
550
  }
484
- setActivityPhase("idle");
485
- setActivityToolName(undefined);
551
+ setStableActivity("idle");
486
552
  setContextTokens(session.lastInputTokens);
487
553
  setCacheReadTokens(session.lastCacheReadTokens ?? 0);
488
554
  setPendingAsk(session.getPendingAsk?.() ?? null);
@@ -495,6 +561,7 @@ export function App({ session, commandRegistry, store, onProgressCallback, }) {
495
561
  }
496
562
  const msg = err instanceof Error ? err.message : String(err);
497
563
  session.appendErrorMessage?.(msg, "manual_summarize");
564
+ clearActivityFallback();
498
565
  setStatusError(true);
499
566
  }
500
567
  finally {
@@ -504,7 +571,7 @@ export function App({ session, commandRegistry, store, onProgressCallback, }) {
504
571
  setProcessing(false);
505
572
  }
506
573
  }
507
- }, [session, autoSave]);
574
+ }, [session, autoSave, setStableActivity, clearActivityFallback]);
508
575
  runManualSummarizeRef.current = runManualSummarize;
509
576
  const runManualCompact = useCallback(async (instruction) => {
510
577
  if (typeof session.runManualCompact !== "function") {
@@ -515,8 +582,7 @@ export function App({ session, commandRegistry, store, onProgressCallback, }) {
515
582
  const controller = new AbortController();
516
583
  abortControllerRef.current = controller;
517
584
  setProcessing(true);
518
- setActivityPhase("working");
519
- setActivityToolName(undefined);
585
+ setStableActivity("working");
520
586
  setStatusError(false);
521
587
  try {
522
588
  await session.runManualCompact(instruction, { signal: controller.signal });
@@ -524,8 +590,7 @@ export function App({ session, commandRegistry, store, onProgressCallback, }) {
524
590
  autoSave();
525
591
  return;
526
592
  }
527
- setActivityPhase("idle");
528
- setActivityToolName(undefined);
593
+ setStableActivity("idle");
529
594
  setContextTokens(session.lastInputTokens);
530
595
  setCacheReadTokens(session.lastCacheReadTokens ?? 0);
531
596
  setPendingAsk(session.getPendingAsk?.() ?? null);
@@ -538,6 +603,7 @@ export function App({ session, commandRegistry, store, onProgressCallback, }) {
538
603
  }
539
604
  const msg = err instanceof Error ? err.message : String(err);
540
605
  session.appendErrorMessage?.(msg, "manual_compact");
606
+ clearActivityFallback();
541
607
  setStatusError(true);
542
608
  }
543
609
  finally {
@@ -547,7 +613,7 @@ export function App({ session, commandRegistry, store, onProgressCallback, }) {
547
613
  setProcessing(false);
548
614
  }
549
615
  }
550
- }, [session, autoSave]);
616
+ }, [session, autoSave, setStableActivity, clearActivityFallback]);
551
617
  runManualCompactRef.current = runManualCompact;
552
618
  const resolveAgentQuestion = useCallback((answersOverride, notesOverride) => {
553
619
  if (!pendingAsk || pendingAsk.kind !== "agent_question")
@@ -693,6 +759,7 @@ export function App({ session, commandRegistry, store, onProgressCallback, }) {
693
759
  // ------------------------------------------------------------------
694
760
  const handleSubmit = useCallback((input) => {
695
761
  clearInputHint();
762
+ // If a command is waiting for user input (e.g. API key paste), resolve it.
696
763
  if (pendingAsk) {
697
764
  if (pendingAsk.kind === "agent_question") {
698
765
  showInputHint("Use ↑/↓ to select options, ←/→ to navigate questions, Enter to confirm.", 2500);
@@ -757,6 +824,11 @@ export function App({ session, commandRegistry, store, onProgressCallback, }) {
757
824
  // Ctrl+C / Ctrl+L / Ctrl+Y handling
758
825
  // ------------------------------------------------------------------
759
826
  const handleCtrlC = useCallback(() => {
827
+ if (commandPrompt) {
828
+ resolveCommandPrompt(undefined);
829
+ clearInputHint();
830
+ return;
831
+ }
760
832
  if (inputPanelRef.current?.dismissOverlay()) {
761
833
  clearInputHint();
762
834
  return;
@@ -794,18 +866,20 @@ export function App({ session, commandRegistry, store, onProgressCallback, }) {
794
866
  cancelledRef.current = true;
795
867
  abortControllerRef.current?.abort();
796
868
  setProcessing(false);
797
- setActivityPhase("idle");
798
- setActivityToolName(undefined);
869
+ setStableActivity("idle");
799
870
  clearInputHint();
800
871
  }
801
872
  else {
802
873
  showInputHint("Press Ctrl+C again to exit");
803
874
  }
804
875
  }, [
876
+ commandPrompt,
877
+ resolveCommandPrompt,
805
878
  processing,
806
879
  clearInputHint,
807
880
  showInputHint,
808
881
  performExit,
882
+ setStableActivity,
809
883
  ]);
810
884
  const handleCtrlL = useCallback(() => {
811
885
  setHideProgress((prev) => {
@@ -840,6 +914,67 @@ export function App({ session, commandRegistry, store, onProgressCallback, }) {
840
914
  const chunk = typeof data === "string" ? data : shortcutDecoderRef.current.write(data);
841
915
  const events = shortcutParserRef.current.push(chunk);
842
916
  for (const event of events) {
917
+ if (commandPrompt) {
918
+ if (event.type !== "key" && event.type !== "insert")
919
+ continue;
920
+ if (commandPrompt.kind === "select") {
921
+ if (event.type !== "key")
922
+ continue;
923
+ if (event.key === "up" && commandPrompt.options.length > 0) {
924
+ setCommandPrompt((prev) => {
925
+ if (!prev || prev.kind !== "select" || prev.options.length === 0)
926
+ return prev;
927
+ return {
928
+ ...prev,
929
+ selected: (prev.selected - 1 + prev.options.length) % prev.options.length,
930
+ };
931
+ });
932
+ continue;
933
+ }
934
+ if (event.key === "down" && commandPrompt.options.length > 0) {
935
+ setCommandPrompt((prev) => {
936
+ if (!prev || prev.kind !== "select" || prev.options.length === 0)
937
+ return prev;
938
+ return {
939
+ ...prev,
940
+ selected: (prev.selected + 1) % prev.options.length,
941
+ };
942
+ });
943
+ continue;
944
+ }
945
+ if (event.key === "enter") {
946
+ const selected = commandPrompt.options[commandPrompt.selected];
947
+ resolveCommandPrompt(selected?.value);
948
+ continue;
949
+ }
950
+ if (event.key === "escape" || event.key === "ctrl_c") {
951
+ resolveCommandPrompt(undefined);
952
+ continue;
953
+ }
954
+ continue;
955
+ }
956
+ if (event.type === "key" && event.key === "enter") {
957
+ if (!commandPrompt.allowEmpty && commandPrompt.value.trim() === "") {
958
+ setCommandPrompt((prev) => prev && prev.kind === "secret"
959
+ ? { ...prev, error: "API key cannot be empty." }
960
+ : prev);
961
+ continue;
962
+ }
963
+ resolveCommandPrompt(commandPrompt.value);
964
+ continue;
965
+ }
966
+ if (event.type === "key" && (event.key === "escape" || event.key === "ctrl_c")) {
967
+ resolveCommandPrompt(undefined);
968
+ continue;
969
+ }
970
+ const result = applyInlineEdit(commandPrompt.value, commandPrompt.cursor, event);
971
+ if (result) {
972
+ setCommandPrompt((prev) => prev && prev.kind === "secret"
973
+ ? { ...prev, value: result.value, cursor: result.cursor, error: null }
974
+ : prev);
975
+ }
976
+ continue;
977
+ }
843
978
  // --- Review mode for multi-question ask ---
844
979
  if (pendingAsk?.kind === "agent_question" && reviewMode) {
845
980
  if (event.type !== "key")
@@ -1015,6 +1150,8 @@ export function App({ session, commandRegistry, store, onProgressCallback, }) {
1015
1150
  };
1016
1151
  }, [
1017
1152
  stdin,
1153
+ commandPrompt,
1154
+ resolveCommandPrompt,
1018
1155
  pendingAsk,
1019
1156
  resolveSelectedPendingAsk,
1020
1157
  resolveAgentQuestion,
@@ -1035,8 +1172,8 @@ export function App({ session, commandRegistry, store, onProgressCallback, }) {
1035
1172
  // ------------------------------------------------------------------
1036
1173
  // Render
1037
1174
  // ------------------------------------------------------------------
1038
- return (_jsxs(Box, { flexDirection: "column", height: "100%", children: [_jsx(Box, { flexShrink: 0, children: _jsx(Text, { children: " " }) }), _jsxs(Box, { flexDirection: "column", flexShrink: 0, children: [_jsx(Text, { children: " " }), _jsx(LogoPanel, { cwd: process.cwd() })] }), _jsx(ConversationPanel, { entries: entries, markdownMode: markdownMode, streamingAssistantEntryId: null }), planCheckpoints ? _jsx(PlanPanel, { checkpoints: planCheckpoints }) : null, pendingAsk ? (_jsx(AskPanel, { ask: pendingAsk, error: askError, selectedIndex: askSelectionIndex, currentQuestionIndex: currentQuestionIndex, totalQuestions: pendingAsk.kind === "agent_question"
1175
+ return (_jsxs(Box, { flexDirection: "column", height: "100%", children: [_jsx(Box, { flexShrink: 0, children: _jsx(Text, { children: " " }) }), _jsxs(Box, { flexDirection: "column", flexShrink: 0, children: [_jsx(Text, { children: " " }), _jsx(LogoPanel, { cwd: process.cwd() })] }), _jsx(ConversationPanel, { entries: entries, markdownMode: markdownMode, streamingAssistantEntryId: null }), planCheckpoints ? _jsx(PlanPanel, { checkpoints: planCheckpoints, active: activityPhase !== "idle" }) : null, pendingAsk ? (_jsx(AskPanel, { ask: pendingAsk, error: askError, selectedIndex: askSelectionIndex, currentQuestionIndex: currentQuestionIndex, totalQuestions: pendingAsk.kind === "agent_question"
1039
1176
  ? (pendingAsk.payload["questions"] ?? []).length
1040
- : 1, questionAnswers: questionAnswers, customInputMode: customInputMode, noteInputMode: noteInputMode, reviewMode: reviewMode, inlineEditorValue: inlineEditor.value, inlineEditorCursor: inlineEditor.cursor, optionNotes: optionNotes })) : null, _jsx(InputPanel, { ref: inputPanelRef, onSubmit: handleSubmit, disabled: !!pendingAsk, commandRegistry: commandRegistry, store: store, hint: inputHint, onHintRequested: showInputHint, session: session }), _jsx(StatusBar, { phase: activityPhase, toolName: activityToolName, error: statusError, modelName: formatDisplayModelName(session.primaryAgent.modelConfig?.provider, session.primaryAgent.modelConfig?.model), contextTokens: contextTokens, contextLimit: session.primaryAgent.modelConfig?.contextLength, cacheReadTokens: cacheReadTokens })] }));
1177
+ : 1, questionAnswers: questionAnswers, customInputMode: customInputMode, noteInputMode: noteInputMode, reviewMode: reviewMode, inlineEditorValue: inlineEditor.value, inlineEditorCursor: inlineEditor.cursor, optionNotes: optionNotes })) : null, commandPrompt ? _jsx(CommandPromptPanel, { prompt: commandPrompt }) : null, _jsx(InputPanel, { ref: inputPanelRef, onSubmit: handleSubmit, disabled: !!pendingAsk || !!commandPrompt, commandRegistry: commandRegistry, store: store, hint: inputHint, onHintRequested: showInputHint, session: session }), _jsx(StatusBar, { phase: activityPhase, toolName: activityToolName, error: statusError, modelName: formatStatusBarModelName(session.primaryAgent.modelConfig?.provider, session.primaryAgent.modelConfig?.model), contextTokens: contextTokens, contextLimit: session.primaryAgent.modelConfig?.contextLength, cacheReadTokens: cacheReadTokens })] }));
1041
1178
  }
1042
1179
  //# sourceMappingURL=app.js.map