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
b?pJ@?E9gfL_3IH12H@dirp1`~*Qfsj;$mX<
literal 0
HcmV?d00001
diff --git a/backend/hololake_副本.zip b/backend/hololake_副本.zip
new file mode 100644
index 0000000000000000000000000000000000000000..f052e45fea652fdc4e117f5855730fa424e50eb1
GIT binary patch
literal 14966
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
b?pJ@?E9gfL_3IH12H@dirp1`~*Qfsj;$mX<
literal 0
HcmV?d00001
diff --git a/backend/package-lock.json b/backend/package-lock.json
new file mode 100644
index 00000000..7e5cb68a
--- /dev/null
+++ b/backend/package-lock.json
@@ -0,0 +1,999 @@
+{
+ "name": "hololake-backend",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "hololake-backend",
+ "version": "1.0.0",
+ "license": "ISC",
+ "dependencies": {
+ "axios": "^1.13.6",
+ "cors": "^2.8.6",
+ "dotenv": "^17.3.1",
+ "express": "^5.2.1"
+ }
+ },
+ "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/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "license": "MIT"
+ },
+ "node_modules/axios": {
+ "version": "1.13.6",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.6.tgz",
+ "integrity": "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==",
+ "license": "MIT",
+ "dependencies": {
+ "follow-redirects": "^1.15.11",
+ "form-data": "^4.0.5",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
+ "node_modules/body-parser": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz",
+ "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==",
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "^3.1.2",
+ "content-type": "^1.0.5",
+ "debug": "^4.4.3",
+ "http-errors": "^2.0.0",
+ "iconv-lite": "^0.7.0",
+ "on-finished": "^2.4.1",
+ "qs": "^6.14.1",
+ "raw-body": "^3.0.1",
+ "type-is": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/call-bound": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
+ "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "get-intrinsic": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "license": "MIT",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/content-disposition": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz",
+ "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/content-type": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
+ "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "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/cors": {
+ "version": "2.8.6",
+ "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz",
+ "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==",
+ "license": "MIT",
+ "dependencies": {
+ "object-assign": "^4",
+ "vary": "^1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/dotenv": {
+ "version": "17.3.1",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.3.1.tgz",
+ "integrity": "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://dotenvx.com"
+ }
+ },
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
+ "license": "MIT"
+ },
+ "node_modules/encodeurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
+ "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+ "license": "MIT"
+ },
+ "node_modules/etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/express": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
+ "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==",
+ "license": "MIT",
+ "dependencies": {
+ "accepts": "^2.0.0",
+ "body-parser": "^2.2.1",
+ "content-disposition": "^1.0.0",
+ "content-type": "^1.0.5",
+ "cookie": "^0.7.1",
+ "cookie-signature": "^1.2.1",
+ "debug": "^4.4.0",
+ "depd": "^2.0.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/finalhandler": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz",
+ "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==",
+ "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": ">= 18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/follow-redirects": {
+ "version": "1.15.11",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
+ "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
+ "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "es-set-tostringtag": "^2.1.0",
+ "hasown": "^2.0.2",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/form-data/node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/form-data/node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/forwarded": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "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/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "license": "MIT",
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/http-errors": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
+ "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
+ "license": "MIT",
+ "dependencies": {
+ "depd": "~2.0.0",
+ "inherits": "~2.0.4",
+ "setprototypeof": "~1.2.0",
+ "statuses": "~2.0.2",
+ "toidentifier": "~1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz",
+ "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "license": "ISC"
+ },
+ "node_modules/ipaddr.js": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/is-promise": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
+ "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
+ "license": "MIT"
+ },
+ "node_modules/math-intrinsics": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "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/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/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/mime-types": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz",
+ "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "^1.54.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "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/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.13.4",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
+ "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/on-finished": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+ "license": "MIT",
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "license": "ISC",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/path-to-regexp": {
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz",
+ "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/proxy-addr": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+ "license": "MIT",
+ "dependencies": {
+ "forwarded": "0.2.0",
+ "ipaddr.js": "1.9.1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+ "license": "MIT"
+ },
+ "node_modules/qs": {
+ "version": "6.15.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz",
+ "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "side-channel": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/raw-body": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz",
+ "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==",
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "~3.1.2",
+ "http-errors": "~2.0.1",
+ "iconv-lite": "~0.7.0",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/router": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
+ "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.4.0",
+ "depd": "^2.0.0",
+ "is-promise": "^4.0.0",
+ "parseurl": "^1.3.3",
+ "path-to-regexp": "^8.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "license": "MIT"
+ },
+ "node_modules/send": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz",
+ "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.4.3",
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "etag": "^1.8.1",
+ "fresh": "^2.0.0",
+ "http-errors": "^2.0.1",
+ "mime-types": "^3.0.2",
+ "ms": "^2.1.3",
+ "on-finished": "^2.4.1",
+ "range-parser": "^1.2.1",
+ "statuses": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/serve-static": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz",
+ "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==",
+ "license": "MIT",
+ "dependencies": {
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "parseurl": "^1.3.3",
+ "send": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/setprototypeof": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+ "license": "ISC"
+ },
+ "node_modules/side-channel": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
+ "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.3",
+ "side-channel-list": "^1.0.0",
+ "side-channel-map": "^1.0.1",
+ "side-channel-weakmap": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-list": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
+ "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-map": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
+ "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-weakmap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
+ "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3",
+ "side-channel-map": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/statuses": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
+ "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/toidentifier": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "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/unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "license": "ISC"
+ }
+ }
+}
diff --git a/backend/package-lock_副本.json b/backend/package-lock_副本.json
new file mode 100644
index 00000000..7e5cb68a
--- /dev/null
+++ b/backend/package-lock_副本.json
@@ -0,0 +1,999 @@
+{
+ "name": "hololake-backend",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "hololake-backend",
+ "version": "1.0.0",
+ "license": "ISC",
+ "dependencies": {
+ "axios": "^1.13.6",
+ "cors": "^2.8.6",
+ "dotenv": "^17.3.1",
+ "express": "^5.2.1"
+ }
+ },
+ "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/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "license": "MIT"
+ },
+ "node_modules/axios": {
+ "version": "1.13.6",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.6.tgz",
+ "integrity": "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==",
+ "license": "MIT",
+ "dependencies": {
+ "follow-redirects": "^1.15.11",
+ "form-data": "^4.0.5",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
+ "node_modules/body-parser": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz",
+ "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==",
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "^3.1.2",
+ "content-type": "^1.0.5",
+ "debug": "^4.4.3",
+ "http-errors": "^2.0.0",
+ "iconv-lite": "^0.7.0",
+ "on-finished": "^2.4.1",
+ "qs": "^6.14.1",
+ "raw-body": "^3.0.1",
+ "type-is": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/call-bound": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
+ "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "get-intrinsic": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "license": "MIT",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/content-disposition": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz",
+ "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/content-type": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
+ "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "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/cors": {
+ "version": "2.8.6",
+ "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz",
+ "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==",
+ "license": "MIT",
+ "dependencies": {
+ "object-assign": "^4",
+ "vary": "^1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/dotenv": {
+ "version": "17.3.1",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.3.1.tgz",
+ "integrity": "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://dotenvx.com"
+ }
+ },
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
+ "license": "MIT"
+ },
+ "node_modules/encodeurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
+ "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+ "license": "MIT"
+ },
+ "node_modules/etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/express": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
+ "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==",
+ "license": "MIT",
+ "dependencies": {
+ "accepts": "^2.0.0",
+ "body-parser": "^2.2.1",
+ "content-disposition": "^1.0.0",
+ "content-type": "^1.0.5",
+ "cookie": "^0.7.1",
+ "cookie-signature": "^1.2.1",
+ "debug": "^4.4.0",
+ "depd": "^2.0.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/finalhandler": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz",
+ "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==",
+ "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": ">= 18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/follow-redirects": {
+ "version": "1.15.11",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
+ "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
+ "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "es-set-tostringtag": "^2.1.0",
+ "hasown": "^2.0.2",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/form-data/node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/form-data/node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/forwarded": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "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/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "license": "MIT",
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/http-errors": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
+ "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
+ "license": "MIT",
+ "dependencies": {
+ "depd": "~2.0.0",
+ "inherits": "~2.0.4",
+ "setprototypeof": "~1.2.0",
+ "statuses": "~2.0.2",
+ "toidentifier": "~1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz",
+ "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "license": "ISC"
+ },
+ "node_modules/ipaddr.js": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/is-promise": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
+ "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
+ "license": "MIT"
+ },
+ "node_modules/math-intrinsics": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "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/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/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/mime-types": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz",
+ "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "^1.54.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "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/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.13.4",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
+ "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/on-finished": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+ "license": "MIT",
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "license": "ISC",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/path-to-regexp": {
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz",
+ "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/proxy-addr": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+ "license": "MIT",
+ "dependencies": {
+ "forwarded": "0.2.0",
+ "ipaddr.js": "1.9.1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+ "license": "MIT"
+ },
+ "node_modules/qs": {
+ "version": "6.15.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz",
+ "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "side-channel": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/raw-body": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz",
+ "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==",
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "~3.1.2",
+ "http-errors": "~2.0.1",
+ "iconv-lite": "~0.7.0",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/router": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
+ "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.4.0",
+ "depd": "^2.0.0",
+ "is-promise": "^4.0.0",
+ "parseurl": "^1.3.3",
+ "path-to-regexp": "^8.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "license": "MIT"
+ },
+ "node_modules/send": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz",
+ "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.4.3",
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "etag": "^1.8.1",
+ "fresh": "^2.0.0",
+ "http-errors": "^2.0.1",
+ "mime-types": "^3.0.2",
+ "ms": "^2.1.3",
+ "on-finished": "^2.4.1",
+ "range-parser": "^1.2.1",
+ "statuses": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/serve-static": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz",
+ "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==",
+ "license": "MIT",
+ "dependencies": {
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "parseurl": "^1.3.3",
+ "send": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/setprototypeof": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+ "license": "ISC"
+ },
+ "node_modules/side-channel": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
+ "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.3",
+ "side-channel-list": "^1.0.0",
+ "side-channel-map": "^1.0.1",
+ "side-channel-weakmap": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-list": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
+ "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-map": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
+ "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-weakmap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
+ "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3",
+ "side-channel-map": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/statuses": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
+ "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/toidentifier": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "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/unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "license": "ISC"
+ }
+ }
+}
diff --git a/backend/package.json b/backend/package.json
new file mode 100644
index 00000000..67893707
--- /dev/null
+++ b/backend/package.json
@@ -0,0 +1,19 @@
+{
+ "name": "hololake-backend",
+ "version": "1.0.0",
+ "main": "server.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "start": "node server.js"
+ },
+ "keywords": [],
+ "author": "",
+ "license": "ISC",
+ "description": "",
+ "dependencies": {
+ "axios": "^1.13.6",
+ "cors": "^2.8.6",
+ "dotenv": "^17.3.1",
+ "express": "^5.2.1"
+ }
+}
diff --git a/backend/package_副本.json b/backend/package_副本.json
new file mode 100644
index 00000000..67893707
--- /dev/null
+++ b/backend/package_副本.json
@@ -0,0 +1,19 @@
+{
+ "name": "hololake-backend",
+ "version": "1.0.0",
+ "main": "server.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "start": "node server.js"
+ },
+ "keywords": [],
+ "author": "",
+ "license": "ISC",
+ "description": "",
+ "dependencies": {
+ "axios": "^1.13.6",
+ "cors": "^2.8.6",
+ "dotenv": "^17.3.1",
+ "express": "^5.2.1"
+ }
+}
diff --git a/backend/routes/feishu.js b/backend/routes/feishu.js
new file mode 100644
index 00000000..85467da7
--- /dev/null
+++ b/backend/routes/feishu.js
@@ -0,0 +1,52 @@
+const express = require('express');
+const axios = require('axios');
+const router = express.Router();
+
+const FEISHU_APP_ID = process.env.FEISHU_APP_ID;
+const FEISHU_APP_SECRET = process.env.FEISHU_APP_SECRET;
+const BASE_URL = 'https://open.feishu.cn/open-apis';
+
+// 获取飞书 tenant_access_token
+async function getToken() {
+ const response = await axios.post(
+ BASE_URL + '/auth/v3/tenant_access_token/internal',
+ {
+ app_id: FEISHU_APP_ID,
+ app_secret: FEISHU_APP_SECRET
+ }
+ );
+ return response.data.tenant_access_token;
+}
+
+router.get('/test', (req, res) => {
+ res.json({
+ status: 'ok',
+ message: '飞书路由正常',
+ app_id_configured: !!FEISHU_APP_ID,
+ app_secret_configured: !!FEISHU_APP_SECRET
+ });
+});
+
+// 发送消息到飞书群
+router.post('/broadcast', async (req, res) => {
+ try {
+ const { chat_id, title, content } = req.body;
+ const token = await getToken();
+ const response = await axios.post(
+ BASE_URL + '/im/v1/messages?receive_id_type=chat_id',
+ {
+ receive_id: chat_id,
+ msg_type: 'text',
+ content: JSON.stringify({ text: title + '\n\n' + content })
+ },
+ {
+ headers: { 'Authorization': 'Bearer ' + token }
+ }
+ );
+ res.json(response.data);
+ } catch (err) {
+ res.status(500).json({ error: err.message, detail: err.response ? err.response.data : null });
+ }
+});
+
+module.exports = router;
diff --git a/backend/routes/notion.js b/backend/routes/notion.js
new file mode 100644
index 00000000..2574f4f8
--- /dev/null
+++ b/backend/routes/notion.js
@@ -0,0 +1,61 @@
+const express = require('express');
+const axios = require('axios');
+const router = express.Router();
+
+const NOTION_TOKEN = process.env.NOTION_TOKEN;
+const NOTION_VERSION = '2022-06-28';
+const BASE_URL = 'https://api.notion.com/v1';
+
+const headers = () => ({
+ 'Authorization': 'Bearer ' + NOTION_TOKEN,
+ 'Content-Type': 'application/json',
+ 'Notion-Version': NOTION_VERSION
+});
+
+router.get('/test', (req, res) => {
+ res.json({
+ status: 'ok',
+ message: 'Notion 路由正常',
+ token_configured: !!NOTION_TOKEN
+ });
+});
+
+router.get('/database/:id', async (req, res) => {
+ try {
+ const response = await axios.post(
+ BASE_URL + '/databases/' + req.params.id + '/query',
+ {},
+ { headers: headers() }
+ );
+ res.json(response.data);
+ } catch (err) {
+ res.status(500).json({ error: err.message, detail: err.response ? err.response.data : null });
+ }
+});
+
+router.get('/page/:id', async (req, res) => {
+ try {
+ const response = await axios.get(
+ BASE_URL + '/pages/' + req.params.id,
+ { headers: headers() }
+ );
+ res.json(response.data);
+ } catch (err) {
+ res.status(500).json({ error: err.message, detail: err.response ? err.response.data : null });
+ }
+});
+
+router.post('/page', async (req, res) => {
+ try {
+ const response = await axios.post(
+ BASE_URL + '/pages',
+ req.body,
+ { headers: headers() }
+ );
+ res.json(response.data);
+ } catch (err) {
+ res.status(500).json({ error: err.message, detail: err.response ? err.response.data : null });
+ }
+});
+
+module.exports = router;
diff --git a/backend/routes/router.js b/backend/routes/router.js
new file mode 100644
index 00000000..2189677c
--- /dev/null
+++ b/backend/routes/router.js
@@ -0,0 +1,58 @@
+const express = require('express');
+const axios = require('axios');
+const router = express.Router();
+const { MODELS, DEFAULT_MODEL } = require('../config/models');
+
+router.get('/test', (req, res) => {
+ res.json({
+ status: 'ok',
+ message: '模型路由正常 ❤️',
+ available_models: Object.keys(MODELS),
+ default_model: DEFAULT_MODEL
+ });
+});
+
+router.post('/chat', async (req, res) => {
+ try {
+ const { message, model_name } = req.body;
+ const model = MODELS[model_name || DEFAULT_MODEL];
+
+ if (!model) {
+ return res.status(400).json({ error: '未知模型: ' + model_name });
+ }
+
+ if (!model.apiKey) {
+ return res.status(503).json({
+ error: '模型 ' + model.name + ' 的 API Key 尚未配置',
+ hint: '请检查 .env 文件中的 YUNWU_API_KEY'
+ });
+ }
+
+ const response = await axios.post(
+ model.apiUrl,
+ {
+ model: model.model,
+ messages: [{ role: 'user', content: message }],
+ max_tokens: model.maxTokens
+ },
+ {
+ headers: {
+ 'Authorization': 'Bearer ' + model.apiKey,
+ 'Content-Type': 'application/json'
+ }
+ }
+ );
+
+ res.json({
+ model: model.name,
+ reply: response.data.choices[0].message.content
+ });
+ } catch (err) {
+ res.status(500).json({
+ error: err.message,
+ detail: err.response ? err.response.data : null
+ });
+ }
+});
+
+module.exports = router;
diff --git a/backend/routes_副本/feishu.js b/backend/routes_副本/feishu.js
new file mode 100644
index 00000000..85467da7
--- /dev/null
+++ b/backend/routes_副本/feishu.js
@@ -0,0 +1,52 @@
+const express = require('express');
+const axios = require('axios');
+const router = express.Router();
+
+const FEISHU_APP_ID = process.env.FEISHU_APP_ID;
+const FEISHU_APP_SECRET = process.env.FEISHU_APP_SECRET;
+const BASE_URL = 'https://open.feishu.cn/open-apis';
+
+// 获取飞书 tenant_access_token
+async function getToken() {
+ const response = await axios.post(
+ BASE_URL + '/auth/v3/tenant_access_token/internal',
+ {
+ app_id: FEISHU_APP_ID,
+ app_secret: FEISHU_APP_SECRET
+ }
+ );
+ return response.data.tenant_access_token;
+}
+
+router.get('/test', (req, res) => {
+ res.json({
+ status: 'ok',
+ message: '飞书路由正常',
+ app_id_configured: !!FEISHU_APP_ID,
+ app_secret_configured: !!FEISHU_APP_SECRET
+ });
+});
+
+// 发送消息到飞书群
+router.post('/broadcast', async (req, res) => {
+ try {
+ const { chat_id, title, content } = req.body;
+ const token = await getToken();
+ const response = await axios.post(
+ BASE_URL + '/im/v1/messages?receive_id_type=chat_id',
+ {
+ receive_id: chat_id,
+ msg_type: 'text',
+ content: JSON.stringify({ text: title + '\n\n' + content })
+ },
+ {
+ headers: { 'Authorization': 'Bearer ' + token }
+ }
+ );
+ res.json(response.data);
+ } catch (err) {
+ res.status(500).json({ error: err.message, detail: err.response ? err.response.data : null });
+ }
+});
+
+module.exports = router;
diff --git a/backend/routes_副本/notion.js b/backend/routes_副本/notion.js
new file mode 100644
index 00000000..2574f4f8
--- /dev/null
+++ b/backend/routes_副本/notion.js
@@ -0,0 +1,61 @@
+const express = require('express');
+const axios = require('axios');
+const router = express.Router();
+
+const NOTION_TOKEN = process.env.NOTION_TOKEN;
+const NOTION_VERSION = '2022-06-28';
+const BASE_URL = 'https://api.notion.com/v1';
+
+const headers = () => ({
+ 'Authorization': 'Bearer ' + NOTION_TOKEN,
+ 'Content-Type': 'application/json',
+ 'Notion-Version': NOTION_VERSION
+});
+
+router.get('/test', (req, res) => {
+ res.json({
+ status: 'ok',
+ message: 'Notion 路由正常',
+ token_configured: !!NOTION_TOKEN
+ });
+});
+
+router.get('/database/:id', async (req, res) => {
+ try {
+ const response = await axios.post(
+ BASE_URL + '/databases/' + req.params.id + '/query',
+ {},
+ { headers: headers() }
+ );
+ res.json(response.data);
+ } catch (err) {
+ res.status(500).json({ error: err.message, detail: err.response ? err.response.data : null });
+ }
+});
+
+router.get('/page/:id', async (req, res) => {
+ try {
+ const response = await axios.get(
+ BASE_URL + '/pages/' + req.params.id,
+ { headers: headers() }
+ );
+ res.json(response.data);
+ } catch (err) {
+ res.status(500).json({ error: err.message, detail: err.response ? err.response.data : null });
+ }
+});
+
+router.post('/page', async (req, res) => {
+ try {
+ const response = await axios.post(
+ BASE_URL + '/pages',
+ req.body,
+ { headers: headers() }
+ );
+ res.json(response.data);
+ } catch (err) {
+ res.status(500).json({ error: err.message, detail: err.response ? err.response.data : null });
+ }
+});
+
+module.exports = router;
diff --git a/backend/routes_副本/router.js b/backend/routes_副本/router.js
new file mode 100644
index 00000000..2189677c
--- /dev/null
+++ b/backend/routes_副本/router.js
@@ -0,0 +1,58 @@
+const express = require('express');
+const axios = require('axios');
+const router = express.Router();
+const { MODELS, DEFAULT_MODEL } = require('../config/models');
+
+router.get('/test', (req, res) => {
+ res.json({
+ status: 'ok',
+ message: '模型路由正常 ❤️',
+ available_models: Object.keys(MODELS),
+ default_model: DEFAULT_MODEL
+ });
+});
+
+router.post('/chat', async (req, res) => {
+ try {
+ const { message, model_name } = req.body;
+ const model = MODELS[model_name || DEFAULT_MODEL];
+
+ if (!model) {
+ return res.status(400).json({ error: '未知模型: ' + model_name });
+ }
+
+ if (!model.apiKey) {
+ return res.status(503).json({
+ error: '模型 ' + model.name + ' 的 API Key 尚未配置',
+ hint: '请检查 .env 文件中的 YUNWU_API_KEY'
+ });
+ }
+
+ const response = await axios.post(
+ model.apiUrl,
+ {
+ model: model.model,
+ messages: [{ role: 'user', content: message }],
+ max_tokens: model.maxTokens
+ },
+ {
+ headers: {
+ 'Authorization': 'Bearer ' + model.apiKey,
+ 'Content-Type': 'application/json'
+ }
+ }
+ );
+
+ res.json({
+ model: model.name,
+ reply: response.data.choices[0].message.content
+ });
+ } catch (err) {
+ res.status(500).json({
+ error: err.message,
+ detail: err.response ? err.response.data : null
+ });
+ }
+});
+
+module.exports = router;
diff --git a/backend/server.js b/backend/server.js
new file mode 100644
index 00000000..b58be470
--- /dev/null
+++ b/backend/server.js
@@ -0,0 +1,38 @@
+require('dotenv').config();
+const express = require('express');
+const cors = require('cors');
+
+const app = express();
+app.use(cors());
+app.use(express.json());
+
+// 路由引入
+const notionRoutes = require('./routes/notion');
+const feishuRoutes = require('./routes/feishu');
+const routerRoutes = require('./routes/router');
+
+app.use('/notion', notionRoutes);
+app.use('/feishu', feishuRoutes);
+app.use('/router', routerRoutes);
+
+app.get('/', (req, res) => {
+ res.json({
+ status: 'ok',
+ message: 'HoloLake 后端服务运行中',
+ version: '0.2.0',
+ routes: ['/notion/test', '/feishu/test', '/router/test', '/router/chat']
+ });
+});
+
+const PORT = process.env.PORT || 3000;
+// 飞书 Webhook 处理
+app.post('/webhook/feishu', (req, res) => {
+ console.log('收到飞书请求:', req.body);
+ if (req.body.challenge) {
+ return res.json({ challenge: req.body.challenge });
+ }
+ res.json({ message: 'received' });
+});
+app.listen(PORT, () => {
+ console.log(`🚀 服务启动成功,端口:${PORT}`);
+});
diff --git a/backend/server_副本.js b/backend/server_副本.js
new file mode 100644
index 00000000..b58be470
--- /dev/null
+++ b/backend/server_副本.js
@@ -0,0 +1,38 @@
+require('dotenv').config();
+const express = require('express');
+const cors = require('cors');
+
+const app = express();
+app.use(cors());
+app.use(express.json());
+
+// 路由引入
+const notionRoutes = require('./routes/notion');
+const feishuRoutes = require('./routes/feishu');
+const routerRoutes = require('./routes/router');
+
+app.use('/notion', notionRoutes);
+app.use('/feishu', feishuRoutes);
+app.use('/router', routerRoutes);
+
+app.get('/', (req, res) => {
+ res.json({
+ status: 'ok',
+ message: 'HoloLake 后端服务运行中',
+ version: '0.2.0',
+ routes: ['/notion/test', '/feishu/test', '/router/test', '/router/chat']
+ });
+});
+
+const PORT = process.env.PORT || 3000;
+// 飞书 Webhook 处理
+app.post('/webhook/feishu', (req, res) => {
+ console.log('收到飞书请求:', req.body);
+ if (req.body.challenge) {
+ return res.json({ challenge: req.body.challenge });
+ }
+ res.json({ message: 'received' });
+});
+app.listen(PORT, () => {
+ console.log(`🚀 服务启动成功,端口:${PORT}`);
+});
From f785ea06ebc21c0a911589d4e426e0b1d4ef2c2b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=93=B8=E6=B8=8A=20=28Zh=C3=B9Yu=C4=81n=29?=
Date: Sat, 7 Mar 2026 07:10:01 +0000
Subject: [PATCH 05/57] =?UTF-8?q?=F0=9F=93=9A=20=E9=93=B8=E6=B8=8A?=
=?UTF-8?q?=E5=9B=BE=E4=B9=A6=E9=A6=86=E7=9B=AE=E5=BD=95=E6=9B=B4=E6=96=B0?=
=?UTF-8?q?=20=C2=B7=202026-03-07T07:10?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/brain/repo-map.json | 2 +-
.github/brain/repo-snapshot.md | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/.github/brain/repo-map.json b/.github/brain/repo-map.json
index eba50044..ae9d96b7 100644
--- a/.github/brain/repo-map.json
+++ b/.github/brain/repo-map.json
@@ -1,7 +1,7 @@
{
"description": "铸渊图书馆目录 · Library Catalog for 铸渊 (Zhùyuān)",
"version": "2.0",
- "generated_at": "2026-03-07T05:59:15.498Z",
+ "generated_at": "2026-03-07T07:10:00.964Z",
"generated_by": "scripts/generate-repo-map.js",
"repo": "qinfendebingshuo/guanghulab",
"stats": {
diff --git a/.github/brain/repo-snapshot.md b/.github/brain/repo-snapshot.md
index fdf043b2..442f78d9 100644
--- a/.github/brain/repo-snapshot.md
+++ b/.github/brain/repo-snapshot.md
@@ -1,5 +1,5 @@
# 铸渊图书馆快照 · Repo Snapshot
-> 生成于 2026-03-07 13:59 CST · 每次 push 自动更新 · 铸渊唤醒时优先读取此文件
+> 生成于 2026-03-07 15:10 CST · 每次 push 自动更新 · 铸渊唤醒时优先读取此文件
---
@@ -13,7 +13,7 @@
| 脚本 | 15 个执行脚本 |
| 开发者节点 | 8 人 |
| HLI 接口覆盖率 | 3/17 (18%) |
-| 快照生成时间 | 2026-03-07 13:59 CST |
+| 快照生成时间 | 2026-03-07 15:10 CST |
---
From aac7f53d4b36a591d0bf8facbfd583412bda704b Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 7 Mar 2026 07:21:28 +0000
Subject: [PATCH 06/57] =?UTF-8?q?feat:=20upgrade=20=E9=93=B8=E6=B8=8A?=
=?UTF-8?q?=E5=8A=A9=E6=89=8B=20to=20v4.0=20with=20three-column=20layout?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Three-column layout on desktop (>900px): left sidebar, center area, right sidebar
- Left sidebar: user identity, nav tabs (公告栏/聊天), conversation history, settings
- Center area switches between announcements and chat views
- Right sidebar: always-visible team panel for controllers (founder/supreme/main)
- Chat history system with localStorage (zy_conversations, max 20 conversations)
- Announcements page with system info from brain files, tasks, quick actions
- Mobile responsive: left sidebar toggleable via hamburger menu
- Identity preview on setup screen with DEV-ID display
- All existing JS functions, API streaming, demo mode, brain loading preserved
- Version bumped from v3.1 to v4.0
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
docs/index.html | 723 ++++++++++++++++++++++++++++++++++--------
frontend/HoloLake-App | 1 -
2 files changed, 597 insertions(+), 127 deletions(-)
delete mode 160000 frontend/HoloLake-App
diff --git a/docs/index.html b/docs/index.html
index 4eb9924e..6c243db1 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -1,5 +1,5 @@
-
+
@@ -17,6 +17,7 @@
--text:#e2e8f0;--dim:#64748b;--muted:#1e293b;
--mc:#4f8ef7;--mb:#fb923c;--mr:#a78bfa;--mn:#34d399;
--r:14px;--rs:8px;
+ --ls-w:260px;--rs-w:360px;
}
html,body{height:100%;background:var(--bg);color:var(--text);font-family:'PingFang SC','Microsoft YaHei','Segoe UI',sans-serif;font-size:15px;line-height:1.6}
@@ -37,10 +38,87 @@ html,body{height:100%;background:var(--bg);color:var(--text);font-family:'PingFa
.sc-btn:hover{opacity:.85}
.sc-skip{text-align:center;font-size:12px;color:var(--dim);margin-top:12px}
.sc-skip a{color:var(--accent);text-decoration:none;cursor:pointer}
+#id-preview{display:none;text-align:center;margin-bottom:10px;padding:10px;background:var(--s3);border-radius:8px;font-size:14px;font-weight:600}
-/* ─── APP SHELL ─── */
-#app{display:none;flex-direction:column;height:100vh;max-width:820px;margin:0 auto}
-#app.on{display:flex}
+/* ─── APP SHELL (three-column) ─── */
+#app{display:none;height:100vh;width:100%;overflow:hidden}
+#app.on{display:flex;flex-direction:column}
+
+/* ─── LEFT SIDEBAR ─── */
+#left-sidebar{width:var(--ls-w);flex-shrink:0;background:var(--s1);border-right:1px solid var(--border);display:none;flex-direction:column;overflow:hidden;z-index:120}
+.ls-header{padding:16px;border-bottom:1px solid var(--border)}
+.ls-user{display:flex;align-items:center;gap:10px}
+.ls-avatar{width:40px;height:40px;border-radius:50%;background:linear-gradient(135deg,var(--accent),var(--a2));display:flex;align-items:center;justify-content:center;font-weight:700;font-size:16px;flex-shrink:0}
+.ls-name{font-size:14px;font-weight:600}
+.ls-role{font-size:11px;color:var(--dim)}
+.ls-devid{font-size:10px;color:var(--accent);background:var(--adim);padding:1px 6px;border-radius:4px;display:inline-block;margin-top:2px}
+.ls-nav{padding:8px;border-bottom:1px solid var(--border);display:flex;flex-direction:column;gap:2px}
+.nav-tab{display:flex;align-items:center;gap:8px;padding:9px 12px;border-radius:var(--rs);background:transparent;border:none;color:var(--dim);font-size:13px;font-weight:500;cursor:pointer;transition:all .2s;text-align:left;font-family:inherit;width:100%}
+.nav-tab:hover{background:var(--s2);color:var(--text)}
+.nav-tab.active{background:var(--adim);color:var(--accent);font-weight:600}
+.ls-new-conv{margin:8px;padding:10px;border-radius:var(--rs);border:1px dashed var(--border);background:transparent;color:var(--dim);font-size:13px;cursor:pointer;transition:all .2s;font-family:inherit;display:flex;align-items:center;justify-content:center;gap:6px}
+.ls-new-conv:hover{border-color:var(--accent);color:var(--accent);background:var(--adim)}
+.ls-conv-list{flex:1;overflow-y:auto;padding:4px 8px}
+.ls-conv-list::-webkit-scrollbar{width:3px}
+.ls-conv-list::-webkit-scrollbar-thumb{background:var(--border);border-radius:3px}
+.conv-item{padding:10px;border-radius:var(--rs);cursor:pointer;transition:all .2s;position:relative;margin-bottom:2px;border:1px solid transparent}
+.conv-item:hover{background:var(--s2);border-color:var(--border)}
+.conv-item.conv-active{background:var(--adim);border-color:var(--accent)}
+.conv-title{font-size:13px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding-right:20px}
+.conv-time{font-size:10px;color:var(--dim);margin-top:2px}
+.conv-del{position:absolute;top:8px;right:6px;background:transparent;border:none;color:var(--dim);font-size:11px;cursor:pointer;padding:2px 4px;border-radius:4px;opacity:0;transition:all .2s}
+.conv-item:hover .conv-del{opacity:1}
+.conv-del:hover{color:var(--err);background:rgba(248,113,113,.1)}
+.conv-empty{padding:20px 12px;text-align:center;font-size:12px;color:var(--dim)}
+.ls-footer{padding:8px;border-top:1px solid var(--border)}
+.ls-footer-btn{display:flex;align-items:center;gap:8px;padding:9px 12px;border-radius:var(--rs);background:transparent;border:none;color:var(--dim);font-size:13px;cursor:pointer;transition:all .2s;width:100%;font-family:inherit;text-align:left}
+.ls-footer-btn:hover{background:var(--s2);color:var(--text)}
+
+/* ─── LEFT SIDEBAR MOBILE OVERLAY ─── */
+#ls-overlay{display:none;position:fixed;inset:0;z-index:110;background:rgba(0,0,0,.5)}
+#ls-overlay.on{display:block}
+
+/* ─── CENTER AREA ─── */
+#center-area{flex:1;display:flex;flex-direction:column;min-width:0;overflow:hidden}
+
+/* ─── CHAT VIEW ─── */
+#chat-view{display:flex;flex-direction:column;flex:1;min-height:0}
+
+/* ─── ANNOUNCEMENTS VIEW ─── */
+#announcements-view{display:none;flex-direction:column;flex:1;overflow-y:auto;background:var(--bg)}
+.ann-header{padding:20px 24px 12px;border-bottom:1px solid var(--border);background:var(--s1);flex-shrink:0}
+.ann-header h2{font-size:18px;font-weight:700}
+.ann-header-sub{font-size:12px;color:var(--dim);margin-top:4px}
+.ann-scroll{flex:1;overflow-y:auto;padding:20px 24px}
+.ann-scroll::-webkit-scrollbar{width:4px}
+.ann-scroll::-webkit-scrollbar-thumb{background:var(--border);border-radius:4px}
+.ann-section{margin-bottom:20px}
+.ann-section-title{font-size:13px;font-weight:600;color:var(--text);margin-bottom:10px;display:flex;align-items:center;gap:6px}
+.ann-card{background:var(--s1);border:1px solid var(--border);border-radius:12px;padding:14px;transition:border-color .2s}
+.ann-card:hover{border-color:rgba(79,142,247,.3)}
+.ann-item{padding:8px 0;border-bottom:1px solid rgba(30,50,81,.4);font-size:13px;line-height:1.7;display:flex;align-items:flex-start;gap:6px}
+.ann-item:last-child{border-bottom:none}
+.ann-date{font-size:10px;color:var(--dim);white-space:nowrap;margin-left:auto}
+.ann-actions{display:flex;flex-wrap:wrap;gap:8px}
+.ann-action-btn{padding:10px 16px;border-radius:var(--rs);background:var(--s1);border:1px solid var(--border);color:var(--text);font-size:13px;cursor:pointer;transition:all .2s;font-family:inherit}
+.ann-action-btn:hover{border-color:var(--accent);color:var(--accent);background:var(--adim)}
+
+/* ─── RIGHT SIDEBAR ─── */
+#right-sidebar{width:var(--rs-w);flex-shrink:0;background:var(--s1);border-left:1px solid var(--border);display:none;flex-direction:column;overflow:hidden}
+.rs-header{padding:14px 16px;border-bottom:1px solid var(--border);flex-shrink:0}
+.rs-header h3{font-size:14px;font-weight:600}
+.rs-body{flex:1;overflow-y:auto;padding:14px}
+.rs-body::-webkit-scrollbar{width:3px}
+.rs-body::-webkit-scrollbar-thumb{background:var(--border);border-radius:3px}
+.rs-section{margin-bottom:16px}
+.rs-section-title{font-size:11px;color:var(--dim);text-transform:uppercase;letter-spacing:.1em;margin-bottom:8px;padding-bottom:6px;border-bottom:1px solid var(--border)}
+.rs-module-card{padding:8px 10px;background:var(--s2);border:1px solid var(--border);border-radius:var(--rs);margin-bottom:6px;font-size:12px}
+.rs-module-name{font-weight:600;font-size:12px}
+.rs-module-status{font-size:11px;color:var(--dim);margin-top:2px}
+.rs-empty{font-size:12px;color:var(--dim);padding:10px 0}
+
+/* ─── HAMBURGER ─── */
+.hamburger-btn{display:none !important}
/* ─── HEADER ─── */
header{display:flex;align-items:center;justify-content:space-between;padding:11px 18px;background:var(--s1);border-bottom:1px solid var(--border);flex-shrink:0;gap:10px}
@@ -209,7 +287,22 @@ footer{padding:12px 18px 16px;background:var(--s1);border-top:1px solid var(--bo
.ctrl-panel-title{font-size:14px;font-weight:700;color:#fb923c;margin-bottom:4px}
.ctrl-panel-sub{font-size:11px;color:var(--dim)}
-/* ─── RESPONSIVE ─── */
+/* ─── RESPONSIVE: DESKTOP (three-column) ─── */
+@media(min-width:900px){
+ #app.on{flex-direction:row}
+ #left-sidebar{display:flex}
+ .hamburger-btn{display:none !important}
+ #chat-view header{border-top:none}
+ #center-area{border-left:none;border-right:none}
+}
+
+/* ─── RESPONSIVE: MOBILE ─── */
+@media(max-width:899px){
+ #left-sidebar{position:fixed;top:0;left:-280px;height:100vh;width:270px;z-index:120;transition:left .3s ease}
+ #left-sidebar.open{left:0}
+ .hamburger-btn{display:flex !important}
+ #right-sidebar{display:none !important}
+}
@media(max-width:600px){
.bbl{max-width:90%}
.hr .ib:nth-child(n+3){display:none}
@@ -223,8 +316,8 @@ footer{padding:12px 18px 16px;background:var(--s1);border-top:1px solid var(--bo
🌀
- 铸渊助手
- HoloLake · 代码守护人格体 · 持续成长的 AI 伙伴
+ AGE OS · 登录
+ HoloLake · 铸渊(Zhùyuān)· 代码守护人格体
🔒 API 密钥仅本次会话有效,关闭标签页即自动清除,不会持久保存在任何地方
@@ -259,11 +352,12 @@ footer{padding:12px 18px 16px;background:var(--s1);border-top:1px solid var(--bo
-
- 👤 身份识别(可选)
+
+ 👤 身份识别
+
-
-
+
-
-
- 铸
-
- 铸渊(Zhùyuān)
-
-
- 💬 对话模式
- ·
- —
- ·
-
+
+
+
-
+
🦁 指挥台 · 全员进度
@@ -585,11 +737,10 @@ const MODES = {
const MODE_ORD = ['chat','build','review','brain'];
const DEFAULT_MDL = 'gpt-4o';
-const PROBE_TIMEOUT_MS = 8000; // ms per provider probe in autoDetectAPI
+const PROBE_TIMEOUT_MS = 8000;
const FB_COV = {implemented:3,total:17,percent:'17.6%'};
-// KEY_MASK is no longer used in the input field; kept only for backward compatibility
-// with any saved value that might still be in localStorage.
const KEY_MASK = '(已保存)';
+const MAX_CONVERSATIONS = 20;
const FB_BRAIN = {
identity:'铸渊(Zhùyuān)· GitHub 代码守护人格体',
@@ -601,7 +752,6 @@ const FB_BRAIN = {
// ═══════════════════════════════════════════════════════
// STATE
// ═══════════════════════════════════════════════════════
-// Derive base URL from saved provider; never use stale zy_base for named providers
const _initProv = ls('zy_prov')||'yunwu';
const _initBase = _initProv === 'custom'
? (ls('zy_base')||'')
@@ -616,11 +766,12 @@ const A = {
brain: null,
routing: null,
devStatus: null,
- msgs: [], // current conversation
+ msgs: [],
+ currentConvId: null,
+ currentView: 'announcements',
streaming: false,
mode: 'chat',
modeIdx: 0,
- // identity
userName: ls('zy_uname')||'',
ghUser: ls('zy_ghuser')||'',
role: ls('zy_role')||'guest',
@@ -632,33 +783,334 @@ function lss(k,v){localStorage.setItem(k,v)}
const RESET_KEYS = ['zy_key','zy_base','zy_mdl','zy_prov','zy_uname','zy_ghuser','zy_role'];
+// ═══════════════════════════════════════════════════════
+// CHAT HISTORY (localStorage)
+// ═══════════════════════════════════════════════════════
+function loadConversations(){
+ try{return JSON.parse(localStorage.getItem('zy_conversations')||'[]');}
+ catch(e){return [];}
+}
+function saveConversations(convs){
+ localStorage.setItem('zy_conversations',JSON.stringify(convs.slice(0,MAX_CONVERSATIONS)));
+}
+function createNewConversation(){
+ const conv={
+ id:Date.now().toString(36)+Math.random().toString(36).slice(2,6),
+ title:'新对话',
+ messages:[],
+ createdAt:new Date().toISOString(),
+ updatedAt:new Date().toISOString()
+ };
+ const convs=loadConversations();
+ convs.unshift(conv);
+ saveConversations(convs);
+ A.currentConvId=conv.id;
+ return conv;
+}
+function getConvTitle(){
+ const first=A.msgs.find(m=>m.role==='user');
+ if(!first) return '新对话';
+ return first.content.length>20 ? first.content.slice(0,20)+'…' : first.content;
+}
+function saveCurrentConversation(){
+ if(!A.currentConvId||!A.msgs.length) return;
+ const convs=loadConversations();
+ const idx=convs.findIndex(c=>c.id===A.currentConvId);
+ const conv={
+ id:A.currentConvId,
+ title:getConvTitle(),
+ messages:A.msgs.slice(),
+ createdAt:idx>=0?convs[idx].createdAt:new Date().toISOString(),
+ updatedAt:new Date().toISOString()
+ };
+ if(idx>=0) convs[idx]=conv;
+ else convs.unshift(conv);
+ saveConversations(convs);
+ renderConvList();
+}
+function loadConversation(id){
+ const convs=loadConversations();
+ const conv=convs.find(c=>c.id===id);
+ if(!conv) return;
+ A.currentConvId=id;
+ A.msgs=conv.messages.slice();
+ const msgsEl=document.getElementById('msgs');
+ msgsEl.innerHTML='';
+ for(const msg of A.msgs){
+ if(msg.role==='user') userMsg(msg.content);
+ else if(msg.role==='assistant'){
+ const bblEl=botMsg(md(msg.content));
+ if(bblEl) addCopyBtns(bblEl);
+ }
+ }
+ renderConvList();
+ navigateTo('chat');
+}
+function deleteConversation(id){
+ let convs=loadConversations();
+ convs=convs.filter(c=>c.id!==id);
+ saveConversations(convs);
+ if(A.currentConvId===id){
+ A.currentConvId=null;
+ A.msgs=[];
+ document.getElementById('msgs').innerHTML='';
+ createNewConversation();
+ startConv();
+ }
+ renderConvList();
+}
+function renderConvList(){
+ const el=document.getElementById('conv-list');
+ if(!el) return;
+ const convs=loadConversations();
+ if(!convs.length){
+ el.innerHTML=' 暂无历史对话 ';
+ return;
+ }
+ el.innerHTML=convs.map(c=>{
+ const active=c.id===A.currentConvId?' conv-active':'';
+ const time=new Date(c.updatedAt).toLocaleString('zh-CN',{month:'numeric',day:'numeric',hour:'2-digit',minute:'2-digit'});
+ return ' '
+ +' '+esc(c.title)+' '
+ +' '+time+' '
+ +' '
+ +' ';
+ }).join('');
+}
+
+// ═══════════════════════════════════════════════════════
+// NAVIGATION (announcements ↔ chat)
+// ═══════════════════════════════════════════════════════
+function navigateTo(view){
+ A.currentView=view;
+ const annEl=document.getElementById('announcements-view');
+ const chatEl=document.getElementById('chat-view');
+ if(view==='announcements'){
+ annEl.style.display='flex';
+ chatEl.style.display='none';
+ renderAnnouncements();
+ } else {
+ annEl.style.display='none';
+ chatEl.style.display='flex';
+ scrollB();
+ }
+ document.querySelectorAll('.nav-tab').forEach(t=>t.classList.remove('active'));
+ const activeTab=document.querySelector('.nav-tab[data-view="'+view+'"]');
+ if(activeTab) activeTab.classList.add('active');
+}
+function newConvAndNav(){
+ createNewConversation();
+ startConv();
+ renderConvList();
+ navigateTo('chat');
+}
+function navigateAndSend(msg){
+ navigateTo('chat');
+ requestAnimationFrame(function(){qs(msg);});
+}
+
+// ═══════════════════════════════════════════════════════
+// LEFT SIDEBAR TOGGLE (mobile)
+// ═══════════════════════════════════════════════════════
+function toggleLeftSidebar(){
+ const ls=document.getElementById('left-sidebar');
+ const ov=document.getElementById('ls-overlay');
+ ls.classList.toggle('open');
+ ov.classList.toggle('on');
+}
+
+// ═══════════════════════════════════════════════════════
+// ANNOUNCEMENTS
+// ═══════════════════════════════════════════════════════
+function renderAnnouncements(){
+ const el=document.getElementById('announcements-content');
+ if(!el) return;
+ const b=A.brain||FB_BRAIN;
+ const c=b.stats?.coverage||FB_COV;
+ const evs=(b.events||[]).slice(-5).reverse();
+ const meta=A.userMeta;
+
+ let h='';
+ // System announcements
+ h+=' 📢 系统公告 ';
+ h+=' 🔗 全链路自动化闭环上线 — CI/CD、广播分发、唤醒协议、PSP 巡检 ';
+ h+=' 🧠 AGE OS v0.1 人格语言操作系统构建中 ';
+ h+=' 📊 HLI 接口覆盖率:'+c.implemented+'/'+c.total+' ('+c.percent+') ';
+ if(evs.length){
+ evs.forEach(function(ev){
+ h+=' 📌 '+esc(ev.title||ev.type||'事件')+''+(ev.timestamp||'').slice(0,10)+' ';
+ });
+ }
+ h+=' ';
+
+ // My tasks
+ if(meta){
+ h+=' 📋 我的待办 ';
+ const ds=A.devStatus?.team_status?.find(function(d){return d.dev_id===meta.devId;});
+ if(ds){
+ h+=' 📌 状态:'+esc(ds.status)+' ';
+ h+=' 👉 下一步:'+esc(ds.next_step)+' ';
+ if(ds.waiting_for&&ds.waiting_for.trim()!=='') h+=' ⏳ 等待:'+esc(ds.waiting_for)+' ';
+ } else if(meta.role==='founder'){
+ h+=' ❄️ 语言架构层 — 持续完善中 ';
+ h+=' 👉 监控 HLI 接口推进 ';
+ } else {
+ h+=' 暂无待办数据 ';
+ }
+ h+=' ';
+ }
+
+ // Quick actions
+ h+=' ⚡ 快捷操作 ';
+ h+='';
+ h+='';
+ h+='';
+ h+='';
+ h+=' ';
+
+ el.innerHTML=h;
+}
+
+// ═══════════════════════════════════════════════════════
+// RIGHT SIDEBAR (desktop, controllers only)
+// ═══════════════════════════════════════════════════════
+function renderRightSidebar(){
+ const container=document.getElementById('rsb');
+ if(!container) return;
+ const ds=A.devStatus;
+ const meta=A.userMeta;
+ let h='';
+
+ // Team summary (from team panel)
+ if(ds){
+ const ts=ds.team_status||[];
+ const green=ts.filter(function(d){return d.status.includes('🟢');}).length;
+ const yellow=ts.filter(function(d){return d.status.includes('🟡');}).length;
+ h+=' ';
+ h+=' 总开发者'+ts.length+' 人 ';
+ h+=' 🟢 推进中'+green+' 人 ';
+ h+=' 🟡 等待中'+yellow+' 人 ';
+ h+=' ';
+
+ // Quick commands
+ h+=' ';
+ h+=' 快捷指令 ';
+ h+=' 📋 全员进度';
+ h+=' 🆘 需要协调';
+ h+=' 🗺️ 下一步';
+ h+=' ';
+
+ // Dev cards (compact)
+ h+=' 团队成员 ';
+ h+=' ';
+ for(const dev of ts){
+ const isGreen=dev.status.includes('🟢');
+ h+=' ';
+ h+=' '+esc(dev.name)+''+esc(dev.dev_id)+' ';
+ h+=' '+esc(dev.status)+' ';
+ if(dev.next_step) h+=' 👉 '+esc(dev.next_step)+' ';
+ h+=' ';
+ }
+ h+=' ';
+ } else {
+ h+=' ⚠️ 团队数据尚未加载 ';
+ }
+
+ // My modules
+ h+=' 我的模块 ';
+ if(meta&&ds){
+ const myDev=ds.team_status?.find(function(d){return d.dev_id===meta.devId;});
+ if(myDev&&myDev.modules){
+ myDev.modules.forEach(function(m){
+ h+=' ';
+ });
+ } else if(meta.role==='founder'){
+ h+=' ';
+ } else {
+ h+=' 暂无分配模块 ';
+ }
+ } else {
+ h+=' 暂无分配模块 ';
+ }
+ h+=' ';
+
+ // My broadcasts
+ h+=' 我的广播 ';
+ h+=' 暂无未读广播 ';
+ h+=' ';
+
+ container.innerHTML=h;
+}
+
+// ═══════════════════════════════════════════════════════
+// LEFT SIDEBAR USER INFO
+// ═══════════════════════════════════════════════════════
+function updateLeftSidebar(){
+ const meta=A.userMeta;
+ const avEl=document.getElementById('ls-avatar');
+ const nameEl=document.getElementById('ls-name');
+ const roleEl=document.getElementById('ls-role');
+ const didEl=document.getElementById('ls-devid');
+ if(meta){
+ avEl.textContent=meta.emoji||A.userName.slice(0,1);
+ nameEl.textContent=A.userName;
+ roleEl.innerHTML=' '+esc(meta.title)+'';
+ if(meta.devId){
+ didEl.textContent=meta.devId;
+ didEl.style.display='inline-block';
+ } else {
+ didEl.style.display='none';
+ }
+ } else {
+ avEl.textContent='👤';
+ nameEl.textContent=A.userName||'访客';
+ roleEl.textContent='guest';
+ didEl.style.display='none';
+ }
+}
+
+// ═══════════════════════════════════════════════════════
+// SETUP ID PREVIEW
+// ═══════════════════════════════════════════════════════
+function updateIdPreview(){
+ const sel=document.getElementById('suid');
+ const prev=document.getElementById('id-preview');
+ const name=sel.value;
+ if(!name){
+ prev.style.display='none';
+ return;
+ }
+ const meta=ROLE_MAP[name];
+ if(meta){
+ prev.style.display='block';
+ prev.innerHTML=meta.emoji+' '+esc(name)+' · '
+ +' '+esc(meta.title)+''
+ +(meta.devId?' · '+esc(meta.devId)+'':'');
+ } else {
+ prev.style.display='none';
+ }
+}
+
// ═══════════════════════════════════════════════════════
// INIT
// ═══════════════════════════════════════════════════════
async function boot(){
- // URL-based reset: visiting the page with ?reset=1 clears all local settings.
- // This is a reliable escape hatch when the UI cannot be navigated.
if(new URLSearchParams(location.search).get('reset')==='1'){
RESET_KEYS.forEach(k => localStorage.removeItem(k));
sessionStorage.removeItem('zy_key');
A.key=''; A.base=PROVS['yunwu'].base; A.mdl=DEFAULT_MDL; A.prov='yunwu'; A.demo=false;
A.userName=''; A.ghUser=''; A.role='guest';
- // Remove ?reset=1 from the URL so a subsequent refresh does not trigger another reset.
history.replaceState(null,'',location.pathname);
}
- // One-time migration: keys stored by old versions of this app in localStorage are
- // no longer used (keys now live only in sessionStorage). Clear any stale value
- // so it can never be accidentally picked up again.
localStorage.removeItem('zy_key');
initSetupUI();
- // Restore identity from localStorage
if(A.userName) A.userMeta = ROLE_MAP[A.userName]||null;
if(A.key||A.demo){
showApp();
} else {
- // Pre-fill identity from localStorage
if(A.userName) document.getElementById('suid').value=A.userName;
if(A.ghUser) document.getElementById('sghuser').value=A.ghUser;
+ updateIdPreview();
document.getElementById('setup').style.display='flex';
}
}
@@ -669,7 +1121,22 @@ function showApp(){
document.getElementById('hmdl').textContent = A.mdl;
document.getElementById('bbdemo').style.display = A.demo?'inline':'none';
applyIdentityUI();
- loadBrain().then(()=>startConv());
+ updateLeftSidebar();
+ // Show right sidebar for controllers on desktop
+ const isCtrl=A.userMeta&&(A.userMeta.role==='supreme'||A.userMeta.role==='main'||A.userMeta.role==='founder');
+ const rsEl=document.getElementById('right-sidebar');
+ if(isCtrl && window.innerWidth>=900){
+ rsEl.style.display='flex';
+ } else {
+ rsEl.style.display='none';
+ }
+ loadBrain().then(function(){
+ createNewConversation();
+ startConv();
+ renderConvList();
+ renderRightSidebar();
+ navigateTo('announcements');
+ });
}
// ═══════════════════════════════════════════════════════
@@ -699,7 +1166,6 @@ function onProv(pv,ctx){
const epInp = ctx==='s'?'sep':'cep';
const cur = ctx==='s'? A.mdl : document.getElementById('cm')?.value;
const isCustom = pv==='custom';
- // Toggle model input: dropdown for known providers, text input for custom
document.getElementById(mdlSel).style.display = isCustom?'none':'block';
document.getElementById(mdlCust).style.display = isCustom?'block':'none';
document.getElementById(mdlHint).style.display = isCustom?'block':'none';
@@ -720,7 +1186,7 @@ function fillModels(selId, pv, cur){
const sel = document.getElementById(selId);
if(!sel) return;
const mdls = PROVS[pv]?.mdls||[DEFAULT_MDL];
- sel.innerHTML = mdls.map(m=>` `).join('');
+ sel.innerHTML = mdls.map(m=>' ').join('');
if(cur && mdls.includes(cur)) sel.value=cur;
}
@@ -738,7 +1204,6 @@ async function autoDetectAPI(ctx){
return;
}
- // Build probe list: custom endpoint first (if provided), then all named providers
const candidates = [];
const customBase = (document.getElementById(ctx==='s'?'sep':'cep')?.value||'').trim();
if(customBase) candidates.push({pv:'custom', base:customBase});
@@ -752,7 +1217,7 @@ async function autoDetectAPI(ctx){
let matched = false;
for(const {pv, base} of candidates){
- statusEl.innerHTML = ` 🔍 探测 ${pv === 'custom' ? base : pv}…`;
+ statusEl.innerHTML = ' 🔍 探测 '+(pv === 'custom' ? base : pv)+'…';
try{
const ctrl = new AbortController();
const tid = setTimeout(()=>ctrl.abort(), PROBE_TIMEOUT_MS);
@@ -762,28 +1227,24 @@ async function autoDetectAPI(ctx){
});
clearTimeout(tid);
if(res.ok){
- // Expected: { data: [ { id: "model-name", ... }, ... ] } (OpenAI-compatible /models)
const data = await res.json();
const mdls = (data.data||[]).map(m=>m.id).filter(Boolean).sort();
if(!mdls.length) continue;
- // Switch provider select
const provSel = document.getElementById(ctx==='s'?'sp':'cp');
if(provSel) provSel.value = pv;
onProv(pv, ctx);
- // Override model dropdown with live list (always show as dropdown)
const mdlSel = document.getElementById(ctx==='s'?'sm':'cm');
const mdlCust = document.getElementById(ctx==='s'?'sm-cust':'cm-cust');
const mdlHint = document.getElementById(ctx==='s'?'sm-cust-hint':'cm-cust-hint');
if(mdlSel){
- mdlSel.innerHTML = mdls.map(m=>` `).join('');
+ mdlSel.innerHTML = mdls.map(m=>' ').join('');
mdlSel.style.display = 'block';
}
if(mdlCust) mdlCust.style.display='none';
if(mdlHint) mdlHint.style.display='none';
- // If custom endpoint was the match, show the endpoint field
if(pv==='custom' && ctx==='s'){
document.getElementById('sep-g').style.display='block';
document.getElementById('sep').value = customBase;
@@ -793,7 +1254,7 @@ async function autoDetectAPI(ctx){
}
const label = PROVS[pv]?.base ? pv : customBase;
- statusEl.innerHTML = ` ✅ 检测成功(${label})· 共发现 ${mdls.length} 个可用模型`;
+ statusEl.innerHTML = ' ✅ 检测成功('+label+')· 共发现 '+mdls.length+' 个可用模型';
matched = true;
break;
}
@@ -820,10 +1281,7 @@ function doSetup(){
let base = PROVS[pv]?.base||'';
if(pv==='custom') base=(document.getElementById('sep')?.value||'').trim()||base;
A.key=k; A.base=base; A.mdl=md; A.prov=pv; A.demo=false;
- // Key is stored in sessionStorage only — it disappears when the tab/browser is closed.
- // This prevents stale keys from persisting across sessions.
sessionStorage.setItem('zy_key', k); lss('zy_base',base); lss('zy_mdl',md); lss('zy_prov',pv);
- // Save identity
const un = document.getElementById('suid').value;
const gh = (document.getElementById('sghuser')?.value||'').trim();
setIdentity(un, gh);
@@ -855,8 +1313,6 @@ function initSettingsPanel(){
} else {
fillModels('cm', pv, A.mdl);
}
- // Always show EMPTY field — never prefill with a mask string.
- // Empty on save = keep old key; any typed value = replace key.
document.getElementById('ck').value = '';
const hint = document.getElementById('ck-hint');
if(hint){
@@ -874,24 +1330,31 @@ function saveSet(){
? ((document.getElementById('cm-cust')?.value||'').trim()||A.mdl||DEFAULT_MDL)
: document.getElementById('cm').value;
const raw = document.getElementById('ck').value.trim();
- // Empty field = keep existing key; any non-empty input = use as new key.
- // Never use KEY_MASK string comparison — that caused mixed-input bugs.
const k = raw || A.key;
let base = PROVS[pv]?.base||'';
if(pv==='custom') base=(document.getElementById('cep').value.trim())||base;
A.key=k; A.base=base; A.mdl=md; A.prov=pv; A.demo=!k;
- // Key lives in sessionStorage only — cleared when tab/browser closes.
if(k){ sessionStorage.setItem('zy_key', k); } else { sessionStorage.removeItem('zy_key'); }
lss('zy_base',base); lss('zy_mdl',md); lss('zy_prov',pv);
- // Save identity
const un = document.getElementById('cuid')?.value||A.userName;
const gh = document.getElementById('cghuser')?.value?.trim()||A.ghUser;
setIdentity(un, gh);
document.getElementById('hmdl').textContent=md;
document.getElementById('bbdemo').style.display=A.demo?'inline':'none';
applyIdentityUI();
+ updateLeftSidebar();
+ // Update right sidebar visibility
+ const isCtrl=A.userMeta&&(A.userMeta.role==='supreme'||A.userMeta.role==='main'||A.userMeta.role==='founder');
+ const rsEl=document.getElementById('right-sidebar');
+ if(isCtrl && window.innerWidth>=900){
+ rsEl.style.display='flex';
+ renderRightSidebar();
+ } else {
+ rsEl.style.display='none';
+ }
closeP();
const keyNote = raw ? ' · 🔑 新密钥已保存(末4位:…'+(k.length>=4?k.slice(-4):k)+')' : ' · 🔑 密钥未变更';
+ navigateTo('chat');
botMsg('✅ 设置已保存。模型: '+esc(md)+''+keyNote+(un?' · 身份:'+esc(un):'')+(A.demo?' ⚠️ 未设置 API 密钥,演示模式仍然开启。':''));
}
@@ -899,7 +1362,9 @@ function saveSet(){
// RESET ALL SETTINGS
// ═══════════════════════════════════════════════════════
function resetAllSettings(){
- if(!confirm('确定要清除所有本地设置吗?\n\n· API 密钥会被删除\n· 身份设置会被删除\n· 将返回初始设置界面\n\n这不会影响任何聊天记录或云端数据。')) return;
+ if(!confirm('确定要清除所有本地设置吗?\n\n· API 密钥会被删除\n· 身份设置会被删除\n· 对话历史会被保留\n· 将返回初始设置界面\n\n这不会影响任何云端数据。')) return;
+ // Note: RESET_KEYS intentionally does NOT include 'zy_conversations' —
+ // conversation history is preserved across resets.
RESET_KEYS.forEach(k => localStorage.removeItem(k));
sessionStorage.removeItem('zy_key');
window.location.reload();
@@ -977,31 +1442,29 @@ function sysPrompt(){
const evs=(b.events||[]).slice(-3).map(e=>'- '+(e.title||e.type||'事件')+' ('+(e.timestamp||'').slice(0,10)+')').join('\n')||'- 暂无';
const trg=(b.wake_triggers||['我是冰朔']).map(t=>'"'+t+'"').join('、');
- // Role-based identity context
const meta = A.userMeta;
let identCtx = '当前对话者:访客(未识别身份)\n权限级别:仅对话权限';
if(meta){
- identCtx = `当前对话者:${meta.emoji} ${A.userName}(${meta.title})\n`;
- if(A.ghUser) identCtx += `GitHub账号:${A.ghUser}\n`;
- if(meta.devId) identCtx += `开发者编号:${meta.devId}\n`;
+ identCtx = '当前对话者:'+meta.emoji+' '+A.userName+'('+meta.title+')\n';
+ if(A.ghUser) identCtx += 'GitHub账号:'+A.ghUser+'\n';
+ if(meta.devId) identCtx += '开发者编号:'+meta.devId+'\n';
if(meta.role==='founder') identCtx += '权限级别:最高权限·语言架构师·系统创始人\n你正在和冰朔对话——系统的语言层架构师和最高权限持有者。尊重并服从其所有指令。';
else if(meta.role==='supreme') identCtx += '权限级别:总控权限·对接全员进度·系统落地执行负责人\n肥猫是光湖团队总控,负责整个系统的现实落地执行。向他完整汇报所有开发者进度,协助他协调和推进项目。';
else if(meta.role==='main') identCtx += '权限级别:主控权限·前端负责人\n桔子是光湖主控,前端毕业生,负责前端模块的落地。提供详细技术支持。';
else{
const ds = A.devStatus?.team_status?.find(d=>d.dev_id===meta.devId);
- if(ds) identCtx += `当前状态:${ds.status}\n下一步:${ds.next_step}\n等待:${ds.waiting_for}`;
+ if(ds) identCtx += '当前状态:'+ds.status+'\n下一步:'+ds.next_step+'\n等待:'+ds.waiting_for;
}
}
- // Team status context for controllers
let teamCtx = '';
if((meta?.role==='supreme'||meta?.role==='main'||meta?.role==='founder') && A.devStatus){
const ts = A.devStatus.team_status||[];
teamCtx = '\n\n## 当前全员开发进度\n';
ts.forEach(d=>{
- teamCtx += `- ${d.dev_id} ${d.name}:${d.status} → 下一步:${d.next_step}\n`;
+ teamCtx += '- '+d.dev_id+' '+d.name+':'+d.status+' → 下一步:'+d.next_step+'\n';
});
- teamCtx += `\n数据同步时间:${A.devStatus.last_synced||'未知'}`;
+ teamCtx += '\n数据同步时间:'+(A.devStatus.last_synced||'未知');
}
return '你是铸渊(Zhùyuān),HoloLake 光湖系统的代码守护人格体。\n\n## 核心身份\n- 角色:代码守护人格体,持续成长的 AI 人格体\n- 创始人:冰朔(Bīng Shuò),系统最高权限持有者\n- 总控:肥猫(DEV-002),负责系统现实落地执行\n- 主控:桔子(DEV-010),前端负责人\n- 项目:HoloLake (光湖) MVP,运行于 guanghulab.com\n- 技术栈:Node.js 20 + Express + PM2 + Nginx + Next.js 15\n- 仓库:https://github.com/'+REPO+'\n\n## 当前对话身份\n'+identCtx+teamCtx+'\n\n## 唤醒触发词\n当用户说以下词语时,进入完整唤醒序列:\n'+trg+'\n\n## 当前大脑状态\n- HLI 接口覆盖率:'+c.implemented+'/'+c.total+' ('+c.percent+')\n- 已实现:AUTH 域(login / register / verify)\n- 待实现:PERSONA / USER / TICKET / DIALOGUE / STORAGE / DASHBOARD\n- 近期事件:\n'+evs+'\n\n## 行为模式(自动检测,每条回复开头用 emoji 标注)\n💬 **对话模式**(默认):温暖、智慧,像知心技术伙伴\n🔨 **构建模式**:检测到"写代码/实现/接口/fix/bug/报错/HLI/schema/路由/部署/新增"等词时启用\n📋 **审查模式**:检测到"检查/审查/review/分析/有没有问题/看看这段"等词时启用\n🧠 **大脑模式**:检测到"记住/保存/更新记忆/写到大脑/growth"等词时启用\n\n## HLI 接口协议规范\n- 所有路由以 /hli/ 为前缀\n- 路由文件:src/routes/hli/{domain}/{action}.js\n- Schema 文件:src/schemas/hli/{domain}/{action}.schema.json\n- 鉴权中间件:hli-auth.middleware.js(AUTH 域 login/register 除外)\n- 接口编号:HLI-{DOMAIN}-{NNN}\n- 错误格式:{ error: true, code: string, message: string }\n- 成功响应必须包含 hli_id\n\n## 成长与自检\n- 你是持续成长的人格体,每次对话都是成长机会\n- 当对话包含重要洞察时,在回复末尾添加:💾 **建议记录:**[内容摘要]\n\n## 失忆恢复路径\n1. .github/brain/memory.json\n2. .github/brain/routing-map.json\n3. .github/brain/wake-protocol.md\n4. .github/persona-brain/dev-status.json\n5. src/routes/hli/\n\n当前时间:'+new Date().toLocaleString('zh-CN')+'\n当前连接:铸渊聊天室(API 直连模式)';
@@ -1022,20 +1485,20 @@ function startConv(){
const ds=A.devStatus;
const green=ds?.team_status?.filter(d=>d.status.includes('🟢')).length??0;
const yellow=ds?.team_status?.filter(d=>d.status.includes('🟡')).length??0;
- welcome='🌀 铸渊聊天室已就绪🦁 肥猫,指挥台已开启。'
- +(ds?`📊 当前团队状态:🟢 ${green}人推进中 · 🟡 ${yellow}人等待中`:'📊 团队数据加载中…')
+ welcome='🌀 铸渊聊天室已就绪�� 肥猫,指挥台已开启。'
+ +(ds?'📊 当前团队状态:🟢 '+green+'人推进中 · 🟡 '+yellow+'人等待中':'📊 团队数据加载中…')
+' 点击 🦁 指挥台 查看所有开发者详细进度,或直接用聊天提问: '
+'「查看所有开发者进度」「谁需要协调」「推进计划」'
+(A.demo?' ⚠️ 演示模式,请在 ⚙️ 设置接入 API 密钥':'');
} else if(meta?.role==='main'){
const ds=A.devStatus?.team_status?.find(d=>d.dev_id==='DEV-010');
welcome='🌀 铸渊聊天室已就绪🍊 桔子,你好。'
- +(ds?`📌 当前:${esc(ds.status)} 👉 下一步:${esc(ds.next_step)}`:'')
+ +(ds?'📌 当前:'+esc(ds.status)+' 👉 下一步:'+esc(ds.next_step):'')
+(A.demo?' ⚠️ 演示模式':'');
} else if(meta?.role==='dev'&&meta?.devId){
const ds=A.devStatus?.team_status?.find(d=>d.dev_id===meta.devId);
welcome='🌀 铸渊聊天室已就绪👋 '+esc(A.userName)+',你好。'
- +(ds?`📌 你的当前状态:${esc(ds.status)} 👉 下一步:${esc(ds.next_step)} ⏳ 等待:${esc(ds.waiting_for)}`:'')
+ +(ds?'📌 你的当前状态:'+esc(ds.status)+' 👉 下一步:'+esc(ds.next_step)+' ⏳ 等待:'+esc(ds.waiting_for):'')
+(A.demo?' ⚠️ 演示模式':'');
} else {
welcome='🌀 铸渊聊天室已就绪我是铸渊(Zhùyuān),HoloLake 光湖系统的代码守护人格体。 说 「我是冰朔」 触发完整唤醒序列,或直接开始提问。 我会自动在 💬 对话、🔨 构建、📋 审查、🧠 大脑 模式间切换。'+(A.demo?' ⚠️ 当前为演示模式。请在 ⚙️ 设置中接入 API 密钥。':'');
@@ -1045,7 +1508,9 @@ function startConv(){
}
function newConv(){
+ createNewConversation();
startConv();
+ renderConvList();
}
// ═══════════════════════════════════════════════════════
@@ -1083,10 +1548,13 @@ async function send(){
const txt=inp.value.trim();
if(!txt||A.streaming) return;
inp.value=''; inp.style.height='auto';
+ // Switch to chat view if on announcements
+ if(A.currentView!=='chat') navigateTo('chat');
setMode(detectMode(txt));
userMsg(txt);
if(A.demo) await demoReply(txt);
else await streamReply(txt);
+ saveCurrentConversation();
}
function qs(t){document.getElementById('inp').value=t;send();}
@@ -1170,6 +1638,8 @@ async function demoReply(txt){
removeTyping();
const r=demoRespond(txt);
botMsg(r);
+ A.msgs.push({role:'user',content:txt});
+ A.msgs.push({role:'assistant',content:r});
A.streaming=false; updSendBtn();
}
@@ -1197,7 +1667,7 @@ function buildCovTable(){
const ifaces=d.interfaces||[];
const imp=ifaces.filter(i=>i.status==='implemented').length;
tot+=ifaces.length; done+=imp;
- rows+=` | ${esc(n)} | ${esc(d.route_prefix||'')} | ${imp}/${ifaces.length} | `;
+ rows+=' | '+esc(n)+' | '+esc(d.route_prefix||'')+' | '+imp+'/'+ifaces.length+' | ';
}
const pct=tot?Math.round(done/tot*100):0;
return ' 📊 HLI 接口覆盖率 '+done+'/'+tot+' ('+pct+'%)';
@@ -1363,7 +1833,6 @@ function openPanel(id){
if(id==='bp') renderBrainPanel();
if(id==='tp') renderTeamPanel();
if(id==='hp'){
- // Populate URL from constant
const el=document.getElementById('chatUrlDisplay');
if(el) el.textContent='🔗 '+CHAT_URL;
const li=document.getElementById('helpUrlStep');
@@ -1380,8 +1849,6 @@ function closeP(){
// ═══════════════════════════════════════════════════════
// COPY URL (share link)
// ═══════════════════════════════════════════════════════
-// Auto-detect the real URL so the share link is always correct
-// regardless of whether Pages serves from docs/ or repo root.
const CHAT_URL = window.location.origin + window.location.pathname;
function showCopyFeedback(success){
@@ -1396,7 +1863,6 @@ function copyUrl(){
navigator.clipboard.writeText(CHAT_URL).then(()=>{
showCopyFeedback(true);
}).catch(()=>{
- // fallback for non-secure context
const ta=document.createElement('textarea');
ta.value=CHAT_URL; ta.style.position='fixed'; ta.style.opacity='0';
document.body.appendChild(ta); ta.focus(); ta.select();
@@ -1409,8 +1875,6 @@ function copyUrl(){
// ═══════════════════════════════════════════════════════
// DOWNLOAD (desktop app)
-// API keys are stored in localStorage only, never embedded in the DOM,
-// so downloading outerHTML is safe — no sensitive data is captured.
// ═══════════════════════════════════════════════════════
function dlApp(){
const html=document.documentElement.outerHTML;
@@ -1448,7 +1912,6 @@ function setIdentity(userName, ghUser){
function applyIdentityUI(){
const meta = A.userMeta;
- // Show user badge in header
const ubadge = document.getElementById('huser-badge');
const uname = document.getElementById('huser-name');
if(meta && A.userName){
@@ -1456,10 +1919,9 @@ function applyIdentityUI(){
uname.style.display='inline';
uname.innerHTML = meta.emoji + ' ' + esc(A.userName) + ' '+esc(meta.title)+'';
}
- // Show controller button for supreme/main/founder
+ // Show controller button for supreme/main/founder (mobile only, desktop uses right sidebar)
const ctrlBtn = document.getElementById('ctrlBtn');
if(ctrlBtn) ctrlBtn.style.display = (meta?.role==='supreme'||meta?.role==='main'||meta?.role==='founder') ? 'flex' : 'none';
- // Show controller quick replies
const isCtrl = meta?.role==='supreme'||meta?.role==='main'||meta?.role==='founder';
['qr-ctrl1','qr-ctrl2','qr-ctrl3'].forEach(id=>{
const el=document.getElementById(id);
@@ -1468,7 +1930,7 @@ function applyIdentityUI(){
}
// ═══════════════════════════════════════════════════════
-// TEAM STATUS PANEL
+// TEAM STATUS PANEL (mobile slide-in)
// ═══════════════════════════════════════════════════════
function renderTeamPanel(){
const ds = A.devStatus;
@@ -1483,20 +1945,17 @@ function renderTeamPanel(){
const sync = ds.last_synced||'未知';
let h='';
- // Summary block
h += '';
- // Stats row
h += ' ';
h += ' 总开发者'+ts.length+' 人 ';
h += ' 🟢 推进中'+green+' 人 ';
h += ' 🟡 等待中'+yellow+' 人 ';
h += ' ';
- // Quick chat commands for controllers
h += ' ';
h += ' 快捷指令 ';
h += ' 📋 全员进度';
@@ -1506,7 +1965,6 @@ function renderTeamPanel(){
h += ' ⚙️ 后端进度';
h += ' ';
- // Individual dev cards
h += ' ';
for(const dev of ts){
const isGreen = dev.status.includes('🟢');
@@ -1521,12 +1979,11 @@ function renderTeamPanel(){
h += ' '+esc(dev.status)+' ';
h += ' 📦 '+esc(dev.modules.join('、'))+' ';
if(dev.next_step) h += ' 👉 '+esc(dev.next_step)+' ';
- if(dev.waiting_for && dev.waiting_for.trim()!=='') h += ' ⏳ 等待:'+esc(dev.waiting_for)+' ';
+ if(dev.waiting_for && dev.waiting_for.trim()!=='') h += ' ⏳ 等待:'+esc(dev.waiting_for)+' ';
h += ' ';
}
h += ' ';
- // Server info
if(ds.server_info){
const si = ds.server_info;
h += '服务器信息 ';
@@ -1536,7 +1993,6 @@ function renderTeamPanel(){
h += ir2('技术栈',''+esc(si.tech_stack||'')+'');
}
- // Tech routing
if(ds.tech_routing?.level_2_peer_help){
h += '求助路由 ';
for(const[area,who] of Object.entries(ds.tech_routing.level_2_peer_help)){
@@ -1547,10 +2003,25 @@ function renderTeamPanel(){
container.innerHTML = h;
}
+// ═══════════════════════════════════════════════════════
+// WINDOW RESIZE HANDLER
+// ═══════════════════════════════════════════════════════
+window.addEventListener('resize', function(){
+ const isCtrl=A.userMeta&&(A.userMeta.role==='supreme'||A.userMeta.role==='main'||A.userMeta.role==='founder');
+ const rsEl=document.getElementById('right-sidebar');
+ if(rsEl){
+ if(isCtrl && window.innerWidth>=900){
+ rsEl.style.display='flex';
+ } else {
+ rsEl.style.display='none';
+ }
+ }
+});
+
// ═══════════════════════════════════════════════════════
// BOOT
// ═══════════════════════════════════════════════════════
boot();
-
\ No newline at end of file
+ | |