terminal-smart-cli 0.97.57 → 0.97.59
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 +5 -2
- package/lib/agent.js +20 -2
- package/lib/tools.js +9 -1
- package/package.json +2 -2
package/bin/ts.js
CHANGED
|
@@ -243,7 +243,9 @@ async function personalAiCmd(args = []) {
|
|
|
243
243
|
if (sub === 'status') return show(await api('/api/personal-ai/status',{token}));
|
|
244
244
|
if (['usar','use','modo','mode'].includes(sub)) {
|
|
245
245
|
const mode=String(args[1] || '').toLowerCase();
|
|
246
|
-
const state=await api('/api/personal-ai/mode',{method:'POST',token,body:{mode}});
|
|
246
|
+
const state=await api('/api/personal-ai/mode',{method:'POST',token,body:{mode}});
|
|
247
|
+
cfg = config.save({ forceTsCloud: mode === 'automatico' ? true : undefined });
|
|
248
|
+
show(state); return;
|
|
247
249
|
}
|
|
248
250
|
if (['desconectar','disconnect'].includes(sub)) {
|
|
249
251
|
const provider=String(args[1] || '').toLowerCase();
|
|
@@ -1510,7 +1512,7 @@ async function agentCmd(words, { askFn, cwd: cwdIn = null, onCwd = null, maxIter
|
|
|
1510
1512
|
} });
|
|
1511
1513
|
if (shared?.ok && shared.promptBlock) sharedChannelPrompt = shared.promptBlock;
|
|
1512
1514
|
const personalState = await api('/api/personal-ai/status', { token });
|
|
1513
|
-
const personalReady = personalState?.ok && personalState.mode !== 'automatico'
|
|
1515
|
+
const personalReady = !cfg.forceTsCloud && personalState?.ok && personalState.mode !== 'automatico'
|
|
1514
1516
|
&& (personalState.mode === 'chatgpt' ? personalState.chatgpt
|
|
1515
1517
|
: personalState.mode === 'claude' ? personalState.claude
|
|
1516
1518
|
: personalState.chatgpt && personalState.claude);
|
|
@@ -2871,6 +2873,7 @@ async function conectarCmd(words) {
|
|
|
2871
2873
|
// ts conectar nuvem — volta a usar os créditos do TS
|
|
2872
2874
|
if (sub === 'nuvem' || sub === 'cloud' || sub === 'ts') {
|
|
2873
2875
|
keyring.usar(null);
|
|
2876
|
+
cfg = config.save({ forceTsCloud: true });
|
|
2874
2877
|
console.log(' ' + C.ok('✔ ') + (en ? 'back to TS Cloud (your credits).' : 'de volta ao TS Cloud (seus créditos).'));
|
|
2875
2878
|
return;
|
|
2876
2879
|
}
|
package/lib/agent.js
CHANGED
|
@@ -581,7 +581,11 @@ RULES:
|
|
|
581
581
|
- RESPONSE STYLE (important): write in NATURAL, plain language, like explaining to a person — avoid jargon and internal technical detail that doesn't matter to someone who just wants the result. NO decorative emojis (no 🎮📡🔬✅❌ etc.); to mark pass/fail use ONLY the symbols ✓ (worked) or ✗ (failed). Short sentences; commands/code/paths always in a code block. Don't repeat what already showed up in the steps above.
|
|
582
582
|
- ALWAYS end with a short summary: what was done, the result, and paths of created/changed files.
|
|
583
583
|
- Answer in the user's language.`);
|
|
584
|
-
|
|
584
|
+
// os.userInfo pode falhar em hosts sob pressão de memória. O contexto da
|
|
585
|
+
// máquina é auxiliar; nunca deve impedir uma missão de continuar.
|
|
586
|
+
let userName = process.env.USERNAME || process.env.USER || 'desconhecido';
|
|
587
|
+
try { userName = os.userInfo().username || userName; } catch (_) {}
|
|
588
|
+
const volatile = `\n\nMáquina: ${process.platform} ${os.release()} · host ${os.hostname()} · user ${userName}`
|
|
585
589
|
+ `\nDIRETÓRIO DE TRABALHO (obrigatório): ${wd}`;
|
|
586
590
|
return stable + volatile;
|
|
587
591
|
}
|
|
@@ -831,6 +835,19 @@ function loopSig(name, input) {
|
|
|
831
835
|
}
|
|
832
836
|
|
|
833
837
|
const FILE_MUTATORS = new Set(['escrever_arquivo', 'editar_arquivo', 'editar_documento', 'editar_planilha']);
|
|
838
|
+
function normalizeFileToolInput(name, input, { cwd = process.cwd(), exclusiveTargets = [] } = {}) {
|
|
839
|
+
const out = input && typeof input === 'object' ? Object.assign({}, input) : {};
|
|
840
|
+
if (!FILE_MUTATORS.has(name)) return out;
|
|
841
|
+
const alias = out.caminho || out.path || out.arquivo || out.file || out.filename;
|
|
842
|
+
if (alias && String(alias).trim() && String(alias).trim() !== '.') {
|
|
843
|
+
out.caminho = alias;
|
|
844
|
+
return out;
|
|
845
|
+
}
|
|
846
|
+
if (exclusiveTargets.length === 1) {
|
|
847
|
+
out.caminho = path.relative(cwd, exclusiveTargets[0]) || exclusiveTargets[0];
|
|
848
|
+
}
|
|
849
|
+
return out;
|
|
850
|
+
}
|
|
834
851
|
function mutationBatchConflicts(toolCalls, cwd) {
|
|
835
852
|
const groups = new Map();
|
|
836
853
|
for (const tc of (Array.isArray(toolCalls) ? toolCalls : [])) {
|
|
@@ -1808,6 +1825,7 @@ async function run(task, opts = {}) {
|
|
|
1808
1825
|
for (const tc of tcs) {
|
|
1809
1826
|
const name = (tc.function && tc.function.name) || '';
|
|
1810
1827
|
let input = {}; try { input = JSON.parse((tc.function && tc.function.arguments) || '{}'); } catch (_) {}
|
|
1828
|
+
input = normalizeFileToolInput(name, input, { cwd, exclusiveTargets: _exclusiveFileTargets });
|
|
1811
1829
|
let result;
|
|
1812
1830
|
let _cachedContent = '';
|
|
1813
1831
|
let _ran = false; // true só quando uma ferramenta REALMENTE executou (não gate/bloqueio) → status ✓/✗
|
|
@@ -2510,4 +2528,4 @@ async function run(task, opts = {}) {
|
|
|
2510
2528
|
return { text: finalText, steps, credits: charged + _visionCredits, tokens: acc, model: usedModel, actions, messages, cwd, context: lastCtx, toolErrors: _toolErrs, lastToolError: _lastErr, guard: guardStopped, completion, verification: verifyReport, observability: _observability, report: _finalReport, orchestration: { plan: _planDecision, roles: _roleTrace, inspections: _inspectionTrace, phaseBudgets: _phaseBudgets, phaseUsage: _phaseUsage }, missionCache: _missionCache.stats() };
|
|
2511
2529
|
}
|
|
2512
2530
|
|
|
2513
|
-
module.exports = { run, llm, _test: { systemPrompt, projectBrief, inspectionGateDecision, independentInspectorDecision, candidateAdmitsIncomplete, isInspectionCommand, parseStageJson, materialDecisionPreflight, actionExpectedForTask, requiresActionEvidence, shouldRunPlanner, isComplexTask, validatePlannerDecision, planUpgradeLimit, commandRecoveryHint, windowsUnsupportedUnixCommand, mutationBatchConflicts, normalizePlannerDecision, normalizeInspectorDecision, winFor, estMsgsTok, COMPACT_AT, KEEP_TAIL, loopSig, isCycle, loopDecision, decideApproval, failureFingerprint, missionGuardDecision, missionBudgetSuggestion, missionTokenCap, missionTimeCap, modelCallWindow, modelCallCap, explicitExclusiveFileTargets, executorFallbackChain, forcedModelMismatch, isTransientModelError, executorCompletionCap, completionGateDecision, canCloseFromProofs, taskScopedToolDefs, explicitTaskWorkdir, restrictedGatewayDecision, validarModeloByok, scopeToolDefs, parseTextToolCalls, isUntrustedToolOutput, untrustedToolEnvelope, isRemoteDeployCommand, browserApprovalRequest } };
|
|
2531
|
+
module.exports = { run, llm, _test: { systemPrompt, projectBrief, inspectionGateDecision, independentInspectorDecision, candidateAdmitsIncomplete, isInspectionCommand, parseStageJson, materialDecisionPreflight, actionExpectedForTask, requiresActionEvidence, shouldRunPlanner, isComplexTask, validatePlannerDecision, planUpgradeLimit, commandRecoveryHint, windowsUnsupportedUnixCommand, mutationBatchConflicts, normalizeFileToolInput, normalizePlannerDecision, normalizeInspectorDecision, winFor, estMsgsTok, COMPACT_AT, KEEP_TAIL, loopSig, isCycle, loopDecision, decideApproval, failureFingerprint, missionGuardDecision, missionBudgetSuggestion, missionTokenCap, missionTimeCap, modelCallWindow, modelCallCap, explicitExclusiveFileTargets, executorFallbackChain, forcedModelMismatch, isTransientModelError, executorCompletionCap, completionGateDecision, canCloseFromProofs, taskScopedToolDefs, explicitTaskWorkdir, restrictedGatewayDecision, validarModeloByok, scopeToolDefs, parseTextToolCalls, isUntrustedToolOutput, untrustedToolEnvelope, isRemoteDeployCommand, browserApprovalRequest } };
|
package/lib/tools.js
CHANGED
|
@@ -799,6 +799,9 @@ async function execute(name, input, opts = {}) {
|
|
|
799
799
|
return { total: resultados.length, resultados, aviso: resultados.length < arquivos.length ? 'Lote limitado pelo teto de contexto; peca os trechos restantes em outro lote.' : undefined };
|
|
800
800
|
}
|
|
801
801
|
case 'escrever_arquivo': {
|
|
802
|
+
if (!input.caminho || !String(input.caminho).trim() || String(input.caminho).trim() === '.') {
|
|
803
|
+
return { erro: 'Informe o caminho completo do ARQUIVO em caminho (ex.: docs/relatorio.md). O diretório de trabalho sozinho não é um arquivo.' };
|
|
804
|
+
}
|
|
802
805
|
let p = _abs(input.caminho, baseDir);
|
|
803
806
|
{ const g = _guardTsHome(p); if (g) return { erro: g }; }
|
|
804
807
|
// Confinamento (missões): modelos fracos inventam pastas absolutas
|
|
@@ -832,6 +835,9 @@ async function execute(name, input, opts = {}) {
|
|
|
832
835
|
} finally { held.lock.release(); }
|
|
833
836
|
}
|
|
834
837
|
case 'editar_arquivo': {
|
|
838
|
+
if (!input.caminho || !String(input.caminho).trim() || String(input.caminho).trim() === '.') {
|
|
839
|
+
return { erro: 'Informe o caminho completo do ARQUIVO em caminho (ex.: docs/relatorio.md). O diretório de trabalho sozinho não é um arquivo.' };
|
|
840
|
+
}
|
|
835
841
|
// Edição por ÂNCORA (ideia do hashline do OMYP): troca SÓ o trecho buscado, sem
|
|
836
842
|
// reescrever o arquivo — modelo barato edita com precisão, gasta menos tokens de
|
|
837
843
|
// saída e não corre o risco de "perder" o resto do arquivo num rewrite.
|
|
@@ -972,8 +978,10 @@ async function execute(name, input, opts = {}) {
|
|
|
972
978
|
} catch (e) { return { erro: 'busca falhou: ' + String((e && e.message) || e).slice(0, 200) }; }
|
|
973
979
|
}
|
|
974
980
|
case 'info_sistema': {
|
|
981
|
+
let usuario = process.env.USERNAME || process.env.USER || 'desconhecido';
|
|
982
|
+
try { usuario = os.userInfo().username || usuario; } catch (_) {}
|
|
975
983
|
return {
|
|
976
|
-
so: `${process.platform} ${os.release()}`, host: os.hostname(), usuario
|
|
984
|
+
so: `${process.platform} ${os.release()}`, host: os.hostname(), usuario,
|
|
977
985
|
diretorio_atual: baseDir, home: os.homedir(),
|
|
978
986
|
cpus: os.cpus().length, mem_total_gb: +(os.totalmem() / 1e9).toFixed(1), mem_livre_gb: +(os.freemem() / 1e9).toFixed(1),
|
|
979
987
|
uptime_h: +(os.uptime() / 3600).toFixed(1), node: process.version,
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "terminal-smart-cli",
|
|
3
|
-
"version": "0.97.
|
|
3
|
+
"version": "0.97.59",
|
|
4
4
|
"description": "Terminal Smart no seu terminal — pergunte, analise logs por pipe e orquestre agentes de IA. Comando: ts",
|
|
5
5
|
"bin": {
|
|
6
6
|
"ts": "bin/ts.js"
|
|
7
7
|
},
|
|
8
8
|
"scripts": {
|
|
9
|
-
"test": "node test/durable-operation.test.js && node test/mission-tool-cache.test.js && node test/content-quality-runtime-files.test.js && node test/personal-agent-llm.test.js && node test/personal-inspector-efficiency.test.js && node test/personal-inspector-context.test.js && node test/planner-fallback.test.js"
|
|
9
|
+
"test": "node test/durable-operation.test.js && node test/mission-tool-cache.test.js && node test/content-quality-runtime-files.test.js && node test/personal-agent-llm.test.js && node test/personal-inspector-efficiency.test.js && node test/personal-inspector-context.test.js && node test/planner-fallback.test.js && node test/cli-agent-regressions.test.js"
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
12
|
"bin",
|