@@ -26,6 +26,33 @@ export type CommandStatus =
2626 | "KILLED"
2727 | "RESTARTING" ;
2828
29+ /**
30+ * Error thrown when a command fails with a non-zero exit code.
31+ */
32+ export class CommandError extends Error {
33+ /**
34+ * The exit code returned by the command.
35+ */
36+ exitCode : number ;
37+
38+ /**
39+ * The output produced by the command.
40+ */
41+ output : string ;
42+
43+ constructor ( message : string , exitCode : number , output : string ) {
44+ super ( message ) ;
45+ this . name = "CommandError" ;
46+ this . exitCode = exitCode ;
47+ this . output = output ;
48+
49+ // Maintains proper stack trace for where our error was thrown (only available on V8)
50+ if ( Error . captureStackTrace ) {
51+ Error . captureStackTrace ( this , CommandError ) ;
52+ }
53+ }
54+ }
55+
2956const DEFAULT_SHELL_SIZE = { cols : 128 , rows : 24 } ;
3057
3158// This can not be called Commands due to React Native
@@ -242,6 +269,11 @@ export class Command {
242269 */
243270 #status: CommandStatus = "RUNNING" ;
244271
272+ /**
273+ * The exit code of the command, available after it completes.
274+ */
275+ private exitCode ?: number ;
276+
245277 get status ( ) : CommandStatus {
246278 return this . #status;
247279 }
@@ -276,6 +308,7 @@ export class Command {
276308 this . disposable . addDisposable (
277309 agentClient . shells . onShellExited ( ( { shellId, exitCode } ) => {
278310 if ( shellId === this . shell . shellId ) {
311+ this . exitCode = exitCode ;
279312 this . status = exitCode === 0 ? "FINISHED" : "ERROR" ;
280313 this . barrier . open ( ) ;
281314 }
@@ -390,7 +423,11 @@ export class Command {
390423 return cleaned ;
391424 }
392425
393- throw new Error ( `Command ERROR: ${ cleaned } ` ) ;
426+ throw new CommandError (
427+ `Command failed with exit code ${ this . exitCode ?? "unknown" } ` ,
428+ this . exitCode ?? 1 ,
429+ cleaned
430+ ) ;
394431 }
395432 ) ;
396433 }
0 commit comments