Commit graph

771 commits

Author SHA1 Message Date
liruifengv
d8317d81e5
fix(agent-core-v2): cache workspace alias resolution across calls (#3325)
* fix(agent-core-v2): cache workspace alias resolution across calls

resolveAliasIds re-read the workspace catalog and the whole session
index from disk on every call, so the by_workspace grouping loop and
the per-workspace session counts paid repeated full-file reads per
workspace per request (~2.4s per 50-group page at 1.1k workspaces,
23 pages serially during a client startup drain).

Cache both files as precomputed snapshots (by-id map plus a
root-key -> alias ids index) invalidated by the storage watch events,
which cover atomic rewrites and cross-process writes; storage backends
without watch fall back to reading through. The first resolution primes
the workspace merge via IWorkspaceService.list() so the cached catalog
matches what WorkspaceService.get() would have returned.

* chore: drop the changeset; the user-facing entry ships with the app changelog

* fix(agent-core-v2): coalesce cold alias snapshot loads and guard publication

Concurrent cold resolveAliasIds callers (the /workspaces route fans out
per-workspace counts with Promise.all) all passed the cache check before
any caller finished loading, re-running the full catalog and session
index reads the cache exists to avoid; memoize the in-flight load
promise so a cold batch shares one read. Also capture the invalidation
generation before each read and publish the snapshot only when it is
unchanged, so a mid-read file replacement cannot leave a stale snapshot
installed over the watch invalidation.

* fix(agent-core-v2): publish catalog invalidation through the persistence owner

A debounced fs watch was the only invalidation channel for the alias
catalog snapshot, so an in-process catalog write stayed invisible to
resolveAliasIds for up to the watch debounce window while the previous
read-through code observed every completed write immediately.
IWorkspacePersistence now exposes onDidChange: FileWorkspacePersistence
fires it synchronously on save and re-fires the underlying document
watch (covering atomic rewrites and cross-process writers), and the
aliases service subscribes to it instead of watching raw storage keys.
The session index snapshot keeps the filesystem watch, matching the
read-side ownership of that file.

* fix(agent-core-v2): invalidate session alias snapshots on append-log writes

A flushed session_index.jsonl append was invisible to resolveAliasIds
for up to the fs-watch debounce window, so a sessions request issued
right after a session create could resolve the workspace's aliases from
the pre-append snapshot. IAppendLogStore now publishes onDidWrite after
each durable flush (append batches and rewrites), and the aliases
service drops its session-index snapshot through that event; the raw
filesystem watch stays as the channel for cross-process writers.

* fix(agent-core-v2): fire append-log write events only after actual writes

Once a key has a LogState, every global flush() (WireService flushes
after ordinary agent persistence) completed it successfully and fired
onDidWrite unconditionally, so idle agent activity kept dropping the
alias session-index snapshot and forced full re-reads of an unchanged
index. drain() now reports whether it appended anything and the write
event fires only when a flush actually persisted a batch or a rewrite.

* fix(agent-core-v2): retry shared snapshot loads that span a write

Callers joining an in-flight single-flight load after a completed write
still received the pre-write snapshot: the generation check only guarded
cache publication, not the value returned to awaiters. Each load now
carries the generation it started at, and catalog()/sessionIndex()
re-read (coalesced through the same single-flight) when the settled
load's generation is stale.

* fix(agent-core-v2): report partial progress when an append-log drain fails

A drain that persisted one batch and then failed the next threw without
recording the durable write, so onDidWrite never fired for records that
were in fact persisted (the alias session-index snapshot then missed
its synchronous invalidation). The write box now threads through the
whole owned flush: each successful batch marks it, and the event fires
before the failure propagates.

* fix(agent-core-v2): retry the whole alias resolution across a mid-write

The per-snapshot retry guarded each read on its own, so a write landing
between the catalog and session-index reads returned an alias set
assembled across two generations. resolveAliasIds now captures the
generation once, reads both snapshots together, and retries the whole
resolution when either input was invalidated mid-flight. The
spanned-write test is reworked to gate after the load (so the snapshot
content genuinely predates the write), and a new case covers the
cross-generation mix directly.

* fix(agent-core-v2): replace the session-index fs watch with a size check

A resident chokidar watcher per server on the shared home directory
degraded watch delivery for unrelated files under test-suite boot
volume (the prompts suite lost the config.toml reload race and the
catalog missed a just-written model). In-process appends were already
covered synchronously by the append-log write event; cross-process
writers now surface through a per-call size comparison on the
append-only file, which costs one stat per resolve and needs no
resident watcher.
2026-08-28 17:20:52 +08:00
Kimi Agent
dc6028dc6b
fix(kap-server): only fold user-origin steers by content in the cold transcript (#3328)
* fix(kap-server): only fold user-origin steers by content in the cold transcript

* fix(transcript): check marker-only origins before the steer content match

* fix(transcript): limit the steer bypass to marker-only skill triggers

* fix(transcript): consume the steer count for marker-only activations

* fix(transcript): pair steered contents with messages by origin kind

* refactor(kap-server): read the steer origin kind without nested casts

---------

Co-authored-by: kimi-agent-bot <kimi-agent-bot@users.noreply.github.com>
2026-08-28 17:05:59 +08:00
liruifengv
2bf7ed22d7
feat(auth): split model readiness from sign-in state in /api/v1/auth (#3293)
* feat(auth): split model readiness from sign-in state in /api/v1/auth

GET /api/v1/auth now reports models_ready (the default model resolves
against the configured catalog, providerless and env-injected models
included) instead of the compound ready flag, and no longer carries
default_model — config values are served by /config alone. The v1
summary schema follows.

OAuth managed-model refreshes now heal a lost default model: the
refresh snapshot includes defaultModel, so an unchanged catalog with
a missing default still lands the write-back branch and re-selects
one. The refresh also rebases onto a fresh config read after the
remote fetch, so a model or thinking change made during the fetch is
no longer overwritten. The shared discovery refresh path (scheduler,
POST /providers/{id}:refresh) heals the default the same way.

Config changes are now published to WS clients on every write path:
a debounced+trailing publisher bridges IConfigService section changes
to ConfigChanged with camelCase changedFields and a full config
projection, and the broadcaster forwards event.config.changed and
event.model_catalog.changed (both previously published but never
delivered). All three event types are registered in the event unions,
so session_event parsing and AsyncAPI describe them.

BREAKING CHANGE: GET /api/v1/auth drops the ready and default_model
fields in favor of models_ready; event.config.changed's changedFields
is now camelCase domain names instead of the raw snake_case request
keys (v1 summary schema follows).

* fix(kap-server): expose the session model in session list projections

GET /api/v1/sessions hardcoded agent_config.model to '' and the v2
projection had no model field at all, so clients could only learn a
session's model via the post-select /status read — which races the WS
replay and often never lands. SessionFacts now carries the live
session's model (same source as the snapshot route), toWireSession
emits it, and the v2 activity domain gains a nullable model field.

* fix(kap-server): gate prompt submission on the effective session model

The submit gate called ensureReady() with no override, so it only ever
validated config.default_model: a session with a bound model (or a
prompt carrying one) was rejected with 40113 whenever default_model was
missing or dangling. Pass the effective model (request model, then the
agent profile's bound model, falling back to default_model inside
ensureReady) on both the prompt submit and btw routes.

* fix(agent-core-v2): honor defaultProvider in model readiness resolution

resolveModelForReady stopped at the flat baseUrl fallback, so a model
that omits provider/providerId and relies on the configured
defaultProvider resolved at runtime (ModelCatalog.resolveProviderContext
falls back to it) while /api/v1/auth reported models_ready:false and the
send gate rejected the prompt. Mirror the runtime order (providerId ->
provider -> defaultProvider -> flat baseUrl) and pass the configured
default provider from both readiness callers.

* fix(kap-server): redact inline model credentials from config responses

toConfigResponse only redacted the providers section, so a model's
inline apiKey/oauth rode GET /config verbatim and, via the new
event.config.changed publisher, every WS connection plus the persistent
event journal. Project the models section the same way: strip
credential fields and report has_api_key.

* fix(agent-core-v2): honor defaultProvider in ensureReady credential checks

The readiness phase learned the defaultProvider fallback, but the
credential phase right after still derived the provider only from the
model's explicit fields: a model omitting provider/providerId passed
readiness yet missed the default provider's apiKey/OAuth material and
prompts failed with auth.token_missing. Mirror the same provider chain
(providerId -> provider -> defaultProvider) when resolving credentials.

* fix(kap-server): validate the model a profile bind will select at the prompt gate

The gate validated the session's current model even for a prompt that
switches profile without a model — but bind falls back to defaultModel
in that case, so a stale session model drew a misleading 40113 before
bind could run. Gate on bind's selection order instead: the request's
explicit model, then the default on a profile switch, then the session's
bound model.

* fix(kap-server): redact inline service credentials from config responses

The earlier redaction covered providers and models, but toConfigResponse
still passed the services section through verbatim: inline or
env-injected apiKey, oauth references, and credential-bearing
customHeaders rode GET /config and, via the event.config.changed
publisher, every WS connection plus the persistent event journal.
Project services the same way: strip apiKey/oauth into has_api_key and
report only the header names as custom_header_keys (the MCP
envKeys/headerKeys convention).

* fix(kap-server): keep unlisted config domains through event validation

The config.changed broadcaster returned the zod-parsed config, which
strips domains absent from configResponseSchema (mcp, identity,
model_catalog, image, tools, token_counting): changedFields named them
while the advertised full snapshot no longer matched GET /api/v1/config.
Make the response projection passthrough (defineRoute validates only
requests, so REST responses are unaffected).

* fix(agent-core-v2): use the exact configured key for model readiness lookups

resolveModelForReady trimmed the model id before the models-table lookup
while ModelCatalog and ensureReady use the configured string as an exact
record key: a whitespace-padded default_model was reported ready and then
crashed the submit gate with an internal error instead of 40113, and a
legitimate key containing spaces was reported dangling. Trim only rejects
blank values now; the lookup always uses the raw key.

* fix(protocol): keep unlisted config domains in the shared event projection

The shared configResponseSchema stripped domains it does not enumerate
(mcp, identity, model_catalog, image, tools, token_counting, subagent,
secondary_model), so event.config.changed parsed through agentEventSchema
named them in changedFields while omitting their values. Make the shared
projection passthrough like the kap-server-local one.

* fix(agent-core-v2): use the exact default_provider key in readiness checks

The defaultProvider fallback trimmed the configured value before the
providers-table lookup while ProviderService and ModelCatalog use the
configured string verbatim: a whitespace-padded default_provider could
build successfully yet report not-ready (40113), or report ready for a
provider runtime resolution cannot find. Trim only rejects blank values;
the lookup uses the raw key.

* chore: sync web dist from code-app

Rebuild the bundled web UI against this branch's /auth contract (models_ready, no ready/default_model): the previous bundle still read the old fields and stayed in the not-ready flow against this server.

code-app: 000d2594ff3e95b553be326126bab3f939b62944

* Revert "chore: sync web dist from code-app"

This reverts commit 9400a24a03863b3e8b780dda251540f824f02f3a.

* fix(oauth): rebase the default selection after the refresh fetch

A provider refresh snapshots the config before the remote catalog fetch;
when the user selects a default model while the fetch is in flight, the
stale snapshot's empty default made an otherwise unchanged catalog enter
the write path and the self-heal persisted the generated default over the
user's newer selection. Each branch now re-reads and rebases the
default/thinking selection after its fetch, before cloning, comparing,
or writing.

* style(kap-server): pass optional custom_header_keys without conditional spread
2026-08-28 15:53:56 +08:00
7Sageer
4e7738b73c
feat(kap-server): support server-local path attachments (#3247)
* feat(kap-server): support server-local path attachments

Web and desktop clients can now attach files, images, and videos to a
prompt by server-local absolute path instead of uploading a copy. The
daemon validates the path (absolute, realpath-resolved, non-sensitive,
local runtime only) and references the original file in place, so the
agent reads the original path; the upload flow is unchanged.

Submitted file attachments are also recorded on the prompt origin and
projected as typed transcript attachments, so web clients render
attachment chips for plain files without parsing the model-facing
notice text.

* fix(kap-server): forward file attachment metadata from skill activations

* Delete .changeset/web-attach-by-path.md

Signed-off-by: 7Sageer <sag77r@hotmail.com>

---------

Signed-off-by: 7Sageer <sag77r@hotmail.com>
2026-08-28 12:03:47 +08:00
7Sageer
23921e9f2c
fix(agent-core-v2): notify the model of previous background tasks terminated by app exit (#3292)
* fix(agent-core-v2): unify previous-session lost-task notice into a single reminder on resume

* fix(agent-core-v2): harden resumed task reminders

* docs: clarify task resume reminder
2026-08-28 12:03:20 +08:00
github-actions[bot]
52e8d19dbd
ci: release packages (#3140)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-27 19:33:51 +08:00
liruifengv
21f7ef64f0
fix(auth): keep OAuth login alive when its own provisioning writes the provider (#3294)
* fix(auth): keep OAuth login alive when its own provisioning writes the provider

* fix(auth): settle the OAuth flow as authenticated before provisioning

* fix(auth): publish the login as authenticated only after provisioning completes
2026-08-27 18:29:35 +08:00
zy
74d9bd132e
fix(mcp): send content or structuredContent to the model, never both (#3234)
Some checks are pending
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
CI / build (push) Waiting to run
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-vscode-legacy (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
Release / Release (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
* fix(mcp): forward structuredContent only as fallback when content has no usable text

Servers that follow the MCP spec's backwards-compatibility SHOULD return
the same JSON both as a TextContent block and as structuredContent.
Forwarding both to the model sent the same data twice. structuredContent
now rides the mcp-structured-result block only when the content blocks
carry no usable text; _meta still always passes through.

* test(mcp): verify structured-content fallback over a real stdio MCP server

Round-trip four server result shapes (dual-emit, structuredContent-only,
prose+structured, vendor _meta) through StdioMcpClient and the output
pipeline, so the fallback behaviour is checked against real protocol
bytes instead of hand-built result objects.

* fix(mcp): dedupe structuredContent only against its verbatim serialization

The earlier has-usable-text gate also suppressed the structured payload
when content was a lossy human summary — the primary case from #2554
(list_projects returning 'N item(s)' while the items live in
structuredContent). Skip the structured block only when a content text
block parses to the same JSON value (semantic compare, key order and
formatting insensitive); summaries and structured-only results still
pass through.

* fix(mcp): forward structuredContent only when content does not already cover it

Replace the verbatim-serialization comparison with a size heuristic:
well-behaved servers render the same data into content (the spec's
dual-emit, or a faithful human reorganisation), and either way the text
measures at roughly the same size as the payload, so forwarding it would
double the information. Append the structured payload only when content
carries no usable text, or when the payload is more than twice the text
size — the signature of a lossy summary. Verified against a live video-
editor MCP whose tools all measure a json/text ratio of 1.2-1.9.

* fix(mcp): send content or structuredContent to the model, never both

Final policy: content and structuredContent are alternatives. content
wins whenever it carries anything usable (a media block or non-whitespace
text); structuredContent fills in only for an empty content array. There
is no reliable signal that the structured payload is richer than what the
server already rendered into content, so no size or structure heuristic
is attempted. _meta still always passes through.

* refactor(mcp): rename the structured-extras wrapper to mcp-result-extras

The block carries structuredContent and/or _meta; the old
mcp-structured-result name was inaccurate whenever it is a pure _meta
carrier.

* ci: retrigger after flaky mcpCore client-stdio close-buffering test

* ci: retrigger after flaky minidb concurrent writer/reader test
2026-08-27 17:24:27 +08:00
7Sageer
bd5e32f683
fix(secondary-model): stop rewriting the section when providers refresh or are removed (#3284)
* fix(secondary-model): stop rewriting the section when providers refresh or are removed

Provider refresh, provider deletion/rename, catalog/registry import,
OAuth logout, and SDK removeProvider used to cascade into the user's
[secondary_model] block: pool entries were silently pruned, and the
whole section was deleted when its effective default dangled. The
cascade ran from a cache-refresh path (including an unattended 6h
scheduler), so upstream model-list changes could irreversibly destroy
hand-written configuration without any notice.

Config is user intent; the catalog is an availability snapshot. Stop
rewriting the section on every provider/models writer. An entry whose
model no longer resolves fails pool validation on the next session
create with a message naming the offending alias, which is the same
fail-fast contract hand-written typos already had.

* chore(sdk): add changeset for the removed secondary-model cascade export

* Delete .changeset/sdk-remove-secondary-model-cascade.md

Signed-off-by: 7Sageer <sag77r@hotmail.com>

* Delete .changeset/secondary-model-no-silent-rewrite.md

Signed-off-by: 7Sageer <sag77r@hotmail.com>

---------

Signed-off-by: 7Sageer <sag77r@hotmail.com>
2026-08-27 16:50:42 +08:00
liruifengv
7066950653
fix(oauth): show a cancelled state when authorization is denied on the web page (#3291)
* fix(oauth): show a cancelled state when authorization is denied on the web page

* chore: drop the changeset and the dist-web sync from this PR
2026-08-27 16:20:48 +08:00
liruifengv
f143130c07
fix(transcript): carry the orchestrator's prompt on subagent turns (#3289)
* fix(transcript): carry the orchestrator's prompt on subagent turns

* chore: add changeset for subagent turn prompts
2026-08-27 16:03:06 +08:00
liruifengv
692bb0a409
feat(kap-server): add task detach action to move foreground tasks to background (#3273)
* feat(kap-server): add task detach action to move foreground tasks to background

* test(kimi-code-sdk): normalize v2-only parentToolCallId in task parity projections

* fix(agent-core-v2): distinguish user-initiated detach in tool result text

* feat(agent-core-v2): mention user-initiated backgrounding in the bash tool description

* feat(agent-core-v2): use a client-agnostic background-task panel hint in the bash tool description

* ci: retrigger checks

* feat(agent-core-v2): client-agnostic human_shell_hint and a detached_by_user marker in tool results

* fix(protocol,docs): declare parent_tool_call_id in the shared task schema and document the detach action

* style: remove added comments
2026-08-27 15:38:21 +08:00
Haozhe
cd7c97b377
fix(agent-core-v2): retry failed wire journal repair before accepting appends (#3282) 2026-08-27 14:52:44 +08:00
Haozhe
7de7b18ee9
feat(agent-core-v2): self-heal corrupted wire journals during restore (#3281) 2026-08-27 11:13:45 +08:00
Kimi Agent
b17bd61cef
fix(agent-core-v2): clear the turn outcome when an undo rewinds the turn it describes (#3278)
Some checks are pending
CI / build (push) Waiting to run
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-vscode-legacy (push) Waiting to run
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
Release / Release (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
* fix(agent-core-v2): clear the turn outcome when an undo rewinds the turn it describes

* fix(agent-core-v2): clear the turn outcome too when an undo outruns the tracked anchors

* fix(agent-core-v2): reconcile the persisted turn outcome against the replayed wire on restore

* fix(agent-core-v2): keep the persisted outcome when an undo rewinds only later turns

---------

Co-authored-by: kimi-agent-bot <kimi-agent-bot@users.noreply.github.com>
2026-08-27 03:16:45 +08:00
Kimi Agent
a9656841b8
test(mcp): deflake early-close replay test in stdio MCP clients (#3269)
Some checks are pending
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-vscode-legacy (push) Waiting to run
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
CI / build (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
Release / Release (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
The drain probe treated any callTool failure as proof the transport close
had been processed, but a stdin write error (EPIPE) can win the race
against the child's exit notification, so the listener could be registered
before the close was buffered and the synchronous replay never fired.
Break the drain loop only on errors that are impossible before the SDK's
_onclose ran ('Not connected' / 'Connection closed' / the transport's
not-running guard).

Also drop the assertion that the replayed reason contains the child's
final stderr: the reason snapshots the stderr buffer at close time, which
can legitimately race delivery of the last stderr chunk (reproduced 2/40
under CPU load). Tail capture itself stays covered by the stderrSnapshot
assertion. Finally, flush the fixture's banner through the stderr write
callback before process.exit so the write cannot be truncated.

Co-authored-by: kimi-agent-bot <kimi-agent-bot@users.noreply.github.com>
2026-08-26 21:21:29 +08:00
Haozhe
b3f08b68c8
fix(kap-server): include stable question and option ids in transcript question entities (#3272) 2026-08-26 21:14:27 +08:00
Haozhe
75c94c4a0e
fix(agent-core-v2): fall back to kimi-file URL for prompt attachments (#3271)
- turn.started now derives the attachment file id from the kimi-file URL when the media part carries no id, so prompt images uploaded through the global file library stay attached in the live transcript instead of vanishing until the post-turn heal
- an explicit id must still match the URL file id, and non-kimi-file URLs are still ignored
- restore the turn.started prompt-attachment regression coverage dropped by the model-as-container refactor and extend it to the id-less kimi-file form
2026-08-26 21:12:38 +08:00
LCZcn96
75550c5686
fix(vscode): restore live context usage on v2 (#3098)
* fix(vscode): restore live context usage on v2

* chore: point changeset at vscode extension and node-sdk packages
2026-08-26 19:57:50 +08:00
Haozhe
5634cb556f
fix(kap-server): project steered messages as live user frames in the transcript (#3262) 2026-08-26 17:55:34 +08:00
Haozhe
c488586091
fix(kap-server): remove undone turns from the live transcript projection (#3259)
* fix(kap-server): remove undone turns from the live transcript projection

* fix(agent-core-v2): report the earliest removed turn id on conversation undo
2026-08-26 16:40:39 +08:00
7Sageer
4b044926e3
fix(agent-core-v2): spill oversized tool outputs and surface dropped content (#3227)
* fix(agent-core-v2): spill oversized tool outputs and surface dropped content

* fix(agent-core-v2): preserve spill fields through tool result normalization

normalizeToolResult rebuilds every tool result with a field whitelist,
which stripped untruncatedOutput / untruncatedOutputTotalChars /
spillExempt before ToolResultTruncationService could see them: the
spill-on-truncation path never fired for Bash/Grep/FetchURL/WebSearch,
and reads of spill files were not exempted from re-spilling.

Pass the three engine-internal fields through, and add executor-level
integration tests that run a retainFullOutput tool and a spill-exempt
result through the real ToolResultTruncationService.

* refactor(agent-core-v2): drop banned JSDoc and fix harness error typing

main banned JSDoc in comment-free packages (#3226); remove the doc
blocks on the new contract fields and on isSpillFilePath. Type the
harness scripted stream error as Error to satisfy only-throw-error
under oxlint --type-aware.

* fix(agent-core-v2): preserve completion status when spilling output

* fix(agent-core-v2): mirror dedupe reminders into the spill suffix

appendReminder additions lived only in the final output, so they were
dropped when the spill pointer replaced it; mirror the reminder into
untruncatedOutputSuffix for retained results, widening ToolDedupeResult
to ExecutableToolResult plus its message field. Also stop claiming the
full output was saved when retention capped out, narrow spillExempt to
'true' per the optional-property convention, and pass traceId directly
in the harness.

* fix(agent-core-v2): prefer persisted Bash task logs

* refactor(agent-core-v2): unify tool-result truncation in the spill pipeline

Route every tool result through ToolResultTruncationService.truncateForModel
as the single model-context decision point: spillExempt pass-through, the
50k char budget, per-line shaping, spill persistence with a 10MB retention
cap, and append-or-replace pointer rendering. Tools no longer declare
truncation options; sources keep only memory-safety caps.

- rename ToolResultBuilder to ToolOutputAccumulator and drop its options
- mcp keeps only its media pipeline and shares the unified 50k budget
- bash persists foreground logs at the spill threshold and reuses them as
  spill.outputPath only within the retention budget
- carry completion/error messages in spill.suffix so retention capping
  cannot drop them
- render a bounded preview when spill persistence fails
- suppress suffix lines already present inline in append mode
- call out text-only persistence when media parts stay attached

* fix(agent-core-v2): preserve success status in spilled output

* fix(agent-core-v2): reuse the complete task log for spilled bash output beyond 10MB

* Update tool-result-spill.md

Signed-off-by: 7Sageer <sag77r@hotmail.com>

---------

Signed-off-by: 7Sageer <sag77r@hotmail.com>
2026-08-26 14:34:29 +08:00
Kimi Agent
f35f214e20
test(kap-server): use a neutral model name in transcript projector tests (#3256)
Co-authored-by: kimi-agent-bot <kimi-agent-bot@users.noreply.github.com>
2026-08-26 14:14:41 +08:00
qer
6595955b31
fix(kap-server): report run_in_background on the task wire (#3239)
Some checks are pending
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / build (push) Waiting to run
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-vscode-legacy (push) Waiting to run
CI / typecheck (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
Release / Release (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
* fix(kap-server): report run_in_background on the task wire

The /tasks wire now carries the task's detached flag as
run_in_background (schema in both the kap-server local copy and the
public protocol package). A running foreground subagent used to be
indistinguishable from a background one on this surface — clients that
defaulted the missing field to true would treat it as background.

* chore: add changeset for the run_in_background wire fix

* fix(kap-server): make run_in_background a required wire field

The field is always emitted (ghost-restored records pre-dating it read
true: the persisted store only lists terminal-and-detached or running
tasks, which all carry a concrete flag). Making the contract required
means a producer that omits it fails as an ordinary protocol error
instead of clients silently re-interpreting the row as foreground

* fix(protocol): keep run_in_background optional in the public task schema

The public schema types the agent-core v1 task service too, which does
not emit the field — making it required there is a breaking protocol
change (and broke agent-core's typecheck). kap-server's own local
schema stays required: it is the sole writer of the /tasks response
and always emits. Consumers apply the foreground fallback when the
field is absent
2026-08-25 22:13:29 +08:00
tpoisonooo
1dc34b46de
fix(agent/loop): abort listeners (#3241)
* fix(agent-core-v2): remove the fsProcess abort listener after command completion

* fix(agent-core-v2): raise the abort-listener ceiling on step signals

* chore: add the abort-listener fixes changeset

---------

Co-authored-by: konghuanjun <konghuanjun@moonshot.ai>
2026-08-25 20:25:18 +08:00
Haozhe
f0a609487f
feat(kimi-code): add remote control web tunnel (#3034)
* feat(kimi-code): add remote control web tunnel

Add CLI and TUI entry points for exposing the local web UI remotely.
Bridge HTTP and WebSocket traffic with local authentication and reconnect handling.

* fix(kimi-code): prevent remote control websocket crash

* fix(kimi-code): align websocket dependency versions

* fix(kimi-code): harden remote control connection setup

Reconnect when management closes during the HTTP tunnel handshake.
Reject non-loopback Remote Control binds whose CSP blocks path bootstrap.

* fix(kimi-code): fix remote control rewriting, caching, and WS frame loss

* feat(kimi-code): add remote control QR output

* build: update pnpm dependencies hash

* refactor(kimi-code): remove the --allow-remote-terminals flag

* feat(kimi-code): add remote control lock, rc command, and QR fixes

* fix(kap-server): broadcast user prompts to all session clients on submit

- agent-core-v2: emit prompt.submitted (status running|queued) at enqueue and prompt.started when the turn launches
- kap-server: project prompt.submitted/prompt.started into transcript prompt entities and the live transcript REST response
- update flake.nix pnpmDeps hash for the PR lockfile

* fix(node-sdk): drop v2-only prompt.started from SDK event stream

- event-mapper: add prompt.started to the dropped v2-only prompt lifecycle types (parity with submitted/completed/aborted/steered)
- cli test: assert only visible sub-commands and stub the experimental flag env for determinism

* ci(pkg-pr-new): post custom install comment for npm 12 compatibility

* feat(kimi-code): render remote control QR as inline image on capable terminals

* feat(kimi-code): improve remote control terminal output

- add onboarding, security, device management, and help guidance
- show compact clickable links and QR image fallback details
- report relay and remote device connection lifecycle

* test(agent-core-v2): update tool event snapshot

* revert(ci): keep preview workflow unchanged in rc pr

---------

Co-authored-by: liruifengv <liruifeng1024@gmail.com>
2026-08-25 20:22:06 +08:00
Haozhe
e6a302b310
feat(agent-core-v2): add KIMI_CODE_INFINITE_RETRY infinite retry mode (#3240)
- retry every failed LLM request indefinitely in runRequest when
  KIMI_CODE_INFINITE_RETRY is set, covering turn steps and operation
  requests such as compaction
- keep projection recovery ahead of the infinite retry branch, honor
  Retry-After, and keep abort effective during backoff waits
- exclude context overflow from infinite retry so the deterministic
  turn-level and compaction-level overflow recovery paths still run
- extract retryBackoffDelay for single-attempt backoff computation
2026-08-25 19:51:46 +08:00
Haozhe
2102c43dce
refactor(agent-core-v2): migrate dateChange to an agent runtime injection effect (#3225)
Some checks are pending
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / build (push) Waiting to run
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-vscode-legacy (push) Waiting to run
CI / typecheck (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
Release / Release (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
- replace the Agent-scoped DI service with an eager non-durable Agent Runtime; the date_change injection provider registration now lives in an actor effect owned by the actor lifecycle, and the seed memo moves from the dateChange.seed state key into machine context
- honor eager: true for non-durable runtimes in AgentRuntimeSet so consumer-less runtimes still materialize
2026-08-25 14:12:50 +08:00
Haozhe
1ade345171
refactor: ban JSDoc in comment-free packages (#3226)
* refactor: ban JSDoc in comment-free packages

* fix: scan comments after a shebang in check-no-comments
2026-08-25 13:34:35 +08:00
Haozhe
4d5147ba5d
fix(agent-core-v2): keep agent lifecycle context active through scope teardown (#3206)
* fix(agent-core-v2): keep agent lifecycle context active through scope teardown

* fix(agent-core-v2): deactivate agents after scope-units teardown

* fix(kap-server): install process handlers only after successful startup

* fix(agent-core-v2): let the teardown finalizer own create-failure deactivation

* fix(agent-core-v2): await asynchronous scope-units teardown before deactivation

* fix(agent-core-v2): await agent scope teardown before completing removal

* fix(agent-core-v2): mark fire-and-forget scope disposals after awaitable dispose

* fix(agent-core-v2): return the in-flight promise from repeated disposeAsync

* fix(agent-core-v2): await child containers and keep kap-server handlers through shutdown
2026-08-25 11:10:49 +08:00
Haozhe
41f1eaed9a
refactor(agent-core-v2): merge contextInjector and systemReminder into reminder agent runtime domain (#3223) 2026-08-25 10:49:45 +08:00
Haozhe
243f348329
refactor(agent-core-v2): drop in-place system prompt refresh (#3211)
Some checks are pending
CI / build (push) Waiting to run
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-vscode-legacy (push) Waiting to run
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
Release / Release (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
2026-08-24 21:55:23 +08:00
Haozhe
71caabdc6d
feat(kap-server): add workspace-agnostic multi-root POST /api/v1/fs:suggest (#3210) 2026-08-24 21:37:41 +08:00
Haozhe
d3b27cc778
feat(agent-core-v2): enable tower through experimental flag (#3033) 2026-08-24 20:48:05 +08:00
tpoisonooo
15f20537c7
fix(tower): remove command queue (#3193)
* fix(tower): remove command queue

* feat(agent-core-v2): support an explicit base branch in TowerInit

* fix(kimi-code): keep tower objective order across a mid-turn compaction

* feat(agent-core-v2): add abandoned tower mission status to release stale scopes

* chore: consolidate tower changesets into one feature entry

* chore: consolidate tower changesets into one feature entry

---------

Co-authored-by: konghuanjun <konghuanjun@moonshot.ai>
2026-08-24 20:30:04 +08:00
Haozhe
2d00599010
feat(agent-core-v2): record turn-level tool repeats (#3209)
* feat(agent-core-v2): record turn-level tool repeats

* fix(agent-core-v2): bound turn repeat signatures
2026-08-24 20:25:15 +08:00
Haozhe
496bb6ce4e
feat(agent-core-v2): add independent [swarm] timeout_ms for AgentSwarm (#3198)
Add a dedicated [swarm] config section so AgentSwarm subagent timeouts no longer follow [subagent] timeout_ms: timeout_ms (default 7200000, i.e. 2 hours; 0 = no timeout) with the KIMI_CODE_SWARM_TIMEOUT_MS env override, mirroring the [subagent] section. Deliberate behavior change with no fallback: a value previously set in [subagent] timeout_ms to cover swarms needs to move to [swarm]. Print mode (kimi -p) keeps its no wall-clock cap semantics: [swarm] timeout_ms also defaults to 0 there unless explicitly set. Docs updated in both locales (config-files, env-vars, tools) and the config manifest regenerated.
2026-08-24 19:42:55 +08:00
Haozhe
f4dc9ba1ae
refactor(agent-core-v2): migrate skill domain to agent runtime (#3202)
- define the AgentSkill contract and SkillRuntime (activate /
  promptWithSkills / recordModelToolActivation) with a lazy, non-durable
  provider; recordActivation dispatches SkillActivated directly and the
  skillKey / SkillActivate relay is gone
- allow agent runtime descriptors to omit logic (durable definitions
  still require it), making skill the first pure-API domain
- featurize the skill domain: app/skillCatalog,
  workspace/workspaceSkillCatalog, session/sessionSkillCatalog,
  agent/skill, and agent/tools/skill move under src/features/skill;
  the static Skill tool registration and the AgentSkillService are gone
- resolve the runtime at the edge: kap-server routes and node-sdk
  activateSkill go through IAgentLifecycleService.resolve, and the
  klient dispatcher keeps the agentSkillService wire name over a
  per-agent view
2026-08-24 18:53:04 +08:00
Haozhe
09858919c4
refactor(kap-server): serve WS fs watch from the engine workspace fs watch service (#3196) 2026-08-24 15:22:57 +08:00
qer
2f12469301
fix(transcript): fold mid-turn task notifications into the current turn on cold rebuild (#3102)
* fix(transcript): fold mid-turn task notifications into the current turn on cold rebuild

* chore: changeset for the notification fold fix

* fix(transcript): key the notification fold on persisted task-turn boundaries, not the previous message role

* fix(transcript): collect background_task turn origins too, and fall back when the wire has no turn.started records

* fix(transcript): fold consecutive task notifications into the same turn

* fix(transcript): normalize folded notification text to the live title/body form

* fix(transcript): stop folded notification text before child blocks, preserve legacy background_task turns absent from the boundary set

* fix(transcript): truncate folded notification text at the first child-block tag, not just the tag lines

* fix(transcript): drop folded notifications without a persisted step, truncate only at output blocks

* fix(transcript): attach mid-turn task notifications to the following step, cold and live

* fix(transcript): keep other tasks' notifications in task-origin turns

* fix(transcript): derive task-turn boundaries from durable turn.prompt records

* feat(transcript): carry subagent model and thinking effort on task entities

* fix(transcript): mirror turn liveness into meta.activity, live and cold

* fix(transcript): populate the prompts entity from prompt.accepted/queued engine events

* fix(transcript): reconcile liveness and the prompt queue at backfill from the live loop state

* fix(transcript): include the prompts entity in the REST transcript response

* fix(agent-core-v2): publish prompt.accepted on the event bus

* test(transcript): add the contract-level e2e covering every entity the client renders from

* fix(transcript): guard the prompt backfill against missing services; align stream expectations with prompt.accepted on the bus

* test(agent-core-v2): re-record event stream snapshots with prompt.accepted published

* fix(transcript): settle the spawned agent row when its lifecycle redirects to the task row

* test(transcript): move the contract e2e timeout to the describe arg (jest lint)

* fix(transcript): declare task model fields in the wire schema, carry prompt content on accepted, normalize queued content

- transcriptTaskSchema declares model/thinkingEffort: Zod strips
  undeclared keys, so schema-driven REST/WS consumers lost both fields
  the projector now populates.
- PromptAccepted carries the admitted content (it is the only event a
  first-turn prompt ever emits, and the bare id left the prompts entity
  permanently partial) — projected with userMessageId and the public
  content shape via projectPromptContentParts, same as queued and the
  live backfill.
- Regenerate the wire manifest and re-record the affected event-stream
  snapshots.

* fix(transcript): preserve task model fields across termination and accepted prompt details across queueing

- onTaskLifecycle carried resultSummary/usage/error/stateReason but
  dropped model/thinkingEffort: a completed detached-Agent row lost the
  metadata spawned set while running.
- prompt.queued rebuilt the entity from scratch, discarding the
  userMessageId and createdAt that prompt.accepted had just stamped —
  build the queued update from prev.

* fix(transcript): keep prompt.accepted out of the public v1 event stream

The observable marker made the broadcaster forward every accepted
prompt to v1 WS clients, but events-zod has no accepted variant (v1
surfaces submission through the service-synthesized prompt.submitted)
and the SDK mapper didn't drop it — schema-driven clients could reject
the frame. Drop it at the WS edge and in the SDK's dropped set; the
transcript projection keeps consuming it internally.

* fix(transcript): derive cold task-turn boundaries through undo anchor replays

* fix(transcript): flush trailing folded notifications into the open turn

* fix(transcript): drop trailing buffered notifications to match the live projector

* chore: split transcript changesets per logical change

* fix(transcript): parse only the generated Title/Severity header lines in folded notifications
2026-08-24 14:33:36 +08:00
7Sageer
ee53d84fb0
fix(agent-core-v2): honor default thinking effort for secondary-bound subagents (#3191)
* fix(agent-core-v2): honor default_effort for secondary-bound subagents

[secondary_model].default_effort was parsed but never consumed, so a
subagent bound to a secondary/pool model resolved its thinking effort
from the main-oriented global [thinking].effort or the middle of the
bound model's support_efforts. Pass the section's default_effort as the
explicit spawn thinking, then fall back to the bound model entry's own
declared default_effort, both ahead of the global thinking config.

* docs(configuration): document secondary_model default_effort precedence

* fix(agent-core-v2): apply the model-default thinking fallback to tower spawns

TowerSpawnTool resolves the subagent binding directly and bypasses
planSpawn, so pool-bound tower workers never saw the bound model
entry's default_effort fallback. Apply the same resolution in launch.

* fix(agent-core-v2): preserve disabled thinking for subagents
2026-08-24 14:14:47 +08:00
Haozhe
4e16f2a869
refactor(agent-core-v2): migrate interaction to agent runtime contract and drop legacy runtime facilities (#3194) 2026-08-24 13:49:05 +08:00
Haozhe
9a715820c4
refactor(agent-core-v2): featurize todo/cron/interaction and migrate goal to agent runtime (#3184)
Some checks are pending
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / build (push) Waiting to run
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-vscode-legacy (push) Waiting to run
CI / typecheck (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
Release / Release (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
* refactor(agent-core-v2): featurize todo/cron/interaction and migrate goal to agent runtime

* refactor(agent-core-v2): move cron scheduling helpers into features/cron/internal
2026-08-23 23:03:51 +08:00
Liu Zhongnuo
ea0626ad48
fix(agent-core): gate background questions on task controls (#3159)
* fix(agent-core): gate background questions on task controls

* fix(agent-core): recheck background question policy
2026-08-23 20:40:23 +08:00
Haozhe
ffa877cfd8
fix(agent-core-v2): stop refreshing the system prompt on AGENTS.md changes (#3182) 2026-08-23 20:35:55 +08:00
Haozhe
2adc6a1c6e
fix(acp-server): restore local execution fallback, stdio MCP, and session reload (#3183)
* fix(acp-server): restore local process execution fallback

* fix(acp-server): accept stdio MCP servers in ACP sessions

* fix(agent-core-v2): allow runtime re-registration after removal

* chore: add acp regression fixes changeset

* fix(agent-core-v2): prune staged runtime entries when removal teardown fails
2026-08-23 20:31:33 +08:00
Haozhe
368b4b7400
refactor(agent-core-v2): migrate agent domains to agent runtime architecture (#3175) 2026-08-23 17:36:59 +08:00
7Sageer
d723cc47ee
feat(agent-core-v2): add the unified MCP management plane (#3002)
Some checks are pending
CI / build (push) Waiting to run
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-vscode-legacy (push) Waiting to run
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
Release / Release (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
* feat(agent-core-v2): add the unified MCP management plane

Port the v1 MCP management plane (#2858) onto the v2 DI x Scope engine:

- App-scope IMcpOAuthService shared by every workspace handler and
  session overlay: credential events, single-flight refresh, proactive
  refresh timers, OAuthTokenTransaction-serialized writes, offline
  tokenState, shutdown. Providers read tokens through the store so
  grants written or revoked by another process are honored immediately;
  http/sse transports ride the transaction fetch.
- IMcpConfigStore: the single write point for the user-level mcp.json
  over the filesystem byte store, byte-identical to v1's format, with
  per-entry validation, name normalization, __proto__-safe parsing, a
  mutation tail, and an onDidWrite event.
- IMcpRegistryService: the unified read view over the layered config
  files (with per-entry origins) and plugin manifests (full descriptors
  incl. disabled, with provenance); collisions stay visible and runtime
  resolution ranks an enabled plugin above the file layers.
- IMcpManagementService: guarded CRUD, connection-test probes, the
  locator-addressed inspection/auth-status surface, and
  locator-addressed OAuth begin/complete/cancel/reset with ambiguity
  rejection. Engine services stay ungated; the mcp_management flag
  gates the edge exposure.
- Workspace runtime aligns with v1 precedence (an enabled plugin entry
  wins over the file layers, shadows revive), and management writes
  reload immediately via onDidWrite instead of the watch debounce.
- node-sdk v2 facade delegates to the engine service (deleting its
  in-process duplication); kap-server exposes /api/v2/mcp/* and klient
  gains global.mcp.*, both flag-gated.

* fix(agent-core-v2): settle early and cancelled MCP OAuth callbacks

* refactor(node-sdk): write session MCP persists through the engine config store

* refactor(agent-core-v2): strip comments from the MCP management plane files

* fix(agent-core-v2): harden MCP management readiness

* test(node-sdk): cover offline MCP auth statuses

* fix(agent-core-v2): isolate stdio MCP probes

* fix(klient): normalize MCP OAuth errors

* fix(mcp): honor workspace CRUD context and refresh timing

* fix(mcp): drain OAuth refreshes during shutdown

* fix(mcp): guard CRUD across registry collisions

* fix(mcp): canonicalize trust and refresh scheduling

* fix(mcp): close callback listener on setup failure

* fix(mcp): preserve trust and oauth behavior

* fix(oauth): retain refresh tokens after SDK saves

* fix(oauth): stop proactive sweep during shutdown

* fix: await MCP workspace reconciliation

* fix: serialize MCP OAuth and trust cleanup

* fix: reject persisted MCP plugin collisions

* fix: reconcile MCP workspaces concurrently

* fix(mcp): check project-layer trust at the queried cwd

* fix(mcp): expire abandoned OAuth flows after an idle timeout

* fix(mcp): keep mutable user entries writable past read-only collisions

* fix(mcp): abort the auth::complete long poll on client disconnect

* fix(mcp): map OAuth flow failures to wire code 40929

* docs(mcp): note probe credential effects and plane semantics

* chore: add the SDK changeset for MCP management cwd params

* feat(mcp): expose the management plane without the experimental flag

* fix(mcp): preserve auth management semantics

* fix(agent-core-v2): bound MCP OAuth auth-server requests and the shutdown drain

* fix(node-sdk): restate engine MCP management errors as KimiError

* fix(agent-core-v2): preserve shared OAuth flow lifetime

* fix(agent-core-v2): close MCP OAuth cancellation and shutdown gaps

- bound the authorization-code exchange with the request timeout and the
  flow/caller abort signals, and make shutdown abort hung begins and close
  their callback listeners immediately
- keep token-transaction effect coalescing intact when durable tokens carry
  local stamps, and serialize the meta sidecar and tokens-saved event with
  the token write inside the lock
- drain transport-driven grants, their trailing SDK save continuations, and
  interactive completions during shutdown, with a cancellable deadline

* fix(agent-core-v2): harden MCP probe runtime resolution and path handling

- resolve stdio probes against the containing workspace's runtimes and
  reject out-of-workspace probes for non-local runtime_id instead of
  silently falling back to a local-only transient registry
- share one Windows-aware path canonicalization across the config loader,
  registry trust lookup, trust records, and workspace matching
- keep a UTF-8 BOM fatal for the user-level mcp.json store, matching the
  workspace loader and v1
- validate completeServerAuth timeoutMs bounds at the engine boundary

* fix(agent-core-v2): await workspace MCP reconciliation on plugin mutations

Plugin install/enable/disable/remove now resolve only after reload
listeners settle their waitUntil work, so a disabled plugin's MCP server
cannot linger connected and an enabled one is visible to the next
session, matching v1. The workspace MCP consumer joins the barrier while
keeping its log-only failure tolerance; delivery is awaited outside the
mutation queue to avoid self-deadlock through consumption reads.

* fix(mcp): close the SDK, klient, and server edge gaps

- register mcp.oauth_failed in the v1 error registry and restate unknown
  engine codes as internal instead of minting undeclared KimiError codes
- route persisted session MCP adds through the same KimiError restating
  as the global management methods
- give the klient IPC transport a per-call timeout so completeAuth's long
  poll outlives the 30s default, clamped to the Node timer ceiling, and
  align the contract timeoutMs upper bound with REST
- await the MCP OAuth service shutdown directly in SDK and server close
  before scope disposal

* fix(agent-core-v2): keep file-over-plugin MCP precedence and harden the plane

- Revert the v1-style precedence flip: the workspace merge and
  resolveRuntimeTarget keep the file entry above plugins (v2's historical
  order; the divergence from v1 is deliberate and documented in AGENTS.md).
- Guards follow each engine's winner: project-layer entries stay read-only,
  while plugin entries never block user-level writes, so a file entry may
  shadow a plugin and removing it revives the plugin. The parity suite pins
  the engine split for a persisted session add over a plugin-owned name.
- inspectServers tolerates a wire-encoded null targets array: klient's ipc
  transport sends null for an omitted leading optional argument.
- Fire the config store's onDidWrite after the mutation tail settles, so a
  write listener can re-enter the store without deadlocking the queue;
  concurrent-mutation and re-entrant-listener tests pin both contracts.

* chore: condense the sdk MCP changeset to one sentence

* test(node-sdk): pin verify:false auth-status parity and fix the sdk changeset
2026-08-22 18:22:37 +08:00
qer
0f44537c13
feat(agent-core-v2): turn /tower into a mode parallel to plan mode (#3099)
* feat(agent-core-v2): turn /tower into a mode parallel to plan mode

* feat(agent-core-v2): align /tower command semantics with the original skill behavior

* fix(tui): harden the /tower command against mid-turn objectives, legacy engines, and stale status

* fix(agent-core-v2): keep restored tower state inert while the feature flag is off

* fix(agent-core-v2): include TowerInit in the mode tool overlay and report flag-gated tower state

* feat(agent-core-v2): expose tower control tools statically and make the mode injection history-derived

* fix(tui): warn that tower mode needs a restart after a live flag flip; drop redundant undefined from SessionStatus mode fields

* fix(agent-core-v2): let tower mode exit clear persisted state while the flag is off

* fix(agent-core-v2): emit the tower exit reminder through a disabled flag and drop the redundant REST state comparison

* fix(tui): show the Tower mode status row only when the experiment is available

* fix(agent-core-v2): confine tower mode to the main agent and always re-assert it for objectives

* feat(kap-server): project tower mode into transcript modes and reassert explicit toggles

* fix(agent-core-v2): fold the main-agent invariant into the effective tower state

* fix(kap-server): gate the cold tower mode badge behind the experiment flag

* fix(agent-core-v2): reapply the tower tool overlay after a profile bind; fix(kap-server): clear cold tower badges on non-main agents

* fix(protocol): mirror towerMode and tower_mode in the shared zod schemas

* test(agent-core-v2): adapt tower tests to the agent lifecycle context architecture

* chore(agent-core-v2): regenerate the wire manifest; test(node-sdk): look up the main agent via findAgentHandle

* fix(agent-core-v2): exit a replayed tower mode when the workspace belongs to another session

* fix(agent-core-v2): carry tower ownership in the enter record so forks clear inherited mode

* fix(agent-core-v2): apply the tower overlay before dispatching enter and repair it on status updates

* fix(agent-core-v2): validate store ownership before entering tower mode

* fix(agent-core-v2): claim the repository tower owner at enter; fix(tui): confirm mode activation before reporting success

* fix(agent-core-v2): make the first tower claim exclusive and refuse adoption over a live owner

* feat(agent-core-v2): guard tower adoption and teardown with a cross-process ownership lease

* revert(agent-core-v2): drop the cross-process lease and enter-time claim, keep ownership checks process-local

* fix(agent-core): hide the v2-only tower flag from the legacy experiments list

* fix(agent-core-v2): keep tower mode inert until the tower feature is assembled

A live /experiments flip refreshes the flag but cannot re-run App-scope
feature assembly, so the tower tools/profile stay unregistered until a
restart. Gate enter()/isActive on the assembly fact and say so in the
TUI error. Also resolve the AGENTS.md conflict block committed by the
merge, and widen the TUI experimentalFlag type to string now that flags
live in two registries.

* fix(kap-server): gate the cold tower badge on tower feature assembly

Same live-flip gap as the mode machinery: a persisted tower_mode.enter
plus a flag enabled without a restart would still show the badge while
the feature is inert. Require isTowerFeatureAssembled() alongside the
flag, re-exported from agent-core-v2.

* fix(agent-core-v2): liveness-aware tower entry and per-App assembly state

enter() now mirrors TowerInit's adoption rule: a stored owner blocks
entry only while that session is live in this process, so a new session
can enter the mode and reach TowerInit to adopt a stale tower. The
assembly marker is keyed by each App's flag service (WeakSet) instead of
process-global module state, so coexisting Apps no longer leak assembly
into one another.

* fix(agent-core-v2): keep stale-owner adoption across resume; reject tower updates that do not take

exitForeignTower now treats a stored owner as foreign only while that
session is live, so a mode entered by adopting a dead owner's tower
survives close/restart. The TUI validates the model prerequisite before
enabling tower for an objective, and the REST agent_config path throws
session.tower_mode_invalid when enter() did not take effect instead of
acknowledging a no-op.

* fix(agent-core-v2): clear the tower assembly marker when the feature unloads

Register the WeakSet cleanup via the feature's onDispose so the
capability follows the managed unit's lifecycle — after
unprovideUnit('tower'), isActive/enter() no longer treat the retracted
tool set as assembled.

* fix(agent-core-v2): publish tower deactivation on gate loss; reject refused setTowerMode in the SDK

isActive now reconciles its projection: restore and feature-manager unit
changes publish AgentStatusUpdated({ towerMode: false }) when the
persisted mode lost a gate (flag off at runtime, feature unloaded), so
live transcript badges and TUI state stop showing an inert mode. The
SDK's setTowerMode(true) verifies the effective state and throws
session.tower_mode_invalid, matching the REST path.

* fix(agent-core-v2): reconcile tower projection on config changes and cold ownership moves

The last unreconciled gate inputs: a live setConfig writing the
experimental section (no session reload, no units event) now republishes
towerMode:false through the config-change subscription, and the cold
transcript badge mirrors the same ownership/liveness rule as enter() —
retained while the store owner is this session or no live session, cleared
once a live session elsewhere owns the tower.

* fix(agent-core-v2): reconcile the tower projection in both directions

The OFF-only reconcile left a hole: re-enabling the flag in the same
process made isActive true again with no towerMode:true publish, and
enter() could not heal it (it early-returns when already effective).
The projection now tracks the last published state and emits both
false→true and true→false transitions from the same restore/units/config
triggers; direct publishes (enter/exit/restoreTowerTools) keep the
tracker in sync.

* fix(agent-core-v2): validate forked tower ownership even while the flag is off

exitForeignTower's flag short-circuit let a fork restored while the
experiment was disabled keep its inherited enter record; re-enabling the
flag later revived both source and fork over the same store. Ownership
validation is flag-independent state hygiene, so restore now runs it
regardless of the effective flag — a live foreign owner clears the
fork's persisted mode before any gate can rise again.

* fix(agent-core-v2): veto tower tools while the tower experiment is off

With the feature assembled and the tool overlay active, disabling the
flag live left TowerInit/TowerTeardown callable — they have no flag
check — so prompts could still mutate or dismantle .tower/ while the
experiment reported disabled. A dedicated onBeforeExecuteTool hook now
denies every tower tool whenever the flag is off, mirroring the TodoList
veto.

* fix(agent-core-v2): keep tower worker write isolation when the flag turns off

The worker Write/Edit guard is identity-scoped (tower-worker profile),
not feature-activity-scoped: disabling the experiment live must not let
already-spawned detached workers write into the main checkout or other
worktrees. The guard no longer checks the flag; the tower-tool veto
added earlier covers protocol access instead.

* test(agent-core-v2): make tower tests hermetic for CI

Three CI-only failures: towerService git fixtures committed without a
repo-local identity (CI has no global gitconfig), the node-sdk tower
positive tests relied on the developer shell's
KIMI_CODE_EXPERIMENTAL_FLAG=1 master switch instead of enabling the
tower flag explicitly, and the legacy harness experimental-features
expectation still listed the tower entry removed from the v1 registry.
2026-08-21 14:47:37 +08:00
wszqkzqk
30e7f62d2c
fix(kaos): resolve Git Bash POSIX paths for file tools on Windows (#2200)
Some checks are pending
CI / build (push) Waiting to run
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-vscode-legacy (push) Waiting to run
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
Release / Release (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
Add a shell path bridge that translates between win32 paths and the
MSYS2/Git Bash path dialect. File tools resolve model-supplied paths
through it before canonicalization and workspace checks: drive-letter
forms translate lexically, root-relative paths resolve via cygpath -w
with per-segment caching, and every failure mode falls back to the
previous behavior.

Fixes #2199
2026-08-20 22:42:16 +08:00