@ycodium-ai/plugin-im 0.2.3214 → 0.2.3216

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 (2) hide show
  1. package/dist/index.js +80 -39
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -126336,8 +126336,16 @@ var foldConclusionEvent = (state, name, data) => {
126336
126336
  const pending = conclusionDebtsOf(state);
126337
126337
  if (name === "conclusion-delivered") {
126338
126338
  const { [key]: _delivered, ...rest } = pending;
126339
- return { ...state, conclusions: rest };
126339
+ return {
126340
+ ...state,
126341
+ conclusions: rest,
126342
+ deliveredConclusions: keepNewest(
126343
+ { ...state.deliveredConclusions, [key]: true },
126344
+ CONCLUSION_DEBT_LIMIT
126345
+ )
126346
+ };
126340
126347
  }
126348
+ if (state.deliveredConclusions?.[key] === true) return state;
126341
126349
  const chatKey = data["chatKey"];
126342
126350
  const recordedAt = data["recordedAt"];
126343
126351
  if (typeof chatKey !== "string" || chatKey === "" || typeof recordedAt !== "string" || !Number.isFinite(Date.parse(recordedAt))) {
@@ -126354,13 +126362,13 @@ var foldConclusionEvent = (state, name, data) => {
126354
126362
  var makeConclusionLedger = (core) => {
126355
126363
  const inFlight = /* @__PURE__ */ new Set();
126356
126364
  const registering = /* @__PURE__ */ new Map();
126357
- const delivered = makeBoundedMap(CONCLUSION_DEBT_LIMIT);
126365
+ const unpersisted = /* @__PURE__ */ new Set();
126366
+ const delivered = (key) => core.state.deliveredConclusions?.[key] === true;
126358
126367
  let disposed = false;
126359
126368
  core.host.onDispose(() => {
126360
126369
  disposed = true;
126361
126370
  });
126362
126371
  const settle = (debt) => {
126363
- delivered.set(keyOf(debt.threadId, debt.userMessageId), true);
126364
126372
  core.commit("conclusion-delivered", {
126365
126373
  threadId: debt.threadId,
126366
126374
  userMessageId: debt.userMessageId
@@ -126378,15 +126386,25 @@ var makeConclusionLedger = (core) => {
126378
126386
  gate.resolve();
126379
126387
  };
126380
126388
  },
126381
- owe: (debt) => {
126389
+ /** 重放才传 recover;只对本次成功补出的欠账调度恢复,已有欠账交给原来的收尾路径。 */
126390
+ owe: async (debt, recover) => {
126391
+ const key = keyOf(debt.threadId, debt.userMessageId);
126392
+ if (delivered(key)) {
126393
+ core.host.log.info("chat skipped a conclusion debt already delivered", { ...debt });
126394
+ return;
126395
+ }
126382
126396
  const pending = conclusionDebtsOf(core.state);
126383
- if (Object.keys(pending).length >= CONCLUSION_DEBT_LIMIT && pending[keyOf(debt.threadId, debt.userMessageId)] === void 0) {
126397
+ const added = pending[key] === void 0 || unpersisted.has(key);
126398
+ if (Object.keys(pending).length >= CONCLUSION_DEBT_LIMIT && pending[key] === void 0) {
126384
126399
  core.host.log.warn("chat dropped its oldest conclusion debt at capacity", {
126385
126400
  oldest: Object.values(pending)[0],
126386
126401
  limit: CONCLUSION_DEBT_LIMIT
126387
126402
  });
126388
126403
  }
126389
- core.commit("conclusion-owed", { ...debt });
126404
+ if (added) unpersisted.add(key);
126405
+ await core.commitDurably("conclusion-owed", { ...debt });
126406
+ unpersisted.delete(key);
126407
+ if (added) await recover?.(debt);
126390
126408
  },
126391
126409
  forTurn: async (threadId, turnId = null) => {
126392
126410
  await Promise.all(registering.get(threadId) ?? []);
@@ -126395,17 +126413,19 @@ var makeConclusionLedger = (core) => {
126395
126413
  const key = userMessageId === void 0 ? void 0 : keyOf(threadId, userMessageId);
126396
126414
  return {
126397
126415
  debt: key === void 0 ? void 0 : conclusionDebtsOf(core.state)[key],
126398
- handled: key !== void 0 && (delivered.get(key) === true || inFlight.has(key)),
126416
+ handled: key !== void 0 && (delivered(key) || inFlight.has(key)),
126399
126417
  execution
126400
126418
  };
126401
126419
  },
126402
126420
  deliver: async (debt, send) => {
126403
126421
  const key = keyOf(debt.threadId, debt.userMessageId);
126404
- if (disposed || inFlight.has(key) || conclusionDebtsOf(core.state)[key] === void 0)
126422
+ if (disposed || delivered(key) || inFlight.has(key) || conclusionDebtsOf(core.state)[key] === void 0)
126405
126423
  return false;
126406
126424
  inFlight.add(key);
126407
126425
  try {
126408
- const sent = await send(() => conclusionDebtsOf(core.state)[key] !== void 0);
126426
+ const sent = await send(
126427
+ () => !delivered(key) && conclusionDebtsOf(core.state)[key] !== void 0
126428
+ );
126409
126429
  if (sent) settle(debt);
126410
126430
  return sent;
126411
126431
  } finally {
@@ -126414,7 +126434,7 @@ var makeConclusionLedger = (core) => {
126414
126434
  },
126415
126435
  discard: (debt) => {
126416
126436
  const key = keyOf(debt.threadId, debt.userMessageId);
126417
- if (!disposed && !inFlight.has(key) && conclusionDebtsOf(core.state)[key] !== void 0) {
126437
+ if (!disposed && !delivered(key) && !inFlight.has(key) && conclusionDebtsOf(core.state)[key] !== void 0) {
126418
126438
  settle(debt);
126419
126439
  }
126420
126440
  }
@@ -134339,16 +134359,18 @@ var makeImCore = (input) => {
134339
134359
  }
134340
134360
  );
134341
134361
  let persisting = Promise.resolve();
134342
- const commit = (name, data) => {
134362
+ const commitDurably = (name, data) => {
134343
134363
  state = foldImEvent(state, name, data);
134344
- persisting = persisting.then(
134364
+ const saved = persisting.then(
134345
134365
  () => host.events.append({ name, aggregate: { kind: "plugin", id: input.pluginId }, data })
134346
- ).then(
134347
- () => void 0,
134348
- (error) => {
134349
- host.log.warn("chat could not save its state", { name, error: describeError(error) });
134350
- }
134351
- );
134366
+ ).then(() => void 0);
134367
+ persisting = saved.catch((error) => {
134368
+ host.log.warn("chat could not save its state", { name, error: describeError(error) });
134369
+ });
134370
+ return saved;
134371
+ };
134372
+ const commit = (name, data) => {
134373
+ void commitDurably(name, data);
134352
134374
  };
134353
134375
  const bindChat = (chatKey, threadId) => {
134354
134376
  commit("chat-updated", { chatKey, threadId });
@@ -134414,6 +134436,7 @@ var makeImCore = (input) => {
134414
134436
  },
134415
134437
  ready,
134416
134438
  commit,
134439
+ commitDurably,
134417
134440
  bindChat,
134418
134441
  outbound,
134419
134442
  deliver,
@@ -134885,6 +134908,7 @@ import { projectOrNull } from "@ycodium-ai/plugin-api";
134885
134908
 
134886
134909
  // src/inboxProcessing.ts
134887
134910
  var processingFor = (store, rowId, entry, retry) => ({
134911
+ replayed: entry.replayed === true,
134888
134912
  get entry() {
134889
134913
  return store.get(rowId, entry.key);
134890
134914
  },
@@ -135046,7 +135070,7 @@ var makeInboxReplay = (core, currentBot, state, enqueueForChat, resumeMessage, c
135046
135070
  await resumeMessage(
135047
135071
  bot,
135048
135072
  latest.message === entry.message ? message : restoreInbound(core.adapterFor(bot.platform), latest.message),
135049
- latest,
135073
+ { ...latest, replayed: true },
135050
135074
  chatId
135051
135075
  );
135052
135076
  });
@@ -146630,7 +146654,7 @@ var enqueueConclusion = (core, ledger, binding, debt, send) => core.outbound(
146630
146654
 
146631
146655
  // src/conclusionRecovery.ts
146632
146656
  var MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
146633
- var recoverConclusions = async (core, ledger, delivery, failures) => {
146657
+ var makeConclusionRecovery = (core, ledger, delivery, failures) => {
146634
146658
  let disposed = false;
146635
146659
  core.host.onDispose(() => {
146636
146660
  disposed = true;
@@ -146641,15 +146665,15 @@ var recoverConclusions = async (core, ledger, delivery, failures) => {
146641
146665
  error: describeError(error)
146642
146666
  });
146643
146667
  };
146644
- await core.ready;
146645
- for (const debt of Object.values(conclusionDebtsOf(core.state))) {
146668
+ const recoverConclusion = async (debt) => {
146669
+ await core.ready;
146646
146670
  if (disposed) return;
146647
146671
  try {
146648
146672
  const execution = await core.host.projections.getThreadExecution(debt.threadId);
146649
146673
  if (disposed) return;
146650
146674
  if (execution === null) {
146651
146675
  ledger.discard(debt);
146652
- continue;
146676
+ return;
146653
146677
  }
146654
146678
  const latest = execution.latestTurn;
146655
146679
  if (latest?.userMessageId !== debt.userMessageId) {
@@ -146657,16 +146681,16 @@ var recoverConclusions = async (core, ledger, delivery, failures) => {
146657
146681
  ...debt
146658
146682
  });
146659
146683
  ledger.discard(debt);
146660
- continue;
146684
+ return;
146661
146685
  }
146662
- if (latest.state === "running" || execution.session?.activeTurnId != null) continue;
146686
+ if (latest.state === "running" || execution.session?.activeTurnId != null) return;
146663
146687
  if (latest.completedAt !== null && Date.parse(latest.completedAt) < Date.now() - MAX_AGE_MS) {
146664
146688
  core.host.log.info("chat discarded a conclusion older than seven days", { ...debt });
146665
146689
  ledger.discard(debt);
146666
- continue;
146690
+ return;
146667
146691
  }
146668
146692
  const binding = core.bindingForChatKey(debt.chatKey);
146669
- if (binding === void 0) continue;
146693
+ if (binding === void 0) return;
146670
146694
  enqueueConclusion(core, ledger, binding, debt, async (owed) => {
146671
146695
  try {
146672
146696
  if (latest.state === "error") {
@@ -146689,7 +146713,15 @@ var recoverConclusions = async (core, ledger, delivery, failures) => {
146689
146713
  } catch (error) {
146690
146714
  couldNotRecover(debt, error);
146691
146715
  }
146692
- }
146716
+ };
146717
+ const recoverConclusions = async () => {
146718
+ await core.ready;
146719
+ for (const debt of Object.values(conclusionDebtsOf(core.state))) {
146720
+ if (disposed) return;
146721
+ await recoverConclusion(debt);
146722
+ }
146723
+ };
146724
+ return { recoverConclusion, recoverConclusions };
146693
146725
  };
146694
146726
 
146695
146727
  // src/notificationTargets.ts
@@ -146713,7 +146745,13 @@ var makeNotifications = (core, deps) => {
146713
146745
  const { takeWorking } = deps;
146714
146746
  const { turnCards } = deps.replyCards;
146715
146747
  const { failures, conclusions, delivery } = deps;
146716
- void recoverConclusions(core, conclusions, delivery, failures);
146748
+ const { recoverConclusion, recoverConclusions } = makeConclusionRecovery(
146749
+ core,
146750
+ conclusions,
146751
+ delivery,
146752
+ failures
146753
+ );
146754
+ void recoverConclusions();
146717
146755
  const projectByThread = /* @__PURE__ */ new Map();
146718
146756
  const projectOfThread = async (threadId) => {
146719
146757
  const known = projectByThread.get(threadId);
@@ -146831,7 +146869,7 @@ var makeNotifications = (core, deps) => {
146831
146869
  const rememberThreadProject = (threadId, projectId) => {
146832
146870
  projectByThread.set(threadId, projectId);
146833
146871
  };
146834
- return { rememberThreadProject };
146872
+ return { rememberThreadProject, recoverConclusion };
146835
146873
  };
146836
146874
 
146837
146875
  // src/panelCommands.ts
@@ -148211,7 +148249,7 @@ var teamGoalRequestId = (binding, messageId) => {
148211
148249
  return NodeCrypto5.createHash("sha256").update(identity2).digest("hex");
148212
148250
  };
148213
148251
  var makeTeamGoals = (core) => {
148214
- const { host, t, deliver, commit } = core;
148252
+ const { host, t, deliver, commitDurably } = core;
148215
148253
  const hasRosterFor = async (binding) => {
148216
148254
  try {
148217
148255
  const roster = await host.plugins.invoke({
@@ -148255,13 +148293,16 @@ var makeTeamGoals = (core) => {
148255
148293
  throw new Error("team startGoal returned an invalid result");
148256
148294
  }
148257
148295
  topicRoot?.confirmConsumed();
148258
- commit("team-goal-started", { chatKey: chatKeyOf(binding), threadId: result2.leadThreadId });
148259
148296
  goal = { leadThreadId: result2.leadThreadId, leadName: result2.leadName };
148260
148297
  } catch (error) {
148261
148298
  host.log.warn("chat could not start the team goal", { error: describeError(error) });
148262
148299
  await deliver(binding, t("team.startFailed"));
148263
148300
  return null;
148264
148301
  }
148302
+ await commitDurably("team-goal-started", {
148303
+ chatKey: chatKeyOf(binding),
148304
+ threadId: goal.leadThreadId
148305
+ });
148265
148306
  await accepted?.(goal.leadThreadId);
148266
148307
  await deliver(
148267
148308
  binding,
@@ -149581,6 +149622,7 @@ var makeTurns = (core, deps) => {
149581
149622
  const startTurn = async (binding, message, accepted, inbox) => {
149582
149623
  const chatKey = chatKeyOf(binding);
149583
149624
  const text4 = message.text;
149625
+ const replayed = inbox?.replayed === true || (inbox?.entry?.attempts ?? 0) > 0;
149584
149626
  const threadId = inbox?.entry?.threadId ?? await ensureThread(binding, message);
149585
149627
  if (threadId === null) {
149586
149628
  await inbox?.complete();
@@ -149686,12 +149728,10 @@ var makeTurns = (core, deps) => {
149686
149728
  if (!dispatched) return null;
149687
149729
  topicRoot?.confirmConsumed();
149688
149730
  if (intentAction?.kind !== "steer") {
149689
- deps.conclusions.owe({
149690
- chatKey,
149691
- threadId,
149692
- userMessageId,
149693
- recordedAt: (/* @__PURE__ */ new Date()).toISOString()
149694
- });
149731
+ await deps.conclusions.owe(
149732
+ { chatKey, threadId, userMessageId, recordedAt: (/* @__PURE__ */ new Date()).toISOString() },
149733
+ replayed ? deps.recoverConclusion : void 0
149734
+ );
149695
149735
  }
149696
149736
  } finally {
149697
149737
  registered();
@@ -152463,7 +152503,7 @@ var makeWecomAppAdapter = (deps) => {
152463
152503
  // src/index.ts
152464
152504
  var definition = {
152465
152505
  id: "im",
152466
- apiVersion: 21,
152506
+ apiVersion: 22,
152467
152507
  // 第二个参数只给插件自己的测试夹具:换掉文件 IO 与派发重试的等待。宿主只传 ctx。
152468
152508
  activate: async (ctx, testing = {}) => {
152469
152509
  const { dispatchSleep } = testing;
@@ -152592,6 +152632,7 @@ var definition = {
152592
152632
  const turns = makeTurns(core, {
152593
152633
  conclusions,
152594
152634
  attachments: inboundAttachments,
152635
+ recoverConclusion: notifications.recoverConclusion,
152595
152636
  queueFlow: interactions.queueFlow,
152596
152637
  rememberThreadProject: notifications.rememberThreadProject,
152597
152638
  noteInboundUserMessage: webSync.noteInboundUserMessage,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ycodium-ai/plugin-im",
3
- "version": "0.2.3214",
3
+ "version": "0.2.3216",
4
4
  "description": "Talk to your agents from Telegram, WeCom, Lark, or WeChat (experimental).",
5
5
  "keywords": [
6
6
  "im",
@@ -32,7 +32,7 @@
32
32
  "markdown-it": "^15.0.2",
33
33
  "react": "19.2.6",
34
34
  "vite-plus": "0.2.2",
35
- "@ycodium-ai/plugin-api": "0.2.3214"
35
+ "@ycodium-ai/plugin-api": "0.2.3216"
36
36
  },
37
37
  "ycodium": {
38
38
  "plugin": "./dist/index.js",