mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-25 09:41:04 +01:00
docs(api): document decision queue routes
Add complete OpenAPI coverage for decision queue and triage endpoints, including request schemas, response shapes, authentication, and status codes. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
3310823de0
commit
ec41102ae7
2 files changed
+208
No files matched your search
@@ -26,6 +26,7 @@ const apiPrefixes: Record<string, string> = {
|
||||
"company-skill-policy.ts": "/api",
|
||||
"costs.ts": "/api",
|
||||
"dashboard.ts": "/api",
|
||||
"decision-queues.ts": "/api",
|
||||
"decisions.ts": "/api",
|
||||
"decision-training.ts": "/api",
|
||||
"environments.ts": "/api",
|
||||
@@ -190,6 +191,26 @@ describe("openapi routes", () => {
|
||||
expect(res.body.paths["/api/companies/{companyId}/folders/items/move"].post.summary).toBe(
|
||||
"Move an item into or out of a folder",
|
||||
);
|
||||
const createQueue = res.body.paths["/api/companies/{companyId}/decision-queues"].post;
|
||||
expect(createQueue.security).toContainEqual({ AgentBearerAuth: [] });
|
||||
expect(createQueue.responses["200"]).toBeDefined();
|
||||
expect(createQueue.responses["201"]).toBeDefined();
|
||||
expect(createQueue.requestBody.content["application/json"].schema).toMatchObject({
|
||||
type: "object",
|
||||
properties: {
|
||||
key: { type: "string", minLength: 1, maxLength: 80 },
|
||||
title: { type: "string", minLength: 1, maxLength: 120 },
|
||||
},
|
||||
required: ["key", "title"],
|
||||
});
|
||||
const updateTriage = res.body.paths[
|
||||
"/api/companies/{companyId}/decision-triage/{sourceKind}/{sourceId}"
|
||||
].put;
|
||||
expect(updateTriage.responses["422"]).toBeDefined();
|
||||
expect(updateTriage.requestBody.content["application/json"].schema.properties).toMatchObject({
|
||||
decideBy: { nullable: true },
|
||||
snoozedUntil: { type: "string", format: "date-time", nullable: true },
|
||||
});
|
||||
expect(JSON.stringify(res.body.paths["/api/tool-gateway/tools"].get)).not.toContain("sessionToken");
|
||||
expect(JSON.stringify(res.body.paths["/api/tool-gateway/tools/call"].post)).not.toContain("sessionToken");
|
||||
});
|
||||
|
||||
@@ -48,8 +48,13 @@ import {
|
||||
companyArtifactsQuerySchema,
|
||||
companyArtifactsResponseSchema,
|
||||
// Decisions
|
||||
addDecisionQueueItemSchema,
|
||||
createDecisionQueueSchema,
|
||||
decisionAttentionSourceKindSchema,
|
||||
decisionInputsSchema,
|
||||
decisionOptionsSchema,
|
||||
updateDecisionQueueSchema,
|
||||
updateDecisionTriageSchema,
|
||||
// Routine
|
||||
createRoutineSchema,
|
||||
updateRoutineSchema,
|
||||
@@ -3277,6 +3282,188 @@ registry.registerPath({
|
||||
|
||||
// ─── Decisions ──────────────────────────────────────────────────────────────
|
||||
|
||||
// Decision queues and triage
|
||||
|
||||
const decisionQueueSeedRuleSchema = z.object({
|
||||
key: z.string(),
|
||||
description: z.string(),
|
||||
signal: z.enum([
|
||||
"issue_has_pull_request_work_product",
|
||||
"plan_document_confirmation",
|
||||
"ask_user_questions",
|
||||
]),
|
||||
}).strict();
|
||||
|
||||
const decisionQueueSchema = z.object({
|
||||
id: z.string(),
|
||||
companyId: z.string(),
|
||||
key: z.string(),
|
||||
title: z.string(),
|
||||
description: z.string().nullable(),
|
||||
createdByType: z.enum(["agent", "user", "system"]),
|
||||
createdByAgentId: z.string().nullable(),
|
||||
createdByUserId: z.string().nullable(),
|
||||
createdByRunId: z.string().nullable(),
|
||||
retentionDays: z.number().int().nullable(),
|
||||
seedRules: z.array(decisionQueueSeedRuleSchema),
|
||||
seedRulesEnabled: z.boolean(),
|
||||
itemCount: z.number().int().nonnegative(),
|
||||
createdAt: z.string().datetime(),
|
||||
updatedAt: z.string().datetime(),
|
||||
}).strict();
|
||||
|
||||
const decisionQueueItemSchema = z.object({
|
||||
id: z.string(),
|
||||
companyId: z.string(),
|
||||
queueId: z.string(),
|
||||
sourceKind: decisionAttentionSourceKindSchema,
|
||||
sourceId: z.string(),
|
||||
addedByType: z.enum(["agent", "user", "system"]),
|
||||
addedByAgentId: z.string().nullable(),
|
||||
addedByUserId: z.string().nullable(),
|
||||
addedByRunId: z.string().nullable(),
|
||||
responsibleUserId: z.string().nullable(),
|
||||
createdAt: z.string().datetime(),
|
||||
}).strict();
|
||||
|
||||
const decisionTriageSchema = z.object({
|
||||
id: z.string(),
|
||||
companyId: z.string(),
|
||||
sourceKind: decisionAttentionSourceKindSchema,
|
||||
sourceId: z.string(),
|
||||
decideBy: z.string().nullable(),
|
||||
snoozedUntil: z.string().datetime().nullable(),
|
||||
setByType: z.enum(["agent", "user"]),
|
||||
setByAgentId: z.string().nullable(),
|
||||
setByUserId: z.string().nullable(),
|
||||
setByRunId: z.string().nullable(),
|
||||
responsibleUserId: z.string().nullable(),
|
||||
version: z.number().int().positive(),
|
||||
createdAt: z.string().datetime(),
|
||||
updatedAt: z.string().datetime(),
|
||||
}).strict();
|
||||
|
||||
registerCurrentRoute({
|
||||
method: "get",
|
||||
path: "/api/companies/{companyId}/decision-queue-seed-rules",
|
||||
tags: ["decision-queues"],
|
||||
summary: "List built-in decision queue seed rules",
|
||||
responses: { 200: r.ok(z.array(decisionQueueSeedRuleSchema)), 401: r.unauthorized, 403: r.forbidden },
|
||||
});
|
||||
|
||||
registerCurrentRoute({
|
||||
method: "get",
|
||||
path: "/api/companies/{companyId}/decision-queues",
|
||||
tags: ["decision-queues"],
|
||||
summary: "List decision queues",
|
||||
responses: { 200: r.ok(z.array(decisionQueueSchema)), 401: r.unauthorized, 403: r.forbidden },
|
||||
});
|
||||
|
||||
registerCurrentRoute({
|
||||
method: "post",
|
||||
path: "/api/companies/{companyId}/decision-queues",
|
||||
tags: ["decision-queues"],
|
||||
summary: "Create a decision queue",
|
||||
body: createDecisionQueueSchema,
|
||||
responses: {
|
||||
200: r.ok(decisionQueueSchema),
|
||||
201: r.ok(decisionQueueSchema),
|
||||
400: r.badRequest,
|
||||
401: r.unauthorized,
|
||||
403: r.forbidden,
|
||||
},
|
||||
});
|
||||
|
||||
registerCurrentRoute({
|
||||
method: "patch",
|
||||
path: "/api/companies/{companyId}/decision-queues/{key}",
|
||||
tags: ["decision-queues"],
|
||||
summary: "Update a decision queue",
|
||||
body: updateDecisionQueueSchema,
|
||||
responses: {
|
||||
200: r.ok(decisionQueueSchema),
|
||||
400: r.badRequest,
|
||||
401: r.unauthorized,
|
||||
403: r.forbidden,
|
||||
404: r.notFound,
|
||||
},
|
||||
});
|
||||
|
||||
registerCurrentRoute({
|
||||
method: "get",
|
||||
path: "/api/companies/{companyId}/decision-queues/{key}/items",
|
||||
tags: ["decision-queues"],
|
||||
summary: "List visible items in a decision queue",
|
||||
responses: {
|
||||
200: r.ok(z.array(decisionQueueItemSchema)),
|
||||
401: r.unauthorized,
|
||||
403: r.forbidden,
|
||||
404: r.notFound,
|
||||
},
|
||||
});
|
||||
|
||||
registerCurrentRoute({
|
||||
method: "post",
|
||||
path: "/api/companies/{companyId}/decision-queues/{key}/items",
|
||||
tags: ["decision-queues"],
|
||||
summary: "Add an item to a decision queue",
|
||||
body: addDecisionQueueItemSchema,
|
||||
responses: {
|
||||
200: r.ok(decisionQueueItemSchema),
|
||||
201: r.ok(decisionQueueItemSchema),
|
||||
400: r.badRequest,
|
||||
401: r.unauthorized,
|
||||
403: r.forbidden,
|
||||
404: r.notFound,
|
||||
},
|
||||
});
|
||||
|
||||
registerCurrentRoute({
|
||||
method: "delete",
|
||||
path: "/api/companies/{companyId}/decision-queues/{key}/items/{sourceKind}/{sourceId}",
|
||||
tags: ["decision-queues"],
|
||||
summary: "Remove an item from a decision queue",
|
||||
responses: {
|
||||
200: r.ok(decisionQueueItemSchema),
|
||||
400: r.badRequest,
|
||||
401: r.unauthorized,
|
||||
403: r.forbidden,
|
||||
404: r.notFound,
|
||||
},
|
||||
});
|
||||
|
||||
registerCurrentRoute({
|
||||
method: "get",
|
||||
path: "/api/companies/{companyId}/decision-triage/{sourceKind}/{sourceId}",
|
||||
tags: ["decision-queues"],
|
||||
summary: "Get decision triage for an attention source",
|
||||
responses: {
|
||||
200: r.ok(decisionTriageSchema.nullable()),
|
||||
400: r.badRequest,
|
||||
401: r.unauthorized,
|
||||
403: r.forbidden,
|
||||
404: r.notFound,
|
||||
},
|
||||
});
|
||||
|
||||
registerCurrentRoute({
|
||||
method: "put",
|
||||
path: "/api/companies/{companyId}/decision-triage/{sourceKind}/{sourceId}",
|
||||
tags: ["decision-queues"],
|
||||
summary: "Set decision triage for an attention source",
|
||||
body: updateDecisionTriageSchema,
|
||||
responses: {
|
||||
200: r.ok(decisionTriageSchema),
|
||||
400: r.badRequest,
|
||||
401: r.unauthorized,
|
||||
403: r.forbidden,
|
||||
404: r.notFound,
|
||||
422: r.unprocessable,
|
||||
},
|
||||
});
|
||||
|
||||
// Decisions
|
||||
|
||||
const createDecisionBodySchema = z.object({
|
||||
title: z.string().trim().min(1).max(500),
|
||||
body: z.string().max(100_000),
|
||||
|
||||
Reference in new issue
Block a user