@interactive-inc/claude-funnel 0.31.0 → 0.33.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/index.d.ts CHANGED
@@ -607,6 +607,7 @@ declare const channelSpecSchema: z.ZodObject<{
607
607
  }, z.core.$strip>;
608
608
  type ChannelSpec = z.infer<typeof channelSpecSchema>;
609
609
  declare const profileSpecSchema: z.ZodObject<{
610
+ name: z.ZodString;
610
611
  channel: z.ZodString;
611
612
  options: z.ZodOptional<z.ZodArray<z.ZodString>>;
612
613
  env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
@@ -635,6 +636,7 @@ declare const localConfigSchema: z.ZodObject<{
635
636
  }, z.core.$strip>], "type">>>;
636
637
  }, z.core.$strip>>;
637
638
  profiles: z.ZodOptional<z.ZodArray<z.ZodObject<{
639
+ name: z.ZodString;
638
640
  channel: z.ZodString;
639
641
  options: z.ZodOptional<z.ZodArray<z.ZodString>>;
640
642
  env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
@@ -1490,6 +1492,15 @@ declare const funnelJsonSchema: () => Record<string, unknown>;
1490
1492
  * spawned with the env set resolves the override.
1491
1493
  */
1492
1494
  declare function resolveFunnelDir(): string;
1495
+ declare const DEFAULT_GATEWAY_PORT = 9742;
1496
+ /**
1497
+ * Resolves the gateway port. Defaults to 9742 — the port a programmatically
1498
+ * hosted gateway (`new Funnel().gatewayServer()`) uses. The `funnel` CLI entry
1499
+ * sets `FUNNEL_PORT` to a distinct default so a CLI launch never collides with
1500
+ * an embedding app's gateway on 9742. Read at call time so a daemon spawned
1501
+ * with the env set resolves the override.
1502
+ */
1503
+ declare function resolveFunnelPort(): number;
1493
1504
  declare const FUNNEL_DIR: string;
1494
1505
  declare const SETTINGS_PATH: string;
1495
1506
  type Deps = {
@@ -4578,4 +4589,4 @@ ${string}`;
4578
4589
  };
4579
4590
  }, "/", "/update">;
4580
4591
  //#endregion
4581
- export { AliveStub, AttachOptions, BroadcastEvent, BroadcastSubscriber, CONNECTOR_CONNECTION_STATUSES, ChannelConfig, ChannelConnectorView, ChannelDeliveryMode, ChannelServerOptions, ChannelSpec, ConnectorConfig, ConnectorConnectionEvent, ConnectorConnectionQuery, ConnectorConnectionRecord, ConnectorConnectionStatus, ConnectorDiagnosticLog, ConnectorDiagnosticSqlReader, ConnectorProcessedEvent, ConnectorProcessedQuery, ConnectorProcessedRecord, ConnectorQuery, ConnectorRawEvent, ConnectorRawQuery, ConnectorRawRecord, ConnectorSpec, ConnectorSyncOutcome, 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, FunnelEventLog, FunnelEventRecord, FunnelFileSystem, FunnelGateway, FunnelGatewayServer, FunnelGatewayToken, FunnelIdGenerator, FunnelListenerSupervisor, FunnelListenersClient, FunnelLocalConfig, FunnelLocalConfigSync, FunnelLocalConfigWriter, FunnelLogger, FunnelMcp, FunnelProcessRunner, FunnelProfiles, FunnelSettingsReader, FunnelSettingsStore, FunnelSlackEventProcessor, FunnelTokenPrompter, type GatewayEmitInput, type GatewayRouteDeps, type Env$1 as GatewayServerEnv, GhConnectorConfig, LOCAL_CONFIG_FILENAME, LaunchOptions, ListListenersResult, ListenerEntry, ListenerOpResult, LocalConfig, LocalConfigSyncResult, LogEntry, MemoryConnectorDiagnosticLog, MemoryFunnelClock, MemoryFunnelEventLog, MemoryFunnelFileSystem, MemoryFunnelIdGenerator, MemoryFunnelLogger, MemoryFunnelProcessRunner, MemoryFunnelTokenPrompter, MemoryProcessCall, MemoryProcessHandler, MemoryProcessResponse, MemoryProcessSyncHandler, MockFunnelSettingsReader, NodeFunnelClock, NodeFunnelFileSystem, NodeFunnelIdGenerator, NodeFunnelLogger, NodeFunnelProcessRunner, NodeFunnelTokenPrompter, NoopFunnelLogger, NotifyFn, OnFunnelError, ProcessListStub, ProcessSnapshot, ProfileConfig, ProfileSpec, PublishRequest, PublishResponse, PublishResult, ReplayableEvent, RunOptions, RunResult, SETTINGS_PATH, SETTINGS_VERSION, ScheduleCatchupPolicy, ScheduleConnectorConfig, ScheduleEntry, ScheduleListenerOptions, Settings, SlackConnectorConfig, SlackListenerOptions, SlackProcessed, SlackProcessedEmit, SlackProcessedSkip, SlackRawEvent, SlackSkipReason, SqliteConnectorDiagnosticLog, SqliteFunnelEventLog, StoredConnectionEvent, StoredProcessedEvent, StoredRawEvent, channelConfigSchema, channelDeliveryModeSchema, channelSpecSchema, app as cliApp, connectorConfigSchema, connectorConnectionEventSchema, connectorProcessedEventSchema, connectorRawEventSchema, connectorSpecSchema, createCliApp, createSettings, discordConnectorSchema, factory, funnelEventSchema, funnelJsonSchema, ghConnectorSchema, localConfigSchema, profileConfigSchema, profileSpecSchema, publishRequestSchema, publishResponseSchema, queryToCliArgs, resolveFunnelDir, scheduleCatchupPolicySchema, scheduleConnectorSchema, scheduleEntrySchema, settingsSchema, slackConnectorSchema, startChannelServer, toRequest };
4592
+ export { AliveStub, AttachOptions, BroadcastEvent, BroadcastSubscriber, CONNECTOR_CONNECTION_STATUSES, ChannelConfig, ChannelConnectorView, ChannelDeliveryMode, ChannelServerOptions, ChannelSpec, ConnectorConfig, ConnectorConnectionEvent, ConnectorConnectionQuery, ConnectorConnectionRecord, ConnectorConnectionStatus, ConnectorDiagnosticLog, ConnectorDiagnosticSqlReader, ConnectorProcessedEvent, ConnectorProcessedQuery, ConnectorProcessedRecord, ConnectorQuery, ConnectorRawEvent, ConnectorRawQuery, ConnectorRawRecord, ConnectorSpec, ConnectorSyncOutcome, ConnectorType, DEFAULT_GATEWAY_PORT, 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, FunnelEventLog, FunnelEventRecord, FunnelFileSystem, FunnelGateway, FunnelGatewayServer, FunnelGatewayToken, FunnelIdGenerator, FunnelListenerSupervisor, FunnelListenersClient, FunnelLocalConfig, FunnelLocalConfigSync, FunnelLocalConfigWriter, FunnelLogger, FunnelMcp, FunnelProcessRunner, FunnelProfiles, FunnelSettingsReader, FunnelSettingsStore, FunnelSlackEventProcessor, FunnelTokenPrompter, type GatewayEmitInput, type GatewayRouteDeps, type Env$1 as GatewayServerEnv, GhConnectorConfig, LOCAL_CONFIG_FILENAME, LaunchOptions, ListListenersResult, ListenerEntry, ListenerOpResult, LocalConfig, LocalConfigSyncResult, LogEntry, MemoryConnectorDiagnosticLog, MemoryFunnelClock, MemoryFunnelEventLog, MemoryFunnelFileSystem, MemoryFunnelIdGenerator, MemoryFunnelLogger, MemoryFunnelProcessRunner, MemoryFunnelTokenPrompter, MemoryProcessCall, MemoryProcessHandler, MemoryProcessResponse, MemoryProcessSyncHandler, MockFunnelSettingsReader, NodeFunnelClock, NodeFunnelFileSystem, NodeFunnelIdGenerator, NodeFunnelLogger, NodeFunnelProcessRunner, NodeFunnelTokenPrompter, NoopFunnelLogger, NotifyFn, OnFunnelError, ProcessListStub, ProcessSnapshot, ProfileConfig, ProfileSpec, PublishRequest, PublishResponse, PublishResult, ReplayableEvent, RunOptions, RunResult, SETTINGS_PATH, SETTINGS_VERSION, ScheduleCatchupPolicy, ScheduleConnectorConfig, ScheduleEntry, ScheduleListenerOptions, Settings, SlackConnectorConfig, SlackListenerOptions, SlackProcessed, SlackProcessedEmit, SlackProcessedSkip, SlackRawEvent, SlackSkipReason, SqliteConnectorDiagnosticLog, SqliteFunnelEventLog, StoredConnectionEvent, StoredProcessedEvent, StoredRawEvent, channelConfigSchema, channelDeliveryModeSchema, channelSpecSchema, app as cliApp, connectorConfigSchema, connectorConnectionEventSchema, connectorProcessedEventSchema, connectorRawEventSchema, connectorSpecSchema, createCliApp, createSettings, discordConnectorSchema, factory, funnelEventSchema, funnelJsonSchema, ghConnectorSchema, localConfigSchema, profileConfigSchema, profileSpecSchema, publishRequestSchema, publishResponseSchema, queryToCliArgs, resolveFunnelDir, resolveFunnelPort, scheduleCatchupPolicySchema, scheduleConnectorSchema, scheduleEntrySchema, settingsSchema, slackConnectorSchema, startChannelServer, toRequest };
package/dist/index.js CHANGED
@@ -112,6 +112,17 @@ function resolveFunnelDir() {
112
112
  if (override && override.length > 0) return override;
113
113
  return join(homedir(), ".funnel");
114
114
  }
115
+ const DEFAULT_GATEWAY_PORT = 9742;
116
+ /**
117
+ * Resolves the gateway port. Defaults to 9742 — the port a programmatically
118
+ * hosted gateway (`new Funnel().gatewayServer()`) uses. The `funnel` CLI entry
119
+ * sets `FUNNEL_PORT` to a distinct default so a CLI launch never collides with
120
+ * an embedding app's gateway on 9742. Read at call time so a daemon spawned
121
+ * with the env set resolves the override.
122
+ */
123
+ function resolveFunnelPort() {
124
+ return Number(process.env.FUNNEL_PORT) || 9742;
125
+ }
115
126
  const FUNNEL_DIR = join(homedir(), ".funnel");
116
127
  const SETTINGS_PATH = join(FUNNEL_DIR, "settings.json");
117
128
  const defaultFs$5 = new NodeFunnelFileSystem();
@@ -923,7 +934,9 @@ const channelSpecSchema = z.object({
923
934
  connectors: z.array(connectorSpecSchema).optional()
924
935
  });
925
936
  const profileSpecSchema = z.object({
926
- /** Name of the channel (declared in `channels[]`) this profile subscribes to. */
937
+ /** Handle for `fnl claude --profile <name>`. A profile is only launchable by this name. */
938
+ name: z.string(),
939
+ /** Name of the channel (declared in `channels[]`) this profile binds. The profile depends on the channel, never the reverse. */
927
940
  channel: z.string(),
928
941
  /** Args prepended to the claude argv on every launch through this profile. */
929
942
  options: z.array(z.string()).optional(),
@@ -986,11 +999,11 @@ var FunnelLocalConfig = class {
986
999
  const profiles = config.profiles ?? [];
987
1000
  if (profiles.length === 0) return;
988
1001
  const channelNames = new Set(config.channels.map((channel) => channel.name));
989
- const boundChannels = /* @__PURE__ */ new Set();
1002
+ const seenNames = /* @__PURE__ */ new Set();
990
1003
  for (const profile of profiles) {
991
- if (!channelNames.has(profile.channel)) throw new Error(`${LOCAL_CONFIG_FILENAME} is invalid: a profile binds channel "${profile.channel}", which is not declared in channels[]`);
992
- if (boundChannels.has(profile.channel)) throw new Error(`${LOCAL_CONFIG_FILENAME} is invalid: channel "${profile.channel}" has more than one profile; only the first is applied remove the extras`);
993
- boundChannels.add(profile.channel);
1004
+ if (!channelNames.has(profile.channel)) throw new Error(`${LOCAL_CONFIG_FILENAME} is invalid: profile "${profile.name}" binds channel "${profile.channel}", which is not declared in channels[]`);
1005
+ if (seenNames.has(profile.name)) throw new Error(`${LOCAL_CONFIG_FILENAME} is invalid: more than one profile is named "${profile.name}" names must be unique`);
1006
+ seenNames.add(profile.name);
994
1007
  }
995
1008
  }
996
1009
  };
@@ -1800,7 +1813,6 @@ const resolveDaemonScript = () => {
1800
1813
  };
1801
1814
  //#endregion
1802
1815
  //#region lib/gateway/gateway.ts
1803
- const DEFAULT_PORT$1 = 9742;
1804
1816
  const STARTUP_TIMEOUT_MS = 5e3;
1805
1817
  const SIGTERM_TIMEOUT_MS = 2e3;
1806
1818
  const POLL_INTERVAL_MS = 100;
@@ -1834,7 +1846,7 @@ var FunnelGateway = class {
1834
1846
  this.tmpDir = deps.tmpDir ?? funnelTmpDir();
1835
1847
  this.pidFile = join(this.dir, "gateway.pid");
1836
1848
  this.gatewayLog = join(this.tmpDir, "gateway.log");
1837
- this.port = deps.port ?? DEFAULT_PORT$1;
1849
+ this.port = deps.port ?? resolveFunnelPort();
1838
1850
  this.sleep = deps.sleep ?? defaultSleep$1;
1839
1851
  Object.freeze(this);
1840
1852
  }
@@ -3042,7 +3054,6 @@ const statusHandler$1 = factory$1.createHandlers((c) => {
3042
3054
  const gatewayRoutes = factory$1.createApp().get("/health", ...healthHandler).get("/status", ...statusHandler$1).get("/listeners", ...listenersListHandler).post("/listeners/:channel/:connector/start", ...listenersStartHandler).delete("/listeners/:channel/:connector", ...listenersStopHandler).post("/listeners/:channel/:connector/restart", ...listenersRestartHandler).post("/channels/:channel/connectors/:connector/call", ...channelsConnectorsCallHandler).post("/channels/:channel/publish", ...channelsPublishHandler$1);
3043
3055
  //#endregion
3044
3056
  //#region lib/gateway/gateway-server.ts
3045
- const DEFAULT_PORT = 9742;
3046
3057
  const DEFAULT_HOST = "127.0.0.1";
3047
3058
  const LOOPBACK_HOSTS = new Set([
3048
3059
  "127.0.0.1",
@@ -3085,7 +3096,7 @@ var FunnelGatewayServer = class {
3085
3096
  constructor(deps) {
3086
3097
  this.channels = deps.channels;
3087
3098
  this.settings = deps.settings;
3088
- this.port = deps.port ?? DEFAULT_PORT;
3099
+ this.port = deps.port ?? resolveFunnelPort();
3089
3100
  this.hostname = deps.hostname ?? DEFAULT_HOST;
3090
3101
  this.dbPath = deps.dbPath ?? defaultDbPath();
3091
3102
  this.process = deps.process;
@@ -3855,10 +3866,9 @@ const usageHintForType = (type) => {
3855
3866
  //#endregion
3856
3867
  //#region lib/engine/mcp/channel-server.ts
3857
3868
  const DEFAULT_FUNNEL_DIR = join(homedir(), ".funnel");
3858
- const DEFAULT_GATEWAY_BASE_URL = "http://localhost:9742";
3859
3869
  const startChannelServer = async (options = {}) => {
3860
3870
  const dir = options.dir ?? DEFAULT_FUNNEL_DIR;
3861
- const gatewayBaseUrl = options.gatewayUrl ?? process.env.FUNNEL_GATEWAY_URL ?? DEFAULT_GATEWAY_BASE_URL;
3871
+ const gatewayBaseUrl = options.gatewayUrl ?? process.env.FUNNEL_GATEWAY_URL ?? `http://localhost:${resolveFunnelPort()}`;
3862
3872
  const gatewayWsUrl = `${gatewayBaseUrl.replace(/^http/, "ws")}/ws`;
3863
3873
  const channelId = options.channelId ?? process.env.FUNNEL_CHANNEL_ID;
3864
3874
  const channel = channelId ? readChannelConnectors(dir, channelId) : null;
@@ -5385,7 +5395,7 @@ Spawned as a detached background process so it keeps running after the terminal
5385
5395
  On macOS wraps the process with caffeinate -is by default to prevent idle and system sleep.
5386
5396
  Use --no-caffeine to disable caffeinate.
5387
5397
 
5388
- port: 9742 (override via FUNNEL_PORT)
5398
+ port: 9743 (CLI default; override via FUNNEL_PORT)
5389
5399
  pid: ~/.funnel/gateway.pid
5390
5400
  log: ${join(funnelTmpDir(), "gateway.log")}
5391
5401
 
@@ -5745,4 +5755,4 @@ const createCliApp = (funnel) => {
5745
5755
  /** CLI Hono app wired to a default `new Funnel()`. For embedding with a custom Funnel use `createCliApp`. */
5746
5756
  const app = createCliApp(new Funnel());
5747
5757
  //#endregion
5748
- export { CONNECTOR_CONNECTION_STATUSES, ConnectorDiagnosticLog, ConnectorDiagnosticSqlReader, DEFAULT_GATEWAY_TOKEN_PATH, FUNNEL_DIR, FUNNEL_MCP_COMMAND, FUNNEL_MCP_NAME, Funnel, FunnelBroadcaster, FunnelChannelPublisher, FunnelChannels, FunnelClaude, FunnelClock, FunnelConnectorFactory, FunnelConnectorListener, FunnelEventLog, FunnelFileSystem, FunnelGateway, FunnelGatewayServer, FunnelGatewayToken, FunnelIdGenerator, FunnelListenerSupervisor, FunnelListenersClient, FunnelLocalConfig, FunnelLocalConfigSync, FunnelLocalConfigWriter, FunnelLogger, FunnelMcp, FunnelProcessRunner, FunnelProfiles, FunnelSettingsReader, FunnelSettingsStore, FunnelSlackEventProcessor, FunnelTokenPrompter, LOCAL_CONFIG_FILENAME, MemoryConnectorDiagnosticLog, MemoryFunnelClock, MemoryFunnelEventLog, MemoryFunnelFileSystem, MemoryFunnelIdGenerator, MemoryFunnelLogger, MemoryFunnelProcessRunner, MemoryFunnelTokenPrompter, MockFunnelSettingsReader, NodeFunnelClock, NodeFunnelFileSystem, NodeFunnelIdGenerator, NodeFunnelLogger, NodeFunnelProcessRunner, NodeFunnelTokenPrompter, NoopFunnelLogger, SETTINGS_PATH, SETTINGS_VERSION, SqliteConnectorDiagnosticLog, SqliteFunnelEventLog, channelConfigSchema, channelDeliveryModeSchema, channelSpecSchema, app as cliApp, connectorConfigSchema, connectorConnectionEventSchema, connectorProcessedEventSchema, connectorRawEventSchema, connectorSpecSchema, createCliApp, createSettings, discordConnectorSchema, factory, funnelEventSchema, funnelJsonSchema, ghConnectorSchema, localConfigSchema, profileConfigSchema, profileSpecSchema, publishRequestSchema, publishResponseSchema, queryToCliArgs, resolveFunnelDir, scheduleCatchupPolicySchema, scheduleConnectorSchema, scheduleEntrySchema, settingsSchema, slackConnectorSchema, startChannelServer, toRequest };
5758
+ export { CONNECTOR_CONNECTION_STATUSES, ConnectorDiagnosticLog, ConnectorDiagnosticSqlReader, DEFAULT_GATEWAY_PORT, DEFAULT_GATEWAY_TOKEN_PATH, FUNNEL_DIR, FUNNEL_MCP_COMMAND, FUNNEL_MCP_NAME, Funnel, FunnelBroadcaster, FunnelChannelPublisher, FunnelChannels, FunnelClaude, FunnelClock, FunnelConnectorFactory, FunnelConnectorListener, FunnelEventLog, FunnelFileSystem, FunnelGateway, FunnelGatewayServer, FunnelGatewayToken, FunnelIdGenerator, FunnelListenerSupervisor, FunnelListenersClient, FunnelLocalConfig, FunnelLocalConfigSync, FunnelLocalConfigWriter, FunnelLogger, FunnelMcp, FunnelProcessRunner, FunnelProfiles, FunnelSettingsReader, FunnelSettingsStore, FunnelSlackEventProcessor, FunnelTokenPrompter, LOCAL_CONFIG_FILENAME, MemoryConnectorDiagnosticLog, MemoryFunnelClock, MemoryFunnelEventLog, MemoryFunnelFileSystem, MemoryFunnelIdGenerator, MemoryFunnelLogger, MemoryFunnelProcessRunner, MemoryFunnelTokenPrompter, MockFunnelSettingsReader, NodeFunnelClock, NodeFunnelFileSystem, NodeFunnelIdGenerator, NodeFunnelLogger, NodeFunnelProcessRunner, NodeFunnelTokenPrompter, NoopFunnelLogger, SETTINGS_PATH, SETTINGS_VERSION, SqliteConnectorDiagnosticLog, SqliteFunnelEventLog, channelConfigSchema, channelDeliveryModeSchema, channelSpecSchema, app as cliApp, connectorConfigSchema, connectorConnectionEventSchema, connectorProcessedEventSchema, connectorRawEventSchema, connectorSpecSchema, createCliApp, createSettings, discordConnectorSchema, factory, funnelEventSchema, funnelJsonSchema, ghConnectorSchema, localConfigSchema, profileConfigSchema, profileSpecSchema, publishRequestSchema, publishResponseSchema, queryToCliArgs, resolveFunnelDir, resolveFunnelPort, scheduleCatchupPolicySchema, scheduleConnectorSchema, scheduleEntrySchema, settingsSchema, slackConnectorSchema, startChannelServer, toRequest };
@@ -112,6 +112,9 @@
112
112
  "items": {
113
113
  "type": "object",
114
114
  "properties": {
115
+ "name": {
116
+ "type": "string"
117
+ },
115
118
  "channel": {
116
119
  "type": "string"
117
120
  },
@@ -135,6 +138,7 @@
135
138
  }
136
139
  },
137
140
  "required": [
141
+ "name",
138
142
  "channel"
139
143
  ],
140
144
  "additionalProperties": false
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@interactive-inc/claude-funnel",
3
- "version": "0.31.0",
3
+ "version": "0.33.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",