sneakoscope 10.3.9 → 10.3.10
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 +5 -5
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/dist/config/skills-manifest.json +1 -1
- package/dist/core/agent-bridge/async-command.js +5 -3
- package/dist/core/agents/agent-effort-policy.js +3 -6
- package/dist/core/agents/agent-orchestrator.js +0 -1
- package/dist/core/agents/agent-roster.js +2 -4
- package/dist/core/agents/native-worker-backend-router.js +5 -5
- package/dist/core/codex-app/codex-model-catalog.js +0 -3
- package/dist/core/codex-app/openrouter-provider.js +0 -1
- package/dist/core/codex-compat/codex-capability-matrix.js +0 -9
- package/dist/core/codex-compat/codex-runtime-contract.js +0 -1
- package/dist/core/codex-control/codex-sdk-config-policy.js +2 -1
- package/dist/core/codex-lb/combined-catalog/builder.js +2 -2
- package/dist/core/codex-lb/combined-catalog/latest-generation.js +53 -0
- package/dist/core/codex-lb/desktop-controller-v3/live-probes.js +2 -3
- package/dist/core/codex-lb/desktop-controller-v3/preflight-probes.js +2 -3
- package/dist/core/codex-lb/desktop-controller-v3/probe-route.js +23 -0
- package/dist/core/codex-model-guard.js +0 -9
- package/dist/core/commands/naruto-command.js +2 -2
- package/dist/core/doctor/doctor-codex-startup-repair.js +8 -0
- package/dist/core/doctor/stale-subagent-default.js +30 -0
- package/dist/core/harness-conflicts.js +1 -1
- package/dist/core/hooks-runtime/exclusive-gui-surface-gate.js +155 -0
- package/dist/core/hooks-runtime/global-role-pin-refresh.js +25 -0
- package/dist/core/hooks-runtime/hook-context.js +3 -1
- package/dist/core/hooks-runtime/jev-spawn-routing.js +2 -6
- package/dist/core/hooks-runtime/managed-guidance-preflight.js +20 -2
- package/dist/core/hooks-runtime/parent-orchestration-gate.js +3 -3
- package/dist/core/hooks-runtime/payload-signals.js +1 -1
- package/dist/core/hooks-runtime/spawn-role-pin-heal.js +15 -0
- package/dist/core/hooks-runtime/spawn-tool-name.js +7 -0
- package/dist/core/hooks-runtime/subagent-spawn-policy.js +7 -4
- package/dist/core/hooks-runtime/subagent-stop-hook.js +2 -0
- package/dist/core/hooks-runtime.js +12 -1
- package/dist/core/init.js +1 -0
- package/dist/core/managed-assets/managed-assets-manifest.js +1 -1
- package/dist/core/pipeline-internals/runtime-core.js +2 -3
- package/dist/core/provider/model-router.js +8 -11
- package/dist/core/recallpulse/policy.js +3 -3
- package/dist/core/recallpulse.js +1 -1
- package/dist/core/research/mock-result.js +3 -3
- package/dist/core/research/research-adversarial-review.js +12 -12
- package/dist/core/research/research-claim-synthesizer.js +5 -5
- package/dist/core/research/research-falsification-runner.js +5 -5
- package/dist/core/research/research-super-search.js +2 -2
- package/dist/core/research/research-synthesis-writer.js +4 -4
- package/dist/core/research.js +7 -7
- package/dist/core/routes.js +5 -3
- package/dist/core/subagents/agent-catalog.js +3 -0
- package/dist/core/subagents/exclusive-surface-rule.js +3 -0
- package/dist/core/subagents/exclusive-tool-surface.js +19 -0
- package/dist/core/subagents/model-policy.js +8 -11
- package/dist/core/subagents/model-tiers.js +99 -22
- package/dist/core/subagents/naruto-help-contract.js +7 -7
- package/dist/core/subagents/naruto-host-credentials.js +3 -3
- package/dist/core/subagents/official-subagent-config.js +11 -5
- package/dist/core/subagents/official-subagent-prompt.js +3 -1
- package/dist/core/subagents/role-model-pins.js +84 -0
- package/dist/core/version.js +1 -1
- package/dist/native/sks-menubar/Sources/SettingsViewController.swift +1 -1
- package/dist/scripts/codex-sdk-backend-router-check.js +4 -5
- package/package.json +1 -1
- package/dist/core/codex-app/codex-desktop-routing-ownership.js +0 -90
- package/dist/core/codex-app/codex-models-cache.js +0 -153
- package/dist/core/codex-app/multi-provider-router-support.js +0 -25
- package/dist/core/codex-app/role-model-catalog-priority.js +0 -61
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
Sneakoscope Codex (`sks`) is an open-source trust layer for Codex CLI and ChatGPT Desktop. It coordinates bounded AI coding agents, records machine-verifiable evidence, preserves project memory, and blocks release claims that are not supported by current tests or artifacts. Search visibility outcomes are measured separately; SKS does not promise rankings or traffic.
|
|
17
17
|
<!-- END SKS SEARCH VISIBILITY MARKETING -->
|
|
18
18
|
|
|
19
|
-
Current package: **SKS 10.3.
|
|
19
|
+
Current package: **SKS 10.3.10**. Install the latest stable release from npm.
|
|
20
20
|
|
|
21
21
|
[Quick start](#install-in-one-command) · [Commands](#everyday-commands) · [SKS Center](#sks-center-macos) · [Documentation](#documentation) · [Changelog](CHANGELOG.md)
|
|
22
22
|
|
|
@@ -59,8 +59,8 @@ for setup boundaries and reported execution evidence.
|
|
|
59
59
|
|
|
60
60
|
## Everyday commands
|
|
61
61
|
|
|
62
|
-
SKS enables experimental
|
|
63
|
-
repair. Turn it off in **SKS Center → Settings →
|
|
62
|
+
SKS enables experimental Codex context management by default during setup and
|
|
63
|
+
repair. Turn it off in **SKS Center → Settings → Context management**, or
|
|
64
64
|
use `sks codex-app context-management off`. Updates preserve an explicit opt-out.
|
|
65
65
|
Start a new task after changing the setting. Availability depends on a supported
|
|
66
66
|
Codex client and eligible ChatGPT sign-in; API-key and custom-provider sessions
|
|
@@ -183,8 +183,8 @@ soon as Codex lists it:
|
|
|
183
183
|
| Work | Tier | Effort | Today |
|
|
184
184
|
| --- | --- | --- | --- |
|
|
185
185
|
| Tiny mechanical tasks | fast | low | `gpt-6-luna` |
|
|
186
|
-
| Instructed implementation | balanced | low | `gpt-6-sol` |
|
|
187
|
-
| Exploration, large-context reads, and direct tool operation | context | medium | `gpt-6-sol` |
|
|
186
|
+
| Instructed implementation | balanced | low | `gpt-6.1-sol` |
|
|
187
|
+
| Exploration, large-context reads, and direct tool operation | context | medium | `gpt-6.1-sol` |
|
|
188
188
|
| Planning, review, debugging, and focused judgment | deep | max | `gpt-6-astra` |
|
|
189
189
|
|
|
190
190
|
With Jev mode on, Jev picks the tier for every spawn, every gated parent edit,
|
|
@@ -8,6 +8,7 @@ import { desktopBridgeStatusV3 } from '../codex-lb/desktop-controller-v3.js';
|
|
|
8
8
|
import { bridgeClientUrl } from '../codex-lb/desktop-controller-v3/shared.js';
|
|
9
9
|
import { runProcess } from '../fsx.js';
|
|
10
10
|
import { createResponsesTransport } from './responses-transport.js';
|
|
11
|
+
import { latestModelForTier } from '../subagents/model-tiers.js';
|
|
11
12
|
const USAGE = 'sks agent-bridge async --prompt "task" [--tools status,stats] [--json]';
|
|
12
13
|
const MAX_PROMPT_BYTES = 16 * 1024;
|
|
13
14
|
export function redactAsyncToolOutput(stdout) {
|
|
@@ -55,7 +56,7 @@ export function parseAsyncCommandArgs(args) {
|
|
|
55
56
|
export async function agentBridgeAsyncCommand(args) {
|
|
56
57
|
const json = args.includes('--json');
|
|
57
58
|
if (args.includes('--help')) {
|
|
58
|
-
const help = { schema: 'sks.async-tool-run.v1', ok: true, status: 'help', usage: USAGE, model: '
|
|
59
|
+
const help = { schema: 'sks.async-tool-run.v1', ok: true, status: 'help', usage: USAGE, model: latestModelForTier('deep'), provider: 'codex-lb', tools: 'Explicitly selected R0 remote-readable SKS command contracts only.' };
|
|
59
60
|
console.log(json ? JSON.stringify(help, null, 2) : USAGE);
|
|
60
61
|
return help;
|
|
61
62
|
}
|
|
@@ -63,9 +64,10 @@ export async function agentBridgeAsyncCommand(args) {
|
|
|
63
64
|
const parsed = parseAsyncCommandArgs(args);
|
|
64
65
|
const home = homedir();
|
|
65
66
|
const status = await desktopBridgeStatusV3({ home });
|
|
66
|
-
const
|
|
67
|
+
const deepModel = latestModelForTier('deep');
|
|
68
|
+
const model = `codex-lb:${deepModel}`;
|
|
67
69
|
const route = status.routing.policy?.model_routes[model];
|
|
68
|
-
if (!status.service.running || !status.service.loopback_origin || route?.provider_id !== 'codex-lb' || route.upstream_model !==
|
|
70
|
+
if (!status.service.running || !status.service.loopback_origin || route?.provider_id !== 'codex-lb' || route.upstream_model !== deepModel) {
|
|
69
71
|
throw new Error('async_astra_bridge_route_unavailable');
|
|
70
72
|
}
|
|
71
73
|
const endpoint = await bridgeClientUrl(status.service.loopback_origin, '/backend-api/codex/responses', { home });
|
|
@@ -2,9 +2,6 @@ import { codexModelEffortCapability } from '../codex-control/codex-model-capabil
|
|
|
2
2
|
import { managedOfficialSubagentRoleByName } from '../managed-assets/managed-assets-manifest.js';
|
|
3
3
|
import { decideSubagentModel, subagentModelProfile } from '../subagents/model-policy.js';
|
|
4
4
|
import { MODEL_TIERS, resolveLatestModelTiers } from '../subagents/model-tiers.js';
|
|
5
|
-
export function decideAgentEffort(input = {}) {
|
|
6
|
-
return decideOfficialSubagentModel(input);
|
|
7
|
-
}
|
|
8
5
|
export function decideOfficialSubagentModel(input = {}) {
|
|
9
6
|
const persona = input.persona || {};
|
|
10
7
|
const prompt = String(input.prompt || '');
|
|
@@ -46,7 +43,7 @@ export function decideOfficialSubagentModel(input = {}) {
|
|
|
46
43
|
downshift_triggers: [
|
|
47
44
|
'instructed UI, logic, backend, or native implementation selects the balanced tier',
|
|
48
45
|
'long-context, Browser/Chrome, Computer Use, image-generation, or large search selects the context tier',
|
|
49
|
-
'tiny short-context mechanical search/typing/rename work selects the
|
|
46
|
+
'tiny short-context mechanical search/typing/rename work selects the fast tier'
|
|
50
47
|
]
|
|
51
48
|
};
|
|
52
49
|
}
|
|
@@ -100,7 +97,7 @@ export function decideOfficialSubagentModel(input = {}) {
|
|
|
100
97
|
downshift_triggers: [
|
|
101
98
|
'instructed UI, logic, backend, or native implementation selects the balanced tier',
|
|
102
99
|
'long-context, Browser/Chrome, Computer Use, or image-generation execution selects the context tier',
|
|
103
|
-
'tiny short-context mechanical work selects the
|
|
100
|
+
'tiny short-context mechanical work selects the fast tier'
|
|
104
101
|
]
|
|
105
102
|
};
|
|
106
103
|
}
|
|
@@ -125,7 +122,7 @@ export function buildAgentEffortPolicy(roster = {}) {
|
|
|
125
122
|
policy_version: 1,
|
|
126
123
|
dynamic: true,
|
|
127
124
|
service_tier: 'fast',
|
|
128
|
-
model_catalog_policy: '
|
|
125
|
+
model_catalog_policy: 'official_subagent_model_tiers',
|
|
129
126
|
model_constraint: [...new Set(MODEL_TIERS.map((tier) => latest.models[tier]))],
|
|
130
127
|
model_tiers: MODEL_TIERS.map((tier) => `${tier}:${latest.models[tier]}-${latest.efforts[tier]}`),
|
|
131
128
|
allowed_efforts: ['low', 'medium', 'high', 'max'],
|
|
@@ -93,7 +93,6 @@ export async function runNativeAgentOrchestrator(opts = {}) {
|
|
|
93
93
|
concurrency: opts.concurrency,
|
|
94
94
|
prompt,
|
|
95
95
|
maxAgentCount,
|
|
96
|
-
officialSubagentPolicy,
|
|
97
96
|
...(opts.readonly === undefined ? {} : { readonly: opts.readonly })
|
|
98
97
|
});
|
|
99
98
|
roster = applyFastModeToRoster(roster, fastModePolicy);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DEFAULT_AGENT_CONCURRENCY, DEFAULT_AGENT_COUNT, HARD_AGENT_CONCURRENCY, MAX_AGENT_COUNT, agentSessionId } from './agent-schema.js';
|
|
2
2
|
import { defaultAgentPersonas, validatePersonaUniqueness } from './agent-persona.js';
|
|
3
|
-
import { buildAgentEffortPolicy,
|
|
3
|
+
import { buildAgentEffortPolicy, decideOfficialSubagentModel } from './agent-effort-policy.js';
|
|
4
4
|
function resolveMaxAgentCount(value) {
|
|
5
5
|
const parsed = Number(value);
|
|
6
6
|
if (!Number.isFinite(parsed) || parsed < 1)
|
|
@@ -35,9 +35,7 @@ export function buildAgentRoster(opts = {}) {
|
|
|
35
35
|
if (!uniqueness.ok)
|
|
36
36
|
throw new Error('Invalid agent personas: ' + JSON.stringify(uniqueness));
|
|
37
37
|
const roster = personas.map((persona, index) => {
|
|
38
|
-
const effort = opts.
|
|
39
|
-
? decideOfficialSubagentModel({ persona, prompt: opts.prompt || '', agentId: persona.id, readonly: opts.readonly === true || persona.read_only })
|
|
40
|
-
: decideAgentEffort({ persona, prompt: opts.prompt || '', agentId: persona.id, readonly: opts.readonly === true || persona.read_only });
|
|
38
|
+
const effort = decideOfficialSubagentModel({ persona, prompt: opts.prompt || '', agentId: persona.id, readonly: opts.readonly === true || persona.read_only });
|
|
41
39
|
return {
|
|
42
40
|
id: persona.id,
|
|
43
41
|
session_id: agentSessionId(persona.id, index + 1),
|
|
@@ -8,7 +8,7 @@ import { runCodexTask } from '../codex-control/codex-control-plane.js';
|
|
|
8
8
|
import { CODEX_AGENT_WORKER_RESULT_SCHEMA_ID, codexAgentWorkerResultSchema } from '../codex-control/schemas/agent-worker-result.schema.js';
|
|
9
9
|
import { leanEngineeringCompactText, leanPolicyReference } from '../lean-engineering-policy.js';
|
|
10
10
|
import { readCodexLbModelCatalog, readLbHealth } from '../codex-lb/codex-lb-env.js';
|
|
11
|
-
import { categoryForWorkerRole,
|
|
11
|
+
import { categoryForWorkerRole, isNarutoTierModel, modelRouteReason, routeModel } from '../provider/model-router.js';
|
|
12
12
|
import { codexTimeoutClassForRoute } from '../codex-control/codex-reliability-shield.js';
|
|
13
13
|
import { decideSubagentModel } from '../subagents/model-policy.js';
|
|
14
14
|
import { latestTierModelSet } from '../subagents/model-tiers.js';
|
|
@@ -246,7 +246,7 @@ export async function resolveWorkerModelRouting(input, deps = {}) {
|
|
|
246
246
|
const explicitTierRaw = String(env.SKS_WORKER_SERVICE_TIER || env.SKS_SERVICE_TIER || '').trim();
|
|
247
247
|
const explicitReasoning = normalizeModelReasoning(explicitReasoningRaw);
|
|
248
248
|
const explicitTier = normalizeServiceTier(explicitTierRaw);
|
|
249
|
-
const explicitNarutoModelInvalid = narutoOnly && Boolean(explicitModel) && !
|
|
249
|
+
const explicitNarutoModelInvalid = narutoOnly && Boolean(explicitModel) && !isNarutoTierModel(explicitModel);
|
|
250
250
|
const explicitNarutoReasoningInvalid = narutoOnly && Boolean(explicitReasoningRaw) && !explicitReasoning;
|
|
251
251
|
const explicitNarutoTierInvalid = narutoOnly && Boolean(explicitTierRaw) && !explicitTier;
|
|
252
252
|
const currentModels = latestTierModelSet();
|
|
@@ -254,7 +254,7 @@ export async function resolveWorkerModelRouting(input, deps = {}) {
|
|
|
254
254
|
&& currentModels.has(String(input.agent?.routed_model || ''))
|
|
255
255
|
? String(input.agent?.routed_model)
|
|
256
256
|
: '';
|
|
257
|
-
const
|
|
257
|
+
const savedPreferenceEffort = savedPreferenceModel
|
|
258
258
|
? normalizeModelReasoning(input.agent?.routed_model_reasoning_effort)
|
|
259
259
|
: null;
|
|
260
260
|
const jevModel = !explicitModel && input.agent?.routed_model_policy === 'jev_sealed_routing'
|
|
@@ -277,14 +277,14 @@ export async function resolveWorkerModelRouting(input, deps = {}) {
|
|
|
277
277
|
narutoOnly: true,
|
|
278
278
|
taskText: taskKindText,
|
|
279
279
|
riskText,
|
|
280
|
-
reasoningEffort: jevEffort ||
|
|
280
|
+
reasoningEffort: jevEffort || savedPreferenceEffort || liveJevEffort,
|
|
281
281
|
availableModels: lbCatalog?.models || [],
|
|
282
282
|
availableModelEfforts: lbCatalog?.model_efforts || {},
|
|
283
283
|
...(selectedModel ? { model: selectedModel } : {})
|
|
284
284
|
})
|
|
285
285
|
: {
|
|
286
286
|
model: (explicitModel && currentModels.has(explicitModel) ? explicitModel : '') || savedPreferenceModel || liveJevModel || taskPolicy.model,
|
|
287
|
-
reasoning: explicitReasoning ||
|
|
287
|
+
reasoning: explicitReasoning || savedPreferenceEffort || liveJevEffort || taskPolicy.modelReasoningEffort,
|
|
288
288
|
serviceTier: explicitTier || input.fastModePolicy.service_tier || 'fast'
|
|
289
289
|
};
|
|
290
290
|
const blockers = [
|
|
@@ -14,9 +14,6 @@ export function codexHomePath(input = {}) {
|
|
|
14
14
|
export function codexUserConfigPath(input = {}) {
|
|
15
15
|
return path.join(codexHomePath(input), 'config.toml');
|
|
16
16
|
}
|
|
17
|
-
export function defaultOpenCodexCatalogPath(input = {}) {
|
|
18
|
-
return path.join(codexHomePath(input), 'opencodex-catalog.json');
|
|
19
|
-
}
|
|
20
17
|
export async function readConfiguredCodexModelRoutingContext(input = {}) {
|
|
21
18
|
const configPath = input.configPath || codexUserConfigPath(input);
|
|
22
19
|
let config = '';
|
|
@@ -7,7 +7,6 @@ export const SKS_CODEX_CAPABILITY_IDS = [
|
|
|
7
7
|
'agents_max_concurrent_threads_per_session',
|
|
8
8
|
'thread_list_search_read',
|
|
9
9
|
'mcp_startup_tool_timeouts',
|
|
10
|
-
'gpt56_terra_luna_sol_routing',
|
|
11
10
|
'exec_mcp_transient_recovery',
|
|
12
11
|
'rollout_token_budget'
|
|
13
12
|
];
|
|
@@ -46,13 +45,6 @@ export function buildCodexCapabilityMatrix(input = {}) {
|
|
|
46
45
|
sources: [help, config],
|
|
47
46
|
forceAvailable: true
|
|
48
47
|
});
|
|
49
|
-
const gpt56 = resolveBooleanCapability({
|
|
50
|
-
id: 'gpt56_terra_luna_sol_routing',
|
|
51
|
-
policy: policies.gpt56TerraLunaSolRouting || 'delegate',
|
|
52
|
-
markers: [/gpt-5\.6-(?:luna|terra|sol)/],
|
|
53
|
-
sources: [help, config],
|
|
54
|
-
forceAvailable: Boolean(detected)
|
|
55
|
-
});
|
|
56
48
|
const execMcp = resolveBooleanCapability({
|
|
57
49
|
id: 'exec_mcp_transient_recovery',
|
|
58
50
|
policy: policies.execMcpTransientRecovery || 'probe',
|
|
@@ -75,7 +67,6 @@ export function buildCodexCapabilityMatrix(input = {}) {
|
|
|
75
67
|
agents_max_concurrent_threads_per_session: agentsConcurrency,
|
|
76
68
|
thread_list_search_read: threadList,
|
|
77
69
|
mcp_startup_tool_timeouts: mcpTimeouts,
|
|
78
|
-
gpt56_terra_luna_sol_routing: gpt56,
|
|
79
70
|
exec_mcp_transient_recovery: execMcp,
|
|
80
71
|
rollout_token_budget: rollout
|
|
81
72
|
},
|
|
@@ -26,7 +26,6 @@ export const CURRENT_CODEX_RUNTIME_CONTRACT = {
|
|
|
26
26
|
remoteNativeEnvironment: 'probe',
|
|
27
27
|
rolloutTokenBudget: 'probe',
|
|
28
28
|
mcpStartupToolTimeouts: 'wrap',
|
|
29
|
-
gpt56TerraLunaSolRouting: 'delegate',
|
|
30
29
|
mcpPaginatedDiscovery: 'wrap',
|
|
31
30
|
portableAgentPlugins: 'delegate',
|
|
32
31
|
automaticApprovalReview: 'delegate'
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { mapCodexSdkSandboxPolicy } from './codex-sdk-sandbox-policy.js';
|
|
2
|
+
import { parseGptModelId } from '../subagents/model-tiers.js';
|
|
2
3
|
export function buildCodexSdkConfig(input) {
|
|
3
4
|
const model = String(input.model || process.env.SKS_CODEX_MODEL || process.env.CODEX_MODEL || '').trim();
|
|
4
5
|
const serviceTier = String(input.serviceTier || process.env.SKS_SERVICE_TIER || 'fast');
|
|
@@ -26,7 +27,7 @@ export function buildCodexSdkConfig(input) {
|
|
|
26
27
|
return config;
|
|
27
28
|
}
|
|
28
29
|
export function normalizeAstraSdkEffort(model, effort) {
|
|
29
|
-
return model.trim().toLowerCase() === '
|
|
30
|
+
return parseGptModelId(model.trim().toLowerCase())?.family === 'astra' && ['none', 'minimal'].includes(effort.trim().toLowerCase())
|
|
30
31
|
? 'low' : effort;
|
|
31
32
|
}
|
|
32
33
|
export function buildCodexExecutionPolicy(input) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { buildBridgeRouteIndex, sha256Stable } from '../route-index.js';
|
|
2
2
|
import { COMBINED_BRIDGE_CATALOG_SCHEMA } from './contracts.js';
|
|
3
3
|
import { normalizeProviderCatalog, providerCatalogStatus, routeProviderState } from './normalize.js';
|
|
4
|
+
import { pinCatalogToLatestGenerations } from './latest-generation.js';
|
|
4
5
|
import { compareModels, unique } from './shared.js';
|
|
5
6
|
import { applyBridgeModelSelection, availableModelRows, emptyBridgeModelSelection } from './model-selection.js';
|
|
6
7
|
export function buildCombinedBridgeCatalog(registry, options) {
|
|
@@ -10,8 +11,7 @@ export function buildCombinedBridgeCatalog(registry, options) {
|
|
|
10
11
|
openrouter: normalizeProviderCatalog(options.catalogs.openrouter)
|
|
11
12
|
};
|
|
12
13
|
const selection = options.selection || emptyBridgeModelSelection(createdAt);
|
|
13
|
-
const allModels = [...normalized['codex-lb'].models, ...normalized.openrouter.models]
|
|
14
|
-
.sort(compareModels);
|
|
14
|
+
const allModels = pinCatalogToLatestGenerations([...normalized['codex-lb'].models, ...normalized.openrouter.models].sort(compareModels));
|
|
15
15
|
const availableOpenRouterModels = availableModelRows(allModels, selection);
|
|
16
16
|
const models = options.selection ? applyBridgeModelSelection(allModels, selection) : allModels;
|
|
17
17
|
const routeBuild = buildBridgeRouteIndex({
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { compareModelVersions, parseGptModelId } from '../../subagents/model-tiers.js';
|
|
2
|
+
function isListed(model) {
|
|
3
|
+
const visibility = String(model.visibility || 'list').toLowerCase();
|
|
4
|
+
return visibility !== 'hide' && visibility !== 'hidden';
|
|
5
|
+
}
|
|
6
|
+
function escapeRegExp(text) {
|
|
7
|
+
return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
8
|
+
}
|
|
9
|
+
function displayNamePattern(displayName) {
|
|
10
|
+
const body = escapeRegExp(displayName.trim()).replace(/\\?-|\s+/g, '[-\\s]');
|
|
11
|
+
return new RegExp(`(?<![\\w-])${body}(?![\\w-])`, 'gi');
|
|
12
|
+
}
|
|
13
|
+
export function pinCatalogToLatestGenerations(models) {
|
|
14
|
+
const newest = new Map();
|
|
15
|
+
for (const model of models) {
|
|
16
|
+
const id = parseGptModelId(model.public_id);
|
|
17
|
+
if (!id || !isListed(model))
|
|
18
|
+
continue;
|
|
19
|
+
const best = newest.get(id.family);
|
|
20
|
+
if (!best || compareModelVersions(id.version, parseGptModelId(best.public_id).version) > 0)
|
|
21
|
+
newest.set(id.family, model);
|
|
22
|
+
}
|
|
23
|
+
const byId = new Map(models.map((model) => [model.public_id, model]));
|
|
24
|
+
return models.map((model) => {
|
|
25
|
+
const id = parseGptModelId(model.public_id);
|
|
26
|
+
let next = model;
|
|
27
|
+
if (id && isListed(model)) {
|
|
28
|
+
const best = newest.get(id.family);
|
|
29
|
+
if (best && compareModelVersions(parseGptModelId(best.public_id).version, id.version) > 0)
|
|
30
|
+
next = { ...next, visibility: 'hide' };
|
|
31
|
+
}
|
|
32
|
+
const upgrade = model.upgrade;
|
|
33
|
+
const target = upgrade && typeof upgrade === 'object' ? String(upgrade.model || '') : '';
|
|
34
|
+
const targetId = parseGptModelId(target);
|
|
35
|
+
const replacement = targetId ? newest.get(targetId.family) : undefined;
|
|
36
|
+
if (targetId && replacement && replacement.public_id !== target
|
|
37
|
+
&& compareModelVersions(parseGptModelId(replacement.public_id).version, targetId.version) > 0) {
|
|
38
|
+
const old = byId.get(target);
|
|
39
|
+
const markdown = upgrade.migration_markdown;
|
|
40
|
+
next = {
|
|
41
|
+
...next,
|
|
42
|
+
upgrade: {
|
|
43
|
+
...upgrade,
|
|
44
|
+
model: replacement.public_id,
|
|
45
|
+
...(typeof markdown === 'string' && old?.display_name
|
|
46
|
+
? { migration_markdown: markdown.replace(displayNamePattern(old.display_name), () => replacement.display_name) }
|
|
47
|
+
: {})
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
return next;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
@@ -5,6 +5,7 @@ import { runVoiceRealtimeProbeV3 } from '../probes/voice-realtime-probe.js';
|
|
|
5
5
|
import { runAuxiliarySurfacesProbeV3 } from '../probes/auxiliary-surfaces-probe.js';
|
|
6
6
|
import { capabilityProbeResultV3 } from '../probes/probe-evidence.js';
|
|
7
7
|
import { validateCapabilityDeepEvidenceV2 } from '../trusted-deep-evidence.js';
|
|
8
|
+
import { probeRouteForProvider } from './probe-route.js';
|
|
8
9
|
import { bridgeClientUrl, providerCode, safeCode, timeoutMs, unique } from './shared.js';
|
|
9
10
|
export function textResponsePayloadValid(contentType, text) {
|
|
10
11
|
if (/text\/event-stream/i.test(contentType || '')) {
|
|
@@ -40,9 +41,7 @@ export function textResponsePayloadValid(contentType, text) {
|
|
|
40
41
|
return payload !== null && typeof payload === 'object';
|
|
41
42
|
}
|
|
42
43
|
export async function probeProviderText(core, providerId, loopbackOrigin, context, options) {
|
|
43
|
-
const route = core.policy
|
|
44
|
-
? Object.entries(core.policy.model_routes).find(([, target]) => target.provider_id === providerId)
|
|
45
|
-
: null;
|
|
44
|
+
const route = probeRouteForProvider(core.policy, providerId);
|
|
46
45
|
if (!loopbackOrigin || !route) {
|
|
47
46
|
return capabilityProbeResultV3({
|
|
48
47
|
...context,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { capabilityProbeResultV3 } from '../probes/probe-evidence.js';
|
|
2
|
+
import { probeRouteForProvider } from './probe-route.js';
|
|
2
3
|
import { activeProviderIds, providerCode } from './shared.js';
|
|
3
4
|
export function nativeIdentityProbe(core, context) {
|
|
4
5
|
const oauth = core.auth.mode === 'chatgpt_oauth' || core.auth.mode === 'mixed';
|
|
@@ -123,9 +124,7 @@ export function providerAuthProbe(core, providerId, context) {
|
|
|
123
124
|
});
|
|
124
125
|
}
|
|
125
126
|
export function providerModelRouteProbe(core, providerId, context, liveText = null) {
|
|
126
|
-
const route = core.policy
|
|
127
|
-
? Object.entries(core.policy.model_routes).find(([, target]) => target.provider_id === providerId)
|
|
128
|
-
: null;
|
|
127
|
+
const route = probeRouteForProvider(core.policy, providerId);
|
|
129
128
|
const verified = Boolean(route && core.catalogSync.providers[providerId].state === 'verified');
|
|
130
129
|
const liveRouteProven = Boolean(verified && route && liveText
|
|
131
130
|
&& liveText.capability === 'text_responses'
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { compareModelVersions, parseGptModelId } from '../../subagents/model-tiers.js';
|
|
2
|
+
const FAMILY_ORDER = ['sol', 'astra', 'luna', 'terra'];
|
|
3
|
+
function familyRank(family) {
|
|
4
|
+
const index = FAMILY_ORDER.indexOf(family);
|
|
5
|
+
return index === -1 ? FAMILY_ORDER.length : index;
|
|
6
|
+
}
|
|
7
|
+
export function probeRouteForProvider(policy, providerId) {
|
|
8
|
+
if (!policy)
|
|
9
|
+
return null;
|
|
10
|
+
const routes = Object.entries(policy.model_routes).filter(([, target]) => target.provider_id === providerId);
|
|
11
|
+
let best = null;
|
|
12
|
+
for (const entry of routes) {
|
|
13
|
+
const id = parseGptModelId(entry[0]);
|
|
14
|
+
if (!id)
|
|
15
|
+
continue;
|
|
16
|
+
if (!best
|
|
17
|
+
|| compareModelVersions(id.version, best.version) > 0
|
|
18
|
+
|| (compareModelVersions(id.version, best.version) === 0 && familyRank(id.family) < familyRank(best.family))) {
|
|
19
|
+
best = { entry, version: id.version, family: id.family };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return best?.entry ?? routes[0] ?? null;
|
|
23
|
+
}
|
|
@@ -5,12 +5,3 @@ function copyArgs(args = []) {
|
|
|
5
5
|
export function preserveCodexModelArgs(args = []) {
|
|
6
6
|
return copyArgs(args);
|
|
7
7
|
}
|
|
8
|
-
export function forceRequiredCodexModelArgs(args = []) {
|
|
9
|
-
return preserveCodexModelArgs(args);
|
|
10
|
-
}
|
|
11
|
-
export function forceRequiredCodexModelConfigArgs(args = []) {
|
|
12
|
-
return preserveCodexModelArgs(args);
|
|
13
|
-
}
|
|
14
|
-
export function isForbiddenCodexModel(_value = '') {
|
|
15
|
-
return false;
|
|
16
|
-
}
|
|
@@ -740,8 +740,8 @@ function blockGlmOverride(json) {
|
|
|
740
740
|
schema: NARUTO_RESULT_SCHEMA,
|
|
741
741
|
ok: false,
|
|
742
742
|
status: 'blocked',
|
|
743
|
-
reason: '
|
|
744
|
-
blockers: ['
|
|
743
|
+
reason: 'retired_glm_naruto_flag:--glm',
|
|
744
|
+
blockers: ['retired_glm_naruto_flag:--glm'],
|
|
745
745
|
hint: 'Use normal sks naruto for the official Codex subagent workflow. OpenRouter models are selected in SKS Center Providers via Use OpenRouter.'
|
|
746
746
|
};
|
|
747
747
|
process.exitCode = 1;
|
|
@@ -3,6 +3,7 @@ import os from 'node:os';
|
|
|
3
3
|
import { exists, nowIso, readText, writeJsonAtomic } from '../fsx.js';
|
|
4
4
|
import { isUnmanagedProjectCodexConfig, writeCodexConfigGuarded } from '../codex/codex-config-guard.js';
|
|
5
5
|
import { escapeRegExp } from '../text/regex.js';
|
|
6
|
+
import { moveStaleSubagentDefault } from './stale-subagent-default.js';
|
|
6
7
|
export const DOCTOR_CODEX_STARTUP_REPAIR_SCHEMA = 'sks.doctor-codex-startup-repair.v1';
|
|
7
8
|
export async function runDoctorCodexStartupRepair(input) {
|
|
8
9
|
const root = path.resolve(input.root || process.cwd());
|
|
@@ -103,6 +104,13 @@ async function inspectOrRepairConfig(root, candidate, fix, nodeReplCommandCandid
|
|
|
103
104
|
warnings.push(...nodeReplRepair.warnings);
|
|
104
105
|
staleMcpBlocksRemoved.push(...nodeReplRepair.removed);
|
|
105
106
|
mcpBlocksRepaired.push(...nodeReplRepair.repaired);
|
|
107
|
+
if (candidate.scope === 'global') {
|
|
108
|
+
const moved = moveStaleSubagentDefault(next);
|
|
109
|
+
if (fix)
|
|
110
|
+
next = moved.text;
|
|
111
|
+
if (moved.from)
|
|
112
|
+
warnings.push(`default_subagent_model_${fix ? 'moved_to_latest' : 'not_latest'}:${moved.from}->${moved.to}`);
|
|
113
|
+
}
|
|
106
114
|
for (const server of ['supabase_sauron']) {
|
|
107
115
|
if (tomlBlock(next, `mcp_servers.${server}`))
|
|
108
116
|
optionalMcpBlocksIgnored.push(server);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { catalogIsAuthoritative, latestModelForTier, supersededByNewerSameFamily } from '../subagents/model-tiers.js';
|
|
2
|
+
const ANY_TABLE = /^\s*\[/;
|
|
3
|
+
const AGENTS_TABLE = /^\s*\[agents\]\s*(?:#.*)?$/;
|
|
4
|
+
const DEFAULT_LINE = /^(\s*default_subagent_model\s*=\s*")([^"]*)("\s*(?:#[^\r\n]*)?\s*)$/;
|
|
5
|
+
export function moveStaleSubagentDefault(text) {
|
|
6
|
+
const unchanged = { text, from: null, to: null };
|
|
7
|
+
if (!catalogIsAuthoritative())
|
|
8
|
+
return unchanged;
|
|
9
|
+
const lines = text.split('\n');
|
|
10
|
+
let inAgents = false;
|
|
11
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
12
|
+
const line = lines[index] || '';
|
|
13
|
+
if (ANY_TABLE.test(line)) {
|
|
14
|
+
inAgents = AGENTS_TABLE.test(line);
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
if (!inAgents)
|
|
18
|
+
continue;
|
|
19
|
+
const match = DEFAULT_LINE.exec(line);
|
|
20
|
+
if (!match)
|
|
21
|
+
continue;
|
|
22
|
+
const current = String(match[2] || '');
|
|
23
|
+
if (!supersededByNewerSameFamily(current))
|
|
24
|
+
return unchanged;
|
|
25
|
+
const latest = latestModelForTier('deep');
|
|
26
|
+
lines[index] = `${match[1]}${latest}${match[3]}`;
|
|
27
|
+
return { text: lines.join('\n'), from: current, to: latest };
|
|
28
|
+
}
|
|
29
|
+
return unchanged;
|
|
30
|
+
}
|
|
@@ -349,7 +349,7 @@ export function formatHarnessConflictReport(scan, opts = {}) {
|
|
|
349
349
|
}
|
|
350
350
|
export function llmHarnessCleanupPrompt(scan) {
|
|
351
351
|
const paths = (scan?.conflicts || []).map((x) => `- ${x.scope}: ${x.path} (${x.reason})`).join('\n') || '- No paths supplied. Re-run `sks doctor --json` first.';
|
|
352
|
-
return `Use
|
|
352
|
+
return `Use the model currently selected in Codex with reasoning effort high.
|
|
353
353
|
|
|
354
354
|
Goal: completely remove the conflicting Codex harnesses before installing Sneakoscope Codex.
|
|
355
355
|
|