mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-23 00:53:38 +02:00
fix: complete agent feedback API and runner contracts
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
c0c5d5be1e
commit
71e9bac392
6 files changed
+83
-17
No files matched your search
@@ -45,6 +45,11 @@
|
||||
"runner": "Drain or shut down the runner process."
|
||||
},
|
||||
"optionalGrantGroups": [
|
||||
{
|
||||
"id": "feedback",
|
||||
"description": "Internally attributed complaints and improvement suggestions; no additional grant required beyond active run authority.",
|
||||
"operationIds": ["submit_complaint", "submit_suggestion"]
|
||||
},
|
||||
{
|
||||
"id": "discovery",
|
||||
"description": "Company-visible task, agent, project, and goal discovery.",
|
||||
@@ -264,12 +269,12 @@
|
||||
"legacyGroup": 13,
|
||||
"name": "Reference files",
|
||||
"owner": "always instruction tools + optional domain tools + test-only escape hatch",
|
||||
"operationIds": ["list_cases", "upsert_case", "list_routines", "manage_routine", "create_skill", "update_skill", "list_company_skills", "sync_company_skills", "list_secret_metadata", "read_secret_value", "export_company", "administer_company", "generic_api_request", "search_api", "call_api", "create_project", "read_agent_instructions", "update_agent_instructions", "get_agent_instruction_history", "restore_agent_instructions"],
|
||||
"operationIds": ["list_cases", "upsert_case", "list_routines", "manage_routine", "create_skill", "update_skill", "list_company_skills", "sync_company_skills", "list_secret_metadata", "read_secret_value", "export_company", "administer_company", "generic_api_request", "search_api", "call_api", "create_project", "read_agent_instructions", "update_agent_instructions", "get_agent_instruction_history", "restore_agent_instructions", "submit_complaint", "submit_suggestion"],
|
||||
"controlPlaneOperationIds": ["append_audit_record"],
|
||||
"realSurface": "agent instruction revisions, project, case, routine, company-skill, secret, portability, and administration services",
|
||||
"realSurface": "agent instruction revisions, project, case, routine, company-skill, secret, portability, and administration services, and run-attributed agent commentary",
|
||||
"mockStateDomains": ["company", "cases", "routines", "skills", "secrets", "audit", "fault"],
|
||||
"prpEvidence": "bounded domain projections, redacted broker receipts, company diffs, and audit references",
|
||||
"gap": "Instruction read/update/history/restore require the live canonical revision service, current responsible-user permissions, and pinned base revisions for writes. Their service, authority, and product E2E tests are separate from the legacy mock scenarios. Project and skill creation and API tools require the live server authority; generic_api_request is test-only and the remaining domain operations are scenario-only. Broad administer_company is deferred and cannot claim product coverage. Production API and paired dedicated-tool regressions are recorded separately in paperclip-evals/evals/runner-api-tools; the legacy scenario count is not evidence of that coverage."
|
||||
"gap": "Instruction read/update/history/restore require the live canonical revision service, current responsible-user permissions, and pinned base revisions for writes. Their service, authority, and product E2E tests are separate from the legacy mock scenarios. Project and skill creation and API tools require the live server authority; generic_api_request is test-only and the remaining domain operations are scenario-only. Broad administer_company is deferred and cannot claim product coverage. Production API and paired dedicated-tool regressions are recorded separately in paperclip-evals/evals/runner-api-tools; the legacy scenario count is not evidence of that coverage. Feedback actions are live-only: shared persistence, authority, API, and actual Codex smoke tests cover them; the legacy scenario count does not claim feedback coverage."
|
||||
},
|
||||
{
|
||||
"id": "mh",
|
||||
|
||||
@@ -6,7 +6,7 @@ Status: canonical explanatory contract for the Paperclip runner V1 surface.
|
||||
|
||||
This document keeps three independent meanings of **group** separate. PRP families describe wire evidence and controller commands; capability placement decides who owns an operation; behavioral eval groups organize the 106 scenario corpus. None of the three axes can be used as a substitute for another.
|
||||
|
||||
The generated totals are **105 PRP events in 31 event families**, **18 controller commands in 7 command families**, **10 control-plane operations**, **54 reconciled semantic operations** (18 always, 36 optional), and **106 scenarios in 16 behavior groups**.
|
||||
The generated totals are **105 PRP events in 31 event families**, **18 controller commands in 7 command families**, **10 control-plane operations**, **56 reconciled semantic operations** (18 always, 38 optional), and **106 scenarios in 16 behavior groups**.
|
||||
|
||||
## Axis 1: PRP v1 event and command families
|
||||
|
||||
@@ -87,12 +87,13 @@ Placement has exactly three outcomes:
|
||||
|
||||
`answer_status_question`, `block_task`, `finish_task`, `get_agent_instruction_history`, `get_task_context`, `get_task_history`, `inspect_operation_result`, `list_document_revisions`, `list_documents`, `read_agent_instructions`, `read_document`, `register_deliverable`, `report_progress`, `request_human_input`, `request_review`, `restore_agent_instructions`, `update_agent_instructions`, `write_document`.
|
||||
|
||||
### Optional operations (36) and grant groups (13)
|
||||
### Optional operations (38) and grant groups (14)
|
||||
|
||||
Grant groups are documentation/exposure bundles, not additional authority. The operation descriptor's exact `requiredClaims` remains decisive.
|
||||
|
||||
| Grant group | Operations | Required claims represented | Purpose |
|
||||
| --- | --- | --- | --- |
|
||||
| `feedback` | `submit_complaint`<br>`submit_suggestion` | none | Internally attributed complaints and improvement suggestions; no additional grant required beyond active run authority. |
|
||||
| `discovery` | `search_tasks`<br>`list_agents`<br>`get_agent`<br>`list_projects`<br>`list_goals`<br>`set_task_title` | `discovery:agents:read`<br>`discovery:goals:read`<br>`discovery:projects:read`<br>`discovery:tasks:read` | Company-visible task, agent, project, and goal discovery. |
|
||||
| `projects` | `create_project`<br>`list_project_repositories` | none | Project creation and authorized repository discovery through the live company/run authority. |
|
||||
| `delegation_dependencies` | `create_task`<br>`reassign_task`<br>`set_dependencies`<br>`hire_agent` | `delegation:agents:create`<br>`delegation:tasks:assign`<br>`delegation:tasks:create`<br>`dependencies:write` | Create or reassign delegated work and maintain dependency edges. |
|
||||
@@ -162,6 +163,8 @@ Grant groups are documentation/exposure bundles, not additional authority. The o
|
||||
| `search_tasks` | `optional_agent_tool` | `discovery:tasks:read` | `standard`<br>`ask`<br>`planning`<br>`skill_test` | `read` | `none` | no | `snapshot_read:company_tasks` | `scenario` + `live`<br>`live_codex` | `unbound`<br>read projection surfaced via a tool-result item event; no control-plane state diff<br>catalog PRP status: `audit_pending` |
|
||||
| `set_dependencies` | `optional_agent_tool` | `dependencies:write` | `standard`<br>`skill_test` | `company_write` | `required` | no | `semantic_command:set_dependencies` | `scenario` + `live`<br>`live_codex` | `issues.update.blockedByIssueIds`<br>semantic-operation item event plus company-entity state diff and audit record<br>catalog PRP status: `bound` |
|
||||
| `set_task_title` | `optional_agent_tool` | none | `standard`<br>`ask`<br>`planning`<br>`skill_test` | `task_write` | `required` | no | inline/no mapping | `live`<br>`live_codex` | `setIssueTitle`<br>Run-bound title update and transactional activity record.<br>catalog PRP status: `bound` |
|
||||
| `submit_complaint` | `optional_agent_tool` | none | `standard`<br>`ask`<br>`planning` | `task_write` | `required` | no | inline/no mapping | `live`<br>`live_codex` | `submitAgentCommentary`<br>Run-bound local commentary and transactional activity record.<br>catalog PRP status: `bound` |
|
||||
| `submit_suggestion` | `optional_agent_tool` | none | `standard`<br>`ask`<br>`planning` | `task_write` | `required` | no | inline/no mapping | `live`<br>`live_codex` | `submitAgentCommentary`<br>Run-bound local commentary and transactional activity record.<br>catalog PRP status: `bound` |
|
||||
| `sync_company_skills` | `optional_agent_tool` | `company_skills:write` | `standard`<br>`skill_test` | `admin` | `required` | no | `mock_extension:company_skills.sync` | `scenario`<br>`scenario_mock` | `unbound`<br>company admin/portability item event plus audit record<br>catalog PRP status: `audit_pending` |
|
||||
| `update_agent_instructions` | `always_agent_tool` | none | `standard`<br>`planning` | `company_write` | `recommended` | no | inline/no mapping | `live`<br>`live_codex` | `agentInstructionRevisionService`<br>tool-result item event plus canonical revision receipt for writes; no scenario mock coverage<br>catalog PRP status: `bound` |
|
||||
| `update_skill` | `optional_agent_tool` | none | `standard`<br>`skill_test` | `company_write` | `required` | no | `semantic_command:update_skill` | `scenario` + `live`<br>`live_codex` | `PaperclipRunnerToolAuthority`<br>Authenticated skill file API with version guard, durable receipt, and attributed activity.<br>catalog PRP status: `bound` |
|
||||
@@ -188,7 +191,7 @@ Behavior groups describe expected outcomes and trajectories. They do not grant t
|
||||
| [`ap` — Approvals](#behavior-group-ap-approvals) | optional governance tools + governed approver | `list_approvals`<br>`get_approval`<br>`get_approval_context`<br>`request_approval`<br>`decide_approval`<br>`comment_on_approval` | `route_wake`<br>`append_audit_record` | company approval, decision, issue-link, comment, and governed-action services | `company`<br>`task`<br>`approvals`<br>`actor`<br>`wake`<br>`audit`<br>`idempotency` | 6 | governed semantic receipts, audit references, and attention/continuation linkage | Production binding and additive governed-action receipts are unbound; board-only authority stays outside grants. |
|
||||
| [`ar` — Artifacts](#behavior-group-ar-artifacts) | always tools + artifact/work-product services | `register_deliverable` | `append_audit_record` | attachment upload and issue work-product routes | `task`<br>`artifacts`<br>`workProducts`<br>`workspace`<br>`audit`<br>`idempotency` | 4 | artifact/work-product reference and durable inspectability receipt; never binary bytes | Production upload/register composite and additive durable-reference receipt are unbound. |
|
||||
| [`er` — Errors and critical rules](#behavior-group-er-errors-and-critical-rules) | runner/control plane + optional workspace/wake tools | `get_workspace_runtime`<br>`control_workspace_service`<br>`schedule_wake`<br>`inspect_operation_result` | `release_task`<br>`enforce_budget`<br>`persist_run`<br>`replay_run`<br>`reconcile_run` | workspace runtime, monitor/recovery, budget, run persistence/replay, release, and terminal services | `workspace`<br>`budget`<br>`run`<br>`wake`<br>`audit`<br>`idempotency`<br>`fault` | 9 | runtime/workspace/attention/run lifecycle, typed denials, replay facts, and terminal causality | Budget stop reasons and semantic denial/conflict receipts require additive v1 envelopes; inspect_operation_result remains scenario-only. |
|
||||
| [`rf` — Reference files](#behavior-group-rf-reference-files) | always instruction tools + optional domain tools + test-only escape hatch | `list_cases`<br>`upsert_case`<br>`list_routines`<br>`manage_routine`<br>`create_skill`<br>`update_skill`<br>`list_company_skills`<br>`sync_company_skills`<br>`list_secret_metadata`<br>`read_secret_value`<br>`export_company`<br>`administer_company`<br>`generic_api_request`<br>`search_api`<br>`call_api`<br>`create_project`<br>`read_agent_instructions`<br>`update_agent_instructions`<br>`get_agent_instruction_history`<br>`restore_agent_instructions` | `append_audit_record` | agent instruction revisions, project, case, routine, company-skill, secret, portability, and administration services | `company`<br>`cases`<br>`routines`<br>`skills`<br>`secrets`<br>`audit`<br>`fault` | 22 | bounded domain projections, redacted broker receipts, company diffs, and audit references | Instruction read/update/history/restore require the live canonical revision service, current responsible-user permissions, and pinned base revisions for writes. Their service, authority, and product E2E tests are separate from the legacy mock scenarios. Project and skill creation and API tools require the live server authority; generic_api_request is test-only and the remaining domain operations are scenario-only. Broad administer_company is deferred and cannot claim product coverage. Production API and paired dedicated-tool regressions are recorded separately in paperclip-evals/evals/runner-api-tools; the legacy scenario count is not evidence of that coverage. |
|
||||
| [`rf` — Reference files](#behavior-group-rf-reference-files) | always instruction tools + optional domain tools + test-only escape hatch | `list_cases`<br>`upsert_case`<br>`list_routines`<br>`manage_routine`<br>`create_skill`<br>`update_skill`<br>`list_company_skills`<br>`sync_company_skills`<br>`list_secret_metadata`<br>`read_secret_value`<br>`export_company`<br>`administer_company`<br>`generic_api_request`<br>`search_api`<br>`call_api`<br>`create_project`<br>`read_agent_instructions`<br>`update_agent_instructions`<br>`get_agent_instruction_history`<br>`restore_agent_instructions`<br>`submit_complaint`<br>`submit_suggestion` | `append_audit_record` | agent instruction revisions, project, case, routine, company-skill, secret, portability, and administration services, and run-attributed agent commentary | `company`<br>`cases`<br>`routines`<br>`skills`<br>`secrets`<br>`audit`<br>`fault` | 22 | bounded domain projections, redacted broker receipts, company diffs, and audit references | Instruction read/update/history/restore require the live canonical revision service, current responsible-user permissions, and pinned base revisions for writes. Their service, authority, and product E2E tests are separate from the legacy mock scenarios. Project and skill creation and API tools require the live server authority; generic_api_request is test-only and the remaining domain operations are scenario-only. Broad administer_company is deferred and cannot claim product coverage. Production API and paired dedicated-tool regressions are recorded separately in paperclip-evals/evals/runner-api-tools; the legacy scenario count is not evidence of that coverage. Feedback actions are live-only: shared persistence, authority, API, and actual Codex smoke tests cover them; the legacy scenario count does not claim feedback coverage. |
|
||||
| [`mh` — Multi-hop](#behavior-group-mh-multi-hop) | composed semantic operations + control-plane continuation | `create_task`<br>`set_dependencies`<br>`request_human_input`<br>`request_approval`<br>`register_deliverable` | `route_wake`<br>`reconcile_run` | delegation, dependency, interaction, approval, artifact, and terminal orchestration services | `task`<br>`blockers`<br>`interactions`<br>`approvals`<br>`artifacts`<br>`wake`<br>`run`<br>`audit` | 4 | correlated operation receipts, state diffs, attention hops, work assessment, status decision, and terminal outcome | No generic transaction tool is allowed; shared mock/real conformance must prove each composed effect. |
|
||||
| [`rs` — Restraint and no-call](#behavior-group-rs-restraint-and-no-call) | policy/exposure layer | `answer_status_question`<br>`read_secret_value`<br>`generic_api_request` | `enforce_budget` | task-mode, secret-broker, test-scope, pause, and budget policy checks | `actor`<br>`task`<br>`budget`<br>`secrets`<br>`audit`<br>`fault` | 3 | absence of forbidden effects plus typed policy denial/redaction receipts when a call is attempted | Typed redaction/authorization receipts need additive v1 evidence; generic_api_request is never a product fallback. |
|
||||
| [`wk` — Wake situations](#behavior-group-wk-wake-situations) | control plane + always context/history tools | `get_task_context`<br>`get_task_history`<br>`schedule_wake` | `select_work`<br>`route_wake` | wakeup requests, heartbeat context, comment/interaction/approval/blocker wake routing, and scheduled wake services | `wake`<br>`task`<br>`comments`<br>`interactions`<br>`approvals`<br>`blockers`<br>`run` | 8 | attention request routing/resolution plus resumed session/run causality | Production scheduling binding is unbound; control-plane routing remains non-callable. |
|
||||
@@ -465,10 +468,10 @@ Current responsibility-based paths are normative. Numbered `phase-*` or mileston
|
||||
### Catalog split and deliberate replacement
|
||||
|
||||
- Scenario/eval catalog: **40** operations.
|
||||
- Live dispatcher catalog: **42** operations.
|
||||
- Shared: **28**; union/canonical authority: **54**.
|
||||
- Live dispatcher catalog: **44** operations.
|
||||
- Shared: **28**; union/canonical authority: **56**.
|
||||
- Scenario-only: `administer_company`, `export_company`, `inspect_operation_result`, `list_cases`, `list_company_skills`, `list_goals`, `list_routines`, `list_secret_metadata`, `manage_routine`, `read_secret_value`, `sync_company_skills`, `upsert_case`.
|
||||
- Live-only: `call_api`, `create_project`, `get_agent`, `get_agent_instruction_history`, `get_approval`, `get_approval_context`, `hire_agent`, `list_project_repositories`, `read_agent_instructions`, `restore_agent_instructions`, `schedule_wake`, `search_api`, `set_task_title`, `update_agent_instructions`.
|
||||
- Live-only: `call_api`, `create_project`, `get_agent`, `get_agent_instruction_history`, `get_approval`, `get_approval_context`, `hire_agent`, `list_project_repositories`, `read_agent_instructions`, `restore_agent_instructions`, `schedule_wake`, `search_api`, `set_task_title`, `submit_complaint`, `submit_suggestion`, `update_agent_instructions`.
|
||||
- The generated provider contract contains exactly the live catalog; the canonical union remains the migration authority until all scenario-only operations are either implemented, deferred, or removed by an explicit reconciliation decision.
|
||||
- `generic_api_request` stays exported only for controlled tests and cannot be cited as real-surface, mock-parity, or PRP product coverage.
|
||||
|
||||
|
||||
@@ -20,9 +20,9 @@ describe("canonical semantic-catalog reconciliation authority", () => {
|
||||
it("pins the reconciled op-set relationship between the two catalogs", () => {
|
||||
const summary = capabilityCatalogReconciliation();
|
||||
expect(summary.scenarioCount).toBe(40);
|
||||
expect(summary.liveCount).toBe(42);
|
||||
expect(summary.liveCount).toBe(44);
|
||||
expect(summary.sharedCount).toBe(28);
|
||||
expect(summary.unionCount).toBe(54);
|
||||
expect(summary.unionCount).toBe(56);
|
||||
// Any operation added to or removed from either catalog without a
|
||||
// reconciliation decision changes these exact sets and fails the gate.
|
||||
expect(summary.liveOnly).toEqual([
|
||||
@@ -39,6 +39,8 @@ describe("canonical semantic-catalog reconciliation authority", () => {
|
||||
"schedule_wake",
|
||||
"search_api",
|
||||
"set_task_title",
|
||||
"submit_complaint",
|
||||
"submit_suggestion",
|
||||
"update_agent_instructions",
|
||||
]);
|
||||
expect(summary.scenarioOnly).toEqual([
|
||||
@@ -58,7 +60,7 @@ describe("canonical semantic-catalog reconciliation authority", () => {
|
||||
});
|
||||
|
||||
it("is the single source both catalogs derive their operation set from", () => {
|
||||
expect(CAPABILITY_CANONICAL_OPERATIONS).toHaveLength(54);
|
||||
expect(CAPABILITY_CANONICAL_OPERATIONS).toHaveLength(56);
|
||||
const canonicalIds = new Set(CAPABILITY_CANONICAL_OPERATIONS.map((operation) => operation.operationId));
|
||||
// Neither catalog may contain an operation absent from the canonical source.
|
||||
for (const tool of SCENARIO_CATALOG) expect(canonicalIds.has(tool.operationId)).toBe(true);
|
||||
@@ -92,7 +94,7 @@ describe("canonical semantic-catalog reconciliation authority", () => {
|
||||
});
|
||||
|
||||
it("names placement, claims, task modes, side-effect class, idempotency, redaction, mock mapping, real binding status, and PRP evidence for every operation", () => {
|
||||
expect(CAPABILITY_CANONICAL_CATALOG).toHaveLength(54);
|
||||
expect(CAPABILITY_CANONICAL_CATALOG).toHaveLength(56);
|
||||
for (const operation of CAPABILITY_CANONICAL_CATALOG) {
|
||||
expect(operation.placement).toMatch(/^(always|optional)_agent_tool$/);
|
||||
expect(Array.isArray(operation.requiredClaims)).toBe(true);
|
||||
@@ -118,7 +120,7 @@ describe("canonical semantic-catalog reconciliation authority", () => {
|
||||
it("classifies real binding status so generic_api_request is never product coverage", () => {
|
||||
const summary = capabilityCatalogReconciliation();
|
||||
expect(summary.byRealBindingStatus).toEqual({
|
||||
live_codex: 41,
|
||||
live_codex: 43,
|
||||
scenario_mock: 12,
|
||||
test_only: 1,
|
||||
});
|
||||
|
||||
@@ -466,13 +466,13 @@ describe("workflow reports and stress traceability", () => {
|
||||
candidateFailures: 36,
|
||||
});
|
||||
expect(report.coverage).toMatchObject({
|
||||
canonicalOperations: 54,
|
||||
canonicalOperations: 56,
|
||||
capabilityCases: 106,
|
||||
workflows: 12,
|
||||
stressFindings: 44,
|
||||
stressExclusions: 1,
|
||||
});
|
||||
expect(report.coverage.operations).toHaveLength(54);
|
||||
expect(report.coverage.operations).toHaveLength(56);
|
||||
expect(report.coverage.composedWorkflows).toHaveLength(12);
|
||||
expect(
|
||||
report.coverage.operations.find(
|
||||
@@ -480,7 +480,7 @@ describe("workflow reports and stress traceability", () => {
|
||||
)?.workflowIds.length,
|
||||
).toBeGreaterThan(0);
|
||||
expect(renderRunnerWorkflowMarkdown(report)).toContain(
|
||||
"54 operations · 106 capability cases · 12 workflows",
|
||||
"56 operations · 106 capability cases · 12 workflows",
|
||||
);
|
||||
expect(renderRunnerWorkflowJUnit(report)).toContain(
|
||||
'tests="36" failures="36" skipped="0"',
|
||||
|
||||
@@ -19,6 +19,7 @@ const apiPrefixes: Record<string, string> = {
|
||||
"activity.ts": "/api",
|
||||
"adapters.ts": "/api",
|
||||
"agents.ts": "/api",
|
||||
"agent-commentary.ts": "/api",
|
||||
"agent-avatars.ts": "/api",
|
||||
"announcements.ts": "/api",
|
||||
"ai-connections.ts": "/api",
|
||||
@@ -237,6 +238,27 @@ function loadSpecRoutes() {
|
||||
}
|
||||
|
||||
describe("openapi routes", () => {
|
||||
it("documents strict run-attributed feedback without a read endpoint", () => {
|
||||
const { spec } = loadSpecRoutes();
|
||||
const path = spec.paths["/api/companies/{companyId}/agent-commentary"];
|
||||
expect(Object.keys(path)).toEqual(["post"]);
|
||||
const operation = path.post;
|
||||
expect(operation.security).toEqual([{ AgentBearerAuth: [] }]);
|
||||
expect(operation["x-paperclip-authorization"]).toEqual({ actor: "agent", heartbeatBound: true });
|
||||
expect(operation.description).toContain("X-Paperclip-Run-Id");
|
||||
const body = operation.requestBody.content["application/json"].schema;
|
||||
expect(body.additionalProperties).toBe(false);
|
||||
expect(Object.keys(body.properties).sort()).toEqual(["body", "idempotencyKey", "kind"]);
|
||||
expect(body.properties.body.maxLength).toBe(524288);
|
||||
for (const code of ["200", "201"]) {
|
||||
const result = operation.responses[code].content["application/json"].schema;
|
||||
expect(result.additionalProperties).toBe(false);
|
||||
expect(Object.keys(result.properties).sort()).toEqual(["createdAt", "id", "kind", "replayed"]);
|
||||
}
|
||||
expect(operation.responses["409"]).toBeDefined();
|
||||
expect(operation.responses["503"]).toBeDefined();
|
||||
});
|
||||
|
||||
it("documents board-only pool management with revision-checked deletion", () => {
|
||||
const { spec } = loadSpecRoutes();
|
||||
const pools = spec.paths["/api/companies/{companyId}/ai-connection-pools"];
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
slackToolCallSchema,
|
||||
slackSearchConfigSchema,
|
||||
// Agent
|
||||
submitAgentCommentarySchema,
|
||||
AGENT_PALETTE_IDS,
|
||||
AGENT_AVATAR_SIZES,
|
||||
CHARACTER_STATES,
|
||||
@@ -1263,6 +1264,7 @@ function registerCurrentRoute(input: {
|
||||
type OpenApiAuthLevel =
|
||||
| "public"
|
||||
| "agent_run"
|
||||
| "agent_heartbeat"
|
||||
| "runtime_tools"
|
||||
| "authenticated"
|
||||
| "board"
|
||||
@@ -1684,6 +1686,7 @@ function resolveOperationAuthLevel(
|
||||
if (key === "GET /api/mcp/requests/{id}" || key === "GET /api/mcp/device") return "public";
|
||||
if (path === "/api/mcp/setup" || path === "/api/mcp/device/consent" || path.startsWith("/api/mcp/requests/") || path.startsWith("/api/mcp/connections")) return "board";
|
||||
if (PUBLIC_OPERATIONS.has(key)) return "public";
|
||||
if (key === "POST /api/companies/{companyId}/agent-commentary") return "agent_heartbeat";
|
||||
if (key === "POST /api/mcp/project-tools" || key === "POST /api/companies/{companyId}/slack/tasks/{issueId}/tools") return "agent_run";
|
||||
if (RUNTIME_TOOLS_OPERATIONS.has(key)) return "runtime_tools";
|
||||
if (INSTANCE_ADMIN_OPERATIONS.has(key)) return "instance_admin";
|
||||
@@ -1755,6 +1758,8 @@ function applyDocumentFixups(document: any): any {
|
||||
operation.security = [];
|
||||
} else if (authLevel === "agent_run") {
|
||||
operation.security = [securityRequirement(AGENT_RUN_AUTH_SCHEME)];
|
||||
} else if (authLevel === "agent_heartbeat") {
|
||||
operation.security = [securityRequirement(AGENT_BEARER_AUTH_SCHEME)];
|
||||
} else if (authLevel === "runtime_tools") {
|
||||
operation.security = RUNTIME_TOOLS_SECURITY;
|
||||
} else if (authLevel === "authenticated") {
|
||||
@@ -1770,6 +1775,8 @@ function applyDocumentFixups(document: any): any {
|
||||
? { actor: "board" }
|
||||
: authLevel === "agent_run"
|
||||
? { actor: "agent", heartbeatBound: true, taskBound: true }
|
||||
: authLevel === "agent_heartbeat"
|
||||
? { actor: "agent", heartbeatBound: true }
|
||||
: authLevel === "runtime_tools"
|
||||
? { actor: "runtime_tools", heartbeatBound: true }
|
||||
: authLevel === "authenticated"
|
||||
@@ -5267,6 +5274,33 @@ registry.registerPath({
|
||||
responses: { 200: r.ok(), 400: r.badRequest, 401: r.unauthorized },
|
||||
});
|
||||
|
||||
// ─── Agent feedback ──────────────────────────────────────────────────────────
|
||||
|
||||
const agentCommentaryAcknowledgementSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
kind: z.enum(["complaint", "suggestion"]),
|
||||
createdAt: z.string().datetime(),
|
||||
replayed: z.boolean(),
|
||||
}).strict();
|
||||
|
||||
registry.registerPath({
|
||||
method: "post",
|
||||
path: "/api/companies/{companyId}/agent-commentary",
|
||||
tags: ["agents"],
|
||||
summary: "Submit internally attributed agent feedback",
|
||||
description: "Requires an active legacy agent run: a run-bound agent JWT, or an agent API key with X-Paperclip-Run-Id. Attribution is derived from authority; ownership fields are rejected. Equivalent replay returns the existing acknowledgement. Native runs use their bound feedback tools. Failure must not interrupt the primary task or trigger retries.",
|
||||
request: {
|
||||
params: z.object({ companyId: z.string() }),
|
||||
body: jsonBody(submitAgentCommentarySchema),
|
||||
},
|
||||
responses: {
|
||||
200: r.ok(agentCommentaryAcknowledgementSchema),
|
||||
201: { ...r.ok(agentCommentaryAcknowledgementSchema), description: "Feedback stored" },
|
||||
400: r.badRequest, 401: r.unauthorized, 403: r.forbidden, 409: r.conflict,
|
||||
503: { description: "Feedback storage unavailable; continue the primary task without retrying" },
|
||||
},
|
||||
});
|
||||
|
||||
// ─── Costs ───────────────────────────────────────────────────────────────────
|
||||
|
||||
const costSummaryPaths = [
|
||||
|
||||
Reference in new issue
Block a user