Bladeren bron

fix(packaging): materialize runtime dependencies

Yichen Jiang 2 maanden geleden
bovenliggende
commit
a7e8805340

+ 2 - 2
.agents/notes/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.i18n.yaml

@@ -2,5 +2,5 @@
 # side as of the last confirmed-consistent state. Both languages carry equal authority;
 # after editing either side, bring the other along and re-record with:
 #   pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.md
-2026-07-10-single-file-executable-sdk-runtime-distribution.md: 29aa14db2b3b64cefb7960ee8f316682ba1ac736
-2026-07-10-single-file-executable-sdk-runtime-distribution.zh.md: f10d72b394246e9e57033a5382ec977bdc6f3ab8
+2026-07-10-single-file-executable-sdk-runtime-distribution.md: c2b6d9ff1825915e39738bf8f782c302ecfc1d0d
+2026-07-10-single-file-executable-sdk-runtime-distribution.zh.md: d7758a77083e07b1d2cac99ae2be3f15e6edd2dc

File diff suppressed because it is too large
+ 0 - 1
.agents/notes/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.md


File diff suppressed because it is too large
+ 0 - 1
.agents/notes/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.zh.md


File diff suppressed because it is too large
+ 118 - 112
pnpm-lock.yaml


+ 4 - 0
pnpm-workspace.yaml

@@ -24,6 +24,10 @@ packages:
 # builds must resolve those matching names to this workspace's pinned sources.
 linkWorkspacePackages: true
 
+overrides:
+  '@deepseek-ai/cosmokit': 'link:vendor/cosmokit'
+  '@deepseek-ai/schemastery': 'link:vendor/schemastery'
+
 peerDependencyRules:
   allowedVersions:
     typescript: '>=5 <7'

+ 45 - 1
scripts/build-exe-for-python-sdk.ts

@@ -8,7 +8,7 @@
 
 import { spawn } from 'node:child_process'
 import { existsSync, statSync } from 'node:fs'
-import { chmod, copyFile, cp, mkdir, readFile, rm, writeFile } from 'node:fs/promises'
+import { chmod, copyFile, cp, lstat, mkdir, readFile, readdir, realpath, rm, writeFile } from 'node:fs/promises'
 import { basename, dirname, join, resolve, sep } from 'node:path'
 import { parseArgs } from 'node:util'
 
@@ -259,6 +259,7 @@ class SingleExeBuild {
       this.staging,
     ])
     await this.restoreLegacyHoists()
+    await this.materializeStagedLinks()
     if (this.cli.dryRun) {
       for (const name of DEPLOY_ONLY_DOCS) console.log(`build-exe-for-python-sdk: [dry-run] rm -f ${join(this.staging, name)}`)
     } else {
@@ -311,6 +312,49 @@ class SingleExeBuild {
     }
   }
 
+  /** Replace deploy-time package links with files and reject any remaining link. */
+  private async materializeStagedLinks(): Promise<void> {
+    if (this.cli.dryRun) {
+      console.log('build-exe-for-python-sdk: [dry-run] materialize staged package links')
+      return
+    }
+    const nodeModules = join(this.staging, 'node_modules')
+    let remaining = await this.findSymlink(nodeModules)
+    while (remaining !== undefined) {
+      const segments = remaining.slice(nodeModules.length + 1).split(sep)
+      const binIndex = segments.lastIndexOf('.bin')
+      if (binIndex >= 0) {
+        await rm(join(nodeModules, ...segments.slice(0, binIndex + 1)), { recursive: true, force: true })
+        remaining = await this.findSymlink(nodeModules)
+        continue
+      }
+      const destination = remaining
+      const source = await realpath(destination)
+      const nestedNodeModules = join(source, 'node_modules')
+      await rm(destination, { recursive: true, force: true })
+      await cp(source, destination, {
+        recursive: true,
+        dereference: true,
+        filter: path => path !== nestedNodeModules && !path.startsWith(nestedNodeModules + sep),
+      })
+      remaining = await this.findSymlink(nodeModules)
+    }
+  }
+
+  /** Return the first symbolic link below a directory, if one exists. */
+  private async findSymlink(directory: string): Promise<string | undefined> {
+    for (const entry of await readdir(directory, { withFileTypes: true })) {
+      const path = join(directory, entry.name)
+      const metadata = await lstat(path)
+      if (metadata.isSymbolicLink()) return path
+      if (metadata.isDirectory()) {
+        const nested = await this.findSymlink(path)
+        if (nested !== undefined) return nested
+      }
+    }
+    return undefined
+  }
+
   /** Add the executable entry and pkg assets to the staged manifest. */
   async injectPkgConfig(): Promise<void> {
     const patch = { bin: ENTRY_BIN, pkg: { assets: ASSET_GLOBS } }

Some files were not shown because too many files changed in this diff