lark-remote 0.5.19 → 0.5.21

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 (136) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/bridge/approval-actions.d.ts +1 -1
  3. package/dist/bridge/approval-actions.js +1 -1
  4. package/dist/bridge/bash-run.d.ts +71 -0
  5. package/dist/bridge/bash-run.js +217 -0
  6. package/dist/bridge/compact.d.ts +155 -0
  7. package/dist/bridge/compact.js +450 -0
  8. package/dist/bridge/final-usage.js +4 -4
  9. package/dist/bridge/inbound-media.js +72 -46
  10. package/dist/bridge/index.d.ts +106 -153
  11. package/dist/bridge/index.js +400 -1000
  12. package/dist/bridge/job-watch.d.ts +68 -0
  13. package/dist/bridge/job-watch.js +146 -0
  14. package/dist/bridge/queue-manager.d.ts +3 -3
  15. package/dist/bridge/queue-manager.js +10 -29
  16. package/dist/card/approval-render.d.ts +2 -2
  17. package/dist/card/approval-render.js +141 -130
  18. package/dist/card/card-budget.js +123 -98
  19. package/dist/card/card-helpers.d.ts +3 -3
  20. package/dist/card/card-helpers.js +6 -6
  21. package/dist/card/final-answer-file.js +1 -1
  22. package/dist/card/run-renderer.d.ts +3 -3
  23. package/dist/card/run-renderer.js +114 -159
  24. package/dist/card/run-state.d.ts +1 -15
  25. package/dist/card/run-state.js +358 -292
  26. package/dist/card/tool-render.d.ts +1 -1
  27. package/dist/card/tool-render.js +21 -17
  28. package/dist/card/usage-format.d.ts +22 -7
  29. package/dist/card/usage-format.js +119 -100
  30. package/dist/cli.js +15 -3
  31. package/dist/clone.js +2 -2
  32. package/dist/common/text-width.js +36 -24
  33. package/dist/common/tool-summary.js +132 -90
  34. package/dist/config/codex-config.js +130 -106
  35. package/dist/config/index.d.ts +16 -2
  36. package/dist/config/index.js +23 -8
  37. package/dist/connector/index.js +6 -6
  38. package/dist/error-classification.js +3 -2
  39. package/dist/inbound/placeholder.d.ts +1 -1
  40. package/dist/inbound/placeholder.js +1 -1
  41. package/dist/index.js +387 -281
  42. package/dist/logger/index.js +6 -6
  43. package/dist/message-handlers.d.ts +0 -5
  44. package/dist/message-handlers.js +254 -237
  45. package/dist/model-catalog.d.ts +2 -2
  46. package/dist/model-catalog.js +3 -8
  47. package/dist/platform/identity.js +1 -1
  48. package/dist/platform/path.d.ts +1 -1
  49. package/dist/platform/path.js +1 -1
  50. package/dist/platform/sleep-blocker.js +1 -1
  51. package/dist/platform/terminator-win32.js +2 -1
  52. package/dist/router/commands/ls.d.ts +3 -0
  53. package/dist/router/commands/ls.js +256 -175
  54. package/dist/router/commands/order.js +184 -159
  55. package/dist/router/commands/resume.js +190 -152
  56. package/dist/router/commands/ws.js +219 -174
  57. package/dist/router/config/dsh.d.ts +4 -8
  58. package/dist/router/config/dsh.js +3 -10
  59. package/dist/router/config/kimi.js +1 -1
  60. package/dist/router/config/types.d.ts +1 -1
  61. package/dist/router/config-diff.js +1 -1
  62. package/dist/router/index.d.ts +56 -11
  63. package/dist/router/index.js +401 -391
  64. package/dist/runner/bash/runner.js +2 -4
  65. package/dist/runner/claude/session.d.ts +1 -1
  66. package/dist/runner/claude/session.js +6 -4
  67. package/dist/runner/codex/app-server/runner.d.ts +9 -2
  68. package/dist/runner/codex/app-server/runner.js +30 -25
  69. package/dist/runner/codex/app-server/translator.d.ts +2 -5
  70. package/dist/runner/codex/app-server/translator.js +291 -238
  71. package/dist/runner/common/acp/acp-approval.d.ts +1 -1
  72. package/dist/runner/common/acp/acp-approval.js +1 -1
  73. package/dist/runner/common/acp/base-acp-runner.d.ts +5 -2
  74. package/dist/runner/common/acp/base-acp-runner.js +26 -65
  75. package/dist/runner/common/acp/base-translator.d.ts +12 -2
  76. package/dist/runner/common/acp/base-translator.js +50 -26
  77. package/dist/runner/common/acp/protocol-types.d.ts +1 -1
  78. package/dist/runner/common/acp/protocol-types.js +2 -2
  79. package/dist/runner/common/connection-based-runner.d.ts +32 -1
  80. package/dist/runner/common/connection-based-runner.js +32 -2
  81. package/dist/runner/common/jsonl-stream.js +154 -187
  82. package/dist/runner/common/jsonrpc/client.d.ts +29 -0
  83. package/dist/runner/common/jsonrpc/client.js +43 -12
  84. package/dist/runner/common/jsonrpc/connection-manager.d.ts +2 -2
  85. package/dist/runner/common/jsonrpc/connection-manager.js +4 -4
  86. package/dist/runner/common/spawning-runner.d.ts +6 -1
  87. package/dist/runner/common/spawning-runner.js +9 -4
  88. package/dist/runner/common/turn-started.d.ts +8 -0
  89. package/dist/runner/common/turn-started.js +11 -0
  90. package/dist/runner/dsh/approval.js +84 -51
  91. package/dist/runner/dsh/catalog-probe.d.ts +17 -0
  92. package/dist/runner/dsh/catalog-probe.js +10 -0
  93. package/dist/runner/dsh/client.d.ts +7 -11
  94. package/dist/runner/dsh/client.js +356 -289
  95. package/dist/runner/dsh/exit-cancel.d.ts +2 -2
  96. package/dist/runner/dsh/exit-cancel.js +2 -2
  97. package/dist/runner/dsh/inflight.d.ts +1 -1
  98. package/dist/runner/dsh/inflight.js +1 -1
  99. package/dist/runner/dsh/mux-stream.js +28 -8
  100. package/dist/runner/dsh/runner.d.ts +44 -4
  101. package/dist/runner/dsh/runner.js +296 -199
  102. package/dist/runner/dsh/translator.d.ts +1 -31
  103. package/dist/runner/dsh/translator.js +180 -178
  104. package/dist/runner/index.d.ts +1 -1
  105. package/dist/runner/kimi/acp/runner.d.ts +1 -2
  106. package/dist/runner/kimi/acp/runner.js +82 -46
  107. package/dist/runner/kimi/acp/translator.d.ts +1 -1
  108. package/dist/runner/kimi/acp/translator.js +3 -4
  109. package/dist/runner/opencode/acp/error-monitor.js +5 -5
  110. package/dist/runner/opencode/acp/runner.d.ts +2 -2
  111. package/dist/runner/opencode/acp/runner.js +4 -4
  112. package/dist/runner/pi/rpc/client.js +4 -13
  113. package/dist/runner/pi/rpc/protocol-types.d.ts +1 -1
  114. package/dist/runner/pi/rpc/protocol-types.js +1 -1
  115. package/dist/runner/pi/rpc/runner.d.ts +3 -0
  116. package/dist/runner/pi/rpc/runner.js +27 -42
  117. package/dist/runner/pi/rpc/translator.js +61 -60
  118. package/dist/runner/types.d.ts +2 -2
  119. package/dist/runner/types.js +1 -1
  120. package/dist/session/claude/sessions.d.ts +45 -0
  121. package/dist/session/claude/sessions.js +160 -122
  122. package/dist/session/codex/rollout-reader.js +181 -182
  123. package/dist/session/common/throw-session-list-error.d.ts +10 -0
  124. package/dist/session/common/throw-session-list-error.js +16 -0
  125. package/dist/session/dsh/sessions.js +291 -235
  126. package/dist/session/kimi/sessions.d.ts +40 -8
  127. package/dist/session/kimi/sessions.js +373 -301
  128. package/dist/session/opencode/sessions.d.ts +142 -1
  129. package/dist/session/opencode/sessions.js +378 -321
  130. package/dist/session/pi/sessions.js +4 -5
  131. package/dist/session/session-store.d.ts +9 -1
  132. package/dist/session/session-store.js +99 -99
  133. package/dist/update/version-check.js +2 -1
  134. package/dist/workspace/index.d.ts +1 -1
  135. package/dist/workspace/index.js +1 -1
  136. package/package.json +1 -1
