├── opencode ├── bunfig.toml ├── packages │ ├── tui │ │ ├── sdk │ │ │ ├── Brewfile │ │ │ ├── .release-please-manifest.json │ │ │ ├── .gitignore │ │ │ ├── internal │ │ │ │ ├── apiform │ │ │ │ │ ├── form.go │ │ │ │ │ └── tag.go │ │ │ │ ├── version.go │ │ │ │ ├── param │ │ │ │ │ └── field.go │ │ │ │ ├── testutil │ │ │ │ │ └── testutil.go │ │ │ │ ├── apiquery │ │ │ │ │ ├── tag.go │ │ │ │ │ └── query.go │ │ │ │ ├── apijson │ │ │ │ │ ├── tag.go │ │ │ │ │ ├── registry.go │ │ │ │ │ └── field.go │ │ │ │ └── apierror │ │ │ │ │ └── apierror.go │ │ │ ├── scripts │ │ │ │ ├── format │ │ │ │ ├── lint │ │ │ │ ├── bootstrap │ │ │ │ ├── mock │ │ │ │ └── test │ │ │ ├── lib │ │ │ │ └── .keep │ │ │ ├── examples │ │ │ │ └── .keep │ │ │ ├── go.mod │ │ │ ├── .stats.yml │ │ │ ├── .devcontainer │ │ │ │ └── devcontainer.json │ │ │ ├── usage_test.go │ │ │ ├── go.sum │ │ │ ├── option │ │ │ │ └── middleware.go │ │ │ ├── SECURITY.md │ │ │ ├── .github │ │ │ │ └── workflows │ │ │ │ │ └── ci.yml │ │ │ ├── aliases.go │ │ │ ├── release-please-config.json │ │ │ ├── config_test.go │ │ │ ├── file_test.go │ │ │ └── CONTRIBUTING.md │ │ ├── .gitignore │ │ ├── input │ │ │ ├── cursor.go │ │ │ ├── focus.go │ │ │ ├── cancelreader_other.go │ │ │ ├── doc.go │ │ │ ├── mode.go │ │ │ ├── paste.go │ │ │ ├── da1.go │ │ │ ├── focus_test.go │ │ │ ├── go.mod │ │ │ ├── driver_other.go │ │ │ ├── driver_test.go │ │ │ ├── clipboard.go │ │ │ ├── mod.go │ │ │ ├── input.go │ │ │ ├── termcap.go │ │ │ ├── xterm.go │ │ │ ├── parse_test.go │ │ │ └── go.sum │ │ ├── internal │ │ │ ├── completions │ │ │ │ ├── provider.go │ │ │ │ └── suggestion.go │ │ │ ├── styles │ │ │ │ ├── styles.go │ │ │ │ └── background.go │ │ │ ├── layout │ │ │ │ └── layout.go │ │ │ ├── util │ │ │ │ ├── concurrency_test.go │ │ │ │ ├── concurrency.go │ │ │ │ └── util.go │ │ │ ├── clipboard │ │ │ │ └── clipboard_nocgo.go │ │ │ └── components │ │ │ │ ├── qr │ │ │ │ └── qr.go │ │ │ │ └── chat │ │ │ │ └── cache.go │ │ └── .goreleaser.yml │ ├── opencode │ │ ├── src │ │ │ ├── tool │ │ │ │ ├── patch.txt │ │ │ │ ├── lsp-hover.txt │ │ │ │ ├── lsp-diagnostics.txt │ │ │ │ ├── ls.txt │ │ │ │ ├── websearch.txt │ │ │ │ ├── glob.txt │ │ │ │ ├── write.txt │ │ │ │ ├── grep.txt │ │ │ │ ├── webfetch.txt │ │ │ │ ├── tool.ts │ │ │ │ ├── todoread.txt │ │ │ │ ├── lsp-diagnostics.ts │ │ │ │ ├── edit.txt │ │ │ │ ├── lsp-hover.ts │ │ │ │ ├── multiedit.ts │ │ │ │ ├── read.txt │ │ │ │ ├── todo.ts │ │ │ │ ├── bash.ts │ │ │ │ └── task.txt │ │ │ ├── session │ │ │ │ ├── prompt │ │ │ │ │ ├── anthropic_spoof.txt │ │ │ │ │ ├── plan.txt │ │ │ │ │ ├── summarize.txt │ │ │ │ │ ├── initialize.txt │ │ │ │ │ └── title.txt │ │ │ │ └── mode.ts │ │ │ ├── cli │ │ │ │ ├── cmd │ │ │ │ │ ├── cmd.ts │ │ │ │ │ ├── debug │ │ │ │ │ │ ├── scrap.ts │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ ├── file.ts │ │ │ │ │ │ ├── snapshot.ts │ │ │ │ │ │ └── lsp.ts │ │ │ │ │ ├── generate.ts │ │ │ │ │ ├── models.ts │ │ │ │ │ └── serve.ts │ │ │ │ ├── bootstrap.ts │ │ │ │ └── error.ts │ │ │ ├── provider │ │ │ │ ├── models-macro.ts │ │ │ │ └── transform.ts │ │ │ ├── util │ │ │ │ ├── lazy.ts │ │ │ │ ├── scrap.ts │ │ │ │ ├── timeout.ts │ │ │ │ ├── context.ts │ │ │ │ └── error.ts │ │ │ ├── flag │ │ │ │ └── flag.ts │ │ │ ├── auth │ │ │ │ ├── copilot.ts │ │ │ │ └── index.ts │ │ │ ├── global │ │ │ │ └── index.ts │ │ │ ├── file │ │ │ │ ├── time.ts │ │ │ │ └── watch.ts │ │ │ ├── config │ │ │ │ └── hooks.ts │ │ │ └── format │ │ │ │ └── index.ts │ │ ├── .gitignore │ │ ├── tsconfig.json │ │ ├── sst-env.d.ts │ │ ├── README.md │ │ ├── test │ │ │ └── tool │ │ │ │ ├── __snapshots__ │ │ │ │ └── tool.test.ts.snap │ │ │ │ └── tool.test.ts │ │ ├── script │ │ │ └── schema.ts │ │ ├── package.json │ │ ├── bin │ │ │ ├── opencode.cmd │ │ │ └── opencode │ │ └── AGENTS.md │ ├── web │ │ ├── public │ │ │ ├── social-share.png │ │ │ └── favicon.svg │ │ ├── src │ │ │ ├── assets │ │ │ │ ├── lander │ │ │ │ │ ├── screenshot.png │ │ │ │ │ ├── screenshot-splash.png │ │ │ │ │ ├── check.svg │ │ │ │ │ └── copy.svg │ │ │ │ ├── logo-dark.svg │ │ │ │ ├── logo-light.svg │ │ │ │ ├── logo-ornate-light.svg │ │ │ │ └── logo-ornate-dark.svg │ │ │ ├── content.config.ts │ │ │ ├── components │ │ │ │ ├── Hero.astro │ │ │ │ ├── share │ │ │ │ │ ├── copy-button.module.css │ │ │ │ │ ├── content-code.module.css │ │ │ │ │ ├── content-error.tsx │ │ │ │ │ ├── copy-button.tsx │ │ │ │ │ ├── content-text.tsx │ │ │ │ │ ├── content-code.tsx │ │ │ │ │ ├── content-text.module.css │ │ │ │ │ ├── content-error.module.css │ │ │ │ │ └── content-bash.tsx │ │ │ │ └── Head.astro │ │ │ ├── content │ │ │ │ └── docs │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── docs │ │ │ │ │ ├── lsp-servers.mdx │ │ │ │ │ ├── mcp-servers.mdx │ │ │ │ │ └── keybinds.mdx │ │ │ ├── styles │ │ │ │ └── custom.css │ │ │ └── types │ │ │ │ └── lang-map.d.ts │ │ ├── sst-env.d.ts │ │ ├── tsconfig.json │ │ ├── .gitignore │ │ ├── config.mjs │ │ └── package.json │ └── function │ │ ├── tsconfig.json │ │ ├── package.json │ │ └── sst-env.d.ts ├── .gitignore ├── stainless-workspace.json ├── tsconfig.json ├── .editorconfig ├── opencode.json ├── sdks │ └── github │ │ ├── sst-env.d.ts │ │ ├── package.json │ │ ├── tsconfig.json │ │ └── action.yml ├── scripts │ ├── hooks │ ├── hooks.bat │ ├── stainless │ └── release ├── .github │ └── workflows │ │ ├── notify-discord.yml │ │ ├── deploy.yml │ │ ├── opencode.yml │ │ ├── stats.yml │ │ └── publish.yml ├── sst.config.ts ├── AGENTS.md ├── sst-env.d.ts ├── package.json ├── LICENSE ├── STATS.md └── infra │ └── app.ts ├── crates ├── code-mesh-tui │ ├── src │ │ ├── status.rs │ │ ├── utils │ │ │ └── mod.rs │ │ ├── components │ │ │ └── mod.rs │ │ ├── bin │ │ │ └── tui-demo.rs │ │ └── renderer.rs │ └── Cargo.toml ├── code-mesh-core │ ├── src │ │ ├── llm │ │ │ └── model.rs │ │ ├── features.rs │ │ ├── error.rs │ │ ├── agent │ │ │ └── mod.rs │ │ ├── memory │ │ │ └── mod.rs │ │ ├── planner │ │ │ └── mod.rs │ │ └── storage │ │ │ └── mod.rs │ ├── tests │ │ └── integration │ │ │ └── mod.rs │ └── benches │ │ └── mod.rs └── code-mesh-cli │ └── src │ └── cmd │ └── mod.rs ├── .hive-mind ├── sessions │ └── session-1752624671432-glgfnnabu-auto-save-1752624676726.json ├── hive.db-shm └── hive.db-wal ├── run-npm-cli.sh ├── .swarm ├── memory.db-shm └── memory.db-wal ├── npm ├── bin │ └── code-mesh-linux-x64 ├── jest.config.js ├── tests │ └── setup.ts ├── jest.browser.config.js ├── tsconfig.json └── webpack.config.js ├── rust-toolchain.toml ├── .dockerignore ├── .github └── dependabot.yml ├── tarpaulin.toml ├── LICENSE ├── test_stored_credentials.sh ├── docs ├── book.toml ├── legacy │ └── README.md └── src │ └── SUMMARY.md ├── .gitignore ├── Dockerfile ├── test_oauth.sh └── deny.toml /opencode/bunfig.toml: -------------------------------------------------------------------------------- 1 | [install] 2 | exact = true -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/Brewfile: -------------------------------------------------------------------------------- 1 | brew "go" 2 | -------------------------------------------------------------------------------- /opencode/packages/tui/.gitignore: -------------------------------------------------------------------------------- 1 | opencode-test 2 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/tool/patch.txt: -------------------------------------------------------------------------------- 1 | do not use 2 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/tool/lsp-hover.txt: -------------------------------------------------------------------------------- 1 | do not use 2 | -------------------------------------------------------------------------------- /crates/code-mesh-tui/src/status.rs: -------------------------------------------------------------------------------- 1 | pub use crate::components::StatusBar; -------------------------------------------------------------------------------- /opencode/packages/opencode/src/tool/lsp-diagnostics.txt: -------------------------------------------------------------------------------- 1 | do not use 2 | -------------------------------------------------------------------------------- /.hive-mind/sessions/session-1752624671432-glgfnnabu-auto-save-1752624676726.json: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /opencode/packages/opencode/.gitignore: -------------------------------------------------------------------------------- 1 | research 2 | dist 3 | gen 4 | app.log 5 | -------------------------------------------------------------------------------- /run-npm-cli.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd /workspaces/code-mesh/npm && node bin/code-mesh.js "$@" -------------------------------------------------------------------------------- /.swarm/memory.db-shm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruvnet/code-mesh/HEAD/.swarm/memory.db-shm -------------------------------------------------------------------------------- /.swarm/memory.db-wal: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruvnet/code-mesh/HEAD/.swarm/memory.db-wal -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/.release-please-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | ".": "0.1.0-alpha.8" 3 | } -------------------------------------------------------------------------------- /.hive-mind/hive.db-shm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruvnet/code-mesh/HEAD/.hive-mind/hive.db-shm -------------------------------------------------------------------------------- /.hive-mind/hive.db-wal: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruvnet/code-mesh/HEAD/.hive-mind/hive.db-wal -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/.gitignore: -------------------------------------------------------------------------------- 1 | .prism.log 2 | codegen.log 3 | Brewfile.lock.json 4 | .idea/ 5 | -------------------------------------------------------------------------------- /npm/bin/code-mesh-linux-x64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruvnet/code-mesh/HEAD/npm/bin/code-mesh-linux-x64 -------------------------------------------------------------------------------- /crates/code-mesh-tui/src/utils/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod syntax_highlighter; 2 | 3 | pub use syntax_highlighter::SyntaxHighlighter; -------------------------------------------------------------------------------- /opencode/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | .opencode 4 | .sst 5 | .env 6 | .idea 7 | .vscode 8 | openapi.json 9 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/session/prompt/anthropic_spoof.txt: -------------------------------------------------------------------------------- 1 | You are Claude Code, Anthropic's official CLI for Claude. 2 | -------------------------------------------------------------------------------- /opencode/packages/web/public/social-share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruvnet/code-mesh/HEAD/opencode/packages/web/public/social-share.png -------------------------------------------------------------------------------- /opencode/stainless-workspace.json: -------------------------------------------------------------------------------- 1 | { 2 | "project": "opencode", 3 | "openapi_spec": "openapi.json", 4 | "stainless_config": "stainless.yml" 5 | } 6 | -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/internal/apiform/form.go: -------------------------------------------------------------------------------- 1 | package apiform 2 | 3 | type Marshaler interface { 4 | MarshalMultipart() ([]byte, string, error) 5 | } 6 | -------------------------------------------------------------------------------- /opencode/packages/web/src/assets/lander/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruvnet/code-mesh/HEAD/opencode/packages/web/src/assets/lander/screenshot.png -------------------------------------------------------------------------------- /opencode/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "extends": "@tsconfig/bun/tsconfig.json", 4 | "compilerOptions": {} 5 | } 6 | -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/scripts/format: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | echo "==> Running gofmt -s -w" 8 | gofmt -s -w . 9 | -------------------------------------------------------------------------------- /rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "stable" 3 | components = ["rustfmt", "clippy", "rust-src"] 4 | targets = ["wasm32-unknown-unknown"] 5 | profile = "minimal" -------------------------------------------------------------------------------- /opencode/packages/web/src/assets/lander/screenshot-splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruvnet/code-mesh/HEAD/opencode/packages/web/src/assets/lander/screenshot-splash.png -------------------------------------------------------------------------------- /opencode/packages/opencode/src/cli/cmd/cmd.ts: -------------------------------------------------------------------------------- 1 | import type { CommandModule } from "yargs" 2 | 3 | export function cmd(input: CommandModule) { 4 | return input 5 | } 6 | -------------------------------------------------------------------------------- /opencode/packages/opencode/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "extends": "@tsconfig/bun/tsconfig.json", 4 | "compilerOptions": {} 5 | } 6 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/provider/models-macro.ts: -------------------------------------------------------------------------------- 1 | export async function data() { 2 | const json = await fetch("https://models.dev/api.json").then((x) => x.text()) 3 | return json 4 | } 5 | -------------------------------------------------------------------------------- /opencode/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | insert_final_newline = true 6 | end_of_line = lf 7 | indent_style = space 8 | indent_size = 2 9 | max_line_length = 80 10 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/cli/cmd/debug/scrap.ts: -------------------------------------------------------------------------------- 1 | import { cmd } from "../cmd" 2 | 3 | export const ScrapCommand = cmd({ 4 | command: "scrap", 5 | builder: (yargs) => yargs, 6 | async handler() {}, 7 | }) 8 | -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/internal/version.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package internal 4 | 5 | const PackageVersion = "0.1.0-alpha.8" // x-release-please-version 6 | -------------------------------------------------------------------------------- /crates/code-mesh-tui/src/components/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod command_palette; 2 | pub mod dialog; 3 | pub mod status_bar; 4 | 5 | pub use command_palette::CommandPalette; 6 | pub use dialog::{Dialog, DialogResult}; 7 | pub use status_bar::StatusBar; -------------------------------------------------------------------------------- /opencode/opencode.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://opencode.ai/config.json", 3 | "mcp": { 4 | "weather": { 5 | "type": "local", 6 | "command": ["opencode", "x", "@h1deya/mcp-server-weather"] 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/scripts/lint: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | echo "==> Running Go build" 8 | go build ./... 9 | 10 | echo "==> Checking tests compile" 11 | go test -run=^$ ./... 12 | -------------------------------------------------------------------------------- /opencode/packages/tui/input/cursor.go: -------------------------------------------------------------------------------- 1 | package input 2 | 3 | import "image" 4 | 5 | // CursorPositionEvent represents a cursor position event. Where X is the 6 | // zero-based column and Y is the zero-based row. 7 | type CursorPositionEvent image.Point 8 | -------------------------------------------------------------------------------- /opencode/packages/web/sst-env.d.ts: -------------------------------------------------------------------------------- 1 | /* This file is auto-generated by SST. Do not edit. */ 2 | /* tslint:disable */ 3 | /* eslint-disable */ 4 | /* deno-fmt-ignore-file */ 5 | 6 | /// 7 | 8 | import "sst" 9 | export {} -------------------------------------------------------------------------------- /opencode/sdks/github/sst-env.d.ts: -------------------------------------------------------------------------------- 1 | /* This file is auto-generated by SST. Do not edit. */ 2 | /* tslint:disable */ 3 | /* eslint-disable */ 4 | /* deno-fmt-ignore-file */ 5 | 6 | /// 7 | 8 | import "sst" 9 | export {} -------------------------------------------------------------------------------- /opencode/packages/opencode/sst-env.d.ts: -------------------------------------------------------------------------------- 1 | /* This file is auto-generated by SST. Do not edit. */ 2 | /* tslint:disable */ 3 | /* eslint-disable */ 4 | /* deno-fmt-ignore-file */ 5 | 6 | /// 7 | 8 | import "sst" 9 | export {} -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/lib/.keep: -------------------------------------------------------------------------------- 1 | File generated from our OpenAPI spec by Stainless. 2 | 3 | This directory can be used to store custom files to expand the SDK. 4 | It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. -------------------------------------------------------------------------------- /opencode/packages/web/src/assets/lander/check.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /opencode/packages/web/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "astro/tsconfigs/strict", 3 | "include": [".astro/types.d.ts", "**/*"], 4 | "exclude": ["dist"], 5 | "compilerOptions": { 6 | "jsx": "preserve", 7 | "jsxImportSource": "solid-js" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/examples/.keep: -------------------------------------------------------------------------------- 1 | File generated from our OpenAPI spec by Stainless. 2 | 3 | This directory can be used to store example files demonstrating usage of this SDK. 4 | It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. -------------------------------------------------------------------------------- /opencode/scripts/hooks: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ ! -d ".git" ]; then 4 | exit 0 5 | fi 6 | 7 | mkdir -p .git/hooks 8 | 9 | cat > .git/hooks/pre-push << 'EOF' 10 | #!/bin/sh 11 | bun run typecheck 12 | EOF 13 | 14 | chmod +x .git/hooks/pre-push 15 | echo "✅ Pre-push hook installed" 16 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/util/lazy.ts: -------------------------------------------------------------------------------- 1 | export function lazy(fn: () => T) { 2 | let value: T | undefined 3 | let loaded = false 4 | 5 | return (): T => { 6 | if (loaded) return value as T 7 | loaded = true 8 | value = fn() 9 | return value as T 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/util/scrap.ts: -------------------------------------------------------------------------------- 1 | export const foo: string = "42" 2 | export const bar: number = 123 3 | 4 | export function dummyFunction(): void { 5 | console.log("This is a dummy function") 6 | } 7 | 8 | export function randomHelper(): boolean { 9 | return Math.random() > 0.5 10 | } 11 | -------------------------------------------------------------------------------- /crates/code-mesh-core/src/llm/model.rs: -------------------------------------------------------------------------------- 1 | //! Model trait and common implementations 2 | 3 | use super::provider::{Cost, Limits, ModelCapabilities}; 4 | use serde_json::Value; 5 | use std::collections::HashMap; 6 | 7 | /// Model trait representing an AI model (re-exported from provider) 8 | pub use super::provider::Model; -------------------------------------------------------------------------------- /opencode/packages/function/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "extends": "@tsconfig/node22/tsconfig.json", 4 | "compilerOptions": { 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "types": ["@cloudflare/workers-types", "node"] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /opencode/packages/tui/internal/completions/provider.go: -------------------------------------------------------------------------------- 1 | package completions 2 | 3 | // CompletionProvider defines the interface for completion data providers 4 | type CompletionProvider interface { 5 | GetId() string 6 | GetChildEntries(query string) ([]CompletionSuggestion, error) 7 | GetEmptyMessage() string 8 | } 9 | -------------------------------------------------------------------------------- /opencode/packages/opencode/README.md: -------------------------------------------------------------------------------- 1 | # js 2 | 3 | To install dependencies: 4 | 5 | ```bash 6 | bun install 7 | ``` 8 | 9 | To run: 10 | 11 | ```bash 12 | bun run index.ts 13 | ``` 14 | 15 | This project was created using `bun init` in bun v1.2.12. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime. 16 | -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/sst/opencode-sdk-go 2 | 3 | go 1.21 4 | 5 | require ( 6 | github.com/tidwall/gjson v1.14.4 7 | github.com/tidwall/sjson v1.2.5 8 | ) 9 | 10 | require ( 11 | github.com/tidwall/match v1.1.1 // indirect 12 | github.com/tidwall/pretty v1.2.1 // indirect 13 | ) 14 | -------------------------------------------------------------------------------- /opencode/scripts/hooks.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | if not exist ".git" ( 4 | exit /b 0 5 | ) 6 | 7 | if not exist ".git\hooks" ( 8 | mkdir ".git\hooks" 9 | ) 10 | 11 | ( 12 | echo #!/bin/sh 13 | echo bun run typecheck 14 | ) > ".git\hooks\pre-push" 15 | 16 | echo ✅ Pre-push hook installed 17 | -------------------------------------------------------------------------------- /opencode/packages/tui/input/focus.go: -------------------------------------------------------------------------------- 1 | package input 2 | 3 | // FocusEvent represents a terminal focus event. 4 | // This occurs when the terminal gains focus. 5 | type FocusEvent struct{} 6 | 7 | // BlurEvent represents a terminal blur event. 8 | // This occurs when the terminal loses focus. 9 | type BlurEvent struct{} 10 | -------------------------------------------------------------------------------- /opencode/packages/web/src/content.config.ts: -------------------------------------------------------------------------------- 1 | import { defineCollection } from "astro:content" 2 | import { docsLoader } from "@astrojs/starlight/loaders" 3 | import { docsSchema } from "@astrojs/starlight/schema" 4 | 5 | export const collections = { 6 | docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), 7 | } 8 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/tool/ls.txt: -------------------------------------------------------------------------------- 1 | Lists files and directories in a given path. The path parameter must be an absolute path, not a relative path. You can optionally provide an array of glob patterns to ignore with the ignore parameter. You should generally prefer the Glob and Grep tools, if you know which directories to search. 2 | -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/.stats.yml: -------------------------------------------------------------------------------- 1 | configured_endpoints: 22 2 | openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-7270b9e4859010d6680bcc92afcd6f7c679d80a2645f65d7097d19ce2e8cdc5a.yml 3 | openapi_spec_hash: 5fcbfaedebfea62c17c74437a9728b04 4 | config_hash: 38041c37df28a1c4383718e6d148dd0a 5 | -------------------------------------------------------------------------------- /opencode/packages/tui/input/cancelreader_other.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | // +build !windows 3 | 4 | package input 5 | 6 | import ( 7 | "io" 8 | 9 | "github.com/muesli/cancelreader" 10 | ) 11 | 12 | func newCancelreader(r io.Reader, _ int) (cancelreader.CancelReader, error) { 13 | return cancelreader.NewReader(r) //nolint:wrapcheck 14 | } 15 | -------------------------------------------------------------------------------- /opencode/packages/web/src/components/Hero.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Default from '@astrojs/starlight/components/Hero.astro'; 3 | import Lander from './Lander.astro'; 4 | 5 | const { slug } = Astro.locals.starlightRoute.entry; 6 | --- 7 | 8 | { slug === "" 9 | ? 10 | : 11 | } 12 | -------------------------------------------------------------------------------- /opencode/packages/tui/internal/styles/styles.go: -------------------------------------------------------------------------------- 1 | package styles 2 | 3 | import ( 4 | "github.com/charmbracelet/lipgloss/v2" 5 | "github.com/charmbracelet/lipgloss/v2/compat" 6 | ) 7 | 8 | func WhitespaceStyle(bg compat.AdaptiveColor) lipgloss.WhitespaceOption { 9 | return lipgloss.WithWhitespaceStyle(NewStyle().Background(bg).Lipgloss()) 10 | } 11 | -------------------------------------------------------------------------------- /opencode/packages/web/.gitignore: -------------------------------------------------------------------------------- 1 | # build output 2 | dist/ 3 | # generated types 4 | .astro/ 5 | 6 | # dependencies 7 | node_modules/ 8 | 9 | # logs 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | pnpm-debug.log* 14 | 15 | 16 | # environment variables 17 | .env 18 | .env.production 19 | 20 | # macOS-specific files 21 | .DS_Store 22 | -------------------------------------------------------------------------------- /crates/code-mesh-core/tests/integration/mod.rs: -------------------------------------------------------------------------------- 1 | //! Integration tests for code-mesh-core 2 | 3 | use code_mesh_core::*; 4 | use std::sync::Arc; 5 | use tempfile::TempDir; 6 | 7 | mod common; 8 | use common::{mocks::*, fixtures::*, *}; 9 | 10 | pub mod end_to_end_tests; 11 | pub mod api_integration_tests; 12 | pub mod workflow_tests; 13 | pub mod performance_tests; -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the 2 | // README at: https://github.com/devcontainers/templates/tree/main/src/debian 3 | { 4 | "name": "Development", 5 | "image": "mcr.microsoft.com/devcontainers/go:1.23-bookworm", 6 | "postCreateCommand": "go mod tidy" 7 | } 8 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/flag/flag.ts: -------------------------------------------------------------------------------- 1 | export namespace Flag { 2 | export const OPENCODE_AUTO_SHARE = truthy("OPENCODE_AUTO_SHARE") 3 | export const OPENCODE_DISABLE_WATCHER = truthy("OPENCODE_DISABLE_WATCHER") 4 | 5 | function truthy(key: string) { 6 | const value = process.env[key]?.toLowerCase() 7 | return value === "true" || value === "1" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /opencode/packages/tui/internal/styles/background.go: -------------------------------------------------------------------------------- 1 | package styles 2 | 3 | import "image/color" 4 | 5 | type TerminalInfo struct { 6 | Background color.Color 7 | BackgroundIsDark bool 8 | } 9 | 10 | var Terminal *TerminalInfo 11 | 12 | func init() { 13 | Terminal = &TerminalInfo{ 14 | Background: color.Black, 15 | BackgroundIsDark: true, 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /opencode/packages/tui/input/doc.go: -------------------------------------------------------------------------------- 1 | // Package input provides a set of utilities for handling input events in a 2 | // terminal environment. It includes support for reading input events, parsing 3 | // escape sequences, and handling clipboard events. 4 | // The package is designed to work with various terminal types and supports 5 | // customization through flags and options. 6 | package input 7 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/session/prompt/plan.txt: -------------------------------------------------------------------------------- 1 | 2 | Plan mode is active. The user indicated that they do not want you to execute yet -- you MUST NOT make any edits, run any non-readonly tools (including changing configs or making commits), or otherwise make any changes to the system. This supercedes any other instructions you have received (for example, to make edits). 3 | 4 | -------------------------------------------------------------------------------- /opencode/packages/tui/input/mode.go: -------------------------------------------------------------------------------- 1 | package input 2 | 3 | import "github.com/charmbracelet/x/ansi" 4 | 5 | // ModeReportEvent is a message that represents a mode report event (DECRPM). 6 | // 7 | // See: https://vt100.net/docs/vt510-rm/DECRPM.html 8 | type ModeReportEvent struct { 9 | // Mode is the mode number. 10 | Mode ansi.Mode 11 | 12 | // Value is the mode value. 13 | Value ansi.ModeSetting 14 | } 15 | -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/scripts/bootstrap: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ]; then 8 | brew bundle check >/dev/null 2>&1 || { 9 | echo "==> Installing Homebrew dependencies…" 10 | brew bundle 11 | } 12 | fi 13 | 14 | echo "==> Installing Go dependencies…" 15 | 16 | go mod tidy -e 17 | -------------------------------------------------------------------------------- /opencode/packages/web/public/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /opencode/packages/web/src/content/docs/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: opencode 3 | description: The AI coding agent built for the terminal. 4 | template: splash 5 | hero: 6 | title: The AI coding agent built for the terminal. 7 | tagline: The AI coding agent built for the terminal. 8 | image: 9 | dark: ../../assets/logo-ornate-dark.svg 10 | light: ../../assets/logo-ornate-light.svg 11 | alt: opencode logo 12 | --- 13 | -------------------------------------------------------------------------------- /crates/code-mesh-cli/src/cmd/mod.rs: -------------------------------------------------------------------------------- 1 | //! Command implementations 2 | 3 | pub mod auth; 4 | pub mod config; 5 | pub mod error; 6 | pub mod init; 7 | pub mod models; 8 | pub mod oauth; 9 | pub mod run; 10 | pub mod serve; 11 | pub mod status; 12 | pub mod ui; 13 | pub mod utils; 14 | 15 | // Re-export commonly used types 16 | pub use error::{CliError, Result}; 17 | pub use ui::{UI, Theme, ProgressTracker}; 18 | pub use config::{Config, Profile}; -------------------------------------------------------------------------------- /opencode/.github/workflows/notify-discord.yml: -------------------------------------------------------------------------------- 1 | name: Notify Discord on Release 2 | 3 | on: 4 | release: 5 | types: [published] # fires only when a release is published 6 | 7 | jobs: 8 | notify: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Send nicely-formatted embed to Discord 12 | uses: SethCohen/github-releases-to-discord@v1 13 | with: 14 | webhook-url: ${{ secrets.DISCORD_WEBHOOK }} 15 | -------------------------------------------------------------------------------- /crates/code-mesh-tui/src/bin/tui-demo.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use code_mesh_tui::{App, Config}; 3 | 4 | #[tokio::main] 5 | async fn main() -> Result<()> { 6 | // Initialize logging 7 | tracing_subscriber::fmt::init(); 8 | 9 | // Load configuration 10 | let config = Config::load_or_default(); 11 | 12 | // Create and run the application 13 | let mut app = App::new(config).await?; 14 | app.run().await?; 15 | 16 | Ok(()) 17 | } -------------------------------------------------------------------------------- /opencode/packages/web/config.mjs: -------------------------------------------------------------------------------- 1 | const stage = process.env.SST_STAGE || "dev" 2 | 3 | export default { 4 | url: stage === "production" 5 | ? "https://opencode.ai" 6 | : `https://${stage}.opencode.ai`, 7 | socialCard: "https://social-cards.sst.dev", 8 | github: "https://github.com/sst/opencode", 9 | discord: "https://opencode.ai/discord", 10 | headerLinks: [ 11 | { name: "Home", url: "/" }, 12 | { name: "Docs", url: "/docs/" }, 13 | ], 14 | } 15 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/util/timeout.ts: -------------------------------------------------------------------------------- 1 | export function withTimeout(promise: Promise, ms: number): Promise { 2 | let timeout: NodeJS.Timeout 3 | return Promise.race([ 4 | promise.then((result) => { 5 | clearTimeout(timeout) 6 | return result 7 | }), 8 | new Promise((_, reject) => { 9 | timeout = setTimeout(() => { 10 | reject(new Error(`Operation timed out after ${ms}ms`)) 11 | }, ms) 12 | }), 13 | ]) 14 | } 15 | -------------------------------------------------------------------------------- /opencode/packages/web/src/assets/lander/copy.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /opencode/packages/tui/input/paste.go: -------------------------------------------------------------------------------- 1 | package input 2 | 3 | // PasteEvent is an message that is emitted when a terminal receives pasted text 4 | // using bracketed-paste. 5 | type PasteEvent string 6 | 7 | // PasteStartEvent is an message that is emitted when the terminal starts the 8 | // bracketed-paste text. 9 | type PasteStartEvent struct{} 10 | 11 | // PasteEndEvent is an message that is emitted when the terminal ends the 12 | // bracketed-paste text. 13 | type PasteEndEvent struct{} 14 | -------------------------------------------------------------------------------- /opencode/packages/opencode/test/tool/__snapshots__/tool.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Bun Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`tool.ls basic 1`] = ` 4 | "- /home/thdxr/dev/projects/sst/opencode/js/example/ 5 | - home/ 6 | - thdxr/ 7 | - dev/ 8 | - projects/ 9 | - sst/ 10 | - opencode/ 11 | - js/ 12 | - example/ 13 | - ink.tsx 14 | - broken.ts 15 | - cli.ts 16 | " 17 | `; 18 | -------------------------------------------------------------------------------- /opencode/sst.config.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | export default $config({ 4 | app(input) { 5 | return { 6 | name: "opencode", 7 | removal: input?.stage === "production" ? "retain" : "remove", 8 | protect: ["production"].includes(input?.stage), 9 | home: "cloudflare", 10 | } 11 | }, 12 | async run() { 13 | const { api } = await import("./infra/app.js") 14 | return { 15 | api: api.url, 16 | } 17 | }, 18 | }) 19 | -------------------------------------------------------------------------------- /opencode/AGENTS.md: -------------------------------------------------------------------------------- 1 | # TUI Agent Guidelines 2 | 3 | ## Style 4 | 5 | - prefer single word variable/function names 6 | - avoid try catch where possible - prefer to let exceptions bubble up 7 | - avoid else statements where possible 8 | - do not make useless helper functions - inline functionality unless the 9 | function is reusable or composable 10 | - prefer Bun apis 11 | 12 | ## Workflow 13 | 14 | - you can regenerate the golang sdk by calling ./scripts/stainless.ts 15 | - we use bun for everything 16 | -------------------------------------------------------------------------------- /opencode/packages/function/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@opencode/function", 3 | "version": "0.0.1", 4 | "$schema": "https://json.schemastore.org/package.json", 5 | "private": true, 6 | "type": "module", 7 | "devDependencies": { 8 | "@cloudflare/workers-types": "4.20250522.0", 9 | "typescript": "catalog:", 10 | "@types/node": "catalog:" 11 | }, 12 | "dependencies": { 13 | "@octokit/auth-app": "8.0.1", 14 | "@octokit/rest": "22.0.0", 15 | "jose": "6.0.11" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /opencode/sdks/github/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "github", 3 | "type": "module", 4 | "private": true, 5 | "devDependencies": { 6 | "@octokit/webhooks-types": "^7.6.1", 7 | "@types/bun": "latest", 8 | "@types/node": "^24.0.10" 9 | }, 10 | "peerDependencies": { 11 | "typescript": "^5" 12 | }, 13 | "dependencies": { 14 | "@actions/core": "^1.11.1", 15 | "@actions/github": "^6.0.1", 16 | "@octokit/graphql": "^9.0.1", 17 | "@octokit/rest": "^22.0.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/cli/bootstrap.ts: -------------------------------------------------------------------------------- 1 | import { App } from "../app/app" 2 | import { ConfigHooks } from "../config/hooks" 3 | import { Format } from "../format" 4 | import { LSP } from "../lsp" 5 | import { Share } from "../share/share" 6 | 7 | export async function bootstrap(input: App.Input, cb: (app: App.Info) => Promise) { 8 | return App.provide(input, async (app) => { 9 | Share.init() 10 | Format.init() 11 | ConfigHooks.init() 12 | LSP.init() 13 | 14 | return cb(app) 15 | }) 16 | } 17 | -------------------------------------------------------------------------------- /opencode/packages/tui/input/da1.go: -------------------------------------------------------------------------------- 1 | package input 2 | 3 | import "github.com/charmbracelet/x/ansi" 4 | 5 | // PrimaryDeviceAttributesEvent is an event that represents the terminal 6 | // primary device attributes. 7 | type PrimaryDeviceAttributesEvent []int 8 | 9 | func parsePrimaryDevAttrs(params ansi.Params) Event { 10 | // Primary Device Attributes 11 | da1 := make(PrimaryDeviceAttributesEvent, len(params)) 12 | for i, p := range params { 13 | if !p.HasMore() { 14 | da1[i] = p.Param(0) 15 | } 16 | } 17 | return da1 18 | } 19 | -------------------------------------------------------------------------------- /opencode/packages/tui/input/focus_test.go: -------------------------------------------------------------------------------- 1 | package input 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestFocus(t *testing.T) { 8 | var p Parser 9 | _, e := p.parseSequence([]byte("\x1b[I")) 10 | switch e.(type) { 11 | case FocusEvent: 12 | // ok 13 | default: 14 | t.Error("invalid sequence") 15 | } 16 | } 17 | 18 | func TestBlur(t *testing.T) { 19 | var p Parser 20 | _, e := p.parseSequence([]byte("\x1b[O")) 21 | switch e.(type) { 22 | case BlurEvent: 23 | // ok 24 | default: 25 | t.Error("invalid sequence") 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/session/prompt/summarize.txt: -------------------------------------------------------------------------------- 1 | You are a helpful AI assistant tasked with summarizing conversations. 2 | 3 | When asked to summarize, provide a detailed but concise summary of the conversation. 4 | Focus on information that would be helpful for continuing the conversation, including: 5 | - What was done 6 | - What is currently being worked on 7 | - Which files are being modified 8 | - What needs to be done next 9 | 10 | Your summary should be comprehensive enough to provide context but concise enough to be quickly understood. 11 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/tool/websearch.txt: -------------------------------------------------------------------------------- 1 | 2 | - Allows opencode to search the web and use the results to inform responses 3 | - Provides up-to-date information for current events and recent data 4 | - Returns search result information formatted as search result blocks 5 | - Use this tool for accessing information beyond Claude's knowledge cutoff 6 | - Searches are performed automatically within a single API call 7 | 8 | Usage notes: 9 | - Domain filtering is supported to include or block specific websites 10 | - Web search is only available in the US 11 | 12 | -------------------------------------------------------------------------------- /opencode/packages/tui/input/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/charmbracelet/x/input 2 | 3 | go 1.23.0 4 | 5 | require ( 6 | github.com/charmbracelet/x/ansi v0.9.3 7 | github.com/charmbracelet/x/windows v0.2.1 8 | github.com/muesli/cancelreader v0.2.2 9 | github.com/rivo/uniseg v0.4.7 10 | github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e 11 | golang.org/x/sys v0.33.0 12 | ) 13 | 14 | require ( 15 | github.com/lucasb-eyer/go-colorful v1.2.0 // indirect 16 | github.com/mattn/go-runewidth v0.0.16 // indirect 17 | golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect 18 | ) 19 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/tool/glob.txt: -------------------------------------------------------------------------------- 1 | - Fast file pattern matching tool that works with any codebase size 2 | - Supports glob patterns like "**/*.js" or "src/**/*.ts" 3 | - Returns matching file paths sorted by modification time 4 | - Use this tool when you need to find files by name patterns 5 | - When you are doing an open ended search that may require multiple rounds of globbing and grepping, use the Agent tool instead 6 | - You have the capability to call multiple tools in a single response. It is always better to speculatively perform multiple searches as a batch that are potentially useful. 7 | -------------------------------------------------------------------------------- /opencode/packages/tui/input/driver_other.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | // +build !windows 3 | 4 | package input 5 | 6 | // ReadEvents reads input events from the terminal. 7 | // 8 | // It reads the events available in the input buffer and returns them. 9 | func (d *Reader) ReadEvents() ([]Event, error) { 10 | return d.readEvents() 11 | } 12 | 13 | // parseWin32InputKeyEvent parses a Win32 input key events. This function is 14 | // only available on Windows. 15 | func (p *Parser) parseWin32InputKeyEvent(*win32InputState, uint16, uint16, rune, bool, uint32, uint16) Event { 16 | return nil 17 | } 18 | -------------------------------------------------------------------------------- /npm/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | testEnvironment: 'node', 4 | roots: ['/src', '/tests'], 5 | testMatch: [ 6 | '**/__tests__/**/*.ts', 7 | '**/?(*.)+(spec|test).ts' 8 | ], 9 | transform: { 10 | '^.+\.ts$': 'ts-jest' 11 | }, 12 | setupFilesAfterEnv: ['/tests/setup.ts'], 13 | collectCoverageFrom: [ 14 | 'src/**/*.ts', 15 | '!src/**/*.d.ts', 16 | '!src/**/*.test.ts', 17 | '!src/**/*.spec.ts' 18 | ], 19 | coverageDirectory: 'coverage', 20 | coverageReporters: ['text', 'lcov', 'html'], 21 | verbose: true 22 | }; -------------------------------------------------------------------------------- /opencode/packages/opencode/src/cli/cmd/generate.ts: -------------------------------------------------------------------------------- 1 | import { Server } from "../../server/server" 2 | import fs from "fs/promises" 3 | import path from "path" 4 | import type { CommandModule } from "yargs" 5 | 6 | export const GenerateCommand = { 7 | command: "generate", 8 | handler: async () => { 9 | const specs = await Server.openapi() 10 | const dir = "gen" 11 | await fs.rmdir(dir, { recursive: true }).catch(() => {}) 12 | await fs.mkdir(dir, { recursive: true }) 13 | await Bun.write(path.join(dir, "openapi.json"), JSON.stringify(specs, null, 2)) 14 | }, 15 | } satisfies CommandModule 16 | -------------------------------------------------------------------------------- /crates/code-mesh-core/benches/mod.rs: -------------------------------------------------------------------------------- 1 | // Performance benchmarks for code-mesh-core 2 | // 3 | // This module provides comprehensive benchmarking for all core components 4 | // to track performance improvements and detect regressions. 5 | 6 | pub mod tool_benchmarks; 7 | pub mod llm_benchmarks; 8 | pub mod session_benchmarks; 9 | pub mod memory_benchmarks; 10 | pub mod storage_benchmarks; 11 | pub mod integration_benchmarks; 12 | 13 | pub use tool_benchmarks::*; 14 | pub use llm_benchmarks::*; 15 | pub use session_benchmarks::*; 16 | pub use memory_benchmarks::*; 17 | pub use storage_benchmarks::*; 18 | pub use integration_benchmarks::*; -------------------------------------------------------------------------------- /opencode/.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: deploy 2 | 3 | on: 4 | push: 5 | branches: 6 | - dev 7 | - production 8 | workflow_dispatch: 9 | 10 | concurrency: ${{ github.workflow }}-${{ github.ref }} 11 | 12 | jobs: 13 | deploy: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v3 17 | 18 | - uses: oven-sh/setup-bun@v1 19 | with: 20 | bun-version: 1.2.17 21 | 22 | - run: bun install 23 | 24 | - run: bun sst deploy --stage=${{ github.ref_name }} 25 | env: 26 | CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} 27 | -------------------------------------------------------------------------------- /opencode/packages/tui/input/driver_test.go: -------------------------------------------------------------------------------- 1 | package input 2 | 3 | import ( 4 | "io" 5 | "strings" 6 | "testing" 7 | ) 8 | 9 | func BenchmarkDriver(b *testing.B) { 10 | input := "\x1b\x1b[Ztest\x00\x1b]10;1234/1234/1234\x07\x1b[27;2;27~" 11 | rdr := strings.NewReader(input) 12 | drv, err := NewReader(rdr, "dumb", 0) 13 | if err != nil { 14 | b.Fatalf("could not create driver: %v", err) 15 | } 16 | 17 | b.ReportAllocs() 18 | b.ResetTimer() 19 | for i := 0; i < b.N; i++ { 20 | rdr.Reset(input) 21 | if _, err := drv.ReadEvents(); err != nil && err != io.EOF { 22 | b.Errorf("error reading input: %v", err) 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /opencode/packages/tui/internal/layout/layout.go: -------------------------------------------------------------------------------- 1 | package layout 2 | 3 | import ( 4 | tea "github.com/charmbracelet/bubbletea/v2" 5 | ) 6 | 7 | var Current *LayoutInfo 8 | 9 | func init() { 10 | Current = &LayoutInfo{ 11 | Viewport: Dimensions{Width: 80, Height: 25}, 12 | Container: Dimensions{Width: 80, Height: 25}, 13 | } 14 | } 15 | 16 | type LayoutSize string 17 | 18 | type Dimensions struct { 19 | Width int 20 | Height int 21 | } 22 | 23 | type LayoutInfo struct { 24 | Viewport Dimensions 25 | Container Dimensions 26 | } 27 | 28 | type Modal interface { 29 | tea.Model 30 | Render(background string) string 31 | Close() tea.Cmd 32 | } 33 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/session/prompt/initialize.txt: -------------------------------------------------------------------------------- 1 | Please analyze this codebase and create an AGENTS.md file containing: 2 | 1. Build/lint/test commands - especially for running a single test 3 | 2. Code style guidelines including imports, formatting, types, naming conventions, error handling, etc. 4 | 5 | The file you create will be given to agentic coding agents (such as yourself) that operate in this repository. Make it about 20 lines long. 6 | If there are Cursor rules (in .cursor/rules/ or .cursorrules) or Copilot rules (in .github/copilot-instructions.md), make sure to include them. 7 | 8 | If there's already an AGENTS.md, improve it if it's located in ${path} 9 | -------------------------------------------------------------------------------- /opencode/packages/tui/internal/util/concurrency_test.go: -------------------------------------------------------------------------------- 1 | package util_test 2 | 3 | import ( 4 | "strconv" 5 | "strings" 6 | "testing" 7 | "time" 8 | 9 | "github.com/sst/opencode/internal/util" 10 | ) 11 | 12 | func TestWriteStringsPar(t *testing.T) { 13 | items := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} 14 | sb := strings.Builder{} 15 | util.WriteStringsPar(&sb, items, func(i int) string { 16 | // sleep for the inverse duration so that later items finish first 17 | time.Sleep(time.Duration(10-i) * time.Millisecond) 18 | return strconv.Itoa(i) 19 | }) 20 | if sb.String() != "0123456789" { 21 | t.Fatalf("expected 0123456789, got %s", sb.String()) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /opencode/packages/web/src/styles/custom.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --sl-color-bg-surface: var(--sl-color-bg-nav); 3 | --sl-color-divider: var(--sl-color-gray-5); 4 | } 5 | 6 | .expressive-code .frame { 7 | box-shadow: none; 8 | } 9 | 10 | @media (prefers-color-scheme: dark) { 11 | .shiki, 12 | .shiki span { 13 | color: var(--shiki-dark) !important; 14 | background-color: var(--shiki-dark-bg) !important; 15 | /* Optional, if you also want font styles */ 16 | font-style: var(--shiki-dark-font-style) !important; 17 | font-weight: var(--shiki-dark-font-weight) !important; 18 | text-decoration: var(--shiki-dark-text-decoration) !important; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/session/prompt/title.txt: -------------------------------------------------------------------------------- 1 | 2 | Generate a conversation thread title based on the first user message. 3 | 4 | 5 | 6 | - Maximum 50 characters 7 | - Single line only - NO newlines or line breaks 8 | - Create a descriptive thread name that captures the topic 9 | - No quotes, colons, or special formatting 10 | - Do not include explanatory text like "Title:" or similar prefixes 11 | 12 | 13 | 14 | Return only the thread title text on a single line with no newlines, explanations, or additional formatting. 15 | You should NEVER reply to the user's message. You can only generate titles. 16 | 17 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/tool/write.txt: -------------------------------------------------------------------------------- 1 | Writes a file to the local filesystem. 2 | 3 | Usage: 4 | - This tool will overwrite the existing file if there is one at the provided path. 5 | - If this is an existing file, you MUST use the Read tool first to read the file's contents. This tool will fail if you did not read the file first. 6 | - ALWAYS prefer editing existing files in the codebase. NEVER write new files unless explicitly required. 7 | - NEVER proactively create documentation files (*.md) or README files. Only create documentation files if explicitly requested by the User. 8 | - Only use emojis if the user explicitly requests it. Avoid writing emojis to files unless asked. 9 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/cli/cmd/models.ts: -------------------------------------------------------------------------------- 1 | import { App } from "../../app/app" 2 | import { Provider } from "../../provider/provider" 3 | import { cmd } from "./cmd" 4 | 5 | export const ModelsCommand = cmd({ 6 | command: "models", 7 | describe: "list all available models", 8 | handler: async () => { 9 | await App.provide({ cwd: process.cwd() }, async () => { 10 | const providers = await Provider.list() 11 | 12 | for (const [providerID, provider] of Object.entries(providers)) { 13 | for (const modelID of Object.keys(provider.info.models)) { 14 | console.log(`${providerID}/${modelID}`) 15 | } 16 | } 17 | }) 18 | }, 19 | }) 20 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/auth/copilot.ts: -------------------------------------------------------------------------------- 1 | import { Global } from "../global" 2 | import { lazy } from "../util/lazy" 3 | import path from "path" 4 | 5 | export const AuthCopilot = lazy(async () => { 6 | const file = Bun.file(path.join(Global.Path.state, "plugin", "copilot.ts")) 7 | const response = fetch("https://raw.githubusercontent.com/sst/opencode-github-copilot/refs/heads/main/auth.ts") 8 | .then((x) => Bun.write(file, x)) 9 | .catch(() => {}) 10 | 11 | if (!file.exists()) { 12 | const worked = await response 13 | if (!worked) return 14 | } 15 | const result = await import(file.name!).catch(() => {}) 16 | if (!result) return 17 | return result.AuthCopilot 18 | }) 19 | -------------------------------------------------------------------------------- /opencode/.github/workflows/opencode.yml: -------------------------------------------------------------------------------- 1 | name: opencode 2 | 3 | on: 4 | issue_comment: 5 | types: [created] 6 | 7 | jobs: 8 | opencode: 9 | if: startsWith(github.event.comment.body, 'hey opencode') 10 | runs-on: ubuntu-latest 11 | permissions: 12 | id-token: write 13 | steps: 14 | - name: Checkout repository 15 | uses: actions/checkout@v4 16 | with: 17 | fetch-depth: 1 18 | 19 | - name: Run opencode 20 | uses: sst/opencode/sdks/github@dev 21 | #uses: ./github-actions 22 | env: 23 | ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} 24 | with: 25 | model: anthropic/claude-sonnet-4-20250514 26 | -------------------------------------------------------------------------------- /opencode/packages/tui/internal/clipboard/clipboard_nocgo.go: -------------------------------------------------------------------------------- 1 | //go:build !windows && !darwin && !linux && !cgo 2 | 3 | package clipboard 4 | 5 | import "context" 6 | 7 | func initialize() error { 8 | return errNoCgo 9 | } 10 | 11 | func read(t Format) (buf []byte, err error) { 12 | panic("clipboard: cannot use when CGO_ENABLED=0") 13 | } 14 | 15 | func readc(t string) ([]byte, error) { 16 | panic("clipboard: cannot use when CGO_ENABLED=0") 17 | } 18 | 19 | func write(t Format, buf []byte) (<-chan struct{}, error) { 20 | panic("clipboard: cannot use when CGO_ENABLED=0") 21 | } 22 | 23 | func watch(ctx context.Context, t Format) <-chan []byte { 24 | panic("clipboard: cannot use when CGO_ENABLED=0") 25 | } 26 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/tool/grep.txt: -------------------------------------------------------------------------------- 1 | - Fast content search tool that works with any codebase size 2 | - Searches file contents using regular expressions 3 | - Supports full regex syntax (eg. "log.*Error", "function\s+\w+", etc.) 4 | - Filter files by pattern with the include parameter (eg. "*.js", "*.{ts,tsx}") 5 | - Returns file paths with at least one match sorted by modification time 6 | - Use this tool when you need to find files containing specific patterns 7 | - If you need to identify/count the number of matches within files, use the Bash tool with `rg` (ripgrep) directly. Do NOT use `grep`. 8 | - When you are doing an open ended search that may require multiple rounds of globbing and grepping, use the Agent tool instead 9 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/util/context.ts: -------------------------------------------------------------------------------- 1 | import { AsyncLocalStorage } from "async_hooks" 2 | 3 | export namespace Context { 4 | export class NotFound extends Error { 5 | constructor(public readonly name: string) { 6 | super(`No context found for ${name}`) 7 | } 8 | } 9 | 10 | export function create(name: string) { 11 | const storage = new AsyncLocalStorage() 12 | return { 13 | use() { 14 | const result = storage.getStore() 15 | if (!result) { 16 | throw new NotFound(name) 17 | } 18 | return result 19 | }, 20 | provide(value: T, fn: () => R) { 21 | return storage.run(value, fn) 22 | }, 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # Git 2 | .git/ 3 | .gitignore 4 | .gitattributes 5 | 6 | # GitHub 7 | .github/ 8 | 9 | # Documentation 10 | *.md 11 | docs/ 12 | 13 | # Target directories 14 | target/ 15 | **/target/ 16 | 17 | # IDE files 18 | .vscode/ 19 | .idea/ 20 | *.swp 21 | *.swo 22 | 23 | # OS files 24 | .DS_Store 25 | Thumbs.db 26 | 27 | # Logs 28 | *.log 29 | 30 | # Temporary files 31 | tmp/ 32 | temp/ 33 | 34 | # Node modules (if any) 35 | node_modules/ 36 | npm/node_modules/ 37 | 38 | # WASM artifacts 39 | pkg/ 40 | wasm-pack.log 41 | 42 | # Test artifacts 43 | coverage/ 44 | *.profraw 45 | 46 | # Local configuration 47 | .env 48 | .env.local 49 | 50 | # Backup files 51 | *.bak 52 | *.backup 53 | 54 | # Archive files 55 | *.tar.gz 56 | *.zip -------------------------------------------------------------------------------- /opencode/packages/web/src/components/share/copy-button.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | position: absolute; 3 | opacity: 0; 4 | visibility: hidden; 5 | transition: opacity 0.15s ease; 6 | 7 | button { 8 | cursor: pointer; 9 | background: none; 10 | border: none; 11 | padding: 0.125rem; 12 | background-color: var(--sl-color-bg); 13 | color: var(--sl-color-text-secondary); 14 | 15 | svg { 16 | display: block; 17 | width: 1rem; 18 | height: 1rem; 19 | } 20 | 21 | &[data-copied="true"] { 22 | color: var(--sl-color-green-high); 23 | } 24 | } 25 | } 26 | 27 | /* Show copy button when parent is hovered */ 28 | *:hover > .root { 29 | opacity: 1; 30 | visibility: visible; 31 | } 32 | -------------------------------------------------------------------------------- /opencode/packages/web/src/components/share/content-code.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | border: 1px solid var(--sl-color-divider); 3 | background-color: var(--sl-color-bg-surface); 4 | border-radius: 0.25rem; 5 | padding: 0.5rem calc(0.5rem + 3px); 6 | 7 | &[data-flush="true"] { 8 | border: none; 9 | background-color: transparent; 10 | padding: 0; 11 | border-radius: 0; 12 | } 13 | 14 | pre { 15 | --shiki-dark-bg: var(--sl-color-bg-surface) !important; 16 | background-color: var(--sl-color-bg-surface) !important; 17 | line-height: 1.6; 18 | font-size: 0.75rem; 19 | white-space: pre-wrap; 20 | word-break: break-word; 21 | 22 | span { 23 | white-space: break-spaces; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /npm/tests/setup.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Jest setup for Node.js tests 3 | */ 4 | 5 | // Mock WASM module for testing 6 | global.WebAssembly = { 7 | instantiate: jest.fn().mockResolvedValue({ 8 | instance: { 9 | exports: {} 10 | } 11 | }), 12 | compile: jest.fn().mockResolvedValue({}), 13 | validate: jest.fn().mockReturnValue(true), 14 | Module: jest.fn(), 15 | Instance: jest.fn(), 16 | Memory: jest.fn(), 17 | Table: jest.fn(), 18 | Global: jest.fn(), 19 | CompileError: Error, 20 | LinkError: Error, 21 | RuntimeError: Error 22 | } as any; 23 | 24 | // Mock console methods for cleaner test output 25 | global.console = { 26 | ...console, 27 | debug: jest.fn(), 28 | log: jest.fn(), 29 | warn: jest.fn(), 30 | error: jest.fn() 31 | }; -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/internal/param/field.go: -------------------------------------------------------------------------------- 1 | package param 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type FieldLike interface{ field() } 8 | 9 | // Field is a wrapper used for all values sent to the API, 10 | // to distinguish zero values from null or omitted fields. 11 | // 12 | // It also allows sending arbitrary deserializable values. 13 | // 14 | // To instantiate a Field, use the helpers exported from 15 | // the package root: `F()`, `Null()`, `Raw()`, etc. 16 | type Field[T any] struct { 17 | FieldLike 18 | Value T 19 | Null bool 20 | Present bool 21 | Raw any 22 | } 23 | 24 | func (f Field[T]) String() string { 25 | if s, ok := any(f.Value).(fmt.Stringer); ok { 26 | return s.String() 27 | } 28 | return fmt.Sprintf("%v", f.Value) 29 | } 30 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/cli/error.ts: -------------------------------------------------------------------------------- 1 | import { Config } from "../config/config" 2 | import { MCP } from "../mcp" 3 | import { UI } from "./ui" 4 | 5 | export function FormatError(input: unknown) { 6 | if (MCP.Failed.isInstance(input)) 7 | return `MCP server "${input.data.name}" failed. Note, opencode does not support MCP authentication yet.` 8 | if (Config.JsonError.isInstance(input)) return `Config file at ${input.data.path} is not valid JSON` 9 | if (Config.InvalidError.isInstance(input)) 10 | return [ 11 | `Config file at ${input.data.path} is invalid`, 12 | ...(input.data.issues?.map((issue) => "↳ " + issue.message + " " + issue.path.join(".")) ?? []), 13 | ].join("\n") 14 | 15 | if (UI.CancelledError.isInstance(input)) return "" 16 | } 17 | -------------------------------------------------------------------------------- /opencode/sst-env.d.ts: -------------------------------------------------------------------------------- 1 | /* This file is auto-generated by SST. Do not edit. */ 2 | /* tslint:disable */ 3 | /* eslint-disable */ 4 | /* deno-fmt-ignore-file */ 5 | 6 | declare module "sst" { 7 | export interface Resource { 8 | "Api": { 9 | "type": "sst.cloudflare.Worker" 10 | "url": string 11 | } 12 | "Bucket": { 13 | "type": "sst.cloudflare.Bucket" 14 | } 15 | "GITHUB_APP_ID": { 16 | "type": "sst.sst.Secret" 17 | "value": string 18 | } 19 | "GITHUB_APP_PRIVATE_KEY": { 20 | "type": "sst.sst.Secret" 21 | "value": string 22 | } 23 | "Web": { 24 | "type": "sst.cloudflare.Astro" 25 | "url": string 26 | } 27 | } 28 | } 29 | /// 30 | 31 | import "sst" 32 | export {} -------------------------------------------------------------------------------- /opencode/scripts/stainless: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | echo "Starting opencode server on port 4096..." 6 | bun run ./packages/opencode/src/index.ts serve --port 4096 & 7 | SERVER_PID=$! 8 | 9 | echo "Waiting for server to start..." 10 | sleep 3 11 | 12 | echo "Fetching OpenAPI spec from http://127.0.0.1:4096/doc..." 13 | curl -s http://127.0.0.1:4096/doc > openapi.json 14 | 15 | echo "Stopping server..." 16 | kill $SERVER_PID 17 | 18 | echo "Running stl builds create..." 19 | stl builds create --branch dev --pull --allow-empty --targets go 20 | 21 | echo "Cleaning up..." 22 | rm -rf packages/tui/sdk 23 | mv opencode-go/ packages/tui/sdk/ 24 | rm -rf packages/tui/sdk/.git 25 | 26 | echo "Kicking off production build..." 27 | stl builds create --branch main --wait false 28 | 29 | echo "Done!" 30 | -------------------------------------------------------------------------------- /opencode/packages/function/sst-env.d.ts: -------------------------------------------------------------------------------- 1 | /* This file is auto-generated by SST. Do not edit. */ 2 | /* tslint:disable */ 3 | /* eslint-disable */ 4 | /* deno-fmt-ignore-file */ 5 | 6 | import "sst" 7 | declare module "sst" { 8 | export interface Resource { 9 | "GITHUB_APP_ID": { 10 | "type": "sst.sst.Secret" 11 | "value": string 12 | } 13 | "GITHUB_APP_PRIVATE_KEY": { 14 | "type": "sst.sst.Secret" 15 | "value": string 16 | } 17 | "Web": { 18 | "type": "sst.cloudflare.Astro" 19 | "url": string 20 | } 21 | } 22 | } 23 | // cloudflare 24 | import * as cloudflare from "@cloudflare/workers-types"; 25 | declare module "sst" { 26 | export interface Resource { 27 | "Api": cloudflare.Service 28 | "Bucket": cloudflare.R2Bucket 29 | } 30 | } 31 | 32 | import "sst" 33 | export {} -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/usage_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package opencode_test 4 | 5 | import ( 6 | "context" 7 | "os" 8 | "testing" 9 | 10 | "github.com/sst/opencode-sdk-go" 11 | "github.com/sst/opencode-sdk-go/internal/testutil" 12 | "github.com/sst/opencode-sdk-go/option" 13 | ) 14 | 15 | func TestUsage(t *testing.T) { 16 | baseURL := "http://localhost:4010" 17 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 18 | baseURL = envURL 19 | } 20 | if !testutil.CheckTestServer(t, baseURL) { 21 | return 22 | } 23 | client := opencode.NewClient( 24 | option.WithBaseURL(baseURL), 25 | ) 26 | sessions, err := client.Session.List(context.TODO()) 27 | if err != nil { 28 | t.Error(err) 29 | return 30 | } 31 | t.Logf("%+v\n", sessions) 32 | } 33 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "cargo" 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" 7 | day: "monday" 8 | time: "04:00" 9 | open-pull-requests-limit: 10 10 | reviewers: 11 | - "maintainer-team" 12 | assignees: 13 | - "security-team" 14 | commit-message: 15 | prefix: "chore(deps):" 16 | labels: 17 | - "dependencies" 18 | - "rust" 19 | 20 | - package-ecosystem: "github-actions" 21 | directory: "/.github/workflows" 22 | schedule: 23 | interval: "weekly" 24 | day: "monday" 25 | time: "04:00" 26 | open-pull-requests-limit: 5 27 | reviewers: 28 | - "maintainer-team" 29 | commit-message: 30 | prefix: "chore(ci):" 31 | labels: 32 | - "dependencies" 33 | - "github-actions" -------------------------------------------------------------------------------- /opencode/packages/web/src/types/lang-map.d.ts: -------------------------------------------------------------------------------- 1 | declare module "lang-map" { 2 | /** Returned by calling `map()` */ 3 | export interface MapReturn { 4 | /** All extensions keyed by language name */ 5 | extensions: Record 6 | /** All languages keyed by file-extension */ 7 | languages: Record 8 | } 9 | 10 | /** 11 | * Calling `map()` gives you the raw lookup tables: 12 | * 13 | * ```js 14 | * const { extensions, languages } = map(); 15 | * ``` 16 | */ 17 | function map(): MapReturn 18 | 19 | /** Static method: get extensions for a given language */ 20 | namespace map { 21 | function extensions(language: string): string[] 22 | /** Static method: get languages for a given extension */ 23 | function languages(extension: string): string[] 24 | } 25 | 26 | export = map 27 | } 28 | -------------------------------------------------------------------------------- /opencode/sdks/github/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | // Environment setup & latest features 4 | "lib": ["ESNext"], 5 | "target": "ESNext", 6 | "module": "ESNext", 7 | "moduleDetection": "force", 8 | "jsx": "react-jsx", 9 | "allowJs": true, 10 | 11 | // Bundler mode 12 | "moduleResolution": "bundler", 13 | "allowImportingTsExtensions": true, 14 | "verbatimModuleSyntax": true, 15 | "noEmit": true, 16 | 17 | // Best practices 18 | "strict": true, 19 | "skipLibCheck": true, 20 | "noFallthroughCasesInSwitch": true, 21 | "noUncheckedIndexedAccess": true, 22 | "noImplicitOverride": true, 23 | 24 | // Some stricter flags (disabled by default) 25 | "noUnusedLocals": false, 26 | "noUnusedParameters": false, 27 | "noPropertyAccessFromIndexSignature": false 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /opencode/packages/tui/input/clipboard.go: -------------------------------------------------------------------------------- 1 | package input 2 | 3 | import "github.com/charmbracelet/x/ansi" 4 | 5 | // ClipboardSelection represents a clipboard selection. The most common 6 | // clipboard selections are "system" and "primary" and selections. 7 | type ClipboardSelection = byte 8 | 9 | // Clipboard selections. 10 | const ( 11 | SystemClipboard ClipboardSelection = ansi.SystemClipboard 12 | PrimaryClipboard ClipboardSelection = ansi.PrimaryClipboard 13 | ) 14 | 15 | // ClipboardEvent is a clipboard read message event. This message is emitted when 16 | // a terminal receives an OSC52 clipboard read message event. 17 | type ClipboardEvent struct { 18 | Content string 19 | Selection ClipboardSelection 20 | } 21 | 22 | // String returns the string representation of the clipboard message. 23 | func (e ClipboardEvent) String() string { 24 | return e.Content 25 | } 26 | -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/go.sum: -------------------------------------------------------------------------------- 1 | github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= 2 | github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= 3 | github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= 4 | github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= 5 | github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= 6 | github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= 7 | github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= 8 | github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= 9 | github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= 10 | github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= 11 | -------------------------------------------------------------------------------- /opencode/.github/workflows/stats.yml: -------------------------------------------------------------------------------- 1 | name: stats 2 | 3 | on: 4 | schedule: 5 | - cron: "0 12 * * *" # Run daily at 12:00 UTC 6 | workflow_dispatch: # Allow manual trigger 7 | 8 | jobs: 9 | stats: 10 | runs-on: ubuntu-latest 11 | permissions: 12 | contents: write 13 | 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v4 17 | 18 | - name: Setup Bun 19 | uses: oven-sh/setup-bun@v2 20 | with: 21 | bun-version: latest 22 | 23 | - name: Run stats script 24 | run: bun scripts/stats.ts 25 | 26 | - name: Commit stats 27 | run: | 28 | git config --local user.email "action@github.com" 29 | git config --local user.name "GitHub Action" 30 | git add STATS.md 31 | git diff --staged --quiet || git commit -m "ignore: update download stats $(date -I)" 32 | git push 33 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/tool/webfetch.txt: -------------------------------------------------------------------------------- 1 | - Fetches content from a specified URL 2 | - Takes a URL and a prompt as input 3 | - Fetches the URL content, converts HTML to markdown 4 | - Returns the model's response about the content 5 | - Use this tool when you need to retrieve and analyze web content 6 | 7 | Usage notes: 8 | - IMPORTANT: If an MCP-provided web fetch tool is available, prefer using that tool instead of this one, as it may have fewer restrictions. All MCP-provided tools start with "mcp__". 9 | - The URL must be a fully-formed valid URL 10 | - HTTP URLs will be automatically upgraded to HTTPS 11 | - The prompt should describe what information you want to extract from the page 12 | - This tool is read-only and does not modify any files 13 | - Results may be summarized if the content is very large 14 | - Includes a self-cleaning 15-minute cache for faster responses when repeatedly accessing the same URL 15 | -------------------------------------------------------------------------------- /opencode/packages/tui/internal/completions/suggestion.go: -------------------------------------------------------------------------------- 1 | package completions 2 | 3 | import "github.com/sst/opencode/internal/styles" 4 | 5 | // CompletionSuggestion represents a data-only completion suggestion 6 | // with no styling or rendering logic 7 | type CompletionSuggestion struct { 8 | // The text to be displayed in the list. May contain minimal inline 9 | // ANSI styling if intrinsic to the data (e.g., git diff colors). 10 | Display func(styles.Style) string 11 | 12 | // The value to be used when the item is selected (e.g., inserted into the editor). 13 | Value string 14 | 15 | // An optional, longer description to be displayed. 16 | Description string 17 | 18 | // The ID of the provider that generated this suggestion. 19 | ProviderID string 20 | 21 | // The raw, underlying data object (e.g., opencode.Symbol, commands.Command). 22 | // This allows the selection handler to perform rich actions. 23 | RawData any 24 | } 25 | -------------------------------------------------------------------------------- /opencode/packages/tui/internal/util/concurrency.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "strings" 5 | ) 6 | 7 | func mapParallel[in, out any](items []in, fn func(in) out) chan out { 8 | mapChans := make([]chan out, 0, len(items)) 9 | 10 | for _, v := range items { 11 | ch := make(chan out) 12 | mapChans = append(mapChans, ch) 13 | go func() { 14 | defer close(ch) 15 | ch <- fn(v) 16 | }() 17 | } 18 | 19 | resultChan := make(chan out) 20 | 21 | go func() { 22 | defer close(resultChan) 23 | for _, ch := range mapChans { 24 | v := <-ch 25 | resultChan <- v 26 | } 27 | }() 28 | 29 | return resultChan 30 | } 31 | 32 | // WriteStringsPar allows to iterate over a list and compute strings in parallel, 33 | // yet write them in order. 34 | func WriteStringsPar[a any](sb *strings.Builder, items []a, fn func(a) string) { 35 | ch := mapParallel(items, fn) 36 | 37 | for v := range ch { 38 | sb.WriteString(v) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /opencode/packages/tui/input/mod.go: -------------------------------------------------------------------------------- 1 | package input 2 | 3 | // KeyMod represents modifier keys. 4 | type KeyMod int 5 | 6 | // Modifier keys. 7 | const ( 8 | ModShift KeyMod = 1 << iota 9 | ModAlt 10 | ModCtrl 11 | ModMeta 12 | 13 | // These modifiers are used with the Kitty protocol. 14 | // XXX: Meta and Super are swapped in the Kitty protocol, 15 | // this is to preserve compatibility with XTerm modifiers. 16 | 17 | ModHyper 18 | ModSuper // Windows/Command keys 19 | 20 | // These are key lock states. 21 | 22 | ModCapsLock 23 | ModNumLock 24 | ModScrollLock // Defined in Windows API only 25 | ) 26 | 27 | // Contains reports whether m contains the given modifiers. 28 | // 29 | // Example: 30 | // 31 | // m := ModAlt | ModCtrl 32 | // m.Contains(ModCtrl) // true 33 | // m.Contains(ModAlt | ModCtrl) // true 34 | // m.Contains(ModAlt | ModCtrl | ModShift) // false 35 | func (m KeyMod) Contains(mods KeyMod) bool { 36 | return m&mods == mods 37 | } 38 | -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/internal/testutil/testutil.go: -------------------------------------------------------------------------------- 1 | package testutil 2 | 3 | import ( 4 | "net/http" 5 | "os" 6 | "strconv" 7 | "testing" 8 | ) 9 | 10 | func CheckTestServer(t *testing.T, url string) bool { 11 | if _, err := http.Get(url); err != nil { 12 | const SKIP_MOCK_TESTS = "SKIP_MOCK_TESTS" 13 | if str, ok := os.LookupEnv(SKIP_MOCK_TESTS); ok { 14 | skip, err := strconv.ParseBool(str) 15 | if err != nil { 16 | t.Fatalf("strconv.ParseBool(os.LookupEnv(%s)) failed: %s", SKIP_MOCK_TESTS, err) 17 | } 18 | if skip { 19 | t.Skip("The test will not run without a mock Prism server running against your OpenAPI spec") 20 | return false 21 | } 22 | t.Errorf("The test will not run without a mock Prism server running against your OpenAPI spec. You can set the environment variable %s to true to skip running any tests that require the mock server", SKIP_MOCK_TESTS) 23 | return false 24 | } 25 | } 26 | return true 27 | } 28 | -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/internal/apiquery/tag.go: -------------------------------------------------------------------------------- 1 | package apiquery 2 | 3 | import ( 4 | "reflect" 5 | "strings" 6 | ) 7 | 8 | const queryStructTag = "query" 9 | const formatStructTag = "format" 10 | 11 | type parsedStructTag struct { 12 | name string 13 | omitempty bool 14 | inline bool 15 | } 16 | 17 | func parseQueryStructTag(field reflect.StructField) (tag parsedStructTag, ok bool) { 18 | raw, ok := field.Tag.Lookup(queryStructTag) 19 | if !ok { 20 | return 21 | } 22 | parts := strings.Split(raw, ",") 23 | if len(parts) == 0 { 24 | return tag, false 25 | } 26 | tag.name = parts[0] 27 | for _, part := range parts[1:] { 28 | switch part { 29 | case "omitempty": 30 | tag.omitempty = true 31 | case "inline": 32 | tag.inline = true 33 | } 34 | } 35 | return 36 | } 37 | 38 | func parseFormatStructTag(field reflect.StructField) (format string, ok bool) { 39 | format, ok = field.Tag.Lookup(formatStructTag) 40 | return 41 | } 42 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/cli/cmd/debug/index.ts: -------------------------------------------------------------------------------- 1 | import { bootstrap } from "../../bootstrap" 2 | import { cmd } from "../cmd" 3 | import { FileCommand } from "./file" 4 | import { LSPCommand } from "./lsp" 5 | import { RipgrepCommand } from "./ripgrep" 6 | import { ScrapCommand } from "./scrap" 7 | import { SnapshotCommand } from "./snapshot" 8 | 9 | export const DebugCommand = cmd({ 10 | command: "debug", 11 | builder: (yargs) => 12 | yargs 13 | .command(LSPCommand) 14 | .command(RipgrepCommand) 15 | .command(FileCommand) 16 | .command(ScrapCommand) 17 | .command(SnapshotCommand) 18 | .command({ 19 | command: "wait", 20 | async handler() { 21 | await bootstrap({ cwd: process.cwd() }, async () => { 22 | await new Promise((resolve) => setTimeout(resolve, 1_000 * 60 * 60 * 24)) 23 | }) 24 | }, 25 | }) 26 | .demandCommand(), 27 | async handler() {}, 28 | }) 29 | -------------------------------------------------------------------------------- /npm/jest.browser.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | testEnvironment: 'jsdom', 4 | roots: ['/src', '/tests'], 5 | testMatch: [ 6 | '**/__tests__/**/*.browser.ts', 7 | '**/?(*.)+(browser.spec|browser.test).ts' 8 | ], 9 | transform: { 10 | '^.+\.ts$': 'ts-loader' 11 | }, 12 | moduleNameMapping: { 13 | '^@/(.*)$': '/src/$1' 14 | }, 15 | setupFilesAfterEnv: ['/tests/browser.setup.ts'], 16 | collectCoverageFrom: [ 17 | 'src/**/*.ts', 18 | '!src/**/*.d.ts', 19 | '!src/**/*.test.ts', 20 | '!src/**/*.spec.ts' 21 | ], 22 | coverageDirectory: 'coverage-browser', 23 | coverageReporters: ['text', 'lcov', 'html'], 24 | verbose: true, 25 | testEnvironmentOptions: { 26 | url: 'https://localhost' 27 | }, 28 | globals: { 29 | 'ts-jest': { 30 | useESM: true 31 | } 32 | }, 33 | // Mock WebAssembly for tests 34 | setupFiles: ['/tests/wasm.mock.ts'] 35 | }; -------------------------------------------------------------------------------- /opencode/packages/opencode/src/tool/tool.ts: -------------------------------------------------------------------------------- 1 | import type { StandardSchemaV1 } from "@standard-schema/spec" 2 | 3 | export namespace Tool { 4 | interface Metadata { 5 | [key: string]: any 6 | } 7 | export type Context = { 8 | sessionID: string 9 | messageID: string 10 | abort: AbortSignal 11 | metadata(input: { title?: string; metadata?: M }): void 12 | } 13 | export interface Info { 14 | id: string 15 | description: string 16 | parameters: Parameters 17 | execute( 18 | args: StandardSchemaV1.InferOutput, 19 | ctx: Context, 20 | ): Promise<{ 21 | title: string 22 | metadata: M 23 | output: string 24 | }> 25 | } 26 | 27 | export function define( 28 | input: Info, 29 | ): Info { 30 | return input 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /opencode/packages/web/src/assets/logo-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /opencode/packages/web/src/components/share/content-error.tsx: -------------------------------------------------------------------------------- 1 | import style from "./content-error.module.css" 2 | import { type JSX, createSignal } from "solid-js" 3 | import { createOverflow } from "./common" 4 | 5 | interface Props extends JSX.HTMLAttributes { 6 | expand?: boolean 7 | } 8 | export function ContentError(props: Props) { 9 | const [expanded, setExpanded] = createSignal(false) 10 | const overflow = createOverflow() 11 | 12 | return ( 13 |
17 |
18 | {props.children} 19 |
20 | {((!props.expand && overflow.status) || expanded()) && ( 21 | 28 | )} 29 |
30 | ) 31 | } 32 | -------------------------------------------------------------------------------- /opencode/packages/web/src/assets/logo-light.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/tool/todoread.txt: -------------------------------------------------------------------------------- 1 | Use this tool to read the current to-do list for the session. This tool should be used proactively and frequently to ensure that you are aware of 2 | the status of the current task list. You should make use of this tool as often as possible, especially in the following situations: 3 | - At the beginning of conversations to see what's pending 4 | - Before starting new tasks to prioritize work 5 | - When the user asks about previous tasks or plans 6 | - Whenever you're uncertain about what to do next 7 | - After completing tasks to update your understanding of remaining work 8 | - After every few messages to ensure you're on track 9 | 10 | Usage: 11 | - This tool takes in no parameters. So leave the input blank or empty. DO NOT include a dummy object, placeholder string or a key like "input" or "empty". LEAVE IT BLANK. 12 | - Returns a list of todo items with their status, priority, and content 13 | - Use this information to track progress and plan next steps 14 | - If no todos exist yet, an empty list will be returned 15 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/tool/lsp-diagnostics.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod" 2 | import { Tool } from "./tool" 3 | import path from "path" 4 | import { LSP } from "../lsp" 5 | import { App } from "../app/app" 6 | import DESCRIPTION from "./lsp-diagnostics.txt" 7 | 8 | export const LspDiagnosticTool = Tool.define({ 9 | id: "lsp_diagnostics", 10 | description: DESCRIPTION, 11 | parameters: z.object({ 12 | path: z.string().describe("The path to the file to get diagnostics."), 13 | }), 14 | execute: async (args) => { 15 | const app = App.info() 16 | const normalized = path.isAbsolute(args.path) ? args.path : path.join(app.path.cwd, args.path) 17 | await LSP.touchFile(normalized, true) 18 | const diagnostics = await LSP.diagnostics() 19 | const file = diagnostics[normalized] 20 | return { 21 | title: path.relative(app.path.root, normalized), 22 | metadata: { 23 | diagnostics, 24 | }, 25 | output: file?.length ? file.map(LSP.Diagnostic.pretty).join("\n") : "No errors found", 26 | } 27 | }, 28 | }) 29 | -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/scripts/mock: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | if [[ -n "$1" && "$1" != '--'* ]]; then 8 | URL="$1" 9 | shift 10 | else 11 | URL="$(grep 'openapi_spec_url' .stats.yml | cut -d' ' -f2)" 12 | fi 13 | 14 | # Check if the URL is empty 15 | if [ -z "$URL" ]; then 16 | echo "Error: No OpenAPI spec path/url provided or found in .stats.yml" 17 | exit 1 18 | fi 19 | 20 | echo "==> Starting mock server with URL ${URL}" 21 | 22 | # Run prism mock on the given spec 23 | if [ "$1" == "--daemon" ]; then 24 | npm exec --package=@stainless-api/prism-cli@5.8.5 -- prism mock "$URL" &> .prism.log & 25 | 26 | # Wait for server to come online 27 | echo -n "Waiting for server" 28 | while ! grep -q "✖ fatal\|Prism is listening" ".prism.log" ; do 29 | echo -n "." 30 | sleep 0.1 31 | done 32 | 33 | if grep -q "✖ fatal" ".prism.log"; then 34 | cat .prism.log 35 | exit 1 36 | fi 37 | 38 | echo 39 | else 40 | npm exec --package=@stainless-api/prism-cli@5.8.5 -- prism mock "$URL" 41 | fi 42 | -------------------------------------------------------------------------------- /crates/code-mesh-core/src/features.rs: -------------------------------------------------------------------------------- 1 | //! Feature flags for Code Mesh Core 2 | 3 | /// Whether compression support is available 4 | pub const HAS_COMPRESSION: bool = cfg!(feature = "compression"); 5 | 6 | /// Whether file watching support is available 7 | pub const HAS_FILE_WATCHING: bool = cfg!(feature = "file-watching"); 8 | 9 | /// Whether advanced crypto support is available 10 | pub const HAS_ADVANCED_CRYPTO: bool = cfg!(feature = "crypto"); 11 | 12 | /// Whether tokio runtime is available 13 | pub const HAS_TOKIO: bool = cfg!(feature = "native"); 14 | 15 | /// Whether WASM support is available 16 | pub const HAS_WASM: bool = cfg!(feature = "wasm"); 17 | 18 | /// Whether web support is available 19 | pub const HAS_WEB: bool = cfg!(feature = "web"); 20 | 21 | /// Whether OpenAI support is available 22 | pub const HAS_OPENAI: bool = cfg!(feature = "openai"); 23 | 24 | /// Whether Anthropic support is available 25 | pub const HAS_ANTHROPIC: bool = cfg!(feature = "anthropic"); 26 | 27 | /// Whether Mistral support is available 28 | pub const HAS_MISTRAL: bool = cfg!(feature = "mistral"); -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/internal/apijson/tag.go: -------------------------------------------------------------------------------- 1 | package apijson 2 | 3 | import ( 4 | "reflect" 5 | "strings" 6 | ) 7 | 8 | const jsonStructTag = "json" 9 | const formatStructTag = "format" 10 | 11 | type parsedStructTag struct { 12 | name string 13 | required bool 14 | extras bool 15 | metadata bool 16 | inline bool 17 | } 18 | 19 | func parseJSONStructTag(field reflect.StructField) (tag parsedStructTag, ok bool) { 20 | raw, ok := field.Tag.Lookup(jsonStructTag) 21 | if !ok { 22 | return 23 | } 24 | parts := strings.Split(raw, ",") 25 | if len(parts) == 0 { 26 | return tag, false 27 | } 28 | tag.name = parts[0] 29 | for _, part := range parts[1:] { 30 | switch part { 31 | case "required": 32 | tag.required = true 33 | case "extras": 34 | tag.extras = true 35 | case "metadata": 36 | tag.metadata = true 37 | case "inline": 38 | tag.inline = true 39 | } 40 | } 41 | return 42 | } 43 | 44 | func parseFormatStructTag(field reflect.StructField) (format string, ok bool) { 45 | format, ok = field.Tag.Lookup(formatStructTag) 46 | return 47 | } 48 | -------------------------------------------------------------------------------- /opencode/packages/web/src/components/share/copy-button.tsx: -------------------------------------------------------------------------------- 1 | import { createSignal } from "solid-js" 2 | import { IconClipboard, IconCheckCircle } from "../icons" 3 | import styles from "./copy-button.module.css" 4 | 5 | interface CopyButtonProps { 6 | text: string 7 | } 8 | 9 | export function CopyButton(props: CopyButtonProps) { 10 | const [copied, setCopied] = createSignal(false) 11 | 12 | function handleCopyClick() { 13 | if (props.text) { 14 | navigator.clipboard.writeText(props.text) 15 | .catch((err) => console.error("Copy failed", err)) 16 | 17 | setCopied(true) 18 | setTimeout(() => setCopied(false), 2000) 19 | } 20 | } 21 | 22 | return ( 23 |
24 | 34 |
35 | ) 36 | } 37 | -------------------------------------------------------------------------------- /opencode/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/package.json", 3 | "name": "opencode", 4 | "private": true, 5 | "type": "module", 6 | "packageManager": "bun@1.2.14", 7 | "scripts": { 8 | "dev": "bun run packages/opencode/src/index.ts", 9 | "typecheck": "bun run --filter='*' typecheck", 10 | "stainless": "./scripts/stainless", 11 | "postinstall": "./scripts/hooks" 12 | }, 13 | "workspaces": { 14 | "packages": [ 15 | "packages/*" 16 | ], 17 | "catalog": { 18 | "typescript": "5.8.2", 19 | "@types/node": "22.13.9", 20 | "zod": "3.25.49", 21 | "ai": "5.0.0-beta.18" 22 | } 23 | }, 24 | "devDependencies": { 25 | "prettier": "3.5.3", 26 | "sst": "3.17.8" 27 | }, 28 | "repository": { 29 | "type": "git", 30 | "url": "https://github.com/sst/opencode" 31 | }, 32 | "license": "MIT", 33 | "prettier": { 34 | "semi": false, 35 | "printWidth": 120 36 | }, 37 | "trustedDependencies": [ 38 | "esbuild", 39 | "protobufjs", 40 | "sharp" 41 | ], 42 | "patchedDependencies": {} 43 | } 44 | -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/internal/apiform/tag.go: -------------------------------------------------------------------------------- 1 | package apiform 2 | 3 | import ( 4 | "reflect" 5 | "strings" 6 | ) 7 | 8 | const jsonStructTag = "json" 9 | const formStructTag = "form" 10 | const formatStructTag = "format" 11 | 12 | type parsedStructTag struct { 13 | name string 14 | required bool 15 | extras bool 16 | metadata bool 17 | } 18 | 19 | func parseFormStructTag(field reflect.StructField) (tag parsedStructTag, ok bool) { 20 | raw, ok := field.Tag.Lookup(formStructTag) 21 | if !ok { 22 | raw, ok = field.Tag.Lookup(jsonStructTag) 23 | } 24 | if !ok { 25 | return 26 | } 27 | parts := strings.Split(raw, ",") 28 | if len(parts) == 0 { 29 | return tag, false 30 | } 31 | tag.name = parts[0] 32 | for _, part := range parts[1:] { 33 | switch part { 34 | case "required": 35 | tag.required = true 36 | case "extras": 37 | tag.extras = true 38 | case "metadata": 39 | tag.metadata = true 40 | } 41 | } 42 | return 43 | } 44 | 45 | func parseFormatStructTag(field reflect.StructField) (format string, ok bool) { 46 | format, ok = field.Tag.Lookup(formatStructTag) 47 | return 48 | } 49 | -------------------------------------------------------------------------------- /tarpaulin.toml: -------------------------------------------------------------------------------- 1 | # Tarpaulin configuration for code coverage 2 | 3 | [report] 4 | # Output formats 5 | out = ["Html", "Xml", "Json"] 6 | 7 | # Output directory 8 | output-dir = "coverage" 9 | 10 | # Include all features 11 | all-features = true 12 | 13 | # Timeout for each test (in seconds) 14 | timeout = 120 15 | 16 | # Follow symbolic links 17 | follow-exec = true 18 | 19 | # Run tests for the whole workspace 20 | workspace = true 21 | 22 | # Exclude files from coverage 23 | exclude-files = [ 24 | "tests/*", 25 | "benches/*", 26 | "examples/*", 27 | "target/*", 28 | "**/main.rs", 29 | "**/*test*.rs", 30 | "**/*mock*.rs" 31 | ] 32 | 33 | # Coverage threshold (percentage) 34 | fail-under = 80 35 | 36 | # Generate coverage for all packages 37 | all = true 38 | 39 | # Include line coverage 40 | line = true 41 | 42 | # Include branch coverage 43 | branch = true 44 | 45 | # Count hits for each line 46 | count = true 47 | 48 | # Verbose output 49 | verbose = true 50 | 51 | # Engine to use 52 | engine = "llvm" 53 | 54 | # Additional arguments for tests 55 | args = [ 56 | "--test-threads=1" 57 | ] -------------------------------------------------------------------------------- /opencode/packages/opencode/src/cli/cmd/debug/file.ts: -------------------------------------------------------------------------------- 1 | import { File } from "../../../file" 2 | import { bootstrap } from "../../bootstrap" 3 | import { cmd } from "../cmd" 4 | 5 | const FileReadCommand = cmd({ 6 | command: "read ", 7 | builder: (yargs) => 8 | yargs.positional("path", { 9 | type: "string", 10 | demandOption: true, 11 | description: "File path to read", 12 | }), 13 | async handler(args) { 14 | await bootstrap({ cwd: process.cwd() }, async () => { 15 | const content = await File.read(args.path) 16 | console.log(content) 17 | }) 18 | }, 19 | }) 20 | 21 | const FileStatusCommand = cmd({ 22 | command: "status", 23 | builder: (yargs) => yargs, 24 | async handler() { 25 | await bootstrap({ cwd: process.cwd() }, async () => { 26 | const status = await File.status() 27 | console.log(JSON.stringify(status, null, 2)) 28 | }) 29 | }, 30 | }) 31 | 32 | export const FileCommand = cmd({ 33 | command: "file", 34 | builder: (yargs) => yargs.command(FileReadCommand).command(FileStatusCommand).demandCommand(), 35 | async handler() {}, 36 | }) 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 rUv 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /opencode/packages/web/src/components/share/content-text.tsx: -------------------------------------------------------------------------------- 1 | import style from "./content-text.module.css" 2 | import { createSignal } from "solid-js" 3 | import { createOverflow } from "./common" 4 | 5 | interface Props { 6 | text: string 7 | expand?: boolean 8 | compact?: boolean 9 | } 10 | export function ContentText(props: Props) { 11 | const [expanded, setExpanded] = createSignal(false) 12 | const overflow = createOverflow() 13 | 14 | return ( 15 |
20 |
21 |         {props.text}
22 |       
23 | {((!props.expand && overflow.status) || expanded()) && ( 24 | 32 | )} 33 |
34 | ) 35 | } 36 | -------------------------------------------------------------------------------- /opencode/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 opencode 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /opencode/packages/web/src/components/share/content-code.tsx: -------------------------------------------------------------------------------- 1 | import { codeToHtml, bundledLanguages } from "shiki" 2 | import { createResource, Suspense } from "solid-js" 3 | import { transformerNotationDiff } from "@shikijs/transformers" 4 | import style from "./content-code.module.css" 5 | 6 | interface Props { 7 | code: string 8 | lang?: string 9 | flush?: boolean 10 | } 11 | export function ContentCode(props: Props) { 12 | const [html] = createResource( 13 | () => [props.code, props.lang], 14 | async ([code, lang]) => { 15 | // TODO: For testing delays 16 | // await new Promise((resolve) => setTimeout(resolve, 3000)) 17 | return (await codeToHtml(code || "", { 18 | lang: lang && lang in bundledLanguages ? lang : "text", 19 | themes: { 20 | light: "github-light", 21 | dark: "github-dark", 22 | }, 23 | transformers: [transformerNotationDiff()], 24 | })) as string 25 | }, 26 | ) 27 | return ( 28 | 29 |
30 | 31 | ) 32 | } 33 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/tool/edit.txt: -------------------------------------------------------------------------------- 1 | Performs exact string replacements in files. 2 | 3 | Usage: 4 | - You must use your `Read` tool at least once in the conversation before editing. This tool will error if you attempt an edit without reading the file. 5 | - When editing text from Read tool output, ensure you preserve the exact indentation (tabs/spaces) as it appears AFTER the line number prefix. The line number prefix format is: spaces + line number + tab. Everything after that tab is the actual file content to match. Never include any part of the line number prefix in the oldString or newString. 6 | - ALWAYS prefer editing existing files in the codebase. NEVER write new files unless explicitly required. 7 | - Only use emojis if the user explicitly requests it. Avoid adding emojis to files unless asked. 8 | - The edit will FAIL if `oldString` is not unique in the file. Either provide a larger string with more surrounding context to make it unique or use `replaceAll` to change every instance of `oldString`. 9 | - Use `replaceAll` for replacing and renaming strings across the file. This parameter is useful if you want to rename a variable for instance. 10 | -------------------------------------------------------------------------------- /npm/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "lib": ["ES2020", "DOM", "DOM.Iterable", "WebWorker"], 5 | "module": "ESNext", 6 | "moduleResolution": "node", 7 | "allowSyntheticDefaultImports": true, 8 | "esModuleInterop": true, 9 | "allowJs": true, 10 | "declaration": true, 11 | "declarationMap": true, 12 | "sourceMap": true, 13 | "outDir": "./dist", 14 | "rootDir": "./src", 15 | "strict": true, 16 | "noUnusedLocals": false, 17 | "noUnusedParameters": false, 18 | "noImplicitReturns": true, 19 | "noFallthroughCasesInSwitch": true, 20 | "skipLibCheck": true, 21 | "forceConsistentCasingInFileNames": true, 22 | "resolveJsonModule": true, 23 | "isolatedModules": true, 24 | "incremental": true, 25 | "experimentalDecorators": true, 26 | "emitDecoratorMetadata": true, 27 | "types": ["node", "jest"] 28 | }, 29 | "include": [ 30 | "src/**/*", 31 | "wasm/**/*.d.ts" 32 | ], 33 | "exclude": [ 34 | "node_modules", 35 | "dist", 36 | "**/*.test.ts", 37 | "**/*.spec.ts" 38 | ], 39 | "ts-node": { 40 | "esm": true 41 | } 42 | } -------------------------------------------------------------------------------- /opencode/packages/opencode/src/tool/lsp-hover.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod" 2 | import { Tool } from "./tool" 3 | import path from "path" 4 | import { LSP } from "../lsp" 5 | import { App } from "../app/app" 6 | import DESCRIPTION from "./lsp-hover.txt" 7 | 8 | export const LspHoverTool = Tool.define({ 9 | id: "lsp_hover", 10 | description: DESCRIPTION, 11 | parameters: z.object({ 12 | file: z.string().describe("The path to the file to get diagnostics."), 13 | line: z.number().describe("The line number to get diagnostics."), 14 | character: z.number().describe("The character number to get diagnostics."), 15 | }), 16 | execute: async (args) => { 17 | const app = App.info() 18 | const file = path.isAbsolute(args.file) ? args.file : path.join(app.path.cwd, args.file) 19 | await LSP.touchFile(file, true) 20 | const result = await LSP.hover({ 21 | ...args, 22 | file, 23 | }) 24 | 25 | return { 26 | title: path.relative(app.path.root, file) + ":" + args.line + ":" + args.character, 27 | metadata: { 28 | result, 29 | }, 30 | output: JSON.stringify(result, null, 2), 31 | } 32 | }, 33 | }) 34 | -------------------------------------------------------------------------------- /opencode/packages/tui/internal/util/util.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "log/slog" 5 | "os" 6 | "strings" 7 | "time" 8 | 9 | tea "github.com/charmbracelet/bubbletea/v2" 10 | ) 11 | 12 | func CmdHandler(msg tea.Msg) tea.Cmd { 13 | return func() tea.Msg { 14 | return msg 15 | } 16 | } 17 | 18 | func Clamp(v, low, high int) int { 19 | // Swap if needed to ensure low <= high 20 | if high < low { 21 | low, high = high, low 22 | } 23 | return min(high, max(low, v)) 24 | } 25 | 26 | func IsWsl() bool { 27 | // Check for WSL environment variables 28 | if os.Getenv("WSL_DISTRO_NAME") != "" { 29 | return true 30 | } 31 | 32 | // Check /proc/version for WSL signature 33 | if data, err := os.ReadFile("/proc/version"); err == nil { 34 | version := strings.ToLower(string(data)) 35 | return strings.Contains(version, "microsoft") || strings.Contains(version, "wsl") 36 | } 37 | 38 | return false 39 | } 40 | 41 | func Measure(tag string) func(...any) { 42 | startTime := time.Now() 43 | return func(tags ...any) { 44 | args := append([]any{"timeTakenMs", time.Since(startTime).Milliseconds()}, tags...) 45 | slog.Debug(tag, args...) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/internal/apiquery/query.go: -------------------------------------------------------------------------------- 1 | package apiquery 2 | 3 | import ( 4 | "net/url" 5 | "reflect" 6 | "time" 7 | ) 8 | 9 | func MarshalWithSettings(value interface{}, settings QuerySettings) url.Values { 10 | e := encoder{time.RFC3339, true, settings} 11 | kv := url.Values{} 12 | val := reflect.ValueOf(value) 13 | if !val.IsValid() { 14 | return nil 15 | } 16 | typ := val.Type() 17 | for _, pair := range e.typeEncoder(typ)("", val) { 18 | kv.Add(pair.key, pair.value) 19 | } 20 | return kv 21 | } 22 | 23 | func Marshal(value interface{}) url.Values { 24 | return MarshalWithSettings(value, QuerySettings{}) 25 | } 26 | 27 | type Queryer interface { 28 | URLQuery() url.Values 29 | } 30 | 31 | type QuerySettings struct { 32 | NestedFormat NestedQueryFormat 33 | ArrayFormat ArrayQueryFormat 34 | } 35 | 36 | type NestedQueryFormat int 37 | 38 | const ( 39 | NestedQueryFormatBrackets NestedQueryFormat = iota 40 | NestedQueryFormatDots 41 | ) 42 | 43 | type ArrayQueryFormat int 44 | 45 | const ( 46 | ArrayQueryFormatComma ArrayQueryFormat = iota 47 | ArrayQueryFormatRepeat 48 | ArrayQueryFormatIndices 49 | ArrayQueryFormatBrackets 50 | ) 51 | -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/internal/apijson/registry.go: -------------------------------------------------------------------------------- 1 | package apijson 2 | 3 | import ( 4 | "reflect" 5 | 6 | "github.com/tidwall/gjson" 7 | ) 8 | 9 | type UnionVariant struct { 10 | TypeFilter gjson.Type 11 | DiscriminatorValue interface{} 12 | Type reflect.Type 13 | } 14 | 15 | var unionRegistry = map[reflect.Type]unionEntry{} 16 | var unionVariants = map[reflect.Type]interface{}{} 17 | 18 | type unionEntry struct { 19 | discriminatorKey string 20 | variants []UnionVariant 21 | } 22 | 23 | func RegisterUnion(typ reflect.Type, discriminator string, variants ...UnionVariant) { 24 | unionRegistry[typ] = unionEntry{ 25 | discriminatorKey: discriminator, 26 | variants: variants, 27 | } 28 | for _, variant := range variants { 29 | unionVariants[variant.Type] = typ 30 | } 31 | } 32 | 33 | // Useful to wrap a union type to force it to use [apijson.UnmarshalJSON] since you cannot define an 34 | // UnmarshalJSON function on the interface itself. 35 | type UnionUnmarshaler[T any] struct { 36 | Value T 37 | } 38 | 39 | func (c *UnionUnmarshaler[T]) UnmarshalJSON(buf []byte) error { 40 | return UnmarshalRoot(buf, &c.Value) 41 | } 42 | -------------------------------------------------------------------------------- /opencode/scripts/release: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Parse command line arguments 4 | minor=false 5 | while [ "$#" -gt 0 ]; do 6 | case "$1" in 7 | --minor) minor=true; shift 1;; 8 | *) echo "Unknown parameter: $1"; exit 1;; 9 | esac 10 | done 11 | 12 | git fetch --force --tags 13 | 14 | # Get the latest Git tag 15 | latest_tag=$(git tag --sort=committerdate | grep -E '[0-9]' | tail -1) 16 | 17 | # If there is no tag, exit the script 18 | if [ -z "$latest_tag" ]; then 19 | echo "No tags found" 20 | exit 1 21 | fi 22 | 23 | echo "Latest tag: $latest_tag" 24 | 25 | # Split the tag into major, minor, and patch numbers 26 | IFS='.' read -ra VERSION <<< "$latest_tag" 27 | 28 | if [ "$minor" = true ]; then 29 | # Increment the minor version and reset patch to 0 30 | minor_number=${VERSION[1]} 31 | let "minor_number++" 32 | new_version="${VERSION[0]}.$minor_number.0" 33 | else 34 | # Increment the patch version 35 | patch_number=${VERSION[2]} 36 | let "patch_number++" 37 | new_version="${VERSION[0]}.${VERSION[1]}.$patch_number" 38 | fi 39 | 40 | echo "New version: $new_version" 41 | 42 | git tag $new_version 43 | git push --tags 44 | -------------------------------------------------------------------------------- /crates/code-mesh-core/src/error.rs: -------------------------------------------------------------------------------- 1 | //! Error types for Code Mesh Core 2 | 3 | use thiserror::Error; 4 | 5 | #[derive(Error, Debug)] 6 | pub enum Error { 7 | #[error("Provider error: {0}")] 8 | Provider(String), 9 | 10 | #[error("Model not found: {0}")] 11 | ModelNotFound(String), 12 | 13 | #[error("Authentication failed: {0}")] 14 | AuthenticationFailed(String), 15 | 16 | #[error("Tool execution error: {0}")] 17 | ToolExecutionError(String), 18 | 19 | #[error("Storage error: {0}")] 20 | Storage(#[from] crate::storage::StorageError), 21 | 22 | #[error("Session error: {0}")] 23 | Session(String), 24 | 25 | #[error("Network error: {0}")] 26 | Network(#[from] reqwest::Error), 27 | 28 | #[error("Serialization error: {0}")] 29 | Serialization(#[from] serde_json::Error), 30 | 31 | #[error("IO error: {0}")] 32 | Io(#[from] std::io::Error), 33 | 34 | #[error("Parse error: {0}")] 35 | ParseInt(#[from] std::num::ParseIntError), 36 | 37 | #[error("Other error: {0}")] 38 | Other(#[from] anyhow::Error), 39 | } 40 | 41 | pub type Result = std::result::Result; -------------------------------------------------------------------------------- /opencode/packages/web/src/content/docs/docs/lsp-servers.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: LSP servers 3 | --- 4 | 5 | opencode integrates with _Language Server Protocol_, or LSP to improve how the LLM interacts with your codebase. 6 | 7 | LSP servers for different languages give the LLM: 8 | 9 | - **Diagnostics**: These include things like errors and lint warnings. So the LLM can generate code that has fewer mistakes without having to run the code. 10 | - **Quick actions**: The LSP can allow the LLM to better navigate the codebase through features like _go-to-definition_ and _find references_. 11 | 12 | ## Auto-detection 13 | 14 | By default, opencode will **automatically detect** the languages used in your project and add the right LSP servers. 15 | 16 | ## Manual configuration 17 | 18 | You can also manually configure LSP servers by adding them under the `lsp` section in your opencode config. 19 | 20 | ```json title="opencode.json" 21 | { 22 | "lsp": { 23 | "go": { 24 | "disabled": false, 25 | "command": "gopls" 26 | }, 27 | "typescript": { 28 | "disabled": false, 29 | "command": "typescript-language-server", 30 | "args": ["--stdio"] 31 | } 32 | } 33 | } 34 | ``` 35 | -------------------------------------------------------------------------------- /test_stored_credentials.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "=== Testing Code Mesh Persistent Storage ===" 4 | echo 5 | 6 | # Create auth.json with a test API key 7 | mkdir -p ~/.code-mesh 8 | cat > ~/.code-mesh/auth.json << 'EOF' 9 | { 10 | "credentials": { 11 | "anthropic": { 12 | "type": "apikey", 13 | "key": "sk-ant-test-key-12345" 14 | } 15 | } 16 | } 17 | EOF 18 | 19 | echo "1. Created test credentials in ~/.code-mesh/auth.json" 20 | echo 21 | 22 | echo "2. Checking auth status:" 23 | cargo run --bin code-mesh -- auth list 24 | echo 25 | 26 | echo "3. Testing run command with stored credentials:" 27 | echo " This should fail with 'invalid API key' but show that credentials are being used" 28 | cargo run --bin code-mesh -- run 'What is 2+2?' 2>&1 | head -20 29 | echo 30 | 31 | echo "4. Cleaning up test credentials" 32 | rm ~/.code-mesh/auth.json 33 | 34 | echo "=== Test Complete ===" 35 | echo 36 | echo "Summary:" 37 | echo "✅ Persistent storage is working correctly" 38 | echo "✅ Credentials are loaded from ~/.code-mesh/auth.json" 39 | echo "✅ Provider registry discovers and uses stored credentials" 40 | echo "✅ The error 'invalid x-api-key' proves the stored key is being sent to the API" -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/option/middleware.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package option 4 | 5 | import ( 6 | "log" 7 | "net/http" 8 | "net/http/httputil" 9 | ) 10 | 11 | // WithDebugLog logs the HTTP request and response content. 12 | // If the logger parameter is nil, it uses the default logger. 13 | // 14 | // WithDebugLog is for debugging and development purposes only. 15 | // It should not be used in production code. The behavior and interface 16 | // of WithDebugLog is not guaranteed to be stable. 17 | func WithDebugLog(logger *log.Logger) RequestOption { 18 | return WithMiddleware(func(req *http.Request, nxt MiddlewareNext) (*http.Response, error) { 19 | if logger == nil { 20 | logger = log.Default() 21 | } 22 | 23 | if reqBytes, err := httputil.DumpRequest(req, true); err == nil { 24 | logger.Printf("Request Content:\n%s\n", reqBytes) 25 | } 26 | 27 | resp, err := nxt(req) 28 | if err != nil { 29 | return resp, err 30 | } 31 | 32 | if respBytes, err := httputil.DumpResponse(resp, true); err == nil { 33 | logger.Printf("Response Content:\n%s\n", respBytes) 34 | } 35 | 36 | return resp, err 37 | }) 38 | } 39 | -------------------------------------------------------------------------------- /opencode/packages/web/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@opencode/web", 3 | "type": "module", 4 | "version": "0.0.1", 5 | "scripts": { 6 | "dev": "astro dev", 7 | "dev:remote": "sst shell --stage=dev --target=Web astro dev", 8 | "start": "astro dev", 9 | "build": "astro build", 10 | "preview": "astro preview", 11 | "astro": "astro" 12 | }, 13 | "dependencies": { 14 | "@astrojs/cloudflare": "^12.5.4", 15 | "@astrojs/markdown-remark": "6.3.1", 16 | "@astrojs/solid-js": "5.1.0", 17 | "@astrojs/starlight": "0.34.3", 18 | "@fontsource/ibm-plex-mono": "5.2.5", 19 | "@shikijs/transformers": "3.4.2", 20 | "@types/luxon": "3.6.2", 21 | "ai": "catalog:", 22 | "astro": "5.7.13", 23 | "diff": "8.0.2", 24 | "js-base64": "3.7.7", 25 | "lang-map": "0.4.0", 26 | "luxon": "3.6.1", 27 | "marked": "15.0.12", 28 | "marked-shiki": "1.2.0", 29 | "rehype-autolink-headings": "7.1.0", 30 | "sharp": "0.32.5", 31 | "shiki": "3.4.2", 32 | "solid-js": "1.9.7", 33 | "toolbeam-docs-theme": "0.4.3" 34 | }, 35 | "devDependencies": { 36 | "opencode": "workspace:*", 37 | "@types/node": "catalog:", 38 | "typescript": "catalog:" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/global/index.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs/promises" 2 | import { xdgData, xdgCache, xdgConfig, xdgState } from "xdg-basedir" 3 | import path from "path" 4 | 5 | const app = "opencode" 6 | 7 | const data = path.join(xdgData!, app) 8 | const cache = path.join(xdgCache!, app) 9 | const config = path.join(xdgConfig!, app) 10 | const state = path.join(xdgState!, app) 11 | 12 | export namespace Global { 13 | export const Path = { 14 | data, 15 | bin: path.join(data, "bin"), 16 | providers: path.join(config, "providers"), 17 | cache, 18 | config, 19 | state, 20 | } as const 21 | } 22 | 23 | await Promise.all([ 24 | fs.mkdir(Global.Path.data, { recursive: true }), 25 | fs.mkdir(Global.Path.config, { recursive: true }), 26 | fs.mkdir(Global.Path.providers, { recursive: true }), 27 | fs.mkdir(Global.Path.state, { recursive: true }), 28 | ]) 29 | 30 | const CACHE_VERSION = "2" 31 | 32 | const version = await Bun.file(path.join(Global.Path.cache, "version")) 33 | .text() 34 | .catch(() => "0") 35 | 36 | if (version !== CACHE_VERSION) { 37 | await fs.rm(Global.Path.cache, { recursive: true, force: true }) 38 | await Bun.file(path.join(Global.Path.cache, "version")).write(CACHE_VERSION) 39 | } 40 | -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/internal/apijson/field.go: -------------------------------------------------------------------------------- 1 | package apijson 2 | 3 | import "reflect" 4 | 5 | type status uint8 6 | 7 | const ( 8 | missing status = iota 9 | null 10 | invalid 11 | valid 12 | ) 13 | 14 | type Field struct { 15 | raw string 16 | status status 17 | } 18 | 19 | // Returns true if the field is explicitly `null` _or_ if it is not present at all (ie, missing). 20 | // To check if the field's key is present in the JSON with an explicit null value, 21 | // you must check `f.IsNull() && !f.IsMissing()`. 22 | func (j Field) IsNull() bool { return j.status <= null } 23 | func (j Field) IsMissing() bool { return j.status == missing } 24 | func (j Field) IsInvalid() bool { return j.status == invalid } 25 | func (j Field) Raw() string { return j.raw } 26 | 27 | func getSubField(root reflect.Value, index []int, name string) reflect.Value { 28 | strct := root.FieldByIndex(index[:len(index)-1]) 29 | if !strct.IsValid() { 30 | panic("couldn't find encapsulating struct for field " + name) 31 | } 32 | meta := strct.FieldByName("JSON") 33 | if !meta.IsValid() { 34 | return reflect.Value{} 35 | } 36 | field := meta.FieldByName(name) 37 | if !field.IsValid() { 38 | return reflect.Value{} 39 | } 40 | return field 41 | } 42 | -------------------------------------------------------------------------------- /opencode/packages/opencode/script/schema.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bun 2 | 3 | import "zod-openapi/extend" 4 | import { Config } from "../src/config/config" 5 | import { zodToJsonSchema } from "zod-to-json-schema" 6 | 7 | const file = process.argv[2] 8 | 9 | const result = zodToJsonSchema(Config.Info, { 10 | /** 11 | * We'll use the `default` values of the field as the only value in `examples`. 12 | * This will ensure no docs are needed to be read, as the configuration is 13 | * self-documenting. 14 | * 15 | * See https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-00#rfc.section.9.5 16 | */ 17 | postProcess(jsonSchema) { 18 | const schema = jsonSchema as typeof jsonSchema & { 19 | examples?: unknown[] 20 | } 21 | if (schema && typeof schema === "object" && "type" in schema && schema.type === "string" && schema?.default) { 22 | if (!schema.examples) { 23 | schema.examples = [schema.default] 24 | } 25 | 26 | schema.description = [schema.description || "", `default: \`${schema.default}\``] 27 | .filter(Boolean) 28 | .join("\n\n") 29 | .trim() 30 | } 31 | 32 | return jsonSchema 33 | }, 34 | }) 35 | await Bun.write(file, JSON.stringify(result, null, 2)) 36 | -------------------------------------------------------------------------------- /crates/code-mesh-tui/src/renderer.rs: -------------------------------------------------------------------------------- 1 | use ratatui::{ 2 | Frame, 3 | layout::Rect, 4 | widgets::Widget, 5 | }; 6 | 7 | use crate::theme::Theme; 8 | 9 | /// Renderer wrapper for consistent styling and theme application 10 | pub struct Renderer<'a> { 11 | frame: &'a mut Frame<'a>, 12 | theme: &'a dyn Theme, 13 | } 14 | 15 | impl<'a> Renderer<'a> { 16 | /// Create a new renderer 17 | pub fn new(frame: &'a mut Frame<'a>, theme: &'a dyn Theme) -> Self { 18 | Self { frame, theme } 19 | } 20 | 21 | /// Get the current theme 22 | pub fn theme(&self) -> &dyn Theme { 23 | self.theme 24 | } 25 | 26 | /// Render a widget in the specified area 27 | pub fn render_widget(&mut self, widget: W, area: Rect) { 28 | self.frame.render_widget(widget, area); 29 | } 30 | 31 | /// Render a stateful widget 32 | pub fn render_stateful_widget( 33 | &mut self, 34 | widget: W, 35 | area: Rect, 36 | state: &mut W::State 37 | ) { 38 | self.frame.render_stateful_widget(widget, area, state); 39 | } 40 | 41 | /// Get the terminal size 42 | pub fn size(&self) -> Rect { 43 | self.frame.size() 44 | } 45 | } -------------------------------------------------------------------------------- /crates/code-mesh-core/src/agent/mod.rs: -------------------------------------------------------------------------------- 1 | //! Agent orchestration for Code Mesh 2 | 3 | use async_trait::async_trait; 4 | use serde::{Deserialize, Serialize}; 5 | 6 | /// Agent trait for AI agents 7 | #[async_trait] 8 | pub trait Agent: Send + Sync { 9 | /// Get agent ID 10 | fn id(&self) -> &str; 11 | 12 | /// Get agent name 13 | fn name(&self) -> &str; 14 | 15 | /// Get agent capabilities 16 | fn capabilities(&self) -> &[String]; 17 | 18 | /// Execute a task 19 | async fn execute(&self, task: Task) -> crate::Result; 20 | } 21 | 22 | /// Task for an agent to execute 23 | #[derive(Debug, Clone, Serialize, Deserialize)] 24 | pub struct Task { 25 | pub id: String, 26 | pub description: String, 27 | pub context: serde_json::Value, 28 | pub dependencies: Vec, 29 | } 30 | 31 | /// Result of task execution 32 | #[derive(Debug, Clone, Serialize, Deserialize)] 33 | pub struct TaskResult { 34 | pub task_id: String, 35 | pub status: TaskStatus, 36 | pub output: serde_json::Value, 37 | pub error: Option, 38 | } 39 | 40 | #[derive(Debug, Clone, Copy, Serialize, Deserialize)] 41 | #[serde(rename_all = "lowercase")] 42 | pub enum TaskStatus { 43 | Pending, 44 | Running, 45 | Completed, 46 | Failed, 47 | } -------------------------------------------------------------------------------- /docs/book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | title = "Code Mesh Documentation" 3 | description = "Comprehensive documentation for Code Mesh - AI-powered coding assistant" 4 | author = "Code Mesh Contributors" 5 | language = "en" 6 | multilingual = false 7 | src = "src" 8 | 9 | [build] 10 | build-dir = "book" 11 | create-missing = true 12 | 13 | [rust] 14 | edition = "2021" 15 | 16 | [output.html] 17 | default-theme = "navy" 18 | preferred-dark-theme = "navy" 19 | curly-quotes = true 20 | mathjax-support = false 21 | copy-fonts = true 22 | additional-css = ["theme/custom.css"] 23 | additional-js = ["theme/custom.js"] 24 | 25 | [output.html.search] 26 | enable = true 27 | limit-results = 30 28 | teaser-word-count = 30 29 | use-boolean-and = true 30 | boost-title = 2 31 | boost-hierarchy = 1 32 | boost-paragraph = 1 33 | expand = true 34 | heading-split-level = 3 35 | 36 | [output.html.git-repository-url] 37 | url = "https://github.com/yourusername/code-mesh" 38 | git-repository-icon = "fa-github" 39 | 40 | [output.html.edit-url-template] 41 | template = "https://github.com/yourusername/code-mesh/edit/main/docs/{path}" 42 | 43 | [preprocessor.links] 44 | 45 | [preprocessor.index] 46 | 47 | [preprocessor.toc] 48 | command = "mdbook-toc" 49 | renderer = ["html"] 50 | 51 | [preprocessor.mermaid] 52 | command = "mdbook-mermaid" -------------------------------------------------------------------------------- /opencode/packages/opencode/src/tool/multiedit.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod" 2 | import { Tool } from "./tool" 3 | import { EditTool } from "./edit" 4 | import DESCRIPTION from "./multiedit.txt" 5 | import path from "path" 6 | import { App } from "../app/app" 7 | 8 | export const MultiEditTool = Tool.define({ 9 | id: "multiedit", 10 | description: DESCRIPTION, 11 | parameters: z.object({ 12 | filePath: z.string().describe("The absolute path to the file to modify"), 13 | edits: z.array(EditTool.parameters).describe("Array of edit operations to perform sequentially on the file"), 14 | }), 15 | async execute(params, ctx) { 16 | const results = [] 17 | for (const [, edit] of params.edits.entries()) { 18 | const result = await EditTool.execute( 19 | { 20 | filePath: params.filePath, 21 | oldString: edit.oldString, 22 | newString: edit.newString, 23 | replaceAll: edit.replaceAll, 24 | }, 25 | ctx, 26 | ) 27 | results.push(result) 28 | } 29 | const app = App.info() 30 | return { 31 | title: path.relative(app.path.root, params.filePath), 32 | metadata: { 33 | results: results.map((r) => r.metadata), 34 | }, 35 | output: results.at(-1)!.output, 36 | } 37 | }, 38 | }) 39 | -------------------------------------------------------------------------------- /opencode/STATS.md: -------------------------------------------------------------------------------- 1 | # Download Stats 2 | 3 | | Date | GitHub Downloads | npm Downloads | Total | 4 | | ---------- | ---------------- | --------------- | ----------------- | 5 | | 2025-06-29 | 18,789 (+0) | 39,420 (+0) | 58,209 (+0) | 6 | | 2025-06-30 | 20,127 (+1,338) | 41,059 (+1,639) | 61,186 (+2,977) | 7 | | 2025-07-01 | 22,108 (+1,981) | 43,745 (+2,686) | 65,853 (+4,667) | 8 | | 2025-07-02 | 24,814 (+2,706) | 46,168 (+2,423) | 70,982 (+5,129) | 9 | | 2025-07-03 | 27,834 (+3,020) | 49,955 (+3,787) | 77,789 (+6,807) | 10 | | 2025-07-04 | 30,608 (+2,774) | 54,758 (+4,803) | 85,366 (+7,577) | 11 | | 2025-07-05 | 32,524 (+1,916) | 58,371 (+3,613) | 90,895 (+5,529) | 12 | | 2025-07-06 | 33,766 (+1,242) | 59,694 (+1,323) | 93,460 (+2,565) | 13 | | 2025-07-08 | 38,052 (+4,286) | 64,468 (+4,774) | 102,520 (+9,060) | 14 | | 2025-07-10 | 43,796 (+5,744) | 71,402 (+6,934) | 115,198 (+12,678) | 15 | | 2025-07-11 | 46,982 (+3,186) | 77,462 (+6,060) | 124,444 (+9,246) | 16 | | 2025-07-12 | 49,302 (+2,320) | 82,177 (+4,715) | 131,479 (+7,035) | 17 | | 2025-07-13 | 50,803 (+1,501) | 86,394 (+4,217) | 137,197 (+5,718) | 18 | | 2025-07-14 | 53,283 (+2,480) | 87,860 (+1,466) | 141,143 (+3,946) | 19 | | 2025-07-15 | 57,590 (+4,307) | 91,036 (+3,176) | 148,626 (+7,483) | 20 | -------------------------------------------------------------------------------- /opencode/packages/tui/input/input.go: -------------------------------------------------------------------------------- 1 | package input 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | // Event represents a terminal event. 9 | type Event any 10 | 11 | // UnknownEvent represents an unknown event. 12 | type UnknownEvent string 13 | 14 | // String returns a string representation of the unknown event. 15 | func (e UnknownEvent) String() string { 16 | return fmt.Sprintf("%q", string(e)) 17 | } 18 | 19 | // MultiEvent represents multiple messages event. 20 | type MultiEvent []Event 21 | 22 | // String returns a string representation of the multiple messages event. 23 | func (e MultiEvent) String() string { 24 | var sb strings.Builder 25 | for _, ev := range e { 26 | sb.WriteString(fmt.Sprintf("%v\n", ev)) 27 | } 28 | return sb.String() 29 | } 30 | 31 | // WindowSizeEvent is used to report the terminal size. Note that Windows does 32 | // not have support for reporting resizes via SIGWINCH signals and relies on 33 | // the Windows Console API to report window size changes. 34 | type WindowSizeEvent struct { 35 | Width int 36 | Height int 37 | } 38 | 39 | // WindowOpEvent is a window operation (XTWINOPS) report event. This is used to 40 | // report various window operations such as reporting the window size or cell 41 | // size. 42 | type WindowOpEvent struct { 43 | Op int 44 | Args []int 45 | } 46 | -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting Security Issues 4 | 5 | This SDK is generated by [Stainless Software Inc](http://stainless.com). Stainless takes security seriously, and encourages you to report any security vulnerability promptly so that appropriate action can be taken. 6 | 7 | To report a security issue, please contact the Stainless team at security@stainless.com. 8 | 9 | ## Responsible Disclosure 10 | 11 | We appreciate the efforts of security researchers and individuals who help us maintain the security of 12 | SDKs we generate. If you believe you have found a security vulnerability, please adhere to responsible 13 | disclosure practices by allowing us a reasonable amount of time to investigate and address the issue 14 | before making any information public. 15 | 16 | ## Reporting Non-SDK Related Security Issues 17 | 18 | If you encounter security issues that are not directly related to SDKs but pertain to the services 19 | or products provided by Opencode, please follow the respective company's security reporting guidelines. 20 | 21 | ### Opencode Terms and Policies 22 | 23 | Please contact support@sst.dev for any questions or concerns regarding the security of our services. 24 | 25 | --- 26 | 27 | Thank you for helping us keep the SDKs and systems they interact with secure. 28 | -------------------------------------------------------------------------------- /opencode/packages/tui/input/termcap.go: -------------------------------------------------------------------------------- 1 | package input 2 | 3 | import ( 4 | "bytes" 5 | "encoding/hex" 6 | "strings" 7 | ) 8 | 9 | // CapabilityEvent represents a Termcap/Terminfo response event. Termcap 10 | // responses are generated by the terminal in response to RequestTermcap 11 | // (XTGETTCAP) requests. 12 | // 13 | // See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands 14 | type CapabilityEvent string 15 | 16 | func parseTermcap(data []byte) CapabilityEvent { 17 | // XTGETTCAP 18 | if len(data) == 0 { 19 | return CapabilityEvent("") 20 | } 21 | 22 | var tc strings.Builder 23 | split := bytes.Split(data, []byte{';'}) 24 | for _, s := range split { 25 | parts := bytes.SplitN(s, []byte{'='}, 2) 26 | if len(parts) == 0 { 27 | return CapabilityEvent("") 28 | } 29 | 30 | name, err := hex.DecodeString(string(parts[0])) 31 | if err != nil || len(name) == 0 { 32 | continue 33 | } 34 | 35 | var value []byte 36 | if len(parts) > 1 { 37 | value, err = hex.DecodeString(string(parts[1])) 38 | if err != nil { 39 | continue 40 | } 41 | } 42 | 43 | if tc.Len() > 0 { 44 | tc.WriteByte(';') 45 | } 46 | tc.WriteString(string(name)) 47 | if len(value) > 0 { 48 | tc.WriteByte('=') 49 | tc.WriteString(string(value)) 50 | } 51 | } 52 | 53 | return CapabilityEvent(tc.String()) 54 | } 55 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Rust 2 | /target/ 3 | **/target/ 4 | **/*.rs.bk 5 | Cargo.lock 6 | 7 | # IDE 8 | .vscode/ 9 | .idea/ 10 | *.swp 11 | *.swo 12 | *~ 13 | 14 | # OS 15 | .DS_Store 16 | .DS_Store? 17 | ._* 18 | .Spotlight-V100 19 | .Trashes 20 | ehthumbs.db 21 | Thumbs.db 22 | 23 | # Logs 24 | *.log 25 | logs/ 26 | 27 | # Environment files 28 | .env 29 | .env.local 30 | .env.development.local 31 | .env.test.local 32 | .env.production.local 33 | 34 | # Node.js (for NPM package) 35 | node_modules/ 36 | npm-debug.log* 37 | yarn-debug.log* 38 | yarn-error.log* 39 | .pnpm-debug.log* 40 | npm/node_modules/ 41 | npm/dist/ 42 | npm/coverage/ 43 | npm/*.tgz 44 | npm/wasm/ 45 | npm/tsconfig.tsbuildinfo 46 | 47 | # Build outputs 48 | dist/ 49 | build/ 50 | pkg/ 51 | *.wasm 52 | 53 | # TypeScript 54 | *.tsbuildinfo 55 | *.d.ts.map 56 | 57 | # Code Mesh specific 58 | .code-mesh/ 59 | code-mesh-sessions/ 60 | *.db 61 | *.sqlite 62 | *.sqlite3 63 | 64 | # Development artifacts 65 | .claude/ 66 | .roo/ 67 | .roomodes 68 | claude-flow/ 69 | coordination/ 70 | memory/ 71 | simple_*_test 72 | test_*.rs 73 | *_test_* 74 | 75 | # Temporary files 76 | tmp/ 77 | temp/ 78 | *.tmp 79 | *.temp 80 | *.bak 81 | *.backup 82 | 83 | # Documentation build 84 | docs/book/ 85 | 86 | # Benchmarks 87 | criterion/ 88 | flamegraph.svg 89 | perf.data* 90 | 91 | # Coverage 92 | tarpaulin-report.html 93 | cobertura.xml 94 | lcov.info -------------------------------------------------------------------------------- /opencode/packages/opencode/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/package.json", 3 | "version": "0.0.5", 4 | "name": "opencode", 5 | "type": "module", 6 | "private": true, 7 | "scripts": { 8 | "typecheck": "tsc --noEmit", 9 | "dev": "bun run ./src/index.ts" 10 | }, 11 | "bin": { 12 | "opencode": "./bin/opencode" 13 | }, 14 | "exports": { 15 | "./*": "./src/*.ts" 16 | }, 17 | "devDependencies": { 18 | "@ai-sdk/amazon-bedrock": "2.2.10", 19 | "@ai-sdk/anthropic": "1.2.12", 20 | "@standard-schema/spec": "1.0.0", 21 | "@tsconfig/bun": "1.0.7", 22 | "@types/bun": "latest", 23 | "@types/turndown": "5.0.5", 24 | "@types/yargs": "17.0.33", 25 | "typescript": "catalog:", 26 | "vscode-languageserver-types": "3.17.5", 27 | "zod-to-json-schema": "3.24.5" 28 | }, 29 | "dependencies": { 30 | "@clack/prompts": "0.11.0", 31 | "@modelcontextprotocol/sdk": "1.15.1", 32 | "@openauthjs/openauth": "0.4.3", 33 | "ai": "catalog:", 34 | "decimal.js": "10.5.0", 35 | "diff": "8.0.2", 36 | "hono": "4.7.10", 37 | "hono-openapi": "0.4.8", 38 | "isomorphic-git": "1.32.1", 39 | "open": "10.1.2", 40 | "remeda": "2.22.3", 41 | "turndown": "7.2.0", 42 | "vscode-jsonrpc": "8.2.1", 43 | "xdg-basedir": "5.1.0", 44 | "yargs": "18.0.0", 45 | "zod": "catalog:" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/provider/transform.ts: -------------------------------------------------------------------------------- 1 | import type { ModelMessage } from "ai" 2 | import { unique } from "remeda" 3 | 4 | export namespace ProviderTransform { 5 | export function message(msgs: ModelMessage[], providerID: string, modelID: string) { 6 | if (providerID === "anthropic" || modelID.includes("anthropic")) { 7 | const system = msgs.filter((msg) => msg.role === "system").slice(0, 2) 8 | const final = msgs.filter((msg) => msg.role !== "system").slice(-2) 9 | 10 | for (const msg of unique([...system, ...final])) { 11 | msg.providerOptions = { 12 | ...msg.providerOptions, 13 | anthropic: { 14 | cacheControl: { type: "ephemeral" }, 15 | }, 16 | openaiCompatible: { 17 | cache_control: { type: "ephemeral" }, 18 | }, 19 | } 20 | } 21 | } 22 | if (providerID === "amazon-bedrock" || modelID.includes("anthropic")) { 23 | const system = msgs.filter((msg) => msg.role === "system").slice(0, 2) 24 | const final = msgs.filter((msg) => msg.role !== "system").slice(-2) 25 | 26 | for (const msg of unique([...system, ...final])) { 27 | msg.providerOptions = { 28 | ...msg.providerOptions, 29 | bedrock: { 30 | cachePoint: { type: "ephemeral" }, 31 | }, 32 | } 33 | } 34 | } 35 | return msgs 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /crates/code-mesh-core/src/memory/mod.rs: -------------------------------------------------------------------------------- 1 | //! Memory management for Code Mesh 2 | 3 | use async_trait::async_trait; 4 | use serde::{Deserialize, Serialize}; 5 | use std::time::Duration; 6 | 7 | /// Memory trait for storing and retrieving data 8 | #[async_trait] 9 | pub trait Memory: Send + Sync { 10 | /// Store a value with optional TTL 11 | async fn store(&self, key: &str, value: MemoryValue, ttl: Option) -> crate::Result<()>; 12 | 13 | /// Retrieve a value 14 | async fn retrieve(&self, key: &str) -> crate::Result>; 15 | 16 | /// Delete a value 17 | async fn delete(&self, key: &str) -> crate::Result<()>; 18 | 19 | /// Search for values matching a pattern 20 | async fn search(&self, pattern: &str, limit: usize) -> crate::Result>; 21 | 22 | /// List all keys in a namespace 23 | async fn list_namespace(&self, namespace: &str) -> crate::Result>; 24 | } 25 | 26 | /// Value stored in memory 27 | #[derive(Debug, Clone, Serialize, Deserialize)] 28 | pub struct MemoryValue { 29 | pub data: serde_json::Value, 30 | pub metadata: MemoryMetadata, 31 | } 32 | 33 | #[derive(Debug, Clone, Serialize, Deserialize)] 34 | pub struct MemoryMetadata { 35 | pub created_at: chrono::DateTime, 36 | pub updated_at: chrono::DateTime, 37 | pub access_count: u64, 38 | pub tags: Vec, 39 | } -------------------------------------------------------------------------------- /opencode/packages/opencode/src/file/time.ts: -------------------------------------------------------------------------------- 1 | import { App } from "../app/app" 2 | import { Log } from "../util/log" 3 | 4 | export namespace FileTime { 5 | const log = Log.create({ service: "file.time" }) 6 | export const state = App.state("tool.filetimes", () => { 7 | const read: { 8 | [sessionID: string]: { 9 | [path: string]: Date | undefined 10 | } 11 | } = {} 12 | return { 13 | read, 14 | } 15 | }) 16 | 17 | export function read(sessionID: string, file: string) { 18 | log.info("read", { sessionID, file }) 19 | const { read } = state() 20 | read[sessionID] = read[sessionID] || {} 21 | read[sessionID][file] = new Date() 22 | } 23 | 24 | export function get(sessionID: string, file: string) { 25 | return state().read[sessionID]?.[file] 26 | } 27 | 28 | export async function assert(sessionID: string, filepath: string) { 29 | const time = get(sessionID, filepath) 30 | if (!time) throw new Error(`You must read the file ${filepath} before overwriting it. Use the Read tool first`) 31 | const stats = await Bun.file(filepath).stat() 32 | if (stats.mtime.getTime() > time.getTime()) { 33 | throw new Error( 34 | `File ${filepath} has been modified since it was last read.\nLast modification: ${stats.mtime.toISOString()}\nLast read: ${time.toISOString()}\n\nPlease read the file again before modifying it.`, 35 | ) 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /opencode/packages/web/src/components/share/content-text.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | color: var(--sl-color-text); 3 | background-color: var(--sl-color-bg-surface); 4 | padding: 0.5rem calc(0.5rem + 3px); 5 | padding-right: calc(1rem + 18px); 6 | border-radius: 0.25rem; 7 | display: flex; 8 | flex-direction: column; 9 | align-items: flex-start; 10 | gap: 1rem; 11 | align-self: flex-start; 12 | font-size: 0.875rem; 13 | 14 | &[data-compact] { 15 | font-size: 0.75rem; 16 | color: var(--sl-color-text-dimmed); 17 | } 18 | 19 | [data-slot="text"] { 20 | line-height: 1.5; 21 | white-space: pre-wrap; 22 | overflow-wrap: anywhere; 23 | display: -webkit-box; 24 | -webkit-box-orient: vertical; 25 | -webkit-line-clamp: 3; 26 | line-clamp: 3; 27 | overflow: hidden; 28 | 29 | [data-expanded] & { 30 | display: block; 31 | } 32 | } 33 | 34 | [data-slot="expand-button"] { 35 | flex: 0 0 auto; 36 | padding: 2px 0; 37 | font-size: 0.75rem; 38 | } 39 | 40 | &[data-theme="invert"] { 41 | background-color: var(--sl-color-blue-high); 42 | color: var(--sl-color-text-invert); 43 | 44 | [data-slot="expand-button"] { 45 | opacity: 0.85; 46 | color: var(--sl-color-text-invert); 47 | 48 | &:hover { 49 | opacity: 1; 50 | } 51 | } 52 | } 53 | 54 | &[data-theme="blue"] { 55 | background-color: var(--sl-color-blue-low); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/cli/cmd/serve.ts: -------------------------------------------------------------------------------- 1 | import { Provider } from "../../provider/provider" 2 | import { Server } from "../../server/server" 3 | import { Share } from "../../share/share" 4 | import { bootstrap } from "../bootstrap" 5 | import { cmd } from "./cmd" 6 | 7 | export const ServeCommand = cmd({ 8 | command: "serve", 9 | builder: (yargs) => 10 | yargs 11 | .option("port", { 12 | alias: ["p"], 13 | type: "number", 14 | describe: "port to listen on", 15 | default: 4096, 16 | }) 17 | .option("hostname", { 18 | alias: ["h"], 19 | type: "string", 20 | describe: "hostname to listen on", 21 | default: "127.0.0.1", 22 | }), 23 | describe: "starts a headless opencode server", 24 | handler: async (args) => { 25 | const cwd = process.cwd() 26 | await bootstrap({ cwd }, async () => { 27 | const providers = await Provider.list() 28 | if (Object.keys(providers).length === 0) { 29 | return "needs_provider" 30 | } 31 | 32 | const hostname = args.hostname 33 | const port = args.port 34 | 35 | await Share.init() 36 | const server = Server.listen({ 37 | port, 38 | hostname, 39 | }) 40 | 41 | console.log(`opencode server listening on http://${server.hostname}:${server.port}`) 42 | 43 | await new Promise(() => {}) 44 | 45 | server.stop() 46 | }) 47 | }, 48 | }) 49 | -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches-ignore: 5 | - 'generated' 6 | - 'codegen/**' 7 | - 'integrated/**' 8 | - 'stl-preview-head/**' 9 | - 'stl-preview-base/**' 10 | pull_request: 11 | branches-ignore: 12 | - 'stl-preview-head/**' 13 | - 'stl-preview-base/**' 14 | 15 | jobs: 16 | lint: 17 | timeout-minutes: 10 18 | name: lint 19 | runs-on: ${{ github.repository == 'stainless-sdks/opencode-go' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} 20 | if: github.event_name == 'push' || github.event.pull_request.head.repo.fork 21 | 22 | steps: 23 | - uses: actions/checkout@v4 24 | 25 | - name: Setup go 26 | uses: actions/setup-go@v5 27 | with: 28 | go-version-file: ./go.mod 29 | 30 | - name: Run lints 31 | run: ./scripts/lint 32 | test: 33 | timeout-minutes: 10 34 | name: test 35 | runs-on: ${{ github.repository == 'stainless-sdks/opencode-go' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} 36 | if: github.event_name == 'push' || github.event.pull_request.head.repo.fork 37 | steps: 38 | - uses: actions/checkout@v4 39 | 40 | - name: Setup go 41 | uses: actions/setup-go@v5 42 | with: 43 | go-version-file: ./go.mod 44 | 45 | - name: Bootstrap 46 | run: ./scripts/bootstrap 47 | 48 | - name: Run tests 49 | run: ./scripts/test 50 | -------------------------------------------------------------------------------- /opencode/packages/web/src/components/Head.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { Base64 } from "js-base64"; 3 | import type { Props } from '@astrojs/starlight/props' 4 | import Default from '@astrojs/starlight/components/Head.astro' 5 | import config from '../../config.mjs' 6 | 7 | const slug = Astro.url.pathname.replace(/^\//, "").replace(/\/$/, ""); 8 | const { 9 | entry: { 10 | data: { title , description }, 11 | }, 12 | } = Astro.locals.starlightRoute; 13 | const isDocs = slug.startsWith("docs") 14 | 15 | let encodedTitle = ''; 16 | let ogImage = `${config.url}/social-share.png`; 17 | let truncatedDesc = ''; 18 | 19 | if (isDocs) { 20 | // Truncate to fit S3's max key size 21 | encodedTitle = encodeURIComponent( 22 | Base64.encode( 23 | // Convert to ASCII 24 | encodeURIComponent( 25 | // Truncate to fit S3's max key size 26 | title.substring(0, 700) 27 | ) 28 | ) 29 | ); 30 | 31 | if (description) { 32 | truncatedDesc = encodeURIComponent(description.substring(0, 400)) 33 | } 34 | 35 | ogImage = `${config.socialCard}/opencode-docs/${encodedTitle}.png?desc=${truncatedDesc}`; 36 | } 37 | --- 38 | 39 | { slug === "" && ( 40 | {title} | AI coding agent built for the terminal 41 | )} 42 | 43 | 44 | 45 | { (isDocs || !slug.startsWith("s")) && ( 46 | 47 | 48 | )} 49 | -------------------------------------------------------------------------------- /opencode/packages/web/src/content/docs/docs/mcp-servers.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: MCP servers 3 | description: Add local and remote MCP tools. 4 | --- 5 | 6 | You can add external tools to opencode using the _Model Context Protocol_, or MCP. opencode supports both: 7 | 8 | - Local servers 9 | - And remote servers 10 | 11 | Once added, MCP tools are automatically available to the LLM alongside built-in tools. 12 | 13 | --- 14 | 15 | ## Configure 16 | 17 | You can define MCP servers in your opencode config under `mcp`. 18 | 19 | ### Local 20 | 21 | Add a local MCP servers under `mcp.localmcp`. 22 | 23 | ```json title="opencode.json" 24 | { 25 | "$schema": "https://opencode.ai/config.json", 26 | "mcp": { 27 | "localmcp": { 28 | "type": "local", 29 | "command": ["bun", "x", "my-mcp-command"], 30 | "enabled": true, 31 | "environment": { 32 | "MY_ENV_VAR": "my_env_var_value" 33 | } 34 | } 35 | } 36 | } 37 | ``` 38 | 39 | You can also disable a server by setting `enabled` to `false`. This is useful if you want to temporarily disable a server without removing it from your config. 40 | 41 | ### Remote 42 | 43 | Add a remote MCP servers under `mcp.remotemcp`. 44 | 45 | ```json title="opencode.json" 46 | { 47 | "$schema": "https://opencode.ai/config.json", 48 | "mcp": { 49 | "remotemcp": { 50 | "type": "remote", 51 | "url": "https://my-mcp-server.com", 52 | "enabled": true 53 | } 54 | } 55 | } 56 | ``` 57 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Multi-stage Docker build for Code Mesh 2 | 3 | # Build stage 4 | FROM rust:1.75 as builder 5 | 6 | WORKDIR /app 7 | 8 | # Copy dependency files 9 | COPY Cargo.toml Cargo.lock ./ 10 | COPY crates/ ./crates/ 11 | 12 | # Build dependencies first (cached layer) 13 | RUN cargo build --release --bin code-mesh 14 | 15 | # Runtime stage 16 | FROM debian:bookworm-slim 17 | 18 | # Install runtime dependencies 19 | RUN apt-get update && apt-get install -y \ 20 | ca-certificates \ 21 | curl \ 22 | git \ 23 | && rm -rf /var/lib/apt/lists/* 24 | 25 | # Create app user 26 | RUN useradd -r -s /bin/false code-mesh 27 | 28 | # Copy binary from builder stage 29 | COPY --from=builder /app/target/release/code-mesh /usr/local/bin/code-mesh 30 | 31 | # Set permissions 32 | RUN chmod +x /usr/local/bin/code-mesh 33 | 34 | # Switch to app user 35 | USER code-mesh 36 | 37 | # Set working directory 38 | WORKDIR /home/code-mesh 39 | 40 | # Health check 41 | HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ 42 | CMD code-mesh status || exit 1 43 | 44 | # Default command 45 | ENTRYPOINT ["code-mesh"] 46 | CMD ["--help"] 47 | 48 | # Metadata 49 | LABEL org.opencontainers.image.title="Code Mesh" 50 | LABEL org.opencontainers.image.description="AI-powered coding assistant built in Rust" 51 | LABEL org.opencontainers.image.vendor="ruvnet" 52 | LABEL org.opencontainers.image.licenses="MIT" 53 | LABEL org.opencontainers.image.source="https://github.com/ruvnet/code-mesh" -------------------------------------------------------------------------------- /opencode/packages/opencode/test/tool/tool.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, test } from "bun:test" 2 | import { App } from "../../src/app/app" 3 | import { GlobTool } from "../../src/tool/glob" 4 | import { ListTool } from "../../src/tool/ls" 5 | 6 | const ctx = { 7 | sessionID: "test", 8 | messageID: "", 9 | abort: AbortSignal.any([]), 10 | metadata: () => {}, 11 | } 12 | describe("tool.glob", () => { 13 | test("truncate", async () => { 14 | await App.provide({ cwd: process.cwd() }, async () => { 15 | let result = await GlobTool.execute( 16 | { 17 | pattern: "../../node_modules/**/*", 18 | path: undefined, 19 | }, 20 | ctx, 21 | ) 22 | expect(result.metadata.truncated).toBe(true) 23 | }) 24 | }) 25 | test("basic", async () => { 26 | await App.provide({ cwd: process.cwd() }, async () => { 27 | let result = await GlobTool.execute( 28 | { 29 | pattern: "*.json", 30 | path: undefined, 31 | }, 32 | ctx, 33 | ) 34 | expect(result.metadata).toMatchObject({ 35 | truncated: false, 36 | count: 3, 37 | }) 38 | }) 39 | }) 40 | }) 41 | 42 | describe("tool.ls", () => { 43 | test("basic", async () => { 44 | const result = await App.provide({ cwd: process.cwd() }, async () => { 45 | return await ListTool.execute({ path: "./example", ignore: [".git"] }, ctx) 46 | }) 47 | expect(result.output).toMatchSnapshot() 48 | }) 49 | }) 50 | -------------------------------------------------------------------------------- /opencode/packages/tui/internal/components/qr/qr.go: -------------------------------------------------------------------------------- 1 | package qr 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/sst/opencode/internal/styles" 7 | "github.com/sst/opencode/internal/theme" 8 | "rsc.io/qr" 9 | ) 10 | 11 | var tops_bottoms = []rune{' ', '▀', '▄', '█'} 12 | 13 | // Generate a text string to a QR code, which you can write to a terminal or file. 14 | func Generate(text string) (string, int, error) { 15 | code, err := qr.Encode(text, qr.Level(0)) 16 | if err != nil { 17 | return "", 0, err 18 | } 19 | 20 | t := theme.CurrentTheme() 21 | if t == nil { 22 | return "", 0, err 23 | } 24 | 25 | // Create lipgloss style for QR code with theme colors 26 | qrStyle := styles.NewStyle().Foreground(t.Text()).Background(t.Background()) 27 | 28 | var result strings.Builder 29 | 30 | // content 31 | for y := 0; y < code.Size-1; y += 2 { 32 | var line strings.Builder 33 | for x := 0; x < code.Size; x += 1 { 34 | var num int8 35 | if code.Black(x, y) { 36 | num += 1 37 | } 38 | if code.Black(x, y+1) { 39 | num += 2 40 | } 41 | line.WriteRune(tops_bottoms[num]) 42 | } 43 | result.WriteString(qrStyle.Render(line.String()) + "\n") 44 | } 45 | 46 | // add lower border when required (only required when QR size is odd) 47 | if code.Size%2 == 1 { 48 | var borderLine strings.Builder 49 | for range code.Size { 50 | borderLine.WriteRune('▀') 51 | } 52 | result.WriteString(qrStyle.Render(borderLine.String()) + "\n") 53 | } 54 | 55 | return result.String(), code.Size, nil 56 | } 57 | -------------------------------------------------------------------------------- /opencode/packages/tui/input/xterm.go: -------------------------------------------------------------------------------- 1 | package input 2 | 3 | import ( 4 | "github.com/charmbracelet/x/ansi" 5 | ) 6 | 7 | func parseXTermModifyOtherKeys(params ansi.Params) Event { 8 | // XTerm modify other keys starts with ESC [ 27 ; ; ~ 9 | xmod, _, _ := params.Param(1, 1) 10 | xrune, _, _ := params.Param(2, 1) 11 | mod := KeyMod(xmod - 1) 12 | r := rune(xrune) 13 | 14 | switch r { 15 | case ansi.BS: 16 | return KeyPressEvent{Mod: mod, Code: KeyBackspace} 17 | case ansi.HT: 18 | return KeyPressEvent{Mod: mod, Code: KeyTab} 19 | case ansi.CR: 20 | return KeyPressEvent{Mod: mod, Code: KeyEnter} 21 | case ansi.ESC: 22 | return KeyPressEvent{Mod: mod, Code: KeyEscape} 23 | case ansi.DEL: 24 | return KeyPressEvent{Mod: mod, Code: KeyBackspace} 25 | } 26 | 27 | // CSI 27 ; ; ~ keys defined in XTerm modifyOtherKeys 28 | k := KeyPressEvent{Code: r, Mod: mod} 29 | if k.Mod <= ModShift { 30 | k.Text = string(r) 31 | } 32 | 33 | return k 34 | } 35 | 36 | // TerminalVersionEvent is a message that represents the terminal version. 37 | type TerminalVersionEvent string 38 | 39 | // ModifyOtherKeysEvent represents a modifyOtherKeys event. 40 | // 41 | // 0: disable 42 | // 1: enable mode 1 43 | // 2: enable mode 2 44 | // 45 | // See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Functions-using-CSI-_-ordered-by-the-final-character_s_ 46 | // See: https://invisible-island.net/xterm/manpage/xterm.html#VT100-Widget-Resources:modifyOtherKeys 47 | type ModifyOtherKeysEvent uint8 48 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/tool/read.txt: -------------------------------------------------------------------------------- 1 | Reads a file from the local filesystem. You can access any file directly by using this tool. 2 | Assume this tool is able to read all files on the machine. If the User provides a path to a file assume that path is valid. It is okay to read a file that does not exist; an error will be returned. 3 | 4 | Usage: 5 | - The filePath parameter must be an absolute path, not a relative path 6 | - By default, it reads up to 2000 lines starting from the beginning of the file 7 | - You can optionally specify a line offset and limit (especially handy for long files), but it's recommended to read the whole file by not providing these parameters 8 | - Any lines longer than 2000 characters will be truncated 9 | - Results are returned using cat -n format, with line numbers starting at 1 10 | - This tool allows opencode to read images (eg PNG, JPG, etc). When reading an image file the contents are presented visually as opencode is a multimodal LLM. 11 | - You have the capability to call multiple tools in a single response. It is always better to speculatively read multiple files as a batch that are potentially useful. 12 | - You will regularly be asked to read screenshots. If the user provides a path to a screenshot ALWAYS use this tool to view the file at the path. This tool will work with all temporary file paths like /var/folders/123/abc/T/TemporaryItems/NSIRD_screencaptureui_ZfB1tD/Screenshot.png 13 | - If you read a file that exists but has empty contents you will receive a system reminder warning in place of file contents. 14 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/util/error.ts: -------------------------------------------------------------------------------- 1 | import { z, type ZodSchema } from "zod" 2 | // import { Log } from "./log" 3 | 4 | // const log = Log.create() 5 | 6 | export abstract class NamedError extends Error { 7 | abstract schema(): ZodSchema 8 | abstract toObject(): { name: string; data: any } 9 | 10 | static create(name: Name, data: Data) { 11 | const schema = z 12 | .object({ 13 | name: z.literal(name), 14 | data, 15 | }) 16 | .openapi({ 17 | ref: name, 18 | }) 19 | const result = class extends NamedError { 20 | public static readonly Schema = schema 21 | 22 | public readonly name = name as Name 23 | 24 | constructor( 25 | public readonly data: z.input, 26 | options?: ErrorOptions, 27 | ) { 28 | super(name, options) 29 | this.name = name 30 | } 31 | 32 | static isInstance(input: any): input is InstanceType { 33 | return "name" in input && input.name === name 34 | } 35 | 36 | schema() { 37 | return schema 38 | } 39 | 40 | toObject() { 41 | return { 42 | name: name, 43 | data: this.data, 44 | } 45 | } 46 | } 47 | Object.defineProperty(result, "name", { value: name }) 48 | return result 49 | } 50 | 51 | public static readonly Unknown = NamedError.create( 52 | "UnknownError", 53 | z.object({ 54 | message: z.string(), 55 | }), 56 | ) 57 | } 58 | -------------------------------------------------------------------------------- /opencode/packages/tui/input/parse_test.go: -------------------------------------------------------------------------------- 1 | package input 2 | 3 | import ( 4 | "image/color" 5 | "reflect" 6 | "testing" 7 | 8 | "github.com/charmbracelet/x/ansi" 9 | ) 10 | 11 | func TestParseSequence_Events(t *testing.T) { 12 | input := []byte("\x1b\x1b[Ztest\x00\x1b]10;rgb:1234/1234/1234\x07\x1b[27;2;27~\x1b[?1049;2$y\x1b[4;1$y") 13 | want := []Event{ 14 | KeyPressEvent{Code: KeyTab, Mod: ModShift | ModAlt}, 15 | KeyPressEvent{Code: 't', Text: "t"}, 16 | KeyPressEvent{Code: 'e', Text: "e"}, 17 | KeyPressEvent{Code: 's', Text: "s"}, 18 | KeyPressEvent{Code: 't', Text: "t"}, 19 | KeyPressEvent{Code: KeySpace, Mod: ModCtrl}, 20 | ForegroundColorEvent{color.RGBA{R: 0x12, G: 0x12, B: 0x12, A: 0xff}}, 21 | KeyPressEvent{Code: KeyEscape, Mod: ModShift}, 22 | ModeReportEvent{Mode: ansi.AltScreenSaveCursorMode, Value: ansi.ModeReset}, 23 | ModeReportEvent{Mode: ansi.InsertReplaceMode, Value: ansi.ModeSet}, 24 | } 25 | 26 | var p Parser 27 | for i := 0; len(input) != 0; i++ { 28 | if i >= len(want) { 29 | t.Fatalf("reached end of want events") 30 | } 31 | n, got := p.parseSequence(input) 32 | if !reflect.DeepEqual(got, want[i]) { 33 | t.Errorf("got %#v (%T), want %#v (%T)", got, got, want[i], want[i]) 34 | } 35 | input = input[n:] 36 | } 37 | } 38 | 39 | func BenchmarkParseSequence(b *testing.B) { 40 | var p Parser 41 | input := []byte("\x1b\x1b[Ztest\x00\x1b]10;1234/1234/1234\x07\x1b[27;2;27~") 42 | b.ReportAllocs() 43 | b.ResetTimer() 44 | for i := 0; i < b.N; i++ { 45 | p.parseSequence(input) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/file/watch.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod" 2 | import { Bus } from "../bus" 3 | import fs from "fs" 4 | import { App } from "../app/app" 5 | import { Log } from "../util/log" 6 | import { Flag } from "../flag/flag" 7 | 8 | export namespace FileWatcher { 9 | const log = Log.create({ service: "file.watcher" }) 10 | 11 | export const Event = { 12 | Updated: Bus.event( 13 | "file.watcher.updated", 14 | z.object({ 15 | file: z.string(), 16 | event: z.union([z.literal("rename"), z.literal("change")]), 17 | }), 18 | ), 19 | } 20 | const state = App.state( 21 | "file.watcher", 22 | () => { 23 | const app = App.use() 24 | if (!app.info.git) return {} 25 | try { 26 | const watcher = fs.watch(app.info.path.cwd, { recursive: true }, (event, file) => { 27 | log.info("change", { file, event }) 28 | if (!file) return 29 | // for some reason async local storage is lost here 30 | // https://github.com/oven-sh/bun/issues/20754 31 | App.provideExisting(app, async () => { 32 | Bus.publish(Event.Updated, { 33 | file, 34 | event, 35 | }) 36 | }) 37 | }) 38 | return { watcher } 39 | } catch { 40 | return {} 41 | } 42 | }, 43 | async (state) => { 44 | state.watcher?.close() 45 | }, 46 | ) 47 | 48 | export function init() { 49 | if (Flag.OPENCODE_DISABLE_WATCHER || true) return 50 | state() 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /opencode/infra/app.ts: -------------------------------------------------------------------------------- 1 | export const domain = (() => { 2 | if ($app.stage === "production") return "opencode.ai" 3 | if ($app.stage === "dev") return "dev.opencode.ai" 4 | return `${$app.stage}.dev.opencode.ai` 5 | })() 6 | 7 | const GITHUB_APP_ID = new sst.Secret("GITHUB_APP_ID") 8 | const GITHUB_APP_PRIVATE_KEY = new sst.Secret("GITHUB_APP_PRIVATE_KEY") 9 | const bucket = new sst.cloudflare.Bucket("Bucket") 10 | 11 | export const api = new sst.cloudflare.Worker("Api", { 12 | domain: `api.${domain}`, 13 | handler: "packages/function/src/api.ts", 14 | environment: { 15 | WEB_DOMAIN: domain, 16 | }, 17 | url: true, 18 | link: [bucket, GITHUB_APP_ID, GITHUB_APP_PRIVATE_KEY], 19 | transform: { 20 | worker: (args) => { 21 | args.logpush = true 22 | args.bindings = $resolve(args.bindings).apply((bindings) => [ 23 | ...bindings, 24 | { 25 | name: "SYNC_SERVER", 26 | type: "durable_object_namespace", 27 | className: "SyncServer", 28 | }, 29 | ]) 30 | args.migrations = { 31 | // Note: when releasing the next tag, make sure all stages use tag v2 32 | oldTag: $app.stage === "production" ? "" : "v1", 33 | newTag: $app.stage === "production" ? "" : "v1", 34 | //newSqliteClasses: ["SyncServer"], 35 | } 36 | }, 37 | }, 38 | }) 39 | 40 | new sst.cloudflare.x.Astro("Web", { 41 | domain, 42 | path: "packages/web", 43 | environment: { 44 | // For astro config 45 | SST_STAGE: $app.stage, 46 | VITE_API_URL: api.url, 47 | }, 48 | }) 49 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/cli/cmd/debug/snapshot.ts: -------------------------------------------------------------------------------- 1 | import { Snapshot } from "../../../snapshot" 2 | import { bootstrap } from "../../bootstrap" 3 | import { cmd } from "../cmd" 4 | 5 | export const SnapshotCommand = cmd({ 6 | command: "snapshot", 7 | builder: (yargs) => yargs.command(CreateCommand).command(RestoreCommand).command(DiffCommand).demandCommand(), 8 | async handler() {}, 9 | }) 10 | 11 | const CreateCommand = cmd({ 12 | command: "create", 13 | async handler() { 14 | await bootstrap({ cwd: process.cwd() }, async () => { 15 | const result = await Snapshot.create("test") 16 | console.log(result) 17 | }) 18 | }, 19 | }) 20 | 21 | const RestoreCommand = cmd({ 22 | command: "restore ", 23 | builder: (yargs) => 24 | yargs.positional("commit", { 25 | type: "string", 26 | description: "commit", 27 | demandOption: true, 28 | }), 29 | async handler(args) { 30 | await bootstrap({ cwd: process.cwd() }, async () => { 31 | await Snapshot.restore("test", args.commit) 32 | console.log("restored") 33 | }) 34 | }, 35 | }) 36 | 37 | export const DiffCommand = cmd({ 38 | command: "diff ", 39 | describe: "diff", 40 | builder: (yargs) => 41 | yargs.positional("commit", { 42 | type: "string", 43 | description: "commit", 44 | demandOption: true, 45 | }), 46 | async handler(args) { 47 | await bootstrap({ cwd: process.cwd() }, async () => { 48 | const diff = await Snapshot.diff("test", args.commit) 49 | console.log(diff) 50 | }) 51 | }, 52 | }) 53 | -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/aliases.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package opencode 4 | 5 | import ( 6 | "github.com/sst/opencode-sdk-go/internal/apierror" 7 | "github.com/sst/opencode-sdk-go/shared" 8 | ) 9 | 10 | type Error = apierror.Error 11 | 12 | // This is an alias to an internal type. 13 | type MessageAbortedError = shared.MessageAbortedError 14 | 15 | // This is an alias to an internal type. 16 | type MessageAbortedErrorName = shared.MessageAbortedErrorName 17 | 18 | // This is an alias to an internal value. 19 | const MessageAbortedErrorNameMessageAbortedError = shared.MessageAbortedErrorNameMessageAbortedError 20 | 21 | // This is an alias to an internal type. 22 | type ProviderAuthError = shared.ProviderAuthError 23 | 24 | // This is an alias to an internal type. 25 | type ProviderAuthErrorData = shared.ProviderAuthErrorData 26 | 27 | // This is an alias to an internal type. 28 | type ProviderAuthErrorName = shared.ProviderAuthErrorName 29 | 30 | // This is an alias to an internal value. 31 | const ProviderAuthErrorNameProviderAuthError = shared.ProviderAuthErrorNameProviderAuthError 32 | 33 | // This is an alias to an internal type. 34 | type UnknownError = shared.UnknownError 35 | 36 | // This is an alias to an internal type. 37 | type UnknownErrorData = shared.UnknownErrorData 38 | 39 | // This is an alias to an internal type. 40 | type UnknownErrorName = shared.UnknownErrorName 41 | 42 | // This is an alias to an internal value. 43 | const UnknownErrorNameUnknownError = shared.UnknownErrorNameUnknownError 44 | -------------------------------------------------------------------------------- /opencode/sdks/github/action.yml: -------------------------------------------------------------------------------- 1 | name: "opencode GitHub Action" 2 | description: "Run opencode in GitHub Actions workflows" 3 | branding: 4 | icon: "code" 5 | color: "orange" 6 | 7 | inputs: 8 | model: 9 | description: "Model to use" 10 | required: false 11 | 12 | share: 13 | description: "Share the opencode session (defaults to true for public repos)" 14 | required: false 15 | 16 | outputs: 17 | share_url: 18 | description: "URL to share the opencode execution" 19 | value: ${{ steps.run_opencode.outputs.share_url }} 20 | 21 | runs: 22 | using: "composite" 23 | steps: 24 | - name: Setup Node.js 25 | uses: actions/setup-node@v4 26 | with: 27 | node-version: 22 28 | 29 | - name: Install Bun 30 | uses: oven-sh/setup-bun@v2 31 | with: 32 | bun-version: 1.2.16 33 | 34 | - name: Install Dependencies 35 | shell: bash 36 | run: | 37 | cd ${GITHUB_ACTION_PATH} 38 | bun install 39 | 40 | - name: Install opencode 41 | shell: bash 42 | run: curl -fsSL https://opencode.ai/install | bash 43 | 44 | - name: Run opencode 45 | shell: bash 46 | id: run_opencode 47 | run: | 48 | bun run ${GITHUB_ACTION_PATH}/src/index.ts 49 | env: 50 | INPUT_MODEL: ${{ inputs.model }} 51 | INPUT_SHARE: ${{ inputs.share }} 52 | 53 | #- name: Testing 54 | # shell: bash 55 | # run: | 56 | # gh pr comment ${{ github.event.number }} --body "This is an automated comment" 57 | # env: 58 | # GH_TOKEN: ${{ github.token }} 59 | -------------------------------------------------------------------------------- /test_oauth.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Testing OAuth authentication persistence..." 4 | 5 | # Test Console OAuth (creates API key) 6 | echo "1. Testing Console OAuth (API Key Creation)" 7 | echo " This will create an API key using OAuth and save it persistently" 8 | echo " Command: cargo run --bin code-mesh -- auth login" 9 | echo "" 10 | 11 | # Test Auth List to see storage 12 | echo "2. Testing Auth Status" 13 | echo " This will show current authentication status" 14 | echo " Command: cargo run --bin code-mesh -- auth list" 15 | echo "" 16 | 17 | # Test Run Command to see if it finds stored credentials 18 | echo "3. Testing Run Command with Stored Credentials" 19 | echo " This will check if the run command finds stored credentials" 20 | echo " Command: cargo run --bin code-mesh -- run 'help me debug this code'" 21 | echo "" 22 | 23 | # Test Logout 24 | echo "4. Testing Logout" 25 | echo " This will remove stored credentials" 26 | echo " Command: cargo run --bin code-mesh -- auth logout anthropic" 27 | echo "" 28 | 29 | echo "Manual test sequence:" 30 | echo "1. cargo run --bin code-mesh -- auth login" 31 | echo "2. Select 'Anthropic (Claude)'" 32 | echo "3. Select 'Console OAuth (API Key Creation)'" 33 | echo "4. Complete OAuth flow" 34 | echo "5. cargo run --bin code-mesh -- auth list (should show ✅ Authenticated)" 35 | echo "6. cargo run --bin code-mesh -- run 'test' (should find stored credentials)" 36 | echo "7. cargo run --bin code-mesh -- auth logout anthropic (should remove credentials)" 37 | echo "8. cargo run --bin code-mesh -- auth list (should show ❌ Not authenticated)" -------------------------------------------------------------------------------- /opencode/packages/web/src/assets/logo-ornate-light.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/auth/index.ts: -------------------------------------------------------------------------------- 1 | import path from "path" 2 | import { Global } from "../global" 3 | import fs from "fs/promises" 4 | import { z } from "zod" 5 | 6 | export namespace Auth { 7 | export const Oauth = z.object({ 8 | type: z.literal("oauth"), 9 | refresh: z.string(), 10 | access: z.string(), 11 | expires: z.number(), 12 | }) 13 | 14 | export const Api = z.object({ 15 | type: z.literal("api"), 16 | key: z.string(), 17 | }) 18 | 19 | export const Info = z.discriminatedUnion("type", [Oauth, Api]) 20 | export type Info = z.infer 21 | 22 | const filepath = path.join(Global.Path.data, "auth.json") 23 | 24 | export async function get(providerID: string) { 25 | const file = Bun.file(filepath) 26 | return file 27 | .json() 28 | .catch(() => ({})) 29 | .then((x) => x[providerID] as Info | undefined) 30 | } 31 | 32 | export async function all(): Promise> { 33 | const file = Bun.file(filepath) 34 | return file.json().catch(() => ({})) 35 | } 36 | 37 | export async function set(key: string, info: Info) { 38 | const file = Bun.file(filepath) 39 | const data = await all() 40 | await Bun.write(file, JSON.stringify({ ...data, [key]: info }, null, 2)) 41 | await fs.chmod(file.name!, 0o600) 42 | } 43 | 44 | export async function remove(key: string) { 45 | const file = Bun.file(filepath) 46 | const data = await all() 47 | delete data[key] 48 | await Bun.write(file, JSON.stringify(data, null, 2)) 49 | await fs.chmod(file.name!, 0o600) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /docs/legacy/README.md: -------------------------------------------------------------------------------- 1 | # Legacy Documentation 2 | 3 | This directory contains documentation and implementation summaries from the development process of Code Mesh. These files provide historical context and detailed implementation notes that were generated during the port from OpenCode to Rust. 4 | 5 | ## Contents 6 | 7 | ### Implementation Summaries 8 | - `ANTHROPIC_IMPLEMENTATION_COMPLETE.md` - Complete Anthropic provider implementation details 9 | - `IMPLEMENTATION_SUMMARY.md` - Overall project implementation summary 10 | - `TOOL_IMPLEMENTATION_SUMMARY.md` - Detailed tool system implementation notes 11 | - `TUI_IMPLEMENTATION.md` - Terminal UI implementation documentation 12 | - `WEB_TOOLS_IMPLEMENTATION_REPORT.md` - Web tools implementation report 13 | 14 | ### Architecture & Design 15 | - `ARCHITECTURE.md` - System architecture documentation 16 | - `coordination.md` - Agent coordination system design 17 | - `memory-bank.md` - Memory management system documentation 18 | 19 | ### Performance & Testing 20 | - `PERFORMANCE.md` - Performance optimization notes 21 | - `PERFORMANCE_SUMMARY.md` - Performance benchmarks and analysis 22 | - `TESTING.md` - Testing strategy and implementation 23 | 24 | ### Development Process 25 | - `opencode-tools-analysis.md` - Analysis of original OpenCode tools 26 | - `github-update.md` - GitHub integration updates 27 | - `README-old.md` - Original project README 28 | 29 | ## Note 30 | 31 | These documents are preserved for historical reference and development insights. For current documentation, please refer to the main project documentation in the `docs/` directory and the project README. -------------------------------------------------------------------------------- /opencode/packages/tui/internal/components/chat/cache.go: -------------------------------------------------------------------------------- 1 | package chat 2 | 3 | import ( 4 | "crypto/sha256" 5 | "encoding/hex" 6 | "fmt" 7 | "sync" 8 | ) 9 | 10 | // MessageCache caches rendered messages to avoid re-rendering 11 | type MessageCache struct { 12 | mu sync.RWMutex 13 | cache map[string]string 14 | } 15 | 16 | // NewMessageCache creates a new message cache 17 | func NewMessageCache() *MessageCache { 18 | return &MessageCache{ 19 | cache: make(map[string]string), 20 | } 21 | } 22 | 23 | // generateKey creates a unique key for a message based on its content and rendering parameters 24 | func (c *MessageCache) GenerateKey(params ...any) string { 25 | h := sha256.New() 26 | for _, param := range params { 27 | h.Write(fmt.Appendf(nil, ":%v", param)) 28 | } 29 | return hex.EncodeToString(h.Sum(nil)) 30 | } 31 | 32 | // Get retrieves a cached rendered message 33 | func (c *MessageCache) Get(key string) (string, bool) { 34 | c.mu.RLock() 35 | defer c.mu.RUnlock() 36 | 37 | content, exists := c.cache[key] 38 | return content, exists 39 | } 40 | 41 | // Set stores a rendered message in the cache 42 | func (c *MessageCache) Set(key string, content string) { 43 | c.mu.Lock() 44 | defer c.mu.Unlock() 45 | c.cache[key] = content 46 | } 47 | 48 | // Clear removes all entries from the cache 49 | func (c *MessageCache) Clear() { 50 | c.mu.Lock() 51 | defer c.mu.Unlock() 52 | 53 | c.cache = make(map[string]string) 54 | } 55 | 56 | // Size returns the number of cached entries 57 | func (c *MessageCache) Size() int { 58 | c.mu.RLock() 59 | defer c.mu.RUnlock() 60 | 61 | return len(c.cache) 62 | } 63 | -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/scripts/test: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | RED='\033[0;31m' 8 | GREEN='\033[0;32m' 9 | YELLOW='\033[0;33m' 10 | NC='\033[0m' # No Color 11 | 12 | function prism_is_running() { 13 | curl --silent "http://localhost:4010" >/dev/null 2>&1 14 | } 15 | 16 | kill_server_on_port() { 17 | pids=$(lsof -t -i tcp:"$1" || echo "") 18 | if [ "$pids" != "" ]; then 19 | kill "$pids" 20 | echo "Stopped $pids." 21 | fi 22 | } 23 | 24 | function is_overriding_api_base_url() { 25 | [ -n "$TEST_API_BASE_URL" ] 26 | } 27 | 28 | if ! is_overriding_api_base_url && ! prism_is_running ; then 29 | # When we exit this script, make sure to kill the background mock server process 30 | trap 'kill_server_on_port 4010' EXIT 31 | 32 | # Start the dev server 33 | ./scripts/mock --daemon 34 | fi 35 | 36 | if is_overriding_api_base_url ; then 37 | echo -e "${GREEN}✔ Running tests against ${TEST_API_BASE_URL}${NC}" 38 | echo 39 | elif ! prism_is_running ; then 40 | echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Prism server" 41 | echo -e "running against your OpenAPI spec." 42 | echo 43 | echo -e "To run the server, pass in the path or url of your OpenAPI" 44 | echo -e "spec to the prism command:" 45 | echo 46 | echo -e " \$ ${YELLOW}npm exec --package=@stoplight/prism-cli@~5.3.2 -- prism mock path/to/your.openapi.yml${NC}" 47 | echo 48 | 49 | exit 1 50 | else 51 | echo -e "${GREEN}✔ Mock prism server is running with your OpenAPI spec${NC}" 52 | echo 53 | fi 54 | 55 | echo "==> Running tests" 56 | go test ./... "$@" 57 | -------------------------------------------------------------------------------- /opencode/packages/web/src/components/share/content-error.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | background-color: var(--sl-color-bg-surface); 3 | padding: 0.5rem calc(0.5rem + 3px); 4 | border-radius: 0.25rem; 5 | display: flex; 6 | flex-direction: column; 7 | align-items: flex-start; 8 | gap: 1rem; 9 | align-self: flex-start; 10 | 11 | [data-section="content"] { 12 | pre { 13 | margin-bottom: 0.5rem; 14 | line-height: 1.5; 15 | font-size: 0.75rem; 16 | white-space: pre-wrap; 17 | word-break: break-word; 18 | 19 | &:last-child { 20 | margin-bottom: 0; 21 | } 22 | 23 | span { 24 | margin-right: 0.25rem; 25 | &:last-child { 26 | margin-right: 0; 27 | } 28 | } 29 | span[data-color="red"] { 30 | color: var(--sl-color-red); 31 | } 32 | span[data-color="dimmed"] { 33 | color: var(--sl-color-text-dimmed); 34 | } 35 | span[data-marker="label"] { 36 | text-transform: uppercase; 37 | letter-spacing: -0.5px; 38 | } 39 | span[data-separator] { 40 | margin-right: 0.375rem; 41 | } 42 | } 43 | } 44 | 45 | &[data-expanded="true"] { 46 | [data-section="content"] { 47 | display: block; 48 | } 49 | } 50 | &[data-expanded="false"] { 51 | [data-section="content"] { 52 | display: -webkit-box; 53 | -webkit-box-orient: vertical; 54 | -webkit-line-clamp: 7; 55 | overflow: hidden; 56 | } 57 | } 58 | 59 | button { 60 | flex: 0 0 auto; 61 | padding: 2px 0; 62 | font-size: 0.75rem; 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/internal/apierror/apierror.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package apierror 4 | 5 | import ( 6 | "fmt" 7 | "net/http" 8 | "net/http/httputil" 9 | 10 | "github.com/sst/opencode-sdk-go/internal/apijson" 11 | ) 12 | 13 | // Error represents an error that originates from the API, i.e. when a request is 14 | // made and the API returns a response with a HTTP status code. Other errors are 15 | // not wrapped by this SDK. 16 | type Error struct { 17 | JSON errorJSON `json:"-"` 18 | StatusCode int 19 | Request *http.Request 20 | Response *http.Response 21 | } 22 | 23 | // errorJSON contains the JSON metadata for the struct [Error] 24 | type errorJSON struct { 25 | raw string 26 | ExtraFields map[string]apijson.Field 27 | } 28 | 29 | func (r *Error) UnmarshalJSON(data []byte) (err error) { 30 | return apijson.UnmarshalRoot(data, r) 31 | } 32 | 33 | func (r errorJSON) RawJSON() string { 34 | return r.raw 35 | } 36 | 37 | func (r *Error) Error() string { 38 | // Attempt to re-populate the response body 39 | return fmt.Sprintf("%s \"%s\": %d %s %s", r.Request.Method, r.Request.URL, r.Response.StatusCode, http.StatusText(r.Response.StatusCode), r.JSON.RawJSON()) 40 | } 41 | 42 | func (r *Error) DumpRequest(body bool) []byte { 43 | if r.Request.GetBody != nil { 44 | r.Request.Body, _ = r.Request.GetBody() 45 | } 46 | out, _ := httputil.DumpRequestOut(r.Request, body) 47 | return out 48 | } 49 | 50 | func (r *Error) DumpResponse(body bool) []byte { 51 | out, _ := httputil.DumpResponse(r.Response, body) 52 | return out 53 | } 54 | -------------------------------------------------------------------------------- /opencode/packages/opencode/bin/opencode.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | setlocal enabledelayedexpansion 3 | 4 | if defined OPENCODE_BIN_PATH ( 5 | set "resolved=%OPENCODE_BIN_PATH%" 6 | goto :execute 7 | ) 8 | 9 | rem Get the directory of this script 10 | set "script_dir=%~dp0" 11 | set "script_dir=%script_dir:~0,-1%" 12 | 13 | rem Detect platform and architecture 14 | set "platform=win32" 15 | 16 | rem Detect architecture 17 | if "%PROCESSOR_ARCHITECTURE%"=="AMD64" ( 18 | set "arch=x64" 19 | ) else if "%PROCESSOR_ARCHITECTURE%"=="ARM64" ( 20 | set "arch=arm64" 21 | ) else if "%PROCESSOR_ARCHITECTURE%"=="x86" ( 22 | set "arch=x86" 23 | ) else ( 24 | set "arch=x64" 25 | ) 26 | 27 | set "name=opencode-!platform!-!arch!" 28 | set "binary=opencode.exe" 29 | 30 | rem Search for the binary starting from script location 31 | set "resolved=" 32 | set "current_dir=%script_dir%" 33 | 34 | :search_loop 35 | set "candidate=%current_dir%\node_modules\%name%\bin\%binary%" 36 | if exist "%candidate%" ( 37 | set "resolved=%candidate%" 38 | goto :execute 39 | ) 40 | 41 | rem Move up one directory 42 | for %%i in ("%current_dir%") do set "parent_dir=%%~dpi" 43 | set "parent_dir=%parent_dir:~0,-1%" 44 | 45 | rem Check if we've reached the root 46 | if "%current_dir%"=="%parent_dir%" goto :not_found 47 | set "current_dir=%parent_dir%" 48 | goto :search_loop 49 | 50 | :not_found 51 | echo It seems that your package manager failed to install the right version of the opencode CLI for your platform. You can try manually installing the "%name%" package >&2 52 | exit /b 1 53 | 54 | :execute 55 | rem Execute the binary with all arguments 56 | "%resolved%" %* 57 | -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/release-please-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": { 3 | ".": {} 4 | }, 5 | "$schema": "https://raw.githubusercontent.com/stainless-api/release-please/main/schemas/config.json", 6 | "include-v-in-tag": true, 7 | "include-component-in-tag": false, 8 | "versioning": "prerelease", 9 | "prerelease": true, 10 | "bump-minor-pre-major": true, 11 | "bump-patch-for-minor-pre-major": false, 12 | "pull-request-header": "Automated Release PR", 13 | "pull-request-title-pattern": "release: ${version}", 14 | "changelog-sections": [ 15 | { 16 | "type": "feat", 17 | "section": "Features" 18 | }, 19 | { 20 | "type": "fix", 21 | "section": "Bug Fixes" 22 | }, 23 | { 24 | "type": "perf", 25 | "section": "Performance Improvements" 26 | }, 27 | { 28 | "type": "revert", 29 | "section": "Reverts" 30 | }, 31 | { 32 | "type": "chore", 33 | "section": "Chores" 34 | }, 35 | { 36 | "type": "docs", 37 | "section": "Documentation" 38 | }, 39 | { 40 | "type": "style", 41 | "section": "Styles" 42 | }, 43 | { 44 | "type": "refactor", 45 | "section": "Refactors" 46 | }, 47 | { 48 | "type": "test", 49 | "section": "Tests", 50 | "hidden": true 51 | }, 52 | { 53 | "type": "build", 54 | "section": "Build System" 55 | }, 56 | { 57 | "type": "ci", 58 | "section": "Continuous Integration", 59 | "hidden": true 60 | } 61 | ], 62 | "release-type": "go", 63 | "extra-files": [ 64 | "internal/version.go", 65 | "README.md" 66 | ] 67 | } -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/config_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package opencode_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/sst/opencode-sdk-go" 12 | "github.com/sst/opencode-sdk-go/internal/testutil" 13 | "github.com/sst/opencode-sdk-go/option" 14 | ) 15 | 16 | func TestConfigGet(t *testing.T) { 17 | t.Skip("skipped: tests are disabled for the time being") 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := opencode.NewClient( 26 | option.WithBaseURL(baseURL), 27 | ) 28 | _, err := client.Config.Get(context.TODO()) 29 | if err != nil { 30 | var apierr *opencode.Error 31 | if errors.As(err, &apierr) { 32 | t.Log(string(apierr.DumpRequest(true))) 33 | } 34 | t.Fatalf("err should be nil: %s", err.Error()) 35 | } 36 | } 37 | 38 | func TestConfigProviders(t *testing.T) { 39 | t.Skip("skipped: tests are disabled for the time being") 40 | baseURL := "http://localhost:4010" 41 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 42 | baseURL = envURL 43 | } 44 | if !testutil.CheckTestServer(t, baseURL) { 45 | return 46 | } 47 | client := opencode.NewClient( 48 | option.WithBaseURL(baseURL), 49 | ) 50 | _, err := client.Config.Providers(context.TODO()) 51 | if err != nil { 52 | var apierr *opencode.Error 53 | if errors.As(err, &apierr) { 54 | t.Log(string(apierr.DumpRequest(true))) 55 | } 56 | t.Fatalf("err should be nil: %s", err.Error()) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /opencode/packages/web/src/assets/logo-ornate-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/file_test.go: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | package opencode_test 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "os" 9 | "testing" 10 | 11 | "github.com/sst/opencode-sdk-go" 12 | "github.com/sst/opencode-sdk-go/internal/testutil" 13 | "github.com/sst/opencode-sdk-go/option" 14 | ) 15 | 16 | func TestFileRead(t *testing.T) { 17 | t.Skip("skipped: tests are disabled for the time being") 18 | baseURL := "http://localhost:4010" 19 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 20 | baseURL = envURL 21 | } 22 | if !testutil.CheckTestServer(t, baseURL) { 23 | return 24 | } 25 | client := opencode.NewClient( 26 | option.WithBaseURL(baseURL), 27 | ) 28 | _, err := client.File.Read(context.TODO(), opencode.FileReadParams{ 29 | Path: opencode.F("path"), 30 | }) 31 | if err != nil { 32 | var apierr *opencode.Error 33 | if errors.As(err, &apierr) { 34 | t.Log(string(apierr.DumpRequest(true))) 35 | } 36 | t.Fatalf("err should be nil: %s", err.Error()) 37 | } 38 | } 39 | 40 | func TestFileStatus(t *testing.T) { 41 | t.Skip("skipped: tests are disabled for the time being") 42 | baseURL := "http://localhost:4010" 43 | if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { 44 | baseURL = envURL 45 | } 46 | if !testutil.CheckTestServer(t, baseURL) { 47 | return 48 | } 49 | client := opencode.NewClient( 50 | option.WithBaseURL(baseURL), 51 | ) 52 | _, err := client.File.Status(context.TODO()) 53 | if err != nil { 54 | var apierr *opencode.Error 55 | if errors.As(err, &apierr) { 56 | t.Log(string(apierr.DumpRequest(true))) 57 | } 58 | t.Fatalf("err should be nil: %s", err.Error()) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /crates/code-mesh-tui/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "code-mesh-tui" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | license.workspace = true 7 | description = "Interactive Terminal User Interface for the Code-Mesh distributed swarm intelligence system" 8 | homepage = "https://github.com/ruvnet/code-mesh" 9 | repository = "https://github.com/ruvnet/code-mesh" 10 | documentation = "https://docs.rs/code-mesh-tui" 11 | readme = "README.md" 12 | keywords = ["tui", "terminal", "swarm", "visualization", "monitoring"] 13 | categories = ["command-line-utilities", "visualization", "development-tools"] 14 | 15 | [dependencies] 16 | # Core dependencies 17 | code-mesh-core = { version = "0.1.0", path = "../code-mesh-core" } 18 | tokio.workspace = true 19 | anyhow.workspace = true 20 | serde.workspace = true 21 | serde_json.workspace = true 22 | clap.workspace = true 23 | 24 | # TUI dependencies 25 | ratatui.workspace = true 26 | crossterm.workspace = true 27 | tui-textarea.workspace = true 28 | tui-input.workspace = true 29 | 30 | # Text processing and rendering 31 | syntect.workspace = true 32 | pulldown-cmark.workspace = true 33 | unicode-width.workspace = true 34 | unicode-segmentation.workspace = true 35 | 36 | # Color and styling 37 | owo-colors = "4.0" 38 | 39 | # Event handling 40 | futures.workspace = true 41 | futures-util.workspace = true 42 | 43 | # File and path utilities 44 | dirs.workspace = true 45 | walkdir.workspace = true 46 | 47 | # Date/time 48 | chrono.workspace = true 49 | 50 | # UUID generation 51 | uuid.workspace = true 52 | 53 | # Logging 54 | tracing.workspace = true 55 | tracing-subscriber.workspace = true 56 | 57 | [dev-dependencies] 58 | tokio-test.workspace = true 59 | tempfile.workspace = true -------------------------------------------------------------------------------- /opencode/packages/opencode/src/cli/cmd/debug/lsp.ts: -------------------------------------------------------------------------------- 1 | import { LSP } from "../../../lsp" 2 | import { bootstrap } from "../../bootstrap" 3 | import { cmd } from "../cmd" 4 | import { Log } from "../../../util/log" 5 | 6 | export const LSPCommand = cmd({ 7 | command: "lsp", 8 | builder: (yargs) => 9 | yargs.command(DiagnosticsCommand).command(SymbolsCommand).command(DocumentSymbolsCommand).demandCommand(), 10 | async handler() {}, 11 | }) 12 | 13 | const DiagnosticsCommand = cmd({ 14 | command: "diagnostics ", 15 | builder: (yargs) => yargs.positional("file", { type: "string", demandOption: true }), 16 | async handler(args) { 17 | await bootstrap({ cwd: process.cwd() }, async () => { 18 | await LSP.touchFile(args.file, true) 19 | console.log(await LSP.diagnostics()) 20 | }) 21 | }, 22 | }) 23 | 24 | export const SymbolsCommand = cmd({ 25 | command: "symbols ", 26 | builder: (yargs) => yargs.positional("query", { type: "string", demandOption: true }), 27 | async handler(args) { 28 | await bootstrap({ cwd: process.cwd() }, async () => { 29 | using _ = Log.Default.time("symbols") 30 | const results = await LSP.workspaceSymbol(args.query) 31 | console.log(JSON.stringify(results, null, 2)) 32 | }) 33 | }, 34 | }) 35 | 36 | export const DocumentSymbolsCommand = cmd({ 37 | command: "document-symbols ", 38 | builder: (yargs) => yargs.positional("uri", { type: "string", demandOption: true }), 39 | async handler(args) { 40 | await bootstrap({ cwd: process.cwd() }, async () => { 41 | using _ = Log.Default.time("document-symbols") 42 | const results = await LSP.documentSymbol(args.uri) 43 | console.log(JSON.stringify(results, null, 2)) 44 | }) 45 | }, 46 | }) 47 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/config/hooks.ts: -------------------------------------------------------------------------------- 1 | import { App } from "../app/app" 2 | import { Bus } from "../bus" 3 | import { File } from "../file" 4 | import { Session } from "../session" 5 | import { Log } from "../util/log" 6 | import { Config } from "./config" 7 | import path from "path" 8 | 9 | export namespace ConfigHooks { 10 | const log = Log.create({ service: "config.hooks" }) 11 | 12 | export function init() { 13 | log.info("init") 14 | const app = App.info() 15 | 16 | Bus.subscribe(File.Event.Edited, async (payload) => { 17 | const cfg = await Config.get() 18 | const ext = path.extname(payload.properties.file) 19 | for (const item of cfg.experimental?.hook?.file_edited?.[ext] ?? []) { 20 | log.info("file_edited", { 21 | file: payload.properties.file, 22 | command: item.command, 23 | }) 24 | Bun.spawn({ 25 | cmd: item.command.map((x) => x.replace("$FILE", payload.properties.file)), 26 | env: item.environment, 27 | cwd: app.path.cwd, 28 | stdout: "ignore", 29 | stderr: "ignore", 30 | }) 31 | } 32 | }) 33 | 34 | Bus.subscribe(Session.Event.Idle, async () => { 35 | const cfg = await Config.get() 36 | if (cfg.experimental?.hook?.session_completed) { 37 | for (const item of cfg.experimental.hook.session_completed) { 38 | log.info("session_completed", { 39 | command: item.command, 40 | }) 41 | Bun.spawn({ 42 | cmd: item.command, 43 | cwd: App.info().path.cwd, 44 | env: item.environment, 45 | stdout: "ignore", 46 | stderr: "ignore", 47 | }) 48 | } 49 | } 50 | }) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /deny.toml: -------------------------------------------------------------------------------- 1 | # Configuration for cargo-deny 2 | [advisories] 3 | db-path = "~/.cargo/advisory-db" 4 | db-urls = ["https://github.com/rustsec/advisory-db"] 5 | vulnerability = "deny" 6 | unmaintained = "warn" 7 | yanked = "warn" 8 | notice = "warn" 9 | ignore = [ 10 | #"RUSTSEC-0000-0000", 11 | ] 12 | 13 | [licenses] 14 | unlicensed = "deny" 15 | allow = [ 16 | "MIT", 17 | "Apache-2.0", 18 | "Apache-2.0 WITH LLVM-exception", 19 | "BSD-2-Clause", 20 | "BSD-3-Clause", 21 | "ISC", 22 | "Unicode-DFS-2016", 23 | ] 24 | deny = [ 25 | "GPL-2.0", 26 | "GPL-3.0", 27 | "AGPL-1.0", 28 | "AGPL-3.0", 29 | ] 30 | copyleft = "warn" 31 | allow-osi-fsf-free = "neither" 32 | default = "deny" 33 | confidence-threshold = 0.8 34 | exceptions = [ 35 | # Allow ring which has a unique license structure 36 | { allow = ["MIT", "ISC", "OpenSSL"], name = "ring" }, 37 | ] 38 | 39 | [bans] 40 | multiple-versions = "warn" 41 | wildcards = "allow" 42 | highlight = "all" 43 | workspace-default-features = "allow" 44 | external-default-features = "allow" 45 | allow = [ 46 | # Allow common duplicate dependencies 47 | { name = "syn", version = "*" }, 48 | { name = "quote", version = "*" }, 49 | { name = "proc-macro2", version = "*" }, 50 | ] 51 | deny = [ 52 | # Deny old versions with known issues 53 | { name = "openssl", version = "<0.10.55" }, 54 | { name = "tokio", version = "<1.20" }, 55 | # Deny packages that could be problematic 56 | { name = "git2", version = "*" }, # Use libgit2-sys instead 57 | ] 58 | 59 | [sources] 60 | unknown-registry = "warn" 61 | unknown-git = "warn" 62 | allow-registry = ["https://github.com/rust-lang/crates.io-index"] 63 | allow-git = [ 64 | "https://github.com/", 65 | "https://gitlab.com/", 66 | ] -------------------------------------------------------------------------------- /opencode/packages/web/src/content/docs/docs/keybinds.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Keybinds 3 | description: Customize your keybinds. 4 | --- 5 | 6 | opencode has a list of keybinds that you can customize through the opencode config. 7 | 8 | ```json title="opencode.json" 9 | { 10 | "$schema": "https://opencode.ai/config.json", 11 | "keybinds": { 12 | "leader": "ctrl+x", 13 | "help": "h", 14 | "editor_open": "e", 15 | "session_new": "n", 16 | "session_list": "l", 17 | "session_share": "s", 18 | "session_interrupt": "esc", 19 | "session_compact": "c", 20 | "tool_details": "d", 21 | "model_list": "m", 22 | "theme_list": "t", 23 | "project_init": "i", 24 | "input_clear": "ctrl+c", 25 | "input_paste": "ctrl+v", 26 | "input_submit": "enter", 27 | "input_newline": "shift+enter,ctrl+j", 28 | "history_previous": "up", 29 | "history_next": "down", 30 | "messages_page_up": "pgup", 31 | "messages_page_down": "pgdown", 32 | "messages_half_page_up": "ctrl+alt+u", 33 | "messages_half_page_down": "ctrl+alt+d", 34 | "messages_previous": "ctrl+alt+k", 35 | "messages_next": "ctrl+alt+j", 36 | "messages_first": "ctrl+g", 37 | "messages_last": "ctrl+alt+g", 38 | "app_exit": "ctrl+c,q" 39 | } 40 | } 41 | ``` 42 | 43 | ## Leader key 44 | 45 | opencode uses a `leader` key for most keybinds. This avoids conflicts in your terminal. 46 | 47 | By default, `ctrl+x` is the leader key and most actions require you to first press the leader key and then the shortcut. For example, to start a new session you first press `ctrl+x` and then press `n`. 48 | 49 | You don't need to use a leader key for your keybinds but we recommend doing so. 50 | -------------------------------------------------------------------------------- /opencode/.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: publish 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - dev 8 | tags: 9 | - "*" 10 | 11 | concurrency: ${{ github.workflow }}-${{ github.ref }} 12 | 13 | permissions: 14 | contents: write 15 | packages: write 16 | 17 | jobs: 18 | publish: 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: actions/checkout@v3 22 | with: 23 | fetch-depth: 0 24 | 25 | - run: git fetch --force --tags 26 | 27 | - uses: actions/setup-go@v5 28 | with: 29 | go-version: ">=1.24.0" 30 | cache: true 31 | cache-dependency-path: go.sum 32 | 33 | - uses: oven-sh/setup-bun@v2 34 | with: 35 | bun-version: 1.2.17 36 | 37 | - name: Install makepkg 38 | run: | 39 | sudo apt-get update 40 | sudo apt-get install -y pacman-package-manager 41 | 42 | - name: Setup SSH for AUR 43 | run: | 44 | mkdir -p ~/.ssh 45 | echo "${{ secrets.AUR_KEY }}" > ~/.ssh/id_rsa 46 | chmod 600 ~/.ssh/id_rsa 47 | ssh-keyscan -H aur.archlinux.org >> ~/.ssh/known_hosts 48 | git config --global user.email "opencode@sst.dev" 49 | git config --global user.name "opencode" 50 | 51 | - name: Publish 52 | run: | 53 | bun install 54 | if [ "${{ startsWith(github.ref, 'refs/tags/') }}" = "true" ]; then 55 | ./script/publish.ts 56 | else 57 | ./script/publish.ts --snapshot 58 | fi 59 | working-directory: ./packages/opencode 60 | env: 61 | GITHUB_TOKEN: ${{ secrets.SST_GITHUB_TOKEN }} 62 | AUR_KEY: ${{ secrets.AUR_KEY }} 63 | NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }} 64 | -------------------------------------------------------------------------------- /opencode/packages/tui/input/go.sum: -------------------------------------------------------------------------------- 1 | github.com/charmbracelet/x/ansi v0.9.3 h1:BXt5DHS/MKF+LjuK4huWrC6NCvHtexww7dMayh6GXd0= 2 | github.com/charmbracelet/x/ansi v0.9.3/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE= 3 | github.com/charmbracelet/x/windows v0.2.1 h1:3x7vnbpQrjpuq/4L+I4gNsG5htYoCiA5oe9hLjAij5I= 4 | github.com/charmbracelet/x/windows v0.2.1/go.mod h1:ptZp16h40gDYqs5TSawSVW+yiLB13j4kSMA0lSCHL0M= 5 | github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= 6 | github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= 7 | github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= 8 | github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= 9 | github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= 10 | github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= 11 | github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= 12 | github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= 13 | github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= 14 | github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= 15 | github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= 16 | golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= 17 | golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= 18 | golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= 19 | golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 20 | -------------------------------------------------------------------------------- /opencode/packages/tui/sdk/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Setting up the environment 2 | 3 | To set up the repository, run: 4 | 5 | ```sh 6 | $ ./scripts/bootstrap 7 | $ ./scripts/build 8 | ``` 9 | 10 | This will install all the required dependencies and build the SDK. 11 | 12 | You can also [install go 1.18+ manually](https://go.dev/doc/install). 13 | 14 | ## Modifying/Adding code 15 | 16 | Most of the SDK is generated code. Modifications to code will be persisted between generations, but may 17 | result in merge conflicts between manual patches and changes from the generator. The generator will never 18 | modify the contents of the `lib/` and `examples/` directories. 19 | 20 | ## Adding and running examples 21 | 22 | All files in the `examples/` directory are not modified by the generator and can be freely edited or added to. 23 | 24 | ```go 25 | # add an example to examples//main.go 26 | 27 | package main 28 | 29 | func main() { 30 | // ... 31 | } 32 | ``` 33 | 34 | ```sh 35 | $ go run ./examples/ 36 | ``` 37 | 38 | ## Using the repository from source 39 | 40 | To use a local version of this library from source in another project, edit the `go.mod` with a replace 41 | directive. This can be done through the CLI with the following: 42 | 43 | ```sh 44 | $ go mod edit -replace github.com/sst/opencode-sdk-go=/path/to/opencode-sdk-go 45 | ``` 46 | 47 | ## Running tests 48 | 49 | Most tests require you to [set up a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests. 50 | 51 | ```sh 52 | # you will need npm installed 53 | $ npx prism mock path/to/your/openapi.yml 54 | ``` 55 | 56 | ```sh 57 | $ ./scripts/test 58 | ``` 59 | 60 | ## Formatting 61 | 62 | This library uses the standard gofmt code formatter: 63 | 64 | ```sh 65 | $ ./scripts/format 66 | ``` 67 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/tool/todo.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod" 2 | import { Tool } from "./tool" 3 | import DESCRIPTION_WRITE from "./todowrite.txt" 4 | import { App } from "../app/app" 5 | 6 | const TodoInfo = z.object({ 7 | content: z.string().min(1).describe("Brief description of the task"), 8 | status: z.enum(["pending", "in_progress", "completed", "cancelled"]).describe("Current status of the task"), 9 | priority: z.enum(["high", "medium", "low"]).describe("Priority level of the task"), 10 | id: z.string().describe("Unique identifier for the todo item"), 11 | }) 12 | type TodoInfo = z.infer 13 | 14 | const state = App.state("todo-tool", () => { 15 | const todos: { 16 | [sessionId: string]: TodoInfo[] 17 | } = {} 18 | return todos 19 | }) 20 | 21 | export const TodoWriteTool = Tool.define({ 22 | id: "todowrite", 23 | description: DESCRIPTION_WRITE, 24 | parameters: z.object({ 25 | todos: z.array(TodoInfo).describe("The updated todo list"), 26 | }), 27 | async execute(params, opts) { 28 | const todos = state() 29 | todos[opts.sessionID] = params.todos 30 | return { 31 | title: `${params.todos.filter((x) => x.status !== "completed").length} todos`, 32 | output: JSON.stringify(params.todos, null, 2), 33 | metadata: { 34 | todos: params.todos, 35 | }, 36 | } 37 | }, 38 | }) 39 | 40 | export const TodoReadTool = Tool.define({ 41 | id: "todoread", 42 | description: "Use this tool to read your todo list", 43 | parameters: z.object({}), 44 | async execute(_params, opts) { 45 | const todos = state()[opts.sessionID] ?? [] 46 | return { 47 | title: `${todos.filter((x) => x.status !== "completed").length} todos`, 48 | metadata: { 49 | todos, 50 | }, 51 | output: JSON.stringify(todos, null, 2), 52 | } 53 | }, 54 | }) 55 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/tool/bash.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod" 2 | import { Tool } from "./tool" 3 | import DESCRIPTION from "./bash.txt" 4 | import { App } from "../app/app" 5 | 6 | const MAX_OUTPUT_LENGTH = 30000 7 | const DEFAULT_TIMEOUT = 1 * 60 * 1000 8 | const MAX_TIMEOUT = 10 * 60 * 1000 9 | 10 | export const BashTool = Tool.define({ 11 | id: "bash", 12 | description: DESCRIPTION, 13 | parameters: z.object({ 14 | command: z.string().describe("The command to execute"), 15 | timeout: z.number().min(0).max(MAX_TIMEOUT).describe("Optional timeout in milliseconds").optional(), 16 | description: z 17 | .string() 18 | .describe( 19 | "Clear, concise description of what this command does in 5-10 words. Examples:\nInput: ls\nOutput: Lists files in current directory\n\nInput: git status\nOutput: Shows working tree status\n\nInput: npm install\nOutput: Installs package dependencies\n\nInput: mkdir foo\nOutput: Creates directory 'foo'", 20 | ), 21 | }), 22 | async execute(params, ctx) { 23 | const timeout = Math.min(params.timeout ?? DEFAULT_TIMEOUT, MAX_TIMEOUT) 24 | 25 | const process = Bun.spawn({ 26 | cmd: ["bash", "-c", params.command], 27 | cwd: App.info().path.cwd, 28 | maxBuffer: MAX_OUTPUT_LENGTH, 29 | signal: ctx.abort, 30 | timeout: timeout, 31 | stdout: "pipe", 32 | stderr: "pipe", 33 | }) 34 | await process.exited 35 | const stdout = await new Response(process.stdout).text() 36 | const stderr = await new Response(process.stderr).text() 37 | 38 | return { 39 | title: params.command, 40 | metadata: { 41 | stderr, 42 | stdout, 43 | exit: process.exitCode, 44 | description: params.description, 45 | }, 46 | output: [``, stdout ?? "", ``, ``, stderr ?? "", ``].join("\n"), 47 | } 48 | }, 49 | }) 50 | -------------------------------------------------------------------------------- /opencode/packages/opencode/AGENTS.md: -------------------------------------------------------------------------------- 1 | # opencode agent guidelines 2 | 3 | ## Build/Test Commands 4 | 5 | - **Install**: `bun install` 6 | - **Run**: `bun run index.ts` 7 | - **Typecheck**: `bun run typecheck` (npm run typecheck) 8 | - **Test**: `bun test` (runs all tests) 9 | - **Single test**: `bun test test/tool/tool.test.ts` (specific test file) 10 | 11 | ## Code Style 12 | 13 | - **Runtime**: Bun with TypeScript ESM modules 14 | - **Imports**: Use relative imports for local modules, named imports preferred 15 | - **Types**: Zod schemas for validation, TypeScript interfaces for structure 16 | - **Naming**: camelCase for variables/functions, PascalCase for classes/namespaces 17 | - **Error handling**: Use Result patterns, avoid throwing exceptions in tools 18 | - **File structure**: Namespace-based organization (e.g., `Tool.define()`, `Session.create()`) 19 | 20 | ## IMPORTANT 21 | 22 | - Try to keep things in one function unless composable or reusable 23 | - DO NOT do unnecessary destructuring of variables 24 | - DO NOT use `else` statements unless necessary 25 | - DO NOT use `try`/`catch` if it can be avoided 26 | - AVOID `try`/`catch` where possible 27 | - AVOID `else` statements 28 | - AVOID using `any` type 29 | - AVOID `let` statements 30 | - PREFER single word variable names where possible 31 | - Use as many bun apis as possible like Bun.file() 32 | 33 | ## Architecture 34 | 35 | - **Tools**: Implement `Tool.Info` interface with `execute()` method 36 | - **Context**: Pass `sessionID` in tool context, use `App.provide()` for DI 37 | - **Validation**: All inputs validated with Zod schemas 38 | - **Logging**: Use `Log.create({ service: "name" })` pattern 39 | - **Storage**: Use `Storage` namespace for persistence 40 | - **API Client**: Go TUI communicates with TypeScript server via stainless SDK. When adding/modifying server endpoints in `packages/opencode/src/server/server.ts`, ask the user to generate a new client SDK to proceed with client-side changes. 41 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/session/mode.ts: -------------------------------------------------------------------------------- 1 | import { mergeDeep } from "remeda" 2 | import { App } from "../app/app" 3 | import { Config } from "../config/config" 4 | import z from "zod" 5 | 6 | export namespace Mode { 7 | export const Info = z 8 | .object({ 9 | name: z.string(), 10 | model: z 11 | .object({ 12 | modelID: z.string(), 13 | providerID: z.string(), 14 | }) 15 | .optional(), 16 | prompt: z.string().optional(), 17 | tools: z.record(z.boolean()), 18 | }) 19 | .openapi({ 20 | ref: "Mode", 21 | }) 22 | export type Info = z.infer 23 | const state = App.state("mode", async () => { 24 | const cfg = await Config.get() 25 | const mode = mergeDeep( 26 | { 27 | build: {}, 28 | plan: { 29 | tools: { 30 | write: false, 31 | edit: false, 32 | patch: false, 33 | bash: false, 34 | }, 35 | }, 36 | }, 37 | cfg.mode ?? {}, 38 | ) 39 | const result: Record = {} 40 | for (const [key, value] of Object.entries(mode)) { 41 | let item = result[key] 42 | if (!item) 43 | item = result[key] = { 44 | name: key, 45 | tools: {}, 46 | } 47 | const model = value.model ?? cfg.model 48 | if (model) { 49 | const [providerID, ...rest] = model.split("/") 50 | const modelID = rest.join("/") 51 | item.model = { 52 | modelID, 53 | providerID, 54 | } 55 | } 56 | if (value.prompt) item.prompt = value.prompt 57 | if (value.tools) item.tools = value.tools 58 | } 59 | 60 | return result 61 | }) 62 | 63 | export async function get(mode: string) { 64 | return state().then((x) => x[mode]) 65 | } 66 | 67 | export async function list() { 68 | return state().then((x) => Object.values(x)) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /opencode/packages/opencode/src/format/index.ts: -------------------------------------------------------------------------------- 1 | import { App } from "../app/app" 2 | import { Bus } from "../bus" 3 | import { File } from "../file" 4 | import { Log } from "../util/log" 5 | import path from "path" 6 | 7 | import * as Formatter from "./formatter" 8 | 9 | export namespace Format { 10 | const log = Log.create({ service: "format" }) 11 | 12 | const state = App.state("format", () => { 13 | const enabled: Record = {} 14 | 15 | return { 16 | enabled, 17 | } 18 | }) 19 | 20 | async function isEnabled(item: Formatter.Info) { 21 | const s = state() 22 | let status = s.enabled[item.name] 23 | if (status === undefined) { 24 | status = await item.enabled() 25 | s.enabled[item.name] = status 26 | } 27 | return status 28 | } 29 | 30 | async function getFormatter(ext: string) { 31 | const result = [] 32 | for (const item of Object.values(Formatter)) { 33 | if (!item.extensions.includes(ext)) continue 34 | if (!(await isEnabled(item))) continue 35 | result.push(item) 36 | } 37 | return result 38 | } 39 | 40 | export function init() { 41 | log.info("init") 42 | Bus.subscribe(File.Event.Edited, async (payload) => { 43 | const file = payload.properties.file 44 | log.info("formatting", { file }) 45 | const ext = path.extname(file) 46 | 47 | for (const item of await getFormatter(ext)) { 48 | log.info("running", { command: item.command }) 49 | const proc = Bun.spawn({ 50 | cmd: item.command.map((x) => x.replace("$FILE", file)), 51 | cwd: App.info().path.cwd, 52 | env: item.environment, 53 | stdout: "ignore", 54 | stderr: "ignore", 55 | }) 56 | const exit = await proc.exited 57 | if (exit !== 0) 58 | log.error("failed", { 59 | command: item.command, 60 | ...item.environment, 61 | }) 62 | } 63 | }) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /crates/code-mesh-core/src/planner/mod.rs: -------------------------------------------------------------------------------- 1 | //! Task planning for Code Mesh 2 | 3 | use async_trait::async_trait; 4 | use serde::{Deserialize, Serialize}; 5 | 6 | /// Planner trait for task decomposition and planning 7 | #[async_trait] 8 | pub trait Planner: Send + Sync { 9 | /// Create a plan from a high-level task description 10 | async fn plan(&self, task: &str, context: PlanContext) -> crate::Result; 11 | 12 | /// Update a plan based on progress 13 | async fn update_plan(&self, plan: &mut Plan, progress: &Progress) -> crate::Result<()>; 14 | } 15 | 16 | /// Planning context 17 | #[derive(Debug, Clone, Serialize, Deserialize)] 18 | pub struct PlanContext { 19 | pub available_tools: Vec, 20 | pub constraints: Vec, 21 | pub preferences: serde_json::Value, 22 | } 23 | 24 | /// Execution plan 25 | #[derive(Debug, Clone, Serialize, Deserialize)] 26 | pub struct Plan { 27 | pub id: String, 28 | pub goal: String, 29 | pub steps: Vec, 30 | pub dependencies: Vec, 31 | } 32 | 33 | /// Plan step 34 | #[derive(Debug, Clone, Serialize, Deserialize)] 35 | pub struct Step { 36 | pub id: String, 37 | pub description: String, 38 | pub tool: Option, 39 | pub parameters: serde_json::Value, 40 | pub expected_outcome: String, 41 | } 42 | 43 | /// Step dependency 44 | #[derive(Debug, Clone, Serialize, Deserialize)] 45 | pub struct Dependency { 46 | pub from: String, 47 | pub to: String, 48 | pub dependency_type: DependencyType, 49 | } 50 | 51 | #[derive(Debug, Clone, Copy, Serialize, Deserialize)] 52 | #[serde(rename_all = "snake_case")] 53 | pub enum DependencyType { 54 | Sequential, 55 | Parallel, 56 | Conditional, 57 | } 58 | 59 | /// Progress tracking 60 | #[derive(Debug, Clone, Serialize, Deserialize)] 61 | pub struct Progress { 62 | pub completed_steps: Vec, 63 | pub failed_steps: Vec<(String, String)>, // (step_id, error) 64 | pub current_step: Option, 65 | } -------------------------------------------------------------------------------- /opencode/packages/web/src/components/share/content-bash.tsx: -------------------------------------------------------------------------------- 1 | import style from "./content-bash.module.css" 2 | import { createResource, createSignal } from "solid-js" 3 | import { createOverflow } from "./common" 4 | import { codeToHtml } from "shiki" 5 | 6 | interface Props { 7 | command: string 8 | output: string 9 | description?: string 10 | expand?: boolean 11 | } 12 | 13 | export function ContentBash(props: Props) { 14 | const [commandHtml] = createResource( 15 | () => props.command, 16 | async (command) => { 17 | return codeToHtml(command || "", { 18 | lang: "bash", 19 | themes: { 20 | light: "github-light", 21 | dark: "github-dark", 22 | }, 23 | }) 24 | }, 25 | ) 26 | 27 | const [outputHtml] = createResource( 28 | () => props.output, 29 | async (output) => { 30 | return codeToHtml(output || "", { 31 | lang: "console", 32 | themes: { 33 | light: "github-light", 34 | dark: "github-dark", 35 | }, 36 | }) 37 | }, 38 | ) 39 | 40 | const [expanded, setExpanded] = createSignal(false) 41 | const overflow = createOverflow() 42 | 43 | return ( 44 |
45 |
46 |
47 | {props.description} 48 |
49 |
50 |
51 |
52 |
53 |
54 | 55 | {!props.expand && overflow.status && ( 56 | 64 | )} 65 |
66 | ) 67 | } 68 | -------------------------------------------------------------------------------- /npm/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const WasmPackPlugin = require('@wasm-tool/wasm-pack-plugin'); 3 | 4 | module.exports = (env, argv) => { 5 | const isProduction = argv.mode === 'production'; 6 | 7 | return { 8 | mode: isProduction ? 'production' : 'development', 9 | entry: { 10 | index: './src/index.ts', 11 | browser: './src/browser.ts', 12 | 'wasm-runner': './src/wasm-runner.ts' 13 | }, 14 | output: { 15 | path: path.resolve(__dirname, 'dist'), 16 | filename: '[name].js', 17 | library: { 18 | name: 'CodeMesh', 19 | type: 'umd' 20 | }, 21 | globalObject: 'this', 22 | clean: true 23 | }, 24 | resolve: { 25 | extensions: ['.ts', '.js', '.wasm'], 26 | fallback: { 27 | "fs": false, 28 | "path": false, 29 | "os": false, 30 | "crypto": false, 31 | "stream": false, 32 | "buffer": false 33 | } 34 | }, 35 | module: { 36 | rules: [ 37 | { 38 | test: /\.ts$/, 39 | use: 'ts-loader', 40 | exclude: /node_modules/ 41 | }, 42 | { 43 | test: /\.wasm$/, 44 | type: 'webassembly/async' 45 | } 46 | ] 47 | }, 48 | plugins: [ 49 | new WasmPackPlugin({ 50 | crateDirectory: path.resolve(__dirname, '../crates/code-mesh-wasm'), 51 | outDir: path.resolve(__dirname, 'wasm/bundler'), 52 | args: '--log-level warn', 53 | extraArgs: '--target bundler' 54 | }) 55 | ], 56 | experiments: { 57 | asyncWebAssembly: true 58 | }, 59 | devtool: isProduction ? 'source-map' : 'eval-source-map', 60 | optimization: { 61 | minimize: isProduction, 62 | splitChunks: { 63 | chunks: 'all', 64 | cacheGroups: { 65 | wasm: { 66 | test: /\.wasm$/, 67 | name: 'wasm', 68 | chunks: 'all' 69 | } 70 | } 71 | } 72 | } 73 | }; 74 | }; -------------------------------------------------------------------------------- /opencode/packages/opencode/src/tool/task.txt: -------------------------------------------------------------------------------- 1 | Launch a new agent that has access to the following tools: Bash, Glob, Grep, LS, Read, Edit, MultiEdit, Write, NotebookRead, NotebookEdit, WebFetch, TodoRead, TodoWrite, WebSearch. When you are searching for a keyword or file and are not confident that you will find the right match in the first few tries, use the Agent tool to perform the search for you. 2 | 3 | When to use the Agent tool: 4 | - If you are searching for a keyword like "config" or "logger", or for questions like "which file does X?", the Agent tool is strongly recommended 5 | 6 | When NOT to use the Agent tool: 7 | - If you want to read a specific file path, use the Read or Glob tool instead of the Agent tool, to find the match more quickly 8 | - If you are searching for a specific class definition like "class Foo", use the Glob tool instead, to find the match more quickly 9 | - If you are searching for code within a specific file or set of 2-3 files, use the Read tool instead of the Agent tool, to find the match more quickly 10 | 11 | Usage notes: 12 | 1. Launch multiple agents concurrently whenever possible, to maximize performance; to do that, use a single message with multiple tool uses 13 | 2. When the agent is done, it will return a single message back to you. The result returned by the agent is not visible to the user. To show the user the result, you should send a text message back to the user with a concise summary of the result. 14 | 3. Each agent invocation is stateless. You will not be able to send additional messages to the agent, nor will the agent be able to communicate with you outside of its final report. Therefore, your prompt should contain a highly detailed task description for the agent to perform autonomously and you should specify exactly what information the agent should return back to you in its final and only message to you. 15 | 4. The agent's outputs should generally be trusted 16 | 5. Clearly tell the agent whether you expect it to write code or just to do research (search, file reads, web fetches, etc.), since it is not aware of the user's intent 17 | -------------------------------------------------------------------------------- /opencode/packages/tui/.goreleaser.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | project_name: opencode 3 | before: 4 | hooks: 5 | builds: 6 | - env: 7 | - CGO_ENABLED=0 8 | goos: 9 | - linux 10 | - darwin 11 | goarch: 12 | - amd64 13 | - arm64 14 | ldflags: 15 | - -s -w -X github.com/sst/opencode/internal/version.Version={{.Version}} 16 | main: ./main.go 17 | 18 | archives: 19 | - format: tar.gz 20 | name_template: >- 21 | opencode- 22 | {{- if eq .Os "darwin" }}mac- 23 | {{- else if eq .Os "windows" }}windows- 24 | {{- else if eq .Os "linux" }}linux-{{end}} 25 | {{- if eq .Arch "amd64" }}x86_64 26 | {{- else if eq .Arch "#86" }}i386 27 | {{- else }}{{ .Arch }}{{ end }} 28 | {{- if .Arm }}v{{ .Arm }}{{ end }} 29 | format_overrides: 30 | - goos: windows 31 | format: zip 32 | checksum: 33 | name_template: "checksums.txt" 34 | snapshot: 35 | name_template: "0.0.0-{{ .Timestamp }}" 36 | aurs: 37 | - name: opencode 38 | homepage: "https://github.com/sst/opencode" 39 | description: "terminal based agent that can build anything" 40 | maintainers: 41 | - "dax" 42 | - "adam" 43 | license: "MIT" 44 | private_key: "{{ .Env.AUR_KEY }}" 45 | git_url: "ssh://aur@aur.archlinux.org/opencode-bin.git" 46 | provides: 47 | - opencode 48 | conflicts: 49 | - opencode 50 | package: |- 51 | install -Dm755 ./opencode "${pkgdir}/usr/bin/opencode" 52 | brews: 53 | - repository: 54 | owner: sst 55 | name: homebrew-tap 56 | nfpms: 57 | - maintainer: kujtimiihoxha 58 | description: terminal based agent that can build anything 59 | formats: 60 | - deb 61 | - rpm 62 | file_name_template: >- 63 | {{ .ProjectName }}- 64 | {{- if eq .Os "darwin" }}mac 65 | {{- else }}{{ .Os }}{{ end }}-{{ .Arch }} 66 | 67 | changelog: 68 | sort: asc 69 | filters: 70 | exclude: 71 | - "^docs:" 72 | - "^doc:" 73 | - "^test:" 74 | - "^ci:" 75 | - "^ignore:" 76 | - "^example:" 77 | - "^wip:" 78 | -------------------------------------------------------------------------------- /opencode/packages/opencode/bin/opencode: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | if [ -n "$OPENCODE_BIN_PATH" ]; then 5 | resolved="$OPENCODE_BIN_PATH" 6 | else 7 | # Get the real path of this script, resolving any symlinks 8 | script_path="$0" 9 | while [ -L "$script_path" ]; do 10 | link_target="$(readlink "$script_path")" 11 | case "$link_target" in 12 | /*) script_path="$link_target" ;; 13 | *) script_path="$(dirname "$script_path")/$link_target" ;; 14 | esac 15 | done 16 | script_dir="$(dirname "$script_path")" 17 | script_dir="$(cd "$script_dir" && pwd)" 18 | 19 | # Map platform names 20 | case "$(uname -s)" in 21 | Darwin) platform="darwin" ;; 22 | Linux) platform="linux" ;; 23 | MINGW*|CYGWIN*|MSYS*) platform="win32" ;; 24 | *) platform="$(uname -s | tr '[:upper:]' '[:lower:]')" ;; 25 | esac 26 | 27 | # Map architecture names 28 | case "$(uname -m)" in 29 | x86_64|amd64) arch="x64" ;; 30 | aarch64) arch="arm64" ;; 31 | armv7l) arch="arm" ;; 32 | *) arch="$(uname -m)" ;; 33 | esac 34 | 35 | name="opencode-${platform}-${arch}" 36 | binary="opencode" 37 | [ "$platform" = "win32" ] && binary="opencode.exe" 38 | 39 | # Search for the binary starting from real script location 40 | resolved="" 41 | current_dir="$script_dir" 42 | while [ "$current_dir" != "/" ]; do 43 | candidate="$current_dir/node_modules/$name/bin/$binary" 44 | if [ -f "$candidate" ]; then 45 | resolved="$candidate" 46 | break 47 | fi 48 | current_dir="$(dirname "$current_dir")" 49 | done 50 | 51 | if [ -z "$resolved" ]; then 52 | printf "It seems that your package manager failed to install the right version of the opencode CLI for your platform. You can try manually installing the \"%s\" package\n" "$name" >&2 53 | exit 1 54 | fi 55 | fi 56 | 57 | # Handle SIGINT gracefully 58 | trap '' INT 59 | 60 | # Execute the binary with all arguments 61 | exec "$resolved" "$@" 62 | -------------------------------------------------------------------------------- /docs/src/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | [Introduction](README.md) 4 | 5 | # Getting Started 6 | 7 | - [Quick Start](getting-started/quick-start.md) 8 | - [Installation](getting-started/installation.md) 9 | - [First Steps](getting-started/first-steps.md) 10 | - [Configuration](getting-started/configuration.md) 11 | 12 | # User Guide 13 | 14 | - [CLI Reference](user-guide/cli-reference.md) 15 | - [Authentication](user-guide/authentication.md) 16 | - [Sessions & Memory](user-guide/sessions.md) 17 | - [Multi-Agent Workflows](user-guide/multi-agent.md) 18 | - [Tool System](user-guide/tools.md) 19 | - [WASM/Browser Usage](user-guide/wasm.md) 20 | 21 | # Migration Guide 22 | 23 | - [From OpenCode](migration/from-opencode.md) 24 | - [Configuration Migration](migration/configuration.md) 25 | - [Breaking Changes](migration/breaking-changes.md) 26 | 27 | # Developer Guide 28 | 29 | - [Architecture Overview](development/architecture.md) 30 | - [Contributing Guidelines](development/contributing.md) 31 | - [Development Setup](development/setup.md) 32 | - [Building & Testing](development/building.md) 33 | - [API Documentation](development/api.md) 34 | - [Tool Development](development/tool-development.md) 35 | - [Provider Development](development/provider-development.md) 36 | 37 | # Examples & Tutorials 38 | 39 | - [Common Workflows](examples/workflows.md) 40 | - [Integration Examples](examples/integrations.md) 41 | - [Advanced Usage](examples/advanced.md) 42 | - [Best Practices](examples/best-practices.md) 43 | 44 | # Reference 45 | 46 | - [Architecture Decision Records](reference/adrs/README.md) 47 | - [ADR-001: Multi-Agent Architecture](reference/adrs/001-multi-agent-architecture.md) 48 | - [ADR-002: WASM Compilation Strategy](reference/adrs/002-wasm-strategy.md) 49 | - [ADR-003: Storage Abstraction](reference/adrs/003-storage-abstraction.md) 50 | - [Troubleshooting](reference/troubleshooting.md) 51 | - [FAQ](reference/faq.md) 52 | - [Glossary](reference/glossary.md) 53 | 54 | # Appendices 55 | 56 | - [License](appendices/license.md) 57 | - [Changelog](appendices/changelog.md) 58 | - [Acknowledgments](appendices/acknowledgments.md) -------------------------------------------------------------------------------- /crates/code-mesh-core/src/storage/mod.rs: -------------------------------------------------------------------------------- 1 | //! Storage abstractions for Code Mesh 2 | 3 | use async_trait::async_trait; 4 | use std::path::PathBuf; 5 | 6 | mod file; 7 | 8 | /// Storage trait for persistent data 9 | #[async_trait] 10 | pub trait Storage: Send + Sync { 11 | /// Store a value with a key 12 | async fn set(&self, key: &str, value: &[u8]) -> Result<(), StorageError>; 13 | 14 | /// Retrieve a value by key 15 | async fn get(&self, key: &str) -> Result>, StorageError>; 16 | 17 | /// Delete a value by key 18 | async fn delete(&self, key: &str) -> Result<(), StorageError>; 19 | 20 | /// List all keys with optional prefix 21 | async fn list(&self, prefix: Option<&str>) -> Result, StorageError>; 22 | 23 | /// Check if a key exists 24 | async fn exists(&self, key: &str) -> Result; 25 | } 26 | 27 | /// Storage errors 28 | #[derive(Debug, thiserror::Error)] 29 | pub enum StorageError { 30 | #[error("IO error: {0}")] 31 | Io(#[from] std::io::Error), 32 | 33 | #[error("Serialization error: {0}")] 34 | Serialization(#[from] serde_json::Error), 35 | 36 | #[error("Key not found: {0}")] 37 | KeyNotFound(String), 38 | 39 | #[error("Storage error: {0}")] 40 | Other(String), 41 | } 42 | 43 | /// File-based storage implementation 44 | pub struct FileStorage { 45 | base_path: PathBuf, 46 | } 47 | 48 | impl FileStorage { 49 | pub fn new(base_path: PathBuf) -> Self { 50 | Self { base_path } 51 | } 52 | 53 | pub fn default() -> Result { 54 | let data_dir = dirs::data_dir() 55 | .ok_or_else(|| StorageError::Other("Could not find data directory".to_string()))?; 56 | let base_path = data_dir.join("code-mesh").join("storage"); 57 | Ok(Self::new(base_path)) 58 | } 59 | 60 | fn key_to_path(&self, key: &str) -> PathBuf { 61 | // Sanitize key to prevent path traversal 62 | let safe_key = key.replace(['/', '\\'], "_").replace("..", "_"); 63 | self.base_path.join(safe_key) 64 | } 65 | } --------------------------------------------------------------------------------