diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f160b417e..57f3abb93 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -58,6 +58,7 @@ jobs: ./script/publish.ts env: OPENCODE_BUMP: ${{ inputs.bump }} + OPENCODE_TAG: latest GITHUB_TOKEN: ${{ secrets.SST_GITHUB_TOKEN }} AUR_KEY: ${{ secrets.AUR_KEY }} NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index 711af3d42..a331462ed 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -30,7 +30,5 @@ jobs: run: | ./packages/opencode/script/publish.ts env: - OPENCODE_SNAPSHOT: true - OPENCODE_TAG: ${{ github.ref_name }} GITHUB_TOKEN: ${{ secrets.SST_GITHUB_TOKEN }} NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/bun.lock b/bun.lock index 683cc0587..804bebca2 100644 --- a/bun.lock +++ b/bun.lock @@ -4,6 +4,7 @@ "": { "name": "opencode", "dependencies": { + "@opencode-ai/script": "workspace:*", "@opencode-ai/sdk": "workspace:*", }, "devDependencies": { @@ -114,7 +115,7 @@ }, "packages/css": { "name": "@opencode-ai/css", - "version": "0.15.0", + "version": "0.15.2", }, "packages/desktop": { "name": "@opencode-ai/desktop", @@ -220,6 +221,7 @@ "@ai-sdk/google-vertex": "3.0.16", "@babel/core": "7.28.4", "@octokit/webhooks-types": "7.6.1", + "@opencode-ai/script": "workspace:*", "@parcel/watcher-win32-x64": "2.5.1", "@standard-schema/spec": "1.0.0", "@tsconfig/bun": "catalog:", @@ -246,6 +248,12 @@ "typescript": "catalog:", }, }, + "packages/script": { + "name": "@opencode-ai/script", + "devDependencies": { + "@types/bun": "catalog:", + }, + }, "packages/sdk/js": { "name": "@opencode-ai/sdk", "version": "0.15.2", @@ -270,7 +278,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "0.15.0", + "version": "0.15.2", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/css": "workspace:*", @@ -902,6 +910,8 @@ "@opencode-ai/plugin": ["@opencode-ai/plugin@workspace:packages/plugin"], + "@opencode-ai/script": ["@opencode-ai/script@workspace:packages/script"], + "@opencode-ai/sdk": ["@opencode-ai/sdk@workspace:packages/sdk/js"], "@opencode-ai/slack": ["@opencode-ai/slack@workspace:packages/slack"], diff --git a/package.json b/package.json index b1920bc32..c12f61804 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,8 @@ "turbo": "2.5.6" }, "dependencies": { - "@opencode-ai/sdk": "workspace:*" + "@opencode-ai/sdk": "workspace:*", + "@opencode-ai/script": "workspace:*" }, "repository": { "type": "git", diff --git a/packages/console/app/src/routes/workspace.tsx b/packages/console/app/src/routes/workspace.tsx index 2ac629f52..ef79ec4fe 100644 --- a/packages/console/app/src/routes/workspace.tsx +++ b/packages/console/app/src/routes/workspace.tsx @@ -1,4 +1,3 @@ -import { Show } from "solid-js" import { query, createAsync, RouteSectionProps, useParams, A } from "@solidjs/router" import "./workspace.css" import { IconWorkspaceLogo } from "../component/icon" @@ -7,7 +6,6 @@ import { UserMenu } from "./user-menu" import { withActor } from "~/context/auth.withActor" import { User } from "@opencode-ai/console-core/user.js" import { Actor } from "@opencode-ai/console-core/actor.js" -import { querySessionInfo } from "./workspace/common" const getUserEmail = query(async (workspaceID: string) => { "use server" @@ -21,7 +19,6 @@ const getUserEmail = query(async (workspaceID: string) => { export default function WorkspaceLayout(props: RouteSectionProps) { const params = useParams() const userEmail = createAsync(() => getUserEmail(params.id)) - const sessionInfo = createAsync(() => querySessionInfo(params.id)) return (
@@ -29,9 +26,7 @@ export default function WorkspaceLayout(props: RouteSectionProps) { - - - +
diff --git a/packages/console/function/src/auth.ts b/packages/console/function/src/auth.ts index e991e8c22..4d3ca6591 100644 --- a/packages/console/function/src/auth.ts +++ b/packages/console/function/src/auth.ts @@ -1,3 +1,4 @@ +import type { KVNamespace } from "@cloudflare/workers-types" import { z } from "zod" import { issuer } from "@openauthjs/openauth" import type { Theme } from "@openauthjs/openauth/ui/theme" @@ -94,6 +95,7 @@ export default { // }), }, storage: CloudflareStorage({ + // @ts-ignore namespace: env.AuthStorage, }), subjects, diff --git a/packages/css/package.json b/packages/css/package.json index c281e28d5..c4c28f2de 100644 --- a/packages/css/package.json +++ b/packages/css/package.json @@ -1,13 +1,12 @@ { "name": "@opencode-ai/css", - "version": "0.15.0", + "version": "0.15.2", "type": "module", "exports": { ".": "./src/index.css", "./*": "./src/*" }, "scripts": { - "build": "bun run build.ts", "dev": "bun run dev.ts" } } diff --git a/packages/css/src/components/select.css b/packages/css/src/components/select.css index d7b4b589d..2403bfb26 100644 --- a/packages/css/src/components/select.css +++ b/packages/css/src/components/select.css @@ -1,20 +1,4 @@ [data-component="select"] { - display: inline-flex; - align-items: center; - gap: calc(var(--spacing) * 2); - border-style: solid; - border-width: 1px; - border-radius: var(--radius-md); - border-color: var(--color-smoke-4); - font-family: var(--font-sans); - font-size: var(--text-base); - line-height: var(--text-base--line-height); - font-weight: var(--font-weight-normal); - cursor: pointer; - transition: all 0.2s ease-in-out; - text-decoration: none; - user-select: none; - &:disabled { opacity: 0.5; cursor: not-allowed; @@ -28,38 +12,35 @@ [data-slot="section"] { font-size: var(--text-xs); line-height: var(--text-xs--line-height); - font-weight: var(--font-weight-normal); + font-weight: var(--font-weight-light); + text-transform: uppercase; + color: var(--text-default-text-weak); + opacity: 0.6; margin-top: calc(var(--spacing) * 3); margin-left: calc(var(--spacing) * 2); &:first-child { - margin-top: calc(var(--spacing) * 0); + margin-top: 0; } } [data-slot="item"] { - /* "relative flex cursor-pointer select-none items-center": true, */ - /* "rounded-sm px-2 py-0.5 text-xs outline-none text-text": true, */ - /* "transition-colors data-[disabled]:pointer-events-none": true, */ - /* "data-[highlighted]:bg-background-element data-[disabled]:opacity-50": true, */ position: relative; display: flex; align-items: center; - justify-content: center; - gap: calc(var(--spacing) * 2); - border-style: solid; - border-width: 1px; - border-radius: var(--radius-md); - font-family: var(--font-sans); - font-size: var(--text-base); - line-height: var(--text-base--line-height); - font-weight: var(--font-weight-normal); + padding: calc(var(--spacing) * 2) calc(var(--spacing) * 2); + border-radius: var(--radius-sm); + font-size: var(--text-xs); + line-height: var(--text-xs--line-height); + color: var(--text-default-text); cursor: pointer; - transition: all 0.2s ease-in-out; - text-decoration: none; + transition: + background-color 0.2s ease-in-out, + color 0.2s ease-in-out; + outline: none; user-select: none; &[data-highlighted] { - background-color: var(--color-background-element); + background-color: var(--surface-default-surface); } &[data-disabled] { @@ -67,16 +48,7 @@ opacity: 0.5; } - /* [data-slot="item-label"] { */ - /* font-size: var(--text-xs); */ - /* line-height: var(--text-xs--line-height); */ - /* font-weight: var(--font-weight-normal); */ - /* } */ - [data-slot="item-indicator"] { - /* display: flex; */ - /* align-items: center; */ - /* gap: calc(var(--spacing) * 1); */ margin-left: auto; } } @@ -88,46 +60,61 @@ white-space: nowrap; } [data-slot="icon"] { - /* "group size-fit shrink-0 text-text-muted transition-transform duration-100": true, */ width: fit-content; height: fit-content; flex-shrink: 0; + color: var(--text-default-text-weak); + transition: transform 0.1s ease-in-out; } } } [data-component="select-content"] { - /* "min-w-32 overflow-hidden rounded-md border border-border-subtle/40": true, */ - /* "bg-background-panel p-1 shadow-md z-50": true, */ - /* "data-[closed]:animate-out data-[closed]:fade-out-0 data-[closed]:zoom-out-95": true, */ - /* "data-[expanded]:animate-in data-[expanded]:fade-in-0 data-[expanded]:zoom-in-95": true, */ min-width: 8rem; overflow: hidden; border-radius: var(--radius-md); border-width: 1px; border-style: solid; - border-color: var(--color-smoke-4); - background-color: var(--color-smoke-2); + border-color: var(--border-default-border-weak); + background-color: var(--surface-raised-surface-raised); padding: calc(var(--spacing) * 1); + box-shadow: var(--shadow-md); z-index: 50; - /* &[data-closed] { */ - /* animation: fade-out-0 0.2s ease-out; */ - /* animation-fill-mode: forwards; */ - /* animation-delay: 0.2s; */ - /* opacity: 0; */ - /* } */ - /* &[data-expanded] { */ - /* animation: fade-in-0 0.2s ease-out; */ - /* animation-fill-mode: forwards; */ - /* animation-delay: 0.2s; */ - /* opacity: 1; */ - /* } */ + &[data-closed] { + animation: select-close 0.15s ease-out; + } + + &[data-expanded] { + animation: select-open 0.15s ease-out; + } + [data-slot="list"] { - /* overflow-y-auto max-h-48 whitespace-nowrap overflow-x-hidden */ overflow-y: auto; max-height: 12rem; white-space: nowrap; overflow-x: hidden; } } + +@keyframes select-open { + from { + opacity: 0; + transform: scale(0.95); + } + to { + opacity: 1; + transform: scale(1); + } +} + +@keyframes select-close { + from { + opacity: 1; + transform: scale(1); + } + to { + opacity: 0; + transform: scale(0.95); + } +} diff --git a/packages/css/src/components/tabs.css b/packages/css/src/components/tabs.css new file mode 100644 index 000000000..3a70b4867 --- /dev/null +++ b/packages/css/src/components/tabs.css @@ -0,0 +1,98 @@ +[data-component="tabs"] { + display: flex; + flex-direction: column; + height: 100%; + + & [data-slot="list"] { + position: relative; + display: flex; + align-items: center; + background-color: var(--surface-default-surface); + overflow-x: auto; + + /* Hide scrollbar */ + scrollbar-width: none; + -ms-overflow-style: none; + + &::-webkit-scrollbar { + display: none; + } + + /* Divider between tabs */ + & > [data-slot="trigger"]:not(:first-child) { + border-left: 1px solid var(--border-default-border-weak); + } + + /* After element to fill remaining space */ + &::after { + content: ""; + display: block; + flex-grow: 1; + height: calc(var(--spacing) * 8); + border-left: 1px solid var(--border-default-border-weak); + border-bottom: 1px solid var(--border-default-border-weak); + } + + &:empty::after { + border-left: none; + } + } + + & [data-slot="trigger"] { + position: relative; + padding: 0 calc(var(--spacing) * 3); + height: calc(var(--spacing) * 8); + display: flex; + align-items: center; + font-size: var(--text-sm); + font-weight: var(--font-weight-medium); + color: var(--text-default-text-weak); + cursor: pointer; + white-space: nowrap; + flex-shrink: 0; + border-bottom: 1px solid var(--border-default-border-weak); + background-color: transparent; + transition: + background-color 0.15s ease, + color 0.15s ease; + + &:disabled { + pointer-events: none; + opacity: 0.5; + } + + &:focus-visible { + outline: none; + box-shadow: 0 0 0 2px var(--border-default-border-focus); + } + + &[data-selected] { + color: var(--text-default-text); + background-color: var(--surface-panel-surface); + border-bottom-color: transparent; + } + + &:hover:not(:disabled):not([data-selected]) { + color: var(--text-default-text); + } + } + + & [data-slot="content"] { + background-color: var(--surface-panel-surface); + overflow-y: auto; + flex: 1; + + /* Hide scrollbar */ + scrollbar-width: none; + -ms-overflow-style: none; + + &::-webkit-scrollbar { + display: none; + } + + &:focus-visible { + outline: none; + box-shadow: 0 0 0 2px var(--border-default-border-focus); + } + } +} diff --git a/packages/css/src/index.css b/packages/css/src/index.css index 731fc6f3c..1ac357fe1 100644 --- a/packages/css/src/index.css +++ b/packages/css/src/index.css @@ -8,5 +8,6 @@ @import "./components/button.css" layer(components); @import "./components/icon.css" layer(components); @import "./components/select.css" layer(components); +@import "./components/tabs.css" layer(components); @import "./utilities.css" layer(utilities); diff --git a/packages/desktop/src/pages/index.tsx b/packages/desktop/src/pages/index.tsx index 54f6ff83b..d520c8643 100644 --- a/packages/desktop/src/pages/index.tsx +++ b/packages/desktop/src/pages/index.tsx @@ -213,11 +213,22 @@ export default function Page() { }) } + const plus = ( + setStore("fileSelectOpen", true)} + > + + + ) + return (
-
-
-
+
+
+
@@ -256,92 +267,15 @@ export default function Page() { -
-
- m.role === "user") ?? []} - label={(m) => sync.data.part[m.id].find((p) => p.type === "text")!.text} - class="bg-transparent! max-w-48 pl-0! text-text-muted!" - /> - - -
-
- -
- setStore("fileSelectOpen", true)} - > - - - - - {(file) => ( - props.onTabClick(props.file)} - > -
- - {getFilename(file.path)} -
-
- )} -
-
-
- - {(file) => ( - - - - )} - -
-
+
setStore("modelSelectOpen", true)} onInputRefChange={(element: HTMLTextAreaElement | undefined) => { inputRef = element ?? undefined }} /> -
diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 310847c01..ff4402c4a 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -31,8 +31,13 @@ "@types/yargs": "17.0.33", "typescript": "catalog:", "vscode-languageserver-types": "3.17.5", +<<<<<<< HEAD "why-is-node-running": "3.2.2", "zod-to-json-schema": "3.24.5" +======= + "zod-to-json-schema": "3.24.5", + "@opencode-ai/script": "workspace:*" +>>>>>>> dev }, "dependencies": { "@clack/prompts": "1.0.0-alpha.1", diff --git a/packages/opencode/script/build.ts b/packages/opencode/script/build.ts index a5edbeb3a..e6c234e6b 100755 --- a/packages/opencode/script/build.ts +++ b/packages/opencode/script/build.ts @@ -8,6 +8,7 @@ const dir = new URL("..", import.meta.url).pathname process.chdir(dir) import pkg from "../package.json" +import { Script } from "@opencode-ai/script" const singleFlag = process.argv.includes("--single") @@ -28,7 +29,6 @@ const targets = singleFlag await $`rm -rf dist` const binaries: Record = {} -const version = process.env["OPENCODE_VERSION"] ?? "dev" for (const [os, arch] of targets) { console.log(`building ${os}-${arch}`) const name = `${pkg.name}-${os}-${arch}` @@ -51,7 +51,7 @@ for (const [os, arch] of targets) { compile: { target: `bun-${os}-${arch}` as any, outfile: `dist/${name}/bin/opencode`, - execArgv: [`--user-agent=opencode/${version}`, `--env-file=""`, `--`], + execArgv: [`--user-agent=opencode/${Script.version}`, `--env-file=""`, `--`], windows: {}, }, entrypoints: [ @@ -60,7 +60,7 @@ for (const [os, arch] of targets) { "./src/cli/cmd/tui/worker.ts", ], define: { - OPENCODE_VERSION: `'${version}'`, + OPENCODE_VERSION: `'${Script.version}'`, OTUI_TREE_SITTER_WORKER_PATH: "/$bunfs/root/../../node_modules/@opentui/core/parser.worker.js", }, }) @@ -70,7 +70,7 @@ for (const [os, arch] of targets) { JSON.stringify( { name, - version, + version: Script.version, os: [os === "windows" ? "win32" : os], cpu: [arch], }, @@ -78,7 +78,7 @@ for (const [os, arch] of targets) { 2, ), ) - binaries[name] = version + binaries[name] = Script.version } export { binaries } diff --git a/packages/opencode/script/publish.ts b/packages/opencode/script/publish.ts index 948dcf252..e58956350 100755 --- a/packages/opencode/script/publish.ts +++ b/packages/opencode/script/publish.ts @@ -1,20 +1,10 @@ #!/usr/bin/env bun +import { $ } from "bun" +import pkg from "../package.json" +import { Script } from "@opencode-ai/script" + const dir = new URL("..", import.meta.url).pathname process.chdir(dir) -import { $ } from "bun" - -import pkg from "../package.json" - -const snapshot = process.env["OPENCODE_SNAPSHOT"] === "true" -let version = process.env["OPENCODE_VERSION"] -const tag = process.env["OPENCODE_TAG"] ?? (snapshot ? "snapshot" : "latest") -if (!version && snapshot) { - version = `0.0.0-${tag}-${new Date().toISOString().slice(0, 16).replace(/[-:T]/g, "")}` - process.env["OPENCODE_VERSION"] = version -} -if (!version) throw new Error("OPENCODE_VERSION is required") - -console.log(`publishing ${version}`) const { binaries } = await import("./build.ts") { @@ -38,7 +28,7 @@ await Bun.file(`./dist/${pkg.name}/package.json`).write( preinstall: "node ./preinstall.mjs", postinstall: "node ./postinstall.mjs", }, - version, + version: Script.version, optionalDependencies: binaries, }, null, @@ -46,11 +36,11 @@ await Bun.file(`./dist/${pkg.name}/package.json`).write( ), ) for (const [name] of Object.entries(binaries)) { - await $`cd dist/${name} && chmod 777 -R . && bun publish --access public --tag ${tag}` + await $`cd dist/${name} && chmod 777 -R . && bun publish --access public --tag ${Script.tag}` } -await $`cd ./dist/${pkg.name} && bun publish --access public --tag ${tag}` +await $`cd ./dist/${pkg.name} && bun publish --access public --tag ${Script.tag}` -if (!snapshot) { +if (!Script.preview) { for (const key of Object.keys(binaries)) { await $`cd dist/${key}/bin && zip -r ../../${key}.zip *` } @@ -67,7 +57,7 @@ if (!snapshot) { "# Maintainer: adam", "", "pkgname='opencode-bin'", - `pkgver=${version.split("-")[0]}`, + `pkgver=${Script.version.split("-")[0]}`, "options=('!debug' '!strip')", "pkgrel=1", "pkgdesc='The AI coding agent built for the terminal.'", @@ -78,10 +68,10 @@ if (!snapshot) { "conflicts=('opencode')", "depends=('fzf' 'ripgrep')", "", - `source_aarch64=("\${pkgname}_\${pkgver}_aarch64.zip::https://github.com/sst/opencode/releases/download/v${version}/opencode-linux-arm64.zip")`, + `source_aarch64=("\${pkgname}_\${pkgver}_aarch64.zip::https://github.com/sst/opencode/releases/download/v${Script.version}/opencode-linux-arm64.zip")`, `sha256sums_aarch64=('${arm64Sha}')`, "", - `source_x86_64=("\${pkgname}_\${pkgver}_x86_64.zip::https://github.com/sst/opencode/releases/download/v${version}/opencode-linux-x64.zip")`, + `source_x86_64=("\${pkgname}_\${pkgver}_x86_64.zip::https://github.com/sst/opencode/releases/download/v${Script.version}/opencode-linux-x64.zip")`, `sha256sums_x86_64=('${x64Sha}')`, "", "package() {", @@ -96,7 +86,7 @@ if (!snapshot) { "# Maintainer: adam", "", "pkgname='opencode'", - `pkgver=${version.split("-")[0]}`, + `pkgver=${Script.version.split("-")[0]}`, "options=('!debug' '!strip')", "pkgrel=1", "pkgdesc='The AI coding agent built for the terminal.'", @@ -108,7 +98,7 @@ if (!snapshot) { "depends=('fzf' 'ripgrep')", "makedepends=('git' 'bun-bin' 'go')", "", - `source=("opencode-\${pkgver}.tar.gz::https://github.com/sst/opencode/archive/v${version}.tar.gz")`, + `source=("opencode-\${pkgver}.tar.gz::https://github.com/sst/opencode/archive/v${Script.version}.tar.gz")`, `sha256sums=('SKIP')`, "", "build() {", @@ -139,7 +129,7 @@ if (!snapshot) { await Bun.file(`./dist/aur-${pkg}/PKGBUILD`).write(pkgbuild) await $`cd ./dist/aur-${pkg} && makepkg --printsrcinfo > .SRCINFO` await $`cd ./dist/aur-${pkg} && git add PKGBUILD .SRCINFO` - await $`cd ./dist/aur-${pkg} && git commit -m "Update to v${version}"` + await $`cd ./dist/aur-${pkg} && git commit -m "Update to v${Script.version}"` await $`cd ./dist/aur-${pkg} && git push` break } catch (e) { @@ -157,11 +147,11 @@ if (!snapshot) { "class Opencode < Formula", ` desc "The AI coding agent built for the terminal."`, ` homepage "https://github.com/sst/opencode"`, - ` version "${version.split("-")[0]}"`, + ` version "${Script.version.split("-")[0]}"`, "", " on_macos do", " if Hardware::CPU.intel?", - ` url "https://github.com/sst/opencode/releases/download/v${version}/opencode-darwin-x64.zip"`, + ` url "https://github.com/sst/opencode/releases/download/v${Script.version}/opencode-darwin-x64.zip"`, ` sha256 "${macX64Sha}"`, "", " def install", @@ -169,7 +159,7 @@ if (!snapshot) { " end", " end", " if Hardware::CPU.arm?", - ` url "https://github.com/sst/opencode/releases/download/v${version}/opencode-darwin-arm64.zip"`, + ` url "https://github.com/sst/opencode/releases/download/v${Script.version}/opencode-darwin-arm64.zip"`, ` sha256 "${macArm64Sha}"`, "", " def install", @@ -180,14 +170,14 @@ if (!snapshot) { "", " on_linux do", " if Hardware::CPU.intel? and Hardware::CPU.is_64_bit?", - ` url "https://github.com/sst/opencode/releases/download/v${version}/opencode-linux-x64.zip"`, + ` url "https://github.com/sst/opencode/releases/download/v${Script.version}/opencode-linux-x64.zip"`, ` sha256 "${x64Sha}"`, " def install", ' bin.install "opencode"', " end", " end", " if Hardware::CPU.arm? and Hardware::CPU.is_64_bit?", - ` url "https://github.com/sst/opencode/releases/download/v${version}/opencode-linux-arm64.zip"`, + ` url "https://github.com/sst/opencode/releases/download/v${Script.version}/opencode-linux-arm64.zip"`, ` sha256 "${arm64Sha}"`, " def install", ' bin.install "opencode"', @@ -203,6 +193,6 @@ if (!snapshot) { await $`git clone https://${process.env["GITHUB_TOKEN"]}@github.com/sst/homebrew-tap.git ./dist/homebrew-tap` await Bun.file("./dist/homebrew-tap/opencode.rb").write(homebrewFormula) await $`cd ./dist/homebrew-tap && git add opencode.rb` - await $`cd ./dist/homebrew-tap && git commit -m "Update to v${version}"` + await $`cd ./dist/homebrew-tap && git commit -m "Update to v${Script.version}"` await $`cd ./dist/homebrew-tap && git push` } diff --git a/packages/opencode/src/cli/cmd/upgrade.ts b/packages/opencode/src/cli/cmd/upgrade.ts index 8c1abdeab..65f3bab4d 100644 --- a/packages/opencode/src/cli/cmd/upgrade.ts +++ b/packages/opencode/src/cli/cmd/upgrade.ts @@ -27,9 +27,19 @@ export const UpgradeCommand = { const detectedMethod = await Installation.method() const method = (args.method as Installation.Method) ?? detectedMethod if (method === "unknown") { - prompts.log.error(`opencode is installed to ${process.execPath} and seems to be managed by a package manager`) - prompts.outro("Done") - return + prompts.log.error(`opencode is installed to ${process.execPath} and may be managed by a package manager`) + const install = await prompts.select({ + message: "Install anyways?", + options: [ + { label: "Yes", value: true }, + { label: "No", value: false }, + ], + initialValue: false, + }) + if (!install) { + prompts.outro("Done") + return + } } prompts.log.info("Using method: " + method) const target = args.target ? args.target.replace(/^v/, "") : await Installation.latest() diff --git a/packages/opencode/src/installation/index.ts b/packages/opencode/src/installation/index.ts index ab9c8093e..4ce231ae9 100644 --- a/packages/opencode/src/installation/index.ts +++ b/packages/opencode/src/installation/index.ts @@ -50,6 +50,7 @@ export namespace Installation { export async function method() { if (process.execPath.includes(path.join(".opencode", "bin"))) return "curl" + if (process.execPath.includes(path.join(".local", "bin"))) return "curl" const exec = process.execPath.toLowerCase() const checks = [ diff --git a/packages/script/package.json b/packages/script/package.json new file mode 100644 index 000000000..2791305f3 --- /dev/null +++ b/packages/script/package.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://json.schemastore.org/package", + "name": "@opencode-ai/script", + "devDependencies": { + "@types/bun": "catalog:" + }, + "exports": { + ".": "./src/index.ts" + } +} diff --git a/packages/script/src/index.ts b/packages/script/src/index.ts new file mode 100644 index 000000000..4237a76a2 --- /dev/null +++ b/packages/script/src/index.ts @@ -0,0 +1,35 @@ +import { $ } from "bun" + +if (process.versions.bun !== "1.3.0") { + throw new Error("This script requires bun@1.3.0") +} + +const TAG = process.env["OPENCODE_TAG"] ?? (await $`git branch --show-current`.text().then((x) => x.trim())) +const IS_PREVIEW = TAG !== "latest" +const VERSION = await (async () => { + if (IS_PREVIEW) return `0.0.0-${new Date().toISOString().slice(0, 16).replace(/[-:T]/g, "")}` + const version = await fetch("https://registry.npmjs.org/opencode-ai/latest") + .then((res) => { + if (!res.ok) throw new Error(res.statusText) + return res.json() + }) + .then((data: any) => data.version) + const [major, minor, patch] = version.split(".").map((x: string) => Number(x) || 0) + const t = process.env["OPENCODE_BUMP"]?.toLowerCase() + if (t === "major") return `${major + 1}.0.0` + if (t === "minor") return `${major}.${minor + 1}.0` + return `${major}.${minor}.${patch + 1}` +})() + +export const Script = { + get tag() { + return TAG + }, + get version() { + return VERSION + }, + get preview() { + return IS_PREVIEW + }, +} +console.log(`opencode script`, JSON.stringify(Script, null, 2)) diff --git a/packages/script/tsconfig.json b/packages/script/tsconfig.json new file mode 100644 index 000000000..00ef12546 --- /dev/null +++ b/packages/script/tsconfig.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@tsconfig/bun/tsconfig.json", + "compilerOptions": { + "lib": ["ESNext", "DOM", "DOM.Iterable"], + "noUncheckedIndexedAccess": false + } +} diff --git a/packages/ui/index.html b/packages/ui/index.html index b7f74e79d..7697a5f96 100644 --- a/packages/ui/index.html +++ b/packages/ui/index.html @@ -1,5 +1,5 @@ - + diff --git a/packages/ui/package.json b/packages/ui/package.json index 0e5d4c379..e9b453612 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "0.15.0", + "version": "0.15.2", "type": "module", "exports": { ".": "./src/components/index.ts", diff --git a/packages/ui/src/app.tsx b/packages/ui/src/app.tsx index be2ec357e..f42781543 100644 --- a/packages/ui/src/app.tsx +++ b/packages/ui/src/app.tsx @@ -1,66 +1,100 @@ import type { Component } from "solid-js" -import { Button } from "./components/button" -import { Select } from "./components" +import { Button, Select, Tabs } from "./components" import "@opencode-ai/css" import "./index.css" const App: Component = () => { + const Content = (props: { dark?: boolean }) => ( +
+

Buttons

+
+ + + + + + +
+

Select

+
+ + console.log(x)} placeholder="Select" /> -
-
-
-

Buttons

-
- - - - - - -
-

Select

-
-