cortico-world-workbuddy 0.3.0 → 0.3.4

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.
@@ -26,7 +26,6 @@ const TEXT = {
26
26
  source: '来源',
27
27
  token: 'Token(掩码)',
28
28
  account: '账号',
29
- region: '区域',
30
29
  upstream: '上游',
31
30
  rediscover: '重新检测本机登录',
32
31
  pasteToken: '手动粘贴 access token',
@@ -39,29 +38,26 @@ const TEXT = {
39
38
  lastError: '最近错误',
40
39
  models: '个模型',
41
40
  currentModel: '当前模型',
42
- priorityTitle: '中转站优先',
43
- priorityLabel: '是否启用Workbuddy',
44
- priorityDesc:
45
- '打开后桌宠每轮对话优先调用 WorkBuddy 的模型,关闭则完全跳过 WorkBuddy。需要 WorkBuddy 桌面端主进程在运行。',
46
41
  procRunning: 'WorkBuddy 主进程:运行中',
47
42
  procStopped: 'WorkBuddy 主进程:未检测到',
48
- noProcess: '未检测到Workbuddy',
49
- enabledOn: '已开启:桌宠优先走 WorkBuddy 模型',
50
- enabledOff: '已关闭:桌宠跳过 WorkBuddy',
51
- usageTitle: '用量',
43
+ usageTitle: '用量与成本',
52
44
  usageDesc:
53
- '本机记账的调用用量与 WorkBuddy 积分包余额。积分取上游每次调用回传的真实扣费(可能为 0),倍率按目录 + 限时优惠实时计算。',
45
+ '经由 WorkBuddy 消耗的 token 与积分(本地记账):积分取上游每次调用回传的真实扣费(可能为 0),token 取同一段 SSE 的 usage;倍率按目录 + 限时优惠实时计算。',
54
46
  usageRefresh: '刷新余额',
55
47
  usageClear: '清空本地账本',
56
48
  usageCleared: '本地账本已清空',
57
49
  metricCalls: '调用',
50
+ metricFailed: '失败',
58
51
  metricCredit: '积分',
59
52
  metricInput: '输入 tok',
60
53
  metricOutput: '输出 tok',
54
+ metricCached: '缓存命中',
55
+ metricTotal: '共 tok',
61
56
  spanToday: '今天',
62
57
  spanWeek: '近 7 天',
63
58
  spanMonth: '近 30 天',
64
- byModel: '按模型',
59
+ spanAll: '全部',
60
+ byModel: '按模型(近 30 天)',
65
61
  balanceTitle: '积分包余额',
66
62
  colPkgName: '积分包',
67
63
  colPkgRemain: '剩余',
@@ -107,7 +103,6 @@ const TEXT = {
107
103
  source: 'Source',
108
104
  token: 'Token (masked)',
109
105
  account: 'Account',
110
- region: 'Region',
111
106
  upstream: 'Upstream',
112
107
  rediscover: 'Re-detect local sign-in',
113
108
  pasteToken: 'Paste an access token manually',
@@ -120,29 +115,26 @@ const TEXT = {
120
115
  lastError: 'Last error',
121
116
  models: 'models',
122
117
  currentModel: 'Current model',
123
- priorityTitle: 'Relay first',
124
- priorityLabel: 'Enable Workbuddy',
125
- priorityDesc:
126
- 'Same state as the “Relay first” button on the Home page: when on, the pet asks a WorkBuddy model first every turn; when off, WorkBuddy is skipped entirely. Requires the WorkBuddy desktop main process.',
127
118
  procRunning: 'WorkBuddy process: running',
128
119
  procStopped: 'WorkBuddy process: not detected',
129
- noProcess: 'Workbuddy not detected',
130
- enabledOn: 'On: the pet asks WorkBuddy first',
131
- enabledOff: 'Off: the pet skips WorkBuddy',
132
- usageTitle: 'Usage',
120
+ usageTitle: 'Usage & cost',
133
121
  usageDesc:
134
- 'Locally recorded call usage plus the WorkBuddy credit balance. Credits come from the per-call figure the upstream returns (may be 0); multipliers combine the catalog with time-limited offers in real time.',
122
+ 'Tokens and credits spent through WorkBuddy (locally recorded): credits are the per-call figure the upstream returns (may be 0), tokens come from the same SSE usage block; multipliers combine the catalog with time-limited offers in real time.',
135
123
  usageRefresh: 'Refresh balance',
136
124
  usageClear: 'Clear local ledger',
137
125
  usageCleared: 'Local ledger cleared',
138
126
  metricCalls: 'Calls',
127
+ metricFailed: 'Failed',
139
128
  metricCredit: 'Credits',
140
129
  metricInput: 'Input tok',
141
130
  metricOutput: 'Output tok',
131
+ metricCached: 'Cached',
132
+ metricTotal: 'Total tok',
142
133
  spanToday: 'Today',
143
134
  spanWeek: 'Last 7 days',
144
135
  spanMonth: 'Last 30 days',
145
- byModel: 'By model',
136
+ spanAll: 'All',
137
+ byModel: 'By model (last 30 days)',
146
138
  balanceTitle: 'Credit packages',
147
139
  colPkgName: 'Package',
148
140
  colPkgRemain: 'Remaining',
@@ -215,9 +207,10 @@ function mountModels(ctx) {
215
207
  const head = ui.rowbar();
216
208
  const refreshBtn = ui.button(s.refresh, { variant: 'primary' });
217
209
  const stateChip = ui.chip('', 'plain');
210
+ const procChip = ui.chip('', 'plain');
218
211
  const currentChip = ui.chip('', 'accent');
219
212
  const allBox = ui.checkbox(s.showAllModels, { checked: false });
220
- head.append(refreshBtn, stateChip, currentChip, allBox.el);
213
+ head.append(refreshBtn, stateChip, procChip, currentChip, allBox.el);
221
214
  sheet.body.append(head);
222
215
 
223
216
  const errLine = ui.msgline();
@@ -238,6 +231,7 @@ function mountModels(ctx) {
238
231
  state?.safeOnly === false ? s.safeOnlyOff : s.safeOnlyOn
239
232
  }`;
240
233
  currentChip.textContent = `${s.currentModel}: ${state?.model || '—'}`;
234
+ procChip.textContent = state?.running ? s.procRunning : s.procStopped;
241
235
  }
242
236
 
243
237
  /** 当前是否允许选这个模型:safeOnly 开时只放行安全清单。 */
@@ -397,7 +391,6 @@ function mountAccount(ctx) {
397
391
  { k: s.source, v: state?.tokenSource ?? '—' },
398
392
  { k: s.token, v: state?.tokenMask ?? '—' },
399
393
  { k: s.account, v: state?.account?.name ?? '—' },
400
- { k: s.region, v: state?.region ?? '—' },
401
394
  { k: s.upstream, v: state?.baseUrl ?? '—' },
402
395
  ];
403
396
  if (state?.lastError) rows.push({ k: s.lastError, v: state.lastError });
@@ -467,63 +460,17 @@ function mountAccount(ctx) {
467
460
  });
468
461
  }
469
462
 
470
- function mountPriority(ctx) {
471
- const s = strings(ctx);
472
- const { ui } = ctx;
473
-
474
- const sheet = ui.sheet({ title: s.priorityTitle, desc: s.priorityDesc });
475
- ctx.root.append(sheet.el);
476
-
477
- const statusLine = ui.msgline();
478
-
479
- /** 用服务端状态刷新界面(不触发 onChange)。 */
480
- function apply(r) {
481
- if (!r) return;
482
- box.setChecked(r.prefer === true);
483
- statusLine.textContent = r.running ? s.procRunning : s.procStopped;
484
- }
485
-
486
- const box = ui.checkbox(s.priorityLabel, {
487
- checked: false,
488
- title: s.priorityDesc,
489
- onChange: async (checked) => {
490
- try {
491
- const r = await ctx.invoke('set', [checked]);
492
- if (r?.ok) {
493
- apply(r);
494
- ui.toast(checked ? s.enabledOn : s.enabledOff);
495
- } else {
496
- // 没检测到 WorkBuddy 主进程(或其它失败):开关退回关,并把原因说清楚。
497
- apply(r);
498
- box.setChecked(false);
499
- ui.toast(r?.error ?? s.noProcess, 'bad');
500
- }
501
- } catch (err) {
502
- box.setChecked(false);
503
- ui.toast(String(err?.message ?? err), 'bad');
504
- }
505
- },
506
- });
507
- sheet.body.append(box.el, statusLine);
508
-
509
- async function load() {
510
- apply(await ctx.invoke('state'));
511
- }
512
-
513
- ctx.stream({
514
- message: () => load().catch(() => {}),
515
- });
516
-
517
- load().catch((err) => {
518
- statusLine.textContent = String(err?.message ?? err);
519
- });
520
- }
521
-
522
463
  function fmtNum(n) {
523
464
  if (typeof n !== 'number' || !Number.isFinite(n)) return '—';
524
465
  return String(Math.round(n * 100) / 100);
525
466
  }
526
467
 
468
+ /** 有记录未回传 credit 时明确标出缺口,绝不把未知当成 0。 */
469
+ function fmtCredit(bucket) {
470
+ const known = fmtNum(bucket?.credit);
471
+ return (bucket?.creditUnknown ?? 0) > 0 ? `${known} + ?` : known;
472
+ }
473
+
527
474
  function mountUsage(ctx) {
528
475
  const s = strings(ctx);
529
476
  const { ui } = ctx;
@@ -542,16 +489,26 @@ function mountUsage(ctx) {
542
489
  const errLine = ui.msgline();
543
490
  sheet.body.append(errLine);
544
491
 
545
- // 区间概览:今天 / 近 7 天 / 近 30 天 / 全部(口径与 Coopanion「用量与成本」一致)。
492
+ // 区间概览:今天 / 近 7 天 / 近 30 天 / 全部(口径与 Coopanion「用量与成本」一致:
493
+ // 调用数、失败数、积分、输入/输出/缓存命中/合计 token)。
546
494
  const overview = ui.table({
547
- head: ['', s.metricCalls, s.metricCredit, s.metricInput, s.metricOutput],
495
+ head: [
496
+ '',
497
+ s.metricCalls,
498
+ s.metricFailed,
499
+ s.metricCredit,
500
+ s.metricInput,
501
+ s.metricOutput,
502
+ s.metricCached,
503
+ s.metricTotal,
504
+ ],
548
505
  maxHeight: '220px',
549
506
  });
550
507
  sheet.body.append(overview.el);
551
508
 
552
509
  const modelSection = ui.section(s.byModel);
553
510
  const modelTable = ui.table({
554
- head: [s.colModel, s.metricCalls, s.metricCredit, s.metricInput, s.metricOutput],
511
+ head: [s.colModel, s.metricCalls, s.metricFailed, s.metricCredit, s.metricInput, s.metricOutput, s.metricTotal],
555
512
  maxHeight: '260px',
556
513
  });
557
514
  modelSection.append(modelTable.el);
@@ -582,24 +539,46 @@ function mountUsage(ctx) {
582
539
 
583
540
  function spanRow(label, bucket) {
584
541
  const b = bucket ?? {};
585
- return [label, String(b.calls ?? 0), fmtNum(b.credit), fmtNum(b.prompt), fmtNum(b.completion)];
542
+ return [
543
+ label,
544
+ String(b.calls ?? 0),
545
+ String(b.failed ?? 0),
546
+ fmtCredit(b),
547
+ fmtNum(b.prompt),
548
+ fmtNum(b.completion),
549
+ fmtNum(b.cached),
550
+ fmtNum(b.total),
551
+ ];
586
552
  }
587
553
 
588
554
  function render() {
589
555
  const totals = state?.summary?.totals ?? {};
590
- todayChip.textContent = `${s.todayCredit}: ${fmtNum(totals.today?.credit)} · ${s.todayTokens}: ${fmtNum(
556
+ todayChip.textContent = `${s.todayCredit}: ${fmtCredit(totals.today)} · ${s.todayTokens}: ${fmtNum(
591
557
  (totals.today?.prompt ?? 0) + (totals.today?.completion ?? 0),
592
558
  )}`;
593
559
  balanceChip.textContent = `${s.balanceTitle}: ${fmtNum(state?.balance?.total)}`;
594
560
 
595
- const spans = [spanRow(s.spanToday, totals.today), spanRow(s.spanWeek, totals.week), spanRow(s.spanMonth, totals.month)];
561
+ const spans = [
562
+ spanRow(s.spanToday, totals.today),
563
+ spanRow(s.spanWeek, totals.week),
564
+ spanRow(s.spanMonth, totals.month),
565
+ spanRow(s.spanAll, totals.all),
566
+ ];
596
567
  overview.clear();
597
568
  for (const row of spans) overview.addRow(row);
598
569
 
599
570
  const byModel = state?.summary?.byModel ?? [];
600
571
  modelTable.clear(byModel.length > 0 ? undefined : s.noData);
601
572
  for (const m of byModel) {
602
- modelTable.addRow([m.model, String(m.calls ?? 0), fmtNum(m.credit), fmtNum(m.prompt), fmtNum(m.completion)]);
573
+ modelTable.addRow([
574
+ m.model,
575
+ String(m.calls ?? 0),
576
+ String(m.failed ?? 0),
577
+ fmtCredit(m),
578
+ fmtNum(m.prompt),
579
+ fmtNum(m.completion),
580
+ fmtNum(m.total),
581
+ ]);
603
582
  }
604
583
 
605
584
  const packages = state?.balance?.packages ?? [];
@@ -706,7 +685,6 @@ export default {
706
685
  panels: {
707
686
  models: { mount: mountModels },
708
687
  account: { mount: mountAccount },
709
- priority: { mount: mountPriority },
710
688
  usage: { mount: mountUsage },
711
689
  },
712
690
  };