Spaces:
Paused
Paused
| import type { | |
| Approval, | |
| DocumentRevision, | |
| FeedbackTargetType, | |
| FeedbackTrace, | |
| FeedbackVote, | |
| Issue, | |
| IssueAttachment, | |
| IssueComment, | |
| IssueDocument, | |
| IssueLabel, | |
| IssueWorkProduct, | |
| UpsertIssueDocument, | |
| } from "@paperclipai/shared"; | |
| import { api } from "./client"; | |
| export type IssueUpdateResponse = Issue & { | |
| comment?: IssueComment | null; | |
| }; | |
| export const issuesApi = { | |
| list: ( | |
| companyId: string, | |
| filters?: { | |
| status?: string; | |
| projectId?: string; | |
| assigneeAgentId?: string; | |
| participantAgentId?: string; | |
| assigneeUserId?: string; | |
| touchedByUserId?: string; | |
| inboxArchivedByUserId?: string; | |
| unreadForUserId?: string; | |
| labelId?: string; | |
| executionWorkspaceId?: string; | |
| originKind?: string; | |
| originId?: string; | |
| includeRoutineExecutions?: boolean; | |
| q?: string; | |
| }, | |
| ) => { | |
| const params = new URLSearchParams(); | |
| if (filters?.status) params.set("status", filters.status); | |
| if (filters?.projectId) params.set("projectId", filters.projectId); | |
| if (filters?.assigneeAgentId) params.set("assigneeAgentId", filters.assigneeAgentId); | |
| if (filters?.participantAgentId) params.set("participantAgentId", filters.participantAgentId); | |
| if (filters?.assigneeUserId) params.set("assigneeUserId", filters.assigneeUserId); | |
| if (filters?.touchedByUserId) params.set("touchedByUserId", filters.touchedByUserId); | |
| if (filters?.inboxArchivedByUserId) params.set("inboxArchivedByUserId", filters.inboxArchivedByUserId); | |
| if (filters?.unreadForUserId) params.set("unreadForUserId", filters.unreadForUserId); | |
| if (filters?.labelId) params.set("labelId", filters.labelId); | |
| if (filters?.executionWorkspaceId) params.set("executionWorkspaceId", filters.executionWorkspaceId); | |
| if (filters?.originKind) params.set("originKind", filters.originKind); | |
| if (filters?.originId) params.set("originId", filters.originId); | |
| if (filters?.includeRoutineExecutions) params.set("includeRoutineExecutions", "true"); | |
| if (filters?.q) params.set("q", filters.q); | |
| const qs = params.toString(); | |
| return api.get<Issue[]>(`/companies/${companyId}/issues${qs ? `?${qs}` : ""}`); | |
| }, | |
| listLabels: (companyId: string) => api.get<IssueLabel[]>(`/companies/${companyId}/labels`), | |
| createLabel: (companyId: string, data: { name: string; color: string }) => | |
| api.post<IssueLabel>(`/companies/${companyId}/labels`, data), | |
| deleteLabel: (id: string) => api.delete<IssueLabel>(`/labels/${id}`), | |
| get: (id: string) => api.get<Issue>(`/issues/${id}`), | |
| markRead: (id: string) => api.post<{ id: string; lastReadAt: Date }>(`/issues/${id}/read`, {}), | |
| markUnread: (id: string) => api.delete<{ id: string; removed: boolean }>(`/issues/${id}/read`), | |
| archiveFromInbox: (id: string) => | |
| api.post<{ id: string; archivedAt: Date }>(`/issues/${id}/inbox-archive`, {}), | |
| unarchiveFromInbox: (id: string) => | |
| api.delete<{ id: string; archivedAt: Date } | { ok: true }>(`/issues/${id}/inbox-archive`), | |
| create: (companyId: string, data: Record<string, unknown>) => | |
| api.post<Issue>(`/companies/${companyId}/issues`, data), | |
| update: (id: string, data: Record<string, unknown>) => | |
| api.patch<IssueUpdateResponse>(`/issues/${id}`, data), | |
| remove: (id: string) => api.delete<Issue>(`/issues/${id}`), | |
| checkout: (id: string, agentId: string) => | |
| api.post<Issue>(`/issues/${id}/checkout`, { | |
| agentId, | |
| expectedStatuses: ["todo", "backlog", "blocked"], | |
| }), | |
| release: (id: string) => api.post<Issue>(`/issues/${id}/release`, {}), | |
| listComments: (id: string) => api.get<IssueComment[]>(`/issues/${id}/comments`), | |
| listFeedbackVotes: (id: string) => api.get<FeedbackVote[]>(`/issues/${id}/feedback-votes`), | |
| listFeedbackTraces: (id: string, filters?: Record<string, string | boolean | undefined>) => { | |
| const params = new URLSearchParams(); | |
| for (const [key, value] of Object.entries(filters ?? {})) { | |
| if (value === undefined) continue; | |
| params.set(key, String(value)); | |
| } | |
| const qs = params.toString(); | |
| return api.get<FeedbackTrace[]>(`/issues/${id}/feedback-traces${qs ? `?${qs}` : ""}`); | |
| }, | |
| upsertFeedbackVote: ( | |
| id: string, | |
| data: { | |
| targetType: FeedbackTargetType; | |
| targetId: string; | |
| vote: "up" | "down"; | |
| reason?: string; | |
| allowSharing?: boolean; | |
| }, | |
| ) => api.post<FeedbackVote>(`/issues/${id}/feedback-votes`, data), | |
| addComment: (id: string, body: string, reopen?: boolean, interrupt?: boolean) => | |
| api.post<IssueComment>( | |
| `/issues/${id}/comments`, | |
| { | |
| body, | |
| ...(reopen === undefined ? {} : { reopen }), | |
| ...(interrupt === undefined ? {} : { interrupt }), | |
| }, | |
| ), | |
| listDocuments: (id: string) => api.get<IssueDocument[]>(`/issues/${id}/documents`), | |
| getDocument: (id: string, key: string) => api.get<IssueDocument>(`/issues/${id}/documents/${encodeURIComponent(key)}`), | |
| upsertDocument: (id: string, key: string, data: UpsertIssueDocument) => | |
| api.put<IssueDocument>(`/issues/${id}/documents/${encodeURIComponent(key)}`, data), | |
| listDocumentRevisions: (id: string, key: string) => | |
| api.get<DocumentRevision[]>(`/issues/${id}/documents/${encodeURIComponent(key)}/revisions`), | |
| restoreDocumentRevision: (id: string, key: string, revisionId: string) => | |
| api.post<IssueDocument>(`/issues/${id}/documents/${encodeURIComponent(key)}/revisions/${revisionId}/restore`, {}), | |
| deleteDocument: (id: string, key: string) => | |
| api.delete<{ ok: true }>(`/issues/${id}/documents/${encodeURIComponent(key)}`), | |
| listAttachments: (id: string) => api.get<IssueAttachment[]>(`/issues/${id}/attachments`), | |
| uploadAttachment: ( | |
| companyId: string, | |
| issueId: string, | |
| file: File, | |
| issueCommentId?: string | null, | |
| ) => { | |
| const form = new FormData(); | |
| form.append("file", file); | |
| if (issueCommentId) { | |
| form.append("issueCommentId", issueCommentId); | |
| } | |
| return api.postForm<IssueAttachment>(`/companies/${companyId}/issues/${issueId}/attachments`, form); | |
| }, | |
| deleteAttachment: (id: string) => api.delete<{ ok: true }>(`/attachments/${id}`), | |
| listApprovals: (id: string) => api.get<Approval[]>(`/issues/${id}/approvals`), | |
| linkApproval: (id: string, approvalId: string) => | |
| api.post<Approval[]>(`/issues/${id}/approvals`, { approvalId }), | |
| unlinkApproval: (id: string, approvalId: string) => | |
| api.delete<{ ok: true }>(`/issues/${id}/approvals/${approvalId}`), | |
| listWorkProducts: (id: string) => api.get<IssueWorkProduct[]>(`/issues/${id}/work-products`), | |
| createWorkProduct: (id: string, data: Record<string, unknown>) => | |
| api.post<IssueWorkProduct>(`/issues/${id}/work-products`, data), | |
| updateWorkProduct: (id: string, data: Record<string, unknown>) => | |
| api.patch<IssueWorkProduct>(`/work-products/${id}`, data), | |
| deleteWorkProduct: (id: string) => api.delete<IssueWorkProduct>(`/work-products/${id}`), | |
| }; | |