clawfast 1.0.1 → 1.0.3

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.
Files changed (3) hide show
  1. package/README.md +19 -36
  2. package/dist/clawfast.cjs +918 -292
  3. package/package.json +1 -1
package/dist/clawfast.cjs CHANGED
@@ -85,8 +85,8 @@ var init_boot_ui = __esm({
85
85
  var require_main = __commonJS({
86
86
  "../node_modules/.pnpm/dotenv@17.4.2/node_modules/dotenv/lib/main.js"(exports2, module2) {
87
87
  "use strict";
88
- var fs3 = require("fs");
89
- var path5 = require("path");
88
+ var fs6 = require("fs");
89
+ var path8 = require("path");
90
90
  var os5 = require("os");
91
91
  var crypto2 = require("crypto");
92
92
  var TIPS = [
@@ -217,7 +217,7 @@ var require_main = __commonJS({
217
217
  if (options && options.path && options.path.length > 0) {
218
218
  if (Array.isArray(options.path)) {
219
219
  for (const filepath of options.path) {
220
- if (fs3.existsSync(filepath)) {
220
+ if (fs6.existsSync(filepath)) {
221
221
  possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
222
222
  }
223
223
  }
@@ -225,15 +225,15 @@ var require_main = __commonJS({
225
225
  possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`;
226
226
  }
227
227
  } else {
228
- possibleVaultPath = path5.resolve(process.cwd(), ".env.vault");
228
+ possibleVaultPath = path8.resolve(process.cwd(), ".env.vault");
229
229
  }
230
- if (fs3.existsSync(possibleVaultPath)) {
230
+ if (fs6.existsSync(possibleVaultPath)) {
231
231
  return possibleVaultPath;
232
232
  }
233
233
  return null;
234
234
  }
235
235
  function _resolveHome(envPath) {
236
- return envPath[0] === "~" ? path5.join(os5.homedir(), envPath.slice(1)) : envPath;
236
+ return envPath[0] === "~" ? path8.join(os5.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 = path5.resolve(process.cwd(), ".env");
253
+ const dotenvPath = path8.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 path6 of optionPaths) {
281
+ for (const path9 of optionPaths) {
282
282
  try {
283
- const parsed = DotenvModule.parse(fs3.readFileSync(path6, { encoding }));
283
+ const parsed = DotenvModule.parse(fs6.readFileSync(path9, { encoding }));
284
284
  DotenvModule.populate(parsedAll, parsed, options);
285
285
  } catch (e) {
286
286
  if (debug) {
287
- _debug(`failed to load ${path6} ${e.message}`);
287
+ _debug(`failed to load ${path9} ${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 = path5.relative(process.cwd(), filePath);
300
+ const relative2 = path8.relative(process.cwd(), filePath);
301
301
  shortPaths.push(relative2);
302
302
  } catch (e) {
303
303
  if (debug) {
@@ -442,7 +442,7 @@ async function ensureProviderKey() {
442
442
  if (hasAnyProviderKey()) return true;
443
443
  if (!process.stdin.isTTY) {
444
444
  process.stderr.write(
445
- `Nenhuma chave de modelo configurada. Defina OPENROUTER_API_KEY (ou HUGGINGFACE_API_KEY/HF_TOKEN/OPENAI_API_KEY) em ${clawfastEnvPath()} ou como vari\xE1vel de ambiente.
445
+ `Nenhuma chave de modelo configurada. Defina NVIDIA_API_KEY (ou OPENAI_API_KEY) em ${clawfastEnvPath()} ou como vari\xE1vel de ambiente.
446
446
  `
447
447
  );
448
448
  return false;
@@ -450,15 +450,15 @@ async function ensureProviderKey() {
450
450
  process.stdout.write(
451
451
  `
452
452
  ${C.greenB}Bem-vindo ao clawfast!${C.reset}
453
- ${C.dim}Para come\xE7ar, preciso de uma chave de modelo. A mais simples \xE9 o OpenRouter (tem modelos gratuitos):${C.reset}
454
- ${C.cyan}1.${C.reset} crie uma chave em ${C.green}https://openrouter.ai/keys${C.reset}
453
+ ${C.dim}Para come\xE7ar, preciso de uma chave de modelo. Use a NVIDIA build (modelos gratuitos):${C.reset}
454
+ ${C.cyan}1.${C.reset} crie uma chave em ${C.green}https://build.nvidia.com/${C.reset}
455
455
  ${C.cyan}2.${C.reset} cole abaixo (fica salva em ${clawfastEnvPath()})
456
456
 
457
457
  `
458
458
  );
459
459
  let key = "";
460
460
  while (!key) {
461
- key = await promptLine(`${C.greenB}Chave OpenRouter${C.reset} \u276F `);
461
+ key = await promptLine(`${C.greenB}Chave NVIDIA${C.reset} \u276F `);
462
462
  if (!key) {
463
463
  process.stdout.write(
464
464
  `${C.dim}chave vazia \u2014 cole de novo, ou Ctrl+C para sair.${C.reset}
@@ -466,8 +466,8 @@ ${C.dim}Para come\xE7ar, preciso de uma chave de modelo. A mais simples \xE9 o O
466
466
  );
467
467
  }
468
468
  }
469
- setEnvVar(clawfastEnvPath(), "OPENROUTER_API_KEY", key);
470
- process.env.OPENROUTER_API_KEY = key;
469
+ setEnvVar(clawfastEnvPath(), "NVIDIA_API_KEY", key);
470
+ process.env.NVIDIA_API_KEY = key;
471
471
  process.stdout.write(
472
472
  `${C.green}\u2713 chave salva em ${clawfastEnvPath()}${C.reset}
473
473
  `
@@ -485,12 +485,7 @@ var init_config = __esm({
485
485
  import_node_readline = __toESM(require("node:readline"));
486
486
  clawfastHome = () => process.env.CLAWFAST_HOME?.trim() || import_node_path.default.join(import_node_os.default.homedir(), ".clawfast");
487
487
  clawfastEnvPath = () => import_node_path.default.join(clawfastHome(), ".env");
488
- PROVIDER_KEYS = [
489
- "OPENROUTER_API_KEY",
490
- "OPENAI_API_KEY",
491
- "HUGGINGFACE_API_KEY",
492
- "HF_TOKEN"
493
- ];
488
+ PROVIDER_KEYS = ["NVIDIA_API_KEY", "OPENAI_API_KEY"];
494
489
  hasAnyProviderKey = () => PROVIDER_KEYS.some((name25) => Boolean(process.env[name25]?.trim()));
495
490
  C = {
496
491
  reset: "\x1B[0m",
@@ -502,6 +497,101 @@ var init_config = __esm({
502
497
  }
503
498
  });
504
499
 
500
+ // src/version.ts
501
+ var clawfastVersion, isDevVersion, isNewerVersion;
502
+ var init_version = __esm({
503
+ "src/version.ts"() {
504
+ "use strict";
505
+ clawfastVersion = () => true ? "1.0.3" : "0.0.0-dev";
506
+ isDevVersion = () => clawfastVersion().includes("-dev");
507
+ isNewerVersion = (a, b) => {
508
+ const parse3 = (v) => v.split("-")[0].split(".").map((n) => Number.parseInt(n, 10) || 0);
509
+ const pa = parse3(a);
510
+ const pb = parse3(b);
511
+ const len = Math.max(pa.length, pb.length);
512
+ for (let i = 0; i < len; i++) {
513
+ const da = pa[i] ?? 0;
514
+ const db = pb[i] ?? 0;
515
+ if (da > db) return true;
516
+ if (da < db) return false;
517
+ }
518
+ return false;
519
+ };
520
+ }
521
+ });
522
+
523
+ // src/update.ts
524
+ var import_node_fs2, import_node_path2, import_node_child_process, CHECK_INTERVAL_MS, REGISTRY_URL, cacheFile, readCache, writeCache, getUpdateNotice, refreshUpdateCacheInBackground, runSelfUpdate;
525
+ var init_update = __esm({
526
+ "src/update.ts"() {
527
+ "use strict";
528
+ import_node_fs2 = __toESM(require("node:fs"));
529
+ import_node_path2 = __toESM(require("node:path"));
530
+ import_node_child_process = require("node:child_process");
531
+ init_config();
532
+ init_version();
533
+ CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
534
+ REGISTRY_URL = "https://registry.npmjs.org/clawfast/latest";
535
+ cacheFile = () => import_node_path2.default.join(clawfastHome(), "update-check.json");
536
+ readCache = () => {
537
+ try {
538
+ const raw = import_node_fs2.default.readFileSync(cacheFile(), "utf8");
539
+ const parsed = JSON.parse(raw);
540
+ if (typeof parsed?.latest === "string" && typeof parsed?.lastCheck === "number") {
541
+ return parsed;
542
+ }
543
+ } catch {
544
+ }
545
+ return null;
546
+ };
547
+ writeCache = (cache) => {
548
+ try {
549
+ import_node_fs2.default.mkdirSync(clawfastHome(), { recursive: true });
550
+ import_node_fs2.default.writeFileSync(cacheFile(), JSON.stringify(cache), "utf8");
551
+ } catch {
552
+ }
553
+ };
554
+ getUpdateNotice = (current) => {
555
+ if (isDevVersion()) return null;
556
+ const cache = readCache();
557
+ if (cache && isNewerVersion(cache.latest, current)) {
558
+ return `nova versao ${cache.latest} disponivel (voce tem ${current}) \u2014 rode: clawfast update`;
559
+ }
560
+ return null;
561
+ };
562
+ refreshUpdateCacheInBackground = (current) => {
563
+ if (isDevVersion()) return;
564
+ const cache = readCache();
565
+ if (cache && Date.now() - cache.lastCheck < CHECK_INTERVAL_MS) return;
566
+ void (async () => {
567
+ try {
568
+ const controller = new AbortController();
569
+ const timer2 = setTimeout(() => controller.abort(), 3e3);
570
+ const res = await fetch(REGISTRY_URL, {
571
+ signal: controller.signal,
572
+ headers: { accept: "application/json" }
573
+ });
574
+ clearTimeout(timer2);
575
+ if (!res.ok) return;
576
+ const body = await res.json();
577
+ if (typeof body.version === "string") {
578
+ writeCache({ lastCheck: Date.now(), latest: body.version });
579
+ }
580
+ } catch {
581
+ }
582
+ })();
583
+ };
584
+ runSelfUpdate = () => new Promise((resolve2) => {
585
+ const child = (0, import_node_child_process.spawn)("npm install -g clawfast@latest", {
586
+ stdio: "inherit",
587
+ shell: true
588
+ });
589
+ child.on("close", (code) => resolve2(code ?? 1));
590
+ child.on("error", () => resolve2(1));
591
+ });
592
+ }
593
+ });
594
+
505
595
  // src/paste-input.ts
506
596
  function createPasteInput(opts = {}) {
507
597
  const input = new import_node_stream.PassThrough();
@@ -634,6 +724,215 @@ var init_paste_input = __esm({
634
724
  }
635
725
  });
636
726
 
727
+ // src/skills.ts
728
+ function listSkills() {
729
+ const dir = skillsDir();
730
+ let entries = [];
731
+ try {
732
+ entries = import_node_fs3.default.readdirSync(dir).filter((f) => f.endsWith(".md"));
733
+ } catch {
734
+ return [];
735
+ }
736
+ const skills = [];
737
+ for (const entry of entries.sort()) {
738
+ const file2 = import_node_path3.default.join(dir, entry);
739
+ let raw = "";
740
+ try {
741
+ raw = import_node_fs3.default.readFileSync(file2, "utf8");
742
+ } catch {
743
+ continue;
744
+ }
745
+ const { meta: meta3, body } = parseFrontmatter(raw);
746
+ const name25 = meta3.name?.trim() || entry.replace(/\.md$/, "");
747
+ const triggers = parseTriggers(meta3.triggers);
748
+ skills.push({
749
+ name: name25,
750
+ description: meta3.description?.trim() || "(sem descricao)",
751
+ // Default matching keywords = the slug's word parts when none were given.
752
+ triggers: triggers.length > 0 ? triggers : name25.split("-").filter(Boolean),
753
+ always: isTrue(meta3.always),
754
+ body: body.trim(),
755
+ file: file2
756
+ });
757
+ }
758
+ return skills;
759
+ }
760
+ function saveSkill(input) {
761
+ const slug = slugify(input.name);
762
+ if (!slug) {
763
+ throw new Error("nome de skill invalido (vazio apos normalizacao)");
764
+ }
765
+ const dir = skillsDir();
766
+ import_node_fs3.default.mkdirSync(dir, { recursive: true });
767
+ const file2 = import_node_path3.default.join(dir, `${slug}.md`);
768
+ const overwritten = import_node_fs3.default.existsSync(file2);
769
+ const triggers = (input.triggers ?? []).map((t) => t.trim().toLowerCase()).filter(Boolean);
770
+ const frontmatter = [
771
+ "---",
772
+ `name: ${slug}`,
773
+ `description: ${escapeFrontmatterValue(input.description ?? "")}`,
774
+ `triggers: ${triggers.join(", ")}`,
775
+ `always: ${input.always ? "true" : "false"}`,
776
+ "---",
777
+ ""
778
+ ].join("\n");
779
+ import_node_fs3.default.writeFileSync(file2, frontmatter + input.body.trim() + "\n", {
780
+ encoding: "utf8"
781
+ });
782
+ return {
783
+ skill: {
784
+ name: slug,
785
+ description: input.description?.trim() || "(sem descricao)",
786
+ triggers: triggers.length > 0 ? triggers : slug.split("-").filter(Boolean),
787
+ always: Boolean(input.always),
788
+ body: input.body.trim(),
789
+ file: file2
790
+ },
791
+ file: file2,
792
+ overwritten
793
+ };
794
+ }
795
+ function deleteSkill(name25) {
796
+ const slug = slugify(name25);
797
+ const file2 = import_node_path3.default.join(skillsDir(), `${slug}.md`);
798
+ try {
799
+ import_node_fs3.default.unlinkSync(file2);
800
+ return true;
801
+ } catch {
802
+ return false;
803
+ }
804
+ }
805
+ function buildSkillsIndexSection(skills = listSkills()) {
806
+ if (skills.length === 0) return "";
807
+ const lines = skills.map((s) => `- ${s.name}: ${s.description}`).join("\n");
808
+ return `
809
+
810
+ <skills_disponiveis>
811
+ Voce tem skills instaladas \u2014 conhecimento e procedimentos reutilizaveis criados pelo usuario. Quando o pedido do usuario casar com uma skill, o runtime do CLI carrega AUTOMATICAMENTE o conteudo completo dela neste turno (voce nao precisa pedir). Trate o conteudo carregado como instrucao de alta prioridade. Skills instaladas:
812
+ ${lines}
813
+ </skills_disponiveis>`;
814
+ }
815
+ function selectSkillsForInput(userInput, skills = listSkills()) {
816
+ const haystack = userInput.toLowerCase();
817
+ const matched = [];
818
+ for (const skill of skills) {
819
+ if (skill.always) {
820
+ matched.push(skill);
821
+ continue;
822
+ }
823
+ const keywords = [skill.name, ...skill.triggers].map((k) => k.toLowerCase()).filter((k) => k.length >= 3);
824
+ if (keywords.some((k) => haystack.includes(k))) {
825
+ matched.push(skill);
826
+ }
827
+ }
828
+ return matched;
829
+ }
830
+ function renderSkillBodies(skills) {
831
+ if (skills.length === 0) return "";
832
+ const blocks = skills.map((s) => `<skill name="${s.name}">
833
+ ${s.body}
834
+ </skill>`).join("\n\n");
835
+ return `
836
+
837
+ <active_skills>
838
+ As skills a seguir foram carregadas porque o pedido atual casou com elas (ou estao marcadas como sempre-ativas). Siga o conhecimento e os procedimentos delas como instrucao de alta prioridade nesta tarefa.
839
+
840
+ ${blocks}
841
+ </active_skills>`;
842
+ }
843
+ var import_node_fs3, import_node_path3, skillsDir, slugify, FRONTMATTER_RE, parseFrontmatter, parseTriggers, isTrue, escapeFrontmatterValue;
844
+ var init_skills = __esm({
845
+ "src/skills.ts"() {
846
+ "use strict";
847
+ import_node_fs3 = __toESM(require("node:fs"));
848
+ import_node_path3 = __toESM(require("node:path"));
849
+ init_config();
850
+ skillsDir = () => import_node_path3.default.join(clawfastHome(), "skills");
851
+ slugify = (name25) => name25.trim().toLowerCase().normalize("NFD").replace(/[̀-ͯ]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64);
852
+ FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
853
+ parseFrontmatter = (raw) => {
854
+ const match = raw.match(FRONTMATTER_RE);
855
+ if (!match) return { meta: {}, body: raw };
856
+ const meta3 = {};
857
+ for (const line of match[1].split(/\r?\n/)) {
858
+ const idx = line.indexOf(":");
859
+ if (idx === -1) continue;
860
+ const key = line.slice(0, idx).trim().toLowerCase();
861
+ const value = line.slice(idx + 1).trim();
862
+ if (key) meta3[key] = value;
863
+ }
864
+ return { meta: meta3, body: raw.slice(match[0].length) };
865
+ };
866
+ parseTriggers = (raw) => (raw ?? "").split(",").map((t) => t.trim().toLowerCase()).filter(Boolean);
867
+ isTrue = (raw) => /^(1|true|yes|sim)$/i.test((raw ?? "").trim());
868
+ escapeFrontmatterValue = (value) => value.replace(/\r?\n/g, " ").trim();
869
+ }
870
+ });
871
+
872
+ // src/news.ts
873
+ var import_node_fs4, import_node_path4, NEWS, latestNewsVersion, renderNews, stateFile, readState, writeState, consumePostUpdateLaunch;
874
+ var init_news = __esm({
875
+ "src/news.ts"() {
876
+ "use strict";
877
+ import_node_fs4 = __toESM(require("node:fs"));
878
+ import_node_path4 = __toESM(require("node:path"));
879
+ init_config();
880
+ NEWS = {
881
+ "1.0.3": [
882
+ "Atualizacao: `clawfast update` atualiza o CLI e mostra as boas-vindas; aparece um aviso quando ha versao nova; /nov lista as novidades.",
883
+ "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: minimax-m3, kimi-k2.6, glm-5.1 e qwen3.5-397b \u2014 todos com function calling de verdade (as ferramentas disparam).",
885
+ "Resiliencia a rate limit (429): cai para os outros modelos como contingencia e espera/retenta a cadeia automaticamente."
886
+ ]
887
+ };
888
+ latestNewsVersion = () => {
889
+ const keys = Object.keys(NEWS);
890
+ if (keys.length === 0) return null;
891
+ return keys.sort((a, b) => {
892
+ const pa = a.split(".").map(Number);
893
+ const pb = b.split(".").map(Number);
894
+ for (let i = 0; i < 3; i++) {
895
+ if ((pb[i] ?? 0) !== (pa[i] ?? 0)) return (pb[i] ?? 0) - (pa[i] ?? 0);
896
+ }
897
+ return 0;
898
+ })[0];
899
+ };
900
+ renderNews = (version3) => {
901
+ const key = NEWS[version3] ? version3 : latestNewsVersion();
902
+ if (!key || !NEWS[key]) {
903
+ return "Sem novidades registradas para esta versao.";
904
+ }
905
+ const lines = NEWS[key].map((item) => ` \u2022 ${item}`).join("\n");
906
+ return `Novidades da versao ${key}:
907
+ ${lines}`;
908
+ };
909
+ stateFile = () => import_node_path4.default.join(clawfastHome(), "state.json");
910
+ readState = () => {
911
+ try {
912
+ return JSON.parse(import_node_fs4.default.readFileSync(stateFile(), "utf8"));
913
+ } catch {
914
+ return {};
915
+ }
916
+ };
917
+ writeState = (state) => {
918
+ try {
919
+ import_node_fs4.default.mkdirSync(clawfastHome(), { recursive: true });
920
+ import_node_fs4.default.writeFileSync(stateFile(), JSON.stringify(state), "utf8");
921
+ } catch {
922
+ }
923
+ };
924
+ consumePostUpdateLaunch = (current) => {
925
+ const state = readState();
926
+ const previous = state.lastVersion;
927
+ if (previous !== current) {
928
+ writeState({ ...state, lastVersion: current });
929
+ return Boolean(previous);
930
+ }
931
+ return false;
932
+ };
933
+ }
934
+ });
935
+
637
936
  // ../node_modules/.pnpm/@ai-sdk+provider@3.0.10/node_modules/@ai-sdk/provider/dist/index.mjs
638
937
  function getErrorMessage(error51) {
639
938
  if (error51 == null) {
@@ -1100,7 +1399,7 @@ __export(util_exports, {
1100
1399
  required: () => required,
1101
1400
  safeExtend: () => safeExtend,
1102
1401
  shallowClone: () => shallowClone,
1103
- slugify: () => slugify,
1402
+ slugify: () => slugify2,
1104
1403
  stringifyPrimitive: () => stringifyPrimitive,
1105
1404
  uint8ArrayToBase64: () => uint8ArrayToBase64,
1106
1405
  uint8ArrayToBase64url: () => uint8ArrayToBase64url,
@@ -1206,10 +1505,10 @@ function mergeDefs(...defs) {
1206
1505
  function cloneDef(schema) {
1207
1506
  return mergeDefs(schema._zod.def);
1208
1507
  }
1209
- function getElementAtPath(obj, path5) {
1210
- if (!path5)
1508
+ function getElementAtPath(obj, path8) {
1509
+ if (!path8)
1211
1510
  return obj;
1212
- return path5.reduce((acc, key) => acc?.[key], obj);
1511
+ return path8.reduce((acc, key) => acc?.[key], obj);
1213
1512
  }
1214
1513
  function promiseAllObject(promisesObj) {
1215
1514
  const keys = Object.keys(promisesObj);
@@ -1233,7 +1532,7 @@ function randomString(length = 10) {
1233
1532
  function esc(str) {
1234
1533
  return JSON.stringify(str);
1235
1534
  }
1236
- function slugify(input) {
1535
+ function slugify2(input) {
1237
1536
  return input.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/[\s_-]+/g, "-").replace(/^-+|-+$/g, "");
1238
1537
  }
1239
1538
  function isObject(data) {
@@ -1537,11 +1836,11 @@ function explicitlyAborted(x, startIndex = 0) {
1537
1836
  }
1538
1837
  return false;
1539
1838
  }
1540
- function prefixIssues(path5, issues) {
1839
+ function prefixIssues(path8, issues) {
1541
1840
  return issues.map((iss) => {
1542
1841
  var _a25;
1543
1842
  (_a25 = iss).path ?? (_a25.path = []);
1544
- iss.path.unshift(path5);
1843
+ iss.path.unshift(path8);
1545
1844
  return iss;
1546
1845
  });
1547
1846
  }
@@ -1759,16 +2058,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
1759
2058
  }
1760
2059
  function formatError(error51, mapper = (issue2) => issue2.message) {
1761
2060
  const fieldErrors = { _errors: [] };
1762
- const processError = (error52, path5 = []) => {
2061
+ const processError = (error52, path8 = []) => {
1763
2062
  for (const issue2 of error52.issues) {
1764
2063
  if (issue2.code === "invalid_union" && issue2.errors.length) {
1765
- issue2.errors.map((issues) => processError({ issues }, [...path5, ...issue2.path]));
2064
+ issue2.errors.map((issues) => processError({ issues }, [...path8, ...issue2.path]));
1766
2065
  } else if (issue2.code === "invalid_key") {
1767
- processError({ issues: issue2.issues }, [...path5, ...issue2.path]);
2066
+ processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
1768
2067
  } else if (issue2.code === "invalid_element") {
1769
- processError({ issues: issue2.issues }, [...path5, ...issue2.path]);
2068
+ processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
1770
2069
  } else {
1771
- const fullpath = [...path5, ...issue2.path];
2070
+ const fullpath = [...path8, ...issue2.path];
1772
2071
  if (fullpath.length === 0) {
1773
2072
  fieldErrors._errors.push(mapper(issue2));
1774
2073
  } else {
@@ -1795,17 +2094,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
1795
2094
  }
1796
2095
  function treeifyError(error51, mapper = (issue2) => issue2.message) {
1797
2096
  const result = { errors: [] };
1798
- const processError = (error52, path5 = []) => {
2097
+ const processError = (error52, path8 = []) => {
1799
2098
  var _a25, _b18;
1800
2099
  for (const issue2 of error52.issues) {
1801
2100
  if (issue2.code === "invalid_union" && issue2.errors.length) {
1802
- issue2.errors.map((issues) => processError({ issues }, [...path5, ...issue2.path]));
2101
+ issue2.errors.map((issues) => processError({ issues }, [...path8, ...issue2.path]));
1803
2102
  } else if (issue2.code === "invalid_key") {
1804
- processError({ issues: issue2.issues }, [...path5, ...issue2.path]);
2103
+ processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
1805
2104
  } else if (issue2.code === "invalid_element") {
1806
- processError({ issues: issue2.issues }, [...path5, ...issue2.path]);
2105
+ processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
1807
2106
  } else {
1808
- const fullpath = [...path5, ...issue2.path];
2107
+ const fullpath = [...path8, ...issue2.path];
1809
2108
  if (fullpath.length === 0) {
1810
2109
  result.errors.push(mapper(issue2));
1811
2110
  continue;
@@ -1837,8 +2136,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
1837
2136
  }
1838
2137
  function toDotPath(_path) {
1839
2138
  const segs = [];
1840
- const path5 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
1841
- for (const seg of path5) {
2139
+ const path8 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
2140
+ for (const seg of path8) {
1842
2141
  if (typeof seg === "number")
1843
2142
  segs.push(`[${seg}]`);
1844
2143
  else if (typeof seg === "symbol")
@@ -11979,7 +12278,7 @@ function _toUpperCase() {
11979
12278
  }
11980
12279
  // @__NO_SIDE_EFFECTS__
11981
12280
  function _slugify() {
11982
- return /* @__PURE__ */ _overwrite((input) => slugify(input));
12281
+ return /* @__PURE__ */ _overwrite((input) => slugify2(input));
11983
12282
  }
11984
12283
  // @__NO_SIDE_EFFECTS__
11985
12284
  function _array(Class2, element, params) {
@@ -15341,13 +15640,13 @@ function resolveRef(ref, ctx) {
15341
15640
  if (!ref.startsWith("#")) {
15342
15641
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
15343
15642
  }
15344
- const path5 = ref.slice(1).split("/").filter(Boolean);
15345
- if (path5.length === 0) {
15643
+ const path8 = ref.slice(1).split("/").filter(Boolean);
15644
+ if (path8.length === 0) {
15346
15645
  return ctx.rootSchema;
15347
15646
  }
15348
15647
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
15349
- if (path5[0] === defsKey) {
15350
- const key = path5[1];
15648
+ if (path8[0] === defsKey) {
15649
+ const key = path8[1];
15351
15650
  if (!key || !ctx.defs[key]) {
15352
15651
  throw new Error(`Reference not found: ${ref}`);
15353
15652
  }
@@ -16536,8 +16835,8 @@ var init_parseUtil = __esm({
16536
16835
  init_errors3();
16537
16836
  init_en2();
16538
16837
  makeIssue = (params) => {
16539
- const { data, path: path5, errorMaps, issueData } = params;
16540
- const fullPath = [...path5, ...issueData.path || []];
16838
+ const { data, path: path8, errorMaps, issueData } = params;
16839
+ const fullPath = [...path8, ...issueData.path || []];
16541
16840
  const fullIssue = {
16542
16841
  ...issueData,
16543
16842
  path: fullPath
@@ -16820,11 +17119,11 @@ var init_types = __esm({
16820
17119
  init_parseUtil();
16821
17120
  init_util2();
16822
17121
  ParseInputLazyPath = class {
16823
- constructor(parent, value, path5, key) {
17122
+ constructor(parent, value, path8, key) {
16824
17123
  this._cachedPath = [];
16825
17124
  this.parent = parent;
16826
17125
  this.data = value;
16827
- this._path = path5;
17126
+ this._path = path8;
16828
17127
  this._key = key;
16829
17128
  }
16830
17129
  get path() {
@@ -22863,8 +23162,8 @@ var require_auth_config = __commonJS({
22863
23162
  writeAuthConfig: () => writeAuthConfig
22864
23163
  });
22865
23164
  module2.exports = __toCommonJS(auth_config_exports);
22866
- var fs3 = __toESM2(require("fs"));
22867
- var path5 = __toESM2(require("path"));
23165
+ var fs6 = __toESM2(require("fs"));
23166
+ var path8 = __toESM2(require("path"));
22868
23167
  var import_token_util = require_token_util();
22869
23168
  function getAuthConfigPath() {
22870
23169
  const dataDir = (0, import_token_util.getVercelDataDir)();
@@ -22873,15 +23172,15 @@ var require_auth_config = __commonJS({
22873
23172
  `Unable to find Vercel CLI data directory. Your platform: ${process.platform}. Supported: darwin, linux, win32.`
22874
23173
  );
22875
23174
  }
22876
- return path5.join(dataDir, "auth.json");
23175
+ return path8.join(dataDir, "auth.json");
22877
23176
  }
22878
23177
  function readAuthConfig() {
22879
23178
  try {
22880
23179
  const authPath = getAuthConfigPath();
22881
- if (!fs3.existsSync(authPath)) {
23180
+ if (!fs6.existsSync(authPath)) {
22882
23181
  return null;
22883
23182
  }
22884
- const content = fs3.readFileSync(authPath, "utf8");
23183
+ const content = fs6.readFileSync(authPath, "utf8");
22885
23184
  if (!content) {
22886
23185
  return null;
22887
23186
  }
@@ -22892,11 +23191,11 @@ var require_auth_config = __commonJS({
22892
23191
  }
22893
23192
  function writeAuthConfig(config3) {
22894
23193
  const authPath = getAuthConfigPath();
22895
- const authDir = path5.dirname(authPath);
22896
- if (!fs3.existsSync(authDir)) {
22897
- fs3.mkdirSync(authDir, { mode: 504, recursive: true });
23194
+ const authDir = path8.dirname(authPath);
23195
+ if (!fs6.existsSync(authDir)) {
23196
+ fs6.mkdirSync(authDir, { mode: 504, recursive: true });
22898
23197
  }
22899
- fs3.writeFileSync(authPath, JSON.stringify(config3, null, 2), { mode: 384 });
23198
+ fs6.writeFileSync(authPath, JSON.stringify(config3, null, 2), { mode: 384 });
22900
23199
  }
22901
23200
  function isValidAccessToken(authConfig, expirationBufferMs = 0) {
22902
23201
  if (!authConfig.token)
@@ -23087,8 +23386,8 @@ var require_token_util = __commonJS({
23087
23386
  saveToken: () => saveToken
23088
23387
  });
23089
23388
  module2.exports = __toCommonJS(token_util_exports);
23090
- var path5 = __toESM2(require("path"));
23091
- var fs3 = __toESM2(require("fs"));
23389
+ var path8 = __toESM2(require("path"));
23390
+ var fs6 = __toESM2(require("fs"));
23092
23391
  var import_token_error = require_token_error();
23093
23392
  var import_token_io = require_token_io();
23094
23393
  var import_auth_config = require_auth_config();
@@ -23100,7 +23399,7 @@ var require_token_util = __commonJS({
23100
23399
  if (!dataDir) {
23101
23400
  return null;
23102
23401
  }
23103
- return path5.join(dataDir, vercelFolder);
23402
+ return path8.join(dataDir, vercelFolder);
23104
23403
  }
23105
23404
  async function getVercelToken2(options) {
23106
23405
  const authConfig = (0, import_auth_config.readAuthConfig)();
@@ -23176,13 +23475,13 @@ var require_token_util = __commonJS({
23176
23475
  "Unable to find project root directory. Have you linked your project with `vc link?`"
23177
23476
  );
23178
23477
  }
23179
- const prjPath = path5.join(dir, ".vercel", "project.json");
23180
- if (!fs3.existsSync(prjPath)) {
23478
+ const prjPath = path8.join(dir, ".vercel", "project.json");
23479
+ if (!fs6.existsSync(prjPath)) {
23181
23480
  throw new import_token_error.VercelOidcTokenError(
23182
23481
  "project.json not found, have you linked your project with `vc link?`"
23183
23482
  );
23184
23483
  }
23185
- const prj = JSON.parse(fs3.readFileSync(prjPath, "utf8"));
23484
+ const prj = JSON.parse(fs6.readFileSync(prjPath, "utf8"));
23186
23485
  if (typeof prj.projectId !== "string" && typeof prj.orgId !== "string") {
23187
23486
  throw new TypeError(
23188
23487
  "Expected a string-valued projectId property. Try running `vc link` to re-link your project."
@@ -23197,11 +23496,11 @@ var require_token_util = __commonJS({
23197
23496
  "Unable to find user data directory. Please reach out to Vercel support."
23198
23497
  );
23199
23498
  }
23200
- const tokenPath = path5.join(dir, "com.vercel.token", `${projectId}.json`);
23499
+ const tokenPath = path8.join(dir, "com.vercel.token", `${projectId}.json`);
23201
23500
  const tokenJson = JSON.stringify(token);
23202
- fs3.mkdirSync(path5.dirname(tokenPath), { mode: 504, recursive: true });
23203
- fs3.writeFileSync(tokenPath, tokenJson);
23204
- fs3.chmodSync(tokenPath, 432);
23501
+ fs6.mkdirSync(path8.dirname(tokenPath), { mode: 504, recursive: true });
23502
+ fs6.writeFileSync(tokenPath, tokenJson);
23503
+ fs6.chmodSync(tokenPath, 432);
23205
23504
  return;
23206
23505
  }
23207
23506
  function loadToken(projectId) {
@@ -23211,11 +23510,11 @@ var require_token_util = __commonJS({
23211
23510
  "Unable to find user data directory. Please reach out to Vercel support."
23212
23511
  );
23213
23512
  }
23214
- const tokenPath = path5.join(dir, "com.vercel.token", `${projectId}.json`);
23215
- if (!fs3.existsSync(tokenPath)) {
23513
+ const tokenPath = path8.join(dir, "com.vercel.token", `${projectId}.json`);
23514
+ if (!fs6.existsSync(tokenPath)) {
23216
23515
  return null;
23217
23516
  }
23218
- const token = JSON.parse(fs3.readFileSync(tokenPath, "utf8"));
23517
+ const token = JSON.parse(fs6.readFileSync(tokenPath, "utf8"));
23219
23518
  assertVercelOidcTokenResponse(token);
23220
23519
  return token;
23221
23520
  }
@@ -25166,7 +25465,7 @@ var init_platform = __esm({
25166
25465
 
25167
25466
  // ../node_modules/.pnpm/@opentelemetry+api@1.9.0/node_modules/@opentelemetry/api/build/esm/version.js
25168
25467
  var VERSION3;
25169
- var init_version = __esm({
25468
+ var init_version2 = __esm({
25170
25469
  "../node_modules/.pnpm/@opentelemetry+api@1.9.0/node_modules/@opentelemetry/api/build/esm/version.js"() {
25171
25470
  "use strict";
25172
25471
  VERSION3 = "1.9.0";
@@ -25241,7 +25540,7 @@ var re, isCompatible;
25241
25540
  var init_semver = __esm({
25242
25541
  "../node_modules/.pnpm/@opentelemetry+api@1.9.0/node_modules/@opentelemetry/api/build/esm/internal/semver.js"() {
25243
25542
  "use strict";
25244
- init_version();
25543
+ init_version2();
25245
25544
  re = /^(\d+)\.(\d+)\.(\d+)(-(.+))?$/;
25246
25545
  isCompatible = _makeCompatibilityCheck(VERSION3);
25247
25546
  }
@@ -25290,7 +25589,7 @@ var init_global_utils = __esm({
25290
25589
  "../node_modules/.pnpm/@opentelemetry+api@1.9.0/node_modules/@opentelemetry/api/build/esm/internal/global-utils.js"() {
25291
25590
  "use strict";
25292
25591
  init_platform();
25293
- init_version();
25592
+ init_version2();
25294
25593
  init_semver();
25295
25594
  major = VERSION3.split(".")[0];
25296
25595
  GLOBAL_OPENTELEMETRY_API_KEY = Symbol.for("opentelemetry.js.api." + major);
@@ -35241,7 +35540,7 @@ function createOpenRouter(options = {}) {
35241
35540
  );
35242
35541
  const createChatModel = (modelId, settings = {}) => new OpenRouterChatLanguageModel(modelId, settings, {
35243
35542
  provider: "openrouter.chat",
35244
- url: ({ path: path5 }) => `${baseURL}${path5}`,
35543
+ url: ({ path: path8 }) => `${baseURL}${path8}`,
35245
35544
  headers: getHeaders,
35246
35545
  compatibility,
35247
35546
  fetch: options.fetch,
@@ -35249,7 +35548,7 @@ function createOpenRouter(options = {}) {
35249
35548
  });
35250
35549
  const createCompletionModel = (modelId, settings = {}) => new OpenRouterCompletionLanguageModel(modelId, settings, {
35251
35550
  provider: "openrouter.completion",
35252
- url: ({ path: path5 }) => `${baseURL}${path5}`,
35551
+ url: ({ path: path8 }) => `${baseURL}${path8}`,
35253
35552
  headers: getHeaders,
35254
35553
  compatibility,
35255
35554
  fetch: options.fetch,
@@ -35257,21 +35556,21 @@ function createOpenRouter(options = {}) {
35257
35556
  });
35258
35557
  const createEmbeddingModel = (modelId, settings = {}) => new OpenRouterEmbeddingModel(modelId, settings, {
35259
35558
  provider: "openrouter.embedding",
35260
- url: ({ path: path5 }) => `${baseURL}${path5}`,
35559
+ url: ({ path: path8 }) => `${baseURL}${path8}`,
35261
35560
  headers: getHeaders,
35262
35561
  fetch: options.fetch,
35263
35562
  extraBody: options.extraBody
35264
35563
  });
35265
35564
  const createImageModel = (modelId, settings = {}) => new OpenRouterImageModel(modelId, settings, {
35266
35565
  provider: "openrouter.image",
35267
- url: ({ path: path5 }) => `${baseURL}${path5}`,
35566
+ url: ({ path: path8 }) => `${baseURL}${path8}`,
35268
35567
  headers: getHeaders,
35269
35568
  fetch: options.fetch,
35270
35569
  extraBody: options.extraBody
35271
35570
  });
35272
35571
  const createVideoModel = (modelId, settings = {}) => new OpenRouterVideoModel(modelId, settings, {
35273
35572
  provider: "openrouter.video",
35274
- url: ({ path: path5 }) => `${baseURL}${path5}`,
35573
+ url: ({ path: path8 }) => `${baseURL}${path8}`,
35275
35574
  headers: getHeaders,
35276
35575
  fetch: options.fetch,
35277
35576
  extraBody: options.extraBody
@@ -39807,37 +40106,37 @@ function createOpenAI(options = {}) {
39807
40106
  );
39808
40107
  const createChatModel = (modelId) => new OpenAIChatLanguageModel(modelId, {
39809
40108
  provider: `${providerName}.chat`,
39810
- url: ({ path: path5 }) => `${baseURL}${path5}`,
40109
+ url: ({ path: path8 }) => `${baseURL}${path8}`,
39811
40110
  headers: getHeaders,
39812
40111
  fetch: options.fetch
39813
40112
  });
39814
40113
  const createCompletionModel = (modelId) => new OpenAICompletionLanguageModel(modelId, {
39815
40114
  provider: `${providerName}.completion`,
39816
- url: ({ path: path5 }) => `${baseURL}${path5}`,
40115
+ url: ({ path: path8 }) => `${baseURL}${path8}`,
39817
40116
  headers: getHeaders,
39818
40117
  fetch: options.fetch
39819
40118
  });
39820
40119
  const createEmbeddingModel = (modelId) => new OpenAIEmbeddingModel(modelId, {
39821
40120
  provider: `${providerName}.embedding`,
39822
- url: ({ path: path5 }) => `${baseURL}${path5}`,
40121
+ url: ({ path: path8 }) => `${baseURL}${path8}`,
39823
40122
  headers: getHeaders,
39824
40123
  fetch: options.fetch
39825
40124
  });
39826
40125
  const createImageModel = (modelId) => new OpenAIImageModel(modelId, {
39827
40126
  provider: `${providerName}.image`,
39828
- url: ({ path: path5 }) => `${baseURL}${path5}`,
40127
+ url: ({ path: path8 }) => `${baseURL}${path8}`,
39829
40128
  headers: getHeaders,
39830
40129
  fetch: options.fetch
39831
40130
  });
39832
40131
  const createTranscriptionModel = (modelId) => new OpenAITranscriptionModel(modelId, {
39833
40132
  provider: `${providerName}.transcription`,
39834
- url: ({ path: path5 }) => `${baseURL}${path5}`,
40133
+ url: ({ path: path8 }) => `${baseURL}${path8}`,
39835
40134
  headers: getHeaders,
39836
40135
  fetch: options.fetch
39837
40136
  });
39838
40137
  const createSpeechModel = (modelId) => new OpenAISpeechModel(modelId, {
39839
40138
  provider: `${providerName}.speech`,
39840
- url: ({ path: path5 }) => `${baseURL}${path5}`,
40139
+ url: ({ path: path8 }) => `${baseURL}${path8}`,
39841
40140
  headers: getHeaders,
39842
40141
  fetch: options.fetch
39843
40142
  });
@@ -39852,7 +40151,7 @@ function createOpenAI(options = {}) {
39852
40151
  const createResponsesModel = (modelId) => {
39853
40152
  return new OpenAIResponsesLanguageModel(modelId, {
39854
40153
  provider: `${providerName}.responses`,
39855
- url: ({ path: path5 }) => `${baseURL}${path5}`,
40154
+ url: ({ path: path8 }) => `${baseURL}${path8}`,
39856
40155
  headers: getHeaders,
39857
40156
  fetch: options.fetch,
39858
40157
  fileIdPrefixes: ["file-"]
@@ -45073,7 +45372,7 @@ function supportsMultimodalToolResults(modelName) {
45073
45372
  const normalized = modelName.toLowerCase();
45074
45373
  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");
45075
45374
  }
45076
- var isRecord, isXaiModelSlug, isGeminiModelSlug, requestCanRouteToXai, requestCanRouteToGemini, hasOwnEncryptedContent, stripEncryptedContent, sanitizeOpenRouterRequestForXai, hasJsonRefKey, wrapToolContentIfGeminiRefSensitive, sanitizeOpenRouterRequestForGeminiFunctionResponses, patchKimiReasoningToolCalls, OPENROUTER_METADATA_HEADER, withOpenRouterMetadataHeader, openrouterPatchFetch, openrouter2, openai2, nvidia, huggingface, deepseek, kimi, buildProviderMap, hasEnvValue, hasHuggingFaceKey, isDeepSeekEnabled, isKimiEnabled, CLI_MODEL_CHAIN, baseProviders, modelCutoffDates, modelDisplayNames, getModelDisplayName, getModelCutoffDate, myProvider;
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;
45077
45376
  var init_providers = __esm({
45078
45377
  "../lib/ai/providers.ts"() {
45079
45378
  "use strict";
@@ -45238,11 +45537,6 @@ var init_providers = __esm({
45238
45537
  baseURL: process.env.NVIDIA_BASE_URL || "https://integrate.api.nvidia.com/v1",
45239
45538
  apiKey: process.env.NVIDIA_API_KEY
45240
45539
  });
45241
- huggingface = createOpenAI({
45242
- name: "huggingface",
45243
- baseURL: process.env.HUGGINGFACE_BASE_URL || "https://router.huggingface.co/v1",
45244
- apiKey: process.env.HUGGINGFACE_API_KEY || process.env.HF_TOKEN
45245
- });
45246
45540
  deepseek = createOpenAI({
45247
45541
  name: "deepseek",
45248
45542
  // Default to the deepsproxy port the clawfast proxy-manager starts it on, so
@@ -45268,19 +45562,14 @@ var init_providers = __esm({
45268
45562
  "model-deepseek-v4-flash": or("z-ai/glm-4.5-air:free"),
45269
45563
  "model-opus-4.6": nvidia("nvidia/nemotron-3-ultra-550b-a55b"),
45270
45564
  "model-kimi-k2.6": or("qwen/qwen3-coder:free"),
45565
+ // NVIDIA build models — primary provider for the local CLI (chat-completions).
45566
+ "model-nvidia-minimax-m3": nvidia.chat("minimaxai/minimax-m3"),
45567
+ "model-nvidia-kimi-k2.6": nvidia.chat("moonshotai/kimi-k2.6"),
45568
+ "model-nvidia-glm-5.1": nvidia.chat("z-ai/glm-5.1"),
45569
+ "model-nvidia-qwen3.5-397b": nvidia.chat("qwen/qwen3.5-397b-a17b"),
45271
45570
  // Extra explicit keys for the CLI.
45272
- "model-glm-4.5-air": or("z-ai/glm-4.5-air:free"),
45273
- "model-qwen3-coder": or("qwen/qwen3-coder:free"),
45274
45571
  "model-openai-chat-latest": openai2("chat-latest"),
45275
45572
  "model-nvidia-nemotron": nvidia("nvidia/nemotron-3-ultra-550b-a55b"),
45276
- "model-hf-qwen3-6-35b-a3b": huggingface.chat("Qwen/Qwen3.6-35B-A3B"),
45277
- "model-hf-glm-5-1-fp8": huggingface.chat("zai-org/GLM-5.1-FP8"),
45278
- "model-hf-deepseek-v4-flash": huggingface.chat(
45279
- "deepseek-ai/DeepSeek-V4-Flash"
45280
- ),
45281
- "model-hf-deepseek-v4-flash-nvfp4": huggingface.chat(
45282
- "nvidia/DeepSeek-V4-Flash-NVFP4"
45283
- ),
45284
45573
  // DeepSeek via logged-in web session (deepsproxy) or official API.
45285
45574
  "model-deepseek-proxy": deepseek.chat(
45286
45575
  process.env.DEEPSEEK_MODEL || "deepseek-v4-flash"
@@ -45297,7 +45586,6 @@ var init_providers = __esm({
45297
45586
  "title-generator-model": or("z-ai/glm-4.5-air:free")
45298
45587
  });
45299
45588
  hasEnvValue = (name25) => Boolean(process.env[name25]?.trim());
45300
- hasHuggingFaceKey = () => hasEnvValue("HUGGINGFACE_API_KEY") || hasEnvValue("HF_TOKEN");
45301
45589
  isDeepSeekEnabled = () => {
45302
45590
  const flag = process.env.DEEPSEEK_ENABLED?.trim().toLowerCase();
45303
45591
  if (flag === "1" || flag === "true" || flag === "yes") return true;
@@ -45311,23 +45599,19 @@ var init_providers = __esm({
45311
45599
  return hasEnvValue("KIMI_BASE_URL") || hasEnvValue("KIMI_API_KEY");
45312
45600
  };
45313
45601
  CLI_MODEL_CHAIN = [
45314
- ...hasEnvValue("OPENROUTER_API_KEY") ? [
45315
- "agent-model",
45316
- // OpenRouter glm-4.5-air:free — real tool calling
45317
- "model-qwen3-coder"
45318
- // OpenRouter qwen/qwen3-coder:free
45602
+ ...hasEnvValue("NVIDIA_API_KEY") ? [
45603
+ "model-nvidia-minimax-m3",
45604
+ // NVIDIA minimaxai/minimax-m3
45605
+ "model-nvidia-kimi-k2.6",
45606
+ // NVIDIA moonshotai/kimi-k2.6
45607
+ "model-nvidia-glm-5.1",
45608
+ // NVIDIA z-ai/glm-5.1
45609
+ "model-nvidia-qwen3.5-397b"
45610
+ // NVIDIA qwen/qwen3.5-397b-a17b
45319
45611
  ] : [],
45320
45612
  // Web-session proxies: chat-grade, selectable via /model, fallbacks here.
45321
45613
  ...isKimiEnabled() ? ["model-kimi-proxy"] : [],
45322
45614
  ...isDeepSeekEnabled() ? ["model-deepseek-proxy"] : [],
45323
- ...hasHuggingFaceKey() ? [
45324
- "model-hf-qwen3-6-35b-a3b",
45325
- // Hugging Face Qwen/Qwen3.6-35B-A3B
45326
- "model-hf-glm-5-1-fp8",
45327
- // Hugging Face zai-org/GLM-5.1-FP8
45328
- "model-hf-deepseek-v4-flash"
45329
- // Hugging Face deepseek-ai/DeepSeek-V4-Flash
45330
- ] : [],
45331
45615
  ...hasEnvValue("OPENAI_API_KEY") ? [
45332
45616
  // OpenAI API model closest to the ChatGPT instant experience.
45333
45617
  "model-openai-chat-latest"
@@ -45344,10 +45628,10 @@ var init_providers = __esm({
45344
45628
  "model-deepseek-v4-flash": "May 2025",
45345
45629
  "model-opus-4.6": "May 2025",
45346
45630
  "model-kimi-k2.6": "April 2024",
45347
- "model-hf-qwen3-6-35b-a3b": "Unknown",
45348
- "model-hf-glm-5-1-fp8": "Unknown",
45349
- "model-hf-deepseek-v4-flash": "Unknown",
45350
- "model-hf-deepseek-v4-flash-nvfp4": "Unknown",
45631
+ "model-nvidia-minimax-m3": "Unknown",
45632
+ "model-nvidia-kimi-k2.6": "April 2024",
45633
+ "model-nvidia-glm-5.1": "Unknown",
45634
+ "model-nvidia-qwen3.5-397b": "Unknown",
45351
45635
  "model-deepseek-proxy": "July 2024",
45352
45636
  "model-kimi-proxy": "April 2024",
45353
45637
  "model-openai-chat-latest": "August 2025",
@@ -45368,10 +45652,10 @@ var init_providers = __esm({
45368
45652
  "model-deepseek-v4-flash": "DeepSeek V4 Flash",
45369
45653
  "model-opus-4.6": "Anthropic Claude Opus 4.6",
45370
45654
  "model-kimi-k2.6": "Moonshot Kimi K2.6",
45371
- "model-hf-qwen3-6-35b-a3b": "Qwen Qwen3.6 35B A3B",
45372
- "model-hf-glm-5-1-fp8": "Z.ai GLM 5.1 FP8",
45373
- "model-hf-deepseek-v4-flash": "DeepSeek V4 Flash",
45374
- "model-hf-deepseek-v4-flash-nvfp4": "NVIDIA DeepSeek V4 Flash NVFP4",
45655
+ "model-nvidia-minimax-m3": "NVIDIA - MiniMax M3",
45656
+ "model-nvidia-kimi-k2.6": "NVIDIA - Moonshot Kimi K2.6",
45657
+ "model-nvidia-glm-5.1": "NVIDIA - Z.ai GLM 5.1",
45658
+ "model-nvidia-qwen3.5-397b": "NVIDIA - Qwen3.5 397B A17B",
45375
45659
  "model-deepseek-proxy": "DeepSeek (sessao web logada / deepsproxy)",
45376
45660
  "model-kimi-proxy": "Kimi (sessao web logada / kimiproxy)",
45377
45661
  "model-openai-chat-latest": "OpenAI Chat Latest",
@@ -48403,8 +48687,8 @@ var init_background_process_tracker = __esm({
48403
48687
  /**
48404
48688
  * Normalize file path for comparison
48405
48689
  */
48406
- normalizePath(path5) {
48407
- let normalized = path5.trim().replace(/\/+/g, "/");
48690
+ normalizePath(path8) {
48691
+ let normalized = path8.trim().replace(/\/+/g, "/");
48408
48692
  if (normalized.startsWith("./")) {
48409
48693
  normalized = normalized.slice(2);
48410
48694
  }
@@ -48642,8 +48926,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
48642
48926
  return decodedFile;
48643
48927
  };
48644
48928
  }
48645
- function normalizeWindowsPath(path5) {
48646
- return path5.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
48929
+ function normalizeWindowsPath(path8) {
48930
+ return path8.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
48647
48931
  }
48648
48932
  var import_path;
48649
48933
  var init_module_node = __esm({
@@ -51532,9 +51816,9 @@ async function addSourceContext(frames) {
51532
51816
  LRU_FILE_CONTENTS_CACHE.reduce();
51533
51817
  return frames;
51534
51818
  }
51535
- function getContextLinesFromFile(path5, ranges, output) {
51819
+ function getContextLinesFromFile(path8, ranges, output) {
51536
51820
  return new Promise((resolve2) => {
51537
- const stream = (0, import_node_fs2.createReadStream)(path5);
51821
+ const stream = (0, import_node_fs5.createReadStream)(path8);
51538
51822
  const lineReaded = (0, import_node_readline2.createInterface)({
51539
51823
  input: stream
51540
51824
  });
@@ -51549,7 +51833,7 @@ function getContextLinesFromFile(path5, ranges, output) {
51549
51833
  let rangeStart = range[0];
51550
51834
  let rangeEnd = range[1];
51551
51835
  function onStreamError() {
51552
- LRU_FILE_CONTENTS_FS_READ_FAILED.set(path5, 1);
51836
+ LRU_FILE_CONTENTS_FS_READ_FAILED.set(path8, 1);
51553
51837
  lineReaded.close();
51554
51838
  lineReaded.removeAllListeners();
51555
51839
  destroyStreamAndResolve();
@@ -51610,8 +51894,8 @@ function clearLineContext(frame2) {
51610
51894
  delete frame2.context_line;
51611
51895
  delete frame2.post_context;
51612
51896
  }
51613
- function shouldSkipContextLinesForFile(path5) {
51614
- return path5.startsWith("node:") || path5.endsWith(".min.js") || path5.endsWith(".min.cjs") || path5.endsWith(".min.mjs") || path5.startsWith("data:");
51897
+ function shouldSkipContextLinesForFile(path8) {
51898
+ return path8.startsWith("node:") || path8.endsWith(".min.js") || path8.endsWith(".min.cjs") || path8.endsWith(".min.mjs") || path8.startsWith("data:");
51615
51899
  }
51616
51900
  function shouldSkipContextLinesForFrame(frame2) {
51617
51901
  if (void 0 !== frame2.lineno && frame2.lineno > MAX_CONTEXTLINES_LINENO) return true;
@@ -51682,12 +51966,12 @@ function snipLine(line, colno) {
51682
51966
  if (end < lineLength) newLine += "...";
51683
51967
  return newLine;
51684
51968
  }
51685
- var import_node_fs2, import_node_readline2, LRU_FILE_CONTENTS_CACHE, LRU_FILE_CONTENTS_FS_READ_FAILED, DEFAULT_LINES_OF_CONTEXT, MAX_CONTEXTLINES_COLNO, MAX_CONTEXTLINES_LINENO;
51969
+ var import_node_fs5, import_node_readline2, LRU_FILE_CONTENTS_CACHE, LRU_FILE_CONTENTS_FS_READ_FAILED, DEFAULT_LINES_OF_CONTEXT, MAX_CONTEXTLINES_COLNO, MAX_CONTEXTLINES_LINENO;
51686
51970
  var init_context_lines_node = __esm({
51687
51971
  "../node_modules/.pnpm/posthog-node@5.35.13_rxjs@7.8.2/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/context-lines.node.mjs"() {
51688
51972
  "use strict";
51689
51973
  init_dist8();
51690
- import_node_fs2 = require("node:fs");
51974
+ import_node_fs5 = require("node:fs");
51691
51975
  import_node_readline2 = require("node:readline");
51692
51976
  LRU_FILE_CONTENTS_CACHE = new error_tracking_exports.ReduceableCache(25);
51693
51977
  LRU_FILE_CONTENTS_FS_READ_FAILED = new error_tracking_exports.ReduceableCache(20);
@@ -51719,7 +52003,7 @@ var init_relative_path_node = __esm({
51719
52003
 
51720
52004
  // ../node_modules/.pnpm/posthog-node@5.35.13_rxjs@7.8.2/node_modules/posthog-node/dist/version.mjs
51721
52005
  var version2;
51722
- var init_version2 = __esm({
52006
+ var init_version3 = __esm({
51723
52007
  "../node_modules/.pnpm/posthog-node@5.35.13_rxjs@7.8.2/node_modules/posthog-node/dist/version.mjs"() {
51724
52008
  "use strict";
51725
52009
  version2 = "5.35.13";
@@ -52837,7 +53121,7 @@ var MINIMUM_POLLING_INTERVAL, THIRTY_SECONDS, MAX_CACHE_SIZE, WAITUNTIL_DEBOUNCE
52837
53121
  var init_client = __esm({
52838
53122
  "../node_modules/.pnpm/posthog-node@5.35.13_rxjs@7.8.2/node_modules/posthog-node/dist/client.mjs"() {
52839
53123
  "use strict";
52840
- init_version2();
53124
+ init_version3();
52841
53125
  init_dist8();
52842
53126
  init_types5();
52843
53127
  init_feature_flag_evaluations();
@@ -67021,8 +67305,8 @@ var init_logger2 = __esm({
67021
67305
  });
67022
67306
 
67023
67307
  // ../lib/ai/tools/file.ts
67024
- function isSpritPath(path5) {
67025
- return path5.split(/[\\/]/).some((segment) => segment.toLowerCase() === "sprit");
67308
+ function isSpritPath(path8) {
67309
+ return path8.split(/[\\/]/).some((segment) => segment.toLowerCase() === "sprit");
67026
67310
  }
67027
67311
  function getViewSandboxType(sandbox) {
67028
67312
  return isCentrifugoSandbox(sandbox) ? "centrifugo" : "e2b";
@@ -67053,7 +67337,7 @@ function captureFileViewImageUsage(args) {
67053
67337
  const {
67054
67338
  context: context2,
67055
67339
  sandbox,
67056
- path: path5,
67340
+ path: path8,
67057
67341
  outcome,
67058
67342
  durationMs,
67059
67343
  mediaType,
@@ -67071,7 +67355,7 @@ function captureFileViewImageUsage(args) {
67071
67355
  model: getActiveModelName(context2),
67072
67356
  configured_model: context2.modelName,
67073
67357
  sandbox_type: getViewSandboxType(sandbox),
67074
- file_extension: getFileExtension(path5),
67358
+ file_extension: getFileExtension(path8),
67075
67359
  outcome,
67076
67360
  success: outcome === "success",
67077
67361
  duration_ms: durationMs,
@@ -67145,22 +67429,22 @@ async function runSandboxCommand(sandbox, command, envVars, timeoutMs = 6e4) {
67145
67429
  function isWindowsSandbox(sandbox) {
67146
67430
  return isCentrifugoSandbox(sandbox) && sandbox.isWindows();
67147
67431
  }
67148
- function getWindowsNativePath(path5) {
67149
- if (/^[A-Za-z]:[\\/]/.test(path5)) return path5;
67150
- if (path5.startsWith("/tmp/")) {
67151
- return `C:\\temp${path5.slice(4).replace(/\//g, "\\")}`;
67432
+ function getWindowsNativePath(path8) {
67433
+ if (/^[A-Za-z]:[\\/]/.test(path8)) return path8;
67434
+ if (path8.startsWith("/tmp/")) {
67435
+ return `C:\\temp${path8.slice(4).replace(/\//g, "\\")}`;
67152
67436
  }
67153
- return path5.replace(/\//g, "\\");
67437
+ return path8.replace(/\//g, "\\");
67154
67438
  }
67155
- function getPythonPathForSandbox(sandbox, path5) {
67156
- return isWindowsSandbox(sandbox) ? getWindowsNativePath(path5) : path5;
67439
+ function getPythonPathForSandbox(sandbox, path8) {
67440
+ return isWindowsSandbox(sandbox) ? getWindowsNativePath(path8) : path8;
67157
67441
  }
67158
- function toWindowsBashPath(path5) {
67159
- const drive = path5.match(/^([A-Za-z]):[\\/](.*)$/);
67442
+ function toWindowsBashPath(path8) {
67443
+ const drive = path8.match(/^([A-Za-z]):[\\/](.*)$/);
67160
67444
  if (drive) {
67161
67445
  return `/${drive[1].toLowerCase()}/${drive[2].replace(/\\/g, "/")}`;
67162
67446
  }
67163
- return path5.replace(/\\/g, "/");
67447
+ return path8.replace(/\\/g, "/");
67164
67448
  }
67165
67449
  async function detectSandboxShell(sandbox) {
67166
67450
  if (!isWindowsSandbox(sandbox)) return "bash";
@@ -67199,8 +67483,8 @@ PY`;
67199
67483
  }
67200
67484
  }
67201
67485
  }
67202
- async function getSandboxFileState(sandbox, path5) {
67203
- const pythonPath = getPythonPathForSandbox(sandbox, path5);
67486
+ async function getSandboxFileState(sandbox, path8) {
67487
+ const pythonPath = getPythonPathForSandbox(sandbox, path8);
67204
67488
  const result = await runPythonScript(
67205
67489
  sandbox,
67206
67490
  FILE_STATE_SCRIPT,
@@ -67217,23 +67501,23 @@ async function getSandboxFileState(sandbox, path5) {
67217
67501
  if (result.exitCode !== 0) {
67218
67502
  return {
67219
67503
  kind: "unknown",
67220
- path: path5,
67504
+ path: path8,
67221
67505
  error: result.stderr || result.stdout || "file state command failed"
67222
67506
  };
67223
67507
  }
67224
67508
  try {
67225
67509
  const payload = JSON.parse(result.stdout.trim());
67226
67510
  if (payload.kind === "file" && typeof payload.sizeBytes === "number" && Number.isFinite(payload.sizeBytes)) {
67227
- return { ...payload, path: path5 };
67511
+ return { ...payload, path: path8 };
67228
67512
  }
67229
67513
  if (payload.kind === "missing" || payload.kind === "not_file") {
67230
- return { ...payload, path: path5 };
67514
+ return { ...payload, path: path8 };
67231
67515
  }
67232
67516
  } catch {
67233
67517
  }
67234
67518
  return {
67235
67519
  kind: "unknown",
67236
- path: path5,
67520
+ path: path8,
67237
67521
  error: result.stderr || result.stdout || "invalid file state response"
67238
67522
  };
67239
67523
  }
@@ -67265,8 +67549,8 @@ ${numberedContent}${truncatedNotice}${footerNotice}`;
67265
67549
  })
67266
67550
  };
67267
67551
  }
67268
- async function readSandboxTextFile(sandbox, path5, range) {
67269
- const pythonPath = getPythonPathForSandbox(sandbox, path5);
67552
+ async function readSandboxTextFile(sandbox, path8, range) {
67553
+ const pythonPath = getPythonPathForSandbox(sandbox, path8);
67270
67554
  const envVars = {
67271
67555
  HACKERAI_FILE_READ_PATH: pythonPath,
67272
67556
  HACKERAI_FILE_READ_RANGE_START: String(range?.[0] ?? 0),
@@ -67294,40 +67578,40 @@ async function readSandboxTextFile(sandbox, path5, range) {
67294
67578
  }
67295
67579
  return payload;
67296
67580
  }
67297
- async function readSandboxTextFileWithFallback(sandbox, path5, range) {
67581
+ async function readSandboxTextFileWithFallback(sandbox, path8, range) {
67298
67582
  try {
67299
- return await readSandboxTextFile(sandbox, path5, range);
67583
+ return await readSandboxTextFile(sandbox, path8, range);
67300
67584
  } catch (error51) {
67301
67585
  const errorMessage = error51 instanceof Error ? error51.message : String(error51);
67302
67586
  if (errorMessage.startsWith("Invalid ") || errorMessage.includes("File not found")) {
67303
67587
  throw error51;
67304
67588
  }
67305
- const state = await getSandboxFileState(sandbox, path5);
67589
+ const state = await getSandboxFileState(sandbox, path8);
67306
67590
  if (state.kind === "unknown") {
67307
67591
  throw new Error(
67308
- `Unable to determine file size for ${path5}; refusing to load the file into memory. ${state.error}`
67592
+ `Unable to determine file size for ${path8}; refusing to load the file into memory. ${state.error}`
67309
67593
  );
67310
67594
  }
67311
67595
  if (state.kind === "missing") {
67312
- throw new Error(`File not found or is not a regular file: ${path5}`);
67596
+ throw new Error(`File not found or is not a regular file: ${path8}`);
67313
67597
  }
67314
67598
  if (state.kind === "not_file") {
67315
- throw new Error(`File is not a regular file: ${path5}`);
67599
+ throw new Error(`File is not a regular file: ${path8}`);
67316
67600
  }
67317
67601
  if (state.sizeBytes > MAX_TEXT_FILE_READ_BYTES) {
67318
67602
  if (range) {
67319
67603
  throw new Error(
67320
- `Unable to perform a bounded range read for ${path5}, 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.`
67604
+ `Unable to perform a bounded range read for ${path8}, 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.`
67321
67605
  );
67322
67606
  }
67323
67607
  return {
67324
- path: path5,
67608
+ path: path8,
67325
67609
  sizeBytes: state.sizeBytes,
67326
67610
  totalLines: 0,
67327
67611
  tooLarge: true
67328
67612
  };
67329
67613
  }
67330
- const fileContent = await sandbox.files.read(path5, {
67614
+ const fileContent = await sandbox.files.read(path8, {
67331
67615
  user: "user"
67332
67616
  });
67333
67617
  const lines = fileContent.split("\n");
@@ -67356,7 +67640,7 @@ async function readSandboxTextFileWithFallback(sandbox, path5, range) {
67356
67640
  const startIndex = start - 1;
67357
67641
  const endIndex = end === -1 ? lines.length : end;
67358
67642
  return {
67359
- path: path5,
67643
+ path: path8,
67360
67644
  sizeBytes: Buffer.byteLength(fileContent),
67361
67645
  totalLines: lines.length,
67362
67646
  content: lines.slice(startIndex, endIndex).join("\n"),
@@ -67364,7 +67648,7 @@ async function readSandboxTextFileWithFallback(sandbox, path5, range) {
67364
67648
  };
67365
67649
  }
67366
67650
  return {
67367
- path: path5,
67651
+ path: path8,
67368
67652
  sizeBytes: Buffer.byteLength(fileContent),
67369
67653
  totalLines: lines.length,
67370
67654
  content: fileContent,
@@ -67372,7 +67656,7 @@ async function readSandboxTextFileWithFallback(sandbox, path5, range) {
67372
67656
  };
67373
67657
  }
67374
67658
  }
67375
- async function appendSandboxTextFile(sandbox, path5, text2) {
67659
+ async function appendSandboxTextFile(sandbox, path8, text2) {
67376
67660
  const tempPath = `/tmp/hackerai_append_${Date.now()}_${Math.random().toString(36).slice(2)}.tmp`;
67377
67661
  await sandbox.files.write(tempPath, text2, {
67378
67662
  user: "user"
@@ -67381,7 +67665,7 @@ async function appendSandboxTextFile(sandbox, path5, text2) {
67381
67665
  sandbox,
67382
67666
  APPEND_TEXT_FILE_SCRIPT,
67383
67667
  {
67384
- HACKERAI_FILE_APPEND_TARGET_PATH: getPythonPathForSandbox(sandbox, path5),
67668
+ HACKERAI_FILE_APPEND_TARGET_PATH: getPythonPathForSandbox(sandbox, path8),
67385
67669
  HACKERAI_FILE_APPEND_SOURCE_PATH: getPythonPathForSandbox(
67386
67670
  sandbox,
67387
67671
  tempPath
@@ -67393,13 +67677,13 @@ async function appendSandboxTextFile(sandbox, path5, text2) {
67393
67677
  throw new Error(result.stderr || result.stdout || "Failed to append file");
67394
67678
  }
67395
67679
  }
67396
- async function readSandboxFileForView(sandbox, path5, includeData) {
67680
+ async function readSandboxFileForView(sandbox, path8, includeData) {
67397
67681
  if (isCentrifugoSandbox(sandbox) && sandbox.isWindows()) {
67398
67682
  throw new Error(
67399
67683
  "The view action is not available for Windows local sandboxes yet. Use a Linux/E2B sandbox or inspect the image manually."
67400
67684
  );
67401
67685
  }
67402
- const sandboxPath = getSandboxViewPath(sandbox, path5);
67686
+ const sandboxPath = getSandboxViewPath(sandbox, path8);
67403
67687
  const viewEnvVars = {
67404
67688
  HACKERAI_FILE_VIEW_PATH: sandboxPath,
67405
67689
  HACKERAI_FILE_VIEW_INCLUDE_DATA: includeData ? "1" : "0",
@@ -67742,19 +68026,19 @@ try:
67742
68026
  except OSError:
67743
68027
  pass
67744
68028
  `;
67745
- getFilename = (path5) => path5.split("/").pop() || path5;
67746
- getFileExtension = (path5) => {
67747
- const filename = getFilename(path5);
68029
+ getFilename = (path8) => path8.split("/").pop() || path8;
68030
+ getFileExtension = (path8) => {
68031
+ const filename = getFilename(path8);
67748
68032
  const dotIndex = filename.lastIndexOf(".");
67749
68033
  if (dotIndex <= 0 || dotIndex === filename.length - 1) return void 0;
67750
68034
  return filename.slice(dotIndex + 1).toLowerCase();
67751
68035
  };
67752
- getSandboxViewPath = (sandbox, path5) => {
68036
+ getSandboxViewPath = (sandbox, path8) => {
67753
68037
  const maybeSandbox = sandbox;
67754
- if (isCentrifugoSandbox(maybeSandbox) && maybeSandbox.isWindows() && path5.startsWith("/tmp/")) {
67755
- return `C:\\temp${path5.slice(4).replace(/\//g, "\\")}`;
68038
+ if (isCentrifugoSandbox(maybeSandbox) && maybeSandbox.isWindows() && path8.startsWith("/tmp/")) {
68039
+ return `C:\\temp${path8.slice(4).replace(/\//g, "\\")}`;
67756
68040
  }
67757
- return path5;
68041
+ return path8;
67758
68042
  };
67759
68043
  stripTrailingWs = (line) => line.replace(/[ \t]+$/u, "");
67760
68044
  editSchema = external_exports.object({
@@ -67828,7 +68112,7 @@ ${instructionsDescription}`,
67828
68112
  "A list of edits to be sequentially applied to the file. Required for `edit` action."
67829
68113
  )
67830
68114
  }),
67831
- execute: async ({ action, path: path5, text: text2, range, edits }) => {
68115
+ execute: async ({ action, path: path8, text: text2, range, edits }) => {
67832
68116
  try {
67833
68117
  const { sandbox } = await sandboxManager.getSandbox();
67834
68118
  switch (action) {
@@ -67838,7 +68122,7 @@ ${instructionsDescription}`,
67838
68122
  captureFileViewImageUsage({
67839
68123
  context: context2,
67840
68124
  sandbox,
67841
- path: path5,
68125
+ path: path8,
67842
68126
  outcome: "unsupported_model",
67843
68127
  durationMs: Date.now() - viewStartedAt,
67844
68128
  failureReason: "unsupported_model"
@@ -67847,26 +68131,26 @@ ${instructionsDescription}`,
67847
68131
  }
67848
68132
  let viewPayload;
67849
68133
  try {
67850
- viewPayload = await readSandboxFileForView(sandbox, path5, false);
68134
+ viewPayload = await readSandboxFileForView(sandbox, path8, false);
67851
68135
  } catch (error51) {
67852
68136
  captureFileViewImageUsage({
67853
68137
  context: context2,
67854
68138
  sandbox,
67855
- path: path5,
68139
+ path: path8,
67856
68140
  outcome: "inspection_failed",
67857
68141
  durationMs: Date.now() - viewStartedAt,
67858
68142
  failureReason: classifyFileViewError(error51)
67859
68143
  });
67860
68144
  throw error51;
67861
68145
  }
67862
- const filename = getFilename(path5);
68146
+ const filename = getFilename(path8);
67863
68147
  let previewFiles = [];
67864
68148
  let previewUploadError;
67865
68149
  try {
67866
68150
  previewFiles = await uploadViewPreviewFiles({
67867
68151
  context: context2,
67868
68152
  sandbox,
67869
- sourcePath: path5,
68153
+ sourcePath: path8,
67870
68154
  payload: viewPayload
67871
68155
  });
67872
68156
  } catch (error51) {
@@ -67880,7 +68164,7 @@ ${instructionsDescription}`,
67880
68164
  user_id: context2.userID,
67881
68165
  sandbox_type: getViewSandboxType(sandbox),
67882
68166
  file_name: filename,
67883
- source_path: path5,
68167
+ source_path: path8,
67884
68168
  kind: viewPayload.kind,
67885
68169
  media_type: viewPayload.mediaType,
67886
68170
  size_bytes: viewPayload.sizeBytes,
@@ -67891,7 +68175,7 @@ ${instructionsDescription}`,
67891
68175
  captureFileViewImageUsage({
67892
68176
  context: context2,
67893
68177
  sandbox,
67894
- path: path5,
68178
+ path: path8,
67895
68179
  outcome: "success",
67896
68180
  durationMs: Date.now() - viewStartedAt,
67897
68181
  mediaType: viewPayload.mediaType,
@@ -67901,7 +68185,7 @@ ${instructionsDescription}`,
67901
68185
  return {
67902
68186
  action: "view",
67903
68187
  content: `Viewing image file: ${filename} (${viewPayload.mediaType}, ${viewPayload.sizeBytes} bytes).`,
67904
- path: path5,
68188
+ path: path8,
67905
68189
  filename,
67906
68190
  mediaType: viewPayload.mediaType,
67907
68191
  sizeBytes: viewPayload.sizeBytes,
@@ -67911,8 +68195,8 @@ ${instructionsDescription}`,
67911
68195
  };
67912
68196
  }
67913
68197
  case "read": {
67914
- const filename = path5.split("/").pop() || path5;
67915
- const spritChunked = isSpritPath(path5);
68198
+ const filename = path8.split("/").pop() || path8;
68199
+ const spritChunked = isSpritPath(path8);
67916
68200
  let effectiveRange = range;
67917
68201
  if (spritChunked) {
67918
68202
  const start = range && range[0] > 0 ? range[0] : 1;
@@ -67925,7 +68209,7 @@ ${instructionsDescription}`,
67925
68209
  }
67926
68210
  const readPayload = await readSandboxTextFileWithFallback(
67927
68211
  sandbox,
67928
- path5,
68212
+ path8,
67929
68213
  effectiveRange
67930
68214
  );
67931
68215
  if (readPayload.tooLarge) {
@@ -67962,46 +68246,46 @@ File is too large to read in full (${formatBytes(readPayload.sizeBytes)}, ${tota
67962
68246
  if (text2 === void 0) {
67963
68247
  return { error: "text is required for write action" };
67964
68248
  }
67965
- await sandbox.files.write(path5, text2, {
68249
+ await sandbox.files.write(path8, text2, {
67966
68250
  user: "user"
67967
68251
  });
67968
- return `File written: ${path5}`;
68252
+ return `File written: ${path8}`;
67969
68253
  }
67970
68254
  case "append": {
67971
68255
  if (text2 === void 0) {
67972
68256
  return { error: "text is required for append action" };
67973
68257
  }
67974
- const existingState = await getSandboxFileState(sandbox, path5);
68258
+ const existingState = await getSandboxFileState(sandbox, path8);
67975
68259
  if (existingState.kind === "unknown") {
67976
68260
  return {
67977
- error: `Cannot append safely because the existing file size could not be determined for ${path5}. ${existingState.error}`
68261
+ error: `Cannot append safely because the existing file size could not be determined for ${path8}. ${existingState.error}`
67978
68262
  };
67979
68263
  }
67980
68264
  if (existingState.kind === "not_file") {
67981
68265
  return {
67982
- error: `Cannot append to ${path5} because it is not a file.`
68266
+ error: `Cannot append to ${path8} because it is not a file.`
67983
68267
  };
67984
68268
  }
67985
68269
  if (existingState.kind === "file" && existingState.sizeBytes > MAX_TEXT_FILE_READ_BYTES) {
67986
- await appendSandboxTextFile(sandbox, path5, text2);
68270
+ await appendSandboxTextFile(sandbox, path8, text2);
67987
68271
  return {
67988
- content: `File appended: ${path5}
68272
+ content: `File appended: ${path8}
67989
68273
  Existing file is ${formatBytes(existingState.sizeBytes)}, so the full diff preview was skipped to avoid loading the entire file into memory.`
67990
68274
  };
67991
68275
  }
67992
68276
  let existingContent = "";
67993
68277
  try {
67994
- existingContent = await sandbox.files.read(path5, {
68278
+ existingContent = await sandbox.files.read(path8, {
67995
68279
  user: "user"
67996
68280
  });
67997
68281
  } catch {
67998
68282
  }
67999
68283
  const newContent = existingContent + text2;
68000
- await sandbox.files.write(path5, newContent, {
68284
+ await sandbox.files.write(path8, newContent, {
68001
68285
  user: "user"
68002
68286
  });
68003
68287
  return {
68004
- content: `File appended: ${path5}`,
68288
+ content: `File appended: ${path8}`,
68005
68289
  originalContent: truncateOutput({
68006
68290
  content: existingContent,
68007
68291
  mode: "read-file"
@@ -68016,31 +68300,31 @@ Existing file is ${formatBytes(existingState.sizeBytes)}, so the full diff previ
68016
68300
  if (!edits || edits.length === 0) {
68017
68301
  return { error: "edits array is required for edit action" };
68018
68302
  }
68019
- const existingState = await getSandboxFileState(sandbox, path5);
68303
+ const existingState = await getSandboxFileState(sandbox, path8);
68020
68304
  if (existingState.kind === "unknown") {
68021
68305
  return {
68022
- error: `Cannot edit ${path5} safely because the file size could not be determined. ${existingState.error}`
68306
+ error: `Cannot edit ${path8} safely because the file size could not be determined. ${existingState.error}`
68023
68307
  };
68024
68308
  }
68025
68309
  if (existingState.kind === "missing") {
68026
68310
  return {
68027
- error: `Cannot edit file ${path5} - file is empty or does not exist`
68311
+ error: `Cannot edit file ${path8} - file is empty or does not exist`
68028
68312
  };
68029
68313
  }
68030
68314
  if (existingState.kind === "not_file") {
68031
- return { error: `Cannot edit ${path5} because it is not a file.` };
68315
+ return { error: `Cannot edit ${path8} because it is not a file.` };
68032
68316
  }
68033
68317
  if (existingState.sizeBytes > MAX_TEXT_FILE_READ_BYTES) {
68034
68318
  return {
68035
- error: `File ${path5} 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.`
68319
+ error: `File ${path8} 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.`
68036
68320
  };
68037
68321
  }
68038
- const originalContent = await sandbox.files.read(path5, {
68322
+ const originalContent = await sandbox.files.read(path8, {
68039
68323
  user: "user"
68040
68324
  });
68041
68325
  if (!originalContent) {
68042
68326
  return {
68043
- error: `Cannot edit file ${path5} - file is empty or does not exist`
68327
+ error: `Cannot edit file ${path8} - file is empty or does not exist`
68044
68328
  };
68045
68329
  }
68046
68330
  const resolvedEdits = [];
@@ -68085,7 +68369,7 @@ ${hint}` : "")
68085
68369
  }
68086
68370
  }
68087
68371
  }
68088
- await sandbox.files.write(path5, content, {
68372
+ await sandbox.files.write(path8, content, {
68089
68373
  user: "user"
68090
68374
  });
68091
68375
  const lines = content.split("\n");
@@ -68361,20 +68645,20 @@ var init_utils4 = __esm({
68361
68645
 
68362
68646
  // src/local-sandbox.ts
68363
68647
  function inferShellFlag(shell2) {
68364
- const base = import_node_path2.default.basename(shell2).toLowerCase();
68648
+ const base = import_node_path5.default.basename(shell2).toLowerCase();
68365
68649
  if (base === "cmd" || base === "cmd.exe") return "/C";
68366
68650
  if (base === "powershell" || base === "powershell.exe" || base === "pwsh") {
68367
68651
  return "-Command";
68368
68652
  }
68369
68653
  return "-c";
68370
68654
  }
68371
- var import_node_child_process, import_node_fs3, import_node_path2, import_node_os2, import_node_url, import_meta, LocalSandbox;
68655
+ var import_node_child_process2, import_node_fs6, import_node_path5, import_node_os2, import_node_url, import_meta, LocalSandbox;
68372
68656
  var init_local_sandbox = __esm({
68373
68657
  "src/local-sandbox.ts"() {
68374
68658
  "use strict";
68375
- import_node_child_process = require("node:child_process");
68376
- import_node_fs3 = require("node:fs");
68377
- import_node_path2 = __toESM(require("node:path"));
68659
+ import_node_child_process2 = require("node:child_process");
68660
+ import_node_fs6 = require("node:fs");
68661
+ import_node_path5 = __toESM(require("node:path"));
68378
68662
  import_node_os2 = __toESM(require("node:os"));
68379
68663
  import_node_url = require("node:url");
68380
68664
  init_utils4();
@@ -68398,7 +68682,7 @@ var init_local_sandbox = __esm({
68398
68682
  this.shellFlag,
68399
68683
  command
68400
68684
  );
68401
- child = (0, import_node_child_process.spawn)(this.shellBin, spawnSpec.args, {
68685
+ child = (0, import_node_child_process2.spawn)(this.shellBin, spawnSpec.args, {
68402
68686
  cwd,
68403
68687
  env,
68404
68688
  detached: !!opts?.background,
@@ -68472,15 +68756,15 @@ var init_local_sandbox = __esm({
68472
68756
  this.files = {
68473
68757
  write: async (filePath, content) => {
68474
68758
  const resolved = this.resolvePath(filePath);
68475
- await import_node_fs3.promises.mkdir(import_node_path2.default.dirname(resolved), { recursive: true });
68759
+ await import_node_fs6.promises.mkdir(import_node_path5.default.dirname(resolved), { recursive: true });
68476
68760
  const data = typeof content === "string" ? content : content instanceof ArrayBuffer ? Buffer.from(content) : content;
68477
- await import_node_fs3.promises.writeFile(resolved, data);
68761
+ await import_node_fs6.promises.writeFile(resolved, data);
68478
68762
  },
68479
68763
  read: async (filePath) => {
68480
- return import_node_fs3.promises.readFile(this.resolvePath(filePath), "utf8");
68764
+ return import_node_fs6.promises.readFile(this.resolvePath(filePath), "utf8");
68481
68765
  },
68482
68766
  remove: async (filePath) => {
68483
- await import_node_fs3.promises.rm(this.resolvePath(filePath), {
68767
+ await import_node_fs6.promises.rm(this.resolvePath(filePath), {
68484
68768
  recursive: true,
68485
68769
  force: true
68486
68770
  });
@@ -68488,8 +68772,8 @@ var init_local_sandbox = __esm({
68488
68772
  list: async (dirPath = ".") => {
68489
68773
  const resolved = this.resolvePath(dirPath);
68490
68774
  try {
68491
- const entries = await import_node_fs3.promises.readdir(resolved, { withFileTypes: true });
68492
- return entries.filter((e) => e.isFile()).map((e) => ({ name: import_node_path2.default.join(resolved, e.name) }));
68775
+ const entries = await import_node_fs6.promises.readdir(resolved, { withFileTypes: true });
68776
+ return entries.filter((e) => e.isFile()).map((e) => ({ name: import_node_path5.default.join(resolved, e.name) }));
68493
68777
  } catch {
68494
68778
  return [];
68495
68779
  }
@@ -68504,11 +68788,11 @@ var init_local_sandbox = __esm({
68504
68788
  this.shellBin = shell2.shell;
68505
68789
  this.shellFlag = shell2.shellFlag;
68506
68790
  }
68507
- const base = opts?.workdir || process.env.CLI_WORKDIR || import_node_path2.default.join(process.cwd(), "SPRIT");
68508
- this.workdir = import_node_path2.default.resolve(base).replace(/\\/g, "/");
68791
+ const base = opts?.workdir || process.env.CLI_WORKDIR || import_node_path5.default.join(process.cwd(), "SPRIT");
68792
+ this.workdir = import_node_path5.default.resolve(base).replace(/\\/g, "/");
68509
68793
  }
68510
68794
  async init() {
68511
- await import_node_fs3.promises.mkdir(this.workdir, { recursive: true });
68795
+ await import_node_fs6.promises.mkdir(this.workdir, { recursive: true });
68512
68796
  await this.seedReconToolkit();
68513
68797
  }
68514
68798
  /**
@@ -68524,8 +68808,8 @@ var init_local_sandbox = __esm({
68524
68808
  const assetsDir = (0, import_node_url.fileURLToPath)(
68525
68809
  new URL("../assets/recon", import_meta.url)
68526
68810
  );
68527
- const destDir = import_node_path2.default.join(this.workdir, "recon");
68528
- await import_node_fs3.promises.mkdir(destDir, { recursive: true });
68811
+ const destDir = import_node_path5.default.join(this.workdir, "recon");
68812
+ await import_node_fs6.promises.mkdir(destDir, { recursive: true });
68529
68813
  const files = [
68530
68814
  ["recon_deep.py", true],
68531
68815
  ["console_recon.js", true],
@@ -68533,17 +68817,17 @@ var init_local_sandbox = __esm({
68533
68817
  ["scope.txt", false]
68534
68818
  ];
68535
68819
  for (const [name25, overwrite] of files) {
68536
- const dest = import_node_path2.default.join(destDir, name25);
68820
+ const dest = import_node_path5.default.join(destDir, name25);
68537
68821
  if (!overwrite) {
68538
68822
  try {
68539
- await import_node_fs3.promises.access(dest);
68823
+ await import_node_fs6.promises.access(dest);
68540
68824
  continue;
68541
68825
  } catch {
68542
68826
  }
68543
68827
  }
68544
68828
  try {
68545
- const content = await import_node_fs3.promises.readFile(import_node_path2.default.join(assetsDir, name25));
68546
- await import_node_fs3.promises.writeFile(dest, content);
68829
+ const content = await import_node_fs6.promises.readFile(import_node_path5.default.join(assetsDir, name25));
68830
+ await import_node_fs6.promises.writeFile(dest, content);
68547
68831
  } catch {
68548
68832
  }
68549
68833
  }
@@ -68646,7 +68930,7 @@ EDITING SCRIPTS:
68646
68930
  const pid = child.pid;
68647
68931
  if (pid && import_node_os2.default.platform() === "win32") {
68648
68932
  try {
68649
- (0, import_node_child_process.spawn)("taskkill", ["/PID", String(pid), "/T", "/F"], {
68933
+ (0, import_node_child_process2.spawn)("taskkill", ["/PID", String(pid), "/T", "/F"], {
68650
68934
  windowsHide: true
68651
68935
  });
68652
68936
  return;
@@ -68659,15 +68943,15 @@ EDITING SCRIPTS:
68659
68943
  }
68660
68944
  }
68661
68945
  resolvePath(p) {
68662
- if (import_node_path2.default.isAbsolute(p)) return p;
68663
- return import_node_path2.default.join(this.workdir, p);
68946
+ if (import_node_path5.default.isAbsolute(p)) return p;
68947
+ return import_node_path5.default.join(this.workdir, p);
68664
68948
  }
68665
68949
  isBashLikeShell() {
68666
- const base = import_node_path2.default.basename(this.shellBin).toLowerCase();
68950
+ const base = import_node_path5.default.basename(this.shellBin).toLowerCase();
68667
68951
  return base === "bash" || base === "bash.exe" || base === "sh";
68668
68952
  }
68669
68953
  isCmdShell() {
68670
- const base = import_node_path2.default.basename(this.shellBin).toLowerCase();
68954
+ const base = import_node_path5.default.basename(this.shellBin).toLowerCase();
68671
68955
  return base === "cmd" || base === "cmd.exe";
68672
68956
  }
68673
68957
  getWindowsShellNotes() {
@@ -68871,7 +69155,7 @@ function formatToolCall(toolName, input) {
68871
69155
  return `${C2.cyan}executando${C2.reset} ${C2.bold}$ ${truncate3(cmd, 400)}${C2.reset}${bg}`;
68872
69156
  }
68873
69157
  case "file": {
68874
- const path5 = String(i.path ?? "");
69158
+ const path8 = String(i.path ?? "");
68875
69159
  const brief = i.brief ? `${C2.dim} - ${truncate3(String(i.brief))}${C2.reset}` : "";
68876
69160
  const map2 = {
68877
69161
  write: `${C2.green}criando arquivo${C2.reset}`,
@@ -68882,7 +69166,7 @@ function formatToolCall(toolName, input) {
68882
69166
  };
68883
69167
  const action = typeof i.action === "string" ? i.action : "";
68884
69168
  const label = map2[action] ?? (action ? `${C2.blue}arquivo (${action})${C2.reset}` : `${C2.blue}preparando operacao de arquivo${C2.reset}`);
68885
- const target = path5 ? ` ${C2.bold}${path5}${C2.reset}` : "";
69169
+ const target = path8 ? ` ${C2.bold}${path8}${C2.reset}` : "";
68886
69170
  return `${label}${target}${brief}`;
68887
69171
  }
68888
69172
  case "todo_write":
@@ -68958,7 +69242,7 @@ function killProxy(child) {
68958
69242
  started.delete(child);
68959
69243
  try {
68960
69244
  if (process.platform === "win32") {
68961
- (0, import_node_child_process2.spawnSync)("taskkill", ["/pid", String(child.pid), "/T", "/F"], {
69245
+ (0, import_node_child_process3.spawnSync)("taskkill", ["/pid", String(child.pid), "/T", "/F"], {
68962
69246
  stdio: "ignore"
68963
69247
  });
68964
69248
  } else {
@@ -68989,12 +69273,12 @@ async function ensureProxyReady(id, log2) {
68989
69273
  };
68990
69274
  }
68991
69275
  let freshSetup = false;
68992
- if (!(0, import_node_fs4.existsSync)(dir)) {
69276
+ if (!(0, import_node_fs7.existsSync)(dir)) {
68993
69277
  log2(`${def.label}: baixando o proxy (uma vez) em ${dir} \u2026`);
68994
69278
  const root = proxiesRoot();
68995
- (0, import_node_fs4.mkdirSync)(root, { recursive: true });
69279
+ (0, import_node_fs7.mkdirSync)(root, { recursive: true });
68996
69280
  const cloned = run("git", ["clone", def.repoUrl, dir], root);
68997
- if (!cloned.ok || !(0, import_node_fs4.existsSync)(dir)) {
69281
+ if (!cloned.ok || !(0, import_node_fs7.existsSync)(dir)) {
68998
69282
  return {
68999
69283
  ok: false,
69000
69284
  message: `${def.label}: falha ao clonar o proxy (git).`
@@ -69002,7 +69286,7 @@ async function ensureProxyReady(id, log2) {
69002
69286
  }
69003
69287
  freshSetup = true;
69004
69288
  }
69005
- if (!(0, import_node_fs4.existsSync)(import_node_path3.default.join(dir, "node_modules"))) {
69289
+ if (!(0, import_node_fs7.existsSync)(import_node_path6.default.join(dir, "node_modules"))) {
69006
69290
  log2(`${def.label}: instalando depend\xEAncias (pode demorar) \u2026`);
69007
69291
  if (!run("npm", ["install"], dir).ok) {
69008
69292
  return { ok: false, message: `${def.label}: 'npm install' falhou.` };
@@ -69020,11 +69304,11 @@ async function ensureProxyReady(id, log2) {
69020
69304
  }
69021
69305
  }
69022
69306
  log2(`${def.label}: iniciando o proxy\u2026`);
69023
- const child = (0, import_node_child_process2.spawn)(asShellCommand("npm", ["start"]), {
69307
+ const child = (0, import_node_child_process3.spawn)(asShellCommand("npm", ["start"]), {
69024
69308
  cwd: dir,
69025
69309
  shell: true,
69026
69310
  stdio: ["ignore", "ignore", "ignore"],
69027
- env: childEnv()
69311
+ env: { ...childEnv(), PORT: String(def.port) }
69028
69312
  });
69029
69313
  started.add(child);
69030
69314
  child.on("exit", () => started.delete(child));
@@ -69047,14 +69331,14 @@ async function ensureProxyReady(id, log2) {
69047
69331
  message: `${def.label}: o proxy n\xE3o respondeu em 90s. Tente de novo, ou rode 'npm run login' em ${dir}.`
69048
69332
  };
69049
69333
  }
69050
- var import_node_os3, import_node_path3, import_node_fs4, import_node_child_process2, DEFS, PROXY_MODEL_KEYS, proxyIdForModelKey, proxiesRoot, dirFor, healthUrl, baseUrl, wait, started, exitHooksInstalled, quoteArg, asShellCommand, run, hasCommand;
69334
+ var import_node_os3, import_node_path6, import_node_fs7, import_node_child_process3, DEFS, PROXY_MODEL_KEYS, proxyIdForModelKey, proxiesRoot, dirFor, healthUrl, baseUrl, wait, started, exitHooksInstalled, quoteArg, asShellCommand, run, hasCommand;
69051
69335
  var init_proxy_manager2 = __esm({
69052
69336
  "src/proxy-manager.ts"() {
69053
69337
  "use strict";
69054
69338
  import_node_os3 = __toESM(require("node:os"));
69055
- import_node_path3 = __toESM(require("node:path"));
69056
- import_node_fs4 = require("node:fs");
69057
- import_node_child_process2 = require("node:child_process");
69339
+ import_node_path6 = __toESM(require("node:path"));
69340
+ import_node_fs7 = require("node:fs");
69341
+ import_node_child_process3 = require("node:child_process");
69058
69342
  DEFS = {
69059
69343
  deepseek: {
69060
69344
  id: "deepseek",
@@ -69086,11 +69370,11 @@ var init_proxy_manager2 = __esm({
69086
69370
  if (key === PROXY_MODEL_KEYS.kimi) return "kimi";
69087
69371
  return null;
69088
69372
  };
69089
- proxiesRoot = () => import_node_path3.default.join(
69090
- process.env.CLAWFAST_HOME?.trim() || import_node_path3.default.join(import_node_os3.default.homedir(), ".clawfast"),
69373
+ proxiesRoot = () => import_node_path6.default.join(
69374
+ process.env.CLAWFAST_HOME?.trim() || import_node_path6.default.join(import_node_os3.default.homedir(), ".clawfast"),
69091
69375
  "proxies"
69092
69376
  );
69093
- dirFor = (def) => process.env[def.dirEnv]?.trim() || import_node_path3.default.join(proxiesRoot(), def.folder);
69377
+ dirFor = (def) => process.env[def.dirEnv]?.trim() || import_node_path6.default.join(proxiesRoot(), def.folder);
69094
69378
  healthUrl = (def) => `http://localhost:${def.port}/health`;
69095
69379
  baseUrl = (def) => `http://localhost:${def.port}/v1`;
69096
69380
  wait = (ms) => new Promise((r) => setTimeout(r, ms));
@@ -69099,7 +69383,7 @@ var init_proxy_manager2 = __esm({
69099
69383
  quoteArg = (s) => /[\s"&|<>^()]/.test(s) ? `"${s.replace(/"/g, '\\"')}"` : s;
69100
69384
  asShellCommand = (cmd, args) => [cmd, ...args.map(quoteArg)].join(" ");
69101
69385
  run = (cmd, args, cwd) => {
69102
- const res = (0, import_node_child_process2.spawnSync)(asShellCommand(cmd, args), {
69386
+ const res = (0, import_node_child_process3.spawnSync)(asShellCommand(cmd, args), {
69103
69387
  cwd,
69104
69388
  shell: true,
69105
69389
  stdio: "inherit",
@@ -69109,7 +69393,7 @@ var init_proxy_manager2 = __esm({
69109
69393
  };
69110
69394
  hasCommand = (cmd) => {
69111
69395
  const probe = process.platform === "win32" ? "where" : "which";
69112
- return (0, import_node_child_process2.spawnSync)(asShellCommand(probe, [cmd]), {
69396
+ return (0, import_node_child_process3.spawnSync)(asShellCommand(probe, [cmd]), {
69113
69397
  stdio: "ignore",
69114
69398
  shell: true
69115
69399
  }).status === 0;
@@ -69254,7 +69538,7 @@ async function createAgent() {
69254
69538
  const sandboxManager = new LocalSandboxManager(sandbox);
69255
69539
  const writer = createConsoleWriter();
69256
69540
  const render = createRenderer();
69257
- const initialModelName = CLI_MODEL_CHAIN[0] ?? "agent-model";
69541
+ const initialModelName = CLI_MODEL_CHAIN[0] ?? "model-nvidia-minimax-m3";
69258
69542
  let currentModelName = initialModelName;
69259
69543
  let selectedModelKey = null;
69260
69544
  const context2 = {
@@ -69303,6 +69587,8 @@ async function createAgent() {
69303
69587
  system += pythonOnlyPolicy();
69304
69588
  system += deepReconPolicy(sandbox.getWorkdir());
69305
69589
  system += buildCliNotesSection();
69590
+ system += buildSkillsIndexSection();
69591
+ system += skillsScopePolicy();
69306
69592
  if (isWebSessionProxyModel(modelName)) {
69307
69593
  system += proxyToolProtocolPolicy();
69308
69594
  }
@@ -69340,25 +69626,18 @@ async function createAgent() {
69340
69626
  }
69341
69627
  function getUnavailableModelGroups() {
69342
69628
  const groups = [];
69343
- if (!hasEnvValue2("HUGGINGFACE_API_KEY") && !hasEnvValue2("HF_TOKEN")) {
69629
+ if (!hasEnvValue2("NVIDIA_API_KEY")) {
69344
69630
  groups.push({
69345
- provider: "Hugging Face",
69346
- reason: "faltando HUGGINGFACE_API_KEY ou HF_TOKEN em .env.local",
69631
+ provider: "NVIDIA build",
69632
+ reason: "faltando NVIDIA_API_KEY em .env.local (https://build.nvidia.com/)",
69347
69633
  models: [
69348
- "model-hf-qwen3-6-35b-a3b",
69349
- "model-hf-glm-5-1-fp8",
69350
- "model-hf-deepseek-v4-flash"
69634
+ "model-nvidia-minimax-m3",
69635
+ "model-nvidia-kimi-k2.6",
69636
+ "model-nvidia-glm-5.1",
69637
+ "model-nvidia-qwen3.5-397b"
69351
69638
  ].map((key) => ({ key, label: labelFor(key) }))
69352
69639
  });
69353
69640
  }
69354
- groups.push({
69355
- provider: "Hugging Face chat router",
69356
- reason: "indisponivel no endpoint /v1/chat/completions com a configuracao atual",
69357
- models: ["model-hf-deepseek-v4-flash-nvfp4"].map((key) => ({
69358
- key,
69359
- label: labelFor(key)
69360
- }))
69361
- });
69362
69641
  if (!hasEnvValue2("OPENAI_API_KEY")) {
69363
69642
  groups.push({
69364
69643
  provider: "OpenAI",
@@ -69512,11 +69791,20 @@ ${seen}`);
69512
69791
  }
69513
69792
  async function send(userInput, signal) {
69514
69793
  history.push({ role: "user", content: userInput });
69794
+ const matchedSkills = selectSkillsForInput(userInput);
69795
+ const turnSystem = matchedSkills.length ? system + renderSkillBodies(matchedSkills) : system;
69796
+ if (matchedSkills.length) {
69797
+ render.info(
69798
+ `\u25B8 skills ativadas: ${matchedSkills.map((s) => s.name).join(", ")}`
69799
+ );
69800
+ }
69515
69801
  let lastError = null;
69516
69802
  let autoContinues = 0;
69517
69803
  let bridgeSteps = 0;
69518
- const modelChain = getActiveModelChain();
69804
+ const modelChain = [...getActiveModelChain()];
69519
69805
  const usingFixedModel = selectedModelKey !== null;
69806
+ let rateLimitWaits = 0;
69807
+ let addedRateLimitFallbacks = false;
69520
69808
  for (let idx = 0; idx < modelChain.length; idx++) {
69521
69809
  const modelKey = modelChain[idx];
69522
69810
  currentModelName = modelKey;
@@ -69534,7 +69822,7 @@ ${seen}`);
69534
69822
  try {
69535
69823
  const result = streamText({
69536
69824
  model: myProvider.languageModel(modelKey),
69537
- system,
69825
+ system: turnSystem,
69538
69826
  messages: history,
69539
69827
  tools,
69540
69828
  stopWhen: stepCountIs(MAX_STEPS),
@@ -69652,6 +69940,17 @@ ${resultText}`
69652
69940
  }
69653
69941
  lastError = err ?? streamError;
69654
69942
  const msg = lastError instanceof Error ? lastError.message : String(lastError);
69943
+ const rateLimited = isRateLimitError(msg);
69944
+ if (rateLimited && !addedRateLimitFallbacks) {
69945
+ const extras = CLI_MODEL_CHAIN.filter((k) => !modelChain.includes(k));
69946
+ if (extras.length) {
69947
+ modelChain.push(...extras);
69948
+ addedRateLimitFallbacks = true;
69949
+ render.info(
69950
+ `\u25B8 ${labelFor(modelKey)} no limite (429) \u2014 tentando como conting\xEAncia: ${extras.map(labelFor).join(", ")}`
69951
+ );
69952
+ }
69953
+ }
69655
69954
  const hasNext = idx + 1 < modelChain.length;
69656
69955
  const hint = loginRequiredHint(msg);
69657
69956
  if (hint) {
@@ -69664,6 +69963,22 @@ ${resultText}`
69664
69963
  while (history.length && history[history.length - 1]?.role !== "user") {
69665
69964
  history.pop();
69666
69965
  }
69966
+ if (rateLimited && rateLimitWaits < MAX_RATE_LIMIT_WAITS) {
69967
+ const waitMs = Math.min(3e3 * 2 ** rateLimitWaits, 15e3);
69968
+ rateLimitWaits++;
69969
+ render.info(
69970
+ `\u25B8 rate limit \u2014 aguardando ${Math.round(waitMs / 1e3)}s antes da pr\xF3xima tentativa (Ctrl+C cancela)\u2026`
69971
+ );
69972
+ await sleep(waitMs, signal);
69973
+ if (signal?.aborted) {
69974
+ render.endTurn();
69975
+ return;
69976
+ }
69977
+ if (!hasNext) {
69978
+ idx = -1;
69979
+ continue;
69980
+ }
69981
+ }
69667
69982
  }
69668
69983
  }
69669
69984
  render.error(
@@ -69676,6 +69991,9 @@ ${resultText}`
69676
69991
  function getSystemPromptAudit() {
69677
69992
  return systemPromptAudit;
69678
69993
  }
69994
+ async function refreshSkills() {
69995
+ await rebuildSystemPrompt(currentModelName);
69996
+ }
69679
69997
  function isRunningCommand() {
69680
69998
  return sandbox.isProcessRunning();
69681
69999
  }
@@ -69691,19 +70009,20 @@ ${resultText}`
69691
70009
  sendStdin,
69692
70010
  getSystemPrompt,
69693
70011
  getSystemPromptAudit,
70012
+ refreshSkills,
69694
70013
  getModelChoices,
69695
70014
  getModelSelection,
69696
70015
  setModelSelection,
69697
70016
  close
69698
70017
  };
69699
70018
  }
69700
- var import_promises, import_node_path4, MAX_STEPS, MAX_OUTPUT_TOKENS, MAX_AUTO_CONTINUES, UNFINISHED_TAIL_RE, BENIGN_CLOSER_RE, TOOL_CALL_NUDGE, MAX_BRIDGE_STEPS, BRIDGE_RESULT_PREAMBLE, truncateBridgeSummary, isWebSessionProxyModel, proxyToolProtocolPolicy, SYSTEM_PROMPT_SOURCE, REQUIRED_SYSTEM_PROMPT_MARKERS, MODEL_LABELS, labelFor, loginRequiredHint, CLI_PYTHON_ONLY_POLICY, pythonOnlyPolicy, scriptFilePolicy, deepReconPolicy, hasEnvValue2, envFlagEnabled, CLI_PERSONALITIES, buildCliUserCustomization, buildCliNotesSection, cliGuardrailsConfig, maybeDumpSystemPrompt, auditSystemPrompt, assertFullSystemPrompt;
70019
+ var import_promises, import_node_path7, MAX_STEPS, MAX_OUTPUT_TOKENS, MAX_AUTO_CONTINUES, MAX_RATE_LIMIT_WAITS, isRateLimitError, sleep, UNFINISHED_TAIL_RE, BENIGN_CLOSER_RE, TOOL_CALL_NUDGE, MAX_BRIDGE_STEPS, BRIDGE_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;
69701
70020
  var init_agent = __esm({
69702
70021
  "src/agent.ts"() {
69703
70022
  "use strict";
69704
70023
  init_dist5();
69705
70024
  import_promises = require("node:fs/promises");
69706
- import_node_path4 = __toESM(require("node:path"));
70025
+ import_node_path7 = __toESM(require("node:path"));
69707
70026
  init_providers();
69708
70027
  init_system_prompt();
69709
70028
  init_notes();
@@ -69720,10 +70039,27 @@ var init_agent = __esm({
69720
70039
  init_local_sandbox_manager();
69721
70040
  init_console_writer();
69722
70041
  init_render();
70042
+ init_skills();
69723
70043
  init_proxy_manager2();
69724
70044
  MAX_STEPS = 100;
69725
70045
  MAX_OUTPUT_TOKENS = 16384;
69726
70046
  MAX_AUTO_CONTINUES = 3;
70047
+ MAX_RATE_LIMIT_WAITS = 4;
70048
+ isRateLimitError = (msg) => /\b429\b|too many requests|rate.?limit|resource_exhausted|quota|insufficient_quota/i.test(
70049
+ msg
70050
+ );
70051
+ sleep = (ms, signal) => new Promise((resolve2) => {
70052
+ if (signal?.aborted) return resolve2();
70053
+ const timer2 = setTimeout(resolve2, ms);
70054
+ signal?.addEventListener(
70055
+ "abort",
70056
+ () => {
70057
+ clearTimeout(timer2);
70058
+ resolve2();
70059
+ },
70060
+ { once: true }
70061
+ );
70062
+ });
69727
70063
  UNFINISHED_TAIL_RE = /(?::|\.\.\.|…)\s*$|\b(?:vou|irei|deixe-me|deixa eu|em seguida|pr[oó]ximo passo|agora (?:vou|irei|preciso)|let me|i(?:'|’)?ll|i will|i(?:'|’)?m going to|going to|next,? i)\b[^.!?\n]{0,120}[.!?]?\s*$/i;
69728
70064
  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;
69729
70065
  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.";
@@ -69764,18 +70100,14 @@ Regras:
69764
70100
  "DANGEROUS MODE"
69765
70101
  ];
69766
70102
  MODEL_LABELS = {
69767
- "agent-model": "OpenRouter - glm-4.5-air:free",
69768
- "model-glm-4.5-air": "OpenRouter - glm-4.5-air:free",
69769
- "model-qwen3-coder": "OpenRouter - qwen3-coder:free",
70103
+ "model-nvidia-minimax-m3": "NVIDIA - minimaxai/minimax-m3",
70104
+ "model-nvidia-kimi-k2.6": "NVIDIA - moonshotai/kimi-k2.6",
70105
+ "model-nvidia-glm-5.1": "NVIDIA - z-ai/glm-5.1",
70106
+ "model-nvidia-qwen3.5-397b": "NVIDIA - qwen/qwen3.5-397b-a17b",
69770
70107
  "model-openai-chat-latest": "OpenAI - chat-latest",
69771
- "model-hf-qwen3-6-35b-a3b": "Hugging Face - Qwen3.6 35B A3B",
69772
- "model-hf-glm-5-1-fp8": "Hugging Face - GLM 5.1 FP8",
69773
- "model-hf-deepseek-v4-flash": "Hugging Face - DeepSeek V4 Flash",
69774
- "model-hf-deepseek-v4-flash-nvfp4": "Hugging Face - DeepSeek V4 Flash NVFP4",
69775
70108
  "model-deepseek-proxy": "DeepSeek - sessao web logada (deepsproxy)",
69776
70109
  "model-kimi-proxy": "Kimi - sessao web logada (kimiproxy)",
69777
70110
  "fallback-openai-chat-latest": "OpenAI - chat-latest",
69778
- "fallback-agent-model": "NVIDIA - nemotron-3-ultra-550b",
69779
70111
  "model-nvidia-nemotron": "NVIDIA - nemotron-3-ultra-550b"
69780
70112
  };
69781
70113
  labelFor = (key) => MODEL_LABELS[key] ?? key;
@@ -69845,6 +70177,17 @@ Workflow:
69845
70177
 
69846
70178
  You MAY extend the toolkit (edit recon/recon_deep.py via the file tool) when a task needs a capability it lacks \u2014 keep it Python and keep the scope gate intact. recon/console_recon.js is an in-page payload string injected by Python Playwright (page.evaluate), NOT a Node script \u2014 never run it with \`node\`.
69847
70179
  </deep_recon_tooling>`;
70180
+ skillsScopePolicy = () => `
70181
+
70182
+ <skills_scope>
70183
+ ABSOLUTE RULE FOR THIS LOCAL CLI SESSION \u2014 applies to EVERY model and EVERY task:
70184
+
70185
+ Your skills are INTERNAL to you and live ONLY in ${skillsDir()}. The skills currently installed are listed in the <skills_disponiveis> block, and the full body of a matching skill is injected in <active_skills> when relevant.
70186
+
70187
+ - To list, describe, or "analyze" YOUR skills, use <skills_disponiveis> / <active_skills>. If you need the raw text of one of your skills, read ONLY the .md files inside ${skillsDir()}.
70188
+ - NEVER treat any other skills directory on this machine as yours. Folders such as ~/.agents/skills, ~/.claude/skills, ~/.augment/skills, ~/.cursor, and any other agent/tool skill folder belong to OTHER tools and are OUT OF SCOPE \u2014 ignore them completely and never read, list, summarize, or load them as your skills.
70189
+ - Do NOT scan the filesystem hunting for "skills". When asked about your skills, answer from your internal skills above, not from a disk search.
70190
+ </skills_scope>`;
69848
70191
  hasEnvValue2 = (name25) => Boolean(process.env[name25]?.trim());
69849
70192
  envFlagEnabled = (value) => {
69850
70193
  const normalized = value?.trim().toLowerCase();
@@ -69902,7 +70245,7 @@ ${section}` : "";
69902
70245
  return null;
69903
70246
  }
69904
70247
  await (0, import_promises.mkdir)(workdir, { recursive: true });
69905
- const outputPath = import_node_path4.default.join(workdir, "system-prompt.txt");
70248
+ const outputPath = import_node_path7.default.join(workdir, "system-prompt.txt");
69906
70249
  await (0, import_promises.writeFile)(outputPath, system, "utf8");
69907
70250
  return outputPath;
69908
70251
  };
@@ -69954,7 +70297,7 @@ function asciiTitle(text2) {
69954
70297
  }
69955
70298
  return out2;
69956
70299
  }
69957
- function buildBanner(_systemPromptChars) {
70300
+ function buildBanner(_systemPromptChars, version3 = "1") {
69958
70301
  const user = (import_node_os4.default.userInfo().username || "hacker").toLowerCase();
69959
70302
  const host = (import_node_os4.default.hostname() || "localhost").split(".")[0].toLowerCase();
69960
70303
  const art = asciiTitle("CLAWFAST");
@@ -69978,7 +70321,7 @@ function buildBanner(_systemPromptChars) {
69978
70321
  { text: shortCwd() },
69979
70322
  { text: "" }
69980
70323
  ];
69981
- const title = `clawfast v1`;
70324
+ const title = `clawfast v${version3}`;
69982
70325
  const topFill = "\u2500".repeat(Math.max(0, BOX_W - vlen(title) - 5));
69983
70326
  const top = `${C3.green}\u256D\u2500 ${C3.greenB}${C3.bold}${title}${C3.reset}${C3.green} ${topFill}\u256E${C3.reset}`;
69984
70327
  const bottom = `${C3.green}\u2570${"\u2500".repeat(BOX_W - 2)}\u256F${C3.reset}`;
@@ -70062,7 +70405,22 @@ async function main() {
70062
70405
  const agent = await createAgent2();
70063
70406
  const sys = agent.getSystemPrompt();
70064
70407
  stopBootSpinner();
70065
- process.stdout.write(buildBanner2(sys.length));
70408
+ const version3 = clawfastVersion();
70409
+ process.stdout.write(buildBanner2(sys.length, version3));
70410
+ const updateNotice = getUpdateNotice(version3);
70411
+ if (updateNotice) {
70412
+ process.stdout.write(
70413
+ `${ui2.C.yellow}\u2191 ${updateNotice}${ui2.C.reset}
70414
+ `
70415
+ );
70416
+ }
70417
+ refreshUpdateCacheInBackground(version3);
70418
+ if (consumePostUpdateLaunch(version3)) {
70419
+ process.stdout.write(
70420
+ `${ui2.C.greenB}Seja bem vindo ao submundo.${ui2.C.reset} ${ui2.C.dim}clawfast atualizado para ${version3} \u2014 rode ${ui2.C.reset}${ui2.C.cyan}/nov${ui2.C.reset}${ui2.C.dim} para ver as novidades.${ui2.C.reset}
70421
+ `
70422
+ );
70423
+ }
70066
70424
  const pasteInput = createPasteInput();
70067
70425
  const rl = import_node_readline3.default.createInterface({
70068
70426
  input: pasteInput.input,
@@ -70072,8 +70430,11 @@ async function main() {
70072
70430
  let closing = false;
70073
70431
  let commandQueue = Promise.resolve();
70074
70432
  let awaitingModelSelection = false;
70433
+ let skillCreator = null;
70075
70434
  const prompt = () => {
70076
- rl.setPrompt(awaitingModelSelection ? modelPrompt() : shellPrompt2());
70435
+ rl.setPrompt(
70436
+ skillCreator ? skillPrompt(skillCreator.phase) : awaitingModelSelection ? modelPrompt() : shellPrompt2()
70437
+ );
70077
70438
  rl.prompt();
70078
70439
  };
70079
70440
  let activeAbort = null;
@@ -70126,14 +70487,235 @@ ${ui2.C.dim}Ctrl+C de novo para fechar${ui2.C.reset}
70126
70487
  process.removeAllListeners("SIGINT");
70127
70488
  process.on("SIGINT", handleSigint);
70128
70489
  rl.on("SIGINT", handleSigint);
70490
+ const printSkillList = () => {
70491
+ const skills = listSkills();
70492
+ if (skills.length === 0) {
70493
+ process.stdout.write(
70494
+ `
70495
+ ${ui2.C.dim}nenhuma skill instalada. crie uma com /skillcreator${ui2.C.reset}
70496
+ `
70497
+ );
70498
+ return;
70499
+ }
70500
+ process.stdout.write(
70501
+ `
70502
+ ${ui2.C.cyan}skills instaladas${ui2.C.reset} ${ui2.C.dim}(${skillsDir()})${ui2.C.reset}
70503
+ `
70504
+ );
70505
+ for (const s of skills) {
70506
+ const flags = s.always ? ` ${ui2.C.yellow}[sempre]${ui2.C.reset}` : "";
70507
+ process.stdout.write(
70508
+ ` ${ui2.C.green}${s.name}${ui2.C.reset}${flags} ${ui2.C.dim}\u2014${ui2.C.reset} ${s.description}
70509
+ `
70510
+ );
70511
+ }
70512
+ process.stdout.write(
70513
+ `${ui2.C.dim}remover: /skill delete <nome>${ui2.C.reset}
70514
+ `
70515
+ );
70516
+ };
70517
+ const handleSkillCommand = (input) => {
70518
+ if (input === "/skillcreator") {
70519
+ skillCreator = {
70520
+ phase: "name",
70521
+ name: "",
70522
+ description: "",
70523
+ triggers: [],
70524
+ bodyLines: []
70525
+ };
70526
+ process.stdout.write(
70527
+ `
70528
+ ${ui2.C.greenB}criar skill${ui2.C.reset} ${ui2.C.dim}(/cancelar para abortar)${ui2.C.reset}
70529
+ ${ui2.C.dim}skills ficam disponiveis para TODOS os modelos; o conteudo completo so e carregado quando o pedido casa com a skill.${ui2.C.reset}
70530
+ ${ui2.C.cyan}nome da skill?${ui2.C.reset} ${ui2.C.dim}(ex: xss-recon)${ui2.C.reset}
70531
+ `
70532
+ );
70533
+ return;
70534
+ }
70535
+ printSkillList();
70536
+ };
70537
+ const handleSkillSubcommand = async (input) => {
70538
+ const rest = input.replace(/^\/skills?\s+/, "").trim();
70539
+ const parts = rest.split(/\s+/);
70540
+ const sub = (parts.shift() ?? "").toLowerCase();
70541
+ const arg = parts.join(" ").trim();
70542
+ if (sub === "list" || sub === "ls") {
70543
+ printSkillList();
70544
+ return;
70545
+ }
70546
+ if (sub === "delete" || sub === "rm" || sub === "remove") {
70547
+ if (!arg) {
70548
+ process.stdout.write(
70549
+ `${ui2.C.yellow}uso: /skill delete <nome>${ui2.C.reset}
70550
+ `
70551
+ );
70552
+ return;
70553
+ }
70554
+ if (deleteSkill(arg)) {
70555
+ await agent.refreshSkills();
70556
+ process.stdout.write(
70557
+ `${ui2.C.green}\u2713 skill '${slugify(arg)}' removida${ui2.C.reset}
70558
+ `
70559
+ );
70560
+ } else {
70561
+ process.stdout.write(
70562
+ `${ui2.C.yellow}skill '${arg}' nao encontrada${ui2.C.reset}
70563
+ `
70564
+ );
70565
+ }
70566
+ return;
70567
+ }
70568
+ process.stdout.write(
70569
+ `${ui2.C.yellow}subcomando desconhecido: ${sub}${ui2.C.reset}
70570
+ ${ui2.C.dim}use: /skillcreator | /skills | /skill delete <nome>${ui2.C.reset}
70571
+ `
70572
+ );
70573
+ };
70574
+ const printBodyTally = (sc) => {
70575
+ const text2 = sc.bodyLines.join("\n");
70576
+ const lines = text2 ? text2.split("\n").length : 0;
70577
+ process.stdout.write(
70578
+ `${ui2.C.dim} capturado: ${lines} linhas, ${text2.length} chars \u2014 continue colando, /fim para salvar, /desfazer para remover o ultimo, /cancelar para abortar${ui2.C.reset}
70579
+ `
70580
+ );
70581
+ };
70582
+ const handleSkillCreatorLine = async (line, input) => {
70583
+ const sc = skillCreator;
70584
+ if (!sc) return;
70585
+ if (input === "/cancelar" || input === "/cancel") {
70586
+ skillCreator = null;
70587
+ process.stdout.write(
70588
+ `
70589
+ ${ui2.C.dim}criacao de skill cancelada${ui2.C.reset}
70590
+ `
70591
+ );
70592
+ return;
70593
+ }
70594
+ switch (sc.phase) {
70595
+ case "name": {
70596
+ const slug = slugify(input);
70597
+ if (!slug) {
70598
+ process.stdout.write(
70599
+ `${ui2.C.yellow}nome invalido \u2014 tente de novo${ui2.C.reset}
70600
+ `
70601
+ );
70602
+ return;
70603
+ }
70604
+ sc.name = slug;
70605
+ if (listSkills().some((s) => s.name === slug)) {
70606
+ process.stdout.write(
70607
+ `${ui2.C.yellow}ja existe uma skill '${slug}' \u2014 sera sobrescrita${ui2.C.reset}
70608
+ `
70609
+ );
70610
+ }
70611
+ sc.phase = "desc";
70612
+ process.stdout.write(
70613
+ `${ui2.C.cyan}descricao curta (1 linha)?${ui2.C.reset}
70614
+ `
70615
+ );
70616
+ return;
70617
+ }
70618
+ case "desc": {
70619
+ sc.description = input;
70620
+ sc.phase = "triggers";
70621
+ process.stdout.write(
70622
+ `${ui2.C.cyan}palavras-gatilho?${ui2.C.reset} ${ui2.C.dim}(separadas por virgula; Enter usa o proprio nome)${ui2.C.reset}
70623
+ `
70624
+ );
70625
+ return;
70626
+ }
70627
+ case "triggers": {
70628
+ const looksLikeBody = /[\r\n]/.test(input) || input.length > 200;
70629
+ if (looksLikeBody) {
70630
+ sc.triggers = [];
70631
+ sc.phase = "body";
70632
+ sc.bodyLines.push(line.replace(/\r$/, ""));
70633
+ process.stdout.write(
70634
+ `${ui2.C.yellow}isso parece a skill, nao gatilhos \u2014 capturei como conteudo.${ui2.C.reset}
70635
+ `
70636
+ );
70637
+ printBodyTally(sc);
70638
+ return;
70639
+ }
70640
+ sc.triggers = input ? input.split(",").map((t) => t.trim()).filter(Boolean) : [];
70641
+ sc.phase = "body";
70642
+ process.stdout.write(
70643
+ `${ui2.C.cyan}cole ou escreva a skill agora${ui2.C.reset} ${ui2.C.dim}(qualquer tamanho). termine com uma linha contendo so /fim${ui2.C.reset}
70644
+ `
70645
+ );
70646
+ return;
70647
+ }
70648
+ case "body": {
70649
+ if (input === "/fim") {
70650
+ const body = sc.bodyLines.join("\n").trim();
70651
+ if (!body) {
70652
+ process.stdout.write(
70653
+ `${ui2.C.yellow}corpo vazio \u2014 cole algum conteudo ou /cancelar${ui2.C.reset}
70654
+ `
70655
+ );
70656
+ return;
70657
+ }
70658
+ const res = saveSkill({
70659
+ name: sc.name,
70660
+ description: sc.description,
70661
+ triggers: sc.triggers,
70662
+ body
70663
+ });
70664
+ skillCreator = null;
70665
+ await agent.refreshSkills();
70666
+ process.stdout.write(
70667
+ `
70668
+ ${ui2.C.green}\u2713 skill '${res.skill.name}' ${res.overwritten ? "atualizada" : "criada"}${ui2.C.reset} ${ui2.C.dim}(${res.file})${ui2.C.reset}
70669
+ ${ui2.C.dim}ja disponivel para todos os modelos nesta sessao.${ui2.C.reset}
70670
+ `
70671
+ );
70672
+ return;
70673
+ }
70674
+ if (input === "/desfazer" || input === "/undo") {
70675
+ if (sc.bodyLines.length === 0) {
70676
+ process.stdout.write(
70677
+ `${ui2.C.dim}nada para desfazer${ui2.C.reset}
70678
+ `
70679
+ );
70680
+ } else {
70681
+ sc.bodyLines.pop();
70682
+ process.stdout.write(
70683
+ `${ui2.C.yellow}ultimo trecho removido.${ui2.C.reset}
70684
+ `
70685
+ );
70686
+ printBodyTally(sc);
70687
+ }
70688
+ return;
70689
+ }
70690
+ sc.bodyLines.push(line.replace(/\r$/, ""));
70691
+ printBodyTally(sc);
70692
+ return;
70693
+ }
70694
+ }
70695
+ };
70129
70696
  const handleLine = async (line) => {
70130
70697
  if (closing) return;
70131
70698
  const input = line.trim();
70699
+ if (skillCreator) {
70700
+ await handleSkillCreatorLine(line, input);
70701
+ if (!closing) prompt();
70702
+ return;
70703
+ }
70132
70704
  if (input === "/exit" || input === "/quit") {
70133
70705
  closing = true;
70134
70706
  rl.close();
70135
70707
  return;
70136
70708
  }
70709
+ if (input === "/skillcreator" || input === "/skill" || input === "/skills") {
70710
+ handleSkillCommand(input);
70711
+ if (!closing) prompt();
70712
+ return;
70713
+ }
70714
+ if (input.startsWith("/skill ") || input.startsWith("/skills ")) {
70715
+ await handleSkillSubcommand(input);
70716
+ if (!closing) prompt();
70717
+ return;
70718
+ }
70137
70719
  if (awaitingModelSelection) {
70138
70720
  if (!input || input === "cancelar" || input === "cancel" || input === "sair" || input === "q") {
70139
70721
  awaitingModelSelection = false;
@@ -70197,6 +70779,13 @@ ${ui2.C.dim}selecao de modelo cancelada${ui2.C.reset}
70197
70779
  );
70198
70780
  process.stdout.write(sys2 + "\n");
70199
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}
70200
70789
  `);
70201
70790
  if (!closing) prompt();
70202
70791
  return;
@@ -70252,6 +70841,10 @@ ${ui2.C.dim}selecao de modelo cancelada${ui2.C.reset}
70252
70841
  function modelPrompt() {
70253
70842
  return "\n\x1B[96m\x1B[1mmodelo\x1B[0m\x1B[92m\x1B[1m>\x1B[0m ";
70254
70843
  }
70844
+ function skillPrompt(phase) {
70845
+ const label = phase === "name" ? "nome" : phase === "desc" ? "descricao" : phase === "triggers" ? "gatilhos" : "skill";
70846
+ return `\x1B[96m\x1B[1m${label}\x1B[0m\x1B[92m\x1B[1m>\x1B[0m `;
70847
+ }
70255
70848
  function formatModelSelection(result, options = {}) {
70256
70849
  const { C: C4 } = {
70257
70850
  C: {
@@ -70303,17 +70896,20 @@ var init_index = __esm({
70303
70896
  init_paste_input();
70304
70897
  init_boot_ui();
70305
70898
  init_config();
70899
+ init_skills();
70900
+ init_version();
70901
+ init_update();
70902
+ init_news();
70306
70903
  loadClawfastEnv();
70307
70904
  deepseekEnabled = /^(1|true|yes)$/i.test(process.env.DEEPSEEK_ENABLED?.trim() ?? "") || Boolean(process.env.DEEPSEEK_BASE_URL?.trim()) || Boolean(process.env.DEEPSEEK_API_KEY?.trim());
70308
70905
  configuredModelProviders = [
70309
70906
  deepseekEnabled ? "DeepSeek (proxy/web session)" : null,
70310
- process.env.OPENROUTER_API_KEY?.trim() ? "OpenRouter" : null,
70311
- process.env.HUGGINGFACE_API_KEY?.trim() || process.env.HF_TOKEN?.trim() ? "Hugging Face" : null,
70907
+ process.env.NVIDIA_API_KEY?.trim() ? "NVIDIA build" : null,
70312
70908
  process.env.OPENAI_API_KEY?.trim() ? "OpenAI" : null
70313
70909
  ].filter((name25) => Boolean(name25));
70314
70910
  if (configuredModelProviders.length === 0) {
70315
70911
  console.error(
70316
- `Nenhuma chave de modelo configurada. Defina OPENROUTER_API_KEY (ou HUGGINGFACE_API_KEY/HF_TOKEN/OPENAI_API_KEY) em ${clawfastEnvPath()} ou como vari\xE1vel de ambiente.`
70912
+ `Nenhuma chave de modelo configurada. Defina NVIDIA_API_KEY (ou OPENAI_API_KEY) em ${clawfastEnvPath()} ou como vari\xE1vel de ambiente.`
70317
70913
  );
70318
70914
  process.exit(1);
70319
70915
  }
@@ -70328,8 +70924,38 @@ var init_index = __esm({
70328
70924
  // boot.ts
70329
70925
  init_boot_ui();
70330
70926
  init_config();
70927
+ init_version();
70928
+ init_update();
70331
70929
  loadClawfastEnv();
70930
+ async function handleSubcommand() {
70931
+ const arg = process.argv[2];
70932
+ if (arg === "--version" || arg === "-v" || arg === "version") {
70933
+ process.stdout.write(`clawfast ${clawfastVersion()}
70934
+ `);
70935
+ process.exit(0);
70936
+ }
70937
+ if (arg === "update" || arg === "upgrade") {
70938
+ process.stdout.write(`\x1B[92mAtualizando o clawfast\u2026\x1B[0m
70939
+ `);
70940
+ const code = await runSelfUpdate();
70941
+ if (code === 0) {
70942
+ process.stdout.write(
70943
+ `
70944
+ \x1B[92m\x1B[1mSeja bem vindo ao submundo.\x1B[0m
70945
+ `
70946
+ );
70947
+ } else {
70948
+ process.stdout.write(
70949
+ `
70950
+ \x1B[91mFalha ao atualizar (codigo ${code}).\x1B[0m Tente manualmente: \x1B[1mnpm install -g clawfast@latest\x1B[0m
70951
+ `
70952
+ );
70953
+ }
70954
+ process.exit(code === 0 ? 0 : 1);
70955
+ }
70956
+ }
70332
70957
  async function boot() {
70958
+ await handleSubcommand();
70333
70959
  const hasKey = await ensureProviderKey();
70334
70960
  if (!hasKey) process.exit(1);
70335
70961
  startBootSpinner();