feat(plugins): add document CRUD methods to Plugin SDK

Wire issue document list/get/upsert/delete operations through the
JSON-RPC protocol so plugins can manage issue documents with the same
capabilities available via the REST API.

Fixes #940
This commit is contained in:
Justin Miller
2026-03-16 15:53:50 -06:00
parent 3dc3347a58
commit 0d4dd50b35
7 changed files with 216 additions and 1 deletions

View File

@@ -16,6 +16,7 @@ import { agentService } from "./agents.js";
import { projectService } from "./projects.js";
import { issueService } from "./issues.js";
import { goalService } from "./goals.js";
import { documentService } from "./documents.js";
import { heartbeatService } from "./heartbeat.js";
import { subscribeCompanyLiveEvents } from "./live-events.js";
import { randomUUID } from "node:crypto";
@@ -450,6 +451,7 @@ export function buildHostServices(
const heartbeat = heartbeatService(db);
const projects = projectService(db);
const issues = issueService(db);
const documents = documentService(db);
const goals = goalService(db);
const activity = activityService(db);
const costs = costService(db);
@@ -796,6 +798,43 @@ export function buildHostServices(
},
},
issueDocuments: {
async list(params) {
const companyId = ensureCompanyId(params.companyId);
await ensurePluginAvailableForCompany(companyId);
requireInCompany("Issue", await issues.getById(params.issueId), companyId);
const rows = await documents.listIssueDocuments(params.issueId);
return rows as any;
},
async get(params) {
const companyId = ensureCompanyId(params.companyId);
await ensurePluginAvailableForCompany(companyId);
requireInCompany("Issue", await issues.getById(params.issueId), companyId);
const doc = await documents.getIssueDocumentByKey(params.issueId, params.key);
return (doc ?? null) as any;
},
async upsert(params) {
const companyId = ensureCompanyId(params.companyId);
await ensurePluginAvailableForCompany(companyId);
requireInCompany("Issue", await issues.getById(params.issueId), companyId);
const result = await documents.upsertIssueDocument({
issueId: params.issueId,
key: params.key,
body: params.body,
title: params.title ?? null,
format: params.format ?? "markdown",
changeSummary: params.changeSummary ?? null,
});
return result.document as any;
},
async delete(params) {
const companyId = ensureCompanyId(params.companyId);
await ensurePluginAvailableForCompany(companyId);
requireInCompany("Issue", await issues.getById(params.issueId), companyId);
await documents.deleteIssueDocument(params.issueId, params.key);
},
},
agents: {
async list(params) {
const companyId = ensureCompanyId(params.companyId);