diff --git a/.envrc b/.envrc new file mode 100644 index 0000000000..533548463c --- /dev/null +++ b/.envrc @@ -0,0 +1,4 @@ +# Check if nix command is available before trying to use flake +if command -v nix >/dev/null 2>&1; then + use flake +fi \ No newline at end of file diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index b4369fa1a4..ec41b02e95 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,3 +1,35 @@ -### What does this PR do? +## Context -### How did you verify your code works? + + +## Implementation + + + +## Screenshots + +| before | after | +| ------ | ----- | +| | | + +## How to Test + + + +## Get in Touch + + diff --git a/.github/workflows/publish-next.yml b/.github/workflows/publish-next.yml deleted file mode 100644 index e55cbb8d1f..0000000000 --- a/.github/workflows/publish-next.yml +++ /dev/null @@ -1,72 +0,0 @@ -# kilocode_change - new file -# -# Next Release Workflow for Kilo CLI -# =================================== -# -# HOW TO RELEASE: -# 1. Go to GitHub Actions → publish-next -# 2. Click "Run workflow" -# 3. Optionally enter a version (e.g., 1.2.0-next.1) -# 4. Click "Run workflow" -# -# HOW USERS INSTALL: -# npm install -g @kilocode/cli@next -# -# REQUIRED GITHUB SECRETS: -# - NPM_TOKEN: npm authentication token with publish access to @kilocode/cli -# (Get from: npmjs.com → Access Tokens → Generate New Token → Automation) -# -# WHAT THIS DOES: -# - Runs the existing publish-start.ts script with OPENCODE_CHANNEL=next -# - Builds all platform binaries (Linux, macOS, Windows, x64, ARM64) -# - Publishes to npm with @next tag (won't affect stable users) -# - Version format: 0.0.0-next-{timestamp} (auto) or custom (manual input) -# - Does NOT create git tags or GitHub releases (preview mode) -# -name: publish-next -run-name: "next release ${{ inputs.version || 'auto' }}" - -on: - workflow_dispatch: - inputs: - version: - description: "Override version (optional, e.g., 1.2.0-next.1)" - required: false - type: string - -concurrency: ${{ github.workflow }}-${{ github.ref }}-${{ inputs.version }} - -permissions: - id-token: write - contents: write - packages: write - -jobs: - publish-next: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - run: git fetch --force --tags - - - uses: ./.github/actions/setup-bun - - - uses: actions/setup-node@v4 - with: - node-version: "24" - registry-url: "https://registry.npmjs.org" - - - name: Publish Next - run: ./script/publish-start.ts - env: - OPENCODE_CHANNEL: next - OPENCODE_VERSION: ${{ inputs.version }} - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - uses: actions/upload-artifact@v4 - with: - name: kilocode-cli-next - path: packages/opencode/dist diff --git a/.github/workflows/publish-stable.yml b/.github/workflows/publish-stable.yml index 8051910a2b..840f7e8b1f 100644 --- a/.github/workflows/publish-stable.yml +++ b/.github/workflows/publish-stable.yml @@ -53,6 +53,19 @@ jobs: - uses: ./.github/actions/setup-bun + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - uses: actions/setup-node@v4 with: node-version: "24" @@ -68,6 +81,7 @@ jobs: env: OPENCODE_CHANNEL: latest OPENCODE_VERSION: ${{ inputs.version }} + OPENCODE_SKIP_NOTES: "1" NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000..b4dca2d1c5 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,128 @@ +# Kilo Code Community Code of Conduct + +## Our Pledge + +We as community members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +- Demonstrating empathy and kindness toward other people +- Being respectful of differing opinions, viewpoints, and experiences +- Giving and gracefully accepting constructive feedback +- Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +- Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +- The use of sexualized language or imagery, and sexual attention or + advances of any kind +- Trolling, insulting or derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or email + address, without their explicit permission +- Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +hi@kilo.ai. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9b12e41a25..1d00372f96 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,32 +1,22 @@ -# Contributing to OpenCode +# Contributing to Kilo CLI -We want to make it easy for you to contribute to OpenCode. Here are the most common type of changes that get merged: +See [the Documentation for details on contributing](https://kilo.ai/docs/extending/contributing-to-kilo). -- Bug fixes -- Additional LSPs / Formatters -- Improvements to LLM performance -- Support for new providers -- Fixes for environment-specific quirks -- Missing standard behavior -- Documentation improvements +## TL;DR -However, any UI or core product feature must go through a design review with the core team before implementation. +There are lots of ways to contribute to the project: -If you are unsure if a PR would be accepted, feel free to ask a maintainer or look for issues with any of the following labels: +- **Code Contributions:** Implement new features or fix bugs +- **Documentation:** Improve existing docs or create new guides +- **Bug Reports:** Report issues you encounter +- **Feature Requests:** Suggest new features or improvements +- **Community Support:** Help other users in the community -- [`help wanted`](https://github.com/Kilo-Org/kilo/issues?q=is%3Aissue%20state%3Aopen%20label%3Ahelp-wanted) -- [`good first issue`](https://github.com/Kilo-Org/kilo/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22good%20first%20issue%22) -- [`bug`](https://github.com/Kilo-Org/kilo/issues?q=is%3Aissue%20state%3Aopen%20label%3Abug) -- [`perf`](https://github.com/Kilo-Org/kilo/issues?q=is%3Aopen%20is%3Aissue%20label%3A%22perf%22) +The Kilo Community is [on Discord](https://kilo.ai/discord). -> [!NOTE] -> PRs that ignore these guardrails will likely be closed. +## Developing Kilo CLI -Want to take on an issue? Leave a comment and a maintainer may assign it to you unless it is something we are already working on. - -## Developing OpenCode - -- Requirements: Bun 1.3+ +- **Requirements:** Bun 1.3+ - Install dependencies and start the dev server from the repo root: ```bash @@ -36,225 +26,63 @@ Want to take on an issue? Leave a comment and a maintainer may assign it to you ### Running against a different directory -By default, `bun dev` runs OpenCode in the `packages/opencode` directory. To run it against a different directory or repository: +By default, `bun dev` runs Kilo CLI in the `packages/kilo-cli` directory. To run it against a different directory or repository: ```bash bun dev ``` -To run OpenCode in the root of the opencode repo itself: +To run Kilo CLI in the root of the repo itself: ```bash bun dev . ``` -### Building a "localcode" +### Building a "local" binary To compile a standalone executable: ```bash -./packages/opencode/script/build.ts --single +./packages/kilo-cli/script/build.ts --single ``` Then run it with: ```bash -./packages/opencode/dist/opencode-/bin/opencode +./packages/kilo-cli/dist/kilo-cli-/bin/kilo ``` Replace `` with your platform (e.g., `darwin-arm64`, `linux-x64`). -- Core pieces: - - `packages/opencode`: OpenCode core business logic & server. - - `packages/opencode/src/cli/cmd/tui/`: The TUI code, written in SolidJS with [opentui](https://github.com/sst/opentui) - - `packages/app`: The shared web UI components, written in SolidJS - - `packages/desktop`: The native desktop app, built with Tauri (wraps `packages/app`) - - `packages/plugin`: Source for `@kilocode/plugin` +### Understanding bun dev vs kilo -### Understanding bun dev vs opencode - -During development, `bun dev` is the local equivalent of the built `opencode` command. Both run the same CLI interface: +During development, `bun dev` is the local equivalent of the built `kilo` command. Both run the same CLI interface: ```bash # Development (from project root) bun dev --help # Show all available commands bun dev serve # Start headless API server bun dev web # Start server + open web interface -bun dev # Start TUI in specific directory # Production -opencode --help # Show all available commands -opencode serve # Start headless API server -opencode web # Start server + open web interface -opencode # Start TUI in specific directory +kilo --help # Show all available commands +kilo serve # Start headless API server +kilo web # Start server + open web interface ``` -### Running the API Server +### Pull Request Expectations -To start the OpenCode headless API server: - -```bash -bun dev serve -``` - -This starts the headless server on port 4096 by default. You can specify a different port: - -```bash -bun dev serve --port 8080 -``` - -### Running the Web App - -To test UI changes during development: - -1. **First, start the OpenCode server** (see [Running the API Server](#running-the-api-server) section above) -2. **Then run the web app:** - -```bash -bun run --cwd packages/app dev -``` - -This starts a local dev server at http://localhost:5173 (or similar port shown in output). Most UI changes can be tested here, but the server must be running for full functionality. - -### Running the Desktop App - -The desktop app is a native Tauri application that wraps the web UI. - -To run the native desktop app: - -```bash -bun run --cwd packages/desktop tauri dev -``` - -This starts the web dev server on http://localhost:1420 and opens the native window. - -If you only want the web dev server (no native shell): - -```bash -bun run --cwd packages/desktop dev -``` - -To create a production `dist/` and build the native app bundle: - -```bash -bun run --cwd packages/desktop tauri build -``` - -This runs `bun run --cwd packages/desktop build` automatically via Tauri’s `beforeBuildCommand`. - -> [!NOTE] -> Running the desktop app requires additional Tauri dependencies (Rust toolchain, platform-specific libraries). See the [Tauri prerequisites](https://v2.tauri.app/start/prerequisites/) for setup instructions. - -> [!NOTE] -> If you make changes to the API or SDK (e.g. `packages/opencode/src/server/server.ts`), run `./script/generate.ts` to regenerate the SDK and related files. - -Please try to follow the [style guide](./AGENTS.md) - -### Setting up a Debugger - -Bun debugging is currently rough around the edges. We hope this guide helps you get set up and avoid some pain points. - -The most reliable way to debug OpenCode is to run it manually in a terminal via `bun run --inspect= dev ...` and attach -your debugger via that URL. Other methods can result in breakpoints being mapped incorrectly, at least in VSCode (YMMV). - -Caveats: - -- If you want to run the OpenCode TUI and have breakpoints triggered in the server code, you might need to run `bun dev spawn` instead of - the usual `bun dev`. This is because `bun dev` runs the server in a worker thread and breakpoints might not work there. -- If `spawn` does not work for you, you can debug the server separately: - - Debug server: `bun run --inspect=ws://localhost:6499/ --cwd packages/opencode ./src/index.ts serve --port 4096`, - then attach TUI with `opencode attach http://localhost:4096` - - Debug TUI: `bun run --inspect=ws://localhost:6499/ --cwd packages/opencode --conditions=browser ./src/index.ts` - -Other tips and tricks: - -- You might want to use `--inspect-wait` or `--inspect-brk` instead of `--inspect`, depending on your workflow -- Specifying `--inspect=ws://localhost:6499/` on every invocation can be tiresome, you may want to `export BUN_OPTIONS=--inspect=ws://localhost:6499/` instead - -#### VSCode Setup - -If you use VSCode, you can use our example configurations [.vscode/settings.example.json](.vscode/settings.example.json) and [.vscode/launch.example.json](.vscode/launch.example.json). - -Some debug methods that can be problematic: - -- Debug configurations with `"request": "launch"` can have breakpoints incorrectly mapped and thus unusable -- The same problem arises when running OpenCode in the VSCode `JavaScript Debug Terminal` - -With that said, you may want to try these methods, as they might work for you. - -## Pull Request Expectations - -### Issue First Policy - -**All PRs must reference an existing issue.** Before opening a PR, open an issue describing the bug or feature. This helps maintainers triage and prevents duplicate work. PRs without a linked issue may be closed without review. - -- Use `Fixes #123` or `Closes #123` in your PR description to link the issue -- For small fixes, a brief issue is fine - just enough context for maintainers to understand the problem - -### General Requirements - -- Keep pull requests small and focused -- Explain the issue and why your change fixes it -- Before adding new functionality, ensure it doesn't already exist elsewhere in the codebase - -### UI Changes - -If your PR includes UI changes, please include screenshots or videos showing the before and after. This helps maintainers review faster and gives you quicker feedback. - -### Logic Changes - -For non-UI changes (bug fixes, new features, refactors), explain **how you verified it works**: - -- What did you test? -- How can a reviewer reproduce/confirm the fix? - -### No AI-Generated Walls of Text - -Long, AI-generated PR descriptions and issues are not acceptable and may be ignored. Respect the maintainers' time: - -- Write short, focused descriptions -- Explain what changed and why in your own words -- If you can't explain it briefly, your PR might be too large - -### PR Titles - -PR titles should follow conventional commit standards: - -- `feat:` new feature or functionality -- `fix:` bug fix -- `docs:` documentation or README changes -- `chore:` maintenance tasks, dependency updates, etc. -- `refactor:` code refactoring without changing behavior -- `test:` adding or updating tests - -You can optionally include a scope to indicate which package is affected: - -- `feat(app):` feature in the app package -- `fix(desktop):` bug fix in the desktop package -- `chore(opencode):` maintenance in the opencode package - -Examples: - -- `docs: update contributing guidelines` -- `fix: resolve crash on startup` -- `feat: add dark mode support` -- `feat(app): add dark mode support` -- `fix(desktop): resolve crash on startup` -- `chore: bump dependency versions` +- **Issue First Policy:** All PRs must reference an existing issue. +- **UI Changes:** Include screenshots or videos (before/after). +- **Logic Changes:** Explain how you verified it works. +- **PR Titles:** Follow conventional commit standards (`feat:`, `fix:`, `docs:`, etc.). ### Style Preferences -These are not strictly enforced, they are just general guidelines: - -- **Functions:** Keep logic within a single function unless breaking it out adds clear reuse or composition benefits. -- **Destructuring:** Do not do unnecessary destructuring of variables. -- **Control flow:** Avoid `else` statements. -- **Error handling:** Prefer `.catch(...)` instead of `try`/`catch` when possible. -- **Types:** Reach for precise types and avoid `any`. -- **Variables:** Stick to immutable patterns and avoid `let`. -- **Naming:** Choose concise single-word identifiers when they remain descriptive. -- **Runtime APIs:** Use Bun helpers such as `Bun.file()` when they fit the use case. - -## Feature Requests - -For net-new functionality, start with a design conversation. Open an issue describing the problem, your proposed approach (optional), and why it belongs in OpenCode. The core team will help decide whether it should move forward; please wait for that approval instead of opening a feature PR directly. +- **Functions:** Keep logic within a single function unless breaking it out adds clear reuse. +- **Destructuring:** Avoid unnecessary destructuring. +- **Control flow:** Avoid `else` statements; prefer early returns. +- **Types:** Avoid `any`. +- **Variables:** Prefer `const`. +- **Naming:** Concise single-word identifiers when descriptive. +- **Runtime APIs:** Use Bun helpers (e.g., `Bun.file()`). diff --git a/LICENSE b/LICENSE index 6439474bee..81a8bb2f98 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2025 opencode +Copyright (c) 2025 Kilo Code Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/PRIVACY.md b/PRIVACY.md new file mode 100644 index 0000000000..065b6a58b4 --- /dev/null +++ b/PRIVACY.md @@ -0,0 +1,28 @@ +# Kilo CLI Privacy Policy + +**Last Updated: March 7th, 2025** + +Kilo CLI respects your privacy and is committed to transparency about how we handle your data. Below is a simple breakdown of where key pieces of data go—and, importantly, where they don't. + +### **Where Your Data Goes (And Where It Doesn't)** + +- **Code & Files**: Kilo CLI accesses files on your local machine when needed for AI-assisted features. When you send commands to Kilo CLI, relevant files may be transmitted to your chosen AI model provider (e.g., OpenAI, Anthropic, OpenRouter) to generate responses. We do not have access to this data, but AI providers may store it per their privacy policies. +- **Commands**: Any commands executed through Kilo CLI happen on your local environment. However, when you use AI-powered features, the relevant code and context from your commands may be transmitted to your chosen AI model provider (e.g., OpenAI, Anthropic, OpenRouter) to generate responses. We do not have access to or store this data, but AI providers may process it per their privacy policies. +- **Prompts & AI Requests**: When you use AI-powered features, your prompts and relevant project context are sent to your chosen AI model provider (e.g., OpenAI, Anthropic, OpenRouter) to generate responses. We do not store or process this data. These AI providers have their own privacy policies and may store data per their terms of service. +- **API Keys & Credentials**: If you enter an API key (e.g., to connect an AI model), it is stored locally on your device and never sent to us or any third party, except the provider you have chosen. + +### **Your Choices & Control** + +- You can run models locally to prevent data being sent to third-parties. + +### **Security & Updates** + +We take reasonable measures to secure your data, but no system is 100% secure. If our privacy policy changes, we will update this document and note the changes in our release notes. + +### **Contact Us** + +For any privacy-related questions, you can reach out to us at hi@kilo.ai. + +--- + +By using Kilo CLI, you agree to this Privacy Policy. diff --git a/README.md b/README.md index 9d443a6982..df67978d3e 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,18 @@ --- +### Installation + +```bash +# npm +npm install -g @kilocode/cli + +# Or run directly with npx +npx @kilocode/cli +``` + +Then run `kilo` in any project directory to start. + ### Agents Kilo CLI includes two built-in agents you can switch between using the `Tab` key: @@ -69,7 +81,7 @@ If you're interested in contributing, please read our [contributing docs](./CONT #### Where did Kilo CLI come from? -Kilo CLI is a fork of [OpenCode](https://github.com/Kilo-Org/kilo), enhanced to work within the Kilo agentic engineering platform. +Kilo CLI is a fork of [OpenCode](https://github.com/anomalyco/opencode), enhanced to work within the Kilo agentic engineering platform. --- diff --git a/SECURITY.md b/SECURITY.md index 88015f337f..beb53a8a65 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -4,17 +4,17 @@ ### Overview -OpenCode is an AI-powered coding assistant that runs locally on your machine. It provides an agent system with access to powerful tools including shell execution, file operations, and web access. +Kilo CLI is an AI-powered coding assistant that runs locally on your machine. It provides an agent system with access to powerful tools including shell execution, file operations, and web access. ### No Sandbox -OpenCode does **not** sandbox the agent. The permission system exists as a UX feature to help users stay aware of what actions the agent is taking - it prompts for confirmation before executing commands, writing files, etc. However, it is not designed to provide security isolation. +Kilo CLI does **not** sandbox the agent. The permission system exists as a UX feature to help users stay aware of what actions the agent is taking - it prompts for confirmation before executing commands, writing files, etc. However, it is not designed to provide security isolation. -If you need true isolation, run OpenCode inside a Docker container or VM. +If you need true isolation, run Kilo CLI inside a Docker container or VM. ### Server Mode -Server mode is opt-in only. When enabled, set `OPENCODE_SERVER_PASSWORD` to require HTTP Basic Auth. Without this, the server runs unauthenticated (with a warning). It is the end user's responsibility to secure the server - any functionality it provides is not a vulnerability. +Server mode is opt-in only. When enabled, set `KILO_SERVER_PASSWORD` to require HTTP Basic Auth. Without this, the server runs unauthenticated (with a warning). It is the end user's responsibility to secure the server - any functionality it provides is not a vulnerability. ### Out of Scope @@ -38,4 +38,4 @@ The team will send a response indicating the next steps in handling your report. ## Escalation -If you do not receive an acknowledgement of your report within 6 business days, you may send an email to security@anoma.ly +If you do not receive an acknowledgement of your report within 6 business days, you may send an email to hi@kilo.ai diff --git a/bun.lock b/bun.lock index 453b22de0f..6de021cfbc 100644 --- a/bun.lock +++ b/bun.lock @@ -24,7 +24,7 @@ }, "packages/app": { "name": "@opencode-ai/app", - "version": "1.1.42", + "version": "1.0.13", "dependencies": { "@kilocode/sdk": "workspace:*", "@kobalte/core": "catalog:", @@ -74,7 +74,7 @@ }, "packages/console/app": { "name": "@opencode-ai/console-app", - "version": "1.1.42", + "version": "1.0.13", "dependencies": { "@cloudflare/vite-plugin": "1.15.2", "@ibm/plex": "6.4.1", @@ -108,7 +108,7 @@ }, "packages/console/core": { "name": "@opencode-ai/console-core", - "version": "1.1.42", + "version": "1.0.13", "dependencies": { "@aws-sdk/client-sts": "3.782.0", "@jsx-email/render": "1.1.1", @@ -135,7 +135,7 @@ }, "packages/console/function": { "name": "@opencode-ai/console-function", - "version": "1.1.42", + "version": "1.0.13", "dependencies": { "@ai-sdk/anthropic": "2.0.0", "@ai-sdk/openai": "2.0.2", @@ -159,7 +159,7 @@ }, "packages/console/mail": { "name": "@opencode-ai/console-mail", - "version": "1.1.42", + "version": "1.0.13", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", @@ -183,7 +183,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "1.1.42", + "version": "1.0.13", "dependencies": { "@opencode-ai/app": "workspace:*", "@opencode-ai/ui": "workspace:*", @@ -213,7 +213,7 @@ }, "packages/enterprise": { "name": "@opencode-ai/enterprise", - "version": "1.1.42", + "version": "1.0.13", "dependencies": { "@opencode-ai/ui": "workspace:*", "@opencode-ai/util": "workspace:*", @@ -242,7 +242,7 @@ }, "packages/function": { "name": "@opencode-ai/function", - "version": "1.1.42", + "version": "1.0.13", "dependencies": { "@octokit/auth-app": "8.0.1", "@octokit/rest": "catalog:", @@ -258,7 +258,7 @@ }, "packages/kilo-gateway": { "name": "@kilocode/kilo-gateway", - "version": "1.0.0", + "version": "1.0.13", "dependencies": { "@clack/prompts": "1.0.0-alpha.1", "@kilocode/plugin": "workspace:*", @@ -290,7 +290,7 @@ }, "packages/kilo-telemetry": { "name": "@kilocode/kilo-telemetry", - "version": "1.0.0", + "version": "1.0.13", "dependencies": { "@kilocode/kilo-gateway": "workspace:*", "@opentelemetry/api": "1.9.0", @@ -310,7 +310,7 @@ }, "packages/opencode": { "name": "@kilocode/cli", - "version": "1.1.42", + "version": "1.0.13", "bin": { "kilo": "./bin/kilo", }, @@ -416,7 +416,7 @@ }, "packages/plugin": { "name": "@kilocode/plugin", - "version": "1.1.42", + "version": "1.0.13", "dependencies": { "@kilocode/sdk": "workspace:*", "zod": "catalog:", @@ -436,7 +436,7 @@ }, "packages/sdk/js": { "name": "@kilocode/sdk", - "version": "1.1.42", + "version": "1.0.13", "devDependencies": { "@hey-api/openapi-ts": "0.90.10", "@tsconfig/node22": "catalog:", @@ -447,7 +447,7 @@ }, "packages/slack": { "name": "@opencode-ai/slack", - "version": "1.1.42", + "version": "1.0.13", "dependencies": { "@kilocode/sdk": "workspace:*", "@slack/bolt": "^3.17.1", @@ -460,7 +460,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "1.1.42", + "version": "1.0.13", "dependencies": { "@kilocode/sdk": "workspace:*", "@kobalte/core": "catalog:", @@ -502,7 +502,7 @@ }, "packages/util": { "name": "@opencode-ai/util", - "version": "1.1.42", + "version": "1.0.13", "dependencies": { "zod": "catalog:", }, @@ -513,7 +513,7 @@ }, "packages/web": { "name": "@opencode-ai/web", - "version": "1.1.42", + "version": "1.0.13", "dependencies": { "@astrojs/cloudflare": "12.6.3", "@astrojs/markdown-remark": "6.3.1", diff --git a/flake.nix b/flake.nix index fdcc499a07..f1e24bed5e 100644 --- a/flake.nix +++ b/flake.nix @@ -19,15 +19,26 @@ in { devShells = forEachSystem (pkgs: { - default = pkgs.mkShell { - packages = with pkgs; [ - bun - nodejs_20 - pkg-config - openssl - git - ]; - }; + default = + let + kilo = pkgs.writeShellScriptBin "kilo" '' + cd "$KILO_ROOT" + exec ${pkgs.bun}/bin/bun dev "$@" + ''; + in + pkgs.mkShell { + packages = with pkgs; [ + bun + nodejs_20 + pkg-config + openssl + git + kilo + ]; + shellHook = '' + export KILO_ROOT="$PWD" + ''; + }; }); packages = forEachSystem ( diff --git a/packages/app/package.json b/packages/app/package.json index 4471c8987b..f93e0fc1ab 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/app", - "version": "1.1.42", + "version": "1.0.13", "description": "", "type": "module", "exports": { diff --git a/packages/console/app/package.json b/packages/console/app/package.json index f1b0aca8f5..0f8379a4c0 100644 --- a/packages/console/app/package.json +++ b/packages/console/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-app", - "version": "1.1.42", + "version": "1.0.13", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/console/core/package.json b/packages/console/core/package.json index 59a9d2ecc4..eb967c4883 100644 --- a/packages/console/core/package.json +++ b/packages/console/core/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/console-core", - "version": "1.1.42", + "version": "1.0.13", "private": true, "type": "module", "license": "MIT", diff --git a/packages/console/function/package.json b/packages/console/function/package.json index 8cfdc1c0af..4d673c0709 100644 --- a/packages/console/function/package.json +++ b/packages/console/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-function", - "version": "1.1.42", + "version": "1.0.13", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/console/mail/package.json b/packages/console/mail/package.json index 622d34815c..fe58a23586 100644 --- a/packages/console/mail/package.json +++ b/packages/console/mail/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-mail", - "version": "1.1.42", + "version": "1.0.13", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", diff --git a/packages/desktop/package.json b/packages/desktop/package.json index 5ba2ec347b..7ec49676be 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/desktop", "private": true, - "version": "1.1.42", + "version": "1.0.13", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/enterprise/package.json b/packages/enterprise/package.json index d0e2b0135d..3af8040468 100644 --- a/packages/enterprise/package.json +++ b/packages/enterprise/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/enterprise", - "version": "1.1.42", + "version": "1.0.13", "private": true, "type": "module", "license": "MIT", diff --git a/packages/extensions/zed/extension.toml b/packages/extensions/zed/extension.toml index dfd89907bb..ab7b0bd412 100644 --- a/packages/extensions/zed/extension.toml +++ b/packages/extensions/zed/extension.toml @@ -1,7 +1,7 @@ id = "opencode" name = "OpenCode" description = "The open source coding agent." -version = "1.1.42" +version = "1.0.13" schema_version = 1 authors = ["Anomaly"] repository = "https://github.com/Kilo-Org/kilo" @@ -11,26 +11,26 @@ name = "OpenCode" icon = "./icons/opencode.svg" [agent_servers.opencode.targets.darwin-aarch64] -archive = "https://github.com/Kilo-Org/kilo/releases/download/v1.1.42/opencode-darwin-arm64.zip" +archive = "https://github.com/Kilo-Org/kilo/releases/download/v1.0.13/opencode-darwin-arm64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.darwin-x86_64] -archive = "https://github.com/Kilo-Org/kilo/releases/download/v1.1.42/opencode-darwin-x64.zip" +archive = "https://github.com/Kilo-Org/kilo/releases/download/v1.0.13/opencode-darwin-x64.zip" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-aarch64] -archive = "https://github.com/Kilo-Org/kilo/releases/download/v1.1.42/opencode-linux-arm64.tar.gz" +archive = "https://github.com/Kilo-Org/kilo/releases/download/v1.0.13/opencode-linux-arm64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.linux-x86_64] -archive = "https://github.com/Kilo-Org/kilo/releases/download/v1.1.42/opencode-linux-x64.tar.gz" +archive = "https://github.com/Kilo-Org/kilo/releases/download/v1.0.13/opencode-linux-x64.tar.gz" cmd = "./opencode" args = ["acp"] [agent_servers.opencode.targets.windows-x86_64] -archive = "https://github.com/Kilo-Org/kilo/releases/download/v1.1.42/opencode-windows-x64.zip" +archive = "https://github.com/Kilo-Org/kilo/releases/download/v1.0.13/opencode-windows-x64.zip" cmd = "./opencode.exe" args = ["acp"] diff --git a/packages/function/package.json b/packages/function/package.json index 34a0f5c7ba..b58b40e9ad 100644 --- a/packages/function/package.json +++ b/packages/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/function", - "version": "1.1.42", + "version": "1.0.13", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/kilo-gateway/package.json b/packages/kilo-gateway/package.json index f244e05f13..1d0dbfc5eb 100644 --- a/packages/kilo-gateway/package.json +++ b/packages/kilo-gateway/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/kilo-gateway", - "version": "1.0.0", + "version": "1.0.13", "type": "module", "license": "MIT", "description": "Unified Kilo Gateway package for OpenCode - authentication, provider, and API integration", diff --git a/packages/kilo-gateway/src/tui/components/dialog-kilo-notifications.tsx b/packages/kilo-gateway/src/tui/components/dialog-kilo-notifications.tsx index 4b2d75577d..166dedc9c3 100644 --- a/packages/kilo-gateway/src/tui/components/dialog-kilo-notifications.tsx +++ b/packages/kilo-gateway/src/tui/components/dialog-kilo-notifications.tsx @@ -6,7 +6,7 @@ * Each notification shows title, message, and clickable action link. */ -import { For } from "solid-js" +import { createSignal, For } from "solid-js" import { getTUIDependencies } from "../context.js" import type { KilocodeNotification } from "../../api/notifications.js" @@ -20,6 +20,7 @@ export function DialogKiloNotifications(props: DialogKiloNotificationsProps) { const TextAttributes = deps.TextAttributes const dialog = deps.useDialog() const { theme } = deps.useTheme() + const [closeHover, setCloseHover] = createSignal(false) deps.useKeyboard((evt: any) => { if (evt.name === "escape" || evt.name === "return") { @@ -33,33 +34,59 @@ export function DialogKiloNotifications(props: DialogKiloNotificationsProps) { News - esc + setCloseHover(true)} + onMouseOut={() => setCloseHover(false)} + onMouseUp={() => dialog.clear()} + > + esc + - + - {(notification) => ( - - - * - - {notification.title} - + {(notification) => { + const [hover, setHover] = createSignal(false) + + return ( + setHover(true)} + onMouseOut={() => setHover(false)} + > + + * + + {notification.title} + + + + + {notification.message} + + {notification.action && ( + + + [{notification.action.actionText}] + + + )} + - - - {notification.message} - - {notification.action && ( - - - [{notification.action.actionText}] - - - )} - - - )} + ) + }} diff --git a/packages/kilo-gateway/src/tui/components/notification-banner.tsx b/packages/kilo-gateway/src/tui/components/notification-banner.tsx index cc13e77bed..f156cbd36b 100644 --- a/packages/kilo-gateway/src/tui/components/notification-banner.tsx +++ b/packages/kilo-gateway/src/tui/components/notification-banner.tsx @@ -10,7 +10,7 @@ * Message text with word wrap... */ -import { Show } from "solid-js" +import { createSignal, Show } from "solid-js" import { getTUIDependencies } from "../context.js" import type { KilocodeNotification } from "../../api/notifications.js" @@ -23,19 +23,31 @@ interface NotificationBannerProps { export function NotificationBanner(props: NotificationBannerProps) { const deps = getTUIDependencies() const { theme } = deps.useTheme() + const [hover, setHover] = createSignal(false) return ( - + setHover(true)} + onMouseOut={() => setHover(false)} + onMouseUp={props.onClick} + > {/* Line 1: Icon + Title + Count */} - + * - + {props.notification.title} 0}> - + ({props.totalCount} new) @@ -43,7 +55,7 @@ export function NotificationBanner(props: NotificationBannerProps) { {/* Line 2: Message (indented to align under title) */} - + {props.notification.message} diff --git a/packages/kilo-telemetry/package.json b/packages/kilo-telemetry/package.json index 35b5502e36..8534864dc1 100644 --- a/packages/kilo-telemetry/package.json +++ b/packages/kilo-telemetry/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/kilo-telemetry", - "version": "1.0.0", + "version": "1.0.13", "type": "module", "license": "MIT", "description": "Telemetry for Kilo CLI - PostHog analytics integration", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 2e26efe8e7..d7b0977ab0 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.1.42", + "version": "1.0.13", "name": "@kilocode/cli", "type": "module", "license": "MIT", @@ -75,12 +75,12 @@ "@hono/zod-validator": "catalog:", "@kilocode/kilo-gateway": "workspace:*", "@kilocode/kilo-telemetry": "workspace:*", + "@kilocode/plugin": "workspace:*", "@kilocode/sdk": "workspace:*", "@modelcontextprotocol/sdk": "1.25.2", "@octokit/graphql": "9.0.2", "@octokit/rest": "catalog:", "@openauthjs/openauth": "catalog:", - "@kilocode/plugin": "workspace:*", "@opencode-ai/script": "workspace:*", "@opencode-ai/util": "workspace:*", "@openrouter/ai-sdk-provider": "1.5.2", diff --git a/packages/opencode/script/build.ts b/packages/opencode/script/build.ts index 13857fe4d4..92af0fd5bf 100755 --- a/packages/opencode/script/build.ts +++ b/packages/opencode/script/build.ts @@ -171,6 +171,10 @@ for (const item of targets) { version: Script.version, os: [item.os], cpu: [item.arch], + repository: { + type: "git", + url: "https://github.com/Kilo-Org/kilo", + }, }, null, 2, diff --git a/packages/opencode/script/pack.ts b/packages/opencode/script/pack.ts index 6534112c28..497e7f3ad1 100755 --- a/packages/opencode/script/pack.ts +++ b/packages/opencode/script/pack.ts @@ -52,13 +52,18 @@ for (const tag of tags) { if (!Script.preview) { // Create archives for GitHub release + // kilocode_change start - use absolute paths to avoid issues with scoped package names containing '/' + const archiveDir = `${dir}/dist/archives` + await $`mkdir -p ${archiveDir}` for (const key of Object.keys(binaries)) { + const archiveName = key.replace("/", "-") // @kilocode/cli-linux-arm64 → @kilocode-cli-linux-arm64 if (key.includes("linux")) { - await $`tar -czf ../../${key}.tar.gz *`.cwd(`dist/${key}/bin`) + await $`tar -czf ${archiveDir}/${archiveName}.tar.gz *`.cwd(`dist/${key}/bin`) } else { - await $`zip -r ../../${key}.zip *`.cwd(`dist/${key}/bin`) + await $`zip -r ${archiveDir}/${archiveName}.zip *`.cwd(`dist/${key}/bin`) } } + // kilocode_change end const image = "ghcr.io/Kilo-Org/kilo" const platforms = "linux/amd64,linux/arm64" diff --git a/packages/opencode/script/publish-registries.ts b/packages/opencode/script/publish-registries.ts index b6d1b686a8..41d990b5df 100644 --- a/packages/opencode/script/publish-registries.ts +++ b/packages/opencode/script/publish-registries.ts @@ -4,14 +4,20 @@ import { Script } from "@opencode-ai/script" if (!Script.preview) { // Calculate SHA values - const arm64Sha = await $`sha256sum ./dist/@kilocode/cli-linux-arm64.tar.gz | cut -d' ' -f1` + // kilocode_change start - archives now use '-' instead of '/' and are in archives/ subdirectory + const arm64Sha = await $`sha256sum ./dist/archives/@kilocode-cli-linux-arm64.tar.gz | cut -d' ' -f1` .text() .then((x) => x.trim()) - const x64Sha = await $`sha256sum ./dist/@kilocode/cli-linux-x64.tar.gz | cut -d' ' -f1`.text().then((x) => x.trim()) - const macX64Sha = await $`sha256sum ./dist/@kilocode/cli-darwin-x64.zip | cut -d' ' -f1`.text().then((x) => x.trim()) - const macArm64Sha = await $`sha256sum ./dist/@kilocode/cli-darwin-arm64.zip | cut -d' ' -f1` + const x64Sha = await $`sha256sum ./dist/archives/@kilocode-cli-linux-x64.tar.gz | cut -d' ' -f1` .text() .then((x) => x.trim()) + const macX64Sha = await $`sha256sum ./dist/archives/@kilocode-cli-darwin-x64.zip | cut -d' ' -f1` + .text() + .then((x) => x.trim()) + const macArm64Sha = await $`sha256sum ./dist/archives/@kilocode-cli-darwin-arm64.zip | cut -d' ' -f1` + .text() + .then((x) => x.trim()) + // kilocode_change end const [pkgver, _subver = ""] = Script.version.split(/(-.*)/, 2) diff --git a/packages/opencode/script/publish.ts b/packages/opencode/script/publish.ts index 4ce0074ab3..1fe4a2cd79 100755 --- a/packages/opencode/script/publish.ts +++ b/packages/opencode/script/publish.ts @@ -31,6 +31,10 @@ await Bun.file(`./dist/${pkg.name}/package.json`).write( }, version: Script.version, optionalDependencies: binaries, + repository: { + type: "git", + url: "https://github.com/Kilo-Org/kilo", + }, }, null, 2, @@ -55,13 +59,18 @@ for (const tag of tags) { if (!Script.preview) { // Create archives for GitHub release + // kilocode_change start - use absolute paths to avoid issues with scoped package names containing '/' + const archiveDir = `${dir}/dist/archives` + await $`mkdir -p ${archiveDir}` for (const key of Object.keys(binaries)) { + const archiveName = key.replace("/", "-") // @kilocode/cli-linux-arm64 → @kilocode-cli-linux-arm64 if (key.includes("linux")) { - await $`tar -czf ../../${key}.tar.gz *`.cwd(`dist/${key}/bin`) + await $`tar -czf ${archiveDir}/${archiveName}.tar.gz *`.cwd(`dist/${key}/bin`) } else { - await $`zip -r ../../${key}.zip *`.cwd(`dist/${key}/bin`) + await $`zip -r ${archiveDir}/${archiveName}.zip *`.cwd(`dist/${key}/bin`) } } + // kilocode_change end const image = "ghcr.io/kilo-org/kilo" // kilocode_change const platforms = "linux/amd64,linux/arm64" diff --git a/packages/opencode/script/seed-e2e.ts b/packages/opencode/script/seed-e2e.ts index 0384a2c2e3..98693b807a 100644 --- a/packages/opencode/script/seed-e2e.ts +++ b/packages/opencode/script/seed-e2e.ts @@ -26,7 +26,7 @@ const seed = async () => { sessionID: session.id, role: "user" as const, time: { created: now }, - agent: "build", + agent: "code", // kilocode_change - renamed from "build" to "code" model: { providerID, modelID, diff --git a/packages/opencode/src/agent/agent.ts b/packages/opencode/src/agent/agent.ts index f1727c2a73..0b7cde850b 100644 --- a/packages/opencode/src/agent/agent.ts +++ b/packages/opencode/src/agent/agent.ts @@ -72,9 +72,11 @@ export namespace Agent { const user = PermissionNext.fromConfig(cfg.permission ?? {}) const result: Record = { - build: { - name: "build", + // kilocode_change start + code: { + name: "code", description: "The default agent. Executes tools based on configured permissions.", + // kilocode_change end options: {}, permission: PermissionNext.merge( defaults, @@ -201,19 +203,23 @@ export namespace Agent { } for (const [key, value] of Object.entries(cfg.agent ?? {})) { + // kilocode_change start + // Treat "build" config as "code" for backward compatibility + const effectiveKey = key === "build" ? "code" : key if (value.disable) { - delete result[key] + delete result[effectiveKey] continue } - let item = result[key] + let item = result[effectiveKey] if (!item) - item = result[key] = { - name: key, + item = result[effectiveKey] = { + name: effectiveKey, mode: "all", permission: PermissionNext.merge(defaults, user), options: {}, native: false, } + // kilocode_change end if (value.model) item.model = Provider.parseModel(value.model) item.prompt = value.prompt ?? item.prompt item.description = value.description ?? item.description @@ -248,7 +254,10 @@ export namespace Agent { }) export async function get(agent: string) { - return state().then((x) => x[agent]) + // kilocode_change start - Treat "build" as "code" for backward compatibility + const effectiveAgent = agent === "build" ? "code" : agent + return state().then((x) => x[effectiveAgent]) + // kilocode_change end } export async function list() { @@ -256,7 +265,7 @@ export namespace Agent { return pipe( await state(), values(), - sortBy([(x) => (cfg.default_agent ? x.name === cfg.default_agent : x.name === "build"), "desc"]), + sortBy([(x) => (cfg.default_agent ? x.name === cfg.default_agent : x.name === "code"), "desc"]), // kilocode_change - renamed from "build" to "code" ) } @@ -265,8 +274,11 @@ export namespace Agent { const agents = await state() if (cfg.default_agent) { - const agent = agents[cfg.default_agent] + // kilocode_change start - Treat "build" as "code" for backward compatibility + const effectiveDefault = cfg.default_agent === "build" ? "code" : cfg.default_agent + const agent = agents[effectiveDefault] if (!agent) throw new Error(`default agent "${cfg.default_agent}" not found`) + // kilocode_change end if (agent.mode === "subagent") throw new Error(`default agent "${cfg.default_agent}" is a subagent`) if (agent.hidden === true) throw new Error(`default agent "${cfg.default_agent}" is hidden`) return agent.name diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index afa754b24d..f39327b679 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -1013,12 +1013,14 @@ export namespace Config { .string() .describe("Small model to use for tasks like title generation in the format of provider/model") .optional(), + // kilocode_change - renamed from "build" to "code" default_agent: z .string() .optional() .describe( - "Default agent to use when none is specified. Must be a primary agent. Falls back to 'build' if not set or if the specified agent is invalid.", + "Default agent to use when none is specified. Must be a primary agent. Falls back to 'code' if not set or if the specified agent is invalid.", ), + // kilocode_change end username: z .string() .optional() diff --git a/packages/opencode/src/kilocode/components/tips.tsx b/packages/opencode/src/kilocode/components/tips.tsx index 0a2c4cb929..1e09b5c170 100644 --- a/packages/opencode/src/kilocode/components/tips.tsx +++ b/packages/opencode/src/kilocode/components/tips.tsx @@ -54,7 +54,7 @@ export function Tips() { const TIPS = [ "Type {highlight}@{/highlight} followed by a filename to fuzzy search and attach files", "Start a message with {highlight}!{/highlight} to run shell commands directly (e.g., {highlight}!ls -la{/highlight})", - "Press {highlight}Tab{/highlight} to cycle between Build and Plan agents", + "Press {highlight}Tab{/highlight} to cycle between Code and Plan agents", "Use {highlight}/undo{/highlight} to revert the last message and file changes", "Use {highlight}/redo{/highlight} to restore previously undone messages and file changes", "Drag and drop images into the terminal to add them as context", diff --git a/packages/opencode/src/kilocode/modes-migrator.ts b/packages/opencode/src/kilocode/modes-migrator.ts index ca99a63d63..8d73cb916b 100644 --- a/packages/opencode/src/kilocode/modes-migrator.ts +++ b/packages/opencode/src/kilocode/modes-migrator.ts @@ -23,7 +23,8 @@ export namespace ModesMigrator { } // Default modes to skip - these have native Opencode equivalents - const DEFAULT_MODE_SLUGS = new Set(["code", "architect", "ask", "debug", "orchestrator"]) + // kilocode_change - added "build" for backward compatibility after renaming "build" to "code" + const DEFAULT_MODE_SLUGS = new Set(["code", "build", "architect", "ask", "debug", "orchestrator"]) // Group to permission mapping const GROUP_TO_PERMISSION: Record = { diff --git a/packages/opencode/src/provider/transform.ts b/packages/opencode/src/provider/transform.ts index 10f4bd7aee..875bf513aa 100644 --- a/packages/opencode/src/provider/transform.ts +++ b/packages/opencode/src/provider/transform.ts @@ -345,10 +345,24 @@ export namespace ProviderTransform { switch (model.api.npm) { case "@openrouter/ai-sdk-provider": - case "@kilocode/kilo-gateway": // kilocode_change if (!model.id.includes("gpt") && !model.id.includes("gemini-3")) return {} return Object.fromEntries(OPENAI_EFFORTS.map((effort) => [effort, { reasoning: { effort } }])) + // kilocode_change start - GPT models via Kilo need encrypted reasoning content to avoid org_id mismatch + case "@kilocode/kilo-gateway": + if (!model.id.includes("gpt") && !model.id.includes("gemini-3")) return {} + return Object.fromEntries( + OPENAI_EFFORTS.map((effort) => [ + effort, + { + reasoningEffort: effort, + reasoningSummary: "auto", + include: ["reasoning.encrypted_content"], + }, + ]), + ) + // kilocode_change end + // TODO: YOU CANNOT SET max_tokens if this is set!!! case "@ai-sdk/gateway": return Object.fromEntries(OPENAI_EFFORTS.map((effort) => [effort, { reasoningEffort: effort }])) @@ -604,7 +618,8 @@ export namespace ProviderTransform { result["textVerbosity"] = "low" } - if (input.model.providerID.startsWith("opencode")) { + // kilocode_change - include kilo provider for encrypted reasoning content + if (input.model.providerID.startsWith("opencode") || input.model.api.npm === "@kilocode/kilo-gateway") { result["promptCacheKey"] = input.sessionID result["include"] = ["reasoning.encrypted_content"] result["reasoningSummary"] = "auto" diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts index 94eabdef7f..6cc7d0b63d 100644 --- a/packages/opencode/src/session/prompt.ts +++ b/packages/opencode/src/session/prompt.ts @@ -18,7 +18,7 @@ import { SystemPrompt } from "./system" import { InstructionPrompt } from "./instruction" import { Plugin } from "../plugin" import PROMPT_PLAN from "../session/prompt/plan.txt" -import BUILD_SWITCH from "../session/prompt/build-switch.txt" +import CODE_SWITCH from "../session/prompt/code-switch.txt" import MAX_STEPS from "../session/prompt/max-steps.txt" import { defer } from "../util/defer" import { clone } from "remeda" @@ -1214,13 +1214,15 @@ export namespace SessionPrompt { }) } const wasPlan = input.messages.some((msg) => msg.info.role === "assistant" && msg.info.agent === "plan") - if (wasPlan && input.agent.name === "build") { + // kilocode_change start - renamed from "build" to "code" + if (wasPlan && input.agent.name === "code") { + // kilocode_change end userMessage.parts.push({ id: Identifier.ascending("part"), messageID: userMessage.info.id, sessionID: userMessage.info.sessionID, type: "text", - text: BUILD_SWITCH, + text: CODE_SWITCH, synthetic: true, }) } @@ -1241,7 +1243,7 @@ export namespace SessionPrompt { sessionID: userMessage.info.sessionID, type: "text", text: - BUILD_SWITCH + "\n\n" + `A plan file exists at ${plan}. You should execute on the plan defined within it`, + CODE_SWITCH + "\n\n" + `A plan file exists at ${plan}. You should execute on the plan defined within it`, synthetic: true, }) userMessage.parts.push(part) diff --git a/packages/opencode/src/session/prompt/build-switch.txt b/packages/opencode/src/session/prompt/code-switch.txt similarity index 76% rename from packages/opencode/src/session/prompt/build-switch.txt rename to packages/opencode/src/session/prompt/code-switch.txt index 3737b74d89..4407f011c1 100644 --- a/packages/opencode/src/session/prompt/build-switch.txt +++ b/packages/opencode/src/session/prompt/code-switch.txt @@ -1,5 +1,5 @@ -Your operational mode has changed from plan to build. +Your operational mode has changed from plan to code. You are no longer in read-only mode. You are permitted to make file changes, run shell commands, and utilize your arsenal of tools as needed. diff --git a/packages/opencode/src/tool/plan.ts b/packages/opencode/src/tool/plan.ts index 6cb7a691c8..c93a522768 100644 --- a/packages/opencode/src/tool/plan.ts +++ b/packages/opencode/src/tool/plan.ts @@ -27,13 +27,15 @@ export const PlanExitTool = Tool.define("plan_exit", { sessionID: ctx.sessionID, questions: [ { - question: `Plan at ${plan} is complete. Would you like to switch to the build agent and start implementing?`, - header: "Build Agent", + // kilocode_change start + question: `Plan at ${plan} is complete. Would you like to switch to the code agent and start implementing?`, + header: "Code Agent", custom: false, options: [ - { label: "Yes", description: "Switch to build agent and start implementing the plan" }, + { label: "Yes", description: "Switch to code agent and start implementing the plan" }, { label: "No", description: "Stay with plan agent to continue refining the plan" }, ], + // kilocode_change end }, ], tool: ctx.callID ? { messageID: ctx.messageID, callID: ctx.callID } : undefined, @@ -51,7 +53,7 @@ export const PlanExitTool = Tool.define("plan_exit", { time: { created: Date.now(), }, - agent: "build", + agent: "code", // kilocode_change - renamed from "build" to "code" model, } await Session.updateMessage(userMsg) @@ -64,11 +66,13 @@ export const PlanExitTool = Tool.define("plan_exit", { synthetic: true, } satisfies MessageV2.TextPart) + // kilocode_change start return { - title: "Switching to build agent", - output: "User approved switching to build agent. Wait for further instructions.", + title: "Switching to code agent", + output: "User approved switching to code agent. Wait for further instructions.", metadata: {}, } + // kilocode_change end }, }) @@ -88,7 +92,7 @@ export const PlanEnterTool = Tool.define("plan_enter", { custom: false, options: [ { label: "Yes", description: "Switch to plan agent for research and planning" }, - { label: "No", description: "Stay with build agent to continue making changes" }, + { label: "No", description: "Stay with code agent to continue making changes" }, // kilocode_change - renamed from "build" to "code" ], }, ], diff --git a/packages/opencode/test/acp/event-subscription.test.ts b/packages/opencode/test/acp/event-subscription.test.ts index a38432ea32..db5410af2e 100644 --- a/packages/opencode/test/acp/event-subscription.test.ts +++ b/packages/opencode/test/acp/event-subscription.test.ts @@ -159,8 +159,10 @@ function createFakeAgent() { return { data: [ { - name: "build", - description: "build", + // kilocode_change start - renamed from "build" to "code" + name: "code", + description: "code", + // kilocode_change end mode: "agent", }, ], diff --git a/packages/opencode/test/agent/agent.test.ts b/packages/opencode/test/agent/agent.test.ts index 1ff303b766..4f50d65850 100644 --- a/packages/opencode/test/agent/agent.test.ts +++ b/packages/opencode/test/agent/agent.test.ts @@ -17,7 +17,7 @@ test("returns default native agents when no config", async () => { fn: async () => { const agents = await Agent.list() const names = agents.map((a) => a.name) - expect(names).toContain("build") + expect(names).toContain("code") // kilocode_change expect(names).toContain("plan") expect(names).toContain("general") expect(names).toContain("explore") @@ -28,20 +28,22 @@ test("returns default native agents when no config", async () => { }) }) -test("build agent has correct default properties", async () => { +// kilocode_change start - renamed from "build" to "code" +test("code agent has correct default properties", async () => { await using tmp = await tmpdir() await Instance.provide({ directory: tmp.path, fn: async () => { - const build = await Agent.get("build") - expect(build).toBeDefined() - expect(build?.mode).toBe("primary") - expect(build?.native).toBe(true) - expect(evalPerm(build, "edit")).toBe("allow") - expect(evalPerm(build, "bash")).toBe("allow") + const code = await Agent.get("code") + expect(code).toBeDefined() + expect(code?.mode).toBe("primary") + expect(code?.native).toBe(true) + expect(evalPerm(code, "edit")).toBe("allow") + expect(evalPerm(code, "bash")).toBe("allow") }, }) }) +// kilocode_change end test("plan agent denies edits except .opencode/plans/*", async () => { await using tmp = await tmpdir() @@ -137,26 +139,30 @@ test("custom agent config overrides native agent properties", async () => { await using tmp = await tmpdir({ config: { agent: { - build: { + // kilocode_change start + code: { model: "anthropic/claude-3", - description: "Custom build agent", + description: "Custom code agent", temperature: 0.7, color: "#FF0000", }, + // kilocode_change end }, }, }) await Instance.provide({ directory: tmp.path, fn: async () => { - const build = await Agent.get("build") - expect(build).toBeDefined() - expect(build?.model?.providerID).toBe("anthropic") - expect(build?.model?.modelID).toBe("claude-3") - expect(build?.description).toBe("Custom build agent") - expect(build?.temperature).toBe(0.7) - expect(build?.color).toBe("#FF0000") - expect(build?.native).toBe(true) + // kilocode_change start - renamed from "build" to "code" + const code = await Agent.get("code") + expect(code).toBeDefined() + expect(code?.model?.providerID).toBe("anthropic") + expect(code?.model?.modelID).toBe("claude-3") + expect(code?.description).toBe("Custom code agent") + expect(code?.temperature).toBe(0.7) + expect(code?.color).toBe("#FF0000") + expect(code?.native).toBe(true) + // kilocode_change end }, }) }) @@ -185,7 +191,9 @@ test("agent permission config merges with defaults", async () => { await using tmp = await tmpdir({ config: { agent: { - build: { + // kilocode_change start + code: { + // kilocode_change end permission: { bash: { "rm -rf *": "deny", @@ -198,12 +206,14 @@ test("agent permission config merges with defaults", async () => { await Instance.provide({ directory: tmp.path, fn: async () => { - const build = await Agent.get("build") - expect(build).toBeDefined() + // kilocode_change start - renamed from "build" to "code" + const code = await Agent.get("code") + expect(code).toBeDefined() // Specific pattern is denied - expect(PermissionNext.evaluate("bash", "rm -rf *", build!.permission).action).toBe("deny") + expect(PermissionNext.evaluate("bash", "rm -rf *", code!.permission).action).toBe("deny") // Edit still allowed - expect(evalPerm(build, "edit")).toBe("allow") + expect(evalPerm(code, "edit")).toBe("allow") + // kilocode_change end }, }) }) @@ -219,9 +229,11 @@ test("global permission config applies to all agents", async () => { await Instance.provide({ directory: tmp.path, fn: async () => { - const build = await Agent.get("build") - expect(build).toBeDefined() - expect(evalPerm(build, "bash")).toBe("deny") + // kilocode_change start - renamed from "build" to "code" + const code = await Agent.get("code") + expect(code).toBeDefined() + expect(evalPerm(code, "bash")).toBe("deny") + // kilocode_change end }, }) }) @@ -230,7 +242,9 @@ test("agent steps/maxSteps config sets steps property", async () => { await using tmp = await tmpdir({ config: { agent: { - build: { steps: 50 }, + // kilocode_change start - renamed from "build" to "code" + code: { steps: 50 }, + // kilocode_change end plan: { maxSteps: 100 }, }, }, @@ -238,9 +252,9 @@ test("agent steps/maxSteps config sets steps property", async () => { await Instance.provide({ directory: tmp.path, fn: async () => { - const build = await Agent.get("build") + const code = await Agent.get("code") // kilocode_change const plan = await Agent.get("plan") - expect(build?.steps).toBe(50) + expect(code?.steps).toBe(50) // kilocode_change expect(plan?.steps).toBe(100) }, }) @@ -267,15 +281,17 @@ test("agent name can be overridden", async () => { await using tmp = await tmpdir({ config: { agent: { - build: { name: "Builder" }, + code: { name: "Coder" }, // kilocode_change }, }, }) await Instance.provide({ directory: tmp.path, fn: async () => { - const build = await Agent.get("build") - expect(build?.name).toBe("Builder") + // kilocode_change start - renamed from "build" to "code" + const code = await Agent.get("code") + expect(code?.name).toBe("Coder") + // kilocode_change end }, }) }) @@ -284,15 +300,17 @@ test("agent prompt can be set from config", async () => { await using tmp = await tmpdir({ config: { agent: { - build: { prompt: "Custom system prompt" }, + code: { prompt: "Custom system prompt" }, // kilocode_change }, }, }) await Instance.provide({ directory: tmp.path, fn: async () => { - const build = await Agent.get("build") - expect(build?.prompt).toBe("Custom system prompt") + // kilocode_change start - renamed from "build" to "code" + const code = await Agent.get("code") + expect(code?.prompt).toBe("Custom system prompt") + // kilocode_change end }, }) }) @@ -301,7 +319,7 @@ test("unknown agent properties are placed into options", async () => { await using tmp = await tmpdir({ config: { agent: { - build: { + code: { random_property: "hello", another_random: 123, }, @@ -311,9 +329,11 @@ test("unknown agent properties are placed into options", async () => { await Instance.provide({ directory: tmp.path, fn: async () => { - const build = await Agent.get("build") - expect(build?.options.random_property).toBe("hello") - expect(build?.options.another_random).toBe(123) + // kilocode_change start - renamed from "build" to "code" + const code = await Agent.get("code") + expect(code?.options.random_property).toBe("hello") + expect(code?.options.another_random).toBe(123) + // kilocode_change end }, }) }) @@ -322,7 +342,9 @@ test("agent options merge correctly", async () => { await using tmp = await tmpdir({ config: { agent: { - build: { + // kilocode_change start - renamed from "build" to "code" + code: { + // kilocode_change end options: { custom_option: true, another_option: "value", @@ -334,9 +356,11 @@ test("agent options merge correctly", async () => { await Instance.provide({ directory: tmp.path, fn: async () => { - const build = await Agent.get("build") - expect(build?.options.custom_option).toBe(true) - expect(build?.options.another_option).toBe("value") + // kilocode_change start - renamed from "build" to "code" + const code = await Agent.get("code") + expect(code?.options.custom_option).toBe(true) + expect(code?.options.another_option).toBe("value") + // kilocode_change end }, }) }) @@ -385,9 +409,11 @@ test("default permission includes doom_loop and external_directory as ask", asyn await Instance.provide({ directory: tmp.path, fn: async () => { - const build = await Agent.get("build") - expect(evalPerm(build, "doom_loop")).toBe("ask") - expect(evalPerm(build, "external_directory")).toBe("ask") + // kilocode_change start - renamed from "build" to "code" + const code = await Agent.get("code") + expect(evalPerm(code, "doom_loop")).toBe("ask") + expect(evalPerm(code, "external_directory")).toBe("ask") + // kilocode_change end }, }) }) @@ -397,8 +423,10 @@ test("webfetch is allowed by default", async () => { await Instance.provide({ directory: tmp.path, fn: async () => { - const build = await Agent.get("build") - expect(evalPerm(build, "webfetch")).toBe("allow") + // kilocode_change start - renamed from "build" to "code" + const code = await Agent.get("code") + expect(evalPerm(code, "webfetch")).toBe("allow") + // kilocode_change end }, }) }) @@ -407,7 +435,9 @@ test("legacy tools config converts to permissions", async () => { await using tmp = await tmpdir({ config: { agent: { - build: { + // kilocode_change start - renamed from "build" to "code" + code: { + // kilocode_change end tools: { bash: false, read: false, @@ -419,9 +449,11 @@ test("legacy tools config converts to permissions", async () => { await Instance.provide({ directory: tmp.path, fn: async () => { - const build = await Agent.get("build") - expect(evalPerm(build, "bash")).toBe("deny") - expect(evalPerm(build, "read")).toBe("deny") + // kilocode_change start - renamed from "build" to "code" + const code = await Agent.get("code") + expect(evalPerm(code, "bash")).toBe("deny") + expect(evalPerm(code, "read")).toBe("deny") + // kilocode_change end }, }) }) @@ -430,7 +462,9 @@ test("legacy tools config maps write/edit/patch/multiedit to edit permission", a await using tmp = await tmpdir({ config: { agent: { - build: { + // kilocode_change start - renamed from "build" to "code" + code: { + // kilocode_change end tools: { write: false, }, @@ -441,8 +475,10 @@ test("legacy tools config maps write/edit/patch/multiedit to edit permission", a await Instance.provide({ directory: tmp.path, fn: async () => { - const build = await Agent.get("build") - expect(evalPerm(build, "edit")).toBe("deny") + // kilocode_change start - renamed from "build" to "code" + const code = await Agent.get("code") + expect(evalPerm(code, "edit")).toBe("deny") + // kilocode_change end }, }) }) @@ -459,10 +495,12 @@ test("Truncate.DIR is allowed even when user denies external_directory globally" await Instance.provide({ directory: tmp.path, fn: async () => { - const build = await Agent.get("build") - expect(PermissionNext.evaluate("external_directory", Truncate.DIR, build!.permission).action).toBe("allow") - expect(PermissionNext.evaluate("external_directory", Truncate.GLOB, build!.permission).action).toBe("allow") - expect(PermissionNext.evaluate("external_directory", "/some/other/path", build!.permission).action).toBe("deny") + // kilocode_change start - renamed from "build" to "code" + const code = await Agent.get("code") + expect(PermissionNext.evaluate("external_directory", Truncate.DIR, code!.permission).action).toBe("allow") + expect(PermissionNext.evaluate("external_directory", Truncate.GLOB, code!.permission).action).toBe("allow") + expect(PermissionNext.evaluate("external_directory", "/some/other/path", code!.permission).action).toBe("deny") + // kilocode_change end }, }) }) @@ -472,7 +510,9 @@ test("Truncate.DIR is allowed even when user denies external_directory per-agent await using tmp = await tmpdir({ config: { agent: { - build: { + // kilocode_change start - renamed from "build" to "code" + code: { + // kilocode_change end permission: { external_directory: "deny", }, @@ -483,10 +523,12 @@ test("Truncate.DIR is allowed even when user denies external_directory per-agent await Instance.provide({ directory: tmp.path, fn: async () => { - const build = await Agent.get("build") - expect(PermissionNext.evaluate("external_directory", Truncate.DIR, build!.permission).action).toBe("allow") - expect(PermissionNext.evaluate("external_directory", Truncate.GLOB, build!.permission).action).toBe("allow") - expect(PermissionNext.evaluate("external_directory", "/some/other/path", build!.permission).action).toBe("deny") + // kilocode_change start - renamed from "build" to "code" + const code = await Agent.get("code") + expect(PermissionNext.evaluate("external_directory", Truncate.DIR, code!.permission).action).toBe("allow") + expect(PermissionNext.evaluate("external_directory", Truncate.GLOB, code!.permission).action).toBe("allow") + expect(PermissionNext.evaluate("external_directory", "/some/other/path", code!.permission).action).toBe("deny") + // kilocode_change end }, }) }) @@ -506,20 +548,24 @@ test("explicit Truncate.DIR deny is respected", async () => { await Instance.provide({ directory: tmp.path, fn: async () => { - const build = await Agent.get("build") - expect(PermissionNext.evaluate("external_directory", Truncate.DIR, build!.permission).action).toBe("deny") - expect(PermissionNext.evaluate("external_directory", Truncate.GLOB, build!.permission).action).toBe("deny") + // kilocode_change start - renamed from "build" to "code" + const code = await Agent.get("code") + expect(PermissionNext.evaluate("external_directory", Truncate.DIR, code!.permission).action).toBe("deny") + expect(PermissionNext.evaluate("external_directory", Truncate.GLOB, code!.permission).action).toBe("deny") + // kilocode_change end }, }) }) -test("defaultAgent returns build when no default_agent config", async () => { +// kilocode_change start - renamed from "build" to "code" +test("defaultAgent returns code when no default_agent config", async () => { + // kilocode_change end await using tmp = await tmpdir() await Instance.provide({ directory: tmp.path, fn: async () => { const agent = await Agent.defaultAgent() - expect(agent).toBe("build") + expect(agent).toBe("code") // kilocode_change }, }) }) @@ -601,11 +647,15 @@ test("defaultAgent throws when default_agent points to non-existent agent", asyn }) }) -test("defaultAgent returns plan when build is disabled and default_agent not set", async () => { +// kilocode_change start - renamed from "build" to "code" +test("defaultAgent returns plan when code is disabled and default_agent not set", async () => { + // kilocode_change end await using tmp = await tmpdir({ config: { agent: { - build: { disable: true }, + // kilocode_change start - renamed from "build" to "code" + code: { disable: true }, + // kilocode_change end }, }, }) @@ -613,7 +663,7 @@ test("defaultAgent returns plan when build is disabled and default_agent not set directory: tmp.path, fn: async () => { const agent = await Agent.defaultAgent() - // build is disabled, so it should return plan (next primary agent) + // kilocode_change - code is disabled, so it should return plan (next primary agent) expect(agent).toBe("plan") }, }) @@ -623,7 +673,9 @@ test("defaultAgent throws when all primary agents are disabled", async () => { await using tmp = await tmpdir({ config: { agent: { - build: { disable: true }, + // kilocode_change start - renamed from "build" to "code" + code: { disable: true }, + // kilocode_change end plan: { disable: true }, }, }, @@ -631,8 +683,81 @@ test("defaultAgent throws when all primary agents are disabled", async () => { await Instance.provide({ directory: tmp.path, fn: async () => { - // build and plan are disabled, no primary-capable agents remain + // kilocode_change - code and plan are disabled, no primary-capable agents remain await expect(Agent.defaultAgent()).rejects.toThrow("no primary visible agent found") }, }) }) + +// kilocode_change start - Backward compatibility tests for "build" -> "code" rename +test("Agent.get('build') returns code agent for backward compatibility", async () => { + await using tmp = await tmpdir() + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const build = await Agent.get("build") + const code = await Agent.get("code") + expect(build).toBeDefined() + expect(build).toBe(code) + expect(build?.name).toBe("code") + }, + }) +}) + +test("agent.build config applies to code agent for backward compatibility", async () => { + await using tmp = await tmpdir({ + config: { + agent: { + build: { + temperature: 0.8, + color: "#00FF00", + }, + }, + }, + }) + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const code = await Agent.get("code") + expect(code).toBeDefined() + expect(code?.temperature).toBe(0.8) + expect(code?.color).toBe("#00FF00") + }, + }) +}) + +test("default_agent: 'build' returns code agent for backward compatibility", async () => { + await using tmp = await tmpdir({ + config: { + default_agent: "build", + }, + }) + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const agent = await Agent.defaultAgent() + expect(agent).toBe("code") + }, + }) +}) + +test("agent.build disable removes code agent for backward compatibility", async () => { + await using tmp = await tmpdir({ + config: { + agent: { + build: { disable: true }, + }, + }, + }) + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const code = await Agent.get("code") + expect(code).toBeUndefined() + const agents = await Agent.list() + const names = agents.map((a) => a.name) + expect(names).not.toContain("code") + }, + }) +}) +// kilocode_change end diff --git a/packages/opencode/test/cli/tui/transcript.test.ts b/packages/opencode/test/cli/tui/transcript.test.ts index 8dd5187545..2f4b5bd9b0 100644 --- a/packages/opencode/test/cli/tui/transcript.test.ts +++ b/packages/opencode/test/cli/tui/transcript.test.ts @@ -13,7 +13,7 @@ describe("transcript", () => { id: "msg_123", sessionID: "ses_123", role: "assistant", - agent: "build", + agent: "code", // kilocode_change modelID: "claude-sonnet-4-20250514", providerID: "anthropic", mode: "", @@ -26,7 +26,7 @@ describe("transcript", () => { test("includes metadata when enabled", () => { const result = formatAssistantHeader(baseMsg, true) - expect(result).toBe("## Assistant (Build · claude-sonnet-4-20250514 · 5.4s)\n\n") + expect(result).toBe("## Assistant (Code · claude-sonnet-4-20250514 · 5.4s)\n\n") // kilocode_change }) test("excludes metadata when disabled", () => { @@ -37,7 +37,7 @@ describe("transcript", () => { test("handles missing completed time", () => { const msg = { ...baseMsg, time: { created: 1000000 } } const result = formatAssistantHeader(msg as AssistantMessage, true) - expect(result).toBe("## Assistant (Build · claude-sonnet-4-20250514)\n\n") + expect(result).toBe("## Assistant (Code · claude-sonnet-4-20250514)\n\n") // kilocode_change }) test("titlecases agent name", () => { @@ -178,7 +178,7 @@ describe("transcript", () => { id: "msg_123", sessionID: "ses_123", role: "user", - agent: "build", + agent: "code", // kilocode_change model: { providerID: "anthropic", modelID: "claude-sonnet-4-20250514" }, time: { created: 1000000 }, } @@ -193,7 +193,7 @@ describe("transcript", () => { id: "msg_123", sessionID: "ses_123", role: "assistant", - agent: "build", + agent: "code", // kilocode_change modelID: "claude-sonnet-4-20250514", providerID: "anthropic", mode: "", @@ -205,7 +205,7 @@ describe("transcript", () => { } const parts: Part[] = [{ id: "p1", sessionID: "ses_123", messageID: "msg_123", type: "text", text: "Hi there" }] const result = formatMessage(msg, parts, options) - expect(result).toContain("## Assistant (Build · claude-sonnet-4-20250514 · 5.4s)") + expect(result).toContain("## Assistant (Code · claude-sonnet-4-20250514 · 5.4s)") // kilocode_change expect(result).toContain("Hi there") }) }) @@ -223,7 +223,7 @@ describe("transcript", () => { id: "msg_1", sessionID: "ses_abc123", role: "user" as const, - agent: "build", + agent: "code", // kilocode_change model: { providerID: "anthropic", modelID: "claude-sonnet-4-20250514" }, time: { created: 1000000000000 }, }, @@ -234,7 +234,7 @@ describe("transcript", () => { id: "msg_2", sessionID: "ses_abc123", role: "assistant" as const, - agent: "build", + agent: "code", // kilocode_change modelID: "claude-sonnet-4-20250514", providerID: "anthropic", mode: "", @@ -255,7 +255,7 @@ describe("transcript", () => { expect(result).toContain("**Session ID:** ses_abc123") expect(result).toContain("## User") expect(result).toContain("Hello") - expect(result).toContain("## Assistant (Build · claude-sonnet-4-20250514 · 0.5s)") + expect(result).toContain("## Assistant (Code · claude-sonnet-4-20250514 · 0.5s)") // kilocode_change expect(result).toContain("Hi!") expect(result).toContain("---") }) @@ -272,7 +272,7 @@ describe("transcript", () => { id: "msg_1", sessionID: "ses_abc123", role: "assistant" as const, - agent: "build", + agent: "code", // kilocode_change modelID: "claude-sonnet-4-20250514", providerID: "anthropic", mode: "", @@ -290,7 +290,7 @@ describe("transcript", () => { const result = formatTranscript(session, messages, options) expect(result).toContain("## Assistant\n\n") - expect(result).not.toContain("Build") + expect(result).not.toContain("Code") // kilocode_change expect(result).not.toContain("claude-sonnet-4-20250514") }) }) diff --git a/packages/opencode/test/config/agent-color.test.ts b/packages/opencode/test/config/agent-color.test.ts index a2c3742967..273537b1f7 100644 --- a/packages/opencode/test/config/agent-color.test.ts +++ b/packages/opencode/test/config/agent-color.test.ts @@ -14,7 +14,7 @@ test("agent color parsed from project config", async () => { JSON.stringify({ $schema: "https://opencode.ai/config.json", agent: { - build: { color: "#FFA500" }, + code: { color: "#FFA500" }, // kilocode_change }, }), ) @@ -24,7 +24,7 @@ test("agent color parsed from project config", async () => { directory: tmp.path, fn: async () => { const cfg = await Config.get() - expect(cfg.agent?.["build"]?.color).toBe("#FFA500") + expect(cfg.agent?.["code"]?.color).toBe("#FFA500") // kilocode_change }, }) }) diff --git a/packages/opencode/test/tool/apply_patch.test.ts b/packages/opencode/test/tool/apply_patch.test.ts index a08e235885..3a12210f33 100644 --- a/packages/opencode/test/tool/apply_patch.test.ts +++ b/packages/opencode/test/tool/apply_patch.test.ts @@ -9,7 +9,7 @@ const baseCtx = { sessionID: "test", messageID: "", callID: "", - agent: "build", + agent: "code", // kilocode_change abort: AbortSignal.any([]), messages: [], metadata: () => {}, diff --git a/packages/opencode/test/tool/bash.test.ts b/packages/opencode/test/tool/bash.test.ts index 454293c8fb..3f19db304b 100644 --- a/packages/opencode/test/tool/bash.test.ts +++ b/packages/opencode/test/tool/bash.test.ts @@ -10,7 +10,7 @@ const ctx = { sessionID: "test", messageID: "", callID: "", - agent: "build", + agent: "code", // kilocode_change abort: AbortSignal.any([]), messages: [], metadata: () => {}, diff --git a/packages/opencode/test/tool/external-directory.test.ts b/packages/opencode/test/tool/external-directory.test.ts index 33c5e2c739..716dd9a3ff 100644 --- a/packages/opencode/test/tool/external-directory.test.ts +++ b/packages/opencode/test/tool/external-directory.test.ts @@ -9,7 +9,7 @@ const baseCtx: Omit = { sessionID: "test", messageID: "", callID: "", - agent: "build", + agent: "code", // kilocode_change abort: AbortSignal.any([]), messages: [], metadata: () => {}, diff --git a/packages/opencode/test/tool/grep.test.ts b/packages/opencode/test/tool/grep.test.ts index e774580df6..7c7b31cf58 100644 --- a/packages/opencode/test/tool/grep.test.ts +++ b/packages/opencode/test/tool/grep.test.ts @@ -8,7 +8,7 @@ const ctx = { sessionID: "test", messageID: "", callID: "", - agent: "build", + agent: "code", // kilocode_change abort: AbortSignal.any([]), messages: [], metadata: () => {}, diff --git a/packages/opencode/test/tool/read.test.ts b/packages/opencode/test/tool/read.test.ts index afa14bc6cb..dda648c558 100644 --- a/packages/opencode/test/tool/read.test.ts +++ b/packages/opencode/test/tool/read.test.ts @@ -12,7 +12,7 @@ const ctx = { sessionID: "test", messageID: "", callID: "", - agent: "build", + agent: "code", // kilocode_change abort: AbortSignal.any([]), messages: [], metadata: () => {}, @@ -136,7 +136,9 @@ describe("tool.read env file permissions", () => { ["environment.ts", false], ] - describe.each(["build", "plan"])("agent=%s", (agentName) => { + // kilocode_change start - renamed from "build" to "code" + describe.each(["code", "plan"])("agent=%s", (agentName) => { + // kilocode_change end test.each(cases)("%s asks=%s", async (filename, shouldAsk) => { await using tmp = await tmpdir({ init: (dir) => Bun.write(path.join(dir, filename), "content"), diff --git a/packages/plugin/package.json b/packages/plugin/package.json index a72846f170..a615192f82 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/plugin", - "version": "1.1.42", + "version": "1.0.13", "type": "module", "license": "MIT", "scripts": { @@ -25,4 +25,4 @@ "typescript": "catalog:", "@typescript/native-preview": "catalog:" } -} +} \ No newline at end of file diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index 12c433abcd..9ad5fcfea9 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@kilocode/sdk", - "version": "1.1.42", + "version": "1.0.13", "type": "module", "license": "MIT", "scripts": { @@ -30,4 +30,4 @@ "publishConfig": { "directory": "dist" } -} +} \ No newline at end of file diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index d80734812a..a1a1d481bf 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -1671,7 +1671,7 @@ export type Config = { */ small_model?: string /** - * Default agent to use when none is specified. Must be a primary agent. Falls back to 'build' if not set or if the specified agent is invalid. + * Default agent to use when none is specified. Must be a primary agent. Falls back to 'code' if not set or if the specified agent is invalid. */ default_agent?: string /** diff --git a/packages/sdk/openapi.json b/packages/sdk/openapi.json index a02c5dff37..74c91210bc 100644 --- a/packages/sdk/openapi.json +++ b/packages/sdk/openapi.json @@ -9821,7 +9821,7 @@ "type": "string" }, "default_agent": { - "description": "Default agent to use when none is specified. Must be a primary agent. Falls back to 'build' if not set or if the specified agent is invalid.", + "description": "Default agent to use when none is specified. Must be a primary agent. Falls back to 'code' if not set or if the specified agent is invalid.", "type": "string" }, "username": { diff --git a/packages/slack/package.json b/packages/slack/package.json index f6703a01d1..26794fb5b7 100644 --- a/packages/slack/package.json +++ b/packages/slack/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/slack", - "version": "1.1.42", + "version": "1.0.13", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/ui/package.json b/packages/ui/package.json index 9efd23fd29..b8dbc98a30 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "1.1.42", + "version": "1.0.13", "type": "module", "license": "MIT", "exports": { diff --git a/packages/util/package.json b/packages/util/package.json index 06677a1132..38143cd603 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/util", - "version": "1.1.42", + "version": "1.0.13", "private": true, "type": "module", "license": "MIT", diff --git a/packages/web/package.json b/packages/web/package.json index 4e22998717..9f1a7b62a9 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -2,7 +2,7 @@ "name": "@opencode-ai/web", "type": "module", "license": "MIT", - "version": "1.1.42", + "version": "1.0.13", "scripts": { "dev": "astro dev", "dev:remote": "VITE_API_URL=https://api.opencode.ai astro dev", diff --git a/script/publish-start.ts b/script/publish-start.ts index 385a2384bc..9e91c2425c 100755 --- a/script/publish-start.ts +++ b/script/publish-start.ts @@ -37,7 +37,10 @@ let notes: string[] = [] console.log("=== publishing ===\n") -if (!Script.preview) { +const skipNotes = process.env["OPENCODE_SKIP_NOTES"] === "1" // kilocode_change +if (skipNotes) console.log("changelog skipped: OPENCODE_SKIP_NOTES=1") // kilocode_change + +if (!Script.preview && !skipNotes) { const previous = await getLatestRelease() notes = await buildNotes(previous, "HEAD") // notes.unshift(highlightsTemplate) @@ -86,7 +89,7 @@ if (!Script.preview) { await $`git cherry-pick HEAD..origin/dev`.nothrow() await $`git push origin HEAD --tags --no-verify --force-with-lease` await new Promise((resolve) => setTimeout(resolve, 5_000)) - await $`gh release create v${Script.version} -d --title "v${Script.version}" --notes ${notes.join("\n") || "No notable changes"} ./packages/opencode/dist/*.zip ./packages/opencode/dist/*.tar.gz` + await $`gh release create v${Script.version} -d --title "v${Script.version}" --notes ${notes.join("\n") || "No notable changes"} ./packages/opencode/dist/archives/*.zip ./packages/opencode/dist/archives/*.tar.gz` // kilocode_change - archives now in subdirectory const release = await $`gh release view v${Script.version} --json id,tagName`.json() output += `release=${release.id}\n` output += `tag=${release.tagName}\n` diff --git a/sdks/vscode/package.json b/sdks/vscode/package.json index 00a8e373c7..f957c454b7 100644 --- a/sdks/vscode/package.json +++ b/sdks/vscode/package.json @@ -2,7 +2,7 @@ "name": "opencode", "displayName": "opencode", "description": "opencode for VS Code", - "version": "1.1.42", + "version": "1.0.13", "publisher": "sst-dev", "repository": { "type": "git",