mirror of
https://github.com/morluto/rea.git
synced 2026-11-07 05:56:19 -10:00
fix(ida): report registration timeout bounds (#7893)
This commit is contained in:
1 parent
3a512303d9
commit
b0b25ad93e
2 files changed
+61
-6
No files matched your search
@@ -5,6 +5,7 @@ import { AnalysisCleanupLease } from "../artifacts/AnalysisCleanupLease.js";
|
||||
import type { RetainedResourceScope } from "../application/AnalysisProvider.js";
|
||||
import { ConfigurationError } from "../domain/configurationErrors.js";
|
||||
import { AnalysisCancelledError } from "../domain/analysisErrorCore.js";
|
||||
import type { AnalysisInputIssue } from "../domain/analysisErrorCore.js";
|
||||
import { projectInputIssues } from "../domain/inputIssueProjection.js";
|
||||
import { err, ok, type Result } from "../domain/result.js";
|
||||
import {
|
||||
@@ -20,6 +21,8 @@ import { readBoundedFileBytes } from "../process/BoundedFileBytes.js";
|
||||
|
||||
/** Omitted registration `timeoutMs` for each upstream IDA MCP request. */
|
||||
export const DEFAULT_IDA_REQUEST_TIMEOUT_MS = 300_000;
|
||||
/** Shortest valid registration request timeout. */
|
||||
const MIN_IDA_REQUEST_TIMEOUT_MS = 1;
|
||||
/** Node timer ceiling. Larger registration values would be clamped instead of honored. */
|
||||
export const MAX_IDA_REQUEST_TIMEOUT_MS = 2_147_483_647;
|
||||
|
||||
@@ -34,7 +37,7 @@ const common = {
|
||||
protocol: z.literal("native").optional(),
|
||||
timeoutMs: z
|
||||
.int()
|
||||
.positive()
|
||||
.min(MIN_IDA_REQUEST_TIMEOUT_MS)
|
||||
.max(MAX_IDA_REQUEST_TIMEOUT_MS)
|
||||
.default(DEFAULT_IDA_REQUEST_TIMEOUT_MS),
|
||||
workspaceRoot: z
|
||||
@@ -78,6 +81,17 @@ const registrationSchema = z
|
||||
/** An upstream MCP registration plus REA's database lifecycle selection. */
|
||||
export type IdaConfiguration = z.infer<typeof registrationSchema>;
|
||||
|
||||
/** Render only schema-owned constraints, never rejected registration values. */
|
||||
const registrationConstraint = (
|
||||
issue: AnalysisInputIssue,
|
||||
): string | undefined => {
|
||||
if (issue.path.length === 1 && issue.path[0] === "timeoutMs")
|
||||
return `timeoutMs must be an integer from ${String(MIN_IDA_REQUEST_TIMEOUT_MS)} to ${String(MAX_IDA_REQUEST_TIMEOUT_MS)} milliseconds`;
|
||||
return issue.message === undefined
|
||||
? undefined
|
||||
: `${issue.path.join(".") || "registration"}: ${issue.message}`;
|
||||
};
|
||||
|
||||
/** Resolved compatibility facts; persisted identities and diagnostics intentionally differ. */
|
||||
export const IDA_COMPATIBILITY_PROFILES = {
|
||||
legacy: {
|
||||
@@ -171,11 +185,10 @@ export const readIdaConfiguration = (
|
||||
const constraints = projectInputIssues(
|
||||
parsed.error.issues,
|
||||
registration,
|
||||
).flatMap((issue) =>
|
||||
issue.message === undefined
|
||||
? []
|
||||
: [`${issue.path.join(".") || "registration"}: ${issue.message}`],
|
||||
);
|
||||
).flatMap((issue) => {
|
||||
const constraint = registrationConstraint(issue);
|
||||
return constraint === undefined ? [] : [constraint];
|
||||
});
|
||||
if (constraints.length === 0)
|
||||
return err(
|
||||
idaConfigurationError(
|
||||
|
||||
@@ -119,6 +119,17 @@ cliTest.for([
|
||||
},
|
||||
constraint: "workspaceRoot must be absolute",
|
||||
},
|
||||
...[0, 2_147_483_648, 1.5, "registration-secret"].map((timeoutMs) => ({
|
||||
name: `invalid timeout ${String(timeoutMs)}`,
|
||||
registration: { command: "provider-must-not-launch", timeoutMs },
|
||||
constraint:
|
||||
"timeoutMs must be an integer from 1 to 2147483647 milliseconds",
|
||||
})),
|
||||
...[1, 2_147_483_647].map((timeoutMs) => ({
|
||||
name: `valid timeout ${String(timeoutMs)}`,
|
||||
registration: { command: "provider-must-not-launch", timeoutMs },
|
||||
constraint: undefined,
|
||||
})),
|
||||
{
|
||||
name: "valid registration",
|
||||
registration: { command: "provider-must-not-launch", args: [] },
|
||||
@@ -156,5 +167,36 @@ cliTest.for([
|
||||
]),
|
||||
});
|
||||
expect(result.stdout).not.toContain("registration-secret");
|
||||
if (constraint?.startsWith("timeoutMs") === true) {
|
||||
const providers = await cli.run({
|
||||
arguments: ["providers", "--json"],
|
||||
environment: { HOME: root, REA_IDA_MCP_CONFIG: path },
|
||||
timeoutMs: 10_000,
|
||||
});
|
||||
expect(providers.exitCode, providers.stderr).toBe(0);
|
||||
expect(providers.json).toMatchObject({
|
||||
analysis_provider_candidates: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
provider: expect.objectContaining({ id: "ida" }),
|
||||
availability: expect.objectContaining({
|
||||
status: "unavailable",
|
||||
code: "open_options_invalid",
|
||||
reason: expect.stringContaining(constraint),
|
||||
diagnostics: expect.objectContaining({
|
||||
configuration_details: expect.objectContaining({
|
||||
settings: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
setting: "REA_IDA_MCP_CONFIG",
|
||||
constraint: expect.stringContaining(constraint),
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
]),
|
||||
});
|
||||
expect(providers.stdout).not.toContain("registration-secret");
|
||||
}
|
||||
},
|
||||
);
|
||||
Reference in new issue
Block a user