claude-mcp-bridge 0.1.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.
Files changed (70) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +312 -0
  3. package/dist/index.d.ts +3 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +256 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/tools/ping.d.ts +18 -0
  8. package/dist/tools/ping.d.ts.map +1 -0
  9. package/dist/tools/ping.js +78 -0
  10. package/dist/tools/ping.js.map +1 -0
  11. package/dist/tools/query.d.ts +27 -0
  12. package/dist/tools/query.d.ts.map +1 -0
  13. package/dist/tools/query.js +138 -0
  14. package/dist/tools/query.js.map +1 -0
  15. package/dist/tools/review.d.ts +31 -0
  16. package/dist/tools/review.d.ts.map +1 -0
  17. package/dist/tools/review.js +204 -0
  18. package/dist/tools/review.js.map +1 -0
  19. package/dist/tools/search.d.ts +23 -0
  20. package/dist/tools/search.d.ts.map +1 -0
  21. package/dist/tools/search.js +50 -0
  22. package/dist/tools/search.js.map +1 -0
  23. package/dist/tools/structured.d.ts +27 -0
  24. package/dist/tools/structured.d.ts.map +1 -0
  25. package/dist/tools/structured.js +88 -0
  26. package/dist/tools/structured.js.map +1 -0
  27. package/dist/utils/env.d.ts +3 -0
  28. package/dist/utils/env.d.ts.map +1 -0
  29. package/dist/utils/env.js +30 -0
  30. package/dist/utils/env.js.map +1 -0
  31. package/dist/utils/errors.d.ts +5 -0
  32. package/dist/utils/errors.d.ts.map +1 -0
  33. package/dist/utils/errors.js +58 -0
  34. package/dist/utils/errors.js.map +1 -0
  35. package/dist/utils/files.d.ts +22 -0
  36. package/dist/utils/files.d.ts.map +1 -0
  37. package/dist/utils/files.js +60 -0
  38. package/dist/utils/files.js.map +1 -0
  39. package/dist/utils/git.d.ts +14 -0
  40. package/dist/utils/git.d.ts.map +1 -0
  41. package/dist/utils/git.js +57 -0
  42. package/dist/utils/git.js.map +1 -0
  43. package/dist/utils/model.d.ts +7 -0
  44. package/dist/utils/model.d.ts.map +1 -0
  45. package/dist/utils/model.js +45 -0
  46. package/dist/utils/model.js.map +1 -0
  47. package/dist/utils/parse.d.ts +28 -0
  48. package/dist/utils/parse.d.ts.map +1 -0
  49. package/dist/utils/parse.js +141 -0
  50. package/dist/utils/parse.js.map +1 -0
  51. package/dist/utils/prompts.d.ts +19 -0
  52. package/dist/utils/prompts.d.ts.map +1 -0
  53. package/dist/utils/prompts.js +37 -0
  54. package/dist/utils/prompts.js.map +1 -0
  55. package/dist/utils/retry.d.ts +9 -0
  56. package/dist/utils/retry.d.ts.map +1 -0
  57. package/dist/utils/retry.js +29 -0
  58. package/dist/utils/retry.js.map +1 -0
  59. package/dist/utils/security.d.ts +18 -0
  60. package/dist/utils/security.d.ts.map +1 -0
  61. package/dist/utils/security.js +37 -0
  62. package/dist/utils/security.js.map +1 -0
  63. package/dist/utils/spawn.d.ts +30 -0
  64. package/dist/utils/spawn.d.ts.map +1 -0
  65. package/dist/utils/spawn.js +170 -0
  66. package/dist/utils/spawn.js.map +1 -0
  67. package/package.json +61 -0
  68. package/prompts/review-agentic.md +23 -0
  69. package/prompts/review-quick.md +25 -0
  70. package/prompts/search.md +13 -0
