@interactive-inc/claude-funnel 0.59.0 → 0.59.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.
@@ -1,4 +1,4 @@
1
- import { t as ghConnectorSchema } from "./gh-connector-schema-DUcZgN2Q.js";
1
+ import { t as ghConnectorSchema } from "./gh-connector-schema-ClPLSYD9.js";
2
2
  import { t as NodeFunnelFileSystem } from "./node-file-system-BcrmWN9I.js";
3
3
  import { n as FunnelIdGenerator, t as FunnelSettingsReader } from "./settings-reader-DPqrpV7s.js";
4
4
  import { t as discordConnectorSchema } from "./discord-connector-schema-B_N6IXLz.js";
package/dist/gateway.d.ts CHANGED
@@ -1,3 +1,3 @@
1
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 "./diagnostic-log-Cb3v8P7p.js";
2
- import { $ as PublishResult, J as MemoryFunnelEventLog, K as MemoryConnectorDiagnosticLog, Q as PublishResponse, X as FunnelChannelPublisher, Y as SqliteFunnelEventLog, Z as PublishRequest, _t as FunnelListenerSupervisor, at as ChannelWsUrlInput, bt as FunnelBroadcaster, ct as FunnelGatewayServer, dt as FunnelEventLog, et as publishRequestSchema, ft as FunnelEventRecord, gt as GatewayRouteDeps, ht as GatewayEmitInput, it as gatewayLoopbackUrl, lt as GatewayEventStore, mt as Env, nt as DEFAULT_GATEWAY_TOKEN_PATH, ot as channelWsProtocols, pt as funnelEventSchema, q as SqliteConnectorDiagnosticLog, rt as FunnelGatewayToken, st as channelWsUrl, t as GatewayApp, tt as publishResponseSchema, ut as FunnelEvent, vt as BroadcastEvent, xt as ReplayableEvent, yt as BroadcastSubscriber } from "./index-Conbxl5O.js";
2
+ import { $ as PublishResponse, J as SqliteConnectorDiagnosticLog, Q as PublishRequest, St as ReplayableEvent, X as SqliteFunnelEventLog, Y as MemoryFunnelEventLog, Z as FunnelChannelPublisher, _t as GatewayRouteDeps, at as gatewayLoopbackUrl, bt as BroadcastSubscriber, ct as channelWsUrl, dt as FunnelEvent, et as PublishResult, ft as FunnelEventLog, gt as GatewayEmitInput, ht as Env, it as FunnelGatewayToken, lt as FunnelGatewayServer, mt as funnelEventSchema, nt as publishResponseSchema, ot as ChannelWsUrlInput, pt as FunnelEventRecord, q as MemoryConnectorDiagnosticLog, rt as DEFAULT_GATEWAY_TOKEN_PATH, st as channelWsProtocols, t as GatewayApp, tt as publishRequestSchema, ut as GatewayEventStore, vt as FunnelListenerSupervisor, xt as FunnelBroadcaster, yt as BroadcastEvent } from "./index-D7mjirUL.js";
3
3
  export { BroadcastEvent, BroadcastSubscriber, CONNECTOR_CONNECTION_STATUSES, ChannelWsUrlInput, 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, GatewayEventStore, type GatewayRouteDeps, type Env as GatewayServerEnv, MemoryConnectorDiagnosticLog, MemoryFunnelEventLog, PublishRequest, PublishResponse, PublishResult, ReplayableEvent, SqliteConnectorDiagnosticLog, SqliteFunnelEventLog, StoredConnectionEvent, StoredProcessedEvent, StoredRawEvent, channelWsProtocols, channelWsUrl, connectorConnectionEventSchema, connectorProcessedEventSchema, connectorRawEventSchema, funnelEventSchema, gatewayLoopbackUrl, publishRequestSchema, publishResponseSchema };
package/dist/gateway.js CHANGED
@@ -1,3 +1,3 @@
1
- import { t as gatewayLoopbackUrl } from "./gateway-base-url-6foMXfFf.js";
2
- import { S as publishResponseSchema, _ as funnelEventSchema, a as connectorConnectionEventSchema, b as FunnelChannelPublisher, c as MemoryFunnelEventLog, d as DEFAULT_GATEWAY_TOKEN_PATH, f as FunnelGatewayToken, g as FunnelEventLog, h as SqliteFunnelEventLog, i as ConnectorDiagnosticLog, l as channelWsProtocols, m as FunnelListenerSupervisor, n as SqliteConnectorDiagnosticLog, o as connectorProcessedEventSchema, p as FunnelGatewayServer, r as CONNECTOR_CONNECTION_STATUSES, s as connectorRawEventSchema, t as MemoryConnectorDiagnosticLog, u as channelWsUrl, v as FunnelBroadcaster, x as publishRequestSchema } from "./memory-diagnostic-log-5LzwJ_F7.js";
1
+ import { t as gatewayLoopbackUrl } from "./gateway-base-url-DxVjjDoW.js";
2
+ import { S as publishResponseSchema, _ as funnelEventSchema, a as connectorConnectionEventSchema, b as FunnelChannelPublisher, c as MemoryFunnelEventLog, d as DEFAULT_GATEWAY_TOKEN_PATH, f as FunnelGatewayToken, g as FunnelEventLog, h as SqliteFunnelEventLog, i as ConnectorDiagnosticLog, l as channelWsProtocols, m as FunnelListenerSupervisor, n as SqliteConnectorDiagnosticLog, o as connectorProcessedEventSchema, p as FunnelGatewayServer, r as CONNECTOR_CONNECTION_STATUSES, s as connectorRawEventSchema, t as MemoryConnectorDiagnosticLog, u as channelWsUrl, v as FunnelBroadcaster, x as publishRequestSchema } from "./memory-diagnostic-log-B9Us7X05.js";
3
3
  export { CONNECTOR_CONNECTION_STATUSES, ConnectorDiagnosticLog, DEFAULT_GATEWAY_TOKEN_PATH, FunnelBroadcaster, FunnelChannelPublisher, FunnelEventLog, FunnelGatewayServer, FunnelGatewayToken, FunnelListenerSupervisor, MemoryConnectorDiagnosticLog, MemoryFunnelEventLog, SqliteConnectorDiagnosticLog, SqliteFunnelEventLog, channelWsProtocols, channelWsUrl, connectorConnectionEventSchema, connectorProcessedEventSchema, connectorRawEventSchema, funnelEventSchema, gatewayLoopbackUrl, publishRequestSchema, publishResponseSchema };
@@ -10,7 +10,9 @@ import { z } from "zod";
10
10
  * callers do not branch on `process.platform`. `isAlive` checks whether a PID
11
11
  * names a live (non-zombie) process; `listProcessesContaining` enumerates
12
12
  * processes whose command line includes `marker`, used for funnel-gateway tag
