aisubs 0.3.9 → 0.3.10

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,12 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.10 - 2026-09-22
4
+
5
+ - Cache the resolved OpenCode compatibility version for one hour and deduplicate
6
+ concurrent lookups.
7
+ - Keep using the last successful version when an hourly GitHub refresh fails,
8
+ while rate-limiting initial lookup failures too.
9
+
3
10
  ## 0.3.9 - 2026-09-22
4
11
 
5
12
  - Resolve the current OpenCode release for every authorized request instead of
@@ -2,6 +2,7 @@ import { randomBytes } from "node:crypto";
2
2
  import { bearerRequest, isRecord, numberValue, requireAllowedHost, responseJson, stringArray, stringValue, } from "../utils.js";
3
3
  const API_HOST = "opencode.ai";
4
4
  const API_KEY_LIFETIME_MS = 365 * 24 * 60 * 60_000;
5
+ const COMPATIBILITY_VERSION_TTL_MS = 60 * 60_000;
5
6
  const ID_PATTERN = /^(ses|msg)_[0-9a-f]{12}[0-9A-Za-z]{14}$/;
6
7
  const ID_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
7
8
  function openCodeUsageMeter(id, label, raw) {
@@ -38,15 +39,44 @@ export function parseOpenCodeGoUsage(raw) {
38
39
  }
39
40
  function openCodeProvider(config, options = {}) {
40
41
  const fetcher = options.fetch ?? globalThis.fetch;
42
+ let versionCache;
43
+ let versionRequest;
41
44
  const compatibilityVersion = async () => {
42
- const response = await fetcher("https://api.github.com/repos/anomalyco/opencode/releases/latest", { headers: { accept: "application/vnd.github+json", "user-agent": "aisubs" } });
43
- if (!response.ok)
44
- throw new Error(`OpenCode version lookup failed: ${response.status}`);
45
- const raw = await response.json();
46
- const version = isRecord(raw) ? stringValue(raw.tag_name)?.replace(/^v/, "") : undefined;
47
- if (!version)
48
- throw new Error("OpenCode version lookup returned no release version");
49
- return version;
45
+ if (versionCache && Date.now() < versionCache.expiresAt) {
46
+ if (versionCache.value)
47
+ return versionCache.value;
48
+ throw versionCache.error;
49
+ }
50
+ if (versionRequest)
51
+ return versionRequest;
52
+ const staleVersion = versionCache?.value;
53
+ versionRequest = (async () => {
54
+ try {
55
+ const response = await fetcher("https://api.github.com/repos/anomalyco/opencode/releases/latest", { headers: { accept: "application/vnd.github+json", "user-agent": "aisubs" } });
56
+ if (!response.ok)
57
+ throw new Error(`OpenCode version lookup failed: ${response.status}`);
58
+ const raw = await response.json();
59
+ const version = isRecord(raw) ? stringValue(raw.tag_name)?.replace(/^v/, "") : undefined;
60
+ if (!version)
61
+ throw new Error("OpenCode version lookup returned no release version");
62
+ versionCache = { value: version, expiresAt: Date.now() + COMPATIBILITY_VERSION_TTL_MS };
63
+ return version;
64
+ }
65
+ catch (error) {
66
+ versionCache = {
67
+ value: staleVersion,
68
+ error,
69
+ expiresAt: Date.now() + COMPATIBILITY_VERSION_TTL_MS,
70
+ };
71
+ if (staleVersion)
72
+ return staleVersion;
73
+ throw error;
74
+ }
75
+ finally {
76
+ versionRequest = undefined;
77
+ }
78
+ })();
79
+ return versionRequest;
50
80
  };
51
81
  const routingIds = new Map();
52
82
  let lastTimestamp = 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aisubs",
3
- "version": "0.3.9",
3
+ "version": "0.3.10",
4
4
  "description": "Connect AI provider accounts and use those subscriptions from any local tool or as api.",
5
5
  "keywords": [
6
6
  "ai",