clawfast 1.0.3 → 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 +1282 -475
- package/package.json +1 -1
package/dist/clawfast.cjs
CHANGED
|
@@ -86,8 +86,8 @@ var require_main = __commonJS({
|
|
|
86
86
|
"../node_modules/.pnpm/dotenv@17.4.2/node_modules/dotenv/lib/main.js"(exports2, module2) {
|
|
87
87
|
"use strict";
|
|
88
88
|
var fs6 = require("fs");
|
|
89
|
-
var
|
|
90
|
-
var
|
|
89
|
+
var path10 = require("path");
|
|
90
|
+
var os7 = require("os");
|
|
91
91
|
var crypto2 = require("crypto");
|
|
92
92
|
var TIPS = [
|
|
93
93
|
"\u25C8 encrypted .env [www.dotenvx.com]",
|
|
@@ -225,7 +225,7 @@ var require_main = __commonJS({
|
|
|
225
225
|
possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`;
|
|
226
226
|
}
|
|
227
227
|
} else {
|
|
228
|
-
possibleVaultPath =
|
|
228
|
+
possibleVaultPath = path10.resolve(process.cwd(), ".env.vault");
|
|
229
229
|
}
|
|
230
230
|
if (fs6.existsSync(possibleVaultPath)) {
|
|
231
231
|
return possibleVaultPath;
|
|
@@ -233,7 +233,7 @@ var require_main = __commonJS({
|
|
|
233
233
|
return null;
|
|
234
234
|
}
|
|
235
235
|
function _resolveHome(envPath) {
|
|
236
|
-
return envPath[0] === "~" ?
|
|
236
|
+
return envPath[0] === "~" ? path10.join(os7.homedir(), envPath.slice(1)) : envPath;
|
|
237
237
|
}
|
|
238
238
|
function _configVault(options) {
|
|
239
239
|
const debug = parseBoolean(process.env.DOTENV_CONFIG_DEBUG || options && options.debug);
|
|
@@ -250,7 +250,7 @@ var require_main = __commonJS({
|
|
|
250
250
|
return { parsed };
|
|
251
251
|
}
|
|
252
252
|
function configDotenv(options) {
|
|
253
|
-
const dotenvPath =
|
|
253
|
+
const dotenvPath = path10.resolve(process.cwd(), ".env");
|
|
254
254
|
let encoding = "utf8";
|
|
255
255
|
let processEnv = process.env;
|
|
256
256
|
if (options && options.processEnv != null) {
|
|
@@ -278,13 +278,13 @@ var require_main = __commonJS({
|
|
|
278
278
|
}
|
|
279
279
|
let lastError;
|
|
280
280
|
const parsedAll = {};
|
|
281
|
-
for (const
|
|
281
|
+
for (const path11 of optionPaths) {
|
|
282
282
|
try {
|
|
283
|
-
const parsed = DotenvModule.parse(fs6.readFileSync(
|
|
283
|
+
const parsed = DotenvModule.parse(fs6.readFileSync(path11, { encoding }));
|
|
284
284
|
DotenvModule.populate(parsedAll, parsed, options);
|
|
285
285
|
} catch (e) {
|
|
286
286
|
if (debug) {
|
|
287
|
-
_debug(`failed to load ${
|
|
287
|
+
_debug(`failed to load ${path11} ${e.message}`);
|
|
288
288
|
}
|
|
289
289
|
lastError = e;
|
|
290
290
|
}
|
|
@@ -297,7 +297,7 @@ var require_main = __commonJS({
|
|
|
297
297
|
const shortPaths = [];
|
|
298
298
|
for (const filePath of optionPaths) {
|
|
299
299
|
try {
|
|
300
|
-
const relative2 =
|
|
300
|
+
const relative2 = path10.relative(process.cwd(), filePath);
|
|
301
301
|
shortPaths.push(relative2);
|
|
302
302
|
} catch (e) {
|
|
303
303
|
if (debug) {
|
|
@@ -502,7 +502,7 @@ var clawfastVersion, isDevVersion, isNewerVersion;
|
|
|
502
502
|
var init_version = __esm({
|
|
503
503
|
"src/version.ts"() {
|
|
504
504
|
"use strict";
|
|
505
|
-
clawfastVersion = () => true ? "
|
|
505
|
+
clawfastVersion = () => true ? "2.0.0" : "0.0.0-dev";
|
|
506
506
|
isDevVersion = () => clawfastVersion().includes("-dev");
|
|
507
507
|
isNewerVersion = (a, b) => {
|
|
508
508
|
const parse3 = (v) => v.split("-")[0].split(".").map((n) => Number.parseInt(n, 10) || 0);
|
|
@@ -699,14 +699,14 @@ var init_paste_input = __esm({
|
|
|
699
699
|
/** Replace any paste chips in a submitted line with their real content. */
|
|
700
700
|
expand(line) {
|
|
701
701
|
if (this.pastes.size === 0) return line;
|
|
702
|
-
let
|
|
702
|
+
let out3 = line;
|
|
703
703
|
for (const [chip, content] of this.pastes) {
|
|
704
|
-
if (
|
|
705
|
-
|
|
704
|
+
if (out3.includes(chip)) {
|
|
705
|
+
out3 = out3.split(chip).join(content);
|
|
706
706
|
this.pastes.delete(chip);
|
|
707
707
|
}
|
|
708
708
|
}
|
|
709
|
-
return
|
|
709
|
+
return out3;
|
|
710
710
|
}
|
|
711
711
|
/** How many captured pastes are still waiting to be expanded. */
|
|
712
712
|
pendingCount() {
|
|
@@ -878,10 +878,18 @@ var init_news = __esm({
|
|
|
878
878
|
import_node_path4 = __toESM(require("node:path"));
|
|
879
879
|
init_config();
|
|
880
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
|
+
],
|
|
881
889
|
"1.0.3": [
|
|
882
890
|
"Atualizacao: `clawfast update` atualiza o CLI e mostra as boas-vindas; aparece um aviso quando ha versao nova; /nov lista as novidades.",
|
|
883
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.",
|
|
884
|
-
"Modelos na NVIDIA build:
|
|
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).",
|
|
885
893
|
"Resiliencia a rate limit (429): cai para os outros modelos como contingencia e espera/retenta a cadeia automaticamente."
|
|
886
894
|
]
|
|
887
895
|
};
|
|
@@ -1505,10 +1513,10 @@ function mergeDefs(...defs) {
|
|
|
1505
1513
|
function cloneDef(schema) {
|
|
1506
1514
|
return mergeDefs(schema._zod.def);
|
|
1507
1515
|
}
|
|
1508
|
-
function getElementAtPath(obj,
|
|
1509
|
-
if (!
|
|
1516
|
+
function getElementAtPath(obj, path10) {
|
|
1517
|
+
if (!path10)
|
|
1510
1518
|
return obj;
|
|
1511
|
-
return
|
|
1519
|
+
return path10.reduce((acc, key) => acc?.[key], obj);
|
|
1512
1520
|
}
|
|
1513
1521
|
function promiseAllObject(promisesObj) {
|
|
1514
1522
|
const keys = Object.keys(promisesObj);
|
|
@@ -1836,11 +1844,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
1836
1844
|
}
|
|
1837
1845
|
return false;
|
|
1838
1846
|
}
|
|
1839
|
-
function prefixIssues(
|
|
1847
|
+
function prefixIssues(path10, issues) {
|
|
1840
1848
|
return issues.map((iss) => {
|
|
1841
1849
|
var _a25;
|
|
1842
1850
|
(_a25 = iss).path ?? (_a25.path = []);
|
|
1843
|
-
iss.path.unshift(
|
|
1851
|
+
iss.path.unshift(path10);
|
|
1844
1852
|
return iss;
|
|
1845
1853
|
});
|
|
1846
1854
|
}
|
|
@@ -2058,16 +2066,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
2058
2066
|
}
|
|
2059
2067
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
2060
2068
|
const fieldErrors = { _errors: [] };
|
|
2061
|
-
const processError = (error52,
|
|
2069
|
+
const processError = (error52, path10 = []) => {
|
|
2062
2070
|
for (const issue2 of error52.issues) {
|
|
2063
2071
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
2064
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
2072
|
+
issue2.errors.map((issues) => processError({ issues }, [...path10, ...issue2.path]));
|
|
2065
2073
|
} else if (issue2.code === "invalid_key") {
|
|
2066
|
-
processError({ issues: issue2.issues }, [...
|
|
2074
|
+
processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
|
|
2067
2075
|
} else if (issue2.code === "invalid_element") {
|
|
2068
|
-
processError({ issues: issue2.issues }, [...
|
|
2076
|
+
processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
|
|
2069
2077
|
} else {
|
|
2070
|
-
const fullpath = [...
|
|
2078
|
+
const fullpath = [...path10, ...issue2.path];
|
|
2071
2079
|
if (fullpath.length === 0) {
|
|
2072
2080
|
fieldErrors._errors.push(mapper(issue2));
|
|
2073
2081
|
} else {
|
|
@@ -2094,17 +2102,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
2094
2102
|
}
|
|
2095
2103
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
2096
2104
|
const result = { errors: [] };
|
|
2097
|
-
const processError = (error52,
|
|
2105
|
+
const processError = (error52, path10 = []) => {
|
|
2098
2106
|
var _a25, _b18;
|
|
2099
2107
|
for (const issue2 of error52.issues) {
|
|
2100
2108
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
2101
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
2109
|
+
issue2.errors.map((issues) => processError({ issues }, [...path10, ...issue2.path]));
|
|
2102
2110
|
} else if (issue2.code === "invalid_key") {
|
|
2103
|
-
processError({ issues: issue2.issues }, [...
|
|
2111
|
+
processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
|
|
2104
2112
|
} else if (issue2.code === "invalid_element") {
|
|
2105
|
-
processError({ issues: issue2.issues }, [...
|
|
2113
|
+
processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
|
|
2106
2114
|
} else {
|
|
2107
|
-
const fullpath = [...
|
|
2115
|
+
const fullpath = [...path10, ...issue2.path];
|
|
2108
2116
|
if (fullpath.length === 0) {
|
|
2109
2117
|
result.errors.push(mapper(issue2));
|
|
2110
2118
|
continue;
|
|
@@ -2136,8 +2144,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
2136
2144
|
}
|
|
2137
2145
|
function toDotPath(_path) {
|
|
2138
2146
|
const segs = [];
|
|
2139
|
-
const
|
|
2140
|
-
for (const seg of
|
|
2147
|
+
const path10 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
2148
|
+
for (const seg of path10) {
|
|
2141
2149
|
if (typeof seg === "number")
|
|
2142
2150
|
segs.push(`[${seg}]`);
|
|
2143
2151
|
else if (typeof seg === "symbol")
|
|
@@ -12449,11 +12457,11 @@ function _catch(Class2, innerType, catchValue) {
|
|
|
12449
12457
|
});
|
|
12450
12458
|
}
|
|
12451
12459
|
// @__NO_SIDE_EFFECTS__
|
|
12452
|
-
function _pipe(Class2, in_,
|
|
12460
|
+
function _pipe(Class2, in_, out3) {
|
|
12453
12461
|
return new Class2({
|
|
12454
12462
|
type: "pipe",
|
|
12455
12463
|
in: in_,
|
|
12456
|
-
out:
|
|
12464
|
+
out: out3
|
|
12457
12465
|
});
|
|
12458
12466
|
}
|
|
12459
12467
|
// @__NO_SIDE_EFFECTS__
|
|
@@ -14689,19 +14697,19 @@ function _catch2(innerType, catchValue) {
|
|
|
14689
14697
|
function nan(params) {
|
|
14690
14698
|
return _nan(ZodNaN, params);
|
|
14691
14699
|
}
|
|
14692
|
-
function pipe(in_,
|
|
14700
|
+
function pipe(in_, out3) {
|
|
14693
14701
|
return new ZodPipe({
|
|
14694
14702
|
type: "pipe",
|
|
14695
14703
|
in: in_,
|
|
14696
|
-
out:
|
|
14704
|
+
out: out3
|
|
14697
14705
|
// ...util.normalizeParams(params),
|
|
14698
14706
|
});
|
|
14699
14707
|
}
|
|
14700
|
-
function codec(in_,
|
|
14708
|
+
function codec(in_, out3, params) {
|
|
14701
14709
|
return new ZodCodec({
|
|
14702
14710
|
type: "pipe",
|
|
14703
14711
|
in: in_,
|
|
14704
|
-
out:
|
|
14712
|
+
out: out3,
|
|
14705
14713
|
transform: params.decode,
|
|
14706
14714
|
reverseTransform: params.encode
|
|
14707
14715
|
});
|
|
@@ -15640,13 +15648,13 @@ function resolveRef(ref, ctx) {
|
|
|
15640
15648
|
if (!ref.startsWith("#")) {
|
|
15641
15649
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
15642
15650
|
}
|
|
15643
|
-
const
|
|
15644
|
-
if (
|
|
15651
|
+
const path10 = ref.slice(1).split("/").filter(Boolean);
|
|
15652
|
+
if (path10.length === 0) {
|
|
15645
15653
|
return ctx.rootSchema;
|
|
15646
15654
|
}
|
|
15647
15655
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
15648
|
-
if (
|
|
15649
|
-
const key =
|
|
15656
|
+
if (path10[0] === defsKey) {
|
|
15657
|
+
const key = path10[1];
|
|
15650
15658
|
if (!key || !ctx.defs[key]) {
|
|
15651
15659
|
throw new Error(`Reference not found: ${ref}`);
|
|
15652
15660
|
}
|
|
@@ -16835,8 +16843,8 @@ var init_parseUtil = __esm({
|
|
|
16835
16843
|
init_errors3();
|
|
16836
16844
|
init_en2();
|
|
16837
16845
|
makeIssue = (params) => {
|
|
16838
|
-
const { data, path:
|
|
16839
|
-
const fullPath = [...
|
|
16846
|
+
const { data, path: path10, errorMaps, issueData } = params;
|
|
16847
|
+
const fullPath = [...path10, ...issueData.path || []];
|
|
16840
16848
|
const fullIssue = {
|
|
16841
16849
|
...issueData,
|
|
16842
16850
|
path: fullPath
|
|
@@ -17119,11 +17127,11 @@ var init_types = __esm({
|
|
|
17119
17127
|
init_parseUtil();
|
|
17120
17128
|
init_util2();
|
|
17121
17129
|
ParseInputLazyPath = class {
|
|
17122
|
-
constructor(parent, value,
|
|
17130
|
+
constructor(parent, value, path10, key) {
|
|
17123
17131
|
this._cachedPath = [];
|
|
17124
17132
|
this.parent = parent;
|
|
17125
17133
|
this.data = value;
|
|
17126
|
-
this._path =
|
|
17134
|
+
this._path = path10;
|
|
17127
17135
|
this._key = key;
|
|
17128
17136
|
}
|
|
17129
17137
|
get path() {
|
|
@@ -23163,7 +23171,7 @@ var require_auth_config = __commonJS({
|
|
|
23163
23171
|
});
|
|
23164
23172
|
module2.exports = __toCommonJS(auth_config_exports);
|
|
23165
23173
|
var fs6 = __toESM2(require("fs"));
|
|
23166
|
-
var
|
|
23174
|
+
var path10 = __toESM2(require("path"));
|
|
23167
23175
|
var import_token_util = require_token_util();
|
|
23168
23176
|
function getAuthConfigPath() {
|
|
23169
23177
|
const dataDir = (0, import_token_util.getVercelDataDir)();
|
|
@@ -23172,7 +23180,7 @@ var require_auth_config = __commonJS({
|
|
|
23172
23180
|
`Unable to find Vercel CLI data directory. Your platform: ${process.platform}. Supported: darwin, linux, win32.`
|
|
23173
23181
|
);
|
|
23174
23182
|
}
|
|
23175
|
-
return
|
|
23183
|
+
return path10.join(dataDir, "auth.json");
|
|
23176
23184
|
}
|
|
23177
23185
|
function readAuthConfig() {
|
|
23178
23186
|
try {
|
|
@@ -23191,7 +23199,7 @@ var require_auth_config = __commonJS({
|
|
|
23191
23199
|
}
|
|
23192
23200
|
function writeAuthConfig(config3) {
|
|
23193
23201
|
const authPath = getAuthConfigPath();
|
|
23194
|
-
const authDir =
|
|
23202
|
+
const authDir = path10.dirname(authPath);
|
|
23195
23203
|
if (!fs6.existsSync(authDir)) {
|
|
23196
23204
|
fs6.mkdirSync(authDir, { mode: 504, recursive: true });
|
|
23197
23205
|
}
|
|
@@ -23386,7 +23394,7 @@ var require_token_util = __commonJS({
|
|
|
23386
23394
|
saveToken: () => saveToken
|
|
23387
23395
|
});
|
|
23388
23396
|
module2.exports = __toCommonJS(token_util_exports);
|
|
23389
|
-
var
|
|
23397
|
+
var path10 = __toESM2(require("path"));
|
|
23390
23398
|
var fs6 = __toESM2(require("fs"));
|
|
23391
23399
|
var import_token_error = require_token_error();
|
|
23392
23400
|
var import_token_io = require_token_io();
|
|
@@ -23399,7 +23407,7 @@ var require_token_util = __commonJS({
|
|
|
23399
23407
|
if (!dataDir) {
|
|
23400
23408
|
return null;
|
|
23401
23409
|
}
|
|
23402
|
-
return
|
|
23410
|
+
return path10.join(dataDir, vercelFolder);
|
|
23403
23411
|
}
|
|
23404
23412
|
async function getVercelToken2(options) {
|
|
23405
23413
|
const authConfig = (0, import_auth_config.readAuthConfig)();
|
|
@@ -23475,7 +23483,7 @@ var require_token_util = __commonJS({
|
|
|
23475
23483
|
"Unable to find project root directory. Have you linked your project with `vc link?`"
|
|
23476
23484
|
);
|
|
23477
23485
|
}
|
|
23478
|
-
const prjPath =
|
|
23486
|
+
const prjPath = path10.join(dir, ".vercel", "project.json");
|
|
23479
23487
|
if (!fs6.existsSync(prjPath)) {
|
|
23480
23488
|
throw new import_token_error.VercelOidcTokenError(
|
|
23481
23489
|
"project.json not found, have you linked your project with `vc link?`"
|
|
@@ -23496,9 +23504,9 @@ var require_token_util = __commonJS({
|
|
|
23496
23504
|
"Unable to find user data directory. Please reach out to Vercel support."
|
|
23497
23505
|
);
|
|
23498
23506
|
}
|
|
23499
|
-
const tokenPath =
|
|
23507
|
+
const tokenPath = path10.join(dir, "com.vercel.token", `${projectId}.json`);
|
|
23500
23508
|
const tokenJson = JSON.stringify(token);
|
|
23501
|
-
fs6.mkdirSync(
|
|
23509
|
+
fs6.mkdirSync(path10.dirname(tokenPath), { mode: 504, recursive: true });
|
|
23502
23510
|
fs6.writeFileSync(tokenPath, tokenJson);
|
|
23503
23511
|
fs6.chmodSync(tokenPath, 432);
|
|
23504
23512
|
return;
|
|
@@ -23510,7 +23518,7 @@ var require_token_util = __commonJS({
|
|
|
23510
23518
|
"Unable to find user data directory. Please reach out to Vercel support."
|
|
23511
23519
|
);
|
|
23512
23520
|
}
|
|
23513
|
-
const tokenPath =
|
|
23521
|
+
const tokenPath = path10.join(dir, "com.vercel.token", `${projectId}.json`);
|
|
23514
23522
|
if (!fs6.existsSync(tokenPath)) {
|
|
23515
23523
|
return null;
|
|
23516
23524
|
}
|
|
@@ -35540,7 +35548,7 @@ function createOpenRouter(options = {}) {
|
|
|
35540
35548
|
);
|
|
35541
35549
|
const createChatModel = (modelId, settings = {}) => new OpenRouterChatLanguageModel(modelId, settings, {
|
|
35542
35550
|
provider: "openrouter.chat",
|
|
35543
|
-
url: ({ path:
|
|
35551
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
35544
35552
|
headers: getHeaders,
|
|
35545
35553
|
compatibility,
|
|
35546
35554
|
fetch: options.fetch,
|
|
@@ -35548,7 +35556,7 @@ function createOpenRouter(options = {}) {
|
|
|
35548
35556
|
});
|
|
35549
35557
|
const createCompletionModel = (modelId, settings = {}) => new OpenRouterCompletionLanguageModel(modelId, settings, {
|
|
35550
35558
|
provider: "openrouter.completion",
|
|
35551
|
-
url: ({ path:
|
|
35559
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
35552
35560
|
headers: getHeaders,
|
|
35553
35561
|
compatibility,
|
|
35554
35562
|
fetch: options.fetch,
|
|
@@ -35556,21 +35564,21 @@ function createOpenRouter(options = {}) {
|
|
|
35556
35564
|
});
|
|
35557
35565
|
const createEmbeddingModel = (modelId, settings = {}) => new OpenRouterEmbeddingModel(modelId, settings, {
|
|
35558
35566
|
provider: "openrouter.embedding",
|
|
35559
|
-
url: ({ path:
|
|
35567
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
35560
35568
|
headers: getHeaders,
|
|
35561
35569
|
fetch: options.fetch,
|
|
35562
35570
|
extraBody: options.extraBody
|
|
35563
35571
|
});
|
|
35564
35572
|
const createImageModel = (modelId, settings = {}) => new OpenRouterImageModel(modelId, settings, {
|
|
35565
35573
|
provider: "openrouter.image",
|
|
35566
|
-
url: ({ path:
|
|
35574
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
35567
35575
|
headers: getHeaders,
|
|
35568
35576
|
fetch: options.fetch,
|
|
35569
35577
|
extraBody: options.extraBody
|
|
35570
35578
|
});
|
|
35571
35579
|
const createVideoModel = (modelId, settings = {}) => new OpenRouterVideoModel(modelId, settings, {
|
|
35572
35580
|
provider: "openrouter.video",
|
|
35573
|
-
url: ({ path:
|
|
35581
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
35574
35582
|
headers: getHeaders,
|
|
35575
35583
|
fetch: options.fetch,
|
|
35576
35584
|
extraBody: options.extraBody
|
|
@@ -40106,37 +40114,37 @@ function createOpenAI(options = {}) {
|
|
|
40106
40114
|
);
|
|
40107
40115
|
const createChatModel = (modelId) => new OpenAIChatLanguageModel(modelId, {
|
|
40108
40116
|
provider: `${providerName}.chat`,
|
|
40109
|
-
url: ({ path:
|
|
40117
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
40110
40118
|
headers: getHeaders,
|
|
40111
40119
|
fetch: options.fetch
|
|
40112
40120
|
});
|
|
40113
40121
|
const createCompletionModel = (modelId) => new OpenAICompletionLanguageModel(modelId, {
|
|
40114
40122
|
provider: `${providerName}.completion`,
|
|
40115
|
-
url: ({ path:
|
|
40123
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
40116
40124
|
headers: getHeaders,
|
|
40117
40125
|
fetch: options.fetch
|
|
40118
40126
|
});
|
|
40119
40127
|
const createEmbeddingModel = (modelId) => new OpenAIEmbeddingModel(modelId, {
|
|
40120
40128
|
provider: `${providerName}.embedding`,
|
|
40121
|
-
url: ({ path:
|
|
40129
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
40122
40130
|
headers: getHeaders,
|
|
40123
40131
|
fetch: options.fetch
|
|
40124
40132
|
});
|
|
40125
40133
|
const createImageModel = (modelId) => new OpenAIImageModel(modelId, {
|
|
40126
40134
|
provider: `${providerName}.image`,
|
|
40127
|
-
url: ({ path:
|
|
40135
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
40128
40136
|
headers: getHeaders,
|
|
40129
40137
|
fetch: options.fetch
|
|
40130
40138
|
});
|
|
40131
40139
|
const createTranscriptionModel = (modelId) => new OpenAITranscriptionModel(modelId, {
|
|
40132
40140
|
provider: `${providerName}.transcription`,
|
|
40133
|
-
url: ({ path:
|
|
40141
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
40134
40142
|
headers: getHeaders,
|
|
40135
40143
|
fetch: options.fetch
|
|
40136
40144
|
});
|
|
40137
40145
|
const createSpeechModel = (modelId) => new OpenAISpeechModel(modelId, {
|
|
40138
40146
|
provider: `${providerName}.speech`,
|
|
40139
|
-
url: ({ path:
|
|
40147
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
40140
40148
|
headers: getHeaders,
|
|
40141
40149
|
fetch: options.fetch
|
|
40142
40150
|
});
|
|
@@ -40151,7 +40159,7 @@ function createOpenAI(options = {}) {
|
|
|
40151
40159
|
const createResponsesModel = (modelId) => {
|
|
40152
40160
|
return new OpenAIResponsesLanguageModel(modelId, {
|
|
40153
40161
|
provider: `${providerName}.responses`,
|
|
40154
|
-
url: ({ path:
|
|
40162
|
+
url: ({ path: path10 }) => `${baseURL}${path10}`,
|
|
40155
40163
|
headers: getHeaders,
|
|
40156
40164
|
fetch: options.fetch,
|
|
40157
40165
|
fileIdPrefixes: ["file-"]
|
|
@@ -45372,7 +45380,7 @@ function supportsMultimodalToolResults(modelName) {
|
|
|
45372
45380
|
const normalized = modelName.toLowerCase();
|
|
45373
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");
|
|
45374
45382
|
}
|
|
45375
|
-
var isRecord, isXaiModelSlug, isGeminiModelSlug, requestCanRouteToXai, requestCanRouteToGemini, hasOwnEncryptedContent, stripEncryptedContent, sanitizeOpenRouterRequestForXai, hasJsonRefKey, wrapToolContentIfGeminiRefSensitive, sanitizeOpenRouterRequestForGeminiFunctionResponses, patchKimiReasoningToolCalls, OPENROUTER_METADATA_HEADER, withOpenRouterMetadataHeader, openrouterPatchFetch, openrouter2, openai2, nvidia, deepseek, kimi, buildProviderMap, hasEnvValue, isDeepSeekEnabled, isKimiEnabled, CLI_MODEL_CHAIN, baseProviders, modelCutoffDates, modelDisplayNames, getModelDisplayName, getModelCutoffDate, myProvider;
|
|
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;
|
|
45376
45384
|
var init_providers = __esm({
|
|
45377
45385
|
"../lib/ai/providers.ts"() {
|
|
45378
45386
|
"use strict";
|
|
@@ -45532,10 +45540,43 @@ var init_providers = __esm({
|
|
|
45532
45540
|
name: "openai",
|
|
45533
45541
|
apiKey: process.env.OPENAI_API_KEY
|
|
45534
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
|
+
};
|
|
45535
45575
|
nvidia = createOpenAI({
|
|
45536
45576
|
name: "nvidia",
|
|
45537
45577
|
baseURL: process.env.NVIDIA_BASE_URL || "https://integrate.api.nvidia.com/v1",
|
|
45538
|
-
apiKey: process.env.NVIDIA_API_KEY
|
|
45578
|
+
apiKey: process.env.NVIDIA_API_KEY,
|
|
45579
|
+
fetch: nvidiaPatchFetch
|
|
45539
45580
|
});
|
|
45540
45581
|
deepseek = createOpenAI({
|
|
45541
45582
|
name: "deepseek",
|
|
@@ -45563,7 +45604,9 @@ var init_providers = __esm({
|
|
|
45563
45604
|
"model-opus-4.6": nvidia("nvidia/nemotron-3-ultra-550b-a55b"),
|
|
45564
45605
|
"model-kimi-k2.6": or("qwen/qwen3-coder:free"),
|
|
45565
45606
|
// NVIDIA build models — primary provider for the local CLI (chat-completions).
|
|
45566
|
-
"model-nvidia-
|
|
45607
|
+
"model-nvidia-mistral-medium-3.5": nvidia.chat(
|
|
45608
|
+
"mistralai/mistral-medium-3.5-128b"
|
|
45609
|
+
),
|
|
45567
45610
|
"model-nvidia-kimi-k2.6": nvidia.chat("moonshotai/kimi-k2.6"),
|
|
45568
45611
|
"model-nvidia-glm-5.1": nvidia.chat("z-ai/glm-5.1"),
|
|
45569
45612
|
"model-nvidia-qwen3.5-397b": nvidia.chat("qwen/qwen3.5-397b-a17b"),
|
|
@@ -45600,8 +45643,8 @@ var init_providers = __esm({
|
|
|
45600
45643
|
};
|
|
45601
45644
|
CLI_MODEL_CHAIN = [
|
|
45602
45645
|
...hasEnvValue("NVIDIA_API_KEY") ? [
|
|
45603
|
-
"model-nvidia-
|
|
45604
|
-
// NVIDIA
|
|
45646
|
+
"model-nvidia-mistral-medium-3.5",
|
|
45647
|
+
// NVIDIA mistralai/mistral-medium-3.5-128b
|
|
45605
45648
|
"model-nvidia-kimi-k2.6",
|
|
45606
45649
|
// NVIDIA moonshotai/kimi-k2.6
|
|
45607
45650
|
"model-nvidia-glm-5.1",
|
|
@@ -45628,7 +45671,7 @@ var init_providers = __esm({
|
|
|
45628
45671
|
"model-deepseek-v4-flash": "May 2025",
|
|
45629
45672
|
"model-opus-4.6": "May 2025",
|
|
45630
45673
|
"model-kimi-k2.6": "April 2024",
|
|
45631
|
-
"model-nvidia-
|
|
45674
|
+
"model-nvidia-mistral-medium-3.5": "Unknown",
|
|
45632
45675
|
"model-nvidia-kimi-k2.6": "April 2024",
|
|
45633
45676
|
"model-nvidia-glm-5.1": "Unknown",
|
|
45634
45677
|
"model-nvidia-qwen3.5-397b": "Unknown",
|
|
@@ -45652,7 +45695,7 @@ var init_providers = __esm({
|
|
|
45652
45695
|
"model-deepseek-v4-flash": "DeepSeek V4 Flash",
|
|
45653
45696
|
"model-opus-4.6": "Anthropic Claude Opus 4.6",
|
|
45654
45697
|
"model-kimi-k2.6": "Moonshot Kimi K2.6",
|
|
45655
|
-
"model-nvidia-
|
|
45698
|
+
"model-nvidia-mistral-medium-3.5": "NVIDIA - Mistral Medium 3.5",
|
|
45656
45699
|
"model-nvidia-kimi-k2.6": "NVIDIA - Moonshot Kimi K2.6",
|
|
45657
45700
|
"model-nvidia-glm-5.1": "NVIDIA - Z.ai GLM 5.1",
|
|
45658
45701
|
"model-nvidia-qwen3.5-397b": "NVIDIA - Qwen3.5 397B A17B",
|
|
@@ -48687,8 +48730,8 @@ var init_background_process_tracker = __esm({
|
|
|
48687
48730
|
/**
|
|
48688
48731
|
* Normalize file path for comparison
|
|
48689
48732
|
*/
|
|
48690
|
-
normalizePath(
|
|
48691
|
-
let normalized =
|
|
48733
|
+
normalizePath(path10) {
|
|
48734
|
+
let normalized = path10.trim().replace(/\/+/g, "/");
|
|
48692
48735
|
if (normalized.startsWith("./")) {
|
|
48693
48736
|
normalized = normalized.slice(2);
|
|
48694
48737
|
}
|
|
@@ -48926,8 +48969,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
|
|
|
48926
48969
|
return decodedFile;
|
|
48927
48970
|
};
|
|
48928
48971
|
}
|
|
48929
|
-
function normalizeWindowsPath(
|
|
48930
|
-
return
|
|
48972
|
+
function normalizeWindowsPath(path10) {
|
|
48973
|
+
return path10.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
|
|
48931
48974
|
}
|
|
48932
48975
|
var import_path;
|
|
48933
48976
|
var init_module_node = __esm({
|
|
@@ -51816,9 +51859,9 @@ async function addSourceContext(frames) {
|
|
|
51816
51859
|
LRU_FILE_CONTENTS_CACHE.reduce();
|
|
51817
51860
|
return frames;
|
|
51818
51861
|
}
|
|
51819
|
-
function getContextLinesFromFile(
|
|
51862
|
+
function getContextLinesFromFile(path10, ranges, output) {
|
|
51820
51863
|
return new Promise((resolve2) => {
|
|
51821
|
-
const stream = (0, import_node_fs5.createReadStream)(
|
|
51864
|
+
const stream = (0, import_node_fs5.createReadStream)(path10);
|
|
51822
51865
|
const lineReaded = (0, import_node_readline2.createInterface)({
|
|
51823
51866
|
input: stream
|
|
51824
51867
|
});
|
|
@@ -51833,7 +51876,7 @@ function getContextLinesFromFile(path8, ranges, output) {
|
|
|
51833
51876
|
let rangeStart = range[0];
|
|
51834
51877
|
let rangeEnd = range[1];
|
|
51835
51878
|
function onStreamError() {
|
|
51836
|
-
LRU_FILE_CONTENTS_FS_READ_FAILED.set(
|
|
51879
|
+
LRU_FILE_CONTENTS_FS_READ_FAILED.set(path10, 1);
|
|
51837
51880
|
lineReaded.close();
|
|
51838
51881
|
lineReaded.removeAllListeners();
|
|
51839
51882
|
destroyStreamAndResolve();
|
|
@@ -51894,8 +51937,8 @@ function clearLineContext(frame2) {
|
|
|
51894
51937
|
delete frame2.context_line;
|
|
51895
51938
|
delete frame2.post_context;
|
|
51896
51939
|
}
|
|
51897
|
-
function shouldSkipContextLinesForFile(
|
|
51898
|
-
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:");
|
|
51899
51942
|
}
|
|
51900
51943
|
function shouldSkipContextLinesForFrame(frame2) {
|
|
51901
51944
|
if (void 0 !== frame2.lineno && frame2.lineno > MAX_CONTEXTLINES_LINENO) return true;
|
|
@@ -51914,22 +51957,22 @@ function makeLineReaderRanges(lines) {
|
|
|
51914
51957
|
const line = lines[0];
|
|
51915
51958
|
if ("number" != typeof line) return [];
|
|
51916
51959
|
let current = makeContextRange(line);
|
|
51917
|
-
const
|
|
51960
|
+
const out3 = [];
|
|
51918
51961
|
while (true) {
|
|
51919
51962
|
if (i === lines.length - 1) {
|
|
51920
|
-
|
|
51963
|
+
out3.push(current);
|
|
51921
51964
|
break;
|
|
51922
51965
|
}
|
|
51923
51966
|
const next = lines[i + 1];
|
|
51924
51967
|
if ("number" != typeof next) break;
|
|
51925
51968
|
if (next <= current[1]) current[1] = next + DEFAULT_LINES_OF_CONTEXT;
|
|
51926
51969
|
else {
|
|
51927
|
-
|
|
51970
|
+
out3.push(current);
|
|
51928
51971
|
current = makeContextRange(next);
|
|
51929
51972
|
}
|
|
51930
51973
|
i++;
|
|
51931
51974
|
}
|
|
51932
|
-
return
|
|
51975
|
+
return out3;
|
|
51933
51976
|
}
|
|
51934
51977
|
function makeContextRange(line) {
|
|
51935
51978
|
return [
|
|
@@ -55447,8 +55490,8 @@ async function createE2BPtyHandle(sandbox, opts) {
|
|
|
55447
55490
|
sendInput(bytes) {
|
|
55448
55491
|
return pty.sendInput(pid, bytes);
|
|
55449
55492
|
},
|
|
55450
|
-
async resize(
|
|
55451
|
-
await pty.resize(pid, { cols, rows });
|
|
55493
|
+
async resize(cols2, rows) {
|
|
55494
|
+
await pty.resize(pid, { cols: cols2, rows });
|
|
55452
55495
|
},
|
|
55453
55496
|
async kill() {
|
|
55454
55497
|
const killed = await pty.kill(pid);
|
|
@@ -55589,9 +55632,9 @@ var init_pty_session_manager = __esm({
|
|
|
55589
55632
|
consumeDelta(session) {
|
|
55590
55633
|
const total = this.totalBufferBytes(session);
|
|
55591
55634
|
const start = Math.min(session.readCursor, total);
|
|
55592
|
-
const
|
|
55635
|
+
const out3 = this.sliceBuffer(session, start, total);
|
|
55593
55636
|
session.readCursor = total;
|
|
55594
|
-
return
|
|
55637
|
+
return out3;
|
|
55595
55638
|
}
|
|
55596
55639
|
/**
|
|
55597
55640
|
* Returns the full accumulated buffer without advancing `readCursor`.
|
|
@@ -55649,7 +55692,7 @@ var init_pty_session_manager = __esm({
|
|
|
55649
55692
|
}
|
|
55650
55693
|
sliceBuffer(session, start, end) {
|
|
55651
55694
|
if (end <= start) return new Uint8Array(0);
|
|
55652
|
-
const
|
|
55695
|
+
const out3 = new Uint8Array(end - start);
|
|
55653
55696
|
let outOffset = 0;
|
|
55654
55697
|
let cursor = 0;
|
|
55655
55698
|
for (const chunk of session.buffer) {
|
|
@@ -55662,11 +55705,11 @@ var init_pty_session_manager = __esm({
|
|
|
55662
55705
|
if (chunkStart >= end) break;
|
|
55663
55706
|
const sliceStart = Math.max(0, start - chunkStart);
|
|
55664
55707
|
const sliceEnd = Math.min(chunk.byteLength, end - chunkStart);
|
|
55665
|
-
|
|
55708
|
+
out3.set(chunk.subarray(sliceStart, sliceEnd), outOffset);
|
|
55666
55709
|
outOffset += sliceEnd - sliceStart;
|
|
55667
55710
|
cursor = chunkEnd;
|
|
55668
55711
|
}
|
|
55669
|
-
return
|
|
55712
|
+
return out3;
|
|
55670
55713
|
}
|
|
55671
55714
|
async killAndRemove(session, _reason) {
|
|
55672
55715
|
if (session.closing) {
|
|
@@ -55924,7 +55967,7 @@ var require_xterm_headless = __commonJS({
|
|
|
55924
55967
|
};
|
|
55925
55968
|
Object.defineProperty(t2, "__esModule", { value: true }), t2.InputHandler = t2.WindowsOptionsReportType = void 0, t2.isValidColorIndex = k;
|
|
55926
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;
|
|
55927
|
-
function
|
|
55970
|
+
function C5(e3, t3) {
|
|
55928
55971
|
if (e3 > 24) return t3.setWinLines || false;
|
|
55929
55972
|
switch (e3) {
|
|
55930
55973
|
case 1:
|
|
@@ -56059,7 +56102,7 @@ var require_xterm_headless = __commonJS({
|
|
|
56059
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);
|
|
56060
56103
|
}
|
|
56061
56104
|
registerCsiHandler(e3, t3) {
|
|
56062
|
-
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)));
|
|
56063
56106
|
}
|
|
56064
56107
|
registerDcsHandler(e3, t3) {
|
|
56065
56108
|
return this._parser.registerDcsHandler(e3, new v.DcsHandler(t3));
|
|
@@ -56573,7 +56616,7 @@ var require_xterm_headless = __commonJS({
|
|
|
56573
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;
|
|
56574
56617
|
}
|
|
56575
56618
|
windowOptions(e3) {
|
|
56576
|
-
if (!
|
|
56619
|
+
if (!C5(e3.params[0], this._optionsService.rawOptions.windowOptions)) return true;
|
|
56577
56620
|
const t3 = e3.length > 1 ? e3.params[1] : 0;
|
|
56578
56621
|
switch (e3.params[0]) {
|
|
56579
56622
|
case 14:
|
|
@@ -61700,12 +61743,12 @@ function applyDelta(source, delta) {
|
|
|
61700
61743
|
zDelta.pos += cnt;
|
|
61701
61744
|
break;
|
|
61702
61745
|
case ";": {
|
|
61703
|
-
const
|
|
61704
|
-
if (cnt !== checksum(
|
|
61746
|
+
const out3 = zOut.toByteArray(source);
|
|
61747
|
+
if (cnt !== checksum(out3))
|
|
61705
61748
|
throw new Error("bad checksum");
|
|
61706
61749
|
if (total !== limit)
|
|
61707
61750
|
throw new Error("generated size does not match predicted size");
|
|
61708
|
-
return
|
|
61751
|
+
return out3;
|
|
61709
61752
|
}
|
|
61710
61753
|
default:
|
|
61711
61754
|
throw new Error("unknown delta operator");
|
|
@@ -66279,11 +66322,11 @@ async function createCentrifugoPtyHandle(sandbox, opts) {
|
|
|
66279
66322
|
};
|
|
66280
66323
|
await publish(payload);
|
|
66281
66324
|
},
|
|
66282
|
-
async resize(
|
|
66325
|
+
async resize(cols2, rows) {
|
|
66283
66326
|
const payload = {
|
|
66284
66327
|
type: "pty_resize",
|
|
66285
66328
|
sessionId,
|
|
66286
|
-
cols,
|
|
66329
|
+
cols: cols2,
|
|
66287
66330
|
rows,
|
|
66288
66331
|
targetConnectionId: connectionId
|
|
66289
66332
|
};
|
|
@@ -66518,7 +66561,7 @@ In using these tools, adhere to the following guidelines:
|
|
|
66518
66561
|
timeout,
|
|
66519
66562
|
interactive
|
|
66520
66563
|
}, { toolCallId, abortSignal }) => {
|
|
66521
|
-
const
|
|
66564
|
+
const cols2 = DEFAULT_PTY_COLS;
|
|
66522
66565
|
const rows = DEFAULT_PTY_ROWS;
|
|
66523
66566
|
let activePtySessionId;
|
|
66524
66567
|
let emitQueue = Promise.resolve();
|
|
@@ -66613,20 +66656,20 @@ In using these tools, adhere to the following guidelines:
|
|
|
66613
66656
|
}
|
|
66614
66657
|
}
|
|
66615
66658
|
const session = await ptySessionManager2.create(chatId, {
|
|
66616
|
-
cols,
|
|
66659
|
+
cols: cols2,
|
|
66617
66660
|
rows,
|
|
66618
66661
|
createHandle: async () => {
|
|
66619
66662
|
if (isCentrifugo) {
|
|
66620
66663
|
const { createCentrifugoPtyHandle: createCentrifugoPtyHandle2 } = await Promise.resolve().then(() => (init_centrifugo_pty_adapter(), centrifugo_pty_adapter_exports));
|
|
66621
66664
|
return createCentrifugoPtyHandle2(sandbox, {
|
|
66622
66665
|
command,
|
|
66623
|
-
cols,
|
|
66666
|
+
cols: cols2,
|
|
66624
66667
|
rows,
|
|
66625
66668
|
envs: caidoEnvVars
|
|
66626
66669
|
});
|
|
66627
66670
|
}
|
|
66628
66671
|
return createE2BPtyHandle(sandbox, {
|
|
66629
|
-
cols,
|
|
66672
|
+
cols: cols2,
|
|
66630
66673
|
rows,
|
|
66631
66674
|
envs: caidoEnvVars
|
|
66632
66675
|
});
|
|
@@ -67305,8 +67348,8 @@ var init_logger2 = __esm({
|
|
|
67305
67348
|
});
|
|
67306
67349
|
|
|
67307
67350
|
// ../lib/ai/tools/file.ts
|
|
67308
|
-
function isSpritPath(
|
|
67309
|
-
return
|
|
67351
|
+
function isSpritPath(path10) {
|
|
67352
|
+
return path10.split(/[\\/]/).some((segment) => segment.toLowerCase() === "sprit");
|
|
67310
67353
|
}
|
|
67311
67354
|
function getViewSandboxType(sandbox) {
|
|
67312
67355
|
return isCentrifugoSandbox(sandbox) ? "centrifugo" : "e2b";
|
|
@@ -67337,7 +67380,7 @@ function captureFileViewImageUsage(args) {
|
|
|
67337
67380
|
const {
|
|
67338
67381
|
context: context2,
|
|
67339
67382
|
sandbox,
|
|
67340
|
-
path:
|
|
67383
|
+
path: path10,
|
|
67341
67384
|
outcome,
|
|
67342
67385
|
durationMs,
|
|
67343
67386
|
mediaType,
|
|
@@ -67355,7 +67398,7 @@ function captureFileViewImageUsage(args) {
|
|
|
67355
67398
|
model: getActiveModelName(context2),
|
|
67356
67399
|
configured_model: context2.modelName,
|
|
67357
67400
|
sandbox_type: getViewSandboxType(sandbox),
|
|
67358
|
-
file_extension: getFileExtension(
|
|
67401
|
+
file_extension: getFileExtension(path10),
|
|
67359
67402
|
outcome,
|
|
67360
67403
|
success: outcome === "success",
|
|
67361
67404
|
duration_ms: durationMs,
|
|
@@ -67429,22 +67472,22 @@ async function runSandboxCommand(sandbox, command, envVars, timeoutMs = 6e4) {
|
|
|
67429
67472
|
function isWindowsSandbox(sandbox) {
|
|
67430
67473
|
return isCentrifugoSandbox(sandbox) && sandbox.isWindows();
|
|
67431
67474
|
}
|
|
67432
|
-
function getWindowsNativePath(
|
|
67433
|
-
if (/^[A-Za-z]:[\\/]/.test(
|
|
67434
|
-
if (
|
|
67435
|
-
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, "\\")}`;
|
|
67436
67479
|
}
|
|
67437
|
-
return
|
|
67480
|
+
return path10.replace(/\//g, "\\");
|
|
67438
67481
|
}
|
|
67439
|
-
function getPythonPathForSandbox(sandbox,
|
|
67440
|
-
return isWindowsSandbox(sandbox) ? getWindowsNativePath(
|
|
67482
|
+
function getPythonPathForSandbox(sandbox, path10) {
|
|
67483
|
+
return isWindowsSandbox(sandbox) ? getWindowsNativePath(path10) : path10;
|
|
67441
67484
|
}
|
|
67442
|
-
function toWindowsBashPath(
|
|
67443
|
-
const drive =
|
|
67485
|
+
function toWindowsBashPath(path10) {
|
|
67486
|
+
const drive = path10.match(/^([A-Za-z]):[\\/](.*)$/);
|
|
67444
67487
|
if (drive) {
|
|
67445
67488
|
return `/${drive[1].toLowerCase()}/${drive[2].replace(/\\/g, "/")}`;
|
|
67446
67489
|
}
|
|
67447
|
-
return
|
|
67490
|
+
return path10.replace(/\\/g, "/");
|
|
67448
67491
|
}
|
|
67449
67492
|
async function detectSandboxShell(sandbox) {
|
|
67450
67493
|
if (!isWindowsSandbox(sandbox)) return "bash";
|
|
@@ -67483,8 +67526,8 @@ PY`;
|
|
|
67483
67526
|
}
|
|
67484
67527
|
}
|
|
67485
67528
|
}
|
|
67486
|
-
async function getSandboxFileState(sandbox,
|
|
67487
|
-
const pythonPath = getPythonPathForSandbox(sandbox,
|
|
67529
|
+
async function getSandboxFileState(sandbox, path10) {
|
|
67530
|
+
const pythonPath = getPythonPathForSandbox(sandbox, path10);
|
|
67488
67531
|
const result = await runPythonScript(
|
|
67489
67532
|
sandbox,
|
|
67490
67533
|
FILE_STATE_SCRIPT,
|
|
@@ -67501,23 +67544,23 @@ async function getSandboxFileState(sandbox, path8) {
|
|
|
67501
67544
|
if (result.exitCode !== 0) {
|
|
67502
67545
|
return {
|
|
67503
67546
|
kind: "unknown",
|
|
67504
|
-
path:
|
|
67547
|
+
path: path10,
|
|
67505
67548
|
error: result.stderr || result.stdout || "file state command failed"
|
|
67506
67549
|
};
|
|
67507
67550
|
}
|
|
67508
67551
|
try {
|
|
67509
67552
|
const payload = JSON.parse(result.stdout.trim());
|
|
67510
67553
|
if (payload.kind === "file" && typeof payload.sizeBytes === "number" && Number.isFinite(payload.sizeBytes)) {
|
|
67511
|
-
return { ...payload, path:
|
|
67554
|
+
return { ...payload, path: path10 };
|
|
67512
67555
|
}
|
|
67513
67556
|
if (payload.kind === "missing" || payload.kind === "not_file") {
|
|
67514
|
-
return { ...payload, path:
|
|
67557
|
+
return { ...payload, path: path10 };
|
|
67515
67558
|
}
|
|
67516
67559
|
} catch {
|
|
67517
67560
|
}
|
|
67518
67561
|
return {
|
|
67519
67562
|
kind: "unknown",
|
|
67520
|
-
path:
|
|
67563
|
+
path: path10,
|
|
67521
67564
|
error: result.stderr || result.stdout || "invalid file state response"
|
|
67522
67565
|
};
|
|
67523
67566
|
}
|
|
@@ -67549,8 +67592,8 @@ ${numberedContent}${truncatedNotice}${footerNotice}`;
|
|
|
67549
67592
|
})
|
|
67550
67593
|
};
|
|
67551
67594
|
}
|
|
67552
|
-
async function readSandboxTextFile(sandbox,
|
|
67553
|
-
const pythonPath = getPythonPathForSandbox(sandbox,
|
|
67595
|
+
async function readSandboxTextFile(sandbox, path10, range) {
|
|
67596
|
+
const pythonPath = getPythonPathForSandbox(sandbox, path10);
|
|
67554
67597
|
const envVars = {
|
|
67555
67598
|
HACKERAI_FILE_READ_PATH: pythonPath,
|
|
67556
67599
|
HACKERAI_FILE_READ_RANGE_START: String(range?.[0] ?? 0),
|
|
@@ -67578,40 +67621,40 @@ async function readSandboxTextFile(sandbox, path8, range) {
|
|
|
67578
67621
|
}
|
|
67579
67622
|
return payload;
|
|
67580
67623
|
}
|
|
67581
|
-
async function readSandboxTextFileWithFallback(sandbox,
|
|
67624
|
+
async function readSandboxTextFileWithFallback(sandbox, path10, range) {
|
|
67582
67625
|
try {
|
|
67583
|
-
return await readSandboxTextFile(sandbox,
|
|
67626
|
+
return await readSandboxTextFile(sandbox, path10, range);
|
|
67584
67627
|
} catch (error51) {
|
|
67585
67628
|
const errorMessage = error51 instanceof Error ? error51.message : String(error51);
|
|
67586
67629
|
if (errorMessage.startsWith("Invalid ") || errorMessage.includes("File not found")) {
|
|
67587
67630
|
throw error51;
|
|
67588
67631
|
}
|
|
67589
|
-
const state = await getSandboxFileState(sandbox,
|
|
67632
|
+
const state = await getSandboxFileState(sandbox, path10);
|
|
67590
67633
|
if (state.kind === "unknown") {
|
|
67591
67634
|
throw new Error(
|
|
67592
|
-
`Unable to determine file size for ${
|
|
67635
|
+
`Unable to determine file size for ${path10}; refusing to load the file into memory. ${state.error}`
|
|
67593
67636
|
);
|
|
67594
67637
|
}
|
|
67595
67638
|
if (state.kind === "missing") {
|
|
67596
|
-
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}`);
|
|
67597
67640
|
}
|
|
67598
67641
|
if (state.kind === "not_file") {
|
|
67599
|
-
throw new Error(`File is not a regular file: ${
|
|
67642
|
+
throw new Error(`File is not a regular file: ${path10}`);
|
|
67600
67643
|
}
|
|
67601
67644
|
if (state.sizeBytes > MAX_TEXT_FILE_READ_BYTES) {
|
|
67602
67645
|
if (range) {
|
|
67603
67646
|
throw new Error(
|
|
67604
|
-
`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.`
|
|
67605
67648
|
);
|
|
67606
67649
|
}
|
|
67607
67650
|
return {
|
|
67608
|
-
path:
|
|
67651
|
+
path: path10,
|
|
67609
67652
|
sizeBytes: state.sizeBytes,
|
|
67610
67653
|
totalLines: 0,
|
|
67611
67654
|
tooLarge: true
|
|
67612
67655
|
};
|
|
67613
67656
|
}
|
|
67614
|
-
const fileContent = await sandbox.files.read(
|
|
67657
|
+
const fileContent = await sandbox.files.read(path10, {
|
|
67615
67658
|
user: "user"
|
|
67616
67659
|
});
|
|
67617
67660
|
const lines = fileContent.split("\n");
|
|
@@ -67640,7 +67683,7 @@ async function readSandboxTextFileWithFallback(sandbox, path8, range) {
|
|
|
67640
67683
|
const startIndex = start - 1;
|
|
67641
67684
|
const endIndex = end === -1 ? lines.length : end;
|
|
67642
67685
|
return {
|
|
67643
|
-
path:
|
|
67686
|
+
path: path10,
|
|
67644
67687
|
sizeBytes: Buffer.byteLength(fileContent),
|
|
67645
67688
|
totalLines: lines.length,
|
|
67646
67689
|
content: lines.slice(startIndex, endIndex).join("\n"),
|
|
@@ -67648,7 +67691,7 @@ async function readSandboxTextFileWithFallback(sandbox, path8, range) {
|
|
|
67648
67691
|
};
|
|
67649
67692
|
}
|
|
67650
67693
|
return {
|
|
67651
|
-
path:
|
|
67694
|
+
path: path10,
|
|
67652
67695
|
sizeBytes: Buffer.byteLength(fileContent),
|
|
67653
67696
|
totalLines: lines.length,
|
|
67654
67697
|
content: fileContent,
|
|
@@ -67656,7 +67699,7 @@ async function readSandboxTextFileWithFallback(sandbox, path8, range) {
|
|
|
67656
67699
|
};
|
|
67657
67700
|
}
|
|
67658
67701
|
}
|
|
67659
|
-
async function appendSandboxTextFile(sandbox,
|
|
67702
|
+
async function appendSandboxTextFile(sandbox, path10, text2) {
|
|
67660
67703
|
const tempPath = `/tmp/hackerai_append_${Date.now()}_${Math.random().toString(36).slice(2)}.tmp`;
|
|
67661
67704
|
await sandbox.files.write(tempPath, text2, {
|
|
67662
67705
|
user: "user"
|
|
@@ -67665,7 +67708,7 @@ async function appendSandboxTextFile(sandbox, path8, text2) {
|
|
|
67665
67708
|
sandbox,
|
|
67666
67709
|
APPEND_TEXT_FILE_SCRIPT,
|
|
67667
67710
|
{
|
|
67668
|
-
HACKERAI_FILE_APPEND_TARGET_PATH: getPythonPathForSandbox(sandbox,
|
|
67711
|
+
HACKERAI_FILE_APPEND_TARGET_PATH: getPythonPathForSandbox(sandbox, path10),
|
|
67669
67712
|
HACKERAI_FILE_APPEND_SOURCE_PATH: getPythonPathForSandbox(
|
|
67670
67713
|
sandbox,
|
|
67671
67714
|
tempPath
|
|
@@ -67677,13 +67720,13 @@ async function appendSandboxTextFile(sandbox, path8, text2) {
|
|
|
67677
67720
|
throw new Error(result.stderr || result.stdout || "Failed to append file");
|
|
67678
67721
|
}
|
|
67679
67722
|
}
|
|
67680
|
-
async function readSandboxFileForView(sandbox,
|
|
67723
|
+
async function readSandboxFileForView(sandbox, path10, includeData) {
|
|
67681
67724
|
if (isCentrifugoSandbox(sandbox) && sandbox.isWindows()) {
|
|
67682
67725
|
throw new Error(
|
|
67683
67726
|
"The view action is not available for Windows local sandboxes yet. Use a Linux/E2B sandbox or inspect the image manually."
|
|
67684
67727
|
);
|
|
67685
67728
|
}
|
|
67686
|
-
const sandboxPath = getSandboxViewPath(sandbox,
|
|
67729
|
+
const sandboxPath = getSandboxViewPath(sandbox, path10);
|
|
67687
67730
|
const viewEnvVars = {
|
|
67688
67731
|
HACKERAI_FILE_VIEW_PATH: sandboxPath,
|
|
67689
67732
|
HACKERAI_FILE_VIEW_INCLUDE_DATA: includeData ? "1" : "0",
|
|
@@ -68026,19 +68069,19 @@ try:
|
|
|
68026
68069
|
except OSError:
|
|
68027
68070
|
pass
|
|
68028
68071
|
`;
|
|
68029
|
-
getFilename = (
|
|
68030
|
-
getFileExtension = (
|
|
68031
|
-
const filename = getFilename(
|
|
68072
|
+
getFilename = (path10) => path10.split("/").pop() || path10;
|
|
68073
|
+
getFileExtension = (path10) => {
|
|
68074
|
+
const filename = getFilename(path10);
|
|
68032
68075
|
const dotIndex = filename.lastIndexOf(".");
|
|
68033
68076
|
if (dotIndex <= 0 || dotIndex === filename.length - 1) return void 0;
|
|
68034
68077
|
return filename.slice(dotIndex + 1).toLowerCase();
|
|
68035
68078
|
};
|
|
68036
|
-
getSandboxViewPath = (sandbox,
|
|
68079
|
+
getSandboxViewPath = (sandbox, path10) => {
|
|
68037
68080
|
const maybeSandbox = sandbox;
|
|
68038
|
-
if (isCentrifugoSandbox(maybeSandbox) && maybeSandbox.isWindows() &&
|
|
68039
|
-
return `C:\\temp${
|
|
68081
|
+
if (isCentrifugoSandbox(maybeSandbox) && maybeSandbox.isWindows() && path10.startsWith("/tmp/")) {
|
|
68082
|
+
return `C:\\temp${path10.slice(4).replace(/\//g, "\\")}`;
|
|
68040
68083
|
}
|
|
68041
|
-
return
|
|
68084
|
+
return path10;
|
|
68042
68085
|
};
|
|
68043
68086
|
stripTrailingWs = (line) => line.replace(/[ \t]+$/u, "");
|
|
68044
68087
|
editSchema = external_exports.object({
|
|
@@ -68112,7 +68155,7 @@ ${instructionsDescription}`,
|
|
|
68112
68155
|
"A list of edits to be sequentially applied to the file. Required for `edit` action."
|
|
68113
68156
|
)
|
|
68114
68157
|
}),
|
|
68115
|
-
execute: async ({ action, path:
|
|
68158
|
+
execute: async ({ action, path: path10, text: text2, range, edits }) => {
|
|
68116
68159
|
try {
|
|
68117
68160
|
const { sandbox } = await sandboxManager.getSandbox();
|
|
68118
68161
|
switch (action) {
|
|
@@ -68122,7 +68165,7 @@ ${instructionsDescription}`,
|
|
|
68122
68165
|
captureFileViewImageUsage({
|
|
68123
68166
|
context: context2,
|
|
68124
68167
|
sandbox,
|
|
68125
|
-
path:
|
|
68168
|
+
path: path10,
|
|
68126
68169
|
outcome: "unsupported_model",
|
|
68127
68170
|
durationMs: Date.now() - viewStartedAt,
|
|
68128
68171
|
failureReason: "unsupported_model"
|
|
@@ -68131,26 +68174,26 @@ ${instructionsDescription}`,
|
|
|
68131
68174
|
}
|
|
68132
68175
|
let viewPayload;
|
|
68133
68176
|
try {
|
|
68134
|
-
viewPayload = await readSandboxFileForView(sandbox,
|
|
68177
|
+
viewPayload = await readSandboxFileForView(sandbox, path10, false);
|
|
68135
68178
|
} catch (error51) {
|
|
68136
68179
|
captureFileViewImageUsage({
|
|
68137
68180
|
context: context2,
|
|
68138
68181
|
sandbox,
|
|
68139
|
-
path:
|
|
68182
|
+
path: path10,
|
|
68140
68183
|
outcome: "inspection_failed",
|
|
68141
68184
|
durationMs: Date.now() - viewStartedAt,
|
|
68142
68185
|
failureReason: classifyFileViewError(error51)
|
|
68143
68186
|
});
|
|
68144
68187
|
throw error51;
|
|
68145
68188
|
}
|
|
68146
|
-
const filename = getFilename(
|
|
68189
|
+
const filename = getFilename(path10);
|
|
68147
68190
|
let previewFiles = [];
|
|
68148
68191
|
let previewUploadError;
|
|
68149
68192
|
try {
|
|
68150
68193
|
previewFiles = await uploadViewPreviewFiles({
|
|
68151
68194
|
context: context2,
|
|
68152
68195
|
sandbox,
|
|
68153
|
-
sourcePath:
|
|
68196
|
+
sourcePath: path10,
|
|
68154
68197
|
payload: viewPayload
|
|
68155
68198
|
});
|
|
68156
68199
|
} catch (error51) {
|
|
@@ -68164,7 +68207,7 @@ ${instructionsDescription}`,
|
|
|
68164
68207
|
user_id: context2.userID,
|
|
68165
68208
|
sandbox_type: getViewSandboxType(sandbox),
|
|
68166
68209
|
file_name: filename,
|
|
68167
|
-
source_path:
|
|
68210
|
+
source_path: path10,
|
|
68168
68211
|
kind: viewPayload.kind,
|
|
68169
68212
|
media_type: viewPayload.mediaType,
|
|
68170
68213
|
size_bytes: viewPayload.sizeBytes,
|
|
@@ -68175,7 +68218,7 @@ ${instructionsDescription}`,
|
|
|
68175
68218
|
captureFileViewImageUsage({
|
|
68176
68219
|
context: context2,
|
|
68177
68220
|
sandbox,
|
|
68178
|
-
path:
|
|
68221
|
+
path: path10,
|
|
68179
68222
|
outcome: "success",
|
|
68180
68223
|
durationMs: Date.now() - viewStartedAt,
|
|
68181
68224
|
mediaType: viewPayload.mediaType,
|
|
@@ -68185,7 +68228,7 @@ ${instructionsDescription}`,
|
|
|
68185
68228
|
return {
|
|
68186
68229
|
action: "view",
|
|
68187
68230
|
content: `Viewing image file: ${filename} (${viewPayload.mediaType}, ${viewPayload.sizeBytes} bytes).`,
|
|
68188
|
-
path:
|
|
68231
|
+
path: path10,
|
|
68189
68232
|
filename,
|
|
68190
68233
|
mediaType: viewPayload.mediaType,
|
|
68191
68234
|
sizeBytes: viewPayload.sizeBytes,
|
|
@@ -68195,8 +68238,8 @@ ${instructionsDescription}`,
|
|
|
68195
68238
|
};
|
|
68196
68239
|
}
|
|
68197
68240
|
case "read": {
|
|
68198
|
-
const filename =
|
|
68199
|
-
const spritChunked = isSpritPath(
|
|
68241
|
+
const filename = path10.split("/").pop() || path10;
|
|
68242
|
+
const spritChunked = isSpritPath(path10);
|
|
68200
68243
|
let effectiveRange = range;
|
|
68201
68244
|
if (spritChunked) {
|
|
68202
68245
|
const start = range && range[0] > 0 ? range[0] : 1;
|
|
@@ -68209,7 +68252,7 @@ ${instructionsDescription}`,
|
|
|
68209
68252
|
}
|
|
68210
68253
|
const readPayload = await readSandboxTextFileWithFallback(
|
|
68211
68254
|
sandbox,
|
|
68212
|
-
|
|
68255
|
+
path10,
|
|
68213
68256
|
effectiveRange
|
|
68214
68257
|
);
|
|
68215
68258
|
if (readPayload.tooLarge) {
|
|
@@ -68246,46 +68289,46 @@ File is too large to read in full (${formatBytes(readPayload.sizeBytes)}, ${tota
|
|
|
68246
68289
|
if (text2 === void 0) {
|
|
68247
68290
|
return { error: "text is required for write action" };
|
|
68248
68291
|
}
|
|
68249
|
-
await sandbox.files.write(
|
|
68292
|
+
await sandbox.files.write(path10, text2, {
|
|
68250
68293
|
user: "user"
|
|
68251
68294
|
});
|
|
68252
|
-
return `File written: ${
|
|
68295
|
+
return `File written: ${path10}`;
|
|
68253
68296
|
}
|
|
68254
68297
|
case "append": {
|
|
68255
68298
|
if (text2 === void 0) {
|
|
68256
68299
|
return { error: "text is required for append action" };
|
|
68257
68300
|
}
|
|
68258
|
-
const existingState = await getSandboxFileState(sandbox,
|
|
68301
|
+
const existingState = await getSandboxFileState(sandbox, path10);
|
|
68259
68302
|
if (existingState.kind === "unknown") {
|
|
68260
68303
|
return {
|
|
68261
|
-
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}`
|
|
68262
68305
|
};
|
|
68263
68306
|
}
|
|
68264
68307
|
if (existingState.kind === "not_file") {
|
|
68265
68308
|
return {
|
|
68266
|
-
error: `Cannot append to ${
|
|
68309
|
+
error: `Cannot append to ${path10} because it is not a file.`
|
|
68267
68310
|
};
|
|
68268
68311
|
}
|
|
68269
68312
|
if (existingState.kind === "file" && existingState.sizeBytes > MAX_TEXT_FILE_READ_BYTES) {
|
|
68270
|
-
await appendSandboxTextFile(sandbox,
|
|
68313
|
+
await appendSandboxTextFile(sandbox, path10, text2);
|
|
68271
68314
|
return {
|
|
68272
|
-
content: `File appended: ${
|
|
68315
|
+
content: `File appended: ${path10}
|
|
68273
68316
|
Existing file is ${formatBytes(existingState.sizeBytes)}, so the full diff preview was skipped to avoid loading the entire file into memory.`
|
|
68274
68317
|
};
|
|
68275
68318
|
}
|
|
68276
68319
|
let existingContent = "";
|
|
68277
68320
|
try {
|
|
68278
|
-
existingContent = await sandbox.files.read(
|
|
68321
|
+
existingContent = await sandbox.files.read(path10, {
|
|
68279
68322
|
user: "user"
|
|
68280
68323
|
});
|
|
68281
68324
|
} catch {
|
|
68282
68325
|
}
|
|
68283
68326
|
const newContent = existingContent + text2;
|
|
68284
|
-
await sandbox.files.write(
|
|
68327
|
+
await sandbox.files.write(path10, newContent, {
|
|
68285
68328
|
user: "user"
|
|
68286
68329
|
});
|
|
68287
68330
|
return {
|
|
68288
|
-
content: `File appended: ${
|
|
68331
|
+
content: `File appended: ${path10}`,
|
|
68289
68332
|
originalContent: truncateOutput({
|
|
68290
68333
|
content: existingContent,
|
|
68291
68334
|
mode: "read-file"
|
|
@@ -68300,31 +68343,31 @@ Existing file is ${formatBytes(existingState.sizeBytes)}, so the full diff previ
|
|
|
68300
68343
|
if (!edits || edits.length === 0) {
|
|
68301
68344
|
return { error: "edits array is required for edit action" };
|
|
68302
68345
|
}
|
|
68303
|
-
const existingState = await getSandboxFileState(sandbox,
|
|
68346
|
+
const existingState = await getSandboxFileState(sandbox, path10);
|
|
68304
68347
|
if (existingState.kind === "unknown") {
|
|
68305
68348
|
return {
|
|
68306
|
-
error: `Cannot edit ${
|
|
68349
|
+
error: `Cannot edit ${path10} safely because the file size could not be determined. ${existingState.error}`
|
|
68307
68350
|
};
|
|
68308
68351
|
}
|
|
68309
68352
|
if (existingState.kind === "missing") {
|
|
68310
68353
|
return {
|
|
68311
|
-
error: `Cannot edit file ${
|
|
68354
|
+
error: `Cannot edit file ${path10} - file is empty or does not exist`
|
|
68312
68355
|
};
|
|
68313
68356
|
}
|
|
68314
68357
|
if (existingState.kind === "not_file") {
|
|
68315
|
-
return { error: `Cannot edit ${
|
|
68358
|
+
return { error: `Cannot edit ${path10} because it is not a file.` };
|
|
68316
68359
|
}
|
|
68317
68360
|
if (existingState.sizeBytes > MAX_TEXT_FILE_READ_BYTES) {
|
|
68318
68361
|
return {
|
|
68319
|
-
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.`
|
|
68320
68363
|
};
|
|
68321
68364
|
}
|
|
68322
|
-
const originalContent = await sandbox.files.read(
|
|
68365
|
+
const originalContent = await sandbox.files.read(path10, {
|
|
68323
68366
|
user: "user"
|
|
68324
68367
|
});
|
|
68325
68368
|
if (!originalContent) {
|
|
68326
68369
|
return {
|
|
68327
|
-
error: `Cannot edit file ${
|
|
68370
|
+
error: `Cannot edit file ${path10} - file is empty or does not exist`
|
|
68328
68371
|
};
|
|
68329
68372
|
}
|
|
68330
68373
|
const resolvedEdits = [];
|
|
@@ -68369,7 +68412,7 @@ ${hint}` : "")
|
|
|
68369
68412
|
}
|
|
68370
68413
|
}
|
|
68371
68414
|
}
|
|
68372
|
-
await sandbox.files.write(
|
|
68415
|
+
await sandbox.files.write(path10, content, {
|
|
68373
68416
|
user: "user"
|
|
68374
68417
|
});
|
|
68375
68418
|
const lines = content.split("\n");
|
|
@@ -68609,11 +68652,11 @@ function findGitBash() {
|
|
|
68609
68652
|
if ((0, import_fs.existsSync)(c)) return c;
|
|
68610
68653
|
}
|
|
68611
68654
|
try {
|
|
68612
|
-
const
|
|
68655
|
+
const out3 = (0, import_child_process.execSync)("where git", {
|
|
68613
68656
|
encoding: "utf8",
|
|
68614
68657
|
stdio: ["ignore", "pipe", "ignore"]
|
|
68615
68658
|
});
|
|
68616
|
-
const gitExe =
|
|
68659
|
+
const gitExe = out3.split(/\r?\n/).find((l) => l.trim().endsWith("git.exe"));
|
|
68617
68660
|
if (gitExe) {
|
|
68618
68661
|
const bash = (0, import_path3.join)((0, import_path3.dirname)((0, import_path3.dirname)(gitExe.trim())), "bin", "bash.exe");
|
|
68619
68662
|
if ((0, import_fs.existsSync)(bash)) return bash;
|
|
@@ -68794,6 +68837,7 @@ var init_local_sandbox = __esm({
|
|
|
68794
68837
|
async init() {
|
|
68795
68838
|
await import_node_fs6.promises.mkdir(this.workdir, { recursive: true });
|
|
68796
68839
|
await this.seedReconToolkit();
|
|
68840
|
+
await this.seedAuditToolkit();
|
|
68797
68841
|
}
|
|
68798
68842
|
/**
|
|
68799
68843
|
* Seed the deep-recon toolkit (recon_deep.py + console_recon.js + README)
|
|
@@ -68834,6 +68878,29 @@ var init_local_sandbox = __esm({
|
|
|
68834
68878
|
} catch {
|
|
68835
68879
|
}
|
|
68836
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);
|
|
68898
|
+
} catch {
|
|
68899
|
+
}
|
|
68900
|
+
}
|
|
68901
|
+
} catch {
|
|
68902
|
+
}
|
|
68903
|
+
}
|
|
68837
68904
|
getConnectionId() {
|
|
68838
68905
|
return "local";
|
|
68839
68906
|
}
|
|
@@ -68879,6 +68946,21 @@ EDITING SCRIPTS:
|
|
|
68879
68946
|
getOsContext() {
|
|
68880
68947
|
return this.getSandboxContext();
|
|
68881
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
|
+
}
|
|
68882
68964
|
getWorkdir() {
|
|
68883
68965
|
return this.workdir;
|
|
68884
68966
|
}
|
|
@@ -69155,7 +69237,7 @@ function formatToolCall(toolName, input) {
|
|
|
69155
69237
|
return `${C2.cyan}executando${C2.reset} ${C2.bold}$ ${truncate3(cmd, 400)}${C2.reset}${bg}`;
|
|
69156
69238
|
}
|
|
69157
69239
|
case "file": {
|
|
69158
|
-
const
|
|
69240
|
+
const path10 = String(i.path ?? "");
|
|
69159
69241
|
const brief = i.brief ? `${C2.dim} - ${truncate3(String(i.brief))}${C2.reset}` : "";
|
|
69160
69242
|
const map2 = {
|
|
69161
69243
|
write: `${C2.green}criando arquivo${C2.reset}`,
|
|
@@ -69166,7 +69248,7 @@ function formatToolCall(toolName, input) {
|
|
|
69166
69248
|
};
|
|
69167
69249
|
const action = typeof i.action === "string" ? i.action : "";
|
|
69168
69250
|
const label = map2[action] ?? (action ? `${C2.blue}arquivo (${action})${C2.reset}` : `${C2.blue}preparando operacao de arquivo${C2.reset}`);
|
|
69169
|
-
const target =
|
|
69251
|
+
const target = path10 ? ` ${C2.bold}${path10}${C2.reset}` : "";
|
|
69170
69252
|
return `${label}${target}${brief}`;
|
|
69171
69253
|
}
|
|
69172
69254
|
case "todo_write":
|
|
@@ -69401,15 +69483,210 @@ var init_proxy_manager2 = __esm({
|
|
|
69401
69483
|
}
|
|
69402
69484
|
});
|
|
69403
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
|
+
|
|
69404
69673
|
// src/agent.ts
|
|
69405
69674
|
var agent_exports = {};
|
|
69406
69675
|
__export(agent_exports, {
|
|
69407
69676
|
createAgent: () => createAgent
|
|
69408
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
|
+
}
|
|
69409
69684
|
function looksUnfinished(text2) {
|
|
69410
69685
|
if (!text2) return false;
|
|
69411
|
-
if (
|
|
69412
|
-
|
|
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));
|
|
69413
69690
|
}
|
|
69414
69691
|
function decideAutoContinue(finishReason, lastStepText, turnToolCalls, autoContinues) {
|
|
69415
69692
|
if (autoContinues >= MAX_AUTO_CONTINUES) return null;
|
|
@@ -69424,8 +69701,12 @@ function decideAutoContinue(finishReason, lastStepText, turnToolCalls, autoConti
|
|
|
69424
69701
|
if (!text2 && turnToolCalls === 0) {
|
|
69425
69702
|
return { nudge: true, reason: "resposta vazia do modelo" };
|
|
69426
69703
|
}
|
|
69427
|
-
if (turnToolCalls > 0 && looksUnfinished(text2)) {
|
|
69428
|
-
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
|
+
};
|
|
69429
69710
|
}
|
|
69430
69711
|
if (turnToolCalls === 0 && looksUnfinished(text2) && !BENIGN_CLOSER_RE.test(text2.slice(-200))) {
|
|
69431
69712
|
return {
|
|
@@ -69538,7 +69819,7 @@ async function createAgent() {
|
|
|
69538
69819
|
const sandboxManager = new LocalSandboxManager(sandbox);
|
|
69539
69820
|
const writer = createConsoleWriter();
|
|
69540
69821
|
const render = createRenderer();
|
|
69541
|
-
const initialModelName = CLI_MODEL_CHAIN[0] ?? "model-nvidia-
|
|
69822
|
+
const initialModelName = CLI_MODEL_CHAIN[0] ?? "model-nvidia-mistral-medium-3.5";
|
|
69542
69823
|
let currentModelName = initialModelName;
|
|
69543
69824
|
let selectedModelKey = null;
|
|
69544
69825
|
const context2 = {
|
|
@@ -69606,6 +69887,8 @@ async function createAgent() {
|
|
|
69606
69887
|
);
|
|
69607
69888
|
}
|
|
69608
69889
|
const history = [];
|
|
69890
|
+
let auditMode = false;
|
|
69891
|
+
const projectRoot = projectRootFromWorkdir(sandbox.getWorkdir());
|
|
69609
69892
|
function getActiveModelChain() {
|
|
69610
69893
|
return selectedModelKey ? [selectedModelKey] : CLI_MODEL_CHAIN;
|
|
69611
69894
|
}
|
|
@@ -69631,7 +69914,7 @@ async function createAgent() {
|
|
|
69631
69914
|
provider: "NVIDIA build",
|
|
69632
69915
|
reason: "faltando NVIDIA_API_KEY em .env.local (https://build.nvidia.com/)",
|
|
69633
69916
|
models: [
|
|
69634
|
-
"model-nvidia-
|
|
69917
|
+
"model-nvidia-mistral-medium-3.5",
|
|
69635
69918
|
"model-nvidia-kimi-k2.6",
|
|
69636
69919
|
"model-nvidia-glm-5.1",
|
|
69637
69920
|
"model-nvidia-qwen3.5-397b"
|
|
@@ -69791,12 +70074,30 @@ ${seen}`);
|
|
|
69791
70074
|
}
|
|
69792
70075
|
async function send(userInput, signal) {
|
|
69793
70076
|
history.push({ role: "user", content: userInput });
|
|
69794
|
-
|
|
69795
|
-
|
|
69796
|
-
if (matchedSkills.length) {
|
|
70077
|
+
if (!auditMode && detectProjectAuditIntent(userInput)) {
|
|
70078
|
+
auditMode = true;
|
|
69797
70079
|
render.info(
|
|
69798
|
-
`\u25B8
|
|
70080
|
+
`\u25B8 modo AN\xC1LISE DE PROJETO (somente leitura) \u2014 auditando ${projectRoot}. Diga "modo normal" para sair.`
|
|
69799
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
|
+
}
|
|
69800
70101
|
}
|
|
69801
70102
|
let lastError = null;
|
|
69802
70103
|
let autoContinues = 0;
|
|
@@ -69805,6 +70106,7 @@ ${seen}`);
|
|
|
69805
70106
|
const usingFixedModel = selectedModelKey !== null;
|
|
69806
70107
|
let rateLimitWaits = 0;
|
|
69807
70108
|
let addedRateLimitFallbacks = false;
|
|
70109
|
+
let stallRetries = 0;
|
|
69808
70110
|
for (let idx = 0; idx < modelChain.length; idx++) {
|
|
69809
70111
|
const modelKey = modelChain[idx];
|
|
69810
70112
|
currentModelName = modelKey;
|
|
@@ -69819,6 +70121,27 @@ ${seen}`);
|
|
|
69819
70121
|
render.fallback(`trocando para fallback: ${labelFor(modelKey)}`);
|
|
69820
70122
|
}
|
|
69821
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
|
+
};
|
|
69822
70145
|
try {
|
|
69823
70146
|
const result = streamText({
|
|
69824
70147
|
model: myProvider.languageModel(modelKey),
|
|
@@ -69827,7 +70150,7 @@ ${seen}`);
|
|
|
69827
70150
|
tools,
|
|
69828
70151
|
stopWhen: stepCountIs(MAX_STEPS),
|
|
69829
70152
|
maxOutputTokens: MAX_OUTPUT_TOKENS,
|
|
69830
|
-
abortSignal: signal,
|
|
70153
|
+
abortSignal: stallController.signal,
|
|
69831
70154
|
onError: ({ error: error51 }) => {
|
|
69832
70155
|
streamError = error51;
|
|
69833
70156
|
}
|
|
@@ -69836,38 +70159,72 @@ ${seen}`);
|
|
|
69836
70159
|
let bufferedProxyText = "";
|
|
69837
70160
|
let turnToolCalls = 0;
|
|
69838
70161
|
const shouldBufferProxyText = isWebSessionProxyModel(modelKey);
|
|
69839
|
-
|
|
69840
|
-
|
|
69841
|
-
|
|
69842
|
-
|
|
69843
|
-
|
|
69844
|
-
|
|
69845
|
-
|
|
69846
|
-
|
|
69847
|
-
|
|
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;
|
|
69848
70180
|
}
|
|
69849
|
-
|
|
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;
|
|
69850
70212
|
}
|
|
69851
|
-
case "reasoning-delta":
|
|
69852
|
-
render.reasoning(part.text ?? part.delta ?? "");
|
|
69853
|
-
break;
|
|
69854
|
-
case "tool-call":
|
|
69855
|
-
turnToolCalls++;
|
|
69856
|
-
render.toolCall(part.toolName, part.input ?? part.args);
|
|
69857
|
-
break;
|
|
69858
|
-
case "tool-result":
|
|
69859
|
-
render.toolResult(part.toolName, part.output ?? part.result);
|
|
69860
|
-
break;
|
|
69861
|
-
case "start-step":
|
|
69862
|
-
lastStepText = "";
|
|
69863
|
-
bufferedProxyText = "";
|
|
69864
|
-
break;
|
|
69865
|
-
case "error":
|
|
69866
|
-
streamError = part.error;
|
|
69867
|
-
break;
|
|
69868
|
-
default:
|
|
69869
|
-
break;
|
|
69870
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
|
+
);
|
|
69871
70228
|
}
|
|
69872
70229
|
if (streamError) throw streamError;
|
|
69873
70230
|
const response = await result.response;
|
|
@@ -69875,12 +70232,13 @@ ${seen}`);
|
|
|
69875
70232
|
const finishReason = String(
|
|
69876
70233
|
await result.finishReason.catch(() => "unknown")
|
|
69877
70234
|
);
|
|
69878
|
-
|
|
70235
|
+
const leakedCall = !shouldBufferProxyText && hasLeakedToolCallMarker(lastStepText);
|
|
70236
|
+
if (finishReason === "stop" && turnToolCalls === 0 && bridgeSteps < MAX_BRIDGE_STEPS && (shouldBufferProxyText || leakedCall)) {
|
|
69879
70237
|
const bridged = parseProxyToolCalls(lastStepText);
|
|
69880
70238
|
if (bridged) {
|
|
69881
70239
|
bridgeSteps++;
|
|
69882
70240
|
render.info(
|
|
69883
|
-
`\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)}`
|
|
69884
70242
|
);
|
|
69885
70243
|
const resultText = await runBridgedToolCalls(bridged, signal);
|
|
69886
70244
|
if (signal?.aborted) {
|
|
@@ -69889,7 +70247,7 @@ ${seen}`);
|
|
|
69889
70247
|
}
|
|
69890
70248
|
history.push({
|
|
69891
70249
|
role: "user",
|
|
69892
|
-
content: `${BRIDGE_RESULT_PREAMBLE}
|
|
70250
|
+
content: `${leakedCall ? LEAKED_CALL_RESULT_PREAMBLE : BRIDGE_RESULT_PREAMBLE}
|
|
69893
70251
|
|
|
69894
70252
|
${resultText}`
|
|
69895
70253
|
});
|
|
@@ -69938,6 +70296,28 @@ ${resultText}`
|
|
|
69938
70296
|
render.endTurn();
|
|
69939
70297
|
return;
|
|
69940
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
|
+
}
|
|
69941
70321
|
lastError = err ?? streamError;
|
|
69942
70322
|
const msg = lastError instanceof Error ? lastError.message : String(lastError);
|
|
69943
70323
|
const rateLimited = isRateLimitError(msg);
|
|
@@ -70016,13 +70396,13 @@ ${resultText}`
|
|
|
70016
70396
|
close
|
|
70017
70397
|
};
|
|
70018
70398
|
}
|
|
70019
|
-
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;
|
|
70020
70400
|
var init_agent = __esm({
|
|
70021
70401
|
"src/agent.ts"() {
|
|
70022
70402
|
"use strict";
|
|
70023
70403
|
init_dist5();
|
|
70024
70404
|
import_promises = require("node:fs/promises");
|
|
70025
|
-
|
|
70405
|
+
import_node_path8 = __toESM(require("node:path"));
|
|
70026
70406
|
init_providers();
|
|
70027
70407
|
init_system_prompt();
|
|
70028
70408
|
init_notes();
|
|
@@ -70041,10 +70421,16 @@ var init_agent = __esm({
|
|
|
70041
70421
|
init_render();
|
|
70042
70422
|
init_skills();
|
|
70043
70423
|
init_proxy_manager2();
|
|
70424
|
+
init_audit_mode();
|
|
70044
70425
|
MAX_STEPS = 100;
|
|
70045
70426
|
MAX_OUTPUT_TOKENS = 16384;
|
|
70046
70427
|
MAX_AUTO_CONTINUES = 3;
|
|
70047
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;
|
|
70048
70434
|
isRateLimitError = (msg) => /\b429\b|too many requests|rate.?limit|resource_exhausted|quota|insufficient_quota/i.test(
|
|
70049
70435
|
msg
|
|
70050
70436
|
);
|
|
@@ -70060,11 +70446,14 @@ var init_agent = __esm({
|
|
|
70060
70446
|
{ once: true }
|
|
70061
70447
|
);
|
|
70062
70448
|
});
|
|
70063
|
-
|
|
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;
|
|
70064
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;
|
|
70065
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.";
|
|
70066
70454
|
MAX_BRIDGE_STEPS = 50;
|
|
70067
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.";
|
|
70068
70457
|
truncateBridgeSummary = (value, max = 180) => value.length > max ? `${value.slice(0, max)}...` : value;
|
|
70069
70458
|
isWebSessionProxyModel = (modelName) => modelName === "model-deepseek-proxy" || modelName === "model-kimi-proxy";
|
|
70070
70459
|
proxyToolProtocolPolicy = () => `
|
|
@@ -70100,7 +70489,7 @@ Regras:
|
|
|
70100
70489
|
"DANGEROUS MODE"
|
|
70101
70490
|
];
|
|
70102
70491
|
MODEL_LABELS = {
|
|
70103
|
-
"model-nvidia-
|
|
70492
|
+
"model-nvidia-mistral-medium-3.5": "NVIDIA - mistralai/mistral-medium-3.5-128b",
|
|
70104
70493
|
"model-nvidia-kimi-k2.6": "NVIDIA - moonshotai/kimi-k2.6",
|
|
70105
70494
|
"model-nvidia-glm-5.1": "NVIDIA - z-ai/glm-5.1",
|
|
70106
70495
|
"model-nvidia-qwen3.5-397b": "NVIDIA - qwen/qwen3.5-397b-a17b",
|
|
@@ -70245,7 +70634,7 @@ ${section}` : "";
|
|
|
70245
70634
|
return null;
|
|
70246
70635
|
}
|
|
70247
70636
|
await (0, import_promises.mkdir)(workdir, { recursive: true });
|
|
70248
|
-
const outputPath =
|
|
70637
|
+
const outputPath = import_node_path8.default.join(workdir, "system-prompt.txt");
|
|
70249
70638
|
await (0, import_promises.writeFile)(outputPath, system, "utf8");
|
|
70250
70639
|
return outputPath;
|
|
70251
70640
|
};
|
|
@@ -70276,7 +70665,9 @@ __export(ui_exports, {
|
|
|
70276
70665
|
agentHeader: () => agentHeader,
|
|
70277
70666
|
buildBanner: () => buildBanner,
|
|
70278
70667
|
shellPrompt: () => shellPrompt,
|
|
70279
|
-
|
|
70668
|
+
shortCwd: () => shortCwd,
|
|
70669
|
+
ui: () => ui,
|
|
70670
|
+
vlen: () => vlen
|
|
70280
70671
|
});
|
|
70281
70672
|
function shortCwd() {
|
|
70282
70673
|
const cwd = process.cwd();
|
|
@@ -70289,13 +70680,13 @@ function shortCwd() {
|
|
|
70289
70680
|
}
|
|
70290
70681
|
function asciiTitle(text2) {
|
|
70291
70682
|
const rows = 6;
|
|
70292
|
-
const
|
|
70683
|
+
const out3 = [];
|
|
70293
70684
|
for (let r = 0; r < rows; r++) {
|
|
70294
|
-
|
|
70685
|
+
out3.push(
|
|
70295
70686
|
[...text2].map((ch) => GLYPHS[ch] ? GLYPHS[ch][r] : " ").join(" ")
|
|
70296
70687
|
);
|
|
70297
70688
|
}
|
|
70298
|
-
return
|
|
70689
|
+
return out3;
|
|
70299
70690
|
}
|
|
70300
70691
|
function buildBanner(_systemPromptChars, version3 = "1") {
|
|
70301
70692
|
const user = (import_node_os4.default.userInfo().username || "hacker").toLowerCase();
|
|
@@ -70367,7 +70758,8 @@ var init_ui = __esm({
|
|
|
70367
70758
|
cyan: `${ESC}36m`,
|
|
70368
70759
|
cyanB: `${ESC}96m`,
|
|
70369
70760
|
magenta: `${ESC}95m`,
|
|
70370
|
-
yellow: `${ESC}93m
|
|
70761
|
+
yellow: `${ESC}93m`,
|
|
70762
|
+
red: `${ESC}91m`
|
|
70371
70763
|
};
|
|
70372
70764
|
INNER = 42;
|
|
70373
70765
|
BOX_W = INNER + 4;
|
|
@@ -70391,16 +70783,462 @@ var init_ui = __esm({
|
|
|
70391
70783
|
}
|
|
70392
70784
|
});
|
|
70393
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
|
+
|
|
70394
71232
|
// index.ts
|
|
70395
71233
|
var index_exports = {};
|
|
70396
71234
|
async function main() {
|
|
70397
71235
|
const { createAgent: createAgent2 } = await Promise.resolve().then(() => (init_agent(), agent_exports));
|
|
70398
|
-
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;
|
|
70399
71239
|
if (!bootQuiet) {
|
|
70400
|
-
process.stdout.write(
|
|
70401
|
-
|
|
70402
|
-
`
|
|
70403
|
-
);
|
|
71240
|
+
process.stdout.write(`${C5.dim} booting local sandbox + agent\u2026${C5.reset}
|
|
71241
|
+
`);
|
|
70404
71242
|
}
|
|
70405
71243
|
const agent = await createAgent2();
|
|
70406
71244
|
const sys = agent.getSystemPrompt();
|
|
@@ -70409,39 +71247,36 @@ async function main() {
|
|
|
70409
71247
|
process.stdout.write(buildBanner2(sys.length, version3));
|
|
70410
71248
|
const updateNotice = getUpdateNotice(version3);
|
|
70411
71249
|
if (updateNotice) {
|
|
70412
|
-
process.stdout.write(
|
|
70413
|
-
|
|
70414
|
-
`
|
|
70415
|
-
);
|
|
71250
|
+
process.stdout.write(`${C5.yellow}\u2191 ${updateNotice}${C5.reset}
|
|
71251
|
+
`);
|
|
70416
71252
|
}
|
|
70417
71253
|
refreshUpdateCacheInBackground(version3);
|
|
70418
71254
|
if (consumePostUpdateLaunch(version3)) {
|
|
70419
71255
|
process.stdout.write(
|
|
70420
|
-
`${
|
|
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}
|
|
70421
71257
|
`
|
|
70422
71258
|
);
|
|
70423
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
|
+
];
|
|
70424
71272
|
const pasteInput = createPasteInput();
|
|
70425
|
-
const
|
|
70426
|
-
input: pasteInput.input,
|
|
70427
|
-
output: process.stdout,
|
|
70428
|
-
terminal: true
|
|
70429
|
-
});
|
|
71273
|
+
const inputUI = new InteractiveInput2(pasteInput, COMMANDS);
|
|
70430
71274
|
let closing = false;
|
|
70431
|
-
let
|
|
70432
|
-
let awaitingModelSelection = false;
|
|
70433
|
-
let skillCreator = null;
|
|
70434
|
-
const prompt = () => {
|
|
70435
|
-
rl.setPrompt(
|
|
70436
|
-
skillCreator ? skillPrompt(skillCreator.phase) : awaitingModelSelection ? modelPrompt() : shellPrompt2()
|
|
70437
|
-
);
|
|
70438
|
-
rl.prompt();
|
|
70439
|
-
};
|
|
71275
|
+
let shuttingDown = false;
|
|
70440
71276
|
let activeAbort = null;
|
|
70441
71277
|
let turnActive = false;
|
|
70442
71278
|
let exitArmed = false;
|
|
70443
71279
|
let exitTimer = null;
|
|
70444
|
-
let lastSigint = 0;
|
|
70445
71280
|
const armExit = () => {
|
|
70446
71281
|
exitArmed = true;
|
|
70447
71282
|
if (exitTimer) clearTimeout(exitTimer);
|
|
@@ -70450,69 +71285,58 @@ async function main() {
|
|
|
70450
71285
|
exitTimer = null;
|
|
70451
71286
|
}, 2e3);
|
|
70452
71287
|
};
|
|
70453
|
-
const
|
|
70454
|
-
|
|
70455
|
-
|
|
70456
|
-
|
|
70457
|
-
|
|
70458
|
-
|
|
70459
|
-
|
|
70460
|
-
|
|
70461
|
-
|
|
70462
|
-
|
|
70463
|
-
|
|
70464
|
-
|
|
70465
|
-
|
|
70466
|
-
|
|
70467
|
-
|
|
70468
|
-
|
|
70469
|
-
|
|
70470
|
-
|
|
70471
|
-
|
|
70472
|
-
|
|
70473
|
-
|
|
70474
|
-
|
|
70475
|
-
`
|
|
70476
|
-
|
|
70477
|
-
} else {
|
|
70478
|
-
process.stdout.write(
|
|
70479
|
-
`
|
|
70480
|
-
${ui2.C.dim}Ctrl+C de novo para fechar${ui2.C.reset}
|
|
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)}
|
|
70481
71312
|
`
|
|
70482
|
-
|
|
70483
|
-
if (!awaitingModelSelection) prompt();
|
|
70484
|
-
}
|
|
70485
|
-
armExit();
|
|
71313
|
+
);
|
|
70486
71314
|
};
|
|
70487
|
-
|
|
70488
|
-
process.on("SIGINT", handleSigint);
|
|
70489
|
-
rl.on("SIGINT", handleSigint);
|
|
71315
|
+
let skillCreator = null;
|
|
70490
71316
|
const printSkillList = () => {
|
|
70491
71317
|
const skills = listSkills();
|
|
70492
71318
|
if (skills.length === 0) {
|
|
70493
71319
|
process.stdout.write(
|
|
70494
71320
|
`
|
|
70495
|
-
${
|
|
71321
|
+
${C5.dim}nenhuma skill instalada. crie uma com /skillcreator${C5.reset}
|
|
70496
71322
|
`
|
|
70497
71323
|
);
|
|
70498
71324
|
return;
|
|
70499
71325
|
}
|
|
70500
71326
|
process.stdout.write(
|
|
70501
71327
|
`
|
|
70502
|
-
${
|
|
71328
|
+
${C5.cyan}skills instaladas${C5.reset} ${C5.dim}(${skillsDir()})${C5.reset}
|
|
70503
71329
|
`
|
|
70504
71330
|
);
|
|
70505
71331
|
for (const s of skills) {
|
|
70506
|
-
const flags = s.always ? ` ${
|
|
71332
|
+
const flags = s.always ? ` ${C5.yellow}[sempre]${C5.reset}` : "";
|
|
70507
71333
|
process.stdout.write(
|
|
70508
|
-
` ${
|
|
71334
|
+
` ${C5.green}${s.name}${C5.reset}${flags} ${C5.dim}\u2014${C5.reset} ${s.description}
|
|
70509
71335
|
`
|
|
70510
71336
|
);
|
|
70511
71337
|
}
|
|
70512
|
-
process.stdout.write(
|
|
70513
|
-
|
|
70514
|
-
`
|
|
70515
|
-
);
|
|
71338
|
+
process.stdout.write(`${C5.dim}remover: /skill delete <nome>${C5.reset}
|
|
71339
|
+
`);
|
|
70516
71340
|
};
|
|
70517
71341
|
const handleSkillCommand = (input) => {
|
|
70518
71342
|
if (input === "/skillcreator") {
|
|
@@ -70525,9 +71349,9 @@ ${ui2.C.cyan}skills instaladas${ui2.C.reset} ${ui2.C.dim}(${skillsDir()})${ui2.C
|
|
|
70525
71349
|
};
|
|
70526
71350
|
process.stdout.write(
|
|
70527
71351
|
`
|
|
70528
|
-
${
|
|
70529
|
-
${
|
|
70530
|
-
${
|
|
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}
|
|
70531
71355
|
`
|
|
70532
71356
|
);
|
|
70533
71357
|
return;
|
|
@@ -70545,29 +71369,27 @@ ${ui2.C.cyan}nome da skill?${ui2.C.reset} ${ui2.C.dim}(ex: xss-recon)${ui2.C.res
|
|
|
70545
71369
|
}
|
|
70546
71370
|
if (sub === "delete" || sub === "rm" || sub === "remove") {
|
|
70547
71371
|
if (!arg) {
|
|
70548
|
-
process.stdout.write(
|
|
70549
|
-
|
|
70550
|
-
`
|
|
70551
|
-
);
|
|
71372
|
+
process.stdout.write(`${C5.yellow}uso: /skill delete <nome>${C5.reset}
|
|
71373
|
+
`);
|
|
70552
71374
|
return;
|
|
70553
71375
|
}
|
|
70554
71376
|
if (deleteSkill(arg)) {
|
|
70555
71377
|
await agent.refreshSkills();
|
|
70556
71378
|
process.stdout.write(
|
|
70557
|
-
`${
|
|
71379
|
+
`${C5.green}\u2713 skill '${slugify(arg)}' removida${C5.reset}
|
|
70558
71380
|
`
|
|
70559
71381
|
);
|
|
70560
71382
|
} else {
|
|
70561
71383
|
process.stdout.write(
|
|
70562
|
-
`${
|
|
71384
|
+
`${C5.yellow}skill '${arg}' nao encontrada${C5.reset}
|
|
70563
71385
|
`
|
|
70564
71386
|
);
|
|
70565
71387
|
}
|
|
70566
71388
|
return;
|
|
70567
71389
|
}
|
|
70568
71390
|
process.stdout.write(
|
|
70569
|
-
`${
|
|
70570
|
-
${
|
|
71391
|
+
`${C5.yellow}subcomando desconhecido: ${sub}${C5.reset}
|
|
71392
|
+
${C5.dim}use: /skillcreator | /skills | /skill delete <nome>${C5.reset}
|
|
70571
71393
|
`
|
|
70572
71394
|
);
|
|
70573
71395
|
};
|
|
@@ -70575,7 +71397,7 @@ ${ui2.C.dim}use: /skillcreator | /skills | /skill delete <nome>${ui2.C.reset}
|
|
|
70575
71397
|
const text2 = sc.bodyLines.join("\n");
|
|
70576
71398
|
const lines = text2 ? text2.split("\n").length : 0;
|
|
70577
71399
|
process.stdout.write(
|
|
70578
|
-
`${
|
|
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}
|
|
70579
71401
|
`
|
|
70580
71402
|
);
|
|
70581
71403
|
};
|
|
@@ -70584,11 +71406,9 @@ ${ui2.C.dim}use: /skillcreator | /skills | /skill delete <nome>${ui2.C.reset}
|
|
|
70584
71406
|
if (!sc) return;
|
|
70585
71407
|
if (input === "/cancelar" || input === "/cancel") {
|
|
70586
71408
|
skillCreator = null;
|
|
70587
|
-
process.stdout.write(
|
|
70588
|
-
|
|
70589
|
-
|
|
70590
|
-
`
|
|
70591
|
-
);
|
|
71409
|
+
process.stdout.write(`
|
|
71410
|
+
${C5.dim}criacao de skill cancelada${C5.reset}
|
|
71411
|
+
`);
|
|
70592
71412
|
return;
|
|
70593
71413
|
}
|
|
70594
71414
|
switch (sc.phase) {
|
|
@@ -70596,7 +71416,7 @@ ${ui2.C.dim}criacao de skill cancelada${ui2.C.reset}
|
|
|
70596
71416
|
const slug = slugify(input);
|
|
70597
71417
|
if (!slug) {
|
|
70598
71418
|
process.stdout.write(
|
|
70599
|
-
`${
|
|
71419
|
+
`${C5.yellow}nome invalido \u2014 tente de novo${C5.reset}
|
|
70600
71420
|
`
|
|
70601
71421
|
);
|
|
70602
71422
|
return;
|
|
@@ -70604,22 +71424,20 @@ ${ui2.C.dim}criacao de skill cancelada${ui2.C.reset}
|
|
|
70604
71424
|
sc.name = slug;
|
|
70605
71425
|
if (listSkills().some((s) => s.name === slug)) {
|
|
70606
71426
|
process.stdout.write(
|
|
70607
|
-
`${
|
|
71427
|
+
`${C5.yellow}ja existe uma skill '${slug}' \u2014 sera sobrescrita${C5.reset}
|
|
70608
71428
|
`
|
|
70609
71429
|
);
|
|
70610
71430
|
}
|
|
70611
71431
|
sc.phase = "desc";
|
|
70612
|
-
process.stdout.write(
|
|
70613
|
-
|
|
70614
|
-
`
|
|
70615
|
-
);
|
|
71432
|
+
process.stdout.write(`${C5.cyan}descricao curta (1 linha)?${C5.reset}
|
|
71433
|
+
`);
|
|
70616
71434
|
return;
|
|
70617
71435
|
}
|
|
70618
71436
|
case "desc": {
|
|
70619
71437
|
sc.description = input;
|
|
70620
71438
|
sc.phase = "triggers";
|
|
70621
71439
|
process.stdout.write(
|
|
70622
|
-
`${
|
|
71440
|
+
`${C5.cyan}palavras-gatilho?${C5.reset} ${C5.dim}(separadas por virgula; Enter usa o proprio nome)${C5.reset}
|
|
70623
71441
|
`
|
|
70624
71442
|
);
|
|
70625
71443
|
return;
|
|
@@ -70631,7 +71449,7 @@ ${ui2.C.dim}criacao de skill cancelada${ui2.C.reset}
|
|
|
70631
71449
|
sc.phase = "body";
|
|
70632
71450
|
sc.bodyLines.push(line.replace(/\r$/, ""));
|
|
70633
71451
|
process.stdout.write(
|
|
70634
|
-
`${
|
|
71452
|
+
`${C5.yellow}isso parece a skill, nao gatilhos \u2014 capturei como conteudo.${C5.reset}
|
|
70635
71453
|
`
|
|
70636
71454
|
);
|
|
70637
71455
|
printBodyTally(sc);
|
|
@@ -70640,7 +71458,7 @@ ${ui2.C.dim}criacao de skill cancelada${ui2.C.reset}
|
|
|
70640
71458
|
sc.triggers = input ? input.split(",").map((t) => t.trim()).filter(Boolean) : [];
|
|
70641
71459
|
sc.phase = "body";
|
|
70642
71460
|
process.stdout.write(
|
|
70643
|
-
`${
|
|
71461
|
+
`${C5.cyan}cole ou escreva a skill agora${C5.reset} ${C5.dim}(qualquer tamanho). termine com uma linha contendo so /fim${C5.reset}
|
|
70644
71462
|
`
|
|
70645
71463
|
);
|
|
70646
71464
|
return;
|
|
@@ -70650,7 +71468,7 @@ ${ui2.C.dim}criacao de skill cancelada${ui2.C.reset}
|
|
|
70650
71468
|
const body = sc.bodyLines.join("\n").trim();
|
|
70651
71469
|
if (!body) {
|
|
70652
71470
|
process.stdout.write(
|
|
70653
|
-
`${
|
|
71471
|
+
`${C5.yellow}corpo vazio \u2014 cole algum conteudo ou /cancelar${C5.reset}
|
|
70654
71472
|
`
|
|
70655
71473
|
);
|
|
70656
71474
|
return;
|
|
@@ -70665,22 +71483,20 @@ ${ui2.C.dim}criacao de skill cancelada${ui2.C.reset}
|
|
|
70665
71483
|
await agent.refreshSkills();
|
|
70666
71484
|
process.stdout.write(
|
|
70667
71485
|
`
|
|
70668
|
-
${
|
|
70669
|
-
${
|
|
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}
|
|
70670
71488
|
`
|
|
70671
71489
|
);
|
|
70672
71490
|
return;
|
|
70673
71491
|
}
|
|
70674
71492
|
if (input === "/desfazer" || input === "/undo") {
|
|
70675
71493
|
if (sc.bodyLines.length === 0) {
|
|
70676
|
-
process.stdout.write(
|
|
70677
|
-
|
|
70678
|
-
`
|
|
70679
|
-
);
|
|
71494
|
+
process.stdout.write(`${C5.dim}nada para desfazer${C5.reset}
|
|
71495
|
+
`);
|
|
70680
71496
|
} else {
|
|
70681
71497
|
sc.bodyLines.pop();
|
|
70682
71498
|
process.stdout.write(
|
|
70683
|
-
`${
|
|
71499
|
+
`${C5.yellow}ultimo trecho removido.${C5.reset}
|
|
70684
71500
|
`
|
|
70685
71501
|
);
|
|
70686
71502
|
printBodyTally(sc);
|
|
@@ -70693,206 +71509,197 @@ ${ui2.C.dim}ja disponivel para todos os modelos nesta sessao.${ui2.C.reset}
|
|
|
70693
71509
|
}
|
|
70694
71510
|
}
|
|
70695
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
|
+
};
|
|
70696
71544
|
const handleLine = async (line) => {
|
|
70697
71545
|
if (closing) return;
|
|
70698
71546
|
const input = line.trim();
|
|
70699
71547
|
if (skillCreator) {
|
|
70700
71548
|
await handleSkillCreatorLine(line, input);
|
|
70701
|
-
if (!closing) prompt();
|
|
70702
71549
|
return;
|
|
70703
71550
|
}
|
|
70704
71551
|
if (input === "/exit" || input === "/quit") {
|
|
70705
71552
|
closing = true;
|
|
70706
|
-
rl.close();
|
|
70707
71553
|
return;
|
|
70708
71554
|
}
|
|
70709
71555
|
if (input === "/skillcreator" || input === "/skill" || input === "/skills") {
|
|
70710
71556
|
handleSkillCommand(input);
|
|
70711
|
-
if (!closing) prompt();
|
|
70712
71557
|
return;
|
|
70713
71558
|
}
|
|
70714
71559
|
if (input.startsWith("/skill ") || input.startsWith("/skills ")) {
|
|
70715
71560
|
await handleSkillSubcommand(input);
|
|
70716
|
-
if (!closing) prompt();
|
|
70717
71561
|
return;
|
|
70718
71562
|
}
|
|
70719
|
-
if (
|
|
70720
|
-
|
|
70721
|
-
|
|
70722
|
-
|
|
70723
|
-
|
|
70724
|
-
${ui2.C.dim}selecao de modelo cancelada${ui2.C.reset}
|
|
70725
|
-
`
|
|
70726
|
-
);
|
|
70727
|
-
if (!closing) prompt();
|
|
70728
|
-
return;
|
|
70729
|
-
}
|
|
71563
|
+
if (input === "/model" || input === "/models") {
|
|
71564
|
+
await openModelSelector();
|
|
71565
|
+
return;
|
|
71566
|
+
}
|
|
71567
|
+
if (input.startsWith("/model ") || input.startsWith("/models ")) {
|
|
70730
71568
|
const arg = input.replace(/^\/models?\s*/, "");
|
|
70731
71569
|
try {
|
|
70732
|
-
|
|
70733
|
-
process.stdout.write(formatModelSelection(result));
|
|
70734
|
-
awaitingModelSelection = !result.ok;
|
|
71570
|
+
printModelResult(await agent.setModelSelection(arg));
|
|
70735
71571
|
} catch (err) {
|
|
70736
|
-
|
|
70737
|
-
`
|
|
70738
|
-
[fatal] ${err instanceof Error ? err.stack || err.message : String(err)}
|
|
70739
|
-
`
|
|
70740
|
-
);
|
|
70741
|
-
awaitingModelSelection = false;
|
|
71572
|
+
printFatal(err);
|
|
70742
71573
|
}
|
|
70743
|
-
if (!closing) prompt();
|
|
70744
|
-
return;
|
|
70745
|
-
}
|
|
70746
|
-
if (!input) {
|
|
70747
|
-
prompt();
|
|
70748
71574
|
return;
|
|
70749
71575
|
}
|
|
70750
|
-
if (input === "/
|
|
70751
|
-
const
|
|
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>`;
|
|
70752
71587
|
try {
|
|
70753
|
-
|
|
70754
|
-
awaitingModelSelection = !arg && result.ok;
|
|
71588
|
+
await (0, import_promises2.writeFile)(filePath, html, "utf8");
|
|
70755
71589
|
process.stdout.write(
|
|
70756
|
-
|
|
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
|
+
`
|
|
70757
71593
|
);
|
|
70758
71594
|
} catch (err) {
|
|
70759
|
-
process.
|
|
70760
|
-
|
|
70761
|
-
[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)}
|
|
70762
71597
|
`
|
|
70763
71598
|
);
|
|
70764
|
-
awaitingModelSelection = false;
|
|
70765
71599
|
}
|
|
70766
|
-
if (!closing) prompt();
|
|
70767
71600
|
return;
|
|
70768
71601
|
}
|
|
70769
|
-
if (input === "/
|
|
70770
|
-
const sys2 = agent.getSystemPrompt();
|
|
70771
|
-
const audit = agent.getSystemPromptAudit();
|
|
70772
|
-
process.stdout.write(
|
|
70773
|
-
`\x1B[90m\u2500\u2500\u2500\u2500 system prompt (${sys2.length.toLocaleString()} caracteres) \u2500\u2500\u2500\u2500\x1B[0m
|
|
70774
|
-
`
|
|
70775
|
-
);
|
|
71602
|
+
if (input === "/nov" || input === "/novidades") {
|
|
70776
71603
|
process.stdout.write(
|
|
70777
|
-
|
|
71604
|
+
`
|
|
71605
|
+
${C5.cyan}${renderNews(clawfastVersion())}${C5.reset}
|
|
70778
71606
|
`
|
|
70779
71607
|
);
|
|
70780
|
-
process.stdout.write(sys2 + "\n");
|
|
70781
|
-
process.stdout.write(`\x1B[90m\u2500\u2500\u2500\u2500 fim do system prompt \u2500\u2500\u2500\u2500\x1B[0m
|
|
70782
|
-
`);
|
|
70783
|
-
if (!closing) prompt();
|
|
70784
|
-
return;
|
|
70785
|
-
}
|
|
70786
|
-
if (input === "/nov" || input === "/novidades") {
|
|
70787
|
-
process.stdout.write(`
|
|
70788
|
-
${ui2.C.cyan}${renderNews(clawfastVersion())}${ui2.C.reset}
|
|
70789
|
-
`);
|
|
70790
|
-
if (!closing) prompt();
|
|
70791
71608
|
return;
|
|
70792
71609
|
}
|
|
71610
|
+
if (!input) return;
|
|
70793
71611
|
process.stdout.write("\n" + agentHeader2());
|
|
70794
71612
|
activeAbort = new AbortController();
|
|
70795
71613
|
turnActive = true;
|
|
70796
|
-
|
|
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
|
+
);
|
|
70797
71635
|
try {
|
|
70798
71636
|
await agent.send(input, activeAbort.signal);
|
|
70799
71637
|
} catch (err) {
|
|
70800
|
-
|
|
70801
|
-
`
|
|
70802
|
-
[fatal] ${err instanceof Error ? err.stack || err.message : String(err)}
|
|
70803
|
-
`
|
|
70804
|
-
);
|
|
71638
|
+
printFatal(err);
|
|
70805
71639
|
} finally {
|
|
71640
|
+
inputUI.endTurn();
|
|
70806
71641
|
activeAbort = null;
|
|
70807
71642
|
turnActive = false;
|
|
70808
71643
|
}
|
|
70809
|
-
if (!closing) prompt();
|
|
70810
71644
|
};
|
|
70811
|
-
|
|
70812
|
-
|
|
70813
|
-
const line = pasteInput.expand(rawLine);
|
|
71645
|
+
process.removeAllListeners("SIGINT");
|
|
71646
|
+
process.on("SIGINT", () => {
|
|
70814
71647
|
if (turnActive) {
|
|
70815
|
-
|
|
70816
|
-
agent.sendStdin(line);
|
|
70817
|
-
}
|
|
71648
|
+
activeAbort?.abort();
|
|
70818
71649
|
return;
|
|
70819
71650
|
}
|
|
70820
|
-
|
|
70821
|
-
commandQueue = commandQueue.then(() => handleLine(line)).catch((err) => {
|
|
70822
|
-
process.stderr.write(
|
|
70823
|
-
`
|
|
70824
|
-
[fatal] ${err instanceof Error ? err.stack || err.message : String(err)}
|
|
70825
|
-
`
|
|
70826
|
-
);
|
|
70827
|
-
}).finally(() => {
|
|
70828
|
-
if (!closing) rl.resume();
|
|
70829
|
-
});
|
|
70830
|
-
});
|
|
70831
|
-
rl.on("close", async () => {
|
|
70832
|
-
closing = true;
|
|
70833
|
-
pasteInput.dispose();
|
|
70834
|
-
await commandQueue.catch(() => void 0);
|
|
70835
|
-
process.stdout.write("\nClosing sandbox...\n");
|
|
70836
|
-
await agent.close();
|
|
70837
|
-
process.exit(0);
|
|
71651
|
+
void shutdown();
|
|
70838
71652
|
});
|
|
70839
71653
|
process.on("exit", () => pasteInput.dispose());
|
|
70840
|
-
|
|
70841
|
-
|
|
70842
|
-
|
|
70843
|
-
|
|
70844
|
-
|
|
70845
|
-
|
|
70846
|
-
|
|
70847
|
-
|
|
70848
|
-
|
|
70849
|
-
|
|
70850
|
-
|
|
70851
|
-
reset: "\x1B[0m",
|
|
70852
|
-
bold: "\x1B[1m",
|
|
70853
|
-
dim: "\x1B[90m",
|
|
70854
|
-
green: "\x1B[32m",
|
|
70855
|
-
cyan: "\x1B[36m",
|
|
70856
|
-
yellow: "\x1B[33m",
|
|
70857
|
-
red: "\x1B[31m"
|
|
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";
|
|
70858
71665
|
}
|
|
70859
71666
|
};
|
|
70860
|
-
|
|
70861
|
-
|
|
70862
|
-
|
|
70863
|
-
|
|
70864
|
-
""
|
|
70865
|
-
|
|
70866
|
-
|
|
70867
|
-
|
|
70868
|
-
|
|
70869
|
-
|
|
70870
|
-
|
|
70871
|
-
|
|
70872
|
-
);
|
|
70873
|
-
}
|
|
70874
|
-
if (result.selection.unavailable.length > 0) {
|
|
70875
|
-
lines.push("", `${C4.yellow}${C4.bold}Indisponiveis${C4.reset}`);
|
|
70876
|
-
for (const group of result.selection.unavailable) {
|
|
70877
|
-
lines.push(`${group.provider}: ${C4.dim}${group.reason}${C4.reset}`);
|
|
70878
|
-
for (const model of group.models) {
|
|
70879
|
-
lines.push(` - ${model.label} ${C4.dim}(${model.key})${C4.reset}`);
|
|
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;
|
|
70880
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);
|
|
70881
71691
|
}
|
|
70882
71692
|
}
|
|
70883
|
-
|
|
70884
|
-
"",
|
|
70885
|
-
options.choosing ? `${C4.dim}Digite o numero, nome do modelo, auto para fallback, ou cancelar.${C4.reset}` : `${C4.dim}Use /model <numero> para fixar, /model auto para voltar ao fallback automatico.${C4.reset}`
|
|
70886
|
-
);
|
|
70887
|
-
return `
|
|
70888
|
-
${lines.join("\n")}
|
|
70889
|
-
`;
|
|
71693
|
+
await shutdown();
|
|
70890
71694
|
}
|
|
70891
|
-
var
|
|
71695
|
+
var import_node_os6, import_node_path9, import_node_fs8, import_promises2, deepseekEnabled, configuredModelProviders;
|
|
70892
71696
|
var init_index = __esm({
|
|
70893
71697
|
"index.ts"() {
|
|
70894
71698
|
"use strict";
|
|
70895
|
-
|
|
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");
|
|
70896
71703
|
init_paste_input();
|
|
70897
71704
|
init_boot_ui();
|
|
70898
71705
|
init_config();
|