terminal-smart-cli 0.97.30 → 0.97.31
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/bin/ts.js +14 -1
- package/lib/agent.js +19 -5
- package/lib/intelligence-core.js +19 -10
- package/package.json +1 -1
package/bin/ts.js
CHANGED
|
@@ -1079,6 +1079,19 @@ async function pollRun(token, runId, sp) {
|
|
|
1079
1079
|
}
|
|
1080
1080
|
}
|
|
1081
1081
|
|
|
1082
|
+
// A run é o resumo; o motivo técnico da falha fica na etapa. Centralizar a
|
|
1083
|
+
// leitura evita que o usuário receba apenas "falhou" e tenha de investigar
|
|
1084
|
+
// logs ou a interface web para saber o que fazer em seguida.
|
|
1085
|
+
function runFailureMessage(run) {
|
|
1086
|
+
const failed = (run && Array.isArray(run.steps) ? run.steps : []).find(s => s && s.status === 'failed');
|
|
1087
|
+
const raw = String((failed && (failed.error_message || failed.result_summary)) || (run && run.error) || '').trim();
|
|
1088
|
+
const code = String((failed && failed.error_code) || '').trim();
|
|
1089
|
+
if (code === 'execution_unavailable' || /n[aã]o executo comandos diretamente|n[aã]o tenho acesso.*(windows|computador|m[aá]quina|sistema)|execute.*powershell/i.test(raw)) {
|
|
1090
|
+
return 'Esta orquestração roda na nuvem e não acessa arquivos do seu computador. Para criar, editar ou inspecionar algo local, use: ts agente "sua tarefa".';
|
|
1091
|
+
}
|
|
1092
|
+
return raw || 'Nenhuma ação foi concluída. Consulte as etapas da execução para ver o motivo.';
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1082
1095
|
// Fluxo completo de orquestração (usado pelo `ts run` e pelo /run do modo conversa).
|
|
1083
1096
|
// askFn permite aprovar com o readline do REPL sem conflito de stdin; nunca chama process.exit.
|
|
1084
1097
|
async function runFlow(goal, { askFn = ui.ask, json = false, yes = false } = {}) {
|
|
@@ -1112,7 +1125,7 @@ async function runFlow(goal, { askFn = ui.ask, json = false, yes = false } = {})
|
|
|
1112
1125
|
const result = run.final_result || run.result || '';
|
|
1113
1126
|
if (result) { console.log(''); console.log(ui.md(String(result)).split('\n').map(l => ' ' + l).join('\n')); console.log(''); }
|
|
1114
1127
|
} else if (run.status === 'failed') {
|
|
1115
|
-
console.error(ui.errLine(C.bold(T.run_failed) +
|
|
1128
|
+
console.error(ui.errLine(C.bold(T.run_failed) + C.dim(' · ' + runFailureMessage(run).slice(0, 320))));
|
|
1116
1129
|
} else {
|
|
1117
1130
|
console.log(ui.infoLine(T.run_paused(runLbl(run.status))));
|
|
1118
1131
|
}
|
package/lib/agent.js
CHANGED
|
@@ -1259,7 +1259,13 @@ async function run(task, opts = {}) {
|
|
|
1259
1259
|
async function _callRole(role, system, user, validate = null) {
|
|
1260
1260
|
const phase = role === 'planner' ? 'planning' : (role === 'inspector' ? 'verification' : 'execution');
|
|
1261
1261
|
const contract = intelligence.agentRoleContract(role, opts.accountPlan || 'free', { complex: _complexTask });
|
|
1262
|
-
const
|
|
1262
|
+
const baseCandidates = (model ? [selectedModel] : [...contract.candidates]).slice(0, 1 + planUpgradeLimit(opts.accountPlan || 'free'));
|
|
1263
|
+
// Plano vazio/JSON inválido é uma falha objetiva, mas não autoriza trocar o
|
|
1264
|
+
// planejador pelo executor. A segunda tentativa curta mantém a Luna como
|
|
1265
|
+
// dona do planejamento e atende inclusive ao Free sem upgrade de modelo.
|
|
1266
|
+
const candidates = role === 'planner' && baseCandidates.length === 1
|
|
1267
|
+
? [baseCandidates[0], baseCandidates[0]]
|
|
1268
|
+
: baseCandidates;
|
|
1263
1269
|
let last = null;
|
|
1264
1270
|
let lastFailureReported = false;
|
|
1265
1271
|
const phaseStartedAt = Date.now();
|
|
@@ -1296,8 +1302,12 @@ async function run(task, opts = {}) {
|
|
|
1296
1302
|
onStepDone({ name: 'agente_' + role, ok: false, status: 'error', evidence: last.message });
|
|
1297
1303
|
lastFailureReported = true;
|
|
1298
1304
|
if (candidateIndex + 1 < candidates.length) {
|
|
1299
|
-
|
|
1300
|
-
onStep({ name: '
|
|
1305
|
+
const next = candidates[candidateIndex + 1];
|
|
1306
|
+
if (next === roleModel) onStep({ name: 'nova_tentativa', detail: `${last.message}: nova tentativa curta com ${roleModel}`, retry: true });
|
|
1307
|
+
else {
|
|
1308
|
+
_fallbackTrace.push({ role, from: roleModel, to: next, reason: last.message });
|
|
1309
|
+
onStep({ name: 'fallback_modelo', detail: `${last.message}: ${roleModel} → ${next}`, retry: true });
|
|
1310
|
+
}
|
|
1301
1311
|
}
|
|
1302
1312
|
continue;
|
|
1303
1313
|
}
|
|
@@ -1313,8 +1323,12 @@ async function run(task, opts = {}) {
|
|
|
1313
1323
|
lastFailureReported = true;
|
|
1314
1324
|
if (candidateIndex + 1 < candidates.length) {
|
|
1315
1325
|
const reason = String(e && e.message || 'falha objetiva').slice(0, 100);
|
|
1316
|
-
|
|
1317
|
-
onStep({ name: '
|
|
1326
|
+
const next = candidates[candidateIndex + 1];
|
|
1327
|
+
if (next === roleModel) onStep({ name: 'nova_tentativa', detail: `${reason}: nova tentativa curta com ${roleModel}`, retry: true });
|
|
1328
|
+
else {
|
|
1329
|
+
_fallbackTrace.push({ role, from: roleModel, to: next, reason });
|
|
1330
|
+
onStep({ name: 'fallback_modelo', detail: `${reason}: ${roleModel} → ${next}`, retry: true });
|
|
1331
|
+
}
|
|
1318
1332
|
}
|
|
1319
1333
|
if (!isTransientModelError(e) && Number(e && e.status) !== 404 && !/model.*(?:not found|unavailable|unsupported)/i.test(String(e && e.message || ''))) break;
|
|
1320
1334
|
}
|
package/lib/intelligence-core.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
const crypto = require('crypto');
|
|
10
10
|
|
|
11
|
-
const INTELLIGENCE_CONTRACT =
|
|
11
|
+
const INTELLIGENCE_CONTRACT = 2;
|
|
12
12
|
// Keep this machine-readable. Human/provider notes belong in commit history;
|
|
13
13
|
// catalogFreshness appends an ISO time before parsing this value.
|
|
14
14
|
const PRICE_REVISION = '2026-08-11';
|
|
@@ -179,9 +179,18 @@ const MODEL_ALIASES = Object.freeze({
|
|
|
179
179
|
'claude-haiku': 'claude-haiku-4-5',
|
|
180
180
|
});
|
|
181
181
|
|
|
182
|
+
// Equipe oficial do modo Automático: especialização e prova objetiva vêm antes
|
|
183
|
+
// de cascatas longas de modelos. Premium fica fora até validação real.
|
|
184
|
+
const OFFICIAL_AUTOMATIC_TEAM = Object.freeze({
|
|
185
|
+
planner: Object.freeze({ model: 'gpt-5.6-luna', label: 'Luna', responsibility: 'planejamento' }),
|
|
186
|
+
executor: Object.freeze({ model: 'deepseek-v4-pro', label: 'DeepSeek Pro', responsibility: 'execução' }),
|
|
187
|
+
corrector: Object.freeze({ model: 'deepseek-v4-pro', label: 'DeepSeek Pro', responsibility: 'correção' }),
|
|
188
|
+
multimodal: Object.freeze({ model: 'mimo-v2.5', fallback: 'gemini-2.5-flash', label: 'MiMo', responsibility: 'imagem, arquivo e documento visual' }),
|
|
189
|
+
verifier: Object.freeze({ model: null, label: 'Verificadores determinísticos', responsibility: 'prova objetiva de entrega' }),
|
|
190
|
+
});
|
|
191
|
+
|
|
182
192
|
// Contrato dos agentes funcionais. Isto não é fine-tuning: cada papel recebe um
|
|
183
|
-
// prompt curto
|
|
184
|
-
// ferramentas. O primeiro modelo permitido é o padrão; os seguintes são fallback.
|
|
193
|
+
// prompt curto e continua sujeito à prova das ferramentas.
|
|
185
194
|
const AGENT_ROLES = Object.freeze({
|
|
186
195
|
classifier: Object.freeze({
|
|
187
196
|
prompt: 'Classifique a intenção e devolva somente a estrutura pedida. Não execute ferramentas nem invente dados.',
|
|
@@ -189,19 +198,19 @@ const AGENT_ROLES = Object.freeze({
|
|
|
189
198
|
}),
|
|
190
199
|
planner: Object.freeze({
|
|
191
200
|
prompt: 'Decomponha o objetivo em etapas executáveis, dependências, riscos, critérios de aceite e provas. Não execute a tarefa.',
|
|
192
|
-
models: Object.freeze({ free: ['deepseek-v4-flash'], basic: ['gpt-5.6-luna'
|
|
201
|
+
models: Object.freeze({ free: ['deepseek-v4-flash'], basic: ['gpt-5.6-luna'], pro: ['gpt-5.6-luna'] }),
|
|
193
202
|
}),
|
|
194
203
|
executor: Object.freeze({
|
|
195
204
|
prompt: 'Execute somente a etapa recebida com as ferramentas autorizadas. Não declare sucesso sem resultado verificável.',
|
|
196
|
-
models: Object.freeze({ free: ['deepseek-v4-flash'], basic: ['deepseek-v4-pro'
|
|
205
|
+
models: Object.freeze({ free: ['deepseek-v4-flash'], basic: ['deepseek-v4-pro'], pro: ['deepseek-v4-pro'] }),
|
|
197
206
|
}),
|
|
198
207
|
inspector: Object.freeze({
|
|
199
208
|
prompt: 'Inspecione em modo somente leitura e compare evidências com os critérios de aceite. Não altere nada e não elogie por cortesia.',
|
|
200
|
-
models: Object.freeze({ free: ['gemini-2.5-flash-lite'], basic: ['gpt-5.6-luna', '
|
|
209
|
+
models: Object.freeze({ free: ['gemini-2.5-flash-lite'], basic: ['gpt-5.6-luna', 'glm-5.2'], pro: ['gpt-5.6-luna', 'glm-5.2'] }),
|
|
201
210
|
}),
|
|
202
211
|
corrector: Object.freeze({
|
|
203
212
|
prompt: 'Corrija apenas falhas confirmadas pelo inspetor, preserve o que funciona e repita as provas afetadas. Não amplie o escopo.',
|
|
204
|
-
models: Object.freeze({ free: ['deepseek-v4-flash'], basic: ['deepseek-v4-pro'
|
|
213
|
+
models: Object.freeze({ free: ['deepseek-v4-flash'], basic: ['deepseek-v4-pro'], pro: ['deepseek-v4-pro'] }),
|
|
205
214
|
}),
|
|
206
215
|
vision: Object.freeze({
|
|
207
216
|
prompt: 'Extraia fatos observáveis da imagem e separe leitura, inferência e incerteza. Não invente texto ilegível.',
|
|
@@ -209,7 +218,7 @@ const AGENT_ROLES = Object.freeze({
|
|
|
209
218
|
}),
|
|
210
219
|
document: Object.freeze({
|
|
211
220
|
prompt: 'Produza conteúdo estruturado e use o motor nativo do formato solicitado. Preserve editabilidade e valide o arquivo gerado.',
|
|
212
|
-
models: Object.freeze({ free: ['
|
|
221
|
+
models: Object.freeze({ free: ['gemini-2.5-flash'], basic: ['mimo-v2.5', 'gemini-2.5-flash'], pro: ['mimo-v2.5', 'gemini-2.5-flash'] }),
|
|
213
222
|
}),
|
|
214
223
|
site_builder: Object.freeze({
|
|
215
224
|
prompt: 'Crie ou edite o site completo, responsivo e acessível. Preserve o existente quando editar e valide a URL publicada.',
|
|
@@ -479,7 +488,7 @@ function agentRoleContract(role, plan, options) {
|
|
|
479
488
|
// alteram o projeto. Isto vale inclusive no Free: o limite desse plano e de
|
|
480
489
|
// tentativas/orcamento, nao uma degradacao silenciosa da qualidade do papel.
|
|
481
490
|
const complexCore = options && options.complex === true && ['planner', 'executor', 'corrector'].includes(id)
|
|
482
|
-
? (id === 'planner' ? ['gpt-5.6-luna'
|
|
491
|
+
? (id === 'planner' ? ['gpt-5.6-luna'] : ['deepseek-v4-pro'])
|
|
483
492
|
: null;
|
|
484
493
|
const requested = complexCore || spec.models[planId] || spec.models.free;
|
|
485
494
|
const allowedRaw = complexCore && planId === 'free' ? null : (options && Array.isArray(options.allowedModels) ? options.allowedModels : null);
|
|
@@ -524,7 +533,7 @@ function routeModel(task, reliability) {
|
|
|
524
533
|
|
|
525
534
|
module.exports = {
|
|
526
535
|
INTELLIGENCE_CONTRACT, PRICE_REVISION, MODEL_CATALOG, MODEL_ALIASES, DEFAULT_PRICE,
|
|
527
|
-
MEMORY_TYPES, MEMORY_TRUST, CONTEXT_SOURCES, AGENT_ROLES,
|
|
536
|
+
MEMORY_TYPES, MEMORY_TRUST, CONTEXT_SOURCES, OFFICIAL_AUTOMATIC_TEAM, AGENT_ROLES,
|
|
528
537
|
normalizeModelId, modelInfo, legacyPriceMap, normalizeUsage, estimateCostUsd, catalogFreshness,
|
|
529
538
|
createContextLedger, createMemoryRecord, scoreMemoryRecord, createHandoff, cleanOperationalText, buildOperationalSummary,
|
|
530
539
|
normalizeAgentPlan, agentRoleContract, routeModel,
|