@goodandready/dsh-opencode-provider 0.5.20 → 0.5.21

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/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.21
4
+
5
+ - **Analytics completeness**: projection scans above 5000 files now select the newest files by metadata instead of an arbitrary readdir page; file-limit and unreadable-projection cases set `AnalyticsReport.partial`, surfaced in the dashboard.
6
+ - 113 tests.
7
+
3
8
  ## 0.5.20
4
9
 
5
10
  - **CI/reproducibility**: regenerated `package-lock.json` with the normal npm resolver; clean `npm ci --ignore-scripts` now succeeds and `npm run check` passes.
package/README.md CHANGED
@@ -130,12 +130,12 @@ npm pack
130
130
  Install the **packed tarball** into a profile:
131
131
 
132
132
  ```bash
133
- dsh plugin --profile web add /absolute/path/to/goodandready-dsh-opencode-provider-0.5.20.tgz
133
+ dsh plugin --profile web add /absolute/path/to/goodandready-dsh-opencode-provider-0.5.21.tgz
134
134
  # DSH Desktop:
135
- dsh plugin --profile desktop add /absolute/path/to/goodandready-dsh-opencode-provider-0.5.20.tgz
135
+ dsh plugin --profile desktop add /absolute/path/to/goodandready-dsh-opencode-provider-0.5.21.tgz
136
136
 
137
137
  # Or install the published package:
138
- dsh plugin --profile web add @goodandready/dsh-opencode-provider@0.5.20
138
+ dsh plugin --profile web add @goodandready/dsh-opencode-provider@0.5.21
139
139
  ```
140
140
 
141
141
  Restart dsh (or DSH Desktop), then pick **OpenCode (plugin)** or **OpenCode Go (plugin)** in the model picker.
package/README.ru.md CHANGED
@@ -129,12 +129,12 @@ npm pack
129
129
  Установка из **упакованного tarball**:
130
130
 
131
131
  ```bash
132
- dsh plugin --profile web add /absolute/path/to/goodandready-dsh-opencode-provider-0.5.20.tgz
132
+ dsh plugin --profile web add /absolute/path/to/goodandready-dsh-opencode-provider-0.5.21.tgz
133
133
  # DSH Desktop:
134
- dsh plugin --profile desktop add /absolute/path/to/goodandready-dsh-opencode-provider-0.5.20.tgz
134
+ dsh plugin --profile desktop add /absolute/path/to/goodandready-dsh-opencode-provider-0.5.21.tgz
135
135
 
136
136
  # Либо установка опубликованного пакета из npm:
137
- dsh plugin --profile web add @goodandready/dsh-opencode-provider@0.5.20
137
+ dsh plugin --profile web add @goodandready/dsh-opencode-provider@0.5.21
138
138
  ```
139
139
 
140
140
  После установки перезапустите dsh (или DSH Desktop) и выберите **OpenCode (plugin)** или **OpenCode Go (plugin)** в списке моделей.
package/README.zh.md CHANGED
@@ -124,12 +124,12 @@ npm pack
124
124
  通过**打包文件 (.tgz)**安装:
125
125
 
126
126
  ```bash
127
- dsh plugin --profile web add /absolute/path/to/goodandready-dsh-opencode-provider-0.5.20.tgz
127
+ dsh plugin --profile web add /absolute/path/to/goodandready-dsh-opencode-provider-0.5.21.tgz
128
128
  # DSH 桌面端:
129
- dsh plugin --profile desktop add /absolute/path/to/goodandready-dsh-opencode-provider-0.5.20.tgz
129
+ dsh plugin --profile desktop add /absolute/path/to/goodandready-dsh-opencode-provider-0.5.21.tgz
130
130
 
131
131
  # 或从 npm 安装已发布版本:
132
- dsh plugin --profile web add @goodandready/dsh-opencode-provider@0.5.20
132
+ dsh plugin --profile web add @goodandready/dsh-opencode-provider@0.5.21
133
133
  ```
134
134
 
135
135
  安装完成后重启 dsh 或 DSH 桌面端,在模型选择器中选择 **OpenCode (plugin)** 或 **OpenCode Go (plugin)** 即可。
