mirror of
https://github.com/anomalyco/opencode.git
synced 2026-02-10 19:04:17 +00:00
Compare commits
23 Commits
models-end
...
github-v1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
80a853c869 | ||
|
|
cd664a189b | ||
|
|
849f488744 | ||
|
|
5ea1042ffb | ||
|
|
71d280d570 | ||
|
|
5cfb5fdd06 | ||
|
|
30969dc33e | ||
|
|
5f282c268d | ||
|
|
d3d6e7e275 | ||
|
|
a70c66eb3f | ||
|
|
60de810d9a | ||
|
|
95309c2149 | ||
|
|
e9e8d97b0d | ||
|
|
553316af2a | ||
|
|
f27ee4674a | ||
|
|
ad91f9143a | ||
|
|
b43a35b737 | ||
|
|
03803621db | ||
|
|
81326377f2 | ||
|
|
7ed6f690e9 | ||
|
|
1f3bf56640 | ||
|
|
bbc7bdb3fd | ||
|
|
a5c01a81ff |
15
.github/actions/setup-bun/action.yml
vendored
15
.github/actions/setup-bun/action.yml
vendored
@@ -3,20 +3,17 @@ description: "Setup Bun with caching and install dependencies"
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Mount Bun Cache
|
||||
uses: useblacksmith/stickydisk@v1
|
||||
with:
|
||||
key: ${{ github.repository }}-bun-cache
|
||||
path: ~/.bun
|
||||
|
||||
- name: Setup Bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version-file: package.json
|
||||
|
||||
- name: Cache ~/.bun
|
||||
id: cache-bun
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.bun
|
||||
key: ${{ runner.os }}-bun-${{ hashFiles('package.json') }}-${{ hashFiles('bun.lockb', 'bun.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-bun-${{ hashFiles('package.json') }}-
|
||||
|
||||
- name: Install dependencies
|
||||
run: bun install
|
||||
shell: bash
|
||||
|
||||
2
.github/workflows/beta.yml
vendored
2
.github/workflows/beta.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
45
.github/workflows/containers.yml
vendored
Normal file
45
.github/workflows/containers.yml
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
name: containers
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
paths:
|
||||
- packages/containers/**
|
||||
- .github/workflows/containers.yml
|
||||
- package.json
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
env:
|
||||
REGISTRY: ghcr.io/${{ github.repository_owner }}
|
||||
TAG: "24.04"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: ./.github/actions/setup-bun
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to GHCR
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push containers
|
||||
run: bun ./packages/containers/script/build.ts --push
|
||||
env:
|
||||
REGISTRY: ${{ env.REGISTRY }}
|
||||
TAG: ${{ env.TAG }}
|
||||
23
.github/workflows/publish.yml
vendored
23
.github/workflows/publish.yml
vendored
@@ -124,6 +124,15 @@ jobs:
|
||||
|
||||
- uses: ./.github/actions/setup-bun
|
||||
|
||||
- name: Cache apt packages
|
||||
if: contains(matrix.settings.host, 'ubuntu')
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: /var/cache/apt/archives
|
||||
key: ${{ runner.os }}-${{ matrix.settings.target }}-apt-${{ hashFiles('.github/workflows/publish.yml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-${{ matrix.settings.target }}-apt-
|
||||
|
||||
- name: install dependencies (ubuntu only)
|
||||
if: contains(matrix.settings.host, 'ubuntu')
|
||||
run: |
|
||||
@@ -145,7 +154,7 @@ jobs:
|
||||
cd packages/desktop
|
||||
bun ./scripts/prepare.ts
|
||||
env:
|
||||
OPENCODE_VERSION: ${{ needs.publish.outputs.version }}
|
||||
OPENCODE_VERSION: ${{ needs.version.outputs.version }}
|
||||
GITHUB_TOKEN: ${{ secrets.SST_GITHUB_TOKEN }}
|
||||
RUST_TARGET: ${{ matrix.settings.target }}
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
@@ -188,10 +197,12 @@ jobs:
|
||||
needs:
|
||||
- version
|
||||
- build-cli
|
||||
# - build-tauri
|
||||
- build-tauri
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: ./.github/actions/setup-bun
|
||||
|
||||
@@ -228,6 +239,14 @@ jobs:
|
||||
name: opencode-cli
|
||||
path: packages/opencode/dist
|
||||
|
||||
- name: Cache apt packages (AUR)
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: /var/cache/apt/archives
|
||||
key: ${{ runner.os }}-apt-aur-${{ hashFiles('.github/workflows/publish.yml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-apt-aur-
|
||||
|
||||
- name: Setup SSH for AUR
|
||||
run: |
|
||||
sudo apt-get update
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
- To regenerate the JavaScript SDK, run `./packages/sdk/js/script/build.ts`.
|
||||
- ALWAYS USE PARALLEL TOOLS WHEN APPLICABLE.
|
||||
- The default branch in this repo is `dev`.
|
||||
- Prefer automation: execute requested actions without confirmation unless blocked by missing info or safety/irreversibility.
|
||||
|
||||
## Style Guide
|
||||
|
||||
|
||||
30
bun.lock
30
bun.lock
@@ -23,7 +23,7 @@
|
||||
},
|
||||
"packages/app": {
|
||||
"name": "@opencode-ai/app",
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"dependencies": {
|
||||
"@kobalte/core": "catalog:",
|
||||
"@opencode-ai/sdk": "workspace:*",
|
||||
@@ -73,7 +73,7 @@
|
||||
},
|
||||
"packages/console/app": {
|
||||
"name": "@opencode-ai/console-app",
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"dependencies": {
|
||||
"@cloudflare/vite-plugin": "1.15.2",
|
||||
"@ibm/plex": "6.4.1",
|
||||
@@ -107,7 +107,7 @@
|
||||
},
|
||||
"packages/console/core": {
|
||||
"name": "@opencode-ai/console-core",
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-sts": "3.782.0",
|
||||
"@jsx-email/render": "1.1.1",
|
||||
@@ -134,7 +134,7 @@
|
||||
},
|
||||
"packages/console/function": {
|
||||
"name": "@opencode-ai/console-function",
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"dependencies": {
|
||||
"@ai-sdk/anthropic": "2.0.0",
|
||||
"@ai-sdk/openai": "2.0.2",
|
||||
@@ -158,7 +158,7 @@
|
||||
},
|
||||
"packages/console/mail": {
|
||||
"name": "@opencode-ai/console-mail",
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"dependencies": {
|
||||
"@jsx-email/all": "2.2.3",
|
||||
"@jsx-email/cli": "1.4.3",
|
||||
@@ -182,7 +182,7 @@
|
||||
},
|
||||
"packages/desktop": {
|
||||
"name": "@opencode-ai/desktop",
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"dependencies": {
|
||||
"@opencode-ai/app": "workspace:*",
|
||||
"@opencode-ai/ui": "workspace:*",
|
||||
@@ -213,7 +213,7 @@
|
||||
},
|
||||
"packages/enterprise": {
|
||||
"name": "@opencode-ai/enterprise",
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"dependencies": {
|
||||
"@opencode-ai/ui": "workspace:*",
|
||||
"@opencode-ai/util": "workspace:*",
|
||||
@@ -242,7 +242,7 @@
|
||||
},
|
||||
"packages/function": {
|
||||
"name": "@opencode-ai/function",
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"dependencies": {
|
||||
"@octokit/auth-app": "8.0.1",
|
||||
"@octokit/rest": "catalog:",
|
||||
@@ -258,7 +258,7 @@
|
||||
},
|
||||
"packages/opencode": {
|
||||
"name": "opencode",
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"bin": {
|
||||
"opencode": "./bin/opencode",
|
||||
},
|
||||
@@ -362,7 +362,7 @@
|
||||
},
|
||||
"packages/plugin": {
|
||||
"name": "@opencode-ai/plugin",
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"dependencies": {
|
||||
"@opencode-ai/sdk": "workspace:*",
|
||||
"zod": "catalog:",
|
||||
@@ -382,7 +382,7 @@
|
||||
},
|
||||
"packages/sdk/js": {
|
||||
"name": "@opencode-ai/sdk",
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"devDependencies": {
|
||||
"@hey-api/openapi-ts": "0.90.10",
|
||||
"@tsconfig/node22": "catalog:",
|
||||
@@ -393,7 +393,7 @@
|
||||
},
|
||||
"packages/slack": {
|
||||
"name": "@opencode-ai/slack",
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"dependencies": {
|
||||
"@opencode-ai/sdk": "workspace:*",
|
||||
"@slack/bolt": "^3.17.1",
|
||||
@@ -406,7 +406,7 @@
|
||||
},
|
||||
"packages/ui": {
|
||||
"name": "@opencode-ai/ui",
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"dependencies": {
|
||||
"@kobalte/core": "catalog:",
|
||||
"@opencode-ai/sdk": "workspace:*",
|
||||
@@ -448,7 +448,7 @@
|
||||
},
|
||||
"packages/util": {
|
||||
"name": "@opencode-ai/util",
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"dependencies": {
|
||||
"zod": "catalog:",
|
||||
},
|
||||
@@ -459,7 +459,7 @@
|
||||
},
|
||||
"packages/web": {
|
||||
"name": "@opencode-ai/web",
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"dependencies": {
|
||||
"@astrojs/cloudflare": "12.6.3",
|
||||
"@astrojs/markdown-remark": "6.3.1",
|
||||
|
||||
1052
github/index.ts
1052
github/index.ts
File diff suppressed because it is too large
Load Diff
25
packages/app/e2e/thinking-level.spec.ts
Normal file
25
packages/app/e2e/thinking-level.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { test, expect } from "./fixtures"
|
||||
import { modelVariantCycleSelector } from "./utils"
|
||||
|
||||
test("smoke model variant cycle updates label", async ({ page, gotoSession }) => {
|
||||
await gotoSession()
|
||||
|
||||
await page.addStyleTag({
|
||||
content: `${modelVariantCycleSelector} { display: inline-block !important; }`,
|
||||
})
|
||||
|
||||
const button = page.locator(modelVariantCycleSelector)
|
||||
const exists = (await button.count()) > 0
|
||||
test.skip(!exists, "current model has no variants")
|
||||
if (!exists) return
|
||||
|
||||
await expect(button).toBeVisible()
|
||||
|
||||
const before = (await button.innerText()).trim()
|
||||
await button.click()
|
||||
await expect(button).not.toHaveText(before)
|
||||
|
||||
const after = (await button.innerText()).trim()
|
||||
await button.click()
|
||||
await expect(button).not.toHaveText(after)
|
||||
})
|
||||
@@ -12,6 +12,7 @@ export const terminalToggleKey = "Control+Backquote"
|
||||
|
||||
export const promptSelector = '[data-component="prompt-input"]'
|
||||
export const terminalSelector = '[data-component="terminal"]'
|
||||
export const modelVariantCycleSelector = '[data-action="model-variant-cycle"]'
|
||||
|
||||
export function createSdk(directory?: string) {
|
||||
return createOpencodeClient({ baseUrl: serverUrl, directory, throwOnError: true })
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/app",
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"description": "",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
|
||||
@@ -34,11 +34,14 @@ export const DialogSelectModelUnpaid: Component = () => {
|
||||
})
|
||||
|
||||
return (
|
||||
<Dialog title={language.t("dialog.model.select.title")}>
|
||||
<div class="flex flex-col gap-3 px-2.5 flex-1 min-h-0">
|
||||
<Dialog
|
||||
title={language.t("dialog.model.select.title")}
|
||||
class="overflow-y-auto [&_[data-slot=dialog-body]]:overflow-visible [&_[data-slot=dialog-body]]:flex-none"
|
||||
>
|
||||
<div class="flex flex-col gap-3 px-2.5">
|
||||
<div class="text-14-medium text-text-base px-2.5">{language.t("dialog.model.unpaid.freeModels.title")}</div>
|
||||
<List
|
||||
class="flex-1 min-h-0 [&_[data-slot=list-scroll]]:flex-1 [&_[data-slot=list-scroll]]:min-h-0"
|
||||
class="[&_[data-slot=list-scroll]]:overflow-visible"
|
||||
ref={(ref) => (listRef = ref)}
|
||||
items={local.model.list}
|
||||
current={local.model.current()}
|
||||
@@ -76,8 +79,6 @@ export const DialogSelectModelUnpaid: Component = () => {
|
||||
</div>
|
||||
)}
|
||||
</List>
|
||||
<div />
|
||||
<div />
|
||||
</div>
|
||||
<div class="px-1.5 pb-1.5">
|
||||
<div class="w-full rounded-sm border border-border-weak-base bg-surface-raised-base">
|
||||
|
||||
@@ -1953,6 +1953,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
|
||||
keybind={command.keybind("model.variant.cycle")}
|
||||
>
|
||||
<Button
|
||||
data-action="model-variant-cycle"
|
||||
variant="ghost"
|
||||
class="text-text-base _hidden group-hover/prompt-input:inline-block capitalize text-12-regular"
|
||||
onClick={() => local.model.variant.cycle()}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/console-app",
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/console-core",
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/console-function",
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/console-mail",
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"dependencies": {
|
||||
"@jsx-email/all": "2.2.3",
|
||||
"@jsx-email/cli": "1.4.3",
|
||||
|
||||
38
packages/containers/README.md
Normal file
38
packages/containers/README.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# CI containers
|
||||
|
||||
Prebuilt images intended to speed up GitHub Actions jobs by baking in
|
||||
large, slow-to-install dependencies. These are designed for Linux jobs
|
||||
that can use `job.container` in workflows.
|
||||
|
||||
Images
|
||||
|
||||
- `base`: Ubuntu 24.04 with common build tools and utilities
|
||||
- `bun-node`: `base` plus Bun and Node.js 24
|
||||
- `rust`: `bun-node` plus Rust (stable, minimal profile)
|
||||
- `tauri-linux`: `rust` plus Tauri Linux build dependencies
|
||||
- `publish`: `bun-node` plus Docker CLI and AUR tooling
|
||||
|
||||
Build
|
||||
|
||||
```
|
||||
REGISTRY=ghcr.io/anomalyco TAG=24.04 bun ./packages/containers/script/build.ts
|
||||
REGISTRY=ghcr.io/anomalyco TAG=24.04 bun ./packages/containers/script/build.ts --push
|
||||
```
|
||||
|
||||
Workflow usage
|
||||
|
||||
```
|
||||
jobs:
|
||||
build-cli:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: ghcr.io/anomalyco/build/bun-node:24.04
|
||||
```
|
||||
|
||||
Notes
|
||||
|
||||
- These images only help Linux jobs. macOS and Windows jobs cannot run
|
||||
inside Linux containers.
|
||||
- `--push` publishes multi-arch (amd64 + arm64) images using Buildx.
|
||||
- If a job uses Docker Buildx, the container needs access to the host
|
||||
Docker daemon (or `docker-in-docker` with privileged mode).
|
||||
18
packages/containers/base/Dockerfile
Normal file
18
packages/containers/base/Dockerfile
Normal file
@@ -0,0 +1,18 @@
|
||||
FROM ubuntu:24.04
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
ca-certificates \
|
||||
curl \
|
||||
git \
|
||||
jq \
|
||||
openssh-client \
|
||||
pkg-config \
|
||||
python3 \
|
||||
unzip \
|
||||
xz-utils \
|
||||
zip \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
24
packages/containers/bun-node/Dockerfile
Normal file
24
packages/containers/bun-node/Dockerfile
Normal file
@@ -0,0 +1,24 @@
|
||||
ARG REGISTRY=ghcr.io/anomalyco
|
||||
FROM ${REGISTRY}/build/base:24.04
|
||||
|
||||
SHELL ["/bin/bash", "-lc"]
|
||||
|
||||
ARG NODE_VERSION=24.4.0
|
||||
ARG BUN_VERSION=1.3.5
|
||||
|
||||
ENV BUN_INSTALL=/opt/bun
|
||||
ENV PATH=/opt/bun/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||
|
||||
RUN set -euo pipefail; \
|
||||
arch=$(uname -m); \
|
||||
node_arch=x64; \
|
||||
if [ "$arch" = "aarch64" ]; then node_arch=arm64; fi; \
|
||||
curl -fsSL "https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-${node_arch}.tar.xz" \
|
||||
| tar -xJf - -C /usr/local --strip-components=1; \
|
||||
corepack enable
|
||||
|
||||
RUN set -euo pipefail; \
|
||||
curl -fsSL https://bun.sh/install | bash -s -- "bun-v${BUN_VERSION}"; \
|
||||
bun --version; \
|
||||
node --version; \
|
||||
npm --version
|
||||
10
packages/containers/publish/Dockerfile
Normal file
10
packages/containers/publish/Dockerfile
Normal file
@@ -0,0 +1,10 @@
|
||||
ARG REGISTRY=ghcr.io/anomalyco
|
||||
FROM ${REGISTRY}/build/bun-node:24.04
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
docker.io \
|
||||
pacman-package-manager \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
13
packages/containers/rust/Dockerfile
Normal file
13
packages/containers/rust/Dockerfile
Normal file
@@ -0,0 +1,13 @@
|
||||
ARG REGISTRY=ghcr.io/anomalyco
|
||||
FROM ${REGISTRY}/build/bun-node:24.04
|
||||
|
||||
ARG RUST_TOOLCHAIN=stable
|
||||
|
||||
ENV CARGO_HOME=/opt/cargo
|
||||
ENV RUSTUP_HOME=/opt/rustup
|
||||
ENV PATH=/opt/cargo/bin:/opt/bun/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||
|
||||
RUN set -euo pipefail; \
|
||||
curl -fsSL https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain "${RUST_TOOLCHAIN}"; \
|
||||
rustc --version; \
|
||||
cargo --version
|
||||
77
packages/containers/script/build.ts
Normal file
77
packages/containers/script/build.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env bun
|
||||
|
||||
import { $ } from "bun"
|
||||
import path from "path"
|
||||
import { fileURLToPath } from "url"
|
||||
|
||||
const rootDir = fileURLToPath(new URL("../../..", import.meta.url))
|
||||
process.chdir(rootDir)
|
||||
|
||||
const reg = process.env.REGISTRY ?? "ghcr.io/anomalyco"
|
||||
const tag = process.env.TAG ?? "24.04"
|
||||
const push = process.argv.includes("--push") || process.env.PUSH === "1"
|
||||
|
||||
const root = path.join(rootDir, "package.json")
|
||||
const pkg = await Bun.file(root).json()
|
||||
const manager = pkg.packageManager ?? ""
|
||||
const bun = manager.startsWith("bun@") ? manager.slice(4) : ""
|
||||
if (!bun) throw new Error("packageManager must be bun@<version>")
|
||||
|
||||
const images = ["base", "bun-node", "rust", "tauri-linux", "publish"]
|
||||
|
||||
const setup = async () => {
|
||||
if (!push) return
|
||||
const list = await $`docker buildx ls`.text()
|
||||
if (list.includes("opencode")) {
|
||||
await $`docker buildx use opencode`
|
||||
return
|
||||
}
|
||||
await $`docker buildx create --name opencode --use`
|
||||
}
|
||||
|
||||
await setup()
|
||||
|
||||
const platform = "linux/amd64,linux/arm64"
|
||||
|
||||
for (const name of images) {
|
||||
const image = `${reg}/build/${name}:${tag}`
|
||||
const file = `packages/containers/${name}/Dockerfile`
|
||||
if (name === "base") {
|
||||
if (push) {
|
||||
console.log(`docker buildx build --platform ${platform} -f ${file} -t ${image} --push .`)
|
||||
await $`docker buildx build --platform ${platform} -f ${file} -t ${image} --push .`
|
||||
}
|
||||
if (!push) {
|
||||
console.log(`docker build -f ${file} -t ${image} .`)
|
||||
await $`docker build -f ${file} -t ${image} .`
|
||||
}
|
||||
}
|
||||
if (name === "bun-node") {
|
||||
if (push) {
|
||||
console.log(
|
||||
`docker buildx build --platform ${platform} -f ${file} -t ${image} --build-arg REGISTRY=${reg} --build-arg BUN_VERSION=${bun} --push .`,
|
||||
)
|
||||
await $`docker buildx build --platform ${platform} -f ${file} -t ${image} --build-arg REGISTRY=${reg} --build-arg BUN_VERSION=${bun} --push .`
|
||||
}
|
||||
if (!push) {
|
||||
console.log(`docker build -f ${file} -t ${image} --build-arg REGISTRY=${reg} --build-arg BUN_VERSION=${bun} .`)
|
||||
await $`docker build -f ${file} -t ${image} --build-arg REGISTRY=${reg} --build-arg BUN_VERSION=${bun} .`
|
||||
}
|
||||
}
|
||||
if (name !== "base" && name !== "bun-node") {
|
||||
if (push) {
|
||||
console.log(
|
||||
`docker buildx build --platform ${platform} -f ${file} -t ${image} --build-arg REGISTRY=${reg} --push .`,
|
||||
)
|
||||
await $`docker buildx build --platform ${platform} -f ${file} -t ${image} --build-arg REGISTRY=${reg} --push .`
|
||||
}
|
||||
if (!push) {
|
||||
console.log(`docker build -f ${file} -t ${image} --build-arg REGISTRY=${reg} .`)
|
||||
await $`docker build -f ${file} -t ${image} --build-arg REGISTRY=${reg} .`
|
||||
}
|
||||
}
|
||||
|
||||
if (push) {
|
||||
console.log(`pushed ${image}`)
|
||||
}
|
||||
}
|
||||
12
packages/containers/tauri-linux/Dockerfile
Normal file
12
packages/containers/tauri-linux/Dockerfile
Normal file
@@ -0,0 +1,12 @@
|
||||
ARG REGISTRY=ghcr.io/anomalyco
|
||||
FROM ${REGISTRY}/build/rust:24.04
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
libappindicator3-dev \
|
||||
libwebkit2gtk-4.1-dev \
|
||||
librsvg2-dev \
|
||||
patchelf \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
8
packages/containers/tsconfig.json
Normal file
8
packages/containers/tsconfig.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"extends": "@tsconfig/bun/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"lib": ["ESNext", "DOM", "DOM.Iterable"],
|
||||
"noUncheckedIndexedAccess": false
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@opencode-ai/desktop",
|
||||
"private": true,
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
#!/usr/bin/env bun
|
||||
import { $ } from "bun"
|
||||
|
||||
import { Script } from "@opencode-ai/script"
|
||||
import { copyBinaryToSidecarFolder, getCurrentSidecar, windowsify } from "./utils"
|
||||
|
||||
const pkg = await Bun.file("./package.json").json()
|
||||
pkg.version = Script.version
|
||||
await Bun.write("./package.json", JSON.stringify(pkg, null, 2) + "\n")
|
||||
console.log(`Updated package.json version to ${Script.version}`)
|
||||
|
||||
const sidecarConfig = getCurrentSidecar()
|
||||
|
||||
const dir = "src-tauri/target/opencode-binaries"
|
||||
|
||||
8
packages/desktop/src-tauri/Cargo.lock
generated
8
packages/desktop/src-tauri/Cargo.lock
generated
@@ -4914,9 +4914,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-fs"
|
||||
version = "2.4.4"
|
||||
version = "2.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47df422695255ecbe7bac7012440eddaeefd026656171eac9559f5243d3230d9"
|
||||
checksum = "ed390cc669f937afeb8b28032ce837bac8ea023d975a2e207375ec05afaf1804"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"dunce",
|
||||
@@ -4936,9 +4936,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-http"
|
||||
version = "2.5.4"
|
||||
version = "2.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c00685aceab12643cf024f712ab0448ba8fcadf86f2391d49d2e5aa732aacc70"
|
||||
checksum = "68bef611ccbfbce67c813959c11b23c1c084d201aa94222de9eba5f9edc3f897"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"cookie_store",
|
||||
|
||||
@@ -28,7 +28,7 @@ tauri-plugin-process = "2"
|
||||
tauri-plugin-store = "2"
|
||||
tauri-plugin-window-state = "2"
|
||||
tauri-plugin-clipboard-manager = "2"
|
||||
tauri-plugin-http = "2"
|
||||
tauri-plugin-http = "2.5.6"
|
||||
tauri-plugin-notification = "2"
|
||||
tauri-plugin-single-instance = { version = "2", features = ["deep-link"] }
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/enterprise",
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
id = "opencode"
|
||||
name = "OpenCode"
|
||||
description = "The open source coding agent."
|
||||
version = "0.0.0-ci-202601291718"
|
||||
version = "1.1.43"
|
||||
schema_version = 1
|
||||
authors = ["Anomaly"]
|
||||
repository = "https://github.com/anomalyco/opencode"
|
||||
@@ -11,26 +11,26 @@ name = "OpenCode"
|
||||
icon = "./icons/opencode.svg"
|
||||
|
||||
[agent_servers.opencode.targets.darwin-aarch64]
|
||||
archive = "https://github.com/anomalyco/opencode/releases/download/v0.0.0-ci-202601291718/opencode-darwin-arm64.zip"
|
||||
archive = "https://github.com/anomalyco/opencode/releases/download/v1.1.43/opencode-darwin-arm64.zip"
|
||||
cmd = "./opencode"
|
||||
args = ["acp"]
|
||||
|
||||
[agent_servers.opencode.targets.darwin-x86_64]
|
||||
archive = "https://github.com/anomalyco/opencode/releases/download/v0.0.0-ci-202601291718/opencode-darwin-x64.zip"
|
||||
archive = "https://github.com/anomalyco/opencode/releases/download/v1.1.43/opencode-darwin-x64.zip"
|
||||
cmd = "./opencode"
|
||||
args = ["acp"]
|
||||
|
||||
[agent_servers.opencode.targets.linux-aarch64]
|
||||
archive = "https://github.com/anomalyco/opencode/releases/download/v0.0.0-ci-202601291718/opencode-linux-arm64.tar.gz"
|
||||
archive = "https://github.com/anomalyco/opencode/releases/download/v1.1.43/opencode-linux-arm64.tar.gz"
|
||||
cmd = "./opencode"
|
||||
args = ["acp"]
|
||||
|
||||
[agent_servers.opencode.targets.linux-x86_64]
|
||||
archive = "https://github.com/anomalyco/opencode/releases/download/v0.0.0-ci-202601291718/opencode-linux-x64.tar.gz"
|
||||
archive = "https://github.com/anomalyco/opencode/releases/download/v1.1.43/opencode-linux-x64.tar.gz"
|
||||
cmd = "./opencode"
|
||||
args = ["acp"]
|
||||
|
||||
[agent_servers.opencode.targets.windows-x86_64]
|
||||
archive = "https://github.com/anomalyco/opencode/releases/download/v0.0.0-ci-202601291718/opencode-windows-x64.zip"
|
||||
archive = "https://github.com/anomalyco/opencode/releases/download/v1.1.43/opencode-windows-x64.zip"
|
||||
cmd = "./opencode.exe"
|
||||
args = ["acp"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/function",
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"name": "opencode",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
import z from "zod"
|
||||
import { iife } from "@/util/iife"
|
||||
import { Log } from "@/util/log"
|
||||
import { Provider } from "./provider"
|
||||
|
||||
export namespace ProviderModelDetection {
|
||||
export async function detect(provider: Provider.Info): Promise<string[] | undefined> {
|
||||
const log = Log.create({ service: "provider.model-detection" })
|
||||
|
||||
const model = Object.values(provider.models)[0]
|
||||
const providerNPM = model?.api?.npm ?? "@ai-sdk/openai-compatible"
|
||||
const providerBaseURL = provider.options["baseURL"] ?? model?.api?.url ?? ""
|
||||
|
||||
const detectedModels = await iife(async () => {
|
||||
try {
|
||||
if (providerNPM === "@ai-sdk/openai-compatible" && providerBaseURL) {
|
||||
log.info("using OpenAI-compatible method", { providerID: provider.id })
|
||||
return await ProviderModelDetection.OpenAICompatible.listModels(providerBaseURL, provider)
|
||||
}
|
||||
} catch (error) {
|
||||
log.warn(`failed to detect models\n${error}`, { providerID: provider.id })
|
||||
}
|
||||
})
|
||||
|
||||
if (!detectedModels || detectedModels.length === 0) return
|
||||
|
||||
log.info("detected models", { providerID: provider.id, count: detectedModels.length })
|
||||
return detectedModels
|
||||
}
|
||||
}
|
||||
|
||||
export namespace ProviderModelDetection.OpenAICompatible {
|
||||
const OpenAICompatibleResponse = z.object({
|
||||
object: z.string(),
|
||||
data: z.array(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
object: z.string().optional(),
|
||||
created: z.number().optional(),
|
||||
owned_by: z.string().optional(),
|
||||
}),
|
||||
),
|
||||
})
|
||||
type OpenAICompatibleResponse = z.infer<typeof OpenAICompatibleResponse>
|
||||
|
||||
export async function listModels(baseURL: string, provider: Provider.Info): Promise<string[]> {
|
||||
const fetchFn = provider.options["fetch"] ?? fetch
|
||||
const apiKey = provider.options["apiKey"] ?? provider.key ?? ""
|
||||
const headers = new Headers()
|
||||
if (apiKey) headers.append("Authorization", `Bearer ${apiKey}`)
|
||||
|
||||
const res = await fetchFn(`${baseURL}/models`, {
|
||||
headers,
|
||||
signal: AbortSignal.timeout(3 * 1000),
|
||||
})
|
||||
if (!res.ok) throw new Error(`bad http status ${res.status}`)
|
||||
const parsed = OpenAICompatibleResponse.parse(await res.json())
|
||||
|
||||
return parsed.data
|
||||
.filter((model) => model.id && !model.id.includes("embedding") && !model.id.includes("embed"))
|
||||
.map((model) => model.id)
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import { BunProc } from "../bun"
|
||||
import { Plugin } from "../plugin"
|
||||
import { ModelsDev } from "./models"
|
||||
import { NamedError } from "@opencode-ai/util/error"
|
||||
import { Auth, OAUTH_DUMMY_KEY } from "../auth"
|
||||
import { Auth } from "../auth"
|
||||
import { Env } from "../env"
|
||||
import { Instance } from "../project/instance"
|
||||
import { Flag } from "../flag/flag"
|
||||
@@ -667,52 +667,11 @@ export namespace Provider {
|
||||
source: "custom",
|
||||
name: provider.name,
|
||||
env: provider.env ?? [],
|
||||
options: {
|
||||
...(provider.api && { baseURL: provider.api }),
|
||||
},
|
||||
options: {},
|
||||
models: mapValues(provider.models, (model) => fromModelsDevModel(provider, model)),
|
||||
}
|
||||
}
|
||||
|
||||
const ModelsList = z.object({
|
||||
object: z.string(),
|
||||
data: z.array(
|
||||
z
|
||||
.object({
|
||||
id: z.string(),
|
||||
object: z.string().optional(),
|
||||
created: z.number().optional(),
|
||||
owned_by: z.string().optional(),
|
||||
})
|
||||
.catchall(z.any()),
|
||||
),
|
||||
})
|
||||
type ModelsList = z.infer<typeof ModelsList>
|
||||
|
||||
async function listModels(provider: Info) {
|
||||
const baseURL = provider.options["baseURL"]
|
||||
const fetchFn = (provider.options["fetch"] as typeof fetch) ?? fetch
|
||||
const apiKey = provider.options["apiKey"] ?? provider.key ?? ""
|
||||
const headers = new Headers()
|
||||
if (apiKey && apiKey !== OAUTH_DUMMY_KEY) headers.append("Authorization", `Bearer ${apiKey}`)
|
||||
const models = await fetchFn(`${baseURL}/models`, {
|
||||
headers,
|
||||
signal: AbortSignal.timeout(3 * 1000),
|
||||
})
|
||||
.then(async (resp) => {
|
||||
if (!resp.ok) return
|
||||
return ModelsList.parse(await resp.json())
|
||||
})
|
||||
.catch((err) => {
|
||||
log.error(`Failed to fetch models from: ${baseURL}/models`, { error: err })
|
||||
})
|
||||
if (!models) return
|
||||
|
||||
return models.data
|
||||
.filter((model) => model.id && !model.id.includes("embedding") && !model.id.includes("embed"))
|
||||
.map((model) => model.id)
|
||||
}
|
||||
|
||||
const state = Instance.state(async () => {
|
||||
using _ = log.time("state")
|
||||
const config = await Config.get()
|
||||
@@ -944,20 +903,6 @@ export namespace Provider {
|
||||
mergeProvider(providerID, partial)
|
||||
}
|
||||
|
||||
// detect models and prune invalid ones
|
||||
await Promise.all(
|
||||
Object.values(providers).map(async (provider) => {
|
||||
const detected = await listModels(provider)
|
||||
if (!detected) return
|
||||
const detectedSet = new Set(detected)
|
||||
for (const modelID of Object.keys(provider.models)) {
|
||||
if (!detectedSet.has(modelID)) delete provider.models[modelID]
|
||||
}
|
||||
// TODO: add detected models not present in config/models.dev
|
||||
// for (const modelID of detected) {}
|
||||
}),
|
||||
)
|
||||
|
||||
for (const [providerID, provider] of Object.entries(providers)) {
|
||||
if (!isProviderAllowed(providerID)) {
|
||||
delete providers[providerID]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/plugin",
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/sdk",
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/slack",
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/ui",
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"exports": {
|
||||
|
||||
@@ -28,18 +28,33 @@ const Context = createContext<ReturnType<typeof init>>()
|
||||
|
||||
function init() {
|
||||
const [active, setActive] = createSignal<Active | undefined>()
|
||||
let closing = false
|
||||
const timer = { current: undefined as ReturnType<typeof setTimeout> | undefined }
|
||||
const lock = { value: false }
|
||||
|
||||
onCleanup(() => {
|
||||
if (timer.current === undefined) return
|
||||
clearTimeout(timer.current)
|
||||
timer.current = undefined
|
||||
})
|
||||
|
||||
const close = () => {
|
||||
const current = active()
|
||||
if (!current || closing) return
|
||||
closing = true
|
||||
if (!current || lock.value) return
|
||||
lock.value = true
|
||||
current.onClose?.()
|
||||
current.setClosing(true)
|
||||
setTimeout(() => {
|
||||
|
||||
const id = current.id
|
||||
if (timer.current !== undefined) {
|
||||
clearTimeout(timer.current)
|
||||
timer.current = undefined
|
||||
}
|
||||
|
||||
timer.current = setTimeout(() => {
|
||||
timer.current = undefined
|
||||
current.dispose()
|
||||
setActive(undefined)
|
||||
closing = false
|
||||
if (active()?.id === id) setActive(undefined)
|
||||
lock.value = false
|
||||
}, 100)
|
||||
}
|
||||
|
||||
@@ -64,7 +79,12 @@ function init() {
|
||||
current.dispose()
|
||||
setActive(undefined)
|
||||
}
|
||||
closing = false
|
||||
|
||||
if (timer.current !== undefined) {
|
||||
clearTimeout(timer.current)
|
||||
timer.current = undefined
|
||||
}
|
||||
lock.value = false
|
||||
|
||||
const id = Math.random().toString(36).slice(2)
|
||||
let dispose: (() => void) | undefined
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/util",
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@opencode-ai/web",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"dev:remote": "VITE_API_URL=https://api.opencode.ai astro dev",
|
||||
|
||||
@@ -41,6 +41,7 @@ async function main() {
|
||||
for (const pr of prs) {
|
||||
console.log(`\nProcessing PR #${pr.number}: ${pr.title}`)
|
||||
|
||||
// Fetch the PR
|
||||
const fetchPR = await $`git fetch origin pull/${pr.number}/head:pr-${pr.number}`.nothrow()
|
||||
if (fetchPR.exitCode !== 0) {
|
||||
console.log(` Failed to fetch PR #${pr.number}, skipping`)
|
||||
@@ -48,6 +49,24 @@ async function main() {
|
||||
continue
|
||||
}
|
||||
|
||||
// Try to rebase onto current beta branch
|
||||
console.log(` Attempting to rebase PR #${pr.number}...`)
|
||||
const rebase = await $`git rebase beta pr-${pr.number}`.nothrow()
|
||||
if (rebase.exitCode !== 0) {
|
||||
console.log(` Rebase failed for PR #${pr.number} (has conflicts)`)
|
||||
await $`git rebase --abort`.nothrow()
|
||||
await $`git checkout beta`.nothrow()
|
||||
skipped.push({ number: pr.number, reason: "Rebase failed (conflicts)" })
|
||||
continue
|
||||
}
|
||||
|
||||
// Move rebased commits to pr-${pr.number} branch and checkout back to beta
|
||||
await $`git checkout -B pr-${pr.number}`.nothrow()
|
||||
await $`git checkout beta`.nothrow()
|
||||
|
||||
console.log(` Successfully rebased PR #${pr.number}`)
|
||||
|
||||
// Now squash merge the rebased PR
|
||||
const merge = await $`git merge --squash pr-${pr.number}`.nothrow()
|
||||
if (merge.exitCode !== 0) {
|
||||
console.log(` Squash merge failed for PR #${pr.number}`)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "opencode",
|
||||
"displayName": "opencode",
|
||||
"description": "opencode for VS Code",
|
||||
"version": "0.0.0-ci-202601291718",
|
||||
"version": "1.1.43",
|
||||
"publisher": "sst-dev",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
Reference in New Issue
Block a user