codegate-ai 0.15.1 → 0.16.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/cli.js CHANGED
@@ -9,6 +9,7 @@ import { Command, Option } from "commander";
9
9
  import { DEFAULT_CONFIG, OUTPUT_FORMATS, PERSONAS, RUNTIME_MODES, SCAN_COLLECTION_MODES, SCAN_COLLECTION_KINDS, resolveEffectiveConfig, } from "./config.js";
10
10
  import { APP_NAME } from "./index.js";
11
11
  import { runSandboxCommand } from "./layer3-dynamic/sandbox.js";
12
+ import { runClaudeViaSdk } from "./layer3-dynamic/claude-sdk-provider.js";
12
13
  import { loadKnowledgeBase } from "./layer1-discovery/knowledge-base.js";
13
14
  import { createScanDiscoveryContext, discoverDeepScanResources, discoverDeepScanResourcesFromContext, discoverLocalTextAnalysisTargetsFromContext, runScanEngine, } from "./scan.js";
14
15
  import { registerSignalHandlers } from "./runtime/signal-handlers.js";
@@ -70,6 +71,26 @@ export function isDirectCliInvocation(importMetaUrl, argv1, deps = {}) {
70
71
  }
71
72
  }
72
73
  async function runMetaAgentCommandWithSandbox(context) {
74
+ // Claude runs through the Agent SDK so we get structured message
75
+ // iteration and reuse the user's `claude login` session without
76
+ // having to shell-escape prompts or parse stdout JSON envelopes.
77
+ // Codex and generic/OpenCode still spawn their CLIs — swap those
78
+ // once the Codex SDK auth story (see openai/codex#7144) is
79
+ // dependable enough to adopt.
80
+ if (context.agent.metaTool === "claude") {
81
+ const sdkResult = await runClaudeViaSdk({
82
+ prompt: context.command.prompt,
83
+ cwd: context.command.cwd,
84
+ readOnly: context.command.readOnly,
85
+ timeoutMs: context.command.timeoutMs,
86
+ });
87
+ return {
88
+ command: context.command,
89
+ code: sdkResult.code,
90
+ stdout: sdkResult.stdout,
91
+ stderr: sdkResult.stderr,
92
+ };
93
+ }
73
94
  const commandResult = await runSandboxCommand({
74
95
  command: context.command.command,
75
96
  args: context.command.args,
@@ -0,0 +1,21 @@
1
+ import type { SandboxCommandResult } from "./sandbox.js";
2
+ /**
3
+ * Run Claude's layer-3 analysis via @anthropic-ai/claude-agent-sdk instead
4
+ * of spawning the `claude` binary directly.
5
+ *
6
+ * Auth follows the SDK's default precedence: if ANTHROPIC_API_KEY is set it
7
+ * wins, otherwise the SDK delegates to the bundled Claude binary which
8
+ * reads the session written by `claude login` (~/.claude/settings.json).
9
+ * No explicit key plumbing here — intentional, the whole point of the
10
+ * swap is to reuse whatever auth the user already has.
11
+ *
12
+ * Contract matches runSandboxCommand so the caller in cli.ts can treat
13
+ * this as a drop-in for the claude CLI path.
14
+ */
15
+ export interface ClaudeSdkInput {
16
+ prompt: string;
17
+ cwd: string;
18
+ readOnly: boolean;
19
+ timeoutMs?: number;
20
+ }
21
+ export declare function runClaudeViaSdk(input: ClaudeSdkInput): Promise<SandboxCommandResult>;
@@ -0,0 +1,71 @@
1
+ import { query } from "@anthropic-ai/claude-agent-sdk";
2
+ import { DEFAULT_SANDBOX_TIMEOUT_MS } from "./sandbox.js";
3
+ const READ_ONLY_TOOLS = ["Read", "Glob", "Grep"];
4
+ export async function runClaudeViaSdk(input) {
5
+ const timeoutMs = input.timeoutMs ?? DEFAULT_SANDBOX_TIMEOUT_MS;
6
+ const abort = new AbortController();
7
+ let timedOut = false;
8
+ const timer = setTimeout(() => {
9
+ timedOut = true;
10
+ abort.abort();
11
+ }, timeoutMs);
12
+ // Mirror the CLI flag set from command-builder.ts. Non-readOnly = no
13
+ // tools, one turn, plain completion. Read-only = file-read tools only,
14
+ // auto-allowed so we don't deadlock on a permission prompt (no human in
15
+ // the loop), permissionMode 'plan' blocks any write even if a tool slips
16
+ // in via future SDK defaults.
17
+ const options = input.readOnly
18
+ ? {
19
+ cwd: input.cwd,
20
+ maxTurns: 10,
21
+ permissionMode: "plan",
22
+ tools: [...READ_ONLY_TOOLS],
23
+ allowedTools: [...READ_ONLY_TOOLS],
24
+ abortController: abort,
25
+ }
26
+ : {
27
+ cwd: input.cwd,
28
+ maxTurns: 1,
29
+ tools: [],
30
+ abortController: abort,
31
+ };
32
+ try {
33
+ const stream = query({ prompt: input.prompt, options });
34
+ let finalResult = null;
35
+ let errorMessage = null;
36
+ for await (const message of stream) {
37
+ if (message.type !== "result") {
38
+ continue;
39
+ }
40
+ if (message.subtype === "success") {
41
+ finalResult = message.result;
42
+ }
43
+ else {
44
+ // SDK surfaces a structured error subtype — capture the whole
45
+ // thing as stderr so the caller's existing diagnostic path
46
+ // (parseMetaAgentOutput returning null → evidence snippet) sees
47
+ // something useful.
48
+ errorMessage = JSON.stringify(message);
49
+ }
50
+ }
51
+ clearTimeout(timer);
52
+ if (timedOut) {
53
+ return { code: 124, stdout: "", stderr: "claude-agent-sdk: query timed out" };
54
+ }
55
+ if (finalResult !== null) {
56
+ return { code: 0, stdout: finalResult, stderr: "" };
57
+ }
58
+ return { code: 1, stdout: "", stderr: errorMessage ?? "claude-agent-sdk: no result message" };
59
+ }
60
+ catch (error) {
61
+ clearTimeout(timer);
62
+ if (timedOut) {
63
+ return { code: 124, stdout: "", stderr: "claude-agent-sdk: query timed out" };
64
+ }
65
+ return {
66
+ code: 1,
67
+ stdout: "",
68
+ stderr: `claude-agent-sdk: ${error instanceof Error ? error.message : String(error)}`,
69
+ };
70
+ }
71
+ }
@@ -12,5 +12,12 @@ export interface MetaAgentCommand {
12
12
  cwd: string;
13
13
  preview: string;
14
14
  timeoutMs?: number;
15
+ /** Original prompt before CLI shell-escaping — used by SDK-based
16
+ * runners (e.g. claude-sdk-provider) that call the model directly
17
+ * rather than spawning the binary. */
18
+ prompt: string;
19
+ /** Read-only flag preserved so SDK runners can set the equivalent
20
+ * permission mode without re-parsing argv. */
21
+ readOnly: boolean;
15
22
  }
16
23
  export declare function buildMetaAgentCommand(input: MetaAgentCommandInput): MetaAgentCommand;
@@ -51,6 +51,8 @@ export function buildMetaAgentCommand(input) {
51
51
  args,
52
52
  cwd: input.workingDirectory,
53
53
  preview: `${command} ${args.map(shellEscape).join(" ")}`,
54
+ prompt,
55
+ readOnly,
54
56
  };
55
57
  }
56
58
  if (input.tool === "codex") {
@@ -63,6 +65,8 @@ export function buildMetaAgentCommand(input) {
63
65
  args,
64
66
  cwd: input.workingDirectory,
65
67
  preview: `${command} ${args.map(shellEscape).join(" ")}`,
68
+ prompt,
69
+ readOnly,
66
70
  };
67
71
  }
68
72
  // Generic / OpenCode
@@ -77,5 +81,7 @@ export function buildMetaAgentCommand(input) {
77
81
  args: ["-lc", pipeCommand],
78
82
  cwd: input.workingDirectory,
79
83
  preview: `${command} ${shellEscape("-lc")} ${shellEscape(pipeCommand)}`,
84
+ prompt,
85
+ readOnly,
80
86
  };
81
87
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codegate-ai",
3
- "version": "0.15.1",
3
+ "version": "0.16.0",
4
4
  "description": "Pre-flight security scanner for AI coding tool configurations.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -63,6 +63,7 @@
63
63
  ]
64
64
  },
65
65
  "dependencies": {
66
+ "@anthropic-ai/claude-agent-sdk": "^0.2.118",
66
67
  "ajv": "^8.18.0",
67
68
  "commander": "^14.0.3",
68
69
  "dotenv": "^17.3.1",