Add workspace operation tracking and fix project properties JSX
This commit is contained in:
@@ -29,6 +29,7 @@ import {
|
||||
issueService,
|
||||
logActivity,
|
||||
secretService,
|
||||
workspaceOperationService,
|
||||
} from "../services/index.js";
|
||||
import { conflict, forbidden, notFound, unprocessable } from "../errors.js";
|
||||
import { assertBoard, assertCompanyAccess, getActorInfo } from "./authz.js";
|
||||
@@ -62,6 +63,7 @@ export function agentRoutes(db: Db) {
|
||||
const heartbeat = heartbeatService(db);
|
||||
const issueApprovalsSvc = issueApprovalService(db);
|
||||
const secretsSvc = secretService(db);
|
||||
const workspaceOperations = workspaceOperationService(db);
|
||||
const strictSecretsMode = process.env.PAPERCLIP_SECRETS_STRICT_MODE === "true";
|
||||
|
||||
function canCreateAgents(agent: { role: string; permissions: Record<string, unknown> | null | undefined }) {
|
||||
@@ -1560,6 +1562,40 @@ export function agentRoutes(db: Db) {
|
||||
res.json(result);
|
||||
});
|
||||
|
||||
router.get("/heartbeat-runs/:runId/workspace-operations", async (req, res) => {
|
||||
const runId = req.params.runId as string;
|
||||
const run = await heartbeat.getRun(runId);
|
||||
if (!run) {
|
||||
res.status(404).json({ error: "Heartbeat run not found" });
|
||||
return;
|
||||
}
|
||||
assertCompanyAccess(req, run.companyId);
|
||||
|
||||
const context = asRecord(run.contextSnapshot);
|
||||
const executionWorkspaceId = asNonEmptyString(context?.executionWorkspaceId);
|
||||
const operations = await workspaceOperations.listForRun(runId, executionWorkspaceId);
|
||||
res.json(redactCurrentUserValue(operations));
|
||||
});
|
||||
|
||||
router.get("/workspace-operations/:operationId/log", async (req, res) => {
|
||||
const operationId = req.params.operationId as string;
|
||||
const operation = await workspaceOperations.getById(operationId);
|
||||
if (!operation) {
|
||||
res.status(404).json({ error: "Workspace operation not found" });
|
||||
return;
|
||||
}
|
||||
assertCompanyAccess(req, operation.companyId);
|
||||
|
||||
const offset = Number(req.query.offset ?? 0);
|
||||
const limitBytes = Number(req.query.limitBytes ?? 256000);
|
||||
const result = await workspaceOperations.readLog(operationId, {
|
||||
offset: Number.isFinite(offset) ? offset : 0,
|
||||
limitBytes: Number.isFinite(limitBytes) ? limitBytes : 256000,
|
||||
});
|
||||
|
||||
res.json(result);
|
||||
});
|
||||
|
||||
router.get("/issues/:issueId/live-runs", async (req, res) => {
|
||||
const rawId = req.params.issueId as string;
|
||||
const issueSvc = issueService(db);
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { Db } from "@paperclipai/db";
|
||||
import { issues, projects, projectWorkspaces } from "@paperclipai/db";
|
||||
import { updateExecutionWorkspaceSchema } from "@paperclipai/shared";
|
||||
import { validate } from "../middleware/validate.js";
|
||||
import { executionWorkspaceService, logActivity } from "../services/index.js";
|
||||
import { executionWorkspaceService, logActivity, workspaceOperationService } from "../services/index.js";
|
||||
import { parseProjectExecutionWorkspacePolicy } from "../services/execution-workspace-policy.js";
|
||||
import {
|
||||
cleanupExecutionWorkspaceArtifacts,
|
||||
@@ -17,6 +17,7 @@ const TERMINAL_ISSUE_STATUSES = new Set(["done", "cancelled"]);
|
||||
export function executionWorkspaceRoutes(db: Db) {
|
||||
const router = Router();
|
||||
const svc = executionWorkspaceService(db);
|
||||
const workspaceOperationsSvc = workspaceOperationService(db);
|
||||
|
||||
router.get("/companies/:companyId/execution-workspaces", async (req, res) => {
|
||||
const companyId = req.params.companyId as string;
|
||||
@@ -121,6 +122,10 @@ export function executionWorkspaceRoutes(db: Db) {
|
||||
workspace: existing,
|
||||
projectWorkspace,
|
||||
teardownCommand: projectPolicy?.workspaceStrategy?.teardownCommand ?? null,
|
||||
recorder: workspaceOperationsSvc.createRecorder({
|
||||
companyId: existing.companyId,
|
||||
executionWorkspaceId: existing.id,
|
||||
}),
|
||||
});
|
||||
cleanupWarnings = cleanupResult.warnings;
|
||||
const cleanupPatch: Record<string, unknown> = {
|
||||
|
||||
Reference in New Issue
Block a user