@pentoshi/clai 0.6.0 → 0.7.2

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 (119) hide show
  1. package/README.md +18 -15
  2. package/dist/agent/context-manager.d.ts +27 -0
  3. package/dist/agent/context-manager.js +75 -0
  4. package/dist/agent/context-manager.js.map +1 -0
  5. package/dist/agent/runner.d.ts +21 -1
  6. package/dist/agent/runner.js +185 -74
  7. package/dist/agent/runner.js.map +1 -1
  8. package/dist/commands/doctor.js +21 -2
  9. package/dist/commands/doctor.js.map +1 -1
  10. package/dist/commands/update.js +11 -2
  11. package/dist/commands/update.js.map +1 -1
  12. package/dist/index.js +172 -5
  13. package/dist/index.js.map +1 -1
  14. package/dist/llm/anthropic.js +29 -38
  15. package/dist/llm/anthropic.js.map +1 -1
  16. package/dist/llm/gemini.d.ts +2 -0
  17. package/dist/llm/gemini.js +40 -43
  18. package/dist/llm/gemini.js.map +1 -1
  19. package/dist/llm/http.d.ts +23 -1
  20. package/dist/llm/http.js +197 -13
  21. package/dist/llm/http.js.map +1 -1
  22. package/dist/llm/nvidia.js +1 -0
  23. package/dist/llm/nvidia.js.map +1 -1
  24. package/dist/llm/ollama.js +18 -27
  25. package/dist/llm/ollama.js.map +1 -1
  26. package/dist/llm/router.d.ts +7 -0
  27. package/dist/llm/router.js +16 -23
  28. package/dist/llm/router.js.map +1 -1
  29. package/dist/modes/agent.d.ts +4 -2
  30. package/dist/modes/agent.js +2 -2
  31. package/dist/modes/agent.js.map +1 -1
  32. package/dist/modes/ask.js +3 -4
  33. package/dist/modes/ask.js.map +1 -1
  34. package/dist/os/pkgmgr.d.ts +7 -1
  35. package/dist/os/pkgmgr.js +97 -18
  36. package/dist/os/pkgmgr.js.map +1 -1
  37. package/dist/prompts/index.d.ts +7 -0
  38. package/dist/prompts/index.js +12 -4
  39. package/dist/prompts/index.js.map +1 -1
  40. package/dist/repl.d.ts +1 -0
  41. package/dist/repl.js +363 -45
  42. package/dist/repl.js.map +1 -1
  43. package/dist/safety/classifier.d.ts +7 -1
  44. package/dist/safety/classifier.js +260 -86
  45. package/dist/safety/classifier.js.map +1 -1
  46. package/dist/safety/patterns.d.ts +48 -1
  47. package/dist/safety/patterns.js +140 -7
  48. package/dist/safety/patterns.js.map +1 -1
  49. package/dist/store/config.d.ts +23 -3
  50. package/dist/store/config.js +31 -11
  51. package/dist/store/config.js.map +1 -1
  52. package/dist/store/history.d.ts +9 -0
  53. package/dist/store/history.js +58 -1
  54. package/dist/store/history.js.map +1 -1
  55. package/dist/store/keys.d.ts +2 -1
  56. package/dist/store/keys.js +7 -3
  57. package/dist/store/keys.js.map +1 -1
  58. package/dist/store/logs.d.ts +7 -0
  59. package/dist/store/logs.js +39 -1
  60. package/dist/store/logs.js.map +1 -1
  61. package/dist/store/project.d.ts +1 -0
  62. package/dist/store/project.js +34 -9
  63. package/dist/store/project.js.map +1 -1
  64. package/dist/store/scope.d.ts +32 -0
  65. package/dist/store/scope.js +161 -0
  66. package/dist/store/scope.js.map +1 -0
  67. package/dist/tools/fs.d.ts +6 -2
  68. package/dist/tools/fs.js +99 -87
  69. package/dist/tools/fs.js.map +1 -1
  70. package/dist/tools/http.d.ts +5 -3
  71. package/dist/tools/http.js +170 -31
  72. package/dist/tools/http.js.map +1 -1
  73. package/dist/tools/policies/output-policy.d.ts +13 -0
  74. package/dist/tools/policies/output-policy.js +56 -0
  75. package/dist/tools/policies/output-policy.js.map +1 -0
  76. package/dist/tools/reducers/ffuf.d.ts +6 -0
  77. package/dist/tools/reducers/ffuf.js +74 -0
  78. package/dist/tools/reducers/ffuf.js.map +1 -0
  79. package/dist/tools/reducers/generic.d.ts +2 -0
  80. package/dist/tools/reducers/generic.js +60 -0
  81. package/dist/tools/reducers/generic.js.map +1 -0
  82. package/dist/tools/reducers/gobuster.d.ts +2 -0
  83. package/dist/tools/reducers/gobuster.js +36 -0
  84. package/dist/tools/reducers/gobuster.js.map +1 -0
  85. package/dist/tools/reducers/httpx.d.ts +2 -0
  86. package/dist/tools/reducers/httpx.js +38 -0
  87. package/dist/tools/reducers/httpx.js.map +1 -0
  88. package/dist/tools/reducers/nmap.d.ts +7 -0
  89. package/dist/tools/reducers/nmap.js +82 -0
  90. package/dist/tools/reducers/nmap.js.map +1 -0
  91. package/dist/tools/reducers/nuclei.d.ts +2 -0
  92. package/dist/tools/reducers/nuclei.js +51 -0
  93. package/dist/tools/reducers/nuclei.js.map +1 -0
  94. package/dist/tools/reducers/sqlmap.d.ts +2 -0
  95. package/dist/tools/reducers/sqlmap.js +39 -0
  96. package/dist/tools/reducers/sqlmap.js.map +1 -0
  97. package/dist/tools/reducers/subdomains.d.ts +6 -0
  98. package/dist/tools/reducers/subdomains.js +31 -0
  99. package/dist/tools/reducers/subdomains.js.map +1 -0
  100. package/dist/tools/reducers/types.d.ts +14 -0
  101. package/dist/tools/reducers/types.js +2 -0
  102. package/dist/tools/reducers/types.js.map +1 -0
  103. package/dist/tools/registry.d.ts +1 -1
  104. package/dist/tools/registry.js +223 -79
  105. package/dist/tools/registry.js.map +1 -1
  106. package/dist/tools/shell.d.ts +45 -4
  107. package/dist/tools/shell.js +419 -88
  108. package/dist/tools/shell.js.map +1 -1
  109. package/dist/tools/validate.d.ts +37 -0
  110. package/dist/tools/validate.js +144 -0
  111. package/dist/tools/validate.js.map +1 -0
  112. package/dist/types.d.ts +7 -15
  113. package/dist/ui/keys.d.ts +21 -0
  114. package/dist/ui/keys.js +13 -0
  115. package/dist/ui/keys.js.map +1 -0
  116. package/dist/ui/output-pane.d.ts +31 -0
  117. package/dist/ui/output-pane.js +81 -0
  118. package/dist/ui/output-pane.js.map +1 -0
  119. package/package.json +1 -1
