@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/bin.js +3 -3
- package/dist/gateway/daemon.js +153 -153
- package/dist/index.d.ts +16 -10
- package/dist/index.js +34 -21
- package/package.json +4 -1
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
|
|
409
|
-
* previous claude session via `--
|
|
410
|
-
*
|
|
411
|
-
*
|
|
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
|
|
488
|
-
* the user already passed a
|
|
489
|
-
*
|
|
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
|
|
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
|
|
601
|
-
const claudeArgs = this.buildArgs(channel.options, options.userArgs ?? [], cwd,
|
|
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,
|
|
652
|
+
buildArgs(channelOptions, userArgs, cwd, session) {
|
|
653
653
|
const result = [...channelOptions, ...userArgs];
|
|
654
|
-
if (
|
|
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
|
|
661
|
-
* the user already passed a
|
|
662
|
-
*
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
1496
|
-
* previous claude session via `--
|
|
1497
|
-
*
|
|
1498
|
-
*
|
|
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
|
|
1515
|
-
|
|
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.
|
|
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
|
}
|