Merge pull request #259 from pikasTech/feat/provider-profile-model-validate
Pipelines as Code CI / agentrun-nc01-v02-ci-d7de515c4724e8e0af0112de46cf79b64690af7d Success

Provider profile validation accepts model
This commit is contained in:
Lyon
2026-07-09 19:59:20 +08:00
committed by GitHub
2 changed files with 21 additions and 4 deletions
+16 -3
View File
@@ -269,6 +269,7 @@ export async function validateProviderProfile(profileValue: string, body: unknow
const record = body === null ? {} : asRecord(body ?? {}, "providerProfileValidation");
const validationId = `val_${randomUUID().replace(/-/gu, "")}`;
const prompt = typeof record.prompt === "string" && record.prompt.trim().length > 0 ? record.prompt.trim() : `只回复 AGENTRUN_PROVIDER_PROFILE_OK_${profile.replace(/[^a-z0-9]/gu, "_").toUpperCase()}`;
const model = optionalModel(record.model);
const run = await options.store.createRun({
tenantId: "hwlab",
projectId: "pikasTech/HWLAB",
@@ -280,7 +281,7 @@ export async function validateProviderProfile(profileValue: string, body: unknow
sessionRef: { sessionId: `sess_${validationId}`, metadata: { purpose: "provider-profile-validation", validationId, profile } },
resourceBundleRef: null,
});
const command = await options.store.createCommand(run.id, { type: "turn", payload: { prompt }, idempotencyKey: validationId });
const command = await options.store.createCommand(run.id, { type: "turn", payload: { prompt, ...(model ? { model } : {}) }, idempotencyKey: validationId });
const runnerJob = await createKubernetesRunnerJob({
store: options.store,
runId: run.id,
@@ -291,7 +292,7 @@ export async function validateProviderProfile(profileValue: string, body: unknow
},
defaults: runnerDefaults,
});
return validationResponse({ profile, validationId, runId: run.id, commandId: command.id, runnerJob, status: "running" });
return validationResponse({ profile, validationId, runId: run.id, commandId: command.id, runnerJob, status: "running", model });
}
export async function getProviderProfileValidation(profileValue: string, validationId: string, options: { store: AgentRunStore }): Promise<JsonRecord> {
@@ -686,13 +687,14 @@ function runnerDefaultsForValidation(options: ProviderProfileValidationOptions,
};
}
function validationResponse(input: { profile: BackendProfile; validationId: string; runId: string; commandId: string; runnerJob: JsonRecord; status: string }): JsonRecord {
function validationResponse(input: { profile: BackendProfile; validationId: string; runId: string; commandId: string; runnerJob: JsonRecord; status: string; model?: string | null }): JsonRecord {
const jobIdentity = asOptionalRecord(input.runnerJob.jobIdentity);
const jobName = typeof jobIdentity?.name === "string" ? jobIdentity.name : typeof input.runnerJob.jobName === "string" ? input.runnerJob.jobName : null;
return {
action: "provider-profile-validation-started",
validationId: input.validationId,
profile: input.profile,
model: input.model ?? null,
runId: input.runId,
commandId: input.commandId,
jobName,
@@ -703,6 +705,17 @@ function validationResponse(input: { profile: BackendProfile; validationId: stri
};
}
function optionalModel(value: unknown): string | null {
if (value === undefined || value === null || value === "") return null;
if (typeof value !== "string") throw new AgentRunError("schema-invalid", "provider profile validation model must be a string", { httpStatus: 400 });
const model = value.trim();
if (model.length === 0) return null;
if (model.length > 128 || !/^[A-Za-z0-9][A-Za-z0-9._:/+-]{0,127}$/u.test(model)) {
throw new AgentRunError("schema-invalid", "provider profile validation model must be a safe model id", { httpStatus: 400 });
}
return model;
}
function validationStatus(result: JsonRecord): string {
const status = typeof result.status === "string" ? result.status : null;
const terminalStatus = typeof result.terminalStatus === "string" ? result.terminalStatus : null;
@@ -343,13 +343,17 @@ process.exit(1);
(error) => error instanceof Error && error.message.includes("not hyueapi.com"),
);
const validation = await client.post("/api/v1/provider-profiles/deepseek/validate", {}) as JsonRecord;
const validation = await client.post("/api/v1/provider-profiles/deepseek/validate", { model: "deepseek-chat", prompt: "只回复 AGENTRUN_PROVIDER_PROFILE_OK_DEEPSEEK" }) as JsonRecord;
assert.equal(validation.profile, "deepseek");
assert.equal(validation.model, "deepseek-chat");
assert.equal(validation.status, "running");
assert.equal(typeof validation.validationId, "string");
const validationId = String(validation.validationId);
const validationRun = await store.getRun(String(validation.runId)) as JsonRecord;
const validationCommand = await store.getCommand(String(validation.commandId)) as JsonRecord;
assert.equal((validationRun.workspaceRef as JsonRecord).path, "/home/agentrun/agentrun-source");
assert.equal((validationCommand.payload as JsonRecord).model, "deepseek-chat");
assert.equal((validationCommand.payload as JsonRecord).prompt, "只回复 AGENTRUN_PROVIDER_PROFILE_OK_DEEPSEEK");
const jobManifest = JSON.parse(await readFile(createdJobPath, "utf8")) as JsonRecord;
assert.equal(JSON.stringify(jobManifest).includes("agentrun-v01-provider-deepseek"), true);
assert.equal(JSON.stringify(jobManifest).includes(secretText), false);