@phi-code-admin/phi-code 0.97.0 → 0.97.1

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.
@@ -123,6 +123,12 @@ export class InteractiveMode {
123
123
  version;
124
124
  isInitialized = false;
125
125
  onInputCallback;
126
+ // Submissions typed while the main loop was busy (prompt preflight) or a
127
+ // session rebuild was in flight (/new). Queued and replayed instead of
128
+ // silently dropped — a prompt typed right after /new used to disappear
129
+ // with no feedback.
130
+ pendingSubmissions = [];
131
+ sessionTransitioning = false;
126
132
  // Input mode: "act" sends messages to the agent directly; "plan" routes the next
127
133
  // message through the /plan orchestrator (5 sequential phases, one model per phase).
128
134
  // Toggled with Tab (when the editor is empty); shown by the footer Act/Plan indicator.
@@ -2184,7 +2190,14 @@ export class InteractiveMode {
2184
2190
  // Normal message submission
2185
2191
  // First, move any pending bash components to chat
2186
2192
  this.flushPendingBashComponents();
2187
- if (this.onInputCallback) {
2193
+ if (this.sessionTransitioning || !this.onInputCallback) {
2194
+ // The main loop is busy (prompt preflight) or the session is being
2195
+ // rebuilt (/new in flight): queue and replay once ready instead of
2196
+ // dropping the message on the floor.
2197
+ this.pendingSubmissions.push(text);
2198
+ this.showStatus("Message queued — sending when the session is ready");
2199
+ }
2200
+ else {
2188
2201
  this.onInputCallback(text);
2189
2202
  }
2190
2203
  this.editor.addToHistory?.(text);
@@ -2670,6 +2683,14 @@ export class InteractiveMode {
2670
2683
  }
2671
2684
  }
2672
2685
  async getUserInput() {
2686
+ // Replay submissions queued while the loop was busy — but never during a
2687
+ // session rebuild (drainPendingSubmissions fires when it completes).
2688
+ if (!this.sessionTransitioning) {
2689
+ const queued = this.pendingSubmissions.shift();
2690
+ if (queued !== undefined) {
2691
+ return queued;
2692
+ }
2693
+ }
2673
2694
  return new Promise((resolve) => {
2674
2695
  this.onInputCallback = (text) => {
2675
2696
  this.onInputCallback = undefined;
@@ -2677,6 +2698,20 @@ export class InteractiveMode {
2677
2698
  };
2678
2699
  });
2679
2700
  }
2701
+ /**
2702
+ * Hand one queued submission to the waiting main loop, if any. Called when
2703
+ * a session transition completes; the loop drains the rest through
2704
+ * getUserInput() as it comes back around.
2705
+ */
2706
+ drainPendingSubmissions() {
2707
+ if (this.sessionTransitioning)
2708
+ return;
2709
+ const callback = this.onInputCallback;
2710
+ if (!callback || this.pendingSubmissions.length === 0)
2711
+ return;
2712
+ const next = this.pendingSubmissions.shift();
2713
+ callback(next);
2714
+ }
2680
2715
  rebuildChatFromMessages() {
2681
2716
  this.chatContainer.clear();
2682
2717
  const context = this.sessionManager.buildSessionContext();
@@ -4550,6 +4585,9 @@ export class InteractiveMode {
4550
4585
  this.loadingAnimation = undefined;
4551
4586
  }
4552
4587
  this.statusContainer.clear();
4588
+ // While the runtime rebuilds, submissions are queued (not sent into the
4589
+ // half-torn-down session) and replayed by the finally below.
4590
+ this.sessionTransitioning = true;
4553
4591
  try {
4554
4592
  const result = await this.runtimeHost.newSession();
4555
4593
  if (result.cancelled) {
@@ -4563,6 +4601,10 @@ export class InteractiveMode {
4563
4601
  catch (error) {
4564
4602
  await this.handleFatalRuntimeError("Failed to create session", error);
4565
4603
  }
4604
+ finally {
4605
+ this.sessionTransitioning = false;
4606
+ this.drainPendingSubmissions();
4607
+ }
4566
4608
  }
4567
4609
  handleDebugCommand() {
4568
4610
  const width = this.ui.terminal.columns;