@co0ontty/wand 4.45.1 → 4.46.0

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.
@@ -1,6 +1,6 @@
1
1
  {
2
- "commit": "1a79f31b6f38f7a7a2a83ce85c78db126b9f5f47",
3
- "builtAt": "2026-08-22T07:39:53.924Z",
4
- "version": "4.45.1",
2
+ "commit": "bb2b4c9d6db5b2498473bfeec29dfdc96df2b2f0",
3
+ "builtAt": "2026-08-22T13:32:33.756Z",
4
+ "version": "4.46.0",
5
5
  "channel": "stable"
6
6
  }
@@ -104,6 +104,11 @@ export declare class ClaudePtyBridge extends EventEmitter {
104
104
  getRawOutput(): string;
105
105
  getClaudeSessionId(): string | null;
106
106
  isPermissionBlocked(): boolean;
107
+ /**
108
+ * Per-turn busy signal: true while an assistant response is streaming.
109
+ * Mirrors chatState.phase so ProcessManager can expose ptyBusy on the snapshot.
110
+ */
111
+ isResponding(): boolean;
107
112
  getPermissionState(): PermissionState;
108
113
  /**
109
114
  * Set the PTY write function for sending approval input.
@@ -225,6 +225,13 @@ export class ClaudePtyBridge extends EventEmitter {
225
225
  isPermissionBlocked() {
226
226
  return this.permissionState.isBlocked;
227
227
  }
228
+ /**
229
+ * Per-turn busy signal: true while an assistant response is streaming.
230
+ * Mirrors chatState.phase so ProcessManager can expose ptyBusy on the snapshot.
231
+ */
232
+ isResponding() {
233
+ return !this._exited && this.chatState.phase === "responding";
234
+ }
228
235
  getPermissionState() {
229
236
  return this.permissionState;
230
237
  }
@@ -730,6 +730,7 @@ export class ProcessManager extends EventEmitter {
730
730
  initializeClaudeBridge(record, initialOutput) {
731
731
  if (record.provider !== "claude" || !record.providerCliActive)
732
732
  return;
733
+ record.ptyBusy = false;
733
734
  record.ptyBridge?.removeAllListeners();
734
735
  record.ptyBridge = new ClaudePtyBridge({
735
736
  sessionId: record.id,
@@ -789,6 +790,7 @@ export class ProcessManager extends EventEmitter {
789
790
  current.providerCliActive = false;
790
791
  current.providerCliExitCode = exitCode;
791
792
  }
793
+ current.ptyBusy = false;
792
794
  current.pendingEscalation = null;
793
795
  current.ptyPermissionBlocked = false;
794
796
  this.captureClaudeSessionId(current, { allowTimeWindowFallback: true });
@@ -1568,6 +1570,7 @@ export class ProcessManager extends EventEmitter {
1568
1570
  record.providerCliExitCode = exitCode;
1569
1571
  record.providerShellMarker = null;
1570
1572
  record.ptyLaunchMarkerToken = null;
1573
+ record.ptyBusy = false;
1571
1574
  if (record.claudeTaskDiscoveryTimer) {
1572
1575
  clearTimeout(record.claudeTaskDiscoveryTimer);
1573
1576
  record.claudeTaskDiscoveryTimer = null;
@@ -1634,6 +1637,7 @@ export class ProcessManager extends EventEmitter {
1634
1637
  record.providerCliActive = false;
1635
1638
  record.providerShellMarker = null;
1636
1639
  record.ptyLaunchMarkerToken = null;
1640
+ record.ptyBusy = false;
1637
1641
  // Kill any running child process (from JSON chat turns)
1638
1642
  if (record.childProcess) {
1639
1643
  record.childProcess.kill();
@@ -1817,6 +1821,7 @@ export class ProcessManager extends EventEmitter {
1817
1821
  provider: record.provider,
1818
1822
  providerCliActive: record.providerCliActive,
1819
1823
  providerCliExitCode: record.providerCliExitCode,
1824
+ ptyBusy: record.ptyBridge ? record.ptyBridge.isResponding() : record.ptyBusy === true,
1820
1825
  runner: "pty",
1821
1826
  command: record.command,
1822
1827
  cwd: record.cwd,
@@ -2185,6 +2190,17 @@ export class ProcessManager extends EventEmitter {
2185
2190
  const rawMessages = record.ptyBridge?.getMessages() ?? [];
2186
2191
  const isStreaming = record.status === "running";
2187
2192
  const bridgeData = event.data;
2193
+ // 每轮忙碌信号:turn 开始置 true,回复结束清 false。只在翻转时广播,
2194
+ // 避免流式期间每个 chunk 都发 status 事件。
2195
+ const responding = bridgeData?.isResponding === true;
2196
+ if (record.ptyBusy !== responding) {
2197
+ record.ptyBusy = responding;
2198
+ this.emitEvent({
2199
+ type: "status",
2200
+ sessionId: event.sessionId,
2201
+ data: { ptyBusy: responding },
2202
+ });
2203
+ }
2188
2204
  const data = {
2189
2205
  permissionBlocked: this.isPermissionBlocked(record),
2190
2206
  };
@@ -24,6 +24,7 @@ function sessionBase(snapshot) {
24
24
  provider: snapshot.provider,
25
25
  providerCliActive: snapshot.providerCliActive,
26
26
  providerCliExitCode: snapshot.providerCliExitCode,
27
+ ptyBusy: snapshot.ptyBusy === true,
27
28
  runner: snapshot.runner,
28
29
  command: snapshot.command,
29
30
  cwd: snapshot.cwd,
package/dist/types.d.ts CHANGED
@@ -519,6 +519,13 @@ export interface SessionSnapshot {
519
519
  providerCliActive?: boolean;
520
520
  /** Provider CLI exit status; separate from exitCode, which belongs to the persistent PTY shell. */
521
521
  providerCliExitCode?: number | null;
522
+ /**
523
+ * PTY 会话本轮是否正在生成回复(provider CLI busy)。语义对齐 structured 的
524
+ * structuredState.inFlight:turn 开始置 true,回复结束/进程退出清 false。
525
+ * 运行时信号,不持久化,服务重启后视为 false。目前仅 Claude PTY(bridge)能精确判定;
526
+ * 其余 provider 不产生该信号(undefined),客户端应回落到旧行为。
527
+ */
528
+ ptyBusy?: boolean;
522
529
  runner?: SessionRunner;
523
530
  command: string;
524
531
  cwd: string;