@vacbo/opencode-anthropic-fix 0.1.7 → 0.1.9

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 (107) hide show
  1. package/README.md +88 -88
  2. package/dist/opencode-anthropic-auth-cli.mjs +804 -507
  3. package/dist/opencode-anthropic-auth-plugin.js +4751 -4109
  4. package/package.json +67 -59
  5. package/src/__tests__/billing-edge-cases.test.ts +59 -59
  6. package/src/__tests__/bun-proxy.parallel.test.ts +388 -382
  7. package/src/__tests__/cc-comparison.test.ts +87 -87
  8. package/src/__tests__/cc-credentials.test.ts +254 -250
  9. package/src/__tests__/cch-drift-checker.test.ts +51 -51
  10. package/src/__tests__/cch-native-style.test.ts +56 -56
  11. package/src/__tests__/debug-gating.test.ts +42 -42
  12. package/src/__tests__/decomposition-smoke.test.ts +68 -68
  13. package/src/__tests__/fingerprint-regression.test.ts +575 -566
  14. package/src/__tests__/helpers/conversation-history.smoke.test.ts +271 -271
  15. package/src/__tests__/helpers/conversation-history.ts +119 -119
  16. package/src/__tests__/helpers/deferred.smoke.test.ts +103 -103
  17. package/src/__tests__/helpers/deferred.ts +69 -69
  18. package/src/__tests__/helpers/in-memory-storage.smoke.test.ts +155 -155
  19. package/src/__tests__/helpers/in-memory-storage.ts +88 -88
  20. package/src/__tests__/helpers/mock-bun-proxy.smoke.test.ts +68 -68
  21. package/src/__tests__/helpers/mock-bun-proxy.ts +189 -189
  22. package/src/__tests__/helpers/plugin-fetch-harness.smoke.test.ts +273 -273
  23. package/src/__tests__/helpers/plugin-fetch-harness.ts +288 -288
  24. package/src/__tests__/helpers/sse.smoke.test.ts +236 -236
  25. package/src/__tests__/helpers/sse.ts +209 -209
  26. package/src/__tests__/index.parallel.test.ts +605 -595
  27. package/src/__tests__/sanitization-regex.test.ts +112 -112
  28. package/src/__tests__/state-bounds.test.ts +90 -90
  29. package/src/account-identity.test.ts +197 -192
  30. package/src/account-identity.ts +69 -67
  31. package/src/account-state.test.ts +86 -86
  32. package/src/account-state.ts +25 -25
  33. package/src/accounts/matching.test.ts +335 -0
  34. package/src/accounts/matching.ts +167 -0
  35. package/src/accounts/persistence.test.ts +345 -0
  36. package/src/accounts/persistence.ts +432 -0
  37. package/src/accounts/repair.test.ts +276 -0
  38. package/src/accounts/repair.ts +407 -0
  39. package/src/accounts.dedup.test.ts +621 -621
  40. package/src/accounts.test.ts +933 -929
  41. package/src/accounts.ts +633 -989
  42. package/src/backoff.test.ts +345 -345
  43. package/src/backoff.ts +219 -219
  44. package/src/betas.ts +124 -124
  45. package/src/bun-fetch.test.ts +345 -342
  46. package/src/bun-fetch.ts +424 -424
  47. package/src/bun-proxy.test.ts +25 -25
  48. package/src/bun-proxy.ts +209 -209
  49. package/src/cc-credentials.ts +111 -111
  50. package/src/circuit-breaker.test.ts +184 -184
  51. package/src/circuit-breaker.ts +169 -169
  52. package/src/cli/commands/auth.ts +963 -0
  53. package/src/cli/commands/config.ts +547 -0
  54. package/src/cli/formatting.test.ts +406 -0
  55. package/src/cli/formatting.ts +219 -0
  56. package/src/cli.ts +255 -2022
  57. package/src/commands/handlers/betas.ts +100 -0
  58. package/src/commands/handlers/config.ts +99 -0
  59. package/src/commands/handlers/files.ts +375 -0
  60. package/src/commands/oauth-flow.ts +181 -166
  61. package/src/commands/prompts.ts +61 -61
  62. package/src/commands/router.test.ts +421 -0
  63. package/src/commands/router.ts +143 -635
  64. package/src/config.test.ts +482 -482
  65. package/src/config.ts +412 -404
  66. package/src/constants.ts +48 -48
  67. package/src/drift/cch-constants.ts +95 -95
  68. package/src/env.ts +111 -105
  69. package/src/headers/billing.ts +33 -33
  70. package/src/headers/builder.ts +130 -130
  71. package/src/headers/cch.ts +75 -75
  72. package/src/headers/stainless.ts +25 -25
  73. package/src/headers/user-agent.ts +23 -23
  74. package/src/index.ts +436 -828
  75. package/src/models.ts +27 -27
  76. package/src/oauth.test.ts +102 -102
  77. package/src/oauth.ts +178 -178
  78. package/src/parent-pid-watcher.test.ts +148 -148
  79. package/src/parent-pid-watcher.ts +69 -69
  80. package/src/plugin-helpers.ts +82 -82
  81. package/src/refresh-helpers.ts +145 -139
  82. package/src/refresh-lock.test.ts +94 -94
  83. package/src/refresh-lock.ts +93 -93
  84. package/src/request/body.history.test.ts +579 -571
  85. package/src/request/body.ts +255 -255
  86. package/src/request/metadata.ts +65 -65
  87. package/src/request/retry.test.ts +156 -156
  88. package/src/request/retry.ts +67 -67
  89. package/src/request/url.ts +21 -21
  90. package/src/request-orchestration-helpers.ts +648 -0
  91. package/src/response/index.ts +5 -5
  92. package/src/response/mcp.ts +58 -58
  93. package/src/response/streaming.test.ts +313 -311
  94. package/src/response/streaming.ts +412 -410
  95. package/src/rotation.test.ts +304 -301
  96. package/src/rotation.ts +205 -205
  97. package/src/storage.test.ts +547 -547
  98. package/src/storage.ts +315 -291
  99. package/src/system-prompt/builder.ts +38 -38
  100. package/src/system-prompt/index.ts +5 -5
  101. package/src/system-prompt/normalize.ts +60 -60
  102. package/src/system-prompt/sanitize.ts +30 -30
  103. package/src/thinking.ts +21 -20
  104. package/src/token-refresh.test.ts +265 -265
  105. package/src/token-refresh.ts +219 -214
  106. package/src/types.ts +30 -30
  107. package/dist/bun-proxy.mjs +0 -291
