@interactive-inc/claude-funnel 0.53.0 → 0.56.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 (71) hide show
  1. package/README.md +3 -3
  2. package/dist/bin.js +1229 -486
  3. package/dist/claude.d.ts +22 -5
  4. package/dist/claude.js +455 -168
  5. package/dist/{connector-adapter-CePYBTgW.d.ts → connector-adapter-1PxjN-Uk.d.ts} +1 -1
  6. package/dist/{connector-adapter-D5Utumgz.js → connector-adapter-qwXLjQId.js} +1 -1
  7. package/dist/{connector-listener-DU54DN-f.js → connector-listener-CpHBecCj.js} +1 -1
  8. package/dist/connectors/discord.d.ts +6 -6
  9. package/dist/connectors/discord.js +2 -2
  10. package/dist/connectors/gh.d.ts +6 -6
  11. package/dist/connectors/gh.js +2 -2
  12. package/dist/connectors/schedule.d.ts +12 -2
  13. package/dist/connectors/schedule.js +2 -2
  14. package/dist/connectors/slack.d.ts +3 -3
  15. package/dist/connectors/slack.js +2 -2
  16. package/dist/{connector-diagnostic-log-yTOojKUR.d.ts → diagnostic-log-Bxe7Bbvw.d.ts} +2 -2
  17. package/dist/diagnostic-sql-reader-CzYgZpq2.js +83 -0
  18. package/dist/diagnostics.d.ts +2 -0
  19. package/dist/diagnostics.js +2 -0
  20. package/dist/{discord-connector-schema-CBDyGdOI.js → discord-connector-schema-B_N6IXLz.js} +1 -1
  21. package/dist/{discord-connector-schema-R0Uu-3ns.d.ts → discord-connector-schema-CPgcZkXh.d.ts} +1 -1
  22. package/dist/{discord-listener-_jSE3HsQ.js → discord-listener-C0MoKdQO.js} +6 -6
  23. package/dist/docs.d.ts +2 -0
  24. package/dist/docs.js +2 -0
  25. package/dist/doctor.d.ts +2 -0
  26. package/dist/doctor.js +2 -0
  27. package/dist/{file-process-guard-DMeLB6Zd.d.ts → file-process-guard-DI1742H5.d.ts} +5 -4
  28. package/dist/funnel-diagnostics-BpKYrMSu.js +300 -0
  29. package/dist/funnel-diagnostics-qWy5tPSq.d.ts +176 -0
  30. package/dist/funnel-docs-dXPokzr5.d.ts +18 -0
  31. package/dist/funnel-docs-ng5K8w4j.js +653 -0
  32. package/dist/funnel-doctor-BF3Rdgk0.d.ts +34 -0
  33. package/dist/funnel-doctor-CApCezTq.js +82 -0
  34. package/dist/funnel-recovery-BUBsu7WX.d.ts +101 -0
  35. package/dist/funnel-recovery-D9CxD5Zs.js +134 -0
  36. package/dist/gateway/daemon.js +838 -252
  37. package/dist/{gateway-base-url-ssk_He5G.js → gateway-base-url-6foMXfFf.js} +5 -5
  38. package/dist/gateway.d.ts +2 -2
  39. package/dist/gateway.js +2 -2
  40. package/dist/{gh-connector-schema-eoTtHbY6.d.ts → gh-connector-schema-CU1ojfIF.d.ts} +1 -1
  41. package/dist/{gh-connector-schema-o3Q1-ojL.js → gh-connector-schema-DUcZgN2Q.js} +1 -1
  42. package/dist/{gh-listener-DH-fClQm.js → gh-listener-Dsx6AmhH.js} +5 -5
  43. package/dist/{index-DF5VmCPJ.d.ts → index-CrngHrne.d.ts} +104 -607
  44. package/dist/index.d.ts +16 -11
  45. package/dist/index.js +509 -973
  46. package/dist/{local-config-json-schema-D8i-BogY.js → local-config-json-schema-DE1zkMcb.js} +12 -8
  47. package/dist/{local-config-sync-Cq39mT6p.d.ts → local-config-sync-B8b04LrZ.d.ts} +21 -16
  48. package/dist/local-config.d.ts +2 -2
  49. package/dist/local-config.js +2 -2
  50. package/dist/{memory-connector-diagnostic-log-COUWCsT_.js → memory-diagnostic-log-BbFVqDzz.js} +30 -95
  51. package/dist/{memory-token-prompter-CKV7VBM5.d.ts → memory-token-prompter-Lo3YRDzq.d.ts} +4 -4
  52. package/dist/{memory-token-prompter-Q7Snwsv2.js → memory-token-prompter-vBXxY20-.js} +2 -2
  53. package/dist/{profiles-f0mNmEyP.d.ts → profiles-EHTeCOqB.d.ts} +3 -2
  54. package/dist/profiles.d.ts +1 -1
  55. package/dist/profiles.js +1 -1
  56. package/dist/recovery.d.ts +2 -0
  57. package/dist/recovery.js +2 -0
  58. package/dist/{resolve-connector-token-BHmZLRrV.js → resolve-connector-token-CczqG_Ig.js} +1 -1
  59. package/dist/{schedule-connector-schema-iCI61gzU.js → schedule-connector-schema-B_xO5z5B.js} +1 -1
  60. package/dist/{schedule-listener-CUyUFFR1.d.ts → schedule-listener-DKh0hnkK.d.ts} +5 -5
  61. package/dist/{schedule-listener-ePAjians.js → schedule-listener-DP9Jhc6U.js} +14 -4
  62. package/dist/settings-reader-CBrgz01o.d.ts +18 -0
  63. package/dist/{settings-reader-BSU6JyvM.d.ts → settings-schema-zhnMIa8I.d.ts} +1 -16
  64. package/dist/{slack-connector-schema-BCNWluHM.js → slack-connector-schema-C1zEf4TG.js} +1 -1
  65. package/dist/{slack-listener-Bv5xI9gC.d.ts → slack-listener-COQA8wAZ.d.ts} +4 -4
  66. package/dist/{slack-listener-ClQuHhEF.js → slack-listener-DUKPcpJH.js} +7 -7
  67. package/dist/{mcp-QeNCBhOD.js → yaml-render-OhUN-qkS.js} +52 -34
  68. package/package.json +21 -1
  69. /package/dist/{file-system-BeOKXjlV.d.ts → file-system-Wub9Nto4.d.ts} +0 -0
  70. /package/dist/{process-runner-DfniuWVU.d.ts → process-runner-D5I_jhYQ.d.ts} +0 -0
  71. /package/dist/{profiles-wMRnjSid.js → profiles-MnXvYfZF.js} +0 -0
