polygram 0.11.0-rc.7 → 0.11.0-rc.9
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,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://anthropic.com/claude-code/plugin.schema.json",
|
|
3
3
|
"name": "polygram",
|
|
4
|
-
"version": "0.11.0-rc.
|
|
4
|
+
"version": "0.11.0-rc.9",
|
|
5
5
|
"description": "Telegram integration for Claude Code that preserves the OpenClaw per-chat session model. Migration target for OpenClaw users. Multi-bot, multi-chat, per-topic isolation; SQLite transcripts; inline-keyboard approvals. Bundles /polygram:status|logs|pair-code|approvals admin commands plus history (transcript queries) and polygram-send (out-of-turn IPC sends with file-upload validation) skills.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"telegram",
|
|
@@ -365,53 +365,96 @@ class ChannelsProcess extends Process {
|
|
|
365
365
|
'--dangerously-load-development-channels', 'server:polygram-bridge',
|
|
366
366
|
];
|
|
367
367
|
|
|
368
|
-
//
|
|
369
|
-
//
|
|
370
|
-
//
|
|
371
|
-
|
|
372
|
-
|
|
368
|
+
// Resolve config FIRST so the --resume file-check below has the correct
|
|
369
|
+
// cwd (it picks up topic precedence). Other flags get pushed in order
|
|
370
|
+
// after this.
|
|
371
|
+
const topicConfig = opts.threadId && opts.chatConfig?.topics?.[opts.threadId];
|
|
372
|
+
const agent = topicConfig?.agent || opts.chatConfig?.agent || opts.agent;
|
|
373
|
+
const model = topicConfig?.model || opts.chatConfig?.model || opts.model;
|
|
374
|
+
const effort = topicConfig?.effort || opts.chatConfig?.effort || opts.effort;
|
|
375
|
+
const resolvedCwd = topicConfig?.cwd || opts.chatConfig?.cwd || opts.cwd;
|
|
376
|
+
|
|
377
|
+
// Parity audit P8 + rc.8 fs-guard (2026-05-26 shumorobot Music topic):
|
|
378
|
+
// `--session-id <id>` creates a NEW claude session with that id;
|
|
379
|
+
// `--resume <id>` resumes the EXISTING conversation. Lazy-respawn after
|
|
380
|
+
// bridge-disconnect must use --resume so conversation history is
|
|
381
|
+
// preserved. Mirrors tmux-process.js:514-518.
|
|
373
382
|
//
|
|
374
|
-
// rc.
|
|
375
|
-
//
|
|
376
|
-
//
|
|
377
|
-
//
|
|
378
|
-
//
|
|
379
|
-
//
|
|
380
|
-
//
|
|
381
|
-
|
|
383
|
+
// rc.8 ghost-session guard: polygram persists claude_session_id to its
|
|
384
|
+
// DB as soon as the bridge handshakes (onInit), but claude only writes
|
|
385
|
+
// the JSONL after a successful turn. If an early channels attempt fails
|
|
386
|
+
// before claude completes any turn, polygram's DB ends up with a
|
|
387
|
+
// claude_session_id that has NO corresponding file under claude's
|
|
388
|
+
// projects dir. Subsequent `--resume <ghost-id>` makes claude exit
|
|
389
|
+
// clean with "No conversation found" — exactly the Music topic stall
|
|
390
|
+
// observed at 04:04:29 (session_id=567c72db never persisted; rc.4
|
|
391
|
+
// pane snapshot proved it).
|
|
392
|
+
//
|
|
393
|
+
// Fix: before passing --resume, verify the session JSONL actually
|
|
394
|
+
// exists under the launch cwd. If not, drop the ghost id and use
|
|
395
|
+
// --session-id with the freshly-generated uuid — claude creates a
|
|
396
|
+
// fresh session and onInit re-upserts the DB row.
|
|
397
|
+
//
|
|
398
|
+
// Resume cases preserved:
|
|
399
|
+
// - in-daemon lazy respawn (file written after first successful turn)
|
|
400
|
+
// - daemon restart on a chat that completed at least one turn
|
|
401
|
+
// Resume cases correctly dropped:
|
|
402
|
+
// - cross-backend stale ids (different cwd → different projects dir)
|
|
403
|
+
// - ghost ids from failed-before-first-turn attempts
|
|
404
|
+
let canResume = false;
|
|
405
|
+
let resumePath = null;
|
|
406
|
+
if (opts.existingSessionId && resolvedCwd) {
|
|
407
|
+
// claude's projects dir naming: cwd with '/' → '-'.
|
|
408
|
+
// Verified live at ~/.claude/projects/-Users-ivanshumkov-Music-rekordbox/
|
|
409
|
+
const cwdMangled = resolvedCwd.replace(/\//g, '-');
|
|
410
|
+
resumePath = path.join(os.homedir(), '.claude', 'projects', cwdMangled, `${opts.existingSessionId}.jsonl`);
|
|
411
|
+
try { canResume = fs.statSync(resumePath).isFile(); } catch { canResume = false; }
|
|
412
|
+
}
|
|
413
|
+
if (canResume) {
|
|
382
414
|
claudeArgs.push('--resume', opts.existingSessionId);
|
|
383
415
|
} else {
|
|
384
416
|
claudeArgs.push('--session-id', this.claudeSessionId);
|
|
417
|
+
if (opts.existingSessionId) {
|
|
418
|
+
this.logger.warn?.(
|
|
419
|
+
`[${this.label}] channels: dropping DB session ${opts.existingSessionId} — ` +
|
|
420
|
+
`no local file at ${resumePath || '<unknown cwd>'}. Starting fresh with ${this.claudeSessionId}.`,
|
|
421
|
+
);
|
|
422
|
+
}
|
|
385
423
|
}
|
|
386
|
-
|
|
387
|
-
// Parity audit P4: per-chat / per-topic agent flag. Without this, chats
|
|
388
|
-
// configured with agent='music-curation' / 'shumabit' silently fall back
|
|
389
|
-
// to claude's default. Mirrors tmux-process.js:527.
|
|
390
|
-
// Topic precedence over chat — same as tmux pattern (parity audit P7).
|
|
391
|
-
const topicConfig = opts.threadId && opts.chatConfig?.topics?.[opts.threadId];
|
|
392
|
-
const agent = topicConfig?.agent || opts.chatConfig?.agent || opts.agent;
|
|
393
|
-
const model = topicConfig?.model || opts.chatConfig?.model || opts.model;
|
|
394
|
-
const effort = topicConfig?.effort || opts.chatConfig?.effort || opts.effort;
|
|
395
424
|
if (agent) claudeArgs.push('--agent', agent);
|
|
396
425
|
if (model) claudeArgs.unshift('--model', model);
|
|
397
426
|
if (effort) claudeArgs.push('--effort', effort);
|
|
398
427
|
|
|
399
|
-
//
|
|
400
|
-
//
|
|
401
|
-
//
|
|
402
|
-
//
|
|
403
|
-
//
|
|
404
|
-
//
|
|
405
|
-
//
|
|
428
|
+
// rc.9 (2026-05-26 shumorobot first-turn-dead-zone diagnosis): channels
|
|
429
|
+
// backend defaults to permissionMode='bypassPermissions'. Without it,
|
|
430
|
+
// claude TUI shows the canonical interactive permission prompt for
|
|
431
|
+
// every `mcp__polygram-bridge__reply` call:
|
|
432
|
+
//
|
|
433
|
+
// polygram-bridge - reply(...) (MCP)
|
|
434
|
+
// Do you want to proceed?
|
|
435
|
+
// ❯ 1. Yes 2. Yes, and don't ask again 3. No
|
|
436
|
+
//
|
|
437
|
+
// Channels mode has no interactive surface — there's no human at the
|
|
438
|
+
// tmux pane to press a number — so every first-turn hangs until the
|
|
439
|
+
// 30-min turn timeout fires. Reproduced + fixed live via
|
|
440
|
+
// `scripts/spikes/channels-first-turn.mjs`: without bypassPermissions
|
|
441
|
+
// the spike times out at 60s with claude "Marinating" forever; with
|
|
442
|
+
// bypassPermissions it replies in ~5s.
|
|
443
|
+
//
|
|
444
|
+
// The bridge DOES relay `notifications/claude/channel/permission_request`
|
|
445
|
+
// (channels-bridge.mjs:258) for the EXPERIMENTAL channel-permission
|
|
446
|
+
// API, but claude TUI doesn't route ordinary MCP tool calls through
|
|
447
|
+
// that channel — it shows the regular TUI prompt. So the relay path
|
|
448
|
+
// isn't reachable from a fresh-spawn channels turn.
|
|
406
449
|
//
|
|
407
|
-
//
|
|
408
|
-
//
|
|
409
|
-
//
|
|
410
|
-
// confirmations.
|
|
450
|
+
// Config can still override (e.g., chats that genuinely want a
|
|
451
|
+
// different mode set `permissionMode` in chat/topic config); the
|
|
452
|
+
// default ensures bots actually reply out of the box.
|
|
411
453
|
const permissionMode = topicConfig?.permissionMode
|
|
412
454
|
|| opts.chatConfig?.permissionMode
|
|
413
|
-
|| opts.permissionMode
|
|
414
|
-
|
|
455
|
+
|| opts.permissionMode
|
|
456
|
+
|| 'bypassPermissions';
|
|
457
|
+
claudeArgs.push('--permission-mode', permissionMode);
|
|
415
458
|
if (permissionMode === 'bypassPermissions') {
|
|
416
459
|
claudeArgs.push('--dangerously-skip-permissions');
|
|
417
460
|
}
|
|
@@ -466,8 +509,8 @@ class ChannelsProcess extends Process {
|
|
|
466
509
|
// --mcp-config MUST be last (variadic flag)
|
|
467
510
|
claudeArgs.push('--mcp-config', this.mcpConfigPath); // P0 #1: file path, not inline JSON
|
|
468
511
|
|
|
469
|
-
|
|
470
|
-
if (
|
|
512
|
+
// resolvedCwd was computed above (line ~375) for the --resume file-check.
|
|
513
|
+
if (resolvedCwd) claudeArgs.unshift('--add-dir', resolvedCwd);
|
|
471
514
|
|
|
472
515
|
// rc.5 (2026-05-25 shumorobot diagnosis): the launch cwd MUST be the
|
|
473
516
|
// resolved topic/chat cwd, not just opts.cwd. claude's TUI indexes
|
|
@@ -486,7 +529,7 @@ class ChannelsProcess extends Process {
|
|
|
486
529
|
// Real tmuxRunner.spawn signature: {name, cwd, command, args, envExtras, paneWidth}
|
|
487
530
|
await this.runner.spawn({
|
|
488
531
|
name: tmuxName,
|
|
489
|
-
cwd:
|
|
532
|
+
cwd: resolvedCwd || opts.cwd || process.cwd(),
|
|
490
533
|
command: this.claudeBin,
|
|
491
534
|
args: claudeArgs,
|
|
492
535
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "polygram",
|
|
3
|
-
"version": "0.11.0-rc.
|
|
3
|
+
"version": "0.11.0-rc.9",
|
|
4
4
|
"description": "Telegram daemon for Claude Code that preserves the OpenClaw per-chat session model. Migration path for OpenClaw users moving to Claude Code.",
|
|
5
5
|
"main": "lib/ipc/client.js",
|
|
6
6
|
"bin": {
|