package/README.md CHANGED
@@ -69,11 +69,10 @@ clai -y "list the 10 largest files in my home directory"
69
69
  - **`/agent` mode** — Agentic. AI plans, then executes shell commands, edits files, installs missing tools, parses output, and continues until the goal is met.
70
70
  - **7 LLM providers** — Groq, Google Gemini, OpenRouter, OpenAI, Anthropic, NVIDIA NIM, and Ollama (local). All with streaming.
71
71
  - **10 built-in tools** — `shell.exec`, `fs.read`, `fs.write`, `fs.list`, `fs.search`, `pkg.install`, `net.scan`, `http.fetch`, `sysinfo`, `pentest.recon`.
72
- - **Smart safety gate** — Low-risk commands auto-execute; mutating, network, secret-touching, or shell-control commands require confirmation; destructive patterns are blocked.
73
- - **Bounded tool output** — Long scan output is streamed lightly while running, saved to artifacts when needed, and reduced before it reaches the model.
72
+ - **Smart safety gate** — Read-only commands auto-execute; mutating commands require confirmation; destructive patterns are blocked.
74
73
  - **Cross-platform** — macOS, Linux, and Windows. Detects OS-native package managers (brew, apt, dnf, pacman, winget, choco).
75
74
  - **Pentest-aware** — nmap, nikto, sqlmap, gobuster, ffuf, hydra, masscan, whois, dig, netcat, tshark.