@@ -3,6 +3,7 @@ import path from 'node:path';
3
3
  import os from 'node:os';
4
4
  import { findJsonlLine } from '../common/jsonl.js';
5
5
  import { scanJsonlOnce, tailOffsetAfter, scanTailEvents } from '../common/two-pass.js';
6
+ import { throwSessionListError } from '../common/throw-session-list-error.js';
6
7
  import { extractContentBlocks } from '../common/content-blocks.js';
7
8
  import { UsageAccumulator, contextWindowOccupancy, cumulativeUsageFields, } from '../common/usage-accumulator.js';
8
9
  import { isStale } from '../common/constants.js';
@@ -63,7 +64,7 @@ function extractPiText(content) {
63
64
  * dominates displayTitle and squeezes out the user's actual words.
64
65
  * Replace the whole `<skill>…</skill>` block with `skill:x`, preserving any
65
66
  * trailing real text. Falls back to the original text when no skill block
66
- * is present (or the block is malformed/unclosed). Regression 2026-07-13.
67
+ * is present (or the block is malformed/unclosed).
67
68
  */
68
69
  function compressSkillInjection(text) {
69
70
  return text
@@ -193,7 +194,7 @@ function piScalarScan(filePath) {
193
194
  const text = extractPiText(msg.content);
194
195
  // Compress skill-injection bodies so the "最近输入" label shows what
195
196
  // the user invoked (skill:x) + any trailing real input, not a
196
- // truncated SKILL.md head. Regression 2026-07-13.
197
+ // truncated SKILL.md head.
197
198
  if (text)
198
199
  lastUserText = compressSkillInjection(text);
199
200
  }
@@ -367,9 +368,7 @@ export class PiSessionReader {
367
368
  if (err.code === 'ENOENT') {
368
369
  return [];
369
370
  }
370
- getLogger().error(`[pi-session-reader] listSessions failed: ${err}`);
371
- const msg = err instanceof Error ? err.message : String(err);
372
- throw new Error(`pi session list 读取失败: ${msg}`, { cause: err });
371
+ throwSessionListError('pi', err);
373
372
  }
374
373
  const sessions = [];
375
374
  for (const f of files) {
@@ -1,4 +1,10 @@
1
1
  import type { AgentKind } from '../agent-kinds.js';
2
+ /**
3
+ * session reader 共用的失败留痕(claude stat / kimi realpath):ENOENT 是两次
4
+ * 查询之间的正常竞态,静默;其余 errno 必须 debug 留痕,否则「文件不可读」
5
+ * 会被误判成「会话不活跃」。文案由调用方按场景给出,逐字保持。
6
+ */
7
+ export declare function logNonEnoentDebug(err: unknown, message: (errText: string) => string): void;
2
8
  interface SessionEntry {
3
9
  /** Session IDs per agent kind (Map for in-memory, plain object for persistence). */
4
10
  sessions: Map<AgentKind, string>;
@@ -30,7 +36,7 @@ export declare class SessionStore {
30
36
  private sessions;
31
37
  private readonly persistPath?;
32
38
  /**
33
- * 进程内会话代际(2026-08-09 /new 被在途 run init 写回撤销事故):
39
+ * 进程内会话代际(防 /new 被在途 run init 写回撤销):
34
40
  * 每次「用户意图移动 session 指针」+1。system.init 写回通道不 bump。
35
41
  * Bridge 在 run 启动时快照 epoch,init 写回前比较——不一致说明 /new、
36
42
  * /cd、/resume 等在 run 在途时移动了指针,该 run 的写回是 stale 的,丢弃。
@@ -73,6 +79,8 @@ export declare class SessionStore {
73
79
  getArrivalSessionId(userId: string, agent: AgentKind): string | undefined;
74
80
  /** Set the arrival baseline for a specific agent ('' explicitly clears the arrival baseline) */
75
81
  setArrivalSessionId(userId: string, agent: AgentKind, sessionId: string): void;
82
+ /** previous/arrival 两类 setter 共用的单一实现(合并完全重复块)。 */
83
+ private writeSessionId;
76
84
  /** Set cwd for a user, clearing all sessionIds (§9.1) */
77
85
  setCwd(userId: string, cwd: string): void;
78
86
  /** Get cwd for a user, or undefined if no session */
@@ -1,6 +1,90 @@
1
1
  import fs from 'node:fs';
2
2
  import { getLogger } from '../logger/index.js';
3
3
  import { atomicWriteJson } from '../persistence/atomic-write.js';
4
+ /**
5
+ * session reader 共用的失败留痕(claude stat / kimi realpath):ENOENT 是两次
6
+ * 查询之间的正常竞态,静默;其余 errno 必须 debug 留痕,否则「文件不可读」
7
+ * 会被误判成「会话不活跃」。文案由调用方按场景给出,逐字保持。
8
+ */
9
+ export function logNonEnoentDebug(err, message) {
10
+ if (err.code === 'ENOENT')
11
+ return;
12
+ getLogger().debug(message(err?.message ?? String(err)));
13
+ }
14
+ /** 四类 getter 共用的单一实现:entry 缺失 / 空串 → undefined。 */
15
+ function readSessionId(entry, key, agent) {
16
+ if (!entry)
17
+ return undefined;
18
+ const value = entry[key].get(agent);
19
+ if (!value)
20
+ return undefined;
21
+ return value;
22
+ }
23
+ /** 四个 session 字段缺一即损坏记录(整条跳过,cwd 允许缺失)。 */
24
+ function hasRequiredSessionFields(entry) {
25
+ return (!!entry.sessions && !!entry.previousSessions && !!entry.arrivalSessions && !!entry.sessionCwds);
26
+ }
27
+ /** 只保留 truthy 值(sessions / previousSessions / sessionCwds 的口径)。 */
28
+ function truthySessionMap(record) {
29
+ const map = new Map();
30
+ for (const [agent, sid] of Object.entries(record)) {
31
+ if (sid)
32
+ map.set(agent, sid);
33
+ }
34
+ return map;
35
+ }
36
+ /** 全保留(arrivalSessions 的 '' 是显式清空基线,必须跨重启存活)。 */
37
+ function fullSessionMap(record) {
38
+ const map = new Map();
39
+ for (const [agent, sid] of Object.entries(record)) {
40
+ map.set(agent, sid);
41
+ }
42
+ return map;
43
+ }
44
+ /** 单条持久化记录 → 内存 entry;损坏 / 完全空记录返回 undefined。 */
45
+ function parsePersistedEntry(data) {
46
+ if (typeof data !== 'object' || data === null)
47
+ return undefined;
48
+ const entry = data;
49
+ // 四个 session 字段缺失 = 损坏记录,整条跳过。cwd 允许缺失:
50
+ // 全新用户(未 /cd)先切 agent 时 previous/arrival 停车位已落盘,
51
+ // cwd 尚为空——不能因 cwd 缺失把停车位整条丢掉
52
+ // (anchor_r7_parked_previous_survives_rebuild_without_cwd)。
53
+ if (!hasRequiredSessionFields(entry))
54
+ return undefined;
55
+ const sessions = truthySessionMap(entry.sessions);
56
+ const previousSessions = truthySessionMap(entry.previousSessions);
57
+ const arrivalSessions = fullSessionMap(entry.arrivalSessions);
58
+ const sessionCwds = truthySessionMap(entry.sessionCwds);
59
+ // Persist any user that has state: cwd set, or any meaningful
60
+ // sessions/previousSessions value, or any arrival baseline entry
61
+ // ('' arrivals are meaningful). Fully empty records are skipped.
62
+ const hasCwd = !!entry.cwd && entry.cwd.length > 0;
63
+ if (hasCwd || sessions.size > 0 || previousSessions.size > 0 || arrivalSessions.size > 0) {
64
+ return {
65
+ sessions,
66
+ previousSessions,
67
+ sessionCwds,
68
+ arrivalSessions,
69
+ cwd: entry.cwd ?? '',
70
+ };
71
+ }
72
+ return undefined;
73
+ }
74
+ /** 损坏现场留痕:日志 + 改名保留(原文件继续躺着会重复告警、丢排障证据)。 */
75
+ function preserveCorruptStore(persistPath, err) {
76
+ getLogger().warn(`[session] persisted session store corrupted (${persistPath ?? '(memory)'}), ignoring:`, err);
77
+ if (persistPath) {
78
+ const brokenPath = `${persistPath}.corrupt-${Date.now()}`;
79
+ try {
80
+ fs.renameSync(persistPath, brokenPath);
81
+ getLogger().warn(`[session] moved corrupt store to ${brokenPath}`);
82
+ }
83
+ catch (renameErr) {
84
+ getLogger().warn('[session] failed to preserve corrupt store:', renameErr);
85
+ }
86
+ }
87
+ }
4
88
  /**
5
89
  * Per-user session store. Persists cwd + per-agent sessions to disk so that
6
90
  * the last cwd AND the last-used sessionId per agent are restored after
@@ -20,7 +104,7 @@ export class SessionStore {
20
104
  sessions = new Map();
21
105
  persistPath;
22
106
  /**
23
- * 进程内会话代际(2026-08-09 /new 被在途 run init 写回撤销事故):
107
+ * 进程内会话代际(防 /new 被在途 run init 写回撤销):
24
108
  * 每次「用户意图移动 session 指针」+1。system.init 写回通道不 bump。
25
109
  * Bridge 在 run 启动时快照 epoch,init 写回前比较——不一致说明 /new、
26
110
  * /cd、/resume 等在 run 在途时移动了指针,该 run 的写回是 stale 的,丢弃。
@@ -104,20 +188,11 @@ export class SessionStore {
104
188
  }
105
189
  /** Get previous sessionId for a specific agent (stored when switching away) */
106
190
  getPreviousSessionId(userId, agent) {
107
- const entry = this.sessions.get(userId);
108
- if (!entry)
109
- return undefined;
110
- const sessionId = entry.previousSessions.get(agent);
111
- if (!sessionId)
112
- return undefined;
113
- return sessionId;
191
+ return readSessionId(this.sessions.get(userId), 'previousSessions', agent);
114
192
  }
115
193
  /** Set previous sessionId for a specific agent (for potential restore when switching back) */
116
194
  setPreviousSessionId(userId, agent, sessionId) {
117
- this.mutateEntry(userId, (entry) => {
118
- entry.previousSessions.set(agent, sessionId);
119
- return entry;
120
- });
195
+ this.writeSessionId(userId, 'previousSessions', agent, sessionId);
121
196
  }
122
197
  /** Clear previous sessionId for a specific agent */
123
198
  clearPreviousSessionId(userId, agent) {
@@ -128,18 +203,16 @@ export class SessionStore {
128
203
  }
129
204
  /** Get the arrival baseline sessionId for a specific agent ('' and missing → undefined) */
130
205
  getArrivalSessionId(userId, agent) {
131
- const entry = this.sessions.get(userId);
132
- if (!entry)
133
- return undefined;
134
- const sessionId = entry.arrivalSessions.get(agent);
135
- if (!sessionId)
136
- return undefined;
137
- return sessionId;
206
+ return readSessionId(this.sessions.get(userId), 'arrivalSessions', agent);
138
207
  }
139
208
  /** Set the arrival baseline for a specific agent ('' explicitly clears the arrival baseline) */
140
209
  setArrivalSessionId(userId, agent, sessionId) {
210
+ this.writeSessionId(userId, 'arrivalSessions', agent, sessionId);
211
+ }
212
+ /** previous/arrival 两类 setter 共用的单一实现(合并完全重复块)。 */
213
+ writeSessionId(userId, key, agent, sessionId) {
141
214
  this.mutateEntry(userId, (entry) => {
142
- entry.arrivalSessions.set(agent, sessionId);
215
+ entry[key].set(agent, sessionId);
143
216
  return entry;
144
217
  });
145
218
  }
@@ -165,13 +238,7 @@ export class SessionStore {
165
238
  }
166
239
  /** Get sessionId for a specific agent, or undefined if no session or sessionId is empty */
167
240
  getSessionId(userId, agent = 'claude') {
168
- const entry = this.sessions.get(userId);
169
- if (!entry)
170
- return undefined;
171
- const sessionId = entry.sessions.get(agent);
172
- if (!sessionId)
173
- return undefined;
174
- return sessionId;
241
+ return readSessionId(this.sessions.get(userId), 'sessions', agent);
175
242
  }
176
243
  /** Set sessionId for a specific agent, optionally with cwd */
177
244
  setSessionId(userId, agent, sessionId, cwd) {
@@ -196,13 +263,7 @@ export class SessionStore {
196
263
  }
197
264
  /** Get sessionCwd for a specific agent, or undefined if not set */
198
265
  getSessionCwd(userId, agent = 'claude') {
199
- const entry = this.sessions.get(userId);
200
- if (!entry)
201
- return undefined;
202
- const sessionCwd = entry.sessionCwds.get(agent);
203
- if (!sessionCwd)
204
- return undefined;
205
- return sessionCwd;
266
+ return readSessionId(this.sessions.get(userId), 'sessionCwds', agent);
206
267
  }
207
268
  /** Set sessionId and sessionCwd for a specific agent, without touching cwd */
208
269
  setSessionIdAndSessionCwd(userId, agent, sessionId, sessionCwd) {
@@ -224,75 +285,14 @@ export class SessionStore {
224
285
  const parsed = JSON.parse(raw);
225
286
  if (typeof parsed === 'object' && parsed !== null) {
226
287
  for (const [userId, data] of Object.entries(parsed)) {
227
- if (typeof data === 'object' && data !== null) {
228
- const entry = data;
229
- // 四个 session 字段缺失 = 损坏记录,整条跳过。cwd 允许缺失:
230
- // 全新用户(未 /cd)先切 agent 时 previous/arrival 停车位已落盘,
231
- // cwd 尚为空——不能因 cwd 缺失把停车位整条丢掉
232
- // (anchor_r7_parked_previous_survives_rebuild_without_cwd)。
233
- if (!entry.sessions ||
234
- !entry.previousSessions ||
235
- !entry.arrivalSessions ||
236
- !entry.sessionCwds) {
237
- continue;
238
- }
239
- const sessions = new Map();
240
- for (const [agent, sid] of Object.entries(entry.sessions)) {
241
- if (sid) {
242
- sessions.set(agent, sid);
243
- }
244
- }
245
- const previousSessions = new Map();
246
- for (const [agent, sid] of Object.entries(entry.previousSessions)) {
247
- if (sid) {
248
- previousSessions.set(agent, sid);
249
- }
250
- }
251
- const arrivalSessions = new Map();
252
- for (const [agent, sid] of Object.entries(entry.arrivalSessions)) {
253
- // '' entries are meaningful: explicit "cleared arrival" must
254
- // survive a restart instead of being re-defaulted.
255
- arrivalSessions.set(agent, sid);
256
- }
257
- const sessionCwds = new Map();
258
- for (const [agent, scwd] of Object.entries(entry.sessionCwds)) {
259
- if (scwd) {
260
- sessionCwds.set(agent, scwd);
261
- }
262
- }
263
- // Persist any user that has state: cwd set, or any meaningful
264
- // sessions/previousSessions value, or any arrival baseline entry
265
- // ('' arrivals are meaningful). Fully empty records are skipped.
266
- const hasCwd = !!entry.cwd && entry.cwd.length > 0;
267
- if (hasCwd ||
268
- sessions.size > 0 ||
269
- previousSessions.size > 0 ||
270
- arrivalSessions.size > 0) {
271
- this.sessions.set(userId, {
272
- sessions,
273
- previousSessions,
274
- sessionCwds,
275
- arrivalSessions,
276
- cwd: entry.cwd ?? '',
277
- });
278
- }
279
- }
288
+ const entry = parsePersistedEntry(data);
289
+ if (entry)
290
+ this.sessions.set(userId, entry);
280
291
  }
281
292
  }
282
293
  }
283
294
  catch (err) {
284
- getLogger().warn(`[session] persisted session store corrupted (${this.persistPath ?? '(memory)'}), ignoring:`, err);
285
- // 改名保留现场:原文件继续原地躺着会让下次启动重复告警,也丢掉排障证据。
286
- if (this.persistPath) {
287
- const brokenPath = `${this.persistPath}.corrupt-${Date.now()}`;
288
- try {
289
- fs.renameSync(this.persistPath, brokenPath);
290
- getLogger().warn(`[session] moved corrupt store to ${brokenPath}`);
291
- }
292
- catch (renameErr) {
293
- getLogger().warn('[session] failed to preserve corrupt store:', renameErr);
294
- }
295
- }
295
+ preserveCorruptStore(this.persistPath, err);
296
296
  }
297
297
  }
298
298
  autoPersist() {
@@ -99,7 +99,8 @@ function readCache(cachePath) {
99
99
  return null;
100
100
  return cached;
101
101
  }
102
- catch {
102
+ catch (err) {
103
+ getLogger().debug('[update] version cache unreadable, refetching:', err);
103
104
  return null;
104
105
  }
105
106
  }
@@ -11,7 +11,7 @@ export interface WorkspaceEntry {
11
11
  * mid-write cannot leave a truncated JSON file. On load, a corrupt file
12
12
  * is treated as empty (with a warning) so the lark-remote can still start.
13
13
  *
14
- * lastUsedAt 语义(2026-08-19 语义对齐):保存(save)与使用(use/touch)
14
+ * lastUsedAt 语义:保存(save)与使用(use/touch)
15
15
  * 都会把时间戳更新为当前时间。save 内部调用 touch,保证「最近使用」排序
16
16
  * 对新保存的 cwd 同样生效(新条目应排在列表最前,而非沉底)。
17
17
  * 同一毫秒内连续操作时 touch 会用 max+1 保证严格递增,避免 Date.now 相同
@@ -10,7 +10,7 @@ import { getLogger } from '../logger/index.js';
10
10
  * mid-write cannot leave a truncated JSON file. On load, a corrupt file
11
11
  * is treated as empty (with a warning) so the lark-remote can still start.
12
12
  *
13
- * lastUsedAt 语义(2026-08-19 语义对齐):保存(save)与使用(use/touch)
13
+ * lastUsedAt 语义:保存(save)与使用(use/touch)
14
14
  * 都会把时间戳更新为当前时间。save 内部调用 touch,保证「最近使用」排序
15
15
  * 对新保存的 cwd 同样生效(新条目应排在列表最前,而非沉底)。
16
16
  * 同一毫秒内连续操作时 touch 会用 max+1 保证严格递增,避免 Date.now 相同
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lark-remote",
3
- "version": "0.5.19",
3
+ "version": "0.5.21",
4
4
  "description": "Feishu (Lark) private-chat bridge to local coding agents — Claude Code / Codex / opencode / pi / kimi, with live-streaming CardKit 2.0 cards",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",