@iam-brain/opencode-codex-auth 0.1.7 → 0.1.8
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 +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/codex-native.d.ts +6 -2
- package/dist/lib/codex-native.d.ts.map +1 -1
- package/dist/lib/codex-native.js +106 -27
- package/dist/lib/codex-native.js.map +1 -1
- package/dist/lib/config.d.ts +7 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +40 -0
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/fetch-orchestrator.d.ts +5 -0
- package/dist/lib/fetch-orchestrator.d.ts.map +1 -1
- package/dist/lib/fetch-orchestrator.js +20 -2
- package/dist/lib/fetch-orchestrator.js.map +1 -1
- package/dist/lib/installer-cli.d.ts.map +1 -1
- package/dist/lib/installer-cli.js +5 -1
- package/dist/lib/installer-cli.js.map +1 -1
- package/dist/lib/paths.d.ts +8 -0
- package/dist/lib/paths.d.ts.map +1 -1
- package/dist/lib/paths.js +29 -2
- package/dist/lib/paths.js.map +1 -1
- package/dist/lib/personality-skill.d.ts +17 -0
- package/dist/lib/personality-skill.d.ts.map +1 -0
- package/dist/lib/personality-skill.js +136 -0
- package/dist/lib/personality-skill.js.map +1 -0
- package/dist/lib/rotation.d.ts.map +1 -1
- package/dist/lib/rotation.js +64 -73
- package/dist/lib/rotation.js.map +1 -1
- package/dist/lib/session-affinity.d.ts +26 -0
- package/dist/lib/session-affinity.d.ts.map +1 -0
- package/dist/lib/session-affinity.js +166 -0
- package/dist/lib/session-affinity.js.map +1 -0
- package/package.json +1 -1
- package/schemas/codex-config.schema.json +7 -0
package/dist/lib/rotation.js
CHANGED
|
@@ -27,76 +27,73 @@ function resolveOffsetIndex(input, eligibleLength) {
|
|
|
27
27
|
const pid = toNonNegativeInt(input.pid ?? process.pid);
|
|
28
28
|
return pid % eligibleLength;
|
|
29
29
|
}
|
|
30
|
-
function
|
|
30
|
+
function resolveAssignedSessionAccount(input, eligible, strategy) {
|
|
31
31
|
const state = input.stickySessionState;
|
|
32
32
|
const sessionKey = input.stickySessionKey?.trim();
|
|
33
33
|
if (!state || !sessionKey)
|
|
34
34
|
return undefined;
|
|
35
35
|
const assignedIdentityKey = state.bySessionKey.get(sessionKey);
|
|
36
|
-
if (assignedIdentityKey)
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
strategy: "sticky",
|
|
41
|
-
decision: "sticky-session-reuse",
|
|
42
|
-
selectedIdentityKey: assigned.identityKey,
|
|
43
|
-
activeIdentityKey: input.activeIdentityKey,
|
|
44
|
-
sessionKey,
|
|
45
|
-
eligibleCount: eligible.length
|
|
46
|
-
});
|
|
47
|
-
return assigned;
|
|
48
|
-
}
|
|
36
|
+
if (!assignedIdentityKey)
|
|
37
|
+
return undefined;
|
|
38
|
+
const assigned = eligible.find((acc) => acc.identityKey === assignedIdentityKey);
|
|
39
|
+
if (!assigned) {
|
|
49
40
|
state.bySessionKey.delete(sessionKey);
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
input.onDebug?.({
|
|
44
|
+
strategy,
|
|
45
|
+
decision: strategy === "sticky" ? "sticky-session-reuse" : "hybrid-session-reuse",
|
|
46
|
+
selectedIdentityKey: assigned.identityKey,
|
|
47
|
+
activeIdentityKey: input.activeIdentityKey,
|
|
48
|
+
sessionKey,
|
|
49
|
+
eligibleCount: eligible.length
|
|
50
|
+
});
|
|
51
|
+
return assigned;
|
|
52
|
+
}
|
|
53
|
+
function assignSessionAccount(input, selected, strategy, extra) {
|
|
54
|
+
const state = input.stickySessionState;
|
|
55
|
+
const sessionKey = input.stickySessionKey?.trim();
|
|
56
|
+
if (!state || !sessionKey || !selected?.identityKey)
|
|
57
|
+
return;
|
|
58
|
+
state.bySessionKey.set(sessionKey, selected.identityKey);
|
|
59
|
+
const maxEntries = Math.max(1, Math.floor(state.maxEntries ?? DEFAULT_SESSION_ASSIGNMENT_MAX));
|
|
60
|
+
while (state.bySessionKey.size > maxEntries) {
|
|
61
|
+
const oldest = state.bySessionKey.keys().next().value;
|
|
62
|
+
if (!oldest)
|
|
63
|
+
break;
|
|
64
|
+
state.bySessionKey.delete(oldest);
|
|
50
65
|
}
|
|
66
|
+
input.onDebug?.({
|
|
67
|
+
strategy,
|
|
68
|
+
decision: strategy === "sticky" ? "sticky-session-assign" : "hybrid-session-assign",
|
|
69
|
+
selectedIdentityKey: selected.identityKey,
|
|
70
|
+
activeIdentityKey: input.activeIdentityKey,
|
|
71
|
+
sessionKey,
|
|
72
|
+
eligibleCount: input.accounts.length,
|
|
73
|
+
...(extra ? { extra } : {})
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
function resolveStickySessionAccount(input, eligible) {
|
|
77
|
+
const reused = resolveAssignedSessionAccount(input, eligible, "sticky");
|
|
78
|
+
if (reused)
|
|
79
|
+
return reused;
|
|
51
80
|
if (eligible.length === 0)
|
|
52
81
|
return undefined;
|
|
82
|
+
const state = input.stickySessionState;
|
|
83
|
+
if (!state)
|
|
84
|
+
return undefined;
|
|
53
85
|
const index = state.cursor % eligible.length;
|
|
54
86
|
state.cursor = (state.cursor + 1) % eligible.length;
|
|
55
87
|
const selected = eligible[index];
|
|
56
88
|
if (!selected)
|
|
57
89
|
return undefined;
|
|
58
|
-
|
|
59
|
-
state.bySessionKey.set(sessionKey, selected.identityKey);
|
|
60
|
-
const maxEntries = Math.max(1, Math.floor(state.maxEntries ?? DEFAULT_SESSION_ASSIGNMENT_MAX));
|
|
61
|
-
while (state.bySessionKey.size > maxEntries) {
|
|
62
|
-
const oldest = state.bySessionKey.keys().next().value;
|
|
63
|
-
if (!oldest)
|
|
64
|
-
break;
|
|
65
|
-
state.bySessionKey.delete(oldest);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
input.onDebug?.({
|
|
69
|
-
strategy: "sticky",
|
|
70
|
-
decision: "sticky-session-assign",
|
|
71
|
-
selectedIdentityKey: selected.identityKey,
|
|
72
|
-
activeIdentityKey: input.activeIdentityKey,
|
|
73
|
-
sessionKey,
|
|
74
|
-
eligibleCount: eligible.length,
|
|
75
|
-
extra: { sessionCursor: state.cursor }
|
|
76
|
-
});
|
|
90
|
+
assignSessionAccount(input, selected, "sticky", { sessionCursor: state.cursor });
|
|
77
91
|
return selected;
|
|
78
92
|
}
|
|
79
93
|
function resolveHybridSessionAccount(input, eligible) {
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
return undefined;
|
|
84
|
-
const assignedIdentityKey = state.bySessionKey.get(sessionKey);
|
|
85
|
-
if (assignedIdentityKey) {
|
|
86
|
-
const assigned = eligible.find((acc) => acc.identityKey === assignedIdentityKey);
|
|
87
|
-
if (assigned) {
|
|
88
|
-
input.onDebug?.({
|
|
89
|
-
strategy: "hybrid",
|
|
90
|
-
decision: "hybrid-session-reuse",
|
|
91
|
-
selectedIdentityKey: assigned.identityKey,
|
|
92
|
-
activeIdentityKey: input.activeIdentityKey,
|
|
93
|
-
sessionKey,
|
|
94
|
-
eligibleCount: eligible.length
|
|
95
|
-
});
|
|
96
|
-
return assigned;
|
|
97
|
-
}
|
|
98
|
-
state.bySessionKey.delete(sessionKey);
|
|
99
|
-
}
|
|
94
|
+
const reused = resolveAssignedSessionAccount(input, eligible, "hybrid");
|
|
95
|
+
if (reused)
|
|
96
|
+
return reused;
|
|
100
97
|
const ordered = [...eligible].sort((left, right) => {
|
|
101
98
|
const leftLastUsed = left.lastUsed ?? 0;
|
|
102
99
|
const rightLastUsed = right.lastUsed ?? 0;
|
|
@@ -106,30 +103,15 @@ function resolveHybridSessionAccount(input, eligible) {
|
|
|
106
103
|
});
|
|
107
104
|
if (ordered.length === 0)
|
|
108
105
|
return undefined;
|
|
106
|
+
const state = input.stickySessionState;
|
|
107
|
+
if (!state)
|
|
108
|
+
return undefined;
|
|
109
109
|
const index = state.cursor % ordered.length;
|
|
110
110
|
state.cursor = (state.cursor + 1) % ordered.length;
|
|
111
111
|
const selected = ordered[index];
|
|
112
112
|
if (!selected)
|
|
113
113
|
return undefined;
|
|
114
|
-
|
|
115
|
-
state.bySessionKey.set(sessionKey, selected.identityKey);
|
|
116
|
-
const maxEntries = Math.max(1, Math.floor(state.maxEntries ?? DEFAULT_SESSION_ASSIGNMENT_MAX));
|
|
117
|
-
while (state.bySessionKey.size > maxEntries) {
|
|
118
|
-
const oldest = state.bySessionKey.keys().next().value;
|
|
119
|
-
if (!oldest)
|
|
120
|
-
break;
|
|
121
|
-
state.bySessionKey.delete(oldest);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
input.onDebug?.({
|
|
125
|
-
strategy: "hybrid",
|
|
126
|
-
decision: "hybrid-session-assign",
|
|
127
|
-
selectedIdentityKey: selected.identityKey,
|
|
128
|
-
activeIdentityKey: input.activeIdentityKey,
|
|
129
|
-
sessionKey,
|
|
130
|
-
eligibleCount: eligible.length,
|
|
131
|
-
extra: { sessionCursor: state.cursor }
|
|
132
|
-
});
|
|
114
|
+
assignSessionAccount(input, selected, "hybrid", { sessionCursor: state.cursor });
|
|
133
115
|
return selected;
|
|
134
116
|
}
|
|
135
117
|
export function selectAccount(input) {
|
|
@@ -149,11 +131,13 @@ export function selectAccount(input) {
|
|
|
149
131
|
? -1
|
|
150
132
|
: eligible.findIndex((acc) => acc.identityKey === activeIdentityKey);
|
|
151
133
|
if (strategy === "sticky") {
|
|
152
|
-
const stickySessionAccount =
|
|
134
|
+
const stickySessionAccount = resolveAssignedSessionAccount(input, eligible, "sticky") ??
|
|
135
|
+
(input.stickyPidOffset === true ? resolveStickySessionAccount(input, eligible) : undefined);
|
|
153
136
|
if (stickySessionAccount)
|
|
154
137
|
return stickySessionAccount;
|
|
155
138
|
if (activeIndex >= 0) {
|
|
156
139
|
const selected = eligible[activeIndex];
|
|
140
|
+
assignSessionAccount(input, selected, "sticky");
|
|
157
141
|
input.onDebug?.({
|
|
158
142
|
strategy,
|
|
159
143
|
decision: "sticky-active",
|
|
@@ -165,6 +149,7 @@ export function selectAccount(input) {
|
|
|
165
149
|
}
|
|
166
150
|
if (input.stickyPidOffset !== true) {
|
|
167
151
|
const selected = eligible[0];
|
|
152
|
+
assignSessionAccount(input, selected, "sticky");
|
|
168
153
|
input.onDebug?.({
|
|
169
154
|
strategy,
|
|
170
155
|
decision: "sticky-fallback-first",
|
|
@@ -176,6 +161,7 @@ export function selectAccount(input) {
|
|
|
176
161
|
}
|
|
177
162
|
const offsetIndex = resolveOffsetIndex(input, eligible.length);
|
|
178
163
|
const selected = eligible[offsetIndex];
|
|
164
|
+
assignSessionAccount(input, selected, "sticky", { offsetIndex });
|
|
179
165
|
input.onDebug?.({
|
|
180
166
|
strategy,
|
|
181
167
|
decision: "sticky-pid-offset",
|
|
@@ -187,6 +173,9 @@ export function selectAccount(input) {
|
|
|
187
173
|
return selected;
|
|
188
174
|
}
|
|
189
175
|
if (strategy === "hybrid") {
|
|
176
|
+
const existingSession = resolveAssignedSessionAccount(input, eligible, "hybrid");
|
|
177
|
+
if (existingSession)
|
|
178
|
+
return existingSession;
|
|
190
179
|
if (input.stickyPidOffset === true) {
|
|
191
180
|
const sessionAccount = resolveHybridSessionAccount(input, eligible);
|
|
192
181
|
if (sessionAccount)
|
|
@@ -194,6 +183,7 @@ export function selectAccount(input) {
|
|
|
194
183
|
}
|
|
195
184
|
if (activeIndex >= 0) {
|
|
196
185
|
const selected = eligible[activeIndex];
|
|
186
|
+
assignSessionAccount(input, selected, "hybrid");
|
|
197
187
|
input.onDebug?.({
|
|
198
188
|
strategy,
|
|
199
189
|
decision: "hybrid-active",
|
|
@@ -215,6 +205,7 @@ export function selectAccount(input) {
|
|
|
215
205
|
selectedLastUsed = candidateLastUsed;
|
|
216
206
|
}
|
|
217
207
|
}
|
|
208
|
+
assignSessionAccount(input, selected, "hybrid", { lastUsed: selected.lastUsed ?? 0 });
|
|
218
209
|
input.onDebug?.({
|
|
219
210
|
strategy,
|
|
220
211
|
decision: "hybrid-lru",
|
package/dist/lib/rotation.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rotation.js","sourceRoot":"","sources":["../../lib/rotation.ts"],"names":[],"mappings":"AAEA,MAAM,8BAA8B,GAAG,GAAG,CAAA;AAQ1C,MAAM,UAAU,wBAAwB,CAAC,UAAU,GAAG,8BAA8B;IAClF,OAAO;QACL,YAAY,EAAE,IAAI,GAAG,EAAkB;QACvC,MAAM,EAAE,CAAC;QACT,UAAU;KACX,CAAA;AACH,CAAC;AAoCD,SAAS,UAAU,CAAC,OAAsB,EAAE,GAAW;IACrD,IAAI,OAAO,CAAC,OAAO,KAAK,KAAK;QAAE,OAAO,KAAK,CAAA;IAC3C,IAAI,OAAO,OAAO,CAAC,aAAa,KAAK,QAAQ,IAAI,OAAO,CAAC,aAAa,GAAG,GAAG,EAAE,CAAC;QAC7E,OAAO,KAAK,CAAA;IACd,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAc;IACtC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,CAAC,CAAA;IAClE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;AACjD,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAyB,EAAE,cAAsB;IAC3E,IAAI,cAAc,IAAI,CAAC;QAAE,OAAO,CAAC,CAAA;IACjC,IAAI,KAAK,CAAC,eAAe,KAAK,IAAI;QAAE,OAAO,CAAC,CAAA;IAE5C,MAAM,GAAG,GAAG,gBAAgB,CAAC,KAAK,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,CAAA;IACtD,OAAO,GAAG,GAAG,cAAc,CAAA;AAC7B,CAAC;AAED,SAAS,
|
|
1
|
+
{"version":3,"file":"rotation.js","sourceRoot":"","sources":["../../lib/rotation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { OpenAIAuthMode } from "./types";
|
|
2
|
+
export declare const MAX_SESSION_AFFINITY_ENTRIES = 200;
|
|
3
|
+
type SessionAffinityModeRecord = {
|
|
4
|
+
seenSessionKeys?: Record<string, number>;
|
|
5
|
+
stickyBySessionKey?: Record<string, string>;
|
|
6
|
+
hybridBySessionKey?: Record<string, string>;
|
|
7
|
+
};
|
|
8
|
+
export type SessionAffinityFile = {
|
|
9
|
+
version: 1;
|
|
10
|
+
native?: SessionAffinityModeRecord;
|
|
11
|
+
codex?: SessionAffinityModeRecord;
|
|
12
|
+
};
|
|
13
|
+
export type SessionAffinitySnapshot = {
|
|
14
|
+
seenSessionKeys: Map<string, number>;
|
|
15
|
+
stickyBySessionKey: Map<string, string>;
|
|
16
|
+
hybridBySessionKey: Map<string, string>;
|
|
17
|
+
};
|
|
18
|
+
export type SessionExistsFn = (sessionKey: string) => Promise<boolean>;
|
|
19
|
+
export declare function readSessionAffinitySnapshot(file: SessionAffinityFile, mode: OpenAIAuthMode): SessionAffinitySnapshot;
|
|
20
|
+
export declare function writeSessionAffinitySnapshot(file: SessionAffinityFile, mode: OpenAIAuthMode, snapshot: SessionAffinitySnapshot): SessionAffinityFile;
|
|
21
|
+
export declare function createSessionExistsFn(env?: Record<string, string | undefined>): SessionExistsFn;
|
|
22
|
+
export declare function pruneSessionAffinitySnapshot(snapshot: SessionAffinitySnapshot, sessionExists: SessionExistsFn): Promise<number>;
|
|
23
|
+
export declare function loadSessionAffinity(filePath?: string): Promise<SessionAffinityFile>;
|
|
24
|
+
export declare function saveSessionAffinity(update: (current: SessionAffinityFile) => SessionAffinityFile | Promise<SessionAffinityFile>, filePath?: string): Promise<SessionAffinityFile>;
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=session-affinity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-affinity.d.ts","sourceRoot":"","sources":["../../lib/session-affinity.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAE7C,eAAO,MAAM,4BAA4B,MAAM,CAAA;AAE/C,KAAK,yBAAyB,GAAG;IAC/B,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACxC,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC3C,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAC5C,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,CAAC,CAAA;IACV,MAAM,CAAC,EAAE,yBAAyB,CAAA;IAClC,KAAK,CAAC,EAAE,yBAAyB,CAAA;CAClC,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACpC,kBAAkB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACvC,kBAAkB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACxC,CAAA;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;AAuFtE,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,mBAAmB,EACzB,IAAI,EAAE,cAAc,GACnB,uBAAuB,CAOzB;AAED,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,mBAAmB,EACzB,IAAI,EAAE,cAAc,EACpB,QAAQ,EAAE,uBAAuB,GAChC,mBAAmB,CAarB;AAQD,wBAAgB,qBAAqB,CACnC,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,GACpD,eAAe,CAWjB;AAED,wBAAsB,4BAA4B,CAChD,QAAQ,EAAE,uBAAuB,EACjC,aAAa,EAAE,eAAe,GAC7B,OAAO,CAAC,MAAM,CAAC,CAiBjB;AA8BD,wBAAsB,mBAAmB,CAAC,QAAQ,GAAE,MAAqC,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAEvH;AAED,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC,EAC5F,QAAQ,GAAE,MAAqC,GAC9C,OAAO,CAAC,mBAAmB,CAAC,CAK9B"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { defaultSessionAffinityPath, opencodeSessionFilePath } from "./paths";
|
|
4
|
+
export const MAX_SESSION_AFFINITY_ENTRIES = 200;
|
|
5
|
+
const DEFAULT_FILE = { version: 1 };
|
|
6
|
+
function isRecord(value) {
|
|
7
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8
|
+
}
|
|
9
|
+
function clampEntries(entries, maxEntries) {
|
|
10
|
+
if (entries.length <= maxEntries)
|
|
11
|
+
return entries;
|
|
12
|
+
return entries.slice(entries.length - maxEntries);
|
|
13
|
+
}
|
|
14
|
+
function sanitizeStringMap(value, maxEntries = MAX_SESSION_AFFINITY_ENTRIES) {
|
|
15
|
+
if (!isRecord(value))
|
|
16
|
+
return new Map();
|
|
17
|
+
const entries = [];
|
|
18
|
+
for (const [key, mapValue] of Object.entries(value)) {
|
|
19
|
+
if (key.trim().length === 0 || typeof mapValue !== "string")
|
|
20
|
+
continue;
|
|
21
|
+
entries.push([key, mapValue]);
|
|
22
|
+
}
|
|
23
|
+
return new Map(clampEntries(entries, maxEntries));
|
|
24
|
+
}
|
|
25
|
+
function sanitizeSeenMap(value, maxEntries = MAX_SESSION_AFFINITY_ENTRIES) {
|
|
26
|
+
if (!isRecord(value))
|
|
27
|
+
return new Map();
|
|
28
|
+
const entries = [];
|
|
29
|
+
for (const [key, mapValue] of Object.entries(value)) {
|
|
30
|
+
if (key.trim().length === 0 || typeof mapValue !== "number" || !Number.isFinite(mapValue)) {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
entries.push([key, Math.floor(mapValue)]);
|
|
34
|
+
}
|
|
35
|
+
entries.sort((left, right) => left[1] - right[1]);
|
|
36
|
+
return new Map(clampEntries(entries, maxEntries));
|
|
37
|
+
}
|
|
38
|
+
function toModeRecord(snapshot) {
|
|
39
|
+
const seenEntries = clampEntries([...snapshot.seenSessionKeys.entries()].sort((left, right) => left[1] - right[1]), MAX_SESSION_AFFINITY_ENTRIES);
|
|
40
|
+
const stickyEntries = clampEntries([...snapshot.stickyBySessionKey.entries()], MAX_SESSION_AFFINITY_ENTRIES);
|
|
41
|
+
const hybridEntries = clampEntries([...snapshot.hybridBySessionKey.entries()], MAX_SESSION_AFFINITY_ENTRIES);
|
|
42
|
+
return {
|
|
43
|
+
seenSessionKeys: Object.fromEntries(seenEntries),
|
|
44
|
+
stickyBySessionKey: Object.fromEntries(stickyEntries),
|
|
45
|
+
hybridBySessionKey: Object.fromEntries(hybridEntries)
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function sanitizeFile(input) {
|
|
49
|
+
if (!isRecord(input))
|
|
50
|
+
return { ...DEFAULT_FILE };
|
|
51
|
+
const out = { version: 1 };
|
|
52
|
+
for (const mode of ["native", "codex"]) {
|
|
53
|
+
const rawMode = input[mode];
|
|
54
|
+
if (!isRecord(rawMode))
|
|
55
|
+
continue;
|
|
56
|
+
const modeSnapshot = {
|
|
57
|
+
seenSessionKeys: sanitizeSeenMap(rawMode.seenSessionKeys),
|
|
58
|
+
stickyBySessionKey: sanitizeStringMap(rawMode.stickyBySessionKey),
|
|
59
|
+
hybridBySessionKey: sanitizeStringMap(rawMode.hybridBySessionKey)
|
|
60
|
+
};
|
|
61
|
+
if (modeSnapshot.seenSessionKeys.size > 0 ||
|
|
62
|
+
modeSnapshot.stickyBySessionKey.size > 0 ||
|
|
63
|
+
modeSnapshot.hybridBySessionKey.size > 0) {
|
|
64
|
+
out[mode] = toModeRecord(modeSnapshot);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return out;
|
|
68
|
+
}
|
|
69
|
+
export function readSessionAffinitySnapshot(file, mode) {
|
|
70
|
+
const modeRecord = file[mode];
|
|
71
|
+
return {
|
|
72
|
+
seenSessionKeys: sanitizeSeenMap(modeRecord?.seenSessionKeys),
|
|
73
|
+
stickyBySessionKey: sanitizeStringMap(modeRecord?.stickyBySessionKey),
|
|
74
|
+
hybridBySessionKey: sanitizeStringMap(modeRecord?.hybridBySessionKey)
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
export function writeSessionAffinitySnapshot(file, mode, snapshot) {
|
|
78
|
+
const next = sanitizeFile(file);
|
|
79
|
+
const modeRecord = toModeRecord(snapshot);
|
|
80
|
+
if (Object.keys(modeRecord.seenSessionKeys ?? {}).length === 0 &&
|
|
81
|
+
Object.keys(modeRecord.stickyBySessionKey ?? {}).length === 0 &&
|
|
82
|
+
Object.keys(modeRecord.hybridBySessionKey ?? {}).length === 0) {
|
|
83
|
+
delete next[mode];
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
next[mode] = modeRecord;
|
|
87
|
+
}
|
|
88
|
+
return next;
|
|
89
|
+
}
|
|
90
|
+
function isSafeSessionKey(sessionKey) {
|
|
91
|
+
if (!sessionKey || !sessionKey.trim())
|
|
92
|
+
return false;
|
|
93
|
+
if (sessionKey.includes("/") || sessionKey.includes("\\") || sessionKey.includes(".."))
|
|
94
|
+
return false;
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
export function createSessionExistsFn(env = process.env) {
|
|
98
|
+
return async (sessionKey) => {
|
|
99
|
+
if (!isSafeSessionKey(sessionKey))
|
|
100
|
+
return false;
|
|
101
|
+
const filePath = opencodeSessionFilePath(sessionKey, env);
|
|
102
|
+
try {
|
|
103
|
+
await fs.access(filePath);
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
export async function pruneSessionAffinitySnapshot(snapshot, sessionExists) {
|
|
112
|
+
const keySet = new Set([
|
|
113
|
+
...snapshot.seenSessionKeys.keys(),
|
|
114
|
+
...snapshot.stickyBySessionKey.keys(),
|
|
115
|
+
...snapshot.hybridBySessionKey.keys()
|
|
116
|
+
]);
|
|
117
|
+
let removed = 0;
|
|
118
|
+
for (const sessionKey of keySet) {
|
|
119
|
+
const exists = await sessionExists(sessionKey);
|
|
120
|
+
if (exists)
|
|
121
|
+
continue;
|
|
122
|
+
if (snapshot.seenSessionKeys.delete(sessionKey))
|
|
123
|
+
removed += 1;
|
|
124
|
+
snapshot.stickyBySessionKey.delete(sessionKey);
|
|
125
|
+
snapshot.hybridBySessionKey.delete(sessionKey);
|
|
126
|
+
}
|
|
127
|
+
return removed;
|
|
128
|
+
}
|
|
129
|
+
async function readUnlocked(filePath) {
|
|
130
|
+
try {
|
|
131
|
+
const raw = await fs.readFile(filePath, "utf8");
|
|
132
|
+
const parsed = JSON.parse(raw);
|
|
133
|
+
return sanitizeFile(parsed);
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
|
|
137
|
+
return { ...DEFAULT_FILE };
|
|
138
|
+
}
|
|
139
|
+
return { ...DEFAULT_FILE };
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
async function writeUnlocked(filePath, file) {
|
|
143
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
144
|
+
const tmpPath = `${filePath}.tmp`;
|
|
145
|
+
await fs.writeFile(tmpPath, `${JSON.stringify(file, null, 2)}\n`, {
|
|
146
|
+
encoding: "utf8",
|
|
147
|
+
mode: 0o600
|
|
148
|
+
});
|
|
149
|
+
await fs.rename(tmpPath, filePath);
|
|
150
|
+
try {
|
|
151
|
+
await fs.chmod(filePath, 0o600);
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
// best-effort permissions
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
export async function loadSessionAffinity(filePath = defaultSessionAffinityPath()) {
|
|
158
|
+
return readUnlocked(filePath);
|
|
159
|
+
}
|
|
160
|
+
export async function saveSessionAffinity(update, filePath = defaultSessionAffinityPath()) {
|
|
161
|
+
const current = await readUnlocked(filePath);
|
|
162
|
+
const next = sanitizeFile(await update(current));
|
|
163
|
+
await writeUnlocked(filePath, next);
|
|
164
|
+
return next;
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=session-affinity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-affinity.js","sourceRoot":"","sources":["../../lib/session-affinity.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -36,12 +36,19 @@
|
|
|
36
36
|
"type": "string",
|
|
37
37
|
"enum": ["native", "codex", "collab"]
|
|
38
38
|
},
|
|
39
|
+
"rotationStrategy": {
|
|
40
|
+
"type": "string",
|
|
41
|
+
"enum": ["sticky", "hybrid", "round_robin"]
|
|
42
|
+
},
|
|
39
43
|
"sanitizeInputs": {
|
|
40
44
|
"type": "boolean"
|
|
41
45
|
},
|
|
42
46
|
"headerSnapshots": {
|
|
43
47
|
"type": "boolean"
|
|
44
48
|
},
|
|
49
|
+
"headerTransformDebug": {
|
|
50
|
+
"type": "boolean"
|
|
51
|
+
},
|
|
45
52
|
"pidOffset": {
|
|
46
53
|
"type": "boolean"
|
|
47
54
|
}
|