Address PR review feedback

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-04-30 11:45:18 -05:00
1 parent 8af1f418ac
commit 2d8e615efd
6 files changed
+20 -8

No files matched your search

+2
View File
@@ -670,6 +670,7 @@ export {
requestConfirmationResultSchema,
createIssueThreadInteractionSchema,
acceptIssueThreadInteractionSchema,
cancelIssueThreadInteractionSchema,
rejectIssueThreadInteractionSchema,
respondIssueThreadInteractionSchema,
linkIssueApprovalSchema,
@@ -704,6 +705,7 @@ export {
type AddIssueComment,
type CreateIssueThreadInteraction,
type AcceptIssueThreadInteraction,
type CancelIssueThreadInteraction,
type RejectIssueThreadInteraction,
type RespondIssueThreadInteraction,
type LinkIssueApproval,
+2
View File
@@ -176,6 +176,7 @@ export {
requestConfirmationResultSchema,
createIssueThreadInteractionSchema,
acceptIssueThreadInteractionSchema,
cancelIssueThreadInteractionSchema,
rejectIssueThreadInteractionSchema,
respondIssueThreadInteractionSchema,
linkIssueApprovalSchema,
@@ -193,6 +194,7 @@ export {
type AddIssueComment,
type CreateIssueThreadInteraction,
type AcceptIssueThreadInteraction,
type CancelIssueThreadInteraction,
type RejectIssueThreadInteraction,
type RespondIssueThreadInteraction,
type LinkIssueApproval,
+5
View File
@@ -448,6 +448,11 @@ export const rejectIssueThreadInteractionSchema = z.object({
});
export type RejectIssueThreadInteraction = z.infer<typeof rejectIssueThreadInteractionSchema>;
export const cancelIssueThreadInteractionSchema = z.object({
reason: z.string().trim().max(4000).optional(),
});
export type CancelIssueThreadInteraction = z.infer<typeof cancelIssueThreadInteractionSchema>;
export const respondIssueThreadInteractionSchema = z.object({
answers: z.array(askUserQuestionsAnswerSchema).max(20),
summaryMarkdown: multilineTextSchema.pipe(z.string().max(20000)).nullable().optional(),
+2 -1
View File
@@ -7,6 +7,7 @@ import { issueExecutionDecisions } from "@paperclipai/db";
import {
addIssueCommentSchema,
acceptIssueThreadInteractionSchema,
cancelIssueThreadInteractionSchema,
createIssueAttachmentMetadataSchema,
createIssueThreadInteractionSchema,
createIssueWorkProductSchema,
@@ -3184,7 +3185,7 @@ export function issueRoutes(
router.post(
"/issues/:id/interactions/:interactionId/cancel",
validate(rejectIssueThreadInteractionSchema),
validate(cancelIssueThreadInteractionSchema),
async (req, res) => {
const id = req.params.id as string;
const interactionId = req.params.interactionId as string;
@@ -13,6 +13,7 @@ import type {
AcceptIssueThreadInteraction,
AskUserQuestionsAnswer,
AskUserQuestionsInteraction,
CancelIssueThreadInteraction,
CreateIssueThreadInteraction,
IssueThreadInteraction,
RequestConfirmationInteraction,
@@ -26,6 +27,7 @@ import {
acceptIssueThreadInteractionSchema,
askUserQuestionsPayloadSchema,
askUserQuestionsResultSchema,
cancelIssueThreadInteractionSchema,
createIssueThreadInteractionSchema,
rejectIssueThreadInteractionSchema,
requestConfirmationPayloadSchema,
@@ -1152,10 +1154,10 @@ export function issueThreadInteractionService(db: Db) {
cancelQuestions: async (
issue: { id: string; companyId: string },
interactionId: string,
input: RejectIssueThreadInteraction,
input: CancelIssueThreadInteraction,
actor: InteractionActor,
) => {
const data = rejectIssueThreadInteractionSchema.parse(input);
const data = cancelIssueThreadInteractionSchema.parse(input);
const current = await db
.select()
.from(issueThreadInteractions)
+5 -5
View File
@@ -1025,7 +1025,7 @@ function IssueDetailActivityTab({
{hasIssueTreeCost && issueTreeCostSummary ? (
<div className="flex flex-wrap gap-3">
<span className="font-medium text-foreground">
Including sub-issues ${(issueTreeCostSummary.costCents / 100).toLocaleString(undefined, {
Including sub-issues {(issueTreeCostSummary.costCents / 100).toLocaleString(undefined, {
style: "currency",
currency: "USD",
minimumFractionDigits: 4,
@@ -1688,11 +1688,11 @@ export function IssueDetail() {
},
});
const pauseIssueWorkRun = useMutation({
mutationFn: async (runId: string) => {
mutationFn: async ({ runId, scope }: { runId: string; scope: "leaf" | "subtree" }) => {
const created = await issuesApi.createTreeHold(issueId!, {
mode: "pause",
reason: "Paused from active run controls.",
releasePolicy: { strategy: "manual", note: treeControlScope === "leaf" ? "leaf_pause" : "full_pause" },
releasePolicy: { strategy: "manual", note: scope === "leaf" ? "leaf_pause" : "full_pause" },
metadata: { source: "issue_active_run_control", runId },
});
return created;
@@ -3654,11 +3654,11 @@ export function IssueDetail() {
onAttachImage={handleCommentAttachImage}
onInterruptQueued={handleInterruptQueuedRun}
onPauseWorkRun={canManageTreeControl
? (runId) => pauseIssueWorkRun.mutateAsync(runId).then(() => undefined)
? (runId) => pauseIssueWorkRun.mutateAsync({ runId, scope: treeControlScope }).then(() => undefined)
: undefined}
onCancelQueued={handleCancelQueuedComment}
interruptingQueuedRunId={interruptQueuedComment.isPending ? interruptQueuedComment.variables ?? null : null}
pausingWorkRunId={pauseIssueWorkRun.isPending ? pauseIssueWorkRun.variables ?? null : null}
pausingWorkRunId={pauseIssueWorkRun.isPending ? pauseIssueWorkRun.variables?.runId ?? null : null}
onImageClick={handleChatImageClick}
onAcceptInteraction={handleAcceptInteraction}
onRejectInteraction={handleRejectInteraction}