@polderlabs/bizar 4.4.13 → 4.5.1

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 (118) hide show
  1. package/bizar-dash/CHANGELOG.md +37 -276
  2. package/bizar-dash/dist/assets/__vite-browser-external-BIHI7g3E.js +2 -0
  3. package/bizar-dash/dist/assets/__vite-browser-external-BIHI7g3E.js.map +1 -0
  4. package/bizar-dash/dist/assets/main-eWZ4NlCL.css +1 -0
  5. package/bizar-dash/dist/assets/main-usWhlPWa.js +362 -0
  6. package/bizar-dash/dist/assets/main-usWhlPWa.js.map +1 -0
  7. package/bizar-dash/dist/assets/{mobile-DSb-t42Y.js → mobile-DQLFCjwJ.js} +2 -2
  8. package/bizar-dash/dist/assets/{mobile-DSb-t42Y.js.map → mobile-DQLFCjwJ.js.map} +1 -1
  9. package/bizar-dash/dist/assets/mobile-O6ANdD4W.js +352 -0
  10. package/bizar-dash/dist/assets/mobile-O6ANdD4W.js.map +1 -0
  11. package/bizar-dash/dist/index.html +3 -3
  12. package/bizar-dash/dist/mobile.html +2 -2
  13. package/bizar-dash/skills/agent-baseline/SKILL.md +80 -0
  14. package/bizar-dash/skills/bizar/SKILL.md +116 -0
  15. package/bizar-dash/skills/chat/SKILL.md +74 -0
  16. package/bizar-dash/skills/headroom/SKILL.md +94 -0
  17. package/bizar-dash/skills/lightrag/SKILL.md +86 -0
  18. package/bizar-dash/skills/minimax/SKILL.md +80 -0
  19. package/bizar-dash/skills/obsidian/SKILL.md +68 -0
  20. package/bizar-dash/skills/providers/SKILL.md +75 -0
  21. package/bizar-dash/skills/sdk/SKILL.md +138 -0
  22. package/bizar-dash/skills/self-improvement/SKILL.md +53 -0
  23. package/bizar-dash/skills/skills-cli/SKILL.md +94 -0
  24. package/bizar-dash/skills/usage/SKILL.md +62 -0
  25. package/bizar-dash/src/server/api.mjs +18 -0
  26. package/bizar-dash/src/server/headroom.mjs +645 -0
  27. package/bizar-dash/src/server/memory-lightrag.mjs +272 -2
  28. package/bizar-dash/src/server/memory-obsidian.mjs +230 -0
  29. package/bizar-dash/src/server/memory-store.mjs +189 -0
  30. package/bizar-dash/src/server/minimax-usage-store.mjs +372 -0
  31. package/bizar-dash/src/server/minimax.mjs +196 -5
  32. package/bizar-dash/src/server/providers-store.mjs +956 -0
  33. package/bizar-dash/src/server/routes/_shared.mjs +17 -0
  34. package/bizar-dash/src/server/routes/config.mjs +52 -1
  35. package/bizar-dash/src/server/routes/env-vars.mjs +165 -0
  36. package/bizar-dash/src/server/routes/headroom.mjs +126 -0
  37. package/bizar-dash/src/server/routes/lightrag.mjs +154 -0
  38. package/bizar-dash/src/server/routes/memory.mjs +668 -1
  39. package/bizar-dash/src/server/routes/opencode-session-detail.mjs +14 -29
  40. package/bizar-dash/src/server/routes/opencode-sessions.mjs +205 -3
  41. package/bizar-dash/src/server/routes/providers.mjs +266 -5
  42. package/bizar-dash/src/server/routes/skills.mjs +32 -43
  43. package/bizar-dash/src/server/routes/update.mjs +340 -0
  44. package/bizar-dash/src/server/routes/usage.mjs +136 -0
  45. package/bizar-dash/src/server/serve-info.mjs +135 -4
  46. package/bizar-dash/src/server/server.mjs +20 -0
  47. package/bizar-dash/src/server/skills-store.mjs +152 -262
  48. package/bizar-dash/src/web/App.tsx +120 -29
  49. package/bizar-dash/src/web/components/EnvVarManager.tsx +247 -0
  50. package/bizar-dash/src/web/components/HeadroomSettings.tsx +418 -0
  51. package/bizar-dash/src/web/components/HeadroomStatus.tsx +158 -0
  52. package/bizar-dash/src/web/components/SettingsSearch.tsx +213 -0
  53. package/bizar-dash/src/web/components/Topbar.tsx +2 -1
  54. package/bizar-dash/src/web/components/UsageChart.tsx +250 -0
  55. package/bizar-dash/src/web/components/UsageTable.tsx +90 -0
  56. package/bizar-dash/src/web/components/chat/ChatComposer.tsx +21 -25
  57. package/bizar-dash/src/web/components/chat/ChatInfoPanel.tsx +199 -37
  58. package/bizar-dash/src/web/components/chat/ChatThread.tsx +29 -17
  59. package/bizar-dash/src/web/components/chat/FloatingComposer.tsx +7 -1
  60. package/bizar-dash/src/web/components/chat/InfoPanel.tsx +71 -6
  61. package/bizar-dash/src/web/components/chat/useChat.ts +751 -257
  62. package/bizar-dash/src/web/lib/api.ts +43 -0
  63. package/bizar-dash/src/web/lib/types.ts +16 -0
  64. package/bizar-dash/src/web/main.tsx +2 -0
  65. package/bizar-dash/src/web/mobile/views/MobileChat.tsx +110 -35
  66. package/bizar-dash/src/web/styles/chat.css +135 -1
  67. package/bizar-dash/src/web/styles/main.css +46 -0
  68. package/bizar-dash/src/web/styles/memory.css +955 -0
  69. package/bizar-dash/src/web/styles/minimax-usage.css +335 -0
  70. package/bizar-dash/src/web/styles/settings.css +418 -0
  71. package/bizar-dash/src/web/styles/skills.css +302 -0
  72. package/bizar-dash/src/web/styles/tasks.css +288 -0
  73. package/bizar-dash/src/web/views/Chat.tsx +276 -48
  74. package/bizar-dash/src/web/views/Config.tsx +3 -2065
  75. package/bizar-dash/src/web/views/Memory.tsx +140 -0
  76. package/bizar-dash/src/web/views/MiniMaxUsage.tsx +476 -461
  77. package/bizar-dash/src/web/views/Overview.tsx +3 -0
  78. package/bizar-dash/src/web/views/Settings.tsx +36 -0
  79. package/bizar-dash/src/web/views/Skills.tsx +208 -260
  80. package/bizar-dash/src/web/views/Tasks.tsx +348 -1119
  81. package/bizar-dash/src/web/views/memory/ConfigPanel.tsx +289 -0
  82. package/bizar-dash/src/web/views/memory/GitSyncPanel.tsx +220 -0
  83. package/bizar-dash/src/web/views/memory/LightragPanel.tsx +307 -0
  84. package/bizar-dash/src/web/views/memory/MemoryOverview.tsx +354 -0
  85. package/bizar-dash/src/web/views/memory/MemoryStatusCard.tsx +160 -0
  86. package/bizar-dash/src/web/views/memory/ObsidianPanel.tsx +642 -0
  87. package/bizar-dash/src/web/views/memory/SemanticSearchPanel.tsx +194 -0
  88. package/bizar-dash/tests/chat-session-create.test.mjs +391 -0
  89. package/bizar-dash/tests/chat-session-stream.test.mjs +308 -0
  90. package/bizar-dash/tests/env-vars-store.test.mjs +216 -0
  91. package/bizar-dash/tests/headroom-install.test.mjs +173 -0
  92. package/bizar-dash/tests/headroom-settings.test.mjs +126 -0
  93. package/bizar-dash/tests/headroom-status.test.mjs +117 -0
  94. package/bizar-dash/tests/lightrag-defaults.node.test.mjs +118 -0
  95. package/bizar-dash/tests/memory-lightrag-extended.test.mjs +162 -0
  96. package/bizar-dash/tests/memory-obsidian.test.mjs +269 -0
  97. package/bizar-dash/tests/memory-tab.test.mjs +322 -0
  98. package/bizar-dash/tests/minimax-chat-usage.test.mjs +178 -0
  99. package/bizar-dash/tests/minimax-usage-store.node.test.mjs +293 -0
  100. package/bizar-dash/tests/mod-upgrade.node.test.mjs +1 -1
  101. package/bizar-dash/tests/opencode-sessions-detail.test.mjs +12 -9
  102. package/bizar-dash/tests/providers-store-backup-keys.node.test.mjs +479 -3
  103. package/bizar-dash/tests/providers-store-search.node.test.mjs +166 -0
  104. package/bizar-dash/tests/skills-list.test.mjs +232 -0
  105. package/bizar-dash/tests/skills-search.test.mjs +222 -0
  106. package/bizar-dash/tests/submit-feedback.test.mjs +6 -6
  107. package/bizar-dash/tests/tasks-create.test.mjs +187 -0
  108. package/bizar-dash/tests/update-check.test.mjs +127 -0
  109. package/bizar-dash/tests/update-run.test.mjs +266 -0
  110. package/cli/bin.mjs +247 -1
  111. package/cli/provision.mjs +118 -4
  112. package/config/agents/_shared/SKILLS.md +109 -0
  113. package/package.json +1 -1
  114. package/bizar-dash/dist/assets/main-BB5mJurD.js +0 -352
  115. package/bizar-dash/dist/assets/main-BB5mJurD.js.map +0 -1
  116. package/bizar-dash/dist/assets/main-BsnQLXdh.css +0 -1
  117. package/bizar-dash/dist/assets/mobile-Dl1q7Cyq.js +0 -354
  118. package/bizar-dash/dist/assets/mobile-Dl1q7Cyq.js.map +0 -1