@@ -13,14 +13,14 @@
13
13
  */
14
14
 
15
15
  export interface Deferred<T> {
16
- /** The promise that will resolve/reject when called */
17
- promise: Promise<T>;
18
- /** Resolve the promise with a value */
19
- resolve: (value: T | PromiseLike<T>) => void;
20
- /** Reject the promise with a reason */
21
- reject: (reason?: unknown) => void;
22
- /** Whether the promise has settled (resolved or rejected) */
23
- settled: boolean;
16
+ /** The promise that will resolve/reject when called */
17
+ promise: Promise<T>;
18
+ /** Resolve the promise with a value */
19
+ resolve: (value: T | PromiseLike<T>) => void;
20
+ /** Reject the promise with a reason */
21
+ reject: (reason?: unknown) => void;
22
+ /** Whether the promise has settled (resolved or rejected) */
23
+ settled: boolean;
24
24
  }
25
25
 
26
26
  /**
@@ -31,44 +31,44 @@ export interface Deferred<T> {
31
31
  * @returns Deferred object with promise, resolve, reject, and settled state
32
32
  */
33
33
  export function createDeferred<T>(): Deferred<T> {
34
- let resolve: (value: T | PromiseLike<T>) => void;
35
- let reject: (reason?: unknown) => void;
36
- let settled = false;
34
+ let resolve: (value: T | PromiseLike<T>) => void;
35
+ let reject: (reason?: unknown) => void;
36
+ let settled = false;
37
37
 
38
- const promise = new Promise<T>((res, rej) => {
39
- resolve = (value) => {
40
- if (!settled) {
41
- settled = true;
42
- res(value);
43
- }
44
- };
45
- reject = (reason) => {
46
- if (!settled) {
47
- settled = true;
48
- rej(reason);
49
- }
50
- };
51
- });
38
+ const promise = new Promise<T>((res, rej) => {
39
+ resolve = (value) => {
40
+ if (!settled) {
41
+ settled = true;
42
+ res(value);
43
+ }
44
+ };
45
+ reject = (reason) => {
46
+ if (!settled) {
47
+ settled = true;
48
+ rej(reason);
49
+ }
50
+ };
51
+ });
52
52
 
53
- return {
54
- promise,
55
- resolve: resolve!,
56
- reject: reject!,
57
- get settled() {
58
- return settled;
59
- },
60
- };
53
+ return {
54
+ promise,
55
+ resolve: resolve!,
56
+ reject: reject!,
57
+ get settled() {
58
+ return settled;
59
+ },
60
+ };
61
61
  }