13
- * matching across daemons that share a home dir.
13
+ * matching across daemons that share a home dir. `getStartTime` returns a
14
+ * stable string identifying when a PID was started, used to detect PID reuse
15
+ * after the original process died abnormally (no exit hook fired).
14
16
  */
15
17
  var FunnelProcessRunner = class {};
16
18
  //#endregion
@@ -145,6 +147,11 @@ var NodeFunnelProcessRunner = class extends FunnelProcessRunner {
145
147
  if (isWindows()) return this.listProcessesContainingWindows(marker);
146
148
  return this.listProcessesContainingPosix(marker);
147
149
  }
150
+ getStartTime(pid) {
151
+ if (!Number.isInteger(pid) || pid <= 0) return null;
152
+ if (isWindows()) return this.getStartTimeWindows(pid);
153
+ return this.getStartTimePosix(pid);
154
+ }
148
155
  isAlivePosix(pid) {
149
156
  const result = this.runSync([
150
157
  "ps",
@@ -195,6 +202,32 @@ var NodeFunnelProcessRunner = class extends FunnelProcessRunner {
195
202
  }
196
203
  return snapshots;
197
204
  }
205
+ getStartTimePosix(pid) {
206
+ const result = this.runSync([
207
+ "ps",
208
+ "-p",
209
+ String(pid),
210
+ "-o",
211
+ "lstart="
212
+ ]);
213
+ if (result.exitCode !== 0) return null;
214
+ const value = result.stdout.trim();
215
+ if (!value) return null;
216
+ return value;
217
+ }
218
+ getStartTimeWindows(pid) {
219
+ const script = `Get-CimInstance Win32_Process -Filter "ProcessId=${pid}" | Select-Object -ExpandProperty CreationDate | ForEach-Object { $_.ToString("o") }`;
220
+ const result = this.runSync([
221
+ "powershell",
222
+ "-NoProfile",
223
+ "-Command",
224
+ script
225
+ ]);
226
+ if (result.exitCode !== 0) return null;
227
+ const value = result.stdout.trim();
228
+ if (!value) return null;
229
+ return value;
230
+ }
198
231
  listProcessesContainingWindows(marker) {
199
232
  const result = this.runSync([
200
233
  "powershell",
@@ -1,6 +1,6 @@
1
1
  import { t as FunnelConnectorAdapter } from "./connector-adapter-qwXLjQId.js";
2
2
  import { t as FunnelConnectorListener } from "./connector-listener-CpHBecCj.js";
3
- import { n as NodeFunnelProcessRunner } from "./gh-connector-schema-DUcZgN2Q.js";
3
+ import { n as NodeFunnelProcessRunner } from "./gh-connector-schema-ClPLSYD9.js";
4
4
  import { z } from "zod";
5
5
  //#region lib/engine/connectors/gh-adapter.ts
6
6
  const defaultProcess$1 = new NodeFunnelProcessRunner();
@@ -1,11 +1,11 @@
1
1
  import { a as Settings } from "./settings-schema-1hh11jnN.js";
2
- import { n as FunnelClaude, t as FileProcessGuard } from "./file-process-guard-B3IFCj_G.js";
2
+ import { n as FunnelClaude, t as FileProcessGuard } from "./file-process-guard-JhFpmHYo.js";
3
3
  import { n as FunnelIdGenerator, t as FunnelSettingsReader } from "./settings-reader-DPwqOVUm.js";
4
4
  import { S as FunnelLogger, b as FunnelConnectorListener, c as ConnectorProcessedQuery, f as ConnectorRawQuery, g as StoredRawEvent, h as StoredProcessedEvent, i as ConnectorConnectionRecord, l as ConnectorProcessedRecord, m as StoredConnectionEvent, o as ConnectorDiagnosticLog, p as ConnectorRawRecord, r as ConnectorConnectionQuery } from "./diagnostic-log-Cb3v8P7p.js";
5
- import { a as RunOptions, i as ProcessSnapshot, n as DetachOptions, o as RunResult, r as FunnelProcessRunner, t as AttachOptions } from "./process-runner-Cx5O_fTf.js";
5
+ import { a as RunOptions, i as ProcessSnapshot, n as DetachOptions, o as RunResult, r as FunnelProcessRunner, t as AttachOptions } from "./process-runner-DIm1cy95.js";
6
6
  import { n as FunnelFileSystem, t as FileStat } from "./file-system-DxpnnUVb.js";
7
7
  import { t as FunnelProfiles } from "./profiles-g2qGVOWv.js";
8
- import { a as ChannelConnectorView, d as ConnectorConfig, i as FunnelTokenPrompter, l as ScheduleListenerOptions, m as FunnelLocalConfig, n as FunnelLocalConfigSync, o as FunnelChannels, s as FunnelClock, u as SlackListenerOptions } from "./local-config-sync--f739oCJ.js";
8
+ import { a as ChannelConnectorView, d as ConnectorConfig, i as FunnelTokenPrompter, l as ScheduleListenerOptions, m as FunnelLocalConfig, n as FunnelLocalConfigSync, o as FunnelChannels, s as FunnelClock, u as SlackListenerOptions } from "./local-config-sync-BGPAS9Be.js";
9
9
  import { c as FunnelDiagnostics } from "./funnel-diagnostics-K-wON25Y.js";
10
10
  import { n as FunnelDocs } from "./funnel-docs-DYBs1-H_.js";
11
11
  import { t as FunnelRecovery } from "./funnel-recovery-COExL9MD.js";
@@ -1085,9 +1085,12 @@ declare class NodeFunnelProcessRunner extends FunnelProcessRunner {
1085
1085
  kill(pid: number, signal?: string): void;
1086
1086
  isAlive(pid: number): boolean;
1087
1087
  listProcessesContaining(marker: string): ProcessSnapshot[];
1088
+ getStartTime(pid: number): string | null;
1088
1089
  private isAlivePosix;
1089
1090
  private isAliveWindows;
1090
1091
  private listProcessesContainingPosix;
1092
+ private getStartTimePosix;
1093
+ private getStartTimeWindows;
1091
1094
  private listProcessesContainingWindows;
1092
1095
  }
1093
1096
  //#endregion
@@ -1120,6 +1123,7 @@ type MemoryProcessCall = {
1120
1123
  };
1121
1124
  type AliveStub = (pid: number) => boolean;
1122
1125
  type ProcessListStub = (marker: string) => ProcessSnapshot[];
1126
+ type StartTimeStub = (pid: number) => string | null;
1123
1127
  declare class MemoryFunnelProcessRunner extends FunnelProcessRunner {
1124
1128
  readonly calls: MemoryProcessCall[];
1125
1129
  readonly killed: {
@@ -1130,10 +1134,12 @@ declare class MemoryFunnelProcessRunner extends FunnelProcessRunner {
1130
1134
  private syncHandler;
1131
1135
  private aliveStub;
1132
1136
  private listStub;
1137
+ private startTimeStub;
1133
1138
  on(handler: MemoryProcessHandler): this;
1134
1139
  onSync(handler: MemoryProcessSyncHandler): this;
1135
1140
  onIsAlive(stub: AliveStub): this;
1136
1141
  onListProcessesContaining(stub: ProcessListStub): this;
1142
+ onGetStartTime(stub: StartTimeStub): this;
1137
1143
  run(command: string[], options?: RunOptions): Promise<RunResult>;
1138
1144
  runSync(command: string[]): RunResult;
1139
1145
  attach(command: string[], options?: AttachOptions): Promise<number>;
@@ -1141,6 +1147,7 @@ declare class MemoryFunnelProcessRunner extends FunnelProcessRunner {
1141
1147
  kill(pid: number, signal?: string): void;
1142
1148
  isAlive(pid: number): boolean;
1143
1149
  listProcessesContaining(marker: string): ProcessSnapshot[];
1150
+ getStartTime(pid: number): string | null;
1144
1151
  }
1145
1152
  //#endregion
1146
1153
  //#region lib/engine/logger/node-logger.d.ts
@@ -3592,4 +3599,4 @@ declare function buildGatewayRoutes(): _$hono_hono_base0.HonoBase<Env$1, {
3592
3599
  };
3593
3600
  }, "/", "/channels/:channel/publish">;
3594
3601
  //#endregion
3595
- export { PublishResult as $, NodeFunnelFileSystem as A, GatewayServerOptions as B, MemoryProcessCall as C, ProcessListStub as D, MemoryProcessSyncHandler as E, FunnelSettingsStore as F, FunnelGateway as G, ListListenersResult as H, SETTINGS_PATH as I, MemoryFunnelEventLog as J, MemoryConnectorDiagnosticLog as K, resolveFunnelDir as L, createSettings as M, DEFAULT_GATEWAY_PORT as N, NodeFunnelProcessRunner as O, FUNNEL_DIR as P, PublishResponse as Q, resolveFunnelPort as R, MemoryFunnelProcessRunner as S, OnFunnelError as St, MemoryProcessResponse as T, ListenerEntry as U, FunnelListenersClient as V, ListenerOpResult as W, FunnelChannelPublisher as X, SqliteFunnelEventLog as Y, PublishRequest as Z, NoopFunnelLogger as _, FunnelListenerSupervisor as _t, toRequest as a, ChannelWsUrlInput as at, NodeFunnelLogger as b, FunnelBroadcaster as bt, buildServiceRoutes as c, FunnelGatewayServer as ct, MemoryHttpResponse as d, FunnelEventLog as dt, publishRequestSchema as et, NodeFunnelHttpClient as f, FunnelEventRecord as ft, NodeFunnelClock as g, GatewayRouteDeps as gt, MemoryFunnelClock as h, GatewayEmitInput as ht, queryToCliArgs as i, gatewayLoopbackUrl as it, MockFunnelSettingsReader as j, MemoryFunnelFileSystem as k, MemoryFunnelHttpClient as l, GatewayEventStore as lt, NodeFunnelIdGenerator as m, Env$1 as mt, CliApp as n, DEFAULT_GATEWAY_TOKEN_PATH as nt, Env as o, channelWsProtocols as ot, MemoryFunnelIdGenerator as p, funnelEventSchema as pt, SqliteConnectorDiagnosticLog as q, routes as r, FunnelGatewayToken as rt, factory as s, channelWsUrl as st, GatewayApp as t, publishResponseSchema as tt, MemoryHttpHandler as u, FunnelEvent as ut, LogEntry as v, BroadcastEvent as vt, MemoryProcessHandler as w, AliveStub as x, ReplayableEvent as xt, MemoryFunnelLogger as y, BroadcastSubscriber as yt, Funnel as z };
3602
+ export { PublishResponse as $, MemoryFunnelFileSystem as A, Funnel as B, MemoryProcessCall as C, OnFunnelError as Ct, ProcessListStub as D, MemoryProcessSyncHandler as E, FUNNEL_DIR as F, ListenerOpResult as G, FunnelListenersClient as H, FunnelSettingsStore as I, SqliteConnectorDiagnosticLog as J, FunnelGateway as K, SETTINGS_PATH as L, MockFunnelSettingsReader as M, createSettings as N, StartTimeStub as O, DEFAULT_GATEWAY_PORT as P, PublishRequest as Q, resolveFunnelDir as R, MemoryFunnelProcessRunner as S, ReplayableEvent as St, MemoryProcessResponse as T, ListListenersResult as U, GatewayServerOptions as V, ListenerEntry as W, SqliteFunnelEventLog as X, MemoryFunnelEventLog as Y, FunnelChannelPublisher as Z, NoopFunnelLogger as _, GatewayRouteDeps as _t, toRequest as a, gatewayLoopbackUrl as at, NodeFunnelLogger as b, BroadcastSubscriber as bt, buildServiceRoutes as c, channelWsUrl as ct, MemoryHttpResponse as d, FunnelEvent as dt, PublishResult as et, NodeFunnelHttpClient as f, FunnelEventLog as ft, NodeFunnelClock as g, GatewayEmitInput as gt, MemoryFunnelClock as h, Env$1 as ht, queryToCliArgs as i, FunnelGatewayToken as it, NodeFunnelFileSystem as j, NodeFunnelProcessRunner as k, MemoryFunnelHttpClient as l, FunnelGatewayServer as lt, NodeFunnelIdGenerator as m, funnelEventSchema as mt, CliApp as n, publishResponseSchema as nt, Env as o, ChannelWsUrlInput as ot, MemoryFunnelIdGenerator as p, FunnelEventRecord as pt, MemoryConnectorDiagnosticLog as q, routes as r, DEFAULT_GATEWAY_TOKEN_PATH as rt, factory as s, channelWsProtocols as st, GatewayApp as t, publishRequestSchema as tt, MemoryHttpHandler as u, GatewayEventStore as ut, LogEntry as v, FunnelListenerSupervisor as vt, MemoryProcessHandler as w, AliveStub as x, FunnelBroadcaster as xt, MemoryFunnelLogger as y, BroadcastEvent as yt, resolveFunnelPort as z };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { a as Settings, c as profileConfigSchema, i as SETTINGS_VERSION, l as settingsSchema, n as ChannelDeliveryMode, o as channelConfigSchema, r as ProfileConfig, s as channelDeliveryModeSchema, t as ChannelConfig } from "./settings-schema-1hh11jnN.js";
2
2
  import { n as FunnelIdGenerator, t as FunnelSettingsReader } from "./settings-reader-DPwqOVUm.js";
3
3
  import { S as FunnelLogger, _ as connectorConnectionEventSchema, a as ConnectorConnectionStatus, b as FunnelConnectorListener, 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, x as NotifyFn, y as connectorRawEventSchema } from "./diagnostic-log-Cb3v8P7p.js";
4
- import { a as RunOptions, i as ProcessSnapshot, n as DetachOptions, o as RunResult, r as FunnelProcessRunner, t as AttachOptions } from "./process-runner-Cx5O_fTf.js";
4
+ import { a as RunOptions, i as ProcessSnapshot, n as DetachOptions, o as RunResult, r as FunnelProcessRunner, t as AttachOptions } from "./process-runner-DIm1cy95.js";
5
5
  import { n as FunnelFileSystem, t as FileStat } from "./file-system-DxpnnUVb.js";
6
- import { a as ChannelConnectorView, c as FunnelConnectorFactory, d as ConnectorConfig, f as ConnectorType, l as ScheduleListenerOptions, o as FunnelChannels, p as connectorConfigSchema, s as FunnelClock, u as SlackListenerOptions } from "./local-config-sync--f739oCJ.js";
6
+ import { a as ChannelConnectorView, c as FunnelConnectorFactory, d as ConnectorConfig, f as ConnectorType, l as ScheduleListenerOptions, o as FunnelChannels, p as connectorConfigSchema, s as FunnelClock, u as SlackListenerOptions } from "./local-config-sync-BGPAS9Be.js";
7
7
  import { n as FunnelConnectorAdapter, r as JsonValue, t as CallInput } from "./connector-adapter-DGacCppE.js";
8
8
  import { a as ScheduleEntry, c as scheduleEntrySchema, i as ScheduleConnectorConfig, o as scheduleCatchupPolicySchema, r as ScheduleCatchupPolicy, s as scheduleConnectorSchema } from "./schedule-listener-DoMPjHZj.js";
9
9
  import { a as slackConnectorSchema, c as SlackProcessedEmit, d as SlackSkipReason, i as SlackConnectorConfig, l as SlackProcessedSkip, o as FunnelSlackEventProcessor, s as SlackProcessed, u as SlackRawEvent } from "./slack-listener-Dj9NFbAJ.js";
@@ -13,5 +13,5 @@ import { a as RecoveryListenerControl, i as RecoveryGatewayControl, n as Recover
13
13
  import { n as DoctorReport, r as FunnelDoctor, t as DoctorFixMode } from "./funnel-doctor-vxO96TCA.js";
14
14
  import { a as HttpResponse, i as HttpRequest, n as discordConnectorSchema, r as FunnelHttpClient, t as DiscordConnectorConfig } from "./discord-connector-schema-CQyfDkLD.js";
15
15
  import { n as ghConnectorSchema, t as GhConnectorConfig } from "./gh-connector-schema-CZzwzvqY.js";
16
- import { $ as PublishResult, A as NodeFunnelFileSystem, B as GatewayServerOptions, C as MemoryProcessCall, D as ProcessListStub, E as MemoryProcessSyncHandler, F as FunnelSettingsStore, G as FunnelGateway, H as ListListenersResult, I as SETTINGS_PATH, J as MemoryFunnelEventLog, K as MemoryConnectorDiagnosticLog, L as resolveFunnelDir, M as createSettings, N as DEFAULT_GATEWAY_PORT, O as NodeFunnelProcessRunner, P as FUNNEL_DIR, Q as PublishResponse, R as resolveFunnelPort, S as MemoryFunnelProcessRunner, St as OnFunnelError, T as MemoryProcessResponse, U as ListenerEntry, V as FunnelListenersClient, W as ListenerOpResult, X as FunnelChannelPublisher, Y as SqliteFunnelEventLog, Z as PublishRequest, _ as NoopFunnelLogger, _t as FunnelListenerSupervisor, a as toRequest, at as ChannelWsUrlInput, b as NodeFunnelLogger, bt as FunnelBroadcaster, c as buildServiceRoutes, ct as FunnelGatewayServer, d as MemoryHttpResponse, dt as FunnelEventLog, et as publishRequestSchema, f as NodeFunnelHttpClient, ft as FunnelEventRecord, g as NodeFunnelClock, gt as GatewayRouteDeps, h as MemoryFunnelClock, ht as GatewayEmitInput, i as queryToCliArgs, it as gatewayLoopbackUrl, j as MockFunnelSettingsReader, k as MemoryFunnelFileSystem, l as MemoryFunnelHttpClient, lt as GatewayEventStore, m as NodeFunnelIdGenerator, mt as Env$1, n as CliApp, nt as DEFAULT_GATEWAY_TOKEN_PATH, o as Env, ot as channelWsProtocols, p as MemoryFunnelIdGenerator, pt as funnelEventSchema, q as SqliteConnectorDiagnosticLog, r as routes, rt as FunnelGatewayToken, s as factory, st as channelWsUrl, t as GatewayApp, tt as publishResponseSchema, u as MemoryHttpHandler, ut as FunnelEvent, v as LogEntry, vt as BroadcastEvent, w as MemoryProcessHandler, x as AliveStub, xt as ReplayableEvent, y as MemoryFunnelLogger, yt as BroadcastSubscriber, z as Funnel } from "./index-Conbxl5O.js";
17
- export { AliveStub, AttachOptions, BroadcastEvent, BroadcastSubscriber, CONNECTOR_CONNECTION_STATUSES, CallInput, ChannelConfig, ChannelConnectorView, ChannelDeliveryMode, ChannelDiagnosis, ChannelWsUrlInput, CliApp, ConnectorConfig, ConnectorConnectionEvent, ConnectorConnectionQuery, ConnectorConnectionRecord, ConnectorConnectionStatus, ConnectorDiagnosticLog, ConnectorDiagnosticSqlReader, ConnectorProcessedEvent, ConnectorProcessedQuery, ConnectorProcessedRecord, ConnectorQuery, ConnectorRawEvent, ConnectorRawQuery, ConnectorRawRecord, ConnectorType, DEFAULT_GATEWAY_PORT, DEFAULT_GATEWAY_TOKEN_PATH, DetachOptions, DiagnoseAllReport, DiagnosisStatus, DiagnosticConnectionError, DiagnosticEvent, DiagnosticsChannelSource, DiagnosticsGatewayProbe, DiagnosticsPublisher, DiagnosticsTokenReader, DiscordConnectorConfig, DocsTopicListing, DoctorFixMode, DoctorReport, Env, FUNNEL_DIR, FileStat, Funnel, FunnelBroadcaster, FunnelChannelPublisher, FunnelChannels, FunnelClock, FunnelConnectorAdapter, FunnelConnectorFactory, FunnelConnectorListener, FunnelDiagnostics, FunnelDocs, FunnelDoctor, FunnelEvent, FunnelEventLog, FunnelEventRecord, FunnelFileSystem, FunnelGateway, FunnelGatewayServer, FunnelGatewayToken, FunnelHttpClient, FunnelIdGenerator, FunnelListenerSupervisor, FunnelListenersClient, FunnelLogger, FunnelProcessRunner, FunnelRecovery, FunnelSettingsReader, FunnelSettingsStore, FunnelSlackEventProcessor, GatewayApp, GatewayEmitInput, GatewayEventStore, GatewayRouteDeps, Env$1 as GatewayServerEnv, GatewayServerOptions, GhConnectorConfig, HttpRequest, HttpResponse, JsonValue, ListListenersResult, ListenerEntry, ListenerOpResult, LogEntry, MemoryConnectorDiagnosticLog, MemoryFunnelClock, MemoryFunnelEventLog, MemoryFunnelFileSystem, MemoryFunnelHttpClient, MemoryFunnelIdGenerator, MemoryFunnelLogger, MemoryFunnelProcessRunner, MemoryHttpHandler, MemoryHttpResponse, MemoryProcessCall, MemoryProcessHandler, MemoryProcessResponse, MemoryProcessSyncHandler, MockFunnelSettingsReader, NodeFunnelClock, NodeFunnelFileSystem, NodeFunnelHttpClient, NodeFunnelIdGenerator, NodeFunnelLogger, NodeFunnelProcessRunner, NoopFunnelLogger, NotifyFn, OnFunnelError, ProcessListStub, ProcessSnapshot, ProfileConfig, PublishRequest, PublishResponse, PublishResult, RecoveryAction, RecoveryChannelSource, RecoveryGatewayControl, RecoveryListenerControl, RecoveryResult, ReplayResult, ReplayableEvent, RunOptions, RunResult, SETTINGS_PATH, SETTINGS_VERSION, ScheduleCatchupPolicy, ScheduleConnectorConfig, ScheduleEntry, ScheduleListenerOptions, Settings, SlackConnectorConfig, SlackListenerOptions, SlackProcessed, SlackProcessedEmit, SlackProcessedSkip, SlackRawEvent, SlackSkipReason, SqliteConnectorDiagnosticLog, SqliteFunnelEventLog, StoredConnectionEvent, StoredProcessedEvent, StoredRawEvent, buildServiceRoutes, channelConfigSchema, channelDeliveryModeSchema, channelWsProtocols, channelWsUrl, routes as cliRoutes, connectorConfigSchema, connectorConnectionEventSchema, connectorProcessedEventSchema, connectorRawEventSchema, createSettings, discordConnectorSchema, factory, funnelEventSchema, gatewayLoopbackUrl, ghConnectorSchema, previewOf, profileConfigSchema, publishRequestSchema, publishResponseSchema, queryRows, queryToCliArgs, resolveFunnelDir, resolveFunnelPort, scheduleCatchupPolicySchema, scheduleConnectorSchema, scheduleEntrySchema, settingsSchema, slackConnectorSchema, toDiagnosticConnectionError, toDiagnosticEvent, toRequest };
16
+ import { $ as PublishResponse, A as MemoryFunnelFileSystem, B as Funnel, C as MemoryProcessCall, Ct as OnFunnelError, D as ProcessListStub, E as MemoryProcessSyncHandler, F as FUNNEL_DIR, G as ListenerOpResult, H as FunnelListenersClient, I as FunnelSettingsStore, J as SqliteConnectorDiagnosticLog, K as FunnelGateway, L as SETTINGS_PATH, M as MockFunnelSettingsReader, N as createSettings, O as StartTimeStub, P as DEFAULT_GATEWAY_PORT, Q as PublishRequest, R as resolveFunnelDir, S as MemoryFunnelProcessRunner, St as ReplayableEvent, T as MemoryProcessResponse, U as ListListenersResult, V as GatewayServerOptions, W as ListenerEntry, X as SqliteFunnelEventLog, Y as MemoryFunnelEventLog, Z as FunnelChannelPublisher, _ as NoopFunnelLogger, _t as GatewayRouteDeps, a as toRequest, at as gatewayLoopbackUrl, b as NodeFunnelLogger, bt as BroadcastSubscriber, c as buildServiceRoutes, ct as channelWsUrl, d as MemoryHttpResponse, dt as FunnelEvent, et as PublishResult, f as NodeFunnelHttpClient, ft as FunnelEventLog, g as NodeFunnelClock, gt as GatewayEmitInput, h as MemoryFunnelClock, ht as Env$1, i as queryToCliArgs, it as FunnelGatewayToken, j as NodeFunnelFileSystem, k as NodeFunnelProcessRunner, l as MemoryFunnelHttpClient, lt as FunnelGatewayServer, m as NodeFunnelIdGenerator, mt as funnelEventSchema, n as CliApp, nt as publishResponseSchema, o as Env, ot as ChannelWsUrlInput, p as MemoryFunnelIdGenerator, pt as FunnelEventRecord, q as MemoryConnectorDiagnosticLog, r as routes, rt as DEFAULT_GATEWAY_TOKEN_PATH, s as factory, st as channelWsProtocols, t as GatewayApp, tt as publishRequestSchema, u as MemoryHttpHandler, ut as GatewayEventStore, v as LogEntry, vt as FunnelListenerSupervisor, w as MemoryProcessHandler, x as AliveStub, xt as FunnelBroadcaster, y as MemoryFunnelLogger, yt as BroadcastEvent, z as resolveFunnelPort } from "./index-D7mjirUL.js";
17
+ export { AliveStub, AttachOptions, BroadcastEvent, BroadcastSubscriber, CONNECTOR_CONNECTION_STATUSES, CallInput, ChannelConfig, ChannelConnectorView, ChannelDeliveryMode, ChannelDiagnosis, ChannelWsUrlInput, CliApp, ConnectorConfig, ConnectorConnectionEvent, ConnectorConnectionQuery, ConnectorConnectionRecord, ConnectorConnectionStatus, ConnectorDiagnosticLog, ConnectorDiagnosticSqlReader, ConnectorProcessedEvent, ConnectorProcessedQuery, ConnectorProcessedRecord, ConnectorQuery, ConnectorRawEvent, ConnectorRawQuery, ConnectorRawRecord, ConnectorType, DEFAULT_GATEWAY_PORT, DEFAULT_GATEWAY_TOKEN_PATH, DetachOptions, DiagnoseAllReport, DiagnosisStatus, DiagnosticConnectionError, DiagnosticEvent, DiagnosticsChannelSource, DiagnosticsGatewayProbe, DiagnosticsPublisher, DiagnosticsTokenReader, DiscordConnectorConfig, DocsTopicListing, DoctorFixMode, DoctorReport, Env, FUNNEL_DIR, FileStat, Funnel, FunnelBroadcaster, FunnelChannelPublisher, FunnelChannels, FunnelClock, FunnelConnectorAdapter, FunnelConnectorFactory, FunnelConnectorListener, FunnelDiagnostics, FunnelDocs, FunnelDoctor, FunnelEvent, FunnelEventLog, FunnelEventRecord, FunnelFileSystem, FunnelGateway, FunnelGatewayServer, FunnelGatewayToken, FunnelHttpClient, FunnelIdGenerator, FunnelListenerSupervisor, FunnelListenersClient, FunnelLogger, FunnelProcessRunner, FunnelRecovery, FunnelSettingsReader, FunnelSettingsStore, FunnelSlackEventProcessor, GatewayApp, GatewayEmitInput, GatewayEventStore, GatewayRouteDeps, Env$1 as GatewayServerEnv, GatewayServerOptions, GhConnectorConfig, HttpRequest, HttpResponse, JsonValue, ListListenersResult, ListenerEntry, ListenerOpResult, LogEntry, MemoryConnectorDiagnosticLog, MemoryFunnelClock, MemoryFunnelEventLog, MemoryFunnelFileSystem, MemoryFunnelHttpClient, MemoryFunnelIdGenerator, MemoryFunnelLogger, MemoryFunnelProcessRunner, MemoryHttpHandler, MemoryHttpResponse, MemoryProcessCall, MemoryProcessHandler, MemoryProcessResponse, MemoryProcessSyncHandler, MockFunnelSettingsReader, NodeFunnelClock, NodeFunnelFileSystem, NodeFunnelHttpClient, NodeFunnelIdGenerator, NodeFunnelLogger, NodeFunnelProcessRunner, NoopFunnelLogger, NotifyFn, OnFunnelError, ProcessListStub, ProcessSnapshot, ProfileConfig, PublishRequest, PublishResponse, PublishResult, RecoveryAction, RecoveryChannelSource, RecoveryGatewayControl, RecoveryListenerControl, RecoveryResult, ReplayResult, ReplayableEvent, RunOptions, RunResult, SETTINGS_PATH, SETTINGS_VERSION, ScheduleCatchupPolicy, ScheduleConnectorConfig, ScheduleEntry, ScheduleListenerOptions, Settings, SlackConnectorConfig, SlackListenerOptions, SlackProcessed, SlackProcessedEmit, SlackProcessedSkip, SlackRawEvent, SlackSkipReason, SqliteConnectorDiagnosticLog, SqliteFunnelEventLog, StartTimeStub, StoredConnectionEvent, StoredProcessedEvent, StoredRawEvent, buildServiceRoutes, channelConfigSchema, channelDeliveryModeSchema, channelWsProtocols, channelWsUrl, routes as cliRoutes, connectorConfigSchema, connectorConnectionEventSchema, connectorProcessedEventSchema, connectorRawEventSchema, createSettings, discordConnectorSchema, factory, funnelEventSchema, gatewayLoopbackUrl, ghConnectorSchema, previewOf, profileConfigSchema, publishRequestSchema, publishResponseSchema, queryRows, queryToCliArgs, resolveFunnelDir, resolveFunnelPort, scheduleCatchupPolicySchema, scheduleConnectorSchema, scheduleEntrySchema, settingsSchema, slackConnectorSchema, toDiagnosticConnectionError, toDiagnosticEvent, toRequest };
package/dist/index.js CHANGED
@@ -2,18 +2,18 @@ import { t as FunnelConnectorAdapter } from "./connector-adapter-qwXLjQId.js";
2
2
  import { a as FunnelHttpClient, i as NodeFunnelHttpClient, r as FunnelDiscordAdapter, t as FunnelDiscordListener } from "./discord-listener-CKsZGTnH.js";
3
3
  import { t as FunnelConnectorListener } from "./connector-listener-CpHBecCj.js";
4
4
  import { t as FunnelLogger } from "./logger-BP6SisKt.js";
5
- import { n as NodeFunnelProcessRunner, r as FunnelProcessRunner, t as ghConnectorSchema } from "./gh-connector-schema-DUcZgN2Q.js";
6
- import { n as FunnelGhAdapter, t as FunnelGhListener } from "./gh-listener-Dsx6AmhH.js";
5
+ import { n as NodeFunnelProcessRunner, r as FunnelProcessRunner, t as ghConnectorSchema } from "./gh-connector-schema-ClPLSYD9.js";
6
+ import { n as FunnelGhAdapter, t as FunnelGhListener } from "./gh-listener-B2I4s8qh.js";
7
7
  import { n as ScheduleStateStore, t as FunnelScheduleListener } from "./schedule-listener-DP9Jhc6U.js";
8
8
  import { t as FunnelFileSystem } from "./file-system-PWKKU7lA.js";
9
9
  import { t as NodeFunnelFileSystem } from "./node-file-system-BcrmWN9I.js";
10
10
  import { n as FunnelSlackEventProcessor, r as FunnelSlackAdapter, t as FunnelSlackListener } from "./slack-listener-C4wlZaOq.js";
11
11
  import { n as FunnelIdGenerator, t as FunnelSettingsReader } from "./settings-reader-DPqrpV7s.js";
12
- import { a as SETTINGS_PATH, c as SETTINGS_VERSION, d as profileConfigSchema, f as settingsSchema, i as FunnelSettingsStore, l as channelConfigSchema, m as NodeFunnelIdGenerator, n as DEFAULT_GATEWAY_PORT, o as resolveFunnelDir, p as connectorConfigSchema, r as FUNNEL_DIR, s as resolveFunnelPort, t as gatewayLoopbackUrl, u as channelDeliveryModeSchema } from "./gateway-base-url-6foMXfFf.js";
12
+ import { a as SETTINGS_PATH, c as SETTINGS_VERSION, d as profileConfigSchema, f as settingsSchema, i as FunnelSettingsStore, l as channelConfigSchema, m as NodeFunnelIdGenerator, n as DEFAULT_GATEWAY_PORT, o as resolveFunnelDir, p as connectorConfigSchema, r as FUNNEL_DIR, s as resolveFunnelPort, t as gatewayLoopbackUrl, u as channelDeliveryModeSchema } from "./gateway-base-url-DxVjjDoW.js";
13
13
  import { t as discordConnectorSchema } from "./discord-connector-schema-B_N6IXLz.js";
14
14
  import { n as scheduleConnectorSchema, r as scheduleEntrySchema, t as scheduleCatchupPolicySchema } from "./schedule-connector-schema-B_xO5z5B.js";
15
15
  import { t as slackConnectorSchema } from "./slack-connector-schema-C1zEf4TG.js";
16
- import { a as FunnelMcp, o as FileProcessGuard, s as FunnelClaude, t as renderYaml } from "./yaml-render-C9Hhjk-0.js";
16
+ import { a as FunnelMcp, o as FileProcessGuard, s as FunnelClaude, t as renderYaml } from "./yaml-render-cZu6CxkE.js";
17
17
  import { a as toDiagnosticEvent, i as toDiagnosticConnectionError, n as previewOf, r as queryRows, t as FunnelDiagnostics } from "./funnel-diagnostics-BpKYrMSu.js";
18
18
  import { t as ConnectorDiagnosticSqlReader } from "./diagnostic-sql-reader-CzYgZpq2.js";
19
19
  import { t as FunnelDoctor } from "./funnel-doctor-CApCezTq.js";
@@ -21,7 +21,7 @@ import { t as FunnelDocs } from "./funnel-docs-ng5K8w4j.js";
21
21
  import { a as FunnelLocalConfig, n as NodeFunnelTokenPrompter, r as FunnelLocalConfigSync, t as funnelJsonSchema } from "./local-config-json-schema-DE1zkMcb.js";
22
22
  import { t as FunnelProfiles } from "./profiles-MnXvYfZF.js";
23
23
  import { t as FunnelRecovery } from "./funnel-recovery-D9CxD5Zs.js";
24
- import { C as funnelTmpDir, S as publishResponseSchema, _ as funnelEventSchema, a as connectorConnectionEventSchema, b as FunnelChannelPublisher, c as MemoryFunnelEventLog, d as DEFAULT_GATEWAY_TOKEN_PATH, f as FunnelGatewayToken, g as FunnelEventLog, h as SqliteFunnelEventLog, i as ConnectorDiagnosticLog, l as channelWsProtocols, m as FunnelListenerSupervisor, n as SqliteConnectorDiagnosticLog, o as connectorProcessedEventSchema, p as FunnelGatewayServer, r as CONNECTOR_CONNECTION_STATUSES, s as connectorRawEventSchema, t as MemoryConnectorDiagnosticLog, u as channelWsUrl, v as FunnelBroadcaster, x as publishRequestSchema, y as requireBearerToken } from "./memory-diagnostic-log-5LzwJ_F7.js";
24
+ import { C as funnelTmpDir, S as publishResponseSchema, _ as funnelEventSchema, a as connectorConnectionEventSchema, b as FunnelChannelPublisher, c as MemoryFunnelEventLog, d as DEFAULT_GATEWAY_TOKEN_PATH, f as FunnelGatewayToken, g as FunnelEventLog, h as SqliteFunnelEventLog, i as ConnectorDiagnosticLog, l as channelWsProtocols, m as FunnelListenerSupervisor, n as SqliteConnectorDiagnosticLog, o as connectorProcessedEventSchema, p as FunnelGatewayServer, r as CONNECTOR_CONNECTION_STATUSES, s as connectorRawEventSchema, t as MemoryConnectorDiagnosticLog, u as channelWsUrl, v as FunnelBroadcaster, x as publishRequestSchema, y as requireBearerToken } from "./memory-diagnostic-log-B9Us7X05.js";
25
25
  import { dirname, join, resolve } from "node:path";
26
26
  import { hc } from "hono/client";
27
27
  import { appendFileSync, existsSync, mkdirSync } from "node:fs";
@@ -596,6 +596,7 @@ var MemoryFunnelProcessRunner = class extends FunnelProcessRunner {
596
596
  syncHandler = () => empty;
597
597
  aliveStub = null;
598
598
  listStub = null;
599
+ startTimeStub = null;
599
600
  on(handler) {
600
601
  this.handler = handler;
601
602
  return this;
@@ -612,6 +613,10 @@ var MemoryFunnelProcessRunner = class extends FunnelProcessRunner {
612
613
  this.listStub = stub;
613
614
  return this;
614
615
  }
616
+ onGetStartTime(stub) {
617
+ this.startTimeStub = stub;
618
+ return this;
619
+ }
615
620
  async run(command, options = {}) {
616
621
  this.calls.push({
617
622
  kind: "run",
@@ -681,6 +686,10 @@ var MemoryFunnelProcessRunner = class extends FunnelProcessRunner {
681
686
  if (this.listStub) return this.listStub(marker);
682
687
  return [];
683
688
  }
689
+ getStartTime(pid) {
690
+ if (this.startTimeStub) return this.startTimeStub(pid);
691
+ return null;
692
+ }
684
693
  };
685
694
  //#endregion
686
695
  //#region lib/engine/settings/mock-settings-reader.ts
@@ -1,7 +1,7 @@
1
1
  import { n as ChannelDeliveryMode, t as ChannelConfig } from "./settings-schema-1hh11jnN.js";
2
2
  import { n as FunnelIdGenerator, t as FunnelSettingsReader } from "./settings-reader-DPwqOVUm.js";
3
3
  import { S as FunnelLogger, b as FunnelConnectorListener, o as ConnectorDiagnosticLog } from "./diagnostic-log-Cb3v8P7p.js";
4
- import { r as FunnelProcessRunner } from "./process-runner-Cx5O_fTf.js";
4
+ import { r as FunnelProcessRunner } from "./process-runner-DIm1cy95.js";
5
5
  import { n as FunnelFileSystem } from "./file-system-DxpnnUVb.js";
6
6
  import { n as FunnelConnectorAdapter, t as CallInput } from "./connector-adapter-DGacCppE.js";
7
7
  import { a as ScheduleEntry, n as ScheduleOnFired } from "./schedule-listener-DoMPjHZj.js";
@@ -1,3 +1,3 @@
1
- import { C as profileSpecSchema, S as localConfigSchema, _ as LOCAL_CONFIG_FILENAME, b as channelSpecSchema, g as ConnectorSpec, h as ChannelSpec, i as FunnelTokenPrompter, m as FunnelLocalConfig, n as FunnelLocalConfigSync, r as LocalConfigSyncResult, t as ConnectorSyncOutcome, v as LocalConfig, x as connectorSpecSchema, y as ProfileSpec } from "./local-config-sync--f739oCJ.js";
2
- import { i as funnelJsonSchema, n as NodeFunnelTokenPrompter, r as FunnelLocalConfigWriter, t as MemoryFunnelTokenPrompter } from "./memory-token-prompter-BlFwK9k7.js";
1
+ import { C as profileSpecSchema, S as localConfigSchema, _ as LOCAL_CONFIG_FILENAME, b as channelSpecSchema, g as ConnectorSpec, h as ChannelSpec, i as FunnelTokenPrompter, m as FunnelLocalConfig, n as FunnelLocalConfigSync, r as LocalConfigSyncResult, t as ConnectorSyncOutcome, v as LocalConfig, x as connectorSpecSchema, y as ProfileSpec } from "./local-config-sync-BGPAS9Be.js";
2
+ import { i as funnelJsonSchema, n as NodeFunnelTokenPrompter, r as FunnelLocalConfigWriter, t as MemoryFunnelTokenPrompter } from "./memory-token-prompter-CcShtF8B.js";
3
3
  export { ChannelSpec, ConnectorSpec, ConnectorSyncOutcome, FunnelLocalConfig, FunnelLocalConfigSync, FunnelLocalConfigWriter, FunnelTokenPrompter, LOCAL_CONFIG_FILENAME, LocalConfig, LocalConfigSyncResult, MemoryFunnelTokenPrompter, NodeFunnelTokenPrompter, ProfileSpec, channelSpecSchema, connectorSpecSchema, funnelJsonSchema, localConfigSchema, profileSpecSchema };
@@ -1,6 +1,6 @@
1
- import { n as NodeFunnelProcessRunner } from "./gh-connector-schema-DUcZgN2Q.js";
1
+ import { n as NodeFunnelProcessRunner } from "./gh-connector-schema-ClPLSYD9.js";
2
2
  import { t as NodeFunnelFileSystem } from "./node-file-system-BcrmWN9I.js";
3
- import { r as FUNNEL_DIR, s as resolveFunnelPort, t as gatewayLoopbackUrl } from "./gateway-base-url-6foMXfFf.js";
3
+ import { r as FUNNEL_DIR, s as resolveFunnelPort, t as gatewayLoopbackUrl } from "./gateway-base-url-DxVjjDoW.js";
4
4
  import { t as ConnectorDiagnosticSqlReader } from "./diagnostic-sql-reader-CzYgZpq2.js";
5
5
  import { t as FunnelLogSqliteSink } from "./funnel-log-sqlite-sink-B_5_4ybn.js";
6
6
  import { dirname, join } from "node:path";
@@ -1,5 +1,5 @@
1
1
  import { n as FunnelFileSystem } from "./file-system-DxpnnUVb.js";
2
- import { i as FunnelTokenPrompter } from "./local-config-sync--f739oCJ.js";
2
+ import { i as FunnelTokenPrompter } from "./local-config-sync-BGPAS9Be.js";
3
3
 
4
4
  //#region lib/services/local-config/local-config-json-schema.d.ts
5
5
  /**
@@ -34,7 +34,9 @@ type ProcessSnapshot = {
34
34
  * callers do not branch on `process.platform`. `isAlive` checks whether a PID
35
35
  * names a live (non-zombie) process; `listProcessesContaining` enumerates
36
36
  * processes whose command line includes `marker`, used for funnel-gateway tag
37
- * matching across daemons that share a home dir.
37
+ * matching across daemons that share a home dir. `getStartTime` returns a
38
+ * stable string identifying when a PID was started, used to detect PID reuse
39
+ * after the original process died abnormally (no exit hook fired).
38
40
  */
39
41
  declare abstract class FunnelProcessRunner {
40
42
  abstract run(command: string[], options?: RunOptions): Promise<RunResult>;
@@ -44,6 +46,7 @@ declare abstract class FunnelProcessRunner {
44
46
  abstract kill(pid: number, signal?: string): void;
45
47
  abstract isAlive(pid: number): boolean;
46
48
  abstract listProcessesContaining(marker: string): ProcessSnapshot[];
49
+ abstract getStartTime(pid: number): string | null;
47
50
  }
48
51
  //#endregion
49
52
  export { RunOptions as a, ProcessSnapshot as i, DetachOptions as n, RunResult as o, FunnelProcessRunner as r, AttachOptions as t };
@@ -1,6 +1,6 @@
1
- import { n as NodeFunnelProcessRunner } from "./gh-connector-schema-DUcZgN2Q.js";
1
+ import { n as NodeFunnelProcessRunner } from "./gh-connector-schema-ClPLSYD9.js";
2
2
  import { t as NodeFunnelFileSystem } from "./node-file-system-BcrmWN9I.js";
3
- import { m as NodeFunnelIdGenerator, r as FUNNEL_DIR, s as resolveFunnelPort } from "./gateway-base-url-6foMXfFf.js";
3
+ import { m as NodeFunnelIdGenerator, r as FUNNEL_DIR, s as resolveFunnelPort } from "./gateway-base-url-DxVjjDoW.js";
4
4
  import { join } from "node:path";
5
5
  import { stringify } from "yaml";
6
6
  //#region lib/engine/claude/claude.ts
@@ -133,13 +133,33 @@ var FileProcessGuard = class {
133
133
  Object.freeze(this);
134
134
  }
135
135
  isRunning(profileId) {
136
- const pid = this.readPid(profileId);
137
- if (!pid) return false;
138
- return this.process.isAlive(pid);
136
+ const record = this.readRecord(profileId);
137
+ if (!record) return false;
138
+ if (!this.process.isAlive(record.pid)) {
139
+ this.release(profileId);
140
+ return false;
141
+ }
142
+ if (record.startTime !== null) {
143
+ const currentStartTime = this.process.getStartTime(record.pid);
144
+ if (currentStartTime === null) {
145
+ this.release(profileId);
146
+ return false;
147
+ }
148
+ if (currentStartTime !== record.startTime) {
149
+ this.release(profileId);
150
+ return false;
151
+ }
152
+ }
153
+ return true;
139
154
  }
140
155
  acquire(profileId) {
141
156
  this.fs.mkdirSync(this.pidDir, { recursive: true });
142
- this.fs.writeFileSync(this.pidPath(profileId), String(globalThis.process.pid));
157
+ const pid = globalThis.process.pid;
158
+ const record = {
159
+ pid,
160
+ startTime: this.process.getStartTime(pid)
161
+ };
162
+ this.fs.writeFileSync(this.pidPath(profileId), JSON.stringify(record));
143
163
  globalThis.process.once("exit", () => this.release(profileId));
144
164
  }
145
165
  release(profileId) {
@@ -149,14 +169,27 @@ var FileProcessGuard = class {
149
169
  pidPath(profileId) {
150
170
  return join(this.pidDir, `${profileId}.pid`);
151
171
  }
152
- readPid(profileId) {
172
+ readRecord(profileId) {
153
173
  const path = this.pidPath(profileId);
154
174
  if (!this.fs.existsSync(path)) return null;
155
175
  try {
156
176
  const content = this.fs.readFileSync(path).trim();
177
+ if (!content) return null;
178
+ if (content.startsWith("{")) {
179
+ const parsed = JSON.parse(content);
180
+ const pid = typeof parsed.pid === "number" ? parsed.pid : Number(parsed.pid);
181
+ if (!Number.isInteger(pid) || pid <= 0) return null;
182
+ return {
183
+ pid,
184
+ startTime: typeof parsed.startTime === "string" ? parsed.startTime : null
185
+ };
186
+ }
157
187
  const pid = Number(content);
158
188
  if (!pid || pid <= 0) return null;
159
- return pid;
189
+ return {
190
+ pid,
191
+ startTime: null
192
+ };
160
193
  } catch {
161
194
  return null;
162
195
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@interactive-inc/claude-funnel",
3
- "version": "0.59.0",
3
+ "version": "0.59.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",