argus-pentest 0.1.1 → 0.1.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.
package/README.md CHANGED
@@ -24,6 +24,9 @@ argus --help # command-line interface
24
24
  argus doctor # environment and toolchain check
25
25
  ```
26
26
 
27
+ The installed command is `argus`, not `argus-pentest`. If an installed copy ever
28
+ fails to resolve an MCP SDK subpath, run `bun upgrade` and start `argus` again.
29
+
27
30
  From a checkout:
28
31
 
29
32
  ```bash
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "argus-pentest",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Terminal-first authorized security assessment harness: agentic pentesting, WSL/Kali tooling, live terminal, research reports.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
package/src/cli.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bun
2
- import { existsSync } from "node:fs";
2
+ import { existsSync, readFileSync } from "node:fs";
3
3
  import { join, resolve } from "node:path";
4
4
  import { defaultConfig, findConfigPath, loadConfig, saveScopeFile, scopeExample, saveConfig, ensureDataDirs, loadScopeFile } from "./core/config";
5
5
  import { ArgusEngine } from "./core/engine";
@@ -71,7 +71,16 @@ async function main(): Promise<void> {
71
71
  const { positionals, flags } = parseArgs(argv);
72
72
  const command = positionals[0];
73
73
  if (flags.get("version")) {
74
- process.stdout.write("argus 0.1.0\n");
74
+ let version = "0.0.0";
75
+ try {
76
+ const pkg = JSON.parse(readFileSync(join(import.meta.dir, "..", "package.json"), "utf8")) as {
77
+ version?: string;
78
+ };
79
+ version = pkg.version ?? version;
80
+ } catch {
81
+ // a packaged or relocated entrypoint keeps a safe default
82
+ }
83
+ process.stdout.write(`argus ${version}\n`);
75
84
  return;
76
85
  }
77
86
  if (!command || flags.get("help")) {
package/src/core/agent.ts CHANGED
@@ -2391,6 +2391,43 @@ export class GroundedAgent {
2391
2391
  }
2392
2392
 
2393
2393
  const observed = dedupeFindings([...known.values()]);
2394
+ // The loop can end on a step cap, a repeated-action guard, repeated tool
2395
+ // errors or invalid replies. Ask once more for a written answer from the
2396
+ // evidence already collected instead of returning a dead-end fallback.
2397
+ if (!callbacks.signal?.aborted && steps > 0) {
2398
+ callbacks.onStep?.(steps, "writing the final answer from collected evidence");
2399
+ try {
2400
+ const wrapMessages: ChatMessage[] = [
2401
+ ...messages,
2402
+ {
2403
+ role: "user",
2404
+ content:
2405
+ "WRAP-UP: stop using tools. Using only the evidence already collected in this conversation, answer the original goal now. Return exactly one JSON object {\"final\":{\"summary\":string,\"findingIds\":string[],\"nextSteps\":string[],\"gaps\":string[]}}. Name what was attempted, what broke, and the exact remaining blocker or gap. Do not invent results.",
2406
+ },
2407
+ ];
2408
+ const raw = await this.chat.complete(wrapMessages, { signal: callbacks.signal });
2409
+ const reply = parseAgentReply(raw);
2410
+ if (reply.kind === "final") {
2411
+ const verified = verifyAgentReport(reply.final, observed);
2412
+ const finalGaps = [...gaps, ...reply.final.gaps, "step limit reached; finished with a wrap-up answer from collected evidence"];
2413
+ return {
2414
+ summary: verified.summary,
2415
+ verified: verified.verified.length > 0 ? dedupeFindings(verified.verified) : observed,
2416
+ dropped: verified.dropped,
2417
+ nextSteps: reply.final.nextSteps,
2418
+ gaps: [...new Set(finalGaps)],
2419
+ steps,
2420
+ scans: [...new Set(scans)],
2421
+ observed: known.size,
2422
+ targets: [...this.allowedTargets],
2423
+ permissionSummary: permissionSummary(this.permissions),
2424
+ plan: this.plan,
2425
+ };
2426
+ }
2427
+ } catch {
2428
+ // a provider that cannot answer the wrap-up keeps the fallback below
2429
+ }
2430
+ }
2394
2431
  const lastReply = lastInvalidRaw.replace(/\s+/g, " ").trim();
2395
2432
  const stoppedAtBudget = Number.isFinite(this.maxSteps) && steps >= this.maxSteps && !callbacks.signal?.aborted;
2396
2433
  const fallback =
package/src/core/mcp.ts CHANGED
@@ -1,8 +1,10 @@
1
1
  import { Client } from "@modelcontextprotocol/sdk/client";
2
- import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio";
3
- import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp";
4
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp";
5
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio";
2
+ // Explicit .js subpaths: Bun 1.3 cannot resolve extensionless wildcard exports
3
+ // inside a globally installed package.
4
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
5
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
6
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
8
  import { z } from "zod";
7
9
  import { resolve } from "node:path";
8
10
  import type { ArgusConfig, JsonRpcToolInfo, McpServerConfig, ProfileId } from "./types";