Commit graph

682 commits

Author SHA1 Message Date
haozhe.yang
bfaa75d320 feat(agent-core-v2): load AGENTS.md hierarchy and surface size warning
- add profile/context.ts to load the user- and project-level AGENTS.md
  hierarchy with a 32KB soft budget
- add AgentProfileService.applyProfile as the production entry point that
  assembles SystemPromptContext and renders the profile
- add SessionWarningService as the getSessionWarnings producer, surfacing
  agents-md-oversized instead of silently truncating
- cover loading, applyProfile, and the warning surface with tests
2026-07-01 12:06:20 +08:00
haozhe.yang
8fbd378277 feat(agent-core-v2): add shared rg locator/runner and explore git context
- add agentFs/rgLocator: shared ripgrep resolution (system PATH, then optional
  cached fallback) driven through a caller-supplied RgProbe
- add agentFs/runRg: shared Glob rg subprocess plumbing on IKaos
  (timeout/abort, capped output, two-phase kill, EAGAIN single-thread retry)
- rewrite GlobTool to use the shared locator/runner and track fallbacks
- make Grep resolve rg through the shared locator and emit
  fs_grep_node_fallback telemetry when rg is missing
- add agentFs/gitContext.collectGitContext and prepend a sanitized
  <git-context> block to fresh explore subagent prompts
- add noopTelemetryService for tools constructed outside DI
- cover gitContext, glob, fsService, and fileToolsService with tests
2026-07-01 11:57:25 +08:00
haozhe.yang
cc3422c77a feat(agent-core-v2): add plugin management and consumption plane
- parse kimi.plugin.json / .kimi-plugin/plugin.json manifests
  (skills, sessionStart, mcpServers, hooks, commands)
- install plugins from local paths, zip URLs, and GitHub refs via
  the manager, store, source, archive, and github-resolver modules
- load plugin slash commands from .md files with $ARGUMENTS expansion
- register IPluginService/PluginService (App scope) exposing management
  plus consumption planes: skill roots, session starts, MCP servers, hooks
- add session-start context injector and RPC prompt metadata
- cover manifest, manager, source, archive, github-resolver, commands,
  and session-start injection with tests
2026-07-01 11:52:35 +08:00
haozhe.yang
97874de529 feat(loop): split llm stream timing into client and server phases
- add requestBuild/serverFirstToken and serverDecode/clientConsume fields to LLMStreamTiming and LoopStepEndEvent
- forward the split timing through AgentLoopService event and streamTiming mapping
- inject ILogService into AgentLoopService and emit a per-step 'llm response' log via logStepTiming to attribute slow turns
2026-07-01 11:47:22 +08:00
haozhe.yang
4d103c5d76 feat(server-v2): add auth and request security hardening
- add persistent bearer-token auth (token store, credentials, password hashing)
- gate HTTP and WebSocket (bearer subprotocol) upgrades behind auth
- classify loopback vs non-loopback binds and validate hostnames/origin
- add rate limiting and security headers middleware
- add GUI store service and routes
- add process file locking
2026-07-01 11:44:20 +08:00
haozhe.yang
1745ea074a docs(agent-core-dev): rename Core scope to App and drop Turn tier
- replace `Core` with `App` across the skill docs and dep-graph.mjs
- drop the `Turn` scope, collapsing the four-tier tree to three (App/Session/Agent)
- update examples, anti-patterns, banned entity-service names, and createCoreScope -> createAppScope
2026-07-01 11:18:46 +08:00
haozhe.yang
cd47ef4aff refactor(agent-core-v2): rename scoped services to encode scope
- rename service interfaces and implementations to carry the Session/Agent
  scope prefix and Service suffix (e.g. IApprovalService ->
  ISessionApprovalService, ApprovalService -> SessionApprovalService)
- rename LifecycleScope.Core to App in the DI base
- update DI createDecorator keys to match the new identifiers
- propagate the renames through server-v2 routes/transport, examples, docs,
  and the agent-core-dev skill
2026-07-01 01:05:53 +08:00
haozhe.yang
075262a49d Merge remote-tracking branch 'origin/main' into kimi-code-v2 2026-06-30 21:25:35 +08:00
haozhe.yang
6219fa6866 feat(agent-core-v2): give ContextMessage a stable id
- stamp `msg_<ulid>` on every message entering IContextMemory and persist it
  in the context.splice wire record, so ids survive restore
