Commit graph

1217 commits

Author SHA1 Message Date
_Kerman
dabf807205 Merge branch 'kimi-code-v2' of https://github.com/MoonshotAI/kimi-code into kimi-code-v2 2026-07-09 15:26:59 +08:00
_Kerman
65f5d24620 fix: align v2 media and task compaction handling 2026-07-09 15:23:07 +08:00
haozhe.yang
b51d77527e feat(kap-server): surface originating stack trace on error envelopes
- add optional `stack` field to errEnvelope and the envelope schema/interface; omitted when undefined so the wire shape stays byte-identical for callers without a stack
- thread `err.stack` through route error mappers plus the global and transport error handlers
- preserve `details` on `session.undo_unavailable` while adding its stack
- update tests to assert stacks are surfaced, reversing the prior no-leak contract
2026-07-09 15:11:16 +08:00
haozhe.yang
bf976f470c chore(agent-core-review): rename skill from kc-review to agent-core-review 2026-07-09 15:11:16 +08:00
_Kerman
d69ed4b331 fix(agent-core-v2): apply KIMI_CODE_CUSTOM_HEADERS and host identity headers
Port v1's provider-manager outbound header logic to agent-core-v2 so
`KIMI_CODE_CUSTOM_HEADERS` and host identity headers are applied to
outbound LLM requests, closing the migration gap from #1186:

- env `KIMI_CODE_CUSTOM_HEADERS` is the lowest-precedence header layer;
- host identity headers (User-Agent + X-Msh-*) are sent for Kimi
  providers, only the User-Agent for every other provider — a Kimi
  provider routed through the Anthropic protocol still gets the full
  set, matching v1;
- provider `customHeaders` always win on conflict.

Host headers are seeded by the CLI via `createKimiDefaultHeaders` and a
new `IHostRequestHeaders` App-scope token (defaulting to empty), so the
model resolver can layer them without the host threading them through
every call site.
2026-07-09 14:34:24 +08:00
_Kerman
a2cb30b1f6 Merge branch 'kimi-code-v2' of https://github.com/MoonshotAI/kimi-code into kimi-code-v2 2026-07-09 14:18:58 +08:00
_Kerman
7c094d8d6f fix(agent-core-v2): dedupe workspace registry entries by root
Port v1 #1221: collapse registered workspaces that share a root in list(), preferring the entry whose id matches the current canonical encodeWorkDirKey, so a legacy workspaces.json (v1-compatible) does not render the same folder twice through GET /workspaces.
2026-07-09 14:18:11 +08:00
_Kerman
d0f969bc30 fix(agent-core-v2): serialize concurrent model catalog refreshes
Port v1 #1207's _refreshChain so a scheduled refresh and a manual one (or two overlapping manual ones) never race on reading/patching the persisted config.

