@dmsdc-ai/aigentry-telepty 0.1.74 → 0.1.76

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 (2) hide show
  1. package/daemon.js +45 -42
  2. package/package.json +1 -1
package/daemon.js CHANGED
@@ -342,13 +342,17 @@ app.post('/api/sessions/register', (req, res) => {
342
342
  if (backend) existing.backend = backend;
343
343
  if (cmux_workspace_id) existing.cmuxWorkspaceId = cmux_workspace_id;
344
344
  if (cmux_surface_id) existing.cmuxSurfaceId = cmux_surface_id;
345
- console.log(`[REGISTER] Re-registered session ${session_id} (updated metadata)`);
346
- return res.status(200).json({ session_id, type: 'wrapped', command: existing.command, cwd: existing.cwd, reregistered: true });
345
+ if (req.body.delivery_type) existing.type = req.body.delivery_type;
346
+ if (req.body.delivery_endpoint) existing.deliveryEndpoint = req.body.delivery_endpoint;
347
+ if (req.body.delivery_type === 'aterm') existing.ready = true;
348
+ console.log(`[REGISTER] Re-registered session ${session_id} (type: ${existing.type}, updated metadata)`);
349
+ return res.status(200).json({ session_id, type: existing.type, command: existing.command, cwd: existing.cwd, reregistered: true });
347
350
  }
348
351
 
352
+ const { delivery_type, delivery_endpoint } = req.body;
349
353
  const sessionRecord = {
350
354
  id: session_id,
351
- type: 'wrapped',
355
+ type: delivery_type || 'wrapped',
352
356
  ptyProcess: null,
353
357
  ownerWs: null,
354
358
  command: command || 'wrapped',
@@ -356,12 +360,13 @@ app.post('/api/sessions/register', (req, res) => {
356
360
  backend: backend || 'kitty',
357
361
  cmuxWorkspaceId: cmux_workspace_id || null,
358
362
  cmuxSurfaceId: cmux_surface_id || null,
363
+ deliveryEndpoint: delivery_endpoint || null,
359
364
  createdAt: new Date().toISOString(),
360
365
  lastActivityAt: new Date().toISOString(),
361
366
  clients: new Set(),
362
367
  isClosing: false,
363
368
  outputRing: [],
364
- ready: false,
369
+ ready: delivery_type === 'aterm', // aterm sessions are always ready (aterm manages readiness)
365
370
  };
366
371
  // Check for existing session with same base alias and emit replaced event
367
372
  const baseAlias = session_id.replace(/-\d+$/, '');
@@ -421,7 +426,8 @@ app.get('/api/sessions', (req, res) => {
421
426
  lastActivityAt: session.lastActivityAt || null,
422
427
  idleSeconds,
423
428
  active_clients: session.clients.size,
424
- ready: session.ready || false
429
+ ready: session.ready || false,
430
+ deliveryEndpoint: session.deliveryEndpoint || null
425
431
  };
426
432
  });
427
433
  if (idleGt !== null) {
@@ -884,7 +890,19 @@ app.post('/api/sessions/:id/inject', (req, res) => {
884
890
  // Always inject text WITHOUT \r first, then send \r separately after delay
885
891
  // This two-step approach works for ALL CLIs (claude, codex, gemini)
886
892
  function writeToSession(data) {
887
- if (session.type === 'wrapped') {
893
+ if (session.type === 'aterm' && session.deliveryEndpoint) {
894
+ // Route to aterm PtyManager — fire-and-forget, aterm handles delivery
895
+ try {
896
+ const url = session.deliveryEndpoint;
897
+ fetch(url, {
898
+ method: 'POST',
899
+ headers: { 'Content-Type': 'application/json' },
900
+ body: JSON.stringify({ text: data, session_id: id }),
901
+ signal: AbortSignal.timeout(5000)
902
+ }).catch(() => {});
903
+ return true;
904
+ } catch { return false; }
905
+ } else if (session.type === 'wrapped') {
888
906
  if (session.ownerWs && session.ownerWs.readyState === 1) {
889
907
  session.ownerWs.send(JSON.stringify({ type: 'inject', data }));
890
908
  return true;
@@ -897,7 +915,17 @@ app.post('/api/sessions/:id/inject', (req, res) => {
897
915
  }
898
916
 
899
917
  let submitResult = null;
900
- if (session.type === 'wrapped') {
918
+ if (session.type === 'aterm' && session.deliveryEndpoint) {
919
+ // aterm sessions: deliver text + CR via aterm PtyManager endpoint
920
+ const wsOk = writeToSession(finalPrompt);
921
+ if (!wsOk) {
922
+ return res.status(503).json({ error: 'aterm endpoint not reachable' });
923
+ }
924
+ if (!no_enter) {
925
+ setTimeout(() => writeToSession('\r'), 300);
926
+ submitResult = { deferred: true, strategy: 'aterm_endpoint' };
927
+ }
928
+ } else if (session.type === 'wrapped') {
901
929
  // For wrapped sessions: try cmux send (daemon-level auto-detect),
902
930
  // then kitty send-text (bypasses allow bridge queue),
903
931
  // then WS as fallback, then submit via consistent path for CR.
@@ -938,26 +966,24 @@ app.post('/api/sessions/:id/inject', (req, res) => {
938
966
  }
939
967
  }
940
968
  if (!cmuxOk && !kittyOk) {
941
- // WS path: allow-bridge has its own prompt-ready queue
942
- const wsOk = writeToSession(finalPrompt);
969
+ // WS path: combine text + CR into single message.
970
+ // This guarantees CR delivery regardless of allow-bridge version —
971
+ // old allow-bridges with broken idle queue won't split text and CR.
972
+ const wsPayload = no_enter ? finalPrompt : finalPrompt + '\r';
973
+ const wsOk = writeToSession(wsPayload);
943
974
  if (!wsOk) {
944
975
  return res.status(503).json({ error: 'Process not connected' });
945
976
  }
946
977
  deliveryPath = 'ws';
947
- if (!session.ready) {
948
- console.log(`[INJECT] WS (not ready, allow-bridge will queue) for ${id}`);
949
- } else {
950
- console.log(`[INJECT] WS fallback for ${id}`);
951
- }
978
+ console.log(`[INJECT] WS ${no_enter ? '(no-enter)' : '(text+CR combined)'} for ${id}`);
952
979
  }
953
980
 
954
- if (!no_enter) {
981
+ if (!no_enter && deliveryPath !== 'ws') {
982
+ // CR only needed for cmux/kitty paths (WS already included CR in payload)
955
983
  setTimeout(() => {
956
984
  let submitted = false;
957
985
 
958
- // Use the SAME path that delivered text for CR to guarantee ordering
959
986
  if (deliveryPath === 'cmux') {
960
- // cmux: send-key return via same surface
961
987
  if (session.backend === 'cmux') {
962
988
  submitted = terminalBackend.cmuxSendEnter(id);
963
989
  if (submitted) console.log(`[INJECT] cmux submit for ${id}`);
@@ -967,7 +993,6 @@ app.post('/api/sessions/:id/inject', (req, res) => {
967
993
  if (submitted) console.log(`[INJECT] cmux session-level submit for ${id}`);
968
994
  }
969
995
  } else if (deliveryPath === 'kitty') {
970
- // kitty: send-text CR via same window (not osascript!)
971
996
  if (wid && sock) {
972
997
  try {
973
998
  require('child_process').execSync(`kitty @ --to unix:${sock} send-text --match id:${wid} $'\\r'`, {
@@ -980,32 +1005,10 @@ app.post('/api/sessions/:id/inject', (req, res) => {
980
1005
  }
981
1006
  }
982
1007
  }
983
- // deliveryPath === 'ws' or any fallback:
984
- // Try terminal-level submit first (bypasses PTY ICRNL which converts CR→LF)
985
- // This matters for cmux/kitty sessions where text went via WS but
986
- // the application expects CR(13) not LF(10) from Enter.
987
- if (!submitted && session.backend === 'cmux') {
988
- submitted = terminalBackend.cmuxSendEnter(id);
989
- if (submitted) console.log(`[INJECT] cmux submit (fallback) for ${id}`);
990
- }
991
- if (!submitted && session.backend === 'cmux' && session.cmuxWorkspaceId) {
992
- submitted = submitViaCmux(id);
993
- if (submitted) console.log(`[INJECT] cmux session-level submit (fallback) for ${id}`);
994
- }
995
- if (!submitted && wid && sock) {
996
- try {
997
- require('child_process').execSync(`kitty @ --to unix:${sock} send-text --match id:${wid} $'\\r'`, {
998
- timeout: 3000, stdio: ['pipe', 'pipe', 'pipe']
999
- });
1000
- submitted = true;
1001
- console.log(`[INJECT] kitty submit (fallback) for ${id}`);
1002
- } catch {
1003
- session.kittyWindowId = null;
1004
- }
1005
- }
1008
+ // Final fallback for cmux/kitty paths
1006
1009
  if (!submitted) {
1007
1010
  writeToSession('\r');
1008
- console.log(`[INJECT] WS submit for ${id}`);
1011
+ console.log(`[INJECT] WS submit fallback for ${id}`);
1009
1012
  }
1010
1013
 
1011
1014
  // Update tab title (kitty-specific, safe to fail)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dmsdc-ai/aigentry-telepty",
3
- "version": "0.1.74",
3
+ "version": "0.1.76",
4
4
  "main": "daemon.js",
5
5
  "bin": {
6
6
  "aigentry-telepty": "install.js",