diff --git a/.opencode/package-lock.json b/.opencode/package-lock.json index 69798984..8d6c18f3 100644 --- a/.opencode/package-lock.json +++ b/.opencode/package-lock.json @@ -1 +1,399 @@ -{ "name": ".opencode", "lockfileVersion": 3, "requires": true, "packages": { "": { "dependencies": { "@opencode-ai/plugin": "1.17.8" } }, "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.4.tgz", "integrity": "sha512-LCkGo6JDfaBhgST7UpPWgNgLINpcpabaHfyz5OBx75nUYxBsaEPxjnyNjWpeb/xBup/682QnBfRBy2/LvPutZQ==", "cpu": [ "arm64" ], "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.4.tgz", "integrity": "sha512-zExlW9zUJKZH/tOtVMttwjKa4Xm/3KcNjnE3dPN92uCktwavMxpgCA3MoJK/DOnTWsQgo224OaST27/mPNAf+w==", "cpu": [ "x64" ], "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.4.tgz", "integrity": "sha512-Tg3yX65f5GbtXLkrYEHE5oibZG9epyYWas7FogTTEJeDEF9JlXJzKgXaNhT3UXlTOeA+AfZpYZYZ0uPj7Cfquw==", "cpu": [ "arm" ], "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.4.tgz", "integrity": "sha512-dgX0P/9wGPJeHFBG+ZmhgE6bmtMt7NP5CRBGyyktpopdk/mW4POnrpQsSLtKI1dwpc+pPLuXHDh6vvskyQE/sw==", "cpu": [ "arm64" ], "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.4.tgz", "integrity": "sha512-8TNXMEjJc3QEy7R/x1INhgiU+XakDAFUzBhaz7+Rbrs8NH5UQeHQxxmzsSBJGyV6I1jW79undiQm8tOI+D+8FQ==", "cpu": [ "x64" ], "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.4.tgz", "integrity": "sha512-CmCXPQrkbwExx3j946/PtHWHbYJiCRBRDl4BlkRQcJB/YOwQxJRTpoo7aTsortjgoJ1x7opzTSxn7C+ASSLVjQ==", "cpu": [ "x64" ], "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@opencode-ai/plugin": { "version": "1.17.8", "resolved": "https://registry.npmjs.org/@opencode-ai/plugin/-/plugin-1.17.8.tgz", "integrity": "sha512-pkmnYQz5d+xf0h6fAjgplSSJKLqgYKOXr+x6y40GRPdW+/IfndFkMGq7CDsG2SieGD84qv4zYDMyolGo06IMpw==", "license": "MIT", "dependencies": { "@opencode-ai/sdk": "1.17.8", "effect": "4.0.0-beta.74", "zod": "4.1.8" }, "peerDependencies": { "@opentui/core": ">=0.3.4", "@opentui/keymap": ">=0.3.4", "@opentui/solid": ">=0.3.4" }, "peerDependenciesMeta": { "@opentui/core": { "optional": true }, "@opentui/keymap": { "optional": true }, "@opentui/solid": { "optional": true } } }, "node_modules/@opencode-ai/sdk": { "version": "1.17.8", "resolved": "https://registry.npmjs.org/@opencode-ai/sdk/-/sdk-1.17.8.tgz", "integrity": "sha512-6MKmsj2ujZyL44jy+12dpwWYDYKPS9fUr+0wVQxaIlPYQ/eAt8T8T3QrybplJ5ZtHfZUX+esXZ02x2UYYm7oEw==", "license": "MIT", "dependencies": { "cross-spawn": "7.0.6" } }, "node_modules/@standard-schema/spec": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", "license": "MIT" }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" }, "engines": { "node": ">= 8" } }, "node_modules/detect-libc": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "license": "Apache-2.0", "optional": true, "engines": { "node": ">=8" } }, "node_modules/effect": { "version": "4.0.0-beta.74", "resolved": "https://registry.npmjs.org/effect/-/effect-4.0.0-beta.74.tgz", "integrity": "sha512-Yx+Kh12U+i2FmjwEfKs+ePFmpMd43RPD1oGqc/VraSS9bYzvF0Ff3PojwEFEVEewp8xc92Uxu28gTspU4qyvHA==", "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.8.0", "find-my-way-ts": "^0.1.6", "ini": "^7.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^2.0.1", "multipasta": "^0.2.7", "toml": "^4.1.1", "uuid": "^14.0.0", "yaml": "^2.9.0" } }, "node_modules/fast-check": { "version": "4.8.0", "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-4.8.0.tgz", "integrity": "sha512-GOJ158CUMnN6cSahsv4+ExARvIDuzzinFjkp0E9WtiBa5zcVeLozVkWaE4IzFcc+Y48Wp1EDlUZsXRyAztQcSg==", "funding": [ { "type": "individual", "url": "https://github.com/sponsors/dubzzz" }, { "type": "opencollective", "url": "https://opencollective.com/fast-check" } ], "license": "MIT", "dependencies": { "pure-rand": "^8.0.0" }, "engines": { "node": ">=12.17.0" } }, "node_modules/find-my-way-ts": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/find-my-way-ts/-/find-my-way-ts-0.1.6.tgz", "integrity": "sha512-a85L9ZoXtNAey3Y6Z+eBWW658kO/MwR7zIafkIUPUMf3isZG0NCs2pjW2wtjxAKuJPxMAsHUIP4ZPGv0o5gyTA==", "license": "MIT" }, "node_modules/ini": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/ini/-/ini-7.0.0.tgz", "integrity": "sha512-ifK0CgjALofS5bkrcTy4RaQ9Vx2Knf/eLeIO+NaswQEpH1UblrtTSCIvN71qQDMq0PeQ/SSPojvEJp9vvvfr+w==", "license": "ISC", "engines": { "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "license": "ISC" }, "node_modules/kubernetes-types": { "version": "1.30.0", "resolved": "https://registry.npmjs.org/kubernetes-types/-/kubernetes-types-1.30.0.tgz", "integrity": "sha512-Dew1okvhM/SQcIa2rcgujNndZwU8VnSapDgdxlYoB84ZlpAD43U6KLAFqYo17ykSFGHNPrg0qry0bP+GJd9v7Q==", "license": "Apache-2.0" }, "node_modules/msgpackr": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-2.0.4.tgz", "integrity": "sha512-o1C5KRmuRt+apqMr1HuGSqWStZoRBUpEsCsl15uM9VdAF1qHLtvMOU2En747EnTyEl6c4pzPewRMFF31s1CNbA==", "license": "MIT", "optionalDependencies": { "msgpackr-extract": "^3.0.4" } }, "node_modules/msgpackr-extract": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.4.tgz", "integrity": "sha512-4kmO/MdyUIkLIvTPr8VHLil4AtoKIoniWPIEk5+CDy0xnWC84azhSFmuJ7PxZdsYtiP5kEeQsORAVIeMgxT+Hw==", "hasInstallScript": true, "license": "MIT", "optional": true, "dependencies": { "node-gyp-build-optional-packages": "5.2.2" }, "bin": { "download-msgpackr-prebuilds": "bin/download-prebuilds.js" }, "optionalDependencies": { "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.4", "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.4", "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.4", "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.4", "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.4", "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.4" } }, "node_modules/multipasta": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/multipasta/-/multipasta-0.2.7.tgz", "integrity": "sha512-KPA58d68KgGil15oDqXjkUBEBYc00XvbPj5/X+dyzeo/lWm9Nc25pQRlf1D+gv4OpK7NM0J1odrbu9JNNGvynA==", "license": "MIT" }, "node_modules/node-gyp-build-optional-packages": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==", "license": "MIT", "optional": true, "dependencies": { "detect-libc": "^2.0.1" }, "bin": { "node-gyp-build-optional-packages": "bin.js", "node-gyp-build-optional-packages-optional": "optional.js", "node-gyp-build-optional-packages-test": "build-test.js" } }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/pure-rand": { "version": "8.4.0", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-8.4.0.tgz", "integrity": "sha512-IoM8YF/jY0hiugFo/wOWqfmarlE6J0wc6fDK1PhftMk7MGhVZl88sZimmqBBFomLOCSmcCCpsfj7wXASCpvK9A==", "funding": [ { "type": "individual", "url": "https://github.com/sponsors/dubzzz" }, { "type": "opencollective", "url": "https://opencollective.com/fast-check" } ], "license": "MIT" }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/toml": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/toml/-/toml-4.1.1.tgz", "integrity": "sha512-EBJnVBr3dTXdA89WVFoAIPUqkBjxPMwRqsfuo1r240tKFHXv3zgca4+NJib/h6TyvGF7vOawz0jGuryJCdNHrw==", "license": "MIT", "engines": { "node": ">=20" } }, "node_modules/uuid": { "version": "14.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.1.tgz", "integrity": "sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" ], "license": "MIT", "bin": { "uuid": "dist-node/bin/uuid" } }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" }, "engines": { "node": ">= 8" } }, "node_modules/yaml": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", "license": "ISC", "bin": { "yaml": "bin.mjs" }, "engines": { "node": ">= 14.6" }, "funding": { "url": "https://github.com/sponsors/eemeli" } }, "node_modules/zod": { "version": "4.1.8", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" } } }} \ No newline at end of file +{ + "name": ".opencode", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "@opencode-ai/plugin": "1.17.13" + } + }, + "node_modules/@ai-sdk/provider": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-3.0.8.tgz", + "integrity": "sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ==", + "license": "Apache-2.0", + "dependencies": { + "json-schema": "^0.4.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.4.tgz", + "integrity": "sha512-LCkGo6JDfaBhgST7UpPWgNgLINpcpabaHfyz5OBx75nUYxBsaEPxjnyNjWpeb/xBup/682QnBfRBy2/LvPutZQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.4.tgz", + "integrity": "sha512-zExlW9zUJKZH/tOtVMttwjKa4Xm/3KcNjnE3dPN92uCktwavMxpgCA3MoJK/DOnTWsQgo224OaST27/mPNAf+w==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.4.tgz", + "integrity": "sha512-Tg3yX65f5GbtXLkrYEHE5oibZG9epyYWas7FogTTEJeDEF9JlXJzKgXaNhT3UXlTOeA+AfZpYZYZ0uPj7Cfquw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.4.tgz", + "integrity": "sha512-dgX0P/9wGPJeHFBG+ZmhgE6bmtMt7NP5CRBGyyktpopdk/mW4POnrpQsSLtKI1dwpc+pPLuXHDh6vvskyQE/sw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.4.tgz", + "integrity": "sha512-8TNXMEjJc3QEy7R/x1INhgiU+XakDAFUzBhaz7+Rbrs8NH5UQeHQxxmzsSBJGyV6I1jW79undiQm8tOI+D+8FQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.4.tgz", + "integrity": "sha512-CmCXPQrkbwExx3j946/PtHWHbYJiCRBRDl4BlkRQcJB/YOwQxJRTpoo7aTsortjgoJ1x7opzTSxn7C+ASSLVjQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@opencode-ai/plugin": { + "version": "1.17.13", + "resolved": "https://registry.npmjs.org/@opencode-ai/plugin/-/plugin-1.17.13.tgz", + "integrity": "sha512-JjoIs6qTPl0IrXo+J1GTqX9lcb2h2dMoW6BWMR2IbTT3MY2FQ/lvBXDzkx0d3zVRaYN+NTmV4u8Nth396xq+sQ==", + "license": "MIT", + "dependencies": { + "@ai-sdk/provider": "3.0.8", + "@opencode-ai/sdk": "1.17.13", + "effect": "4.0.0-beta.83", + "zod": "4.1.8" + }, + "peerDependencies": { + "@opentui/core": ">=0.3.4", + "@opentui/keymap": ">=0.3.4", + "@opentui/solid": ">=0.3.4" + }, + "peerDependenciesMeta": { + "@opentui/core": { + "optional": true + }, + "@opentui/keymap": { + "optional": true + }, + "@opentui/solid": { + "optional": true + } + } + }, + "node_modules/@opencode-ai/sdk": { + "version": "1.17.13", + "resolved": "https://registry.npmjs.org/@opencode-ai/sdk/-/sdk-1.17.13.tgz", + "integrity": "sha512-VItOGjMzRQx3zypwmeFLNhCiIx32kxS7FqzIJvVZLfyNGCifs3rfGC9qzNKWcxQo4SjNvAw++v4gWWU6Inv+JQ==", + "license": "MIT", + "dependencies": { + "cross-spawn": "7.0.6" + } + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/effect": { + "version": "4.0.0-beta.83", + "resolved": "https://registry.npmjs.org/effect/-/effect-4.0.0-beta.83.tgz", + "integrity": "sha512-0wsak8RtgGAr9UWSbVDgJHZcUqMSvicHcvaZv1MbMM7MCGgW4Rn/137J1MHQbwYPcwYGxT/IqehFd+UbYuj78w==", + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.1.0", + "fast-check": "^4.8.0", + "find-my-way-ts": "^0.1.6", + "ini": "^7.0.0", + "kubernetes-types": "^1.30.0", + "msgpackr": "^2.0.1", + "multipasta": "^0.2.7", + "toml": "^4.1.1", + "uuid": "^14.0.0", + "yaml": "^2.9.0" + } + }, + "node_modules/fast-check": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-4.8.0.tgz", + "integrity": "sha512-GOJ158CUMnN6cSahsv4+ExARvIDuzzinFjkp0E9WtiBa5zcVeLozVkWaE4IzFcc+Y48Wp1EDlUZsXRyAztQcSg==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT", + "dependencies": { + "pure-rand": "^8.0.0" + }, + "engines": { + "node": ">=12.17.0" + } + }, + "node_modules/find-my-way-ts": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/find-my-way-ts/-/find-my-way-ts-0.1.6.tgz", + "integrity": "sha512-a85L9ZoXtNAey3Y6Z+eBWW658kO/MwR7zIafkIUPUMf3isZG0NCs2pjW2wtjxAKuJPxMAsHUIP4ZPGv0o5gyTA==", + "license": "MIT" + }, + "node_modules/ini": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-7.0.0.tgz", + "integrity": "sha512-ifK0CgjALofS5bkrcTy4RaQ9Vx2Knf/eLeIO+NaswQEpH1UblrtTSCIvN71qQDMq0PeQ/SSPojvEJp9vvvfr+w==", + "license": "ISC", + "engines": { + "node": "^22.22.2 || ^24.15.0 || >=26.0.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "license": "(AFL-2.1 OR BSD-3-Clause)" + }, + "node_modules/kubernetes-types": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/kubernetes-types/-/kubernetes-types-1.30.0.tgz", + "integrity": "sha512-Dew1okvhM/SQcIa2rcgujNndZwU8VnSapDgdxlYoB84ZlpAD43U6KLAFqYo17ykSFGHNPrg0qry0bP+GJd9v7Q==", + "license": "Apache-2.0" + }, + "node_modules/msgpackr": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-2.0.4.tgz", + "integrity": "sha512-o1C5KRmuRt+apqMr1HuGSqWStZoRBUpEsCsl15uM9VdAF1qHLtvMOU2En747EnTyEl6c4pzPewRMFF31s1CNbA==", + "license": "MIT", + "optionalDependencies": { + "msgpackr-extract": "^3.0.4" + } + }, + "node_modules/msgpackr-extract": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.4.tgz", + "integrity": "sha512-4kmO/MdyUIkLIvTPr8VHLil4AtoKIoniWPIEk5+CDy0xnWC84azhSFmuJ7PxZdsYtiP5kEeQsORAVIeMgxT+Hw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-gyp-build-optional-packages": "5.2.2" + }, + "bin": { + "download-msgpackr-prebuilds": "bin/download-prebuilds.js" + }, + "optionalDependencies": { + "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.4", + "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.4", + "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.4", + "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.4", + "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.4", + "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.4" + } + }, + "node_modules/multipasta": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/multipasta/-/multipasta-0.2.7.tgz", + "integrity": "sha512-KPA58d68KgGil15oDqXjkUBEBYc00XvbPj5/X+dyzeo/lWm9Nc25pQRlf1D+gv4OpK7NM0J1odrbu9JNNGvynA==", + "license": "MIT" + }, + "node_modules/node-gyp-build-optional-packages": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", + "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==", + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.1" + }, + "bin": { + "node-gyp-build-optional-packages": "bin.js", + "node-gyp-build-optional-packages-optional": "optional.js", + "node-gyp-build-optional-packages-test": "build-test.js" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pure-rand": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-8.4.1.tgz", + "integrity": "sha512-c58R2+SPFcSIPXoU834QN/KPDDOSd8sXcSrqf6e83Me6Rrp1EYkxukkjXMVrKvKaADs1SOyNkWdfvLf6zY8qLQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/toml": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/toml/-/toml-4.1.2.tgz", + "integrity": "sha512-m0vXfHODcw3gk+KONAOlVQ5yNHc3yS3B1ybM3HS1vqDoS0RWTDDVBVVTYi8hH0k+2OM1vmo9fb1WX9EVqjqfHA==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/uuid": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.1.tgz", + "integrity": "sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist-node/bin/uuid" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/yaml": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/zod": { + "version": "4.1.8", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/docs/twitter/2063733456144597200/media/2063642010649530377_1.png b/docs/twitter/2063733456144597200/media/2063642010649530377_1.png new file mode 100644 index 00000000..2a76bef5 Binary files /dev/null and b/docs/twitter/2063733456144597200/media/2063642010649530377_1.png differ diff --git a/docs/twitter/2063733456144597200/media/2063642851284529466_1.png b/docs/twitter/2063733456144597200/media/2063642851284529466_1.png new file mode 100644 index 00000000..eba3a48e Binary files /dev/null and b/docs/twitter/2063733456144597200/media/2063642851284529466_1.png differ diff --git a/docs/twitter/2063733456144597200/media/2063643677440831673_1.png b/docs/twitter/2063733456144597200/media/2063643677440831673_1.png new file mode 100644 index 00000000..fdcc3387 Binary files /dev/null and b/docs/twitter/2063733456144597200/media/2063643677440831673_1.png differ diff --git a/docs/twitter/2063733456144597200/media/2063643677440831673_2.png b/docs/twitter/2063733456144597200/media/2063643677440831673_2.png new file mode 100644 index 00000000..b7ce63ab Binary files /dev/null and b/docs/twitter/2063733456144597200/media/2063643677440831673_2.png differ diff --git a/docs/twitter/2063733456144597200/media/2063643677440831673_3.png b/docs/twitter/2063733456144597200/media/2063643677440831673_3.png new file mode 100644 index 00000000..bcb73670 Binary files /dev/null and b/docs/twitter/2063733456144597200/media/2063643677440831673_3.png differ diff --git a/docs/twitter/2063733456144597200/thread.md b/docs/twitter/2063733456144597200/thread.md new file mode 100644 index 00000000..f164fac1 --- /dev/null +++ b/docs/twitter/2063733456144597200/thread.md @@ -0,0 +1,77 @@ +--- +title: "@NOTimothyLottes I see!" +author: "OZ" +handle: "@winning_tactic" +post_url: "https://x.com/winning_tactic/status/2063733456144597200" +post_id: "2063733456144597200" +timestamp: "2026-06-07 21:22:52" +post_count: 12 +reply_count: 0 +repost_count: 0 +like_count: 0 +view_count: 11 +--- + +# @winning_tactic — @NOTimothyLottes I see! + +## Post 1 (2026-06-07 15:04:23) + +Error codes, many APIs get these so wrong. For example aliasing the same code with multiple meaning so the user has zero idea what actually went wrong and what needs fixing. Here is what I do -> thread + +## Post 2 (2026-06-07 15:07:23) — reply to Post 1 + +I have a force no-inline exit point which prints +ERROR[__line__]:__code__ +Where 'line' is the line number macro __LINE__ passed in from the source, and 'code' is the specific error code. This exits with error code set to 'line'. Thus easy to find termination point in source. + +## Post 3 (2026-06-07 15:13:52) — reply to Post 2 + +Function also scales 'line' by 100, and places the version in the lower digits. So know which release version (I'm not doing more than 100 post-release updates). Note all my source is in a single file (including shader source), so I don't need a file in the error print out + +## Post 4 (2026-06-07 15:19:30) — reply to Post 3 + +I use force inline macros (I_ in my code) that wrap error checks like testing if a win32 call errors with a null pointer (Err0), and uses builtin expect assuming no error to filter through another no-inline (N_) function to GetLastError and exit if fail, otherwise return pointer + +![Media 1](./media/2063642010649530377_1.png) + +## Post 5 (2026-06-07 15:21:31) — reply to Post 4 + +Which means I can simply wrap the calls to WIN32 with a specific Err function and it auto does terminal error checks for cases that shouldn't happen in practice, but if it does happen at least I get instant ability to know where and why + +## Post 6 (2026-06-07 15:22:51) — reply to Post 5 + +The defines I use for context + +![Media 1](./media/2063642851284529466_1.png) + +## Post 7 (2026-06-07 15:26:08) — reply to Post 6 + +And if this is new, what I do for imports is using a M_(name) macro which imports WIN32 symbols as "void name(void)" functions, which I typecast to the correct type at the exact point of call. Means I don't need any system headers or header like code in my code :) + +![Media 1](./media/2063643677440831673_1.png) +![Media 2](./media/2063643677440831673_2.png) +![Media 3](./media/2063643677440831673_3.png) + +## Post 8 (2026-06-07 15:28:34) — reply to Post 7 + +At least for WIN32 I do use standard in EXE dynamic linking since Windows doesn't have the Linux .SO nightmare problem. On Linux I only link to libdl and dlopen and dlsym everything else. In theory that gives portability due to ABI and common libdl naming. + +## Post 9 (2026-06-07 15:30:51) — reply to Post 8 + +The result of all this is "keeping it simple". For the most part I don't do any runtime dynamic creation of 'things' so all my error checks are init time (low cost) only and fail just results in this common Err() with printed {line,code} exit path. + +## Post 10 (2026-06-07 17:18:38) — reply to Post 9 + +Is the error centrally located? e.g. whatever GetLastErr does? I'm motivated to spend some time prettying my own usage, but I keep errors at the call sites, but do a lot of the same action, but the cost is every call is a macro to the real call that handles the rigamarole. green thread based so centrally located is a problem, even though we could do off the curr_tsk register +https://gitlab.com/qsrc.net/Lampyr/-/blob/dev/rt/file.h?ref_type=heads#L61 +then you have to do this kind of jumping through hoops because no one wants to set it up themselves. +https://gitlab.com/qsrc.net/Lampyr/-/blob/dev/rt/mem.h?ref_type=heads#L10 +You certainly have a lot of helper macros and single letter api about them, which I like. tasteful yet foreign. + +## Post 11 (2026-06-07 21:12:08) — reply to Post 10 + +@winning_tactic These are all for errors that kill the application. GetLastError is like the WIN32 version of error number from libc (figure out why an allocation that returned zero failed). + +## Post 12 (2026-06-07 21:22:52) — reply to Post 11 + +@NOTimothyLottes I see! diff --git a/docs/twitter/2063733456144597200/thread_data.json b/docs/twitter/2063733456144597200/thread_data.json new file mode 100644 index 00000000..0869f3fa --- /dev/null +++ b/docs/twitter/2063733456144597200/thread_data.json @@ -0,0 +1,206 @@ +{ + "root_post_id": "2063733456144597200", + "posts": [ + { + "post_id": "2063638204394181034", + "author": "NOTimothyLottes", + "handle": "NOTimothyLottes", + "text": "Error codes, many APIs get these so wrong. For example aliasing the same code with multiple meaning so the user has zero idea what actually went wrong and what needs fixing. Here is what I do -> thread", + "timestamp": "2026-06-07 15:04:23", + "media_urls": [], + "reply_to_id": null, + "quote_of_id": null, + "metrics": { + "reply_count": 3, + "repost_count": 4, + "like_count": 47, + "view_count": 8479 + } + }, + { + "post_id": "2063638960790737206", + "author": "NOTimothyLottes", + "handle": "NOTimothyLottes", + "text": "I have a force no-inline exit point which prints\nERROR[__line__]:__code__ \nWhere 'line' is the line number macro __LINE__ passed in from the source, and 'code' is the specific error code. This exits with error code set to 'line'. Thus easy to find termination point in source.", + "timestamp": "2026-06-07 15:07:23", + "media_urls": [], + "reply_to_id": "2063638204394181034", + "quote_of_id": null, + "metrics": { + "reply_count": 1, + "repost_count": 0, + "like_count": 12, + "view_count": 1060 + } + }, + { + "post_id": "2063640590730842264", + "author": "NOTimothyLottes", + "handle": "NOTimothyLottes", + "text": "Function also scales 'line' by 100, and places the version in the lower digits. So know which release version (I'm not doing more than 100 post-release updates). Note all my source is in a single file (including shader source), so I don't need a file in the error print out", + "timestamp": "2026-06-07 15:13:52", + "media_urls": [], + "reply_to_id": "2063638960790737206", + "quote_of_id": null, + "metrics": { + "reply_count": 1, + "repost_count": 0, + "like_count": 12, + "view_count": 987 + } + }, + { + "post_id": "2063642010649530377", + "author": "NOTimothyLottes", + "handle": "NOTimothyLottes", + "text": "I use force inline macros (I_ in my code) that wrap error checks like testing if a win32 call errors with a null pointer (Err0), and uses builtin expect assuming no error to filter through another no-inline (N_) function to GetLastError and exit if fail, otherwise return pointer", + "timestamp": "2026-06-07 15:19:30", + "media_urls": [ + "https://pbs.twimg.com/media/HKOGypaW4AEU4Xl?format=png&name=orig" + ], + "reply_to_id": "2063640590730842264", + "quote_of_id": null, + "metrics": { + "reply_count": 1, + "repost_count": 0, + "like_count": 8, + "view_count": 689 + } + }, + { + "post_id": "2063642518168739956", + "author": "NOTimothyLottes", + "handle": "NOTimothyLottes", + "text": "Which means I can simply wrap the calls to WIN32 with a specific Err function and it auto does terminal error checks for cases that shouldn't happen in practice, but if it does happen at least I get instant ability to know where and why", + "timestamp": "2026-06-07 15:21:31", + "media_urls": [], + "reply_to_id": "2063642010649530377", + "quote_of_id": null, + "metrics": { + "reply_count": 1, + "repost_count": 0, + "like_count": 6, + "view_count": 592 + } + }, + { + "post_id": "2063642851284529466", + "author": "NOTimothyLottes", + "handle": "NOTimothyLottes", + "text": "The defines I use for context", + "timestamp": "2026-06-07 15:22:51", + "media_urls": [ + "https://pbs.twimg.com/media/HKOIKxeXYAALKO_?format=png&name=orig" + ], + "reply_to_id": "2063642518168739956", + "quote_of_id": null, + "metrics": { + "reply_count": 1, + "repost_count": 0, + "like_count": 7, + "view_count": 564 + } + }, + { + "post_id": "2063643677440831673", + "author": "NOTimothyLottes", + "handle": "NOTimothyLottes", + "text": "And if this is new, what I do for imports is using a M_(name) macro which imports WIN32 symbols as \"void name(void)\" functions, which I typecast to the correct type at the exact point of call. Means I don't need any system headers or header like code in my code :)", + "timestamp": "2026-06-07 15:26:08", + "media_urls": [ + "https://pbs.twimg.com/media/HKOIsxFXgAA_z35?format=png&name=orig", + "https://pbs.twimg.com/media/HKOIx20XMAAtIoB?format=png&name=orig", + "https://pbs.twimg.com/media/HKOI3rPWEAAZ9t0?format=png&name=orig" + ], + "reply_to_id": "2063642851284529466", + "quote_of_id": null, + "metrics": { + "reply_count": 2, + "repost_count": 0, + "like_count": 8, + "view_count": 544 + } + }, + { + "post_id": "2063644292711690546", + "author": "NOTimothyLottes", + "handle": "NOTimothyLottes", + "text": "At least for WIN32 I do use standard in EXE dynamic linking since Windows doesn't have the Linux .SO nightmare problem. On Linux I only link to libdl and dlopen and dlsym everything else. In theory that gives portability due to ABI and common libdl naming.", + "timestamp": "2026-06-07 15:28:34", + "media_urls": [], + "reply_to_id": "2063643677440831673", + "quote_of_id": null, + "metrics": { + "reply_count": 1, + "repost_count": 0, + "like_count": 8, + "view_count": 790 + } + }, + { + "post_id": "2063644866127552521", + "author": "NOTimothyLottes", + "handle": "NOTimothyLottes", + "text": "The result of all this is \"keeping it simple\". For the most part I don't do any runtime dynamic creation of 'things' so all my error checks are init time (low cost) only and fail just results in this common Err() with printed {line,code} exit path.", + "timestamp": "2026-06-07 15:30:51", + "media_urls": [], + "reply_to_id": "2063644292711690546", + "quote_of_id": null, + "metrics": { + "reply_count": 1, + "repost_count": 0, + "like_count": 9, + "view_count": 747 + } + }, + { + "post_id": "2063671989991264586", + "author": "OZ", + "handle": "winning_tactic", + "text": "Is the error centrally located? e.g. whatever GetLastErr does? I'm motivated to spend some time prettying my own usage, but I keep errors at the call sites, but do a lot of the same action, but the cost is every call is a macro to the real call that handles the rigamarole. green thread based so centrally located is a problem, even though we could do off the curr_tsk register\nhttps://gitlab.com/qsrc.net/Lampyr/-/blob/dev/rt/file.h?ref_type=heads#L61\nthen you have to do this kind of jumping through hoops because no one wants to set it up themselves.\nhttps://gitlab.com/qsrc.net/Lampyr/-/blob/dev/rt/mem.h?ref_type=heads#L10\nYou certainly have a lot of helper macros and single letter api about them, which I like. tasteful yet foreign.", + "timestamp": "2026-06-07 17:18:38", + "media_urls": [], + "reply_to_id": "2063644866127552521", + "quote_of_id": null, + "metrics": { + "reply_count": 1, + "repost_count": 0, + "like_count": 0, + "view_count": 97 + } + }, + { + "post_id": "2063730754861822129", + "author": "NOTimothyLottes", + "handle": "NOTimothyLottes", + "text": "@winning_tactic These are all for errors that kill the application. GetLastError is like the WIN32 version of error number from libc (figure out why an allocation that returned zero failed).", + "timestamp": "2026-06-07 21:12:08", + "media_urls": [], + "reply_to_id": "2063671989991264586", + "quote_of_id": null, + "metrics": { + "reply_count": 1, + "repost_count": 0, + "like_count": 0, + "view_count": 28 + } + }, + { + "post_id": "2063733456144597200", + "author": "OZ", + "handle": "winning_tactic", + "text": "@NOTimothyLottes I see!", + "timestamp": "2026-06-07 21:22:52", + "media_urls": [], + "reply_to_id": "2063730754861822129", + "quote_of_id": null, + "metrics": { + "reply_count": 0, + "repost_count": 0, + "like_count": 0, + "view_count": 11 + } + } + ], + "source_url": "https://x.com/winning_tactic/status/2063733456144597200" +} \ No newline at end of file diff --git a/manualslop_layout.ini b/manualslop_layout.ini new file mode 100644 index 00000000..15cded89 --- /dev/null +++ b/manualslop_layout.ini @@ -0,0 +1,132 @@ +;;; !!! This configuration is handled by HelloImGui and stores several Ini Files, separated by markers like this: + ;;;<<>>;;; + +;;;<<>>;;; +[Window][Project Settings] +Pos=0,28 +Size=1666,1172 +Collapsed=0 +DockId=0xAFC85805,3 + +[Window][Files & Media] +Pos=0,28 +Size=1666,1172 +Collapsed=0 +DockId=0xAFC85805,4 + +[Window][AI Settings] +Pos=0,28 +Size=1666,1172 +Collapsed=0 +DockId=0xAFC85805,5 + +[Window][Operations Hub] +Pos=0,28 +Size=1666,1172 +Collapsed=0 +DockId=0xAFC85805,7 + +[Window][Theme] +Pos=0,28 +Size=1666,1172 +Collapsed=0 +DockId=0xAFC85805,6 + +[Window][Discussion Hub] +Pos=0,28 +Size=1666,1172 +Collapsed=0 +DockId=0xAFC85805,0 + +[Window][Log Management] +Pos=0,28 +Size=1666,1172 +Collapsed=0 +DockId=0xAFC85805,1 + +[Window][Diagnostics] +Pos=0,28 +Size=1666,1172 +Collapsed=0 +DockId=0xAFC85805,2 + +[Window][Debug##Default] +Pos=60,60 +Size=400,400 +Collapsed=0 + +[Window][Response] +Pos=346,635 +Size=794,758 +Collapsed=0 + +[Window][Project Stale] +Pos=10,50 +Size=169,184 +Collapsed=0 + +[Table][0x7804123E,3] +RefScale=20 +Column 0 Width=60 +Column 1 Weight=1.0000 +Column 2 Width=70 + +[Table][0x56EAD150,3] +RefScale=20 +Column 0 Width=60 +Column 1 Weight=1.0000 +Column 2 Width=70 + +[Table][0x87F76FD6,3] +RefScale=20 +Column 0 Width=60 +Column 1 Weight=1.0000 +Column 2 Width=70 + +[Table][0x3459F0E7,3] +RefScale=20 +Column 0 Width=60 +Column 1 Weight=1.0000 +Column 2 Width=70 + +[Table][0x51981450,3] +RefScale=20 +Column 0 Width=60 +Column 1 Weight=1.0000 +Column 2 Width=70 + +[Table][0x48E1D781,3] +RefScale=20 +Column 0 Width=60 +Column 1 Weight=1.0000 +Column 2 Width=70 + +[Table][0xFC15AE63,7] +Column 0 Weight=1.0000 +Column 1 Weight=1.0000 +Column 2 Weight=1.0000 +Column 3 Weight=1.0000 +Column 4 Weight=1.0000 +Column 5 Weight=1.0000 +Column 6 Weight=1.0000 + +[Table][0xA02D8C87,3] +RefScale=20 +Column 0 Width=150 +Column 1 Width=100 +Column 2 Weight=1.0000 + +[Docking][Data] +DockSpace ID=0xAFC85805 Window=0x079D3A04 Pos=0,28 Size=1666,1172 CentralNode=1 Selected=0x3F1379AF + +;;;<<>>;;; +;;;<<>>;;; +[Layout] +Name=Default +[StatusBar] +Show=false +ShowFps=true +[Theme] +Name=ImGuiColorsDark +;;;<<>>;;; +{"gImGuiSplitIDs":{"MainDockSpace":2949142533}} diff --git a/scripts/twitter_threads/download_media.py b/scripts/twitter_threads/download_media.py index da8ad40f..2023a13a 100644 --- a/scripts/twitter_threads/download_media.py +++ b/scripts/twitter_threads/download_media.py @@ -40,6 +40,8 @@ def main(argv: list[str] | None = None) -> int: parser.add_argument("--output", type=Path, required=True, help="media output directory") parser.add_argument("--cookies", type=Path, default=None, help="cookies.txt for gallery-dl auth") args = parser.parse_args(argv) + args.output = Path(str(args.output).rstrip("/\\")) + args.cookies = Path(str(args.cookies).rstrip("/\\")) if args.cookies is not None else None try: raw = args.input.read_text(encoding="utf-8") except OSError as e: diff --git a/scripts/twitter_threads/render_markdown.py b/scripts/twitter_threads/render_markdown.py index 057bc3cd..2a21b845 100644 --- a/scripts/twitter_threads/render_markdown.py +++ b/scripts/twitter_threads/render_markdown.py @@ -96,6 +96,8 @@ def main(argv: list[str] | None = None) -> int: parser.add_argument("--media-dir", type=Path, required=True, help="media directory to link") parser.add_argument("--output", type=Path, required=True, help="output .md path") args = parser.parse_args(argv) + args.media_dir = Path(str(args.media_dir).rstrip("/\\")) + args.output = Path(str(args.output).rstrip("/\\")) try: raw = args.input.read_text(encoding="utf-8") except OSError as e: diff --git a/tests/test_twitter_threads_pipeline.py b/tests/test_twitter_threads_pipeline.py index 7decb949..e9b2d2c3 100644 --- a/tests/test_twitter_threads_pipeline.py +++ b/tests/test_twitter_threads_pipeline.py @@ -99,3 +99,31 @@ def test_render_cli(tmp_path: Path) -> None: text = out.read_text(encoding="utf-8") assert "[Media 1](./media/7_img1.jpg)" in text assert "body" in text + +def test_render_cli_trailing_slash_on_media_dir(tmp_path: Path) -> None: + p1 = _post("8", text="body", media_urls=("https://pbs.twimg.com/media/DDD.jpg",)) + t = ThreadData(root_post_id="8", posts=(p1,), source_url="https://x.com/x/x/8") + thread_data_json = tmp_path / "thread_data.json" + thread_data_json.write_text(json.dumps(thread_to_dict(t)), encoding="utf-8") + mediadir = tmp_path / "media" + mediadir.mkdir() + (mediadir / "8_img1.jpg").write_bytes(b"x") + out = tmp_path / "thread.md" + code = render_main(["--input", str(thread_data_json), "--media-dir", "./" + str(mediadir).replace("\\", "/") + "/", "--output", str(out)]) + assert code == 0 + text = out.read_text(encoding="utf-8") + assert "[Media 1](./media/8_img1.jpg)" in text + assert "body" in text + +def test_download_cli_trailing_slash_on_output(tmp_path: Path) -> None: + p1 = _post("9", media_urls=("https://pbs.twimg.com/media/EEE.jpg",)) + t = ThreadData(root_post_id="9", posts=(p1,), source_url="https://x.com/x/x/9") + thread_data_json = tmp_path / "thread_data.json" + thread_data_json.write_text(json.dumps(thread_to_dict(t)), encoding="utf-8") + mediadir = tmp_path / "media" + mediadir.mkdir() + (mediadir / "9_1.jpg").write_bytes(b"x") + with patch("scripts.twitter_threads.download_media.subprocess.run", MagicMock(return_value=MagicMock(returncode=0))): + code = download_main(["--input", str(thread_data_json), "--output", "./" + str(mediadir).replace("\\", "/") + "/"]) + assert code == 0 + assert (mediadir / "9_1.jpg").exists()