@anthonyhaussman/opencode-agy-auth 1.0.11-alpha.4 → 1.0.11-alpha.5

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/README.md CHANGED
@@ -56,6 +56,33 @@ Additionally, you can quickly check your quota using the `/agyquota` slash comma
56
56
 
57
57
  This calls the injected `agy_quota` tool to give you a real-time table of your current usage, tokens remaining, and reset times.
58
58
 
59
+ ### Disk Persistence
60
+
61
+ The plugin persists turn-state and retry-cooldown data to disk so that it survives OpenCode restarts. Files are stored under `~/.config/opencode/` (or `%APPDATA%\opencode\` on Windows):
62
+
63
+ - `antigravity-turn-states.json` - tracks thinking/reasoning state across request turns, with a 24-hour TTL and 5-second throttled writes using atomic tmp+rename.
64
+ - Retry cooldowns are persisted via `CooldownStore` with the same atomic-write pattern.
65
+
66
+ Both stores initialize lazily at runtime - no filesystem reads occur at import time.
67
+
68
+ #### `diskEnabled` Parameter
69
+
70
+ `TurnStateTracker` accepts a `diskEnabled` constructor parameter (defaults to `true`):
71
+
72
+ ```ts
73
+ import { TurnStateTracker } from "@anthonyhaussman/opencode-agy-auth/sdk/request/turn-state-tracker";
74
+
75
+ // Disk persistence enabled (default)
76
+ const tracker = new TurnStateTracker(true);
77
+
78
+ // Memory-only mode - no filesystem reads or writes
79
+ const tracker = new TurnStateTracker(false);
80
+ ```
81
+
82
+ When `diskEnabled` is `false`, the tracker operates entirely in memory. All state is lost when the process exits. This is useful in restricted environments (containers, read-only filesystems) where disk access is unavailable or undesirable.
83
+
84
+ If disk initialization fails at runtime (permission error, corrupt file, etc.), the plugin automatically falls back to memory-only mode and logs a warning. No configuration is needed for normal use - disk persistence works out of the box.
85
+
59
86
  ## Local Testing
60
87
 
61
88
  To test and develop the plugin locally with OpenCode before publishing:
package/dist/index.js CHANGED
@@ -1861,6 +1861,11 @@ function initTurnStateTracker() {
1861
1861
  if (!trackerInstance) {
1862
1862
  try {
1863
1863
  trackerInstance = new TurnStateTracker(true);
1864
+ if (typeof process !== "undefined") {
1865
+ process.on("exit", () => {
1866
+ trackerInstance?.shutdown();
1867
+ });
1868
+ }
1864
1869
  } catch {
1865
1870
  trackerInstance = new TurnStateTracker(false);
1866
1871
  }
@@ -2296,6 +2301,11 @@ function initCooldownPersistence() {
2296
2301
  retryCooldownByKey.set(key, expiresAt);
2297
2302
  }
2298
2303
  cooldownStore.bind(retryCooldownByKey);
2304
+ if (typeof process !== "undefined") {
2305
+ process.on("exit", () => {
2306
+ cooldownStore.shutdown();
2307
+ });
2308
+ }
2299
2309
  } catch {
2300
2310
  cooldownStore.bind(retryCooldownByKey);
2301
2311
  }
@@ -17244,12 +17254,8 @@ function transformRequestBody(body, projectId, effectiveModel, requestedModel, t
17244
17254
  const tracker = getTurnStateTracker();
17245
17255
  let needsRecovery = false;
17246
17256
  if (sessionId2 && tracker) {
17247
- const existing = tracker.getState(sessionId2);
17248
- if (existing) {
17249
- needsRecovery = existing.inToolLoop && !existing.turnHasThinking;
17250
- } else {
17251
- needsRecovery = tracker.recoverFromContents(sessionId2, contents2).inToolLoop && !tracker.getState(sessionId2)?.turnHasThinking;
17252
- }
17257
+ const state = tracker.getState(sessionId2) ?? tracker.recoverFromContents(sessionId2, contents2);
17258
+ needsRecovery = state.inToolLoop && !state.turnHasThinking;
17253
17259
  }
17254
17260
  if (needsRecovery) {
17255
17261
  contents2 = closeToolLoopForThinking(contents2);
@@ -17282,12 +17288,8 @@ function transformRequestBody(body, projectId, effectiveModel, requestedModel, t
17282
17288
  const tracker = getTurnStateTracker();
17283
17289
  let needsRecovery = false;
17284
17290
  if (sessionId && tracker) {
17285
- const existing = tracker.getState(sessionId);
17286
- if (existing) {
17287
- needsRecovery = existing.inToolLoop && !existing.turnHasThinking;
17288
- } else {
17289
- needsRecovery = tracker.recoverFromContents(sessionId, contents).inToolLoop && !tracker.getState(sessionId)?.turnHasThinking;
17290
- }
17291
+ const state = tracker.getState(sessionId) ?? tracker.recoverFromContents(sessionId, contents);
17292
+ needsRecovery = state.inToolLoop && !state.turnHasThinking;
17291
17293
  }
17292
17294
  if (needsRecovery) {
17293
17295
  contents = closeToolLoopForThinking(contents);