terminal-smart-cli 0.97.1 → 0.97.2
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/lib/agent.js +15 -6
- package/lib/meta.js +6 -6
- package/lib/router.js +1 -1
- package/package.json +1 -1
package/lib/agent.js
CHANGED
|
@@ -148,7 +148,7 @@ async function llm({ baseUrl, key, messages, model, signalMs = 180000, noTools =
|
|
|
148
148
|
throw new ApiError(_em, { status: res.status, code: (j && j.code) || (_cap ? 'no_credits' : '') });
|
|
149
149
|
}
|
|
150
150
|
const ch = (j.choices && j.choices[0]) || {};
|
|
151
|
-
return { msg: ch.message || { content: '' }, usage: j.usage || {}, model: j.model || 'smart' };
|
|
151
|
+
return { msg: ch.message || { content: '' }, usage: j.usage || {}, model: j.model || 'smart', billing: j.ts_billing || null };
|
|
152
152
|
}, { tries: 4, baseMs: 800, onRetry });
|
|
153
153
|
}
|
|
154
154
|
|
|
@@ -202,13 +202,17 @@ async function _subAgent({ task, k, model, cwd, lang, onStep }) {
|
|
|
202
202
|
: 'You are a READ-ONLY exploration SUB-AGENT. Investigate by reading/listing/searching files and return a SHORT objective summary with the facts and paths that matter. Do NOT edit/create/run anything. When you have the answer, write the summary as text (no more tool calls).')
|
|
203
203
|
+ `\nDIRETÓRIO DE TRABALHO: ${cwd}`;
|
|
204
204
|
let msgs = [{ role: 'system', content: sys }, { role: 'user', content: String(task || '') }];
|
|
205
|
-
let out = '', tin = 0, tout = 0, tcach = 0;
|
|
206
|
-
const _acc = (u) => {
|
|
205
|
+
let out = '', tin = 0, tout = 0, tcach = 0, billed = 0;
|
|
206
|
+
const _acc = (u, billing) => {
|
|
207
|
+
tin += u.prompt_tokens || 0; tout += u.completion_tokens || 0;
|
|
208
|
+
tcach += (u.prompt_tokens_details && u.prompt_tokens_details.cached_tokens) || u.cached_tokens || 0;
|
|
209
|
+
billed += (billing && billing.charged) || 0;
|
|
210
|
+
};
|
|
207
211
|
for (let i = 0; i < 8; i++) {
|
|
208
212
|
let r;
|
|
209
213
|
try { r = await llm({ baseUrl: k.baseUrl, key: k.key, messages: msgs, model, toolsOverride: roTools }); }
|
|
210
214
|
catch (e) { if (e instanceof ApiError && (e.code === 'no_credits' || e.status === 402)) throw e; break; } // teto de IA → propaga (CTA); transitório → para
|
|
211
|
-
_acc(r.usage || {});
|
|
215
|
+
_acc(r.usage || {}, r.billing);
|
|
212
216
|
const tcs = r.msg.tool_calls || [];
|
|
213
217
|
if (!tcs.length) { out = String(r.msg.content || '').replace(/<think>[\s\S]*?<\/think>/gi, '').trim(); break; }
|
|
214
218
|
msgs.push({ role: 'assistant', content: r.msg.content || '', tool_calls: tcs });
|
|
@@ -226,11 +230,11 @@ async function _subAgent({ task, k, model, cwd, lang, onStep }) {
|
|
|
226
230
|
const pedido = lang !== 'en' ? 'PARE de usar ferramentas. Escreva agora um RESUMO curto do que você descobriu até aqui (fatos e caminhos).' : 'STOP using tools. Write a SHORT summary of what you found so far (facts and paths).';
|
|
227
231
|
try {
|
|
228
232
|
const r = await llm({ baseUrl: k.baseUrl, key: k.key, messages: [...msgs, { role: 'user', content: pedido }], model, noTools: true, signalMs: 60000 });
|
|
229
|
-
_acc(r.usage || {});
|
|
233
|
+
_acc(r.usage || {}, r.billing);
|
|
230
234
|
out = String(r.msg.content || '').replace(/<think>[\s\S]*?<\/think>/gi, '').trim();
|
|
231
235
|
} catch (_) {}
|
|
232
236
|
}
|
|
233
|
-
return { resumo: out || (lang !== 'en' ? '(o sub-agente não produziu um resumo)' : '(sub-agent produced no summary)'), _tin: tin, _tout: tout, _tcach: tcach };
|
|
237
|
+
return { resumo: out || (lang !== 'en' ? '(o sub-agente não produziu um resumo)' : '(sub-agent produced no summary)'), _tin: tin, _tout: tout, _tcach: tcach, _billed: billed };
|
|
234
238
|
}
|
|
235
239
|
|
|
236
240
|
// Aprovação remota via Telegram (modo --yes): envia o pedido e faz poll até
|
|
@@ -536,6 +540,7 @@ async function run(task, opts = {}) {
|
|
|
536
540
|
const r = await llm({ baseUrl: k.baseUrl, key: k.key, model: selectedModel, noTools: true, signalMs: 60000, messages: [{ role: 'system', content: sys }, { role: 'user', content: lines }] });
|
|
537
541
|
const u = r.usage || {};
|
|
538
542
|
acc.inTok += u.prompt_tokens || 0; acc.outTok += u.completion_tokens || 0;
|
|
543
|
+
charged += (r.billing && r.billing.charged) || 0;
|
|
539
544
|
resumo = String(r.msg.content || '').replace(/<think>[\s\S]*?<\/think>/gi, '').trim().slice(0, 6000);
|
|
540
545
|
} catch (_) {}
|
|
541
546
|
if (!resumo) resumo = lang !== 'en'
|
|
@@ -551,6 +556,7 @@ async function run(task, opts = {}) {
|
|
|
551
556
|
// cobrança Smart Credits (best-effort — o teto da sk-hub já protege no gateway)
|
|
552
557
|
const _bill = async () => {
|
|
553
558
|
if (acc.inTok + acc.outTok <= 0) return;
|
|
559
|
+
if (k.billingAuthoritative) return;
|
|
554
560
|
try {
|
|
555
561
|
const c = await api('/api/credit/charge', { method: 'POST', token, body: { model: usedModel, inTok: acc.inTok, outTok: acc.outTok, cachedTok: acc.cachedTok } });
|
|
556
562
|
charged = (c && c.charged) || 0;
|
|
@@ -581,6 +587,7 @@ async function run(task, opts = {}) {
|
|
|
581
587
|
}
|
|
582
588
|
const u = r.usage || {};
|
|
583
589
|
acc.inTok += u.prompt_tokens || 0; acc.outTok += u.completion_tokens || 0;
|
|
590
|
+
charged += (r.billing && r.billing.charged) || 0;
|
|
584
591
|
acc.cachedTok += (u.prompt_tokens_details && u.prompt_tokens_details.cached_tokens) || u.cached_tokens || 0;
|
|
585
592
|
lastCtx = { used: u.prompt_tokens || estMsgsTok(messages), window: ctxWindow };
|
|
586
593
|
if (r.model) usedModel = r.model;
|
|
@@ -866,6 +873,7 @@ async function run(task, opts = {}) {
|
|
|
866
873
|
onStep({ name: 'explorar', detail: argsShort(name, input) });
|
|
867
874
|
const sub = await _subAgent({ task: input.tarefa || input.pergunta || '', k, model: selectedModel, cwd, lang, onStep });
|
|
868
875
|
acc.inTok += sub._tin; acc.outTok += sub._tout; acc.cachedTok += sub._tcach || 0;
|
|
876
|
+
charged += sub._billed || 0;
|
|
869
877
|
result = { resumo: sub.resumo };
|
|
870
878
|
steps++; _ran = true;
|
|
871
879
|
}
|
|
@@ -951,6 +959,7 @@ async function run(task, opts = {}) {
|
|
|
951
959
|
const r = await llm({ baseUrl: k.baseUrl, key: k.key, messages: [...messages, { role: 'user', content: pedido }], model: selectedModel, noTools: true, signalMs: 60000 });
|
|
952
960
|
const u = r.usage || {};
|
|
953
961
|
acc.inTok += u.prompt_tokens || 0; acc.outTok += u.completion_tokens || 0;
|
|
962
|
+
charged += (r.billing && r.billing.charged) || 0;
|
|
954
963
|
acc.cachedTok += (u.prompt_tokens_details && u.prompt_tokens_details.cached_tokens) || u.cached_tokens || 0;
|
|
955
964
|
if (r.model) usedModel = r.model;
|
|
956
965
|
finalText = String(r.msg.content || '').replace(/<think>[\s\S]*?<\/think>/gi, '').replace(/<think>[\s\S]*$/i, '').trim();
|
package/lib/meta.js
CHANGED
|
@@ -611,8 +611,8 @@ async function _llmVision({ token, model, text, imageB64, images, maxTokens = 70
|
|
|
611
611
|
const j = await res.json().catch(() => null);
|
|
612
612
|
if (!res.ok) _capGuard(res, j);
|
|
613
613
|
const u = j?.usage || {};
|
|
614
|
-
let credits = 0;
|
|
615
|
-
if (u.prompt_tokens) { try { const c = await api('/api/credit/charge', { method: 'POST', token, body: { model, inTok: u.prompt_tokens || 0, outTok: u.completion_tokens || 0 } }); credits = (c && c.charged) || 0; } catch (_) {} }
|
|
614
|
+
let credits = (j?.ts_billing && j.ts_billing.charged) || 0;
|
|
615
|
+
if (u.prompt_tokens && !_key.billingAuthoritative) { try { const c = await api('/api/credit/charge', { method: 'POST', token, body: { model, inTok: u.prompt_tokens || 0, outTok: u.completion_tokens || 0 } }); credits = (c && c.charged) || 0; } catch (_) {} }
|
|
616
616
|
return { text: String(j?.choices?.[0]?.message?.content || '').trim(), credits };
|
|
617
617
|
}
|
|
618
618
|
const _os = require('os');
|
|
@@ -811,9 +811,9 @@ async function _llmJson({ token, system, user, maxTokens = 900 }) {
|
|
|
811
811
|
const j = await res.json().catch(() => null);
|
|
812
812
|
if (!res.ok) _capGuard(res, j);
|
|
813
813
|
const u = j?.usage || {};
|
|
814
|
-
let credits = 0;
|
|
814
|
+
let credits = (j?.ts_billing && j.ts_billing.charged) || 0;
|
|
815
815
|
if (u.prompt_tokens) {
|
|
816
|
-
try { const c = await api('/api/credit/charge', { method: 'POST', token, body: { model: 'gemini-2.5-flash-lite', inTok: u.prompt_tokens || 0, outTok: u.completion_tokens || 0 } }); credits = (c && c.charged) || 0; } catch (_) {}
|
|
816
|
+
if (!_key.billingAuthoritative) { try { const c = await api('/api/credit/charge', { method: 'POST', token, body: { model: 'gemini-2.5-flash-lite', inTok: u.prompt_tokens || 0, outTok: u.completion_tokens || 0 } }); credits = (c && c.charged) || 0; } catch (_) {} }
|
|
817
817
|
}
|
|
818
818
|
return { json: _tolerantJson(String(j?.choices?.[0]?.message?.content || '')), credits };
|
|
819
819
|
}
|
|
@@ -834,8 +834,8 @@ async function _llmText({ token, model, system, user, maxTokens = 1200 }) {
|
|
|
834
834
|
const j = await res.json().catch(() => null);
|
|
835
835
|
if (!res.ok) _capGuard(res, j);
|
|
836
836
|
const u = j?.usage || {};
|
|
837
|
-
let credits = 0;
|
|
838
|
-
if (u.prompt_tokens) { try { const c = await api('/api/credit/charge', { method: 'POST', token, body: { model, inTok: u.prompt_tokens || 0, outTok: u.completion_tokens || 0 } }); credits = (c && c.charged) || 0; } catch (_) {} }
|
|
837
|
+
let credits = (j?.ts_billing && j.ts_billing.charged) || 0;
|
|
838
|
+
if (u.prompt_tokens && !_key.billingAuthoritative) { try { const c = await api('/api/credit/charge', { method: 'POST', token, body: { model, inTok: u.prompt_tokens || 0, outTok: u.completion_tokens || 0 } }); credits = (c && c.charged) || 0; } catch (_) {} }
|
|
839
839
|
return { text: String(j?.choices?.[0]?.message?.content || '').trim(), credits };
|
|
840
840
|
}
|
|
841
841
|
|
package/lib/router.js
CHANGED
|
@@ -79,7 +79,7 @@ async function classify(msg, token) {
|
|
|
79
79
|
const word = String(j?.choices?.[0]?.message?.content || '').toLowerCase();
|
|
80
80
|
// cobra a classificação (mesmo padrão do web-intent) — best-effort
|
|
81
81
|
const u = j?.usage || {};
|
|
82
|
-
if (u.prompt_tokens) api('/api/credit/charge', { method: 'POST', token, body: { model: 'gemini-2.5-flash-lite', inTok: u.prompt_tokens || 0, outTok: u.completion_tokens || 0 } }).catch(() => {});
|
|
82
|
+
if (u.prompt_tokens && !k.billingAuthoritative) api('/api/credit/charge', { method: 'POST', token, body: { model: 'gemini-2.5-flash-lite', inTok: u.prompt_tokens || 0, outTok: u.completion_tokens || 0 } }).catch(() => {});
|
|
83
83
|
if (word.includes('agente')) return 'agente';
|
|
84
84
|
if (word.includes('orquestrar')) return 'run';
|
|
85
85
|
return 'chat';
|