From 75bd1b0266514ea674b14bdd759397ab22c080c8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 27 Jun 2026 08:42:28 +0000 Subject: [PATCH 1/5] feat: add embeddings endpoint setting --- bun.lock | 74 +++++++--------- .../settings/EmbeddingsKeySection.tsx | 6 +- .../settings/SearchSection.dom.test.tsx | 87 ++++++++++++++++--- .../src/components/settings/SearchSection.tsx | 72 ++++++++++++++- packages/cli/src/commands/embeddings/index.ts | 14 +-- 5 files changed, 188 insertions(+), 65 deletions(-) diff --git a/bun.lock b/bun.lock index 64012d74..46e5b191 100644 --- a/bun.lock +++ b/bun.lock @@ -1774,7 +1774,7 @@ "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], - "@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="], + "@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="], "@types/node-fetch": ["@types/node-fetch@2.6.13", "", { "dependencies": { "@types/node": "*", "form-data": "^4.0.4" } }, "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw=="], @@ -4020,7 +4020,7 @@ "undici": ["undici@7.25.0", "", {}, "sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ=="], - "undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="], + "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], "unicorn-magic": ["unicorn-magic@0.3.0", "", {}, "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA=="], @@ -4272,11 +4272,7 @@ "@inkeep/cxkit-styled/tailwind-merge": ["tailwind-merge@2.6.0", "", {}, "sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA=="], - "@inkeep/open-knowledge/@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="], - - "@inkeep/open-knowledge-desktop/@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="], - - "@inkeep/open-knowledge-docs/@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="], + "@inkeep/open-knowledge-core/@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="], "@inkeep/open-knowledge-docs/lucide-react": ["lucide-react@0.503.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-HGGkdlPWQ0vTF8jJ5TdIqhQXZi6uh3LnNgfZ8MHiuxFfX3RZeA79r2MW2tHAZKlAVfoNE8esm3p+O6VkIvpj6w=="], @@ -4302,6 +4298,8 @@ "@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], + "@jest/types/@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="], + "@lingui/cli/jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="], "@lingui/conf/jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="], @@ -4414,23 +4412,13 @@ "@tiptap/starter-kit/@tiptap/pm": ["@tiptap/pm@3.22.3", "", { "dependencies": { "prosemirror-changeset": "^2.3.0", "prosemirror-collab": "^1.3.1", "prosemirror-commands": "^1.6.2", "prosemirror-dropcursor": "^1.8.1", "prosemirror-gapcursor": "^1.3.2", "prosemirror-history": "^1.4.1", "prosemirror-inputrules": "^1.4.0", "prosemirror-keymap": "^1.2.2", "prosemirror-markdown": "^1.13.1", "prosemirror-menu": "^1.2.4", "prosemirror-model": "^1.24.1", "prosemirror-schema-basic": "^1.2.3", "prosemirror-schema-list": "^1.5.0", "prosemirror-state": "^1.4.3", "prosemirror-tables": "^1.6.4", "prosemirror-trailing-node": "^3.0.0", "prosemirror-transform": "^1.10.2", "prosemirror-view": "^1.38.1" } }, "sha512-NjfWjZuvrqmpICT+GZWNIjtOdhPyqFKDMtQy7tsQ5rErM9L2ZQdy/+T/BKSO1JdTeBhdg9OP+0yfsqoYp2aT6A=="], - "@types/busboy/@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="], - - "@types/cacheable-request/@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="], - - "@types/fs-extra/@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="], + "@types/jsdom/@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="], "@types/jsdom/undici-types": ["undici-types@7.25.0", "", {}, "sha512-AXNgS1Byr27fTI+2bsPEkV9CxkT8H6xNyRI68b3TatlZo3RkzlqQBLL+w7SmGPVpokjHbcuNVQUWE7FRTg+LRA=="], - "@types/keyv/@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="], - - "@types/plist/@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="], - - "@types/responselike/@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="], + "@types/node-fetch/@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="], - "@types/ws/@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="], - - "@types/yauzl/@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="], + "@types/yazl/@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="], "ajv-keywords/ajv": ["ajv@6.14.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw=="], @@ -4452,8 +4440,12 @@ "ast-kit/@babel/parser": ["@babel/parser@8.0.0-rc.3", "", { "dependencies": { "@babel/types": "^8.0.0-rc.3" }, "bin": "./bin/babel-parser.js" }, "sha512-B20dvP3MfNc/XS5KKCHy/oyWl5IA6Cn9YjXRdDlCjNmUFrjvLXMNUfQq/QUy9fnG2gYkKKcrto2YaF9B32ToOQ=="], + "buffer-image-size/@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="], + "builder-util/fs-extra": ["fs-extra@10.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ=="], + "bun-types/@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="], + "cacache/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], "cacache/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], @@ -4492,8 +4484,6 @@ "dotenv-expand/dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="], - "electron/@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="], - "electron-builder/fs-extra": ["fs-extra@10.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ=="], "electron-publish/fs-extra": ["fs-extra@10.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ=="], @@ -4536,6 +4526,8 @@ "glob/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], + "happy-dom/@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="], + "happy-dom/whatwg-mimetype": ["whatwg-mimetype@3.0.0", "", {}, "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q=="], "hast-util-from-html/parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], @@ -4626,6 +4618,8 @@ "prosemirror-trailing-node/escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], + "protobufjs/@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="], + "proxy-addr/ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="], "proxy-agent/lru-cache": ["lru-cache@7.18.3", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="], @@ -4844,11 +4838,9 @@ "@inkeep/cxkit-primitives/@radix-ui/react-tooltip/@radix-ui/react-visually-hidden": ["@radix-ui/react-visually-hidden@1.1.1", "", { "dependencies": { "@radix-ui/react-primitive": "2.0.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-vVfA2IZ9q/J+gEamvj761Oq1FpWgCDaNOOIfbPVp2MVPLEomUr5+Vf7kJGwQ24YxZSlQVar7Bes8kyTo5Dshpg=="], - "@inkeep/open-knowledge-desktop/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + "@inkeep/open-knowledge-core/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="], - "@inkeep/open-knowledge-docs/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], - - "@inkeep/open-knowledge/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + "@inkeep/open-knowledge-server/@types/yazl/@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="], "@inquirer/confirm/@inquirer/core/@inquirer/ansi": ["@inquirer/ansi@1.0.2", "", {}, "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ=="], @@ -4866,6 +4858,8 @@ "@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], + "@jest/types/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="], + "@malept/flatpak-bundler/fs-extra/jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="], "@malept/flatpak-bundler/fs-extra/universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="], @@ -4908,21 +4902,11 @@ "@radix-ui/react-popover/@radix-ui/react-use-controllable-state/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jrBWOxZITuGcnjRCM2t2U5ZPkCLxD+Ym6DjfssS5haTj2iiak/DOb64JeN6OdLfLgptb6/e2kKR+ZuTrGoZTPA=="], - "@types/busboy/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], - - "@types/cacheable-request/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], - - "@types/fs-extra/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], - - "@types/keyv/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], - - "@types/plist/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], - - "@types/responselike/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + "@types/jsdom/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="], - "@types/ws/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + "@types/node-fetch/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="], - "@types/yauzl/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + "@types/yazl/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="], "ajv-keywords/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], @@ -4942,10 +4926,14 @@ "ast-kit/@babel/parser/@babel/types": ["@babel/types@8.0.0-rc.3", "", { "dependencies": { "@babel/helper-string-parser": "^8.0.0-rc.3", "@babel/helper-validator-identifier": "^8.0.0-rc.3" } }, "sha512-mOm5ZrYmphGfqVWoH5YYMTITb3cDXsFgmvFlvkvWDMsR9X8RFnt7a0Wb6yNIdoFsiMO9WjYLq+U/FMtqIYAF8Q=="], + "buffer-image-size/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="], + "builder-util/fs-extra/jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="], "builder-util/fs-extra/universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="], + "bun-types/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="], + "cacache/glob/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="], "cli-truncate/string-width/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], @@ -4974,8 +4962,6 @@ "electron-updater/fs-extra/universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="], - "electron/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], - "filelist/minimatch/brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="], "form-data/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], @@ -5038,6 +5024,8 @@ "glob/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="], + "happy-dom/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="], + "hast-util-from-html/parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], "hast-util-raw/parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], @@ -5074,6 +5062,8 @@ "prebuild-install/tar-fs/tar-stream": ["tar-stream@2.2.0", "", { "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.1.1" } }, "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ=="], + "protobufjs/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="], + "puppeteer-core/chromium-bidi/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], "puppeteer/puppeteer-core/webdriver-bidi-protocol": ["webdriver-bidi-protocol@0.4.1", "", {}, "sha512-ARrjNjtWRRs2w4Tk7nqrf2gBI0QXWuOmMCx2hU+1jUt6d00MjMxURrhxhGbrsoiZKJrhTSTzbIrc554iKI10qw=="], @@ -5264,6 +5254,8 @@ "@inkeep/cxkit-primitives/@radix-ui/react-tooltip/@radix-ui/react-use-controllable-state/@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw=="], + "@inkeep/open-knowledge-server/@types/yazl/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="], + "@opentelemetry/instrumentation-fetch/@opentelemetry/sdk-trace-web/@opentelemetry/sdk-trace-base/@opentelemetry/resources": ["@opentelemetry/resources@2.1.0", "", { "dependencies": { "@opentelemetry/core": "2.1.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-1CJjf3LCvoefUOgegxi8h6r4B/wLSzInyhGP2UmIBYNlo4Qk5CZ73e1eEyWmfXvFtm1ybkmfb2DqWvspsYLrWw=="], "app-builder-lib/@electron/fuses/fs-extra/jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="], diff --git a/packages/app/src/components/settings/EmbeddingsKeySection.tsx b/packages/app/src/components/settings/EmbeddingsKeySection.tsx index 3465833a..613c6710 100644 --- a/packages/app/src/components/settings/EmbeddingsKeySection.tsx +++ b/packages/app/src/components/settings/EmbeddingsKeySection.tsx @@ -57,13 +57,13 @@ export function EmbeddingsKeySection({ transport }: { transport?: EmbeddingsKeyT

- Your OpenAI API key, used only to create embeddings of your content for semantic search. - Stored once for this machine in{' '} + Your embeddings provider API key, used only to create embeddings of your content for + semantic search. Stored once for this machine in{' '} ~/.ok/secrets.yml {' '} (readable only by your user account) and shared across all projects. Turn the feature on - per project in This project → Search. + per project in This project → Search, where you can also override the endpoint.

diff --git a/packages/app/src/components/settings/SearchSection.dom.test.tsx b/packages/app/src/components/settings/SearchSection.dom.test.tsx index 29c7385c..11a8a56e 100644 --- a/packages/app/src/components/settings/SearchSection.dom.test.tsx +++ b/packages/app/src/components/settings/SearchSection.dom.test.tsx @@ -1,5 +1,10 @@ import { afterEach, beforeEach, describe, expect, mock, test } from 'bun:test'; -import type { Config, ConfigBinding, SemanticIndexStatus } from '@inkeep/open-knowledge-core'; +import { + DEFAULT_EMBEDDINGS_BASE_URL, + type Config, + type ConfigBinding, + type SemanticIndexStatus, +} from '@inkeep/open-knowledge-core'; import { cleanup, render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; @@ -44,8 +49,14 @@ mock.module('@/lib/config-provider', () => ({ const { SearchSection } = await import('./SearchSection'); -function configWithSemanticEnabled(enabled: boolean): Config { - return { search: { semantic: { enabled } } } as unknown as Config; +function configWithSemantic({ + enabled, + baseUrl, +}: { + enabled: boolean; + baseUrl?: string; +}): Config { + return { search: { semantic: { enabled, ...(baseUrl ? { baseUrl } : {}) } } } as unknown as Config; } function makeBinding(): { binding: ConfigBinding; calls: unknown[] } { @@ -87,7 +98,7 @@ describe('SearchSection', () => { test('off: switch is unchecked, body says no content leaves, no coverage panel', () => { const { binding } = makeBinding(); mockProjectLocalBinding = binding; - mockProjectLocalConfig = configWithSemanticEnabled(false); + mockProjectLocalConfig = configWithSemantic({ enabled: false }); render(); @@ -115,7 +126,7 @@ describe('SearchSection', () => { const user = userEvent.setup(); const { binding, calls } = makeBinding(); mockProjectLocalBinding = binding; - mockProjectLocalConfig = configWithSemanticEnabled(false); + mockProjectLocalConfig = configWithSemantic({ enabled: false }); render(); @@ -133,7 +144,7 @@ describe('SearchSection', () => { const user = userEvent.setup(); const { binding, calls } = makeBinding(); mockProjectLocalBinding = binding; - mockProjectLocalConfig = configWithSemanticEnabled(true); + mockProjectLocalConfig = configWithSemantic({ enabled: true }); mockStatus = { enabled: true, keyPresent: true, @@ -155,7 +166,7 @@ describe('SearchSection', () => { test('on + keyed + warmed + capable: shows read-only coverage', async () => { const { binding } = makeBinding(); mockProjectLocalBinding = binding; - mockProjectLocalConfig = configWithSemanticEnabled(true); + mockProjectLocalConfig = configWithSemantic({ enabled: true }); mockStatus = { enabled: true, keyPresent: true, @@ -175,7 +186,7 @@ describe('SearchSection', () => { test('on + capable but nothing embedded yet: shows the lazy-warm hint', async () => { const { binding } = makeBinding(); mockProjectLocalBinding = binding; - mockProjectLocalConfig = configWithSemanticEnabled(true); + mockProjectLocalConfig = configWithSemantic({ enabled: true }); mockStatus = { enabled: true, keyPresent: true, @@ -195,7 +206,7 @@ describe('SearchSection', () => { test('on + NO key: shows the needs-a-key hint pointing at Account (instant, no warm)', async () => { const { binding } = makeBinding(); mockProjectLocalBinding = binding; - mockProjectLocalConfig = configWithSemanticEnabled(true); + mockProjectLocalConfig = configWithSemantic({ enabled: true }); mockStatus = { enabled: true, keyPresent: false, @@ -218,7 +229,7 @@ describe('SearchSection', () => { test('on + key present but provider rejected it: shows the provider-error hint', async () => { const { binding } = makeBinding(); mockProjectLocalBinding = binding; - mockProjectLocalConfig = configWithSemanticEnabled(true); + mockProjectLocalConfig = configWithSemantic({ enabled: true }); mockStatus = { enabled: true, keyPresent: true, @@ -239,7 +250,7 @@ describe('SearchSection', () => { test('on + keyed but not warmed: shows the pending state', async () => { const { binding } = makeBinding(); mockProjectLocalBinding = binding; - mockProjectLocalConfig = configWithSemanticEnabled(true); + mockProjectLocalConfig = configWithSemantic({ enabled: true }); mockStatus = { enabled: true, keyPresent: true, @@ -285,7 +296,7 @@ describe('SearchSection', () => { const user = userEvent.setup(); const { binding, calls } = makeBinding(); mockProjectLocalBinding = binding; - mockProjectLocalConfig = configWithSemanticEnabled(false); + mockProjectLocalConfig = configWithSemantic({ enabled: false }); render(); @@ -305,7 +316,7 @@ describe('SearchSection', () => { patch: () => ({ ok: false, error: { code: 'noop', message: 'fail' } }), } as unknown as ConfigBinding; mockProjectLocalBinding = failBinding; - mockProjectLocalConfig = configWithSemanticEnabled(false); + mockProjectLocalConfig = configWithSemantic({ enabled: false }); render(); @@ -314,4 +325,54 @@ describe('SearchSection', () => { expect(await screen.findByTestId('settings-search-confirm')).toBeDefined(); }); + + test('shows the default endpoint when no custom provider is configured', () => { + const { binding } = makeBinding(); + mockProjectLocalBinding = binding; + mockProjectLocalConfig = configWithSemantic({ enabled: false }); + + render(); + + expect((screen.getByTestId('settings-search-base-url') as HTMLInputElement).value).toBe( + DEFAULT_EMBEDDINGS_BASE_URL, + ); + }); + + test('blurring the endpoint field writes the trimmed custom base URL', async () => { + const user = userEvent.setup(); + const { binding, calls } = makeBinding(); + mockProjectLocalBinding = binding; + mockProjectLocalConfig = configWithSemantic({ enabled: false }); + + render(); + + const input = screen.getByTestId('settings-search-base-url'); + await user.clear(input); + await user.type(input, ' https://azure.example.com/openai/v1/ '); + await user.tab(); + + expect(calls).toContainEqual({ + search: { semantic: { baseUrl: 'https://azure.example.com/openai/v1/' } }, + }); + }); + + test('clearing the endpoint field resets it to the default OpenAI endpoint', async () => { + const user = userEvent.setup(); + const { binding, calls } = makeBinding(); + mockProjectLocalBinding = binding; + mockProjectLocalConfig = configWithSemantic({ + enabled: false, + baseUrl: 'https://azure.example.com/openai/v1', + }); + + render(); + + const input = screen.getByTestId('settings-search-base-url'); + await user.clear(input); + await user.tab(); + + expect(calls).toContainEqual({ + search: { semantic: { baseUrl: DEFAULT_EMBEDDINGS_BASE_URL } }, + }); + }); }); diff --git a/packages/app/src/components/settings/SearchSection.tsx b/packages/app/src/components/settings/SearchSection.tsx index 99ef2fe0..217fc14c 100644 --- a/packages/app/src/components/settings/SearchSection.tsx +++ b/packages/app/src/components/settings/SearchSection.tsx @@ -1,4 +1,4 @@ -import { humanFormat } from '@inkeep/open-knowledge-core'; +import { DEFAULT_EMBEDDINGS_BASE_URL, humanFormat } from '@inkeep/open-knowledge-core'; import { Trans, useLingui } from '@lingui/react/macro'; import { useEffect, useRef, useState } from 'react'; import { toast } from 'sonner'; @@ -13,6 +13,7 @@ import { Dialog as DialogRoot, DialogTitle, } from '@/components/ui/dialog'; +import { Input } from '@/components/ui/input'; import { Switch } from '@/components/ui/switch'; import { useSemanticSearchStatus } from '@/hooks/use-semantic-search-status'; import { useConfigContext } from '@/lib/config-provider'; @@ -24,6 +25,7 @@ export function SearchSection() { const { projectLocalConfig, projectLocalSynced, projectLocalBinding } = useConfigContext(); const { status, refresh } = useSemanticSearchStatus(); const [confirmOpen, setConfirmOpen] = useState(false); + const [baseUrlInput, setBaseUrlInput] = useState(DEFAULT_EMBEDDINGS_BASE_URL); const settleTimersRef = useRef>>([]); useEffect( @@ -33,6 +35,13 @@ export function SearchSection() { [], ); + const configuredBaseUrl = + projectLocalConfig?.search?.semantic?.baseUrl ?? DEFAULT_EMBEDDINGS_BASE_URL; + + useEffect(() => { + setBaseUrlInput(configuredBaseUrl); + }, [configuredBaseUrl]); + const enabled = projectLocalConfig?.search?.semantic?.enabled ?? false; const bindingReady = projectLocalSynced && projectLocalBinding !== null; @@ -61,6 +70,28 @@ export function SearchSection() { return true; } + function writeBaseUrl(next: string): boolean { + if (projectLocalBinding === null) { + toast.error(t`Search settings not yet loaded — try again in a moment`); + return false; + } + const normalized = next.trim() || DEFAULT_EMBEDDINGS_BASE_URL; + if (normalized === configuredBaseUrl) { + setBaseUrlInput(normalized); + return true; + } + const result = projectLocalBinding.patch({ search: { semantic: { baseUrl: normalized } } }); + if (!result.ok) { + const detail = humanFormat(result.error); + toast.error(t`Failed to update the embeddings endpoint — ${detail}`); + return false; + } + setBaseUrlInput(normalized); + refresh(); + scheduleSettleRefresh(); + return true; + } + function onToggleRequest(next: boolean) { if (next) { setConfirmOpen(true); @@ -73,6 +104,10 @@ export function SearchSection() { if (write(true)) setConfirmOpen(false); } + function onBaseUrlBlur() { + writeBaseUrl(baseUrlInput); + } + const serverEnabled = status?.enabled ?? false; const keyPresent = status?.keyPresent ?? false; const ready = status?.ready ?? false; @@ -138,6 +173,41 @@ export function SearchSection() { ) : null} +
+
+ +

+ + Use the default OpenAI endpoint or override it with an OpenAI-compatible base URL for + Azure or a self-hosted provider. + +

+
+ setBaseUrlInput(e.target.value)} + onBlur={onBaseUrlBlur} + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault(); + writeBaseUrl(baseUrlInput); + } + }} + placeholder={DEFAULT_EMBEDDINGS_BASE_URL} + disabled={!bindingReady} + spellCheck={false} + autoComplete="off" + data-testid="settings-search-base-url" + className="h-8 font-mono text-sm" + /> +

+ Clear the field to reset back to the default OpenAI endpoint. +

+
+ { for await (const chunk of process.stdin) chunks.push(chunk as Buffer); return Buffer.concat(chunks).toString('utf-8').trim(); } - return (await password({ message: 'Enter OpenAI embeddings API key:' })).trim(); + return (await password({ message: 'Enter embeddings provider API key:' })).trim(); } function readSemanticConfig(projectDir: string) { @@ -57,7 +57,7 @@ async function fetchLiveCoverage( function setKeyCommand(): Command { return new Command('set-key') - .description('Store your OpenAI embeddings API key in ~/.ok/secrets.yml') + .description('Store your embeddings provider API key in ~/.ok/secrets.yml') .action(async () => { const key = await readKey(); if (!key) { @@ -67,9 +67,9 @@ function setKeyCommand(): Command { } await createEmbeddingsSecretStore().set(key); process.stderr.write( - '✓ OpenAI embeddings API key stored in ~/.ok/secrets.yml (0600, this machine only).\n' + + '✓ Embeddings provider API key stored in ~/.ok/secrets.yml (0600, this machine only).\n' + 'Now enable it per project — the easiest path is OK Desktop → Settings → This\n' + - 'project → Search (a toggle with an egress-confirmation prompt), or run\n' + + 'project → Search (toggle + endpoint settings), or run\n' + '`ok embeddings enable` in the project folder.\n', ); }); @@ -77,14 +77,14 @@ function setKeyCommand(): Command { function clearKeyCommand(): Command { return new Command('clear-key') - .description('Remove your stored OpenAI embeddings API key') + .description('Remove your stored embeddings provider API key') .action(async () => { const { touched } = await clearEmbeddingsKeyFromAllBackends(); if (touched.length === 0) { - process.stderr.write('No stored OpenAI embeddings key found.\n'); + process.stderr.write('No stored embeddings provider key found.\n'); return; } - process.stderr.write(`✓ OpenAI embeddings API key cleared (${touched.join(', ')}).\n`); + process.stderr.write(`✓ Embeddings provider API key cleared (${touched.join(', ')}).\n`); }); } From e9839e119382a515a284ffcd5e335e4778fa0611 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 27 Jun 2026 08:43:00 +0000 Subject: [PATCH 2/5] test: cover embeddings endpoint settings --- .changeset/custom-embeddings-endpoint.md | 5 +++++ .../app/src/components/settings/SearchSection.dom.test.tsx | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/custom-embeddings-endpoint.md diff --git a/.changeset/custom-embeddings-endpoint.md b/.changeset/custom-embeddings-endpoint.md new file mode 100644 index 00000000..2ae779d7 --- /dev/null +++ b/.changeset/custom-embeddings-endpoint.md @@ -0,0 +1,5 @@ +--- +"@inkeep/open-knowledge": patch +--- + +Configure a custom OpenAI-compatible embeddings endpoint from Settings → This project → Search instead of editing config files by hand. The semantic-search settings now expose the embeddings base URL directly, and the account copy plus `ok embeddings set-key` messaging now describe the key as belonging to the configured embeddings provider rather than only to OpenAI. diff --git a/packages/app/src/components/settings/SearchSection.dom.test.tsx b/packages/app/src/components/settings/SearchSection.dom.test.tsx index 11a8a56e..71b9b1f0 100644 --- a/packages/app/src/components/settings/SearchSection.dom.test.tsx +++ b/packages/app/src/components/settings/SearchSection.dom.test.tsx @@ -272,7 +272,7 @@ describe('SearchSection', () => { test('on but server not yet settled: shows the applying state', async () => { const { binding } = makeBinding(); mockProjectLocalBinding = binding; - mockProjectLocalConfig = configWithSemanticEnabled(true); + mockProjectLocalConfig = configWithSemantic({ enabled: true }); mockStatus = { enabled: false, keyPresent: false, From d77b066d471f10769998c69afef914ea44efd25a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 27 Jun 2026 08:50:08 +0000 Subject: [PATCH 3/5] feat: expose embeddings endpoint in settings --- .../settings/SearchSection.dom.test.tsx | 14 +++----- .../src/components/settings/SearchSection.tsx | 33 ++++++++----------- packages/app/src/locales/en/messages.json | 12 +++++-- packages/app/src/locales/en/messages.po | 24 +++++++++++--- packages/app/src/locales/pseudo/messages.json | 12 +++++-- packages/app/src/locales/pseudo/messages.po | 24 +++++++++++--- 6 files changed, 77 insertions(+), 42 deletions(-) diff --git a/packages/app/src/components/settings/SearchSection.dom.test.tsx b/packages/app/src/components/settings/SearchSection.dom.test.tsx index 71b9b1f0..d2dc2103 100644 --- a/packages/app/src/components/settings/SearchSection.dom.test.tsx +++ b/packages/app/src/components/settings/SearchSection.dom.test.tsx @@ -1,8 +1,8 @@ import { afterEach, beforeEach, describe, expect, mock, test } from 'bun:test'; import { - DEFAULT_EMBEDDINGS_BASE_URL, type Config, type ConfigBinding, + DEFAULT_EMBEDDINGS_BASE_URL, type SemanticIndexStatus, } from '@inkeep/open-knowledge-core'; import { cleanup, render, screen, waitFor } from '@testing-library/react'; @@ -49,14 +49,10 @@ mock.module('@/lib/config-provider', () => ({ const { SearchSection } = await import('./SearchSection'); -function configWithSemantic({ - enabled, - baseUrl, -}: { - enabled: boolean; - baseUrl?: string; -}): Config { - return { search: { semantic: { enabled, ...(baseUrl ? { baseUrl } : {}) } } } as unknown as Config; +function configWithSemantic({ enabled, baseUrl }: { enabled: boolean; baseUrl?: string }): Config { + return { + search: { semantic: { enabled, ...(baseUrl ? { baseUrl } : {}) } }, + } as unknown as Config; } function makeBinding(): { binding: ConfigBinding; calls: unknown[] } { diff --git a/packages/app/src/components/settings/SearchSection.tsx b/packages/app/src/components/settings/SearchSection.tsx index 217fc14c..013c9b71 100644 --- a/packages/app/src/components/settings/SearchSection.tsx +++ b/packages/app/src/components/settings/SearchSection.tsx @@ -25,7 +25,6 @@ export function SearchSection() { const { projectLocalConfig, projectLocalSynced, projectLocalBinding } = useConfigContext(); const { status, refresh } = useSemanticSearchStatus(); const [confirmOpen, setConfirmOpen] = useState(false); - const [baseUrlInput, setBaseUrlInput] = useState(DEFAULT_EMBEDDINGS_BASE_URL); const settleTimersRef = useRef>>([]); useEffect( @@ -38,10 +37,6 @@ export function SearchSection() { const configuredBaseUrl = projectLocalConfig?.search?.semantic?.baseUrl ?? DEFAULT_EMBEDDINGS_BASE_URL; - useEffect(() => { - setBaseUrlInput(configuredBaseUrl); - }, [configuredBaseUrl]); - const enabled = projectLocalConfig?.search?.semantic?.enabled ?? false; const bindingReady = projectLocalSynced && projectLocalBinding !== null; @@ -70,23 +65,23 @@ export function SearchSection() { return true; } + function normalizeBaseUrl(next: string): string { + return next.trim() || DEFAULT_EMBEDDINGS_BASE_URL; + } + function writeBaseUrl(next: string): boolean { if (projectLocalBinding === null) { toast.error(t`Search settings not yet loaded — try again in a moment`); return false; } - const normalized = next.trim() || DEFAULT_EMBEDDINGS_BASE_URL; - if (normalized === configuredBaseUrl) { - setBaseUrlInput(normalized); - return true; - } + const normalized = normalizeBaseUrl(next); + if (normalized === configuredBaseUrl) return true; const result = projectLocalBinding.patch({ search: { semantic: { baseUrl: normalized } } }); if (!result.ok) { const detail = humanFormat(result.error); toast.error(t`Failed to update the embeddings endpoint — ${detail}`); return false; } - setBaseUrlInput(normalized); refresh(); scheduleSettleRefresh(); return true; @@ -104,10 +99,6 @@ export function SearchSection() { if (write(true)) setConfirmOpen(false); } - function onBaseUrlBlur() { - writeBaseUrl(baseUrlInput); - } - const serverEnabled = status?.enabled ?? false; const keyPresent = status?.keyPresent ?? false; const ready = status?.ready ?? false; @@ -186,14 +177,18 @@ export function SearchSection() {

setBaseUrlInput(e.target.value)} - onBlur={onBaseUrlBlur} + defaultValue={configuredBaseUrl} + onBlur={(e) => { + const normalized = normalizeBaseUrl(e.currentTarget.value); + if (writeBaseUrl(e.currentTarget.value)) e.currentTarget.value = normalized; + }} onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); - writeBaseUrl(baseUrlInput); + const normalized = normalizeBaseUrl(e.currentTarget.value); + if (writeBaseUrl(e.currentTarget.value)) e.currentTarget.value = normalized; } }} placeholder={DEFAULT_EMBEDDINGS_BASE_URL} diff --git a/packages/app/src/locales/en/messages.json b/packages/app/src/locales/en/messages.json index 07c7e58f..65c6a9ba 100644 --- a/packages/app/src/locales/en/messages.json +++ b/packages/app/src/locales/en/messages.json @@ -594,9 +594,6 @@ "FEr96N": ["Theme"], "FNTx6u": ["Search \"", ["semanticSubmitQuery"], "\" by meaning"], "FOGD7m": ["Create something great."], - "FOyCTr": [ - "Your OpenAI API key, used only to create embeddings of your content for semantic search. Stored once for this machine in <0>~/.ok/secrets.yml (readable only by your user account) and shared across all projects. Turn the feature on per project in This project → Search." - ], "FRYB1Q": ["/api/config returned a malformed body"], "FRqZ9v": ["Couldn't update skill: ", ["0"]], "FTUGgh": ["Enter a repository URL or owner/repo"], @@ -770,6 +767,7 @@ "KujtjC": ["Find"], "L-rMC9": ["Reset to default"], "L1ZE3M": ["Document statistics"], + "L1rRuU": ["Embeddings API endpoint"], "L3CEC1": ["this item"], "L4Cdd9": ["or create a new file <0/>"], "L6Hhh6": ["(root)"], @@ -1403,6 +1401,7 @@ "eG8Jsg": ["Toggle source tab focus mode"], "eJitUk": ["Upload from computer"], "eKThTQ": ["Failed to reorder"], + "eLl1VX": ["Failed to update the embeddings endpoint — ", ["detail"]], "eNQGRb": ["Inline LaTeX math rendered with KaTeX."], "ePK91l": ["Edit"], "eQkgKV": ["Installed"], @@ -1618,6 +1617,7 @@ "l8G3S9": ["Auto-sync is off — you don't have permission to push to this repo"], "lAiyU_": ["Only the current document uses <0>#", ["tag"], "."], "lGs_bQ": ["Page <0>*"], + "lHCR4I": ["Clear the field to reset back to the default OpenAI endpoint."], "lHwYMr": ["Server error: ", ["status"], " ", ["statusText"]], "lI0Td2": ["Use letters, digits, <0>_ and <1>- only."], "lIn9L9": ["Disable sync"], @@ -1785,6 +1785,9 @@ "pha01Y": ["Project-level pages with no incoming graph edges."], "pkAft1": ["Search failed."], "pmKdif": ["Failed: ", ["loadError"]], + "pmOGtg": [ + "Use the default OpenAI endpoint or override it with an OpenAI-compatible base URL for Azure or a self-hosted provider." + ], "pmUArF": ["Workspace"], "ppDgFi": ["Restart with this app's version"], "pzutoc": ["Italic"], @@ -2002,6 +2005,9 @@ "wXO4Tg": [["hrs"], "h ago"], "wbv9xO": ["Create new project"], "wbwHYD": ["Enable sync"], + "wccmX0": [ + "Your embeddings provider API key, used only to create embeddings of your content for semantic search. Stored once for this machine in <0>~/.ok/secrets.yml (readable only by your user account) and shared across all projects. Turn the feature on per project in This project → Search, where you can also override the endpoint." + ], "weP6me": ["Couldn't load docs — type @ again to retry"], "wlwXUk": [ "You picked ~/Downloads. Files there are usually transient — consider a stable folder instead." diff --git a/packages/app/src/locales/en/messages.po b/packages/app/src/locales/en/messages.po index f0a213a0..9025b572 100644 --- a/packages/app/src/locales/en/messages.po +++ b/packages/app/src/locales/en/messages.po @@ -1067,6 +1067,10 @@ msgstr "Clear" msgid "Clear {keyName}" msgstr "Clear {keyName}" +#: src/components/settings/SearchSection.tsx +msgid "Clear the field to reset back to the default OpenAI endpoint." +msgstr "Clear the field to reset back to the default OpenAI endpoint." + #: src/components/FolderTimelineCard.tsx msgid "cleared folder properties" msgstr "cleared folder properties" @@ -2325,6 +2329,10 @@ msgstr "Embed an external page in an inline iframe (docs, demos, Figma, CodeSand msgid "Embed an image with optional alt text." msgstr "Embed an image with optional alt text." +#: src/components/settings/SearchSection.tsx +msgid "Embeddings API endpoint" +msgstr "Embeddings API endpoint" + #: src/components/settings/SearchSection.tsx msgid "Embeddings are computed only when a search runs and are cached locally under <0>.ok/local." msgstr "Embeddings are computed only when a search runs and are cached locally under <0>.ok/local." @@ -2657,6 +2665,10 @@ msgstr "Failed to reorder" msgid "Failed to update property" msgstr "Failed to update property" +#: src/components/settings/SearchSection.tsx +msgid "Failed to update the embeddings endpoint — {detail}" +msgstr "Failed to update the embeddings endpoint — {detail}" + #: src/components/settings/SettingsDialogBody.tsx msgid "Failed to update the project sync default — {detail}" msgstr "Failed to update the project sync default — {detail}" @@ -6686,6 +6698,10 @@ msgstr "Use lowercase letters, digits, and <0>- only." msgid "Use lowercase letters, digits, and hyphens only." msgstr "Use lowercase letters, digits, and hyphens only." +#: src/components/settings/SearchSection.tsx +msgid "Use the default OpenAI endpoint or override it with an OpenAI-compatible base URL for Azure or a self-hosted provider." +msgstr "Use the default OpenAI endpoint or override it with an OpenAI-compatible base URL for Azure or a self-hosted provider." + #: src/components/settings/SettingsDialogShell.tsx msgid "User" msgstr "User" @@ -6914,6 +6930,10 @@ msgstr "You picked the filesystem root (/). Scaffolding here will scan every fil msgid "You picked your home directory. OpenKnowledge will index everything in your home tree — large and may surface personal files." msgstr "You picked your home directory. OpenKnowledge will index everything in your home tree — large and may surface personal files." +#: src/components/settings/EmbeddingsKeySection.tsx +msgid "Your embeddings provider API key, used only to create embeddings of your content for semantic search. Stored once for this machine in <0>~/.ok/secrets.yml (readable only by your user account) and shared across all projects. Turn the feature on per project in This project → Search, where you can also override the endpoint." +msgstr "Your embeddings provider API key, used only to create embeddings of your content for semantic search. Stored once for this machine in <0>~/.ok/secrets.yml (readable only by your user account) and shared across all projects. Turn the feature on per project in This project → Search, where you can also override the endpoint." + #: src/components/settings/SettingsDialogBody.tsx #: src/components/SyncStatusBadge.tsx msgid "Your GitHub session expired — sign in again to verify push access." @@ -6927,10 +6947,6 @@ msgstr "Your GitHub token is missing required scopes. Try signing in again." msgid "Your knowledge base is now on GitHub at <0>{ownerLogin}/{repoName}." msgstr "Your knowledge base is now on GitHub at <0>{ownerLogin}/{repoName}." -#: src/components/settings/EmbeddingsKeySection.tsx -msgid "Your OpenAI API key, used only to create embeddings of your content for semantic search. Stored once for this machine in <0>~/.ok/secrets.yml (readable only by your user account) and shared across all projects. Turn the feature on per project in This project → Search." -msgstr "Your OpenAI API key, used only to create embeddings of your content for semantic search. Stored once for this machine in <0>~/.ok/secrets.yml (readable only by your user account) and shared across all projects. Turn the feature on per project in This project → Search." - #: src/components/CloneDialog.tsx msgid "Your repositories" msgstr "Your repositories" diff --git a/packages/app/src/locales/pseudo/messages.json b/packages/app/src/locales/pseudo/messages.json index f3e59392..717e55fc 100644 --- a/packages/app/src/locales/pseudo/messages.json +++ b/packages/app/src/locales/pseudo/messages.json @@ -594,9 +594,6 @@ "FEr96N": ["Ţĥēḿē"], "FNTx6u": ["Śēàŕćĥ \"", ["semanticSubmitQuery"], "\" ƀŷ ḿēàńĩńĝ"], "FOGD7m": ["Ćŕēàţē śōḿēţĥĩńĝ ĝŕēàţ."], - "FOyCTr": [ - "Ŷōũŕ ŌƥēńÀĨ ÀƤĨ ķēŷ, ũśēď ōńĺŷ ţō ćŕēàţē ēḿƀēďďĩńĝś ōƒ ŷōũŕ ćōńţēńţ ƒōŕ śēḿàńţĩć śēàŕćĥ. Śţōŕēď ōńćē ƒōŕ ţĥĩś ḿàćĥĩńē ĩń <0>~/.ōķ/śēćŕēţś.ŷḿĺ (ŕēàďàƀĺē ōńĺŷ ƀŷ ŷōũŕ ũśēŕ àććōũńţ) àńď śĥàŕēď àćŕōśś àĺĺ ƥŕōĴēćţś. Ţũŕń ţĥē ƒēàţũŕē ōń ƥēŕ ƥŕōĴēćţ ĩń Ţĥĩś ƥŕōĴēćţ → Śēàŕćĥ." - ], "FRYB1Q": ["/àƥĩ/ćōńƒĩĝ ŕēţũŕńēď à ḿàĺƒōŕḿēď ƀōďŷ"], "FRqZ9v": ["Ćōũĺďń'ţ ũƥďàţē śķĩĺĺ: ", ["0"]], "FTUGgh": ["Ēńţēŕ à ŕēƥōśĩţōŕŷ ŨŔĹ ōŕ ōŵńēŕ/ŕēƥō"], @@ -770,6 +767,7 @@ "KujtjC": ["Ƒĩńď"], "L-rMC9": ["Ŕēśēţ ţō ďēƒàũĺţ"], "L1ZE3M": ["Ďōćũḿēńţ śţàţĩśţĩćś"], + "L1rRuU": ["Ēḿƀēďďĩńĝś ÀƤĨ ēńďƥōĩńţ"], "L3CEC1": ["ţĥĩś ĩţēḿ"], "L4Cdd9": ["ōŕ ćŕēàţē à ńēŵ ƒĩĺē <0/>"], "L6Hhh6": ["(ŕōōţ)"], @@ -1403,6 +1401,7 @@ "eG8Jsg": ["Ţōĝĝĺē śōũŕćē ţàƀ ƒōćũś ḿōďē"], "eJitUk": ["Ũƥĺōàď ƒŕōḿ ćōḿƥũţēŕ"], "eKThTQ": ["Ƒàĩĺēď ţō ŕēōŕďēŕ"], + "eLl1VX": ["Ƒàĩĺēď ţō ũƥďàţē ţĥē ēḿƀēďďĩńĝś ēńďƥōĩńţ — ", ["detail"]], "eNQGRb": ["Ĩńĺĩńē ĹàŢēX ḿàţĥ ŕēńďēŕēď ŵĩţĥ ĶàŢēX."], "ePK91l": ["Ēďĩţ"], "eQkgKV": ["Ĩńśţàĺĺēď"], @@ -1618,6 +1617,7 @@ "l8G3S9": ["Àũţō-śŷńć ĩś ōƒƒ — ŷōũ ďōń'ţ ĥàvē ƥēŕḿĩśśĩōń ţō ƥũśĥ ţō ţĥĩś ŕēƥō"], "lAiyU_": ["Ōńĺŷ ţĥē ćũŕŕēńţ ďōćũḿēńţ ũśēś <0>#", ["tag"], "."], "lGs_bQ": ["Ƥàĝē <0>*"], + "lHCR4I": ["Ćĺēàŕ ţĥē ƒĩēĺď ţō ŕēśēţ ƀàćķ ţō ţĥē ďēƒàũĺţ ŌƥēńÀĨ ēńďƥōĩńţ."], "lHwYMr": ["Śēŕvēŕ ēŕŕōŕ: ", ["status"], " ", ["statusText"]], "lI0Td2": ["Ũśē ĺēţţēŕś, ďĩĝĩţś, <0>_ àńď <1>- ōńĺŷ."], "lIn9L9": ["Ďĩśàƀĺē śŷńć"], @@ -1785,6 +1785,9 @@ "pha01Y": ["ƤŕōĴēćţ-ĺēvēĺ ƥàĝēś ŵĩţĥ ńō ĩńćōḿĩńĝ ĝŕàƥĥ ēďĝēś."], "pkAft1": ["Śēàŕćĥ ƒàĩĺēď."], "pmKdif": ["Ƒàĩĺēď: ", ["loadError"]], + "pmOGtg": [ + "Ũśē ţĥē ďēƒàũĺţ ŌƥēńÀĨ ēńďƥōĩńţ ōŕ ōvēŕŕĩďē ĩţ ŵĩţĥ àń ŌƥēńÀĨ-ćōḿƥàţĩƀĺē ƀàśē ŨŔĹ ƒōŕ Àźũŕē ōŕ à śēĺƒ-ĥōśţēď ƥŕōvĩďēŕ." + ], "pmUArF": ["Ŵōŕķśƥàćē"], "ppDgFi": ["Ŕēśţàŕţ ŵĩţĥ ţĥĩś àƥƥ'ś vēŕśĩōń"], "pzutoc": ["Ĩţàĺĩć"], @@ -2002,6 +2005,9 @@ "wXO4Tg": [["hrs"], "ĥ àĝō"], "wbv9xO": ["Ćŕēàţē ńēŵ ƥŕōĴēćţ"], "wbwHYD": ["Ēńàƀĺē śŷńć"], + "wccmX0": [ + "Ŷōũŕ ēḿƀēďďĩńĝś ƥŕōvĩďēŕ ÀƤĨ ķēŷ, ũśēď ōńĺŷ ţō ćŕēàţē ēḿƀēďďĩńĝś ōƒ ŷōũŕ ćōńţēńţ ƒōŕ śēḿàńţĩć śēàŕćĥ. Śţōŕēď ōńćē ƒōŕ ţĥĩś ḿàćĥĩńē ĩń <0>~/.ōķ/śēćŕēţś.ŷḿĺ (ŕēàďàƀĺē ōńĺŷ ƀŷ ŷōũŕ ũśēŕ àććōũńţ) àńď śĥàŕēď àćŕōśś àĺĺ ƥŕōĴēćţś. Ţũŕń ţĥē ƒēàţũŕē ōń ƥēŕ ƥŕōĴēćţ ĩń Ţĥĩś ƥŕōĴēćţ → Śēàŕćĥ, ŵĥēŕē ŷōũ ćàń àĺśō ōvēŕŕĩďē ţĥē ēńďƥōĩńţ." + ], "weP6me": ["Ćōũĺďń'ţ ĺōàď ďōćś — ţŷƥē @ àĝàĩń ţō ŕēţŕŷ"], "wlwXUk": [ "Ŷōũ ƥĩćķēď ~/Ďōŵńĺōàďś. Ƒĩĺēś ţĥēŕē àŕē ũśũàĺĺŷ ţŕàńśĩēńţ — ćōńśĩďēŕ à śţàƀĺē ƒōĺďēŕ ĩńśţēàď." diff --git a/packages/app/src/locales/pseudo/messages.po b/packages/app/src/locales/pseudo/messages.po index 2a401405..84d83e31 100644 --- a/packages/app/src/locales/pseudo/messages.po +++ b/packages/app/src/locales/pseudo/messages.po @@ -1062,6 +1062,10 @@ msgstr "" msgid "Clear {keyName}" msgstr "" +#: src/components/settings/SearchSection.tsx +msgid "Clear the field to reset back to the default OpenAI endpoint." +msgstr "" + #: src/components/FolderTimelineCard.tsx msgid "cleared folder properties" msgstr "" @@ -2320,6 +2324,10 @@ msgstr "" msgid "Embed an image with optional alt text." msgstr "" +#: src/components/settings/SearchSection.tsx +msgid "Embeddings API endpoint" +msgstr "" + #: src/components/settings/SearchSection.tsx msgid "Embeddings are computed only when a search runs and are cached locally under <0>.ok/local." msgstr "" @@ -2652,6 +2660,10 @@ msgstr "" msgid "Failed to update property" msgstr "" +#: src/components/settings/SearchSection.tsx +msgid "Failed to update the embeddings endpoint — {detail}" +msgstr "" + #: src/components/settings/SettingsDialogBody.tsx msgid "Failed to update the project sync default — {detail}" msgstr "" @@ -6681,6 +6693,10 @@ msgstr "" msgid "Use lowercase letters, digits, and hyphens only." msgstr "" +#: src/components/settings/SearchSection.tsx +msgid "Use the default OpenAI endpoint or override it with an OpenAI-compatible base URL for Azure or a self-hosted provider." +msgstr "" + #: src/components/settings/SettingsDialogShell.tsx msgid "User" msgstr "" @@ -6909,6 +6925,10 @@ msgstr "" msgid "You picked your home directory. OpenKnowledge will index everything in your home tree — large and may surface personal files." msgstr "" +#: src/components/settings/EmbeddingsKeySection.tsx +msgid "Your embeddings provider API key, used only to create embeddings of your content for semantic search. Stored once for this machine in <0>~/.ok/secrets.yml (readable only by your user account) and shared across all projects. Turn the feature on per project in This project → Search, where you can also override the endpoint." +msgstr "" + #: src/components/settings/SettingsDialogBody.tsx #: src/components/SyncStatusBadge.tsx msgid "Your GitHub session expired — sign in again to verify push access." @@ -6922,10 +6942,6 @@ msgstr "" msgid "Your knowledge base is now on GitHub at <0>{ownerLogin}/{repoName}." msgstr "" -#: src/components/settings/EmbeddingsKeySection.tsx -msgid "Your OpenAI API key, used only to create embeddings of your content for semantic search. Stored once for this machine in <0>~/.ok/secrets.yml (readable only by your user account) and shared across all projects. Turn the feature on per project in This project → Search." -msgstr "" - #: src/components/CloneDialog.tsx msgid "Your repositories" msgstr "" From dddefeaab700bf8e5fc4b930cc3a8b9fee9d29f2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 27 Jun 2026 08:50:58 +0000 Subject: [PATCH 4/5] chore: restore bun lockfile --- bun.lock | 74 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 41 insertions(+), 33 deletions(-) diff --git a/bun.lock b/bun.lock index 46e5b191..64012d74 100644 --- a/bun.lock +++ b/bun.lock @@ -1774,7 +1774,7 @@ "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], - "@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="], + "@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="], "@types/node-fetch": ["@types/node-fetch@2.6.13", "", { "dependencies": { "@types/node": "*", "form-data": "^4.0.4" } }, "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw=="], @@ -4020,7 +4020,7 @@ "undici": ["undici@7.25.0", "", {}, "sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ=="], - "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + "undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="], "unicorn-magic": ["unicorn-magic@0.3.0", "", {}, "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA=="], @@ -4272,7 +4272,11 @@ "@inkeep/cxkit-styled/tailwind-merge": ["tailwind-merge@2.6.0", "", {}, "sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA=="], - "@inkeep/open-knowledge-core/@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="], + "@inkeep/open-knowledge/@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="], + + "@inkeep/open-knowledge-desktop/@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="], + + "@inkeep/open-knowledge-docs/@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="], "@inkeep/open-knowledge-docs/lucide-react": ["lucide-react@0.503.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-HGGkdlPWQ0vTF8jJ5TdIqhQXZi6uh3LnNgfZ8MHiuxFfX3RZeA79r2MW2tHAZKlAVfoNE8esm3p+O6VkIvpj6w=="], @@ -4298,8 +4302,6 @@ "@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], - "@jest/types/@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="], - "@lingui/cli/jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="], "@lingui/conf/jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="], @@ -4412,13 +4414,23 @@ "@tiptap/starter-kit/@tiptap/pm": ["@tiptap/pm@3.22.3", "", { "dependencies": { "prosemirror-changeset": "^2.3.0", "prosemirror-collab": "^1.3.1", "prosemirror-commands": "^1.6.2", "prosemirror-dropcursor": "^1.8.1", "prosemirror-gapcursor": "^1.3.2", "prosemirror-history": "^1.4.1", "prosemirror-inputrules": "^1.4.0", "prosemirror-keymap": "^1.2.2", "prosemirror-markdown": "^1.13.1", "prosemirror-menu": "^1.2.4", "prosemirror-model": "^1.24.1", "prosemirror-schema-basic": "^1.2.3", "prosemirror-schema-list": "^1.5.0", "prosemirror-state": "^1.4.3", "prosemirror-tables": "^1.6.4", "prosemirror-trailing-node": "^3.0.0", "prosemirror-transform": "^1.10.2", "prosemirror-view": "^1.38.1" } }, "sha512-NjfWjZuvrqmpICT+GZWNIjtOdhPyqFKDMtQy7tsQ5rErM9L2ZQdy/+T/BKSO1JdTeBhdg9OP+0yfsqoYp2aT6A=="], - "@types/jsdom/@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="], + "@types/busboy/@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="], + + "@types/cacheable-request/@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="], + + "@types/fs-extra/@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="], "@types/jsdom/undici-types": ["undici-types@7.25.0", "", {}, "sha512-AXNgS1Byr27fTI+2bsPEkV9CxkT8H6xNyRI68b3TatlZo3RkzlqQBLL+w7SmGPVpokjHbcuNVQUWE7FRTg+LRA=="], - "@types/node-fetch/@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="], + "@types/keyv/@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="], + + "@types/plist/@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="], + + "@types/responselike/@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="], - "@types/yazl/@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="], + "@types/ws/@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="], + + "@types/yauzl/@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="], "ajv-keywords/ajv": ["ajv@6.14.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw=="], @@ -4440,12 +4452,8 @@ "ast-kit/@babel/parser": ["@babel/parser@8.0.0-rc.3", "", { "dependencies": { "@babel/types": "^8.0.0-rc.3" }, "bin": "./bin/babel-parser.js" }, "sha512-B20dvP3MfNc/XS5KKCHy/oyWl5IA6Cn9YjXRdDlCjNmUFrjvLXMNUfQq/QUy9fnG2gYkKKcrto2YaF9B32ToOQ=="], - "buffer-image-size/@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="], - "builder-util/fs-extra": ["fs-extra@10.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ=="], - "bun-types/@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="], - "cacache/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], "cacache/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], @@ -4484,6 +4492,8 @@ "dotenv-expand/dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="], + "electron/@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="], + "electron-builder/fs-extra": ["fs-extra@10.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ=="], "electron-publish/fs-extra": ["fs-extra@10.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ=="], @@ -4526,8 +4536,6 @@ "glob/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], - "happy-dom/@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="], - "happy-dom/whatwg-mimetype": ["whatwg-mimetype@3.0.0", "", {}, "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q=="], "hast-util-from-html/parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], @@ -4618,8 +4626,6 @@ "prosemirror-trailing-node/escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], - "protobufjs/@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="], - "proxy-addr/ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="], "proxy-agent/lru-cache": ["lru-cache@7.18.3", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="], @@ -4838,9 +4844,11 @@ "@inkeep/cxkit-primitives/@radix-ui/react-tooltip/@radix-ui/react-visually-hidden": ["@radix-ui/react-visually-hidden@1.1.1", "", { "dependencies": { "@radix-ui/react-primitive": "2.0.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-vVfA2IZ9q/J+gEamvj761Oq1FpWgCDaNOOIfbPVp2MVPLEomUr5+Vf7kJGwQ24YxZSlQVar7Bes8kyTo5Dshpg=="], - "@inkeep/open-knowledge-core/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="], + "@inkeep/open-knowledge-desktop/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], - "@inkeep/open-knowledge-server/@types/yazl/@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="], + "@inkeep/open-knowledge-docs/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + + "@inkeep/open-knowledge/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], "@inquirer/confirm/@inquirer/core/@inquirer/ansi": ["@inquirer/ansi@1.0.2", "", {}, "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ=="], @@ -4858,8 +4866,6 @@ "@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], - "@jest/types/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="], - "@malept/flatpak-bundler/fs-extra/jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="], "@malept/flatpak-bundler/fs-extra/universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="], @@ -4902,11 +4908,21 @@ "@radix-ui/react-popover/@radix-ui/react-use-controllable-state/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jrBWOxZITuGcnjRCM2t2U5ZPkCLxD+Ym6DjfssS5haTj2iiak/DOb64JeN6OdLfLgptb6/e2kKR+ZuTrGoZTPA=="], - "@types/jsdom/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="], + "@types/busboy/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + + "@types/cacheable-request/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + + "@types/fs-extra/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + + "@types/keyv/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + + "@types/plist/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + + "@types/responselike/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], - "@types/node-fetch/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="], + "@types/ws/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], - "@types/yazl/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="], + "@types/yauzl/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], "ajv-keywords/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], @@ -4926,14 +4942,10 @@ "ast-kit/@babel/parser/@babel/types": ["@babel/types@8.0.0-rc.3", "", { "dependencies": { "@babel/helper-string-parser": "^8.0.0-rc.3", "@babel/helper-validator-identifier": "^8.0.0-rc.3" } }, "sha512-mOm5ZrYmphGfqVWoH5YYMTITb3cDXsFgmvFlvkvWDMsR9X8RFnt7a0Wb6yNIdoFsiMO9WjYLq+U/FMtqIYAF8Q=="], - "buffer-image-size/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="], - "builder-util/fs-extra/jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="], "builder-util/fs-extra/universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="], - "bun-types/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="], - "cacache/glob/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="], "cli-truncate/string-width/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], @@ -4962,6 +4974,8 @@ "electron-updater/fs-extra/universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="], + "electron/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + "filelist/minimatch/brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="], "form-data/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], @@ -5024,8 +5038,6 @@ "glob/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="], - "happy-dom/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="], - "hast-util-from-html/parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], "hast-util-raw/parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], @@ -5062,8 +5074,6 @@ "prebuild-install/tar-fs/tar-stream": ["tar-stream@2.2.0", "", { "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.1.1" } }, "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ=="], - "protobufjs/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="], - "puppeteer-core/chromium-bidi/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], "puppeteer/puppeteer-core/webdriver-bidi-protocol": ["webdriver-bidi-protocol@0.4.1", "", {}, "sha512-ARrjNjtWRRs2w4Tk7nqrf2gBI0QXWuOmMCx2hU+1jUt6d00MjMxURrhxhGbrsoiZKJrhTSTzbIrc554iKI10qw=="], @@ -5254,8 +5264,6 @@ "@inkeep/cxkit-primitives/@radix-ui/react-tooltip/@radix-ui/react-use-controllable-state/@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw=="], - "@inkeep/open-knowledge-server/@types/yazl/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="], - "@opentelemetry/instrumentation-fetch/@opentelemetry/sdk-trace-web/@opentelemetry/sdk-trace-base/@opentelemetry/resources": ["@opentelemetry/resources@2.1.0", "", { "dependencies": { "@opentelemetry/core": "2.1.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-1CJjf3LCvoefUOgegxi8h6r4B/wLSzInyhGP2UmIBYNlo4Qk5CZ73e1eEyWmfXvFtm1ybkmfb2DqWvspsYLrWw=="], "app-builder-lib/@electron/fuses/fs-extra/jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="], From 613bea1235d5c6932db5c3d421c61ba33ca8f36b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 27 Jun 2026 08:53:03 +0000 Subject: [PATCH 5/5] refactor: dedupe endpoint input normalization --- .../app/src/components/settings/SearchSection.tsx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/app/src/components/settings/SearchSection.tsx b/packages/app/src/components/settings/SearchSection.tsx index 013c9b71..95183e71 100644 --- a/packages/app/src/components/settings/SearchSection.tsx +++ b/packages/app/src/components/settings/SearchSection.tsx @@ -99,6 +99,11 @@ export function SearchSection() { if (write(true)) setConfirmOpen(false); } + function commitBaseUrlInput(input: HTMLInputElement): void { + const normalized = normalizeBaseUrl(input.value); + if (writeBaseUrl(input.value)) input.value = normalized; + } + const serverEnabled = status?.enabled ?? false; const keyPresent = status?.keyPresent ?? false; const ready = status?.ready ?? false; @@ -180,15 +185,11 @@ export function SearchSection() { key={configuredBaseUrl} id="settings-search-base-url" defaultValue={configuredBaseUrl} - onBlur={(e) => { - const normalized = normalizeBaseUrl(e.currentTarget.value); - if (writeBaseUrl(e.currentTarget.value)) e.currentTarget.value = normalized; - }} + onBlur={(e) => commitBaseUrlInput(e.currentTarget)} onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); - const normalized = normalizeBaseUrl(e.currentTarget.value); - if (writeBaseUrl(e.currentTarget.value)) e.currentTarget.value = normalized; + commitBaseUrlInput(e.currentTarget); } }} placeholder={DEFAULT_EMBEDDINGS_BASE_URL}