#pragma once #include #include #include #include #include #include namespace ZShell::llm { class LlmTool : public QObject { Q_OBJECT public: explicit LlmTool(QObject* parent = nullptr); ~LlmTool() override; [[nodiscard]] virtual QString name() const = 0; [[nodiscard]] virtual QString description() const = 0; [[nodiscard]] virtual QJsonObject parameters() const = 0; // toolCallId identifies the call within the conversation; tools may use // it to name files they write for later retrieval. virtual void execute( const QString& toolCallId, const QJsonObject& args, std::function done) = 0; virtual void cancel(); [[nodiscard]] QJsonObject specification() const; // The endpoint's context size in tokens (0 = unknown). Set by LlmClient. [[nodiscard]] int contextSize() const { return m_contextSize; } void setContextSize(int value); // Rough cap, in characters, for tool output embedded in a tool result // message. Scales with the context size so a single result cannot // consume the whole window. [[nodiscard]] int inlineBudgetChars() const; // ~4 characters per token; a deliberately coarse estimate used for // budgeting (never for exact accounting). static constexpr int CharsPerToken = 4; // Inline budget when the context size is unknown. static constexpr int DefaultInlineChars = 64 * 1024; protected: int m_contextSize = 0; }; class ToolRegistry : public QObject { Q_OBJECT Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged) public: explicit ToolRegistry(QObject* parent = nullptr); [[nodiscard]] bool enabled() const { return m_enabled; } void setEnabled(bool value); void registerTool(LlmTool* tool); [[nodiscard]] LlmTool* tool(const QString& name) const; [[nodiscard]] QJsonArray specifications() const; void cancelAll(); // Propagated to every registered tool, including later ones. void setContextSize(int value); Q_SIGNALS: void enabledChanged(); private: bool m_enabled = true; int m_contextSize = 0; QList m_tools; }; } // namespace ZShell::llm