GoodBuddy Agents / Validate Agent source (push) Canceled after 0s
GoodBuddy Agents / Build Linux arm64 Agent (push) Canceled after 0s
GoodBuddy Agents / Build Linux x64 Agent (push) Canceled after 0s
Cross-platform packages / Validate source (push) Canceled after 0s
GoodBuddy Agent Release / Authorize Agent release (push) Canceled after 0s
Cross-platform packages / Authorize desktop packaging (push) Canceled after 0s
Cross-platform packages / linux arm64 (push) Canceled after 0s
Cross-platform packages / macos arm64 (push) Canceled after 0s
Cross-platform packages / windows arm64 (push) Canceled after 0s
Cross-platform packages / linux x64 (push) Canceled after 0s
Cross-platform packages / macos x64 (push) Canceled after 0s
Cross-platform packages / windows x64 (push) Canceled after 0s
Cross-platform packages / Publish GitHub and OSS release (push) Canceled after 0s
GoodBuddy Agent Release / Build Linux arm64 compound package (push) Canceled after 0s
GoodBuddy Agent Release / Build Linux x64 compound package (push) Canceled after 0s
GoodBuddy Agent Release / Sign cumulative Agent catalog (push) Canceled after 0s
GoodBuddy Agent Release / Publish Agent to GitHub and OSS (push) Canceled after 0s
The unpublished 0.11.3 candidate could not validate the DeepSeek Harness node-pty prebuilds on every native target, and catalog signing could misread large compound Agent payloads. Release packaging now verifies the rc.8 native layout and writes deterministic stored .gbagent archives with bounded central-directory, mode, CRC, SHA-256, and signature checks. The 0.11.4 recovery also pins reviewed dependency lifecycle scripts, packages the omitted ONNX Runtime license, and carries the approved unpublished notes forward without changing the immutable failed tags or adding a LoongArch package. Release note: 修复跨平台桌面包和大文件 Agent 包的发行校验失败,并将未发布的 0.11.3 内容顺延至 0.11.4。
142 lines
4.0 KiB
JavaScript
142 lines
4.0 KiB
JavaScript
const { readSync } = require('node:fs')
|
|
|
|
const localFileHeaderSignature = 0x04034b50
|
|
const centralDirectoryHeaderSignature = 0x02014b50
|
|
const endOfCentralDirectorySignature = 0x06054b50
|
|
|
|
function readExactZipBytes(handle, length, position, label) {
|
|
const output = Buffer.allocUnsafe(length)
|
|
let offset = 0
|
|
while (offset < length) {
|
|
const bytesRead = readSync(
|
|
handle,
|
|
output,
|
|
offset,
|
|
length - offset,
|
|
position + offset
|
|
)
|
|
if (bytesRead <= 0) {
|
|
throw new Error(`${label} is truncated`)
|
|
}
|
|
offset += bytesRead
|
|
}
|
|
return output
|
|
}
|
|
|
|
function readZipCentralDirectory(handle, archiveSize, limits) {
|
|
if (archiveSize < 22) {
|
|
throw new Error(`${limits.label} central directory is missing`)
|
|
}
|
|
const endSize = Math.min(archiveSize, 65_557)
|
|
const endStart = archiveSize - endSize
|
|
const end = readExactZipBytes(
|
|
handle,
|
|
endSize,
|
|
endStart,
|
|
`${limits.label} end record`
|
|
)
|
|
let endOffset = -1
|
|
for (let index = end.length - 22; index >= 0; index -= 1) {
|
|
if (
|
|
end.readUInt32LE(index) === endOfCentralDirectorySignature &&
|
|
index + 22 + end.readUInt16LE(index + 20) === end.length
|
|
) {
|
|
endOffset = index
|
|
break
|
|
}
|
|
}
|
|
if (endOffset < 0) {
|
|
throw new Error(`${limits.label} central directory is missing`)
|
|
}
|
|
const diskNumber = end.readUInt16LE(endOffset + 4)
|
|
const centralDisk = end.readUInt16LE(endOffset + 6)
|
|
const diskEntryCount = end.readUInt16LE(endOffset + 8)
|
|
const entryCount = end.readUInt16LE(endOffset + 10)
|
|
const centralSize = end.readUInt32LE(endOffset + 12)
|
|
const centralOffset = end.readUInt32LE(endOffset + 16)
|
|
const absoluteEndOffset = endStart + endOffset
|
|
if (
|
|
diskNumber !== 0 ||
|
|
centralDisk !== 0 ||
|
|
diskEntryCount !== entryCount ||
|
|
entryCount === 0 ||
|
|
entryCount === 0xffff ||
|
|
entryCount < limits.minimumEntries ||
|
|
entryCount > limits.maximumEntries ||
|
|
centralSize === 0xffffffff ||
|
|
centralSize < 46 ||
|
|
centralSize > limits.maximumCentralDirectoryBytes ||
|
|
centralOffset === 0xffffffff ||
|
|
centralOffset + centralSize !== absoluteEndOffset
|
|
) {
|
|
throw new Error(`${limits.label} central directory is invalid`)
|
|
}
|
|
const central = readExactZipBytes(
|
|
handle,
|
|
centralSize,
|
|
centralOffset,
|
|
`${limits.label} central directory`
|
|
)
|
|
const entries = []
|
|
let offset = 0
|
|
for (let index = 0; index < entryCount; index += 1) {
|
|
if (
|
|
offset + 46 > central.length ||
|
|
central.readUInt32LE(offset) !==
|
|
centralDirectoryHeaderSignature
|
|
) {
|
|
throw new Error(
|
|
`${limits.label} central directory entry is invalid`
|
|
)
|
|
}
|
|
const nameLength = central.readUInt16LE(offset + 28)
|
|
const extraLength = central.readUInt16LE(offset + 30)
|
|
const commentLength = central.readUInt16LE(offset + 32)
|
|
const entryLength =
|
|
46 + nameLength + extraLength + commentLength
|
|
if (offset + entryLength > central.length) {
|
|
throw new Error(
|
|
`${limits.label} central directory entry exceeds its bounds`
|
|
)
|
|
}
|
|
const flags = central.readUInt16LE(offset + 8)
|
|
const nameBytes = central.subarray(
|
|
offset + 46,
|
|
offset + 46 + nameLength
|
|
)
|
|
const name = new TextDecoder(
|
|
flags & 0x0800 ? 'utf-8' : 'latin1',
|
|
{ fatal: true }
|
|
).decode(nameBytes)
|
|
entries.push({
|
|
name,
|
|
nameBytes: Buffer.from(nameBytes),
|
|
flags,
|
|
compression: central.readUInt16LE(offset + 10),
|
|
checksum: central.readUInt32LE(offset + 16),
|
|
compressedSize: central.readUInt32LE(offset + 20),
|
|
size: central.readUInt32LE(offset + 24),
|
|
diskStart: central.readUInt16LE(offset + 34),
|
|
localOffset: central.readUInt32LE(offset + 42)
|
|
})
|
|
offset += entryLength
|
|
}
|
|
if (offset !== central.length) {
|
|
throw new Error(
|
|
`${limits.label} central directory count is invalid`
|
|
)
|
|
}
|
|
return {
|
|
centralOffset,
|
|
entries
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
centralDirectoryHeaderSignature,
|
|
endOfCentralDirectorySignature,
|
|
localFileHeaderSignature,
|
|
readExactZipBytes,
|
|
readZipCentralDirectory
|
|
}
|