- carry the provider response id as `providerMessageId` on assistant messages
- thread `promptMessageId` from prompt -> turn -> turn.started ->
  InFlightTurnTracker, so snapshot `current_prompt_id` comes from the native
  path instead of post-hoc enrichment
- project real ids on the wire and look up messages by id; drop the positional
  parseMessageId
- make the v1 prompt_id equal its user message id
2026-06-30 21:25:01 +08:00
Haozhe
ceb27f5e44
feat(server): add GUI store API mirroring localStorage (#1231)
Some checks are pending
CI / build (push) Waiting to run
CI / test (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 / 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
Release / Release (push) Waiting to run
* feat(server): add GUI store API mirroring localStorage

- add /api/v1/gui/store/* endpoints (getItem/setItem/removeItem/clear/length) mirroring the browser localStorage interface
- add IGuiStoreService persisting opaque string values to ~/.kimi-code/gui.toml via smol-toml with atomic writes and an in-process write lock
- wire protocol schema, service, routes, and DI registration; add e2e tests and update the API surface snapshot

* chore: add changeset for gui store api

* fix(server): harden GUI store key handling and file permissions

- use a null-prototype record and an own-property check so keys that exist on Object.prototype (toString, constructor, __proto__) behave like ordinary keys
- write gui.toml with 0600 permissions so unsent drafts and input history stay private to the owning user
2026-06-30 21:04:59 +08:00
haozhe.yang
db3a7c4f43 fix(server-v2): serve cold session messages from wire transcript
- add MessageLegacyService (agent-core-v2 L7 edge adapter) implementing the
  v1 GET /sessions/{sid}/messages contract on top of the native services
- cold sessions: load + restore the main agent wire log and read the full
  transcript from IReplayBuilderService; live sessions keep reading
  IContextMemory
- rewrite the messages route as a thin adapter over the legacy service
- register the message.not_found (40403) error code in protocol and
  agent-core-v2
2026-06-30 21:02:23 +08:00
qer
aa6b0d065e
feat(web): always show the usage-data opt-out toggle in settings (#1232)
The telemetry toggle was hidden unless the config explicitly set a value, and its on/off mapping treated the default (unset) state as off even though telemetry is enabled by default. Show it always, treat unset/true as on, and rename it with a description and a restart note.
2026-06-30 20:49:35 +08:00
haozhe.yang
37d3953368 fix(server-v2): align /sessions/:tail actions with v1
- forward undo and archive results from ISessionLegacyService instead of
  re-paginating undo in the route and hardcoding the archive response
- drop the AUTH_TOKEN_MISSING error mapping that v1 does not declare
- move the ContextMessage -> Message projection into agent-core-v2 so
  the session legacy service owns the undo response shape
2026-06-30 20:11:42 +08:00
haozhe.yang
05053ee845 fix(server-v2): align GET /api/v1/auth with v1 readiness summary
The v2 readiness probe returned a simplified snapshot: default_model was
hardcoded to null, providers_count counted only oauth providers, and
managed_provider was synthesized from any authenticated provider. Mirror
v1's AuthSummaryService.get() through a new L7 edge adapter.

- add IAuthLegacyService projecting provider/config/oauth state into the
  v1 AuthSummary wire shape; the native IAuthSummaryService keeps serving
  /api/v2 untouched
- default_model reads the configured defaultModel
- providers_count counts every configured provider
- managed_provider reflects managed:kimi-code cached-token state and is
  null when that provider is absent
- ready matches v1 (providers >= 1, default model set, not revoked)
- register authLegacy at L7 in the domain-layer map
2026-06-30 19:54:43 +08:00
qer
5cb80ce879
feat: support plugin slash commands (#1204)
* feat(agent-core): support plugin slash commands

* feat(node-sdk): expose listPluginCommands

* feat(kimi-code): register and dispatch plugin slash commands

* chore: add changeset for plugin commands

* feat(agent-core): activate plugin commands server-side

* feat(node-sdk): add activatePluginCommand

* feat(kimi-code): render plugin command activations compactly

* feat(agent-core): recurse plugin command directories and preserve namespace

* fix(kimi-code): parse nested plugin command names

* fix(agent-core): update prompt metadata for plugin command turns

* fix(kimi-code): replay plugin command turns as command cards

* fix: treat plugin-command origins as real user prompts in undo

* fix(kimi-code): guard model-empty and clear plugin command render ids

* fix: propagate plugin_command to web and vis turn projectors

* fix(kimi-code): refresh plugin commands through auth flow

* fix(kimi-web): render plugin command cards in chat pane

* fix(kimi-web): render plugin command card in desktop chat view

* fix(kimi-code): treat slash-activation cards as transcript turn boundaries

* fix(kimi-code): count slash-activation entries when trimming transcript turns

* fix(kimi-code): preserve plugin command args in undo selector
2026-06-30 19:38:01 +08:00
haozhe.yang
2fc1fbc648 fix(server-v2): resolve workspace branch from .git/HEAD
- read .git/HEAD and peel ref: refs/heads/<branch> to populate branch
- resolve the real git dir through a .git worktree/submodule file
- keep detached HEAD and unreadable files as branch: null
- add branch-resolution tests for slash branches, detached HEAD, and worktrees
2026-06-30 19:30:17 +08:00
Kai
42e37eb898
feat(timing): split TTFT into api-server and client portions (#1228)
* feat(timing): split TTFT into api-server and client portions

Time-to-first-token previously lumped in-process request building
(message serialization, param assembly) together with network + server
latency, making it impossible to tell whether a slow turn was the client
or the API server.

Add an `onRequestSent` hook to kosong's GenerateOptions, fired by every
provider immediately before it dispatches the network call. The window
from request start to dispatch is attributed to the client; the window
from dispatch to the first streamed token is attributed to the API
server. The split flows through the step.end / turn.step.completed
events (and therefore wire.jsonl) and is surfaced in three places:

- KIMI_CODE_DEBUG=1: `TTFT: 2.5s (api 2.4s + client 100ms)`
- session log: new `llm response` line with the timing breakdown
- vis: firstToken/api + firstToken/client rows and timeline label

The split is omitted (total only) when a provider does not report the
boundary, preserving backward compatibility.

* feat(timing): split the decode window into server vs client time

Time-to-first-token now reports a client/server split, but the slow part
of a long turn is the decode window (inter-token streaming), which was
still a single opaque number. Profiling long sessions showed decode
throughput halving over a session's lifetime independent of context
size, which the synchronous per-chunk stream pipeline can cause: kosong
awaits the host callback for every streamed part, so a loaded main
thread throttles how fast tokens are pulled off the wire.

Account for this directly in the stream loop: the time awaiting the next
part (server + network) versus the time spent processing each part
in-process (deep copy, host callback, part merge). The split is reported
through onStreamEnd and flows through the step.end / turn.step.completed
events (and wire.jsonl) into the same three surfaces as the TTFT split:

- KIMI_CODE_DEBUG=1: `TPS: 40.0 tok/s (200 tokens in 5.0s; server 4.6s + client 400ms)`
- session log: serverDecodeMs / clientConsumeMs on the `llm response` line
- vis: streamDuration/server + streamDuration/client rows and timeline label

A large, growing client share confirms host-side throttling; a dominant
server share points at the server/connection. The per-chunk accounting is
wrapped in try/finally so it stays correct across `continue` and aborts,
and is omitted when the stream reports nothing.
2026-06-30 19:15:02 +08:00
haozhe.yang
73a419ff29 feat(agent-core-v2): implement and register remaining builtin tools
- background: add TaskList / TaskOutput / TaskStop and register them in BackgroundService
- goal: add CreateGoal / GetGoal / SetGoalBudget / UpdateGoal; extend IGoalService with markComplete, markBlocked, setBudgetLimits
- skill: register the Skill tool in AgentSkillService
- question: add AskUserQuestion (foreground + background) via a new Agent-scoped QuestionToolsService
- web: add FetchURL / WebSearch with LocalFetchURL and Moonshot fetch/search providers; add @mozilla/readability and linkedom deps
- move ToolResultBuilder into the tool domain so it can be shared across tool domains
- wire IQuestionToolsService and IWebService into AgentRPCService so the new registration services are instantiated
2026-06-30 18:47:01 +08:00
haozhe.yang
c43177019c feat(server-v2): add session children and warnings endpoints
- surface custom metadata in session index summaries so child sessions can be filtered without per-session document reads
- add ISessionLegacyService.createChild/listChildren: children are forks tagged with parent_session_id + child_session_kind, listed by those markers
- wire GET/POST /sessions/{id}/children and GET /sessions/{id}/warnings, reusing the protocol schemas and mapping session.not_found / session.fork_active_turn
- register the sessionLegacy domain at L7 in the domain-layer check
2026-06-30 18:47:01 +08:00
haozhe.yang
78fa333c98 refactor(agent-core-v2): switch FileStorageService.watch to chokidar
- replace node:fs fs.watch with a chokidar FSWatcher on the parent
  directory (depth 0), filtering events by normalized path so the
  match is correct on Windows as well as POSIX
- keep the existing Event<void> contract, 150ms debounce, and
  ref-counted arm/disarm lifecycle
- add chokidar ^4.0.3 and refresh the lockfile
- settle the watcher in storage watch tests to account for
  chokidar's asynchronous OS-watcher attachment
2026-06-30 18:47:01 +08:00
haozhe.yang
b94c60d50a feat(server-v2): add /api/v1/ws with seq/epoch watermark and resync
Bring the v1 WebSocket protocol to server-v2 so web clients get gap-free
sync across reconnects instead of silently losing events.

- per-session durable event journal with monotonic seq + epoch, recovered
  across restarts
- SessionEventBroadcaster: single per-session fan-out, durable/volatile
  classification, and cursor-based replay (buffer_overflow / epoch_changed)
- WsConnectionV1: client_hello / subscribe with cursors, replay or
  resync_required, and ack carrying authoritative server cursors
- GET /sessions/:id/snapshot: atomic-at-a-watermark state and in-flight turn
- IAgentLifecycleService: onDidCreate / onDidDispose for agent discovery
- GET /connections: list live WebSocket clients
2026-06-30 18:47:01 +08:00
haozhe.yang
858e0f8db7 feat(agent-core-v2): persist workspace registry and rebuild from session index
- add IWorkspaceStore + FileWorkspaceStore persisting the catalog to <homeDir>/workspaces.json in the v1-compatible schema
- WorkspaceRegistryService loads from the store, caches in memory, and writes through on create/update/delete
- when workspaces.json is absent or malformed, rebuild from the legacy session_index.jsonl (one workspace per distinct workDir)
- add tests for cross-instance persistence, rebuild, and write-through
2026-06-30 18:47:01 +08:00
haozhe.yang
d210009877 feat(server-v2): port v1 /sessions/{tail} action routes
- implement SessionLifecycleService.fork (active-turn guard, per-agent
  wire-log copy, metadata rewrite, forked marker, closed-session fork)
- add SessionLegacyService edge adapter for compact/undo/abort/btw over
  the native v2 services
- persist agent transcripts via per-agent homedir and extend SessionMeta
  (isCustomTitle/lastPrompt/agents/custom) for fork parity
- add aborted session status and IWireRecord.getRecords()
- register session.undo_unavailable error code
- dispatch all six /sessions/{tail} actions with v1 error mapping and
  emit session.created on create/fork
2026-06-30 18:47:01 +08:00
haozhe.yang
ce0e4f2589 feat(server-v2): expose /openapi.json via @fastify/swagger
- register @fastify/swagger before routes and serve GET /openapi.json
- add v2-specific openapi transform for multipart upload, binary downloads, and the fs-action/question oneOf dispatchers
- project the session-action dispatcher into archive only (v2 registers a subset of v1 routes)
- reuse protocol wire schemas, no inline re-declaration
2026-06-30 18:47:01 +08:00
haozhe.yang
299e6d6bd8 test(agent-core-v2): expand config slice example to all section owners
- resolve every config-section owner against one shared IConfigRegistry
- add register+inspect scenario asserting all expected sections
- add write+round-trip scenario persisting every persistable section
- stub non-config collaborators to construct owners in isolation
2026-06-30 18:47:01 +08:00
_Kerman
03b513afc0 fix(agent-core-v2): fix tests 2026-06-30 18:44:35 +08:00
liruifengv
659062d11c
fix(tui): enable file path completion for / in shell mode (#1225)
Typing `/\' in shell mode (`!\') now triggers file path completion instead of the slash command menu, for both a bare leading `/\' and inline paths like `ls /\'. Hidden entries are skipped to match `/add-dir\', and accepting a completion no longer produces a double leading slash.
2026-06-30 17:54:24 +08:00
_Kerman
56574a4c1f fix(agent-core-v2): tests 2026-06-30 17:35:58 +08:00
qer
a3f9cec8a9
fix(web): deduplicate workspaces shown in the sidebar (#1221)
Collapse registered workspaces that share a root in the daemon registry (preferring the canonical id) and in the web sidebar merge, so the same folder no longer renders as two identical, synchronously-selected entries.
2026-06-30 17:25:24 +08:00
_Kerman
8d4e702c16 fix(agent-core-v2): reduce service constructor args 2026-06-30 17:03:55 +08:00
_Kerman
567c384840 refactor(agent-core-v2): rename permissionGate 2026-06-30 16:44:17 +08:00
_Kerman
9832ef706b refactor(agent-core-v2): unify permission policy construction 2026-06-30 16:28:55 +08:00
_Kerman
b14cda93c7 fix(agent-core-v2): reduce service constructor args 2026-06-30 15:43:14 +08:00
liruifengv
ec51324230
feat(tui): open undo selector on double-Esc (#1220)
* feat(tui): open undo selector on double-Esc

Pressing Esc twice while idle now opens the undo selector, equivalent to running /undo with no arguments. Esc during streaming, compaction, or with a popup open keeps its cancel/close behavior and does not arm the double-press.

* fix(tui): disarm double-Esc undo on any intervening key

A pending double-Esc was only cleared by text changes, so a sequence like Esc, Ctrl-C, Esc within the window still opened the undo selector. Fire an onNonEscapeInput hook for every non-Escape key and clear the pending state there, so the shortcut only triggers for two consecutive Escape presses.
2026-06-30 15:42:27 +08:00
liruifengv
80e6888e34
fix(tui): open @ file mentions inside slash command arguments (#1223)
Typing @ in the middle of a slash command argument (for example `/goal Fix the @checkout docs`) was swallowed by the slash-argument completion guard before the @ mention branch ran, so the file list never opened. Run the @ mention branch ahead of the slash guards so file mentions take priority; plain slash-argument editing is still suppressed as before.
2026-06-30 15:35:19 +08:00
haozhe.yang
83b93eca64 feat(server-v2): port v1 terminals REST routes
- add /sessions/{session_id}/terminals routes (list/create/get/close)
  mirroring packages/server, backed by the Session-scoped ITerminalService
- add node-pty ITerminalBackend overriding the agent-core-v2 stub
- map session/terminal not-found and cwd-escape to protocol error codes
2026-06-30 14:55:05 +08:00
liruifengv
7f61488a88
docs(changelog): sync 0.20.3 from apps/kimi-code/CHANGELOG.md (#1216) 2026-06-30 14:50:31 +08:00
haozhe.yang
adaa4de0a8 feat(server-v2): port v1 /sessions/:sid/skills routes
- add GET /sessions/{session_id}/skills and POST .../{name}:activate, mirroring the v1 wire contract and protocol schemas
- gate both endpoints on activated (live) sessions via ISessionLifecycleService; when persisted but not live, return 40401 with a "you need to activate it first" hint
- resolve ISkillCatalog for listing and the main agent's IAgentSkillService for activation; map skill.not_found to 40415 and skill.type_unsupported to 40912
- export IAgentSkillService and ISkillCatalog from agent-core-v2
2026-06-30 14:30:53 +08:00
haozhe.yang
f3ebc1e2a7 feat(server-v2): port v1 session fs routes
- expose /api/v1/sessions/{sid}/fs:* mirror routes backed by the
  Session-scoped IFsService (list, read, list_many, stat, stat_many,
  mkdir, search, grep, git_status, diff, open, open-in, reveal) plus the
  fs/{path}:download stream
- extend agent-core-v2 IFsService with list/read/stat/mkdir/resolve
  methods and add fs.is_directory/is_binary/too_large/already_exists
  error codes (protocol KimiErrorCode + FsErrors)
- seed IWorkspaceContext with the session work dir in session-lifecycle
  so workspace-relative services resolve paths against the session root
- port fileLaunch lib for open/reveal/open-in
2026-06-30 14:19:18 +08:00
haozhe.yang
f6720b8c9e feat(skill): add filesystem-agnostic discovery, session-scoped
- port SKILL.md parser (frontmatter + body) from agent-core
- add ISkillCatalogStore business-specific Store so the skill domain never
  touches node:fs; File backend walks roots recursively, InMemory backend
  backs tests
- split the catalog into three scopes: IGlobalSkillCatalog (Core; builtin +
  user/brand), ISkillCatalog (Session; project skills merged by workDir),
  IAgentSkillService (Agent; activation)
- inject ISkillCatalog into AgentSkillService; make activate/activateFromModel
  async and await ISkillCatalog.ready to remove the first-activation race
- bind the File backend in the composition root and trigger loading from
  session-lifecycle
- rename SessionSkillRegistry to InMemorySkillCatalog (backs both Core global
  and Session catalogs)
- add js-yaml for frontmatter parsing
2026-06-30 14:19:18 +08:00
haozhe.yang
78320259a5 feat(agent-core-v2): add built-in file and shell tools
- add fileTools domain (Read/Write/Edit/Grep/Glob)
- add shellTools domain (Bash)
- wire registration through FileToolsService and ShellToolsService
- add readLines to IAgentFileSystem for the Read tool
2026-06-30 14:12:22 +08:00
haozhe.yang
69084ab683 refactor(agent-core-v2): move managed OAuth model refresh into OAuthService
- IOAuthService/OAuthService now owns refreshOAuthProviderModels: the managed
  OAuth provider's credential provisioning and server-side model refresh live
  together in the auth domain.
- modelCatalog is back to a read-only catalog projection (listModels,
  listProviders, getProvider, setDefaultModel); the OAuth refresh method and
  its helpers are removed.
- server-v2 /providers:refresh_oauth route and the oauth example resolve
  IOAuthService for the refresh.
- Move the refresh tests into test/auth and add the auth --> config edge to
  the DI scope diagram.
2026-06-30 14:12:22 +08:00
Kai
525fb146d6
feat(vis): full session debugging — tasks/cron, execution timeline, retries & tool progress (#1210)
* feat(vis): surface background tasks and cron jobs

The visualizer read every wire/state/blob artifact a session persists but
ignored the two on-demand families agent-core also writes under the session
directory: background tasks (tasks/<id>.json + output.log) and cron jobs
(cron/<id>.json). Neither is reconstructable from the wire, so there was no
way to inspect what a session spawned in the background or scheduled.

Server:
- task-store / cron-store read-only readers mirroring agent-core's on-disk
  layout, id-validation guard, and legacy snake_case task normalization
- GET /:id/tasks, /:id/tasks/:taskId/output (byte-window paged via an exact
  nextOffset cursor), and /:id/cron routes
- re-export the public background-task types from agent-core; mirror the
  non-exported CronTask shape with a fixture-backed drift test

Web:
- Tasks tab: process/agent/question kinds with status, timing, kind-specific
  fields, raw JSON, and a progressively paged output.log viewer
- Cron tab: expression, prompt, recurring/one-shot, created/last-fired
- count badges on both tabs

Tests: +20 (lib + route), all 113 vis-server tests green; web typecheck and
build clean.

* feat(agent-core): persist step retries and tool progress summary

Two transient signals were only ever emitted as live-only loop events, so
nothing survived in the agent record for post-hoc analysis:

- step retries: chatWithRetry gains an onRetry callback; turn-step collects
  the recovered attempts and attaches them to step.end as an optional
  `retries` array (previously only the live `step.retrying` event).
- tool progress: tool-call distills a tool's sparse status/percent updates
  into a bounded `progress` summary (updateCount / lastStatus / maxPercent)
  on tool.result. Streamed stdout/stderr is excluded — it would bloat the
  wire and is already reflected in the result output.

Both are additive optional fields, so the wire protocol version is unchanged
and existing records keep loading. New public types: LoopStepRetryRecord,
LoopToolProgressSummary.

* feat(vis): add execution-analysis timeline and surface retries/progress

Turn the debugger from a flat record viewer into an analysis tool.

New Timeline tab: folds the wire into turns → steps → tool calls (client-side,
no extra round-trip) and derives the metrics the raw list hides — per-turn /
per-step / per-tool duration, per-turn token cost, a context-window fill
sparkline with cache-hit rate, a tool usage table, idle-gap detection, and a
config-change timeline.

Inline elsewhere:
- Wire rows show tool.call → tool.result elapsed time; tool.result detail
  shows truncation, output size, retries, and the progress summary.
- Issues drawer gains tool-error, truncation, filtered, max_tokens, and
  retried categories.
- Tasks tab links agent-kind tasks to the subagent's wire.

Wires up vitest for the web package and adds analysis/issues unit tests.

* feat(vis): import debug zips with a logs view and imported-session filtering

A `/export-debug-zip` bundle is just `manifest.json` plus a flattened session
directory, which vis already knows how to read. Importing one therefore lights
up every existing tab for a session that lives on someone else's machine.

Server:
- zip-import: yauzl extraction with zip-slip path guards and entry-count /
  uncompressed-size caps for untrusted uploads.
- import-store: extract a bundle into <home>/imported/<imp_…>/, validate it
  has a main wire, and record an import-meta.json sidecar.
- session-store resolves imp_-prefixed ids against imported/, so wire /
  context / tasks / cron / blobs / logs all work on imported sessions; agent
  homedirs are re-derived locally (the bundle holds foreign absolute paths).
- POST /api/imports (raw zip body) and GET /api/sessions/:id/logs (structured
  log lines — also available for local sessions).

Web:
- session rail: import button + all/local/imported filter + imported badge.
- new Logs tab: virtualized, level filter, search, session/global toggle.
- manifest card atop the State tab for imported sessions.

SessionSummary/SessionDetail gain `imported` + `importMeta`. Tests cover
extraction, the zip-slip guard, list merge, reading an imported wire through
the existing route, and log parsing.

* fix(vis): read tasks/cron from agent homedirs and stop persisting tool status text

Addresses review feedback on the debug-tooling changes:

- Background tasks and cron jobs are persisted under each agent's homedir
  (<session>/agents/<id>/tasks and /cron), not the session root. The Tasks and
  Cron tabs read the session root, so they showed nothing for normal sessions.
  Both routes now aggregate across detail.agents homedirs; task entries carry
  the owning agentId. The route-test fixtures were writing to the wrong
  (session-root) location too — corrected to the real agents/main layout so
  they actually exercise the path.

- tool.result progress no longer keeps free-form status text, only updateCount
  and maxPercent. A tool's status string can contain sensitive data (e.g. an
  MCP OAuth authorization URL) that must not leak into persisted wire files or
  exported debug bundles.

* fix(vis): stop the main content area from overflowing horizontally

The <main> flex child lacked min-w-0, so it defaulted to min-width:auto and
refused to shrink below its content's intrinsic width. Tabs that lay out in
normal flow with flex-wrap rows (the Timeline tab) then got unbounded width,
never wrapped, and blew the layout out to thousands of pixels wide. Adding
min-w-0 lets the column shrink to the available width so its content wraps,
truncates, or scrolls within its own container.

* fix(vis): resolve local global log path and imported-state agent fallback

- Logs tab: for non-imported sessions the shared global log lives at
  <KIMI_CODE_HOME>/logs/kimi-code.log, not under the session dir (that path is
  only used inside exported bundles). The route now reads the home path for
  local sessions, so the global-log toggle works for them.
- Imported detail: a bundle's state.json is best-effort and may omit the
  agents map. When the inventory is empty, fall back to discovering agents
  from disk so routes that require an agent (wire/context) still resolve main.

* fix(vis): harden imported manifest and task parsing against corrupt input

An imported debug zip is untrusted, so a syntactically valid but type-corrupt
file could crash whole views:

- manifest.json: a non-string field (e.g. workspaceDir: 123) flowed into
  SessionSummary.workDir, where the session rail calls .split('/') and crashed
  the entire list. readManifest/readImportMeta now sanitize declared string
  fields, keeping only strings.
- task JSON: a record that passed the shape guard but held a non-string legacy
  field (e.g. stop_reason: 5) threw in normalization, failing GET /tasks with a
  500 and hiding all of a session's tasks. optionalNonEmptyString now tolerates
  non-strings, and listBackgroundTasks skips any record that still fails to
  normalize — honouring the reader's documented silently-skips contract.

* fix(vis): discover rotated logs; keep tool progress on thrown failures

- Logs tab: the diagnostic log can rotate (kimi-code.log.1, .2, …) and an
  exported bundle may contain only the archives. The route now discovers the
  active file plus its rotated siblings and concatenates them oldest-first, so
  a rotated-away log still surfaces (covered by node-sdk's rotated-export case).
- agent-core: a tool that reported sparse progress and then threw lost its
  progress summary, because the catch path built the error tool.result without
  it. Thread progressSummary through that path too, matching the success and
  malformed-return paths.

* fix(vis): skip type-corrupt agent entries in imported state

readImportedDetail's empty-inventory fallback never ran when a bundle's
state.json had a non-empty but type-corrupt agents map (e.g.
`{ "agents": { "main": null } }`): inventoryAgents dereferenced the null entry
and threw, so readSessionDetail returned 500 instead of recovering main from
the on-disk agents/main/wire.jsonl. inventoryAgents now skips non-object
entries, letting the disk-discovery fallback take over.

* fix(vis): reset timeline agent on session change; preserve context on zero-usage steps

- Timeline tab kept the previously-selected agent id across session navigation,
  so a subagent selection would 404 against the next session. Reset it to main
  on sessionId change, mirroring WireTab/ContextTab.
- A zero-usage step.end (e.g. a content-filtered response) reset the
  context-window fill to 0, pushing a false drop into the Timeline chart and the
  Context tab. agent-core's ContextMemory keeps the prior count in that case;
  the analysis lib and the context projector now do the same.

* revert: drop agent-core retries/tool-progress persistence

These were the only changes in this branch that touched agent-core. They
persisted two previously live-only signals (step retries, tool progress) to
the wire purely so the visualizer could display them — marginal features that
did not justify modifying the core loop or extending the wire surface.

Reverts the agent-core loop/type/export changes (restored to main, keeping
#1209) and its changeset, and removes the vis-side rendering and types that
consumed step.end.retries / tool.result.progress. The rest of vis is unchanged
and reads only data agent-core already persists.
2026-06-30 13:40:37 +08:00
github-actions[bot]
b41f108584
ci: release packages (#1197)
Some checks are pending
CI / build (push) Waiting to run
CI / test (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
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-30 12:37:57 +08:00
Haozhe
14d9e98903
feat(server): auto-refresh provider model catalog and push change events (#1207)
* feat(server): auto-refresh provider models and push change events

- add scheduled provider-model refresh in the daemon (configurable
  interval + refresh-on-start) plus manual endpoints:
  POST /providers:refresh and POST /providers/{id}:refresh
- publish global event.model_catalog.changed when a refresh changes
  the catalog so connected clients can resync
- extract the refresh orchestrator into @moonshot-ai/kimi-code-oauth so
  the CLI and server share managed/open-platform/custom-registry logic
- wire the web daemon client to the new refresh endpoints

* chore: add changeset for provider model auto-refresh

* fix(web): reload model and provider caches on catalog change events

When the daemon's scheduled refresh changes the catalog, the pushed
event.model_catalog.changed only advanced the websocket sequence, leaving
the web composer's model/provider refs stale until an unrelated reload.
Reload both caches when the event arrives.

* test(sdk): cover event.model_catalog.changed in event exhaustiveness
2026-06-30 12:29:10 +08:00
_Kerman
632e0a7c9f Merge branch 'kimi-code-v2' of https://github.com/MoonshotAI/kimi-code into kimi-code-v2 2026-06-30 12:28:48 +08:00
_Kerman
48e4c3dae7 fix: agent-core-v2 tests and background persistence options 2026-06-30 12:28:42 +08:00
haozhe.yang
9076f55643 refactor(agent-core-v2): add kaos domain for execution environment
- Add `kaos` domain (`IKaos` per session + `IKaosFactory`) wrapping
  `@moonshot-ai/kaos`, so business code imports `#/kaos` instead of the
  package directly.
- Back `agentFs` and `process` with `IKaos`; drop the per-domain
  `IFileSystemBackend` / `IProcessBackend` interfaces and their
  local/ssh stubs.
- Migrate `read-media`, `path-access`, `background/process-task`, and
  `bootstrap` off direct kaos-package imports.
- Seed `IKaos` per session in `SessionLifecycleService` and expose
  `agentFs` / `fs` on the server-v2 action map.
- Create the server-v2 main agent on demand (`ensureMainAgent`)
  instead of failing requests when it is missing.
2026-06-30 12:17:09 +08:00
qer
636ccc40f1
fix(web): fix mobile Safari composer toolbar overlap and focus zoom (#1212)
* fix(web): keep composer visible above the mobile Safari toolbar and keyboard

* fix(web): scope the mobile Safari composer fix to the toolbar case

* fix(web): prevent page zoom when focusing the mobile composer
2026-06-30 12:15:14 +08:00
haozhe.yang
d4f9933b92 fix(server-v2): serve v1 fs browse/home on distinct routes
- replace the `/fs:action` parametric dispatcher with two routes that
  mirror v1 (`/fs::browse`, `/fs::home`), so the wire path is the
  single-colon `/api/v1/fs:browse` and `/api/v1/fs:home` that v1 serves
- update the folder-picker test to hit the single-colon URLs and assert
  the double-colon form 404s, guarding against reintroducing the
  parametric dispatcher
2026-06-30 12:11:31 +08:00