源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
import { createHash } from "node:crypto";
|
||||
import { readFileSync, writeFileSync } from "node:fs";
|
||||
import { dirname, resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const scriptDir = dirname(fileURLToPath(import.meta.url));
|
||||
const repoRoot = resolve(scriptDir, "../..");
|
||||
const schemaPath = resolve(
|
||||
repoRoot,
|
||||
"packages/agent/daemon/liveprotocol/schema/agent-activity-live-event.schema.json"
|
||||
);
|
||||
const wireContractPath = resolve(
|
||||
repoRoot,
|
||||
"packages/agent/daemon/liveprotocol/schema/agent-activity-live-wire-contract.json"
|
||||
);
|
||||
const canonicalPath = resolve(
|
||||
repoRoot,
|
||||
"packages/events/protocol/definitions/agent/activity.updated.event.json"
|
||||
);
|
||||
const goOutputPath = resolve(
|
||||
repoRoot,
|
||||
"packages/agent/daemon/liveprotocol/protocol_revision.gen.go"
|
||||
);
|
||||
const tsOutputPath = resolve(
|
||||
repoRoot,
|
||||
"packages/agent/activity-core/src/liveProtocolRevision.gen.ts"
|
||||
);
|
||||
const checkOnly = process.argv.includes("--check");
|
||||
|
||||
const liveSchema = JSON.parse(readFileSync(schemaPath, "utf8"));
|
||||
const wireContract = JSON.parse(readFileSync(wireContractPath, "utf8"));
|
||||
const canonicalDefinition = JSON.parse(readFileSync(canonicalPath, "utf8"));
|
||||
const canonicalVariants = [
|
||||
"session_audit",
|
||||
"turn_update",
|
||||
"interaction_update"
|
||||
].map((eventType) => {
|
||||
const variant = canonicalDefinition.payloadSchema.oneOf.find(
|
||||
(candidate) => candidate?.properties?.eventType?.const === eventType
|
||||
);
|
||||
if (!variant) {
|
||||
throw new Error(`canonical agent activity schema is missing ${eventType}`);
|
||||
}
|
||||
return variant;
|
||||
});
|
||||
validateWireContract(wireContract);
|
||||
const digest = createHash("sha256")
|
||||
.update(JSON.stringify({ liveSchema, wireContract, canonicalVariants }))
|
||||
.digest("hex")
|
||||
.slice(0, 16);
|
||||
const revision = `sha256:${digest}`;
|
||||
const goWireFieldConstants = [
|
||||
...wireContract.frameFields,
|
||||
...wireContract.deliveryFields
|
||||
];
|
||||
const goWireFieldConstantWidth = Math.max(
|
||||
...goWireFieldConstants.map((field) => field.goConstant.length)
|
||||
);
|
||||
const goWireFieldDeclarations = goWireFieldConstants
|
||||
.map(
|
||||
(field) =>
|
||||
`\t${field.goConstant.padEnd(goWireFieldConstantWidth)} = ${field.number} // ${field.name}: ${field.wireType}`
|
||||
)
|
||||
.join("\n");
|
||||
const goDeliveryKindConstantWidth = Math.max(
|
||||
...wireContract.deliveryKinds.map((kind) => kind.goConstant.length)
|
||||
);
|
||||
const goDeliveryKindConstants = wireContract.deliveryKinds
|
||||
.map(
|
||||
(kind) =>
|
||||
`\t${kind.goConstant.padEnd(goDeliveryKindConstantWidth)} DeliveryKind = ${kind.value} // payload: ${kind.payloadField}`
|
||||
)
|
||||
.join("\n");
|
||||
|
||||
const outputs = new Map([
|
||||
[
|
||||
goOutputPath,
|
||||
`// Code generated by tools/scripts/generate-agent-live-protocol.mjs. DO NOT EDIT.
|
||||
|
||||
package liveprotocol
|
||||
|
||||
const ProtocolRevision = ${JSON.stringify(revision)}
|
||||
|
||||
// Protobuf-wire field numbers and delivery kinds are generated from
|
||||
// schema/agent-activity-live-wire-contract.json. They participate in
|
||||
// ProtocolRevision and must not be edited independently.
|
||||
const (
|
||||
${goWireFieldDeclarations}
|
||||
)
|
||||
|
||||
const (
|
||||
${goDeliveryKindConstants}
|
||||
)
|
||||
`
|
||||
],
|
||||
[
|
||||
tsOutputPath,
|
||||
`// Code generated by tools/scripts/generate-agent-live-protocol.mjs. DO NOT EDIT.
|
||||
|
||||
export const AGENT_ACTIVITY_LIVE_PROTOCOL_REVISION =
|
||||
${JSON.stringify(revision)} as const;
|
||||
`
|
||||
]
|
||||
]);
|
||||
|
||||
for (const [path, expected] of outputs) {
|
||||
if (checkOnly) {
|
||||
const actual = readFileSync(path, "utf8");
|
||||
if (actual !== expected) {
|
||||
throw new Error(
|
||||
`${path} is stale; run pnpm generate:agent-live-protocol`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
writeFileSync(path, expected);
|
||||
}
|
||||
}
|
||||
|
||||
function validateWireContract(contract) {
|
||||
if (
|
||||
contract?.encoding !== "protobuf-wire" ||
|
||||
!Array.isArray(contract.frameFields) ||
|
||||
!Array.isArray(contract.deliveryFields) ||
|
||||
!Array.isArray(contract.deliveryKinds) ||
|
||||
typeof contract.controls !== "object" ||
|
||||
contract.controls === null
|
||||
) {
|
||||
throw new Error("Agent live wire contract has an invalid root shape");
|
||||
}
|
||||
|
||||
validateNumberedEntries(contract.frameFields, "frame field");
|
||||
validateNumberedEntries(contract.deliveryFields, "delivery field");
|
||||
validateNumberedEntries(contract.deliveryKinds, "delivery kind", "value");
|
||||
|
||||
const deliveryFieldNames = new Set(
|
||||
contract.deliveryFields.map((field) => field.name)
|
||||
);
|
||||
for (const kind of contract.deliveryKinds) {
|
||||
if (!deliveryFieldNames.has(kind.payloadField)) {
|
||||
throw new Error(
|
||||
`delivery kind ${kind.name} references unknown payload field ${kind.payloadField}`
|
||||
);
|
||||
}
|
||||
}
|
||||
for (const requiredControl of [
|
||||
"discontinuity",
|
||||
"attachmentChanged",
|
||||
"attachmentCaughtUp",
|
||||
"goalChanged",
|
||||
"streamReady",
|
||||
"rejected"
|
||||
]) {
|
||||
if (!(requiredControl in contract.controls)) {
|
||||
throw new Error(`wire contract is missing ${requiredControl} control`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function validateNumberedEntries(entries, label, numberKey = "number") {
|
||||
const names = new Set();
|
||||
const constants = new Set();
|
||||
const numbers = new Set();
|
||||
for (const entry of entries) {
|
||||
if (
|
||||
typeof entry?.name !== "string" ||
|
||||
entry.name.length === 0 ||
|
||||
typeof entry?.goConstant !== "string" ||
|
||||
entry.goConstant.length === 0 ||
|
||||
!Number.isSafeInteger(entry?.[numberKey]) ||
|
||||
entry[numberKey] <= 0
|
||||
) {
|
||||
throw new Error(`${label} has an invalid declaration`);
|
||||
}
|
||||
if (
|
||||
names.has(entry.name) ||
|
||||
constants.has(entry.goConstant) ||
|
||||
numbers.has(entry[numberKey])
|
||||
) {
|
||||
throw new Error(`${label} declarations must be unique`);
|
||||
}
|
||||
names.add(entry.name);
|
||||
constants.add(entry.goConstant);
|
||||
numbers.add(entry[numberKey]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user