2026-07-12 07:44:21 +08:00
#!/usr/bin/env node
2026-07-15 14:44:04 +00:00
import { access } from "node:fs/promises" ;
import { dirname , resolve } from "node:path" ;
import { fileURLToPath } from "node:url" ;
2026-07-12 08:45:35 +08:00
// Route production MCP before importing Incur. Incur owns registration helpers
2026-07-16 18:49:35 +08:00
// such as `mcp add`, while only dist/main.js may serve the stdio tool catalog.
2026-07-12 07:44:21 +08:00
const args = process . argv . slice ( 2 );
2026-07-12 23:42:20 +00:00
const { default : packageJson } = await import ( "../package.json" , {
with : { type : "json" },
});
process . env . REA_PACKAGE_VERSION = packageJson . version ;
2026-07-12 07:44:21 +08:00
const isMcpMode =
2026-07-14 20:33:23 +00:00
args . length === 1 && ( args [ 0 ] === "--mcp" || args [ 0 ] === "mcp" );
2026-07-22 20:38:26 +08:00
const isMcpDoctorMode = args [ 0 ] === "mcp" && args [ 1 ] === "doctor" ;
2026-07-15 14:44:04 +00:00
const packageRoot = resolve ( dirname ( fileURLToPath ( import . meta . url )), ".." );
const runtimeFiles = isMcpMode
? [ "dist/main.js" ]
2026-07-22 20:38:26 +08:00
: isMcpDoctorMode
? [ "dist/main.js" , "dist/mcpDoctor.js" ]
2026-10-08 03:44:51 +08:00
: [ "dist/cli.js" , "dist/cliOutput.js" , "dist/cli/streamedJsonOutput.js" ];
2026-07-12 07:44:21 +08:00
2026-08-10 02:59:52 +08:00
if ( ! ( await compiledRuntimeExists ( runtimeFiles ))) {
2026-07-15 14:44:04 +00:00
process . stderr . write (
2026-10-05 22:19:35 -07:00
`REA's compiled runtime is missing. Run \`npm ci && npm run build:cached\` in ${ packageRoot } to install dependencies and build REA, then restart it. If this is an installed package, reinstall rea-agents.\n` ,
2026-07-15 14:44:04 +00:00
);
process . exitCode = 1 ;
} else if ( isMcpMode ) {
2026-07-13 19:09:27 +00:00
const { runEntrypoint } = await import ( "../dist/main.js" );
await runEntrypoint ();
2026-07-22 20:38:26 +08:00
} else if ( isMcpDoctorMode ) {
const { runProductionMcpDoctorCli } = await import ( "../dist/mcpDoctor.js" );
const result = await runProductionMcpDoctorCli ( args . slice ( 2 ), {
dispatcherPath : fileURLToPath ( import . meta . url ),
packageRoot ,
});
process . stdout . write ( result . output );
process . exitCode = result . exitCode ;
2026-07-12 07:44:21 +08:00
} else {
const { createCli } = await import ( "../dist/cli.js" );
2026-10-08 03:44:51 +08:00
const { createStreamedCliJsonOutput } =
await import ( "../dist/cli/streamedJsonOutput.js" );
2026-07-22 20:38:26 +08:00
const {
renderCliOutputArgumentError ,
2026-10-07 02:51:10 -07:00
renderEmptyFilteredCliOutput ,
2026-07-22 20:38:26 +08:00
validateCliOutputArguments ,
} = await import ( "../dist/cliOutput.js" );
const outputArguments = validateCliOutputArguments ( args );
if ( ! outputArguments . ok ) {
process . stdout . write ( renderCliOutputArgumentError ( outputArguments ));
process . exitCode = 1 ;
} else {
2026-10-07 02:51:10 -07:00
let wroteOutput = false ;
2026-10-08 03:44:51 +08:00
const resultOutput = createStreamedCliJsonOutput ( args , process . stdout );
await createCli ( process . env , resultOutput ). serve ( args , {
2026-10-07 02:51:10 -07:00
stdout : ( output ) => {
2026-10-08 03:44:51 +08:00
if ( resultOutput ? . handled ) {
2026-10-09 19:55:09 +08:00
if ( resultOutput . failed ) process . stderr . write ( output );
2026-10-08 03:44:51 +08:00
return ;
}
2026-10-09 19:55:09 +08:00
if ( output . length > 0 ) wroteOutput = true ;
process . stdout . write ( output );
2026-10-07 02:51:10 -07:00
},
2026-07-22 20:38:26 +08:00
});
2026-10-08 03:44:51 +08:00
if ( ! wroteOutput && ! resultOutput ? . handled )
2026-10-07 02:51:10 -07:00
process . stdout . write ( renderEmptyFilteredCliOutput ( args ) ?? "" );
2026-07-22 20:38:26 +08:00
}
2026-07-12 07:44:21 +08:00
}
2026-07-15 14:44:04 +00:00
async function compiledRuntimeExists ( paths ) {
for ( const path of paths ) {
try {
await access ( resolve ( packageRoot , path ));
} catch ( cause ) {
if ( isMissing ( cause )) return false ;
throw cause ;
}
}
return true ;
}
function isMissing ( cause ) {
return (
typeof cause === "object" &&
cause !== null &&
"code" in cause &&
cause . code === "ENOENT"
);
}