MCPcopy Create free account
hub / github.com/diillson/chatcli / runGateway

Method runGateway

cli/gateway_command.go:240–298  ·  view source on GitHub ↗

runGateway builds the configured adapters and runs the messaging runner until ctx is canceled, backing conversations with the given hub store (nil = no cross-channel continuity).

(ctx context.Context, broker hub.Store)

Source from the content-addressed store, hash-verified

238// ctx is canceled, backing conversations with the given hub store (nil = no
239// cross-channel continuity).
240func (cli *ChatCLI) runGateway(ctx context.Context, broker hub.Store) error {
241 // Adopt the interactive session's live model before serving (the daemon is a
242 // separate process that snapshotted .env at boot). Per-message refresh in
243 // gatewayAgentFunc keeps it current after a /switch while the daemon runs.
244 cli.refreshGatewayModel()
245
246 adapters, err := gateway.BuildConfigured()
247 if err != nil {
248 return err
249 }
250 if len(adapters) == 0 {
251 return fmt.Errorf("%s", i18n.T("gateway.no_platforms"))
252 }
253 names := make([]string, 0, len(adapters))
254 for _, a := range adapters {
255 names = append(names, a.Name())
256 // Builders create adapters with a no-op logger (they run at import
257 // time). Inject the daemon's real logger now so adapter events and
258 // every external API request land in the log.
259 if la, ok := a.(gateway.LoggerAware); ok {
260 la.SetLogger(cli.logger)
261 }
262 }
263 // Startup line so gateway.log is never empty while the daemon is live —
264 // immediate proof the advertised log is the one actually being written.
265 cli.logger.Info("gateway started",
266 zap.Strings("platforms", names), zap.Int("adapters", len(adapters)))
267
268 sessions := newHubSessions(broker, cli.logger)
269 sessions.loadBindings(ctx)
270
271 // Voice support: build the transcription provider once (self-hosted-first,
272 // per CHATCLI_TRANSCRIPTION_*). Null when nothing is usable — voice
273 // messages then get a friendly "enable transcription" reply instead of
274 // being silently dropped.
275 transcriber := transcription.NewFromEnv(cli.logger)
276 if !transcription.IsNull(transcriber) {
277 cli.logger.Info("gateway: voice transcription enabled", zap.String("provider", transcriber.Name()))
278 logVoicePreflight(cli.logger, transcriber)
279 }
280 // Self-provisioning backends (embedded whisper) download their engine and
281 // model on first use; kick that off now, tied to the daemon lifetime, so
282 // the one-time fetch races startup instead of the first voice note.
283 if prov, ok := transcriber.(transcription.Provisioner); ok {
284 go func() {
285 if err := prov.EnsureReady(ctx); err != nil {
286 cli.logger.Warn("gateway: transcription engine provisioning failed", zap.Error(err))
287 }
288 }()
289 }
290
291 imgOutbox := newGatewayImageOutbox()
292 runner := gateway.NewRunner(adapters, cli.gatewayAgentFunc(sessions, transcriber, imgOutbox), cli.logger, 0)
293 runner.SetThinkingNotice(i18n.T("gateway.thinking"))
294 runner.SetVoicePrefs(gateway.SharedVoicePrefs())
295 cli.maybeEnableVoiceReplies(runner)
296 cli.maybeEnableImageReplies(runner, imgOutbox)
297 return runner.Run(ctx)

Callers 2

RunGatewayForegroundMethod · 0.95
RunGatewayWithBrokerMethod · 0.95

Calls 15

refreshGatewayModelMethod · 0.95
gatewayAgentFuncMethod · 0.95
SetThinkingNoticeMethod · 0.95
SetVoicePrefsMethod · 0.95
RunMethod · 0.95
BuildConfiguredFunction · 0.92
TFunction · 0.92
NewFromEnvFunction · 0.92
IsNullFunction · 0.92
NewRunnerFunction · 0.92

Tested by

no test coverage detected