NewChatCLI cria uma nova instância de ChatCLI
(ctx context.Context, manager manager.LLMManager, logger *zap.Logger)
| 409 | |
| 410 | // NewChatCLI cria uma nova instância de ChatCLI |
| 411 | func NewChatCLI(ctx context.Context, manager manager.LLMManager, logger *zap.Logger) (*ChatCLI, error) { |
| 412 | cli := &ChatCLI{ |
| 413 | manager: manager, |
| 414 | logger: logger, |
| 415 | history: make([]models.Message, 0), |
| 416 | historyCompactor: NewHistoryCompactor(logger), |
| 417 | historyManager: NewHistoryManager(logger), |
| 418 | animation: NewAnimationManager(), |
| 419 | interactionState: StateNormal, |
| 420 | processingDone: make(chan struct{}), |
| 421 | executionProfile: ProfileNormal, |
| 422 | } |
| 423 | |
| 424 | // Seed the session-lifetime context so interactive handlers can derive |
| 425 | // deadlines from it before Start refreshes it. Every caller passes a |
| 426 | // non-nil context (a real request ctx or context.Background()). |
| 427 | cli.sessionCtx = ctx |
| 428 | |
| 429 | // Wire the security prompt's package-level input guard with our zap |
| 430 | // logger so dropped typeahead is logged at DEBUG. Calling this here |
| 431 | // (before any tool can fire a confirmation) guarantees every prompt in |
| 432 | // the process lifetime uses a logger-aware guard. |
| 433 | coder.SetSecurityPromptLogger(logger) |
| 434 | |
| 435 | // Initialize the per-session scratch workspace. This makes |
| 436 | // $CHATCLI_AGENT_TMPDIR available to every tool and registers the |
| 437 | // scratch + tool-results dirs with the engine / read validator so the |
| 438 | // agent can read and write inside them. |
| 439 | if _, err := agent.InitSessionWorkspace(logger); err != nil { |
| 440 | // Fatal in the sense of "the sandbox is broken" — but we only log |
| 441 | // and continue. The agent falls back to the old /tmp/chatcli-* |
| 442 | // shared dirs without read-on-demand access, which is the legacy |
| 443 | // behavior. |
| 444 | logger.Warn("Failed to initialize session workspace — large tool outputs will not be readable", zap.Error(err)) |
| 445 | } |
| 446 | |
| 447 | pluginMgr, err := plugins.NewManager(logger) |
| 448 | if err != nil { |
| 449 | // Logamos o erro, mas a aplicação continua. O pluginManager será um objeto válido, mas vazio. |
| 450 | logger.Error("Falha crítica ao inicializar o gerenciador de plugins, plugins estarão desabilitados", zap.Error(err)) |
| 451 | } |
| 452 | cli.pluginManager = pluginMgr |
| 453 | if pluginMgr != nil { |
| 454 | pluginMgr.RegisterBuiltinPlugin(plugins.NewBuiltinCoderPlugin()) |
| 455 | pluginMgr.RegisterBuiltinPlugin(plugins.NewBuiltinWebFetchPlugin()) |
| 456 | pluginMgr.RegisterBuiltinPlugin(plugins.NewBuiltinWebSearchPlugin()) |
| 457 | pluginMgr.RegisterBuiltinPlugin(plugins.NewBuiltinSchedulerPlugin()) |
| 458 | pluginMgr.RegisterBuiltinPlugin(plugins.NewBuiltinParkPlugin()) |
| 459 | pluginMgr.RegisterBuiltinPlugin(plugins.NewBuiltinAskPlugin()) |
| 460 | // @send — proactive outbound messaging through the gateway |
| 461 | // platform adapters (Telegram/WhatsApp/Discord/Slack/webhook). |
| 462 | // The adapter is wired below; gateway.BuildConfigured() reads the |
| 463 | // live platform credentials each call, so this works whether or |
| 464 | // not the gateway daemon is running. |
| 465 | pluginMgr.RegisterBuiltinPlugin(plugins.NewBuiltinSendPlugin()) |
| 466 | // @moa — Mixture-of-Agents: fan a prompt out to several models and |
| 467 | // synthesize one best answer. Wired below to the LLM manager. |
| 468 | pluginMgr.RegisterBuiltinPlugin(plugins.NewBuiltinMoaPlugin()) |
no test coverage detected