62
62
 
63
63
  export interface DeferredQueue<T> {
64
- /** Add a new deferred to the queue */
65
- enqueue: () => Deferred<T>;
66
- /** Resolve the next deferred in FIFO order */
67
- resolveNext: (value: T | PromiseLike<T>) => boolean;
68
- /** Reject the next deferred in FIFO order */
69
- rejectNext: (reason?: unknown) => boolean;
70
- /** Number of pending deferreds in the queue */
71
- pending: number;
64
+ /** Add a new deferred to the queue */
65
+ enqueue: () => Deferred<T>;
66
+ /** Resolve the next deferred in FIFO order */
67
+ resolveNext: (value: T | PromiseLike<T>) => boolean;
68
+ /** Reject the next deferred in FIFO order */
69
+ rejectNext: (reason?: unknown) => boolean;
70
+ /** Number of pending deferreds in the queue */
71
+ pending: number;
72
72
  }
73
73
 
74
74
  /**
@@ -80,34 +80,34 @@ export interface DeferredQueue<T> {
80
80
  * @returns Queue with enqueue, resolveNext, rejectNext, and pending count
81
81
  */
82
82
  export function createDeferredQueue<T>(): DeferredQueue<T> {
83
- const queue: Deferred<T>[] = [];
83
+ const queue: Deferred<T>[] = [];
84
84
 
85
- return {
86
- enqueue: () => {
87
- const deferred = createDeferred<T>();
88
- queue.push(deferred);
89
- return deferred;
90
- },
91
- resolveNext: (value) => {
92
- const next = queue.shift();
93
- if (next) {
94
- next.resolve(value);
95
- return true;
96
- }
97
- return false;
98
- },
99
- rejectNext: (reason) => {
100
- const next = queue.shift();
101
- if (next) {
102
- next.reject(reason);
103
- return true;
104
- }
105
- return false;
106
- },
107
- get pending() {
108
- return queue.length;
109
- },
110
- };
85
+ return {
86
+ enqueue: () => {
87
+ const deferred = createDeferred<T>();
88
+ queue.push(deferred);
89
+ return deferred;
90
+ },
91
+ resolveNext: (value) => {
92
+ const next = queue.shift();
93
+ if (next) {
94
+ next.resolve(value);
95
+ return true;
96
+ }
97
+ return false;
98
+ },
99
+ rejectNext: (reason) => {
100
+ const next = queue.shift();
101
+ if (next) {
102
+ next.reject(reason);
103
+ return true;
104
+ }
105
+ return false;
106
+ },
107
+ get pending() {
108
+ return queue.length;
109
+ },
110
+ };
111
111
  }
112
112
 
113
113
  /**
@@ -118,5 +118,5 @@ export function createDeferredQueue<T>(): DeferredQueue<T> {
118
118
  * @returns Promise that resolves after one microtask
119
119
  */
120
120
  export function nextTick(): Promise<void> {
121
- return Promise.resolve();
121
+ return Promise.resolve();
122
122
  }
@@ -2,165 +2,165 @@ import { describe, expect, it } from "vitest";
2
2
  import { createInMemoryStorage, makeAccountsData, makeStoredAccount } from "./in-memory-storage.js";
3
3
 
