sneakoscope 4.0.2 → 4.0.4

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 (32) hide show
  1. package/README.md +8 -7
  2. package/crates/sks-core/Cargo.lock +1 -1
  3. package/crates/sks-core/Cargo.toml +1 -1
  4. package/crates/sks-core/src/main.rs +1 -1
  5. package/dist/bin/sks.js +1 -1
  6. package/dist/cli/command-registry.js +1 -0
  7. package/dist/cli/global-mode-router.js +25 -0
  8. package/dist/cli/router.js +12 -0
  9. package/dist/commands/codex-app.js +10 -1
  10. package/dist/commands/codex.js +15 -1
  11. package/dist/core/codex-app/glm-model-profile.js +2 -0
  12. package/dist/core/codex-app/glm-profile-installer.js +61 -0
  13. package/dist/core/codex-app/glm-profile-schema.js +24 -0
  14. package/dist/core/codex-control/codex-0141-capability.js +95 -0
  15. package/dist/core/commands/glm-command.js +10 -0
  16. package/dist/core/commands/mad-sks-command.js +112 -14
  17. package/dist/core/fsx.js +1 -1
  18. package/dist/core/providers/glm/glm-52-profile.js +30 -0
  19. package/dist/core/providers/glm/glm-52-request.js +34 -0
  20. package/dist/core/providers/glm/glm-52-response-guard.js +34 -0
  21. package/dist/core/providers/glm/glm-52-settings.js +26 -0
  22. package/dist/core/providers/glm/glm-mad-launch.js +113 -0
  23. package/dist/core/providers/glm/glm-mad-mode.js +242 -0
  24. package/dist/core/providers/openrouter/openrouter-client.js +44 -0
  25. package/dist/core/providers/openrouter/openrouter-error.js +37 -0
  26. package/dist/core/providers/openrouter/openrouter-secret-store.js +113 -0
  27. package/dist/core/providers/openrouter/openrouter-types.js +2 -0
  28. package/dist/core/results.js +2 -0
  29. package/dist/core/secret-redaction.js +4 -0
  30. package/dist/core/security/redact-secrets.js +15 -0
  31. package/dist/core/version.js +1 -1
  32. package/package.json +4 -1
