feat: switch to local claude-code-acp package and remove screen transition animations

This commit is contained in:
Mohamed Boudra
2025-10-24 18:10:12 +02:00
parent dd4fa90c5a
commit 8d93eeb5c5
6 changed files with 110 additions and 553 deletions

575
package-lock.json generated
View File

@@ -16,6 +16,39 @@
"typescript": "^5.9.3" "typescript": "^5.9.3"
} }
}, },
"../claude-code-acp": {
"name": "@boudra/claude-code-acp",
"version": "0.8.1",
"license": "Apache-2.0",
"dependencies": {
"@agentclientprotocol/sdk": "0.4.9",
"@anthropic-ai/claude-agent-sdk": "0.1.23",
"@anthropic-ai/claude-code": "2.0.24",
"@modelcontextprotocol/sdk": "1.20.1",
"diff": "8.0.2",
"express": "5.1.0",
"uuid": "13.0.0"
},
"bin": {
"claude-code-acp": "dist/index.js"
},
"devDependencies": {
"@anthropic-ai/sdk": "^0.67.0",
"@types/express": "5.0.3",
"@types/node": "24.9.1",
"@types/uuid": "10.0.0",
"@typescript-eslint/eslint-plugin": "8.46.2",
"@typescript-eslint/parser": "8.46.2",
"@vitest/ui": "3.2.4",
"eslint": "9.38.0",
"eslint-config-prettier": "10.1.8",
"globals": "16.4.0",
"prettier": "3.6.2",
"ts-node": "10.9.2",
"typescript": "5.9.3",
"vitest": "3.2.4"
}
},
"../expo-two-way-audio": { "../expo-two-way-audio": {
"name": "@boudra/expo-two-way-audio", "name": "@boudra/expo-two-way-audio",
"version": "0.1.4", "version": "0.1.4",
@@ -135,46 +168,6 @@
"zod": "^3.25.76 || ^4.1.8" "zod": "^3.25.76 || ^4.1.8"
} }
}, },
"node_modules/@anthropic-ai/claude-agent-sdk": {
"version": "0.1.23",
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.1.23.tgz",
"integrity": "sha512-DktXOjzS2hOuuj2Zpo7fEooONfMa5bm09pt1/Vt4vn30YugELoezn/ZQ/TG5uSQ7+Zl/ElxAvi4vGDorj1Tirg==",
"license": "SEE LICENSE IN README.md",
"engines": {
"node": ">=18.0.0"
},
"optionalDependencies": {
"@img/sharp-darwin-arm64": "^0.33.5",
"@img/sharp-darwin-x64": "^0.33.5",
"@img/sharp-linux-arm": "^0.33.5",
"@img/sharp-linux-arm64": "^0.33.5",
"@img/sharp-linux-x64": "^0.33.5",
"@img/sharp-win32-x64": "^0.33.5"
},
"peerDependencies": {
"zod": "^3.24.1"
}
},
"node_modules/@anthropic-ai/claude-code": {
"version": "2.0.24",
"resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code/-/claude-code-2.0.24.tgz",
"integrity": "sha512-6f/AXoTi3SmFYZl42l6L8brdPSkL+MDQWesRBJwgZy3enNI0LaVn1j/6RxQ7toPKnIyChCN0r6hZi61N8znzzQ==",
"license": "SEE LICENSE IN README.md",
"bin": {
"claude": "cli.js"
},
"engines": {
"node": ">=18.0.0"
},
"optionalDependencies": {
"@img/sharp-darwin-arm64": "^0.33.5",
"@img/sharp-darwin-x64": "^0.33.5",
"@img/sharp-linux-arm": "^0.33.5",
"@img/sharp-linux-arm64": "^0.33.5",
"@img/sharp-linux-x64": "^0.33.5",
"@img/sharp-win32-x64": "^0.33.5"
}
},
"node_modules/@babel/code-frame": { "node_modules/@babel/code-frame": {
"version": "7.27.1", "version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
@@ -1653,295 +1646,8 @@
} }
}, },
"node_modules/@boudra/claude-code-acp": { "node_modules/@boudra/claude-code-acp": {
"version": "0.8.1", "resolved": "../claude-code-acp",
"resolved": "https://npm.pkg.github.com/download/@boudra/claude-code-acp/0.8.1/eb5705eac2631f6327d9a15d2b55ce6a24720f94", "link": true
"integrity": "sha512-MUOJXVBjfmi9Mrf1iBMWjCnXADmoELD7cgDhmIq/HWlacEqE5hmb8j/WcadoP9EwY1xzrSSLBSzJ62x5tuxuUQ==",
"license": "Apache-2.0",
"dependencies": {
"@agentclientprotocol/sdk": "0.4.9",
"@anthropic-ai/claude-agent-sdk": "0.1.23",
"@anthropic-ai/claude-code": "2.0.24",
"@modelcontextprotocol/sdk": "1.20.1",
"diff": "8.0.2",
"express": "5.1.0",
"uuid": "13.0.0"
},
"bin": {
"claude-code-acp": "dist/index.js"
}
},
"node_modules/@boudra/claude-code-acp/node_modules/accepts": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
"integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
"license": "MIT",
"dependencies": {
"mime-types": "^3.0.0",
"negotiator": "^1.0.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/@boudra/claude-code-acp/node_modules/body-parser": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz",
"integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==",
"license": "MIT",
"dependencies": {
"bytes": "^3.1.2",
"content-type": "^1.0.5",
"debug": "^4.4.0",
"http-errors": "^2.0.0",
"iconv-lite": "^0.6.3",
"on-finished": "^2.4.1",
"qs": "^6.14.0",
"raw-body": "^3.0.0",
"type-is": "^2.0.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@boudra/claude-code-acp/node_modules/content-disposition": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz",
"integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==",
"license": "MIT",
"dependencies": {
"safe-buffer": "5.2.1"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/@boudra/claude-code-acp/node_modules/cookie-signature": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
"integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
"license": "MIT",
"engines": {
"node": ">=6.6.0"
}
},
"node_modules/@boudra/claude-code-acp/node_modules/diff": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-8.0.2.tgz",
"integrity": "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.3.1"
}
},
"node_modules/@boudra/claude-code-acp/node_modules/express": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz",
"integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==",
"license": "MIT",
"dependencies": {
"accepts": "^2.0.0",
"body-parser": "^2.2.0",
"content-disposition": "^1.0.0",
"content-type": "^1.0.5",
"cookie": "^0.7.1",
"cookie-signature": "^1.2.1",
"debug": "^4.4.0",
"encodeurl": "^2.0.0",
"escape-html": "^1.0.3",
"etag": "^1.8.1",
"finalhandler": "^2.1.0",
"fresh": "^2.0.0",
"http-errors": "^2.0.0",
"merge-descriptors": "^2.0.0",
"mime-types": "^3.0.0",
"on-finished": "^2.4.1",
"once": "^1.4.0",
"parseurl": "^1.3.3",
"proxy-addr": "^2.0.7",
"qs": "^6.14.0",
"range-parser": "^1.2.1",
"router": "^2.2.0",
"send": "^1.1.0",
"serve-static": "^2.2.0",
"statuses": "^2.0.1",
"type-is": "^2.0.1",
"vary": "^1.1.2"
},
"engines": {
"node": ">= 18"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/@boudra/claude-code-acp/node_modules/finalhandler": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz",
"integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==",
"license": "MIT",
"dependencies": {
"debug": "^4.4.0",
"encodeurl": "^2.0.0",
"escape-html": "^1.0.3",
"on-finished": "^2.4.1",
"parseurl": "^1.3.3",
"statuses": "^2.0.1"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/@boudra/claude-code-acp/node_modules/fresh": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
"integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/@boudra/claude-code-acp/node_modules/iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/@boudra/claude-code-acp/node_modules/media-typer": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz",
"integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/@boudra/claude-code-acp/node_modules/merge-descriptors": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz",
"integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==",
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@boudra/claude-code-acp/node_modules/mime-db": {
"version": "1.54.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
"integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/@boudra/claude-code-acp/node_modules/mime-types": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz",
"integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
"license": "MIT",
"dependencies": {
"mime-db": "^1.54.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/@boudra/claude-code-acp/node_modules/negotiator": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
"integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/@boudra/claude-code-acp/node_modules/qs": {
"version": "6.14.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
"integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
"license": "BSD-3-Clause",
"dependencies": {
"side-channel": "^1.1.0"
},
"engines": {
"node": ">=0.6"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/@boudra/claude-code-acp/node_modules/send": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz",
"integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==",
"license": "MIT",
"dependencies": {
"debug": "^4.3.5",
"encodeurl": "^2.0.0",
"escape-html": "^1.0.3",
"etag": "^1.8.1",
"fresh": "^2.0.0",
"http-errors": "^2.0.0",
"mime-types": "^3.0.1",
"ms": "^2.1.3",
"on-finished": "^2.4.1",
"range-parser": "^1.2.1",
"statuses": "^2.0.1"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/@boudra/claude-code-acp/node_modules/serve-static": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz",
"integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==",
"license": "MIT",
"dependencies": {
"encodeurl": "^2.0.0",
"escape-html": "^1.0.3",
"parseurl": "^1.3.3",
"send": "^1.2.0"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/@boudra/claude-code-acp/node_modules/type-is": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
"integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==",
"license": "MIT",
"dependencies": {
"content-type": "^1.0.5",
"media-typer": "^1.1.0",
"mime-types": "^3.0.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/@boudra/claude-code-acp/node_modules/uuid": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz",
"integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==",
"funding": [
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
],
"license": "MIT",
"bin": {
"uuid": "dist-node/bin/uuid"
}
}, },
"node_modules/@boudra/expo-two-way-audio": { "node_modules/@boudra/expo-two-way-audio": {
"version": "0.1.4", "version": "0.1.4",
@@ -4407,215 +4113,6 @@
"url": "https://github.com/sponsors/nzakas" "url": "https://github.com/sponsors/nzakas"
} }
}, },
"node_modules/@img/sharp-darwin-arm64": {
"version": "0.33.5",
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz",
"integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-darwin-arm64": "1.0.4"
}
},
"node_modules/@img/sharp-darwin-x64": {
"version": "0.33.5",
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz",
"integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-darwin-x64": "1.0.4"
}
},
"node_modules/@img/sharp-libvips-darwin-arm64": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz",
"integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==",
"cpu": [
"arm64"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"darwin"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-darwin-x64": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz",
"integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==",
"cpu": [
"x64"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"darwin"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linux-arm": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz",
"integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==",
"cpu": [
"arm"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"linux"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linux-arm64": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz",
"integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==",
"cpu": [
"arm64"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"linux"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linux-x64": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz",
"integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==",
"cpu": [
"x64"
],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"linux"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-linux-arm": {
"version": "0.33.5",
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz",
"integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==",
"cpu": [
"arm"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linux-arm": "1.0.5"
}
},
"node_modules/@img/sharp-linux-arm64": {
"version": "0.33.5",
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz",
"integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linux-arm64": "1.0.4"
}
},
"node_modules/@img/sharp-linux-x64": {
"version": "0.33.5",
"resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz",
"integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linux-x64": "1.0.4"
}
},
"node_modules/@img/sharp-win32-x64": {
"version": "0.33.5",
"resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz",
"integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==",
"cpu": [
"x64"
],
"license": "Apache-2.0 AND LGPL-3.0-or-later",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@isaacs/cliui": { "node_modules/@isaacs/cliui": {
"version": "8.0.2", "version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
@@ -21627,7 +21124,7 @@
"dependencies": { "dependencies": {
"@agentclientprotocol/sdk": "^0.4.9", "@agentclientprotocol/sdk": "^0.4.9",
"@ai-sdk/openai": "^2.0.52", "@ai-sdk/openai": "^2.0.52",
"@boudra/claude-code-acp": "^0.8.1", "@boudra/claude-code-acp": "file:../../../claude-code-acp",
"@deepgram/sdk": "^3.4.0", "@deepgram/sdk": "^3.4.0",
"@modelcontextprotocol/sdk": "^1.20.1", "@modelcontextprotocol/sdk": "^1.20.1",
"@openrouter/ai-sdk-provider": "^1.2.0", "@openrouter/ai-sdk-provider": "^1.2.0",

View File

@@ -58,12 +58,10 @@ export default function RootLayout() {
<Stack <Stack
screenOptions={{ screenOptions={{
headerShown: false, headerShown: false,
animation: "slide_from_right", animation: "none",
animationDuration: 250,
gestureEnabled: true, gestureEnabled: true,
gestureDirection: "horizontal", gestureDirection: "horizontal",
fullScreenGestureEnabled: true, fullScreenGestureEnabled: true,
animationMatchesGesture: true,
}} }}
> >
<Stack.Screen name="index" /> <Stack.Screen name="index" />

View File

@@ -0,0 +1,24 @@
[
{
"id": "b203dc68-03e0-4971-a3d7-a4822c940b50",
"title": "Agent b203dc68",
"sessionId": "019a16ed-36da-7407-aa21-b56f860f2db7",
"options": {
"type": "claude",
"sessionId": "07f421be-98c1-4f23-9604-8f00274956c7"
},
"createdAt": "2025-10-24T15:53:55.340Z",
"cwd": "/Users/moboudra/dev/voice-dev"
},
{
"id": "d0633729-2f74-426a-a3a8-05e8c7206703",
"title": "Assist with Voice Development",
"sessionId": "019a16f0-18d3-7656-85a8-dae38035049d",
"options": {
"type": "claude",
"sessionId": "79c9a8e0-8a24-4851-baad-62747b815442"
},
"createdAt": "2025-10-24T15:57:04.442Z",
"cwd": "/Users/moboudra/dev/voice-dev"
}
]

View File

@@ -18,7 +18,7 @@
"dependencies": { "dependencies": {
"@agentclientprotocol/sdk": "^0.4.9", "@agentclientprotocol/sdk": "^0.4.9",
"@ai-sdk/openai": "^2.0.52", "@ai-sdk/openai": "^2.0.52",
"@boudra/claude-code-acp": "^0.8.1", "@boudra/claude-code-acp": "file:../../../claude-code-acp",
"@deepgram/sdk": "^3.4.0", "@deepgram/sdk": "^3.4.0",
"@modelcontextprotocol/sdk": "^1.20.1", "@modelcontextprotocol/sdk": "^1.20.1",
"@openrouter/ai-sdk-provider": "^1.2.0", "@openrouter/ai-sdk-provider": "^1.2.0",

View File

@@ -64,7 +64,8 @@ class ACPClient implements Client {
constructor( constructor(
private agentId: string, private agentId: string,
private onUpdate: (agentId: string, update: SessionNotification) => void, private onUpdate: (agentId: string, update: SessionNotification) => void,
private onPermissionRequest: (agentId: string, params: RequestPermissionRequest) => Promise<RequestPermissionResponse> private onPermissionRequest: (agentId: string, params: RequestPermissionRequest) => Promise<RequestPermissionResponse>,
private persistence: AgentPersistence
) {} ) {}
async requestPermission(params: RequestPermissionRequest): Promise<RequestPermissionResponse> { async requestPermission(params: RequestPermissionRequest): Promise<RequestPermissionResponse> {
@@ -75,6 +76,19 @@ class ACPClient implements Client {
} }
async sessionUpdate(params: SessionNotification): Promise<void> { async sessionUpdate(params: SessionNotification): Promise<void> {
// Check if this update contains a Claude session ID
const claudeSessionId = params._meta?.claudeSessionId as string | undefined;
if (claudeSessionId && this.persistence) {
const persisted = await this.persistence.load();
const persistedAgent = persisted.find(a => a.id === this.agentId);
if (persistedAgent && persistedAgent.options.type === "claude") {
if (persistedAgent.options.sessionId === null || persistedAgent.options.sessionId !== claudeSessionId) {
// Update the Claude session ID
persistedAgent.options.sessionId = claudeSessionId;
await this.persistence.upsert(persistedAgent);
}
}
}
this.onUpdate(this.agentId, params); this.onUpdate(this.agentId, params);
} }
@@ -138,6 +152,13 @@ export class AgentManager {
const agentId = persisted.id; const agentId = persisted.id;
const cwd = expandTilde(persisted.cwd); const cwd = expandTilde(persisted.cwd);
// Check if Claude agent has a session ID
if (persisted.options.type === "claude" && persisted.options.sessionId === null) {
throw new Error(
`Cannot resume agent ${agentId}: Claude agent has no session ID. This agent was created but never received any prompts.`
);
}
// Validate that the working directory exists // Validate that the working directory exists
try { try {
await access(cwd, constants.R_OK | constants.X_OK); await access(cwd, constants.R_OK | constants.X_OK);
@@ -166,7 +187,8 @@ export class AgentManager {
}, },
(id, params) => { (id, params) => {
return this.handlePermissionRequest(id, params); return this.handlePermissionRequest(id, params);
} },
this.persistence
); );
const connection = new ClientSideConnection(() => client, stream); const connection = new ClientSideConnection(() => client, stream);
@@ -227,7 +249,7 @@ export class AgentManager {
// Use the loadSession API to resume the existing session // Use the loadSession API to resume the existing session
// If this is a Claude agent, use the Claude's internal session ID for resumption // If this is a Claude agent, use the Claude's internal session ID for resumption
const sessionIdToResume = persisted.options.type === "claude" const sessionIdToResume = persisted.options.type === "claude"
? persisted.options.sessionId ? persisted.options.sessionId! // Not null because we checked above
: persisted.sessionId; : persisted.sessionId;
console.log(`[Agent ${agentId}] Loading session - ACP: ${persisted.sessionId}, Claude: ${sessionIdToResume}`); console.log(`[Agent ${agentId}] Loading session - ACP: ${persisted.sessionId}, Claude: ${sessionIdToResume}`);
@@ -305,7 +327,8 @@ export class AgentManager {
}, },
(id, params) => { (id, params) => {
return this.handlePermissionRequest(id, params); return this.handlePermissionRequest(id, params);
} },
this.persistence
); );
const connection = new ClientSideConnection(() => client, stream); const connection = new ClientSideConnection(() => client, stream);
@@ -407,7 +430,7 @@ export class AgentManager {
sessionId: agent.sessionId, sessionId: agent.sessionId,
options: { options: {
type: "claude", type: "claude",
sessionId: claudeSessionId || agent.sessionId, // Use Claude's internal session ID if available sessionId: claudeSessionId || null, // null until first prompt
}, },
createdAt: agent.createdAt.toISOString(), createdAt: agent.createdAt.toISOString(),
cwd: agent.cwd, cwd: agent.cwd,

View File

@@ -11,7 +11,7 @@ const __dirname = dirname(__filename);
export const AgentOptionsSchema = z.discriminatedUnion("type", [ export const AgentOptionsSchema = z.discriminatedUnion("type", [
z.object({ z.object({
type: z.literal("claude"), type: z.literal("claude"),
sessionId: z.string(), // Claude's internal session ID sessionId: z.string().nullable(), // Claude's internal session ID (null until first prompt)
}), }),
// Add more agent types here in the future // Add more agent types here in the future
]); ]);
@@ -51,9 +51,20 @@ export class AgentPersistence {
for (const agent of parsed) { for (const agent of parsed) {
try { try {
const validated = PersistedAgentSchema.parse(agent); const validated = PersistedAgentSchema.parse(agent);
if (
validated.options.type === "claude" &&
validated.options.sessionId !== null
) {
validated.sessionId = validated.options.sessionId;
}
agents.push(validated); agents.push(validated);
} catch (zodError) { } catch (zodError) {
console.error(`[AgentPersistence] Invalid agent data for ${agent.id}:`, zodError); console.error(
`[AgentPersistence] Invalid agent data for ${agent.id}:`,
zodError
);
// Skip invalid agents // Skip invalid agents
} }
} }
@@ -61,7 +72,9 @@ export class AgentPersistence {
return agents; return agents;
} catch (error) { } catch (error) {
// File doesn't exist or is invalid, return empty array // File doesn't exist or is invalid, return empty array
console.log("[AgentPersistence] No existing agents found or file is invalid"); console.log(
"[AgentPersistence] No existing agents found or file is invalid"
);
return []; return [];
} }
} }
@@ -124,7 +137,9 @@ export class AgentPersistence {
if (agent) { if (agent) {
agent.title = title; agent.title = title;
await this.save(agents); await this.save(agents);
console.log(`[AgentPersistence] Updated title for agent ${agentId}: "${title}"`); console.log(
`[AgentPersistence] Updated title for agent ${agentId}: "${title}"`
);
} }
} }
} }