@thenajs/tools 0.5.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
- export { ShellTool } from "./shell.tool.js";
1
+ export { ShellTool, shellTool } from "./shell.tool.js";
2
+ export type { ShellToolOptions } from "./shell.tool.js";
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACvD,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export { ShellTool } from "./shell.tool.js";
1
+ export { ShellTool, shellTool } from "./shell.tool.js";
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC"}
@@ -1,6 +1,55 @@
1
+ import type { ToolType } from "@thenajs/core";
2
+ export interface ShellToolOptions {
3
+ /** Teto de tempo do comando, em ms. Default: 30s. */
4
+ timeoutMs?: number;
5
+ /** Diretório de trabalho. Default: o do processo. */
6
+ cwd?: string;
7
+ /**
8
+ * Só executa comandos cujo **primeiro token** esteja nesta lista.
9
+ *
10
+ * É a única proteção real contra prompt injection nesta tool. Sem allowlist,
11
+ * qualquer coisa que o modelo escrever é executada com as permissões do
12
+ * processo.
13
+ *
14
+ * ```ts
15
+ * shellTool({ allow: ["ls", "cat", "grep", "git"] })
16
+ * ```
17
+ */
18
+ allow?: string[];
19
+ /** Teto de caracteres devolvidos ao modelo. Default: 8000. */
20
+ maxChars?: number;
21
+ }
22
+ /**
23
+ * Executa um comando shell.
24
+ *
25
+ * ## ⚠️ Leia antes de usar
26
+ *
27
+ * Esta tool dá ao modelo **execução arbitrária de comando** com as permissões
28
+ * do seu processo. Um agente que leia conteúdo de terceiro — um README, uma
29
+ * issue, um arquivo do repositório — pode ser induzido a executar o que
30
+ * estiver escrito lá. O framework não tem defesa contra prompt injection.
31
+ *
32
+ * Use `allow` sempre que o agente puder ver entrada não confiável:
33
+ *
34
+ * ```ts
35
+ * @Agent({ provider, prompt: "./a.agent.md", tools: [shellTool({ allow: ["git", "ls"] })] })
36
+ * ```
37
+ *
38
+ * Sem `allow`, restrinja o uso a ambiente controlado — sua máquina, um
39
+ * container descartável — e nunca a um serviço exposto.
40
+ */
41
+ export declare function shellTool(options?: ShellToolOptions): ToolType;
42
+ /**
43
+ * Versão sem configuração, para uso rápido em ambiente controlado.
44
+ *
45
+ * ⚠️ **Sem allowlist** — o modelo executa qualquer comando. Leia o aviso de
46
+ * `shellTool` antes de usar; para agente que vê entrada não confiável, prefira
47
+ * `shellTool({ allow: [...] })`.
48
+ */
1
49
  export declare class ShellTool {
2
- execute({ command }: {
50
+ private readonly impl;
51
+ execute(args: {
3
52
  command: string;
4
- }): Promise<string>;
53
+ }): Promise<string | import("@thenajs/core").ToolOutput>;
5
54
  }
6
55
  //# sourceMappingURL=shell.tool.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"shell.tool.d.ts","sourceRoot":"","sources":["../src/shell.tool.ts"],"names":[],"mappings":"AAOA,qBAKa,SAAS;IACd,OAAO,CAAC,EAAE,OAAO,EAAE,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE;CAI/C"}
