* revert: roll back workspace trust-boundary hardening
Roll back the hardening added in #3964 that guarded against malicious
content inside an already-trusted repository:
- background git invocations no longer override repo-local git config
(fsmonitor, hooksPath, filters, drivers, gpg, editor)
- agent file tools no longer re-resolve paths through symlinks
- project-local local.toml applies without workspace-trust gating,
additional_dir entries are no longer rejected for resolving to the
home directory or filesystem root, and writing it is auto-approved
again inside a git worktree
Kept, since they only affect the pre-trust window or the trust prompt
itself: the fail-closed trust prompt and lazy footer git detection.
* Update revert-trust-boundary-hardening.md
Signed-off-by: 7Sageer <sag77r@hotmail.com>
---------
Signed-off-by: 7Sageer <sag77r@hotmail.com>
* docs(changelog): sync 2.1.0 from apps/kimi-code/CHANGELOG.md
* docs(changelog): shorten the fullscreen TUI entry to how to enable it
* docs(changelog): reword the fullscreen TUI entry
* fix(remote-control): pick credential slot and relay from login region
Global login stores tokens in kimi-code-env-*.json and should use
code-rc.kimi.ai; Remote Control always read kimi-code.json and
code-rc.kimi.com. Resolve both from the persisted oauth ref.
* fix(telemetry): skip the dead global collector and keep shutdown alive
The global collector host has no DNS. Drop it from the region profile and
skip the send instead of falling back to the mainland endpoint. Keep the
shutdown timeout timer referenced so a failed flush cannot exit before the
TUI hands the process to the foreground server.
* fix(remote-control): require explicit relay origin and drop hardcoded .com defaults
* feat(agent-core-v2): add repeat_breaker config switch
Add a top-level repeat_breaker boolean (default true) to config.toml,
overridable with the KIMI_CODE_REPEAT_BREAKER env var. When disabled,
the agent skips repeat reminders and forced stops on consecutively
repeated identical tool calls; same-step dedupe is unaffected.
* Update repeat-breaker-config-switch.md
Signed-off-by: 7Sageer <sag77r@hotmail.com>
* feat(agent-core-v2): add tool_dedupe config switch
* refactor(agent-core-v2): drop the tool_dedupe config switch
Same-step dedupe stays always on. repeat_breaker remains the only public switch.
* refactor(agent-core-v2): read the repeat breaker from the environment only
KIMI_CODE_REPEAT_BREAKER is the only switch. Unset keeps reminders and forced stops on.
---------
Signed-off-by: 7Sageer <sag77r@hotmail.com>
* fix(kap-server): reject malformed and null Origins
isOriginAllowed conflated an unparseable Origin header with an absent
one and allowed both, so a sandboxed document (Origin: null) passed the
WebSocket upgrade check and had its Origin echoed by the CORS hook.
An absent Origin is still allowed for non-browser clients, but a
present Origin that fails to parse, is null, or uses a non-http(s)
scheme is now rejected: the WS upgrade responds 403 and the CORS hook
withholds Access-Control-Allow-Origin.
* fix(kimi-code): sync web bundle for kimi_origin query gating
* fix(agent-core-v2): gate workspace local.toml behind trust and tighten additional_dir
* fix(agent-core-v2): block symlink escapes in agent file tools
* fix: harden background git invocations against repo-local config
* fix(agent-core-v2): close trust-gate gaps in add-dir and additional_dir validation
* fix: neutralize repo-configured clean and process filters in hardened git calls
* fix(agent-core-v2): fail closed when a path is too deep to verify
* fix: probe worktree-scoped filter config in hardened git calls
* fix: fail closed when git filter discovery fails and cache probes for repo subdirectories
* fix(agent-core-v2): block symlink aliases of the project-local config in write tools
* fix: neutralize smudge, merge drivers, and repo-controlled commit signing in hardened git calls
* fix: expand included git configs when discovering repo-defined drivers
* Revert "fix(kimi-code): sync web bundle for kimi_origin query gating"
This reverts commit cd6af49cf1dfebe505f0e890453c3207a74d3e80.
* fix: keep git hardening fail-closed on includes and probe failures in scanners
* fix: fail closed on uncodable driver names and disable repo-controlled signature verification
* fix: neutralize repo-controlled editors and match include sections case-insensitively
* fix: probe config names only and reject dangling symlinks in file tools
* fix: fail closed when core.worktree escapes the repository
* fix(agent-core-v2): match project config paths across separators and case
* fix: arm footer git only after workspace trust persists
* fix(agent-core-v2): check resolved sensitive targets for absolute outside paths
* fix: only skip git config caching for actual include sections
* refactor: share git config hardening primitives between agent-core-v2 and the CLI
* fix(agent-core-v2): clear trusted additional dirs synchronously on trust revocation
* fix(agent-core-v2): compare resolved write targets with Windows path semantics
* fix: fail closed when the git directory disappears during hardening probes
* refactor: move shared git hardening primitives into @moonshot-ai/git-hardening
* fix: close symlinked-gitdir and submodule-recurse gaps in git hardening
* fix(agent-core-v2): reject home-directory ancestors as additional_dir roots
* fix: compare core.worktree with Windows path semantics
* fix: skip git config probes on renders after a negative repo detection
* fix: resolve gitfile pointers against the .git file directory and match includeIf sections
* test: drop duplicated symlink and plain-file cases covered elsewhere
* fix: only treat project-config writes as aliased when the lexical path misses the config pattern
* test: move the realpath guard matrix into a module test
* test: cover git-hardening primitives in the shared package
* refactor: inline git hardening helpers and drop the shared package
Keep the constants and parsers next to the async engine spawn path and
the sync CLI spawn path instead of a third workspace package.
* refactor: drop footer git trust gate and config probing
Workspace trust is a process-level decision, so the TUI never mounts
the footer until the user has trusted. Footer git status now uses
static hardening flags only.
* refactor: route git execution through IGitService.runGit
- Add runGit(cwd, args, options) to IGitService as the public door for
running git with repo-local config hardening applied.
- GitService implements runGit using the existing hardenedGitConfigArgs
helper; status/diff now delegate to it.
- collectGitContext drops its own spawn/probe logic and calls
IGitService.runGit instead, receiving the service through the
promptPrefix context.
- Tower keeps its own git() function (accepted gap).
* refactor: move git hardening helpers to app/git/hardening
* Revert "fix(kap-server): reject malformed and null Origins"
This reverts commit b799a21d0390ff0e4e66437f0d7b90c0b8171efe.
* feat(plugins): update kimi-webbridge plugin to the 2.0.11 skill
Bring the official plugin in line with the Kimi Browser Extension 2.x
daemon: document the ok/data response envelope, self-serve daemon
recovery via start, the movable listen address (10086 is only the
default), file-body retries on macOS/Linux, and the rewritten
operations reference (CLI subcommands, disk layout, new status
fields). Sync the manifest and marketplace versions to 2.0.11 and
point the help links at the new product pages.
* fix(plugins): point the Browser Extension help links at the canonical product path
The site canonicalizes /products/kimi-webbridge to
/products/kimi-browser-extension; ship the final URL in the skill,
manifest, and docs instead of relying on the redirect.
* docs(skill): list all entries for versions with 10 or fewer upstream entries in sync-changelog
* docs(changelog): sync 2.0.2 from apps/kimi-code/CHANGELOG.md
* fix(agent-core-v2): avoid root watch inventory and add a kill switch
Watch concrete candidate paths so a flooded project root cannot fill the V8 heap. Allow disabling every watcher with [watch] enabled or KIMI_CODE_WATCH.
* fix(agent-core-v2): stop watching the whole .kimi-code directory
Watch missing config files on the file path itself so session writes do not reload.
* feat(agent-core-v2): support api_key_env for provider credentials
Providers can declare api_key_env = "VAR" in config.toml to read their
Bearer token from an environment variable instead of storing it inline.
The value is resolved per request (rotation-friendly); an unset or empty
variable fails with config.invalid naming the provider and variable.
apiKey+apiKeyEnv and apiKeyEnv+oauth are rejected as conflicts.
The /models refresh path resolves the same chain (inline apiKey ->
apiKeyEnv -> env sub-table); a provider whose variable is unset lands in
failed[] without affecting others, and open-platform providers keep the
env declaration instead of persisting the resolved secret.
Custom registries: applyCustomRegistryProvider consumes the api.json env
field — imported providers get apiKeyEnv, the legacy inline apiKey is
dropped, and a hand-edited apiKeyEnv survives refreshes (tracked via
source.envKey). kimi provider add --api-key and the TUI registry token
field are now optional so public registries import without a key.
* docs: document api_key_env provider credentials
* fix(oauth): preserve hand-edited apiKeyEnv on registry refresh and address review nits
* fix(oauth): validate apiKeyEnv conflicts during refresh and address review nits
* fix(oauth): mirror apiKeyEnv in the klient provider contract and harden refresh validation
* fix(oauth): stop auto-binding registry env names to provider credentials
* fix(oauth): preserve hand-edited apiKeyEnv across registry re-imports
* fix(oauth): scope apiKeyEnv preservation to the owning registry
* fix(agent-core-v2): preserve apiKeyEnv across models.dev catalog re-imports
* fix(kap-server): drop apiKeyEnv when the provider update route receives a replacement key
* fix(agent-core-v2): replace provider credential fields on TOML writeback
* fix(kap-server): normalize whitespace-only api_key in the provider update route
* refactor(oauth): unify provider credential rules into shared primitives
A new provider-credential module in the oauth package owns the credential
precedence chain, the mutual-exclusion conflicts, the user-facing messages,
and the write-side tri-state reconciliation; the refresh orchestrator,
agent-core-v2 (model-auth, catalog, auth readiness), and the kap-server
provider routes compose it instead of re-deriving the rules per layer.
applyOpenPlatformConfig now takes credential: {apiKey}|{apiKeyEnv} and
merges onto the existing record, so open-platform refreshes no longer drop
hand-written fields (customHeaders, the env sub-table) on the inline-key
path either, and the refresh's write-then-undo block is gone.
Registry imports converge on removeCustomRegistryEntries +
applyCustomRegistryEntries (prior-snapshot provenance): the exported
capture/restore helpers are gone, the CLI persists a re-import with a
single setConfig instead of per-id removeProvider RPCs, and
default_model/default_provider survive a re-import whenever they still
resolve. kap-server's importCustomRegistry keeps the purge-then-rewrite
two-phase replace the config service's raw-merging writeback requires.
kap-server create/replace routes accept api_key_env (tri-state, mutually
exclusive with api_key), and GET /config plus the provider catalog item
expose the binding. A declared-but-unset api_key_env now fails readiness
checks with config.invalid (was auth.token_missing), matching request-time
behavior. Registry 401/403 without a key prints an authentication hint.
* fix(cli): persist registry re-import removals on both harness generations
The v2 harness's setConfig deep-merges per domain (retaining omitted keys
and skipping undefined defaults), so a shrunk re-import left removed
providers and aliases in config.toml and kept a cleared default dangling.
The CLI and TUI registry flows now share persistRegistryImport: on v2 the
removal phase and the rebuilt records go out as two atomic
replaceConfigSections writes (the writeback merges alias fields from raw
TOML, so the purge must be persisted first); on v1 the removeProvider RPC
cascades the removals before one merge write. defaultModel/defaultProvider
snapshots are captured before any removal so the restore works on both
paths.
* fix(oauth): reject oauth before the legacy env fallback and persist cleared thinking on re-import
refreshProviderModels' env sub-table fallback now throws the same
apiKey+oauth conflict the chat path rejects, instead of authenticating
with the fallback key and rewriting the provider to drop oauth.
persistRegistryImport writes the cleared thinking section through the
replacement payload, and drops the v1 fallback branch — registry imports
always persist through replaceConfigSections, so the removal phase no
longer needs per-id removeProvider RPCs.
* chore: consolidate provider credential changesets into one entry
* chore: trim changeset to the api_key_env entry
* fix: harden provider credential status and registry imports
* fix(oauth): expose browser-safe provider credential rules
* fix(node-sdk): replace serialized provider credentials
* fix(oauth): reject credential conflicts during refresh
* fix: harden custom registry re-imports
Reject reserved provider collisions and credential endpoint drift before mutation. Replace registry-owned sections atomically with compare-and-set guards, and carry the replacement contract through klient and node-sdk.
* refactor(registry): centralize custom registry import ownership
Route CLI and TUI imports through the engine via the typed SDK and Klient operation. Keep registry replacement policy inside the engine and preserve credential edits made while fetching the registry.
Cover the shared entry point with real configuration storage and memory/IPC transport tests.
* test: trim redundant api_key_env and registry-import coverage
* fix(cli): reuse the stored registry key on keyless re-import
Both first-party clients encoded "no key given" as an empty string, but
the engine's fallback chain (options.apiKey ?? registryKeyFromExisting)
only reuses the key parked in the provider's source blob when the option
is undefined. A keyless re-import of a private registry therefore went
out without an Authorization header and failed with 401 from the CLI
and the TUI dialog, while the kap-server REST route (which passes
undefined) reused the stored key fine.
Pass undefined from the CLI handler and the TUI import dialog instead
of normalizing to ''. The dialog's result type now marks apiKey
optional, matching the engine contract.
* test: pin CAS rejection and credential-conflict behavior
The coverage trim went past redundancy in three places, leaving the
PR's headline guards untested. Restore the compare-and-set rejection
path (guarded value changed on disk -> retry error, no write) and the
absent-section guard normalization in config.test.ts, the
apiKey+apiKeyEnv / apiKeyEnv+oauth conflict rejections at runtime
resolution (modelAuth) and at the refresh orchestrator (discovery,
with per-provider failure isolation), and the open-platform refresh
through api_key_env proving the resolved secret never lands in the
provider record. Also add the first direct unit tests for the shared
declaredProviderCredential / reconcileProviderCredentialUpdate
primitives.
* refactor(oauth): share reserved provider id rules between import and refresh
* Delete .changeset/registry-import-concurrent-credentials.md
Signed-off-by: 7Sageer <sag77r@hotmail.com>
* test: trim cross-layer duplicate registry and credential coverage
---------
Signed-off-by: 7Sageer <sag77r@hotmail.com>
* feat(cli): add /desktop slash command and kimi install-app subcommand
Both entry points print the Kimi Code desktop app page
(https://www.kimi.com/code) and open it in the default browser:
the kimi install-app subcommand from the shell, and /desktop
(alias /install-desktop) from the TUI.
* fix(cli): derive the desktop app page from the active region
Replace the hardcoded .com URL with the existing region-aware
kimiCodeOfficialInstallUrl() resolved at invocation time, so
global-region users land on the .ai site and region changes are
respected.
* docs(cli): describe the desktop app page URL as region-dependent
* feat(agent-core-v2): upload images as file references for Kimi models
* fix(agent-core-v2): scope media upload cache by endpoint and recognize SDK auth error status
* fix(agent-core-v2): restore the stripped /v1 for kimi files uploads on the anthropic route
* feat(agent-core-v2): omit oldest media when accumulated inline media exceed the request budget
* fix(agent-core-v2): key the media upload cache by the stable JWT subject
* fix(agent-core-v2): harden media request recovery
* fix(agent-core-v2): correct image memo accounting
* feat(agent-core-v2): include saved paths in dropped media placeholders
* docs: drop the saved-path re-read guarantee from the media budget note
The guarantee does not hold for inline data-URL media (no persisted
path exists), and the runtime warning already conveys path availability
when it applies. Addresses the codex P2 review suggestion by removal.
* perf(tui): batch and cache agent swarm progress rendering
* perf(agent-core-v2): evict completed subagent scopes behind an LRU cache
* fix(agent-core-v2): stop the agent actor in the session machine when its scope is removed
* fix(agent-core-v2): emit a terminal event for the final rate-limited run and defer eviction while background tasks run
* fix(agent-core-v2): include in-flight retries when abandoning suspended agents
* fix(agent-core-v2): roll back the closing flag when scope removal fails and wait per the configured eviction timeout
* fix(agent-core-v2): terminalize subagents spawned after batch cancellation and report task timeouts as failures
* chore: restore upstream/main state of files mangled by lint-staged autofix in the merge commit
oxlint --fix rewrites (prefer-set-has, catch-error-name, prefer toSorted/.at(-1)/toReversed)
touched seven files the branch never modified; one of them (oauth managed-kimi-code.ts)
no longer typechecks. Restore all seven to their exact upstream/main state. Committed
with --no-verify so the same autofix does not re-mangle them.
* fix(agent-core-v2): retry deferred scope evictions without exhausting the attempt budget, dedupe terminal events for starting retries, and patch-level the changeset
* fix(agent-core-v2): finish scope teardown instead of reactivating a partially torn-down scope
* fix(agent-core-v2): terminalize subagent-start hook cancellations and re-acquire resume targets after metadata reads
* fix(tui): record cancelled background agents in the transcript
* fix(agent-core-v2): route mirror terminal events through the batch exactly-once guard
* fix(tui): guard terminal swarm members from re-cancellation and deliver terminal status to cancelled foreground subagent cards
* fix(agent-core-v2): classify eviction as removed when teardown already closed the scope
* Merge remote-tracking branch 'upstream/main' into perf/subagent-scope-eviction
Skip lint-staged for this merge: its oxlint --fix pass rewrites unrelated files
(prefer-set-has etc. mangled seven files in the previous merge commit), while the
merge content is upstream's lint-clean code plus conflict resolutions already
verified by oxlint.
* chore: restore upstream/main changes dropped by a stash roundtrip during the merge
A git stash/pop cycle used to isolate an unrelated flaky test reverted 82 files of the
merge result to the pre-merge branch state, so commit 375ff2a4a missed them. The
working tree already held the correct merged content; this commit restores it.
* fix(agent-core-v2): propagate the cancellation reason from turn abort to tool signals
Cancelling a turn aborted the turn's llm scope and every tool scope
without a reason, so tools and subagents only ever saw the default
AbortError and could not tell a user cancellation from a system abort.
With the swarm terminal-event classification this surfaced as
`subagent.failed` ("This operation was aborted") on Ctrl+C instead of
`subagent.cancelled`.
Carry the reason end to end: `MachineEngine.abort(reason)` sends it on
`input.abort`, the agent machine remembers it for the turn and forwards
it to `turn.abort` and to every tool scope it aborts, the turn machine
passes it to the llm scope, and the loop service hands its cancellation
(a `UserCancellationError` by default) to the engine.
* fix(agent-core-v2): stop rebuilding an evicted subagent after its caller aborts
`createAgentAwaitingClose` polled for the previous scope to finish
closing without ever looking at the caller's abort signal, so cancelling
an `Agent` or `AgentSwarm` resume during that wait still recreated the
scope afterwards. In the `Agent` path the run then rejected before any
terminal event was mirrored, leaving an idle scope that the scope cache
no longer tracked.
Thread the caller's signal into the helper and check it before every
attempt; the Agent tool passes its call controller and the swarm service
passes the attempt signal. Also trim the eviction changeset to the one
sentence the changeset rules ask for.
* fix(agent-core-v2): report task-manager aborts of a subagent as cancelled
When the task manager times out or stops a background subagent it aborts
the run with a plain reason ('Timed out', the TaskStop reason), and the
run rejects with that raw reason. The task manager therefore classifies
the task as timed_out or killed, but the mirror only recognised
`UserCancellationError` as a cancellation and emitted `subagent.failed`,
so the transcript recorded a failure before the authoritative
`background.task.terminated` event could land.
Classify a terminated run by the shape of its abort reason: a real
Error that is not an AbortError (the swarm's own per-item timeout) stays
a failure, everything else that aborted the run is a cancellation. The
swarm's start-failure path uses the same rule.
* fix(agent-core-v2): flush the wire before evicting a subagent scope and re-pick LRU candidates
Two gaps in the scope-cache eviction pass:
- `AgentLifecycleService.remove()` swallows a failed wire flush and still
tears the scope down, so an eviction that hit a disk-full or transient
I/O error would drop the in-memory scope and let a later resume rebuild
from a stale wire. Flush the agent's wire explicitly before removing;
if that fails, keep the scope resident and retry on a later pass. The
idle and task checks are repeated after the flush so a resume that
started meanwhile is not cancelled by the removal.
- The pass snapshotted its candidates up front and re-validated them by
attempt count only, so a scope that was resumed and completed again
while an earlier eviction was awaited kept matching with attempts 0 and
was evicted despite now being the most recently used. Pick the oldest
eligible entry from the live map on every step instead, skipping only
the entries this pass already tried.
---------
Co-authored-by: Kaiyi <me@kaiyi.cool>
* fix(plugins): rename WebBridge display name to Kimi Browser Extension
The product has renamed WebBridge to Kimi Browser Extension in work and
Chrome. Update the user-facing display name across the built-in
capability entry, TUI plugins selector, managed plugin manifest,
marketplace catalog, skill docs, and user docs to match. Internal ids,
binary names, CDN paths, and daemon references are unchanged.
* fix(plugins): bump webbridge to 1.11.4 and keep legacy docs anchor
Address review: point the changeset at the scoped CLI package, bump the
renamed plugin's manifest/catalog/docs version so installed users are
offered the renamed package as an update, and preserve the published
#kimi-webbridge documentation anchor beside the renamed heading.
* docs(plugins): match only the known extension-update error messages
Broadening the version-mismatch trigger to the generic prefix 'Please
update the' would misclassify unrelated tool errors as an outdated
browser extension; match the two known full messages instead.
---------
Co-authored-by: kimi-agent-bot <kimi-agent-bot@users.noreply.github.com>
The platform /usages payload now serves per-window used ratios
(goods_version, a usages map of limit5h/limit7d/monthTotal/monthCode
entries with used_ratio/reset_time, and boosterWallet) instead of
absolute used/limit rows.
- oauth: parse and fetch the quota model; keep the platform helpers
- toolkit / agent-core-v2 / node-sdk: getManagedUsage returns the quota
- kap-server: /oauth/usage passes the camelCase quota shape through
(the legacy snake_case wire is gone)
- TUI /usage: plan rows are presence-driven from the quota payload;
the monthly row carries a kimi/code breakdown line
- docs: server-api reference updated for the new response shape
* docs(web): add common slash commands table and rename startup options section
* docs(interaction): fold the goal mode guide into the interaction page and remove the orphaned page
* docs(skills): clarify flat-form skill naming and its limits
The flat-form description "Skill name is taken from the filename (minus
.md)" read as if the on-disk file should drop the extension, which
repeatedly confused readers. Rewrite the Creating-a-Skill section with
a concrete directory layout, explicit name-derivation rules for both
forms, the directory-over-flat precedence, and the flat form's top-level
scanning and KIMI_SKILL_DIR limitations.
* docs(skills): attribute directory-form names to the required frontmatter
parseSkillText requires name in directory-form SKILL.md and always
registers under it, so the subdirectory name is only a convention, not
the source of the Skill name. Reword the derivation bullets accordingly
(flat form keeps its filename fallback).
---------
Co-authored-by: kimi-agent-bot <kimi-agent-bot@users.noreply.github.com>
* feat(oauth): add the dynamically_loaded_tools capability from the official models endpoint
* feat(agent-core-v2): support per-server deferred disclosure of MCP tools
* feat(klient): mirror per-server deferred in the MCP config contract
* fix(agent-core-v2): honor per-server deferred for the needs-auth MCP tool
* fix(agent-core-v2): register select_tools regardless of the profile tool allowlist
* feat(agent-core-v2): default MCP servers to inline tool disclosure unless deferred is enabled
* feat(agent-core-v2): make the compaction attempt limit configurable
Add loop_control.compaction_max_attempts (default 5) to control the
maximum total attempts for a failing compaction request, replacing the
hardcoded MAX_COMPACTION_RETRY_ATTEMPTS constant. The value flows
through ProfileModelContext into the compaction retry loop, covering
both retryable generation errors and empty/truncated response shrinks.
* fix(agent-core-v2): bound compaction shrink attempts and compute retry delays lazily
Address codex review on #3750: the empty/truncated shrink path allowed
maxAttempts + 1 requests (throwing only when the shrink counter exceeded
the limit), and the backoff delay array was allocated eagerly with
maxAttempts - 1 entries before the first request. The shrink path now
stops at the configured limit, and each delay is computed lazily from
the retry index.
* fix(agent-core-v2): count every compaction request against the shared attempt limit
Address the second codex review round on #3750: the retryable-error and
empty/truncated recovery paths kept separate counters, and the retry
budget reset after each shrink, so alternating failure modes could issue
more requests than compaction_max_attempts. A single requestAttempts
counter now gates all recovery paths (the overflow shrink path keeps its
own tighter cap of 3), making the configured value a true maximum on
total requests per compaction round.
* fix(mcp): preserve original attachments omitted from model output
* test: register session media storage in agent lifecycle fixture
* fix(mcp): retain media originals and bound attachment details
* fix(mcp): resolve session attachments and honor cancellation
* test: check concrete media references in provider requests
* fix(media): read session attachments from their owning storage
* fix(media): preserve attachment access across runtime and history changes
* fix(mime): recognize structured application text attachments
* docs(changelog): sync 0.42.0 from apps/kimi-code/CHANGELOG.md
* docs(changelog): use absolute URL for the Remote Control guide link
* docs(changelog): use absolute URLs for the remaining doc links
* fix(agent-core-v2): avoid repeated truncation of file reads
* fix(agent-core-v2): resume reads within long lines
Add column offsets and forward recovery for bounded long-line reads. Reject malformed UTF-16 in Read instead of replacing invalid input.
* fix(agent-core-v2): warn on lossy UTF-16 reads
Return readable text after strict UTF-16 decoding fails, with a warning retained in budgeted read continuations.
* fix(agent-core-v2): avoid redundant tail scans and detect file changes
* feat(agent-core-v2): allow read-only tools in /btw side questions
The btw child agent previously vetoed every tool call. Allow the
read-only tools Read, Grep, and Glob so side questions about the
codebase can be answered from current file contents; write and
execute tools stay disabled.
* docs: address review — single-sentence changeset, inline-code tool names
* chore: drop the benefit clause from the btw changeset
* feat(kimi-code): two-line collapsed tool cards with width-aware headers
Collapsed cards now show the call on line one and a single dim outcome
row on line two: a Bash command's last output line (the live tail while
running) with a line-count chip, a Grep/Glob path sample, or a generic
tool's first output line. Read groups stay header-only and honor the
global expand state; failed calls keep their preview. Headers split into
head / flexible / tail segments so a long command fills the terminal
width before the chip.
* feat(kimi-code): NotifyUser tool and mid-turn update panel
Add an experimental NotifyUser tool (flag notify_user, off by default)
that agent-core-v2 offers only when the host declares the update_panel
UI capability at bootstrap; the TUI declares it through the SDK harness
options. The system prompt's guidance to send updates is injected only
when the tool is active for the agent. The TUI renders the turn's
updates in a panel above the editor (stacked, 8-row window, Ctrl+N pages
back) that the next turn clears, and keeps a one-line card in the
transcript.
* feat: add subagent updates and bidirectional paging
* fix: preserve session tools and prompts when toggling updates
* fix: correct notification delivery and CI regressions
* feat(secondary-model): drop the experimental flag from the subagent model pool
* feat(secondary-model): sync the web bundle without the experimental gate
* feat(agent-core-v2): add env bindings for print-mode and bash task timeout config keys
Wire bashTaskTimeoutS, printBackgroundMode, printWaitCeilingS, and
printMaxTurns into taskEnvBindings as KIMI_CODE_BACKGROUND_* variables
so headless/print runs (e.g. container harnesses) can bound or disable
the print background policy without mounting a config file. bashTaskTimeoutS
accepts 0 (no timeout); invalid values are ignored. Env-set values count
as set for applyPrintModeConfigDefaults and win over the print fill.
Both integer parsers use Number.isSafeInteger: zod's int() rejects
unsafe integers, and since applySectionEnvBindings validates the combined
overlay, one unsafe value would otherwise discard the whole section's
env bindings, including valid siblings.
* Delete .changeset/print-task-env-bindings.md
Signed-off-by: 7Sageer <sag77r@hotmail.com>
---------
Signed-off-by: 7Sageer <sag77r@hotmail.com>
- remote-control is always available: kimi rc, kimi web --remote-control and /remote-control no longer require KIMI_CODE_EXPERIMENTAL_REMOTE_CONTROL or the master flag
- add the [database] config section with base (session-index read model) and search (global search worker) kill switches, both defaulting to true
- rename the kill-switch env vars to KIMI_CODE_PERSISTENCE_MINIDB_READMODEL and KIMI_CODE_SEARCH_WORKER (precedence: env > config > default)
* refactor: remove the legacy agent-core v1 package
Delete packages/agent-core (v1 engine) and migrate node-sdk fully onto
agent-core-v2:
- node-sdk owns its public contract (error protocol, KimiConfig schema
and file IO, process-global logging facade, telemetry client
interface); event and interaction types re-export from
@moonshot-ai/protocol or agent-core-v2
- createKimiHarness is now the single harness factory, backed by the
v2 client; the v1 SDKRpcClient is deleted
- CLI and vscode run agent-core-v2 unconditionally;
KIMI_CODE_LEGACY_FLAG and useAgentCoreV1 are removed
- the wire.jsonl replay fold moves into agent-core-v2's replayBuilder
(foldWireRecords), and the v2 journal now persists tool-call display
so replay restores diff/todo displays
- TUI engineV2 branches collapse to the v2 path
* test(vscode): retry temp-dir teardown in replay-resume integration test
- rename the mode commands to /yolo and /auto (formerly
/ask-when-needed and /never-ask) and drop their on/off arguments
- running either command now opens the permission mode list with the
corresponding mode preselected; Enter confirms the switch
- decouple the choice picker's initial cursor from the current-value
marker via a new initialValue option
- after a mode switch, show the mode-specific description as the yellow
status line instead of the generic unconfirmed-changes warning
* feat(agent-core-v2): allow unanalyzable bash commands in auto permission mode
* feat(agent-core-v2): drop the dangerous command guard in auto permission mode
* fix(agent-core-v2): keep background questions open past turn end and inline their answers
Background AskUserQuestion reused the generic task pipeline end to end, which
broke it in two ways: the pending interaction was still bound to the asking
turn, so it was cancelled the moment the agent finished its turn, and the
turn-end cancel response was then misread as an answer. On top of that the
completion notification only carried a pointer to the task output file,
forcing an extra Read round trip for a few bytes of JSON.
- Detach background question interactions from the asking turn so they stay
pending until answered, stopped, or the agent closes.
- Treat cancelled interaction responses as dismissals.
- Inline the answer JSON in the question task notification and word the
notification as answered or dismissed; fall back to the output file only
when the answer exceeds the inline budget.
- Trim the background launch result to task id, status, and one next step.
- Fold transcript notification summaries before inline answer blocks.
* fix(agent-core-v2): fail background questions on tool errors and translate interaction cancellations in the question service
Follow-up hardening from review:
- The interaction kernel's cancellation response now has a named shape,
InteractionCancellation, and SessionQuestionService.request translates it
into a dismissal (null) before handing the result to callers. The
AskUserQuestion tool no longer inspects answer maps for a cancelled key,
so a bare answer map can never be mistaken for a cancellation.
- QuestionBackgroundTask settles as failed with the tool's message as the
stop reason when the question tool reports an error, instead of writing
the error text as completed output. The generic task notification then
carries the reason, and the answered/dismissed wording is not used.
- The question notification only says answered or dismissed when the task
output parses as an answers payload; any other output keeps the generic
completed wording.