@khalilgharbaoui/opencode-claude-code-plugin 0.61.0 → 0.61.1

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/index.js CHANGED
@@ -3808,23 +3808,36 @@ import { createHash } from "crypto";
3808
3808
  var fingerprints = /* @__PURE__ */ new Map();
3809
3809
  var fingerprintSeq = 0;
3810
3810
  var MAX_FORK_FINGERPRINTS = 64;
3811
- var DIGEST_VERSION = 2;
3811
+ var DIGEST_VERSION = 3;
3812
3812
  var DCP_MESSAGE_ID_TAG = /<dcp-message-id(?:\s[^>]*)?>[^<]*<\/dcp-message-id>/g;
3813
3813
  var DCP_COMPACT_REF_LINE = /^@(?:\d+|b\d+|blocked)@(?: \[[^\]\n]*\])?$/;
3814
- function withoutDcpRefs(text) {
3815
- let out = text.includes("<dcp-message-id") ? text.replace(DCP_MESSAGE_ID_TAG, "") : text;
3814
+ var DCP_SYSTEM_REMINDER_BLOCK = /<dcp-system-reminder>[\s\S]*?<\/dcp-system-reminder>/g;
3815
+ function withoutDcpRefs(text, version) {
3816
+ let out = text;
3817
+ let removed = false;
3818
+ if (version >= 3 && out.includes("<dcp-system-reminder")) {
3819
+ out = out.replace(DCP_SYSTEM_REMINDER_BLOCK, "");
3820
+ removed = true;
3821
+ }
3822
+ if (out.includes("<dcp-message-id")) {
3823
+ out = out.replace(DCP_MESSAGE_ID_TAG, "");
3824
+ removed = true;
3825
+ }
3816
3826
  for (; ; ) {
3817
3827
  const trimmed = out.trimEnd();
3818
- if (!trimmed.endsWith("@") && !trimmed.endsWith("]")) return out;
3828
+ if (!trimmed.endsWith("@") && !trimmed.endsWith("]")) break;
3819
3829
  const lineStart = trimmed.lastIndexOf("\n") + 1;
3820
- if (!DCP_COMPACT_REF_LINE.test(trimmed.slice(lineStart))) return out;
3830
+ if (!DCP_COMPACT_REF_LINE.test(trimmed.slice(lineStart))) break;
3821
3831
  out = trimmed.slice(0, lineStart);
3832
+ removed = true;
3822
3833
  }
3834
+ if (version < 3 || !removed) return out;
3835
+ return out.replace(/\n{3,}/g, "\n\n").trim();
3823
3836
  }
3824
3837
  function hashPart(hash, part, version) {
3825
3838
  const p = part;
3826
3839
  const type = typeof p?.type === "string" ? p.type : "unknown";
3827
- const content = (text) => version >= 2 ? withoutDcpRefs(text) : text;
3840
+ const content = (text) => version >= 2 ? withoutDcpRefs(text, version) : text;
3828
3841
  switch (type) {
3829
3842
  case "text":
3830
3843
  hash.update("text\0");
@@ -3840,7 +3853,9 @@ function hashPart(hash, part, version) {
3840
3853
  hash.update("result\0");
3841
3854
  hash.update(String(p?.toolName ?? ""));
3842
3855
  hash.update("\0");
3843
- hash.update(stableJson(p?.output, version >= 2 ? withoutDcpRefs : void 0));
3856
+ hash.update(
3857
+ stableJson(p?.output, version >= 2 ? (text) => withoutDcpRefs(text, version) : void 0)
3858
+ );
3844
3859
  break;
3845
3860
  case "file":
3846
3861
  case "image": {
@@ -3888,7 +3903,7 @@ function messageDigest(msg, version) {
3888
3903
  hash.update("\0");
3889
3904
  if (typeof msg.content === "string") {
3890
3905
  hash.update("text\0");
3891
- hash.update(version >= 2 ? withoutDcpRefs(msg.content) : msg.content);
3906
+ hash.update(version >= 2 ? withoutDcpRefs(msg.content, version) : msg.content);
3892
3907
  hash.update("");
3893
3908
  } else if (Array.isArray(msg.content)) {
3894
3909
  for (const part of msg.content) hashPart(hash, part, version);
@@ -7429,6 +7444,7 @@ function findForeignAccountSibling(opts) {
7429
7444
  if (modelSiblingSignature(key, providers) !== signature) return void 0;
7430
7445
  const account = sessionKeyAccount(key, providers);
7431
7446
  if (account === void 0 || account === ownAccount) return void 0;
7447
+ if (opts.only && !opts.only(account)) return void 0;
7432
7448
  return { siblingKey: key, account };
7433
7449
  };
7434
7450
  for (const key of opts.extraKeys ?? []) {
@@ -9130,6 +9146,7 @@ var PLUGIN_LOG_MESSAGES = /* @__PURE__ */ new Set([
9130
9146
  "no configured account could take this turn; it ends here",
9131
9147
  "no proxyTools entry was recognised; nothing will be proxied this turn",
9132
9148
  "no stdout after envelope write; respawning claude process to resume conversation",
9149
+ "not replaying what this claude session missed: the conversation continued on an account in another group",
9133
9150
  "opencode 2 event subscription ended; deleted sessions keep their claude process until idle eviction, and stopped turns keep their proxy calls until the next message",
9134
9151
  "opencode's stored OAuth token for this MCP server has expired, so the bridged server carries no credential; re-authenticate it in opencode",
9135
9152
  "pending proxy call arrived after stream close; rejecting",
@@ -9267,6 +9284,7 @@ var BUNDLE_DATA_ALLOWLIST = {
9267
9284
  historyLength: "count",
9268
9285
  matchedMessages: "count",
9269
9286
  messages: "count",
9287
+ userMessages: "count",
9270
9288
  inputTokens: "count",
9271
9289
  lastTextLength: "count",
9272
9290
  lines: "count",
@@ -18445,30 +18463,45 @@ var ClaudeCodeLanguageModel = class {
18445
18463
  carried: conversationOnTarget
18446
18464
  });
18447
18465
  }
18448
- let accountGroupNote = null;
18449
- if (!compactionMode && groups && accountProviders.size > 0 && includeHistoryContext && failoverAnswer?.kind !== "switch") {
18450
- const foreign = findForeignAccountSibling({
18466
+ let crossGroupAccountRead = false;
18467
+ let crossGroupAccountValue;
18468
+ const crossGroupAccount = () => {
18469
+ if (crossGroupAccountRead) return crossGroupAccountValue;
18470
+ crossGroupAccountRead = true;
18471
+ if (compactionMode || !groups || accountProviders.size === 0) return void 0;
18472
+ if (failoverAnswer?.kind === "switch") return void 0;
18473
+ crossGroupAccountValue = findForeignAccountSibling({
18451
18474
  sessionKey: sk,
18452
18475
  accountProviders,
18453
18476
  // The live process's own view, so the guard holds with
18454
18477
  // `resumeAfterRestart: false`, where the store is never written.
18455
- extraKeys: listClaudeSessionKeys()
18478
+ extraKeys: listClaudeSessionKeys(),
18479
+ only: (account) => !accountsShareGroup(sourceAccount, account, groups)
18480
+ })?.account;
18481
+ return crossGroupAccountValue;
18482
+ };
18483
+ const accountGroupNoteFor = (from) => formatAccountGroupNote({
18484
+ sourceAccount: from,
18485
+ sourceGroup: accountGroup(from, groups),
18486
+ targetAccount: sourceAccount,
18487
+ targetGroup: accountGroup(sourceAccount, groups)
18488
+ });
18489
+ const logAnotherAccountGroup = (from) => {
18490
+ log.notice("starting fresh on this account: it is in another account group", {
18491
+ sessionKey: sk,
18492
+ reason: "another-account-group",
18493
+ account: sourceAccount,
18494
+ from,
18495
+ group: accountGroup(sourceAccount, groups)
18456
18496
  });
18457
- if (foreign && !accountsShareGroup(sourceAccount, foreign.account, groups)) {
18497
+ };
18498
+ let accountGroupNote = null;
18499
+ if (includeHistoryContext) {
18500
+ const from = crossGroupAccount();
18501
+ if (from) {
18458
18502
  includeHistoryContext = false;
18459
- accountGroupNote = formatAccountGroupNote({
18460
- sourceAccount: foreign.account,
18461
- sourceGroup: accountGroup(foreign.account, groups),
18462
- targetAccount: sourceAccount,
18463
- targetGroup: accountGroup(sourceAccount, groups)
18464
- });
18465
- log.notice("starting fresh on this account: it is in another account group", {
18466
- sessionKey: sk,
18467
- reason: "another-account-group",
18468
- account: sourceAccount,
18469
- from: foreign.account,
18470
- group: accountGroup(sourceAccount, groups)
18471
- });
18503
+ accountGroupNote = accountGroupNoteFor(from);
18504
+ logAnotherAccountGroup(from);
18472
18505
  }
18473
18506
  }
18474
18507
  let forkFromClaudeSessionId;
@@ -18618,28 +18651,52 @@ var ClaudeCodeLanguageModel = class {
18618
18651
  });
18619
18652
  }
18620
18653
  const conversationChange = !compactionMode && !includeHistoryContext && failoverAnswer?.kind !== "switch" && !accountGroupNote && (!!getClaudeSessionId(sk) || !!getActiveProcess(sk)) ? classifyConversationChange(sk, filterSideQuestionHistory(options.prompt)) : null;
18621
- const missed = conversationChange?.kind === "missed" ? conversationChange : null;
18622
- if (missed) {
18623
- log.notice("replaying the messages this claude session missed: the conversation continued under another session key", {
18624
- sessionKey: sk,
18625
- messages: missed.messages.length,
18626
- userMessages: missed.userMessages
18627
- });
18654
+ let missed = null;
18655
+ if (conversationChange?.kind === "missed") {
18656
+ const from = crossGroupAccount();
18657
+ if (from) {
18658
+ log.notice(
18659
+ "not replaying what this claude session missed: the conversation continued on an account in another group",
18660
+ {
18661
+ sessionKey: sk,
18662
+ reason: "another-account-group",
18663
+ account: sourceAccount,
18664
+ from,
18665
+ group: accountGroup(sourceAccount, groups),
18666
+ messages: conversationChange.messages.length,
18667
+ userMessages: conversationChange.userMessages
18668
+ }
18669
+ );
18670
+ } else {
18671
+ missed = conversationChange;
18672
+ log.notice("replaying the messages this claude session missed: the conversation continued under another session key", {
18673
+ sessionKey: sk,
18674
+ messages: missed.messages.length,
18675
+ userMessages: missed.userMessages
18676
+ });
18677
+ }
18628
18678
  }
18629
18679
  let rewoundNote = null;
18630
18680
  if (conversationChange?.kind === "rewound") {
18631
18681
  await deleteActiveProcessAndWait(sk);
18632
18682
  deleteClaudeSessionId(sk);
18633
- includeHistoryContext = true;
18634
- replayReason = "history-rewound";
18635
- log.notice("replaying the conversation as text: the thread was edited or undone", {
18636
- sessionKey: sk,
18637
- reason: "history-rewound",
18638
- sharedMessages: conversationChange.sharedMessages,
18639
- removedMessages: conversationChange.removedMessages,
18640
- removedUserMessages: conversationChange.removedUserMessages
18641
- });
18642
- if (mode !== "generate") rewoundNote = formatConversationRewoundNote();
18683
+ const from = crossGroupAccount();
18684
+ if (from) {
18685
+ includeHistoryContext = false;
18686
+ accountGroupNote = accountGroupNote ?? accountGroupNoteFor(from);
18687
+ logAnotherAccountGroup(from);
18688
+ } else {
18689
+ includeHistoryContext = true;
18690
+ replayReason = "history-rewound";
18691
+ log.notice("replaying the conversation as text: the thread was edited or undone", {
18692
+ sessionKey: sk,
18693
+ reason: "history-rewound",
18694
+ sharedMessages: conversationChange.sharedMessages,
18695
+ removedMessages: conversationChange.removedMessages,
18696
+ removedUserMessages: conversationChange.removedUserMessages
18697
+ });
18698
+ if (mode !== "generate") rewoundNote = formatConversationRewoundNote();
18699
+ }
18643
18700
  }
18644
18701
  if (this.config.forkSessions === true && !compactionMode) {
18645
18702
  recordForkFingerprint(sk, options.prompt, cliPath);