1
+ {"version":3,"file":"shell.tool.d.ts","sourceRoot":"","sources":["../src/shell.tool.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAa9C,MAAM,WAAW,gBAAgB;IAC/B,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qDAAqD;IACrD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;;;;;;;OAUG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,SAAS,CAAC,OAAO,GAAE,gBAAqB,GAAG,QAAQ,CA4DlE;AAED;;;;;;GAMG;AACH,qBAKa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAe;IAEpC,OAAO,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE;CAGlC"}
@@ -9,17 +9,105 @@ import { promisify } from "node:util";
9
9
  import { Tool } from "@thenajs/core";
10
10
  import { z } from "zod";
11
11
  const run = promisify(exec);
12
+ const schema = z.object({ command: z.string() });
13
+ /** Teto de tempo padrão. Sem ele, um comando pendurado trava a run para sempre. */
14
+ const DEFAULT_TIMEOUT = 30_000;
15
+ /** Teto de saída devolvida ao modelo, para não entupir a janela de contexto. */
16
+ const MAX_CHARS = 8_000;
17
+ /**
18
+ * Executa um comando shell.
19
+ *
20
+ * ## ⚠️ Leia antes de usar
21
+ *
22
+ * Esta tool dá ao modelo **execução arbitrária de comando** com as permissões
23
+ * do seu processo. Um agente que leia conteúdo de terceiro — um README, uma
24
+ * issue, um arquivo do repositório — pode ser induzido a executar o que
25
+ * estiver escrito lá. O framework não tem defesa contra prompt injection.
26
+ *
27
+ * Use `allow` sempre que o agente puder ver entrada não confiável:
28
+ *
29
+ * ```ts
30
+ * @Agent({ provider, prompt: "./a.agent.md", tools: [shellTool({ allow: ["git", "ls"] })] })
31
+ * ```
32
+ *
33
+ * Sem `allow`, restrinja o uso a ambiente controlado — sua máquina, um
34
+ * container descartável — e nunca a um serviço exposto.
35
+ */
36
+ export function shellTool(options = {}) {
37
+ const timeout = options.timeoutMs ?? DEFAULT_TIMEOUT;
38
+ const maxChars = options.maxChars ?? MAX_CHARS;
39
+ const allow = options.allow?.map((c) => c.trim()).filter(Boolean);
40
+ return {
41
+ name: "shell",
42
+ description: allow
43
+ ? `Executa um comando shell. Permitidos: ${allow.join(", ")}.`
44
+ : "Executa um comando shell e retorna a saída.",
45
+ schema,
46
+ async execute({ command }) {
47
+ if (allow) {
48
+ // O primeiro token decide. Não tenta interpretar a linha inteira: um
49
+ // parser de shell parcial dá falsa sensação de segurança, e `;`, `&&`,
50
+ // `$(…)` e pipes contornariam qualquer coisa mais esperta que isto.
51
+ const programa = command.trim().split(/\s+/)[0] ?? "";
52
+ if (!allow.includes(programa)) {
53
+ return {
54
+ content: `Comando "${programa}" não permitido. ` +
55
+ `Disponíveis: ${allow.join(", ")}.`,
56
+ isError: true,
57
+ };
58
+ }
59
+ if (/[;&|`$><]/.test(command)) {
60
+ // Com allowlist ligada, encadeamento anularia a lista.
61
+ return {
62
+ content: "Encadeamento e redirecionamento não são permitidos " +
63
+ "(`;`, `&&`, `|`, `$(…)`, `>`). Rode um comando por vez.",
64
+ isError: true,
65
+ };
66
+ }
67
+ }
68
+ try {
69
+ const { stdout, stderr } = await run(command, {
70
+ timeout,
71
+ cwd: options.cwd,
72
+ maxBuffer: 10 * 1024 * 1024,
73
+ });
74
+ const saida = stdout || stderr || "(sem saída)";
75
+ return saida.length > maxChars
76
+ ? `${saida.slice(0, maxChars)}\n… [truncado]`
77
+ : saida;
78
+ }
79
+ catch (err) {
80
+ const e = err;
81
+ if (e.killed) {
82
+ return {
83
+ content: `O comando excedeu ${timeout}ms e foi encerrado.`,
84
+ isError: true,
85
+ };
86
+ }
87
+ // Erro vira observação: o modelo lê e tenta outra coisa.
88
+ return { content: e.stderr || e.message, isError: true };
89
+ }
90
+ },
91
+ };
92
+ }
93
+ /**
94
+ * Versão sem configuração, para uso rápido em ambiente controlado.
95
+ *
96
+ * ⚠️ **Sem allowlist** — o modelo executa qualquer comando. Leia o aviso de
97
+ * `shellTool` antes de usar; para agente que vê entrada não confiável, prefira
98
+ * `shellTool({ allow: [...] })`.
99
+ */
12
100
  let ShellTool = class ShellTool {
13
- async execute({ command }) {
14
- const { stdout, stderr } = await run(command);
15
- return stdout || stderr;
101
+ impl = shellTool();
102
+ execute(args) {
103
+ return this.impl.execute(args);
16
104
  }
17
105
  };
18
106
  ShellTool = __decorate([
19
107
  Tool({
20
108
  name: "shell",
21
109
  description: "Executa um comando shell e retorna a saída.",
22
- schema: z.object({ command: z.string() }),
110
+ schema,
23
111
  })
24
112
  ], ShellTool);
25
113
  export { ShellTool };
@@ -1 +1 @@
1
- {"version":3,"file":"shell.tool.js","sourceRoot":"","sources":["../src/shell.tool.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;AAOrB,IAAM,SAAS,GAAf,MAAM,SAAS;IACpB,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,EAAuB;QAC5C,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,CAAC;QAC9C,OAAO,MAAM,IAAI,MAAM,CAAC;IAC1B,CAAC;CACF,CAAA;AALY,SAAS;IALrB,IAAI,CAAC;QACJ,IAAI,EAAE,OAAO;QACb,WAAW,EAAE,6CAA6C;QAC1D,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;KAC1C,CAAC;GACW,SAAS,CAKrB"}
1
+ {"version":3,"file":"shell.tool.js","sourceRoot":"","sources":["../src/shell.tool.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thenajs/tools",
3
- "version": "0.5.0",
3
+ "version": "0.9.0",
4
4
  "description": "Tools prontas para agentes ThenaJS (ex.: ShellTool).",
5
5
  "license": "MIT",
6
6
  "author": "castroneto",
@@ -16,12 +16,22 @@
16
16
  "exports": {
17
17
  ".": "./dist/index.js"
18
18
  },
19
- "files": ["dist"],
19
+ "files": [
20
+ "dist"
21
+ ],
20
22
  "publishConfig": {
21
23
  "access": "public"
22
24
  },
25
+ "engines": {
26
+ "node": ">=20.19"
27
+ },
23
28
  "dependencies": {
24
- "@thenajs/core": "^0.5.0",
29
+ "@thenajs/core": "^0.9.0"
30
+ },
31
+ "peerDependencies": {
32
+ "zod": "^4.0.0"
33
+ },
34
+ "devDependencies": {
25
35
  "zod": "^4.0.0"
26
36
  }
27
37
  }