sneakoscope 10.3.2 → 10.3.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 +22 -12
- package/config/skills-hash-ledger.v1.json +7 -1
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/dist/commands/doctor.js +2 -2
- package/dist/config/skills-manifest.json +13 -7
- package/dist/core/agents/agent-effort-policy.js +15 -13
- package/dist/core/agents/native-worker-backend-router.js +13 -8
- package/dist/core/codex-hooks/codex-hook-managed-install.js +56 -2
- package/dist/core/codex-lb/desktop-bridge-migration/retired-runtime-cleanup.js +1 -0
- package/dist/core/codex-native/core-skill-manifest.js +4 -4
- package/dist/core/decisions/cli.js +9 -2
- package/dist/core/decisions/config.js +7 -0
- package/dist/core/decisions/integration.js +54 -12
- package/dist/core/decisions/policy.js +27 -4
- package/dist/core/decisions/questions.js +39 -9
- package/dist/core/decisions/routing.js +15 -10
- package/dist/core/decisions/types.js +11 -25
- package/dist/core/doctor/current-project-guidance.js +38 -1
- package/dist/core/doctor/skill-legacy-surface.js +2 -1
- package/dist/core/hooks-runtime/hook-context.js +1 -1
- package/dist/core/hooks-runtime/jev-spawn-routing.js +21 -2
- package/dist/core/hooks-runtime/managed-guidance-preflight.js +30 -0
- package/dist/core/hooks-runtime/official-subagent-lifecycle.js +3 -3
- package/dist/core/hooks-runtime/parent-orchestration-gate.js +372 -0
- package/dist/core/hooks-runtime/subagent-context.js +13 -3
- package/dist/core/hooks-runtime/subagent-spawn-policy.js +5 -10
- package/dist/core/hooks-runtime.js +46 -8
- package/dist/core/init/skills/inventory.js +5 -1
- package/dist/core/init/skills.js +4 -4
- package/dist/core/init.js +39 -7
- package/dist/core/managed-assets/managed-assets-manifest.js +17 -17
- package/dist/core/pipeline-internals/runtime-core.js +2 -2
- package/dist/core/provider/model-router.js +8 -5
- package/dist/core/recallpulse/policy.js +2 -2
- package/dist/core/recallpulse.js +3 -3
- package/dist/core/release/gate-affected-globs.js +0 -1
- package/dist/core/research/mock-result.js +2 -2
- package/dist/core/research/research-adversarial-review.js +7 -7
- package/dist/core/research/research-claim-synthesizer.js +3 -3
- package/dist/core/research/research-falsification-runner.js +3 -3
- package/dist/core/research/research-super-search.js +5 -2
- package/dist/core/research/research-synthesis-writer.js +2 -2
- package/dist/core/research.js +5 -5
- package/dist/core/routes/dollar-manifest-lite.js +1 -1
- package/dist/core/routes.js +10 -10
- package/dist/core/runtime/task-profile.js +9 -5
- package/dist/core/subagents/model-policy.js +27 -45
- package/dist/core/subagents/model-tiers.js +153 -0
- package/dist/core/subagents/naruto-command-args.js +3 -3
- package/dist/core/subagents/naruto-help-contract.js +18 -13
- package/dist/core/subagents/naruto-host-credentials.js +8 -13
- package/dist/core/subagents/official-subagent-config.js +11 -7
- package/dist/core/subagents/official-subagent-preparation.js +12 -8
- package/dist/core/subagents/official-subagent-prompt.js +33 -33
- package/dist/core/subagents/official-subagent-runner.js +3 -3
- package/dist/core/subagents/role-model-preferences.js +26 -21
- package/dist/core/update/managed-permission-repair.js +462 -0
- package/dist/core/update/update-migration-state/retired-local-decision.js +32 -2
- package/dist/core/update/update-migration-state/simple-stages.js +42 -5
- package/dist/core/update/update-migration-state.js +63 -1
- package/dist/core/update-check.js +35 -8
- package/dist/core/version.js +1 -1
- package/dist/scripts/codex-native-agent-role-content-check.js +10 -5
- package/dist/scripts/codex-native-gate-lib.js +3 -1
- package/dist/scripts/current-surface-update-e2e-check.js +1 -0
- package/dist/scripts/mutation-callsite-coverage-check.js +2 -2
- package/dist/scripts/release-affected-selector-check.js +1 -2
- package/dist/scripts/typed-routing-gate-lib.js +3 -1
- package/package.json +1 -1
- package/release-gates.v2.json +2 -6
package/dist/core/routes.js
CHANGED
|
@@ -6,7 +6,7 @@ import { CODEX_APP_IMAGE_GENERATION_DOC_URL, CODEX_COMPUTER_USE_ONLY_POLICY, COD
|
|
|
6
6
|
import { getdesignReferencePolicyText, imageUxReviewPipelinePolicyText } from './routes/design-policy.js';
|
|
7
7
|
import { PPT_PIPELINE_SKILL_ALLOWLIST, pptPipelineAllowlistPolicyText } from './routes/ppt-policy.js';
|
|
8
8
|
import { normalizeDollarSkillName, prefixKnownSksDollarReferences, sksPrefixedDollarCommand, sksPrefixedSkillName, unprefixedSksSkillName } from './routes/dollar-prefix.js';
|
|
9
|
-
import { classifyTaskProfile, isTaskProfile, looksLikeDatabaseWorkRequest } from './runtime/task-profile.js';
|
|
9
|
+
import { classifyTaskProfile, IMPLEMENTATION_VERB_RE, isTaskProfile, looksLikeDatabaseWorkRequest } from './runtime/task-profile.js';
|
|
10
10
|
import { legacyCoreSkillNames } from './codex-native/core-skill-manifest.js';
|
|
11
11
|
export * from './routes/constants.js';
|
|
12
12
|
export * from './routes/design-policy.js';
|
|
@@ -121,9 +121,6 @@ export function noUnrequestedFallbackCodePolicyText() {
|
|
|
121
121
|
export function outcomeRubricPolicyText() {
|
|
122
122
|
return 'Outcome rubric: apply the Core Engineering Directive, then use Proof Field, route-gate, reflection, and Honest Mode evidence to judge goal fit, touched surface, verification, and escalation.';
|
|
123
123
|
}
|
|
124
|
-
export function speedLanePolicyText() {
|
|
125
|
-
return 'Proof Field speed lane policy: after the intended write scope is known, run or mentally apply `sks proof-field scan --intent "<goal>" --changed <files>`. Fast lanes keep the parent-owned minimal patch, listed verification, TriWiki validate, and Honest Mode; DB, security, visual-forensic, unknown surface, broad changes, failed verification, or unsupported claims fail closed to the normal Naruto/Honest path.';
|
|
126
|
-
}
|
|
127
124
|
export function hasFromChatImgSignal(prompt = '') {
|
|
128
125
|
return /(?:^|\s)\$?(?:sks-)?from-chat-img(?:\s|:|$)/i.test(String(prompt || ''));
|
|
129
126
|
}
|
|
@@ -233,7 +230,7 @@ export const ROUTES = [
|
|
|
233
230
|
command: '$Naruto',
|
|
234
231
|
mode: 'NARUTO',
|
|
235
232
|
route: 'Codex official subagent workflow',
|
|
236
|
-
description: '$Naruto runs
|
|
233
|
+
description: '$Naruto runs implementation work through Codex official subagents. The parent orchestrates: it owns decomposition, integration, and scoped verification, spawns a child per disjoint slice, and does not implement slices itself; standalone launches default to the latest deep-tier model. Each child runs the newest model of the tier its work needs; Jev mode picks the tier on spawn, and a stored role preference wins. Honor explicit counts and measured host limits, and reuse returned capacity.',
|
|
237
234
|
requiredSkills: ['naruto', 'pipeline-runner', 'prompt-pipeline', 'honest-mode'],
|
|
238
235
|
dollarAliases: ['$Work'],
|
|
239
236
|
appSkillAliases: ['work', 'from-chat-img'],
|
|
@@ -699,7 +696,7 @@ export const COMMAND_CATALOG = [
|
|
|
699
696
|
{ name: 'wiki', usage: 'sks wiki coords|pack|refresh|publish|rebuild-index|validate|validate-shared|wrongness ...', description: 'Build, refresh, publish shared shards, rebuild ignored indexes, validate, and attach wrongness-memory context to RGBA/trig LLM Wiki packs with attention.use_first and attention.hydrate_first for compact recall plus source hydration.' },
|
|
700
697
|
{ name: 'memory', usage: 'sks memory build [--json] | sks memory gc [--dry-run]', description: 'Project TriWiki context-pack memory into managed AGENTS.md blocks or run bounded memory cleanup.' },
|
|
701
698
|
{ name: 'hproof', usage: 'sks hproof check [mission-id|latest]', description: 'Evaluate the H-Proof done gate for a mission.' },
|
|
702
|
-
{ name: 'naruto', usage: 'sks naruto run \"task\" [--agents N] [--max-threads N] [--trusted-project] [--json] | sks naruto status|subagents|proof [latest|M-...] [--json] | sks naruto parent-summary --mission M-... --stdin [--json]', description: 'Run or inspect the Codex official subagent workflow
|
|
699
|
+
{ name: 'naruto', usage: 'sks naruto run \"task\" [--agents N] [--max-threads N] [--trusted-project] [--json] | sks naruto status|subagents|proof [latest|M-...] [--json] | sks naruto parent-summary --mission M-... --stdin [--json]', description: 'Run or inspect the Codex official subagent workflow: an orchestrating parent (latest deep-tier standalone default), children on the newest model of their tier (Jev picks the tier on spawn when Jev mode is on), max_depth=1, and structured parent-thread completion evidence.' },
|
|
703
700
|
{ name: 'reasoning', usage: 'sks reasoning ["prompt"] [--json]', description: 'Show SKS temporary reasoning-effort routing: medium for simple tasks, high for logic, xhigh for research.' },
|
|
704
701
|
{ name: 'gx', usage: 'sks gx init|render|validate|drift|snapshot [name]', description: 'Create and verify deterministic SVG/HTML visual context cartridges.' },
|
|
705
702
|
{ name: 'profile', usage: 'sks profile show|set <model>', description: 'Inspect or set the current SKS model profile metadata.' },
|
|
@@ -1207,6 +1204,9 @@ export function narutoDecisionForRoute(route, prompt = '', profile = classifyTas
|
|
|
1207
1204
|
if (NARUTO_GATE_SPECIALIZED_PARALLEL_ROUTE_IDS.has(routeId)) {
|
|
1208
1205
|
return narutoRouteDecision('generic_naruto', routeId, profile, `specialized_route_default_parallel:${routeId}`, false);
|
|
1209
1206
|
}
|
|
1207
|
+
if (routeId === 'Naruto' && profile === 'answer') {
|
|
1208
|
+
return narutoRouteDecision('generic_naruto', routeId, profile, 'naruto_route_work_without_change_verb', false);
|
|
1209
|
+
}
|
|
1210
1210
|
if (profile === 'passthrough' || profile === 'answer' || profile === 'tiny-change') {
|
|
1211
1211
|
return narutoRouteDecision('none', routeId, profile, `task_profile_${profile}_bypass`, true);
|
|
1212
1212
|
}
|
|
@@ -1263,7 +1263,8 @@ export function reflectionRequiredForRoute(route) {
|
|
|
1263
1263
|
export function looksLikeCodeChangingWork(prompt = '') {
|
|
1264
1264
|
const text = String(prompt || '');
|
|
1265
1265
|
return /\b(implement|build|make|add|edit|modify|change|fix|refactor|simplify|optimi[sz]e|improve|rewrite|migrate|create|delete|remove|rename|update|patch)\b/i.test(text)
|
|
1266
|
-
|| /(코드|구현|개발|수정|변경|추가|삭제|제거|최적화|개선|단순화|정리|해결|고쳐|바꿔|리팩터|마이그레이션)/i.test(text)
|
|
1266
|
+
|| /(코드|구현|개발|수정|변경|추가|삭제|제거|최적화|개선|단순화|정리|해결|고쳐|바꿔|리팩터|마이그레이션)/i.test(text)
|
|
1267
|
+
|| IMPLEMENTATION_VERB_RE.test(text);
|
|
1267
1268
|
}
|
|
1268
1269
|
export function classifyPromptExecutionEffect(prompt = '') {
|
|
1269
1270
|
const text = String(prompt || '').trim();
|
|
@@ -1303,9 +1304,8 @@ export function subagentExecutionPolicyText(route, prompt = '') {
|
|
|
1303
1304
|
return 'Subagent policy: not required for this task profile. Keep the work parent-owned unless a later, concrete decomposition reveals independent slices.';
|
|
1304
1305
|
}
|
|
1305
1306
|
return [
|
|
1306
|
-
'Codex subagent workflow: required for
|
|
1307
|
-
'The parent
|
|
1308
|
-
'Delegate only genuinely independent slices. Use Astra Low for tiny short-context mechanical work and instructed ordinary implementation, Astra Max for review/debug/planning/analysis/architecture/integration/risk judgment, and Astra Medium for long-context or Computer Use, Browser/Chrome, and image-generation execution. Explicit Astra effort preferences, including High, remain supported.',
|
|
1307
|
+
'Codex subagent workflow: required. The parent orchestrates only: it decomposes the task into disjoint slices, spawns a child for each slice, waits, integrates, verifies, and writes the final answer. It does not implement slice work itself; the PreToolUse gate denies parent source edits before the first child starts and while children are running.',
|
|
1308
|
+
'The parent keeps its user-selected model, effort, and service tier. Every child runs the newest model of the tier its work needs: fast for mechanical work, balanced for instructed implementation, context for long-context, browser, Computer Use, and image work, and deep for planning, review, debugging, and risk judgment. When Jev mode is on, Jev picks each spawn\'s tier and SKS seals it; do not pick child models yourself. A stored user role-model preference wins in both modes.',
|
|
1309
1309
|
'Parallel writes require disjoint paths; serialize overlapping paths, prohibit nested delegation, avoid duplicate work, wait for all requested agent threads, and close completed threads after collecting results.',
|
|
1310
1310
|
'Completion evidence comes from official SubagentStart/SubagentStop events plus the parent integration summary, not process counts or PID evidence.'
|
|
1311
1311
|
].join(' ');
|
|
@@ -16,7 +16,11 @@ const GENERIC_DATABASE_DOMAIN_RE = /\bDB\b|디비/i;
|
|
|
16
16
|
const DATABASE_WORK_RE = /\b(?:apply|execute|run|fix|change|modify|migrate|audit|review|inspect|analy[sz]e|query|seed|backfill|optimi[sz]e|create|alter|drop|truncate|update|delete|repair)\b|적용|실행|수정|변경|검수|검토|점검|분석|조회|쿼리|시드|백필|최적화|생성|추가|삭제|복구|만들어/i;
|
|
17
17
|
const DATABASE_CONTROL_SURFACE_META_RE = /\bsks\s+db\b|\b(?:db|database|migrate|migrations?)\b[\s\S]{0,48}\b(?:command|cli|route|routing|parser|classifier|regex|help|usage|topic|docs?|documentation|constant|keyword|alias)\b|\b(?:command|cli|route|routing|parser|classifier|regex|help|usage|topic|docs?|documentation|constant|keyword|alias)\b[\s\S]{0,48}\b(?:db|database|migrate|migrations?)\b|(?:db|디비|데이터베이스|migration|migrate|마이그레이션)\s*(?:커맨드|명령|명령어|CLI|라우트|라우팅|파서|분류기|정규식|도움말|헬프|사용법|토픽|문서|상수|키워드|별칭)|(?:커맨드|명령|명령어|CLI|라우트|라우팅|파서|분류기|정규식|도움말|헬프|사용법|토픽|문서|상수|키워드|별칭)[\s\S]{0,32}(?:db|디비|데이터베이스|migration|migrate|마이그레이션)/i;
|
|
18
18
|
const PARALLEL_CUE_RE = /\b(parallel|subagents?|one agent per|fan out|independent slices?|naruto)\b|병렬|하위\s*에이전트|서브\s*에이전트|나루토|분담/i;
|
|
19
|
-
const
|
|
19
|
+
export const IMPLEMENTATION_VERB_RE = /\b(?:make|set\s+up|port|convert|wire(?:\s+up)?|hook\s+up|handle|integrate|connect|enable|disable|configure|upgrade|bump|replace|move|split|merge|extend|scaffold|introduce)\b|바꿔|바꾸|개발|붙여|연동|연결해|옮겨|설정해|세팅|셋업|넣어|합쳐|분리해|교체|도입|처리해|올려\s*(?:줘|주세요)|짜\s*(?:줘|주세요)/i;
|
|
20
|
+
const BASE_CHANGE_RE = /\b(fix|implement|implementation|change|edit|add|remove|delete|drop|modify|refactor|simplify|optimi[sz]e|improve|build|create|write|update|rename|rewrite|patch|apply|execute|repair|resolve|solve|publish|release|deploy|migrate)\b|\bwork\s+on\b|고쳐|고치|수정|변경|추가|삭제|제거|최적화|개선|단순화|정리|구현|리팩터|작성|생성|만들어|업데이트|적용|실행|해결|이름\s*변경|배포|출시|마이그레이션/i;
|
|
21
|
+
function hasChangeVerb(text) {
|
|
22
|
+
return BASE_CHANGE_RE.test(text) || IMPLEMENTATION_VERB_RE.test(text);
|
|
23
|
+
}
|
|
20
24
|
const BOUNDED_READ_WORK_RE = /\b(audit|review|inspect|analy[sz]e|diagnose|trace|map|verify|test|check|investigate|evaluate)\b|감사|검토|점검|분석|진단|추적|매핑|검증|테스트|조사|평가/i;
|
|
21
25
|
const TINY_CHANGE_RE = /\b(typo|copy|wording|label|spacing|whitespace|punctuation|spelling|one[-\s]?line|single[-\s]?(?:line|word)|rename only)\b|오타|문구|라벨|띄어쓰기|공백|맞춤법|구두점|한\s*줄|단어\s*하나|이름만\s*변경/i;
|
|
22
26
|
const NON_RUNTIME_TINY_SURFACE_RE = /\b(copy|wording|label|spacing|whitespace|punctuation|spelling|readme|docs?|documentation|comment)\b|문구|라벨|띄어쓰기|공백|맞춤법|구두점|문서|주석/i;
|
|
@@ -30,18 +34,18 @@ export function classifyTaskProfile(prompt) {
|
|
|
30
34
|
if (looksLikeExplanationQuestion(text))
|
|
31
35
|
return 'answer';
|
|
32
36
|
const databaseWork = looksLikeDatabaseWorkRequest(text);
|
|
33
|
-
const highRiskMutation = databaseWork || (
|
|
37
|
+
const highRiskMutation = databaseWork || (hasChangeVerb(text) && NON_DATABASE_HIGH_RISK_RE.test(text));
|
|
34
38
|
if (looksLikeTinyChange(text) && (!highRiskMutation || NON_RUNTIME_TINY_SURFACE_RE.test(text)))
|
|
35
39
|
return 'tiny-change';
|
|
36
40
|
if (highRiskMutation)
|
|
37
41
|
return 'high-risk';
|
|
38
|
-
if (PARALLEL_CUE_RE.test(text) &&
|
|
42
|
+
if (PARALLEL_CUE_RE.test(text) && hasChangeVerb(text))
|
|
39
43
|
return 'parallel-write';
|
|
40
44
|
if (PARALLEL_CUE_RE.test(text))
|
|
41
45
|
return 'parallel-read';
|
|
42
46
|
if (DATABASE_CONTROL_SURFACE_META_RE.test(text) && DATABASE_WORK_RE.test(text))
|
|
43
47
|
return 'bounded-work';
|
|
44
|
-
if (
|
|
48
|
+
if (hasChangeVerb(text))
|
|
45
49
|
return 'bounded-work';
|
|
46
50
|
if (BOUNDED_READ_WORK_RE.test(text))
|
|
47
51
|
return 'bounded-work';
|
|
@@ -84,7 +88,7 @@ function matchIndexes(text, pattern) {
|
|
|
84
88
|
.filter((index) => Number.isInteger(index));
|
|
85
89
|
}
|
|
86
90
|
function looksLikeTinyChange(text) {
|
|
87
|
-
return
|
|
91
|
+
return hasChangeVerb(text) && TINY_CHANGE_RE.test(text);
|
|
88
92
|
}
|
|
89
93
|
function looksLikeExplanationQuestion(text) {
|
|
90
94
|
return (EXPLANATION_QUESTION_RE.test(text) || EXPLANATION_REQUEST_RE.test(text))
|
|
@@ -1,44 +1,37 @@
|
|
|
1
|
+
import { latestModelForTier } from './model-tiers.js';
|
|
1
2
|
export const NARUTO_PARENT_MODEL = 'gpt-6-astra';
|
|
2
3
|
export const NARUTO_PARENT_EFFORT = 'max';
|
|
4
|
+
export function narutoParentModel() {
|
|
5
|
+
return latestModelForTier('deep');
|
|
6
|
+
}
|
|
3
7
|
export const ASTRA_SUBAGENT_MODEL = 'gpt-6-astra';
|
|
4
|
-
export const NARUTO_LUNA_MODEL = 'gpt-5.6-luna';
|
|
5
|
-
export const NARUTO_SOL_MODEL = 'gpt-5.6-sol';
|
|
6
|
-
export const NARUTO_TERRA_MODEL = 'gpt-5.6-terra';
|
|
7
|
-
export const LUNA_SUBAGENT_MODEL = ASTRA_SUBAGENT_MODEL;
|
|
8
|
-
export const TERRA_SUBAGENT_MODEL = ASTRA_SUBAGENT_MODEL;
|
|
9
|
-
export const SOL_SUBAGENT_MODEL = ASTRA_SUBAGENT_MODEL;
|
|
10
8
|
export const LUNA_SUBAGENT_EFFORT = 'low';
|
|
11
9
|
export const TERRA_SUBAGENT_EFFORT = 'medium';
|
|
12
10
|
export const DEFAULT_SUBAGENT_EFFORT = 'low';
|
|
13
11
|
export const SOL_MAX_SUBAGENT_EFFORT = 'max';
|
|
14
|
-
export const DEFAULT_SUBAGENT_MODEL = SOL_SUBAGENT_MODEL;
|
|
15
|
-
export const THINKING_SUBAGENT_MODEL = SOL_SUBAGENT_MODEL;
|
|
16
12
|
export const SUBAGENT_EFFORT = SOL_MAX_SUBAGENT_EFFORT;
|
|
13
|
+
export function thinkingSubagentModel() {
|
|
14
|
+
return latestModelForTier('deep');
|
|
15
|
+
}
|
|
16
|
+
export function defaultSubagentModel() {
|
|
17
|
+
return latestModelForTier('deep');
|
|
18
|
+
}
|
|
19
|
+
function tierProfile(policy, kind, tier, modelReasoningEffort) {
|
|
20
|
+
return Object.freeze({
|
|
21
|
+
policy,
|
|
22
|
+
kind,
|
|
23
|
+
tier,
|
|
24
|
+
get model() {
|
|
25
|
+
return latestModelForTier(tier);
|
|
26
|
+
},
|
|
27
|
+
modelReasoningEffort
|
|
28
|
+
});
|
|
29
|
+
}
|
|
17
30
|
export const SUBAGENT_MODEL_POLICIES = Object.freeze({
|
|
18
|
-
luna_max_mechanical:
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
modelReasoningEffort: LUNA_SUBAGENT_EFFORT
|
|
23
|
-
}),
|
|
24
|
-
sol_high_implementation: Object.freeze({
|
|
25
|
-
policy: 'sol_high_implementation',
|
|
26
|
-
kind: 'worker',
|
|
27
|
-
model: SOL_SUBAGENT_MODEL,
|
|
28
|
-
modelReasoningEffort: DEFAULT_SUBAGENT_EFFORT
|
|
29
|
-
}),
|
|
30
|
-
sol_max_judgment: Object.freeze({
|
|
31
|
-
policy: 'sol_max_judgment',
|
|
32
|
-
kind: 'expert',
|
|
33
|
-
model: SOL_SUBAGENT_MODEL,
|
|
34
|
-
modelReasoningEffort: SOL_MAX_SUBAGENT_EFFORT
|
|
35
|
-
}),
|
|
36
|
-
terra_max_context_tools: Object.freeze({
|
|
37
|
-
policy: 'terra_max_context_tools',
|
|
38
|
-
kind: 'worker',
|
|
39
|
-
model: TERRA_SUBAGENT_MODEL,
|
|
40
|
-
modelReasoningEffort: TERRA_SUBAGENT_EFFORT
|
|
41
|
-
})
|
|
31
|
+
luna_max_mechanical: tierProfile('luna_max_mechanical', 'worker', 'fast', LUNA_SUBAGENT_EFFORT),
|
|
32
|
+
sol_high_implementation: tierProfile('sol_high_implementation', 'worker', 'balanced', DEFAULT_SUBAGENT_EFFORT),
|
|
33
|
+
sol_max_judgment: tierProfile('sol_max_judgment', 'expert', 'deep', SOL_MAX_SUBAGENT_EFFORT),
|
|
34
|
+
terra_max_context_tools: tierProfile('terra_max_context_tools', 'worker', 'context', TERRA_SUBAGENT_EFFORT)
|
|
42
35
|
});
|
|
43
36
|
const JUDGMENT_TASK_RE = new RegExp([
|
|
44
37
|
'\\breview(?:er|ing)?\\b',
|
|
@@ -272,19 +265,8 @@ const IMPLEMENTATION_TASK_RE = new RegExp([
|
|
|
272
265
|
const CLEAR_IMPLEMENTATION_ACTION_RE = /(?:^|[.!?]\s*|\bphase\s*:\s*)\s*(?:implement|build|create|add|modify|fix|code|refactor)\b|(?:^|[.!?]\s*)\s*(?:구현|개발|추가|수정|고쳐|코딩|리팩터)/i;
|
|
273
266
|
const DOCUMENT_EXPLORATION_RE = /\b(?:read|scan|explore|compare|summarize|review)\b[^\n]{0,64}\b(?:docs?|documentation|manual|notes?|references?)\b|(?:문서|매뉴얼|노트|자료)[^\n]{0,32}(?:읽|탐색|조사|비교|정리|검토)/i;
|
|
274
267
|
export function subagentModelProfile(policy) {
|
|
275
|
-
|
|
276
|
-
}
|
|
277
|
-
export function narutoChildAssignment(policy) {
|
|
278
|
-
switch (policy) {
|
|
279
|
-
case 'luna_max_mechanical':
|
|
280
|
-
return { model: NARUTO_LUNA_MODEL, effort: 'low' };
|
|
281
|
-
case 'sol_high_implementation':
|
|
282
|
-
return { model: NARUTO_SOL_MODEL, effort: 'low' };
|
|
283
|
-
case 'terra_max_context_tools':
|
|
284
|
-
return { model: NARUTO_TERRA_MODEL, effort: 'medium' };
|
|
285
|
-
case 'sol_max_judgment':
|
|
286
|
-
return { model: ASTRA_SUBAGENT_MODEL, effort: 'max' };
|
|
287
|
-
}
|
|
268
|
+
const profile = SUBAGENT_MODEL_POLICIES[policy];
|
|
269
|
+
return { policy: profile.policy, kind: profile.kind, tier: profile.tier, model: profile.model, modelReasoningEffort: profile.modelReasoningEffort };
|
|
288
270
|
}
|
|
289
271
|
export function decideSubagentModel(input = {}) {
|
|
290
272
|
const text = [
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { codexHomePath } from '../codex-app/codex-model-catalog.js';
|
|
4
|
+
const MODELS_CACHE_FILENAME = 'models_cache.json';
|
|
5
|
+
function modelsCachePath(input) {
|
|
6
|
+
return path.join(codexHomePath(input), MODELS_CACHE_FILENAME);
|
|
7
|
+
}
|
|
8
|
+
export const MODEL_TIERS = Object.freeze(['fast', 'balanced', 'context', 'deep']);
|
|
9
|
+
export const MODEL_TIER_EFFORT = Object.freeze({
|
|
10
|
+
fast: 'low',
|
|
11
|
+
balanced: 'low',
|
|
12
|
+
context: 'medium',
|
|
13
|
+
deep: 'max'
|
|
14
|
+
});
|
|
15
|
+
export const MODEL_TIER_SUMMARY = Object.freeze({
|
|
16
|
+
fast: 'Fastest latest model. Mechanical edits, renames, formatting, and other one-step changes.',
|
|
17
|
+
balanced: 'Fast latest model. Simple coding whose result is already specified.',
|
|
18
|
+
context: 'Latest model at medium effort. Search, multi-file reading, broad exploration, and tool use.',
|
|
19
|
+
deep: 'Most capable latest model. Judgment, architecture, ambiguity, security, or high-stakes work.'
|
|
20
|
+
});
|
|
21
|
+
const TIER_FAMILIES = Object.freeze({
|
|
22
|
+
fast: ['luna'],
|
|
23
|
+
balanced: ['sol'],
|
|
24
|
+
context: ['terra', 'sol'],
|
|
25
|
+
deep: ['astra']
|
|
26
|
+
});
|
|
27
|
+
export const BUILTIN_LATEST_TIER_MODELS = Object.freeze({
|
|
28
|
+
fast: 'gpt-6-luna',
|
|
29
|
+
balanced: 'gpt-6-sol',
|
|
30
|
+
context: 'gpt-6-sol',
|
|
31
|
+
deep: 'gpt-6-astra'
|
|
32
|
+
});
|
|
33
|
+
const MODEL_ID_RE = /^gpt-(\d+(?:\.\d+)*)-([a-z]+)$/;
|
|
34
|
+
let memo = null;
|
|
35
|
+
export function resetLatestModelTierCache() {
|
|
36
|
+
memo = null;
|
|
37
|
+
}
|
|
38
|
+
export function resolveLatestModelTiers(input = {}) {
|
|
39
|
+
const file = modelsCachePath(input);
|
|
40
|
+
let stat = null;
|
|
41
|
+
try {
|
|
42
|
+
stat = fs.statSync(file);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
stat = null;
|
|
46
|
+
}
|
|
47
|
+
const key = stat ? `${file}:${stat.mtimeMs}:${stat.size}` : `${file}:absent`;
|
|
48
|
+
if (memo?.key === key)
|
|
49
|
+
return memo.value;
|
|
50
|
+
const rows = stat && stat.isFile() && stat.size <= 16 * 1024 * 1024 ? readCandidateRows(file) : [];
|
|
51
|
+
const value = resolveFromRows(rows);
|
|
52
|
+
memo = { key, value };
|
|
53
|
+
return value;
|
|
54
|
+
}
|
|
55
|
+
export function latestModelForTier(tier, input = {}) {
|
|
56
|
+
return resolveLatestModelTiers(input).models[tier];
|
|
57
|
+
}
|
|
58
|
+
export function latestTierModelSet(input = {}) {
|
|
59
|
+
return new Set(Object.values(resolveLatestModelTiers(input).models));
|
|
60
|
+
}
|
|
61
|
+
export function isModelTier(value) {
|
|
62
|
+
return typeof value === 'string' && MODEL_TIERS.includes(value);
|
|
63
|
+
}
|
|
64
|
+
export function modelTierForModel(model) {
|
|
65
|
+
const match = MODEL_ID_RE.exec(String(model || '').trim());
|
|
66
|
+
if (!match)
|
|
67
|
+
return null;
|
|
68
|
+
const family = String(match[2] || '');
|
|
69
|
+
for (const tier of MODEL_TIERS) {
|
|
70
|
+
if (TIER_FAMILIES[tier][0] === family)
|
|
71
|
+
return tier;
|
|
72
|
+
}
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
export function effortForTier(tier, resolved = resolveLatestModelTiers()) {
|
|
76
|
+
const wanted = MODEL_TIER_EFFORT[tier];
|
|
77
|
+
const supported = resolved.supported_efforts[resolved.models[tier]] || [];
|
|
78
|
+
if (!supported.length || supported.includes(wanted))
|
|
79
|
+
return wanted;
|
|
80
|
+
const order = ['low', 'medium', 'high', 'max'];
|
|
81
|
+
const index = order.indexOf(wanted);
|
|
82
|
+
const byDistance = [...order].sort((a, b) => Math.abs(order.indexOf(a) - index) - Math.abs(order.indexOf(b) - index));
|
|
83
|
+
return byDistance.find((effort) => supported.includes(effort)) || wanted;
|
|
84
|
+
}
|
|
85
|
+
function readCandidateRows(file) {
|
|
86
|
+
let parsed;
|
|
87
|
+
try {
|
|
88
|
+
parsed = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return [];
|
|
92
|
+
}
|
|
93
|
+
const models = Array.isArray(parsed?.models) ? parsed.models : Array.isArray(parsed) ? parsed : [];
|
|
94
|
+
const rows = [];
|
|
95
|
+
for (const row of models.slice(0, 1024)) {
|
|
96
|
+
if (!row || typeof row !== 'object')
|
|
97
|
+
continue;
|
|
98
|
+
const slug = String(row.slug || row.model || row.id || '').trim();
|
|
99
|
+
const match = MODEL_ID_RE.exec(slug);
|
|
100
|
+
if (!match)
|
|
101
|
+
continue;
|
|
102
|
+
const visibility = String(row.visibility || 'list').toLowerCase();
|
|
103
|
+
if (visibility === 'hide' || visibility === 'hidden')
|
|
104
|
+
continue;
|
|
105
|
+
const efforts = Array.isArray(row.supported_reasoning_levels)
|
|
106
|
+
? row.supported_reasoning_levels
|
|
107
|
+
.map((level) => String(typeof level === 'string' ? level : level?.effort || '').trim().toLowerCase())
|
|
108
|
+
.filter(Boolean)
|
|
109
|
+
: [];
|
|
110
|
+
rows.push({ slug, version: String(match[1] || '0').split('.').map(Number), family: String(match[2] || ''), efforts });
|
|
111
|
+
}
|
|
112
|
+
return rows;
|
|
113
|
+
}
|
|
114
|
+
function compareVersions(a, b) {
|
|
115
|
+
const length = Math.max(a.length, b.length);
|
|
116
|
+
for (let index = 0; index < length; index += 1) {
|
|
117
|
+
const diff = (a[index] || 0) - (b[index] || 0);
|
|
118
|
+
if (diff !== 0)
|
|
119
|
+
return diff;
|
|
120
|
+
}
|
|
121
|
+
return 0;
|
|
122
|
+
}
|
|
123
|
+
function newestRow(rows) {
|
|
124
|
+
return [...rows].sort((left, right) => compareVersions(right.version, left.version))[0] || null;
|
|
125
|
+
}
|
|
126
|
+
function resolveFromRows(rows) {
|
|
127
|
+
const models = { ...BUILTIN_LATEST_TIER_MODELS };
|
|
128
|
+
const supported = Object.fromEntries(rows.map((row) => [row.slug, row.efforts]));
|
|
129
|
+
let fromCache = true;
|
|
130
|
+
for (const tier of MODEL_TIERS) {
|
|
131
|
+
const families = TIER_FAMILIES[tier];
|
|
132
|
+
const candidates = rows
|
|
133
|
+
.filter((row) => families.includes(row.family))
|
|
134
|
+
.sort((left, right) => compareVersions(right.version, left.version)
|
|
135
|
+
|| families.indexOf(left.family) - families.indexOf(right.family));
|
|
136
|
+
const pick = candidates[0] || newestRow(rows);
|
|
137
|
+
if (!pick) {
|
|
138
|
+
fromCache = false;
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
models[tier] = pick.slug;
|
|
142
|
+
}
|
|
143
|
+
return Object.freeze({
|
|
144
|
+
source: fromCache && rows.length ? 'models_cache' : 'builtin',
|
|
145
|
+
models: Object.freeze(models),
|
|
146
|
+
efforts: MODEL_TIER_EFFORT,
|
|
147
|
+
supported_efforts: Object.freeze(supported)
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
export function codexListedEfforts(model, input = {}) {
|
|
151
|
+
const efforts = resolveLatestModelTiers(input).supported_efforts[String(model || '').trim()];
|
|
152
|
+
return efforts && efforts.length ? efforts : null;
|
|
153
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { uniqueStrings } from '../text/strings.js';
|
|
2
2
|
import { NARUTO_CREDENTIAL_BOOLEAN_FLAGS, NARUTO_CREDENTIAL_VALUE_FLAGS } from './naruto-command-input-contract.js';
|
|
3
3
|
import { resolveNarutoCredentialPolicy } from './naruto-host-credentials.js';
|
|
4
|
-
import { DEFAULT_SUBAGENT_EFFORT,
|
|
4
|
+
import { DEFAULT_SUBAGENT_EFFORT, defaultSubagentModel, NARUTO_PARENT_EFFORT, narutoParentModel } from './model-policy.js';
|
|
5
5
|
import { HARD_NARUTO_MAX_THREADS } from './thread-budget.js';
|
|
6
6
|
export function parseNarutoArgs(args) {
|
|
7
7
|
const helpRequested = args.includes('--help') || args.includes('-h');
|
|
@@ -121,9 +121,9 @@ export function parseNarutoArgs(args) {
|
|
|
121
121
|
credentialPolicy: resolveNarutoCredentialPolicy({
|
|
122
122
|
args: action === 'run' ? optionArgs : [],
|
|
123
123
|
env: action === 'run' ? process.env : {},
|
|
124
|
-
defaultParentModel:
|
|
124
|
+
defaultParentModel: narutoParentModel(),
|
|
125
125
|
defaultParentEffort: NARUTO_PARENT_EFFORT,
|
|
126
|
-
defaultSubagentModel:
|
|
126
|
+
defaultSubagentModel: defaultSubagentModel(),
|
|
127
127
|
defaultSubagentEffort: DEFAULT_SUBAGENT_EFFORT
|
|
128
128
|
})
|
|
129
129
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { NARUTO_PARENT_EFFORT,
|
|
1
|
+
import { NARUTO_PARENT_EFFORT, narutoParentModel } from './model-policy.js';
|
|
2
|
+
import { resolveLatestModelTiers } from './model-tiers.js';
|
|
2
3
|
import { NARUTO_ACTIONS } from '../safety/command-contract/types.js';
|
|
3
4
|
import { DEFAULT_AUTOMATIC_SUBAGENT_COUNT, MAX_AUTOMATIC_REVIEWER_COUNT, MAX_AUTOMATIC_SUBAGENT_COUNT, MAX_CRITICAL_AUTOMATIC_REVIEWER_COUNT, MAX_MASS_AUTOMATIC_SUBAGENT_COUNT, officialSubagentRolePlan } from './agent-catalog.js';
|
|
4
5
|
export const NARUTO_HELP_SCHEMA = 'sks.naruto-subagent-workflow.v1';
|
|
@@ -21,16 +22,18 @@ export function renderNarutoUsage() {
|
|
|
21
22
|
' --model-provider NAME Host config.toml provider block (host mode only).',
|
|
22
23
|
' --provider-env-key NAME Environment-variable name used by that provider.',
|
|
23
24
|
' --parent-model NAME Override the parent model identifier.',
|
|
24
|
-
' --parent-effort TIER
|
|
25
|
-
' --subagent-model NAME
|
|
26
|
-
' --subagent-effort TIER
|
|
25
|
+
' --parent-effort TIER Parent default: max; use efforts the model lists.',
|
|
26
|
+
' --subagent-model NAME Default child model; any current tier model (default: latest deep).',
|
|
27
|
+
' --subagent-effort TIER low|medium|high|xhigh|max|ultra as the model lists; vary by task.',
|
|
27
28
|
' --no-forced-login-method Do not inject a forced login method.',
|
|
28
29
|
' --json Emit machine-readable output.',
|
|
29
30
|
'',
|
|
30
|
-
'
|
|
31
|
-
'Automatic fan-out starts at 4/6/8, or 16 for eligible mass mechanical or exploration work on the
|
|
31
|
+
'Model tiers: every child runs the newest model of its tier: fast for tiny mechanical work, balanced for instructed coding, context for reads and tools, deep for planning, analysis, and review judgment.',
|
|
32
|
+
'Automatic fan-out starts at 4/6/8, or 16 for eligible mass mechanical or exploration work on the fast and context tiers.',
|
|
32
33
|
'After decomposition, either lane may expand to 256 independent useful children.',
|
|
33
|
-
'A measured lower Codex host or explicit provider/API limit remains authoritative.'
|
|
34
|
+
'A measured lower Codex host or explicit provider/API limit remains authoritative.',
|
|
35
|
+
'Jev mode on: Jev picks each Codex App child spawn\'s tier and SKS seals its newest model; a stored role preference wins.',
|
|
36
|
+
'The parent orchestrates only; the PreToolUse gate denies parent source edits before the first child starts and while children run.'
|
|
34
37
|
].join('\n');
|
|
35
38
|
}
|
|
36
39
|
export function buildNarutoHelpResult() {
|
|
@@ -53,7 +56,7 @@ export function buildNarutoHelpResult() {
|
|
|
53
56
|
automatic_subagent_ceiling: MAX_AUTOMATIC_SUBAGENT_COUNT,
|
|
54
57
|
mass_automatic_subagent_ceiling: MAX_MASS_AUTOMATIC_SUBAGENT_COUNT,
|
|
55
58
|
absolute_hard_frame_cap: 256,
|
|
56
|
-
fanout_contract: 'automatic fan-out starts at 4/6/8/16 for bounded, explicit-parallel, large-scale, and mass mechanical or exploration work on the
|
|
59
|
+
fanout_contract: 'automatic fan-out starts at 4/6/8/16 for bounded, explicit-parallel, large-scale, and mass mechanical or exploration work on the fast and context tiers; after decomposition both lanes may expand to the 256-child SKS ceiling, max_threads defaults to a 256-child frame budget that is a cap rather than a target, measured lower Codex host and explicit provider/API limits remain authoritative, and later waves reuse capacity',
|
|
57
60
|
automatic_reviewer_ceiling: MAX_AUTOMATIC_REVIEWER_COUNT,
|
|
58
61
|
critical_multi_domain_reviewer_ceiling: MAX_CRITICAL_AUTOMATIC_REVIEWER_COUNT,
|
|
59
62
|
max_threads_is_cap_not_target: true,
|
|
@@ -62,17 +65,19 @@ export function buildNarutoHelpResult() {
|
|
|
62
65
|
triwiki_context: 'bounded_attention_use_first_with_on_demand_hydration',
|
|
63
66
|
model_routing_policy: {
|
|
64
67
|
luna_max: 'tiny_short_context_mechanical_and_mass_shards',
|
|
65
|
-
sol_high: '
|
|
66
|
-
sol_max: '
|
|
67
|
-
terra_max: '
|
|
68
|
-
mixed_slice_rule: '
|
|
68
|
+
sol_high: 'balanced_tier_instructed_ordinary_ui_logic_backend_and_native_implementation',
|
|
69
|
+
sol_max: 'deep_tier_review_debug_planning_architecture_security_database_research_release_and_judgment',
|
|
70
|
+
terra_max: 'context_tier_broad_search_exploration_long_context_long_term_memory_large_first_draft_computer_use_browser_chrome_and_image_generation_execution',
|
|
71
|
+
mixed_slice_rule: 'split_execution_from_judgment_when_possible_otherwise_deep_tier_wins',
|
|
72
|
+
tier_models: 'each tier resolves to the newest model the Codex models cache lists; no model family is pinned',
|
|
73
|
+
current_tier_models: resolveLatestModelTiers().models
|
|
69
74
|
},
|
|
70
75
|
completion_evidence: {
|
|
71
76
|
lifecycle_events: ['SubagentStart', 'SubagentStop'],
|
|
72
77
|
stop_is_success_evidence: false,
|
|
73
78
|
structured_parent_summary: 'subagent-parent-summary.json'
|
|
74
79
|
},
|
|
75
|
-
parent: { model:
|
|
80
|
+
parent: { model: narutoParentModel(), model_reasoning_effort: NARUTO_PARENT_EFFORT },
|
|
76
81
|
agent_catalog_mode: 'full_catalog_only_on_explicit_help',
|
|
77
82
|
agents: officialSubagentRolePlan()
|
|
78
83
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defaultSubagentModel } from './model-policy.js';
|
|
2
|
+
import { codexListedEfforts, latestTierModelSet } from './model-tiers.js';
|
|
2
3
|
export const NARUTO_AUTH_MODES = ['managed', 'host'];
|
|
3
4
|
const IDENTIFIER_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
|
|
4
5
|
const RETIRED_DIRECT_MANAGED_PROVIDERS = new Set(['codex-lb', 'openrouter']);
|
|
@@ -80,7 +81,7 @@ export function resolveNarutoCredentialPolicy(input) {
|
|
|
80
81
|
const models = [
|
|
81
82
|
{ key: 'parentModel', flag: '--parent-model', envKey: 'SKS_NARUTO_PARENT_MODEL', fallback: input.defaultParentModel, effort: false },
|
|
82
83
|
{ key: 'parentEffort', flag: '--parent-effort', envKey: 'SKS_NARUTO_PARENT_EFFORT', fallback: input.defaultParentEffort, effort: true },
|
|
83
|
-
{ key: 'subagentModel', flag: '--subagent-model', envKey: 'SKS_NARUTO_SUBAGENT_MODEL', fallback:
|
|
84
|
+
{ key: 'subagentModel', flag: '--subagent-model', envKey: 'SKS_NARUTO_SUBAGENT_MODEL', fallback: defaultSubagentModel(), effort: false },
|
|
84
85
|
{ key: 'subagentEffort', flag: '--subagent-effort', envKey: 'SKS_NARUTO_SUBAGENT_EFFORT', fallback: input.defaultSubagentEffort, effort: true }
|
|
85
86
|
];
|
|
86
87
|
const resolvedModels = {};
|
|
@@ -103,9 +104,9 @@ export function resolveNarutoCredentialPolicy(input) {
|
|
|
103
104
|
resolvedModels[entry.key] = raw.value;
|
|
104
105
|
sources[entry.key] = raw.source;
|
|
105
106
|
}
|
|
106
|
-
if (resolvedModels.subagentModel
|
|
107
|
-
blockers.push('
|
|
108
|
-
resolvedModels.subagentModel =
|
|
107
|
+
if (!latestTierModelSet().has(String(resolvedModels.subagentModel))) {
|
|
108
|
+
blockers.push('naruto_subagent_model_must_be_current');
|
|
109
|
+
resolvedModels.subagentModel = defaultSubagentModel();
|
|
109
110
|
}
|
|
110
111
|
validateGpt56EffortPair('parent', String(resolvedModels.parentModel), String(resolvedModels.parentEffort), blockers);
|
|
111
112
|
validateGpt56EffortPair('subagent', String(resolvedModels.subagentModel), String(resolvedModels.subagentEffort), blockers);
|
|
@@ -146,15 +147,9 @@ export function resolveNarutoCredentialPolicy(input) {
|
|
|
146
147
|
};
|
|
147
148
|
}
|
|
148
149
|
function validateGpt56EffortPair(scope, model, effort, blockers) {
|
|
149
|
-
const allowed = model
|
|
150
|
-
? ['low', 'medium', 'high', 'xhigh', 'max', 'ultra']
|
|
151
|
-
: model === LUNA_SUBAGENT_MODEL || model === 'gpt-5.6-terra'
|
|
152
|
-
? ['max']
|
|
153
|
-
: model === 'gpt-5.6-sol'
|
|
154
|
-
? scope === 'parent' ? ['max'] : ['high', 'max']
|
|
155
|
-
: null;
|
|
150
|
+
const allowed = codexListedEfforts(model);
|
|
156
151
|
if (allowed && !allowed.includes(effort)) {
|
|
157
|
-
blockers.push(`naruto_${scope}
|
|
152
|
+
blockers.push(`naruto_${scope}_effort_unsupported:${model}:${effort}:allowed_${allowed.join('_or_')}`);
|
|
158
153
|
}
|
|
159
154
|
}
|
|
160
155
|
export function narutoCredentialConfigArgs(policy) {
|
|
@@ -5,7 +5,8 @@ import { parse } from 'smol-toml';
|
|
|
5
5
|
import { ensureDir, exists, PACKAGE_VERSION, readText, sha256, writeTextAtomic } from '../fsx.js';
|
|
6
6
|
import { ensureConfinedDirectory, inspectConfinedPath } from '../managed-path-safety.js';
|
|
7
7
|
import { MANAGED_OFFICIAL_SUBAGENT_ROLES, managedOfficialSubagentRoleContent, managedOfficialSubagentRoleOwnsText } from '../managed-assets/managed-assets-manifest.js';
|
|
8
|
-
import { DEFAULT_SUBAGENT_EFFORT,
|
|
8
|
+
import { DEFAULT_SUBAGENT_EFFORT, defaultSubagentModel as latestDefaultSubagentModel } from './model-policy.js';
|
|
9
|
+
import { latestTierModelSet } from './model-tiers.js';
|
|
9
10
|
import { HARD_NARUTO_MAX_THREADS } from './thread-budget.js';
|
|
10
11
|
import { escapeRegExp } from '../text/regex.js';
|
|
11
12
|
export const DEFAULT_OFFICIAL_SUBAGENT_MAX_THREADS = 256;
|
|
@@ -13,7 +14,9 @@ export const DEFAULT_OFFICIAL_SUBAGENT_MAX_DEPTH = 1;
|
|
|
13
14
|
export const DEFAULT_OFFICIAL_SUBAGENT_JOB_MAX_RUNTIME_SECONDS = 1200;
|
|
14
15
|
export const DEFAULT_OFFICIAL_SUBAGENT_INTERRUPT_MESSAGE = true;
|
|
15
16
|
export const DEFAULT_OFFICIAL_SUBAGENT_ENABLED = true;
|
|
16
|
-
export
|
|
17
|
+
export function defaultOfficialSubagentModel() {
|
|
18
|
+
return latestDefaultSubagentModel();
|
|
19
|
+
}
|
|
17
20
|
export const DEFAULT_OFFICIAL_SUBAGENT_REASONING_EFFORT = DEFAULT_SUBAGENT_EFFORT;
|
|
18
21
|
export const DEFAULT_MULTI_AGENT_V2_MAX_CONCURRENT_THREADS_PER_SESSION = DEFAULT_OFFICIAL_SUBAGENT_MAX_THREADS + 1;
|
|
19
22
|
export const LEGACY_SKS_MAX_THREAD_VALUES = Object.freeze([4, 5, 6, 12]);
|
|
@@ -49,7 +52,8 @@ export function mergeOfficialSubagentConfigResult(text = '', opts = {}) {
|
|
|
49
52
|
next = upsertDefaultUnlessInherited(next, inheritedAgents, 'enabled', `enabled = ${DEFAULT_OFFICIAL_SUBAGENT_ENABLED}`);
|
|
50
53
|
next = upsertDefaultUnlessInherited(next, inheritedAgents, 'max_depth', `max_depth = ${DEFAULT_OFFICIAL_SUBAGENT_MAX_DEPTH}`);
|
|
51
54
|
next = upsertDefaultUnlessInherited(next, inheritedAgents, 'interrupt_message', `interrupt_message = ${DEFAULT_OFFICIAL_SUBAGENT_INTERRUPT_MESSAGE}`);
|
|
52
|
-
|
|
55
|
+
const existingDefault = /^\s*default_subagent_model\s*=\s*"([^"]*)"/m.exec(next)?.[1] || '';
|
|
56
|
+
next = upsertTomlTableKey(next, 'agents', `default_subagent_model = "${latestTierModelSet().has(existingDefault) ? existingDefault : defaultOfficialSubagentModel()}"`);
|
|
53
57
|
next = upsertDefaultUnlessInherited(next, inheritedAgents, 'default_subagent_reasoning_effort', `default_subagent_reasoning_effort = "${DEFAULT_OFFICIAL_SUBAGENT_REASONING_EFFORT}"`);
|
|
54
58
|
next = mergeOfficialMultiAgentV2FeatureConfig(next, {
|
|
55
59
|
sksOwned: opts.sksOwned === true,
|
|
@@ -136,17 +140,17 @@ export async function readOfficialSubagentConfig(root, opts = {}) {
|
|
|
136
140
|
const effectiveMaxThreads = Math.min(maxThreads.value, HARD_NARUTO_MAX_THREADS);
|
|
137
141
|
const maxDepth = resolveLayeredValue(projectLayer.agents.max_depth, globalLayer.agents.max_depth, DEFAULT_OFFICIAL_SUBAGENT_MAX_DEPTH, positiveInteger);
|
|
138
142
|
const interruptMessage = resolveLayeredValue(projectLayer.agents.interrupt_message, globalLayer.agents.interrupt_message, DEFAULT_OFFICIAL_SUBAGENT_INTERRUPT_MESSAGE, booleanValue);
|
|
139
|
-
const defaultSubagentModel = resolveLayeredValue(projectLayer.agents.default_subagent_model, globalLayer.agents.default_subagent_model,
|
|
143
|
+
const defaultSubagentModel = resolveLayeredValue(projectLayer.agents.default_subagent_model, globalLayer.agents.default_subagent_model, defaultOfficialSubagentModel(), nonEmptyString);
|
|
140
144
|
const defaultSubagentReasoningEffort = resolveLayeredValue(projectLayer.agents.default_subagent_reasoning_effort, globalLayer.agents.default_subagent_reasoning_effort, DEFAULT_OFFICIAL_SUBAGENT_REASONING_EFFORT, nonEmptyString);
|
|
141
145
|
const multiAgentV2 = resolveMultiAgentV2Layer(projectLayer.features.multi_agent_v2, globalLayer.features.multi_agent_v2, effectiveMaxThreads);
|
|
142
146
|
const effectiveMultiAgentV2 = {
|
|
143
147
|
...multiAgentV2.value,
|
|
144
148
|
maxConcurrentThreadsPerSession: Math.min(multiAgentV2.value.maxConcurrentThreadsPerSession, HARD_NARUTO_MAX_THREADS + 1)
|
|
145
149
|
};
|
|
146
|
-
const modelCoerced = defaultSubagentModel.value
|
|
150
|
+
const modelCoerced = !latestTierModelSet().has(String(defaultSubagentModel.value));
|
|
147
151
|
const depthCoerced = maxDepth.value > 1;
|
|
148
152
|
const warnings = [
|
|
149
|
-
...(modelCoerced ? [`
|
|
153
|
+
...(modelCoerced ? [`official_subagent_model_coerced_to_latest:${defaultSubagentModel.value}:${defaultSubagentModel.source}`] : []),
|
|
150
154
|
...(depthCoerced ? [`official_subagent_max_depth_coerced_to_one:${maxDepth.value}:${maxDepth.source}`] : []),
|
|
151
155
|
...capacityNormalizationWarnings(maxThreads, multiAgentV2),
|
|
152
156
|
...(projectLayer.legacyWarnings),
|
|
@@ -158,7 +162,7 @@ export async function readOfficialSubagentConfig(root, opts = {}) {
|
|
|
158
162
|
maxDepth: depthCoerced ? DEFAULT_OFFICIAL_SUBAGENT_MAX_DEPTH : maxDepth.value,
|
|
159
163
|
jobMaxRuntimeSeconds: null,
|
|
160
164
|
interruptMessage: interruptMessage.value,
|
|
161
|
-
defaultSubagentModel:
|
|
165
|
+
defaultSubagentModel: modelCoerced ? defaultOfficialSubagentModel() : String(defaultSubagentModel.value),
|
|
162
166
|
defaultSubagentReasoningEffort: defaultSubagentReasoningEffort.value,
|
|
163
167
|
multiAgentV2: effectiveMultiAgentV2,
|
|
164
168
|
sources: {
|