sneakoscope 4.6.5 → 4.7.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/README.md +18 -4
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/crates/sks-core/src/main.rs +1 -1
- package/dist/bin/sks.js +1 -1
- package/dist/cli/install-helpers.js +80 -15
- package/dist/commands/codex-app.js +34 -3
- package/dist/commands/doctor.js +1 -1
- package/dist/core/agents/agent-effort-policy.js +110 -5
- package/dist/core/agents/agent-orchestrator.js +27 -3
- package/dist/core/agents/agent-plan.js +2 -2
- package/dist/core/agents/agent-roster.js +8 -0
- package/dist/core/agents/agent-worker-slot.js +4 -0
- package/dist/core/codex/agent-config-file-repair.js +4 -4
- package/dist/core/codex-app/codex-app-fast-ui-repair.js +4 -2
- package/dist/core/codex-app/codex-app-ui-state-snapshot.js +14 -3
- package/dist/core/codex-app/glm-model-profile.js +1 -1
- package/dist/core/codex-app/glm-profile-installer.js +111 -7
- package/dist/core/codex-app/glm-profile-schema.js +21 -2
- package/dist/core/codex-app.js +2 -0
- package/dist/core/codex-control/codex-sdk-config-policy.js +2 -1
- package/dist/core/codex-model-guard.js +3 -1
- package/dist/core/commands/fast-mode-command.js +5 -2
- package/dist/core/commands/glm-command.js +2 -1
- package/dist/core/commands/mad-sks-command.js +24 -0
- package/dist/core/doctor/doctor-codex-startup-repair.js +111 -9
- package/dist/core/feature-registry.js +3 -3
- package/dist/core/fsx.js +1 -1
- package/dist/core/harness-guard.js +89 -3
- package/dist/core/init.js +13 -16
- package/dist/core/managed-assets/managed-assets-manifest.js +9 -8
- package/dist/core/pipeline-internals/runtime-core.js +3 -3
- package/dist/core/providers/glm/glm-52-profile.js +46 -0
- package/dist/core/providers/glm/glm-52-request.js +11 -2
- package/dist/core/providers/glm/glm-direct-run.js +1 -0
- package/dist/core/providers/glm/glm-mad-launch.js +3 -2
- package/dist/core/providers/glm/glm-profile-resolver.js +69 -4
- package/dist/core/providers/glm/naruto/glm-naruto-command.js +2 -1
- package/dist/core/team-live.js +2 -2
- package/dist/core/version.js +1 -1
- package/dist/scripts/agent-role-config-repair-check.js +5 -3
- package/dist/scripts/codex-native-reference-cache-check.js +8 -1
- package/dist/scripts/doctor-codex-startup-repair-check.js +21 -0
- package/dist/scripts/doctor-fixes-codex-app-fast-ui-check.js +6 -2
- package/dist/scripts/naruto-shadow-clone-swarm-check.js +11 -3
- package/dist/scripts/release-readiness-report.js +1 -1
- package/dist/scripts/sks-3-1-6-directive-check-lib.js +11 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -49,7 +49,7 @@ sks seo-geo-optimizer apply latest --mode seo --apply --json
|
|
|
49
49
|
sks seo-geo-optimizer audit --mode geo --target package --offline --json
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
> 📋 **Current release: `v4.
|
|
52
|
+
> 📋 **Current release: `v4.7.0`** — full release history lives in [CHANGELOG.md](CHANGELOG.md). This README documents how Sneakoscope works today, not its version-by-version changes. Release readiness is tracked in [docs/release-readiness.md](docs/release-readiness.md).
|
|
53
53
|
|
|
54
54
|
## 🍥 Parallelism, UX, And Integrations
|
|
55
55
|
|
|
@@ -321,6 +321,8 @@ sks fix-path
|
|
|
321
321
|
sks update now
|
|
322
322
|
```
|
|
323
323
|
|
|
324
|
+
`sks doctor --fix` repairs stale SKS-managed Codex TOML, agent role `config_file` paths, and unsupported managed role fields. It now dedupes repeated TOML tables before repair, keeps the first existing external MCP block such as `context7` or `supabase` unchanged, and only removes/repairs SKS-owned stale MCP blocks such as broken `node_repl`.
|
|
325
|
+
|
|
324
326
|
### Open Codex CLI With Zellij
|
|
325
327
|
|
|
326
328
|
```sh
|
|
@@ -330,7 +332,7 @@ sks team open-zellij latest
|
|
|
330
332
|
sks team attach-zellij latest
|
|
331
333
|
```
|
|
332
334
|
|
|
333
|
-
Interactive SKS sessions use Zellij layouts. By default SKS launches Codex in Fast service tier with `--model gpt-5.5`, `-c service_tier="fast"`, the selected `model_reasoning_effort`, and `--no-alt-screen` for Zellij-backed interactive panes so terminal scrollback captures the conversation transcript. Non-GLM SKS sessions force the model to `gpt-5.5
|
|
335
|
+
Interactive SKS sessions use Zellij layouts. By default SKS launches Codex in Fast service tier with `--model gpt-5.5`, `-c service_tier="fast"`, the selected `model_reasoning_effort`, and `--no-alt-screen` for Zellij-backed interactive panes so terminal scrollback captures the conversation transcript. Non-GLM SKS sessions force the model to `gpt-5.5`, while the model guard also recognizes `gpt-5.4-mini` as a supported GPT-5.4 mini model; `sks --mad --glm` is the OpenRouter GLM 5.2 exception. `SKS_CODEX_MODEL` and `SKS_CODEX_FAST_HIGH=0` cannot downgrade or remove the non-GLM model pin. You can still set `SKS_CODEX_REASONING` to change reasoning effort, and `SKS_ZELLIJ_CODEX_ALT_SCREEN=1` restores Codex's alternate-screen UI for the next launch. Use `sks --mad --workspace <name>` for an explicit MAD session and `sks help` for CLI help.
|
|
334
336
|
|
|
335
337
|
Before opening the interactive runtime, SKS checks the installed Codex CLI against npm `@openai/codex@latest`. If a newer version exists, it asks `Y/n`; answering `y` updates automatically with `npm i -g @openai/codex@latest` and then opens the runtime with the updated Codex CLI.
|
|
336
338
|
|
|
@@ -338,6 +340,7 @@ For [codex-lb](https://github.com/Soju06/codex-lb), start the server, create a d
|
|
|
338
340
|
|
|
339
341
|
```sh
|
|
340
342
|
sks codex-lb setup --host https://your-codex-lb.example.com --api-key "sk-clb-..."
|
|
343
|
+
sks codex-lb setup --host https://your-codex-lb.example.com --api-key-stdin --yes
|
|
341
344
|
sks codex-lb health
|
|
342
345
|
sks codex-lb repair
|
|
343
346
|
sks
|
|
@@ -353,6 +356,15 @@ sks codex-lb set-key --api-key-stdin # or: sks codex-lb set-key --api-key "sk-
|
|
|
353
356
|
|
|
354
357
|
(To also change the host, use `sks codex-lb reconfigure --host <domain> --api-key <key>`.)
|
|
355
358
|
|
|
359
|
+
For OpenRouter-backed GLM 5.2 in Codex Desktop/SKS, store the key and install the GLM provider/profiles with:
|
|
360
|
+
|
|
361
|
+
```sh
|
|
362
|
+
sks codex-app set-openrouter-key --api-key-stdin
|
|
363
|
+
sks codex-app glm-profile install
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
This writes the OpenRouter key to the SKS user secret store, writes redacted metadata only, and installs Codex Desktop-compatible `openrouter` provider plus selectable `sks-glm-52-*` reasoning profiles. The npm package does not patch the Codex Desktop macOS menu binary; a top-level `Set OpenRouter Key` menu/modal requires upstream Codex Desktop UI support. The package-owned command surface above is the supported repair path.
|
|
367
|
+
|
|
356
368
|
### Switching auth mode: codex-lb ↔ ChatGPT OAuth
|
|
357
369
|
|
|
358
370
|
Switch between the codex-lb API key and your ChatGPT OAuth login at any time with intent-named commands:
|
|
@@ -390,7 +402,7 @@ sks --mad
|
|
|
390
402
|
sks --mad --allow-package-install --allow-service-control --allow-network --yes
|
|
391
403
|
```
|
|
392
404
|
|
|
393
|
-
This syncs existing codex-lb provider auth, creates/uses the `sks-mad-high` xhigh maintenance profile, opens the MAD-SKS permission gate for that Zellij run, starts a same-mission
|
|
405
|
+
This syncs existing codex-lb provider auth, creates/uses the `sks-mad-high` xhigh maintenance profile, opens the MAD-SKS permission gate for that Zellij run, starts a same-mission bounded native agent swarm, and launches a Codex CLI layout whose right-side lanes read that MAD ledger. Bare `sks --mad` grants target-project file and shell scope only; add explicit `--allow-*` flags for packages, services, network, Computer Use, browser use, generated assets, file permissions, DB writes, or other high-risk scopes. MAD-SKS is not a DB-only unlock and does not create a MadDB capability. Catastrophic database wipe/all-row/project-management safeguards remain active outside the first-class MadDB route, and the pipeline contract still forbids unrequested fallback implementation code.
|
|
394
406
|
|
|
395
407
|
Before launching, SKS checks npm for a newer `sneakoscope` and prints a non-blocking update notice when one is available; use `sks update now` or `sks doctor --fix` when you want SKS to update itself. Use `--yes` to approve missing dependency installs automatically. Tune MAD swarm startup with `--mad-agents <n>`, `--mad-swarm-work-items <n>`, and `--mad-swarm-backend <backend>`; `--no-mad-swarm` keeps only the cockpit UI if you need a temporary fallback.
|
|
396
408
|
|
|
@@ -429,7 +441,7 @@ Manual fan-out syntax:
|
|
|
429
441
|
- Team prompt role counts: `$Team <task> executor:8 reviewer:5`
|
|
430
442
|
- Team CLI flag: `sks team "<task>" --agents 8`
|
|
431
443
|
|
|
432
|
-
Effort
|
|
444
|
+
Effort and model tier are assigned per agent. Managed native agents use bounded workspace-write TOML profiles, but every write still needs an assigned lease, non-overlap proof, and parent-owned integration. When the main model is GPT, simple bounded code/docs slices can downshift to `gpt-5.4-mini`, ordinary tool/lease work uses `gpt-5.5` with low model reasoning, and safety/DB/schema/release lanes use `gpt-5.5` with high model reasoning. When the main model is GLM, native workers stay locked to `z-ai/glm-5.2` and receive GLM effort tiers (`minimal`, `low`, `high`, or `xhigh`) instead of falling back to GPT. If a lease conflict, schema failure, proof blocker, DB risk, or release risk appears, the parent can escalate that lane while keeping unrelated lanes cheaper and faster.
|
|
433
445
|
|
|
434
446
|
### Naruto Massive Parallel Work Swarm (`$Naruto`)
|
|
435
447
|
|
|
@@ -528,6 +540,8 @@ sks codex-app remote-control -- --help
|
|
|
528
540
|
|
|
529
541
|
`sks codex-app check` reports whether the installed Codex CLI is new enough, whether the required app flags are visible, whether Fast/speed-selector config is unlocked, whether Codex App Git Actions can use Commit, Push, Commit and Push, and PR flows, whether the Codex Chrome Extension path is ready for web/browser/webapp verification, and whether installed OpenAI default plugins such as Browser, Chrome, Computer Use, Documents, Presentations, Spreadsheets, and LaTeX are enabled. `sks-fast-high` intentionally does not pin `sandbox_mode`, so the Codex App/IDE permissions selector owns Full Access vs workspace-write while SKS supplies the model, Fast service tier, approval, and reasoning defaults. `sks codex-app chrome-extension --json` is the rapid preflight for web QA/UX/browser routes. When codex-lb is configured, SKS keeps it selected as the top-level Codex App provider while still preserving required app flags and plugin settings. Codex CLI 0.130.0+ app-server/remote-control threads can pick up config changes live; older CLI/TUI sessions should still be restarted after `.codex/config.toml` or MCP/plugin changes.
|
|
530
542
|
|
|
543
|
+
For GLM in Codex Desktop, run `sks codex-app glm-profile install`. This writes the OpenRouter provider and selectable GLM 5.2 profiles into `~/.codex/config.toml`: `sks-glm-52-mad`, `sks-glm-52-minimal`, `sks-glm-52-low`, `sks-glm-52-medium`, `sks-glm-52-high`, and `sks-glm-52-xhigh`. Each profile pins `model = "z-ai/glm-5.2"` and the matching `model_reasoning_effort`, so Desktop profile selection can choose both GLM and the reasoning level without editing TOML by hand.
|
|
544
|
+
|
|
531
545
|
For web-related verification, SKS follows the official Codex Chrome Extension setup path first: https://developers.openai.com/codex/app/chrome-extension. `$QA-LOOP`, `$UX-Review`, `$Image-UX-Review`, browser smoke, authenticated web checks, localhost checks, and web visual review must halt quickly if that extension is missing or disabled. Only after the user says the extension setup is complete should the pipeline resume. Codex Computer Use is for native Mac/non-web targets only; it must not be used as browser/web-app verification evidence.
|
|
532
546
|
|
|
533
547
|
Imagegen is a core SKS capability, not a decorative add-on. `$Image-UX-Review`, `$UX-Review`, `$Visual-Review`, `$UI-UX-Review`, and PPT generated-review paths require real Codex App `$imagegen`/`gpt-image-2` output before full visual verification can pass. For newest-model image requests, prompts should say "Use ChatGPT Images 2.0 / GPT Image 2.0 with gpt-image-2" while still invoking Codex App `$imagegen` when live generation is needed. Use `imagegen-source-scout` when current official docs plus X/social prompt-workflow signals are needed; social sources are prompt heuristics only, not capability or evidence specs. `npm run imagegen:capability` checks that the official Codex App imagegen surface is visible and records that capability detection is not output proof; OpenAI API, Responses image-generation, codex-lb, or `CODEX_LB_API_KEY` fallbacks are non-Codex paths and do not satisfy Codex App generated-image evidence unless a separate API fallback task is explicitly requested. The README architecture asset uses the same rule: run `npm run imagegen:readme-architecture:prompt` to print/write the official prompt, generate the image in Codex App `$imagegen`, then rerun `npm run imagegen:readme-architecture -- --output <path>` after Codex App creates a real gpt-image-2 output. When exactly one current generated_images candidate exists after the prompt, `npm run imagegen:readme-architecture -- --auto-pick-latest` can select it automatically. To let the verifier wait while Codex App writes the file, use `npm run imagegen:readme-architecture -- --wait-ms <milliseconds>`; it still accepts only one current candidate under `$CODEX_HOME/generated_images`. Env forms such as `SKS_CODEX_APP_IMAGEGEN_OUTPUT=<path>` remain supported for automation. Use the selected file directly under `$CODEX_HOME/generated_images`; moved or copied files are not accepted as provenance evidence. Disabled or missing `image_generation` remains a blocker that `sks codex-app check`, `npm run imagegen:capability`, and selftest cover.
|
|
@@ -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.
|
|
7
|
+
Some("--version") => println!("sks-rs 4.7.0"),
|
|
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
|
@@ -14,6 +14,8 @@ import { checkZellijCapability } from '../core/zellij/zellij-capability.js';
|
|
|
14
14
|
import { reconcileCodexAppUpgradeProcesses } from '../core/codex-app.js';
|
|
15
15
|
import { recordCodexLbHealthEvent } from '../core/codex-lb-circuit.js';
|
|
16
16
|
import { loadCodexLbEnv, writeCodexLbKeychain, codexLbMetadataPath } from '../core/codex-lb/codex-lb-env.js';
|
|
17
|
+
import { GLM_CODEX_CONFIG_PROFILE_ID, GLM_CODEX_CONFIG_PROVIDER_ID, GLM_CODEX_CONFIG_REASONING_PROFILES } from '../core/providers/glm/glm-52-profile.js';
|
|
18
|
+
import { GLM_52_OPENROUTER_MODEL } from '../core/providers/glm/glm-52-settings.js';
|
|
17
19
|
import { buildCodexLbSetupPlan, codexLbPersistenceSummary, installCodexLbShellProfileSnippet, selectedCodexLbPersistenceModes } from '../core/codex-lb/codex-lb-setup.js';
|
|
18
20
|
import { runPostinstallGlobalDoctorAndMarkPending } from '../core/update/update-migration-state.js';
|
|
19
21
|
const DEFAULT_CODEX_APP_PLUGINS = [
|
|
@@ -1499,6 +1501,63 @@ export function upsertCodexLbConfig(text = '', baseUrl, selectDefault = true) {
|
|
|
1499
1501
|
next = upsertTomlTable(next, 'model_providers.codex-lb', block);
|
|
1500
1502
|
return `${next.trim()}\n`;
|
|
1501
1503
|
}
|
|
1504
|
+
export function upsertCodexAppGlmConfig(text = '') {
|
|
1505
|
+
let next = String(text || '');
|
|
1506
|
+
const providerBlock = [
|
|
1507
|
+
`[model_providers.${GLM_CODEX_CONFIG_PROVIDER_ID}]`,
|
|
1508
|
+
'name = "OpenRouter"',
|
|
1509
|
+
'base_url = "https://openrouter.ai/api/v1"',
|
|
1510
|
+
'wire_api = "responses"',
|
|
1511
|
+
'env_key = "OPENROUTER_API_KEY"',
|
|
1512
|
+
'requires_openai_auth = false'
|
|
1513
|
+
].join('\n');
|
|
1514
|
+
next = upsertTomlTable(next, `model_providers.${GLM_CODEX_CONFIG_PROVIDER_ID}`, providerBlock);
|
|
1515
|
+
for (const profile of GLM_CODEX_CONFIG_REASONING_PROFILES) {
|
|
1516
|
+
const profileBlock = [
|
|
1517
|
+
`[profiles.${profile.id}]`,
|
|
1518
|
+
`model_provider = "${GLM_CODEX_CONFIG_PROVIDER_ID}"`,
|
|
1519
|
+
`model = "${GLM_52_OPENROUTER_MODEL}"`,
|
|
1520
|
+
`model_reasoning_effort = "${profile.reasoning_effort}"`,
|
|
1521
|
+
'service_tier = "default"',
|
|
1522
|
+
'approval_policy = "on-request"'
|
|
1523
|
+
].join('\n');
|
|
1524
|
+
next = upsertTomlTable(next, `profiles.${profile.id}`, profileBlock);
|
|
1525
|
+
}
|
|
1526
|
+
return `${next.trim()}\n`;
|
|
1527
|
+
}
|
|
1528
|
+
export async function ensureGlobalCodexAppGlmProfile(opts = {}) {
|
|
1529
|
+
if (process.env.SKS_SKIP_CODEX_GLM_PROFILE_REPAIR === '1' && opts.force !== true) {
|
|
1530
|
+
return { ok: true, status: 'skipped', reason: 'SKS_SKIP_CODEX_GLM_PROFILE_REPAIR=1' };
|
|
1531
|
+
}
|
|
1532
|
+
const home = opts.home || process.env.HOME || os.homedir();
|
|
1533
|
+
const configPath = opts.configPath || codexLbConfigPath(home);
|
|
1534
|
+
try {
|
|
1535
|
+
await ensureDir(path.dirname(configPath));
|
|
1536
|
+
const current = await readText(configPath, '');
|
|
1537
|
+
const next = upsertCodexAppGlmConfig(current);
|
|
1538
|
+
const safeWrite = await safeWriteCodexConfigToml(configPath, current, next, 'glm-profile');
|
|
1539
|
+
return {
|
|
1540
|
+
...safeWrite,
|
|
1541
|
+
status: safeWrite.status === 'written' ? 'updated' : safeWrite.status,
|
|
1542
|
+
provider: GLM_CODEX_CONFIG_PROVIDER_ID,
|
|
1543
|
+
model: GLM_52_OPENROUTER_MODEL,
|
|
1544
|
+
codex_config_profile: GLM_CODEX_CONFIG_PROFILE_ID,
|
|
1545
|
+
reasoning_profiles: GLM_CODEX_CONFIG_REASONING_PROFILES.map((profile) => profile.id)
|
|
1546
|
+
};
|
|
1547
|
+
}
|
|
1548
|
+
catch (err) {
|
|
1549
|
+
return {
|
|
1550
|
+
ok: false,
|
|
1551
|
+
status: 'failed',
|
|
1552
|
+
config_path: configPath,
|
|
1553
|
+
error: err.message,
|
|
1554
|
+
provider: GLM_CODEX_CONFIG_PROVIDER_ID,
|
|
1555
|
+
model: GLM_52_OPENROUTER_MODEL,
|
|
1556
|
+
codex_config_profile: GLM_CODEX_CONFIG_PROFILE_ID,
|
|
1557
|
+
reasoning_profiles: GLM_CODEX_CONFIG_REASONING_PROFILES.map((profile) => profile.id)
|
|
1558
|
+
};
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1502
1561
|
function detectCodexLbSetupDrift(state = {}) {
|
|
1503
1562
|
const drift = [];
|
|
1504
1563
|
if (state.useDefaultProvider && state.selected !== true)
|
|
@@ -1582,7 +1641,10 @@ export async function ensureGlobalCodexFastModeDuringInstall(opts = {}) {
|
|
|
1582
1641
|
return { status: 'unparseable_config_preserved', config_path: configPath, backup_path: backupPath, parse_smoke: currentSmoke };
|
|
1583
1642
|
}
|
|
1584
1643
|
}
|
|
1585
|
-
const next = normalizeCodexFastModeUiConfig(current, {
|
|
1644
|
+
const next = normalizeCodexFastModeUiConfig(current, {
|
|
1645
|
+
forceFastMode: opts.forceFastMode === true,
|
|
1646
|
+
forceFastModeOff: opts.forceFastModeOff === true
|
|
1647
|
+
});
|
|
1586
1648
|
if (next === ensureTrailingNewline(current))
|
|
1587
1649
|
return { status: 'present', config_path: configPath };
|
|
1588
1650
|
// Safety gate 2: never WRITE a config that would not parse.
|
|
@@ -1604,17 +1666,18 @@ export function normalizeCodexFastModeUiConfig(text = '', opts = {}) {
|
|
|
1604
1666
|
return normalizeCodexFastModeUiConfigOnce(normalizeCodexFastModeUiConfigOnce(text, opts), opts);
|
|
1605
1667
|
}
|
|
1606
1668
|
function normalizeCodexFastModeUiConfigOnce(text = '', opts = {}) {
|
|
1607
|
-
//
|
|
1608
|
-
//
|
|
1609
|
-
// user's own reasoning effort. SKS continues to manage its own namespaced tables below
|
|
1610
|
-
// ([features], [profiles.sks-*], [user.fast_mode], [plugins]).
|
|
1669
|
+
// Keep model and reasoning selection out of top-level config so Codex Desktop can
|
|
1670
|
+
// expose its native model/speed selectors. SKS-owned defaults live in profiles below.
|
|
1611
1671
|
let next = String(text || '');
|
|
1672
|
+
next = removeLegacyTopLevelCodexModeLocks(next);
|
|
1612
1673
|
next = removeTomlTableKey(next, 'notice', 'fast_default_opt_out');
|
|
1613
1674
|
next = removeTomlTableKey(next, 'features', 'codex_hooks');
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1675
|
+
if (opts.forceFastMode === true) {
|
|
1676
|
+
next = upsertTopLevelTomlString(next, 'service_tier', 'fast');
|
|
1677
|
+
}
|
|
1678
|
+
else if (opts.forceFastModeOff === true) {
|
|
1679
|
+
next = upsertTopLevelTomlString(next, 'service_tier', 'default');
|
|
1680
|
+
}
|
|
1618
1681
|
// Codex App feature flags / fast-mode UI / suppress-warning are SET-IF-ABSENT: a fresh
|
|
1619
1682
|
// config still gets SKS's defaults, but SKS NEVER overrides (re-enables) a feature the
|
|
1620
1683
|
// user disabled in the App, and never rejects-then-hides UI by forcing an unrecognized
|
|
@@ -1627,10 +1690,12 @@ function normalizeCodexFastModeUiConfigOnce(text = '', opts = {}) {
|
|
|
1627
1690
|
'guardian_approval = true', 'tool_suggest = true', 'apps = true', 'plugins = true'
|
|
1628
1691
|
])
|
|
1629
1692
|
next = upsertTomlTableKeyIfAbsent(next, 'features', featureLine);
|
|
1630
|
-
if (opts.forceFastMode === true) {
|
|
1693
|
+
if (opts.forceFastMode === true || opts.forceFastModeOff === true) {
|
|
1631
1694
|
next = upsertTomlTableKey(next, 'user.fast_mode', 'visible = true');
|
|
1632
1695
|
next = upsertTomlTableKey(next, 'user.fast_mode', 'enabled = true');
|
|
1633
|
-
next =
|
|
1696
|
+
next = opts.forceFastMode === true
|
|
1697
|
+
? upsertTomlTableKey(next, 'user.fast_mode', 'default_profile = "sks-fast-high"')
|
|
1698
|
+
: removeTomlTableKey(next, 'user.fast_mode', 'default_profile');
|
|
1634
1699
|
}
|
|
1635
1700
|
else {
|
|
1636
1701
|
next = upsertTomlTableKeyIfAbsent(next, 'user.fast_mode', 'visible = true');
|
|
@@ -1672,7 +1737,7 @@ function removeLegacyTopLevelCodexModeLocks(text = '') {
|
|
|
1672
1737
|
return lines.filter((line, index) => {
|
|
1673
1738
|
if (index >= end)
|
|
1674
1739
|
return true;
|
|
1675
|
-
return !/^\s*model_reasoning_effort\s*=/.test(line);
|
|
1740
|
+
return !/^\s*(?:model|model_reasoning_effort)\s*=/.test(line);
|
|
1676
1741
|
}).join('\n').replace(/^\n+/, '').replace(/\n{3,}/g, '\n\n');
|
|
1677
1742
|
}
|
|
1678
1743
|
function removeTopLevelTomlKeyIfValue(text = '', key = '', value = '') {
|
|
@@ -3051,8 +3116,8 @@ export async function selftestCodexLb(tmp) {
|
|
|
3051
3116
|
});
|
|
3052
3117
|
if (brokenChain.ok || brokenChain.status !== 'previous_response_not_found' || brokenChain.chain_unhealthy !== true)
|
|
3053
3118
|
throw new Error('selftest: codex-lb response chain health check did not detect previous_response_not_found');
|
|
3054
|
-
if (
|
|
3055
|
-
throw new Error('selftest: codex-lb setup did not preserve Codex App feature flags, default plugins, profile-scoped reasoning effort, explicit Fast profile, Codex Git commit generation,
|
|
3119
|
+
if (!codexLbConfig.includes('hooks = true') || hasDeprecatedCodexHooksFeatureFlag(codexLbConfig) || !codexLbConfig.includes('remote_control = true') || !codexLbConfig.includes('multi_agent = true') || !codexLbConfig.includes('fast_mode = true') || !codexLbConfig.includes('fast_mode_ui = true') || !codexLbConfig.includes('codex_git_commit = true') || !codexLbConfig.includes('computer_use = true') || !codexLbConfig.includes('browser_use = true') || !codexLbConfig.includes('browser_use_external = true') || !codexLbConfig.includes('guardian_approval = true') || !codexLbConfig.includes('tool_suggest = true') || !codexLbConfig.includes('apps = true') || !codexLbConfig.includes('plugins = true') || !codexLbConfig.includes('[plugins."latex@openai-bundled"]') || !codexLbConfig.includes('[plugins."documents@openai-primary-runtime"]') || !codexLbConfig.includes('[user.fast_mode]') || !codexLbConfig.includes('visible = true') || !codexLbConfig.includes('enabled = true') || !/\[profiles\.custom\][\s\S]*?model_reasoning_effort = "low"/.test(codexLbConfig) || !/\[profiles\.sks-fast-high\][\s\S]*?service_tier = "fast"/.test(codexLbConfig) || codexLbConfig.includes('fast_default_opt_out = true') || hasTopLevelCodexModeLock(codexLbConfig))
|
|
3120
|
+
throw new Error('selftest: codex-lb setup did not preserve Codex App feature flags, default plugins, profile-scoped reasoning effort, explicit Fast profile, Codex Git commit generation, or migrate the hooks feature flag');
|
|
3056
3121
|
if (!hasCodexUnstableFeatureWarningSuppression(codexLbConfig))
|
|
3057
3122
|
throw new Error('selftest: codex-lb setup did not suppress Codex unstable feature warning');
|
|
3058
3123
|
const codexLbLaunch = `source ${path.join(tmp, '.codex', 'sks-codex-lb.env')} && codex '--model' 'gpt-5.5'`;
|
|
@@ -3068,7 +3133,7 @@ function hasTopLevelCodexModeLock(text = '') {
|
|
|
3068
3133
|
const lines = String(text || '').split('\n');
|
|
3069
3134
|
const firstTable = lines.findIndex((x) => /^\s*\[.+\]\s*$/.test(x));
|
|
3070
3135
|
const top = (firstTable === -1 ? lines : lines.slice(0, firstTable)).join('\n');
|
|
3071
|
-
return /(^|\n)\s*model_reasoning_effort\s*=/.test(top);
|
|
3136
|
+
return /(^|\n)\s*(?:model|model_reasoning_effort)\s*=/.test(top);
|
|
3072
3137
|
}
|
|
3073
3138
|
function hasDeprecatedCodexHooksFeatureFlag(text = '') {
|
|
3074
3139
|
const lines = String(text || '').split('\n');
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { flag } from '../cli/args.js';
|
|
1
|
+
import { flag, readOption } from '../cli/args.js';
|
|
2
2
|
import { printJson } from '../cli/output.js';
|
|
3
3
|
import { codexAccessTokenStatus, codexAppIntegrationStatus, codexChromeExtensionStatus, codexProductDesignPluginStatus, formatCodexAppStatus, formatCodexProductDesignPluginStatus } from '../core/codex-app.js';
|
|
4
4
|
import { codexAppRemoteControlCommand } from '../cli/codex-app-command.js';
|
|
5
|
-
import { sksRoot } from '../core/fsx.js';
|
|
5
|
+
import { readStdin, sksRoot } from '../core/fsx.js';
|
|
6
6
|
import { buildCodexAppHarnessMatrix } from '../core/codex-app/codex-app-harness-matrix.js';
|
|
7
7
|
import { syncCodexSksSkills } from '../core/codex-app/codex-skill-sync.js';
|
|
8
8
|
import { syncCodexAgentRoles } from '../core/codex-app/codex-agent-role-sync.js';
|
|
@@ -11,6 +11,7 @@ import { buildCodexHookLifecycle } from '../core/codex-app/codex-hook-lifecycle.
|
|
|
11
11
|
import { resolveCodexAppExecutionProfile } from '../core/codex-app/codex-app-execution-profile.js';
|
|
12
12
|
import { repairCodexNativeManagedAssets } from '../core/codex-native/codex-native-repair-transaction.js';
|
|
13
13
|
import { doctorCodexAppGlmProfile, installCodexAppGlmProfile } from '../core/codex-app/glm-profile-installer.js';
|
|
14
|
+
import { promptForOpenRouterKeyHidden, writeStoredOpenRouterKey } from '../core/providers/openrouter/openrouter-secret-store.js';
|
|
14
15
|
export async function run(_command, args = []) {
|
|
15
16
|
const action = args[0] || 'check';
|
|
16
17
|
if (action === 'remote-control' || action === 'remote')
|
|
@@ -37,6 +38,28 @@ export async function run(_command, args = []) {
|
|
|
37
38
|
: await doctorCodexAppGlmProfile({ root });
|
|
38
39
|
return printCodexAppResult(args, result);
|
|
39
40
|
}
|
|
41
|
+
if (action === 'set-openrouter-key' || action === 'openrouter-key') {
|
|
42
|
+
const root = await sksRoot();
|
|
43
|
+
const key = await readOpenRouterKeyFromArgs(args.slice(1));
|
|
44
|
+
if (!key) {
|
|
45
|
+
const result = { schema: 'sks.codex-app-openrouter-key.v1', ok: false, status: 'missing_key', blockers: ['openrouter_key_missing'], warnings: [] };
|
|
46
|
+
return printCodexAppResult(args, result);
|
|
47
|
+
}
|
|
48
|
+
const record = await writeStoredOpenRouterKey(key);
|
|
49
|
+
const profile = await installCodexAppGlmProfile({ root, apply: true });
|
|
50
|
+
const result = {
|
|
51
|
+
schema: 'sks.codex-app-openrouter-key.v1',
|
|
52
|
+
ok: profile.ok,
|
|
53
|
+
status: profile.ok ? 'stored' : 'stored_profile_blocked',
|
|
54
|
+
key_preview: record.key_preview,
|
|
55
|
+
raw_key_recorded: false,
|
|
56
|
+
secret_store: 'sks-openrouter-secret-store',
|
|
57
|
+
glm_profile: profile,
|
|
58
|
+
blockers: profile.blockers || [],
|
|
59
|
+
warnings: profile.warnings || []
|
|
60
|
+
};
|
|
61
|
+
return printCodexAppResult(args, result);
|
|
62
|
+
}
|
|
40
63
|
if (action === 'product-design' || action === 'design-product' || action === 'ensure-product-design') {
|
|
41
64
|
const checkOnly = flag(args, '--check-only') || flag(args, '--no-install');
|
|
42
65
|
const status = await codexProductDesignPluginStatus({
|
|
@@ -97,9 +120,17 @@ export async function run(_command, args = []) {
|
|
|
97
120
|
process.exitCode = 1;
|
|
98
121
|
return;
|
|
99
122
|
}
|
|
100
|
-
console.error('Usage: sks codex-app check|status|harness-matrix|skill-sync|agent-role-sync|init-deep|hook-lifecycle|execution-profile|glm-profile [install|doctor]|product-design [--check-only]|ensure-product-design|chrome-extension|pat status|remote-control [--json]');
|
|
123
|
+
console.error('Usage: sks codex-app check|status|harness-matrix|skill-sync|agent-role-sync|init-deep|hook-lifecycle|execution-profile|glm-profile [install|doctor]|set-openrouter-key [--api-key-stdin]|product-design [--check-only]|ensure-product-design|chrome-extension|pat status|remote-control [--json]');
|
|
101
124
|
process.exitCode = 1;
|
|
102
125
|
}
|
|
126
|
+
async function readOpenRouterKeyFromArgs(args = []) {
|
|
127
|
+
const key = readOption(args, '--api-key', readOption(args, '--key', ''));
|
|
128
|
+
if (key)
|
|
129
|
+
return String(key).trim();
|
|
130
|
+
if (flag(args, '--api-key-stdin') || flag(args, '--key-stdin'))
|
|
131
|
+
return String(await readStdin()).trim();
|
|
132
|
+
return await promptForOpenRouterKeyHidden() || '';
|
|
133
|
+
}
|
|
103
134
|
function printCodexAppResult(args = [], result) {
|
|
104
135
|
if (flag(args, '--json')) {
|
|
105
136
|
printJson(result);
|
package/dist/commands/doctor.js
CHANGED
|
@@ -56,7 +56,7 @@ async function runDoctor(args = [], root, doctorFix) {
|
|
|
56
56
|
const actualCodexProbeRequested = flag(args, '--actual-codex') || flag(args, '--require-actual-codex') || Boolean(codexBin);
|
|
57
57
|
const actualCodexProbeEnabled = deepDiagnostics || actualCodexProbeRequested;
|
|
58
58
|
const requireActualCodexProbe = flag(args, '--require-actual-codex') || (deepDiagnostics && doctorFix);
|
|
59
|
-
const shouldEvaluateCodexAppUiRepair = deepDiagnostics || flag(args, '--repair-codex-app-ui');
|
|
59
|
+
const shouldEvaluateCodexAppUiRepair = doctorFix || deepDiagnostics || flag(args, '--repair-codex-app-ui');
|
|
60
60
|
const shouldRunZellijRepair = deepDiagnostics || flag(args, '--repair-zellij') || flag(args, '--install-homebrew') || process.env.SKS_REQUIRE_ZELLIJ === '1';
|
|
61
61
|
const nativeCapabilityDiagnosticsRequested = deepDiagnostics || flag(args, '--repair-native-capabilities');
|
|
62
62
|
const doctorPhaseIds = doctorPhaseIdsForProfile(doctorProfile);
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { codexModelEffortCapability } from '../codex-control/codex-model-capabilities.js';
|
|
2
|
+
import { GPT54_MINI_CODEX_MODEL, REQUIRED_CODEX_MODEL } from '../codex-model-guard.js';
|
|
3
|
+
import { GLM_52_OPENROUTER_MODEL } from '../providers/glm/glm-52-settings.js';
|
|
2
4
|
const XHIGH_SIGNAL_RE = /(frontier|autoresearch|novelty|hypothesis|falsif|forensic|from-chat-img|image\s*work\s*order|새로운\s*연구|가설|포렌식)/i;
|
|
3
5
|
const HIGH_SIGNAL_RE = /(database|supabase|sql|migration|security|permission|mad|release|publish|deploy|architecture|policy|schema|hook|rollback|db|보안|배포|마이그레이션|데이터베이스|권한|릴리즈)/i;
|
|
4
6
|
const MEDIUM_SIGNAL_RE = /(tmux|terminal|cli|tool(?:\s|-)?call|router|routing|orchestrat|pipeline|multi[-\s]?session|multi[-\s]?agent|lease|ledger|proof|검증|파이프라인|오케스트레이션|병렬|에이전트)/i;
|
|
5
7
|
const SIMPLE_SIGNAL_RE = /(tiny|simple|small|one[-\s]?line|typo|copy|label|spacing|rename|readme|docs?|간단|단순|오타|문구|라벨)/i;
|
|
8
|
+
const SIMPLE_CODE_MOD_RE = /(tiny|simple|small|one[-\s]?line|typo|copy|label|spacing|rename|readme|docs?|minor|bounded|간단|단순|작은|오타|문구|라벨|이름\s*변경)/i;
|
|
6
9
|
export function decideAgentEffort(input = {}) {
|
|
7
10
|
const persona = input.persona || {};
|
|
8
11
|
const prompt = String(input.prompt || '');
|
|
@@ -27,14 +30,19 @@ export function decideAgentEffort(input = {}) {
|
|
|
27
30
|
effort = 'high';
|
|
28
31
|
reason = 'implementation_lane_capped_at_high';
|
|
29
32
|
}
|
|
30
|
-
const
|
|
33
|
+
const modelDecision = decideAgentWorkerModel({ effort, prompt, role, agentId, readonly: input.readonly === true || persona.read_only === true, writePolicy: String(persona.write_policy || '') });
|
|
34
|
+
const modelCapability = codexModelEffortCapability({ model: modelDecision.model, defaultEffort: modelDecision.model_reasoning_effort });
|
|
31
35
|
return {
|
|
32
36
|
schema: 'sks.agent-effort-decision.v1',
|
|
33
37
|
policy_version: 1,
|
|
34
38
|
agent_id: agentId,
|
|
35
39
|
role,
|
|
40
|
+
model: modelDecision.model,
|
|
36
41
|
reasoning_effort: effort,
|
|
37
|
-
model_reasoning_effort:
|
|
42
|
+
model_reasoning_effort: modelDecision.model_reasoning_effort,
|
|
43
|
+
model_tier: modelDecision.model_tier,
|
|
44
|
+
model_profile: modelDecision.model_profile,
|
|
45
|
+
model_selection_reason: modelDecision.reason,
|
|
38
46
|
model_effort_capability: modelCapability,
|
|
39
47
|
reasoning_profile: reasoningProfileName(effort),
|
|
40
48
|
service_tier: 'fast',
|
|
@@ -76,14 +84,19 @@ export function decideNarutoCloneEffort(input = {}) {
|
|
|
76
84
|
const writes = !readonly || /write|edit|route-local|workspace|patch|integrat/i.test(writePolicy) || hasActionTool;
|
|
77
85
|
const toolUse = writes || NARUTO_ACTION_TOOL_RE.test(prompt);
|
|
78
86
|
const effort = toolUse ? 'medium' : 'low';
|
|
79
|
-
const
|
|
87
|
+
const modelDecision = decideAgentWorkerModel({ effort, prompt, role, agentId, readonly, writePolicy: String(writePolicy || '') });
|
|
88
|
+
const modelCapability = codexModelEffortCapability({ model: modelDecision.model, defaultEffort: modelDecision.model_reasoning_effort });
|
|
80
89
|
return {
|
|
81
90
|
schema: 'sks.agent-effort-decision.v1',
|
|
82
91
|
policy_version: 1,
|
|
83
92
|
agent_id: agentId,
|
|
84
93
|
role,
|
|
94
|
+
model: modelDecision.model,
|
|
85
95
|
reasoning_effort: effort,
|
|
86
|
-
model_reasoning_effort:
|
|
96
|
+
model_reasoning_effort: modelDecision.model_reasoning_effort,
|
|
97
|
+
model_tier: modelDecision.model_tier,
|
|
98
|
+
model_profile: modelDecision.model_profile,
|
|
99
|
+
model_selection_reason: modelDecision.reason,
|
|
87
100
|
model_effort_capability: modelCapability,
|
|
88
101
|
reasoning_profile: reasoningProfileName(effort),
|
|
89
102
|
service_tier: 'fast',
|
|
@@ -102,7 +115,12 @@ export function buildAgentEffortPolicy(roster = {}) {
|
|
|
102
115
|
agent_id: agent.id,
|
|
103
116
|
session_id: agent.session_id,
|
|
104
117
|
role: agent.role,
|
|
118
|
+
model: agent.model,
|
|
105
119
|
reasoning_effort: agent.reasoning_effort,
|
|
120
|
+
model_reasoning_effort: agent.model_reasoning_effort,
|
|
121
|
+
model_tier: agent.model_tier,
|
|
122
|
+
model_profile: agent.model_profile,
|
|
123
|
+
model_selection_reason: agent.model_selection_reason,
|
|
106
124
|
reasoning_profile: agent.reasoning_profile,
|
|
107
125
|
reason: agent.reasoning_reason,
|
|
108
126
|
dynamic: true
|
|
@@ -112,13 +130,15 @@ export function buildAgentEffortPolicy(roster = {}) {
|
|
|
112
130
|
policy_version: 1,
|
|
113
131
|
dynamic: true,
|
|
114
132
|
service_tier: 'fast',
|
|
133
|
+
allowed_models: [GPT54_MINI_CODEX_MODEL, REQUIRED_CODEX_MODEL, GLM_52_OPENROUTER_MODEL],
|
|
134
|
+
model_tiers: ['gpt-5.4-mini', 'gpt-5.5-low', 'gpt-5.5-high', 'glm-5.2-minimal', 'glm-5.2-low', 'glm-5.2-high', 'glm-5.2-xhigh'],
|
|
115
135
|
allowed_efforts: codexModelEffortCapability().advertised_efforts,
|
|
116
136
|
model_effort_capability: codexModelEffortCapability(),
|
|
117
137
|
max_agents: roster.max_agents || 20,
|
|
118
138
|
agent_count: roster.agent_count || decisions.length,
|
|
119
139
|
concurrency: roster.concurrency || decisions.length,
|
|
120
140
|
decisions,
|
|
121
|
-
rule: 'Parent orchestration assigns per-agent
|
|
141
|
+
rule: 'Parent orchestration assigns per-agent model tiers from prompt risk, persona role, lease ownership, and proof state: simple bounded GPT workers can downshift to gpt-5.4-mini; ordinary GPT workers use gpt-5.5 low; risky GPT lanes use gpt-5.5 high. In GLM mode, native workers stay on z-ai/glm-5.2 and receive GLM effort tiers.'
|
|
122
142
|
};
|
|
123
143
|
}
|
|
124
144
|
export function reasoningProfileName(effort) {
|
|
@@ -144,4 +164,89 @@ function effortReason(effort) {
|
|
|
144
164
|
return 'simple_bounded_slice';
|
|
145
165
|
return 'default_orchestration_slice';
|
|
146
166
|
}
|
|
167
|
+
export function decideAgentWorkerModel(input = {}) {
|
|
168
|
+
const mainModel = String(input.mainModel || process.env.SKS_CODEX_MODEL || process.env.CODEX_MODEL || REQUIRED_CODEX_MODEL).trim();
|
|
169
|
+
const glmMain = isGlmWorkerMode(mainModel);
|
|
170
|
+
const gptMain = !glmMain && (!mainModel || /^gpt-/i.test(mainModel));
|
|
171
|
+
const effort = String(input.effort || 'medium');
|
|
172
|
+
const text = [input.prompt, input.role, input.agentId, input.writePolicy].map((item) => String(item || '')).join(' ');
|
|
173
|
+
const simpleText = [input.prompt, input.role, input.agentId].map((item) => String(item || '')).join(' ');
|
|
174
|
+
const risky = HIGH_SIGNAL_RE.test(text) || XHIGH_SIGNAL_RE.test(text);
|
|
175
|
+
const simple = SIMPLE_CODE_MOD_RE.test(simpleText) && !HIGH_SIGNAL_RE.test(simpleText) && !XHIGH_SIGNAL_RE.test(simpleText);
|
|
176
|
+
if (glmMain) {
|
|
177
|
+
const glmEffort = glmWorkerEffort({ effort, risky, simple });
|
|
178
|
+
return {
|
|
179
|
+
model: GLM_52_OPENROUTER_MODEL,
|
|
180
|
+
model_reasoning_effort: glmEffort,
|
|
181
|
+
model_tier: `glm-5.2-${glmEffort === 'none' ? 'minimal' : glmEffort}`,
|
|
182
|
+
model_profile: glmProfileForReasoning(glmEffort),
|
|
183
|
+
reason: `glm_52_${glmEffort}_worker`
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
if (gptMain && risky) {
|
|
187
|
+
return {
|
|
188
|
+
model: REQUIRED_CODEX_MODEL,
|
|
189
|
+
model_reasoning_effort: 'high',
|
|
190
|
+
model_tier: 'gpt-5.5-high',
|
|
191
|
+
model_profile: 'sks-agent-gpt-5.5-high-fast',
|
|
192
|
+
reason: 'risk_signal_worker'
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
if (gptMain && (simple || effort === 'low')) {
|
|
196
|
+
return {
|
|
197
|
+
model: GPT54_MINI_CODEX_MODEL,
|
|
198
|
+
model_reasoning_effort: 'low',
|
|
199
|
+
model_tier: 'gpt-5.4-mini',
|
|
200
|
+
model_profile: 'sks-agent-gpt-5.4-mini-fast',
|
|
201
|
+
reason: simple ? 'simple_code_or_docs_slice_downshift' : 'low_effort_worker_downshift'
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
if (gptMain && (effort === 'high' || effort === 'xhigh')) {
|
|
205
|
+
return {
|
|
206
|
+
model: REQUIRED_CODEX_MODEL,
|
|
207
|
+
model_reasoning_effort: 'high',
|
|
208
|
+
model_tier: 'gpt-5.5-high',
|
|
209
|
+
model_profile: 'sks-agent-gpt-5.5-high-fast',
|
|
210
|
+
reason: 'risk_or_high_effort_worker'
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
model: gptMain ? REQUIRED_CODEX_MODEL : mainModel || REQUIRED_CODEX_MODEL,
|
|
215
|
+
model_reasoning_effort: 'low',
|
|
216
|
+
model_tier: 'gpt-5.5-low',
|
|
217
|
+
model_profile: 'sks-agent-gpt-5.5-low-fast',
|
|
218
|
+
reason: gptMain ? 'ordinary_worker_gpt55_low' : 'non_gpt_main_model_preserved'
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
function isGlmWorkerMode(mainModel) {
|
|
222
|
+
const model = String(mainModel || '').trim().toLowerCase();
|
|
223
|
+
return model === GLM_52_OPENROUTER_MODEL
|
|
224
|
+
|| model === 'glm-5.2'
|
|
225
|
+
|| model === 'glm5.2'
|
|
226
|
+
|| process.env.SKS_GLM_MODE === '1'
|
|
227
|
+
|| process.env.SKS_GLM_WRAPPER_ACTIVE === '1'
|
|
228
|
+
|| process.env.SKS_GLM_MAD_ACTIVE === '1';
|
|
229
|
+
}
|
|
230
|
+
function glmWorkerEffort(input) {
|
|
231
|
+
if (input.effort === 'xhigh')
|
|
232
|
+
return 'xhigh';
|
|
233
|
+
if (input.risky || input.effort === 'high')
|
|
234
|
+
return 'high';
|
|
235
|
+
if (input.simple || input.effort === 'low')
|
|
236
|
+
return 'minimal';
|
|
237
|
+
return 'low';
|
|
238
|
+
}
|
|
239
|
+
function glmProfileForReasoning(effort) {
|
|
240
|
+
if (effort === 'xhigh')
|
|
241
|
+
return 'sks-glm-52-xhigh';
|
|
242
|
+
if (effort === 'high')
|
|
243
|
+
return 'sks-glm-52-high';
|
|
244
|
+
if (effort === 'medium')
|
|
245
|
+
return 'sks-glm-52-medium';
|
|
246
|
+
if (effort === 'low')
|
|
247
|
+
return 'sks-glm-52-low';
|
|
248
|
+
if (effort === 'none')
|
|
249
|
+
return 'sks-glm-52-mad';
|
|
250
|
+
return 'sks-glm-52-minimal';
|
|
251
|
+
}
|
|
147
252
|
//# sourceMappingURL=agent-effort-policy.js.map
|
|
@@ -24,6 +24,7 @@ import { runFakeAgent } from './agent-runner-fake.js';
|
|
|
24
24
|
import { runProcessAgent } from './agent-runner-process.js';
|
|
25
25
|
import { classifyOllamaWorkerSlice, runOllamaAgent } from './agent-runner-ollama.js';
|
|
26
26
|
import { resolveOllamaWorkerConfig } from './ollama-worker-config.js';
|
|
27
|
+
import { decideAgentWorkerModel } from './agent-effort-policy.js';
|
|
27
28
|
import { validateAgentWorkerResult } from './agent-worker-pipeline.js';
|
|
28
29
|
import { writeAgentCleanupReport } from './agent-cleanup.js';
|
|
29
30
|
import { writeAgentTrustReport } from './agent-trust-report.js';
|
|
@@ -93,7 +94,7 @@ export async function runNativeAgentOrchestrator(opts = {}) {
|
|
|
93
94
|
const selectedCoreSkill = routeSkillSelection ? skillProofRecord(routeSkillSelection) : null;
|
|
94
95
|
const namespace = await buildProjectNamespace({ root, missionId });
|
|
95
96
|
await writeProjectNamespaceArtifact(dir, namespace);
|
|
96
|
-
let roster = buildProvidedAgentRoster(opts.roster, { concurrency: opts.concurrency, readonly: opts.readonly, maxAgentCount }) || buildAgentRoster({ agents: opts.agents, concurrency: opts.concurrency, prompt, maxAgentCount, ...(opts.readonly === undefined ? {} : { readonly: opts.readonly }) });
|
|
97
|
+
let roster = buildProvidedAgentRoster(opts.roster, { concurrency: opts.concurrency, readonly: opts.readonly, maxAgentCount, prompt }) || buildAgentRoster({ agents: opts.agents, concurrency: opts.concurrency, prompt, maxAgentCount, ...(opts.readonly === undefined ? {} : { readonly: opts.readonly }) });
|
|
97
98
|
roster = applyFastModeToRoster(roster, fastModePolicy);
|
|
98
99
|
roster.roster = roster.roster.map((agent) => ({
|
|
99
100
|
...agent,
|
|
@@ -1638,6 +1639,19 @@ function buildProvidedAgentRoster(input, opts = {}) {
|
|
|
1638
1639
|
const roster = sourceRows.map((entry, index) => {
|
|
1639
1640
|
const readOnly = opts.readonly === true || entry.read_only === true;
|
|
1640
1641
|
const id = String(entry.id || entry.agent_id || `agent_${index + 1}`);
|
|
1642
|
+
const reasoningEffort = entry.reasoning_effort || entry.model_reasoning_effort || (readOnly ? 'high' : 'medium');
|
|
1643
|
+
const modelDecision = decideAgentWorkerModel({
|
|
1644
|
+
effort: reasoningEffort,
|
|
1645
|
+
prompt: opts.prompt || input?.prompt || '',
|
|
1646
|
+
role: String(entry.role || 'verifier'),
|
|
1647
|
+
agentId: id,
|
|
1648
|
+
readonly: readOnly,
|
|
1649
|
+
writePolicy: String(entry.write_policy || '')
|
|
1650
|
+
});
|
|
1651
|
+
const suppliedModelEffort = String(entry.model_reasoning_effort || '');
|
|
1652
|
+
const modelReasoningEffort = suppliedModelEffort === 'low' || suppliedModelEffort === 'high'
|
|
1653
|
+
? suppliedModelEffort
|
|
1654
|
+
: modelDecision.model_reasoning_effort;
|
|
1641
1655
|
return {
|
|
1642
1656
|
id,
|
|
1643
1657
|
session_id: String(entry.session_id || `${id}-session-${String(index + 1).padStart(2, '0')}`),
|
|
@@ -1646,8 +1660,12 @@ function buildProvidedAgentRoster(input, opts = {}) {
|
|
|
1646
1660
|
index: index + 1,
|
|
1647
1661
|
write_policy: String(entry.write_policy || (readOnly ? 'read-only' : 'route-local-artifact')),
|
|
1648
1662
|
status: 'pending',
|
|
1649
|
-
|
|
1650
|
-
|
|
1663
|
+
model: entry.model || modelDecision.model,
|
|
1664
|
+
reasoning_effort: reasoningEffort,
|
|
1665
|
+
model_reasoning_effort: modelReasoningEffort,
|
|
1666
|
+
model_tier: entry.model_tier || modelDecision.model_tier,
|
|
1667
|
+
model_profile: entry.model_profile || modelDecision.model_profile,
|
|
1668
|
+
model_selection_reason: entry.model_selection_reason || modelDecision.reason,
|
|
1651
1669
|
reasoning_profile: entry.reasoning_profile || (readOnly ? 'sks-logic-high' : 'sks-logic-medium'),
|
|
1652
1670
|
service_tier: entry.service_tier,
|
|
1653
1671
|
reasoning_reason: entry.reasoning_reason || 'route_native_agent_plan',
|
|
@@ -1690,6 +1708,9 @@ async function runAgentByBackend(backend, agent, slice, opts) {
|
|
|
1690
1708
|
sessionId: String(agent.session_id || ''),
|
|
1691
1709
|
cwd: String(opts.cwd || process.cwd()),
|
|
1692
1710
|
prompt: buildDirectSdkWorkerPrompt(slice),
|
|
1711
|
+
model: agent.model || null,
|
|
1712
|
+
reasoningEffort: agent.reasoning_effort || null,
|
|
1713
|
+
modelReasoningEffort: agent.model_reasoning_effort || agent.reasoning_effort || null,
|
|
1693
1714
|
inputFiles: Array.isArray(opts.inputFiles) ? opts.inputFiles.map(String) : [],
|
|
1694
1715
|
inputImages: Array.isArray(opts.inputImages) ? opts.inputImages.map(String) : [],
|
|
1695
1716
|
outputSchemaId: CODEX_AGENT_WORKER_RESULT_SCHEMA_ID,
|
|
@@ -1723,6 +1744,9 @@ async function runAgentByBackend(backend, agent, slice, opts) {
|
|
|
1723
1744
|
structured_output_valid: sdkTask.structuredOutputValid,
|
|
1724
1745
|
worker_result_path: path.relative(ledgerRoot, sdkTask.workerResultPath),
|
|
1725
1746
|
patch_envelope_path: sdkTask.patchEnvelopePath ? path.relative(ledgerRoot, sdkTask.patchEnvelopePath) : null,
|
|
1747
|
+
model: agent.model || null,
|
|
1748
|
+
model_reasoning_effort: agent.model_reasoning_effort || null,
|
|
1749
|
+
model_tier: agent.model_tier || null,
|
|
1726
1750
|
service_tier: opts.serviceTier || 'fast',
|
|
1727
1751
|
fast_mode: opts.fastMode !== false,
|
|
1728
1752
|
blockers: sdkTask.blockers
|
|
@@ -36,8 +36,8 @@ export function agentPipelineStage(policy = {}) {
|
|
|
36
36
|
agent_count: required ? Number(policy.agent_count || DEFAULT_AGENT_COUNT) : 0,
|
|
37
37
|
max_parallel_native_sessions: Number(policy.agent_count || DEFAULT_AGENT_COUNT),
|
|
38
38
|
backend: 'native-agent-kernel',
|
|
39
|
-
read_only:
|
|
40
|
-
write_policy: '
|
|
39
|
+
read_only: false,
|
|
40
|
+
write_policy: 'bounded workspace-write analysis leases; parent-owned integration',
|
|
41
41
|
outputs: policy.outputs || ['agents/agent-proof-evidence.json']
|
|
42
42
|
};
|
|
43
43
|
}
|