@@ -0,0 +1,242 @@
1
+ import readline from 'node:readline/promises';
2
+ import path from 'node:path';
3
+ import { stdin as input, stdout as output } from 'node:process';
4
+ import { printJson } from '../../../cli/output.js';
5
+ import { flag } from '../../../cli/args.js';
6
+ import { nowIso, writeJsonAtomic } from '../../fsx.js';
7
+ import {} from '../openrouter/openrouter-types.js';
8
+ import { sendOpenRouterChatCompletion } from '../openrouter/openrouter-client.js';
9
+ import { resolveOpenRouterApiKey, writeStoredOpenRouterKey } from '../openrouter/openrouter-secret-store.js';
10
+ import { redactOpenRouterKey } from '../../security/redact-secrets.js';
11
+ import { buildGlmCodexAppModelProfile } from './glm-52-profile.js';
12
+ import { buildGlm52KeyValidationRequest, buildGlm52Request } from './glm-52-request.js';
13
+ import { assertGlm52ActualModel } from './glm-52-response-guard.js';
14
+ import { GLM_52_OPENROUTER_MODEL, GLM_MAD_MODE, OPENROUTER_CHAT_COMPLETIONS_URL } from './glm-52-settings.js';
15
+ export async function runMadGlmMode(args = [], adapters = {}) {
16
+ const runtime = buildDefaultAdapters(adapters);
17
+ const repair = flag(args, '--repair');
18
+ const noSaveKey = flag(args, '--no-save-key');
19
+ const skipValidation = flag(args, '--skip-validation');
20
+ const json = flag(args, '--json');
21
+ const profile = buildGlmCodexAppModelProfile();
22
+ let result;
23
+ if (repair) {
24
+ const key = await runtime.promptSecret('OpenRouter API key is required for GLM 5.2 mode.\nEnter OpenRouter API key: ');
25
+ if (!key) {
26
+ result = baseResult({
27
+ status: 'blocked',
28
+ blockers: ['glm_key_prompt_cancelled'],
29
+ warnings: []
30
+ });
31
+ }
32
+ else {
33
+ if (!noSaveKey)
34
+ await runtime.writeSecret(key);
35
+ const validation = skipValidation
36
+ ? { ok: true, value: validationValue(null) }
37
+ : await runtime.validateOpenRouterKey(key);
38
+ result = validation.ok
39
+ ? baseResult({
40
+ status: 'ready',
41
+ ...(validation.value.actual_model ? { actual_model: validation.value.actual_model } : {}),
42
+ openrouter_key_source: noSaveKey ? 'prompt' : 'user-secret-store',
43
+ key_preview: redactOpenRouterKey(key),
44
+ blockers: [],
45
+ warnings: noSaveKey ? ['openrouter_key_not_saved'] : []
46
+ })
47
+ : baseResult({
48
+ status: 'blocked',
49
+ openrouter_key_source: noSaveKey ? 'prompt' : 'user-secret-store',
50
+ key_preview: redactOpenRouterKey(key),
51
+ blockers: [validation.error.code],
52
+ warnings: []
53
+ });
54
+ }
55
+ }
56
+ else {
57
+ const resolved = await resolveOpenRouterApiKey({ env: runtime.env });
58
+ if (!resolved.key && process.stdin.isTTY) {
59
+ const key = await runtime.promptSecret('OpenRouter API key is required for GLM 5.2 mode.\nEnter OpenRouter API key: ');
60
+ if (!key) {
61
+ result = baseResult({ status: 'blocked', blockers: ['glm_key_prompt_cancelled'], warnings: [] });
62
+ }
63
+ else {
64
+ const save = noSaveKey ? false : await runtime.promptConfirm('Save this key for future SKS GLM runs? [Y/n] ', true);
65
+ if (save)
66
+ await runtime.writeSecret(key);
67
+ result = baseResult({
68
+ status: 'ready',
69
+ openrouter_key_source: save ? 'user-secret-store' : 'prompt',
70
+ key_preview: redactOpenRouterKey(key),
71
+ blockers: [],
72
+ warnings: save ? [] : ['openrouter_key_not_saved']
73
+ });
74
+ }
75
+ }
76
+ else if (!resolved.key) {
77
+ result = baseResult({
78
+ status: 'blocked',
79
+ blockers: resolved.blockers,
80
+ warnings: ['set_OPENROUTER_API_KEY_or_run_sks_--mad_--glm_--repair']
81
+ });
82
+ }
83
+ else {
84
+ result = baseResult({
85
+ status: 'ready',
86
+ ...(resolved.source ? { openrouter_key_source: resolved.source } : {}),
87
+ key_preview: resolved.key_preview,
88
+ blockers: [],
89
+ warnings: resolved.warnings
90
+ });
91
+ }
92
+ }
93
+ await writeGlmModeArtifacts(runtime.cwd, result, profile, runtime.nowIso()).catch(() => undefined);
94
+ if (json)
95
+ printJson(result);
96
+ else
97
+ printHumanGlmResult(result, runtime.log);
98
+ if (!result.ok)
99
+ process.exitCode = 1;
100
+ return result;
101
+ }
102
+ function baseResult(input) {
103
+ const result = {
104
+ schema: 'sks.glm-mode-result.v1',
105
+ ok: input.blockers.length === 0 && input.status !== 'failed',
106
+ status: input.status,
107
+ mode: GLM_MAD_MODE,
108
+ provider: 'openrouter',
109
+ model: GLM_52_OPENROUTER_MODEL,
110
+ requested_model: GLM_52_OPENROUTER_MODEL,
111
+ strict_model_lock: true,
112
+ gpt_fallback_allowed: false,
113
+ codex_app_profile_id: 'sks/glm-5.2-mad',
114
+ blockers: input.blockers,
115
+ warnings: input.warnings
116
+ };
117
+ return {
118
+ ...result,
119
+ ...(input.actual_model ? { actual_model: input.actual_model } : {}),
120
+ ...(input.openrouter_key_source ? { openrouter_key_source: input.openrouter_key_source } : {}),
121
+ ...(input.key_preview !== undefined ? { key_preview: input.key_preview } : {})
122
+ };
123
+ }
124
+ function buildDefaultAdapters(overrides) {
125
+ return {
126
+ nowIso: overrides.nowIso || nowIso,
127
+ env: overrides.env || process.env,
128
+ cwd: overrides.cwd || process.cwd(),
129
+ promptSecret: overrides.promptSecret || promptLine,
130
+ promptConfirm: overrides.promptConfirm || promptConfirmLine,
131
+ writeSecret: overrides.writeSecret || (async (value) => {
132
+ await writeStoredOpenRouterKey(value);
133
+ }),
134
+ validateOpenRouterKey: overrides.validateOpenRouterKey || validateOpenRouterKey,
135
+ sendOpenRouterRequest: overrides.sendOpenRouterRequest || (async (request, key) => sendOpenRouterChatCompletion({ request, apiKey: key })),
136
+ log: overrides.log || ((message) => console.log(message))
137
+ };
138
+ }
139
+ async function validateOpenRouterKey(key) {
140
+ const response = await sendOpenRouterChatCompletion({
141
+ apiKey: key,
142
+ request: buildGlm52KeyValidationRequest()
143
+ });
144
+ if (!response.ok)
145
+ return response;
146
+ const guard = assertGlm52ActualModel(response.value.model);
147
+ if (!guard.ok) {
148
+ return {
149
+ ok: false,
150
+ error: {
151
+ code: guard.code,
152
+ message: 'GLM model lock violated.',
153
+ severity: 'blocked'
154
+ }
155
+ };
156
+ }
157
+ return { ok: true, value: validationValue(response.value.model || null) };
158
+ }
159
+ function validationValue(actualModel) {
160
+ return {
161
+ schema: 'sks.openrouter-key-validation.v1',
162
+ ok: true,
163
+ requested_model: GLM_52_OPENROUTER_MODEL,
164
+ actual_model: actualModel,
165
+ strict_model_lock: true,
166
+ gpt_fallback_allowed: false
167
+ };
168
+ }
169
+ async function writeGlmModeArtifacts(cwd, result, profile, generatedAt) {
170
+ const dir = path.join(cwd, '.sneakoscope', 'glm');
171
+ await writeJsonAtomic(path.join(dir, 'mad-glm-session.json'), {
172
+ schema: 'sks.glm-mad-session.v1',
173
+ generated_at: generatedAt,
174
+ result,
175
+ profile_id: profile.id
176
+ });
177
+ await writeJsonAtomic(path.join(dir, 'openrouter-request-summary.json'), {
178
+ schema: 'sks.openrouter-request-summary.v1',
179
+ generated_at: generatedAt,
180
+ endpoint: OPENROUTER_CHAT_COMPLETIONS_URL,
181
+ model: GLM_52_OPENROUTER_MODEL,
182
+ temperature: 1,
183
+ top_p: 0.95,
184
+ reasoning_effort: 'high',
185
+ stream: true,
186
+ provider_allow_fallbacks: false,
187
+ require_parameters: true,
188
+ key_source: result.openrouter_key_source || null,
189
+ key_preview: result.key_preview || null
190
+ });
191
+ await writeJsonAtomic(path.join(dir, 'model-guard.json'), {
192
+ schema: 'sks.glm-model-guard.v1',
193
+ generated_at: generatedAt,
194
+ requested_model: GLM_52_OPENROUTER_MODEL,
195
+ actual_model: result.actual_model || null,
196
+ accepted: result.actual_model ? assertGlm52ActualModel(result.actual_model).ok : result.ok,
197
+ strict_model_lock: true,
198
+ gpt_fallback_allowed: false,
199
+ blockers: result.blockers
200
+ });
201
+ }
202
+ function printHumanGlmResult(result, log) {
203
+ log(`GLM 5.2 MAD mode: ${result.ok ? result.status : 'blocked'}`);
204
+ log(`Model: ${result.model}`);
205
+ log(`GPT fallback: ${result.gpt_fallback_allowed ? 'allowed' : 'blocked'}`);
206
+ if (result.openrouter_key_source)
207
+ log(`OpenRouter key: ${result.openrouter_key_source} ${result.key_preview || ''}`.trim());
208
+ for (const blocker of result.blockers)
209
+ log(`- blocker: ${blocker}`);
210
+ for (const warning of result.warnings)
211
+ log(`- warning: ${warning}`);
212
+ }
213
+ async function promptLine(prompt) {
214
+ if (!process.stdin.isTTY)
215
+ return null;
216
+ const rl = readline.createInterface({ input, output });
217
+ try {
218
+ const answer = await rl.question(prompt);
219
+ return answer.trim() || null;
220
+ }
221
+ finally {
222
+ rl.close();
223
+ }
224
+ }
225
+ async function promptConfirmLine(prompt, defaultYes) {
226
+ if (!process.stdin.isTTY)
227
+ return defaultYes;
228
+ const answer = await promptLine(prompt);
229
+ if (!answer)
230
+ return defaultYes;
231
+ return !/^n(o)?$/i.test(answer);
232
+ }
233
+ export function buildGlmModeDryRunRequest() {
234
+ return buildGlm52Request({
235
+ messages: [{ role: 'user', content: 'SKS GLM dry run.' }],
236
+ stream: false,
237
+ maxTokens: 1,
238
+ toolChoice: 'none',
239
+ parallelToolCalls: false
240
+ });
241
+ }
242
+ //# sourceMappingURL=glm-mad-mode.js.map
@@ -0,0 +1,44 @@
1
+ import { OPENROUTER_CHAT_COMPLETIONS_URL } from './openrouter-types.js';
2
+ import { invalidOpenRouterResponseIssue, normalizeOpenRouterError } from './openrouter-error.js';
3
+ import { redactOpenRouterString } from '../../security/redact-secrets.js';
4
+ export async function sendOpenRouterChatCompletion(input) {
5
+ try {
6
+ const doFetch = input.fetchImpl || fetch;
7
+ const response = await doFetch(input.endpoint || OPENROUTER_CHAT_COMPLETIONS_URL, {
8
+ method: 'POST',
9
+ headers: {
10
+ Authorization: `Bearer ${input.apiKey}`,
11
+ 'Content-Type': 'application/json',
12
+ 'X-OpenRouter-Title': 'Sneakoscope-Codex'
13
+ },
14
+ body: JSON.stringify(input.request)
15
+ });
16
+ const text = await response.text();
17
+ if (!response.ok)
18
+ return { ok: false, error: normalizeOpenRouterError(response.status, text) };
19
+ return parseOpenRouterResponse(text);
20
+ }
21
+ catch (err) {
22
+ return {
23
+ ok: false,
24
+ error: {
25
+ code: 'glm_openrouter_request_failed',
26
+ message: redactOpenRouterString(err instanceof Error ? err.message : String(err)),
27
+ severity: 'failed'
28
+ }
29
+ };
30
+ }
31
+ }
32
+ export function parseOpenRouterResponse(text) {
33
+ try {
34
+ const parsed = JSON.parse(text);
35
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
36
+ return { ok: false, error: invalidOpenRouterResponseIssue('OpenRouter response was not an object.', text) };
37
+ }
38
+ return { ok: true, value: parsed };
39
+ }
40
+ catch {
41
+ return { ok: false, error: invalidOpenRouterResponseIssue('OpenRouter response was not valid JSON.', text) };
42
+ }
43
+ }
44
+ //# sourceMappingURL=openrouter-client.js.map
@@ -0,0 +1,37 @@
1
+ import { redactOpenRouterString } from '../../security/redact-secrets.js';
2
+ export function normalizeOpenRouterError(status, body) {
3
+ const code = status === 401 || status === 403
4
+ ? 'glm_openrouter_unauthorized'
5
+ : status === 429
6
+ ? 'glm_openrouter_rate_limited'
7
+ : status >= 500
8
+ ? 'glm_openrouter_provider_unavailable'
9
+ : 'glm_openrouter_request_failed';
10
+ return {
11
+ code,
12
+ message: statusMessage(code),
13
+ severity: status >= 500 ? 'failed' : 'blocked',
14
+ status,
15
+ redacted_body_tail: redactOpenRouterString(body).slice(-2000)
16
+ };
17
+ }
18
+ export function invalidOpenRouterResponseIssue(message, body) {
19
+ const issue = {
20
+ code: 'glm_openrouter_invalid_response',
21
+ message,
22
+ severity: 'failed'
23
+ };
24
+ return body ? { ...issue, redacted_body_tail: redactOpenRouterString(body).slice(-2000) } : issue;
25
+ }
26
+ function statusMessage(code) {
27
+ if (code === 'glm_openrouter_unauthorized')
28
+ return 'OpenRouter rejected the GLM API key.';
29
+ if (code === 'glm_openrouter_rate_limited')
30
+ return 'OpenRouter rate limited the GLM request.';
31
+ if (code === 'glm_openrouter_provider_unavailable')
32
+ return 'OpenRouter provider is unavailable for GLM 5.2.';
33
+ if (code === 'glm_openrouter_invalid_response')
34
+ return 'OpenRouter returned an invalid response.';
35
+ return 'OpenRouter request failed.';
36
+ }
37
+ //# sourceMappingURL=openrouter-error.js.map
@@ -0,0 +1,113 @@
1
+ import crypto from 'node:crypto';
2
+ import fs from 'node:fs/promises';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+ import { redactOpenRouterKey } from '../../security/redact-secrets.js';
6
+ export const OPENROUTER_KEY_ENV_NAMES = ['OPENROUTER_API_KEY', 'SKS_OPENROUTER_API_KEY'];
7
+ export function openRouterSecretPaths(env = process.env) {
8
+ const sksHome = path.resolve(env.SKS_HOME || path.join(env.HOME || os.homedir(), '.sneakoscope'));
9
+ const secretDir = path.join(sksHome, 'secrets');
10
+ return {
11
+ sksHome,
12
+ secretDir,
13
+ keyPath: path.join(secretDir, 'openrouter-api-key'),
14
+ metadataPath: path.join(secretDir, 'openrouter-api-key.json')
15
+ };
16
+ }
17
+ export async function resolveOpenRouterApiKey(input = {}) {
18
+ const env = input.env || process.env;
19
+ for (const name of OPENROUTER_KEY_ENV_NAMES) {
20
+ const value = String(env[name] || '').trim();
21
+ if (value) {
22
+ return {
23
+ key: value,
24
+ source: 'env',
25
+ env_var: name,
26
+ key_preview: redactOpenRouterKey(value),
27
+ blockers: [],
28
+ warnings: name === 'OPENROUTER_API_KEY' ? [] : ['using_sks_openrouter_api_key_env']
29
+ };
30
+ }
31
+ }
32
+ const stored = await readStoredOpenRouterKey(input.paths || openRouterSecretPaths(env));
33
+ if (stored) {
34
+ return {
35
+ key: stored,
36
+ source: 'user-secret-store',
37
+ key_preview: redactOpenRouterKey(stored),
38
+ blockers: [],
39
+ warnings: []
40
+ };
41
+ }
42
+ return {
43
+ key: null,
44
+ source: null,
45
+ key_preview: null,
46
+ blockers: ['glm_missing_openrouter_key'],
47
+ warnings: []
48
+ };
49
+ }
50
+ export async function readStoredOpenRouterKey(paths) {
51
+ try {
52
+ const text = await fs.readFile(paths.keyPath, 'utf8');
53
+ const key = text.trim();
54
+ return key || null;
55
+ }
56
+ catch {
57
+ return null;
58
+ }
59
+ }
60
+ export async function writeStoredOpenRouterKey(value, input = {}) {
61
+ const key = value.trim();
62
+ if (!key)
63
+ throw new Error('OpenRouter key is empty.');
64
+ const paths = input.paths || openRouterSecretPaths();
65
+ const nowIso = input.nowIso || (() => new Date().toISOString());
66
+ const timestamp = nowIso();
67
+ const previous = input.previousRecord ?? await readOpenRouterKeyRecord(paths);
68
+ await ensureSecretDir(paths.secretDir);
69
+ const tmp = `${paths.keyPath}.${process.pid}.${crypto.randomBytes(3).toString('hex')}.tmp`;
70
+ try {
71
+ const handle = await fs.open(tmp, 'w', 0o600);
72
+ try {
73
+ await handle.writeFile(`${key}\n`, 'utf8');
74
+ await handle.sync().catch(() => undefined);
75
+ }
76
+ finally {
77
+ await handle.close().catch(() => undefined);
78
+ }
79
+ await fs.chmod(tmp, 0o600).catch(() => undefined);
80
+ await fs.rename(tmp, paths.keyPath);
81
+ await fs.chmod(paths.keyPath, 0o600).catch(() => undefined);
82
+ }
83
+ catch (err) {
84
+ await fs.rm(tmp, { force: true }).catch(() => undefined);
85
+ throw err;
86
+ }
87
+ const record = {
88
+ schema: 'sks.openrouter-key.v1',
89
+ created_at: previous?.created_at || timestamp,
90
+ updated_at: timestamp,
91
+ key_hash: crypto.createHash('sha256').update(key).digest('hex'),
92
+ key_preview: redactOpenRouterKey(key)
93
+ };
94
+ await fs.writeFile(paths.metadataPath, `${JSON.stringify(record, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 });
95
+ await fs.chmod(paths.metadataPath, 0o600).catch(() => undefined);
96
+ return record;
97
+ }
98
+ export async function readOpenRouterKeyRecord(paths) {
99
+ try {
100
+ const parsed = JSON.parse(await fs.readFile(paths.metadataPath, 'utf8'));
101
+ if (parsed.schema !== 'sks.openrouter-key.v1' || !parsed.key_hash || !parsed.key_preview)
102
+ return null;
103
+ return parsed;
104
+ }
105
+ catch {
106
+ return null;
107
+ }
108
+ }
109
+ async function ensureSecretDir(secretDir) {
110
+ await fs.mkdir(secretDir, { recursive: true, mode: 0o700 });
111
+ await fs.chmod(secretDir, 0o700).catch(() => undefined);
112
+ }
113
+ //# sourceMappingURL=openrouter-secret-store.js.map
@@ -0,0 +1,2 @@
1
+ export const OPENROUTER_CHAT_COMPLETIONS_URL = 'https://openrouter.ai/api/v1/chat/completions';
2
+ //# sourceMappingURL=openrouter-types.js.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=results.js.map
@@ -1,6 +1,8 @@
1
1
  const SECRET_ENV_NAMES = [
2
2
  'CODEX_ACCESS_TOKEN',
3
3
  'OPENAI_API_KEY',
4
+ 'OPENROUTER_API_KEY',
5
+ 'SKS_OPENROUTER_API_KEY',
4
6
  'CODEX_LB_API_KEY',
5
7
  'ANTHROPIC_API_KEY',
6
8
  'GITHUB_TOKEN',
@@ -8,6 +10,8 @@ const SECRET_ENV_NAMES = [
8
10
  ];
9
11
  const SECRET_PATTERNS = [
10
12
  /\bsk-proj-[A-Za-z0-9_-]{12,}\b/g,
13
+ /\bsk-or-v1-[A-Za-z0-9_-]{12,}\b/g,
14
+ /\bsk-or-[A-Za-z0-9_-]{12,}\b/g,
11
15
  /\bsk-[A-Za-z0-9_-]{20,}\b/g,
12
16
  /\bsk-clb-[A-Za-z0-9_-]{8,}\b/g,
13
17
  /\bgithub_pat_[A-Za-z0-9_]{20,}\b/g,
@@ -0,0 +1,15 @@
1
+ import { redactSecrets, redactString } from '../secret-redaction.js';
2
+ export function redactOpenRouterKey(value) {
3
+ if (!value)
4
+ return '';
5
+ if (value.length <= 10)
6
+ return '<redacted>';
7
+ return `${value.slice(0, 6)}...${value.slice(-4)}`;
8
+ }
9
+ export function redactOpenRouterSecrets(value, env = process.env) {
10
+ return redactSecrets(value, env);
11
+ }
12
+ export function redactOpenRouterString(value, env = process.env) {
13
+ return redactString(String(value ?? ''), env);
14
+ }
15
+ //# sourceMappingURL=redact-secrets.js.map
@@ -1,2 +1,2 @@
1
- export const PACKAGE_VERSION = '4.0.2';
1
+ export const PACKAGE_VERSION = '4.0.4';
2
2
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sneakoscope",
3
3
  "displayName": "ㅅㅋㅅ",
4
- "version": "4.0.2",
4
+ "version": "4.0.4",
5
5
  "description": "Sneakoscope Codex: fast proof-first Codex trust layer with image-based Voxel TriWiki.",
6
6
  "type": "module",
7
7
  "homepage": "https://github.com/mandarange/Sneakoscope-Codex#readme",
@@ -30,6 +30,8 @@
30
30
  "!dist/**/*.d.ts.map",
31
31
  "!dist/**/*.js.map",
32
32
  "!dist/**/*.tsbuildinfo",
33
+ "!dist/**/__tests__",
34
+ "!dist/**/*.test.js",
33
35
  "!dist/vendor/openai-codex/rust-v0.131.0",
34
36
  "!dist/scripts/*-blackbox.js",
35
37
  "!dist/scripts/*-check.js",
@@ -122,6 +124,7 @@
122
124
  "prepublish:fast-check": "node ./dist/scripts/prepublish-fast-check.js",
123
125
  "prepublish:release-check-or-fast": "node ./dist/scripts/prepublish-release-check-or-fast.js",
124
126
  "mad:preflight-blocks-unreadable-config": "node ./dist/scripts/mad-preflight-blocks-unreadable-config-check.js",
127
+ "codex:0.141-compat": "node ./dist/scripts/codex-0141-capability-check.js",
125
128
  "codex:0.136-compat": "node ./dist/scripts/codex-0-136-compat-check.js",
126
129
  "codex:0.136-compat:require-real": "node ./dist/scripts/codex-0-136-compat-check.js --require-real",
127
130
  "codex:0.135-compat": "node ./dist/scripts/codex-0-135-compat-check.js",