@wengine-ai/ccr-provider-qoder 0.3.0 → 0.3.2

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/card.js CHANGED
@@ -10,26 +10,34 @@ var qoderLocales = {
10
10
  connected: "Connected",
11
11
  expired: "Sign-in lapsed \u2014 reconnect with a fresh PAT",
12
12
  error: "Management request failed",
13
- account: "Account",
14
- models: "Models",
15
- pat: "Personal access token",
16
- patPlaceholder: "pt-\u2026",
17
- connect: "Connect",
18
13
  checkin: "Check in",
14
+ checkin_action: "Check in",
15
+ checkin_pending: "Checking in\u2026",
19
16
  checkin_claimed: "Credits claimed",
20
17
  checkin_done: "Already claimed today",
21
18
  checkin_inactive: "No campaign today",
22
19
  checkin_ineligible: "Unavailable",
23
20
  checkin_failed: "Check-in failed",
24
21
  checkinDesktop: "International check-in requires Qoder desktop device identity; claim in Qoder desktop.",
22
+ account: "Account",
23
+ models: "Models",
24
+ models_count: "{{count}} models",
25
+ pat: "Personal access token",
26
+ patPlaceholder: "pt-\u2026",
27
+ connect: "Connect",
25
28
  sync: "Refresh models",
26
29
  usage: "Refresh quota",
27
30
  unknown: "Quota unknown",
28
31
  stale: "Last known quota (stale)",
29
32
  used: "Allowance",
33
+ restore_partial: "Partially completed: restored {{count}} of {{total}} models. Management request failed.",
34
+ hide_partial: "Partially completed: hid {{count}} of {{total}} models. Management request failed.",
35
+ restore_model: "Restore {{model}}",
30
36
  disconnect: "Disconnect",
31
- hide: "Hide",
37
+ hide_model: "Hide {{model}}",
38
+ hidden_models: "Hidden models ({{count}})",
32
39
  restore: "Restore",
40
+ restore_all: "Restore all",
33
41
  cooling: "Rate limited until",
34
42
  noModels: "Refresh models after connecting",
35
43
  free: "free",
@@ -45,26 +53,34 @@ var qoderLocales = {
45
53
  connected: "\u5DF2\u8FDE\u63A5",
46
54
  expired: "\u767B\u5F55\u5DF2\u5931\u6548 \u2014 \u8BF7\u4F7F\u7528\u65B0\u7684 PAT \u91CD\u65B0\u8FDE\u63A5",
47
55
  error: "\u7BA1\u7406\u64CD\u4F5C\u5931\u8D25",
48
- account: "\u8D26\u53F7",
49
- models: "\u6A21\u578B",
50
- pat: "\u4E2A\u4EBA\u8BBF\u95EE\u4EE4\u724C",
51
- patPlaceholder: "pt-\u2026",
52
- connect: "\u8FDE\u63A5",
53
56
  checkin: "\u7B7E\u5230",
57
+ checkin_action: "\u7B7E\u5230",
58
+ checkin_pending: "\u7B7E\u5230\u4E2D\u2026",
54
59
  checkin_claimed: "\u9886\u53D6\u6210\u529F",
55
60
  checkin_done: "\u4ECA\u65E5\u5DF2\u9886",
56
61
  checkin_inactive: "\u4ECA\u65E5\u65E0\u6D3B\u52A8",
57
62
  checkin_ineligible: "\u4E0D\u53EF\u7528",
58
63
  checkin_failed: "\u7B7E\u5230\u5931\u8D25",
59
64
  checkinDesktop: "\u56FD\u9645\u7AD9\u9700\u8981\u5728 Qoder \u684C\u9762\u7AEF\u5185\u7B7E\u5230\u3002",
65
+ account: "\u8D26\u53F7",
66
+ models: "\u6A21\u578B",
67
+ models_count: "{{count}} \u4E2A\u6A21\u578B",
68
+ pat: "\u4E2A\u4EBA\u8BBF\u95EE\u4EE4\u724C",
69
+ patPlaceholder: "pt-\u2026",
70
+ connect: "\u8FDE\u63A5",
60
71
  sync: "\u5237\u65B0\u6A21\u578B",
61
72
  usage: "\u5237\u65B0\u989D\u5EA6",
62
73
  unknown: "\u989D\u5EA6\u672A\u77E5",
63
74
  stale: "\u4E0A\u6B21\u989D\u5EA6\uFF08\u5DF2\u8FC7\u671F\uFF09",
64
75
  used: "\u5DF2\u7528\u989D\u5EA6",
76
+ restore_partial: "\u90E8\u5206\u5B8C\u6210\uFF1A\u5DF2\u6062\u590D {{count}} \u4E2A\u6A21\u578B\uFF0C\u5171 {{total}} \u4E2A\u3002\u7BA1\u7406\u64CD\u4F5C\u5931\u8D25\u3002",
77
+ hide_partial: "\u90E8\u5206\u5B8C\u6210\uFF1A\u5DF2\u9690\u85CF {{count}} \u4E2A\u6A21\u578B\uFF0C\u5171 {{total}} \u4E2A\u3002\u7BA1\u7406\u64CD\u4F5C\u5931\u8D25\u3002",
78
+ restore_model: "\u6062\u590D {{model}}",
65
79
  disconnect: "\u65AD\u5F00\u8FDE\u63A5",
66
- hide: "\u9690\u85CF",
80
+ hide_model: "\u9690\u85CF {{model}}",
81
+ hidden_models: "\u5DF2\u9690\u85CF\u6A21\u578B\uFF08{{count}}\uFF09",
67
82
  restore: "\u6062\u590D",
83
+ restore_all: "\u6062\u590D\u5168\u90E8",
68
84
  cooling: "\u9650\u6D41\u81F3",
69
85
  noModels: "\u8FDE\u63A5\u540E\u8BF7\u5237\u65B0\u6A21\u578B",
70
86
  free: "\u514D\u8D39",
@@ -158,9 +174,36 @@ function mount(el, props) {
158
174
  n.className = cls;
159
175
  return n;
160
176
  };
177
+ const CHIP = "inline-flex max-w-full items-center gap-1 break-all whitespace-normal rounded-lg border border-white/5 bg-white/5 px-2 py-0.5 text-[10px] font-bold text-muted-foreground";
178
+ const CHIP_HIDE = "rounded p-0.5 text-muted-foreground/60 transition-colors hover:bg-white/10 hover:text-foreground disabled:opacity-40";
179
+ const BUTTON_BASE = "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-xl text-sm font-semibold ring-offset-background transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 active:scale-95";
180
+ const BUTTON_OUTLINE = "border border-input bg-input/50 backdrop-blur-md shadow-sm hover:bg-input/80 hover:border-primary/50 hover:shadow-md hover:text-accent-foreground";
181
+ const xIcon = (className) => {
182
+ const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
183
+ svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
184
+ svg.setAttribute("width", "24");
185
+ svg.setAttribute("height", "24");
186
+ svg.setAttribute("viewBox", "0 0 24 24");
187
+ svg.setAttribute("fill", "none");
188
+ svg.setAttribute("stroke", "currentColor");
189
+ svg.setAttribute("stroke-width", "2");
190
+ svg.setAttribute("stroke-linecap", "round");
191
+ svg.setAttribute("stroke-linejoin", "round");
192
+ svg.setAttribute("aria-hidden", "true");
193
+ svg.setAttribute("class", className);
194
+ for (const d of ["M18 6 6 18", "m6 6 12 12"]) {
195
+ const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
196
+ path.setAttribute("d", d);
197
+ svg.appendChild(path);
198
+ }
199
+ return svg;
200
+ };
201
+ const format = (key, vars = {}) => String(words[key] ?? key).replace(/\{\{(\w+)\}\}/g, (_, name) => String(vars[name] ?? ""));
202
+ const sectionBusy = () => disposed || props.disabled || sections.some((s) => s.busy);
161
203
  const sectionWords = (section) => section.site.id === "qoder" ? { title: words.title, description: words.description } : { title: words.cnTitle, description: words.cnDescription };
162
204
  const finish = (section) => {
163
205
  section.busy = false;
206
+ section.pendingModel = null;
164
207
  section.release?.();
165
208
  section.release = void 0;
166
209
  props.onBusy?.(false);
@@ -178,6 +221,7 @@ function mount(el, props) {
178
221
  section.release = lease;
179
222
  section.busy = true;
180
223
  section.error = false;
224
+ section.errorMessage = void 0;
181
225
  props.onBusy?.(true);
182
226
  render();
183
227
  try {
@@ -204,10 +248,67 @@ function mount(el, props) {
204
248
  });
205
249
  const action = (section, label, fn) => {
206
250
  const button = node("button", words[label], "px-3 py-2 rounded-md bg-secondary text-secondary-foreground hover:bg-secondary/80 disabled:opacity-50");
207
- button.disabled = disposed || props.disabled || sections.some((s) => s.busy);
251
+ button.disabled = sectionBusy();
208
252
  button.onclick = fn;
209
253
  return button;
210
254
  };
255
+ const checkinButton = (section) => {
256
+ const pending = !!section.checkinPending;
257
+ const button = node("button", pending ? words.checkin_pending : words.checkin_action, "inline-flex h-8 w-full items-center justify-center gap-2 whitespace-nowrap rounded-xl border border-input bg-input/50 text-xs font-semibold shadow-sm hover:bg-input/80 disabled:pointer-events-none disabled:opacity-50");
258
+ button.type = "button";
259
+ button.disabled = disposed || props.disabled || sections.some((s) => s.busy) || section.status?.status !== "connected";
260
+ button.setAttribute("aria-busy", String(pending));
261
+ button.onclick = () => {
262
+ section.checkinPending = true;
263
+ void run(section, async () => {
264
+ try {
265
+ section.checkin = void 0;
266
+ try {
267
+ section.checkin = await call(section, "/checkin", {});
268
+ } catch {
269
+ section.checkin = { outcome: "failed" };
270
+ }
271
+ } finally {
272
+ section.checkinPending = false;
273
+ }
274
+ });
275
+ };
276
+ return button;
277
+ };
278
+ const checkinNote = (section) => {
279
+ if (!section.checkin) return null;
280
+ const result = section.checkin;
281
+ const amount = result.credit;
282
+ const detail = result.outcome === "claimed" && typeof amount === "number" && Number.isFinite(amount) && amount > 0 ? lang === "zh" ? `+${amount} \u79EF\u5206` : `+${amount} credits` : words[`checkin_${result.outcome}`] ?? words.checkin_failed;
283
+ const note = node("p", detail + (result.outcome === "failed" && result.message ? `: ${result.message}` : ""), result.outcome === "failed" ? "text-destructive" : "text-xs text-muted-foreground");
284
+ note.setAttribute("role", "status");
285
+ return note;
286
+ };
287
+ const smallButton = (label, extra, fn) => {
288
+ const button = node("button", label, `${BUTTON_BASE} ${BUTTON_OUTLINE} ${extra}`);
289
+ button.type = "button";
290
+ button.disabled = sectionBusy();
291
+ button.onclick = fn;
292
+ return button;
293
+ };
294
+ const setModelVisibility = (section, ids, hidden) => void run(section, async () => {
295
+ let completed = 0;
296
+ try {
297
+ for (const id of ids) {
298
+ await call(section, "/models/visibility", { model: id, hidden });
299
+ completed += 1;
300
+ }
301
+ } catch (error) {
302
+ if (completed > 0) section.errorMessage = format(hidden ? "hide_partial" : "restore_partial", { count: completed, total: ids.length });
303
+ throw error;
304
+ } finally {
305
+ try {
306
+ await reconcile(section);
307
+ } finally {
308
+ await refresh(section);
309
+ }
310
+ }
311
+ });
211
312
  const renderSection = (section) => {
212
313
  const panel = node("div", "", "space-y-3 border-t border-border pt-4 first:border-t-0 first:pt-0");
213
314
  panel.append(
@@ -217,7 +318,7 @@ function mount(el, props) {
217
318
  panel.append(node("p", section.status ? words[section.status.status] ?? words.error : words.loading));
218
319
  if (section.status?.expired) panel.append(node("p", words.expired, "text-destructive"));
219
320
  if (section.status?.account) panel.append(node("p", `${words.account}: ${section.status.account}`));
220
- if (section.error) panel.append(node("p", words.error, "text-destructive"));
321
+ if (section.error) panel.append(node("p", section.errorMessage ?? words.error, "text-destructive"));
221
322
  const buttons = node("div", "", "flex flex-wrap gap-2");
222
323
  if (section.status?.status === "not_connected") {
223
324
  const input = node("input", "", "w-full rounded-md border border-input bg-background px-3 py-2 text-sm");
@@ -236,39 +337,30 @@ function mount(el, props) {
236
337
  panel.append(node("p", words.pat, "text-sm font-medium"), input);
237
338
  buttons.append(connectButton);
238
339
  } else if (section.status) {
340
+ if (section.site.id === "qoder-cn") {
341
+ panel.append(checkinButton(section));
342
+ const note = checkinNote(section);
343
+ if (note) panel.append(note);
344
+ } else if (section.status) {
345
+ panel.append(node("p", words.checkinDesktop, "text-sm text-muted-foreground"));
346
+ }
239
347
  buttons.append(action(section, "sync", () => void run(section, async () => {
240
348
  await call(section, "/sync", {});
241
349
  await reconcile(section);
242
350
  await refresh(section);
243
351
  })));
244
- if (section.site.id === "qoder-cn") buttons.append(action(section, "checkin", () => void run(section, async () => {
245
- section.checkin = void 0;
246
- try {
247
- section.checkin = await call(section, "/checkin", {});
248
- } catch {
249
- section.checkin = { outcome: "failed" };
250
- }
251
- })));
252
352
  buttons.append(action(section, "usage", () => void run(section, async () => {
253
353
  section.usage = await call(section, "/usage", {});
254
354
  })));
255
355
  buttons.append(action(section, "disconnect", () => void run(section, async () => {
256
356
  await call(section, "/disconnect", {});
257
357
  section.usage = void 0;
258
- section.checkin = void 0;
259
358
  await reconcile(section);
260
359
  await refresh(section);
261
360
  })));
262
361
  }
263
362
  buttons.append(action(section, "refresh", () => void run(section, () => refresh(section))));
264
363
  panel.append(buttons);
265
- if (section.status?.status === "connected" && section.site.id === "qoder") panel.append(node("p", words.checkinDesktop, "text-sm text-muted-foreground"));
266
- if (section.checkin) {
267
- const result = section.checkin;
268
- const amount = result.credit;
269
- const detail = result.outcome === "claimed" && typeof amount === "number" && Number.isFinite(amount) && amount > 0 ? lang === "zh" ? `+${amount} \u79EF\u5206` : `+${amount} credits` : words[`checkin_${result.outcome}`] ?? words.checkin_failed;
270
- panel.append(node("p", detail + (result.outcome === "failed" && result.message ? `: ${result.message}` : ""), result.outcome === "failed" ? "text-destructive" : "text-sm"));
271
- }
272
364
  const usageLine = node("p", "", "text-sm text-muted-foreground");
273
365
  if (section.usage?.known && Array.isArray(section.usage.windows) && section.usage.windows.length) {
274
366
  usageLine.textContent = `${section.usage.stale ? words.stale : words.used}: ` + section.usage.windows.map((w) => {
@@ -279,18 +371,67 @@ function mount(el, props) {
279
371
  } else usageLine.textContent = words.unknown;
280
372
  panel.append(usageLine);
281
373
  if (section.status?.coolingUntil > Date.now()) panel.append(node("p", `${words.cooling}: ${new Date(section.status.coolingUntil).toLocaleString()}`, "text-sm text-muted-foreground"));
282
- panel.append(node("h4", words.models, "font-medium"));
283
- if (!section.status?.models?.length) panel.append(node("p", words.noModels, "text-sm text-muted-foreground"));
284
- for (const model of section.status?.models ?? []) {
285
- const row = node("div", "", "flex items-center justify-between gap-2");
286
- const label = `${model.id}${model.context ? ` \xB7 ${model.context}` : ""}${model.free ? ` \xB7 ${words.free}` : ""}`;
287
- row.append(node("span", label, "text-sm"));
288
- row.append(action(section, model.hidden ? "restore" : "hide", () => void run(section, async () => {
289
- await call(section, "/models/visibility", { model: model.id, hidden: !model.hidden });
290
- await reconcile(section);
291
- await refresh(section);
292
- })));
293
- panel.append(row);
374
+ const models = Array.isArray(section.status?.models) ? section.status.models : [];
375
+ const visible = models.filter((model) => !model.hidden);
376
+ const hiddenModels = models.filter((model) => model.hidden);
377
+ if (section.status?.status === "connected" || models.length) {
378
+ const count = node("dl", "", "grid max-w-md grid-cols-[auto_minmax(0,1fr)] gap-x-3 gap-y-1 text-xs");
379
+ count.append(
380
+ node("dt", words.models, "text-muted-foreground"),
381
+ node("dd", format("models_count", { count: section.status?.modelCount ?? models.length }), "break-all text-foreground")
382
+ );
383
+ panel.append(count);
384
+ }
385
+ if (!models.length) panel.append(node("p", words.noModels, "text-sm text-muted-foreground"));
386
+ if (visible.length) {
387
+ const chips = node("div", "", "flex flex-wrap gap-2 pt-1");
388
+ for (const model of visible) {
389
+ const id = String(model.id);
390
+ const chip = node("span", id, CHIP);
391
+ if (model.context) chip.append(node("span", String(model.context), "font-medium text-muted-foreground/60"));
392
+ if (model.free) chip.append(node("span", words.free, "font-medium text-muted-foreground/60"));
393
+ const hide = node("button", "", CHIP_HIDE);
394
+ hide.type = "button";
395
+ hide.disabled = sectionBusy();
396
+ hide.setAttribute("aria-label", format("hide_model", { model: id }));
397
+ hide.setAttribute("aria-busy", String(section.busy && section.pendingModel === id));
398
+ hide.append(xIcon("h-3 w-3"));
399
+ hide.onclick = () => {
400
+ section.pendingModel = id;
401
+ setModelVisibility(section, [id], true);
402
+ };
403
+ chip.append(hide);
404
+ chips.append(chip);
405
+ }
406
+ panel.append(chips);
407
+ }
408
+ if (hiddenModels.length) {
409
+ const details = node("details", "", "max-w-md text-xs text-muted-foreground");
410
+ details.append(node("summary", format("hidden_models", { count: hiddenModels.length }), "cursor-pointer select-none font-medium"));
411
+ const list = node("ul", "", "mt-2 space-y-1");
412
+ for (const model of hiddenModels) {
413
+ const id = String(model.id);
414
+ const item = node("li", "", "flex items-center justify-between gap-2");
415
+ item.append(node("span", id, "break-all font-mono"));
416
+ const restore = smallButton(
417
+ words.restore,
418
+ "h-6 shrink-0 px-2 text-[11px]",
419
+ () => {
420
+ section.pendingModel = id;
421
+ setModelVisibility(section, [id], false);
422
+ }
423
+ );
424
+ restore.setAttribute("aria-label", format("restore_model", { model: id }));
425
+ item.append(restore);
426
+ list.append(item);
427
+ }
428
+ details.append(list);
429
+ details.append(smallButton(
430
+ words.restore_all,
431
+ "mt-2 h-7 px-2 text-[11px]",
432
+ () => setModelVisibility(section, hiddenModels.map((model) => String(model.id)), false)
433
+ ));
434
+ panel.append(details);
294
435
  }
295
436
  return panel;
296
437
  };
package/dist/plugin.js CHANGED
@@ -2546,26 +2546,34 @@ var qoderLocales = {
2546
2546
  connected: "Connected",
2547
2547
  expired: "Sign-in lapsed \u2014 reconnect with a fresh PAT",
2548
2548
  error: "Management request failed",
2549
- account: "Account",
2550
- models: "Models",
2551
- pat: "Personal access token",
2552
- patPlaceholder: "pt-\u2026",
2553
- connect: "Connect",
2554
2549
  checkin: "Check in",
2550
+ checkin_action: "Check in",
2551
+ checkin_pending: "Checking in\u2026",
2555
2552
  checkin_claimed: "Credits claimed",
2556
2553
  checkin_done: "Already claimed today",
2557
2554
  checkin_inactive: "No campaign today",
2558
2555
  checkin_ineligible: "Unavailable",
2559
2556
  checkin_failed: "Check-in failed",
2560
2557
  checkinDesktop: "International check-in requires Qoder desktop device identity; claim in Qoder desktop.",
2558
+ account: "Account",
2559
+ models: "Models",
2560
+ models_count: "{{count}} models",
2561
+ pat: "Personal access token",
2562
+ patPlaceholder: "pt-\u2026",
2563
+ connect: "Connect",
2561
2564
  sync: "Refresh models",
2562
2565
  usage: "Refresh quota",
2563
2566
  unknown: "Quota unknown",
2564
2567
  stale: "Last known quota (stale)",
2565
2568
  used: "Allowance",
2569
+ restore_partial: "Partially completed: restored {{count}} of {{total}} models. Management request failed.",
2570
+ hide_partial: "Partially completed: hid {{count}} of {{total}} models. Management request failed.",
2571
+ restore_model: "Restore {{model}}",
2566
2572
  disconnect: "Disconnect",
2567
- hide: "Hide",
2573
+ hide_model: "Hide {{model}}",
2574
+ hidden_models: "Hidden models ({{count}})",
2568
2575
  restore: "Restore",
2576
+ restore_all: "Restore all",
2569
2577
  cooling: "Rate limited until",
2570
2578
  noModels: "Refresh models after connecting",
2571
2579
  free: "free",
@@ -2581,26 +2589,34 @@ var qoderLocales = {
2581
2589
  connected: "\u5DF2\u8FDE\u63A5",
2582
2590
  expired: "\u767B\u5F55\u5DF2\u5931\u6548 \u2014 \u8BF7\u4F7F\u7528\u65B0\u7684 PAT \u91CD\u65B0\u8FDE\u63A5",
2583
2591
  error: "\u7BA1\u7406\u64CD\u4F5C\u5931\u8D25",
2584
- account: "\u8D26\u53F7",
2585
- models: "\u6A21\u578B",
2586
- pat: "\u4E2A\u4EBA\u8BBF\u95EE\u4EE4\u724C",
2587
- patPlaceholder: "pt-\u2026",
2588
- connect: "\u8FDE\u63A5",
2589
2592
  checkin: "\u7B7E\u5230",
2593
+ checkin_action: "\u7B7E\u5230",
2594
+ checkin_pending: "\u7B7E\u5230\u4E2D\u2026",
2590
2595
  checkin_claimed: "\u9886\u53D6\u6210\u529F",
2591
2596
  checkin_done: "\u4ECA\u65E5\u5DF2\u9886",
2592
2597
  checkin_inactive: "\u4ECA\u65E5\u65E0\u6D3B\u52A8",
2593
2598
  checkin_ineligible: "\u4E0D\u53EF\u7528",
2594
2599
  checkin_failed: "\u7B7E\u5230\u5931\u8D25",
2595
2600
  checkinDesktop: "\u56FD\u9645\u7AD9\u9700\u8981\u5728 Qoder \u684C\u9762\u7AEF\u5185\u7B7E\u5230\u3002",
2601
+ account: "\u8D26\u53F7",
2602
+ models: "\u6A21\u578B",
2603
+ models_count: "{{count}} \u4E2A\u6A21\u578B",
2604
+ pat: "\u4E2A\u4EBA\u8BBF\u95EE\u4EE4\u724C",
2605
+ patPlaceholder: "pt-\u2026",
2606
+ connect: "\u8FDE\u63A5",
2596
2607
  sync: "\u5237\u65B0\u6A21\u578B",
2597
2608
  usage: "\u5237\u65B0\u989D\u5EA6",
2598
2609
  unknown: "\u989D\u5EA6\u672A\u77E5",
2599
2610
  stale: "\u4E0A\u6B21\u989D\u5EA6\uFF08\u5DF2\u8FC7\u671F\uFF09",
2600
2611
  used: "\u5DF2\u7528\u989D\u5EA6",
2612
+ restore_partial: "\u90E8\u5206\u5B8C\u6210\uFF1A\u5DF2\u6062\u590D {{count}} \u4E2A\u6A21\u578B\uFF0C\u5171 {{total}} \u4E2A\u3002\u7BA1\u7406\u64CD\u4F5C\u5931\u8D25\u3002",
2613
+ hide_partial: "\u90E8\u5206\u5B8C\u6210\uFF1A\u5DF2\u9690\u85CF {{count}} \u4E2A\u6A21\u578B\uFF0C\u5171 {{total}} \u4E2A\u3002\u7BA1\u7406\u64CD\u4F5C\u5931\u8D25\u3002",
2614
+ restore_model: "\u6062\u590D {{model}}",
2601
2615
  disconnect: "\u65AD\u5F00\u8FDE\u63A5",
2602
- hide: "\u9690\u85CF",
2616
+ hide_model: "\u9690\u85CF {{model}}",
2617
+ hidden_models: "\u5DF2\u9690\u85CF\u6A21\u578B\uFF08{{count}}\uFF09",
2603
2618
  restore: "\u6062\u590D",
2619
+ restore_all: "\u6062\u590D\u5168\u90E8",
2604
2620
  cooling: "\u9650\u6D41\u81F3",
2605
2621
  noModels: "\u8FDE\u63A5\u540E\u8BF7\u5237\u65B0\u6A21\u578B",
2606
2622
  free: "\u514D\u8D39",
@@ -2609,7 +2625,7 @@ var qoderLocales = {
2609
2625
  };
2610
2626
 
2611
2627
  // src/plugin.ts
2612
- var manifest = { name: "qoder", version: "0.3.0", coreApi: "1", description: "Qoder (qoder.com / qoder.cn) subscription provider with PAT sign-in, model management and usage." };
2628
+ var manifest = { name: "qoder", version: "0.3.2", coreApi: "1", description: "Qoder (qoder.com / qoder.cn) subscription provider with PAT sign-in, model management and usage." };
2613
2629
  function activatedTransformer(site, service) {
2614
2630
  return class ActivatedQoderTransformer extends QoderTransformer {
2615
2631
  static TransformerName = site;
package/dist/plugin.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qoder",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "coreApi": "1",
5
5
  "description": "Qoder subscription provider (qoder.com and qoder.cn): Personal Access Token sign-in, fixed chat upstream, model management and quota."
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wengine-ai/ccr-provider-qoder",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Qoder subscription provider (qoder.com and qoder.cn): Personal Access Token sign-in, fixed agent_chat_generation upstream, model management and usage.",
5
5
  "type": "module",
6
6
  "main": "dist/plugin.js",