Merge branch 'dev' into add-auto-model
This commit is contained in:
@@ -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
|
||||
@@ -1,3 +1,35 @@
|
||||
### What does this PR do?
|
||||
## Context
|
||||
|
||||
### How did you verify your code works?
|
||||
<!-- Brief description of WHAT you’re 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 you’d 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. -->
|
||||
|
||||
@@ -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
|
||||
@@ -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 }}
|
||||
|
||||
|
||||
@@ -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
@@ -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 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=<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,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
@@ -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.
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/app",
|
||||
"version": "1.1.42",
|
||||
"version": "1.0.13",
|
||||
"description": "",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/console-app",
|
||||
"version": "1.1.42",
|
||||
"version": "1.0.13",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -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,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,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,7 +1,7 @@
|
||||
{
|
||||
"name": "@opencode-ai/desktop",
|
||||
"private": true,
|
||||
"version": "1.1.42",
|
||||
"version": "1.0.13",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/enterprise",
|
||||
"version": "1.1.42",
|
||||
"version": "1.0.13",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -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,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,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,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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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> = {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
-1
@@ -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>
|
||||
@@ -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",
|
||||
},
|
||||
],
|
||||
|
||||
@@ -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: () => {},
|
||||
|
||||
@@ -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: () => {},
|
||||
|
||||
@@ -8,7 +8,7 @@ const ctx = {
|
||||
sessionID: "test",
|
||||
messageID: "",
|
||||
callID: "",
|
||||
agent: "build",
|
||||
agent: "code", // kilocode_change
|
||||
abort: AbortSignal.any([]),
|
||||
messages: [],
|
||||
metadata: () => {},
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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
|
||||
/**
|
||||
|
||||
@@ -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,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/slack",
|
||||
"version": "1.1.42",
|
||||
"version": "1.0.13",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/ui",
|
||||
"version": "1.1.42",
|
||||
"version": "1.0.13",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"exports": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/util",
|
||||
"version": "1.1.42",
|
||||
"version": "1.0.13",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user