Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/mcp-cloudflare/src/test-utils/fetch-mock-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -467,14 +467,14 @@ export function registerFetchMockInterceptors(fetchMock: FetchMockLike) {
// ===== Autofix =====
pool
.intercept({
path: "/api/0/organizations/sentry-mcp-evals/issues/CLOUDFLARE-MCP-41/autofix/",
path: "/api/0/organizations/sentry-mcp-evals/issues/CLOUDFLARE-MCP-41/autofix/?mode=explorer",
})
.reply(200, { autofix: null }, { headers: JSON_HEADERS })
.persist();

pool
.intercept({
path: "/api/0/organizations/sentry-mcp-evals/issues/PEATED-A8/autofix/",
path: "/api/0/organizations/sentry-mcp-evals/issues/PEATED-A8/autofix/?mode=explorer",
})
.reply(200, autofixStateFixture, { headers: JSON_HEADERS })
.persist();
Expand Down
40 changes: 28 additions & 12 deletions packages/mcp-core/src/api-client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
TagListSchema,
ApiErrorSchema,
ClientKeyListSchema,
type AutofixExplorerStepSchema,
AutofixRunSchema,
AutofixRunStateSchema,
TraceMetaSchema,
Expand Down Expand Up @@ -2566,36 +2567,51 @@ export class SentryApiService {
return await this.requestJSON(apiUrl, undefined, opts);
}

// POST https://us.sentry.io/api/0/issues/5485083130/autofix/
// POST https://us.sentry.io/api/0/issues/5485083130/autofix/?mode=explorer
//
// Explorer mode advances the run one logical step at a time. A new run is
// created when `runId` is omitted (allowed only for `step: "root_cause"`);
// later steps must reuse the original run via `runId`.
async startAutofix(
{
organizationSlug,
issueId,
eventId,
instruction = "",
step,
runId,
userContext,
insertIndex,
}: {
organizationSlug: string;
issueId: string;
eventId?: string;
instruction?: string;
step: z.infer<typeof AutofixExplorerStepSchema>;
runId?: number;
userContext?: string;
insertIndex?: number;
},
opts?: RequestOptions,
): Promise<AutofixRun> {
const payload: Record<string, unknown> = { step };
if (runId !== undefined) {
payload.run_id = runId;
}
if (userContext !== undefined && userContext !== "") {
payload.user_context = userContext;
}
if (insertIndex !== undefined) {
payload.insert_index = insertIndex;
}
const body = await this.requestJSON(
`/organizations/${organizationSlug}/issues/${issueId}/autofix/`,
`/organizations/${organizationSlug}/issues/${issueId}/autofix/?mode=explorer`,
{
method: "POST",
body: JSON.stringify({
event_id: eventId,
instruction,
}),
body: JSON.stringify(payload),
},
opts,
);
return AutofixRunSchema.parse(body);
}

// GET https://us.sentry.io/api/0/issues/5485083130/autofix/
// GET https://us.sentry.io/api/0/issues/5485083130/autofix/?mode=explorer
async getAutofixState(
{
organizationSlug,
Expand All @@ -2607,7 +2623,7 @@ export class SentryApiService {
opts?: RequestOptions,
): Promise<AutofixRunState> {
const body = await this.requestJSON(
`/organizations/${organizationSlug}/issues/${issueId}/autofix/`,
`/organizations/${organizationSlug}/issues/${issueId}/autofix/?mode=explorer`,
undefined,
opts,
);
Expand Down
31 changes: 18 additions & 13 deletions packages/mcp-core/src/api-client/schema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -615,22 +615,27 @@ describe("AutofixRunSchema", () => {
});

describe("AutofixRunStateSchema", () => {
it("accepts explorer-style autofix state without legacy steps", () => {
it("parses an explorer-mode autofix state with blocks and artifacts", () => {
const state = AutofixRunStateSchema.parse(autofixStateExplorerFixture);

expect(state.autofix?.steps).toEqual([]);
expect(state.autofix?.blocks).toEqual([
{
type: "root_cause",
title: "Investigate failing request",
status: "COMPLETED",
},
{
type: "solution",
title: "Draft fix plan",
status: "IN_PROGRESS",
expect(state.autofix?.status).toBe("processing");
expect(state.autofix?.run_id).toBe(21831);
const blocks = state.autofix?.blocks ?? [];
expect(blocks).toHaveLength(2);
expect(blocks[0]?.message.metadata?.step).toBe("root_cause");
expect(blocks[1]?.message.metadata?.step).toBe("solution");
expect(blocks[0]?.artifacts?.[0]?.key).toBe("root_cause");
});

it("defaults missing blocks arrays to []", () => {
const state = AutofixRunStateSchema.parse({
autofix: {
run_id: 1,
status: "processing",
},
]);
});

expect(state.autofix?.blocks).toEqual([]);
});
});

Expand Down
Loading
Loading