#include "workspace.hpp" #include "session.hpp" #include #include #include #include #include #include namespace ZShell::llm { Workspace::Workspace(ChatSession* session, QObject* parent) : QObject(parent), m_session(session) { m_path = pathFor(session->id()); } QString Workspace::pathFor(const QString& sessionId) { const QString state = QStandardPaths::writableLocation(QStandardPaths::GenericStateLocation); return state + QStringLiteral("/zshell/sandboxes/") + sessionId; } bool Workspace::ensure() { return QDir().mkpath(m_path); } QList Workspace::importFiles( const QStringList& paths, QString& error) { error.clear(); if (!ensure()) { error = QStringLiteral("Could not create the sandbox directory"); return {}; } QMimeDatabase mimeDatabase; QList result; for (const QString& rawPath : paths) { const QFileInfo info(rawPath); if (!info.exists() || !info.isFile()) { qWarning() << "Workspace: skipping" << rawPath << ": file not found or not a file"; error = QStringLiteral("File not found: %1").arg(info.fileName()); continue; } const QString mimeType = mimeDatabase.mimeTypeForFile(info).name(); const bool isImage = mimeType.startsWith(QLatin1String("image/"), Qt::CaseInsensitive); const qint64 cap = isImage ? MaxImageBytes : MaxFileBytes; if (info.size() > cap) { qWarning() << "Workspace: skipping" << rawPath << ": too large (" << info.size() << "bytes, cap" << cap << ")"; error = QStringLiteral("File too large: %1").arg(info.fileName()); continue; } QString destination = m_path + QLatin1Char('/') + info.fileName(); int suffix = 1; while (QFile::exists(destination)) { const QString extension = info.suffix().isEmpty() ? QString() : QLatin1Char('.') + info.suffix(); destination = m_path + QLatin1Char('/') + info.completeBaseName() + QStringLiteral("_%1%2").arg(suffix).arg(extension); ++suffix; } if (!QFile::copy(info.absoluteFilePath(), destination)) { qWarning() << "Workspace: skipping" << rawPath << ": copy to" << destination << "failed"; error = QStringLiteral("Could not copy file: %1").arg(info.fileName()); continue; } result.append(new Attachment( info.fileName(), destination, isImage ? Attachment::Kind::Image : Attachment::Kind::File, mimeType, info.size(), m_session)); } return result; } } // namespace ZShell::llm