@@ -0,0 +1,88 @@
1
+ import { spawnClaude, buildClaudeArgs, HARD_TIMEOUT_CAP } from "../utils/spawn.js";
2
+ import { parseClaudeOutput, extractJson } from "../utils/parse.js";
3
+ import { checkErrorPatterns, throwIfClaudeError } from "../utils/errors.js";
4
+ import { readFiles, assemblePrompt, isImageFile } from "../utils/files.js";
5
+ import { verifyDirectory, MAX_FILES } from "../utils/security.js";
6
+ import { resolveModel, getFallbackModel, resolveMaxBudget } from "../utils/model.js";
7
+ export const MAX_SCHEMA_SIZE = 20_000;
8
+ const STDIN_THRESHOLD = 4000;
9
+ export async function executeStructured(input) {
10
+ const { prompt, files = [], timeout, sessionId, noSessionPersistence, maxBudgetUsd } = input;
11
+ const model = resolveModel("structured", input.model);
12
+ if (input.schema.length > MAX_SCHEMA_SIZE) {
13
+ throw new Error(`Schema too large: ${input.schema.length} bytes (max ${MAX_SCHEMA_SIZE})`);
14
+ }
15
+ let parsedSchema;
16
+ try {
17
+ parsedSchema = JSON.parse(input.schema);
18
+ }
19
+ catch {
20
+ throw new Error("Invalid schema: not valid JSON");
21
+ }
22
+ const imageFiles = files.filter((f) => isImageFile(f));
23
+ if (imageFiles.length > 0) {
24
+ throw new Error("Structured tool does not support image files (text only)");
25
+ }
26
+ if (files.length > MAX_FILES) {
27
+ throw new Error(`Too many files: ${files.length} (max ${MAX_FILES})`);
28
+ }
29
+ const cwd = input.workingDirectory
30
+ ? await verifyDirectory(input.workingDirectory)
31
+ : process.cwd();
32
+ const fileContents = files.length > 0 ? await readFiles(files, cwd) : [];
33
+ const fullPrompt = assemblePrompt(prompt, fileContents);
34
+ const useStdin = fullPrompt.length > STDIN_THRESHOLD || files.length > 0;
35
+ const effectiveTimeout = Math.min(timeout ?? 60_000, HARD_TIMEOUT_CAP);
36
+ const args = buildClaudeArgs({
37
+ model,
38
+ fallbackModel: getFallbackModel(),
39
+ maxBudgetUsd: resolveMaxBudget(maxBudgetUsd),
40
+ sessionId,
41
+ noSessionPersistence,
42
+ jsonSchema: JSON.stringify(parsedSchema),
43
+ prompt: useStdin ? undefined : fullPrompt,
44
+ });
45
+ const result = await spawnClaude({ args, cwd, stdin: useStdin ? fullPrompt : undefined, timeout: effectiveTimeout });
46
+ const filesIncluded = fileContents.filter((f) => !f.skipped).map((f) => f.path);
47
+ const filesSkipped = fileContents.filter((f) => f.skipped).map((f) => `${f.path}: ${f.skipped}`);
48
+ if (result.timedOut) {
49
+ return {
50
+ response: `Structured query timed out after ${effectiveTimeout / 1000}s.`,
51
+ valid: false,
52
+ model,
53
+ filesIncluded,
54
+ filesSkipped,
55
+ timedOut: true,
56
+ };
57
+ }
58
+ const parsed = parseClaudeOutput(result.stdout, result.stderr);
59
+ checkErrorPatterns(result.exitCode, result.stdout, result.stderr);
60
+ throwIfClaudeError(parsed.isError, parsed.response);
61
+ const extracted = extractJson(parsed.response);
62
+ if (!extracted) {
63
+ return {
64
+ response: parsed.response,
65
+ valid: false,
66
+ errors: "Could not extract JSON from response",
67
+ model,
68
+ sessionId: parsed.sessionId,
69
+ totalCostUsd: parsed.totalCostUsd,
70
+ usage: parsed.usage,
71
+ filesIncluded,
72
+ filesSkipped,
73
+ timedOut: false,
74
+ };
75
+ }
76
+ return {
77
+ response: extracted.raw,
78
+ valid: true,
79
+ model,
80
+ sessionId: parsed.sessionId,
81
+ totalCostUsd: parsed.totalCostUsd,
82
+ usage: parsed.usage,
83
+ filesIncluded,
84
+ filesSkipped,
85
+ timedOut: false,
86
+ };
87
+ }
88
+ //# sourceMappingURL=structured.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structured.js","sourceRoot":"","sources":["../../src/tools/structured.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ /** Build a minimal, safe environment for Claude CLI subprocesses. */
2
+ export declare function buildSubprocessEnv(): Record<string, string>;
3
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/utils/env.ts"],"names":[],"mappings":"AAgBA,qEAAqE;AACrE,wBAAgB,kBAAkB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAc3D"}
@@ -0,0 +1,30 @@
1
+ const ALLOWED_ENV_KEYS = [
2
+ "ANTHROPIC_API_KEY",
3
+ "CLAUDE_CONFIG_DIR",
4
+ "CLAUDE_CODE_USE_BEDROCK",
5
+ "CLAUDE_CODE_USE_VERTEX",
6
+ "AWS_REGION",
7
+ "AWS_DEFAULT_REGION",
8
+ "HOME",
9
+ "PATH",
10
+ "USER",
11
+ "SHELL",
12
+ "LANG",
13
+ "TERM",
14
+ "XDG_CONFIG_HOME",
15
+ ];
16
+ /** Build a minimal, safe environment for Claude CLI subprocesses. */
17
+ export function buildSubprocessEnv() {
18
+ const env = {
19
+ NO_COLOR: "1",
20
+ FORCE_COLOR: "0",
21
+ };
22
+ for (const key of ALLOWED_ENV_KEYS) {
23
+ const value = process.env[key];
24
+ if (value) {
25
+ env[key] = value;
26
+ }
27
+ }
28
+ return env;
29
+ }
30
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/utils/env.ts"],"names":[],"mappings":"AAAA,MAAM,gBAAgB,GAAG;IACvB,mBAAmB;IACnB,mBAAmB;IACnB,yBAAyB;IACzB,wBAAwB;IACxB,YAAY;IACZ,oBAAoB;IACpB,MAAM;IACN,MAAM;IACN,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,iBAAiB;CAClB,CAAC;AAEF,qEAAqE;AACrE,MAAM,UAAU,kBAAkB;IAChC,MAAM,GAAG,GAA2B;QAClC,QAAQ,EAAE,GAAG;QACb,WAAW,EAAE,GAAG;KACjB,CAAC;IAEF,KAAK,MAAM,GAAG,IAAI,gBAAgB,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,KAAK,EAAE,CAAC;YACV,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACnB,CAAC;IACH,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function isRetryableError(exitCode: number | null, stdout: string, stderr: string): boolean;
2
+ export declare function checkErrorPatterns(exitCode: number | null, stdout: string, stderr: string): void;
3
+ export declare function throwIfClaudeError(isError: boolean, message: string): void;
4
+ export declare function getErrorMessage(e: unknown): string;
5
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAIA,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAejG;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAsChG;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAI1E;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAGlD"}
@@ -0,0 +1,58 @@
1
+ function combinedText(stdout, stderr) {
2
+ return [stdout, stderr].filter(Boolean).join("\n").trim();
3
+ }
4
+ export function isRetryableError(exitCode, stdout, stderr) {
5
+ if (exitCode === 0)
6
+ return false;
7
+ const text = combinedText(stdout, stderr).toLowerCase();
8
+ if (!text)
9
+ return false;
10
+ return [
11
+ "credit balance is too low",
12
+ "rate limit",
13
+ "too many requests",
14
+ "quota",
15
+ "overloaded",
16
+ "529",
17
+ "429",
18
+ ].some((pattern) => text.includes(pattern));
19
+ }
20
+ export function checkErrorPatterns(exitCode, stdout, stderr) {
21
+ if (exitCode === 0)
22
+ return;
23
+ const text = combinedText(stdout, stderr);
24
+ if (!text)
25
+ return;
26
+ const lower = text.toLowerCase();
27
+ if (lower.includes("api key")
28
+ || lower.includes("authentication")
29
+ || lower.includes("unauthorized")
30
+ || lower.includes("forbidden")) {
31
+ throw new Error(`Claude CLI authentication error. Set ANTHROPIC_API_KEY for bare mode.\n\nDetails: ${text}`);
32
+ }
33
+ if (lower.includes("credit balance is too low")
34
+ || lower.includes("rate limit")
35
+ || lower.includes("too many requests")
36
+ || lower.includes("quota")
37
+ || lower.includes("overloaded")) {
38
+ throw new Error(`Claude API quota or rate-limit error.\n\nDetails: ${text}`);
39
+ }
40
+ if (lower.includes("connectionrefused")
41
+ || lower.includes("connection refused")
42
+ || lower.includes("unable to connect to api")
43
+ || lower.includes("network")
44
+ || lower.includes("econnrefused")) {
45
+ throw new Error(`Claude API connection error.\n\nDetails: ${text}`);
46
+ }
47
+ }
48
+ export function throwIfClaudeError(isError, message) {
49
+ if (isError) {
50
+ throw new Error(message);
51
+ }
52
+ }
53
+ export function getErrorMessage(e) {
54
+ if (e instanceof Error)
55
+ return e.message;
56
+ return String(e);
57
+ }
58
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA,SAAS,YAAY,CAAC,MAAc,EAAE,MAAc;IAClD,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,QAAuB,EAAE,MAAc,EAAE,MAAc;IACtF,IAAI,QAAQ,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAEjC,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;IACxD,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC;IAExB,OAAO;QACL,2BAA2B;QAC3B,YAAY;QACZ,mBAAmB;QACnB,OAAO;QACP,YAAY;QACZ,KAAK;QACL,KAAK;KACN,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,QAAuB,EAAE,MAAc,EAAE,MAAc;IACxF,IAAI,QAAQ,KAAK,CAAC;QAAE,OAAO;IAE3B,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,IAAI,CAAC,IAAI;QAAE,OAAO;IAElB,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAEjC,IACE,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC;WACtB,KAAK,CAAC,QAAQ,CAAC,gBAAgB,CAAC;WAChC,KAAK,CAAC,QAAQ,CAAC,cAAc,CAAC;WAC9B,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,EAC9B,CAAC;QACD,MAAM,IAAI,KAAK,CACb,qFAAqF,IAAI,EAAE,CAC5F,CAAC;IACJ,CAAC;IAED,IACE,KAAK,CAAC,QAAQ,CAAC,2BAA2B,CAAC;WACxC,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC;WAC5B,KAAK,CAAC,QAAQ,CAAC,mBAAmB,CAAC;WACnC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC;WACvB,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,EAC/B,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,qDAAqD,IAAI,EAAE,CAAC,CAAC;IAC/E,CAAC;IAED,IACE,KAAK,CAAC,QAAQ,CAAC,mBAAmB,CAAC;WAChC,KAAK,CAAC,QAAQ,CAAC,oBAAoB,CAAC;WACpC,KAAK,CAAC,QAAQ,CAAC,0BAA0B,CAAC;WAC1C,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC;WACzB,KAAK,CAAC,QAAQ,CAAC,cAAc,CAAC,EACjC,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,4CAA4C,IAAI,EAAE,CAAC,CAAC;IACtE,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,OAAgB,EAAE,OAAe;IAClE,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,CAAU;IACxC,IAAI,CAAC,YAAY,KAAK;QAAE,OAAO,CAAC,CAAC,OAAO,CAAC;IACzC,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;AACnB,CAAC"}
@@ -0,0 +1,22 @@
1
+ /** Maximum file size for image files (5MB). */
2
+ export declare const MAX_IMAGE_FILE_SIZE = 5000000;
3
+ /** Extensions treated as image files (binary, passed by path to CLI). */
4
+ export declare const IMAGE_EXTENSIONS: Set<string>;
5
+ /**
6
+ * Check whether a file path refers to an image based on extension.
7
+ */
8
+ export declare function isImageFile(filePath: string): boolean;
9
+ export interface FileContent {
10
+ path: string;
11
+ content: string;
12
+ skipped?: string;
13
+ }
14
+ /**
15
+ * Read multiple files with path sandboxing and size limits.
16
+ */
17
+ export declare function readFiles(files: string[], rootDir: string): Promise<FileContent[]>;
18
+ /**
19
+ * Assemble a prompt with inlined file contents.
20
+ */
21
+ export declare function assemblePrompt(prompt: string, fileContents: FileContent[]): string;
22
+ //# sourceMappingURL=files.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/utils/files.ts"],"names":[],"mappings":"AASA,+CAA+C;AAC/C,eAAO,MAAM,mBAAmB,UAAY,CAAC;AAE7C,yEAAyE;AACzE,eAAO,MAAM,gBAAgB,aAE3B,CAAC;AAEH;;GAEG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAErD;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAsB,SAAS,CAC7B,KAAK,EAAE,MAAM,EAAE,EACf,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,WAAW,EAAE,CAAC,CA8BxB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,GAAG,MAAM,CAWlF"}
@@ -0,0 +1,60 @@
1
+ import path from "node:path";
2
+ import { readFile } from "node:fs/promises";
3
+ import { resolveAndVerify, checkFileSize, MAX_FILE_SIZE, MAX_FILES, } from "./security.js";
4
+ /** Maximum file size for image files (5MB). */
5
+ export const MAX_IMAGE_FILE_SIZE = 5_000_000;
6
+ /** Extensions treated as image files (binary, passed by path to CLI). */
7
+ export const IMAGE_EXTENSIONS = new Set([
8
+ ".png", ".jpg", ".jpeg", ".gif", ".webp", ".bmp",
9
+ ]);
10
+ /**
11
+ * Check whether a file path refers to an image based on extension.
12
+ */
13
+ export function isImageFile(filePath) {
14
+ return IMAGE_EXTENSIONS.has(path.extname(filePath).toLowerCase());
15
+ }
16
+ /**
17
+ * Read multiple files with path sandboxing and size limits.
18
+ */
19
+ export async function readFiles(files, rootDir) {
20
+ if (files.length > MAX_FILES) {
21
+ throw new Error(`Too many files: ${files.length} (max ${MAX_FILES})`);
22
+ }
23
+ return Promise.all(files.map(async (f) => {
24
+ try {
25
+ const resolved = await resolveAndVerify(f, rootDir);
26
+ const size = await checkFileSize(resolved);
27
+ if (size > MAX_FILE_SIZE) {
28
+ return {
29
+ path: f,
30
+ content: "",
31
+ skipped: `${(size / 1024).toFixed(0)}KB exceeds ${(MAX_FILE_SIZE / 1024).toFixed(0)}KB limit`,
32
+ };
33
+ }
34
+ const content = await readFile(resolved, "utf8");
35
+ return { path: f, content };
36
+ }
37
+ catch (e) {
38
+ return {
39
+ path: f,
40
+ content: "",
41
+ skipped: e instanceof Error ? e.message : String(e),
42
+ };
43
+ }
44
+ }));
45
+ }
46
+ /**
47
+ * Assemble a prompt with inlined file contents.
48
+ */
49
+ export function assemblePrompt(prompt, fileContents) {
50
+ if (fileContents.length === 0)
51
+ return prompt;
52
+ const parts = fileContents.map((f) => {
53
+ if (f.skipped) {
54
+ return `--- ${f.path} ---\n[SKIPPED: ${f.skipped}]`;
55
+ }
56
+ return `--- ${f.path} ---\n${f.content}`;
57
+ });
58
+ return `${prompt}\n\n${parts.join("\n\n")}`;
59
+ }
60
+ //# sourceMappingURL=files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/utils/files.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,SAAS,GACV,MAAM,eAAe,CAAC;AAEvB,+CAA+C;AAC/C,MAAM,CAAC,MAAM,mBAAmB,GAAG,SAAS,CAAC;AAE7C,yEAAyE;AACzE,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC;IACtC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CACjD,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,QAAgB;IAC1C,OAAO,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AACpE,CAAC;AAQD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,KAAe,EACf,OAAe;IAEf,IAAI,KAAK,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,mBAAmB,KAAK,CAAC,MAAM,SAAS,SAAS,GAAG,CAAC,CAAC;IACxE,CAAC;IAED,OAAO,OAAO,CAAC,GAAG,CAChB,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAwB,EAAE;QAC1C,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YACpD,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,QAAQ,CAAC,CAAC;YAE3C,IAAI,IAAI,GAAG,aAAa,EAAE,CAAC;gBACzB,OAAO;oBACL,IAAI,EAAE,CAAC;oBACP,OAAO,EAAE,EAAE;oBACX,OAAO,EAAE,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU;iBAC9F,CAAC;YACJ,CAAC;YAED,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YACjD,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC;QAC9B,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO;gBACL,IAAI,EAAE,CAAC;gBACP,OAAO,EAAE,EAAE;gBACX,OAAO,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;aACpD,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CACH,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,MAAc,EAAE,YAA2B;IACxE,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IAE7C,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACnC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;YACd,OAAO,OAAO,CAAC,CAAC,IAAI,mBAAmB,CAAC,CAAC,OAAO,GAAG,CAAC;QACtD,CAAC;QACD,OAAO,OAAO,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,MAAM,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;AAC9C,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Find the git repository root for a given directory.
3
+ * Throws if not inside a git repo.
4
+ */
5
+ export declare function getGitRoot(cwd: string): string;
6
+ /**
7
+ * Get a unified diff of uncommitted changes (staged + unstaged).
8
+ */
9
+ export declare function getUncommittedDiff(cwd: string, contextLines?: number): string;
10
+ /**
11
+ * Get a diff between the current branch and a base branch/ref.
12
+ */
13
+ export declare function getBranchDiff(cwd: string, base: string, contextLines?: number): string;
14
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAS9C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,SAAI,GAAG,MAAM,CA2BxE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,SAAI,GAAG,MAAM,CAkBjF"}
@@ -0,0 +1,57 @@
1
+ import { execFileSync } from "node:child_process";
2
+ /**
3
+ * Find the git repository root for a given directory.
4
+ * Throws if not inside a git repo.
5
+ */
6
+ export function getGitRoot(cwd) {
7
+ try {
8
+ return execFileSync("git", ["-C", cwd, "rev-parse", "--show-toplevel"], {
9
+ encoding: "utf8",
10
+ timeout: 5000,
11
+ }).trim();
12
+ }
13
+ catch {
14
+ throw new Error(`Not a git repository: ${cwd}`);
15
+ }
16
+ }
17
+ /**
18
+ * Get a unified diff of uncommitted changes (staged + unstaged).
19
+ */
20
+ export function getUncommittedDiff(cwd, contextLines = 5) {
21
+ try {
22
+ // Staged changes
23
+ const staged = execFileSync("git", ["-C", cwd, "diff", "--cached", `-U${contextLines}`], { encoding: "utf8", timeout: 30000 }).trim();
24
+ // Unstaged changes
25
+ const unstaged = execFileSync("git", ["-C", cwd, "diff", `-U${contextLines}`], { encoding: "utf8", timeout: 30000 }).trim();
26
+ const parts = [staged, unstaged].filter(Boolean);
27
+ if (parts.length === 0) {
28
+ throw new Error("No uncommitted changes found");
29
+ }
30
+ return parts.join("\n");
31
+ }
32
+ catch (e) {
33
+ if (e instanceof Error && e.message === "No uncommitted changes found") {
34
+ throw e;
35
+ }
36
+ throw new Error(`Failed to get git diff: ${e}`);
37
+ }
38
+ }
39
+ /**
40
+ * Get a diff between the current branch and a base branch/ref.
41
+ */
42
+ export function getBranchDiff(cwd, base, contextLines = 5) {
43
+ try {
44
+ const diff = execFileSync("git", ["-C", cwd, "diff", `${base}...HEAD`, `-U${contextLines}`], { encoding: "utf8", timeout: 30000 }).trim();
45
+ if (!diff) {
46
+ throw new Error(`No diff found between ${base} and HEAD`);
47
+ }
48
+ return diff;
49
+ }
50
+ catch (e) {
51
+ if (e instanceof Error && e.message.startsWith("No diff found")) {
52
+ throw e;
53
+ }
54
+ throw new Error(`Failed to get branch diff against "${base}": ${e}`);
55
+ }
56
+ }
57
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,WAAW,EAAE,iBAAiB,CAAC,EAAE;YACtE,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,IAAI;SACd,CAAC,CAAC,IAAI,EAAE,CAAC;IACZ,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,yBAAyB,GAAG,EAAE,CAAC,CAAC;IAClD,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAW,EAAE,YAAY,GAAG,CAAC;IAC9D,IAAI,CAAC;QACH,iBAAiB;QACjB,MAAM,MAAM,GAAG,YAAY,CACzB,KAAK,EACL,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,YAAY,EAAE,CAAC,EACpD,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CACrC,CAAC,IAAI,EAAE,CAAC;QAET,mBAAmB;QACnB,MAAM,QAAQ,GAAG,YAAY,CAC3B,KAAK,EACL,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,YAAY,EAAE,CAAC,EACxC,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CACrC,CAAC,IAAI,EAAE,CAAC;QAET,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACjD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAClD,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,CAAC,YAAY,KAAK,IAAI,CAAC,CAAC,OAAO,KAAK,8BAA8B,EAAE,CAAC;YACvE,MAAM,CAAC,CAAC;QACV,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,EAAE,CAAC,CAAC;IAClD,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,GAAW,EAAE,IAAY,EAAE,YAAY,GAAG,CAAC;IACvE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,YAAY,CACvB,KAAK,EACL,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,SAAS,EAAE,KAAK,YAAY,EAAE,CAAC,EAC1D,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CACrC,CAAC,IAAI,EAAE,CAAC;QAET,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,yBAAyB,IAAI,WAAW,CAAC,CAAC;QAC5D,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,CAAC,YAAY,KAAK,IAAI,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;YAChE,MAAM,CAAC,CAAC;QACV,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,sCAAsC,IAAI,MAAM,CAAC,EAAE,CAAC,CAAC;IACvE,CAAC;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ export type ToolName = "query" | "structured" | "search" | "review" | "ping";
2
+ export declare function getDefaultModel(tool?: ToolName): string;
3
+ export declare function getFallbackModel(): string | undefined;
4
+ export declare function resolveModel(tool: ToolName, explicit?: string): string;
5
+ export declare function resolveEffort(tool: ToolName, explicit?: string): string | undefined;
6
+ export declare function resolveMaxBudget(explicit?: number): number;
7
+ //# sourceMappingURL=model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/utils/model.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;AAU7E,wBAAgB,eAAe,CAAC,IAAI,GAAE,QAAkB,GAAG,MAAM,CAQhE;AAED,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,SAAS,CAIrD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAEtE;AAOD,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMnF;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAI1D"}
@@ -0,0 +1,45 @@
1
+ const DEFAULT_MODELS = {
2
+ query: "sonnet",
3
+ structured: "sonnet",
4
+ search: "sonnet",
5
+ review: "opus",
6
+ ping: "haiku",
7
+ };
8
+ export function getDefaultModel(tool = "query") {
9
+ const specific = process.env[`CLAUDE_${tool.toUpperCase()}_MODEL`]?.trim();
10
+ if (specific)
11
+ return specific;
12
+ const shared = process.env["CLAUDE_DEFAULT_MODEL"]?.trim();
13
+ if (shared)
14
+ return shared;
15
+ return DEFAULT_MODELS[tool];
16
+ }
17
+ export function getFallbackModel() {
18
+ const value = process.env["CLAUDE_FALLBACK_MODEL"]?.trim();
19
+ if (value?.toLowerCase() === "none")
20
+ return undefined;
21
+ return value || "haiku";
22
+ }
23
+ export function resolveModel(tool, explicit) {
24
+ return explicit?.trim() || getDefaultModel(tool);
25
+ }
26
+ const DEFAULT_EFFORT = {
27
+ review: "high",
28
+ search: "medium",
29
+ };
30
+ export function resolveEffort(tool, explicit) {
31
+ const value = explicit?.trim();
32
+ if (value)
33
+ return value;
34
+ const envVal = process.env[`CLAUDE_${tool.toUpperCase()}_EFFORT`]?.trim();
35
+ if (envVal)
36
+ return envVal;
37
+ return DEFAULT_EFFORT[tool];
38
+ }
39
+ export function resolveMaxBudget(explicit) {
40
+ if (explicit !== undefined && explicit > 0)
41
+ return explicit;
42
+ const envVal = parseFloat(process.env["CLAUDE_MAX_BUDGET_USD"] ?? "0");
43
+ return envVal > 0 ? envVal : 0;
44
+ }
45
+ //# sourceMappingURL=model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/utils/model.ts"],"names":[],"mappings":"AAEA,MAAM,cAAc,GAA6B;IAC/C,KAAK,EAAE,QAAQ;IACf,UAAU,EAAE,QAAQ;IACpB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,MAAM;IACd,IAAI,EAAE,OAAO;CACd,CAAC;AAEF,MAAM,UAAU,eAAe,CAAC,OAAiB,OAAO;IACtD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC;IAC3E,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE9B,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,EAAE,IAAI,EAAE,CAAC;IAC3D,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,EAAE,IAAI,EAAE,CAAC;IAC3D,IAAI,KAAK,EAAE,WAAW,EAAE,KAAK,MAAM;QAAE,OAAO,SAAS,CAAC;IACtD,OAAO,KAAK,IAAI,OAAO,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAc,EAAE,QAAiB;IAC5D,OAAO,QAAQ,EAAE,IAAI,EAAE,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,cAAc,GAAsC;IACxD,MAAM,EAAE,MAAM;IACd,MAAM,EAAE,QAAQ;CACjB,CAAC;AAEF,MAAM,UAAU,aAAa,CAAC,IAAc,EAAE,QAAiB;IAC7D,MAAM,KAAK,GAAG,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC/B,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC;IACxB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC;IAC1E,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,QAAiB;IAChD,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,GAAG,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC5D,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,IAAI,GAAG,CAAC,CAAC;IACvE,OAAO,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AACjC,CAAC"}
@@ -0,0 +1,28 @@
1
+ export declare const OUTPUT_FORMAT = "json";
2
+ export interface ClaudeUsage {
3
+ input_tokens?: number;
4
+ output_tokens?: number;
5
+ cache_creation_input_tokens?: number;
6
+ cache_read_input_tokens?: number;
7
+ server_tool_use?: {
8
+ web_search_requests?: number;
9
+ web_fetch_requests?: number;
10
+ };
11
+ [key: string]: unknown;
12
+ }
13
+ export interface ClaudeOutput {
14
+ response: string;
15
+ sessionId?: string;
16
+ isError: boolean;
17
+ totalCostUsd?: number;
18
+ usage?: ClaudeUsage;
19
+ raw?: unknown;
20
+ }
21
+ export declare function redactSecrets(text: string): string;
22
+ export declare function parseClaudeOutput(stdout: string, stderr: string): ClaudeOutput;
23
+ export declare function tryParsePartial(stdout: string, stderr: string, timeoutMs: number): string;
24
+ export declare function extractJson(text: string): {
25
+ json: unknown;
26
+ raw: string;
27
+ } | null;
28
+ //# sourceMappingURL=parse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/utils/parse.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,aAAa,SAAS,CAAC;AAEpC,MAAM,WAAW,WAAW;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,eAAe,CAAC,EAAE;QAChB,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,kBAAkB,CAAC,EAAE,MAAM,CAAC;KAC7B,CAAC;IACF,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAUD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMlD;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY,CAuB9E;AAmED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAOzF;AAID,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAkC/E"}
@@ -0,0 +1,141 @@
1
+ import stripAnsi from "strip-ansi";
2
+ export const OUTPUT_FORMAT = "json";
3
+ const SECRET_PATTERNS = [
4
+ /sk-ant-api[a-zA-Z0-9_-]{20,}/g,
5
+ /sk-[a-zA-Z0-9_-]{20,}/g,
6
+ /Bearer\s+[a-zA-Z0-9._-]{20,}/gi,
7
+ /token[=:]\s*["']?[a-zA-Z0-9._-]{20,}["']?/gi,
8
+ /[A-Za-z0-9+/]{40,}={0,2}/g,
9
+ ];
10
+ export function redactSecrets(text) {
11
+ let result = text;
12
+ for (const pattern of SECRET_PATTERNS) {
13
+ result = result.replace(pattern, "[REDACTED]");
14
+ }
15
+ return result;
16
+ }
17
+ export function parseClaudeOutput(stdout, stderr) {
18
+ const cleanedStdout = redactSecrets(stripAnsi(stdout).trim());
19
+ const cleanedStderr = redactSecrets(stripAnsi(stderr).trim());
20
+ if (cleanedStdout) {
21
+ const parsed = tryParseJsonObject(cleanedStdout);
22
+ if (parsed)
23
+ return extractFromJson(parsed);
24
+ }
25
+ if (cleanedStderr) {
26
+ const parsed = tryParseJsonObject(cleanedStderr);
27
+ if (parsed)
28
+ return extractFromJson(parsed);
29
+ }
30
+ if (cleanedStdout) {
31
+ return { response: cleanedStdout, isError: false };
32
+ }
33
+ if (cleanedStderr) {
34
+ return { response: cleanedStderr, isError: false };
35
+ }
36
+ throw new Error("Claude CLI produced no output");
37
+ }
38
+ function tryParseJsonObject(text) {
39
+ try {
40
+ return JSON.parse(text);
41
+ }
42
+ catch {
43
+ const start = text.indexOf("{");
44
+ const end = text.lastIndexOf("}");
45
+ if (start !== -1 && end > start) {
46
+ try {
47
+ return JSON.parse(text.slice(start, end + 1));
48
+ }
49
+ catch {
50
+ return null;
51
+ }
52
+ }
53
+ return null;
54
+ }
55
+ }
56
+ function extractFromJson(parsed) {
57
+ if (typeof parsed === "string") {
58
+ return { response: parsed, isError: false, raw: parsed };
59
+ }
60
+ if (!parsed || typeof parsed !== "object") {
61
+ return { response: String(parsed), isError: false, raw: parsed };
62
+ }
63
+ const obj = parsed;
64
+ const sessionId = typeof obj["session_id"] === "string" ? obj["session_id"] : undefined;
65
+ const totalCostUsd = typeof obj["total_cost_usd"] === "number" ? obj["total_cost_usd"] : undefined;
66
+ const usage = obj["usage"] && typeof obj["usage"] === "object"
67
+ ? obj["usage"]
68
+ : undefined;
69
+ const isError = obj["is_error"] === true;
70
+ const response = extractResponseText(obj);
71
+ return {
72
+ response,
73
+ sessionId,
74
+ isError,
75
+ totalCostUsd,
76
+ usage,
77
+ raw: parsed,
78
+ };
79
+ }
80
+ function extractResponseText(obj) {
81
+ for (const key of ["result", "response", "text", "content", "message", "output"]) {
82
+ if (typeof obj[key] === "string") {
83
+ return obj[key];
84
+ }
85
+ }
86
+ if (obj["result"] && typeof obj["result"] === "object") {
87
+ const nested = obj["result"];
88
+ for (const key of ["response", "text", "content", "message", "output"]) {
89
+ if (typeof nested[key] === "string") {
90
+ return nested[key];
91
+ }
92
+ }
93
+ }
94
+ return JSON.stringify(obj, null, 2);
95
+ }
96
+ export function tryParsePartial(stdout, stderr, timeoutMs) {
97
+ try {
98
+ return parseClaudeOutput(stdout, stderr).response;
99
+ }
100
+ catch {
101
+ const combined = redactSecrets(stripAnsi([stdout, stderr].filter(Boolean).join("\n")).trim());
102
+ return combined || `Query timed out after ${Math.round(timeoutMs / 1000)}s.`;
103
+ }
104
+ }
105
+ const MAX_EXTRACT_SIZE = 1_000_000;
106
+ export function extractJson(text) {
107
+ if (!text || text.length > MAX_EXTRACT_SIZE)
108
+ return null;
109
+ try {
110
+ return { json: JSON.parse(text), raw: text };
111
+ }
112
+ catch {
113
+ // continue
114
+ }
115
+ const fenced = text.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/);
116
+ if (fenced) {
117
+ try {
118
+ return { json: JSON.parse(fenced[1]), raw: fenced[1] };
119
+ }
120
+ catch {
121
+ // continue
122
+ }
123
+ }
124
+ const objStart = text.indexOf("{");
125
+ const arrStart = text.indexOf("[");
126
+ const start = objStart === -1 ? arrStart : arrStart === -1 ? objStart : Math.min(objStart, arrStart);
127
+ if (start !== -1) {
128
+ const end = Math.max(text.lastIndexOf("}"), text.lastIndexOf("]"));
129
+ if (end > start) {
130
+ try {
131
+ const slice = text.slice(start, end + 1);
132
+ return { json: JSON.parse(slice), raw: slice };
133
+ }
134
+ catch {
135
+ // continue
136
+ }
137
+ }
138
+ }
139
+ return null;
140
+ }
141
+ //# sourceMappingURL=parse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/utils/parse.ts"],"names":[],"mappings":"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"}