@interactive-inc/claude-funnel 0.49.0 → 0.51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +1 -1
- package/dist/claude-CB1WkV77.d.ts +115 -0
- package/dist/claude.d.ts +59 -0
- package/dist/claude.js +322 -0
- package/dist/{connector-diagnostic-log-OPpPi9V9.d.ts → connector-diagnostic-log-yTOojKUR.d.ts} +14 -14
- package/dist/{logger-Czli2OKh.js → connector-listener-DU54DN-f.js} +1 -9
- package/dist/connectors/discord.d.ts +3 -3
- package/dist/connectors/discord.js +2 -1
- package/dist/connectors/gh.d.ts +4 -3
- package/dist/connectors/gh.js +2 -1
- package/dist/connectors/schedule.d.ts +1 -1
- package/dist/connectors/schedule.js +2 -1
- package/dist/connectors/slack.d.ts +2 -2
- package/dist/connectors/slack.js +2 -1
- package/dist/discord-connector-schema-CBDyGdOI.js +21 -0
- package/dist/{discord-connector-schema-BeThExJp.js → discord-listener-_jSE3HsQ.js} +2 -22
- package/dist/file-system-BeOKXjlV.d.ts +26 -0
- package/dist/file-system-PWKKU7lA.js +9 -0
- package/dist/gateway.d.ts +3 -0
- package/dist/gateway.js +2 -0
- package/dist/gh-connector-schema-eoTtHbY6.d.ts +14 -0
- package/dist/{gh-connector-schema-eYE4g77K.js → gh-connector-schema-o3Q1-ojL.js} +1 -176
- package/dist/gh-listener-DH-fClQm.js +178 -0
- package/dist/index-BM0-f6KL.d.ts +3404 -0
- package/dist/index.d.ts +11 -4083
- package/dist/index.js +247 -3459
- package/dist/local-config-json-schema-8IHjS4Q7.js +439 -0
- package/dist/local-config-sync-BdsrDZOu.d.ts +381 -0
- package/dist/local-config.d.ts +3 -0
- package/dist/local-config.js +3 -0
- package/dist/logger-BP6SisKt.js +9 -0
- package/dist/mcp-Dr-nIBwN.js +253 -0
- package/dist/memory-connector-diagnostic-log-CrW1ltLM.js +2245 -0
- package/dist/memory-token-prompter-B5FFCsGP.d.ts +57 -0
- package/dist/memory-token-prompter-CLerGsgM.js +61 -0
- package/dist/node-file-system-BcrmWN9I.js +48 -0
- package/dist/{gh-connector-schema-CQmEWzdV.d.ts → process-runner-DfniuWVU.d.ts} +1 -14
- package/dist/profiles-f0mNmEyP.d.ts +64 -0
- package/dist/profiles-wMRnjSid.js +129 -0
- package/dist/profiles.d.ts +2 -0
- package/dist/profiles.js +2 -0
- package/dist/schedule-connector-schema-iCI61gzU.js +31 -0
- package/dist/{schedule-listener-3M6WkH1Y.d.ts → schedule-listener-CUyUFFR1.d.ts} +22 -46
- package/dist/{schedule-connector-schema-CM-sRkac.js → schedule-listener-ePAjians.js} +3 -86
- package/dist/settings-reader-BSU6JyvM.d.ts +167 -0
- package/dist/settings-reader-DPqrpV7s.js +11 -0
- package/dist/settings-store-D2XSXTyt.js +186 -0
- package/dist/slack-connector-schema-BCNWluHM.js +32 -0
- package/dist/{slack-listener-9UdAn_ui.d.ts → slack-listener-Bv5xI9gC.d.ts} +31 -31
- package/dist/{slack-connector-schema-DDbSGPZn.js → slack-listener-ClQuHhEF.js} +2 -32
- package/package.json +6 -1
- /package/dist/{connector-adapter-VA6undzc.d.ts → connector-adapter-DKgsVuMH.d.ts} +0 -0
- /package/dist/{discord-connector-schema-DF4pL3Sc.d.ts → discord-connector-schema-R0Uu-3ns.d.ts} +0 -0
package/dist/claude.js
ADDED
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
import { d as settingsSchema, o as resolveFunnelPort } from "./settings-store-D2XSXTyt.js";
|
|
2
|
+
import { a as FileProcessGuard, i as FunnelMcp, n as FUNNEL_MCP_COMMAND, o as FunnelClaude, r as FUNNEL_MCP_NAME, t as FUNNEL_MCP_ARGS } from "./mcp-Dr-nIBwN.js";
|
|
3
|
+
import { a as FunnelLocalConfig, c as connectorSpecSchema, i as FunnelTokenPrompter, l as localConfigSchema, n as NodeFunnelTokenPrompter, o as LOCAL_CONFIG_FILENAME, r as FunnelLocalConfigSync, s as channelSpecSchema, t as funnelJsonSchema, u as profileSpecSchema } from "./local-config-json-schema-8IHjS4Q7.js";
|
|
4
|
+
import { t as FunnelProfiles } from "./profiles-wMRnjSid.js";
|
|
5
|
+
import { n as FunnelLocalConfigWriter, t as MemoryFunnelTokenPrompter } from "./memory-token-prompter-CLerGsgM.js";
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
8
|
+
import { homedir } from "node:os";
|
|
9
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
10
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
11
|
+
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
12
|
+
//#region lib/engine/mcp/channel-subscriber.ts
|
|
13
|
+
const RECONNECT_DELAY = 1e3;
|
|
14
|
+
const MAX_RECONNECT_DELAY = 1e4;
|
|
15
|
+
/**
|
|
16
|
+
* Subscribes to the gateway WebSocket for a single channel and forwards
|
|
17
|
+
* incoming events to the MCP server as `notifications/claude/channel`.
|
|
18
|
+
* Reconnects with exponential backoff and replays missed events via `?since=<offset>`.
|
|
19
|
+
*/
|
|
20
|
+
var FunnelChannelSubscriber = class {
|
|
21
|
+
state = {
|
|
22
|
+
reconnectDelay: RECONNECT_DELAY,
|
|
23
|
+
lastOffset: 0
|
|
24
|
+
};
|
|
25
|
+
constructor(props) {
|
|
26
|
+
this.props = props;
|
|
27
|
+
Object.freeze(this);
|
|
28
|
+
}
|
|
29
|
+
start() {
|
|
30
|
+
this.connect();
|
|
31
|
+
}
|
|
32
|
+
connect() {
|
|
33
|
+
const sinceQuery = this.state.lastOffset > 0 ? `&since=${this.state.lastOffset}` : "";
|
|
34
|
+
const wsUrl = `${this.props.baseUrl}${sinceQuery}`;
|
|
35
|
+
const ws = new WebSocket(wsUrl, this.props.protocols);
|
|
36
|
+
ws.addEventListener("open", () => {
|
|
37
|
+
this.state.reconnectDelay = RECONNECT_DELAY;
|
|
38
|
+
process.stderr.write(`funnel: connected (${wsUrl})\n`);
|
|
39
|
+
});
|
|
40
|
+
ws.addEventListener("message", (event) => this.handleMessage(event));
|
|
41
|
+
ws.addEventListener("close", () => {
|
|
42
|
+
process.stderr.write(`funnel: disconnected, reconnecting in ${this.state.reconnectDelay}ms\n`);
|
|
43
|
+
setTimeout(() => this.connect(), this.state.reconnectDelay);
|
|
44
|
+
this.state.reconnectDelay = Math.min(this.state.reconnectDelay * 2, MAX_RECONNECT_DELAY);
|
|
45
|
+
});
|
|
46
|
+
ws.addEventListener("error", () => {});
|
|
47
|
+
}
|
|
48
|
+
async handleMessage(event) {
|
|
49
|
+
try {
|
|
50
|
+
const payload = JSON.parse(String(event.data));
|
|
51
|
+
const eventType = payload.meta?.event_type ?? "unknown";
|
|
52
|
+
if (typeof payload.offset === "number" && payload.offset > this.state.lastOffset) this.state.lastOffset = payload.offset;
|
|
53
|
+
process.stderr.write(`funnel: received event (${eventType})\n`);
|
|
54
|
+
await this.props.server.notification({
|
|
55
|
+
method: "notifications/claude/channel",
|
|
56
|
+
params: {
|
|
57
|
+
content: payload.content,
|
|
58
|
+
meta: payload.meta
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
} catch (error) {
|
|
62
|
+
process.stderr.write(`funnel: error: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
//#endregion
|
|
67
|
+
//#region lib/engine/mcp/read-channel-connectors.ts
|
|
68
|
+
const TOOL_CONNECTOR_TYPES = new Set([
|
|
69
|
+
"slack",
|
|
70
|
+
"gh",
|
|
71
|
+
"discord"
|
|
72
|
+
]);
|
|
73
|
+
const readChannelConnectors = (dir, channelId) => {
|
|
74
|
+
const settingsPath = join(dir, "settings.json");
|
|
75
|
+
if (!existsSync(settingsPath)) return null;
|
|
76
|
+
const raw = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
77
|
+
const parsed = settingsSchema.safeParse(raw);
|
|
78
|
+
if (!parsed.success) return null;
|
|
79
|
+
const channel = parsed.data.channels.find((c) => c.id === channelId);
|
|
80
|
+
if (!channel) return null;
|
|
81
|
+
const connectors = channel.connectors.filter((c) => TOOL_CONNECTOR_TYPES.has(c.type)).map((c) => ({
|
|
82
|
+
name: c.name,
|
|
83
|
+
type: c.type
|
|
84
|
+
}));
|
|
85
|
+
return {
|
|
86
|
+
channelName: channel.name,
|
|
87
|
+
connectors
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
//#endregion
|
|
91
|
+
//#region lib/engine/mcp/read-gateway-token.ts
|
|
92
|
+
const readGatewayToken = (dir) => {
|
|
93
|
+
const fromEnv = process.env.FUNNEL_GATEWAY_TOKEN;
|
|
94
|
+
if (fromEnv && fromEnv.length > 0) return fromEnv;
|
|
95
|
+
const path = join(dir, "gateway.token");
|
|
96
|
+
if (!existsSync(path)) return null;
|
|
97
|
+
const value = readFileSync(path, "utf-8").trim();
|
|
98
|
+
return value.length > 0 ? value : null;
|
|
99
|
+
};
|
|
100
|
+
//#endregion
|
|
101
|
+
//#region lib/engine/mcp/usage-hint-for-type.ts
|
|
102
|
+
const usageHintForType = (type) => {
|
|
103
|
+
if (type === "slack") return [
|
|
104
|
+
"Slack Web API.",
|
|
105
|
+
"To reply in the same thread: method=POST path=chat.postMessage body={ channel: meta.channel_id, text: \"...\", thread_ts: meta.thread_ts }",
|
|
106
|
+
"To react: method=POST path=reactions.add body={ channel: meta.channel_id, timestamp: meta.thread_ts, name: \"thumbsup\" }",
|
|
107
|
+
"Use meta fields from the incoming event: channel_id (Slack channel), thread_ts (thread anchor), user_id (sender)."
|
|
108
|
+
].join(" ");
|
|
109
|
+
if (type === "discord") return [
|
|
110
|
+
"Discord REST API.",
|
|
111
|
+
"To reply: method=POST path=/channels/<meta.channel_id>/messages body={ content: \"...\" }",
|
|
112
|
+
"Use meta fields: channel_id (Discord channel), user_id (sender), guild_id."
|
|
113
|
+
].join(" ");
|
|
114
|
+
if (type === "gh") return [
|
|
115
|
+
"GitHub REST via gh CLI.",
|
|
116
|
+
"To comment: method=POST path=repos/<meta.repository>/issues/<number>/comments body={ body: \"...\" }",
|
|
117
|
+
"Parse <number> from meta.subject_url. meta fields: repository (owner/repo), subject_type, subject_url, reason."
|
|
118
|
+
].join(" ");
|
|
119
|
+
return "Generic adapter call.";
|
|
120
|
+
};
|
|
121
|
+
//#endregion
|
|
122
|
+
//#region lib/engine/mcp/channel-server.ts
|
|
123
|
+
const DEFAULT_FUNNEL_DIR = join(homedir(), ".funnel");
|
|
124
|
+
const BUILTIN_TOOL_NAMES = ["fnl_status", "fnl_debug"];
|
|
125
|
+
const isBuiltinTool = (name) => BUILTIN_TOOL_NAMES.includes(name);
|
|
126
|
+
const readAllChannels = (dir) => {
|
|
127
|
+
const settingsPath = join(dir, "settings.json");
|
|
128
|
+
if (!existsSync(settingsPath)) return [];
|
|
129
|
+
try {
|
|
130
|
+
const raw = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
131
|
+
const parsed = settingsSchema.safeParse(raw);
|
|
132
|
+
if (!parsed.success) return [];
|
|
133
|
+
return parsed.data.channels.map((c) => ({
|
|
134
|
+
id: c.id,
|
|
135
|
+
name: c.name
|
|
136
|
+
}));
|
|
137
|
+
} catch {
|
|
138
|
+
return [];
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
const startChannelServer = async (options = {}) => {
|
|
142
|
+
const dir = options.dir ?? DEFAULT_FUNNEL_DIR;
|
|
143
|
+
const gatewayBaseUrl = options.gatewayUrl ?? process.env.FUNNEL_GATEWAY_URL ?? `http://127.0.0.1:${resolveFunnelPort()}`;
|
|
144
|
+
const gatewayWsUrl = `${gatewayBaseUrl.replace(/^http/, "ws")}/ws`;
|
|
145
|
+
const channelId = options.channelId ?? process.env.FUNNEL_CHANNEL_ID;
|
|
146
|
+
const channel = channelId ? readChannelConnectors(dir, channelId) : null;
|
|
147
|
+
const token = options.token ?? readGatewayToken(dir);
|
|
148
|
+
const allChannels = readAllChannels(dir);
|
|
149
|
+
const currentChannelName = channel?.channelName ?? null;
|
|
150
|
+
const channelContext = allChannels.length > 0 ? [
|
|
151
|
+
"",
|
|
152
|
+
"Configured channels (use as the `channel` argument to fnl_debug):",
|
|
153
|
+
...allChannels.map((ch) => ` ${ch.name}${ch.name === currentChannelName ? " ← this session" : ""}`)
|
|
154
|
+
].join("\n") : "";
|
|
155
|
+
const server = new Server({
|
|
156
|
+
name: FUNNEL_MCP_NAME,
|
|
157
|
+
version: "1.0.0"
|
|
158
|
+
}, {
|
|
159
|
+
capabilities: {
|
|
160
|
+
experimental: { "claude/channel": {} },
|
|
161
|
+
tools: {}
|
|
162
|
+
},
|
|
163
|
+
instructions: [
|
|
164
|
+
`Events arrive as notifications (method: notifications/claude/channel) with two fields:`,
|
|
165
|
+
` content — the event payload as a JSON string (parse it to read the message)`,
|
|
166
|
+
` meta — key/value strings describing the event`,
|
|
167
|
+
"",
|
|
168
|
+
"meta fields by event_type:",
|
|
169
|
+
" slack: event_type=slack channel_id=C… thread_ts=1234.5678 user_id=U… mentioned=true|false",
|
|
170
|
+
" gh: event_type=gh repository=owner/repo subject_type=Issue|PullRequest subject_url=… reason=…",
|
|
171
|
+
" discord: event_type=discord channel_id=… user_id=… guild_id=… mentioned=true|false",
|
|
172
|
+
" schedule: event_type=schedule entry_id=…",
|
|
173
|
+
"",
|
|
174
|
+
"To reply to a Slack message in the same thread, call the connector tool with:",
|
|
175
|
+
` method: POST`,
|
|
176
|
+
` path: chat.postMessage`,
|
|
177
|
+
` body: { channel: meta.channel_id, text: "your reply", thread_ts: meta.thread_ts }`,
|
|
178
|
+
"",
|
|
179
|
+
"To comment on a GitHub issue/PR (extract from subject_url in meta):",
|
|
180
|
+
` method: POST`,
|
|
181
|
+
` path: repos/<meta.repository>/issues/<number>/comments (parse number from meta.subject_url)`,
|
|
182
|
+
` body: { body: "your reply" }`,
|
|
183
|
+
"",
|
|
184
|
+
"Built-in diagnostic tools — call proactively when events seem missing or delayed:",
|
|
185
|
+
" fnl_status — gateway running state, all listeners alive/dead, Claude WS clients",
|
|
186
|
+
" fnl_debug — per-channel diagnosis with last 10 events, rootCause, suggestedActions",
|
|
187
|
+
" omit channel arg to diagnose all channels; check summary.suggestedActions first",
|
|
188
|
+
channelContext
|
|
189
|
+
].join("\n")
|
|
190
|
+
});
|
|
191
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
192
|
+
const connectorTools = (channel?.connectors ?? []).map((c) => ({
|
|
193
|
+
name: c.name,
|
|
194
|
+
description: `Call the "${c.name}" (${c.type}) connector. ${usageHintForType(c.type)}`,
|
|
195
|
+
inputSchema: {
|
|
196
|
+
type: "object",
|
|
197
|
+
properties: {
|
|
198
|
+
method: {
|
|
199
|
+
type: "string",
|
|
200
|
+
description: "HTTP verb or API method (e.g. POST, chat.postMessage)"
|
|
201
|
+
},
|
|
202
|
+
path: {
|
|
203
|
+
type: "string",
|
|
204
|
+
description: "API path or method name (adapter-specific)"
|
|
205
|
+
},
|
|
206
|
+
body: {
|
|
207
|
+
type: "object",
|
|
208
|
+
description: "Request body / params (adapter-specific)"
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
required: ["method", "path"]
|
|
212
|
+
}
|
|
213
|
+
}));
|
|
214
|
+
const channelEnum = allChannels.length > 0 ? allChannels.map((ch) => ch.name) : void 0;
|
|
215
|
+
const builtinTools = [{
|
|
216
|
+
name: "fnl_status",
|
|
217
|
+
description: "Return the current funnel gateway status as JSON — gateway running state, listener alive/dead per channel, and connected Claude WS clients. Call this when you need to check whether the gateway is up or why events stopped arriving.",
|
|
218
|
+
inputSchema: {
|
|
219
|
+
type: "object",
|
|
220
|
+
properties: {}
|
|
221
|
+
}
|
|
222
|
+
}, {
|
|
223
|
+
name: "fnl_debug",
|
|
224
|
+
description: "Return a full channel diagnosis as JSON — gateway health, listener state, Claude WS connection, last 10 inbound events with outcome, connectionErrors (when listener is dead), and diagnosis.rootCause. Call this first when debugging missing events. Omit `channel` to diagnose all channels at once.",
|
|
225
|
+
inputSchema: {
|
|
226
|
+
type: "object",
|
|
227
|
+
properties: { channel: channelEnum ? {
|
|
228
|
+
type: "string",
|
|
229
|
+
description: `Channel name to inspect. One of: ${channelEnum.join(", ")}. Omit to get all channels.`,
|
|
230
|
+
enum: channelEnum
|
|
231
|
+
} : {
|
|
232
|
+
type: "string",
|
|
233
|
+
description: "Channel name to inspect. Omit to get all channels."
|
|
234
|
+
} }
|
|
235
|
+
}
|
|
236
|
+
}];
|
|
237
|
+
return { tools: [...connectorTools, ...builtinTools] };
|
|
238
|
+
});
|
|
239
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
240
|
+
const toolName = request.params.name;
|
|
241
|
+
if (isBuiltinTool(toolName)) return handleBuiltinTool(toolName, request.params.arguments, gatewayBaseUrl, token, allChannels);
|
|
242
|
+
if (!channel) throw new Error("FUNNEL_CHANNEL_ID is not set or channel not found in settings.json");
|
|
243
|
+
const args = request.params.arguments ?? {};
|
|
244
|
+
const method = typeof args.method === "string" ? args.method : "";
|
|
245
|
+
const path = typeof args.path === "string" ? args.path : "";
|
|
246
|
+
const body = args.body ?? {};
|
|
247
|
+
if (!method || !path) throw new Error("`method` and `path` are required");
|
|
248
|
+
const url = `${gatewayBaseUrl}/channels/${encodeURIComponent(channel.channelName)}/connectors/${encodeURIComponent(toolName)}/call`;
|
|
249
|
+
const headers = { "content-type": "application/json" };
|
|
250
|
+
if (token) headers.authorization = `Bearer ${token}`;
|
|
251
|
+
const res = await fetch(url, {
|
|
252
|
+
method: "POST",
|
|
253
|
+
headers,
|
|
254
|
+
body: JSON.stringify({
|
|
255
|
+
method,
|
|
256
|
+
path,
|
|
257
|
+
body
|
|
258
|
+
})
|
|
259
|
+
});
|
|
260
|
+
const text = await res.text();
|
|
261
|
+
if (!res.ok) throw new Error(`gateway call failed (${res.status}): ${text}`);
|
|
262
|
+
return { content: [{
|
|
263
|
+
type: "text",
|
|
264
|
+
text
|
|
265
|
+
}] };
|
|
266
|
+
});
|
|
267
|
+
const transport = new StdioServerTransport();
|
|
268
|
+
await server.connect(transport);
|
|
269
|
+
if (!channelId) return;
|
|
270
|
+
new FunnelChannelSubscriber({
|
|
271
|
+
server,
|
|
272
|
+
baseUrl: `${gatewayWsUrl}?channel=${encodeURIComponent(channelId)}`,
|
|
273
|
+
protocols: token ? [`funnel.token.${token}`] : void 0
|
|
274
|
+
}).start();
|
|
275
|
+
};
|
|
276
|
+
const handleBuiltinTool = async (name, args, gatewayBaseUrl, token, allChannels) => {
|
|
277
|
+
const headers = {};
|
|
278
|
+
if (token) headers.authorization = `Bearer ${token}`;
|
|
279
|
+
if (name === "fnl_status") {
|
|
280
|
+
const res = await fetch(`${gatewayBaseUrl}/status`, { headers }).catch(() => null);
|
|
281
|
+
if (!res) return { content: [{
|
|
282
|
+
type: "text",
|
|
283
|
+
text: JSON.stringify({
|
|
284
|
+
running: false,
|
|
285
|
+
error: "gateway unreachable",
|
|
286
|
+
hint: "run: fnl gateway start",
|
|
287
|
+
knownChannels: allChannels.map((ch) => ch.name)
|
|
288
|
+
})
|
|
289
|
+
}] };
|
|
290
|
+
const body = await res.json();
|
|
291
|
+
return { content: [{
|
|
292
|
+
type: "text",
|
|
293
|
+
text: JSON.stringify(body)
|
|
294
|
+
}] };
|
|
295
|
+
}
|
|
296
|
+
const channelArg = typeof args?.channel === "string" ? args.channel : null;
|
|
297
|
+
const url = channelArg ? `${gatewayBaseUrl}/debug?channel=${encodeURIComponent(channelArg)}` : `${gatewayBaseUrl}/debug`;
|
|
298
|
+
const res = await fetch(url, { headers }).catch(() => null);
|
|
299
|
+
if (!res) return { content: [{
|
|
300
|
+
type: "text",
|
|
301
|
+
text: JSON.stringify({
|
|
302
|
+
gateway: { running: false },
|
|
303
|
+
channels: allChannels.map((ch) => ({
|
|
304
|
+
id: ch.id,
|
|
305
|
+
name: ch.name,
|
|
306
|
+
diagnosis: {
|
|
307
|
+
status: "error",
|
|
308
|
+
message: "gateway is not running",
|
|
309
|
+
nextAction: "fnl gateway start",
|
|
310
|
+
rootCause: null
|
|
311
|
+
}
|
|
312
|
+
}))
|
|
313
|
+
})
|
|
314
|
+
}] };
|
|
315
|
+
const body = await res.json();
|
|
316
|
+
return { content: [{
|
|
317
|
+
type: "text",
|
|
318
|
+
text: JSON.stringify(body)
|
|
319
|
+
}] };
|
|
320
|
+
};
|
|
321
|
+
//#endregion
|
|
322
|
+
export { FUNNEL_MCP_ARGS, FUNNEL_MCP_COMMAND, FUNNEL_MCP_NAME, FileProcessGuard, FunnelClaude, FunnelLocalConfig, FunnelLocalConfigSync, FunnelLocalConfigWriter, FunnelMcp, FunnelProfiles, FunnelTokenPrompter, LOCAL_CONFIG_FILENAME, MemoryFunnelTokenPrompter, NodeFunnelTokenPrompter, channelSpecSchema, connectorSpecSchema, funnelJsonSchema, localConfigSchema, profileSpecSchema, startChannelServer };
|
package/dist/{connector-diagnostic-log-OPpPi9V9.d.ts → connector-diagnostic-log-yTOojKUR.d.ts}
RENAMED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
|
|
3
|
+
//#region lib/engine/logger/logger.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Structured logger with three levels and an optional log-file path.
|
|
6
|
+
* Defaults to NodeFunnelLogger (appends to `<os.tmpdir()>/funnel/funnel.log`);
|
|
7
|
+
* MemoryFunnelLogger captures entries in memory and NoopFunnelLogger silences output.
|
|
8
|
+
*/
|
|
9
|
+
declare abstract class FunnelLogger {
|
|
10
|
+
abstract info(message: string, meta?: Record<string, unknown>): void;
|
|
11
|
+
abstract warn(message: string, meta?: Record<string, unknown>): void;
|
|
12
|
+
abstract error(message: string, meta?: Record<string, unknown>): void;
|
|
13
|
+
abstract readonly file: string | null;
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
3
16
|
//#region lib/connectors/connector-listener.d.ts
|
|
4
17
|
type NotifyFn = (content: string, meta?: Record<string, string>) => Promise<void>;
|
|
5
18
|
/**
|
|
@@ -19,19 +32,6 @@ declare abstract class FunnelConnectorListener {
|
|
|
19
32
|
isAlive(): boolean;
|
|
20
33
|
}
|
|
21
34
|
//#endregion
|
|
22
|
-
//#region lib/engine/logger/logger.d.ts
|
|
23
|
-
/**
|
|
24
|
-
* Structured logger with three levels and an optional log-file path.
|
|
25
|
-
* Defaults to NodeFunnelLogger (appends to `<os.tmpdir()>/funnel/funnel.log`);
|
|
26
|
-
* MemoryFunnelLogger captures entries in memory and NoopFunnelLogger silences output.
|
|
27
|
-
*/
|
|
28
|
-
declare abstract class FunnelLogger {
|
|
29
|
-
abstract info(message: string, meta?: Record<string, unknown>): void;
|
|
30
|
-
abstract warn(message: string, meta?: Record<string, unknown>): void;
|
|
31
|
-
abstract error(message: string, meta?: Record<string, unknown>): void;
|
|
32
|
-
abstract readonly file: string | null;
|
|
33
|
-
}
|
|
34
|
-
//#endregion
|
|
35
35
|
//#region lib/gateway/connector-diagnostic-log.d.ts
|
|
36
36
|
/**
|
|
37
37
|
* Points in the listener's connection lifecycle. The single source of truth
|
|
@@ -205,4 +205,4 @@ declare abstract class ConnectorDiagnosticLog {
|
|
|
205
205
|
abstract close(): void;
|
|
206
206
|
}
|
|
207
207
|
//#endregion
|
|
208
|
-
export {
|
|
208
|
+
export { FunnelLogger as S, connectorConnectionEventSchema as _, ConnectorConnectionStatus as a, FunnelConnectorListener as b, ConnectorProcessedQuery as c, ConnectorRawEvent as d, ConnectorRawQuery as f, StoredRawEvent as g, StoredProcessedEvent as h, ConnectorConnectionRecord as i, ConnectorProcessedRecord as l, StoredConnectionEvent as m, ConnectorConnectionEvent as n, ConnectorDiagnosticLog as o, ConnectorRawRecord as p, ConnectorConnectionQuery as r, ConnectorProcessedEvent as s, CONNECTOR_CONNECTION_STATUSES as t, ConnectorQuery as u, connectorProcessedEventSchema as v, NotifyFn as x, connectorRawEventSchema as y };
|
|
@@ -16,12 +16,4 @@ var FunnelConnectorListener = class {
|
|
|
16
16
|
}
|
|
17
17
|
};
|
|
18
18
|
//#endregion
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Structured logger with three levels and an optional log-file path.
|
|
22
|
-
* Defaults to NodeFunnelLogger (appends to `<os.tmpdir()>/funnel/funnel.log`);
|
|
23
|
-
* MemoryFunnelLogger captures entries in memory and NoopFunnelLogger silences output.
|
|
24
|
-
*/
|
|
25
|
-
var FunnelLogger = class {};
|
|
26
|
-
//#endregion
|
|
27
|
-
export { FunnelConnectorListener as n, FunnelLogger as t };
|
|
19
|
+
export { FunnelConnectorListener as t };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as
|
|
3
|
-
import {
|
|
1
|
+
import { S as FunnelLogger, b as FunnelConnectorListener, o as ConnectorDiagnosticLog, x as NotifyFn } from "../connector-diagnostic-log-yTOojKUR.js";
|
|
2
|
+
import { n as FunnelConnectorAdapter, t as CallInput } from "../connector-adapter-DKgsVuMH.js";
|
|
3
|
+
import { n as discordConnectorSchema, t as DiscordConnectorConfig } from "../discord-connector-schema-R0Uu-3ns.js";
|
|
4
4
|
|
|
5
5
|
//#region lib/engine/http/http-client.d.ts
|
|
6
6
|
type HttpRequest = {
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as FunnelDiscordEventProcessor, r as FunnelDiscordAdapter, t as FunnelDiscordListener } from "../discord-listener-_jSE3HsQ.js";
|
|
2
|
+
import { t as discordConnectorSchema } from "../discord-connector-schema-CBDyGdOI.js";
|
|
2
3
|
export { FunnelDiscordAdapter, FunnelDiscordEventProcessor, FunnelDiscordListener, discordConnectorSchema };
|
package/dist/connectors/gh.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { S as FunnelLogger, b as FunnelConnectorListener, o as ConnectorDiagnosticLog, x as NotifyFn } from "../connector-diagnostic-log-yTOojKUR.js";
|
|
2
|
+
import { r as FunnelProcessRunner } from "../process-runner-DfniuWVU.js";
|
|
3
|
+
import { n as FunnelConnectorAdapter, t as CallInput } from "../connector-adapter-DKgsVuMH.js";
|
|
4
|
+
import { n as ghConnectorSchema, t as GhConnectorConfig } from "../gh-connector-schema-eoTtHbY6.js";
|
|
4
5
|
|
|
5
6
|
//#region lib/connectors/gh-adapter.d.ts
|
|
6
7
|
type Deps$1 = {
|
package/dist/connectors/gh.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { t as ghConnectorSchema } from "../gh-connector-schema-o3Q1-ojL.js";
|
|
2
|
+
import { n as FunnelGhAdapter, t as FunnelGhListener } from "../gh-listener-DH-fClQm.js";
|
|
2
3
|
export { FunnelGhAdapter, FunnelGhListener, ghConnectorSchema };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as ScheduleEntry, c as scheduleEntrySchema, i as ScheduleConnectorConfig, l as ScheduleStateStore, n as ScheduleOnFired, o as scheduleCatchupPolicySchema, r as ScheduleCatchupPolicy, s as scheduleConnectorSchema, t as FunnelScheduleListener } from "../schedule-listener-CUyUFFR1.js";
|
|
2
2
|
|
|
3
3
|
//#region lib/connectors/match-cron.d.ts
|
|
4
4
|
declare const matchCron: (expr: string, date: Date) => boolean;
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as ScheduleStateStore, r as matchCron, t as FunnelScheduleListener } from "../schedule-listener-ePAjians.js";
|
|
2
|
+
import { n as scheduleConnectorSchema, r as scheduleEntrySchema, t as scheduleCatchupPolicySchema } from "../schedule-connector-schema-iCI61gzU.js";
|
|
2
3
|
export { FunnelScheduleListener, ScheduleStateStore, matchCron, scheduleCatchupPolicySchema, scheduleConnectorSchema, scheduleEntrySchema };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as FunnelConnectorAdapter, t as CallInput } from "../connector-adapter-
|
|
2
|
-
import { a as
|
|
1
|
+
import { n as FunnelConnectorAdapter, t as CallInput } from "../connector-adapter-DKgsVuMH.js";
|
|
2
|
+
import { a as slackConnectorSchema, c as SlackProcessedEmit, d as SlackSkipReason, i as SlackConnectorConfig, l as SlackProcessedSkip, n as SlackOnAppCreated, o as FunnelSlackEventProcessor, r as SlackPreprocessEvent, s as SlackProcessed, t as FunnelSlackListener, u as SlackRawEvent } from "../slack-listener-Bv5xI9gC.js";
|
|
3
3
|
|
|
4
4
|
//#region lib/connectors/slack-adapter.d.ts
|
|
5
5
|
type SlackWebClientLike = {
|
package/dist/connectors/slack.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as FunnelSlackEventProcessor, r as FunnelSlackAdapter, t as FunnelSlackListener } from "../slack-listener-ClQuHhEF.js";
|
|
2
|
+
import { t as slackConnectorSchema } from "../slack-connector-schema-BCNWluHM.js";
|
|
2
3
|
export { FunnelSlackAdapter, FunnelSlackEventProcessor, FunnelSlackListener, slackConnectorSchema };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
//#region lib/connectors/discord-connector-schema.ts
|
|
3
|
+
/**
|
|
4
|
+
* Like slack, a discord connector holds either a literal `botToken` or a
|
|
5
|
+
* `botTokenEnv` reference resolved from `process.env` at listener start. The
|
|
6
|
+
* reference form keeps the secret out of settings.json, but is only set through
|
|
7
|
+
* the engine API (`new Funnel(...)`); funnel.json and the `fnl` CLI produce
|
|
8
|
+
* literals.
|
|
9
|
+
*/
|
|
10
|
+
const discordConnectorSchema = z.object({
|
|
11
|
+
id: z.string(),
|
|
12
|
+
name: z.string(),
|
|
13
|
+
type: z.literal("discord"),
|
|
14
|
+
botToken: z.string().min(10).optional(),
|
|
15
|
+
/** Name of the env var holding the bot token, resolved at listener start. */
|
|
16
|
+
botTokenEnv: z.string().optional(),
|
|
17
|
+
createdAt: z.string().datetime().optional(),
|
|
18
|
+
updatedAt: z.string().datetime().optional()
|
|
19
|
+
});
|
|
20
|
+
//#endregion
|
|
21
|
+
export { discordConnectorSchema as t };
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { t as FunnelConnectorAdapter } from "./connector-adapter-D5Utumgz.js";
|
|
2
2
|
import { t as resolveConnectorToken } from "./resolve-connector-token-BHmZLRrV.js";
|
|
3
|
-
import {
|
|
3
|
+
import { t as FunnelConnectorListener } from "./connector-listener-DU54DN-f.js";
|
|
4
4
|
import { Client, GatewayIntentBits, Partials } from "discord.js";
|
|
5
|
-
import { z } from "zod";
|
|
6
5
|
//#region lib/engine/http/http-client.ts
|
|
7
6
|
var FunnelHttpClient = class {};
|
|
8
7
|
//#endregion
|
|
@@ -225,23 +224,4 @@ const messageOf = (error) => {
|
|
|
225
224
|
return error instanceof Error ? error.message : String(error);
|
|
226
225
|
};
|
|
227
226
|
//#endregion
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* Like slack, a discord connector holds either a literal `botToken` or a
|
|
231
|
-
* `botTokenEnv` reference resolved from `process.env` at listener start. The
|
|
232
|
-
* reference form keeps the secret out of settings.json, but is only set through
|
|
233
|
-
* the engine API (`new Funnel(...)`); funnel.json and the `fnl` CLI produce
|
|
234
|
-
* literals.
|
|
235
|
-
*/
|
|
236
|
-
const discordConnectorSchema = z.object({
|
|
237
|
-
id: z.string(),
|
|
238
|
-
name: z.string(),
|
|
239
|
-
type: z.literal("discord"),
|
|
240
|
-
botToken: z.string().min(10).optional(),
|
|
241
|
-
/** Name of the env var holding the bot token, resolved at listener start. */
|
|
242
|
-
botTokenEnv: z.string().optional(),
|
|
243
|
-
createdAt: z.string().datetime().optional(),
|
|
244
|
-
updatedAt: z.string().datetime().optional()
|
|
245
|
-
});
|
|
246
|
-
//#endregion
|
|
247
|
-
export { FunnelDiscordAdapter as i, FunnelDiscordListener as n, FunnelDiscordEventProcessor as r, discordConnectorSchema as t };
|
|
227
|
+
export { FunnelDiscordEventProcessor as n, FunnelDiscordAdapter as r, FunnelDiscordListener as t };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//#region lib/engine/fs/file-system.d.ts
|
|
2
|
+
type FileStat = {
|
|
3
|
+
mtimeMs: number; /** POSIX mode bits (e.g. 0o600). `null` when the underlying FS does not expose mode. */
|
|
4
|
+
mode: number | null;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Filesystem boundary used everywhere funnel reads or writes.
|
|
8
|
+
* Default is NodeFunnelFileSystem (real `node:fs`); MemoryFunnelFileSystem
|
|
9
|
+
* provides a sandbox for tests and embedded use.
|
|
10
|
+
*/
|
|
11
|
+
declare abstract class FunnelFileSystem {
|
|
12
|
+
abstract existsSync(path: string): boolean;
|
|
13
|
+
abstract readFileSync(path: string): string;
|
|
14
|
+
abstract writeFileSync(path: string, data: string): void;
|
|
15
|
+
/** Write `data` and ensure the resulting file is owner-only (0600). Use for tokens and any file that may contain secrets. */
|
|
16
|
+
abstract writeSecretFileSync(path: string, data: string): void;
|
|
17
|
+
abstract appendFileSync(path: string, data: string): void;
|
|
18
|
+
abstract unlink(path: string): void;
|
|
19
|
+
abstract mkdirSync(path: string, options?: {
|
|
20
|
+
recursive?: boolean;
|
|
21
|
+
}): void;
|
|
22
|
+
abstract readdirSync(path: string): string[];
|
|
23
|
+
abstract statSync(path: string): FileStat;
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
export { FunnelFileSystem as n, FileStat as t };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
//#region lib/engine/fs/file-system.ts
|
|
2
|
+
/**
|
|
3
|
+
* Filesystem boundary used everywhere funnel reads or writes.
|
|
4
|
+
* Default is NodeFunnelFileSystem (real `node:fs`); MemoryFunnelFileSystem
|
|
5
|
+
* provides a sandbox for tests and embedded use.
|
|
6
|
+
*/
|
|
7
|
+
var FunnelFileSystem = class {};
|
|
8
|
+
//#endregion
|
|
9
|
+
export { FunnelFileSystem as t };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { _ as connectorConnectionEventSchema, a as ConnectorConnectionStatus, c as ConnectorProcessedQuery, d as ConnectorRawEvent, f as ConnectorRawQuery, g as StoredRawEvent, h as StoredProcessedEvent, i as ConnectorConnectionRecord, l as ConnectorProcessedRecord, m as StoredConnectionEvent, n as ConnectorConnectionEvent, o as ConnectorDiagnosticLog, p as ConnectorRawRecord, r as ConnectorConnectionQuery, s as ConnectorProcessedEvent, t as CONNECTOR_CONNECTION_STATUSES, u as ConnectorQuery, v as connectorProcessedEventSchema, y as connectorRawEventSchema } from "./connector-diagnostic-log-yTOojKUR.js";
|
|
2
|
+
import { $ as FunnelGatewayToken, G as SqliteFunnelEventLog, H as MemoryConnectorDiagnosticLog, J as PublishResponse, K as FunnelChannelPublisher, Q as DEFAULT_GATEWAY_TOKEN_PATH, U as SqliteConnectorDiagnosticLog, W as MemoryFunnelEventLog, X as publishRequestSchema, Y as PublishResult, Z as publishResponseSchema, at as Env, ct as FunnelListenerSupervisor, dt as FunnelBroadcaster, et as FunnelGatewayServer, ft as ReplayableEvent, it as funnelEventSchema, lt as BroadcastEvent, nt as FunnelEventLog, ot as GatewayEmitInput, q as PublishRequest, rt as FunnelEventRecord, st as GatewayRouteDeps, t as GatewayApp, tt as FunnelEvent, ut as BroadcastSubscriber } from "./index-BM0-f6KL.js";
|
|
3
|
+
export { BroadcastEvent, BroadcastSubscriber, CONNECTOR_CONNECTION_STATUSES, ConnectorConnectionEvent, ConnectorConnectionQuery, ConnectorConnectionRecord, ConnectorConnectionStatus, ConnectorDiagnosticLog, ConnectorProcessedEvent, ConnectorProcessedQuery, ConnectorProcessedRecord, ConnectorQuery, ConnectorRawEvent, ConnectorRawQuery, ConnectorRawRecord, DEFAULT_GATEWAY_TOKEN_PATH, FunnelBroadcaster, FunnelChannelPublisher, FunnelEvent, FunnelEventLog, FunnelEventRecord, FunnelGatewayServer, FunnelGatewayToken, FunnelListenerSupervisor, type GatewayApp, type GatewayEmitInput, type GatewayRouteDeps, type Env as GatewayServerEnv, MemoryConnectorDiagnosticLog, MemoryFunnelEventLog, PublishRequest, PublishResponse, PublishResult, ReplayableEvent, SqliteConnectorDiagnosticLog, SqliteFunnelEventLog, StoredConnectionEvent, StoredProcessedEvent, StoredRawEvent, connectorConnectionEventSchema, connectorProcessedEventSchema, connectorRawEventSchema, funnelEventSchema, publishRequestSchema, publishResponseSchema };
|
package/dist/gateway.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { _ as FunnelBroadcaster, a as connectorConnectionEventSchema, b as publishResponseSchema, c as MemoryFunnelEventLog, d as FunnelGatewayServer, g as funnelEventSchema, h as FunnelEventLog, i as ConnectorDiagnosticLog, l as DEFAULT_GATEWAY_TOKEN_PATH, m as SqliteFunnelEventLog, n as SqliteConnectorDiagnosticLog, o as connectorProcessedEventSchema, p as FunnelListenerSupervisor, r as CONNECTOR_CONNECTION_STATUSES, s as connectorRawEventSchema, t as MemoryConnectorDiagnosticLog, u as FunnelGatewayToken, v as FunnelChannelPublisher, y as publishRequestSchema } from "./memory-connector-diagnostic-log-CrW1ltLM.js";
|
|
2
|
+
export { CONNECTOR_CONNECTION_STATUSES, ConnectorDiagnosticLog, DEFAULT_GATEWAY_TOKEN_PATH, FunnelBroadcaster, FunnelChannelPublisher, FunnelEventLog, FunnelGatewayServer, FunnelGatewayToken, FunnelListenerSupervisor, MemoryConnectorDiagnosticLog, MemoryFunnelEventLog, SqliteConnectorDiagnosticLog, SqliteFunnelEventLog, connectorConnectionEventSchema, connectorProcessedEventSchema, connectorRawEventSchema, funnelEventSchema, publishRequestSchema, publishResponseSchema };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
//#region lib/connectors/gh-connector-schema.d.ts
|
|
4
|
+
declare const ghConnectorSchema: z.ZodObject<{
|
|
5
|
+
id: z.ZodString;
|
|
6
|
+
name: z.ZodString;
|
|
7
|
+
type: z.ZodLiteral<"gh">;
|
|
8
|
+
pollInterval: z.ZodOptional<z.ZodNumber>;
|
|
9
|
+
createdAt: z.ZodOptional<z.ZodString>;
|
|
10
|
+
updatedAt: z.ZodOptional<z.ZodString>;
|
|
11
|
+
}, z.core.$strip>;
|
|
12
|
+
type GhConnectorConfig = z.infer<typeof ghConnectorSchema>;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { ghConnectorSchema as n, GhConnectorConfig as t };
|