sneakoscope 10.6.0 → 10.6.2
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 +1 -1
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/dist/config/skills-manifest.json +1 -1
- package/dist/core/codex-lb/desktop-bridge/capacity-retry-advice.js +89 -0
- package/dist/core/codex-lb/desktop-bridge/compaction-adapter.js +4 -1
- package/dist/core/codex-lb/desktop-bridge/http-forward.js +14 -2
- package/dist/core/codex-lb/desktop-bridge/responses-websocket.js +9 -1
- package/dist/core/version.js +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
Sneakoscope Codex (`sks`) is an open-source local tool for the Codex CLI and Codex desktop app. It adds a macOS control center, bounded agent workflows, repository context, and evidence checks for SKS releases.
|
|
18
18
|
<!-- END SKS SEARCH VISIBILITY MARKETING -->
|
|
19
19
|
|
|
20
|
-
Current package: **SKS 10.6.
|
|
20
|
+
Current package: **SKS 10.6.2**, prepared for npm publication.
|
|
21
21
|
[Release notes](https://github.com/mandarange/Sneakoscope-Codex/releases/tag/v10.5.8)
|
|
22
22
|
· [Changelog](CHANGELOG.md). Install the latest stable release from npm.
|
|
23
23
|
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { Transform } from 'node:stream';
|
|
2
|
+
export const MODEL_CAPACITY_ERROR_CODE = 'server_is_overloaded';
|
|
3
|
+
export const MODEL_CAPACITY_RETRY_AFTER_SECONDS = 5;
|
|
4
|
+
function isObject(value) {
|
|
5
|
+
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
6
|
+
}
|
|
7
|
+
function carriesRetryAfter(headers) {
|
|
8
|
+
return isObject(headers) && Object.keys(headers).some((name) => name.toLowerCase() === 'retry-after');
|
|
9
|
+
}
|
|
10
|
+
export function adviseModelCapacityRetry(event) {
|
|
11
|
+
const error = event.type === 'response.failed' ? (isObject(event.response) ? event.response.error : null)
|
|
12
|
+
: event.type === 'error' ? event.error
|
|
13
|
+
: null;
|
|
14
|
+
if (!isObject(error) || error.code !== MODEL_CAPACITY_ERROR_CODE)
|
|
15
|
+
return false;
|
|
16
|
+
if (event.type === 'error' && carriesRetryAfter(event.headers))
|
|
17
|
+
return false;
|
|
18
|
+
const headers = error.headers ?? {};
|
|
19
|
+
if (!isObject(headers) || carriesRetryAfter(headers))
|
|
20
|
+
return false;
|
|
21
|
+
error.headers = { ...headers, 'Retry-After': String(MODEL_CAPACITY_RETRY_AFTER_SECONDS) };
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
export function modelCapacityAdvisedFrame(frame) {
|
|
25
|
+
if (!frame.includes(MODEL_CAPACITY_ERROR_CODE))
|
|
26
|
+
return null;
|
|
27
|
+
let event;
|
|
28
|
+
try {
|
|
29
|
+
event = JSON.parse(frame.toString('utf8'));
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
return isObject(event) && adviseModelCapacityRetry(event) ? Buffer.from(JSON.stringify(event)) : null;
|
|
35
|
+
}
|
|
36
|
+
export function isAdvisableEventStream(headers) {
|
|
37
|
+
const encoding = String(headers['content-encoding'] || 'identity').trim().toLowerCase();
|
|
38
|
+
return /^text\/event-stream\b/i.test(String(headers['content-type'] || '')) && encoding === 'identity';
|
|
39
|
+
}
|
|
40
|
+
function adviseSseEvents(events, onAdvised) {
|
|
41
|
+
if (!events.includes(MODEL_CAPACITY_ERROR_CODE))
|
|
42
|
+
return events;
|
|
43
|
+
const parts = events.toString('utf8').split(/(\r?\n\r?\n)/);
|
|
44
|
+
let changed = false;
|
|
45
|
+
for (let index = 0; index < parts.length; index += 2) {
|
|
46
|
+
const block = parts[index];
|
|
47
|
+
if (!block.includes(MODEL_CAPACITY_ERROR_CODE))
|
|
48
|
+
continue;
|
|
49
|
+
const lines = block.split(/\r?\n/);
|
|
50
|
+
const data = lines.filter((line) => line.startsWith('data:')).map((line) => line.slice(5).replace(/^ /, '')).join('\n');
|
|
51
|
+
let event;
|
|
52
|
+
try {
|
|
53
|
+
event = JSON.parse(data);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (!isObject(event) || !adviseModelCapacityRetry(event))
|
|
59
|
+
continue;
|
|
60
|
+
const newline = block.includes('\r\n') ? '\r\n' : '\n';
|
|
61
|
+
parts[index] = [...lines.filter((line) => !line.startsWith('data:')), `data: ${JSON.stringify(event)}`].join(newline);
|
|
62
|
+
changed = true;
|
|
63
|
+
}
|
|
64
|
+
if (!changed)
|
|
65
|
+
return events;
|
|
66
|
+
onAdvised();
|
|
67
|
+
return Buffer.from(parts.join(''));
|
|
68
|
+
}
|
|
69
|
+
export function modelCapacityAdvisingSse(onAdvised) {
|
|
70
|
+
let carry = Buffer.alloc(0);
|
|
71
|
+
return new Transform({
|
|
72
|
+
transform(chunk, _encoding, done) {
|
|
73
|
+
const data = carry.length ? Buffer.concat([carry, chunk]) : chunk;
|
|
74
|
+
const lf = data.lastIndexOf('\n\n');
|
|
75
|
+
const crlf = data.lastIndexOf('\r\n\r\n');
|
|
76
|
+
const end = Math.max(lf === -1 ? -1 : lf + 2, crlf === -1 ? -1 : crlf + 4);
|
|
77
|
+
if (end === -1) {
|
|
78
|
+
carry = data;
|
|
79
|
+
done();
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
carry = data.subarray(end);
|
|
83
|
+
done(null, adviseSseEvents(data.subarray(0, end), onAdvised));
|
|
84
|
+
},
|
|
85
|
+
flush(done) {
|
|
86
|
+
done(null, carry.length ? adviseSseEvents(carry, onAdvised) : null);
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { adviseModelCapacityRetry } from './capacity-retry-advice.js';
|
|
2
3
|
export const CODEX_SUMMARIZATION_PROMPT = `You are performing a CONTEXT CHECKPOINT COMPACTION. Create a handoff summary for another LLM that will resume the task.
|
|
3
4
|
|
|
4
5
|
Include:
|
|
@@ -331,10 +332,12 @@ export function compactionResponseEvents(responseId, publicModel, summary, usage
|
|
|
331
332
|
};
|
|
332
333
|
}
|
|
333
334
|
export function compactionFailedEvent(responseId, publicModel, code) {
|
|
334
|
-
|
|
335
|
+
const event = {
|
|
335
336
|
type: 'response.failed',
|
|
336
337
|
response: { ...responseBase(responseId, publicModel), status: 'failed', error: { code, message: code } },
|
|
337
338
|
};
|
|
339
|
+
adviseModelCapacityRetry(event);
|
|
340
|
+
return event;
|
|
338
341
|
}
|
|
339
342
|
export function sseEvent(event) {
|
|
340
343
|
return `event: ${String(event.type)}\ndata: ${JSON.stringify(event)}\n\n`;
|
|
@@ -9,6 +9,7 @@ import { OPENROUTER_ONLY_REFUSAL_CODES, openRouterOnlyEnabled } from './exclusiv
|
|
|
9
9
|
import { ensureDesktopBridgeRemoteTarget, isNoRouteUpstreamError, isUnreachableUpstreamError, refreshDesktopBridgeRemoteTarget, resolveAndBindDesktopBridgeRouteContext, resolveCodexSessionIdentity, resolveDesktopBridgeTarget, safeBridgeErrorCode, singleBridgeHeader } from './security.js';
|
|
10
10
|
import { desktopBridgeListenOrigin } from './state.js';
|
|
11
11
|
import { buildCompactionSummaryRequest, compactEndpointResult, compactionCreatedEvent, compactionFailedEvent, compactionResponseEvents, expandBridgeCompactionItems, newCompactionResponseId, parseProviderSummary, requestsRemoteCompaction, safeUpstreamErrorId, sseEvent, summaryFailure, summaryWithinBounds, } from './compaction-adapter.js';
|
|
12
|
+
import { isAdvisableEventStream, modelCapacityAdvisingSse } from './capacity-retry-advice.js';
|
|
12
13
|
import { DEFAULT_DESKTOP_BRIDGE_MAX_REQUEST_BODY_BYTES, DesktopBridgeError, DesktopBridgeRequestBodyTooLargeError } from './types.js';
|
|
13
14
|
const MAX_UPSTREAM_ERROR_BODY_BYTES = 1024 * 1024;
|
|
14
15
|
function decodeBridgeRequestBody(body, encoding, maximum) {
|
|
@@ -466,15 +467,26 @@ export async function forwardHttp(req, res, config, prepared, authenticatedLocal
|
|
|
466
467
|
return;
|
|
467
468
|
}
|
|
468
469
|
responseStarted = true;
|
|
470
|
+
const advising = isAdvisableEventStream(response.headers) ? modelCapacityAdvisingSse(() => logHttpRejection({
|
|
471
|
+
code: 'bridge_upstream_model_capacity_retry_advised',
|
|
472
|
+
transport: 'http',
|
|
473
|
+
...(req.method === undefined ? {} : { method: req.method }),
|
|
474
|
+
...(req.url === undefined ? {} : { url: req.url }),
|
|
475
|
+
provider_id: provider.provider_id,
|
|
476
|
+
public_model: request.route.public_model,
|
|
477
|
+
})) : null;
|
|
469
478
|
try {
|
|
470
|
-
|
|
479
|
+
const responseHeaders = rewriteResponseHeaders(response.headers, upstreamBaseUrl, authenticatedLocalBaseUrl);
|
|
480
|
+
if (advising)
|
|
481
|
+
delete responseHeaders['content-length'];
|
|
482
|
+
res.writeHead(statusCode, responseHeaders);
|
|
471
483
|
}
|
|
472
484
|
catch (error) {
|
|
473
485
|
response.destroy(error instanceof Error ? error : undefined);
|
|
474
486
|
finish(error);
|
|
475
487
|
return;
|
|
476
488
|
}
|
|
477
|
-
void pipeline(response, res).then(() => finish(), finish);
|
|
489
|
+
void (advising ? pipeline(response, advising, res) : pipeline(response, res)).then(() => finish(), finish);
|
|
478
490
|
});
|
|
479
491
|
if (body)
|
|
480
492
|
upstream.end(body);
|
|
@@ -8,6 +8,7 @@ import { assertDesktopBridgeRouteContext, ensureDesktopBridgeRemoteTarget, isUnr
|
|
|
8
8
|
import { DEFAULT_DESKTOP_BRIDGE_MAX_REQUEST_BODY_BYTES, DesktopBridgeError } from './types.js';
|
|
9
9
|
import { buildCompactionSummaryRequest, compactionCreatedEvent, compactionFailedEvent, compactionResponseEvents, expandBridgeCompactionItems, newCompactionResponseId, parseProviderSummary, requestsRemoteCompaction, ResponsesContinuationChain, summaryFailure, summaryWithinBounds, } from './compaction-adapter.js';
|
|
10
10
|
import { requestProviderCompactionSummary } from './http-forward.js';
|
|
11
|
+
import { modelCapacityAdvisedFrame } from './capacity-retry-advice.js';
|
|
11
12
|
const MAX_PENDING_MESSAGES = 256;
|
|
12
13
|
const CLOSE_GRACE_MS = 1_000;
|
|
13
14
|
const INITIAL_CREATE_TIMEOUT_MS = 60 * 60_000;
|
|
@@ -47,6 +48,7 @@ export function forwardResponsesWebSocket(req, socket, head, config) {
|
|
|
47
48
|
let boundBaseUrl = null;
|
|
48
49
|
let boundCredentialGeneration = null;
|
|
49
50
|
let boundCredentialFingerprint = null;
|
|
51
|
+
let routedModel = null;
|
|
50
52
|
let stopped = false;
|
|
51
53
|
let processing = false;
|
|
52
54
|
let pendingBytes = 0;
|
|
@@ -129,6 +131,7 @@ export function forwardResponsesWebSocket(req, socket, head, config) {
|
|
|
129
131
|
if (stopped || client.readyState !== WebSocket.OPEN)
|
|
130
132
|
return;
|
|
131
133
|
assertBinding(route);
|
|
134
|
+
routedModel = route.public_model;
|
|
132
135
|
if (!bound) {
|
|
133
136
|
bound = route;
|
|
134
137
|
await connect(route);
|
|
@@ -247,7 +250,12 @@ export function forwardResponsesWebSocket(req, socket, head, config) {
|
|
|
247
250
|
peer.on('message', (data, binary) => {
|
|
248
251
|
if (stopped)
|
|
249
252
|
return;
|
|
250
|
-
|
|
253
|
+
let frame = bytes(data);
|
|
254
|
+
const advised = official || binary ? null : modelCapacityAdvisedFrame(frame);
|
|
255
|
+
if (advised) {
|
|
256
|
+
frame = advised;
|
|
257
|
+
logRejection({ code: 'bridge_upstream_model_capacity_retry_advised', transport: 'websocket', provider_id: route.provider_id, public_model: routedModel ?? route.public_model, ...(req.url ? { url: req.url } : {}) });
|
|
258
|
+
}
|
|
251
259
|
chain.received(frame);
|
|
252
260
|
try {
|
|
253
261
|
relay(client, frame, binary);
|
package/dist/core/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const PACKAGE_VERSION = '10.6.
|
|
1
|
+
export const PACKAGE_VERSION = '10.6.2';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sneakoscope",
|
|
3
3
|
"displayName": "ㅅㅋㅅ",
|
|
4
|
-
"version": "10.6.
|
|
4
|
+
"version": "10.6.2",
|
|
5
5
|
"description": "Sneakoscope Codex (`sks`) is an open-source trust layer for Codex CLI and ChatGPT Desktop. It coordinates bounded AI coding agents, records machine-verifiable evidence, preserves project memory, and blocks release claims that are not supported by current tests or artifacts. Search visibility outcomes are measured separately; SKS does not promise rankings or traffic.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"homepage": "https://github.com/mandarange/Sneakoscope-Codex#readme",
|
|
@@ -199,9 +199,9 @@
|
|
|
199
199
|
"ws": "^8.22.0"
|
|
200
200
|
},
|
|
201
201
|
"devDependencies": {
|
|
202
|
-
"@types/node": "^24.19.
|
|
202
|
+
"@types/node": "^24.19.2",
|
|
203
203
|
"@types/ws": "^8.18.2",
|
|
204
|
-
"jsdom": "30.1.
|
|
204
|
+
"jsdom": "30.1.3",
|
|
205
205
|
"mermaid": "12.1.0"
|
|
206
206
|
}
|
|
207
207
|
}
|