@standardagents/code 0.14.1-issue.658.a1599e → 0.14.1-issue.663.d242d1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/artifact.mjs CHANGED
@@ -84,6 +84,24 @@ export function verifyArtifactTree(root, files, metadata = ['manifest.json', 'ma
84
84
  }
85
85
  }
86
86
 
87
+ // Check a native signed archive's listing before extraction: `names` from
88
+ // `tar -tzf` and the entry type letters from `tar -tvzf`. The archive must be
89
+ // exactly one of the signed layouts, with only regular files and the
90
+ // directories those files need. Returns the matching file list.
91
+ export function nativeArchiveLayout(names, types) {
92
+ const listed = names.map(name => name.replace(/^\.\//, '')).sort()
93
+ const layout = [ARTIFACT_FILES, BUNDLE_ARTIFACT_FILES, RUNNER_ARTIFACT_FILES, BUNDLE_RUNNER_ARTIFACT_FILES].find(files => {
94
+ const expected = [...artifactDirectories(files).map(path => `${path}/`), ...files, 'manifest.json', 'manifest.sig'].sort()
95
+ return listed.join('\n') === expected.join('\n')
96
+ })
97
+ if (!layout) throw new Error('native artifact archive has unexpected paths')
98
+ const expectedTypes = '-'.repeat(layout.length + 2) + 'd'.repeat(artifactDirectories(layout).length)
99
+ if ([...types].sort().join('') !== expectedTypes) {
100
+ throw new Error('native artifact archive must contain only regular files and expected directories')
101
+ }
102
+ return layout
103
+ }
104
+
87
105
  // The four native targets the launcher has ever installed. The two deferred
88
106
  // ones stay so their published history verifies.
89
107
  export const NATIVE_ARTIFACT_TARGETS = Object.freeze([
@@ -0,0 +1,93 @@
1
+ import { spawnSync } from 'node:child_process'
2
+ import { createHash, randomUUID } from 'node:crypto'
3
+ import { chmodSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs'
4
+ import { join } from 'node:path'
5
+ import { fileURLToPath } from 'node:url'
6
+
7
+ import { artifactBinaryPath, nativeArchiveLayout, verifyNativeArtifact } from './artifact.mjs'
8
+
9
+ // A release's root package names each native target's signed archive in
10
+ // `standardArtifacts`; npm only selects the platform. The archive downloads
11
+ // from the build coordinator, which serves it from R2, and installs under this
12
+ // package's `native/<target>/` once its size, digest, layout, and signed
13
+ // manifest all check out. The daemon's launcher repair finds it there too.
14
+ export const ARTIFACT_ORIGIN = 'https://builds.standardcode.ai'
15
+ const MAX_ARCHIVE = 128 * 1024 * 1024
16
+ const PACKAGE_ROOT = fileURLToPath(new URL('..', import.meta.url))
17
+
18
+ export function nativeDirectory(target, root = PACKAGE_ROOT) {
19
+ return join(root, 'native', target)
20
+ }
21
+
22
+ export function packageMetadata(root = PACKAGE_ROOT) {
23
+ return JSON.parse(readFileSync(join(root, 'package.json'), 'utf8'))
24
+ }
25
+
26
+ // The signed archive a package names for `target`, or null when its binaries
27
+ // install as an npm platform package instead.
28
+ export function artifactPointer(metadata, target) {
29
+ const artifacts = metadata.standardArtifacts
30
+ if (artifacts === undefined) return null
31
+ const pointer = artifacts?.schema === 1 ? artifacts.targets?.[target] : undefined
32
+ if (!pointer
33
+ || pointer.url !== `${ARTIFACT_ORIGIN}/artifacts/${metadata.version}/${target}.tar.gz`
34
+ || !/^[0-9a-f]{64}$/.test(pointer.sha256 ?? '')
35
+ || !Number.isSafeInteger(pointer.size) || pointer.size < 1 || pointer.size > MAX_ARCHIVE) {
36
+ throw new Error(`This package names no valid native archive for ${target}`)
37
+ }
38
+ return pointer
39
+ }
40
+
41
+ // The installed, verified artifact directory for `target`, or null.
42
+ export function installedArtifact(target, root = PACKAGE_ROOT, publicKey = undefined) {
43
+ const directory = nativeDirectory(target, root)
44
+ try {
45
+ return { directory, manifest: verifyNativeArtifact(directory, { version: packageMetadata(root).version, target }, publicKey) }
46
+ } catch {
47
+ return null
48
+ }
49
+ }
50
+
51
+ function tar(run, args) {
52
+ const result = run('tar', args, { encoding: 'utf8', maxBuffer: 16 * 1024 * 1024 })
53
+ if (result.error) throw result.error
54
+ if (result.status !== 0) throw new Error(`tar ${args[0]} failed: ${result.stderr}`)
55
+ return result.stdout
56
+ }
57
+
58
+ export async function installNativeArtifact({ target, root = PACKAGE_ROOT, fetchImplementation = fetch, run = spawnSync, publicKey = undefined }) {
59
+ const installed = installedArtifact(target, root, publicKey)
60
+ if (installed) return installed.directory
61
+ const metadata = packageMetadata(root)
62
+ const pointer = artifactPointer(metadata, target)
63
+ if (!pointer) throw new Error(`This package carries no native archive for ${target}`)
64
+ const response = await fetchImplementation(pointer.url)
65
+ if (!response.ok) throw new Error(`Downloading the native archive failed with HTTP ${response.status}`)
66
+ const bytes = Buffer.from(await response.arrayBuffer())
67
+ if (bytes.length !== pointer.size || createHash('sha256').update(bytes).digest('hex') !== pointer.sha256) {
68
+ throw new Error('The downloaded native archive does not match its published size and digest')
69
+ }
70
+ const work = join(root, 'native', `.install-${randomUUID()}`)
71
+ mkdirSync(work, { recursive: true, mode: 0o700 })
72
+ try {
73
+ const archive = join(work, 'archive.tar.gz')
74
+ writeFileSync(archive, bytes, { mode: 0o600, flag: 'wx' })
75
+ nativeArchiveLayout(
76
+ tar(run, ['-tzf', archive]).trim().split('\n'),
77
+ tar(run, ['-tvzf', archive]).trim().split('\n').map(line => line[0]),
78
+ )
79
+ const extracted = join(work, 'artifact')
80
+ mkdirSync(extracted, { mode: 0o700 })
81
+ tar(run, ['-xzf', archive, '-C', extracted])
82
+ const manifest = verifyNativeArtifact(extracted, { version: metadata.version, target }, publicKey)
83
+ for (const command of ['standard', 'standardd', 'tmux']) {
84
+ chmodSync(join(extracted, artifactBinaryPath(manifest, command)), 0o755)
85
+ }
86
+ const destination = nativeDirectory(target, root)
87
+ rmSync(destination, { recursive: true, force: true })
88
+ renameSync(extracted, destination)
89
+ return destination
90
+ } finally {
91
+ rmSync(work, { recursive: true, force: true })
92
+ }
93
+ }
package/lib/launcher.mjs CHANGED
@@ -6,6 +6,7 @@ import process from 'node:process'
6
6
 
7
7
  import { platformPackage } from './platform.mjs'
8
8
  import { artifactBinaryPath, requireCompatibleGlibc, verifyNativeArtifact } from './artifact.mjs'
9
+ import { artifactPointer, installNativeArtifact, installedArtifact, packageMetadata } from './install.mjs'
9
10
 
10
11
  const require = createRequire(import.meta.url)
11
12
  const COMMANDS = new Set(['standard', 'standardd'])
@@ -33,11 +34,18 @@ function resolvePackagedBinary(command, options) {
33
34
  options.report,
34
35
  )
35
36
  const resolve = options.resolve ?? require.resolve
37
+ const report = options.report ?? process.report
38
+ // A release that carries no binaries on npm installs its signed R2 archive
39
+ // under this package instead (see install.mjs).
40
+ const downloaded = installedArtifact(platform.rustTarget, options.packageRoot)
41
+ if (downloaded) {
42
+ requireCompatibleGlibc(downloaded.manifest, report?.getReport()?.header?.glibcVersionRuntime)
43
+ return join(downloaded.directory, artifactBinaryPath(downloaded.manifest, command))
44
+ }
36
45
  try {
37
46
  const root = dirname(realpathSync(resolve(`${platform.packageName}/manifest.json`)))
38
47
  const version = JSON.parse(readFileSync(new URL('../package.json', import.meta.url))).version
39
48
  const artifact = verifyNativeArtifact(root, { version, target: platform.rustTarget })
40
- const report = options.report ?? process.report
41
49
  requireCompatibleGlibc(artifact, report?.getReport()?.header?.glibcVersionRuntime)
42
50
  return join(root, artifactBinaryPath(artifact, command))
43
51
  } catch (error) {
@@ -57,8 +65,27 @@ export function spawnBinary(command, args, options = {}) {
57
65
  })
58
66
  }
59
67
 
60
- export function main(command) {
68
+ // Install this platform's signed R2 archive when the package names one and
69
+ // has no binaries installed yet. Package managers that skip install scripts
70
+ // (pnpm by default) reach this on the first launch instead of postinstall.
71
+ export async function ensureNativeBinaries(options = {}) {
72
+ if (options.environment?.STANDARD_CODE_BINARY_DIR ?? process.env.STANDARD_CODE_BINARY_DIR) return
73
+ const platform = platformPackage(options.platform, options.architecture, options.report)
74
+ if (installedArtifact(platform.rustTarget, options.packageRoot)) return
75
+ if (!artifactPointer(packageMetadata(options.packageRoot), platform.rustTarget)) return
76
+ try {
77
+ const resolve = options.resolve ?? require.resolve
78
+ resolve(`${platform.packageName}/manifest.json`)
79
+ return
80
+ } catch {
81
+ // No npm platform package: download the archive.
82
+ }
83
+ await installNativeArtifact({ target: platform.rustTarget, root: options.packageRoot, fetchImplementation: options.fetchImplementation })
84
+ }
85
+
86
+ export async function main(command) {
61
87
  try {
88
+ await ensureNativeBinaries()
62
89
  const result = spawnBinary(command, process.argv.slice(2))
63
90
  if (result.error) throw result.error
64
91
  if (result.signal) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@standardagents/code",
3
- "version": "0.14.1-issue.658.a1599e",
3
+ "version": "0.14.1-issue.663.d242d1",
4
4
  "description": "Platform launcher for the Standard universal terminal network.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
@@ -27,9 +27,20 @@
27
27
  "scripts": {
28
28
  "postinstall": "node postinstall.mjs"
29
29
  },
30
- "optionalDependencies": {
31
- "@standardagents/code-darwin-arm64": "npm:@standardagents/code@0.14.1-issue.658.a1599e-darwin-arm64",
32
- "@standardagents/code-linux-x64-gnu": "npm:@standardagents/code@0.14.1-issue.658.a1599e-linux-x64-gnu"
30
+ "standardArtifacts": {
31
+ "schema": 1,
32
+ "targets": {
33
+ "aarch64-apple-darwin": {
34
+ "url": "https://builds.standardcode.ai/artifacts/0.14.1-issue.663.d242d1/aarch64-apple-darwin.tar.gz",
35
+ "sha256": "d58162d7f9026e37502fcc2e621027015288840f6c4973a53377fad0f61cc8bd",
36
+ "size": 22595079
37
+ },
38
+ "x86_64-unknown-linux-gnu": {
39
+ "url": "https://builds.standardcode.ai/artifacts/0.14.1-issue.663.d242d1/x86_64-unknown-linux-gnu.tar.gz",
40
+ "sha256": "af952fb65cb663f69e120884d85546502f4a8725e5ce85c41c72b423cb1ed13f",
41
+ "size": 28080928
42
+ }
43
+ }
33
44
  },
34
45
  "standardUpgrade": {
35
46
  "schema": 1,
package/postinstall.mjs CHANGED
@@ -1,7 +1,14 @@
1
1
  import { chmodSync } from 'node:fs'
2
2
 
3
- import { resolveBinary } from './lib/launcher.mjs'
3
+ import { ensureNativeBinaries, resolveBinary } from './lib/launcher.mjs'
4
4
 
5
+ try {
6
+ await ensureNativeBinaries()
7
+ } catch (error) {
8
+ // The first launch retries the download.
9
+ const detail = error instanceof Error ? error.message : String(error)
10
+ console.warn(`@standardagents/code: ${detail}`)
11
+ }
5
12
  for (const command of ['standard', 'standardd']) {
6
13
  try {
7
14
  chmodSync(resolveBinary(command), 0o755)