@@ -1,10 +1,10 @@
1
- import { t as FunnelConnectorAdapter } from "./connector-adapter-D5Utumgz.js";
2
- import { t as resolveConnectorToken } from "./resolve-connector-token-BHmZLRrV.js";
3
- import { t as FunnelConnectorListener } from "./connector-listener-DU54DN-f.js";
1
+ import { t as FunnelConnectorAdapter } from "./connector-adapter-qwXLjQId.js";
2
+ import { t as resolveConnectorToken } from "./resolve-connector-token-CczqG_Ig.js";
3
+ import { t as FunnelConnectorListener } from "./connector-listener-CpHBecCj.js";
4
4
  import { z } from "zod";
5
5
  import { WebClient } from "@slack/web-api";
6
6
  import { App, LogLevel } from "@slack/bolt";
7
- //#region lib/connectors/slack-adapter.ts
7
+ //#region lib/engine/connectors/slack-adapter.ts
8
8
  const toRecord = (value) => {
9
9
  const result = {};
10
10
  for (const [key, val] of Object.entries(value)) result[key] = val;
@@ -53,7 +53,7 @@ var FunnelSlackAdapter = class extends FunnelConnectorAdapter {
53
53
  }
54
54
  };
55
55
  //#endregion
56
- //#region lib/connectors/minify-slack-event.ts
56
+ //#region lib/engine/connectors/minify-slack-event.ts
57
57
  const TOP_LEVEL_KEYS = [
58
58
  "type",
59
59
  "subtype",
@@ -137,7 +137,7 @@ const minifySlackEvent = (event) => {
137
137
  return minified;
138
138
  };
139
139
  //#endregion
140
- //#region lib/connectors/slack-event-processor.ts
140
+ //#region lib/engine/connectors/slack-event-processor.ts
141
141
  const ALLOWED_EVENTS = new Set(["message", "app_mention"]);
142
142
  const ALLOWED_SUBTYPES = new Set([
143
143
  void 0,
@@ -212,7 +212,7 @@ var FunnelSlackEventProcessor = class {
212
212
  }
213
213
  };
214
214
  //#endregion
215
- //#region lib/connectors/slack-listener.ts
215
+ //#region lib/engine/connectors/slack-listener.ts
216
216
  const middlewareArgsSchema = z.object({ event: z.record(z.string(), z.unknown()).optional() });
217
217
  var FunnelSlackListener = class extends FunnelConnectorListener {
218
218
  config;
@@ -1,8 +1,8 @@
1
- import { n as NodeFunnelProcessRunner } from "./gh-connector-schema-o3Q1-ojL.js";
1
+ import { n as NodeFunnelProcessRunner } from "./gh-connector-schema-DUcZgN2Q.js";
2
2
  import { t as NodeFunnelFileSystem } from "./node-file-system-BcrmWN9I.js";
3
- import { m as NodeFunnelIdGenerator, r as FUNNEL_DIR, s as resolveFunnelPort } from "./gateway-base-url-ssk_He5G.js";
3
+ import { m as NodeFunnelIdGenerator, r as FUNNEL_DIR, s as resolveFunnelPort } from "./gateway-base-url-6foMXfFf.js";
4
4
  import { join } from "node:path";
5
- import { z } from "zod";
5
+ import { stringify } from "yaml";
6
6
  //#region lib/engine/claude/claude.ts
7
7
  const defaultProcess$1 = new NodeFunnelProcessRunner();
8
8
  const defaultIdGenerator = new NodeFunnelIdGenerator();
@@ -167,16 +167,20 @@ var FileProcessGuard = class {
167
167
  const FUNNEL_MCP_COMMAND = "bun";
168
168
  const FUNNEL_MCP_ARGS = ["funnel", "mcp"];
169
169
  const FUNNEL_MCP_NAME = "funnel";
170
- const mcpEntrySchema = z.object({
171
- command: z.string().optional(),
172
- args: z.array(z.string()).optional()
173
- });
174
- const mcpConfigSchema = z.object({ mcpServers: z.record(z.string(), mcpEntrySchema).optional() });
175
170
  const defaultFs = new NodeFunnelFileSystem();
171
+ const isRecord = (value) => {
172
+ return typeof value === "object" && value !== null && !Array.isArray(value);
173
+ };
176
174
  /**
177
175
  * Installs/uninstalls the funnel MCP entry into a target repository's
178
176
  * `.mcp.json`. Detects an existing entry by command match so renaming is
179
177
  * preserved across re-installs.
178
+ *
179
+ * The raw JSON object is mutated and written back untouched apart from the
180
+ * funnel entry — third-party server fields (`type`, `url`, `env`, `headers`, …)
181
+ * and unrelated top-level keys are preserved verbatim. Never round-trip the
182
+ * file through a narrowing schema: that silently strips every key it does not
183
+ * declare, corrupting other MCP servers.
180
184
  */
181
185
  var FunnelMcp = class {
182
186
  fs;
@@ -187,46 +191,40 @@ var FunnelMcp = class {
187
191
  install(repoPath) {
188
192
  if (!this.fs.existsSync(repoPath)) throw new Error(`repository does not exist: ${repoPath}`);
189
193
  const config = this.readConfig(repoPath);
190
- const servers = config.mcpServers ?? {};
194
+ const existing = config.mcpServers;
195
+ const servers = isRecord(existing) ? existing : {};
191
196
  const targetName = this.findServerName(servers) ?? "funnel";
192
197
  servers[targetName] = {
193
198
  command: "bun",
194
199
  args: FUNNEL_MCP_ARGS
195
200
  };
196
- this.writeConfig(repoPath, {
197
- ...config,
198
- mcpServers: servers
199
- });
201
+ config.mcpServers = servers;
202
+ this.writeConfig(repoPath, config);
200
203
  }
201
204
  uninstall(repoPath) {
202
205
  if (!this.fs.existsSync(repoPath)) return;
203
206
  const config = this.readConfig(repoPath);
204
- const servers = config.mcpServers ?? {};
207
+ const servers = config.mcpServers;
208
+ if (!isRecord(servers)) return;
205
209
  const name = this.findServerName(servers);
206
210
  if (!name) return;
207
- const next = { ...servers };
208
- delete next[name];
209
- this.writeConfig(repoPath, {
210
- ...config,
211
- mcpServers: next
212
- });
211
+ delete servers[name];
212
+ this.writeConfig(repoPath, config);
213
213
  }
214
214
  findInstalledName(cwd) {
215
- const config = this.readConfig(cwd);
216
- return this.findServerName(config.mcpServers ?? {});
215
+ const servers = this.readConfig(cwd).mcpServers;
216
+ return isRecord(servers) ? this.findServerName(servers) : null;
217
217
  }
218
218
  findServerName(servers) {
219
- for (const entry of Object.entries(servers)) {
220
- const name = entry[0];
221
- const value = entry[1];
222
- if (this.isFunnelEntry(value)) return name;
223
- }
219
+ for (const entry of Object.entries(servers)) if (this.isFunnelEntry(entry[1])) return entry[0];
224
220
  return null;
225
221
  }
226
222
  isFunnelEntry(value) {
227
- if (!value) return false;
228
- if (value.command === "bun" && value.args?.[0] === "funnel") return true;
229
- if (value.command === "funnel") return true;
223
+ if (!isRecord(value)) return false;
224
+ const command = value.command;
225
+ const args = value.args;
226
+ if (command === "bun" && Array.isArray(args) && args[0] === "funnel") return true;
227
+ if (command === "funnel") return true;
230
228
  return false;
231
229
  }
232
230
  readConfig(repoPath) {
@@ -240,9 +238,8 @@ var FunnelMcp = class {
240
238
  } catch (error) {
241
239
  throw new Error(`invalid .mcp.json (${mcpPath}): ${error instanceof Error ? error.message : String(error)}`);
242
240
  }
243
- const result = mcpConfigSchema.safeParse(parsed);
244
- if (!result.success) throw new Error(`invalid .mcp.json (${mcpPath}): ${result.error.message}`);
245
- return result.data;
241
+ if (!isRecord(parsed)) throw new Error(`invalid .mcp.json (${mcpPath}): expected a JSON object`);
242
+ return parsed;
246
243
  }
247
244
  writeConfig(repoPath, config) {
248
245
  const mcpPath = join(repoPath, ".mcp.json");
@@ -250,4 +247,25 @@ var FunnelMcp = class {
250
247
  }
251
248
  };
252
249
  //#endregion
253
- export { FileProcessGuard as a, FunnelMcp as i, FUNNEL_MCP_COMMAND as n, FunnelClaude as o, FUNNEL_MCP_NAME as r, FUNNEL_MCP_ARGS as t };
250
+ //#region lib/cli/yaml-render.ts
251
+ /**
252
+ * Render any value as a valid YAML document for CLI output.
253
+ *
254
+ * The CLI never emits JSON: text and YAML are the two surfaces, and YAML
255
+ * subsumes both since plain strings round-trip as themselves. This keeps
256
+ * Claude's job simple — every command's output is parseable the same way.
257
+ *
258
+ * Numbers, booleans, null, and primitive arrays stringify trivially. For
259
+ * objects we use blocks (indent + dash) rather than flow (`{...}`), since
260
+ * indentation is what Claude actually reads.
261
+ */
262
+ const renderYaml = (value) => {
263
+ if (typeof value === "string") return value;
264
+ return stringify(value, {
265
+ indent: 2,
266
+ lineWidth: 0,
267
+ defaultStringType: "PLAIN"
268
+ });
269
+ };
270
+ //#endregion
271
+ export { FunnelMcp as a, FUNNEL_MCP_NAME as i, FUNNEL_MCP_ARGS as n, FileProcessGuard as o, FUNNEL_MCP_COMMAND as r, FunnelClaude as s, renderYaml as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@interactive-inc/claude-funnel",
3
- "version": "0.53.0",
3
+ "version": "0.56.0",
4
4
  "description": "Hub CLI that routes external events (Slack / GitHub / Discord) to Claude Code agents through subscription channels over MCP.",
5
5
  "keywords": [
6
6
  "bun",
@@ -62,6 +62,26 @@
62
62
  "import": "./dist/local-config.js",
63
63
  "default": "./dist/local-config.js"
64
64
  },
65
+ "./diagnostics": {
66
+ "types": "./dist/diagnostics.d.ts",
67
+ "import": "./dist/diagnostics.js",
68
+ "default": "./dist/diagnostics.js"
69
+ },
70
+ "./recovery": {
71
+ "types": "./dist/recovery.d.ts",
72
+ "import": "./dist/recovery.js",
73
+ "default": "./dist/recovery.js"
74
+ },
75
+ "./doctor": {
76
+ "types": "./dist/doctor.d.ts",
77
+ "import": "./dist/doctor.js",
78
+ "default": "./dist/doctor.js"
79
+ },
80
+ "./docs": {
81
+ "types": "./dist/docs.d.ts",
82
+ "import": "./dist/docs.js",
83
+ "default": "./dist/docs.js"
84
+ },
65
85
  "./connectors/slack": {
66
86
  "types": "./dist/connectors/slack.d.ts",
67
87
  "import": "./dist/connectors/slack.js",