fix: let team members correct handshake contracts
This commit is contained in:
parent
f4977ee9f7
commit
1340927b73
2 changed files with 69 additions and 10 deletions
|
|
@ -88,6 +88,7 @@ async function modelAcknowledge({
|
||||||
config,
|
config,
|
||||||
identity,
|
identity,
|
||||||
challenge,
|
challenge,
|
||||||
|
validatorError = null,
|
||||||
fetchImpl = globalThis.fetch,
|
fetchImpl = globalThis.fetch,
|
||||||
}) {
|
}) {
|
||||||
const response = await fetchImpl(completionEndpoint(config.apiUrl), {
|
const response = await fetchImpl(completionEndpoint(config.apiUrl), {
|
||||||
|
|
@ -121,6 +122,7 @@ async function modelAcknowledge({
|
||||||
caller_nonce: challenge.caller_nonce,
|
caller_nonce: challenge.caller_nonce,
|
||||||
role_acknowledged: true,
|
role_acknowledged: true,
|
||||||
},
|
},
|
||||||
|
validator_error_from_previous_attempt: validatorError,
|
||||||
scoped_duties: challenge.scoped_duties,
|
scoped_duties: challenge.scoped_duties,
|
||||||
identity_source: identity,
|
identity_source: identity,
|
||||||
}),
|
}),
|
||||||
|
|
@ -213,16 +215,27 @@ function createMemberRuntime(config, options = {}) {
|
||||||
) {
|
) {
|
||||||
throw new Error("invalid_team_scope");
|
throw new Error("invalid_team_scope");
|
||||||
}
|
}
|
||||||
const acknowledgement = validateAcknowledgement(
|
let acknowledgement = null;
|
||||||
|
let validatorError = null;
|
||||||
|
for (let attempt = 1; attempt <= 3; attempt += 1) {
|
||||||
|
try {
|
||||||
|
acknowledgement = validateAcknowledgement(
|
||||||
await modelAcknowledge({
|
await modelAcknowledge({
|
||||||
config,
|
config,
|
||||||
identity,
|
identity,
|
||||||
challenge,
|
challenge,
|
||||||
|
validatorError,
|
||||||
fetchImpl: options.fetchImpl,
|
fetchImpl: options.fetchImpl,
|
||||||
}),
|
}),
|
||||||
config,
|
config,
|
||||||
challenge,
|
challenge,
|
||||||
);
|
);
|
||||||
|
break;
|
||||||
|
} catch (error) {
|
||||||
|
validatorError = String(error.message || error).slice(0, 200);
|
||||||
|
if (attempt === 3) throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
const payload = {
|
const payload = {
|
||||||
schema: "guanghu.persona-team-member-handshake-payload/v1",
|
schema: "guanghu.persona-team-member-handshake-payload/v1",
|
||||||
persona_id: config.personaId,
|
persona_id: config.personaId,
|
||||||
|
|
|
||||||
|
|
@ -139,6 +139,52 @@ test("member runtime rejects an unscoped or wrong-controller challenge", async (
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("member model gets a bounded retry with the exact validator error", async () => {
|
||||||
|
const { root, config } = fixture();
|
||||||
|
let attempts = 0;
|
||||||
|
let observedValidatorError = null;
|
||||||
|
try {
|
||||||
|
const runtime = createMemberRuntime(config, {
|
||||||
|
fetchImpl: async (_url, request) => {
|
||||||
|
attempts += 1;
|
||||||
|
const body = JSON.parse(request.body);
|
||||||
|
const input = JSON.parse(body.messages[1].content);
|
||||||
|
observedValidatorError =
|
||||||
|
input.validator_error_from_previous_attempt || observedValidatorError;
|
||||||
|
const acknowledgement = {
|
||||||
|
...input.exact_contract,
|
||||||
|
independent_subject_boundary: "归灯不是铸渊的副本。",
|
||||||
|
human_boundary: "不冒充冰朔。",
|
||||||
|
current_model_boundary: "当前模型是可替换运行位。",
|
||||||
|
...(attempts > 1
|
||||||
|
? { responsibility_ack: "只接受本轮列出的有界职责。" }
|
||||||
|
: {}),
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
async json() {
|
||||||
|
return {
|
||||||
|
choices: [
|
||||||
|
{ message: { content: JSON.stringify(acknowledgement) } },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const response = await runtime.handshake({
|
||||||
|
caller_nonce: "ZY-TEAM-CHALLENGE-RETRY-0001",
|
||||||
|
team_controller_id: "ICE-P-ZY001",
|
||||||
|
scoped_duties: ["执行确定性部署预检"],
|
||||||
|
});
|
||||||
|
assert.equal(response.ok, true);
|
||||||
|
assert.equal(attempts, 2);
|
||||||
|
assert.equal(observedValidatorError, "ack_responsibility_ack_missing");
|
||||||
|
} finally {
|
||||||
|
fs.rmSync(root, { recursive: true, force: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
test("all three member handshake packages pass the resident deployment policy", () => {
|
test("all three member handshake packages pass the resident deployment policy", () => {
|
||||||
const root = path.resolve(path.dirname(new URL(import.meta.url).pathname), "../..");
|
const root = path.resolve(path.dirname(new URL(import.meta.url).pathname), "../..");
|
||||||
const packages = [
|
const packages = [
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue