@dmsdc-ai/aigentry-telepty 0.1.39 → 0.1.41

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.
Files changed (3) hide show
  1. package/cli.js +12 -0
  2. package/daemon.js +28 -34
  3. package/package.json +1 -1
package/cli.js CHANGED
@@ -705,7 +705,9 @@ async function main() {
705
705
  let promptReady = true; // assume ready initially for first inject
706
706
  const injectQueue = [];
707
707
 
708
+ let queueFlushTimer = null;
708
709
  function flushInjectQueue() {
710
+ if (queueFlushTimer) { clearTimeout(queueFlushTimer); queueFlushTimer = null; }
709
711
  if (injectQueue.length === 0) return;
710
712
  const batch = injectQueue.splice(0);
711
713
  let delay = 0;
@@ -715,6 +717,15 @@ async function main() {
715
717
  }
716
718
  promptReady = false;
717
719
  }
720
+ function scheduleQueueFlush() {
721
+ if (queueFlushTimer) return;
722
+ queueFlushTimer = setTimeout(() => {
723
+ queueFlushTimer = null;
724
+ if (injectQueue.length > 0) {
725
+ flushInjectQueue();
726
+ }
727
+ }, 3000);
728
+ }
718
729
 
719
730
  // Connect to daemon WebSocket with auto-reconnect
720
731
  const wsUrl = `ws://${REMOTE_HOST}:${PORT}/api/sessions/${encodeURIComponent(sessionId)}?token=${encodeURIComponent(TOKEN)}`;
@@ -767,6 +778,7 @@ async function main() {
767
778
  }
768
779
  } else {
769
780
  injectQueue.push(msg.data);
781
+ scheduleQueueFlush();
770
782
  }
771
783
  } else if (msg.type === 'resize') {
772
784
  child.resize(msg.cols, msg.rows);
package/daemon.js CHANGED
@@ -193,7 +193,14 @@ app.post('/api/sessions/spawn', (req, res) => {
193
193
  app.post('/api/sessions/register', (req, res) => {
194
194
  const { session_id, command, cwd = process.cwd() } = req.body;
195
195
  if (!session_id) return res.status(400).json({ error: 'session_id is required' });
196
- if (sessions[session_id]) return res.status(409).json({ error: `Session ID '${session_id}' is already active.` });
196
+ // Idempotent: allow re-registration (update command/cwd, keep clients)
197
+ if (sessions[session_id]) {
198
+ const existing = sessions[session_id];
199
+ if (command) existing.command = command;
200
+ if (cwd) existing.cwd = cwd;
201
+ console.log(`[REGISTER] Re-registered session ${session_id} (updated metadata)`);
202
+ return res.status(200).json({ session_id, type: 'wrapped', command: existing.command, cwd: existing.cwd, reregistered: true });
203
+ }
197
204
 
198
205
  const sessionRecord = {
199
206
  id: session_id,
@@ -632,43 +639,30 @@ app.post('/api/sessions/:id/inject', (req, res) => {
632
639
  }
633
640
 
634
641
  let submitResult = null;
635
- if (session.type === 'wrapped' && !no_enter) {
636
- // Hybrid: text via WS (allow bridge handles it), Enter via kitty send-key
637
- if (!writeToSession(finalPrompt)) {
638
- return res.status(503).json({ error: 'Wrap process is not connected' });
639
- }
642
+ if (!writeToSession(finalPrompt)) {
643
+ return res.status(503).json({ error: 'Wrap process is not connected' });
644
+ }
645
+
646
+ if (!no_enter) {
647
+ // Universal split_cr: text first, \r after delay
648
+ // Allow bridge 0.1.40+ has 3s queue flush timeout, so \r always gets delivered
640
649
  setTimeout(() => {
641
- // Try kitty send-key Return (reliable for all CLIs)
642
- const windowId = findKittyWindowId(findKittySocket(), id);
643
- if (windowId) {
644
- try {
645
- const { execSync } = require('child_process');
646
- execSync(`kitty @ --to unix:${findKittySocket()} send-key --match id:${windowId} Return`, {
647
- timeout: 3000, stdio: ['pipe', 'pipe', 'pipe']
648
- });
649
- console.log(`[INJECT+SUBMIT] WS text + kitty Return for ${id} (window ${windowId})`);
650
- // Restore tab title after inject (Claude Code overwrites it)
651
- try {
652
- execSync(`kitty @ --to unix:${findKittySocket()} set-tab-title --match id:${windowId} '⚡ telepty :: ${id}'`, {
650
+ const ok = writeToSession('\r');
651
+ console.log(`[INJECT+SUBMIT] Split \\r for ${id}: ${ok ? 'success' : 'failed'}`);
652
+ // Restore kitty tab title (optional, no-op if not kitty)
653
+ try {
654
+ const sock = findKittySocket();
655
+ if (sock) {
656
+ if (!session.kittyWindowId) session.kittyWindowId = findKittyWindowId(sock, id);
657
+ if (session.kittyWindowId) {
658
+ require('child_process').execSync(`kitty @ --to unix:${sock} set-tab-title --match id:${session.kittyWindowId} '⚡ telepty :: ${id}'`, {
653
659
  timeout: 2000, stdio: ['pipe', 'pipe', 'pipe']
654
660
  });
655
- } catch {}
656
- } catch {
657
- writeToSession('\r');
658
- console.log(`[INJECT+SUBMIT] WS text + WS \\r fallback for ${id}`);
661
+ }
659
662
  }
660
- } else {
661
- writeToSession('\r');
662
- console.log(`[INJECT+SUBMIT] WS text + WS \\r (no kitty window) for ${id}`);
663
- }
664
- }, 500);
665
- submitResult = { deferred: true, strategy: 'ws_text_kitty_return' };
666
- } else if (session.type === 'wrapped') {
667
- // no_enter=true for wrapped
668
- if (!writeToSession(finalPrompt)) {
669
- return res.status(503).json({ error: 'Wrap process is not connected' });
670
- }
671
- submitResult = { strategy: 'ws_no_enter' };
663
+ } catch {}
664
+ }, 300);
665
+ submitResult = { deferred: true, strategy: 'split_cr' };
672
666
  } else {
673
667
  if (!writeToSession(finalPrompt)) {
674
668
  return res.status(503).json({ error: 'Wrap process is not connected' });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dmsdc-ai/aigentry-telepty",
3
- "version": "0.1.39",
3
+ "version": "0.1.41",
4
4
  "main": "daemon.js",
5
5
  "bin": {
6
6
  "aigentry-telepty": "install.js",