Applied to both refresh entry points: ModelCatalogService.refreshProviderModels (scheduler + all/single-provider) and OAuthService.refreshOAuthProviderModels (OAuth-only, a separate service in v2).
2026-07-09 14:18:07 +08:00
liruifengv
79a4125b41 feat(kimi-web): add status-aware browser notifications (#1479)
* feat(kimi-web): add approval notification storage key and i18n copy

* feat(kimi-web): add approval notification helpers and tests

* feat(kimi-web): wire approval notifications and guard completion alerts

* fix(kimi-web): extract shouldNotifyCompletion helper and add tests

* feat(kimi-web): add approval notification settings toggle

* chore(kimi-web): add changeset and tidy notification module comment

- Align approval notification tag with spec (kimi-approval-${approvalId})

- Update module header to describe all three notification kinds

* fix(kimi-web): make notifications fire reliably

- Key completion notification tags by turn (sid + promptId) and question
  tags by request id, so a stale notification left in the notification
  center no longer swallows every follow-up alert in the same session
- Suppress notifications only while the window is actually focused, not
  merely visible (document.hasFocus() on top of visibilityState)
- Play the attention sound when a tool needs approval, matching the
  completion and question sounds

* chore(kimi-web): simplify changeset
2026-07-09 13:59:37 +08:00
liruifengv
4d60160e55 docs(changelog): sync 0.23.3 and shorten OAuth error entry (#1509) 2026-07-09 13:59:37 +08:00
github-actions[bot]
ebb3c8fada ci: release packages (#1507)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-09 13:59:37 +08:00
7Sageer
760b922523 fix: surface provider auth error for unavailable models (#1506)
* fix: surface provider auth error for unavailable models

When an OAuth-managed model returns 401 after a forced token refresh, the token is valid but the provider rejected it for that model (the account lacks access). Emit provider.auth_error carrying the provider's message instead of auth.login_required with a misleading "OAuth login expired. Send /login" prompt.

* fix(agent-core): preserve provider auth errors through compaction

Treat provider.auth_error like auth.login_required in the compaction path so an auth rejection during compaction surfaces the provider's message instead of being wrapped as a generic compaction failure.
2026-07-09 13:59:36 +08:00
github-actions[bot]
f6f0dddf60 ci: release packages (#1468)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-09 13:59:36 +08:00
qer
066f54ab76 feat(web): prefix skill slash commands with skill: to distinguish them from built-in commands (#1492) 2026-07-09 13:59:36 +08:00
qer
3b1896ddc8 fix(web): composer model switch also updates global default model (#1491)
* fix(web): composer model switch also updates global default model

The composer model switcher still switches the active session's model via
POST /sessions/{id}/profile (awaited, so the model pill reflects the result),
and additionally fires POST /api/v1/config with { default_model } as a
fire-and-forget side effect so new sessions inherit the chosen default. The
config request is skipped when the model already matches the current default.

* fix(web): route ModelPicker overlay selection through the default-model update

The overlay opened from the composer's "More models" row (and /model) is a
continuation of the same switch flow, so its selection now also bumps the
global default model instead of only switching the active session.

* fix(web): only persist the default model after a confirmed session switch

setModel now returns whether the switch was accepted (true for the draft
path), so the composer flow no longer writes a stale or invalid model alias
into the global config when the session-level switch failed and rolled back.
2026-07-09 13:59:36 +08:00
liruifengv
e954b36b69 feat(web): redesign cron reminder as a message bubble (#1480)
* feat(web): redesign cron reminder as a message bubble

Restyle the cron trigger notice as a right-aligned user-style message bubble that shows the scheduled prompt in full (wrapping across lines), with a small meta row beneath it for the schedule, status, job id and run time. Extract a shared MessageTime component used by both user messages and the cron reminder so the timestamp format and click-to-expand behavior stay consistent, and give the CronCreate/CronList/CronDelete tools distinct calendar icons.

* refactor(web): render cron reminders only as standalone turns

Remove the embedded cron block path from the web transcript projector so cron reminder fires always render through the standalone right-aligned bubble path.

* chore(web): simplify cron redesign changeset
2026-07-09 13:59:36 +08:00
qer
90642aa29d feat(web): support Enter key to confirm archive and other dialogs (#1490) 2026-07-09 13:59:36 +08:00
qer
4683710096 feat(plugins): add Vercel plugin to marketplace (#1489) 2026-07-09 13:59:36 +08:00
qer
89f09b55eb fix(kimi-code): exit 1 when a headless (-p) turn fails (#1483)
Headless (`kimi -p`) failures could exit with code 0 when the event loop
drained during the shutdown cleanup (e.g. telemetry's unref'd retry backoff
when the network is blocked), because the rejection never reached the
process.exit(1) call. Set the failure exit code before any await in both
the run-prompt catch and the main catch, and keep the cleanup timeout ref'd
so the loop stays alive long enough for the rejection to propagate.
2026-07-09 13:59:36 +08:00
STAR-QUAKE
528e224f62 feat(agent-core): discard loaded tool schemas on compaction (#1471)
Align progressive tool disclosure with the discard-on-compaction model:
compaction no longer rebuilds loaded dynamic tool schemas. The boundary
announcement re-lists every loadable name, the model re-selects what it
still needs, and a from-memory call to a no-longer-loaded tool is
rejected by preflight with select guidance.

This removes the keep-all rebuild and its half-trigger budget heuristics
entirely: the post-compaction floor is back to users + summary, which is
structurally outside the auto-compaction trigger band, and the guard
baseline degenerates to summary + reinjected reminders. Every downstream
mechanism already treated the empty loaded set as its consistent base
state (ledger scan, pending clear at the compaction boundary, deferred
extras, preflight wording), so this is a strict simplification.

Co-authored-by: fengchenchen <fengchenchen@moonshot.ai>
2026-07-09 13:59:36 +08:00
Luyu Cheng
58b81ed916 fix: clarify goal blocked audit guidance (#1481) 2026-07-09 13:59:36 +08:00
_Kerman
c920c2edf6 feat(kosong): support structured response formats (#1397) 2026-07-09 13:59:36 +08:00
Luyu Cheng
65e46a2194 fix: count goal creation turn (#1477) 2026-07-09 13:59:36 +08:00
Kai
238f7746d4 fix(agent-core): report EXIF-rotated image dimensions and raise edge cap to 3000px (#1460)
* fix(agent-core): report EXIF-rotated image dimensions and raise edge cap to 3000px

Image compression now reports original dimensions in the decoded
(EXIF-rotated) space, matching the coordinate system of the sent image
and of ReadMediaFile region readback; previously portrait JPEGs
(orientation 5-8) got swapped width/height in captions. The longest-edge
downscale cap rises from 2000px to 3000px, and the default jimp resize
path is documented as the anti-aliased area-average one so it is not
accidentally switched to a point-sampled interpolation mode.

* test: shrink oversized image fixtures to fit CI timeouts

The 3600x3600 fixtures introduced for the 3000px edge cap nearly doubled
the pixel area jimp has to decode and deflate, pushing the slowest
compression tests past the 5s vitest timeout on CI runners. 3600x1800
keeps every fixture over the cap while restoring roughly the workload of
the old 2600x2600 fixtures that CI handled comfortably.

* test: pin anti-aliased downscale quality with executable guards

A 1px checkerboard probe pins the compressor to full-coverage averaging
at integer and fractional ratios, with jimp's point-sampled BILINEAR
mode kept as the executable aliasing counter-example (it collapses the
50%-gray pattern to solid black at 4:1). Also guards the other classic
downscale bugs: transparent-pixel color bleed, mean-brightness drift,
iterative recompression degradation, and zero-size collapse on extreme
aspect ratios.

* fix(agent-core): report decoded EXIF-rotated dimensions in ReadMediaFile notes

The media note derived its original-dimensions line from the header
sniff, which reports pre-rotation values for EXIF orientation 5-8
JPEGs. The sent image and region readback both live in the decoded
(rotated) space, so portrait photos got axis-swapped coordinate
guidance. Once a decode has happened — compression or crop — its
dimensions now overwrite the sniffed ones.

* fix(agent-core): improve handling of EXIF orientation in image dimensions and metadata

* fix(agent-core): sniff EXIF orientation and step budget fallback through 2000px

Two follow-ups to the EXIF and 3000px-cap changes:

sniffImageDimensions now reads the JPEG EXIF Orientation tag (pure
header parse, both byte orders) and reports display-space dimensions
for orientations 5-8. Passthrough images — never decoded — previously
kept the pre-rotation header size in compression results and media
read notes, disagreeing with the decoded space that region readback
uses.

encodeWithinBudget steps the over-budget fallback through 2000px
before the 1000px last resort. Raising the cap to 3000px had left a
regression window: an image whose 2000px encode fits the byte budget
was sent at 1000px where the old 2000px cap used to send it at
2000px.

* fix(kimi-code): record pasted image dimensions in display space

The TUI paste path recorded attachment and original dimensions from its
raw header parser, which ignores EXIF orientation. For a portrait JPEG
the submit-time caption then contradicted the sent image's aspect and
region readback coordinates were axis-swapped. Dimensions now come from
the compression result, which reports display space on both the
compressed and passthrough paths; parseImageMeta remains only the
format/mime gate.

* feat(agent-core): add image compression and crop telemetry

Every image ingestion path now reports an image_compress event —
outcome (compressed / passthrough fast, guard, unsupported, unhelpful,
error), input/output formats, byte and pixel sizes, EXIF transposition,
and duration — and region readback reports an image_crop event with a
failure classification and the region's share of the original area.

Wiring is per call site via a new CompressImageOptions.telemetry
option, so the outcome split and timing are measured inside the
compressor while each caller only names its source: ReadMediaFile
(tool construction, like GrepTool), MCP tool results (McpOutputOptions),
server prompt ingestion (ICoreProcessService now exposes the host
telemetry client), ACP prompts (session track adapter), and TUI paste
(host.track adapter). Properties are numeric/enum only — never paths
or content — and a throwing client can never affect the compression
result.

* fix(agent-core): run the full JPEG quality ladder at fallback sizes

The fallback rescales encoded only at quality 20, so a JPEG whose
ladder failed at the fitted size collapsed straight to the lowest
quality even when the smaller size left budget headroom for a higher
rung (the realistic window is the 1000px step, where the 4x pixel
drop pays for q80/q60). Each fallback edge now walks the same
q80-to-q20 ladder as the fitted size.

* test: shrink heavy JPEG fixtures and add explicit timeouts

The fallback-ladder test runs ~11 pure-JS JPEG encodes and the EXIF
paste test decodes, rotates, and re-encodes a 6.5MP frame; both sat at
the edge of the 5s vitest timeout on CI runners. Narrower fixtures cut
the pixel area (the ladder test keeps its width above 2000px so the
full fallback chain still runs) and explicit 15s timeouts absorb runner
variance.

* fix(server): scope prompt image compression telemetry to the session

The prompt-ingestion image_compress events were emitted with the bare
host telemetry client, while every agent-side source inherits a
session-scoped client — so prompt_inline/prompt_file events could not
be correlated with their session. The route now wraps the client with
withTelemetryContext({ sessionId }) like rpc/core-impl does for
session telemetry.

* chore(changeset): consolidate image compression changesets

One entry covering the cap raise and the EXIF dimension fix, listed
for both the CLI and the SDK so the SDK changelog's compression
description (previously pinned at 2000px) stays accurate.
2026-07-09 13:59:36 +08:00
_Kerman
0829601b1b Merge branch 'kimi-code-v2' of https://github.com/MoonshotAI/kimi-code into kimi-code-v2 2026-07-09 13:54:51 +08:00
_Kerman
3635b4c373 fix(agent-core-v2): align model-facing prompts 2026-07-09 13:54:31 +08:00
haozhe.yang
1f4dfce02f docs(agent-core-review): limit kc-review skill to agent-core-v2
Clarify that the kc-review lenses apply only to packages/agent-core-v2
(the DI x Scope engine), not to the legacy packages/agent-core or other
packages.
2026-07-09 13:50:40 +08:00
_Kerman
dcb58b7f3d Merge branch 'kimi-code-v2' of https://github.com/MoonshotAI/kimi-code into kimi-code-v2 2026-07-09 13:18:06 +08:00
_Kerman
b159946fc9 fix(agent-core-v2): refresh system prompt after compaction 2026-07-09 13:14:26 +08:00
haozhe.yang
536c4c0d44 feat(v2): auto-mint session ids and harden print-mode background drain
- make CreateSessionOptions.sessionId optional; SessionLifecycleService.create and fork now mint `session_<lowercase-uuid>` via a shared createSessionId helper, so edge layers stop minting their own ids (drop randomUUID in the v2 harness, ulid in kap-server)
- rework V2Session.waitForBackgroundTasksOnPrint to re-enumerate each round, suppress terminal notifications while waiting, and bound the drain by [task].print_wait_ceiling_s (default 1h) instead of a hardcoded 30s cap, so kimi -p can run long tasks to completion without being steered into a new turn
- add v2-session unit tests; seed session/agent/bootstrap context in the tool-dedupe harness for the real executor
2026-07-09 13:10:49 +08:00
haozhe.yang
f85dbdbf03 chore(skills): bundle review and test lenses into kc-review
- add agent-core-review umbrella skill with slop and test sub-skills
- move write-tests rules into agent-core-review/test and drop the standalone skill
2026-07-09 13:10:49 +08:00
_Kerman
14626234a4 fix(agent-core-v2): gate skill prompt injection 2026-07-09 12:58:07 +08:00
_Kerman
1f530d41a3 fix(agent-core-v2): align foreground output cap 2026-07-09 12:47:55 +08:00
_Kerman
d98d151ee4 chore: remove full compaction complete data type 2026-07-09 12:37:43 +08:00
_Kerman
2e8d75b133 Merge branch 'kimi-code-v2' of https://github.com/MoonshotAI/kimi-code into kimi-code-v2 2026-07-09 12:28:47 +08:00
_Kerman
c724a744f0 fix(agent-core-v2): preserve oversized tool results 2026-07-09 12:27:10 +08:00
7Sageer
87b3e3bce0 docs(agent-core-v2): clarify live-only op semantics 2026-07-09 12:23:15 +08:00
7Sageer
d13d92c2e0 fix(agent-core-v2): register KIMI_MODEL env overlay statically
The KIMI_MODEL_* effective overlay was registered by ModelService on construction, but the DI layer does not auto-instantiate Eager services, so the overlay never took effect when nothing resolved IModelService. This broke the release-e2e wire-llm-request-trace scenario, where KIMI_MODEL_NAME must synthesize the env model and its thinking capability.

Move registration to module load via a new configOverlayContributions collector, drained by ConfigRegistry on construction — mirroring the existing configSectionContributions pattern. ModelService no longer depends on IConfigRegistry.
2026-07-09 12:23:15 +08:00
qer
f397a3c3bd fix(agent-core-v2): use a fresh TextDecoder per append-log read
The module-level TextDecoder is stateful in stream mode: it buffers a
trailing incomplete multi-byte sequence until the next decode. Sharing it
across reads let leftover state from an earlier read that returned early
(e.g. ensureWireMetadata bailing on the leading metadata record) leak into
the next read and prepend a U+FFFD to its first line, corrupting the
metadata envelope and breaking session fork with "corrupted line 1".

Give each read its own TextDecoder so decoder state never leaks between
reads.
2026-07-09 12:12:20 +08:00
7Sageer
193d4418a5 Revert "fix: make release-e2e scenarios pass under agent-core-v2"
This reverts commit ec9dae72ab.
2026-07-09 11:57:05 +08:00
7Sageer
c377ab22a4 refactor(agent-core-v2): drop replay-only wire ops
Remove the three replay-only Ops that were kept for pre-alignment / 1.5 sessions, now that v2 persists natively in the v1 vocabulary:

- turn.launch (replaced by turn.prompt)

- todo.set (replaced by tools.update_store with key 'todo')

- context.splice (replaced by context.append_message / append_loop_event)

Also drop the dead code that handled them (transcript reducer, task-origin extraction, blob dehydration, harness helpers) and migrate the affected tests to the v1 record types. The live write path already emitted only v1 records, so wire.jsonl output is unchanged.
2026-07-09 11:47:22 +08:00
7Sageer
ec9dae72ab fix: make release-e2e scenarios pass under agent-core-v2
Three independent fixes for release-e2e failures that only appeared with the experimental v2 engine (KIMI_CODE_EXPERIMENTAL_FLAG):

- agent-core-v2: register the KIMI_MODEL env overlay statically so it takes effect even when ModelService is not instantiated (the DI layer does not auto-instantiate Eager services). Fixes wire-llm-request-trace.

- cli: omit the leading system.version meta line in stream-json prompt mode so the role sequence stays clean. Fixes stream-json-cron.

- agent-core-v2: honor --skills-dir via a new explicit skill source seeded from the host. Fixes interactive-skills-dir.

Cherry-picked from 2a7232737 (v2-migration), excluding the node-sdk V2Host change (not applicable on this branch).
2026-07-09 11:40:43 +08:00
haozhe.yang
667898b9df refactor(agent-core-v2): split blob service helpers, rewrite tests
- extract rewriteMediaUrls and blobref parse/format helpers to dedupe URL rewriting
- move the byte-bounded LRU cache into a module-private ByteLruCache with focused unit tests, dropping the protected maxCacheSize test seam
- rewrite blob service tests against the contract on in-memory storage, removing cache-internals cases
2026-07-09 11:22:17 +08:00
haozhe.yang
5355756652 refactor(agent-core-v2): move ReadTool status block to note side channel
- ReadTool.finishReadResult now returns rendered lines as `output` only and
  rides the `<system>` status block on the model-only `note` side channel
- drop the finishOutput helper that concatenated content and status
- update read.test.ts expectations to assert `note` separately from `output`
2026-07-09 11:15:47 +08:00
7Sageer
ad9cf87d2d refactor(agent-core-v2): persist wire records natively in the v1 vocabulary
Remove the persist-time v1 rewrite layer (serializeV1WireRecord): ops now
write v1-shaped records directly, live-only state is declared persist:false
on the op instead of being stripped at write time, and the swarm-exit
reminder pop replays from the swarm_mode.exit record via a cross-model
reducer. Fixes resumed sessions losing the todo list, drifting turn
counters after retries, and removed reminders reappearing on resume.
2026-07-09 01:18:11 +08:00
7Sageer
221e5da209 fix(agent-core-v2): dedupe AgentMeta legacy field declarations 2026-07-09 01:17:56 +08:00
haozhe.yang
3678dadd3b fix(agent-core-v2): strict-decode Edit reads, align with v1
- read the Edit target with errors:'strict' so a non-UTF-8 file fails the
  edit instead of being silently rewritten as U+FFFD (matches v1 kaos)
- declare readWriteFile access since Edit reads before it writes, matching v1
- render edit.md directly instead of through renderPrompt: it has no template
  vars, and raw avoids treating literal {{ }} as a template
- restore the replace_all usage example in edit.md (v1 #1102)
- add a regression test asserting a non-UTF-8 file fails the edit and keeps
  its bytes untouched
2026-07-08 22:36:16 +08:00
haozhe.yang
7fdddbb1ad refactor(agent-core-v2): run external hooks through IHostProcessService
- inject IHostProcessService into ExternalHooksRunnerService and thread it
  through runMatchedHooks to runHook instead of spawning node:child_process
- route hook termination through the service's cross-platform process-tree kill
- settle on the exit code plus drained stdout/stderr so fast-exiting hooks
  keep their trailing output
- hide the child console window on Windows via the service default
- update externalHooks tests for the new dependency
2026-07-08 22:36:15 +08:00
haozhe.yang
84b2989e8f feat(fs-watch): add workspace fs watch with v1-compatible WS delivery
- os layer: add IHostFsWatchService over chokidar (raw create/modify/delete, .git ignored)
- session layer: add ISessionFsWatchService, a workspace-confined, debounced, .gitignore-aware FsChangeEvent feed
- kap-server: add FsWatchBridge pushing event.fs.changed over /api/v1/ws (watch_fs_add/remove, volatile, per-connection filter), byte-compatible with v1
- tests: os/session unit tests and kap-server fs-watch e2e
2026-07-08 22:35:40 +08:00
haozhe.yang
295950f9a2 fix(agent-core-v2): fix cron killswitch, lost deliveries, id clashes
- killswitch: read KIMI_DISABLE_CRON live by re-applying the ConfigService
  env overlay on every get(); CronCreate reads it via ISessionCronService
  instead of a value frozen at tool registration
- delivery: resolve fire delivery on promptService.steer().launched so a
  rejected launch retains one-shot tasks for retry instead of deleting
  them; tick() is now async and awaits delivery before advancing cursors
- ids: switch cron task ids to ULIDs (from 32-bit hex) so two sessions
  sharing a workspace cannot overwrite each other's persisted task;
  CronDelete and persistence accept both ULID and legacy 8-hex ids
- display: CronCreate reports nextFireAt through the service so it honors
  KIMI_CRON_NO_JITTER and matches the scheduler and CronList
- migration: adopt shape-valid tasks with no sessionId tag on
  loadFromStore and stamp the tag back to disk
- persistence: create cron directories 0700 and files 0600 via
  FileStorageService dirMode/fileMode

Gate SessionCronService startup on config.ready and resolve clocks after
ready so config is never read before it is loaded; start() is now async.
2026-07-08 22:35:40 +08:00