package/lib/client.js CHANGED
@@ -138,6 +138,7 @@ window.__ModuleLoader__.load({
138
138
  heatmapByAccount: "Account",
139
139
  heatmapAllAccounts: "All accounts",
140
140
  analyticsHint: "Aggregated from local session metadata by last activity. A session that switched models is counted under its last model; failures are not exposed by the projection. Only plugin routes are counted; legacy opencode sessions belong to the built-in catalog.",
141
+ analyticsPartial: "This report is partial: the projection scan hit its file limit or skipped unreadable files.",
141
142
  analyticsEmpty: "No plugin sessions in this window. Legacy opencode sessions belong to the built-in catalog.",
142
143
  showAll: "Show all",
143
144
  modelSearch: "Search models…",
@@ -343,6 +344,7 @@ window.__ModuleLoader__.load({
343
344
  heatmapByAccount: "账户",
344
345
  heatmapAllAccounts: "全部账户",
345
346
  analyticsHint: "按最后活动时间聚合本地会话元数据。切换过模型的会话计入最后使用的模型;本地投影不暴露失败。仅统计插件路由;旧 opencode 会话属于内置目录。",
347
+ analyticsPartial: "此报告不完整:投影扫描达到文件上限或跳过了不可读文件。",
346
348
  analyticsEmpty: "此窗口内没有插件会话。旧 opencode 会话属于内置目录。",
347
349
  showAll: "显示全部",
348
350
  modelSearch: "搜索模型…",
@@ -923,6 +925,10 @@ window.__ModuleLoader__.load({
923
925
  })
924
926
  ]
925
927
  }),
928
+ analytics.partial === true ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
929
+ className: "oc-hint",
930
+ children: t("analyticsPartial")
931
+ }) : null,
926
932
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
927
933
  className: "oc-hint",
928
934
  children: t("analyticsHint")
package/lib/index.d.ts CHANGED
@@ -352,6 +352,8 @@ interface AnalyticsReport {
352
352
  summary: AnalyticsSummary;
353
353
  days: DayUsageRow[];
354
354
  sessions: SessionUsageRow[];
355
+ /** True when the projection scan hit a cap or skipped unreadable files. */
356
+ partial?: boolean;
355
357
  }
356
358
  interface RouteDeps {
357
359
  readonly config: () => ResolvedConfig;
package/lib/index.js CHANGED
@@ -18,7 +18,7 @@ const DEFAULT_GO_API_BASE = "https://opencode.ai/inference/go";
18
18
  const DEFAULT_GO_ZEN_BASE = "https://opencode.ai/zen/go/v1";
19
19
  const DEFAULT_USAGE_URL = "https://opencode.ai/zen/go/v1/usage";
20
20
  const DEFAULT_AUTH_ENTRY = "opencode-go";
21
- const DEFAULT_USER_AGENT = "dsh-opencode-provider/0.5.20";
21
+ const DEFAULT_USER_AGENT = "dsh-opencode-provider/0.5.21";
22
22
  const DEFAULT_CONTEXT_WINDOW = 262144;
23
23
  const DEFAULT_MAX_TOKENS = 32768;
24
24
  const DEFAULT_GENERATE_MAX_TOKENS = 32768;
@@ -4502,8 +4502,25 @@ async function readModelAnalytics(days = 30) {
4502
4502
  if (cached !== void 0 && Date.now() - cached.at < CACHE_TTL_MS) return cached.report;
4503
4503
  const dir = projectionDirectory();
4504
4504
  const sessions = [];
4505
+ let partial = false;
4505
4506
  try {
4506
- const files = (await readdir(dir, { withFileTypes: true })).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).slice(0, MAX_FILES);
4507
+ let files = (await readdir(dir, { withFileTypes: true })).filter((entry) => entry.isFile() && entry.name.endsWith(".json"));
4508
+ if (files.length > MAX_FILES) {
4509
+ files = (await Promise.all(files.map(async (entry) => {
4510
+ try {
4511
+ return {
4512
+ entry,
4513
+ at: (await stat(join(dir, entry.name))).mtimeMs
4514
+ };
4515
+ } catch {
4516
+ return {
4517
+ entry,
4518
+ at: 0
4519
+ };
4520
+ }
4521
+ }))).sort((left, right) => right.at - left.at).slice(0, MAX_FILES).map((item) => item.entry);
4522
+ partial = true;
4523
+ }
4507
4524
  let cursor = 0;
4508
4525
  const workers = Array.from({ length: Math.min(16, files.length) }, async () => {
4509
4526
  while (true) {
@@ -4517,12 +4534,17 @@ async function readModelAnalytics(days = 30) {
4517
4534
  meta.id = entry.name.replace(/\.json$/i, "");
4518
4535
  sessions.push(meta);
4519
4536
  }
4520
- } catch {}
4537
+ } catch {
4538
+ partial = true;
4539
+ }
4521
4540
  }
4522
4541
  });
4523
4542
  await Promise.all(workers);
4524
- } catch {}
4543
+ } catch {
4544
+ partial = true;
4545
+ }
4525
4546
  const report = aggregateSessions(sessions, clamped);
4547
+ report.partial = partial;
4526
4548
  cache.set(clamped, {
4527
4549
  at: Date.now(),
4528
4550
  report
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodandready/dsh-opencode-provider",
3
- "version": "0.5.20",
3
+ "version": "0.5.21",
4
4
  "description": "OpenCode / OpenCode Go LLM provider plugin for DeepSeek Harness (dsh).",
5
5
  "license": "MIT",
6
6
  "type": "module",