@@ -19,6 +19,7 @@ import (
1919 "neo-code/internal/config"
2020 "neo-code/internal/gateway"
2121 gatewayauth "neo-code/internal/gateway/auth"
22+ agentruntime "neo-code/internal/runtime"
2223 "neo-code/internal/webassets"
2324)
2425
@@ -238,6 +239,15 @@ func startGatewayServer(ctx context.Context, options gatewayCommandOptions, stat
238239 Metrics : metrics ,
239240 })
240241
242+ runnerRegistry := gateway .NewRunnerRegistry (logger )
243+ runnerToolManager := gateway .NewRunnerToolManager (
244+ runnerRegistry ,
245+ relay ,
246+ nil , // capability signer: nil allows execution without token for MVP
247+ 30 * time .Second ,
248+ logger ,
249+ )
250+
241251 runtimePort , closeRuntimePort , err := buildGatewayRuntimePort (signalContext , options .Workdir )
242252 if err != nil {
243253 return fmt .Errorf ("initialize gateway runtime: %w" , err )
@@ -248,6 +258,9 @@ func startGatewayServer(ctx context.Context, options gatewayCommandOptions, stat
248258 }
249259 }()
250260
261+ // 注入 Runner 工具分发器到 runtime,使 ReAct 循环中的工具调用可以通过 runner 执行
262+ injectRunnerDispatcherIntoRuntime (runtimePort , runnerToolManager )
263+
251264 idleCloser := newGatewayIdleShutdownController (logger , cancelRuntime )
252265 defer idleCloser .close ()
253266
@@ -294,6 +307,8 @@ func startGatewayServer(ctx context.Context, options gatewayCommandOptions, stat
294307 AllowedOrigins : gatewayConfig .Security .AllowOrigins ,
295308 StaticFileDir : staticFileDir ,
296309 StaticFileFS : staticFileFS ,
310+ RunnerRegistry : runnerRegistry ,
311+ RunnerToolManager : runnerToolManager ,
297312 ConnectionCountChanged : func (active int ) {
298313 idleCloser .observe (active )
299314 },
@@ -479,6 +494,33 @@ func defaultNewGatewayNetworkServer(options gateway.NetworkServerOptions) (gatew
479494 return gateway .NewNetworkServer (options )
480495}
481496
497+ // injectRunnerDispatcherIntoRuntime 将 RunnerToolManager 注入到多工作区 runtime 的所有 bundle 中,
498+ // 使 ReAct 循环中的工具调用可以通过 runner 远程执行。
499+ func injectRunnerDispatcherIntoRuntime (runtimePort gateway.RuntimePort , runnerToolManager * gateway.RunnerToolManager ) {
500+ if runtimePort == nil || runnerToolManager == nil {
501+ return
502+ }
503+
504+ mw , ok := runtimePort .(* gateway.MultiWorkspaceRuntime )
505+ if ! ok {
506+ return
507+ }
508+
509+ dispatcher := gateway .NewRunnerToolDispatcher (runnerToolManager )
510+
511+ mw .InjectRunnerDispatcher (func (port gateway.RuntimePort ) {
512+ bridge , ok := port .(* gatewayRuntimePortBridge )
513+ if ! ok {
514+ return
515+ }
516+ svc , ok := bridge .runtime .(* agentruntime.Service )
517+ if ! ok {
518+ return
519+ }
520+ svc .SetRunnerToolDispatcher (dispatcher )
521+ })
522+ }
523+
482524// encodeJSONLine 将对象编码为单行 JSON,并写入目标输出流。
483525func encodeJSONLine (writer io.Writer , payload any ) error {
484526 encoder := json .NewEncoder (writer )
0 commit comments