Merge branch 'dev' into add-auto-model

This commit is contained in:
Igor Šćekić
2026-02-03 14:26:28 +01:00
58 changed files with 720 additions and 504 deletions
+4
View File
@@ -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
+34 -2
View File
@@ -1,3 +1,35 @@
### What does this PR do?
## Context
### How did you verify your code works?
<!-- Brief description of WHAT youre doing and WHY. -->
## Implementation
<!--
Some description of HOW you achieved it. Perhaps give a high level description of the program flow. Did you need to refactor something? What tradeoffs did you take? Are there things in here which youd particularly like people to pay close attention to?
-->
## Screenshots
| before | after |
| ------ | ----- |
| | |
## How to Test
<!--
A straightforward scenario of how to test your changes will help reviewers that are not familiar with the part of the code that you are changing but want to see it in action. This section can include a description or step-by-step instructions of how to get to the state of v2 that your change affects.
A "How To Test" section can look something like this:
- Sign in with a user with tracks
- Activate `show_awesome_cat_gifs` feature (add `?feature.show_awesome_cat_gifs=1` to your URL)
- You should see a GIF with cats dancing
-->
## Get in Touch
<!-- We'd love to have a way to chat with you about your changes if necessary. If you're in the [Kilo Code Discord](https://kilo.ai/discord), please share your handle here. -->
-72
View File
@@ -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
+14
View File
@@ -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 }}
+128
View File
@@ -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.
+34 -206
View File
@@ -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 <directory>
```
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-<platform>/bin/opencode
./packages/kilo-cli/dist/kilo-cli-<platform>/bin/kilo
```
Replace `<platform>` 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 <directory> # 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 <directory> # 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 Tauris `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=<url> 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()`).
+1 -1
View File
@@ -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
+28
View File
@@ -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.
+13 -1
View File
@@ -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.
---
+5 -5
View File
@@ -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
+17 -17
View File
@@ -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",
+20 -9
View File
@@ -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 (
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/app",
"version": "1.1.42",
"version": "1.0.13",
"description": "",
"type": "module",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/console-app",
"version": "1.1.42",
"version": "1.0.13",
"type": "module",
"license": "MIT",
"scripts": {
+1 -1
View File
@@ -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",
+1 -1
View File
@@ -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",
+1 -1
View File
@@ -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",
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@opencode-ai/desktop",
"private": true,
"version": "1.1.42",
"version": "1.0.13",
"type": "module",
"license": "MIT",
"scripts": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/enterprise",
"version": "1.1.42",
"version": "1.0.13",
"private": true,
"type": "module",
"license": "MIT",
+6 -6
View File
@@ -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"]
+1 -1
View File
@@ -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",
+1 -1
View File
@@ -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",
@@ -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) {
<text attributes={TextAttributes.BOLD} fg={theme.text}>
News
</text>
<text fg={theme.textMuted}>esc</text>
<box
paddingLeft={1}
paddingRight={1}
backgroundColor={closeHover() ? theme.backgroundElement : undefined}
onMouseOver={() => setCloseHover(true)}
onMouseOut={() => setCloseHover(false)}
onMouseUp={() => dialog.clear()}
>
<text fg={closeHover() ? theme.text : theme.textMuted}>esc</text>
</box>
</box>
<scrollbox maxHeight={15} flexGrow={1}>
<box gap={2} paddingBottom={1}>
<box gap={0} paddingBottom={1}>
<For each={props.notifications}>
{(notification) => (
<box gap={0}>
<box flexDirection="row" gap={1}>
<text fg={theme.info}>*</text>
<text attributes={TextAttributes.BOLD} fg={theme.text}>
{notification.title}
</text>
{(notification) => {
const [hover, setHover] = createSignal(false)
return (
<box
gap={0}
backgroundColor={hover() ? theme.backgroundElement : undefined}
paddingTop={1}
paddingBottom={1}
paddingLeft={2}
paddingRight={2}
onMouseOver={() => setHover(true)}
onMouseOut={() => setHover(false)}
>
<box flexDirection="row" gap={1}>
<text fg={hover() ? theme.primary : theme.info}>*</text>
<text attributes={TextAttributes.BOLD} fg={hover() ? theme.primary : theme.text}>
{notification.title}
</text>
</box>
<box paddingLeft={2}>
<text fg={hover() ? theme.text : theme.textMuted} wrapMode="word">
{notification.message}
</text>
{notification.action && (
<box flexDirection="row" marginTop={1}>
<Link
href={notification.action.actionURL}
fg={theme.primary}
attributes={hover() ? TextAttributes.BOLD : undefined}
>
[{notification.action.actionText}]
</Link>
</box>
)}
</box>
</box>
<box paddingLeft={2}>
<text fg={theme.textMuted} wrapMode="word">
{notification.message}
</text>
{notification.action && (
<box flexDirection="row" marginTop={1}>
<Link href={notification.action.actionURL} fg={theme.primary}>
[{notification.action.actionText}]
</Link>
</box>
)}
</box>
</box>
)}
)
}}
</For>
</box>
</scrollbox>
@@ -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 (
<box flexDirection="column" maxWidth="100%" onMouseUp={props.onClick}>
<box
flexDirection="column"
maxWidth="100%"
backgroundColor={hover() ? theme.backgroundElement : undefined}
paddingTop={1}
paddingBottom={1}
paddingLeft={2}
paddingRight={2}
onMouseOver={() => setHover(true)}
onMouseOut={() => setHover(false)}
onMouseUp={props.onClick}
>
{/* Line 1: Icon + Title + Count */}
<box flexDirection="row" gap={1}>
<text flexShrink={0} style={{ fg: theme.info }}>
<text flexShrink={0} style={{ fg: hover() ? theme.primary : theme.info }}>
*
</text>
<text flexShrink={0} style={{ fg: theme.text }}>
<text flexShrink={0} style={{ fg: hover() ? theme.primary : theme.text }}>
{props.notification.title}
</text>
<Show when={props.totalCount > 0}>
<text flexShrink={0} style={{ fg: theme.textMuted }}>
<text flexShrink={0} style={{ fg: hover() ? theme.primary : theme.textMuted }}>
({props.totalCount} new)
</text>
</Show>
@@ -43,7 +55,7 @@ export function NotificationBanner(props: NotificationBannerProps) {
{/* Line 2: Message (indented to align under title) */}
<box paddingLeft={2}>
<text style={{ fg: theme.textMuted }} wrapMode="word">
<text style={{ fg: hover() ? theme.text : theme.textMuted }} wrapMode="word">
{props.notification.message}
</text>
</box>
+1 -1
View File
@@ -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",
+2 -2
View File
@@ -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",
+4
View File
@@ -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,
+7 -2
View File
@@ -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"
+10 -4
View File
@@ -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)
+11 -2
View File
@@ -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"
+1 -1
View File
@@ -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,
+21 -9
View File
@@ -72,9 +72,11 @@ export namespace Agent {
const user = PermissionNext.fromConfig(cfg.permission ?? {})
const result: Record<string, Info> = {
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
+3 -1
View File
@@ -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()
@@ -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",
@@ -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<string, string> = {
+17 -2
View File
@@ -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"
+6 -4
View File
@@ -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)
@@ -1,5 +1,5 @@
<system-reminder>
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.
</system-reminder>
+11 -7
View File
@@ -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"
],
},
],
@@ -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",
},
],
+199 -74
View File
@@ -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
@@ -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")
})
})
@@ -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
},
})
})
@@ -9,7 +9,7 @@ const baseCtx = {
sessionID: "test",
messageID: "",
callID: "",
agent: "build",
agent: "code", // kilocode_change
abort: AbortSignal.any([]),
messages: [],
metadata: () => {},
+1 -1
View File
@@ -10,7 +10,7 @@ const ctx = {
sessionID: "test",
messageID: "",
callID: "",
agent: "build",
agent: "code", // kilocode_change
abort: AbortSignal.any([]),
messages: [],
metadata: () => {},
@@ -9,7 +9,7 @@ const baseCtx: Omit<Tool.Context, "ask"> = {
sessionID: "test",
messageID: "",
callID: "",
agent: "build",
agent: "code", // kilocode_change
abort: AbortSignal.any([]),
messages: [],
metadata: () => {},
+1 -1
View File
@@ -8,7 +8,7 @@ const ctx = {
sessionID: "test",
messageID: "",
callID: "",
agent: "build",
agent: "code", // kilocode_change
abort: AbortSignal.any([]),
messages: [],
metadata: () => {},
+4 -2
View File
@@ -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"),
+2 -2
View File
@@ -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:"
}
}
}
+2 -2
View File
@@ -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"
}
}
}
+1 -1
View File
@@ -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
/**
+1 -1
View File
@@ -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": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/slack",
"version": "1.1.42",
"version": "1.0.13",
"type": "module",
"license": "MIT",
"scripts": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/ui",
"version": "1.1.42",
"version": "1.0.13",
"type": "module",
"license": "MIT",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/util",
"version": "1.1.42",
"version": "1.0.13",
"private": true,
"type": "module",
"license": "MIT",
+1 -1
View File
@@ -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",
+5 -2
View File
@@ -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`
+1 -1
View File
@@ -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",