Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6547a87391 | |||
| 45435c8f1b | |||
| 3dfbc7c33e | |||
| 60e5b37913 | |||
| 160136014e |
@@ -60,7 +60,7 @@ jobs:
|
|||||||
echo "$HOME/.bun/bin" >> "$GITHUB_PATH"
|
echo "$HOME/.bun/bin" >> "$GITHUB_PATH"
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: bun install --frozen-lockfile --registry=https://registry.npmmirror.com
|
run: bun install --frozen-lockfile
|
||||||
|
|
||||||
- name: Run checks
|
- name: Run checks
|
||||||
run: bun run check
|
run: bun run check
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
node_modules
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
{
|
|
||||||
"lockfileVersion": 1,
|
|
||||||
"configVersion": 0,
|
|
||||||
"workspaces": {
|
|
||||||
"": {
|
|
||||||
"dependencies": {
|
|
||||||
"@opencode-ai/plugin": "1.14.28",
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/node": "^24.7.2",
|
|
||||||
"typescript": "^5.9.3",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"packages": {
|
|
||||||
"@msgpackr-extract/msgpackr-extract-darwin-arm64": ["@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw=="],
|
|
||||||
|
|
||||||
"@msgpackr-extract/msgpackr-extract-darwin-x64": ["@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw=="],
|
|
||||||
|
|
||||||
"@msgpackr-extract/msgpackr-extract-linux-arm": ["@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3", "", { "os": "linux", "cpu": "arm" }, "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw=="],
|
|
||||||
|
|
||||||
"@msgpackr-extract/msgpackr-extract-linux-arm64": ["@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg=="],
|
|
||||||
|
|
||||||
"@msgpackr-extract/msgpackr-extract-linux-x64": ["@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3", "", { "os": "linux", "cpu": "x64" }, "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg=="],
|
|
||||||
|
|
||||||
"@msgpackr-extract/msgpackr-extract-win32-x64": ["@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3", "", { "os": "win32", "cpu": "x64" }, "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ=="],
|
|
||||||
|
|
||||||
"@opencode-ai/plugin": ["@opencode-ai/plugin@1.14.28", "", { "dependencies": { "@opencode-ai/sdk": "1.14.28", "effect": "4.0.0-beta.48", "zod": "4.1.8" }, "peerDependencies": { "@opentui/core": ">=0.1.105", "@opentui/solid": ">=0.1.105" }, "optionalPeers": ["@opentui/core", "@opentui/solid"] }, "sha512-cHJo7t1jwrzbkIVmNgggdWh4cyOVGw5fnbSpuYeL6qwfmH3g/6YLWtw5ZYEP6detUkEebT08mHXDGmsMUpQa+A=="],
|
|
||||||
|
|
||||||
"@opencode-ai/sdk": ["@opencode-ai/sdk@1.14.28", "", { "dependencies": { "cross-spawn": "7.0.6" } }, "sha512-qRFJfD+Zdz3jHHSupW4F6Io1ZFrQ6gCRFlG50O6kEU9xRxrBpK0wGvP+Y5VwwvD/gH9WKMHYinlQpDVI9/lgJQ=="],
|
|
||||||
|
|
||||||
"@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
|
||||||
|
|
||||||
"@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="],
|
|
||||||
|
|
||||||
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
|
||||||
|
|
||||||
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
|
||||||
|
|
||||||
"effect": ["effect@4.0.0-beta.48", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.6.0", "find-my-way-ts": "^0.1.6", "ini": "^6.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^1.11.9", "multipasta": "^0.2.7", "toml": "^4.1.1", "uuid": "^13.0.0", "yaml": "^2.8.3" } }, "sha512-MMAM/ZabuNdNmgXiin+BAanQXK7qM8mlt7nfXDoJ/Gn9V8i89JlCq+2N0AiWmqFLXjGLA0u3FjiOjSOYQk5uMw=="],
|
|
||||||
|
|
||||||
"fast-check": ["fast-check@4.7.0", "", { "dependencies": { "pure-rand": "^8.0.0" } }, "sha512-NsZRtqvSSoCP0HbNjUD+r1JH8zqZalyp6gLY9e7OYs7NK9b6AHOs2baBFeBG7bVNsuoukh89x2Yg3rPsul8ziQ=="],
|
|
||||||
|
|
||||||
"find-my-way-ts": ["find-my-way-ts@0.1.6", "", {}, "sha512-a85L9ZoXtNAey3Y6Z+eBWW658kO/MwR7zIafkIUPUMf3isZG0NCs2pjW2wtjxAKuJPxMAsHUIP4ZPGv0o5gyTA=="],
|
|
||||||
|
|
||||||
"ini": ["ini@6.0.0", "", {}, "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ=="],
|
|
||||||
|
|
||||||
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
|
||||||
|
|
||||||
"kubernetes-types": ["kubernetes-types@1.30.0", "", {}, "sha512-Dew1okvhM/SQcIa2rcgujNndZwU8VnSapDgdxlYoB84ZlpAD43U6KLAFqYo17ykSFGHNPrg0qry0bP+GJd9v7Q=="],
|
|
||||||
|
|
||||||
"msgpackr": ["msgpackr@1.11.10", "", { "optionalDependencies": { "msgpackr-extract": "^3.0.2" } }, "sha512-iCZNq+HszvF+fC3anCm4nBmWEnbeIAfpDs6IStAEKhQ2YSgkjzVG2FF9XJqwwQh5bH3N9OUTUt4QwVN6MLMLtA=="],
|
|
||||||
|
|
||||||
"msgpackr-extract": ["msgpackr-extract@3.0.3", "", { "dependencies": { "node-gyp-build-optional-packages": "5.2.2" }, "optionalDependencies": { "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" }, "bin": { "download-msgpackr-prebuilds": "bin/download-prebuilds.js" } }, "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA=="],
|
|
||||||
|
|
||||||
"multipasta": ["multipasta@0.2.7", "", {}, "sha512-KPA58d68KgGil15oDqXjkUBEBYc00XvbPj5/X+dyzeo/lWm9Nc25pQRlf1D+gv4OpK7NM0J1odrbu9JNNGvynA=="],
|
|
||||||
|
|
||||||
"node-gyp-build-optional-packages": ["node-gyp-build-optional-packages@5.2.2", "", { "dependencies": { "detect-libc": "^2.0.1" }, "bin": { "node-gyp-build-optional-packages": "bin.js", "node-gyp-build-optional-packages-optional": "optional.js", "node-gyp-build-optional-packages-test": "build-test.js" } }, "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw=="],
|
|
||||||
|
|
||||||
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
|
||||||
|
|
||||||
"pure-rand": ["pure-rand@8.4.0", "", {}, "sha512-IoM8YF/jY0hiugFo/wOWqfmarlE6J0wc6fDK1PhftMk7MGhVZl88sZimmqBBFomLOCSmcCCpsfj7wXASCpvK9A=="],
|
|
||||||
|
|
||||||
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
|
||||||
|
|
||||||
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
|
||||||
|
|
||||||
"toml": ["toml@4.1.1", "", {}, "sha512-EBJnVBr3dTXdA89WVFoAIPUqkBjxPMwRqsfuo1r240tKFHXv3zgca4+NJib/h6TyvGF7vOawz0jGuryJCdNHrw=="],
|
|
||||||
|
|
||||||
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
|
||||||
|
|
||||||
"undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
|
||||||
|
|
||||||
"uuid": ["uuid@13.0.0", "", { "bin": "dist-node/bin/uuid" }, "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w=="],
|
|
||||||
|
|
||||||
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
|
||||||
|
|
||||||
"yaml": ["yaml@2.8.3", "", { "bin": "bin.mjs" }, "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg=="],
|
|
||||||
|
|
||||||
"zod": ["zod@4.1.8", "", {}, "sha512-5R1P+WwQqmmMIEACyzSvo4JXHY5WiAFHRMg+zBZKgKS+Q1viRa0C1hmUKtHltoIFKtIdki3pRxkmpP74jnNYHQ=="],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Generated
-413
@@ -1,413 +0,0 @@
|
|||||||
{
|
|
||||||
"name": ".opencode",
|
|
||||||
"lockfileVersion": 3,
|
|
||||||
"requires": true,
|
|
||||||
"packages": {
|
|
||||||
"": {
|
|
||||||
"dependencies": {
|
|
||||||
"@opencode-ai/plugin": "1.14.28"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/node": "^24.7.2",
|
|
||||||
"typescript": "^5.9.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": {
|
|
||||||
"version": "3.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz",
|
|
||||||
"integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"darwin"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": {
|
|
||||||
"version": "3.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz",
|
|
||||||
"integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"darwin"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": {
|
|
||||||
"version": "3.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz",
|
|
||||||
"integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==",
|
|
||||||
"cpu": [
|
|
||||||
"arm"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": {
|
|
||||||
"version": "3.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz",
|
|
||||||
"integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": {
|
|
||||||
"version": "3.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz",
|
|
||||||
"integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": {
|
|
||||||
"version": "3.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz",
|
|
||||||
"integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"win32"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@opencode-ai/plugin": {
|
|
||||||
"version": "1.14.28",
|
|
||||||
"resolved": "https://registry.npmjs.org/@opencode-ai/plugin/-/plugin-1.14.28.tgz",
|
|
||||||
"integrity": "sha512-cHJo7t1jwrzbkIVmNgggdWh4cyOVGw5fnbSpuYeL6qwfmH3g/6YLWtw5ZYEP6detUkEebT08mHXDGmsMUpQa+A==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@opencode-ai/sdk": "1.14.28",
|
|
||||||
"effect": "4.0.0-beta.48",
|
|
||||||
"zod": "4.1.8"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@opentui/core": ">=0.1.105",
|
|
||||||
"@opentui/solid": ">=0.1.105"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@opentui/core": {
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"@opentui/solid": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@opencode-ai/sdk": {
|
|
||||||
"version": "1.14.28",
|
|
||||||
"resolved": "https://registry.npmjs.org/@opencode-ai/sdk/-/sdk-1.14.28.tgz",
|
|
||||||
"integrity": "sha512-qRFJfD+Zdz3jHHSupW4F6Io1ZFrQ6gCRFlG50O6kEU9xRxrBpK0wGvP+Y5VwwvD/gH9WKMHYinlQpDVI9/lgJQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"cross-spawn": "7.0.6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@standard-schema/spec": {
|
|
||||||
"version": "1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz",
|
|
||||||
"integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/@types/node": {
|
|
||||||
"version": "24.12.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.2.tgz",
|
|
||||||
"integrity": "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"undici-types": "~7.16.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/cross-spawn": {
|
|
||||||
"version": "7.0.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
|
||||||
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"path-key": "^3.1.0",
|
|
||||||
"shebang-command": "^2.0.0",
|
|
||||||
"which": "^2.0.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/detect-libc": {
|
|
||||||
"version": "2.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
|
|
||||||
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"optional": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/effect": {
|
|
||||||
"version": "4.0.0-beta.48",
|
|
||||||
"resolved": "https://registry.npmjs.org/effect/-/effect-4.0.0-beta.48.tgz",
|
|
||||||
"integrity": "sha512-MMAM/ZabuNdNmgXiin+BAanQXK7qM8mlt7nfXDoJ/Gn9V8i89JlCq+2N0AiWmqFLXjGLA0u3FjiOjSOYQk5uMw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@standard-schema/spec": "^1.1.0",
|
|
||||||
"fast-check": "^4.6.0",
|
|
||||||
"find-my-way-ts": "^0.1.6",
|
|
||||||
"ini": "^6.0.0",
|
|
||||||
"kubernetes-types": "^1.30.0",
|
|
||||||
"msgpackr": "^1.11.9",
|
|
||||||
"multipasta": "^0.2.7",
|
|
||||||
"toml": "^4.1.1",
|
|
||||||
"uuid": "^13.0.0",
|
|
||||||
"yaml": "^2.8.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/fast-check": {
|
|
||||||
"version": "4.7.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/fast-check/-/fast-check-4.7.0.tgz",
|
|
||||||
"integrity": "sha512-NsZRtqvSSoCP0HbNjUD+r1JH8zqZalyp6gLY9e7OYs7NK9b6AHOs2baBFeBG7bVNsuoukh89x2Yg3rPsul8ziQ==",
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"type": "individual",
|
|
||||||
"url": "https://github.com/sponsors/dubzzz"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/fast-check"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"pure-rand": "^8.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12.17.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/find-my-way-ts": {
|
|
||||||
"version": "0.1.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/find-my-way-ts/-/find-my-way-ts-0.1.6.tgz",
|
|
||||||
"integrity": "sha512-a85L9ZoXtNAey3Y6Z+eBWW658kO/MwR7zIafkIUPUMf3isZG0NCs2pjW2wtjxAKuJPxMAsHUIP4ZPGv0o5gyTA==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/ini": {
|
|
||||||
"version": "6.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/ini/-/ini-6.0.0.tgz",
|
|
||||||
"integrity": "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ==",
|
|
||||||
"license": "ISC",
|
|
||||||
"engines": {
|
|
||||||
"node": "^20.17.0 || >=22.9.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/isexe": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
|
||||||
"license": "ISC"
|
|
||||||
},
|
|
||||||
"node_modules/kubernetes-types": {
|
|
||||||
"version": "1.30.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/kubernetes-types/-/kubernetes-types-1.30.0.tgz",
|
|
||||||
"integrity": "sha512-Dew1okvhM/SQcIa2rcgujNndZwU8VnSapDgdxlYoB84ZlpAD43U6KLAFqYo17ykSFGHNPrg0qry0bP+GJd9v7Q==",
|
|
||||||
"license": "Apache-2.0"
|
|
||||||
},
|
|
||||||
"node_modules/msgpackr": {
|
|
||||||
"version": "1.11.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.10.tgz",
|
|
||||||
"integrity": "sha512-iCZNq+HszvF+fC3anCm4nBmWEnbeIAfpDs6IStAEKhQ2YSgkjzVG2FF9XJqwwQh5bH3N9OUTUt4QwVN6MLMLtA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"optionalDependencies": {
|
|
||||||
"msgpackr-extract": "^3.0.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/msgpackr-extract": {
|
|
||||||
"version": "3.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz",
|
|
||||||
"integrity": "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==",
|
|
||||||
"hasInstallScript": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
|
||||||
"node-gyp-build-optional-packages": "5.2.2"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"download-msgpackr-prebuilds": "bin/download-prebuilds.js"
|
|
||||||
},
|
|
||||||
"optionalDependencies": {
|
|
||||||
"@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3",
|
|
||||||
"@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3",
|
|
||||||
"@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3",
|
|
||||||
"@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3",
|
|
||||||
"@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3",
|
|
||||||
"@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/multipasta": {
|
|
||||||
"version": "0.2.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/multipasta/-/multipasta-0.2.7.tgz",
|
|
||||||
"integrity": "sha512-KPA58d68KgGil15oDqXjkUBEBYc00XvbPj5/X+dyzeo/lWm9Nc25pQRlf1D+gv4OpK7NM0J1odrbu9JNNGvynA==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/node-gyp-build-optional-packages": {
|
|
||||||
"version": "5.2.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz",
|
|
||||||
"integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
|
||||||
"detect-libc": "^2.0.1"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"node-gyp-build-optional-packages": "bin.js",
|
|
||||||
"node-gyp-build-optional-packages-optional": "optional.js",
|
|
||||||
"node-gyp-build-optional-packages-test": "build-test.js"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/path-key": {
|
|
||||||
"version": "3.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
|
||||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/pure-rand": {
|
|
||||||
"version": "8.4.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-8.4.0.tgz",
|
|
||||||
"integrity": "sha512-IoM8YF/jY0hiugFo/wOWqfmarlE6J0wc6fDK1PhftMk7MGhVZl88sZimmqBBFomLOCSmcCCpsfj7wXASCpvK9A==",
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"type": "individual",
|
|
||||||
"url": "https://github.com/sponsors/dubzzz"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/fast-check"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/shebang-command": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"shebang-regex": "^3.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/shebang-regex": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/toml": {
|
|
||||||
"version": "4.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/toml/-/toml-4.1.1.tgz",
|
|
||||||
"integrity": "sha512-EBJnVBr3dTXdA89WVFoAIPUqkBjxPMwRqsfuo1r240tKFHXv3zgca4+NJib/h6TyvGF7vOawz0jGuryJCdNHrw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/typescript": {
|
|
||||||
"version": "5.9.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
|
||||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"bin": {
|
|
||||||
"tsc": "bin/tsc",
|
|
||||||
"tsserver": "bin/tsserver"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=14.17"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/undici-types": {
|
|
||||||
"version": "7.16.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
|
|
||||||
"integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/uuid": {
|
|
||||||
"version": "13.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.1.tgz",
|
|
||||||
"integrity": "sha512-9ezox2roIft6ExBVTVqibSd5dc5/47Sw/uY6b4SjQUT2TzQ0tltNquWA46y4xPQmdZYqvnio22SgWd41M86+jw==",
|
|
||||||
"funding": [
|
|
||||||
"https://github.com/sponsors/broofa",
|
|
||||||
"https://github.com/sponsors/ctavan"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"bin": {
|
|
||||||
"uuid": "dist-node/bin/uuid"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/which": {
|
|
||||||
"version": "2.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
|
||||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
|
||||||
"license": "ISC",
|
|
||||||
"dependencies": {
|
|
||||||
"isexe": "^2.0.0"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"node-which": "bin/node-which"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/yaml": {
|
|
||||||
"version": "2.8.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz",
|
|
||||||
"integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==",
|
|
||||||
"license": "ISC",
|
|
||||||
"bin": {
|
|
||||||
"yaml": "bin.mjs"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 14.6"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/eemeli"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/zod": {
|
|
||||||
"version": "4.1.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/zod/-/zod-4.1.8.tgz",
|
|
||||||
"integrity": "sha512-5R1P+WwQqmmMIEACyzSvo4JXHY5WiAFHRMg+zBZKgKS+Q1viRa0C1hmUKtHltoIFKtIdki3pRxkmpP74jnNYHQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/colinhacks"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"private": true,
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"typecheck": "tsc --noEmit -p tsconfig.json"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@opencode-ai/plugin": "1.14.28"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/node": "^24.7.2",
|
|
||||||
"typescript": "^5.9.3"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -30,30 +30,41 @@ TJWaterAgent/
|
|||||||
1. 启动 HTTP 服务。
|
1. 启动 HTTP 服务。
|
||||||
2. 通过 `@opencode-ai/sdk` 启动内嵌 opencode server,或连接外部 opencode server。
|
2. 通过 `@opencode-ai/sdk` 启动内嵌 opencode server,或连接外部 opencode server。
|
||||||
3. 管理前端 `session_id -> opencode sessionId` 的映射。
|
3. 管理前端 `session_id -> opencode sessionId` 的映射。
|
||||||
4. 保存并传递用户的鉴权信息(accessToken, actorKey)、项目上下文(projectId, projectKey)以及 traceId。
|
4. 保存并传递用户 `Authorization`、`x-user-id`、`x-project-id`、`x-trace-id`。
|
||||||
5. 把 opencode 输出适配成前端需要的 SSE 事件。
|
5. 把 opencode 输出适配成前端需要的 SSE 事件。
|
||||||
6. 为 `.opencode/tools/dynamic_http_call.ts` 等工具提供内部回调接口。
|
6. 为 `.opencode/tools/dynamic_http_call.ts` 提供内部回调接口。
|
||||||
7. 代理调用真实 TJWater 后端 API。
|
7. 代理调用真实 TJWater 后端 API。
|
||||||
|
|
||||||
主要目录结构说明:
|
当前 Agent API 的主入口:
|
||||||
|
|
||||||
| 目录 | 职责 |
|
|
||||||
| --- | --- |
|
|
||||||
| `src/routes/` | 路由定义,如 `chat.ts` 处理聊天请求 |
|
|
||||||
| `src/chat/` | 会话桥接逻辑,负责 Express 与 opencode 会话的同步 |
|
|
||||||
| `src/runtime/` | opencode 运行时管理,控制 SDK 的启动与状态检查 |
|
|
||||||
| `src/session/` | 会话注册中心和工具执行时的上下文关联存储 |
|
|
||||||
| `src/tools/` | 内部工具执行器,如 `dynamicHttpExecutor` 负责构造真实的业务请求 |
|
|
||||||
| `src/learning/` | Agent 学习状态协调器,负责处理记忆累积和知识更新 |
|
|
||||||
| `src/audit/` | 审计记录,包含学习过程和 LLM 请求审计 |
|
|
||||||
|
|
||||||
当前 Agent API 的主接口:
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
POST /api/v1/chat/message
|
POST /api/v1/agent/chat/stream
|
||||||
```
|
```
|
||||||
|
|
||||||
该接口返回 SSE 格式数据。
|
该接口返回 SSE,事件包括:
|
||||||
|
|
||||||
|
| event | 用途 |
|
||||||
|
| --- | --- |
|
||||||
|
| `progress` | 前端过程可视化,展示规划、工具调用和完成状态 |
|
||||||
|
| `token` | 最终回答文本流 |
|
||||||
|
| `tool_call` | 前端地图/面板/图表动作 |
|
||||||
|
| `done` | 当前轮完成 |
|
||||||
|
| `error` | 当前轮失败 |
|
||||||
|
|
||||||
|
主要目录和文件:
|
||||||
|
|
||||||
|
```text
|
||||||
|
src/
|
||||||
|
server.ts
|
||||||
|
config.ts
|
||||||
|
runtime/
|
||||||
|
session/
|
||||||
|
chat/
|
||||||
|
routes/
|
||||||
|
tools/
|
||||||
|
```
|
||||||
|
|
||||||
|
其中 `src/` 是业务服务层,不直接放 opencode skill 或 agent prompt。
|
||||||
|
|
||||||
## `.opencode/` 的职责
|
## `.opencode/` 的职责
|
||||||
|
|
||||||
@@ -62,52 +73,40 @@ POST /api/v1/chat/message
|
|||||||
### agents
|
### agents
|
||||||
|
|
||||||
```text
|
```text
|
||||||
.opencode/agents/instruction.md
|
.opencode/agents/agent.md
|
||||||
```
|
```
|
||||||
|
|
||||||
这里定义默认 agent 的角色、行为规则、模型配置和工具使用策略。目前的 `default_agent` 配置为 `instruction`。
|
这里定义默认 agent 的角色、行为规则、模型配置和工具使用策略。
|
||||||
|
|
||||||
|
当前项目已将 always-loaded instructions 收敛到 `agent.md`,`opencode.json` 不再额外配置 `instructions` 数组。
|
||||||
|
|
||||||
### tools
|
### tools
|
||||||
|
|
||||||
```text
|
```text
|
||||||
.opencode/tools/
|
.opencode/tools/
|
||||||
dynamic_http_call.ts # 动态 HTTP 调用,通过回调 host 服务获取鉴权
|
dynamic_http_call.ts
|
||||||
fetch_result_ref.ts # 获取结果引用
|
locate_features.ts
|
||||||
locate_features.ts # 地图定位
|
view_history.ts
|
||||||
memory_manager.ts # 记忆管理
|
view_scada.ts
|
||||||
skill_manager.ts # 技能管理
|
show_chart.ts
|
||||||
show_chart.ts # 图表展示
|
|
||||||
...
|
|
||||||
```
|
```
|
||||||
|
|
||||||
这些是 opencode 可以调用的自定义工具。
|
这些是 opencode 可以调用的自定义工具。
|
||||||
|
|
||||||
|
`dynamic_http_call.ts` 不直接保存用户 token,也不直接访问后端。它会回调 `TJWaterAgent` 的内部接口,由上级服务层根据当前 session 补上用户 token、项目 ID 和 trace ID,再调用 TJWater 后端。
|
||||||
|
|
||||||
|
前端类工具如 `locate_features`、`view_history`、`view_scada`、`show_chart` 主要用于触发 UI 动作或可视化,不应被当作数据查询工具。
|
||||||
|
|
||||||
### skills
|
### skills
|
||||||
|
|
||||||
```text
|
```text
|
||||||
.opencode/skills/
|
.opencode/skills/tjwater-skills-root-index/
|
||||||
SKILL.md # 根索引
|
SKILL.md
|
||||||
analytics/ # 分析类技能(SCADA、水力模拟、爆管分析等)
|
ai/
|
||||||
business/ # 业务类技能(模型配置、资产管理、项目环境等)
|
analytics/
|
||||||
data/ # 数据类技能(时序数据访问)
|
business/
|
||||||
platform/ # 平台类技能(审计、缓存、元数据等)
|
data/
|
||||||
```
|
platform/
|
||||||
|
|
||||||
这里保存 TJWater 技能树,保持树结构以符合渐进式披露设计。
|
|
||||||
|
|
||||||
## 启动与开发
|
|
||||||
|
|
||||||
项目使用 `bun` 作为包管理器和运行环境。
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 安装依赖
|
|
||||||
bun install
|
|
||||||
|
|
||||||
# 启动开发环境(带 watch 模式)
|
|
||||||
bun run dev
|
|
||||||
|
|
||||||
# 类型检查
|
|
||||||
bun run check
|
|
||||||
```
|
```
|
||||||
|
|
||||||
这里保存 TJWater 技能树,并保持树结构,符合渐进式披露设计。
|
这里保存 TJWater 技能树,并保持树结构,符合渐进式披露设计。
|
||||||
@@ -151,7 +150,12 @@ typescript
|
|||||||
|
|
||||||
## 启动与部署
|
## 启动与部署
|
||||||
|
|
||||||
默认部署不需要全局安装 `opencode` CLI。服务会通过 `@opencode-ai/sdk` 的 embedded 模式启动 opencode server。
|
支持两种 opencode 接入方式:
|
||||||
|
|
||||||
|
1. Embedded 模式:服务通过 `@opencode-ai/sdk` 调用 `createOpencode`,启动本地 `opencode` CLI 子进程并自动创建 client。
|
||||||
|
2. Client 模式:服务通过 `createOpencodeClient` 直接连接一个已经存在的 opencode server。
|
||||||
|
|
||||||
|
因此,只有 Embedded 模式要求运行环境已安装 `opencode` CLI;Client 模式不依赖本地 CLI。
|
||||||
|
|
||||||
根目录的 Bun scripts 已经封装 `.opencode` 依赖安装和类型检查,日常只需要在 `TJWaterAgent/` 根目录操作。
|
根目录的 Bun scripts 已经封装 `.opencode` 依赖安装和类型检查,日常只需要在 `TJWaterAgent/` 根目录操作。
|
||||||
|
|
||||||
@@ -176,9 +180,21 @@ opencode.json
|
|||||||
|
|
||||||
因此修改 agent prompt、tools、skills、模型配置或本地环境变量后,不需要手动重启 `bun run dev`。
|
因此修改 agent prompt、tools、skills、模型配置或本地环境变量后,不需要手动重启 `bun run dev`。
|
||||||
|
|
||||||
本地开发可以在项目根目录的 `.local.env` 中配置环境变量:
|
本地开发可以在项目根目录的 `.local.env` 中配置环境变量。
|
||||||
|
|
||||||
|
Embedded 模式示例:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
OPENCODE_MODE=embedded
|
||||||
|
DEEPSEEK_API_KEY=sk-xxx
|
||||||
|
TJWATER_API_BASE_URL=http://127.0.0.1:8000
|
||||||
|
```
|
||||||
|
|
||||||
|
Client 模式示例:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
OPENCODE_MODE=client
|
||||||
|
OPENCODE_CLIENT_BASE_URL=http://127.0.0.1:4096
|
||||||
DEEPSEEK_API_KEY=sk-xxx
|
DEEPSEEK_API_KEY=sk-xxx
|
||||||
TJWATER_API_BASE_URL=http://127.0.0.1:8000
|
TJWATER_API_BASE_URL=http://127.0.0.1:8000
|
||||||
```
|
```
|
||||||
@@ -288,5 +304,10 @@ bun run start
|
|||||||
如果需要连接外部独立运行的 opencode server,可以配置:
|
如果需要连接外部独立运行的 opencode server,可以配置:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
OPENCODE_BASE_URL=http://127.0.0.1:4096
|
OPENCODE_MODE=client
|
||||||
|
OPENCODE_CLIENT_BASE_URL=http://127.0.0.1:4096
|
||||||
```
|
```
|
||||||
|
|
||||||
|
配置后,`TJWaterAgent` 会连接该外部 opencode server,而不是自行启动 embedded opencode server。
|
||||||
|
|
||||||
|
兼容说明:历史环境变量 `OPENCODE_BASE_URL` 仍可使用,但建议迁移为 `OPENCODE_CLIENT_BASE_URL`,并显式设置 `OPENCODE_MODE=client`。
|
||||||
|
|||||||
+12
-6
@@ -13,17 +13,23 @@ services:
|
|||||||
NODE_ENV: production
|
NODE_ENV: production
|
||||||
HOST: 0.0.0.0
|
HOST: 0.0.0.0
|
||||||
PORT: 8787
|
PORT: 8787
|
||||||
AGENT_INTERNAL_TOKEN: ${AGENT_INTERNAL_TOKEN:-}
|
DEEPSEEK_API_KEY: "sk-8941428ad9be4c789becfa8d66534aba"
|
||||||
OPENCODE_BASE_URL: ${OPENCODE_BASE_URL:-http://127.0.0.1:4096}
|
TJWATER_API_BASE_URL: "http://127.0.0.1:8000"
|
||||||
DEEPSEEK_API_KEY: ${DEEPSEEK_API_KEY:-}
|
# Embedded 模式:容器内启动 opencode CLI 子进程
|
||||||
TJWATER_API_BASE_URL: ${TJWATER_API_BASE_URL:-http://127.0.0.1:8000}
|
OPENCODE_MODE: embedded
|
||||||
|
OPENCODE_HOSTNAME: 0.0.0.0
|
||||||
|
OPENCODE_PORT: 4096
|
||||||
|
# Client 模式:连接外部服务地址,不依赖容器内 CLI
|
||||||
|
# OPENCODE_MODE: client
|
||||||
|
# OPENCODE_CLIENT_BASE_URL: "http://host.docker.internal:4096"
|
||||||
volumes:
|
volumes:
|
||||||
- /home/ubuntu/.config/opencode:/root/.config/opencode
|
- /home/ubuntu/.config/opencode:/root/.config/opencode
|
||||||
- /home/ubuntu/.local/share/opencode:/root/.local/share/opencode
|
- /home/ubuntu/.local/share/opencode:/root/.local/share/opencode
|
||||||
- ./.opencode/agents:/app/.opencode/agents
|
- ./opencode/agents:/app/.opencode/agents
|
||||||
- ./.opencode/skills:/app/.opencode/skills
|
- ./opencode/skills:/app/.opencode/skills
|
||||||
- ./logs:/app/logs
|
- ./logs:/app/logs
|
||||||
- ./data:/app/data
|
- ./data:/app/data
|
||||||
ports:
|
ports:
|
||||||
- "8787:8787"
|
- "8787:8787"
|
||||||
|
# - "4096:4096"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@
|
|||||||
"install:opencode": "bun install --cwd .opencode",
|
"install:opencode": "bun install --cwd .opencode",
|
||||||
"typecheck": "tsc --noEmit -p tsconfig.json",
|
"typecheck": "tsc --noEmit -p tsconfig.json",
|
||||||
"typecheck:opencode": "bun run --cwd .opencode typecheck",
|
"typecheck:opencode": "bun run --cwd .opencode typecheck",
|
||||||
"dev": "bun run typecheck:opencode && bun --watch src/server.ts",
|
"dev": "bun --watch src/server.ts",
|
||||||
"build": "bun run check",
|
"build": "bun run check",
|
||||||
"check": "bun run typecheck && bun run typecheck:opencode",
|
"check": "bun run typecheck && bun run typecheck:opencode",
|
||||||
"push": "git add . && git commit -m \"chore: update\" && git push origin main",
|
"push": "git add . && git commit -m \"chore: update\" && git push origin main",
|
||||||
|
|||||||
+49
-6
@@ -4,8 +4,21 @@ import { z } from "zod";
|
|||||||
// 本地开发可在项目根目录放 .local.env;已存在的系统环境变量优先级更高。
|
// 本地开发可在项目根目录放 .local.env;已存在的系统环境变量优先级更高。
|
||||||
dotenv.config({ path: ".local.env", override: false });
|
dotenv.config({ path: ".local.env", override: false });
|
||||||
|
|
||||||
|
const optionalString = () =>
|
||||||
|
z.preprocess(
|
||||||
|
(value) => {
|
||||||
|
if (typeof value !== "string") {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
const normalized = value.trim();
|
||||||
|
return normalized.length > 0 ? normalized : undefined;
|
||||||
|
},
|
||||||
|
z.string().optional(),
|
||||||
|
);
|
||||||
|
|
||||||
// 统一在启动时解析环境变量,避免业务代码里散落字符串默认值。
|
// 统一在启动时解析环境变量,避免业务代码里散落字符串默认值。
|
||||||
const envSchema = z.object({
|
const envSchema = z
|
||||||
|
.object({
|
||||||
// 运行环境标识,如 development / production。
|
// 运行环境标识,如 development / production。
|
||||||
NODE_ENV: z.string().default("development"),
|
NODE_ENV: z.string().default("development"),
|
||||||
// HTTP 服务监听端口。
|
// HTTP 服务监听端口。
|
||||||
@@ -18,10 +31,20 @@ const envSchema = z.object({
|
|||||||
LLM_REQUEST_AUDIT_LOG_PATH: z
|
LLM_REQUEST_AUDIT_LOG_PATH: z
|
||||||
.string()
|
.string()
|
||||||
.default("./logs/llm-request-audit.log"),
|
.default("./logs/llm-request-audit.log"),
|
||||||
// 外部 opencode server 回调本服务内部工具桥时使用的共享鉴权 token;可暂时留空。
|
// 内部工具桥调用本服务时使用的鉴权 token;未显式配置时启动阶段会自动生成。
|
||||||
AGENT_INTERNAL_TOKEN: z.string().default(""),
|
AGENT_INTERNAL_TOKEN: optionalString(),
|
||||||
// 外部 opencode server 的基础地址。
|
// opencode 运行模式:embedded 会启动本地 CLI 子进程;client 只连接现有 server。
|
||||||
OPENCODE_BASE_URL: z.string().url(),
|
OPENCODE_MODE: z.enum(["embedded", "client"]).default("embedded"),
|
||||||
|
// embedded opencode server 的监听地址。
|
||||||
|
OPENCODE_HOSTNAME: z.string().default("127.0.0.1"),
|
||||||
|
// embedded opencode server 的监听端口。
|
||||||
|
OPENCODE_PORT: z.coerce.number().int().positive().default(4096),
|
||||||
|
// opencode SDK 启动或连接运行时时的超时时间(毫秒)。
|
||||||
|
OPENCODE_TIMEOUT_MS: z.coerce.number().int().positive().default(5000),
|
||||||
|
// 默认使用的 opencode 模型标识。
|
||||||
|
OPENCODE_MODEL: z.string().default("deepseek/deepseek-v4-pro"),
|
||||||
|
// client 模式下,目标 opencode server 的基础地址。
|
||||||
|
OPENCODE_CLIENT_BASE_URL: z.string().url().optional(),
|
||||||
// chat session 在本地注册表中的保活时长(秒)。
|
// chat session 在本地注册表中的保活时长(秒)。
|
||||||
SESSION_TTL_SECONDS: z.coerce.number().int().positive().default(1800),
|
SESSION_TTL_SECONDS: z.coerce.number().int().positive().default(1800),
|
||||||
// 提供给本地 opencode tools 读取的会话上下文目录。
|
// 提供给本地 opencode tools 读取的会话上下文目录。
|
||||||
@@ -82,8 +105,28 @@ const envSchema = z.object({
|
|||||||
.int()
|
.int()
|
||||||
.positive()
|
.positive()
|
||||||
.default(50),
|
.default(50),
|
||||||
|
})
|
||||||
|
.superRefine((env, ctx) => {
|
||||||
|
if (env.OPENCODE_MODE === "client" && !env.OPENCODE_CLIENT_BASE_URL) {
|
||||||
|
ctx.addIssue({
|
||||||
|
code: z.ZodIssueCode.custom,
|
||||||
|
path: ["OPENCODE_CLIENT_BASE_URL"],
|
||||||
|
message: "OPENCODE_CLIENT_BASE_URL is required when OPENCODE_MODE=client",
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export type AppConfig = z.infer<typeof envSchema>;
|
export type AppConfig = z.infer<typeof envSchema>;
|
||||||
|
|
||||||
export const config: AppConfig = envSchema.parse(process.env);
|
const normalizedEnv = {
|
||||||
|
...process.env,
|
||||||
|
OPENCODE_MODE:
|
||||||
|
process.env.OPENCODE_MODE ??
|
||||||
|
(process.env.OPENCODE_CLIENT_BASE_URL || process.env.OPENCODE_BASE_URL
|
||||||
|
? "client"
|
||||||
|
: "embedded"),
|
||||||
|
OPENCODE_CLIENT_BASE_URL:
|
||||||
|
process.env.OPENCODE_CLIENT_BASE_URL ?? process.env.OPENCODE_BASE_URL,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const config: AppConfig = envSchema.parse(normalizedEnv);
|
||||||
|
|||||||
+62
-3
@@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
createOpencode,
|
||||||
createOpencodeClient,
|
createOpencodeClient,
|
||||||
type OpencodeClient,
|
type OpencodeClient,
|
||||||
} from "@opencode-ai/sdk/v2";
|
} from "@opencode-ai/sdk/v2";
|
||||||
@@ -18,6 +19,7 @@ type RuntimeModelOverride = {
|
|||||||
|
|
||||||
export class OpencodeRuntimeAdapter {
|
export class OpencodeRuntimeAdapter {
|
||||||
private clientPromise: Promise<OpencodeClient> | null = null;
|
private clientPromise: Promise<OpencodeClient> | null = null;
|
||||||
|
private closeServer: (() => void) | null = null;
|
||||||
|
|
||||||
async ensureClient(): Promise<OpencodeClient> {
|
async ensureClient(): Promise<OpencodeClient> {
|
||||||
if (!this.clientPromise) {
|
if (!this.clientPromise) {
|
||||||
@@ -97,24 +99,81 @@ export class OpencodeRuntimeAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async dispose(): Promise<void> {
|
async dispose(): Promise<void> {
|
||||||
|
this.closeServer?.();
|
||||||
|
this.closeServer = null;
|
||||||
this.clientPromise = null;
|
this.clientPromise = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async bootstrapClient(): Promise<OpencodeClient> {
|
private async bootstrapClient(): Promise<OpencodeClient> {
|
||||||
|
if (config.OPENCODE_MODE === "client") {
|
||||||
logger.info(
|
logger.info(
|
||||||
{
|
{
|
||||||
baseUrl: config.OPENCODE_BASE_URL,
|
baseUrl: config.OPENCODE_CLIENT_BASE_URL,
|
||||||
|
mode: config.OPENCODE_MODE,
|
||||||
},
|
},
|
||||||
"connecting to opencode server",
|
"connecting to opencode server in client mode",
|
||||||
);
|
);
|
||||||
return createOpencodeClient({
|
return createOpencodeClient({
|
||||||
baseUrl: config.OPENCODE_BASE_URL,
|
baseUrl: config.OPENCODE_CLIENT_BASE_URL,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// embedded 模式下,把服务内工具桥地址注入到 opencode 进程环境里,
|
||||||
|
// 这样 .opencode/tools 下的自定义工具可以回调本服务。
|
||||||
|
process.env.TJWATER_AGENT_INTERNAL_BASE_URL = `http://127.0.0.1:${config.PORT}`;
|
||||||
|
process.env.TJWATER_AGENT_INTERNAL_TOKEN =
|
||||||
|
config.AGENT_INTERNAL_TOKEN ??
|
||||||
|
process.env.TJWATER_AGENT_INTERNAL_TOKEN ??
|
||||||
|
"";
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
{
|
||||||
|
hostname: config.OPENCODE_HOSTNAME,
|
||||||
|
port: config.OPENCODE_PORT,
|
||||||
|
model: config.OPENCODE_MODEL,
|
||||||
|
mode: config.OPENCODE_MODE,
|
||||||
|
},
|
||||||
|
"starting opencode server in embedded mode",
|
||||||
|
);
|
||||||
|
|
||||||
|
let runtime;
|
||||||
|
try {
|
||||||
|
runtime = await createOpencode({
|
||||||
|
hostname: config.OPENCODE_HOSTNAME,
|
||||||
|
port: config.OPENCODE_PORT,
|
||||||
|
timeout: config.OPENCODE_TIMEOUT_MS,
|
||||||
|
config: {
|
||||||
|
model: config.OPENCODE_MODEL,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
if (isMissingOpencodeCli(error)) {
|
||||||
|
throw new Error(
|
||||||
|
"embedded mode requires the opencode CLI to be installed and available in PATH; otherwise set OPENCODE_MODE=client and provide OPENCODE_CLIENT_BASE_URL",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.closeServer = () => {
|
||||||
|
runtime.server.close();
|
||||||
|
};
|
||||||
|
|
||||||
|
return runtime.client;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const opencodeRuntime = new OpencodeRuntimeAdapter();
|
export const opencodeRuntime = new OpencodeRuntimeAdapter();
|
||||||
|
|
||||||
|
function isMissingOpencodeCli(error: unknown): error is NodeJS.ErrnoException {
|
||||||
|
return (
|
||||||
|
typeof error === "object" &&
|
||||||
|
error !== null &&
|
||||||
|
"code" in error &&
|
||||||
|
(error as NodeJS.ErrnoException).code === "ENOENT"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function requireData<T>(data: T | undefined, operation: string): T {
|
function requireData<T>(data: T | undefined, operation: string): T {
|
||||||
if (data === undefined) {
|
if (data === undefined) {
|
||||||
throw new Error(`${operation} returned no data`);
|
throw new Error(`${operation} returned no data`);
|
||||||
|
|||||||
+6
-1
@@ -1,3 +1,4 @@
|
|||||||
|
import { randomUUID } from "node:crypto";
|
||||||
import cors from "cors";
|
import cors from "cors";
|
||||||
import express from "express";
|
import express from "express";
|
||||||
|
|
||||||
@@ -27,7 +28,10 @@ const learningOrchestrator = new LearningOrchestrator(
|
|||||||
);
|
);
|
||||||
const resultReferenceStore = new ResultReferenceStore();
|
const resultReferenceStore = new ResultReferenceStore();
|
||||||
const dynamicHttpExecutor = new DynamicHttpExecutor(resultReferenceStore);
|
const dynamicHttpExecutor = new DynamicHttpExecutor(resultReferenceStore);
|
||||||
const internalToken = config.AGENT_INTERNAL_TOKEN;
|
const internalToken = config.AGENT_INTERNAL_TOKEN ?? randomUUID();
|
||||||
|
|
||||||
|
// 这个 token 只用于仍需服务端上下文的工具桥(dynamic_http_call / fetch_result_ref)。
|
||||||
|
process.env.TJWATER_AGENT_INTERNAL_TOKEN = internalToken;
|
||||||
|
|
||||||
app.use(cors());
|
app.use(cors());
|
||||||
app.use(express.json({ limit: "1mb" }));
|
app.use(express.json({ limit: "1mb" }));
|
||||||
@@ -201,6 +205,7 @@ const shutdown = async () => {
|
|||||||
logger.info("shutting down TJWaterAgent");
|
logger.info("shutting down TJWaterAgent");
|
||||||
server.close();
|
server.close();
|
||||||
resultReferenceStore.stopCleanupLoop();
|
resultReferenceStore.stopCleanupLoop();
|
||||||
|
// 同步关闭 embedded opencode server,避免本服务退出后留下孤儿进程。
|
||||||
await opencodeRuntime.dispose();
|
await opencodeRuntime.dispose();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user