clawfast 1.0.2 → 2.0.0
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 +2 -2
- package/dist/clawfast.cjs +1562 -541
- package/package.json +1 -1
package/dist/clawfast.cjs
CHANGED
|
@@ -85,9 +85,9 @@ var init_boot_ui = __esm({
|
|
|
85
85
|
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
|
-
var
|
|
89
|
-
var
|
|
90
|
-
var
|
|
88
|
+
var fs6 = require("fs");
|
|
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]",
|
|
@@ -217,7 +217,7 @@ var require_main = __commonJS({
|
|
|
217
217
|
if (options && options.path && options.path.length > 0) {
|
|
218
218
|
if (Array.isArray(options.path)) {
|
|
219
219
|
for (const filepath of options.path) {
|
|
220
|
-
if (
|
|
220
|
+
if (fs6.existsSync(filepath)) {
|
|
221
221
|
possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
|
|
222
222
|
}
|
|
223
223
|
}
|
|
@@ -225,15 +225,15 @@ 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
|
-
if (
|
|
230
|
+
if (fs6.existsSync(possibleVaultPath)) {
|
|
231
231
|
return possibleVaultPath;
|
|
232
232
|
}
|
|
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(
|
|
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) {
|
|
@@ -497,6 +497,101 @@ var init_config = __esm({
|
|
|
497
497
|
}
|
|
498
498
|
});
|
|
499
499
|
|
|
500
|
+
// src/version.ts
|
|
501
|
+
var clawfastVersion, isDevVersion, isNewerVersion;
|
|
502
|
+
var init_version = __esm({
|
|
503
|
+
"src/version.ts"() {
|
|
504
|
+
"use strict";
|
|
505
|
+
clawfastVersion = () => true ? "2.0.0" : "0.0.0-dev";
|
|
506
|
+
isDevVersion = () => clawfastVersion().includes("-dev");
|
|
507
|
+
isNewerVersion = (a, b) => {
|
|
508
|
+
const parse3 = (v) => v.split("-")[0].split(".").map((n) => Number.parseInt(n, 10) || 0);
|
|
509
|
+
const pa = parse3(a);
|
|
510
|
+
const pb = parse3(b);
|
|
511
|
+
const len = Math.max(pa.length, pb.length);
|
|
512
|
+
for (let i = 0; i < len; i++) {
|
|
513
|
+
const da = pa[i] ?? 0;
|
|
514
|
+
const db = pb[i] ?? 0;
|
|
515
|
+
if (da > db) return true;
|
|
516
|
+
if (da < db) return false;
|
|
517
|
+
}
|
|
518
|
+
return false;
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
// src/update.ts
|
|
524
|
+
var import_node_fs2, import_node_path2, import_node_child_process, CHECK_INTERVAL_MS, REGISTRY_URL, cacheFile, readCache, writeCache, getUpdateNotice, refreshUpdateCacheInBackground, runSelfUpdate;
|
|
525
|
+
var init_update = __esm({
|
|
526
|
+
"src/update.ts"() {
|
|
527
|
+
"use strict";
|
|
528
|
+
import_node_fs2 = __toESM(require("node:fs"));
|
|
529
|
+
import_node_path2 = __toESM(require("node:path"));
|
|
530
|
+
import_node_child_process = require("node:child_process");
|
|
531
|
+
init_config();
|
|
532
|
+
init_version();
|
|
533
|
+
CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
534
|
+
REGISTRY_URL = "https://registry.npmjs.org/clawfast/latest";
|
|
535
|
+
cacheFile = () => import_node_path2.default.join(clawfastHome(), "update-check.json");
|
|
536
|
+
readCache = () => {
|
|
537
|
+
try {
|
|
538
|
+
const raw = import_node_fs2.default.readFileSync(cacheFile(), "utf8");
|
|
539
|
+
const parsed = JSON.parse(raw);
|
|
540
|
+
if (typeof parsed?.latest === "string" && typeof parsed?.lastCheck === "number") {
|
|
541
|
+
return parsed;
|
|
542
|
+
}
|
|
543
|
+
} catch {
|
|
544
|
+
}
|
|
545
|
+
return null;
|
|
546
|
+
};
|
|
547
|
+
writeCache = (cache) => {
|
|
548
|
+
try {
|
|
549
|
+
import_node_fs2.default.mkdirSync(clawfastHome(), { recursive: true });
|
|
550
|
+
import_node_fs2.default.writeFileSync(cacheFile(), JSON.stringify(cache), "utf8");
|
|
551
|
+
} catch {
|
|
552
|
+
}
|
|
553
|
+
};
|
|
554
|
+
getUpdateNotice = (current) => {
|
|
555
|
+
if (isDevVersion()) return null;
|
|
556
|
+
const cache = readCache();
|
|
557
|
+
if (cache && isNewerVersion(cache.latest, current)) {
|
|
558
|
+
return `nova versao ${cache.latest} disponivel (voce tem ${current}) \u2014 rode: clawfast update`;
|
|
559
|
+
}
|
|
560
|
+
return null;
|
|
561
|
+
};
|
|
562
|
+
refreshUpdateCacheInBackground = (current) => {
|
|
563
|
+
if (isDevVersion()) return;
|
|
564
|
+
const cache = readCache();
|
|
565
|
+
if (cache && Date.now() - cache.lastCheck < CHECK_INTERVAL_MS) return;
|
|
566
|
+
void (async () => {
|
|
567
|
+
try {
|
|
568
|
+
const controller = new AbortController();
|
|
569
|
+
const timer2 = setTimeout(() => controller.abort(), 3e3);
|
|
570
|
+
const res = await fetch(REGISTRY_URL, {
|
|
571
|
+
signal: controller.signal,
|
|
572
|
+
headers: { accept: "application/json" }
|
|
573
|
+
});
|
|
574
|
+
clearTimeout(timer2);
|
|
575
|
+
if (!res.ok) return;
|
|
576
|
+
const body = await res.json();
|
|
577
|
+
if (typeof body.version === "string") {
|
|
578
|
+
writeCache({ lastCheck: Date.now(), latest: body.version });
|
|
579
|
+
}
|
|
580
|
+
} catch {
|
|
581
|
+
}
|
|
582
|
+
})();
|
|
583
|
+
};
|
|
584
|
+
runSelfUpdate = () => new Promise((resolve2) => {
|
|
585
|
+
const child = (0, import_node_child_process.spawn)("npm install -g clawfast@latest", {
|
|
586
|
+
stdio: "inherit",
|
|
587
|
+
shell: true
|
|
588
|
+
});
|
|
589
|
+
child.on("close", (code) => resolve2(code ?? 1));
|
|
590
|
+
child.on("error", () => resolve2(1));
|
|
591
|
+
});
|
|
592
|
+
}
|
|
593
|
+
});
|
|
594
|
+
|
|
500
595
|
// src/paste-input.ts
|
|
501
596
|
function createPasteInput(opts = {}) {
|
|
502
597
|
const input = new import_node_stream.PassThrough();
|
|
@@ -604,14 +699,14 @@ var init_paste_input = __esm({
|
|
|
604
699
|
/** Replace any paste chips in a submitted line with their real content. */
|
|
605
700
|
expand(line) {
|
|
606
701
|
if (this.pastes.size === 0) return line;
|
|
607
|
-
let
|
|
702
|
+
let out3 = line;
|
|
608
703
|
for (const [chip, content] of this.pastes) {
|
|
609
|
-
if (
|
|
610
|
-
|
|
704
|
+
if (out3.includes(chip)) {
|
|
705
|
+
out3 = out3.split(chip).join(content);
|
|
611
706
|
this.pastes.delete(chip);
|
|
612
707
|
}
|
|
613
708
|
}
|
|
614
|
-
return
|
|
709
|
+
return out3;
|
|
615
710
|
}
|
|
616
711
|
/** How many captured pastes are still waiting to be expanded. */
|
|
617
712
|
pendingCount() {
|
|
@@ -634,16 +729,16 @@ function listSkills() {
|
|
|
634
729
|
const dir = skillsDir();
|
|
635
730
|
let entries = [];
|
|
636
731
|
try {
|
|
637
|
-
entries =
|
|
732
|
+
entries = import_node_fs3.default.readdirSync(dir).filter((f) => f.endsWith(".md"));
|
|
638
733
|
} catch {
|
|
639
734
|
return [];
|
|
640
735
|
}
|
|
641
736
|
const skills = [];
|
|
642
737
|
for (const entry of entries.sort()) {
|
|
643
|
-
const file2 =
|
|
738
|
+
const file2 = import_node_path3.default.join(dir, entry);
|
|
644
739
|
let raw = "";
|
|
645
740
|
try {
|
|
646
|
-
raw =
|
|
741
|
+
raw = import_node_fs3.default.readFileSync(file2, "utf8");
|
|
647
742
|
} catch {
|
|
648
743
|
continue;
|
|
649
744
|
}
|
|
@@ -668,9 +763,9 @@ function saveSkill(input) {
|
|
|
668
763
|
throw new Error("nome de skill invalido (vazio apos normalizacao)");
|
|
669
764
|
}
|
|
670
765
|
const dir = skillsDir();
|
|
671
|
-
|
|
672
|
-
const file2 =
|
|
673
|
-
const overwritten =
|
|
766
|
+
import_node_fs3.default.mkdirSync(dir, { recursive: true });
|
|
767
|
+
const file2 = import_node_path3.default.join(dir, `${slug}.md`);
|
|
768
|
+
const overwritten = import_node_fs3.default.existsSync(file2);
|
|
674
769
|
const triggers = (input.triggers ?? []).map((t) => t.trim().toLowerCase()).filter(Boolean);
|
|
675
770
|
const frontmatter = [
|
|
676
771
|
"---",
|
|
@@ -681,7 +776,7 @@ function saveSkill(input) {
|
|
|
681
776
|
"---",
|
|
682
777
|
""
|
|
683
778
|
].join("\n");
|
|
684
|
-
|
|
779
|
+
import_node_fs3.default.writeFileSync(file2, frontmatter + input.body.trim() + "\n", {
|
|
685
780
|
encoding: "utf8"
|
|
686
781
|
});
|
|
687
782
|
return {
|
|
@@ -699,9 +794,9 @@ function saveSkill(input) {
|
|
|
699
794
|
}
|
|
700
795
|
function deleteSkill(name25) {
|
|
701
796
|
const slug = slugify(name25);
|
|
702
|
-
const file2 =
|
|
797
|
+
const file2 = import_node_path3.default.join(skillsDir(), `${slug}.md`);
|
|
703
798
|
try {
|
|
704
|
-
|
|
799
|
+
import_node_fs3.default.unlinkSync(file2);
|
|
705
800
|
return true;
|
|
706
801
|
} catch {
|
|
707
802
|
return false;
|
|
@@ -745,14 +840,14 @@ As skills a seguir foram carregadas porque o pedido atual casou com elas (ou est
|
|
|
745
840
|
${blocks}
|
|
746
841
|
</active_skills>`;
|
|
747
842
|
}
|
|
748
|
-
var
|
|
843
|
+
var import_node_fs3, import_node_path3, skillsDir, slugify, FRONTMATTER_RE, parseFrontmatter, parseTriggers, isTrue, escapeFrontmatterValue;
|
|
749
844
|
var init_skills = __esm({
|
|
750
845
|
"src/skills.ts"() {
|
|
751
846
|
"use strict";
|
|
752
|
-
|
|
753
|
-
|
|
847
|
+
import_node_fs3 = __toESM(require("node:fs"));
|
|
848
|
+
import_node_path3 = __toESM(require("node:path"));
|
|
754
849
|
init_config();
|
|
755
|
-
skillsDir = () =>
|
|
850
|
+
skillsDir = () => import_node_path3.default.join(clawfastHome(), "skills");
|
|
756
851
|
slugify = (name25) => name25.trim().toLowerCase().normalize("NFD").replace(/[̀-ͯ]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64);
|
|
757
852
|
FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
|
|
758
853
|
parseFrontmatter = (raw) => {
|
|
@@ -774,6 +869,78 @@ var init_skills = __esm({
|
|
|
774
869
|
}
|
|
775
870
|
});
|
|
776
871
|
|
|
872
|
+
// src/news.ts
|
|
873
|
+
var import_node_fs4, import_node_path4, NEWS, latestNewsVersion, renderNews, stateFile, readState, writeState, consumePostUpdateLaunch;
|
|
874
|
+
var init_news = __esm({
|
|
875
|
+
"src/news.ts"() {
|
|
876
|
+
"use strict";
|
|
877
|
+
import_node_fs4 = __toESM(require("node:fs"));
|
|
878
|
+
import_node_path4 = __toESM(require("node:path"));
|
|
879
|
+
init_config();
|
|
880
|
+
NEWS = {
|
|
881
|
+
"2.0.0": [
|
|
882
|
+
'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.',
|
|
883
|
+
"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.",
|
|
884
|
+
"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.",
|
|
885
|
+
"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.",
|
|
886
|
+
"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.",
|
|
887
|
+
"Motor Python somente-leitura semeado a cada sessao (audit/project_audit.py); modo --focus mostra a vizinhanca de import de um arquivo especifico."
|
|
888
|
+
],
|
|
889
|
+
"1.0.3": [
|
|
890
|
+
"Atualizacao: `clawfast update` atualiza o CLI e mostra as boas-vindas; aparece um aviso quando ha versao nova; /nov lista as novidades.",
|
|
891
|
+
"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.",
|
|
892
|
+
"Modelos na NVIDIA build: mistral-medium-3.5, kimi-k2.6, glm-5.1 e qwen3.5-397b \u2014 todos com function calling de verdade (as ferramentas disparam).",
|
|
893
|
+
"Resiliencia a rate limit (429): cai para os outros modelos como contingencia e espera/retenta a cadeia automaticamente."
|
|
894
|
+
]
|
|
895
|
+
};
|
|
896
|
+
latestNewsVersion = () => {
|
|
897
|
+
const keys = Object.keys(NEWS);
|
|
898
|
+
if (keys.length === 0) return null;
|
|
899
|
+
return keys.sort((a, b) => {
|
|
900
|
+
const pa = a.split(".").map(Number);
|
|
901
|
+
const pb = b.split(".").map(Number);
|
|
902
|
+
for (let i = 0; i < 3; i++) {
|
|
903
|
+
if ((pb[i] ?? 0) !== (pa[i] ?? 0)) return (pb[i] ?? 0) - (pa[i] ?? 0);
|
|
904
|
+
}
|
|
905
|
+
return 0;
|
|
906
|
+
})[0];
|
|
907
|
+
};
|
|
908
|
+
renderNews = (version3) => {
|
|
909
|
+
const key = NEWS[version3] ? version3 : latestNewsVersion();
|
|
910
|
+
if (!key || !NEWS[key]) {
|
|
911
|
+
return "Sem novidades registradas para esta versao.";
|
|
912
|
+
}
|
|
913
|
+
const lines = NEWS[key].map((item) => ` \u2022 ${item}`).join("\n");
|
|
914
|
+
return `Novidades da versao ${key}:
|
|
915
|
+
${lines}`;
|
|
916
|
+
};
|
|
917
|
+
stateFile = () => import_node_path4.default.join(clawfastHome(), "state.json");
|
|
918
|
+
readState = () => {
|
|
919
|
+
try {
|
|
920
|
+
return JSON.parse(import_node_fs4.default.readFileSync(stateFile(), "utf8"));
|
|
921
|
+
} catch {
|
|
922
|
+
return {};
|
|
923
|
+
}
|
|
924
|
+
};
|
|
925
|
+
writeState = (state) => {
|
|
926
|
+
try {
|
|
927
|
+
import_node_fs4.default.mkdirSync(clawfastHome(), { recursive: true });
|
|
928
|
+
import_node_fs4.default.writeFileSync(stateFile(), JSON.stringify(state), "utf8");
|
|
929
|
+
} catch {
|
|
930
|
+
}
|
|
931
|
+
};
|
|
932
|
+
consumePostUpdateLaunch = (current) => {
|
|
933
|
+
const state = readState();
|
|
934
|
+
const previous = state.lastVersion;
|
|
935
|
+
if (previous !== current) {
|
|
936
|
+
writeState({ ...state, lastVersion: current });
|
|
937
|
+
return Boolean(previous);
|
|
938
|
+
}
|
|
939
|
+
return false;
|
|
940
|
+
};
|
|
941
|
+
}
|
|
942
|
+
});
|
|
943
|
+
|
|
777
944
|
// ../node_modules/.pnpm/@ai-sdk+provider@3.0.10/node_modules/@ai-sdk/provider/dist/index.mjs
|
|
778
945
|
function getErrorMessage(error51) {
|
|
779
946
|
if (error51 == null) {
|
|
@@ -1346,10 +1513,10 @@ function mergeDefs(...defs) {
|
|
|
1346
1513
|
function cloneDef(schema) {
|
|
1347
1514
|
return mergeDefs(schema._zod.def);
|
|
1348
1515
|
}
|
|
1349
|
-
function getElementAtPath(obj,
|
|
1350
|
-
if (!
|
|
1516
|
+
function getElementAtPath(obj, path10) {
|
|
1517
|
+
if (!path10)
|
|
1351
1518
|
return obj;
|
|
1352
|
-
return
|
|
1519
|
+
return path10.reduce((acc, key) => acc?.[key], obj);
|
|
1353
1520
|
}
|
|
1354
1521
|
function promiseAllObject(promisesObj) {
|
|
1355
1522
|
const keys = Object.keys(promisesObj);
|
|
@@ -1677,11 +1844,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
1677
1844
|
}
|
|
1678
1845
|
return false;
|
|
1679
1846
|
}
|
|
1680
|
-
function prefixIssues(
|
|
1847
|
+
function prefixIssues(path10, issues) {
|
|
1681
1848
|
return issues.map((iss) => {
|
|
1682
1849
|
var _a25;
|
|
1683
1850
|
(_a25 = iss).path ?? (_a25.path = []);
|
|
1684
|
-
iss.path.unshift(
|
|
1851
|
+
iss.path.unshift(path10);
|
|
1685
1852
|
return iss;
|
|
1686
1853
|
});
|
|
1687
1854
|
}
|
|
@@ -1899,16 +2066,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
1899
2066
|
}
|
|
1900
2067
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
1901
2068
|
const fieldErrors = { _errors: [] };
|
|
1902
|
-
const processError = (error52,
|
|
2069
|
+
const processError = (error52, path10 = []) => {
|
|
1903
2070
|
for (const issue2 of error52.issues) {
|
|
1904
2071
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
1905
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
2072
|
+
issue2.errors.map((issues) => processError({ issues }, [...path10, ...issue2.path]));
|
|
1906
2073
|
} else if (issue2.code === "invalid_key") {
|
|
1907
|
-
processError({ issues: issue2.issues }, [...
|
|
2074
|
+
processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
|
|
1908
2075
|
} else if (issue2.code === "invalid_element") {
|
|
1909
|
-
processError({ issues: issue2.issues }, [...
|
|
2076
|
+
processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
|
|
1910
2077
|
} else {
|
|
1911
|
-
const fullpath = [...
|
|
2078
|
+
const fullpath = [...path10, ...issue2.path];
|
|
1912
2079
|
if (fullpath.length === 0) {
|
|
1913
2080
|
fieldErrors._errors.push(mapper(issue2));
|
|
1914
2081
|
} else {
|
|
@@ -1935,17 +2102,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
1935
2102
|
}
|
|
1936
2103
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
1937
2104
|
const result = { errors: [] };
|
|
1938
|
-
const processError = (error52,
|
|
2105
|
+
const processError = (error52, path10 = []) => {
|
|
1939
2106
|
var _a25, _b18;
|
|
1940
2107
|
for (const issue2 of error52.issues) {
|
|
1941
2108
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
1942
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
2109
|
+
issue2.errors.map((issues) => processError({ issues }, [...path10, ...issue2.path]));
|
|
1943
2110
|
} else if (issue2.code === "invalid_key") {
|
|
1944
|
-
processError({ issues: issue2.issues }, [...
|
|
2111
|
+
processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
|
|
1945
2112
|
} else if (issue2.code === "invalid_element") {
|
|
1946
|
-
processError({ issues: issue2.issues }, [...
|
|
2113
|
+
processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
|
|
1947
2114
|
} else {
|
|
1948
|
-
const fullpath = [...
|
|
2115
|
+
const fullpath = [...path10, ...issue2.path];
|
|
1949
2116
|
if (fullpath.length === 0) {
|
|
1950
2117
|
result.errors.push(mapper(issue2));
|
|
1951
2118
|
continue;
|
|
@@ -1977,8 +2144,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
1977
2144
|
}
|
|
1978
2145
|
function toDotPath(_path) {
|
|
1979
2146
|
const segs = [];
|
|
1980
|
-
const
|
|
1981
|
-
for (const seg of
|
|
2147
|
+
const path10 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
2148
|
+
for (const seg of path10) {
|
|
1982
2149
|
if (typeof seg === "number")
|
|
1983
2150
|
segs.push(`[${seg}]`);
|
|
1984
2151
|
else if (typeof seg === "symbol")
|
|
@@ -12290,11 +12457,11 @@ function _catch(Class2, innerType, catchValue) {
|
|
|
12290
12457
|
});
|
|
12291
12458
|
}
|
|
12292
12459
|
// @__NO_SIDE_EFFECTS__
|
|
12293
|
-
function _pipe(Class2, in_,
|
|
12460
|
+
function _pipe(Class2, in_, out3) {
|
|
12294
12461
|
return new Class2({
|
|
12295
12462
|
type: "pipe",
|
|
12296
12463
|
in: in_,
|
|
12297
|
-
out:
|
|
12464
|
+
out: out3
|
|
12298
12465
|
});
|
|
12299
12466
|
}
|
|
12300
12467
|
// @__NO_SIDE_EFFECTS__
|
|
@@ -14530,19 +14697,19 @@ function _catch2(innerType, catchValue) {
|
|
|
14530
14697
|
function nan(params) {
|
|
14531
14698
|
return _nan(ZodNaN, params);
|
|
14532
14699
|
}
|
|
14533
|
-
function pipe(in_,
|
|
14700
|
+
function pipe(in_, out3) {
|
|
14534
14701
|
return new ZodPipe({
|
|
14535
14702
|
type: "pipe",
|
|
14536
14703
|
in: in_,
|
|
14537
|
-
out:
|
|
14704
|
+
out: out3
|
|
14538
14705
|
// ...util.normalizeParams(params),
|
|
14539
14706
|
});
|
|
14540
14707
|
}
|
|
14541
|
-
function codec(in_,
|
|
14708
|
+
function codec(in_, out3, params) {
|
|
14542
14709
|
return new ZodCodec({
|
|
14543
14710
|
type: "pipe",
|
|
14544
14711
|
in: in_,
|
|
14545
|
-
out:
|
|
14712
|
+
out: out3,
|
|
14546
14713
|
transform: params.decode,
|
|
14547
14714
|
reverseTransform: params.encode
|
|
14548
14715
|
});
|
|
@@ -15481,13 +15648,13 @@ function resolveRef(ref, ctx) {
|
|
|
15481
15648
|
if (!ref.startsWith("#")) {
|
|
15482
15649
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
15483
15650
|
}
|
|
15484
|
-
const
|
|
15485
|
-
if (
|
|
15651
|
+
const path10 = ref.slice(1).split("/").filter(Boolean);
|
|
15652
|
+
if (path10.length === 0) {
|
|
15486
15653
|
return ctx.rootSchema;
|
|
15487
15654
|
}
|
|
15488
15655
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
15489
|
-
if (
|
|
15490
|
-
const key =
|
|
15656
|
+
if (path10[0] === defsKey) {
|
|
15657
|
+
const key = path10[1];
|
|
15491
15658
|
if (!key || !ctx.defs[key]) {
|
|
15492
15659
|
throw new Error(`Reference not found: ${ref}`);
|
|
15493
15660
|
}
|
|
@@ -16676,8 +16843,8 @@ var init_parseUtil = __esm({
|
|
|
16676
16843
|
init_errors3();
|
|
16677
16844
|
init_en2();
|
|
16678
16845
|
makeIssue = (params) => {
|
|
16679
|
-
const { data, path:
|
|
16680
|
-
const fullPath = [...
|
|
16846
|
+
const { data, path: path10, errorMaps, issueData } = params;
|
|
16847
|
+
const fullPath = [...path10, ...issueData.path || []];
|
|
16681
16848
|
const fullIssue = {
|
|
16682
16849
|
...issueData,
|
|
16683
16850
|
path: fullPath
|
|
@@ -16960,11 +17127,11 @@ var init_types = __esm({
|
|
|
16960
17127
|
init_parseUtil();
|
|
16961
17128
|
init_util2();
|
|
16962
17129
|
ParseInputLazyPath = class {
|
|
16963
|
-
constructor(parent, value,
|
|
17130
|
+
constructor(parent, value, path10, key) {
|
|
16964
17131
|
this._cachedPath = [];
|
|
16965
17132
|
this.parent = parent;
|
|
16966
17133
|
this.data = value;
|
|
16967
|
-
this._path =
|
|
17134
|
+
this._path = path10;
|
|
16968
17135
|
this._key = key;
|
|
16969
17136
|
}
|
|
16970
17137
|
get path() {
|
|
@@ -23003,8 +23170,8 @@ var require_auth_config = __commonJS({
|
|
|
23003
23170
|
writeAuthConfig: () => writeAuthConfig
|
|
23004
23171
|
});
|
|
23005
23172
|
module2.exports = __toCommonJS(auth_config_exports);
|
|
23006
|
-
var
|
|
23007
|
-
var
|
|
23173
|
+
var fs6 = __toESM2(require("fs"));
|
|
23174
|
+
var path10 = __toESM2(require("path"));
|
|
23008
23175
|
var import_token_util = require_token_util();
|
|
23009
23176
|
function getAuthConfigPath() {
|
|
23010
23177
|
const dataDir = (0, import_token_util.getVercelDataDir)();
|
|
@@ -23013,15 +23180,15 @@ var require_auth_config = __commonJS({
|
|
|
23013
23180
|
`Unable to find Vercel CLI data directory. Your platform: ${process.platform}. Supported: darwin, linux, win32.`
|
|
23014
23181
|
);
|
|
23015
23182
|
}
|
|
23016
|
-
return
|
|
23183
|
+
return path10.join(dataDir, "auth.json");
|
|
23017
23184
|
}
|
|
23018
23185
|
function readAuthConfig() {
|
|
23019
23186
|
try {
|
|
23020
23187
|
const authPath = getAuthConfigPath();
|
|
23021
|
-
if (!
|
|
23188
|
+
if (!fs6.existsSync(authPath)) {
|
|
23022
23189
|
return null;
|
|
23023
23190
|
}
|
|
23024
|
-
const content =
|
|
23191
|
+
const content = fs6.readFileSync(authPath, "utf8");
|
|
23025
23192
|
if (!content) {
|
|
23026
23193
|
return null;
|
|
23027
23194
|
}
|
|
@@ -23032,11 +23199,11 @@ var require_auth_config = __commonJS({
|
|
|
23032
23199
|
}
|
|
23033
23200
|
function writeAuthConfig(config3) {
|
|
23034
23201
|
const authPath = getAuthConfigPath();
|
|
23035
|
-
const authDir =
|
|
23036
|
-
if (!
|
|
23037
|
-
|
|
23202
|
+
const authDir = path10.dirname(authPath);
|
|
23203
|
+
if (!fs6.existsSync(authDir)) {
|
|
23204
|
+
fs6.mkdirSync(authDir, { mode: 504, recursive: true });
|
|
23038
23205
|
}
|
|
23039
|
-
|
|
23206
|
+
fs6.writeFileSync(authPath, JSON.stringify(config3, null, 2), { mode: 384 });
|
|
23040
23207
|
}
|
|
23041
23208
|
function isValidAccessToken(authConfig, expirationBufferMs = 0) {
|
|
23042
23209
|
if (!authConfig.token)
|
|
@@ -23227,8 +23394,8 @@ var require_token_util = __commonJS({
|
|
|
23227
23394
|
saveToken: () => saveToken
|
|
23228
23395
|
});
|
|
23229
23396
|
module2.exports = __toCommonJS(token_util_exports);
|
|
23230
|
-
var
|
|
23231
|
-
var
|
|
23397
|
+
var path10 = __toESM2(require("path"));
|
|
23398
|
+
var fs6 = __toESM2(require("fs"));
|
|
23232
23399
|
var import_token_error = require_token_error();
|
|
23233
23400
|
var import_token_io = require_token_io();
|
|
23234
23401
|
var import_auth_config = require_auth_config();
|
|
@@ -23240,7 +23407,7 @@ var require_token_util = __commonJS({
|
|
|
23240
23407
|
if (!dataDir) {
|
|
23241
23408
|
return null;
|
|
23242
23409
|
}
|
|
23243
|
-
return
|
|
23410
|
+
return path10.join(dataDir, vercelFolder);
|
|
23244
23411
|
}
|
|
23245
23412
|
async function getVercelToken2(options) {
|
|
23246
23413
|
const authConfig = (0, import_auth_config.readAuthConfig)();
|
|
@@ -23316,13 +23483,13 @@ var require_token_util = __commonJS({
|
|
|
23316
23483
|
"Unable to find project root directory. Have you linked your project with `vc link?`"
|
|
23317
23484
|
);
|
|
23318
23485
|
}
|
|
23319
|
-
const prjPath =
|
|
23320
|
-
if (!
|
|
23486
|
+
const prjPath = path10.join(dir, ".vercel", "project.json");
|
|
23487
|
+
if (!fs6.existsSync(prjPath)) {
|
|
23321
23488
|
throw new import_token_error.VercelOidcTokenError(
|
|
23322
23489
|
"project.json not found, have you linked your project with `vc link?`"
|
|
23323
23490
|
);
|
|
23324
23491
|
}
|
|
23325
|
-
const prj = JSON.parse(
|
|
23492
|
+
const prj = JSON.parse(fs6.readFileSync(prjPath, "utf8"));
|
|
23326
23493
|
if (typeof prj.projectId !== "string" && typeof prj.orgId !== "string") {
|
|
23327
23494
|
throw new TypeError(
|
|
23328
23495
|
"Expected a string-valued projectId property. Try running `vc link` to re-link your project."
|
|
@@ -23337,11 +23504,11 @@ var require_token_util = __commonJS({
|
|
|
23337
23504
|
"Unable to find user data directory. Please reach out to Vercel support."
|
|
23338
23505
|
);
|
|
23339
23506
|
}
|
|
23340
|
-
const tokenPath =
|
|
23507
|
+
const tokenPath = path10.join(dir, "com.vercel.token", `${projectId}.json`);
|
|
23341
23508
|
const tokenJson = JSON.stringify(token);
|
|
23342
|
-
|
|
23343
|
-
|
|
23344
|
-
|
|
23509
|
+
fs6.mkdirSync(path10.dirname(tokenPath), { mode: 504, recursive: true });
|
|
23510
|
+
fs6.writeFileSync(tokenPath, tokenJson);
|
|
23511
|
+
fs6.chmodSync(tokenPath, 432);
|
|
23345
23512
|
return;
|
|
23346
23513
|
}
|
|
23347
23514
|
function loadToken(projectId) {
|
|
@@ -23351,11 +23518,11 @@ var require_token_util = __commonJS({
|
|
|
23351
23518
|
"Unable to find user data directory. Please reach out to Vercel support."
|
|
23352
23519
|
);
|
|
23353
23520
|
}
|
|
23354
|
-
const tokenPath =
|
|
23355
|
-
if (!
|
|
23521
|
+
const tokenPath = path10.join(dir, "com.vercel.token", `${projectId}.json`);
|
|
23522
|
+
if (!fs6.existsSync(tokenPath)) {
|
|
23356
23523
|
return null;
|
|
23357
23524
|
}
|
|
23358
|
-
const token = JSON.parse(
|
|
23525
|
+
const token = JSON.parse(fs6.readFileSync(tokenPath, "utf8"));
|
|
23359
23526
|
assertVercelOidcTokenResponse(token);
|
|
23360
23527
|
return token;
|
|
23361
23528
|
}
|
|
@@ -25306,7 +25473,7 @@ var init_platform = __esm({
|
|
|
25306
25473
|
|
|
25307
25474
|
// ../node_modules/.pnpm/@opentelemetry+api@1.9.0/node_modules/@opentelemetry/api/build/esm/version.js
|
|
25308
25475
|
var VERSION3;
|
|
25309
|
-
var
|
|
25476
|
+
var init_version2 = __esm({
|
|
25310
25477
|
"../node_modules/.pnpm/@opentelemetry+api@1.9.0/node_modules/@opentelemetry/api/build/esm/version.js"() {
|
|
25311
25478
|
"use strict";
|
|
25312
25479
|
VERSION3 = "1.9.0";
|
|
@@ -25381,7 +25548,7 @@ var re, isCompatible;
|
|
|
25381
25548
|
var init_semver = __esm({
|
|
25382
25549
|
"../node_modules/.pnpm/@opentelemetry+api@1.9.0/node_modules/@opentelemetry/api/build/esm/internal/semver.js"() {
|
|
25383
25550
|
"use strict";
|
|
25384
|
-
|
|
25551
|
+
init_version2();
|
|
25385
25552
|
re = /^(\d+)\.(\d+)\.(\d+)(-(.+))?$/;
|
|
25386
25553
|
isCompatible = _makeCompatibilityCheck(VERSION3);
|
|
25387
25554
|
}
|
|
@@ -25430,7 +25597,7 @@ var init_global_utils = __esm({
|
|
|
25430
25597
|
"../node_modules/.pnpm/@opentelemetry+api@1.9.0/node_modules/@opentelemetry/api/build/esm/internal/global-utils.js"() {
|
|
25431
25598
|
"use strict";
|
|
25432
25599
|
init_platform();
|
|
25433
|
-
|
|
25600
|
+
init_version2();
|
|
25434
25601
|
init_semver();
|
|
25435
25602
|
major = VERSION3.split(".")[0];
|
|
25436
25603
|
GLOBAL_OPENTELEMETRY_API_KEY = Symbol.for("opentelemetry.js.api." + major);
|
|
@@ -35381,7 +35548,7 @@ function createOpenRouter(options = {}) {
|
|
|
35381
35548
|
);
|
|
35382
35549
|
const createChatModel = (modelId, settings = {}) => new OpenRouterChatLanguageModel(modelId, settings, {
|
|
35383
35550
|
provider: "openrouter.chat",
|
|
35384
|
-
url: ({ path:
|
|
35551
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
35385
35552
|
headers: getHeaders,
|
|
35386
35553
|
compatibility,
|
|
35387
35554
|
fetch: options.fetch,
|
|
@@ -35389,7 +35556,7 @@ function createOpenRouter(options = {}) {
|
|
|
35389
35556
|
});
|
|
35390
35557
|
const createCompletionModel = (modelId, settings = {}) => new OpenRouterCompletionLanguageModel(modelId, settings, {
|
|
35391
35558
|
provider: "openrouter.completion",
|
|
35392
|
-
url: ({ path:
|
|
35559
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
35393
35560
|
headers: getHeaders,
|
|
35394
35561
|
compatibility,
|
|
35395
35562
|
fetch: options.fetch,
|
|
@@ -35397,21 +35564,21 @@ function createOpenRouter(options = {}) {
|
|
|
35397
35564
|
});
|
|
35398
35565
|
const createEmbeddingModel = (modelId, settings = {}) => new OpenRouterEmbeddingModel(modelId, settings, {
|
|
35399
35566
|
provider: "openrouter.embedding",
|
|
35400
|
-
url: ({ path:
|
|
35567
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
35401
35568
|
headers: getHeaders,
|
|
35402
35569
|
fetch: options.fetch,
|
|
35403
35570
|
extraBody: options.extraBody
|
|
35404
35571
|
});
|
|
35405
35572
|
const createImageModel = (modelId, settings = {}) => new OpenRouterImageModel(modelId, settings, {
|
|
35406
35573
|
provider: "openrouter.image",
|
|
35407
|
-
url: ({ path:
|
|
35574
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
35408
35575
|
headers: getHeaders,
|
|
35409
35576
|
fetch: options.fetch,
|
|
35410
35577
|
extraBody: options.extraBody
|
|
35411
35578
|
});
|
|
35412
35579
|
const createVideoModel = (modelId, settings = {}) => new OpenRouterVideoModel(modelId, settings, {
|
|
35413
35580
|
provider: "openrouter.video",
|
|
35414
|
-
url: ({ path:
|
|
35581
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
35415
35582
|
headers: getHeaders,
|
|
35416
35583
|
fetch: options.fetch,
|
|
35417
35584
|
extraBody: options.extraBody
|
|
@@ -39947,37 +40114,37 @@ function createOpenAI(options = {}) {
|
|
|
39947
40114
|
);
|
|
39948
40115
|
const createChatModel = (modelId) => new OpenAIChatLanguageModel(modelId, {
|
|
39949
40116
|
provider: `${providerName}.chat`,
|
|
39950
|
-
url: ({ path:
|
|
40117
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
39951
40118
|
headers: getHeaders,
|
|
39952
40119
|
fetch: options.fetch
|
|
39953
40120
|
});
|
|
39954
40121
|
const createCompletionModel = (modelId) => new OpenAICompletionLanguageModel(modelId, {
|
|
39955
40122
|
provider: `${providerName}.completion`,
|
|
39956
|
-
url: ({ path:
|
|
40123
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
39957
40124
|
headers: getHeaders,
|
|
39958
40125
|
fetch: options.fetch
|
|
39959
40126
|
});
|
|
39960
40127
|
const createEmbeddingModel = (modelId) => new OpenAIEmbeddingModel(modelId, {
|
|
39961
40128
|
provider: `${providerName}.embedding`,
|
|
39962
|
-
url: ({ path:
|
|
40129
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
39963
40130
|
headers: getHeaders,
|
|
39964
40131
|
fetch: options.fetch
|
|
39965
40132
|
});
|
|
39966
40133
|
const createImageModel = (modelId) => new OpenAIImageModel(modelId, {
|
|
39967
40134
|
provider: `${providerName}.image`,
|
|
39968
|
-
url: ({ path:
|
|
40135
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
39969
40136
|
headers: getHeaders,
|
|
39970
40137
|
fetch: options.fetch
|
|
39971
40138
|
});
|
|
39972
40139
|
const createTranscriptionModel = (modelId) => new OpenAITranscriptionModel(modelId, {
|
|
39973
40140
|
provider: `${providerName}.transcription`,
|
|
39974
|
-
url: ({ path:
|
|
40141
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
39975
40142
|
headers: getHeaders,
|
|
39976
40143
|
fetch: options.fetch
|
|
39977
40144
|
});
|
|
39978
40145
|
const createSpeechModel = (modelId) => new OpenAISpeechModel(modelId, {
|
|
39979
40146
|
provider: `${providerName}.speech`,
|
|
39980
|
-
url: ({ path:
|
|
40147
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
39981
40148
|
headers: getHeaders,
|
|
39982
40149
|
fetch: options.fetch
|
|
39983
40150
|
});
|
|
@@ -39992,7 +40159,7 @@ function createOpenAI(options = {}) {
|
|
|
39992
40159
|
const createResponsesModel = (modelId) => {
|
|
39993
40160
|
return new OpenAIResponsesLanguageModel(modelId, {
|
|
39994
40161
|
provider: `${providerName}.responses`,
|
|
39995
|
-
url: ({ path:
|
|
40162
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
39996
40163
|
headers: getHeaders,
|
|
39997
40164
|
fetch: options.fetch,
|
|
39998
40165
|
fileIdPrefixes: ["file-"]
|
|
@@ -45213,7 +45380,7 @@ function supportsMultimodalToolResults(modelName) {
|
|
|
45213
45380
|
const normalized = modelName.toLowerCase();
|
|
45214
45381
|
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");
|
|
45215
45382
|
}
|
|
45216
|
-
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;
|
|
45383
|
+
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;
|
|
45217
45384
|
var init_providers = __esm({
|
|
45218
45385
|
"../lib/ai/providers.ts"() {
|
|
45219
45386
|
"use strict";
|
|
@@ -45373,10 +45540,43 @@ var init_providers = __esm({
|
|
|
45373
45540
|
name: "openai",
|
|
45374
45541
|
apiKey: process.env.OPENAI_API_KEY
|
|
45375
45542
|
});
|
|
45543
|
+
isNvidiaMistralModel = (value) => typeof value === "string" && value.toLowerCase().startsWith("mistralai/mistral");
|
|
45544
|
+
applyNvidiaMistralConfig = (body) => {
|
|
45545
|
+
if (!isRecord(body) || !isNvidiaMistralModel(body.model)) {
|
|
45546
|
+
return { body, changed: false };
|
|
45547
|
+
}
|
|
45548
|
+
return {
|
|
45549
|
+
body: {
|
|
45550
|
+
...body,
|
|
45551
|
+
reasoning_effort: "none",
|
|
45552
|
+
temperature: 1,
|
|
45553
|
+
top_p: 1,
|
|
45554
|
+
max_tokens: 16384
|
|
45555
|
+
},
|
|
45556
|
+
changed: true
|
|
45557
|
+
};
|
|
45558
|
+
};
|
|
45559
|
+
nvidiaPatchFetch = async (url2, init) => {
|
|
45560
|
+
if (init?.body && typeof init.body === "string") {
|
|
45561
|
+
try {
|
|
45562
|
+
const parsed = JSON.parse(init.body);
|
|
45563
|
+
const patched = applyNvidiaMistralConfig(parsed);
|
|
45564
|
+
if (patched.changed) {
|
|
45565
|
+
return globalThis.fetch(url2, {
|
|
45566
|
+
...init,
|
|
45567
|
+
body: JSON.stringify(patched.body)
|
|
45568
|
+
});
|
|
45569
|
+
}
|
|
45570
|
+
} catch {
|
|
45571
|
+
}
|
|
45572
|
+
}
|
|
45573
|
+
return globalThis.fetch(url2, init);
|
|
45574
|
+
};
|
|
45376
45575
|
nvidia = createOpenAI({
|
|
45377
45576
|
name: "nvidia",
|
|
45378
45577
|
baseURL: process.env.NVIDIA_BASE_URL || "https://integrate.api.nvidia.com/v1",
|
|
45379
|
-
apiKey: process.env.NVIDIA_API_KEY
|
|
45578
|
+
apiKey: process.env.NVIDIA_API_KEY,
|
|
45579
|
+
fetch: nvidiaPatchFetch
|
|
45380
45580
|
});
|
|
45381
45581
|
deepseek = createOpenAI({
|
|
45382
45582
|
name: "deepseek",
|
|
@@ -45404,7 +45604,9 @@ var init_providers = __esm({
|
|
|
45404
45604
|
"model-opus-4.6": nvidia("nvidia/nemotron-3-ultra-550b-a55b"),
|
|
45405
45605
|
"model-kimi-k2.6": or("qwen/qwen3-coder:free"),
|
|
45406
45606
|
// NVIDIA build models — primary provider for the local CLI (chat-completions).
|
|
45407
|
-
"model-nvidia-
|
|
45607
|
+
"model-nvidia-mistral-medium-3.5": nvidia.chat(
|
|
45608
|
+
"mistralai/mistral-medium-3.5-128b"
|
|
45609
|
+
),
|
|
45408
45610
|
"model-nvidia-kimi-k2.6": nvidia.chat("moonshotai/kimi-k2.6"),
|
|
45409
45611
|
"model-nvidia-glm-5.1": nvidia.chat("z-ai/glm-5.1"),
|
|
45410
45612
|
"model-nvidia-qwen3.5-397b": nvidia.chat("qwen/qwen3.5-397b-a17b"),
|
|
@@ -45441,8 +45643,8 @@ var init_providers = __esm({
|
|
|
45441
45643
|
};
|
|
45442
45644
|
CLI_MODEL_CHAIN = [
|
|
45443
45645
|
...hasEnvValue("NVIDIA_API_KEY") ? [
|
|
45444
|
-
"model-nvidia-
|
|
45445
|
-
// NVIDIA
|
|
45646
|
+
"model-nvidia-mistral-medium-3.5",
|
|
45647
|
+
// NVIDIA mistralai/mistral-medium-3.5-128b
|
|
45446
45648
|
"model-nvidia-kimi-k2.6",
|
|
45447
45649
|
// NVIDIA moonshotai/kimi-k2.6
|
|
45448
45650
|
"model-nvidia-glm-5.1",
|
|
@@ -45469,7 +45671,7 @@ var init_providers = __esm({
|
|
|
45469
45671
|
"model-deepseek-v4-flash": "May 2025",
|
|
45470
45672
|
"model-opus-4.6": "May 2025",
|
|
45471
45673
|
"model-kimi-k2.6": "April 2024",
|
|
45472
|
-
"model-nvidia-
|
|
45674
|
+
"model-nvidia-mistral-medium-3.5": "Unknown",
|
|
45473
45675
|
"model-nvidia-kimi-k2.6": "April 2024",
|
|
45474
45676
|
"model-nvidia-glm-5.1": "Unknown",
|
|
45475
45677
|
"model-nvidia-qwen3.5-397b": "Unknown",
|
|
@@ -45493,7 +45695,7 @@ var init_providers = __esm({
|
|
|
45493
45695
|
"model-deepseek-v4-flash": "DeepSeek V4 Flash",
|
|
45494
45696
|
"model-opus-4.6": "Anthropic Claude Opus 4.6",
|
|
45495
45697
|
"model-kimi-k2.6": "Moonshot Kimi K2.6",
|
|
45496
|
-
"model-nvidia-
|
|
45698
|
+
"model-nvidia-mistral-medium-3.5": "NVIDIA - Mistral Medium 3.5",
|
|
45497
45699
|
"model-nvidia-kimi-k2.6": "NVIDIA - Moonshot Kimi K2.6",
|
|
45498
45700
|
"model-nvidia-glm-5.1": "NVIDIA - Z.ai GLM 5.1",
|
|
45499
45701
|
"model-nvidia-qwen3.5-397b": "NVIDIA - Qwen3.5 397B A17B",
|
|
@@ -48528,8 +48730,8 @@ var init_background_process_tracker = __esm({
|
|
|
48528
48730
|
/**
|
|
48529
48731
|
* Normalize file path for comparison
|
|
48530
48732
|
*/
|
|
48531
|
-
normalizePath(
|
|
48532
|
-
let normalized =
|
|
48733
|
+
normalizePath(path10) {
|
|
48734
|
+
let normalized = path10.trim().replace(/\/+/g, "/");
|
|
48533
48735
|
if (normalized.startsWith("./")) {
|
|
48534
48736
|
normalized = normalized.slice(2);
|
|
48535
48737
|
}
|
|
@@ -48767,8 +48969,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
|
|
|
48767
48969
|
return decodedFile;
|
|
48768
48970
|
};
|
|
48769
48971
|
}
|
|
48770
|
-
function normalizeWindowsPath(
|
|
48771
|
-
return
|
|
48972
|
+
function normalizeWindowsPath(path10) {
|
|
48973
|
+
return path10.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
|
|
48772
48974
|
}
|
|
48773
48975
|
var import_path;
|
|
48774
48976
|
var init_module_node = __esm({
|
|
@@ -51657,9 +51859,9 @@ async function addSourceContext(frames) {
|
|
|
51657
51859
|
LRU_FILE_CONTENTS_CACHE.reduce();
|
|
51658
51860
|
return frames;
|
|
51659
51861
|
}
|
|
51660
|
-
function getContextLinesFromFile(
|
|
51862
|
+
function getContextLinesFromFile(path10, ranges, output) {
|
|
51661
51863
|
return new Promise((resolve2) => {
|
|
51662
|
-
const stream = (0,
|
|
51864
|
+
const stream = (0, import_node_fs5.createReadStream)(path10);
|
|
51663
51865
|
const lineReaded = (0, import_node_readline2.createInterface)({
|
|
51664
51866
|
input: stream
|
|
51665
51867
|
});
|
|
@@ -51674,7 +51876,7 @@ function getContextLinesFromFile(path6, ranges, output) {
|
|
|
51674
51876
|
let rangeStart = range[0];
|
|
51675
51877
|
let rangeEnd = range[1];
|
|
51676
51878
|
function onStreamError() {
|
|
51677
|
-
LRU_FILE_CONTENTS_FS_READ_FAILED.set(
|
|
51879
|
+
LRU_FILE_CONTENTS_FS_READ_FAILED.set(path10, 1);
|
|
51678
51880
|
lineReaded.close();
|
|
51679
51881
|
lineReaded.removeAllListeners();
|
|
51680
51882
|
destroyStreamAndResolve();
|
|
@@ -51735,8 +51937,8 @@ function clearLineContext(frame2) {
|
|
|
51735
51937
|
delete frame2.context_line;
|
|
51736
51938
|
delete frame2.post_context;
|
|
51737
51939
|
}
|
|
51738
|
-
function shouldSkipContextLinesForFile(
|
|
51739
|
-
return
|
|
51940
|
+
function shouldSkipContextLinesForFile(path10) {
|
|
51941
|
+
return path10.startsWith("node:") || path10.endsWith(".min.js") || path10.endsWith(".min.cjs") || path10.endsWith(".min.mjs") || path10.startsWith("data:");
|
|
51740
51942
|
}
|
|
51741
51943
|
function shouldSkipContextLinesForFrame(frame2) {
|
|
51742
51944
|
if (void 0 !== frame2.lineno && frame2.lineno > MAX_CONTEXTLINES_LINENO) return true;
|
|
@@ -51755,22 +51957,22 @@ function makeLineReaderRanges(lines) {
|
|
|
51755
51957
|
const line = lines[0];
|
|
51756
51958
|
if ("number" != typeof line) return [];
|
|
51757
51959
|
let current = makeContextRange(line);
|
|
51758
|
-
const
|
|
51960
|
+
const out3 = [];
|
|
51759
51961
|
while (true) {
|
|
51760
51962
|
if (i === lines.length - 1) {
|
|
51761
|
-
|
|
51963
|
+
out3.push(current);
|
|
51762
51964
|
break;
|
|
51763
51965
|
}
|
|
51764
51966
|
const next = lines[i + 1];
|
|
51765
51967
|
if ("number" != typeof next) break;
|
|
51766
51968
|
if (next <= current[1]) current[1] = next + DEFAULT_LINES_OF_CONTEXT;
|
|
51767
51969
|
else {
|
|
51768
|
-
|
|
51970
|
+
out3.push(current);
|
|
51769
51971
|
current = makeContextRange(next);
|
|
51770
51972
|
}
|
|
51771
51973
|
i++;
|
|
51772
51974
|
}
|
|
51773
|
-
return
|
|
51975
|
+
return out3;
|
|
51774
51976
|
}
|
|
51775
51977
|
function makeContextRange(line) {
|
|
51776
51978
|
return [
|
|
@@ -51807,12 +52009,12 @@ function snipLine(line, colno) {
|
|
|
51807
52009
|
if (end < lineLength) newLine += "...";
|
|
51808
52010
|
return newLine;
|
|
51809
52011
|
}
|
|
51810
|
-
var
|
|
52012
|
+
var import_node_fs5, import_node_readline2, LRU_FILE_CONTENTS_CACHE, LRU_FILE_CONTENTS_FS_READ_FAILED, DEFAULT_LINES_OF_CONTEXT, MAX_CONTEXTLINES_COLNO, MAX_CONTEXTLINES_LINENO;
|
|
51811
52013
|
var init_context_lines_node = __esm({
|
|
51812
52014
|
"../node_modules/.pnpm/posthog-node@5.35.13_rxjs@7.8.2/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/context-lines.node.mjs"() {
|
|
51813
52015
|
"use strict";
|
|
51814
52016
|
init_dist8();
|
|
51815
|
-
|
|
52017
|
+
import_node_fs5 = require("node:fs");
|
|
51816
52018
|
import_node_readline2 = require("node:readline");
|
|
51817
52019
|
LRU_FILE_CONTENTS_CACHE = new error_tracking_exports.ReduceableCache(25);
|
|
51818
52020
|
LRU_FILE_CONTENTS_FS_READ_FAILED = new error_tracking_exports.ReduceableCache(20);
|
|
@@ -51844,7 +52046,7 @@ var init_relative_path_node = __esm({
|
|
|
51844
52046
|
|
|
51845
52047
|
// ../node_modules/.pnpm/posthog-node@5.35.13_rxjs@7.8.2/node_modules/posthog-node/dist/version.mjs
|
|
51846
52048
|
var version2;
|
|
51847
|
-
var
|
|
52049
|
+
var init_version3 = __esm({
|
|
51848
52050
|
"../node_modules/.pnpm/posthog-node@5.35.13_rxjs@7.8.2/node_modules/posthog-node/dist/version.mjs"() {
|
|
51849
52051
|
"use strict";
|
|
51850
52052
|
version2 = "5.35.13";
|
|
@@ -52962,7 +53164,7 @@ var MINIMUM_POLLING_INTERVAL, THIRTY_SECONDS, MAX_CACHE_SIZE, WAITUNTIL_DEBOUNCE
|
|
|
52962
53164
|
var init_client = __esm({
|
|
52963
53165
|
"../node_modules/.pnpm/posthog-node@5.35.13_rxjs@7.8.2/node_modules/posthog-node/dist/client.mjs"() {
|
|
52964
53166
|
"use strict";
|
|
52965
|
-
|
|
53167
|
+
init_version3();
|
|
52966
53168
|
init_dist8();
|
|
52967
53169
|
init_types5();
|
|
52968
53170
|
init_feature_flag_evaluations();
|
|
@@ -55288,8 +55490,8 @@ async function createE2BPtyHandle(sandbox, opts) {
|
|
|
55288
55490
|
sendInput(bytes) {
|
|
55289
55491
|
return pty.sendInput(pid, bytes);
|
|
55290
55492
|
},
|
|
55291
|
-
async resize(
|
|
55292
|
-
await pty.resize(pid, { cols, rows });
|
|
55493
|
+
async resize(cols2, rows) {
|
|
55494
|
+
await pty.resize(pid, { cols: cols2, rows });
|
|
55293
55495
|
},
|
|
55294
55496
|
async kill() {
|
|
55295
55497
|
const killed = await pty.kill(pid);
|
|
@@ -55430,9 +55632,9 @@ var init_pty_session_manager = __esm({
|
|
|
55430
55632
|
consumeDelta(session) {
|
|
55431
55633
|
const total = this.totalBufferBytes(session);
|
|
55432
55634
|
const start = Math.min(session.readCursor, total);
|
|
55433
|
-
const
|
|
55635
|
+
const out3 = this.sliceBuffer(session, start, total);
|
|
55434
55636
|
session.readCursor = total;
|
|
55435
|
-
return
|
|
55637
|
+
return out3;
|
|
55436
55638
|
}
|
|
55437
55639
|
/**
|
|
55438
55640
|
* Returns the full accumulated buffer without advancing `readCursor`.
|
|
@@ -55490,7 +55692,7 @@ var init_pty_session_manager = __esm({
|
|
|
55490
55692
|
}
|
|
55491
55693
|
sliceBuffer(session, start, end) {
|
|
55492
55694
|
if (end <= start) return new Uint8Array(0);
|
|
55493
|
-
const
|
|
55695
|
+
const out3 = new Uint8Array(end - start);
|
|
55494
55696
|
let outOffset = 0;
|
|
55495
55697
|
let cursor = 0;
|
|
55496
55698
|
for (const chunk of session.buffer) {
|
|
@@ -55503,11 +55705,11 @@ var init_pty_session_manager = __esm({
|
|
|
55503
55705
|
if (chunkStart >= end) break;
|
|
55504
55706
|
const sliceStart = Math.max(0, start - chunkStart);
|
|
55505
55707
|
const sliceEnd = Math.min(chunk.byteLength, end - chunkStart);
|
|
55506
|
-
|
|
55708
|
+
out3.set(chunk.subarray(sliceStart, sliceEnd), outOffset);
|
|
55507
55709
|
outOffset += sliceEnd - sliceStart;
|
|
55508
55710
|
cursor = chunkEnd;
|
|
55509
55711
|
}
|
|
55510
|
-
return
|
|
55712
|
+
return out3;
|
|
55511
55713
|
}
|
|
55512
55714
|
async killAndRemove(session, _reason) {
|
|
55513
55715
|
if (session.closing) {
|
|
@@ -55765,7 +55967,7 @@ var require_xterm_headless = __commonJS({
|
|
|
55765
55967
|
};
|
|
55766
55968
|
Object.defineProperty(t2, "__esModule", { value: true }), t2.InputHandler = t2.WindowsOptionsReportType = void 0, t2.isValidColorIndex = k;
|
|
55767
55969
|
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;
|
|
55768
|
-
function
|
|
55970
|
+
function C5(e3, t3) {
|
|
55769
55971
|
if (e3 > 24) return t3.setWinLines || false;
|
|
55770
55972
|
switch (e3) {
|
|
55771
55973
|
case 1:
|
|
@@ -55900,7 +56102,7 @@ var require_xterm_headless = __commonJS({
|
|
|
55900
56102
|
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);
|
|
55901
56103
|
}
|
|
55902
56104
|
registerCsiHandler(e3, t3) {
|
|
55903
|
-
return "t" !== e3.final || e3.prefix || e3.intermediates ? this._parser.registerCsiHandler(e3, t3) : this._parser.registerCsiHandler(e3, ((e4) => !
|
|
56105
|
+
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)));
|
|
55904
56106
|
}
|
|
55905
56107
|
registerDcsHandler(e3, t3) {
|
|
55906
56108
|
return this._parser.registerDcsHandler(e3, new v.DcsHandler(t3));
|
|
@@ -56414,7 +56616,7 @@ var require_xterm_headless = __commonJS({
|
|
|
56414
56616
|
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;
|
|
56415
56617
|
}
|
|
56416
56618
|
windowOptions(e3) {
|
|
56417
|
-
if (!
|
|
56619
|
+
if (!C5(e3.params[0], this._optionsService.rawOptions.windowOptions)) return true;
|
|
56418
56620
|
const t3 = e3.length > 1 ? e3.params[1] : 0;
|
|
56419
56621
|
switch (e3.params[0]) {
|
|
56420
56622
|
case 14:
|
|
@@ -61541,12 +61743,12 @@ function applyDelta(source, delta) {
|
|
|
61541
61743
|
zDelta.pos += cnt;
|
|
61542
61744
|
break;
|
|
61543
61745
|
case ";": {
|
|
61544
|
-
const
|
|
61545
|
-
if (cnt !== checksum(
|
|
61746
|
+
const out3 = zOut.toByteArray(source);
|
|
61747
|
+
if (cnt !== checksum(out3))
|
|
61546
61748
|
throw new Error("bad checksum");
|
|
61547
61749
|
if (total !== limit)
|
|
61548
61750
|
throw new Error("generated size does not match predicted size");
|
|
61549
|
-
return
|
|
61751
|
+
return out3;
|
|
61550
61752
|
}
|
|
61551
61753
|
default:
|
|
61552
61754
|
throw new Error("unknown delta operator");
|
|
@@ -66120,11 +66322,11 @@ async function createCentrifugoPtyHandle(sandbox, opts) {
|
|
|
66120
66322
|
};
|
|
66121
66323
|
await publish(payload);
|
|
66122
66324
|
},
|
|
66123
|
-
async resize(
|
|
66325
|
+
async resize(cols2, rows) {
|
|
66124
66326
|
const payload = {
|
|
66125
66327
|
type: "pty_resize",
|
|
66126
66328
|
sessionId,
|
|
66127
|
-
cols,
|
|
66329
|
+
cols: cols2,
|
|
66128
66330
|
rows,
|
|
66129
66331
|
targetConnectionId: connectionId
|
|
66130
66332
|
};
|
|
@@ -66359,7 +66561,7 @@ In using these tools, adhere to the following guidelines:
|
|
|
66359
66561
|
timeout,
|
|
66360
66562
|
interactive
|
|
66361
66563
|
}, { toolCallId, abortSignal }) => {
|
|
66362
|
-
const
|
|
66564
|
+
const cols2 = DEFAULT_PTY_COLS;
|
|
66363
66565
|
const rows = DEFAULT_PTY_ROWS;
|
|
66364
66566
|
let activePtySessionId;
|
|
66365
66567
|
let emitQueue = Promise.resolve();
|
|
@@ -66454,20 +66656,20 @@ In using these tools, adhere to the following guidelines:
|
|
|
66454
66656
|
}
|
|
66455
66657
|
}
|
|
66456
66658
|
const session = await ptySessionManager2.create(chatId, {
|
|
66457
|
-
cols,
|
|
66659
|
+
cols: cols2,
|
|
66458
66660
|
rows,
|
|
66459
66661
|
createHandle: async () => {
|
|
66460
66662
|
if (isCentrifugo) {
|
|
66461
66663
|
const { createCentrifugoPtyHandle: createCentrifugoPtyHandle2 } = await Promise.resolve().then(() => (init_centrifugo_pty_adapter(), centrifugo_pty_adapter_exports));
|
|
66462
66664
|
return createCentrifugoPtyHandle2(sandbox, {
|
|
66463
66665
|
command,
|
|
66464
|
-
cols,
|
|
66666
|
+
cols: cols2,
|
|
66465
66667
|
rows,
|
|
66466
66668
|
envs: caidoEnvVars
|
|
66467
66669
|
});
|
|
66468
66670
|
}
|
|
66469
66671
|
return createE2BPtyHandle(sandbox, {
|
|
66470
|
-
cols,
|
|
66672
|
+
cols: cols2,
|
|
66471
66673
|
rows,
|
|
66472
66674
|
envs: caidoEnvVars
|
|
66473
66675
|
});
|
|
@@ -67146,8 +67348,8 @@ var init_logger2 = __esm({
|
|
|
67146
67348
|
});
|
|
67147
67349
|
|
|
67148
67350
|
// ../lib/ai/tools/file.ts
|
|
67149
|
-
function isSpritPath(
|
|
67150
|
-
return
|
|
67351
|
+
function isSpritPath(path10) {
|
|
67352
|
+
return path10.split(/[\\/]/).some((segment) => segment.toLowerCase() === "sprit");
|
|
67151
67353
|
}
|
|
67152
67354
|
function getViewSandboxType(sandbox) {
|
|
67153
67355
|
return isCentrifugoSandbox(sandbox) ? "centrifugo" : "e2b";
|
|
@@ -67178,7 +67380,7 @@ function captureFileViewImageUsage(args) {
|
|
|
67178
67380
|
const {
|
|
67179
67381
|
context: context2,
|
|
67180
67382
|
sandbox,
|
|
67181
|
-
path:
|
|
67383
|
+
path: path10,
|
|
67182
67384
|
outcome,
|
|
67183
67385
|
durationMs,
|
|
67184
67386
|
mediaType,
|
|
@@ -67196,7 +67398,7 @@ function captureFileViewImageUsage(args) {
|
|
|
67196
67398
|
model: getActiveModelName(context2),
|
|
67197
67399
|
configured_model: context2.modelName,
|
|
67198
67400
|
sandbox_type: getViewSandboxType(sandbox),
|
|
67199
|
-
file_extension: getFileExtension(
|
|
67401
|
+
file_extension: getFileExtension(path10),
|
|
67200
67402
|
outcome,
|
|
67201
67403
|
success: outcome === "success",
|
|
67202
67404
|
duration_ms: durationMs,
|
|
@@ -67270,22 +67472,22 @@ async function runSandboxCommand(sandbox, command, envVars, timeoutMs = 6e4) {
|
|
|
67270
67472
|
function isWindowsSandbox(sandbox) {
|
|
67271
67473
|
return isCentrifugoSandbox(sandbox) && sandbox.isWindows();
|
|
67272
67474
|
}
|
|
67273
|
-
function getWindowsNativePath(
|
|
67274
|
-
if (/^[A-Za-z]:[\\/]/.test(
|
|
67275
|
-
if (
|
|
67276
|
-
return `C:\\temp${
|
|
67475
|
+
function getWindowsNativePath(path10) {
|
|
67476
|
+
if (/^[A-Za-z]:[\\/]/.test(path10)) return path10;
|
|
67477
|
+
if (path10.startsWith("/tmp/")) {
|
|
67478
|
+
return `C:\\temp${path10.slice(4).replace(/\//g, "\\")}`;
|
|
67277
67479
|
}
|
|
67278
|
-
return
|
|
67480
|
+
return path10.replace(/\//g, "\\");
|
|
67279
67481
|
}
|
|
67280
|
-
function getPythonPathForSandbox(sandbox,
|
|
67281
|
-
return isWindowsSandbox(sandbox) ? getWindowsNativePath(
|
|
67482
|
+
function getPythonPathForSandbox(sandbox, path10) {
|
|
67483
|
+
return isWindowsSandbox(sandbox) ? getWindowsNativePath(path10) : path10;
|
|
67282
67484
|
}
|
|
67283
|
-
function toWindowsBashPath(
|
|
67284
|
-
const drive =
|
|
67485
|
+
function toWindowsBashPath(path10) {
|
|
67486
|
+
const drive = path10.match(/^([A-Za-z]):[\\/](.*)$/);
|
|
67285
67487
|
if (drive) {
|
|
67286
67488
|
return `/${drive[1].toLowerCase()}/${drive[2].replace(/\\/g, "/")}`;
|
|
67287
67489
|
}
|
|
67288
|
-
return
|
|
67490
|
+
return path10.replace(/\\/g, "/");
|
|
67289
67491
|
}
|
|
67290
67492
|
async function detectSandboxShell(sandbox) {
|
|
67291
67493
|
if (!isWindowsSandbox(sandbox)) return "bash";
|
|
@@ -67324,8 +67526,8 @@ PY`;
|
|
|
67324
67526
|
}
|
|
67325
67527
|
}
|
|
67326
67528
|
}
|
|
67327
|
-
async function getSandboxFileState(sandbox,
|
|
67328
|
-
const pythonPath = getPythonPathForSandbox(sandbox,
|
|
67529
|
+
async function getSandboxFileState(sandbox, path10) {
|
|
67530
|
+
const pythonPath = getPythonPathForSandbox(sandbox, path10);
|
|
67329
67531
|
const result = await runPythonScript(
|
|
67330
67532
|
sandbox,
|
|
67331
67533
|
FILE_STATE_SCRIPT,
|
|
@@ -67342,23 +67544,23 @@ async function getSandboxFileState(sandbox, path6) {
|
|
|
67342
67544
|
if (result.exitCode !== 0) {
|
|
67343
67545
|
return {
|
|
67344
67546
|
kind: "unknown",
|
|
67345
|
-
path:
|
|
67547
|
+
path: path10,
|
|
67346
67548
|
error: result.stderr || result.stdout || "file state command failed"
|
|
67347
67549
|
};
|
|
67348
67550
|
}
|
|
67349
67551
|
try {
|
|
67350
67552
|
const payload = JSON.parse(result.stdout.trim());
|
|
67351
67553
|
if (payload.kind === "file" && typeof payload.sizeBytes === "number" && Number.isFinite(payload.sizeBytes)) {
|
|
67352
|
-
return { ...payload, path:
|
|
67554
|
+
return { ...payload, path: path10 };
|
|
67353
67555
|
}
|
|
67354
67556
|
if (payload.kind === "missing" || payload.kind === "not_file") {
|
|
67355
|
-
return { ...payload, path:
|
|
67557
|
+
return { ...payload, path: path10 };
|
|
67356
67558
|
}
|
|
67357
67559
|
} catch {
|
|
67358
67560
|
}
|
|
67359
67561
|
return {
|
|
67360
67562
|
kind: "unknown",
|
|
67361
|
-
path:
|
|
67563
|
+
path: path10,
|
|
67362
67564
|
error: result.stderr || result.stdout || "invalid file state response"
|
|
67363
67565
|
};
|
|
67364
67566
|
}
|
|
@@ -67390,8 +67592,8 @@ ${numberedContent}${truncatedNotice}${footerNotice}`;
|
|
|
67390
67592
|
})
|
|
67391
67593
|
};
|
|
67392
67594
|
}
|
|
67393
|
-
async function readSandboxTextFile(sandbox,
|
|
67394
|
-
const pythonPath = getPythonPathForSandbox(sandbox,
|
|
67595
|
+
async function readSandboxTextFile(sandbox, path10, range) {
|
|
67596
|
+
const pythonPath = getPythonPathForSandbox(sandbox, path10);
|
|
67395
67597
|
const envVars = {
|
|
67396
67598
|
HACKERAI_FILE_READ_PATH: pythonPath,
|
|
67397
67599
|
HACKERAI_FILE_READ_RANGE_START: String(range?.[0] ?? 0),
|
|
@@ -67419,40 +67621,40 @@ async function readSandboxTextFile(sandbox, path6, range) {
|
|
|
67419
67621
|
}
|
|
67420
67622
|
return payload;
|
|
67421
67623
|
}
|
|
67422
|
-
async function readSandboxTextFileWithFallback(sandbox,
|
|
67624
|
+
async function readSandboxTextFileWithFallback(sandbox, path10, range) {
|
|
67423
67625
|
try {
|
|
67424
|
-
return await readSandboxTextFile(sandbox,
|
|
67626
|
+
return await readSandboxTextFile(sandbox, path10, range);
|
|
67425
67627
|
} catch (error51) {
|
|
67426
67628
|
const errorMessage = error51 instanceof Error ? error51.message : String(error51);
|
|
67427
67629
|
if (errorMessage.startsWith("Invalid ") || errorMessage.includes("File not found")) {
|
|
67428
67630
|
throw error51;
|
|
67429
67631
|
}
|
|
67430
|
-
const state = await getSandboxFileState(sandbox,
|
|
67632
|
+
const state = await getSandboxFileState(sandbox, path10);
|
|
67431
67633
|
if (state.kind === "unknown") {
|
|
67432
67634
|
throw new Error(
|
|
67433
|
-
`Unable to determine file size for ${
|
|
67635
|
+
`Unable to determine file size for ${path10}; refusing to load the file into memory. ${state.error}`
|
|
67434
67636
|
);
|
|
67435
67637
|
}
|
|
67436
67638
|
if (state.kind === "missing") {
|
|
67437
|
-
throw new Error(`File not found or is not a regular file: ${
|
|
67639
|
+
throw new Error(`File not found or is not a regular file: ${path10}`);
|
|
67438
67640
|
}
|
|
67439
67641
|
if (state.kind === "not_file") {
|
|
67440
|
-
throw new Error(`File is not a regular file: ${
|
|
67642
|
+
throw new Error(`File is not a regular file: ${path10}`);
|
|
67441
67643
|
}
|
|
67442
67644
|
if (state.sizeBytes > MAX_TEXT_FILE_READ_BYTES) {
|
|
67443
67645
|
if (range) {
|
|
67444
67646
|
throw new Error(
|
|
67445
|
-
`Unable to perform a bounded range read for ${
|
|
67647
|
+
`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.`
|
|
67446
67648
|
);
|
|
67447
67649
|
}
|
|
67448
67650
|
return {
|
|
67449
|
-
path:
|
|
67651
|
+
path: path10,
|
|
67450
67652
|
sizeBytes: state.sizeBytes,
|
|
67451
67653
|
totalLines: 0,
|
|
67452
67654
|
tooLarge: true
|
|
67453
67655
|
};
|
|
67454
67656
|
}
|
|
67455
|
-
const fileContent = await sandbox.files.read(
|
|
67657
|
+
const fileContent = await sandbox.files.read(path10, {
|
|
67456
67658
|
user: "user"
|
|
67457
67659
|
});
|
|
67458
67660
|
const lines = fileContent.split("\n");
|
|
@@ -67481,7 +67683,7 @@ async function readSandboxTextFileWithFallback(sandbox, path6, range) {
|
|
|
67481
67683
|
const startIndex = start - 1;
|
|
67482
67684
|
const endIndex = end === -1 ? lines.length : end;
|
|
67483
67685
|
return {
|
|
67484
|
-
path:
|
|
67686
|
+
path: path10,
|
|
67485
67687
|
sizeBytes: Buffer.byteLength(fileContent),
|
|
67486
67688
|
totalLines: lines.length,
|
|
67487
67689
|
content: lines.slice(startIndex, endIndex).join("\n"),
|
|
@@ -67489,7 +67691,7 @@ async function readSandboxTextFileWithFallback(sandbox, path6, range) {
|
|
|
67489
67691
|
};
|
|
67490
67692
|
}
|
|
67491
67693
|
return {
|
|
67492
|
-
path:
|
|
67694
|
+
path: path10,
|
|
67493
67695
|
sizeBytes: Buffer.byteLength(fileContent),
|
|
67494
67696
|
totalLines: lines.length,
|
|
67495
67697
|
content: fileContent,
|
|
@@ -67497,7 +67699,7 @@ async function readSandboxTextFileWithFallback(sandbox, path6, range) {
|
|
|
67497
67699
|
};
|
|
67498
67700
|
}
|
|
67499
67701
|
}
|
|
67500
|
-
async function appendSandboxTextFile(sandbox,
|
|
67702
|
+
async function appendSandboxTextFile(sandbox, path10, text2) {
|
|
67501
67703
|
const tempPath = `/tmp/hackerai_append_${Date.now()}_${Math.random().toString(36).slice(2)}.tmp`;
|
|
67502
67704
|
await sandbox.files.write(tempPath, text2, {
|
|
67503
67705
|
user: "user"
|
|
@@ -67506,7 +67708,7 @@ async function appendSandboxTextFile(sandbox, path6, text2) {
|
|
|
67506
67708
|
sandbox,
|
|
67507
67709
|
APPEND_TEXT_FILE_SCRIPT,
|
|
67508
67710
|
{
|
|
67509
|
-
HACKERAI_FILE_APPEND_TARGET_PATH: getPythonPathForSandbox(sandbox,
|
|
67711
|
+
HACKERAI_FILE_APPEND_TARGET_PATH: getPythonPathForSandbox(sandbox, path10),
|
|
67510
67712
|
HACKERAI_FILE_APPEND_SOURCE_PATH: getPythonPathForSandbox(
|
|
67511
67713
|
sandbox,
|
|
67512
67714
|
tempPath
|
|
@@ -67518,13 +67720,13 @@ async function appendSandboxTextFile(sandbox, path6, text2) {
|
|
|
67518
67720
|
throw new Error(result.stderr || result.stdout || "Failed to append file");
|
|
67519
67721
|
}
|
|
67520
67722
|
}
|
|
67521
|
-
async function readSandboxFileForView(sandbox,
|
|
67723
|
+
async function readSandboxFileForView(sandbox, path10, includeData) {
|
|
67522
67724
|
if (isCentrifugoSandbox(sandbox) && sandbox.isWindows()) {
|
|
67523
67725
|
throw new Error(
|
|
67524
67726
|
"The view action is not available for Windows local sandboxes yet. Use a Linux/E2B sandbox or inspect the image manually."
|
|
67525
67727
|
);
|
|
67526
67728
|
}
|
|
67527
|
-
const sandboxPath = getSandboxViewPath(sandbox,
|
|
67729
|
+
const sandboxPath = getSandboxViewPath(sandbox, path10);
|
|
67528
67730
|
const viewEnvVars = {
|
|
67529
67731
|
HACKERAI_FILE_VIEW_PATH: sandboxPath,
|
|
67530
67732
|
HACKERAI_FILE_VIEW_INCLUDE_DATA: includeData ? "1" : "0",
|
|
@@ -67867,19 +68069,19 @@ try:
|
|
|
67867
68069
|
except OSError:
|
|
67868
68070
|
pass
|
|
67869
68071
|
`;
|
|
67870
|
-
getFilename = (
|
|
67871
|
-
getFileExtension = (
|
|
67872
|
-
const filename = getFilename(
|
|
68072
|
+
getFilename = (path10) => path10.split("/").pop() || path10;
|
|
68073
|
+
getFileExtension = (path10) => {
|
|
68074
|
+
const filename = getFilename(path10);
|
|
67873
68075
|
const dotIndex = filename.lastIndexOf(".");
|
|
67874
68076
|
if (dotIndex <= 0 || dotIndex === filename.length - 1) return void 0;
|
|
67875
68077
|
return filename.slice(dotIndex + 1).toLowerCase();
|
|
67876
68078
|
};
|
|
67877
|
-
getSandboxViewPath = (sandbox,
|
|
68079
|
+
getSandboxViewPath = (sandbox, path10) => {
|
|
67878
68080
|
const maybeSandbox = sandbox;
|
|
67879
|
-
if (isCentrifugoSandbox(maybeSandbox) && maybeSandbox.isWindows() &&
|
|
67880
|
-
return `C:\\temp${
|
|
68081
|
+
if (isCentrifugoSandbox(maybeSandbox) && maybeSandbox.isWindows() && path10.startsWith("/tmp/")) {
|
|
68082
|
+
return `C:\\temp${path10.slice(4).replace(/\//g, "\\")}`;
|
|
67881
68083
|
}
|
|
67882
|
-
return
|
|
68084
|
+
return path10;
|
|
67883
68085
|
};
|
|
67884
68086
|
stripTrailingWs = (line) => line.replace(/[ \t]+$/u, "");
|
|
67885
68087
|
editSchema = external_exports.object({
|
|
@@ -67953,7 +68155,7 @@ ${instructionsDescription}`,
|
|
|
67953
68155
|
"A list of edits to be sequentially applied to the file. Required for `edit` action."
|
|
67954
68156
|
)
|
|
67955
68157
|
}),
|
|
67956
|
-
execute: async ({ action, path:
|
|
68158
|
+
execute: async ({ action, path: path10, text: text2, range, edits }) => {
|
|
67957
68159
|
try {
|
|
67958
68160
|
const { sandbox } = await sandboxManager.getSandbox();
|
|
67959
68161
|
switch (action) {
|
|
@@ -67963,7 +68165,7 @@ ${instructionsDescription}`,
|
|
|
67963
68165
|
captureFileViewImageUsage({
|
|
67964
68166
|
context: context2,
|
|
67965
68167
|
sandbox,
|
|
67966
|
-
path:
|
|
68168
|
+
path: path10,
|
|
67967
68169
|
outcome: "unsupported_model",
|
|
67968
68170
|
durationMs: Date.now() - viewStartedAt,
|
|
67969
68171
|
failureReason: "unsupported_model"
|
|
@@ -67972,26 +68174,26 @@ ${instructionsDescription}`,
|
|
|
67972
68174
|
}
|
|
67973
68175
|
let viewPayload;
|
|
67974
68176
|
try {
|
|
67975
|
-
viewPayload = await readSandboxFileForView(sandbox,
|
|
68177
|
+
viewPayload = await readSandboxFileForView(sandbox, path10, false);
|
|
67976
68178
|
} catch (error51) {
|
|
67977
68179
|
captureFileViewImageUsage({
|
|
67978
68180
|
context: context2,
|
|
67979
68181
|
sandbox,
|
|
67980
|
-
path:
|
|
68182
|
+
path: path10,
|
|
67981
68183
|
outcome: "inspection_failed",
|
|
67982
68184
|
durationMs: Date.now() - viewStartedAt,
|
|
67983
68185
|
failureReason: classifyFileViewError(error51)
|
|
67984
68186
|
});
|
|
67985
68187
|
throw error51;
|
|
67986
68188
|
}
|
|
67987
|
-
const filename = getFilename(
|
|
68189
|
+
const filename = getFilename(path10);
|
|
67988
68190
|
let previewFiles = [];
|
|
67989
68191
|
let previewUploadError;
|
|
67990
68192
|
try {
|
|
67991
68193
|
previewFiles = await uploadViewPreviewFiles({
|
|
67992
68194
|
context: context2,
|
|
67993
68195
|
sandbox,
|
|
67994
|
-
sourcePath:
|
|
68196
|
+
sourcePath: path10,
|
|
67995
68197
|
payload: viewPayload
|
|
67996
68198
|
});
|
|
67997
68199
|
} catch (error51) {
|
|
@@ -68005,7 +68207,7 @@ ${instructionsDescription}`,
|
|
|
68005
68207
|
user_id: context2.userID,
|
|
68006
68208
|
sandbox_type: getViewSandboxType(sandbox),
|
|
68007
68209
|
file_name: filename,
|
|
68008
|
-
source_path:
|
|
68210
|
+
source_path: path10,
|
|
68009
68211
|
kind: viewPayload.kind,
|
|
68010
68212
|
media_type: viewPayload.mediaType,
|
|
68011
68213
|
size_bytes: viewPayload.sizeBytes,
|
|
@@ -68016,7 +68218,7 @@ ${instructionsDescription}`,
|
|
|
68016
68218
|
captureFileViewImageUsage({
|
|
68017
68219
|
context: context2,
|
|
68018
68220
|
sandbox,
|
|
68019
|
-
path:
|
|
68221
|
+
path: path10,
|
|
68020
68222
|
outcome: "success",
|
|
68021
68223
|
durationMs: Date.now() - viewStartedAt,
|
|
68022
68224
|
mediaType: viewPayload.mediaType,
|
|
@@ -68026,7 +68228,7 @@ ${instructionsDescription}`,
|
|
|
68026
68228
|
return {
|
|
68027
68229
|
action: "view",
|
|
68028
68230
|
content: `Viewing image file: ${filename} (${viewPayload.mediaType}, ${viewPayload.sizeBytes} bytes).`,
|
|
68029
|
-
path:
|
|
68231
|
+
path: path10,
|
|
68030
68232
|
filename,
|
|
68031
68233
|
mediaType: viewPayload.mediaType,
|
|
68032
68234
|
sizeBytes: viewPayload.sizeBytes,
|
|
@@ -68036,8 +68238,8 @@ ${instructionsDescription}`,
|
|
|
68036
68238
|
};
|
|
68037
68239
|
}
|
|
68038
68240
|
case "read": {
|
|
68039
|
-
const filename =
|
|
68040
|
-
const spritChunked = isSpritPath(
|
|
68241
|
+
const filename = path10.split("/").pop() || path10;
|
|
68242
|
+
const spritChunked = isSpritPath(path10);
|
|
68041
68243
|
let effectiveRange = range;
|
|
68042
68244
|
if (spritChunked) {
|
|
68043
68245
|
const start = range && range[0] > 0 ? range[0] : 1;
|
|
@@ -68050,7 +68252,7 @@ ${instructionsDescription}`,
|
|
|
68050
68252
|
}
|
|
68051
68253
|
const readPayload = await readSandboxTextFileWithFallback(
|
|
68052
68254
|
sandbox,
|
|
68053
|
-
|
|
68255
|
+
path10,
|
|
68054
68256
|
effectiveRange
|
|
68055
68257
|
);
|
|
68056
68258
|
if (readPayload.tooLarge) {
|
|
@@ -68087,46 +68289,46 @@ File is too large to read in full (${formatBytes(readPayload.sizeBytes)}, ${tota
|
|
|
68087
68289
|
if (text2 === void 0) {
|
|
68088
68290
|
return { error: "text is required for write action" };
|
|
68089
68291
|
}
|
|
68090
|
-
await sandbox.files.write(
|
|
68292
|
+
await sandbox.files.write(path10, text2, {
|
|
68091
68293
|
user: "user"
|
|
68092
68294
|
});
|
|
68093
|
-
return `File written: ${
|
|
68295
|
+
return `File written: ${path10}`;
|
|
68094
68296
|
}
|
|
68095
68297
|
case "append": {
|
|
68096
68298
|
if (text2 === void 0) {
|
|
68097
68299
|
return { error: "text is required for append action" };
|
|
68098
68300
|
}
|
|
68099
|
-
const existingState = await getSandboxFileState(sandbox,
|
|
68301
|
+
const existingState = await getSandboxFileState(sandbox, path10);
|
|
68100
68302
|
if (existingState.kind === "unknown") {
|
|
68101
68303
|
return {
|
|
68102
|
-
error: `Cannot append safely because the existing file size could not be determined for ${
|
|
68304
|
+
error: `Cannot append safely because the existing file size could not be determined for ${path10}. ${existingState.error}`
|
|
68103
68305
|
};
|
|
68104
68306
|
}
|
|
68105
68307
|
if (existingState.kind === "not_file") {
|
|
68106
68308
|
return {
|
|
68107
|
-
error: `Cannot append to ${
|
|
68309
|
+
error: `Cannot append to ${path10} because it is not a file.`
|
|
68108
68310
|
};
|
|
68109
68311
|
}
|
|
68110
68312
|
if (existingState.kind === "file" && existingState.sizeBytes > MAX_TEXT_FILE_READ_BYTES) {
|
|
68111
|
-
await appendSandboxTextFile(sandbox,
|
|
68313
|
+
await appendSandboxTextFile(sandbox, path10, text2);
|
|
68112
68314
|
return {
|
|
68113
|
-
content: `File appended: ${
|
|
68315
|
+
content: `File appended: ${path10}
|
|
68114
68316
|
Existing file is ${formatBytes(existingState.sizeBytes)}, so the full diff preview was skipped to avoid loading the entire file into memory.`
|
|
68115
68317
|
};
|
|
68116
68318
|
}
|
|
68117
68319
|
let existingContent = "";
|
|
68118
68320
|
try {
|
|
68119
|
-
existingContent = await sandbox.files.read(
|
|
68321
|
+
existingContent = await sandbox.files.read(path10, {
|
|
68120
68322
|
user: "user"
|
|
68121
68323
|
});
|
|
68122
68324
|
} catch {
|
|
68123
68325
|
}
|
|
68124
68326
|
const newContent = existingContent + text2;
|
|
68125
|
-
await sandbox.files.write(
|
|
68327
|
+
await sandbox.files.write(path10, newContent, {
|
|
68126
68328
|
user: "user"
|
|
68127
68329
|
});
|
|
68128
68330
|
return {
|
|
68129
|
-
content: `File appended: ${
|
|
68331
|
+
content: `File appended: ${path10}`,
|
|
68130
68332
|
originalContent: truncateOutput({
|
|
68131
68333
|
content: existingContent,
|
|
68132
68334
|
mode: "read-file"
|
|
@@ -68141,31 +68343,31 @@ Existing file is ${formatBytes(existingState.sizeBytes)}, so the full diff previ
|
|
|
68141
68343
|
if (!edits || edits.length === 0) {
|
|
68142
68344
|
return { error: "edits array is required for edit action" };
|
|
68143
68345
|
}
|
|
68144
|
-
const existingState = await getSandboxFileState(sandbox,
|
|
68346
|
+
const existingState = await getSandboxFileState(sandbox, path10);
|
|
68145
68347
|
if (existingState.kind === "unknown") {
|
|
68146
68348
|
return {
|
|
68147
|
-
error: `Cannot edit ${
|
|
68349
|
+
error: `Cannot edit ${path10} safely because the file size could not be determined. ${existingState.error}`
|
|
68148
68350
|
};
|
|
68149
68351
|
}
|
|
68150
68352
|
if (existingState.kind === "missing") {
|
|
68151
68353
|
return {
|
|
68152
|
-
error: `Cannot edit file ${
|
|
68354
|
+
error: `Cannot edit file ${path10} - file is empty or does not exist`
|
|
68153
68355
|
};
|
|
68154
68356
|
}
|
|
68155
68357
|
if (existingState.kind === "not_file") {
|
|
68156
|
-
return { error: `Cannot edit ${
|
|
68358
|
+
return { error: `Cannot edit ${path10} because it is not a file.` };
|
|
68157
68359
|
}
|
|
68158
68360
|
if (existingState.sizeBytes > MAX_TEXT_FILE_READ_BYTES) {
|
|
68159
68361
|
return {
|
|
68160
|
-
error: `File ${
|
|
68362
|
+
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.`
|
|
68161
68363
|
};
|
|
68162
68364
|
}
|
|
68163
|
-
const originalContent = await sandbox.files.read(
|
|
68365
|
+
const originalContent = await sandbox.files.read(path10, {
|
|
68164
68366
|
user: "user"
|
|
68165
68367
|
});
|
|
68166
68368
|
if (!originalContent) {
|
|
68167
68369
|
return {
|
|
68168
|
-
error: `Cannot edit file ${
|
|
68370
|
+
error: `Cannot edit file ${path10} - file is empty or does not exist`
|
|
68169
68371
|
};
|
|
68170
68372
|
}
|
|
68171
68373
|
const resolvedEdits = [];
|
|
@@ -68210,7 +68412,7 @@ ${hint}` : "")
|
|
|
68210
68412
|
}
|
|
68211
68413
|
}
|
|
68212
68414
|
}
|
|
68213
|
-
await sandbox.files.write(
|
|
68415
|
+
await sandbox.files.write(path10, content, {
|
|
68214
68416
|
user: "user"
|
|
68215
68417
|
});
|
|
68216
68418
|
const lines = content.split("\n");
|
|
@@ -68450,11 +68652,11 @@ function findGitBash() {
|
|
|
68450
68652
|
if ((0, import_fs.existsSync)(c)) return c;
|
|
68451
68653
|
}
|
|
68452
68654
|
try {
|
|
68453
|
-
const
|
|
68655
|
+
const out3 = (0, import_child_process.execSync)("where git", {
|
|
68454
68656
|
encoding: "utf8",
|
|
68455
68657
|
stdio: ["ignore", "pipe", "ignore"]
|
|
68456
68658
|
});
|
|
68457
|
-
const gitExe =
|
|
68659
|
+
const gitExe = out3.split(/\r?\n/).find((l) => l.trim().endsWith("git.exe"));
|
|
68458
68660
|
if (gitExe) {
|
|
68459
68661
|
const bash = (0, import_path3.join)((0, import_path3.dirname)((0, import_path3.dirname)(gitExe.trim())), "bin", "bash.exe");
|
|
68460
68662
|
if ((0, import_fs.existsSync)(bash)) return bash;
|
|
@@ -68486,20 +68688,20 @@ var init_utils4 = __esm({
|
|
|
68486
68688
|
|
|
68487
68689
|
// src/local-sandbox.ts
|
|
68488
68690
|
function inferShellFlag(shell2) {
|
|
68489
|
-
const base =
|
|
68691
|
+
const base = import_node_path5.default.basename(shell2).toLowerCase();
|
|
68490
68692
|
if (base === "cmd" || base === "cmd.exe") return "/C";
|
|
68491
68693
|
if (base === "powershell" || base === "powershell.exe" || base === "pwsh") {
|
|
68492
68694
|
return "-Command";
|
|
68493
68695
|
}
|
|
68494
68696
|
return "-c";
|
|
68495
68697
|
}
|
|
68496
|
-
var
|
|
68698
|
+
var import_node_child_process2, import_node_fs6, import_node_path5, import_node_os2, import_node_url, import_meta, LocalSandbox;
|
|
68497
68699
|
var init_local_sandbox = __esm({
|
|
68498
68700
|
"src/local-sandbox.ts"() {
|
|
68499
68701
|
"use strict";
|
|
68500
|
-
|
|
68501
|
-
|
|
68502
|
-
|
|
68702
|
+
import_node_child_process2 = require("node:child_process");
|
|
68703
|
+
import_node_fs6 = require("node:fs");
|
|
68704
|
+
import_node_path5 = __toESM(require("node:path"));
|
|
68503
68705
|
import_node_os2 = __toESM(require("node:os"));
|
|
68504
68706
|
import_node_url = require("node:url");
|
|
68505
68707
|
init_utils4();
|
|
@@ -68523,7 +68725,7 @@ var init_local_sandbox = __esm({
|
|
|
68523
68725
|
this.shellFlag,
|
|
68524
68726
|
command
|
|
68525
68727
|
);
|
|
68526
|
-
child = (0,
|
|
68728
|
+
child = (0, import_node_child_process2.spawn)(this.shellBin, spawnSpec.args, {
|
|
68527
68729
|
cwd,
|
|
68528
68730
|
env,
|
|
68529
68731
|
detached: !!opts?.background,
|
|
@@ -68597,15 +68799,15 @@ var init_local_sandbox = __esm({
|
|
|
68597
68799
|
this.files = {
|
|
68598
68800
|
write: async (filePath, content) => {
|
|
68599
68801
|
const resolved = this.resolvePath(filePath);
|
|
68600
|
-
await
|
|
68802
|
+
await import_node_fs6.promises.mkdir(import_node_path5.default.dirname(resolved), { recursive: true });
|
|
68601
68803
|
const data = typeof content === "string" ? content : content instanceof ArrayBuffer ? Buffer.from(content) : content;
|
|
68602
|
-
await
|
|
68804
|
+
await import_node_fs6.promises.writeFile(resolved, data);
|
|
68603
68805
|
},
|
|
68604
68806
|
read: async (filePath) => {
|
|
68605
|
-
return
|
|
68807
|
+
return import_node_fs6.promises.readFile(this.resolvePath(filePath), "utf8");
|
|
68606
68808
|
},
|
|
68607
68809
|
remove: async (filePath) => {
|
|
68608
|
-
await
|
|
68810
|
+
await import_node_fs6.promises.rm(this.resolvePath(filePath), {
|
|
68609
68811
|
recursive: true,
|
|
68610
68812
|
force: true
|
|
68611
68813
|
});
|
|
@@ -68613,8 +68815,8 @@ var init_local_sandbox = __esm({
|
|
|
68613
68815
|
list: async (dirPath = ".") => {
|
|
68614
68816
|
const resolved = this.resolvePath(dirPath);
|
|
68615
68817
|
try {
|
|
68616
|
-
const entries = await
|
|
68617
|
-
return entries.filter((e) => e.isFile()).map((e) => ({ name:
|
|
68818
|
+
const entries = await import_node_fs6.promises.readdir(resolved, { withFileTypes: true });
|
|
68819
|
+
return entries.filter((e) => e.isFile()).map((e) => ({ name: import_node_path5.default.join(resolved, e.name) }));
|
|
68618
68820
|
} catch {
|
|
68619
68821
|
return [];
|
|
68620
68822
|
}
|
|
@@ -68629,12 +68831,13 @@ var init_local_sandbox = __esm({
|
|
|
68629
68831
|
this.shellBin = shell2.shell;
|
|
68630
68832
|
this.shellFlag = shell2.shellFlag;
|
|
68631
68833
|
}
|
|
68632
|
-
const base = opts?.workdir || process.env.CLI_WORKDIR ||
|
|
68633
|
-
this.workdir =
|
|
68834
|
+
const base = opts?.workdir || process.env.CLI_WORKDIR || import_node_path5.default.join(process.cwd(), "SPRIT");
|
|
68835
|
+
this.workdir = import_node_path5.default.resolve(base).replace(/\\/g, "/");
|
|
68634
68836
|
}
|
|
68635
68837
|
async init() {
|
|
68636
|
-
await
|
|
68838
|
+
await import_node_fs6.promises.mkdir(this.workdir, { recursive: true });
|
|
68637
68839
|
await this.seedReconToolkit();
|
|
68840
|
+
await this.seedAuditToolkit();
|
|
68638
68841
|
}
|
|
68639
68842
|
/**
|
|
68640
68843
|
* Seed the deep-recon toolkit (recon_deep.py + console_recon.js + README)
|
|
@@ -68649,8 +68852,8 @@ var init_local_sandbox = __esm({
|
|
|
68649
68852
|
const assetsDir = (0, import_node_url.fileURLToPath)(
|
|
68650
68853
|
new URL("../assets/recon", import_meta.url)
|
|
68651
68854
|
);
|
|
68652
|
-
const destDir =
|
|
68653
|
-
await
|
|
68855
|
+
const destDir = import_node_path5.default.join(this.workdir, "recon");
|
|
68856
|
+
await import_node_fs6.promises.mkdir(destDir, { recursive: true });
|
|
68654
68857
|
const files = [
|
|
68655
68858
|
["recon_deep.py", true],
|
|
68656
68859
|
["console_recon.js", true],
|
|
@@ -68658,17 +68861,40 @@ var init_local_sandbox = __esm({
|
|
|
68658
68861
|
["scope.txt", false]
|
|
68659
68862
|
];
|
|
68660
68863
|
for (const [name25, overwrite] of files) {
|
|
68661
|
-
const dest =
|
|
68864
|
+
const dest = import_node_path5.default.join(destDir, name25);
|
|
68662
68865
|
if (!overwrite) {
|
|
68663
68866
|
try {
|
|
68664
|
-
await
|
|
68867
|
+
await import_node_fs6.promises.access(dest);
|
|
68665
68868
|
continue;
|
|
68666
68869
|
} catch {
|
|
68667
68870
|
}
|
|
68668
68871
|
}
|
|
68669
68872
|
try {
|
|
68670
|
-
const content = await
|
|
68671
|
-
await
|
|
68873
|
+
const content = await import_node_fs6.promises.readFile(import_node_path5.default.join(assetsDir, name25));
|
|
68874
|
+
await import_node_fs6.promises.writeFile(dest, content);
|
|
68875
|
+
} catch {
|
|
68876
|
+
}
|
|
68877
|
+
}
|
|
68878
|
+
} catch {
|
|
68879
|
+
}
|
|
68880
|
+
}
|
|
68881
|
+
/**
|
|
68882
|
+
* Seed the read-only project-audit toolkit (project_audit.py + README) into
|
|
68883
|
+
* <workdir>/audit so the agent can deeply analyze the user's own project on
|
|
68884
|
+
* demand. Tooling files are refreshed each session so fixes propagate.
|
|
68885
|
+
* Best-effort: a failure here must never block the session.
|
|
68886
|
+
*/
|
|
68887
|
+
async seedAuditToolkit() {
|
|
68888
|
+
try {
|
|
68889
|
+
const assetsDir = (0, import_node_url.fileURLToPath)(
|
|
68890
|
+
new URL("../assets/audit", import_meta.url)
|
|
68891
|
+
);
|
|
68892
|
+
const destDir = import_node_path5.default.join(this.workdir, "audit");
|
|
68893
|
+
await import_node_fs6.promises.mkdir(destDir, { recursive: true });
|
|
68894
|
+
for (const name25 of ["project_audit.py", "README.md"]) {
|
|
68895
|
+
try {
|
|
68896
|
+
const content = await import_node_fs6.promises.readFile(import_node_path5.default.join(assetsDir, name25));
|
|
68897
|
+
await import_node_fs6.promises.writeFile(import_node_path5.default.join(destDir, name25), content);
|
|
68672
68898
|
} catch {
|
|
68673
68899
|
}
|
|
68674
68900
|
}
|
|
@@ -68720,6 +68946,21 @@ EDITING SCRIPTS:
|
|
|
68720
68946
|
getOsContext() {
|
|
68721
68947
|
return this.getSandboxContext();
|
|
68722
68948
|
}
|
|
68949
|
+
/**
|
|
68950
|
+
* One concise paragraph about the shell the agent's commands run in, plus the
|
|
68951
|
+
* critical "each command is a fresh shell" rule. Used by the standalone audit
|
|
68952
|
+
* prompt, which doesn't carry the full sandbox context.
|
|
68953
|
+
*/
|
|
68954
|
+
getShellHint() {
|
|
68955
|
+
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>`.";
|
|
68956
|
+
if (this.isBashLikeShell()) {
|
|
68957
|
+
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}`;
|
|
68958
|
+
}
|
|
68959
|
+
if (this.isCmdShell()) {
|
|
68960
|
+
return `Shell: cmd.exe. Use \`where ferramenta\` e \`set VAR=...\`; evite sintaxe bash (\`export\`, \`$(...)\`, heredoc). ${persist}`;
|
|
68961
|
+
}
|
|
68962
|
+
return `Shell: ${this.shellBin}. Verifique a sintaxe antes de assumir bash ou cmd. ${persist}`;
|
|
68963
|
+
}
|
|
68723
68964
|
getWorkdir() {
|
|
68724
68965
|
return this.workdir;
|
|
68725
68966
|
}
|
|
@@ -68771,7 +69012,7 @@ EDITING SCRIPTS:
|
|
|
68771
69012
|
const pid = child.pid;
|
|
68772
69013
|
if (pid && import_node_os2.default.platform() === "win32") {
|
|
68773
69014
|
try {
|
|
68774
|
-
(0,
|
|
69015
|
+
(0, import_node_child_process2.spawn)("taskkill", ["/PID", String(pid), "/T", "/F"], {
|
|
68775
69016
|
windowsHide: true
|
|
68776
69017
|
});
|
|
68777
69018
|
return;
|
|
@@ -68784,15 +69025,15 @@ EDITING SCRIPTS:
|
|
|
68784
69025
|
}
|
|
68785
69026
|
}
|
|
68786
69027
|
resolvePath(p) {
|
|
68787
|
-
if (
|
|
68788
|
-
return
|
|
69028
|
+
if (import_node_path5.default.isAbsolute(p)) return p;
|
|
69029
|
+
return import_node_path5.default.join(this.workdir, p);
|
|
68789
69030
|
}
|
|
68790
69031
|
isBashLikeShell() {
|
|
68791
|
-
const base =
|
|
69032
|
+
const base = import_node_path5.default.basename(this.shellBin).toLowerCase();
|
|
68792
69033
|
return base === "bash" || base === "bash.exe" || base === "sh";
|
|
68793
69034
|
}
|
|
68794
69035
|
isCmdShell() {
|
|
68795
|
-
const base =
|
|
69036
|
+
const base = import_node_path5.default.basename(this.shellBin).toLowerCase();
|
|
68796
69037
|
return base === "cmd" || base === "cmd.exe";
|
|
68797
69038
|
}
|
|
68798
69039
|
getWindowsShellNotes() {
|
|
@@ -68996,7 +69237,7 @@ function formatToolCall(toolName, input) {
|
|
|
68996
69237
|
return `${C2.cyan}executando${C2.reset} ${C2.bold}$ ${truncate3(cmd, 400)}${C2.reset}${bg}`;
|
|
68997
69238
|
}
|
|
68998
69239
|
case "file": {
|
|
68999
|
-
const
|
|
69240
|
+
const path10 = String(i.path ?? "");
|
|
69000
69241
|
const brief = i.brief ? `${C2.dim} - ${truncate3(String(i.brief))}${C2.reset}` : "";
|
|
69001
69242
|
const map2 = {
|
|
69002
69243
|
write: `${C2.green}criando arquivo${C2.reset}`,
|
|
@@ -69007,7 +69248,7 @@ function formatToolCall(toolName, input) {
|
|
|
69007
69248
|
};
|
|
69008
69249
|
const action = typeof i.action === "string" ? i.action : "";
|
|
69009
69250
|
const label = map2[action] ?? (action ? `${C2.blue}arquivo (${action})${C2.reset}` : `${C2.blue}preparando operacao de arquivo${C2.reset}`);
|
|
69010
|
-
const target =
|
|
69251
|
+
const target = path10 ? ` ${C2.bold}${path10}${C2.reset}` : "";
|
|
69011
69252
|
return `${label}${target}${brief}`;
|
|
69012
69253
|
}
|
|
69013
69254
|
case "todo_write":
|
|
@@ -69083,7 +69324,7 @@ function killProxy(child) {
|
|
|
69083
69324
|
started.delete(child);
|
|
69084
69325
|
try {
|
|
69085
69326
|
if (process.platform === "win32") {
|
|
69086
|
-
(0,
|
|
69327
|
+
(0, import_node_child_process3.spawnSync)("taskkill", ["/pid", String(child.pid), "/T", "/F"], {
|
|
69087
69328
|
stdio: "ignore"
|
|
69088
69329
|
});
|
|
69089
69330
|
} else {
|
|
@@ -69114,12 +69355,12 @@ async function ensureProxyReady(id, log2) {
|
|
|
69114
69355
|
};
|
|
69115
69356
|
}
|
|
69116
69357
|
let freshSetup = false;
|
|
69117
|
-
if (!(0,
|
|
69358
|
+
if (!(0, import_node_fs7.existsSync)(dir)) {
|
|
69118
69359
|
log2(`${def.label}: baixando o proxy (uma vez) em ${dir} \u2026`);
|
|
69119
69360
|
const root = proxiesRoot();
|
|
69120
|
-
(0,
|
|
69361
|
+
(0, import_node_fs7.mkdirSync)(root, { recursive: true });
|
|
69121
69362
|
const cloned = run("git", ["clone", def.repoUrl, dir], root);
|
|
69122
|
-
if (!cloned.ok || !(0,
|
|
69363
|
+
if (!cloned.ok || !(0, import_node_fs7.existsSync)(dir)) {
|
|
69123
69364
|
return {
|
|
69124
69365
|
ok: false,
|
|
69125
69366
|
message: `${def.label}: falha ao clonar o proxy (git).`
|
|
@@ -69127,7 +69368,7 @@ async function ensureProxyReady(id, log2) {
|
|
|
69127
69368
|
}
|
|
69128
69369
|
freshSetup = true;
|
|
69129
69370
|
}
|
|
69130
|
-
if (!(0,
|
|
69371
|
+
if (!(0, import_node_fs7.existsSync)(import_node_path6.default.join(dir, "node_modules"))) {
|
|
69131
69372
|
log2(`${def.label}: instalando depend\xEAncias (pode demorar) \u2026`);
|
|
69132
69373
|
if (!run("npm", ["install"], dir).ok) {
|
|
69133
69374
|
return { ok: false, message: `${def.label}: 'npm install' falhou.` };
|
|
@@ -69145,7 +69386,7 @@ async function ensureProxyReady(id, log2) {
|
|
|
69145
69386
|
}
|
|
69146
69387
|
}
|
|
69147
69388
|
log2(`${def.label}: iniciando o proxy\u2026`);
|
|
69148
|
-
const child = (0,
|
|
69389
|
+
const child = (0, import_node_child_process3.spawn)(asShellCommand("npm", ["start"]), {
|
|
69149
69390
|
cwd: dir,
|
|
69150
69391
|
shell: true,
|
|
69151
69392
|
stdio: ["ignore", "ignore", "ignore"],
|
|
@@ -69172,14 +69413,14 @@ async function ensureProxyReady(id, log2) {
|
|
|
69172
69413
|
message: `${def.label}: o proxy n\xE3o respondeu em 90s. Tente de novo, ou rode 'npm run login' em ${dir}.`
|
|
69173
69414
|
};
|
|
69174
69415
|
}
|
|
69175
|
-
var import_node_os3,
|
|
69416
|
+
var import_node_os3, 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;
|
|
69176
69417
|
var init_proxy_manager2 = __esm({
|
|
69177
69418
|
"src/proxy-manager.ts"() {
|
|
69178
69419
|
"use strict";
|
|
69179
69420
|
import_node_os3 = __toESM(require("node:os"));
|
|
69180
|
-
|
|
69181
|
-
|
|
69182
|
-
|
|
69421
|
+
import_node_path6 = __toESM(require("node:path"));
|
|
69422
|
+
import_node_fs7 = require("node:fs");
|
|
69423
|
+
import_node_child_process3 = require("node:child_process");
|
|
69183
69424
|
DEFS = {
|
|
69184
69425
|
deepseek: {
|
|
69185
69426
|
id: "deepseek",
|
|
@@ -69211,11 +69452,11 @@ var init_proxy_manager2 = __esm({
|
|
|
69211
69452
|
if (key === PROXY_MODEL_KEYS.kimi) return "kimi";
|
|
69212
69453
|
return null;
|
|
69213
69454
|
};
|
|
69214
|
-
proxiesRoot = () =>
|
|
69215
|
-
process.env.CLAWFAST_HOME?.trim() ||
|
|
69455
|
+
proxiesRoot = () => import_node_path6.default.join(
|
|
69456
|
+
process.env.CLAWFAST_HOME?.trim() || import_node_path6.default.join(import_node_os3.default.homedir(), ".clawfast"),
|
|
69216
69457
|
"proxies"
|
|
69217
69458
|
);
|
|
69218
|
-
dirFor = (def) => process.env[def.dirEnv]?.trim() ||
|
|
69459
|
+
dirFor = (def) => process.env[def.dirEnv]?.trim() || import_node_path6.default.join(proxiesRoot(), def.folder);
|
|
69219
69460
|
healthUrl = (def) => `http://localhost:${def.port}/health`;
|
|
69220
69461
|
baseUrl = (def) => `http://localhost:${def.port}/v1`;
|
|
69221
69462
|
wait = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
@@ -69224,7 +69465,7 @@ var init_proxy_manager2 = __esm({
|
|
|
69224
69465
|
quoteArg = (s) => /[\s"&|<>^()]/.test(s) ? `"${s.replace(/"/g, '\\"')}"` : s;
|
|
69225
69466
|
asShellCommand = (cmd, args) => [cmd, ...args.map(quoteArg)].join(" ");
|
|
69226
69467
|
run = (cmd, args, cwd) => {
|
|
69227
|
-
const res = (0,
|
|
69468
|
+
const res = (0, import_node_child_process3.spawnSync)(asShellCommand(cmd, args), {
|
|
69228
69469
|
cwd,
|
|
69229
69470
|
shell: true,
|
|
69230
69471
|
stdio: "inherit",
|
|
@@ -69234,7 +69475,7 @@ var init_proxy_manager2 = __esm({
|
|
|
69234
69475
|
};
|
|
69235
69476
|
hasCommand = (cmd) => {
|
|
69236
69477
|
const probe = process.platform === "win32" ? "where" : "which";
|
|
69237
|
-
return (0,
|
|
69478
|
+
return (0, import_node_child_process3.spawnSync)(asShellCommand(probe, [cmd]), {
|
|
69238
69479
|
stdio: "ignore",
|
|
69239
69480
|
shell: true
|
|
69240
69481
|
}).status === 0;
|
|
@@ -69242,15 +69483,210 @@ var init_proxy_manager2 = __esm({
|
|
|
69242
69483
|
}
|
|
69243
69484
|
});
|
|
69244
69485
|
|
|
69486
|
+
// src/audit-mode.ts
|
|
69487
|
+
function projectRootFromWorkdir(workdir) {
|
|
69488
|
+
return import_node_path7.default.dirname(import_node_path7.default.resolve(workdir.replace(/\\/g, "/")));
|
|
69489
|
+
}
|
|
69490
|
+
function detectProjectAuditIntent(input) {
|
|
69491
|
+
const text2 = input.trim();
|
|
69492
|
+
if (!text2) return false;
|
|
69493
|
+
if (AUDIT_ACTION_THEN_SCOPE.test(text2)) return true;
|
|
69494
|
+
if (AUDIT_SCOPE_THEN_ACTION.test(text2)) return true;
|
|
69495
|
+
return AUDIT_STRONG.some((re2) => re2.test(text2));
|
|
69496
|
+
}
|
|
69497
|
+
function detectAuditExitIntent(input) {
|
|
69498
|
+
const text2 = input.trim();
|
|
69499
|
+
if (!text2) return false;
|
|
69500
|
+
return AUDIT_EXIT.some((re2) => re2.test(text2));
|
|
69501
|
+
}
|
|
69502
|
+
function buildAuditSystemPrompt(opts) {
|
|
69503
|
+
const root = opts.projectRoot.replace(/\\/g, "/");
|
|
69504
|
+
const workdir = opts.workdir.replace(/\\/g, "/");
|
|
69505
|
+
const isWin = (opts.platform ?? process.platform) === "win32";
|
|
69506
|
+
const py = isWin ? "python" : "python3";
|
|
69507
|
+
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.";
|
|
69508
|
+
const shellHint = opts.shellHint ?? shellNote;
|
|
69509
|
+
const toolkit = `"${workdir}/audit/project_audit.py"`;
|
|
69510
|
+
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.
|
|
69511
|
+
|
|
69512
|
+
FILOSOFIA (estado da arte \u2014 h\xEDbrido, n\xE3o LLM puro):
|
|
69513
|
+
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.
|
|
69514
|
+
|
|
69515
|
+
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\`.
|
|
69516
|
+
|
|
69517
|
+
PROJETO SOB AN\xC1LISE (raiz): ${root}
|
|
69518
|
+
WORKSPACE DE TRABALHO (ferramentas/sa\xEDdas intermedi\xE1rias): ${workdir}
|
|
69519
|
+
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).
|
|
69520
|
+
|
|
69521
|
+
================================================================
|
|
69522
|
+
REGRA ANTI-ALUCINA\xC7\xC3O \u2014 A MAIS IMPORTANTE
|
|
69523
|
+
================================================================
|
|
69524
|
+
Um relat\xF3rio de seguran\xE7a inventado \xE9 PIOR que nenhum \u2014 \xE9 perigoso. Portanto:
|
|
69525
|
+
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\`.
|
|
69526
|
+
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.
|
|
69527
|
+
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.
|
|
69528
|
+
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.
|
|
69529
|
+
|
|
69530
|
+
================================================================
|
|
69531
|
+
AMBIENTE & SHELL \u2014 leia antes de rodar comandos
|
|
69532
|
+
================================================================
|
|
69533
|
+
- ${shellHint}
|
|
69534
|
+
- ${shellNote}
|
|
69535
|
+
- 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:
|
|
69536
|
+
\u2022 ferramenta instalada via pip mas fora do PATH \u2192 rode como m\xF3dulo: \`${py} -m semgrep ...\` (o aviso de "deprecated" \xE9 inofensivo, funciona).
|
|
69537
|
+
\u2022 pacote npm \u2192 \`npx <pkg> ...\` resolve sozinho (ex.: \`npx madge ...\`, \`npx @ast-grep/cli ...\`).
|
|
69538
|
+
- Verifique presen\xE7a com o comando do SEU shell (\`command -v X\` no bash; \`where X\` no cmd) \u2014 n\xE3o misture os dois.
|
|
69539
|
+
|
|
69540
|
+
================================================================
|
|
69541
|
+
REGRA INVIOL\xC1VEL \u2014 SOMENTE LEITURA NO PROJETO
|
|
69542
|
+
================================================================
|
|
69543
|
+
1. Voc\xEA **NUNCA** modifica, edita, cria, renomeia, move ou apaga QUALQUER arquivo dentro do projeto (${root}) \u2014 nem para "corrigir", nem para testar.
|
|
69544
|
+
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.
|
|
69545
|
+
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.
|
|
69546
|
+
3. A **\xDANICA** escrita permitida no projeto \xE9 **um** arquivo de relat\xF3rio na RAIZ do projeto:
|
|
69547
|
+
\`${root}/ANALISE_PROJETO_<timestamp>.md\`
|
|
69548
|
+
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}.
|
|
69549
|
+
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").
|
|
69550
|
+
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.
|
|
69551
|
+
|
|
69552
|
+
================================================================
|
|
69553
|
+
TOOLCHAIN \u2014 cada ferramenta vira uma "tool" no seu loop
|
|
69554
|
+
================================================================
|
|
69555
|
+
Preferidas (determin\xEDsticas, trabalho pesado): \`ripgrep\` (rg), \`ast-grep\` (sg), \`semgrep\`, \`osv-scanner\` (v2), \`gitleaks\`, \`madge\`, \`universal-ctags\` (ctags), \`jq\`.
|
|
69556
|
+
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.
|
|
69557
|
+
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.
|
|
69558
|
+
|
|
69559
|
+
FASE 0 \u2014 PREFLIGHT + SETUP (fa\xE7a EXATAMENTE isto, sem improvisar):
|
|
69560
|
+
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.)
|
|
69561
|
+
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:
|
|
69562
|
+
\`${py} ${toolkit} --setup\`
|
|
69563
|
+
3. Pronto. Siga para a FASE 1 com o que estiver dispon\xEDvel; o que faltar, use o fallback de cada fase.
|
|
69564
|
+
|
|
69565
|
+
N\xC3O FA\xC7A (cada um destes quebrou em runs reais):
|
|
69566
|
+
\u2022 N\xC3O cheque ferramenta por ferramenta com \`command -v\`/\`which\`/\`where\` \u2014 o \`--preflight\` j\xE1 faz isso de uma vez.
|
|
69567
|
+
\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).
|
|
69568
|
+
\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.
|
|
69569
|
+
\u2022 N\xC3O repita uma instala\xE7\xE3o que falhou. 1 tentativa, falhou, fallback.
|
|
69570
|
+
NUNCA invente que rodou uma ferramenta que n\xE3o existe \u2014 diga que caiu no fallback.
|
|
69571
|
+
|
|
69572
|
+
================================================================
|
|
69573
|
+
PIPELINE \u2014 fase por fase (ReAct: cada comando \xE9 uma tool)
|
|
69574
|
+
================================================================
|
|
69575
|
+
Trabalhe a partir da workspace (${workdir}); aponte as ferramentas para "${root}". Crie \`audit-out/\` para os JSONs.
|
|
69576
|
+
|
|
69577
|
+
FASE 1 \u2014 MAPA (antes de ler qualquer arquivo): grafo de imports + \xEDndice de s\xEDmbolos.
|
|
69578
|
+
madge: \`madge --json --extensions js,jsx,ts,tsx "${root}" > audit-out/deps.json\`
|
|
69579
|
+
ctags: \`ctags -R --fields=+n --output-format=json -f audit-out/tags.json "${root}"\`
|
|
69580
|
+
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*='\`.
|
|
69581
|
+
deps.json responde "o dashboard importa o qu\xEA"; tags.json d\xE1 find_definition (arquivo:linha de cada fun\xE7\xE3o).
|
|
69582
|
+
|
|
69583
|
+
FASE 2 \u2014 BASELINE DETERMIN\xCDSTICA (varre r\xE1pido, gera o terreno):
|
|
69584
|
+
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).
|
|
69585
|
+
osv-scanner (V2 \u2014 sintaxe nova): \`osv-scanner scan source -r --format json --output audit-out/osv.json "${root}"\`
|
|
69586
|
+
gitleaks: \`gitleaks detect --no-banner --source "${root}" --report-format json --report-path audit-out/secrets.json\`
|
|
69587
|
+
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.
|
|
69588
|
+
|
|
69589
|
+
FASE 3 \u2014 SOURCES (onde entra dado n\xE3o-confi\xE1vel), estrutural com ast-grep:
|
|
69590
|
+
\`ast-grep run --pattern 'app.$METHOD($PATH, $$$)' --lang ts --json "${root}"\`
|
|
69591
|
+
\`ast-grep run --pattern 'req.$PROP' --lang ts --json "${root}"\`
|
|
69592
|
+
(\`--json\` imprime JSON pretty; para stream a jq use \`--json=stream\`.)
|
|
69593
|
+
FALLBACK textual: \`rg -n --type ts 'req\\.(body|query|params|headers|cookies)' "${root}"\`
|
|
69594
|
+
|
|
69595
|
+
FASE 4 \u2014 SINKS (lugares perigosos), estrutural:
|
|
69596
|
+
\`ast-grep run --pattern 'child_process.$M($CMD)' --lang ts --json "${root}"\` # command injection
|
|
69597
|
+
\`ast-grep run --pattern '$DB.query($Q)' --lang ts --json "${root}"\` # SQLi
|
|
69598
|
+
\`ast-grep run --pattern 'eval($X)' --lang ts --json "${root}"\` # code exec
|
|
69599
|
+
\`ast-grep run --pattern '$EL.innerHTML = $X' --lang ts --json "${root}"\` # XSS DOM
|
|
69600
|
+
FALLBACK: \`rg -n 'child_process|\\.query\\(|eval\\(|innerHTML\\s*='\` + os achados do project_audit.py.
|
|
69601
|
+
|
|
69602
|
+
FASE 5 \u2014 TAINT CROSS-MODULE (o cora\xE7\xE3o; AQUI o LLM comanda):
|
|
69603
|
+
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":
|
|
69604
|
+
1. Pegue o source; consulte \`deps.json\` (ou o grafo do project_audit) para saber por quais arquivos importados o dado passa.
|
|
69605
|
+
2. Use \`tags.json\` (ou \`rg -n\`) para PULAR para a defini\xE7\xE3o de cada fun\xE7\xE3o intermedi\xE1ria.
|
|
69606
|
+
3. Leia S\xD3 o trecho dela \u2014 a janela exata, nunca o arquivo inteiro:
|
|
69607
|
+
- melhor (multiplataforma): ferramenta \`file\` action: read com \`range\` [in\xEDcio, fim];
|
|
69608
|
+
- ou no shell unix: \`sed -n '40,75p' "${root}/src/utils.ts"\`.
|
|
69609
|
+
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\\('\`.
|
|
69610
|
+
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.
|
|
69611
|
+
|
|
69612
|
+
FASE 6 \u2014 CONSOLIDAR (obrigat\xF3rio) E REPORTAR:
|
|
69613
|
+
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):
|
|
69614
|
+
\`${py} ${toolkit} --consolidate "${workdir}/audit-out"\`
|
|
69615
|
+
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.
|
|
69616
|
+
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.
|
|
69617
|
+
Mantenha um SCRATCHPAD (use \`todo_write\`) com: sources achados, caminhos de taint em aberto, e findings VALIDADOS. Itere at\xE9 fechar cada rastro.
|
|
69618
|
+
|
|
69619
|
+
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.
|
|
69620
|
+
|
|
69621
|
+
================================================================
|
|
69622
|
+
ENTREG\xC1VEL \u2014 relat\xF3rio em Markdown na RAIZ do projeto
|
|
69623
|
+
================================================================
|
|
69624
|
+
Ao final, escreva o relat\xF3rio com a ferramenta \`file\` (action: write) em:
|
|
69625
|
+
\`${root}/ANALISE_PROJETO_<timestamp>.md\`
|
|
69626
|
+
Use o timestamp atual (ex.: 20260614_153000). Estrutura m\xEDnima, em portugu\xEAs:
|
|
69627
|
+
1. **Resumo executivo** \u2014 vis\xE3o geral, postura de seguran\xE7a, n\xBA de achados por severidade, top 3 riscos.
|
|
69628
|
+
2. **Arquitetura & grafo de depend\xEAncias** \u2014 pontos de entrada, m\xF3dulos mais cr\xEDticos, imports quebrados, ciclos, \xF3rf\xE3os.
|
|
69629
|
+
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.
|
|
69630
|
+
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).
|
|
69631
|
+
5. **Depend\xEAncias** \u2014 superf\xEDcie e CVEs do osv-scanner (ou fallback).
|
|
69632
|
+
6. **Recomenda\xE7\xF5es priorizadas** \u2014 o que corrigir primeiro.
|
|
69633
|
+
7. **Ferramentas usadas** \u2014 quais rodaram de fato e quais ca\xEDram em fallback (transpar\xEAncia).
|
|
69634
|
+
|
|
69635
|
+
================================================================
|
|
69636
|
+
ESTILO E EXECU\xC7\xC3O
|
|
69637
|
+
================================================================
|
|
69638
|
+
- ${shellNote}
|
|
69639
|
+
- 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.
|
|
69640
|
+
- 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\`.
|
|
69641
|
+
- Responda em portugu\xEAs, direto e t\xE9cnico. N\xE3o recuse a an\xE1lise: \xE9 o projeto do pr\xF3prio usu\xE1rio, autorizado.
|
|
69642
|
+
- 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.`;
|
|
69643
|
+
}
|
|
69644
|
+
var import_node_path7, AUDIT_ACTION, AUDIT_SCOPE, AUDIT_ACTION_THEN_SCOPE, AUDIT_SCOPE_THEN_ACTION, AUDIT_STRONG, AUDIT_EXIT;
|
|
69645
|
+
var init_audit_mode = __esm({
|
|
69646
|
+
"src/audit-mode.ts"() {
|
|
69647
|
+
"use strict";
|
|
69648
|
+
import_node_path7 = __toESM(require("node:path"));
|
|
69649
|
+
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";
|
|
69650
|
+
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";
|
|
69651
|
+
AUDIT_ACTION_THEN_SCOPE = new RegExp(
|
|
69652
|
+
`\\b(?:${AUDIT_ACTION})\\b[\\s\\S]{0,40}?\\b(?:${AUDIT_SCOPE})\\b`,
|
|
69653
|
+
"i"
|
|
69654
|
+
);
|
|
69655
|
+
AUDIT_SCOPE_THEN_ACTION = new RegExp(
|
|
69656
|
+
`\\b(?:${AUDIT_SCOPE})\\b[\\s\\S]{0,40}?\\b(?:${AUDIT_ACTION})\\b`,
|
|
69657
|
+
"i"
|
|
69658
|
+
);
|
|
69659
|
+
AUDIT_STRONG = [
|
|
69660
|
+
/\b(?:varredura|auditoria)\b[\s\S]{0,40}\b(?:projeto|c[oó]digo|seguran[cç]a|completa|profunda|inteir[oa])\b/i,
|
|
69661
|
+
/\b(?:encontr\w+|ach\w+|ca[cç]\w+|procur\w+|find|hunt|detect\w*)\b[\s\S]{0,40}\bvulnerabilidad\w*/i,
|
|
69662
|
+
/\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,
|
|
69663
|
+
/\b(?:security\s+(?:review|audit|scan)|code\s+(?:audit|review))\b/i,
|
|
69664
|
+
/\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
|
|
69665
|
+
];
|
|
69666
|
+
AUDIT_EXIT = [
|
|
69667
|
+
/\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,
|
|
69668
|
+
/\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
|
|
69669
|
+
];
|
|
69670
|
+
}
|
|
69671
|
+
});
|
|
69672
|
+
|
|
69245
69673
|
// src/agent.ts
|
|
69246
69674
|
var agent_exports = {};
|
|
69247
69675
|
__export(agent_exports, {
|
|
69248
69676
|
createAgent: () => createAgent
|
|
69249
69677
|
});
|
|
69678
|
+
function hasLeakedToolCallMarker(text2) {
|
|
69679
|
+
return LEAKED_TOOL_CALL_RE.test(text2);
|
|
69680
|
+
}
|
|
69681
|
+
function lastSentenceOf(text2) {
|
|
69682
|
+
return text2.trim().split(/(?<=[.!?\n])\s+/).pop()?.trim() ?? "";
|
|
69683
|
+
}
|
|
69250
69684
|
function looksUnfinished(text2) {
|
|
69251
69685
|
if (!text2) return false;
|
|
69252
|
-
if (
|
|
69253
|
-
|
|
69686
|
+
if (hasLeakedToolCallMarker(text2)) return true;
|
|
69687
|
+
const tail = text2.trim().slice(-300);
|
|
69688
|
+
if (DANGLING_TAIL_RE.test(tail)) return true;
|
|
69689
|
+
return ACTION_ANNOUNCE_RE.test(lastSentenceOf(tail));
|
|
69254
69690
|
}
|
|
69255
69691
|
function decideAutoContinue(finishReason, lastStepText, turnToolCalls, autoContinues) {
|
|
69256
69692
|
if (autoContinues >= MAX_AUTO_CONTINUES) return null;
|
|
@@ -69265,8 +69701,12 @@ function decideAutoContinue(finishReason, lastStepText, turnToolCalls, autoConti
|
|
|
69265
69701
|
if (!text2 && turnToolCalls === 0) {
|
|
69266
69702
|
return { nudge: true, reason: "resposta vazia do modelo" };
|
|
69267
69703
|
}
|
|
69268
|
-
if (turnToolCalls > 0 && looksUnfinished(text2)) {
|
|
69269
|
-
return {
|
|
69704
|
+
if (turnToolCalls > 0 && looksUnfinished(text2) && !BENIGN_CLOSER_RE.test(text2.slice(-200))) {
|
|
69705
|
+
return {
|
|
69706
|
+
nudge: true,
|
|
69707
|
+
reason: "texto final indica trabalho inacabado",
|
|
69708
|
+
nudgeMessage: TOOL_CALL_NUDGE
|
|
69709
|
+
};
|
|
69270
69710
|
}
|
|
69271
69711
|
if (turnToolCalls === 0 && looksUnfinished(text2) && !BENIGN_CLOSER_RE.test(text2.slice(-200))) {
|
|
69272
69712
|
return {
|
|
@@ -69379,7 +69819,7 @@ async function createAgent() {
|
|
|
69379
69819
|
const sandboxManager = new LocalSandboxManager(sandbox);
|
|
69380
69820
|
const writer = createConsoleWriter();
|
|
69381
69821
|
const render = createRenderer();
|
|
69382
|
-
const initialModelName = CLI_MODEL_CHAIN[0] ?? "model-nvidia-
|
|
69822
|
+
const initialModelName = CLI_MODEL_CHAIN[0] ?? "model-nvidia-mistral-medium-3.5";
|
|
69383
69823
|
let currentModelName = initialModelName;
|
|
69384
69824
|
let selectedModelKey = null;
|
|
69385
69825
|
const context2 = {
|
|
@@ -69447,6 +69887,8 @@ async function createAgent() {
|
|
|
69447
69887
|
);
|
|
69448
69888
|
}
|
|
69449
69889
|
const history = [];
|
|
69890
|
+
let auditMode = false;
|
|
69891
|
+
const projectRoot = projectRootFromWorkdir(sandbox.getWorkdir());
|
|
69450
69892
|
function getActiveModelChain() {
|
|
69451
69893
|
return selectedModelKey ? [selectedModelKey] : CLI_MODEL_CHAIN;
|
|
69452
69894
|
}
|
|
@@ -69472,7 +69914,7 @@ async function createAgent() {
|
|
|
69472
69914
|
provider: "NVIDIA build",
|
|
69473
69915
|
reason: "faltando NVIDIA_API_KEY em .env.local (https://build.nvidia.com/)",
|
|
69474
69916
|
models: [
|
|
69475
|
-
"model-nvidia-
|
|
69917
|
+
"model-nvidia-mistral-medium-3.5",
|
|
69476
69918
|
"model-nvidia-kimi-k2.6",
|
|
69477
69919
|
"model-nvidia-glm-5.1",
|
|
69478
69920
|
"model-nvidia-qwen3.5-397b"
|
|
@@ -69632,12 +70074,30 @@ ${seen}`);
|
|
|
69632
70074
|
}
|
|
69633
70075
|
async function send(userInput, signal) {
|
|
69634
70076
|
history.push({ role: "user", content: userInput });
|
|
69635
|
-
|
|
69636
|
-
|
|
69637
|
-
if (matchedSkills.length) {
|
|
70077
|
+
if (!auditMode && detectProjectAuditIntent(userInput)) {
|
|
70078
|
+
auditMode = true;
|
|
69638
70079
|
render.info(
|
|
69639
|
-
`\u25B8
|
|
70080
|
+
`\u25B8 modo AN\xC1LISE DE PROJETO (somente leitura) \u2014 auditando ${projectRoot}. Diga "modo normal" para sair.`
|
|
69640
70081
|
);
|
|
70082
|
+
} else if (auditMode && detectAuditExitIntent(userInput)) {
|
|
70083
|
+
auditMode = false;
|
|
70084
|
+
render.info("\u25B8 modo normal reativado.");
|
|
70085
|
+
}
|
|
70086
|
+
let turnSystem;
|
|
70087
|
+
if (auditMode) {
|
|
70088
|
+
turnSystem = buildAuditSystemPrompt({
|
|
70089
|
+
projectRoot,
|
|
70090
|
+
workdir: sandbox.getWorkdir(),
|
|
70091
|
+
shellHint: sandbox.getShellHint()
|
|
70092
|
+
});
|
|
70093
|
+
} else {
|
|
70094
|
+
const matchedSkills = selectSkillsForInput(userInput);
|
|
70095
|
+
turnSystem = matchedSkills.length ? system + renderSkillBodies(matchedSkills) : system;
|
|
70096
|
+
if (matchedSkills.length) {
|
|
70097
|
+
render.info(
|
|
70098
|
+
`\u25B8 skills ativadas: ${matchedSkills.map((s) => s.name).join(", ")}`
|
|
70099
|
+
);
|
|
70100
|
+
}
|
|
69641
70101
|
}
|
|
69642
70102
|
let lastError = null;
|
|
69643
70103
|
let autoContinues = 0;
|
|
@@ -69646,6 +70106,7 @@ ${seen}`);
|
|
|
69646
70106
|
const usingFixedModel = selectedModelKey !== null;
|
|
69647
70107
|
let rateLimitWaits = 0;
|
|
69648
70108
|
let addedRateLimitFallbacks = false;
|
|
70109
|
+
let stallRetries = 0;
|
|
69649
70110
|
for (let idx = 0; idx < modelChain.length; idx++) {
|
|
69650
70111
|
const modelKey = modelChain[idx];
|
|
69651
70112
|
currentModelName = modelKey;
|
|
@@ -69660,6 +70121,27 @@ ${seen}`);
|
|
|
69660
70121
|
render.fallback(`trocando para fallback: ${labelFor(modelKey)}`);
|
|
69661
70122
|
}
|
|
69662
70123
|
let streamError = null;
|
|
70124
|
+
let stalled = false;
|
|
70125
|
+
const stallController = new AbortController();
|
|
70126
|
+
const onUserAbort = () => stallController.abort();
|
|
70127
|
+
if (signal) {
|
|
70128
|
+
if (signal.aborted) stallController.abort();
|
|
70129
|
+
else signal.addEventListener("abort", onUserAbort, { once: true });
|
|
70130
|
+
}
|
|
70131
|
+
let stallTimer;
|
|
70132
|
+
const clearStallTimer = () => {
|
|
70133
|
+
if (stallTimer) {
|
|
70134
|
+
clearTimeout(stallTimer);
|
|
70135
|
+
stallTimer = void 0;
|
|
70136
|
+
}
|
|
70137
|
+
};
|
|
70138
|
+
const armStallTimer = () => {
|
|
70139
|
+
clearStallTimer();
|
|
70140
|
+
stallTimer = setTimeout(() => {
|
|
70141
|
+
stalled = true;
|
|
70142
|
+
stallController.abort();
|
|
70143
|
+
}, STREAM_STALL_TIMEOUT_MS);
|
|
70144
|
+
};
|
|
69663
70145
|
try {
|
|
69664
70146
|
const result = streamText({
|
|
69665
70147
|
model: myProvider.languageModel(modelKey),
|
|
@@ -69668,7 +70150,7 @@ ${seen}`);
|
|
|
69668
70150
|
tools,
|
|
69669
70151
|
stopWhen: stepCountIs(MAX_STEPS),
|
|
69670
70152
|
maxOutputTokens: MAX_OUTPUT_TOKENS,
|
|
69671
|
-
abortSignal: signal,
|
|
70153
|
+
abortSignal: stallController.signal,
|
|
69672
70154
|
onError: ({ error: error51 }) => {
|
|
69673
70155
|
streamError = error51;
|
|
69674
70156
|
}
|
|
@@ -69677,38 +70159,72 @@ ${seen}`);
|
|
|
69677
70159
|
let bufferedProxyText = "";
|
|
69678
70160
|
let turnToolCalls = 0;
|
|
69679
70161
|
const shouldBufferProxyText = isWebSessionProxyModel(modelKey);
|
|
69680
|
-
|
|
69681
|
-
|
|
69682
|
-
|
|
69683
|
-
|
|
69684
|
-
|
|
69685
|
-
|
|
69686
|
-
|
|
69687
|
-
|
|
69688
|
-
|
|
70162
|
+
let pendingTools = 0;
|
|
70163
|
+
const noteActivity = () => {
|
|
70164
|
+
if (pendingTools === 0) armStallTimer();
|
|
70165
|
+
};
|
|
70166
|
+
armStallTimer();
|
|
70167
|
+
try {
|
|
70168
|
+
for await (const part of result.fullStream) {
|
|
70169
|
+
switch (part.type) {
|
|
70170
|
+
case "text-delta": {
|
|
70171
|
+
const delta = part.text ?? part.delta ?? "";
|
|
70172
|
+
lastStepText += delta;
|
|
70173
|
+
if (shouldBufferProxyText) {
|
|
70174
|
+
bufferedProxyText += delta;
|
|
70175
|
+
} else {
|
|
70176
|
+
render.text(delta);
|
|
70177
|
+
}
|
|
70178
|
+
noteActivity();
|
|
70179
|
+
break;
|
|
69689
70180
|
}
|
|
69690
|
-
|
|
70181
|
+
case "reasoning-delta":
|
|
70182
|
+
render.reasoning(part.text ?? part.delta ?? "");
|
|
70183
|
+
noteActivity();
|
|
70184
|
+
break;
|
|
70185
|
+
case "tool-call":
|
|
70186
|
+
turnToolCalls++;
|
|
70187
|
+
pendingTools++;
|
|
70188
|
+
clearStallTimer();
|
|
70189
|
+
render.toolCall(part.toolName, part.input ?? part.args);
|
|
70190
|
+
break;
|
|
70191
|
+
case "tool-result":
|
|
70192
|
+
if (pendingTools > 0) pendingTools--;
|
|
70193
|
+
render.toolResult(part.toolName, part.output ?? part.result);
|
|
70194
|
+
noteActivity();
|
|
70195
|
+
break;
|
|
70196
|
+
case "tool-error":
|
|
70197
|
+
if (pendingTools > 0) pendingTools--;
|
|
70198
|
+
noteActivity();
|
|
70199
|
+
break;
|
|
70200
|
+
case "start-step":
|
|
70201
|
+
lastStepText = "";
|
|
70202
|
+
bufferedProxyText = "";
|
|
70203
|
+
noteActivity();
|
|
70204
|
+
break;
|
|
70205
|
+
case "error":
|
|
70206
|
+
streamError = part.error;
|
|
70207
|
+
noteActivity();
|
|
70208
|
+
break;
|
|
70209
|
+
default:
|
|
70210
|
+
noteActivity();
|
|
70211
|
+
break;
|
|
69691
70212
|
}
|
|
69692
|
-
case "reasoning-delta":
|
|
69693
|
-
render.reasoning(part.text ?? part.delta ?? "");
|
|
69694
|
-
break;
|
|
69695
|
-
case "tool-call":
|
|
69696
|
-
turnToolCalls++;
|
|
69697
|
-
render.toolCall(part.toolName, part.input ?? part.args);
|
|
69698
|
-
break;
|
|
69699
|
-
case "tool-result":
|
|
69700
|
-
render.toolResult(part.toolName, part.output ?? part.result);
|
|
69701
|
-
break;
|
|
69702
|
-
case "start-step":
|
|
69703
|
-
lastStepText = "";
|
|
69704
|
-
bufferedProxyText = "";
|
|
69705
|
-
break;
|
|
69706
|
-
case "error":
|
|
69707
|
-
streamError = part.error;
|
|
69708
|
-
break;
|
|
69709
|
-
default:
|
|
69710
|
-
break;
|
|
69711
70213
|
}
|
|
70214
|
+
} finally {
|
|
70215
|
+
clearStallTimer();
|
|
70216
|
+
if (signal) signal.removeEventListener("abort", onUserAbort);
|
|
70217
|
+
}
|
|
70218
|
+
if (stalled) {
|
|
70219
|
+
void Promise.resolve(result.response).catch(() => {
|
|
70220
|
+
});
|
|
70221
|
+
void Promise.resolve(result.finishReason).catch(() => {
|
|
70222
|
+
});
|
|
70223
|
+
throw new Error(
|
|
70224
|
+
`Resposta do modelo travou: nenhum dado recebido por ${Math.round(
|
|
70225
|
+
STREAM_STALL_TIMEOUT_MS / 1e3
|
|
70226
|
+
)}s.`
|
|
70227
|
+
);
|
|
69712
70228
|
}
|
|
69713
70229
|
if (streamError) throw streamError;
|
|
69714
70230
|
const response = await result.response;
|
|
@@ -69716,12 +70232,13 @@ ${seen}`);
|
|
|
69716
70232
|
const finishReason = String(
|
|
69717
70233
|
await result.finishReason.catch(() => "unknown")
|
|
69718
70234
|
);
|
|
69719
|
-
|
|
70235
|
+
const leakedCall = !shouldBufferProxyText && hasLeakedToolCallMarker(lastStepText);
|
|
70236
|
+
if (finishReason === "stop" && turnToolCalls === 0 && bridgeSteps < MAX_BRIDGE_STEPS && (shouldBufferProxyText || leakedCall)) {
|
|
69720
70237
|
const bridged = parseProxyToolCalls(lastStepText);
|
|
69721
70238
|
if (bridged) {
|
|
69722
70239
|
bridgeSteps++;
|
|
69723
70240
|
render.info(
|
|
69724
|
-
`\u25B8 bridge (${bridgeSteps}/${MAX_BRIDGE_STEPS}): executando por tr\xE1s ${bridged.length} chamada(s): ${summarizeBridgedCalls(bridged)}`
|
|
70241
|
+
`\u25B8 ${leakedCall ? "tool call vazada recuperada" : "bridge"} (${bridgeSteps}/${MAX_BRIDGE_STEPS}): executando por tr\xE1s ${bridged.length} chamada(s): ${summarizeBridgedCalls(bridged)}`
|
|
69725
70242
|
);
|
|
69726
70243
|
const resultText = await runBridgedToolCalls(bridged, signal);
|
|
69727
70244
|
if (signal?.aborted) {
|
|
@@ -69730,7 +70247,7 @@ ${seen}`);
|
|
|
69730
70247
|
}
|
|
69731
70248
|
history.push({
|
|
69732
70249
|
role: "user",
|
|
69733
|
-
content: `${BRIDGE_RESULT_PREAMBLE}
|
|
70250
|
+
content: `${leakedCall ? LEAKED_CALL_RESULT_PREAMBLE : BRIDGE_RESULT_PREAMBLE}
|
|
69734
70251
|
|
|
69735
70252
|
${resultText}`
|
|
69736
70253
|
});
|
|
@@ -69779,6 +70296,28 @@ ${resultText}`
|
|
|
69779
70296
|
render.endTurn();
|
|
69780
70297
|
return;
|
|
69781
70298
|
}
|
|
70299
|
+
if (stalled) {
|
|
70300
|
+
while (history.length && history[history.length - 1]?.role !== "user") {
|
|
70301
|
+
history.pop();
|
|
70302
|
+
}
|
|
70303
|
+
const secs = Math.round(STREAM_STALL_TIMEOUT_MS / 1e3);
|
|
70304
|
+
lastError = new Error(
|
|
70305
|
+
`stream travou (${secs}s sem dados) em ${labelFor(modelKey)}`
|
|
70306
|
+
);
|
|
70307
|
+
stallRetries++;
|
|
70308
|
+
const hasNext2 = idx + 1 < modelChain.length;
|
|
70309
|
+
if (stallRetries <= MAX_STALL_RETRIES) {
|
|
70310
|
+
render.error(
|
|
70311
|
+
`modelo "${labelFor(modelKey)}" travou (sem resposta por ${secs}s) \u2014 ${hasNext2 ? "trocando de modelo" : "tentando novamente"} (${stallRetries}/${MAX_STALL_RETRIES})`
|
|
70312
|
+
);
|
|
70313
|
+
if (!hasNext2) idx = -1;
|
|
70314
|
+
continue;
|
|
70315
|
+
}
|
|
70316
|
+
render.error(
|
|
70317
|
+
`modelo "${labelFor(modelKey)}" travou repetidamente (${stallRetries}x); desistindo deste turno. Tente de novo ou troque com /model.`
|
|
70318
|
+
);
|
|
70319
|
+
break;
|
|
70320
|
+
}
|
|
69782
70321
|
lastError = err ?? streamError;
|
|
69783
70322
|
const msg = lastError instanceof Error ? lastError.message : String(lastError);
|
|
69784
70323
|
const rateLimited = isRateLimitError(msg);
|
|
@@ -69857,13 +70396,13 @@ ${resultText}`
|
|
|
69857
70396
|
close
|
|
69858
70397
|
};
|
|
69859
70398
|
}
|
|
69860
|
-
var import_promises,
|
|
70399
|
+
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;
|
|
69861
70400
|
var init_agent = __esm({
|
|
69862
70401
|
"src/agent.ts"() {
|
|
69863
70402
|
"use strict";
|
|
69864
70403
|
init_dist5();
|
|
69865
70404
|
import_promises = require("node:fs/promises");
|
|
69866
|
-
|
|
70405
|
+
import_node_path8 = __toESM(require("node:path"));
|
|
69867
70406
|
init_providers();
|
|
69868
70407
|
init_system_prompt();
|
|
69869
70408
|
init_notes();
|
|
@@ -69882,10 +70421,16 @@ var init_agent = __esm({
|
|
|
69882
70421
|
init_render();
|
|
69883
70422
|
init_skills();
|
|
69884
70423
|
init_proxy_manager2();
|
|
70424
|
+
init_audit_mode();
|
|
69885
70425
|
MAX_STEPS = 100;
|
|
69886
70426
|
MAX_OUTPUT_TOKENS = 16384;
|
|
69887
70427
|
MAX_AUTO_CONTINUES = 3;
|
|
69888
70428
|
MAX_RATE_LIMIT_WAITS = 4;
|
|
70429
|
+
STREAM_STALL_TIMEOUT_MS = (() => {
|
|
70430
|
+
const raw = Number(process.env.HACKERAI_CLI_STREAM_STALL_MS);
|
|
70431
|
+
return Number.isFinite(raw) && raw >= 1e4 ? raw : 18e4;
|
|
70432
|
+
})();
|
|
70433
|
+
MAX_STALL_RETRIES = 2;
|
|
69889
70434
|
isRateLimitError = (msg) => /\b429\b|too many requests|rate.?limit|resource_exhausted|quota|insufficient_quota/i.test(
|
|
69890
70435
|
msg
|
|
69891
70436
|
);
|
|
@@ -69901,11 +70446,14 @@ var init_agent = __esm({
|
|
|
69901
70446
|
{ once: true }
|
|
69902
70447
|
);
|
|
69903
70448
|
});
|
|
69904
|
-
|
|
70449
|
+
LEAKED_TOOL_CALL_RE = /<tool_call|call_tool_function|call_tool\b|<|tool▁call|functions\.\w+\s*[({]|"tool_call_id"/i;
|
|
70450
|
+
DANGLING_TAIL_RE = /(?::|\.\.\.|…)\s*$/;
|
|
70451
|
+
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;
|
|
69905
70452
|
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;
|
|
69906
70453
|
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.";
|
|
69907
70454
|
MAX_BRIDGE_STEPS = 50;
|
|
69908
70455
|
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.";
|
|
70456
|
+
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.";
|
|
69909
70457
|
truncateBridgeSummary = (value, max = 180) => value.length > max ? `${value.slice(0, max)}...` : value;
|
|
69910
70458
|
isWebSessionProxyModel = (modelName) => modelName === "model-deepseek-proxy" || modelName === "model-kimi-proxy";
|
|
69911
70459
|
proxyToolProtocolPolicy = () => `
|
|
@@ -69941,7 +70489,7 @@ Regras:
|
|
|
69941
70489
|
"DANGEROUS MODE"
|
|
69942
70490
|
];
|
|
69943
70491
|
MODEL_LABELS = {
|
|
69944
|
-
"model-nvidia-
|
|
70492
|
+
"model-nvidia-mistral-medium-3.5": "NVIDIA - mistralai/mistral-medium-3.5-128b",
|
|
69945
70493
|
"model-nvidia-kimi-k2.6": "NVIDIA - moonshotai/kimi-k2.6",
|
|
69946
70494
|
"model-nvidia-glm-5.1": "NVIDIA - z-ai/glm-5.1",
|
|
69947
70495
|
"model-nvidia-qwen3.5-397b": "NVIDIA - qwen/qwen3.5-397b-a17b",
|
|
@@ -70086,7 +70634,7 @@ ${section}` : "";
|
|
|
70086
70634
|
return null;
|
|
70087
70635
|
}
|
|
70088
70636
|
await (0, import_promises.mkdir)(workdir, { recursive: true });
|
|
70089
|
-
const outputPath =
|
|
70637
|
+
const outputPath = import_node_path8.default.join(workdir, "system-prompt.txt");
|
|
70090
70638
|
await (0, import_promises.writeFile)(outputPath, system, "utf8");
|
|
70091
70639
|
return outputPath;
|
|
70092
70640
|
};
|
|
@@ -70117,7 +70665,9 @@ __export(ui_exports, {
|
|
|
70117
70665
|
agentHeader: () => agentHeader,
|
|
70118
70666
|
buildBanner: () => buildBanner,
|
|
70119
70667
|
shellPrompt: () => shellPrompt,
|
|
70120
|
-
|
|
70668
|
+
shortCwd: () => shortCwd,
|
|
70669
|
+
ui: () => ui,
|
|
70670
|
+
vlen: () => vlen
|
|
70121
70671
|
});
|
|
70122
70672
|
function shortCwd() {
|
|
70123
70673
|
const cwd = process.cwd();
|
|
@@ -70130,15 +70680,15 @@ function shortCwd() {
|
|
|
70130
70680
|
}
|
|
70131
70681
|
function asciiTitle(text2) {
|
|
70132
70682
|
const rows = 6;
|
|
70133
|
-
const
|
|
70683
|
+
const out3 = [];
|
|
70134
70684
|
for (let r = 0; r < rows; r++) {
|
|
70135
|
-
|
|
70685
|
+
out3.push(
|
|
70136
70686
|
[...text2].map((ch) => GLYPHS[ch] ? GLYPHS[ch][r] : " ").join(" ")
|
|
70137
70687
|
);
|
|
70138
70688
|
}
|
|
70139
|
-
return
|
|
70689
|
+
return out3;
|
|
70140
70690
|
}
|
|
70141
|
-
function buildBanner(_systemPromptChars) {
|
|
70691
|
+
function buildBanner(_systemPromptChars, version3 = "1") {
|
|
70142
70692
|
const user = (import_node_os4.default.userInfo().username || "hacker").toLowerCase();
|
|
70143
70693
|
const host = (import_node_os4.default.hostname() || "localhost").split(".")[0].toLowerCase();
|
|
70144
70694
|
const art = asciiTitle("CLAWFAST");
|
|
@@ -70162,7 +70712,7 @@ function buildBanner(_systemPromptChars) {
|
|
|
70162
70712
|
{ text: shortCwd() },
|
|
70163
70713
|
{ text: "" }
|
|
70164
70714
|
];
|
|
70165
|
-
const title = `clawfast
|
|
70715
|
+
const title = `clawfast v${version3}`;
|
|
70166
70716
|
const topFill = "\u2500".repeat(Math.max(0, BOX_W - vlen(title) - 5));
|
|
70167
70717
|
const top = `${C3.green}\u256D\u2500 ${C3.greenB}${C3.bold}${title}${C3.reset}${C3.green} ${topFill}\u256E${C3.reset}`;
|
|
70168
70718
|
const bottom = `${C3.green}\u2570${"\u2500".repeat(BOX_W - 2)}\u256F${C3.reset}`;
|
|
@@ -70208,7 +70758,8 @@ var init_ui = __esm({
|
|
|
70208
70758
|
cyan: `${ESC}36m`,
|
|
70209
70759
|
cyanB: `${ESC}96m`,
|
|
70210
70760
|
magenta: `${ESC}95m`,
|
|
70211
|
-
yellow: `${ESC}93m
|
|
70761
|
+
yellow: `${ESC}93m`,
|
|
70762
|
+
red: `${ESC}91m`
|
|
70212
70763
|
};
|
|
70213
70764
|
INNER = 42;
|
|
70214
70765
|
BOX_W = INNER + 4;
|
|
@@ -70232,42 +70783,500 @@ var init_ui = __esm({
|
|
|
70232
70783
|
}
|
|
70233
70784
|
});
|
|
70234
70785
|
|
|
70786
|
+
// src/interactive-input.ts
|
|
70787
|
+
var interactive_input_exports = {};
|
|
70788
|
+
__export(interactive_input_exports, {
|
|
70789
|
+
InteractiveInput: () => InteractiveInput
|
|
70790
|
+
});
|
|
70791
|
+
var import_node_readline3, import_node_os5, C4, out2, cols, truncate4, InteractiveInput;
|
|
70792
|
+
var init_interactive_input = __esm({
|
|
70793
|
+
"src/interactive-input.ts"() {
|
|
70794
|
+
"use strict";
|
|
70795
|
+
import_node_readline3 = __toESM(require("node:readline"));
|
|
70796
|
+
import_node_os5 = __toESM(require("node:os"));
|
|
70797
|
+
init_ui();
|
|
70798
|
+
C4 = ui.C;
|
|
70799
|
+
out2 = (s) => process.stdout.write(s);
|
|
70800
|
+
cols = () => process.stdout.columns || 80;
|
|
70801
|
+
truncate4 = (s, n) => vlen(s) > n ? [...s].slice(0, Math.max(0, n - 1)).join("") + "\u2026" : s;
|
|
70802
|
+
InteractiveInput = class {
|
|
70803
|
+
// row the caret sits on within the drawn block
|
|
70804
|
+
constructor(paste, commands) {
|
|
70805
|
+
this.paste = paste;
|
|
70806
|
+
this.commands = commands;
|
|
70807
|
+
this.buffer = "";
|
|
70808
|
+
this.cursor = 0;
|
|
70809
|
+
this.lastRows = 0;
|
|
70810
|
+
this.history = [];
|
|
70811
|
+
this.histIdx = -1;
|
|
70812
|
+
// -1 = editing the live draft
|
|
70813
|
+
this.draft = "";
|
|
70814
|
+
this.ddSel = 0;
|
|
70815
|
+
this.ddSuppressed = false;
|
|
70816
|
+
// Text to restore on the NEXT prompt: when a command is picked from the
|
|
70817
|
+
// dropdown mid-text, we run the command but stash the surrounding text here
|
|
70818
|
+
// so the user doesn't lose what they were typing.
|
|
70819
|
+
this.pendingInitial = null;
|
|
70820
|
+
this.onKey = null;
|
|
70821
|
+
// When set, prompt() draws a compact single-line labelled prompt ("nome ❯ ")
|
|
70822
|
+
// instead of the full message box + dropdown — used for the /skillcreator
|
|
70823
|
+
// step-by-step capture so each phase shows what it's asking for.
|
|
70824
|
+
this.promptLabel = null;
|
|
70825
|
+
this.inputLineIndex = 2;
|
|
70826
|
+
import_node_readline3.default.emitKeypressEvents(paste.input);
|
|
70827
|
+
paste.input.on("keypress", (str, key) => {
|
|
70828
|
+
this.onKey?.(str ?? "", key ?? {});
|
|
70829
|
+
});
|
|
70830
|
+
}
|
|
70831
|
+
// ── public API ─────────────────────────────────────────────────────────────
|
|
70832
|
+
/**
|
|
70833
|
+
* Render the input and resolve when the user submits / Ctrl+C / Ctrl+D.
|
|
70834
|
+
* Pass `{ label }` for a compact labelled prompt (no box, no dropdown).
|
|
70835
|
+
*/
|
|
70836
|
+
prompt(opts = {}) {
|
|
70837
|
+
this.promptLabel = opts.label ?? null;
|
|
70838
|
+
const initial = this.promptLabel === null && this.pendingInitial ? this.pendingInitial : "";
|
|
70839
|
+
this.pendingInitial = null;
|
|
70840
|
+
this.buffer = initial;
|
|
70841
|
+
this.cursor = initial.length;
|
|
70842
|
+
this.histIdx = -1;
|
|
70843
|
+
this.draft = "";
|
|
70844
|
+
this.ddSel = 0;
|
|
70845
|
+
this.ddSuppressed = false;
|
|
70846
|
+
this.lastRows = 0;
|
|
70847
|
+
if (this.promptLabel === null) out2("\n");
|
|
70848
|
+
this.render();
|
|
70849
|
+
return new Promise((resolve2) => {
|
|
70850
|
+
this.onKey = (str, key) => {
|
|
70851
|
+
const done = this.handleEditKey(str, key);
|
|
70852
|
+
if (!done) {
|
|
70853
|
+
this.render();
|
|
70854
|
+
return;
|
|
70855
|
+
}
|
|
70856
|
+
this.onKey = null;
|
|
70857
|
+
resolve2(done.result);
|
|
70858
|
+
};
|
|
70859
|
+
});
|
|
70860
|
+
}
|
|
70861
|
+
/**
|
|
70862
|
+
* Arrow-navigable single-choice list. Returns the chosen index, or null when
|
|
70863
|
+
* the user cancels (Esc / q / Ctrl+C).
|
|
70864
|
+
*/
|
|
70865
|
+
select(title, items, initial = 0) {
|
|
70866
|
+
let sel = Math.max(0, Math.min(initial, items.length - 1));
|
|
70867
|
+
this.lastRows = 0;
|
|
70868
|
+
out2("\n");
|
|
70869
|
+
this.renderList(title, items, sel);
|
|
70870
|
+
return new Promise((resolve2) => {
|
|
70871
|
+
const finish = (value) => {
|
|
70872
|
+
this.collapseTo(this.lastRows);
|
|
70873
|
+
this.onKey = null;
|
|
70874
|
+
resolve2(value);
|
|
70875
|
+
};
|
|
70876
|
+
this.onKey = (str, key) => {
|
|
70877
|
+
if (key.ctrl && key.name === "c") return finish(null);
|
|
70878
|
+
switch (key.name) {
|
|
70879
|
+
case "up":
|
|
70880
|
+
sel = (sel - 1 + items.length) % items.length;
|
|
70881
|
+
this.renderList(title, items, sel);
|
|
70882
|
+
return;
|
|
70883
|
+
case "down":
|
|
70884
|
+
case "tab":
|
|
70885
|
+
sel = (sel + 1) % items.length;
|
|
70886
|
+
this.renderList(title, items, sel);
|
|
70887
|
+
return;
|
|
70888
|
+
case "return":
|
|
70889
|
+
return finish(sel);
|
|
70890
|
+
case "escape":
|
|
70891
|
+
return finish(null);
|
|
70892
|
+
default:
|
|
70893
|
+
if (str === "q") return finish(null);
|
|
70894
|
+
if (/^[1-9]$/.test(str)) {
|
|
70895
|
+
const i = Number(str) - 1;
|
|
70896
|
+
if (i < items.length) {
|
|
70897
|
+
sel = i;
|
|
70898
|
+
this.renderList(title, items, sel);
|
|
70899
|
+
}
|
|
70900
|
+
}
|
|
70901
|
+
return;
|
|
70902
|
+
}
|
|
70903
|
+
};
|
|
70904
|
+
});
|
|
70905
|
+
}
|
|
70906
|
+
/**
|
|
70907
|
+
* Lightweight line reader used WHILE a turn is running, so typed lines can be
|
|
70908
|
+
* forwarded to an interactive command's stdin. No box/dropdown — just echoes
|
|
70909
|
+
* and collects until Enter. Ctrl+C invokes `onSigint`.
|
|
70910
|
+
*/
|
|
70911
|
+
beginTurn(onLine, onSigint) {
|
|
70912
|
+
let buf = "";
|
|
70913
|
+
this.onKey = (str, key) => {
|
|
70914
|
+
if (key.ctrl && key.name === "c") return onSigint();
|
|
70915
|
+
if (key.name === "return") {
|
|
70916
|
+
out2("\r\n");
|
|
70917
|
+
const line = this.paste.expand(buf);
|
|
70918
|
+
buf = "";
|
|
70919
|
+
onLine(line);
|
|
70920
|
+
return;
|
|
70921
|
+
}
|
|
70922
|
+
if (key.name === "backspace") {
|
|
70923
|
+
if (buf.length) {
|
|
70924
|
+
buf = buf.slice(0, -1);
|
|
70925
|
+
out2("\b \b");
|
|
70926
|
+
}
|
|
70927
|
+
return;
|
|
70928
|
+
}
|
|
70929
|
+
if (str && str.charCodeAt(0) >= 32 && !key.ctrl && !key.meta) {
|
|
70930
|
+
buf += str;
|
|
70931
|
+
out2(str);
|
|
70932
|
+
}
|
|
70933
|
+
};
|
|
70934
|
+
}
|
|
70935
|
+
endTurn() {
|
|
70936
|
+
this.onKey = null;
|
|
70937
|
+
}
|
|
70938
|
+
// ── editing ──────────────────────────────────────────────────────────────
|
|
70939
|
+
handleEditKey(str, key) {
|
|
70940
|
+
const items = this.dropdownItems();
|
|
70941
|
+
if (key.ctrl && key.name === "c") {
|
|
70942
|
+
this.finishLine();
|
|
70943
|
+
return { result: { type: "sigint" } };
|
|
70944
|
+
}
|
|
70945
|
+
if (key.ctrl && key.name === "d") {
|
|
70946
|
+
if (this.buffer.length === 0) {
|
|
70947
|
+
this.finishLine();
|
|
70948
|
+
return { result: { type: "eof" } };
|
|
70949
|
+
}
|
|
70950
|
+
this.deleteForward();
|
|
70951
|
+
return null;
|
|
70952
|
+
}
|
|
70953
|
+
switch (key.name) {
|
|
70954
|
+
case "return": {
|
|
70955
|
+
if (items.length > 0) {
|
|
70956
|
+
const name25 = items[this.ddSel].name;
|
|
70957
|
+
const tok = this.slashTokenAtCursor();
|
|
70958
|
+
const leftover = tok ? this.buffer.slice(0, tok.start) + this.buffer.slice(tok.end) : "";
|
|
70959
|
+
this.pendingInitial = leftover.trim() ? leftover : null;
|
|
70960
|
+
this.buffer = name25;
|
|
70961
|
+
this.cursor = name25.length;
|
|
70962
|
+
}
|
|
70963
|
+
const value = this.paste.expand(this.buffer);
|
|
70964
|
+
if (value.trim()) this.history.push(value);
|
|
70965
|
+
this.finishLine();
|
|
70966
|
+
return { result: { type: "line", value } };
|
|
70967
|
+
}
|
|
70968
|
+
case "tab":
|
|
70969
|
+
if (items.length > 0) {
|
|
70970
|
+
this.applyCommandInPlace(items[this.ddSel].name);
|
|
70971
|
+
this.ddSuppressed = false;
|
|
70972
|
+
}
|
|
70973
|
+
return null;
|
|
70974
|
+
case "up":
|
|
70975
|
+
if (items.length > 0) {
|
|
70976
|
+
this.ddSel = (this.ddSel - 1 + items.length) % items.length;
|
|
70977
|
+
} else {
|
|
70978
|
+
this.historyPrev();
|
|
70979
|
+
}
|
|
70980
|
+
return null;
|
|
70981
|
+
case "down":
|
|
70982
|
+
if (items.length > 0) {
|
|
70983
|
+
this.ddSel = (this.ddSel + 1) % items.length;
|
|
70984
|
+
} else {
|
|
70985
|
+
this.historyNext();
|
|
70986
|
+
}
|
|
70987
|
+
return null;
|
|
70988
|
+
case "escape":
|
|
70989
|
+
if (items.length > 0) this.ddSuppressed = true;
|
|
70990
|
+
return null;
|
|
70991
|
+
case "left":
|
|
70992
|
+
if (this.cursor > 0) this.cursor--;
|
|
70993
|
+
return null;
|
|
70994
|
+
case "right":
|
|
70995
|
+
if (this.cursor < this.buffer.length) this.cursor++;
|
|
70996
|
+
return null;
|
|
70997
|
+
case "home":
|
|
70998
|
+
this.cursor = 0;
|
|
70999
|
+
return null;
|
|
71000
|
+
case "end":
|
|
71001
|
+
this.cursor = this.buffer.length;
|
|
71002
|
+
return null;
|
|
71003
|
+
case "backspace":
|
|
71004
|
+
if (this.cursor > 0) {
|
|
71005
|
+
this.buffer = this.buffer.slice(0, this.cursor - 1) + this.buffer.slice(this.cursor);
|
|
71006
|
+
this.cursor--;
|
|
71007
|
+
this.ddSuppressed = false;
|
|
71008
|
+
}
|
|
71009
|
+
return null;
|
|
71010
|
+
case "delete":
|
|
71011
|
+
this.deleteForward();
|
|
71012
|
+
return null;
|
|
71013
|
+
}
|
|
71014
|
+
if (key.ctrl && key.name === "u") {
|
|
71015
|
+
this.buffer = this.buffer.slice(this.cursor);
|
|
71016
|
+
this.cursor = 0;
|
|
71017
|
+
this.ddSuppressed = false;
|
|
71018
|
+
return null;
|
|
71019
|
+
}
|
|
71020
|
+
if (key.ctrl && key.name === "w") {
|
|
71021
|
+
const left = this.buffer.slice(0, this.cursor);
|
|
71022
|
+
const trimmed = left.replace(/\s*\S+\s*$/u, "");
|
|
71023
|
+
this.buffer = trimmed + this.buffer.slice(this.cursor);
|
|
71024
|
+
this.cursor = trimmed.length;
|
|
71025
|
+
this.ddSuppressed = false;
|
|
71026
|
+
return null;
|
|
71027
|
+
}
|
|
71028
|
+
if (key.ctrl && key.name === "a") {
|
|
71029
|
+
this.cursor = 0;
|
|
71030
|
+
return null;
|
|
71031
|
+
}
|
|
71032
|
+
if (key.ctrl && key.name === "e") {
|
|
71033
|
+
this.cursor = this.buffer.length;
|
|
71034
|
+
return null;
|
|
71035
|
+
}
|
|
71036
|
+
if (str && !key.ctrl && !key.meta && str.charCodeAt(0) >= 32) {
|
|
71037
|
+
this.buffer = this.buffer.slice(0, this.cursor) + str + this.buffer.slice(this.cursor);
|
|
71038
|
+
this.cursor += str.length;
|
|
71039
|
+
this.ddSuppressed = false;
|
|
71040
|
+
}
|
|
71041
|
+
return null;
|
|
71042
|
+
}
|
|
71043
|
+
deleteForward() {
|
|
71044
|
+
if (this.cursor < this.buffer.length) {
|
|
71045
|
+
this.buffer = this.buffer.slice(0, this.cursor) + this.buffer.slice(this.cursor + 1);
|
|
71046
|
+
this.ddSuppressed = false;
|
|
71047
|
+
}
|
|
71048
|
+
}
|
|
71049
|
+
historyPrev() {
|
|
71050
|
+
if (this.history.length === 0) return;
|
|
71051
|
+
if (this.histIdx === -1) {
|
|
71052
|
+
this.draft = this.buffer;
|
|
71053
|
+
this.histIdx = this.history.length - 1;
|
|
71054
|
+
} else if (this.histIdx > 0) {
|
|
71055
|
+
this.histIdx--;
|
|
71056
|
+
}
|
|
71057
|
+
this.buffer = this.history[this.histIdx];
|
|
71058
|
+
this.cursor = this.buffer.length;
|
|
71059
|
+
}
|
|
71060
|
+
historyNext() {
|
|
71061
|
+
if (this.histIdx === -1) return;
|
|
71062
|
+
if (this.histIdx < this.history.length - 1) {
|
|
71063
|
+
this.histIdx++;
|
|
71064
|
+
this.buffer = this.history[this.histIdx];
|
|
71065
|
+
} else {
|
|
71066
|
+
this.histIdx = -1;
|
|
71067
|
+
this.buffer = this.draft;
|
|
71068
|
+
}
|
|
71069
|
+
this.cursor = this.buffer.length;
|
|
71070
|
+
}
|
|
71071
|
+
// ── rendering ──────────────────────────────────────────────────────────────
|
|
71072
|
+
// The slash-command "token" the cursor is sitting in — the run of
|
|
71073
|
+
// non-whitespace chars around the cursor, when it begins with "/". Works at
|
|
71074
|
+
// the start of the line OR in the middle of the text (e.g. "veja o /mod"),
|
|
71075
|
+
// so the command dropdown opens wherever you type a slash. Returns the span
|
|
71076
|
+
// [start, end) to replace and the query (the whole token) to filter by.
|
|
71077
|
+
slashTokenAtCursor() {
|
|
71078
|
+
const b = this.buffer;
|
|
71079
|
+
let start = this.cursor;
|
|
71080
|
+
while (start > 0 && !/\s/.test(b[start - 1])) start--;
|
|
71081
|
+
if (b[start] !== "/") return null;
|
|
71082
|
+
let end = this.cursor;
|
|
71083
|
+
while (end < b.length && !/\s/.test(b[end])) end++;
|
|
71084
|
+
const query = b.slice(start, end);
|
|
71085
|
+
if (!/^\/\S*$/.test(query)) return null;
|
|
71086
|
+
return { start, end, query };
|
|
71087
|
+
}
|
|
71088
|
+
// Replace the slash token under the cursor with `name` (used by Tab/Enter
|
|
71089
|
+
// completion), leaving the surrounding text intact and the cursor right after
|
|
71090
|
+
// the inserted command.
|
|
71091
|
+
applyCommandInPlace(name25) {
|
|
71092
|
+
const tok = this.slashTokenAtCursor();
|
|
71093
|
+
if (!tok) return;
|
|
71094
|
+
this.buffer = this.buffer.slice(0, tok.start) + name25 + this.buffer.slice(tok.end);
|
|
71095
|
+
this.cursor = tok.start + name25.length;
|
|
71096
|
+
}
|
|
71097
|
+
dropdownItems() {
|
|
71098
|
+
if (this.promptLabel !== null) return [];
|
|
71099
|
+
if (this.ddSuppressed) return [];
|
|
71100
|
+
const tok = this.slashTokenAtCursor();
|
|
71101
|
+
if (!tok) return [];
|
|
71102
|
+
const q = tok.query.toLowerCase();
|
|
71103
|
+
return this.commands.filter((c) => c.name.toLowerCase().startsWith(q));
|
|
71104
|
+
}
|
|
71105
|
+
render() {
|
|
71106
|
+
if (this.promptLabel !== null) {
|
|
71107
|
+
this.renderCompact();
|
|
71108
|
+
return;
|
|
71109
|
+
}
|
|
71110
|
+
const width = cols();
|
|
71111
|
+
const user = (import_node_os5.default.userInfo().username || "hacker").toLowerCase();
|
|
71112
|
+
const host = (import_node_os5.default.hostname() || "localhost").split(".")[0].toLowerCase();
|
|
71113
|
+
const label = " \u2709 mensagem ";
|
|
71114
|
+
const boxW = Math.min(54, Math.max(28, width - 2));
|
|
71115
|
+
const topFill = "\u2500".repeat(Math.max(0, boxW - vlen(label) - 3));
|
|
71116
|
+
const top = `${C4.green}\u256D\u2500${C4.greenB}${C4.bold}${label}${C4.reset}${C4.green}${topFill}\u256E${C4.reset}`;
|
|
71117
|
+
const id = `${user}\u327F${host} \xB7 ${shortCwd()}`;
|
|
71118
|
+
const idLine = `${C4.green}\u2502 ${C4.dim}${truncate4(id, boxW - 4)}${C4.reset}`;
|
|
71119
|
+
const prefix = `${C4.green}\u2570\u2500${C4.greenB}${C4.bold}\u276F${C4.reset} `;
|
|
71120
|
+
const prefixLen = 4;
|
|
71121
|
+
const avail = Math.max(8, width - prefixLen - 1);
|
|
71122
|
+
let start = 0;
|
|
71123
|
+
if (this.cursor > avail) start = this.cursor - avail;
|
|
71124
|
+
const visible = this.buffer.slice(start, start + avail);
|
|
71125
|
+
const caretCol = prefixLen + (this.cursor - start);
|
|
71126
|
+
const promptLine2 = prefix + visible;
|
|
71127
|
+
const lines = [top, idLine, promptLine2];
|
|
71128
|
+
const items = this.dropdownItems();
|
|
71129
|
+
if (items.length > 0) {
|
|
71130
|
+
this.ddSel = Math.min(this.ddSel, items.length - 1);
|
|
71131
|
+
const ddHint = "\u2191\u2193 navega \xB7 Enter roda \xB7 Tab completa";
|
|
71132
|
+
const nameW = Math.max(...items.map((i) => vlen(i.name)));
|
|
71133
|
+
const ddInner = Math.min(boxW, Math.max(24, width - 4));
|
|
71134
|
+
lines.push(`${C4.dim} \u256D${"\u2500".repeat(ddInner)}\u256E${C4.reset}`);
|
|
71135
|
+
items.forEach((it, i) => {
|
|
71136
|
+
const active2 = i === this.ddSel;
|
|
71137
|
+
const marker25 = active2 ? `${C4.greenB}\u25B8 ` : `${C4.dim} `;
|
|
71138
|
+
const name25 = (active2 ? `${C4.greenB}${C4.bold}` : C4.cyan) + it.name;
|
|
71139
|
+
const pad = " ".repeat(Math.max(1, nameW - vlen(it.name) + 2));
|
|
71140
|
+
const descRoom = ddInner - 2 - nameW - 2;
|
|
71141
|
+
const desc = `${C4.dim}${truncate4(it.desc, Math.max(4, descRoom))}`;
|
|
71142
|
+
const body = `${marker25}${name25}${C4.reset}${pad}${desc}${C4.reset}`;
|
|
71143
|
+
const padded = body + " ".repeat(Math.max(0, ddInner - 1 - vlen(body)));
|
|
71144
|
+
lines.push(`${C4.dim} \u2502${C4.reset}${padded}${C4.dim}\u2502${C4.reset}`);
|
|
71145
|
+
});
|
|
71146
|
+
lines.push(
|
|
71147
|
+
`${C4.dim} \u2570${"\u2500".repeat(ddInner)}\u256F ${ddHint}${C4.reset}`
|
|
71148
|
+
);
|
|
71149
|
+
} else {
|
|
71150
|
+
this.ddSel = 0;
|
|
71151
|
+
}
|
|
71152
|
+
this.inputLineIndex = 2;
|
|
71153
|
+
this.paint(lines, caretCol);
|
|
71154
|
+
}
|
|
71155
|
+
/** Compact single-line labelled prompt ("nome ❯ …") for step-by-step capture. */
|
|
71156
|
+
renderCompact() {
|
|
71157
|
+
const width = cols();
|
|
71158
|
+
const label = this.promptLabel ?? "";
|
|
71159
|
+
const prefix = `${C4.cyan}${C4.bold}${label}${C4.reset} ${C4.greenB}${C4.bold}\u276F${C4.reset} `;
|
|
71160
|
+
const prefixLen = vlen(`${label} \u276F `);
|
|
71161
|
+
const avail = Math.max(8, width - prefixLen - 1);
|
|
71162
|
+
let start = 0;
|
|
71163
|
+
if (this.cursor > avail) start = this.cursor - avail;
|
|
71164
|
+
const visible = this.buffer.slice(start, start + avail);
|
|
71165
|
+
const caretCol = prefixLen + (this.cursor - start);
|
|
71166
|
+
this.inputLineIndex = 0;
|
|
71167
|
+
this.paint([prefix + visible], caretCol);
|
|
71168
|
+
}
|
|
71169
|
+
/** Repaint the whole block, then place the cursor on the active input line. */
|
|
71170
|
+
paint(lines, caretCol) {
|
|
71171
|
+
let s = "";
|
|
71172
|
+
if (this.lastRows > 1) s += `\x1B[${this.lastRows - 1}A`;
|
|
71173
|
+
s += "\r\x1B[0J";
|
|
71174
|
+
s += lines.join("\r\n");
|
|
71175
|
+
this.lastRows = lines.length;
|
|
71176
|
+
const below = lines.length - 1 - this.inputLineIndex;
|
|
71177
|
+
if (below > 0) s += `\x1B[${below}A`;
|
|
71178
|
+
s += "\r";
|
|
71179
|
+
if (caretCol > 0) s += `\x1B[${caretCol}C`;
|
|
71180
|
+
out2(s);
|
|
71181
|
+
}
|
|
71182
|
+
/** Collapse the dropdown, keep the typed line, and drop to a fresh line below. */
|
|
71183
|
+
finishLine() {
|
|
71184
|
+
this.ddSuppressed = true;
|
|
71185
|
+
this.render();
|
|
71186
|
+
const below = this.lastRows - 1 - this.inputLineIndex;
|
|
71187
|
+
if (below > 0) out2(`\x1B[${below}B`);
|
|
71188
|
+
out2("\r\n");
|
|
71189
|
+
this.lastRows = 0;
|
|
71190
|
+
}
|
|
71191
|
+
renderList(title, items, sel) {
|
|
71192
|
+
const width = cols();
|
|
71193
|
+
const labelW = Math.max(...items.map((i) => vlen(i.label)));
|
|
71194
|
+
const inner = Math.min(
|
|
71195
|
+
Math.max(28, width - 4),
|
|
71196
|
+
Math.max(labelW + 8, title.length + 4)
|
|
71197
|
+
);
|
|
71198
|
+
const lines = [];
|
|
71199
|
+
lines.push(`${C4.cyan}\u256D\u2500 ${C4.bold}${title}${C4.reset}`);
|
|
71200
|
+
items.forEach((it, i) => {
|
|
71201
|
+
const active2 = i === sel;
|
|
71202
|
+
const marker25 = active2 ? `${C4.greenB}\u276F ` : `${C4.dim} `;
|
|
71203
|
+
const text2 = active2 ? `${C4.greenB}${C4.bold}${it.label}${C4.reset}` : `${C4.reset}${it.label}`;
|
|
71204
|
+
const hint = it.hint ? ` ${C4.dim}${truncate4(it.hint, Math.max(6, inner - labelW - 6))}${C4.reset}` : "";
|
|
71205
|
+
lines.push(`${C4.cyan}\u2502 ${C4.reset}${marker25}${text2}${C4.reset}${hint}`);
|
|
71206
|
+
});
|
|
71207
|
+
lines.push(
|
|
71208
|
+
`${C4.cyan}\u2570\u2500${C4.reset} ${C4.dim}\u2191\u2193 navega \xB7 Enter seleciona \xB7 Esc cancela${C4.reset}`
|
|
71209
|
+
);
|
|
71210
|
+
this.paintBlock(lines);
|
|
71211
|
+
}
|
|
71212
|
+
/** Repaint a block and leave the cursor just below it (for list/menu modes). */
|
|
71213
|
+
paintBlock(lines) {
|
|
71214
|
+
let s = "";
|
|
71215
|
+
if (this.lastRows > 1) s += `\x1B[${this.lastRows - 1}A`;
|
|
71216
|
+
s += "\r\x1B[0J";
|
|
71217
|
+
s += lines.join("\r\n");
|
|
71218
|
+
s += "\r";
|
|
71219
|
+
out2(s);
|
|
71220
|
+
this.lastRows = lines.length;
|
|
71221
|
+
}
|
|
71222
|
+
/** Move the cursor below a block of `rows` lines and clear it. */
|
|
71223
|
+
collapseTo(rows) {
|
|
71224
|
+
if (rows > 1) out2(`\x1B[${rows - 1}A`);
|
|
71225
|
+
out2("\r\x1B[0J");
|
|
71226
|
+
this.lastRows = 0;
|
|
71227
|
+
}
|
|
71228
|
+
};
|
|
71229
|
+
}
|
|
71230
|
+
});
|
|
71231
|
+
|
|
70235
71232
|
// index.ts
|
|
70236
71233
|
var index_exports = {};
|
|
70237
71234
|
async function main() {
|
|
70238
71235
|
const { createAgent: createAgent2 } = await Promise.resolve().then(() => (init_agent(), agent_exports));
|
|
70239
|
-
const { buildBanner: buildBanner2,
|
|
71236
|
+
const { buildBanner: buildBanner2, agentHeader: agentHeader2, ui: ui2 } = await Promise.resolve().then(() => (init_ui(), ui_exports));
|
|
71237
|
+
const { InteractiveInput: InteractiveInput2 } = await Promise.resolve().then(() => (init_interactive_input(), interactive_input_exports));
|
|
71238
|
+
const C5 = ui2.C;
|
|
70240
71239
|
if (!bootQuiet) {
|
|
70241
|
-
process.stdout.write(
|
|
70242
|
-
|
|
70243
|
-
`
|
|
70244
|
-
);
|
|
71240
|
+
process.stdout.write(`${C5.dim} booting local sandbox + agent\u2026${C5.reset}
|
|
71241
|
+
`);
|
|
70245
71242
|
}
|
|
70246
71243
|
const agent = await createAgent2();
|
|
70247
71244
|
const sys = agent.getSystemPrompt();
|
|
70248
71245
|
stopBootSpinner();
|
|
70249
|
-
|
|
71246
|
+
const version3 = clawfastVersion();
|
|
71247
|
+
process.stdout.write(buildBanner2(sys.length, version3));
|
|
71248
|
+
const updateNotice = getUpdateNotice(version3);
|
|
71249
|
+
if (updateNotice) {
|
|
71250
|
+
process.stdout.write(`${C5.yellow}\u2191 ${updateNotice}${C5.reset}
|
|
71251
|
+
`);
|
|
71252
|
+
}
|
|
71253
|
+
refreshUpdateCacheInBackground(version3);
|
|
71254
|
+
if (consumePostUpdateLaunch(version3)) {
|
|
71255
|
+
process.stdout.write(
|
|
71256
|
+
`${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}
|
|
71257
|
+
`
|
|
71258
|
+
);
|
|
71259
|
+
}
|
|
71260
|
+
process.stdout.write(
|
|
71261
|
+
`${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}
|
|
71262
|
+
`
|
|
71263
|
+
);
|
|
71264
|
+
const COMMANDS = [
|
|
71265
|
+
{ name: "/model", desc: "trocar o modelo (seletor com setas)" },
|
|
71266
|
+
{ name: "/skills", desc: "listar as skills instaladas" },
|
|
71267
|
+
{ name: "/skillcreator", desc: "criar uma nova skill" },
|
|
71268
|
+
{ name: "/system", desc: "salvar o system prompt (HTML) na \xC1rea de Trabalho" },
|
|
71269
|
+
{ name: "/nov", desc: "novidades desta vers\xE3o" },
|
|
71270
|
+
{ name: "/exit", desc: "fechar o clawfast" }
|
|
71271
|
+
];
|
|
70250
71272
|
const pasteInput = createPasteInput();
|
|
70251
|
-
const
|
|
70252
|
-
input: pasteInput.input,
|
|
70253
|
-
output: process.stdout,
|
|
70254
|
-
terminal: true
|
|
70255
|
-
});
|
|
71273
|
+
const inputUI = new InteractiveInput2(pasteInput, COMMANDS);
|
|
70256
71274
|
let closing = false;
|
|
70257
|
-
let
|
|
70258
|
-
let awaitingModelSelection = false;
|
|
70259
|
-
let skillCreator = null;
|
|
70260
|
-
const prompt = () => {
|
|
70261
|
-
rl.setPrompt(
|
|
70262
|
-
skillCreator ? skillPrompt(skillCreator.phase) : awaitingModelSelection ? modelPrompt() : shellPrompt2()
|
|
70263
|
-
);
|
|
70264
|
-
rl.prompt();
|
|
70265
|
-
};
|
|
71275
|
+
let shuttingDown = false;
|
|
70266
71276
|
let activeAbort = null;
|
|
70267
71277
|
let turnActive = false;
|
|
70268
71278
|
let exitArmed = false;
|
|
70269
71279
|
let exitTimer = null;
|
|
70270
|
-
let lastSigint = 0;
|
|
70271
71280
|
const armExit = () => {
|
|
70272
71281
|
exitArmed = true;
|
|
70273
71282
|
if (exitTimer) clearTimeout(exitTimer);
|
|
@@ -70276,69 +71285,58 @@ async function main() {
|
|
|
70276
71285
|
exitTimer = null;
|
|
70277
71286
|
}, 2e3);
|
|
70278
71287
|
};
|
|
70279
|
-
const
|
|
70280
|
-
|
|
70281
|
-
|
|
70282
|
-
|
|
70283
|
-
|
|
70284
|
-
|
|
70285
|
-
|
|
70286
|
-
|
|
70287
|
-
|
|
70288
|
-
|
|
70289
|
-
|
|
70290
|
-
|
|
70291
|
-
|
|
70292
|
-
|
|
70293
|
-
|
|
70294
|
-
|
|
70295
|
-
|
|
70296
|
-
|
|
70297
|
-
|
|
70298
|
-
|
|
70299
|
-
|
|
70300
|
-
|
|
70301
|
-
`
|
|
70302
|
-
|
|
70303
|
-
} else {
|
|
70304
|
-
process.stdout.write(
|
|
70305
|
-
`
|
|
70306
|
-
${ui2.C.dim}Ctrl+C de novo para fechar${ui2.C.reset}
|
|
71288
|
+
const shutdown = async () => {
|
|
71289
|
+
if (shuttingDown) return;
|
|
71290
|
+
shuttingDown = true;
|
|
71291
|
+
closing = true;
|
|
71292
|
+
pasteInput.dispose();
|
|
71293
|
+
process.stdout.write("\nClosing sandbox...\n");
|
|
71294
|
+
await agent.close();
|
|
71295
|
+
process.exit(0);
|
|
71296
|
+
};
|
|
71297
|
+
const desktopDir = () => {
|
|
71298
|
+
const home = import_node_os6.default.homedir();
|
|
71299
|
+
const candidates = [
|
|
71300
|
+
process.env.OneDrive ? import_node_path9.default.join(process.env.OneDrive, "Desktop") : null,
|
|
71301
|
+
process.env.USERPROFILE ? import_node_path9.default.join(process.env.USERPROFILE, "Desktop") : null,
|
|
71302
|
+
import_node_path9.default.join(home, "Desktop"),
|
|
71303
|
+
import_node_path9.default.join(home, "\xC1rea de Trabalho"),
|
|
71304
|
+
import_node_path9.default.join(home, "OneDrive", "Desktop")
|
|
71305
|
+
].filter((p) => Boolean(p));
|
|
71306
|
+
return candidates.find((p) => (0, import_node_fs8.existsSync)(p)) ?? home;
|
|
71307
|
+
};
|
|
71308
|
+
const printFatal = (err) => {
|
|
71309
|
+
process.stderr.write(
|
|
71310
|
+
`
|
|
71311
|
+
[fatal] ${err instanceof Error ? err.stack || err.message : String(err)}
|
|
70307
71312
|
`
|
|
70308
|
-
|
|
70309
|
-
if (!awaitingModelSelection) prompt();
|
|
70310
|
-
}
|
|
70311
|
-
armExit();
|
|
71313
|
+
);
|
|
70312
71314
|
};
|
|
70313
|
-
|
|
70314
|
-
process.on("SIGINT", handleSigint);
|
|
70315
|
-
rl.on("SIGINT", handleSigint);
|
|
71315
|
+
let skillCreator = null;
|
|
70316
71316
|
const printSkillList = () => {
|
|
70317
71317
|
const skills = listSkills();
|
|
70318
71318
|
if (skills.length === 0) {
|
|
70319
71319
|
process.stdout.write(
|
|
70320
71320
|
`
|
|
70321
|
-
${
|
|
71321
|
+
${C5.dim}nenhuma skill instalada. crie uma com /skillcreator${C5.reset}
|
|
70322
71322
|
`
|
|
70323
71323
|
);
|
|
70324
71324
|
return;
|
|
70325
71325
|
}
|
|
70326
71326
|
process.stdout.write(
|
|
70327
71327
|
`
|
|
70328
|
-
${
|
|
71328
|
+
${C5.cyan}skills instaladas${C5.reset} ${C5.dim}(${skillsDir()})${C5.reset}
|
|
70329
71329
|
`
|
|
70330
71330
|
);
|
|
70331
71331
|
for (const s of skills) {
|
|
70332
|
-
const flags = s.always ? ` ${
|
|
71332
|
+
const flags = s.always ? ` ${C5.yellow}[sempre]${C5.reset}` : "";
|
|
70333
71333
|
process.stdout.write(
|
|
70334
|
-
` ${
|
|
71334
|
+
` ${C5.green}${s.name}${C5.reset}${flags} ${C5.dim}\u2014${C5.reset} ${s.description}
|
|
70335
71335
|
`
|
|
70336
71336
|
);
|
|
70337
71337
|
}
|
|
70338
|
-
process.stdout.write(
|
|
70339
|
-
|
|
70340
|
-
`
|
|
70341
|
-
);
|
|
71338
|
+
process.stdout.write(`${C5.dim}remover: /skill delete <nome>${C5.reset}
|
|
71339
|
+
`);
|
|
70342
71340
|
};
|
|
70343
71341
|
const handleSkillCommand = (input) => {
|
|
70344
71342
|
if (input === "/skillcreator") {
|
|
@@ -70351,9 +71349,9 @@ ${ui2.C.cyan}skills instaladas${ui2.C.reset} ${ui2.C.dim}(${skillsDir()})${ui2.C
|
|
|
70351
71349
|
};
|
|
70352
71350
|
process.stdout.write(
|
|
70353
71351
|
`
|
|
70354
|
-
${
|
|
70355
|
-
${
|
|
70356
|
-
${
|
|
71352
|
+
${C5.greenB}criar skill${C5.reset} ${C5.dim}(/cancelar para abortar)${C5.reset}
|
|
71353
|
+
${C5.dim}skills ficam disponiveis para TODOS os modelos; o conteudo completo so e carregado quando o pedido casa com a skill.${C5.reset}
|
|
71354
|
+
${C5.cyan}nome da skill?${C5.reset} ${C5.dim}(ex: xss-recon)${C5.reset}
|
|
70357
71355
|
`
|
|
70358
71356
|
);
|
|
70359
71357
|
return;
|
|
@@ -70371,29 +71369,27 @@ ${ui2.C.cyan}nome da skill?${ui2.C.reset} ${ui2.C.dim}(ex: xss-recon)${ui2.C.res
|
|
|
70371
71369
|
}
|
|
70372
71370
|
if (sub === "delete" || sub === "rm" || sub === "remove") {
|
|
70373
71371
|
if (!arg) {
|
|
70374
|
-
process.stdout.write(
|
|
70375
|
-
|
|
70376
|
-
`
|
|
70377
|
-
);
|
|
71372
|
+
process.stdout.write(`${C5.yellow}uso: /skill delete <nome>${C5.reset}
|
|
71373
|
+
`);
|
|
70378
71374
|
return;
|
|
70379
71375
|
}
|
|
70380
71376
|
if (deleteSkill(arg)) {
|
|
70381
71377
|
await agent.refreshSkills();
|
|
70382
71378
|
process.stdout.write(
|
|
70383
|
-
`${
|
|
71379
|
+
`${C5.green}\u2713 skill '${slugify(arg)}' removida${C5.reset}
|
|
70384
71380
|
`
|
|
70385
71381
|
);
|
|
70386
71382
|
} else {
|
|
70387
71383
|
process.stdout.write(
|
|
70388
|
-
`${
|
|
71384
|
+
`${C5.yellow}skill '${arg}' nao encontrada${C5.reset}
|
|
70389
71385
|
`
|
|
70390
71386
|
);
|
|
70391
71387
|
}
|
|
70392
71388
|
return;
|
|
70393
71389
|
}
|
|
70394
71390
|
process.stdout.write(
|
|
70395
|
-
`${
|
|
70396
|
-
${
|
|
71391
|
+
`${C5.yellow}subcomando desconhecido: ${sub}${C5.reset}
|
|
71392
|
+
${C5.dim}use: /skillcreator | /skills | /skill delete <nome>${C5.reset}
|
|
70397
71393
|
`
|
|
70398
71394
|
);
|
|
70399
71395
|
};
|
|
@@ -70401,7 +71397,7 @@ ${ui2.C.dim}use: /skillcreator | /skills | /skill delete <nome>${ui2.C.reset}
|
|
|
70401
71397
|
const text2 = sc.bodyLines.join("\n");
|
|
70402
71398
|
const lines = text2 ? text2.split("\n").length : 0;
|
|
70403
71399
|
process.stdout.write(
|
|
70404
|
-
`${
|
|
71400
|
+
`${C5.dim} capturado: ${lines} linhas, ${text2.length} chars \u2014 continue colando, /fim para salvar, /desfazer para remover o ultimo, /cancelar para abortar${C5.reset}
|
|
70405
71401
|
`
|
|
70406
71402
|
);
|
|
70407
71403
|
};
|
|
@@ -70410,11 +71406,9 @@ ${ui2.C.dim}use: /skillcreator | /skills | /skill delete <nome>${ui2.C.reset}
|
|
|
70410
71406
|
if (!sc) return;
|
|
70411
71407
|
if (input === "/cancelar" || input === "/cancel") {
|
|
70412
71408
|
skillCreator = null;
|
|
70413
|
-
process.stdout.write(
|
|
70414
|
-
|
|
70415
|
-
|
|
70416
|
-
`
|
|
70417
|
-
);
|
|
71409
|
+
process.stdout.write(`
|
|
71410
|
+
${C5.dim}criacao de skill cancelada${C5.reset}
|
|
71411
|
+
`);
|
|
70418
71412
|
return;
|
|
70419
71413
|
}
|
|
70420
71414
|
switch (sc.phase) {
|
|
@@ -70422,7 +71416,7 @@ ${ui2.C.dim}criacao de skill cancelada${ui2.C.reset}
|
|
|
70422
71416
|
const slug = slugify(input);
|
|
70423
71417
|
if (!slug) {
|
|
70424
71418
|
process.stdout.write(
|
|
70425
|
-
`${
|
|
71419
|
+
`${C5.yellow}nome invalido \u2014 tente de novo${C5.reset}
|
|
70426
71420
|
`
|
|
70427
71421
|
);
|
|
70428
71422
|
return;
|
|
@@ -70430,22 +71424,20 @@ ${ui2.C.dim}criacao de skill cancelada${ui2.C.reset}
|
|
|
70430
71424
|
sc.name = slug;
|
|
70431
71425
|
if (listSkills().some((s) => s.name === slug)) {
|
|
70432
71426
|
process.stdout.write(
|
|
70433
|
-
`${
|
|
71427
|
+
`${C5.yellow}ja existe uma skill '${slug}' \u2014 sera sobrescrita${C5.reset}
|
|
70434
71428
|
`
|
|
70435
71429
|
);
|
|
70436
71430
|
}
|
|
70437
71431
|
sc.phase = "desc";
|
|
70438
|
-
process.stdout.write(
|
|
70439
|
-
|
|
70440
|
-
`
|
|
70441
|
-
);
|
|
71432
|
+
process.stdout.write(`${C5.cyan}descricao curta (1 linha)?${C5.reset}
|
|
71433
|
+
`);
|
|
70442
71434
|
return;
|
|
70443
71435
|
}
|
|
70444
71436
|
case "desc": {
|
|
70445
71437
|
sc.description = input;
|
|
70446
71438
|
sc.phase = "triggers";
|
|
70447
71439
|
process.stdout.write(
|
|
70448
|
-
`${
|
|
71440
|
+
`${C5.cyan}palavras-gatilho?${C5.reset} ${C5.dim}(separadas por virgula; Enter usa o proprio nome)${C5.reset}
|
|
70449
71441
|
`
|
|
70450
71442
|
);
|
|
70451
71443
|
return;
|
|
@@ -70457,7 +71449,7 @@ ${ui2.C.dim}criacao de skill cancelada${ui2.C.reset}
|
|
|
70457
71449
|
sc.phase = "body";
|
|
70458
71450
|
sc.bodyLines.push(line.replace(/\r$/, ""));
|
|
70459
71451
|
process.stdout.write(
|
|
70460
|
-
`${
|
|
71452
|
+
`${C5.yellow}isso parece a skill, nao gatilhos \u2014 capturei como conteudo.${C5.reset}
|
|
70461
71453
|
`
|
|
70462
71454
|
);
|
|
70463
71455
|
printBodyTally(sc);
|
|
@@ -70466,7 +71458,7 @@ ${ui2.C.dim}criacao de skill cancelada${ui2.C.reset}
|
|
|
70466
71458
|
sc.triggers = input ? input.split(",").map((t) => t.trim()).filter(Boolean) : [];
|
|
70467
71459
|
sc.phase = "body";
|
|
70468
71460
|
process.stdout.write(
|
|
70469
|
-
`${
|
|
71461
|
+
`${C5.cyan}cole ou escreva a skill agora${C5.reset} ${C5.dim}(qualquer tamanho). termine com uma linha contendo so /fim${C5.reset}
|
|
70470
71462
|
`
|
|
70471
71463
|
);
|
|
70472
71464
|
return;
|
|
@@ -70476,7 +71468,7 @@ ${ui2.C.dim}criacao de skill cancelada${ui2.C.reset}
|
|
|
70476
71468
|
const body = sc.bodyLines.join("\n").trim();
|
|
70477
71469
|
if (!body) {
|
|
70478
71470
|
process.stdout.write(
|
|
70479
|
-
`${
|
|
71471
|
+
`${C5.yellow}corpo vazio \u2014 cole algum conteudo ou /cancelar${C5.reset}
|
|
70480
71472
|
`
|
|
70481
71473
|
);
|
|
70482
71474
|
return;
|
|
@@ -70491,22 +71483,20 @@ ${ui2.C.dim}criacao de skill cancelada${ui2.C.reset}
|
|
|
70491
71483
|
await agent.refreshSkills();
|
|
70492
71484
|
process.stdout.write(
|
|
70493
71485
|
`
|
|
70494
|
-
${
|
|
70495
|
-
${
|
|
71486
|
+
${C5.green}\u2713 skill '${res.skill.name}' ${res.overwritten ? "atualizada" : "criada"}${C5.reset} ${C5.dim}(${res.file})${C5.reset}
|
|
71487
|
+
${C5.dim}ja disponivel para todos os modelos nesta sessao.${C5.reset}
|
|
70496
71488
|
`
|
|
70497
71489
|
);
|
|
70498
71490
|
return;
|
|
70499
71491
|
}
|
|
70500
71492
|
if (input === "/desfazer" || input === "/undo") {
|
|
70501
71493
|
if (sc.bodyLines.length === 0) {
|
|
70502
|
-
process.stdout.write(
|
|
70503
|
-
|
|
70504
|
-
`
|
|
70505
|
-
);
|
|
71494
|
+
process.stdout.write(`${C5.dim}nada para desfazer${C5.reset}
|
|
71495
|
+
`);
|
|
70506
71496
|
} else {
|
|
70507
71497
|
sc.bodyLines.pop();
|
|
70508
71498
|
process.stdout.write(
|
|
70509
|
-
`${
|
|
71499
|
+
`${C5.yellow}ultimo trecho removido.${C5.reset}
|
|
70510
71500
|
`
|
|
70511
71501
|
);
|
|
70512
71502
|
printBodyTally(sc);
|
|
@@ -70519,203 +71509,204 @@ ${ui2.C.dim}ja disponivel para todos os modelos nesta sessao.${ui2.C.reset}
|
|
|
70519
71509
|
}
|
|
70520
71510
|
}
|
|
70521
71511
|
};
|
|
71512
|
+
const printModelResult = (result) => {
|
|
71513
|
+
process.stdout.write(
|
|
71514
|
+
`${result.ok ? `${C5.green}\u2713` : `${C5.red}\u2717`} ${result.message}${C5.reset}
|
|
71515
|
+
`
|
|
71516
|
+
);
|
|
71517
|
+
};
|
|
71518
|
+
const openModelSelector = async () => {
|
|
71519
|
+
const state = agent.getModelSelection();
|
|
71520
|
+
const items = [
|
|
71521
|
+
{
|
|
71522
|
+
label: "Auto \u2014 cadeia de fallback autom\xE1tica",
|
|
71523
|
+
hint: "tenta os modelos em ordem"
|
|
71524
|
+
},
|
|
71525
|
+
...state.chain.map((c) => ({ label: c.label, hint: c.key }))
|
|
71526
|
+
];
|
|
71527
|
+
const activeIdx = state.mode === "auto" ? 0 : Math.max(
|
|
71528
|
+
0,
|
|
71529
|
+
1 + state.chain.findIndex((c) => c.key === state.activeModelKey)
|
|
71530
|
+
);
|
|
71531
|
+
const choice2 = await inputUI.select("selecionar modelo", items, activeIdx);
|
|
71532
|
+
if (choice2 === null) {
|
|
71533
|
+
process.stdout.write(`${C5.dim}sele\xE7\xE3o de modelo cancelada${C5.reset}
|
|
71534
|
+
`);
|
|
71535
|
+
return;
|
|
71536
|
+
}
|
|
71537
|
+
const arg = choice2 === 0 ? "auto" : state.chain[choice2 - 1].key;
|
|
71538
|
+
try {
|
|
71539
|
+
printModelResult(await agent.setModelSelection(arg));
|
|
71540
|
+
} catch (err) {
|
|
71541
|
+
printFatal(err);
|
|
71542
|
+
}
|
|
71543
|
+
};
|
|
70522
71544
|
const handleLine = async (line) => {
|
|
70523
71545
|
if (closing) return;
|
|
70524
71546
|
const input = line.trim();
|
|
70525
71547
|
if (skillCreator) {
|
|
70526
71548
|
await handleSkillCreatorLine(line, input);
|
|
70527
|
-
if (!closing) prompt();
|
|
70528
71549
|
return;
|
|
70529
71550
|
}
|
|
70530
71551
|
if (input === "/exit" || input === "/quit") {
|
|
70531
71552
|
closing = true;
|
|
70532
|
-
rl.close();
|
|
70533
71553
|
return;
|
|
70534
71554
|
}
|
|
70535
71555
|
if (input === "/skillcreator" || input === "/skill" || input === "/skills") {
|
|
70536
71556
|
handleSkillCommand(input);
|
|
70537
|
-
if (!closing) prompt();
|
|
70538
71557
|
return;
|
|
70539
71558
|
}
|
|
70540
71559
|
if (input.startsWith("/skill ") || input.startsWith("/skills ")) {
|
|
70541
71560
|
await handleSkillSubcommand(input);
|
|
70542
|
-
if (!closing) prompt();
|
|
70543
71561
|
return;
|
|
70544
71562
|
}
|
|
70545
|
-
if (
|
|
70546
|
-
|
|
70547
|
-
|
|
70548
|
-
|
|
70549
|
-
|
|
70550
|
-
${ui2.C.dim}selecao de modelo cancelada${ui2.C.reset}
|
|
70551
|
-
`
|
|
70552
|
-
);
|
|
70553
|
-
if (!closing) prompt();
|
|
70554
|
-
return;
|
|
70555
|
-
}
|
|
71563
|
+
if (input === "/model" || input === "/models") {
|
|
71564
|
+
await openModelSelector();
|
|
71565
|
+
return;
|
|
71566
|
+
}
|
|
71567
|
+
if (input.startsWith("/model ") || input.startsWith("/models ")) {
|
|
70556
71568
|
const arg = input.replace(/^\/models?\s*/, "");
|
|
70557
71569
|
try {
|
|
70558
|
-
|
|
70559
|
-
process.stdout.write(formatModelSelection(result));
|
|
70560
|
-
awaitingModelSelection = !result.ok;
|
|
71570
|
+
printModelResult(await agent.setModelSelection(arg));
|
|
70561
71571
|
} catch (err) {
|
|
70562
|
-
|
|
70563
|
-
`
|
|
70564
|
-
[fatal] ${err instanceof Error ? err.stack || err.message : String(err)}
|
|
70565
|
-
`
|
|
70566
|
-
);
|
|
70567
|
-
awaitingModelSelection = false;
|
|
71572
|
+
printFatal(err);
|
|
70568
71573
|
}
|
|
70569
|
-
if (!closing) prompt();
|
|
70570
71574
|
return;
|
|
70571
71575
|
}
|
|
70572
|
-
if (
|
|
70573
|
-
|
|
70574
|
-
|
|
70575
|
-
|
|
70576
|
-
|
|
70577
|
-
|
|
71576
|
+
if (input === "/system") {
|
|
71577
|
+
const sysText = agent.getSystemPrompt();
|
|
71578
|
+
const audit = agent.getSystemPromptAudit();
|
|
71579
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").replace("T", "_").slice(0, 19);
|
|
71580
|
+
const filePath = import_node_path9.default.join(
|
|
71581
|
+
desktopDir(),
|
|
71582
|
+
`clawfast-system-prompt_${stamp}.html`
|
|
71583
|
+
);
|
|
71584
|
+
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"}`;
|
|
71585
|
+
const b64 = Buffer.from(sysText, "utf8").toString("base64");
|
|
71586
|
+
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>`;
|
|
70578
71587
|
try {
|
|
70579
|
-
|
|
70580
|
-
awaitingModelSelection = !arg && result.ok;
|
|
71588
|
+
await (0, import_promises2.writeFile)(filePath, html, "utf8");
|
|
70581
71589
|
process.stdout.write(
|
|
70582
|
-
|
|
71590
|
+
`${C5.green}\u2713 system prompt salvo${C5.reset} ${C5.dim}(${sysText.length.toLocaleString()} caracteres \u2014 abra no navegador)${C5.reset}
|
|
71591
|
+
${C5.cyan}${filePath}${C5.reset}
|
|
71592
|
+
`
|
|
70583
71593
|
);
|
|
70584
71594
|
} catch (err) {
|
|
70585
|
-
process.
|
|
70586
|
-
|
|
70587
|
-
[fatal] ${err instanceof Error ? err.stack || err.message : String(err)}
|
|
71595
|
+
process.stdout.write(
|
|
71596
|
+
`${C5.red}\u2717 n\xE3o consegui salvar o arquivo:${C5.reset} ${err instanceof Error ? err.message : String(err)}
|
|
70588
71597
|
`
|
|
70589
71598
|
);
|
|
70590
|
-
awaitingModelSelection = false;
|
|
70591
71599
|
}
|
|
70592
|
-
if (!closing) prompt();
|
|
70593
71600
|
return;
|
|
70594
71601
|
}
|
|
70595
|
-
if (input === "/
|
|
70596
|
-
const sys2 = agent.getSystemPrompt();
|
|
70597
|
-
const audit = agent.getSystemPromptAudit();
|
|
71602
|
+
if (input === "/nov" || input === "/novidades") {
|
|
70598
71603
|
process.stdout.write(
|
|
70599
|
-
|
|
70600
|
-
|
|
70601
|
-
);
|
|
70602
|
-
process.stdout.write(
|
|
70603
|
-
`\x1B[90mfonte: ${audit.source} | verificado: ${audit.requiredMarkersVerified ? "sim" : "nao"} | chars: ${audit.chars.toLocaleString()}${audit.dumpPath ? ` | dump: ${audit.dumpPath}` : ""}\x1B[0m
|
|
71604
|
+
`
|
|
71605
|
+
${C5.cyan}${renderNews(clawfastVersion())}${C5.reset}
|
|
70604
71606
|
`
|
|
70605
71607
|
);
|
|
70606
|
-
process.stdout.write(sys2 + "\n");
|
|
70607
|
-
process.stdout.write(`\x1B[90m\u2500\u2500\u2500\u2500 fim do system prompt \u2500\u2500\u2500\u2500\x1B[0m
|
|
70608
|
-
`);
|
|
70609
|
-
if (!closing) prompt();
|
|
70610
71608
|
return;
|
|
70611
71609
|
}
|
|
71610
|
+
if (!input) return;
|
|
70612
71611
|
process.stdout.write("\n" + agentHeader2());
|
|
70613
71612
|
activeAbort = new AbortController();
|
|
70614
71613
|
turnActive = true;
|
|
70615
|
-
|
|
71614
|
+
inputUI.beginTurn(
|
|
71615
|
+
(l) => {
|
|
71616
|
+
if (agent.isRunningCommand()) agent.sendStdin(l);
|
|
71617
|
+
},
|
|
71618
|
+
() => {
|
|
71619
|
+
if (exitArmed) {
|
|
71620
|
+
closing = true;
|
|
71621
|
+
activeAbort?.abort();
|
|
71622
|
+
return;
|
|
71623
|
+
}
|
|
71624
|
+
if (activeAbort && !activeAbort.signal.aborted) {
|
|
71625
|
+
activeAbort.abort();
|
|
71626
|
+
process.stdout.write(
|
|
71627
|
+
`
|
|
71628
|
+
${C5.dim}interrompido \u2014 Ctrl+C de novo para fechar${C5.reset}
|
|
71629
|
+
`
|
|
71630
|
+
);
|
|
71631
|
+
}
|
|
71632
|
+
armExit();
|
|
71633
|
+
}
|
|
71634
|
+
);
|
|
70616
71635
|
try {
|
|
70617
71636
|
await agent.send(input, activeAbort.signal);
|
|
70618
71637
|
} catch (err) {
|
|
70619
|
-
|
|
70620
|
-
`
|
|
70621
|
-
[fatal] ${err instanceof Error ? err.stack || err.message : String(err)}
|
|
70622
|
-
`
|
|
70623
|
-
);
|
|
71638
|
+
printFatal(err);
|
|
70624
71639
|
} finally {
|
|
71640
|
+
inputUI.endTurn();
|
|
70625
71641
|
activeAbort = null;
|
|
70626
71642
|
turnActive = false;
|
|
70627
71643
|
}
|
|
70628
|
-
if (!closing) prompt();
|
|
70629
71644
|
};
|
|
70630
|
-
|
|
70631
|
-
|
|
70632
|
-
const line = pasteInput.expand(rawLine);
|
|
71645
|
+
process.removeAllListeners("SIGINT");
|
|
71646
|
+
process.on("SIGINT", () => {
|
|
70633
71647
|
if (turnActive) {
|
|
70634
|
-
|
|
70635
|
-
agent.sendStdin(line);
|
|
70636
|
-
}
|
|
71648
|
+
activeAbort?.abort();
|
|
70637
71649
|
return;
|
|
70638
71650
|
}
|
|
70639
|
-
|
|
70640
|
-
commandQueue = commandQueue.then(() => handleLine(line)).catch((err) => {
|
|
70641
|
-
process.stderr.write(
|
|
70642
|
-
`
|
|
70643
|
-
[fatal] ${err instanceof Error ? err.stack || err.message : String(err)}
|
|
70644
|
-
`
|
|
70645
|
-
);
|
|
70646
|
-
}).finally(() => {
|
|
70647
|
-
if (!closing) rl.resume();
|
|
70648
|
-
});
|
|
70649
|
-
});
|
|
70650
|
-
rl.on("close", async () => {
|
|
70651
|
-
closing = true;
|
|
70652
|
-
pasteInput.dispose();
|
|
70653
|
-
await commandQueue.catch(() => void 0);
|
|
70654
|
-
process.stdout.write("\nClosing sandbox...\n");
|
|
70655
|
-
await agent.close();
|
|
70656
|
-
process.exit(0);
|
|
71651
|
+
void shutdown();
|
|
70657
71652
|
});
|
|
70658
71653
|
process.on("exit", () => pasteInput.dispose());
|
|
70659
|
-
|
|
70660
|
-
|
|
70661
|
-
|
|
70662
|
-
|
|
70663
|
-
|
|
70664
|
-
|
|
70665
|
-
|
|
70666
|
-
|
|
70667
|
-
|
|
70668
|
-
|
|
70669
|
-
|
|
70670
|
-
reset: "\x1B[0m",
|
|
70671
|
-
bold: "\x1B[1m",
|
|
70672
|
-
dim: "\x1B[90m",
|
|
70673
|
-
green: "\x1B[32m",
|
|
70674
|
-
cyan: "\x1B[36m",
|
|
70675
|
-
yellow: "\x1B[33m",
|
|
70676
|
-
red: "\x1B[31m"
|
|
71654
|
+
const currentSkillLabel = () => {
|
|
71655
|
+
if (!skillCreator) return void 0;
|
|
71656
|
+
switch (skillCreator.phase) {
|
|
71657
|
+
case "name":
|
|
71658
|
+
return "nome";
|
|
71659
|
+
case "desc":
|
|
71660
|
+
return "descri\xE7\xE3o";
|
|
71661
|
+
case "triggers":
|
|
71662
|
+
return "gatilhos";
|
|
71663
|
+
default:
|
|
71664
|
+
return "skill";
|
|
70677
71665
|
}
|
|
70678
71666
|
};
|
|
70679
|
-
|
|
70680
|
-
|
|
70681
|
-
|
|
70682
|
-
|
|
70683
|
-
""
|
|
70684
|
-
|
|
70685
|
-
|
|
70686
|
-
|
|
70687
|
-
|
|
70688
|
-
|
|
70689
|
-
|
|
70690
|
-
|
|
70691
|
-
);
|
|
70692
|
-
}
|
|
70693
|
-
if (result.selection.unavailable.length > 0) {
|
|
70694
|
-
lines.push("", `${C4.yellow}${C4.bold}Indisponiveis${C4.reset}`);
|
|
70695
|
-
for (const group of result.selection.unavailable) {
|
|
70696
|
-
lines.push(`${group.provider}: ${C4.dim}${group.reason}${C4.reset}`);
|
|
70697
|
-
for (const model of group.models) {
|
|
70698
|
-
lines.push(` - ${model.label} ${C4.dim}(${model.key})${C4.reset}`);
|
|
71667
|
+
while (!closing) {
|
|
71668
|
+
const skillLabel = currentSkillLabel();
|
|
71669
|
+
const res = await inputUI.prompt(skillLabel ? { label: skillLabel } : {});
|
|
71670
|
+
if (closing) break;
|
|
71671
|
+
if (res.type === "eof") {
|
|
71672
|
+
closing = true;
|
|
71673
|
+
break;
|
|
71674
|
+
}
|
|
71675
|
+
if (res.type === "sigint") {
|
|
71676
|
+
if (exitArmed) {
|
|
71677
|
+
closing = true;
|
|
71678
|
+
break;
|
|
70699
71679
|
}
|
|
71680
|
+
process.stdout.write(`${C5.dim}Ctrl+C de novo para fechar${C5.reset}
|
|
71681
|
+
`);
|
|
71682
|
+
armExit();
|
|
71683
|
+
continue;
|
|
71684
|
+
}
|
|
71685
|
+
if (!skillCreator && !res.value.trim()) continue;
|
|
71686
|
+
exitArmed = false;
|
|
71687
|
+
try {
|
|
71688
|
+
await handleLine(res.value);
|
|
71689
|
+
} catch (err) {
|
|
71690
|
+
printFatal(err);
|
|
70700
71691
|
}
|
|
70701
71692
|
}
|
|
70702
|
-
|
|
70703
|
-
"",
|
|
70704
|
-
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}`
|
|
70705
|
-
);
|
|
70706
|
-
return `
|
|
70707
|
-
${lines.join("\n")}
|
|
70708
|
-
`;
|
|
71693
|
+
await shutdown();
|
|
70709
71694
|
}
|
|
70710
|
-
var
|
|
71695
|
+
var import_node_os6, import_node_path9, import_node_fs8, import_promises2, deepseekEnabled, configuredModelProviders;
|
|
70711
71696
|
var init_index = __esm({
|
|
70712
71697
|
"index.ts"() {
|
|
70713
71698
|
"use strict";
|
|
70714
|
-
|
|
71699
|
+
import_node_os6 = __toESM(require("node:os"));
|
|
71700
|
+
import_node_path9 = __toESM(require("node:path"));
|
|
71701
|
+
import_node_fs8 = require("node:fs");
|
|
71702
|
+
import_promises2 = require("node:fs/promises");
|
|
70715
71703
|
init_paste_input();
|
|
70716
71704
|
init_boot_ui();
|
|
70717
71705
|
init_config();
|
|
70718
71706
|
init_skills();
|
|
71707
|
+
init_version();
|
|
71708
|
+
init_update();
|
|
71709
|
+
init_news();
|
|
70719
71710
|
loadClawfastEnv();
|
|
70720
71711
|
deepseekEnabled = /^(1|true|yes)$/i.test(process.env.DEEPSEEK_ENABLED?.trim() ?? "") || Boolean(process.env.DEEPSEEK_BASE_URL?.trim()) || Boolean(process.env.DEEPSEEK_API_KEY?.trim());
|
|
70721
71712
|
configuredModelProviders = [
|
|
@@ -70740,8 +71731,38 @@ var init_index = __esm({
|
|
|
70740
71731
|
// boot.ts
|
|
70741
71732
|
init_boot_ui();
|
|
70742
71733
|
init_config();
|
|
71734
|
+
init_version();
|
|
71735
|
+
init_update();
|
|
70743
71736
|
loadClawfastEnv();
|
|
71737
|
+
async function handleSubcommand() {
|
|
71738
|
+
const arg = process.argv[2];
|
|
71739
|
+
if (arg === "--version" || arg === "-v" || arg === "version") {
|
|
71740
|
+
process.stdout.write(`clawfast ${clawfastVersion()}
|
|
71741
|
+
`);
|
|
71742
|
+
process.exit(0);
|
|
71743
|
+
}
|
|
71744
|
+
if (arg === "update" || arg === "upgrade") {
|
|
71745
|
+
process.stdout.write(`\x1B[92mAtualizando o clawfast\u2026\x1B[0m
|
|
71746
|
+
`);
|
|
71747
|
+
const code = await runSelfUpdate();
|
|
71748
|
+
if (code === 0) {
|
|
71749
|
+
process.stdout.write(
|
|
71750
|
+
`
|
|
71751
|
+
\x1B[92m\x1B[1mSeja bem vindo ao submundo.\x1B[0m
|
|
71752
|
+
`
|
|
71753
|
+
);
|
|
71754
|
+
} else {
|
|
71755
|
+
process.stdout.write(
|
|
71756
|
+
`
|
|
71757
|
+
\x1B[91mFalha ao atualizar (codigo ${code}).\x1B[0m Tente manualmente: \x1B[1mnpm install -g clawfast@latest\x1B[0m
|
|
71758
|
+
`
|
|
71759
|
+
);
|
|
71760
|
+
}
|
|
71761
|
+
process.exit(code === 0 ? 0 : 1);
|
|
71762
|
+
}
|
|
71763
|
+
}
|
|
70744
71764
|
async function boot() {
|
|
71765
|
+
await handleSubcommand();
|
|
70745
71766
|
const hasKey = await ensureProviderKey();
|
|
70746
71767
|
if (!hasKey) process.exit(1);
|
|
70747
71768
|
startBootSpinner();
|