pilotswarm 0.5.4 → 0.5.5

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pilotswarm",
3
- "version": "0.5.4",
3
+ "version": "0.5.5",
4
4
  "description": "PilotSwarm application package: terminal UI, browser portal + Web API server, and MCP server — one install, three bins.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -77,7 +77,7 @@
77
77
  "hono": "^4.12.10",
78
78
  "ink": "^6.8.0",
79
79
  "jose": "^6.2.2",
80
- "pilotswarm-sdk": "^0.5.4",
80
+ "pilotswarm-sdk": "^0.5.5",
81
81
  "react": "^19.2.4",
82
82
  "react-dom": "^19.2.4",
83
83
  "ws": "^8.18.2"
@@ -300,7 +300,12 @@ function buildSessionMergePatch(previousSession, nextSession) {
300
300
  changed = true;
301
301
  }
302
302
 
303
- if (nextSession.pendingQuestion === undefined && previousSession?.pendingQuestion && nextSession.status !== "input_required") {
303
+ if (nextSession.pendingQuestion === undefined && previousSession?.pendingQuestion && nextSession.status !== "input_required"
304
+ && !isSameOrOlderSessionUpdate(previousSession, nextSession)) {
305
+ // Only a genuinely newer update may clear a pending question. A stale or
306
+ // in-flight detail-sync that raced the input_required_started event (and
307
+ // so still reports the pre-question status with no pendingQuestion) must
308
+ // not wipe the question the user is looking at.
304
309
  patch.pendingQuestion = null;
305
310
  changed = true;
306
311
  }
@@ -3026,6 +3031,28 @@ export class PilotSwarmUiController {
3026
3031
  sessionId,
3027
3032
  history: appendEventToHistory(existing, event),
3028
3033
  });
3034
+ // The input_required_started event carries the full question payload and
3035
+ // reaches us on the live event stream — well ahead of the slower
3036
+ // customStatus detail-sync (scheduleSessionDetailSync below). Set
3037
+ // pendingQuestion + status synchronously so an answer typed the moment the
3038
+ // question appears takes the direct sendAnswer path instead of being
3039
+ // misrouted into the outbox queue, where it would sit until a later send
3040
+ // flushed it. The eventual detail-sync reconciles to the authoritative
3041
+ // customStatus.
3042
+ if (event.eventType === "session.input_required_started" && event.data?.question) {
3043
+ this.dispatch({
3044
+ type: "sessions/merged",
3045
+ session: {
3046
+ sessionId,
3047
+ status: "input_required",
3048
+ pendingQuestion: {
3049
+ question: event.data.question,
3050
+ choices: Array.isArray(event.data.choices) ? event.data.choices : undefined,
3051
+ allowFreeform: event.data.allowFreeform ?? true,
3052
+ },
3053
+ },
3054
+ });
3055
+ }
3029
3056
  this.reconcileOutboxAgainstEvent(sessionId, event);
3030
3057
  const derivedModel = extractSessionModelFromEvent(event);
3031
3058
  const currentSession = this.getState().sessions.byId[sessionId] || { sessionId };