sneakoscope 4.0.3 → 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.
package/README.md CHANGED
@@ -35,15 +35,16 @@ Set up this agent project with Sneakoscope Codex. Use [[mandarange/Sneakoscope-C
35
35
 
36
36
  ## 🚀 Current Release
37
37
 
38
- SKS **4.0.3** adds a GLM 5.2-only MAD mode through OpenRouter while preserving the proof-first SKS pipeline. `sks --mad --glm` resolves the GLM profile, keeps GPT/OpenAI fallback disabled, and records model-lock proof; `sks --mad --glm --repair` rotates the OpenRouter API key outside project files.
38
+ SKS **4.0.4** makes the GLM 5.2 MAD launch path real: `sks --mad --glm` now resolves the OpenRouter key, opens the MAD Zellij launch flow with Codex configured for `z-ai/glm-5.2`, blocks GPT fallback panes, and records launch proof; `sks --mad --glm --repair` still rotates the OpenRouter API key outside project files.
39
39
 
40
- What changed in 4.0.3:
40
+ What changed in 4.0.4:
41
41
 
42
- - **GLM 5.2 MAD mode.** `sks --mad --glm` enters a `mad-glm` profile using OpenRouter model `z-ai/glm-5.2`.
43
- - **No GPT fallback.** GLM requests use `provider.allow_fallbacks: false`, omit fallback `models`, and reject non-GLM response model ids before mutation.
42
+ - **GLM MAD actually launches.** `sks --mad --glm` no longer stops after the readiness banner; it continues into the MAD launcher with a GLM/OpenRouter Codex profile.
43
+ - **No leaked OpenRouter key.** The Zellij pane uses a mission-local `sks-glm-codex-wrapper.sh` that reads the key at runtime, so layout artifacts do not contain the raw secret.
44
+ - **No GPT fallback panes.** GLM MAD disables the existing GPT/codex-sdk native swarm by default until a GLM worker backend exists, preserving the no-fallback guarantee.
45
+ - **Launch proof.** Each GLM MAD launch writes `mad-glm-launch.json` with provider/model/profile/wrapper evidence and records disabled fallback status.
44
46
  - **OpenRouter key lifecycle.** Keys resolve from `OPENROUTER_API_KEY`, `SKS_OPENROUTER_API_KEY`, or the user SKS secret store; stored keys use private permissions and redacted metadata.
45
- - **Codex App profile.** `sks codex-app glm-profile install` writes the `sks/glm-5.2-mad` profile metadata for Codex App selection.
46
- - **Codex 0.141 alignment.** SKS delegates remote relay, cwd/shell/path preservation, selected plugin MCP activation, App/MCP dedupe, bounded prompt-image cache, bounded feedback upload, and terminal resize behavior to Codex-native semantics where available.
47
+ - **4.0.3 GLM request safeguards remain.** GLM requests still use `provider.allow_fallbacks: false`, omit fallback `models`, and reject non-GLM response model ids before mutation.
47
48
 
48
49
  SKS **3.1.16** was a launch-reliability patch on the 3.1.15 doctor-reliability release. It made `sks --mad` self-bootstrap a fresh project instead of dead-ending on a missing Codex config.
49
50
 
@@ -76,7 +76,7 @@ dependencies = [
76
76
 
77
77
  [[package]]
78
78
  name = "sks-core"
79
- version = "4.0.3"
79
+ version = "4.0.4"
80
80
  dependencies = [
81
81
  "serde_json",
82
82
  ]
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "sks-core"
3
- version = "4.0.3"
3
+ version = "4.0.4"
4
4
  edition = "2021"
5
5
 
6
6
  [dependencies]
@@ -4,7 +4,7 @@ use std::io::{self, Read, Seek, SeekFrom};
4
4
  fn main() {
5
5
  let mut args = std::env::args().skip(1);
6
6
  match args.next().as_deref() {
7
- Some("--version") => println!("sks-rs 4.0.3"),
7
+ Some("--version") => println!("sks-rs 4.0.4"),
8
8
  Some("compact-info") => {
9
9
  let mut input = String::new();
10
10
  let _ = io::stdin().read_to_string(&mut input);
package/dist/bin/sks.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- const FAST_PACKAGE_VERSION = '4.0.3';
2
+ const FAST_PACKAGE_VERSION = '4.0.4';
3
3
  const args = process.argv.slice(2);
4
4
  try {
5
5
  if (args[0] === '--agent' && args[1] === 'worker') {
@@ -1,5 +1,10 @@
1
1
  import { runMadGlmMode } from '../providers/glm/glm-mad-mode.js';
2
+ import { flag } from '../../cli/args.js';
3
+ import { madHighCommand } from './mad-sks-command.js';
2
4
  export async function glmCommand(args = []) {
3
- return runMadGlmMode(args);
5
+ const result = await runMadGlmMode(args);
6
+ if (!result.ok || flag(args, '--repair') || flag(args, '--json'))
7
+ return result;
8
+ return madHighCommand(['--glm', ...args], { glmReadiness: result });
4
9
  }
5
10
  //# sourceMappingURL=glm-command.js.map
@@ -24,16 +24,19 @@ import { writeCodex0138CapabilityArtifacts } from '../codex-control/codex-0138-c
24
24
  import { writeCodex0139CapabilityArtifacts } from '../codex-control/codex-0139-capability.js';
25
25
  import { resolveCodexNativeInvocationPlan } from '../codex-native/codex-native-invocation-router.js';
26
26
  import { repairZellijForSks } from '../zellij/zellij-self-heal.js';
27
+ import { buildMadGlmLaunchArtifact, buildMadGlmLaunchProfileNoWrite, resolveMadGlmLaunchKey, writeMadGlmCodexWrapper } from '../providers/glm/glm-mad-launch.js';
28
+ import { GLM_MAD_MODE } from '../providers/glm/glm-52-settings.js';
27
29
  export async function madHighCommand(args = [], deps = {}) {
28
30
  const subcommand = firstSubcommand(args);
29
31
  if (subcommand)
30
32
  return madSksSubcommand(subcommand, args.filter((arg) => String(arg) !== subcommand));
31
33
  const cleanArgs = stripMadLaunchOnlyArgs(args);
32
34
  const rawArgs = (args || []).map((arg) => String(arg));
35
+ const glmMadLaunch = isMadGlmLaunch(rawArgs, deps);
33
36
  const madDbGrant = resolveMadLaunchMadDbGrant(rawArgs);
34
37
  const dryRun = rawArgs.includes('--dry-run');
35
- if (args.includes('--json') && !dryRun) {
36
- const profile = buildMadHighLaunchProfileNoWrite();
38
+ if (rawArgs.includes('--json') && !dryRun) {
39
+ const profile = glmMadLaunch ? buildMadGlmLaunchProfileNoWrite() : buildMadHighLaunchProfileNoWrite();
37
40
  return console.log(JSON.stringify(profile, null, 2));
38
41
  }
39
42
  const update = { status: 'notice_only', non_blocking: true };
@@ -76,7 +79,7 @@ export async function madHighCommand(args = [], deps = {}) {
76
79
  }
77
80
  return report;
78
81
  }
79
- const codexUpdate = deps.maybePromptCodexUpdateForLaunch ? await deps.maybePromptCodexUpdateForLaunch(args, { label: 'MAD launch' }) : { status: 'skipped' };
82
+ const codexUpdate = deps.maybePromptCodexUpdateForLaunch ? await deps.maybePromptCodexUpdateForLaunch(args, { label: glmMadLaunch ? 'GLM MAD launch' : 'MAD launch' }) : { status: 'skipped' };
80
83
  if (codexUpdate.status === 'failed' || codexUpdate.status === 'updated_not_reflected') {
81
84
  console.error(`Codex CLI update failed: ${codexUpdate.error || 'updated version was not visible on PATH'}`);
82
85
  process.exitCode = 1;
@@ -86,7 +89,7 @@ export async function madHighCommand(args = [], deps = {}) {
86
89
  ? { status: 'skipped', command: 'sks doctor --fix --yes' }
87
90
  : deps.maybePromptZellijUpdateForLaunch
88
91
  ? await deps.maybePromptZellijUpdateForLaunch(args, {
89
- label: 'MAD launch',
92
+ label: glmMadLaunch ? 'GLM MAD launch' : 'MAD launch',
90
93
  root: launchRoot,
91
94
  selfHealOnMissing: true,
92
95
  autoApprove: rawArgs.includes('--yes') || rawArgs.includes('-y'),
@@ -121,8 +124,10 @@ export async function madHighCommand(args = [], deps = {}) {
121
124
  process.exitCode = 1;
122
125
  return;
123
126
  }
124
- const lb = deps.maybePromptCodexLbSetupForLaunch ? await deps.maybePromptCodexLbSetupForLaunch(args) : { status: 'skipped' };
125
- if (lb.status === 'missing_api_key') {
127
+ const lb = glmMadLaunch
128
+ ? { status: 'skipped_glm_openrouter', ok: false, reason: 'glm_mad_uses_openrouter_directly' }
129
+ : deps.maybePromptCodexLbSetupForLaunch ? await deps.maybePromptCodexLbSetupForLaunch(args) : { status: 'skipped' };
130
+ if (!glmMadLaunch && lb.status === 'missing_api_key') {
126
131
  process.exitCode = 1;
127
132
  return;
128
133
  }
@@ -171,6 +176,11 @@ export async function madHighCommand(args = [], deps = {}) {
171
176
  return launchPreflight;
172
177
  }
173
178
  const madLaunch = await activateMadZellijPermissionState(process.cwd(), args);
179
+ const glmRuntime = glmMadLaunch ? await prepareMadGlmLaunchRuntime(madLaunch, deps) : null;
180
+ if (glmMadLaunch && !glmRuntime?.ok) {
181
+ process.exitCode = 1;
182
+ return glmRuntime;
183
+ }
174
184
  const madDbCapability = madDbGrant.enabled
175
185
  ? await createMadDbCapability(madLaunch.root, { missionId: madLaunch.mission_id, ack: madDbGrant.ack, cwd: process.cwd() })
176
186
  : null;
@@ -221,7 +231,9 @@ export async function madHighCommand(args = [], deps = {}) {
221
231
  error: err?.message || String(err)
222
232
  }));
223
233
  await appendJsonlBounded(path.join(madLaunch.dir, 'events.jsonl'), { ts: nowIso(), type: 'mad_sks.update_notice_checked', non_blocking: true, update_available: updateNotice.update_available === true, source: updateNotice.source });
224
- console.log(`SKS MAD ready: ${madHighProfileName()} | gate ${madLaunch.mission_id}`);
234
+ console.log(`SKS MAD ready: ${glmRuntime?.profile?.profile_name || madHighProfileName()} | gate ${madLaunch.mission_id}`);
235
+ if (glmRuntime?.profile)
236
+ console.log(`GLM MAD launch active: ${glmRuntime.profile.model} via OpenRouter; GPT fallback blocked.`);
225
237
  if (madDbCapability)
226
238
  console.log(`MAD-DB one-cycle capability active (${madDbGrant.source}); expires ${madDbCapability.expires_at}.`);
227
239
  if (updateNotice.update_available === true)
@@ -233,8 +245,18 @@ export async function madHighCommand(args = [], deps = {}) {
233
245
  SKS_MAD_SKS_TARGET_ROOT: madLaunch.gate.cwd,
234
246
  SKS_MAD_SKS_PROTECTED_CORE_DIGEST: madLaunch.gate.protected_core_digest
235
247
  };
236
- const launchOpts = codexLbImmediateLaunchOpts(cleanArgs, launchLb, { codexArgs: profile.launch_args, conciseBlockers: true, madSksEnv, launchEnv: madSksEnv });
237
248
  const explicitWorkspace = readOption(cleanArgs, '--workspace', readOption(cleanArgs, '--session', null));
249
+ const launchProfile = glmRuntime?.profile || profile;
250
+ const launchOpts = glmRuntime
251
+ ? buildGlmMadLaunchOpts(cleanArgs, {
252
+ codexArgs: launchProfile.launch_args,
253
+ conciseBlockers: true,
254
+ madSksEnv,
255
+ launchEnv: madSksEnv,
256
+ codexBin: glmRuntime.wrapper.wrapper_path,
257
+ explicitWorkspace
258
+ })
259
+ : codexLbImmediateLaunchOpts(cleanArgs, launchLb, { codexArgs: launchProfile.launch_args, conciseBlockers: true, madSksEnv, launchEnv: madSksEnv });
238
260
  // Only the auto-derived stable `sks-mad-<cwd>` name accumulates panes across
239
261
  // runs; when the user names a session explicitly (or codex-lb already minted a
240
262
  // fresh unique session) respect it and skip the reset.
@@ -268,11 +290,12 @@ export async function madHighCommand(args = [], deps = {}) {
268
290
  worker_panes_created: 0,
269
291
  right_column_mode: 'spawn-on-first-worker'
270
292
  });
271
- const madNativeSwarm = await startMadNativeSwarm(madLaunch.root, madLaunch, args, profile, {
293
+ const madNativeSwarm = await startMadNativeSwarm(madLaunch.root, madLaunch, args, launchProfile, {
272
294
  env: {
273
295
  ...madSksEnv,
274
296
  ...(launch.session_name ? { SKS_ZELLIJ_SESSION_NAME: launch.session_name } : {})
275
297
  },
298
+ glmLaunch: glmRuntime ? { provider: glmRuntime.profile.provider, model: glmRuntime.profile.model } : null,
276
299
  zellijSessionName: launch.session_name || null,
277
300
  workerPlacement: headlessZellij ? 'process' : shouldAutoAttachZellij(args) ? 'zellij-pane' : 'process',
278
301
  zellijVisiblePaneCap: Number(process.env.SKS_ZELLIJ_VISIBLE_PANE_CAP || 8)
@@ -296,6 +319,67 @@ export async function madHighCommand(args = [], deps = {}) {
296
319
  console.log('MAD launch running headless: live_panes=false.');
297
320
  return launch;
298
321
  }
322
+ function isMadGlmLaunch(args = [], deps = {}) {
323
+ const list = (args || []).map((arg) => String(arg));
324
+ return list.includes('--glm') || deps?.glmReadiness?.mode === GLM_MAD_MODE;
325
+ }
326
+ async function prepareMadGlmLaunchRuntime(madLaunch, deps = {}) {
327
+ const keyResolution = await resolveMadGlmLaunchKey(process.env);
328
+ const profile = buildMadGlmLaunchProfileNoWrite();
329
+ if (!keyResolution.key) {
330
+ const blocked = {
331
+ schema: 'sks.glm-mad-launch.v1',
332
+ ok: false,
333
+ status: 'blocked',
334
+ mission_id: madLaunch.mission_id,
335
+ provider: profile.provider,
336
+ model: profile.model,
337
+ gpt_fallback_allowed: false,
338
+ blockers: keyResolution.blockers,
339
+ warnings: keyResolution.warnings
340
+ };
341
+ await writeJsonAtomic(path.join(madLaunch.dir, 'mad-glm-launch.json'), blocked);
342
+ await appendJsonlBounded(path.join(madLaunch.dir, 'events.jsonl'), {
343
+ ts: nowIso(),
344
+ type: 'mad_sks.glm_launch_blocked',
345
+ blockers: keyResolution.blockers
346
+ });
347
+ console.error('SKS GLM MAD launch blocked: OpenRouter API key is missing.');
348
+ console.error('Run: sks --mad --glm --repair');
349
+ return blocked;
350
+ }
351
+ const wrapper = await writeMadGlmCodexWrapper({
352
+ missionDir: madLaunch.dir,
353
+ realCodexBin: process.env.SKS_CODEX_BIN || null
354
+ });
355
+ const report = {
356
+ ...buildMadGlmLaunchArtifact({
357
+ missionId: madLaunch.mission_id,
358
+ keyResolution,
359
+ wrapper,
360
+ profile
361
+ }),
362
+ readiness_status: deps?.glmReadiness?.status || null
363
+ };
364
+ await writeJsonAtomic(path.join(madLaunch.dir, 'mad-glm-launch.json'), report);
365
+ await appendJsonlBounded(path.join(madLaunch.dir, 'events.jsonl'), {
366
+ ts: nowIso(),
367
+ type: 'mad_sks.glm_launch_profile_ready',
368
+ provider: profile.provider,
369
+ model: profile.model,
370
+ key_source: keyResolution.source || null,
371
+ gpt_fallback_allowed: false
372
+ });
373
+ return { ok: true, profile, wrapper, report };
374
+ }
375
+ function buildGlmMadLaunchOpts(cleanArgs = [], opts = {}) {
376
+ if (opts.explicitWorkspace)
377
+ return opts;
378
+ const root = readOption(cleanArgs, '--root', process.cwd());
379
+ const session = sanitizeZellijSessionName(`sks-glm-${Date.now().toString(36)}-${path.basename(root) || 'project'}`);
380
+ console.log(`Using fresh GLM Zellij session: ${session}`);
381
+ return { ...opts, session, glmMadLaunch: true };
382
+ }
299
383
  export function resolveMadLaunchMadDbGrant(args = []) {
300
384
  const list = (args || []).map((arg) => String(arg));
301
385
  return {
@@ -319,6 +403,9 @@ export async function startMadNativeSwarm(root, madLaunch, args = [], profile =
319
403
  status: 'disabled',
320
404
  reason: swarm.disabled_reason,
321
405
  mission_id: madLaunch.mission_id,
406
+ model_provider: opts.glmLaunch?.provider || null,
407
+ model: opts.glmLaunch?.model || null,
408
+ gpt_fallback_allowed: opts.glmLaunch ? false : null,
322
409
  lane_count: 1,
323
410
  ledger_root: path.relative(root, ledgerRoot)
324
411
  };
@@ -381,6 +468,9 @@ export async function startMadNativeSwarm(root, madLaunch, args = [], profile =
381
468
  zellij_session_name: opts.zellijSessionName || null,
382
469
  worker_placement: opts.workerPlacement || (swarm.backend === 'zellij' ? 'zellij-pane' : 'process'),
383
470
  zellij_visible_pane_cap: opts.zellijVisiblePaneCap || null,
471
+ model_provider: opts.glmLaunch?.provider || null,
472
+ model: opts.glmLaunch?.model || null,
473
+ gpt_fallback_allowed: opts.glmLaunch ? false : null,
384
474
  readonly: true,
385
475
  command,
386
476
  stdout_log: path.relative(root, stdoutLog),
@@ -430,13 +520,18 @@ export async function startMadNativeSwarm(root, madLaunch, args = [], profile =
430
520
  }
431
521
  export function resolveMadNativeSwarmOptions(args = [], profile = {}, opts = {}) {
432
522
  const list = (args || []).map((arg) => String(arg));
433
- const disabled = list.includes('--no-swarm') || list.includes('--no-mad-swarm') || process.env.SKS_MAD_NATIVE_SWARM === '0';
523
+ const operatorDisabled = list.includes('--no-swarm') || list.includes('--no-mad-swarm') || process.env.SKS_MAD_NATIVE_SWARM === '0';
524
+ const glmRequested = list.includes('--glm') || opts.glmLaunch?.provider === 'openrouter';
525
+ const glmNativeSwarmDisabled = glmRequested && process.env.SKS_GLM_MAD_ALLOW_GPT_SWARM !== '1';
526
+ const disabled = operatorDisabled || glmNativeSwarmDisabled;
434
527
  const agents = clampInt(readOption(list, '--mad-agents', readOption(list, '--mad-swarm-agents', process.env.SKS_MAD_SWARM_AGENTS || opts.agents || 5)), 1, 20);
435
528
  const workItems = clampInt(readOption(list, '--mad-swarm-work-items', process.env.SKS_MAD_SWARM_WORK_ITEMS || opts.workItems || agents), agents, 100);
436
529
  const backend = defaultMadSwarmBackend(list, opts);
437
530
  return {
438
531
  enabled: !disabled,
439
- disabled_reason: disabled ? 'operator_disabled_mad_native_swarm' : null,
532
+ disabled_reason: operatorDisabled
533
+ ? 'operator_disabled_mad_native_swarm'
534
+ : glmNativeSwarmDisabled ? 'glm_mad_native_swarm_disabled_to_block_gpt_fallback' : null,
440
535
  agents,
441
536
  workItems,
442
537
  backend,
@@ -516,12 +611,14 @@ async function activateMadZellijPermissionState(cwd = process.cwd(), args = [])
516
611
  const root = await sksRoot();
517
612
  if (!(await exists(path.join(root, '.sneakoscope'))))
518
613
  await initProject(root, {});
614
+ const rawArgs = (args || []).map((arg) => String(arg));
615
+ const activatedBy = rawArgs.includes('--glm') ? 'sks --mad --glm' : 'sks --mad';
519
616
  const flags = parseMadSksFlags(['--mad-sks', ...args].filter(Boolean));
520
- const permission = buildMadSksPermissionModel({ targetRoot: cwd, userIntent: 'sks --mad Zellij scoped high-power maintenance session', flags });
617
+ const permission = buildMadSksPermissionModel({ targetRoot: cwd, userIntent: `${activatedBy} Zellij scoped high-power maintenance session`, flags });
521
618
  const allowedScopes = new Set(permission.allowed_scopes || []);
522
619
  const has = (scope) => allowedScopes.has(scope);
523
620
  const dbWriteAllowed = has('db_write');
524
- const { id, dir } = await createMission(root, { mode: 'mad-sks', prompt: 'sks --mad Zellij scoped high-power maintenance session' });
621
+ const { id, dir } = await createMission(root, { mode: 'mad-sks', prompt: `${activatedBy} Zellij scoped high-power maintenance session` });
525
622
  await writeCodex0138CapabilityArtifacts(root, { missionId: id }).catch(() => null);
526
623
  await writeCodex0139CapabilityArtifacts(root, { missionId: id }).catch(() => null);
527
624
  const codexNativeInvocation = await resolveCodexNativeInvocationPlan({
@@ -582,7 +679,7 @@ async function activateMadZellijPermissionState(cwd = process.cwd(), args = [])
582
679
  warnings: codexNativeInvocation.warnings,
583
680
  artifact_path: 'mad-codex-native-invocation.json'
584
681
  } : null,
585
- activated_by: 'sks --mad',
682
+ activated_by: activatedBy,
586
683
  cwd: path.resolve(cwd || process.cwd())
587
684
  };
588
685
  await writeJsonAtomic(path.join(dir, 'mad-sks-gate.json'), gate);
@@ -621,6 +718,7 @@ function madLaunchOnlyFlags() {
621
718
  '--mad',
622
719
  '--MAD',
623
720
  '--mad-sks',
721
+ '--glm',
624
722
  '--high',
625
723
  '--attach',
626
724
  '--no-attach',
package/dist/core/fsx.js CHANGED
@@ -5,7 +5,7 @@ import os from 'node:os';
5
5
  import crypto from 'node:crypto';
6
6
  import { spawn } from 'node:child_process';
7
7
  import { fileURLToPath } from 'node:url';
8
- export const PACKAGE_VERSION = '4.0.3';
8
+ export const PACKAGE_VERSION = '4.0.4';
9
9
  export const DEFAULT_PROCESS_TAIL_BYTES = 256 * 1024;
10
10
  export const DEFAULT_PROCESS_TIMEOUT_MS = 30 * 60 * 1000;
11
11
  export function nowIso() {
@@ -0,0 +1,113 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { nowIso, writeTextAtomic } from '../../fsx.js';
4
+ import { resolveOpenRouterApiKey, openRouterSecretPaths } from '../openrouter/openrouter-secret-store.js';
5
+ import { GLM_52_OPENROUTER_MODEL } from './glm-52-settings.js';
6
+ export const GLM_MAD_PROFILE_ID = 'sks/glm-5.2-mad';
7
+ export const OPENROUTER_CODEX_PROVIDER = 'openrouter';
8
+ export function buildMadGlmLaunchProfileNoWrite() {
9
+ return {
10
+ schema: 'sks.glm-mad-launch-profile.v1',
11
+ profile_name: GLM_MAD_PROFILE_ID,
12
+ provider: OPENROUTER_CODEX_PROVIDER,
13
+ model: GLM_52_OPENROUTER_MODEL,
14
+ launch_args: [
15
+ '--sandbox',
16
+ 'danger-full-access',
17
+ '--ask-for-approval',
18
+ 'never',
19
+ '-c',
20
+ 'service_tier=fast',
21
+ '-c',
22
+ 'model_reasoning_effort=high',
23
+ '-c',
24
+ 'model_provider="openrouter"',
25
+ '-c',
26
+ `model="${GLM_52_OPENROUTER_MODEL}"`,
27
+ '-c',
28
+ 'model_providers.openrouter.name="OpenRouter"',
29
+ '-c',
30
+ 'model_providers.openrouter.base_url="https://openrouter.ai/api/v1"',
31
+ '-c',
32
+ 'model_providers.openrouter.env_key="OPENROUTER_API_KEY"',
33
+ '-c',
34
+ 'model_providers.openrouter.wire_api="responses"',
35
+ '-c',
36
+ 'model_providers.openrouter.requires_openai_auth=false'
37
+ ],
38
+ sandbox_mode: 'danger-full-access',
39
+ approval_policy: 'never',
40
+ model_reasoning_effort: 'high',
41
+ service_tier: 'fast',
42
+ gpt_fallback_allowed: false,
43
+ writes_user_codex_config: false
44
+ };
45
+ }
46
+ export async function resolveMadGlmLaunchKey(env = process.env) {
47
+ return resolveOpenRouterApiKey({ env });
48
+ }
49
+ export async function writeMadGlmCodexWrapper(input) {
50
+ const env = input.env || process.env;
51
+ const paths = openRouterSecretPaths(env);
52
+ const realCodexBin = String(input.realCodexBin || env.SKS_CODEX_BIN || 'codex');
53
+ const wrapperPath = path.join(input.missionDir, 'sks-glm-codex-wrapper.sh');
54
+ await writeTextAtomic(wrapperPath, buildMadGlmCodexWrapperScript({
55
+ realCodexBin,
56
+ secretKeyPath: paths.keyPath
57
+ }));
58
+ await fs.chmod(wrapperPath, 0o700).catch(() => undefined);
59
+ return {
60
+ wrapper_path: wrapperPath,
61
+ real_codex_bin: realCodexBin,
62
+ secret_key_path: paths.keyPath,
63
+ raw_key_written_to_wrapper: false
64
+ };
65
+ }
66
+ export function buildMadGlmCodexWrapperScript(input) {
67
+ return [
68
+ '#!/bin/sh',
69
+ 'set -eu',
70
+ '# Generated by SKS GLM MAD launch. This wrapper reads the key at runtime',
71
+ '# so Zellij layout artifacts never contain the raw OpenRouter secret.',
72
+ 'if [ -z "${OPENROUTER_API_KEY:-}" ] && [ -n "${SKS_OPENROUTER_API_KEY:-}" ]; then',
73
+ ' OPENROUTER_API_KEY="$SKS_OPENROUTER_API_KEY"',
74
+ ' export OPENROUTER_API_KEY',
75
+ 'fi',
76
+ `if [ -z "\${OPENROUTER_API_KEY:-}" ] && [ -r ${shellQuote(input.secretKeyPath)} ]; then`,
77
+ ` OPENROUTER_API_KEY="$(cat ${shellQuote(input.secretKeyPath)})"`,
78
+ ' export OPENROUTER_API_KEY',
79
+ 'fi',
80
+ 'if [ -z "${OPENROUTER_API_KEY:-}" ]; then',
81
+ ' echo "SKS GLM MAD blocked: OPENROUTER_API_KEY is missing. Run sks --mad --glm --repair or export OPENROUTER_API_KEY." >&2',
82
+ ' exit 66',
83
+ 'fi',
84
+ `exec ${shellQuote(input.realCodexBin)} "$@"`,
85
+ ''
86
+ ].join('\n');
87
+ }
88
+ export function buildMadGlmLaunchArtifact(input) {
89
+ const profile = input.profile || buildMadGlmLaunchProfileNoWrite();
90
+ return {
91
+ schema: 'sks.glm-mad-launch.v1',
92
+ generated_at: nowIso(),
93
+ ok: Boolean(input.keyResolution.key),
94
+ mission_id: input.missionId,
95
+ provider: profile.provider,
96
+ model: profile.model,
97
+ profile_name: profile.profile_name,
98
+ strict_model_lock: true,
99
+ gpt_fallback_allowed: false,
100
+ openrouter_key_source: input.keyResolution.source || null,
101
+ key_preview: input.keyResolution.key_preview || null,
102
+ wrapper_path: input.wrapper.wrapper_path,
103
+ real_codex_bin: input.wrapper.real_codex_bin,
104
+ raw_key_written_to_wrapper: false,
105
+ codex_args: profile.launch_args,
106
+ blockers: input.keyResolution.key ? [] : input.keyResolution.blockers,
107
+ warnings: input.keyResolution.warnings || []
108
+ };
109
+ }
110
+ function shellQuote(value) {
111
+ return `'${String(value).replace(/'/g, `'\\''`)}'`;
112
+ }
113
+ //# sourceMappingURL=glm-mad-launch.js.map
@@ -1,2 +1,2 @@
1
- export const PACKAGE_VERSION = '4.0.3';
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.3",
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",