76
- - **Manual update checks** — Run `/update` or `clai update` to check for new releases.
75
+ - **Auto-update** — Checks for new versions on startup; run `/update` or `clai update` to upgrade.
77
76
  - **Persistent history** — Session history with automatic key redaction in logs.
78
77
 
79
78
  ## Provider Setup
@@ -90,8 +89,6 @@ clai supports 7 LLM providers with free tiers:
90
89
  | NVIDIA NIM | `meta/llama-3.3-70b-instruct` | ✓ | `nvapi-` |
91
90
  | Ollama | `llama3.1:8b` | ✓ | (local URL) |
92
91
 
93
- `freeOnly` mode is enabled by default. Paid providers are excluded from fallback unless you explicitly opt in by disabling `freeOnly` in config or setting `CLAI_ALLOW_PAID=1`.
94
-
95
92
  ```sh
96
93
  # Store an API key
97
94
  clai set groq gsk_xxxxxxxxxxxxxxxx
@@ -145,41 +142,45 @@ export OLLAMA_HOST=http://localhost:11434
145
142
  | `/set <provider> [key]` | Store API key (masked input if key omitted) |
146
143
  | `/unset <provider>` | Remove stored key |
147
144
  | `/keys` | List configured providers, masked |
145
+ | `/variants [on|off|low|medium|high]` | Toggle model thinking/reasoning variants |
148
146
  | `/think` | Show hidden thinking from last response |
147
+ | `/output [last|id|list]`| Toggle full saved tool output |
149
148
  | `/clear` | Clear conversation context |
150
149
  | `/history` | Show past sessions |
151
150
  | `/save <name>` | Save current session |
152
151
  | `/cwd <path>` | Change working directory |
153
152
  | `/allow <tool>` | Whitelist a tool for the session |
154
- | `/output [last]` | Toggle full output from the last tool |
153
+ | `/scope add <targets>` | Add authorized pentest targets |
154
+ | `/fallback [on|off]` | Try other configured providers after a failure |
155
155
  | `/update` | Check for updates |
156
156
  | `/exit` | Quit |
157
157
  | `/help` | List commands |
158
158
  | `Ctrl+C` | Abort current response (second Ctrl+C exits) |
159
+ | `Ctrl+O` | Toggle full tool output (same keys on all OSes) |
159
160
 
160
161
  ## Built-in Tools (Agent Mode)
161
162
 
162
163
  | Tool | Description | Risk Level |
163
164
  |------------------|--------------------------------------------------------------------|------------|
164
- | `shell.exec` | Run shell commands with bounded capture and live progress | smart* |
165
+ | `shell.exec` | Run shell commands via execa (120s timeout, streams output) | smart* |
165
166
  | `fs.read` | Read files (sandboxed to approved roots) | safe |
166
167
  | `fs.write` | Write files (sandboxed) | confirm |
167
168
  | `fs.list` | List directory contents | safe |
168
169
  | `fs.search` | Search files with ripgrep (falls back to grep) | safe |
169
170
  | `pkg.install` | Install packages via detected OS package manager | confirm |
170
171
  | `net.scan` | Nmap wrapper for port scanning | confirm |
171
- | `http.fetch` | HTTP GET/HEAD with streaming response limits | safe* |
172
+ | `http.fetch` | HTTP GET/POST with response size limits | safe |
172
173
  | `sysinfo` | OS, architecture, shell, and working directory info | safe |
173
174
  | `pentest.recon` | Composite: whois + dig + nmap top-100 ports | confirm |
174
175
 
175
- > \* **smart** = only low-risk commands such as `ls`, `whoami`, and `uname` auto-execute. Network scanners, shell control syntax, secret paths, mutating commands, and non-GET HTTP methods require confirmation.
176
+ > \* **smart** = read-only commands (`curl`, `ls`, `whoami`, `gobuster`, `dirb`, etc.) auto-execute; mutating commands require confirmation.
176
177
 
177
178
  ## Safety Gate
178
179
 
179
180
  Every tool call passes through a 3-tier classifier:
180
181
 
181
- - **`safe`** — Auto-run: sandboxed read-only fs, sysinfo, GET/HEAD http.fetch, and low-risk shell info commands.
182
- - **`confirm`** — User prompt: mutating shell commands, fs.write, pkg.install, net.scan, network/private HTTP targets, scanner tools, and commands touching possible secrets.
182
+ - **`safe`** — Auto-run: read-only fs, sysinfo, http.fetch, read-only shell commands (`curl`, `ls`, `whoami`, `ifconfig`, `gobuster`, `dirb`, `ffuf`, `nikto`, etc.)
183
+ - **`confirm`** — User prompt: mutating shell commands, fs.write, pkg.install, net.scan
183
184
  - **`block`** — Refuse with explanation: `rm -rf /`, fork bombs, public IP scans without authorization, exfiltration patterns
184
185
 
185
186
  ### Pentest Authorization
@@ -190,15 +191,17 @@ Security tools require a one-time acknowledgment:
190
191
  clai authorize-pentest AGREE
191
192
  ```
