#pragma once #include #include #include #include #include #include #include "kompanion_mw_export.h" // Minimal model provider interface so tests can stub generation. class IModelProvider { public: virtual ~IModelProvider() = default; virtual QString generate(const QString &prompt, const QString &aspect) = 0; }; // Default Ollama-backed provider. Uses OLLAMA_BASE and simple /api/generate call. class OllamaModelProvider : public QObject, public IModelProvider { Q_OBJECT public: explicit OllamaModelProvider(QObject *parent=nullptr); QString generate(const QString &prompt, const QString &aspect) override; void setBaseUrl(const QString &base) { baseUrl_ = base; } void setDefaultModel(const QString &m) { defaultModel_ = m; } private: QString chooseModelForAspect(const QString &aspect) const; // simple heuristic QString baseUrl_; QString defaultModel_ = QStringLiteral("qwen2.5:7b"); QNetworkAccessManager nam_; }; // Simple stub provider used by tests; returns deterministic text. class StubModelProvider : public IModelProvider { public: explicit StubModelProvider(QString canned) : canned_(std::move(canned)) {} QString generate(const QString &prompt, const QString &aspect) override { Q_UNUSED(prompt); Q_UNUSED(aspect); return canned_; } private: QString canned_; }; // Orchestrator: replicates runtime/kom_runner.py behaviors in C++. // - Watches a JSONL tasks file under XDG_STATE_HOME/kompanion // - Processes tasks like {"type":"journal.from_prompt", "prompt":"...", "aspect":"companion"} // - Appends to journal (/journal/YYYY-MM-DD.md) and to a simple ledger JSONL class KOMPANION_MW_EXPORT Orchestrator : public QObject { Q_OBJECT public: explicit Orchestrator(QObject *parent=nullptr); // Injectable model provider (Ollama by default). Ownership left to caller. void setModelProvider(IModelProvider *prov) { model_ = prov; } // Directories resolved from XDG_* on start(); overridable for tests. void setStateDir(const QDir &dir) { stateDir_ = dir; } void setConfigDir(const QDir &dir) { configDir_ = dir; } // Poll loop control. void start(int intervalMs = 3000); void stop(); // One-shot tick (public for tests). void processPendingTasks(); signals: void taskProcessed(const QString &kind); private: void ensureResolvedDirs(); void continuityHandshakeOnce(); void ledgerAppend(const QJsonObject &evt); void journalAppend(const QString &line); // Also emits ledger entry QString nowUtc() const; // Task handlers void handleJournalFromPrompt(const QJsonObject &obj); // Helpers QString tasksPath() const { return stateDir_.filePath("tasks.jsonl"); } QString journalDirPath() const { return stateDir_.filePath("journal"); } QString ledgerPath() const { return stateDir_.filePath("trust_ledger.jsonl"); } QDir stateDir_; QDir configDir_; QTimer timer_; bool continuityDone_ = false; IModelProvider *model_ = nullptr; // not owned };