diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000..69b31b3
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,3 @@
+# https://play.aidungeon.com/scenario/[AID_SHORTID]
+AID_SHORTID=""
+AID_TOKEN=""
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 65b6d04..05baca0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,3 +26,5 @@ lerna-debug.log*
.env.test.local
.env.production.local
.env.local
+.env.token
+.env.keys
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
index f55bfff..97e616b 100644
--- a/.vscode/extensions.json
+++ b/.vscode/extensions.json
@@ -4,6 +4,7 @@
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"usernamehw.errorlens",
- "xyz.local-history"
+ "xyz.local-history",
+ "remcohaszing.schemastore"
]
}
diff --git a/context.js b/dist/context.js
similarity index 100%
rename from context.js
rename to dist/context.js
diff --git a/input.js b/dist/input.js
similarity index 100%
rename from input.js
rename to dist/input.js
diff --git a/library.js b/dist/library.js
similarity index 74%
rename from library.js
rename to dist/library.js
index 1933fd6..fb42900 100644
--- a/library.js
+++ b/dist/library.js
@@ -1,3 +1,4 @@
+///
// Your "Library" tab should look like this
// [source code not public yet]
diff --git a/dist/library.min.js b/dist/library.min.js
new file mode 100644
index 0000000..e69de29
diff --git a/output.js b/dist/output.js
similarity index 100%
rename from output.js
rename to dist/output.js
diff --git a/eslint.config.js b/eslint.config.js
index ebb33cd..78abe17 100644
--- a/eslint.config.js
+++ b/eslint.config.js
@@ -9,6 +9,8 @@ export default tseslint.config([
tseslint.configs.recommended,
eslintConfigPrettier,
{
+ files: ["**/*.js"],
+ ignores: ["utils/**"],
rules: {
"no-undef": "off",
"no-var": "error",
@@ -18,18 +20,23 @@ export default tseslint.config([
"prefer-regex-literals": ["error", { disallowRedundantWrapping: true }],
quotes: ["error", "double", { avoidEscape: true, allowTemplateLiterals: false }],
"space-before-blocks": ["error", "always"]
- }
- },
- {
- files: ["context.js", "input.js", "library.js", "output.js"],
+ },
languageOptions: {
ecmaVersion: "latest",
sourceType: "script",
- globals: globals.es2024
+ globals: globals.es2022
}
},
{
- files: ["tools/*.js", "utils/**/*.js"],
+ files: ["utils/**/*.js"],
+ rules: {
+ "no-var": "error",
+ "prefer-const": ["error", { destructuring: "all" }],
+ "prefer-promise-reject-errors": "error",
+ "prefer-regex-literals": ["error", { disallowRedundantWrapping: true }],
+ quotes: ["error", "double", { avoidEscape: true, allowTemplateLiterals: false }],
+ "space-before-blocks": ["error", "always"]
+ },
languageOptions: {
ecmaVersion: "latest",
sourceType: "module",
diff --git a/package.json b/package.json
index d8c5092..e760234 100644
--- a/package.json
+++ b/package.json
@@ -10,15 +10,17 @@
},
"type": "module",
"scripts": {
- "minify": "terser ./src/library.js -c -o library.min.js"
+ "run:Dev": "dotenvx run --env AID_ENV=development -f .env --quiet -- node ./utils/ai.dungeon/index.js",
+ "run:Prod": "dotenvx run --env AID_ENV=production -f .env --quiet -- node ./utils/ai.dungeon/index.js"
},
"devDependencies": {
+ "@dotenvx/dotenvx": "^1.44.1",
"@eslint/js": "^9.27.0",
+ "ai.dungeon": "workspace:^",
"eslint": "^9.27.0",
"eslint-config-prettier": "^10.1.5",
"globals": "^16.1.0",
"prettier": "^3.5.3",
- "terser": "^5.39.2",
"typescript": "^5.8.3",
"typescript-eslint": "^8.32.1"
},
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 79d9e31..211f0f0 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -8,9 +8,15 @@ importers:
.:
devDependencies:
+ '@dotenvx/dotenvx':
+ specifier: ^1.44.1
+ version: 1.44.1
'@eslint/js':
specifier: ^9.27.0
version: 9.27.0
+ ai.dungeon:
+ specifier: workspace:^
+ version: link:utils/ai.dungeon
eslint:
specifier: ^9.27.0
version: 9.27.0
@@ -23,9 +29,6 @@ importers:
prettier:
specifier: ^3.5.3
version: 3.5.3
- terser:
- specifier: ^5.39.2
- version: 5.39.2
typescript:
specifier: ^5.8.3
version: 5.8.3
@@ -33,8 +36,37 @@ importers:
specifier: ^8.32.1
version: 8.32.1(eslint@9.27.0)(typescript@5.8.3)
+ utils/ai.dungeon:
+ dependencies:
+ axios:
+ specifier: ^1.9.0
+ version: 1.9.0
+ terser:
+ specifier: ^5.39.2
+ version: 5.39.2
+ watchpack:
+ specifier: ^2.4.2
+ version: 2.4.4
+ devDependencies:
+ '@types/node':
+ specifier: ^22.15.21
+ version: 22.15.21
+ '@types/watchpack':
+ specifier: ^2.4.4
+ version: 2.4.4
+
packages:
+ '@dotenvx/dotenvx@1.44.1':
+ resolution: {integrity: sha512-j1QImCqf/XJmhIjC1OPpgiZV9g370HG9MNT9s/CDwCKsoYzNCPEKK+GfsidahJx7yIlBbm+4dPLlGec+bKn7oA==}
+ hasBin: true
+
+ '@ecies/ciphers@0.2.3':
+ resolution: {integrity: sha512-tapn6XhOueMwht3E2UzY0ZZjYokdaw9XtL9kEyjhQ/Fb9vL9xTFbOaI+fV0AWvTpYu4BNloC6getKW6NtSg4mA==}
+ engines: {bun: '>=1', deno: '>=2', node: '>=16'}
+ peerDependencies:
+ '@noble/ciphers': ^1.0.0
+
'@eslint-community/eslint-utils@4.7.0':
resolution: {integrity: sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -114,6 +146,18 @@ packages:
'@jridgewell/trace-mapping@0.3.25':
resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
+ '@noble/ciphers@1.3.0':
+ resolution: {integrity: sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==}
+ engines: {node: ^14.21.3 || >=16}
+
+ '@noble/curves@1.9.1':
+ resolution: {integrity: sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==}
+ engines: {node: ^14.21.3 || >=16}
+
+ '@noble/hashes@1.8.0':
+ resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==}
+ engines: {node: ^14.21.3 || >=16}
+
'@nodelib/fs.scandir@2.1.5':
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
engines: {node: '>= 8'}
@@ -129,9 +173,18 @@ packages:
'@types/estree@1.0.7':
resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==}
+ '@types/graceful-fs@4.1.9':
+ resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==}
+
'@types/json-schema@7.0.15':
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
+ '@types/node@22.15.21':
+ resolution: {integrity: sha512-EV/37Td6c+MgKAbkcLG6vqZ2zEYHD7bvSrzqqs2RIhbA6w3x+Dqz8MZM3sP6kGTeLrdoOgKZe+Xja7tUB2DNkQ==}
+
+ '@types/watchpack@2.4.4':
+ resolution: {integrity: sha512-SbuSavsPxfOPZwVHBgQUVuzYBe6+8KL7dwiJLXaj5rmv3DxktOMwX5WP1J6UontwUbewjVoc7pCgZvqy6rPn+A==}
+
'@typescript-eslint/eslint-plugin@8.32.1':
resolution: {integrity: sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -199,6 +252,12 @@ packages:
argparse@2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
+ asynckit@0.4.0:
+ resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
+
+ axios@1.9.0:
+ resolution: {integrity: sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==}
+
balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
@@ -215,6 +274,10 @@ packages:
buffer-from@1.1.2:
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
+ call-bind-apply-helpers@1.0.2:
+ resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
+ engines: {node: '>= 0.4'}
+
callsites@3.1.0:
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
engines: {node: '>=6'}
@@ -230,6 +293,14 @@ packages:
color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+ combined-stream@1.0.8:
+ resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
+ engines: {node: '>= 0.8'}
+
+ commander@11.1.0:
+ resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==}
+ engines: {node: '>=16'}
+
commander@2.20.3:
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
@@ -252,6 +323,38 @@ packages:
deep-is@0.1.4:
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
+ delayed-stream@1.0.0:
+ resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
+ engines: {node: '>=0.4.0'}
+
+ dotenv@16.5.0:
+ resolution: {integrity: sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==}
+ engines: {node: '>=12'}
+
+ dunder-proto@1.0.1:
+ resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
+ engines: {node: '>= 0.4'}
+
+ eciesjs@0.4.15:
+ resolution: {integrity: sha512-r6kEJXDKecVOCj2nLMuXK/FCPeurW33+3JRpfXVbjLja3XUYFfD9I/JBreH6sUyzcm3G/YQboBjMla6poKeSdA==}
+ engines: {bun: '>=1', deno: '>=2', node: '>=16'}
+
+ es-define-property@1.0.1:
+ resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
+ engines: {node: '>= 0.4'}
+
+ es-errors@1.3.0:
+ resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
+ engines: {node: '>= 0.4'}
+
+ es-object-atoms@1.1.1:
+ resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
+ engines: {node: '>= 0.4'}
+
+ es-set-tostringtag@2.1.0:
+ resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
+ engines: {node: '>= 0.4'}
+
escape-string-regexp@4.0.0:
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
engines: {node: '>=10'}
@@ -304,6 +407,10 @@ packages:
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
engines: {node: '>=0.10.0'}
+ execa@5.1.1:
+ resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
+ engines: {node: '>=10'}
+
fast-deep-equal@3.1.3:
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
@@ -320,6 +427,14 @@ packages:
fastq@1.19.1:
resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==}
+ fdir@6.4.4:
+ resolution: {integrity: sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==}
+ peerDependencies:
+ picomatch: ^3 || ^4
+ peerDependenciesMeta:
+ picomatch:
+ optional: true
+
file-entry-cache@8.0.0:
resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
engines: {node: '>=16.0.0'}
@@ -339,6 +454,34 @@ packages:
flatted@3.3.3:
resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==}
+ follow-redirects@1.15.9:
+ resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==}
+ engines: {node: '>=4.0'}
+ peerDependencies:
+ debug: '*'
+ peerDependenciesMeta:
+ debug:
+ optional: true
+
+ form-data@4.0.2:
+ resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==}
+ engines: {node: '>= 6'}
+
+ function-bind@1.1.2:
+ resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
+
+ get-intrinsic@1.3.0:
+ resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
+ engines: {node: '>= 0.4'}
+
+ get-proto@1.0.1:
+ resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
+ engines: {node: '>= 0.4'}
+
+ get-stream@6.0.1:
+ resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
+ engines: {node: '>=10'}
+
glob-parent@5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'}
@@ -347,6 +490,9 @@ packages:
resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
engines: {node: '>=10.13.0'}
+ glob-to-regexp@0.4.1:
+ resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==}
+
globals@14.0.0:
resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
engines: {node: '>=18'}
@@ -355,6 +501,13 @@ packages:
resolution: {integrity: sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g==}
engines: {node: '>=18'}
+ gopd@1.2.0:
+ resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
+ engines: {node: '>= 0.4'}
+
+ graceful-fs@4.2.11:
+ resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+
graphemer@1.4.0:
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
@@ -362,6 +515,22 @@ packages:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'}
+ has-symbols@1.1.0:
+ resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
+ engines: {node: '>= 0.4'}
+
+ has-tostringtag@1.0.2:
+ resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==}
+ engines: {node: '>= 0.4'}
+
+ hasown@2.0.2:
+ resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
+ engines: {node: '>= 0.4'}
+
+ human-signals@2.1.0:
+ resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
+ engines: {node: '>=10.17.0'}
+
ignore@5.3.2:
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
engines: {node: '>= 4'}
@@ -390,9 +559,17 @@ packages:
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
engines: {node: '>=0.12.0'}
+ is-stream@2.0.1:
+ resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
+ engines: {node: '>=8'}
+
isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+ isexe@3.1.1:
+ resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==}
+ engines: {node: '>=16'}
+
js-yaml@4.1.0:
resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
hasBin: true
@@ -420,6 +597,13 @@ packages:
lodash.merge@4.6.2:
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
+ math-intrinsics@1.1.0:
+ resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
+ engines: {node: '>= 0.4'}
+
+ merge-stream@2.0.0:
+ resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
+
merge2@1.4.1:
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
engines: {node: '>= 8'}
@@ -428,6 +612,18 @@ packages:
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
engines: {node: '>=8.6'}
+ mime-db@1.52.0:
+ resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
+ engines: {node: '>= 0.6'}
+
+ mime-types@2.1.35:
+ resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
+ engines: {node: '>= 0.6'}
+
+ mimic-fn@2.1.0:
+ resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
+ engines: {node: '>=6'}
+
minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
@@ -441,6 +637,18 @@ packages:
natural-compare@1.4.0:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
+ npm-run-path@4.0.1:
+ resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
+ engines: {node: '>=8'}
+
+ object-treeify@1.1.33:
+ resolution: {integrity: sha512-EFVjAYfzWqWsBMRHPMAXLCDIJnpMhdWAqR7xG6M6a2cs6PMFpl/+Z20w9zDW4vkxOFfddegBKq9Rehd0bxWE7A==}
+ engines: {node: '>= 10'}
+
+ onetime@5.1.2:
+ resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
+ engines: {node: '>=6'}
+
optionator@0.9.4:
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
engines: {node: '>= 0.8.0'}
@@ -469,6 +677,10 @@ packages:
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
engines: {node: '>=8.6'}
+ picomatch@4.0.2:
+ resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==}
+ engines: {node: '>=12'}
+
prelude-ls@1.2.1:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'}
@@ -478,6 +690,9 @@ packages:
engines: {node: '>=14'}
hasBin: true
+ proxy-from-env@1.1.0:
+ resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
+
punycode@2.3.1:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'}
@@ -509,6 +724,9 @@ packages:
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
engines: {node: '>=8'}
+ signal-exit@3.0.7:
+ resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
+
source-map-support@0.5.21:
resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
@@ -516,6 +734,10 @@ packages:
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
engines: {node: '>=0.10.0'}
+ strip-final-newline@2.0.0:
+ resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
+ engines: {node: '>=6'}
+
strip-json-comments@3.1.1:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'}
@@ -555,14 +777,26 @@ packages:
engines: {node: '>=14.17'}
hasBin: true
+ undici-types@6.21.0:
+ resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
+
uri-js@4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
+ watchpack@2.4.4:
+ resolution: {integrity: sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==}
+ engines: {node: '>=10.13.0'}
+
which@2.0.2:
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
engines: {node: '>= 8'}
hasBin: true
+ which@4.0.0:
+ resolution: {integrity: sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==}
+ engines: {node: ^16.13.0 || >=18.0.0}
+ hasBin: true
+
word-wrap@1.2.5:
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
engines: {node: '>=0.10.0'}
@@ -573,6 +807,22 @@ packages:
snapshots:
+ '@dotenvx/dotenvx@1.44.1':
+ dependencies:
+ commander: 11.1.0
+ dotenv: 16.5.0
+ eciesjs: 0.4.15
+ execa: 5.1.1
+ fdir: 6.4.4(picomatch@4.0.2)
+ ignore: 5.3.2
+ object-treeify: 1.1.33
+ picomatch: 4.0.2
+ which: 4.0.0
+
+ '@ecies/ciphers@0.2.3(@noble/ciphers@1.3.0)':
+ dependencies:
+ '@noble/ciphers': 1.3.0
+
'@eslint-community/eslint-utils@4.7.0(eslint@9.27.0)':
dependencies:
eslint: 9.27.0
@@ -652,6 +902,14 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.0
+ '@noble/ciphers@1.3.0': {}
+
+ '@noble/curves@1.9.1':
+ dependencies:
+ '@noble/hashes': 1.8.0
+
+ '@noble/hashes@1.8.0': {}
+
'@nodelib/fs.scandir@2.1.5':
dependencies:
'@nodelib/fs.stat': 2.0.5
@@ -666,8 +924,21 @@ snapshots:
'@types/estree@1.0.7': {}
+ '@types/graceful-fs@4.1.9':
+ dependencies:
+ '@types/node': 22.15.21
+
'@types/json-schema@7.0.15': {}
+ '@types/node@22.15.21':
+ dependencies:
+ undici-types: 6.21.0
+
+ '@types/watchpack@2.4.4':
+ dependencies:
+ '@types/graceful-fs': 4.1.9
+ '@types/node': 22.15.21
+
'@typescript-eslint/eslint-plugin@8.32.1(@typescript-eslint/parser@8.32.1(eslint@9.27.0)(typescript@5.8.3))(eslint@9.27.0)(typescript@5.8.3)':
dependencies:
'@eslint-community/regexpp': 4.12.1
@@ -764,6 +1035,16 @@ snapshots:
argparse@2.0.1: {}
+ asynckit@0.4.0: {}
+
+ axios@1.9.0:
+ dependencies:
+ follow-redirects: 1.15.9
+ form-data: 4.0.2
+ proxy-from-env: 1.1.0
+ transitivePeerDependencies:
+ - debug
+
balanced-match@1.0.2: {}
brace-expansion@1.1.11:
@@ -781,6 +1062,11 @@ snapshots:
buffer-from@1.1.2: {}
+ call-bind-apply-helpers@1.0.2:
+ dependencies:
+ es-errors: 1.3.0
+ function-bind: 1.1.2
+
callsites@3.1.0: {}
chalk@4.1.2:
@@ -794,6 +1080,12 @@ snapshots:
color-name@1.1.4: {}
+ combined-stream@1.0.8:
+ dependencies:
+ delayed-stream: 1.0.0
+
+ commander@11.1.0: {}
+
commander@2.20.3: {}
concat-map@0.0.1: {}
@@ -810,6 +1102,38 @@ snapshots:
deep-is@0.1.4: {}
+ delayed-stream@1.0.0: {}
+
+ dotenv@16.5.0: {}
+
+ dunder-proto@1.0.1:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ es-errors: 1.3.0
+ gopd: 1.2.0
+
+ eciesjs@0.4.15:
+ dependencies:
+ '@ecies/ciphers': 0.2.3(@noble/ciphers@1.3.0)
+ '@noble/ciphers': 1.3.0
+ '@noble/curves': 1.9.1
+ '@noble/hashes': 1.8.0
+
+ es-define-property@1.0.1: {}
+
+ es-errors@1.3.0: {}
+
+ es-object-atoms@1.1.1:
+ dependencies:
+ es-errors: 1.3.0
+
+ es-set-tostringtag@2.1.0:
+ dependencies:
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ has-tostringtag: 1.0.2
+ hasown: 2.0.2
+
escape-string-regexp@4.0.0: {}
eslint-config-prettier@10.1.5(eslint@9.27.0):
@@ -883,6 +1207,18 @@ snapshots:
esutils@2.0.3: {}
+ execa@5.1.1:
+ dependencies:
+ cross-spawn: 7.0.6
+ get-stream: 6.0.1
+ human-signals: 2.1.0
+ is-stream: 2.0.1
+ merge-stream: 2.0.0
+ npm-run-path: 4.0.1
+ onetime: 5.1.2
+ signal-exit: 3.0.7
+ strip-final-newline: 2.0.0
+
fast-deep-equal@3.1.3: {}
fast-glob@3.3.3:
@@ -901,6 +1237,10 @@ snapshots:
dependencies:
reusify: 1.1.0
+ fdir@6.4.4(picomatch@4.0.2):
+ optionalDependencies:
+ picomatch: 4.0.2
+
file-entry-cache@8.0.0:
dependencies:
flat-cache: 4.0.1
@@ -921,6 +1261,37 @@ snapshots:
flatted@3.3.3: {}
+ follow-redirects@1.15.9: {}
+
+ form-data@4.0.2:
+ dependencies:
+ asynckit: 0.4.0
+ combined-stream: 1.0.8
+ es-set-tostringtag: 2.1.0
+ mime-types: 2.1.35
+
+ function-bind@1.1.2: {}
+
+ get-intrinsic@1.3.0:
+ 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
+
+ get-proto@1.0.1:
+ dependencies:
+ dunder-proto: 1.0.1
+ es-object-atoms: 1.1.1
+
+ get-stream@6.0.1: {}
+
glob-parent@5.1.2:
dependencies:
is-glob: 4.0.3
@@ -929,14 +1300,32 @@ snapshots:
dependencies:
is-glob: 4.0.3
+ glob-to-regexp@0.4.1: {}
+
globals@14.0.0: {}
globals@16.1.0: {}
+ gopd@1.2.0: {}
+
+ graceful-fs@4.2.11: {}
+
graphemer@1.4.0: {}
has-flag@4.0.0: {}
+ has-symbols@1.1.0: {}
+
+ has-tostringtag@1.0.2:
+ dependencies:
+ has-symbols: 1.1.0
+
+ hasown@2.0.2:
+ dependencies:
+ function-bind: 1.1.2
+
+ human-signals@2.1.0: {}
+
ignore@5.3.2: {}
ignore@7.0.4: {}
@@ -956,8 +1345,12 @@ snapshots:
is-number@7.0.0: {}
+ is-stream@2.0.1: {}
+
isexe@2.0.0: {}
+ isexe@3.1.1: {}
+
js-yaml@4.1.0:
dependencies:
argparse: 2.0.1
@@ -983,6 +1376,10 @@ snapshots:
lodash.merge@4.6.2: {}
+ math-intrinsics@1.1.0: {}
+
+ merge-stream@2.0.0: {}
+
merge2@1.4.1: {}
micromatch@4.0.8:
@@ -990,6 +1387,14 @@ snapshots:
braces: 3.0.3
picomatch: 2.3.1
+ mime-db@1.52.0: {}
+
+ mime-types@2.1.35:
+ dependencies:
+ mime-db: 1.52.0
+
+ mimic-fn@2.1.0: {}
+
minimatch@3.1.2:
dependencies:
brace-expansion: 1.1.11
@@ -1002,6 +1407,16 @@ snapshots:
natural-compare@1.4.0: {}
+ npm-run-path@4.0.1:
+ dependencies:
+ path-key: 3.1.1
+
+ object-treeify@1.1.33: {}
+
+ onetime@5.1.2:
+ dependencies:
+ mimic-fn: 2.1.0
+
optionator@0.9.4:
dependencies:
deep-is: 0.1.4
@@ -1029,10 +1444,14 @@ snapshots:
picomatch@2.3.1: {}
+ picomatch@4.0.2: {}
+
prelude-ls@1.2.1: {}
prettier@3.5.3: {}
+ proxy-from-env@1.1.0: {}
+
punycode@2.3.1: {}
queue-microtask@1.2.3: {}
@@ -1053,6 +1472,8 @@ snapshots:
shebang-regex@3.0.0: {}
+ signal-exit@3.0.7: {}
+
source-map-support@0.5.21:
dependencies:
buffer-from: 1.1.2
@@ -1060,6 +1481,8 @@ snapshots:
source-map@0.6.1: {}
+ strip-final-newline@2.0.0: {}
+
strip-json-comments@3.1.1: {}
supports-color@7.2.0:
@@ -1097,14 +1520,25 @@ snapshots:
typescript@5.8.3: {}
+ undici-types@6.21.0: {}
+
uri-js@4.4.1:
dependencies:
punycode: 2.3.1
+ watchpack@2.4.4:
+ dependencies:
+ glob-to-regexp: 0.4.1
+ graceful-fs: 4.2.11
+
which@2.0.2:
dependencies:
isexe: 2.0.0
+ which@4.0.0:
+ dependencies:
+ isexe: 3.1.1
+
word-wrap@1.2.5: {}
yocto-queue@0.1.0: {}
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
new file mode 100644
index 0000000..9a82b7a
--- /dev/null
+++ b/pnpm-workspace.yaml
@@ -0,0 +1,2 @@
+packages:
+ - 'utils/*'
diff --git a/utils/ai.dungeon/README.md b/utils/ai.dungeon/README.md
new file mode 100644
index 0000000..c34a25d
--- /dev/null
+++ b/utils/ai.dungeon/README.md
@@ -0,0 +1 @@
+# AI Dungeon Scenario Updater
diff --git a/utils/ai.dungeon/index.js b/utils/ai.dungeon/index.js
new file mode 100644
index 0000000..0ea246e
--- /dev/null
+++ b/utils/ai.dungeon/index.js
@@ -0,0 +1,418 @@
+"use strict";
+import path from "path";
+import fs from "node:fs";
+import Watchpack from "watchpack";
+import axios from "axios";
+import { minify } from "terser";
+
+const log = (...msg) => {
+ console.log("[LOG]", ...msg);
+};
+const err = (...msg) => {
+ console.error("[ERROR]", ...msg);
+};
+/**
+ * @template O
+ * @param { O } obj
+ * @returns { string }
+ */
+const objToStr = (obj) => Object.prototype.toString.call(obj).match(/\[object (.*)\]/)[1];
+/**
+ * Object is typeof `object` / JSON Object
+ * @template O
+ * @param { O } obj
+ */
+const isObj = (obj) => objToStr(obj) === "Object";
+/**
+ * Object is `null` or `undefined`
+ * @template O
+ * @param { O } obj
+ */
+const isNull = (obj) => {
+ return Object.is(obj, null) || Object.is(obj, undefined);
+};
+/**
+ * Object is Blank
+ * @template O
+ * @param { O } obj
+ */
+const isBlank = (obj) => {
+ return (
+ (typeof obj === "string" && Object.is(obj.trim(), "")) ||
+ ((obj instanceof Set || obj instanceof Map) && Object.is(obj.size, 0)) ||
+ (Array.isArray(obj) && Object.is(obj.length, 0)) ||
+ (isObj(obj) && Object.is(Object.keys(obj).length, 0))
+ );
+};
+/**
+ * Object is Empty
+ * @template O
+ * @param { O } obj
+ */
+const isEmpty = (obj) => {
+ return isNull(obj) || isBlank(obj);
+};
+
+const toTime = () => {
+ return new Intl.DateTimeFormat("default", {
+ hour: "numeric",
+ minute: "numeric",
+ second: "numeric",
+ fractionalSecondDigits: 3
+ }).format(new Date());
+};
+
+/**
+ * @param {import('node:fs').PathLike} filePath
+ * @param {string} encoding
+ */
+const canAccess = async (filePath, encoding = "utf-8") => {
+ try {
+ await fs.promises.access(filePath, fs.promises.constants.R_OK | fs.promises.constants.W_OK);
+ const data = await fs.promises.readFile(filePath, encoding);
+ return data.toString(encoding);
+ } catch (e) {
+ err(e);
+ }
+};
+
+// /**
+// * @returns {Promise}
+// */
+// const getToken = () => {
+// return new Promise((resolve, reject) => {
+// if (typeof indexedDB !== "undefined") {
+// const dbReq = indexedDB.open("firebaseLocalStorageDb");
+// dbReq.onerror = reject;
+// dbReq.onsuccess = (event) => {
+// const transaction = event.target.result.transaction(["firebaseLocalStorage"], "readwrite");
+// const objectStore = transaction.objectStore("firebaseLocalStorage");
+// const allKeys = objectStore.getAllKeys();
+// allKeys.onerror = reject;
+// allKeys.onsuccess = (evt) => {
+// const key = evt.target.result.find((r) => r.includes("firebase:authUser:"));
+// objectStore.get(key).onsuccess = (evt) => {
+// const { value } = evt.target.result;
+// resolve(`AID_TOKEN="${value.stsTokenManager.accessToken}"`);
+// };
+// };
+// };
+// } else {
+// reject(new Error("indexedDB is not defined."))
+// }
+// });
+// };
+const AIDRequest = class {
+ #_;
+ /** @type {string} */
+ token;
+ /**
+ * @type { { operationName: string; variables: {[key: string]: unknown}; query: string; } }
+ */
+ data = {};
+ constructor(accessToken) {
+ this.token = accessToken;
+ }
+ get headers() {
+ return this.#_;
+ }
+ /**
+ * @param {string} data
+ */
+ set headers(data) {
+ this.#_ = {
+ authorization: `firebase ${this.token}`,
+ "content-type": "application/json",
+ "x-gql-operation-name": data,
+ "Sec-GPC": "1",
+ "Sec-Fetch-Dest": "empty",
+ "Sec-Fetch-Mode": "cors",
+ "Sec-Fetch-Site": "same-site",
+ Priority: "u=4"
+ };
+ }
+ /**
+ * @param {this["data"]} d
+ */
+ setBody(d) {
+ d.variables ??= {};
+ this.data = d;
+ return this;
+ }
+ format() {
+ const { headers, data } = this;
+ return {
+ headers,
+ data
+ };
+ }
+ async fetch(type, shortId) {
+ const resp = {
+ data: {}
+ };
+ try {
+ const template = {
+ adventure: {
+ headers: {
+ "x-gql-operation-name": "GetGameplayAdventure"
+ },
+ body: {
+ operationName: "GetGameplayAdventure",
+ variables: { shortId, limit: 1000000, desc: true },
+ query:
+ "query GetGameplayAdventure($shortId: String, $limit: Int, $offset: Int, $desc: Boolean) {\n adventure(shortId: $shortId) {\n id\n publicId\n shortId\n scenarioId\n instructions\n title\n description\n tags\n nsfw\n isOwner\n userJoined\n gameState\n actionCount\n contentType\n createdAt\n showComments\n commentCount\n allowComments\n voteCount\n userVote\n editedAt\n published\n unlisted\n deletedAt\n saveCount\n isSaved\n user {\n id\n isCurrentUser\n isMember\n profile {\n id\n title\n thumbImageUrl\n __typename\n }\n __typename\n }\n shortCode\n thirdPerson\n imageStyle\n memory\n authorsNote\n image\n actionWindow(limit: $limit, offset: $offset, desc: $desc) {\n id\n imageText\n ...ActionSubscriptionAction\n __typename\n }\n allPlayers {\n ...PlayerSubscriptionPlayer\n __typename\n }\n storyCards {\n id\n ...StoryCard\n __typename\n }\n __typename\n }\n}\n\nfragment ActionSubscriptionAction on Action {\n id\n text\n type\n imageUrl\n shareUrl\n imageText\n adventureId\n decisionId\n undoneAt\n deletedAt\n createdAt\n logId\n __typename\n}\n\nfragment PlayerSubscriptionPlayer on Player {\n id\n userId\n characterName\n isTypingAt\n user {\n id\n isMember\n profile {\n id\n title\n thumbImageUrl\n __typename\n }\n __typename\n }\n createdAt\n deletedAt\n blockedAt\n __typename\n}\n\nfragment StoryCard on StoryCard {\n id\n type\n keys\n value\n title\n useForCharacterCreation\n description\n updatedAt\n deletedAt\n __typename\n}"
+ }
+ },
+ adventureDetails: {
+ body: {
+ operationName: "GetAdventureDetails",
+ variables: { shortId },
+ query:
+ "query GetAdventureDetails($shortId: String) {\n adventureState(shortId: $shortId) {\n id\n details\n __typename\n }\n}"
+ }
+ },
+ scenario: {
+ headers: {
+ "x-gql-operation-name": "GetScenario"
+ },
+ body: {
+ operationName: "GetScenario",
+ variables: { shortId },
+ query:
+ "query GetScenario($shortId: String) {\n scenario(shortId: $shortId) {\n id\n contentType\n createdAt\n editedAt\n publicId\n shortId\n title\n description\n prompt\n memory\n authorsNote\n image\n isOwner\n published\n unlisted\n allowComments\n showComments\n commentCount\n voteCount\n userVote\n saveCount\n storyCardCount\n isSaved\n tags\n adventuresPlayed\n thirdPerson\n nsfw\n contentRating\n contentRatingLockedAt\n contentRatingLockedMessage\n tags\n type\n details\n parentScenario {\n id\n shortId\n title\n __typename\n }\n user {\n isCurrentUser\n isMember\n profile {\n title\n thumbImageUrl\n __typename\n }\n __typename\n }\n options {\n id\n userId\n shortId\n title\n prompt\n parentScenarioId\n deletedAt\n __typename\n }\n storyCards {\n id\n ...StoryCard\n __typename\n }\n ...CardSearchable\n __typename\n }\n}\n\nfragment CardSearchable on Searchable {\n id\n contentType\n publicId\n shortId\n title\n description\n image\n tags\n userVote\n voteCount\n published\n unlisted\n publishedAt\n createdAt\n isOwner\n editedAt\n deletedAt\n blockedAt\n isSaved\n saveCount\n commentCount\n userId\n contentRating\n user {\n id\n isMember\n profile {\n id\n title\n thumbImageUrl\n __typename\n }\n __typename\n }\n ... on Adventure {\n actionCount\n userJoined\n playPublicId\n unlisted\n playerCount\n __typename\n }\n ... on Scenario {\n adventuresPlayed\n __typename\n }\n __typename\n}\n\nfragment StoryCard on StoryCard {\n id\n type\n keys\n value\n title\n useForCharacterCreation\n description\n updatedAt\n deletedAt\n __typename\n}"
+ }
+ },
+ scenarioScripting: {
+ operationName: "GetScenarioScripting",
+ variables: { shortId },
+ query:
+ "query GetScenarioScripting($shortId: String) {\n scenario(shortId: $shortId) {\n gameCodeSharedLibrary\n gameCodeOnInput\n gameCodeOnOutput\n gameCodeOnModelContext\n recentScriptLogs\n lastModelContext\n }\n}"
+ },
+ aiVersions: {
+ headers: {
+ "x-gql-operation-name": "GetAiVersions"
+ },
+ body: {
+ operationName: "GetAiVersions",
+ variables: {},
+ query:
+ "query GetAiVersions {\n aiVisibleVersions {\n success\n message\n aiVisibleVersions {\n id\n type\n versionName\n aiDetails\n aiSettings\n access\n release\n available\n instructions\n engineNameEngine {\n engineName\n available\n availableSettings\n __typename\n }\n __typename\n }\n visibleTextVersions {\n id\n type\n versionName\n aiDetails\n aiSettings\n access\n release\n available\n instructions\n engineNameEngine {\n engineName\n available\n availableSettings\n __typename\n }\n __typename\n }\n visibleImageVersions {\n id\n type\n versionName\n aiDetails\n aiSettings\n access\n release\n available\n instructions\n engineNameEngine {\n engineName\n available\n availableSettings\n __typename\n }\n __typename\n }\n __typename\n }\n}"
+ }
+ },
+ importStoryCards: {
+ headers: {
+ "x-gql-operation-name": "ImportStoryCards"
+ },
+ body: {
+ operationName: "ImportStoryCards",
+ variables: {
+ input: shortId
+ },
+ query:
+ "mutation ImportStoryCards($input: ImportStoryCardsInput!) { importStoryCards(input: $input) { success message storyCards { keys value type __typename } __typename }}"
+ }
+ },
+ UpdateScenario: {
+ headers: {
+ "x-gql-operation-name": "UpdateScenario"
+ },
+ body: {
+ operationName: "UpdateScenario",
+ variables: {
+ input: shortId
+ },
+ query:
+ "mutation UpdateScenario($input: ScenarioInput) { updateScenario(input: $input) { scenario { id title description prompt memory authorsNote tags nsfw contentRating contentRatingLockedAt contentRatingLockedMessage published thirdPerson allowComments unlisted image uploadId type details editedAt __typename } message success __typename }}"
+ }
+ },
+ UpdateScenarioScripts: {
+ headers: {
+ "x-gql-operation-name": "UpdateScenarioScripts"
+ },
+ body: {
+ operationName: "UpdateScenarioScripts",
+ variables: shortId,
+ query:
+ "mutation UpdateScenarioScripts($shortId: String, $gameCode: JSONObject) { updateScenarioScripts(shortId: $shortId, gameCode: $gameCode) { success message scenario { id gameCodeSharedLibrary gameCodeOnInput gameCodeOnOutput gameCodeOnModelContext __typename } __typename }}"
+ }
+ },
+ UpdateOptionTitle: {
+ headers: {
+ "x-gql-operation-name": "UpdateOptionTitle"
+ },
+ body: {
+ operationName: "UpdateOptionTitle",
+ variables: {
+ input: shortId
+ },
+ query:
+ "mutation UpdateOptionTitle($input: ScenarioInput) { updateScenario(input: $input) { scenario { id shortId title prompt parentScenarioId deletedAt __typename } message success __typename }}"
+ }
+ },
+ UpdateAdventureState: {
+ headers: {
+ "x-gql-operation-name": "UpdateAdventureState"
+ },
+ body: {
+ operationName: "UpdateAdventureState",
+ variables: {
+ input: shortId
+ },
+ query:
+ "mutation UpdateAdventureState($input: AdventureStateInput) { updateAdventureState(input: $input) { adventure { id details editedAt __typename } message success __typename }}"
+ }
+ },
+ UpdateAdventurePlot: {
+ headers: {
+ "x-gql-operation-name": "UpdateAdventurePlot"
+ },
+ body: {
+ operationName: "UpdateAdventurePlot",
+ variables: {
+ input: shortId
+ },
+ query:
+ "mutation UpdateAdventurePlot($input: AdventurePlotInput) { updateAdventurePlot(input: $input) { adventure { id thirdPerson memory authorsNote editedAt __typename } message success __typename }}"
+ }
+ }
+ };
+ const sel = template[type];
+ if (!sel) {
+ return resp;
+ }
+ this.headers = sel.headers;
+ this.setBody(sel.body);
+ const req = await axios({
+ method: "post",
+ url: "/graphql",
+ baseURL: "https://api.aidungeon.com",
+ timeout: 1000,
+ responseType: "json",
+ ...this.format()
+ });
+ Object.assign(resp, req);
+ return resp;
+ } catch (ex) {
+ err(ex);
+ }
+ return resp;
+ }
+ toJSON() {
+ const { operationName, variables, query } = this.data;
+ return {
+ operationName,
+ variables,
+ query
+ };
+ }
+};
+
+const minifyCode = async (code) => {
+ return (await minify(code, { ecma: 2022 })).code;
+};
+
+async function build() {
+ try {
+ const { AID_ENV, AID_TOKEN, AID_SHORTID } = process.env;
+ const isDev = typeof AID_ENV === "string" && AID_ENV === "development";
+ const r = new AIDRequest(AID_TOKEN);
+ const buildFiles = async () => {
+ try {
+ const files = await Promise.all([
+ canAccess("./src/context.js").then(async (c) => {
+ if (!isDev) {
+ await fs.promises.writeFile("./dist/context.js", c);
+ }
+ return { onModelContext: c };
+ }),
+ canAccess("./src/input.js").then(async (c) => {
+ if (!isDev) {
+ await fs.promises.writeFile("./dist/input.js", c);
+ }
+ return { onInput: c };
+ }),
+ canAccess("./src/library.js").then(async (c) => {
+ if (!isDev) {
+ await fs.promises.writeFile("./dist/library.js", c);
+ await fs.promises.writeFile("./dist/library.min.js", await minifyCode(c));
+ }
+ return { sharedLibrary: c };
+ }),
+ canAccess("./src/output.js").then(async (c) => {
+ if (!isDev) {
+ await fs.promises.writeFile("./dist/output.js", c);
+ }
+ return { onOutput: c };
+ })
+ ]);
+ if (!isDev) {
+ log("Created Files:", {
+ time: toTime()
+ });
+ }
+ if (typeof AID_SHORTID === "string" && !isEmpty(AID_SHORTID)) {
+ const gameCode = {};
+ for (const f of files) {
+ for (const [k, v] of Object.entries(f)) {
+ gameCode[k] = v;
+ }
+ }
+ const { data } = await r.fetch("UpdateScenarioScripts", {
+ gameCode,
+ shortId: AID_SHORTID
+ });
+ if (isEmpty(data.data)) {
+ err(data);
+ return;
+ }
+ if (data.data.errors && Array.isArray(data.data.errors)) {
+ throw new Error(data.data.errors[0].message)
+ }
+ log("UpdateScenarioScripts:", {
+ message: data.data.updateScenarioScripts.message,
+ time: toTime()
+ });
+ }
+ } catch (ex) {
+ err(ex);
+ }
+ };
+ log(`Node ENV: ${AID_ENV}`);
+ await buildFiles();
+ if (isDev) {
+ const wp = new Watchpack();
+ let changed = new Set();
+ wp.watch(["context.js", "input.js", "library.js", "output.js"], ["./src"]);
+ wp.on("change", (changedFile, mtime) => {
+ if (mtime === null) {
+ changed.delete(changedFile);
+ } else {
+ changed.add(changedFile);
+ }
+ });
+ wp.on("aggregated", async () => {
+ // Filter out files that start with a dot from detected changes
+ // (as they are hidden files or temp files created by an editor).
+ const changes = Array.from(changed).filter((filePath) => {
+ return !path.basename(filePath).startsWith(".");
+ });
+ changed = new Set();
+
+ if (changes.length === 0) {
+ return;
+ }
+
+ await buildFiles();
+ });
+ } else {
+ process.exit(0);
+ }
+ } catch (ex) {
+ err(ex);
+ }
+}
+
+build();
+
+// export { build };
+// export default build;
diff --git a/utils/ai.dungeon/package.json b/utils/ai.dungeon/package.json
new file mode 100644
index 0000000..d699e28
--- /dev/null
+++ b/utils/ai.dungeon/package.json
@@ -0,0 +1,25 @@
+{
+ "$schema": "https://json.schemastore.org/package.json",
+ "name": "ai.dungeon",
+ "description": "Upload changes to AI Dungeon scenarios",
+ "version": "1.0.0",
+ "license": "MIT",
+ "type": "module",
+ "main": "./index.js",
+ "exports": {
+ ".": {
+ "import": {
+ "default": "./index.js"
+ }
+ }
+ },
+ "devDependencies": {
+ "@types/node": "^22.15.21",
+ "@types/watchpack": "^2.4.4"
+ },
+ "dependencies": {
+ "axios": "^1.9.0",
+ "terser": "^5.39.2",
+ "watchpack": "^2.4.2"
+ }
+}