diff --git a/bun.lock b/bun.lock index 9cdc9fc04..ee5f571d8 100644 --- a/bun.lock +++ b/bun.lock @@ -4,6 +4,7 @@ "": { "name": "opencode", "devDependencies": { + "@hey-api/openapi-ts": "0.80.1", "prettier": "3.5.3", "sst": "3.17.8", }, @@ -72,7 +73,7 @@ "zod-to-json-schema": "3.24.5", }, }, - "packages/sdk/js": { + "packages/sdk": { "name": "@opencode-ai/sdk", "version": "0.1.0-alpha.20", "devDependencies": { @@ -388,6 +389,10 @@ "@fontsource/ibm-plex-mono": ["@fontsource/ibm-plex-mono@5.2.5", "", {}, "sha512-G09N3GfuT9qj3Ax2FDZvKqZttzM3v+cco2l8uXamhKyXLdmlaUDH5o88/C3vtTHj2oT7yRKsvxz9F+BXbWKMYA=="], + "@hey-api/json-schema-ref-parser": ["@hey-api/json-schema-ref-parser@1.0.6", "", { "dependencies": { "@jsdevtools/ono": "^7.1.3", "@types/json-schema": "^7.0.15", "js-yaml": "^4.1.0", "lodash": "^4.17.21" } }, "sha512-yktiFZoWPtEW8QKS65eqKwA5MTKp88CyiL8q72WynrBs/73SAaxlSWlA2zW/DZlywZ5hX1OYzrCC0wFdvO9c2w=="], + + "@hey-api/openapi-ts": ["@hey-api/openapi-ts@0.80.1", "", { "dependencies": { "@hey-api/json-schema-ref-parser": "1.0.6", "ansi-colors": "4.1.3", "c12": "2.0.1", "color-support": "1.1.3", "commander": "13.0.0", "handlebars": "4.7.8", "open": "10.1.2", "semver": "7.7.2" }, "peerDependencies": { "typescript": "^5.5.3" }, "bin": { "openapi-ts": "bin/index.cjs" } }, "sha512-AC478kg36vmmrseLZNFonZ/cmXXmDzW5yWz4PVg1S8ebJsRtVRJ/QU+mtnXfzf9avN2P0pz/AO4WAe4jyFY2gA=="], + "@hono/zod-validator": ["@hono/zod-validator@0.4.2", "", { "peerDependencies": { "hono": ">=3.9.0", "zod": "^3.19.1" } }, "sha512-1rrlBg+EpDPhzOV4hT9pxr5+xDVmKuz6YJl+la7VCwK6ass5ldyKm5fD+umJdV2zhHD6jROoCCv8NbTwyfhT0g=="], "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], @@ -478,7 +483,7 @@ "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.4", "", {}, "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw=="], - "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="], + "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.29", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ=="], "@jsdevtools/ono": ["@jsdevtools/ono@7.1.3", "", {}, "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg=="], @@ -536,7 +541,7 @@ "@openauthjs/openauth": ["@openauthjs/openauth@0.4.3", "", { "dependencies": { "@standard-schema/spec": "1.0.0-beta.3", "aws4fetch": "1.0.20", "jose": "5.9.6" }, "peerDependencies": { "arctic": "^2.2.2", "hono": "^4.0.0" } }, "sha512-RlnjqvHzqcbFVymEwhlUEuac4utA5h4nhSK/i2szZuQmxTIqbGUxZ+nM+avM+VV4Ing+/ZaNLKILoXS3yrkOOw=="], - "@opencode-ai/sdk": ["@opencode-ai/sdk@workspace:packages/sdk/js"], + "@opencode-ai/sdk": ["@opencode-ai/sdk@workspace:packages/sdk"], "@opencode/function": ["@opencode/function@workspace:packages/function"], @@ -792,6 +797,8 @@ "ansi-align": ["ansi-align@3.0.1", "", { "dependencies": { "string-width": "^4.1.0" } }, "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w=="], + "ansi-colors": ["ansi-colors@4.1.3", "", {}, "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw=="], + "ansi-escapes": ["ansi-escapes@7.0.0", "", { "dependencies": { "environment": "^1.0.0" } }, "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw=="], "ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="], @@ -904,6 +911,8 @@ "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="], + "c12": ["c12@2.0.1", "", { "dependencies": { "chokidar": "^4.0.1", "confbox": "^0.1.7", "defu": "^6.1.4", "dotenv": "^16.4.5", "giget": "^1.2.3", "jiti": "^2.3.0", "mlly": "^1.7.1", "ohash": "^1.1.4", "pathe": "^1.1.2", "perfect-debounce": "^1.0.0", "pkg-types": "^1.2.0", "rc9": "^2.1.2" }, "peerDependencies": { "magicast": "^0.3.5" }, "optionalPeers": ["magicast"] }, "sha512-Z4JgsKXHG37C6PYUtIxCfLJZvo6FyhHJoClwwb9ftUkLpPSkuYqn6Tr+vnaN8hymm0kIbcg6Ey3kv/Q71k5w/A=="], + "call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="], "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], @@ -936,6 +945,8 @@ "ci-info": ["ci-info@4.3.0", "", {}, "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ=="], + "citty": ["citty@0.1.6", "", { "dependencies": { "consola": "^3.2.3" } }, "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ=="], + "cjs-module-lexer": ["cjs-module-lexer@1.4.3", "", {}, "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q=="], "clean-git-ref": ["clean-git-ref@2.0.1", "", {}, "sha512-bLSptAy2P0s6hU4PzuIMKmMJJSE6gLXGH1cntDu7bWJUksvuM+7ReOK61mozULErYvP6a15rnYl0zFDef+pyPw=="], @@ -968,14 +979,20 @@ "color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="], + "color-support": ["color-support@1.1.3", "", { "bin": { "color-support": "bin.js" } }, "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg=="], + "comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="], - "commander": ["commander@10.0.1", "", {}, "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug=="], + "commander": ["commander@13.0.0", "", {}, "sha512-oPYleIY8wmTVzkvQq10AEok6YcTC4sRUBl8F9gVuwchGVUCTbl/vhLTaQqutuuySYOsu8YTgV+OxKc/8Yvx+mQ=="], "common-ancestor-path": ["common-ancestor-path@1.0.1", "", {}, "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w=="], "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], + "confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], + + "consola": ["consola@3.4.2", "", {}, "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA=="], + "content-disposition": ["content-disposition@1.0.0", "", { "dependencies": { "safe-buffer": "5.2.1" } }, "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg=="], "content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="], @@ -1066,6 +1083,8 @@ "dlv": ["dlv@1.1.3", "", {}, "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="], + "dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="], + "dset": ["dset@3.1.4", "", {}, "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA=="], "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], @@ -1232,6 +1251,8 @@ "fs-constants": ["fs-constants@1.0.0", "", {}, "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="], + "fs-minipass": ["fs-minipass@2.1.0", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg=="], + "fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="], "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], @@ -1254,6 +1275,8 @@ "get-stream": ["get-stream@6.0.1", "", {}, "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="], + "giget": ["giget@1.2.5", "", { "dependencies": { "citty": "^0.1.6", "consola": "^3.4.0", "defu": "^6.1.4", "node-fetch-native": "^1.6.6", "nypm": "^0.5.4", "pathe": "^2.0.3", "tar": "^6.2.1" }, "bin": { "giget": "dist/cli.mjs" } }, "sha512-r1ekGw/Bgpi3HLV3h1MRBIlSAdHoIMklpaQ3OQLFcRw9PwAj2rqigvIbg+dBUI51OxVI2jsEtDywDBjSiuf7Ug=="], + "github-from-package": ["github-from-package@0.0.0", "", {}, "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="], "github-slugger": ["github-slugger@2.0.0", "", {}, "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw=="], @@ -1276,6 +1299,8 @@ "h3": ["h3@1.15.3", "", { "dependencies": { "cookie-es": "^1.2.2", "crossws": "^0.3.4", "defu": "^6.1.4", "destr": "^2.0.5", "iron-webcrypto": "^1.2.1", "node-mock-http": "^1.0.0", "radix3": "^1.1.2", "ufo": "^1.6.1", "uncrypto": "^0.1.3" } }, "sha512-z6GknHqyX0h9aQaTx22VZDf6QyZn+0Nh+Ym8O/u0SGSkyF5cuTJYKlc8MkzW3Nzf9LE1ivcpmYC3FUGpywhuUQ=="], + "handlebars": ["handlebars@4.7.8", "", { "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.2", "source-map": "^0.6.1", "wordwrap": "^1.0.0" }, "optionalDependencies": { "uglify-js": "^3.1.4" }, "bin": { "handlebars": "bin/handlebars" } }, "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ=="], + "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], "has-property-descriptors": ["has-property-descriptors@1.0.2", "", { "dependencies": { "es-define-property": "^1.0.0" } }, "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg=="], @@ -1498,6 +1523,8 @@ "jest-worker": ["jest-worker@29.7.0", "", { "dependencies": { "@types/node": "*", "jest-util": "^29.7.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" } }, "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw=="], + "jiti": ["jiti@2.5.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w=="], + "jmespath": ["jmespath@0.16.0", "", {}, "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw=="], "jose": ["jose@6.0.11", "", {}, "sha512-QxG7EaliDARm1O1S8BGakqncGT9s25bKL1WSf6/oa17Tkqwi8D2ZNglqCF+DsYF88/rV66Q/Q2mFAy697E1DUg=="], @@ -1546,6 +1573,8 @@ "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], + "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], + "lodash.memoize": ["lodash.memoize@4.1.2", "", {}, "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag=="], "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], @@ -1718,8 +1747,16 @@ "minimisted": ["minimisted@2.0.1", "", { "dependencies": { "minimist": "^1.2.5" } }, "sha512-1oPjfuLQa2caorJUM8HV8lGgWCc0qqAO1MNv/k05G4qslmsndV/5WdNZrqCiyqiz3wohia2Ij2B7w2Dr7/IyrA=="], + "minipass": ["minipass@5.0.0", "", {}, "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ=="], + + "minizlib": ["minizlib@2.1.2", "", { "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" } }, "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg=="], + + "mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="], + "mkdirp-classic": ["mkdirp-classic@0.5.3", "", {}, "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="], + "mlly": ["mlly@1.7.4", "", { "dependencies": { "acorn": "^8.14.0", "pathe": "^2.0.1", "pkg-types": "^1.3.0", "ufo": "^1.5.4" } }, "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw=="], + "mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="], "mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="], @@ -1736,6 +1773,8 @@ "negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="], + "neo-async": ["neo-async@2.6.2", "", {}, "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="], + "neotraverse": ["neotraverse@0.6.18", "", {}, "sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA=="], "nlcst-to-string": ["nlcst-to-string@4.0.0", "", { "dependencies": { "@types/nlcst": "^2.0.0" } }, "sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA=="], @@ -1770,6 +1809,8 @@ "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="], + "nypm": ["nypm@0.5.4", "", { "dependencies": { "citty": "^0.1.6", "consola": "^3.4.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "tinyexec": "^0.3.2", "ufo": "^1.5.4" }, "bin": { "nypm": "dist/cli.mjs" } }, "sha512-X0SNNrZiGU8/e/zAB7sCTtdxWTMSIO73q+xuKgglm2Yvzwlo8UoC5FNySQFCvl84uPaeADkqHUZUkWy4aH4xOA=="], + "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], "object-hash": ["object-hash@2.2.0", "", {}, "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw=="], @@ -1778,7 +1819,7 @@ "ofetch": ["ofetch@1.4.1", "", { "dependencies": { "destr": "^2.0.3", "node-fetch-native": "^1.6.4", "ufo": "^1.5.4" } }, "sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw=="], - "ohash": ["ohash@2.0.11", "", {}, "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ=="], + "ohash": ["ohash@1.1.6", "", {}, "sha512-TBu7PtV8YkAZn0tSxobKY2n2aAQva936lhRrj6957aDaCf9IEtqsKbgMzXE/F/sjqYOwmrukeORHNLe5glk7Cg=="], "oidc-token-hash": ["oidc-token-hash@5.1.0", "", {}, "sha512-y0W+X7Ppo7oZX6eovsRkuzcSM40Bicg2JEJkDJ4irIt1wsYAP5MLSNv+QAogO8xivMffw/9OvV3um1pxXgt1uA=="], @@ -1850,7 +1891,9 @@ "path-to-regexp": ["path-to-regexp@6.3.0", "", {}, "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="], - "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + "pathe": ["pathe@1.1.2", "", {}, "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="], + + "perfect-debounce": ["perfect-debounce@1.0.0", "", {}, "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA=="], "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], @@ -1864,6 +1907,8 @@ "pkg-dir": ["pkg-dir@4.2.0", "", { "dependencies": { "find-up": "^4.0.0" } }, "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ=="], + "pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="], + "possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="], "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], @@ -1912,6 +1957,8 @@ "rc": ["rc@1.2.8", "", { "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, "bin": { "rc": "./cli.js" } }, "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw=="], + "rc9": ["rc9@2.1.2", "", { "dependencies": { "defu": "^6.1.4", "destr": "^2.0.3" } }, "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg=="], + "react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="], "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], @@ -2062,7 +2109,7 @@ "solid-refresh": ["solid-refresh@0.6.3", "", { "dependencies": { "@babel/generator": "^7.23.6", "@babel/helper-module-imports": "^7.22.15", "@babel/types": "^7.23.6" }, "peerDependencies": { "solid-js": "^1.3" } }, "sha512-F3aPsX6hVw9ttm5LYlth8Q15x6MlI/J3Dn+o3EQyRTtTxidepSTwAYdozt01/YA+7ObcciagGEyXIopGZzQtbA=="], - "source-map": ["source-map@0.7.4", "", {}, "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA=="], + "source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], @@ -2134,6 +2181,8 @@ "synckit": ["synckit@0.11.11", "", { "dependencies": { "@pkgr/core": "^0.2.9" } }, "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw=="], + "tar": ["tar@6.2.1", "", { "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A=="], + "tar-fs": ["tar-fs@3.1.0", "", { "dependencies": { "pump": "^3.0.0", "tar-stream": "^3.1.5" }, "optionalDependencies": { "bare-fs": "^4.0.1", "bare-path": "^3.0.0" } }, "sha512-5Mty5y/sOF1YWj1J6GiBodjlDc05CUR8PKXrsnFAiSG0xA+GHeWLovaZPYUDXkH/1iKRf2+M5+OrRgzC7O9b7w=="], "tar-stream": ["tar-stream@3.1.7", "", { "dependencies": { "b4a": "^1.6.4", "fast-fifo": "^1.2.0", "streamx": "^2.15.0" } }, "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ=="], @@ -2210,6 +2259,8 @@ "ufo": ["ufo@1.6.1", "", {}, "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA=="], + "uglify-js": ["uglify-js@3.19.3", "", { "bin": { "uglifyjs": "bin/uglifyjs" } }, "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ=="], + "ultrahtml": ["ultrahtml@1.6.0", "", {}, "sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw=="], "uncrypto": ["uncrypto@0.1.3", "", {}, "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q=="], @@ -2314,6 +2365,8 @@ "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], + "wordwrap": ["wordwrap@1.0.0", "", {}, "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q=="], + "workerd": ["workerd@1.20250709.0", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20250709.0", "@cloudflare/workerd-darwin-arm64": "1.20250709.0", "@cloudflare/workerd-linux-64": "1.20250709.0", "@cloudflare/workerd-linux-arm64": "1.20250709.0", "@cloudflare/workerd-windows-64": "1.20250709.0" }, "bin": { "workerd": "bin/workerd" } }, "sha512-BqLPpmvRN+TYUSG61OkWamsGdEuMwgvabP8m0QOHIfofnrD2YVyWqE1kXJ0GH5EsVEuWamE5sR8XpTfsGBmIpg=="], "wrangler": ["wrangler@4.24.3", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.4.0", "@cloudflare/unenv-preset": "2.3.3", "blake3-wasm": "2.1.5", "esbuild": "0.25.4", "miniflare": "4.20250709.0", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.17", "workerd": "1.20250709.0" }, "optionalDependencies": { "fsevents": "~2.3.2" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20250709.0" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" } }, "sha512-stB1Wfs5NKlspsAzz8SBujBKsDqT5lpCyrL+vSUMy3uueEtI1A5qyORbKoJhIguEbwHfWS39mBsxzm6Vm1J2cg=="], @@ -2384,7 +2437,7 @@ "@ai-sdk/anthropic/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@2.2.8", "", { "dependencies": { "@ai-sdk/provider": "1.1.3", "nanoid": "^3.3.8", "secure-json-parse": "^2.7.0" }, "peerDependencies": { "zod": "^3.23.8" } }, "sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA=="], - "@ampproject/remapping/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.29", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ=="], + "@arethetypeswrong/cli/commander": ["commander@10.0.1", "", {}, "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug=="], "@arethetypeswrong/cli/marked": ["marked@9.1.6", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-jcByLnIFkd5gSXZmjNvS1TlmRhCXZjIzHYlaGkPlLIekG55JDR2Z4va9tZwCiP+/RDERiNhMOFu01xd6O5ct1Q=="], @@ -2394,16 +2447,18 @@ "@astrojs/mdx/@astrojs/markdown-remark": ["@astrojs/markdown-remark@6.3.2", "", { "dependencies": { "@astrojs/internal-helpers": "0.6.1", "@astrojs/prism": "3.3.0", "github-slugger": "^2.0.0", "hast-util-from-html": "^2.0.3", "hast-util-to-text": "^4.0.2", "import-meta-resolve": "^4.1.0", "js-yaml": "^4.1.0", "mdast-util-definitions": "^6.0.0", "rehype-raw": "^7.0.0", "rehype-stringify": "^10.0.1", "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.2", "remark-smartypants": "^3.0.2", "shiki": "^3.2.1", "smol-toml": "^1.3.1", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.1", "vfile": "^6.0.3" } }, "sha512-bO35JbWpVvyKRl7cmSJD822e8YA8ThR/YbUsciWNA7yTcqpIAL2hJDToWP5KcZBWxGT6IOdOkHSXARSNZc4l/Q=="], + "@astrojs/mdx/source-map": ["source-map@0.7.4", "", {}, "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA=="], + "@aws-crypto/util/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="], "@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - "@babel/generator/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.29", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ=="], - "@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], "@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + "@cspotcode/source-map-support/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="], + "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], "@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="], @@ -2434,19 +2489,13 @@ "@jest/pattern/jest-regex-util": ["jest-regex-util@30.0.1", "", {}, "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA=="], - "@jest/reporters/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.29", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ=="], - "@jest/reporters/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], "@jest/reporters/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], - "@jest/source-map/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.29", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ=="], - - "@jest/transform/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.29", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ=="], - "@jest/types/@types/node": ["@types/node@22.13.9", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw=="], - "@jridgewell/gen-mapping/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.29", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ=="], + "@mdx-js/mdx/source-map": ["source-map@0.7.4", "", {}, "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA=="], "@openauthjs/openauth/@standard-schema/spec": ["@standard-schema/spec@1.0.0-beta.3", "", {}, "sha512-0ifF3BjA1E8SY9C+nUew8RefNOIq0cDlYALPty4rhUm8Rrl6tCM8hBT4bhGhx7I7iXD0uAgt50lgo8dD73ACMw=="], @@ -2502,12 +2551,18 @@ "error-ex/is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="], + "estree-util-to-js/source-map": ["source-map@0.7.4", "", {}, "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA=="], + "express/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="], "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], "filelist/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="], + "fs-minipass/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + + "giget/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + "glob/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="], "gray-matter/js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="], @@ -2518,8 +2573,6 @@ "ignore-walk/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="], - "istanbul-lib-source-maps/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - "istanbul-reports/html-escaper": ["html-escaper@2.0.2", "", {}, "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg=="], "jest-changed-files/p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], @@ -2578,6 +2631,12 @@ "miniflare/zod": ["zod@3.22.3", "", {}, "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug=="], + "minizlib/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + + "mlly/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + + "nypm/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + "opencontrol/@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.6.1", "", { "dependencies": { "content-type": "^1.0.5", "cors": "^2.8.5", "eventsource": "^3.0.2", "express": "^5.0.1", "express-rate-limit": "^7.5.0", "pkce-challenge": "^4.1.0", "raw-body": "^3.0.0", "zod": "^3.23.8", "zod-to-json-schema": "^3.24.1" } }, "sha512-oxzMzYCkZHMntzuyerehK3fV6A2Kwh5BD6CGEJSVDU2QNEhfLOptf2X7esQgaHZXHZY0oHmMsOtIDLP71UJXgA=="], "opencontrol/hono": ["hono@4.7.4", "", {}, "sha512-Pst8FuGqz3L7tFF+u9Pu70eI0xa5S3LPUmrNd5Jm8nTHze9FxLTK9Kaj5g/k4UcwuJSXTP65SyHOPLrffpcAJg=="], @@ -2596,6 +2655,8 @@ "pkg-dir/find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="], + "pkg-types/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + "prebuild-install/tar-fs": ["tar-fs@2.1.3", "", { "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", "tar-stream": "^2.1.4" } }, "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg=="], "pretty-format/ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="], @@ -2614,8 +2675,6 @@ "sitemap/sax": ["sax@1.4.1", "", {}, "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg=="], - "source-map-support/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - "sst/jose": ["jose@5.2.3", "", {}, "sha512-KUXdbctm1uHVL8BYhnyHkgp3zDX5KW8ZhAKVFEfUbU2P8Alpzjb+48hHvjOdQIyPshoblhzsuqOwEEAbtHVirA=="], "stack-utils/escape-string-regexp": ["escape-string-regexp@2.0.0", "", {}, "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w=="], @@ -2624,6 +2683,8 @@ "strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "tar/chownr": ["chownr@2.0.0", "", {}, "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="], + "test-exclude/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], "to-buffer/isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="], @@ -2636,14 +2697,18 @@ "tsc-multi/yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], + "unenv/ohash": ["ohash@2.0.11", "", {}, "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ=="], + + "unenv/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + "unicode-trie/pako": ["pako@0.2.9", "", {}, "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA=="], + "unifont/ohash": ["ohash@2.0.11", "", {}, "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ=="], + "unstorage/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], "uri-js/punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], - "v8-to-istanbul/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.29", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ=="], - "wrangler/esbuild": ["esbuild@0.25.4", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.4", "@esbuild/android-arm": "0.25.4", "@esbuild/android-arm64": "0.25.4", "@esbuild/android-x64": "0.25.4", "@esbuild/darwin-arm64": "0.25.4", "@esbuild/darwin-x64": "0.25.4", "@esbuild/freebsd-arm64": "0.25.4", "@esbuild/freebsd-x64": "0.25.4", "@esbuild/linux-arm": "0.25.4", "@esbuild/linux-arm64": "0.25.4", "@esbuild/linux-ia32": "0.25.4", "@esbuild/linux-loong64": "0.25.4", "@esbuild/linux-mips64el": "0.25.4", "@esbuild/linux-ppc64": "0.25.4", "@esbuild/linux-riscv64": "0.25.4", "@esbuild/linux-s390x": "0.25.4", "@esbuild/linux-x64": "0.25.4", "@esbuild/netbsd-arm64": "0.25.4", "@esbuild/netbsd-x64": "0.25.4", "@esbuild/openbsd-arm64": "0.25.4", "@esbuild/openbsd-x64": "0.25.4", "@esbuild/sunos-x64": "0.25.4", "@esbuild/win32-arm64": "0.25.4", "@esbuild/win32-ia32": "0.25.4", "@esbuild/win32-x64": "0.25.4" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q=="], "wrap-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="], diff --git a/package.json b/package.json index 37ce6cf08..8316ba095 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,7 @@ }, "workspaces": { "packages": [ - "packages/*", - "packages/sdk/js" + "packages/*" ], "catalog": { "@types/node": "22.13.9", @@ -25,6 +24,7 @@ } }, "devDependencies": { + "@hey-api/openapi-ts": "0.80.1", "prettier": "3.5.3", "sst": "3.17.8" }, diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts index 1c4f19b67..c3e42c4f6 100644 --- a/packages/opencode/src/server/server.ts +++ b/packages/opencode/src/server/server.ts @@ -94,6 +94,7 @@ export namespace Server { "/event", describeRoute({ description: "Get events", + operationId: "event.subscribe", responses: { 200: { description: "Event stream", @@ -137,6 +138,7 @@ export namespace Server { "/app", describeRoute({ description: "Get app info", + operationId: "app.get", responses: { 200: { description: "200", @@ -156,6 +158,7 @@ export namespace Server { "/app/init", describeRoute({ description: "Initialize the app", + operationId: "app.init", responses: { 200: { description: "Initialize the app", @@ -176,6 +179,7 @@ export namespace Server { "/config", describeRoute({ description: "Get config info", + operationId: "config.get", responses: { 200: { description: "Get config info", @@ -195,6 +199,7 @@ export namespace Server { "/session", describeRoute({ description: "List all sessions", + operationId: "session.list", responses: { 200: { description: "List of sessions", @@ -216,6 +221,7 @@ export namespace Server { "/session", describeRoute({ description: "Create a new session", + operationId: "session.create", responses: { ...ERRORS, 200: { @@ -237,6 +243,7 @@ export namespace Server { "/session/:id", describeRoute({ description: "Delete a session and all its data", + operationId: "session.delete", responses: { 200: { description: "Successfully deleted session", @@ -263,6 +270,7 @@ export namespace Server { "/session/:id/init", describeRoute({ description: "Analyze the app and create an AGENTS.md file", + operationId: "session.init", responses: { 200: { description: "200", @@ -299,6 +307,7 @@ export namespace Server { "/session/:id/abort", describeRoute({ description: "Abort a session", + operationId: "session.abort", responses: { 200: { description: "Aborted session", @@ -324,6 +333,7 @@ export namespace Server { "/session/:id/share", describeRoute({ description: "Share a session", + operationId: "session.share", responses: { 200: { description: "Successfully shared session", @@ -352,6 +362,7 @@ export namespace Server { "/session/:id/share", describeRoute({ description: "Unshare the session", + operationId: "session.unshare", responses: { 200: { description: "Successfully unshared session", @@ -380,6 +391,7 @@ export namespace Server { "/session/:id/summarize", describeRoute({ description: "Summarize the session", + operationId: "session.summarize", responses: { 200: { description: "Summarized session", @@ -415,6 +427,7 @@ export namespace Server { "/session/:id/message", describeRoute({ description: "List messages for a session", + operationId: "session.messages", responses: { 200: { description: "List of messages", @@ -448,6 +461,7 @@ export namespace Server { "/session/:id/message", describeRoute({ description: "Create and send a new message to a session", + operationId: "session.chat", responses: { 200: { description: "Created message", @@ -477,6 +491,7 @@ export namespace Server { "/session/:id/revert", describeRoute({ description: "Revert a message", + operationId: "session.revert", responses: { 200: { description: "Updated session", @@ -506,6 +521,7 @@ export namespace Server { "/session/:id/unrevert", describeRoute({ description: "Restore all reverted messages", + operationId: "session.unrevert", responses: { 200: { description: "Updated session", @@ -533,6 +549,7 @@ export namespace Server { "/config/providers", describeRoute({ description: "List all providers", + operationId: "config.providers", responses: { 200: { description: "List of providers", @@ -561,6 +578,7 @@ export namespace Server { "/find", describeRoute({ description: "Find text in files", + operationId: "find.text", responses: { 200: { description: "Matches", @@ -593,6 +611,7 @@ export namespace Server { "/find/file", describeRoute({ description: "Find files", + operationId: "find.files", responses: { 200: { description: "File paths", @@ -625,6 +644,7 @@ export namespace Server { "/find/symbol", describeRoute({ description: "Find workspace symbols", + operationId: "find.symbols", responses: { 200: { description: "Symbols", @@ -652,6 +672,7 @@ export namespace Server { "/file", describeRoute({ description: "Read a file", + operationId: "file.read", responses: { 200: { description: "File content", @@ -688,6 +709,7 @@ export namespace Server { "/file/status", describeRoute({ description: "Get file status", + operationId: "file.status", responses: { 200: { description: "File status", @@ -708,6 +730,7 @@ export namespace Server { "/log", describeRoute({ description: "Write a log entry to the server logs", + operationId: "app.log", responses: { 200: { description: "Log entry written successfully", @@ -757,6 +780,7 @@ export namespace Server { "/mode", describeRoute({ description: "List all modes", + operationId: "app.modes", responses: { 200: { description: "List of modes", @@ -777,6 +801,7 @@ export namespace Server { "/tui/append-prompt", describeRoute({ description: "Append prompt to the TUI", + operationId: "tui.appendPrompt", responses: { 200: { description: "Prompt processed successfully", @@ -800,6 +825,7 @@ export namespace Server { "/tui/open-help", describeRoute({ description: "Open the help dialog", + operationId: "tui.openHelp", responses: { 200: { description: "Help dialog opened successfully", diff --git a/packages/sdk/.prettierignore b/packages/sdk/.prettierignore deleted file mode 100644 index 3548c5af9..000000000 --- a/packages/sdk/.prettierignore +++ /dev/null @@ -1,7 +0,0 @@ -CHANGELOG.md -/ecosystem-tests/*/** -/node_modules -/deno - -# don't format tsc output, will break source maps -/dist diff --git a/packages/sdk/.prettierrc.json b/packages/sdk/.prettierrc.json deleted file mode 100644 index af75adaf6..000000000 --- a/packages/sdk/.prettierrc.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "arrowParens": "always", - "experimentalTernaries": true, - "printWidth": 110, - "singleQuote": true, - "trailingComma": "all" -} diff --git a/packages/sdk/.release-please-manifest.json b/packages/sdk/.release-please-manifest.json deleted file mode 100644 index de4ea38f0..000000000 --- a/packages/sdk/.release-please-manifest.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - ".": "0.1.0-alpha.20" -} diff --git a/packages/sdk/.stats.yml b/packages/sdk/.stats.yml deleted file mode 100644 index 3f719fabf..000000000 --- a/packages/sdk/.stats.yml +++ /dev/null @@ -1,4 +0,0 @@ -configured_endpoints: 26 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-62d8fccba4eb8dc3a80434e0849eab3352e49fb96a718bb7b6d17ed8e582b716.yml -openapi_spec_hash: 4ff9376cf9634e91731e63fe482ea532 -config_hash: 1ae82c93499b9f0b9ba828b8919f9cb3 diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json new file mode 100644 index 000000000..ad259caf0 --- /dev/null +++ b/packages/sdk/js/package.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/package.json", + "name": "@opencode-ai/sdk", + "version": "0.0.0", + "files": [ + "dist" + ] +} diff --git a/packages/sdk/js/script/generate.ts b/packages/sdk/js/script/generate.ts new file mode 100755 index 000000000..9249ded9f --- /dev/null +++ b/packages/sdk/js/script/generate.ts @@ -0,0 +1,36 @@ +#!/usr/bin/env bun + +import { $ } from "bun" +import fs from "fs/promises" +import path from "path" + +console.log("=== Generating SDKs ===") +console.log() + +import { createClient, defaultPlugins } from "@hey-api/openapi-ts" + +const dir = new URL("..", import.meta.url).pathname +await fs.rmdir(path.join(dir, "src/gen"), { recursive: true }) +await $`bun run ../../opencode/src/index.ts generate > openapi.json`.cwd(dir) + +await createClient({ + input: "./openapi.json", + output: "./src/gen", + plugins: [ + { + name: "@hey-api/typescript", + exportFromIndex: false, + }, + { + name: "@hey-api/sdk", + asClass: true, + exportFromIndex: false, + auth: false, + }, + { + name: "@hey-api/client-fetch", + exportFromIndex: false, + baseUrl: "http://localhost:4096", + }, + ], +}) diff --git a/packages/sdk/js/src/gen/client.gen.ts b/packages/sdk/js/src/gen/client.gen.ts new file mode 100644 index 000000000..3bb22b24a --- /dev/null +++ b/packages/sdk/js/src/gen/client.gen.ts @@ -0,0 +1,18 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { ClientOptions } from './types.gen'; +import { type Config, type ClientOptions as DefaultClientOptions, createClient, createConfig } from './client'; + +/** + * The `createClientConfig()` function will be called on client initialization + * and the returned object will become the client's initial configuration. + * + * You may want to initialize your client this way instead of calling + * `setConfig()`. This is useful for example if you're using Next.js + * to ensure your client always has the correct values. + */ +export type CreateClientConfig = (override?: Config) => Config & T>; + +export const client = createClient(createConfig({ + baseUrl: 'http://localhost:4096' +})); \ No newline at end of file diff --git a/packages/sdk/js/src/gen/client/client.ts b/packages/sdk/js/src/gen/client/client.ts new file mode 100644 index 000000000..89d1e3158 --- /dev/null +++ b/packages/sdk/js/src/gen/client/client.ts @@ -0,0 +1,195 @@ +import type { Client, Config, RequestOptions } from './types'; +import { + buildUrl, + createConfig, + createInterceptors, + getParseAs, + mergeConfigs, + mergeHeaders, + setAuthParams, +} from './utils'; + +type ReqInit = Omit & { + body?: any; + headers: ReturnType; +}; + +export const createClient = (config: Config = {}): Client => { + let _config = mergeConfigs(createConfig(), config); + + const getConfig = (): Config => ({ ..._config }); + + const setConfig = (config: Config): Config => { + _config = mergeConfigs(_config, config); + return getConfig(); + }; + + const interceptors = createInterceptors< + Request, + Response, + unknown, + RequestOptions + >(); + + const request: Client['request'] = async (options) => { + const opts = { + ..._config, + ...options, + fetch: options.fetch ?? _config.fetch ?? globalThis.fetch, + headers: mergeHeaders(_config.headers, options.headers), + }; + + if (opts.security) { + await setAuthParams({ + ...opts, + security: opts.security, + }); + } + + if (opts.requestValidator) { + await opts.requestValidator(opts); + } + + if (opts.body && opts.bodySerializer) { + opts.body = opts.bodySerializer(opts.body); + } + + // remove Content-Type header if body is empty to avoid sending invalid requests + if (opts.body === undefined || opts.body === '') { + opts.headers.delete('Content-Type'); + } + + const url = buildUrl(opts); + const requestInit: ReqInit = { + redirect: 'follow', + ...opts, + }; + + let request = new Request(url, requestInit); + + for (const fn of interceptors.request._fns) { + if (fn) { + request = await fn(request, opts); + } + } + + // fetch must be assigned here, otherwise it would throw the error: + // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation + const _fetch = opts.fetch!; + let response = await _fetch(request); + + for (const fn of interceptors.response._fns) { + if (fn) { + response = await fn(response, request, opts); + } + } + + const result = { + request, + response, + }; + + if (response.ok) { + if ( + response.status === 204 || + response.headers.get('Content-Length') === '0' + ) { + return opts.responseStyle === 'data' + ? {} + : { + data: {}, + ...result, + }; + } + + const parseAs = + (opts.parseAs === 'auto' + ? getParseAs(response.headers.get('Content-Type')) + : opts.parseAs) ?? 'json'; + + let data: any; + switch (parseAs) { + case 'arrayBuffer': + case 'blob': + case 'formData': + case 'json': + case 'text': + data = await response[parseAs](); + break; + case 'stream': + return opts.responseStyle === 'data' + ? response.body + : { + data: response.body, + ...result, + }; + } + + if (parseAs === 'json') { + if (opts.responseValidator) { + await opts.responseValidator(data); + } + + if (opts.responseTransformer) { + data = await opts.responseTransformer(data); + } + } + + return opts.responseStyle === 'data' + ? data + : { + data, + ...result, + }; + } + + const textError = await response.text(); + let jsonError: unknown; + + try { + jsonError = JSON.parse(textError); + } catch { + // noop + } + + const error = jsonError ?? textError; + let finalError = error; + + for (const fn of interceptors.error._fns) { + if (fn) { + finalError = (await fn(error, response, request, opts)) as string; + } + } + + finalError = finalError || ({} as string); + + if (opts.throwOnError) { + throw finalError; + } + + // TODO: we probably want to return error and improve types + return opts.responseStyle === 'data' + ? undefined + : { + error: finalError, + ...result, + }; + }; + + return { + buildUrl, + connect: (options) => request({ ...options, method: 'CONNECT' }), + delete: (options) => request({ ...options, method: 'DELETE' }), + get: (options) => request({ ...options, method: 'GET' }), + getConfig, + head: (options) => request({ ...options, method: 'HEAD' }), + interceptors, + options: (options) => request({ ...options, method: 'OPTIONS' }), + patch: (options) => request({ ...options, method: 'PATCH' }), + post: (options) => request({ ...options, method: 'POST' }), + put: (options) => request({ ...options, method: 'PUT' }), + request, + setConfig, + trace: (options) => request({ ...options, method: 'TRACE' }), + }; +}; diff --git a/packages/sdk/js/src/gen/client/index.ts b/packages/sdk/js/src/gen/client/index.ts new file mode 100644 index 000000000..5da1f7aee --- /dev/null +++ b/packages/sdk/js/src/gen/client/index.ts @@ -0,0 +1,22 @@ +export type { Auth } from '../core/auth'; +export type { QuerySerializerOptions } from '../core/bodySerializer'; +export { + formDataBodySerializer, + jsonBodySerializer, + urlSearchParamsBodySerializer, +} from '../core/bodySerializer'; +export { buildClientParams } from '../core/params'; +export { createClient } from './client'; +export type { + Client, + ClientOptions, + Config, + CreateClientConfig, + Options, + OptionsLegacyParser, + RequestOptions, + RequestResult, + ResponseStyle, + TDataShape, +} from './types'; +export { createConfig, mergeHeaders } from './utils'; diff --git a/packages/sdk/js/src/gen/client/types.ts b/packages/sdk/js/src/gen/client/types.ts new file mode 100644 index 000000000..85295df07 --- /dev/null +++ b/packages/sdk/js/src/gen/client/types.ts @@ -0,0 +1,222 @@ +import type { Auth } from '../core/auth'; +import type { + Client as CoreClient, + Config as CoreConfig, +} from '../core/types'; +import type { Middleware } from './utils'; + +export type ResponseStyle = 'data' | 'fields'; + +export interface Config + extends Omit, + CoreConfig { + /** + * Base URL for all requests made by this client. + */ + baseUrl?: T['baseUrl']; + /** + * Fetch API implementation. You can use this option to provide a custom + * fetch instance. + * + * @default globalThis.fetch + */ + fetch?: (request: Request) => ReturnType; + /** + * Please don't use the Fetch client for Next.js applications. The `next` + * options won't have any effect. + * + * Install {@link https://www.npmjs.com/package/@hey-api/client-next `@hey-api/client-next`} instead. + */ + next?: never; + /** + * Return the response data parsed in a specified format. By default, `auto` + * will infer the appropriate method from the `Content-Type` response header. + * You can override this behavior with any of the {@link Body} methods. + * Select `stream` if you don't want to parse response data at all. + * + * @default 'auto' + */ + parseAs?: + | 'arrayBuffer' + | 'auto' + | 'blob' + | 'formData' + | 'json' + | 'stream' + | 'text'; + /** + * Should we return only data or multiple fields (data, error, response, etc.)? + * + * @default 'fields' + */ + responseStyle?: ResponseStyle; + /** + * Throw an error instead of returning it in the response? + * + * @default false + */ + throwOnError?: T['throwOnError']; +} + +export interface RequestOptions< + TResponseStyle extends ResponseStyle = 'fields', + ThrowOnError extends boolean = boolean, + Url extends string = string, +> extends Config<{ + responseStyle: TResponseStyle; + throwOnError: ThrowOnError; + }> { + /** + * Any body that you want to add to your request. + * + * {@link https://developer.mozilla.org/docs/Web/API/fetch#body} + */ + body?: unknown; + path?: Record; + query?: Record; + /** + * Security mechanism(s) to use for the request. + */ + security?: ReadonlyArray; + url: Url; +} + +export type RequestResult< + TData = unknown, + TError = unknown, + ThrowOnError extends boolean = boolean, + TResponseStyle extends ResponseStyle = 'fields', +> = ThrowOnError extends true + ? Promise< + TResponseStyle extends 'data' + ? TData extends Record + ? TData[keyof TData] + : TData + : { + data: TData extends Record + ? TData[keyof TData] + : TData; + request: Request; + response: Response; + } + > + : Promise< + TResponseStyle extends 'data' + ? + | (TData extends Record + ? TData[keyof TData] + : TData) + | undefined + : ( + | { + data: TData extends Record + ? TData[keyof TData] + : TData; + error: undefined; + } + | { + data: undefined; + error: TError extends Record + ? TError[keyof TError] + : TError; + } + ) & { + request: Request; + response: Response; + } + >; + +export interface ClientOptions { + baseUrl?: string; + responseStyle?: ResponseStyle; + throwOnError?: boolean; +} + +type MethodFn = < + TData = unknown, + TError = unknown, + ThrowOnError extends boolean = false, + TResponseStyle extends ResponseStyle = 'fields', +>( + options: Omit, 'method'>, +) => RequestResult; + +type RequestFn = < + TData = unknown, + TError = unknown, + ThrowOnError extends boolean = false, + TResponseStyle extends ResponseStyle = 'fields', +>( + options: Omit, 'method'> & + Pick>, 'method'>, +) => RequestResult; + +type BuildUrlFn = < + TData extends { + body?: unknown; + path?: Record; + query?: Record; + url: string; + }, +>( + options: Pick & Options, +) => string; + +export type Client = CoreClient & { + interceptors: Middleware; +}; + +/** + * The `createClientConfig()` function will be called on client initialization + * and the returned object will become the client's initial configuration. + * + * You may want to initialize your client this way instead of calling + * `setConfig()`. This is useful for example if you're using Next.js + * to ensure your client always has the correct values. + */ +export type CreateClientConfig = ( + override?: Config, +) => Config & T>; + +export interface TDataShape { + body?: unknown; + headers?: unknown; + path?: unknown; + query?: unknown; + url: string; +} + +type OmitKeys = Pick>; + +export type Options< + TData extends TDataShape = TDataShape, + ThrowOnError extends boolean = boolean, + TResponseStyle extends ResponseStyle = 'fields', +> = OmitKeys< + RequestOptions, + 'body' | 'path' | 'query' | 'url' +> & + Omit; + +export type OptionsLegacyParser< + TData = unknown, + ThrowOnError extends boolean = boolean, + TResponseStyle extends ResponseStyle = 'fields', +> = TData extends { body?: any } + ? TData extends { headers?: any } + ? OmitKeys< + RequestOptions, + 'body' | 'headers' | 'url' + > & + TData + : OmitKeys, 'body' | 'url'> & + TData & + Pick, 'headers'> + : TData extends { headers?: any } + ? OmitKeys< + RequestOptions, + 'headers' | 'url' + > & + TData & + Pick, 'body'> + : OmitKeys, 'url'> & TData; diff --git a/packages/sdk/js/src/gen/client/utils.ts b/packages/sdk/js/src/gen/client/utils.ts new file mode 100644 index 000000000..a52e67292 --- /dev/null +++ b/packages/sdk/js/src/gen/client/utils.ts @@ -0,0 +1,417 @@ +import { getAuthToken } from '../core/auth'; +import type { + QuerySerializer, + QuerySerializerOptions, +} from '../core/bodySerializer'; +import { jsonBodySerializer } from '../core/bodySerializer'; +import { + serializeArrayParam, + serializeObjectParam, + serializePrimitiveParam, +} from '../core/pathSerializer'; +import type { Client, ClientOptions, Config, RequestOptions } from './types'; + +interface PathSerializer { + path: Record; + url: string; +} + +const PATH_PARAM_RE = /\{[^{}]+\}/g; + +type ArrayStyle = 'form' | 'spaceDelimited' | 'pipeDelimited'; +type MatrixStyle = 'label' | 'matrix' | 'simple'; +type ArraySeparatorStyle = ArrayStyle | MatrixStyle; + +const defaultPathSerializer = ({ path, url: _url }: PathSerializer) => { + let url = _url; + const matches = _url.match(PATH_PARAM_RE); + if (matches) { + for (const match of matches) { + let explode = false; + let name = match.substring(1, match.length - 1); + let style: ArraySeparatorStyle = 'simple'; + + if (name.endsWith('*')) { + explode = true; + name = name.substring(0, name.length - 1); + } + + if (name.startsWith('.')) { + name = name.substring(1); + style = 'label'; + } else if (name.startsWith(';')) { + name = name.substring(1); + style = 'matrix'; + } + + const value = path[name]; + + if (value === undefined || value === null) { + continue; + } + + if (Array.isArray(value)) { + url = url.replace( + match, + serializeArrayParam({ explode, name, style, value }), + ); + continue; + } + + if (typeof value === 'object') { + url = url.replace( + match, + serializeObjectParam({ + explode, + name, + style, + value: value as Record, + valueOnly: true, + }), + ); + continue; + } + + if (style === 'matrix') { + url = url.replace( + match, + `;${serializePrimitiveParam({ + name, + value: value as string, + })}`, + ); + continue; + } + + const replaceValue = encodeURIComponent( + style === 'label' ? `.${value as string}` : (value as string), + ); + url = url.replace(match, replaceValue); + } + } + return url; +}; + +export const createQuerySerializer = ({ + allowReserved, + array, + object, +}: QuerySerializerOptions = {}) => { + const querySerializer = (queryParams: T) => { + const search: string[] = []; + if (queryParams && typeof queryParams === 'object') { + for (const name in queryParams) { + const value = queryParams[name]; + + if (value === undefined || value === null) { + continue; + } + + if (Array.isArray(value)) { + const serializedArray = serializeArrayParam({ + allowReserved, + explode: true, + name, + style: 'form', + value, + ...array, + }); + if (serializedArray) search.push(serializedArray); + } else if (typeof value === 'object') { + const serializedObject = serializeObjectParam({ + allowReserved, + explode: true, + name, + style: 'deepObject', + value: value as Record, + ...object, + }); + if (serializedObject) search.push(serializedObject); + } else { + const serializedPrimitive = serializePrimitiveParam({ + allowReserved, + name, + value: value as string, + }); + if (serializedPrimitive) search.push(serializedPrimitive); + } + } + } + return search.join('&'); + }; + return querySerializer; +}; + +/** + * Infers parseAs value from provided Content-Type header. + */ +export const getParseAs = ( + contentType: string | null, +): Exclude => { + if (!contentType) { + // If no Content-Type header is provided, the best we can do is return the raw response body, + // which is effectively the same as the 'stream' option. + return 'stream'; + } + + const cleanContent = contentType.split(';')[0]?.trim(); + + if (!cleanContent) { + return; + } + + if ( + cleanContent.startsWith('application/json') || + cleanContent.endsWith('+json') + ) { + return 'json'; + } + + if (cleanContent === 'multipart/form-data') { + return 'formData'; + } + + if ( + ['application/', 'audio/', 'image/', 'video/'].some((type) => + cleanContent.startsWith(type), + ) + ) { + return 'blob'; + } + + if (cleanContent.startsWith('text/')) { + return 'text'; + } + + return; +}; + +export const setAuthParams = async ({ + security, + ...options +}: Pick, 'security'> & + Pick & { + headers: Headers; + }) => { + for (const auth of security) { + const token = await getAuthToken(auth, options.auth); + + if (!token) { + continue; + } + + const name = auth.name ?? 'Authorization'; + + switch (auth.in) { + case 'query': + if (!options.query) { + options.query = {}; + } + options.query[name] = token; + break; + case 'cookie': + options.headers.append('Cookie', `${name}=${token}`); + break; + case 'header': + default: + options.headers.set(name, token); + break; + } + + return; + } +}; + +export const buildUrl: Client['buildUrl'] = (options) => { + const url = getUrl({ + baseUrl: options.baseUrl as string, + path: options.path, + query: options.query, + querySerializer: + typeof options.querySerializer === 'function' + ? options.querySerializer + : createQuerySerializer(options.querySerializer), + url: options.url, + }); + return url; +}; + +export const getUrl = ({ + baseUrl, + path, + query, + querySerializer, + url: _url, +}: { + baseUrl?: string; + path?: Record; + query?: Record; + querySerializer: QuerySerializer; + url: string; +}) => { + const pathUrl = _url.startsWith('/') ? _url : `/${_url}`; + let url = (baseUrl ?? '') + pathUrl; + if (path) { + url = defaultPathSerializer({ path, url }); + } + let search = query ? querySerializer(query) : ''; + if (search.startsWith('?')) { + search = search.substring(1); + } + if (search) { + url += `?${search}`; + } + return url; +}; + +export const mergeConfigs = (a: Config, b: Config): Config => { + const config = { ...a, ...b }; + if (config.baseUrl?.endsWith('/')) { + config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1); + } + config.headers = mergeHeaders(a.headers, b.headers); + return config; +}; + +export const mergeHeaders = ( + ...headers: Array['headers'] | undefined> +): Headers => { + const mergedHeaders = new Headers(); + for (const header of headers) { + if (!header || typeof header !== 'object') { + continue; + } + + const iterator = + header instanceof Headers ? header.entries() : Object.entries(header); + + for (const [key, value] of iterator) { + if (value === null) { + mergedHeaders.delete(key); + } else if (Array.isArray(value)) { + for (const v of value) { + mergedHeaders.append(key, v as string); + } + } else if (value !== undefined) { + // assume object headers are meant to be JSON stringified, i.e. their + // content value in OpenAPI specification is 'application/json' + mergedHeaders.set( + key, + typeof value === 'object' ? JSON.stringify(value) : (value as string), + ); + } + } + } + return mergedHeaders; +}; + +type ErrInterceptor = ( + error: Err, + response: Res, + request: Req, + options: Options, +) => Err | Promise; + +type ReqInterceptor = ( + request: Req, + options: Options, +) => Req | Promise; + +type ResInterceptor = ( + response: Res, + request: Req, + options: Options, +) => Res | Promise; + +class Interceptors { + _fns: (Interceptor | null)[]; + + constructor() { + this._fns = []; + } + + clear() { + this._fns = []; + } + + getInterceptorIndex(id: number | Interceptor): number { + if (typeof id === 'number') { + return this._fns[id] ? id : -1; + } else { + return this._fns.indexOf(id); + } + } + exists(id: number | Interceptor) { + const index = this.getInterceptorIndex(id); + return !!this._fns[index]; + } + + eject(id: number | Interceptor) { + const index = this.getInterceptorIndex(id); + if (this._fns[index]) { + this._fns[index] = null; + } + } + + update(id: number | Interceptor, fn: Interceptor) { + const index = this.getInterceptorIndex(id); + if (this._fns[index]) { + this._fns[index] = fn; + return id; + } else { + return false; + } + } + + use(fn: Interceptor) { + this._fns = [...this._fns, fn]; + return this._fns.length - 1; + } +} + +// `createInterceptors()` response, meant for external use as it does not +// expose internals +export interface Middleware { + error: Pick< + Interceptors>, + 'eject' | 'use' + >; + request: Pick>, 'eject' | 'use'>; + response: Pick< + Interceptors>, + 'eject' | 'use' + >; +} + +// do not add `Middleware` as return type so we can use _fns internally +export const createInterceptors = () => ({ + error: new Interceptors>(), + request: new Interceptors>(), + response: new Interceptors>(), +}); + +const defaultQuerySerializer = createQuerySerializer({ + allowReserved: false, + array: { + explode: true, + style: 'form', + }, + object: { + explode: true, + style: 'deepObject', + }, +}); + +const defaultHeaders = { + 'Content-Type': 'application/json', +}; + +export const createConfig = ( + override: Config & T> = {}, +): Config & T> => ({ + ...jsonBodySerializer, + headers: defaultHeaders, + parseAs: 'auto', + querySerializer: defaultQuerySerializer, + ...override, +}); diff --git a/packages/sdk/js/src/gen/core/auth.ts b/packages/sdk/js/src/gen/core/auth.ts new file mode 100644 index 000000000..451c7f30f --- /dev/null +++ b/packages/sdk/js/src/gen/core/auth.ts @@ -0,0 +1,40 @@ +export type AuthToken = string | undefined; + +export interface Auth { + /** + * Which part of the request do we use to send the auth? + * + * @default 'header' + */ + in?: 'header' | 'query' | 'cookie'; + /** + * Header or query parameter name. + * + * @default 'Authorization' + */ + name?: string; + scheme?: 'basic' | 'bearer'; + type: 'apiKey' | 'http'; +} + +export const getAuthToken = async ( + auth: Auth, + callback: ((auth: Auth) => Promise | AuthToken) | AuthToken, +): Promise => { + const token = + typeof callback === 'function' ? await callback(auth) : callback; + + if (!token) { + return; + } + + if (auth.scheme === 'bearer') { + return `Bearer ${token}`; + } + + if (auth.scheme === 'basic') { + return `Basic ${btoa(token)}`; + } + + return token; +}; diff --git a/packages/sdk/js/src/gen/core/bodySerializer.ts b/packages/sdk/js/src/gen/core/bodySerializer.ts new file mode 100644 index 000000000..98ce7791f --- /dev/null +++ b/packages/sdk/js/src/gen/core/bodySerializer.ts @@ -0,0 +1,88 @@ +import type { + ArrayStyle, + ObjectStyle, + SerializerOptions, +} from './pathSerializer'; + +export type QuerySerializer = (query: Record) => string; + +export type BodySerializer = (body: any) => any; + +export interface QuerySerializerOptions { + allowReserved?: boolean; + array?: SerializerOptions; + object?: SerializerOptions; +} + +const serializeFormDataPair = ( + data: FormData, + key: string, + value: unknown, +): void => { + if (typeof value === 'string' || value instanceof Blob) { + data.append(key, value); + } else { + data.append(key, JSON.stringify(value)); + } +}; + +const serializeUrlSearchParamsPair = ( + data: URLSearchParams, + key: string, + value: unknown, +): void => { + if (typeof value === 'string') { + data.append(key, value); + } else { + data.append(key, JSON.stringify(value)); + } +}; + +export const formDataBodySerializer = { + bodySerializer: | Array>>( + body: T, + ): FormData => { + const data = new FormData(); + + Object.entries(body).forEach(([key, value]) => { + if (value === undefined || value === null) { + return; + } + if (Array.isArray(value)) { + value.forEach((v) => serializeFormDataPair(data, key, v)); + } else { + serializeFormDataPair(data, key, value); + } + }); + + return data; + }, +}; + +export const jsonBodySerializer = { + bodySerializer: (body: T): string => + JSON.stringify(body, (_key, value) => + typeof value === 'bigint' ? value.toString() : value, + ), +}; + +export const urlSearchParamsBodySerializer = { + bodySerializer: | Array>>( + body: T, + ): string => { + const data = new URLSearchParams(); + + Object.entries(body).forEach(([key, value]) => { + if (value === undefined || value === null) { + return; + } + if (Array.isArray(value)) { + value.forEach((v) => serializeUrlSearchParamsPair(data, key, v)); + } else { + serializeUrlSearchParamsPair(data, key, value); + } + }); + + return data.toString(); + }, +}; diff --git a/packages/sdk/js/src/gen/core/params.ts b/packages/sdk/js/src/gen/core/params.ts new file mode 100644 index 000000000..ba35263d8 --- /dev/null +++ b/packages/sdk/js/src/gen/core/params.ts @@ -0,0 +1,151 @@ +type Slot = 'body' | 'headers' | 'path' | 'query'; + +export type Field = + | { + in: Exclude; + /** + * Field name. This is the name we want the user to see and use. + */ + key: string; + /** + * Field mapped name. This is the name we want to use in the request. + * If omitted, we use the same value as `key`. + */ + map?: string; + } + | { + in: Extract; + /** + * Key isn't required for bodies. + */ + key?: string; + map?: string; + }; + +export interface Fields { + allowExtra?: Partial>; + args?: ReadonlyArray; +} + +export type FieldsConfig = ReadonlyArray; + +const extraPrefixesMap: Record = { + $body_: 'body', + $headers_: 'headers', + $path_: 'path', + $query_: 'query', +}; +const extraPrefixes = Object.entries(extraPrefixesMap); + +type KeyMap = Map< + string, + { + in: Slot; + map?: string; + } +>; + +const buildKeyMap = (fields: FieldsConfig, map?: KeyMap): KeyMap => { + if (!map) { + map = new Map(); + } + + for (const config of fields) { + if ('in' in config) { + if (config.key) { + map.set(config.key, { + in: config.in, + map: config.map, + }); + } + } else if (config.args) { + buildKeyMap(config.args, map); + } + } + + return map; +}; + +interface Params { + body: unknown; + headers: Record; + path: Record; + query: Record; +} + +const stripEmptySlots = (params: Params) => { + for (const [slot, value] of Object.entries(params)) { + if (value && typeof value === 'object' && !Object.keys(value).length) { + delete params[slot as Slot]; + } + } +}; + +export const buildClientParams = ( + args: ReadonlyArray, + fields: FieldsConfig, +) => { + const params: Params = { + body: {}, + headers: {}, + path: {}, + query: {}, + }; + + const map = buildKeyMap(fields); + + let config: FieldsConfig[number] | undefined; + + for (const [index, arg] of args.entries()) { + if (fields[index]) { + config = fields[index]; + } + + if (!config) { + continue; + } + + if ('in' in config) { + if (config.key) { + const field = map.get(config.key)!; + const name = field.map || config.key; + (params[field.in] as Record)[name] = arg; + } else { + params.body = arg; + } + } else { + for (const [key, value] of Object.entries(arg ?? {})) { + const field = map.get(key); + + if (field) { + const name = field.map || key; + (params[field.in] as Record)[name] = value; + } else { + const extra = extraPrefixes.find(([prefix]) => + key.startsWith(prefix), + ); + + if (extra) { + const [prefix, slot] = extra; + (params[slot] as Record)[ + key.slice(prefix.length) + ] = value; + } else { + for (const [slot, allowed] of Object.entries( + config.allowExtra ?? {}, + )) { + if (allowed) { + (params[slot as Slot] as Record)[key] = value; + break; + } + } + } + } + } + } + } + + stripEmptySlots(params); + + return params; +}; diff --git a/packages/sdk/js/src/gen/core/pathSerializer.ts b/packages/sdk/js/src/gen/core/pathSerializer.ts new file mode 100644 index 000000000..d692cf0a3 --- /dev/null +++ b/packages/sdk/js/src/gen/core/pathSerializer.ts @@ -0,0 +1,179 @@ +interface SerializeOptions + extends SerializePrimitiveOptions, + SerializerOptions {} + +interface SerializePrimitiveOptions { + allowReserved?: boolean; + name: string; +} + +export interface SerializerOptions { + /** + * @default true + */ + explode: boolean; + style: T; +} + +export type ArrayStyle = 'form' | 'spaceDelimited' | 'pipeDelimited'; +export type ArraySeparatorStyle = ArrayStyle | MatrixStyle; +type MatrixStyle = 'label' | 'matrix' | 'simple'; +export type ObjectStyle = 'form' | 'deepObject'; +type ObjectSeparatorStyle = ObjectStyle | MatrixStyle; + +interface SerializePrimitiveParam extends SerializePrimitiveOptions { + value: string; +} + +export const separatorArrayExplode = (style: ArraySeparatorStyle) => { + switch (style) { + case 'label': + return '.'; + case 'matrix': + return ';'; + case 'simple': + return ','; + default: + return '&'; + } +}; + +export const separatorArrayNoExplode = (style: ArraySeparatorStyle) => { + switch (style) { + case 'form': + return ','; + case 'pipeDelimited': + return '|'; + case 'spaceDelimited': + return '%20'; + default: + return ','; + } +}; + +export const separatorObjectExplode = (style: ObjectSeparatorStyle) => { + switch (style) { + case 'label': + return '.'; + case 'matrix': + return ';'; + case 'simple': + return ','; + default: + return '&'; + } +}; + +export const serializeArrayParam = ({ + allowReserved, + explode, + name, + style, + value, +}: SerializeOptions & { + value: unknown[]; +}) => { + if (!explode) { + const joinedValues = ( + allowReserved ? value : value.map((v) => encodeURIComponent(v as string)) + ).join(separatorArrayNoExplode(style)); + switch (style) { + case 'label': + return `.${joinedValues}`; + case 'matrix': + return `;${name}=${joinedValues}`; + case 'simple': + return joinedValues; + default: + return `${name}=${joinedValues}`; + } + } + + const separator = separatorArrayExplode(style); + const joinedValues = value + .map((v) => { + if (style === 'label' || style === 'simple') { + return allowReserved ? v : encodeURIComponent(v as string); + } + + return serializePrimitiveParam({ + allowReserved, + name, + value: v as string, + }); + }) + .join(separator); + return style === 'label' || style === 'matrix' + ? separator + joinedValues + : joinedValues; +}; + +export const serializePrimitiveParam = ({ + allowReserved, + name, + value, +}: SerializePrimitiveParam) => { + if (value === undefined || value === null) { + return ''; + } + + if (typeof value === 'object') { + throw new Error( + 'Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.', + ); + } + + return `${name}=${allowReserved ? value : encodeURIComponent(value)}`; +}; + +export const serializeObjectParam = ({ + allowReserved, + explode, + name, + style, + value, + valueOnly, +}: SerializeOptions & { + value: Record | Date; + valueOnly?: boolean; +}) => { + if (value instanceof Date) { + return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`; + } + + if (style !== 'deepObject' && !explode) { + let values: string[] = []; + Object.entries(value).forEach(([key, v]) => { + values = [ + ...values, + key, + allowReserved ? (v as string) : encodeURIComponent(v as string), + ]; + }); + const joinedValues = values.join(','); + switch (style) { + case 'form': + return `${name}=${joinedValues}`; + case 'label': + return `.${joinedValues}`; + case 'matrix': + return `;${name}=${joinedValues}`; + default: + return joinedValues; + } + } + + const separator = separatorObjectExplode(style); + const joinedValues = Object.entries(value) + .map(([key, v]) => + serializePrimitiveParam({ + allowReserved, + name: style === 'deepObject' ? `${name}[${key}]` : key, + value: v as string, + }), + ) + .join(separator); + return style === 'label' || style === 'matrix' + ? separator + joinedValues + : joinedValues; +}; diff --git a/packages/sdk/js/src/gen/core/types.ts b/packages/sdk/js/src/gen/core/types.ts new file mode 100644 index 000000000..2dd4106fb --- /dev/null +++ b/packages/sdk/js/src/gen/core/types.ts @@ -0,0 +1,118 @@ +import type { Auth, AuthToken } from './auth'; +import type { + BodySerializer, + QuerySerializer, + QuerySerializerOptions, +} from './bodySerializer'; + +export interface Client< + RequestFn = never, + Config = unknown, + MethodFn = never, + BuildUrlFn = never, +> { + /** + * Returns the final request URL. + */ + buildUrl: BuildUrlFn; + connect: MethodFn; + delete: MethodFn; + get: MethodFn; + getConfig: () => Config; + head: MethodFn; + options: MethodFn; + patch: MethodFn; + post: MethodFn; + put: MethodFn; + request: RequestFn; + setConfig: (config: Config) => Config; + trace: MethodFn; +} + +export interface Config { + /** + * Auth token or a function returning auth token. The resolved value will be + * added to the request payload as defined by its `security` array. + */ + auth?: ((auth: Auth) => Promise | AuthToken) | AuthToken; + /** + * A function for serializing request body parameter. By default, + * {@link JSON.stringify()} will be used. + */ + bodySerializer?: BodySerializer | null; + /** + * An object containing any HTTP headers that you want to pre-populate your + * `Headers` object with. + * + * {@link https://developer.mozilla.org/docs/Web/API/Headers/Headers#init See more} + */ + headers?: + | RequestInit['headers'] + | Record< + string, + | string + | number + | boolean + | (string | number | boolean)[] + | null + | undefined + | unknown + >; + /** + * The request method. + * + * {@link https://developer.mozilla.org/docs/Web/API/fetch#method See more} + */ + method?: + | 'CONNECT' + | 'DELETE' + | 'GET' + | 'HEAD' + | 'OPTIONS' + | 'PATCH' + | 'POST' + | 'PUT' + | 'TRACE'; + /** + * A function for serializing request query parameters. By default, arrays + * will be exploded in form style, objects will be exploded in deepObject + * style, and reserved characters are percent-encoded. + * + * This method will have no effect if the native `paramsSerializer()` Axios + * API function is used. + * + * {@link https://swagger.io/docs/specification/serialization/#query View examples} + */ + querySerializer?: QuerySerializer | QuerySerializerOptions; + /** + * A function validating request data. This is useful if you want to ensure + * the request conforms to the desired shape, so it can be safely sent to + * the server. + */ + requestValidator?: (data: unknown) => Promise; + /** + * A function transforming response data before it's returned. This is useful + * for post-processing data, e.g. converting ISO strings into Date objects. + */ + responseTransformer?: (data: unknown) => Promise; + /** + * A function validating response data. This is useful if you want to ensure + * the response conforms to the desired shape, so it can be safely passed to + * the transformers and returned to the user. + */ + responseValidator?: (data: unknown) => Promise; +} + +type IsExactlyNeverOrNeverUndefined = [T] extends [never] + ? true + : [T] extends [never | undefined] + ? [undefined] extends [T] + ? false + : true + : false; + +export type OmitNever> = { + [K in keyof T as IsExactlyNeverOrNeverUndefined extends true + ? never + : K]: T[K]; +}; diff --git a/packages/sdk/js/src/gen/sdk.gen.ts b/packages/sdk/js/src/gen/sdk.gen.ts new file mode 100644 index 000000000..6df19467e --- /dev/null +++ b/packages/sdk/js/src/gen/sdk.gen.ts @@ -0,0 +1,327 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Options as ClientOptions, TDataShape, Client } from './client'; +import type { EventSubscribeData, EventSubscribeResponses, AppGetData, AppGetResponses, AppInitData, AppInitResponses, ConfigGetData, ConfigGetResponses, SessionListData, SessionListResponses, SessionCreateData, SessionCreateResponses, SessionCreateErrors, SessionDeleteData, SessionDeleteResponses, SessionInitData, SessionInitResponses, SessionAbortData, SessionAbortResponses, SessionUnshareData, SessionUnshareResponses, SessionShareData, SessionShareResponses, SessionSummarizeData, SessionSummarizeResponses, SessionMessagesData, SessionMessagesResponses, SessionChatData, SessionChatResponses, SessionRevertData, SessionRevertResponses, SessionUnrevertData, SessionUnrevertResponses, ConfigProvidersData, ConfigProvidersResponses, FindTextData, FindTextResponses, FindFilesData, FindFilesResponses, FindSymbolsData, FindSymbolsResponses, FileReadData, FileReadResponses, FileStatusData, FileStatusResponses, AppLogData, AppLogResponses, AppModesData, AppModesResponses, TuiAppendPromptData, TuiAppendPromptResponses, TuiOpenHelpData, TuiOpenHelpResponses } from './types.gen'; +import { client as _heyApiClient } from './client.gen'; + +export type Options = ClientOptions & { + /** + * You can provide a client instance returned by `createClient()` instead of + * individual options. This might be also useful if you want to implement a + * custom client. + */ + client?: Client; + /** + * You can pass arbitrary values through the `meta` object. This can be + * used to access values that aren't defined as part of the SDK function. + */ + meta?: Record; +}; + +class Event { + /** + * Get events + */ + public static subscribe(options?: Options) { + return (options?.client ?? _heyApiClient).get({ + url: '/event', + ...options + }); + } +} + +class App { + /** + * Get app info + */ + public static get(options?: Options) { + return (options?.client ?? _heyApiClient).get({ + url: '/app', + ...options + }); + } + + /** + * Initialize the app + */ + public static init(options?: Options) { + return (options?.client ?? _heyApiClient).post({ + url: '/app/init', + ...options + }); + } + + /** + * Write a log entry to the server logs + */ + public static log(options?: Options) { + return (options?.client ?? _heyApiClient).post({ + url: '/log', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options?.headers + } + }); + } + + /** + * List all modes + */ + public static modes(options?: Options) { + return (options?.client ?? _heyApiClient).get({ + url: '/mode', + ...options + }); + } +} + +class Config { + /** + * Get config info + */ + public static get(options?: Options) { + return (options?.client ?? _heyApiClient).get({ + url: '/config', + ...options + }); + } + + /** + * List all providers + */ + public static providers(options?: Options) { + return (options?.client ?? _heyApiClient).get({ + url: '/config/providers', + ...options + }); + } +} + +class Session { + /** + * List all sessions + */ + public static list(options?: Options) { + return (options?.client ?? _heyApiClient).get({ + url: '/session', + ...options + }); + } + + /** + * Create a new session + */ + public static create(options?: Options) { + return (options?.client ?? _heyApiClient).post({ + url: '/session', + ...options + }); + } + + /** + * Delete a session and all its data + */ + public static delete(options: Options) { + return (options.client ?? _heyApiClient).delete({ + url: '/session/{id}', + ...options + }); + } + + /** + * Analyze the app and create an AGENTS.md file + */ + public static init(options: Options) { + return (options.client ?? _heyApiClient).post({ + url: '/session/{id}/init', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } + }); + } + + /** + * Abort a session + */ + public static abort(options: Options) { + return (options.client ?? _heyApiClient).post({ + url: '/session/{id}/abort', + ...options + }); + } + + /** + * Unshare the session + */ + public static unshare(options: Options) { + return (options.client ?? _heyApiClient).delete({ + url: '/session/{id}/share', + ...options + }); + } + + /** + * Share a session + */ + public static share(options: Options) { + return (options.client ?? _heyApiClient).post({ + url: '/session/{id}/share', + ...options + }); + } + + /** + * Summarize the session + */ + public static summarize(options: Options) { + return (options.client ?? _heyApiClient).post({ + url: '/session/{id}/summarize', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } + }); + } + + /** + * List messages for a session + */ + public static messages(options: Options) { + return (options.client ?? _heyApiClient).get({ + url: '/session/{id}/message', + ...options + }); + } + + /** + * Create and send a new message to a session + */ + public static chat(options: Options) { + return (options.client ?? _heyApiClient).post({ + url: '/session/{id}/message', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } + }); + } + + /** + * Revert a message + */ + public static revert(options: Options) { + return (options.client ?? _heyApiClient).post({ + url: '/session/{id}/revert', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } + }); + } + + /** + * Restore all reverted messages + */ + public static unrevert(options: Options) { + return (options.client ?? _heyApiClient).post({ + url: '/session/{id}/unrevert', + ...options + }); + } +} + +class Find { + /** + * Find text in files + */ + public static text(options: Options) { + return (options.client ?? _heyApiClient).get({ + url: '/find', + ...options + }); + } + + /** + * Find files + */ + public static files(options: Options) { + return (options.client ?? _heyApiClient).get({ + url: '/find/file', + ...options + }); + } + + /** + * Find workspace symbols + */ + public static symbols(options: Options) { + return (options.client ?? _heyApiClient).get({ + url: '/find/symbol', + ...options + }); + } +} + +class File { + /** + * Read a file + */ + public static read(options: Options) { + return (options.client ?? _heyApiClient).get({ + url: '/file', + ...options + }); + } + + /** + * Get file status + */ + public static status(options?: Options) { + return (options?.client ?? _heyApiClient).get({ + url: '/file/status', + ...options + }); + } +} + +class Tui { + /** + * Append prompt to the TUI + */ + public static appendPrompt(options?: Options) { + return (options?.client ?? _heyApiClient).post({ + url: '/tui/append-prompt', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options?.headers + } + }); + } + + /** + * Open the help dialog + */ + public static openHelp(options?: Options) { + return (options?.client ?? _heyApiClient).post({ + url: '/tui/open-help', + ...options + }); + } +} + +export class Default { + static event = Event; + static app = App; + static config = Config; + static session = Session; + static find = Find; + static file = File; + static tui = Tui; +} \ No newline at end of file diff --git a/packages/sdk/js/src/gen/types.gen.ts b/packages/sdk/js/src/gen/types.gen.ts new file mode 100644 index 000000000..6fcd1c415 --- /dev/null +++ b/packages/sdk/js/src/gen/types.gen.ts @@ -0,0 +1,1450 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type Event = ({ + type: 'installation.updated'; +} & EventInstallationUpdated) | ({ + type: 'lsp.client.diagnostics'; +} & EventLspClientDiagnostics) | ({ + type: 'message.updated'; +} & EventMessageUpdated) | ({ + type: 'message.removed'; +} & EventMessageRemoved) | ({ + type: 'message.part.updated'; +} & EventMessagePartUpdated) | ({ + type: 'message.part.removed'; +} & EventMessagePartRemoved) | ({ + type: 'storage.write'; +} & EventStorageWrite) | ({ + type: 'permission.updated'; +} & EventPermissionUpdated) | ({ + type: 'file.edited'; +} & EventFileEdited) | ({ + type: 'session.updated'; +} & EventSessionUpdated) | ({ + type: 'session.deleted'; +} & EventSessionDeleted) | ({ + type: 'session.idle'; +} & EventSessionIdle) | ({ + type: 'session.error'; +} & EventSessionError) | ({ + type: 'server.connected'; +} & EventServerConnected) | ({ + type: 'file.watcher.updated'; +} & EventFileWatcherUpdated) | ({ + type: 'ide.installed'; +} & EventIdeInstalled); + +export type EventInstallationUpdated = { + type: string; + properties: { + version: string; + }; +}; + +export type EventLspClientDiagnostics = { + type: string; + properties: { + serverID: string; + path: string; + }; +}; + +export type EventMessageUpdated = { + type: string; + properties: { + info: Message; + }; +}; + +export type Message = ({ + role: 'user'; +} & UserMessage) | ({ + role: 'assistant'; +} & AssistantMessage); + +export type UserMessage = { + id: string; + sessionID: string; + role: string; + time: { + created: number; + }; +}; + +export type AssistantMessage = { + id: string; + sessionID: string; + role: string; + time: { + created: number; + completed?: number; + }; + error?: ({ + name: 'ProviderAuthError'; + } & ProviderAuthError) | ({ + name: 'UnknownError'; + } & UnknownError) | ({ + name: 'MessageOutputLengthError'; + } & MessageOutputLengthError) | ({ + name: 'MessageAbortedError'; + } & MessageAbortedError); + system: Array; + modelID: string; + providerID: string; + mode: string; + path: { + cwd: string; + root: string; + }; + summary?: boolean; + cost: number; + tokens: { + input: number; + output: number; + reasoning: number; + cache: { + read: number; + write: number; + }; + }; +}; + +export type ProviderAuthError = { + name: string; + data: { + providerID: string; + message: string; + }; +}; + +export type UnknownError = { + name: string; + data: { + message: string; + }; +}; + +export type MessageOutputLengthError = { + name: string; + data: { + [key: string]: unknown; + }; +}; + +export type MessageAbortedError = { + name: string; + data: { + [key: string]: unknown; + }; +}; + +export type EventMessageRemoved = { + type: string; + properties: { + sessionID: string; + messageID: string; + }; +}; + +export type EventMessagePartUpdated = { + type: string; + properties: { + part: Part; + }; +}; + +export type Part = ({ + type: 'text'; +} & TextPart) | ({ + type: 'file'; +} & FilePart) | ({ + type: 'tool'; +} & ToolPart) | ({ + type: 'step-start'; +} & StepStartPart) | ({ + type: 'step-finish'; +} & StepFinishPart) | ({ + type: 'snapshot'; +} & SnapshotPart) | ({ + type: 'patch'; +} & PatchPart); + +export type TextPart = { + id: string; + sessionID: string; + messageID: string; + type: string; + text: string; + synthetic?: boolean; + time?: { + start: number; + end?: number; + }; +}; + +export type FilePart = { + id: string; + sessionID: string; + messageID: string; + type: string; + mime: string; + filename?: string; + url: string; + source?: FilePartSource; +}; + +export type FilePartSource = ({ + type: 'file'; +} & FileSource) | ({ + type: 'symbol'; +} & SymbolSource); + +export type FileSource = { + text: FilePartSourceText; + type: string; + path: string; +}; + +export type FilePartSourceText = { + value: string; + start: number; + end: number; +}; + +export type SymbolSource = { + text: FilePartSourceText; + type: string; + path: string; + range: Range; + name: string; + kind: number; +}; + +export type Range = { + start: { + line: number; + character: number; + }; + end: { + line: number; + character: number; + }; +}; + +export type ToolPart = { + id: string; + sessionID: string; + messageID: string; + type: string; + callID: string; + tool: string; + state: ToolState; +}; + +export type ToolState = ({ + status: 'pending'; +} & ToolStatePending) | ({ + status: 'running'; +} & ToolStateRunning) | ({ + status: 'completed'; +} & ToolStateCompleted) | ({ + status: 'error'; +} & ToolStateError); + +export type ToolStatePending = { + status: string; +}; + +export type ToolStateRunning = { + status: string; + input?: unknown; + title?: string; + metadata?: { + [key: string]: unknown; + }; + time: { + start: number; + }; +}; + +export type ToolStateCompleted = { + status: string; + input: { + [key: string]: unknown; + }; + output: string; + title: string; + metadata: { + [key: string]: unknown; + }; + time: { + start: number; + end: number; + }; +}; + +export type ToolStateError = { + status: string; + input: { + [key: string]: unknown; + }; + error: string; + time: { + start: number; + end: number; + }; +}; + +export type StepStartPart = { + id: string; + sessionID: string; + messageID: string; + type: string; +}; + +export type StepFinishPart = { + id: string; + sessionID: string; + messageID: string; + type: string; + cost: number; + tokens: { + input: number; + output: number; + reasoning: number; + cache: { + read: number; + write: number; + }; + }; +}; + +export type SnapshotPart = { + id: string; + sessionID: string; + messageID: string; + type: string; + snapshot: string; +}; + +export type PatchPart = { + id: string; + sessionID: string; + messageID: string; + type: string; + hash: string; + files: Array; +}; + +export type EventMessagePartRemoved = { + type: string; + properties: { + sessionID: string; + messageID: string; + partID: string; + }; +}; + +export type EventStorageWrite = { + type: string; + properties: { + key: string; + content?: unknown; + }; +}; + +export type EventPermissionUpdated = { + type: string; + properties: PermissionInfo; +}; + +export type PermissionInfo = { + id: string; + sessionID: string; + title: string; + metadata: { + [key: string]: unknown; + }; + time: { + created: number; + }; +}; + +export type EventFileEdited = { + type: string; + properties: { + file: string; + }; +}; + +export type EventSessionUpdated = { + type: string; + properties: { + info: Session; + }; +}; + +export type Session = { + id: string; + parentID?: string; + share?: { + url: string; + }; + title: string; + version: string; + time: { + created: number; + updated: number; + }; + revert?: { + messageID: string; + partID?: string; + snapshot?: string; + diff?: string; + }; +}; + +export type EventSessionDeleted = { + type: string; + properties: { + info: Session; + }; +}; + +export type EventSessionIdle = { + type: string; + properties: { + sessionID: string; + }; +}; + +export type EventSessionError = { + type: string; + properties: { + sessionID?: string; + error?: ({ + name: 'ProviderAuthError'; + } & ProviderAuthError) | ({ + name: 'UnknownError'; + } & UnknownError) | ({ + name: 'MessageOutputLengthError'; + } & MessageOutputLengthError) | ({ + name: 'MessageAbortedError'; + } & MessageAbortedError); + }; +}; + +export type EventServerConnected = { + type: string; + properties: { + [key: string]: unknown; + }; +}; + +export type EventFileWatcherUpdated = { + type: string; + properties: { + file: string; + event: string; + }; +}; + +export type EventIdeInstalled = { + type: string; + properties: { + ide: string; + }; +}; + +export type App = { + hostname: string; + git: boolean; + path: { + config: string; + data: string; + root: string; + cwd: string; + state: string; + }; + time: { + initialized?: number; + }; +}; + +export type Config = { + /** + * JSON schema reference for configuration validation + */ + $schema?: string; + /** + * Theme name to use for the interface + */ + theme?: string; + keybinds?: KeybindsConfig; + /** + * Control sharing behavior:'manual' allows manual sharing via commands, 'auto' enables automatic sharing, 'disabled' disables all sharing + */ + share?: 'manual' | 'auto' | 'disabled'; + /** + * @deprecated Use 'share' field instead. Share newly created sessions automatically + */ + autoshare?: boolean; + /** + * Automatically update to the latest version + */ + autoupdate?: boolean; + /** + * Disable providers that are loaded automatically + */ + disabled_providers?: Array; + /** + * Model to use in the format of provider/model, eg anthropic/claude-2 + */ + model?: string; + /** + * Small model to use for tasks like summarization and title generation in the format of provider/model + */ + small_model?: string; + /** + * Custom username to display in conversations instead of system username + */ + username?: string; + /** + * Modes configuration, see https://opencode.ai/docs/modes + */ + mode?: { + build?: ModeConfig; + plan?: ModeConfig; + [key: string]: ModeConfig | undefined; + }; + /** + * Modes configuration, see https://opencode.ai/docs/modes + */ + agent?: { + general?: AgentConfig; + [key: string]: AgentConfig | undefined; + }; + /** + * Custom provider configurations and model overrides + */ + provider?: { + [key: string]: { + api?: string; + name?: string; + env?: Array; + id?: string; + npm?: string; + models: { + [key: string]: { + id?: string; + name?: string; + release_date?: string; + attachment?: boolean; + reasoning?: boolean; + temperature?: boolean; + tool_call?: boolean; + cost?: { + input: number; + output: number; + cache_read?: number; + cache_write?: number; + }; + limit?: { + context: number; + output: number; + }; + options?: { + [key: string]: unknown; + }; + }; + }; + options?: { + apiKey?: string; + baseURL?: string; + [key: string]: unknown | string | undefined; + }; + }; + }; + /** + * MCP (Model Context Protocol) server configurations + */ + mcp?: { + [key: string]: ({ + type: 'local'; + } & McpLocalConfig) | ({ + type: 'remote'; + } & McpRemoteConfig); + }; + /** + * Additional instruction files or patterns to include + */ + instructions?: Array; + layout?: LayoutConfig; + permission?: { + edit?: string; + bash?: string | { + [key: string]: string; + }; + }; + experimental?: { + hook?: { + file_edited?: { + [key: string]: Array<{ + command: Array; + environment?: { + [key: string]: string; + }; + }>; + }; + session_completed?: Array<{ + command: Array; + environment?: { + [key: string]: string; + }; + }>; + }; + }; +}; + +export type KeybindsConfig = { + /** + * Leader key for keybind combinations + */ + leader: string; + /** + * Show help dialog + */ + app_help: string; + /** + * Next mode + */ + switch_mode: string; + /** + * Previous Mode + */ + switch_mode_reverse: string; + /** + * Open external editor + */ + editor_open: string; + /** + * Export session to editor + */ + session_export: string; + /** + * Create a new session + */ + session_new: string; + /** + * List all sessions + */ + session_list: string; + /** + * Share current session + */ + session_share: string; + /** + * Unshare current session + */ + session_unshare: string; + /** + * Interrupt current session + */ + session_interrupt: string; + /** + * Compact the session + */ + session_compact: string; + /** + * Toggle tool details + */ + tool_details: string; + /** + * List available models + */ + model_list: string; + /** + * List available themes + */ + theme_list: string; + /** + * List files + */ + file_list: string; + /** + * Close file + */ + file_close: string; + /** + * Search file + */ + file_search: string; + /** + * Split/unified diff + */ + file_diff_toggle: string; + /** + * Create/update AGENTS.md + */ + project_init: string; + /** + * Clear input field + */ + input_clear: string; + /** + * Paste from clipboard + */ + input_paste: string; + /** + * Submit input + */ + input_submit: string; + /** + * Insert newline in input + */ + input_newline: string; + /** + * Scroll messages up by one page + */ + messages_page_up: string; + /** + * Scroll messages down by one page + */ + messages_page_down: string; + /** + * Scroll messages up by half page + */ + messages_half_page_up: string; + /** + * Scroll messages down by half page + */ + messages_half_page_down: string; + /** + * Navigate to previous message + */ + messages_previous: string; + /** + * Navigate to next message + */ + messages_next: string; + /** + * Navigate to first message + */ + messages_first: string; + /** + * Navigate to last message + */ + messages_last: string; + /** + * Toggle layout + */ + messages_layout_toggle: string; + /** + * Copy message + */ + messages_copy: string; + /** + * @deprecated use messages_undo. Revert message + */ + messages_revert: string; + /** + * Undo message + */ + messages_undo: string; + /** + * Redo message + */ + messages_redo: string; + /** + * Exit the application + */ + app_exit: string; +}; + +export type ModeConfig = { + model?: string; + temperature?: number; + prompt?: string; + tools?: { + [key: string]: boolean; + }; + disable?: boolean; +}; + +export type AgentConfig = ModeConfig & { + description: string; +}; + +export type Provider = { + api?: string; + name: string; + env: Array; + id: string; + npm?: string; + models: { + [key: string]: Model; + }; +}; + +export type Model = { + id: string; + name: string; + release_date: string; + attachment: boolean; + reasoning: boolean; + temperature: boolean; + tool_call: boolean; + cost: { + input: number; + output: number; + cache_read?: number; + cache_write?: number; + }; + limit: { + context: number; + output: number; + }; + options: { + [key: string]: unknown; + }; +}; + +export type McpLocalConfig = { + /** + * Type of MCP server connection + */ + type: string; + /** + * Command and arguments to run the MCP server + */ + command: Array; + /** + * Environment variables to set when running the MCP server + */ + environment?: { + [key: string]: string; + }; + /** + * Enable or disable the MCP server on startup + */ + enabled?: boolean; +}; + +export type McpRemoteConfig = { + /** + * Type of MCP server connection + */ + type: string; + /** + * URL of the remote MCP server + */ + url: string; + /** + * Enable or disable the MCP server on startup + */ + enabled?: boolean; + /** + * Headers to send with the request + */ + headers?: { + [key: string]: string; + }; +}; + +export type LayoutConfig = 'auto' | 'stretch'; + +export type _Error = { + data: { + [key: string]: unknown; + }; +}; + +export type TextPartInput = { + id?: string; + type: string; + text: string; + synthetic?: boolean; + time?: { + start: number; + end?: number; + }; +}; + +export type FilePartInput = { + id?: string; + type: string; + mime: string; + filename?: string; + url: string; + source?: FilePartSource; +}; + +export type Symbol = { + name: string; + kind: number; + location: { + uri: string; + range: Range; + }; +}; + +export type File = { + path: string; + added: number; + removed: number; + status: 'added' | 'deleted' | 'modified'; +}; + +export type Mode = { + name: string; + temperature?: number; + model?: { + modelID: string; + providerID: string; + }; + prompt?: string; + tools: { + [key: string]: boolean; + }; +}; + +export type EventSubscribeData = { + body?: never; + path?: never; + query?: never; + url: '/event'; +}; + +export type EventSubscribeResponses = { + /** + * Event stream + */ + 200: Event; +}; + +export type EventSubscribeResponse = EventSubscribeResponses[keyof EventSubscribeResponses]; + +export type AppGetData = { + body?: never; + path?: never; + query?: never; + url: '/app'; +}; + +export type AppGetResponses = { + /** + * 200 + */ + 200: App; +}; + +export type AppGetResponse = AppGetResponses[keyof AppGetResponses]; + +export type AppInitData = { + body?: never; + path?: never; + query?: never; + url: '/app/init'; +}; + +export type AppInitResponses = { + /** + * Initialize the app + */ + 200: boolean; +}; + +export type AppInitResponse = AppInitResponses[keyof AppInitResponses]; + +export type ConfigGetData = { + body?: never; + path?: never; + query?: never; + url: '/config'; +}; + +export type ConfigGetResponses = { + /** + * Get config info + */ + 200: Config; +}; + +export type ConfigGetResponse = ConfigGetResponses[keyof ConfigGetResponses]; + +export type SessionListData = { + body?: never; + path?: never; + query?: never; + url: '/session'; +}; + +export type SessionListResponses = { + /** + * List of sessions + */ + 200: Array; +}; + +export type SessionListResponse = SessionListResponses[keyof SessionListResponses]; + +export type SessionCreateData = { + body?: never; + path?: never; + query?: never; + url: '/session'; +}; + +export type SessionCreateErrors = { + /** + * Bad request + */ + 400: _Error; +}; + +export type SessionCreateError = SessionCreateErrors[keyof SessionCreateErrors]; + +export type SessionCreateResponses = { + /** + * Successfully created session + */ + 200: Session; +}; + +export type SessionCreateResponse = SessionCreateResponses[keyof SessionCreateResponses]; + +export type SessionDeleteData = { + body?: never; + path: { + id: string; + }; + query?: never; + url: '/session/{id}'; +}; + +export type SessionDeleteResponses = { + /** + * Successfully deleted session + */ + 200: boolean; +}; + +export type SessionDeleteResponse = SessionDeleteResponses[keyof SessionDeleteResponses]; + +export type SessionInitData = { + body?: { + messageID: string; + providerID: string; + modelID: string; + }; + path: { + /** + * Session ID + */ + id: string; + }; + query?: never; + url: '/session/{id}/init'; +}; + +export type SessionInitResponses = { + /** + * 200 + */ + 200: boolean; +}; + +export type SessionInitResponse = SessionInitResponses[keyof SessionInitResponses]; + +export type SessionAbortData = { + body?: never; + path: { + id: string; + }; + query?: never; + url: '/session/{id}/abort'; +}; + +export type SessionAbortResponses = { + /** + * Aborted session + */ + 200: boolean; +}; + +export type SessionAbortResponse = SessionAbortResponses[keyof SessionAbortResponses]; + +export type SessionUnshareData = { + body?: never; + path: { + id: string; + }; + query?: never; + url: '/session/{id}/share'; +}; + +export type SessionUnshareResponses = { + /** + * Successfully unshared session + */ + 200: Session; +}; + +export type SessionUnshareResponse = SessionUnshareResponses[keyof SessionUnshareResponses]; + +export type SessionShareData = { + body?: never; + path: { + id: string; + }; + query?: never; + url: '/session/{id}/share'; +}; + +export type SessionShareResponses = { + /** + * Successfully shared session + */ + 200: Session; +}; + +export type SessionShareResponse = SessionShareResponses[keyof SessionShareResponses]; + +export type SessionSummarizeData = { + body?: { + providerID: string; + modelID: string; + }; + path: { + /** + * Session ID + */ + id: string; + }; + query?: never; + url: '/session/{id}/summarize'; +}; + +export type SessionSummarizeResponses = { + /** + * Summarized session + */ + 200: boolean; +}; + +export type SessionSummarizeResponse = SessionSummarizeResponses[keyof SessionSummarizeResponses]; + +export type SessionMessagesData = { + body?: never; + path: { + /** + * Session ID + */ + id: string; + }; + query?: never; + url: '/session/{id}/message'; +}; + +export type SessionMessagesResponses = { + /** + * List of messages + */ + 200: Array<{ + info: Message; + parts: Array; + }>; +}; + +export type SessionMessagesResponse = SessionMessagesResponses[keyof SessionMessagesResponses]; + +export type SessionChatData = { + body?: { + messageID?: string; + providerID: string; + modelID: string; + mode?: string; + system?: string; + tools?: { + [key: string]: boolean; + }; + parts: Array<({ + type: 'text'; + } & TextPartInput) | ({ + type: 'file'; + } & FilePartInput)>; + }; + path: { + /** + * Session ID + */ + id: string; + }; + query?: never; + url: '/session/{id}/message'; +}; + +export type SessionChatResponses = { + /** + * Created message + */ + 200: AssistantMessage; +}; + +export type SessionChatResponse = SessionChatResponses[keyof SessionChatResponses]; + +export type SessionRevertData = { + body?: { + messageID: string; + partID?: string; + }; + path: { + id: string; + }; + query?: never; + url: '/session/{id}/revert'; +}; + +export type SessionRevertResponses = { + /** + * Updated session + */ + 200: Session; +}; + +export type SessionRevertResponse = SessionRevertResponses[keyof SessionRevertResponses]; + +export type SessionUnrevertData = { + body?: never; + path: { + id: string; + }; + query?: never; + url: '/session/{id}/unrevert'; +}; + +export type SessionUnrevertResponses = { + /** + * Updated session + */ + 200: Session; +}; + +export type SessionUnrevertResponse = SessionUnrevertResponses[keyof SessionUnrevertResponses]; + +export type ConfigProvidersData = { + body?: never; + path?: never; + query?: never; + url: '/config/providers'; +}; + +export type ConfigProvidersResponses = { + /** + * List of providers + */ + 200: { + providers: Array; + default: { + [key: string]: string; + }; + }; +}; + +export type ConfigProvidersResponse = ConfigProvidersResponses[keyof ConfigProvidersResponses]; + +export type FindTextData = { + body?: never; + path?: never; + query: { + pattern: string; + }; + url: '/find'; +}; + +export type FindTextResponses = { + /** + * Matches + */ + 200: Array<{ + path: { + text: string; + }; + lines: { + text: string; + }; + line_number: number; + absolute_offset: number; + submatches: Array<{ + match: { + text: string; + }; + start: number; + end: number; + }>; + }>; +}; + +export type FindTextResponse = FindTextResponses[keyof FindTextResponses]; + +export type FindFilesData = { + body?: never; + path?: never; + query: { + query: string; + }; + url: '/find/file'; +}; + +export type FindFilesResponses = { + /** + * File paths + */ + 200: Array; +}; + +export type FindFilesResponse = FindFilesResponses[keyof FindFilesResponses]; + +export type FindSymbolsData = { + body?: never; + path?: never; + query: { + query: string; + }; + url: '/find/symbol'; +}; + +export type FindSymbolsResponses = { + /** + * Symbols + */ + 200: Array; +}; + +export type FindSymbolsResponse = FindSymbolsResponses[keyof FindSymbolsResponses]; + +export type FileReadData = { + body?: never; + path?: never; + query: { + path: string; + }; + url: '/file'; +}; + +export type FileReadResponses = { + /** + * File content + */ + 200: { + type: 'raw' | 'patch'; + content: string; + }; +}; + +export type FileReadResponse = FileReadResponses[keyof FileReadResponses]; + +export type FileStatusData = { + body?: never; + path?: never; + query?: never; + url: '/file/status'; +}; + +export type FileStatusResponses = { + /** + * File status + */ + 200: Array; +}; + +export type FileStatusResponse = FileStatusResponses[keyof FileStatusResponses]; + +export type AppLogData = { + body?: { + /** + * Service name for the log entry + */ + service: string; + /** + * Log level + */ + level: 'debug' | 'info' | 'error' | 'warn'; + /** + * Log message + */ + message: string; + /** + * Additional metadata for the log entry + */ + extra?: { + [key: string]: unknown; + }; + }; + path?: never; + query?: never; + url: '/log'; +}; + +export type AppLogResponses = { + /** + * Log entry written successfully + */ + 200: boolean; +}; + +export type AppLogResponse = AppLogResponses[keyof AppLogResponses]; + +export type AppModesData = { + body?: never; + path?: never; + query?: never; + url: '/mode'; +}; + +export type AppModesResponses = { + /** + * List of modes + */ + 200: Array; +}; + +export type AppModesResponse = AppModesResponses[keyof AppModesResponses]; + +export type TuiAppendPromptData = { + body?: { + text: string; + }; + path?: never; + query?: never; + url: '/tui/append-prompt'; +}; + +export type TuiAppendPromptResponses = { + /** + * Prompt processed successfully + */ + 200: boolean; +}; + +export type TuiAppendPromptResponse = TuiAppendPromptResponses[keyof TuiAppendPromptResponses]; + +export type TuiOpenHelpData = { + body?: never; + path?: never; + query?: never; + url: '/tui/open-help'; +}; + +export type TuiOpenHelpResponses = { + /** + * Help dialog opened successfully + */ + 200: boolean; +}; + +export type TuiOpenHelpResponse = TuiOpenHelpResponses[keyof TuiOpenHelpResponses]; + +export type ClientOptions = { + baseUrl: `${string}://${string}` | (string & {}); +}; \ No newline at end of file diff --git a/packages/sdk/js/src/index.ts b/packages/sdk/js/src/index.ts new file mode 100644 index 000000000..9bd5b5db6 --- /dev/null +++ b/packages/sdk/js/src/index.ts @@ -0,0 +1,3 @@ +export { createClient } from "./gen/client" +export { client } from "./gen/client.gen" +export { Default as opencode } from "./gen/sdk.gen" diff --git a/packages/sdk/package.json b/packages/sdk/package.json deleted file mode 100644 index 12f57b1d3..000000000 --- a/packages/sdk/package.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "name": "@opencode-ai/sdk", - "version": "0.1.0-alpha.20", - "description": "The official TypeScript library for the Opencode API", - "author": "Opencode ", - "types": "dist/index.d.ts", - "main": "dist/index.js", - "type": "commonjs", - "repository": "github:sst/opencode-sdk-js", - "license": "MIT", - "packageManager": "yarn@1.22.22", - "files": [ - "**/*" - ], - "private": false, - "scripts": { - "test": "./scripts/test", - "build": "./scripts/build", - "prepublishOnly": "echo 'to publish, run yarn build && (cd dist; yarn publish)' && exit 1", - "format": "./scripts/format", - "prepare": "if ./scripts/utils/check-is-in-git-install.sh; then ./scripts/build && ./scripts/utils/git-swap.sh; fi", - "tsn": "ts-node -r tsconfig-paths/register", - "lint": "./scripts/lint", - "fix": "./scripts/format" - }, - "dependencies": {}, - "devDependencies": { - "@arethetypeswrong/cli": "^0.17.0", - "@swc/core": "^1.3.102", - "@swc/jest": "^0.2.29", - "@types/jest": "^29.4.0", - "@types/node": "^20.17.6", - "@typescript-eslint/eslint-plugin": "8.31.1", - "@typescript-eslint/parser": "8.31.1", - "eslint": "^9.20.1", - "eslint-plugin-prettier": "^5.4.1", - "eslint-plugin-unused-imports": "^4.1.4", - "iconv-lite": "^0.6.3", - "jest": "^29.4.0", - "prettier": "^3.0.0", - "publint": "^0.2.12", - "ts-jest": "^29.1.0", - "ts-node": "^10.5.0", - "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz", - "tsconfig-paths": "^4.0.0", - "typescript": "catalog:", - "typescript-eslint": "8.31.1" - }, - "imports": { - "@opencode-ai/sdk": ".", - "@opencode-ai/sdk/*": "./src/*" - }, - "exports": { - ".": { - "import": "./dist/index.mjs", - "require": "./dist/index.js" - }, - "./*.mjs": { - "default": "./dist/*.mjs" - }, - "./*.js": { - "default": "./dist/*.js" - }, - "./*": { - "import": "./dist/*.mjs", - "require": "./dist/*.js" - } - } -} diff --git a/packages/sdk/script/publish.ts b/packages/sdk/script/publish.ts index 47d26b74b..34b66f7f0 100755 --- a/packages/sdk/script/publish.ts +++ b/packages/sdk/script/publish.ts @@ -7,12 +7,37 @@ import path from 'path'; console.log('=== Generating SDKs ==='); console.log(); -const dir = new URL('..', import.meta.url).pathname; +import { createClient, defaultPlugins } from '@hey-api/openapi-ts'; +const dir = new URL('..', import.meta.url).pathname; +await $`bun run ../opencode/src/index.ts generate > openapi.json`.cwd(dir); + +await createClient({ + input: './openapi.json', + output: './js', + plugins: [ + { + name: '@hey-api/typescript', + exportFromIndex: false, + }, + { + name: '@hey-api/sdk', + asClass: true, + exportFromIndex: false, + auth: false, + }, + { + name: '@hey-api/client-fetch', + exportFromIndex: false, + baseUrl: 'http://localhost:4096', + }, + ], +}); + +/* await fs.rm(path.join(dir, 'js'), { recursive: true, force: true }); await fs.rm(path.join(dir, 'go'), { recursive: true, force: true }); -await $`bun run ../opencode/src/index.ts generate > openapi.json`.cwd(dir); await $`stl builds create --branch dev --pull --allow-empty --+target go --+target typescript`.cwd(dir); await $`mv opencode-go/ go`; @@ -21,3 +46,4 @@ await fs.rm(path.join(dir, 'go', '.git'), { recursive: true, force: true }); await $`mv opencode-typescript/ js`; await $`rm -rf js/.git`.cwd(dir); await $`rm -rf js/yarn.lock`.cwd(dir); +*/