4
4
  describe("in-memory-storage smoke tests", () => {
5
- it("createInMemoryStorage creates storage with initial data", () => {
6
- const initial = makeAccountsData([{ refreshToken: "tok1" }]);
7
- const storage = createInMemoryStorage(initial);
8
-
9
- expect(storage.snapshot()).toEqual(initial);
10
- });
11
-
12
- it("createInMemoryStorage creates storage with null initial state", async () => {
13
- const storage = createInMemoryStorage();
14
-
15
- // loadAccountsMock should return null
16
- const loaded = await storage.loadAccountsMock();
17
- expect(loaded).toBeNull();
18
-
19
- // snapshot should throw when null
20
- expect(() => storage.snapshot()).toThrow("Storage snapshot is null");
21
- });
22
-
23
- it("setSnapshot updates both disk and memory state", async () => {
24
- const storage = createInMemoryStorage();
25
- const data = makeAccountsData([{ refreshToken: "tok1" }]);
26
-
27
- storage.setSnapshot(data);
28
-
29
- // Memory should match
30
- expect(storage.snapshot()).toEqual(data);
31
-
32
- // Disk should match (via loadAccountsMock)
33
- const loaded = await storage.loadAccountsMock();
34
- expect(loaded).toEqual(data);
35
- });
36
-
37
- it("snapshot returns deep copy - mutations don't affect storage", () => {
38
- const initial = makeAccountsData([{ refreshToken: "tok1", enabled: true }]);
39
- const storage = createInMemoryStorage(initial);
40
-
41
- const snap = storage.snapshot();
42
- snap.accounts[0].enabled = false;
43
- snap.accounts[0].refreshToken = "mutated";
44
-
45
- // Storage should be unchanged
46
- const snap2 = storage.snapshot();
47
- expect(snap2.accounts[0].enabled).toBe(true);
48
- expect(snap2.accounts[0].refreshToken).toBe("tok1");
49
- });
50
-
51
- it("saveAccountsMock writes to disk state", async () => {
52
- const storage = createInMemoryStorage();
53
- const data = makeAccountsData([{ refreshToken: "tok1" }]);
54
-
55
- // Save via mock
56
- await storage.saveAccountsMock(data);
57
-
58
- // Should be readable via loadAccountsMock
59
- const loaded = await storage.loadAccountsMock();
60
- expect(loaded).toEqual(data);
61
- });
62
-
63
- it("mutateDiskOnly changes disk without affecting caller's snapshot", () => {
64
- const initial = makeAccountsData([{ refreshToken: "tok1", enabled: true }]);
65
- const storage = createInMemoryStorage(initial);
66
-
67
- // Get current snapshot (what test subject holds)
68
- const beforeSnapshot = storage.snapshot();
69
- expect(beforeSnapshot.accounts[0].enabled).toBe(true);
70
-
71
- // Simulate another process writing to disk
72
- storage.mutateDiskOnly((disk) => ({
73
- ...disk,
74
- accounts: disk.accounts.map((a) => ({ ...a, enabled: false })),
75
- }));
76
-
77
- // Caller's snapshot should be unchanged
78
- const afterSnapshot = storage.snapshot();
79
- expect(afterSnapshot.accounts[0].enabled).toBe(true);
80
-
81
- // But disk state should be changed
82
- expect(afterSnapshot.accounts[0].enabled).toBe(true); // Still true in memory
83
- });
84
-
85
- it("mutateDiskOnly affects subsequent loadAccountsMock calls", async () => {
86
- const initial = makeAccountsData([{ refreshToken: "tok1", enabled: true }]);
87
- const storage = createInMemoryStorage(initial);
88
-
89
- // Mutate disk
90
- storage.mutateDiskOnly((disk) => ({
91
- ...disk,
92
- accounts: disk.accounts.map((a) => ({ ...a, enabled: false })),
93
- }));
94
-
95
- // Load should see the mutated state
96
- const loaded = await storage.loadAccountsMock();
97
- expect(loaded?.accounts[0].enabled).toBe(false);
98
- });
99
-
100
- it("mutateDiskOnly throws when disk state is null", () => {
101
- const storage = createInMemoryStorage();
102
-
103
- expect(() =>
104
- storage.mutateDiskOnly((disk) => ({
105
- ...disk,
106
- accounts: [],
107
- })),
108
- ).toThrow("Cannot mutate disk - disk state is null");
109
- });
110
-
111
- it("makeStoredAccount creates valid account with defaults", () => {
112
- const account = makeStoredAccount({ refreshToken: "my-token" });
113
-
114
- expect(account.refreshToken).toBe("my-token");
115
- expect(account.id).toMatch(/^acct-/);
116
- expect(account.enabled).toBe(true);
117
- expect(account.consecutiveFailures).toBe(0);
118
- expect(account.lastFailureTime).toBeNull();
119
- expect(account.stats.requests).toBe(0);
120
- expect(account.addedAt).toBeGreaterThan(0);
121
- });
122
-
123
- it("makeStoredAccount applies overrides", () => {
124
- const account = makeStoredAccount({
125
- refreshToken: "tok1",
126
- enabled: false,
127
- consecutiveFailures: 5,
128
- email: "test@example.com",
5
+ it("createInMemoryStorage creates storage with initial data", () => {
6
+ const initial = makeAccountsData([{ refreshToken: "tok1" }]);
7
+ const storage = createInMemoryStorage(initial);
8
+
9
+ expect(storage.snapshot()).toEqual(initial);
10
+ });
11
+
12
+ it("createInMemoryStorage creates storage with null initial state", async () => {
13
+ const storage = createInMemoryStorage();
14
+
15
+ // loadAccountsMock should return null
16
+ const loaded = await storage.loadAccountsMock();
17
+ expect(loaded).toBeNull();
18
+
19
+ // snapshot should throw when null
20
+ expect(() => storage.snapshot()).toThrow("Storage snapshot is null");
21
+ });
22
+
23
+ it("setSnapshot updates both disk and memory state", async () => {
24
+ const storage = createInMemoryStorage();
25
+ const data = makeAccountsData([{ refreshToken: "tok1" }]);
26
+
27
+ storage.setSnapshot(data);
28
+
29
+ // Memory should match
30
+ expect(storage.snapshot()).toEqual(data);
31
+
32
+ // Disk should match (via loadAccountsMock)
33
+ const loaded = await storage.loadAccountsMock();
34
+ expect(loaded).toEqual(data);
129
35
  });
130
36
 
131
- expect(account.refreshToken).toBe("tok1");
132
- expect(account.enabled).toBe(false);
133
- expect(account.consecutiveFailures).toBe(5);
134
- expect(account.email).toBe("test@example.com");
135
- });
136
-
137
- it("makeAccountsData creates storage with multiple accounts", () => {
138
- const data = makeAccountsData([
139
- { refreshToken: "tok1", email: "a@test.com" },
140
- { refreshToken: "tok2", email: "b@test.com" },
141
- ]);
142
-
143
- expect(data.version).toBe(1);
144
- expect(data.activeIndex).toBe(0);
145
- expect(data.accounts).toHaveLength(2);
146
- expect(data.accounts[0].refreshToken).toBe("tok1");
147
- expect(data.accounts[1].refreshToken).toBe("tok2");
148
- expect(data.accounts[0].addedAt).toBe(1000);
149
- expect(data.accounts[1].addedAt).toBe(2000);
150
- });
151
-
152
- it("makeAccountsData accepts extra storage fields", () => {
153
- const data = makeAccountsData([{ refreshToken: "tok1" }], {
154
- activeIndex: 2,
37
+ it("snapshot returns deep copy - mutations don't affect storage", () => {
38
+ const initial = makeAccountsData([{ refreshToken: "tok1", enabled: true }]);
39
+ const storage = createInMemoryStorage(initial);
40
+
41
+ const snap = storage.snapshot();
42
+ snap.accounts[0].enabled = false;
43
+ snap.accounts[0].refreshToken = "mutated";
44
+
45
+ // Storage should be unchanged
46
+ const snap2 = storage.snapshot();
47
+ expect(snap2.accounts[0].enabled).toBe(true);
48
+ expect(snap2.accounts[0].refreshToken).toBe("tok1");
49
+ });
50
+
51
+ it("saveAccountsMock writes to disk state", async () => {
52
+ const storage = createInMemoryStorage();
53
+ const data = makeAccountsData([{ refreshToken: "tok1" }]);
54
+
55
+ // Save via mock
56
+ await storage.saveAccountsMock(data);
57
+
58
+ // Should be readable via loadAccountsMock
59
+ const loaded = await storage.loadAccountsMock();
60
+ expect(loaded).toEqual(data);
155
61
  });
156
62
 
157
- expect(data.activeIndex).toBe(2);
158
- });
63
+ it("mutateDiskOnly changes disk without affecting caller's snapshot", () => {
64
+ const initial = makeAccountsData([{ refreshToken: "tok1", enabled: true }]);
65
+ const storage = createInMemoryStorage(initial);
66
+
67
+ // Get current snapshot (what test subject holds)
68
+ const beforeSnapshot = storage.snapshot();
69
+ expect(beforeSnapshot.accounts[0].enabled).toBe(true);
70
+
71
+ // Simulate another process writing to disk
72
+ storage.mutateDiskOnly((disk) => ({
73
+ ...disk,
74
+ accounts: disk.accounts.map((a) => ({ ...a, enabled: false })),
75
+ }));
159
76
 
160
- it("storage mocks are vi.fn() instances", () => {
161
- const storage = createInMemoryStorage();
77
+ // Caller's snapshot should be unchanged
78
+ const afterSnapshot = storage.snapshot();
79
+ expect(afterSnapshot.accounts[0].enabled).toBe(true);
80
+
81
+ // But disk state should be changed
82
+ expect(afterSnapshot.accounts[0].enabled).toBe(true); // Still true in memory
83
+ });
162
84
 
163
- expect(storage.loadAccountsMock).toBeDefined();
164
- expect(storage.saveAccountsMock).toBeDefined();
165
- });
85
+ it("mutateDiskOnly affects subsequent loadAccountsMock calls", async () => {
86
+ const initial = makeAccountsData([{ refreshToken: "tok1", enabled: true }]);
87
+ const storage = createInMemoryStorage(initial);
88
+
89
+ // Mutate disk
90
+ storage.mutateDiskOnly((disk) => ({
91
+ ...disk,
92
+ accounts: disk.accounts.map((a) => ({ ...a, enabled: false })),
93
+ }));
94
+
95
+ // Load should see the mutated state
96
+ const loaded = await storage.loadAccountsMock();
97
+ expect(loaded?.accounts[0].enabled).toBe(false);
98
+ });
99
+
100
+ it("mutateDiskOnly throws when disk state is null", () => {
101
+ const storage = createInMemoryStorage();
102
+
103
+ expect(() =>
104
+ storage.mutateDiskOnly((disk) => ({
105
+ ...disk,
106
+ accounts: [],
107
+ })),
108
+ ).toThrow("Cannot mutate disk - disk state is null");
109
+ });
110
+
111
+ it("makeStoredAccount creates valid account with defaults", () => {
112
+ const account = makeStoredAccount({ refreshToken: "my-token" });
113
+
114
+ expect(account.refreshToken).toBe("my-token");
115
+ expect(account.id).toMatch(/^acct-/);
116
+ expect(account.enabled).toBe(true);
117
+ expect(account.consecutiveFailures).toBe(0);
118
+ expect(account.lastFailureTime).toBeNull();
119
+ expect(account.stats.requests).toBe(0);
120
+ expect(account.addedAt).toBeGreaterThan(0);
121
+ });
122
+
123
+ it("makeStoredAccount applies overrides", () => {
124
+ const account = makeStoredAccount({
125
+ refreshToken: "tok1",
126
+ enabled: false,
127
+ consecutiveFailures: 5,
128
+ email: "test@example.com",
129
+ });
130
+
131
+ expect(account.refreshToken).toBe("tok1");
132
+ expect(account.enabled).toBe(false);
133
+ expect(account.consecutiveFailures).toBe(5);
134
+ expect(account.email).toBe("test@example.com");
135
+ });
136
+
137
+ it("makeAccountsData creates storage with multiple accounts", () => {
138
+ const data = makeAccountsData([
139
+ { refreshToken: "tok1", email: "a@test.com" },
140
+ { refreshToken: "tok2", email: "b@test.com" },
141
+ ]);
142
+
143
+ expect(data.version).toBe(1);
144
+ expect(data.activeIndex).toBe(0);
145
+ expect(data.accounts).toHaveLength(2);
146
+ expect(data.accounts[0].refreshToken).toBe("tok1");
147
+ expect(data.accounts[1].refreshToken).toBe("tok2");
148
+ expect(data.accounts[0].addedAt).toBe(1000);
149
+ expect(data.accounts[1].addedAt).toBe(2000);
150
+ });
151
+
152
+ it("makeAccountsData accepts extra storage fields", () => {
153
+ const data = makeAccountsData([{ refreshToken: "tok1" }], {
154
+ activeIndex: 2,
155
+ });
156
+
157
+ expect(data.activeIndex).toBe(2);
158
+ });
159
+
160
+ it("storage mocks are vi.fn() instances", () => {
161
+ const storage = createInMemoryStorage();
162
+
163
+ expect(storage.loadAccountsMock).toBeDefined();
164
+ expect(storage.saveAccountsMock).toBeDefined();
165
+ });
166
166
  });