@printwithsynergy/synergy-mcp 0.1.1

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 ADDED
@@ -0,0 +1,160 @@
1
+ # synergy-mcp
2
+
3
+ Cross-stack dev-audit MCP server for the [Print With Synergy](https://printwithsynergy.com)
4
+ stack.
5
+
6
+ Serves four tools over the MCP stdio transport, scoped to the six repos in the
7
+ stack — `codex-pdf`, `lint-pdf`, `lens-pdf`, `compile-pdf`, `synergy`, `platform`:
8
+
9
+ | Tool | What it answers |
10
+ | -------------------- | --------------------------------------------------------------------- |
11
+ | `blast_radius` | Who breaks if I change this symbol / route / env var? |
12
+ | `floor_pin_grid` | Which repo pins which org package, at which version? |
13
+ | `pattern_audit` | Which repos have CI / consume-surface / RFC 7807 / deep CLAUDE.md? |
14
+ | `stack_health_grid` | What does `/healthz` + `/v1/contract` say across the prod URLs? |
15
+
16
+ Built to close gaps the cross-stack architecture audit surfaced — pin drift,
17
+ pattern divergence, "lens vs lens-server" naming collisions, ad-hoc health
18
+ endpoint shapes.
19
+
20
+ ## Install
21
+
22
+ ```bash
23
+ npm install -g @printwithsynergy/synergy-mcp
24
+ # or use npx directly from your MCP client config
25
+ ```
26
+
27
+ ## Configure
28
+
29
+ The server needs to know where your six repo working trees live. Two ways:
30
+
31
+ ### 1. Stack root (recommended)
32
+
33
+ If you clone every repo into a single parent directory:
34
+
35
+ ```bash
36
+ export SYNERGY_MCP_STACK_ROOT=$HOME/code/printwithsynergy
37
+ # expects $HOME/code/printwithsynergy/{codex-pdf,lint-pdf,lens-pdf,compile-pdf,synergy,platform}
38
+ ```
39
+
40
+ ### 2. Per-repo overrides
41
+
42
+ For non-uniform paths:
43
+
44
+ ```bash
45
+ export SYNERGY_MCP_PATH_CODEX_PDF=/path/to/codex-pdf
46
+ export SYNERGY_MCP_PATH_LINT_PDF=/path/to/lint-pdf
47
+ # ... one per repo
48
+ ```
49
+
50
+ Per-repo env wins over `SYNERGY_MCP_STACK_ROOT` for the same repo. Repos that
51
+ don't resolve are simply skipped — tools return rows for whatever is available
52
+ plus a `notes[]` entry naming the missing repo.
53
+
54
+ ### Prod URLs (for `stack_health_grid` only)
55
+
56
+ Defaults match the production hostnames the audit catalogued; override per
57
+ service:
58
+
59
+ ```bash
60
+ export SYNERGY_MCP_URL_CODEX_PDF=https://codex.lintpdf.com
61
+ export SYNERGY_MCP_URL_LINT_PDF=https://lintpdf.com
62
+ export SYNERGY_MCP_URL_COMPILE_PDF=https://compilepdf.com
63
+ export SYNERGY_MCP_URL_SYNERGY=https://... # not set by default
64
+ export SYNERGY_MCP_URL_PLATFORM=https://... # not set by default
65
+ # lens-pdf has no HTTP surface (npm library only) — no URL needed.
66
+ ```
67
+
68
+ ## Use from Claude Code
69
+
70
+ Add to your Claude Code MCP config (`~/.config/claude-code/mcp.json` or
71
+ project-local equivalent):
72
+
73
+ ```json
74
+ {
75
+ "mcpServers": {
76
+ "synergy-mcp": {
77
+ "command": "npx",
78
+ "args": ["-y", "@printwithsynergy/synergy-mcp"],
79
+ "env": {
80
+ "SYNERGY_MCP_STACK_ROOT": "/Users/you/code/printwithsynergy"
81
+ }
82
+ }
83
+ }
84
+ }
85
+ ```
86
+
87
+ Tools then show up as `mcp__synergy_mcp__blast_radius`,
88
+ `mcp__synergy_mcp__floor_pin_grid`, etc.
89
+
90
+ ## Tools
91
+
92
+ ### `blast_radius`
93
+
94
+ ```json
95
+ {
96
+ "target": "CodexDocument",
97
+ "kind": "symbol"
98
+ }
99
+ ```
100
+
101
+ Kinds: `symbol` | `route` | `env_var`. Default `symbol`.
102
+
103
+ Returns per-hit `{ repo, file, line, text, kind }` where `kind` is one of
104
+ `import` | `usage` | `route` | `env`.
105
+
106
+ Implementation note: regex-based (Python `from X import Y`, TS
107
+ `import { Y } from 'X'`, plus bare-name usage). Not AST.
108
+ [`ctxo`](https://github.com/anthropics/code-review-graph) ships a real AST
109
+ backed blast-radius for TS/Go/C# but doesn't have a Python plugin yet; this
110
+ tool fills the gap with the working substitute that lint-pdf's `CLAUDE.md`
111
+ already calls out.
112
+
113
+ ### `floor_pin_grid`
114
+
115
+ ```json
116
+ { "package": "codex-pdf" }
117
+ ```
118
+
119
+ Or omit `package` to return rows for every detected org package.
120
+
121
+ Audit finding #2 — the bug it would have caught on day one: lint-pdf pinning
122
+ `codex-pdf>=1.19.0` with no upper bound while compile-pdf pinned `<2.0`.
123
+
124
+ ### `pattern_audit`
125
+
126
+ ```json
127
+ { "patterns": ["has_ci", "has_problem_details_errors"] }
128
+ ```
129
+
130
+ Omit `patterns` to run every known probe. Each row is
131
+ `{ repo, pattern, present, evidence }`. Available patterns are listed in the
132
+ result's `available_patterns` field.
133
+
134
+ Probes are intentionally cheap (file existence, shallow grep). Audit findings
135
+ #1, #6, #13, and #4 each get a probe.
136
+
137
+ ### `stack_health_grid`
138
+
139
+ ```json
140
+ { "timeout_ms": 5000 }
141
+ ```
142
+
143
+ Optional `repos: ["codex-pdf", "synergy"]` to subset.
144
+
145
+ Each row: `{ repo, url, endpoint, status, latency_ms, body_summary }`. Endpoint
146
+ mapping per repo matches audit finding #15.
147
+
148
+ ## Develop
149
+
150
+ ```bash
151
+ pnpm install
152
+ pnpm dev # tsx watch
153
+ pnpm typecheck # tsc --noEmit
154
+ pnpm test # vitest run
155
+ pnpm build # tsc → dist/
156
+ ```
157
+
158
+ ## License
159
+
160
+ AGPL-3.0-or-later, matching the rest of the printwithsynergy engine stack.
@@ -0,0 +1,14 @@
1
+ export type RepoName = "codex-pdf" | "lint-pdf" | "lens-pdf" | "compile-pdf" | "synergy" | "platform";
2
+ export declare const KNOWN_REPOS: RepoName[];
3
+ /** Language tag drives which AST / pattern set to use. */
4
+ export type RepoLang = "python" | "typescript";
5
+ export declare const REPO_LANG: Record<RepoName, RepoLang>;
6
+ /** Prod URLs for stack_health_grid. Override via env. */
7
+ export declare const PROD_URLS: Record<RepoName, string | null>;
8
+ /** Resolve the working-tree path for a single repo, or null. */
9
+ export declare function resolveRepoPath(repo: RepoName): string | null;
10
+ /** Resolve all six repo paths. Missing repos appear as null. */
11
+ export declare function resolveAllRepoPaths(): Record<RepoName, string | null>;
12
+ /** True if any repo resolves; the caller can surface `config_missing`. */
13
+ export declare function hasAnyRepo(): boolean;
14
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAqBA,MAAM,MAAM,QAAQ,GAChB,WAAW,GACX,UAAU,GACV,UAAU,GACV,aAAa,GACb,SAAS,GACT,UAAU,CAAC;AAEf,eAAO,MAAM,WAAW,EAAE,QAAQ,EAOjC,CAAC;AAEF,0DAA0D;AAC1D,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,YAAY,CAAC;AAE/C,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAOhD,CAAC;AAEF,yDAAyD;AACzD,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CASrD,CAAC;AAUF,gEAAgE;AAChE,wBAAgB,eAAe,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,CAW7D;AAED,gEAAgE;AAChE,wBAAgB,mBAAmB,IAAI,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC,CAMrE;AAED,0EAA0E;AAC1E,wBAAgB,UAAU,IAAI,OAAO,CAEpC"}
package/dist/config.js ADDED
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Stack configuration.
3
+ *
4
+ * synergy-mcp serves a cross-stack dev-audit MCP over six repos in
5
+ * the Print With Synergy stack. It needs to know where each repo's
6
+ * working tree is on the host. Two ways to tell it:
7
+ *
8
+ * 1. Env vars (per-repo): SYNERGY_MCP_PATH_CODEX_PDF=/path/to/codex-pdf
9
+ * (...one per repo). Highest priority.
10
+ * 2. Stack root env: SYNERGY_MCP_STACK_ROOT=/path/to/clones — assumes
11
+ * each repo is a sibling directory named after the repo. This is
12
+ * the common case when you clone all six into a single
13
+ * `printwithsynergy/` directory.
14
+ *
15
+ * If neither is set, the server starts but every tool returns an
16
+ * empty result with a `config_missing` flag so the caller can prompt
17
+ * the user to configure.
18
+ */
19
+ import { existsSync } from "node:fs";
20
+ import { join } from "node:path";
21
+ export const KNOWN_REPOS = [
22
+ "codex-pdf",
23
+ "lint-pdf",
24
+ "lens-pdf",
25
+ "compile-pdf",
26
+ "synergy",
27
+ "platform",
28
+ ];
29
+ export const REPO_LANG = {
30
+ "codex-pdf": "python",
31
+ "lint-pdf": "python",
32
+ "compile-pdf": "python",
33
+ "lens-pdf": "typescript",
34
+ synergy: "typescript",
35
+ platform: "typescript",
36
+ };
37
+ /** Prod URLs for stack_health_grid. Override via env. */
38
+ export const PROD_URLS = {
39
+ "codex-pdf": process.env.SYNERGY_MCP_URL_CODEX_PDF ?? "https://codex.lintpdf.com",
40
+ "lint-pdf": process.env.SYNERGY_MCP_URL_LINT_PDF ?? "https://lintpdf.com",
41
+ "compile-pdf": process.env.SYNERGY_MCP_URL_COMPILE_PDF ?? "https://compilepdf.com",
42
+ "lens-pdf": null, // npm library — no prod URL
43
+ synergy: process.env.SYNERGY_MCP_URL_SYNERGY ?? null,
44
+ platform: process.env.SYNERGY_MCP_URL_PLATFORM ?? null,
45
+ };
46
+ /**
47
+ * Map a RepoName to its env-var-friendly UPPERCASE_SNAKE form, e.g.
48
+ * "codex-pdf" → "CODEX_PDF". Used to look up SYNERGY_MCP_PATH_<NAME>.
49
+ */
50
+ function envKey(repo) {
51
+ return repo.toUpperCase().replace(/-/g, "_");
52
+ }
53
+ /** Resolve the working-tree path for a single repo, or null. */
54
+ export function resolveRepoPath(repo) {
55
+ const perRepoEnv = process.env[`SYNERGY_MCP_PATH_${envKey(repo)}`];
56
+ if (perRepoEnv && existsSync(perRepoEnv))
57
+ return perRepoEnv;
58
+ const stackRoot = process.env.SYNERGY_MCP_STACK_ROOT;
59
+ if (stackRoot) {
60
+ const guess = join(stackRoot, repo);
61
+ if (existsSync(guess))
62
+ return guess;
63
+ }
64
+ return null;
65
+ }
66
+ /** Resolve all six repo paths. Missing repos appear as null. */
67
+ export function resolveAllRepoPaths() {
68
+ const result = {};
69
+ for (const repo of KNOWN_REPOS) {
70
+ result[repo] = resolveRepoPath(repo);
71
+ }
72
+ return result;
73
+ }
74
+ /** True if any repo resolves; the caller can surface `config_missing`. */
75
+ export function hasAnyRepo() {
76
+ return KNOWN_REPOS.some((r) => resolveRepoPath(r) !== null);
77
+ }
78
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAUjC,MAAM,CAAC,MAAM,WAAW,GAAe;IACrC,WAAW;IACX,UAAU;IACV,UAAU;IACV,aAAa;IACb,SAAS;IACT,UAAU;CACX,CAAC;AAKF,MAAM,CAAC,MAAM,SAAS,GAA+B;IACnD,WAAW,EAAE,QAAQ;IACrB,UAAU,EAAE,QAAQ;IACpB,aAAa,EAAE,QAAQ;IACvB,UAAU,EAAE,YAAY;IACxB,OAAO,EAAE,YAAY;IACrB,QAAQ,EAAE,YAAY;CACvB,CAAC;AAEF,yDAAyD;AACzD,MAAM,CAAC,MAAM,SAAS,GAAoC;IACxD,WAAW,EACT,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,2BAA2B;IACtE,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,wBAAwB,IAAI,qBAAqB;IACzE,aAAa,EACX,OAAO,CAAC,GAAG,CAAC,2BAA2B,IAAI,wBAAwB;IACrE,UAAU,EAAE,IAAI,EAAE,4BAA4B;IAC9C,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,IAAI;IACpD,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,wBAAwB,IAAI,IAAI;CACvD,CAAC;AAEF;;;GAGG;AACH,SAAS,MAAM,CAAC,IAAc;IAC5B,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC/C,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,eAAe,CAAC,IAAc;IAC5C,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnE,IAAI,UAAU,IAAI,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,UAAU,CAAC;IAE5D,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC;IACrD,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QACpC,IAAI,UAAU,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;IACtC,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,mBAAmB;IACjC,MAAM,MAAM,GAA6C,EAAE,CAAC;IAC5D,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,MAAM,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,MAAyC,CAAC;AACnD,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,UAAU;IACxB,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;AAC9D,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * synergy-mcp — cross-stack dev-audit MCP server for the Print With
4
+ * Synergy stack. Serves four tools over stdio:
5
+ *
6
+ * - blast_radius — find every call site of a symbol / route / env
7
+ * var across the six configured repos.
8
+ * - floor_pin_grid — the (repo × org-package × version-spec) matrix.
9
+ * - pattern_audit — the (repo × architectural-pattern) matrix.
10
+ * - stack_health_grid — parallel /healthz + /v1/contract probes
11
+ * across the prod URLs.
12
+ *
13
+ * Configuration is via environment variables — see ./config.ts.
14
+ * Designed to run from Claude Code via `npx @printwithsynergy/synergy-mcp`
15
+ * (or installed globally) over the stdio transport.
16
+ */
17
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
18
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
19
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
20
+ import { z } from "zod";
21
+ import { hasAnyRepo } from "./config.js";
22
+ import { BlastRadiusInput, blastRadius } from "./tools/blast-radius.js";
23
+ import { FloorPinGridInput, floorPinGrid } from "./tools/floor-pin-grid.js";
24
+ import { PatternAuditInput, patternAudit } from "./tools/pattern-audit.js";
25
+ import { StackHealthGridInput, stackHealthGrid, } from "./tools/stack-health-grid.js";
26
+ const SERVER_NAME = "synergy-mcp";
27
+ const SERVER_VERSION = "0.1.0";
28
+ const TOOLS = [
29
+ {
30
+ name: "blast_radius",
31
+ description: "Find every call site of a symbol, HTTP route, or env var across the printwithsynergy stack's six repos (codex-pdf, lint-pdf, lens-pdf, compile-pdf, synergy, platform). Use to answer 'who breaks if I change X?' before refactoring across the seam.",
32
+ schema: BlastRadiusInput,
33
+ handler: blastRadius,
34
+ },
35
+ {
36
+ name: "floor_pin_grid",
37
+ description: "Return the (repo × org-package × version-spec) matrix across pyproject.toml dependencies + package.json {dependencies,devDependencies,peerDependencies}. Detects drift — e.g. one repo pinning codex-pdf>=1.19.0 with no upper bound while another caps at <2.0.",
38
+ schema: FloorPinGridInput,
39
+ handler: floorPinGrid,
40
+ },
41
+ {
42
+ name: "pattern_audit",
43
+ description: "Return the (repo × pattern) matrix for the architectural patterns the cross-stack audit found inconsistently applied. Patterns include presence of CI workflows, the /v1/contract endpoint, consume-surface-audit / engine-purity tripwires, RFC 7807 Problem Details, and CLAUDE.md depth.",
44
+ schema: PatternAuditInput,
45
+ handler: patternAudit,
46
+ },
47
+ {
48
+ name: "stack_health_grid",
49
+ description: "Fetch /healthz and /v1/contract (where exposed) across the configured prod URLs for the stack, in parallel, returning status code + latency + body summary per probe. Branches per-repo for the five different endpoint shapes the audit cataloged.",
50
+ schema: StackHealthGridInput,
51
+ handler: stackHealthGrid,
52
+ },
53
+ ];
54
+ /** Render a Zod object schema to a minimal JSON Schema. */
55
+ function toJsonSchema(zod) {
56
+ const shape = zod.shape;
57
+ const properties = {};
58
+ const required = [];
59
+ for (const [key, raw] of Object.entries(shape)) {
60
+ const field = raw;
61
+ const description = field.description ?? undefined;
62
+ const entry = { description };
63
+ let inner = field;
64
+ if (field instanceof z.ZodOptional || field instanceof z.ZodDefault) {
65
+ inner = field._def.innerType;
66
+ }
67
+ else {
68
+ required.push(key);
69
+ }
70
+ if (inner instanceof z.ZodString) {
71
+ entry.type = "string";
72
+ }
73
+ else if (inner instanceof z.ZodNumber) {
74
+ entry.type = "number";
75
+ }
76
+ else if (inner instanceof z.ZodBoolean) {
77
+ entry.type = "boolean";
78
+ }
79
+ else if (inner instanceof z.ZodEnum) {
80
+ entry.type = "string";
81
+ entry.enum = inner._def.values;
82
+ }
83
+ else if (inner instanceof z.ZodArray) {
84
+ entry.type = "array";
85
+ entry.items = { type: "string" };
86
+ }
87
+ else {
88
+ entry.type = "object";
89
+ }
90
+ properties[key] = entry;
91
+ }
92
+ const out = {
93
+ type: "object",
94
+ properties,
95
+ };
96
+ if (required.length > 0)
97
+ out.required = required;
98
+ return out;
99
+ }
100
+ async function main() {
101
+ const server = new Server({ name: SERVER_NAME, version: SERVER_VERSION }, { capabilities: { tools: {} } });
102
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
103
+ const tools = TOOLS.map((t) => ({
104
+ name: t.name,
105
+ description: t.description,
106
+ inputSchema: toJsonSchema(t.schema),
107
+ }));
108
+ return { tools };
109
+ });
110
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
111
+ const { name, arguments: args } = request.params;
112
+ const tool = TOOLS.find((t) => t.name === name);
113
+ if (!tool) {
114
+ return {
115
+ content: [{ type: "text", text: `Unknown tool: ${name}` }],
116
+ isError: true,
117
+ };
118
+ }
119
+ if (!hasAnyRepo() && name !== "stack_health_grid") {
120
+ return {
121
+ content: [
122
+ {
123
+ type: "text",
124
+ text: "No repos configured. Set SYNERGY_MCP_STACK_ROOT to the directory containing your six repo clones, or SYNERGY_MCP_PATH_<REPO> per-repo (e.g. SYNERGY_MCP_PATH_CODEX_PDF=/path/to/codex-pdf).",
125
+ },
126
+ ],
127
+ isError: true,
128
+ };
129
+ }
130
+ const parsed = tool.schema.safeParse(args ?? {});
131
+ if (!parsed.success) {
132
+ return {
133
+ content: [
134
+ {
135
+ type: "text",
136
+ text: `Invalid arguments for ${name}: ${parsed.error.message}`,
137
+ },
138
+ ],
139
+ isError: true,
140
+ };
141
+ }
142
+ try {
143
+ const result = await tool.handler(parsed.data);
144
+ return {
145
+ content: [
146
+ { type: "text", text: JSON.stringify(result, null, 2) },
147
+ ],
148
+ };
149
+ }
150
+ catch (err) {
151
+ const msg = err instanceof Error ? err.message : String(err);
152
+ return {
153
+ content: [{ type: "text", text: `Tool error: ${msg}` }],
154
+ isError: true,
155
+ };
156
+ }
157
+ });
158
+ const transport = new StdioServerTransport();
159
+ await server.connect(transport);
160
+ // Lifecycle: server runs until stdio closes.
161
+ }
162
+ main().catch((err) => {
163
+ console.error("synergy-mcp fatal:", err);
164
+ process.exit(1);
165
+ });
166
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC5E,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC3E,OAAO,EACL,oBAAoB,EACpB,eAAe,GAChB,MAAM,8BAA8B,CAAC;AAEtC,MAAM,WAAW,GAAG,aAAa,CAAC;AAClC,MAAM,cAAc,GAAG,OAAO,CAAC;AAgB/B,MAAM,KAAK,GAAG;IACZ;QACE,IAAI,EAAE,cAAc;QACpB,WAAW,EACT,uPAAuP;QACzP,MAAM,EAAE,gBAAgB;QACxB,OAAO,EAAE,WAAW;KACsB;IAC5C;QACE,IAAI,EAAE,gBAAgB;QACtB,WAAW,EACT,kQAAkQ;QACpQ,MAAM,EAAE,iBAAiB;QACzB,OAAO,EAAE,YAAY;KACsB;IAC7C;QACE,IAAI,EAAE,eAAe;QACrB,WAAW,EACT,6RAA6R;QAC/R,MAAM,EAAE,iBAAiB;QACzB,OAAO,EAAE,YAAY;KACsB;IAC7C;QACE,IAAI,EAAE,mBAAmB;QACzB,WAAW,EACT,qPAAqP;QACvP,MAAM,EAAE,oBAAoB;QAC5B,OAAO,EAAE,eAAe;KACsB;CACxC,CAAC;AAEX,2DAA2D;AAC3D,SAAS,YAAY,CACnB,GAA+B;IAE/B,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC;IACxB,MAAM,UAAU,GAA4B,EAAE,CAAC;IAC/C,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/C,MAAM,KAAK,GAAG,GAAmB,CAAC;QAClC,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,IAAI,SAAS,CAAC;QACnD,MAAM,KAAK,GAA4B,EAAE,WAAW,EAAE,CAAC;QACvD,IAAI,KAAK,GAAiB,KAAK,CAAC;QAChC,IAAI,KAAK,YAAY,CAAC,CAAC,WAAW,IAAI,KAAK,YAAY,CAAC,CAAC,UAAU,EAAE,CAAC;YACpE,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,SAAyB,CAAC;QAC/C,CAAC;aAAM,CAAC;YACN,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;QACD,IAAI,KAAK,YAAY,CAAC,CAAC,SAAS,EAAE,CAAC;YACjC,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC;QACxB,CAAC;aAAM,IAAI,KAAK,YAAY,CAAC,CAAC,SAAS,EAAE,CAAC;YACxC,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC;QACxB,CAAC;aAAM,IAAI,KAAK,YAAY,CAAC,CAAC,UAAU,EAAE,CAAC;YACzC,KAAK,CAAC,IAAI,GAAG,SAAS,CAAC;QACzB,CAAC;aAAM,IAAI,KAAK,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC;YACtC,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC;YACtB,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;QACjC,CAAC;aAAM,IAAI,KAAK,YAAY,CAAC,CAAC,QAAQ,EAAE,CAAC;YACvC,KAAK,CAAC,IAAI,GAAG,OAAO,CAAC;YACrB,KAAK,CAAC,KAAK,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;QACnC,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC;QACxB,CAAC;QACD,UAAU,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IAC1B,CAAC;IACD,MAAM,GAAG,GAA4B;QACnC,IAAI,EAAE,QAAQ;QACd,UAAU;KACX,CAAC;IACF,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,GAAG,CAAC,QAAQ,GAAG,QAAQ,CAAC;IACjD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,cAAc,EAAE,EAC9C,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAChC,CAAC;IAEF,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE;QAC1D,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC9B,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,WAAW,EAAE,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC;SACpC,CAAC,CAAC,CAAC;QACJ,OAAO,EAAE,KAAK,EAAE,CAAC;IACnB,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QAChE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;QACjD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QAChD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,iBAAiB,IAAI,EAAE,EAAE,CAAC;gBACnE,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,UAAU,EAAE,IAAI,IAAI,KAAK,mBAAmB,EAAE,CAAC;YAClD,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,6LAA6L;qBACpM;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QACjD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,yBAAyB,IAAI,KAAK,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE;qBAC/D;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAa,CAAC,CAAC;YACxD,OAAO;gBACL,OAAO,EAAE;oBACP,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;iBACjE;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC7D,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,eAAe,GAAG,EAAE,EAAE,CAAC;gBAChE,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,6CAA6C;AAC/C,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,oBAAoB,EAAE,GAAG,CAAC,CAAC;IACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,33 @@
1
+ import { z } from "zod";
2
+ import { type RepoName } from "../config.js";
3
+ export declare const BlastRadiusInput: z.ZodObject<{
4
+ target: z.ZodString;
5
+ kind: z.ZodDefault<z.ZodEnum<["symbol", "route", "env_var"]>>;
6
+ repos: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
7
+ max_results_per_repo: z.ZodDefault<z.ZodNumber>;
8
+ }, "strip", z.ZodTypeAny, {
9
+ target: string;
10
+ kind: "symbol" | "route" | "env_var";
11
+ max_results_per_repo: number;
12
+ repos?: string[] | undefined;
13
+ }, {
14
+ target: string;
15
+ kind?: "symbol" | "route" | "env_var" | undefined;
16
+ repos?: string[] | undefined;
17
+ max_results_per_repo?: number | undefined;
18
+ }>;
19
+ export interface BlastRadiusHit {
20
+ repo: RepoName;
21
+ file: string;
22
+ line: number;
23
+ text: string;
24
+ kind: "import" | "usage" | "route" | "env";
25
+ }
26
+ export interface BlastRadiusResult {
27
+ target: string;
28
+ kind: z.infer<typeof BlastRadiusInput>["kind"];
29
+ hits: BlastRadiusHit[];
30
+ notes: string[];
31
+ }
32
+ export declare function blastRadius(input: z.infer<typeof BlastRadiusInput>): Promise<BlastRadiusResult>;
33
+ //# sourceMappingURL=blast-radius.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blast-radius.d.ts","sourceRoot":"","sources":["../../src/tools/blast-radius.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAIL,KAAK,QAAQ,EAEd,MAAM,cAAc,CAAC;AAEtB,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;EAyB3B,CAAC;AAEH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,KAAK,CAAC;CAC5C;AA0JD,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;IAC/C,IAAI,EAAE,cAAc,EAAE,CAAC;IACvB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,wBAAsB,WAAW,CAC/B,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,GACtC,OAAO,CAAC,iBAAiB,CAAC,CA2B5B"}