clawfast 1.0.3 → 2.0.1
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 +4 -4
- package/dist/clawfast.cjs +1584 -629
- package/package.json +1 -1
package/dist/clawfast.cjs
CHANGED
|
@@ -86,8 +86,8 @@ var require_main = __commonJS({
|
|
|
86
86
|
"../node_modules/.pnpm/dotenv@17.4.2/node_modules/dotenv/lib/main.js"(exports2, module2) {
|
|
87
87
|
"use strict";
|
|
88
88
|
var fs6 = require("fs");
|
|
89
|
-
var
|
|
90
|
-
var
|
|
89
|
+
var path10 = require("path");
|
|
90
|
+
var os7 = require("os");
|
|
91
91
|
var crypto2 = require("crypto");
|
|
92
92
|
var TIPS = [
|
|
93
93
|
"\u25C8 encrypted .env [www.dotenvx.com]",
|
|
@@ -225,7 +225,7 @@ var require_main = __commonJS({
|
|
|
225
225
|
possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`;
|
|
226
226
|
}
|
|
227
227
|
} else {
|
|
228
|
-
possibleVaultPath =
|
|
228
|
+
possibleVaultPath = path10.resolve(process.cwd(), ".env.vault");
|
|
229
229
|
}
|
|
230
230
|
if (fs6.existsSync(possibleVaultPath)) {
|
|
231
231
|
return possibleVaultPath;
|
|
@@ -233,7 +233,7 @@ var require_main = __commonJS({
|
|
|
233
233
|
return null;
|
|
234
234
|
}
|
|
235
235
|
function _resolveHome(envPath) {
|
|
236
|
-
return envPath[0] === "~" ?
|
|
236
|
+
return envPath[0] === "~" ? path10.join(os7.homedir(), envPath.slice(1)) : envPath;
|
|
237
237
|
}
|
|
238
238
|
function _configVault(options) {
|
|
239
239
|
const debug = parseBoolean(process.env.DOTENV_CONFIG_DEBUG || options && options.debug);
|
|
@@ -250,7 +250,7 @@ var require_main = __commonJS({
|
|
|
250
250
|
return { parsed };
|
|
251
251
|
}
|
|
252
252
|
function configDotenv(options) {
|
|
253
|
-
const dotenvPath =
|
|
253
|
+
const dotenvPath = path10.resolve(process.cwd(), ".env");
|
|
254
254
|
let encoding = "utf8";
|
|
255
255
|
let processEnv = process.env;
|
|
256
256
|
if (options && options.processEnv != null) {
|
|
@@ -278,13 +278,13 @@ var require_main = __commonJS({
|
|
|
278
278
|
}
|
|
279
279
|
let lastError;
|
|
280
280
|
const parsedAll = {};
|
|
281
|
-
for (const
|
|
281
|
+
for (const path11 of optionPaths) {
|
|
282
282
|
try {
|
|
283
|
-
const parsed = DotenvModule.parse(fs6.readFileSync(
|
|
283
|
+
const parsed = DotenvModule.parse(fs6.readFileSync(path11, { encoding }));
|
|
284
284
|
DotenvModule.populate(parsedAll, parsed, options);
|
|
285
285
|
} catch (e) {
|
|
286
286
|
if (debug) {
|
|
287
|
-
_debug(`failed to load ${
|
|
287
|
+
_debug(`failed to load ${path11} ${e.message}`);
|
|
288
288
|
}
|
|
289
289
|
lastError = e;
|
|
290
290
|
}
|
|
@@ -297,7 +297,7 @@ var require_main = __commonJS({
|
|
|
297
297
|
const shortPaths = [];
|
|
298
298
|
for (const filePath of optionPaths) {
|
|
299
299
|
try {
|
|
300
|
-
const relative2 =
|
|
300
|
+
const relative2 = path10.relative(process.cwd(), filePath);
|
|
301
301
|
shortPaths.push(relative2);
|
|
302
302
|
} catch (e) {
|
|
303
303
|
if (debug) {
|
|
@@ -426,6 +426,52 @@ ${line}
|
|
|
426
426
|
}
|
|
427
427
|
import_node_fs.default.writeFileSync(filePath, content, { encoding: "utf8", mode: 384 });
|
|
428
428
|
}
|
|
429
|
+
function fileDefines(filePath, key) {
|
|
430
|
+
try {
|
|
431
|
+
const content = import_node_fs.default.readFileSync(filePath, "utf8");
|
|
432
|
+
return new RegExp(`^${key}=`, "m").test(content);
|
|
433
|
+
} catch {
|
|
434
|
+
return false;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
function swapNvidiaKey(key) {
|
|
438
|
+
const local = import_node_path.default.resolve(process.cwd(), ".env.local");
|
|
439
|
+
const target = fileDefines(local, "NVIDIA_API_KEY") ? local : clawfastEnvPath();
|
|
440
|
+
setEnvVar(target, "NVIDIA_API_KEY", key);
|
|
441
|
+
process.env.NVIDIA_API_KEY = key;
|
|
442
|
+
return target;
|
|
443
|
+
}
|
|
444
|
+
async function testNvidiaKey(key) {
|
|
445
|
+
const baseURL = process.env.NVIDIA_BASE_URL || "https://integrate.api.nvidia.com/v1";
|
|
446
|
+
try {
|
|
447
|
+
const res = await fetch(`${baseURL.replace(/\/$/, "")}/chat/completions`, {
|
|
448
|
+
method: "POST",
|
|
449
|
+
headers: {
|
|
450
|
+
Authorization: `Bearer ${key}`,
|
|
451
|
+
"Content-Type": "application/json"
|
|
452
|
+
},
|
|
453
|
+
body: JSON.stringify({
|
|
454
|
+
model: "openai/gpt-oss-120b",
|
|
455
|
+
messages: [{ role: "user", content: "hi" }],
|
|
456
|
+
max_tokens: 1
|
|
457
|
+
})
|
|
458
|
+
});
|
|
459
|
+
if (res.ok) return { ok: true, status: res.status, detail: "OK" };
|
|
460
|
+
let detail = res.statusText || `HTTP ${res.status}`;
|
|
461
|
+
try {
|
|
462
|
+
const body = await res.json();
|
|
463
|
+
detail = body.detail || body.error?.message || body.title || detail;
|
|
464
|
+
} catch {
|
|
465
|
+
}
|
|
466
|
+
return { ok: false, status: res.status, detail };
|
|
467
|
+
} catch (err) {
|
|
468
|
+
return {
|
|
469
|
+
ok: false,
|
|
470
|
+
status: 0,
|
|
471
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
}
|
|
429
475
|
function promptLine(question) {
|
|
430
476
|
const rl = import_node_readline.default.createInterface({
|
|
431
477
|
input: process.stdin,
|
|
@@ -502,7 +548,7 @@ var clawfastVersion, isDevVersion, isNewerVersion;
|
|
|
502
548
|
var init_version = __esm({
|
|
503
549
|
"src/version.ts"() {
|
|
504
550
|
"use strict";
|
|
505
|
-
clawfastVersion = () => true ? "
|
|
551
|
+
clawfastVersion = () => true ? "2.0.1" : "0.0.0-dev";
|
|
506
552
|
isDevVersion = () => clawfastVersion().includes("-dev");
|
|
507
553
|
isNewerVersion = (a, b) => {
|
|
508
554
|
const parse3 = (v) => v.split("-")[0].split(".").map((n) => Number.parseInt(n, 10) || 0);
|
|
@@ -699,14 +745,14 @@ var init_paste_input = __esm({
|
|
|
699
745
|
/** Replace any paste chips in a submitted line with their real content. */
|
|
700
746
|
expand(line) {
|
|
701
747
|
if (this.pastes.size === 0) return line;
|
|
702
|
-
let
|
|
748
|
+
let out3 = line;
|
|
703
749
|
for (const [chip, content] of this.pastes) {
|
|
704
|
-
if (
|
|
705
|
-
|
|
750
|
+
if (out3.includes(chip)) {
|
|
751
|
+
out3 = out3.split(chip).join(content);
|
|
706
752
|
this.pastes.delete(chip);
|
|
707
753
|
}
|
|
708
754
|
}
|
|
709
|
-
return
|
|
755
|
+
return out3;
|
|
710
756
|
}
|
|
711
757
|
/** How many captured pastes are still waiting to be expanded. */
|
|
712
758
|
pendingCount() {
|
|
@@ -869,19 +915,153 @@ var init_skills = __esm({
|
|
|
869
915
|
}
|
|
870
916
|
});
|
|
871
917
|
|
|
918
|
+
// src/ui.ts
|
|
919
|
+
var ui_exports = {};
|
|
920
|
+
__export(ui_exports, {
|
|
921
|
+
C: () => C2,
|
|
922
|
+
agentHeader: () => agentHeader,
|
|
923
|
+
buildBanner: () => buildBanner,
|
|
924
|
+
shellPrompt: () => shellPrompt,
|
|
925
|
+
shortCwd: () => shortCwd,
|
|
926
|
+
ui: () => ui,
|
|
927
|
+
vlen: () => vlen
|
|
928
|
+
});
|
|
929
|
+
function shortCwd() {
|
|
930
|
+
const cwd = process.cwd();
|
|
931
|
+
const home = import_node_os2.default.homedir();
|
|
932
|
+
const rel = cwd.startsWith(home) ? "~" + cwd.slice(home.length) : cwd;
|
|
933
|
+
const norm = rel.replace(/\\/g, "/");
|
|
934
|
+
if (norm.length <= 30) return norm;
|
|
935
|
+
const parts = norm.split("/");
|
|
936
|
+
return parts.length > 3 ? `${parts[0]}/\u2026/${parts[parts.length - 1]}` : norm.slice(-30);
|
|
937
|
+
}
|
|
938
|
+
function asciiTitle(text2) {
|
|
939
|
+
const rows = 6;
|
|
940
|
+
const out3 = [];
|
|
941
|
+
for (let r = 0; r < rows; r++) {
|
|
942
|
+
out3.push(
|
|
943
|
+
[...text2].map((ch) => GLYPHS[ch] ? GLYPHS[ch][r] : " ").join(" ")
|
|
944
|
+
);
|
|
945
|
+
}
|
|
946
|
+
return out3;
|
|
947
|
+
}
|
|
948
|
+
function buildBanner(_systemPromptChars, version3 = "1") {
|
|
949
|
+
const user = (import_node_os2.default.userInfo().username || "hacker").toLowerCase();
|
|
950
|
+
const host = (import_node_os2.default.hostname() || "localhost").split(".")[0].toLowerCase();
|
|
951
|
+
const art = asciiTitle("CLAWFAST");
|
|
952
|
+
const artW = vlen(art[0]);
|
|
953
|
+
const slogan = "Com o clawfast voc\xEA faz tudo";
|
|
954
|
+
const header = [
|
|
955
|
+
"",
|
|
956
|
+
...art.map((line) => `${C2.greenB}${C2.bold}${line}${C2.reset}`),
|
|
957
|
+
"",
|
|
958
|
+
`${C2.cyanB}${C2.bold}${center(slogan, artW)}${C2.reset}`,
|
|
959
|
+
""
|
|
960
|
+
];
|
|
961
|
+
const info = [
|
|
962
|
+
{ text: "" },
|
|
963
|
+
{ text: `Bem-vindo de volta, ${user}!`, accent: true },
|
|
964
|
+
{ text: "" },
|
|
965
|
+
{ text: "clawfast usa a pasta SPRIT/ para criar" },
|
|
966
|
+
{ text: "arquivos, scripts e tudo mais." },
|
|
967
|
+
{ text: "" },
|
|
968
|
+
{ text: `${user}@${host} \xB7 sem limites` },
|
|
969
|
+
{ text: shortCwd() },
|
|
970
|
+
{ text: "" }
|
|
971
|
+
];
|
|
972
|
+
const title = `clawfast v${version3}`;
|
|
973
|
+
const topFill = "\u2500".repeat(Math.max(0, BOX_W - vlen(title) - 5));
|
|
974
|
+
const top = `${C2.green}\u256D\u2500 ${C2.greenB}${C2.bold}${title}${C2.reset}${C2.green} ${topFill}\u256E${C2.reset}`;
|
|
975
|
+
const bottom = `${C2.green}\u2570${"\u2500".repeat(BOX_W - 2)}\u256F${C2.reset}`;
|
|
976
|
+
const cardLines = info.map(({ text: text2, accent }) => {
|
|
977
|
+
const color = accent ? `${C2.greenB}${C2.bold}` : C2.green;
|
|
978
|
+
const body = `${color}${padEndV(text2, INNER)}${C2.reset}`;
|
|
979
|
+
return `${C2.green}\u2502 ${C2.reset}${body}${C2.green} \u2502${C2.reset}`;
|
|
980
|
+
});
|
|
981
|
+
const card = [top, ...cardLines, bottom];
|
|
982
|
+
return "\n" + [...header, ...card].join("\n") + "\n";
|
|
983
|
+
}
|
|
984
|
+
function shellPrompt() {
|
|
985
|
+
const user = (import_node_os2.default.userInfo().username || "hacker").toLowerCase();
|
|
986
|
+
const host = (import_node_os2.default.hostname() || "localhost").split(".")[0].toLowerCase();
|
|
987
|
+
const W = 52;
|
|
988
|
+
const label = " \u2709 mensagem ";
|
|
989
|
+
const topFill = "\u2500".repeat(Math.max(0, W - vlen(label) - 3));
|
|
990
|
+
const top = `${C2.green}\u256D\u2500${C2.greenB}${C2.bold}${label}${C2.reset}${C2.green}${topFill}\u256E${C2.reset}`;
|
|
991
|
+
const id = `${user}\u327F${host} \xB7 ${shortCwd()}`;
|
|
992
|
+
const mid = `${C2.green}\u2502 ${C2.dim}${id}${C2.reset}`;
|
|
993
|
+
const bottom = `${C2.green}\u2570\u2500${C2.greenB}${C2.bold}\u276F${C2.reset} `;
|
|
994
|
+
return `
|
|
995
|
+
${top}
|
|
996
|
+
${mid}
|
|
997
|
+
${bottom}`;
|
|
998
|
+
}
|
|
999
|
+
function agentHeader() {
|
|
1000
|
+
return `${C2.magenta}\u256D\u2500 clawfast ${"\u2500".repeat(20)}${C2.reset}
|
|
1001
|
+
`;
|
|
1002
|
+
}
|
|
1003
|
+
var import_node_os2, ESC, C2, INNER, BOX_W, vlen, padEndV, center, GLYPHS, ui;
|
|
1004
|
+
var init_ui = __esm({
|
|
1005
|
+
"src/ui.ts"() {
|
|
1006
|
+
"use strict";
|
|
1007
|
+
import_node_os2 = __toESM(require("node:os"));
|
|
1008
|
+
ESC = "\x1B[";
|
|
1009
|
+
C2 = {
|
|
1010
|
+
reset: `${ESC}0m`,
|
|
1011
|
+
bold: `${ESC}1m`,
|
|
1012
|
+
dim: `${ESC}90m`,
|
|
1013
|
+
green: `${ESC}32m`,
|
|
1014
|
+
greenB: `${ESC}92m`,
|
|
1015
|
+
cyan: `${ESC}36m`,
|
|
1016
|
+
cyanB: `${ESC}96m`,
|
|
1017
|
+
magenta: `${ESC}95m`,
|
|
1018
|
+
yellow: `${ESC}93m`,
|
|
1019
|
+
red: `${ESC}91m`
|
|
1020
|
+
};
|
|
1021
|
+
INNER = 42;
|
|
1022
|
+
BOX_W = INNER + 4;
|
|
1023
|
+
vlen = (s) => [...s.replace(/\x1b\[[0-9;]*m/g, "")].length;
|
|
1024
|
+
padEndV = (s, w) => s + " ".repeat(Math.max(0, w - vlen(s)));
|
|
1025
|
+
center = (s, w) => {
|
|
1026
|
+
const pad = Math.max(0, w - vlen(s));
|
|
1027
|
+
const left = Math.floor(pad / 2);
|
|
1028
|
+
return " ".repeat(left) + s + " ".repeat(pad - left);
|
|
1029
|
+
};
|
|
1030
|
+
GLYPHS = {
|
|
1031
|
+
C: [" \u2588\u2588\u2588\u2588\u2588", "\u2588\u2588 ", "\u2588\u2588 ", "\u2588\u2588 ", "\u2588\u2588 ", " \u2588\u2588\u2588\u2588\u2588"],
|
|
1032
|
+
L: ["\u2588\u2588 ", "\u2588\u2588 ", "\u2588\u2588 ", "\u2588\u2588 ", "\u2588\u2588 ", "\u2588\u2588\u2588\u2588\u2588\u2588"],
|
|
1033
|
+
A: [" \u2588\u2588\u2588\u2588 ", "\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588", "\u2588\u2588\u2588\u2588\u2588\u2588", "\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588"],
|
|
1034
|
+
W: ["\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588 \u2588\u2588", "\u2588\u2588 \u2588 \u2588\u2588", "\u2588\u2588\u2588\u2588\u2588\u2588\u2588", " \u2588\u2588 \u2588\u2588 "],
|
|
1035
|
+
F: ["\u2588\u2588\u2588\u2588\u2588\u2588", "\u2588\u2588 ", "\u2588\u2588\u2588\u2588\u2588 ", "\u2588\u2588 ", "\u2588\u2588 ", "\u2588\u2588 "],
|
|
1036
|
+
S: [" \u2588\u2588\u2588\u2588\u2588", "\u2588\u2588 ", " \u2588\u2588\u2588\u2588 ", " \u2588\u2588", " \u2588\u2588", "\u2588\u2588\u2588\u2588\u2588 "],
|
|
1037
|
+
T: ["\u2588\u2588\u2588\u2588\u2588\u2588", " \u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588 "]
|
|
1038
|
+
};
|
|
1039
|
+
ui = { C: C2, buildBanner, shellPrompt, agentHeader };
|
|
1040
|
+
}
|
|
1041
|
+
});
|
|
1042
|
+
|
|
872
1043
|
// src/news.ts
|
|
873
|
-
var import_node_fs4, import_node_path4, NEWS, latestNewsVersion, renderNews, stateFile, readState, writeState, consumePostUpdateLaunch;
|
|
1044
|
+
var import_node_fs4, import_node_path4, NEWS, latestNewsVersion, wrapText, renderNews, stateFile, readState, writeState, consumePostUpdateLaunch;
|
|
874
1045
|
var init_news = __esm({
|
|
875
1046
|
"src/news.ts"() {
|
|
876
1047
|
"use strict";
|
|
877
1048
|
import_node_fs4 = __toESM(require("node:fs"));
|
|
878
1049
|
import_node_path4 = __toESM(require("node:path"));
|
|
879
1050
|
init_config();
|
|
1051
|
+
init_ui();
|
|
880
1052
|
NEWS = {
|
|
1053
|
+
"2.0.0": [
|
|
1054
|
+
'Modo ANALISE DE PROJETO (somente leitura): peca "analise/varredura/auditoria do meu projeto" e o clawfast troca sozinho para um auditor dedicado \u2014 sem /comando. Diga "modo normal" para sair.',
|
|
1055
|
+
"Ele mapeia o projeto inteiro: grafo de imports nos dois sentidos (o que cada arquivo importa E quem o importa), achando imports quebrados, ciclos e arquivos orfaos.",
|
|
1056
|
+
"Motor hibrido (estado da arte): orquestra ferramentas deterministicas (ast-grep, semgrep, osv-scanner v2, gitleaks, madge, ctags, rg) para o trabalho pesado e usa o modelo so para o taint cross-module e a validacao. Roda `--preflight` e instala o que falta; cai em fallback (Python + rg) quando uma ferramenta nao existe.",
|
|
1057
|
+
"Caca agressiva de vulnerabilidades e segredos: SQLi, injecao de comando/codigo, XSS, TLS desligado, cripto fraca, CORS aberto, chaves/tokens embutidos (mascarados no relatorio). Regra de ouro: descarta achado sem caminho source->sink confirmado no codigo real.",
|
|
1058
|
+
"Garantia de seguranca: nesse modo ele NUNCA edita/cria/apaga nada no seu projeto \u2014 a unica escrita e UM relatorio ANALISE_PROJETO_<data>.md na raiz do projeto.",
|
|
1059
|
+
"Motor Python somente-leitura semeado a cada sessao (audit/project_audit.py); modo --focus mostra a vizinhanca de import de um arquivo especifico."
|
|
1060
|
+
],
|
|
881
1061
|
"1.0.3": [
|
|
882
1062
|
"Atualizacao: `clawfast update` atualiza o CLI e mostra as boas-vindas; aparece um aviso quando ha versao nova; /nov lista as novidades.",
|
|
883
1063
|
"Skills: /skillcreator cria ou cola uma skill (de qualquer tamanho), /skills lista e /skill delete remove. As skills viram conhecimento disponivel para TODOS os modelos.",
|
|
884
|
-
"Modelos na NVIDIA build:
|
|
1064
|
+
"Modelos na NVIDIA build: mistral-medium-3.5, gpt-oss-120b, glm-5.1 e qwen3.5-397b \u2014 todos com function calling de verdade (as ferramentas disparam).",
|
|
885
1065
|
"Resiliencia a rate limit (429): cai para os outros modelos como contingencia e espera/retenta a cadeia automaticamente."
|
|
886
1066
|
]
|
|
887
1067
|
};
|
|
@@ -897,14 +1077,50 @@ var init_news = __esm({
|
|
|
897
1077
|
return 0;
|
|
898
1078
|
})[0];
|
|
899
1079
|
};
|
|
1080
|
+
wrapText = (text2, width) => {
|
|
1081
|
+
const words = text2.split(/\s+/).filter(Boolean);
|
|
1082
|
+
const lines = [];
|
|
1083
|
+
let line = "";
|
|
1084
|
+
for (const word of words) {
|
|
1085
|
+
if (line && vlen(line) + 1 + vlen(word) > width) {
|
|
1086
|
+
lines.push(line);
|
|
1087
|
+
line = word;
|
|
1088
|
+
} else {
|
|
1089
|
+
line = line ? `${line} ${word}` : word;
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
if (line) lines.push(line);
|
|
1093
|
+
return lines.length ? lines : [""];
|
|
1094
|
+
};
|
|
900
1095
|
renderNews = (version3) => {
|
|
901
1096
|
const key = NEWS[version3] ? version3 : latestNewsVersion();
|
|
902
1097
|
if (!key || !NEWS[key]) {
|
|
903
|
-
return
|
|
904
|
-
}
|
|
905
|
-
const
|
|
906
|
-
|
|
907
|
-
|
|
1098
|
+
return `${C2.dim}Sem novidades registradas para esta versao.${C2.reset}`;
|
|
1099
|
+
}
|
|
1100
|
+
const cols2 = process.stdout.columns || 80;
|
|
1101
|
+
const BOX = Math.min(Math.max(cols2 - 2, 48), 80);
|
|
1102
|
+
const INNER2 = BOX - 4;
|
|
1103
|
+
const BULLET = "\u2022 ";
|
|
1104
|
+
const INDENT = " ".repeat(BULLET.length);
|
|
1105
|
+
const title = `Novidades \xB7 v${key}`;
|
|
1106
|
+
const topFill = "\u2500".repeat(Math.max(0, BOX - vlen(title) - 5));
|
|
1107
|
+
const top = `${C2.green}\u256D\u2500 ${C2.greenB}${C2.bold}${title}${C2.reset}${C2.green} ${topFill}\u256E${C2.reset}`;
|
|
1108
|
+
const bottom = `${C2.green}\u2570${"\u2500".repeat(BOX - 2)}\u256F${C2.reset}`;
|
|
1109
|
+
const row = (content) => {
|
|
1110
|
+
const pad = " ".repeat(Math.max(0, INNER2 - vlen(content)));
|
|
1111
|
+
return `${C2.green}\u2502 ${C2.reset}${content}${pad}${C2.green} \u2502${C2.reset}`;
|
|
1112
|
+
};
|
|
1113
|
+
const body = [row("")];
|
|
1114
|
+
NEWS[key].forEach((item, idx) => {
|
|
1115
|
+
if (idx > 0) body.push(row(""));
|
|
1116
|
+
const wrapped = wrapText(item, INNER2 - BULLET.length);
|
|
1117
|
+
wrapped.forEach((line, i) => {
|
|
1118
|
+
const prefix = i === 0 ? `${C2.cyanB}${BULLET}${C2.reset}` : INDENT;
|
|
1119
|
+
body.push(row(`${prefix}${line}`));
|
|
1120
|
+
});
|
|
1121
|
+
});
|
|
1122
|
+
body.push(row(""));
|
|
1123
|
+
return [top, ...body, bottom].join("\n");
|
|
908
1124
|
};
|
|
909
1125
|
stateFile = () => import_node_path4.default.join(clawfastHome(), "state.json");
|
|
910
1126
|
readState = () => {
|
|
@@ -1505,10 +1721,10 @@ function mergeDefs(...defs) {
|
|
|
1505
1721
|
function cloneDef(schema) {
|
|
1506
1722
|
return mergeDefs(schema._zod.def);
|
|
1507
1723
|
}
|
|
1508
|
-
function getElementAtPath(obj,
|
|
1509
|
-
if (!
|
|
1724
|
+
function getElementAtPath(obj, path10) {
|
|
1725
|
+
if (!path10)
|
|
1510
1726
|
return obj;
|
|
1511
|
-
return
|
|
1727
|
+
return path10.reduce((acc, key) => acc?.[key], obj);
|
|
1512
1728
|
}
|
|
1513
1729
|
function promiseAllObject(promisesObj) {
|
|
1514
1730
|
const keys = Object.keys(promisesObj);
|
|
@@ -1836,11 +2052,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
1836
2052
|
}
|
|
1837
2053
|
return false;
|
|
1838
2054
|
}
|
|
1839
|
-
function prefixIssues(
|
|
2055
|
+
function prefixIssues(path10, issues) {
|
|
1840
2056
|
return issues.map((iss) => {
|
|
1841
2057
|
var _a25;
|
|
1842
2058
|
(_a25 = iss).path ?? (_a25.path = []);
|
|
1843
|
-
iss.path.unshift(
|
|
2059
|
+
iss.path.unshift(path10);
|
|
1844
2060
|
return iss;
|
|
1845
2061
|
});
|
|
1846
2062
|
}
|
|
@@ -2058,16 +2274,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
2058
2274
|
}
|
|
2059
2275
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
2060
2276
|
const fieldErrors = { _errors: [] };
|
|
2061
|
-
const processError = (error52,
|
|
2277
|
+
const processError = (error52, path10 = []) => {
|
|
2062
2278
|
for (const issue2 of error52.issues) {
|
|
2063
2279
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
2064
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
2280
|
+
issue2.errors.map((issues) => processError({ issues }, [...path10, ...issue2.path]));
|
|
2065
2281
|
} else if (issue2.code === "invalid_key") {
|
|
2066
|
-
processError({ issues: issue2.issues }, [...
|
|
2282
|
+
processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
|
|
2067
2283
|
} else if (issue2.code === "invalid_element") {
|
|
2068
|
-
processError({ issues: issue2.issues }, [...
|
|
2284
|
+
processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
|
|
2069
2285
|
} else {
|
|
2070
|
-
const fullpath = [...
|
|
2286
|
+
const fullpath = [...path10, ...issue2.path];
|
|
2071
2287
|
if (fullpath.length === 0) {
|
|
2072
2288
|
fieldErrors._errors.push(mapper(issue2));
|
|
2073
2289
|
} else {
|
|
@@ -2094,17 +2310,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
2094
2310
|
}
|
|
2095
2311
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
2096
2312
|
const result = { errors: [] };
|
|
2097
|
-
const processError = (error52,
|
|
2313
|
+
const processError = (error52, path10 = []) => {
|
|
2098
2314
|
var _a25, _b18;
|
|
2099
2315
|
for (const issue2 of error52.issues) {
|
|
2100
2316
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
2101
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
2317
|
+
issue2.errors.map((issues) => processError({ issues }, [...path10, ...issue2.path]));
|
|
2102
2318
|
} else if (issue2.code === "invalid_key") {
|
|
2103
|
-
processError({ issues: issue2.issues }, [...
|
|
2319
|
+
processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
|
|
2104
2320
|
} else if (issue2.code === "invalid_element") {
|
|
2105
|
-
processError({ issues: issue2.issues }, [...
|
|
2321
|
+
processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
|
|
2106
2322
|
} else {
|
|
2107
|
-
const fullpath = [...
|
|
2323
|
+
const fullpath = [...path10, ...issue2.path];
|
|
2108
2324
|
if (fullpath.length === 0) {
|
|
2109
2325
|
result.errors.push(mapper(issue2));
|
|
2110
2326
|
continue;
|
|
@@ -2136,8 +2352,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
2136
2352
|
}
|
|
2137
2353
|
function toDotPath(_path) {
|
|
2138
2354
|
const segs = [];
|
|
2139
|
-
const
|
|
2140
|
-
for (const seg of
|
|
2355
|
+
const path10 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
2356
|
+
for (const seg of path10) {
|
|
2141
2357
|
if (typeof seg === "number")
|
|
2142
2358
|
segs.push(`[${seg}]`);
|
|
2143
2359
|
else if (typeof seg === "symbol")
|
|
@@ -12449,11 +12665,11 @@ function _catch(Class2, innerType, catchValue) {
|
|
|
12449
12665
|
});
|
|
12450
12666
|
}
|
|
12451
12667
|
// @__NO_SIDE_EFFECTS__
|
|
12452
|
-
function _pipe(Class2, in_,
|
|
12668
|
+
function _pipe(Class2, in_, out3) {
|
|
12453
12669
|
return new Class2({
|
|
12454
12670
|
type: "pipe",
|
|
12455
12671
|
in: in_,
|
|
12456
|
-
out:
|
|
12672
|
+
out: out3
|
|
12457
12673
|
});
|
|
12458
12674
|
}
|
|
12459
12675
|
// @__NO_SIDE_EFFECTS__
|
|
@@ -14689,19 +14905,19 @@ function _catch2(innerType, catchValue) {
|
|
|
14689
14905
|
function nan(params) {
|
|
14690
14906
|
return _nan(ZodNaN, params);
|
|
14691
14907
|
}
|
|
14692
|
-
function pipe(in_,
|
|
14908
|
+
function pipe(in_, out3) {
|
|
14693
14909
|
return new ZodPipe({
|
|
14694
14910
|
type: "pipe",
|
|
14695
14911
|
in: in_,
|
|
14696
|
-
out:
|
|
14912
|
+
out: out3
|
|
14697
14913
|
// ...util.normalizeParams(params),
|
|
14698
14914
|
});
|
|
14699
14915
|
}
|
|
14700
|
-
function codec(in_,
|
|
14916
|
+
function codec(in_, out3, params) {
|
|
14701
14917
|
return new ZodCodec({
|
|
14702
14918
|
type: "pipe",
|
|
14703
14919
|
in: in_,
|
|
14704
|
-
out:
|
|
14920
|
+
out: out3,
|
|
14705
14921
|
transform: params.decode,
|
|
14706
14922
|
reverseTransform: params.encode
|
|
14707
14923
|
});
|
|
@@ -15640,13 +15856,13 @@ function resolveRef(ref, ctx) {
|
|
|
15640
15856
|
if (!ref.startsWith("#")) {
|
|
15641
15857
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
15642
15858
|
}
|
|
15643
|
-
const
|
|
15644
|
-
if (
|
|
15859
|
+
const path10 = ref.slice(1).split("/").filter(Boolean);
|
|
15860
|
+
if (path10.length === 0) {
|
|
15645
15861
|
return ctx.rootSchema;
|
|
15646
15862
|
}
|
|
15647
15863
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
15648
|
-
if (
|
|
15649
|
-
const key =
|
|
15864
|
+
if (path10[0] === defsKey) {
|
|
15865
|
+
const key = path10[1];
|
|
15650
15866
|
if (!key || !ctx.defs[key]) {
|
|
15651
15867
|
throw new Error(`Reference not found: ${ref}`);
|
|
15652
15868
|
}
|
|
@@ -16835,8 +17051,8 @@ var init_parseUtil = __esm({
|
|
|
16835
17051
|
init_errors3();
|
|
16836
17052
|
init_en2();
|
|
16837
17053
|
makeIssue = (params) => {
|
|
16838
|
-
const { data, path:
|
|
16839
|
-
const fullPath = [...
|
|
17054
|
+
const { data, path: path10, errorMaps, issueData } = params;
|
|
17055
|
+
const fullPath = [...path10, ...issueData.path || []];
|
|
16840
17056
|
const fullIssue = {
|
|
16841
17057
|
...issueData,
|
|
16842
17058
|
path: fullPath
|
|
@@ -17119,11 +17335,11 @@ var init_types = __esm({
|
|
|
17119
17335
|
init_parseUtil();
|
|
17120
17336
|
init_util2();
|
|
17121
17337
|
ParseInputLazyPath = class {
|
|
17122
|
-
constructor(parent, value,
|
|
17338
|
+
constructor(parent, value, path10, key) {
|
|
17123
17339
|
this._cachedPath = [];
|
|
17124
17340
|
this.parent = parent;
|
|
17125
17341
|
this.data = value;
|
|
17126
|
-
this._path =
|
|
17342
|
+
this._path = path10;
|
|
17127
17343
|
this._key = key;
|
|
17128
17344
|
}
|
|
17129
17345
|
get path() {
|
|
@@ -23163,7 +23379,7 @@ var require_auth_config = __commonJS({
|
|
|
23163
23379
|
});
|
|
23164
23380
|
module2.exports = __toCommonJS(auth_config_exports);
|
|
23165
23381
|
var fs6 = __toESM2(require("fs"));
|
|
23166
|
-
var
|
|
23382
|
+
var path10 = __toESM2(require("path"));
|
|
23167
23383
|
var import_token_util = require_token_util();
|
|
23168
23384
|
function getAuthConfigPath() {
|
|
23169
23385
|
const dataDir = (0, import_token_util.getVercelDataDir)();
|
|
@@ -23172,7 +23388,7 @@ var require_auth_config = __commonJS({
|
|
|
23172
23388
|
`Unable to find Vercel CLI data directory. Your platform: ${process.platform}. Supported: darwin, linux, win32.`
|
|
23173
23389
|
);
|
|
23174
23390
|
}
|
|
23175
|
-
return
|
|
23391
|
+
return path10.join(dataDir, "auth.json");
|
|
23176
23392
|
}
|
|
23177
23393
|
function readAuthConfig() {
|
|
23178
23394
|
try {
|
|
@@ -23191,7 +23407,7 @@ var require_auth_config = __commonJS({
|
|
|
23191
23407
|
}
|
|
23192
23408
|
function writeAuthConfig(config3) {
|
|
23193
23409
|
const authPath = getAuthConfigPath();
|
|
23194
|
-
const authDir =
|
|
23410
|
+
const authDir = path10.dirname(authPath);
|
|
23195
23411
|
if (!fs6.existsSync(authDir)) {
|
|
23196
23412
|
fs6.mkdirSync(authDir, { mode: 504, recursive: true });
|
|
23197
23413
|
}
|
|
@@ -23386,7 +23602,7 @@ var require_token_util = __commonJS({
|
|
|
23386
23602
|
saveToken: () => saveToken
|
|
23387
23603
|
});
|
|
23388
23604
|
module2.exports = __toCommonJS(token_util_exports);
|
|
23389
|
-
var
|
|
23605
|
+
var path10 = __toESM2(require("path"));
|
|
23390
23606
|
var fs6 = __toESM2(require("fs"));
|
|
23391
23607
|
var import_token_error = require_token_error();
|
|
23392
23608
|
var import_token_io = require_token_io();
|
|
@@ -23399,7 +23615,7 @@ var require_token_util = __commonJS({
|
|
|
23399
23615
|
if (!dataDir) {
|
|
23400
23616
|
return null;
|
|
23401
23617
|
}
|
|
23402
|
-
return
|
|
23618
|
+
return path10.join(dataDir, vercelFolder);
|
|
23403
23619
|
}
|
|
23404
23620
|
async function getVercelToken2(options) {
|
|
23405
23621
|
const authConfig = (0, import_auth_config.readAuthConfig)();
|
|
@@ -23475,7 +23691,7 @@ var require_token_util = __commonJS({
|
|
|
23475
23691
|
"Unable to find project root directory. Have you linked your project with `vc link?`"
|
|
23476
23692
|
);
|
|
23477
23693
|
}
|
|
23478
|
-
const prjPath =
|
|
23694
|
+
const prjPath = path10.join(dir, ".vercel", "project.json");
|
|
23479
23695
|
if (!fs6.existsSync(prjPath)) {
|
|
23480
23696
|
throw new import_token_error.VercelOidcTokenError(
|
|
23481
23697
|
"project.json not found, have you linked your project with `vc link?`"
|
|
@@ -23496,9 +23712,9 @@ var require_token_util = __commonJS({
|
|
|
23496
23712
|
"Unable to find user data directory. Please reach out to Vercel support."
|
|
23497
23713
|
);
|
|
23498
23714
|
}
|
|
23499
|
-
const tokenPath =
|
|
23715
|
+
const tokenPath = path10.join(dir, "com.vercel.token", `${projectId}.json`);
|
|
23500
23716
|
const tokenJson = JSON.stringify(token);
|
|
23501
|
-
fs6.mkdirSync(
|
|
23717
|
+
fs6.mkdirSync(path10.dirname(tokenPath), { mode: 504, recursive: true });
|
|
23502
23718
|
fs6.writeFileSync(tokenPath, tokenJson);
|
|
23503
23719
|
fs6.chmodSync(tokenPath, 432);
|
|
23504
23720
|
return;
|
|
@@ -23510,7 +23726,7 @@ var require_token_util = __commonJS({
|
|
|
23510
23726
|
"Unable to find user data directory. Please reach out to Vercel support."
|
|
23511
23727
|
);
|
|
23512
23728
|
}
|
|
23513
|
-
const tokenPath =
|
|
23729
|
+
const tokenPath = path10.join(dir, "com.vercel.token", `${projectId}.json`);
|
|
23514
23730
|
if (!fs6.existsSync(tokenPath)) {
|
|
23515
23731
|
return null;
|
|
23516
23732
|
}
|
|
@@ -35540,7 +35756,7 @@ function createOpenRouter(options = {}) {
|
|
|
35540
35756
|
);
|
|
35541
35757
|
const createChatModel = (modelId, settings = {}) => new OpenRouterChatLanguageModel(modelId, settings, {
|
|
35542
35758
|
provider: "openrouter.chat",
|
|
35543
|
-
url: ({ path:
|
|
35759
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
35544
35760
|
headers: getHeaders,
|
|
35545
35761
|
compatibility,
|
|
35546
35762
|
fetch: options.fetch,
|
|
@@ -35548,7 +35764,7 @@ function createOpenRouter(options = {}) {
|
|
|
35548
35764
|
});
|
|
35549
35765
|
const createCompletionModel = (modelId, settings = {}) => new OpenRouterCompletionLanguageModel(modelId, settings, {
|
|
35550
35766
|
provider: "openrouter.completion",
|
|
35551
|
-
url: ({ path:
|
|
35767
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
35552
35768
|
headers: getHeaders,
|
|
35553
35769
|
compatibility,
|
|
35554
35770
|
fetch: options.fetch,
|
|
@@ -35556,21 +35772,21 @@ function createOpenRouter(options = {}) {
|
|
|
35556
35772
|
});
|
|
35557
35773
|
const createEmbeddingModel = (modelId, settings = {}) => new OpenRouterEmbeddingModel(modelId, settings, {
|
|
35558
35774
|
provider: "openrouter.embedding",
|
|
35559
|
-
url: ({ path:
|
|
35775
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
35560
35776
|
headers: getHeaders,
|
|
35561
35777
|
fetch: options.fetch,
|
|
35562
35778
|
extraBody: options.extraBody
|
|
35563
35779
|
});
|
|
35564
35780
|
const createImageModel = (modelId, settings = {}) => new OpenRouterImageModel(modelId, settings, {
|
|
35565
35781
|
provider: "openrouter.image",
|
|
35566
|
-
url: ({ path:
|
|
35782
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
35567
35783
|
headers: getHeaders,
|
|
35568
35784
|
fetch: options.fetch,
|
|
35569
35785
|
extraBody: options.extraBody
|
|
35570
35786
|
});
|
|
35571
35787
|
const createVideoModel = (modelId, settings = {}) => new OpenRouterVideoModel(modelId, settings, {
|
|
35572
35788
|
provider: "openrouter.video",
|
|
35573
|
-
url: ({ path:
|
|
35789
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
35574
35790
|
headers: getHeaders,
|
|
35575
35791
|
fetch: options.fetch,
|
|
35576
35792
|
extraBody: options.extraBody
|
|
@@ -40106,37 +40322,37 @@ function createOpenAI(options = {}) {
|
|
|
40106
40322
|
);
|
|
40107
40323
|
const createChatModel = (modelId) => new OpenAIChatLanguageModel(modelId, {
|
|
40108
40324
|
provider: `${providerName}.chat`,
|
|
40109
|
-
url: ({ path:
|
|
40325
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
40110
40326
|
headers: getHeaders,
|
|
40111
40327
|
fetch: options.fetch
|
|
40112
40328
|
});
|
|
40113
40329
|
const createCompletionModel = (modelId) => new OpenAICompletionLanguageModel(modelId, {
|
|
40114
40330
|
provider: `${providerName}.completion`,
|
|
40115
|
-
url: ({ path:
|
|
40331
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
40116
40332
|
headers: getHeaders,
|
|
40117
40333
|
fetch: options.fetch
|
|
40118
40334
|
});
|
|
40119
40335
|
const createEmbeddingModel = (modelId) => new OpenAIEmbeddingModel(modelId, {
|
|
40120
40336
|
provider: `${providerName}.embedding`,
|
|
40121
|
-
url: ({ path:
|
|
40337
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
40122
40338
|
headers: getHeaders,
|
|
40123
40339
|
fetch: options.fetch
|
|
40124
40340
|
});
|
|
40125
40341
|
const createImageModel = (modelId) => new OpenAIImageModel(modelId, {
|
|
40126
40342
|
provider: `${providerName}.image`,
|
|
40127
|
-
url: ({ path:
|
|
40343
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
40128
40344
|
headers: getHeaders,
|
|
40129
40345
|
fetch: options.fetch
|
|
40130
40346
|
});
|
|
40131
40347
|
const createTranscriptionModel = (modelId) => new OpenAITranscriptionModel(modelId, {
|
|
40132
40348
|
provider: `${providerName}.transcription`,
|
|
40133
|
-
url: ({ path:
|
|
40349
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
40134
40350
|
headers: getHeaders,
|
|
40135
40351
|
fetch: options.fetch
|
|
40136
40352
|
});
|
|
40137
40353
|
const createSpeechModel = (modelId) => new OpenAISpeechModel(modelId, {
|
|
40138
40354
|
provider: `${providerName}.speech`,
|
|
40139
|
-
url: ({ path:
|
|
40355
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
40140
40356
|
headers: getHeaders,
|
|
40141
40357
|
fetch: options.fetch
|
|
40142
40358
|
});
|
|
@@ -40151,7 +40367,7 @@ function createOpenAI(options = {}) {
|
|
|
40151
40367
|
const createResponsesModel = (modelId) => {
|
|
40152
40368
|
return new OpenAIResponsesLanguageModel(modelId, {
|
|
40153
40369
|
provider: `${providerName}.responses`,
|
|
40154
|
-
url: ({ path:
|
|
40370
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
40155
40371
|
headers: getHeaders,
|
|
40156
40372
|
fetch: options.fetch,
|
|
40157
40373
|
fileIdPrefixes: ["file-"]
|
|
@@ -45372,7 +45588,7 @@ function supportsMultimodalToolResults(modelName) {
|
|
|
45372
45588
|
const normalized = modelName.toLowerCase();
|
|
45373
45589
|
return normalized === "ask-model" || normalized.includes("gemini") || normalized.includes("google/") || isAnthropicModel(normalized) || normalized.includes("anthropic/") || normalized.includes("claude") || normalized.includes("openai") || normalized.includes("openai/") || normalized.includes("gpt-") || normalized.includes("o1") || normalized.includes("o3") || normalized.includes("o4") || normalized.includes("x-ai/") || normalized.includes("grok");
|
|
45374
45590
|
}
|
|
45375
|
-
var isRecord, isXaiModelSlug, isGeminiModelSlug, requestCanRouteToXai, requestCanRouteToGemini, hasOwnEncryptedContent, stripEncryptedContent, sanitizeOpenRouterRequestForXai, hasJsonRefKey, wrapToolContentIfGeminiRefSensitive, sanitizeOpenRouterRequestForGeminiFunctionResponses, patchKimiReasoningToolCalls, OPENROUTER_METADATA_HEADER, withOpenRouterMetadataHeader, openrouterPatchFetch, openrouter2, openai2, nvidia, deepseek, kimi, buildProviderMap, hasEnvValue, isDeepSeekEnabled, isKimiEnabled, CLI_MODEL_CHAIN, baseProviders, modelCutoffDates, modelDisplayNames, getModelDisplayName, getModelCutoffDate, myProvider;
|
|
45591
|
+
var isRecord, isXaiModelSlug, isGeminiModelSlug, requestCanRouteToXai, requestCanRouteToGemini, hasOwnEncryptedContent, stripEncryptedContent, sanitizeOpenRouterRequestForXai, hasJsonRefKey, wrapToolContentIfGeminiRefSensitive, sanitizeOpenRouterRequestForGeminiFunctionResponses, patchKimiReasoningToolCalls, OPENROUTER_METADATA_HEADER, withOpenRouterMetadataHeader, openrouterPatchFetch, openrouter2, openai2, isNvidiaMistralModel, applyNvidiaMistralConfig, nvidiaPatchFetch, nvidia, deepseek, kimi, buildProviderMap, hasEnvValue, isDeepSeekEnabled, isKimiEnabled, CLI_MODEL_CHAIN, baseProviders, modelCutoffDates, modelDisplayNames, getModelDisplayName, getModelCutoffDate, myProvider;
|
|
45376
45592
|
var init_providers = __esm({
|
|
45377
45593
|
"../lib/ai/providers.ts"() {
|
|
45378
45594
|
"use strict";
|
|
@@ -45532,10 +45748,47 @@ var init_providers = __esm({
|
|
|
45532
45748
|
name: "openai",
|
|
45533
45749
|
apiKey: process.env.OPENAI_API_KEY
|
|
45534
45750
|
});
|
|
45751
|
+
isNvidiaMistralModel = (value) => typeof value === "string" && value.toLowerCase().startsWith("mistralai/mistral");
|
|
45752
|
+
applyNvidiaMistralConfig = (body) => {
|
|
45753
|
+
if (!isRecord(body) || !isNvidiaMistralModel(body.model)) {
|
|
45754
|
+
return { body, changed: false };
|
|
45755
|
+
}
|
|
45756
|
+
return {
|
|
45757
|
+
body: {
|
|
45758
|
+
...body,
|
|
45759
|
+
reasoning_effort: "none",
|
|
45760
|
+
temperature: 1,
|
|
45761
|
+
top_p: 1,
|
|
45762
|
+
max_tokens: 16384
|
|
45763
|
+
},
|
|
45764
|
+
changed: true
|
|
45765
|
+
};
|
|
45766
|
+
};
|
|
45767
|
+
nvidiaPatchFetch = async (url2, init) => {
|
|
45768
|
+
const key = process.env.NVIDIA_API_KEY?.trim();
|
|
45769
|
+
const headers = new Headers(init?.headers);
|
|
45770
|
+
if (key) headers.set("Authorization", `Bearer ${key}`);
|
|
45771
|
+
let nextInit = { ...init, headers };
|
|
45772
|
+
if (typeof nextInit.body === "string") {
|
|
45773
|
+
try {
|
|
45774
|
+
const parsed = JSON.parse(nextInit.body);
|
|
45775
|
+
const patched = applyNvidiaMistralConfig(parsed);
|
|
45776
|
+
if (patched.changed) {
|
|
45777
|
+
nextInit = { ...nextInit, body: JSON.stringify(patched.body) };
|
|
45778
|
+
}
|
|
45779
|
+
} catch {
|
|
45780
|
+
}
|
|
45781
|
+
}
|
|
45782
|
+
return globalThis.fetch(url2, nextInit);
|
|
45783
|
+
};
|
|
45535
45784
|
nvidia = createOpenAI({
|
|
45536
45785
|
name: "nvidia",
|
|
45537
45786
|
baseURL: process.env.NVIDIA_BASE_URL || "https://integrate.api.nvidia.com/v1",
|
|
45538
|
-
|
|
45787
|
+
// Placeholder so the SDK never throws "missing API key" at request build time
|
|
45788
|
+
// when the env is empty at load — nvidiaPatchFetch sets the real Authorization
|
|
45789
|
+
// header from process.env on every request (see above).
|
|
45790
|
+
apiKey: process.env.NVIDIA_API_KEY || "nvapi-clawfast-runtime",
|
|
45791
|
+
fetch: nvidiaPatchFetch
|
|
45539
45792
|
});
|
|
45540
45793
|
deepseek = createOpenAI({
|
|
45541
45794
|
name: "deepseek",
|
|
@@ -45563,8 +45816,10 @@ var init_providers = __esm({
|
|
|
45563
45816
|
"model-opus-4.6": nvidia("nvidia/nemotron-3-ultra-550b-a55b"),
|
|
45564
45817
|
"model-kimi-k2.6": or("qwen/qwen3-coder:free"),
|
|
45565
45818
|
// NVIDIA build models — primary provider for the local CLI (chat-completions).
|
|
45566
|
-
"model-nvidia-
|
|
45567
|
-
|
|
45819
|
+
"model-nvidia-mistral-medium-3.5": nvidia.chat(
|
|
45820
|
+
"mistralai/mistral-medium-3.5-128b"
|
|
45821
|
+
),
|
|
45822
|
+
"model-nvidia-gpt-oss-120b": nvidia.chat("openai/gpt-oss-120b"),
|
|
45568
45823
|
"model-nvidia-glm-5.1": nvidia.chat("z-ai/glm-5.1"),
|
|
45569
45824
|
"model-nvidia-qwen3.5-397b": nvidia.chat("qwen/qwen3.5-397b-a17b"),
|
|
45570
45825
|
// Extra explicit keys for the CLI.
|
|
@@ -45600,10 +45855,10 @@ var init_providers = __esm({
|
|
|
45600
45855
|
};
|
|
45601
45856
|
CLI_MODEL_CHAIN = [
|
|
45602
45857
|
...hasEnvValue("NVIDIA_API_KEY") ? [
|
|
45603
|
-
"model-nvidia-
|
|
45604
|
-
// NVIDIA
|
|
45605
|
-
"model-nvidia-
|
|
45606
|
-
// NVIDIA
|
|
45858
|
+
"model-nvidia-mistral-medium-3.5",
|
|
45859
|
+
// NVIDIA mistralai/mistral-medium-3.5-128b
|
|
45860
|
+
"model-nvidia-gpt-oss-120b",
|
|
45861
|
+
// NVIDIA openai/gpt-oss-120b
|
|
45607
45862
|
"model-nvidia-glm-5.1",
|
|
45608
45863
|
// NVIDIA z-ai/glm-5.1
|
|
45609
45864
|
"model-nvidia-qwen3.5-397b"
|
|
@@ -45628,8 +45883,8 @@ var init_providers = __esm({
|
|
|
45628
45883
|
"model-deepseek-v4-flash": "May 2025",
|
|
45629
45884
|
"model-opus-4.6": "May 2025",
|
|
45630
45885
|
"model-kimi-k2.6": "April 2024",
|
|
45631
|
-
"model-nvidia-
|
|
45632
|
-
"model-nvidia-
|
|
45886
|
+
"model-nvidia-mistral-medium-3.5": "Unknown",
|
|
45887
|
+
"model-nvidia-gpt-oss-120b": "June 2024",
|
|
45633
45888
|
"model-nvidia-glm-5.1": "Unknown",
|
|
45634
45889
|
"model-nvidia-qwen3.5-397b": "Unknown",
|
|
45635
45890
|
"model-deepseek-proxy": "July 2024",
|
|
@@ -45652,8 +45907,8 @@ var init_providers = __esm({
|
|
|
45652
45907
|
"model-deepseek-v4-flash": "DeepSeek V4 Flash",
|
|
45653
45908
|
"model-opus-4.6": "Anthropic Claude Opus 4.6",
|
|
45654
45909
|
"model-kimi-k2.6": "Moonshot Kimi K2.6",
|
|
45655
|
-
"model-nvidia-
|
|
45656
|
-
"model-nvidia-
|
|
45910
|
+
"model-nvidia-mistral-medium-3.5": "NVIDIA - Mistral Medium 3.5",
|
|
45911
|
+
"model-nvidia-gpt-oss-120b": "NVIDIA - OpenAI GPT-OSS 120B",
|
|
45657
45912
|
"model-nvidia-glm-5.1": "NVIDIA - Z.ai GLM 5.1",
|
|
45658
45913
|
"model-nvidia-qwen3.5-397b": "NVIDIA - Qwen3.5 397B A17B",
|
|
45659
45914
|
"model-deepseek-proxy": "DeepSeek (sessao web logada / deepsproxy)",
|
|
@@ -48687,8 +48942,8 @@ var init_background_process_tracker = __esm({
|
|
|
48687
48942
|
/**
|
|
48688
48943
|
* Normalize file path for comparison
|
|
48689
48944
|
*/
|
|
48690
|
-
normalizePath(
|
|
48691
|
-
let normalized =
|
|
48945
|
+
normalizePath(path10) {
|
|
48946
|
+
let normalized = path10.trim().replace(/\/+/g, "/");
|
|
48692
48947
|
if (normalized.startsWith("./")) {
|
|
48693
48948
|
normalized = normalized.slice(2);
|
|
48694
48949
|
}
|
|
@@ -48926,8 +49181,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
|
|
|
48926
49181
|
return decodedFile;
|
|
48927
49182
|
};
|
|
48928
49183
|
}
|
|
48929
|
-
function normalizeWindowsPath(
|
|
48930
|
-
return
|
|
49184
|
+
function normalizeWindowsPath(path10) {
|
|
49185
|
+
return path10.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
|
|
48931
49186
|
}
|
|
48932
49187
|
var import_path;
|
|
48933
49188
|
var init_module_node = __esm({
|
|
@@ -51816,9 +52071,9 @@ async function addSourceContext(frames) {
|
|
|
51816
52071
|
LRU_FILE_CONTENTS_CACHE.reduce();
|
|
51817
52072
|
return frames;
|
|
51818
52073
|
}
|
|
51819
|
-
function getContextLinesFromFile(
|
|
52074
|
+
function getContextLinesFromFile(path10, ranges, output) {
|
|
51820
52075
|
return new Promise((resolve2) => {
|
|
51821
|
-
const stream = (0, import_node_fs5.createReadStream)(
|
|
52076
|
+
const stream = (0, import_node_fs5.createReadStream)(path10);
|
|
51822
52077
|
const lineReaded = (0, import_node_readline2.createInterface)({
|
|
51823
52078
|
input: stream
|
|
51824
52079
|
});
|
|
@@ -51833,7 +52088,7 @@ function getContextLinesFromFile(path8, ranges, output) {
|
|
|
51833
52088
|
let rangeStart = range[0];
|
|
51834
52089
|
let rangeEnd = range[1];
|
|
51835
52090
|
function onStreamError() {
|
|
51836
|
-
LRU_FILE_CONTENTS_FS_READ_FAILED.set(
|
|
52091
|
+
LRU_FILE_CONTENTS_FS_READ_FAILED.set(path10, 1);
|
|
51837
52092
|
lineReaded.close();
|
|
51838
52093
|
lineReaded.removeAllListeners();
|
|
51839
52094
|
destroyStreamAndResolve();
|
|
@@ -51894,8 +52149,8 @@ function clearLineContext(frame2) {
|
|
|
51894
52149
|
delete frame2.context_line;
|
|
51895
52150
|
delete frame2.post_context;
|
|
51896
52151
|
}
|
|
51897
|
-
function shouldSkipContextLinesForFile(
|
|
51898
|
-
return
|
|
52152
|
+
function shouldSkipContextLinesForFile(path10) {
|
|
52153
|
+
return path10.startsWith("node:") || path10.endsWith(".min.js") || path10.endsWith(".min.cjs") || path10.endsWith(".min.mjs") || path10.startsWith("data:");
|
|
51899
52154
|
}
|
|
51900
52155
|
function shouldSkipContextLinesForFrame(frame2) {
|
|
51901
52156
|
if (void 0 !== frame2.lineno && frame2.lineno > MAX_CONTEXTLINES_LINENO) return true;
|
|
@@ -51914,22 +52169,22 @@ function makeLineReaderRanges(lines) {
|
|
|
51914
52169
|
const line = lines[0];
|
|
51915
52170
|
if ("number" != typeof line) return [];
|
|
51916
52171
|
let current = makeContextRange(line);
|
|
51917
|
-
const
|
|
52172
|
+
const out3 = [];
|
|
51918
52173
|
while (true) {
|
|
51919
52174
|
if (i === lines.length - 1) {
|
|
51920
|
-
|
|
52175
|
+
out3.push(current);
|
|
51921
52176
|
break;
|
|
51922
52177
|
}
|
|
51923
52178
|
const next = lines[i + 1];
|
|
51924
52179
|
if ("number" != typeof next) break;
|
|
51925
52180
|
if (next <= current[1]) current[1] = next + DEFAULT_LINES_OF_CONTEXT;
|
|
51926
52181
|
else {
|
|
51927
|
-
|
|
52182
|
+
out3.push(current);
|
|
51928
52183
|
current = makeContextRange(next);
|
|
51929
52184
|
}
|
|
51930
52185
|
i++;
|
|
51931
52186
|
}
|
|
51932
|
-
return
|
|
52187
|
+
return out3;
|
|
51933
52188
|
}
|
|
51934
52189
|
function makeContextRange(line) {
|
|
51935
52190
|
return [
|
|
@@ -55447,8 +55702,8 @@ async function createE2BPtyHandle(sandbox, opts) {
|
|
|
55447
55702
|
sendInput(bytes) {
|
|
55448
55703
|
return pty.sendInput(pid, bytes);
|
|
55449
55704
|
},
|
|
55450
|
-
async resize(
|
|
55451
|
-
await pty.resize(pid, { cols, rows });
|
|
55705
|
+
async resize(cols2, rows) {
|
|
55706
|
+
await pty.resize(pid, { cols: cols2, rows });
|
|
55452
55707
|
},
|
|
55453
55708
|
async kill() {
|
|
55454
55709
|
const killed = await pty.kill(pid);
|
|
@@ -55589,9 +55844,9 @@ var init_pty_session_manager = __esm({
|
|
|
55589
55844
|
consumeDelta(session) {
|
|
55590
55845
|
const total = this.totalBufferBytes(session);
|
|
55591
55846
|
const start = Math.min(session.readCursor, total);
|
|
55592
|
-
const
|
|
55847
|
+
const out3 = this.sliceBuffer(session, start, total);
|
|
55593
55848
|
session.readCursor = total;
|
|
55594
|
-
return
|
|
55849
|
+
return out3;
|
|
55595
55850
|
}
|
|
55596
55851
|
/**
|
|
55597
55852
|
* Returns the full accumulated buffer without advancing `readCursor`.
|
|
@@ -55649,7 +55904,7 @@ var init_pty_session_manager = __esm({
|
|
|
55649
55904
|
}
|
|
55650
55905
|
sliceBuffer(session, start, end) {
|
|
55651
55906
|
if (end <= start) return new Uint8Array(0);
|
|
55652
|
-
const
|
|
55907
|
+
const out3 = new Uint8Array(end - start);
|
|
55653
55908
|
let outOffset = 0;
|
|
55654
55909
|
let cursor = 0;
|
|
55655
55910
|
for (const chunk of session.buffer) {
|
|
@@ -55662,11 +55917,11 @@ var init_pty_session_manager = __esm({
|
|
|
55662
55917
|
if (chunkStart >= end) break;
|
|
55663
55918
|
const sliceStart = Math.max(0, start - chunkStart);
|
|
55664
55919
|
const sliceEnd = Math.min(chunk.byteLength, end - chunkStart);
|
|
55665
|
-
|
|
55920
|
+
out3.set(chunk.subarray(sliceStart, sliceEnd), outOffset);
|
|
55666
55921
|
outOffset += sliceEnd - sliceStart;
|
|
55667
55922
|
cursor = chunkEnd;
|
|
55668
55923
|
}
|
|
55669
|
-
return
|
|
55924
|
+
return out3;
|
|
55670
55925
|
}
|
|
55671
55926
|
async killAndRemove(session, _reason) {
|
|
55672
55927
|
if (session.closing) {
|
|
@@ -55924,7 +56179,7 @@ var require_xterm_headless = __commonJS({
|
|
|
55924
56179
|
};
|
|
55925
56180
|
Object.defineProperty(t2, "__esModule", { value: true }), t2.InputHandler = t2.WindowsOptionsReportType = void 0, t2.isValidColorIndex = k;
|
|
55926
56181
|
const n2 = s2(3534), o = s2(6760), a = s2(6717), h = s2(7150), c = s2(726), l = s2(6107), u = s2(8938), d = s2(3055), f = s2(5451), _ = s2(6501), p = s2(6415), g = s2(1346), v = s2(9823), m = s2(8693), b = s2(802), S = { "(": 0, ")": 1, "*": 2, "+": 3, "-": 1, ".": 2 }, y = 131072;
|
|
55927
|
-
function
|
|
56182
|
+
function C5(e3, t3) {
|
|
55928
56183
|
if (e3 > 24) return t3.setWinLines || false;
|
|
55929
56184
|
switch (e3) {
|
|
55930
56185
|
case 1:
|
|
@@ -56059,7 +56314,7 @@ var require_xterm_headless = __commonJS({
|
|
|
56059
56314
|
this._parser.precedingJoinState = g2, this._activeBuffer.x < a2 && s3 - t3 > 0 && 0 === _2.getWidth(this._activeBuffer.x) && !_2.hasContent(this._activeBuffer.x) && _2.setCellFromCodepoint(this._activeBuffer.x, 0, 1, f2), this._dirtyRowTracker.markDirty(this._activeBuffer.y);
|
|
56060
56315
|
}
|
|
56061
56316
|
registerCsiHandler(e3, t3) {
|
|
56062
|
-
return "t" !== e3.final || e3.prefix || e3.intermediates ? this._parser.registerCsiHandler(e3, t3) : this._parser.registerCsiHandler(e3, ((e4) => !
|
|
56317
|
+
return "t" !== e3.final || e3.prefix || e3.intermediates ? this._parser.registerCsiHandler(e3, t3) : this._parser.registerCsiHandler(e3, ((e4) => !C5(e4.params[0], this._optionsService.rawOptions.windowOptions) || t3(e4)));
|
|
56063
56318
|
}
|
|
56064
56319
|
registerDcsHandler(e3, t3) {
|
|
56065
56320
|
return this._parser.registerDcsHandler(e3, new v.DcsHandler(t3));
|
|
@@ -56573,7 +56828,7 @@ var require_xterm_headless = __commonJS({
|
|
|
56573
56828
|
return (e3.length < 2 || (s3 = e3.params[1]) > this._bufferService.rows || 0 === s3) && (s3 = this._bufferService.rows), s3 > t3 && (this._activeBuffer.scrollTop = t3 - 1, this._activeBuffer.scrollBottom = s3 - 1, this._setCursor(0, 0)), true;
|
|
56574
56829
|
}
|
|
56575
56830
|
windowOptions(e3) {
|
|
56576
|
-
if (!
|
|
56831
|
+
if (!C5(e3.params[0], this._optionsService.rawOptions.windowOptions)) return true;
|
|
56577
56832
|
const t3 = e3.length > 1 ? e3.params[1] : 0;
|
|
56578
56833
|
switch (e3.params[0]) {
|
|
56579
56834
|
case 14:
|
|
@@ -61700,12 +61955,12 @@ function applyDelta(source, delta) {
|
|
|
61700
61955
|
zDelta.pos += cnt;
|
|
61701
61956
|
break;
|
|
61702
61957
|
case ";": {
|
|
61703
|
-
const
|
|
61704
|
-
if (cnt !== checksum(
|
|
61958
|
+
const out3 = zOut.toByteArray(source);
|
|
61959
|
+
if (cnt !== checksum(out3))
|
|
61705
61960
|
throw new Error("bad checksum");
|
|
61706
61961
|
if (total !== limit)
|
|
61707
61962
|
throw new Error("generated size does not match predicted size");
|
|
61708
|
-
return
|
|
61963
|
+
return out3;
|
|
61709
61964
|
}
|
|
61710
61965
|
default:
|
|
61711
61966
|
throw new Error("unknown delta operator");
|
|
@@ -66279,11 +66534,11 @@ async function createCentrifugoPtyHandle(sandbox, opts) {
|
|
|
66279
66534
|
};
|
|
66280
66535
|
await publish(payload);
|
|
66281
66536
|
},
|
|
66282
|
-
async resize(
|
|
66537
|
+
async resize(cols2, rows) {
|
|
66283
66538
|
const payload = {
|
|
66284
66539
|
type: "pty_resize",
|
|
66285
66540
|
sessionId,
|
|
66286
|
-
cols,
|
|
66541
|
+
cols: cols2,
|
|
66287
66542
|
rows,
|
|
66288
66543
|
targetConnectionId: connectionId
|
|
66289
66544
|
};
|
|
@@ -66518,7 +66773,7 @@ In using these tools, adhere to the following guidelines:
|
|
|
66518
66773
|
timeout,
|
|
66519
66774
|
interactive
|
|
66520
66775
|
}, { toolCallId, abortSignal }) => {
|
|
66521
|
-
const
|
|
66776
|
+
const cols2 = DEFAULT_PTY_COLS;
|
|
66522
66777
|
const rows = DEFAULT_PTY_ROWS;
|
|
66523
66778
|
let activePtySessionId;
|
|
66524
66779
|
let emitQueue = Promise.resolve();
|
|
@@ -66613,20 +66868,20 @@ In using these tools, adhere to the following guidelines:
|
|
|
66613
66868
|
}
|
|
66614
66869
|
}
|
|
66615
66870
|
const session = await ptySessionManager2.create(chatId, {
|
|
66616
|
-
cols,
|
|
66871
|
+
cols: cols2,
|
|
66617
66872
|
rows,
|
|
66618
66873
|
createHandle: async () => {
|
|
66619
66874
|
if (isCentrifugo) {
|
|
66620
66875
|
const { createCentrifugoPtyHandle: createCentrifugoPtyHandle2 } = await Promise.resolve().then(() => (init_centrifugo_pty_adapter(), centrifugo_pty_adapter_exports));
|
|
66621
66876
|
return createCentrifugoPtyHandle2(sandbox, {
|
|
66622
66877
|
command,
|
|
66623
|
-
cols,
|
|
66878
|
+
cols: cols2,
|
|
66624
66879
|
rows,
|
|
66625
66880
|
envs: caidoEnvVars
|
|
66626
66881
|
});
|
|
66627
66882
|
}
|
|
66628
66883
|
return createE2BPtyHandle(sandbox, {
|
|
66629
|
-
cols,
|
|
66884
|
+
cols: cols2,
|
|
66630
66885
|
rows,
|
|
66631
66886
|
envs: caidoEnvVars
|
|
66632
66887
|
});
|
|
@@ -67305,8 +67560,8 @@ var init_logger2 = __esm({
|
|
|
67305
67560
|
});
|
|
67306
67561
|
|
|
67307
67562
|
// ../lib/ai/tools/file.ts
|
|
67308
|
-
function isSpritPath(
|
|
67309
|
-
return
|
|
67563
|
+
function isSpritPath(path10) {
|
|
67564
|
+
return path10.split(/[\\/]/).some((segment) => segment.toLowerCase() === "sprit");
|
|
67310
67565
|
}
|
|
67311
67566
|
function getViewSandboxType(sandbox) {
|
|
67312
67567
|
return isCentrifugoSandbox(sandbox) ? "centrifugo" : "e2b";
|
|
@@ -67337,7 +67592,7 @@ function captureFileViewImageUsage(args) {
|
|
|
67337
67592
|
const {
|
|
67338
67593
|
context: context2,
|
|
67339
67594
|
sandbox,
|
|
67340
|
-
path:
|
|
67595
|
+
path: path10,
|
|
67341
67596
|
outcome,
|
|
67342
67597
|
durationMs,
|
|
67343
67598
|
mediaType,
|
|
@@ -67355,7 +67610,7 @@ function captureFileViewImageUsage(args) {
|
|
|
67355
67610
|
model: getActiveModelName(context2),
|
|
67356
67611
|
configured_model: context2.modelName,
|
|
67357
67612
|
sandbox_type: getViewSandboxType(sandbox),
|
|
67358
|
-
file_extension: getFileExtension(
|
|
67613
|
+
file_extension: getFileExtension(path10),
|
|
67359
67614
|
outcome,
|
|
67360
67615
|
success: outcome === "success",
|
|
67361
67616
|
duration_ms: durationMs,
|
|
@@ -67429,22 +67684,22 @@ async function runSandboxCommand(sandbox, command, envVars, timeoutMs = 6e4) {
|
|
|
67429
67684
|
function isWindowsSandbox(sandbox) {
|
|
67430
67685
|
return isCentrifugoSandbox(sandbox) && sandbox.isWindows();
|
|
67431
67686
|
}
|
|
67432
|
-
function getWindowsNativePath(
|
|
67433
|
-
if (/^[A-Za-z]:[\\/]/.test(
|
|
67434
|
-
if (
|
|
67435
|
-
return `C:\\temp${
|
|
67687
|
+
function getWindowsNativePath(path10) {
|
|
67688
|
+
if (/^[A-Za-z]:[\\/]/.test(path10)) return path10;
|
|
67689
|
+
if (path10.startsWith("/tmp/")) {
|
|
67690
|
+
return `C:\\temp${path10.slice(4).replace(/\//g, "\\")}`;
|
|
67436
67691
|
}
|
|
67437
|
-
return
|
|
67692
|
+
return path10.replace(/\//g, "\\");
|
|
67438
67693
|
}
|
|
67439
|
-
function getPythonPathForSandbox(sandbox,
|
|
67440
|
-
return isWindowsSandbox(sandbox) ? getWindowsNativePath(
|
|
67694
|
+
function getPythonPathForSandbox(sandbox, path10) {
|
|
67695
|
+
return isWindowsSandbox(sandbox) ? getWindowsNativePath(path10) : path10;
|
|
67441
67696
|
}
|
|
67442
|
-
function toWindowsBashPath(
|
|
67443
|
-
const drive =
|
|
67697
|
+
function toWindowsBashPath(path10) {
|
|
67698
|
+
const drive = path10.match(/^([A-Za-z]):[\\/](.*)$/);
|
|
67444
67699
|
if (drive) {
|
|
67445
67700
|
return `/${drive[1].toLowerCase()}/${drive[2].replace(/\\/g, "/")}`;
|
|
67446
67701
|
}
|
|
67447
|
-
return
|
|
67702
|
+
return path10.replace(/\\/g, "/");
|
|
67448
67703
|
}
|
|
67449
67704
|
async function detectSandboxShell(sandbox) {
|
|
67450
67705
|
if (!isWindowsSandbox(sandbox)) return "bash";
|
|
@@ -67483,8 +67738,8 @@ PY`;
|
|
|
67483
67738
|
}
|
|
67484
67739
|
}
|
|
67485
67740
|
}
|
|
67486
|
-
async function getSandboxFileState(sandbox,
|
|
67487
|
-
const pythonPath = getPythonPathForSandbox(sandbox,
|
|
67741
|
+
async function getSandboxFileState(sandbox, path10) {
|
|
67742
|
+
const pythonPath = getPythonPathForSandbox(sandbox, path10);
|
|
67488
67743
|
const result = await runPythonScript(
|
|
67489
67744
|
sandbox,
|
|
67490
67745
|
FILE_STATE_SCRIPT,
|
|
@@ -67501,23 +67756,23 @@ async function getSandboxFileState(sandbox, path8) {
|
|
|
67501
67756
|
if (result.exitCode !== 0) {
|
|
67502
67757
|
return {
|
|
67503
67758
|
kind: "unknown",
|
|
67504
|
-
path:
|
|
67759
|
+
path: path10,
|
|
67505
67760
|
error: result.stderr || result.stdout || "file state command failed"
|
|
67506
67761
|
};
|
|
67507
67762
|
}
|
|
67508
67763
|
try {
|
|
67509
67764
|
const payload = JSON.parse(result.stdout.trim());
|
|
67510
67765
|
if (payload.kind === "file" && typeof payload.sizeBytes === "number" && Number.isFinite(payload.sizeBytes)) {
|
|
67511
|
-
return { ...payload, path:
|
|
67766
|
+
return { ...payload, path: path10 };
|
|
67512
67767
|
}
|
|
67513
67768
|
if (payload.kind === "missing" || payload.kind === "not_file") {
|
|
67514
|
-
return { ...payload, path:
|
|
67769
|
+
return { ...payload, path: path10 };
|
|
67515
67770
|
}
|
|
67516
67771
|
} catch {
|
|
67517
67772
|
}
|
|
67518
67773
|
return {
|
|
67519
67774
|
kind: "unknown",
|
|
67520
|
-
path:
|
|
67775
|
+
path: path10,
|
|
67521
67776
|
error: result.stderr || result.stdout || "invalid file state response"
|
|
67522
67777
|
};
|
|
67523
67778
|
}
|
|
@@ -67549,8 +67804,8 @@ ${numberedContent}${truncatedNotice}${footerNotice}`;
|
|
|
67549
67804
|
})
|
|
67550
67805
|
};
|
|
67551
67806
|
}
|
|
67552
|
-
async function readSandboxTextFile(sandbox,
|
|
67553
|
-
const pythonPath = getPythonPathForSandbox(sandbox,
|
|
67807
|
+
async function readSandboxTextFile(sandbox, path10, range) {
|
|
67808
|
+
const pythonPath = getPythonPathForSandbox(sandbox, path10);
|
|
67554
67809
|
const envVars = {
|
|
67555
67810
|
HACKERAI_FILE_READ_PATH: pythonPath,
|
|
67556
67811
|
HACKERAI_FILE_READ_RANGE_START: String(range?.[0] ?? 0),
|
|
@@ -67578,40 +67833,40 @@ async function readSandboxTextFile(sandbox, path8, range) {
|
|
|
67578
67833
|
}
|
|
67579
67834
|
return payload;
|
|
67580
67835
|
}
|
|
67581
|
-
async function readSandboxTextFileWithFallback(sandbox,
|
|
67836
|
+
async function readSandboxTextFileWithFallback(sandbox, path10, range) {
|
|
67582
67837
|
try {
|
|
67583
|
-
return await readSandboxTextFile(sandbox,
|
|
67838
|
+
return await readSandboxTextFile(sandbox, path10, range);
|
|
67584
67839
|
} catch (error51) {
|
|
67585
67840
|
const errorMessage = error51 instanceof Error ? error51.message : String(error51);
|
|
67586
67841
|
if (errorMessage.startsWith("Invalid ") || errorMessage.includes("File not found")) {
|
|
67587
67842
|
throw error51;
|
|
67588
67843
|
}
|
|
67589
|
-
const state = await getSandboxFileState(sandbox,
|
|
67844
|
+
const state = await getSandboxFileState(sandbox, path10);
|
|
67590
67845
|
if (state.kind === "unknown") {
|
|
67591
67846
|
throw new Error(
|
|
67592
|
-
`Unable to determine file size for ${
|
|
67847
|
+
`Unable to determine file size for ${path10}; refusing to load the file into memory. ${state.error}`
|
|
67593
67848
|
);
|
|
67594
67849
|
}
|
|
67595
67850
|
if (state.kind === "missing") {
|
|
67596
|
-
throw new Error(`File not found or is not a regular file: ${
|
|
67851
|
+
throw new Error(`File not found or is not a regular file: ${path10}`);
|
|
67597
67852
|
}
|
|
67598
67853
|
if (state.kind === "not_file") {
|
|
67599
|
-
throw new Error(`File is not a regular file: ${
|
|
67854
|
+
throw new Error(`File is not a regular file: ${path10}`);
|
|
67600
67855
|
}
|
|
67601
67856
|
if (state.sizeBytes > MAX_TEXT_FILE_READ_BYTES) {
|
|
67602
67857
|
if (range) {
|
|
67603
67858
|
throw new Error(
|
|
67604
|
-
`Unable to perform a bounded range read for ${
|
|
67859
|
+
`Unable to perform a bounded range read for ${path10}, and the file is too large to load safely (${formatBytes(state.sizeBytes)}). Use a targeted terminal command that writes a small result to a separate file.`
|
|
67605
67860
|
);
|
|
67606
67861
|
}
|
|
67607
67862
|
return {
|
|
67608
|
-
path:
|
|
67863
|
+
path: path10,
|
|
67609
67864
|
sizeBytes: state.sizeBytes,
|
|
67610
67865
|
totalLines: 0,
|
|
67611
67866
|
tooLarge: true
|
|
67612
67867
|
};
|
|
67613
67868
|
}
|
|
67614
|
-
const fileContent = await sandbox.files.read(
|
|
67869
|
+
const fileContent = await sandbox.files.read(path10, {
|
|
67615
67870
|
user: "user"
|
|
67616
67871
|
});
|
|
67617
67872
|
const lines = fileContent.split("\n");
|
|
@@ -67640,7 +67895,7 @@ async function readSandboxTextFileWithFallback(sandbox, path8, range) {
|
|
|
67640
67895
|
const startIndex = start - 1;
|
|
67641
67896
|
const endIndex = end === -1 ? lines.length : end;
|
|
67642
67897
|
return {
|
|
67643
|
-
path:
|
|
67898
|
+
path: path10,
|
|
67644
67899
|
sizeBytes: Buffer.byteLength(fileContent),
|
|
67645
67900
|
totalLines: lines.length,
|
|
67646
67901
|
content: lines.slice(startIndex, endIndex).join("\n"),
|
|
@@ -67648,7 +67903,7 @@ async function readSandboxTextFileWithFallback(sandbox, path8, range) {
|
|
|
67648
67903
|
};
|
|
67649
67904
|
}
|
|
67650
67905
|
return {
|
|
67651
|
-
path:
|
|
67906
|
+
path: path10,
|
|
67652
67907
|
sizeBytes: Buffer.byteLength(fileContent),
|
|
67653
67908
|
totalLines: lines.length,
|
|
67654
67909
|
content: fileContent,
|
|
@@ -67656,7 +67911,7 @@ async function readSandboxTextFileWithFallback(sandbox, path8, range) {
|
|
|
67656
67911
|
};
|
|
67657
67912
|
}
|
|
67658
67913
|
}
|
|
67659
|
-
async function appendSandboxTextFile(sandbox,
|
|
67914
|
+
async function appendSandboxTextFile(sandbox, path10, text2) {
|
|
67660
67915
|
const tempPath = `/tmp/hackerai_append_${Date.now()}_${Math.random().toString(36).slice(2)}.tmp`;
|
|
67661
67916
|
await sandbox.files.write(tempPath, text2, {
|
|
67662
67917
|
user: "user"
|
|
@@ -67665,7 +67920,7 @@ async function appendSandboxTextFile(sandbox, path8, text2) {
|
|
|
67665
67920
|
sandbox,
|
|
67666
67921
|
APPEND_TEXT_FILE_SCRIPT,
|
|
67667
67922
|
{
|
|
67668
|
-
HACKERAI_FILE_APPEND_TARGET_PATH: getPythonPathForSandbox(sandbox,
|
|
67923
|
+
HACKERAI_FILE_APPEND_TARGET_PATH: getPythonPathForSandbox(sandbox, path10),
|
|
67669
67924
|
HACKERAI_FILE_APPEND_SOURCE_PATH: getPythonPathForSandbox(
|
|
67670
67925
|
sandbox,
|
|
67671
67926
|
tempPath
|
|
@@ -67677,13 +67932,13 @@ async function appendSandboxTextFile(sandbox, path8, text2) {
|
|
|
67677
67932
|
throw new Error(result.stderr || result.stdout || "Failed to append file");
|
|
67678
67933
|
}
|
|
67679
67934
|
}
|
|
67680
|
-
async function readSandboxFileForView(sandbox,
|
|
67935
|
+
async function readSandboxFileForView(sandbox, path10, includeData) {
|
|
67681
67936
|
if (isCentrifugoSandbox(sandbox) && sandbox.isWindows()) {
|
|
67682
67937
|
throw new Error(
|
|
67683
67938
|
"The view action is not available for Windows local sandboxes yet. Use a Linux/E2B sandbox or inspect the image manually."
|
|
67684
67939
|
);
|
|
67685
67940
|
}
|
|
67686
|
-
const sandboxPath = getSandboxViewPath(sandbox,
|
|
67941
|
+
const sandboxPath = getSandboxViewPath(sandbox, path10);
|
|
67687
67942
|
const viewEnvVars = {
|
|
67688
67943
|
HACKERAI_FILE_VIEW_PATH: sandboxPath,
|
|
67689
67944
|
HACKERAI_FILE_VIEW_INCLUDE_DATA: includeData ? "1" : "0",
|
|
@@ -68026,19 +68281,19 @@ try:
|
|
|
68026
68281
|
except OSError:
|
|
68027
68282
|
pass
|
|
68028
68283
|
`;
|
|
68029
|
-
getFilename = (
|
|
68030
|
-
getFileExtension = (
|
|
68031
|
-
const filename = getFilename(
|
|
68284
|
+
getFilename = (path10) => path10.split("/").pop() || path10;
|
|
68285
|
+
getFileExtension = (path10) => {
|
|
68286
|
+
const filename = getFilename(path10);
|
|
68032
68287
|
const dotIndex = filename.lastIndexOf(".");
|
|
68033
68288
|
if (dotIndex <= 0 || dotIndex === filename.length - 1) return void 0;
|
|
68034
68289
|
return filename.slice(dotIndex + 1).toLowerCase();
|
|
68035
68290
|
};
|
|
68036
|
-
getSandboxViewPath = (sandbox,
|
|
68291
|
+
getSandboxViewPath = (sandbox, path10) => {
|
|
68037
68292
|
const maybeSandbox = sandbox;
|
|
68038
|
-
if (isCentrifugoSandbox(maybeSandbox) && maybeSandbox.isWindows() &&
|
|
68039
|
-
return `C:\\temp${
|
|
68293
|
+
if (isCentrifugoSandbox(maybeSandbox) && maybeSandbox.isWindows() && path10.startsWith("/tmp/")) {
|
|
68294
|
+
return `C:\\temp${path10.slice(4).replace(/\//g, "\\")}`;
|
|
68040
68295
|
}
|
|
68041
|
-
return
|
|
68296
|
+
return path10;
|
|
68042
68297
|
};
|
|
68043
68298
|
stripTrailingWs = (line) => line.replace(/[ \t]+$/u, "");
|
|
68044
68299
|
editSchema = external_exports.object({
|
|
@@ -68112,7 +68367,7 @@ ${instructionsDescription}`,
|
|
|
68112
68367
|
"A list of edits to be sequentially applied to the file. Required for `edit` action."
|
|
68113
68368
|
)
|
|
68114
68369
|
}),
|
|
68115
|
-
execute: async ({ action, path:
|
|
68370
|
+
execute: async ({ action, path: path10, text: text2, range, edits }) => {
|
|
68116
68371
|
try {
|
|
68117
68372
|
const { sandbox } = await sandboxManager.getSandbox();
|
|
68118
68373
|
switch (action) {
|
|
@@ -68122,7 +68377,7 @@ ${instructionsDescription}`,
|
|
|
68122
68377
|
captureFileViewImageUsage({
|
|
68123
68378
|
context: context2,
|
|
68124
68379
|
sandbox,
|
|
68125
|
-
path:
|
|
68380
|
+
path: path10,
|
|
68126
68381
|
outcome: "unsupported_model",
|
|
68127
68382
|
durationMs: Date.now() - viewStartedAt,
|
|
68128
68383
|
failureReason: "unsupported_model"
|
|
@@ -68131,26 +68386,26 @@ ${instructionsDescription}`,
|
|
|
68131
68386
|
}
|
|
68132
68387
|
let viewPayload;
|
|
68133
68388
|
try {
|
|
68134
|
-
viewPayload = await readSandboxFileForView(sandbox,
|
|
68389
|
+
viewPayload = await readSandboxFileForView(sandbox, path10, false);
|
|
68135
68390
|
} catch (error51) {
|
|
68136
68391
|
captureFileViewImageUsage({
|
|
68137
68392
|
context: context2,
|
|
68138
68393
|
sandbox,
|
|
68139
|
-
path:
|
|
68394
|
+
path: path10,
|
|
68140
68395
|
outcome: "inspection_failed",
|
|
68141
68396
|
durationMs: Date.now() - viewStartedAt,
|
|
68142
68397
|
failureReason: classifyFileViewError(error51)
|
|
68143
68398
|
});
|
|
68144
68399
|
throw error51;
|
|
68145
68400
|
}
|
|
68146
|
-
const filename = getFilename(
|
|
68401
|
+
const filename = getFilename(path10);
|
|
68147
68402
|
let previewFiles = [];
|
|
68148
68403
|
let previewUploadError;
|
|
68149
68404
|
try {
|
|
68150
68405
|
previewFiles = await uploadViewPreviewFiles({
|
|
68151
68406
|
context: context2,
|
|
68152
68407
|
sandbox,
|
|
68153
|
-
sourcePath:
|
|
68408
|
+
sourcePath: path10,
|
|
68154
68409
|
payload: viewPayload
|
|
68155
68410
|
});
|
|
68156
68411
|
} catch (error51) {
|
|
@@ -68164,7 +68419,7 @@ ${instructionsDescription}`,
|
|
|
68164
68419
|
user_id: context2.userID,
|
|
68165
68420
|
sandbox_type: getViewSandboxType(sandbox),
|
|
68166
68421
|
file_name: filename,
|
|
68167
|
-
source_path:
|
|
68422
|
+
source_path: path10,
|
|
68168
68423
|
kind: viewPayload.kind,
|
|
68169
68424
|
media_type: viewPayload.mediaType,
|
|
68170
68425
|
size_bytes: viewPayload.sizeBytes,
|
|
@@ -68175,7 +68430,7 @@ ${instructionsDescription}`,
|
|
|
68175
68430
|
captureFileViewImageUsage({
|
|
68176
68431
|
context: context2,
|
|
68177
68432
|
sandbox,
|
|
68178
|
-
path:
|
|
68433
|
+
path: path10,
|
|
68179
68434
|
outcome: "success",
|
|
68180
68435
|
durationMs: Date.now() - viewStartedAt,
|
|
68181
68436
|
mediaType: viewPayload.mediaType,
|
|
@@ -68185,7 +68440,7 @@ ${instructionsDescription}`,
|
|
|
68185
68440
|
return {
|
|
68186
68441
|
action: "view",
|
|
68187
68442
|
content: `Viewing image file: ${filename} (${viewPayload.mediaType}, ${viewPayload.sizeBytes} bytes).`,
|
|
68188
|
-
path:
|
|
68443
|
+
path: path10,
|
|
68189
68444
|
filename,
|
|
68190
68445
|
mediaType: viewPayload.mediaType,
|
|
68191
68446
|
sizeBytes: viewPayload.sizeBytes,
|
|
@@ -68195,8 +68450,8 @@ ${instructionsDescription}`,
|
|
|
68195
68450
|
};
|
|
68196
68451
|
}
|
|
68197
68452
|
case "read": {
|
|
68198
|
-
const filename =
|
|
68199
|
-
const spritChunked = isSpritPath(
|
|
68453
|
+
const filename = path10.split("/").pop() || path10;
|
|
68454
|
+
const spritChunked = isSpritPath(path10);
|
|
68200
68455
|
let effectiveRange = range;
|
|
68201
68456
|
if (spritChunked) {
|
|
68202
68457
|
const start = range && range[0] > 0 ? range[0] : 1;
|
|
@@ -68209,7 +68464,7 @@ ${instructionsDescription}`,
|
|
|
68209
68464
|
}
|
|
68210
68465
|
const readPayload = await readSandboxTextFileWithFallback(
|
|
68211
68466
|
sandbox,
|
|
68212
|
-
|
|
68467
|
+
path10,
|
|
68213
68468
|
effectiveRange
|
|
68214
68469
|
);
|
|
68215
68470
|
if (readPayload.tooLarge) {
|
|
@@ -68246,46 +68501,46 @@ File is too large to read in full (${formatBytes(readPayload.sizeBytes)}, ${tota
|
|
|
68246
68501
|
if (text2 === void 0) {
|
|
68247
68502
|
return { error: "text is required for write action" };
|
|
68248
68503
|
}
|
|
68249
|
-
await sandbox.files.write(
|
|
68504
|
+
await sandbox.files.write(path10, text2, {
|
|
68250
68505
|
user: "user"
|
|
68251
68506
|
});
|
|
68252
|
-
return `File written: ${
|
|
68507
|
+
return `File written: ${path10}`;
|
|
68253
68508
|
}
|
|
68254
68509
|
case "append": {
|
|
68255
68510
|
if (text2 === void 0) {
|
|
68256
68511
|
return { error: "text is required for append action" };
|
|
68257
68512
|
}
|
|
68258
|
-
const existingState = await getSandboxFileState(sandbox,
|
|
68513
|
+
const existingState = await getSandboxFileState(sandbox, path10);
|
|
68259
68514
|
if (existingState.kind === "unknown") {
|
|
68260
68515
|
return {
|
|
68261
|
-
error: `Cannot append safely because the existing file size could not be determined for ${
|
|
68516
|
+
error: `Cannot append safely because the existing file size could not be determined for ${path10}. ${existingState.error}`
|
|
68262
68517
|
};
|
|
68263
68518
|
}
|
|
68264
68519
|
if (existingState.kind === "not_file") {
|
|
68265
68520
|
return {
|
|
68266
|
-
error: `Cannot append to ${
|
|
68521
|
+
error: `Cannot append to ${path10} because it is not a file.`
|
|
68267
68522
|
};
|
|
68268
68523
|
}
|
|
68269
68524
|
if (existingState.kind === "file" && existingState.sizeBytes > MAX_TEXT_FILE_READ_BYTES) {
|
|
68270
|
-
await appendSandboxTextFile(sandbox,
|
|
68525
|
+
await appendSandboxTextFile(sandbox, path10, text2);
|
|
68271
68526
|
return {
|
|
68272
|
-
content: `File appended: ${
|
|
68527
|
+
content: `File appended: ${path10}
|
|
68273
68528
|
Existing file is ${formatBytes(existingState.sizeBytes)}, so the full diff preview was skipped to avoid loading the entire file into memory.`
|
|
68274
68529
|
};
|
|
68275
68530
|
}
|
|
68276
68531
|
let existingContent = "";
|
|
68277
68532
|
try {
|
|
68278
|
-
existingContent = await sandbox.files.read(
|
|
68533
|
+
existingContent = await sandbox.files.read(path10, {
|
|
68279
68534
|
user: "user"
|
|
68280
68535
|
});
|
|
68281
68536
|
} catch {
|
|
68282
68537
|
}
|
|
68283
68538
|
const newContent = existingContent + text2;
|
|
68284
|
-
await sandbox.files.write(
|
|
68539
|
+
await sandbox.files.write(path10, newContent, {
|
|
68285
68540
|
user: "user"
|
|
68286
68541
|
});
|
|
68287
68542
|
return {
|
|
68288
|
-
content: `File appended: ${
|
|
68543
|
+
content: `File appended: ${path10}`,
|
|
68289
68544
|
originalContent: truncateOutput({
|
|
68290
68545
|
content: existingContent,
|
|
68291
68546
|
mode: "read-file"
|
|
@@ -68300,31 +68555,31 @@ Existing file is ${formatBytes(existingState.sizeBytes)}, so the full diff previ
|
|
|
68300
68555
|
if (!edits || edits.length === 0) {
|
|
68301
68556
|
return { error: "edits array is required for edit action" };
|
|
68302
68557
|
}
|
|
68303
|
-
const existingState = await getSandboxFileState(sandbox,
|
|
68558
|
+
const existingState = await getSandboxFileState(sandbox, path10);
|
|
68304
68559
|
if (existingState.kind === "unknown") {
|
|
68305
68560
|
return {
|
|
68306
|
-
error: `Cannot edit ${
|
|
68561
|
+
error: `Cannot edit ${path10} safely because the file size could not be determined. ${existingState.error}`
|
|
68307
68562
|
};
|
|
68308
68563
|
}
|
|
68309
68564
|
if (existingState.kind === "missing") {
|
|
68310
68565
|
return {
|
|
68311
|
-
error: `Cannot edit file ${
|
|
68566
|
+
error: `Cannot edit file ${path10} - file is empty or does not exist`
|
|
68312
68567
|
};
|
|
68313
68568
|
}
|
|
68314
68569
|
if (existingState.kind === "not_file") {
|
|
68315
|
-
return { error: `Cannot edit ${
|
|
68570
|
+
return { error: `Cannot edit ${path10} because it is not a file.` };
|
|
68316
68571
|
}
|
|
68317
68572
|
if (existingState.sizeBytes > MAX_TEXT_FILE_READ_BYTES) {
|
|
68318
68573
|
return {
|
|
68319
|
-
error: `File ${
|
|
68574
|
+
error: `File ${path10} is too large for the edit action (${formatBytes(existingState.sizeBytes)}). Use a targeted shell command, restore the file from a clean source, or replace it with the write action instead of loading the whole file into memory.`
|
|
68320
68575
|
};
|
|
68321
68576
|
}
|
|
68322
|
-
const originalContent = await sandbox.files.read(
|
|
68577
|
+
const originalContent = await sandbox.files.read(path10, {
|
|
68323
68578
|
user: "user"
|
|
68324
68579
|
});
|
|
68325
68580
|
if (!originalContent) {
|
|
68326
68581
|
return {
|
|
68327
|
-
error: `Cannot edit file ${
|
|
68582
|
+
error: `Cannot edit file ${path10} - file is empty or does not exist`
|
|
68328
68583
|
};
|
|
68329
68584
|
}
|
|
68330
68585
|
const resolvedEdits = [];
|
|
@@ -68369,7 +68624,7 @@ ${hint}` : "")
|
|
|
68369
68624
|
}
|
|
68370
68625
|
}
|
|
68371
68626
|
}
|
|
68372
|
-
await sandbox.files.write(
|
|
68627
|
+
await sandbox.files.write(path10, content, {
|
|
68373
68628
|
user: "user"
|
|
68374
68629
|
});
|
|
68375
68630
|
const lines = content.split("\n");
|
|
@@ -68609,11 +68864,11 @@ function findGitBash() {
|
|
|
68609
68864
|
if ((0, import_fs.existsSync)(c)) return c;
|
|
68610
68865
|
}
|
|
68611
68866
|
try {
|
|
68612
|
-
const
|
|
68867
|
+
const out3 = (0, import_child_process.execSync)("where git", {
|
|
68613
68868
|
encoding: "utf8",
|
|
68614
68869
|
stdio: ["ignore", "pipe", "ignore"]
|
|
68615
68870
|
});
|
|
68616
|
-
const gitExe =
|
|
68871
|
+
const gitExe = out3.split(/\r?\n/).find((l) => l.trim().endsWith("git.exe"));
|
|
68617
68872
|
if (gitExe) {
|
|
68618
68873
|
const bash = (0, import_path3.join)((0, import_path3.dirname)((0, import_path3.dirname)(gitExe.trim())), "bin", "bash.exe");
|
|
68619
68874
|
if ((0, import_fs.existsSync)(bash)) return bash;
|
|
@@ -68652,14 +68907,14 @@ function inferShellFlag(shell2) {
|
|
|
68652
68907
|
}
|
|
68653
68908
|
return "-c";
|
|
68654
68909
|
}
|
|
68655
|
-
var import_node_child_process2, import_node_fs6, import_node_path5,
|
|
68910
|
+
var import_node_child_process2, import_node_fs6, import_node_path5, import_node_os3, import_node_url, import_meta, LocalSandbox;
|
|
68656
68911
|
var init_local_sandbox = __esm({
|
|
68657
68912
|
"src/local-sandbox.ts"() {
|
|
68658
68913
|
"use strict";
|
|
68659
68914
|
import_node_child_process2 = require("node:child_process");
|
|
68660
68915
|
import_node_fs6 = require("node:fs");
|
|
68661
68916
|
import_node_path5 = __toESM(require("node:path"));
|
|
68662
|
-
|
|
68917
|
+
import_node_os3 = __toESM(require("node:os"));
|
|
68663
68918
|
import_node_url = require("node:url");
|
|
68664
68919
|
init_utils4();
|
|
68665
68920
|
import_meta = {};
|
|
@@ -68784,7 +69039,7 @@ var init_local_sandbox = __esm({
|
|
|
68784
69039
|
this.shellBin = shellOverride;
|
|
68785
69040
|
this.shellFlag = process.env.CLI_SHELL_FLAG || inferShellFlag(shellOverride);
|
|
68786
69041
|
} else {
|
|
68787
|
-
const shell2 = getDefaultShell(
|
|
69042
|
+
const shell2 = getDefaultShell(import_node_os3.default.platform());
|
|
68788
69043
|
this.shellBin = shell2.shell;
|
|
68789
69044
|
this.shellFlag = shell2.shellFlag;
|
|
68790
69045
|
}
|
|
@@ -68794,6 +69049,7 @@ var init_local_sandbox = __esm({
|
|
|
68794
69049
|
async init() {
|
|
68795
69050
|
await import_node_fs6.promises.mkdir(this.workdir, { recursive: true });
|
|
68796
69051
|
await this.seedReconToolkit();
|
|
69052
|
+
await this.seedAuditToolkit();
|
|
68797
69053
|
}
|
|
68798
69054
|
/**
|
|
68799
69055
|
* Seed the deep-recon toolkit (recon_deep.py + console_recon.js + README)
|
|
@@ -68834,27 +69090,50 @@ var init_local_sandbox = __esm({
|
|
|
68834
69090
|
} catch {
|
|
68835
69091
|
}
|
|
68836
69092
|
}
|
|
69093
|
+
/**
|
|
69094
|
+
* Seed the read-only project-audit toolkit (project_audit.py + README) into
|
|
69095
|
+
* <workdir>/audit so the agent can deeply analyze the user's own project on
|
|
69096
|
+
* demand. Tooling files are refreshed each session so fixes propagate.
|
|
69097
|
+
* Best-effort: a failure here must never block the session.
|
|
69098
|
+
*/
|
|
69099
|
+
async seedAuditToolkit() {
|
|
69100
|
+
try {
|
|
69101
|
+
const assetsDir = (0, import_node_url.fileURLToPath)(
|
|
69102
|
+
new URL("../assets/audit", import_meta.url)
|
|
69103
|
+
);
|
|
69104
|
+
const destDir = import_node_path5.default.join(this.workdir, "audit");
|
|
69105
|
+
await import_node_fs6.promises.mkdir(destDir, { recursive: true });
|
|
69106
|
+
for (const name25 of ["project_audit.py", "README.md"]) {
|
|
69107
|
+
try {
|
|
69108
|
+
const content = await import_node_fs6.promises.readFile(import_node_path5.default.join(assetsDir, name25));
|
|
69109
|
+
await import_node_fs6.promises.writeFile(import_node_path5.default.join(destDir, name25), content);
|
|
69110
|
+
} catch {
|
|
69111
|
+
}
|
|
69112
|
+
}
|
|
69113
|
+
} catch {
|
|
69114
|
+
}
|
|
69115
|
+
}
|
|
68837
69116
|
getConnectionId() {
|
|
68838
69117
|
return "local";
|
|
68839
69118
|
}
|
|
68840
69119
|
getConnectionName() {
|
|
68841
|
-
return `local:${
|
|
69120
|
+
return `local:${import_node_os3.default.hostname()}`;
|
|
68842
69121
|
}
|
|
68843
69122
|
getUserId() {
|
|
68844
69123
|
return "local";
|
|
68845
69124
|
}
|
|
68846
69125
|
isWindows() {
|
|
68847
|
-
return
|
|
69126
|
+
return import_node_os3.default.platform() === "win32" && !this.isBashLikeShell();
|
|
68848
69127
|
}
|
|
68849
69128
|
supportsPty() {
|
|
68850
69129
|
return false;
|
|
68851
69130
|
}
|
|
68852
69131
|
getSandboxContext() {
|
|
68853
|
-
const platform = `${
|
|
69132
|
+
const platform = `${import_node_os3.default.type()} ${import_node_os3.default.release()} (${import_node_os3.default.arch()})`;
|
|
68854
69133
|
const shellInvocation = `${this.shellBin} ${this.shellFlag}`;
|
|
68855
|
-
const windowsNotes =
|
|
69134
|
+
const windowsNotes = import_node_os3.default.platform() === "win32" ? this.getWindowsShellNotes() : "";
|
|
68856
69135
|
const pentestToolingNotes = this.getLocalPentestToolingNotes();
|
|
68857
|
-
return `You are executing commands directly on the user's local host (${platform}, hostname "${
|
|
69136
|
+
return `You are executing commands directly on the user's local host (${platform}, hostname "${import_node_os3.default.hostname()}") in DANGEROUS MODE: there is NO sandbox isolation.
|
|
68858
69137
|
Commands are invoked via \`${shellInvocation}\`. The working directory is "${this.workdir}".
|
|
68859
69138
|
Be careful: file system, network and process operations all affect the real host system.
|
|
68860
69139
|
A real human user is present at this terminal. When a command prompts for input \u2014 a password, a y/n confirmation, an interactive installer, a REPL prompt (python, mysql, ftp), an ssh/sudo prompt, etc. \u2014 the user types the answer and it is forwarded to the command's stdin. So you MAY run commands that prompt for input; just run the command and the user will respond when asked. Prefer non-interactive flags (like --yes) when they exist and are convenient, but interactive prompts are fully supported. Only full-screen / raw-mode TUI programs (vim, top, htop, less without \`| cat\`) are unsupported, since there is no PTY \u2014 avoid those and use line-oriented alternatives.
|
|
@@ -68879,6 +69158,21 @@ EDITING SCRIPTS:
|
|
|
68879
69158
|
getOsContext() {
|
|
68880
69159
|
return this.getSandboxContext();
|
|
68881
69160
|
}
|
|
69161
|
+
/**
|
|
69162
|
+
* One concise paragraph about the shell the agent's commands run in, plus the
|
|
69163
|
+
* critical "each command is a fresh shell" rule. Used by the standalone audit
|
|
69164
|
+
* prompt, which doesn't carry the full sandbox context.
|
|
69165
|
+
*/
|
|
69166
|
+
getShellHint() {
|
|
69167
|
+
const persist = "IMPORTANTE: cada comando roda num shell NOVO \u2014 vari\xE1veis, `export`/`set` e mudan\xE7as de PATH N\xC3O persistem para o pr\xF3ximo comando. Chame cada ferramenta pelo caminho completo, por um lan\xE7ador que resolve o PATH (`npx <pkg>`), ou via `python -m <modulo>`.";
|
|
69168
|
+
if (this.isBashLikeShell()) {
|
|
69169
|
+
return `Shell: ${this.shellBin} (POSIX, tipo Git Bash). Use sintaxe bash: \`export VAR=...\`, \`command -v ferramenta\`, \`which\`. N\xC3O use \`set VAR=\` nem \`where\` do cmd. ${persist}`;
|
|
69170
|
+
}
|
|
69171
|
+
if (this.isCmdShell()) {
|
|
69172
|
+
return `Shell: cmd.exe. Use \`where ferramenta\` e \`set VAR=...\`; evite sintaxe bash (\`export\`, \`$(...)\`, heredoc). ${persist}`;
|
|
69173
|
+
}
|
|
69174
|
+
return `Shell: ${this.shellBin}. Verifique a sintaxe antes de assumir bash ou cmd. ${persist}`;
|
|
69175
|
+
}
|
|
68882
69176
|
getWorkdir() {
|
|
68883
69177
|
return this.workdir;
|
|
68884
69178
|
}
|
|
@@ -68928,7 +69222,7 @@ EDITING SCRIPTS:
|
|
|
68928
69222
|
// alive — `taskkill /T` tears down the whole tree so Ctrl+C truly stops it.
|
|
68929
69223
|
killChildTree(child) {
|
|
68930
69224
|
const pid = child.pid;
|
|
68931
|
-
if (pid &&
|
|
69225
|
+
if (pid && import_node_os3.default.platform() === "win32") {
|
|
68932
69226
|
try {
|
|
68933
69227
|
(0, import_node_child_process2.spawn)("taskkill", ["/PID", String(pid), "/T", "/F"], {
|
|
68934
69228
|
windowsHide: true
|
|
@@ -68983,7 +69277,7 @@ WINDOWS SHELL NOTES:
|
|
|
68983
69277
|
- For HTTP, prefer \`curl.exe\` if available; for DNS use \`nslookup\`.`;
|
|
68984
69278
|
}
|
|
68985
69279
|
getLocalPentestToolingNotes() {
|
|
68986
|
-
if (
|
|
69280
|
+
if (import_node_os3.default.platform() === "win32") {
|
|
68987
69281
|
return `
|
|
68988
69282
|
|
|
68989
69283
|
LOCAL PENTEST TOOLING:
|
|
@@ -69102,10 +69396,10 @@ function createRenderer() {
|
|
|
69102
69396
|
reasoning(delta) {
|
|
69103
69397
|
sep3("reasoning");
|
|
69104
69398
|
if (!reasoningHeaderShown) {
|
|
69105
|
-
out(`${
|
|
69399
|
+
out(`${C3.dim}pensando: `);
|
|
69106
69400
|
reasoningHeaderShown = true;
|
|
69107
69401
|
}
|
|
69108
|
-
out(`${
|
|
69402
|
+
out(`${C3.dim}${delta}${C3.reset}`);
|
|
69109
69403
|
},
|
|
69110
69404
|
toolCall(toolName, input) {
|
|
69111
69405
|
sep3("tool");
|
|
@@ -69117,23 +69411,23 @@ function createRenderer() {
|
|
|
69117
69411
|
const note = summarizeResult(toolName, output);
|
|
69118
69412
|
if (note) {
|
|
69119
69413
|
sep3("tool");
|
|
69120
|
-
out(`${
|
|
69414
|
+
out(`${C3.dim} ok ${note}${C3.reset}
|
|
69121
69415
|
`);
|
|
69122
69416
|
}
|
|
69123
69417
|
},
|
|
69124
69418
|
info(msg) {
|
|
69125
69419
|
sep3("info");
|
|
69126
|
-
out(`${
|
|
69420
|
+
out(`${C3.dim}${msg}${C3.reset}
|
|
69127
69421
|
`);
|
|
69128
69422
|
},
|
|
69129
69423
|
fallback(msg) {
|
|
69130
69424
|
sep3("info");
|
|
69131
|
-
out(`${
|
|
69425
|
+
out(`${C3.yellow}-> ${msg}${C3.reset}
|
|
69132
69426
|
`);
|
|
69133
69427
|
},
|
|
69134
69428
|
error(msg) {
|
|
69135
69429
|
sep3("info");
|
|
69136
|
-
out(`${
|
|
69430
|
+
out(`${C3.red}x ${msg}${C3.reset}
|
|
69137
69431
|
`);
|
|
69138
69432
|
},
|
|
69139
69433
|
endTurn() {
|
|
@@ -69151,31 +69445,31 @@ function formatToolCall(toolName, input) {
|
|
|
69151
69445
|
switch (toolName) {
|
|
69152
69446
|
case "run_terminal_cmd": {
|
|
69153
69447
|
const cmd = String(i.command ?? "").trim();
|
|
69154
|
-
const bg = i.is_background ? `${
|
|
69155
|
-
return `${
|
|
69448
|
+
const bg = i.is_background ? `${C3.dim} (background)${C3.reset}` : "";
|
|
69449
|
+
return `${C3.cyan}executando${C3.reset} ${C3.bold}$ ${truncate3(cmd, 400)}${C3.reset}${bg}`;
|
|
69156
69450
|
}
|
|
69157
69451
|
case "file": {
|
|
69158
|
-
const
|
|
69159
|
-
const brief = i.brief ? `${
|
|
69452
|
+
const path10 = String(i.path ?? "");
|
|
69453
|
+
const brief = i.brief ? `${C3.dim} - ${truncate3(String(i.brief))}${C3.reset}` : "";
|
|
69160
69454
|
const map2 = {
|
|
69161
|
-
write: `${
|
|
69162
|
-
edit: `${
|
|
69163
|
-
append: `${
|
|
69164
|
-
read: `${
|
|
69165
|
-
view: `${
|
|
69455
|
+
write: `${C3.green}criando arquivo${C3.reset}`,
|
|
69456
|
+
edit: `${C3.yellow}editando arquivo${C3.reset}`,
|
|
69457
|
+
append: `${C3.green}anexando arquivo${C3.reset}`,
|
|
69458
|
+
read: `${C3.blue}lendo arquivo${C3.reset}`,
|
|
69459
|
+
view: `${C3.blue}visualizando arquivo${C3.reset}`
|
|
69166
69460
|
};
|
|
69167
69461
|
const action = typeof i.action === "string" ? i.action : "";
|
|
69168
|
-
const label = map2[action] ?? (action ? `${
|
|
69169
|
-
const target =
|
|
69462
|
+
const label = map2[action] ?? (action ? `${C3.blue}arquivo (${action})${C3.reset}` : `${C3.blue}preparando operacao de arquivo${C3.reset}`);
|
|
69463
|
+
const target = path10 ? ` ${C3.bold}${path10}${C3.reset}` : "";
|
|
69170
69464
|
return `${label}${target}${brief}`;
|
|
69171
69465
|
}
|
|
69172
69466
|
case "todo_write":
|
|
69173
|
-
return `${
|
|
69467
|
+
return `${C3.magenta}atualizando lista de tarefas${C3.reset}`;
|
|
69174
69468
|
default:
|
|
69175
|
-
return `${
|
|
69469
|
+
return `${C3.cyan}${toolName}${C3.reset} ${C3.dim}${truncate3(
|
|
69176
69470
|
JSON.stringify(i),
|
|
69177
69471
|
200
|
|
69178
|
-
)}${
|
|
69472
|
+
)}${C3.reset}`;
|
|
69179
69473
|
}
|
|
69180
69474
|
}
|
|
69181
69475
|
function summarizeResult(toolName, output) {
|
|
@@ -69189,11 +69483,11 @@ function summarizeResult(toolName, output) {
|
|
|
69189
69483
|
if (toolName === "todo_write") return "tarefas salvas";
|
|
69190
69484
|
return null;
|
|
69191
69485
|
}
|
|
69192
|
-
var
|
|
69486
|
+
var C3, out, truncate3;
|
|
69193
69487
|
var init_render = __esm({
|
|
69194
69488
|
"src/render.ts"() {
|
|
69195
69489
|
"use strict";
|
|
69196
|
-
|
|
69490
|
+
C3 = {
|
|
69197
69491
|
reset: "\x1B[0m",
|
|
69198
69492
|
dim: "\x1B[90m",
|
|
69199
69493
|
red: "\x1B[31m",
|
|
@@ -69331,11 +69625,11 @@ async function ensureProxyReady(id, log2) {
|
|
|
69331
69625
|
message: `${def.label}: o proxy n\xE3o respondeu em 90s. Tente de novo, ou rode 'npm run login' em ${dir}.`
|
|
69332
69626
|
};
|
|
69333
69627
|
}
|
|
69334
|
-
var
|
|
69628
|
+
var import_node_os4, import_node_path6, import_node_fs7, import_node_child_process3, DEFS, PROXY_MODEL_KEYS, proxyIdForModelKey, proxiesRoot, dirFor, healthUrl, baseUrl, wait, started, exitHooksInstalled, quoteArg, asShellCommand, run, hasCommand;
|
|
69335
69629
|
var init_proxy_manager2 = __esm({
|
|
69336
69630
|
"src/proxy-manager.ts"() {
|
|
69337
69631
|
"use strict";
|
|
69338
|
-
|
|
69632
|
+
import_node_os4 = __toESM(require("node:os"));
|
|
69339
69633
|
import_node_path6 = __toESM(require("node:path"));
|
|
69340
69634
|
import_node_fs7 = require("node:fs");
|
|
69341
69635
|
import_node_child_process3 = require("node:child_process");
|
|
@@ -69371,7 +69665,7 @@ var init_proxy_manager2 = __esm({
|
|
|
69371
69665
|
return null;
|
|
69372
69666
|
};
|
|
69373
69667
|
proxiesRoot = () => import_node_path6.default.join(
|
|
69374
|
-
process.env.CLAWFAST_HOME?.trim() || import_node_path6.default.join(
|
|
69668
|
+
process.env.CLAWFAST_HOME?.trim() || import_node_path6.default.join(import_node_os4.default.homedir(), ".clawfast"),
|
|
69375
69669
|
"proxies"
|
|
69376
69670
|
);
|
|
69377
69671
|
dirFor = (def) => process.env[def.dirEnv]?.trim() || import_node_path6.default.join(proxiesRoot(), def.folder);
|
|
@@ -69401,15 +69695,210 @@ var init_proxy_manager2 = __esm({
|
|
|
69401
69695
|
}
|
|
69402
69696
|
});
|
|
69403
69697
|
|
|
69698
|
+
// src/audit-mode.ts
|
|
69699
|
+
function projectRootFromWorkdir(workdir) {
|
|
69700
|
+
return import_node_path7.default.dirname(import_node_path7.default.resolve(workdir.replace(/\\/g, "/")));
|
|
69701
|
+
}
|
|
69702
|
+
function detectProjectAuditIntent(input) {
|
|
69703
|
+
const text2 = input.trim();
|
|
69704
|
+
if (!text2) return false;
|
|
69705
|
+
if (AUDIT_ACTION_THEN_SCOPE.test(text2)) return true;
|
|
69706
|
+
if (AUDIT_SCOPE_THEN_ACTION.test(text2)) return true;
|
|
69707
|
+
return AUDIT_STRONG.some((re2) => re2.test(text2));
|
|
69708
|
+
}
|
|
69709
|
+
function detectAuditExitIntent(input) {
|
|
69710
|
+
const text2 = input.trim();
|
|
69711
|
+
if (!text2) return false;
|
|
69712
|
+
return AUDIT_EXIT.some((re2) => re2.test(text2));
|
|
69713
|
+
}
|
|
69714
|
+
function buildAuditSystemPrompt(opts) {
|
|
69715
|
+
const root = opts.projectRoot.replace(/\\/g, "/");
|
|
69716
|
+
const workdir = opts.workdir.replace(/\\/g, "/");
|
|
69717
|
+
const isWin = (opts.platform ?? process.platform) === "win32";
|
|
69718
|
+
const py = isWin ? "python" : "python3";
|
|
69719
|
+
const shellNote = isWin ? "Voc\xEA est\xE1 em Windows. Use `python` (n\xE3o `python3`), aspas em caminhos com espa\xE7os, e `/` ou `\\` indiferente nos caminhos." : "Use `python3` quando `python` n\xE3o existir.";
|
|
69720
|
+
const shellHint = opts.shellHint ?? shellNote;
|
|
69721
|
+
const toolkit = `"${workdir}/audit/project_audit.py"`;
|
|
69722
|
+
return `Voc\xEA \xE9 o **HackerAI Auditor** \u2014 um ORQUESTRADOR de auditoria de SEGURAN\xC7A DE APLICA\xC7\xD5ES e ARQUITETURA DE C\xD3DIGO, operando em modo SOMENTE LEITURA dentro do terminal do VS Code, no projeto REAL do usu\xE1rio.
|
|
69723
|
+
|
|
69724
|
+
FILOSOFIA (estado da arte \u2014 h\xEDbrido, n\xE3o LLM puro):
|
|
69725
|
+
Voc\xEA N\xC3O \xE9 um LLM que l\xEA o projeto inteiro linha a linha. Voc\xEA \xE9 um orquestrador que roda FERRAMENTAS DETERMIN\xCDSTICAS para o trabalho pesado (mapeamento, SAST, depend\xEAncias, segredos) e usa o RACIOC\xCDNIO DO MODELO s\xF3 para o que ferramenta gr\xE1tis nenhuma faz bem: **taint cross-module** (seguir o dado que cruza fronteira de fun\xE7\xE3o/arquivo) e **valida\xE7\xE3o** de cada achado lendo o c\xF3digo real. LLM puro infla recall mas explode falso-positivo; ferramenta pura perde sem\xE2ntica inter-procedural; o h\xEDbrido ganha. O Semgrep gr\xE1tis s\xF3 faz taint INTRA-procedural (dentro de uma fun\xE7\xE3o) \u2014 a propaga\xE7\xE3o que atravessa imports \xE9 exatamente o buraco que o seu racioc\xEDnio preenche.
|
|
69726
|
+
|
|
69727
|
+
Miss\xE3o desta sess\xE3o: an\xE1lise extremamente precisa e profunda do projeto inteiro e entrega de **um relat\xF3rio** acion\xE1vel e honesto. Ferramentas do agente: \`run_terminal_cmd\`, \`file\`, \`todo_write\`.
|
|
69728
|
+
|
|
69729
|
+
PROJETO SOB AN\xC1LISE (raiz): ${root}
|
|
69730
|
+
WORKSPACE DE TRABALHO (ferramentas/sa\xEDdas intermedi\xE1rias): ${workdir}
|
|
69731
|
+
SA\xCDDAS INTERMEDI\xC1RIAS: grave JSON/tempor\xE1rios em \`${workdir}/audit-out/\` (crie a pasta). N\xC3O use /tmp (pode n\xE3o existir no Windows).
|
|
69732
|
+
|
|
69733
|
+
================================================================
|
|
69734
|
+
REGRA ANTI-ALUCINA\xC7\xC3O \u2014 A MAIS IMPORTANTE
|
|
69735
|
+
================================================================
|
|
69736
|
+
Um relat\xF3rio de seguran\xE7a inventado \xE9 PIOR que nenhum \u2014 \xE9 perigoso. Portanto:
|
|
69737
|
+
1. Voc\xEA s\xF3 pode relatar um achado que veio de DADOS REAIS que voc\xEA LEU nesta sess\xE3o: a sa\xEDda de uma ferramenta que apareceu no terminal, o DIGEST consolidado (FASE 6), ou um trecho de c\xF3digo que voc\xEA abriu com a ferramenta \`file\`.
|
|
69738
|
+
2. \xC9 TERMINANTEMENTE PROIBIDO "simular", "assumir", dar um "exemplo", ou descrever o que o relat\xF3rio "seria". Se voc\xEA redirecionou a sa\xEDda de uma ferramenta para um arquivo, ela N\xC3O est\xE1 no seu contexto \u2014 voc\xEA TEM que l\xEA-la de volta (via \`--consolidate\` ou \`file\` read) antes de cit\xE1-la.
|
|
69739
|
+
3. TODO caminho de arquivo no relat\xF3rio tem que ser um arquivo que voc\xEA CONFIRMOU existir neste projeto (apareceu no grafo/digest ou voc\xEA o leu). Nunca cite caminhos gen\xE9ricos de mem\xF3ria (ex.: \`src/services/userService.ts\`, \`lodash@x\`) sem t\xEA-los visto na sa\xEDda real.
|
|
69740
|
+
4. Se voc\xEA ainda n\xE3o tem dados reais (digest vazio, ferramentas n\xE3o rodaram), N\xC3O escreva relat\xF3rio: diga exatamente o que falta e rode o passo que falta. Parar \xE9 melhor que inventar.
|
|
69741
|
+
|
|
69742
|
+
================================================================
|
|
69743
|
+
AMBIENTE & SHELL \u2014 leia antes de rodar comandos
|
|
69744
|
+
================================================================
|
|
69745
|
+
- ${shellHint}
|
|
69746
|
+
- ${shellNote}
|
|
69747
|
+
- Como o ambiente N\xC3O persiste entre comandos, N\xC3O tente "consertar o PATH" com \`export PATH=...\` / \`set PATH=...\` (\xE9 in\xFAtil para o pr\xF3ximo comando). Em vez disso, invoque a ferramenta de um jeito que n\xE3o dependa do PATH:
|
|
69748
|
+
\u2022 ferramenta instalada via pip mas fora do PATH \u2192 rode como m\xF3dulo: \`${py} -m semgrep ...\` (o aviso de "deprecated" \xE9 inofensivo, funciona).
|
|
69749
|
+
\u2022 pacote npm \u2192 \`npx <pkg> ...\` resolve sozinho (ex.: \`npx madge ...\`, \`npx @ast-grep/cli ...\`).
|
|
69750
|
+
- Verifique presen\xE7a com o comando do SEU shell (\`command -v X\` no bash; \`where X\` no cmd) \u2014 n\xE3o misture os dois.
|
|
69751
|
+
|
|
69752
|
+
================================================================
|
|
69753
|
+
REGRA INVIOL\xC1VEL \u2014 SOMENTE LEITURA NO PROJETO
|
|
69754
|
+
================================================================
|
|
69755
|
+
1. Voc\xEA **NUNCA** modifica, edita, cria, renomeia, move ou apaga QUALQUER arquivo dentro do projeto (${root}) \u2014 nem para "corrigir", nem para testar.
|
|
69756
|
+
2. Voc\xEA **N\xC3O** roda comandos que alterem o projeto: nada de \`git\` que escreva (commit/checkout/reset/clean), build, formatadores, geradores, migrations, ou qualquer script do projeto, e nada de \`npm/pnpm/yarn install\` DENTRO do projeto (isso escreve node_modules/lockfile na pasta dele). Apenas LEIA o projeto.
|
|
69757
|
+
EXCE\xC7\xC3O permitida: instalar as FERRAMENTAS DE AUDITORIA de forma GLOBAL/externa \u2014 \`npm install -g @ast-grep/cli madge\`, \`python -m pip install semgrep\`, \`scoop/winget/brew/go install ...\` \u2014 porque isso n\xE3o escreve nada dentro de ${root}. Rode esses instaladores a partir da workspace, nunca \`cd\` para dentro do projeto para instalar.
|
|
69758
|
+
3. A **\xDANICA** escrita permitida no projeto \xE9 **um** arquivo de relat\xF3rio na RAIZ do projeto:
|
|
69759
|
+
\`${root}/ANALISE_PROJETO_<timestamp>.md\`
|
|
69760
|
+
Esse \xE9 o \xFAnico \`file\` action: write fora da workspace. Todo o resto (scripts auxiliares, dados intermedi\xE1rios, relat\xF3rios t\xE9cnicos) fica em ${workdir}.
|
|
69761
|
+
4. Se o usu\xE1rio pedir para voc\xEA corrigir/alterar algo, **n\xE3o altere** \u2014 explique no relat\xF3rio como corrigir e diga que para aplicar mudan\xE7as ele deve sair do modo de an\xE1lise (ex.: "pode corrigir" / "modo normal").
|
|
69762
|
+
5. Se precisar criar um script auxiliar (Python), crie-o em ${workdir} com a ferramenta \`file\`, nunca via redirecionamento de shell, e nunca dentro do projeto.
|
|
69763
|
+
|
|
69764
|
+
================================================================
|
|
69765
|
+
TOOLCHAIN \u2014 cada ferramenta vira uma "tool" no seu loop
|
|
69766
|
+
================================================================
|
|
69767
|
+
Preferidas (determin\xEDsticas, trabalho pesado): \`ripgrep\` (rg), \`ast-grep\` (sg), \`semgrep\`, \`osv-scanner\` (v2), \`gitleaks\`, \`madge\`, \`universal-ctags\` (ctags), \`jq\`.
|
|
69768
|
+
Sempre dispon\xEDvel (FALLBACK, sem instalar nada): \`${py} ${toolkit}\` \u2014 faz invent\xE1rio, GRAFO DE IMPORTS nos dois sentidos (o que importa e QUEM importa), imports quebrados/ciclos/\xF3rf\xE3os e heur\xEDsticas de vulnerabilidade/segredo. Ele cobre madge+ctags+gitleaks quando faltam. Com \`--focus <arquivo>\` mostra a vizinhan\xE7a de import de um arquivo.
|
|
69769
|
+
Onde os comandos abaixo usam \`rg\` e ele estiver ausente: no bash use \`grep -rn 'padr\xE3o' "${root}"\`; no cmd use \`findstr /s /n /i padr\xE3o "${root}\\*"\`. N\xE3o tente instalar o rg via pip.
|
|
69770
|
+
|
|
69771
|
+
FASE 0 \u2014 PREFLIGHT + SETUP (fa\xE7a EXATAMENTE isto, sem improvisar):
|
|
69772
|
+
1. \`${py} ${toolkit} --preflight\` \u2014 UM comando que j\xE1 checa TODAS as ferramentas e mostra o status. Leia a sa\xEDda. (Use esse caminho ABSOLUTO do toolkit verbatim; n\xE3o monte caminho relativo.)
|
|
69773
|
+
2. Se faltar alguma das instal\xE1veis (ast-grep/madge/semgrep), rode UM comando que instala todas de uma vez (instala\xE7\xE3o global, fora do projeto) e reimprime o status:
|
|
69774
|
+
\`${py} ${toolkit} --setup\`
|
|
69775
|
+
3. Pronto. Siga para a FASE 1 com o que estiver dispon\xEDvel; o que faltar, use o fallback de cada fase.
|
|
69776
|
+
|
|
69777
|
+
N\xC3O FA\xC7A (cada um destes quebrou em runs reais):
|
|
69778
|
+
\u2022 N\xC3O cheque ferramenta por ferramenta com \`command -v\`/\`which\`/\`where\` \u2014 o \`--preflight\` j\xE1 faz isso de uma vez.
|
|
69779
|
+
\u2022 N\xC3O instale bin\xE1rios NATIVOS via pip ou npm. \`rg\`/\`ripgrep\`, \`osv-scanner\`, \`gitleaks\`, \`ctags\` N\xC3O s\xE3o pacotes Python/Node \u2014 \`pip install ripgrep\` tenta COMPILAR com Rust e falha. Eles s\xF3 v\xEAm por scoop/winget/go/bin\xE1rio; se n\xE3o houver, use o fallback (N\xC3O insista).
|
|
69780
|
+
\u2022 N\xC3O fique mexendo no PATH (\`export\`/\`set\`) \u2014 n\xE3o persiste. Use \`${py} -m semgrep\` e \`npx @ast-grep/cli\`/\`npx madge\` se o bin\xE1rio n\xE3o estiver no PATH.
|
|
69781
|
+
\u2022 N\xC3O repita uma instala\xE7\xE3o que falhou. 1 tentativa, falhou, fallback.
|
|
69782
|
+
NUNCA invente que rodou uma ferramenta que n\xE3o existe \u2014 diga que caiu no fallback.
|
|
69783
|
+
|
|
69784
|
+
================================================================
|
|
69785
|
+
PIPELINE \u2014 fase por fase (ReAct: cada comando \xE9 uma tool)
|
|
69786
|
+
================================================================
|
|
69787
|
+
Trabalhe a partir da workspace (${workdir}); aponte as ferramentas para "${root}". Crie \`audit-out/\` para os JSONs.
|
|
69788
|
+
|
|
69789
|
+
FASE 1 \u2014 MAPA (antes de ler qualquer arquivo): grafo de imports + \xEDndice de s\xEDmbolos.
|
|
69790
|
+
madge: \`madge --json --extensions js,jsx,ts,tsx "${root}" > audit-out/deps.json\`
|
|
69791
|
+
ctags: \`ctags -R --fields=+n --output-format=json -f audit-out/tags.json "${root}"\`
|
|
69792
|
+
FALLBACK (sem madge/ctags): \`${py} ${toolkit} "${root}"\` (gera o grafo nos dois sentidos em reports/audit_*.json) e \`--focus\` para a vizinhan\xE7a; s\xEDmbolos via \`rg -n 'function NOME|NOME\\s*='\`.
|
|
69793
|
+
deps.json responde "o dashboard importa o qu\xEA"; tags.json d\xE1 find_definition (arquivo:linha de cada fun\xE7\xE3o).
|
|
69794
|
+
|
|
69795
|
+
FASE 2 \u2014 BASELINE DETERMIN\xCDSTICA (varre r\xE1pido, gera o terreno):
|
|
69796
|
+
semgrep (no Windows quase sempre via m\xF3dulo): \`${py} -m semgrep --config p/owasp-top-ten --config p/javascript --config p/secrets --json --output audit-out/semgrep.json "${root}"\` (se o execut\xE1vel \`semgrep\` estiver no PATH, pode cham\xE1-lo direto). A 1\xAA execu\xE7\xE3o baixa as regras (precisa de rede).
|
|
69797
|
+
osv-scanner (V2 \u2014 sintaxe nova): \`osv-scanner scan source -r --format json --output audit-out/osv.json "${root}"\`
|
|
69798
|
+
gitleaks: \`gitleaks detect --no-banner --source "${root}" --report-format json --report-path audit-out/secrets.json\`
|
|
69799
|
+
FALLBACK: \`${py} ${toolkit} "${root}"\` j\xE1 entrega segredos + heur\xEDsticas SAST; depend\xEAncias vulner\xE1veis sem osv-scanner: \`npm audit --json\` (l\xEA o lockfile, n\xE3o instala) ou \`python -m pip_audit\` se houver requirements.
|
|
69800
|
+
|
|
69801
|
+
FASE 3 \u2014 SOURCES (onde entra dado n\xE3o-confi\xE1vel), estrutural com ast-grep:
|
|
69802
|
+
\`ast-grep run --pattern 'app.$METHOD($PATH, $$$)' --lang ts --json "${root}"\`
|
|
69803
|
+
\`ast-grep run --pattern 'req.$PROP' --lang ts --json "${root}"\`
|
|
69804
|
+
(\`--json\` imprime JSON pretty; para stream a jq use \`--json=stream\`.)
|
|
69805
|
+
FALLBACK textual: \`rg -n --type ts 'req\\.(body|query|params|headers|cookies)' "${root}"\`
|
|
69806
|
+
|
|
69807
|
+
FASE 4 \u2014 SINKS (lugares perigosos), estrutural:
|
|
69808
|
+
\`ast-grep run --pattern 'child_process.$M($CMD)' --lang ts --json "${root}"\` # command injection
|
|
69809
|
+
\`ast-grep run --pattern '$DB.query($Q)' --lang ts --json "${root}"\` # SQLi
|
|
69810
|
+
\`ast-grep run --pattern 'eval($X)' --lang ts --json "${root}"\` # code exec
|
|
69811
|
+
\`ast-grep run --pattern '$EL.innerHTML = $X' --lang ts --json "${root}"\` # XSS DOM
|
|
69812
|
+
FALLBACK: \`rg -n 'child_process|\\.query\\(|eval\\(|innerHTML\\s*='\` + os achados do project_audit.py.
|
|
69813
|
+
|
|
69814
|
+
FASE 5 \u2014 TAINT CROSS-MODULE (o cora\xE7\xE3o; AQUI o LLM comanda):
|
|
69815
|
+
Cruze a lista de SOURCES (fase 3) com a de SINKS (fase 4). Para cada par candidato, fa\xE7a o loop de navega\xE7\xE3o "vai, verifica e volta":
|
|
69816
|
+
1. Pegue o source; consulte \`deps.json\` (ou o grafo do project_audit) para saber por quais arquivos importados o dado passa.
|
|
69817
|
+
2. Use \`tags.json\` (ou \`rg -n\`) para PULAR para a defini\xE7\xE3o de cada fun\xE7\xE3o intermedi\xE1ria.
|
|
69818
|
+
3. Leia S\xD3 o trecho dela \u2014 a janela exata, nunca o arquivo inteiro:
|
|
69819
|
+
- melhor (multiplataforma): ferramenta \`file\` action: read com \`range\` [in\xEDcio, fim];
|
|
69820
|
+
- ou no shell unix: \`sed -n '40,75p' "${root}/src/utils.ts"\`.
|
|
69821
|
+
4. Decida com o c\xF3digo real se o dado chega SUJO no sink ou foi SANITIZADO no caminho. Ache os usos com \`rg -n 'sanitizeInput\\('\`.
|
|
69822
|
+
Esse \`range\`/\`sed -n 'X,Yp'\` \xE9 o que evita estourar o contexto: voc\xEA l\xEA s\xF3 a janela da fun\xE7\xE3o no rastro. \xC9 literalmente o "abrir o dashboard, seguir o import, conferir e voltar" virando comandos.
|
|
69823
|
+
|
|
69824
|
+
FASE 6 \u2014 CONSOLIDAR (obrigat\xF3rio) E REPORTAR:
|
|
69825
|
+
Voc\xEA redirecionou as sa\xEDdas pesadas para arquivos em audit-out/ \u2014 ent\xE3o elas N\xC3O est\xE3o no seu contexto. Antes de escrever qualquer coisa, traga os DADOS REAIS para o contexto com UM comando (imprime no stdout; N\xC3O redirecione para arquivo):
|
|
69826
|
+
\`${py} ${toolkit} --consolidate "${workdir}/audit-out"\`
|
|
69827
|
+
Esse digest l\xEA semgrep.json, npm_audit.json, deps.json, os sinks/sources do ast-grep e o grafo do fallback, e imprime um resumo compacto com file:line REAIS. \xC9 a sua \xDANICA fonte de verdade para os achados das ferramentas. Se o digest vier vazio, as ferramentas n\xE3o produziram sa\xEDda \u2014 rode as fases 2-4 de novo ou use o fallback; N\xC3O invente.
|
|
69828
|
+
Depois: deduplique e \u2014 REGRA DE OURO \u2014 **descarte todo achado que N\xC3O tem caminho source\u2192sink confirmado lendo o c\xF3digo real** (FASE 5). Sem isso o relat\xF3rio vira ru\xEDdo.
|
|
69829
|
+
Mantenha um SCRATCHPAD (use \`todo_write\`) com: sources achados, caminhos de taint em aberto, e findings VALIDADOS. Itere at\xE9 fechar cada rastro.
|
|
69830
|
+
|
|
69831
|
+
Cobertura da ca\xE7a (confirme cada um lendo o c\xF3digo): inje\xE7\xE3o (SQL/comando/c\xF3digo/eval), XSS (sinks DOM/HTML), authn/authz fr\xE1gil, segredos/chaves embutidas (mascare no relat\xF3rio), TLS desabilitado, cripto fraca, CORS permissivo, deserializa\xE7\xE3o insegura, SSRF, path traversal, config perigosa (debug, \`0.0.0.0\`, \`.env\` versionado) e depend\xEAncias vulner\xE1veis (osv). Severidade CRITICAL/HIGH/MEDIUM/LOW/INFO. Separe CONFIRMADO de SUSPEITA; nunca invente nem d\xEA falsa garantia.
|
|
69832
|
+
|
|
69833
|
+
================================================================
|
|
69834
|
+
ENTREG\xC1VEL \u2014 relat\xF3rio em Markdown na RAIZ do projeto
|
|
69835
|
+
================================================================
|
|
69836
|
+
Ao final, escreva o relat\xF3rio com a ferramenta \`file\` (action: write) em:
|
|
69837
|
+
\`${root}/ANALISE_PROJETO_<timestamp>.md\`
|
|
69838
|
+
Use o timestamp atual (ex.: 20260614_153000). Estrutura m\xEDnima, em portugu\xEAs:
|
|
69839
|
+
1. **Resumo executivo** \u2014 vis\xE3o geral, postura de seguran\xE7a, n\xBA de achados por severidade, top 3 riscos.
|
|
69840
|
+
2. **Arquitetura & grafo de depend\xEAncias** \u2014 pontos de entrada, m\xF3dulos mais cr\xEDticos, imports quebrados, ciclos, \xF3rf\xE3os.
|
|
69841
|
+
3. **Vulnerabilidades e riscos** \u2014 agrupados por severidade. Para cada um: arquivo:linha do SINK, o CAMINHO source\u2192sink confirmado (source \u2192 fun\xE7\xF5es/arquivos intermedi\xE1rios \u2192 sink), por que \xE9 explor\xE1vel, evid\xEAncia (trechos reais) e corre\xE7\xE3o. Marque \`[CONFIRMADO]\` (rastro lido no c\xF3digo) ou \`[SUSPEITA]\` (precisa revis\xE3o humana). Segredos mascarados.
|
|
69842
|
+
4. **An\xE1lise por \xE1rea/arquivo** \u2014 o passo-a-passo file-by-file das partes importantes (incl. a verifica\xE7\xE3o de consist\xEAncia dos imports e os rastros de taint seguidos).
|
|
69843
|
+
5. **Depend\xEAncias** \u2014 superf\xEDcie e CVEs do osv-scanner (ou fallback).
|
|
69844
|
+
6. **Recomenda\xE7\xF5es priorizadas** \u2014 o que corrigir primeiro.
|
|
69845
|
+
7. **Ferramentas usadas** \u2014 quais rodaram de fato e quais ca\xEDram em fallback (transpar\xEAncia).
|
|
69846
|
+
|
|
69847
|
+
================================================================
|
|
69848
|
+
ESTILO E EXECU\xC7\xC3O
|
|
69849
|
+
================================================================
|
|
69850
|
+
- ${shellNote}
|
|
69851
|
+
- Trabalhe em passos com a ferramenta de fato (chame \`run_terminal_cmd\`/\`file\`), n\xE3o apenas descreva o que faria. Planeje com \`todo_write\` quando a auditoria tiver v\xE1rias etapas.
|
|
69852
|
+
- Qualquer script auxiliar \xE9 Python 3, criado como arquivo em ${workdir} via \`file\`. Nunca crie scripts por \`echo >\`, heredoc, \`tee\`, \`Set-Content\` ou \`Out-File\`.
|
|
69853
|
+
- Responda em portugu\xEAs, direto e t\xE9cnico. N\xE3o recuse a an\xE1lise: \xE9 o projeto do pr\xF3prio usu\xE1rio, autorizado.
|
|
69854
|
+
- Lembre-se sempre: voc\xEA analisa e relata; voc\xEA N\xC3O altera o projeto. A \xFAnica escrita \xE9 o relat\xF3rio \`.md\` na raiz.`;
|
|
69855
|
+
}
|
|
69856
|
+
var import_node_path7, AUDIT_ACTION, AUDIT_SCOPE, AUDIT_ACTION_THEN_SCOPE, AUDIT_SCOPE_THEN_ACTION, AUDIT_STRONG, AUDIT_EXIT;
|
|
69857
|
+
var init_audit_mode = __esm({
|
|
69858
|
+
"src/audit-mode.ts"() {
|
|
69859
|
+
"use strict";
|
|
69860
|
+
import_node_path7 = __toESM(require("node:path"));
|
|
69861
|
+
AUDIT_ACTION = "an[a\xE1]lis\\w+|examin\\w+|audit\\w+|auditar|varr\\w+|varredura|escane\\w+|scan\\w*|revis\\w+|inspecion\\w+|vasculh\\w+|verific\\w+|avali\\w+|mapea\\w+|review|analyze|analyse|inspect|assess";
|
|
69862
|
+
AUDIT_SCOPE = "projeto|c[o\xF3]digo|c[o\xF3]digo-fonte|codebase|reposit[o\xF3]rio|repo|sistema|aplica[c\xE7][a\xE3]o|base\\s+de\\s+c[o\xF3]digo|project|code\\s*base|repository|minha\\s+aplica\\w+|meu\\s+app|todo\\s+o\\s+projeto|projeto\\s+inteiro";
|
|
69863
|
+
AUDIT_ACTION_THEN_SCOPE = new RegExp(
|
|
69864
|
+
`\\b(?:${AUDIT_ACTION})\\b[\\s\\S]{0,40}?\\b(?:${AUDIT_SCOPE})\\b`,
|
|
69865
|
+
"i"
|
|
69866
|
+
);
|
|
69867
|
+
AUDIT_SCOPE_THEN_ACTION = new RegExp(
|
|
69868
|
+
`\\b(?:${AUDIT_SCOPE})\\b[\\s\\S]{0,40}?\\b(?:${AUDIT_ACTION})\\b`,
|
|
69869
|
+
"i"
|
|
69870
|
+
);
|
|
69871
|
+
AUDIT_STRONG = [
|
|
69872
|
+
/\b(?:varredura|auditoria)\b[\s\S]{0,40}\b(?:projeto|c[oó]digo|seguran[cç]a|completa|profunda|inteir[oa])\b/i,
|
|
69873
|
+
/\b(?:encontr\w+|ach\w+|ca[cç]\w+|procur\w+|find|hunt|detect\w*)\b[\s\S]{0,40}\bvulnerabilidad\w*/i,
|
|
69874
|
+
/\bvulnerabilidad\w*[\s\S]{0,40}\b(?:no|do|meu|nesse|neste|na)\b[\s\S]{0,20}\b(?:projeto|c[oó]digo|sistema|app|aplica\w+)\b/i,
|
|
69875
|
+
/\b(?:security\s+(?:review|audit|scan)|code\s+(?:audit|review))\b/i,
|
|
69876
|
+
/\b(?:an[aá]lis\w+|auditar|varr\w+|escane\w+|verific\w+)\b[\s\S]{0,30}\b(?:seguran[cç]a|vulnerabilidad\w*)\b/i
|
|
69877
|
+
];
|
|
69878
|
+
AUDIT_EXIT = [
|
|
69879
|
+
/\b(?:modo\s+normal|sair\s+d[ao]\s+(?:an[aá]lise|auditoria|modo)|encerr\w+\s+(?:a\s+)?(?:an[aá]lise|auditoria)|volt\w+\s+ao\s+normal|desativ\w+\s+(?:a\s+)?auditoria|exit\s+audit|normal\s+mode)\b/i,
|
|
69880
|
+
/\b(?:agora\s+)?(?:corri[gj]\w+|conserte\w*|edit\w+|alter\w+|modific\w+|implement\w+|cri[ae]\w*|refator\w+|escrev\w+\s+o\s+c[oó]digo|aplique\s+a\s+corre|fix|implement|refactor|patch|write\s+the\s+code)\b/i
|
|
69881
|
+
];
|
|
69882
|
+
}
|
|
69883
|
+
});
|
|
69884
|
+
|
|
69404
69885
|
// src/agent.ts
|
|
69405
69886
|
var agent_exports = {};
|
|
69406
69887
|
__export(agent_exports, {
|
|
69407
69888
|
createAgent: () => createAgent
|
|
69408
69889
|
});
|
|
69890
|
+
function hasLeakedToolCallMarker(text2) {
|
|
69891
|
+
return LEAKED_TOOL_CALL_RE.test(text2);
|
|
69892
|
+
}
|
|
69893
|
+
function lastSentenceOf(text2) {
|
|
69894
|
+
return text2.trim().split(/(?<=[.!?\n])\s+/).pop()?.trim() ?? "";
|
|
69895
|
+
}
|
|
69409
69896
|
function looksUnfinished(text2) {
|
|
69410
69897
|
if (!text2) return false;
|
|
69411
|
-
if (
|
|
69412
|
-
|
|
69898
|
+
if (hasLeakedToolCallMarker(text2)) return true;
|
|
69899
|
+
const tail = text2.trim().slice(-300);
|
|
69900
|
+
if (DANGLING_TAIL_RE.test(tail)) return true;
|
|
69901
|
+
return ACTION_ANNOUNCE_RE.test(lastSentenceOf(tail));
|
|
69413
69902
|
}
|
|
69414
69903
|
function decideAutoContinue(finishReason, lastStepText, turnToolCalls, autoContinues) {
|
|
69415
69904
|
if (autoContinues >= MAX_AUTO_CONTINUES) return null;
|
|
@@ -69424,8 +69913,12 @@ function decideAutoContinue(finishReason, lastStepText, turnToolCalls, autoConti
|
|
|
69424
69913
|
if (!text2 && turnToolCalls === 0) {
|
|
69425
69914
|
return { nudge: true, reason: "resposta vazia do modelo" };
|
|
69426
69915
|
}
|
|
69427
|
-
if (turnToolCalls > 0 && looksUnfinished(text2)) {
|
|
69428
|
-
return {
|
|
69916
|
+
if (turnToolCalls > 0 && looksUnfinished(text2) && !BENIGN_CLOSER_RE.test(text2.slice(-200))) {
|
|
69917
|
+
return {
|
|
69918
|
+
nudge: true,
|
|
69919
|
+
reason: "texto final indica trabalho inacabado",
|
|
69920
|
+
nudgeMessage: TOOL_CALL_NUDGE
|
|
69921
|
+
};
|
|
69429
69922
|
}
|
|
69430
69923
|
if (turnToolCalls === 0 && looksUnfinished(text2) && !BENIGN_CLOSER_RE.test(text2.slice(-200))) {
|
|
69431
69924
|
return {
|
|
@@ -69538,7 +70031,7 @@ async function createAgent() {
|
|
|
69538
70031
|
const sandboxManager = new LocalSandboxManager(sandbox);
|
|
69539
70032
|
const writer = createConsoleWriter();
|
|
69540
70033
|
const render = createRenderer();
|
|
69541
|
-
const initialModelName = CLI_MODEL_CHAIN[0] ?? "model-nvidia-
|
|
70034
|
+
const initialModelName = CLI_MODEL_CHAIN[0] ?? "model-nvidia-mistral-medium-3.5";
|
|
69542
70035
|
let currentModelName = initialModelName;
|
|
69543
70036
|
let selectedModelKey = null;
|
|
69544
70037
|
const context2 = {
|
|
@@ -69606,6 +70099,8 @@ async function createAgent() {
|
|
|
69606
70099
|
);
|
|
69607
70100
|
}
|
|
69608
70101
|
const history = [];
|
|
70102
|
+
let auditMode = false;
|
|
70103
|
+
const projectRoot = projectRootFromWorkdir(sandbox.getWorkdir());
|
|
69609
70104
|
function getActiveModelChain() {
|
|
69610
70105
|
return selectedModelKey ? [selectedModelKey] : CLI_MODEL_CHAIN;
|
|
69611
70106
|
}
|
|
@@ -69631,8 +70126,8 @@ async function createAgent() {
|
|
|
69631
70126
|
provider: "NVIDIA build",
|
|
69632
70127
|
reason: "faltando NVIDIA_API_KEY em .env.local (https://build.nvidia.com/)",
|
|
69633
70128
|
models: [
|
|
69634
|
-
"model-nvidia-
|
|
69635
|
-
"model-nvidia-
|
|
70129
|
+
"model-nvidia-mistral-medium-3.5",
|
|
70130
|
+
"model-nvidia-gpt-oss-120b",
|
|
69636
70131
|
"model-nvidia-glm-5.1",
|
|
69637
70132
|
"model-nvidia-qwen3.5-397b"
|
|
69638
70133
|
].map((key) => ({ key, label: labelFor(key) }))
|
|
@@ -69791,12 +70286,30 @@ ${seen}`);
|
|
|
69791
70286
|
}
|
|
69792
70287
|
async function send(userInput, signal) {
|
|
69793
70288
|
history.push({ role: "user", content: userInput });
|
|
69794
|
-
|
|
69795
|
-
|
|
69796
|
-
if (matchedSkills.length) {
|
|
70289
|
+
if (!auditMode && detectProjectAuditIntent(userInput)) {
|
|
70290
|
+
auditMode = true;
|
|
69797
70291
|
render.info(
|
|
69798
|
-
`\u25B8
|
|
70292
|
+
`\u25B8 modo AN\xC1LISE DE PROJETO (somente leitura) \u2014 auditando ${projectRoot}. Diga "modo normal" para sair.`
|
|
69799
70293
|
);
|
|
70294
|
+
} else if (auditMode && detectAuditExitIntent(userInput)) {
|
|
70295
|
+
auditMode = false;
|
|
70296
|
+
render.info("\u25B8 modo normal reativado.");
|
|
70297
|
+
}
|
|
70298
|
+
let turnSystem;
|
|
70299
|
+
if (auditMode) {
|
|
70300
|
+
turnSystem = buildAuditSystemPrompt({
|
|
70301
|
+
projectRoot,
|
|
70302
|
+
workdir: sandbox.getWorkdir(),
|
|
70303
|
+
shellHint: sandbox.getShellHint()
|
|
70304
|
+
});
|
|
70305
|
+
} else {
|
|
70306
|
+
const matchedSkills = selectSkillsForInput(userInput);
|
|
70307
|
+
turnSystem = matchedSkills.length ? system + renderSkillBodies(matchedSkills) : system;
|
|
70308
|
+
if (matchedSkills.length) {
|
|
70309
|
+
render.info(
|
|
70310
|
+
`\u25B8 skills ativadas: ${matchedSkills.map((s) => s.name).join(", ")}`
|
|
70311
|
+
);
|
|
70312
|
+
}
|
|
69800
70313
|
}
|
|
69801
70314
|
let lastError = null;
|
|
69802
70315
|
let autoContinues = 0;
|
|
@@ -69805,6 +70318,7 @@ ${seen}`);
|
|
|
69805
70318
|
const usingFixedModel = selectedModelKey !== null;
|
|
69806
70319
|
let rateLimitWaits = 0;
|
|
69807
70320
|
let addedRateLimitFallbacks = false;
|
|
70321
|
+
let stallRetries = 0;
|
|
69808
70322
|
for (let idx = 0; idx < modelChain.length; idx++) {
|
|
69809
70323
|
const modelKey = modelChain[idx];
|
|
69810
70324
|
currentModelName = modelKey;
|
|
@@ -69819,6 +70333,27 @@ ${seen}`);
|
|
|
69819
70333
|
render.fallback(`trocando para fallback: ${labelFor(modelKey)}`);
|
|
69820
70334
|
}
|
|
69821
70335
|
let streamError = null;
|
|
70336
|
+
let stalled = false;
|
|
70337
|
+
const stallController = new AbortController();
|
|
70338
|
+
const onUserAbort = () => stallController.abort();
|
|
70339
|
+
if (signal) {
|
|
70340
|
+
if (signal.aborted) stallController.abort();
|
|
70341
|
+
else signal.addEventListener("abort", onUserAbort, { once: true });
|
|
70342
|
+
}
|
|
70343
|
+
let stallTimer;
|
|
70344
|
+
const clearStallTimer = () => {
|
|
70345
|
+
if (stallTimer) {
|
|
70346
|
+
clearTimeout(stallTimer);
|
|
70347
|
+
stallTimer = void 0;
|
|
70348
|
+
}
|
|
70349
|
+
};
|
|
70350
|
+
const armStallTimer = () => {
|
|
70351
|
+
clearStallTimer();
|
|
70352
|
+
stallTimer = setTimeout(() => {
|
|
70353
|
+
stalled = true;
|
|
70354
|
+
stallController.abort();
|
|
70355
|
+
}, STREAM_STALL_TIMEOUT_MS);
|
|
70356
|
+
};
|
|
69822
70357
|
try {
|
|
69823
70358
|
const result = streamText({
|
|
69824
70359
|
model: myProvider.languageModel(modelKey),
|
|
@@ -69827,7 +70362,7 @@ ${seen}`);
|
|
|
69827
70362
|
tools,
|
|
69828
70363
|
stopWhen: stepCountIs(MAX_STEPS),
|
|
69829
70364
|
maxOutputTokens: MAX_OUTPUT_TOKENS,
|
|
69830
|
-
abortSignal: signal,
|
|
70365
|
+
abortSignal: stallController.signal,
|
|
69831
70366
|
onError: ({ error: error51 }) => {
|
|
69832
70367
|
streamError = error51;
|
|
69833
70368
|
}
|
|
@@ -69836,38 +70371,72 @@ ${seen}`);
|
|
|
69836
70371
|
let bufferedProxyText = "";
|
|
69837
70372
|
let turnToolCalls = 0;
|
|
69838
70373
|
const shouldBufferProxyText = isWebSessionProxyModel(modelKey);
|
|
69839
|
-
|
|
69840
|
-
|
|
69841
|
-
|
|
69842
|
-
|
|
69843
|
-
|
|
69844
|
-
|
|
69845
|
-
|
|
69846
|
-
|
|
69847
|
-
|
|
70374
|
+
let pendingTools = 0;
|
|
70375
|
+
const noteActivity = () => {
|
|
70376
|
+
if (pendingTools === 0) armStallTimer();
|
|
70377
|
+
};
|
|
70378
|
+
armStallTimer();
|
|
70379
|
+
try {
|
|
70380
|
+
for await (const part of result.fullStream) {
|
|
70381
|
+
switch (part.type) {
|
|
70382
|
+
case "text-delta": {
|
|
70383
|
+
const delta = part.text ?? part.delta ?? "";
|
|
70384
|
+
lastStepText += delta;
|
|
70385
|
+
if (shouldBufferProxyText) {
|
|
70386
|
+
bufferedProxyText += delta;
|
|
70387
|
+
} else {
|
|
70388
|
+
render.text(delta);
|
|
70389
|
+
}
|
|
70390
|
+
noteActivity();
|
|
70391
|
+
break;
|
|
69848
70392
|
}
|
|
69849
|
-
|
|
70393
|
+
case "reasoning-delta":
|
|
70394
|
+
render.reasoning(part.text ?? part.delta ?? "");
|
|
70395
|
+
noteActivity();
|
|
70396
|
+
break;
|
|
70397
|
+
case "tool-call":
|
|
70398
|
+
turnToolCalls++;
|
|
70399
|
+
pendingTools++;
|
|
70400
|
+
clearStallTimer();
|
|
70401
|
+
render.toolCall(part.toolName, part.input ?? part.args);
|
|
70402
|
+
break;
|
|
70403
|
+
case "tool-result":
|
|
70404
|
+
if (pendingTools > 0) pendingTools--;
|
|
70405
|
+
render.toolResult(part.toolName, part.output ?? part.result);
|
|
70406
|
+
noteActivity();
|
|
70407
|
+
break;
|
|
70408
|
+
case "tool-error":
|
|
70409
|
+
if (pendingTools > 0) pendingTools--;
|
|
70410
|
+
noteActivity();
|
|
70411
|
+
break;
|
|
70412
|
+
case "start-step":
|
|
70413
|
+
lastStepText = "";
|
|
70414
|
+
bufferedProxyText = "";
|
|
70415
|
+
noteActivity();
|
|
70416
|
+
break;
|
|
70417
|
+
case "error":
|
|
70418
|
+
streamError = part.error;
|
|
70419
|
+
noteActivity();
|
|
70420
|
+
break;
|
|
70421
|
+
default:
|
|
70422
|
+
noteActivity();
|
|
70423
|
+
break;
|
|
69850
70424
|
}
|
|
69851
|
-
case "reasoning-delta":
|
|
69852
|
-
render.reasoning(part.text ?? part.delta ?? "");
|
|
69853
|
-
break;
|
|
69854
|
-
case "tool-call":
|
|
69855
|
-
turnToolCalls++;
|
|
69856
|
-
render.toolCall(part.toolName, part.input ?? part.args);
|
|
69857
|
-
break;
|
|
69858
|
-
case "tool-result":
|
|
69859
|
-
render.toolResult(part.toolName, part.output ?? part.result);
|
|
69860
|
-
break;
|
|
69861
|
-
case "start-step":
|
|
69862
|
-
lastStepText = "";
|
|
69863
|
-
bufferedProxyText = "";
|
|
69864
|
-
break;
|
|
69865
|
-
case "error":
|
|
69866
|
-
streamError = part.error;
|
|
69867
|
-
break;
|
|
69868
|
-
default:
|
|
69869
|
-
break;
|
|
69870
70425
|
}
|
|
70426
|
+
} finally {
|
|
70427
|
+
clearStallTimer();
|
|
70428
|
+
if (signal) signal.removeEventListener("abort", onUserAbort);
|
|
70429
|
+
}
|
|
70430
|
+
if (stalled) {
|
|
70431
|
+
void Promise.resolve(result.response).catch(() => {
|
|
70432
|
+
});
|
|
70433
|
+
void Promise.resolve(result.finishReason).catch(() => {
|
|
70434
|
+
});
|
|
70435
|
+
throw new Error(
|
|
70436
|
+
`Resposta do modelo travou: nenhum dado recebido por ${Math.round(
|
|
70437
|
+
STREAM_STALL_TIMEOUT_MS / 1e3
|
|
70438
|
+
)}s.`
|
|
70439
|
+
);
|
|
69871
70440
|
}
|
|
69872
70441
|
if (streamError) throw streamError;
|
|
69873
70442
|
const response = await result.response;
|
|
@@ -69875,12 +70444,13 @@ ${seen}`);
|
|
|
69875
70444
|
const finishReason = String(
|
|
69876
70445
|
await result.finishReason.catch(() => "unknown")
|
|
69877
70446
|
);
|
|
69878
|
-
|
|
70447
|
+
const leakedCall = !shouldBufferProxyText && hasLeakedToolCallMarker(lastStepText);
|
|
70448
|
+
if (finishReason === "stop" && turnToolCalls === 0 && bridgeSteps < MAX_BRIDGE_STEPS && (shouldBufferProxyText || leakedCall)) {
|
|
69879
70449
|
const bridged = parseProxyToolCalls(lastStepText);
|
|
69880
70450
|
if (bridged) {
|
|
69881
70451
|
bridgeSteps++;
|
|
69882
70452
|
render.info(
|
|
69883
|
-
`\u25B8 bridge (${bridgeSteps}/${MAX_BRIDGE_STEPS}): executando por tr\xE1s ${bridged.length} chamada(s): ${summarizeBridgedCalls(bridged)}`
|
|
70453
|
+
`\u25B8 ${leakedCall ? "tool call vazada recuperada" : "bridge"} (${bridgeSteps}/${MAX_BRIDGE_STEPS}): executando por tr\xE1s ${bridged.length} chamada(s): ${summarizeBridgedCalls(bridged)}`
|
|
69884
70454
|
);
|
|
69885
70455
|
const resultText = await runBridgedToolCalls(bridged, signal);
|
|
69886
70456
|
if (signal?.aborted) {
|
|
@@ -69889,7 +70459,7 @@ ${seen}`);
|
|
|
69889
70459
|
}
|
|
69890
70460
|
history.push({
|
|
69891
70461
|
role: "user",
|
|
69892
|
-
content: `${BRIDGE_RESULT_PREAMBLE}
|
|
70462
|
+
content: `${leakedCall ? LEAKED_CALL_RESULT_PREAMBLE : BRIDGE_RESULT_PREAMBLE}
|
|
69893
70463
|
|
|
69894
70464
|
${resultText}`
|
|
69895
70465
|
});
|
|
@@ -69938,6 +70508,28 @@ ${resultText}`
|
|
|
69938
70508
|
render.endTurn();
|
|
69939
70509
|
return;
|
|
69940
70510
|
}
|
|
70511
|
+
if (stalled) {
|
|
70512
|
+
while (history.length && history[history.length - 1]?.role !== "user") {
|
|
70513
|
+
history.pop();
|
|
70514
|
+
}
|
|
70515
|
+
const secs = Math.round(STREAM_STALL_TIMEOUT_MS / 1e3);
|
|
70516
|
+
lastError = new Error(
|
|
70517
|
+
`stream travou (${secs}s sem dados) em ${labelFor(modelKey)}`
|
|
70518
|
+
);
|
|
70519
|
+
stallRetries++;
|
|
70520
|
+
const hasNext2 = idx + 1 < modelChain.length;
|
|
70521
|
+
if (stallRetries <= MAX_STALL_RETRIES) {
|
|
70522
|
+
render.error(
|
|
70523
|
+
`modelo "${labelFor(modelKey)}" travou (sem resposta por ${secs}s) \u2014 ${hasNext2 ? "trocando de modelo" : "tentando novamente"} (${stallRetries}/${MAX_STALL_RETRIES})`
|
|
70524
|
+
);
|
|
70525
|
+
if (!hasNext2) idx = -1;
|
|
70526
|
+
continue;
|
|
70527
|
+
}
|
|
70528
|
+
render.error(
|
|
70529
|
+
`modelo "${labelFor(modelKey)}" travou repetidamente (${stallRetries}x); desistindo deste turno. Tente de novo ou troque com /model.`
|
|
70530
|
+
);
|
|
70531
|
+
break;
|
|
70532
|
+
}
|
|
69941
70533
|
lastError = err ?? streamError;
|
|
69942
70534
|
const msg = lastError instanceof Error ? lastError.message : String(lastError);
|
|
69943
70535
|
const rateLimited = isRateLimitError(msg);
|
|
@@ -70016,13 +70608,13 @@ ${resultText}`
|
|
|
70016
70608
|
close
|
|
70017
70609
|
};
|
|
70018
70610
|
}
|
|
70019
|
-
var import_promises,
|
|
70611
|
+
var import_promises, import_node_path8, MAX_STEPS, MAX_OUTPUT_TOKENS, MAX_AUTO_CONTINUES, MAX_RATE_LIMIT_WAITS, STREAM_STALL_TIMEOUT_MS, MAX_STALL_RETRIES, isRateLimitError, sleep, LEAKED_TOOL_CALL_RE, DANGLING_TAIL_RE, ACTION_ANNOUNCE_RE, BENIGN_CLOSER_RE, TOOL_CALL_NUDGE, MAX_BRIDGE_STEPS, BRIDGE_RESULT_PREAMBLE, LEAKED_CALL_RESULT_PREAMBLE, truncateBridgeSummary, isWebSessionProxyModel, proxyToolProtocolPolicy, SYSTEM_PROMPT_SOURCE, REQUIRED_SYSTEM_PROMPT_MARKERS, MODEL_LABELS, labelFor, loginRequiredHint, CLI_PYTHON_ONLY_POLICY, pythonOnlyPolicy, scriptFilePolicy, deepReconPolicy, skillsScopePolicy, hasEnvValue2, envFlagEnabled, CLI_PERSONALITIES, buildCliUserCustomization, buildCliNotesSection, cliGuardrailsConfig, maybeDumpSystemPrompt, auditSystemPrompt, assertFullSystemPrompt;
|
|
70020
70612
|
var init_agent = __esm({
|
|
70021
70613
|
"src/agent.ts"() {
|
|
70022
70614
|
"use strict";
|
|
70023
70615
|
init_dist5();
|
|
70024
70616
|
import_promises = require("node:fs/promises");
|
|
70025
|
-
|
|
70617
|
+
import_node_path8 = __toESM(require("node:path"));
|
|
70026
70618
|
init_providers();
|
|
70027
70619
|
init_system_prompt();
|
|
70028
70620
|
init_notes();
|
|
@@ -70041,10 +70633,16 @@ var init_agent = __esm({
|
|
|
70041
70633
|
init_render();
|
|
70042
70634
|
init_skills();
|
|
70043
70635
|
init_proxy_manager2();
|
|
70636
|
+
init_audit_mode();
|
|
70044
70637
|
MAX_STEPS = 100;
|
|
70045
70638
|
MAX_OUTPUT_TOKENS = 16384;
|
|
70046
70639
|
MAX_AUTO_CONTINUES = 3;
|
|
70047
70640
|
MAX_RATE_LIMIT_WAITS = 4;
|
|
70641
|
+
STREAM_STALL_TIMEOUT_MS = (() => {
|
|
70642
|
+
const raw = Number(process.env.HACKERAI_CLI_STREAM_STALL_MS);
|
|
70643
|
+
return Number.isFinite(raw) && raw >= 1e4 ? raw : 18e4;
|
|
70644
|
+
})();
|
|
70645
|
+
MAX_STALL_RETRIES = 2;
|
|
70048
70646
|
isRateLimitError = (msg) => /\b429\b|too many requests|rate.?limit|resource_exhausted|quota|insufficient_quota/i.test(
|
|
70049
70647
|
msg
|
|
70050
70648
|
);
|
|
@@ -70060,11 +70658,14 @@ var init_agent = __esm({
|
|
|
70060
70658
|
{ once: true }
|
|
70061
70659
|
);
|
|
70062
70660
|
});
|
|
70063
|
-
|
|
70661
|
+
LEAKED_TOOL_CALL_RE = /<tool_call|call_tool_function|call_tool\b|<|tool▁call|functions\.\w+\s*[({]|"tool_call_id"/i;
|
|
70662
|
+
DANGLING_TAIL_RE = /(?::|\.\.\.|…)\s*$/;
|
|
70663
|
+
ACTION_ANNOUNCE_RE = /^(?:ent[aã]o[,:]?\s+|agora[,:]?\s+|em seguida[,:]?\s+|a seguir[,:]?\s+|por fim[,:]?\s+|primeiro[,:]?\s+|then[,:]?\s+|now[,:]?\s+|first[,:]?\s+|next,?\s+)*(?:vou\b|irei\b|deixe-me\b|deixa eu\b|pr[oó]ximo passo\b|agora (?:vou|irei|preciso)\b|let me\b|i(?:'|’)?ll\b|i will\b|i(?:'|’)?m going to\b|i am going to\b|going to\b|i(?:'|’)?m about to\b|next,? i\b)/i;
|
|
70064
70664
|
BENIGN_CLOSER_RE = /\b(?:let me know|just let me know|deixa eu saber|me avis(?:e|a)|qualquer (?:coisa|d[uú]vida)|fico (?:à|a) disposi[cç][aã]o)\b[^.!?:\n]{0,80}[.!?]?\s*$/i;
|
|
70065
70665
|
TOOL_CALL_NUDGE = "Voc\xEA anunciou uma a\xE7\xE3o mas n\xE3o executou nenhuma ferramenta neste turno. Pare de descrever o que vai fazer e CHAME a ferramenta agora: use a ferramenta `file` (action write para criar, edit para alterar) para qualquer arquivo ou script, e `run_terminal_cmd` para rodar comandos. N\xC3O escreva o conte\xFAdo do arquivo na resposta nem cole markup de tool call \u2014 emita a chamada de ferramenta de verdade.";
|
|
70066
70666
|
MAX_BRIDGE_STEPS = 50;
|
|
70067
70667
|
BRIDGE_RESULT_PREAMBLE = "Voc\xEA roda via proxy de sess\xE3o web (sem function-calling nativo), ent\xE3o o runtime do CLI consumiu o bloco JSON anterior como chamada interna e EXECUTOU de verdade. N\xE3o repita o bloco nem o texto anterior. Os resultados REAIS est\xE3o abaixo. Continue a tarefa: se precisar de mais a\xE7\xF5es, emita SOMENTE o PR\xD3XIMO bloco ```json (um array de {brief, command, timeout} para terminal, ou {action, path, text} para arquivo). Um bloco por vez. Quando a tarefa terminar, responda em texto normal SEM bloco json.";
|
|
70668
|
+
LEAKED_CALL_RESULT_PREAMBLE = "Sua chamada de ferramenta anterior chegou como TEXTO (n\xE3o como function call nativo), ent\xE3o o runtime do CLI a executou mesmo assim. Os resultados REAIS est\xE3o abaixo. Continue a tarefa chamando as ferramentas NORMALMENTE (run_terminal_cmd, file, todo_write) como function calls de verdade \u2014 N\xC3O cole markup de tool call (`call_tool_function`, `<tool_call>`, etc.) nem JSON de chamada como texto na resposta.";
|
|
70068
70669
|
truncateBridgeSummary = (value, max = 180) => value.length > max ? `${value.slice(0, max)}...` : value;
|
|
70069
70670
|
isWebSessionProxyModel = (modelName) => modelName === "model-deepseek-proxy" || modelName === "model-kimi-proxy";
|
|
70070
70671
|
proxyToolProtocolPolicy = () => `
|
|
@@ -70100,8 +70701,8 @@ Regras:
|
|
|
70100
70701
|
"DANGEROUS MODE"
|
|
70101
70702
|
];
|
|
70102
70703
|
MODEL_LABELS = {
|
|
70103
|
-
"model-nvidia-
|
|
70104
|
-
"model-nvidia-
|
|
70704
|
+
"model-nvidia-mistral-medium-3.5": "NVIDIA - mistralai/mistral-medium-3.5-128b",
|
|
70705
|
+
"model-nvidia-gpt-oss-120b": "NVIDIA - openai/gpt-oss-120b",
|
|
70105
70706
|
"model-nvidia-glm-5.1": "NVIDIA - z-ai/glm-5.1",
|
|
70106
70707
|
"model-nvidia-qwen3.5-397b": "NVIDIA - qwen/qwen3.5-397b-a17b",
|
|
70107
70708
|
"model-openai-chat-latest": "OpenAI - chat-latest",
|
|
@@ -70245,7 +70846,7 @@ ${section}` : "";
|
|
|
70245
70846
|
return null;
|
|
70246
70847
|
}
|
|
70247
70848
|
await (0, import_promises.mkdir)(workdir, { recursive: true });
|
|
70248
|
-
const outputPath =
|
|
70849
|
+
const outputPath = import_node_path8.default.join(workdir, "system-prompt.txt");
|
|
70249
70850
|
await (0, import_promises.writeFile)(outputPath, system, "utf8");
|
|
70250
70851
|
return outputPath;
|
|
70251
70852
|
};
|
|
@@ -70270,124 +70871,453 @@ ${section}` : "";
|
|
|
70270
70871
|
}
|
|
70271
70872
|
});
|
|
70272
70873
|
|
|
70273
|
-
// src/
|
|
70274
|
-
var
|
|
70275
|
-
__export(
|
|
70276
|
-
|
|
70277
|
-
buildBanner: () => buildBanner,
|
|
70278
|
-
shellPrompt: () => shellPrompt,
|
|
70279
|
-
ui: () => ui
|
|
70874
|
+
// src/interactive-input.ts
|
|
70875
|
+
var interactive_input_exports = {};
|
|
70876
|
+
__export(interactive_input_exports, {
|
|
70877
|
+
InteractiveInput: () => InteractiveInput
|
|
70280
70878
|
});
|
|
70281
|
-
|
|
70282
|
-
|
|
70283
|
-
|
|
70284
|
-
const rel = cwd.startsWith(home) ? "~" + cwd.slice(home.length) : cwd;
|
|
70285
|
-
const norm = rel.replace(/\\/g, "/");
|
|
70286
|
-
if (norm.length <= 30) return norm;
|
|
70287
|
-
const parts = norm.split("/");
|
|
70288
|
-
return parts.length > 3 ? `${parts[0]}/\u2026/${parts[parts.length - 1]}` : norm.slice(-30);
|
|
70289
|
-
}
|
|
70290
|
-
function asciiTitle(text2) {
|
|
70291
|
-
const rows = 6;
|
|
70292
|
-
const out2 = [];
|
|
70293
|
-
for (let r = 0; r < rows; r++) {
|
|
70294
|
-
out2.push(
|
|
70295
|
-
[...text2].map((ch) => GLYPHS[ch] ? GLYPHS[ch][r] : " ").join(" ")
|
|
70296
|
-
);
|
|
70297
|
-
}
|
|
70298
|
-
return out2;
|
|
70299
|
-
}
|
|
70300
|
-
function buildBanner(_systemPromptChars, version3 = "1") {
|
|
70301
|
-
const user = (import_node_os4.default.userInfo().username || "hacker").toLowerCase();
|
|
70302
|
-
const host = (import_node_os4.default.hostname() || "localhost").split(".")[0].toLowerCase();
|
|
70303
|
-
const art = asciiTitle("CLAWFAST");
|
|
70304
|
-
const artW = vlen(art[0]);
|
|
70305
|
-
const slogan = "Com o clawfast voc\xEA faz tudo";
|
|
70306
|
-
const header = [
|
|
70307
|
-
"",
|
|
70308
|
-
...art.map((line) => `${C3.greenB}${C3.bold}${line}${C3.reset}`),
|
|
70309
|
-
"",
|
|
70310
|
-
`${C3.cyanB}${C3.bold}${center(slogan, artW)}${C3.reset}`,
|
|
70311
|
-
""
|
|
70312
|
-
];
|
|
70313
|
-
const info = [
|
|
70314
|
-
{ text: "" },
|
|
70315
|
-
{ text: `Bem-vindo de volta, ${user}!`, accent: true },
|
|
70316
|
-
{ text: "" },
|
|
70317
|
-
{ text: "clawfast usa a pasta SPRIT/ para criar" },
|
|
70318
|
-
{ text: "arquivos, scripts e tudo mais." },
|
|
70319
|
-
{ text: "" },
|
|
70320
|
-
{ text: `${user}@${host} \xB7 sem limites` },
|
|
70321
|
-
{ text: shortCwd() },
|
|
70322
|
-
{ text: "" }
|
|
70323
|
-
];
|
|
70324
|
-
const title = `clawfast v${version3}`;
|
|
70325
|
-
const topFill = "\u2500".repeat(Math.max(0, BOX_W - vlen(title) - 5));
|
|
70326
|
-
const top = `${C3.green}\u256D\u2500 ${C3.greenB}${C3.bold}${title}${C3.reset}${C3.green} ${topFill}\u256E${C3.reset}`;
|
|
70327
|
-
const bottom = `${C3.green}\u2570${"\u2500".repeat(BOX_W - 2)}\u256F${C3.reset}`;
|
|
70328
|
-
const cardLines = info.map(({ text: text2, accent }) => {
|
|
70329
|
-
const color = accent ? `${C3.greenB}${C3.bold}` : C3.green;
|
|
70330
|
-
const body = `${color}${padEndV(text2, INNER)}${C3.reset}`;
|
|
70331
|
-
return `${C3.green}\u2502 ${C3.reset}${body}${C3.green} \u2502${C3.reset}`;
|
|
70332
|
-
});
|
|
70333
|
-
const card = [top, ...cardLines, bottom];
|
|
70334
|
-
return "\n" + [...header, ...card].join("\n") + "\n";
|
|
70335
|
-
}
|
|
70336
|
-
function shellPrompt() {
|
|
70337
|
-
const user = (import_node_os4.default.userInfo().username || "hacker").toLowerCase();
|
|
70338
|
-
const host = (import_node_os4.default.hostname() || "localhost").split(".")[0].toLowerCase();
|
|
70339
|
-
const W = 52;
|
|
70340
|
-
const label = " \u2709 mensagem ";
|
|
70341
|
-
const topFill = "\u2500".repeat(Math.max(0, W - vlen(label) - 3));
|
|
70342
|
-
const top = `${C3.green}\u256D\u2500${C3.greenB}${C3.bold}${label}${C3.reset}${C3.green}${topFill}\u256E${C3.reset}`;
|
|
70343
|
-
const id = `${user}\u327F${host} \xB7 ${shortCwd()}`;
|
|
70344
|
-
const mid = `${C3.green}\u2502 ${C3.dim}${id}${C3.reset}`;
|
|
70345
|
-
const bottom = `${C3.green}\u2570\u2500${C3.greenB}${C3.bold}\u276F${C3.reset} `;
|
|
70346
|
-
return `
|
|
70347
|
-
${top}
|
|
70348
|
-
${mid}
|
|
70349
|
-
${bottom}`;
|
|
70350
|
-
}
|
|
70351
|
-
function agentHeader() {
|
|
70352
|
-
return `${C3.magenta}\u256D\u2500 clawfast ${"\u2500".repeat(20)}${C3.reset}
|
|
70353
|
-
`;
|
|
70354
|
-
}
|
|
70355
|
-
var import_node_os4, ESC, C3, INNER, BOX_W, vlen, padEndV, center, GLYPHS, ui;
|
|
70356
|
-
var init_ui = __esm({
|
|
70357
|
-
"src/ui.ts"() {
|
|
70879
|
+
var import_node_readline3, import_node_os5, C4, out2, cols, truncate4, InteractiveInput;
|
|
70880
|
+
var init_interactive_input = __esm({
|
|
70881
|
+
"src/interactive-input.ts"() {
|
|
70358
70882
|
"use strict";
|
|
70359
|
-
|
|
70360
|
-
|
|
70361
|
-
|
|
70362
|
-
|
|
70363
|
-
|
|
70364
|
-
|
|
70365
|
-
|
|
70366
|
-
|
|
70367
|
-
|
|
70368
|
-
|
|
70369
|
-
|
|
70370
|
-
|
|
70371
|
-
|
|
70372
|
-
|
|
70373
|
-
|
|
70374
|
-
|
|
70375
|
-
|
|
70376
|
-
|
|
70377
|
-
|
|
70378
|
-
|
|
70379
|
-
|
|
70380
|
-
|
|
70381
|
-
|
|
70382
|
-
|
|
70383
|
-
|
|
70384
|
-
|
|
70385
|
-
|
|
70386
|
-
|
|
70387
|
-
|
|
70388
|
-
|
|
70883
|
+
import_node_readline3 = __toESM(require("node:readline"));
|
|
70884
|
+
import_node_os5 = __toESM(require("node:os"));
|
|
70885
|
+
init_ui();
|
|
70886
|
+
C4 = ui.C;
|
|
70887
|
+
out2 = (s) => process.stdout.write(s);
|
|
70888
|
+
cols = () => process.stdout.columns || 80;
|
|
70889
|
+
truncate4 = (s, n) => vlen(s) > n ? [...s].slice(0, Math.max(0, n - 1)).join("") + "\u2026" : s;
|
|
70890
|
+
InteractiveInput = class {
|
|
70891
|
+
// row the caret sits on within the drawn block
|
|
70892
|
+
constructor(paste, commands) {
|
|
70893
|
+
this.paste = paste;
|
|
70894
|
+
this.commands = commands;
|
|
70895
|
+
this.buffer = "";
|
|
70896
|
+
this.cursor = 0;
|
|
70897
|
+
this.lastRows = 0;
|
|
70898
|
+
this.history = [];
|
|
70899
|
+
this.histIdx = -1;
|
|
70900
|
+
// -1 = editing the live draft
|
|
70901
|
+
this.draft = "";
|
|
70902
|
+
this.ddSel = 0;
|
|
70903
|
+
this.ddSuppressed = false;
|
|
70904
|
+
// Text to restore on the NEXT prompt: when a command is picked from the
|
|
70905
|
+
// dropdown mid-text, we run the command but stash the surrounding text here
|
|
70906
|
+
// so the user doesn't lose what they were typing.
|
|
70907
|
+
this.pendingInitial = null;
|
|
70908
|
+
this.onKey = null;
|
|
70909
|
+
// When set, prompt() draws a compact single-line labelled prompt ("nome ❯ ")
|
|
70910
|
+
// instead of the full message box + dropdown — used for the /skillcreator
|
|
70911
|
+
// step-by-step capture so each phase shows what it's asking for.
|
|
70912
|
+
this.promptLabel = null;
|
|
70913
|
+
// When true, the submitted value is NOT recorded in ↑ history (used for the
|
|
70914
|
+
// /api key prompt so a pasted secret can't be recalled with the up arrow).
|
|
70915
|
+
this.promptSecret = false;
|
|
70916
|
+
this.inputLineIndex = 2;
|
|
70917
|
+
import_node_readline3.default.emitKeypressEvents(paste.input);
|
|
70918
|
+
paste.input.on("keypress", (str, key) => {
|
|
70919
|
+
this.onKey?.(str ?? "", key ?? {});
|
|
70920
|
+
});
|
|
70921
|
+
}
|
|
70922
|
+
// ── public API ─────────────────────────────────────────────────────────────
|
|
70923
|
+
/**
|
|
70924
|
+
* Render the input and resolve when the user submits / Ctrl+C / Ctrl+D.
|
|
70925
|
+
* Pass `{ label }` for a compact labelled prompt (no box, no dropdown).
|
|
70926
|
+
*/
|
|
70927
|
+
prompt(opts = {}) {
|
|
70928
|
+
this.promptLabel = opts.label ?? null;
|
|
70929
|
+
this.promptSecret = opts.secret ?? false;
|
|
70930
|
+
const initial = this.promptLabel === null && this.pendingInitial ? this.pendingInitial : "";
|
|
70931
|
+
this.pendingInitial = null;
|
|
70932
|
+
this.buffer = initial;
|
|
70933
|
+
this.cursor = initial.length;
|
|
70934
|
+
this.histIdx = -1;
|
|
70935
|
+
this.draft = "";
|
|
70936
|
+
this.ddSel = 0;
|
|
70937
|
+
this.ddSuppressed = false;
|
|
70938
|
+
this.lastRows = 0;
|
|
70939
|
+
if (this.promptLabel === null) out2("\n");
|
|
70940
|
+
this.render();
|
|
70941
|
+
return new Promise((resolve2) => {
|
|
70942
|
+
this.onKey = (str, key) => {
|
|
70943
|
+
const done = this.handleEditKey(str, key);
|
|
70944
|
+
if (!done) {
|
|
70945
|
+
this.render();
|
|
70946
|
+
return;
|
|
70947
|
+
}
|
|
70948
|
+
this.onKey = null;
|
|
70949
|
+
resolve2(done.result);
|
|
70950
|
+
};
|
|
70951
|
+
});
|
|
70952
|
+
}
|
|
70953
|
+
/**
|
|
70954
|
+
* Arrow-navigable single-choice list. Returns the chosen index, or null when
|
|
70955
|
+
* the user cancels (Esc / q / Ctrl+C).
|
|
70956
|
+
*/
|
|
70957
|
+
select(title, items, initial = 0) {
|
|
70958
|
+
let sel = Math.max(0, Math.min(initial, items.length - 1));
|
|
70959
|
+
this.lastRows = 0;
|
|
70960
|
+
out2("\n");
|
|
70961
|
+
this.renderList(title, items, sel);
|
|
70962
|
+
return new Promise((resolve2) => {
|
|
70963
|
+
const finish = (value) => {
|
|
70964
|
+
this.collapseTo(this.lastRows);
|
|
70965
|
+
this.onKey = null;
|
|
70966
|
+
resolve2(value);
|
|
70967
|
+
};
|
|
70968
|
+
this.onKey = (str, key) => {
|
|
70969
|
+
if (key.ctrl && key.name === "c") return finish(null);
|
|
70970
|
+
switch (key.name) {
|
|
70971
|
+
case "up":
|
|
70972
|
+
sel = (sel - 1 + items.length) % items.length;
|
|
70973
|
+
this.renderList(title, items, sel);
|
|
70974
|
+
return;
|
|
70975
|
+
case "down":
|
|
70976
|
+
case "tab":
|
|
70977
|
+
sel = (sel + 1) % items.length;
|
|
70978
|
+
this.renderList(title, items, sel);
|
|
70979
|
+
return;
|
|
70980
|
+
case "return":
|
|
70981
|
+
return finish(sel);
|
|
70982
|
+
case "escape":
|
|
70983
|
+
return finish(null);
|
|
70984
|
+
default:
|
|
70985
|
+
if (str === "q") return finish(null);
|
|
70986
|
+
if (/^[1-9]$/.test(str)) {
|
|
70987
|
+
const i = Number(str) - 1;
|
|
70988
|
+
if (i < items.length) {
|
|
70989
|
+
sel = i;
|
|
70990
|
+
this.renderList(title, items, sel);
|
|
70991
|
+
}
|
|
70992
|
+
}
|
|
70993
|
+
return;
|
|
70994
|
+
}
|
|
70995
|
+
};
|
|
70996
|
+
});
|
|
70997
|
+
}
|
|
70998
|
+
/**
|
|
70999
|
+
* Lightweight line reader used WHILE a turn is running, so typed lines can be
|
|
71000
|
+
* forwarded to an interactive command's stdin. No box/dropdown — just echoes
|
|
71001
|
+
* and collects until Enter. Ctrl+C invokes `onSigint`.
|
|
71002
|
+
*/
|
|
71003
|
+
beginTurn(onLine, onSigint) {
|
|
71004
|
+
let buf = "";
|
|
71005
|
+
this.onKey = (str, key) => {
|
|
71006
|
+
if (key.ctrl && key.name === "c") return onSigint();
|
|
71007
|
+
if (key.name === "return") {
|
|
71008
|
+
out2("\r\n");
|
|
71009
|
+
const line = this.paste.expand(buf);
|
|
71010
|
+
buf = "";
|
|
71011
|
+
onLine(line);
|
|
71012
|
+
return;
|
|
71013
|
+
}
|
|
71014
|
+
if (key.name === "backspace") {
|
|
71015
|
+
if (buf.length) {
|
|
71016
|
+
buf = buf.slice(0, -1);
|
|
71017
|
+
out2("\b \b");
|
|
71018
|
+
}
|
|
71019
|
+
return;
|
|
71020
|
+
}
|
|
71021
|
+
if (str && str.charCodeAt(0) >= 32 && !key.ctrl && !key.meta) {
|
|
71022
|
+
buf += str;
|
|
71023
|
+
out2(str);
|
|
71024
|
+
}
|
|
71025
|
+
};
|
|
71026
|
+
}
|
|
71027
|
+
endTurn() {
|
|
71028
|
+
this.onKey = null;
|
|
71029
|
+
}
|
|
71030
|
+
// ── editing ──────────────────────────────────────────────────────────────
|
|
71031
|
+
handleEditKey(str, key) {
|
|
71032
|
+
const items = this.dropdownItems();
|
|
71033
|
+
if (key.ctrl && key.name === "c") {
|
|
71034
|
+
this.finishLine();
|
|
71035
|
+
return { result: { type: "sigint" } };
|
|
71036
|
+
}
|
|
71037
|
+
if (key.ctrl && key.name === "d") {
|
|
71038
|
+
if (this.buffer.length === 0) {
|
|
71039
|
+
this.finishLine();
|
|
71040
|
+
return { result: { type: "eof" } };
|
|
71041
|
+
}
|
|
71042
|
+
this.deleteForward();
|
|
71043
|
+
return null;
|
|
71044
|
+
}
|
|
71045
|
+
switch (key.name) {
|
|
71046
|
+
case "return": {
|
|
71047
|
+
if (items.length > 0) {
|
|
71048
|
+
const name25 = items[this.ddSel].name;
|
|
71049
|
+
const tok = this.slashTokenAtCursor();
|
|
71050
|
+
const leftover = tok ? this.buffer.slice(0, tok.start) + this.buffer.slice(tok.end) : "";
|
|
71051
|
+
this.pendingInitial = leftover.trim() ? leftover : null;
|
|
71052
|
+
this.buffer = name25;
|
|
71053
|
+
this.cursor = name25.length;
|
|
71054
|
+
}
|
|
71055
|
+
const value = this.paste.expand(this.buffer);
|
|
71056
|
+
if (value.trim() && !this.promptSecret) this.history.push(value);
|
|
71057
|
+
this.finishLine();
|
|
71058
|
+
return { result: { type: "line", value } };
|
|
71059
|
+
}
|
|
71060
|
+
case "tab":
|
|
71061
|
+
if (items.length > 0) {
|
|
71062
|
+
this.applyCommandInPlace(items[this.ddSel].name);
|
|
71063
|
+
this.ddSuppressed = false;
|
|
71064
|
+
}
|
|
71065
|
+
return null;
|
|
71066
|
+
case "up":
|
|
71067
|
+
if (items.length > 0) {
|
|
71068
|
+
this.ddSel = (this.ddSel - 1 + items.length) % items.length;
|
|
71069
|
+
} else {
|
|
71070
|
+
this.historyPrev();
|
|
71071
|
+
}
|
|
71072
|
+
return null;
|
|
71073
|
+
case "down":
|
|
71074
|
+
if (items.length > 0) {
|
|
71075
|
+
this.ddSel = (this.ddSel + 1) % items.length;
|
|
71076
|
+
} else {
|
|
71077
|
+
this.historyNext();
|
|
71078
|
+
}
|
|
71079
|
+
return null;
|
|
71080
|
+
case "escape":
|
|
71081
|
+
if (items.length > 0) this.ddSuppressed = true;
|
|
71082
|
+
return null;
|
|
71083
|
+
case "left":
|
|
71084
|
+
if (this.cursor > 0) this.cursor--;
|
|
71085
|
+
return null;
|
|
71086
|
+
case "right":
|
|
71087
|
+
if (this.cursor < this.buffer.length) this.cursor++;
|
|
71088
|
+
return null;
|
|
71089
|
+
case "home":
|
|
71090
|
+
this.cursor = 0;
|
|
71091
|
+
return null;
|
|
71092
|
+
case "end":
|
|
71093
|
+
this.cursor = this.buffer.length;
|
|
71094
|
+
return null;
|
|
71095
|
+
case "backspace":
|
|
71096
|
+
if (this.cursor > 0) {
|
|
71097
|
+
this.buffer = this.buffer.slice(0, this.cursor - 1) + this.buffer.slice(this.cursor);
|
|
71098
|
+
this.cursor--;
|
|
71099
|
+
this.ddSuppressed = false;
|
|
71100
|
+
}
|
|
71101
|
+
return null;
|
|
71102
|
+
case "delete":
|
|
71103
|
+
this.deleteForward();
|
|
71104
|
+
return null;
|
|
71105
|
+
}
|
|
71106
|
+
if (key.ctrl && key.name === "u") {
|
|
71107
|
+
this.buffer = this.buffer.slice(this.cursor);
|
|
71108
|
+
this.cursor = 0;
|
|
71109
|
+
this.ddSuppressed = false;
|
|
71110
|
+
return null;
|
|
71111
|
+
}
|
|
71112
|
+
if (key.ctrl && key.name === "w") {
|
|
71113
|
+
const left = this.buffer.slice(0, this.cursor);
|
|
71114
|
+
const trimmed = left.replace(/\s*\S+\s*$/u, "");
|
|
71115
|
+
this.buffer = trimmed + this.buffer.slice(this.cursor);
|
|
71116
|
+
this.cursor = trimmed.length;
|
|
71117
|
+
this.ddSuppressed = false;
|
|
71118
|
+
return null;
|
|
71119
|
+
}
|
|
71120
|
+
if (key.ctrl && key.name === "a") {
|
|
71121
|
+
this.cursor = 0;
|
|
71122
|
+
return null;
|
|
71123
|
+
}
|
|
71124
|
+
if (key.ctrl && key.name === "e") {
|
|
71125
|
+
this.cursor = this.buffer.length;
|
|
71126
|
+
return null;
|
|
71127
|
+
}
|
|
71128
|
+
if (str && !key.ctrl && !key.meta && str.charCodeAt(0) >= 32) {
|
|
71129
|
+
this.buffer = this.buffer.slice(0, this.cursor) + str + this.buffer.slice(this.cursor);
|
|
71130
|
+
this.cursor += str.length;
|
|
71131
|
+
this.ddSuppressed = false;
|
|
71132
|
+
}
|
|
71133
|
+
return null;
|
|
71134
|
+
}
|
|
71135
|
+
deleteForward() {
|
|
71136
|
+
if (this.cursor < this.buffer.length) {
|
|
71137
|
+
this.buffer = this.buffer.slice(0, this.cursor) + this.buffer.slice(this.cursor + 1);
|
|
71138
|
+
this.ddSuppressed = false;
|
|
71139
|
+
}
|
|
71140
|
+
}
|
|
71141
|
+
historyPrev() {
|
|
71142
|
+
if (this.history.length === 0) return;
|
|
71143
|
+
if (this.histIdx === -1) {
|
|
71144
|
+
this.draft = this.buffer;
|
|
71145
|
+
this.histIdx = this.history.length - 1;
|
|
71146
|
+
} else if (this.histIdx > 0) {
|
|
71147
|
+
this.histIdx--;
|
|
71148
|
+
}
|
|
71149
|
+
this.buffer = this.history[this.histIdx];
|
|
71150
|
+
this.cursor = this.buffer.length;
|
|
71151
|
+
}
|
|
71152
|
+
historyNext() {
|
|
71153
|
+
if (this.histIdx === -1) return;
|
|
71154
|
+
if (this.histIdx < this.history.length - 1) {
|
|
71155
|
+
this.histIdx++;
|
|
71156
|
+
this.buffer = this.history[this.histIdx];
|
|
71157
|
+
} else {
|
|
71158
|
+
this.histIdx = -1;
|
|
71159
|
+
this.buffer = this.draft;
|
|
71160
|
+
}
|
|
71161
|
+
this.cursor = this.buffer.length;
|
|
71162
|
+
}
|
|
71163
|
+
// ── rendering ──────────────────────────────────────────────────────────────
|
|
71164
|
+
// The slash-command "token" the cursor is sitting in — the run of
|
|
71165
|
+
// non-whitespace chars around the cursor, when it begins with "/". Works at
|
|
71166
|
+
// the start of the line OR in the middle of the text (e.g. "veja o /mod"),
|
|
71167
|
+
// so the command dropdown opens wherever you type a slash. Returns the span
|
|
71168
|
+
// [start, end) to replace and the query (the whole token) to filter by.
|
|
71169
|
+
slashTokenAtCursor() {
|
|
71170
|
+
const b = this.buffer;
|
|
71171
|
+
let start = this.cursor;
|
|
71172
|
+
while (start > 0 && !/\s/.test(b[start - 1])) start--;
|
|
71173
|
+
if (b[start] !== "/") return null;
|
|
71174
|
+
let end = this.cursor;
|
|
71175
|
+
while (end < b.length && !/\s/.test(b[end])) end++;
|
|
71176
|
+
const query = b.slice(start, end);
|
|
71177
|
+
if (!/^\/\S*$/.test(query)) return null;
|
|
71178
|
+
return { start, end, query };
|
|
71179
|
+
}
|
|
71180
|
+
// Replace the slash token under the cursor with `name` (used by Tab/Enter
|
|
71181
|
+
// completion), leaving the surrounding text intact and the cursor right after
|
|
71182
|
+
// the inserted command.
|
|
71183
|
+
applyCommandInPlace(name25) {
|
|
71184
|
+
const tok = this.slashTokenAtCursor();
|
|
71185
|
+
if (!tok) return;
|
|
71186
|
+
this.buffer = this.buffer.slice(0, tok.start) + name25 + this.buffer.slice(tok.end);
|
|
71187
|
+
this.cursor = tok.start + name25.length;
|
|
71188
|
+
}
|
|
71189
|
+
dropdownItems() {
|
|
71190
|
+
if (this.promptLabel !== null) return [];
|
|
71191
|
+
if (this.ddSuppressed) return [];
|
|
71192
|
+
const tok = this.slashTokenAtCursor();
|
|
71193
|
+
if (!tok) return [];
|
|
71194
|
+
const q = tok.query.toLowerCase();
|
|
71195
|
+
return this.commands.filter((c) => c.name.toLowerCase().startsWith(q));
|
|
71196
|
+
}
|
|
71197
|
+
render() {
|
|
71198
|
+
if (this.promptLabel !== null) {
|
|
71199
|
+
this.renderCompact();
|
|
71200
|
+
return;
|
|
71201
|
+
}
|
|
71202
|
+
const width = cols();
|
|
71203
|
+
const user = (import_node_os5.default.userInfo().username || "hacker").toLowerCase();
|
|
71204
|
+
const host = (import_node_os5.default.hostname() || "localhost").split(".")[0].toLowerCase();
|
|
71205
|
+
const label = " \u2709 mensagem ";
|
|
71206
|
+
const boxW = Math.min(54, Math.max(28, width - 2));
|
|
71207
|
+
const topFill = "\u2500".repeat(Math.max(0, boxW - vlen(label) - 3));
|
|
71208
|
+
const top = `${C4.green}\u256D\u2500${C4.greenB}${C4.bold}${label}${C4.reset}${C4.green}${topFill}\u256E${C4.reset}`;
|
|
71209
|
+
const id = `${user}\u327F${host} \xB7 ${shortCwd()}`;
|
|
71210
|
+
const idLine = `${C4.green}\u2502 ${C4.dim}${truncate4(id, boxW - 4)}${C4.reset}`;
|
|
71211
|
+
const prefix = `${C4.green}\u2570\u2500${C4.greenB}${C4.bold}\u276F${C4.reset} `;
|
|
71212
|
+
const prefixLen = 4;
|
|
71213
|
+
const avail = Math.max(8, width - prefixLen - 1);
|
|
71214
|
+
let start = 0;
|
|
71215
|
+
if (this.cursor > avail) start = this.cursor - avail;
|
|
71216
|
+
const visible = this.buffer.slice(start, start + avail);
|
|
71217
|
+
const caretCol = prefixLen + (this.cursor - start);
|
|
71218
|
+
const promptLine2 = prefix + visible;
|
|
71219
|
+
const lines = [top, idLine, promptLine2];
|
|
71220
|
+
const items = this.dropdownItems();
|
|
71221
|
+
if (items.length > 0) {
|
|
71222
|
+
this.ddSel = Math.min(this.ddSel, items.length - 1);
|
|
71223
|
+
const ddHint = "\u2191\u2193 navega \xB7 Enter roda \xB7 Tab completa";
|
|
71224
|
+
const nameW = Math.max(...items.map((i) => vlen(i.name)));
|
|
71225
|
+
const ddInner = Math.min(boxW, Math.max(24, width - 4));
|
|
71226
|
+
lines.push(`${C4.dim} \u256D${"\u2500".repeat(ddInner)}\u256E${C4.reset}`);
|
|
71227
|
+
items.forEach((it, i) => {
|
|
71228
|
+
const active2 = i === this.ddSel;
|
|
71229
|
+
const marker25 = active2 ? `${C4.greenB}\u25B8 ` : `${C4.dim} `;
|
|
71230
|
+
const name25 = (active2 ? `${C4.greenB}${C4.bold}` : C4.cyan) + it.name;
|
|
71231
|
+
const pad = " ".repeat(Math.max(1, nameW - vlen(it.name) + 2));
|
|
71232
|
+
const descRoom = ddInner - 2 - nameW - 2;
|
|
71233
|
+
const desc = `${C4.dim}${truncate4(it.desc, Math.max(4, descRoom))}`;
|
|
71234
|
+
const body = `${marker25}${name25}${C4.reset}${pad}${desc}${C4.reset}`;
|
|
71235
|
+
const padded = body + " ".repeat(Math.max(0, ddInner - 1 - vlen(body)));
|
|
71236
|
+
lines.push(`${C4.dim} \u2502${C4.reset}${padded}${C4.dim}\u2502${C4.reset}`);
|
|
71237
|
+
});
|
|
71238
|
+
lines.push(
|
|
71239
|
+
`${C4.dim} \u2570${"\u2500".repeat(ddInner)}\u256F ${ddHint}${C4.reset}`
|
|
71240
|
+
);
|
|
71241
|
+
} else {
|
|
71242
|
+
this.ddSel = 0;
|
|
71243
|
+
}
|
|
71244
|
+
this.inputLineIndex = 2;
|
|
71245
|
+
this.paint(lines, caretCol);
|
|
71246
|
+
}
|
|
71247
|
+
/** Compact single-line labelled prompt ("nome ❯ …") for step-by-step capture. */
|
|
71248
|
+
renderCompact() {
|
|
71249
|
+
const width = cols();
|
|
71250
|
+
const label = this.promptLabel ?? "";
|
|
71251
|
+
const prefix = `${C4.cyan}${C4.bold}${label}${C4.reset} ${C4.greenB}${C4.bold}\u276F${C4.reset} `;
|
|
71252
|
+
const prefixLen = vlen(`${label} \u276F `);
|
|
71253
|
+
const avail = Math.max(8, width - prefixLen - 1);
|
|
71254
|
+
let start = 0;
|
|
71255
|
+
if (this.cursor > avail) start = this.cursor - avail;
|
|
71256
|
+
const visible = this.buffer.slice(start, start + avail);
|
|
71257
|
+
const caretCol = prefixLen + (this.cursor - start);
|
|
71258
|
+
this.inputLineIndex = 0;
|
|
71259
|
+
this.paint([prefix + visible], caretCol);
|
|
71260
|
+
}
|
|
71261
|
+
/** Repaint the whole block, then place the cursor on the active input line. */
|
|
71262
|
+
paint(lines, caretCol) {
|
|
71263
|
+
let s = "";
|
|
71264
|
+
if (this.lastRows > 1) s += `\x1B[${this.lastRows - 1}A`;
|
|
71265
|
+
s += "\r\x1B[0J";
|
|
71266
|
+
s += lines.join("\r\n");
|
|
71267
|
+
this.lastRows = lines.length;
|
|
71268
|
+
const below = lines.length - 1 - this.inputLineIndex;
|
|
71269
|
+
if (below > 0) s += `\x1B[${below}A`;
|
|
71270
|
+
s += "\r";
|
|
71271
|
+
if (caretCol > 0) s += `\x1B[${caretCol}C`;
|
|
71272
|
+
out2(s);
|
|
71273
|
+
}
|
|
71274
|
+
/** Collapse the dropdown, keep the typed line, and drop to a fresh line below. */
|
|
71275
|
+
finishLine() {
|
|
71276
|
+
this.ddSuppressed = true;
|
|
71277
|
+
this.render();
|
|
71278
|
+
const below = this.lastRows - 1 - this.inputLineIndex;
|
|
71279
|
+
if (below > 0) out2(`\x1B[${below}B`);
|
|
71280
|
+
out2("\r\n");
|
|
71281
|
+
this.lastRows = 0;
|
|
71282
|
+
}
|
|
71283
|
+
renderList(title, items, sel) {
|
|
71284
|
+
const width = cols();
|
|
71285
|
+
const labelW = Math.max(...items.map((i) => vlen(i.label)));
|
|
71286
|
+
const inner = Math.min(
|
|
71287
|
+
Math.max(28, width - 4),
|
|
71288
|
+
Math.max(labelW + 8, title.length + 4)
|
|
71289
|
+
);
|
|
71290
|
+
const lines = [];
|
|
71291
|
+
lines.push(`${C4.cyan}\u256D\u2500 ${C4.bold}${title}${C4.reset}`);
|
|
71292
|
+
items.forEach((it, i) => {
|
|
71293
|
+
const active2 = i === sel;
|
|
71294
|
+
const marker25 = active2 ? `${C4.greenB}\u276F ` : `${C4.dim} `;
|
|
71295
|
+
const text2 = active2 ? `${C4.greenB}${C4.bold}${it.label}${C4.reset}` : `${C4.reset}${it.label}`;
|
|
71296
|
+
const hint = it.hint ? ` ${C4.dim}${truncate4(it.hint, Math.max(6, inner - labelW - 6))}${C4.reset}` : "";
|
|
71297
|
+
lines.push(`${C4.cyan}\u2502 ${C4.reset}${marker25}${text2}${C4.reset}${hint}`);
|
|
71298
|
+
});
|
|
71299
|
+
lines.push(
|
|
71300
|
+
`${C4.cyan}\u2570\u2500${C4.reset} ${C4.dim}\u2191\u2193 navega \xB7 Enter seleciona \xB7 Esc cancela${C4.reset}`
|
|
71301
|
+
);
|
|
71302
|
+
this.paintBlock(lines);
|
|
71303
|
+
}
|
|
71304
|
+
/** Repaint a block and leave the cursor just below it (for list/menu modes). */
|
|
71305
|
+
paintBlock(lines) {
|
|
71306
|
+
let s = "";
|
|
71307
|
+
if (this.lastRows > 1) s += `\x1B[${this.lastRows - 1}A`;
|
|
71308
|
+
s += "\r\x1B[0J";
|
|
71309
|
+
s += lines.join("\r\n");
|
|
71310
|
+
s += "\r";
|
|
71311
|
+
out2(s);
|
|
71312
|
+
this.lastRows = lines.length;
|
|
71313
|
+
}
|
|
71314
|
+
/** Move the cursor below a block of `rows` lines and clear it. */
|
|
71315
|
+
collapseTo(rows) {
|
|
71316
|
+
if (rows > 1) out2(`\x1B[${rows - 1}A`);
|
|
71317
|
+
out2("\r\x1B[0J");
|
|
71318
|
+
this.lastRows = 0;
|
|
71319
|
+
}
|
|
70389
71320
|
};
|
|
70390
|
-
ui = { C: C3, buildBanner, shellPrompt, agentHeader };
|
|
70391
71321
|
}
|
|
70392
71322
|
});
|
|
70393
71323
|
|
|
@@ -70395,12 +71325,12 @@ var init_ui = __esm({
|
|
|
70395
71325
|
var index_exports = {};
|
|
70396
71326
|
async function main() {
|
|
70397
71327
|
const { createAgent: createAgent2 } = await Promise.resolve().then(() => (init_agent(), agent_exports));
|
|
70398
|
-
const { buildBanner: buildBanner2,
|
|
71328
|
+
const { buildBanner: buildBanner2, agentHeader: agentHeader2, ui: ui2 } = await Promise.resolve().then(() => (init_ui(), ui_exports));
|
|
71329
|
+
const { InteractiveInput: InteractiveInput2 } = await Promise.resolve().then(() => (init_interactive_input(), interactive_input_exports));
|
|
71330
|
+
const C5 = ui2.C;
|
|
70399
71331
|
if (!bootQuiet) {
|
|
70400
|
-
process.stdout.write(
|
|
70401
|
-
|
|
70402
|
-
`
|
|
70403
|
-
);
|
|
71332
|
+
process.stdout.write(`${C5.dim} booting local sandbox + agent\u2026${C5.reset}
|
|
71333
|
+
`);
|
|
70404
71334
|
}
|
|
70405
71335
|
const agent = await createAgent2();
|
|
70406
71336
|
const sys = agent.getSystemPrompt();
|
|
@@ -70409,39 +71339,37 @@ async function main() {
|
|
|
70409
71339
|
process.stdout.write(buildBanner2(sys.length, version3));
|
|
70410
71340
|
const updateNotice = getUpdateNotice(version3);
|
|
70411
71341
|
if (updateNotice) {
|
|
70412
|
-
process.stdout.write(
|
|
70413
|
-
|
|
70414
|
-
`
|
|
70415
|
-
);
|
|
71342
|
+
process.stdout.write(`${C5.yellow}\u2191 ${updateNotice}${C5.reset}
|
|
71343
|
+
`);
|
|
70416
71344
|
}
|
|
70417
71345
|
refreshUpdateCacheInBackground(version3);
|
|
70418
71346
|
if (consumePostUpdateLaunch(version3)) {
|
|
70419
71347
|
process.stdout.write(
|
|
70420
|
-
`${
|
|
71348
|
+
`${C5.greenB}Seja bem vindo ao submundo.${C5.reset} ${C5.dim}clawfast atualizado para ${version3} \u2014 rode ${C5.reset}${C5.cyan}/nov${C5.reset}${C5.dim} para ver as novidades.${C5.reset}
|
|
70421
71349
|
`
|
|
70422
71350
|
);
|
|
70423
71351
|
}
|
|
71352
|
+
process.stdout.write(
|
|
71353
|
+
`${C5.dim}digite ${C5.reset}${C5.cyan}/${C5.reset}${C5.dim} para ver os comandos \xB7 \u2191\u2193 hist\xF3rico \xB7 Ctrl+C interrompe${C5.reset}
|
|
71354
|
+
`
|
|
71355
|
+
);
|
|
71356
|
+
const COMMANDS = [
|
|
71357
|
+
{ name: "/model", desc: "trocar o modelo (seletor com setas)" },
|
|
71358
|
+
{ name: "/api", desc: "trocar a chave NVIDIA (testa e ativa na hora)" },
|
|
71359
|
+
{ name: "/skills", desc: "listar as skills instaladas" },
|
|
71360
|
+
{ name: "/skillcreator", desc: "criar uma nova skill" },
|
|
71361
|
+
{ name: "/system", desc: "salvar o system prompt (HTML) na \xC1rea de Trabalho" },
|
|
71362
|
+
{ name: "/nov", desc: "novidades desta vers\xE3o" },
|
|
71363
|
+
{ name: "/exit", desc: "fechar o clawfast" }
|
|
71364
|
+
];
|
|
70424
71365
|
const pasteInput = createPasteInput();
|
|
70425
|
-
const
|
|
70426
|
-
input: pasteInput.input,
|
|
70427
|
-
output: process.stdout,
|
|
70428
|
-
terminal: true
|
|
70429
|
-
});
|
|
71366
|
+
const inputUI = new InteractiveInput2(pasteInput, COMMANDS);
|
|
70430
71367
|
let closing = false;
|
|
70431
|
-
let
|
|
70432
|
-
let awaitingModelSelection = false;
|
|
70433
|
-
let skillCreator = null;
|
|
70434
|
-
const prompt = () => {
|
|
70435
|
-
rl.setPrompt(
|
|
70436
|
-
skillCreator ? skillPrompt(skillCreator.phase) : awaitingModelSelection ? modelPrompt() : shellPrompt2()
|
|
70437
|
-
);
|
|
70438
|
-
rl.prompt();
|
|
70439
|
-
};
|
|
71368
|
+
let shuttingDown = false;
|
|
70440
71369
|
let activeAbort = null;
|
|
70441
71370
|
let turnActive = false;
|
|
70442
71371
|
let exitArmed = false;
|
|
70443
71372
|
let exitTimer = null;
|
|
70444
|
-
let lastSigint = 0;
|
|
70445
71373
|
const armExit = () => {
|
|
70446
71374
|
exitArmed = true;
|
|
70447
71375
|
if (exitTimer) clearTimeout(exitTimer);
|
|
@@ -70450,69 +71378,58 @@ async function main() {
|
|
|
70450
71378
|
exitTimer = null;
|
|
70451
71379
|
}, 2e3);
|
|
70452
71380
|
};
|
|
70453
|
-
const
|
|
70454
|
-
|
|
70455
|
-
|
|
70456
|
-
|
|
70457
|
-
|
|
70458
|
-
|
|
70459
|
-
|
|
70460
|
-
|
|
70461
|
-
|
|
70462
|
-
|
|
70463
|
-
|
|
70464
|
-
|
|
70465
|
-
|
|
70466
|
-
|
|
70467
|
-
|
|
70468
|
-
|
|
70469
|
-
|
|
70470
|
-
|
|
70471
|
-
|
|
70472
|
-
|
|
70473
|
-
|
|
70474
|
-
|
|
70475
|
-
`
|
|
70476
|
-
|
|
70477
|
-
} else {
|
|
70478
|
-
process.stdout.write(
|
|
70479
|
-
`
|
|
70480
|
-
${ui2.C.dim}Ctrl+C de novo para fechar${ui2.C.reset}
|
|
71381
|
+
const shutdown = async () => {
|
|
71382
|
+
if (shuttingDown) return;
|
|
71383
|
+
shuttingDown = true;
|
|
71384
|
+
closing = true;
|
|
71385
|
+
pasteInput.dispose();
|
|
71386
|
+
process.stdout.write("\nClosing sandbox...\n");
|
|
71387
|
+
await agent.close();
|
|
71388
|
+
process.exit(0);
|
|
71389
|
+
};
|
|
71390
|
+
const desktopDir = () => {
|
|
71391
|
+
const home = import_node_os6.default.homedir();
|
|
71392
|
+
const candidates = [
|
|
71393
|
+
process.env.OneDrive ? import_node_path9.default.join(process.env.OneDrive, "Desktop") : null,
|
|
71394
|
+
process.env.USERPROFILE ? import_node_path9.default.join(process.env.USERPROFILE, "Desktop") : null,
|
|
71395
|
+
import_node_path9.default.join(home, "Desktop"),
|
|
71396
|
+
import_node_path9.default.join(home, "\xC1rea de Trabalho"),
|
|
71397
|
+
import_node_path9.default.join(home, "OneDrive", "Desktop")
|
|
71398
|
+
].filter((p) => Boolean(p));
|
|
71399
|
+
return candidates.find((p) => (0, import_node_fs8.existsSync)(p)) ?? home;
|
|
71400
|
+
};
|
|
71401
|
+
const printFatal = (err) => {
|
|
71402
|
+
process.stderr.write(
|
|
71403
|
+
`
|
|
71404
|
+
[fatal] ${err instanceof Error ? err.stack || err.message : String(err)}
|
|
70481
71405
|
`
|
|
70482
|
-
|
|
70483
|
-
if (!awaitingModelSelection) prompt();
|
|
70484
|
-
}
|
|
70485
|
-
armExit();
|
|
71406
|
+
);
|
|
70486
71407
|
};
|
|
70487
|
-
|
|
70488
|
-
process.on("SIGINT", handleSigint);
|
|
70489
|
-
rl.on("SIGINT", handleSigint);
|
|
71408
|
+
let skillCreator = null;
|
|
70490
71409
|
const printSkillList = () => {
|
|
70491
71410
|
const skills = listSkills();
|
|
70492
71411
|
if (skills.length === 0) {
|
|
70493
71412
|
process.stdout.write(
|
|
70494
71413
|
`
|
|
70495
|
-
${
|
|
71414
|
+
${C5.dim}nenhuma skill instalada. crie uma com /skillcreator${C5.reset}
|
|
70496
71415
|
`
|
|
70497
71416
|
);
|
|
70498
71417
|
return;
|
|
70499
71418
|
}
|
|
70500
71419
|
process.stdout.write(
|
|
70501
71420
|
`
|
|
70502
|
-
${
|
|
71421
|
+
${C5.cyan}skills instaladas${C5.reset} ${C5.dim}(${skillsDir()})${C5.reset}
|
|
70503
71422
|
`
|
|
70504
71423
|
);
|
|
70505
71424
|
for (const s of skills) {
|
|
70506
|
-
const flags = s.always ? ` ${
|
|
71425
|
+
const flags = s.always ? ` ${C5.yellow}[sempre]${C5.reset}` : "";
|
|
70507
71426
|
process.stdout.write(
|
|
70508
|
-
` ${
|
|
71427
|
+
` ${C5.green}${s.name}${C5.reset}${flags} ${C5.dim}\u2014${C5.reset} ${s.description}
|
|
70509
71428
|
`
|
|
70510
71429
|
);
|
|
70511
71430
|
}
|
|
70512
|
-
process.stdout.write(
|
|
70513
|
-
|
|
70514
|
-
`
|
|
70515
|
-
);
|
|
71431
|
+
process.stdout.write(`${C5.dim}remover: /skill delete <nome>${C5.reset}
|
|
71432
|
+
`);
|
|
70516
71433
|
};
|
|
70517
71434
|
const handleSkillCommand = (input) => {
|
|
70518
71435
|
if (input === "/skillcreator") {
|
|
@@ -70525,9 +71442,9 @@ ${ui2.C.cyan}skills instaladas${ui2.C.reset} ${ui2.C.dim}(${skillsDir()})${ui2.C
|
|
|
70525
71442
|
};
|
|
70526
71443
|
process.stdout.write(
|
|
70527
71444
|
`
|
|
70528
|
-
${
|
|
70529
|
-
${
|
|
70530
|
-
${
|
|
71445
|
+
${C5.greenB}criar skill${C5.reset} ${C5.dim}(/cancelar para abortar)${C5.reset}
|
|
71446
|
+
${C5.dim}skills ficam disponiveis para TODOS os modelos; o conteudo completo so e carregado quando o pedido casa com a skill.${C5.reset}
|
|
71447
|
+
${C5.cyan}nome da skill?${C5.reset} ${C5.dim}(ex: xss-recon)${C5.reset}
|
|
70531
71448
|
`
|
|
70532
71449
|
);
|
|
70533
71450
|
return;
|
|
@@ -70545,29 +71462,27 @@ ${ui2.C.cyan}nome da skill?${ui2.C.reset} ${ui2.C.dim}(ex: xss-recon)${ui2.C.res
|
|
|
70545
71462
|
}
|
|
70546
71463
|
if (sub === "delete" || sub === "rm" || sub === "remove") {
|
|
70547
71464
|
if (!arg) {
|
|
70548
|
-
process.stdout.write(
|
|
70549
|
-
|
|
70550
|
-
`
|
|
70551
|
-
);
|
|
71465
|
+
process.stdout.write(`${C5.yellow}uso: /skill delete <nome>${C5.reset}
|
|
71466
|
+
`);
|
|
70552
71467
|
return;
|
|
70553
71468
|
}
|
|
70554
71469
|
if (deleteSkill(arg)) {
|
|
70555
71470
|
await agent.refreshSkills();
|
|
70556
71471
|
process.stdout.write(
|
|
70557
|
-
`${
|
|
71472
|
+
`${C5.green}\u2713 skill '${slugify(arg)}' removida${C5.reset}
|
|
70558
71473
|
`
|
|
70559
71474
|
);
|
|
70560
71475
|
} else {
|
|
70561
71476
|
process.stdout.write(
|
|
70562
|
-
`${
|
|
71477
|
+
`${C5.yellow}skill '${arg}' nao encontrada${C5.reset}
|
|
70563
71478
|
`
|
|
70564
71479
|
);
|
|
70565
71480
|
}
|
|
70566
71481
|
return;
|
|
70567
71482
|
}
|
|
70568
71483
|
process.stdout.write(
|
|
70569
|
-
`${
|
|
70570
|
-
${
|
|
71484
|
+
`${C5.yellow}subcomando desconhecido: ${sub}${C5.reset}
|
|
71485
|
+
${C5.dim}use: /skillcreator | /skills | /skill delete <nome>${C5.reset}
|
|
70571
71486
|
`
|
|
70572
71487
|
);
|
|
70573
71488
|
};
|
|
@@ -70575,7 +71490,7 @@ ${ui2.C.dim}use: /skillcreator | /skills | /skill delete <nome>${ui2.C.reset}
|
|
|
70575
71490
|
const text2 = sc.bodyLines.join("\n");
|
|
70576
71491
|
const lines = text2 ? text2.split("\n").length : 0;
|
|
70577
71492
|
process.stdout.write(
|
|
70578
|
-
`${
|
|
71493
|
+
`${C5.dim} capturado: ${lines} linhas, ${text2.length} chars \u2014 continue colando, /fim para salvar, /desfazer para remover o ultimo, /cancelar para abortar${C5.reset}
|
|
70579
71494
|
`
|
|
70580
71495
|
);
|
|
70581
71496
|
};
|
|
@@ -70584,11 +71499,9 @@ ${ui2.C.dim}use: /skillcreator | /skills | /skill delete <nome>${ui2.C.reset}
|
|
|
70584
71499
|
if (!sc) return;
|
|
70585
71500
|
if (input === "/cancelar" || input === "/cancel") {
|
|
70586
71501
|
skillCreator = null;
|
|
70587
|
-
process.stdout.write(
|
|
70588
|
-
|
|
70589
|
-
|
|
70590
|
-
`
|
|
70591
|
-
);
|
|
71502
|
+
process.stdout.write(`
|
|
71503
|
+
${C5.dim}criacao de skill cancelada${C5.reset}
|
|
71504
|
+
`);
|
|
70592
71505
|
return;
|
|
70593
71506
|
}
|
|
70594
71507
|
switch (sc.phase) {
|
|
@@ -70596,7 +71509,7 @@ ${ui2.C.dim}criacao de skill cancelada${ui2.C.reset}
|
|
|
70596
71509
|
const slug = slugify(input);
|
|
70597
71510
|
if (!slug) {
|
|
70598
71511
|
process.stdout.write(
|
|
70599
|
-
`${
|
|
71512
|
+
`${C5.yellow}nome invalido \u2014 tente de novo${C5.reset}
|
|
70600
71513
|
`
|
|
70601
71514
|
);
|
|
70602
71515
|
return;
|
|
@@ -70604,22 +71517,20 @@ ${ui2.C.dim}criacao de skill cancelada${ui2.C.reset}
|
|
|
70604
71517
|
sc.name = slug;
|
|
70605
71518
|
if (listSkills().some((s) => s.name === slug)) {
|
|
70606
71519
|
process.stdout.write(
|
|
70607
|
-
`${
|
|
71520
|
+
`${C5.yellow}ja existe uma skill '${slug}' \u2014 sera sobrescrita${C5.reset}
|
|
70608
71521
|
`
|
|
70609
71522
|
);
|
|
70610
71523
|
}
|
|
70611
71524
|
sc.phase = "desc";
|
|
70612
|
-
process.stdout.write(
|
|
70613
|
-
|
|
70614
|
-
`
|
|
70615
|
-
);
|
|
71525
|
+
process.stdout.write(`${C5.cyan}descricao curta (1 linha)?${C5.reset}
|
|
71526
|
+
`);
|
|
70616
71527
|
return;
|
|
70617
71528
|
}
|
|
70618
71529
|
case "desc": {
|
|
70619
71530
|
sc.description = input;
|
|
70620
71531
|
sc.phase = "triggers";
|
|
70621
71532
|
process.stdout.write(
|
|
70622
|
-
`${
|
|
71533
|
+
`${C5.cyan}palavras-gatilho?${C5.reset} ${C5.dim}(separadas por virgula; Enter usa o proprio nome)${C5.reset}
|
|
70623
71534
|
`
|
|
70624
71535
|
);
|
|
70625
71536
|
return;
|
|
@@ -70631,7 +71542,7 @@ ${ui2.C.dim}criacao de skill cancelada${ui2.C.reset}
|
|
|
70631
71542
|
sc.phase = "body";
|
|
70632
71543
|
sc.bodyLines.push(line.replace(/\r$/, ""));
|
|
70633
71544
|
process.stdout.write(
|
|
70634
|
-
`${
|
|
71545
|
+
`${C5.yellow}isso parece a skill, nao gatilhos \u2014 capturei como conteudo.${C5.reset}
|
|
70635
71546
|
`
|
|
70636
71547
|
);
|
|
70637
71548
|
printBodyTally(sc);
|
|
@@ -70640,7 +71551,7 @@ ${ui2.C.dim}criacao de skill cancelada${ui2.C.reset}
|
|
|
70640
71551
|
sc.triggers = input ? input.split(",").map((t) => t.trim()).filter(Boolean) : [];
|
|
70641
71552
|
sc.phase = "body";
|
|
70642
71553
|
process.stdout.write(
|
|
70643
|
-
`${
|
|
71554
|
+
`${C5.cyan}cole ou escreva a skill agora${C5.reset} ${C5.dim}(qualquer tamanho). termine com uma linha contendo so /fim${C5.reset}
|
|
70644
71555
|
`
|
|
70645
71556
|
);
|
|
70646
71557
|
return;
|
|
@@ -70650,7 +71561,7 @@ ${ui2.C.dim}criacao de skill cancelada${ui2.C.reset}
|
|
|
70650
71561
|
const body = sc.bodyLines.join("\n").trim();
|
|
70651
71562
|
if (!body) {
|
|
70652
71563
|
process.stdout.write(
|
|
70653
|
-
`${
|
|
71564
|
+
`${C5.yellow}corpo vazio \u2014 cole algum conteudo ou /cancelar${C5.reset}
|
|
70654
71565
|
`
|
|
70655
71566
|
);
|
|
70656
71567
|
return;
|
|
@@ -70665,22 +71576,20 @@ ${ui2.C.dim}criacao de skill cancelada${ui2.C.reset}
|
|
|
70665
71576
|
await agent.refreshSkills();
|
|
70666
71577
|
process.stdout.write(
|
|
70667
71578
|
`
|
|
70668
|
-
${
|
|
70669
|
-
${
|
|
71579
|
+
${C5.green}\u2713 skill '${res.skill.name}' ${res.overwritten ? "atualizada" : "criada"}${C5.reset} ${C5.dim}(${res.file})${C5.reset}
|
|
71580
|
+
${C5.dim}ja disponivel para todos os modelos nesta sessao.${C5.reset}
|
|
70670
71581
|
`
|
|
70671
71582
|
);
|
|
70672
71583
|
return;
|
|
70673
71584
|
}
|
|
70674
71585
|
if (input === "/desfazer" || input === "/undo") {
|
|
70675
71586
|
if (sc.bodyLines.length === 0) {
|
|
70676
|
-
process.stdout.write(
|
|
70677
|
-
|
|
70678
|
-
`
|
|
70679
|
-
);
|
|
71587
|
+
process.stdout.write(`${C5.dim}nada para desfazer${C5.reset}
|
|
71588
|
+
`);
|
|
70680
71589
|
} else {
|
|
70681
71590
|
sc.bodyLines.pop();
|
|
70682
71591
|
process.stdout.write(
|
|
70683
|
-
`${
|
|
71592
|
+
`${C5.yellow}ultimo trecho removido.${C5.reset}
|
|
70684
71593
|
`
|
|
70685
71594
|
);
|
|
70686
71595
|
printBodyTally(sc);
|
|
@@ -70693,206 +71602,252 @@ ${ui2.C.dim}ja disponivel para todos os modelos nesta sessao.${ui2.C.reset}
|
|
|
70693
71602
|
}
|
|
70694
71603
|
}
|
|
70695
71604
|
};
|
|
71605
|
+
const printModelResult = (result) => {
|
|
71606
|
+
process.stdout.write(
|
|
71607
|
+
`${result.ok ? `${C5.green}\u2713` : `${C5.red}\u2717`} ${result.message}${C5.reset}
|
|
71608
|
+
`
|
|
71609
|
+
);
|
|
71610
|
+
};
|
|
71611
|
+
const openModelSelector = async () => {
|
|
71612
|
+
const state = agent.getModelSelection();
|
|
71613
|
+
const items = [
|
|
71614
|
+
{
|
|
71615
|
+
label: "Auto \u2014 cadeia de fallback autom\xE1tica",
|
|
71616
|
+
hint: "tenta os modelos em ordem"
|
|
71617
|
+
},
|
|
71618
|
+
...state.chain.map((c) => ({ label: c.label, hint: c.key }))
|
|
71619
|
+
];
|
|
71620
|
+
const activeIdx = state.mode === "auto" ? 0 : Math.max(
|
|
71621
|
+
0,
|
|
71622
|
+
1 + state.chain.findIndex((c) => c.key === state.activeModelKey)
|
|
71623
|
+
);
|
|
71624
|
+
const choice2 = await inputUI.select("selecionar modelo", items, activeIdx);
|
|
71625
|
+
if (choice2 === null) {
|
|
71626
|
+
process.stdout.write(`${C5.dim}sele\xE7\xE3o de modelo cancelada${C5.reset}
|
|
71627
|
+
`);
|
|
71628
|
+
return;
|
|
71629
|
+
}
|
|
71630
|
+
const arg = choice2 === 0 ? "auto" : state.chain[choice2 - 1].key;
|
|
71631
|
+
try {
|
|
71632
|
+
printModelResult(await agent.setModelSelection(arg));
|
|
71633
|
+
} catch (err) {
|
|
71634
|
+
printFatal(err);
|
|
71635
|
+
}
|
|
71636
|
+
};
|
|
71637
|
+
const handleApiSwap = async (inlineKey) => {
|
|
71638
|
+
let raw = inlineKey;
|
|
71639
|
+
if (!raw) {
|
|
71640
|
+
process.stdout.write(
|
|
71641
|
+
`${C5.dim}Cole a nova chave NVIDIA (cria em ${C5.reset}${C5.cyan}https://build.nvidia.com/${C5.reset}${C5.dim}). Enter vazio ou Ctrl+C cancela.${C5.reset}
|
|
71642
|
+
`
|
|
71643
|
+
);
|
|
71644
|
+
const res = await inputUI.prompt({
|
|
71645
|
+
label: "nova NVIDIA API key",
|
|
71646
|
+
secret: true
|
|
71647
|
+
});
|
|
71648
|
+
if (res.type !== "line" || !res.value.trim()) {
|
|
71649
|
+
process.stdout.write(`${C5.dim}troca de chave cancelada${C5.reset}
|
|
71650
|
+
`);
|
|
71651
|
+
return;
|
|
71652
|
+
}
|
|
71653
|
+
raw = res.value;
|
|
71654
|
+
}
|
|
71655
|
+
const key = raw.replace(/\s+/g, "").match(/nvapi-[A-Za-z0-9_-]+/)?.[0] ?? "";
|
|
71656
|
+
if (!key) {
|
|
71657
|
+
process.stdout.write(
|
|
71658
|
+
`${C5.red}\u2717 n\xE3o encontrei uma chave NVIDIA no que foi colado${C5.reset} ${C5.dim}(esperado um token "nvapi-\u2026"; cole a chave completa).${C5.reset}
|
|
71659
|
+
`
|
|
71660
|
+
);
|
|
71661
|
+
return;
|
|
71662
|
+
}
|
|
71663
|
+
process.stdout.write(`${C5.dim}testando a chave na NVIDIA\u2026${C5.reset}
|
|
71664
|
+
`);
|
|
71665
|
+
const test = await testNvidiaKey(key);
|
|
71666
|
+
if (!test.ok) {
|
|
71667
|
+
if (test.status === 401 || test.status === 403) {
|
|
71668
|
+
process.stdout.write(
|
|
71669
|
+
`${C5.red}\u2717 a NVIDIA recusou a chave (${test.status}): ${test.detail}${C5.reset}
|
|
71670
|
+
${C5.dim}chave N\xC3O salva \u2014 confira se copiou inteira e se a conta tem acesso de infer\xEAncia.${C5.reset}
|
|
71671
|
+
`
|
|
71672
|
+
);
|
|
71673
|
+
return;
|
|
71674
|
+
}
|
|
71675
|
+
process.stdout.write(
|
|
71676
|
+
`${C5.yellow}\u26A0 n\xE3o consegui validar (${test.status || "rede"}): ${test.detail}${C5.reset}
|
|
71677
|
+
${C5.dim}salvando mesmo assim \u2014 o pr\xF3ximo pedido vai usar a chave nova.${C5.reset}
|
|
71678
|
+
`
|
|
71679
|
+
);
|
|
71680
|
+
}
|
|
71681
|
+
const file2 = swapNvidiaKey(key);
|
|
71682
|
+
const masked = `${key.slice(0, 9)}\u2026${key.slice(-4)} (${key.length} chars)`;
|
|
71683
|
+
process.stdout.write(
|
|
71684
|
+
`${C5.green}\u2713 chave NVIDIA trocada e ativa${C5.reset} ${C5.dim}${masked}${C5.reset}
|
|
71685
|
+
${C5.dim}salva em ${C5.reset}${C5.cyan}${file2}${C5.reset}
|
|
71686
|
+
`
|
|
71687
|
+
);
|
|
71688
|
+
};
|
|
70696
71689
|
const handleLine = async (line) => {
|
|
70697
71690
|
if (closing) return;
|
|
70698
71691
|
const input = line.trim();
|
|
70699
71692
|
if (skillCreator) {
|
|
70700
71693
|
await handleSkillCreatorLine(line, input);
|
|
70701
|
-
if (!closing) prompt();
|
|
70702
71694
|
return;
|
|
70703
71695
|
}
|
|
70704
71696
|
if (input === "/exit" || input === "/quit") {
|
|
70705
71697
|
closing = true;
|
|
70706
|
-
rl.close();
|
|
70707
71698
|
return;
|
|
70708
71699
|
}
|
|
70709
71700
|
if (input === "/skillcreator" || input === "/skill" || input === "/skills") {
|
|
70710
71701
|
handleSkillCommand(input);
|
|
70711
|
-
if (!closing) prompt();
|
|
70712
71702
|
return;
|
|
70713
71703
|
}
|
|
70714
71704
|
if (input.startsWith("/skill ") || input.startsWith("/skills ")) {
|
|
70715
71705
|
await handleSkillSubcommand(input);
|
|
70716
|
-
if (!closing) prompt();
|
|
70717
71706
|
return;
|
|
70718
71707
|
}
|
|
70719
|
-
if (
|
|
70720
|
-
|
|
70721
|
-
|
|
70722
|
-
|
|
70723
|
-
|
|
70724
|
-
${ui2.C.dim}selecao de modelo cancelada${ui2.C.reset}
|
|
70725
|
-
`
|
|
70726
|
-
);
|
|
70727
|
-
if (!closing) prompt();
|
|
70728
|
-
return;
|
|
70729
|
-
}
|
|
71708
|
+
if (input === "/model" || input === "/models") {
|
|
71709
|
+
await openModelSelector();
|
|
71710
|
+
return;
|
|
71711
|
+
}
|
|
71712
|
+
if (input.startsWith("/model ") || input.startsWith("/models ")) {
|
|
70730
71713
|
const arg = input.replace(/^\/models?\s*/, "");
|
|
70731
71714
|
try {
|
|
70732
|
-
|
|
70733
|
-
process.stdout.write(formatModelSelection(result));
|
|
70734
|
-
awaitingModelSelection = !result.ok;
|
|
71715
|
+
printModelResult(await agent.setModelSelection(arg));
|
|
70735
71716
|
} catch (err) {
|
|
70736
|
-
|
|
70737
|
-
`
|
|
70738
|
-
[fatal] ${err instanceof Error ? err.stack || err.message : String(err)}
|
|
70739
|
-
`
|
|
70740
|
-
);
|
|
70741
|
-
awaitingModelSelection = false;
|
|
71717
|
+
printFatal(err);
|
|
70742
71718
|
}
|
|
70743
|
-
if (!closing) prompt();
|
|
70744
71719
|
return;
|
|
70745
71720
|
}
|
|
70746
|
-
if (
|
|
70747
|
-
|
|
70748
|
-
|
|
70749
|
-
|
|
70750
|
-
|
|
70751
|
-
|
|
71721
|
+
if (input === "/system") {
|
|
71722
|
+
const sysText = agent.getSystemPrompt();
|
|
71723
|
+
const audit = agent.getSystemPromptAudit();
|
|
71724
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").replace("T", "_").slice(0, 19);
|
|
71725
|
+
const filePath = import_node_path9.default.join(
|
|
71726
|
+
desktopDir(),
|
|
71727
|
+
`clawfast-system-prompt_${stamp}.html`
|
|
71728
|
+
);
|
|
71729
|
+
const meta3 = `clawfast v${clawfastVersion()} \u2014 system prompt \xB7 gerado em ${(/* @__PURE__ */ new Date()).toLocaleString()} \xB7 ${audit.chars.toLocaleString()} chars \xB7 fonte ${audit.source} \xB7 verificado ${audit.requiredMarkersVerified ? "sim" : "nao"}`;
|
|
71730
|
+
const b64 = Buffer.from(sysText, "utf8").toString("base64");
|
|
71731
|
+
const html = `<!doctype html><html lang="pt-br"><head><meta charset="utf-8"><title>clawfast \u2014 system prompt</title><style>body{background:#0b0f0b;color:#bfffbf;font:14px/1.55 ui-monospace,Consolas,Menlo,monospace;margin:0;padding:28px}h1{color:#7CFC00;font-size:18px;margin:0 0 6px}.meta{color:#6f9a6f;margin:0 0 18px;font-size:12px}pre{white-space:pre-wrap;word-wrap:break-word;margin:0}</style></head><body><h1>clawfast \u2014 system prompt</h1><div class="meta">${meta3}</div><pre id="c"></pre><script>document.getElementById("c").textContent=decodeURIComponent(escape(atob("${b64}")));</script></body></html>`;
|
|
70752
71732
|
try {
|
|
70753
|
-
|
|
70754
|
-
awaitingModelSelection = !arg && result.ok;
|
|
71733
|
+
await (0, import_promises2.writeFile)(filePath, html, "utf8");
|
|
70755
71734
|
process.stdout.write(
|
|
70756
|
-
|
|
71735
|
+
`${C5.green}\u2713 system prompt salvo${C5.reset} ${C5.dim}(${sysText.length.toLocaleString()} caracteres \u2014 abra no navegador)${C5.reset}
|
|
71736
|
+
${C5.cyan}${filePath}${C5.reset}
|
|
71737
|
+
`
|
|
70757
71738
|
);
|
|
70758
71739
|
} catch (err) {
|
|
70759
|
-
process.
|
|
70760
|
-
|
|
70761
|
-
[fatal] ${err instanceof Error ? err.stack || err.message : String(err)}
|
|
71740
|
+
process.stdout.write(
|
|
71741
|
+
`${C5.red}\u2717 n\xE3o consegui salvar o arquivo:${C5.reset} ${err instanceof Error ? err.message : String(err)}
|
|
70762
71742
|
`
|
|
70763
71743
|
);
|
|
70764
|
-
awaitingModelSelection = false;
|
|
70765
71744
|
}
|
|
70766
|
-
if (!closing) prompt();
|
|
70767
71745
|
return;
|
|
70768
71746
|
}
|
|
70769
|
-
if (input === "/
|
|
70770
|
-
|
|
70771
|
-
const audit = agent.getSystemPromptAudit();
|
|
70772
|
-
process.stdout.write(
|
|
70773
|
-
`\x1B[90m\u2500\u2500\u2500\u2500 system prompt (${sys2.length.toLocaleString()} caracteres) \u2500\u2500\u2500\u2500\x1B[0m
|
|
70774
|
-
`
|
|
70775
|
-
);
|
|
70776
|
-
process.stdout.write(
|
|
70777
|
-
`\x1B[90mfonte: ${audit.source} | verificado: ${audit.requiredMarkersVerified ? "sim" : "nao"} | chars: ${audit.chars.toLocaleString()}${audit.dumpPath ? ` | dump: ${audit.dumpPath}` : ""}\x1B[0m
|
|
70778
|
-
`
|
|
70779
|
-
);
|
|
70780
|
-
process.stdout.write(sys2 + "\n");
|
|
70781
|
-
process.stdout.write(`\x1B[90m\u2500\u2500\u2500\u2500 fim do system prompt \u2500\u2500\u2500\u2500\x1B[0m
|
|
70782
|
-
`);
|
|
70783
|
-
if (!closing) prompt();
|
|
71747
|
+
if (input === "/api" || input.startsWith("/api ")) {
|
|
71748
|
+
await handleApiSwap(input.replace(/^\/api\s*/, "").trim());
|
|
70784
71749
|
return;
|
|
70785
71750
|
}
|
|
70786
71751
|
if (input === "/nov" || input === "/novidades") {
|
|
70787
71752
|
process.stdout.write(`
|
|
70788
|
-
${
|
|
71753
|
+
${renderNews(clawfastVersion())}
|
|
71754
|
+
|
|
70789
71755
|
`);
|
|
70790
|
-
if (!closing) prompt();
|
|
70791
71756
|
return;
|
|
70792
71757
|
}
|
|
71758
|
+
if (!input) return;
|
|
70793
71759
|
process.stdout.write("\n" + agentHeader2());
|
|
70794
71760
|
activeAbort = new AbortController();
|
|
70795
71761
|
turnActive = true;
|
|
70796
|
-
|
|
71762
|
+
inputUI.beginTurn(
|
|
71763
|
+
(l) => {
|
|
71764
|
+
if (agent.isRunningCommand()) agent.sendStdin(l);
|
|
71765
|
+
},
|
|
71766
|
+
() => {
|
|
71767
|
+
if (exitArmed) {
|
|
71768
|
+
closing = true;
|
|
71769
|
+
activeAbort?.abort();
|
|
71770
|
+
return;
|
|
71771
|
+
}
|
|
71772
|
+
if (activeAbort && !activeAbort.signal.aborted) {
|
|
71773
|
+
activeAbort.abort();
|
|
71774
|
+
process.stdout.write(
|
|
71775
|
+
`
|
|
71776
|
+
${C5.dim}interrompido \u2014 Ctrl+C de novo para fechar${C5.reset}
|
|
71777
|
+
`
|
|
71778
|
+
);
|
|
71779
|
+
}
|
|
71780
|
+
armExit();
|
|
71781
|
+
}
|
|
71782
|
+
);
|
|
70797
71783
|
try {
|
|
70798
71784
|
await agent.send(input, activeAbort.signal);
|
|
70799
71785
|
} catch (err) {
|
|
70800
|
-
|
|
70801
|
-
`
|
|
70802
|
-
[fatal] ${err instanceof Error ? err.stack || err.message : String(err)}
|
|
70803
|
-
`
|
|
70804
|
-
);
|
|
71786
|
+
printFatal(err);
|
|
70805
71787
|
} finally {
|
|
71788
|
+
inputUI.endTurn();
|
|
70806
71789
|
activeAbort = null;
|
|
70807
71790
|
turnActive = false;
|
|
70808
71791
|
}
|
|
70809
|
-
if (!closing) prompt();
|
|
70810
71792
|
};
|
|
70811
|
-
|
|
70812
|
-
|
|
70813
|
-
const line = pasteInput.expand(rawLine);
|
|
71793
|
+
process.removeAllListeners("SIGINT");
|
|
71794
|
+
process.on("SIGINT", () => {
|
|
70814
71795
|
if (turnActive) {
|
|
70815
|
-
|
|
70816
|
-
agent.sendStdin(line);
|
|
70817
|
-
}
|
|
71796
|
+
activeAbort?.abort();
|
|
70818
71797
|
return;
|
|
70819
71798
|
}
|
|
70820
|
-
|
|
70821
|
-
commandQueue = commandQueue.then(() => handleLine(line)).catch((err) => {
|
|
70822
|
-
process.stderr.write(
|
|
70823
|
-
`
|
|
70824
|
-
[fatal] ${err instanceof Error ? err.stack || err.message : String(err)}
|
|
70825
|
-
`
|
|
70826
|
-
);
|
|
70827
|
-
}).finally(() => {
|
|
70828
|
-
if (!closing) rl.resume();
|
|
70829
|
-
});
|
|
70830
|
-
});
|
|
70831
|
-
rl.on("close", async () => {
|
|
70832
|
-
closing = true;
|
|
70833
|
-
pasteInput.dispose();
|
|
70834
|
-
await commandQueue.catch(() => void 0);
|
|
70835
|
-
process.stdout.write("\nClosing sandbox...\n");
|
|
70836
|
-
await agent.close();
|
|
70837
|
-
process.exit(0);
|
|
71799
|
+
void shutdown();
|
|
70838
71800
|
});
|
|
70839
71801
|
process.on("exit", () => pasteInput.dispose());
|
|
70840
|
-
|
|
70841
|
-
|
|
70842
|
-
|
|
70843
|
-
|
|
70844
|
-
|
|
70845
|
-
|
|
70846
|
-
|
|
70847
|
-
|
|
70848
|
-
|
|
70849
|
-
|
|
70850
|
-
|
|
70851
|
-
reset: "\x1B[0m",
|
|
70852
|
-
bold: "\x1B[1m",
|
|
70853
|
-
dim: "\x1B[90m",
|
|
70854
|
-
green: "\x1B[32m",
|
|
70855
|
-
cyan: "\x1B[36m",
|
|
70856
|
-
yellow: "\x1B[33m",
|
|
70857
|
-
red: "\x1B[31m"
|
|
71802
|
+
const currentSkillLabel = () => {
|
|
71803
|
+
if (!skillCreator) return void 0;
|
|
71804
|
+
switch (skillCreator.phase) {
|
|
71805
|
+
case "name":
|
|
71806
|
+
return "nome";
|
|
71807
|
+
case "desc":
|
|
71808
|
+
return "descri\xE7\xE3o";
|
|
71809
|
+
case "triggers":
|
|
71810
|
+
return "gatilhos";
|
|
71811
|
+
default:
|
|
71812
|
+
return "skill";
|
|
70858
71813
|
}
|
|
70859
71814
|
};
|
|
70860
|
-
|
|
70861
|
-
|
|
70862
|
-
|
|
70863
|
-
|
|
70864
|
-
""
|
|
70865
|
-
|
|
70866
|
-
|
|
70867
|
-
|
|
70868
|
-
|
|
70869
|
-
|
|
70870
|
-
|
|
70871
|
-
|
|
70872
|
-
);
|
|
70873
|
-
}
|
|
70874
|
-
if (result.selection.unavailable.length > 0) {
|
|
70875
|
-
lines.push("", `${C4.yellow}${C4.bold}Indisponiveis${C4.reset}`);
|
|
70876
|
-
for (const group of result.selection.unavailable) {
|
|
70877
|
-
lines.push(`${group.provider}: ${C4.dim}${group.reason}${C4.reset}`);
|
|
70878
|
-
for (const model of group.models) {
|
|
70879
|
-
lines.push(` - ${model.label} ${C4.dim}(${model.key})${C4.reset}`);
|
|
71815
|
+
while (!closing) {
|
|
71816
|
+
const skillLabel = currentSkillLabel();
|
|
71817
|
+
const res = await inputUI.prompt(skillLabel ? { label: skillLabel } : {});
|
|
71818
|
+
if (closing) break;
|
|
71819
|
+
if (res.type === "eof") {
|
|
71820
|
+
closing = true;
|
|
71821
|
+
break;
|
|
71822
|
+
}
|
|
71823
|
+
if (res.type === "sigint") {
|
|
71824
|
+
if (exitArmed) {
|
|
71825
|
+
closing = true;
|
|
71826
|
+
break;
|
|
70880
71827
|
}
|
|
71828
|
+
process.stdout.write(`${C5.dim}Ctrl+C de novo para fechar${C5.reset}
|
|
71829
|
+
`);
|
|
71830
|
+
armExit();
|
|
71831
|
+
continue;
|
|
71832
|
+
}
|
|
71833
|
+
if (!skillCreator && !res.value.trim()) continue;
|
|
71834
|
+
exitArmed = false;
|
|
71835
|
+
try {
|
|
71836
|
+
await handleLine(res.value);
|
|
71837
|
+
} catch (err) {
|
|
71838
|
+
printFatal(err);
|
|
70881
71839
|
}
|
|
70882
71840
|
}
|
|
70883
|
-
|
|
70884
|
-
"",
|
|
70885
|
-
options.choosing ? `${C4.dim}Digite o numero, nome do modelo, auto para fallback, ou cancelar.${C4.reset}` : `${C4.dim}Use /model <numero> para fixar, /model auto para voltar ao fallback automatico.${C4.reset}`
|
|
70886
|
-
);
|
|
70887
|
-
return `
|
|
70888
|
-
${lines.join("\n")}
|
|
70889
|
-
`;
|
|
71841
|
+
await shutdown();
|
|
70890
71842
|
}
|
|
70891
|
-
var
|
|
71843
|
+
var import_node_os6, import_node_path9, import_node_fs8, import_promises2, deepseekEnabled, configuredModelProviders;
|
|
70892
71844
|
var init_index = __esm({
|
|
70893
71845
|
"index.ts"() {
|
|
70894
71846
|
"use strict";
|
|
70895
|
-
|
|
71847
|
+
import_node_os6 = __toESM(require("node:os"));
|
|
71848
|
+
import_node_path9 = __toESM(require("node:path"));
|
|
71849
|
+
import_node_fs8 = require("node:fs");
|
|
71850
|
+
import_promises2 = require("node:fs/promises");
|
|
70896
71851
|
init_paste_input();
|
|
70897
71852
|
init_boot_ui();
|
|
70898
71853
|
init_config();
|