@@ -308,11 +308,31 @@ export async function fetchRemains({ force = false } = {}) {
308
308
  if (!force) {
309
309
  const cached = readCachedRemains();
310
310
  if (cached && cached.apiKeyHint === maskKey(resolved.key) && (Date.now() - cached.fetchedAt) < 60_000) {
311
+ // Cached — still record it so usage totals stay honest.
312
+ await recordUsageDynamic({
313
+ providerId: 'minimax',
314
+ modelId: 'unknown',
315
+ endpoint: 'remains',
316
+ requestId: `rem_${Math.random().toString(36).slice(2, 9)}`,
317
+ promptTokens: 0,
318
+ completionTokens: 0,
319
+ totalTokens: 0,
320
+ cachedTokens: 0,
321
+ reasoningTokens: 0,
322
+ latencyMs: 0,
323
+ finishReason: null,
324
+ error: null,
325
+ keyEnvVar: resolved.source,
326
+ isBackup: false,
327
+ cached: true,
328
+ });
311
329
  return { ok: true, cached: true, ...cached };
312
330
  }
313
331
  }
314
332
  const urls = resolveBaseUrls();
315
333
  const url = `${urls.tokenBase.replace(/\/$/, '')}/v1/token_plan/remains?group_id=${encodeURIComponent(resolved.groupId)}`;
334
+ const requestId = `rem_${Math.random().toString(36).slice(2, 9)}`;
335
+ const startMs = Date.now();
316
336
  let resp;
317
337
  try {
318
338
  resp = await fetchWithTimeout(url, {
@@ -324,28 +344,102 @@ export async function fetchRemains({ force = false } = {}) {
324
344
  },
325
345
  });
326
346
  } catch (err) {
347
+ const latencyMs = Date.now() - startMs;
348
+ await recordUsageDynamic({
349
+ providerId: 'minimax',
350
+ modelId: 'unknown',
351
+ endpoint: 'remains',
352
+ requestId,
353
+ promptTokens: 0,
354
+ completionTokens: 0,
355
+ totalTokens: 0,
356
+ cachedTokens: 0,
357
+ reasoningTokens: 0,
358
+ latencyMs,
359
+ finishReason: null,
360
+ error: { code: 'network_error', message: err.message || 'fetch failed' },
361
+ keyEnvVar: resolved.source,
362
+ isBackup: false,
363
+ cached: false,
364
+ });
327
365
  return { ok: false, error: 'network_error', message: err.message || 'fetch failed' };
328
366
  }
367
+ const latencyMs = Date.now() - startMs;
329
368
  const text = await resp.text();
330
369
  let body = null;
331
370
  try { body = text ? JSON.parse(text) : null; } catch { /* keep as null */ }
332
371
  if (!resp.ok) {
372
+ const errMsg = body?.base_resp?.status_msg || resp.statusText || 'request failed';
373
+ await recordUsageDynamic({
374
+ providerId: 'minimax',
375
+ modelId: 'unknown',
376
+ endpoint: 'remains',
377
+ requestId,
378
+ promptTokens: 0,
379
+ completionTokens: 0,
380
+ totalTokens: 0,
381
+ cachedTokens: 0,
382
+ reasoningTokens: 0,
383
+ latencyMs,
384
+ finishReason: null,
385
+ error: { code: `http_${resp.status}`, message: errMsg },
386
+ keyEnvVar: resolved.source,
387
+ isBackup: false,
388
+ cached: false,
389
+ });
333
390
  return {
334
391
  ok: false,
335
392
  error: `http_${resp.status}`,
336
- message: body?.base_resp?.status_msg || resp.statusText || 'request failed',
393
+ message: errMsg,
337
394
  status: resp.status,
338
395
  };
339
396
  }
340
397
  if (!body || body.base_resp?.status_code !== 0) {
398
+ const errMsg = body?.base_resp?.status_msg || 'unknown error';
399
+ await recordUsageDynamic({
400
+ providerId: 'minimax',
401
+ modelId: 'unknown',
402
+ endpoint: 'remains',
403
+ requestId,
404
+ promptTokens: 0,
405
+ completionTokens: 0,
406
+ totalTokens: 0,
407
+ cachedTokens: 0,
408
+ reasoningTokens: 0,
409
+ latencyMs,
410
+ finishReason: null,
411
+ error: { code: 'api_error', message: errMsg },
412
+ keyEnvVar: resolved.source,
413
+ isBackup: false,
414
+ cached: false,
415
+ });
341
416
  return {
342
417
  ok: false,
343
418
  error: 'api_error',
344
- message: body?.base_resp?.status_msg || 'unknown error',
419
+ message: errMsg,
345
420
  raw: body,
346
421
  };
347
422
  }
348
423
 
424
+ // Record success for remains (no token metering — it's a quota check).
425
+ await recordUsageDynamic({
426
+ providerId: 'minimax',
427
+ modelId: 'unknown',
428
+ endpoint: 'remains',
429
+ requestId,
430
+ promptTokens: 0,
431
+ completionTokens: 0,
432
+ totalTokens: 0,
433
+ cachedTokens: 0,
434
+ reasoningTokens: 0,
435
+ latencyMs,
436
+ finishReason: null,
437
+ error: null,
438
+ keyEnvVar: resolved.source,
439
+ isBackup: false,
440
+ cached: false,
441
+ });
442
+
349
443
  // Augment with ISO timestamps + human labels for the UI.
350
444
  const models = (body.model_remains || []).map((m) => ({
351
445
  ...m,
@@ -403,6 +497,8 @@ export async function chatCompletion({
403
497
  max_completion_tokens: maxTokens,
404
498
  stream: false,
405
499
  });
500
+ const requestId = `msg_${Math.random().toString(36).slice(2, 9)}`;
501
+ const startMs = Date.now();
406
502
  let resp;
407
503
  try {
408
504
  resp = await fetchWithTimeout(url, {
@@ -415,41 +511,136 @@ export async function chatCompletion({
415
511
  body,
416
512
  });
417
513
  } catch (err) {
514
+ // Record error usage.
515
+ await recordUsageDynamic({
516
+ providerId: 'minimax',
517
+ modelId: model,
518
+ endpoint: 'chat',
519
+ requestId,
520
+ promptTokens: 0,
521
+ completionTokens: 0,
522
+ totalTokens: 0,
523
+ cachedTokens: 0,
524
+ reasoningTokens: 0,
525
+ latencyMs: Date.now() - startMs,
526
+ finishReason: null,
527
+ error: { code: 'network_error', message: err.message || 'fetch failed' },
528
+ keyEnvVar: resolved.source,
529
+ isBackup: false,
530
+ cached: false,
531
+ });
418
532
  return { ok: false, error: 'network_error', message: err.message || 'fetch failed' };
419
533
  }
534
+ const latencyMs = Date.now() - startMs;
420
535
  const text = await resp.text();
421
536
  let data = null;
422
537
  try { data = text ? JSON.parse(text) : null; } catch { /* ignore */ }
423
538
  if (!resp.ok) {
539
+ const errMsg = data?.base_resp?.status_msg || resp.statusText || 'request failed';
540
+ // Record error usage.
541
+ await recordUsageDynamic({
542
+ providerId: 'minimax',
543
+ modelId: model,
544
+ endpoint: 'chat',
545
+ requestId,
546
+ promptTokens: 0,
547
+ completionTokens: 0,
548
+ totalTokens: 0,
549
+ cachedTokens: 0,
550
+ reasoningTokens: 0,
551
+ latencyMs,
552
+ finishReason: null,
553
+ error: { code: `http_${resp.status}`, message: errMsg },
554
+ keyEnvVar: resolved.source,
555
+ isBackup: false,
556
+ cached: false,
557
+ });
424
558
  return {
425
559
  ok: false,
426
560
  error: `http_${resp.status}`,
427
- message: data?.base_resp?.status_msg || resp.statusText || 'request failed',
561
+ message: errMsg,
428
562
  status: resp.status,
429
563
  raw: data,
430
564
  };
431
565
  }
432
566
  if (!data || data.base_resp?.status_code !== 0) {
567
+ const errMsg = data?.base_resp?.status_msg || 'unknown error';
568
+ // Record error usage.
569
+ await recordUsageDynamic({
570
+ providerId: 'minimax',
571
+ modelId: model,
572
+ endpoint: 'chat',
573
+ requestId,
574
+ promptTokens: 0,
575
+ completionTokens: 0,
576
+ totalTokens: 0,
577
+ cachedTokens: 0,
578
+ reasoningTokens: 0,
579
+ latencyMs,
580
+ finishReason: null,
581
+ error: { code: 'api_error', message: errMsg },
582
+ keyEnvVar: resolved.source,
583
+ isBackup: false,
584
+ cached: false,
585
+ });
433
586
  return {
434
587
  ok: false,
435
588
  error: 'api_error',
436
- message: data?.base_resp?.status_msg || 'unknown error',
589
+ message: errMsg,
437
590
  raw: data,
438
591
  };
439
592
  }
440
593
  const choice = (data.choices || [])[0] || {};
441
594
  const content = choice?.message?.content || '';
595
+ const usage = data.usage || null;
596
+ const promptTokens = usage?.prompt_tokens ?? 0;
597
+ const completionTokens = usage?.completion_tokens ?? 0;
598
+ const totalTokens = usage?.total_tokens ?? promptTokens + completionTokens;
599
+ const cachedTokens = usage?.prompt_tokens_details?.cached_tokens ?? 0;
600
+ const reasoningTokens = usage?.completion_tokens_details?.reasoning_tokens ?? 0;
601
+
602
+ // Record success usage.
603
+ await recordUsageDynamic({
604
+ providerId: 'minimax',
605
+ modelId: data.model || model,
606
+ endpoint: 'chat',
607
+ requestId,
608
+ promptTokens,
609
+ completionTokens,
610
+ totalTokens,
611
+ cachedTokens,
612
+ reasoningTokens,
613
+ latencyMs,
614
+ finishReason: choice?.finish_reason || null,
615
+ error: null,
616
+ keyEnvVar: resolved.source,
617
+ isBackup: false,
618
+ cached: false,
619
+ });
620
+
442
621
  return {
443
622
  ok: true,
444
623
  model: data.model || model,
445
624
  content,
446
625
  reasoning: choice?.message?.reasoning_content || null,
447
626
  finishReason: choice?.finish_reason || null,
448
- usage: data.usage || null,
627
+ usage,
449
628
  baseResp: data.base_resp,
450
629
  };
451
630
  }
452
631
 
632
+ /**
633
+ * Dynamically import the usage store and record a usage entry.
634
+ * Separated from chatCompletion() to avoid a circular import.
635
+ * @param {object} record
636
+ */
637
+ async function recordUsageDynamic(record) {
638
+ try {
639
+ const { recordUsage } = await import('./minimax-usage-store.mjs');
640
+ recordUsage(record);
641
+ } catch { /* best-effort — usage recording must never break the API */ }
642
+ }
643
+
453
644
  // ─── Helpers ────────────────────────────────────────────────────────────────
454
645
 
455
646
  /** Mask the API key for safe logging / display. Shows last 4 chars. */