opencode-copilot-account-switcher 0.14.3 → 0.14.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.
@@ -20,6 +20,9 @@ type WechatBindFlowInput = {
20
20
  readCommonSettings: () => Promise<CommonSettingsStore>;
21
21
  writeCommonSettings: (settings: CommonSettingsStore) => Promise<void>;
22
22
  writeLine?: (line: string) => Promise<void>;
23
+ renderQrTerminal?: (input: {
24
+ value: string;
25
+ }) => Promise<string | undefined>;
23
26
  now?: () => number;
24
27
  };
25
28
  export declare function runWechatBindFlow(input: WechatBindFlowInput): Promise<WechatBindFlowResult>;
@@ -1,6 +1,7 @@
1
1
  import { bindOperator, readOperatorBinding, rebindOperator, resetOperatorBinding } from "./operator-store.js";
2
2
  import { loadOpenClawWeixinPublicHelpers } from "./compat/openclaw-public-helpers.js";
3
3
  import { buildOpenClawMenuAccount } from "./openclaw-account-adapter.js";
4
+ import qrcodeTerminal from "qrcode-terminal";
4
5
  const DEFAULT_QR_WAIT_TIMEOUT_MS = 480000;
5
6
  function pickFirstNonEmptyString(...values) {
6
7
  for (const value of values) {
@@ -32,6 +33,13 @@ async function rollbackBinding(action, previousOperatorBinding, persistOperatorR
32
33
  }
33
34
  await clearOperatorBinding().catch(() => { });
34
35
  }
36
+ async function renderQrTerminalDefault(input) {
37
+ return await new Promise((resolve) => {
38
+ qrcodeTerminal.generate(input.value, { small: true }, (output) => {
39
+ resolve(typeof output === "string" && output.trim().length > 0 ? output : undefined);
40
+ });
41
+ });
42
+ }
35
43
  export async function runWechatBindFlow(input) {
36
44
  const now = input.now ?? Date.now;
37
45
  const loadPublicHelpers = input.loadPublicHelpers ?? loadOpenClawWeixinPublicHelpers;
@@ -39,6 +47,7 @@ export async function runWechatBindFlow(input) {
39
47
  const persistOperatorRebinding = input.rebindOperator ?? rebindOperator;
40
48
  const loadOperatorBinding = input.readOperatorBinding ?? readOperatorBinding;
41
49
  const clearOperatorBinding = input.resetOperatorBinding ?? resetOperatorBinding;
50
+ const renderQrTerminal = input.renderQrTerminal ?? renderQrTerminalDefault;
42
51
  const writeLine = input.writeLine ?? (async (line) => {
43
52
  process.stdout.write(`${line}\n`);
44
53
  });
@@ -53,6 +62,10 @@ export async function runWechatBindFlow(input) {
53
62
  await writeLine(qrTerminal);
54
63
  }
55
64
  else if (qrUrl) {
65
+ const renderedQr = await renderQrTerminal({ value: qrUrl }).catch(() => undefined);
66
+ if (renderedQr) {
67
+ await writeLine(renderedQr);
68
+ }
56
69
  await writeLine(`QR URL fallback: ${qrUrl}`);
57
70
  }
58
71
  else {
@@ -66,28 +79,16 @@ export async function runWechatBindFlow(input) {
66
79
  throw new Error("qr login did not complete");
67
80
  }
68
81
  const accountId = pickFirstNonEmptyString(waited?.accountId, helpers.latestAccountState?.accountId, (await helpers.accountHelpers.listAccountIds()).at(-1));
69
- const userId = pickFirstNonEmptyString(waited?.userId, waited?.openid, waited?.uid);
70
82
  if (!accountId) {
71
83
  throw new Error("missing accountId after qr login");
72
84
  }
73
- if (!userId) {
74
- throw new Error("missing userId after qr login");
75
- }
76
85
  const boundAt = now();
77
- const operatorBinding = {
78
- wechatAccountId: accountId,
79
- userId,
80
- boundAt,
81
- };
86
+ const userIdFromWait = pickFirstNonEmptyString(waited?.userId, waited?.openid, waited?.uid);
82
87
  const previousOperatorBinding = input.action === "wechat-rebind" ? await loadOperatorBinding() : undefined;
83
88
  let menuAccount;
89
+ let boundUserId = "";
90
+ let shouldRollbackBinding = false;
84
91
  try {
85
- if (input.action === "wechat-rebind") {
86
- await persistOperatorRebinding(operatorBinding);
87
- }
88
- else {
89
- await persistOperatorBinding(operatorBinding);
90
- }
91
92
  const menuAccountState = accountId
92
93
  ? {
93
94
  ...(helpers.latestAccountState ?? {
@@ -96,7 +97,7 @@ export async function runWechatBindFlow(input) {
96
97
  baseUrl: "https://ilinkai.weixin.qq.com",
97
98
  }),
98
99
  accountId,
99
- userId,
100
+ ...(userIdFromWait ? { userId: userIdFromWait } : {}),
100
101
  boundAt,
101
102
  }
102
103
  : helpers.latestAccountState;
@@ -104,6 +105,23 @@ export async function runWechatBindFlow(input) {
104
105
  latestAccountState: menuAccountState,
105
106
  accountHelpers: helpers.accountHelpers,
106
107
  });
108
+ const userId = pickFirstNonEmptyString(userIdFromWait, menuAccount?.userId);
109
+ if (!userId) {
110
+ throw new Error("missing userId after qr login");
111
+ }
112
+ boundUserId = userId;
113
+ const operatorBinding = {
114
+ wechatAccountId: accountId,
115
+ userId,
116
+ boundAt,
117
+ };
118
+ shouldRollbackBinding = true;
119
+ if (input.action === "wechat-rebind") {
120
+ await persistOperatorRebinding(operatorBinding);
121
+ }
122
+ else {
123
+ await persistOperatorBinding(operatorBinding);
124
+ }
107
125
  const settings = await input.readCommonSettings();
108
126
  const notifications = settings.wechat?.notifications ?? {
109
127
  enabled: true,
@@ -126,12 +144,14 @@ export async function runWechatBindFlow(input) {
126
144
  await input.writeCommonSettings(settings);
127
145
  }
128
146
  catch (error) {
129
- await rollbackBinding(input.action, previousOperatorBinding, persistOperatorRebinding, clearOperatorBinding);
147
+ if (shouldRollbackBinding) {
148
+ await rollbackBinding(input.action, previousOperatorBinding, persistOperatorRebinding, clearOperatorBinding);
149
+ }
130
150
  throw error;
131
151
  }
132
152
  return {
133
153
  accountId,
134
- userId,
154
+ userId: boundUserId,
135
155
  name: menuAccount?.name,
136
156
  enabled: menuAccount?.enabled,
137
157
  configured: menuAccount?.configured,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-copilot-account-switcher",
3
- "version": "0.14.3",
3
+ "version": "0.14.5",
4
4
  "description": "GitHub Copilot account switcher plugin for OpenCode",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",