remote-cli-agent 0.1.0 → 0.3.0

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,9 +1,8 @@
1
- import { IPty } from 'node-pty';
2
1
  export interface TerminalSession {
3
2
  id: string;
4
3
  name: string;
5
4
  command?: string;
6
- pty?: IPty;
5
+ pty?: any;
7
6
  tmuxSession?: string;
8
7
  }
9
8
  export declare function setOutputHandler(handler: (sessionId: string, data: string) => void): void;
package/dist/terminal.js CHANGED
@@ -1,6 +1,14 @@
1
- import { spawn as nodePtySpawn } from 'node-pty';
2
- import { execSync } from 'child_process';
1
+ import { execSync, spawn as childSpawn } from 'child_process';
3
2
  import { v4 as uuidv4 } from 'uuid';
3
+ // Try to load node-pty, fall back to child_process
4
+ let nodePtySpawn;
5
+ try {
6
+ const pty = await import('node-pty');
7
+ nodePtySpawn = pty.spawn;
8
+ }
9
+ catch {
10
+ nodePtySpawn = null;
11
+ }
4
12
  // Active sessions
5
13
  const sessions = new Map();
6
14
  // Callbacks
@@ -39,15 +47,27 @@ export function attachTmuxSession(sessionName) {
39
47
  return null;
40
48
  }
41
49
  const id = uuidv4();
42
- const shell = process.env.SHELL || '/bin/bash';
43
- // Spawn a PTY that attaches to the tmux session
44
- const pty = nodePtySpawn(shell, ['-c', `tmux attach-session -t ${sessionName}`], {
45
- name: 'xterm-256color',
46
- cols: 80,
47
- rows: 24,
48
- cwd: process.env.HOME || '/',
49
- env: process.env
50
- });
50
+ const shell = process.env.SHELL || '/bin/zsh';
51
+ const tmuxArgs = ['-c', `tmux attach-session -t ${sessionName}`];
52
+ let pty;
53
+ if (nodePtySpawn) {
54
+ try {
55
+ pty = nodePtySpawn(shell, tmuxArgs, {
56
+ name: 'xterm-256color',
57
+ cols: 80,
58
+ rows: 24,
59
+ cwd: process.env.HOME || '/',
60
+ env: process.env
61
+ });
62
+ }
63
+ catch (err) {
64
+ console.warn('node-pty spawn failed, falling back:', err.message);
65
+ pty = null;
66
+ }
67
+ }
68
+ if (!pty) {
69
+ pty = createScriptPty(shell, tmuxArgs);
70
+ }
51
71
  const session = {
52
72
  id,
53
73
  name: `tmux: ${sessionName}`,
@@ -69,16 +89,29 @@ export function attachTmuxSession(sessionName) {
69
89
  // Spawn a new PTY session
70
90
  export function spawnSession(command) {
71
91
  const id = uuidv4();
72
- const shell = process.env.SHELL || '/bin/bash';
92
+ const shell = process.env.SHELL || '/bin/zsh';
73
93
  const cmd = command || shell;
74
94
  const args = command ? ['-c', command] : [];
75
- const pty = nodePtySpawn(command ? shell : shell, args, {
76
- name: 'xterm-256color',
77
- cols: 80,
78
- rows: 24,
79
- cwd: process.env.HOME || '/',
80
- env: process.env
81
- });
95
+ let pty;
96
+ if (nodePtySpawn) {
97
+ try {
98
+ pty = nodePtySpawn(shell, args, {
99
+ name: 'xterm-256color',
100
+ cols: 80,
101
+ rows: 24,
102
+ cwd: process.env.HOME || '/',
103
+ env: process.env
104
+ });
105
+ }
106
+ catch (err) {
107
+ console.warn('node-pty spawn failed, falling back to child_process:', err.message);
108
+ pty = null;
109
+ }
110
+ }
111
+ if (!pty) {
112
+ // Fallback: use child_process with script command to get a PTY
113
+ pty = createScriptPty(shell, args);
114
+ }
82
115
  const session = {
83
116
  id,
84
117
  name: command || shell,
@@ -91,6 +124,39 @@ export function spawnSession(command) {
91
124
  console.log(`Spawned session "${session.name}" with id ${id}`);
92
125
  return session;
93
126
  }
127
+ // Fallback PTY using macOS/Linux `script` command
128
+ function createScriptPty(shell, args) {
129
+ const fullCmd = args.length > 0 ? `${shell} ${args.join(' ')}` : shell;
130
+ // Use `script` to allocate a PTY
131
+ const proc = childSpawn('script', ['-q', '/dev/null', shell, ...args], {
132
+ stdio: ['pipe', 'pipe', 'pipe'],
133
+ env: { ...process.env, TERM: 'xterm-256color' },
134
+ cwd: process.env.HOME || '/',
135
+ });
136
+ const dataHandlers = [];
137
+ const exitHandlers = [];
138
+ proc.stdout?.on('data', (data) => {
139
+ for (const h of dataHandlers)
140
+ h(data.toString());
141
+ });
142
+ proc.stderr?.on('data', (data) => {
143
+ for (const h of dataHandlers)
144
+ h(data.toString());
145
+ });
146
+ proc.on('exit', (code) => {
147
+ for (const h of exitHandlers)
148
+ h({ exitCode: code ?? 0 });
149
+ });
150
+ return {
151
+ onData(handler) { dataHandlers.push(handler); },
152
+ onExit(handler) { exitHandlers.push(handler); },
153
+ write(data) { proc.stdin?.write(data); },
154
+ resize(_cols, _rows) { },
155
+ kill() { proc.kill(); },
156
+ cols: 80,
157
+ rows: 24,
158
+ };
159
+ }
94
160
  function setupPtyHandlers(session) {
95
161
  if (!session.pty)
96
162
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remote-cli-agent",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "remote-cli": "./dist/index.js"
@@ -9,6 +9,7 @@
9
9
  "build": "tsc",
10
10
  "start": "node dist/index.js",
11
11
  "dev": "tsx src/index.ts",
12
+ "postinstall": "node -e \"const fs=require('fs'),p=require('path'),d=p.join(__dirname,'node_modules','node-pty','prebuilds');try{fs.readdirSync(d).forEach(a=>{const h=p.join(d,a,'spawn-helper');try{fs.chmodSync(h,0o755);console.log('Fixed permissions:',h)}catch{}})}catch{}\"",
12
13
  "prepublishOnly": "npm run build"
13
14
  },
14
15
  "dependencies": {