@interactive-inc/claude-funnel 0.22.0 → 0.22.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/index.d.ts CHANGED
@@ -405,10 +405,15 @@ type Deps$13 = {
405
405
  /**
406
406
  * Per-channel persistent Claude Code session IDs, keyed by the cwd the
407
407
  * channel was launched from. The whole point is to give each (channel, cwd)
408
- * its own stable conversation: relaunching from the same path picks up the
409
- * previous claude session via `--session-id <uuid>`, while a different cwd
410
- * (or a different channel) gets an independent one — so sessions never
411
- * silently bleed across workspaces the way claude's `-c` does.
408
+ * its own stable conversation: relaunching from the same path resumes the
409
+ * previous claude session via `--resume <uuid>`, while a different cwd (or
410
+ * a different channel) gets an independent one — so sessions never silently
411
+ * bleed across workspaces the way claude's `-c` does.
412
+ *
413
+ * `get` and `create` are intentionally separate: claude's `--session-id`
414
+ * only accepts a fresh UUID (it errors if the session jsonl already
415
+ * exists), so callers must check `get` first and fall back to `create`
416
+ * only when there is nothing to resume.
412
417
  *
413
418
  * Storage lives under `<dir>/channels/<channel-id>/sessions.json` (channel
414
419
  * id, not name, so renames don't lose history). The file is a flat
@@ -419,10 +424,10 @@ declare class FunnelSessions {
419
424
  private readonly idGenerator;
420
425
  private readonly dir;
421
426
  constructor(deps: Deps$13);
422
- /** Returns the existing session id for (channelId, cwd) or generates and persists a new one. */
423
- getOrCreate(channelId: string, cwd: string): string;
424
427
  /** Returns the existing session id for (channelId, cwd) or null. */
425
428
  get(channelId: string, cwd: string): string | null;
429
+ /** Generates a new session id for (channelId, cwd) and persists it, overwriting any prior entry. */
430
+ create(channelId: string, cwd: string): string;
426
431
  /** Drops the recorded session id for (channelId, cwd). No-op if absent. */
427
432
  clear(channelId: string, cwd: string): void;
428
433
  /** Drops the whole session map for the channel (e.g. when the channel is deleted). */
@@ -484,11 +489,12 @@ declare class FunnelClaude {
484
489
  private isProcessAlive;
485
490
  private buildArgs;
486
491
  /**
487
- * Decides whether funnel should inject `--session-id`. We back off when
488
- * the user already passed a session-shaping flag, since combining them
489
- * would either confuse claude or override the explicit user intent.
492
+ * Decides whether funnel should resume an existing claude session or start
493
+ * a freshly minted one. Backs off when the user already passed a
494
+ * session-shaping flag, since combining them would either confuse claude
495
+ * or override the explicit user intent.
490
496
  */
491
- private resolveSessionId;
497
+ private resolveSession;
492
498
  private buildEnv;
493
499
  }
494
500
  //#endregion
package/dist/index.js CHANGED
@@ -597,8 +597,8 @@ var FunnelClaude = class {
597
597
  this.writePidFile(options.profileName);
598
598
  this.installCleanup(options.profileName);
599
599
  }
600
- const sessionId = channel.resume ? this.resolveSessionId(channel.id, cwd, options.userArgs ?? []) : null;
601
- const claudeArgs = this.buildArgs(channel.options, options.userArgs ?? [], cwd, sessionId);
600
+ const session = channel.resume ? this.resolveSession(channel.id, cwd, options.userArgs ?? []) : null;
601
+ const claudeArgs = this.buildArgs(channel.options, options.userArgs ?? [], cwd, session);
602
602
  const env = this.buildEnv(channel.id, channel.env);
603
603
  this.logger.info(`claude launch`, {
604
604
  channel: options.channel,
@@ -649,25 +649,35 @@ var FunnelClaude = class {
649
649
  isProcessAlive(pid) {
650
650
  return this.process.isAlive(pid);
651
651
  }
652
- buildArgs(channelOptions, userArgs, cwd, sessionId) {
652
+ buildArgs(channelOptions, userArgs, cwd, session) {
653
653
  const result = [...channelOptions, ...userArgs];
654
- if (sessionId !== null) result.push("--session-id", sessionId);
654
+ if (session !== null) if (session.mode === "resume") result.push("--resume", session.id);
655
+ else result.push("--session-id", session.id);
655
656
  const mcpName = this.mcp.findInstalledName(cwd);
656
657
  if (mcpName && !result.includes("--dangerously-load-development-channels") && !result.includes("--channels")) result.push("--dangerously-load-development-channels", `server:${mcpName}`);
657
658
  return result;
658
659
  }
659
660
  /**
660
- * Decides whether funnel should inject `--session-id`. We back off when
661
- * the user already passed a session-shaping flag, since combining them
662
- * would either confuse claude or override the explicit user intent.
661
+ * Decides whether funnel should resume an existing claude session or start
662
+ * a freshly minted one. Backs off when the user already passed a
663
+ * session-shaping flag, since combining them would either confuse claude
664
+ * or override the explicit user intent.
663
665
  */
664
- resolveSessionId(channelId, cwd, userArgs) {
666
+ resolveSession(channelId, cwd, userArgs) {
665
667
  for (const arg of userArgs) {
666
668
  if (arg === "-c" || arg === "--continue") return null;
667
669
  if (arg === "--resume" || arg.startsWith("--resume=")) return null;
668
670
  if (arg === "--session-id" || arg.startsWith("--session-id=")) return null;
669
671
  }
670
- return this.sessions.getOrCreate(channelId, cwd);
672
+ const existing = this.sessions.get(channelId, cwd);
673
+ if (existing !== null) return {
674
+ id: existing,
675
+ mode: "resume"
676
+ };
677
+ return {
678
+ id: this.sessions.create(channelId, cwd),
679
+ mode: "new"
680
+ };
671
681
  }
672
682
  buildEnv(channelId, channelEnv) {
673
683
  const env = {};
@@ -1492,10 +1502,15 @@ const sessionsMapSchema = z.record(z.string(), z.string());
1492
1502
  /**
1493
1503
  * Per-channel persistent Claude Code session IDs, keyed by the cwd the
1494
1504
  * channel was launched from. The whole point is to give each (channel, cwd)
1495
- * its own stable conversation: relaunching from the same path picks up the
1496
- * previous claude session via `--session-id <uuid>`, while a different cwd
1497
- * (or a different channel) gets an independent one — so sessions never
1498
- * silently bleed across workspaces the way claude's `-c` does.
1505
+ * its own stable conversation: relaunching from the same path resumes the
1506
+ * previous claude session via `--resume <uuid>`, while a different cwd (or
1507
+ * a different channel) gets an independent one — so sessions never silently
1508
+ * bleed across workspaces the way claude's `-c` does.
1509
+ *
1510
+ * `get` and `create` are intentionally separate: claude's `--session-id`
1511
+ * only accepts a fresh UUID (it errors if the session jsonl already
1512
+ * exists), so callers must check `get` first and fall back to `create`
1513
+ * only when there is nothing to resume.
1499
1514
  *
1500
1515
  * Storage lives under `<dir>/channels/<channel-id>/sessions.json` (channel
1501
1516
  * id, not name, so renames don't lose history). The file is a flat
@@ -1511,20 +1526,18 @@ var FunnelSessions = class {
1511
1526
  this.dir = deps.dir;
1512
1527
  Object.freeze(this);
1513
1528
  }
1514
- /** Returns the existing session id for (channelId, cwd) or generates and persists a new one. */
1515
- getOrCreate(channelId, cwd) {
1529
+ /** Returns the existing session id for (channelId, cwd) or null. */
1530
+ get(channelId, cwd) {
1531
+ return this.readMap(channelId)[cwd] ?? null;
1532
+ }
1533
+ /** Generates a new session id for (channelId, cwd) and persists it, overwriting any prior entry. */
1534
+ create(channelId, cwd) {
1516
1535
  const map = this.readMap(channelId);
1517
- const existing = map[cwd];
1518
- if (existing) return existing;
1519
1536
  const sessionId = this.idGenerator.generate();
1520
1537
  map[cwd] = sessionId;
1521
1538
  this.writeMap(channelId, map);
1522
1539
  return sessionId;
1523
1540
  }
1524
- /** Returns the existing session id for (channelId, cwd) or null. */
1525
- get(channelId, cwd) {
1526
- return this.readMap(channelId)[cwd] ?? null;
1527
- }
1528
1541
  /** Drops the recorded session id for (channelId, cwd). No-op if absent. */
1529
1542
  clear(channelId, cwd) {
1530
1543
  const map = this.readMap(channelId);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@interactive-inc/claude-funnel",
3
- "version": "0.22.0",
3
+ "version": "0.22.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",
@@ -90,5 +90,8 @@
90
90
  },
91
91
  "engines": {
92
92
  "bun": ">=1.3.0"
93
+ },
94
+ "scripts": {
95
+ "prepack": "make build"
93
96
  }
94
97
  }