@co0ontty/wand 1.60.5 → 1.61.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": "0c8dc16285dd049afbc98eb8a17204ed37cb33d4",
3
- "builtAt": "2026-06-13T10:07:33.053Z",
4
- "version": "1.60.5",
2
+ "commit": "676ee8ed1518463d31f33f9d6679d7700aac3eb7",
3
+ "builtAt": "2026-06-13T13:58:28.141Z",
4
+ "version": "1.61.0",
5
5
  "channel": "stable"
6
6
  }
@@ -165,7 +165,10 @@ function isClaudeSessionFileAvailable(cwd, claudeSessionId) {
165
165
  * interpretations and validate with existsSync, falling back to naive replacement.
166
166
  */
167
167
  function invertNormalizedProjectDir(dirName) {
168
- // The normalization is: path.resolve(cwd).replace(/\//g, "-")
168
+ // The normalization replaces every non-alphanumeric char with "-", so this
169
+ // inversion is best-effort: "-" most often maps back to "/", but may also be
170
+ // a literal "-", ".", or "_". We try "/" vs "-" per position and validate with
171
+ // existsSync; dots/underscores in the original path can't be recovered here.
169
172
  const naive = dirName.replace(/-/g, "/");
170
173
  if (existsSync(naive))
171
174
  return naive;
@@ -494,7 +497,11 @@ function listClaudeTaskIds() {
494
497
  }
495
498
  }
496
499
  function getClaudeProjectDir(cwd) {
497
- const normalized = path.resolve(cwd).replace(/\//g, "-");
500
+ // Claude Code encodes the project dir by replacing every non-alphanumeric
501
+ // character (slash, dot, underscore, etc.) with "-", not just "/". Mirroring
502
+ // only "/" misses paths like ".../vibe_coding/wand" → the scan looks in a
503
+ // directory Claude never wrote to, so the session ID is never discovered.
504
+ const normalized = path.resolve(cwd).replace(/[^a-zA-Z0-9]/g, "-");
498
505
  return path.join(os.homedir(), ".claude", "projects", normalized);
499
506
  }
500
507
  function getLatestClaudeTaskId(excludeIds) {
@@ -119,8 +119,6 @@ export declare class StructuredSessionManager {
119
119
  stop(id: string): SessionSnapshot;
120
120
  delete(id: string): void;
121
121
  private requireSession;
122
- private buildQueuedPlaceholderTurns;
123
- private buildRenderableMessages;
124
122
  private emitStructuredSnapshot;
125
123
  private flushNextQueuedMessage;
126
124
  private emit;
@@ -629,6 +629,21 @@ export class StructuredSessionManager {
629
629
  this.interruptedWith.set(id, prompt);
630
630
  if (opts.preserveQueue) {
631
631
  this.preserveQueueOnInterrupt.add(id);
632
+ // 「立即发送」排队条某一条:interrupt 把它作为新输入重发,但该条仍留在
633
+ // queuedMessages 里。必须在这里把它从队列摘掉一次,否则 preserveQueue 会
634
+ // 原样保留整条队列,待 interruptPrompt 跑完 flushNextQueuedMessage 会把它
635
+ // 当成普通排队再发一遍(重复发送)。客户端按 index 乐观删除,服务端这里
636
+ // 没有 index,只能按文本删第一处匹配(排队文本入队时已 trim,promote 重发
637
+ // 也会 trim,所以精确匹配可靠;重复文本极少见且语义等价)。
638
+ const queue = session.queuedMessages ?? [];
639
+ const removeAt = queue.indexOf(prompt);
640
+ if (removeAt !== -1) {
641
+ const trimmedQueue = queue.slice(0, removeAt).concat(queue.slice(removeAt + 1));
642
+ session = { ...session, queuedMessages: trimmedQueue };
643
+ this.sessions.set(id, session);
644
+ this.storage.saveSession(session);
645
+ this.emitStructuredSnapshot(session);
646
+ }
632
647
  }
633
648
  else {
634
649
  this.preserveQueueOnInterrupt.delete(id);
@@ -957,23 +972,13 @@ export class StructuredSessionManager {
957
972
  }
958
973
  return session;
959
974
  }
960
- buildQueuedPlaceholderTurns(session) {
961
- return (session.queuedMessages ?? []).map((text) => ({
962
- role: "user",
963
- content: [{ type: "text", text, __queued: true }],
964
- }));
965
- }
966
- buildRenderableMessages(session) {
967
- return [
968
- ...(session.messages ?? []),
969
- ...this.buildQueuedPlaceholderTurns(session),
970
- ];
971
- }
972
975
  emitStructuredSnapshot(session, eventType = "output") {
976
+ // 排队消息只通过 payload.queuedMessages 单独下发,由各端在消息卡片外的「排队条」
977
+ // 里纵向渲染——绝不再把它们当成 __queued 占位 turn 混进 messages 消息流里,否则会
978
+ // 和排队条重复显示(旧的「显示异常」根因)。
973
979
  const payload = buildStructuredOutputPayload(session);
974
980
  const data = {
975
981
  ...payload,
976
- messages: this.buildRenderableMessages(session),
977
982
  status: session.status,
978
983
  exitCode: session.exitCode,
979
984
  };