@interactive-inc/claude-funnel 0.25.0 → 0.25.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
@@ -494,8 +494,23 @@ declare class FunnelClaude {
494
494
  * a freshly minted one. Backs off when the user already passed a
495
495
  * session-shaping flag, since combining them would either confuse claude
496
496
  * or override the explicit user intent.
497
+ *
498
+ * A persisted id is only resumed when its session jsonl still exists on
499
+ * disk. claude errors out on `--resume <id>` for a missing conversation, and
500
+ * a persisted id can outlive its jsonl (claude pruned it, or the very first
501
+ * launch was aborted after `create` wrote the id but before the jsonl
502
+ * appeared). When the file is gone we mint a fresh session instead, which
503
+ * overwrites the dangling entry — so the store self-heals.
497
504
  */
498
505
  private resolveSession;
506
+ /**
507
+ * Mirrors claude's session storage path
508
+ * (`<config-dir>/projects/<cwd-with-slashes-as-dashes>/<id>.jsonl`) to check
509
+ * whether a recorded session still exists. Reads the same `CLAUDE_CONFIG_DIR`
510
+ * the child will run under so the check matches reality; a wrong guess can
511
+ * only ever produce a false negative (start fresh), never a bad resume.
512
+ */
513
+ private sessionFileExists;
499
514
  private buildEnv;
500
515
  }
501
516
  //#endregion
package/dist/index.js CHANGED
@@ -577,7 +577,7 @@ var FunnelClaude = class {
577
577
  this.writePidFile(options.profileName);
578
578
  this.installCleanup(options.profileName);
579
579
  }
580
- const session = options.resume ?? true ? this.resolveSession(channel.id, cwd, options.userArgs ?? []) : null;
580
+ const session = options.resume ?? true ? this.resolveSession(channel.id, cwd, options.userArgs ?? [], options.env ?? {}) : null;
581
581
  const claudeArgs = this.buildArgs(options.options ?? [], options.userArgs ?? [], cwd, session);
582
582
  const env = this.buildEnv(channel.id, options.env ?? {});
583
583
  this.logger.info(`claude launch`, {
@@ -642,15 +642,22 @@ var FunnelClaude = class {
642
642
  * a freshly minted one. Backs off when the user already passed a
643
643
  * session-shaping flag, since combining them would either confuse claude
644
644
  * or override the explicit user intent.
645
+ *
646
+ * A persisted id is only resumed when its session jsonl still exists on
647
+ * disk. claude errors out on `--resume <id>` for a missing conversation, and
648
+ * a persisted id can outlive its jsonl (claude pruned it, or the very first
649
+ * launch was aborted after `create` wrote the id but before the jsonl
650
+ * appeared). When the file is gone we mint a fresh session instead, which
651
+ * overwrites the dangling entry — so the store self-heals.
645
652
  */
646
- resolveSession(channelId, cwd, userArgs) {
653
+ resolveSession(channelId, cwd, userArgs, recipeEnv) {
647
654
  for (const arg of userArgs) {
648
655
  if (arg === "-c" || arg === "--continue") return null;
649
656
  if (arg === "--resume" || arg.startsWith("--resume=")) return null;
650
657
  if (arg === "--session-id" || arg.startsWith("--session-id=")) return null;
651
658
  }
652
659
  const existing = this.sessions.get(channelId, cwd);
653
- if (existing !== null) return {
660
+ if (existing !== null && this.sessionFileExists(cwd, existing, recipeEnv)) return {
654
661
  id: existing,
655
662
  mode: "resume"
656
663
  };
@@ -659,6 +666,18 @@ var FunnelClaude = class {
659
666
  mode: "new"
660
667
  };
661
668
  }
669
+ /**
670
+ * Mirrors claude's session storage path
671
+ * (`<config-dir>/projects/<cwd-with-slashes-as-dashes>/<id>.jsonl`) to check
672
+ * whether a recorded session still exists. Reads the same `CLAUDE_CONFIG_DIR`
673
+ * the child will run under so the check matches reality; a wrong guess can
674
+ * only ever produce a false negative (start fresh), never a bad resume.
675
+ */
676
+ sessionFileExists(cwd, sessionId, recipeEnv) {
677
+ const configDir = recipeEnv.CLAUDE_CONFIG_DIR ?? globalThis.process.env.CLAUDE_CONFIG_DIR ?? join(homedir(), ".claude");
678
+ const projectSlug = cwd.replace(/\//g, "-");
679
+ return this.fs.existsSync(join(configDir, "projects", projectSlug, `${sessionId}.jsonl`));
680
+ }
662
681
  buildEnv(channelId, recipeEnv) {
663
682
  const env = {};
664
683
  for (const [key, value] of Object.entries(recipeEnv)) env[key] = value;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@interactive-inc/claude-funnel",
3
- "version": "0.25.0",
3
+ "version": "0.25.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",