@xgjktech/xg_cwork_im 1.18.4 → 1.18.5

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,7 @@
1
1
  /**
2
2
  * 单轮模型覆盖:在 dispatch 前登记,由 before_model_resolve 消费。
3
- * 弥补 replyOptions.modelOverride 在部分自定义 provider 上解析失败时被 autoFallback 覆盖的问题。
3
+ * 仅当当前候选与用户点名模型一致时生效;主候选被跳过进入 fallback 时不得覆盖回原模型。
4
+ * 主通道仍以 replyOptions.modelOverride 为准,本机制只在候选一致时补一次显式覆盖。
4
5
  */
5
6
  export interface PendingPerMessageModel {
6
7
  /** 原始 model ref,如 xgjk-newapi/MiniMax-M2.7-Cloud */
@@ -11,6 +12,12 @@ export interface PendingPerMessageModel {
11
12
  export declare function normalizeModelRefRaw(raw: string): string;
12
13
  /** 将 provider/model 或别名拆成 hook 可用的字段 */
13
14
  export declare function splitModelRef(raw: string): PendingPerMessageModel | undefined;
15
+ /**
16
+ * 单轮覆盖只在「当前候选 == 用户点名的目标模型」时生效。
17
+ * 主模型被冷却/额度跳过进入 fallback 后,当前候选已不是目标模型,
18
+ * 钩子不得再把 fallback 候选改回目标模型。目标未带 provider 时仅比对 model。
19
+ */
20
+ export declare function matchesPendingCandidate(ctxProvider: string | undefined, ctxModel: string | undefined, pending: PendingPerMessageModel): boolean;
14
21
  export declare function setPendingPerMessageModel(sessionKey: string, raw: string): PendingPerMessageModel | undefined;
15
22
  export declare function takePendingPerMessageModel(sessionKey: string | undefined): PendingPerMessageModel | undefined;
16
23
  export declare function clearPendingPerMessageModel(sessionKey: string | undefined): void;
@@ -1 +1 @@
1
- {"version":3,"file":"per-message-model-pending.d.ts","sourceRoot":"","sources":["../../src/per-message-model-pending.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,WAAW,sBAAsB;IACnC,oDAAoD;IACpD,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACjB;AAID,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wCAAwC;AACxC,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,sBAAsB,GAAG,SAAS,CAW7E;AAED,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,sBAAsB,GAAG,SAAS,CAK7G;AAED,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,sBAAsB,GAAG,SAAS,CAM7G;AAED,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAGhF;AAED,8BAA8B;AAC9B,wBAAgB,8BAA8B,IAAI,IAAI,CAErD"}
1
+ {"version":3,"file":"per-message-model-pending.d.ts","sourceRoot":"","sources":["../../src/per-message-model-pending.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,MAAM,WAAW,sBAAsB;IACnC,oDAAoD;IACpD,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACjB;AAID,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wCAAwC;AACxC,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,sBAAsB,GAAG,SAAS,CAW7E;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACnC,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,OAAO,EAAE,sBAAsB,GAChC,OAAO,CAST;AAED,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,sBAAsB,GAAG,SAAS,CAK7G;AAED,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,sBAAsB,GAAG,SAAS,CAM7G;AAED,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAGhF;AAED,8BAA8B;AAC9B,wBAAgB,8BAA8B,IAAI,IAAI,CAErD"}
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * 单轮模型覆盖:在 dispatch 前登记,由 before_model_resolve 消费。
3
- * 弥补 replyOptions.modelOverride 在部分自定义 provider 上解析失败时被 autoFallback 覆盖的问题。
3
+ * 仅当当前候选与用户点名模型一致时生效;主候选被跳过进入 fallback 时不得覆盖回原模型。
4
+ * 主通道仍以 replyOptions.modelOverride 为准,本机制只在候选一致时补一次显式覆盖。
4
5
  */
5
6
  import { getSharedMap } from "./process-shared-store.js";
6
7
  const pendingBySessionKey = getSharedMap("pending-per-message-model");
@@ -22,6 +23,21 @@ export function splitModelRef(raw) {
22
23
  }
23
24
  return { raw: normalized, model: normalized };
24
25
  }
26
+ /**
27
+ * 单轮覆盖只在「当前候选 == 用户点名的目标模型」时生效。
28
+ * 主模型被冷却/额度跳过进入 fallback 后,当前候选已不是目标模型,
29
+ * 钩子不得再把 fallback 候选改回目标模型。目标未带 provider 时仅比对 model。
30
+ */
31
+ export function matchesPendingCandidate(ctxProvider, ctxModel, pending) {
32
+ const candidateProvider = (ctxProvider ?? "").trim().toLowerCase();
33
+ const candidateModel = (ctxModel ?? "").trim();
34
+ const targetProvider = (pending.provider ?? "").trim().toLowerCase();
35
+ const targetModel = pending.model.trim();
36
+ if (candidateModel !== targetModel) {
37
+ return false;
38
+ }
39
+ return targetProvider === "" || candidateProvider === targetProvider;
40
+ }
25
41
  export function setPendingPerMessageModel(sessionKey, raw) {
26
42
  const parsed = splitModelRef(raw);
27
43
  if (!parsed)
@@ -1 +1 @@
1
- {"version":3,"file":"per-message-model-pending.js","sourceRoot":"","sources":["../../src/per-message-model-pending.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AASzD,MAAM,mBAAmB,GAAG,YAAY,CAAiC,2BAA2B,CAAC,CAAC;AAEtG,MAAM,UAAU,oBAAoB,CAAC,GAAW;IAC5C,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AACzD,CAAC;AAED,wCAAwC;AACxC,MAAM,UAAU,aAAa,CAAC,GAAW;IACrC,MAAM,UAAU,GAAG,oBAAoB,CAAC,GAAG,CAAC,CAAC;IAC7C,IAAI,CAAC,UAAU;QAAE,OAAO,SAAS,CAAC;IAClC,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACZ,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;QACnD,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACjD,IAAI,CAAC,QAAQ,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAC;QAC1C,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAChD,CAAC;IACD,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,UAAkB,EAAE,GAAW;IACrE,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,mBAAmB,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAC5C,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,UAA8B;IACrE,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE;QAAE,OAAO,SAAS,CAAC;IAC1C,MAAM,OAAO,GAAG,mBAAmB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACpD,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAC/B,mBAAmB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACvC,OAAO,OAAO,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,UAA8B;IACtE,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE;QAAE,OAAO;IAChC,mBAAmB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;AAC3C,CAAC;AAED,8BAA8B;AAC9B,MAAM,UAAU,8BAA8B;IAC1C,mBAAmB,CAAC,KAAK,EAAE,CAAC;AAChC,CAAC"}
1
+ {"version":3,"file":"per-message-model-pending.js","sourceRoot":"","sources":["../../src/per-message-model-pending.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,8 @@
1
1
  /**
2
- * before_model_resolve:消费 IM ext.ai_model 登记的单轮模型,优先于 session autoFallback 探测。
2
+ * before_model_resolve:消费 IM ext.ai_model 登记的单轮模型。
3
+ * 守卫语义:仅当「当前正在解析的候选 == 用户点名的目标模型」时才应用覆盖。
4
+ * 初选候选因冷却/额度在外层被跳过进入 fallback 后,当前候选已不是目标模型,
5
+ * 覆盖必须静默放弃,否则会把降级候选(如 newapi-xgjk/back-model)改回冷却中的主模型。
3
6
  */
4
7
  import type { OpenClawPluginApi } from "openclaw/plugin-sdk/channel-plugin-common";
5
8
  export declare function registerPerMessageModelHook(api: OpenClawPluginApi): void;
@@ -1 +1 @@
1
- {"version":3,"file":"register-per-message-model-hook.d.ts","sourceRoot":"","sources":["../../src/register-per-message-model-hook.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2CAA2C,CAAC;AAGnF,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,iBAAiB,GAAG,IAAI,CAyBxE"}
1
+ {"version":3,"file":"register-per-message-model-hook.d.ts","sourceRoot":"","sources":["../../src/register-per-message-model-hook.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2CAA2C,CAAC;AAGnF,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,iBAAiB,GAAG,IAAI,CAmCxE"}
@@ -1,21 +1,33 @@
1
1
  /**
2
- * before_model_resolve:消费 IM ext.ai_model 登记的单轮模型,优先于 session autoFallback 探测。
2
+ * before_model_resolve:消费 IM ext.ai_model 登记的单轮模型。
3
+ * 守卫语义:仅当「当前正在解析的候选 == 用户点名的目标模型」时才应用覆盖。
4
+ * 初选候选因冷却/额度在外层被跳过进入 fallback 后,当前候选已不是目标模型,
5
+ * 覆盖必须静默放弃,否则会把降级候选(如 newapi-xgjk/back-model)改回冷却中的主模型。
3
6
  */
4
- import { takePendingPerMessageModel } from "./per-message-model-pending.js";
7
+ import { matchesPendingCandidate, takePendingPerMessageModel } from "./per-message-model-pending.js";
5
8
  export function registerPerMessageModelHook(api) {
6
9
  api.on("before_model_resolve", async (_event, ctx) => {
10
+ // 取后即删:无论命中与否,首个候选钩子就消费本次单轮覆盖,
11
+ // 避免残留到下一个 fallback 候选或下一轮消息。
7
12
  const pending = takePendingPerMessageModel(ctx.sessionKey);
8
- if (!pending)
13
+ if (!pending) {
9
14
  return;
15
+ }
16
+ const ctxProvider = ctx.modelProviderId?.trim() ?? "";
17
+ const ctxModel = ctx.modelId?.trim() ?? "";
18
+ if (!matchesPendingCandidate(ctxProvider, ctxModel, pending)) {
19
+ api.logger.info(`[xg_cwork_im] [model] before_model_resolve hookDecision=skip session=${ctx.sessionKey} ` +
20
+ `candidate=${ctxProvider}/${ctxModel} pending=${pending.raw}`);
21
+ return;
22
+ }
23
+ api.logger.info(`[xg_cwork_im] [model] before_model_resolve hookDecision=apply session=${ctx.sessionKey} ` +
24
+ `provider=${pending.provider ?? ""} model=${pending.model}`);
10
25
  if (pending.provider) {
11
- api.logger.info(`[xg_cwork_im] [model] before_model_resolve session=${ctx.sessionKey} ` +
12
- `provider=${pending.provider} model=${pending.model}`);
13
26
  return {
14
27
  providerOverride: pending.provider,
15
28
  modelOverride: pending.model,
16
29
  };
17
30
  }
18
- api.logger.info(`[xg_cwork_im] [model] before_model_resolve session=${ctx.sessionKey} model=${pending.raw}`);
19
31
  return { modelOverride: pending.raw };
20
32
  }, { priority: 100 });
21
33
  }
@@ -1 +1 @@
1
- {"version":3,"file":"register-per-message-model-hook.js","sourceRoot":"","sources":["../../src/register-per-message-model-hook.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,0BAA0B,EAAE,MAAM,gCAAgC,CAAC;AAE5E,MAAM,UAAU,2BAA2B,CAAC,GAAsB;IAC9D,GAAG,CAAC,EAAE,CACF,sBAAsB,EACtB,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE;QAClB,MAAM,OAAO,GAAG,0BAA0B,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAC3D,IAAI,CAAC,OAAO;YAAE,OAAO;QAErB,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;YACnB,GAAG,CAAC,MAAM,CAAC,IAAI,CACX,sDAAsD,GAAG,CAAC,UAAU,GAAG;gBACnE,YAAY,OAAO,CAAC,QAAQ,UAAU,OAAO,CAAC,KAAK,EAAE,CAC5D,CAAC;YACF,OAAO;gBACH,gBAAgB,EAAE,OAAO,CAAC,QAAQ;gBAClC,aAAa,EAAE,OAAO,CAAC,KAAK;aAC/B,CAAC;QACN,CAAC;QAED,GAAG,CAAC,MAAM,CAAC,IAAI,CACX,sDAAsD,GAAG,CAAC,UAAU,UAAU,OAAO,CAAC,GAAG,EAAE,CAC9F,CAAC;QACF,OAAO,EAAE,aAAa,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1C,CAAC,EACD,EAAE,QAAQ,EAAE,GAAG,EAAE,CACpB,CAAC;AACN,CAAC"}
1
+ {"version":3,"file":"register-per-message-model-hook.js","sourceRoot":"","sources":["../../src/register-per-message-model-hook.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,uBAAuB,EAAE,0BAA0B,EAAE,MAAM,gCAAgC,CAAC;AAErG,MAAM,UAAU,2BAA2B,CAAC,GAAsB;IAC9D,GAAG,CAAC,EAAE,CACF,sBAAsB,EACtB,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE;QAClB,+BAA+B;QAC/B,8BAA8B;QAC9B,MAAM,OAAO,GAAG,0BAA0B,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAC3D,IAAI,CAAC,OAAO,EAAE,CAAC;YACX,OAAO;QACX,CAAC;QAED,MAAM,WAAW,GAAG,GAAG,CAAC,eAAe,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QACtD,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAC3C,IAAI,CAAC,uBAAuB,CAAC,WAAW,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,CAAC;YAC3D,GAAG,CAAC,MAAM,CAAC,IAAI,CACX,wEAAwE,GAAG,CAAC,UAAU,GAAG;gBACrF,aAAa,WAAW,IAAI,QAAQ,YAAY,OAAO,CAAC,GAAG,EAAE,CACpE,CAAC;YACF,OAAO;QACX,CAAC;QAED,GAAG,CAAC,MAAM,CAAC,IAAI,CACX,yEAAyE,GAAG,CAAC,UAAU,GAAG;YACtF,YAAY,OAAO,CAAC,QAAQ,IAAI,EAAE,UAAU,OAAO,CAAC,KAAK,EAAE,CAClE,CAAC;QACF,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;YACnB,OAAO;gBACH,gBAAgB,EAAE,OAAO,CAAC,QAAQ;gBAClC,aAAa,EAAE,OAAO,CAAC,KAAK;aAC/B,CAAC;QACN,CAAC;QACD,OAAO,EAAE,aAAa,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1C,CAAC,EACD,EAAE,QAAQ,EAAE,GAAG,EAAE,CACpB,CAAC;AACN,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=register-per-message-model-hook.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register-per-message-model-hook.test.d.ts","sourceRoot":"","sources":["../../src/register-per-message-model-hook.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,91 @@
1
+ import assert from "node:assert/strict";
2
+ import { describe, it } from "node:test";
3
+ import { clearAllPendingPerMessageModel, matchesPendingCandidate, setPendingPerMessageModel, takePendingPerMessageModel, } from "./per-message-model-pending.js";
4
+ import { registerPerMessageModelHook } from "./register-per-message-model-hook.js";
5
+ function fakeApi() {
6
+ const captured = [];
7
+ const logs = [];
8
+ const api = {
9
+ on: (name, handler, opts) => {
10
+ captured.push({ name, handler, opts });
11
+ },
12
+ logger: {
13
+ info: (...args) => {
14
+ logs.push(args.join(" "));
15
+ },
16
+ },
17
+ };
18
+ return { api, captured, logs };
19
+ }
20
+ describe("matchesPendingCandidate", () => {
21
+ it("matches exact provider/model", () => {
22
+ const pending = setPendingPerMessageModel("s1", "openai/gpt-5.6-sol");
23
+ assert.ok(matchesPendingCandidate("openai", "gpt-5.6-sol", pending));
24
+ clearAllPendingPerMessageModel();
25
+ });
26
+ it("matches model only when pending has no provider", () => {
27
+ const pending = setPendingPerMessageModel("s1", "gpt-5.6-sol");
28
+ assert.equal(pending.provider, undefined);
29
+ assert.ok(matchesPendingCandidate("openai", "gpt-5.6-sol", pending));
30
+ assert.ok(matchesPendingCandidate("newapi-xgjk", "gpt-5.6-sol", pending));
31
+ clearAllPendingPerMessageModel();
32
+ });
33
+ it("rejects candidate that is a fallback, not the requested model", () => {
34
+ const pending = setPendingPerMessageModel("s1", "openai/gpt-5.6-sol");
35
+ assert.equal(matchesPendingCandidate("newapi-xgjk", "back-model", pending), false);
36
+ clearAllPendingPerMessageModel();
37
+ });
38
+ it("normalizes whitespace and provider case", () => {
39
+ const pending = setPendingPerMessageModel("s1", " openai/gpt-5.6-sol ");
40
+ assert.ok(matchesPendingCandidate(" OpenAI ", " gpt-5.6-sol ", pending));
41
+ assert.equal(matchesPendingCandidate("newapi-xgjk", "gpt-5.6-sol", pending), false);
42
+ clearAllPendingPerMessageModel();
43
+ });
44
+ });
45
+ describe("registerPerMessageModelHook", () => {
46
+ it("registers before_model_resolve with priority 100", () => {
47
+ const { api, captured } = fakeApi();
48
+ registerPerMessageModelHook(api);
49
+ assert.equal(captured.length, 1);
50
+ assert.equal(captured[0].name, "before_model_resolve");
51
+ assert.deepEqual(captured[0].opts, { priority: 100 });
52
+ });
53
+ it("applies override when current candidate matches requested model", async () => {
54
+ const { api, captured, logs } = fakeApi();
55
+ registerPerMessageModelHook(api);
56
+ setPendingPerMessageModel("s1", "openai/gpt-5.6-sol");
57
+ const result = await captured[0].handler({}, { sessionKey: "s1", modelProviderId: "openai", modelId: "gpt-5.6-sol" });
58
+ assert.deepEqual(result, { providerOverride: "openai", modelOverride: "gpt-5.6-sol" });
59
+ assert.match(logs.join(" "), /hookDecision=apply/);
60
+ assert.equal(takePendingPerMessageModel("s1"), undefined);
61
+ clearAllPendingPerMessageModel();
62
+ });
63
+ it("does not override a fallback candidate back to the requested model", async () => {
64
+ const { api, captured, logs } = fakeApi();
65
+ registerPerMessageModelHook(api);
66
+ setPendingPerMessageModel("s1", "openai/gpt-5.6-sol");
67
+ const result = await captured[0].handler({}, { sessionKey: "s1", modelProviderId: "newapi-xgjk", modelId: "back-model" });
68
+ assert.equal(result, undefined);
69
+ assert.match(logs.join(" "), /hookDecision=skip/);
70
+ assert.equal(takePendingPerMessageModel("s1"), undefined);
71
+ clearAllPendingPerMessageModel();
72
+ });
73
+ it("does not consume another session's pending model", async () => {
74
+ const { api, captured } = fakeApi();
75
+ registerPerMessageModelHook(api);
76
+ setPendingPerMessageModel("s1", "openai/gpt-5.6-sol");
77
+ await captured[0].handler({}, { sessionKey: "s2", modelProviderId: "openai", modelId: "gpt-5.6-sol" });
78
+ assert.equal(takePendingPerMessageModel("s2"), undefined);
79
+ const pendingForS1 = takePendingPerMessageModel("s1");
80
+ assert.equal(pendingForS1?.model, "gpt-5.6-sol");
81
+ clearAllPendingPerMessageModel();
82
+ });
83
+ it("does nothing when no pending model is registered", async () => {
84
+ const { api, captured } = fakeApi();
85
+ registerPerMessageModelHook(api);
86
+ clearAllPendingPerMessageModel();
87
+ const result = await captured[0].handler({}, { sessionKey: "s1", modelProviderId: "openai", modelId: "gpt-5.6-sol" });
88
+ assert.equal(result, undefined);
89
+ });
90
+ });
91
+ //# sourceMappingURL=register-per-message-model-hook.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register-per-message-model-hook.test.js","sourceRoot":"","sources":["../../src/register-per-message-model-hook.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xgjktech/xg_cwork_im",
3
- "version": "1.18.4",
3
+ "version": "1.18.5",
4
4
  "description": "XG CWork IM channel plugin for OpenClaw",
5
5
  "keywords": [
6
6
  "bot",
@@ -25,7 +25,7 @@
25
25
  "build": "tsc -p tsconfig.json",
26
26
  "type-check": "tsc -p tsconfig.json --noEmit",
27
27
  "lint": "tsc -p tsconfig.json --noEmit",
28
- "test": "npm run build && node --test dist/src/account-reconciler.test.js dist/src/inbound-terminal-state.test.js dist/src/user-facing-errors.test.js dist/src/deliver-text.test.js dist/src/agent-context-types.test.js dist/src/build-project-prompt.test.js dist/src/nas-volumes.test.js dist/src/workspace-event.test.js dist/src/workspace-event-scheduler.test.js dist/src/connection-workspace-event.test.js dist/src/block-streaming-config.test.js dist/src/channel-disabled-account.test.js dist/src/per-message-fallback-notice.test.js dist/src/thinking-ws-progress.test.js dist/src/resource-file.test.js dist/src/turn-deliver-buffer.test.js dist/src/run-usage.test.js dist/src/ws-run-event-unmapped.test.js dist/src/item-event-guard.test.js dist/src/inbound-model.test.js dist/src/auto-model-router.test.js dist/src/channel-config.test.js dist/src/send-service.test.js dist/src/send-file-tool.test.js dist/src/plan-tool-result.test.js dist/src/plan-blocked-notice.test.js dist/src/plan-store-access.test.js dist/src/plan-tool-middleware.test.js dist/src/plan-event-subscription.test.js dist/src/plan-ws-registry.test.js dist/src/plan-stat-event.test.js dist/src/active-round-registry.test.js dist/src/interrupt-round.test.js dist/src/subagent-monitor.test.js dist/src/turn-end-controller.test.js dist/src/session-env-store.test.js dist/src/register-exec-env-hook.test.js dist/src/cron-appkey-binding-store.test.js dist/src/ws-inbound-schema.test.js dist/src/connection.test.js dist/src/reply-dispatch-driver.test.js",
28
+ "test": "npm run build && node --test dist/src/account-reconciler.test.js dist/src/inbound-terminal-state.test.js dist/src/user-facing-errors.test.js dist/src/deliver-text.test.js dist/src/agent-context-types.test.js dist/src/build-project-prompt.test.js dist/src/nas-volumes.test.js dist/src/workspace-event.test.js dist/src/workspace-event-scheduler.test.js dist/src/connection-workspace-event.test.js dist/src/block-streaming-config.test.js dist/src/channel-disabled-account.test.js dist/src/per-message-fallback-notice.test.js dist/src/register-per-message-model-hook.test.js dist/src/thinking-ws-progress.test.js dist/src/resource-file.test.js dist/src/turn-deliver-buffer.test.js dist/src/run-usage.test.js dist/src/ws-run-event-unmapped.test.js dist/src/item-event-guard.test.js dist/src/inbound-model.test.js dist/src/auto-model-router.test.js dist/src/channel-config.test.js dist/src/send-service.test.js dist/src/send-file-tool.test.js dist/src/plan-tool-result.test.js dist/src/plan-blocked-notice.test.js dist/src/plan-store-access.test.js dist/src/plan-tool-middleware.test.js dist/src/plan-event-subscription.test.js dist/src/plan-ws-registry.test.js dist/src/plan-stat-event.test.js dist/src/active-round-registry.test.js dist/src/interrupt-round.test.js dist/src/subagent-monitor.test.js dist/src/turn-end-controller.test.js dist/src/session-env-store.test.js dist/src/register-exec-env-hook.test.js dist/src/cron-appkey-binding-store.test.js dist/src/ws-inbound-schema.test.js dist/src/connection.test.js dist/src/reply-dispatch-driver.test.js",
29
29
  "install:prod": "npm install --omit=dev",
30
30
  "prepublishOnly": "npm run build"
31
31
  },