diff --git a/.changeset/allow-keyless-indexing.md b/.changeset/allow-keyless-indexing.md new file mode 100644 index 0000000000..c60fa89140 --- /dev/null +++ b/.changeset/allow-keyless-indexing.md @@ -0,0 +1,7 @@ +--- +"@kilocode/cli": patch +"@kilocode/kilo-indexing": patch +"kilo-code": patch +--- + +Support unauthenticated OpenAI-compatible endpoints for codebase indexing without requiring a placeholder API key. diff --git a/.changeset/calm-models-reason.md b/.changeset/calm-models-reason.md new file mode 100644 index 0000000000..49fc92940f --- /dev/null +++ b/.changeset/calm-models-reason.md @@ -0,0 +1,5 @@ +--- +"kilo-code": minor +--- + +Support multiple provider APIs, adaptive thinking, split reasoning, and output effort variants for custom providers. diff --git a/.changeset/close-read-tui-news.md b/.changeset/close-read-tui-news.md new file mode 100644 index 0000000000..ce1fd8845c --- /dev/null +++ b/.changeset/close-read-tui-news.md @@ -0,0 +1,5 @@ +--- +"@kilocode/cli": patch +--- + +Hide TUI news after they have been opened and add a button to close the news dialog. diff --git a/.changeset/fix-diff-viewer-corners.md b/.changeset/fix-diff-viewer-corners.md new file mode 100644 index 0000000000..ed8c1520ac --- /dev/null +++ b/.changeset/fix-diff-viewer-corners.md @@ -0,0 +1,5 @@ +--- +"kilo-code": patch +--- + +Remove stray rounded corners between files in the Changes diff viewer. diff --git a/.changeset/fix-kilo-npm-upgrade.md b/.changeset/fix-kilo-npm-upgrade.md new file mode 100644 index 0000000000..307a40eb8f --- /dev/null +++ b/.changeset/fix-kilo-npm-upgrade.md @@ -0,0 +1,5 @@ +--- +"@kilocode/cli": patch +--- + +Fix upgrades to resolve Kilo CLI packages and releases instead of OpenCode packages and versions. diff --git a/.changeset/fix-session-scope-toggle.md b/.changeset/fix-session-scope-toggle.md new file mode 100644 index 0000000000..38396df275 --- /dev/null +++ b/.changeset/fix-session-scope-toggle.md @@ -0,0 +1,5 @@ +--- +"@kilocode/cli": patch +--- + +Show current-worktree sessions by default in the TUI sessions dialog and keep all/current scope toggling working when a scope has no sessions. diff --git a/.changeset/highlight-jetbrains-shell-commands.md b/.changeset/highlight-jetbrains-shell-commands.md new file mode 100644 index 0000000000..394ac4ea35 --- /dev/null +++ b/.changeset/highlight-jetbrains-shell-commands.md @@ -0,0 +1,5 @@ +--- +"@kilocode/kilo-jetbrains": patch +--- + +Highlight shell tool commands in JetBrains chat transcripts. diff --git a/.changeset/improve-jetbrains-markdown.md b/.changeset/improve-jetbrains-markdown.md new file mode 100644 index 0000000000..ff1a1845e0 --- /dev/null +++ b/.changeset/improve-jetbrains-markdown.md @@ -0,0 +1,5 @@ +--- +"@kilocode/kilo-jetbrains": patch +--- + +Improve markdown readability in JetBrains chat transcripts. diff --git a/.changeset/jetbrains-hide-read-payloads.md b/.changeset/jetbrains-hide-read-payloads.md new file mode 100644 index 0000000000..6216844f0c --- /dev/null +++ b/.changeset/jetbrains-hide-read-payloads.md @@ -0,0 +1,5 @@ +--- +"@kilocode/kilo-jetbrains": patch +--- + +Hide generated read-tool payload lines from JetBrains prompt bubbles while keeping attachments and assistant tool output visible. diff --git a/.changeset/jetbrains-horizontal-attachments.md b/.changeset/jetbrains-horizontal-attachments.md new file mode 100644 index 0000000000..2b167a0198 --- /dev/null +++ b/.changeset/jetbrains-horizontal-attachments.md @@ -0,0 +1,5 @@ +--- +"@kilocode/kilo-jetbrains": patch +--- + +Show JetBrains prompt attachments in one horizontal scrolling row in session history. diff --git a/.changeset/jetbrains-paste-attachments.md b/.changeset/jetbrains-paste-attachments.md new file mode 100644 index 0000000000..1003291b27 --- /dev/null +++ b/.changeset/jetbrains-paste-attachments.md @@ -0,0 +1,5 @@ +--- +"@kilocode/kilo-jetbrains": patch +--- + +Support pasting files and images into JetBrains chat prompts as attachments. diff --git a/.changeset/jetbrains-prompt-attachment-preview.md b/.changeset/jetbrains-prompt-attachment-preview.md new file mode 100644 index 0000000000..f5b33305c4 --- /dev/null +++ b/.changeset/jetbrains-prompt-attachment-preview.md @@ -0,0 +1,5 @@ +--- +"@kilocode/kilo-jetbrains": patch +--- + +Show JetBrains prompt attachments inside the prompt bubble with previews and open embedded attachments in editor tabs. diff --git a/.changeset/jetbrains-prompt-attachments.md b/.changeset/jetbrains-prompt-attachments.md new file mode 100644 index 0000000000..efde818645 --- /dev/null +++ b/.changeset/jetbrains-prompt-attachments.md @@ -0,0 +1,5 @@ +--- +"@kilocode/kilo-jetbrains": patch +--- + +Support sending file and image attachments from the JetBrains chat prompt. diff --git a/.changeset/jetbrains-prompt-input-height.md b/.changeset/jetbrains-prompt-input-height.md new file mode 100644 index 0000000000..120f0ff4dd --- /dev/null +++ b/.changeset/jetbrains-prompt-input-height.md @@ -0,0 +1,5 @@ +--- +"@kilocode/kilo-jetbrains": patch +--- + +Limit JetBrains prompt input growth to the session while preserving scrolling for long prompts. diff --git a/.changeset/jetbrains-restartless-unload.md b/.changeset/jetbrains-restartless-unload.md new file mode 100644 index 0000000000..62e2f7941a --- /dev/null +++ b/.changeset/jetbrains-restartless-unload.md @@ -0,0 +1,5 @@ +--- +"@kilocode/kilo-jetbrains": patch +--- + +Stop Kilo backend processes and clear JetBrains UI resources during restartless plugin unloads. diff --git a/.changeset/jetbrains-session-drop-overlay.md b/.changeset/jetbrains-session-drop-overlay.md new file mode 100644 index 0000000000..64be585e38 --- /dev/null +++ b/.changeset/jetbrains-session-drop-overlay.md @@ -0,0 +1,5 @@ +--- +"@kilocode/kilo-jetbrains": patch +--- + +Support dropping files anywhere in a JetBrains chat session to add them to the prompt. diff --git a/.changeset/jetbrains-session-icons.md b/.changeset/jetbrains-session-icons.md new file mode 100644 index 0000000000..7787da1199 --- /dev/null +++ b/.changeset/jetbrains-session-icons.md @@ -0,0 +1,5 @@ +--- +"@kilocode/kilo-jetbrains": patch +--- + +Polish session header controls and align session view icons. diff --git a/.changeset/jetbrains-vfs-frontend-handoff.md b/.changeset/jetbrains-vfs-frontend-handoff.md new file mode 100644 index 0000000000..5191468366 --- /dev/null +++ b/.changeset/jetbrains-vfs-frontend-handoff.md @@ -0,0 +1,5 @@ +--- +"@kilocode/kilo-jetbrains": patch +--- + +Open embedded JetBrains message attachments in frontend-managed Kilo editor tabs with loading and connection retry states. diff --git a/.changeset/kilo-branding-leftovers.md b/.changeset/kilo-branding-leftovers.md new file mode 100644 index 0000000000..b9db063093 --- /dev/null +++ b/.changeset/kilo-branding-leftovers.md @@ -0,0 +1,5 @@ +--- +"@kilocode/cli": patch +--- + +Replace remaining OpenCode-branded CLI and TUI copy with Kilo branding. diff --git a/.changeset/list-agent-manager-worktrees.md b/.changeset/list-agent-manager-worktrees.md new file mode 100644 index 0000000000..2e15a890ad --- /dev/null +++ b/.changeset/list-agent-manager-worktrees.md @@ -0,0 +1,5 @@ +--- +"@kilocode/cli": patch +--- + +Show Agent Manager and other Git worktrees in the Kilo Console project view. diff --git a/.changeset/load-bundled-atomic-chat.md b/.changeset/load-bundled-atomic-chat.md new file mode 100644 index 0000000000..0931695aca --- /dev/null +++ b/.changeset/load-bundled-atomic-chat.md @@ -0,0 +1,5 @@ +--- +"@kilocode/cli": patch +--- + +Load the bundled Atomic Chat integration without attempting to install an unpublished npm plugin. diff --git a/.changeset/minimax-m3-reasoning-toggle.md b/.changeset/minimax-m3-reasoning-toggle.md new file mode 100644 index 0000000000..90839cc040 --- /dev/null +++ b/.changeset/minimax-m3-reasoning-toggle.md @@ -0,0 +1,6 @@ +--- +"kilo-code": patch +"@kilocode/cli": patch +--- + +Add an instant/thinking reasoning toggle for MiniMax M-series models, matching the existing glm/kimi/qwen behavior. diff --git a/.changeset/native-plan-architect-parity.md b/.changeset/native-plan-architect-parity.md new file mode 100644 index 0000000000..2de5bf1895 --- /dev/null +++ b/.changeset/native-plan-architect-parity.md @@ -0,0 +1,5 @@ +--- +"@kilocode/cli": patch +--- + +Make native Plan mode follow Architect-style planning behavior while preserving Plan mode restrictions and repo-root plan files. diff --git a/.changeset/notify-background-sessions.md b/.changeset/notify-background-sessions.md new file mode 100644 index 0000000000..6b5646bcf7 --- /dev/null +++ b/.changeset/notify-background-sessions.md @@ -0,0 +1,5 @@ +--- +"kilo-code": minor +--- + +Offer opt-in attention sounds when sessions finish, error, or need input across the sidebar, editor tabs, and Agent Manager. diff --git a/.changeset/opencode-v1-14-51-to-v1-15-4.md b/.changeset/opencode-v1-14-51-to-v1-15-4.md new file mode 100644 index 0000000000..84907dc90c --- /dev/null +++ b/.changeset/opencode-v1-14-51-to-v1-15-4.md @@ -0,0 +1,33 @@ +--- +"@kilocode/cli": patch +"kilo-code": patch +--- + +Changes from opencode v1.14.51 to v1.15.4 upstream: + +- Core Improvements: Clarified how to recover when the npm package is installed without its native binary. +- Core Improvements: Reduced unnecessary prompting around shell, task, and todo flows. +- Core Bugfixes: Ignored invalid exports in custom tool modules instead of failing tool loading. +- Core Bugfixes: Ignored project instruction lookup errors so sessions keep loading when project instruction discovery fails. +- Core Bugfixes: Fixed versioned event projector lookups so event replay uses the right handlers. +- Core Bugfixes: Avoid duplicate consecutive entries in prompt history. +- Core Bugfixes: Show full config validation errors during TUI startup instead of a generic failure. +- Core Bugfixes: Fixed npm installs so the CLI can recover and fetch the right native binary on more setups. +- Core Bugfixes: Fixed multiline `@` mentions in prompts. +- Core Bugfixes: Preserved custom tool metadata from Zod schemas. +- Core Bugfixes: Preserved custom tool argument descriptions in generated schemas. +- Core Bugfixes: Fixed file watching in repos where `.git` is a symlink. (@kagura-agent) +- Core Bugfixes: Fixed sync events not reaching project-scoped subscribers in injected instances. +- Core Bugfixes: Reduced wasted work when reading very large files after output truncation. +- Core Bugfixes: Fixed project-scoped bus events so file watcher and update notifications reach the right instance. +- Core Bugfixes: Fixed custom LSP servers not sending refresh events after they initialize. +- Core Bugfixes: Hid background subagent task instructions unless experimental background mode is enabled. +- TUI Improvements: Added a collapsed thinking view that can be expanded inline. +- TUI Improvements: Added pinned sessions with quick-switch slots in the session picker. +- TUI Improvements: Newly pinned sessions now stay at the end of the pinned list instead of jumping to the top. +- TUI Improvements: Made Markdown H1 headings easier to distinguish. +- TUI Bugfixes: Fixed thinking mode defaults so reasoning starts collapsed consistently. +- TUI Bugfixes: Limited session quick-switching to pinned sessions. +- TUI Bugfixes: Fixed Markdown table rendering in chat output. +- TUI Bugfixes: Fixed `kilo run --agent` resolving project-local agents. +- TUI Bugfixes: Fixed async commands losing the active instance context, which could break agent generation and GitHub-driven runs. diff --git a/.changeset/plan-timestamp-prefix.md b/.changeset/plan-timestamp-prefix.md new file mode 100644 index 0000000000..d757c9686b --- /dev/null +++ b/.changeset/plan-timestamp-prefix.md @@ -0,0 +1,5 @@ +--- +"@kilocode/cli": patch +--- + +Restore session timestamp prefixes for generated plan filenames while preserving descriptive model-chosen names. diff --git a/.changeset/preserve-console-review-expansion.md b/.changeset/preserve-console-review-expansion.md new file mode 100644 index 0000000000..3b7f19283a --- /dev/null +++ b/.changeset/preserve-console-review-expansion.md @@ -0,0 +1,5 @@ +--- +"@kilocode/cli": patch +--- + +Keep expanded Kilo Console file diffs open while resizing the context sidebar. diff --git a/.changeset/preserve-console-terminals.md b/.changeset/preserve-console-terminals.md new file mode 100644 index 0000000000..476e44608f --- /dev/null +++ b/.changeset/preserve-console-terminals.md @@ -0,0 +1,5 @@ +--- +"@kilocode/cli": patch +--- + +Keep Kilo Console terminal sessions open when changing diff layout and other console preferences. diff --git a/.changeset/render-jetbrains-attachment-cards.md b/.changeset/render-jetbrains-attachment-cards.md new file mode 100644 index 0000000000..fc26c664e3 --- /dev/null +++ b/.changeset/render-jetbrains-attachment-cards.md @@ -0,0 +1,5 @@ +--- +"@kilocode/kilo-jetbrains": patch +--- + +Render file attachments as attachment cards in JetBrains prompts and session history. diff --git a/.changeset/render-jetbrains-shell-markdown.md b/.changeset/render-jetbrains-shell-markdown.md new file mode 100644 index 0000000000..267e7bd805 --- /dev/null +++ b/.changeset/render-jetbrains-shell-markdown.md @@ -0,0 +1,5 @@ +--- +"@kilocode/kilo-jetbrains": patch +--- + +Render JetBrains shell tool output with markdown code blocks. diff --git a/.changeset/silent-comet-attachments.md b/.changeset/silent-comet-attachments.md new file mode 100644 index 0000000000..fb622dba66 --- /dev/null +++ b/.changeset/silent-comet-attachments.md @@ -0,0 +1,5 @@ +--- +"@kilocode/kilo-jetbrains": patch +--- + +Open embedded transcript attachments in stable Kilo editor tabs. diff --git a/.github/workflows/close-stale-prs.yml b/.github/workflows/close-stale-prs.yml deleted file mode 100644 index 3e7b1db14b..0000000000 --- a/.github/workflows/close-stale-prs.yml +++ /dev/null @@ -1,236 +0,0 @@ -name: close-stale-prs # kilocode_change - -on: - workflow_dispatch: - inputs: - dryRun: - description: "Log actions without closing PRs" - type: boolean - default: false - schedule: - - cron: "0 6 * * *" - -permissions: - contents: read - issues: write - pull-requests: write - -jobs: - close-stale-prs: - if: github.repository == 'anomalyco/opencode' # kilocode_change - Kilo uses kilo-auto-close.yml - runs-on: blacksmith-2vcpu-ubuntu-2404 # kilocode_change - timeout-minutes: 15 - steps: - - name: Close inactive PRs - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const DAYS_INACTIVE = 60 - const MAX_RETRIES = 3 - - // Adaptive delay: fast for small batches, slower for large to respect - // GitHub's 80 content-generating requests/minute limit - const SMALL_BATCH_THRESHOLD = 10 - const SMALL_BATCH_DELAY_MS = 1000 // 1s for daily operations (≤10 PRs) - const LARGE_BATCH_DELAY_MS = 2000 // 2s for backlog (>10 PRs) = ~30 ops/min, well under 80 limit - - const startTime = Date.now() - const cutoff = new Date(Date.now() - DAYS_INACTIVE * 24 * 60 * 60 * 1000) - const { owner, repo } = context.repo - const dryRun = context.payload.inputs?.dryRun === "true" - - core.info(`Dry run mode: ${dryRun}`) - core.info(`Cutoff date: ${cutoff.toISOString()}`) - - function sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)) - } - - async function withRetry(fn, description = 'API call') { - let lastError - for (let attempt = 0; attempt < MAX_RETRIES; attempt++) { - try { - const result = await fn() - return result - } catch (error) { - lastError = error - const isRateLimited = error.status === 403 && - (error.message?.includes('rate limit') || error.message?.includes('secondary')) - - if (!isRateLimited) { - throw error - } - - // Parse retry-after header, default to 60 seconds - const retryAfter = error.response?.headers?.['retry-after'] - ? parseInt(error.response.headers['retry-after']) - : 60 - - // Exponential backoff: retryAfter * 2^attempt - const backoffMs = retryAfter * 1000 * Math.pow(2, attempt) - - core.warning(`${description}: Rate limited (attempt ${attempt + 1}/${MAX_RETRIES}). Waiting ${backoffMs / 1000}s before retry...`) - - await sleep(backoffMs) - } - } - core.error(`${description}: Max retries (${MAX_RETRIES}) exceeded`) - throw lastError - } - - const query = ` - query($owner: String!, $repo: String!, $cursor: String) { - repository(owner: $owner, name: $repo) { - pullRequests(first: 100, states: OPEN, after: $cursor) { - pageInfo { - hasNextPage - endCursor - } - nodes { - number - title - author { - login - } - createdAt - commits(last: 1) { - nodes { - commit { - committedDate - } - } - } - comments(last: 1) { - nodes { - createdAt - } - } - reviews(last: 1) { - nodes { - createdAt - } - } - } - } - } - } - ` - - const allPrs = [] - let cursor = null - let hasNextPage = true - let pageCount = 0 - - while (hasNextPage) { - pageCount++ - core.info(`Fetching page ${pageCount} of open PRs...`) - - const result = await withRetry( - () => github.graphql(query, { owner, repo, cursor }), - `GraphQL page ${pageCount}` - ) - - allPrs.push(...result.repository.pullRequests.nodes) - hasNextPage = result.repository.pullRequests.pageInfo.hasNextPage - cursor = result.repository.pullRequests.pageInfo.endCursor - - core.info(`Page ${pageCount}: fetched ${result.repository.pullRequests.nodes.length} PRs (total: ${allPrs.length})`) - - // Delay between pagination requests (use small batch delay for reads) - if (hasNextPage) { - await sleep(SMALL_BATCH_DELAY_MS) - } - } - - core.info(`Found ${allPrs.length} open pull requests`) - - const stalePrs = allPrs.filter((pr) => { - const dates = [ - new Date(pr.createdAt), - pr.commits.nodes[0] ? new Date(pr.commits.nodes[0].commit.committedDate) : null, - pr.comments.nodes[0] ? new Date(pr.comments.nodes[0].createdAt) : null, - pr.reviews.nodes[0] ? new Date(pr.reviews.nodes[0].createdAt) : null, - ].filter((d) => d !== null) - - const lastActivity = dates.sort((a, b) => b.getTime() - a.getTime())[0] - - if (!lastActivity || lastActivity > cutoff) { - core.info(`PR #${pr.number} is fresh (last activity: ${lastActivity?.toISOString() || "unknown"})`) - return false - } - - core.info(`PR #${pr.number} is STALE (last activity: ${lastActivity.toISOString()})`) - return true - }) - - if (!stalePrs.length) { - core.info("No stale pull requests found.") - return - } - - core.info(`Found ${stalePrs.length} stale pull requests`) - - // ============================================ - // Close stale PRs - // ============================================ - const requestDelayMs = stalePrs.length > SMALL_BATCH_THRESHOLD - ? LARGE_BATCH_DELAY_MS - : SMALL_BATCH_DELAY_MS - - core.info(`Using ${requestDelayMs}ms delay between operations (${stalePrs.length > SMALL_BATCH_THRESHOLD ? 'large' : 'small'} batch mode)`) - - let closedCount = 0 - let skippedCount = 0 - - for (const pr of stalePrs) { - const issue_number = pr.number - const closeComment = `Closing this pull request because it has had no updates for more than ${DAYS_INACTIVE} days. If you plan to continue working on it, feel free to reopen or open a new PR.` - - if (dryRun) { - core.info(`[dry-run] Would close PR #${issue_number} from ${pr.author?.login || 'unknown'}: ${pr.title}`) - continue - } - - try { - // Add comment - await withRetry( - () => github.rest.issues.createComment({ - owner, - repo, - issue_number, - body: closeComment, - }), - `Comment on PR #${issue_number}` - ) - - // Close PR - await withRetry( - () => github.rest.pulls.update({ - owner, - repo, - pull_number: issue_number, - state: "closed", - }), - `Close PR #${issue_number}` - ) - - closedCount++ - core.info(`Closed PR #${issue_number} from ${pr.author?.login || 'unknown'}: ${pr.title}`) - - // Delay before processing next PR - await sleep(requestDelayMs) - } catch (error) { - skippedCount++ - core.error(`Failed to close PR #${issue_number}: ${error.message}`) - } - } - - const elapsed = Math.round((Date.now() - startTime) / 1000) - core.info(`\n========== Summary ==========`) - core.info(`Total open PRs found: ${allPrs.length}`) - core.info(`Stale PRs identified: ${stalePrs.length}`) - core.info(`PRs closed: ${closedCount}`) - core.info(`PRs skipped (errors): ${skippedCount}`) - core.info(`Elapsed time: ${elapsed}s`) - core.info(`=============================`) diff --git a/.github/workflows/close-issues.yml b/.github/workflows/disabled/close-issues.yml.disabled similarity index 75% rename from .github/workflows/close-issues.yml rename to .github/workflows/disabled/close-issues.yml.disabled index c071fd5bc8..b8a2e3f575 100644 --- a/.github/workflows/close-issues.yml +++ b/.github/workflows/disabled/close-issues.yml.disabled @@ -7,13 +7,12 @@ on: jobs: close: - if: github.repository == 'anomalyco/opencode' # kilocode_change - Kilo uses kilo-auto-close.yml runs-on: ubuntu-latest permissions: contents: read issues: write steps: - - uses: actions/checkout@v6 # kilocode_change + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: diff --git a/.github/workflows/duplicate-issues.yml b/.github/workflows/disabled/duplicate-issues.yml.disabled similarity index 88% rename from .github/workflows/duplicate-issues.yml rename to .github/workflows/disabled/duplicate-issues.yml.disabled index cf02d8e0a4..ea2a67cb78 100644 --- a/.github/workflows/duplicate-issues.yml +++ b/.github/workflows/disabled/duplicate-issues.yml.disabled @@ -6,28 +6,25 @@ on: jobs: check-duplicates: - if: false # kilocode_change - disabled: not needed in kilocode repo + if: github.event.action == 'opened' runs-on: blacksmith-4vcpu-ubuntu-2404 permissions: contents: read issues: write steps: - name: Checkout repository - uses: actions/checkout@v6 # kilocode_change + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: fetch-depth: 1 - uses: ./.github/actions/setup-bun - # kilocode_change start - - name: Setup Kilo - uses: ./.github/actions/setup-kilo - # kilocode_change end + - name: Install opencode + run: curl -fsSL https://kilo.ai/install | bash - name: Check duplicates and compliance env: - KILO_API_KEY: ${{ secrets.KILO_API_KEY }} - KILO_ORG_ID: ${{ secrets.KILO_ORG_ID }} + OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} KILO_PERMISSION: | { @@ -38,7 +35,7 @@ jobs: "webfetch": "deny" } run: | - kilo run -m "kilo/anthropic/claude-haiku-4.5" "A new issue has been created: + opencode run -m opencode/claude-sonnet-4-6 "A new issue has been created: Issue number: ${{ github.event.issue.number }} @@ -128,23 +125,18 @@ jobs: issues: write steps: - name: Checkout repository - uses: actions/checkout@v6 # kilocode_change + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: fetch-depth: 1 - uses: ./.github/actions/setup-bun - # kilocode_change start - - name: Setup Kilo - uses: ./.github/actions/setup-kilo - # kilocode_change end + - name: Install opencode + run: curl -fsSL https://kilo.ai/install | bash - name: Recheck compliance env: - # kilocode_change start - KILO_API_KEY: ${{ secrets.KILO_API_KEY }} - KILO_ORG_ID: ${{ secrets.KILO_ORG_ID }} - # kilocode_change end + OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} KILO_PERMISSION: | { @@ -155,7 +147,7 @@ jobs: "webfetch": "deny" } run: | - kilo run -m "kilo/anthropic/claude-haiku-4.5" "Issue #${{ github.event.issue.number }} was previously flagged as non-compliant and has been edited. + opencode run -m opencode/claude-sonnet-4-6 "Issue #${{ github.event.issue.number }} was previously flagged as non-compliant and has been edited. Lookup this issue with gh issue view ${{ github.event.issue.number }}. diff --git a/.github/workflows/triage.yml b/.github/workflows/disabled/triage.yml.disabled similarity index 64% rename from .github/workflows/triage.yml rename to .github/workflows/disabled/triage.yml.disabled index b467817c71..0b2c9d89a1 100644 --- a/.github/workflows/triage.yml +++ b/.github/workflows/disabled/triage.yml.disabled @@ -6,33 +6,31 @@ on: jobs: triage: - if: github.repository == 'Kilo-Org/kilocode' runs-on: blacksmith-4vcpu-ubuntu-2404 permissions: contents: read issues: write steps: - name: Checkout repository - uses: actions/checkout@v6 # kilocode_change + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: fetch-depth: 1 - name: Setup Bun uses: ./.github/actions/setup-bun - - name: Setup Kilo - uses: ./.github/actions/setup-kilo + - name: Install opencode + run: curl -fsSL https://kilo.ai/install | bash - name: Triage issue env: - KILO_API_KEY: ${{ secrets.KILO_API_KEY }} - KILO_ORG_ID: ${{ secrets.KILO_ORG_ID }} + OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} ISSUE_NUMBER: ${{ github.event.issue.number }} ISSUE_TITLE: ${{ github.event.issue.title }} ISSUE_BODY: ${{ github.event.issue.body }} run: | - kilo run --agent triage "The following issue was just opened, triage it: + opencode run --agent triage "The following issue was just opened, triage it: Title: $ISSUE_TITLE diff --git a/.github/workflows/watch-opencode-releases.yml b/.github/workflows/watch-opencode-releases.yml index 8762e9481d..10da78231b 100644 --- a/.github/workflows/watch-opencode-releases.yml +++ b/.github/workflows/watch-opencode-releases.yml @@ -12,7 +12,7 @@ permissions: jobs: check-release: - if: vars.OPENCODE_WATCH_ENABLED != 'false' + if: github.repository == 'Kilo-Org/kilocode' && vars.OPENCODE_WATCH_ENABLED != 'false' runs-on: ubuntu-latest timeout-minutes: 5 steps: diff --git a/.kilo/plans/jetbrains-mdview-editor-theme-colors.md b/.kilo/plans/jetbrains-mdview-editor-theme-colors.md new file mode 100644 index 0000000000..20e85b546f --- /dev/null +++ b/.kilo/plans/jetbrains-mdview-editor-theme-colors.md @@ -0,0 +1,67 @@ +# JetBrains MdView Editor Theme Colors Plan + +## Goal + +Keep JetBrains markdown layout compact while making markdown colors and backgrounds come from the active editor color scheme, and ensure existing theme/editor-setting listeners refresh all existing `MdView` instances after changes. + +## Findings + +- `SessionUi` already subscribes to `EditorColorsManager.TOPIC` and `LafManagerListener.TOPIC`, then calls `applyStyle(SessionEditorStyle.current())` on the session tree. +- Most markdown consumers already propagate that style through `MdView.applyStyle(style)` via `TextView`, `ReasoningView`, message lists, and session panels. +- `PlanExitView.applyStyle()` sets only font/code font/foreground and does not call `md.applyStyle(style)`, so internal markdown role colors can stay tied to the initial style. +- `MdViewHybrid.applyStyle()` restyles retained HTML panes and code block containers, but retained `CodeField` editors need explicit reapplication of `SessionEditorStyle.applyToEditor()` after creation so syntax highlighting and editor colors follow scheme changes. +- `MdCommon.defaults()` currently mixes editor colors, UI theme colors, and one literal inline-code color fallback. The literal fallback should be removed, and markdown roles should derive from `EditorColorsScheme`/syntax attributes wherever possible. +- `TextView` currently overrides markdown background with `SessionUiStyle.Transcript.bgColor()` (`UiStyle.Colors.bg()`), while prompt markdown already uses `style.editorBackground`. If markdown surfaces should consistently use editor background, normal text views need to use `style.editorBackground` too. + +## Implementation Plan + +1. Keep compact CSS unchanged. + - Do not reintroduce line-height, margin, padding, heading sizing, or other geometry rules. + - Keep the current role color/background selectors only. + +2. Derive markdown role defaults from editor settings. + - Update `MdCommon.defaults(style)` to use `style.editorForeground` and `style.editorBackground` for primary text/background. + - Add small local helper functions for editor attributes, for example foreground/background from `style.editorScheme.getAttributes(key)` and color keys from `style.editorScheme.getColor(key)`. + - Use public IntelliJ editor keys for role colors: + - Links: `CodeInsightColors.HYPERLINK_ATTRIBUTES.foregroundColor`, fallback to platform link color if absent. + - Inline code foreground/background: `DefaultLanguageHighlighterColors.DOC_CODE_INLINE`, fallback to `STRING`, then editor foreground/background. + - Code block foreground/background: `DefaultLanguageHighlighterColors.DOC_CODE_BLOCK`, fallback to editor foreground/background. + - Quote/emphasis/list weak text: comment/doc-comment attributes, fallback to editor foreground or `UIUtil.getContextHelpForeground()` only when the scheme has no useful value. + - Borders/HR/table/code border: editor preview/border color keys such as `EditorColors.PREVIEW_BORDER_COLOR`, fallback to `UiStyle.Colors.contentBorder()`. + - Remove `JBColor(0x...)` or other literal runtime color fallbacks from `MdCommon`. + - Keep public `MdView` API unchanged; role colors stay internal unless a concrete external override need appears. + +3. Ensure style propagation reaches every markdown instance. + - Update `PlanExitView.applyStyle(style)` to call `md.applyStyle(style)` before applying its explicit font/code-font/foreground overrides. + - Audit existing markdown callers after the change; keep using the existing `SessionEditorStyleTarget` propagation path rather than adding per-`MdView` theme listeners. + - Keep explicit foreground overrides in `TextView`, `ReasoningView`, and `PlanExitView` where they intentionally set body text role, but let internal markdown role colors refresh from the new style snapshot. + +4. Ensure retained hybrid code blocks update after editor setting changes. + - In `MdViewHybrid.CodeView.style(opts)`, for retained `CodeField` blocks, reapply `style.applyToEditor(editor)` to the underlying editor if it exists. + - Reapply code editor background/scroll pane/viewport backgrounds from `opts.preBg` in the same path. + - Preserve retained component/editor reuse: do not rebuild code block panes just to update style. + +5. Align markdown backgrounds with editor settings. + - Keep `MdCommon` default background as `style.editorBackground`. + - Change normal `TextView` markdown background to `style.editorBackground` if the intent is that all markdown surfaces use editor background, matching `PromptView` and session root behavior. + - Preserve `transparent` handling: when `md.opaque = false`, background should still be the editor-derived value for child/code surfaces, but the Swing component should remain non-opaque. + +6. Update tests. + - Extend `MdViewTest` to verify markdown role CSS changes when applying a `SessionEditorStyle` backed by a customized editor scheme, especially inline code, code block, link, and border colors. + - Extend `MdViewHybridTest` to assert `applyStyle()` updates retained HTML panes and retained code editors without replacing them, including editor scheme/background changes. + - Add or extend `PlanExitViewTest` so `applyStyle()` refreshes the nested markdown style, not just foreground/font overrides. + - Keep existing compactness expectations: tests should not assert new spacing, padding, margin, line-height, or size rules. + +## Verification + +- From `packages/kilo-jetbrains/`, run `./gradlew frontend:test --tests '*MdView*'`. +- From `packages/kilo-jetbrains/`, run `./gradlew frontend:test --tests '*PlanExitViewTest*'` if the focused test is not covered by the MdView filter. +- From `packages/kilo-jetbrains/`, run `bun run typecheck`. + +## Constraints + +- Do not introduce JCEF, Compose, or Kotlin UI DSL. +- Do not add new theme/editor listeners in `MdView`; use the existing `SessionUi` listener and `SessionEditorStyleTarget` propagation path. +- Avoid hardcoded runtime colors in markdown styling; prefer editor scheme attributes/color keys, then platform/theme APIs as non-literal fallbacks. +- Preserve retained Swing behavior and `MdViewHybrid.sync()` component reuse. +- Keep the public `MdView` override API stable unless implementation proves a new external override is required. diff --git a/.kilo/plans/jetbrains-mdview-vscode-styling.md b/.kilo/plans/jetbrains-mdview-vscode-styling.md new file mode 100644 index 0000000000..89e816d023 --- /dev/null +++ b/.kilo/plans/jetbrains-mdview-vscode-styling.md @@ -0,0 +1,69 @@ +# JetBrains MdView VS Code Styling Plan + +## Goal + +Improve JetBrains markdown output so assistant/user transcript markdown visually matches the VS Code webview markdown style while keeping the existing Swing/JBHtmlPane + editor-backed code block architecture. + +## Findings + +- VS Code markdown styling is split across `packages/ui/src/components/markdown.css`, `packages/kilo-ui/src/components/markdown.css`, `packages/kilo-ui/src/styles/vscode-bridge.css`, and message-part overrides. +- Base VS Code markdown uses 14px sans text, 160% line height, tight first/last margins, same-size medium headings, 12px paragraph spacing, link-colored anchors, compact lists, weak list markers, weak blockquotes with a 2px left border, invisible HR spacing, bordered/padded code blocks, green inline code, and lightly bordered tables. +- The VS Code theme bridge maps markdown roles to editor/theme tokens: heading/link/list/image use `textLinkForeground`, text/strong/code-block use editor foreground, inline code uses charts/syntax green, quote/emphasis use description foreground, HR uses panel border. +- JetBrains markdown is rendered by `MdViewHybrid` and `MdViewHtmlPane`, with shared CSS from `MdCommon.rules()` and defaults from `MdCommon.defaults()`. +- JetBrains currently styles only broad tag font/color, links, code/pre colors, blockquote border/text color, and table border. It lacks VS Code-equivalent spacing, heading/strong/emphasis/list marker/table cell rules, inline-code foreground, blockquote geometry, HR spacing, and code block surface polish. +- JetBrains fenced code blocks are already stronger than VS Code in one respect: they use `EditorTextField` with real IDE syntax highlighting and streaming retention. Preserve this instead of switching to web/JCEF rendering. + +## Implementation Plan + +1. Expand JetBrains markdown style tokens. + - Add internal fields to `MdStyle` for heading, strong, emphasis, inline code foreground, list marker, HR, table/header, and code block border colors. + - Keep the public `MdView` override API stable unless a new external override is clearly needed. + - Compute defaults in `MdCommon.defaults(style)` from IntelliJ/editor theme sources and centralized Kilo semantic colors where no platform key matches. + - Use `JBColor.namedColor("Kilo.Markdown.*", fallback)` for Kilo-specific markdown palette fallbacks, so themes can override them and runtime code avoids scattered hardcoded colors. + +2. Mirror VS Code markdown CSS in `MdCommon.rules()`. + - Add root/body wrapping rules: max width behavior, break-word wrapping, base line-height, and first/last-child margin trimming where supported by `JBHtmlPane` CSS. + - Add heading rules: same base size, medium/bold weight, role-specific color, line height, and bottom spacing. + - Add paragraph, list, list item, nested list, and marker rules. If Swing HTML does not support `::marker`, fall back to `li { color: ... }` plus child text color reset only if supported; otherwise keep list text normal and document the limitation in tests. + - Add strong/emphasis colors matching VS Code token roles. + - Add anchor styling matching VS Code: themed link color, no forced background, and underline behavior where `JBHtmlPane` supports it. + - Add blockquote geometry: 2px left border, 24px vertical margin, 8px left padding, weak text, and normal style. + - Add table layout rules: collapse borders, full width where possible, 24px vertical margin, 12px cell padding, weak row borders, stronger header text. + - Keep HRs visually hidden but spaced consistently with VS Code if the renderer includes them. `MdViewHybrid` currently filters thematic breaks, so this mainly benefits `MdViewHtmlPane` and future reuse. + - Add inline-code foreground and medium font weight. Avoid inline code backgrounds unless the current `JBHtmlPane` configuration already draws them acceptably. + +3. Polish JetBrains code block containers without losing IDE highlighting. + - Keep `EditorTextField` for fenced/indented blocks and `JBTextArea` fallback. + - Style `JBScrollPane` code blocks to match VS Code’s `markdown-code` wrapper feel: subtle background, subtle border, rounded-ish platform arc if feasible, 12px-ish padding, and thin horizontal scrollbar behavior. + - Use `SessionUiStyle.View.Code` for geometry constants. Add only minimal new constants there if current values cannot represent the VS Code spacing. + - Separate code block border color from table border internally so table styling can change without affecting code boxes. + - Continue applying `SessionEditorStyle.applyToEditor(ed)` so code blocks follow IDE syntax highlighting and editor font changes. + +4. Add file/path affordance parity where safe. + - For markdown links whose `href` looks like a relative file path, keep existing link dispatch so the current caller can open files/URLs appropriately. + - Consider decorating inline code that looks like a path with a `file-link` class only when an `openFile` callback is available through the existing usage path. If the current `MdView` abstraction only has `openUrl`, do not widen it unless the call sites can pass file opening cleanly. + - At minimum, make inline code/path-looking content visually closer to VS Code by using the inline-code foreground and dotted underline for explicit file links where generated HTML contains link/code classes. + +5. Preserve retained Swing behavior. + - Keep `MdViewHybrid.sync()` prefix reuse logic unchanged unless necessary. + - Ensure style updates call `reloadCssStylesheets()` and reassign text only for retained `JBHtmlPane` blocks, not by rebuilding all blocks. + - Keep streaming fenced-code fast path and editor disposal behavior intact. + +6. Add focused tests. + - Extend `MdViewTest` and/or `MdViewHybridTest` to assert `overrideSheet()` contains the new VS Code-equivalent rules for headings, strong/emphasis, links, inline code foreground, list/table/blockquote spacing, HR, and code block/table border separation. + - Add component tests for code block pane styling: background, viewport background, border color, padding, scrollbar policy, and retained editor instance after `applyStyle()`. + - Keep existing stress/leak tests green. Add a small stress assertion only if the implementation changes style application semantics. + - Add a changeset: `@kilocode/kilo-jetbrains` patch with user-facing wording such as `Improve markdown readability in JetBrains chat transcripts.` + +## Verification + +- Run targeted JetBrains markdown tests first from `packages/kilo-jetbrains/`: `./gradlew frontend:test --tests '*MdView*'` if the Gradle module supports it; otherwise run the closest supported targeted Gradle test command. +- Run `bun run typecheck` from `packages/kilo-jetbrains/`. +- If targeted Gradle filtering is unreliable, run `./gradlew test` from `packages/kilo-jetbrains/`. + +## Constraints + +- Do not introduce JCEF, Compose, or Kotlin UI DSL. +- Keep changes inside `packages/kilo-jetbrains/` and `.changeset/` unless a shared Kilo UI source of truth is explicitly required. +- No `kilocode_change` markers are needed for JetBrains or Kilo UI paths. +- Prefer IntelliJ theme APIs and centralized semantic tokens over scattered literal colors. diff --git a/.kilo/plans/jetbrains-session-ui-icons-header.md b/.kilo/plans/jetbrains-session-ui-icons-header.md new file mode 100644 index 0000000000..7ed4ae5250 --- /dev/null +++ b/.kilo/plans/jetbrains-session-ui-icons-header.md @@ -0,0 +1,63 @@ +# JetBrains Session UI Icons And Header Layout Plan + +## Goal +Improve JetBrains session UI icon consistency and reduce accidental header interactions: +- Use Kilo/VS Code-aligned session icons in session views. +- Fix the reasoning header icon. +- Normalize session part collapse/expand chevrons so collapsed/expanded states do not jump between differently sized glyphs. +- Move the session-details toggle away from compaction and place it before the session title. + +## Findings +- Session view icons are centralized in `packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/session/views/SessionViewIcons.kt` and loaded from `frontend/src/main/resources/icons/views/*.svg`. +- The JetBrains `views` SVGs already mirror the shared VS Code/UI icon paths from `packages/ui/src/components/icon.tsx` for the audited names, including `brain`, `chevron-down`, `chevron-right`, `checklist`, `console`, `warning`, etc. +- The reasoning view currently renders `SessionViewIcons.eye` in `ReasoningView.kt`; VS Code/shared UI uses the `brain` icon for reasoning/thinking surfaces, and `SessionViewIcons.brain` already exists. +- Standard collapsible session parts use `SessionViewIcons.chevronDown` when expanded and `SessionViewIcons.chevronRight` when collapsed in `AbstractSessionPartView.kt`; `QuestionResultView.kt` repeats this pattern manually. The down/right SVG paths have different visual extents. +- The session header currently places the details toggle next to the compact button in the right-side controls in `SessionHeaderPanel.kt`, making the two actions easy to confuse. + +## Implementation Steps +1. **Keep icon sources aligned with VS Code/shared UI** + - Treat `packages/ui/src/components/icon.tsx` as the source for Kilo web/session glyph shapes. + - Re-check `SessionViewIcons.kt` entries against available JetBrains assets; only update or add SVGs if a session view uses a Kilo icon missing from `frontend/src/main/resources/icons/views/`. + - Preserve JetBrains SVG theming rules: no `currentColor`; use literal palette colors and dark variants where assets are added or changed. + +2. **Fix reasoning icon** + - In `ReasoningView.kt`, change the reasoning header glyph from `SessionViewIcons.eye` to `SessionViewIcons.brain`. + - Add or update test coverage in `ReasoningViewTest.kt` by inspecting the rendered Swing label tree and asserting the reasoning icon is `SessionViewIcons.brain`. + +3. **Normalize collapse/expand chevrons for session parts** + - Stop using the mixed `chevronRight`/`chevronDown` pair for collapsible session content. + - Use a single base Kilo chevron glyph for both states, matching the current custom chevron used by the session header (`/icons/chevron-down.svg` / equivalent `SessionViewIcons.chevronDown`). + - Add a shared rotated icon for the opposite state instead of switching to a differently sized right-facing asset. Prefer a small reusable helper or centralized icon field rather than importing header-specific UI into session views. + - Update `AbstractSessionPartView.kt` and `QuestionResultView.kt` to use the normalized chevron pair. + - Leave `QuestionView.kt` navigation chevrons alone unless auditing shows they are being used for collapse/expand; those are previous/next controls, not expand/collapse controls. + +4. **Relocate and change header show/hide details toggle** + - In `SessionHeaderPanel.kt`, replace the custom header details chevron with platform `AllIcons` arrows/chevrons, e.g. collapsed = `AllIcons.General.ArrowRight`, expanded = `AllIcons.General.ArrowDown`. + - Move the details toggle out of the right-side controls and into `BorderLayout.WEST` of the header row. + - Rebuild the top header as: + - outer border layout + - west: details toggle button + - center: inner border layout + - inner center: session title + - inner east: horizontal stack/row with price/context and compact button + - Remove the details toggle from the right-side row so compaction remains visually separate from show/hide details. + - Keep existing tooltip/accessibility strings and expansion persistence behavior unchanged. + +5. **Tests** + - Update `SessionHeaderPanelTest.kt` to assert: + - collapsed/expanded header details icons use the selected `AllIcons` constants; + - the details toggle persists expansion state as before; + - the details toggle is parented/laid out separately from the compact button. + - Update `AbstractSessionPartViewTest.kt` to assert collapsible parts keep the same icon dimensions across collapsed/expanded states and no longer use the mismatched right/down pair. + - Update `QuestionResultViewTest.kt` similarly because it has its own chevron implementation. + - Update `ReasoningViewTest.kt` for the brain icon. + +6. **Verification** + - Run the smallest relevant JetBrains checks from `packages/kilo-jetbrains/`: + - `./gradlew test --tests "ai.kilocode.client.session.views.ReasoningViewTest" --tests "ai.kilocode.client.session.views.base.AbstractSessionPartViewTest" --tests "ai.kilocode.client.session.views.QuestionResultViewTest" --tests "ai.kilocode.client.session.ui.header.SessionHeaderPanelTest"` + - `./gradlew typecheck` + - If the filtered Gradle test syntax is not accepted by the project, run `./gradlew test` from `packages/kilo-jetbrains/` instead. + +## Notes +- No shared upstream `opencode` files are involved; changes stay under `packages/kilo-jetbrains/`. +- A changeset may be needed because this is user-facing JetBrains UI polish; confirm existing changeset policy for the private JetBrains package during implementation. diff --git a/bun.lock b/bun.lock index 128179d2e1..f048a50cb8 100644 --- a/bun.lock +++ b/bun.lock @@ -291,6 +291,7 @@ "@kilocode/kilo-i18n": "workspace:*", "@kilocode/kilo-indexing": "workspace:*", "@kilocode/kilo-ui": "workspace:*", + "@kilocode/plugin": "workspace:*", "@kilocode/sdk": "workspace:*", "@opencode-ai/ui": "workspace:*", "@pierre/diffs": "catalog:", diff --git a/flake.nix b/flake.nix index 56438ab332..7383da725d 100644 --- a/flake.nix +++ b/flake.nix @@ -76,8 +76,11 @@ }; kilo-dev = pkgs.writeShellScriptBin "kilo-dev" '' - cd "$KILO_ROOT" - exec ${bun}/bin/bun dev "$@" + set -euo pipefail + + : "''${KILO_ROOT:?KILO_ROOT is not set. Enter the flake dev shell from the repo root.}" + export KILO_DEV_CWD="$PWD" + exec ${bun}/bin/bun --cwd "$KILO_ROOT/packages/opencode" --conditions=browser ./src/index.ts "$@" ''; kilo-install-bin = pkgs.writeShellScriptBin "kilo-install" '' diff --git a/nix/hashes.json b/nix/hashes.json index 022fc3658c..d484352aa8 100644 --- a/nix/hashes.json +++ b/nix/hashes.json @@ -1,8 +1,8 @@ { "nodeModules": { - "x86_64-linux": "sha256-eDZ7bR8/xjtQj8Y+X02h/D7afn2TGC3xOTnDmwFKkwo=", - "aarch64-linux": "sha256-CvsqQ8uSoZmc/9ClO4I/Wwb2NIQqynt57n/G0P9mFPY=", - "aarch64-darwin": "sha256-mIC3G1zON6WmKyZT5YaYGc0Wh6v/tQ+aJaZcU7/nyzE=", - "x86_64-darwin": "sha256-U6A3ZPFUVUDdgwxCJXX5X0HzR6DiLzIoHViDoQDiMMY=" + "x86_64-linux": "sha256-jvRriUZ4wVKCs5Lek4b+Ln98WJe3QUZ9xzLX7E6XUG4=", + "aarch64-linux": "sha256-tcr6VJXR0H0iCS4LaRPb8tjapNIt8+WVn1jyWWiwUdg=", + "aarch64-darwin": "sha256-Rwg8EbHvxNo1mDr2RqPUDAX7QR//pFcnmgXfDbIx4oY=", + "x86_64-darwin": "sha256-Wsu1lxKb/gzdi7i0iwok9Uejk9QLEn/K3jaqURjsyT0=" } } diff --git a/packages/kilo-console/src/client.ts b/packages/kilo-console/src/client.ts index adca1648a7..37b3822b2f 100644 --- a/packages/kilo-console/src/client.ts +++ b/packages/kilo-console/src/client.ts @@ -29,6 +29,7 @@ import type { VcsInfo, Worktree, WorktreeDiffItem, + WorktreeListResponse, } from "@kilocode/sdk/v2/client" export type Scope = "global" | "project" @@ -54,7 +55,7 @@ export type ProjectConsoleSnapshot = { project: ProjectItem config: EffectiveConfig vcs: VcsInfo - worktrees: string[] + worktrees: WorktreeListResponse terminals: ProjectTerminalItem[] } @@ -447,7 +448,7 @@ export async function loadProjectConsole(input: ProjectConsoleQuery): Promise loadProjectTerminals({ url: input.url, dir }, dir)), + [query.dir, ...dirs.map((item) => item.directory)].map((dir) => loadProjectTerminals({ url: input.url, dir }, dir)), ) return { diff --git a/packages/kilo-console/src/routes/projects/ProjectConsoleRoute.tsx b/packages/kilo-console/src/routes/projects/ProjectConsoleRoute.tsx index f4ad90840d..b4d9e09955 100644 --- a/packages/kilo-console/src/routes/projects/ProjectConsoleRoute.tsx +++ b/packages/kilo-console/src/routes/projects/ProjectConsoleRoute.tsx @@ -58,6 +58,7 @@ type Context = { dir: string label: string kind: "local" | "worktree" + managed: boolean } type Editor = { kind: "create"; value: string } | { kind: "rename"; item: Context; value: string } @@ -135,6 +136,7 @@ function refreshEvent(event: ProjectConsoleEvent) { if (type.startsWith("permission.")) return true if (type.startsWith("question.")) return true if (type.startsWith("message.")) return true + if (type === "global.config.updated") return true return false } @@ -179,8 +181,14 @@ export function ProjectConsoleRoute() { const data = snap() if (!data) return [] return [ - { id: "local", dir: data.project.worktree, label: "Local", kind: "local" }, - ...data.worktrees.map((dir) => ({ id: dir, dir, label: title(dir), kind: "worktree" as const })), + { id: "local", dir: data.project.worktree, label: "Local", kind: "local", managed: false }, + ...data.worktrees.map((item) => ({ + id: item.directory, + dir: item.directory, + label: title(item.directory), + kind: "worktree" as const, + managed: item.managed, + })), ] }) const terminals = createMemo(() => { @@ -499,8 +507,12 @@ export function ProjectConsoleRoute() { setEditor({ kind: "rename", item, value: displayLabel(item) }) } + function canManage(item: Context | undefined) { + return item?.kind === "worktree" && item.managed + } + function removeWorktree(item: Context) { - if (!projectInput() || item.kind === "local") return + if (!projectInput() || !canManage(item)) return setPending({ kind: "delete", item }) } @@ -512,7 +524,7 @@ export function ProjectConsoleRoute() { function resetSelected() { const item = current() - if (!projectInput() || !item || item.kind === "local") return + if (!projectInput() || !canManage(item)) return setPending({ kind: "reset", item }) } @@ -653,11 +665,14 @@ export function ProjectConsoleRoute() { const base = query() const data = snap() if (!base || !data) return - const dirs = new Set([data.project.worktree, ...data.worktrees]) + const dirs = new Set([data.project.worktree, ...data.worktrees.map((item) => item.directory)]) const stop = subscribeProjectEvents({ url: base.url, dir: data.project.worktree }, (event) => { if (event.directory !== "global" && !dirs.has(event.directory)) return const id = eventSession(event) if (id && messageEvent(event)) markUnread(id) + // Terminal fitting emits pty.updated for every width change. Ignore those refreshes while + // dragging so the controlled review accordion keeps its expanded files mounted. + if (resize.pending && eventType(event) === "pty.updated") return if (refreshEvent(event)) scheduleRefetch() }) onCleanup(stop) @@ -765,19 +780,21 @@ export function ProjectConsoleRoute() { > - + + + @@ -913,7 +930,7 @@ export function ProjectConsoleRoute() { {current()?.dir ?? snap()?.project.worktree ?? project()} - +
) @@ -2518,7 +2525,7 @@ const AgentManagerContent: Component = () => { ) })()} - @@ -2607,7 +2614,11 @@ const AgentManagerContent: Component = () => { {t("agentManager.session.openInWorktree")} - openLocally(s.id)}> + + openLocally(s.id), + )} + > {t("agentManager.session.openLocally")} @@ -2711,8 +2722,8 @@ const AgentManagerContent: Component = () => { newTerminalLabel: t("agentManager.terminal.new"), newSessionMenuLabel: t("agentManager.session.newSession"), moreOptionsLabel: t("agentManager.tab.newOptions"), - onNewSession: handleAddSession, - onNewTerminal: () => termHandlers.requestNew(), + onNewSession: metrics.click("new_session", "tab_bar", handleAddSession), + onNewTerminal: metrics.click("embedded_terminal", "new_tab_menu", () => termHandlers.requestNew()), })} @@ -2738,7 +2749,7 @@ const AgentManagerContent: Component = () => { <> - @@ -2774,7 +2785,14 @@ const AgentManagerContent: Component = () => { variant="ghost" icon={active() ? "stop" : "play"} disabled={rs()?.state === "stopping"} - onClick={() => runWorktree(rid())} + onClick={metrics.click( + "run_script", + "tab_toolbar", + () => runWorktree(rid()), + () => ({ + action: active() ? "stop" : configured() ? "run" : "configure", + }), + )} > {active() ? "Stop" : "Run"} @@ -2794,7 +2812,9 @@ const AgentManagerContent: Component = () => { /> - + {t("agentManager.run.configure")} @@ -2813,6 +2833,9 @@ const AgentManagerContent: Component = () => { diff --git a/packages/kilo-vscode/webview-ui/agent-manager/NewWorktreeDialog.tsx b/packages/kilo-vscode/webview-ui/agent-manager/NewWorktreeDialog.tsx index 4d79b0cf04..0685e6b72b 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/NewWorktreeDialog.tsx +++ b/packages/kilo-vscode/webview-ui/agent-manager/NewWorktreeDialog.tsx @@ -34,6 +34,7 @@ import { useSpeechToText } from "../src/components/speech-to-text/useSpeechToTex import { convertToMentionPath } from "../src/utils/path-mentions" import { insertSpacedText } from "../src/components/chat/prompt-input-utils" import { BranchSelect, BranchSelectPopover } from "../src/components/shared/BranchSelect" +import { tracker } from "./telemetry" type VersionCount = 1 | 2 | 3 | 4 const VERSION_OPTIONS: VersionCount[] = [1, 2, 3, 4] @@ -71,6 +72,10 @@ export const NewWorktreeDialog: Component<{ onClose: () => void; defaultBaseBran const session = useSession() const provider = useProvider() const { config } = useConfig() + const metrics = tracker(vscode) + const track = (button: string, properties?: Record) => + metrics.track(button, "configure_worktree_dialog", properties) + const click = metrics.click const [tab, setTab] = createSignal("new") @@ -209,6 +214,8 @@ export const NewWorktreeDialog: Component<{ onClose: () => void; defaultBaseBran if (compareMode() && totalAllocations(modelAllocations()) === 0) return false return true } + const total = () => (compareMode() ? totalAllocations(modelAllocations()) : versions()) + const mode = () => (compareMode() ? "compare_models" : versions() > 1 ? "multiple_versions" : "single") const handleSubmit = () => { if (!canSubmit()) return @@ -224,7 +231,7 @@ export const NewWorktreeDialog: Component<{ onClose: () => void; defaultBaseBran const isCompare = compareMode() const allocations = isCompare ? allocationsToArray(modelAllocations()) : undefined - const count = isCompare ? totalAllocations(modelAllocations()) : versions() + const count = total() const sel = isCompare ? null : model() vscode.postMessage({ @@ -320,6 +327,7 @@ export const NewWorktreeDialog: Component<{ onClose: () => void; defaultBaseBran const handleBranchSelect = (name: string) => { if (isPending()) return + track("import_branch") setImportPending(true) setBranchOpen(false) setBranchSearch("") @@ -333,7 +341,7 @@ export const NewWorktreeDialog: Component<{ onClose: () => void; defaultBaseBran @@ -584,7 +601,9 @@ export const NewWorktreeDialog: Component<{ onClose: () => void; defaultBaseBran @@ -622,6 +647,7 @@ export const NewWorktreeDialog: Component<{ onClose: () => void; defaultBaseBran diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/CustomProviderDialog.tsx b/packages/kilo-vscode/webview-ui/src/components/settings/CustomProviderDialog.tsx index 9b24cacf22..c314e52269 100644 --- a/packages/kilo-vscode/webview-ui/src/components/settings/CustomProviderDialog.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/settings/CustomProviderDialog.tsx @@ -3,6 +3,7 @@ import { useDialog } from "@kilocode/kilo-ui/context/dialog" import { Dialog } from "@kilocode/kilo-ui/dialog" import { IconButton } from "@kilocode/kilo-ui/icon-button" import { ProviderIcon } from "@kilocode/kilo-ui/provider-icon" +import { Select } from "@kilocode/kilo-ui/select" import { Spinner } from "@kilocode/kilo-ui/spinner" import { TextField } from "@kilocode/kilo-ui/text-field" import { showToast } from "@kilocode/kilo-ui/toast" @@ -12,14 +13,20 @@ import { useConfig } from "../../context/config" import { useLanguage } from "../../context/language" import { useProvider } from "../../context/provider" import { useVSCode } from "../../context/vscode" -import type { ExtensionMessage, ProviderConfig } from "../../types/messages" +import type { ExtensionMessage, ProviderAuthState, ProviderConfig } from "../../types/messages" import { createProviderAction } from "../../utils/provider-action" import { MASKED_CUSTOM_PROVIDER_KEY, resolveCustomProviderKey } from "../../../../src/shared/custom-provider" +import { + CUSTOM_PROVIDER_PACKAGE, + isCustomProviderPackage, + type CustomProviderPackage, +} from "../../../../src/shared/provider-model" import { ModelCard } from "./CustomProviderModelCard" import type { ChatTemplateArgsValue, EnableThinkingValue, ModelEntry, + OutputEffortValue, ReasoningEffortValue, ThinkingTypeValue, VariantEntry, @@ -29,6 +36,12 @@ import type { FormErrors, FormState, HeaderRow } from "./CustomProviderValidatio const DEBOUNCE_MS = 500 const SEARCH_DEBOUNCE_MS = 150 +const PACKAGE_OPTIONS: Array<{ value: CustomProviderPackage; label: string }> = [ + { value: "@ai-sdk/openai-compatible", label: "OpenAI Compatible" }, + { value: "@ai-sdk/openai", label: "OpenAI Responses" }, + { value: "@ai-sdk/anthropic", label: "Anthropic Messages" }, +] + /** Subsequence fuzzy match — "gpt4o" matches "gpt-4o-mini". */ function fuzzy(query: string, target: string) { const q = query.toLowerCase() @@ -41,15 +54,80 @@ function fuzzy(query: string, target: string) { } type FetchedModel = { id: string; name: string } +type RawModel = { name?: string; reasoning?: boolean; variants?: Record> } + +function parseVariant([name, cfg]: [string, Record]): VariantEntry { + return { + name, + enableThinking: typeof cfg.enable_thinking === "boolean" ? cfg.enable_thinking : undefined, + thinking: + typeof cfg.thinking === "object" && cfg.thinking !== null + ? ((cfg.thinking as { type?: string }).type as ThinkingTypeValue) + : undefined, + splitReasoning: typeof cfg.reasoning_split === "boolean" ? cfg.reasoning_split : undefined, + reasoningEffort: + typeof cfg.reasoningEffort === "string" ? (cfg.reasoningEffort as ReasoningEffortValue) : undefined, + outputEffort: typeof cfg.effort === "string" ? (cfg.effort as OutputEffortValue) : undefined, + chatTemplateArgs: + typeof cfg.chat_template_args === "object" && cfg.chat_template_args !== null + ? ((cfg.chat_template_args as { enable_thinking?: boolean }).enable_thinking as ChatTemplateArgsValue) + : undefined, + } +} + +function initModels(cfg: ProviderConfig | undefined): ModelEntry[] { + if (!cfg?.models || typeof cfg.models !== "object") return [{ id: "", name: "", reasoning: false, variants: [] }] + const entries = Object.entries(cfg.models) + if (entries.length === 0) return [{ id: "", name: "", reasoning: false, variants: [] }] + return entries.map(([id, model]) => { + const raw = model as RawModel + return { + id, + name: raw.name ?? id, + reasoning: raw.reasoning ?? false, + variants: Object.entries(raw.variants ?? {}).map(parseVariant), + } + }) +} + +function initHeaders(cfg: ProviderConfig | undefined): HeaderRow[] { + const opts = cfg?.options as { headers?: Record } | undefined + const headers = opts?.headers + if (!headers || typeof headers !== "object") return [{ key: "", value: "" }] + const entries = Object.entries(headers) + if (entries.length === 0) return [{ key: "", value: "" }] + return entries.map(([key, value]) => ({ key, value })) +} + +type ExistingProvider = { + providerID: string + name: string + config: ProviderConfig +} + +function resolveAuth(existing: ExistingProvider | undefined, states: Record) { + if (!existing || existing.config.env?.length) return + return states[existing.providerID] +} + +function initForm(existing: ExistingProvider | undefined, auth: ProviderAuthState | undefined): FormState { + const npm = existing?.config?.npm + return { + providerID: existing?.providerID ?? "", + name: existing?.name ?? "", + npm: isCustomProviderPackage(npm) ? npm : CUSTOM_PROVIDER_PACKAGE, + baseURL: (existing?.config?.options as { baseURL?: string } | undefined)?.baseURL ?? "", + apiKey: resolveCustomProviderKey(auth), + models: initModels(existing?.config), + headers: initHeaders(existing?.config), + saving: false, + } +} export interface CustomProviderDialogProps { onBack?: () => void /** When set, the dialog opens in edit mode with pre-filled values. */ - existing?: { - providerID: string - name: string - config: ProviderConfig - } + existing?: ExistingProvider } const CustomProviderDialog = (props: CustomProviderDialogProps) => { @@ -63,60 +141,8 @@ const CustomProviderDialog = (props: CustomProviderDialogProps) => { const editing = () => !!props.existing - function initModels(): ModelEntry[] { - const cfg = props.existing?.config - if (!cfg?.models || typeof cfg.models !== "object") return [{ id: "", name: "", reasoning: false, variants: [] }] - const entries = Object.entries(cfg.models) - if (entries.length === 0) return [{ id: "", name: "", reasoning: false, variants: [] }] - return entries.map(([id, m]) => { - const raw = m as { name?: string; reasoning?: boolean; variants?: Record> } - const variants: VariantEntry[] = Object.entries(raw?.variants ?? {}).map(([vname, vcfg]) => ({ - name: vname, - enableThinking: typeof vcfg.enable_thinking === "boolean" ? (vcfg.enable_thinking as boolean) : undefined, - thinking: - typeof vcfg.thinking === "object" && vcfg.thinking !== null - ? ((vcfg.thinking as { type?: string }).type as ThinkingTypeValue) - : undefined, - reasoningEffort: - typeof vcfg.reasoningEffort === "string" ? (vcfg.reasoningEffort as ReasoningEffortValue) : undefined, - chatTemplateArgs: - typeof vcfg.chat_template_args === "object" && vcfg.chat_template_args !== null - ? ((vcfg.chat_template_args as { enable_thinking?: boolean }).enable_thinking as ChatTemplateArgsValue) - : undefined, - })) - return { - id, - name: raw?.name ?? id, - reasoning: raw?.reasoning ?? false, - variants, - } - }) - } - - function initHeaders(): HeaderRow[] { - const opts = props.existing?.config?.options as { headers?: Record } | undefined - const headers = opts?.headers - if (!headers || typeof headers !== "object") return [{ key: "", value: "" }] - const entries = Object.entries(headers) - if (entries.length === 0) return [{ key: "", value: "" }] - return entries.map(([key, value]) => ({ key, value })) - } - - const auth = props.existing?.config?.env?.length - ? undefined - : props.existing - ? provider.authStates()[props.existing.providerID] - : undefined - - const [form, setForm] = createStore({ - providerID: props.existing?.providerID ?? "", - name: props.existing?.name ?? "", - baseURL: (props.existing?.config?.options as { baseURL?: string } | undefined)?.baseURL ?? "", - apiKey: resolveCustomProviderKey(auth), - models: initModels(), - headers: initHeaders(), - saving: false, - }) + const auth = resolveAuth(props.existing, provider.authStates()) + const [form, setForm] = createStore(initForm(props.existing, auth)) const [errors, setErrors] = createStore({ providerID: undefined, @@ -160,11 +186,13 @@ const CustomProviderDialog = (props: CustomProviderDialogProps) => { // SolidJS store proxies track at the property level — any store write // (including setForm("models", ...)) invalidates effects that read from // the same store, causing unwanted re-runs that wipe the model picker. + const [fetchPackage, setFetchPackage] = createSignal(form.npm) const [fetchURL, setFetchURL] = createSignal(form.baseURL) const [fetchKey, setFetchKey] = createSignal("") let fetchVersion = 0 createEffect(() => { + const npm = fetchPackage() const url = fetchURL() const key = fetchKey() void key // subscribe to key changes without using the value here @@ -175,7 +203,7 @@ const CustomProviderDialog = (props: CustomProviderDialogProps) => { setFetchStatus(undefined) setSearch("") - if (!/^https?:\/\//.test(url.trim())) return + if (npm === "@ai-sdk/anthropic" || !/^https?:\/\//.test(url.trim())) return fetchVersion++ const version = fetchVersion @@ -354,7 +382,9 @@ const CustomProviderDialog = (props: CustomProviderDialogProps) => { name: "", enableThinking: undefined, thinking: undefined, + splitReasoning: undefined, reasoningEffort: undefined, + outputEffort: undefined, chatTemplateArgs: undefined, } setForm("models", mi, "variants", (v) => [...v, blank]) @@ -490,6 +520,30 @@ const CustomProviderDialog = (props: CustomProviderDialogProps) => { validationState={errors.name ? "invalid" : undefined} error={errors.name} /> +
+ + o.value === props.v.splitReasoning)} + value={(o) => String(o.value)} + label={(o) => props.t(o.labelKey)} + onSelect={(o) => props.onChangeSplitReasoning(o?.value)} + placeholder={props.t("provider.custom.models.variants.splitReasoning.placeholder")} + variant="secondary" + size="small" + triggerVariant="settings" + /> +
+
+ + o.value === agentSound())} - value={(o) => o.value} - label={(o) => language.t(o.labelKey)} - onSelect={(o) => { - if (o) { - setAgentSound(o.value) - save("sounds.agent", o.value) - } + current={SOUND_OPTIONS.find((option) => option.value === sound())} + value={(option) => option.value} + label={(option) => language.t(option.labelKey)} + onSelect={(option) => { + if (!option) return + setSound(option.value) + vscode.postMessage({ type: "updateSetting", key: "attention.sound", value: option.value }) }} + disabled={!enabled()} variant="secondary" size="small" triggerVariant="settings" /> - - - o.value === errorSound())} - value={(o) => o.value} - label={(o) => language.t(o.labelKey)} - onSelect={(o) => { - if (o) { - setErrorSound(o.value) - save("sounds.errors", o.value) - } - }} - variant="secondary" - size="small" - triggerVariant="settings" - /> - - -
+ disabled={!enabled()} + onClick={() => vscode.postMessage({ type: "testNotification", sound: sound() })} + > + {language.t("settings.notifications.testSound")} + + + + ) } diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/ProvidersTab.tsx b/packages/kilo-vscode/webview-ui/src/components/settings/ProvidersTab.tsx index f8b1431160..c3efad5252 100644 --- a/packages/kilo-vscode/webview-ui/src/components/settings/ProvidersTab.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/settings/ProvidersTab.tsx @@ -17,7 +17,7 @@ import ProviderConnectDialog from "./ProviderConnectDialog" import ProviderSelectDialog from "./ProviderSelectDialog" import { CUSTOM_PROVIDER_ID, isPopularProvider, providerIcon, providerNoteKey, sortProviders } from "./provider-catalog" import { disabledProviderOptions, providersWithKiloFallback, visibleConnectedIds } from "./provider-visibility" -import { KILO_PROVIDER_ID, CUSTOM_PROVIDER_PACKAGE } from "../../../../src/shared/provider-model" +import { isCustomProviderPackage, KILO_PROVIDER_ID } from "../../../../src/shared/provider-model" import { createProviderAction } from "../../utils/provider-action" type ProviderSource = "env" | "api" | "config" | "custom" @@ -79,7 +79,7 @@ const ProvidersTab: Component = () => { if (current === "api") return language.t("provider.connect.method.apiKey") if (current === "config") { const cfg = config().provider?.[item.id] - if (cfg?.npm === "@ai-sdk/openai-compatible") return language.t("settings.providers.tag.custom") + if (isCustomProviderPackage(cfg?.npm)) return language.t("settings.providers.tag.custom") return language.t("settings.providers.tag.config") } if (item.id === "openai" && current === "custom") return language.t("settings.providers.tag.chatgpt") @@ -93,7 +93,7 @@ const ProvidersTab: Component = () => { function isCustom(item: Provider) { const cfg = config().provider?.[item.id] - return cfg?.npm === CUSTOM_PROVIDER_PACKAGE + return isCustomProviderPackage(cfg?.npm) } function editProvider(item: Provider) { diff --git a/packages/kilo-vscode/webview-ui/src/components/shared/WorkingIndicator.tsx b/packages/kilo-vscode/webview-ui/src/components/shared/WorkingIndicator.tsx index a46c9a0b1d..efddf2e2bc 100644 --- a/packages/kilo-vscode/webview-ui/src/components/shared/WorkingIndicator.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/shared/WorkingIndicator.tsx @@ -10,6 +10,7 @@ import { Button } from "@kilocode/kilo-ui/button" import { useSession } from "../../context/session" import { useLanguage } from "../../context/language" import { useVSCode } from "../../context/vscode" +import { tracksElapsed } from "./working-indicator-utils" export const WorkingIndicator: Component = () => { const session = useSession() @@ -23,7 +24,7 @@ export const WorkingIndicator: Component = () => { const since = session.busySince() const status = session.status() - if (status === "idle" || !since) { + if (!tracksElapsed(status, session.submitting(), since)) { setElapsed(0) return } diff --git a/packages/kilo-vscode/webview-ui/src/components/shared/working-indicator-utils.ts b/packages/kilo-vscode/webview-ui/src/components/shared/working-indicator-utils.ts new file mode 100644 index 0000000000..7b66e886bc --- /dev/null +++ b/packages/kilo-vscode/webview-ui/src/components/shared/working-indicator-utils.ts @@ -0,0 +1,5 @@ +import type { SessionStatus } from "../../types/messages" + +export function tracksElapsed(status: SessionStatus, submitting: boolean, since: number | undefined): since is number { + return since !== undefined && (status !== "idle" || submitting) +} diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts index cc7804d3d3..368f62f0ef 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts @@ -840,6 +840,7 @@ export const dict = { "provider.custom.field.providerID.description": "أحرف صغيرة وأرقام وواصلات أو شرطات سفلية", "provider.custom.field.name.label": "الاسم المعروض", "provider.custom.field.name.placeholder": "مزود الذكاء الاصطناعي", + "provider.custom.field.package.label": "Provider API", "provider.custom.field.baseURL.label": "عنوان URL الأساسي", "provider.custom.field.baseURL.placeholder": "https://api.myprovider.com/v1", "provider.custom.field.apiKey.label": "مفتاح API", @@ -865,6 +866,11 @@ export const dict = { "provider.custom.models.variants.thinking.placeholder": "thinking", "provider.custom.models.variants.thinking.enabled": "enabled", "provider.custom.models.variants.thinking.disabled": "disabled", + "provider.custom.models.variants.thinking.adaptive": "adaptive", + "provider.custom.models.variants.splitReasoning.label": "Split reasoning (required for e.g. MiniMax)", + "provider.custom.models.variants.splitReasoning.placeholder": "reasoning_split", + "provider.custom.models.variants.splitReasoning.true": "true", + "provider.custom.models.variants.splitReasoning.false": "false", "provider.custom.models.variants.chatTemplateArgs.label": "تفعيل التفكير عبر وسائط قالب الدردشة (مثل Hugging Face)", "provider.custom.models.variants.chatTemplateArgs.placeholder": "chat_template_args", "provider.custom.models.variants.chatTemplateArgs.true": "true", @@ -877,6 +883,13 @@ export const dict = { "provider.custom.models.variants.reasoningEffort.medium": "medium", "provider.custom.models.variants.reasoningEffort.high": "high", "provider.custom.models.variants.reasoningEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.label": "Output effort (e.g. Anthropic)", + "provider.custom.models.variants.outputEffort.placeholder": "effort", + "provider.custom.models.variants.outputEffort.low": "low", + "provider.custom.models.variants.outputEffort.medium": "medium", + "provider.custom.models.variants.outputEffort.high": "high", + "provider.custom.models.variants.outputEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.max": "max", "provider.custom.models.remove": "إزالة النموذج", "provider.custom.models.add": "إضافة نموذج", "provider.custom.models.fetch": "جلب النماذج", @@ -1255,6 +1268,9 @@ export const dict = { "settings.notifications.errors.title": "أخطاء", "settings.notifications.errors.description": "إظهار إشعار عند الأخطاء", "settings.notifications.sounds": "أصوات", + "settings.notifications.enable.title": "تمكين الإشعارات الصوتية", + "settings.notifications.enable.description": "تشغيل أصوات عند اكتمال الجلسات أو حدوث خطأ أو الحاجة إلى ردّك", + "settings.notifications.testSound": "اختبار", "settings.notifications.agentSound.title": "صوت إكمال الوكيل", "settings.notifications.agentSound.description": "الصوت عند إكمال الوكيل", "settings.notifications.permSound.title": "صوت طلب الأذونات", @@ -1262,6 +1278,9 @@ export const dict = { "settings.notifications.errorSound.title": "صوت الخطأ", "settings.notifications.errorSound.description": "الصوت عند الأخطاء", "settings.notifications.sound.default": "افتراضي", + "settings.notifications.sound.system": "النظام", + "settings.notifications.sound.description": + "يستخدم الخيار الافتراضي أصواتًا مختلفة عند الاكتمال أو الحاجة إلى ردّك أو حدوث خطأ. تستخدم الخيارات الأخرى صوتًا واحدًا لجميع الأحداث.", "settings.notifications.sound.none": "بدون", "settings.experimental.share.title": "وضع المشاركة", "settings.experimental.share.description": "سلوك مشاركة الجلسة", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/br.ts b/packages/kilo-vscode/webview-ui/src/i18n/br.ts index aae8ae7793..a96a80a5dc 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/br.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/br.ts @@ -852,6 +852,7 @@ export const dict = { "provider.custom.field.providerID.description": "Letras minúsculas, números, hifens ou underscores", "provider.custom.field.name.label": "Nome de exibição", "provider.custom.field.name.placeholder": "Meu Provedor de IA", + "provider.custom.field.package.label": "Provider API", "provider.custom.field.baseURL.label": "URL base", "provider.custom.field.baseURL.placeholder": "https://api.myprovider.com/v1", "provider.custom.field.apiKey.label": "Chave de API", @@ -877,6 +878,11 @@ export const dict = { "provider.custom.models.variants.thinking.placeholder": "thinking", "provider.custom.models.variants.thinking.enabled": "enabled", "provider.custom.models.variants.thinking.disabled": "disabled", + "provider.custom.models.variants.thinking.adaptive": "adaptive", + "provider.custom.models.variants.splitReasoning.label": "Split reasoning (required for e.g. MiniMax)", + "provider.custom.models.variants.splitReasoning.placeholder": "reasoning_split", + "provider.custom.models.variants.splitReasoning.true": "true", + "provider.custom.models.variants.splitReasoning.false": "false", "provider.custom.models.variants.chatTemplateArgs.label": "Ativar pensamento via args do template de chat (ex. Hugging Face)", "provider.custom.models.variants.chatTemplateArgs.placeholder": "chat_template_args", @@ -890,6 +896,13 @@ export const dict = { "provider.custom.models.variants.reasoningEffort.medium": "medium", "provider.custom.models.variants.reasoningEffort.high": "high", "provider.custom.models.variants.reasoningEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.label": "Output effort (e.g. Anthropic)", + "provider.custom.models.variants.outputEffort.placeholder": "effort", + "provider.custom.models.variants.outputEffort.low": "low", + "provider.custom.models.variants.outputEffort.medium": "medium", + "provider.custom.models.variants.outputEffort.high": "high", + "provider.custom.models.variants.outputEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.max": "max", "provider.custom.models.remove": "Remover modelo", "provider.custom.models.add": "Adicionar modelo", "provider.custom.models.fetch": "Buscar modelos", @@ -1284,6 +1297,10 @@ export const dict = { "settings.notifications.errors.title": "Erros", "settings.notifications.errors.description": "Mostrar notificação em erros", "settings.notifications.sounds": "Sons", + "settings.notifications.enable.title": "Ativar notificações sonoras", + "settings.notifications.enable.description": + "Reproduzir sons quando as sessões forem concluídas, ocorrer um erro ou sua interação for necessária", + "settings.notifications.testSound": "Testar", "settings.notifications.agentSound.title": "Som de conclusão do agente", "settings.notifications.agentSound.description": "Som ao concluir o agente", "settings.notifications.permSound.title": "Som de solicitação de permissão", @@ -1291,6 +1308,9 @@ export const dict = { "settings.notifications.errorSound.title": "Som de erro", "settings.notifications.errorSound.description": "Som em erros", "settings.notifications.sound.default": "Padrão", + "settings.notifications.sound.system": "Sistema", + "settings.notifications.sound.description": + "A opção padrão usa sons diferentes para conclusão, interação e erros. As outras opções usam um único som para todos os eventos.", "settings.notifications.sound.none": "Nenhum", "settings.experimental.share.title": "Modo de compartilhamento", "settings.experimental.share.description": "Comportamento do compartilhamento de sessão", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts index 0cb6354780..cac7503c0b 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts @@ -893,6 +893,7 @@ export const dict = { "provider.custom.field.providerID.description": "Mala slova, brojevi, crtice ili donje crte", "provider.custom.field.name.label": "Naziv za prikaz", "provider.custom.field.name.placeholder": "Moj AI provajder", + "provider.custom.field.package.label": "Provider API", "provider.custom.field.baseURL.label": "Osnovni URL", "provider.custom.field.baseURL.placeholder": "https://api.myprovider.com/v1", "provider.custom.field.apiKey.label": "API ključ", @@ -919,6 +920,11 @@ export const dict = { "provider.custom.models.variants.thinking.placeholder": "thinking", "provider.custom.models.variants.thinking.enabled": "enabled", "provider.custom.models.variants.thinking.disabled": "disabled", + "provider.custom.models.variants.thinking.adaptive": "adaptive", + "provider.custom.models.variants.splitReasoning.label": "Split reasoning (required for e.g. MiniMax)", + "provider.custom.models.variants.splitReasoning.placeholder": "reasoning_split", + "provider.custom.models.variants.splitReasoning.true": "true", + "provider.custom.models.variants.splitReasoning.false": "false", "provider.custom.models.variants.chatTemplateArgs.label": "Omogući razmišljanje preko argumenata chat predloška (npr. Hugging Face)", "provider.custom.models.variants.chatTemplateArgs.placeholder": "chat_template_args", @@ -932,6 +938,13 @@ export const dict = { "provider.custom.models.variants.reasoningEffort.medium": "medium", "provider.custom.models.variants.reasoningEffort.high": "high", "provider.custom.models.variants.reasoningEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.label": "Output effort (e.g. Anthropic)", + "provider.custom.models.variants.outputEffort.placeholder": "effort", + "provider.custom.models.variants.outputEffort.low": "low", + "provider.custom.models.variants.outputEffort.medium": "medium", + "provider.custom.models.variants.outputEffort.high": "high", + "provider.custom.models.variants.outputEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.max": "max", "provider.custom.models.remove": "Ukloni model", "provider.custom.models.add": "Dodaj model", "provider.custom.models.fetch": "Preuzmi modele", @@ -1284,6 +1297,10 @@ export const dict = { "settings.notifications.errors.title": "Greške", "settings.notifications.errors.description": "Prikaži obavijest pri greškama", "settings.notifications.sounds": "Zvukovi", + "settings.notifications.enable.title": "Omogući zvučne obavijesti", + "settings.notifications.enable.description": + "Reproduciraj zvukove kada se sesije završe, naiđu na grešku ili trebaju vaš unos", + "settings.notifications.testSound": "Testiraj", "settings.notifications.agentSound.title": "Zvuk završetka agenta", "settings.notifications.agentSound.description": "Zvuk pri završetku agenta", "settings.notifications.permSound.title": "Zvuk zahtjeva za dozvolu", @@ -1291,6 +1308,9 @@ export const dict = { "settings.notifications.errorSound.title": "Zvuk greške", "settings.notifications.errorSound.description": "Zvuk pri greškama", "settings.notifications.sound.default": "Zadano", + "settings.notifications.sound.system": "Sistem", + "settings.notifications.sound.description": + "Zadana opcija koristi različite zvukove za završetak, unos i greške. Ostale opcije koriste jedan zvuk za sve događaje.", "settings.notifications.sound.none": "Ništa", "settings.experimental.share.title": "Način dijeljenja", "settings.experimental.share.description": "Ponašanje dijeljenja sesije", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/da.ts b/packages/kilo-vscode/webview-ui/src/i18n/da.ts index 06eb40d34f..4193a9164c 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/da.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/da.ts @@ -887,6 +887,7 @@ export const dict = { "provider.custom.field.providerID.description": "Små bogstaver, tal, bindestreger eller understregninger", "provider.custom.field.name.label": "Visningsnavn", "provider.custom.field.name.placeholder": "Min AI-udbyder", + "provider.custom.field.package.label": "Provider API", "provider.custom.field.baseURL.label": "Basis-URL", "provider.custom.field.baseURL.placeholder": "https://api.myprovider.com/v1", "provider.custom.field.apiKey.label": "API-nøgle", @@ -912,6 +913,11 @@ export const dict = { "provider.custom.models.variants.thinking.placeholder": "thinking", "provider.custom.models.variants.thinking.enabled": "enabled", "provider.custom.models.variants.thinking.disabled": "disabled", + "provider.custom.models.variants.thinking.adaptive": "adaptive", + "provider.custom.models.variants.splitReasoning.label": "Split reasoning (required for e.g. MiniMax)", + "provider.custom.models.variants.splitReasoning.placeholder": "reasoning_split", + "provider.custom.models.variants.splitReasoning.true": "true", + "provider.custom.models.variants.splitReasoning.false": "false", "provider.custom.models.variants.chatTemplateArgs.label": "Aktivér tænkning via chat-skabelonargs (f.eks. Hugging Face)", "provider.custom.models.variants.chatTemplateArgs.placeholder": "chat_template_args", @@ -925,6 +931,13 @@ export const dict = { "provider.custom.models.variants.reasoningEffort.medium": "medium", "provider.custom.models.variants.reasoningEffort.high": "high", "provider.custom.models.variants.reasoningEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.label": "Output effort (e.g. Anthropic)", + "provider.custom.models.variants.outputEffort.placeholder": "effort", + "provider.custom.models.variants.outputEffort.low": "low", + "provider.custom.models.variants.outputEffort.medium": "medium", + "provider.custom.models.variants.outputEffort.high": "high", + "provider.custom.models.variants.outputEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.max": "max", "provider.custom.models.remove": "Fjern model", "provider.custom.models.add": "Tilføj model", "provider.custom.models.fetch": "Hent modeller", @@ -1278,6 +1291,10 @@ export const dict = { "settings.notifications.errors.title": "Fejl", "settings.notifications.errors.description": "Vis notifikation ved fejl", "settings.notifications.sounds": "Lyde", + "settings.notifications.enable.title": "Aktivér lydnotifikationer", + "settings.notifications.enable.description": + "Afspil lyde, når sessioner fuldføres, der opstår en fejl, eller der er brug for input fra dig", + "settings.notifications.testSound": "Test", "settings.notifications.agentSound.title": "Agentafslutningslyd", "settings.notifications.agentSound.description": "Lyd ved agentafslutning", "settings.notifications.permSound.title": "Tilladelsesanmodningslyd", @@ -1285,6 +1302,9 @@ export const dict = { "settings.notifications.errorSound.title": "Fejllyd", "settings.notifications.errorSound.description": "Lyd ved fejl", "settings.notifications.sound.default": "Standard", + "settings.notifications.sound.system": "System", + "settings.notifications.sound.description": + "Standardindstillingen bruger forskellige lyde til afslutning, input og fejl. Andre valg bruger én lyd til alle hændelser.", "settings.notifications.sound.none": "Ingen", "settings.experimental.share.title": "Delingstilstand", "settings.experimental.share.description": "Adfærd for sessionsdeling", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/de.ts b/packages/kilo-vscode/webview-ui/src/i18n/de.ts index 57b4a20191..62d670e8ac 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/de.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/de.ts @@ -899,6 +899,7 @@ export const dict = { "provider.custom.field.providerID.description": "Kleinbuchstaben, Zahlen, Bindestriche oder Unterstriche", "provider.custom.field.name.label": "Anzeigename", "provider.custom.field.name.placeholder": "Mein KI-Anbieter", + "provider.custom.field.package.label": "Provider API", "provider.custom.field.baseURL.label": "Basis-URL", "provider.custom.field.baseURL.placeholder": "https://api.myprovider.com/v1", "provider.custom.field.apiKey.label": "API-Schlüssel", @@ -925,6 +926,11 @@ export const dict = { "provider.custom.models.variants.thinking.placeholder": "thinking", "provider.custom.models.variants.thinking.enabled": "enabled", "provider.custom.models.variants.thinking.disabled": "disabled", + "provider.custom.models.variants.thinking.adaptive": "adaptive", + "provider.custom.models.variants.splitReasoning.label": "Split reasoning (required for e.g. MiniMax)", + "provider.custom.models.variants.splitReasoning.placeholder": "reasoning_split", + "provider.custom.models.variants.splitReasoning.true": "true", + "provider.custom.models.variants.splitReasoning.false": "false", "provider.custom.models.variants.chatTemplateArgs.label": "Nachdenken über Chat-Vorlagenargumente aktivieren (z.B. Hugging Face)", "provider.custom.models.variants.chatTemplateArgs.placeholder": "chat_template_args", @@ -938,6 +944,13 @@ export const dict = { "provider.custom.models.variants.reasoningEffort.medium": "medium", "provider.custom.models.variants.reasoningEffort.high": "high", "provider.custom.models.variants.reasoningEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.label": "Output effort (e.g. Anthropic)", + "provider.custom.models.variants.outputEffort.placeholder": "effort", + "provider.custom.models.variants.outputEffort.low": "low", + "provider.custom.models.variants.outputEffort.medium": "medium", + "provider.custom.models.variants.outputEffort.high": "high", + "provider.custom.models.variants.outputEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.max": "max", "provider.custom.models.remove": "Modell entfernen", "provider.custom.models.add": "Modell hinzufügen", "provider.custom.models.fetch": "Modelle abrufen", @@ -1300,6 +1313,10 @@ export const dict = { "settings.notifications.errors.title": "Fehler", "settings.notifications.errors.description": "Benachrichtigung bei Fehlern anzeigen", "settings.notifications.sounds": "Töne", + "settings.notifications.enable.title": "Tonbenachrichtigungen aktivieren", + "settings.notifications.enable.description": + "Töne wiedergeben, wenn Sitzungen abgeschlossen werden, ein Fehler auftritt oder Ihre Eingabe erforderlich ist", + "settings.notifications.testSound": "Testen", "settings.notifications.agentSound.title": "Agent-Abschlusston", "settings.notifications.agentSound.description": "Ton bei Agent-Abschluss abspielen", "settings.notifications.permSound.title": "Berechtigungsanfrageton", @@ -1307,6 +1324,9 @@ export const dict = { "settings.notifications.errorSound.title": "Fehlerton", "settings.notifications.errorSound.description": "Ton bei Fehlern abspielen", "settings.notifications.sound.default": "Standard", + "settings.notifications.sound.system": "System", + "settings.notifications.sound.description": + "Die Standardeinstellung verwendet unterschiedliche Töne für Abschluss, Eingabe und Fehler. Bei anderen Optionen wird für alle Ereignisse derselbe Ton verwendet.", "settings.notifications.sound.none": "Kein", "settings.experimental.share.title": "Freigabemodus", "settings.experimental.share.description": "Verhalten der Sitzungsfreigabe", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/en.ts b/packages/kilo-vscode/webview-ui/src/i18n/en.ts index 6c5f544a4e..88239df5eb 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/en.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/en.ts @@ -812,6 +812,7 @@ export const dict = { "provider.custom.field.providerID.description": "Lowercase letters, numbers, hyphens, or underscores", "provider.custom.field.name.label": "Display name", "provider.custom.field.name.placeholder": "My AI Provider", + "provider.custom.field.package.label": "Provider API", "provider.custom.field.baseURL.label": "Base URL", "provider.custom.field.baseURL.placeholder": "https://api.myprovider.com/v1", "provider.custom.field.apiKey.label": "API key", @@ -837,6 +838,11 @@ export const dict = { "provider.custom.models.variants.thinking.placeholder": "thinking", "provider.custom.models.variants.thinking.enabled": "enabled", "provider.custom.models.variants.thinking.disabled": "disabled", + "provider.custom.models.variants.thinking.adaptive": "adaptive", + "provider.custom.models.variants.splitReasoning.label": "Split reasoning (required for e.g. MiniMax)", + "provider.custom.models.variants.splitReasoning.placeholder": "reasoning_split", + "provider.custom.models.variants.splitReasoning.true": "true", + "provider.custom.models.variants.splitReasoning.false": "false", "provider.custom.models.variants.chatTemplateArgs.label": "Enable thinking via chat template args (e.g. Hugging Face)", "provider.custom.models.variants.chatTemplateArgs.placeholder": "chat_template_args", @@ -850,6 +856,13 @@ export const dict = { "provider.custom.models.variants.reasoningEffort.medium": "medium", "provider.custom.models.variants.reasoningEffort.high": "high", "provider.custom.models.variants.reasoningEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.label": "Output effort (e.g. Anthropic)", + "provider.custom.models.variants.outputEffort.placeholder": "effort", + "provider.custom.models.variants.outputEffort.low": "low", + "provider.custom.models.variants.outputEffort.medium": "medium", + "provider.custom.models.variants.outputEffort.high": "high", + "provider.custom.models.variants.outputEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.max": "max", "provider.custom.models.remove": "Remove model", "provider.custom.models.add": "Add model", "provider.custom.models.fetch": "Fetch models", @@ -1260,6 +1273,10 @@ export const dict = { "settings.notifications.errors.title": "Errors", "settings.notifications.errors.description": "Show notification on errors", "settings.notifications.sounds": "Sounds", + "settings.notifications.enable.title": "Enable Sound Notifications", + "settings.notifications.enable.description": + "Play sounds when sessions complete, encounter an error, or need your input", + "settings.notifications.testSound": "Test", "settings.notifications.agentSound.title": "Agent Completion Sound", "settings.notifications.agentSound.description": "Sound to play when agent completes", "settings.notifications.permSound.title": "Permission Request Sound", @@ -1267,6 +1284,9 @@ export const dict = { "settings.notifications.errorSound.title": "Error Sound", "settings.notifications.errorSound.description": "Sound to play on errors", "settings.notifications.sound.default": "Default", + "settings.notifications.sound.system": "System", + "settings.notifications.sound.description": + "Default uses different sounds for completion, input, and errors. Other choices use one sound for every event.", "settings.notifications.sound.none": "None", "settings.experimental.share.title": "Share Mode", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/es.ts b/packages/kilo-vscode/webview-ui/src/i18n/es.ts index 960802b244..86d637dbc5 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/es.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/es.ts @@ -895,6 +895,7 @@ export const dict = { "provider.custom.field.providerID.description": "Letras minúsculas, números, guiones o guiones bajos", "provider.custom.field.name.label": "Nombre para mostrar", "provider.custom.field.name.placeholder": "Mi proveedor de IA", + "provider.custom.field.package.label": "Provider API", "provider.custom.field.baseURL.label": "URL base", "provider.custom.field.baseURL.placeholder": "https://api.myprovider.com/v1", "provider.custom.field.apiKey.label": "Clave API", @@ -920,6 +921,11 @@ export const dict = { "provider.custom.models.variants.thinking.placeholder": "thinking", "provider.custom.models.variants.thinking.enabled": "enabled", "provider.custom.models.variants.thinking.disabled": "disabled", + "provider.custom.models.variants.thinking.adaptive": "adaptive", + "provider.custom.models.variants.splitReasoning.label": "Split reasoning (required for e.g. MiniMax)", + "provider.custom.models.variants.splitReasoning.placeholder": "reasoning_split", + "provider.custom.models.variants.splitReasoning.true": "true", + "provider.custom.models.variants.splitReasoning.false": "false", "provider.custom.models.variants.chatTemplateArgs.label": "Activar pensamiento mediante args de plantilla de chat (ej. Hugging Face)", "provider.custom.models.variants.chatTemplateArgs.placeholder": "chat_template_args", @@ -933,6 +939,13 @@ export const dict = { "provider.custom.models.variants.reasoningEffort.medium": "medium", "provider.custom.models.variants.reasoningEffort.high": "high", "provider.custom.models.variants.reasoningEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.label": "Output effort (e.g. Anthropic)", + "provider.custom.models.variants.outputEffort.placeholder": "effort", + "provider.custom.models.variants.outputEffort.low": "low", + "provider.custom.models.variants.outputEffort.medium": "medium", + "provider.custom.models.variants.outputEffort.high": "high", + "provider.custom.models.variants.outputEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.max": "max", "provider.custom.models.remove": "Eliminar modelo", "provider.custom.models.add": "Añadir modelo", "provider.custom.models.fetch": "Obtener modelos", @@ -1292,6 +1305,10 @@ export const dict = { "settings.notifications.errors.title": "Errores", "settings.notifications.errors.description": "Mostrar notificación en errores", "settings.notifications.sounds": "Sonidos", + "settings.notifications.enable.title": "Activar las notificaciones sonoras", + "settings.notifications.enable.description": + "Reproducir sonidos cuando las sesiones finalicen, se produzca un error o se requiera tu intervención", + "settings.notifications.testSound": "Probar", "settings.notifications.agentSound.title": "Sonido de finalización del agente", "settings.notifications.agentSound.description": "Sonido a reproducir cuando el agente finaliza", "settings.notifications.permSound.title": "Sonido de solicitud de permiso", @@ -1299,6 +1316,9 @@ export const dict = { "settings.notifications.errorSound.title": "Sonido de error", "settings.notifications.errorSound.description": "Sonido a reproducir en errores", "settings.notifications.sound.default": "Predeterminado", + "settings.notifications.sound.system": "Sistema", + "settings.notifications.sound.description": + "La opción predeterminada utiliza sonidos diferentes para la finalización, la intervención y los errores. Las demás opciones utilizan un solo sonido para todos los eventos.", "settings.notifications.sound.none": "Ninguno", "settings.experimental.share.title": "Modo de compartir", "settings.experimental.share.description": "Comportamiento de compartir sesión", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts index 14ad670f31..d6630fac7a 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts @@ -901,6 +901,7 @@ export const dict = { "provider.custom.field.providerID.description": "Lettres minuscules, chiffres, tirets ou underscores", "provider.custom.field.name.label": "Nom d'affichage", "provider.custom.field.name.placeholder": "Mon fournisseur IA", + "provider.custom.field.package.label": "Provider API", "provider.custom.field.baseURL.label": "URL de base", "provider.custom.field.baseURL.placeholder": "https://api.myprovider.com/v1", "provider.custom.field.apiKey.label": "Clé API", @@ -927,6 +928,11 @@ export const dict = { "provider.custom.models.variants.thinking.placeholder": "thinking", "provider.custom.models.variants.thinking.enabled": "enabled", "provider.custom.models.variants.thinking.disabled": "disabled", + "provider.custom.models.variants.thinking.adaptive": "adaptive", + "provider.custom.models.variants.splitReasoning.label": "Split reasoning (required for e.g. MiniMax)", + "provider.custom.models.variants.splitReasoning.placeholder": "reasoning_split", + "provider.custom.models.variants.splitReasoning.true": "true", + "provider.custom.models.variants.splitReasoning.false": "false", "provider.custom.models.variants.chatTemplateArgs.label": "Activer la réflexion via les args du modèle de chat (ex. Hugging Face)", "provider.custom.models.variants.chatTemplateArgs.placeholder": "chat_template_args", @@ -940,6 +946,13 @@ export const dict = { "provider.custom.models.variants.reasoningEffort.medium": "medium", "provider.custom.models.variants.reasoningEffort.high": "high", "provider.custom.models.variants.reasoningEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.label": "Output effort (e.g. Anthropic)", + "provider.custom.models.variants.outputEffort.placeholder": "effort", + "provider.custom.models.variants.outputEffort.low": "low", + "provider.custom.models.variants.outputEffort.medium": "medium", + "provider.custom.models.variants.outputEffort.high": "high", + "provider.custom.models.variants.outputEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.max": "max", "provider.custom.models.remove": "Supprimer le modèle", "provider.custom.models.add": "Ajouter un modèle", "provider.custom.models.fetch": "Récupérer les modèles", @@ -1307,6 +1320,10 @@ export const dict = { "settings.notifications.errors.title": "Erreurs", "settings.notifications.errors.description": "Afficher une notification en cas d'erreur", "settings.notifications.sounds": "Sons", + "settings.notifications.enable.title": "Activer les notifications sonores", + "settings.notifications.enable.description": + "Lire des sons lorsque les sessions se terminent, rencontrent une erreur ou nécessitent votre intervention", + "settings.notifications.testSound": "Tester", "settings.notifications.agentSound.title": "Son d'achèvement de l'agent", "settings.notifications.agentSound.description": "Son à jouer lorsque l'agent termine", "settings.notifications.permSound.title": "Son de demande d'autorisation", @@ -1314,6 +1331,9 @@ export const dict = { "settings.notifications.errorSound.title": "Son d'erreur", "settings.notifications.errorSound.description": "Son à jouer en cas d'erreur", "settings.notifications.sound.default": "Par défaut", + "settings.notifications.sound.system": "Système", + "settings.notifications.sound.description": + "L’option par défaut utilise des sons différents pour la fin des sessions, les demandes d’intervention et les erreurs. Les autres options utilisent un même son pour tous les événements.", "settings.notifications.sound.none": "Aucun", "settings.experimental.share.title": "Mode de partage", "settings.experimental.share.description": "Comportement du partage de session", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/it.ts b/packages/kilo-vscode/webview-ui/src/i18n/it.ts index d9d7b7c9ac..25ab96b451 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/it.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/it.ts @@ -708,6 +708,7 @@ export const dict = { "provider.custom.field.providerID.description": "Lettere minuscole, numeri, trattini o underscore", "provider.custom.field.name.label": "Nome visualizzato", "provider.custom.field.name.placeholder": "Il mio provider AI", + "provider.custom.field.package.label": "Provider API", "provider.custom.field.baseURL.label": "URL base", "provider.custom.field.baseURL.placeholder": "https://api.mio-provider.com/v1", "provider.custom.field.apiKey.label": "API key", @@ -733,6 +734,11 @@ export const dict = { "provider.custom.models.variants.thinking.placeholder": "thinking", "provider.custom.models.variants.thinking.enabled": "enabled", "provider.custom.models.variants.thinking.disabled": "disabled", + "provider.custom.models.variants.thinking.adaptive": "adaptive", + "provider.custom.models.variants.splitReasoning.label": "Split reasoning (required for e.g. MiniMax)", + "provider.custom.models.variants.splitReasoning.placeholder": "reasoning_split", + "provider.custom.models.variants.splitReasoning.true": "true", + "provider.custom.models.variants.splitReasoning.false": "false", "provider.custom.models.variants.chatTemplateArgs.label": "Enable thinking via chat template args (e.g. Hugging Face)", "provider.custom.models.variants.chatTemplateArgs.placeholder": "chat_template_args", @@ -746,6 +752,13 @@ export const dict = { "provider.custom.models.variants.reasoningEffort.medium": "medium", "provider.custom.models.variants.reasoningEffort.high": "high", "provider.custom.models.variants.reasoningEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.label": "Output effort (e.g. Anthropic)", + "provider.custom.models.variants.outputEffort.placeholder": "effort", + "provider.custom.models.variants.outputEffort.low": "low", + "provider.custom.models.variants.outputEffort.medium": "medium", + "provider.custom.models.variants.outputEffort.high": "high", + "provider.custom.models.variants.outputEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.max": "max", "provider.custom.models.remove": "Rimuovi modello", "provider.custom.models.add": "Aggiungi modello", "provider.custom.models.fetch": "Recupera modelli", @@ -1121,6 +1134,10 @@ export const dict = { "settings.notifications.errors.title": "Errori", "settings.notifications.errors.description": "Mostra una notifica per gli errori", "settings.notifications.sounds": "Suoni", + "settings.notifications.enable.title": "Abilita le notifiche sonore", + "settings.notifications.enable.description": + "Riproduci suoni quando le sessioni si concludono, si verifica un errore o è richiesto il tuo intervento", + "settings.notifications.testSound": "Prova", "settings.notifications.agentSound.title": "Suono completamento agente", "settings.notifications.agentSound.description": "Suono da riprodurre quando l'agente completa un task", "settings.notifications.permSound.title": "Suono richiesta autorizzazione", @@ -1128,6 +1145,9 @@ export const dict = { "settings.notifications.errorSound.title": "Suono errore", "settings.notifications.errorSound.description": "Suono da riprodurre per gli errori", "settings.notifications.sound.default": "Predefinito", + "settings.notifications.sound.system": "Sistema", + "settings.notifications.sound.description": + "L'opzione predefinita usa suoni diversi per completamento, intervento ed errori. Le altre opzioni usano un unico suono per tutti gli eventi.", "settings.notifications.sound.none": "Nessuno", "settings.experimental.share.title": "Modalità condivisione", "settings.experimental.share.description": "Come si comporta la condivisione sessione", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts index da1e7436df..11872ef150 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts @@ -883,6 +883,7 @@ export const dict = { "provider.custom.field.providerID.description": "小文字、数字、ハイフン、アンダースコア", "provider.custom.field.name.label": "表示名", "provider.custom.field.name.placeholder": "マイAIプロバイダー", + "provider.custom.field.package.label": "Provider API", "provider.custom.field.baseURL.label": "ベースURL", "provider.custom.field.baseURL.placeholder": "https://api.myprovider.com/v1", "provider.custom.field.apiKey.label": "APIキー", @@ -908,6 +909,11 @@ export const dict = { "provider.custom.models.variants.thinking.placeholder": "thinking", "provider.custom.models.variants.thinking.enabled": "enabled", "provider.custom.models.variants.thinking.disabled": "disabled", + "provider.custom.models.variants.thinking.adaptive": "adaptive", + "provider.custom.models.variants.splitReasoning.label": "Split reasoning (required for e.g. MiniMax)", + "provider.custom.models.variants.splitReasoning.placeholder": "reasoning_split", + "provider.custom.models.variants.splitReasoning.true": "true", + "provider.custom.models.variants.splitReasoning.false": "false", "provider.custom.models.variants.chatTemplateArgs.label": "チャットテンプレート引数で思考を有効化 (例: Hugging Face)", "provider.custom.models.variants.chatTemplateArgs.placeholder": "chat_template_args", "provider.custom.models.variants.chatTemplateArgs.true": "true", @@ -920,6 +926,13 @@ export const dict = { "provider.custom.models.variants.reasoningEffort.medium": "medium", "provider.custom.models.variants.reasoningEffort.high": "high", "provider.custom.models.variants.reasoningEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.label": "Output effort (e.g. Anthropic)", + "provider.custom.models.variants.outputEffort.placeholder": "effort", + "provider.custom.models.variants.outputEffort.low": "low", + "provider.custom.models.variants.outputEffort.medium": "medium", + "provider.custom.models.variants.outputEffort.high": "high", + "provider.custom.models.variants.outputEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.max": "max", "provider.custom.models.remove": "モデルを削除", "provider.custom.models.add": "モデルを追加", "provider.custom.models.fetch": "モデルを取得", @@ -1272,6 +1285,10 @@ export const dict = { "settings.notifications.errors.title": "エラー", "settings.notifications.errors.description": "エラー発生時に通知を表示", "settings.notifications.sounds": "サウンド", + "settings.notifications.enable.title": "サウンド通知を有効にする", + "settings.notifications.enable.description": + "セッションの完了時、エラーの発生時、またはユーザー入力が必要なときにサウンドを再生します", + "settings.notifications.testSound": "テスト", "settings.notifications.agentSound.title": "エージェント完了サウンド", "settings.notifications.agentSound.description": "エージェント完了時に再生するサウンド", "settings.notifications.permSound.title": "権限リクエストサウンド", @@ -1279,6 +1296,9 @@ export const dict = { "settings.notifications.errorSound.title": "エラーサウンド", "settings.notifications.errorSound.description": "エラー発生時に再生するサウンド", "settings.notifications.sound.default": "デフォルト", + "settings.notifications.sound.system": "システム", + "settings.notifications.sound.description": + "デフォルトでは、完了、入力、エラーにそれぞれ異なるサウンドが使用されます。その他の選択肢では、すべてのイベントに同じサウンドが使用されます。", "settings.notifications.sound.none": "なし", "settings.experimental.share.title": "共有モード", "settings.experimental.share.description": "セッション共有の動作", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts index 6d50cf6184..d51d567b64 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts @@ -845,6 +845,7 @@ export const dict = { "provider.custom.field.providerID.description": "소문자, 숫자, 하이픈 또는 밑줄", "provider.custom.field.name.label": "표시 이름", "provider.custom.field.name.placeholder": "내 AI 공급자", + "provider.custom.field.package.label": "Provider API", "provider.custom.field.baseURL.label": "기본 URL", "provider.custom.field.baseURL.placeholder": "https://api.myprovider.com/v1", "provider.custom.field.apiKey.label": "API 키", @@ -870,6 +871,11 @@ export const dict = { "provider.custom.models.variants.thinking.placeholder": "thinking", "provider.custom.models.variants.thinking.enabled": "enabled", "provider.custom.models.variants.thinking.disabled": "disabled", + "provider.custom.models.variants.thinking.adaptive": "adaptive", + "provider.custom.models.variants.splitReasoning.label": "Split reasoning (required for e.g. MiniMax)", + "provider.custom.models.variants.splitReasoning.placeholder": "reasoning_split", + "provider.custom.models.variants.splitReasoning.true": "true", + "provider.custom.models.variants.splitReasoning.false": "false", "provider.custom.models.variants.chatTemplateArgs.label": "채팅 템플릿 인수로 사고 활성화 (예: Hugging Face)", "provider.custom.models.variants.chatTemplateArgs.placeholder": "chat_template_args", "provider.custom.models.variants.chatTemplateArgs.true": "true", @@ -882,6 +888,13 @@ export const dict = { "provider.custom.models.variants.reasoningEffort.medium": "medium", "provider.custom.models.variants.reasoningEffort.high": "high", "provider.custom.models.variants.reasoningEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.label": "Output effort (e.g. Anthropic)", + "provider.custom.models.variants.outputEffort.placeholder": "effort", + "provider.custom.models.variants.outputEffort.low": "low", + "provider.custom.models.variants.outputEffort.medium": "medium", + "provider.custom.models.variants.outputEffort.high": "high", + "provider.custom.models.variants.outputEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.max": "max", "provider.custom.models.remove": "모델 제거", "provider.custom.models.add": "모델 추가", "provider.custom.models.fetch": "모델 가져오기", @@ -1266,6 +1279,10 @@ export const dict = { "settings.notifications.errors.title": "오류", "settings.notifications.errors.description": "오류 발생 시 알림 표시", "settings.notifications.sounds": "소리", + "settings.notifications.enable.title": "소리 알림 활성화", + "settings.notifications.enable.description": + "세션이 완료되거나 오류가 발생하거나 사용자 입력이 필요할 때 소리를 재생합니다", + "settings.notifications.testSound": "테스트", "settings.notifications.agentSound.title": "에이전트 완료 소리", "settings.notifications.agentSound.description": "에이전트 완료 시 재생할 소리", "settings.notifications.permSound.title": "권한 요청 소리", @@ -1273,6 +1290,9 @@ export const dict = { "settings.notifications.errorSound.title": "오류 소리", "settings.notifications.errorSound.description": "오류 발생 시 재생할 소리", "settings.notifications.sound.default": "기본값", + "settings.notifications.sound.system": "시스템", + "settings.notifications.sound.description": + "기본값은 완료, 입력, 오류에 서로 다른 소리를 사용합니다. 다른 옵션에서는 모든 이벤트에 동일한 소리를 사용합니다.", "settings.notifications.sound.none": "없음", "settings.experimental.share.title": "공유 모드", "settings.experimental.share.description": "세션 공유 동작 방식", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts index 716bbe1d18..4dcc114373 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts @@ -846,6 +846,7 @@ export const dict = { "provider.custom.field.providerID.description": "Kleine letters, cijfers, koppeltekens of onderstrepingstekens", "provider.custom.field.name.label": "Weergavenaam", "provider.custom.field.name.placeholder": "Mijn AI Provider", + "provider.custom.field.package.label": "Provider API", "provider.custom.field.baseURL.label": "Basis-URL", "provider.custom.field.baseURL.placeholder": "https://api.mijnprovider.com/v1", "provider.custom.field.apiKey.label": "API-sleutel", @@ -871,6 +872,11 @@ export const dict = { "provider.custom.models.variants.thinking.placeholder": "thinking", "provider.custom.models.variants.thinking.enabled": "enabled", "provider.custom.models.variants.thinking.disabled": "disabled", + "provider.custom.models.variants.thinking.adaptive": "adaptive", + "provider.custom.models.variants.splitReasoning.label": "Split reasoning (required for e.g. MiniMax)", + "provider.custom.models.variants.splitReasoning.placeholder": "reasoning_split", + "provider.custom.models.variants.splitReasoning.true": "true", + "provider.custom.models.variants.splitReasoning.false": "false", "provider.custom.models.variants.chatTemplateArgs.label": "Nadenken inschakelen via chat template args (bijv. Hugging Face)", "provider.custom.models.variants.chatTemplateArgs.placeholder": "chat_template_args", @@ -884,6 +890,13 @@ export const dict = { "provider.custom.models.variants.reasoningEffort.medium": "medium", "provider.custom.models.variants.reasoningEffort.high": "high", "provider.custom.models.variants.reasoningEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.label": "Output effort (e.g. Anthropic)", + "provider.custom.models.variants.outputEffort.placeholder": "effort", + "provider.custom.models.variants.outputEffort.low": "low", + "provider.custom.models.variants.outputEffort.medium": "medium", + "provider.custom.models.variants.outputEffort.high": "high", + "provider.custom.models.variants.outputEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.max": "max", "provider.custom.models.remove": "Model verwijderen", "provider.custom.models.add": "Model toevoegen", "provider.custom.models.fetch": "Modellen ophalen", @@ -1277,6 +1290,10 @@ export const dict = { "settings.notifications.errors.title": "Fouten", "settings.notifications.errors.description": "Toon melding bij fouten", "settings.notifications.sounds": "Geluiden", + "settings.notifications.enable.title": "Geluidsmeldingen inschakelen", + "settings.notifications.enable.description": + "Geluiden afspelen wanneer sessies worden voltooid, er een fout optreedt of uw invoer vereist is", + "settings.notifications.testSound": "Testen", "settings.notifications.agentSound.title": "Agent Voltooiingsgeluid", "settings.notifications.agentSound.description": "Geluid om af te spelen wanneer agent voltooit", "settings.notifications.permSound.title": "Toestemmingsverzoek Geluid", @@ -1284,6 +1301,9 @@ export const dict = { "settings.notifications.errorSound.title": "Fout Geluid", "settings.notifications.errorSound.description": "Geluid om af te spelen bij fouten", "settings.notifications.sound.default": "Standaard", + "settings.notifications.sound.system": "Systeem", + "settings.notifications.sound.description": + "Standaard worden verschillende geluiden gebruikt voor voltooiing, invoer en fouten. Andere keuzes gebruiken voor elke gebeurtenis hetzelfde geluid.", "settings.notifications.sound.none": "Geen", "settings.experimental.share.title": "Deelmodus", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/no.ts b/packages/kilo-vscode/webview-ui/src/i18n/no.ts index beef9ac746..7eb5c3a938 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/no.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/no.ts @@ -854,6 +854,7 @@ export const dict = { "provider.custom.field.providerID.description": "Små bokstaver, tall, bindestreker eller understreker", "provider.custom.field.name.label": "Visningsnavn", "provider.custom.field.name.placeholder": "Min AI-leverandør", + "provider.custom.field.package.label": "Provider API", "provider.custom.field.baseURL.label": "Basis-URL", "provider.custom.field.baseURL.placeholder": "https://api.myprovider.com/v1", "provider.custom.field.apiKey.label": "API-nøkkel", @@ -879,6 +880,11 @@ export const dict = { "provider.custom.models.variants.thinking.placeholder": "thinking", "provider.custom.models.variants.thinking.enabled": "enabled", "provider.custom.models.variants.thinking.disabled": "disabled", + "provider.custom.models.variants.thinking.adaptive": "adaptive", + "provider.custom.models.variants.splitReasoning.label": "Split reasoning (required for e.g. MiniMax)", + "provider.custom.models.variants.splitReasoning.placeholder": "reasoning_split", + "provider.custom.models.variants.splitReasoning.true": "true", + "provider.custom.models.variants.splitReasoning.false": "false", "provider.custom.models.variants.chatTemplateArgs.label": "Aktiver tenkning via chat-malargumenter (f.eks. Hugging Face)", "provider.custom.models.variants.chatTemplateArgs.placeholder": "chat_template_args", @@ -892,6 +898,13 @@ export const dict = { "provider.custom.models.variants.reasoningEffort.medium": "medium", "provider.custom.models.variants.reasoningEffort.high": "high", "provider.custom.models.variants.reasoningEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.label": "Output effort (e.g. Anthropic)", + "provider.custom.models.variants.outputEffort.placeholder": "effort", + "provider.custom.models.variants.outputEffort.low": "low", + "provider.custom.models.variants.outputEffort.medium": "medium", + "provider.custom.models.variants.outputEffort.high": "high", + "provider.custom.models.variants.outputEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.max": "max", "provider.custom.models.remove": "Fjern modell", "provider.custom.models.add": "Legg til modell", "provider.custom.models.fetch": "Hent modeller", @@ -1243,6 +1256,10 @@ export const dict = { "settings.notifications.errors.title": "Feil", "settings.notifications.errors.description": "Vis varsling ved feil", "settings.notifications.sounds": "Lyder", + "settings.notifications.enable.title": "Aktiver lydvarsler", + "settings.notifications.enable.description": + "Spill av lyder når økter fullføres, det oppstår en feil eller det trengs innspill fra deg", + "settings.notifications.testSound": "Test", "settings.notifications.agentSound.title": "Agentfullføringslyd", "settings.notifications.agentSound.description": "Lyd ved agentfullføring", "settings.notifications.permSound.title": "Tillatelsesforespørselslyd", @@ -1250,6 +1267,9 @@ export const dict = { "settings.notifications.errorSound.title": "Feillyd", "settings.notifications.errorSound.description": "Lyd ved feil", "settings.notifications.sound.default": "Standard", + "settings.notifications.sound.system": "System", + "settings.notifications.sound.description": + "Standardvalget bruker forskjellige lyder for fullføring, innspill og feil. Andre valg bruker én lyd for alle hendelser.", "settings.notifications.sound.none": "Ingen", "settings.experimental.share.title": "Delingsmodus", "settings.experimental.share.description": "Oppførsel for sesjonsdeling", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts index 012bb9c919..7690e393b7 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts @@ -852,6 +852,7 @@ export const dict = { "provider.custom.field.providerID.description": "Małe litery, cyfry, myślniki lub podkreślenia", "provider.custom.field.name.label": "Nazwa wyświetlana", "provider.custom.field.name.placeholder": "Mój dostawca AI", + "provider.custom.field.package.label": "Provider API", "provider.custom.field.baseURL.label": "Bazowy URL", "provider.custom.field.baseURL.placeholder": "https://api.myprovider.com/v1", "provider.custom.field.apiKey.label": "Klucz API", @@ -878,6 +879,11 @@ export const dict = { "provider.custom.models.variants.thinking.placeholder": "thinking", "provider.custom.models.variants.thinking.enabled": "enabled", "provider.custom.models.variants.thinking.disabled": "disabled", + "provider.custom.models.variants.thinking.adaptive": "adaptive", + "provider.custom.models.variants.splitReasoning.label": "Split reasoning (required for e.g. MiniMax)", + "provider.custom.models.variants.splitReasoning.placeholder": "reasoning_split", + "provider.custom.models.variants.splitReasoning.true": "true", + "provider.custom.models.variants.splitReasoning.false": "false", "provider.custom.models.variants.chatTemplateArgs.label": "Włącz myślenie przez argumenty szablonu czatu (np. Hugging Face)", "provider.custom.models.variants.chatTemplateArgs.placeholder": "chat_template_args", @@ -891,6 +897,13 @@ export const dict = { "provider.custom.models.variants.reasoningEffort.medium": "medium", "provider.custom.models.variants.reasoningEffort.high": "high", "provider.custom.models.variants.reasoningEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.label": "Output effort (e.g. Anthropic)", + "provider.custom.models.variants.outputEffort.placeholder": "effort", + "provider.custom.models.variants.outputEffort.low": "low", + "provider.custom.models.variants.outputEffort.medium": "medium", + "provider.custom.models.variants.outputEffort.high": "high", + "provider.custom.models.variants.outputEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.max": "max", "provider.custom.models.remove": "Usuń model", "provider.custom.models.add": "Dodaj model", "provider.custom.models.fetch": "Pobierz modele", @@ -1243,6 +1256,10 @@ export const dict = { "settings.notifications.errors.title": "Błędy", "settings.notifications.errors.description": "Pokaż powiadomienie przy błędach", "settings.notifications.sounds": "Dźwięki", + "settings.notifications.enable.title": "Włącz powiadomienia dźwiękowe", + "settings.notifications.enable.description": + "Odtwarzaj dźwięki, gdy sesje się zakończą, wystąpi błąd lub będzie potrzebna Twoja reakcja", + "settings.notifications.testSound": "Testuj", "settings.notifications.agentSound.title": "Dźwięk zakończenia agenta", "settings.notifications.agentSound.description": "Dźwięk odtwarzany po zakończeniu agenta", "settings.notifications.permSound.title": "Dźwięk żądania uprawnień", @@ -1250,6 +1267,9 @@ export const dict = { "settings.notifications.errorSound.title": "Dźwięk błędu", "settings.notifications.errorSound.description": "Dźwięk odtwarzany przy błędach", "settings.notifications.sound.default": "Domyślny", + "settings.notifications.sound.system": "System", + "settings.notifications.sound.description": + "Opcja domyślna używa różnych dźwięków dla zakończenia, oczekiwania na reakcję i błędów. Pozostałe opcje używają jednego dźwięku dla wszystkich zdarzeń.", "settings.notifications.sound.none": "Brak", "settings.experimental.share.title": "Tryb udostępniania", "settings.experimental.share.description": "Zachowanie udostępniania sesji", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts index cccc0ec8f7..e9718e51e9 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts @@ -891,6 +891,7 @@ export const dict = { "provider.custom.field.providerID.description": "Строчные буквы, цифры, дефисы или подчёркивания", "provider.custom.field.name.label": "Отображаемое имя", "provider.custom.field.name.placeholder": "Мой AI-провайдер", + "provider.custom.field.package.label": "Provider API", "provider.custom.field.baseURL.label": "Базовый URL", "provider.custom.field.baseURL.placeholder": "https://api.myprovider.com/v1", "provider.custom.field.apiKey.label": "API-ключ", @@ -917,6 +918,11 @@ export const dict = { "provider.custom.models.variants.thinking.placeholder": "thinking", "provider.custom.models.variants.thinking.enabled": "enabled", "provider.custom.models.variants.thinking.disabled": "disabled", + "provider.custom.models.variants.thinking.adaptive": "adaptive", + "provider.custom.models.variants.splitReasoning.label": "Split reasoning (required for e.g. MiniMax)", + "provider.custom.models.variants.splitReasoning.placeholder": "reasoning_split", + "provider.custom.models.variants.splitReasoning.true": "true", + "provider.custom.models.variants.splitReasoning.false": "false", "provider.custom.models.variants.chatTemplateArgs.label": "Включить размышление через аргументы шаблона чата (напр. Hugging Face)", "provider.custom.models.variants.chatTemplateArgs.placeholder": "chat_template_args", @@ -930,6 +936,13 @@ export const dict = { "provider.custom.models.variants.reasoningEffort.medium": "medium", "provider.custom.models.variants.reasoningEffort.high": "high", "provider.custom.models.variants.reasoningEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.label": "Output effort (e.g. Anthropic)", + "provider.custom.models.variants.outputEffort.placeholder": "effort", + "provider.custom.models.variants.outputEffort.low": "low", + "provider.custom.models.variants.outputEffort.medium": "medium", + "provider.custom.models.variants.outputEffort.high": "high", + "provider.custom.models.variants.outputEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.max": "max", "provider.custom.models.remove": "Удалить модель", "provider.custom.models.add": "Добавить модель", "provider.custom.models.fetch": "Получить модели", @@ -1283,6 +1296,10 @@ export const dict = { "settings.notifications.errors.title": "Ошибки", "settings.notifications.errors.description": "Показать уведомление при ошибках", "settings.notifications.sounds": "Звуки", + "settings.notifications.enable.title": "Включить звуковые уведомления", + "settings.notifications.enable.description": + "Воспроизводить звуки при завершении сеансов, возникновении ошибки или необходимости вашего участия", + "settings.notifications.testSound": "Тест", "settings.notifications.agentSound.title": "Звук завершения агента", "settings.notifications.agentSound.description": "Звук при завершении агента", "settings.notifications.permSound.title": "Звук запроса разрешений", @@ -1290,6 +1307,9 @@ export const dict = { "settings.notifications.errorSound.title": "Звук ошибки", "settings.notifications.errorSound.description": "Звук при ошибках", "settings.notifications.sound.default": "По умолчанию", + "settings.notifications.sound.system": "Системный", + "settings.notifications.sound.description": + "По умолчанию для завершения, запроса вашего участия и ошибок используются разные звуки. В остальных вариантах для всех событий используется один и тот же звук.", "settings.notifications.sound.none": "Нет", "settings.experimental.share.title": "Режим обмена", "settings.experimental.share.description": "Поведение обмена сессиями", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/th.ts b/packages/kilo-vscode/webview-ui/src/i18n/th.ts index e6ed8b9475..e67be317df 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/th.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/th.ts @@ -878,6 +878,7 @@ export const dict = { "provider.custom.field.providerID.description": "ตัวอักษรพิมพ์เล็ก ตัวเลข ขีดกลาง หรือขีดล่าง", "provider.custom.field.name.label": "ชื่อที่แสดง", "provider.custom.field.name.placeholder": "ผู้ให้บริการ AI ของฉัน", + "provider.custom.field.package.label": "Provider API", "provider.custom.field.baseURL.label": "URL พื้นฐาน", "provider.custom.field.baseURL.placeholder": "https://api.myprovider.com/v1", "provider.custom.field.apiKey.label": "คีย์ API", @@ -903,6 +904,11 @@ export const dict = { "provider.custom.models.variants.thinking.placeholder": "thinking", "provider.custom.models.variants.thinking.enabled": "enabled", "provider.custom.models.variants.thinking.disabled": "disabled", + "provider.custom.models.variants.thinking.adaptive": "adaptive", + "provider.custom.models.variants.splitReasoning.label": "Split reasoning (required for e.g. MiniMax)", + "provider.custom.models.variants.splitReasoning.placeholder": "reasoning_split", + "provider.custom.models.variants.splitReasoning.true": "true", + "provider.custom.models.variants.splitReasoning.false": "false", "provider.custom.models.variants.chatTemplateArgs.label": "เปิดใช้งานการคิดผ่านอาร์กิวเมนต์เทมเพลตแชท (เช่น Hugging Face)", "provider.custom.models.variants.chatTemplateArgs.placeholder": "chat_template_args", @@ -916,6 +922,13 @@ export const dict = { "provider.custom.models.variants.reasoningEffort.medium": "medium", "provider.custom.models.variants.reasoningEffort.high": "high", "provider.custom.models.variants.reasoningEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.label": "Output effort (e.g. Anthropic)", + "provider.custom.models.variants.outputEffort.placeholder": "effort", + "provider.custom.models.variants.outputEffort.low": "low", + "provider.custom.models.variants.outputEffort.medium": "medium", + "provider.custom.models.variants.outputEffort.high": "high", + "provider.custom.models.variants.outputEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.max": "max", "provider.custom.models.remove": "ลบโมเดล", "provider.custom.models.add": "เพิ่มโมเดล", "provider.custom.models.fetch": "ดึงโมเดล", @@ -1262,6 +1275,10 @@ export const dict = { "settings.notifications.errors.title": "ข้อผิดพลาด", "settings.notifications.errors.description": "แสดงการแจ้งเตือนเมื่อเกิดข้อผิดพลาด", "settings.notifications.sounds": "เสียง", + "settings.notifications.enable.title": "เปิดใช้การแจ้งเตือนด้วยเสียง", + "settings.notifications.enable.description": + "เล่นเสียงเมื่อเซสชันเสร็จสิ้น เกิดข้อผิดพลาด หรือต้องการให้คุณป้อนข้อมูล", + "settings.notifications.testSound": "ทดสอบ", "settings.notifications.agentSound.title": "เสียงเอเจนต์เสร็จสิ้น", "settings.notifications.agentSound.description": "เสียงเมื่อเอเจนต์ทำงานเสร็จ", "settings.notifications.permSound.title": "เสียงคำขออนุญาต", @@ -1269,6 +1286,9 @@ export const dict = { "settings.notifications.errorSound.title": "เสียงข้อผิดพลาด", "settings.notifications.errorSound.description": "เสียงเมื่อเกิดข้อผิดพลาด", "settings.notifications.sound.default": "ค่าเริ่มต้น", + "settings.notifications.sound.system": "ระบบ", + "settings.notifications.sound.description": + "ค่าเริ่มต้นจะใช้เสียงที่แตกต่างกันสำหรับการเสร็จสิ้น การป้อนข้อมูล และข้อผิดพลาด ส่วนตัวเลือกอื่นจะใช้เสียงเดียวสำหรับทุกเหตุการณ์", "settings.notifications.sound.none": "ไม่มี", "settings.experimental.share.title": "โหมดแชร์", "settings.experimental.share.description": "พฤติกรรมการแชร์เซสชัน", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts index 707171faa7..431778e572 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts @@ -844,6 +844,7 @@ export const dict = { "provider.custom.field.providerID.description": "Küçük harfler, rakamlar, tire veya alt çizgi", "provider.custom.field.name.label": "Görünen ad", "provider.custom.field.name.placeholder": "Yapay Zeka Sağlayıcım", + "provider.custom.field.package.label": "Provider API", "provider.custom.field.baseURL.label": "Temel URL", "provider.custom.field.baseURL.placeholder": "https://api.saglayicim.com/v1", "provider.custom.field.apiKey.label": "API anahtarı", @@ -870,6 +871,11 @@ export const dict = { "provider.custom.models.variants.thinking.placeholder": "thinking", "provider.custom.models.variants.thinking.enabled": "enabled", "provider.custom.models.variants.thinking.disabled": "disabled", + "provider.custom.models.variants.thinking.adaptive": "adaptive", + "provider.custom.models.variants.splitReasoning.label": "Split reasoning (required for e.g. MiniMax)", + "provider.custom.models.variants.splitReasoning.placeholder": "reasoning_split", + "provider.custom.models.variants.splitReasoning.true": "true", + "provider.custom.models.variants.splitReasoning.false": "false", "provider.custom.models.variants.chatTemplateArgs.label": "Sohbet şablonu argümanları ile düşünmeyi etkinleştir (ör. Hugging Face)", "provider.custom.models.variants.chatTemplateArgs.placeholder": "chat_template_args", @@ -883,6 +889,13 @@ export const dict = { "provider.custom.models.variants.reasoningEffort.medium": "medium", "provider.custom.models.variants.reasoningEffort.high": "high", "provider.custom.models.variants.reasoningEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.label": "Output effort (e.g. Anthropic)", + "provider.custom.models.variants.outputEffort.placeholder": "effort", + "provider.custom.models.variants.outputEffort.low": "low", + "provider.custom.models.variants.outputEffort.medium": "medium", + "provider.custom.models.variants.outputEffort.high": "high", + "provider.custom.models.variants.outputEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.max": "max", "provider.custom.models.remove": "Modeli kaldır", "provider.custom.models.add": "Model ekle", "provider.custom.models.fetch": "Modelleri getir", @@ -1270,6 +1283,10 @@ export const dict = { "settings.notifications.errors.title": "Hatalar", "settings.notifications.errors.description": "Hata oluştuğunda bildirim göster", "settings.notifications.sounds": "Sesler", + "settings.notifications.enable.title": "Sesli bildirimleri etkinleştir", + "settings.notifications.enable.description": + "Oturumlar tamamlandığında, bir hatayla karşılaşıldığında veya sizden giriş beklendiğinde ses çal", + "settings.notifications.testSound": "Test et", "settings.notifications.agentSound.title": "Ajan Tamamlanma Sesi", "settings.notifications.agentSound.description": "Ajan tamamlandığında çalınacak ses", "settings.notifications.permSound.title": "İzin İsteği Sesi", @@ -1277,6 +1294,9 @@ export const dict = { "settings.notifications.errorSound.title": "Hata Sesi", "settings.notifications.errorSound.description": "Hata oluştuğunda çalınacak ses", "settings.notifications.sound.default": "Varsayılan", + "settings.notifications.sound.system": "Sistem", + "settings.notifications.sound.description": + "Varsayılan seçenekte tamamlanma, giriş ve hatalar için farklı sesler kullanılır. Diğer seçeneklerde tüm etkinlikler için tek bir ses kullanılır.", "settings.notifications.sound.none": "Yok", "settings.experimental.share.title": "Paylaşım Modu", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/uk.ts b/packages/kilo-vscode/webview-ui/src/i18n/uk.ts index 5d54096273..280f20ded7 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/uk.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/uk.ts @@ -845,6 +845,7 @@ export const dict = { "provider.custom.field.providerID.description": "Малі літери, цифри, дефіс або підкреслення", "provider.custom.field.name.label": "Відображувана назва", "provider.custom.field.name.placeholder": "Мій ШІ-провайдер", + "provider.custom.field.package.label": "Provider API", "provider.custom.field.baseURL.label": "Базовий URL", "provider.custom.field.baseURL.placeholder": "https://api.miy-provyder.com/v1", "provider.custom.field.apiKey.label": "API-ключ", @@ -871,6 +872,11 @@ export const dict = { "provider.custom.models.variants.thinking.placeholder": "thinking", "provider.custom.models.variants.thinking.enabled": "enabled", "provider.custom.models.variants.thinking.disabled": "disabled", + "provider.custom.models.variants.thinking.adaptive": "adaptive", + "provider.custom.models.variants.splitReasoning.label": "Split reasoning (required for e.g. MiniMax)", + "provider.custom.models.variants.splitReasoning.placeholder": "reasoning_split", + "provider.custom.models.variants.splitReasoning.true": "true", + "provider.custom.models.variants.splitReasoning.false": "false", "provider.custom.models.variants.chatTemplateArgs.label": "Увімкнути мислення через аргументи шаблону чату (напр. Hugging Face)", "provider.custom.models.variants.chatTemplateArgs.placeholder": "chat_template_args", @@ -884,6 +890,13 @@ export const dict = { "provider.custom.models.variants.reasoningEffort.medium": "medium", "provider.custom.models.variants.reasoningEffort.high": "high", "provider.custom.models.variants.reasoningEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.label": "Output effort (e.g. Anthropic)", + "provider.custom.models.variants.outputEffort.placeholder": "effort", + "provider.custom.models.variants.outputEffort.low": "low", + "provider.custom.models.variants.outputEffort.medium": "medium", + "provider.custom.models.variants.outputEffort.high": "high", + "provider.custom.models.variants.outputEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.max": "max", "provider.custom.models.remove": "Видалити модель", "provider.custom.models.add": "Додати модель", "provider.custom.models.fetch": "Отримати моделі", @@ -1269,6 +1282,10 @@ export const dict = { "settings.notifications.errors.title": "Помилки", "settings.notifications.errors.description": "Показувати сповіщення при виникненні помилок", "settings.notifications.sounds": "Звуки", + "settings.notifications.enable.title": "Увімкнути звукові сповіщення", + "settings.notifications.enable.description": + "Відтворювати звуки, коли сеанси завершуються, виникає помилка або потрібна ваша відповідь", + "settings.notifications.testSound": "Тест", "settings.notifications.agentSound.title": "Звук завершення агента", "settings.notifications.agentSound.description": "Звук, що відтворюється після завершення агента", "settings.notifications.permSound.title": "Звук запиту дозволу", @@ -1276,6 +1293,9 @@ export const dict = { "settings.notifications.errorSound.title": "Звук помилки", "settings.notifications.errorSound.description": "Звук, що відтворюється при виникненні помилок", "settings.notifications.sound.default": "За замовчуванням", + "settings.notifications.sound.system": "Системний", + "settings.notifications.sound.description": + "За замовчуванням для завершення, запиту на введення та помилок використовуються різні звуки. В інших варіантах для всіх подій використовується один і той самий звук.", "settings.notifications.sound.none": "Немає", "settings.experimental.share.title": "Режим публікації", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts index cd32c4c248..28b2ac634f 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts @@ -864,6 +864,7 @@ export const dict = { "provider.custom.field.providerID.description": "小写字母、数字、连字符或下划线", "provider.custom.field.name.label": "显示名称", "provider.custom.field.name.placeholder": "我的 AI 提供商", + "provider.custom.field.package.label": "Provider API", "provider.custom.field.baseURL.label": "基础 URL", "provider.custom.field.baseURL.placeholder": "https://api.myprovider.com/v1", "provider.custom.field.apiKey.label": "API 密钥", @@ -889,6 +890,11 @@ export const dict = { "provider.custom.models.variants.thinking.placeholder": "thinking", "provider.custom.models.variants.thinking.enabled": "enabled", "provider.custom.models.variants.thinking.disabled": "disabled", + "provider.custom.models.variants.thinking.adaptive": "adaptive", + "provider.custom.models.variants.splitReasoning.label": "Split reasoning (required for e.g. MiniMax)", + "provider.custom.models.variants.splitReasoning.placeholder": "reasoning_split", + "provider.custom.models.variants.splitReasoning.true": "true", + "provider.custom.models.variants.splitReasoning.false": "false", "provider.custom.models.variants.chatTemplateArgs.label": "通过聊天模板参数启用思考(如 Hugging Face)", "provider.custom.models.variants.chatTemplateArgs.placeholder": "chat_template_args", "provider.custom.models.variants.chatTemplateArgs.true": "true", @@ -901,6 +907,13 @@ export const dict = { "provider.custom.models.variants.reasoningEffort.medium": "medium", "provider.custom.models.variants.reasoningEffort.high": "high", "provider.custom.models.variants.reasoningEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.label": "Output effort (e.g. Anthropic)", + "provider.custom.models.variants.outputEffort.placeholder": "effort", + "provider.custom.models.variants.outputEffort.low": "low", + "provider.custom.models.variants.outputEffort.medium": "medium", + "provider.custom.models.variants.outputEffort.high": "high", + "provider.custom.models.variants.outputEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.max": "max", "provider.custom.models.remove": "移除模型", "provider.custom.models.add": "添加模型", "provider.custom.models.fetch": "获取模型", @@ -1244,6 +1257,9 @@ export const dict = { "settings.notifications.errors.title": "错误", "settings.notifications.errors.description": "发生错误时显示通知", "settings.notifications.sounds": "声音", + "settings.notifications.enable.title": "启用声音通知", + "settings.notifications.enable.description": "在会话完成、遇到错误或需要你输入时播放声音", + "settings.notifications.testSound": "测试", "settings.notifications.agentSound.title": "智能体完成提示音", "settings.notifications.agentSound.description": "智能体完成时播放的声音", "settings.notifications.permSound.title": "权限请求提示音", @@ -1251,6 +1267,9 @@ export const dict = { "settings.notifications.errorSound.title": "错误提示音", "settings.notifications.errorSound.description": "发生错误时播放的声音", "settings.notifications.sound.default": "默认", + "settings.notifications.sound.system": "系统", + "settings.notifications.sound.description": + "默认选项为完成、输入和错误使用不同的声音。其他选项为所有事件使用同一种声音。", "settings.notifications.sound.none": "无", "settings.experimental.share.title": "分享模式", "settings.experimental.share.description": "会话分享行为", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts index 7bfd5f39d9..0320ead9e9 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts @@ -832,6 +832,7 @@ export const dict = { "provider.custom.field.providerID.description": "小寫字母、數字、連字號或底線", "provider.custom.field.name.label": "顯示名稱", "provider.custom.field.name.placeholder": "我的 AI 提供商", + "provider.custom.field.package.label": "Provider API", "provider.custom.field.baseURL.label": "基礎 URL", "provider.custom.field.baseURL.placeholder": "https://api.myprovider.com/v1", "provider.custom.field.apiKey.label": "API 金鑰", @@ -857,6 +858,11 @@ export const dict = { "provider.custom.models.variants.thinking.placeholder": "thinking", "provider.custom.models.variants.thinking.enabled": "enabled", "provider.custom.models.variants.thinking.disabled": "disabled", + "provider.custom.models.variants.thinking.adaptive": "adaptive", + "provider.custom.models.variants.splitReasoning.label": "Split reasoning (required for e.g. MiniMax)", + "provider.custom.models.variants.splitReasoning.placeholder": "reasoning_split", + "provider.custom.models.variants.splitReasoning.true": "true", + "provider.custom.models.variants.splitReasoning.false": "false", "provider.custom.models.variants.chatTemplateArgs.label": "透過聊天範本參數啟用思考(如 Hugging Face)", "provider.custom.models.variants.chatTemplateArgs.placeholder": "chat_template_args", "provider.custom.models.variants.chatTemplateArgs.true": "true", @@ -869,6 +875,13 @@ export const dict = { "provider.custom.models.variants.reasoningEffort.medium": "medium", "provider.custom.models.variants.reasoningEffort.high": "high", "provider.custom.models.variants.reasoningEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.label": "Output effort (e.g. Anthropic)", + "provider.custom.models.variants.outputEffort.placeholder": "effort", + "provider.custom.models.variants.outputEffort.low": "low", + "provider.custom.models.variants.outputEffort.medium": "medium", + "provider.custom.models.variants.outputEffort.high": "high", + "provider.custom.models.variants.outputEffort.xhigh": "xhigh", + "provider.custom.models.variants.outputEffort.max": "max", "provider.custom.models.remove": "移除模型", "provider.custom.models.add": "新增模型", "provider.custom.models.fetch": "取得模型", @@ -1212,6 +1225,9 @@ export const dict = { "settings.notifications.errors.title": "錯誤", "settings.notifications.errors.description": "發生錯誤時顯示通知", "settings.notifications.sounds": "聲音", + "settings.notifications.enable.title": "啟用聲音通知", + "settings.notifications.enable.description": "在工作階段完成、遇到錯誤或需要你輸入時播放聲音", + "settings.notifications.testSound": "測試", "settings.notifications.agentSound.title": "Agent 完成提示音", "settings.notifications.agentSound.description": "Agent 完成時播放的聲音", "settings.notifications.permSound.title": "權限請求提示音", @@ -1219,6 +1235,9 @@ export const dict = { "settings.notifications.errorSound.title": "錯誤提示音", "settings.notifications.errorSound.description": "發生錯誤時播放的聲音", "settings.notifications.sound.default": "預設", + "settings.notifications.sound.system": "系統", + "settings.notifications.sound.description": + "預設選項會為完成、輸入和錯誤使用不同的聲音。其他選項則會對所有事件使用同一種聲音。", "settings.notifications.sound.none": "無", "settings.experimental.share.title": "分享模式", "settings.experimental.share.description": "工作階段分享行為", diff --git a/packages/kilo-vscode/webview-ui/src/types/messages/extension-messages.ts b/packages/kilo-vscode/webview-ui/src/types/messages/extension-messages.ts index 95d64f15dc..2a285e6b79 100644 --- a/packages/kilo-vscode/webview-ui/src/types/messages/extension-messages.ts +++ b/packages/kilo-vscode/webview-ui/src/types/messages/extension-messages.ts @@ -496,12 +496,8 @@ export interface GlobalConfigLoadedMessage { export interface NotificationSettingsLoadedMessage { type: "notificationSettingsLoaded" settings: { - notifyAgent: boolean - notifyPermissions: boolean - notifyErrors: boolean - soundAgent: string - soundPermissions: string - soundErrors: string + attentionEnabled: boolean + attentionSound: string } } diff --git a/packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts b/packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts index 15b73c3fda..b47d1df7fe 100644 --- a/packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts +++ b/packages/kilo-vscode/webview-ui/src/types/messages/webview-messages.ts @@ -453,6 +453,11 @@ export interface RequestNotificationSettingsMessage { type: "requestNotificationSettings" } +export interface TestNotificationMessage { + type: "testNotification" + sound: string +} + export interface ResetAllSettingsRequest { type: "resetAllSettings" } @@ -1163,6 +1168,7 @@ export type WebviewMessage = | UpdateConfigMessage | OpenSettingsTabRequest | RequestNotificationSettingsMessage + | TestNotificationMessage | ResetAllSettingsRequest | SettingsTabChangedMessage | SyncSessionRequest diff --git a/packages/opencode/AGENTS.md b/packages/opencode/AGENTS.md index 565b93773c..dbd905e0f6 100644 --- a/packages/opencode/AGENTS.md +++ b/packages/opencode/AGENTS.md @@ -1,4 +1,4 @@ -# opencode agent guidelines +# Kilo CLI package guidelines ## Build/Test diff --git a/packages/opencode/script/run-workspace-server b/packages/opencode/script/run-workspace-server index 4371a15797..3953f1ae3d 100755 --- a/packages/opencode/script/run-workspace-server +++ b/packages/opencode/script/run-workspace-server @@ -1,11 +1,11 @@ #!/usr/bin/env bun -// This script runs a separate OpenCode server to be used as a remote +// This script runs a separate Kilo server to be used as a remote // kilocode_change // workspace, simulating a remote environment but all local to make // debugger easier // // *Important*: make sure you add the debug workspace plugin first. -// In `.opencode/opencode.jsonc` in the root of this project add: +// In `.kilo/kilo.jsonc` in the root of this project add: // kilocode_change // // "plugin": ["../packages/opencode/src/control-plane/dev/debug-workspace-plugin.ts"] // diff --git a/packages/opencode/specs/tui-plugins.md b/packages/opencode/specs/tui-plugins.md index f583642666..67eb9122b5 100644 --- a/packages/opencode/specs/tui-plugins.md +++ b/packages/opencode/specs/tui-plugins.md @@ -18,7 +18,7 @@ Example: ```json { - "$schema": "https://opencode.ai/tui.json", + "$schema": "https://app.kilo.ai/tui.json", "theme": "smoke-theme", "leader_timeout": 2000, "keybinds": { @@ -35,7 +35,7 @@ Example: "notifications": true, "sound": true, "volume": 0.4, - "sound_pack": "opencode.default", + "sound_pack": "kilo.default", "sounds": { "error": "/Users/me/sounds/error.mp3" } @@ -184,15 +184,15 @@ npm plugins can declare a version compatibility range in `package.json` using th } ``` -- The value is a semver range checked against the running OpenCode version. +- The value is a semver range checked against the running Kilo version. - If the range is not satisfied, the plugin is skipped with a warning and a session error. - If `engines.opencode` is absent, no check is performed (backward compatible). - File plugins are never checked; only npm package plugins are validated. - Install flow is shared by CLI and TUI in `src/plugin/install.ts`. - Shared helpers are `installPlugin`, `readPluginManifest`, and `patchPluginConfig`. -- `opencode plugin ` and TUI install both run install → manifest read → config patch. -- Alias: `opencode plug `. +- `kilo plugin ` and TUI install both run install → manifest read → config patch. +- Alias: `kilo plug `. - `-g` / `--global` writes into the global config dir. - Local installs resolve target dir inside `patchPluginConfig`. - For local scope, path is `/.opencode` only when VCS is git and `worktree !== "/"`; otherwise `/.opencode`. @@ -213,7 +213,7 @@ npm plugins can declare a version compatibility range in `package.json` using th - There is no uninstall, list, or update CLI command for external plugins. - Local file plugins are configured directly in `tui.json`. -When `plugin` entries exist in a writable `.opencode` dir or `KILO_CONFIG_DIR`, OpenCode installs `@kilocode/plugin` into that dir and writes: +When `plugin` entries exist in a writable `.opencode` dir or `KILO_CONFIG_DIR`, Kilo installs `@kilocode/plugin` into that dir and writes: - `package.json` - `bun.lock` @@ -246,7 +246,7 @@ Top-level API groups exposed to `tui(api, options, meta)`: ### Keymap - `api.keymap` exposes the raw `Keymap` instance from the host. -- The host already installs the default OpenTUI bundle (`default keys`, metadata fields, and enabled fields) plus OpenCode's comma bindings, leader token, base layout fallback, pending-sequence helpers, and managed textarea layer. +- The host already installs the default OpenTUI bundle (`default keys`, metadata fields, and enabled fields) plus Kilo's comma bindings, leader token, base layout fallback, pending-sequence helpers, and managed textarea layer. - Register commands with `api.keymap.registerLayer({ commands: [...] })`. - Register key bindings with `bindings: [{ key, cmd, desc }]` in the same layer or a separate layer. - Use `api.keymap.acquireResource(...)` for shared plugin addon setup that should ref-count against the host keymap. @@ -275,7 +275,7 @@ Top-level API groups exposed to `tui(api, options, meta)`: - `api.attention.soundboard.registerPack({ id, name?, sounds })` registers a sound pack and returns a disposer. Relative paths resolve from the plugin root and are cleaned up on plugin deactivation. - `api.attention.soundboard.activate(id, { persist })` selects the active pack. `persist: true` writes the selected pack id to TUI KV state, not `tui.json`. - `api.attention.soundboard.current()` and `list()` expose the active/registered packs for plugin UX. -- Config `attention.sounds` overrides active-pack sounds by slot. Failed loads fall back to the active pack and then `opencode.default`. +- Config `attention.sounds` overrides active-pack sounds by slot. Failed loads fall back to the active pack and then `kilo.default`. - The host strips ANSI/control characters and collapses newlines before sending text to the terminal notification API. - Terminal and OS settings decide whether a requested notification is visibly displayed. - Prefer privacy-safe messages such as `"A question needs your input"`; avoid full commands, paths, prompts, errors, secrets, or file contents unless the plugin intentionally exposes them. diff --git a/packages/opencode/src/auth/index.ts b/packages/opencode/src/auth/index.ts index 9779f7202c..de4375add8 100644 --- a/packages/opencode/src/auth/index.ts +++ b/packages/opencode/src/auth/index.ts @@ -5,7 +5,7 @@ import { Global } from "@opencode-ai/core/global" import { AppFileSystem } from "@opencode-ai/core/filesystem" import { Telemetry } from "@kilocode/kilo-telemetry" // kilocode_change -export const OAUTH_DUMMY_KEY = "opencode-oauth-dummy-key" +export const OAUTH_DUMMY_KEY = "kilo-oauth-dummy-key" // kilocode_change const file = path.join(Global.Path.data, "auth.json") diff --git a/packages/opencode/src/cli/cmd/providers.ts b/packages/opencode/src/cli/cmd/providers.ts index 00341e1912..8983fe4502 100644 --- a/packages/opencode/src/cli/cmd/providers.ts +++ b/packages/opencode/src/cli/cmd/providers.ts @@ -370,7 +370,6 @@ export const ProvidersLoginCommand = effectCmd({ // kilocode_change start const priority: Record = { kilo: 0, - opencode: 1, anthropic: 2, "github-copilot": 3, openai: 4, @@ -401,7 +400,6 @@ export const ProvidersLoginCommand = effectCmd({ value: x.id, hint: { kilo: "recommended", // kilocode_change - opencode: "recommended", openai: "ChatGPT login or API key", // kilocode_change }[x.id], })), @@ -457,7 +455,7 @@ export const ProvidersLoginCommand = effectCmd({ } yield* Prompt.log.warn( - `This only stores a credential for ${provider} - you will need configure it in opencode.json, check the docs for examples.`, + `This only stores a credential for ${provider} - you will need configure it in kilo.json, check the docs for examples.`, // kilocode_change ) } @@ -466,22 +464,18 @@ export const ProvidersLoginCommand = effectCmd({ "Amazon Bedrock authentication priority:\n" + " 1. Bearer token (AWS_BEARER_TOKEN_BEDROCK or /connect)\n" + " 2. AWS credential chain (profile, access keys, IAM roles, EKS IRSA)\n\n" + - "Configure via opencode.json options (profile, region, endpoint) or\n" + + "Configure via kilo.json options (profile, region, endpoint) or\n" + // kilocode_change "AWS environment variables (AWS_PROFILE, AWS_REGION, AWS_ACCESS_KEY_ID, AWS_WEB_IDENTITY_TOKEN_FILE).", ) } - if (provider === "opencode") { - yield* Prompt.log.info("Create an api key at https://opencode.ai/auth") - } - if (provider === "vercel") { yield* Prompt.log.info("You can create an api key at https://vercel.link/ai-gateway-token") } if (["cloudflare", "cloudflare-ai-gateway"].includes(provider)) { yield* Prompt.log.info( - "Cloudflare AI Gateway can be configured with CLOUDFLARE_GATEWAY_ID, CLOUDFLARE_ACCOUNT_ID, and CLOUDFLARE_API_TOKEN environment variables. Read more: https://opencode.ai/docs/providers/#cloudflare-ai-gateway", + "Cloudflare AI Gateway can be configured with CLOUDFLARE_GATEWAY_ID, CLOUDFLARE_ACCOUNT_ID, and CLOUDFLARE_API_TOKEN environment variables. Read more: https://kilo.ai/docs/ai-providers/cloudflare", // kilocode_change ) } diff --git a/packages/opencode/src/cli/cmd/tui/attention.ts b/packages/opencode/src/cli/cmd/tui/attention.ts index 3af7b2e64a..04adb495e4 100644 --- a/packages/opencode/src/cli/cmd/tui/attention.ts +++ b/packages/opencode/src/cli/cmd/tui/attention.ts @@ -40,14 +40,14 @@ type TuiAttentionHost = TuiAttention & { const log = Log.create({ service: "tui.attention" }) -const DEFAULT_TITLE = "opencode" -const DEFAULT_PACK_ID = "opencode.default" +const DEFAULT_TITLE = "Kilo" // kilocode_change +const DEFAULT_PACK_ID = "kilo.default" // kilocode_change const KV_SOUND_PACK = "attention_sound_pack" const TITLE_LIMIT = 80 const MESSAGE_LIMIT = 240 const BUILTIN_PACK: RegisteredSoundPack = { id: DEFAULT_PACK_ID, - name: "OpenCode Default", + name: "Kilo Default", // kilocode_change builtin: true, sounds: { default: defaultSoundPath, diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx index 163eedadce..3d15fce24c 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx @@ -48,12 +48,7 @@ export function providerOptions(list: { id: string; name: string }[]): ProviderO title: provider.name, value: provider.id, providerID: provider.id, - description: { - opencode: "(Recommended)", - anthropic: "(API key)", - openai: "(ChatGPT Plus/Pro or API key)", - "opencode-go": "Low cost subscription for everyone", - }[provider.id], + description: KiloProvider.PROVIDER_DESCRIPTIONS[provider.id], // kilocode_change category: provider.id in PROVIDER_PRIORITY ? "Popular" : "Providers", })), ), diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-retry-action.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-retry-action.tsx index 6e4db2a21a..84c88caf0c 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-retry-action.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-retry-action.tsx @@ -7,7 +7,7 @@ import { Link } from "@tui/ui/link" import { BgPulse } from "./bg-pulse" import { useBindings } from "../keymap" -const GO_URL = "https://opencode.ai/go" +const KILO_PRICING_URL = "https://kilo.ai/pricing" // kilocode_change const PAD_X = 3 const PAD_TOP_OUTER = 1 const FOREGROUND_ALPHA = 186 @@ -40,7 +40,7 @@ export function DialogRetryAction(props: DialogRetryActionProps) { const dialog = useDialog() const { theme } = useTheme() const fg = selectedForeground(theme) - const showGoTreatment = () => props.link === GO_URL + const showGoTreatment = () => props.link === KILO_PRICING_URL // kilocode_change const textBg = () => (showGoTreatment() ? panelOverlay(theme.backgroundPanel) : undefined) const [selected, setSelected] = createSignal<"dismiss" | "action">("action") diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx index 1be189658c..b42966dd8e 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx @@ -14,7 +14,6 @@ import { createDebouncedSignal } from "../util/signal" import { useToast } from "../ui/toast" import { openWorkspaceSelect, type WorkspaceSelection, warpWorkspaceSession } from "./dialog-workspace-create" import { Spinner } from "./spinner" -import path from "path" // kilocode_change import { errorMessage } from "@/util/error" import { DialogSessionDeleteFailed } from "./dialog-session-delete-failed" import { WorkspaceLabel } from "./workspace-label" @@ -31,7 +30,7 @@ export function DialogSessionList() { const toast = useToast() const [toDelete, setToDelete] = createSignal() const [search, setSearch] = createDebouncedSignal("", 150) - const [global, setGlobal] = createSignal(true) // kilocode_change - show all worktrees by default + const [global, setGlobal] = createSignal(false) // kilocode_change - show current worktree by default const deleteHint = useCommandShortcut("session.delete") const quickSwitch1 = useCommandShortcut("session.quick_switch.1") const quickSwitch9 = useCommandShortcut("session.quick_switch.9") @@ -39,15 +38,17 @@ export function DialogSessionList() { // kilocode_change start - always fetch from experimental endpoint (returns GlobalSession with worktree info) // TODO: extend /experimental/session to accept `scope`/`path` so this dialog can respect the // upstream `session_directory_filter_enabled` KV toggle (via sync.session.query()) while - // keeping worktree grouping. Currently the toggle has no effect here. + // keeping worktree grouping. const [searchResults, searchActions] = createResource( - () => search(), - async (query) => { + () => ({ query: search(), global: global(), directory: project.instance.directory() }), // kilocode_change + async (input) => { const result = await sdk.client.experimental.session.list( { - search: query || undefined, + search: input.query || undefined, roots: true, worktrees: true, + current: input.global ? undefined : "true", + directory: input.global ? undefined : input.directory || undefined, limit: 30, }, { throwOnError: true }, @@ -59,15 +60,7 @@ export function DialogSessionList() { const currentSessionID = createMemo(() => (route.data.type === "session" ? route.data.sessionID : undefined)) - // kilocode_change start - client-side worktree filtering when global is off - const sessions = createMemo(() => { - const all = searchResults() ?? [] - if (global()) return all - const root = project.instance.path().worktree - if (!root || root === "/") return all - return all.filter((s) => s.directory === root || s.directory.startsWith(root + path.sep)) - }) - // kilocode_change end + const sessions = createMemo(() => searchResults() ?? []) // kilocode_change - endpoint applies worktree scope function recover(session: NonNullable[number]>) { const workspace = project.workspace.get(session.workspaceID!) @@ -154,8 +147,6 @@ export function DialogSessionList() { .map((x) => x.id) } - const [browseOrder] = createSignal(orderByRecency(sync.data.session)) - const quickSwitchHint = createMemo(() => { const first = quickSwitch1() const last = quickSwitch9() @@ -176,8 +167,7 @@ export function DialogSessionList() { .map((x) => [x.id, x]), ) - const searchResult = searchResults() - const displayOrder = searchResult ? orderByRecency(searchResult) : browseOrder() + const displayOrder = orderByRecency(sessions()) // kilocode_change - respect current scope const pinned = local.session.pinned().filter((id) => sessionMap.has(id)) const pinnedSet = new Set(pinned) @@ -335,6 +325,7 @@ export function DialogSessionList() { { command: "session.scope.toggle", title: global() ? "current" : "all", + requiresSelection: false, onTrigger: async () => { setToDelete(undefined) setGlobal((v) => !v) diff --git a/packages/opencode/src/cli/cmd/tui/config/tui-migrate.ts b/packages/opencode/src/cli/cmd/tui/config/tui-migrate.ts index 2d44ebbe46..9dc3a9e837 100644 --- a/packages/opencode/src/cli/cmd/tui/config/tui-migrate.ts +++ b/packages/opencode/src/cli/cmd/tui/config/tui-migrate.ts @@ -12,7 +12,7 @@ import * as ConfigPaths from "@/config/paths" const log = Log.create({ service: "tui.migrate" }) -const TUI_SCHEMA_URL = "https://opencode.ai/tui.json" +const TUI_SCHEMA_URL = "https://app.kilo.ai/tui.json" // kilocode_change const decodeTheme = Schema.decodeUnknownOption(Schema.String) const decodeRecord = Schema.decodeUnknownOption(Schema.Record(Schema.String, Schema.Unknown)) diff --git a/packages/opencode/src/cli/cmd/tui/config/tui.ts b/packages/opencode/src/cli/cmd/tui/config/tui.ts index 0934295c36..d9ff1c293b 100644 --- a/packages/opencode/src/cli/cmd/tui/config/tui.ts +++ b/packages/opencode/src/cli/cmd/tui/config/tui.ts @@ -253,7 +253,7 @@ const loadState = Effect.fn("TuiConfig.loadState")(function* (ctx: { directory: notifications: acc.result.attention?.notifications ?? true, sound: acc.result.attention?.sound ?? true, volume: acc.result.attention?.volume ?? 0.4, - sound_pack: acc.result.attention?.sound_pack ?? "opencode.default", + sound_pack: acc.result.attention?.sound_pack ?? "kilo.default", // kilocode_change sounds: acc.result.attention?.sounds ?? {}, }, keybinds: createBindingLookup(TuiKeybind.toBindingConfig(parsedKeybinds), { diff --git a/packages/opencode/src/cli/cmd/tui/feature-plugins/home/tips-view.tsx b/packages/opencode/src/cli/cmd/tui/feature-plugins/home/tips-view.tsx index 3988fb2ff1..e060a7cb34 100644 --- a/packages/opencode/src/cli/cmd/tui/feature-plugins/home/tips-view.tsx +++ b/packages/opencode/src/cli/cmd/tui/feature-plugins/home/tips-view.tsx @@ -217,10 +217,10 @@ const TIPS: Tip[] = [ "Override any keybind in {highlight}tui.json{/highlight} via the {highlight}keybinds{/highlight} section", "Set any keybind to {highlight}none{/highlight} to disable it completely", "Configure local or remote MCP servers in the {highlight}mcp{/highlight} config section", - "Add {highlight}.md{/highlight} files to {highlight}.opencode/commands/{/highlight} to define reusable custom prompts", + "Add {highlight}.md{/highlight} files to {highlight}.kilo/command/{/highlight} to define reusable custom prompts", // kilocode_change "Use {highlight}$ARGUMENTS{/highlight}, {highlight}$1{/highlight}, {highlight}$2{/highlight} in custom commands for dynamic input", "Use backticks in commands to inject shell output (e.g., {highlight}`git status`{/highlight})", - "Add {highlight}.md{/highlight} files to {highlight}.opencode/agents/{/highlight} for specialized AI personas", + "Add {highlight}.md{/highlight} files to {highlight}.kilo/agent/{/highlight} for specialized AI personas", // kilocode_change "Configure per-agent permissions for {highlight}edit{/highlight}, {highlight}bash{/highlight}, and {highlight}webfetch{/highlight} tools", 'Use patterns like {highlight}"git *": "allow"{/highlight} for granular bash permissions', 'Set {highlight}"rm -rf *": "deny"{/highlight} to block destructive commands', @@ -229,9 +229,9 @@ const TIPS: Tip[] = [ 'Set {highlight}"formatter": false{/highlight} in config to disable formatters enabled by another config layer', "Define custom formatter commands with file extensions in config", 'Set {highlight}"lsp": true{/highlight} in config to enable built-in LSP servers for code analysis', - "Create {highlight}.ts{/highlight} files in {highlight}.opencode/tools/{/highlight} to define new LLM tools", + "Create {highlight}.ts{/highlight} files in {highlight}.kilo/tools/{/highlight} to define new LLM tools", // kilocode_change "Tool definitions can invoke scripts written in Python, Go, etc", - "Add {highlight}.ts{/highlight} files to {highlight}.opencode/plugins/{/highlight} for event hooks", + "Add {highlight}.ts{/highlight} files to {highlight}.kilo/plugins/{/highlight} for event hooks", // kilocode_change "Use plugins to send OS notifications when sessions complete", "Create a plugin to prevent Kilo from reading sensitive files", "Use {highlight}kilo run{/highlight} for non-interactive scripting", // kilocode_change @@ -243,12 +243,12 @@ const TIPS: Tip[] = [ "Run {highlight}kilo upgrade{/highlight} to update to the latest version", "Run {highlight}kilo auth list{/highlight} to see all configured providers", "Run {highlight}kilo agent create{/highlight} for guided agent creation", // kilocode_change - "Use {highlight}/opencode{/highlight} in GitHub issues/PRs to trigger AI actions", + "Use {highlight}/kilo{/highlight} in GitHub issues/PRs to trigger AI actions", // kilocode_change "Run {highlight}kilo github install{/highlight} to set up the GitHub workflow", // kilocode_change - "Comment {highlight}/opencode fix this{/highlight} on issues to auto-create PRs", + "Comment {highlight}/kilo fix this{/highlight} on issues to auto-create PRs", // kilocode_change "Comment {highlight}/oc{/highlight} on PR code lines for targeted code reviews", 'Use {highlight}"theme": "system"{/highlight} to match your terminal\'s colors', - "Create JSON theme files in {highlight}.opencode/themes/{/highlight} directory", + "Create JSON theme files in {highlight}.kilo/themes/{/highlight} directory", // kilocode_change "Themes support dark/light variants for both modes", "Use numeric xterm color codes 0-255 in custom theme JSON", "Use {highlight}{env:VAR_NAME}{/highlight} syntax to reference environment variables in config", diff --git a/packages/opencode/src/cli/cmd/tui/feature-plugins/sidebar/footer.tsx b/packages/opencode/src/cli/cmd/tui/feature-plugins/sidebar/footer.tsx index cb3ba451de..5a54455b6f 100644 --- a/packages/opencode/src/cli/cmd/tui/feature-plugins/sidebar/footer.tsx +++ b/packages/opencode/src/cli/cmd/tui/feature-plugins/sidebar/footer.tsx @@ -49,7 +49,9 @@ function View(props: { api: TuiPluginApi }) { ✕ - OpenCode includes free models so you can start immediately. + {/* kilocode_change start */} + Kilo includes free models so you can start immediately. + {/* kilocode_change end */} Connect from 75+ providers to use other models, including Claude, GPT, Gemini etc @@ -64,13 +66,11 @@ function View(props: { api: TuiPluginApi }) { {path().parent}/ {path().name} + {/* kilocode_change start */} - Open - - Code - {" "} - {props.api.app.version} + Kilo {props.api.app.version} + {/* kilocode_change end */} ) } diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx index 0f9214092e..07346125bf 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx @@ -87,13 +87,11 @@ export function Sidebar(props: { sessionID: string; overlay?: boolean }) { + {/* kilocode_change start */} - Open - - Code - {" "} - {InstallationVersion} + Kilo {InstallationVersion} + {/* kilocode_change end */} diff --git a/packages/opencode/src/cli/cmd/tui/thread.ts b/packages/opencode/src/cli/cmd/tui/thread.ts index 0a8c34865c..e4fd896dfd 100644 --- a/packages/opencode/src/cli/cmd/tui/thread.ts +++ b/packages/opencode/src/cli/cmd/tui/thread.ts @@ -84,12 +84,17 @@ async function input(value?: string) { } export function resolveThreadDirectory(project?: string, envPWD = process.env.PWD, cwd = process.cwd()) { - // kilocode_change start - ignore stale PWD from wrappers such as `bun --cwd` + // kilocode_change start - ignore stale PWD from wrappers such as `bun --cwd`, except kilo-dev's caller cwd + const dev = process.env.KILO_DEV_CWD const real = Filesystem.resolve(cwd) - const root = envPWD && Filesystem.resolve(envPWD) === real ? Filesystem.resolve(envPWD) : real + const root = dev + ? Filesystem.resolve(dev) + : envPWD && Filesystem.resolve(envPWD) === real + ? Filesystem.resolve(envPWD) + : real // kilocode_change end if (project) return Filesystem.resolve(path.isAbsolute(project) ? project : path.join(root, project)) - return real // kilocode_change + return dev ? root : real // kilocode_change } export const TuiThreadCommand = cmd({ diff --git a/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx b/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx index 700735d38c..a211155ce4 100644 --- a/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx +++ b/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx @@ -31,13 +31,7 @@ export interface DialogSelectProps { onSelect?: (option: DialogSelectOption) => void skipFilter?: boolean renderFilter?: boolean - actions?: { - command: string - title: string - side?: "left" | "right" - disabled?: boolean - onTrigger: (option: DialogSelectOption) => void - }[] + actions?: DialogSelectAction[] // kilocode_change - supports actions without a selected option footerHints?: { title: string label: string @@ -47,6 +41,27 @@ export interface DialogSelectProps { current?: T } +// kilocode_change start - support list-level actions when no option is selected +type DialogSelectActionBase = { + command: string + title: string + side?: "left" | "right" + disabled?: boolean +} + +type DialogSelectAction = DialogSelectActionBase & + ( + | { + requiresSelection?: true + onTrigger: (option: DialogSelectOption) => void + } + | { + requiresSelection: false + onTrigger: () => void + } + ) +// kilocode_change end + export interface DialogSelectOption { title: string value: T @@ -303,6 +318,12 @@ export function DialogSelect(props: DialogSelectProps) { category: "Dialog", run() { setStore("input", "keyboard") + // kilocode_change start - allow actions such as scope toggles on empty lists + if (item.requiresSelection === false) { + item.onTrigger() + return + } + // kilocode_change end const option = selected() if (!option) return item.onTrigger(option) diff --git a/packages/opencode/src/cli/cmd/uninstall.ts b/packages/opencode/src/cli/cmd/uninstall.ts index 6b32981443..18c5ca466e 100644 --- a/packages/opencode/src/cli/cmd/uninstall.ts +++ b/packages/opencode/src/cli/cmd/uninstall.ts @@ -8,6 +8,7 @@ import path from "path" import os from "os" import { Filesystem } from "@/util/filesystem" import { Process } from "@/util/process" +import { Brew as KiloBrew } from "@/kilocode/installation" // kilocode_change interface UninstallArgs { keepConfig: boolean @@ -133,7 +134,7 @@ async function showRemovalSummary(targets: RemovalTargets, method: Installation. pnpm: "pnpm uninstall -g @kilocode/cli", // kilocode_change bun: "bun remove -g @kilocode/cli", // kilocode_change yarn: "yarn global remove @kilocode/cli", // kilocode_change - brew: "brew uninstall opencode", + brew: `brew uninstall ${KiloBrew.name}`, // kilocode_change choco: "choco uninstall kilo", // kilocode_change scoop: "scoop uninstall kilo", // kilocode_change } @@ -184,7 +185,7 @@ async function executeUninstall(method: Installation.Method, targets: RemovalTar pnpm: ["pnpm", "uninstall", "-g", "@kilocode/cli"], // kilocode_change bun: ["bun", "remove", "-g", "@kilocode/cli"], // kilocode_change yarn: ["yarn", "global", "remove", "@kilocode/cli"], // kilocode_change - brew: ["brew", "uninstall", "opencode"], + brew: ["brew", "uninstall", KiloBrew.name], // kilocode_change choco: ["choco", "uninstall", "kilo"], // kilocode_change scoop: ["scoop", "uninstall", "kilo"], // kilocode_change } diff --git a/packages/opencode/src/cli/cmd/upgrade.ts b/packages/opencode/src/cli/cmd/upgrade.ts index 8aa6049d2c..67bd30b3e6 100644 --- a/packages/opencode/src/cli/cmd/upgrade.ts +++ b/packages/opencode/src/cli/cmd/upgrade.ts @@ -17,7 +17,7 @@ export const UpgradeCommand = { alias: "m", describe: "installation method to use", type: "string", - choices: ["curl", "npm", "pnpm", "bun", "brew", "choco", "scoop"], + choices: ["curl", "npm", "yarn", "pnpm", "bun", "brew", "choco", "scoop"], // kilocode_change }) }, handler: async (args: { target?: string; method?: string }) => { @@ -43,7 +43,7 @@ export const UpgradeCommand = { } } prompts.log.info("Using method: " + method) - const target = args.target ? args.target.replace(/^v/, "") : await Installation.latest() + const target = args.target ? args.target.replace(/^v/, "") : await Installation.latest(method) // kilocode_change if (InstallationVersion === target) { prompts.log.warn(`kilo upgrade skipped: ${target} is already installed`) // kilocode_change diff --git a/packages/opencode/src/cli/upgrade.ts b/packages/opencode/src/cli/upgrade.ts index 00ca70fb33..444c1edf2e 100644 --- a/packages/opencode/src/cli/upgrade.ts +++ b/packages/opencode/src/cli/upgrade.ts @@ -9,8 +9,8 @@ export async function upgrade() { const config = await AppRuntime.runPromise(Config.Service.use((cfg) => cfg.getGlobal())) if (config.autoupdate === false || Flag.KILO_DISABLE_AUTOUPDATE) return const method = await Installation.method() - // kilocode_change start - only auto-upgrade for npm/pnpm/bun (we only publish @kilocode/cli via npm registry) - if (method !== "npm" && method !== "pnpm" && method !== "bun") return + // kilocode_change start - only auto-upgrade for npm/yarn/pnpm/bun (we only publish @kilocode/cli via npm registry) + if (method !== "npm" && method !== "yarn" && method !== "pnpm" && method !== "bun") return // kilocode_change end const latest = await Installation.latest(method).catch(() => {}) if (!latest) return diff --git a/packages/opencode/src/command/template/initialize.txt b/packages/opencode/src/command/template/initialize.txt index 90751e3d6f..a403dac904 100644 --- a/packages/opencode/src/command/template/initialize.txt +++ b/packages/opencode/src/command/template/initialize.txt @@ -1,6 +1,6 @@ Create or update `AGENTS.md` for this repository. -The goal is a compact instruction file that helps future OpenCode sessions avoid mistakes and ramp up quickly. Every line should answer: "Would an agent likely miss this without help?" If not, leave it out. +The goal is a compact instruction file that helps future Kilo sessions avoid mistakes and ramp up quickly. Every line should answer: "Would an agent likely miss this without help?" If not, leave it out. User-provided focus or constraints (honor these): $ARGUMENTS @@ -12,7 +12,7 @@ Read the highest-value sources first: - build, test, lint, formatter, typecheck, and codegen config - CI workflows and pre-commit / task runner config - existing instruction files (`AGENTS.md`, `CLAUDE.md`, `.cursor/rules/`, `.cursorrules`, `.github/copilot-instructions.md`) -- repo-local OpenCode config such as `opencode.json` +- repo-local Kilo config such as `kilo.json` If architecture is still unclear after reading config and docs, inspect a small number of representative code files to find the real entrypoints, package boundaries, and execution flow. Prefer reading the files that explain how the system is wired together over random leaf files. @@ -57,7 +57,7 @@ Exclude: - long tutorials or exhaustive file trees - obvious language conventions - speculative claims or anything you could not verify -- content better stored in another file referenced via `opencode.json` `instructions` +- content better stored in another file referenced via `kilo.json` `instructions` When in doubt, omit. diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index 457bfc9b04..440fb4aa4a 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -163,7 +163,7 @@ export const Info = Schema.Struct({ description: "Server configuration for the kilo serve command", // kilocode_change }), command: Schema.optional(Schema.Record(Schema.String, ConfigCommand.Info)).annotate({ - description: "Command configuration, see https://opencode.ai/docs/commands", + description: "Command configuration, see https://kilo.ai/docs/customize/workflows", // kilocode_change }), skills: Schema.optional(ConfigSkills.Info).annotate({ description: "Additional skill folder paths" }), reference: Schema.optional(ConfigReference.Info).annotate({ @@ -285,7 +285,7 @@ export const Info = Schema.Struct({ [Schema.Record(Schema.String, ConfigAgent.Info)], ), // kilocode_change start - ).annotate({ description: "Agent configuration, see https://opencode.ai/docs/agents" }), + ).annotate({ description: "Agent configuration, see https://kilo.ai/docs/customize/custom-subagents" }), // kilocode_change provider: Schema.optional(Schema.Record(Schema.String, Schema.NullOr(ConfigProvider.Info))).annotate({ // kilocode_change end description: "Custom provider configurations and model overrides", diff --git a/packages/opencode/src/control-plane/dev/README.md b/packages/opencode/src/control-plane/dev/README.md index 74d68a75a8..3f015b1ae7 100644 --- a/packages/opencode/src/control-plane/dev/README.md +++ b/packages/opencode/src/control-plane/dev/README.md @@ -1,16 +1,16 @@ -This is a plugin to simulate a remote environment locally. Add this to `.opencode/opencode.jsonc`: +This is a plugin to simulate a remote environment locally. Add this to `.kilo/kilo.jsonc`: ```json "plugin": ["../packages/opencode/src/control-plane/dev/debug-workspace-plugin.ts"], ``` -In a separate terminal, run a separate OpenCode server. This will act like a remote server and the local instance will proxy all requests to it: +In a separate terminal, run a separate Kilo server. This will act like a remote server and the local instance will proxy all requests to it: ``` ./packages/opencode/script/run-workspace-server ``` -With the plugin install, you can now run OpenCode and create a `debug` workspace type. This will create a "remote" workspace which talks to the second workspace server started above. +With the plugin install, you can now run Kilo and create a `debug` workspace type. This will create a "remote" workspace which talks to the second workspace server started above. How this works: diff --git a/packages/opencode/src/effect/bridge.ts b/packages/opencode/src/effect/bridge.ts index 46ba454d37..c608d83974 100644 --- a/packages/opencode/src/effect/bridge.ts +++ b/packages/opencode/src/effect/bridge.ts @@ -34,7 +34,8 @@ function captureSync() { export const bind = (fn: (...args: Args) => Result) => { const captured = captureSync() return (...args: Args) => - restore(captured.instance, captured.workspace, () => // kilocode_change + restore(captured.instance, captured.workspace, () => + // kilocode_change Effect.runSync( attachWith( Effect.sync(() => fn(...args)), diff --git a/packages/opencode/src/installation/index.ts b/packages/opencode/src/installation/index.ts index 9b0e06c4af..6a8ef1e3d1 100644 --- a/packages/opencode/src/installation/index.ts +++ b/packages/opencode/src/installation/index.ts @@ -11,6 +11,15 @@ import { makeRuntime } from "@opencode-ai/core/effect/runtime" import semver from "semver" import { InstallationChannel, InstallationVersion } from "@opencode-ai/core/installation/version" import { NpmConfig } from "@opencode-ai/core/npm-config" +// kilocode_change start +import { + Brew as KiloBrew, + Choco as KiloChoco, + Npm as KiloNpm, + Release as KiloRelease, + Scoop as KiloScoop, +} from "@/kilocode/installation" +// kilocode_change end const log = Log.create({ service: "installation" }) @@ -51,7 +60,7 @@ export const Info = Schema.Struct({ export type Info = Schema.Schema.Type export function userAgent(client = "cli") { - return `opencode/${InstallationChannel}/${InstallationVersion}/${client}` + return `kilo/${InstallationChannel}/${InstallationVersion}/${client}` // kilocode_change } export const USER_AGENT = userAgent() @@ -129,15 +138,15 @@ export const layer: Layer.Layer text(["yarn", "global", "list"]) }, { name: "pnpm", command: () => text(["pnpm", "list", "-g", "--depth=0"]) }, { name: "bun", command: () => text(["bun", "pm", "ls", "-g"]) }, - { name: "brew", command: () => text(["brew", "list", "--formula", "opencode"]) }, - { name: "scoop", command: () => text(["scoop", "list", "opencode"]) }, - { name: "choco", command: () => text(["choco", "list", "--limit-output", "opencode"]) }, + { name: "brew", command: () => text(["brew", "list", "--formula", KiloBrew.formula]) }, // kilocode_change + { name: "scoop", command: () => text(["scoop", "list", KiloScoop.name]) }, // kilocode_change + { name: "choco", command: () => text(["choco", "list", "--limit-output", KiloChoco.name]) }, // kilocode_change ] checks.sort((a, b) => { @@ -186,8 +196,16 @@ export const layer: Layer.Layer] -type Req = { - resolve: (id: string) => string -} - -type LogLike = { - debug: (msg: string, data?: Record) => void +export function isAtomicChatPlugin(item: PluginSpec): boolean { + const spec = typeof item === "string" ? item : item[0] + const parsed = parsePluginSpecifier(spec) + if (!parsed.version.startsWith("npm:")) return parsed.pkg === ATOMIC_CHAT_PLUGIN + if (!parsed.version.startsWith(`npm:${ATOMIC_CHAT_PLUGIN}`)) return false + const version = parsed.version.slice(`npm:${ATOMIC_CHAT_PLUGIN}`.length) + return version === "" || version.startsWith("@") } export function hasAtomicChatPlugin(plugins: readonly PluginSpec[]): boolean { - return plugins.some((item) => { - const spec = typeof item === "string" ? item : item[0] - return spec.includes("plugin-atomic-chat") || spec === ATOMIC_CHAT_PLUGIN - }) + return plugins.some(isAtomicChatPlugin) } -export function resolveAtomicChatPlugin(req: Req, log?: LogLike): string { - try { - const file = req.resolve(ATOMIC_CHAT_PLUGIN) - return pathToFileURL(file).href - } catch (err) { - const error = err instanceof Error ? err.message : String(err) - log?.debug("failed to resolve atomic chat plugin package, using package marker", { error }) - return ATOMIC_CHAT_PLUGIN - } -} - -export function ensureAtomicChatPlugin(items: readonly PluginSpec[], plugin?: string): PluginSpec[] { +export function ensureAtomicChatPlugin(items: readonly PluginSpec[]): PluginSpec[] { const plugins = [...items] - if (!plugin) return plugins if (hasAtomicChatPlugin(plugins)) return plugins - return [...plugins, plugin] + return [...plugins, ATOMIC_CHAT_PLUGIN] } diff --git a/packages/opencode/src/kilocode/cli/cmd/tui/context/tui-config.tsx b/packages/opencode/src/kilocode/cli/cmd/tui/context/tui-config.tsx index 5a667fe693..bb9ac401c6 100644 --- a/packages/opencode/src/kilocode/cli/cmd/tui/context/tui-config.tsx +++ b/packages/opencode/src/kilocode/cli/cmd/tui/context/tui-config.tsx @@ -30,7 +30,7 @@ export namespace KiloTuiConfig { notifications: next.attention?.notifications ?? true, sound: next.attention?.sound ?? true, volume: next.attention?.volume ?? 0.4, - sound_pack: next.attention?.sound_pack ?? "opencode.default", + sound_pack: next.attention?.sound_pack ?? "kilo.default", sounds: next.attention?.sounds ?? {}, }, keybinds: createBindingLookup(TuiKeybind.toBindingConfig(keybinds), { diff --git a/packages/opencode/src/kilocode/components/dialog-indexing.tsx b/packages/opencode/src/kilocode/components/dialog-indexing.tsx index f3b6bf4cd8..869fc0ca12 100644 --- a/packages/opencode/src/kilocode/components/dialog-indexing.tsx +++ b/packages/opencode/src/kilocode/components/dialog-indexing.tsx @@ -59,7 +59,7 @@ const PROVIDER_FIELDS: Record = { ollama: [{ key: "baseUrl", label: "Base URL", placeholder: "http://localhost:11434" }], "openai-compatible": [ { key: "baseUrl", label: "Base URL", placeholder: "https://api.example.com/v1" }, - { key: "apiKey", label: "API Key", placeholder: "sk-...", sensitive: true }, + { key: "apiKey", label: "API Key (optional)", placeholder: "sk-...", sensitive: true }, ], gemini: [{ key: "apiKey", label: "API Key", placeholder: "AI...", sensitive: true }], mistral: [{ key: "apiKey", label: "API Key", placeholder: "...", sensitive: true }], diff --git a/packages/opencode/src/kilocode/components/dialog-kilo-notifications.tsx b/packages/opencode/src/kilocode/components/dialog-kilo-notifications.tsx index 63657146ad..9915c371fc 100644 --- a/packages/opencode/src/kilocode/components/dialog-kilo-notifications.tsx +++ b/packages/opencode/src/kilocode/components/dialog-kilo-notifications.tsx @@ -86,6 +86,11 @@ export function DialogKiloNotifications(props: DialogKiloNotificationsProps) { + + dialog.clear()}> + close + + ) } diff --git a/packages/opencode/src/kilocode/components/kilo-news.tsx b/packages/opencode/src/kilocode/components/kilo-news.tsx index 6c5508de45..6b0f592049 100644 --- a/packages/opencode/src/kilocode/components/kilo-news.tsx +++ b/packages/opencode/src/kilocode/components/kilo-news.tsx @@ -9,24 +9,28 @@ import { createEffect, createMemo, createSignal, on, Show } from "solid-js" import { useSync } from "@tui/context/sync" import { useSDK } from "@tui/context/sdk" import { useDialog } from "@tui/ui/dialog" +import { useKV } from "@tui/context/kv" import type { KilocodeNotification } from "@kilocode/kilo-gateway" import { NotificationBanner } from "./notification-banner.js" import { DialogKiloNotifications } from "./dialog-kilo-notifications.js" +import { News } from "./news.js" export function KiloNews() { const sync = useSync() const sdk = useSDK() const dialog = useDialog() + const kv = useKV() const [notifications, setNotifications] = createSignal([]) const [fetched, setFetched] = createSignal(false) const isKiloConnected = createMemo(() => sync.data.provider_next.connected.includes("kilo")) + const unread = createMemo(() => News.unread(notifications(), kv.get(News.key, []))) const openNewsDialog = () => { - const items = notifications() - if (items.length > 0) { - dialog.replace(() => ) - } + const items = unread() + if (items.length === 0) return + dialog.replace(() => ) + kv.set(News.key, News.read(items, kv.get(News.key, []))) } // Reactively wait for sync to complete, then fetch notifications once @@ -53,12 +57,8 @@ export function KiloNews() { // The banner content appears once notifications are loaded; the fixed-height // placeholder keeps the surrounding elements stable during the async fetch. return ( - 0} fallback={}> - + 0} fallback={}> + ) } diff --git a/packages/opencode/src/kilocode/components/news.ts b/packages/opencode/src/kilocode/components/news.ts new file mode 100644 index 0000000000..26c53b8583 --- /dev/null +++ b/packages/opencode/src/kilocode/components/news.ts @@ -0,0 +1,19 @@ +import type { KilocodeNotification } from "@kilocode/kilo-gateway" + +export namespace News { + export const key = "news_read_ids" + + function ids(value: unknown) { + if (!Array.isArray(value)) return [] + return value.filter((id): id is string => typeof id === "string") + } + + export function unread(items: KilocodeNotification[], value: unknown) { + const read = new Set(ids(value)) + return items.filter((item) => !read.has(item.id)) + } + + export function read(items: KilocodeNotification[], value: unknown) { + return [...new Set([...ids(value), ...items.map((item) => item.id)])] + } +} diff --git a/packages/opencode/src/kilocode/config/default-plugins.ts b/packages/opencode/src/kilocode/config/default-plugins.ts index 6829a9efb7..2c535c8e48 100644 --- a/packages/opencode/src/kilocode/config/default-plugins.ts +++ b/packages/opencode/src/kilocode/config/default-plugins.ts @@ -1,7 +1,7 @@ import { createRequire } from "module" import { ConfigPlugin } from "@/config/plugin" import { isIndexingPlugin } from "@kilocode/kilo-indexing/detect" -import { ensureAtomicChatPlugin, resolveAtomicChatPlugin } from "@/kilocode/atomic-chat-feature" +import { ensureAtomicChatPlugin, isAtomicChatPlugin } from "@/kilocode/atomic-chat-feature" import { ensureIndexingPlugin, resolveIndexingPlugin } from "@/kilocode/indexing-feature" type Log = { @@ -19,12 +19,14 @@ export namespace KilocodeDefaultPlugins { if (!opts.disabled) { plugins = ensureIndexingPlugin(plugins, resolveIndexingPlugin(req, opts.log)) - plugins = ensureAtomicChatPlugin(plugins, resolveAtomicChatPlugin(req, opts.log)) + plugins = ensureAtomicChatPlugin(plugins) } cfg.plugin = plugins - // Built-in indexing is not loaded through external plugins and must not wait for their setup. - const origins = cfg.plugin_origins?.filter((item) => !isIndexingPlugin(item.spec)) + // Built-in plugins are not loaded externally and must not wait for external plugin setup. + const origins = cfg.plugin_origins?.filter( + (item) => !isIndexingPlugin(item.spec) && !isAtomicChatPlugin(item.spec), + ) if (!origins) return cfg if (opts.disabled) { cfg.plugin_origins = origins @@ -34,6 +36,7 @@ export namespace KilocodeDefaultPlugins { cfg.plugin_origins = [ ...origins, ...plugins + .filter((spec) => !isIndexingPlugin(spec) && !isAtomicChatPlugin(spec)) .filter((spec) => !known.has(ConfigPlugin.pluginSpecifier(spec))) .map((spec) => ({ spec, source: "builtin", scope: "global" as const })), ] diff --git a/packages/opencode/src/kilocode/installation/index.ts b/packages/opencode/src/kilocode/installation/index.ts new file mode 100644 index 0000000000..ac2a39c46c --- /dev/null +++ b/packages/opencode/src/kilocode/installation/index.ts @@ -0,0 +1,26 @@ +export const Npm = { + name: "@kilocode/cli", + path: "@kilocode%2fcli", +} + +export const Brew = { + name: "kilo", + tap: "Kilo-Org/tap", + formula: "Kilo-Org/tap/kilo", + api: "https://formulae.brew.sh/api/formula/kilo.json", +} + +export const Choco = { + name: "kilo", + api: "https://community.chocolatey.org/api/v2/Packages?$filter=Id%20eq%20%27kilo%27%20and%20IsLatestVersion&$select=Version", +} + +export const Scoop = { + name: "kilo", + manifest: "https://raw.githubusercontent.com/ScoopInstaller/Main/master/bucket/kilo.json", +} + +export const Release = { + api: "https://api.github.com/repos/Kilo-Org/kilocode/releases/latest", + install: "https://kilo.ai/install", +} diff --git a/packages/opencode/src/kilocode/server/httpapi/handlers/config-console.ts b/packages/opencode/src/kilocode/server/httpapi/handlers/config-console.ts index 36796f1a6e..0ffd2cef99 100644 --- a/packages/opencode/src/kilocode/server/httpapi/handlers/config-console.ts +++ b/packages/opencode/src/kilocode/server/httpapi/handlers/config-console.ts @@ -79,8 +79,9 @@ export const configConsoleHandlers = HttpApiBuilder.group(InstanceHttpApi, "conf return yield* config.get() } if (body.scope === "global") { - const result = yield* config.updateGlobal(patch) - if (result.changed) { + const hot = Object.keys(patch).every((key) => key === "console") + const result = yield* config.updateGlobal(patch, hot ? { dispose: false } : undefined) + if (result.changed && !hot) { yield* disposeAllInstancesAndEmitGlobalDisposed({ swallowErrors: true }).pipe( Effect.catchCause(() => Effect.void), ) diff --git a/packages/opencode/src/kilocode/session/compaction-chunks.ts b/packages/opencode/src/kilocode/session/compaction-chunks.ts index ea0b49cff9..e040d87470 100644 --- a/packages/opencode/src/kilocode/session/compaction-chunks.ts +++ b/packages/opencode/src/kilocode/session/compaction-chunks.ts @@ -63,12 +63,7 @@ export namespace KiloCompactionChunks { return input.result === "stop" && input.error?.name === "ContextOverflowError" } - export function needed(input: { - cfg: Config.Info - model: Provider.Model - tokens: number - outputTokenMax?: number - }) { + export function needed(input: { cfg: Config.Info; model: Provider.Model; tokens: number; outputTokenMax?: number }) { const mdl = model(input.model, input.outputTokenMax) // Apply 1.3x multiplier to token estimate to compensate for Token.estimate // under-counting actual provider tokenizer counts by ~15-30%. diff --git a/packages/opencode/src/kilocode/session/index.ts b/packages/opencode/src/kilocode/session/index.ts index 086db38c0a..3899296bcc 100644 --- a/packages/opencode/src/kilocode/session/index.ts +++ b/packages/opencode/src/kilocode/session/index.ts @@ -17,6 +17,7 @@ import type { Provider } from "@/provider/provider" import { zod as toZod } from "@opencode-ai/core/effect-zod" import { ENV_FEATURE } from "@kilocode/kilo-gateway" import { fn } from "@/kilocode/fn" +import path from "path" export namespace KiloSession { const log = Log.create({ service: "session.kilo" }) @@ -316,6 +317,7 @@ export namespace KiloSession { projectID?: string directory?: string directories?: string[] + currentDirectory?: string roots?: boolean start?: number cursor?: number @@ -360,6 +362,19 @@ export namespace KiloSession { const limit = input.limit ?? 100 const dirs = [...new Set((input.directories ?? []).map((dir) => Filesystem.resolve(dir)))] + const sorted = [...dirs].sort((a, b) => b.length - a.length) + const worktree = (dir: string) => { + for (const root of sorted) { + if (!Filesystem.contains(root, dir)) continue + const rel = path.relative(root, dir) + const parts = rel.split(path.sep) + if ((parts[0] === ".kilo" || parts[0] === ".kilocode") && parts[1] === "worktrees" && parts[2]) { + return path.join(root, parts[0], parts[1], parts[2]) + } + return root + } + } + const current = input.currentDirectory ? worktree(Filesystem.resolve(input.currentDirectory)) : undefined const rows = Database.use((db) => { const query = @@ -377,7 +392,10 @@ export namespace KiloSession { dirs.length > 0 ? rows.filter((row) => { const dir = Filesystem.resolve(row.directory) - return dirs.some((root) => Filesystem.contains(root, dir)) + const root = worktree(dir) + if (!root) return false + if (input.currentDirectory) return root === current + return true }) : rows diff --git a/packages/opencode/src/kilocode/session/native-plan-prompt.txt b/packages/opencode/src/kilocode/session/native-plan-prompt.txt new file mode 100644 index 0000000000..f6cfdf2ece --- /dev/null +++ b/packages/opencode/src/kilocode/session/native-plan-prompt.txt @@ -0,0 +1,47 @@ + +# Native Plan Mode + +You are Kilo Code, an experienced technical leader who is inquisitive, skeptical, and an excellent planner. + +Your job is to gather context, challenge assumptions, resolve design questions, and produce an implementation-ready plan that another agent can execute. You do not implement source-code changes. + +## Planning Behavior + +- Inspect the codebase and available local context before asking questions that can be answered without the user. +- Interview the user about every important aspect of the plan until you reach shared understanding. +- Walk down each branch of the design tree, resolving dependencies between decisions one by one. +- Ask one question at a time, and include your recommended answer. +- Continue until the important decisions are resolved or explicitly marked out of scope. +- Challenge vague or overloaded terms such as "user", "account", "tenant", "job", "workflow", "session", or "state" until their meaning is precise in this codebase. +- Cross-check user claims against the actual code and available context. If they conflict, call out the contradiction directly. +- Use concrete scenarios and edge cases to test the proposed design. +- Prefer short, actionable plans over long speculative documents. +- Never provide level-of-effort estimates such as hours, days, or weeks. + +## Plan Files + +- You may create and edit plan Markdown files only. +- Follow the latest Plan File reminder for the target plan location. +- If no exact plan file path is provided, follow the latest Plan File reminder for the directory and generated filename pattern. +- Use repo-root `plans/`, `.plans/`, or `.opencode/plans/` only when requested or required by the repo/client and your permissions allow it. +- Do not write the final plan or call `plan_exit` until the user chooses "Finalize and save the plan". +- After final approval, write the final plan to the chosen plan file, then call `plan_exit` with the saved plan path. +- Do not edit source files or non-plan documentation files. +- Do not run mutating commands. +- If implementation requires source edits or mutating commands, tell the user to switch to an implementation-capable agent. + +## Completion Behavior + +- Keep planning until the important design decisions are resolved or explicitly marked out of scope. +- If material uncertainty remains, keep the plan open: summarize the current state, identify the most important unresolved decision, and ask exactly one next question with your recommended answer. +- If the plan is implementation-ready but not saved, do not print the full plan in chat. Give a concise draft-ready summary, then ask exactly one question with these choices: + 1. Finalize and save the plan + 2. Continue refining +- Recommend "Finalize and save the plan" only when the goal, constraints, affected boundaries, data flow, failure modes, rollout or migration path, and validation plan are addressed or explicitly out of scope. +- If the user chooses "Finalize and save the plan", write the complete finalized Markdown plan to the chosen plan file, then call `plan_exit` as described above. +- If the user chooses "Continue refining", keep planning and do not write the final plan or call `plan_exit`. +- After `plan_exit`, rely on the client follow-up to ask whether the user wants to implement the saved plan in a new session. +- Do not implement source or documentation changes as this agent. + +Saved plans should be concise and actionable. Prefer a clear ordered task list over a lengthy design document. Include only the context, decisions, risks, validation steps, and open questions another implementation-capable agent needs to execute safely. + diff --git a/packages/opencode/src/kilocode/session/prompt.ts b/packages/opencode/src/kilocode/session/prompt.ts index 90e33619f9..2200e4089f 100644 --- a/packages/opencode/src/kilocode/session/prompt.ts +++ b/packages/opencode/src/kilocode/session/prompt.ts @@ -20,7 +20,7 @@ import { environmentDetails, type EditorContext } from "@/kilocode/editor-contex import { Identifier } from "@/id/id" import { Filesystem } from "@/util/filesystem" import { InstanceState } from "@/effect/instance-state" -import PROMPT_PLAN from "@/session/prompt/plan.txt" +import NATIVE_PLAN_PROMPT from "@/kilocode/session/native-plan-prompt.txt" import CODE_SWITCH from "@/session/prompt/code-switch.txt" export namespace KiloSessionPrompt { @@ -282,36 +282,23 @@ export namespace KiloSessionPrompt { const ctx = Instance.bind(() => Instance.current)() const plan = Session.plan(input.session, ctx) - if (mode(input.agent.name) === "plan") { - add( - [ - PROMPT_PLAN, - "", - "## Plan File", - "Use the plan path specified by the user or project instructions when present and permissions allow it.", - "If none is specified, create a plan in .kilo/plans/ using a concise kebab-case filename based on the plan details.", - "Do not choose .kilo/plans/ when instructions specify an allowed plan path such as .plans/.", - "You may write/edit plan Markdown files only. Do not edit source files.", - "When finalizing, call plan_exit with the path of the plan file you wrote.", - ].join("\n"), - ) - return - } + if (mode(input.agent.name) === "plan") add(NATIVE_PLAN_PROMPT) const file = input.messages ? PlanFile.latest(input.messages) : undefined const saved = PlanFile.resolve(file, ctx) const target = saved ?? plan + const time = input.session.time.created const dir = path.dirname(target) if (saved && !(await Filesystem.exists(target))) await ensurePlanDir(dir) const info = saved ? `The current saved plan file is ${target}. Read and edit this file when refining the plan.` - : `Use the plan path specified by the user or project instructions when present and permissions allow it. If none is specified, create a plan in ${dir} using a concise kebab-case filename based on the plan details.` + : `Use any exact plan file path from user or project instructions unchanged. If only a directory is specified, create the plan there; otherwise create it in ${dir}. For generated filenames, use ${time}-.md, choosing the suffix from the plan details, for example ${time}-database-cache-plan.md.` const body = [ "## Plan File", info, "Use the chosen plan path as the main plan file. Do not write or edit other files unless the user explicitly asks and your permissions allow it.", - "Project/user instructions about plan location (for example .plans/) are authorized when permissions allow them; they do not conflict with this reminder. When finalizing, call plan_exit with the path of the plan file you wrote.", + "Project/user instructions about plan location (for example plans/ or .plans/) are authorized when permissions allow them; they do not conflict with this reminder. When finalizing, call plan_exit with the path of the plan file you wrote.", 'Before creating or updating the plan file, or calling plan_exit, ask the user to choose exactly one of: "Finalize and save the plan" or "Continue refining". If the user chooses to finalize, write the main plan file, then call plan_exit.', ].join("\n") add(`\n${body}\n`) diff --git a/packages/opencode/src/plugin/digitalocean.ts b/packages/opencode/src/plugin/digitalocean.ts index e94cee93cb..16feb58ffc 100644 --- a/packages/opencode/src/plugin/digitalocean.ts +++ b/packages/opencode/src/plugin/digitalocean.ts @@ -14,7 +14,7 @@ const OAUTH_PORT = 1456 const OAUTH_REDIRECT_PATH = "/auth/callback" const OAUTH_TOKEN_PATH = "/auth/token" const ROUTER_REFRESH_INTERVAL_MS = 5 * 60 * 1000 -const MAK_NAME_PREFIX = "opencode-oauth" +const MAK_NAME_PREFIX = "kilo-oauth" // kilocode_change interface ImplicitTokenPayload { access_token: string @@ -65,11 +65,12 @@ function buildAuthorizeUrl(state: string): string { return `${DO_AUTHORIZE_URL}?${params.toString()}` } +// kilocode_change start - Kilo branding for the DigitalOcean OAuth callback page const HTML_CALLBACK = ` - OpenCode - DigitalOcean Authorization + Kilo - DigitalOcean Authorization