From bc6f4aed2bfb662d24a28b1cfe927a3e8af637bf Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Tue, 4 Nov 2025 12:33:03 -0500 Subject: [PATCH 01/10] local web --- packages/desktop/src/index.tsx | 4 +++- packages/opencode/src/cli/cmd/tui/app.tsx | 1 + .../src/cli/cmd/tui/component/dialog-session-list.tsx | 2 +- packages/opencode/src/cli/cmd/web.ts | 9 ++++++--- packages/opencode/src/server/server.ts | 11 ++++++++++- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/packages/desktop/src/index.tsx b/packages/desktop/src/index.tsx index 0d631a5a..9fe5da2f 100644 --- a/packages/desktop/src/index.tsx +++ b/packages/desktop/src/index.tsx @@ -12,7 +12,9 @@ import Home from "@/pages" const host = import.meta.env.VITE_OPENCODE_SERVER_HOST ?? "127.0.0.1" const port = import.meta.env.VITE_OPENCODE_SERVER_PORT ?? "4096" -const url = new URLSearchParams(document.location.search).get("url") || `http://${host}:${port}` +const url = + new URLSearchParams(document.location.search).get("url") || + (location.hostname.includes("opencode.ai") ? `http://${host}:${port}` : "/") const root = document.getElementById("root") if (import.meta.env.DEV && !(root instanceof HTMLElement)) { diff --git a/packages/opencode/src/cli/cmd/tui/app.tsx b/packages/opencode/src/cli/cmd/tui/app.tsx index 7938ec86..e57ef8cd 100644 --- a/packages/opencode/src/cli/cmd/tui/app.tsx +++ b/packages/opencode/src/cli/cmd/tui/app.tsx @@ -358,6 +358,7 @@ function App() { event.on(SessionApi.Event.Deleted.type, (evt) => { if (route.data.type === "session" && route.data.sessionID === evt.properties.info.id) { + dialog.clear() route.navigate({ type: "home" }) toast.show({ variant: "info", diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx index 31b1c2b5..4a720aa1 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx @@ -72,7 +72,7 @@ export function DialogSessionList() { }, }) setToDelete(undefined) - dialog.clear() + // dialog.clear() return } setToDelete(option.value) diff --git a/packages/opencode/src/cli/cmd/web.ts b/packages/opencode/src/cli/cmd/web.ts index 4823414f..8fc8a991 100644 --- a/packages/opencode/src/cli/cmd/web.ts +++ b/packages/opencode/src/cli/cmd/web.ts @@ -26,12 +26,15 @@ export const WebCommand = cmd({ port, hostname, }) - const url = `https://desktop.dev.opencode.ai?url=${server.url}` UI.empty() UI.println(UI.logo(" ")) UI.empty() - UI.println(UI.Style.TEXT_INFO_BOLD + " Web interface: ", UI.Style.TEXT_NORMAL, url) - open(url).catch(() => {}) + UI.println( + UI.Style.TEXT_INFO_BOLD + " Web interface: ", + UI.Style.TEXT_NORMAL, + server.url.toString(), + ) + open(server.url.toString()).catch(() => {}) await new Promise(() => {}) await server.stop() }, diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts index 919d6828..68c61453 100644 --- a/packages/opencode/src/server/server.ts +++ b/packages/opencode/src/server/server.ts @@ -10,6 +10,7 @@ import { import { Hono } from "hono" import { cors } from "hono/cors" import { stream, streamSSE } from "hono/streaming" +import { proxy } from "hono/proxy" import { Session } from "../session" import z from "zod" import { Provider } from "../provider/provider" @@ -1696,7 +1697,15 @@ export namespace Server { }) }) }, - ), + ) + .all("/*", async (c) => { + return proxy(`https://desktop.dev.opencode.ai${c.req.path}`, { + ...c.req, + headers: { + host: "desktop.dev.opencode.ai", + }, + }) + }), ) export async function openapi() { From 1bf1b93404edc063fa286f822717f8aaa34b757a Mon Sep 17 00:00:00 2001 From: Sebastian Herrlinger Date: Tue, 4 Nov 2025 18:38:44 +0100 Subject: [PATCH 02/10] Revert "upgrade opentui to address disappearing content issues #3776, #3697" This reverts commit 90fc3ddb02714cf1767ac49a47594f4b16bc3e48. --- bun.lock | 20 ++++++++++---------- packages/opencode/package.json | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/bun.lock b/bun.lock index e49c70c6..9776208d 100644 --- a/bun.lock +++ b/bun.lock @@ -184,8 +184,8 @@ "@opencode-ai/plugin": "workspace:*", "@opencode-ai/script": "workspace:*", "@opencode-ai/sdk": "workspace:*", - "@opentui/core": "0.1.34", - "@opentui/solid": "0.1.34", + "@opentui/core": "0.1.33", + "@opentui/solid": "0.1.33", "@parcel/watcher": "2.5.1", "@pierre/precision-diffs": "catalog:", "@solid-primitives/event-bus": "1.1.2", @@ -961,21 +961,21 @@ "@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="], - "@opentui/core": ["@opentui/core@0.1.34", "", { "dependencies": { "bun-ffi-structs": "^0.1.0", "jimp": "1.6.0", "yoga-layout": "3.2.1" }, "optionalDependencies": { "@dimforge/rapier2d-simd-compat": "^0.17.3", "@opentui/core-darwin-arm64": "0.1.34", "@opentui/core-darwin-x64": "0.1.34", "@opentui/core-linux-arm64": "0.1.34", "@opentui/core-linux-x64": "0.1.34", "@opentui/core-win32-arm64": "0.1.34", "@opentui/core-win32-x64": "0.1.34", "bun-webgpu": "0.1.3", "planck": "^1.4.2", "three": "0.177.0" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-rsqEbHXIFL6JEZs/2dCHn7efnJaGByqpI3mMtt+cJvyt7ZiGU9y+JwryFb9rE8KZMtwsUWN1ECz58ufy6iJvzA=="], + "@opentui/core": ["@opentui/core@0.1.33", "", { "dependencies": { "bun-ffi-structs": "^0.1.0", "jimp": "1.6.0", "yoga-layout": "3.2.1" }, "optionalDependencies": { "@dimforge/rapier2d-simd-compat": "^0.17.3", "@opentui/core-darwin-arm64": "0.1.33", "@opentui/core-darwin-x64": "0.1.33", "@opentui/core-linux-arm64": "0.1.33", "@opentui/core-linux-x64": "0.1.33", "@opentui/core-win32-arm64": "0.1.33", "@opentui/core-win32-x64": "0.1.33", "bun-webgpu": "0.1.3", "planck": "^1.4.2", "three": "0.177.0" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-vwHdrPIqnsY6YnG2JTNhenHSsx+HUPYrQTBZdmEfCj9ROGVzKgUKbSDH1xGK2OtSNRb2KVBg4XaMpq0bie6afQ=="], - "@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.1.34", "", { "os": "darwin", "cpu": "arm64" }, "sha512-P/Pw66vJ1W5pIVg7D5bUlMPBTarXh0S/conHRaeybBZoO+8G04A6x9ufeaD/L4HCE0iR0huSoHGDB1VxZUL2Zg=="], + "@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.1.33", "", { "os": "darwin", "cpu": "arm64" }, "sha512-JBvzcP2V7fT9KxFAMenHRd/t72qPP5IL5kzge2uok1T7t2nw3Wa+CWI5s6FYP42p2b1W9qZkv5Fno5gA7OAYuQ=="], - "@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.1.34", "", { "os": "darwin", "cpu": "x64" }, "sha512-JKfDC2qI1AmY4u504FKfrSdP0qOJIn+rI7kj0C0ydpvj1Wd2c6ImOsbnny70372Uq/m3EXxPE3Hq/66DL4P94A=="], + "@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.1.33", "", { "os": "darwin", "cpu": "x64" }, "sha512-x7DY6VCkAky10z/2o4UkkuNW/nIvoX7uAh3dJOHWZCLbiKywSFvFk3QZVVcH5BMk4tOOophYTzika4s4HpaeMg=="], - "@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.1.34", "", { "os": "linux", "cpu": "arm64" }, "sha512-E1xAuz0xx7lmh7tZmexP/4Aceyzmpuo4c9UoNd844Aweu/AlmjsmaOMOBLA77I94RSbEuGKJt9WAPyiSZbgwVw=="], + "@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.1.33", "", { "os": "linux", "cpu": "arm64" }, "sha512-bBc1EdkVxsLBtqGjXM2BYpBJLa57ogcrSADSZbc5cQkPu0muSGzUwBbVnVZJUjWEfk6n5jcd4dDmLezVoQga0A=="], - "@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.1.34", "", { "os": "linux", "cpu": "x64" }, "sha512-VZxgdOUR8h2l3LUPex0A02pLsw9+P4RouL7sJ2Ul/sXvvi/b2ptzJvGQluynV6yHa2etYklZWDyWyMJmF8OKzw=="], + "@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.1.33", "", { "os": "linux", "cpu": "x64" }, "sha512-3oVL5mrLlKLUc1lc4v7xS3BJ9N7PnnimbGwAvlnVpfaAygotAs1XkPcjsUe6ItMnSJyi0FWiDHUE2+GiDtM5Nw=="], - "@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.1.34", "", { "os": "win32", "cpu": "arm64" }, "sha512-4HXGcYdAHodhm0VnL3nn9uYFvmUhKHiN2vSMDy5KO2NZ49O1IXcS001g/TKryv0hcK1kIUBkq+RH/0vrieCAJw=="], + "@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.1.33", "", { "os": "win32", "cpu": "arm64" }, "sha512-Q68v7wssE+r0OG1KIGfi7m3fnu8KOK4ZNg9ML6EwE47VF9/bqgUe+6fPiXh5mmHzTwof7nAOdXCf052av5/upQ=="], - "@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.1.34", "", { "os": "win32", "cpu": "x64" }, "sha512-ptuIL6QO7LVFGI6ouZ01fw+AQfjJC+DURjsqiQhoaS/iunFefZY0q83V7ZWgv0nYlhRm+E2yWjRNNzCySJlTaQ=="], + "@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.1.33", "", { "os": "win32", "cpu": "x64" }, "sha512-PvuchmUnbMCUXXMzfle/WTzhNGIdJ6RGCCoclx3YVUyNUVuUicPf42OEV+td2m81/Hr3CgcLn98HYX1TLIzPrw=="], - "@opentui/solid": ["@opentui/solid@0.1.34", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.1.34", "babel-plugin-module-resolver": "5.0.2", "babel-preset-solid": "1.9.9", "s-js": "^0.4.9" }, "peerDependencies": { "solid-js": "1.9.9" } }, "sha512-GPT+EeC6vcDnb4aUJ2K4t01GlbNoMZUfMTiIif55JSjXTKURzdDLL4mOhxar1+iJqwubYHEu/nC1GkTiGWIJoQ=="], + "@opentui/solid": ["@opentui/solid@0.1.33", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.1.33", "babel-plugin-module-resolver": "5.0.2", "babel-preset-solid": "1.9.9", "s-js": "^0.4.9" }, "peerDependencies": { "solid-js": "1.9.9" } }, "sha512-bWSALdGJ2j51zwZ2gK1ZIBxFgauHq+V1ejEnyd4XamYMdWfpAKU+AUWDVLbpx1T9XG1oAnycJZfYX7BsZdVOOg=="], "@oslojs/asn1": ["@oslojs/asn1@1.0.0", "", { "dependencies": { "@oslojs/binary": "1.0.0" } }, "sha512-zw/wn0sj0j0QKbIXfIlnEcTviaCzYOY3V5rAyjR6YtOByFtJiT574+8p9Wlach0lZH9fddD4yb9laEAIl4vXQA=="], diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 927ac9d2..b0c8be7d 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -54,8 +54,8 @@ "@opencode-ai/plugin": "workspace:*", "@opencode-ai/script": "workspace:*", "@opencode-ai/sdk": "workspace:*", - "@opentui/core": "0.1.34", - "@opentui/solid": "0.1.34", + "@opentui/core": "0.1.33", + "@opentui/solid": "0.1.33", "@parcel/watcher": "2.5.1", "@solid-primitives/event-bus": "1.1.2", "@pierre/precision-diffs": "catalog:", From f9af9fc22184c5e4a62a18a2df6746d6a1945264 Mon Sep 17 00:00:00 2001 From: opencode Date: Tue, 4 Nov 2025 17:47:34 +0000 Subject: [PATCH 03/10] release: v1.0.21 --- bun.lock | 22 +++++++++++----------- packages/console/app/package.json | 2 +- packages/console/core/package.json | 2 +- packages/console/function/package.json | 2 +- packages/console/mail/package.json | 2 +- packages/desktop/package.json | 2 +- packages/function/package.json | 2 +- packages/opencode/package.json | 2 +- packages/plugin/package.json | 2 +- packages/sdk/js/package.json | 2 +- packages/sdk/js/src/gen/types.gen.ts | 2 +- packages/slack/package.json | 2 +- packages/ui/package.json | 2 +- packages/web/package.json | 2 +- sdks/vscode/package.json | 2 +- 15 files changed, 25 insertions(+), 25 deletions(-) diff --git a/bun.lock b/bun.lock index 9776208d..34a21d6a 100644 --- a/bun.lock +++ b/bun.lock @@ -39,7 +39,7 @@ }, "packages/console/core": { "name": "@opencode-ai/console-core", - "version": "1.0.20", + "version": "1.0.21", "dependencies": { "@aws-sdk/client-sts": "3.782.0", "@jsx-email/render": "1.1.1", @@ -66,7 +66,7 @@ }, "packages/console/function": { "name": "@opencode-ai/console-function", - "version": "1.0.20", + "version": "1.0.21", "dependencies": { "@ai-sdk/anthropic": "2.0.0", "@ai-sdk/openai": "2.0.2", @@ -90,7 +90,7 @@ }, "packages/console/mail": { "name": "@opencode-ai/console-mail", - "version": "1.0.20", + "version": "1.0.21", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", @@ -111,7 +111,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "1.0.20", + "version": "1.0.21", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -150,7 +150,7 @@ }, "packages/function": { "name": "@opencode-ai/function", - "version": "1.0.20", + "version": "1.0.21", "dependencies": { "@octokit/auth-app": "8.0.1", "@octokit/rest": "22.0.0", @@ -166,7 +166,7 @@ }, "packages/opencode": { "name": "opencode", - "version": "1.0.20", + "version": "1.0.21", "bin": { "opencode": "./bin/opencode", }, @@ -243,7 +243,7 @@ }, "packages/plugin": { "name": "@opencode-ai/plugin", - "version": "1.0.20", + "version": "1.0.21", "dependencies": { "@opencode-ai/sdk": "workspace:*", "zod": "catalog:", @@ -263,7 +263,7 @@ }, "packages/sdk/js": { "name": "@opencode-ai/sdk", - "version": "1.0.20", + "version": "1.0.21", "devDependencies": { "@hey-api/openapi-ts": "0.81.0", "@tsconfig/node22": "catalog:", @@ -274,7 +274,7 @@ }, "packages/slack": { "name": "@opencode-ai/slack", - "version": "1.0.20", + "version": "1.0.21", "dependencies": { "@opencode-ai/sdk": "workspace:*", "@slack/bolt": "^3.17.1", @@ -287,7 +287,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "1.0.20", + "version": "1.0.21", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -317,7 +317,7 @@ }, "packages/web": { "name": "@opencode-ai/web", - "version": "1.0.20", + "version": "1.0.21", "dependencies": { "@astrojs/cloudflare": "12.6.3", "@astrojs/markdown-remark": "6.3.1", diff --git a/packages/console/app/package.json b/packages/console/app/package.json index ad25ada7..cb14e648 100644 --- a/packages/console/app/package.json +++ b/packages/console/app/package.json @@ -7,7 +7,7 @@ "dev:remote": "VITE_AUTH_URL=https://auth.dev.opencode.ai bun sst shell --stage=dev bun dev", "build": "vinxi build && ../../opencode/script/schema.ts ./.output/public/config.json", "start": "vinxi start", - "version": "1.0.20" + "version": "1.0.21" }, "dependencies": { "@ibm/plex": "6.4.1", diff --git a/packages/console/core/package.json b/packages/console/core/package.json index 5dd902e7..477a5549 100644 --- a/packages/console/core/package.json +++ b/packages/console/core/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/console-core", - "version": "1.0.20", + "version": "1.0.21", "private": true, "type": "module", "dependencies": { diff --git a/packages/console/function/package.json b/packages/console/function/package.json index 564d5b0c..9cae8d9f 100644 --- a/packages/console/function/package.json +++ b/packages/console/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-function", - "version": "1.0.20", + "version": "1.0.21", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/console/mail/package.json b/packages/console/mail/package.json index 7d1d54ab..2e1943c2 100644 --- a/packages/console/mail/package.json +++ b/packages/console/mail/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-mail", - "version": "1.0.20", + "version": "1.0.21", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", diff --git a/packages/desktop/package.json b/packages/desktop/package.json index 4364e34d..23f2a734 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/desktop", - "version": "1.0.20", + "version": "1.0.21", "description": "", "type": "module", "scripts": { diff --git a/packages/function/package.json b/packages/function/package.json index 4861ea8e..7129dbab 100644 --- a/packages/function/package.json +++ b/packages/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/function", - "version": "1.0.20", + "version": "1.0.21", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index b0c8be7d..2e97b6de 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.0.20", + "version": "1.0.21", "name": "opencode", "type": "module", "private": true, diff --git a/packages/plugin/package.json b/packages/plugin/package.json index 89793148..14aa2405 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/plugin", - "version": "1.0.20", + "version": "1.0.21", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index 24023d1b..b0dc34c1 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/sdk", - "version": "1.0.20", + "version": "1.0.21", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", diff --git a/packages/sdk/js/src/gen/types.gen.ts b/packages/sdk/js/src/gen/types.gen.ts index 97dc559d..7293f13c 100644 --- a/packages/sdk/js/src/gen/types.gen.ts +++ b/packages/sdk/js/src/gen/types.gen.ts @@ -163,7 +163,7 @@ export type KeybindsConfig = { */ history_previous?: string /** - * Previous history item + * Next history item */ history_next?: string /** diff --git a/packages/slack/package.json b/packages/slack/package.json index 5e8d6bb4..76f3dea8 100644 --- a/packages/slack/package.json +++ b/packages/slack/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/slack", - "version": "1.0.20", + "version": "1.0.21", "type": "module", "scripts": { "dev": "bun run src/index.ts", diff --git a/packages/ui/package.json b/packages/ui/package.json index 96cca8ed..7cfd1e78 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "1.0.20", + "version": "1.0.21", "type": "module", "exports": { ".": "./src/components/index.ts", diff --git a/packages/web/package.json b/packages/web/package.json index d0ec79f8..fe654df9 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/web", "type": "module", - "version": "1.0.20", + "version": "1.0.21", "scripts": { "dev": "astro dev", "dev:remote": "VITE_API_URL=https://api.opencode.ai astro dev", diff --git a/sdks/vscode/package.json b/sdks/vscode/package.json index 82adb2da..7557f4c0 100644 --- a/sdks/vscode/package.json +++ b/sdks/vscode/package.json @@ -2,7 +2,7 @@ "name": "opencode", "displayName": "opencode", "description": "opencode for VS Code", - "version": "1.0.20", + "version": "1.0.21", "publisher": "sst-dev", "repository": { "type": "git", From 7a7060ef156451c90137cfccd74a59e3f3e40f68 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Tue, 4 Nov 2025 13:32:56 -0500 Subject: [PATCH 04/10] fix session performance issue from large diffs --- packages/opencode/src/server/server.ts | 28 +++++++++++++++ packages/opencode/src/session/index.ts | 11 ++++-- packages/opencode/src/session/summary.ts | 5 ++- packages/opencode/src/storage/storage.ts | 43 ++++++++++++++++++------ packages/sdk/js/src/gen/sdk.gen.ts | 9 +++-- packages/sdk/js/src/gen/types.gen.ts | 22 ++++++++++-- 6 files changed, 101 insertions(+), 17 deletions(-) diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts index 68c61453..59e066e1 100644 --- a/packages/opencode/src/server/server.ts +++ b/packages/opencode/src/server/server.ts @@ -758,6 +758,34 @@ export namespace Server { return c.json(messages) }, ) + .get( + "/session/:id/diff", + describeRoute({ + description: "Get the diff for this session", + operationId: "session.diff", + responses: { + 200: { + description: "List of diffs", + content: { + "application/json": { + schema: resolver(Snapshot.FileDiff.array()), + }, + }, + }, + ...errors(400, 404), + }, + }), + validator( + "param", + z.object({ + id: z.string().meta({ description: "Session ID" }), + }), + ), + async (c) => { + const diff = await Session.diff(c.req.valid("param").id) + return c.json(diff) + }, + ) .get( "/session/:id/message/:messageID", describeRoute({ diff --git a/packages/opencode/src/session/index.ts b/packages/opencode/src/session/index.ts index 71d59d84..f8a2ba91 100644 --- a/packages/opencode/src/session/index.ts +++ b/packages/opencode/src/session/index.ts @@ -15,8 +15,8 @@ import { MessageV2 } from "./message-v2" import { Instance } from "../project/instance" import { SessionPrompt } from "./prompt" import { fn } from "@/util/fn" -import { Snapshot } from "@/snapshot" import { Command } from "../command" +import { Snapshot } from "@/snapshot" export namespace Session { const log = Log.create({ service: "session" }) @@ -42,7 +42,9 @@ export namespace Session { parentID: Identifier.schema("session").optional(), summary: z .object({ - diffs: Snapshot.FileDiff.array(), + additions: z.number(), + deletions: z.number(), + diffs: Snapshot.FileDiff.array().optional(), }) .optional(), share: z @@ -258,6 +260,11 @@ export namespace Session { return result } + export const diff = fn(Identifier.schema("session"), async (sessionID) => { + const diffs = await Storage.read(["session_diff", sessionID]) + return diffs ?? [] + }) + export const messages = fn(Identifier.schema("session"), async (sessionID) => { const result = [] as MessageV2.WithParts[] for (const p of await Storage.list(["message", sessionID])) { diff --git a/packages/opencode/src/session/summary.ts b/packages/opencode/src/session/summary.ts index ffd0f8da..9795a306 100644 --- a/packages/opencode/src/session/summary.ts +++ b/packages/opencode/src/session/summary.ts @@ -11,6 +11,7 @@ import { SystemPrompt } from "./system" import { Log } from "@/util/log" import path from "path" import { Instance } from "@/project/instance" +import { Storage } from "@/storage/storage" export namespace SessionSummary { const log = Log.create({ service: "session.summary" }) @@ -44,9 +45,11 @@ export namespace SessionSummary { ) await Session.update(input.sessionID, (draft) => { draft.summary = { - diffs, + additions: diffs.reduce((sum, x) => sum + x.additions, 0), + deletions: diffs.reduce((sum, x) => sum + x.deletions, 0), } }) + await Storage.write(["session_diff", input.sessionID], diffs) } async function summarizeMessage(input: { messageID: string; messages: MessageV2.WithParts[] }) { diff --git a/packages/opencode/src/storage/storage.ts b/packages/opencode/src/storage/storage.ts index 9eb0f8f5..66ce20d9 100644 --- a/packages/opencode/src/storage/storage.ts +++ b/packages/opencode/src/storage/storage.ts @@ -85,7 +85,9 @@ export namespace Storage { const session = await Bun.file(sessionFile).json() await Bun.write(dest, JSON.stringify(session)) log.info(`migrating messages for session ${session.id}`) - for await (const msgFile of new Bun.Glob(`storage/session/message/${session.id}/*.json`).scan({ + for await (const msgFile of new Bun.Glob( + `storage/session/message/${session.id}/*.json`, + ).scan({ cwd: fullProjectDir, absolute: true, })) { @@ -98,12 +100,12 @@ export namespace Storage { await Bun.write(dest, JSON.stringify(message)) log.info(`migrating parts for message ${message.id}`) - for await (const partFile of new Bun.Glob(`storage/session/part/${session.id}/${message.id}/*.json`).scan( - { - cwd: fullProjectDir, - absolute: true, - }, - )) { + for await (const partFile of new Bun.Glob( + `storage/session/part/${session.id}/${message.id}/*.json`, + ).scan({ + cwd: fullProjectDir, + absolute: true, + })) { const dest = path.join(dir, "part", message.id, path.basename(partFile)) const part = await Bun.file(partFile).json() log.info("copying", { @@ -117,6 +119,29 @@ export namespace Storage { } } }, + async (dir) => { + for await (const item of new Bun.Glob("session/*/*.json").scan({ + cwd: dir, + absolute: true, + })) { + const session = await Bun.file(item).json() + if (!session.projectID) continue + if (!session.summary?.diffs) continue + const { diffs } = session.summary + await Bun.file(path.join(dir, "session_diff", session.id + ".json")).write( + JSON.stringify(diffs), + ) + await Bun.file(path.join(dir, "session", session.projectID, session.id + ".json")).write( + JSON.stringify({ + ...session, + summary: { + additions: diffs.reduce((sum: any, x: any) => sum + x.additions, 0), + deletions: diffs.reduce((sum: any, x: any) => sum + x.deletions, 0), + }, + }), + ) + } + }, ] const state = lazy(async () => { @@ -128,9 +153,7 @@ export namespace Storage { for (let index = migration; index < MIGRATIONS.length; index++) { log.info("running migration", { index }) const migration = MIGRATIONS[index] - await migration(dir).catch((e) => { - log.error("failed to run migration", { error: e, index }) - }) + await migration(dir).catch(() => log.error("failed to run migration", { index })) await Bun.write(path.join(dir, "migration"), (index + 1).toString()) } return { diff --git a/packages/sdk/js/src/gen/sdk.gen.ts b/packages/sdk/js/src/gen/sdk.gen.ts index b76b6996..1a54da8f 100644 --- a/packages/sdk/js/src/gen/sdk.gen.ts +++ b/packages/sdk/js/src/gen/sdk.gen.ts @@ -55,6 +55,7 @@ import type { SessionShareErrors, SessionDiffData, SessionDiffResponses, + SessionDiffErrors, SessionSummarizeData, SessionSummarizeResponses, SessionSummarizeErrors, @@ -475,12 +476,16 @@ class Session extends _HeyApiClient { } /** - * Get the diff that resulted from this user message + * Get the diff for this session */ public diff( options: Options, ) { - return (options.client ?? this._client).get({ + return (options.client ?? this._client).get< + SessionDiffResponses, + SessionDiffErrors, + ThrowOnError + >({ url: "/session/{id}/diff", ...options, }) diff --git a/packages/sdk/js/src/gen/types.gen.ts b/packages/sdk/js/src/gen/types.gen.ts index 7293f13c..d4b76332 100644 --- a/packages/sdk/js/src/gen/types.gen.ts +++ b/packages/sdk/js/src/gen/types.gen.ts @@ -527,7 +527,9 @@ export type Session = { directory: string parentID?: string summary?: { - diffs: Array + additions: number + deletions: number + diffs?: Array } share?: { url: string @@ -1882,6 +1884,9 @@ export type SessionShareResponse = SessionShareResponses[keyof SessionShareRespo export type SessionDiffData = { body?: never path: { + /** + * Session ID + */ id: string } query?: { @@ -1891,9 +1896,22 @@ export type SessionDiffData = { url: "/session/{id}/diff" } +export type SessionDiffErrors = { + /** + * Bad request + */ + 400: BadRequestError + /** + * Not found + */ + 404: NotFoundError +} + +export type SessionDiffError = SessionDiffErrors[keyof SessionDiffErrors] + export type SessionDiffResponses = { /** - * Successfully retrieved diff + * List of diffs */ 200: Array } From 434c0ff0d7f7e6f453d3c51560d16bc91e473ca8 Mon Sep 17 00:00:00 2001 From: opencode Date: Tue, 4 Nov 2025 18:41:38 +0000 Subject: [PATCH 05/10] release: v1.0.22 --- bun.lock | 22 +++++++++++----------- packages/console/app/package.json | 2 +- packages/console/core/package.json | 2 +- packages/console/function/package.json | 2 +- packages/console/mail/package.json | 2 +- packages/desktop/package.json | 2 +- packages/function/package.json | 2 +- packages/opencode/package.json | 2 +- packages/plugin/package.json | 2 +- packages/sdk/js/package.json | 2 +- packages/slack/package.json | 2 +- packages/ui/package.json | 2 +- packages/web/package.json | 2 +- sdks/vscode/package.json | 2 +- 14 files changed, 24 insertions(+), 24 deletions(-) diff --git a/bun.lock b/bun.lock index 34a21d6a..92b77a60 100644 --- a/bun.lock +++ b/bun.lock @@ -39,7 +39,7 @@ }, "packages/console/core": { "name": "@opencode-ai/console-core", - "version": "1.0.21", + "version": "1.0.22", "dependencies": { "@aws-sdk/client-sts": "3.782.0", "@jsx-email/render": "1.1.1", @@ -66,7 +66,7 @@ }, "packages/console/function": { "name": "@opencode-ai/console-function", - "version": "1.0.21", + "version": "1.0.22", "dependencies": { "@ai-sdk/anthropic": "2.0.0", "@ai-sdk/openai": "2.0.2", @@ -90,7 +90,7 @@ }, "packages/console/mail": { "name": "@opencode-ai/console-mail", - "version": "1.0.21", + "version": "1.0.22", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", @@ -111,7 +111,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "1.0.21", + "version": "1.0.22", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -150,7 +150,7 @@ }, "packages/function": { "name": "@opencode-ai/function", - "version": "1.0.21", + "version": "1.0.22", "dependencies": { "@octokit/auth-app": "8.0.1", "@octokit/rest": "22.0.0", @@ -166,7 +166,7 @@ }, "packages/opencode": { "name": "opencode", - "version": "1.0.21", + "version": "1.0.22", "bin": { "opencode": "./bin/opencode", }, @@ -243,7 +243,7 @@ }, "packages/plugin": { "name": "@opencode-ai/plugin", - "version": "1.0.21", + "version": "1.0.22", "dependencies": { "@opencode-ai/sdk": "workspace:*", "zod": "catalog:", @@ -263,7 +263,7 @@ }, "packages/sdk/js": { "name": "@opencode-ai/sdk", - "version": "1.0.21", + "version": "1.0.22", "devDependencies": { "@hey-api/openapi-ts": "0.81.0", "@tsconfig/node22": "catalog:", @@ -274,7 +274,7 @@ }, "packages/slack": { "name": "@opencode-ai/slack", - "version": "1.0.21", + "version": "1.0.22", "dependencies": { "@opencode-ai/sdk": "workspace:*", "@slack/bolt": "^3.17.1", @@ -287,7 +287,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "1.0.21", + "version": "1.0.22", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -317,7 +317,7 @@ }, "packages/web": { "name": "@opencode-ai/web", - "version": "1.0.21", + "version": "1.0.22", "dependencies": { "@astrojs/cloudflare": "12.6.3", "@astrojs/markdown-remark": "6.3.1", diff --git a/packages/console/app/package.json b/packages/console/app/package.json index cb14e648..75af9169 100644 --- a/packages/console/app/package.json +++ b/packages/console/app/package.json @@ -7,7 +7,7 @@ "dev:remote": "VITE_AUTH_URL=https://auth.dev.opencode.ai bun sst shell --stage=dev bun dev", "build": "vinxi build && ../../opencode/script/schema.ts ./.output/public/config.json", "start": "vinxi start", - "version": "1.0.21" + "version": "1.0.22" }, "dependencies": { "@ibm/plex": "6.4.1", diff --git a/packages/console/core/package.json b/packages/console/core/package.json index 477a5549..b5dad734 100644 --- a/packages/console/core/package.json +++ b/packages/console/core/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/console-core", - "version": "1.0.21", + "version": "1.0.22", "private": true, "type": "module", "dependencies": { diff --git a/packages/console/function/package.json b/packages/console/function/package.json index 9cae8d9f..f7133067 100644 --- a/packages/console/function/package.json +++ b/packages/console/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-function", - "version": "1.0.21", + "version": "1.0.22", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/console/mail/package.json b/packages/console/mail/package.json index 2e1943c2..3e84e2ca 100644 --- a/packages/console/mail/package.json +++ b/packages/console/mail/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-mail", - "version": "1.0.21", + "version": "1.0.22", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", diff --git a/packages/desktop/package.json b/packages/desktop/package.json index 23f2a734..2c689723 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/desktop", - "version": "1.0.21", + "version": "1.0.22", "description": "", "type": "module", "scripts": { diff --git a/packages/function/package.json b/packages/function/package.json index 7129dbab..bb223e3e 100644 --- a/packages/function/package.json +++ b/packages/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/function", - "version": "1.0.21", + "version": "1.0.22", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 2e97b6de..b050e7ab 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.0.21", + "version": "1.0.22", "name": "opencode", "type": "module", "private": true, diff --git a/packages/plugin/package.json b/packages/plugin/package.json index 14aa2405..85fee69b 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/plugin", - "version": "1.0.21", + "version": "1.0.22", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index b0dc34c1..1931dff2 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/sdk", - "version": "1.0.21", + "version": "1.0.22", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", diff --git a/packages/slack/package.json b/packages/slack/package.json index 76f3dea8..a38cdd10 100644 --- a/packages/slack/package.json +++ b/packages/slack/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/slack", - "version": "1.0.21", + "version": "1.0.22", "type": "module", "scripts": { "dev": "bun run src/index.ts", diff --git a/packages/ui/package.json b/packages/ui/package.json index 7cfd1e78..38b28deb 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "1.0.21", + "version": "1.0.22", "type": "module", "exports": { ".": "./src/components/index.ts", diff --git a/packages/web/package.json b/packages/web/package.json index fe654df9..39335a00 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/web", "type": "module", - "version": "1.0.21", + "version": "1.0.22", "scripts": { "dev": "astro dev", "dev:remote": "VITE_API_URL=https://api.opencode.ai astro dev", diff --git a/sdks/vscode/package.json b/sdks/vscode/package.json index 7557f4c0..7d29958f 100644 --- a/sdks/vscode/package.json +++ b/sdks/vscode/package.json @@ -2,7 +2,7 @@ "name": "opencode", "displayName": "opencode", "description": "opencode for VS Code", - "version": "1.0.21", + "version": "1.0.22", "publisher": "sst-dev", "repository": { "type": "git", From ee1ff8cc07fcac5e6e879bc8084835f339a6b52c Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Tue, 4 Nov 2025 14:07:22 -0500 Subject: [PATCH 06/10] tui: add ability to interrupt running sessions from command palette --- .../cli/cmd/tui/component/prompt/index.tsx | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx index 7835539e..785eb7e4 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx @@ -115,15 +115,11 @@ export function Prompt(props: PromptProps) { { title: "Clear prompt", value: "prompt.clear", - disabled: true, category: "Prompt", + disabled: true, onSelect: (dialog) => { input.extmarks.clear() - setStore("prompt", { - input: "", - parts: [], - }) - setStore("extmarkToPartIndex", new Map()) + input.clear() dialog.clear() }, }, @@ -156,16 +152,27 @@ export function Prompt(props: PromptProps) { } }, }, + { + title: "Interrupt session", + value: "session.interrupt", + keybind: "session_interrupt", + category: "Session", + disabled: true, + onSelect: (dialog) => { + if (!props.sessionID) return + sdk.client.session.abort({ + path: { + id: props.sessionID, + }, + }) + dialog.clear() + }, + }, ] }) sdk.event.on(TuiEvent.PromptAppend.type, (evt) => { - setStore( - "prompt", - produce((draft) => { - draft.input += evt.properties.text - }), - ) + input.insertText(evt.properties.text) }) createEffect(() => { From 52e2b40610da07898339e8f23190fd3b18d09611 Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Tue, 4 Nov 2025 13:22:18 -0600 Subject: [PATCH 07/10] fix: stop showing auto complete if user types a space --- .../cmd/tui/component/prompt/autocomplete.tsx | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx index 02fd3fcc..812496dd 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx @@ -54,6 +54,12 @@ export function Autocomplete(props: { const val = props.input().getTextRange(store.index + 1, props.input().cursorOffset + 1) + // If the filter contains a space, hide the autocomplete + if (val.includes(" ")) { + hide() + return undefined + } + return val }) @@ -373,7 +379,17 @@ export function Autocomplete(props: { return store.visible }, onInput() { - if (store.visible && props.input().cursorOffset <= store.index) hide() + if (store.visible) { + if (props.input().cursorOffset <= store.index) { + hide() + return + } + // Check if a space was typed after the trigger character + const currentText = props.input().getTextRange(store.index + 1, props.input().cursorOffset + 1) + if (currentText.includes(" ")) { + hide() + } + } }, onKeyDown(e: KeyEvent) { if (store.visible) { From 8a9a474df625f578034f36b9bf7ea1315bfbde28 Mon Sep 17 00:00:00 2001 From: Timo Clasen Date: Tue, 4 Nov 2025 20:28:03 +0100 Subject: [PATCH 08/10] feat(TUI): add autocomplete readline style keybinds (#3717) Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> --- .../cli/cmd/tui/component/dialog-command.tsx | 13 +++++--- .../cmd/tui/component/prompt/autocomplete.tsx | 30 +++++++++++++++---- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-command.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-command.tsx index 66a312e5..b9ba4a9b 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-command.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-command.tsx @@ -22,15 +22,16 @@ export type CommandOption = DialogSelectOption & { function init() { const [registrations, setRegistrations] = createSignal[]>([]) + const [suspendCount, setSuspendCount] = createSignal(0) const dialog = useDialog() const keybind = useKeybind() const options = createMemo(() => { return registrations().flatMap((x) => x()) }) + const suspended = () => suspendCount() > 0 - let keybinds = true useKeyboard((evt) => { - if (!keybinds) return + if (suspended()) return for (const option of options()) { if (option.keybind && keybind.match(option.keybind, evt)) { evt.preventDefault() @@ -50,8 +51,9 @@ function init() { } }, keybinds(enabled: boolean) { - keybinds = enabled + setSuspendCount((count) => count + (enabled ? -1 : 1)) }, + suspended, show() { dialog.replace(() => ) }, @@ -83,7 +85,10 @@ export function CommandProvider(props: ParentProps) { const keybind = useKeybind() useKeyboard((evt) => { - if (keybind.match("command_list", evt) && dialog.stack.length === 0) { + if (value.suspended()) return + if (dialog.stack.length > 0) return + if (evt.defaultPrevented) return + if (keybind.match("command_list", evt)) { evt.preventDefault() dialog.replace(() => ) return diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx index 812496dd..a4c1f33d 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/autocomplete.tsx @@ -393,11 +393,31 @@ export function Autocomplete(props: { }, onKeyDown(e: KeyEvent) { if (store.visible) { - if (e.name === "up") move(-1) - if (e.name === "down") move(1) - if (e.name === "escape") hide() - if (e.name === "return" || e.name === "tab") select() - if (["up", "down", "return", "tab", "escape"].includes(e.name)) e.preventDefault() + const name = e.name?.toLowerCase() + const ctrlOnly = e.ctrl && !e.meta && !e.shift + const isNavUp = name === "up" || (ctrlOnly && name === "p") + const isNavDown = name === "down" || (ctrlOnly && name === "n") + + if (isNavUp) { + move(-1) + e.preventDefault() + return + } + if (isNavDown) { + move(1) + e.preventDefault() + return + } + if (name === "escape") { + hide() + e.preventDefault() + return + } + if (name === "return" || name === "tab") { + select() + e.preventDefault() + return + } } if (!store.visible) { if (e.name === "@") { From ba8bc1b8b488e10eec8c0b915a753f4810164343 Mon Sep 17 00:00:00 2001 From: opencode Date: Tue, 4 Nov 2025 19:38:18 +0000 Subject: [PATCH 09/10] release: v1.0.23 --- bun.lock | 22 +++++++++++----------- packages/console/app/package.json | 2 +- packages/console/core/package.json | 2 +- packages/console/function/package.json | 2 +- packages/console/mail/package.json | 2 +- packages/desktop/package.json | 2 +- packages/function/package.json | 2 +- packages/opencode/package.json | 2 +- packages/plugin/package.json | 2 +- packages/sdk/js/package.json | 2 +- packages/slack/package.json | 2 +- packages/ui/package.json | 2 +- packages/web/package.json | 2 +- sdks/vscode/package.json | 2 +- 14 files changed, 24 insertions(+), 24 deletions(-) diff --git a/bun.lock b/bun.lock index 92b77a60..e18ad950 100644 --- a/bun.lock +++ b/bun.lock @@ -39,7 +39,7 @@ }, "packages/console/core": { "name": "@opencode-ai/console-core", - "version": "1.0.22", + "version": "1.0.23", "dependencies": { "@aws-sdk/client-sts": "3.782.0", "@jsx-email/render": "1.1.1", @@ -66,7 +66,7 @@ }, "packages/console/function": { "name": "@opencode-ai/console-function", - "version": "1.0.22", + "version": "1.0.23", "dependencies": { "@ai-sdk/anthropic": "2.0.0", "@ai-sdk/openai": "2.0.2", @@ -90,7 +90,7 @@ }, "packages/console/mail": { "name": "@opencode-ai/console-mail", - "version": "1.0.22", + "version": "1.0.23", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", @@ -111,7 +111,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "1.0.22", + "version": "1.0.23", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -150,7 +150,7 @@ }, "packages/function": { "name": "@opencode-ai/function", - "version": "1.0.22", + "version": "1.0.23", "dependencies": { "@octokit/auth-app": "8.0.1", "@octokit/rest": "22.0.0", @@ -166,7 +166,7 @@ }, "packages/opencode": { "name": "opencode", - "version": "1.0.22", + "version": "1.0.23", "bin": { "opencode": "./bin/opencode", }, @@ -243,7 +243,7 @@ }, "packages/plugin": { "name": "@opencode-ai/plugin", - "version": "1.0.22", + "version": "1.0.23", "dependencies": { "@opencode-ai/sdk": "workspace:*", "zod": "catalog:", @@ -263,7 +263,7 @@ }, "packages/sdk/js": { "name": "@opencode-ai/sdk", - "version": "1.0.22", + "version": "1.0.23", "devDependencies": { "@hey-api/openapi-ts": "0.81.0", "@tsconfig/node22": "catalog:", @@ -274,7 +274,7 @@ }, "packages/slack": { "name": "@opencode-ai/slack", - "version": "1.0.22", + "version": "1.0.23", "dependencies": { "@opencode-ai/sdk": "workspace:*", "@slack/bolt": "^3.17.1", @@ -287,7 +287,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "1.0.22", + "version": "1.0.23", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/sdk": "workspace:*", @@ -317,7 +317,7 @@ }, "packages/web": { "name": "@opencode-ai/web", - "version": "1.0.22", + "version": "1.0.23", "dependencies": { "@astrojs/cloudflare": "12.6.3", "@astrojs/markdown-remark": "6.3.1", diff --git a/packages/console/app/package.json b/packages/console/app/package.json index 75af9169..7e06d824 100644 --- a/packages/console/app/package.json +++ b/packages/console/app/package.json @@ -7,7 +7,7 @@ "dev:remote": "VITE_AUTH_URL=https://auth.dev.opencode.ai bun sst shell --stage=dev bun dev", "build": "vinxi build && ../../opencode/script/schema.ts ./.output/public/config.json", "start": "vinxi start", - "version": "1.0.22" + "version": "1.0.23" }, "dependencies": { "@ibm/plex": "6.4.1", diff --git a/packages/console/core/package.json b/packages/console/core/package.json index b5dad734..c1ab2347 100644 --- a/packages/console/core/package.json +++ b/packages/console/core/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/console-core", - "version": "1.0.22", + "version": "1.0.23", "private": true, "type": "module", "dependencies": { diff --git a/packages/console/function/package.json b/packages/console/function/package.json index f7133067..0c6e0288 100644 --- a/packages/console/function/package.json +++ b/packages/console/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-function", - "version": "1.0.22", + "version": "1.0.23", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/console/mail/package.json b/packages/console/mail/package.json index 3e84e2ca..30e772b6 100644 --- a/packages/console/mail/package.json +++ b/packages/console/mail/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-mail", - "version": "1.0.22", + "version": "1.0.23", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", diff --git a/packages/desktop/package.json b/packages/desktop/package.json index 2c689723..34188445 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/desktop", - "version": "1.0.22", + "version": "1.0.23", "description": "", "type": "module", "scripts": { diff --git a/packages/function/package.json b/packages/function/package.json index bb223e3e..eeb842ca 100644 --- a/packages/function/package.json +++ b/packages/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/function", - "version": "1.0.22", + "version": "1.0.23", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index b050e7ab..3e4f5c02 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.0.22", + "version": "1.0.23", "name": "opencode", "type": "module", "private": true, diff --git a/packages/plugin/package.json b/packages/plugin/package.json index 85fee69b..0ad4afe6 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/plugin", - "version": "1.0.22", + "version": "1.0.23", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index 1931dff2..d4de9ca1 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/sdk", - "version": "1.0.22", + "version": "1.0.23", "type": "module", "scripts": { "typecheck": "tsgo --noEmit", diff --git a/packages/slack/package.json b/packages/slack/package.json index a38cdd10..f9392ef3 100644 --- a/packages/slack/package.json +++ b/packages/slack/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/slack", - "version": "1.0.22", + "version": "1.0.23", "type": "module", "scripts": { "dev": "bun run src/index.ts", diff --git a/packages/ui/package.json b/packages/ui/package.json index 38b28deb..585a249b 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "1.0.22", + "version": "1.0.23", "type": "module", "exports": { ".": "./src/components/index.ts", diff --git a/packages/web/package.json b/packages/web/package.json index 39335a00..2de696b3 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/web", "type": "module", - "version": "1.0.22", + "version": "1.0.23", "scripts": { "dev": "astro dev", "dev:remote": "VITE_API_URL=https://api.opencode.ai astro dev", diff --git a/sdks/vscode/package.json b/sdks/vscode/package.json index 7d29958f..6a8ed497 100644 --- a/sdks/vscode/package.json +++ b/sdks/vscode/package.json @@ -2,7 +2,7 @@ "name": "opencode", "displayName": "opencode", "description": "opencode for VS Code", - "version": "1.0.22", + "version": "1.0.23", "publisher": "sst-dev", "repository": { "type": "git", From fe94bb8e50ed9625e553cc7bd79d3a02889c2979 Mon Sep 17 00:00:00 2001 From: Ola <74724224+OlaHulleberg@users.noreply.github.com> Date: Tue, 4 Nov 2025 22:36:12 +0100 Subject: [PATCH 10/10] feat(provider): add GitHub Enterprise support for Copilot (#2522) Co-authored-by: Jon-Mikkel Korsvik <48263282+jkorsvik@users.noreply.github.com> Co-authored-by: GitHub Action Co-authored-by: Aiden Cline --- packages/opencode/src/auth/index.ts | 1 + packages/opencode/src/cli/cmd/auth.ts | 355 ++++++++++++--------- packages/opencode/src/config/config.ts | 1 + packages/opencode/src/plugin/index.ts | 2 +- packages/opencode/src/provider/provider.ts | 60 +++- packages/plugin/src/index.ts | 61 +++- packages/sdk/js/src/gen/types.gen.ts | 5 + 7 files changed, 319 insertions(+), 166 deletions(-) diff --git a/packages/opencode/src/auth/index.ts b/packages/opencode/src/auth/index.ts index 6d90c932..883b9acc 100644 --- a/packages/opencode/src/auth/index.ts +++ b/packages/opencode/src/auth/index.ts @@ -10,6 +10,7 @@ export namespace Auth { refresh: z.string(), access: z.string(), expires: z.number(), + enterpriseUrl: z.string().optional(), }) .meta({ ref: "OAuth" }) diff --git a/packages/opencode/src/cli/cmd/auth.ts b/packages/opencode/src/cli/cmd/auth.ts index 763d82b3..aa833e97 100644 --- a/packages/opencode/src/cli/cmd/auth.ts +++ b/packages/opencode/src/cli/cmd/auth.ts @@ -102,178 +102,223 @@ export const AuthLoginCommand = cmd({ prompts.outro("Done") return } - await ModelsDev.refresh().catch(() => {}) - const providers = await ModelsDev.get() - const priority: Record = { - opencode: 0, - anthropic: 1, - "github-copilot": 2, - openai: 3, - google: 4, - openrouter: 5, - vercel: 6, - } - let provider = await prompts.autocomplete({ - message: "Select provider", - maxItems: 8, - options: [ - ...pipe( - providers, - values(), - sortBy( - (x) => priority[x.id] ?? 99, - (x) => x.name ?? x.id, - ), - map((x) => ({ - label: x.name, - value: x.id, - hint: priority[x.id] <= 1 ? "recommended" : undefined, - })), + await ModelsDev.refresh().catch(() => {}) + const providers = await ModelsDev.get() + const priority: Record = { + opencode: 0, + anthropic: 1, + "github-copilot": 2, + openai: 3, + google: 4, + openrouter: 5, + vercel: 6, + } + let provider = await prompts.autocomplete({ + message: "Select provider", + maxItems: 8, + options: [ + ...pipe( + providers, + values(), + sortBy( + (x) => priority[x.id] ?? 99, + (x) => x.name ?? x.id, ), - { - value: "other", - label: "Other", - }, - ], - }) + map((x) => ({ + label: x.name, + value: x.id, + hint: priority[x.id] <= 1 ? "recommended" : undefined, + })), + ), + { + value: "other", + label: "Other", + }, + ], + }) - if (prompts.isCancel(provider)) throw new UI.CancelledError() + if (prompts.isCancel(provider)) throw new UI.CancelledError() - const plugin = await Plugin.list().then((x) => x.find((x) => x.auth?.provider === provider)) - if (plugin && plugin.auth) { - let index = 0 - if (plugin.auth.methods.length > 1) { - const method = await prompts.select({ - message: "Login method", - options: [ - ...plugin.auth.methods.map((x, index) => ({ - label: x.label, - value: index.toString(), - })), - ], - }) - if (prompts.isCancel(method)) throw new UI.CancelledError() - index = parseInt(method) - } - const method = plugin.auth.methods[index] - if (method.type === "oauth") { - await new Promise((resolve) => setTimeout(resolve, 10)) - const authorize = await method.authorize() + const plugin = await Plugin.list().then((x) => x.find((x) => x.auth?.provider === provider)) + if (plugin && plugin.auth) { + let index = 0 + if (plugin.auth.methods.length > 1) { + const method = await prompts.select({ + message: "Login method", + options: [ + ...plugin.auth.methods.map((x, index) => ({ + label: x.label, + value: index.toString(), + })), + ], + }) + if (prompts.isCancel(method)) throw new UI.CancelledError() + index = parseInt(method) + } + const method = plugin.auth.methods[index] - if (authorize.url) { - prompts.log.info("Go to: " + authorize.url) + // Handle prompts for all auth types + await new Promise((resolve) => setTimeout(resolve, 10)) + const inputs: Record = {} + if (method.prompts) { + for (const prompt of method.prompts) { + if (prompt.condition && !prompt.condition(inputs)) { + continue } - - if (authorize.method === "auto") { - if (authorize.instructions) { - prompts.log.info(authorize.instructions) - } - const spinner = prompts.spinner() - spinner.start("Waiting for authorization...") - const result = await authorize.callback() - if (result.type === "failed") { - spinner.stop("Failed to authorize", 1) - } - if (result.type === "success") { - if ("refresh" in result) { - await Auth.set(provider, { - type: "oauth", - refresh: result.refresh, - access: result.access, - expires: result.expires, - }) - } - if ("key" in result) { - await Auth.set(provider, { - type: "api", - key: result.key, - }) - } - spinner.stop("Login successful") - } - } - - if (authorize.method === "code") { - const code = await prompts.text({ - message: "Paste the authorization code here: ", - validate: (x) => (x && x.length > 0 ? undefined : "Required"), + if (prompt.type === "select") { + const value = await prompts.select({ + message: prompt.message, + options: prompt.options, }) - if (prompts.isCancel(code)) throw new UI.CancelledError() - const result = await authorize.callback(code) - if (result.type === "failed") { - prompts.log.error("Failed to authorize") + if (prompts.isCancel(value)) throw new UI.CancelledError() + inputs[prompt.key] = value + } else { + const value = await prompts.text({ + message: prompt.message, + placeholder: prompt.placeholder, + validate: prompt.validate ? (v) => prompt.validate!(v ?? "") : undefined, + }) + if (prompts.isCancel(value)) throw new UI.CancelledError() + inputs[prompt.key] = value + } + } + } + + if (method.type === "oauth") { + const authorize = await method.authorize(inputs) + + if (authorize.url) { + prompts.log.info("Go to: " + authorize.url) + } + + if (authorize.method === "auto") { + if (authorize.instructions) { + prompts.log.info(authorize.instructions) + } + const spinner = prompts.spinner() + spinner.start("Waiting for authorization...") + const result = await authorize.callback() + if (result.type === "failed") { + spinner.stop("Failed to authorize", 1) + } + if (result.type === "success") { + const saveProvider = result.provider ?? provider + if ("refresh" in result) { + const { type: _, provider: __, refresh, access, expires, ...extraFields } = result + await Auth.set(saveProvider, { + type: "oauth", + refresh, + access, + expires, + ...extraFields, + }) } - if (result.type === "success") { - if ("refresh" in result) { - await Auth.set(provider, { - type: "oauth", - refresh: result.refresh, - access: result.access, - expires: result.expires, - }) - } - if ("key" in result) { - await Auth.set(provider, { - type: "api", - key: result.key, - }) - } - prompts.log.success("Login successful") + if ("key" in result) { + await Auth.set(saveProvider, { + type: "api", + key: result.key, + }) } + spinner.stop("Login successful") + } + } + + if (authorize.method === "code") { + const code = await prompts.text({ + message: "Paste the authorization code here: ", + validate: (x) => (x && x.length > 0 ? undefined : "Required"), + }) + if (prompts.isCancel(code)) throw new UI.CancelledError() + const result = await authorize.callback(code) + if (result.type === "failed") { + prompts.log.error("Failed to authorize") + } + if (result.type === "success") { + const saveProvider = result.provider ?? provider + if ("refresh" in result) { + const { type: _, provider: __, refresh, access, expires, ...extraFields } = result + await Auth.set(saveProvider, { + type: "oauth", + refresh, + access, + expires, + ...extraFields, + }) + } + if ("key" in result) { + await Auth.set(saveProvider, { + type: "api", + key: result.key, + }) + } + prompts.log.success("Login successful") + } + } + + prompts.outro("Done") + return + } + + if (method.type === "api") { + if (method.authorize) { + const result = await method.authorize(inputs) + if (result.type === "failed") { + prompts.log.error("Failed to authorize") + } + if (result.type === "success") { + const saveProvider = result.provider ?? provider + await Auth.set(saveProvider, { + type: "api", + key: result.key, + }) + prompts.log.success("Login successful") } prompts.outro("Done") return } } + } - if (provider === "other") { - provider = await prompts.text({ - message: "Enter provider id", - validate: (x) => (x && x.match(/^[0-9a-z-]+$/) ? undefined : "a-z, 0-9 and hyphens only"), - }) - if (prompts.isCancel(provider)) throw new UI.CancelledError() - provider = provider.replace(/^@ai-sdk\//, "") - if (prompts.isCancel(provider)) throw new UI.CancelledError() - prompts.log.warn( - `This only stores a credential for ${provider} - you will need configure it in opencode.json, check the docs for examples.`, - ) - } - - if (provider === "amazon-bedrock") { - prompts.log.info( - "Amazon bedrock can be configured with standard AWS environment variables like AWS_BEARER_TOKEN_BEDROCK, AWS_PROFILE or AWS_ACCESS_KEY_ID", - ) - prompts.outro("Done") - return - } - - if (provider === "google-vertex") { - prompts.log.info( - "Google Cloud Vertex AI uses Application Default Credentials. Set GOOGLE_APPLICATION_CREDENTIALS or run 'gcloud auth application-default login'. Optionally set GOOGLE_CLOUD_PROJECT and GOOGLE_CLOUD_LOCATION (or VERTEX_LOCATION)", - ) - prompts.outro("Done") - return - } - - if (provider === "opencode") { - prompts.log.info("Create an api key at https://opencode.ai/auth") - } - - if (provider === "vercel") { - prompts.log.info("You can create an api key at https://vercel.link/ai-gateway-token") - } - - const key = await prompts.password({ - message: "Enter your API key", - validate: (x) => (x && x.length > 0 ? undefined : "Required"), - }) - if (prompts.isCancel(key)) throw new UI.CancelledError() - await Auth.set(provider, { - type: "api", - key, + if (provider === "other") { + provider = await prompts.text({ + message: "Enter provider id", + validate: (x) => (x && x.match(/^[0-9a-z-]+$/) ? undefined : "a-z, 0-9 and hyphens only"), }) + if (prompts.isCancel(provider)) throw new UI.CancelledError() + provider = provider.replace(/^@ai-sdk\//, "") + if (prompts.isCancel(provider)) throw new UI.CancelledError() + prompts.log.warn( + `This only stores a credential for ${provider} - you will need configure it in opencode.json, check the docs for examples.`, + ) + } + if (provider === "amazon-bedrock") { + prompts.log.info( + "Amazon bedrock can be configured with standard AWS environment variables like AWS_BEARER_TOKEN_BEDROCK, AWS_PROFILE or AWS_ACCESS_KEY_ID", + ) prompts.outro("Done") + return + } + + if (provider === "opencode") { + prompts.log.info("Create an api key at https://opencode.ai/auth") + } + + if (provider === "vercel") { + prompts.log.info("You can create an api key at https://vercel.link/ai-gateway-token") + } + + const key = await prompts.password({ + message: "Enter your API key", + validate: (x) => (x && x.length > 0 ? undefined : "Required"), + }) + if (prompts.isCancel(key)) throw new UI.CancelledError() + await Auth.set(provider, { + type: "api", + key, + }) + + prompts.outro("Done") }, }) }, diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index 63a956fb..efd31ccb 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -574,6 +574,7 @@ export namespace Config { .object({ apiKey: z.string().optional(), baseURL: z.string().optional(), + enterpriseUrl: z.string().optional().describe("GitHub Enterprise URL for copilot authentication"), timeout: z .union([ z diff --git a/packages/opencode/src/plugin/index.ts b/packages/opencode/src/plugin/index.ts index 1d433628..a3d8d6c0 100644 --- a/packages/opencode/src/plugin/index.ts +++ b/packages/opencode/src/plugin/index.ts @@ -28,7 +28,7 @@ export namespace Plugin { } const plugins = [...(config.plugin ?? [])] if (!Flag.OPENCODE_DISABLE_DEFAULT_PLUGINS) { - plugins.push("opencode-copilot-auth@0.0.3") + plugins.push("opencode-copilot-auth@0.0.4") plugins.push("opencode-anthropic-auth@0.0.2") } for (let plugin of plugins) { diff --git a/packages/opencode/src/provider/provider.ts b/packages/opencode/src/provider/provider.ts index 730ba396..3be091df 100644 --- a/packages/opencode/src/provider/provider.ts +++ b/packages/opencode/src/provider/provider.ts @@ -283,6 +283,18 @@ export namespace Provider { const configProviders = Object.entries(config.provider ?? {}) + // Add GitHub Copilot Enterprise provider that inherits from GitHub Copilot + if (database["github-copilot"]) { + const githubCopilot = database["github-copilot"] + database["github-copilot-enterprise"] = { + ...githubCopilot, + id: "github-copilot-enterprise", + name: "GitHub Copilot Enterprise", + // Enterprise uses a different API endpoint - will be set dynamically based on auth + api: undefined, + } + } + for (const [providerID, provider] of configProviders) { const existing = database[providerID] const parsed: ModelsDev.Provider = { @@ -378,14 +390,44 @@ export namespace Provider { if (!plugin.auth) continue const providerID = plugin.auth.provider if (disabled.has(providerID)) continue + + // For github-copilot plugin, check if auth exists for either github-copilot or github-copilot-enterprise + let hasAuth = false const auth = await Auth.get(providerID) - if (!auth) continue + if (auth) hasAuth = true + + // Special handling for github-copilot: also check for enterprise auth + if (providerID === "github-copilot" && !hasAuth) { + const enterpriseAuth = await Auth.get("github-copilot-enterprise") + if (enterpriseAuth) hasAuth = true + } + + if (!hasAuth) continue if (!plugin.auth.loader) continue - const options = await plugin.auth.loader( - () => Auth.get(providerID) as any, - database[plugin.auth.provider], - ) - mergeProvider(plugin.auth.provider, options ?? {}, "custom") + + // Load for the main provider if auth exists + if (auth) { + const options = await plugin.auth.loader( + () => Auth.get(providerID) as any, + database[plugin.auth.provider], + ) + mergeProvider(plugin.auth.provider, options ?? {}, "custom") + } + + // If this is github-copilot plugin, also register for github-copilot-enterprise if auth exists + if (providerID === "github-copilot") { + const enterpriseProviderID = "github-copilot-enterprise" + if (!disabled.has(enterpriseProviderID)) { + const enterpriseAuth = await Auth.get(enterpriseProviderID) + if (enterpriseAuth) { + const enterpriseOptions = await plugin.auth.loader( + () => Auth.get(enterpriseProviderID) as any, + database[enterpriseProviderID], + ) + mergeProvider(enterpriseProviderID, enterpriseOptions ?? {}, "custom") + } + } + } } // load config @@ -458,7 +500,8 @@ export namespace Provider { : installedPath const mod = await import(modPath) if (options["timeout"] !== undefined && options["timeout"] !== null) { - // Only override fetch if user explicitly sets timeout + // Preserve custom fetch if it exists, wrap it with timeout logic + const customFetch = options["fetch"] options["fetch"] = async (input: any, init?: BunFetchRequestInit) => { const { signal, ...rest } = init ?? {} @@ -468,7 +511,8 @@ export namespace Provider { const combined = signals.length > 1 ? AbortSignal.any(signals) : signals[0] - return fetch(input, { + const fetchFn = customFetch ?? fetch + return fetchFn(input, { ...rest, signal: combined, // @ts-ignore see here: https://github.com/oven-sh/bun/issues/16682 diff --git a/packages/plugin/src/index.ts b/packages/plugin/src/index.ts index 9c2647c6..f103749b 100644 --- a/packages/plugin/src/index.ts +++ b/packages/plugin/src/index.ts @@ -39,13 +39,35 @@ export interface Hooks { | { type: "oauth" label: string - authorize(): Promise< + prompts?: Array< + | { + type: "text" + key: string + message: string + placeholder?: string + validate?: (value: string) => string | undefined + condition?: (inputs: Record) => boolean + } + | { + type: "select" + key: string + message: string + options: Array<{ + label: string + value: string + hint?: string + }> + condition?: (inputs: Record) => boolean + } + > + authorize(inputs?: Record): Promise< { url: string; instructions: string } & ( | { method: "auto" callback(): Promise< | ({ type: "success" + provider?: string } & ( | { refresh: string @@ -64,6 +86,7 @@ export interface Hooks { callback(code: string): Promise< | ({ type: "success" + provider?: string } & ( | { refresh: string @@ -80,7 +103,41 @@ export interface Hooks { ) > } - | { type: "api"; label: string } + | { + type: "api" + label: string + prompts?: Array< + | { + type: "text" + key: string + message: string + placeholder?: string + validate?: (value: string) => string | undefined + condition?: (inputs: Record) => boolean + } + | { + type: "select" + key: string + message: string + options: Array<{ + label: string + value: string + hint?: string + }> + condition?: (inputs: Record) => boolean + } + > + authorize?(inputs?: Record): Promise< + | { + type: "success" + key: string + provider?: string + } + | { + type: "failed" + } + > + } )[] } /** diff --git a/packages/sdk/js/src/gen/types.gen.ts b/packages/sdk/js/src/gen/types.gen.ts index d4b76332..0c0135b4 100644 --- a/packages/sdk/js/src/gen/types.gen.ts +++ b/packages/sdk/js/src/gen/types.gen.ts @@ -405,6 +405,10 @@ export type Config = { options?: { apiKey?: string baseURL?: string + /** + * GitHub Enterprise URL for copilot authentication + */ + enterpriseUrl?: string /** * Timeout in milliseconds for requests to this provider. Default is 300000 (5 minutes). Set to false to disable timeout. */ @@ -1135,6 +1139,7 @@ export type OAuth = { refresh: string access: string expires: number + enterpriseUrl?: string } export type ApiAuth = {