192
193
 
193
- Public target scanning is blocked unless the target is private/local or the tool call carries explicit structured ownership confirmation.
194
+ Public targets do not require a stored scope, but keeping one helps clai remember what you are authorized to test. Add targets with:
194
195
 
195
- ### Tool Output
196
+ ```sh
197
+ clai scope add --targets example.com,10.0.0.0/24
198
+ ```
196
199
 
197
- During long tool runs, clai shows live output in dim text so you can see progress. After the AI summarizes the result, raw output is collapsed. Press `Ctrl+O` on macOS, Linux, or Windows to toggle full output for the last tool. In non-interactive terminals, use `/output last` or open the saved artifact path.
200
+ Inside the REPL, use `/scope add example.com`. If the agent proposes a public recon target that is not covered, clai shows a scope suggestion and still lets you continue through the normal confirmation flow.
198
201
 
199
202
  ## Updates
200
203
 
201
- clai does not call GitHub automatically by default. Check manually:
204
+ clai checks for updates automatically on startup (every 4 hours, non-blocking). You can also check manually:
202
205
 
203
206
  ```sh
204
207
  # CLI command
@@ -0,0 +1,27 @@
1
+ import type { ChatMessage } from "../types.js";
2
+ /**
3
+ * Crude per-char token estimator. Production-grade tokenization differs by
4
+ * provider, but for budgeting an order-of-magnitude heuristic ("chars / 4")
5
+ * is enough to decide when to compact. We deliberately err on the side of
6
+ * over-estimating — better to compact one turn too early than to lose state
7
+ * to a provider context-window error.
8
+ */
9
+ export declare function estimateTokens(text: string): number;
10
+ export declare function estimateMessagesTokens(messages: ChatMessage[]): number;
11
+ export interface CompactOptions {
12
+ /** Soft budget (tokens). When estimated tokens exceed this, compact. */
13
+ budgetTokens?: number | undefined;
14
+ /** Keep this many trailing messages (system + user/assistant pairs). */
15
+ keepRecent?: number | undefined;
16
+ }
17
+ /**
18
+ * Replace older messages with a single condensed "memory" message while
19
+ * preserving the system prompt and the most recent N messages.
20
+ *
21
+ * We do not call the LLM here — that's a future enhancement. The current
22
+ * compaction is mechanical: keep the system prompt; replace the prefix of
23
+ * older turns with a bullet list of the assistant's last lines and the
24
+ * tool calls that produced output. This is conservative and reversible
25
+ * (the artifact files still hold the raw outputs).
26
+ */
27
+ export declare function compactMessages(messages: ChatMessage[], options?: CompactOptions): ChatMessage[];
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Crude per-char token estimator. Production-grade tokenization differs by
3
+ * provider, but for budgeting an order-of-magnitude heuristic ("chars / 4")
4
+ * is enough to decide when to compact. We deliberately err on the side of
5
+ * over-estimating — better to compact one turn too early than to lose state
6
+ * to a provider context-window error.
7
+ */
8
+ export function estimateTokens(text) {
9
+ return Math.ceil(text.length / 4);
10
+ }
11
+ export function estimateMessagesTokens(messages) {
12
+ let sum = 0;
13
+ for (const message of messages) {
14
+ sum += estimateTokens(message.content) + 4; // role overhead
15
+ }
16
+ return sum;
17
+ }
18
+ const DEFAULT_BUDGET_TOKENS = 24_000;
19
+ const DEFAULT_KEEP_RECENT = 8;
20
+ /**
21
+ * Replace older messages with a single condensed "memory" message while
22
+ * preserving the system prompt and the most recent N messages.
23
+ *
24
+ * We do not call the LLM here — that's a future enhancement. The current
25
+ * compaction is mechanical: keep the system prompt; replace the prefix of
26
+ * older turns with a bullet list of the assistant's last lines and the
27
+ * tool calls that produced output. This is conservative and reversible
28
+ * (the artifact files still hold the raw outputs).
29
+ */
30
+ export function compactMessages(messages, options = {}) {
31
+ const budget = options.budgetTokens ?? DEFAULT_BUDGET_TOKENS;
32
+ const keepRecent = Math.max(2, options.keepRecent ?? DEFAULT_KEEP_RECENT);
33
+ if (messages.length <= keepRecent + 1)
34
+ return messages;
35
+ if (estimateMessagesTokens(messages) <= budget)
36
+ return messages;
37
+ // Always keep the system prompt (index 0 if it's a system message).
38
+ const head = [];
39
+ let start = 0;
40
+ if (messages[0]?.role === "system") {
41
+ head.push(messages[0]);
42
+ start = 1;
43
+ }
44
+ const tail = messages.slice(Math.max(start, messages.length - keepRecent));
45
+ const middle = messages.slice(start, messages.length - tail.length);
46
+ if (middle.length === 0)
47
+ return messages;
48
+ const bullets = [];
49
+ for (const msg of middle) {
50
+ if (msg.role === "user") {
51
+ bullets.push(`- user asked: ${oneLine(msg.content, 200)}`);
52
+ }
53
+ else if (msg.role === "assistant") {
54
+ const line = oneLine(msg.content, 200);
55
+ if (line)
56
+ bullets.push(`- assistant: ${line}`);
57
+ }
58
+ else if (msg.role === "tool") {
59
+ bullets.push(`- tool result: ${oneLine(msg.content, 200)}`);
60
+ }
61
+ }
62
+ const memo = {
63
+ role: "system",
64
+ content: `Earlier turns in this session, summarized to fit the context budget. Full artifacts (when produced) are saved on disk and can be expanded with /output.\n\n` +
65
+ bullets.join("\n"),
66
+ };
67
+ return [...head, memo, ...tail];
68
+ }
69
+ function oneLine(text, maxChars) {
70
+ const cleaned = text.replace(/\s+/g, " ").trim();
71
+ if (cleaned.length <= maxChars)
72
+ return cleaned;
73
+ return `${cleaned.slice(0, maxChars - 1)}…`;
74
+ }
75
+ //# sourceMappingURL=context-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-manager.js","sourceRoot":"","sources":["../../src/agent/context-manager.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,13 @@
1
1
  import type { ChatMessage, ProviderId, ToolCall, ToolResult } from "../types.js";
2
+ export interface SessionPolicy {
3
+ /** Tools the user authorized once during this REPL session. Not persisted. */
4
+ allow: Set<string>;
5
+ /** Mutable flag so the runner can flip pentest auth for this session only. */
6
+ pentestAuthorized: {
7
+ value: boolean;
8
+ };
9
+ }
10
+ export declare function createSessionPolicy(): SessionPolicy;
2
11
  export interface AgentRunOptions {
3
12
  provider?: ProviderId | undefined;
4
13
  model?: string | undefined;
@@ -8,6 +17,17 @@ export interface AgentRunOptions {
8
17
  signal?: AbortSignal | undefined;
9
18
  onToolStart?: ((call: ToolCall) => void) | undefined;
10
19
  onToolResult?: ((call: ToolCall, result: ToolResult) => void) | undefined;
20
+ session?: SessionPolicy | undefined;
21
+ }
22
+ export interface ParseToolCallOptions {
23
+ /**
24
+ * When true, only formats that are explicitly tool-call delimited are
25
+ * accepted: ```tool fenced JSON, <tool_call> XML, and the Kimi sentinel
26
+ * token format. Loose formats (any fenced block, heading-prefix, trailing
27
+ * JSON) are dropped — useful when models routinely emit JSON examples in
28
+ * prose. Default is `false` so existing free-tier models keep working.
29
+ */
30
+ strict?: boolean | undefined;
11
31
  }
12
- export declare function parseToolCall(text: string): ToolCall | undefined;
32
+ export declare function parseToolCall(text: string, options?: ParseToolCallOptions): ToolCall | undefined;
13
33
  export declare function runAgentLoop(prompt: string, options?: AgentRunOptions): Promise<string>;