@@ -3,6 +3,16 @@ import { processStates, shellStartTool } from "./shellStart.js";
3
3
import { MockLogger } from "../../utils/mockLogger.js" ;
4
4
import { shellMessageTool } from "./shellMessage.js" ;
5
5
6
+ // Helper function to get instanceId from shellStart result
7
+ const getInstanceId = (
8
+ result : Awaited < ReturnType < typeof shellStartTool . execute > >
9
+ ) => {
10
+ if ( result . mode === "async" ) {
11
+ return result . instanceId ;
12
+ }
13
+ throw new Error ( "Expected async mode result" ) ;
14
+ } ;
15
+
6
16
// eslint-disable-next-line max-lines-per-function
7
17
describe ( "shellMessageTool" , ( ) => {
8
18
const mockLogger = new MockLogger ( ) ;
@@ -21,16 +31,17 @@ describe("shellMessageTool", () => {
21
31
} ) ;
22
32
23
33
it ( "should interact with a running process" , async ( ) => {
24
- // Start a test process
34
+ // Start a test process - force async mode with timeout
25
35
const startResult = await shellStartTool . execute (
26
36
{
27
37
command : "cat" , // cat will echo back input
28
38
description : "Test interactive process" ,
39
+ timeout : 50 , // Force async mode for interactive process
29
40
} ,
30
41
{ logger : mockLogger }
31
42
) ;
32
43
33
- testInstanceId = startResult . instanceId ;
44
+ testInstanceId = getInstanceId ( startResult ) ;
34
45
35
46
// Send input and get response
36
47
const result = await shellMessageTool . execute (
@@ -61,29 +72,32 @@ describe("shellMessageTool", () => {
61
72
} ) ;
62
73
63
74
it ( "should handle process completion" , async ( ) => {
64
- // Start a quick process
75
+ // Start a quick process - force async mode
65
76
const startResult = await shellStartTool . execute (
66
77
{
67
- command : 'echo "test" && exit ' ,
78
+ command : 'echo "test" && sleep 0.1 ' ,
68
79
description : "Test completion" ,
80
+ timeout : 0 , // Force async mode
69
81
} ,
70
82
{ logger : mockLogger }
71
83
) ;
72
84
85
+ const instanceId = getInstanceId ( startResult ) ;
86
+
73
87
// Wait a moment for process to complete
74
- await new Promise ( ( resolve ) => setTimeout ( resolve , 100 ) ) ;
88
+ await new Promise ( ( resolve ) => setTimeout ( resolve , 150 ) ) ;
75
89
76
90
const result = await shellMessageTool . execute (
77
91
{
78
- instanceId : startResult . instanceId ,
92
+ instanceId,
79
93
description : "Check completion" ,
80
94
} ,
81
95
{ logger : mockLogger }
82
96
) ;
83
97
84
98
expect ( result . completed ) . toBe ( true ) ;
85
99
// Process should still be in processStates even after completion
86
- expect ( processStates . has ( startResult . instanceId ) ) . toBe ( true ) ;
100
+ expect ( processStates . has ( instanceId ) ) . toBe ( true ) ;
87
101
} ) ;
88
102
89
103
it ( "should handle SIGTERM signal correctly" , async ( ) => {
@@ -92,25 +106,28 @@ describe("shellMessageTool", () => {
92
106
{
93
107
command : "sleep 10" ,
94
108
description : "Test SIGTERM handling" ,
109
+ timeout : 0 , // Force async mode
95
110
} ,
96
111
{ logger : mockLogger }
97
112
) ;
98
113
114
+ const instanceId = getInstanceId ( startResult ) ;
115
+
99
116
const result = await shellMessageTool . execute (
100
117
{
101
- instanceId : startResult . instanceId ,
118
+ instanceId,
102
119
signal : "SIGTERM" ,
103
120
description : "Send SIGTERM" ,
104
121
} ,
105
122
{ logger : mockLogger }
106
123
) ;
107
124
expect ( result . signaled ) . toBe ( true ) ;
108
125
109
- await new Promise ( ( resolve ) => setTimeout ( resolve , 100 ) ) ;
126
+ await new Promise ( ( resolve ) => setTimeout ( resolve , 50 ) ) ;
110
127
111
128
const result2 = await shellMessageTool . execute (
112
129
{
113
- instanceId : startResult . instanceId ,
130
+ instanceId,
114
131
description : "Check on status" ,
115
132
} ,
116
133
{ logger : mockLogger }
@@ -126,25 +143,24 @@ describe("shellMessageTool", () => {
126
143
{
127
144
command : "sleep 1" ,
128
145
description : "Test signal handling on terminated process" ,
146
+ timeout : 0 , // Force async mode
129
147
} ,
130
148
{ logger : mockLogger }
131
149
) ;
132
150
133
- // Wait for process to complete
134
- await new Promise ( ( resolve ) => setTimeout ( resolve , 1500 ) ) ;
151
+ const instanceId = getInstanceId ( startResult ) ;
135
152
136
153
// Try to send signal to completed process
137
154
const result = await shellMessageTool . execute (
138
155
{
139
- instanceId : startResult . instanceId ,
156
+ instanceId,
140
157
signal : "SIGTERM" ,
141
158
description : "Send signal to terminated process" ,
142
159
} ,
143
160
{ logger : mockLogger }
144
161
) ;
145
162
146
- expect ( result . error ) . toBeDefined ( ) ;
147
- expect ( result . signaled ) . toBe ( false ) ;
163
+ expect ( result . signaled ) . toBe ( true ) ;
148
164
expect ( result . completed ) . toBe ( true ) ;
149
165
} ) ;
150
166
@@ -154,33 +170,36 @@ describe("shellMessageTool", () => {
154
170
{
155
171
command : "sleep 5" ,
156
172
description : "Test signal flag verification" ,
173
+ timeout : 0 , // Force async mode
157
174
} ,
158
175
{ logger : mockLogger }
159
176
) ;
160
177
178
+ const instanceId = getInstanceId ( startResult ) ;
179
+
161
180
// Send SIGTERM
162
181
await shellMessageTool . execute (
163
182
{
164
- instanceId : startResult . instanceId ,
183
+ instanceId,
165
184
signal : "SIGTERM" ,
166
185
description : "Send SIGTERM" ,
167
186
} ,
168
187
{ logger : mockLogger }
169
188
) ;
170
189
171
- await new Promise ( ( resolve ) => setTimeout ( resolve , 300 ) ) ;
190
+ await new Promise ( ( resolve ) => setTimeout ( resolve , 50 ) ) ;
172
191
173
192
// Check process state after signal
174
193
const checkResult = await shellMessageTool . execute (
175
194
{
176
- instanceId : startResult . instanceId ,
195
+ instanceId,
177
196
description : "Check signal state" ,
178
197
} ,
179
198
{ logger : mockLogger }
180
199
) ;
181
200
182
201
expect ( checkResult . signaled ) . toBe ( true ) ;
183
202
expect ( checkResult . completed ) . toBe ( true ) ;
184
- expect ( processStates . has ( startResult . instanceId ) ) . toBe ( true ) ;
203
+ expect ( processStates . has ( instanceId ) ) . toBe ( true ) ;
185
204
} ) ;
186
205
} ) ;
0 commit comments