larkin 0.4.11 → 0.4.12

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/dist/app/cli.mjs CHANGED
@@ -87,7 +87,7 @@ Reset replaces one idle, zero-backlog Runtime session. Recover is an explicit op
87
87
  larkin pi-auth logout <provider> [--agent <App ID>]
88
88
  Show non-sensitive official Pi credential metadata or remove one target provider credential.`,
89
89
  comment: `Usage: larkin comment reply --message-id <doc_comment_message_id> --text '<reply>' --json
90
- Reply once, as the Runtime-bound Bot, to the exact cloud-document comment locator supplied by canonical Inbox.`,
90
+ Reply as the Runtime-bound Bot to the exact cloud-document comment locator supplied by canonical Inbox. Retrying the same body is idempotent; a different body appends a follow-up reply to the same comment.`,
91
91
  telemetry: `Usage: larkin telemetry <status|export|import|flush>
92
92
  Inspect the durable local trace queue, move an offline bundle, or upload queued OTLP traces.`,
93
93
  };
@@ -304,18 +304,22 @@ function runCommentReply(argv, privateEnv, io, dependencies, store) {
304
304
  if (!store.inboxTargetIsFresh(targetKey))
305
305
  throw new Error("comment reply 需要先 poll 当前 document-comment target 的最新 Inbox 消息");
306
306
  const digest = createHash("sha256").update(input.text).digest("hex");
307
+ const ledgerKey = `${input.messageId}::${digest}`;
307
308
  const claim = store.mutateJson("freshnessState", { version: 1, cursors: {} }, (state) => {
308
309
  state.document_comment_replies ??= {};
309
- const prior = state.document_comment_replies[input.messageId];
310
- if (prior?.status === "sent" && prior.digest === digest)
310
+ const legacy = state.document_comment_replies[input.messageId];
311
+ const prior = state.document_comment_replies[ledgerKey]
312
+ ?? (legacy?.digest === digest ? legacy : undefined);
313
+ if (prior?.status === "sent")
311
314
  return "sent";
312
- if (prior?.status === "sending" && prior.digest === digest)
315
+ const messageEntries = Object.entries(state.document_comment_replies)
316
+ .filter(([key]) => key === input.messageId || key.startsWith(`${input.messageId}::`));
317
+ if (messageEntries.some(([, entry]) => entry.status === "sending"))
313
318
  return "ambiguous";
314
- if (prior && prior.status !== "failed" && prior.digest !== digest)
315
- return "conflict";
316
- state.document_comment_replies[input.messageId] = { digest, status: "sending", updated_at: new Date().toISOString() };
317
- const keys = Object.keys(state.document_comment_replies);
318
- for (const stale of keys.slice(0, Math.max(0, keys.length - 512)))
319
+ state.document_comment_replies[ledgerKey] = { digest, status: "sending", updated_at: new Date().toISOString() };
320
+ const terminalKeys = Object.keys(state.document_comment_replies)
321
+ .filter((key) => state.document_comment_replies[key]?.status !== "sending");
322
+ for (const stale of terminalKeys.slice(0, Math.max(0, terminalKeys.length - 512)))
319
323
  delete state.document_comment_replies[stale];
320
324
  return "ready";
321
325
  });
@@ -324,9 +328,7 @@ function runCommentReply(argv, privateEnv, io, dependencies, store) {
324
328
  return 0;
325
329
  }
326
330
  if (claim === "ambiguous")
327
- throw new Error("comment reply 上次调用结果不明确,已 fail-closed 以避免重复评论;请由用户检查原评论线程");
328
- if (claim === "conflict")
329
- throw new Error("comment reply 已为同一 Inbox 消息提交不同正文,拒绝覆盖或重复发送");
331
+ throw new Error("comment reply 上次调用结果不明确,已 fail-closed 以避免重复评论;请勿改写正文重试,请由用户检查原评论线程");
330
332
  const nativeArgs = target.topLevel
331
333
  ? [
332
334
  "drive", "file.comments", "create_v2",
@@ -353,7 +355,7 @@ function runCommentReply(argv, privateEnv, io, dependencies, store) {
353
355
  if (terminalStatus) {
354
356
  store.mutateJson("freshnessState", { version: 1, cursors: {} }, (state) => {
355
357
  state.document_comment_replies ??= {};
356
- state.document_comment_replies[input.messageId] = {
358
+ state.document_comment_replies[ledgerKey] = {
357
359
  digest,
358
360
  status: terminalStatus,
359
361
  updated_at: new Date().toISOString(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "larkin",
3
- "version": "0.4.11",
3
+ "version": "0.4.12",
4
4
  "private": false,
5
5
  "larkinPackageRole": "npm-published",
6
6
  "files": [