mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-17 20:09:05 +02:00
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Native Runner runs report provider errors and can also save a structured failure result. > - Codex rejects a model that the user's ChatGPT account cannot use. > - Master now diagnoses this rejection, but the task's compact run data omits its message. The thread can still call it a generic run failure. > - Users need the account restriction and a clear step to repair the model selection. > - This pull request shows the existing diagnosis as “Model unavailable” on the task. ## Linked Issues or Issue Description **What happened?** Codex returns HTTP 400 with `invalid_request_error` and the message `The 'gpt-6.1-sol' model is not supported when using Codex with a ChatGPT account.` Master now stores an actionable diagnosis for this rejection. The task thread still labels it “Run failed” and does not receive its error text in compact run data. **Expected behavior** Show the account restriction on the task and in the run error. Tell the user to choose a supported model or clear the task's model override before retrying. **Steps to reproduce** 1. Use a Native Runner Codex agent signed in with a ChatGPT account. 2. Select a model that produces the rejection above and start a task. 3. Let the runner save its generic failed result. Inspect the task's failure marker and recovery notice. **Additional context** Refs: #15304. That merged PR diagnoses the provider failure and preserves worker and review recovery rules. This PR adds its task-facing message and guidance without changing that diagnosis or those rules. Refs: #13134. That PR improves model discovery for ChatGPT accounts. This PR exposes the rejection when a configured model still fails at execution time. ## What Changed - Return a bounded model rejection message in compact issue-run data. - Show “Model unavailable” and model-change guidance in the task thread and recovery notice. - Add database and UI regression tests, including both the original rejection text and master's fixed diagnosis. Document the new failure message. ## Verification - Focused merged-branch validation: 279 tests passed across activity service, native provider failure observation and PostgreSQL integration, TaskChatThread, and ExecutionBlockerNotice. - `pnpm -r typecheck`, `pnpm build`, and `pnpm check:token-gates` passed on the merged source tree. - Greptile reviewed conflict-resolution commit `1db39c4e636a92e2e76ba224b71c6f1e2f556c81` at 5/5 with no findings or inline comments. - All 55 check runs completed without failure on that commit. The two optional Storybook jobs were skipped. The legacy Snyk status passed. The branch has no merge conflicts. - UI regression assertion: the task's failure marker says “Model unavailable” and retains the account restriction. It no longer says that this failure happened after a final response. ## Risks - Provider recognition and recovery are owned by the existing master implementation. This PR exposes only bounded error text for failed runs with `native_provider_model_rejected`. - Historical runs with the generic `adapter_failed` code are not reclassified. No stored run is rewritten. - Existing retry and reconciliation gates remain in place. No schema migration or model configuration change is required. ## Model Used OpenAI Codex, based on GPT-6, with reasoning, code execution, and browser inspection. The exact deployment model ID and context window are not exposed in this session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge Co-Authored-By: Paperclip <noreply@paperclip.ing>
85 lines
2.8 KiB
TypeScript
85 lines
2.8 KiB
TypeScript
import type { ActivityEvent, ExecutionProjection, RunLivenessState } from "@paperclipai/shared";
|
|
import { api, type RequestOptions } from "./client";
|
|
|
|
export type { RunLivenessState } from "@paperclipai/shared";
|
|
|
|
export interface RunForIssue {
|
|
runId: string;
|
|
execution?: ExecutionProjection | null;
|
|
runtimeMode?: "legacy" | "native";
|
|
status: string;
|
|
agentId: string;
|
|
adapterType: string;
|
|
startedAt: string | null;
|
|
finishedAt: string | null;
|
|
createdAt: string;
|
|
invocationSource: string;
|
|
responsibleUserId?: string | null;
|
|
errorCode?: string | null;
|
|
/** Bounded provider message for a failed model rejection. */
|
|
error?: string | null;
|
|
usageJson: Record<string, unknown> | null;
|
|
resultJson: Record<string, unknown> | null;
|
|
logBytes?: number | null;
|
|
retryOfRunId?: string | null;
|
|
scheduledRetryAt?: string | null;
|
|
scheduledRetryAttempt?: number;
|
|
scheduledRetryReason?: string | null;
|
|
retryExhaustedReason?: string | null;
|
|
livenessState?: RunLivenessState | null;
|
|
livenessReason?: string | null;
|
|
continuationAttempt?: number;
|
|
lastUsefulActionAt?: string | null;
|
|
nextAction?: string | null;
|
|
wakeCommentIds?: string[] | null;
|
|
wakeCommentId?: string | null;
|
|
contextCommentId?: string | null;
|
|
contextIssueId?: string | null;
|
|
contextSnapshot?: Record<string, unknown> | null;
|
|
environment?: {
|
|
id: string;
|
|
name: string;
|
|
driver: string;
|
|
} | null;
|
|
environmentLease?: {
|
|
id: string;
|
|
status: string;
|
|
leasePolicy: string;
|
|
provider: string | null;
|
|
providerLeaseId: string | null;
|
|
executionWorkspaceId: string | null;
|
|
workspacePath: string | null;
|
|
failureReason: string | null;
|
|
cleanupStatus: string | null;
|
|
acquiredAt: string | Date;
|
|
releasedAt: string | Date | null;
|
|
} | null;
|
|
}
|
|
|
|
export interface IssueForRun {
|
|
issueId: string;
|
|
identifier: string | null;
|
|
title: string;
|
|
status: string;
|
|
priority: string;
|
|
}
|
|
|
|
export const activityApi = {
|
|
list: (
|
|
companyId: string,
|
|
filters?: { entityType?: string; entityId?: string; agentId?: string; limit?: number },
|
|
options?: RequestOptions,
|
|
) => {
|
|
const params = new URLSearchParams();
|
|
if (filters?.entityType) params.set("entityType", filters.entityType);
|
|
if (filters?.entityId) params.set("entityId", filters.entityId);
|
|
if (filters?.agentId) params.set("agentId", filters.agentId);
|
|
if (filters?.limit) params.set("limit", String(filters.limit));
|
|
const qs = params.toString();
|
|
return api.get<ActivityEvent[]>(`/companies/${companyId}/activity${qs ? `?${qs}` : ""}`, options);
|
|
},
|
|
forIssue: (issueId: string) => api.get<ActivityEvent[]>(`/issues/${issueId}/activity`),
|
|
runsForIssue: (issueId: string) => api.get<RunForIssue[]>(`/issues/${issueId}/runs`),
|
|
issuesForRun: (runId: string) => api.get<IssueForRun[]>(`/heartbeat-runs/${runId}/issues`),
|
|
};
|