Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions .github/workflows/desktop-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -116,16 +116,12 @@ jobs:
p12-file-base64: ${{ secrets.APPLE_CERTIFICATE }}
p12-password: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}

- name: Prebuild
working-directory: packages/desktop
env:
DEEPAGENT_CODE_CHANNEL: ${{ github.event_name == 'push' && 'prod' || (github.event.inputs.channel || 'prod') }}
run: bun run prebuild

# bun run build invokes the package prebuild lifecycle before electron-vite.
- name: Build renderer
working-directory: packages/desktop
env:
DEEPAGENT_CODE_CHANNEL: ${{ github.event_name == 'push' && 'prod' || (github.event.inputs.channel || 'prod') }}
NODE_OPTIONS: --max-old-space-size=4096
run: bun run build

- name: Package
Expand Down
3 changes: 2 additions & 1 deletion bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion packages/deepagent-code/script/build-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const result = await Bun.build({
outdir: "./dist/node",
format: "esm",
sourcemap: "linked",
external: ["jsonc-parser", "@lydell/node-pty"],
external: ["@lydell/node-pty", "jsonc-parser"],
define: {
DEEPAGENT_CODE_MODELS_DEV: generated.modelsData,
DEEPAGENT_CODE_CHANNEL: `'${Script.channel}'`,
Expand All @@ -43,6 +43,12 @@ const unsupportedBunAPIs = [...new Set(source.match(/\bBun\.[A-Za-z_$][A-Za-z0-9
if (unsupportedBunAPIs.length > 0) {
throw new Error(`Node server bundle contains Bun-only runtime APIs: ${unsupportedBunAPIs.join(", ")}`)
}
if (!source.includes('from "@lydell/node-pty"')) {
throw new Error("Node server bundle does not import the node-pty platform selector")
}
if (!source.includes('from "jsonc-parser"')) {
throw new Error("Node server bundle does not import the external jsonc-parser runtime dependency")
}
await Bun.write(
bundle,
source
Expand Down
33 changes: 14 additions & 19 deletions packages/desktop/electron.vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { sentryVitePlugin } from "@sentry/vite-plugin"
import { defineConfig } from "electron-vite"
import appPlugin from "@deepagent-code/app/vite"
import * as fs from "node:fs/promises"
import { copyFile, cp, mkdir, readdir, rm } from "node:fs/promises"

const DEEPAGENT_CODE_SERVER_DIST = "../deepagent-code/dist/node"
const DOMAIN_PACKS_DIST = "../domain-packs"
Expand All @@ -13,8 +13,6 @@ const channel = (() => {
return "dev"
})()

const nodePtyPkg = `@lydell/node-pty-${process.platform}-${process.arch}`

const sentry =
process.env.SENTRY_AUTH_TOKEN && process.env.SENTRY_ORG && process.env.SENTRY_PROJECT
? sentryVitePlugin({
Expand All @@ -32,7 +30,7 @@ const sentry =
})
: false

export default defineConfig({
export default defineConfig(({ command }) => ({
main: {
define: {
"import.meta.env.DEEPAGENT_CODE_CHANNEL": JSON.stringify(channel),
Expand All @@ -41,32 +39,29 @@ export default defineConfig({
rollupOptions: {
input: { index: "src/main/index.ts", sidecar: "src/main/sidecar.ts" },
},
externalizeDeps: { include: [nodePtyPkg] },
externalizeDeps: { include: ["@lydell/node-pty"] },
},
plugins: [
{
name: "deepagent-code:node-pty-narrower",
enforce: "pre",
resolveId(s) {
if (s === "@lydell/node-pty") return nodePtyPkg
},
},
{
name: "deepagent-code:virtual-server-module",
enforce: "pre",
resolveId(id) {
if (id === "virtual:deepagent-code-server") return this.resolve(`${DEEPAGENT_CODE_SERVER_DIST}/node.js`)
if (id !== "virtual:deepagent-code-server") return
if (command === "build") return { id: "./chunks/node.js", external: true }
return this.resolve(`${DEEPAGENT_CODE_SERVER_DIST}/node.js`)
},
},
{
name: "deepagent-code:copy-server-assets",
async writeBundle() {
for (const l of await fs.readdir(DEEPAGENT_CODE_SERVER_DIST)) {
if (!l.endsWith(".wasm")) continue
await fs.writeFile(`./out/main/chunks/${l}`, await fs.readFile(`${DEEPAGENT_CODE_SERVER_DIST}/${l}`))
await mkdir("./out/main/chunks", { recursive: true })
for (const file of await readdir(DEEPAGENT_CODE_SERVER_DIST)) {
if (!file.endsWith(".wasm") && (command !== "build" || (file !== "node.js" && file !== "node.js.map")))
continue
await copyFile(`${DEEPAGENT_CODE_SERVER_DIST}/${file}`, `./out/main/chunks/${file}`)
}
await fs.rm("./out/main/domain-packs", { recursive: true, force: true })
await fs.cp(DOMAIN_PACKS_DIST, "./out/main/domain-packs", { recursive: true })
await rm("./out/main/domain-packs", { recursive: true, force: true })
await cp(DOMAIN_PACKS_DIST, "./out/main/domain-packs", { recursive: true })
},
},
],
Expand Down Expand Up @@ -95,4 +90,4 @@ export default defineConfig({
},
},
},
})
}))
5 changes: 3 additions & 2 deletions packages/desktop/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"predev": "bun ./scripts/predev.ts",
"dev": "electron-vite dev",
"prebuild": "bun ./scripts/prebuild.ts",
"build": "electron-vite build",
"build": "electron-vite build && bun ./scripts/audit-server-bundle.ts",
"preview": "electron-vite preview",
"test": "bun test ./src",
"test:ci": "mkdir -p .artifacts/unit && bun test ./src --reporter=junit --reporter-outfile=.artifacts/unit/junit.xml",
Expand All @@ -37,18 +37,19 @@
"main": "./out/main/index.js",
"dependencies": {
"@deepagent-code/core": "workspace:*",
"@lydell/node-pty": "catalog:",
"@zip.js/zip.js": "2.7.62",
"effect": "catalog:",
"electron-context-menu": "4.1.2",
"electron-log": "^5",
"electron-store": "^10",
"electron-updater": "^6",
"electron-window-state": "^5.0.3",
"jsonc-parser": "3.3.1",
"marked": "^15"
},
"devDependencies": {
"@actions/artifact": "4.0.0",
"@lydell/node-pty": "catalog:",
"@deepagent-code/app": "workspace:*",
"@deepagent-code/ui": "workspace:*",
"@jridgewell/trace-mapping": "0.3.31",
Expand Down
35 changes: 35 additions & 0 deletions packages/desktop/scripts/audit-server-bundle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/usr/bin/env bun

import { strict as assert } from "node:assert"
import { readdir } from "node:fs/promises"
import path from "node:path"

const chunks = path.resolve("out/main/chunks")
const sidecar = await Bun.file(path.resolve("out/main/sidecar.js")).text()
const server = Bun.file(path.join(chunks, "node.js"))
const sourceMap = Bun.file(path.join(chunks, "node.js.map"))
const files = await readdir(chunks)

assert.match(sidecar, /import\(["']\.\/chunks\/node\.js["']\)/, "sidecar must load the external server bundle")
assert.equal(await server.exists(), true, "external server bundle is missing")
assert.equal(await sourceMap.exists(), true, "external server source map is missing")
assert.deepEqual(
files.filter((file) => /^node-.+\.js$/.test(file)),
[],
"Rollup must not emit a transformed copy of the server bundle",
)

const source = await server.text()
assert.match(source, /sourceMappingURL=node\.js\.map/, "external server bundle is not linked to its source map")
assert.equal(
source.includes('from "@lydell/node-pty"'),
true,
"external server bundle does not use the packaged node-pty platform selector",
)
assert.equal(
source.includes('from "jsonc-parser"') || source.includes("from 'jsonc-parser'"),
true,
"external server bundle does not declare its packaged jsonc-parser dependency",
)

console.log(`External server bundle verified: ${Math.ceil(server.size / 1024 / 1024)} MiB`)
Loading