@@ -28,6 +28,7 @@ import (
2828 "neo-code/internal/tools"
2929 "neo-code/internal/tools/mcp"
3030 "neo-code/internal/tui"
31+ "neo-code/internal/tui/services"
3132)
3233
3334func TestNewProgram (t * testing.T ) {
@@ -1439,11 +1440,183 @@ func TestNewMemoExtractorAdapterPropagatesFactoryBuildError(t *testing.T) {
14391440 }
14401441}
14411442
1443+ func TestResolveBootstrapRuntimeMode (t * testing.T ) {
1444+ mode , err := resolveBootstrapRuntimeMode ("" )
1445+ if err != nil {
1446+ t .Fatalf ("resolveBootstrapRuntimeMode() error = %v" , err )
1447+ }
1448+ if mode != RuntimeModeLocal {
1449+ t .Fatalf ("expected default mode %q, got %q" , RuntimeModeLocal , mode )
1450+ }
1451+
1452+ mode , err = resolveBootstrapRuntimeMode (" GATEWAY " )
1453+ if err != nil {
1454+ t .Fatalf ("resolveBootstrapRuntimeMode() error = %v" , err )
1455+ }
1456+ if mode != RuntimeModeGateway {
1457+ t .Fatalf ("expected gateway mode %q, got %q" , RuntimeModeGateway , mode )
1458+ }
1459+
1460+ _ , err = resolveBootstrapRuntimeMode ("invalid" )
1461+ if err == nil {
1462+ t .Fatalf ("expected invalid runtime mode error" )
1463+ }
1464+ }
1465+
1466+ func TestBuildRuntimeRejectsInvalidRuntimeMode (t * testing.T ) {
1467+ t .Parallel ()
1468+
1469+ _ , err := BuildRuntime (context .Background (), BootstrapOptions {RuntimeMode : "invalid" })
1470+ if err == nil {
1471+ t .Fatalf ("expected invalid runtime mode error" )
1472+ }
1473+ }
1474+
1475+ func TestDefaultNewRemoteRuntimeAdapterReturnsInitError (t * testing.T ) {
1476+ home := t .TempDir ()
1477+ t .Setenv ("HOME" , home )
1478+ t .Setenv ("USERPROFILE" , home )
1479+
1480+ _ , err := defaultNewRemoteRuntimeAdapter (services.RemoteRuntimeAdapterOptions {
1481+ ListenAddress : "ipc://127.0.0.1" ,
1482+ TokenFile : home + "/missing-token.json" ,
1483+ })
1484+ if err == nil {
1485+ t .Fatalf ("expected defaultNewRemoteRuntimeAdapter to fail when token is missing" )
1486+ }
1487+ }
1488+
1489+ func TestBuildRuntimeGatewayModeUsesRemoteAdapter (t * testing.T ) {
1490+ disableBuiltinProviderAPIKeys (t )
1491+
1492+ home := t .TempDir ()
1493+ t .Setenv ("HOME" , home )
1494+ t .Setenv ("USERPROFILE" , home )
1495+
1496+ originalFactory := newRemoteRuntimeAdapter
1497+ t .Cleanup (func () { newRemoteRuntimeAdapter = originalFactory })
1498+
1499+ stubRuntime := & stubRemoteRuntimeForBootstrap {
1500+ events : make (chan agentruntime.RuntimeEvent ),
1501+ }
1502+ newRemoteRuntimeAdapter = func (_ services.RemoteRuntimeAdapterOptions ) (runtimeWithClose , error ) {
1503+ return stubRuntime , nil
1504+ }
1505+
1506+ bundle , err := BuildRuntime (context .Background (), BootstrapOptions {RuntimeMode : RuntimeModeGateway })
1507+ if err != nil {
1508+ t .Fatalf ("BuildRuntime() error = %v" , err )
1509+ }
1510+ if bundle .Runtime != stubRuntime {
1511+ t .Fatalf ("expected gateway runtime adapter to be wired" )
1512+ }
1513+ if bundle .Close == nil {
1514+ t .Fatalf ("expected non-nil close function" )
1515+ }
1516+ if err := bundle .Close (); err != nil {
1517+ t .Fatalf ("bundle.Close() error = %v" , err )
1518+ }
1519+ if ! stubRuntime .closed {
1520+ t .Fatalf ("expected remote runtime close to be called" )
1521+ }
1522+ }
1523+
1524+ func TestBuildRuntimeGatewayModeFailsFastWhenAdapterInitFails (t * testing.T ) {
1525+ disableBuiltinProviderAPIKeys (t )
1526+
1527+ home := t .TempDir ()
1528+ t .Setenv ("HOME" , home )
1529+ t .Setenv ("USERPROFILE" , home )
1530+
1531+ originalFactory := newRemoteRuntimeAdapter
1532+ t .Cleanup (func () { newRemoteRuntimeAdapter = originalFactory })
1533+
1534+ newRemoteRuntimeAdapter = func (_ services.RemoteRuntimeAdapterOptions ) (runtimeWithClose , error ) {
1535+ return nil , errors .New ("gateway connect failed" )
1536+ }
1537+
1538+ _ , err := BuildRuntime (context .Background (), BootstrapOptions {RuntimeMode : RuntimeModeGateway })
1539+ if err == nil {
1540+ t .Fatalf ("expected gateway mode fail-fast error" )
1541+ }
1542+ if ! strings .Contains (err .Error (), "gateway connect failed" ) {
1543+ t .Fatalf ("unexpected error: %v" , err )
1544+ }
1545+ }
1546+
14421547type stubToolForBootstrap struct {
14431548 name string
14441549 content string
14451550}
14461551
1552+ type stubRemoteRuntimeForBootstrap struct {
1553+ closed bool
1554+ events chan agentruntime.RuntimeEvent
1555+ }
1556+
1557+ func (s * stubRemoteRuntimeForBootstrap ) Submit (context.Context , agentruntime.PrepareInput ) error {
1558+ return nil
1559+ }
1560+
1561+ func (s * stubRemoteRuntimeForBootstrap ) PrepareUserInput (
1562+ context.Context ,
1563+ agentruntime.PrepareInput ,
1564+ ) (agentruntime.UserInput , error ) {
1565+ return agentruntime.UserInput {}, nil
1566+ }
1567+
1568+ func (s * stubRemoteRuntimeForBootstrap ) Run (context.Context , agentruntime.UserInput ) error {
1569+ return nil
1570+ }
1571+
1572+ func (s * stubRemoteRuntimeForBootstrap ) Compact (context.Context , agentruntime.CompactInput ) (agentruntime.CompactResult , error ) {
1573+ return agentruntime.CompactResult {}, nil
1574+ }
1575+
1576+ func (s * stubRemoteRuntimeForBootstrap ) ExecuteSystemTool (
1577+ context.Context ,
1578+ agentruntime.SystemToolInput ,
1579+ ) (tools.ToolResult , error ) {
1580+ return tools.ToolResult {}, nil
1581+ }
1582+
1583+ func (s * stubRemoteRuntimeForBootstrap ) ResolvePermission (context.Context , agentruntime.PermissionResolutionInput ) error {
1584+ return nil
1585+ }
1586+
1587+ func (s * stubRemoteRuntimeForBootstrap ) CancelActiveRun () bool {
1588+ return false
1589+ }
1590+
1591+ func (s * stubRemoteRuntimeForBootstrap ) Events () <- chan agentruntime.RuntimeEvent {
1592+ return s .events
1593+ }
1594+
1595+ func (s * stubRemoteRuntimeForBootstrap ) ListSessions (context.Context ) ([]agentsession.Summary , error ) {
1596+ return nil , nil
1597+ }
1598+
1599+ func (s * stubRemoteRuntimeForBootstrap ) LoadSession (context.Context , string ) (agentsession.Session , error ) {
1600+ return agentsession.Session {}, nil
1601+ }
1602+
1603+ func (s * stubRemoteRuntimeForBootstrap ) ActivateSessionSkill (context.Context , string , string ) error {
1604+ return nil
1605+ }
1606+
1607+ func (s * stubRemoteRuntimeForBootstrap ) DeactivateSessionSkill (context.Context , string , string ) error {
1608+ return nil
1609+ }
1610+
1611+ func (s * stubRemoteRuntimeForBootstrap ) ListSessionSkills (context.Context , string ) ([]agentruntime.SessionSkillState , error ) {
1612+ return nil , nil
1613+ }
1614+
1615+ func (s * stubRemoteRuntimeForBootstrap ) Close () error {
1616+ s .closed = true
1617+ return nil
1618+ }
1619+
14471620func (s stubToolForBootstrap ) Name () string { return s .name }
14481621func (s stubToolForBootstrap ) Description () string { return "stub" }
14491622func (s stubToolForBootstrap ) Schema () map [string ]any { return map [string ]any {"type" : "object" } }
0 commit comments