@ai-devkit/agent-manager 0.7.0 → 0.9.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.
@@ -5,8 +5,8 @@ export declare class TtyWriter {
5
5
  *
6
6
  * Dispatches to the correct mechanism based on terminal type:
7
7
  * - tmux: `tmux send-keys`
8
- * - iTerm2: AppleScript `write text`
9
- * - Terminal.app: System Events `keystroke` + `key code 36` (Return)
8
+ * - iTerm2: Two separate AppleScript `write text` calls (text then newline)
9
+ * - Terminal.app: Two separate AppleScript `do script` calls (text then newline)
10
10
  *
11
11
  * All AppleScript is executed via `execFile('osascript', ['-e', script])`
12
12
  * to avoid shell interpolation and command injection.
@@ -17,6 +17,12 @@ export declare class TtyWriter {
17
17
  */
18
18
  static send(location: TerminalLocation, message: string): Promise<void>;
19
19
  private static sendViaTmux;
20
+ /**
21
+ * Build an AppleScript that finds an iTerm2 session by TTY and runs a
22
+ * command against it. The `sessionCommand` is inserted inside a
23
+ * `tell targetSession` block.
24
+ */
25
+ private static iterm2SessionScript;
20
26
  private static sendViaITerm2;
21
27
  private static sendViaTerminalApp;
22
28
  }
@@ -1 +1 @@
1
- {"version":3,"file":"TtyWriter.d.ts","sourceRoot":"","sources":["../../src/terminal/TtyWriter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAa/D,qBAAa,SAAS;IAClB;;;;;;;;;;;;;;OAcG;WACU,IAAI,CAAC,QAAQ,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;mBAgBxD,WAAW;mBAWX,aAAa;mBAsCb,kBAAkB;CA6C1C"}
1
+ {"version":3,"file":"TtyWriter.d.ts","sourceRoot":"","sources":["../../src/terminal/TtyWriter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAgB/D,qBAAa,SAAS;IAClB;;;;;;;;;;;;;;OAcG;WACU,IAAI,CAAC,QAAQ,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;mBAgBxD,WAAW;IAWhC;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,mBAAmB;mBAsBb,aAAa;mBAuBb,kBAAkB;CA0D1C"}
@@ -7,10 +7,13 @@ const TerminalFocusManager_1 = require("./TerminalFocusManager");
7
7
  const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
8
8
  /**
9
9
  * Escape a string for safe use inside an AppleScript double-quoted string.
10
- * Backslashes and double quotes must be escaped.
10
+ * Backslashes, double quotes, and newlines must be escaped.
11
11
  */
12
12
  function escapeAppleScript(text) {
13
- return text.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
13
+ return text
14
+ .replace(/\\/g, '\\\\')
15
+ .replace(/"/g, '\\"')
16
+ .replace(/\r\n|\r|\n/g, '\\n');
14
17
  }
15
18
  class TtyWriter {
16
19
  /**
@@ -18,8 +21,8 @@ class TtyWriter {
18
21
  *
19
22
  * Dispatches to the correct mechanism based on terminal type:
20
23
  * - tmux: `tmux send-keys`
21
- * - iTerm2: AppleScript `write text`
22
- * - Terminal.app: System Events `keystroke` + `key code 36` (Return)
24
+ * - iTerm2: Two separate AppleScript `write text` calls (text then newline)
25
+ * - Terminal.app: Two separate AppleScript `do script` calls (text then newline)
23
26
  *
24
27
  * All AppleScript is executed via `execFile('osascript', ['-e', script])`
25
28
  * to avoid shell interpolation and command injection.
@@ -51,12 +54,13 @@ class TtyWriter {
51
54
  await new Promise((resolve) => setTimeout(resolve, 150));
52
55
  await execFileAsync('tmux', ['send-keys', '-t', identifier, 'Enter']);
53
56
  }
54
- static async sendViaITerm2(tty, message) {
55
- const escaped = escapeAppleScript(message);
56
- // Send text WITHOUT a trailing newline to avoid the newline being swallowed
57
- // by bracketed paste mode. Then simulate pressing Return separately so that
58
- // Claude Code (and other interactive TUIs) treat it as a real submit action.
59
- const script = `
57
+ /**
58
+ * Build an AppleScript that finds an iTerm2 session by TTY and runs a
59
+ * command against it. The `sessionCommand` is inserted inside a
60
+ * `tell targetSession` block.
61
+ */
62
+ static iterm2SessionScript(tty, sessionCommand) {
63
+ return `
60
64
  tell application "iTerm"
61
65
  set targetSession to missing value
62
66
  repeat with w in windows
@@ -72,64 +76,82 @@ tell application "iTerm"
72
76
  if targetSession is not missing value then exit repeat
73
77
  end repeat
74
78
  if targetSession is missing value then return "not_found"
75
- tell targetSession to write text "${escaped}" newline no
76
- end tell
77
- tell application "iTerm" to activate
78
- delay 0.15
79
- tell application "System Events"
80
- tell process "iTerm2"
81
- key code 36
82
- end tell
79
+ tell targetSession to ${sessionCommand}
83
80
  end tell
84
81
  return "ok"`;
85
- const { stdout } = await execFileAsync('osascript', ['-e', script]);
86
- if (stdout.trim() !== 'ok') {
82
+ }
83
+ static async sendViaITerm2(tty, message) {
84
+ const escaped = escapeAppleScript(message);
85
+ // Send text and Enter as two separate write text calls so the newline
86
+ // is delivered outside the bracketed paste sequence of the message body.
87
+ // iTerm2 appends the newline after the paste-end marker (\e[201~), so
88
+ // the inner TUI (Claude Code, Codex) sees it as a real submit action.
89
+ const textScript = TtyWriter.iterm2SessionScript(tty, `write text "${escaped}" newline no`);
90
+ const { stdout: textResult } = await execFileAsync('osascript', ['-e', textScript]);
91
+ if (textResult.trim() !== 'ok') {
87
92
  throw new Error(`iTerm2 session not found for TTY ${tty}`);
88
93
  }
94
+ // Wait for the paste to complete before sending Enter separately
95
+ await new Promise((resolve) => setTimeout(resolve, 150));
96
+ const enterScript = TtyWriter.iterm2SessionScript(tty, 'write text "" newline yes');
97
+ const { stdout: enterResult } = await execFileAsync('osascript', ['-e', enterScript]);
98
+ if (enterResult.trim() !== 'ok') {
99
+ throw new Error(`iTerm2 session disappeared before Enter could be sent for TTY ${tty}`);
100
+ }
89
101
  }
90
102
  static async sendViaTerminalApp(tty, message) {
91
103
  const escaped = escapeAppleScript(message);
92
- // Use System Events keystroke to type into the foreground process,
93
- // NOT Terminal.app's "do script" which runs a new shell command.
94
- // First activate Terminal and select the correct tab, then type via System Events.
95
- // Send the text first, then wait for the paste/input to complete before pressing
96
- // Return separately this ensures interactive TUIs (like Claude Code) see the
97
- // Return as a real submit action, not part of a bracketed paste.
98
- const script = `
104
+ // Use Terminal.app's `do script` to send text to the correct tab by TTY.
105
+ // We avoid System Events `keystroke` + `key code 36` because it requires
106
+ // accessibility permissions and unreliably delivers the Return key.
107
+ //
108
+ // `do script` with `in` targets a specific tab without opening a new one.
109
+ // We send text and Enter as two separate calls so the newline arrives
110
+ // outside of bracketed paste mode — same pattern as iTerm2 and tmux.
111
+ const textScript = `
99
112
  tell application "Terminal"
100
- set targetFound to false
113
+ set targetTab to missing value
101
114
  repeat with w in windows
102
115
  repeat with i from 1 to count of tabs of w
103
116
  set t to tab i of w
104
117
  if tty of t is "${tty}" then
105
- set selected tab of w to t
106
- set index of w to 1
107
- activate
108
- set targetFound to true
118
+ set targetTab to t
109
119
  exit repeat
110
120
  end if
111
121
  end repeat
112
- if targetFound then exit repeat
122
+ if targetTab is not missing value then exit repeat
113
123
  end repeat
114
- if not targetFound then return "not_found"
115
- end tell
116
- delay 0.1
117
- tell application "System Events"
118
- tell process "Terminal"
119
- keystroke "${escaped}"
120
- end tell
121
- end tell
122
- delay 0.15
123
- tell application "System Events"
124
- tell process "Terminal"
125
- key code 36
126
- end tell
124
+ if targetTab is missing value then return "not_found"
125
+ do script "${escaped}" in targetTab
127
126
  end tell
128
127
  return "ok"`;
129
- const { stdout } = await execFileAsync('osascript', ['-e', script]);
130
- if (stdout.trim() !== 'ok') {
128
+ const { stdout: textResult } = await execFileAsync('osascript', ['-e', textScript]);
129
+ if (textResult.trim() !== 'ok') {
131
130
  throw new Error(`Terminal.app tab not found for TTY ${tty}`);
132
131
  }
132
+ // Wait for the text to be delivered before sending Enter
133
+ await new Promise((resolve) => setTimeout(resolve, 150));
134
+ const enterScript = `
135
+ tell application "Terminal"
136
+ set targetTab to missing value
137
+ repeat with w in windows
138
+ repeat with i from 1 to count of tabs of w
139
+ set t to tab i of w
140
+ if tty of t is "${tty}" then
141
+ set targetTab to t
142
+ exit repeat
143
+ end if
144
+ end repeat
145
+ if targetTab is not missing value then exit repeat
146
+ end repeat
147
+ if targetTab is missing value then return "not_found"
148
+ do script "" in targetTab
149
+ end tell
150
+ return "ok"`;
151
+ const { stdout: enterResult } = await execFileAsync('osascript', ['-e', enterScript]);
152
+ if (enterResult.trim() !== 'ok') {
153
+ throw new Error(`Terminal.app tab disappeared before Enter could be sent for TTY ${tty}`);
154
+ }
133
155
  }
134
156
  }
135
157
  exports.TtyWriter = TtyWriter;
@@ -1 +1 @@
1
- {"version":3,"file":"TtyWriter.js","sourceRoot":"","sources":["../../src/terminal/TtyWriter.ts"],"names":[],"mappings":";;;AAAA,iDAAyC;AACzC,+BAAiC;AAEjC,iEAAsD;AAEtD,MAAM,aAAa,GAAG,IAAA,gBAAS,EAAC,wBAAQ,CAAC,CAAC;AAE1C;;;GAGG;AACH,SAAS,iBAAiB,CAAC,IAAY;IACnC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAC5D,CAAC;AAED,MAAa,SAAS;IAClB;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,QAA0B,EAAE,OAAe;QACzD,QAAQ,QAAQ,CAAC,IAAI,EAAE,CAAC;YACpB,KAAK,mCAAY,CAAC,IAAI;gBAClB,OAAO,SAAS,CAAC,WAAW,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YAC/D,KAAK,mCAAY,CAAC,MAAM;gBACpB,OAAO,SAAS,CAAC,aAAa,CAAC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YAC1D,KAAK,mCAAY,CAAC,YAAY;gBAC1B,OAAO,SAAS,CAAC,kBAAkB,CAAC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YAC/D;gBACI,MAAM,IAAI,KAAK,CACX,iDAAiD,QAAQ,CAAC,IAAI,KAAK;oBACnE,wCAAwC,CAC3C,CAAC;QACV,CAAC;IACL,CAAC;IAEO,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,UAAkB,EAAE,OAAe;QAChE,kEAAkE;QAClE,oEAAoE;QACpE,qEAAqE;QACrE,sEAAsE;QACtE,6DAA6D;QAC7D,MAAM,aAAa,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;QAC5E,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;QACzD,MAAM,aAAa,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1E,CAAC;IAEO,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,GAAW,EAAE,OAAe;QAC3D,MAAM,OAAO,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAC3C,4EAA4E;QAC5E,4EAA4E;QAC5E,6EAA6E;QAC7E,MAAM,MAAM,GAAG;;;;;;0BAMG,GAAG;;;;;;;;;;sCAUS,OAAO;;;;;;;;;YASjC,CAAC;QAEL,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QACpE,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,oCAAoC,GAAG,EAAE,CAAC,CAAC;QAC/D,CAAC;IACL,CAAC;IAEO,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,GAAW,EAAE,OAAe;QAChE,MAAM,OAAO,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAC3C,mEAAmE;QACnE,iEAAiE;QACjE,mFAAmF;QACnF,iFAAiF;QACjF,+EAA+E;QAC/E,iEAAiE;QACjE,MAAM,MAAM,GAAG;;;;;;wBAMC,GAAG;;;;;;;;;;;;;;;iBAeV,OAAO;;;;;;;;;YASZ,CAAC;QAEL,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QACpE,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,sCAAsC,GAAG,EAAE,CAAC,CAAC;QACjE,CAAC;IACL,CAAC;CACJ;AA9HD,8BA8HC"}
1
+ {"version":3,"file":"TtyWriter.js","sourceRoot":"","sources":["../../src/terminal/TtyWriter.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-devkit/agent-manager",
3
- "version": "0.7.0",
3
+ "version": "0.9.0",
4
4
  "description": "Standalone agent detection and management utilities for AI DevKit",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",