@interactive-inc/claude-funnel 0.10.0 → 0.10.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/dist/bin.js +448 -448
- package/dist/connectors/slack.d.ts +1 -29
- package/dist/gateway/daemon.js +166 -166
- package/dist/index.d.ts +4 -11
- package/dist/index.js +133 -120
- package/dist/slack-event-processor-CS-bAit9.d.ts +43 -0
- package/package.json +1 -6
- package/dist/slack-connector-schema-D7zAHN8k.d.ts +0 -15
- package/lib/bin.ts +0 -3
- package/lib/cli/factory.ts +0 -10
- package/lib/cli/index.ts +0 -85
- package/lib/cli/router/query-to-cli-args.ts +0 -20
- package/lib/cli/router/to-request.ts +0 -113
- package/lib/cli/router/validator.ts +0 -27
- package/lib/cli/routes/channels.$channel.connectors.$connector.rename.$newName.ts +0 -27
- package/lib/cli/routes/channels.$channel.connectors.$connector.request.ts +0 -40
- package/lib/cli/routes/channels.$channel.connectors.$connector.schedules.add.$id.ts +0 -41
- package/lib/cli/routes/channels.$channel.connectors.$connector.schedules.remove.$id.ts +0 -22
- package/lib/cli/routes/channels.$channel.connectors.$connector.schedules.ts +0 -23
- package/lib/cli/routes/channels.$channel.connectors.$connector.ts +0 -26
- package/lib/cli/routes/channels.$channel.connectors.add.$connector.ts +0 -92
- package/lib/cli/routes/channels.$channel.connectors.remove.$connector.ts +0 -22
- package/lib/cli/routes/channels.$channel.connectors.set.$connector.ts +0 -63
- package/lib/cli/routes/channels.$channel.connectors.ts +0 -26
- package/lib/cli/routes/channels.$channel.publish.ts +0 -52
- package/lib/cli/routes/channels.$channel.rename.$newName.ts +0 -22
- package/lib/cli/routes/channels.$channel.set.delivery.$mode.ts +0 -34
- package/lib/cli/routes/channels.$channel.ts +0 -34
- package/lib/cli/routes/channels.add.$channel.ts +0 -33
- package/lib/cli/routes/channels.remove.$channel.ts +0 -20
- package/lib/cli/routes/channels.ts +0 -39
- package/lib/cli/routes/claude.ts +0 -70
- package/lib/cli/routes/gateway.listeners.ts +0 -41
- package/lib/cli/routes/gateway.logs.ts +0 -123
- package/lib/cli/routes/gateway.restart.ts +0 -50
- package/lib/cli/routes/gateway.run.ts +0 -41
- package/lib/cli/routes/gateway.start.ts +0 -50
- package/lib/cli/routes/gateway.status.ts +0 -19
- package/lib/cli/routes/gateway.stop.ts +0 -32
- package/lib/cli/routes/gateway.ts +0 -55
- package/lib/cli/routes/index.ts +0 -219
- package/lib/cli/routes/profiles.$profile.as-default.ts +0 -22
- package/lib/cli/routes/profiles.$profile.rename.$newName.ts +0 -22
- package/lib/cli/routes/profiles.$profile.run.ts +0 -36
- package/lib/cli/routes/profiles.add.$profile.ts +0 -49
- package/lib/cli/routes/profiles.remove.$profile.ts +0 -20
- package/lib/cli/routes/profiles.set.$profile.ts +0 -45
- package/lib/cli/routes/profiles.ts +0 -40
- package/lib/cli/routes/status.ts +0 -93
- package/lib/cli/routes/update.ts +0 -27
- package/lib/connectors/connector-adapter.ts +0 -9
- package/lib/connectors/connector-config-schema.ts +0 -16
- package/lib/connectors/connector-factory.ts +0 -94
- package/lib/connectors/connector-listener.ts +0 -20
- package/lib/connectors/discord-adapter.ts +0 -51
- package/lib/connectors/discord-connector-schema.ts +0 -12
- package/lib/connectors/discord-event-processor.ts +0 -48
- package/lib/connectors/discord-listener.ts +0 -111
- package/lib/connectors/discord.ts +0 -4
- package/lib/connectors/gh-adapter.ts +0 -48
- package/lib/connectors/gh-connector-schema.ts +0 -12
- package/lib/connectors/gh-listener.ts +0 -137
- package/lib/connectors/gh.ts +0 -3
- package/lib/connectors/match-cron.ts +0 -78
- package/lib/connectors/schedule-connector-schema.ts +0 -33
- package/lib/connectors/schedule-listener.ts +0 -207
- package/lib/connectors/schedule-state-store.ts +0 -54
- package/lib/connectors/schedule.ts +0 -4
- package/lib/connectors/slack-adapter.ts +0 -36
- package/lib/connectors/slack-connector-schema.ts +0 -13
- package/lib/connectors/slack-event-processor.ts +0 -97
- package/lib/connectors/slack-listener.ts +0 -97
- package/lib/connectors/slack.ts +0 -4
- package/lib/engine/channels/channels.ts +0 -520
- package/lib/engine/claude/claude.ts +0 -205
- package/lib/engine/claude/gateway-controller.ts +0 -4
- package/lib/engine/fs/file-system.ts +0 -23
- package/lib/engine/fs/memory-file-system.ts +0 -102
- package/lib/engine/fs/node-file-system.ts +0 -68
- package/lib/engine/http/http-client.ts +0 -17
- package/lib/engine/http/memory-http-client.ts +0 -36
- package/lib/engine/http/node-http-client.ts +0 -23
- package/lib/engine/id/id-generator.ts +0 -7
- package/lib/engine/id/memory-id-generator.ts +0 -20
- package/lib/engine/id/node-id-generator.ts +0 -7
- package/lib/engine/logger/logger.ts +0 -11
- package/lib/engine/logger/memory-logger.ts +0 -28
- package/lib/engine/logger/node-logger.ts +0 -49
- package/lib/engine/logger/noop-logger.ts +0 -9
- package/lib/engine/mcp/channel-server.ts +0 -123
- package/lib/engine/mcp/channel-subscriber.ts +0 -82
- package/lib/engine/mcp/mcp.ts +0 -126
- package/lib/engine/mcp/read-channel-connectors.ts +0 -34
- package/lib/engine/mcp/read-gateway-token.ts +0 -16
- package/lib/engine/mcp/usage-hint-for-type.ts +0 -15
- package/lib/engine/process/memory-process-runner.ts +0 -88
- package/lib/engine/process/node-process-runner.ts +0 -91
- package/lib/engine/process/process-runner.ts +0 -33
- package/lib/engine/profiles/profile-channel-checker.ts +0 -7
- package/lib/engine/profiles/profiles.ts +0 -126
- package/lib/engine/settings/mock-settings-reader.ts +0 -27
- package/lib/engine/settings/settings-reader.ts +0 -6
- package/lib/engine/settings/settings-schema.ts +0 -48
- package/lib/engine/settings/settings-store.ts +0 -110
- package/lib/engine/time/clock.ts +0 -15
- package/lib/engine/time/memory-clock.ts +0 -26
- package/lib/engine/time/node-clock.ts +0 -7
- package/lib/funnel.ts +0 -294
- package/lib/gateway/auth-middleware.ts +0 -44
- package/lib/gateway/broadcaster.ts +0 -319
- package/lib/gateway/channel-publisher.ts +0 -67
- package/lib/gateway/daemon.ts +0 -47
- package/lib/gateway/factory.ts +0 -10
- package/lib/gateway/funnel-event-store.ts +0 -155
- package/lib/gateway/gateway-server.ts +0 -426
- package/lib/gateway/gateway-token.ts +0 -79
- package/lib/gateway/gateway.ts +0 -209
- package/lib/gateway/kill-competing-slack-gateways.ts +0 -56
- package/lib/gateway/listener-supervisor.ts +0 -339
- package/lib/gateway/listeners-client.ts +0 -128
- package/lib/gateway/publish-schema.ts +0 -27
- package/lib/gateway/resolve-daemon-script.ts +0 -26
- package/lib/gateway/routes/channels.connectors.call.ts +0 -39
- package/lib/gateway/routes/channels.publish.ts +0 -44
- package/lib/gateway/routes/health.ts +0 -13
- package/lib/gateway/routes/index.ts +0 -26
- package/lib/gateway/routes/listeners.list.ts +0 -6
- package/lib/gateway/routes/listeners.restart.ts +0 -15
- package/lib/gateway/routes/listeners.start.ts +0 -15
- package/lib/gateway/routes/listeners.stop.ts +0 -15
- package/lib/gateway/routes/route-deps.ts +0 -19
- package/lib/gateway/routes/status.ts +0 -15
- package/lib/gateway/routes/validator.ts +0 -17
- package/lib/index.ts +0 -67
- package/lib/logger/leuco-human-file-writer.ts +0 -65
- package/lib/logger/leuco-human-logger.ts +0 -98
- package/lib/logger/leuco-human-record.ts +0 -16
- package/lib/logger/leuco-human-stdout-writer.ts +0 -26
- package/lib/logger/leuco-human-writer.ts +0 -14
- package/lib/logger/leuco-logger-memory-sink.ts +0 -67
- package/lib/logger/leuco-logger-record.ts +0 -13
- package/lib/logger/leuco-logger-sink.ts +0 -33
- package/lib/logger/leuco-logger-sqlite-sink.ts +0 -355
- package/lib/logger/leuco-logger.ts +0 -135
- package/lib/tui/app.tsx +0 -357
- package/lib/tui/components/add-row.tsx +0 -18
- package/lib/tui/components/brand.tsx +0 -27
- package/lib/tui/components/card.tsx +0 -44
- package/lib/tui/components/detail-bar.tsx +0 -46
- package/lib/tui/components/editable-field.tsx +0 -33
- package/lib/tui/components/empty-state.tsx +0 -11
- package/lib/tui/components/gateway-status.tsx +0 -66
- package/lib/tui/components/keymap.tsx +0 -29
- package/lib/tui/components/menu-item.tsx +0 -73
- package/lib/tui/components/menu.tsx +0 -26
- package/lib/tui/components/panel-header.tsx +0 -22
- package/lib/tui/components/readonly-field.tsx +0 -18
- package/lib/tui/components/section-header.tsx +0 -25
- package/lib/tui/components/selection-accent.tsx +0 -32
- package/lib/tui/components/session-item.tsx +0 -33
- package/lib/tui/components/session-list.tsx +0 -33
- package/lib/tui/components/ui/hascii/accordion-item.tsx +0 -88
- package/lib/tui/components/ui/hascii/accordion.tsx +0 -96
- package/lib/tui/components/ui/hascii/alert-dialog.tsx +0 -43
- package/lib/tui/components/ui/hascii/badge.tsx +0 -51
- package/lib/tui/components/ui/hascii/breadcrumb.tsx +0 -58
- package/lib/tui/components/ui/hascii/button.tsx +0 -194
- package/lib/tui/components/ui/hascii/card-content.tsx +0 -14
- package/lib/tui/components/ui/hascii/card-description.tsx +0 -13
- package/lib/tui/components/ui/hascii/card-footer.tsx +0 -14
- package/lib/tui/components/ui/hascii/card-header.tsx +0 -14
- package/lib/tui/components/ui/hascii/card-title.tsx +0 -13
- package/lib/tui/components/ui/hascii/card.tsx +0 -27
- package/lib/tui/components/ui/hascii/checkbox.tsx +0 -65
- package/lib/tui/components/ui/hascii/command.tsx +0 -159
- package/lib/tui/components/ui/hascii/dialog-content.tsx +0 -14
- package/lib/tui/components/ui/hascii/dialog-description.tsx +0 -13
- package/lib/tui/components/ui/hascii/dialog-footer.tsx +0 -14
- package/lib/tui/components/ui/hascii/dialog-header.tsx +0 -14
- package/lib/tui/components/ui/hascii/dialog-title.tsx +0 -13
- package/lib/tui/components/ui/hascii/dialog.tsx +0 -27
- package/lib/tui/components/ui/hascii/file-tree.tsx +0 -142
- package/lib/tui/components/ui/hascii/focus-group.tsx +0 -62
- package/lib/tui/components/ui/hascii/form-item.tsx +0 -43
- package/lib/tui/components/ui/hascii/input-otp.tsx +0 -86
- package/lib/tui/components/ui/hascii/input.tsx +0 -130
- package/lib/tui/components/ui/hascii/pagination.tsx +0 -105
- package/lib/tui/components/ui/hascii/progress.tsx +0 -28
- package/lib/tui/components/ui/hascii/select.tsx +0 -131
- package/lib/tui/components/ui/hascii/separator.tsx +0 -35
- package/lib/tui/components/ui/hascii/sidebar-content.tsx +0 -23
- package/lib/tui/components/ui/hascii/sidebar-header.tsx +0 -14
- package/lib/tui/components/ui/hascii/sidebar-menu-item.tsx +0 -67
- package/lib/tui/components/ui/hascii/sidebar.tsx +0 -24
- package/lib/tui/components/ui/hascii/skeleton.tsx +0 -60
- package/lib/tui/components/ui/hascii/slider.tsx +0 -91
- package/lib/tui/components/ui/hascii/snackbar.tsx +0 -75
- package/lib/tui/components/ui/hascii/sparkline.tsx +0 -53
- package/lib/tui/components/ui/hascii/spinner.tsx +0 -47
- package/lib/tui/components/ui/hascii/stepper.tsx +0 -54
- package/lib/tui/components/ui/hascii/switch.tsx +0 -66
- package/lib/tui/components/ui/hascii/table.tsx +0 -95
- package/lib/tui/components/ui/hascii/tabs.tsx +0 -59
- package/lib/tui/components/ui/hascii/toggle-group-item.tsx +0 -45
- package/lib/tui/components/ui/hascii/toggle-group.tsx +0 -99
- package/lib/tui/components/ui/hascii/tree.tsx +0 -104
- package/lib/tui/components/view-shell.tsx +0 -44
- package/lib/tui/filter-input.tsx +0 -33
- package/lib/tui/hooks/hascii/use-pressable.ts +0 -54
- package/lib/tui/parse-comma-list.ts +0 -14
- package/lib/tui/profile-launcher.tsx +0 -61
- package/lib/tui/scrollbar-options.ts +0 -19
- package/lib/tui/sidebar.tsx +0 -50
- package/lib/tui/theme.ts +0 -40
- package/lib/tui/tui.tsx +0 -20
- package/lib/tui/types.ts +0 -38
- package/lib/tui/unique-name.ts +0 -18
- package/lib/tui/use-event-stream.ts +0 -133
- package/lib/tui/use-snapshot.ts +0 -99
- package/lib/tui/utils/hascii/form-item-context.tsx +0 -23
- package/lib/tui/utils/hascii/input-focus-context.tsx +0 -31
- package/lib/tui/utils/hascii/theme-context.tsx +0 -26
- package/lib/tui/utils/hascii/theme.ts +0 -176
- package/lib/tui/views/channels-view.tsx +0 -108
- package/lib/tui/views/connectors-view.tsx +0 -164
- package/lib/tui/views/events-view.tsx +0 -160
- package/lib/tui/views/listeners-view.tsx +0 -80
- package/lib/tui/views/profiles-view.tsx +0 -152
package/dist/index.d.ts
CHANGED
|
@@ -3,10 +3,10 @@ import { n as discordConnectorSchema, t as DiscordConnectorConfig } from "./disc
|
|
|
3
3
|
import { n as FunnelConnectorListener, r as NotifyFn, t as FunnelLogger } from "./logger-CTlXs7z4.js";
|
|
4
4
|
import { a as FunnelProcessRunner, i as DetachOptions, n as ghConnectorSchema, o as RunOptions, r as AttachOptions, s as RunResult, t as GhConnectorConfig } from "./gh-connector-schema-BZFAS-p-.js";
|
|
5
5
|
import { a as ScheduleEntry, c as scheduleEntrySchema, i as ScheduleConnectorConfig, n as FunnelFileSystem, o as scheduleCatchupPolicySchema, r as ScheduleCatchupPolicy, s as scheduleConnectorSchema, t as FileStat } from "./file-system-Co60LrmR.js";
|
|
6
|
-
import { n as slackConnectorSchema, t as
|
|
6
|
+
import { a as SlackRawEvent, i as SlackProcessedSkip, n as SlackProcessed, o as SlackConnectorConfig, r as SlackProcessedEmit, s as slackConnectorSchema, t as FunnelSlackEventProcessor } from "./slack-event-processor-CS-bAit9.js";
|
|
7
7
|
import { z } from "zod";
|
|
8
|
-
import { Server, ServerWebSocket } from "bun";
|
|
9
8
|
import * as _$hono_factory0 from "hono/factory";
|
|
9
|
+
import { Server, ServerWebSocket } from "bun";
|
|
10
10
|
import * as _$hono_utils_http_status0 from "hono/utils/http-status";
|
|
11
11
|
import * as _$hono_hono_base0 from "hono/hono-base";
|
|
12
12
|
|
|
@@ -339,13 +339,7 @@ declare class FunnelChannels {
|
|
|
339
339
|
listener: FunnelConnectorListener;
|
|
340
340
|
}[];
|
|
341
341
|
private requireChannel;
|
|
342
|
-
private requireConnector;
|
|
343
|
-
private requireSlackConnector;
|
|
344
|
-
private requireGhConnector;
|
|
345
|
-
private requireDiscordConnector;
|
|
346
|
-
private requireScheduleConnector;
|
|
347
342
|
private assertNoTokenCollision;
|
|
348
|
-
private tokensOf;
|
|
349
343
|
}
|
|
350
344
|
//#endregion
|
|
351
345
|
//#region lib/engine/claude/gateway-controller.d.ts
|
|
@@ -1037,7 +1031,7 @@ type Props$4 = {
|
|
|
1037
1031
|
*/
|
|
1038
1032
|
declare class Funnel {
|
|
1039
1033
|
private readonly props;
|
|
1040
|
-
private readonly
|
|
1034
|
+
private readonly memos;
|
|
1041
1035
|
constructor(props?: Props$4);
|
|
1042
1036
|
/**
|
|
1043
1037
|
* Sandboxed Funnel wired with in-memory implementations for every IO boundary.
|
|
@@ -1045,7 +1039,6 @@ declare class Funnel {
|
|
|
1045
1039
|
* and ad-hoc experiments. Override individual fields by passing them in `props`.
|
|
1046
1040
|
*/
|
|
1047
1041
|
static inMemory(props?: Props$4): Funnel;
|
|
1048
|
-
private memo;
|
|
1049
1042
|
/** Resolved on-disk paths the facade will read/write when methods are called. Pure compute, not memoized. */
|
|
1050
1043
|
get paths(): {
|
|
1051
1044
|
dir: string;
|
|
@@ -3885,4 +3878,4 @@ ${string}`;
|
|
|
3885
3878
|
//#region lib/tui/tui.d.ts
|
|
3886
3879
|
declare function launchTui(funnel: Funnel): Promise<void>;
|
|
3887
3880
|
//#endregion
|
|
3888
|
-
export { AttachOptions, BroadcastEvent, BroadcastSubscriber, ChannelConfig, ChannelConnectorView, ChannelDeliveryMode, ChannelServerOptions, ConnectorConfig, ConnectorType, DEFAULT_GATEWAY_TOKEN_PATH, DetachOptions, DiscordConnectorConfig, Env, FUNNEL_DIR, FUNNEL_MCP_COMMAND, FUNNEL_MCP_NAME, FileStat, Funnel, FunnelBroadcaster, FunnelChannelPublisher, FunnelChannels, FunnelClaude, FunnelClock, FunnelConnectorFactory, FunnelConnectorListener, FunnelEvent, FunnelEventStore, FunnelFileSystem, FunnelGateway, FunnelGatewayServer, FunnelGatewayToken, FunnelIdGenerator, FunnelListenerSupervisor, FunnelListenersClient, FunnelLogger, FunnelMcp, FunnelProcessRunner, FunnelProfiles, FunnelSettingsReader, FunnelSettingsStore, GhConnectorConfig, LaunchOptions, ListListenersResult, ListenerEntry, ListenerOpResult, LogEntry, MemoryFunnelClock, MemoryFunnelFileSystem, MemoryFunnelIdGenerator, MemoryFunnelLogger, MemoryFunnelProcessRunner, MemoryProcessCall, MemoryProcessHandler, MemoryProcessResponse, MemoryProcessSyncHandler, MockFunnelSettingsReader, NodeFunnelClock, NodeFunnelFileSystem, NodeFunnelIdGenerator, NodeFunnelLogger, NodeFunnelProcessRunner, NoopFunnelLogger, NotifyFn, ProfileConfig, PublishRequest, PublishResponse, PublishResult, ReplayableEvent, RunOptions, RunResult, SETTINGS_PATH, SETTINGS_VERSION, ScheduleCatchupPolicy,
|
|
3881
|
+
export { AttachOptions, BroadcastEvent, BroadcastSubscriber, ChannelConfig, ChannelConnectorView, ChannelDeliveryMode, ChannelServerOptions, ConnectorConfig, ConnectorType, DEFAULT_GATEWAY_TOKEN_PATH, DetachOptions, DiscordConnectorConfig, Env, FUNNEL_DIR, FUNNEL_MCP_COMMAND, FUNNEL_MCP_NAME, FileStat, Funnel, FunnelBroadcaster, FunnelChannelPublisher, FunnelChannels, FunnelClaude, FunnelClock, FunnelConnectorFactory, FunnelConnectorListener, FunnelEvent, FunnelEventStore, FunnelFileSystem, FunnelGateway, FunnelGatewayServer, FunnelGatewayToken, FunnelIdGenerator, FunnelListenerSupervisor, FunnelListenersClient, FunnelLogger, FunnelMcp, FunnelProcessRunner, FunnelProfiles, FunnelSettingsReader, FunnelSettingsStore, FunnelSlackEventProcessor, GhConnectorConfig, LaunchOptions, ListListenersResult, ListenerEntry, ListenerOpResult, LogEntry, MemoryFunnelClock, MemoryFunnelFileSystem, MemoryFunnelIdGenerator, MemoryFunnelLogger, MemoryFunnelProcessRunner, MemoryProcessCall, MemoryProcessHandler, MemoryProcessResponse, MemoryProcessSyncHandler, MockFunnelSettingsReader, NodeFunnelClock, NodeFunnelFileSystem, NodeFunnelIdGenerator, NodeFunnelLogger, NodeFunnelProcessRunner, NoopFunnelLogger, NotifyFn, ProfileConfig, PublishRequest, PublishResponse, PublishResult, ReplayableEvent, RunOptions, RunResult, SETTINGS_PATH, SETTINGS_VERSION, ScheduleCatchupPolicy, ScheduleConnectorConfig, ScheduleEntry, Settings, SlackConnectorConfig, SlackProcessed, SlackProcessedEmit, SlackProcessedSkip, SlackRawEvent, channelConfigSchema, channelDeliveryModeSchema, app as cliApp, connectorConfigSchema, createCliApp, createSettings, discordConnectorSchema, factory, funnelEventSchema, ghConnectorSchema, launchTui, profileConfigSchema, publishRequestSchema, publishResponseSchema, queryToCliArgs, scheduleCatchupPolicySchema, scheduleConnectorSchema, scheduleEntrySchema, settingsSchema, slackConnectorSchema, startChannelServer, toRequest };
|
package/dist/index.js
CHANGED
|
@@ -2,18 +2,18 @@ import { i as FunnelDiscordAdapter, n as FunnelDiscordListener, t as discordConn
|
|
|
2
2
|
import { n as FunnelLogger, r as FunnelConnectorListener, t as NodeFunnelLogger } from "./node-logger-DQz_BGOD.js";
|
|
3
3
|
import { a as FunnelProcessRunner, i as NodeFunnelProcessRunner, n as FunnelGhListener, r as FunnelGhAdapter, t as ghConnectorSchema } from "./gh-connector-schema-2ml29MBC.js";
|
|
4
4
|
import { a as ScheduleStateStore, i as FunnelScheduleListener, n as scheduleConnectorSchema, o as NodeFunnelFileSystem, r as scheduleEntrySchema, s as FunnelFileSystem, t as scheduleCatchupPolicySchema } from "./schedule-connector-schema-CkuIQ0JQ.js";
|
|
5
|
-
import { i as FunnelSlackAdapter, n as FunnelSlackListener, t as slackConnectorSchema } from "./slack-connector-schema-Cd22WiHB.js";
|
|
5
|
+
import { i as FunnelSlackAdapter, n as FunnelSlackListener, r as FunnelSlackEventProcessor, t as slackConnectorSchema } from "./slack-connector-schema-Cd22WiHB.js";
|
|
6
6
|
import { dirname, join, resolve } from "node:path";
|
|
7
7
|
import { existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
8
8
|
import { z } from "zod";
|
|
9
9
|
import { homedir } from "node:os";
|
|
10
|
-
import "
|
|
10
|
+
import { fileURLToPath } from "node:url";
|
|
11
11
|
import { timingSafeEqual } from "node:crypto";
|
|
12
12
|
import { createFactory } from "hono/factory";
|
|
13
13
|
import { Database } from "bun:sqlite";
|
|
14
14
|
import { HTTPException } from "hono/http-exception";
|
|
15
15
|
import { zValidator } from "@hono/zod-validator";
|
|
16
|
-
import { Server
|
|
16
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
17
17
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
18
18
|
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
19
19
|
import { stringify } from "yaml";
|
|
@@ -183,6 +183,40 @@ var FunnelConnectorFactory = class {
|
|
|
183
183
|
}
|
|
184
184
|
};
|
|
185
185
|
//#endregion
|
|
186
|
+
//#region lib/engine/channels/connector-tokens.ts
|
|
187
|
+
/**
|
|
188
|
+
* Return every secret token contained in a connector config. Used by token
|
|
189
|
+
* collision detection at add/update time so the same Slack bot or Discord
|
|
190
|
+
* bot cannot be registered under two connectors. Centralizes the per-type
|
|
191
|
+
* switch so the channels facade does not embed type-specific knowledge.
|
|
192
|
+
*/
|
|
193
|
+
function connectorTokens(connector) {
|
|
194
|
+
switch (connector.type) {
|
|
195
|
+
case "slack": return [connector.botToken, connector.appToken];
|
|
196
|
+
case "discord": return [connector.botToken];
|
|
197
|
+
case "gh":
|
|
198
|
+
case "schedule": return [];
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
//#endregion
|
|
202
|
+
//#region lib/engine/channels/require-connector.ts
|
|
203
|
+
function isConnectorOfType(connector, type) {
|
|
204
|
+
return connector.type === type;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Look up a connector by name and narrow its discriminated union to a single
|
|
208
|
+
* variant via a type predicate. Throws if the connector is missing or has the
|
|
209
|
+
* wrong `type`. Replaces per-type `requireXxxConnector` privates — adding a
|
|
210
|
+
* new connector type only touches the `ConnectorConfig` union, not this
|
|
211
|
+
* helper.
|
|
212
|
+
*/
|
|
213
|
+
function requireConnectorOfType(channel, connectorName, type) {
|
|
214
|
+
const connector = channel.connectors.find((c) => c.name === connectorName);
|
|
215
|
+
if (!connector) throw new Error(`connector "${connectorName}" not found in channel "${channel.name}"`);
|
|
216
|
+
if (!isConnectorOfType(connector, type)) throw new Error(`connector "${connectorName}" is type "${connector.type}", not "${type}"`);
|
|
217
|
+
return connector;
|
|
218
|
+
}
|
|
219
|
+
//#endregion
|
|
186
220
|
//#region lib/engine/time/clock.ts
|
|
187
221
|
/**
|
|
188
222
|
* Time boundary. Default NodeFunnelClock returns `new Date()`; MemoryFunnelClock
|
|
@@ -320,39 +354,41 @@ var FunnelChannels = class {
|
|
|
320
354
|
const now = this.clock.iso();
|
|
321
355
|
const createdAt = now;
|
|
322
356
|
const updatedAt = now;
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
357
|
+
switch (input.type) {
|
|
358
|
+
case "slack": return {
|
|
359
|
+
id,
|
|
360
|
+
type: "slack",
|
|
361
|
+
name: input.name,
|
|
362
|
+
botToken: input.botToken,
|
|
363
|
+
appToken: input.appToken,
|
|
364
|
+
createdAt,
|
|
365
|
+
updatedAt
|
|
366
|
+
};
|
|
367
|
+
case "gh": return {
|
|
368
|
+
id,
|
|
369
|
+
type: "gh",
|
|
370
|
+
name: input.name,
|
|
371
|
+
...input.pollInterval !== void 0 ? { pollInterval: input.pollInterval } : {},
|
|
372
|
+
createdAt,
|
|
373
|
+
updatedAt
|
|
374
|
+
};
|
|
375
|
+
case "discord": return {
|
|
376
|
+
id,
|
|
377
|
+
type: "discord",
|
|
378
|
+
name: input.name,
|
|
379
|
+
botToken: input.botToken,
|
|
380
|
+
createdAt,
|
|
381
|
+
updatedAt
|
|
382
|
+
};
|
|
383
|
+
case "schedule": return {
|
|
384
|
+
id,
|
|
385
|
+
type: "schedule",
|
|
386
|
+
name: input.name,
|
|
387
|
+
entries: input.entries ?? [],
|
|
388
|
+
createdAt,
|
|
389
|
+
updatedAt
|
|
390
|
+
};
|
|
391
|
+
}
|
|
356
392
|
}
|
|
357
393
|
removeConnector(channelName, connectorName) {
|
|
358
394
|
const settings = this.store.read();
|
|
@@ -374,8 +410,7 @@ var FunnelChannels = class {
|
|
|
374
410
|
}
|
|
375
411
|
updateSlackConnector(channelName, connectorName, fields) {
|
|
376
412
|
const settings = this.store.read();
|
|
377
|
-
const
|
|
378
|
-
const connector = this.requireSlackConnector(channel, connectorName);
|
|
413
|
+
const connector = requireConnectorOfType(this.requireChannel(settings, channelName), connectorName, "slack");
|
|
379
414
|
const updated = {
|
|
380
415
|
...connector,
|
|
381
416
|
botToken: fields.botToken ?? connector.botToken,
|
|
@@ -388,16 +423,14 @@ var FunnelChannels = class {
|
|
|
388
423
|
}
|
|
389
424
|
updateGhConnector(channelName, connectorName, fields) {
|
|
390
425
|
const settings = this.store.read();
|
|
391
|
-
const
|
|
392
|
-
const connector = this.requireGhConnector(channel, connectorName);
|
|
426
|
+
const connector = requireConnectorOfType(this.requireChannel(settings, channelName), connectorName, "gh");
|
|
393
427
|
if (fields.pollInterval !== void 0) connector.pollInterval = fields.pollInterval;
|
|
394
428
|
connector.updatedAt = this.clock.iso();
|
|
395
429
|
this.store.write(settings);
|
|
396
430
|
}
|
|
397
431
|
updateDiscordConnector(channelName, connectorName, fields) {
|
|
398
432
|
const settings = this.store.read();
|
|
399
|
-
const
|
|
400
|
-
const connector = this.requireDiscordConnector(channel, connectorName);
|
|
433
|
+
const connector = requireConnectorOfType(this.requireChannel(settings, channelName), connectorName, "discord");
|
|
401
434
|
const updated = {
|
|
402
435
|
...connector,
|
|
403
436
|
botToken: fields.botToken ?? connector.botToken,
|
|
@@ -408,13 +441,11 @@ var FunnelChannels = class {
|
|
|
408
441
|
this.store.write(settings);
|
|
409
442
|
}
|
|
410
443
|
listScheduleEntries(channelName, connectorName) {
|
|
411
|
-
|
|
412
|
-
return this.requireScheduleConnector(channel, connectorName).entries;
|
|
444
|
+
return requireConnectorOfType(this.requireChannel(this.store.read(), channelName), connectorName, "schedule").entries;
|
|
413
445
|
}
|
|
414
446
|
addScheduleEntry(channelName, connectorName, entry) {
|
|
415
447
|
const settings = this.store.read();
|
|
416
|
-
const
|
|
417
|
-
const connector = this.requireScheduleConnector(channel, connectorName);
|
|
448
|
+
const connector = requireConnectorOfType(this.requireChannel(settings, channelName), connectorName, "schedule");
|
|
418
449
|
const persisted = {
|
|
419
450
|
id: entry.id ?? this.idGenerator.generate(),
|
|
420
451
|
cron: entry.cron,
|
|
@@ -429,8 +460,7 @@ var FunnelChannels = class {
|
|
|
429
460
|
}
|
|
430
461
|
removeScheduleEntry(channelName, connectorName, id) {
|
|
431
462
|
const settings = this.store.read();
|
|
432
|
-
const
|
|
433
|
-
const connector = this.requireScheduleConnector(channel, connectorName);
|
|
463
|
+
const connector = requireConnectorOfType(this.requireChannel(settings, channelName), connectorName, "schedule");
|
|
434
464
|
const index = connector.entries.findIndex((e) => e.id === id);
|
|
435
465
|
if (index < 0) throw new Error(`schedule entry "${id}" not found`);
|
|
436
466
|
connector.entries.splice(index, 1);
|
|
@@ -470,44 +500,14 @@ var FunnelChannels = class {
|
|
|
470
500
|
if (!channel) throw new Error(`channel "${name}" not found`);
|
|
471
501
|
return channel;
|
|
472
502
|
}
|
|
473
|
-
requireConnector(channel, connectorName) {
|
|
474
|
-
const connector = channel.connectors.find((c) => c.name === connectorName);
|
|
475
|
-
if (!connector) throw new Error(`connector "${connectorName}" not found in channel "${channel.name}"`);
|
|
476
|
-
return connector;
|
|
477
|
-
}
|
|
478
|
-
requireSlackConnector(channel, connectorName) {
|
|
479
|
-
const connector = this.requireConnector(channel, connectorName);
|
|
480
|
-
if (connector.type !== "slack") throw new Error(`connector "${connectorName}" is type "${connector.type}", not "slack"`);
|
|
481
|
-
return connector;
|
|
482
|
-
}
|
|
483
|
-
requireGhConnector(channel, connectorName) {
|
|
484
|
-
const connector = this.requireConnector(channel, connectorName);
|
|
485
|
-
if (connector.type !== "gh") throw new Error(`connector "${connectorName}" is type "${connector.type}", not "gh"`);
|
|
486
|
-
return connector;
|
|
487
|
-
}
|
|
488
|
-
requireDiscordConnector(channel, connectorName) {
|
|
489
|
-
const connector = this.requireConnector(channel, connectorName);
|
|
490
|
-
if (connector.type !== "discord") throw new Error(`connector "${connectorName}" is type "${connector.type}", not "discord"`);
|
|
491
|
-
return connector;
|
|
492
|
-
}
|
|
493
|
-
requireScheduleConnector(channel, connectorName) {
|
|
494
|
-
const connector = this.requireConnector(channel, connectorName);
|
|
495
|
-
if (connector.type !== "schedule") throw new Error(`connector "${connectorName}" is type "${connector.type}", not "schedule"`);
|
|
496
|
-
return connector;
|
|
497
|
-
}
|
|
498
503
|
assertNoTokenCollision(settings, candidate) {
|
|
499
|
-
const tokens =
|
|
504
|
+
const tokens = connectorTokens(candidate);
|
|
500
505
|
if (tokens.length === 0) return;
|
|
501
506
|
for (const channel of settings.channels) for (const other of channel.connectors) {
|
|
502
507
|
if (other.id === candidate.id) continue;
|
|
503
|
-
for (const token of
|
|
508
|
+
for (const token of connectorTokens(other)) if (tokens.includes(token)) throw new Error(`token already in use by connector "${other.name}" in channel "${channel.name}"`);
|
|
504
509
|
}
|
|
505
510
|
}
|
|
506
|
-
tokensOf(connector) {
|
|
507
|
-
if (connector.type === "slack") return [connector.botToken, connector.appToken];
|
|
508
|
-
if (connector.type === "discord") return [connector.botToken];
|
|
509
|
-
return [];
|
|
510
|
-
}
|
|
511
511
|
};
|
|
512
512
|
//#endregion
|
|
513
513
|
//#region lib/engine/claude/claude.ts
|
|
@@ -1096,14 +1096,18 @@ var FunnelChannelPublisher = class {
|
|
|
1096
1096
|
* The candidates cover:
|
|
1097
1097
|
* 1. dev: this helper lives at lib/gateway/, so daemon.ts is its sibling
|
|
1098
1098
|
* 2. built sibling: dist/gateway/daemon.js if the helper itself ends up at dist/gateway/
|
|
1099
|
-
* 3. bundled: when this helper is inlined into dist/bin.js,
|
|
1099
|
+
* 3. bundled: when this helper is inlined into dist/bin.js, the helper's dir is dist/,
|
|
1100
1100
|
* and daemon.js lives at dist/gateway/daemon.js
|
|
1101
|
+
*
|
|
1102
|
+
* `import.meta.url` works in both Bun and Node test runners; `import.meta.dir`
|
|
1103
|
+
* is Bun-only and breaks vitest.
|
|
1101
1104
|
*/
|
|
1102
1105
|
const resolveDaemonScript = () => {
|
|
1106
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
1103
1107
|
const candidates = [
|
|
1104
|
-
resolve(
|
|
1105
|
-
resolve(
|
|
1106
|
-
resolve(
|
|
1108
|
+
resolve(here, "./daemon.ts"),
|
|
1109
|
+
resolve(here, "./daemon.js"),
|
|
1110
|
+
resolve(here, "./gateway/daemon.js")
|
|
1107
1111
|
];
|
|
1108
1112
|
for (const candidate of candidates) if (existsSync(candidate)) return candidate;
|
|
1109
1113
|
throw new Error(`daemon script not found (looked in ${candidates.join(", ")})`);
|
|
@@ -1174,8 +1178,8 @@ var FunnelGateway = class {
|
|
|
1174
1178
|
"-c",
|
|
1175
1179
|
command
|
|
1176
1180
|
]);
|
|
1177
|
-
const deadline =
|
|
1178
|
-
while (
|
|
1181
|
+
const deadline = this.clock.millis() + STARTUP_TIMEOUT_MS;
|
|
1182
|
+
while (this.clock.millis() < deadline) {
|
|
1179
1183
|
if (this.isRunning()) return true;
|
|
1180
1184
|
await this.sleep(POLL_INTERVAL_MS$1);
|
|
1181
1185
|
}
|
|
@@ -2737,7 +2741,7 @@ const SANDBOX_TMP_DIR = "/sandbox/tmp";
|
|
|
2737
2741
|
* ```
|
|
2738
2742
|
*/
|
|
2739
2743
|
var Funnel = class Funnel {
|
|
2740
|
-
|
|
2744
|
+
memos = {};
|
|
2741
2745
|
constructor(props = {}) {
|
|
2742
2746
|
this.props = props;
|
|
2743
2747
|
Object.freeze(this);
|
|
@@ -2759,12 +2763,6 @@ var Funnel = class Funnel {
|
|
|
2759
2763
|
tmpDir: props.tmpDir ?? SANDBOX_TMP_DIR
|
|
2760
2764
|
});
|
|
2761
2765
|
}
|
|
2762
|
-
memo(key, build) {
|
|
2763
|
-
if (this.cache.has(key)) return this.cache.get(key);
|
|
2764
|
-
const value = build();
|
|
2765
|
-
this.cache.set(key, value);
|
|
2766
|
-
return value;
|
|
2767
|
-
}
|
|
2768
2766
|
/** Resolved on-disk paths the facade will read/write when methods are called. Pure compute, not memoized. */
|
|
2769
2767
|
get paths() {
|
|
2770
2768
|
const dir = this.props.dir ?? FUNNEL_DIR;
|
|
@@ -2776,61 +2774,71 @@ var Funnel = class Funnel {
|
|
|
2776
2774
|
}
|
|
2777
2775
|
/** Filesystem boundary. Defaults to NodeFunnelFileSystem. */
|
|
2778
2776
|
get fs() {
|
|
2779
|
-
|
|
2777
|
+
if (!this.memos.fs) this.memos.fs = this.props.fs ?? new NodeFunnelFileSystem();
|
|
2778
|
+
return this.memos.fs;
|
|
2780
2779
|
}
|
|
2781
2780
|
/** Process runner boundary. Defaults to NodeFunnelProcessRunner. */
|
|
2782
2781
|
get process() {
|
|
2783
|
-
|
|
2782
|
+
if (!this.memos.process) this.memos.process = this.props.process ?? new NodeFunnelProcessRunner();
|
|
2783
|
+
return this.memos.process;
|
|
2784
2784
|
}
|
|
2785
2785
|
/** Logger boundary. Defaults to NodeFunnelLogger. */
|
|
2786
2786
|
get logger() {
|
|
2787
|
-
|
|
2787
|
+
if (!this.memos.logger) this.memos.logger = this.props.logger ?? new NodeFunnelLogger();
|
|
2788
|
+
return this.memos.logger;
|
|
2788
2789
|
}
|
|
2789
2790
|
/** Clock boundary. Defaults to NodeFunnelClock. */
|
|
2790
2791
|
get clock() {
|
|
2791
|
-
|
|
2792
|
+
if (!this.memos.clock) this.memos.clock = this.props.clock ?? new NodeFunnelClock();
|
|
2793
|
+
return this.memos.clock;
|
|
2792
2794
|
}
|
|
2793
2795
|
/** ID generator boundary. Defaults to NodeFunnelIdGenerator. */
|
|
2794
2796
|
get idGenerator() {
|
|
2795
|
-
|
|
2797
|
+
if (!this.memos.idGenerator) this.memos.idGenerator = this.props.idGenerator ?? new NodeFunnelIdGenerator();
|
|
2798
|
+
return this.memos.idGenerator;
|
|
2796
2799
|
}
|
|
2797
2800
|
/** Settings reader. If not injected, a FunnelSettingsStore rooted at `dir` is created. */
|
|
2798
2801
|
get store() {
|
|
2799
|
-
|
|
2802
|
+
if (!this.memos.store) this.memos.store = this.props.store ?? new FunnelSettingsStore({
|
|
2800
2803
|
path: this.paths.settings,
|
|
2801
2804
|
fs: this.fs
|
|
2802
|
-
})
|
|
2805
|
+
});
|
|
2806
|
+
return this.memos.store;
|
|
2803
2807
|
}
|
|
2804
2808
|
/** Pure factory that constructs per-type listeners and adapters from connector configs. */
|
|
2805
2809
|
get factory() {
|
|
2806
|
-
|
|
2810
|
+
if (!this.memos.factory) this.memos.factory = new FunnelConnectorFactory({
|
|
2807
2811
|
fs: this.fs,
|
|
2808
2812
|
process: this.process,
|
|
2809
2813
|
logger: this.logger,
|
|
2810
2814
|
dir: this.paths.dir
|
|
2811
|
-
})
|
|
2815
|
+
});
|
|
2816
|
+
return this.memos.factory;
|
|
2812
2817
|
}
|
|
2813
2818
|
/** Channel CRUD + nested connector CRUD + schedule entries + listener/adapter dispatch. */
|
|
2814
2819
|
get channels() {
|
|
2815
|
-
|
|
2820
|
+
if (!this.memos.channels) this.memos.channels = new FunnelChannels({
|
|
2816
2821
|
store: this.store,
|
|
2817
2822
|
factory: this.factory,
|
|
2818
2823
|
profileChecker: this.profiles,
|
|
2819
2824
|
clock: this.clock,
|
|
2820
2825
|
idGenerator: this.idGenerator
|
|
2821
|
-
})
|
|
2826
|
+
});
|
|
2827
|
+
return this.memos.channels;
|
|
2822
2828
|
}
|
|
2823
2829
|
/** Launch profiles (named presets for `fnl claude`: path + sub-agent + channel id). */
|
|
2824
2830
|
get profiles() {
|
|
2825
|
-
|
|
2831
|
+
if (!this.memos.profiles) this.memos.profiles = new FunnelProfiles({ store: this.store });
|
|
2832
|
+
return this.memos.profiles;
|
|
2826
2833
|
}
|
|
2827
2834
|
/** funnel MCP installer (writes/removes `.mcp.json` entries in target repos). */
|
|
2828
2835
|
get mcp() {
|
|
2829
|
-
|
|
2836
|
+
if (!this.memos.mcp) this.memos.mcp = new FunnelMcp({ fs: this.fs });
|
|
2837
|
+
return this.memos.mcp;
|
|
2830
2838
|
}
|
|
2831
2839
|
/** Launch Claude Code with a channel injected via env, MCP installed, gateway ensured. */
|
|
2832
2840
|
get claude() {
|
|
2833
|
-
|
|
2841
|
+
if (!this.memos.claude) this.memos.claude = new FunnelClaude({
|
|
2834
2842
|
channels: this.channels,
|
|
2835
2843
|
mcp: this.mcp,
|
|
2836
2844
|
gateway: this.gateway,
|
|
@@ -2838,24 +2846,27 @@ var Funnel = class Funnel {
|
|
|
2838
2846
|
process: this.process,
|
|
2839
2847
|
logger: this.logger,
|
|
2840
2848
|
dir: this.paths.dir
|
|
2841
|
-
})
|
|
2849
|
+
});
|
|
2850
|
+
return this.memos.claude;
|
|
2842
2851
|
}
|
|
2843
2852
|
/** Gateway daemon controller (PID-file, start/stop the separate `bun daemon.ts` process). */
|
|
2844
2853
|
get gateway() {
|
|
2845
|
-
|
|
2854
|
+
if (!this.memos.gateway) this.memos.gateway = new FunnelGateway({
|
|
2846
2855
|
fs: this.fs,
|
|
2847
2856
|
process: this.process,
|
|
2848
2857
|
clock: this.clock,
|
|
2849
2858
|
dir: this.paths.dir,
|
|
2850
2859
|
tmpDir: this.paths.tmpDir
|
|
2851
|
-
})
|
|
2860
|
+
});
|
|
2861
|
+
return this.memos.gateway;
|
|
2852
2862
|
}
|
|
2853
2863
|
/** Read / generate the daemon's gateway token (mode 0600 file under `dir`). */
|
|
2854
2864
|
get gatewayToken() {
|
|
2855
|
-
|
|
2865
|
+
if (!this.memos.gatewayToken) this.memos.gatewayToken = new FunnelGatewayToken({
|
|
2856
2866
|
fs: this.fs,
|
|
2857
2867
|
dir: this.paths.dir
|
|
2858
|
-
})
|
|
2868
|
+
});
|
|
2869
|
+
return this.memos.gatewayToken;
|
|
2859
2870
|
}
|
|
2860
2871
|
/**
|
|
2861
2872
|
* HTTP client for `POST /channels/:channel/publish` on the running gateway
|
|
@@ -2863,15 +2874,16 @@ var Funnel = class Funnel {
|
|
|
2863
2874
|
* connector. Returns `{ state: "offline" }` if the daemon isn't up.
|
|
2864
2875
|
*/
|
|
2865
2876
|
get publisher() {
|
|
2866
|
-
|
|
2877
|
+
if (!this.memos.publisher) {
|
|
2867
2878
|
const gateway = this.gateway;
|
|
2868
2879
|
const token = this.gatewayToken;
|
|
2869
|
-
|
|
2880
|
+
this.memos.publisher = new FunnelChannelPublisher({
|
|
2870
2881
|
port: gateway.getPort(),
|
|
2871
2882
|
isDaemonRunning: () => gateway.isRunning(),
|
|
2872
2883
|
getToken: () => token.read()
|
|
2873
2884
|
});
|
|
2874
|
-
}
|
|
2885
|
+
}
|
|
2886
|
+
return this.memos.publisher;
|
|
2875
2887
|
}
|
|
2876
2888
|
/**
|
|
2877
2889
|
* HTTP client for listener operations on the running gateway daemon.
|
|
@@ -2879,15 +2891,16 @@ var Funnel = class Funnel {
|
|
|
2879
2891
|
* paths stay write-only without parsing strings.
|
|
2880
2892
|
*/
|
|
2881
2893
|
get listeners() {
|
|
2882
|
-
|
|
2894
|
+
if (!this.memos.listeners) {
|
|
2883
2895
|
const gateway = this.gateway;
|
|
2884
2896
|
const token = this.gatewayToken;
|
|
2885
|
-
|
|
2897
|
+
this.memos.listeners = new FunnelListenersClient({
|
|
2886
2898
|
port: gateway.getPort(),
|
|
2887
2899
|
isDaemonRunning: () => gateway.isRunning(),
|
|
2888
2900
|
getToken: () => token.read()
|
|
2889
2901
|
});
|
|
2890
|
-
}
|
|
2902
|
+
}
|
|
2903
|
+
return this.memos.listeners;
|
|
2891
2904
|
}
|
|
2892
2905
|
/**
|
|
2893
2906
|
* In-process gateway server. Unlike `gateway.start()` (which spawns a daemon),
|
|
@@ -3016,7 +3029,7 @@ const startChannelServer = async (options = {}) => {
|
|
|
3016
3029
|
const channelId = options.channelId ?? process.env.FUNNEL_CHANNEL_ID;
|
|
3017
3030
|
const channel = channelId ? readChannelConnectors(dir, channelId) : null;
|
|
3018
3031
|
const token = options.token ?? readGatewayToken(dir);
|
|
3019
|
-
const server = new Server
|
|
3032
|
+
const server = new Server({
|
|
3020
3033
|
name: FUNNEL_MCP_NAME,
|
|
3021
3034
|
version: "1.0.0"
|
|
3022
3035
|
}, {
|
|
@@ -6293,4 +6306,4 @@ async function launchTui(funnel) {
|
|
|
6293
6306
|
});
|
|
6294
6307
|
}
|
|
6295
6308
|
//#endregion
|
|
6296
|
-
export { DEFAULT_GATEWAY_TOKEN_PATH, FUNNEL_DIR, FUNNEL_MCP_COMMAND, FUNNEL_MCP_NAME, Funnel, FunnelBroadcaster, FunnelChannelPublisher, FunnelChannels, FunnelClaude, FunnelClock, FunnelConnectorFactory, FunnelConnectorListener, FunnelEventStore, FunnelFileSystem, FunnelGateway, FunnelGatewayServer, FunnelGatewayToken, FunnelIdGenerator, FunnelListenerSupervisor, FunnelListenersClient, FunnelLogger, FunnelMcp, FunnelProcessRunner, FunnelProfiles, FunnelSettingsReader, FunnelSettingsStore, MemoryFunnelClock, MemoryFunnelFileSystem, MemoryFunnelIdGenerator, MemoryFunnelLogger, MemoryFunnelProcessRunner, MockFunnelSettingsReader, NodeFunnelClock, NodeFunnelFileSystem, NodeFunnelIdGenerator, NodeFunnelLogger, NodeFunnelProcessRunner, NoopFunnelLogger, SETTINGS_PATH, SETTINGS_VERSION, channelConfigSchema, channelDeliveryModeSchema, app as cliApp, connectorConfigSchema, createCliApp, createSettings, discordConnectorSchema, factory, funnelEventSchema, ghConnectorSchema, launchTui, profileConfigSchema, publishRequestSchema, publishResponseSchema, queryToCliArgs, scheduleCatchupPolicySchema, scheduleConnectorSchema, scheduleEntrySchema, settingsSchema, slackConnectorSchema, startChannelServer, toRequest };
|
|
6309
|
+
export { DEFAULT_GATEWAY_TOKEN_PATH, FUNNEL_DIR, FUNNEL_MCP_COMMAND, FUNNEL_MCP_NAME, Funnel, FunnelBroadcaster, FunnelChannelPublisher, FunnelChannels, FunnelClaude, FunnelClock, FunnelConnectorFactory, FunnelConnectorListener, FunnelEventStore, FunnelFileSystem, FunnelGateway, FunnelGatewayServer, FunnelGatewayToken, FunnelIdGenerator, FunnelListenerSupervisor, FunnelListenersClient, FunnelLogger, FunnelMcp, FunnelProcessRunner, FunnelProfiles, FunnelSettingsReader, FunnelSettingsStore, FunnelSlackEventProcessor, MemoryFunnelClock, MemoryFunnelFileSystem, MemoryFunnelIdGenerator, MemoryFunnelLogger, MemoryFunnelProcessRunner, MockFunnelSettingsReader, NodeFunnelClock, NodeFunnelFileSystem, NodeFunnelIdGenerator, NodeFunnelLogger, NodeFunnelProcessRunner, NoopFunnelLogger, SETTINGS_PATH, SETTINGS_VERSION, channelConfigSchema, channelDeliveryModeSchema, app as cliApp, connectorConfigSchema, createCliApp, createSettings, discordConnectorSchema, factory, funnelEventSchema, ghConnectorSchema, launchTui, profileConfigSchema, publishRequestSchema, publishResponseSchema, queryToCliArgs, scheduleCatchupPolicySchema, scheduleConnectorSchema, scheduleEntrySchema, settingsSchema, slackConnectorSchema, startChannelServer, toRequest };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
//#region lib/connectors/slack-connector-schema.d.ts
|
|
4
|
+
declare const slackConnectorSchema: z.ZodObject<{
|
|
5
|
+
id: z.ZodString;
|
|
6
|
+
name: z.ZodString;
|
|
7
|
+
type: z.ZodLiteral<"slack">;
|
|
8
|
+
botToken: z.ZodString;
|
|
9
|
+
appToken: z.ZodString;
|
|
10
|
+
createdAt: z.ZodOptional<z.ZodString>;
|
|
11
|
+
updatedAt: z.ZodOptional<z.ZodString>;
|
|
12
|
+
}, z.core.$strip>;
|
|
13
|
+
type SlackConnectorConfig = z.infer<typeof slackConnectorSchema>;
|
|
14
|
+
//#endregion
|
|
15
|
+
//#region lib/connectors/slack-event-processor.d.ts
|
|
16
|
+
type SlackRawEvent = Record<string, unknown>;
|
|
17
|
+
type SlackProcessedSkip = {
|
|
18
|
+
skip: true;
|
|
19
|
+
};
|
|
20
|
+
type SlackProcessedEmit = {
|
|
21
|
+
skip: false;
|
|
22
|
+
content: string;
|
|
23
|
+
meta: Record<string, string>;
|
|
24
|
+
shouldReact: boolean;
|
|
25
|
+
channel: string;
|
|
26
|
+
timestamp: string;
|
|
27
|
+
};
|
|
28
|
+
type SlackProcessed = SlackProcessedSkip | SlackProcessedEmit;
|
|
29
|
+
type Props = {
|
|
30
|
+
ownBotUserId: string;
|
|
31
|
+
ownBotId: string;
|
|
32
|
+
now?: () => number;
|
|
33
|
+
};
|
|
34
|
+
declare class FunnelSlackEventProcessor {
|
|
35
|
+
private readonly ownBotUserId;
|
|
36
|
+
private readonly ownBotId;
|
|
37
|
+
private readonly now;
|
|
38
|
+
private readonly dedup;
|
|
39
|
+
constructor(props: Props);
|
|
40
|
+
process(event: SlackRawEvent): SlackProcessed;
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
export { SlackRawEvent as a, SlackProcessedSkip as i, SlackProcessed as n, SlackConnectorConfig as o, SlackProcessedEmit as r, slackConnectorSchema as s, FunnelSlackEventProcessor as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@interactive-inc/claude-funnel",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.1",
|
|
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",
|
|
@@ -27,11 +27,6 @@
|
|
|
27
27
|
"funnel": "./dist/bin.js"
|
|
28
28
|
},
|
|
29
29
|
"files": [
|
|
30
|
-
"lib/**/*.ts",
|
|
31
|
-
"lib/**/*.tsx",
|
|
32
|
-
"!lib/**/*.test.ts",
|
|
33
|
-
"!lib/**/*.test.tsx",
|
|
34
|
-
"!lib/**/*.bun-test.ts",
|
|
35
30
|
"dist/**/*",
|
|
36
31
|
"README.md",
|
|
37
32
|
"LICENSE"
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
|
|
3
|
-
//#region lib/connectors/slack-connector-schema.d.ts
|
|
4
|
-
declare const slackConnectorSchema: z.ZodObject<{
|
|
5
|
-
id: z.ZodString;
|
|
6
|
-
name: z.ZodString;
|
|
7
|
-
type: z.ZodLiteral<"slack">;
|
|
8
|
-
botToken: z.ZodString;
|
|
9
|
-
appToken: z.ZodString;
|
|
10
|
-
createdAt: z.ZodOptional<z.ZodString>;
|
|
11
|
-
updatedAt: z.ZodOptional<z.ZodString>;
|
|
12
|
-
}, z.core.$strip>;
|
|
13
|
-
type SlackConnectorConfig = z.infer<typeof slackConnectorSchema>;
|
|
14
|
-
//#endregion
|
|
15
|
-
export { slackConnectorSchema as n, SlackConnectorConfig as t };
|
package/lib/bin.ts
DELETED