@ancleto/spec 0.6.6 → 0.6.7
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 +26 -1
- package/agents/context-resolver.md +1 -1
- package/agents/documenter.md +1 -1
- package/agents/memory-keeper.md +1 -1
- package/agents/technical-discovery.md +1 -1
- package/agents/tester.md +1 -1
- package/package.json +1 -1
- package/src/cli/index.js +40 -18
- package/src/core/tier-models.js +48 -0
package/README.md
CHANGED
|
@@ -106,7 +106,7 @@ ancleto init --agent opencode --tier normal
|
|
|
106
106
|
|
|
107
107
|
* `normal`: Modelos balanceados sin restricciones agresivas de contexto (default).
|
|
108
108
|
* `minimo`: Enfoque en el modelo pago más económico viable, con alta compresión de contexto y exclusión de tests/docs en el discovery.
|
|
109
|
-
* `gratis`: Bloqueado a modelos gratuitos
|
|
109
|
+
* `gratis`: Bloqueado a modelos gratuitos, empaquetado ultra-agresivo y un límite estricto (budget) de tokens enviado al LLM. Si tenés acceso a **Muse Spark 1.3 Free** (`opencode/muse-spark-1.3-contributor-free`, no abierto a todos), se usa ese; si no, se usa `opencode/big-pickle`. En modo interactivo el instalador te lo pregunta; la elección queda guardada en `.ancletorc` (`gratisModel`).
|
|
110
110
|
|
|
111
111
|
La configuración se preserva en `.ancletorc` (raíz del proyecto) y `.ancleto-tier` (junto a la configuración instalada).
|
|
112
112
|
|
|
@@ -211,3 +211,28 @@ ancleto init --with-azure
|
|
|
211
211
|
```
|
|
212
212
|
|
|
213
213
|
Esto escribe `azure.enabled: true` en tu `.ancletorc`. Solo deberás completar la sección de Azure en el archivo `PRODUCT.md` e instalar su extensión (`az extension add --name azure-devops`).
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## 🤖 Referencia: Agentes y Modelos por Tier
|
|
218
|
+
|
|
219
|
+
Los 10 agentes instalados y el modelo que usa cada uno según tu tier. Al instalar, el nivel elegido se escribe en la línea `model:` de cada agente (y se re-aplica en cada `update`).
|
|
220
|
+
|
|
221
|
+
| Agente | `normal` (default) | `minimo` | `gratis` |
|
|
222
|
+
|---|---|---|---|
|
|
223
|
+
| orchestrator | `opencode-go/qwen3.7-plus` | `opencode-go/deepseek-v4.1-flash` | ver nota ↓ |
|
|
224
|
+
| coder | `opencode-go/minimax-m3` | `opencode-go/deepseek-v4.1-flash` | ver nota ↓ |
|
|
225
|
+
| tester | `opencode-go/deepseek-v4.1-flash` | `opencode-go/deepseek-v4.1-flash` | ver nota ↓ |
|
|
226
|
+
| spec-writer | `opencode-go/qwen3.7-plus` | `opencode-go/deepseek-v4.1-flash` | ver nota ↓ |
|
|
227
|
+
| reviewer | `opencode-go/qwen3.6-plus` | `opencode-go/deepseek-v4.1-flash` | ver nota ↓ |
|
|
228
|
+
| technical-discovery | `opencode-go/deepseek-v4.1-flash` | `opencode-go/deepseek-v4.1-flash` | ver nota ↓ |
|
|
229
|
+
| technical-seed-writer | `opencode-go/minimax-m3` | `opencode-go/deepseek-v4.1-flash` | ver nota ↓ |
|
|
230
|
+
| memory-keeper | `opencode-go/deepseek-v4.1-flash` | `opencode-go/deepseek-v4.1-flash` | ver nota ↓ |
|
|
231
|
+
| context-resolver | `opencode-go/deepseek-v4.1-flash` | `opencode-go/deepseek-v4.1-flash` | ver nota ↓ |
|
|
232
|
+
| documenter | `opencode-go/deepseek-v4.1-flash` | `opencode-go/deepseek-v4.1-flash` | ver nota ↓ |
|
|
233
|
+
|
|
234
|
+
El tier `minimo` usa un único modelo (`deepseek-v4.1-flash`) para los 10 agentes: es el más económico del catálogo para coding (0.15/0.60 por millón de tokens) con 1M de contexto.
|
|
235
|
+
|
|
236
|
+
**Tier `gratis`:** los 10 agentes usan **Muse Spark 1.3 Free** (`opencode/muse-spark-1.3-contributor-free`) **si está disponible** en tu cuenta (no está abierto a todos). En una instalación interactiva el wizard te lo pregunta; la respuesta se guarda en `.ancletorc` (`gratisModel`) y se reutiliza en los siguientes `install`/`update`. Sin TTY (CI) se detecta con `opencode models` — con timeout — y si no se puede confirmar se usa `opencode/big-pickle`. El instalador siempre informa cuál aplicó (`ancleto: modelo gratis: ...`).
|
|
237
|
+
|
|
238
|
+
> Variable avanzada: `ANCLETO_MUSE_SPARK=1` fuerza Muse Spark, `ANCLETO_MUSE_SPARK=0` fuerza `big-pickle` (útil para tests o para fijar el comportamiento; tiene prioridad sobre la elección guardada).
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Resolves intake grounding context (Work Item / card) before triage, so the orchestrator classifies and delegates with the real card content
|
|
3
3
|
mode: subagent
|
|
4
|
-
model: opencode-go/deepseek-v4-flash
|
|
4
|
+
model: opencode-go/deepseek-v4.1-flash
|
|
5
5
|
temperature: 0.1
|
|
6
6
|
color: '#8b5cf6'
|
|
7
7
|
tools:
|
package/agents/documenter.md
CHANGED
package/agents/memory-keeper.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Owns the repository memory (.ancleto/memory.db) — recalls prior lessons at intake and records rules and decisions at close, so a finding survives the session that produced it
|
|
3
3
|
mode: subagent
|
|
4
|
-
model: opencode-go/deepseek-v4-flash
|
|
4
|
+
model: opencode-go/deepseek-v4.1-flash
|
|
5
5
|
temperature: 0.1
|
|
6
6
|
color: '#f59e0b'
|
|
7
7
|
tools:
|
package/agents/tester.md
CHANGED
package/package.json
CHANGED
package/src/cli/index.js
CHANGED
|
@@ -12,6 +12,7 @@ import { memoryDoctor } from '../core/memory/doctor.js'
|
|
|
12
12
|
import { writeDiscoveryMap } from '../core/discovery.js'
|
|
13
13
|
import { readProjectTier, buildRepomixArgs, tierTokenBudget } from '../core/repomix-tier.js'
|
|
14
14
|
import { showBanner, selectOption, stopBanner } from './ui.js'
|
|
15
|
+
import { tierModels, gratisModel, envGratisModel, isKnownGratisModel, MUSE_SPARK_MODEL, GRATIS_FALLBACK_MODEL } from '../core/tier-models.js'
|
|
15
16
|
|
|
16
17
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
17
18
|
const ROOT = join(__dirname, '..', '..')
|
|
@@ -137,26 +138,26 @@ const TIERS = {
|
|
|
137
138
|
normal: {
|
|
138
139
|
orchestrator: 'opencode-go/qwen3.7-plus',
|
|
139
140
|
coder: 'opencode-go/minimax-m3',
|
|
140
|
-
tester: 'opencode-go/deepseek-v4-flash',
|
|
141
|
+
tester: 'opencode-go/deepseek-v4.1-flash',
|
|
141
142
|
'spec-writer': 'opencode-go/qwen3.7-plus',
|
|
142
143
|
reviewer: 'opencode-go/qwen3.6-plus',
|
|
143
|
-
'technical-discovery': 'opencode-go/deepseek-v4-flash',
|
|
144
|
+
'technical-discovery': 'opencode-go/deepseek-v4.1-flash',
|
|
144
145
|
'technical-seed-writer': 'opencode-go/minimax-m3',
|
|
145
|
-
'memory-keeper': 'opencode-go/deepseek-v4-flash',
|
|
146
|
-
'context-resolver': 'opencode-go/deepseek-v4-flash',
|
|
147
|
-
documenter: 'opencode-go/deepseek-v4-flash'
|
|
146
|
+
'memory-keeper': 'opencode-go/deepseek-v4.1-flash',
|
|
147
|
+
'context-resolver': 'opencode-go/deepseek-v4.1-flash',
|
|
148
|
+
documenter: 'opencode-go/deepseek-v4.1-flash'
|
|
148
149
|
},
|
|
149
150
|
minimo: {
|
|
150
|
-
orchestrator: 'opencode-go/deepseek-v4-flash',
|
|
151
|
-
coder: 'opencode-go/
|
|
152
|
-
tester: 'opencode-go/deepseek-v4-flash',
|
|
153
|
-
'spec-writer': 'opencode-go/
|
|
154
|
-
reviewer: 'opencode-go/deepseek-v4-flash',
|
|
155
|
-
'technical-discovery': 'opencode-go/deepseek-v4-flash',
|
|
156
|
-
'technical-seed-writer': 'opencode-go/
|
|
157
|
-
'memory-keeper': 'opencode-go/deepseek-v4-flash',
|
|
158
|
-
'context-resolver': 'opencode-go/deepseek-v4-flash',
|
|
159
|
-
documenter: 'opencode-go/deepseek-v4-flash'
|
|
151
|
+
orchestrator: 'opencode-go/deepseek-v4.1-flash',
|
|
152
|
+
coder: 'opencode-go/deepseek-v4.1-flash',
|
|
153
|
+
tester: 'opencode-go/deepseek-v4.1-flash',
|
|
154
|
+
'spec-writer': 'opencode-go/deepseek-v4.1-flash',
|
|
155
|
+
reviewer: 'opencode-go/deepseek-v4.1-flash',
|
|
156
|
+
'technical-discovery': 'opencode-go/deepseek-v4.1-flash',
|
|
157
|
+
'technical-seed-writer': 'opencode-go/deepseek-v4.1-flash',
|
|
158
|
+
'memory-keeper': 'opencode-go/deepseek-v4.1-flash',
|
|
159
|
+
'context-resolver': 'opencode-go/deepseek-v4.1-flash',
|
|
160
|
+
documenter: 'opencode-go/deepseek-v4.1-flash'
|
|
160
161
|
},
|
|
161
162
|
gratis: {
|
|
162
163
|
orchestrator: 'opencode/big-pickle',
|
|
@@ -176,8 +177,8 @@ function tierStatePath(targetDir) {
|
|
|
176
177
|
return join(targetDir, '.ancleto-tier')
|
|
177
178
|
}
|
|
178
179
|
|
|
179
|
-
async function applyTier(agentsDir, tier) {
|
|
180
|
-
const map = TIERS[tier]
|
|
180
|
+
async function applyTier(agentsDir, tier, models = null) {
|
|
181
|
+
const map = models || TIERS[tier]
|
|
181
182
|
for (const [name, model] of Object.entries(map)) {
|
|
182
183
|
const p = join(agentsDir, name + '.md')
|
|
183
184
|
if (!(await exists(p))) continue
|
|
@@ -389,9 +390,11 @@ async function install(args) {
|
|
|
389
390
|
|
|
390
391
|
let agent = agentFlag || (existingRc?.agent && SUPPORTED_AGENTS.includes(existingRc.agent) ? existingRc.agent : null)
|
|
391
392
|
|
|
393
|
+
let bannerShown = false
|
|
392
394
|
const isInteractive = Boolean(process.stdout.isTTY) && ((projectDir && !agent) || !tier)
|
|
393
395
|
if (isInteractive) {
|
|
394
396
|
await showBanner()
|
|
397
|
+
bannerShown = true
|
|
395
398
|
if (projectDir && !agent) {
|
|
396
399
|
agent = await selectOption('Agente/IDE', SUPPORTED_AGENTS, Math.max(0, SUPPORTED_AGENTS.indexOf(DEFAULT_AGENT)))
|
|
397
400
|
}
|
|
@@ -405,12 +408,29 @@ async function install(args) {
|
|
|
405
408
|
if (projectDir && !agent) agent = DEFAULT_AGENT
|
|
406
409
|
if (!tier) tier = TIERS[storedTier] ? storedTier : 'normal'
|
|
407
410
|
|
|
411
|
+
let gratisModelChoice = null
|
|
412
|
+
if (tier === 'gratis') {
|
|
413
|
+
const env = envGratisModel()
|
|
414
|
+
const persisted = isKnownGratisModel(existingRc?.gratisModel) ? existingRc.gratisModel : null
|
|
415
|
+
if (env || persisted) {
|
|
416
|
+
gratisModelChoice = env || persisted
|
|
417
|
+
} else if (process.stdout.isTTY) {
|
|
418
|
+
if (!bannerShown) await showBanner()
|
|
419
|
+
const answer = await selectOption('Muse Spark 1.3 Free disponible en tu cuenta?', ['No (usar big-pickle)', 'Si (Muse Spark)'], 0)
|
|
420
|
+
if (!bannerShown) stopBanner()
|
|
421
|
+
gratisModelChoice = answer.startsWith('Si') ? MUSE_SPARK_MODEL : GRATIS_FALLBACK_MODEL
|
|
422
|
+
} else {
|
|
423
|
+
gratisModelChoice = gratisModel()
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
408
427
|
if (projectDir) {
|
|
409
428
|
await copyTemplates(projectDir)
|
|
410
429
|
await scaffoldAspec(projectDir)
|
|
411
430
|
const agentSkillsDir = await installAgentSkills(projectDir, agent)
|
|
412
431
|
await writeManifest(projectDir, {
|
|
413
432
|
agent,
|
|
433
|
+
...(gratisModelChoice ? { gratisModel: gratisModelChoice } : {}),
|
|
414
434
|
installedPaths: {
|
|
415
435
|
templates: ['AGENTS.md', 'PRODUCT.md'],
|
|
416
436
|
agents: ['.opencode/agents'],
|
|
@@ -422,7 +442,8 @@ async function install(args) {
|
|
|
422
442
|
await copyAssets(target)
|
|
423
443
|
}
|
|
424
444
|
|
|
425
|
-
|
|
445
|
+
const models = tierModels(tier, TIERS, gratisModelChoice)
|
|
446
|
+
await applyTier(join(target, 'agents'), tier, models)
|
|
426
447
|
await writeFile(tierStatePath(target), tier + '\n')
|
|
427
448
|
|
|
428
449
|
let azureMcp = false
|
|
@@ -440,6 +461,7 @@ async function install(args) {
|
|
|
440
461
|
: `${target} (disponible en todos tus proyectos)`
|
|
441
462
|
console.log(`ancleto: instalado en ${loc}`)
|
|
442
463
|
console.log(`ancleto: tier de costo de agents: ${tier}`)
|
|
464
|
+
if (tier === 'gratis') console.log(`ancleto: modelo gratis: ${models.orchestrator}`)
|
|
443
465
|
if (res.added.length) {
|
|
444
466
|
console.log(`ancleto: MCP configurados: ${res.added.join(', ')} en ${res.file}`)
|
|
445
467
|
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process'
|
|
2
|
+
|
|
3
|
+
export const MUSE_SPARK_MODEL = 'opencode/muse-spark-1.3-contributor-free'
|
|
4
|
+
export const GRATIS_FALLBACK_MODEL = 'opencode/big-pickle'
|
|
5
|
+
|
|
6
|
+
let probed = null
|
|
7
|
+
|
|
8
|
+
export function envGratisModel() {
|
|
9
|
+
if (process.env.ANCLETO_MUSE_SPARK === '1') return MUSE_SPARK_MODEL
|
|
10
|
+
if (process.env.ANCLETO_MUSE_SPARK === '0') return GRATIS_FALLBACK_MODEL
|
|
11
|
+
return null
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function isKnownGratisModel(model) {
|
|
15
|
+
return model === MUSE_SPARK_MODEL || model === GRATIS_FALLBACK_MODEL
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function detectMuseSpark() {
|
|
19
|
+
const env = envGratisModel()
|
|
20
|
+
if (env) return env === MUSE_SPARK_MODEL
|
|
21
|
+
if (probed !== null) return probed
|
|
22
|
+
try {
|
|
23
|
+
const r = spawnSync('opencode models opencode', {
|
|
24
|
+
encoding: 'utf8',
|
|
25
|
+
timeout: 5000,
|
|
26
|
+
shell: true,
|
|
27
|
+
stdio: ['ignore', 'pipe', 'pipe']
|
|
28
|
+
})
|
|
29
|
+
probed = !r.error && r.status === 0
|
|
30
|
+
&& String(r.stdout || '').split('\n').some((l) => l.trim() === MUSE_SPARK_MODEL)
|
|
31
|
+
} catch {
|
|
32
|
+
probed = false
|
|
33
|
+
}
|
|
34
|
+
return probed
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function gratisModel(persisted = null) {
|
|
38
|
+
const env = envGratisModel()
|
|
39
|
+
if (env) return env
|
|
40
|
+
if (isKnownGratisModel(persisted)) return persisted
|
|
41
|
+
return detectMuseSpark() ? MUSE_SPARK_MODEL : GRATIS_FALLBACK_MODEL
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function tierModels(tier, tiers, gratisOverride = null) {
|
|
45
|
+
if (tier !== 'gratis') return tiers[tier]
|
|
46
|
+
const model = gratisOverride || gratisModel()
|
|
47
|
+
return Object.fromEntries(Object.keys(tiers.gratis).map((k) => [k, model]))
|
|
48
|
+
}
|