diff --git a/bun.lock b/bun.lock index 6f94f9c3..edacee9f 100644 --- a/bun.lock +++ b/bun.lock @@ -43,7 +43,7 @@ }, "packages/app": { "name": "@prover-coder-ai/docker-git", - "version": "1.3.8", + "version": "1.3.10", "bin": { "docker-git": "dist/src/docker-git/main.js", }, @@ -62,6 +62,7 @@ "@effect/workflow": "^0.18.2", "@gridland/bun": "0.4.3", "@gridland/web": "0.4.3", + "@prover-coder-ai/docker-git-openapi": "workspace:*", "@prover-coder-ai/docker-git-session-sync": "workspace:*", "effect": "^3.21.3", "react": "19.2.4", @@ -153,7 +154,7 @@ }, "packages/docker-git-session-sync": { "name": "@prover-coder-ai/docker-git-session-sync", - "version": "1.0.64", + "version": "1.0.66", "bin": { "docker-git-session-sync": "dist/docker-git-session-sync.js", }, @@ -231,6 +232,19 @@ "vitest": "^4.1.9", }, }, + "packages/openapi": { + "name": "@prover-coder-ai/docker-git-openapi", + "version": "0.1.0", + "dependencies": { + "@effect/schema": "^0.75.5", + "effect": "^3.21.3", + "openapi-fetch": "^0.17.0", + }, + "devDependencies": { + "openapi-typescript": "^7.13.0", + "typescript": "^6.0.3", + }, + }, "packages/terminal": { "name": "@prover-coder-ai/docker-git-terminal", "version": "0.1.1", @@ -654,12 +668,20 @@ "@prover-coder-ai/docker-git-container": ["@prover-coder-ai/docker-git-container@workspace:packages/container"], + "@prover-coder-ai/docker-git-openapi": ["@prover-coder-ai/docker-git-openapi@workspace:packages/openapi"], + "@prover-coder-ai/docker-git-session-sync": ["@prover-coder-ai/docker-git-session-sync@workspace:packages/docker-git-session-sync"], "@prover-coder-ai/docker-git-terminal": ["@prover-coder-ai/docker-git-terminal@workspace:packages/terminal"], "@prover-coder-ai/eslint-plugin-suggest-members": ["@prover-coder-ai/eslint-plugin-suggest-members@0.0.26", "", { "dependencies": { "@effect/platform": "^0.96.0", "@effect/platform-node": "^0.106.0", "@effect/schema": "^0.75.5", "@typescript-eslint/utils": "8.57.2", "effect": "^3.21.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <7.0.0" } }, "sha512-RWl1jYZTMK1p0L6GA7VXvTrtiNkbQyjkgk3mvz0Vv7ImTrctDOLFfNIRoJmhU+e5irj1u5uK2p9QoZtRzi4ILQ=="], + "@redocly/ajv": ["@redocly/ajv@8.11.2", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", "uri-js-replace": "^1.0.1" } }, "sha512-io1JpnwtIcvojV7QKDUSIuMN/ikdOUd1ReEnUnMKGfDVridQZ31J0MmIuqwuRjWDZfmvr+Q0MqCcfHM2gTivOg=="], + + "@redocly/config": ["@redocly/config@0.22.0", "", {}, "sha512-gAy93Ddo01Z3bHuVdPWfCwzgfaYgMdaZPcfL7JZ7hWJoK9V0lXDbigTWkhiPFAaLWzbOJ+kbUQG1+XwIm0KRGQ=="], + + "@redocly/openapi-core": ["@redocly/openapi-core@1.34.15", "", { "dependencies": { "@redocly/ajv": "8.11.2", "@redocly/config": "0.22.0", "colorette": "1.4.0", "https-proxy-agent": "7.0.6", "js-levenshtein": "1.1.6", "js-yaml": "4.1.1", "minimatch": "5.1.9", "pluralize": "8.0.0", "yaml-ast-parser": "0.0.43" } }, "sha512-HAwCnNyKcs5XGQqms+9t7OdAPM/5TDstmhF+0i7tdCFato2QKuYIlyWETwkXd8c5zbltr1oB+6y9NTeQLr2d6Q=="], + "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.3", "", { "os": "android", "cpu": "arm64" }, "sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw=="], "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-PcAhP+ynjURNyy8SKGl5DQP94aGuB/7JrXJb/t7P+hanXvQVMWzUvRRhBAcg/lNRadBhoUPqSoP4xw5tR/KBEA=="], @@ -846,6 +868,8 @@ "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "8.16.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], + "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="], + "ajv": ["ajv@6.14.0", "", { "dependencies": { "fast-deep-equal": "3.1.3", "fast-json-stable-stringify": "2.1.0", "json-schema-traverse": "0.4.1", "uri-js": "4.4.1" } }, "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw=="], "ansi-colors": ["ansi-colors@4.1.3", "", {}, "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw=="], @@ -958,6 +982,8 @@ "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + "colorette": ["colorette@1.4.0", "", {}, "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g=="], + "colors": ["colors@1.4.0", "", {}, "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA=="], "commander": ["commander@5.1.0", "", {}, "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg=="], @@ -1232,6 +1258,8 @@ "htmlparser2": ["htmlparser2@10.0.0", "", { "dependencies": { "domelementtype": "2.3.0", "domhandler": "5.0.3", "domutils": "3.2.2", "entities": "6.0.1" } }, "sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g=="], + "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="], + "human-id": ["human-id@4.1.3", "", { "bin": { "human-id": "dist/cli.js" } }, "sha512-tsYlhAYpjCKa//8rXZ9DqKEawhPoSytweBC2eNvcaDK+57RZLHGqNs3PZTQO6yekLFSuvA6AlnAfrw1uBvtb+Q=="], "human-signals": ["human-signals@1.1.1", "", {}, "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw=="], @@ -1246,6 +1274,8 @@ "indent-string": ["indent-string@5.0.0", "", {}, "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg=="], + "index-to-position": ["index-to-position@1.2.0", "", {}, "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw=="], + "ini": ["ini@4.1.3", "", {}, "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg=="], "internal-slot": ["internal-slot@1.1.0", "", { "dependencies": { "es-errors": "1.3.0", "hasown": "2.0.2", "side-channel": "1.1.0" } }, "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw=="], @@ -1354,6 +1384,8 @@ "jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="], + "js-levenshtein": ["js-levenshtein@1.1.6", "", {}, "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g=="], + "js-stringify": ["js-stringify@1.0.2", "", {}, "sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g=="], "js-tokens": ["js-tokens@10.0.0", "", {}, "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q=="], @@ -1524,6 +1556,12 @@ "onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="], + "openapi-fetch": ["openapi-fetch@0.17.0", "", { "dependencies": { "openapi-typescript-helpers": "^0.1.0" } }, "sha512-PsbZR1wAPcG91eEthKhN+Zn92FMHxv+/faECIwjXdxfTODGSGegYv0sc1Olz+HYPvKOuoXfp+0pA2XVt2cI0Ig=="], + + "openapi-typescript": ["openapi-typescript@7.13.0", "", { "dependencies": { "@redocly/openapi-core": "^1.34.6", "ansi-colors": "^4.1.3", "change-case": "^5.4.4", "parse-json": "^8.3.0", "supports-color": "^10.2.2", "yargs-parser": "^21.1.1" }, "peerDependencies": { "typescript": "^5.x" }, "bin": { "openapi-typescript": "bin/cli.js" } }, "sha512-EFP392gcqXS7ntPvbhBzbF8TyBA+baIYEm791Hy5YkjDYKTnk/Tn5OQeKm5BIZvJihpp8Zzr4hzx0Irde1LNGQ=="], + + "openapi-typescript-helpers": ["openapi-typescript-helpers@0.1.0", "", {}, "sha512-OKTGPthhivLw/fHz6c3OPtg72vi86qaMlqbJuVJ23qOvQ+53uw1n7HdmkJFibloF7QEjDrDkzJiOJuockM/ljw=="], + "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "0.1.4", "fast-levenshtein": "2.0.6", "levn": "0.4.1", "prelude-ls": "1.2.1", "type-check": "0.4.0", "word-wrap": "1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], "outdent": ["outdent@0.5.0", "", {}, "sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q=="], @@ -1548,7 +1586,7 @@ "parse-entities": ["parse-entities@2.0.0", "", { "dependencies": { "character-entities": "1.2.4", "character-entities-legacy": "1.1.4", "character-reference-invalid": "1.1.4", "is-alphanumerical": "1.0.4", "is-decimal": "1.0.4", "is-hexadecimal": "1.0.4" } }, "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ=="], - "parse-json": ["parse-json@5.2.0", "", { "dependencies": { "@babel/code-frame": "7.27.1", "error-ex": "1.3.4", "json-parse-even-better-errors": "2.3.1", "lines-and-columns": "1.2.4" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="], + "parse-json": ["parse-json@8.3.0", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "index-to-position": "^1.1.0", "type-fest": "^4.39.1" } }, "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ=="], "parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "6.0.1" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], @@ -1772,7 +1810,7 @@ "structured-field-values": ["structured-field-values@2.0.4", "", {}, "sha512-5zpJXYLPwW3WYUD/D58tQjIBs10l3Yx64jZfcKGs/RH79E2t9Xm/b9+ydwdMNVSksnsIY+HR/2IlQmgo0AcTAg=="], - "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + "supports-color": ["supports-color@10.2.2", "", {}, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="], "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], @@ -1842,6 +1880,8 @@ "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "2.3.1" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], + "uri-js-replace": ["uri-js-replace@1.0.1", "", {}, "sha512-W+C9NWNLFOoBI2QWDp4UT9pv65r2w5Cx+3sTYFvtMdDBxkKt1syCqsUdSFAChbEe1uK5TfS04wt/nGwmaeIQ0g=="], + "uri-template-router": ["uri-template-router@1.0.0", "", {}, "sha512-WKcL9ZSIEhHE3f5P4Z47Tf0nWbcgV1ISb/OBuF8YKEYi0SQOyTLCzM6B/gAKFWZhRhqA+C/Ks8UXe2qU5W0FVg=="], "url-template": ["url-template@3.1.1", "", {}, "sha512-4oszoaEKE/mQOtAmdMWqIRHmkxWkUZMnXFnjQ5i01CuRSK3uluxcH1MRVVVWmhlnzT1SCDfKxxficm2G37qzCA=="], @@ -1900,6 +1940,10 @@ "yaml": ["yaml@2.8.2", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A=="], + "yaml-ast-parser": ["yaml-ast-parser@0.0.43", "", {}, "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A=="], + + "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], + "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], "yoga-layout": ["yoga-layout@3.2.1", "", {}, "sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ=="], @@ -2006,6 +2050,10 @@ "@prover-coder-ai/eslint-plugin-suggest-members/effect": ["effect@3.21.2", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "fast-check": "^3.23.1" } }, "sha512-rXd2FGDM8KdjSIrc+mqEELo7ScW7xTVxEf1iInmPSpIde9/nyGuFM710cjTo7/EreGXiUX2MOonPpprbz2XHCg=="], + "@redocly/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], + + "@redocly/openapi-core/minimatch": ["minimatch@5.1.9", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw=="], + "@rolldown/binding-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.4", "", { "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow=="], "@ton-ai-core/vibecode-linter/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "3.1.3", "fast-uri": "3.1.0", "json-schema-traverse": "1.0.0", "require-from-string": "2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], @@ -2028,6 +2076,8 @@ "@vitest/eslint-plugin/@typescript-eslint/utils": ["@typescript-eslint/utils@8.61.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.61.0", "@typescript-eslint/types": "8.61.0", "@typescript-eslint/typescript-estree": "8.61.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-3bzFt7ImFMW/jVYwJamDoe/dMOdFLSC6pom6rRjdh4SZJEYupyMzem8e7vKZLclLfpHjlwSAXOUxtKxGXUiLqA=="], + "chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + "effect/fast-check": ["fast-check@3.23.2", "", { "dependencies": { "pure-rand": "6.1.0" } }, "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A=="], "encoding-sniffer/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": "2.1.2" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], @@ -2082,6 +2132,8 @@ "is-expression/acorn": ["acorn@7.4.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A=="], + "istanbul-lib-report/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + "jest-util/@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="], "jest-util/ci-info": ["ci-info@3.9.0", "", {}, "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ=="], @@ -2100,12 +2152,18 @@ "normalize-package-data/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="], + "openapi-typescript/typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], + + "parse-json/type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="], + "parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], "path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], "pretty-format/ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="], + "read-pkg/parse-json": ["parse-json@5.2.0", "", { "dependencies": { "@babel/code-frame": "7.27.1", "error-ex": "1.3.4", "json-parse-even-better-errors": "2.3.1", "lines-and-columns": "1.2.4" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="], + "read-pkg/type-fest": ["type-fest@0.6.0", "", {}, "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg=="], "read-pkg-up/find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "5.0.0", "path-exists": "4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="], @@ -2268,6 +2326,8 @@ "@prover-coder-ai/eslint-plugin-suggest-members/effect/fast-check": ["fast-check@3.23.2", "", { "dependencies": { "pure-rand": "6.1.0" } }, "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A=="], + "@redocly/openapi-core/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "1.0.2" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + "@ton-ai-core/vibecode-linter/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], "@ton-ai-core/vibecode-linter/effect/fast-check": ["fast-check@3.23.2", "", { "dependencies": { "pure-rand": "6.1.0" } }, "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A=="], @@ -2458,6 +2518,8 @@ "@prover-coder-ai/eslint-plugin-suggest-members/effect/fast-check/pure-rand": ["pure-rand@6.1.0", "", {}, "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA=="], + "@redocly/openapi-core/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + "@ton-ai-core/vibecode-linter/effect/fast-check/pure-rand": ["pure-rand@6.1.0", "", {}, "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA=="], "@ton-ai-core/vibecode-linter/jscpd/fs-extra/jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "2.0.1" }, "optionalDependencies": { "graceful-fs": "4.2.11" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="], diff --git a/package.json b/package.json index b1a942d8..27e3c7cd 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "packages/container", "packages/docker-git-session-sync", "packages/lib", + "packages/openapi", "packages/terminal" ], "scripts": { @@ -20,7 +21,7 @@ "api:dev": "bun run --filter @effect-template/api dev", "api:test": "bun run --filter @effect-template/api test", "api:typecheck": "bun run --filter @effect-template/api typecheck", - "check": "bun run --filter @prover-coder-ai/docker-git-session-sync check && bun run --filter @prover-coder-ai/docker-git-terminal check && bun run --filter @prover-coder-ai/docker-git check && bun run --filter @effect-template/lib typecheck", + "check": "bun run --filter @prover-coder-ai/docker-git-session-sync check && bun run --filter @prover-coder-ai/docker-git-terminal check && bun run --filter @prover-coder-ai/docker-git-openapi check && bun run --filter @prover-coder-ai/docker-git check && bun run --filter @effect-template/lib typecheck", "check:dist-deps-prune": "bun node_modules/@prover-coder-ai/dist-deps-prune/dist/main.js scan --package ./packages/app/package.json --prune-dev true --silent", "changeset": "changeset", "changeset-publish": "bun -e \"if (!process.env.NPM_TOKEN) { console.log('Skipping publish: NPM_TOKEN is not set'); process.exit(0); }\" && changeset publish", @@ -42,13 +43,15 @@ "dev": "bun run --cwd packages/app dev", "web:dev": "bun run --cwd packages/app dev:web", "web:build": "bun run --cwd packages/app build:web", + "web:generate-api": "bun run --cwd packages/openapi generate", + "openapi:lint-contract": "bun run --cwd packages/api lint:openapi-contract", "web:preview": "bun run --cwd packages/app preview:web", "web:serve": "bun run --cwd packages/app serve:web", "lint": "bun run --filter @prover-coder-ai/docker-git-terminal lint && bun run --filter @prover-coder-ai/docker-git lint && bun run --filter @effect-template/lib lint", "lint:tests": "bun run --filter @prover-coder-ai/docker-git lint:tests", "lint:effect": "bun run --filter @prover-coder-ai/docker-git-session-sync lint:effect && bun run --filter @prover-coder-ai/docker-git-terminal lint:effect && bun run --filter @prover-coder-ai/docker-git lint:effect && bun run --filter @prover-coder-ai/docker-git-container lint:effect && bun run --filter @effect-template/lib lint:effect && bun run --filter @effect-template/api lint:effect", "test": "bun run --filter @prover-coder-ai/docker-git-session-sync test && bun run --filter @prover-coder-ai/docker-git-terminal test && bun run --filter @prover-coder-ai/docker-git test && bun run --filter @effect-template/lib test", - "typecheck": "bun run --filter @prover-coder-ai/docker-git-session-sync typecheck && bun run --filter @prover-coder-ai/docker-git-terminal typecheck && bun run --filter @prover-coder-ai/docker-git typecheck && bun run --filter @effect-template/lib typecheck", + "typecheck": "bun run --filter @prover-coder-ai/docker-git-session-sync typecheck && bun run --filter @prover-coder-ai/docker-git-terminal typecheck && bun run --filter @prover-coder-ai/docker-git-openapi typecheck && bun run --filter @prover-coder-ai/docker-git typecheck && bun run --filter @effect-template/lib typecheck", "start": "bun run --cwd packages/app build:docker-git && bun ./packages/app/dist/src/docker-git/main.js" }, "devDependencies": { diff --git a/packages/api/Dockerfile b/packages/api/Dockerfile index 7a90dc03..593094f0 100644 --- a/packages/api/Dockerfile +++ b/packages/api/Dockerfile @@ -76,12 +76,13 @@ RUN set -eu; \ FROM controller-base AS workspace-deps COPY package.json bun.lock bunfig.toml tsconfig.base.json tsconfig.json ./ -RUN mkdir -p packages/api packages/app packages/container packages/docker-git-session-sync packages/lib packages/terminal +RUN mkdir -p packages/api packages/app packages/container packages/docker-git-session-sync packages/lib packages/openapi packages/terminal COPY packages/api/package.json ./packages/api/package.json COPY packages/app/package.json ./packages/app/package.json COPY packages/container/package.json ./packages/container/package.json COPY packages/docker-git-session-sync/package.json ./packages/docker-git-session-sync/package.json COPY packages/lib/package.json ./packages/lib/package.json +COPY packages/openapi/package.json ./packages/openapi/package.json COPY packages/terminal/package.json ./packages/terminal/package.json RUN set -eu; \ diff --git a/packages/api/package.json b/packages/api/package.json index b61ad57f..d2b9f357 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -16,6 +16,7 @@ "typecheck": "tsc --noEmit -p tsconfig.json", "lint": "eslint .", "lint:effect": "eslint --config eslint.effect-ts-check.config.mjs .", + "lint:openapi-contract": "vitest run tests/openapi.test.ts", "pretest": "bun run --cwd ../terminal build && bun run --cwd ../container build && bun run --cwd ../lib build", "test": "vitest run" }, diff --git a/packages/api/src/api/openapi.ts b/packages/api/src/api/openapi.ts new file mode 100644 index 00000000..4c4da351 --- /dev/null +++ b/packages/api/src/api/openapi.ts @@ -0,0 +1,793 @@ +import * as HttpApi from "@effect/platform/HttpApi" +import * as HttpApiEndpoint from "@effect/platform/HttpApiEndpoint" +import * as HttpApiGroup from "@effect/platform/HttpApiGroup" +import * as HttpApiSchema from "@effect/platform/HttpApiSchema" +import * as OpenApi from "@effect/platform/OpenApi" +import * as Schema from "effect/Schema" + +import { + ActiveProjectTerminalSessionRequestSchema, + AgentSessionSchema, + ApplyAllRequestSchema, + ApplyProjectRequestSchema, + AuthMenuRequestSchema, + AuthTerminalSessionRequestSchema, + CodexAuthImportRequestSchema, + CodexAuthLogoutRequestSchema, + CreateProjectRequestSchema, + GitAuthLoginRequestSchema, + GitAuthLogoutRequestSchema, + GithubAuthLoginRequestSchema, + GithubAuthLogoutRequestSchema, + GitlabAuthLoginRequestSchema, + GitlabAuthLogoutRequestSchema, + GrokAuthLogoutRequestSchema, + ProjectAuthRequestSchema, + ProjectBrowserSessionSchema, + ProjectDatabaseForwardSchema, + ProjectDatabaseProfileRequestSchema, + ProjectDatabaseProfileSchema, + ProjectDatabaseSessionSchema, + ProjectPortForwardRequestSchema, + ProjectSkillUpdateRequestSchema, + StartPanelCloudflareTunnelRequestSchema, + StartProjectTerminalSessionRequestSchema, + UpProjectRequestSchema +} from "./schema.js" + +const NullableStringSchema = Schema.NullOr(Schema.String) +const OptionalOkSchema = Schema.optional(Schema.Boolean) + +const ProjectIdParam = HttpApiSchema.param("projectId", Schema.String) +const ProjectKeyParam = HttpApiSchema.param("projectKey", Schema.String) +const SessionIdParam = HttpApiSchema.param("sessionId", Schema.String) +const TargetPortParam = HttpApiSchema.param("targetPort", Schema.NumberFromString) +const ProfileIdParam = HttpApiSchema.param("profileId", Schema.String) +const PromptKindParam = HttpApiSchema.param("kind", Schema.String) +const ScopeIdParam = HttpApiSchema.param("scopeId", Schema.String) +const SkillNameParam = HttpApiSchema.param("name", Schema.String) +const PidParam = HttpApiSchema.param("pid", Schema.NumberFromString) + +export const OkResponseSchema = Schema.Struct({ + ok: Schema.Literal(true) +}) + +export const HealthResponseSchema = Schema.Struct({ + cwd: Schema.String, + ok: Schema.Boolean, + projectsRoot: Schema.String, + revision: NullableStringSchema +}) + +export const ProjectStatusSchema = Schema.Literal("running", "stopped", "unknown") + +const ProjectSummaryFields = { + clonedOnHostname: Schema.optional(Schema.String), + containerName: Schema.optional(Schema.String), + displayName: Schema.String, + id: Schema.String, + projectKey: Schema.String, + repoRef: Schema.String, + repoUrl: Schema.String, + sshSessions: Schema.Number, + startedAtEpochMs: Schema.NullOr(Schema.Number), + startedAtIso: NullableStringSchema, + status: ProjectStatusSchema, + statusLabel: Schema.String +} + +export const ProjectSummarySchema = Schema.Struct(ProjectSummaryFields) + +export const ProjectDetailsSchema = Schema.Struct({ + ...ProjectSummaryFields, + authorizedKeysExists: Schema.Boolean, + authorizedKeysPath: Schema.String, + codexAuthPath: Schema.String, + codexHome: Schema.String, + containerName: Schema.String, + envGlobalPath: Schema.String, + envProjectPath: Schema.String, + gpu: Schema.Literal("none", "all"), + projectDir: Schema.String, + serviceName: Schema.String, + sshCommand: Schema.String, + sshPort: Schema.Number, + sshUser: Schema.String, + targetDir: Schema.String +}) + +export const ProjectsResponseSchema = Schema.Struct({ + projects: Schema.Array(ProjectSummarySchema) +}) + +export const ProjectResponseSchema = Schema.Struct({ + ok: OptionalOkSchema, + project: ProjectDetailsSchema +}) + +export const CreateProjectAcceptedResponseSchema = Schema.Struct({ + accepted: Schema.Literal(true), + cursor: Schema.Number, + projectId: Schema.String +}) + +export const StartProjectTerminalSessionAcceptedResponseSchema = Schema.Struct({ + accepted: Schema.Literal(true), + cursor: Schema.Number, + projectId: Schema.String, + requestId: Schema.String +}) + +export const OutputResponseSchema = Schema.Struct({ + output: Schema.String +}) + +export const ProjectPortForwardStatusSchema = Schema.Literal("running", "stopped", "unknown") + +export const ProjectPortForwardSchema = Schema.Struct({ + bindHost: Schema.String, + containerName: Schema.String, + createdAt: NullableStringSchema, + hostPort: Schema.Number, + id: Schema.String, + projectId: Schema.String, + projectKey: Schema.String, + proxyPath: Schema.String, + publicHost: Schema.String, + status: ProjectPortForwardStatusSchema, + targetContainerName: Schema.String, + targetPort: Schema.Number, + url: Schema.String +}) + +export const ProjectPortForwardsResponseSchema = Schema.Struct({ + forwards: Schema.Array(ProjectPortForwardSchema) +}) + +export const ProjectPortForwardResponseSchema = Schema.Struct({ + forward: ProjectPortForwardSchema +}) + +export const ProjectBrowserResponseSchema = Schema.Struct({ + browser: ProjectBrowserSessionSchema +}) + +export const PanelCloudflareTunnelStatusSchema = Schema.Literal("starting", "running", "stopped", "failed") + +export const PanelCloudflareTunnelSessionSchema = Schema.Struct({ + error: NullableStringSchema, + id: Schema.String, + logTail: Schema.Array(Schema.String), + panelUrl: Schema.String, + publicUrl: NullableStringSchema, + startedAt: Schema.String, + status: PanelCloudflareTunnelStatusSchema, + stoppedAt: NullableStringSchema +}) + +export const PanelCloudflareTunnelResponseSchema = Schema.Struct({ + tunnel: Schema.NullOr(PanelCloudflareTunnelSessionSchema) +}) + +export const ProjectDatabaseProfilesResponseSchema = Schema.Struct({ + profiles: Schema.Array(ProjectDatabaseProfileSchema) +}) + +export const ProjectDatabaseProfileResponseSchema = Schema.Struct({ + profile: ProjectDatabaseProfileSchema +}) + +export const ProjectDatabaseSessionResponseSchema = Schema.Struct({ + session: ProjectDatabaseSessionSchema +}) + +export const ProjectDatabaseForwardsResponseSchema = Schema.Struct({ + forwards: Schema.Array(ProjectDatabaseForwardSchema) +}) + +export const ProjectDatabaseForwardResponseSchema = Schema.Struct({ + forward: ProjectDatabaseForwardSchema +}) + +export const GithubTokenStatusSchema = Schema.Struct({ + key: Schema.String, + label: Schema.String, + login: NullableStringSchema, + status: Schema.Literal("valid", "invalid", "unknown") +}) + +export const GithubAuthStatusSchema = Schema.Struct({ + summary: Schema.String, + tokens: Schema.Array(GithubTokenStatusSchema) +}) + +export const GithubStatusResponseSchema = Schema.Struct({ + ok: OptionalOkSchema, + status: GithubAuthStatusSchema +}) + +export const GitlabTokenStatusSchema = Schema.Struct({ + key: Schema.String, + label: Schema.String, + login: NullableStringSchema, + status: Schema.Literal("valid", "invalid", "unknown") +}) + +export const GitlabAuthStatusSchema = Schema.Struct({ + summary: Schema.String, + tokens: Schema.Array(GitlabTokenStatusSchema) +}) + +export const GitlabStatusResponseSchema = Schema.Struct({ + ok: OptionalOkSchema, + status: GitlabAuthStatusSchema +}) + +export const GitAuthConnectionStatusSchema = Schema.Struct({ + host: Schema.String, + user: Schema.String +}) + +export const GitAuthStatusSchema = Schema.Struct({ + connections: Schema.Array(GitAuthConnectionStatusSchema), + summary: Schema.String +}) + +export const GitStatusResponseSchema = Schema.Struct({ + ok: OptionalOkSchema, + status: GitAuthStatusSchema +}) + +export const CodexAuthStatusSchema = Schema.Struct({ + account: NullableStringSchema, + authPath: Schema.String, + label: Schema.String, + message: Schema.String, + present: Schema.Boolean +}) + +export const CodexStatusResponseSchema = Schema.Struct({ + ok: OptionalOkSchema, + status: CodexAuthStatusSchema +}) + +export const GrokAuthStatusSchema = Schema.Struct({ + authPath: Schema.String, + connected: Schema.Boolean, + label: Schema.String, + message: Schema.String, + method: Schema.Literal("none", "api-key", "oauth") +}) + +export const GrokStatusResponseSchema = Schema.Struct({ + ok: OptionalOkSchema, + status: GrokAuthStatusSchema +}) + +export const AuthSnapshotSchema = Schema.Struct({ + claudeAuthEntries: Schema.Number, + claudeAuthPath: Schema.String, + codexAuthEntries: Schema.optionalWith(Schema.Number, { default: () => 0 }), + codexAuthPath: Schema.optionalWith(Schema.String, { default: () => "" }), + geminiAuthEntries: Schema.Number, + geminiAuthPath: Schema.String, + gitTokenEntries: Schema.Number, + gitUserEntries: Schema.Number, + githubTokenEntries: Schema.Number, + globalEnvPath: Schema.String, + grokAuthEntries: Schema.optionalWith(Schema.Number, { default: () => 0 }), + grokAuthPath: Schema.optionalWith(Schema.String, { default: () => "" }), + totalEntries: Schema.Number +}) + +export const AuthSnapshotResponseSchema = Schema.Struct({ + ok: OptionalOkSchema, + snapshot: AuthSnapshotSchema +}) + +export const ProjectAuthSnapshotSchema = Schema.Struct({ + activeClaudeLabel: NullableStringSchema, + activeGeminiLabel: NullableStringSchema, + activeGitLabel: NullableStringSchema, + activeGithubLabel: NullableStringSchema, + activeGrokLabel: NullableStringSchema, + claudeAuthEntries: Schema.Number, + claudeAuthPath: Schema.String, + codexAuthEntries: Schema.optionalWith(Schema.Number, { default: () => 0 }), + codexAuthPath: Schema.optionalWith(Schema.String, { default: () => "" }), + envGlobalPath: Schema.String, + envProjectPath: Schema.String, + geminiAuthEntries: Schema.Number, + geminiAuthPath: Schema.String, + gitTokenEntries: Schema.Number, + githubTokenEntries: Schema.Number, + grokAuthEntries: Schema.optionalWith(Schema.Number, { default: () => 0 }), + grokAuthPath: Schema.optionalWith(Schema.String, { default: () => "" }), + projectDir: Schema.String, + projectName: Schema.String +}) + +export const ProjectAuthSnapshotResponseSchema = Schema.Struct({ + ok: OptionalOkSchema, + snapshot: ProjectAuthSnapshotSchema +}) + +export const TerminalSessionSchema = Schema.Struct({ + attachedClients: Schema.optional(Schema.Number), + closedAt: Schema.optional(Schema.String), + createdAt: Schema.String, + exitCode: Schema.optional(Schema.Number), + id: Schema.String, + projectId: Schema.String, + signal: Schema.optional(Schema.Number), + sshCommand: Schema.String, + startedAt: Schema.optional(Schema.String), + status: Schema.Literal("ready", "attached", "exited", "failed") +}) + +export const TerminalSessionResponseSchema = Schema.Struct({ + ok: OptionalOkSchema, + project: ProjectDetailsSchema, + session: TerminalSessionSchema +}) + +export const ProjectTerminalSessionsResponseSchema = Schema.Struct({ + activeSessionId: NullableStringSchema, + sessions: Schema.Array(TerminalSessionSchema) +}) + +export const ProjectTerminalSessionResponseSchema = Schema.Struct({ + session: TerminalSessionSchema +}) + +export const ActiveProjectTerminalSessionResponseSchema = Schema.Struct({ + ok: OptionalOkSchema, + session: TerminalSessionSchema +}) + +export const TerminalSessionLookupResponseSchema = Schema.Struct({ + projectDisplayName: Schema.String, + projectKey: Schema.String, + session: TerminalSessionSchema +}) + +export const AuthTerminalSessionResponseSchema = Schema.Struct({ + ok: OptionalOkSchema, + session: TerminalSessionSchema +}) + +export const ProjectPromptKindSchema = Schema.Literal("claude", "codex", "gemini", "grok") + +export const ProjectPromptFileSchema = Schema.Struct({ + absolutePath: Schema.String, + bytes: Schema.Number, + content: Schema.String, + exists: Schema.Boolean, + fileName: Schema.String, + kind: ProjectPromptKindSchema, + relativePath: Schema.String +}) + +export const ProjectPromptsSnapshotSchema = Schema.Struct({ + projectDir: Schema.String, + projectId: Schema.String, + projectKey: Schema.String, + prompts: Schema.Array(ProjectPromptFileSchema) +}) + +export const ProjectPromptsResponseSchema = Schema.Struct({ + ok: OptionalOkSchema, + snapshot: ProjectPromptsSnapshotSchema +}) + +export const ProjectPromptUpdateResponseSchema = Schema.Struct({ + ok: OptionalOkSchema, + prompt: ProjectPromptFileSchema, + snapshot: ProjectPromptsSnapshotSchema +}) + +export const ProjectSkillScopeSchema = Schema.Literal( + "skills", + "agents/skills", + "agents/.skills", + "claude/skills", + "codex/skills", + "gemini/skills", + "grok/skills" +) + +export const ProjectSkillFileSchema = Schema.Struct({ + absolutePath: Schema.String, + bytes: Schema.Number, + content: Schema.String, + id: Schema.String, + name: Schema.String, + relativePath: Schema.String, + scope: ProjectSkillScopeSchema, + updatedAtIso: NullableStringSchema +}) + +export const ProjectSkillScopeInfoSchema = Schema.Struct({ + absoluteRoot: Schema.String, + relativeRoot: Schema.String, + scope: ProjectSkillScopeSchema +}) + +export const ProjectSkillsSnapshotSchema = Schema.Struct({ + projectDir: Schema.String, + projectId: Schema.String, + projectKey: Schema.String, + scopes: Schema.Array(ProjectSkillScopeInfoSchema), + skills: Schema.Array(ProjectSkillFileSchema) +}) + +export const ProjectSkillsResponseSchema = Schema.Struct({ + ok: OptionalOkSchema, + snapshot: ProjectSkillsSnapshotSchema +}) + +export const ProjectSkillUpdateResponseSchema = Schema.Struct({ + ok: OptionalOkSchema, + skill: ProjectSkillFileSchema, + snapshot: ProjectSkillsSnapshotSchema +}) + +export const ContainerTaskKindSchema = Schema.Literal("ssh", "web-terminal", "agent", "background", "system") + +export const ContainerTaskSchema = Schema.Struct({ + command: Schema.String, + elapsed: Schema.optional(Schema.String), + etime: Schema.String, + etimes: Schema.Number, + kind: ContainerTaskKindSchema, + logAvailable: Schema.Boolean, + managedId: Schema.optional(Schema.String), + pid: Schema.Number, + ppid: Schema.Number, + tty: Schema.String, + user: Schema.String +}) + +export const ContainerTaskSnapshotSchema = Schema.Struct({ + agents: Schema.Array(AgentSessionSchema), + containerName: Schema.String, + generatedAt: Schema.String, + projectId: Schema.String, + sshConnections: Schema.Number, + tasks: Schema.Array(ContainerTaskSchema), + terminalSessions: Schema.Array(TerminalSessionSchema) +}) + +export const ContainerTaskSnapshotResponseSchema = Schema.Struct({ + snapshot: ContainerTaskSnapshotSchema +}) + +const QueryIncludeDefaultSchema = Schema.Struct({ + includeDefault: Schema.optional(Schema.String) +}) + +const QueryLabelSchema = Schema.Struct({ + label: Schema.optional(Schema.String) +}) + +const QueryLinesSchema = Schema.Struct({ + lines: Schema.optional(Schema.String) +}) + +const ApiErrorEnvelopeSchema = Schema.Struct({ + command: Schema.optional(Schema.String), + details: Schema.optional(Schema.Unknown), + message: Schema.String, + provider: Schema.optional(Schema.String), + type: Schema.String +}) + +const ApiErrorResponseSchema = Schema.Struct({ + error: ApiErrorEnvelopeSchema +}) + +const endpoint = { + del: HttpApiEndpoint.del, + get: HttpApiEndpoint.get, + post: HttpApiEndpoint.post, + put: HttpApiEndpoint.put +} + +const CoreGroup = HttpApiGroup.make("core").add( + endpoint.get("health", "/health").addSuccess(HealthResponseSchema) +) + +const ProjectsGroup = HttpApiGroup.make("projects") + .add(endpoint.get("listProjects", "/projects").addSuccess(ProjectsResponseSchema)) + .add( + endpoint.post("createProject", "/projects") + .setPayload(CreateProjectRequestSchema) + .addSuccess(ProjectResponseSchema, { status: 201 }) + .addSuccess(CreateProjectAcceptedResponseSchema, { status: 202 }) + ) + .add( + endpoint.post("applyAllProjects", "/projects/apply-all") + .setPayload(ApplyAllRequestSchema) + .addSuccess(OkResponseSchema) + ) + .add(endpoint.post("downAllProjects", "/projects/down-all").addSuccess(OkResponseSchema)) + .add(endpoint.get("getProject")`/projects/${ProjectIdParam}`.addSuccess(ProjectResponseSchema)) + .add(endpoint.del("deleteProject")`/projects/${ProjectIdParam}`.addSuccess(OkResponseSchema)) + .add(endpoint.post("downProject")`/projects/${ProjectIdParam}/down`.addSuccess(OkResponseSchema)) + .add( + endpoint.post("applyProject")`/projects/${ProjectIdParam}/apply` + .setPayload(ApplyProjectRequestSchema) + .addSuccess(ProjectResponseSchema) + ) + .add( + endpoint.post("upProject")`/projects/${ProjectIdParam}/up` + .setPayload(UpProjectRequestSchema) + .addSuccess(ProjectResponseSchema) + ) + .add(endpoint.post("resumeProject")`/projects/${ProjectIdParam}/resume`.addSuccess(ProjectResponseSchema)) + .add(endpoint.post("suspendProject")`/projects/${ProjectIdParam}/suspend`.addSuccess(ProjectResponseSchema)) + .add(endpoint.get("projectPs")`/projects/${ProjectIdParam}/ps`.addSuccess(OutputResponseSchema)) + .add(endpoint.get("projectLogs")`/projects/${ProjectIdParam}/logs`.addSuccess(OutputResponseSchema)) + +const ProjectPortsGroup = HttpApiGroup.make("projectPorts") + .add(endpoint.get("listProjectPorts")`/projects/${ProjectIdParam}/ports`.addSuccess(ProjectPortForwardsResponseSchema)) + .add( + endpoint.post("createProjectPort")`/projects/${ProjectIdParam}/ports` + .setPayload(ProjectPortForwardRequestSchema) + .addSuccess(ProjectPortForwardResponseSchema, { status: 201 }) + ) + .add( + endpoint.del("deleteProjectPort")`/projects/${ProjectIdParam}/ports/${TargetPortParam}` + .addSuccess(OkResponseSchema) + ) + +const ProjectBrowserGroup = HttpApiGroup.make("projectBrowser") + .add(endpoint.get("readProjectBrowser")`/projects/${ProjectIdParam}/browser`.addSuccess(ProjectBrowserResponseSchema)) + .add( + endpoint.post("startProjectBrowser")`/projects/${ProjectIdParam}/browser/start` + .addSuccess(ProjectBrowserResponseSchema) + ) + +const ProjectDatabasesGroup = HttpApiGroup.make("projectDatabases") + .add( + endpoint.get("listDatabaseProfiles")`/projects/${ProjectIdParam}/databases/profiles` + .addSuccess(ProjectDatabaseProfilesResponseSchema) + ) + .add( + endpoint.post("saveDatabaseProfile")`/projects/${ProjectIdParam}/databases/profiles` + .setPayload(ProjectDatabaseProfileRequestSchema) + .addSuccess(ProjectDatabaseProfileResponseSchema, { status: 201 }) + ) + .add( + endpoint.del("deleteDatabaseProfile")`/projects/${ProjectIdParam}/databases/profiles/${ProfileIdParam}` + .addSuccess(OkResponseSchema) + ) + .add( + endpoint.post("exposeDatabaseProfile")`/projects/${ProjectIdParam}/databases/profiles/${ProfileIdParam}/expose` + .addSuccess(ProjectDatabaseForwardResponseSchema, { status: 201 }) + ) + .add( + endpoint.del("deleteDatabaseForward")`/projects/${ProjectIdParam}/databases/profiles/${ProfileIdParam}/expose` + .addSuccess(OkResponseSchema) + ) + .add( + endpoint.get("listDatabaseForwards")`/projects/${ProjectIdParam}/databases/forwards` + .addSuccess(ProjectDatabaseForwardsResponseSchema) + ) + .add( + endpoint.get("readDatabaseSession")`/projects/${ProjectIdParam}/databases/session` + .addSuccess(ProjectDatabaseSessionResponseSchema) + ) + .add( + endpoint.post("openDatabaseEditor")`/projects/${ProjectIdParam}/databases/open` + .addSuccess(ProjectDatabaseSessionResponseSchema) + ) + .add( + endpoint.post("restartDatabaseEditor")`/projects/${ProjectIdParam}/databases/restart` + .addSuccess(ProjectDatabaseSessionResponseSchema) + ) + +const AuthGroup = HttpApiGroup.make("auth") + .add(endpoint.get("githubStatus", "/auth/github/status").addSuccess(GithubStatusResponseSchema)) + .add(endpoint.get("gitlabStatus", "/auth/gitlab/status").addSuccess(GitlabStatusResponseSchema)) + .add(endpoint.get("gitStatus", "/auth/git/status").addSuccess(GitStatusResponseSchema)) + .add( + endpoint.get("grokStatus", "/auth/grok/status") + .setUrlParams(QueryLabelSchema) + .addSuccess(GrokStatusResponseSchema) + ) + .add( + endpoint.get("codexStatus", "/auth/codex/status") + .setUrlParams(QueryLabelSchema) + .addSuccess(CodexStatusResponseSchema) + ) + .add( + endpoint.post("githubLogin", "/auth/github/login") + .setPayload(GithubAuthLoginRequestSchema) + .addSuccess(GithubStatusResponseSchema, { status: 201 }) + ) + .add( + endpoint.post("githubLogout", "/auth/github/logout") + .setPayload(GithubAuthLogoutRequestSchema) + .addSuccess(GithubStatusResponseSchema) + ) + .add( + endpoint.post("gitlabLogin", "/auth/gitlab/login") + .setPayload(GitlabAuthLoginRequestSchema) + .addSuccess(GitlabStatusResponseSchema, { status: 201 }) + ) + .add( + endpoint.post("gitlabLogout", "/auth/gitlab/logout") + .setPayload(GitlabAuthLogoutRequestSchema) + .addSuccess(GitlabStatusResponseSchema) + ) + .add( + endpoint.post("gitLogin", "/auth/git/login") + .setPayload(GitAuthLoginRequestSchema) + .addSuccess(GitStatusResponseSchema, { status: 201 }) + ) + .add( + endpoint.post("gitLogout", "/auth/git/logout") + .setPayload(GitAuthLogoutRequestSchema) + .addSuccess(GitStatusResponseSchema) + ) + .add(endpoint.get("authMenu", "/auth/menu").addSuccess(AuthSnapshotResponseSchema)) + .add( + endpoint.post("authMenuAction", "/auth/menu") + .setPayload(AuthMenuRequestSchema) + .addSuccess(AuthSnapshotResponseSchema) + ) + .add( + endpoint.post("authTerminalSession", "/auth/terminal-sessions") + .setPayload(AuthTerminalSessionRequestSchema) + .addSuccess(AuthTerminalSessionResponseSchema, { status: 201 }) + ) + .add( + endpoint.post("codexImport", "/auth/codex/import") + .setPayload(CodexAuthImportRequestSchema) + .addSuccess(CodexStatusResponseSchema, { status: 201 }) + ) + .add( + endpoint.post("codexLogout", "/auth/codex/logout") + .setPayload(CodexAuthLogoutRequestSchema) + .addSuccess(CodexStatusResponseSchema) + ) + .add( + endpoint.post("grokLogout", "/auth/grok/logout") + .setPayload(GrokAuthLogoutRequestSchema) + .addSuccess(GrokStatusResponseSchema) + ) + +const ProjectAuthGroup = HttpApiGroup.make("projectAuth") + .add(endpoint.get("projectAuth")`/projects/${ProjectIdParam}/auth/menu`.addSuccess(ProjectAuthSnapshotResponseSchema)) + .add( + endpoint.post("projectAuthAction")`/projects/${ProjectIdParam}/auth/menu` + .setPayload(ProjectAuthRequestSchema) + .addSuccess(ProjectAuthSnapshotResponseSchema) + ) + +const TerminalGroup = HttpApiGroup.make("terminal") + .add( + endpoint.post("createTerminalByKey")`/projects/by-key/${ProjectKeyParam}/terminal-sessions` + .addSuccess(TerminalSessionResponseSchema, { status: 201 }) + ) + .add( + endpoint.post("startTerminalByKey")`/projects/by-key/${ProjectKeyParam}/terminal-sessions/start` + .setPayload(StartProjectTerminalSessionRequestSchema) + .addSuccess(StartProjectTerminalSessionAcceptedResponseSchema, { status: 202 }) + ) + .add( + endpoint.get("listTerminalsByKey")`/projects/by-key/${ProjectKeyParam}/terminal-sessions` + .addSuccess(ProjectTerminalSessionsResponseSchema) + ) + .add( + endpoint.get("getTerminalByKey")`/projects/by-key/${ProjectKeyParam}/terminal-sessions/${SessionIdParam}` + .addSuccess(ProjectTerminalSessionResponseSchema) + ) + .add( + endpoint.del("deleteTerminalByKey")`/projects/by-key/${ProjectKeyParam}/terminal-sessions/${SessionIdParam}` + .addSuccess(OkResponseSchema) + ) + .add( + endpoint.put("setActiveTerminalByKey")`/projects/by-key/${ProjectKeyParam}/terminal-sessions/active` + .setPayload(ActiveProjectTerminalSessionRequestSchema) + .addSuccess(ActiveProjectTerminalSessionResponseSchema) + ) + .add(endpoint.get("lookupTerminal")`/terminal-sessions/${SessionIdParam}`.addSuccess(TerminalSessionLookupResponseSchema)) + .add( + endpoint.del("deleteAuthTerminal")`/auth/terminal-sessions/${SessionIdParam}`.addSuccess(OkResponseSchema) + ) + +const PromptsGroup = HttpApiGroup.make("prompts") + .add(endpoint.get("listPrompts")`/projects/${ProjectIdParam}/prompts`.addSuccess(ProjectPromptsResponseSchema)) + .add( + endpoint.put("writePrompt")`/projects/${ProjectIdParam}/prompts/${PromptKindParam}` + .setPayload(Schema.Struct({ content: Schema.String })) + .addSuccess(ProjectPromptUpdateResponseSchema) + ) + .add( + endpoint.del("deletePrompt")`/projects/${ProjectIdParam}/prompts/${PromptKindParam}` + .addSuccess(ProjectPromptsResponseSchema) + ) + +const SkillsGroup = HttpApiGroup.make("skills") + .add(endpoint.get("listSkills")`/projects/${ProjectIdParam}/skills`.addSuccess(ProjectSkillsResponseSchema)) + .add( + endpoint.post("writeSkill")`/projects/${ProjectIdParam}/skills` + .setPayload(ProjectSkillUpdateRequestSchema) + .addSuccess(ProjectSkillUpdateResponseSchema) + ) + .add( + endpoint.del("deleteSkill")`/projects/${ProjectIdParam}/skills/${ScopeIdParam}/${SkillNameParam}` + .addSuccess(ProjectSkillsResponseSchema) + ) + +const TasksGroup = HttpApiGroup.make("tasks") + .add( + endpoint.get("listTasks")`/projects/${ProjectIdParam}/tasks` + .setUrlParams(QueryIncludeDefaultSchema) + .addSuccess(ContainerTaskSnapshotResponseSchema) + ) + .add(endpoint.post("stopTask")`/projects/${ProjectIdParam}/tasks/${PidParam}/stop`.addSuccess(OkResponseSchema)) + .add( + endpoint.get("taskLogs")`/projects/${ProjectIdParam}/tasks/${PidParam}/logs` + .setUrlParams(QueryLinesSchema) + .addSuccess(OutputResponseSchema) + ) + +const SharingGroup = HttpApiGroup.make("sharing") + .add(endpoint.get("readPanelCloudflareTunnel", "/cloudflare-tunnels/panel").addSuccess(PanelCloudflareTunnelResponseSchema)) + .add( + endpoint.post("startPanelCloudflareTunnel", "/cloudflare-tunnels/panel") + .setPayload(StartPanelCloudflareTunnelRequestSchema) + .addSuccess(PanelCloudflareTunnelResponseSchema, { status: 202 }) + ) + .add(endpoint.del("stopPanelCloudflareTunnel", "/cloudflare-tunnels/panel").addSuccess(PanelCloudflareTunnelResponseSchema)) + +export const DockerGitApi = HttpApi.make("docker-git") + .annotate(OpenApi.Title, "docker-git API") + .annotate(OpenApi.Version, "1.0.0") + .annotate(OpenApi.Description, "Effect contract for docker-git JSON REST endpoints.") + .addError(ApiErrorResponseSchema, { status: 400 }) + .addError(ApiErrorResponseSchema, { status: 401 }) + .addError(ApiErrorResponseSchema, { status: 404 }) + .addError(ApiErrorResponseSchema, { status: 409 }) + .addError(ApiErrorResponseSchema, { status: 500 }) + .add(CoreGroup) + .add(ProjectsGroup) + .add(ProjectPortsGroup) + .add(ProjectBrowserGroup) + .add(ProjectDatabasesGroup) + .add(AuthGroup) + .add(ProjectAuthGroup) + .add(TerminalGroup) + .add(PromptsGroup) + .add(SkillsGroup) + .add(TasksGroup) + .add(SharingGroup) + +/** + * Builds the OpenAPI document from the Effect HttpApi contract. + * + * @returns OpenAPI 3.1 specification for JSON REST endpoints. + * + * @pure true - deterministic projection from the static Effect contract. + * @effect none + * @invariant every documented path is derived from DockerGitApi, not hand-written JSON. + * @precondition DockerGitApi is importable without starting the HTTP server. + * @postcondition the returned spec has openapi = "3.1.0". + * @complexity O(n) time / O(n) space where n is the number of endpoints and schemas. + * @throws Never. + */ +// CHANGE: derive Swagger/OpenAPI from the Effect HttpApi contract. +// WHY: frontend clients must be generated from one typed REST contract. +// QUOTE(ТЗ): "Надо сделать REST API нормальный на базе Effect и использовать Swagger." +// REF: user-message-2026-06-18-openapi-fetch +// SOURCE: https://openapi-ts.dev/openapi-fetch/ +// FORMAT THEOREM: forall endpoint e in DockerGitApi, e is represented in buildDockerGitOpenApi().paths. +// PURITY: CORE +// EFFECT: none +// INVARIANT: spec = OpenApi.fromApi(DockerGitApi). +// COMPLEXITY: O(n)/O(n) +export const buildDockerGitOpenApi = (): OpenApi.OpenAPISpec => + OpenApi.fromApi(DockerGitApi, { additionalPropertiesStrategy: "strict" }) diff --git a/packages/api/src/http.ts b/packages/api/src/http.ts index 0118efac..94c4752c 100644 --- a/packages/api/src/http.ts +++ b/packages/api/src/http.ts @@ -46,6 +46,7 @@ import { UpProjectRequestSchema } from "./api/schema.js" import type { UpProjectRequestInput } from "./api/schema.js" +import { buildDockerGitOpenApi } from "./api/openapi.js" import { defaultProjectsRoot } from "@effect-template/lib/usecases/menu-helpers" import { resolveWorkspaceRoot } from "@effect-template/lib/shell/workspace-root" import { @@ -300,6 +301,51 @@ const textResponse = (data: string, contentType: string, status = 200) => ) ) +/** + * Renders a Swagger UI document that loads the generated OpenAPI contract. + * + * @returns HTML document for interactive API documentation. + * + * @pure true - deterministic string construction. + * @effect none + * @invariant the document references the relative openapi.json path. + * @precondition Swagger UI CDN assets are reachable by the browser. + * @postcondition direct /docs and proxied /api/docs both resolve their adjacent OpenAPI document. + * @complexity O(1) time / O(1) space. + * @throws Never. + */ +// CHANGE: expose browser-readable Swagger UI for the Effect REST contract. +// WHY: generated clients and humans must inspect the same OpenAPI document. +// QUOTE(ТЗ): "использовать Swagger" +// REF: user-message-2026-06-18-openapi-fetch +// SOURCE: n/a +// FORMAT THEOREM: docsPath(d) = p -> openApiPath(d) = sibling(p, "openapi.json") +// PURITY: CORE +// EFFECT: none +// INVARIANT: Swagger UI reads the relative OpenAPI document. +// COMPLEXITY: O(1)/O(1) +const renderSwaggerDocsHtml = (): string => ` + + + + + docker-git API + + + +
+ + + +` + const binaryResponse = (data: Uint8Array, contentType: string, status = 200) => Effect.succeed( HttpServerResponse.setStatus( @@ -941,6 +987,14 @@ const skillerConnectResponse = ( export const makeRouter = () => { const withCoreRoutes = HttpRouter.empty.pipe( + HttpRouter.get( + "/openapi.json", + jsonResponse(buildDockerGitOpenApi(), 200).pipe(Effect.catchAll(errorResponse)) + ), + HttpRouter.get( + "/docs", + textResponse(renderSwaggerDocsHtml(), "text/html; charset=utf-8").pipe(Effect.catchAll(errorResponse)) + ), HttpRouter.get( "/health", Effect.gen(function*(_) { diff --git a/packages/api/tests/openapi.test.ts b/packages/api/tests/openapi.test.ts new file mode 100644 index 00000000..dad37446 --- /dev/null +++ b/packages/api/tests/openapi.test.ts @@ -0,0 +1,200 @@ +import { describe, expect, it } from "@effect/vitest" +import { Effect } from "effect" +import * as fc from "fast-check" + +import { buildDockerGitOpenApi } from "../src/api/openapi.js" + +const documentedMethods = ["delete", "get", "post", "put"] as const +const commonErrorStatuses = ["400", "401", "404", "409", "500"] +const okOnlyOperations = [ + { method: "post", path: "/projects/apply-all" }, + { method: "post", path: "/projects/down-all" }, + { method: "delete", path: "/projects/{projectId}" }, + { method: "post", path: "/projects/{projectId}/down" }, + { method: "delete", path: "/projects/{projectId}/ports/{targetPort}" }, + { method: "delete", path: "/projects/{projectId}/databases/profiles/{profileId}" }, + { method: "delete", path: "/projects/{projectId}/databases/profiles/{profileId}/expose" }, + { method: "delete", path: "/projects/by-key/{projectKey}/terminal-sessions/{sessionId}" }, + { method: "delete", path: "/auth/terminal-sessions/{sessionId}" }, + { method: "post", path: "/projects/{projectId}/tasks/{pid}/stop" } +] as const + +describe("openapi contract", () => { + it.effect("documents generated REST paths from the Effect HttpApi contract", () => + Effect.sync(() => { + const spec = buildDockerGitOpenApi() + const paths = spec.paths ?? {} + + expect(spec.openapi).toBe("3.1.0") + expect(paths["/health"]).toBeDefined() + expect(paths["/projects"]).toBeDefined() + expect(paths["/projects/{projectId}"]).toBeDefined() + expect(paths["/auth/git/status"]).toBeDefined() + expect(paths["/auth/gitlab/status"]).toBeDefined() + expect(paths["/auth/codex/status"]).toBeDefined() + expect(paths["/auth/grok/status"]).toBeDefined() + expect(paths["/auth/codex/login"]).toBeUndefined() + expect(paths["/projects/{projectId}/auth/menu"]).toBeDefined() + expect(paths["/projects/{projectId}/auth"]).toBeUndefined() + expect(Object.keys(paths)).toHaveLength(54) + })) + + it.effect("documents real HTTP success status codes for create and async endpoints", () => + Effect.sync(() => { + const spec = buildDockerGitOpenApi() + const paths = spec.paths ?? {} + + const postResponseStatuses = (path: string): ReadonlyArray => + Object.keys(paths[path]?.post?.responses ?? {}) + + expect(postResponseStatuses("/projects")).toEqual(expect.arrayContaining(["201", "202", "400"])) + expect(postResponseStatuses("/projects/{projectId}/ports")).toEqual(expect.arrayContaining(["201", "400"])) + expect(postResponseStatuses("/projects/{projectId}/databases/profiles")).toEqual( + expect.arrayContaining(["201", "400"]) + ) + expect(postResponseStatuses("/projects/{projectId}/databases/profiles/{profileId}/expose")).toEqual( + expect.arrayContaining(["201", "400"]) + ) + expect(postResponseStatuses("/auth/terminal-sessions")).toEqual(expect.arrayContaining(["201", "400"])) + expect(postResponseStatuses("/projects/by-key/{projectKey}/terminal-sessions")).toEqual( + expect.arrayContaining(["201", "400"]) + ) + expect(postResponseStatuses("/projects/by-key/{projectKey}/terminal-sessions/start")).toEqual( + expect.arrayContaining(["202", "400"]) + ) + })) + + it.effect("documents the nested API error envelope used by HTTP handlers", () => + Effect.sync(() => { + const spec = buildDockerGitOpenApi() + const serializedBadRequestSchema = JSON.stringify( + spec.paths?.["/projects"]?.post?.responses?.["400"] ?? {} + ) + + expect(serializedBadRequestSchema).toContain("\"required\":[\"error\"]") + expect(serializedBadRequestSchema).toContain("\"error\":{\"type\":\"object\"") + expect(serializedBadRequestSchema).toContain("\"type\":{\"type\":\"string\"") + expect(serializedBadRequestSchema).toContain("\"message\":{\"type\":\"string\"") + expect(serializedBadRequestSchema).toContain("\"provider\":{\"type\":\"string\"") + expect(serializedBadRequestSchema).toContain("\"command\":{\"type\":\"string\"") + expect(serializedBadRequestSchema).not.toContain("\"required\":[\"error\",\"message\"]") + })) + + it.effect("documents common API error statuses for every JSON REST operation", () => + Effect.sync(() => { + const spec = buildDockerGitOpenApi() + const paths = spec.paths ?? {} + + for (const [path, item] of Object.entries(paths)) { + for (const method of documentedMethods) { + const responses = item[method]?.responses + if (responses === undefined) { + continue + } + + expect(Object.keys(responses), `${method.toUpperCase()} ${path}`).toEqual( + expect.arrayContaining(commonErrorStatuses) + ) + } + } + })) + + it.effect("preserves common error status invariant for arbitrary documented operations", () => + Effect.sync(() => { + const spec = buildDockerGitOpenApi() + const paths = spec.paths ?? {} + const operations = Object.entries(paths).flatMap(([path, item]) => + documentedMethods.flatMap((method) => { + const responses = item[method]?.responses + return responses === undefined ? [] : [{ method, path, responses }] + }) + ) + + expect(operations.length).toBeGreaterThan(0) + + fc.assert( + fc.property(fc.integer({ min: 0, max: operations.length - 1 }), (index) => { + const operation = operations[index] + if (operation === undefined) { + return false + } + expect(Object.keys(operation.responses), `${operation.method.toUpperCase()} ${operation.path}`).toEqual( + expect.arrayContaining(commonErrorStatuses) + ) + return true + }), + { numRuns: Math.max(operations.length * 2, 50) } + ) + })) + + it.effect("documents ok-only HTTP handlers as 200 JSON responses", () => + Effect.sync(() => { + const spec = buildDockerGitOpenApi() + const paths = spec.paths ?? {} + + for (const operation of okOnlyOperations) { + const responses = paths[operation.path]?.[operation.method]?.responses ?? {} + const serializedSuccessSchema = JSON.stringify(responses["200"] ?? {}) + + expect(responses["200"], `${operation.method.toUpperCase()} ${operation.path}`).toBeDefined() + expect(responses["204"], `${operation.method.toUpperCase()} ${operation.path}`).toBeUndefined() + expect(serializedSuccessSchema).toContain("\"required\":[\"ok\"]") + expect(serializedSuccessSchema).toContain("\"ok\":{\"type\":\"boolean\",\"enum\":[true]}") + } + })) + + it.effect("preserves ok-only handler response invariant for arbitrary ok-only operations", () => + Effect.sync(() => { + const spec = buildDockerGitOpenApi() + const paths = spec.paths ?? {} + + fc.assert( + fc.property(fc.constantFrom(...okOnlyOperations), (operation) => { + const responses = paths[operation.path]?.[operation.method]?.responses ?? {} + const serializedSuccessSchema = JSON.stringify(responses["200"] ?? {}) + + expect(responses["200"], `${operation.method.toUpperCase()} ${operation.path}`).toBeDefined() + expect(responses["204"], `${operation.method.toUpperCase()} ${operation.path}`).toBeUndefined() + expect(serializedSuccessSchema).toContain("\"required\":[\"ok\"]") + expect(serializedSuccessSchema).toContain("\"ok\":{\"type\":\"boolean\",\"enum\":[true]}") + }), + { numRuns: okOnlyOperations.length * 2 } + ) + })) + + it.effect("documents project auth snapshots without nonexistent totalEntries", () => + Effect.sync(() => { + const spec = buildDockerGitOpenApi() + const serializedProjectAuthSchema = JSON.stringify( + spec.paths?.["/projects/{projectId}/auth/menu"]?.get?.responses?.["200"] ?? {} + ) + + expect(serializedProjectAuthSchema).toContain("\"projectName\":{\"type\":\"string\"") + expect(serializedProjectAuthSchema).not.toContain("\"totalEntries\"") + })) + + it.effect("documents active terminal response ok envelope", () => + Effect.sync(() => { + const spec = buildDockerGitOpenApi() + const serializedActiveTerminalSchema = JSON.stringify( + spec.paths?.["/projects/by-key/{projectKey}/terminal-sessions/active"]?.put?.responses?.["200"] ?? {} + ) + + expect(serializedActiveTerminalSchema).toContain("\"required\":[\"session\"]") + expect(serializedActiveTerminalSchema).toContain("\"ok\":{\"type\":\"boolean\"") + expect(serializedActiveTerminalSchema).toContain("\"session\":{\"type\":\"object\"") + })) + + it.effect("documents task snapshot terminal sessions and agents", () => + Effect.sync(() => { + const spec = buildDockerGitOpenApi() + const serializedTaskSchema = JSON.stringify( + spec.paths?.["/projects/{projectId}/tasks"]?.get?.responses?.["200"] ?? {} + ) + + expect(serializedTaskSchema).toContain("\"required\":[\"agents\"") + expect(serializedTaskSchema).toContain("\"terminalSessions\"") + expect(serializedTaskSchema).toContain("\"provider\":{\"type\":\"string\"") + expect(serializedTaskSchema).toContain("\"sshCommand\":{\"type\":\"string\"") + })) +}) diff --git a/packages/app/biome.json b/packages/app/biome.json index 27008332..6d652efc 100644 --- a/packages/app/biome.json +++ b/packages/app/biome.json @@ -6,7 +6,8 @@ "useIgnoreFile": false }, "files": { - "ignoreUnknown": false + "ignoreUnknown": false, + "includes": ["**"] }, "assist": { "enabled": false diff --git a/packages/app/package.json b/packages/app/package.json index 2256e2c5..f377aa0f 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -18,6 +18,7 @@ "build:app": "vite build --ssr src/app/main.ts", "build:web": "vite build --config vite.web.config.ts", "build:web:strict": "bun ../../scripts/ci/check-web-build-output.mjs", + "generate:api": "bun run --cwd ../openapi generate", "prepack": "bun run build:docker-git", "dev": "vite build --watch --ssr src/app/main.ts", "dev:web": "vite --config vite.web.config.ts", @@ -64,7 +65,6 @@ "homepage": "https://github.com/ProverCoderAI/docker-git#readme", "packageManager": "bun@1.3.11", "dependencies": { - "@prover-coder-ai/docker-git-session-sync": "workspace:*", "@effect/cli": "^0.75.2", "@effect/cluster": "^0.59.0", "@effect/experimental": "^0.60.0", @@ -79,6 +79,8 @@ "@effect/workflow": "^0.18.2", "@gridland/bun": "0.4.3", "@gridland/web": "0.4.3", + "@prover-coder-ai/docker-git-openapi": "workspace:*", + "@prover-coder-ai/docker-git-session-sync": "workspace:*", "effect": "^3.21.3", "react": "19.2.4", "react-dom": "19.2.4", diff --git a/packages/app/src/web/api-auth-schema.ts b/packages/app/src/web/api-auth-schema.ts index d15eec9d..9d02807c 100644 --- a/packages/app/src/web/api-auth-schema.ts +++ b/packages/app/src/web/api-auth-schema.ts @@ -23,6 +23,41 @@ export const GithubStatusResponseSchema = Schema.Struct({ status: GithubAuthStatusSchema }) +/** + * Boundary schema for the controller Codex authentication status. + * + * @pure true - describes immutable response data only. + * @effect none + * @invariant account may be null, while authPath, label, message, and present are always typed. + * @precondition input is an unknown JSON value received from the API boundary. + * @postcondition successful decoding yields the UI-safe Codex auth status shape. + * @complexity O(1) schema construction; O(n) decode where n is the response size. + * @throws Never. + */ +export const CodexAuthStatusSchema = Schema.Struct({ + account: NullableString, + authPath: Schema.String, + label: Schema.String, + message: Schema.String, + present: Schema.Boolean +}) + +/** + * Boundary schema for the Codex status API response envelope. + * + * @pure true - describes immutable response data only. + * @effect none + * @invariant status is always present; ok is an optional compatibility flag. + * @precondition input is an unknown JSON value received from the API boundary. + * @postcondition successful decoding yields a response with a validated CodexAuthStatusSchema status. + * @complexity O(1) schema construction; O(n) decode where n is the response size. + * @throws Never. + */ +export const CodexStatusResponseSchema = Schema.Struct({ + ok: Schema.optional(Schema.Boolean), + status: CodexAuthStatusSchema +}) + const AuthProviderSnapshotFields = { claudeAuthEntries: Schema.Number, claudeAuthPath: Schema.String, diff --git a/packages/app/src/web/api-create-project.ts b/packages/app/src/web/api-create-project.ts index a2ae250c..ad9e74cd 100644 --- a/packages/app/src/web/api-create-project.ts +++ b/packages/app/src/web/api-create-project.ts @@ -1,13 +1,48 @@ import type { Effect } from "effect" -import { requestJson } from "./api-http.js" +import { + type BaseCreateProjectBody, + baseCreateProjectBody, + type CreateProjectRequestDraft, + optionalProjectResourceFields, + type OptionalProjectResourceFieldsBody +} from "./api-project-create-body.js" import { CreateProjectAcceptedResponseSchema } from "./api-schema.js" -import type { CreateProjectAcceptedResponse, CreateProjectDraft } from "./api-schema.js" - -export const startCreateProject = (draft: CreateProjectDraft): Effect.Effect => - requestJson( - "POST", - "/projects", - CreateProjectAcceptedResponseSchema, - { ...draft, async: true, openSsh: false, useManagedAuthorizedKeys: true } - ) +import type { CreateProjectAcceptedResponse } from "./api-schema.js" +import { openApiJsonSchema } from "./openapi-client.js" + +type CreateProjectAcceptedBody = Readonly< + & BaseCreateProjectBody + & OptionalProjectResourceFieldsBody + & { + readonly async: true + } +> + +/** + * Builds the async POST /projects request body. + * + * @param draft - Validated project creation draft plus optional resource limits. + * @returns Request body for an accepted asynchronous create request. + * + * @pure true - deterministic serialization of immutable input. + * @effect none + * @invariant async create uses the same common fields and optional resource fields as sync create. + * @precondition draft fields were validated by the UI create flow. + * @postcondition output includes async = true and preserves defined Playwright resource limits. + * @complexity O(1). + * @throws Never. + */ +export const createProjectAcceptedBody = (draft: CreateProjectRequestDraft): CreateProjectAcceptedBody => ({ + ...baseCreateProjectBody(draft), + async: true, + ...optionalProjectResourceFields(draft) +}) + +export const startCreateProject = ( + draft: CreateProjectRequestDraft +): Effect.Effect => + openApiJsonSchema(CreateProjectAcceptedResponseSchema, (client) => + client.POST("/projects", { + body: createProjectAcceptedBody(draft) + })) diff --git a/packages/app/src/web/api-database.ts b/packages/app/src/web/api-database.ts index d45cd0bf..31b19dee 100644 --- a/packages/app/src/web/api-database.ts +++ b/packages/app/src/web/api-database.ts @@ -1,6 +1,5 @@ import { Effect } from "effect" -import { requestJson, requestText } from "./api-http.js" import { ProjectDatabaseForwardResponseSchema, ProjectDatabaseForwardsResponseSchema, @@ -9,32 +8,31 @@ import { ProjectDatabaseSessionResponseSchema } from "./api-schema.js" import type { ProjectDatabaseForward, ProjectDatabaseSession } from "./api-schema.js" +import { openApiJsonSchema, openApiVoid } from "./openapi-client.js" export const projectDatabaseEditorUrl = (session: ProjectDatabaseSession): string => session.editorPath export const projectDatabaseExternalUrl = (forward: ProjectDatabaseForward): string => `${forward.publicHost}:${forward.hostPort}` -const projectDatabaseProfilePath = (projectId: string, profileId: string): string => - `/projects/${encodeURIComponent(projectId)}/databases/profiles/${encodeURIComponent(profileId)}` - -const projectDatabaseForwardPath = (projectId: string, profileId: string): string => - `${projectDatabaseProfilePath(projectId, profileId)}/expose` - export const loadProjectDatabaseProfiles = (projectId: string) => - requestJson( - "GET", - `/projects/${encodeURIComponent(projectId)}/databases/profiles`, - ProjectDatabaseProfilesResponseSchema + openApiJsonSchema( + ProjectDatabaseProfilesResponseSchema, + (client) => + client.GET("/projects/{projectId}/databases/profiles", { + params: { path: { projectId } } + }) ).pipe( Effect.map((response) => response.profiles) ) export const loadProjectDatabaseForwards = (projectId: string) => - requestJson( - "GET", - `/projects/${encodeURIComponent(projectId)}/databases/forwards`, - ProjectDatabaseForwardsResponseSchema + openApiJsonSchema( + ProjectDatabaseForwardsResponseSchema, + (client) => + client.GET("/projects/{projectId}/databases/forwards", { + params: { path: { projectId } } + }) ).pipe( Effect.map((response) => response.forwards) ) @@ -44,11 +42,13 @@ export const saveProjectDatabaseProfile = ( connectionString: string, label: string | null ) => - requestJson( - "POST", - `/projects/${encodeURIComponent(projectId)}/databases/profiles`, + openApiJsonSchema( ProjectDatabaseProfileResponseSchema, - { connectionString, label } + (client) => + client.POST("/projects/{projectId}/databases/profiles", { + body: { connectionString, label }, + params: { path: { projectId } } + }) ).pipe( Effect.map((response) => response.profile) ) @@ -56,16 +56,23 @@ export const saveProjectDatabaseProfile = ( export const deleteProjectDatabaseProfile = ( projectId: string, profileId: string -) => requestText("DELETE", projectDatabaseProfilePath(projectId, profileId)).pipe(Effect.asVoid) +) => + openApiVoid((client) => + client.DELETE("/projects/{projectId}/databases/profiles/{profileId}", { + params: { path: { profileId, projectId } } + }) + ) export const exposeProjectDatabaseProfile = ( projectId: string, profileId: string ) => - requestJson( - "POST", - `/projects/${encodeURIComponent(projectId)}/databases/profiles/${encodeURIComponent(profileId)}/expose`, - ProjectDatabaseForwardResponseSchema + openApiJsonSchema( + ProjectDatabaseForwardResponseSchema, + (client) => + client.POST("/projects/{projectId}/databases/profiles/{profileId}/expose", { + params: { path: { profileId, projectId } } + }) ).pipe( Effect.map((response) => response.forward) ) @@ -73,31 +80,42 @@ export const exposeProjectDatabaseProfile = ( export const deleteProjectDatabaseForward = ( projectId: string, profileId: string -) => requestText("DELETE", projectDatabaseForwardPath(projectId, profileId)).pipe(Effect.asVoid) +) => + openApiVoid((client) => + client.DELETE("/projects/{projectId}/databases/profiles/{profileId}/expose", { + params: { path: { profileId, projectId } } + }) + ) export const loadProjectDatabaseSession = (projectId: string) => - requestJson( - "GET", - `/projects/${encodeURIComponent(projectId)}/databases/session`, - ProjectDatabaseSessionResponseSchema + openApiJsonSchema( + ProjectDatabaseSessionResponseSchema, + (client) => + client.GET("/projects/{projectId}/databases/session", { + params: { path: { projectId } } + }) ).pipe( Effect.map((response) => response.session) ) export const openProjectDatabaseEditor = (projectId: string) => - requestJson( - "POST", - `/projects/${encodeURIComponent(projectId)}/databases/open`, - ProjectDatabaseSessionResponseSchema + openApiJsonSchema( + ProjectDatabaseSessionResponseSchema, + (client) => + client.POST("/projects/{projectId}/databases/open", { + params: { path: { projectId } } + }) ).pipe( Effect.map((response) => response.session) ) export const restartProjectDatabaseEditor = (projectId: string) => - requestJson( - "POST", - `/projects/${encodeURIComponent(projectId)}/databases/restart`, - ProjectDatabaseSessionResponseSchema + openApiJsonSchema( + ProjectDatabaseSessionResponseSchema, + (client) => + client.POST("/projects/{projectId}/databases/restart", { + params: { path: { projectId } } + }) ).pipe( Effect.map((response) => response.session) ) diff --git a/packages/app/src/web/api-project-core.ts b/packages/app/src/web/api-project-core.ts index a12f2f75..565b6143 100644 --- a/packages/app/src/web/api-project-core.ts +++ b/packages/app/src/web/api-project-core.ts @@ -1,76 +1,94 @@ import { Effect } from "effect" -import type { ApplyProjectRequest, ProjectResourceLimitRequest } from "../shared/project-resource-request.js" -import { requestJson } from "./api-http.js" -import type { CreateProjectDraft } from "./api-schema.js" +import type { ApplyProjectRequest } from "../shared/project-resource-request.js" +import { + baseCreateProjectBody, + type CreateProjectRequestDraft, + optionalProjectResourceFields +} from "./api-project-create-body.js" import { OutputResponseSchema, ProjectResponseSchema } from "./api-schema.js" +import { openApiJsonSchema } from "./openapi-client.js" export type { ApplyProjectRequest, ProjectResourceLimitRequest } from "../shared/project-resource-request.js" +export type { CreateProjectRequestDraft } from "./api-project-create-body.js" -type CreateProjectRequestDraft = CreateProjectDraft & ProjectResourceLimitRequest +const applyProjectBody = (request: ApplyProjectRequest | undefined) => ({ + ...(request?.cpuLimit !== undefined && { cpuLimit: request.cpuLimit }), + ...(request?.gpu !== undefined && { gpu: request.gpu }), + ...(request?.ramLimit !== undefined && { ramLimit: request.ramLimit }), + ...(request !== undefined && optionalProjectResourceFields(request)) +}) + +const createProjectBody = (draft: CreateProjectRequestDraft) => ({ + ...baseCreateProjectBody(draft), + ...optionalProjectResourceFields(draft) +}) export const loadProjectDetails = (projectId: string) => - requestJson("GET", `/projects/${encodeURIComponent(projectId)}`, ProjectResponseSchema).pipe( - Effect.map((response) => response.project) - ) + openApiJsonSchema(ProjectResponseSchema, (client) => + client.GET("/projects/{projectId}", { + params: { path: { projectId } } + })).pipe( + Effect.map((response) => response.project) + ) export const loadProjectPs = (projectId: string) => - requestJson("GET", `/projects/${encodeURIComponent(projectId)}/ps`, OutputResponseSchema).pipe( - Effect.map((response) => response.output) - ) + openApiJsonSchema(OutputResponseSchema, (client) => + client.GET("/projects/{projectId}/ps", { + params: { path: { projectId } } + })).pipe( + Effect.map((response) => response.output) + ) export const loadProjectLogs = (projectId: string) => - requestJson("GET", `/projects/${encodeURIComponent(projectId)}/logs`, OutputResponseSchema).pipe( - Effect.map((response) => response.output) - ) + openApiJsonSchema(OutputResponseSchema, (client) => + client.GET("/projects/{projectId}/logs", { + params: { path: { projectId } } + })).pipe( + Effect.map((response) => response.output) + ) export const applyProject = ( projectId: string, request?: ApplyProjectRequest ) => - requestJson( - "POST", - `/projects/${encodeURIComponent(projectId)}/apply`, - ProjectResponseSchema, - request - ).pipe( - Effect.map((response) => response.project) - ) + openApiJsonSchema(ProjectResponseSchema, (client) => + client.POST("/projects/{projectId}/apply", { + body: applyProjectBody(request), + params: { path: { projectId } } + })).pipe( + Effect.map((response) => response.project) + ) export const createProject = (draft: CreateProjectRequestDraft) => - requestJson( - "POST", - "/projects", - ProjectResponseSchema, - { ...draft, openSsh: false, useManagedAuthorizedKeys: true } - ).pipe( - Effect.map((response) => response.project) - ) + openApiJsonSchema(ProjectResponseSchema, (client) => + client.POST("/projects", { + body: createProjectBody(draft) + })).pipe( + Effect.map((response) => response.project) + ) export const upProject = (projectId: string) => - requestJson( - "POST", - `/projects/${encodeURIComponent(projectId)}/up`, - ProjectResponseSchema, - { useManagedAuthorizedKeys: true } - ).pipe( - Effect.map((response) => response.project) - ) + openApiJsonSchema(ProjectResponseSchema, (client) => + client.POST("/projects/{projectId}/up", { + body: { useManagedAuthorizedKeys: true }, + params: { path: { projectId } } + })).pipe( + Effect.map((response) => response.project) + ) export const resumeProject = (projectId: string) => - requestJson( - "POST", - `/projects/${encodeURIComponent(projectId)}/resume`, - ProjectResponseSchema - ).pipe( - Effect.map((response) => response.project) - ) + openApiJsonSchema(ProjectResponseSchema, (client) => + client.POST("/projects/{projectId}/resume", { + params: { path: { projectId } } + })).pipe( + Effect.map((response) => response.project) + ) export const suspendProject = (projectId: string) => - requestJson( - "POST", - `/projects/${encodeURIComponent(projectId)}/suspend`, - ProjectResponseSchema - ).pipe( - Effect.map((response) => response.project) - ) + openApiJsonSchema(ProjectResponseSchema, (client) => + client.POST("/projects/{projectId}/suspend", { + params: { path: { projectId } } + })).pipe( + Effect.map((response) => response.project) + ) diff --git a/packages/app/src/web/api-project-create-body.ts b/packages/app/src/web/api-project-create-body.ts new file mode 100644 index 00000000..db0f7019 --- /dev/null +++ b/packages/app/src/web/api-project-create-body.ts @@ -0,0 +1,107 @@ +import type { ProjectResourceLimitRequest } from "../shared/project-resource-request.js" +import type { CreateProjectDraft } from "./api-schema.js" + +/** + * Draft accepted by POST /projects helpers. + * + * @pure true - type-only boundary contract. + * @effect none + * @invariant includes the base project draft plus optional resource limit fields shared by sync and async create flows. + * @precondition callers already validated UI input into CreateProjectDraft fields. + * @postcondition request builders can serialize the same resource fields for both create variants. + * @complexity O(1). + * @throws Never. + */ +export type CreateProjectRequestDraft = CreateProjectDraft & ProjectResourceLimitRequest + +/** + * Optional resource-limit fragment serialized into POST /projects request bodies. + * + * @pure true - structural type contract only. + * @effect none + * @invariant present fields are defined strings; undefined inputs are omitted by optionalProjectResourceFields. + * @precondition callers construct this value through optionalProjectResourceFields. + * @postcondition spreading this fragment cannot add undefined Playwright limit fields. + * @complexity O(1). + * @throws Never. + */ +export type OptionalProjectResourceFieldsBody = Readonly<{ + readonly playwrightCpuLimit?: Exclude + readonly playwrightRamLimit?: Exclude +}> + +/** + * Common POST /projects request body shared by synchronous and asynchronous create flows. + * + * @pure true - structural type contract only. + * @effect none + * @invariant sync and async create flows share identical non-async fields. + * @precondition callers construct this value through baseCreateProjectBody. + * @postcondition openSsh is false and managed authorized keys are enabled for web-created projects. + * @complexity O(1). + * @throws Never. + */ +export type BaseCreateProjectBody = Readonly<{ + readonly cpuLimit: CreateProjectDraft["cpuLimit"] + readonly enableMcpPlaywright: CreateProjectDraft["enableMcpPlaywright"] + readonly force: CreateProjectDraft["force"] + readonly forceEnv: CreateProjectDraft["forceEnv"] + readonly gpu: CreateProjectDraft["gpu"] + readonly openSsh: false + readonly outDir: CreateProjectDraft["outDir"] + readonly ramLimit: CreateProjectDraft["ramLimit"] + readonly repoRef: CreateProjectDraft["repoRef"] + readonly repoUrl: CreateProjectDraft["repoUrl"] + readonly up: CreateProjectDraft["up"] + readonly useManagedAuthorizedKeys: true +}> + +/** + * Serializes optional Playwright resource limits for project creation requests. + * + * @param request - Shared resource limit fields from the validated create draft. + * @returns Object containing only defined Playwright limit fields. + * + * @pure true - deterministic projection from immutable input. + * @effect none + * @invariant undefined optional fields are omitted from the request body. + * @precondition request is a validated web create/apply resource limit request. + * @postcondition output is safe to spread into a JSON request body. + * @complexity O(1). + * @throws Never. + */ +export const optionalProjectResourceFields = ( + request: ProjectResourceLimitRequest +): OptionalProjectResourceFieldsBody => ({ + ...(request.playwrightCpuLimit !== undefined && { playwrightCpuLimit: request.playwrightCpuLimit }), + ...(request.playwrightRamLimit !== undefined && { playwrightRamLimit: request.playwrightRamLimit }) +}) + +/** + * Builds the common POST /projects request body used by sync and async flows. + * + * @param draft - Validated project creation draft. + * @returns Shared request body fields without the flow-specific async flag. + * + * @pure true - deterministic serialization of create draft fields. + * @effect none + * @invariant sync and async create requests share one definition of common fields. + * @precondition draft fields were validated by the UI create flow. + * @postcondition output preserves all non-optional project creation fields. + * @complexity O(1). + * @throws Never. + */ +export const baseCreateProjectBody = (draft: CreateProjectDraft): BaseCreateProjectBody => ({ + cpuLimit: draft.cpuLimit, + enableMcpPlaywright: draft.enableMcpPlaywright, + force: draft.force, + forceEnv: draft.forceEnv, + gpu: draft.gpu, + openSsh: false, + outDir: draft.outDir, + ramLimit: draft.ramLimit, + repoRef: draft.repoRef, + repoUrl: draft.repoUrl, + up: draft.up, + useManagedAuthorizedKeys: true +}) diff --git a/packages/app/src/web/api-prompts.ts b/packages/app/src/web/api-prompts.ts index a45d7a9f..d040462f 100644 --- a/packages/app/src/web/api-prompts.ts +++ b/packages/app/src/web/api-prompts.ts @@ -1,40 +1,37 @@ import { Effect } from "effect" -import { requestJson } from "./api-http.js" import { ProjectPromptsResponseSchema, ProjectPromptUpdateResponseSchema } from "./api-schema.js" import type { ProjectPromptKind } from "./api-schema.js" +import { openApiJsonSchema } from "./openapi-client.js" export const loadProjectPrompts = (projectId: string) => - requestJson( - "GET", - `/projects/${encodeURIComponent(projectId)}/prompts`, - ProjectPromptsResponseSchema - ).pipe( - Effect.map((response) => response.snapshot) - ) + openApiJsonSchema(ProjectPromptsResponseSchema, (client) => + client.GET("/projects/{projectId}/prompts", { + params: { path: { projectId } } + })).pipe( + Effect.map((response) => response.snapshot) + ) export const writeProjectPrompt = ( projectId: string, kind: ProjectPromptKind, content: string ) => - requestJson( - "PUT", - `/projects/${encodeURIComponent(projectId)}/prompts/${encodeURIComponent(kind)}`, - ProjectPromptUpdateResponseSchema, - { content } - ).pipe( - Effect.map((response) => response.snapshot) - ) + openApiJsonSchema(ProjectPromptUpdateResponseSchema, (client) => + client.PUT("/projects/{projectId}/prompts/{kind}", { + body: { content }, + params: { path: { kind, projectId } } + })).pipe( + Effect.map((response) => response.snapshot) + ) export const deleteProjectPrompt = ( projectId: string, kind: ProjectPromptKind ) => - requestJson( - "DELETE", - `/projects/${encodeURIComponent(projectId)}/prompts/${encodeURIComponent(kind)}`, - ProjectPromptsResponseSchema - ).pipe( - Effect.map((response) => response.snapshot) - ) + openApiJsonSchema(ProjectPromptsResponseSchema, (client) => + client.DELETE("/projects/{projectId}/prompts/{kind}", { + params: { path: { kind, projectId } } + })).pipe( + Effect.map((response) => response.snapshot) + ) diff --git a/packages/app/src/web/api-schema.ts b/packages/app/src/web/api-schema.ts index 322c51c3..3d8df97c 100644 --- a/packages/app/src/web/api-schema.ts +++ b/packages/app/src/web/api-schema.ts @@ -5,6 +5,8 @@ import { NullableString } from "./api-project-schema.js" export { AuthSnapshotResponseSchema, AuthSnapshotSchema, + CodexAuthStatusSchema, + CodexStatusResponseSchema, GithubAuthStatusSchema, GithubStatusResponseSchema, GithubTokenStatusSchema, diff --git a/packages/app/src/web/api-share.ts b/packages/app/src/web/api-share.ts index e6bd4c89..fc1e4149 100644 --- a/packages/app/src/web/api-share.ts +++ b/packages/app/src/web/api-share.ts @@ -1,7 +1,7 @@ import { Effect } from "effect" -import { requestJson } from "./api-http.js" import { PanelCloudflareTunnelResponseSchema } from "./api-schema.js" +import { openApiJsonSchema } from "./openapi-client.js" /** * Reads the controller-owned panel Cloudflare tunnel session. @@ -25,7 +25,7 @@ import { PanelCloudflareTunnelResponseSchema } from "./api-schema.js" // INVARIANT: Only schema-decoded tunnel state crosses the API boundary. // COMPLEXITY: O(1) local work plus network IO. export const loadPanelCloudflareTunnel = () => - requestJson("GET", "/cloudflare-tunnels/panel", PanelCloudflareTunnelResponseSchema).pipe( + openApiJsonSchema(PanelCloudflareTunnelResponseSchema, (client) => client.GET("/cloudflare-tunnels/panel")).pipe( Effect.map((response) => response.tunnel) ) @@ -51,14 +51,12 @@ export const loadPanelCloudflareTunnel = () => // INVARIANT: Returned state is decoded by PanelCloudflareTunnelResponseSchema. // COMPLEXITY: O(1) local work plus network IO and controller-side startup. export const startPanelCloudflareTunnel = (panelUrl: string) => - requestJson( - "POST", - "/cloudflare-tunnels/panel", - PanelCloudflareTunnelResponseSchema, - { panelUrl } - ).pipe( - Effect.map((response) => response.tunnel) - ) + openApiJsonSchema(PanelCloudflareTunnelResponseSchema, (client) => + client.POST("/cloudflare-tunnels/panel", { + body: { panelUrl } + })).pipe( + Effect.map((response) => response.tunnel) + ) /** * Stops the controller-owned panel Cloudflare tunnel. @@ -82,6 +80,6 @@ export const startPanelCloudflareTunnel = (panelUrl: string) => // INVARIANT: Returned state is decoded by PanelCloudflareTunnelResponseSchema. // COMPLEXITY: O(1) local work plus network IO and controller-side cleanup. export const stopPanelCloudflareTunnel = () => - requestJson("DELETE", "/cloudflare-tunnels/panel", PanelCloudflareTunnelResponseSchema).pipe( + openApiJsonSchema(PanelCloudflareTunnelResponseSchema, (client) => client.DELETE("/cloudflare-tunnels/panel")).pipe( Effect.map((response) => response.tunnel) ) diff --git a/packages/app/src/web/api-skills.ts b/packages/app/src/web/api-skills.ts index f76c5e78..b0ffb147 100644 --- a/packages/app/src/web/api-skills.ts +++ b/packages/app/src/web/api-skills.ts @@ -1,8 +1,8 @@ import { Effect } from "effect" -import { requestJson } from "./api-http.js" import { ProjectSkillsResponseSchema, ProjectSkillUpdateResponseSchema } from "./api-schema.js" import type { ProjectSkillScope } from "./api-schema.js" +import { openApiJsonSchema } from "./openapi-client.js" const skillScopeIdByScope: Readonly> = { "skills": "skills", @@ -17,13 +17,12 @@ const skillScopeIdByScope: Readonly> = { export const projectSkillScopeToId = (scope: ProjectSkillScope): string => skillScopeIdByScope[scope] export const loadProjectSkills = (projectId: string) => - requestJson( - "GET", - `/projects/${encodeURIComponent(projectId)}/skills`, - ProjectSkillsResponseSchema - ).pipe( - Effect.map((response) => response.snapshot) - ) + openApiJsonSchema(ProjectSkillsResponseSchema, (client) => + client.GET("/projects/{projectId}/skills", { + params: { path: { projectId } } + })).pipe( + Effect.map((response) => response.snapshot) + ) export const writeProjectSkill = ( projectId: string, @@ -31,26 +30,25 @@ export const writeProjectSkill = ( name: string, content: string ) => - requestJson( - "POST", - `/projects/${encodeURIComponent(projectId)}/skills`, - ProjectSkillUpdateResponseSchema, - { scope, name, content } - ).pipe( - Effect.map((response) => response.snapshot) - ) + openApiJsonSchema(ProjectSkillUpdateResponseSchema, (client) => + client.POST("/projects/{projectId}/skills", { + body: { content, name, scope }, + params: { path: { projectId } } + })).pipe( + Effect.map((response) => response.snapshot) + ) export const deleteProjectSkill = ( projectId: string, scope: ProjectSkillScope, name: string ) => - requestJson( - "DELETE", - `/projects/${encodeURIComponent(projectId)}/skills/${encodeURIComponent(projectSkillScopeToId(scope))}/${ - encodeURIComponent(name) - }`, - ProjectSkillsResponseSchema + openApiJsonSchema( + ProjectSkillsResponseSchema, + (client) => + client.DELETE("/projects/{projectId}/skills/{scopeId}/{name}", { + params: { path: { name, projectId, scopeId: projectSkillScopeToId(scope) } } + }) ).pipe( Effect.map((response) => response.snapshot) ) diff --git a/packages/app/src/web/api-tasks.ts b/packages/app/src/web/api-tasks.ts index c7fc7357..e4938207 100644 --- a/packages/app/src/web/api-tasks.ts +++ b/packages/app/src/web/api-tasks.ts @@ -1,38 +1,40 @@ import { Effect } from "effect" -import { requestJson, requestText } from "./api-http.js" import { ContainerTaskSnapshotResponseSchema, OutputResponseSchema } from "./api-schema.js" - -const projectTasksPath = (projectId: string, shouldIncludeDefault: boolean): string => - `/projects/${encodeURIComponent(projectId)}/tasks${shouldIncludeDefault ? "?includeDefault=true" : ""}` +import { openApiJsonSchema, openApiVoid } from "./openapi-client.js" export const loadProjectTasks = (projectId: string, shouldIncludeDefault = false) => - requestJson( - "GET", - projectTasksPath(projectId, shouldIncludeDefault), - ContainerTaskSnapshotResponseSchema - ).pipe( - Effect.map((response) => response.snapshot) - ) + openApiJsonSchema(ContainerTaskSnapshotResponseSchema, (client) => + client.GET("/projects/{projectId}/tasks", { + params: { + path: { projectId }, + query: shouldIncludeDefault ? { includeDefault: "true" } : {} + } + })).pipe( + Effect.map((response) => response.snapshot) + ) export const stopProjectTask = ( projectId: string, pid: number ) => - requestText( - "POST", - `/projects/${encodeURIComponent(projectId)}/tasks/${pid}/stop` - ).pipe(Effect.asVoid) + openApiVoid((client) => + client.POST("/projects/{projectId}/tasks/{pid}/stop", { + params: { path: { pid: String(pid), projectId } } + }) + ) export const loadProjectTaskLogs = ( projectId: string, pid: number, lines = 200 ) => - requestJson( - "GET", - `/projects/${encodeURIComponent(projectId)}/tasks/${pid}/logs?lines=${lines}`, - OutputResponseSchema - ).pipe( - Effect.map((response) => response.output) - ) + openApiJsonSchema(OutputResponseSchema, (client) => + client.GET("/projects/{projectId}/tasks/{pid}/logs", { + params: { + path: { pid: String(pid), projectId }, + query: { lines: String(lines) } + } + })).pipe( + Effect.map((response) => response.output) + ) diff --git a/packages/app/src/web/api-terminal.ts b/packages/app/src/web/api-terminal.ts new file mode 100644 index 00000000..47ca25e1 --- /dev/null +++ b/packages/app/src/web/api-terminal.ts @@ -0,0 +1,183 @@ +import { Effect } from "effect" + +import { + AuthTerminalSessionResponseSchema, + ProjectTerminalSessionResponseSchema, + ProjectTerminalSessionsResponseSchema, + StartProjectTerminalSessionAcceptedResponseSchema, + TerminalSessionLookupResponseSchema, + TerminalSessionResponseSchema +} from "./api-schema.js" +import { openApiJsonSchema, openApiVoid } from "./openapi-client.js" + +export const createProjectTerminalSession = (projectKey: string) => + openApiJsonSchema( + TerminalSessionResponseSchema, + (client) => + client.POST("/projects/by-key/{projectKey}/terminal-sessions", { + params: { path: { projectKey } } + }) + ).pipe( + Effect.map((response) => ({ + project: response.project, + session: response.session + })) + ) + +export const startProjectTerminalSession = ( + projectKey: string, + requestId: string +) => + openApiJsonSchema( + StartProjectTerminalSessionAcceptedResponseSchema, + (client) => + client.POST("/projects/by-key/{projectKey}/terminal-sessions/start", { + body: { requestId }, + params: { path: { projectKey } } + }) + ) + +export const createAuthTerminalSession = ( + flow: "ClaudeOauth" | "GeminiOauth" | "GrokOauth", + label: string | null +) => + openApiJsonSchema(AuthTerminalSessionResponseSchema, (client) => + client.POST("/auth/terminal-sessions", { + body: { flow, label } + })).pipe( + Effect.map((response) => response.session) + ) + +export const deleteProjectTerminalSession = ( + projectKey: string, + sessionId: string +) => + openApiVoid((client) => + client.DELETE("/projects/by-key/{projectKey}/terminal-sessions/{sessionId}", { + params: { path: { projectKey, sessionId } } + }) + ) + +export const deleteAuthTerminalSession = (sessionId: string) => + openApiVoid((client) => + client.DELETE("/auth/terminal-sessions/{sessionId}", { + params: { path: { sessionId } } + }) + ) + +// WHY: panel UI needs only the sessions array for list rendering. +// INVARIANT: this helper intentionally projects the full terminal workspace response to sessions. +export const loadProjectTerminalSessions = (projectKey: string) => + openApiJsonSchema( + ProjectTerminalSessionsResponseSchema, + (client) => + client.GET("/projects/by-key/{projectKey}/terminal-sessions", { + params: { path: { projectKey } } + }) + ).pipe( + Effect.map((response) => response.sessions) + ) + +// WHY: SSH-link initialization needs the full terminal workspace, including activeSessionId. +// INVARIANT: this helper intentionally preserves the complete response shape. +export const loadProjectTerminalWorkspace = (projectKey: string) => + openApiJsonSchema( + ProjectTerminalSessionsResponseSchema, + (client) => + client.GET("/projects/by-key/{projectKey}/terminal-sessions", { + params: { path: { projectKey } } + }) + ) + +export const setProjectActiveTerminalSession = ( + projectKey: string, + sessionId: string +) => + openApiJsonSchema( + ProjectTerminalSessionResponseSchema, + (client) => + client.PUT("/projects/by-key/{projectKey}/terminal-sessions/active", { + body: { sessionId }, + params: { path: { projectKey } } + }) + ).pipe( + Effect.map((response) => response.session) + ) + +export const loadProjectTerminalSession = ( + projectKey: string, + sessionId: string +) => + openApiJsonSchema( + ProjectTerminalSessionResponseSchema, + (client) => + client.GET("/projects/by-key/{projectKey}/terminal-sessions/{sessionId}", { + params: { path: { projectKey, sessionId } } + }) + ).pipe( + Effect.map((response) => response.session) + ) + +export const loadTerminalSessionById = (sessionId: string) => + openApiJsonSchema(TerminalSessionLookupResponseSchema, (client) => + client.GET("/terminal-sessions/{sessionId}", { + params: { path: { sessionId } } + })) + +const invalidTerminalClosePath = (path: string): string => `Invalid terminal close path: ${path}` + +const authTerminalClosePathPattern = /^\/auth\/terminal-sessions\/([^/]+)$/u +const projectTerminalClosePathPattern = /^\/projects\/by-key\/([^/]+)\/terminal-sessions\/([^/]+)$/u + +const decodeTerminalClosePathSegment = ( + segment: string, + path: string +): Effect.Effect => + Effect.try({ + try: () => decodeURIComponent(segment), + catch: () => invalidTerminalClosePath(path) + }) + +const readTerminalClosePathMatchSegment = ( + match: RegExpExecArray, + index: number, + path: string +): Effect.Effect => { + const segment = match[index] + return segment === undefined + ? Effect.fail(invalidTerminalClosePath(path)) + : decodeTerminalClosePathSegment(segment, path) +} + +const deleteMatchedAuthTerminalSession = ( + match: RegExpExecArray, + path: string +): Effect.Effect => + readTerminalClosePathMatchSegment(match, 1, path).pipe( + Effect.flatMap((sessionId) => deleteAuthTerminalSession(sessionId)) + ) + +const deleteMatchedProjectTerminalSession = ( + match: RegExpExecArray, + path: string +): Effect.Effect => + Effect.all({ + projectKey: readTerminalClosePathMatchSegment(match, 1, path), + sessionId: readTerminalClosePathMatchSegment(match, 2, path) + }).pipe( + Effect.flatMap(({ projectKey, sessionId }) => deleteProjectTerminalSession(projectKey, sessionId)) + ) + +export const deleteTerminalSessionByPath = (path: string): Effect.Effect => { + const authMatch = authTerminalClosePathPattern.exec(path) + if (authMatch !== null) { + return deleteMatchedAuthTerminalSession(authMatch, path) + } + + const projectMatch = projectTerminalClosePathPattern.exec(path) + if (projectMatch !== null) { + return deleteMatchedProjectTerminalSession(projectMatch, path) + } + + return Effect.fail(invalidTerminalClosePath(path)) +} diff --git a/packages/app/src/web/api.ts b/packages/app/src/web/api.ts index 73ca2dfc..3b2a71ef 100644 --- a/packages/app/src/web/api.ts +++ b/packages/app/src/web/api.ts @@ -3,10 +3,10 @@ import { Effect } from "effect" import { sortSelectItemsByLaunchTime } from "../docker-git/menu-select-order.js" import type { SelectProjectRuntime } from "../docker-git/menu-types.js" import type { AuthMenuRequestBody, ProjectAuthMenuRequestBody } from "../shared/auth-menu-request.js" -import { requestJson, requestText, requestTextStream, resolveApiBaseUrl } from "./api-http.js" +import { requestJson, requestTextStream, resolveApiBaseUrl } from "./api-http.js" import { AuthSnapshotResponseSchema, - AuthTerminalSessionResponseSchema, + CodexStatusResponseSchema, GithubStatusResponseSchema, HealthResponseSchema, ProjectAuthSnapshotResponseSchema, @@ -15,12 +15,7 @@ import { ProjectPortForwardResponseSchema, ProjectPortForwardsResponseSchema, ProjectsResponseSchema, - ProjectTerminalSessionResponseSchema, - ProjectTerminalSessionsResponseSchema, - SkillerLaunchResponseSchema, - StartProjectTerminalSessionAcceptedResponseSchema, - TerminalSessionLookupResponseSchema, - TerminalSessionResponseSchema + SkillerLaunchResponseSchema } from "./api-schema.js" import type { AuthMenuFlow, @@ -30,6 +25,7 @@ import type { ProjectPortForward, ProjectSummary } from "./api-schema.js" +import { openApiJsonSchema, openApiVoid } from "./openapi-client.js" export { startCreateProject } from "./api-create-project.js" export { @@ -60,6 +56,19 @@ export { deleteProjectPrompt, loadProjectPrompts, writeProjectPrompt } from "./a export { loadPanelCloudflareTunnel, startPanelCloudflareTunnel, stopPanelCloudflareTunnel } from "./api-share.js" export { deleteProjectSkill, loadProjectSkills, projectSkillScopeToId, writeProjectSkill } from "./api-skills.js" export { loadProjectTaskLogs, loadProjectTasks, stopProjectTask } from "./api-tasks.js" +export { + createAuthTerminalSession, + createProjectTerminalSession, + deleteAuthTerminalSession, + deleteProjectTerminalSession, + deleteTerminalSessionByPath, + loadProjectTerminalSession, + loadProjectTerminalSessions, + loadProjectTerminalWorkspace, + loadTerminalSessionById, + setProjectActiveTerminalSession, + startProjectTerminalSession +} from "./api-terminal.js" export type * from "./api-types.js" @@ -105,8 +114,8 @@ export const sortDashboardProjects = ( export const loadDashboard = (): Effect.Effect => Effect.all({ - health: requestJson("GET", "/health", HealthResponseSchema), - projectsResponse: requestJson("GET", "/projects", ProjectsResponseSchema) + health: openApiJsonSchema(HealthResponseSchema, (client) => client.GET("/health")), + projectsResponse: openApiJsonSchema(ProjectsResponseSchema, (client) => client.GET("/projects")) }).pipe( Effect.map(({ health, projectsResponse }) => ({ apiBaseUrl: resolveApiBaseUrl(), @@ -134,16 +143,25 @@ export const openSkiller = (projectKey?: string, sessionId?: string) => ) export const loadProjectPortForwards = (projectId: string) => - requestJson("GET", `/projects/${encodeURIComponent(projectId)}/ports`, ProjectPortForwardsResponseSchema).pipe( - Effect.map((response) => response.forwards) - ) + openApiJsonSchema(ProjectPortForwardsResponseSchema, (client) => + client.GET("/projects/{projectId}/ports", { + params: { path: { projectId } } + })).pipe( + Effect.map((response) => response.forwards) + ) export const loadProjectBrowser = (projectId: string) => - requestJson("GET", `/projects/${encodeURIComponent(projectId)}/browser`, ProjectBrowserResponseSchema) + openApiJsonSchema(ProjectBrowserResponseSchema, (client) => + client.GET("/projects/{projectId}/browser", { + params: { path: { projectId } } + })) .pipe(Effect.map((response) => response.browser)) export const startProjectBrowser = (projectId: string) => - requestJson("POST", `/projects/${encodeURIComponent(projectId)}/browser/start`, ProjectBrowserResponseSchema) + openApiJsonSchema(ProjectBrowserResponseSchema, (client) => + client.POST("/projects/{projectId}/browser/start", { + params: { path: { projectId } } + })) .pipe(Effect.map((response) => response.browser)) export const createProjectPortForward = ( @@ -151,138 +169,59 @@ export const createProjectPortForward = ( targetPort: number, hostPort?: number ) => - requestJson( - "POST", - `/projects/${encodeURIComponent(projectId)}/ports`, - ProjectPortForwardResponseSchema, - hostPort === undefined ? { targetPort } : { hostPort, targetPort } - ).pipe( - Effect.map((response) => response.forward) - ) + openApiJsonSchema(ProjectPortForwardResponseSchema, (client) => + client.POST("/projects/{projectId}/ports", { + body: hostPort === undefined ? { targetPort } : { hostPort, targetPort }, + params: { path: { projectId } } + })).pipe( + Effect.map((response) => response.forward) + ) export const deleteProjectPortForward = ( projectId: string, targetPort: number -) => requestText("DELETE", `/projects/${encodeURIComponent(projectId)}/ports/${targetPort}`).pipe(Effect.asVoid) - -export const createProjectTerminalSession = (projectKey: string) => - requestJson( - "POST", - `/projects/by-key/${encodeURIComponent(projectKey)}/terminal-sessions`, - TerminalSessionResponseSchema - ).pipe( - Effect.map((response) => ({ - project: response.project, - session: response.session - })) - ) - -export const startProjectTerminalSession = ( - projectKey: string, - requestId: string -) => - requestJson( - "POST", - `/projects/by-key/${encodeURIComponent(projectKey)}/terminal-sessions/start`, - StartProjectTerminalSessionAcceptedResponseSchema, - { requestId } - ) - -export const createAuthTerminalSession = ( - flow: "ClaudeOauth" | "GeminiOauth" | "GrokOauth", - label: string | null -) => - requestJson( - "POST", - "/auth/terminal-sessions", - AuthTerminalSessionResponseSchema, - { flow, label } - ).pipe( - Effect.map((response) => response.session) - ) - -export const deleteProjectTerminalSession = ( - projectKey: string, - sessionId: string -) => - requestText( - "DELETE", - `/projects/by-key/${encodeURIComponent(projectKey)}/terminal-sessions/${encodeURIComponent(sessionId)}` - ) - .pipe( - Effect.asVoid - ) - -export const loadProjectTerminalSessions = (projectKey: string) => - requestJson( - "GET", - `/projects/by-key/${encodeURIComponent(projectKey)}/terminal-sessions`, - ProjectTerminalSessionsResponseSchema - ).pipe( - Effect.map((response) => response.sessions) - ) - -export const loadProjectTerminalWorkspace = (projectKey: string) => - requestJson( - "GET", - `/projects/by-key/${encodeURIComponent(projectKey)}/terminal-sessions`, - ProjectTerminalSessionsResponseSchema - ) - -export const setProjectActiveTerminalSession = ( - projectKey: string, - sessionId: string -) => - requestJson( - "PUT", - `/projects/by-key/${encodeURIComponent(projectKey)}/terminal-sessions/active`, - ProjectTerminalSessionResponseSchema, - { sessionId } - ).pipe( - Effect.map((response) => response.session) - ) - -export const loadProjectTerminalSession = ( - projectKey: string, - sessionId: string ) => - requestJson( - "GET", - `/projects/by-key/${encodeURIComponent(projectKey)}/terminal-sessions/${encodeURIComponent(sessionId)}`, - ProjectTerminalSessionResponseSchema - ).pipe( - Effect.map((response) => response.session) - ) - -export const loadTerminalSessionById = (sessionId: string) => - requestJson( - "GET", - `/terminal-sessions/${encodeURIComponent(sessionId)}`, - TerminalSessionLookupResponseSchema + openApiVoid((client) => + client.DELETE("/projects/{projectId}/ports/{targetPort}", { + params: { path: { projectId, targetPort: String(targetPort) } } + }) ) -export const deleteTerminalSessionByPath = (path: string) => requestText("DELETE", path).pipe(Effect.asVoid) - export const downProject = (projectId: string) => - requestText("POST", `/projects/${encodeURIComponent(projectId)}/down`).pipe(Effect.asVoid) + openApiVoid((client) => + client.POST("/projects/{projectId}/down", { + params: { path: { projectId } } + }) + ) export const deleteProject = (projectId: string) => - requestText("DELETE", `/projects/${encodeURIComponent(projectId)}`).pipe(Effect.asVoid) + openApiVoid((client) => + client.DELETE("/projects/{projectId}", { + params: { path: { projectId } } + }) + ) -export const downAllProjects = () => requestText("POST", "/projects/down-all").pipe(Effect.asVoid) +export const downAllProjects = () => openApiVoid((client) => client.POST("/projects/down-all")) export const applyAllProjects = (shouldApplyActiveOnly: boolean) => - requestText("POST", "/projects/apply-all", { activeOnly: shouldApplyActiveOnly }).pipe(Effect.asVoid) + openApiVoid((client) => + client.POST("/projects/apply-all", { + body: { activeOnly: shouldApplyActiveOnly } + }) + ) export const loadGithubStatus = () => - requestJson("GET", "/auth/github/status", GithubStatusResponseSchema).pipe( + openApiJsonSchema(GithubStatusResponseSchema, (client) => client.GET("/auth/github/status")).pipe( Effect.map((response) => response.status) ) export const loginGithub = (label: string | null) => - requestJson("POST", "/auth/github/login", GithubStatusResponseSchema, { label }).pipe( - Effect.map((response) => response.status) - ) + openApiJsonSchema(GithubStatusResponseSchema, (client) => + client.POST("/auth/github/login", { + body: { label } + })).pipe( + Effect.map((response) => response.status) + ) export const loginGithubStream = (label: string | null, onChunk: (chunk: string) => void) => requestTextStream({ @@ -301,7 +240,10 @@ export const loginCodexStream = (label: string | null, onChunk: (chunk: string) }) export const logoutCodex = (label: string | null) => - requestText("POST", "/auth/codex/logout", { label }).pipe(Effect.asVoid) + openApiJsonSchema(CodexStatusResponseSchema, (client) => + client.POST("/auth/codex/logout", { + body: { label } + })).pipe(Effect.asVoid) export const loadProjectEvents = ( projectId: string, @@ -316,36 +258,34 @@ export const loadProjectEvents = ( ) export const loadAuthSnapshot = () => - requestJson("GET", "/auth/menu", AuthSnapshotResponseSchema).pipe( + openApiJsonSchema(AuthSnapshotResponseSchema, (client) => client.GET("/auth/menu")).pipe( Effect.map((response) => response.snapshot) ) export const runAuthMenuFlow = (request: AuthMenuRequestBody & { readonly flow: AuthMenuFlow }) => - requestJson("POST", "/auth/menu", AuthSnapshotResponseSchema, request).pipe( + openApiJsonSchema(AuthSnapshotResponseSchema, (client) => client.POST("/auth/menu", { body: request })).pipe( Effect.map((response) => response.snapshot) ) export const loadProjectAuthSnapshot = (projectId: string) => - requestJson( - "GET", - `/projects/${encodeURIComponent(projectId)}/auth/menu`, - ProjectAuthSnapshotResponseSchema - ).pipe( - Effect.map((response) => response.snapshot) - ) + openApiJsonSchema(ProjectAuthSnapshotResponseSchema, (client) => + client.GET("/projects/{projectId}/auth/menu", { + params: { path: { projectId } } + })).pipe( + Effect.map((response) => response.snapshot) + ) export const runProjectAuthFlow = ( projectId: string, request: ProjectAuthMenuRequestBody & { readonly flow: ProjectAuthFlow } ) => - requestJson( - "POST", - `/projects/${encodeURIComponent(projectId)}/auth/menu`, - ProjectAuthSnapshotResponseSchema, - request - ).pipe( - Effect.map((response) => response.snapshot) - ) + openApiJsonSchema(ProjectAuthSnapshotResponseSchema, (client) => + client.POST("/projects/{projectId}/auth/menu", { + body: request, + params: { path: { projectId } } + })).pipe( + Effect.map((response) => response.snapshot) + ) export { resolveApiBaseUrl } from "./api-http.js" diff --git a/packages/app/src/web/openapi-client.ts b/packages/app/src/web/openapi-client.ts new file mode 100644 index 00000000..bdb26bbf --- /dev/null +++ b/packages/app/src/web/openapi-client.ts @@ -0,0 +1,46 @@ +import { makeDockerGitOpenApiRuntime } from "@prover-coder-ai/docker-git-openapi" + +import { resolveApiBaseUrl } from "./api-http.js" + +const openApiRuntime = makeDockerGitOpenApiRuntime({ + resolveBaseUrl: resolveApiBaseUrl +}) + +/** + * Executes a docker-git OpenAPI JSON request against the current browser API base URL. + * + * @pure false - performs HTTP IO when the returned Effect is run. + * @effect openapi-fetch request wrapped in Effect. + * @invariant the shared OpenAPI runtime owns transport decoding and error rendering. + * @precondition request uses generated docker-git OpenAPI paths. + * @postcondition success contains the endpoint data branch as a JSON transport value. + * @complexity O(n)/O(n) for error rendering, O(1)/O(1) on local success handling. + * @throws Never; failures are returned in the Effect error channel. + */ +export const openApiJson: typeof openApiRuntime.openApiJson = openApiRuntime.openApiJson + +/** + * Executes a docker-git OpenAPI request and decodes the response with an Effect Schema. + * + * @pure false - performs HTTP IO and boundary decoding when the returned Effect is run. + * @effect openapi-fetch request plus synchronous Schema decoding. + * @invariant generated transport shapes are decoded before leaving the web API boundary. + * @precondition schema matches the endpoint success response contract. + * @postcondition success contains the schema-decoded DTO expected by UI code. + * @complexity O(n)/O(n) where n is the decoded response size. + * @throws Never; failures are returned in the Effect error channel. + */ +export const openApiJsonSchema: typeof openApiRuntime.openApiJsonSchema = openApiRuntime.openApiJsonSchema + +/** + * Executes a docker-git OpenAPI request whose success response has no body. + * + * @pure false - performs HTTP IO when the returned Effect is run. + * @effect openapi-fetch request wrapped in Effect. + * @invariant only the HTTP success status determines the void success branch. + * @precondition request targets an endpoint whose successful response has no content. + * @postcondition success returns void without exposing transport details. + * @complexity O(n)/O(n) for error rendering, O(1)/O(1) on local success handling. + * @throws Never; failures are returned in the Effect error channel. + */ +export const openApiVoid: typeof openApiRuntime.openApiVoid = openApiRuntime.openApiVoid diff --git a/packages/app/tests/docker-git/api-create-project.test.ts b/packages/app/tests/docker-git/api-create-project.test.ts new file mode 100644 index 00000000..21b944c4 --- /dev/null +++ b/packages/app/tests/docker-git/api-create-project.test.ts @@ -0,0 +1,78 @@ +import { describe, expect, it } from "@effect/vitest" +import { Effect } from "effect" +import * as fc from "fast-check" + +import { createProjectAcceptedBody } from "../../src/web/api-create-project.js" +import type { CreateProjectRequestDraft } from "../../src/web/api-project-create-body.js" + +const projectDraft = { + cpuLimit: "80%", + enableMcpPlaywright: true, + force: false, + forceEnv: false, + gpu: "none", + outDir: "/home/dev/.docker-git/octocat/hello-world", + playwrightCpuLimit: "40%", + playwrightRamLimit: "512m", + ramLimit: "2g", + repoRef: "main", + repoUrl: "https://github.com/octocat/hello-world.git", + up: true +} satisfies CreateProjectRequestDraft + +const hasOwnField = (value: object, key: string): boolean => Object.prototype.hasOwnProperty.call(value, key) +const optionalPlaywrightLimitArbitrary = fc.option(fc.string(), { nil: undefined }) + +describe("api create project request body", () => { + it.effect("preserves async create invariants for arbitrary Playwright resource limits", () => + Effect.sync(() => { + fc.assert( + fc.property( + optionalPlaywrightLimitArbitrary, + optionalPlaywrightLimitArbitrary, + (playwrightCpuLimit, playwrightRamLimit) => { + const draft: CreateProjectRequestDraft = { + ...projectDraft, + playwrightCpuLimit, + playwrightRamLimit + } + const body = createProjectAcceptedBody(draft) + + expect(body.async).toBe(true) + expect(body.openSsh).toBe(false) + expect(body.useManagedAuthorizedKeys).toBe(true) + expect(hasOwnField(body, "playwrightCpuLimit")).toBe(playwrightCpuLimit !== undefined) + expect(hasOwnField(body, "playwrightRamLimit")).toBe(playwrightRamLimit !== undefined) + if (playwrightCpuLimit !== undefined) { + expect(body.playwrightCpuLimit).toBe(playwrightCpuLimit) + } + if (playwrightRamLimit !== undefined) { + expect(body.playwrightRamLimit).toBe(playwrightRamLimit) + } + } + ), + { numRuns: 50 } + ) + })) + + it.effect("serializes async create requests with Playwright resource limits", () => + Effect.sync(() => { + expect(createProjectAcceptedBody(projectDraft)).toEqual({ + async: true, + cpuLimit: "80%", + enableMcpPlaywright: true, + force: false, + forceEnv: false, + gpu: "none", + openSsh: false, + outDir: "/home/dev/.docker-git/octocat/hello-world", + playwrightCpuLimit: "40%", + playwrightRamLimit: "512m", + ramLimit: "2g", + repoRef: "main", + repoUrl: "https://github.com/octocat/hello-world.git", + up: true, + useManagedAuthorizedKeys: true + }) + })) +}) diff --git a/packages/app/tests/docker-git/api-terminal.test.ts b/packages/app/tests/docker-git/api-terminal.test.ts new file mode 100644 index 00000000..4d5e2bed --- /dev/null +++ b/packages/app/tests/docker-git/api-terminal.test.ts @@ -0,0 +1,87 @@ +import { describe, expect, it } from "@effect/vitest" +import { Effect } from "effect" +import { beforeEach, vi } from "vitest" + +import { deleteTerminalSessionByPath } from "../../src/web/api-terminal.js" + +type CapturedDeleteRequest = { + readonly params: Readonly> + readonly route: string +} + +type MinimalDeleteClient = { + readonly DELETE: ( + route: string, + options: { readonly params: { readonly path: Readonly> } } + ) => void +} + +const capturedDeleteRequests = vi.hoisted((): Array => []) +const openApiVoidMock = vi.hoisted(() => + vi.fn((request: (client: MinimalDeleteClient) => void) => { + const client: MinimalDeleteClient = { + DELETE: (route, options) => { + capturedDeleteRequests.push({ + params: options.params.path, + route + }) + } + } + request(client) + return Effect.void + }) +) + +vi.mock("../../src/web/openapi-client.js", () => ({ + openApiJsonSchema: vi.fn(), + openApiVoid: openApiVoidMock +})) + +describe("api terminal helpers", () => { + beforeEach(() => { + capturedDeleteRequests.length = 0 + openApiVoidMock.mockClear() + }) + + it.effect("routes auth terminal close paths through the typed OpenAPI endpoint", () => + deleteTerminalSessionByPath("/auth/terminal-sessions/auth-session-1").pipe( + Effect.tap(() => + Effect.sync(() => { + expect(capturedDeleteRequests).toEqual([ + { + params: { sessionId: "auth-session-1" }, + route: "/auth/terminal-sessions/{sessionId}" + } + ]) + }) + ) + )) + + it.effect("routes project terminal close paths through the typed OpenAPI endpoint", () => + deleteTerminalSessionByPath("/projects/by-key/octocat%2Fhello-world/terminal-sessions/session-1").pipe( + Effect.tap(() => + Effect.sync(() => { + expect(capturedDeleteRequests).toEqual([ + { + params: { + projectKey: "octocat/hello-world", + sessionId: "session-1" + }, + route: "/projects/by-key/{projectKey}/terminal-sessions/{sessionId}" + } + ]) + }) + ) + )) + + it.effect("rejects unsupported terminal close paths before issuing a request", () => + Effect.gen(function*(_) { + const result = yield* _(Effect.either(deleteTerminalSessionByPath("/terminal-sessions/session-1"))) + + expect(result._tag).toBe("Left") + if (result._tag === "Left") { + expect(result.left).toBe("Invalid terminal close path: /terminal-sessions/session-1") + } + expect(capturedDeleteRequests).toEqual([]) + })) +}) diff --git a/packages/app/tests/docker-git/controller-resource-limits.test.ts b/packages/app/tests/docker-git/controller-resource-limits.test.ts index 2a78d0f6..5b33b933 100644 --- a/packages/app/tests/docker-git/controller-resource-limits.test.ts +++ b/packages/app/tests/docker-git/controller-resource-limits.test.ts @@ -120,6 +120,13 @@ describe("API Dockerfile controller tooling install", () => { expect(contents).toContain("test \"$(bun --version)\" = \"1.3.11\"") expect(contents).toContain("node-gyp --version") })) + + it.effect("copies generated OpenAPI package metadata into workspace dependency install stage", () => + Effect.gen(function*(_) { + const contents = yield* _(readComposeFile("packages/api/Dockerfile")) + expect(contents).toContain("packages/openapi") + expect(contents).toContain("COPY packages/openapi/package.json ./packages/openapi/package.json") + })) }) describe("OpenCode E2E auth bootstrap", () => { diff --git a/packages/openapi/openapi.json b/packages/openapi/openapi.json new file mode 100644 index 00000000..1e797e52 --- /dev/null +++ b/packages/openapi/openapi.json @@ -0,0 +1,22055 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "docker-git API", + "version": "1.0.0", + "description": "Effect contract for docker-git JSON REST endpoints." + }, + "paths": { + "/health": { + "get": { + "tags": [ + "core" + ], + "operationId": "core.health", + "parameters": [], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "cwd", + "ok", + "projectsRoot", + "revision" + ], + "properties": { + "cwd": { + "type": "string" + }, + "ok": { + "type": "boolean" + }, + "projectsRoot": { + "type": "string" + }, + "revision": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/projects": { + "get": { + "tags": [ + "projects" + ], + "operationId": "projects.listProjects", + "parameters": [], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "projects" + ], + "properties": { + "projects": { + "type": "array", + "items": { + "type": "object", + "required": [ + "displayName", + "id", + "projectKey", + "repoRef", + "repoUrl", + "sshSessions", + "startedAtEpochMs", + "startedAtIso", + "status", + "statusLabel" + ], + "properties": { + "clonedOnHostname": { + "type": "string" + }, + "containerName": { + "type": "string" + }, + "displayName": { + "type": "string" + }, + "id": { + "type": "string" + }, + "projectKey": { + "type": "string" + }, + "repoRef": { + "type": "string" + }, + "repoUrl": { + "type": "string" + }, + "sshSessions": { + "type": "number" + }, + "startedAtEpochMs": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "startedAtIso": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "status": { + "type": "string", + "enum": [ + "running", + "stopped", + "unknown" + ] + }, + "statusLabel": { + "type": "string" + } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + }, + "post": { + "tags": [ + "projects" + ], + "operationId": "projects.createProject", + "parameters": [], + "security": [], + "responses": { + "201": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "project" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "project": { + "type": "object", + "required": [ + "containerName", + "displayName", + "id", + "projectKey", + "repoRef", + "repoUrl", + "sshSessions", + "startedAtEpochMs", + "startedAtIso", + "status", + "statusLabel", + "authorizedKeysExists", + "authorizedKeysPath", + "codexAuthPath", + "codexHome", + "envGlobalPath", + "envProjectPath", + "gpu", + "projectDir", + "serviceName", + "sshCommand", + "sshPort", + "sshUser", + "targetDir" + ], + "properties": { + "clonedOnHostname": { + "type": "string" + }, + "containerName": { + "type": "string" + }, + "displayName": { + "type": "string" + }, + "id": { + "type": "string" + }, + "projectKey": { + "type": "string" + }, + "repoRef": { + "type": "string" + }, + "repoUrl": { + "type": "string" + }, + "sshSessions": { + "type": "number" + }, + "startedAtEpochMs": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "startedAtIso": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "status": { + "type": "string", + "enum": [ + "running", + "stopped", + "unknown" + ] + }, + "statusLabel": { + "type": "string" + }, + "authorizedKeysExists": { + "type": "boolean" + }, + "authorizedKeysPath": { + "type": "string" + }, + "codexAuthPath": { + "type": "string" + }, + "codexHome": { + "type": "string" + }, + "envGlobalPath": { + "type": "string" + }, + "envProjectPath": { + "type": "string" + }, + "gpu": { + "type": "string", + "enum": [ + "none", + "all" + ] + }, + "projectDir": { + "type": "string" + }, + "serviceName": { + "type": "string" + }, + "sshCommand": { + "type": "string" + }, + "sshPort": { + "type": "number" + }, + "sshUser": { + "type": "string" + }, + "targetDir": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "202": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "accepted", + "cursor", + "projectId" + ], + "properties": { + "accepted": { + "type": "boolean", + "enum": [ + true + ] + }, + "cursor": { + "type": "number" + }, + "projectId": { + "type": "string" + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [], + "properties": { + "repoUrl": { + "type": "string" + }, + "repoRef": { + "type": "string" + }, + "targetDir": { + "type": "string" + }, + "sshPort": { + "type": "string" + }, + "sshUser": { + "type": "string" + }, + "containerName": { + "type": "string" + }, + "serviceName": { + "type": "string" + }, + "volumeName": { + "type": "string" + }, + "secretsRoot": { + "type": "string" + }, + "authorizedKeysPath": { + "type": "string" + }, + "authorizedKeysContents": { + "type": "string" + }, + "useManagedAuthorizedKeys": { + "type": "boolean" + }, + "envGlobalPath": { + "type": "string" + }, + "envProjectPath": { + "type": "string" + }, + "codexAuthPath": { + "type": "string" + }, + "codexHome": { + "type": "string" + }, + "cpuLimit": { + "type": "string" + }, + "ramLimit": { + "type": "string" + }, + "playwrightCpuLimit": { + "type": "string" + }, + "playwrightRamLimit": { + "type": "string" + }, + "gpu": { + "type": "string", + "enum": [ + "none", + "all" + ] + }, + "dockerNetworkMode": { + "type": "string" + }, + "dockerSharedNetworkName": { + "type": "string" + }, + "enableMcpPlaywright": { + "type": "boolean" + }, + "outDir": { + "type": "string" + }, + "gitTokenLabel": { + "type": "string" + }, + "skipGithubAuth": { + "type": "boolean" + }, + "codexTokenLabel": { + "type": "string" + }, + "claudeTokenLabel": { + "type": "string" + }, + "geminiTokenLabel": { + "type": "string" + }, + "grokTokenLabel": { + "type": "string" + }, + "agentAutoMode": { + "type": "string" + }, + "up": { + "type": "boolean" + }, + "openSsh": { + "type": "boolean" + }, + "force": { + "type": "boolean" + }, + "forceEnv": { + "type": "boolean" + }, + "waitForClone": { + "type": "boolean" + }, + "async": { + "type": "boolean" + }, + "clonedOnHostname": { + "type": "string", + "description": "a string matching the pattern ^(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?)(?:\\.[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$", + "title": "maxLength(253)", + "minLength": 1, + "maxLength": 253, + "pattern": "^(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?)(?:\\.[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$" + } + }, + "additionalProperties": false + } + } + }, + "required": true + } + } + }, + "/projects/apply-all": { + "post": { + "tags": [ + "projects" + ], + "operationId": "projects.applyAllProjects", + "parameters": [], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ok" + ], + "properties": { + "ok": { + "type": "boolean", + "enum": [ + true + ] + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [], + "properties": { + "activeOnly": { + "type": "boolean" + } + }, + "additionalProperties": false + } + } + }, + "required": true + } + } + }, + "/projects/down-all": { + "post": { + "tags": [ + "projects" + ], + "operationId": "projects.downAllProjects", + "parameters": [], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ok" + ], + "properties": { + "ok": { + "type": "boolean", + "enum": [ + true + ] + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/projects/{projectId}": { + "get": { + "tags": [ + "projects" + ], + "operationId": "projects.getProject", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "project" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "project": { + "type": "object", + "required": [ + "containerName", + "displayName", + "id", + "projectKey", + "repoRef", + "repoUrl", + "sshSessions", + "startedAtEpochMs", + "startedAtIso", + "status", + "statusLabel", + "authorizedKeysExists", + "authorizedKeysPath", + "codexAuthPath", + "codexHome", + "envGlobalPath", + "envProjectPath", + "gpu", + "projectDir", + "serviceName", + "sshCommand", + "sshPort", + "sshUser", + "targetDir" + ], + "properties": { + "clonedOnHostname": { + "type": "string" + }, + "containerName": { + "type": "string" + }, + "displayName": { + "type": "string" + }, + "id": { + "type": "string" + }, + "projectKey": { + "type": "string" + }, + "repoRef": { + "type": "string" + }, + "repoUrl": { + "type": "string" + }, + "sshSessions": { + "type": "number" + }, + "startedAtEpochMs": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "startedAtIso": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "status": { + "type": "string", + "enum": [ + "running", + "stopped", + "unknown" + ] + }, + "statusLabel": { + "type": "string" + }, + "authorizedKeysExists": { + "type": "boolean" + }, + "authorizedKeysPath": { + "type": "string" + }, + "codexAuthPath": { + "type": "string" + }, + "codexHome": { + "type": "string" + }, + "envGlobalPath": { + "type": "string" + }, + "envProjectPath": { + "type": "string" + }, + "gpu": { + "type": "string", + "enum": [ + "none", + "all" + ] + }, + "projectDir": { + "type": "string" + }, + "serviceName": { + "type": "string" + }, + "sshCommand": { + "type": "string" + }, + "sshPort": { + "type": "number" + }, + "sshUser": { + "type": "string" + }, + "targetDir": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + }, + "delete": { + "tags": [ + "projects" + ], + "operationId": "projects.deleteProject", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ok" + ], + "properties": { + "ok": { + "type": "boolean", + "enum": [ + true + ] + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/projects/{projectId}/down": { + "post": { + "tags": [ + "projects" + ], + "operationId": "projects.downProject", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ok" + ], + "properties": { + "ok": { + "type": "boolean", + "enum": [ + true + ] + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/projects/{projectId}/apply": { + "post": { + "tags": [ + "projects" + ], + "operationId": "projects.applyProject", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "project" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "project": { + "type": "object", + "required": [ + "containerName", + "displayName", + "id", + "projectKey", + "repoRef", + "repoUrl", + "sshSessions", + "startedAtEpochMs", + "startedAtIso", + "status", + "statusLabel", + "authorizedKeysExists", + "authorizedKeysPath", + "codexAuthPath", + "codexHome", + "envGlobalPath", + "envProjectPath", + "gpu", + "projectDir", + "serviceName", + "sshCommand", + "sshPort", + "sshUser", + "targetDir" + ], + "properties": { + "clonedOnHostname": { + "type": "string" + }, + "containerName": { + "type": "string" + }, + "displayName": { + "type": "string" + }, + "id": { + "type": "string" + }, + "projectKey": { + "type": "string" + }, + "repoRef": { + "type": "string" + }, + "repoUrl": { + "type": "string" + }, + "sshSessions": { + "type": "number" + }, + "startedAtEpochMs": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "startedAtIso": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "status": { + "type": "string", + "enum": [ + "running", + "stopped", + "unknown" + ] + }, + "statusLabel": { + "type": "string" + }, + "authorizedKeysExists": { + "type": "boolean" + }, + "authorizedKeysPath": { + "type": "string" + }, + "codexAuthPath": { + "type": "string" + }, + "codexHome": { + "type": "string" + }, + "envGlobalPath": { + "type": "string" + }, + "envProjectPath": { + "type": "string" + }, + "gpu": { + "type": "string", + "enum": [ + "none", + "all" + ] + }, + "projectDir": { + "type": "string" + }, + "serviceName": { + "type": "string" + }, + "sshCommand": { + "type": "string" + }, + "sshPort": { + "type": "number" + }, + "sshUser": { + "type": "string" + }, + "targetDir": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [], + "properties": { + "cpuLimit": { + "type": "string" + }, + "ramLimit": { + "type": "string" + }, + "playwrightCpuLimit": { + "type": "string" + }, + "playwrightRamLimit": { + "type": "string" + }, + "gpu": { + "type": "string", + "enum": [ + "none", + "all" + ] + } + }, + "additionalProperties": false + } + } + }, + "required": true + } + } + }, + "/projects/{projectId}/up": { + "post": { + "tags": [ + "projects" + ], + "operationId": "projects.upProject", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "project" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "project": { + "type": "object", + "required": [ + "containerName", + "displayName", + "id", + "projectKey", + "repoRef", + "repoUrl", + "sshSessions", + "startedAtEpochMs", + "startedAtIso", + "status", + "statusLabel", + "authorizedKeysExists", + "authorizedKeysPath", + "codexAuthPath", + "codexHome", + "envGlobalPath", + "envProjectPath", + "gpu", + "projectDir", + "serviceName", + "sshCommand", + "sshPort", + "sshUser", + "targetDir" + ], + "properties": { + "clonedOnHostname": { + "type": "string" + }, + "containerName": { + "type": "string" + }, + "displayName": { + "type": "string" + }, + "id": { + "type": "string" + }, + "projectKey": { + "type": "string" + }, + "repoRef": { + "type": "string" + }, + "repoUrl": { + "type": "string" + }, + "sshSessions": { + "type": "number" + }, + "startedAtEpochMs": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "startedAtIso": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "status": { + "type": "string", + "enum": [ + "running", + "stopped", + "unknown" + ] + }, + "statusLabel": { + "type": "string" + }, + "authorizedKeysExists": { + "type": "boolean" + }, + "authorizedKeysPath": { + "type": "string" + }, + "codexAuthPath": { + "type": "string" + }, + "codexHome": { + "type": "string" + }, + "envGlobalPath": { + "type": "string" + }, + "envProjectPath": { + "type": "string" + }, + "gpu": { + "type": "string", + "enum": [ + "none", + "all" + ] + }, + "projectDir": { + "type": "string" + }, + "serviceName": { + "type": "string" + }, + "sshCommand": { + "type": "string" + }, + "sshPort": { + "type": "number" + }, + "sshUser": { + "type": "string" + }, + "targetDir": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [], + "properties": { + "authorizedKeysContents": { + "type": "string" + }, + "useManagedAuthorizedKeys": { + "type": "boolean" + } + }, + "additionalProperties": false + } + } + }, + "required": true + } + } + }, + "/projects/{projectId}/resume": { + "post": { + "tags": [ + "projects" + ], + "operationId": "projects.resumeProject", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "project" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "project": { + "type": "object", + "required": [ + "containerName", + "displayName", + "id", + "projectKey", + "repoRef", + "repoUrl", + "sshSessions", + "startedAtEpochMs", + "startedAtIso", + "status", + "statusLabel", + "authorizedKeysExists", + "authorizedKeysPath", + "codexAuthPath", + "codexHome", + "envGlobalPath", + "envProjectPath", + "gpu", + "projectDir", + "serviceName", + "sshCommand", + "sshPort", + "sshUser", + "targetDir" + ], + "properties": { + "clonedOnHostname": { + "type": "string" + }, + "containerName": { + "type": "string" + }, + "displayName": { + "type": "string" + }, + "id": { + "type": "string" + }, + "projectKey": { + "type": "string" + }, + "repoRef": { + "type": "string" + }, + "repoUrl": { + "type": "string" + }, + "sshSessions": { + "type": "number" + }, + "startedAtEpochMs": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "startedAtIso": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "status": { + "type": "string", + "enum": [ + "running", + "stopped", + "unknown" + ] + }, + "statusLabel": { + "type": "string" + }, + "authorizedKeysExists": { + "type": "boolean" + }, + "authorizedKeysPath": { + "type": "string" + }, + "codexAuthPath": { + "type": "string" + }, + "codexHome": { + "type": "string" + }, + "envGlobalPath": { + "type": "string" + }, + "envProjectPath": { + "type": "string" + }, + "gpu": { + "type": "string", + "enum": [ + "none", + "all" + ] + }, + "projectDir": { + "type": "string" + }, + "serviceName": { + "type": "string" + }, + "sshCommand": { + "type": "string" + }, + "sshPort": { + "type": "number" + }, + "sshUser": { + "type": "string" + }, + "targetDir": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/projects/{projectId}/suspend": { + "post": { + "tags": [ + "projects" + ], + "operationId": "projects.suspendProject", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "project" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "project": { + "type": "object", + "required": [ + "containerName", + "displayName", + "id", + "projectKey", + "repoRef", + "repoUrl", + "sshSessions", + "startedAtEpochMs", + "startedAtIso", + "status", + "statusLabel", + "authorizedKeysExists", + "authorizedKeysPath", + "codexAuthPath", + "codexHome", + "envGlobalPath", + "envProjectPath", + "gpu", + "projectDir", + "serviceName", + "sshCommand", + "sshPort", + "sshUser", + "targetDir" + ], + "properties": { + "clonedOnHostname": { + "type": "string" + }, + "containerName": { + "type": "string" + }, + "displayName": { + "type": "string" + }, + "id": { + "type": "string" + }, + "projectKey": { + "type": "string" + }, + "repoRef": { + "type": "string" + }, + "repoUrl": { + "type": "string" + }, + "sshSessions": { + "type": "number" + }, + "startedAtEpochMs": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "startedAtIso": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "status": { + "type": "string", + "enum": [ + "running", + "stopped", + "unknown" + ] + }, + "statusLabel": { + "type": "string" + }, + "authorizedKeysExists": { + "type": "boolean" + }, + "authorizedKeysPath": { + "type": "string" + }, + "codexAuthPath": { + "type": "string" + }, + "codexHome": { + "type": "string" + }, + "envGlobalPath": { + "type": "string" + }, + "envProjectPath": { + "type": "string" + }, + "gpu": { + "type": "string", + "enum": [ + "none", + "all" + ] + }, + "projectDir": { + "type": "string" + }, + "serviceName": { + "type": "string" + }, + "sshCommand": { + "type": "string" + }, + "sshPort": { + "type": "number" + }, + "sshUser": { + "type": "string" + }, + "targetDir": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/projects/{projectId}/ps": { + "get": { + "tags": [ + "projects" + ], + "operationId": "projects.projectPs", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "output" + ], + "properties": { + "output": { + "type": "string" + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/projects/{projectId}/logs": { + "get": { + "tags": [ + "projects" + ], + "operationId": "projects.projectLogs", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "output" + ], + "properties": { + "output": { + "type": "string" + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/projects/{projectId}/ports": { + "get": { + "tags": [ + "projectPorts" + ], + "operationId": "projectPorts.listProjectPorts", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "forwards" + ], + "properties": { + "forwards": { + "type": "array", + "items": { + "type": "object", + "required": [ + "bindHost", + "containerName", + "createdAt", + "hostPort", + "id", + "projectId", + "projectKey", + "proxyPath", + "publicHost", + "status", + "targetContainerName", + "targetPort", + "url" + ], + "properties": { + "bindHost": { + "type": "string" + }, + "containerName": { + "type": "string" + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "hostPort": { + "type": "number" + }, + "id": { + "type": "string" + }, + "projectId": { + "type": "string" + }, + "projectKey": { + "type": "string" + }, + "proxyPath": { + "type": "string" + }, + "publicHost": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "running", + "stopped", + "unknown" + ] + }, + "targetContainerName": { + "type": "string" + }, + "targetPort": { + "type": "number" + }, + "url": { + "type": "string" + } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + }, + "post": { + "tags": [ + "projectPorts" + ], + "operationId": "projectPorts.createProjectPort", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "201": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "forward" + ], + "properties": { + "forward": { + "type": "object", + "required": [ + "bindHost", + "containerName", + "createdAt", + "hostPort", + "id", + "projectId", + "projectKey", + "proxyPath", + "publicHost", + "status", + "targetContainerName", + "targetPort", + "url" + ], + "properties": { + "bindHost": { + "type": "string" + }, + "containerName": { + "type": "string" + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "hostPort": { + "type": "number" + }, + "id": { + "type": "string" + }, + "projectId": { + "type": "string" + }, + "projectKey": { + "type": "string" + }, + "proxyPath": { + "type": "string" + }, + "publicHost": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "running", + "stopped", + "unknown" + ] + }, + "targetContainerName": { + "type": "string" + }, + "targetPort": { + "type": "number" + }, + "url": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "targetPort" + ], + "properties": { + "hostPort": { + "type": "number" + }, + "targetPort": { + "type": "number" + } + }, + "additionalProperties": false + } + } + }, + "required": true + } + } + }, + "/projects/{projectId}/ports/{targetPort}": { + "delete": { + "tags": [ + "projectPorts" + ], + "operationId": "projectPorts.deleteProjectPort", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + }, + { + "name": "targetPort", + "in": "path", + "schema": { + "$ref": "#/components/schemas/NumberFromString" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ok" + ], + "properties": { + "ok": { + "type": "boolean", + "enum": [ + true + ] + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/projects/{projectId}/browser": { + "get": { + "tags": [ + "projectBrowser" + ], + "operationId": "projectBrowser.readProjectBrowser", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "browser" + ], + "properties": { + "browser": { + "type": "object", + "required": [ + "cdpPath", + "cdpUrl", + "containerName", + "noVncPath", + "noVncUrl", + "projectId", + "projectKey", + "status" + ], + "properties": { + "cdpPath": { + "type": "string" + }, + "cdpUrl": { + "type": "string" + }, + "containerName": { + "type": "string" + }, + "noVncPath": { + "type": "string" + }, + "noVncUrl": { + "type": "string" + }, + "projectId": { + "type": "string" + }, + "projectKey": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "running", + "stopped", + "missing", + "unknown" + ] + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/projects/{projectId}/browser/start": { + "post": { + "tags": [ + "projectBrowser" + ], + "operationId": "projectBrowser.startProjectBrowser", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "browser" + ], + "properties": { + "browser": { + "type": "object", + "required": [ + "cdpPath", + "cdpUrl", + "containerName", + "noVncPath", + "noVncUrl", + "projectId", + "projectKey", + "status" + ], + "properties": { + "cdpPath": { + "type": "string" + }, + "cdpUrl": { + "type": "string" + }, + "containerName": { + "type": "string" + }, + "noVncPath": { + "type": "string" + }, + "noVncUrl": { + "type": "string" + }, + "projectId": { + "type": "string" + }, + "projectKey": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "running", + "stopped", + "missing", + "unknown" + ] + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/projects/{projectId}/databases/profiles": { + "get": { + "tags": [ + "projectDatabases" + ], + "operationId": "projectDatabases.listDatabaseProfiles", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "profiles" + ], + "properties": { + "profiles": { + "type": "array", + "items": { + "type": "object", + "required": [ + "createdAt", + "database", + "engine", + "host", + "id", + "label", + "maskedConnectionString", + "port", + "updatedAt", + "user" + ], + "properties": { + "createdAt": { + "type": "string" + }, + "database": { + "type": "string" + }, + "engine": { + "type": "string", + "enum": [ + "postgres", + "mysql", + "mariadb" + ] + }, + "host": { + "type": "string" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "maskedConnectionString": { + "type": "string" + }, + "port": { + "type": "number" + }, + "updatedAt": { + "type": "string" + }, + "user": { + "type": "string" + } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + }, + "post": { + "tags": [ + "projectDatabases" + ], + "operationId": "projectDatabases.saveDatabaseProfile", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "201": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "profile" + ], + "properties": { + "profile": { + "type": "object", + "required": [ + "createdAt", + "database", + "engine", + "host", + "id", + "label", + "maskedConnectionString", + "port", + "updatedAt", + "user" + ], + "properties": { + "createdAt": { + "type": "string" + }, + "database": { + "type": "string" + }, + "engine": { + "type": "string", + "enum": [ + "postgres", + "mysql", + "mariadb" + ] + }, + "host": { + "type": "string" + }, + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "maskedConnectionString": { + "type": "string" + }, + "port": { + "type": "number" + }, + "updatedAt": { + "type": "string" + }, + "user": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "connectionString" + ], + "properties": { + "connectionString": { + "type": "string" + }, + "label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + } + } + }, + "required": true + } + } + }, + "/projects/{projectId}/databases/profiles/{profileId}": { + "delete": { + "tags": [ + "projectDatabases" + ], + "operationId": "projectDatabases.deleteDatabaseProfile", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + }, + { + "name": "profileId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ok" + ], + "properties": { + "ok": { + "type": "boolean", + "enum": [ + true + ] + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/projects/{projectId}/databases/profiles/{profileId}/expose": { + "post": { + "tags": [ + "projectDatabases" + ], + "operationId": "projectDatabases.exposeDatabaseProfile", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + }, + { + "name": "profileId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "201": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "forward" + ], + "properties": { + "forward": { + "type": "object", + "required": [ + "bindHost", + "containerName", + "createdAt", + "database", + "engine", + "externalConnectionString", + "hostPort", + "id", + "maskedExternalConnectionString", + "profileId", + "profileLabel", + "projectId", + "projectKey", + "publicHost", + "status", + "targetHost", + "targetPort" + ], + "properties": { + "bindHost": { + "type": "string" + }, + "containerName": { + "type": "string" + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "database": { + "type": "string" + }, + "engine": { + "type": "string", + "enum": [ + "postgres", + "mysql", + "mariadb" + ] + }, + "externalConnectionString": { + "type": "string" + }, + "hostPort": { + "type": "number" + }, + "id": { + "type": "string" + }, + "maskedExternalConnectionString": { + "type": "string" + }, + "profileId": { + "type": "string" + }, + "profileLabel": { + "type": "string" + }, + "projectId": { + "type": "string" + }, + "projectKey": { + "type": "string" + }, + "publicHost": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "running", + "stopped", + "unknown" + ] + }, + "targetHost": { + "type": "string" + }, + "targetPort": { + "type": "number" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + }, + "delete": { + "tags": [ + "projectDatabases" + ], + "operationId": "projectDatabases.deleteDatabaseForward", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + }, + { + "name": "profileId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ok" + ], + "properties": { + "ok": { + "type": "boolean", + "enum": [ + true + ] + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/projects/{projectId}/databases/forwards": { + "get": { + "tags": [ + "projectDatabases" + ], + "operationId": "projectDatabases.listDatabaseForwards", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "forwards" + ], + "properties": { + "forwards": { + "type": "array", + "items": { + "type": "object", + "required": [ + "bindHost", + "containerName", + "createdAt", + "database", + "engine", + "externalConnectionString", + "hostPort", + "id", + "maskedExternalConnectionString", + "profileId", + "profileLabel", + "projectId", + "projectKey", + "publicHost", + "status", + "targetHost", + "targetPort" + ], + "properties": { + "bindHost": { + "type": "string" + }, + "containerName": { + "type": "string" + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "database": { + "type": "string" + }, + "engine": { + "type": "string", + "enum": [ + "postgres", + "mysql", + "mariadb" + ] + }, + "externalConnectionString": { + "type": "string" + }, + "hostPort": { + "type": "number" + }, + "id": { + "type": "string" + }, + "maskedExternalConnectionString": { + "type": "string" + }, + "profileId": { + "type": "string" + }, + "profileLabel": { + "type": "string" + }, + "projectId": { + "type": "string" + }, + "projectKey": { + "type": "string" + }, + "publicHost": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "running", + "stopped", + "unknown" + ] + }, + "targetHost": { + "type": "string" + }, + "targetPort": { + "type": "number" + } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/projects/{projectId}/databases/session": { + "get": { + "tags": [ + "projectDatabases" + ], + "operationId": "projectDatabases.readDatabaseSession", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "session" + ], + "properties": { + "session": { + "type": "object", + "required": [ + "configHash", + "containerName", + "editorPath", + "editorUrl", + "projectId", + "projectKey", + "status" + ], + "properties": { + "configHash": { + "type": "string" + }, + "containerName": { + "type": "string" + }, + "editorPath": { + "type": "string" + }, + "editorUrl": { + "type": "string" + }, + "projectId": { + "type": "string" + }, + "projectKey": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "running", + "stopped", + "missing", + "unknown" + ] + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/projects/{projectId}/databases/open": { + "post": { + "tags": [ + "projectDatabases" + ], + "operationId": "projectDatabases.openDatabaseEditor", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "session" + ], + "properties": { + "session": { + "type": "object", + "required": [ + "configHash", + "containerName", + "editorPath", + "editorUrl", + "projectId", + "projectKey", + "status" + ], + "properties": { + "configHash": { + "type": "string" + }, + "containerName": { + "type": "string" + }, + "editorPath": { + "type": "string" + }, + "editorUrl": { + "type": "string" + }, + "projectId": { + "type": "string" + }, + "projectKey": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "running", + "stopped", + "missing", + "unknown" + ] + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/projects/{projectId}/databases/restart": { + "post": { + "tags": [ + "projectDatabases" + ], + "operationId": "projectDatabases.restartDatabaseEditor", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "session" + ], + "properties": { + "session": { + "type": "object", + "required": [ + "configHash", + "containerName", + "editorPath", + "editorUrl", + "projectId", + "projectKey", + "status" + ], + "properties": { + "configHash": { + "type": "string" + }, + "containerName": { + "type": "string" + }, + "editorPath": { + "type": "string" + }, + "editorUrl": { + "type": "string" + }, + "projectId": { + "type": "string" + }, + "projectKey": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "running", + "stopped", + "missing", + "unknown" + ] + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/auth/github/status": { + "get": { + "tags": [ + "auth" + ], + "operationId": "auth.githubStatus", + "parameters": [], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "status" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "status": { + "type": "object", + "required": [ + "summary", + "tokens" + ], + "properties": { + "summary": { + "type": "string" + }, + "tokens": { + "type": "array", + "items": { + "type": "object", + "required": [ + "key", + "label", + "login", + "status" + ], + "properties": { + "key": { + "type": "string" + }, + "label": { + "type": "string" + }, + "login": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "status": { + "type": "string", + "enum": [ + "valid", + "invalid", + "unknown" + ] + } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/auth/gitlab/status": { + "get": { + "tags": [ + "auth" + ], + "operationId": "auth.gitlabStatus", + "parameters": [], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "status" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "status": { + "type": "object", + "required": [ + "summary", + "tokens" + ], + "properties": { + "summary": { + "type": "string" + }, + "tokens": { + "type": "array", + "items": { + "type": "object", + "required": [ + "key", + "label", + "login", + "status" + ], + "properties": { + "key": { + "type": "string" + }, + "label": { + "type": "string" + }, + "login": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "status": { + "type": "string", + "enum": [ + "valid", + "invalid", + "unknown" + ] + } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/auth/git/status": { + "get": { + "tags": [ + "auth" + ], + "operationId": "auth.gitStatus", + "parameters": [], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "status" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "status": { + "type": "object", + "required": [ + "connections", + "summary" + ], + "properties": { + "connections": { + "type": "array", + "items": { + "type": "object", + "required": [ + "host", + "user" + ], + "properties": { + "host": { + "type": "string" + }, + "user": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "summary": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/auth/grok/status": { + "get": { + "tags": [ + "auth" + ], + "operationId": "auth.grokStatus", + "parameters": [ + { + "name": "label", + "in": "query", + "schema": { + "type": "string" + }, + "required": false + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "status" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "status": { + "type": "object", + "required": [ + "authPath", + "connected", + "label", + "message", + "method" + ], + "properties": { + "authPath": { + "type": "string" + }, + "connected": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "message": { + "type": "string" + }, + "method": { + "type": "string", + "enum": [ + "none", + "api-key", + "oauth" + ] + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/auth/codex/status": { + "get": { + "tags": [ + "auth" + ], + "operationId": "auth.codexStatus", + "parameters": [ + { + "name": "label", + "in": "query", + "schema": { + "type": "string" + }, + "required": false + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "status" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "status": { + "type": "object", + "required": [ + "account", + "authPath", + "label", + "message", + "present" + ], + "properties": { + "account": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "authPath": { + "type": "string" + }, + "label": { + "type": "string" + }, + "message": { + "type": "string" + }, + "present": { + "type": "boolean" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/auth/github/login": { + "post": { + "tags": [ + "auth" + ], + "operationId": "auth.githubLogin", + "parameters": [], + "security": [], + "responses": { + "201": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "status" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "status": { + "type": "object", + "required": [ + "summary", + "tokens" + ], + "properties": { + "summary": { + "type": "string" + }, + "tokens": { + "type": "array", + "items": { + "type": "object", + "required": [ + "key", + "label", + "login", + "status" + ], + "properties": { + "key": { + "type": "string" + }, + "label": { + "type": "string" + }, + "login": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "status": { + "type": "string", + "enum": [ + "valid", + "invalid", + "unknown" + ] + } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [], + "properties": { + "label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "token": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "scopes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + } + } + }, + "required": true + } + } + }, + "/auth/github/logout": { + "post": { + "tags": [ + "auth" + ], + "operationId": "auth.githubLogout", + "parameters": [], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "status" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "status": { + "type": "object", + "required": [ + "summary", + "tokens" + ], + "properties": { + "summary": { + "type": "string" + }, + "tokens": { + "type": "array", + "items": { + "type": "object", + "required": [ + "key", + "label", + "login", + "status" + ], + "properties": { + "key": { + "type": "string" + }, + "label": { + "type": "string" + }, + "login": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "status": { + "type": "string", + "enum": [ + "valid", + "invalid", + "unknown" + ] + } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [], + "properties": { + "label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + } + } + }, + "required": true + } + } + }, + "/auth/gitlab/login": { + "post": { + "tags": [ + "auth" + ], + "operationId": "auth.gitlabLogin", + "parameters": [], + "security": [], + "responses": { + "201": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "status" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "status": { + "type": "object", + "required": [ + "summary", + "tokens" + ], + "properties": { + "summary": { + "type": "string" + }, + "tokens": { + "type": "array", + "items": { + "type": "object", + "required": [ + "key", + "label", + "login", + "status" + ], + "properties": { + "key": { + "type": "string" + }, + "label": { + "type": "string" + }, + "login": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "status": { + "type": "string", + "enum": [ + "valid", + "invalid", + "unknown" + ] + } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [], + "properties": { + "label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "token": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + } + } + }, + "required": true + } + } + }, + "/auth/gitlab/logout": { + "post": { + "tags": [ + "auth" + ], + "operationId": "auth.gitlabLogout", + "parameters": [], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "status" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "status": { + "type": "object", + "required": [ + "summary", + "tokens" + ], + "properties": { + "summary": { + "type": "string" + }, + "tokens": { + "type": "array", + "items": { + "type": "object", + "required": [ + "key", + "label", + "login", + "status" + ], + "properties": { + "key": { + "type": "string" + }, + "label": { + "type": "string" + }, + "login": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "status": { + "type": "string", + "enum": [ + "valid", + "invalid", + "unknown" + ] + } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [], + "properties": { + "label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + } + } + }, + "required": true + } + } + }, + "/auth/git/login": { + "post": { + "tags": [ + "auth" + ], + "operationId": "auth.gitLogin", + "parameters": [], + "security": [], + "responses": { + "201": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "status" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "status": { + "type": "object", + "required": [ + "connections", + "summary" + ], + "properties": { + "connections": { + "type": "array", + "items": { + "type": "object", + "required": [ + "host", + "user" + ], + "properties": { + "host": { + "type": "string" + }, + "user": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "summary": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "host" + ], + "properties": { + "host": { + "type": "string" + }, + "token": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "user": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + } + } + }, + "required": true + } + } + }, + "/auth/git/logout": { + "post": { + "tags": [ + "auth" + ], + "operationId": "auth.gitLogout", + "parameters": [], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "status" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "status": { + "type": "object", + "required": [ + "connections", + "summary" + ], + "properties": { + "connections": { + "type": "array", + "items": { + "type": "object", + "required": [ + "host", + "user" + ], + "properties": { + "host": { + "type": "string" + }, + "user": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "summary": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "host" + ], + "properties": { + "host": { + "type": "string" + } + }, + "additionalProperties": false + } + } + }, + "required": true + } + } + }, + "/auth/menu": { + "get": { + "tags": [ + "auth" + ], + "operationId": "auth.authMenu", + "parameters": [], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "snapshot" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "snapshot": { + "type": "object", + "required": [ + "claudeAuthEntries", + "claudeAuthPath", + "geminiAuthEntries", + "geminiAuthPath", + "gitTokenEntries", + "gitUserEntries", + "githubTokenEntries", + "globalEnvPath", + "totalEntries" + ], + "properties": { + "claudeAuthEntries": { + "type": "number" + }, + "claudeAuthPath": { + "type": "string" + }, + "codexAuthEntries": { + "type": "number" + }, + "codexAuthPath": { + "type": "string" + }, + "geminiAuthEntries": { + "type": "number" + }, + "geminiAuthPath": { + "type": "string" + }, + "gitTokenEntries": { + "type": "number" + }, + "gitUserEntries": { + "type": "number" + }, + "githubTokenEntries": { + "type": "number" + }, + "globalEnvPath": { + "type": "string" + }, + "grokAuthEntries": { + "type": "number" + }, + "grokAuthPath": { + "type": "string" + }, + "totalEntries": { + "type": "number" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + }, + "post": { + "tags": [ + "auth" + ], + "operationId": "auth.authMenuAction", + "parameters": [], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "snapshot" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "snapshot": { + "type": "object", + "required": [ + "claudeAuthEntries", + "claudeAuthPath", + "geminiAuthEntries", + "geminiAuthPath", + "gitTokenEntries", + "gitUserEntries", + "githubTokenEntries", + "globalEnvPath", + "totalEntries" + ], + "properties": { + "claudeAuthEntries": { + "type": "number" + }, + "claudeAuthPath": { + "type": "string" + }, + "codexAuthEntries": { + "type": "number" + }, + "codexAuthPath": { + "type": "string" + }, + "geminiAuthEntries": { + "type": "number" + }, + "geminiAuthPath": { + "type": "string" + }, + "gitTokenEntries": { + "type": "number" + }, + "gitUserEntries": { + "type": "number" + }, + "githubTokenEntries": { + "type": "number" + }, + "globalEnvPath": { + "type": "string" + }, + "grokAuthEntries": { + "type": "number" + }, + "grokAuthPath": { + "type": "string" + }, + "totalEntries": { + "type": "number" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "flow" + ], + "properties": { + "flow": { + "type": "string", + "enum": [ + "GithubRemove", + "GitSet", + "GitRemove", + "ClaudeLogout", + "GeminiApiKey", + "GeminiLogout", + "GrokApiKey", + "GrokLogout" + ] + }, + "label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "token": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "user": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "apiKey": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + } + } + }, + "required": true + } + } + }, + "/auth/terminal-sessions": { + "post": { + "tags": [ + "auth" + ], + "operationId": "auth.authTerminalSession", + "parameters": [], + "security": [], + "responses": { + "201": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "session" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "session": { + "type": "object", + "required": [ + "createdAt", + "id", + "projectId", + "sshCommand", + "status" + ], + "properties": { + "attachedClients": { + "type": "number" + }, + "closedAt": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "exitCode": { + "type": "number" + }, + "id": { + "type": "string" + }, + "projectId": { + "type": "string" + }, + "signal": { + "type": "number" + }, + "sshCommand": { + "type": "string" + }, + "startedAt": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "ready", + "attached", + "exited", + "failed" + ] + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "flow" + ], + "properties": { + "flow": { + "type": "string", + "enum": [ + "ClaudeOauth", + "GeminiOauth", + "GrokOauth" + ] + }, + "label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + } + } + }, + "required": true + } + } + }, + "/auth/codex/import": { + "post": { + "tags": [ + "auth" + ], + "operationId": "auth.codexImport", + "parameters": [], + "security": [], + "responses": { + "201": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "status" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "status": { + "type": "object", + "required": [ + "account", + "authPath", + "label", + "message", + "present" + ], + "properties": { + "account": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "authPath": { + "type": "string" + }, + "label": { + "type": "string" + }, + "message": { + "type": "string" + }, + "present": { + "type": "boolean" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "authText" + ], + "properties": { + "label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "authText": { + "type": "string" + } + }, + "additionalProperties": false + } + } + }, + "required": true + } + } + }, + "/auth/codex/logout": { + "post": { + "tags": [ + "auth" + ], + "operationId": "auth.codexLogout", + "parameters": [], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "status" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "status": { + "type": "object", + "required": [ + "account", + "authPath", + "label", + "message", + "present" + ], + "properties": { + "account": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "authPath": { + "type": "string" + }, + "label": { + "type": "string" + }, + "message": { + "type": "string" + }, + "present": { + "type": "boolean" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [], + "properties": { + "label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + } + } + }, + "required": true + } + } + }, + "/auth/grok/logout": { + "post": { + "tags": [ + "auth" + ], + "operationId": "auth.grokLogout", + "parameters": [], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "status" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "status": { + "type": "object", + "required": [ + "authPath", + "connected", + "label", + "message", + "method" + ], + "properties": { + "authPath": { + "type": "string" + }, + "connected": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "message": { + "type": "string" + }, + "method": { + "type": "string", + "enum": [ + "none", + "api-key", + "oauth" + ] + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [], + "properties": { + "label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + } + } + }, + "required": true + } + } + }, + "/projects/{projectId}/auth/menu": { + "get": { + "tags": [ + "projectAuth" + ], + "operationId": "projectAuth.projectAuth", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "snapshot" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "snapshot": { + "type": "object", + "required": [ + "activeClaudeLabel", + "activeGeminiLabel", + "activeGitLabel", + "activeGithubLabel", + "activeGrokLabel", + "claudeAuthEntries", + "claudeAuthPath", + "envGlobalPath", + "envProjectPath", + "geminiAuthEntries", + "geminiAuthPath", + "gitTokenEntries", + "githubTokenEntries", + "projectDir", + "projectName" + ], + "properties": { + "activeClaudeLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "activeGeminiLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "activeGitLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "activeGithubLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "activeGrokLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "claudeAuthEntries": { + "type": "number" + }, + "claudeAuthPath": { + "type": "string" + }, + "codexAuthEntries": { + "type": "number" + }, + "codexAuthPath": { + "type": "string" + }, + "envGlobalPath": { + "type": "string" + }, + "envProjectPath": { + "type": "string" + }, + "geminiAuthEntries": { + "type": "number" + }, + "geminiAuthPath": { + "type": "string" + }, + "gitTokenEntries": { + "type": "number" + }, + "githubTokenEntries": { + "type": "number" + }, + "grokAuthEntries": { + "type": "number" + }, + "grokAuthPath": { + "type": "string" + }, + "projectDir": { + "type": "string" + }, + "projectName": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + }, + "post": { + "tags": [ + "projectAuth" + ], + "operationId": "projectAuth.projectAuthAction", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "snapshot" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "snapshot": { + "type": "object", + "required": [ + "activeClaudeLabel", + "activeGeminiLabel", + "activeGitLabel", + "activeGithubLabel", + "activeGrokLabel", + "claudeAuthEntries", + "claudeAuthPath", + "envGlobalPath", + "envProjectPath", + "geminiAuthEntries", + "geminiAuthPath", + "gitTokenEntries", + "githubTokenEntries", + "projectDir", + "projectName" + ], + "properties": { + "activeClaudeLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "activeGeminiLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "activeGitLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "activeGithubLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "activeGrokLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "claudeAuthEntries": { + "type": "number" + }, + "claudeAuthPath": { + "type": "string" + }, + "codexAuthEntries": { + "type": "number" + }, + "codexAuthPath": { + "type": "string" + }, + "envGlobalPath": { + "type": "string" + }, + "envProjectPath": { + "type": "string" + }, + "geminiAuthEntries": { + "type": "number" + }, + "geminiAuthPath": { + "type": "string" + }, + "gitTokenEntries": { + "type": "number" + }, + "githubTokenEntries": { + "type": "number" + }, + "grokAuthEntries": { + "type": "number" + }, + "grokAuthPath": { + "type": "string" + }, + "projectDir": { + "type": "string" + }, + "projectName": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "flow" + ], + "properties": { + "flow": { + "type": "string", + "enum": [ + "ProjectGithubConnect", + "ProjectGithubDisconnect", + "ProjectGitConnect", + "ProjectGitDisconnect", + "ProjectClaudeConnect", + "ProjectClaudeDisconnect", + "ProjectGeminiConnect", + "ProjectGeminiDisconnect", + "ProjectGrokConnect", + "ProjectGrokDisconnect" + ] + }, + "label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + } + } + }, + "required": true + } + } + }, + "/projects/by-key/{projectKey}/terminal-sessions": { + "post": { + "tags": [ + "terminal" + ], + "operationId": "terminal.createTerminalByKey", + "parameters": [ + { + "name": "projectKey", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "201": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "project", + "session" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "project": { + "type": "object", + "required": [ + "containerName", + "displayName", + "id", + "projectKey", + "repoRef", + "repoUrl", + "sshSessions", + "startedAtEpochMs", + "startedAtIso", + "status", + "statusLabel", + "authorizedKeysExists", + "authorizedKeysPath", + "codexAuthPath", + "codexHome", + "envGlobalPath", + "envProjectPath", + "gpu", + "projectDir", + "serviceName", + "sshCommand", + "sshPort", + "sshUser", + "targetDir" + ], + "properties": { + "clonedOnHostname": { + "type": "string" + }, + "containerName": { + "type": "string" + }, + "displayName": { + "type": "string" + }, + "id": { + "type": "string" + }, + "projectKey": { + "type": "string" + }, + "repoRef": { + "type": "string" + }, + "repoUrl": { + "type": "string" + }, + "sshSessions": { + "type": "number" + }, + "startedAtEpochMs": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "startedAtIso": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "status": { + "type": "string", + "enum": [ + "running", + "stopped", + "unknown" + ] + }, + "statusLabel": { + "type": "string" + }, + "authorizedKeysExists": { + "type": "boolean" + }, + "authorizedKeysPath": { + "type": "string" + }, + "codexAuthPath": { + "type": "string" + }, + "codexHome": { + "type": "string" + }, + "envGlobalPath": { + "type": "string" + }, + "envProjectPath": { + "type": "string" + }, + "gpu": { + "type": "string", + "enum": [ + "none", + "all" + ] + }, + "projectDir": { + "type": "string" + }, + "serviceName": { + "type": "string" + }, + "sshCommand": { + "type": "string" + }, + "sshPort": { + "type": "number" + }, + "sshUser": { + "type": "string" + }, + "targetDir": { + "type": "string" + } + }, + "additionalProperties": false + }, + "session": { + "type": "object", + "required": [ + "createdAt", + "id", + "projectId", + "sshCommand", + "status" + ], + "properties": { + "attachedClients": { + "type": "number" + }, + "closedAt": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "exitCode": { + "type": "number" + }, + "id": { + "type": "string" + }, + "projectId": { + "type": "string" + }, + "signal": { + "type": "number" + }, + "sshCommand": { + "type": "string" + }, + "startedAt": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "ready", + "attached", + "exited", + "failed" + ] + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + }, + "get": { + "tags": [ + "terminal" + ], + "operationId": "terminal.listTerminalsByKey", + "parameters": [ + { + "name": "projectKey", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "activeSessionId", + "sessions" + ], + "properties": { + "activeSessionId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "sessions": { + "type": "array", + "items": { + "type": "object", + "required": [ + "createdAt", + "id", + "projectId", + "sshCommand", + "status" + ], + "properties": { + "attachedClients": { + "type": "number" + }, + "closedAt": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "exitCode": { + "type": "number" + }, + "id": { + "type": "string" + }, + "projectId": { + "type": "string" + }, + "signal": { + "type": "number" + }, + "sshCommand": { + "type": "string" + }, + "startedAt": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "ready", + "attached", + "exited", + "failed" + ] + } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/projects/by-key/{projectKey}/terminal-sessions/start": { + "post": { + "tags": [ + "terminal" + ], + "operationId": "terminal.startTerminalByKey", + "parameters": [ + { + "name": "projectKey", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "202": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "accepted", + "cursor", + "projectId", + "requestId" + ], + "properties": { + "accepted": { + "type": "boolean", + "enum": [ + true + ] + }, + "cursor": { + "type": "number" + }, + "projectId": { + "type": "string" + }, + "requestId": { + "type": "string" + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "requestId" + ], + "properties": { + "requestId": { + "$ref": "#/components/schemas/UUID" + } + }, + "additionalProperties": false + } + } + }, + "required": true + } + } + }, + "/projects/by-key/{projectKey}/terminal-sessions/{sessionId}": { + "get": { + "tags": [ + "terminal" + ], + "operationId": "terminal.getTerminalByKey", + "parameters": [ + { + "name": "projectKey", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + }, + { + "name": "sessionId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "session" + ], + "properties": { + "session": { + "type": "object", + "required": [ + "createdAt", + "id", + "projectId", + "sshCommand", + "status" + ], + "properties": { + "attachedClients": { + "type": "number" + }, + "closedAt": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "exitCode": { + "type": "number" + }, + "id": { + "type": "string" + }, + "projectId": { + "type": "string" + }, + "signal": { + "type": "number" + }, + "sshCommand": { + "type": "string" + }, + "startedAt": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "ready", + "attached", + "exited", + "failed" + ] + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + }, + "delete": { + "tags": [ + "terminal" + ], + "operationId": "terminal.deleteTerminalByKey", + "parameters": [ + { + "name": "projectKey", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + }, + { + "name": "sessionId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ok" + ], + "properties": { + "ok": { + "type": "boolean", + "enum": [ + true + ] + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/projects/by-key/{projectKey}/terminal-sessions/active": { + "put": { + "tags": [ + "terminal" + ], + "operationId": "terminal.setActiveTerminalByKey", + "parameters": [ + { + "name": "projectKey", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "session" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "session": { + "type": "object", + "required": [ + "createdAt", + "id", + "projectId", + "sshCommand", + "status" + ], + "properties": { + "attachedClients": { + "type": "number" + }, + "closedAt": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "exitCode": { + "type": "number" + }, + "id": { + "type": "string" + }, + "projectId": { + "type": "string" + }, + "signal": { + "type": "number" + }, + "sshCommand": { + "type": "string" + }, + "startedAt": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "ready", + "attached", + "exited", + "failed" + ] + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "sessionId" + ], + "properties": { + "sessionId": { + "type": "string" + } + }, + "additionalProperties": false + } + } + }, + "required": true + } + } + }, + "/terminal-sessions/{sessionId}": { + "get": { + "tags": [ + "terminal" + ], + "operationId": "terminal.lookupTerminal", + "parameters": [ + { + "name": "sessionId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "projectDisplayName", + "projectKey", + "session" + ], + "properties": { + "projectDisplayName": { + "type": "string" + }, + "projectKey": { + "type": "string" + }, + "session": { + "type": "object", + "required": [ + "createdAt", + "id", + "projectId", + "sshCommand", + "status" + ], + "properties": { + "attachedClients": { + "type": "number" + }, + "closedAt": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "exitCode": { + "type": "number" + }, + "id": { + "type": "string" + }, + "projectId": { + "type": "string" + }, + "signal": { + "type": "number" + }, + "sshCommand": { + "type": "string" + }, + "startedAt": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "ready", + "attached", + "exited", + "failed" + ] + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/auth/terminal-sessions/{sessionId}": { + "delete": { + "tags": [ + "terminal" + ], + "operationId": "terminal.deleteAuthTerminal", + "parameters": [ + { + "name": "sessionId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ok" + ], + "properties": { + "ok": { + "type": "boolean", + "enum": [ + true + ] + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/projects/{projectId}/prompts": { + "get": { + "tags": [ + "prompts" + ], + "operationId": "prompts.listPrompts", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "snapshot" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "snapshot": { + "type": "object", + "required": [ + "projectDir", + "projectId", + "projectKey", + "prompts" + ], + "properties": { + "projectDir": { + "type": "string" + }, + "projectId": { + "type": "string" + }, + "projectKey": { + "type": "string" + }, + "prompts": { + "type": "array", + "items": { + "type": "object", + "required": [ + "absolutePath", + "bytes", + "content", + "exists", + "fileName", + "kind", + "relativePath" + ], + "properties": { + "absolutePath": { + "type": "string" + }, + "bytes": { + "type": "number" + }, + "content": { + "type": "string" + }, + "exists": { + "type": "boolean" + }, + "fileName": { + "type": "string" + }, + "kind": { + "type": "string", + "enum": [ + "claude", + "codex", + "gemini", + "grok" + ] + }, + "relativePath": { + "type": "string" + } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/projects/{projectId}/prompts/{kind}": { + "put": { + "tags": [ + "prompts" + ], + "operationId": "prompts.writePrompt", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + }, + { + "name": "kind", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "prompt", + "snapshot" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "prompt": { + "type": "object", + "required": [ + "absolutePath", + "bytes", + "content", + "exists", + "fileName", + "kind", + "relativePath" + ], + "properties": { + "absolutePath": { + "type": "string" + }, + "bytes": { + "type": "number" + }, + "content": { + "type": "string" + }, + "exists": { + "type": "boolean" + }, + "fileName": { + "type": "string" + }, + "kind": { + "type": "string", + "enum": [ + "claude", + "codex", + "gemini", + "grok" + ] + }, + "relativePath": { + "type": "string" + } + }, + "additionalProperties": false + }, + "snapshot": { + "type": "object", + "required": [ + "projectDir", + "projectId", + "projectKey", + "prompts" + ], + "properties": { + "projectDir": { + "type": "string" + }, + "projectId": { + "type": "string" + }, + "projectKey": { + "type": "string" + }, + "prompts": { + "type": "array", + "items": { + "type": "object", + "required": [ + "absolutePath", + "bytes", + "content", + "exists", + "fileName", + "kind", + "relativePath" + ], + "properties": { + "absolutePath": { + "type": "string" + }, + "bytes": { + "type": "number" + }, + "content": { + "type": "string" + }, + "exists": { + "type": "boolean" + }, + "fileName": { + "type": "string" + }, + "kind": { + "type": "string", + "enum": [ + "claude", + "codex", + "gemini", + "grok" + ] + }, + "relativePath": { + "type": "string" + } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "content" + ], + "properties": { + "content": { + "type": "string" + } + }, + "additionalProperties": false + } + } + }, + "required": true + } + }, + "delete": { + "tags": [ + "prompts" + ], + "operationId": "prompts.deletePrompt", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + }, + { + "name": "kind", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "snapshot" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "snapshot": { + "type": "object", + "required": [ + "projectDir", + "projectId", + "projectKey", + "prompts" + ], + "properties": { + "projectDir": { + "type": "string" + }, + "projectId": { + "type": "string" + }, + "projectKey": { + "type": "string" + }, + "prompts": { + "type": "array", + "items": { + "type": "object", + "required": [ + "absolutePath", + "bytes", + "content", + "exists", + "fileName", + "kind", + "relativePath" + ], + "properties": { + "absolutePath": { + "type": "string" + }, + "bytes": { + "type": "number" + }, + "content": { + "type": "string" + }, + "exists": { + "type": "boolean" + }, + "fileName": { + "type": "string" + }, + "kind": { + "type": "string", + "enum": [ + "claude", + "codex", + "gemini", + "grok" + ] + }, + "relativePath": { + "type": "string" + } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/projects/{projectId}/skills": { + "get": { + "tags": [ + "skills" + ], + "operationId": "skills.listSkills", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "snapshot" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "snapshot": { + "type": "object", + "required": [ + "projectDir", + "projectId", + "projectKey", + "scopes", + "skills" + ], + "properties": { + "projectDir": { + "type": "string" + }, + "projectId": { + "type": "string" + }, + "projectKey": { + "type": "string" + }, + "scopes": { + "type": "array", + "items": { + "type": "object", + "required": [ + "absoluteRoot", + "relativeRoot", + "scope" + ], + "properties": { + "absoluteRoot": { + "type": "string" + }, + "relativeRoot": { + "type": "string" + }, + "scope": { + "type": "string", + "enum": [ + "skills", + "agents/skills", + "agents/.skills", + "claude/skills", + "codex/skills", + "gemini/skills", + "grok/skills" + ] + } + }, + "additionalProperties": false + } + }, + "skills": { + "type": "array", + "items": { + "type": "object", + "required": [ + "absolutePath", + "bytes", + "content", + "id", + "name", + "relativePath", + "scope", + "updatedAtIso" + ], + "properties": { + "absolutePath": { + "type": "string" + }, + "bytes": { + "type": "number" + }, + "content": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "relativePath": { + "type": "string" + }, + "scope": { + "type": "string", + "enum": [ + "skills", + "agents/skills", + "agents/.skills", + "claude/skills", + "codex/skills", + "gemini/skills", + "grok/skills" + ] + }, + "updatedAtIso": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + }, + "post": { + "tags": [ + "skills" + ], + "operationId": "skills.writeSkill", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "skill", + "snapshot" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "skill": { + "type": "object", + "required": [ + "absolutePath", + "bytes", + "content", + "id", + "name", + "relativePath", + "scope", + "updatedAtIso" + ], + "properties": { + "absolutePath": { + "type": "string" + }, + "bytes": { + "type": "number" + }, + "content": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "relativePath": { + "type": "string" + }, + "scope": { + "type": "string", + "enum": [ + "skills", + "agents/skills", + "agents/.skills", + "claude/skills", + "codex/skills", + "gemini/skills", + "grok/skills" + ] + }, + "updatedAtIso": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + }, + "snapshot": { + "type": "object", + "required": [ + "projectDir", + "projectId", + "projectKey", + "scopes", + "skills" + ], + "properties": { + "projectDir": { + "type": "string" + }, + "projectId": { + "type": "string" + }, + "projectKey": { + "type": "string" + }, + "scopes": { + "type": "array", + "items": { + "type": "object", + "required": [ + "absoluteRoot", + "relativeRoot", + "scope" + ], + "properties": { + "absoluteRoot": { + "type": "string" + }, + "relativeRoot": { + "type": "string" + }, + "scope": { + "type": "string", + "enum": [ + "skills", + "agents/skills", + "agents/.skills", + "claude/skills", + "codex/skills", + "gemini/skills", + "grok/skills" + ] + } + }, + "additionalProperties": false + } + }, + "skills": { + "type": "array", + "items": { + "type": "object", + "required": [ + "absolutePath", + "bytes", + "content", + "id", + "name", + "relativePath", + "scope", + "updatedAtIso" + ], + "properties": { + "absolutePath": { + "type": "string" + }, + "bytes": { + "type": "number" + }, + "content": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "relativePath": { + "type": "string" + }, + "scope": { + "type": "string", + "enum": [ + "skills", + "agents/skills", + "agents/.skills", + "claude/skills", + "codex/skills", + "gemini/skills", + "grok/skills" + ] + }, + "updatedAtIso": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "scope", + "name", + "content" + ], + "properties": { + "scope": { + "type": "string", + "enum": [ + "skills", + "agents/skills", + "agents/.skills", + "claude/skills", + "codex/skills", + "gemini/skills", + "grok/skills" + ] + }, + "name": { + "type": "string" + }, + "content": { + "type": "string" + } + }, + "additionalProperties": false + } + } + }, + "required": true + } + } + }, + "/projects/{projectId}/skills/{scopeId}/{name}": { + "delete": { + "tags": [ + "skills" + ], + "operationId": "skills.deleteSkill", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + }, + { + "name": "scopeId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + }, + { + "name": "name", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "snapshot" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "snapshot": { + "type": "object", + "required": [ + "projectDir", + "projectId", + "projectKey", + "scopes", + "skills" + ], + "properties": { + "projectDir": { + "type": "string" + }, + "projectId": { + "type": "string" + }, + "projectKey": { + "type": "string" + }, + "scopes": { + "type": "array", + "items": { + "type": "object", + "required": [ + "absoluteRoot", + "relativeRoot", + "scope" + ], + "properties": { + "absoluteRoot": { + "type": "string" + }, + "relativeRoot": { + "type": "string" + }, + "scope": { + "type": "string", + "enum": [ + "skills", + "agents/skills", + "agents/.skills", + "claude/skills", + "codex/skills", + "gemini/skills", + "grok/skills" + ] + } + }, + "additionalProperties": false + } + }, + "skills": { + "type": "array", + "items": { + "type": "object", + "required": [ + "absolutePath", + "bytes", + "content", + "id", + "name", + "relativePath", + "scope", + "updatedAtIso" + ], + "properties": { + "absolutePath": { + "type": "string" + }, + "bytes": { + "type": "number" + }, + "content": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "relativePath": { + "type": "string" + }, + "scope": { + "type": "string", + "enum": [ + "skills", + "agents/skills", + "agents/.skills", + "claude/skills", + "codex/skills", + "gemini/skills", + "grok/skills" + ] + }, + "updatedAtIso": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/projects/{projectId}/tasks": { + "get": { + "tags": [ + "tasks" + ], + "operationId": "tasks.listTasks", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + }, + { + "name": "includeDefault", + "in": "query", + "schema": { + "type": "string" + }, + "required": false + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "snapshot" + ], + "properties": { + "snapshot": { + "type": "object", + "required": [ + "agents", + "containerName", + "generatedAt", + "projectId", + "sshConnections", + "tasks", + "terminalSessions" + ], + "properties": { + "agents": { + "type": "array", + "items": { + "type": "object", + "required": [ + "id", + "projectId", + "provider", + "label", + "command", + "containerName", + "status", + "source", + "pidFile", + "hostPid", + "startedAt", + "updatedAt" + ], + "properties": { + "id": { + "type": "string" + }, + "projectId": { + "type": "string" + }, + "provider": { + "type": "string", + "enum": [ + "codex", + "opencode", + "claude", + "grok", + "custom" + ] + }, + "label": { + "type": "string" + }, + "command": { + "type": "string" + }, + "containerName": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "starting", + "running", + "stopping", + "stopped", + "exited", + "failed" + ] + }, + "source": { + "type": "string" + }, + "pidFile": { + "type": "string" + }, + "hostPid": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "startedAt": { + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "stoppedAt": { + "type": "string" + }, + "exitCode": { + "type": "number" + }, + "signal": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "containerName": { + "type": "string" + }, + "generatedAt": { + "type": "string" + }, + "projectId": { + "type": "string" + }, + "sshConnections": { + "type": "number" + }, + "tasks": { + "type": "array", + "items": { + "type": "object", + "required": [ + "command", + "etime", + "etimes", + "kind", + "logAvailable", + "pid", + "ppid", + "tty", + "user" + ], + "properties": { + "command": { + "type": "string" + }, + "elapsed": { + "type": "string" + }, + "etime": { + "type": "string" + }, + "etimes": { + "type": "number" + }, + "kind": { + "type": "string", + "enum": [ + "ssh", + "web-terminal", + "agent", + "background", + "system" + ] + }, + "logAvailable": { + "type": "boolean" + }, + "managedId": { + "type": "string" + }, + "pid": { + "type": "number" + }, + "ppid": { + "type": "number" + }, + "tty": { + "type": "string" + }, + "user": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "terminalSessions": { + "type": "array", + "items": { + "type": "object", + "required": [ + "createdAt", + "id", + "projectId", + "sshCommand", + "status" + ], + "properties": { + "attachedClients": { + "type": "number" + }, + "closedAt": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "exitCode": { + "type": "number" + }, + "id": { + "type": "string" + }, + "projectId": { + "type": "string" + }, + "signal": { + "type": "number" + }, + "sshCommand": { + "type": "string" + }, + "startedAt": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "ready", + "attached", + "exited", + "failed" + ] + } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/projects/{projectId}/tasks/{pid}/stop": { + "post": { + "tags": [ + "tasks" + ], + "operationId": "tasks.stopTask", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + }, + { + "name": "pid", + "in": "path", + "schema": { + "$ref": "#/components/schemas/NumberFromString" + }, + "required": true + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ok" + ], + "properties": { + "ok": { + "type": "boolean", + "enum": [ + true + ] + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/projects/{projectId}/tasks/{pid}/logs": { + "get": { + "tags": [ + "tasks" + ], + "operationId": "tasks.taskLogs", + "parameters": [ + { + "name": "projectId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + }, + { + "name": "pid", + "in": "path", + "schema": { + "$ref": "#/components/schemas/NumberFromString" + }, + "required": true + }, + { + "name": "lines", + "in": "query", + "schema": { + "type": "string" + }, + "required": false + } + ], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "output" + ], + "properties": { + "output": { + "type": "string" + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + }, + "/cloudflare-tunnels/panel": { + "get": { + "tags": [ + "sharing" + ], + "operationId": "sharing.readPanelCloudflareTunnel", + "parameters": [], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "tunnel" + ], + "properties": { + "tunnel": { + "anyOf": [ + { + "type": "object", + "required": [ + "error", + "id", + "logTail", + "panelUrl", + "publicUrl", + "startedAt", + "status", + "stoppedAt" + ], + "properties": { + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "id": { + "type": "string" + }, + "logTail": { + "type": "array", + "items": { + "type": "string" + } + }, + "panelUrl": { + "type": "string" + }, + "publicUrl": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "startedAt": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "starting", + "running", + "stopped", + "failed" + ] + }, + "stoppedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + }, + "post": { + "tags": [ + "sharing" + ], + "operationId": "sharing.startPanelCloudflareTunnel", + "parameters": [], + "security": [], + "responses": { + "202": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "tunnel" + ], + "properties": { + "tunnel": { + "anyOf": [ + { + "type": "object", + "required": [ + "error", + "id", + "logTail", + "panelUrl", + "publicUrl", + "startedAt", + "status", + "stoppedAt" + ], + "properties": { + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "id": { + "type": "string" + }, + "logTail": { + "type": "array", + "items": { + "type": "string" + } + }, + "panelUrl": { + "type": "string" + }, + "publicUrl": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "startedAt": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "starting", + "running", + "stopped", + "failed" + ] + }, + "stoppedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "panelUrl" + ], + "properties": { + "panelUrl": { + "type": "string" + } + }, + "additionalProperties": false + } + } + }, + "required": true + } + }, + "delete": { + "tags": [ + "sharing" + ], + "operationId": "sharing.stopPanelCloudflareTunnel", + "parameters": [], + "security": [], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "tunnel" + ], + "properties": { + "tunnel": { + "anyOf": [ + { + "type": "object", + "required": [ + "error", + "id", + "logTail", + "panelUrl", + "publicUrl", + "startedAt", + "status", + "stoppedAt" + ], + "properties": { + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "id": { + "type": "string" + }, + "logTail": { + "type": "array", + "items": { + "type": "string" + } + }, + "panelUrl": { + "type": "string" + }, + "publicUrl": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "startedAt": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "starting", + "running", + "stopped", + "failed" + ] + }, + "stoppedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + } + } + } + }, + "400": { + "description": "The request did not match the expected schema", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" + }, + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "401": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message", + "type" + ], + "properties": { + "command": { + "type": "string" + }, + "details": { + "$id": "/schemas/unknown", + "title": "unknown" + }, + "message": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "HttpApiDecodeError": { + "type": "object", + "required": [ + "issues", + "message", + "_tag" + ], + "properties": { + "issues": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Issue" + } + }, + "message": { + "type": "string" + }, + "_tag": { + "type": "string", + "enum": [ + "HttpApiDecodeError" + ] + } + }, + "additionalProperties": false, + "description": "The request did not match the expected schema" + }, + "Issue": { + "type": "object", + "required": [ + "_tag", + "path", + "message" + ], + "properties": { + "_tag": { + "type": "string", + "enum": [ + "Pointer", + "Unexpected", + "Missing", + "Composite", + "Refinement", + "Transformation", + "Type", + "Forbidden" + ], + "description": "The tag identifying the type of parse issue" + }, + "path": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PropertyKey" + }, + "description": "The path to the property where the issue occurred" + }, + "message": { + "type": "string", + "description": "A descriptive message explaining the issue" + } + }, + "additionalProperties": false, + "description": "Represents an error encountered while parsing a value to match the schema" + }, + "PropertyKey": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "object", + "required": [ + "_tag", + "key" + ], + "properties": { + "_tag": { + "type": "string", + "enum": [ + "symbol" + ] + }, + "key": { + "type": "string" + } + }, + "additionalProperties": false, + "description": "an object to be decoded into a globally shared symbol" + } + ] + }, + "NumberFromString": { + "type": "string", + "description": "a string to be decoded into a number" + }, + "UUID": { + "type": "string", + "description": "a Universally Unique Identifier", + "format": "uuid", + "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$" + } + }, + "securitySchemes": {} + }, + "security": [], + "tags": [ + { + "name": "core" + }, + { + "name": "projects" + }, + { + "name": "projectPorts" + }, + { + "name": "projectBrowser" + }, + { + "name": "projectDatabases" + }, + { + "name": "auth" + }, + { + "name": "projectAuth" + }, + { + "name": "terminal" + }, + { + "name": "prompts" + }, + { + "name": "skills" + }, + { + "name": "tasks" + }, + { + "name": "sharing" + } + ] +} diff --git a/packages/openapi/package.json b/packages/openapi/package.json new file mode 100644 index 00000000..0e748a23 --- /dev/null +++ b/packages/openapi/package.json @@ -0,0 +1,43 @@ +{ + "name": "@prover-coder-ai/docker-git-openapi", + "version": "0.1.0", + "private": true, + "description": "Generated docker-git OpenAPI artifacts", + "type": "module", + "packageManager": "bun@1.3.11", + "types": "./src/index.ts", + "exports": { + ".": { + "types": "./src/index.ts", + "import": "./src/index.ts" + }, + "./client": { + "types": "./src/client.ts", + "import": "./src/client.ts" + }, + "./openapi-paths": { + "types": "./src/openapi-paths.ts", + "import": "./src/openapi-paths.ts" + }, + "./openapi.json": "./openapi.json" + }, + "scripts": { + "check": "bun run typecheck", + "generate": "bun ../../scripts/write-openapi.ts && openapi-typescript openapi.json -o src/openapi-paths.ts", + "typecheck": "tsc --noEmit -p tsconfig.json" + }, + "dependencies": { + "@effect/schema": "^0.75.5", + "effect": "^3.21.3", + "openapi-fetch": "^0.17.0" + }, + "devDependencies": { + "openapi-typescript": "^7.13.0", + "typescript": "^6.0.3" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/ProverCoderAI/docker-git.git" + }, + "license": "MIT" +} diff --git a/packages/openapi/src/client.ts b/packages/openapi/src/client.ts new file mode 100644 index 00000000..208b9418 --- /dev/null +++ b/packages/openapi/src/client.ts @@ -0,0 +1,312 @@ +import * as ParseResult from "@effect/schema/ParseResult" +import type * as Schema from "@effect/schema/Schema" +import * as TreeFormatter from "@effect/schema/TreeFormatter" +import { Effect, Either, Option } from "effect" +import createClient, { type Client, type Middleware } from "openapi-fetch" + +import type { paths } from "./openapi-paths.js" + +export type DockerGitOpenApiClient = Client + +export type ApiTransportValue = + | undefined + | null + | boolean + | number + | string + | ReadonlyArray + | { readonly [key: string]: ApiTransportValue } + +export type ApiTransportError = ApiTransportValue | object + +export type OpenApiResponse = { + readonly data?: A + readonly error?: ApiTransportError + readonly response: Response +} + +export type OpenApiRequestResult = PromiseLike> + +export type OpenApiRequest = (client: DockerGitOpenApiClient) => OpenApiRequestResult + +export type DockerGitOpenApiRuntimeOptions = { + readonly resolveBaseUrl: () => string +} + +export type DockerGitOpenApiRuntime = { + readonly openApiJson: (request: OpenApiRequest) => Effect.Effect + readonly openApiJsonSchema: ( + schema: Schema.Schema, + request: OpenApiRequest + ) => Effect.Effect + readonly openApiVoid: (request: OpenApiRequest) => Effect.Effect +} + +type RunOpenApi = (request: OpenApiRequest) => Effect.Effect, string> + +const noCacheHeaders: Readonly> = { + accept: "application/json", + "cache-control": "no-cache, no-store, max-age=0", + pragma: "no-cache" +} + +const stringifyJson = (value: ApiTransportError): Effect.Effect => + Effect.try({ + try: () => JSON.stringify(value, null, 2), + catch: () => null + }) + +const safeJson = (value: ApiTransportError): Effect.Effect => + stringifyJson(value).pipe( + Effect.orElseSucceed(() => "unrenderable response payload") + ) + +const renderTransportValue = (value: ApiTransportError): Effect.Effect => { + if (typeof value === "string") { + return Effect.succeed(value) + } + if (typeof value === "object" && value !== null && "message" in value) { + const message = value["message"] + if (typeof message === "string") { + return Effect.succeed(message) + } + } + return safeJson(value) +} + +const renderOpenApiError = ( + response: Response, + error: ApiTransportError | undefined +): Effect.Effect => { + if (response.status === 429) { + return Effect.succeed("HTTP 429: tunnel or proxy rate limited the request. Retry or request a fresh tunnel URL.") + } + return error === undefined ? Effect.succeed(`HTTP ${response.status}`) : renderTransportValue(error) +} + +const noCacheGetMiddleware: Middleware = { + onRequest: ({ request }) => { + if (request.method !== "GET") { + return + } + const url = new URL(request.url) + url.searchParams.set("_", String(Date.now())) + return new Request(url, request) + } +} + +/** + * Creates a typed openapi-fetch client for the docker-git JSON REST API. + * + * @param baseUrl - Absolute API base URL. + * @returns Typed OpenAPI client with no-cache headers and GET cache-busting middleware. + * + * @pure false - constructs a browser/Fetch API HTTP client adapter. + * @effect none - client construction only; network IO happens when request methods are executed. + * @invariant client paths are constrained by generated DockerGit OpenAPI paths. + * @precondition baseUrl points at a docker-git API server or compatible proxy. + * @postcondition returned client sends no-cache headers on JSON requests. + * @complexity O(1)/O(1) + * @throws Never. + */ +export const createDockerGitOpenApiClient = (baseUrl: string): DockerGitOpenApiClient => { + const client = createClient({ + baseUrl, + headers: noCacheHeaders + }) + client.use(noCacheGetMiddleware) + return client +} + +/** + * Runs a typed OpenAPI request with a provided client through Effect. + * + * @param client - Typed docker-git OpenAPI client. + * @param request - Deferred openapi-fetch request. + * @returns Effect containing raw transport response data or a string failure. + * + * @pure false - executes Promise-producing openapi-fetch request when the Effect is run. + * @effect Promise interop isolated through Effect.tryPromise. + * @invariant no Promise escapes the function boundary. + * @precondition request was built against the same generated OpenAPI path map as client. + * @postcondition transport failures are represented in the Effect error channel. + * @complexity O(1)/O(1) excluding network and response body costs. + * @throws Never. + */ +export const runOpenApi = ( + client: DockerGitOpenApiClient, + request: OpenApiRequest +): Effect.Effect, string> => + Effect.tryPromise({ + try: () => request(client), + catch: String + }) + +const failRenderedOpenApiError = ( + response: Response, + error: ApiTransportError | undefined +): Effect.Effect => + renderOpenApiError(response, error).pipe( + Effect.flatMap((message) => Effect.fail(message)) + ) + +const openApiJsonWithRunner = ( + runner: RunOpenApi, + request: OpenApiRequest +): Effect.Effect => + runner(request).pipe( + Effect.flatMap(({ data, error, response }) => + Option.match(Option.fromNullable(error), { + onNone: () => + response.ok + ? Option.match(Option.fromNullable(data), { + onNone: () => Effect.fail(`HTTP ${response.status}: empty response`), + onSome: (value) => Effect.succeed(value) + }) + : failRenderedOpenApiError(response, error), + onSome: (apiError) => failRenderedOpenApiError(response, apiError) + }) + ) + ) + +const decodeSchema = (schema: Schema.Schema, value: ApiTransportValue): Effect.Effect => + Either.match(ParseResult.decodeUnknownEither(schema)(value), { + onLeft: (error) => Effect.fail(TreeFormatter.formatIssueSync(error)), + onRight: (decoded) => Effect.succeed(decoded) + }) + +const openApiJsonSchemaWithRunner = ( + runner: RunOpenApi, + schema: Schema.Schema, + request: OpenApiRequest +): Effect.Effect => + openApiJsonWithRunner(runner, request).pipe( + Effect.flatMap((data) => decodeSchema(schema, data)) + ) + +const openApiVoidWithRunner = ( + runner: RunOpenApi, + request: OpenApiRequest +): Effect.Effect => + runner(request).pipe( + Effect.flatMap(({ error, response }) => + response.ok + ? Option.match(Option.fromNullable(error), { + onNone: () => Effect.void, + onSome: (apiError) => failRenderedOpenApiError(response, apiError) + }) + : failRenderedOpenApiError(response, error) + ) + ) + +/** + * Executes a typed OpenAPI JSON request through a provided client. + * + * @param client - Typed docker-git OpenAPI client. + * @param request - Deferred typed openapi-fetch request. + * @returns Effect containing raw 2xx response data or a rendered API error. + * + * @pure false - performs browser HTTP IO when the Effect is run. + * @effect Network request via openapi-fetch wrapped by Effect.tryPromise. + * @invariant Promise interop is isolated inside this boundary. + * @precondition request uses a static path from generated OpenAPI paths. + * @postcondition successful Effect contains only the 2xx data branch as a transport value. + * @complexity O(n) local response rendering where n is the error payload size. + * @throws Never; failures are returned in the Effect error channel. + */ +export const openApiJson = ( + client: DockerGitOpenApiClient, + request: OpenApiRequest +): Effect.Effect => + openApiJsonWithRunner((nextRequest) => runOpenApi(client, nextRequest), request) + +/** + * Executes a typed OpenAPI request and decodes the data with an Effect Schema. + * + * @param client - Typed docker-git OpenAPI client. + * @param schema - Boundary decoder preserving the consumer DTO type. + * @param request - Deferred typed openapi-fetch request. + * @returns Effect containing schema-decoded response data. + * + * @pure false - performs browser HTTP IO and boundary decoding when the Effect is run. + * @effect openapi-fetch request plus synchronous Effect Schema decoding. + * @invariant transport typing comes from OpenAPI; exported data typing comes from Schema. + * @precondition schema matches the endpoint success response documented in DockerGitApi. + * @postcondition no generated optional/default representation leaks into existing consumers. + * @complexity O(n) where n is the decoded response size. + * @throws Never; failures are returned in the Effect error channel. + */ +export const openApiJsonSchema = ( + client: DockerGitOpenApiClient, + schema: Schema.Schema, + request: OpenApiRequest +): Effect.Effect => + openApiJsonSchemaWithRunner((nextRequest) => runOpenApi(client, nextRequest), schema, request) + +/** + * Executes a typed OpenAPI request whose successful response has no body. + * + * @param client - Typed docker-git OpenAPI client. + * @param request - Deferred typed openapi-fetch request. + * @returns Effect that succeeds with void for successful empty responses. + * + * @pure false - performs browser HTTP IO when the Effect is run. + * @effect Network request via openapi-fetch wrapped by Effect.tryPromise. + * @invariant only response status determines success for empty endpoints. + * @precondition request targets an endpoint whose OpenAPI success response has no content. + * @postcondition successful Effect returns void and never exposes transport details. + * @complexity O(n) local response rendering where n is the error payload size. + * @throws Never; failures are returned in the Effect error channel. + */ +export const openApiVoid = ( + client: DockerGitOpenApiClient, + request: OpenApiRequest +): Effect.Effect => + openApiVoidWithRunner((nextRequest) => runOpenApi(client, nextRequest), request) + +/** + * Creates reusable Effect helpers backed by a base URL resolver. + * + * @param options - Runtime configuration containing a base URL resolver. + * @returns OpenAPI helper set with a baseUrl-keyed client cache. + * + * @pure false - closes over mutable client cache for client reuse in a shell boundary. + * @effect none during construction; returned helpers perform HTTP IO when their Effects run. + * @invariant cache is keyed only by resolved baseUrl and invalidated on baseUrl change. + * @precondition resolveBaseUrl is deterministic for the duration of a single request Effect. + * @postcondition consumers can share OpenAPI helpers without importing app-specific base URL logic. + * @complexity O(1)/O(1) for client lookup, excluding request execution. + * @throws Never. + */ +export const makeDockerGitOpenApiRuntime = ( + options: DockerGitOpenApiRuntimeOptions +): DockerGitOpenApiRuntime => { + const clientCache: { + baseUrl: string | null + client: DockerGitOpenApiClient | null + } = { + baseUrl: null, + client: null + } + + const getOpenApiClient = (): DockerGitOpenApiClient => { + const baseUrl = options.resolveBaseUrl() + if (clientCache.client === null || clientCache.baseUrl !== baseUrl) { + clientCache.baseUrl = baseUrl + clientCache.client = createDockerGitOpenApiClient(baseUrl) + } + return clientCache.client + } + + const runRuntimeOpenApi = (request: OpenApiRequest): Effect.Effect, string> => + Effect.tryPromise({ + try: () => request(getOpenApiClient()), + catch: String + }) + + return { + openApiJson: (request) => openApiJsonWithRunner(runRuntimeOpenApi, request), + openApiJsonSchema: (schema, request) => openApiJsonSchemaWithRunner(runRuntimeOpenApi, schema, request), + openApiVoid: (request) => openApiVoidWithRunner(runRuntimeOpenApi, request) + } +} diff --git a/packages/openapi/src/index.ts b/packages/openapi/src/index.ts new file mode 100644 index 00000000..5f171cd1 --- /dev/null +++ b/packages/openapi/src/index.ts @@ -0,0 +1,2 @@ +export * from "./client.js" +export * from "./openapi-paths.js" diff --git a/packages/openapi/src/openapi-paths.ts b/packages/openapi/src/openapi-paths.ts new file mode 100644 index 00000000..21e1bdd6 --- /dev/null +++ b/packages/openapi/src/openapi-paths.ts @@ -0,0 +1,9600 @@ +/** + * This file was auto-generated by openapi-typescript. + * Do not make direct changes to the file. + */ + +export interface paths { + "/health": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["core.health"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["projects.listProjects"]; + put?: never; + post: operations["projects.createProject"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/apply-all": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["projects.applyAllProjects"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/down-all": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["projects.downAllProjects"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/{projectId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["projects.getProject"]; + put?: never; + post?: never; + delete: operations["projects.deleteProject"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/{projectId}/down": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["projects.downProject"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/{projectId}/apply": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["projects.applyProject"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/{projectId}/up": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["projects.upProject"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/{projectId}/resume": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["projects.resumeProject"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/{projectId}/suspend": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["projects.suspendProject"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/{projectId}/ps": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["projects.projectPs"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/{projectId}/logs": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["projects.projectLogs"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/{projectId}/ports": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["projectPorts.listProjectPorts"]; + put?: never; + post: operations["projectPorts.createProjectPort"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/{projectId}/ports/{targetPort}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + delete: operations["projectPorts.deleteProjectPort"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/{projectId}/browser": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["projectBrowser.readProjectBrowser"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/{projectId}/browser/start": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["projectBrowser.startProjectBrowser"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/{projectId}/databases/profiles": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["projectDatabases.listDatabaseProfiles"]; + put?: never; + post: operations["projectDatabases.saveDatabaseProfile"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/{projectId}/databases/profiles/{profileId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + delete: operations["projectDatabases.deleteDatabaseProfile"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/{projectId}/databases/profiles/{profileId}/expose": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["projectDatabases.exposeDatabaseProfile"]; + delete: operations["projectDatabases.deleteDatabaseForward"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/{projectId}/databases/forwards": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["projectDatabases.listDatabaseForwards"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/{projectId}/databases/session": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["projectDatabases.readDatabaseSession"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/{projectId}/databases/open": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["projectDatabases.openDatabaseEditor"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/{projectId}/databases/restart": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["projectDatabases.restartDatabaseEditor"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/auth/github/status": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["auth.githubStatus"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/auth/gitlab/status": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["auth.gitlabStatus"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/auth/git/status": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["auth.gitStatus"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/auth/grok/status": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["auth.grokStatus"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/auth/codex/status": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["auth.codexStatus"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/auth/github/login": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["auth.githubLogin"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/auth/github/logout": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["auth.githubLogout"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/auth/gitlab/login": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["auth.gitlabLogin"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/auth/gitlab/logout": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["auth.gitlabLogout"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/auth/git/login": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["auth.gitLogin"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/auth/git/logout": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["auth.gitLogout"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/auth/menu": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["auth.authMenu"]; + put?: never; + post: operations["auth.authMenuAction"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/auth/terminal-sessions": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["auth.authTerminalSession"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/auth/codex/import": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["auth.codexImport"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/auth/codex/logout": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["auth.codexLogout"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/auth/grok/logout": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["auth.grokLogout"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/{projectId}/auth/menu": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["projectAuth.projectAuth"]; + put?: never; + post: operations["projectAuth.projectAuthAction"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/by-key/{projectKey}/terminal-sessions": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["terminal.listTerminalsByKey"]; + put?: never; + post: operations["terminal.createTerminalByKey"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/by-key/{projectKey}/terminal-sessions/start": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["terminal.startTerminalByKey"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/by-key/{projectKey}/terminal-sessions/{sessionId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["terminal.getTerminalByKey"]; + put?: never; + post?: never; + delete: operations["terminal.deleteTerminalByKey"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/by-key/{projectKey}/terminal-sessions/active": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put: operations["terminal.setActiveTerminalByKey"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/terminal-sessions/{sessionId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["terminal.lookupTerminal"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/auth/terminal-sessions/{sessionId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + delete: operations["terminal.deleteAuthTerminal"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/{projectId}/prompts": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["prompts.listPrompts"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/{projectId}/prompts/{kind}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put: operations["prompts.writePrompt"]; + post?: never; + delete: operations["prompts.deletePrompt"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/{projectId}/skills": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["skills.listSkills"]; + put?: never; + post: operations["skills.writeSkill"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/{projectId}/skills/{scopeId}/{name}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + delete: operations["skills.deleteSkill"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/{projectId}/tasks": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["tasks.listTasks"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/{projectId}/tasks/{pid}/stop": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post: operations["tasks.stopTask"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/projects/{projectId}/tasks/{pid}/logs": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["tasks.taskLogs"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/cloudflare-tunnels/panel": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["sharing.readPanelCloudflareTunnel"]; + put?: never; + post: operations["sharing.startPanelCloudflareTunnel"]; + delete: operations["sharing.stopPanelCloudflareTunnel"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; +} +export type webhooks = Record; +export interface components { + schemas: { + /** @description The request did not match the expected schema */ + HttpApiDecodeError: { + issues: components["schemas"]["Issue"][]; + message: string; + /** @enum {string} */ + _tag: "HttpApiDecodeError"; + }; + /** @description Represents an error encountered while parsing a value to match the schema */ + Issue: { + /** + * @description The tag identifying the type of parse issue + * @enum {string} + */ + _tag: "Pointer" | "Unexpected" | "Missing" | "Composite" | "Refinement" | "Transformation" | "Type" | "Forbidden"; + /** @description The path to the property where the issue occurred */ + path: components["schemas"]["PropertyKey"][]; + /** @description A descriptive message explaining the issue */ + message: string; + }; + PropertyKey: string | number | { + /** @enum {string} */ + _tag: "symbol"; + key: string; + }; + /** @description a string to be decoded into a number */ + NumberFromString: string; + /** + * Format: uuid + * @description a Universally Unique Identifier + */ + UUID: string; + }; + responses: never; + parameters: never; + requestBodies: never; + headers: never; + pathItems: never; +} +export type $defs = Record; +export interface operations { + "core.health": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + cwd: string; + ok: boolean; + projectsRoot: string; + revision: string | null; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "projects.listProjects": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + projects: { + clonedOnHostname?: string; + containerName?: string; + displayName: string; + id: string; + projectKey: string; + repoRef: string; + repoUrl: string; + sshSessions: number; + startedAtEpochMs: number | null; + startedAtIso: string | null; + /** @enum {string} */ + status: "running" | "stopped" | "unknown"; + statusLabel: string; + }[]; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "projects.createProject": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + repoUrl?: string; + repoRef?: string; + targetDir?: string; + sshPort?: string; + sshUser?: string; + containerName?: string; + serviceName?: string; + volumeName?: string; + secretsRoot?: string; + authorizedKeysPath?: string; + authorizedKeysContents?: string; + useManagedAuthorizedKeys?: boolean; + envGlobalPath?: string; + envProjectPath?: string; + codexAuthPath?: string; + codexHome?: string; + cpuLimit?: string; + ramLimit?: string; + playwrightCpuLimit?: string; + playwrightRamLimit?: string; + /** @enum {string} */ + gpu?: "none" | "all"; + dockerNetworkMode?: string; + dockerSharedNetworkName?: string; + enableMcpPlaywright?: boolean; + outDir?: string; + gitTokenLabel?: string; + skipGithubAuth?: boolean; + codexTokenLabel?: string; + claudeTokenLabel?: string; + geminiTokenLabel?: string; + grokTokenLabel?: string; + agentAutoMode?: string; + up?: boolean; + openSsh?: boolean; + force?: boolean; + forceEnv?: boolean; + waitForClone?: boolean; + async?: boolean; + /** + * maxLength(253) + * @description a string matching the pattern ^(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?)(?:\.[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$ + */ + clonedOnHostname?: string; + }; + }; + }; + responses: { + /** @description Success */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + project: { + clonedOnHostname?: string; + containerName: string; + displayName: string; + id: string; + projectKey: string; + repoRef: string; + repoUrl: string; + sshSessions: number; + startedAtEpochMs: number | null; + startedAtIso: string | null; + /** @enum {string} */ + status: "running" | "stopped" | "unknown"; + statusLabel: string; + authorizedKeysExists: boolean; + authorizedKeysPath: string; + codexAuthPath: string; + codexHome: string; + envGlobalPath: string; + envProjectPath: string; + /** @enum {string} */ + gpu: "none" | "all"; + projectDir: string; + serviceName: string; + sshCommand: string; + sshPort: number; + sshUser: string; + targetDir: string; + }; + }; + }; + }; + /** @description Success */ + 202: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @enum {boolean} */ + accepted: true; + cursor: number; + projectId: string; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "projects.applyAllProjects": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + activeOnly?: boolean; + }; + }; + }; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @enum {boolean} */ + ok: true; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "projects.downAllProjects": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @enum {boolean} */ + ok: true; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "projects.getProject": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + project: { + clonedOnHostname?: string; + containerName: string; + displayName: string; + id: string; + projectKey: string; + repoRef: string; + repoUrl: string; + sshSessions: number; + startedAtEpochMs: number | null; + startedAtIso: string | null; + /** @enum {string} */ + status: "running" | "stopped" | "unknown"; + statusLabel: string; + authorizedKeysExists: boolean; + authorizedKeysPath: string; + codexAuthPath: string; + codexHome: string; + envGlobalPath: string; + envProjectPath: string; + /** @enum {string} */ + gpu: "none" | "all"; + projectDir: string; + serviceName: string; + sshCommand: string; + sshPort: number; + sshUser: string; + targetDir: string; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "projects.deleteProject": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @enum {boolean} */ + ok: true; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "projects.downProject": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @enum {boolean} */ + ok: true; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "projects.applyProject": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + cpuLimit?: string; + ramLimit?: string; + playwrightCpuLimit?: string; + playwrightRamLimit?: string; + /** @enum {string} */ + gpu?: "none" | "all"; + }; + }; + }; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + project: { + clonedOnHostname?: string; + containerName: string; + displayName: string; + id: string; + projectKey: string; + repoRef: string; + repoUrl: string; + sshSessions: number; + startedAtEpochMs: number | null; + startedAtIso: string | null; + /** @enum {string} */ + status: "running" | "stopped" | "unknown"; + statusLabel: string; + authorizedKeysExists: boolean; + authorizedKeysPath: string; + codexAuthPath: string; + codexHome: string; + envGlobalPath: string; + envProjectPath: string; + /** @enum {string} */ + gpu: "none" | "all"; + projectDir: string; + serviceName: string; + sshCommand: string; + sshPort: number; + sshUser: string; + targetDir: string; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "projects.upProject": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + authorizedKeysContents?: string; + useManagedAuthorizedKeys?: boolean; + }; + }; + }; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + project: { + clonedOnHostname?: string; + containerName: string; + displayName: string; + id: string; + projectKey: string; + repoRef: string; + repoUrl: string; + sshSessions: number; + startedAtEpochMs: number | null; + startedAtIso: string | null; + /** @enum {string} */ + status: "running" | "stopped" | "unknown"; + statusLabel: string; + authorizedKeysExists: boolean; + authorizedKeysPath: string; + codexAuthPath: string; + codexHome: string; + envGlobalPath: string; + envProjectPath: string; + /** @enum {string} */ + gpu: "none" | "all"; + projectDir: string; + serviceName: string; + sshCommand: string; + sshPort: number; + sshUser: string; + targetDir: string; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "projects.resumeProject": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + project: { + clonedOnHostname?: string; + containerName: string; + displayName: string; + id: string; + projectKey: string; + repoRef: string; + repoUrl: string; + sshSessions: number; + startedAtEpochMs: number | null; + startedAtIso: string | null; + /** @enum {string} */ + status: "running" | "stopped" | "unknown"; + statusLabel: string; + authorizedKeysExists: boolean; + authorizedKeysPath: string; + codexAuthPath: string; + codexHome: string; + envGlobalPath: string; + envProjectPath: string; + /** @enum {string} */ + gpu: "none" | "all"; + projectDir: string; + serviceName: string; + sshCommand: string; + sshPort: number; + sshUser: string; + targetDir: string; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "projects.suspendProject": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + project: { + clonedOnHostname?: string; + containerName: string; + displayName: string; + id: string; + projectKey: string; + repoRef: string; + repoUrl: string; + sshSessions: number; + startedAtEpochMs: number | null; + startedAtIso: string | null; + /** @enum {string} */ + status: "running" | "stopped" | "unknown"; + statusLabel: string; + authorizedKeysExists: boolean; + authorizedKeysPath: string; + codexAuthPath: string; + codexHome: string; + envGlobalPath: string; + envProjectPath: string; + /** @enum {string} */ + gpu: "none" | "all"; + projectDir: string; + serviceName: string; + sshCommand: string; + sshPort: number; + sshUser: string; + targetDir: string; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "projects.projectPs": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + output: string; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "projects.projectLogs": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + output: string; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "projectPorts.listProjectPorts": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + forwards: { + bindHost: string; + containerName: string; + createdAt: string | null; + hostPort: number; + id: string; + projectId: string; + projectKey: string; + proxyPath: string; + publicHost: string; + /** @enum {string} */ + status: "running" | "stopped" | "unknown"; + targetContainerName: string; + targetPort: number; + url: string; + }[]; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "projectPorts.createProjectPort": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + hostPort?: number; + targetPort: number; + }; + }; + }; + responses: { + /** @description Success */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + forward: { + bindHost: string; + containerName: string; + createdAt: string | null; + hostPort: number; + id: string; + projectId: string; + projectKey: string; + proxyPath: string; + publicHost: string; + /** @enum {string} */ + status: "running" | "stopped" | "unknown"; + targetContainerName: string; + targetPort: number; + url: string; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "projectPorts.deleteProjectPort": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + targetPort: components["schemas"]["NumberFromString"]; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @enum {boolean} */ + ok: true; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "projectBrowser.readProjectBrowser": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + browser: { + cdpPath: string; + cdpUrl: string; + containerName: string; + noVncPath: string; + noVncUrl: string; + projectId: string; + projectKey: string; + /** @enum {string} */ + status: "running" | "stopped" | "missing" | "unknown"; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "projectBrowser.startProjectBrowser": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + browser: { + cdpPath: string; + cdpUrl: string; + containerName: string; + noVncPath: string; + noVncUrl: string; + projectId: string; + projectKey: string; + /** @enum {string} */ + status: "running" | "stopped" | "missing" | "unknown"; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "projectDatabases.listDatabaseProfiles": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + profiles: { + createdAt: string; + database: string; + /** @enum {string} */ + engine: "postgres" | "mysql" | "mariadb"; + host: string; + id: string; + label: string; + maskedConnectionString: string; + port: number; + updatedAt: string; + user: string; + }[]; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "projectDatabases.saveDatabaseProfile": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + connectionString: string; + label?: string | null; + }; + }; + }; + responses: { + /** @description Success */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + profile: { + createdAt: string; + database: string; + /** @enum {string} */ + engine: "postgres" | "mysql" | "mariadb"; + host: string; + id: string; + label: string; + maskedConnectionString: string; + port: number; + updatedAt: string; + user: string; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "projectDatabases.deleteDatabaseProfile": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + profileId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @enum {boolean} */ + ok: true; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "projectDatabases.exposeDatabaseProfile": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + profileId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + forward: { + bindHost: string; + containerName: string; + createdAt: string | null; + database: string; + /** @enum {string} */ + engine: "postgres" | "mysql" | "mariadb"; + externalConnectionString: string; + hostPort: number; + id: string; + maskedExternalConnectionString: string; + profileId: string; + profileLabel: string; + projectId: string; + projectKey: string; + publicHost: string; + /** @enum {string} */ + status: "running" | "stopped" | "unknown"; + targetHost: string; + targetPort: number; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "projectDatabases.deleteDatabaseForward": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + profileId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @enum {boolean} */ + ok: true; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "projectDatabases.listDatabaseForwards": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + forwards: { + bindHost: string; + containerName: string; + createdAt: string | null; + database: string; + /** @enum {string} */ + engine: "postgres" | "mysql" | "mariadb"; + externalConnectionString: string; + hostPort: number; + id: string; + maskedExternalConnectionString: string; + profileId: string; + profileLabel: string; + projectId: string; + projectKey: string; + publicHost: string; + /** @enum {string} */ + status: "running" | "stopped" | "unknown"; + targetHost: string; + targetPort: number; + }[]; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "projectDatabases.readDatabaseSession": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + session: { + configHash: string; + containerName: string; + editorPath: string; + editorUrl: string; + projectId: string; + projectKey: string; + /** @enum {string} */ + status: "running" | "stopped" | "missing" | "unknown"; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "projectDatabases.openDatabaseEditor": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + session: { + configHash: string; + containerName: string; + editorPath: string; + editorUrl: string; + projectId: string; + projectKey: string; + /** @enum {string} */ + status: "running" | "stopped" | "missing" | "unknown"; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "projectDatabases.restartDatabaseEditor": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + session: { + configHash: string; + containerName: string; + editorPath: string; + editorUrl: string; + projectId: string; + projectKey: string; + /** @enum {string} */ + status: "running" | "stopped" | "missing" | "unknown"; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "auth.githubStatus": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + status: { + summary: string; + tokens: { + key: string; + label: string; + login: string | null; + /** @enum {string} */ + status: "valid" | "invalid" | "unknown"; + }[]; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "auth.gitlabStatus": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + status: { + summary: string; + tokens: { + key: string; + label: string; + login: string | null; + /** @enum {string} */ + status: "valid" | "invalid" | "unknown"; + }[]; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "auth.gitStatus": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + status: { + connections: { + host: string; + user: string; + }[]; + summary: string; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "auth.grokStatus": { + parameters: { + query?: { + label?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + status: { + authPath: string; + connected: boolean; + label: string; + message: string; + /** @enum {string} */ + method: "none" | "api-key" | "oauth"; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "auth.codexStatus": { + parameters: { + query?: { + label?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + status: { + account: string | null; + authPath: string; + label: string; + message: string; + present: boolean; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "auth.githubLogin": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + label?: string | null; + token?: string | null; + scopes?: string | null; + }; + }; + }; + responses: { + /** @description Success */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + status: { + summary: string; + tokens: { + key: string; + label: string; + login: string | null; + /** @enum {string} */ + status: "valid" | "invalid" | "unknown"; + }[]; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "auth.githubLogout": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + label?: string | null; + }; + }; + }; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + status: { + summary: string; + tokens: { + key: string; + label: string; + login: string | null; + /** @enum {string} */ + status: "valid" | "invalid" | "unknown"; + }[]; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "auth.gitlabLogin": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + label?: string | null; + token?: string | null; + }; + }; + }; + responses: { + /** @description Success */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + status: { + summary: string; + tokens: { + key: string; + label: string; + login: string | null; + /** @enum {string} */ + status: "valid" | "invalid" | "unknown"; + }[]; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "auth.gitlabLogout": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + label?: string | null; + }; + }; + }; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + status: { + summary: string; + tokens: { + key: string; + label: string; + login: string | null; + /** @enum {string} */ + status: "valid" | "invalid" | "unknown"; + }[]; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "auth.gitLogin": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + host: string; + token?: string | null; + user?: string | null; + }; + }; + }; + responses: { + /** @description Success */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + status: { + connections: { + host: string; + user: string; + }[]; + summary: string; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "auth.gitLogout": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + host: string; + }; + }; + }; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + status: { + connections: { + host: string; + user: string; + }[]; + summary: string; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "auth.authMenu": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + snapshot: { + claudeAuthEntries: number; + claudeAuthPath: string; + codexAuthEntries?: number; + codexAuthPath?: string; + geminiAuthEntries: number; + geminiAuthPath: string; + gitTokenEntries: number; + gitUserEntries: number; + githubTokenEntries: number; + globalEnvPath: string; + grokAuthEntries?: number; + grokAuthPath?: string; + totalEntries: number; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "auth.authMenuAction": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + /** @enum {string} */ + flow: "GithubRemove" | "GitSet" | "GitRemove" | "ClaudeLogout" | "GeminiApiKey" | "GeminiLogout" | "GrokApiKey" | "GrokLogout"; + label?: string | null; + token?: string | null; + user?: string | null; + apiKey?: string | null; + }; + }; + }; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + snapshot: { + claudeAuthEntries: number; + claudeAuthPath: string; + codexAuthEntries?: number; + codexAuthPath?: string; + geminiAuthEntries: number; + geminiAuthPath: string; + gitTokenEntries: number; + gitUserEntries: number; + githubTokenEntries: number; + globalEnvPath: string; + grokAuthEntries?: number; + grokAuthPath?: string; + totalEntries: number; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "auth.authTerminalSession": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + /** @enum {string} */ + flow: "ClaudeOauth" | "GeminiOauth" | "GrokOauth"; + label?: string | null; + }; + }; + }; + responses: { + /** @description Success */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + session: { + attachedClients?: number; + closedAt?: string; + createdAt: string; + exitCode?: number; + id: string; + projectId: string; + signal?: number; + sshCommand: string; + startedAt?: string; + /** @enum {string} */ + status: "ready" | "attached" | "exited" | "failed"; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "auth.codexImport": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + label?: string | null; + authText: string; + }; + }; + }; + responses: { + /** @description Success */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + status: { + account: string | null; + authPath: string; + label: string; + message: string; + present: boolean; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "auth.codexLogout": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + label?: string | null; + }; + }; + }; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + status: { + account: string | null; + authPath: string; + label: string; + message: string; + present: boolean; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "auth.grokLogout": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + label?: string | null; + }; + }; + }; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + status: { + authPath: string; + connected: boolean; + label: string; + message: string; + /** @enum {string} */ + method: "none" | "api-key" | "oauth"; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "projectAuth.projectAuth": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + snapshot: { + activeClaudeLabel: string | null; + activeGeminiLabel: string | null; + activeGitLabel: string | null; + activeGithubLabel: string | null; + activeGrokLabel: string | null; + claudeAuthEntries: number; + claudeAuthPath: string; + codexAuthEntries?: number; + codexAuthPath?: string; + envGlobalPath: string; + envProjectPath: string; + geminiAuthEntries: number; + geminiAuthPath: string; + gitTokenEntries: number; + githubTokenEntries: number; + grokAuthEntries?: number; + grokAuthPath?: string; + projectDir: string; + projectName: string; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "projectAuth.projectAuthAction": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + /** @enum {string} */ + flow: "ProjectGithubConnect" | "ProjectGithubDisconnect" | "ProjectGitConnect" | "ProjectGitDisconnect" | "ProjectClaudeConnect" | "ProjectClaudeDisconnect" | "ProjectGeminiConnect" | "ProjectGeminiDisconnect" | "ProjectGrokConnect" | "ProjectGrokDisconnect"; + label?: string | null; + }; + }; + }; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + snapshot: { + activeClaudeLabel: string | null; + activeGeminiLabel: string | null; + activeGitLabel: string | null; + activeGithubLabel: string | null; + activeGrokLabel: string | null; + claudeAuthEntries: number; + claudeAuthPath: string; + codexAuthEntries?: number; + codexAuthPath?: string; + envGlobalPath: string; + envProjectPath: string; + geminiAuthEntries: number; + geminiAuthPath: string; + gitTokenEntries: number; + githubTokenEntries: number; + grokAuthEntries?: number; + grokAuthPath?: string; + projectDir: string; + projectName: string; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "terminal.listTerminalsByKey": { + parameters: { + query?: never; + header?: never; + path: { + projectKey: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + activeSessionId: string | null; + sessions: { + attachedClients?: number; + closedAt?: string; + createdAt: string; + exitCode?: number; + id: string; + projectId: string; + signal?: number; + sshCommand: string; + startedAt?: string; + /** @enum {string} */ + status: "ready" | "attached" | "exited" | "failed"; + }[]; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "terminal.createTerminalByKey": { + parameters: { + query?: never; + header?: never; + path: { + projectKey: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + project: { + clonedOnHostname?: string; + containerName: string; + displayName: string; + id: string; + projectKey: string; + repoRef: string; + repoUrl: string; + sshSessions: number; + startedAtEpochMs: number | null; + startedAtIso: string | null; + /** @enum {string} */ + status: "running" | "stopped" | "unknown"; + statusLabel: string; + authorizedKeysExists: boolean; + authorizedKeysPath: string; + codexAuthPath: string; + codexHome: string; + envGlobalPath: string; + envProjectPath: string; + /** @enum {string} */ + gpu: "none" | "all"; + projectDir: string; + serviceName: string; + sshCommand: string; + sshPort: number; + sshUser: string; + targetDir: string; + }; + session: { + attachedClients?: number; + closedAt?: string; + createdAt: string; + exitCode?: number; + id: string; + projectId: string; + signal?: number; + sshCommand: string; + startedAt?: string; + /** @enum {string} */ + status: "ready" | "attached" | "exited" | "failed"; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "terminal.startTerminalByKey": { + parameters: { + query?: never; + header?: never; + path: { + projectKey: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + requestId: components["schemas"]["UUID"]; + }; + }; + }; + responses: { + /** @description Success */ + 202: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @enum {boolean} */ + accepted: true; + cursor: number; + projectId: string; + requestId: string; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "terminal.getTerminalByKey": { + parameters: { + query?: never; + header?: never; + path: { + projectKey: string; + sessionId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + session: { + attachedClients?: number; + closedAt?: string; + createdAt: string; + exitCode?: number; + id: string; + projectId: string; + signal?: number; + sshCommand: string; + startedAt?: string; + /** @enum {string} */ + status: "ready" | "attached" | "exited" | "failed"; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "terminal.deleteTerminalByKey": { + parameters: { + query?: never; + header?: never; + path: { + projectKey: string; + sessionId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @enum {boolean} */ + ok: true; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "terminal.setActiveTerminalByKey": { + parameters: { + query?: never; + header?: never; + path: { + projectKey: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + sessionId: string; + }; + }; + }; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + session: { + attachedClients?: number; + closedAt?: string; + createdAt: string; + exitCode?: number; + id: string; + projectId: string; + signal?: number; + sshCommand: string; + startedAt?: string; + /** @enum {string} */ + status: "ready" | "attached" | "exited" | "failed"; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "terminal.lookupTerminal": { + parameters: { + query?: never; + header?: never; + path: { + sessionId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + projectDisplayName: string; + projectKey: string; + session: { + attachedClients?: number; + closedAt?: string; + createdAt: string; + exitCode?: number; + id: string; + projectId: string; + signal?: number; + sshCommand: string; + startedAt?: string; + /** @enum {string} */ + status: "ready" | "attached" | "exited" | "failed"; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "terminal.deleteAuthTerminal": { + parameters: { + query?: never; + header?: never; + path: { + sessionId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @enum {boolean} */ + ok: true; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "prompts.listPrompts": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + snapshot: { + projectDir: string; + projectId: string; + projectKey: string; + prompts: { + absolutePath: string; + bytes: number; + content: string; + exists: boolean; + fileName: string; + /** @enum {string} */ + kind: "claude" | "codex" | "gemini" | "grok"; + relativePath: string; + }[]; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "prompts.writePrompt": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + kind: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + content: string; + }; + }; + }; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + prompt: { + absolutePath: string; + bytes: number; + content: string; + exists: boolean; + fileName: string; + /** @enum {string} */ + kind: "claude" | "codex" | "gemini" | "grok"; + relativePath: string; + }; + snapshot: { + projectDir: string; + projectId: string; + projectKey: string; + prompts: { + absolutePath: string; + bytes: number; + content: string; + exists: boolean; + fileName: string; + /** @enum {string} */ + kind: "claude" | "codex" | "gemini" | "grok"; + relativePath: string; + }[]; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "prompts.deletePrompt": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + kind: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + snapshot: { + projectDir: string; + projectId: string; + projectKey: string; + prompts: { + absolutePath: string; + bytes: number; + content: string; + exists: boolean; + fileName: string; + /** @enum {string} */ + kind: "claude" | "codex" | "gemini" | "grok"; + relativePath: string; + }[]; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "skills.listSkills": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + snapshot: { + projectDir: string; + projectId: string; + projectKey: string; + scopes: { + absoluteRoot: string; + relativeRoot: string; + /** @enum {string} */ + scope: "skills" | "agents/skills" | "agents/.skills" | "claude/skills" | "codex/skills" | "gemini/skills" | "grok/skills"; + }[]; + skills: { + absolutePath: string; + bytes: number; + content: string; + id: string; + name: string; + relativePath: string; + /** @enum {string} */ + scope: "skills" | "agents/skills" | "agents/.skills" | "claude/skills" | "codex/skills" | "gemini/skills" | "grok/skills"; + updatedAtIso: string | null; + }[]; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "skills.writeSkill": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + /** @enum {string} */ + scope: "skills" | "agents/skills" | "agents/.skills" | "claude/skills" | "codex/skills" | "gemini/skills" | "grok/skills"; + name: string; + content: string; + }; + }; + }; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + skill: { + absolutePath: string; + bytes: number; + content: string; + id: string; + name: string; + relativePath: string; + /** @enum {string} */ + scope: "skills" | "agents/skills" | "agents/.skills" | "claude/skills" | "codex/skills" | "gemini/skills" | "grok/skills"; + updatedAtIso: string | null; + }; + snapshot: { + projectDir: string; + projectId: string; + projectKey: string; + scopes: { + absoluteRoot: string; + relativeRoot: string; + /** @enum {string} */ + scope: "skills" | "agents/skills" | "agents/.skills" | "claude/skills" | "codex/skills" | "gemini/skills" | "grok/skills"; + }[]; + skills: { + absolutePath: string; + bytes: number; + content: string; + id: string; + name: string; + relativePath: string; + /** @enum {string} */ + scope: "skills" | "agents/skills" | "agents/.skills" | "claude/skills" | "codex/skills" | "gemini/skills" | "grok/skills"; + updatedAtIso: string | null; + }[]; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "skills.deleteSkill": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + scopeId: string; + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + ok?: boolean; + snapshot: { + projectDir: string; + projectId: string; + projectKey: string; + scopes: { + absoluteRoot: string; + relativeRoot: string; + /** @enum {string} */ + scope: "skills" | "agents/skills" | "agents/.skills" | "claude/skills" | "codex/skills" | "gemini/skills" | "grok/skills"; + }[]; + skills: { + absolutePath: string; + bytes: number; + content: string; + id: string; + name: string; + relativePath: string; + /** @enum {string} */ + scope: "skills" | "agents/skills" | "agents/.skills" | "claude/skills" | "codex/skills" | "gemini/skills" | "grok/skills"; + updatedAtIso: string | null; + }[]; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "tasks.listTasks": { + parameters: { + query?: { + includeDefault?: string; + }; + header?: never; + path: { + projectId: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + snapshot: { + agents: { + id: string; + projectId: string; + /** @enum {string} */ + provider: "codex" | "opencode" | "claude" | "grok" | "custom"; + label: string; + command: string; + containerName: string; + /** @enum {string} */ + status: "starting" | "running" | "stopping" | "stopped" | "exited" | "failed"; + source: string; + pidFile: string; + hostPid: number | null; + startedAt: string; + updatedAt: string; + stoppedAt?: string; + exitCode?: number; + signal?: string; + }[]; + containerName: string; + generatedAt: string; + projectId: string; + sshConnections: number; + tasks: { + command: string; + elapsed?: string; + etime: string; + etimes: number; + /** @enum {string} */ + kind: "ssh" | "web-terminal" | "agent" | "background" | "system"; + logAvailable: boolean; + managedId?: string; + pid: number; + ppid: number; + tty: string; + user: string; + }[]; + terminalSessions: { + attachedClients?: number; + closedAt?: string; + createdAt: string; + exitCode?: number; + id: string; + projectId: string; + signal?: number; + sshCommand: string; + startedAt?: string; + /** @enum {string} */ + status: "ready" | "attached" | "exited" | "failed"; + }[]; + }; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "tasks.stopTask": { + parameters: { + query?: never; + header?: never; + path: { + projectId: string; + pid: components["schemas"]["NumberFromString"]; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + /** @enum {boolean} */ + ok: true; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "tasks.taskLogs": { + parameters: { + query?: { + lines?: string; + }; + header?: never; + path: { + projectId: string; + pid: components["schemas"]["NumberFromString"]; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + output: string; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "sharing.readPanelCloudflareTunnel": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + tunnel: { + error: string | null; + id: string; + logTail: string[]; + panelUrl: string; + publicUrl: string | null; + startedAt: string; + /** @enum {string} */ + status: "starting" | "running" | "stopped" | "failed"; + stoppedAt: string | null; + } | null; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "sharing.startPanelCloudflareTunnel": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": { + panelUrl: string; + }; + }; + }; + responses: { + /** @description Success */ + 202: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + tunnel: { + error: string | null; + id: string; + logTail: string[]; + panelUrl: string; + publicUrl: string | null; + startedAt: string; + /** @enum {string} */ + status: "starting" | "running" | "stopped" | "failed"; + stoppedAt: string | null; + } | null; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; + "sharing.stopPanelCloudflareTunnel": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Success */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + tunnel: { + error: string | null; + id: string; + logTail: string[]; + panelUrl: string; + publicUrl: string | null; + startedAt: string; + /** @enum {string} */ + status: "starting" | "running" | "stopped" | "failed"; + stoppedAt: string | null; + } | null; + }; + }; + }; + /** @description The request did not match the expected schema */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HttpApiDecodeError"] | { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + /** @description Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": { + error: { + command?: string; + /** unknown */ + details?: unknown; + message: string; + provider?: string; + type: string; + }; + }; + }; + }; + }; + }; +} diff --git a/packages/openapi/tsconfig.json b/packages/openapi/tsconfig.json new file mode 100644 index 00000000..b244d935 --- /dev/null +++ b/packages/openapi/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": ".", + "lib": ["ES2023", "DOM"], + "types": [] + }, + "include": ["src/**/*"], + "exclude": ["node_modules"] +} diff --git a/scripts/e2e/local-package-cli.sh b/scripts/e2e/local-package-cli.sh index f06dac31..7d895dd0 100755 --- a/scripts/e2e/local-package-cli.sh +++ b/scripts/e2e/local-package-cli.sh @@ -12,11 +12,14 @@ KEEP="${KEEP:-0}" PACK_LOG="$ROOT/bun-pack.log" SESSION_PACK_LOG="$ROOT/bun-pack-session-sync.log" +OPENAPI_PACK_LOG="$ROOT/bun-pack-openapi.log" HELP_LOG_BUN="$ROOT/docker-git-help-bun.log" TAR_LIST="$ROOT/tar-list.txt" SESSION_TAR_LIST="$ROOT/session-tar-list.txt" +OPENAPI_TAR_LIST="$ROOT/openapi-tar-list.txt" PACKED_TARBALL="" SESSION_PACKED_TARBALL="" +OPENAPI_PACKED_TARBALL="" PACKAGE_JSON="$REPO_ROOT/packages/app/package.json" PACKAGE_JSON_BACKUP="$ROOT/package.json.backup" @@ -36,6 +39,10 @@ on_error() { echo "--- bun pack session sync log ---" >&2 cat "$SESSION_PACK_LOG" >&2 || true fi + if [[ -f "$OPENAPI_PACK_LOG" ]]; then + echo "--- bun pack openapi log ---" >&2 + cat "$OPENAPI_PACK_LOG" >&2 || true + fi if [[ -f "$HELP_LOG_BUN" ]]; then echo "--- bun run docker-git --help log ---" >&2 cat "$HELP_LOG_BUN" >&2 || true @@ -56,6 +63,9 @@ cleanup() { if [[ -n "$SESSION_PACKED_TARBALL" ]] && [[ -f "$SESSION_PACKED_TARBALL" ]]; then rm -f "$SESSION_PACKED_TARBALL" >/dev/null 2>&1 || true fi + if [[ -n "$OPENAPI_PACKED_TARBALL" ]] && [[ -f "$OPENAPI_PACKED_TARBALL" ]]; then + rm -f "$OPENAPI_PACKED_TARBALL" >/dev/null 2>&1 || true + fi rm -rf "$ROOT" >/dev/null 2>&1 || true } @@ -80,8 +90,19 @@ session_first_line="$(head -n 1 "$session_entry_tmp" | tr -d '\r')" [[ "$session_first_line" == "#!/usr/bin/env bun" ]] \ || fail "packed session sync entrypoint missing shebang: expected '#!/usr/bin/env bun', got '$session_first_line'" +cd "$REPO_ROOT/packages/openapi" +OPENAPI_PACKED_TARBALL="$(bun pm pack --quiet --ignore-scripts --destination "$ROOT" | tee "$OPENAPI_PACK_LOG" | tail -n 1 | tr -d '\r')" +[[ -n "$OPENAPI_PACKED_TARBALL" ]] || fail "bun pm pack did not return openapi tarball path" +[[ -f "$OPENAPI_PACKED_TARBALL" ]] || fail "packed openapi tarball not found: $OPENAPI_PACKED_TARBALL" + +tar -tf "$OPENAPI_PACKED_TARBALL" >"$OPENAPI_TAR_LIST" +grep -Fq -- "package/src/index.ts" "$OPENAPI_TAR_LIST" \ + || fail "packed openapi tarball does not include src/index.ts" +grep -Fq -- "package/openapi.json" "$OPENAPI_TAR_LIST" \ + || fail "packed openapi tarball does not include openapi.json" + cp "$PACKAGE_JSON" "$PACKAGE_JSON_BACKUP" -SESSION_PACKED_TARBALL="$SESSION_PACKED_TARBALL" bun -e 'import { readFileSync, writeFileSync } from "node:fs"; const path = process.argv[1]; const pkg = JSON.parse(readFileSync(path, "utf8")); delete pkg.devDependencies; pkg.dependencies = pkg.dependencies ?? {}; pkg.dependencies["@prover-coder-ai/docker-git-session-sync"] = `file:${process.env.SESSION_PACKED_TARBALL}`; writeFileSync(path, JSON.stringify(pkg, null, 2) + "\n");' "$PACKAGE_JSON" +SESSION_PACKED_TARBALL="$SESSION_PACKED_TARBALL" OPENAPI_PACKED_TARBALL="$OPENAPI_PACKED_TARBALL" bun -e 'import { readFileSync, writeFileSync } from "node:fs"; const path = process.argv[1]; const pkg = JSON.parse(readFileSync(path, "utf8")); delete pkg.devDependencies; pkg.dependencies = pkg.dependencies ?? {}; pkg.dependencies["@prover-coder-ai/docker-git-session-sync"] = `file:${process.env.SESSION_PACKED_TARBALL}`; pkg.dependencies["@prover-coder-ai/docker-git-openapi"] = `file:${process.env.OPENAPI_PACKED_TARBALL}`; writeFileSync(path, JSON.stringify(pkg, null, 2) + "\n");' "$PACKAGE_JSON" cd "$REPO_ROOT/packages/app" PACKED_TARBALL="$(bun pm pack --quiet --ignore-scripts --destination "$ROOT" | tee "$PACK_LOG" | tail -n 1 | tr -d '\r')" diff --git a/scripts/write-openapi.ts b/scripts/write-openapi.ts new file mode 100644 index 00000000..f1e30a12 --- /dev/null +++ b/scripts/write-openapi.ts @@ -0,0 +1,23 @@ +import { dirname, resolve } from "node:path" +import { fileURLToPath } from "node:url" + +import { buildDockerGitOpenApi } from "../packages/api/src/api/openapi.js" + +const __filename = fileURLToPath(import.meta.url) +const __dirname = dirname(__filename) +const repositoryRoot = resolve(__dirname, "..") +const outputPath = resolve(repositoryRoot, "packages/openapi/openapi.json") + +const describeWriteError = (error: unknown): string => + error instanceof Error ? error.message : String(error) + +try { + const spec = buildDockerGitOpenApi() + const content = `${JSON.stringify(spec, null, 2)}\n` + + await Bun.write(outputPath, content) + console.log(`OpenAPI spec written to ${outputPath}`) +} catch (error) { + console.error(`Failed to write OpenAPI spec: ${describeWriteError(error)}`) + process.exit(1) +}