@interactive-inc/claude-funnel 0.52.0 → 0.55.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/README.md +25 -3
- package/dist/bin.js +1276 -520
- package/dist/claude.d.ts +22 -5
- package/dist/claude.js +456 -169
- package/dist/connector-adapter-1PxjN-Uk.d.ts +25 -0
- package/dist/{connector-adapter-D5Utumgz.js → connector-adapter-qwXLjQId.js} +1 -1
- package/dist/{connector-listener-DU54DN-f.js → connector-listener-CpHBecCj.js} +1 -1
- package/dist/connectors/discord.d.ts +6 -6
- package/dist/connectors/discord.js +2 -2
- package/dist/connectors/gh.d.ts +6 -6
- package/dist/connectors/gh.js +2 -2
- package/dist/connectors/schedule.d.ts +12 -2
- package/dist/connectors/schedule.js +2 -2
- package/dist/connectors/slack.d.ts +3 -3
- package/dist/connectors/slack.js +2 -2
- package/dist/{connector-diagnostic-log-yTOojKUR.d.ts → diagnostic-log-Bxe7Bbvw.d.ts} +2 -2
- package/dist/diagnostic-sql-reader-CzYgZpq2.js +83 -0
- package/dist/diagnostics.d.ts +2 -0
- package/dist/diagnostics.js +2 -0
- package/dist/{discord-connector-schema-CBDyGdOI.js → discord-connector-schema-B_N6IXLz.js} +1 -1
- package/dist/{discord-connector-schema-R0Uu-3ns.d.ts → discord-connector-schema-CPgcZkXh.d.ts} +1 -1
- package/dist/{discord-listener-_jSE3HsQ.js → discord-listener-C0MoKdQO.js} +6 -6
- package/dist/docs.d.ts +2 -0
- package/dist/docs.js +2 -0
- package/dist/doctor.d.ts +2 -0
- package/dist/doctor.js +2 -0
- package/dist/{file-process-guard-BgrVHe9I.d.ts → file-process-guard-DI1742H5.d.ts} +31 -15
- package/dist/funnel-diagnostics-BpKYrMSu.js +300 -0
- package/dist/funnel-diagnostics-qWy5tPSq.d.ts +176 -0
- package/dist/funnel-docs-dXPokzr5.d.ts +18 -0
- package/dist/funnel-docs-ng5K8w4j.js +653 -0
- package/dist/funnel-doctor-BF3Rdgk0.d.ts +34 -0
- package/dist/funnel-doctor-CApCezTq.js +82 -0
- package/dist/funnel-recovery-BUBsu7WX.d.ts +101 -0
- package/dist/funnel-recovery-D9CxD5Zs.js +134 -0
- package/dist/gateway/daemon.js +810 -211
- package/dist/{settings-store-D2XSXTyt.js → gateway-base-url-6foMXfFf.js} +19 -6
- package/dist/gateway.d.ts +3 -3
- package/dist/gateway.js +3 -2
- package/dist/{gh-connector-schema-eoTtHbY6.d.ts → gh-connector-schema-CU1ojfIF.d.ts} +1 -1
- package/dist/{gh-connector-schema-o3Q1-ojL.js → gh-connector-schema-DUcZgN2Q.js} +1 -1
- package/dist/{gh-listener-DH-fClQm.js → gh-listener-Dsx6AmhH.js} +5 -5
- package/dist/{index-NFs2jzCa.d.ts → index-CrngHrne.d.ts} +187 -619
- package/dist/index.d.ts +16 -11
- package/dist/index.js +512 -976
- package/dist/{local-config-json-schema-8IHjS4Q7.js → local-config-json-schema-DE1zkMcb.js} +35 -9
- package/dist/{local-config-sync-BdsrDZOu.d.ts → local-config-sync-B8b04LrZ.d.ts} +45 -25
- package/dist/local-config.d.ts +2 -2
- package/dist/local-config.js +2 -2
- package/dist/{memory-connector-diagnostic-log-CrW1ltLM.js → memory-diagnostic-log-BZ1VD80X.js} +61 -99
- package/dist/{memory-token-prompter-B5FFCsGP.d.ts → memory-token-prompter-Lo3YRDzq.d.ts} +4 -4
- package/dist/{memory-token-prompter-CLerGsgM.js → memory-token-prompter-vBXxY20-.js} +2 -2
- package/dist/{profiles-f0mNmEyP.d.ts → profiles-EHTeCOqB.d.ts} +3 -2
- package/dist/profiles.d.ts +1 -1
- package/dist/profiles.js +1 -1
- package/dist/recovery.d.ts +2 -0
- package/dist/recovery.js +2 -0
- package/dist/{resolve-connector-token-BHmZLRrV.js → resolve-connector-token-CczqG_Ig.js} +1 -1
- package/dist/{schedule-connector-schema-iCI61gzU.js → schedule-connector-schema-B_xO5z5B.js} +1 -1
- package/dist/{schedule-listener-CUyUFFR1.d.ts → schedule-listener-DKh0hnkK.d.ts} +5 -5
- package/dist/{schedule-listener-ePAjians.js → schedule-listener-DP9Jhc6U.js} +14 -4
- package/dist/settings-reader-CBrgz01o.d.ts +18 -0
- package/dist/{settings-reader-BSU6JyvM.d.ts → settings-schema-zhnMIa8I.d.ts} +1 -16
- package/dist/{slack-connector-schema-BCNWluHM.js → slack-connector-schema-C1zEf4TG.js} +1 -1
- package/dist/{slack-listener-Bv5xI9gC.d.ts → slack-listener-COQA8wAZ.d.ts} +4 -4
- package/dist/{slack-listener-ClQuHhEF.js → slack-listener-DUKPcpJH.js} +7 -7
- package/dist/{mcp-Dr-nIBwN.js → yaml-render-OhUN-qkS.js} +52 -34
- package/package.json +21 -1
- package/dist/connector-adapter-DKgsVuMH.d.ts +0 -11
- /package/dist/{file-system-BeOKXjlV.d.ts → file-system-Wub9Nto4.d.ts} +0 -0
- /package/dist/{process-runner-DfniuWVU.d.ts → process-runner-D5I_jhYQ.d.ts} +0 -0
- /package/dist/{profiles-wMRnjSid.js → profiles-MnXvYfZF.js} +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { S as FunnelLogger, b as FunnelConnectorListener, o as ConnectorDiagnosticLog, x as NotifyFn } from "./
|
|
2
|
-
import { n as FunnelFileSystem } from "./file-system-
|
|
1
|
+
import { S as FunnelLogger, b as FunnelConnectorListener, o as ConnectorDiagnosticLog, x as NotifyFn } from "./diagnostic-log-Bxe7Bbvw.js";
|
|
2
|
+
import { n as FunnelFileSystem } from "./file-system-Wub9Nto4.js";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
|
|
5
|
-
//#region lib/connectors/schedule-state-store.d.ts
|
|
5
|
+
//#region lib/engine/connectors/schedule-state-store.d.ts
|
|
6
6
|
type Deps$1 = {
|
|
7
7
|
path: string;
|
|
8
8
|
fs?: FunnelFileSystem;
|
|
@@ -21,7 +21,7 @@ declare class ScheduleStateStore {
|
|
|
21
21
|
save(state: Map<string, Date>): void;
|
|
22
22
|
}
|
|
23
23
|
//#endregion
|
|
24
|
-
//#region lib/connectors/schedule-connector-schema.d.ts
|
|
24
|
+
//#region lib/engine/connectors/schedule-connector-schema.d.ts
|
|
25
25
|
/**
|
|
26
26
|
* Catch-up behavior when the daemon was down past one or more matching minutes.
|
|
27
27
|
*
|
|
@@ -67,7 +67,7 @@ declare const scheduleConnectorSchema: z.ZodObject<{
|
|
|
67
67
|
}, z.core.$strip>;
|
|
68
68
|
type ScheduleConnectorConfig = z.infer<typeof scheduleConnectorSchema>;
|
|
69
69
|
//#endregion
|
|
70
|
-
//#region lib/connectors/schedule-listener.d.ts
|
|
70
|
+
//#region lib/engine/connectors/schedule-listener.d.ts
|
|
71
71
|
type ScheduleOnFired = (entry: ScheduleEntry, firedAt: Date) => void | Promise<void>;
|
|
72
72
|
type Deps = {
|
|
73
73
|
config: ScheduleConnectorConfig;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { t as FunnelConnectorListener } from "./connector-listener-
|
|
1
|
+
import { t as FunnelConnectorListener } from "./connector-listener-CpHBecCj.js";
|
|
2
2
|
import { t as NodeFunnelFileSystem } from "./node-file-system-BcrmWN9I.js";
|
|
3
3
|
import { dirname } from "node:path";
|
|
4
|
-
//#region lib/connectors/match-cron.ts
|
|
4
|
+
//#region lib/engine/connectors/match-cron.ts
|
|
5
5
|
const parseField = (expr, min, max) => {
|
|
6
6
|
const values = /* @__PURE__ */ new Set();
|
|
7
7
|
for (const part of expr.split(",")) {
|
|
@@ -35,6 +35,16 @@ const parseField = (expr, min, max) => {
|
|
|
35
35
|
values
|
|
36
36
|
};
|
|
37
37
|
};
|
|
38
|
+
/**
|
|
39
|
+
* Returns true when `date` (local time) satisfies a 5-field cron expression.
|
|
40
|
+
*
|
|
41
|
+
* Two deliberate deviations from Vixie cron, called out so schedules are not
|
|
42
|
+
* written expecting the other behavior:
|
|
43
|
+
* - Day-of-month and day-of-week are ANDed, not ORed. Vixie cron fires when
|
|
44
|
+
* EITHER matches once both are restricted; here every field must match.
|
|
45
|
+
* - Day-of-week is 0-6 (Sunday=0). `7` for Sunday is NOT accepted (it throws
|
|
46
|
+
* as out-of-range); use `0`.
|
|
47
|
+
*/
|
|
38
48
|
const matchCron = (expr, date) => {
|
|
39
49
|
const parts = expr.trim().split(/\s+/);
|
|
40
50
|
if (parts.length !== 5) throw new Error(`cron must have 5 fields (got ${parts.length}): "${expr}"`);
|
|
@@ -66,7 +76,7 @@ const matchCron = (expr, date) => {
|
|
|
66
76
|
return true;
|
|
67
77
|
};
|
|
68
78
|
//#endregion
|
|
69
|
-
//#region lib/connectors/schedule-state-store.ts
|
|
79
|
+
//#region lib/engine/connectors/schedule-state-store.ts
|
|
70
80
|
const defaultFs = new NodeFunnelFileSystem();
|
|
71
81
|
/**
|
|
72
82
|
* Per-connector lastFiredAt persistence for the schedule listener. The path is
|
|
@@ -98,7 +108,7 @@ var ScheduleStateStore = class {
|
|
|
98
108
|
}
|
|
99
109
|
};
|
|
100
110
|
//#endregion
|
|
101
|
-
//#region lib/connectors/schedule-listener.ts
|
|
111
|
+
//#region lib/engine/connectors/schedule-listener.ts
|
|
102
112
|
const MAX_CATCHUP_MINUTES = 1440;
|
|
103
113
|
var FunnelScheduleListener = class extends FunnelConnectorListener {
|
|
104
114
|
config;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { a as Settings } from "./settings-schema-zhnMIa8I.js";
|
|
2
|
+
|
|
3
|
+
//#region lib/engine/id/id-generator.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* ID generator boundary. Default NodeFunnelIdGenerator wraps `crypto.randomUUID()`;
|
|
6
|
+
* MemoryFunnelIdGenerator emits `<prefix>-1, <prefix>-2, ...` for deterministic tests.
|
|
7
|
+
*/
|
|
8
|
+
declare abstract class FunnelIdGenerator {
|
|
9
|
+
abstract generate(): string;
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region lib/engine/settings/settings-reader.d.ts
|
|
13
|
+
declare abstract class FunnelSettingsReader {
|
|
14
|
+
abstract read(): Settings;
|
|
15
|
+
abstract write(settings: Settings): void;
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { FunnelIdGenerator as n, FunnelSettingsReader as t };
|
|
@@ -149,19 +149,4 @@ declare const settingsSchema: z.ZodObject<{
|
|
|
149
149
|
}, z.core.$strip>;
|
|
150
150
|
type Settings = z.infer<typeof settingsSchema>;
|
|
151
151
|
//#endregion
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* ID generator boundary. Default NodeFunnelIdGenerator wraps `crypto.randomUUID()`;
|
|
155
|
-
* MemoryFunnelIdGenerator emits `<prefix>-1, <prefix>-2, ...` for deterministic tests.
|
|
156
|
-
*/
|
|
157
|
-
declare abstract class FunnelIdGenerator {
|
|
158
|
-
abstract generate(): string;
|
|
159
|
-
}
|
|
160
|
-
//#endregion
|
|
161
|
-
//#region lib/engine/settings/settings-reader.d.ts
|
|
162
|
-
declare abstract class FunnelSettingsReader {
|
|
163
|
-
abstract read(): Settings;
|
|
164
|
-
abstract write(settings: Settings): void;
|
|
165
|
-
}
|
|
166
|
-
//#endregion
|
|
167
|
-
export { ProfileConfig as a, channelConfigSchema as c, settingsSchema as d, ChannelDeliveryMode as i, channelDeliveryModeSchema as l, FunnelIdGenerator as n, SETTINGS_VERSION as o, ChannelConfig as r, Settings as s, FunnelSettingsReader as t, profileConfigSchema as u };
|
|
152
|
+
export { Settings as a, profileConfigSchema as c, SETTINGS_VERSION as i, settingsSchema as l, ChannelDeliveryMode as n, channelConfigSchema as o, ProfileConfig as r, channelDeliveryModeSchema as s, ChannelConfig as t };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { S as FunnelLogger, b as FunnelConnectorListener, o as ConnectorDiagnosticLog, x as NotifyFn } from "./
|
|
1
|
+
import { S as FunnelLogger, b as FunnelConnectorListener, o as ConnectorDiagnosticLog, x as NotifyFn } from "./diagnostic-log-Bxe7Bbvw.js";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { App } from "@slack/bolt";
|
|
4
4
|
|
|
5
|
-
//#region lib/connectors/slack-event-processor.d.ts
|
|
5
|
+
//#region lib/engine/connectors/slack-event-processor.d.ts
|
|
6
6
|
type SlackRawEvent = Record<string, unknown>;
|
|
7
7
|
/**
|
|
8
8
|
* Why the processor dropped an event. Mirrored verbatim into the diagnostic
|
|
@@ -41,7 +41,7 @@ declare class FunnelSlackEventProcessor {
|
|
|
41
41
|
process(event: SlackRawEvent): SlackProcessed;
|
|
42
42
|
}
|
|
43
43
|
//#endregion
|
|
44
|
-
//#region lib/connectors/slack-connector-schema.d.ts
|
|
44
|
+
//#region lib/engine/connectors/slack-connector-schema.d.ts
|
|
45
45
|
/**
|
|
46
46
|
* A slack connector resolves its tokens one of two ways, set at sync time:
|
|
47
47
|
*
|
|
@@ -70,7 +70,7 @@ declare const slackConnectorSchema: z.ZodObject<{
|
|
|
70
70
|
}, z.core.$strip>;
|
|
71
71
|
type SlackConnectorConfig = z.infer<typeof slackConnectorSchema>;
|
|
72
72
|
//#endregion
|
|
73
|
-
//#region lib/connectors/slack-listener.d.ts
|
|
73
|
+
//#region lib/engine/connectors/slack-listener.d.ts
|
|
74
74
|
type SlackOnAppCreated = (app: App) => void | Promise<void>;
|
|
75
75
|
type SlackPreprocessEvent = (event: SlackRawEvent) => SlackRawEvent | null;
|
|
76
76
|
type Deps = {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { t as FunnelConnectorAdapter } from "./connector-adapter-
|
|
2
|
-
import { t as resolveConnectorToken } from "./resolve-connector-token-
|
|
3
|
-
import { t as FunnelConnectorListener } from "./connector-listener-
|
|
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-
|
|
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 {
|
|
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 {
|
|
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
|
|
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
|
-
|
|
197
|
-
|
|
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
|
-
|
|
208
|
-
|
|
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
|
|
216
|
-
return this.findServerName(
|
|
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
|
-
|
|
229
|
-
|
|
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
|
-
|
|
244
|
-
|
|
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
|
-
|
|
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.
|
|
3
|
+
"version": "0.55.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",
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
//#region lib/connectors/connector-adapter.d.ts
|
|
2
|
-
type CallInput = {
|
|
3
|
-
method: string;
|
|
4
|
-
path: string;
|
|
5
|
-
body?: unknown;
|
|
6
|
-
};
|
|
7
|
-
declare abstract class FunnelConnectorAdapter {
|
|
8
|
-
abstract call(input: CallInput): Promise<unknown>;
|
|
9
|
-
}
|
|
10
|
-
//#endregion
|
|
11
|
-
export { FunnelConnectorAdapter as n, CallInput as t };
|
|
File without changes
|
|
File without changes
|
|
File without changes
|