saros-proxy 0.9.0 → 0.10.1
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/LICENSE +0 -0
- package/README.md +50 -28
- package/dist/cli/autostart.d.ts +0 -0
- package/dist/cli/autostart.js +0 -0
- package/dist/cli/autostart.js.map +0 -0
- package/dist/cli/daemon.d.ts +0 -0
- package/dist/cli/daemon.js +0 -0
- package/dist/cli/daemon.js.map +0 -0
- package/dist/cli/dsh-config.d.ts +0 -0
- package/dist/cli/dsh-config.js +0 -0
- package/dist/cli/dsh-config.js.map +0 -0
- package/dist/cli/harness-models.d.ts +0 -0
- package/dist/cli/harness-models.js +0 -0
- package/dist/cli/harness-models.js.map +0 -0
- package/dist/cli/harness-sync.d.ts +0 -0
- package/dist/cli/harness-sync.js +0 -0
- package/dist/cli/harness-sync.js.map +0 -0
- package/dist/cli/help.d.ts +0 -0
- package/dist/cli/help.js +0 -0
- package/dist/cli/help.js.map +0 -0
- package/dist/cli/omp-config.d.ts +0 -0
- package/dist/cli/omp-config.js +0 -0
- package/dist/cli/omp-config.js.map +0 -0
- package/dist/cli/opencode-config.d.ts +0 -0
- package/dist/cli/opencode-config.js +0 -0
- package/dist/cli/opencode-config.js.map +0 -0
- package/dist/cli/overview.d.ts +0 -0
- package/dist/cli/overview.js +0 -0
- package/dist/cli/overview.js.map +0 -0
- package/dist/cli/pi-config.d.ts +0 -0
- package/dist/cli/pi-config.js +0 -0
- package/dist/cli/pi-config.js.map +0 -0
- package/dist/cli/setup.d.ts +0 -0
- package/dist/cli/setup.js +2 -2
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/ui.d.ts +1 -1
- package/dist/cli/ui.js +0 -0
- package/dist/cli/ui.js.map +1 -1
- package/dist/cli/update-check.d.ts +0 -0
- package/dist/cli/update-check.js +0 -0
- package/dist/cli/update-check.js.map +0 -0
- package/dist/cli/usage.d.ts +0 -0
- package/dist/cli/usage.js +71 -5
- package/dist/cli/usage.js.map +1 -1
- package/dist/config.d.ts +0 -0
- package/dist/config.js +0 -0
- package/dist/config.js.map +0 -0
- package/dist/constants.d.ts +3 -0
- package/dist/constants.js +4 -0
- package/dist/constants.js.map +1 -1
- package/dist/index.d.ts +0 -0
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/key-encryption.d.ts +0 -0
- package/dist/key-encryption.js +0 -0
- package/dist/key-encryption.js.map +0 -0
- package/dist/logger.d.ts +0 -0
- package/dist/logger.js +0 -0
- package/dist/logger.js.map +0 -0
- package/dist/model-probe.d.ts +0 -0
- package/dist/model-probe.js +0 -0
- package/dist/model-probe.js.map +0 -0
- package/dist/model-stats.d.ts +0 -0
- package/dist/model-stats.js +0 -0
- package/dist/model-stats.js.map +0 -0
- package/dist/models-fetcher.d.ts +0 -0
- package/dist/models-fetcher.js +0 -0
- package/dist/models-fetcher.js.map +0 -0
- package/dist/models-sync.d.ts +0 -0
- package/dist/models-sync.js +0 -0
- package/dist/models-sync.js.map +0 -0
- package/dist/probe-cache.d.ts +0 -0
- package/dist/probe-cache.js +0 -0
- package/dist/probe-cache.js.map +0 -0
- package/dist/providers/commandcode.d.ts +0 -0
- package/dist/providers/commandcode.js +5 -0
- package/dist/providers/commandcode.js.map +1 -1
- package/dist/providers/index.d.ts +1 -1
- package/dist/providers/index.js +2 -2
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/infer.d.ts +4 -4
- package/dist/providers/infer.js +0 -0
- package/dist/providers/infer.js.map +0 -0
- package/dist/providers/opencode-go.d.ts +0 -0
- package/dist/providers/opencode-go.js +15 -4
- package/dist/providers/opencode-go.js.map +1 -1
- package/dist/providers/types.d.ts +17 -0
- package/dist/providers/types.js +0 -0
- package/dist/providers/types.js.map +0 -0
- package/dist/proxy-logic.d.ts +15 -0
- package/dist/proxy-logic.js +17 -0
- package/dist/proxy-logic.js.map +1 -1
- package/dist/proxy.d.ts +23 -0
- package/dist/proxy.js +137 -46
- package/dist/proxy.js.map +1 -1
- package/dist/token-usage.d.ts +53 -0
- package/dist/token-usage.js +198 -0
- package/dist/token-usage.js.map +1 -0
- package/dist/usage-client.d.ts +25 -4
- package/dist/usage-client.js +43 -12
- package/dist/usage-client.js.map +1 -1
- package/dist/validation.d.ts +4 -4
- package/dist/validation.js +4 -4
- package/dist/validation.js.map +0 -0
- package/package.json +6 -6
- package/dist/dashboard-parser.d.ts +0 -47
- package/dist/dashboard-parser.js +0 -88
- package/dist/dashboard-parser.js.map +0 -1
- package/dist/firefox-cookies.d.ts +0 -42
- package/dist/firefox-cookies.js +0 -170
- package/dist/firefox-cookies.js.map +0 -1
- package/dist/scraper.d.ts +0 -70
- package/dist/scraper.js +0 -239
- package/dist/scraper.js.map +0 -1
package/dist/scraper.d.ts
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* scraper.ts — Dashboard scraper; Saros uses this to predict account exhaustion.
|
|
3
|
-
*
|
|
4
|
-
* Provides both one-shot scraping (scrapeDashboard) and a background scraper
|
|
5
|
-
* that periodically fetches dashboard pages for all configured accounts.
|
|
6
|
-
* Uses recursive setTimeout (not setInterval) with AbortController to prevent
|
|
7
|
-
* overlapping cycles and to support clean shutdown.
|
|
8
|
-
*/
|
|
9
|
-
import { type UsageData } from './dashboard-parser.js';
|
|
10
|
-
import type { ScrapingAccount } from './config.js';
|
|
11
|
-
export interface ScrapeResult {
|
|
12
|
-
/** Whether the fetch and parse completed successfully. */
|
|
13
|
-
success: boolean;
|
|
14
|
-
/** Parsed usage data when successful. */
|
|
15
|
-
usage?: UsageData;
|
|
16
|
-
/** Human-readable error message on failure. */
|
|
17
|
-
error?: string;
|
|
18
|
-
/** HTTP status code returned by the upstream server, if reachable. */
|
|
19
|
-
httpStatus?: number;
|
|
20
|
-
/** Wall-clock duration of the entire fetch+parse operation in milliseconds. */
|
|
21
|
-
durationMs?: number;
|
|
22
|
-
}
|
|
23
|
-
interface AccountUsage {
|
|
24
|
-
usage: UsageData;
|
|
25
|
-
lastScrapedAt: Date;
|
|
26
|
-
lastError?: string;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Fetch the OpenCode-Go dashboard and parse usage percentages.
|
|
30
|
-
*
|
|
31
|
-
* Makes a single HTTP GET request to `https://opencode.ai/workspace/{workspaceId}/go`
|
|
32
|
-
* with the provided auth cookie. On a successful 2xx response the HTML is parsed
|
|
33
|
-
* with {@link parseAllUsage} and the resulting usage data is returned.
|
|
34
|
-
*
|
|
35
|
-
* @param workspaceId — The OpenCode workspace identifier.
|
|
36
|
-
* @param authCookie — The `auth` cookie value for authentication.
|
|
37
|
-
* @param options - Optional settings.
|
|
38
|
-
* @param options.timeoutMs - Request timeout in milliseconds (default: 15000).
|
|
39
|
-
* @returns A {@link ScrapeResult} with status, parsed data, and timing info.
|
|
40
|
-
*/
|
|
41
|
-
export declare function scrapeDashboard(workspaceId: string, authCookie: string, options?: {
|
|
42
|
-
timeoutMs?: number;
|
|
43
|
-
signal?: AbortSignal;
|
|
44
|
-
}): Promise<ScrapeResult>;
|
|
45
|
-
/**
|
|
46
|
-
* Get all usage data (for health endpoint).
|
|
47
|
-
*/
|
|
48
|
-
export declare function getAllUsage(): Map<string, AccountUsage>;
|
|
49
|
-
/**
|
|
50
|
-
* Clear the in-memory usage store (for testing).
|
|
51
|
-
* Production code should NOT call this unless resetting state is intentional.
|
|
52
|
-
*/
|
|
53
|
-
export declare function clearUsageStore(): void;
|
|
54
|
-
/**
|
|
55
|
-
* Start the background scraper.
|
|
56
|
-
* Scrapes all configured accounts every intervalMs using recursive setTimeout,
|
|
57
|
-
* preventing overlapping cycles. If already running, aborts the previous cycle
|
|
58
|
-
* and clears its timer first.
|
|
59
|
-
*/
|
|
60
|
-
export declare function startScraper(accounts: ScrapingAccount[], intervalMs: number): void;
|
|
61
|
-
/**
|
|
62
|
-
* Stop the background scraper.
|
|
63
|
-
* Aborts any in-flight scrape cycle and clears the scheduled timer.
|
|
64
|
-
*/
|
|
65
|
-
export declare function stopScraper(): void;
|
|
66
|
-
/**
|
|
67
|
-
* Check if the scraper is currently running (either a cycle in flight or a timer scheduled).
|
|
68
|
-
*/
|
|
69
|
-
export declare function isScraperRunning(): boolean;
|
|
70
|
-
export {};
|
package/dist/scraper.js
DELETED
|
@@ -1,239 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* scraper.ts — Dashboard scraper; Saros uses this to predict account exhaustion.
|
|
3
|
-
*
|
|
4
|
-
* Provides both one-shot scraping (scrapeDashboard) and a background scraper
|
|
5
|
-
* that periodically fetches dashboard pages for all configured accounts.
|
|
6
|
-
* Uses recursive setTimeout (not setInterval) with AbortController to prevent
|
|
7
|
-
* overlapping cycles and to support clean shutdown.
|
|
8
|
-
*/
|
|
9
|
-
import { parseAllUsage } from './dashboard-parser.js';
|
|
10
|
-
import { logger } from './logger.js';
|
|
11
|
-
/** Module-level store: workspaceId → AccountUsage */
|
|
12
|
-
const usageStore = new Map();
|
|
13
|
-
/** Active timer handle, if any */
|
|
14
|
-
let scraperTimer = null;
|
|
15
|
-
/** AbortController for the current scrape cycle, if any */
|
|
16
|
-
let abortController = null;
|
|
17
|
-
// ---------------------------------------------------------------------------
|
|
18
|
-
// Constants
|
|
19
|
-
// ---------------------------------------------------------------------------
|
|
20
|
-
const FIREFOX_UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:136.0) Gecko/20100101 Firefox/136.0';
|
|
21
|
-
const DEFAULT_TIMEOUT_MS = 15_000;
|
|
22
|
-
// ---------------------------------------------------------------------------
|
|
23
|
-
// Helpers
|
|
24
|
-
// ---------------------------------------------------------------------------
|
|
25
|
-
/**
|
|
26
|
-
* Combine multiple AbortSignals into one — fires when any of them fire.
|
|
27
|
-
* Cleans up listeners when any signal fires or when the resulting signal
|
|
28
|
-
* is garbage collected.
|
|
29
|
-
*/
|
|
30
|
-
function anySignal(signals) {
|
|
31
|
-
const controller = new AbortController();
|
|
32
|
-
for (const signal of signals) {
|
|
33
|
-
if (signal.aborted) {
|
|
34
|
-
controller.abort(signal.reason);
|
|
35
|
-
return controller.signal;
|
|
36
|
-
}
|
|
37
|
-
signal.addEventListener('abort', () => controller.abort(signal.reason), { once: true });
|
|
38
|
-
}
|
|
39
|
-
return controller.signal;
|
|
40
|
-
}
|
|
41
|
-
// ---------------------------------------------------------------------------
|
|
42
|
-
// Public API
|
|
43
|
-
// ---------------------------------------------------------------------------
|
|
44
|
-
/**
|
|
45
|
-
* Fetch the OpenCode-Go dashboard and parse usage percentages.
|
|
46
|
-
*
|
|
47
|
-
* Makes a single HTTP GET request to `https://opencode.ai/workspace/{workspaceId}/go`
|
|
48
|
-
* with the provided auth cookie. On a successful 2xx response the HTML is parsed
|
|
49
|
-
* with {@link parseAllUsage} and the resulting usage data is returned.
|
|
50
|
-
*
|
|
51
|
-
* @param workspaceId — The OpenCode workspace identifier.
|
|
52
|
-
* @param authCookie — The `auth` cookie value for authentication.
|
|
53
|
-
* @param options - Optional settings.
|
|
54
|
-
* @param options.timeoutMs - Request timeout in milliseconds (default: 15000).
|
|
55
|
-
* @returns A {@link ScrapeResult} with status, parsed data, and timing info.
|
|
56
|
-
*/
|
|
57
|
-
export async function scrapeDashboard(workspaceId, authCookie, options) {
|
|
58
|
-
const start = performance.now();
|
|
59
|
-
const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
60
|
-
const url = `https://opencode.ai/workspace/${encodeURIComponent(workspaceId)}/go`;
|
|
61
|
-
try {
|
|
62
|
-
// Combine external signal with timeout via race
|
|
63
|
-
const externalSignal = options?.signal;
|
|
64
|
-
const timeoutSignal = AbortSignal.timeout(timeoutMs);
|
|
65
|
-
const combinedSignal = externalSignal
|
|
66
|
-
? anySignal([externalSignal, timeoutSignal])
|
|
67
|
-
: timeoutSignal;
|
|
68
|
-
const response = await fetch(url, {
|
|
69
|
-
headers: {
|
|
70
|
-
Cookie: `auth=${authCookie}`,
|
|
71
|
-
'User-Agent': FIREFOX_UA,
|
|
72
|
-
},
|
|
73
|
-
signal: combinedSignal,
|
|
74
|
-
});
|
|
75
|
-
const httpStatus = response.status;
|
|
76
|
-
const durationMs = Math.round(performance.now() - start);
|
|
77
|
-
// Classify HTTP error status into a user-facing error message
|
|
78
|
-
if (!response.ok) {
|
|
79
|
-
let error;
|
|
80
|
-
if (httpStatus === 401 || httpStatus === 403) {
|
|
81
|
-
error = 'Cookie expired or invalid';
|
|
82
|
-
}
|
|
83
|
-
else if (httpStatus === 429) {
|
|
84
|
-
error = 'Rate limited by opencode.ai';
|
|
85
|
-
}
|
|
86
|
-
else {
|
|
87
|
-
error = `HTTP ${httpStatus}`;
|
|
88
|
-
}
|
|
89
|
-
return {
|
|
90
|
-
success: false,
|
|
91
|
-
error,
|
|
92
|
-
httpStatus,
|
|
93
|
-
durationMs,
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
// Parse HTML body
|
|
97
|
-
const html = await response.text();
|
|
98
|
-
const usage = parseAllUsage(html);
|
|
99
|
-
return {
|
|
100
|
-
success: true,
|
|
101
|
-
usage,
|
|
102
|
-
httpStatus,
|
|
103
|
-
durationMs,
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
catch (err) {
|
|
107
|
-
const durationMs = Math.round(performance.now() - start);
|
|
108
|
-
// Timeout
|
|
109
|
-
if (err instanceof DOMException && err.name === 'TimeoutError') {
|
|
110
|
-
return {
|
|
111
|
-
success: false,
|
|
112
|
-
error: 'Request timed out',
|
|
113
|
-
durationMs,
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
// Intentional abort (from our AbortController during stop)
|
|
117
|
-
if (err instanceof DOMException && err.name === 'AbortError') {
|
|
118
|
-
return {
|
|
119
|
-
success: false,
|
|
120
|
-
error: 'Aborted',
|
|
121
|
-
durationMs,
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
// Network or other errors
|
|
125
|
-
const message = err instanceof Error ? err.message : 'Unknown fetch error';
|
|
126
|
-
return {
|
|
127
|
-
success: false,
|
|
128
|
-
error: message,
|
|
129
|
-
durationMs,
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
// ---------------------------------------------------------------------------
|
|
134
|
-
// Usage store accessors
|
|
135
|
-
// ---------------------------------------------------------------------------
|
|
136
|
-
/**
|
|
137
|
-
* Get all usage data (for health endpoint).
|
|
138
|
-
*/
|
|
139
|
-
export function getAllUsage() {
|
|
140
|
-
return new Map(usageStore);
|
|
141
|
-
}
|
|
142
|
-
/**
|
|
143
|
-
* Clear the in-memory usage store (for testing).
|
|
144
|
-
* Production code should NOT call this unless resetting state is intentional.
|
|
145
|
-
*/
|
|
146
|
-
export function clearUsageStore() {
|
|
147
|
-
usageStore.clear();
|
|
148
|
-
}
|
|
149
|
-
// ---------------------------------------------------------------------------
|
|
150
|
-
// Timer management
|
|
151
|
-
// ---------------------------------------------------------------------------
|
|
152
|
-
/**
|
|
153
|
-
* Scrape a single account and update the store.
|
|
154
|
-
*/
|
|
155
|
-
async function scrapeAndStore(account, signal) {
|
|
156
|
-
const result = await scrapeDashboard(account.workspaceId, account.authCookie, { signal });
|
|
157
|
-
if (result.success && result.usage) {
|
|
158
|
-
usageStore.set(account.workspaceId, {
|
|
159
|
-
usage: result.usage,
|
|
160
|
-
lastScrapedAt: new Date(),
|
|
161
|
-
});
|
|
162
|
-
logger.info({ workspaceId: account.workspaceId, durationMs: result.durationMs }, 'Scraped dashboard for %s', account.workspaceId);
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
const prev = usageStore.get(account.workspaceId);
|
|
166
|
-
usageStore.set(account.workspaceId, {
|
|
167
|
-
usage: prev?.usage ?? { rolling: null, weekly: null, monthly: null },
|
|
168
|
-
lastScrapedAt: new Date(),
|
|
169
|
-
lastError: result.error ?? 'Unknown error',
|
|
170
|
-
});
|
|
171
|
-
logger.warn({ workspaceId: account.workspaceId, error: result.error, httpStatus: result.httpStatus }, 'Failed to scrape dashboard for %s: %s', account.workspaceId, result.error);
|
|
172
|
-
}
|
|
173
|
-
// Error already logged and stored above — no further action needed
|
|
174
|
-
}
|
|
175
|
-
/**
|
|
176
|
-
* Run a full scrape cycle across all configured accounts sequentially.
|
|
177
|
-
* Checks the abort signal between accounts and returns early if aborted.
|
|
178
|
-
*/
|
|
179
|
-
async function runScrapeCycle(accounts, signal) {
|
|
180
|
-
for (const account of accounts) {
|
|
181
|
-
if (signal?.aborted)
|
|
182
|
-
return;
|
|
183
|
-
await scrapeAndStore(account, signal);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
/**
|
|
187
|
-
* Start the background scraper.
|
|
188
|
-
* Scrapes all configured accounts every intervalMs using recursive setTimeout,
|
|
189
|
-
* preventing overlapping cycles. If already running, aborts the previous cycle
|
|
190
|
-
* and clears its timer first.
|
|
191
|
-
*/
|
|
192
|
-
export function startScraper(accounts, intervalMs) {
|
|
193
|
-
// Cancel any in-flight cycle and clear any existing timer
|
|
194
|
-
stopScraper();
|
|
195
|
-
const controller = new AbortController();
|
|
196
|
-
abortController = controller;
|
|
197
|
-
const schedule = async () => {
|
|
198
|
-
if (controller.signal.aborted)
|
|
199
|
-
return;
|
|
200
|
-
await runScrapeCycle(accounts, controller.signal).catch((err) => {
|
|
201
|
-
logger.error({ err }, 'Scrape cycle failed');
|
|
202
|
-
});
|
|
203
|
-
if (controller.signal.aborted)
|
|
204
|
-
return;
|
|
205
|
-
scraperTimer = setTimeout(schedule, intervalMs);
|
|
206
|
-
// Allow the process to exit even if the timer is still running
|
|
207
|
-
if (scraperTimer && typeof scraperTimer === 'object' && 'unref' in scraperTimer) {
|
|
208
|
-
scraperTimer.unref();
|
|
209
|
-
}
|
|
210
|
-
};
|
|
211
|
-
// Start first cycle immediately
|
|
212
|
-
schedule().catch((err) => {
|
|
213
|
-
logger.error({ err }, 'Initial scrape cycle failed');
|
|
214
|
-
});
|
|
215
|
-
logger.info('Background scraper started (interval: %d ms, accounts: %d)', intervalMs, accounts.length);
|
|
216
|
-
}
|
|
217
|
-
/**
|
|
218
|
-
* Stop the background scraper.
|
|
219
|
-
* Aborts any in-flight scrape cycle and clears the scheduled timer.
|
|
220
|
-
*/
|
|
221
|
-
export function stopScraper() {
|
|
222
|
-
if (abortController !== null) {
|
|
223
|
-
abortController.abort();
|
|
224
|
-
abortController = null;
|
|
225
|
-
}
|
|
226
|
-
if (scraperTimer !== null) {
|
|
227
|
-
clearTimeout(scraperTimer);
|
|
228
|
-
scraperTimer = null;
|
|
229
|
-
}
|
|
230
|
-
// Only log if we actually stopped something — allows idempotent calls from startScraper
|
|
231
|
-
// without spurious "stopped" messages when nothing was running.
|
|
232
|
-
}
|
|
233
|
-
/**
|
|
234
|
-
* Check if the scraper is currently running (either a cycle in flight or a timer scheduled).
|
|
235
|
-
*/
|
|
236
|
-
export function isScraperRunning() {
|
|
237
|
-
return scraperTimer !== null || abortController !== null;
|
|
238
|
-
}
|
|
239
|
-
//# sourceMappingURL=scraper.js.map
|
package/dist/scraper.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scraper.js","sourceRoot":"","sources":["../src/scraper.ts"],"names":[],"mappings":"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"}
|