Commit graph

673 commits

Author SHA1 Message Date
github-actions[bot]
50b919b67e
ci: release packages (#1752)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-16 10:17:32 +08:00
Kai
1d7c205e83
fix: close two silent-exit vectors around unhandled rejections (#1758)
Some checks are pending
CI / test-pi-tui (push) Waiting to run
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
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
CI / typecheck (push) Waiting to run
Release / Native release artifact (push) Blocked by required conditions
Release / Desktop release artifact (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
* fix: record crash telemetry for unhandled promise rejections

The crash handler only listened on uncaughtExceptionMonitor, which never
fires for a rejection that has a listener — and the TUI always registers
one, converting rejections into a silent exit(1) with no telemetry at
all. Observe unhandledRejection directly so those crashes still leave a
trace. Since registering a real listener suppresses Node's default
crash-on-rejection, rethrow when we are the only listener (print /
server modes), deduped so the monitor does not double-report.

* fix: fall back to text paste when the clipboard image handler rejects

The Ctrl+V image-paste dispatch chained off the async handler without a
rejection branch, so any failure inside it became an unhandled
rejection — which the CLI's crash path turns into a silent exit(1).
Treat a rejection like "no image available" and paste as text.

* fix: dedupe all rethrown rejection reasons at the crash monitor

Non-Error rejection reasons (plain objects, strings, null) were recorded
by the rejection handler but not added to the dedupe set, so the
uncaughtExceptionMonitor pass after the rethrow reported a second crash
for the same failure; null/undefined reasons also crashed the monitor's
own error-type extraction. Use a Set so primitives dedupe by value, add
every rethrown reason, and classify monitor crashes null-safely.
2026-07-16 02:14:14 +08:00
Kai
918c1354d9
fix: align Anthropic-compatible model capabilities (#1746)
* fix: align Anthropic-compatible model capabilities

* fix: warn on Anthropic effort mismatches

* fix: harden Anthropic model resolution

* fix: align Anthropic replay and ACP thinking state

* fix: normalize Anthropic thinking stream payloads

* fix: backfill non-empty preserved thinking

* fix: resolve session thinking effort with provider context

* fix: honor adaptive thinking opt-out in effort resolution
2026-07-16 01:31:38 +08:00
Kai
f0c8a103c6
fix: preserve the crash error in diagnostic logs on unexpected exit (#1757)
The TUI crash path (uncaughtException / unhandledRejection) logged the
error into an asynchronously-drained sink and then called process.exit()
on the same tick, so the one line explaining the crash was never written
to disk. Flush the diagnostic logs synchronously before exiting.
2026-07-16 01:26:27 +08:00
_Kerman
df75a0f5c2
refactor(agent-core-v2): derive session busy from agent activity (#1751) 2026-07-15 23:33:58 +08:00
qer
e885aec7ff
feat(web): show detailed diagnostics for model request failures (#1756)
Surface the coded provider error the daemon already sends: a semantic
title per error code, the provider's raw message, and expandable
diagnostics (error code, HTTP status, request ID, SDK error name) with
copy support, instead of a bare text-only toast.
2026-07-15 23:07:38 +08:00
qer
1186686554
fix(web): dedupe background subagent rows in the agents dock (#1754)
* fix(web): dedupe background subagent rows in the agents dock

* fix(web): seed agent identity on late task registration and prefer REST output in task fold

* fix(web): backfill terminal output to folded background subagent rows

* fix(web): sync subagent phase when the REST fold makes a row terminal
2026-07-15 23:07:23 +08:00
Haozhe
d8ddabb605
fix(kap-server): close auth bypass via percent-encoded API paths (#1753)
* fix(kap-server): fail closed on percent-encoded API paths in auth bypass

The auth hook checked the raw, still percent-encoded request URL against
its bypass policy, while find-my-way matches routes against the decoded
path. A raw /%61pi/v1/... URL therefore skipped the bearer-token check
yet still reached the /api/... handlers, allowing unauthenticated access
to every API route.

Decode the request path the same way the router does before matching,
and fail closed when the path cannot be decoded. Add tests covering
encoded /api/ paths, encoded meta documents, the encoded healthz probe,
and unaffected non-API bypasses.

* fix(agent-core-v2): make session fs path confinement symlink-aware

SessionFsService confined paths only lexically, so a symlink planted
inside the workspace could steer read, list, stat, mkdir, resolvePath
and resolveDownload to host files outside the session directory.

- add IHostFileSystem.realpath (Node fs.realpath semantics) and
  implement it in the node-local HostFileSystem
- resolveWithin now re-verifies each candidate through realpath of the
  longest existing prefix (so not-yet-created paths still work) and
  rejects paths escaping the canonicalized workspace roots, which are
  resolved once and cached
- cover symlink escapes for every fs entry point plus kap-server
  read/download e2e; in-workspace symlink targets remain allowed

* fix(agent-core-v2): accept workspace roots given through a symlink

WorkspaceRegistryService.createOrTouch probes the root with the
lstat-based IHostFileSystem.stat, so a root given as a symlink to a
directory reported isDirectory=false and session creation was rejected
with fs.path_not_found ("not a directory").

Re-check a non-directory root through IHostFileSystem.realpath before
failing, while keeping the workspace identity lexical (v1 deliberately
never realpaths the root either). Covered by a unit test for a
symlink-form root and a kap-server e2e that creates a session with a
symlinked cwd and reads a file through it.
2026-07-15 23:05:19 +08:00
_Kerman
4f99114342
refactor(kap-server): drop the @moonshot-ai/protocol dependency (#1755) 2026-07-15 22:40:05 +08:00
Haozhe
0b790cdc05
feat(web): allow attaching any file type and fix CSP on non-loopback binds (#1731)
* feat(web): allow attaching any file type in chat

- Composer, paste, and drop no longer filter out non-media files;
  arbitrary files upload as generic icon chips and are submitted as
  file content parts
- kap-server materializes file parts into the session's attachments
  dir and replaces them with a path reference, so the model opens the
  file with the Read tool on demand instead of receiving inline bytes
- Images rejected by the provider format gate (SVG, AVIF, ...) are now
  persisted and referenced by path instead of being dropped with a
  notice; uploaded file names are sanitized before hitting disk

* fix(server): stop CSP from blocking web bootstrap script and fonts

- Move the anti-FOUC bootstrap from an inline <script> in index.html
  to /boot.js: CSP 'self' never covers inline scripts, while a classic
  same-origin script keeps the same render-blocking timing
- Allow data: in font-src — KaTeX and the Inter / JetBrains Mono
  Variable fonts ship @font-face data URIs in their distributed CSS
- Set explicit form-action, base-uri, and frame-ancestors, which do
  not fall back to default-src
- Add a regression test asserting the served index.html carries no
  inline scripts or inline event handlers

* fix(web): normalize empty attachment MIME so extensionless files submit

Files with an empty File.type (Makefile, LICENSE, other extensionless
or unknown types) stored mediaType: '' on the chip, and the submit
fallback used ?? which does not catch empty strings — the wire schema
requires a non-empty media_type, so the prompt was rejected. Normalize
to application/octet-stream at attachment creation, adopt the
server-recorded MIME after upload completes, and make both submit
mappings use || so reloaded chips with '' are covered too.

* feat(web): render all user-turn attachments as chips

* feat(web): attach files by dropping them anywhere in the window

* refactor(web): share one attachment chip between composer and chat bubble

* fix(web): neutral attachment chips, paperclip attach icon, and clickable file chips

* fix(web): drop the extension badge from attachment chips

* fix(web): use the tabler paperclip for the attach button

* fix(web): whitelist attachment previews, reject active document types

Clicking a file chip navigated a new tab to a blob: URL of the uploaded
bytes whenever the type looked browser-renderable. blob: inherits the
web origin, so a text/html or image/svg+xml attachment would execute
same-origin script with the daemon credential (localStorage) and a live
window.opener.

Preview is now restricted to inert types (pdf, non-SVG images, video,
audio, non-HTML text), the blob is re-wrapped with the whitelisted MIME
instead of trusting the recorded content-type, and window.opener is
severed. Non-whitelisted types no longer silently download: the chip
reports 'unsupported' and the pane shows a transient hint.

* fix(web): recover file attachment chips from the server notice

The kap-server prompt route replaces file parts with an "Attached file
…" text notice before enqueueing, so after any snapshot resync the
attachment chip degraded into raw notice text leaking the absolute
server path — unlike image/video uploads, which already recover their
chip from the <video|image path> tag. Parse the notice the same way:
the materialized basename carries the file id, so the chip becomes
clickable again (and editable back into the composer); inline-base64
notices (content-hash named, no file id) still collapse into a
non-clickable chip instead of raw text.

The notice wording is now a client/server contract — flagged on
buildAttachedFileNotice.

* fix(web): preserve UUID file ids when rebuilding attachment chips

* fix(web): skip unresendable file chips when loading attachments for edit

---------

Co-authored-by: qer <wbxl2000@outlook.com>
2026-07-15 21:54:48 +08:00
qer
b89d385fa5
fix(web): confirm dialogs respond to Enter and await async actions (#1744)
Some checks are pending
CI / test (3) (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 (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (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 / Publish native release assets (push) Blocked by required conditions
Release / Deploy docs (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
Release / Desktop release artifact (push) Blocked by required conditions
Release / Release (push) Waiting to run
* fix(web): confirm dialogs respond to Enter and await async actions

The confirm dialog's initial focus was resolved from the Button
component's $el, which is a text node in dev builds (the component has
a template-root comment, so it renders as a fragment). Focus fell back
to the header close button, so Enter cancelled instead of confirming.
Resolve the initial focus with a CSS selector on the confirm button
instead.

ConfirmOptions now accepts an async action: the dialog stays open with
a loading state (cancel/Esc/overlay suppressed) until the work settles.
The archive-session, remove-workspace, and delete-provider confirms
move from the menu components into App.vue so the dialog can await the
actual client call.

* fix(web): block superseding a confirm dialog while its action runs

A second confirm() during an in-flight action would replace the busy
dialog and inherit the global busy state, opening inert until the first
action settled. Resolve the new request unconfirmed instead.
2026-07-15 20:04:50 +08:00
github-actions[bot]
6a8e610ca3
ci: release packages (#1702)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-15 18:00:18 +08:00
liruifengv
fcb63ebdc2
chore: downgrade unreleased changesets to patch (#1747) 2026-07-15 17:57:36 +08:00
qer
72f425e18d
fix(agent-core-v2): make Gemini tool call ids unique across turns (#1730)
* fix(agent-core-v2): make Gemini tool call ids unique across turns

* fix(kosong): recover tool names from entropy-suffixed Gemini call ids

The orphan tool-message fallback in toolCallIdToName stripped only one
trailing "_<suffix>" segment, so with the new
"{tool_name}_{upstream_id}_{entropy}" id shape it returned
"AgentSwarm_0" instead of "AgentSwarm" once the preceding assistant
call had been compacted away. Strip the fixed 8-hex entropy suffix
first, then the upstream id segment, in both the kosong and
agent-core-v2 providers. Also drop the inline implementation comment
that agent-core-v2 forbids outside the file header.

---------

Co-authored-by: haozhe.yang <yanghaozhe@moonshot.ai>
2026-07-15 17:47:53 +08:00
Luyu Cheng
481b28b8f4
fix(agent-core-v2): correct goal lifecycle error guidance (#1743)
* fix(agent-core-v2): correct goal lifecycle error guidance

* refactor(agent-core-v2): remove unused goal service API
2026-07-15 15:42:39 +08:00
Luyu Cheng
8a3f1ffa6f
fix(kap-server): derive session title from first skill slash command (#1741) 2026-07-15 15:42:25 +08:00
Haozhe
a74ab44ac7
feat: raise default per-step LLM retry budget to 10 attempts (#1740)
* feat: raise default per-step LLM retry budget to 10 attempts

The default of 3 attempts only produced ~1.5s of backoff (0.5s/1s), so
sustained provider overload (429) surfaced to the user almost
immediately. With 10 attempts the exponential ramp (500ms base, x2,
32s cap, 25% jitter) waits out multi-minute overload windows before
failing the turn. Applies to both agent-core (chatWithRetry) and
agent-core-v2 (stepRetry service); loop_control.max_retries_per_step
still overrides.

* test(agent-core): pin retry-dependent tests to the new default budget

- error-paths: the warn-log attempt field now reads 1/10 with the
  default 10-attempt budget
- goal-session pause tests: every LLM call throws a retryable error, so
  the default 10-attempt backoff (~2min) blew the 5s test timeout; pin
  maxRetriesPerStep=1 since the pause behavior does not depend on the
  retry count
2026-07-15 15:24:17 +08:00
qer
6eb8e13417
fix(kimi-web): improve mobile safe-area handling (#1459)
* fix(kimi-web): improve mobile safe-area handling

* fix(kimi-web): restore dock-height fallback where ChatDock is absent

* fix(kimi-web): pin the app shell to the visual viewport height

* fix(kimi-web): pin the app shell to the visual viewport

* chore: add changeset for mobile safe-area fixes
2026-07-15 14:50:01 +08:00
Haozhe
5d6ff022b1
feat(agent-core): drop default timeouts for print-mode background tasks (#1737)
* feat(agent-core): drop default timeouts for print-mode background tasks

- add `bash_task_timeout_s` config under [background] (0 = no timeout),
  covering the background Bash default and the re-arm after a foreground
  command is moved to the background on timeout
- allow `[subagent] timeout_ms = 0` (no timeout) and thread it through
  Agent/AgentSwarm task registration and the swarm batch timer
- fill both with 0 in print-mode config defaults so `kimi -p` never kills
  background work by wall-clock and only the model stops a task;
  interactive defaults are unchanged
- sync the Bash tool description/parameter text with the effective
  default and update user docs (en/zh) plus changeset

* test(agent-core): satisfy KimiConfig providers requirement in print-defaults tests

* fix(agent-core): clear the foreground deadline on detach when the background timeout is disabled

`detach()` only re-arms when `detachTimeoutMs` is defined, so passing
`undefined` with `bash_task_timeout_s = 0` kept the armed foreground
deadline and a manually detached command was still killed at its
foreground timeout. Pass `0` instead so the reset clears the timer.
Caught by Codex review on #1737.
2026-07-15 14:35:32 +08:00
Luyu Cheng
513f374aa0
fix(agent-core-v2): validate goal records (#1694) 2026-07-15 14:19:03 +08:00
qer
b6ae0a1054
fix(web): surface session list load failures (#1641)
* fix(web): surface session list load failures

* fix(web): preserve partial session pages
2026-07-15 13:58:03 +08:00
qer
d8d4e8ceb5
fix(web): keep long streams responsive (#1643)
* fix(web): keep long streams responsive

* fix(web): drop queued events for archived sessions
2026-07-15 13:47:11 +08:00
qer
b24a347e20
fix(kap-server): carry the live subagent roster in the session snapshot (#1719)
* fix(kap-server): carry the live subagent roster in the session snapshot

* fix(kap-server): clear the subagent roster on the next main turn start

* fix(kap-server): exclude background subagents from the snapshot roster

* fix(kap-server): finalize live roster entries when the main turn aborts

* fix(kap-server): drop roster entries when foreground subagents detach

* fix(web): expand the swarm card by default while subagents are running

* docs(kap-server): qualify the roster-clearing durability claim
2026-07-15 12:40:30 +08:00
liruifengv
286d3e7aca
feat: add check-kimi-code-docs builtin skill (#1727)
* feat(agent-core): add check-kimi-code-docs builtin skill

* feat(agent-core-v2): add check-kimi-code-docs builtin skill

* docs: list check-kimi-code-docs in builtin skill commands

* chore: add changeset for check-kimi-code-docs skill
2026-07-15 11:42:47 +08:00
Haozhe
3703d0346e
feat(agent-core): default print mode to steer with unbounded limits (#1722)
- change the default print background mode from 'exit' to 'steer' so
  `kimi -p` stays alive while background tasks are pending and each
  completion steers a new main turn
- add print-mode config defaults (applyPrintModeConfigDefaults):
  effectively unbounded wait ceiling and turn cap, 72h subagent
  timeout; explicit user config always wins
- thread the new `uiMode` option from SDKRpcClient through KimiCore
  into session create/resume
- clamp setTimeout delays to 0x7fffffff so huge timeouts are not
  clamped to 1ms by Node
2026-07-15 11:11:00 +08:00
Luyu Cheng
7de218a909
fix(kimi-web): resume paused goals (#1693)
Some checks are pending
Release / Release (push) Waiting to run
CI / typecheck (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-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
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
Release / Deploy docs (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
Release / Desktop release artifact (push) Blocked by required conditions
* fix(kimi-web): resume paused goals

* fix(agent-core-v2): defer paused goal continuation
2026-07-15 00:00:29 +08:00
Luyu Cheng
2bf009fe27
fix(agent-core-v2): reject subagent goals (#1697)
* fix(agent-core-v2): reject subagent goals

* fix(kap-server): guard reflected subagent goals
2026-07-14 23:30:30 +08:00
qer
de493aeec9
fix(web): use upward chevron for dock card expand buttons (#1715)
* fix(web): use upward chevron for plan card expand button

* fix(web): use upward chevron for question card expand button
2026-07-14 23:06:15 +08:00
Luyu Cheng
722694adf9
fix(agent-core-v2): enforce goal deadlines (#1698) 2026-07-14 23:00:05 +08:00
qer
20b69724aa
fix(web): make code block copy work over plain HTTP (#1714) 2026-07-14 22:31:36 +08:00
Luyu Cheng
5c0f17cfcf
fix(agent-core-v2): persist active goal time (#1695)
* fix(agent-core-v2): persist active goal time

* fix(agent-core-v2): migrate active goal anchors

* fix(agent-core-v2): migrate envelope-less goal logs

* fix(agent-core-v2): advance migrated goal checkpoints

* fix(agent-core-v2): align crash recovery with wire domain
2026-07-14 22:29:36 +08:00
Luyu Cheng
e53cd79957
fix(agent-core-v2): align goal turn budgets (#1692)
* fix(agent-core-v2): align goal turn budgets

* fix(agent-core-v2): preserve blocked goal outcomes

* fix(agent-core-v2): stop resumed goals at turn budget
2026-07-14 22:11:28 +08:00
Haozhe
78ca44b4d1
feat(kimi-code): keep print-mode goal runs alive until the goal settles (#1712)
* feat(kimi-code): keep print-mode goal runs alive until the goal settles

- applyPrintBackgroundPolicy waits for goal continuation turns via a goalActive hook before applying the exit/drain/steer mode, bounded by the wait ceiling
- createPrintTurnEndings skips the timeout when the remaining budget is not finite
- update the changeset to cover the goal-run lifecycle

* fix(kimi-code): wake the print goal wait periodically so settled goals exit promptly
2026-07-14 21:09:09 +08:00
Luyu Cheng
b781e8cbcf
fix(agent-core-v2): preserve goal continuations (#1696)
* fix(agent-core-v2): preserve goal continuations

* fix(agent-core-v2): cancel preserved continuation turns
2026-07-14 20:46:18 +08:00
Luyu Cheng
3107f963a5
fix(agent-core-v2): isolate replaced goals (#1700)
* fix(agent-core-v2): isolate replaced goals

* fix(agent-core-v2): tighten stale goal guards

* fix(agent-core-v2): preserve replacement goal budgets

* fix(agent-core-v2): continue replacement goals

* fix(agent-core-v2): adopt resumed goal turns

* fix(agent-core-v2): guard stale goal budgets

* fix(agent-core-v2): keep stale outcomes nonterminal

* fix(agent-core-v2): preserve same-batch goal outcomes

* fix(agent-core-v2): gate stale replacement outcomes

* fix(agent-core-v2): preserve replacement goal mutations

* fix(agent-core-v2): revalidate delayed goal creation
2026-07-14 20:32:05 +08:00
qer
9eff230f97
fix(web): show errors for failed actions and add daemon request/operation logging (#1711)
Some checks are pending
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-windows (push) Waiting to run
CI / build (push) Waiting to run
CI / test (1) (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 / Desktop release artifact (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
CI / typecheck (push) Waiting to run
CI / lint (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
* fix(web): show errors for failed actions and add daemon request/operation logging

* fix(web): dedupe identical operation-failure toasts to avoid flooding

* Revert "fix(web): dedupe identical operation-failure toasts to avoid flooding"

This reverts commit 54fcfdcc97a034d7236d61cbb3664292a8966c64.
2026-07-14 19:17:28 +08:00
qer
ddfdfb0b09
fix(server): synthesize session status only from the main agent's turn (#1708)
* fix(server): synthesize session status only from the main agent's turn

A sub-agent runs its own turn on the shared session channel, and the
broadcaster synthesized event.session.status_changed from every agent's
turn.started/turn.ended. A foreground sub-agent finishing mid-turn thus
emitted a bogus idle transition that clients read as 'turn finished'
(notifications, sounds, unread dots, queued-message drain), while the
real main-agent turn end was swallowed by dedup.

Gate the status synthesis on MAIN_AGENT_ID, matching the existing
main-only rule in InFlightTurnTracker.

* fix(server): emit idle when a sub-agent turn ends as the last active agent

Defensive follow-up to the main-only status synthesis: ensureState seeds
lastStatus from ISessionActivity, which counts any agent's turn, so a
session first activated while only a sub-agent was active would stay
running for subscribers until the next main turn. A sub-agent's own
lease and loop state are already released when its turn.ended is
published, so a session-wide idle activity read cannot be a
mid-main-turn foreground sub-agent — emit idle in that case only.
Dedup keeps it a no-op everywhere else.

* revert: drop the defensive idle emit for sub-agent-only turn endings

This reverts 7918b45fe. The stale-seed scenario it guarded is
effectively unreachable in production: sessions are activated at
creation / first prompt and stay active for the process lifetime, and
persisted detached tasks are reconciled as lost on restart, never
resumed. The guard also raised a new behavioral question of its own
(failed/cancelled sub-agent endings would emit a success-style idle).
Keep the PR to the minimal main-only status synthesis; the theoretical
corner self-corrects on the next REST status pull or main turn.
2026-07-14 18:35:49 +08:00
Haozhe
38a2363a00
fix: cross-version session compatibility and real message times in snapshot history (#1704)
* fix(server): report CLI version as server_version

- kap-server: accept opts.version in startServer, reported as
  server_version (/meta, OpenAPI, session exports, lock registry,
  default User-Agent); defaults to its own package version
- kimi-code: pass the CLI product version when starting the server
- add boot test covering /api/v1/meta, lock file, and User-Agent

* fix(agent-core-v2): make new sessions resumable by older v1 builds

- add wireRecord.seal() to write the metadata envelope at agent creation,
  so fresh logs satisfy v1 replay's first-record-must-be-metadata invariant
- seal the wire log before any op dispatch in AgentLifecycleService.create;
  no-op when the log already has records (resume / forked copies)
- seed empty agents/custom maps in session metadata so v1 Session.resume()
  can index agents['main'] on a v2-created state.json
- add seal unit tests and lifecycle sealing tests

* fix(kap-server): show real message send times in snapshot history

- read per-record times stamped on wire.jsonl via reduceContextTranscript
  and cache them alongside the transcript messages
- prefer each record's real dispatch time for created_at; records without a
  stamp fall back to session.createdAt + index, clamped so the page stays
  strictly increasing (mirrors MessageLegacyService.list)
- add tests for fallback, clamping, and the page-offset index mapping

* fix(agent-core-v2): backfill missing agents/custom maps in existing session metadata

- load() now heals pre-fix v2 state.json documents that never gained the
  agents/custom maps, persisting the backfill so one open on a new build
  leaves the session resumable by released v1 builds (Session.resume()
  indexes agents['main'] unconditionally)
- updatedAt is deliberately untouched so the format heal does not reorder
  session listings

* feat(agent-core-v2): make subagent timeout configurable, default 2h

- add [subagent] config section with timeout_ms and KIMI_SUBAGENT_TIMEOUT_MS env override
- resolve Agent and AgentSwarm per-run timeouts through resolveSubagentTimeoutMs
- update tool descriptions and tests to reflect the 2-hour default

* feat(agent-core-v2): align print-mode background policy with v1

- add printBackgroundMode/printMaxTurns to the task config section with resolvePrintBackgroundMode (keepAliveOnExit fallback)
- apply exit/drain/steer policy to kimi -p on the experimental engine, buffering turn.ended events and failing the run when a steered turn fails
- register the subagent config section from the package entry

* fix(agent-core-v2): strict equality in metadata heal, comments in file headers only

- replace == null with === undefined in the session-metadata heal to
  satisfy eqeqeq (oxlint --type-aware in CI)
- move the seal() rationale into the wireRecord contract header and the
  agents/custom invariant into the sessionMetadata header per the
  tree's header-only comment convention
2026-07-14 18:35:02 +08:00
Haozhe
8490c3e36b
feat(agent-core-v2): record compaction droppedCount in wire traces and rename select_tools capability (#1707)
* feat(agent-core-v2): record droppedCount on full-compaction llm.request wire ops

- add per-attempt droppedCount to the llm.request source logFields so
  replays can see how much history each retry round blinded
- cover compaction/loop request events in the full-compaction test

* refactor(agent-core-v2): rename select_tools capability to dynamically_loaded_tools

- rename the ModelCapability bit and catalog field across capability.ts,
  catalog.ts, modelResolverService and the toolSelect gate
- update toolSelect flag description wording to match
- update all affected tests and the test harness capabilityNames helper

* chore: add changesets for v2 wire trace and capability rename
2026-07-14 18:01:11 +08:00
Haozhe
07c3632415
fix(workspace): sync workspace catalog across v1/v2 and soft-delete (#1701)
- register the cwd in workspaces.json when a v1 (TUI/SDK) session is
  created, via a shared workspaceRegistryFile read/write/touch module
- merge session_index.jsonl into the catalog once at v2 startup
  (awaited during kap-server boot), adding only paths absent from
  workspaces.json
- make v2 workspace delete a soft delete through the v1-compatible
  deleted_workspace_ids field: the session-index merge never resurrects
  tombstoned ids, while an explicit createOrTouch clears the tombstone
2026-07-14 17:34:35 +08:00
github-actions[bot]
1d2249bfa4
ci: release packages (#1682)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-14 17:03:41 +08:00
qer
ab22a2adf0
fix(web): show just the thinking level name in the model pill (#1689)
Drop the "thinking:" / "思考:" prefix from the effort suffix and
capitalize the level via effortLabel, matching the segment labels.
2026-07-14 17:00:09 +08:00
Haozhe
94c0ef89d2
fix(agent-core): re-register builtin tools when provider resolves late (#1688)
When the model provider becomes resolvable only after the agent starts
(async OAuth / managed free-tokens registration), the builtin tool table
stayed empty: initializeBuiltinTools was gated on hasProvider at fixed
checkpoints and none fired. loopTools now self-heals on read once a
provider resolves, so tool calls no longer fail with "Tool not found".
2026-07-14 16:37:17 +08:00
Kai
d158e0a7ac
fix: resolve and synchronize thinking effort (#1625)
* fix: preserve provider thinking effort values

* fix: resolve Kimi thinking effort fallbacks

* fix: use resolved Kimi effort in v2 requests

* fix: align Kimi effort resolution paths

* fix: synchronize forced Kimi effort state

* fix: synchronize forced Kimi effort in v2 state

* fix: tolerate unresolved models in v2 status
2026-07-14 16:37:03 +08:00
Kai
e417ee7c2c
fix(kosong): restore Kimi preserved-thinking sessions (#1684)
* fix: preserve empty reasoning across providers

* fix(kosong): restore Kimi preserved-thinking sessions
2026-07-14 16:17:48 +08:00
Luyu Cheng
ec1c9748c8
fix(agent-core-v2): preserve goal completion summaries and error messages (#1678)
* fix(agent-core-v2): preserve goal completion summaries

* fix(agent-core-v2): preserve loop error messages

* fix(agent-core-v2): keep goal cancellation responsive
2026-07-14 15:13:47 +08:00
qer
0f64b4dcc4
fix(web): submit thinking level verbatim and drop the hardcoded default (#1673)
* fix(web): submit thinking level verbatim and drop the hardcoded default

Align kimi-web's thinking-level handling with the TUI:

- Submit the stored level as-is on every prompt path (prompt, steer,
  skill activation, BTW side chat) instead of coercing it onto the
  target model's declared efforts.
- No stored preference (undefined) instead of a hardcoded 'high'
  default: prompts omit the thinking override and the daemon resolves
  the config/model default, same as an unset [thinking] in the TUI.
- Model switcher pre-selects the target model's own default level when
  switching models; re-selecting the current model keeps the level.
- Display the effective level (stored value, else the model default)
  in the composer, mobile sheet, and /status panel.

* chore(web): remove the dead dev:stub script

The stub daemon (dev/stub-daemon.mjs) no longer exists, so the
dev:stub npm script and its docs references were dead weight.

* fix(web): pin the model default thinking level and persist picks globally

- With no stored preference, loadModels() pins the active model's
  catalog default_effort as a concrete in-memory value, so what the
  UI shows, what prompts submit, and what the session runs always
  agree. localStorage stays reserved for levels the user picked.
- setThinking and model switches now also write the daemon-wide
  [thinking] config (same mapping as the TUI's thinkingEffortToConfig),
  so sessions created by other clients inherit the pick.
2026-07-14 15:04:28 +08:00
github-actions[bot]
2383137f3e
ci: release packages (#1583)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-14 15:01:30 +08:00
Haozhe
003e583d86
fix(agent-core-v2): project support_efforts and default_effort in the model catalog (#1677)
Align toProtocolModel with the v1 projection and the protocol wire schema by applying effectiveModelConfig and emitting support_efforts / default_effort, so clients of the v2 /models endpoint see thinking-effort levels again.
2026-07-14 14:53:50 +08:00
Kai
d1820ff0f8
fix: preserve empty reasoning across providers (#1676) 2026-07-14 14:30:56 +08:00