mirror of
https://github.com/MoonshotAI/kimi-code.git
synced 2026-08-02 04:54:53 +00:00
45 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
d03a4886fd
|
feat(server): remove the 50 MiB upload size cap and stream uploads to disk (#2312)
Some checks are pending
CI / build (push) Waiting to run
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
Release / Release (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
- add writeStream/putStream to the storage and blob store interfaces so large values are written incrementally (tmp + fsync + rename) instead of being buffered in memory - FileService.save now streams the request body straight to the blob store and only counts bytes for FileMeta.size - drop the multipart fileSize limit and the file.too_large error from the /files upload path (41301 stays in the wire protocol for session export) |
||
|
|
48bf3d4c28
|
feat(kap-server): bundle the desktop app log into session exports on request (#2223)
* feat(kap-server): bundle the desktop app log into session exports on request * refactor(agent-core-v2): align the desktop log export with repo conventions |
||
|
|
d751b6796c
|
feat(kap-server): global session work status, transcript subscribe_v2, and plan endpoint (#2094)
* feat(session): add core work aggregate and consume it at WS/REST edges
- agent-core-v2: add the sessionActivity domain (ISessionActivityView,
Session scope) folding each agent's activity view and the interaction
kernel into busy / main_turn_active / pending_interaction /
last_turn_reason, firing cause-tagged change events only on real
tuple changes
- kap-server: resolveSessionFacts reads the core view; the WS
broadcaster drops its per-agent fold/dedup and delegates to the
view, deferring turn_ended emissions until after the turn.ended
frame so busy:false never precedes it; global events now fan out
to every established connection via addGlobalTarget without any
subscription
- kimi-inspect: add src/activity (GlobalEventsWs + SessionActivityHub
+ useSessionActivities) consuming the global push; the Sidebar
renders running / approval / question / failed badges per session
* feat(kap-server): decouple transcript stream from agent_filter
- transcript frames (transcript.reset/ops) are governed by the per-agent
transcript grades alone and bypass the legacy agent allowlist; the filter
still gates session_event delivery
- client_hello is handshake-only in code: hello and subscribe share one
attach path, and hello's inline subscription fields are deprecated
(subscriptions made optional) in both protocol packages
- flush deferred work_changed(busy:false) from a microtask so it always
lands after the matching turn.ended frame
* fix(kimi-inspect): restore session activity hub in the browser
- bind the default fetch in SessionActivityHub: a member call hits the
browser's Illegal invocation (receiver is not the global object), and
the swallowed error left the REST seed never firing, so the Sidebar
badges never populated on refresh
- create the hub in useEffect + useState instead of useMemo: under
StrictMode the first mount's cleanup closes the memo-created hub for
the rest of the page's life
* chore: add changeset for the global session work status push
* feat(kap-server): add transcript plan endpoint for ExitPlanMode calls
- add GET /sessions/{id}/transcript/plan projecting one ExitPlanMode
call's plan info (content, path, options, review outcome) from the
first available fact: the linked approval interaction's request
display, the live tool frame's display, or the tool result output
- add TOOL_CALL_NOT_FOUND (40416) error code
- add transcriptPlanResponseSchema to the transcript contract
- cover live, auto-mode, cold-rebuild, and error paths in tests
- update the API surface snapshot and AGENTS.md
* feat: move transcript subscriptions to subscribe_v2 and extend the plan endpoint
- add subscribe_v2 / unsubscribe_v2 WS control frames as the only
carrier of per-agent transcript grades and the transcript_since
cursor; client_hello / subscribe no longer accept transcript fields
- serialize control-frame handling per connection so interleaved
attaches cannot overwrite fresher subscription state
- make tool_call_id optional on GET /sessions/{id}/transcript/plan:
omitted lists every ExitPlanMode call with recoverable plan content
as a plans array
- add a Plan lookup card to the kimi-inspect agent inspector via
fetchTranscriptPlan
- add TOOL_CALL_NOT_FOUND (40416) to the shared protocol error codes
- update AGENTS.md and add changesets
|
||
|
|
8bf5bacba9
|
ci: release packages (#1989)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
a3699dd6aa
|
feat(kap-server): expose per-tool active state in GET /api/v1/tools (#2005)
* feat(kap-server): expose per-tool active state in GET /api/v1/tools * Update tools-list-active-flag.md Signed-off-by: 7Sageer <7sageer@djwcb.cn> --------- Signed-off-by: 7Sageer <7sageer@djwcb.cn> |
||
|
|
ce0e3ceb04
|
feat: support custom agent files (#1735)
Some checks are pending
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
Release / Release (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
CI / test (2) (push) Waiting to run
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-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 / typecheck (push) Waiting to run
* feat: support custom agent files
Discover Markdown+frontmatter agent definitions from user, project, and configured directories; merge them into a session-level profile catalog (priority: builtin < user < extra < project < explicit). Custom agents work as subagents via the Agent tool and as the main agent.
- agent-core-v2: new agentFileCatalog domain (discovery/parsing/profile factory, mirroring skillRoots/parseFrontmatter) and sessionAgentProfileCatalog merged view; AgentProfile.tools becomes optional (undefined = all tools) and gains disallowedTools deny list, evaluated in profileService.isToolActive and persisted in session wire records so resume keeps the gate even if the file is gone
- CLI: restore --agent/--agent-file for the v2 print runner (KIMI_CODE_EXPERIMENTAL_FLAG); the v1 TUI rejects them with a clear v2-only error
- kap-server/protocol: optional profile field on prompt submission with first-bind semantics (same-name no-op, different name rejected)
- docs: custom agents section (en/zh) + config/CLI references + changeset
* chore: shorten custom agents changeset
* fix(agent-core-v2): stringify caught errors in agent catalog log calls
* docs: drop v2 engine notes from custom agents docs
* fix: align custom agent binding semantics across engine and edges
- agent-core-v2: bind now owns the first-bind invariant — switching
profiles after bind throws profile.already_bound (checked again in the
synchronous segment before the first wire dispatch, so concurrent binds
cannot both pass); unknown names throw profile.unknown; same-name
rebinds keep the persisted thinking effort.
- kap-server / CLI: edges degrade to error mapping / same-name no-op
instead of their own divergent guards.
- agent files: reject non-string mode values, honor disallowedTools in
the append-mode Skill probe, pass --agent-file through unresolved so
the engine can expand ~, reject empty --agent-file values.
- session catalog: ready is recoverable via reload() after a fatal
source failure, and agent-file discovery is kicked at session
materialize so resumed sessions see file agents from the first turn.
- docs: first-bind semantics, name: agent override, tools: [] meaning,
--agent-file last-wins.
* fix: tighten custom agent behavior
* fix: address custom agent review findings
* fix(agent-core,agent-core-v2): keep active-tool wire records replayable by v1
Binding a profile without a tool allowlist (the default for file-defined
custom agents) persisted a tools.set_active_tools record with no `names`
key. v1 clients discover v2 sessions through the shared session index and
replay newer wire versions without migration, so the record crashed v1
resume with a TypeError and wedged the session permanently.
The v2 engine no longer writes the record when the base set is already
"every tool active" (its absence encodes the same state), and v1 replay
now skips records that lack `names` as defense in depth for wires already
written by preview builds. A same-name rebind that resets an allowlist to
"all tools" has no v1-safe encoding and is left as a documented gap (no
production caller today); a future tools.reset_active_tools Op is safe
because v1 silently no-ops unknown record types.
* fix(agent-core-v2): tolerate unreadable directories in agent-file discovery
A single unreadable subdirectory (EACCES anywhere in the scanned tree)
previously aborted the whole discovery pass, zeroing every agent of that
source on every session start with one path-less warning. The walker now
skips-and-warns per directory below the root (mirroring the skill
discovery it parallels), root-level failures are isolated per root so one
bad root no longer takes its siblings down, and only a genuinely transient
whole-fs outage (os.fs.unavailable) still propagates so the session
catalog keeps its previous contribution. Source-level warnings now name
the offending path, and repeated skip warnings are capped with a summary
that samples the suppressed paths.
Also consolidates the path primitives (~ expansion, base-relative
resolution, realpath type probes) shared by the root resolvers, the
walker, and the explicit-file source into agentFileCatalog/paths.ts, and
tightens parser diagnostics: frontmatter null is treated as absent, and a
present-but-wrong-typed name/description reports a type error instead of
"missing".
* fix(agent-core-v2): warn when a same-name builtin suppresses a file profile
A directory-discovered agent file colliding with a builtin profile
without override: true was silently dropped at merge time. The suppression
now logs a warning naming the profile and the opt-in.
* refactor(agent-core-v2): pass skillActive explicitly to renderSystemPrompt
The third parameter was a full tool list used only for includes('Skill'),
which forced the agent-file profile factory to answer a boolean question
with sentinel lists. The template now takes an explicit skillActive flag;
a skillActiveFor helper keeps builtin call sites derived from their tool
arrays.
* refactor(agent-core-v2): fall back to the configured default model in bind
BindAgentInput.model is now optional: the engine resolves a missing model
against the configured defaultModel and throws model.not_configured when
neither is set, so edges no longer each re-implement the fallback.
* fix(agent-core-v2,kap-server): reject unsupported thinking atomically at first bind
A REST prompt carrying profile + an unsupported thinking effort bound the
session first and failed setThinking after, wedging the session on an
identity the user never successfully used. The effort is now validated up
front when the caller marks it as an explicit request (strictThinking):
the bind rejects before any await or state mutation, and the requested
effort rides along in the bind instead of a separate setThinking. Internal
spawn/fork paths pass inherited thinking without the flag and keep the
previous clamp behavior — a persisted effort that drifted out of the
model's support list must not break subagent spawning. The route's
now-redundant model fallback is dropped in favor of the engine-side
default.
* fix(agent-core-v2): await the agent profile catalog at session materialize
The catalog's ready promise was only kicked, so a resumed session's first
turn could render the Agent tool description without the file-defined
agent types. Discovery is local-fs and cheap, so materialize now awaits
it; ready only rejects for a fatal explicit-source error, which is exactly
the case that should fail fast. A failure there now also removes and
disposes the half-materialized handle instead of leaving it registered in
the session cache.
* test: cover the --agent-file fatal path and tidy profile registration hygiene
The v2 print CLI now has a test asserting an invalid --agent-file fails
before any turn. The denylist profiles in binding.test.ts register in a
beforeAll (idempotent, scoped to the describe's run window) instead of at
module scope during collection.
* docs: align custom agent docs with v2-engine gating
--agent/--agent-file are rejected without the v2 engine, so restore the
requirement in the Agents and Command Reference pages (and use
KIMI_CODE_EXPERIMENTAL_FLAG=1 in the examples), note that tool lists only
shape model-visible disclosure (permission rules are the enforcement
layer), and remind authors of delegation-bound agents to state the
handoff contract in the prompt body.
* test(agent-core-v2): revert unrelated style churn in fs/workspace tests
Keep these files' diff limited to the realpath fakes the feature needs;
the lint-preference rewrites belong to a separate cleanup.
* feat(agent-core-v2): add permanent system prompt override via SYSTEM.md
Read $KIMI_CODE_HOME/SYSTEM.md on every startup and inject it as the default main-agent profile (name "agent", override: true), replacing the builtin default system prompt while inheriting builtin tools and description. Missing or empty files are ignored; unreadable files warn and fall back to the builtin profile.
The body supports variable substitution (${skills}, ${agents_md}, ${cwd}, ${cwd_listing}, ${os}, ${shell}, ${now}); unknown variables pass through verbatim.
Priority: --agent-file / --agent / project override > SYSTEM.md > same-name user-scope scan files.
* feat(agent-core-v2): gate tools globally and accept session disabledTools
Add a [tools] config section: "enabled" acts as a global allowlist (empty = unconstrained), "disabled" as a denylist applied on top, both intersected with the active profile's policy in isToolActive (mcp glob supported).
Plumb a session-persistent disabledTools parameter through the stack: v2 RPC PromptPayload, REST "disabled_tools" (protocol and kap-server parallel schemas), klient contract/facade, and node-sdk. The server applies it via profileService.setSessionDisabledTools, which replaces the client-owned denylist, keeps the profile's own deny, persists across resume, and rejects calls before a profile is bound with profile.not_bound (mapped to 40001). v1 core-api gains a type-only field and ignores it.
* fix: enforce session tool policy across agents
* fix(agent-core-v2): enforce tool policy at execution
* fix(agent-core-v2): align subagent tool descriptions with policy
* fix(agent-core-v2): harden custom agent policy state
* fix(agent-core-v2): harden custom agent lifecycle
* refactor(agent-core-v2): persist profile binding in a single profile.bind record
* fix(agent-core-v2): skip unreadable paths during agent file discovery
* fix(agent-core-v2): exempt select_tools from the executor policy guard
- share one composed profile/global/session tool-policy evaluation between
the executor gate and prompt rendering instead of two verbatim copies
- tolerate context-build failure in system prompt refresh instead of
rejecting callers (config watcher void-fire, session policy fan-out)
* test(agent-core-v2): resolve profile and tool-policy SUTs by interface
- drop the Object.assign patching of tool-policy methods onto the shared
profile service; rename describes so the SUT ownership is accurate
- classify profile.bind as v2-only with the accepted v1-replay tradeoff
documented, un-red the wire vocabulary guard test
- cover the select_tools guard exemption with an executor-level test
* fix(agent-core-v2): enforce explicit select_tools policy
* feat(agent-core-v2): accept Claude-style tool lists and rename agent-file mode to promptMode
* feat(agent-core-v2): unify prompt templating on ${var}
- Replace the nunjucks renderer with a single ${var} regex renderer
(unknown placeholders pass through verbatim) and drop nunjucks from
agent-core-v2.
- Merge the variable tables into one catalog shared by the builtin
system.md, SYSTEM.md, and agent file bodies; adds additional_dirs_info
plus code-composed blocks (windows_notes, additional_dirs_section,
skills_section).
- Replace the agent-file promptMode field with ${base_prompt}: bodies
are always rendered as templates, and ${base_prompt} expands to the
effective default profile prompt (honoring the SYSTEM.md override).
- Migrate the builtin system.md, goal reminders, compaction instruction,
and tool description templates to the same syntax.
* docs: complete agent priority chain and link SYSTEM.md precedence
* test: fix invalid custom agent fixture
* fix(cli): reject multiple agent selectors
* feat(agent-core-v2): add subagents allowlist to agent files
* fix(agent-core-v2): persist the subagent allowlist in the profile binding
The delegation allowlist now rides the profile.bind record like the tool
denylist, so a resumed session keeps enforcing it even when the source
agent file was deleted or changed. Agent/AgentSwarm resolve the caller's
allowlist from the persisted binding data instead of looking the profile
up in the live catalog.
* feat(agent-core-v2): warn on tool patterns that never match
Profile bind/apply and [tools] config changes now statically flag
entries that can never activate anything — wildcards without the mcp__
prefix (a bare * in an allowlist disables everything, in a denylist
nothing), incomplete mcp__ literals, and names no registered or
builtin-profile tool has — via a tool-pattern-no-match warning event,
once per pattern, instead of letting the tool set silently shrink. The
known-name vocabulary is the live registry plus literal names from the
builtin profiles, so flag-gated tools stay known and a typo in one agent
file cannot legitimize the same typo in another.
* docs: align --agent-file docs with the single-selector CLI
The flag accepts exactly one file and conflicts with --agent, but the
docs still described the earlier repeatable, composable design.
* docs: note the agent-file trust model and never-matching tool patterns
Spell out that project-scoped agent files can replace the default main
agent's whole system prompt (unlike AGENTS.md reference injection), and
list the three tool-pattern shapes that never match and now raise a
warning.
* chore: slim changeset wording to user-facing language
Drop wire record names, enforcement mechanics, and template syntax from
the entries; split the v1 resume fix into its own patch changeset; add a
patch entry for the tool-pattern warnings.
* chore: shorten changeset entries to one-line summaries
* Delete .changeset/v1-resume-v2-sessions.md
Signed-off-by: 7Sageer <12210216@mail.sustech.edu.cn>
* test: drop class-instance spread in sessionLifecycle test stub
* chore: clear the comments
---------
Signed-off-by: 7Sageer <12210216@mail.sustech.edu.cn>
|
||
|
|
5ae60fa673
|
feat(transcript): add unified transcript layer, drop the /api/v2 RPC surface (#1888)
* feat(transcript): add unified transcript layer and v1 surface
- add packages/transcript: agent-granular L1 store, idempotent L2 ops,
off/turn/block/delta L3 granularity, L4 view registry, and turn-cursor
pagination; sole owner of all transcript wire types
- kap-server: engine-event-driven TranscriptService with history backfill,
GET /sessions/{id}/transcript, and transcript.ops WS deltas with
per-connection granularity control
- kimi-inspect: render ChatView from the transcript surface (REST pages +
delta-only WS) instead of context memory
- sync flake.nix workspace lists and document packages/transcript and
packages/server-e2e in AGENTS.md
* fix(transcript): project live prompts and anchor backfilled items
- agent-core-v2: carry the extracted prompt text on turn.started so the
transcript projector can render the user input at turn open (the context
append with the same text is not a bus event and lands later)
- kap-server: keep the prompt through turn.ended; anchor backfilled
markers/taskrefs to their following snapshot turn so replaying history
after live turns arrived keeps the historical order
- transcript: add an optional beforeTurn placement anchor to
marker.upsert / taskref.upsert; anchored inserts land before the first
turn at or past the anchor instead of appending blindly
Addresses review feedback on #1888.
* fix(transcript): adopt backfilled stream frames and group goal turns
- kap-server: on mid-stream attach, adopt the backfill-seeded stream frame
(id + offset) instead of opening an empty one whose upsert clobbered the
seeded text and whose offset-0 appends could not land
- transcript: group a turn-opening system_trigger (goal continuation) into
its own turn so cold rebuilds keep the turn boundary and stay
ordinal-aligned with the engine's live turn numbering
Addresses review feedback on #1888.
* fix(transcript): drop stale live stores on close and heal after turns
- drop a session's live transcript store when the session closes or archives
(lifecycle events plus a re-check on the cached-entry path) so reads fall
back to the cold rebuild instead of serving a stale store
- re-read an ended turn from the persisted wire records (debounced per
agent) and merge it back live-first: headers keep live state/timestamps
while origin/prompt recover from disk, and truncated text/thinking frames
from a mid-turn attach are restored only when the persisted text is
longer — a fresh live frame or a lagging flush is never reverted
Addresses review feedback on #1888.
* fix(transcript): adopt seeded tool frames and route subagent questions
- kap-server: adopt the backfill-seeded tool frame when a tool.result
arrives for a call that started before the projector attached, so the
output lands instead of being dropped (the producer-store lookups now
ride one projector options object)
- agent-core-v2: record the owning agent on question interactions
(ISessionQuestionService.request gains an agentId option, passed by
AskUserQuestionTool from its agent scope) so a subagent's questions
route to its own transcript and WS events instead of 'main'
Addresses review feedback on #1888.
* fix(transcript): adopt parent frames, namespace live markers, redact resets
- kap-server: fall back to store adoption when subagent.spawned links a
parent tool call that started before the projector attached, so the
agentRefs link is not lost on mid-bind attaches
- kap-server: id live markers in their own namespace (live-mN) — the cold
rebuild numbers its markers m1... too, and a colliding id made the
store's upsert replace the historical marker instead of appending
- transcript/kap-server: redact transcript.reset snapshots to the
subscriber's grade (below 'block' the step/frame detail is stripped), so
a 'turn'-grade subscription no longer receives full content on resets
Addresses review feedback on #1888.
* fix(transcript): fold blocked turns into failed, drop inline v2 comment
- kap-server: map turn.ended reason 'blocked' to the 'failed' transcript
state, matching the engine's TurnEndReason wire contract and the v1
mapTurnReason folding (it was presented as a user cancellation)
- agent-core-v2: move the question agentId rationale into the ask-user
file header — package rules keep comments in the top-of-file block only
Addresses review feedback on #1888.
* fix(transcript): keep roster descriptors and resolved-event agents
- kap-server: keep the metadata-seeded roster descriptor (parentAgentId /
label) when an on-demand history backfill lands its roster entry, instead
of downgrading it to { agentId, type }
- kap-server: remember each interaction's owning agent and stamp it on the
resolved question/approval v1 events — they were hard-coded to 'main', so
an agent-filtered subscriber saw a subagent's question open but never
close
Addresses review feedback on #1888.
* fix(transcript): defer pending seeding, skip ghost roster entries
- kap-server: announce interactions pending at bind time only after the
initial backfill (new TranscriptBinding.seedPendingInteractions), and
adopt the seeded tool frame on the request/resolve paths, so a
pre-existing approval lands next to its backfilled tool call and keeps
the approvalId back-link
- kap-server: skip the roster entry when a probed agent id has neither a
roster presence nor persisted content (agent_id=nope no longer conjures
a ghost subagent)
- agent-core-v2: fold the turnEvents import rationale into the loop file
header (package rule: comments live in the top-of-file block only)
Addresses review feedback on #1888.
* fix(transcript): reject hostile agent ids, honor the agent allowlist
- transcript/kap-server: validate agent ids as plain names (no separators,
no dot segments) at the REST query layer and again before the id is
joined into the wire-records path — an authenticated client could
otherwise read a wire.jsonl outside the agents directory
- kap-server: compose the legacy v1 agent allowlist with transcript
grades on every fan-out path (initial resets, per-ops fan-out,
roster-driven resets), so a filtered connection no longer receives
other agents' transcript frames
Addresses review feedback on #1888.
* fix(transcript): settle foreground shell tasks on shell.completed
- agent-core-v2: emit a transient shell.completed event when a foreground
`!` command settles (detached runs keep reporting through the task
lifecycle) — the generic task.terminated never fires for foreground
tasks, so their transcript cards were stuck at 'running'
- kap-server: map shell.completed to the terminal transcript task state
(completed/failed) and classify the event as volatile on both v1
durability gates, like its shell.* siblings
Addresses review feedback on #1888.
* fix(transcript): replay early resolves, reset on a widened filter
- kap-server: register bind-time pending interactions without frames so a
resolve arriving before the post-backfill seed still routes, then replay
it at seed time — request and resolve land together with the approvalId
back-link, instead of the interaction vanishing entirely
- kap-server: treat an agent newly admitted by a broadened legacy agent
filter as owed a transcript.reset even when its grade transition is a
no-op (delta → delta) — its ops were suppressed so far, so it has no
baseline otherwise
Addresses review feedback on #1888.
* fix(transcript): keep materialized transcripts on agent disposal
- kap-server: only the projector dies with the agent scope — the
materialized transcript and roster entry now survive disposal (the
roster mirrors session metadata, which keeps completed agents).
Dropping them lost already-served history for good: the backfill cache
dedupes per agent, so the next read rebuilt an empty shell instead of
replaying the persisted records
Addresses review feedback on #1888.
* fix(transcript): anchor refreshes by oldest turn, group slash turns
- kimi-inspect: re-cover the previously loaded window after a refresh by
paging until the previous OLDEST turn is loaded again (extracted as
recoverLoadedWindow) — a count-based stop silently dropped the window's
head once new turns shifted the server window
- transcript: group user-slash skill/plugin activations into their own
turn (marker included), mirroring the engine's isRealUserPrompt — their
assistant output no longer folds into the previous turn on cold rebuilds;
other triggers stay marker-only
Addresses review feedback on #1888.
* fix(transcript): compare all tool fields, overlay in-flight backfills
- transcript: include toolCallId/name/view/input in the tool frame
equality check — an upsert correcting only those was dropped as a no-op,
leaving stale tool metadata on clients
- kap-server: overlay the loop's active turn as 'running' after a backfill
(cold grouping marks every rebuilt turn completed, so a live turn showed
as finished until it ended); snapshot data supplies origin/prompt, and a
projector-owned running header is never downgraded
Addresses review feedback on #1888.
* fix(transcript): gate ops before the seed, re-assert running headers
- kap-server: gate the transcript ops fan-out (and roster-driven resets) on
a per-connection seeded flag set only after the baseline reset has
landed — a subscriber joining mid-stream no longer receives deltas
against an empty baseline
- kap-server: always re-assert the loop's active turn as 'running' after
the snapshot ops in a backfill (skipping the overlay when a live running
header existed let the snapshot's cold 'completed' header downgrade it);
live header fields win over the snapshot's
Addresses review feedback on #1888.
* docs(agent-core-v2): fold turnEvents notes into the file header
Move the turn.started prompt rationale from field/function TSDoc into the
module header — package rules keep comments in the top-of-file block only.
Addresses review feedback on #1888.
* fix(transcript): emit shell failure output, dispose per-agent listeners
- agent-core-v2: emit the synthesized failure text as a final shell.output
chunk before shell.completed (it was never streamed, so failed
foreground commands showed empty output in transcript tasks until a
full rebuild)
- kap-server: track each agent's bus subscription per agent and dispose it
in onDidDispose — the listener captures the projector, so a disposed
agent no longer keeps projecting late events into the store
Addresses review feedback on #1888.
* fix(transcript): route shell events by task id, tidy question docs
- agent-core-v2: keep the commandId → foreground-task-id mapping and carry
taskId on shell.output / shell.completed, so consumers attaching
mid-command (having missed shell.started) can still route output and the
terminal state
- kap-server: fall back to the event's taskId in the shell output/completed
projectors and seed the shell task before the first chunk, so output is
preserved and the terminal upsert cannot clobber it with an empty tail
- agent-core-v2: fold the question agentId note into the question.ts file
header (package rule: comments live in the top-of-file block only)
Addresses review feedback on #1888.
* fix(transcript): tighten agent id validation, match kinds in heals
- transcript: constrain agent ids to a filename-safe shape
([A-Za-z0-9._-], <=128 chars) — NUL-containing or overlong ids made the
wire-records read throw unhandled errors (500) instead of failing
validation
- kap-server: require the live frame's kind to match before the post-turn
heal's length shortcut — a kind-mismatched frame (the projector guessed
the stream kind wrong mid-turn) is now replaced by the persisted one
instead of being skipped
Addresses review feedback on #1888.
* fix(transcript): heal missed tool results, seed pendings per agent
- kap-server: re-emit tool frames in the post-turn heal when the live step
lacks the frame or the live frame lacks the outcome the persisted one
carries (a tool.result dropped in the attach race is otherwise
unrecoverable); live-only extras (display / agentRefs / approvalId) are
preserved, and frames with a live outcome stay untouched
- kap-server: scope seedPendingInteractions by agent — the initial seed
after backfillMain covers main-owned pendings, and each subagent's
pendings seed after its own on-demand backfill, so placement and the
approvalId back-link find the persisted tool frames
Addresses review feedback on #1888.
* fix(protocol): register shell.completed on the v1 event surface
- packages/protocol: add ShellCompletedEvent (plus optional taskId on
shell.output / shell.completed and prompt on turn.started) to the event
interfaces, zod schemas, the agent event union, and the volatile list —
schema-validating consumers previously rejected the forwarded
shell.completed frames outright
- kap-server: mirror the same fields in the v1 events-zod module
Addresses review feedback on #1888.
* test(node-sdk): cover shell.completed in the exhaustive event switch
The SDK's session-event type test asserts exhaustiveness with assertNever;
register the new event there (CI typecheck caught it).
Addresses review feedback on #1888.
* fix(transcript): source cold-session rosters from session metadata
- kap-server: add TranscriptService.readColdRoster (persisted state.json →
descriptors, mapped like the live seeding) and use it for the cold
transcript path — the requested agent id is only appended when it has
content (or is main), so an empty probe (agent_id=nope) no longer
fabricates a ghost roster entry, matching the live path
Addresses review feedback on #1888.
* fix(transcript): emit taskrefs when seeding missed shell commands
- kap-server: the mid-command-attach seeding in onShellOutput now emits
the matching taskref.upsert (exactly like onShellStarted), and
onShellCompleted emits one when the whole command was missed — the task
no longer exists only in the global map with no timeline item to render
Addresses review feedback on #1888.
* fix(transcript): defer unseeded live pendings, keep cold tools running
- kap-server: pendings created before their owning agent's seed has run
now defer into the same unseeded queue as bind-time ones (tracked per
agent) — announcing them during the backfill window misplaced them into
a synthetic step with no later repair
- transcript: cold grouping initializes tool frames as 'running' and lets
the tool-message branch transition them to done/error — an approval-
gated or still-executing tool no longer shows as completed on rebuilds
Addresses review feedback on #1888.
* fix(transcript): seed live-created agents, merge backfills live-first
- kap-server: agents created after binding are marked seeded immediately —
their projector covers every event from creation on, so their pendings
announce without waiting for an explicit history read (which previously
left live subagent approvals/questions stuck in the unseeded queue)
- kap-server: the initial backfill merges turns live-first via
healTurnOps (snapshotToOps gains a turn-mapper parameter) — live frame
fields landed during the disk read (display/approvalId, longer text)
are no longer replaced by the staler persisted version
Addresses review feedback on #1888.
* fix(transcript): count pages in turn segments, not head units
- transcript: the leading non-turn unit no longer consumes a turn slot —
pages are counted in turn segments and the head unit rides only with the
page reaching the first turn. A timeline with a head marker and exactly
pageSize turns used to drop the marker from the newest page and
hallucinate an older marker-only page (has_more: true with no older
turns)
Addresses review feedback on #1888.
* fix(transcript): send baseline resets after cursor replay
- kap-server: broadcaster.subscribe gains deferTranscriptReset (recording
prev grades/filter per target) plus flushTranscriptSeed; the v1
connection defers the transcript baseline on cursor-carrying
(re)subscribes and flushes it after replay — a reconnecting client no
longer sees the reset's current seq ahead of the replayed lower-seq
backlog
Addresses review feedback on #1888.
* fix(transcript): gate the ops fan-out only when a reset is coming
- kap-server: willSendTranscriptReset decides upfront whether any reset
will be sent (grade upgrade or widened legacy filter); a same-grades
resubscribe no longer un-seeds the target, so ops emitted mid-resubscribe
keep flowing instead of being silently dropped by the fan-out gate
Addresses review feedback on #1888.
* fix(transcript): seed subscribers even when no reset is owed
- kap-server: a no-reset subscription (e.g. a client subscribing to a
fresh session with an empty roster) now still marks the target seeded
after subscribeTranscript completes — roster resets and ops would
otherwise stay gated forever once agents appear
Addresses review feedback on #1888.
* fix(transcript): guard mismatched appends, expose prompt via klient
- transcript: appendAtOffset now treats an overlapping chunk whose head
does not match the local tail as a gap (diverged stream) instead of
silently rewriting from the offset and dropping local content
- klient: add the optional prompt field to the turn.started event schema
so SDK listeners receive it instead of zod stripping it
Addresses review feedback on #1888.
* fix(transcript): open turns for subagent run prompts in cold grouping
- transcript: add the subagent system trigger to the turn-opening set —
a subagent's run prompt (persisted as system_trigger/'subagent') always
launches a new engine turn, so resumed subagent histories no longer fold
the response into the previous turn or lose the prompt
Addresses review feedback on #1888.
* fix(transcript): guard bus subscriptions independently of projectors
- kap-server: subscribeAgent now guards on a dedicated subscribedAgents
set instead of projector existence — a projector seeded before its
agent's handle exists (e.g. during an on-demand backfill) no longer
blocks the bus subscription, so the agent's live events keep flowing
Addresses review feedback on #1888.
* fix(kimi-inspect): reconcile the transcript on every socket open
- apps/kimi-inspect: TranscriptWs now reports onReconnected on the FIRST
successful open too, not only on re-established ones — ops emitted
between the REST page load and the subscription (a delayed or failed
first connection) were previously lost onto a stale store; the consumer's
refresh guard drops the no-op call while the initial load is in flight
Addresses review feedback on #1888.
* fix(transcript): derive the active step, dedupe tool error rendering
- kap-server: the projector gains a stepOrdinal lookup backed by the
engine's activity view (resolved lazily through the agent lifecycle), so
deltas after a late attach at step >= 2 land in the real active step
instead of a synthesized t<N>.1
- apps/kimi-inspect: render a tool frame's error only when it differs from
its output — onToolResult sets both to the same string for failed tools,
which drew the failure twice in red
Addresses review feedback on #1888.
* fix(kimi-inspect): reconcile the transcript on the subscribe ack
- apps/kimi-inspect: TranscriptWs now fires onReconnected when the
subscribe ack for its client_hello arrives instead of at socket open —
the server attaches the transcript stream only after processing
client_hello, so a refresh fired at open could finish before the
subscription was active and still miss the ops in between
Addresses review feedback on #1888.
* fix(kimi-inspect): coalesce concurrent transcript refreshes instead of dropping
A subscribe ack landing while the initial REST load was still in flight
hit the `if (refreshing) return` guard, so ops emitted between the REST
page snapshot and the WS subscribe were neither in the page nor
delivered over the socket. Replace the drop guard with a coalesced
runner: at most one refresh in flight, and triggers during a run are
collapsed into exactly one follow-up run after it settles.
* fix(kap-server): force the transcript baseline after cursor-based replay
A cursor re-subscribe at unchanged grades deferred its baseline and then
compared against the previous grades on flush, so no reset was sent —
while volatile ops fanned out during the deferral had been dropped,
leaving the client with a permanent gap. flushTranscriptSeed now always
seeds a full baseline (previous grades no longer tracked in the deferred
record), and a regression test covers the same-grade cursor resubscribe.
Also drop the inline comments added to shellCommandService.ts — the
agent-core-v2 convention keeps commentary in the top-of-file block; the
context moved there.
* fix(kap-server): harden transcript seeding against stale and wildcard subs
Two subscribeTranscript gaps found in review:
- Re-read the target's subscription after the history awaits: subscribe
work runs asynchronously, so an overlapping downgrade/unsubscribe used
to be answered with resets computed from the stale spec. The reset
loop now uses the latest grades/filter from state.targets and bails
when the target is gone or no longer graded.
- Backfill roster agents admitted via the wildcard grade, not just
explicitly named ones: a historical subagent seeded into the roster
from session metadata had no materialized AgentTranscript, so
wildcard subscribers silently never received its baseline reset.
Adds regression tests for the wildcard backfill, the mid-seed
downgrade, and the mid-seed unsubscribe (all three fail without the
fix); makeCore now accepts persisted agent metadata for roster seeding.
* fix(transcript): let meta.merge clear mode badges on mode exit
`agent.status.updated` with `planMode: false` / `swarmMode: false` was
dropped by the transcript projector because `meta.merge` could only set
mode badges, never clear them — clients kept rendering an exited mode
until the next full reset. The merge wire shape now accepts `null` per
mode key (set = object, clear = null, absent = keep): the reducer
deletes the key and normalizes an empty `modes` away, the zod schema
validates the nullable form, and the projector emits the clearing op
for exit events.
* fix(agent-core-v2): keep system-turn steering text out of turn prompts
`turn.started.prompt` was populated from the turn input for every
origin, so system-triggered turns (goal continuation, subagent run,
cron) exposed their internal steering text to live transcript
consumers; the cold rebuild mirrored the same leak when grouping
persisted history. The loop now populates the prompt only for
displayable user origins (user input, or a user-slash skill/plugin
activation) via the new isDisplayablePromptOrigin gate, and the cold
grouping opens hidden-origin turns promptless. Turns still open
normally — only the prompt text is withheld.
* fix(kap-server): reattach the transcript fan-out after a session reload
When the engine session closed or archived, TranscriptService dropped
the live store together with its ops listener set, but the
broadcaster's SessionState kept its transcriptStream — so
ensureTranscriptStream returned early for a later subscribe on the
resumed session, delivering a fresh reset but never the live
transcript.ops. The stream is now pinned to its TranscriptStore
instance and the fan-out re-registers whenever a rebuilt store shows
up. Adds a regression test that drops the service entry mid-stream and
asserts ops keep flowing after resubscribe (fails without the fix).
* fix(transcript): map legacy background_task origins in cold rebuilds
Legacy/v1 sessions persist background-task notifications with
origin.kind === 'background_task' (the live mapper already handles that
spelling), but the cold grouping only mapped 'task' — after a restart
those turns fell through to { kind: 'other' } and lost their taskId, so
the transcript could no longer associate the notification turn with its
background task. Both spellings now share the task-origin branch.
* fix(kap-server): project no-taskId shell failures into the transcript
A foreground `!` command that failed before onForegroundTaskStart ran
(Bash validation/spawn/registerTask errors) published shell.output /
shell.completed with taskId undefined, and the projector's guard
dropped them — the live transcript lost the stderr and the terminal
state of a command that did run. Shell events now resolve their task as
the id learned at shell.started, else the event's own taskId, else a
synthetic per-command id (shell-<commandId>), so early failures land
like any other shell task.
* refactor: drop the /api/v2 RPC surface and the klient http transport
- kap-server: remove the /api/v2 REST routes and /api/v2/ws socket (registerRpcRoutes renamed to serviceDispatcherRoutes; transport/ws/{eventMap,registerWs,wsClient,wsConnection,wsProtocol} deleted). /api/v1/debug/* is now the only RPC surface — a reflection dispatcher over the entire scoped DI registry with no whitelist — and /api/v1/ws the only WS endpoint
- klient: drop the http transport (transports/http/*, transports/ws/wsSocket.ts) and the kap-server devDependency; transports reduce to the ipc|memory subpath entries, and the dual/v2 e2e suites go with them
- kimi-inspect: target /api/v1/debug only with no fallback, replace the Service-event push channel (wsChannel/wsSocket) with on-demand fetch plus 15 s polling, and show a blocking "Debug surface unavailable" screen on connection failure
- transcript: add global attachment/interaction/todo entities (model, ops, wire schema) and project them from engine events in kap-server's coreEventMap
* fix(kimi-inspect): drop the unused TranscriptTodo import
|
||
|
|
319001ae5c
|
refactor: remove git detection from workspace wire and folder browse (#1787) | ||
|
|
df75a0f5c2
|
refactor(agent-core-v2): derive session busy from agent activity (#1751) | ||
|
|
2bf009fe27
|
fix(agent-core-v2): reject subagent goals (#1697)
* fix(agent-core-v2): reject subagent goals * fix(kap-server): guard reflected subagent goals |
||
|
|
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 |
||
|
|
2383137f3e
|
ci: release packages (#1583)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
5eb62178b3
|
feat(web): add session diagnostic export (#1646)
* feat(web): add session diagnostic export * fix(web): bound session export resources * fix(web): make session export atomic * feat(web): add session export entry to session menus with item icons |
||
|
|
0303b82c3e
|
fix: align v1 protocol handshake and tool_result media passthrough (#1630)
* fix(protocol): make server_hello heartbeat_ms optional kap-server dropped the server-initiated WS heartbeat and no longer emits heartbeat_ms in server_hello, but the published v1 schema still required it, so spec-compliant clients rejected the handshake before subscribing. - mark heartbeat_ms optional in serverHelloPayloadSchema (advisory only) - add a ws-control test for a server_hello without heartbeat_ms - align kimi-web WireServerHello and the server-e2e handshake assertion * fix(agent-core-v2): pass media parts through tool_result projection - keep raw kosong content-part array for tool results carrying image/video/audio parts instead of flattening to text - restore ReadMediaFile media rendering after session reload/resume * chore: add changeset for optional server_hello heartbeat_ms * docs(agent-core-v2): move tool_result media rationale to module header Per the agent-core-v2 comment conventions, comments live solely in the top-of-file block — move the media-passthrough rationale out of the buildProtocolContent JSDoc into the module header. |
||
|
|
e223549a79
|
fix(web): make mid-turn delta offsets step-relative (#1609)
* fix(web): make mid-turn delta offsets step-relative Reset in-flight text and client stream alignment at step boundaries so resync seeds only the current step instead of duplicating prior steps. * fix(web): dedupe resync-seeded messages by normalized content The exact-JSON content signature missed duplicates when the two copies differed by thinking signature, tool progress, part boundaries, or the tool set (finished parallel tools leave running_tools). Reduce content to concatenated stream text plus sorted tool-call ids and treat a covered subset as the duplicate, merging the seed's tool progress into the existing cards before dropping it. |
||
|
|
f338fcdac4
|
fix(web): restore swarm member list after page refresh (#1589)
* fix(web): restore swarm member list after page refresh * chore: add changeset for swarm roster refresh fix |
||
|
|
2da45fc419
|
fix(web): restore the goal card after a page refresh (#1606)
* fix(web): restore the goal card after a page refresh * fix(web): assert goal endpoint URL without stringification * fix(web): skip goal recovery write when a live goal event wins the race * fix(web): track goal events with a per-session version so clears win the recovery race |
||
|
|
bc8eb1e417
|
chore: drop #/ import array fallbacks and custom resolution plugins (#1594) | ||
|
|
ceb158dc54
|
feat(v2): land agent-core-v2 engine and kap-server behind experimental flag (#1441)
Some checks are pending
CI / typecheck (push) Waiting to run
CI / test-pi-tui (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
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / build (push) Waiting to run
CI / test (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Release / Desktop release artifact (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
* fix: adapt grep tool to agent-core-v2 * fix(agent-core-v2): enrich PATH from the user's login shell at startup - port probeLoginShellPath/mergeLoginShellPath/applyLoginShellPath into _base/execEnv/loginShellPath.ts as a pure helper (no DI) - export execFileText from environmentProbe for reuse by the probe - run applyLoginShellPathFromNode concurrently with the host probe in HostEnvironmentService, mirroring kaos LocalKaos.create() Aligns agent-core-v2 with kaos |
||
|
|
7db88b6f0c
|
feat(server): add --dangerous-bypass-auth and --keep-alive flags (#1368)
* feat(server): add --dangerous-bypass-auth and --keep-alive flags - --dangerous-bypass-auth disables bearer-token auth on every REST and WebSocket route and advertises it via /api/v1/meta so the web UI skips the token prompt; the startup banner drops the token and shows a red danger notice - --keep-alive keeps the daemon running instead of idle-killing after 60s; implied by --host / --allowed-host and always on in --foreground mode * fix(server): address review feedback on bypass-auth - keep the token and skip the bypass notice when a daemon is reused, since the requested --dangerous-bypass-auth flag is not applied to the already-running server - clear the cached dangerous_bypass_auth web state on HTTP 401 so a stale bypass value cannot hide the token prompt after the server restarts without the flag |
||
|
|
329846c569
|
feat(agent-core): keep head and tail of user messages during compaction (#1313)
* feat(agent-core): keep head and tail of user messages during compaction Compaction used to keep only the most recent 20k tokens of real user input, so the original task statement was the first thing to vanish in long sessions. Now, when the user-message pool fits the 20k budget it is still kept whole; when it overflows, the oldest 2k tokens and the most recent 18k are kept instead, with an elision marker between the two segments telling the model what was omitted and that the summary covers it. The summary prefix and the default system prompt describe the new shape as well. The new `keptHeadUserMessageCount` record field keeps restore and the wire-transcript folded length consistent: records without it (written by older versions) restore with the original tail-only selection that produced them, and the vis model-mode projection mirrors the same head/marker/tail rebuild. * style(agent-core): drop redundant spread over slice in head selection |
||
|
|
ba7f18b3fb
|
ci: release packages (#1268)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
b905dd4910
|
feat(web): redesign web UI and add design system (#1258)
* feat: redesign web ui & add design system * feat(web): add motion to redesigned UI and add changesets Animate toast enter/leave, dialog open, and workspace-list and tool-row expand/collapse instead of snapping, and add the changesets covering the web redesign. * fix(web): remove undo message exit animation * fix(web): route agent tools to AgentTool and focus dialog on open - toolRegistry matched the raw 'agent' name, but normalizeToolName folds agent/subagent into 'task', so agent calls fell through to GenericTool and lost the inline Open button for the subagent detail panel. - Dialog's focus watcher only fired on change; callers that mount with open already true (Login, Settings, ...) never moved focus into the modal. Run it immediately so initial focus and restore-on-close work. * feat(web): add logo long-press design-system easter egg Hold the sidebar logo for 3 seconds to open a dialog showing the design system page. Also trim and rebalance the redesign changesets. * fix(web): silence Sidebar v-show warning by making it single-root Nest the design-system Teleport inside the sidebar <aside> so the component has a single element root. App applies v-show to Sidebar, which needs an element root to attach to; the fragment root logged a "non-element root node" warning on every reactive update and the collapse did not take effect. * fix(web): thinking toggle, tool-group i18n, agent detail button - Show the default-thinking switch as on whenever thinking is effectively enabled (enabled !== false), matching the core resolver. - Route the grouped tool-call header and status through vue-i18n. - Hide the subagent "Open detail" button when no matching task exists (e.g. a completed foreground subagent after a refresh). * fix(web): use strict equality in agent detail button guard oxlint eqeqeq flagged the loose != null check; resolveAgentTaskId returns string | undefined, so compare with !== undefined. * chore(web): remove stray design mockups and screenshots Remove the design exploration mockups, screenshots, prompts, and notes that were accidentally committed under apps/kimi-web/design. Keep design-system.html, which the sidebar logo easter egg still references. * fix(web): keep sessions on continuation failure, treat absent thinking as on - Keep sessions already loaded from earlier pages when a continuation page fetch fails, instead of replacing the workspace with an empty page. - Treat an absent thinking config as enabled in the settings toggle, matching the core resolver (thinking is on unless explicitly disabled). * feat(web): open design-system easter egg on 10 logo clicks Replace the 3-second long-press trigger with 10 consecutive clicks on the Kimi mark; the count resets after a short idle. The long-press was unreliable because pointerleave cancelled the timer on any drift. * fix(web): treat cancelled swarm members as finished phaseForTask now lets a terminal status (completed/failed/cancelled) override a stale subagentPhase, so a cancelled swarm member no longer stays live and suppresses the finished AgentSwarm card. * feat(web): use 1s long-press for design-system easter egg Switch the logo easter egg back to a long-press, shortened to 1 second, and make it reliable this time: use pointer capture plus touch-action:none so a slight drift no longer cancels the hold. * fix(web): use plain Spinner for activity notices ActivityNotice renders for non-chat loading states (e.g. compaction), so it must use Spinner per the design-system rule that reserves MoonSpinner for the chat first-response state. * docs(web): add a11y guidance to design system * docs(web): drop stale design README link * fix(web): restore model search focus and define panel header weight - Bind the model picker's search Input to searchRef so useDialogFocus moves focus into it on open instead of the dialog's close button. - Use the defined --weight-semibold token for panel header titles (--weight-bold is not declared, so the shorthand was invalid). * fix(web): let any open dialog own Escape over the side panel Track open design-system Dialog instances in a shared count and include it in App.vue's anyOverlayOpen, so a dialog whose open state lives outside App.vue (such as the sidebar session search) captures Escape before the background side panel closes. * fix(web): base dock-work flag on filtered dock task lists Foreground subagents are excluded from the dock task lists, so a session whose only task is a foreground subagent no longer renders an empty workbar above the composer. * fix(web): create subagent task before forwarding text deltas A client that subscribes from a snapshot after subagent.spawned already fired never received the lifecycle taskCreated; the reducer only applies taskProgress to existing tasks, so assistant text deltas were dropped and the live subagent detail stayed blank. Emit taskCreated (via patchSubagent) before the text progress, mirroring the tool-progress path. * fix(web): keep plan, swarm, and goal mode toggles per session Plan, swarm, and goal modes were stored as global scalars on the web client and a single localStorage key each, so they leaked across sessions. Bind them to the active session via per-session maps, persist per session, and apply server status/events to the originating session so background sessions keep independent state. * fix(web): keep subagent detail reachable for synthesized tasks When the web client subscribes after a subagent already spawned, the synthesized subagent task has no parentToolCallId, so the Agent tool's Open-detail button was hidden and the panel would not open. Fall back to the single unmapped subagent task when resolving the detail target in both the button visibility and the panel open paths. * fix(web): keep session kebab menu from being clipped Teleport the SessionRow kebab menu to body and anchor it with fixed positioning so the collapsing group-sessions list's overflow:hidden no longer clips the dropdown. * fix(web): apply staged modes to the created session by id When starting the first prompt, apply the staged plan/swarm/goal modes to the just-created session's per-session maps by id instead of via the activeSessionId-based setters, so a session switch during the selectSession await can't drop the modes for this session or pollute another. * refactor(web): unify confirmation dialogs into a single modal Replace the inconsistent confirmation patterns (native confirm(), two-step menu arming, hand-rolled inline strips, bare buttons) with one modal ConfirmDialog driven by a global useConfirmDialog() composable, and consolidate the duplicated confirm/cancel i18n keys. * feat(web): inline message queue with separate stop button - Send button always sends/enqueues; interrupt moves to a separate red Stop button shown only while running, so the two can no longer be confused. - Queued prompts now render inline at the tail of the transcript (after the running turn) instead of behind the dock panel: click to edit, remove, drag the grip to reorder, with image thumbnails and a "next up" marker. - Remove the dock queue panel and the QueuePane component; Steer stays on Ctrl/Cmd+S. * chore: add changeset for web queue UX * feat(web): prompt reliability, sidebar menu, and composer/markdown polish - Fix spurious errors when question/approval/task actions were already complete - Add loading feedback to question and approval prompts; block double-clicks - Make the question "Other" option selectable by row click and let Enter advance/submit - Consolidate workspace section actions into an overflow menu - Tighten markdown prose line-height and block spacing - Recall input history only when the caret is at text start |
||
|
|
f2c7ec75d3
|
ci: release packages (#1224)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
86e0c9201e
|
feat(agent-core): rework compaction to keep only user prompts and summary (#1214)
* feat(agent-core): rework compaction to keep only user prompts and summary
* refactor(agent-core): rewrite compaction summary as first-person handoff
Rework the full-compaction summary to read as the agent's own continuing
notes instead of a third-party report:
- compaction-instruction.md: free-form first-person continuation that
preserves exact commands, paths and outcomes, states the precise next
action, and flags claimed-but-unverified work rather than trusting it.
- compaction-summary-prefix.md: skeptical "your own working notes"
framing; drop the collaborative third-party prefix.
- system.md: add compaction-awareness guidance so the model continues
naturally from a summary and re-checks any reported "done".
- Rename the compaction helpers module to handoff.ts.
Update tests and regenerate snapshots for the new prompt text, and fill
in contextSummary in the restored-compaction replay expectations.
* fix(agent-core): count image/audio/video parts in token estimation
estimateTokensForContentPart returned 0 for image_url/audio_url/video_url,
so auto-compaction triggers, the overflow-shrink budget, the kept-user
budget, and the reported context size all went blind to media — a
media-heavy session could overflow the model window while the estimate
reported a near-empty context. Media parts now carry a fixed estimate
(MEDIA_TOKEN_ESTIMATE), and the content-part switch is exhaustive so a new
ContentPart kind must declare its estimate rather than silently count as
zero.
* feat(agent-core): re-surface active background tasks after compaction
Folding the live context to [recent user prompts, summary] drops the
messages that started background tasks and their status updates, so the
model could forget a task is still running and spawn a duplicate.
injectAfterCompaction now appends a system-reminder listing active
background tasks (with guidance to use TaskOutput/TaskList/TaskStop
instead of re-spawning). It runs only post-compaction and carries an
injection origin, so the next compaction drops and rebuilds it rather
than stacking copies; the all-user-role post-compaction shape is
preserved (no tool-pairing reintroduced).
* test(agent-core): add compaction scenario guards and risk probes
Adds compaction-scenarios.test.ts driving the real Agent/ContextMemory/
FullCompaction machinery:
- A guard test locking in that repeated compaction folds the prior summary
into the new one instead of stacking two summaries.
- Seven `it.fails` probes that executably reproduce known, currently-accepted
edge-case defects so the suite stays green while documenting each one
precisely; any of them will flip red (forcing removal of `.fails`) the day
the behavior is fixed. They cover: assistant/tool appended during an
in-flight summarizer call being dropped; unbounded shrink on empty
summaries; the fixed 20k kept-user budget overflowing a small model window;
a tool result orphaned when compaction starts mid-exchange; legacy
compaction records dropping their verbatim tail on replay; micro-compaction
clearing recent tool results in an overflow-shrunk suffix; and media being
discarded when the oldest kept user message is truncated.
* fix(agent-core): repair tool_use/tool_result adjacency in projected context
A tool call and its result can end up non-adjacent in history — a
background-task notification or flushed steer lands between them, or an
interrupted/nested step delays the result — which strict providers reject
with HTTP 400. The projector now moves each tool_use's result up to
immediately follow it (projection-time only; the stored history is
untouched), and full compaction projects its summarizer input with a
synthetic result for any still-open call so the summary request stays
well-formed. Micro-compaction only surfaced this latent ordering by busting
the prompt cache, so it now defaults off.
Includes projector adjacency regression tests, a context-level integration
test, and a compaction synthesize-missing guard; the prior "keeps an
unresolved tool exchange out of the compaction prompt" test is updated to
the now-well-formed (synthetic-result) behavior.
* fix(agent-core): preserve the verbatim tail when restoring legacy compactions
A pre-rework `context.apply_compaction` record used
`[summary, ...history.slice(compactedCount)]` semantics and kept a verbatim
recent tail, but it has no `keptUserMessageCount`. The reworked applyCompaction
re-folded such records into the all-user shape, dropping the recent
assistant/tool tail — so resuming a session compacted by an older version
silently lost its most recent context.
On restore of such a record (gated on records.restoring, no keptUserMessageCount,
and compactedCount < history length) reproduce the old shape instead. The
forward/live path is unchanged; the projector's tool-adjacency repair keeps the
restored tail well-formed, and compaction only runs at clean step boundaries so
the tail has no open exchange. The legacy-tail probe now passes as a regression
guard via the real restore path.
* fix(agent-core): align legacy compaction foldedLength with live restore
The transcript reducer re-derived foldedLength for pre-rework
context.apply_compaction records (no keptUserMessageCount) using the new
kept-user+summary rule, but ContextMemory's restore now reproduces the legacy
[summary, ...history.slice(compactedCount)] shape for those records. The two
diverged for legacy sessions, so MessageService's foldedLength-vs-live-history
comparison could mis-handle GET /messages (miss or misorder recent output).
The reducer now mirrors the live legacy fold: when compactedCount is below the
pre-compaction length it computes 1 + (length - compactedCount); otherwise it
falls back to the kept-user derivation. The MessageService transcript test's
fixture is corrected to a new-format record, matching its all-user live mock.
* fix(kosong): merge a follow-up user turn into the preceding tool_results
The Anthropic message merge keyed on isToolResultOnly(last) ===
isToolResultOnly(converted), which left a tool_result-only user turn
followed by a plain-text user turn unmerged. After tool-exchange repair
this shape (assistant tool_use -> tool_result -> injected notification)
produces two adjacent user messages, which strict Anthropic-compatible
backends reject with HTTP 400.
Switch to the asymmetric predicate isToolResultOnly(last) ||
!isToolResultOnly(converted): a tool-result-only running message absorbs
whatever user turn follows (parallel tool_results or a trailing text),
yielding a valid [tool_result, ..., text] message; a plain-text running
message still only absorbs plain text. [tool_result, text] is valid for
both native Anthropic (which concatenates anyway) and strict backends.
* test(agent-core): pin micro-compaction flag in the shrunk-suffix probe
The 'does not clear recent tool results when projecting a shrunk suffix'
probe is an it.fails that only documents a real defect while
micro-compaction is active. It inherited the ambient
KIMI_CODE_EXPERIMENTAL master switch, so its pass/fail flipped with the
runner: green locally (master switch on) but a hard failure in CI, where
the flag defaults off and MicroCompaction.compact() is a no-op that
leaves the tool result intact.
Enable KIMI_CODE_EXPERIMENTAL_MICRO_COMPACTION explicitly for this probe
so it deterministically exercises the micro-compaction path regardless of
the environment.
* fix(agent-core): harden full compaction against in-flight races, unbounded shrink, and media loss
Three compaction-path fixes surfaced by review, each flipping its
documenting it.fails probe to a passing it:
- Append race (CMP-02): after the summarizer returns, the post-summary
history check only compared the compacted prefix. A live step appending
to the tail while a manual/SDK compaction was in flight slipped through —
an appended assistant/tool turn is neither summarized (the summary covers
only the snapshot) nor kept (the rebuild keeps user input), so it
vanished. Now cancel when the appended tail contains a non-user message;
an appended user message is still kept (rebuild picks it up), preserving
the existing 'keeps messages appended while compacting an unchanged
prefix' behavior.
- Unbounded empty/truncated shrink: an empty or truncated summary dropped
the oldest message and reset retryCount, so a model that kept returning
empty could issue ~one request per history entry. Bound the shrink
attempts by MAX_COMPACTION_RETRY_ATTEMPTS, mirroring the overflow-shrink
counter.
- Media dropped on truncation (CMP-07): truncating the oldest kept user
message replaced its whole content with one text block, discarding any
image/audio/video. Keep the non-text parts and spend the remaining budget
(maxTokens minus their cost) on truncated text.
* fix(vis): mirror legacy compaction tail in the model-mode projector
For a pre-rework context.apply_compaction record (no keptUserMessageCount),
agent-core's ContextMemory restore and the transcript reducer keep the old
[summary, ...history.slice(compactedCount)] tail — a verbatim recent tail
including assistant/tool. The vis model-mode projector always applied the
new kept-user selection, so opening an older compacted session in model
mode hid the assistant/tool tail the resumed agent still holds (and
surfaced a pre-compaction user message the agent dropped).
Branch on a missing keptUserMessageCount with compactedCount < history
length and reproduce the legacy shape, matching the agent-core restore.
* fix(agent-core): cancel compaction on any droppable user-role tail
The in-flight append guard cancelled only when the tail grew with a
non-user role. A user-role message that compaction would still drop — a
background-task notification, hook/cron reminder, or shell-command output —
slipped through: appended after the summary snapshot (so absent from the
summary) and dropped by the all-user rebuild (which keeps only real user
input), vanishing silently.
Key the guard on the same predicate applyCompaction uses (!isRealUserInput)
so it cancels whenever the appended tail holds anything compaction would
drop. A real user message is still kept, so a live user turn racing a
manual/SDK compaction continues to complete.
* fix(agent-core): exclude pre-clear prompts from legacy folded length
The transcript reducer's legacy fallback (records predating
keptUserMessageCount, compacted with no verbatim tail) re-derived the
kept-user count from the whole transcript, including messages before the
last context.clear. Live ContextMemory rebuilds _history from post-clear
messages only, so counting pre-clear prompts overstated foldedLength;
MessageService then saw context.history.length <= foldedLength and skipped
appending unflushed live tail messages, dropping recent output from the
messages endpoint for old sessions compacted after a clear.
Derive only from entries at or after clearFloor to match the live context.
* fix(agent-core): drop media when truncating the oldest kept prompt
Revert the media-preserving truncation: keeping non-text parts on the
truncated boundary message overshot the kept-user budget when the media
alone exceeded it, and reordered interleaved text/media parts. Both codex
(no media-aware truncation) and Claude Code (strips media at compaction)
decline to preserve media on a truncated message, since media cannot be
partially truncated and keeping it whole breaks the budget.
truncateUserMessage now keeps only the truncated text. Recent messages
that fit the budget are still kept verbatim with their media; only the
oldest, partially-overflowing boundary message loses its attachments.
* fix(agent-core): make manual compaction and turns mutually exclusive
A manual/SDK compaction could start while a turn was streaming, or a new
turn could launch while a compaction was in flight. Either way the turn
mutates the shared context (streaming content into an existing assistant
message, or appending new messages) during the summarizer await, and that
output is neither summarized nor preserved by the all-user rebuild —
silent loss that object-identity checks can't detect (the streamed message
is mutated in place).
Guard both directions so the agent does one of {turn, compaction} at a
time: begin() refuses a manual compaction while a turn is active, and
launch() refuses a new turn while a compaction is in progress. Auto
compaction is exempt — it runs from within the turn at a step boundary,
which blocks the turn for its duration.
* chore(changeset): consolidate compaction changesets into one
* chore(agent-core): drop external-product references from compaction comments
* test(agent-core): add Anthropic wire-compliance smoke tests for compaction
Drive real compaction output and the compaction summarizer projection
through the real Anthropic provider conversion and assert the wire request
is well-formed: strict user/assistant alternation and every tool_use
answered by an adjacent tool_result. Locks in the cross-layer guarantee
(projector merge + Anthropic consecutive-user merge + adjacency repair +
synthesizeMissing) that compacted sessions stay valid for strict
Anthropic-compatible backends.
* fix(agent-core): defer and replay inputs during manual compaction instead of rejecting
Manual/SDK compaction runs outside a turn, so the earlier guard rejected
prompts/steers that arrived while it held the context. That broke three
things: a REST/web prompt got stuck 'running' (no terminal turn event), a
background-task/cron steer was silently lost (null was read as 'buffered'
but nothing was), and a follow-up prompt could land in the window after
isCompacting cleared but before reminders were reinjected.
Reuse the existing defer-and-replay model instead of rejecting:
- steer() and launch() buffer into steerBuffer while a compaction is in
progress (returning null = buffered), mirroring how an active turn defers
input.
- FullCompaction.compactionWorker keeps isCompacting true through
refreshSystemPrompt + injectAfterCompaction (moving markCompleted and the
completed event after reinjection), then replays the buffer via
TurnFlow.onCompactionFinished — on success, on an A1 prefix/tail cancel,
and on failure/abort.
- onCompactionFinished flushes into an active turn if one exists, else
launches a fresh turn from the deferred input.
No PromptService change: a deferred prompt's eventual turn.started lets it
associate the pending prompt and clear it on turn.ended.
* fix(kosong): merge consecutive user turns for strict providers
Gemini/Vertex require strictly alternating user/model turns and reject
consecutive user turns with HTTP 400. They arise after compaction (kept
prompts + user-role summary + injected reminders) and when a turn is
steered in right after a tool result. Anthropic already merged them
inline; the Google converter did not, so post-compaction requests failed.
Extract the asymmetric merge into a shared mergeConsecutiveUserMessages
helper applied at each strict provider's conversion boundary: refactor
Anthropic to use it (behavior unchanged) and apply it at the Google
converter's exit. A conformance suite drives every strict provider with
the post-compaction shape and a steer-after-tool-result shape, asserting
no consecutive same-role turns reach the wire, so a new strict provider
cannot silently omit the merge.
The provider-agnostic projector stays structure-preserving: lenient
providers (OpenAI/Kimi) keep distinct turns for clearer message
boundaries; only strict providers normalize, where the requirement lives.
|
||
|
|
108299be3c
|
refactor!: overhaul thinking config and effort resolution (#1132)
* feat: support multi-level thinking effort switching
- kimi provider: emit thinking.effort in the new wire format; keep reasoning_effort mirrored during the transition
- model catalog: thread support_efforts / default_effort from oauth through to /models
- config schema: add supportEfforts / defaultEffort on model aliases
- TUI: multi-segment thinking control in /model, new /effort command, footer effort display
- switch status uses displayName and distinguishes model vs effort-only changes
* docs: add thinking effort design plans
- thinking-effort-switching.md: implemented multi-level effort switching
- thinking-model-overhaul.md: follow-up refactor plan for the thinking state model
* docs: collapse thinking overhaul plan into a single PR
* refactor!: overhaul thinking config and effort resolution
Replace default_thinking and thinking.mode with a single [thinking] enabled/effort table. ThinkingEffort is now an open string ('off' | 'on' | model-declared effort); effort levels come from each model's support_efforts instead of a fixed enum.
Centralize default and always_thinking clamp logic in resolveThinkingEffort/defaultThinkingEffortFor, and honor an explicitly configured effort when an always_thinking model is forced back on.
TUI keeps a single thinkingEffort field instead of the boolean + level pair; 'on' is normalized to the model default at the UI boundary.
BREAKING CHANGE: default_thinking and thinking.mode are removed from config; migrate to [thinking] enabled/effort.
* refactor: rename residual thinking level wording to effort
Rename comments, error messages, parameter names, the SetThinkingPayload wire field (level -> effort), and TUI local variables so the thinking effort naming is consistent throughout. No behavior change.
* refactor: rename remaining camelCase thinking level identifiers to effort
Rename liveLevel/prevLevel/levelChanged/commitLevel/effectiveLevel to liveEffort/prevEffort/effortChanged/commitEffort/effectiveEffort in the TUI model picker and config commands.
* refactor: eliminate remaining thinking level wording in comments and tests
Rename levelLabel -> effortLabel, EffortSelectorOptions.levels -> efforts, and 'effort level(s)' / 'default level' / 'requested level' wording in comments, error messages, slash-command description, and test titles to effort. Also restore the withThinking(effort) parameter rename in the Kimi provider that was accidentally reverted.
* fix: address codex review feedback on thinking effort handling
- OpenAI thinkingEffortToReasoningEffort and Anthropic clampEffort now normalize 'on' / unrecognized efforts instead of throwing, so boolean non-Kimi models no longer crash on session start.
- ACP resolveCurrentThinkingEnabled treats a non-empty thinking.effort as enabled, matching agent-core's resolveThinkingEffort.
- REST promptThinkingSchema accepts any non-empty effort string so model-declared efforts are not rejected at the API boundary.
* test: align kimi e2e expectations with supportEfforts-gated reasoning_effort
The kimi provider now sends reasoning_effort only when the model declares support_efforts; boolean models (no support_efforts) send only thinking.type. Update the kimi e2e tests to drop the stale reasoning_effort expectation for the boolean test model.
* test: cover [thinking] effort parsing in config.test
Add effort = "high" to the documented [thinking] table in the config parse test and assert config.thinking.effort is resolved, so the new [thinking] effort field has direct parse coverage.
* docs: add thinking test coverage gap analysis
Capture the explore agent's test coverage review for the thinking overhaul PR, including P1/P2 gaps and the two open design questions, for follow-up test additions.
* feat(oauth): parse nested think_efforts from /models response
The /models endpoint now returns effort levels under a nested think_efforts object ({ support, valid_efforts, default_effort }). Parse it preferentially in both managed-kimi-code and open-platform model parsing, falling back to the legacy flat support_efforts / default_effort fields for older servers.
* refactor(oauth): only read nested think_efforts; gate on support=true
Drop the legacy flat support_efforts / default_effort fallback. The think_efforts object is now the single source, and its support flag gates the whole object — when support is not true, valid_efforts and default_effort are ignored entirely.
* chore: remove unused parseStringArray import in open-platform
* docs: finalize thinking effort release notes
Downgrade the changeset to minor with an English summary, drop the version-specific 'added in 1.0.0' info block, and present the deprecated config fields as a table (field / deprecated in 0.21.0 / description).
* refactor: drop temporary refresh toggles and kimi reasoning_effort mirror
Remove the always-true REFRESH_MODELS_ON_PICKER_OPEN / REFRESH_PROVIDER_MODELS_ON_STARTUP toggles and their stale re-enable TODOs, and stop sending reasoning_effort from the kimi provider (thinking.effort is the only wire field now).
* fix(tui): avoid persisting "on" as thinking effort
* fix: preserve persisted thinking effort across login and provider setup
* fix(tui): show actual thinking effort in /status and footer
* test(tui): align message-flow expectations with effort persistence and /status display
* fix(vis): rename thinkingLevel to thinkingEffort in config.update analysis
|
||
|
|
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 |
||
|
|
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 |
||
|
|
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. |
||
|
|
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
|
||
|
|
dfcfdfd9dd
|
feat(web): hide empty sessions from the session list (#1166)
* chore(web): remove the /sessions slash command
* feat(web): hide empty sessions from the session list
Add an optional exclude_empty parameter to the session list API; the web client passes it so unused "New Session" entries are hidden by default, with pagination and has_more computed on the filtered set.
* fix(protocol): add exclude_empty to the session list query schema
Keep the shared protocol schema in sync with the server route so clients using the protocol type see the new parameter.
* fix(protocol): keep exclude_empty off the child session list schema
listSessionChildrenQuerySchema aliased the main list schema, so it inherited exclude_empty even though the /sessions/{id}/children route does not filter by it. Split it so generated clients are not misled.
|
||
|
|
2db5fc20ec
|
feat: add shell mode (!) to the CLI (#1079)
* feat: add shell mode (`!`) to the CLI Add shell mode, letting users run shell commands directly from the prompt with `!`. Output streams live into the transcript, supports backgrounding (ctrl+b), cancellation (Esc / Ctrl+C), input queuing while running, and enters the conversation context with resume support. * feat(kimi-code): show shell mode label on editor border and add tip Render a "! shell mode" label on the top-left of the editor border while the editor is in `!` bash mode, so the active mode is visible at a glance. Also add a rotating toolbar tip (`! to run a shell command`) to surface the feature. * feat(kimi-code): refine shell mode queue, history, and display - Keep `!` commands out of input history so they never resurface as bare text stripped of their `!`. - Make `!` commands non-steerable: Ctrl-S skips them (they stay queued to run after the current task) and the steer hint is only shown when something is actually steerable. - Render queued `!` commands with a `$` prompt and the shell-mode hue so they read as commands, not as text to send to the model. - Echo executed shell commands with a `$` prompt instead of `!`. * fix(kimi-code): sanitize shell output and harden rendering Captured shell command output can contain terminal control sequences (colours, cursor moves, alternate-screen switches, OSC hyperlinks, carriage-return spinners, bells). pi-tui's Text passes strings straight to the terminal, so any unhandled sequence was executed by the terminal and fought with pi-tui's own cursor control, producing the blank-screen-plus-leftover-characters mess after running commands like pnpm dev or a nested TUI. - Sanitize CSI (incl. private modes), OSC, single-char ESC and C0 control chars (keeping newline and tab) in both the finished/resume view (previously unsanitized) and the running tail. - Make the sanitize, format, and ShellRunComponent render paths never-throw, and cap the live running buffer, so a misbehaving command cannot crash the TUI. - Dispose transcript children on clear so ShellRunComponent's timer is released on /clear or session switch. * fix(kimi-code): render shell command echo with $ instead of sparkles The shell command echo is a 'user' transcript entry, so UserMessageComponent prefixed it with the USER_MESSAGE_BULLET (sparkles), producing 'sparkles $ command'. Add an optional bullet override to UserMessageComponent / TranscriptEntry and set it to an empty string for the shell echo (both live and resume), so the '$ command' content sits at the leading column where the sparkles marker used to be. Normal user messages keep the sparkles bullet. * fix(kimi-code): enter shell mode when pasting a !-prefixed command The bash-mode trigger only handled the single ! keystroke, so a pasted !cmd was inserted as literal text in prompt mode and submitted as a normal message. After pi-tui inserts pasted content, detect an empty-prompt buffer that now starts with !, switch to bash mode, and strip the leading ! so the buffer holds only the command, matching the typed ! path. * fix(kimi-code): restore shell mode when recalling a queued command recallLastQueued() dropped the queued item's mode, and the Up-arrow recall only restored the text. A queued ! command (queued while another command runs, which resets the editor to prompt mode) therefore came back as a normal prompt and was submitted as a message instead of a shell command. Return the full QueuedMessage from recallLastQueued() and restore editor.inputMode (plus the onInputModeChange sync) from the recalled item's mode. * feat(kimi-code): use violet as the shell mode color Replace the claude-code-style magenta/rose shellMode token with a violet that is distinct from plan-mode blue, the user role amber, success green, error red, and the teal accent. Custom themes that omit the token fall back to this new default via the base+overrides merge, so existing custom themes keep working unchanged. * chore: refine the shell mode changeset * docs: document shell mode Add a Shell mode section to the interaction guide and list the ! and Ctrl+B shortcuts in the keyboard reference, in both English and Chinese. * test(protocol): include shell events in volatile classification check shell.output and shell.started were added as volatile event types for shell mode; update the snapshot test's volatile-type list and count accordingly. * fix(agent-core): surface shell command failure reason with no output When a ! shell command fails without producing stdout/stderr (non-zero exit with no output, timeout, spawn failure), the failure reason lived only in the tool result's output and the TUI showed '(no output)'. Fold it into stderr so the live view and replay show what went wrong. * fix(kimi-code): decode CSI-u ! to enter shell mode In terminals with the Kitty keyboard protocol (VSCode integrated terminal, Kitty), pressing ! arrives as a CSI-u sequence, so the raw normalized === '!' comparison never matched and shell mode could not be entered by typing !. Decode with printableChar before comparing, matching every other printable-key check in the TUI. * fix(kimi-code): do not steer while a shell command is running Ctrl-S steers queued input into the running turn, but a shell command is not an agent turn, so steering during streamingPhase === 'shell' would launch a turn before the command output is recorded. Keep Ctrl-S a no-op during shell runs; queued messages stay queued. * fix(agent-core): escape bash tag delimiters in shell output Shell command output is arbitrary text; if it contains a bash tag delimiter such as </bash-stdout>, the recorded pseudo-XML wrapper breaks and replay extracts the wrong slice. Escape the content when wrapping it in agent-core and unescape when extracting during replay, so output survives round-trip intact. * docs: document the shellMode theme token The shellMode color token was added to the palette but not propagated to its mirrors. Add it to the custom-theme docs token table, the theme JSON schema, and the custom-theme skill token list. * feat(agent-core): reset background task deadline on detach Add a resettable deadline timer to BackgroundManager and let tasks register a detach timeout; when a foreground task is moved to the background, its deadline resets to the background default counted from the detach moment. Wire this into shell mode so ! commands run with a 3-minute foreground timeout and get 10 minutes once detached to the background, instead of staying bounded by the original 60-second foreground deadline. * feat(agent-core): lower shell mode foreground timeout to 2 minutes |
||
|
|
ff177155ca
|
fix(web): stop auto-dismissing pending questions and approvals on a timeout (#1070)
* fix(web): stop dismissing questions after a 60 second timeout The server's question broker auto-expired AskUserQuestion requests after 60s, which dismissed the question even when the user simply needed more time. Remove the timeout, and the now-unused expires_at field, so a question stays pending until the user answers or explicitly dismisses it. |
||
|
|
66640380eb
|
feat: replace silent AGENTS.md truncation with a visible warning (#1040)
Oversized AGENTS.md files are no longer silently truncated. The full content is injected, and a warning is shown in the TUI status bar and the web UI when the combined AGENTS.md size exceeds the recommended 32 KB. A generic session-warnings API backs this so future warning types can be added without changing the API surface. |
||
|
|
4292ae9f9b
|
fix: surface provider content filter and preserve context tokens (#963)
* fix: surface provider content filter and preserve context tokens * fix: complete filtered turn handling across surfaces - context: accumulate token estimate for zero-usage steps to preserve the tokenCount / tokenCountCoveredMessageCount invariant - turn/goal: pause the goal when a turn is blocked by safety policy - subagent: surface a filtered child turn as a distinct error - acp: map filtered to the native ACP refusal stop reason - tui: show a filtered-specific message in the btw panel - cli: drop the redundant content_filter suffix from the error message - tests: cover filtered across cli, web, acp, and goal flows |
||
|
|
ba64072559
|
feat: detach foreground tasks to background (#821)
Some checks failed
CI / build (push) Has been cancelled
CI / test (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / typecheck (push) Has been cancelled
Nix Build / Check flake.nix workspace sync (push) Has been cancelled
Release / Release (push) Has been cancelled
Release / Native release artifact (push) Has been cancelled
Nix Build / nix build .#kimi-code (push) Has been cancelled
Release / Deploy docs (push) Has been cancelled
Release / Publish native release assets (push) Has been cancelled
|
||
|
|
495fe8c674
|
feat(web): add session search (#895)
* feat(web): add session search Add a search box to the web sidebar that instantly filters all loaded sessions by title and the last user prompt (case-insensitive). Surface the last user prompt from the server: the daemon already persisted it in session metadata, and it now flows through the session schema into the REST response so the web client can match against it. * fix(web): keep lastPrompt fresh on session.meta.updated Address Codex review: the daemon emits session.meta.updated with patch.lastPrompt whenever a new prompt is submitted, but the web projector only forwarded the title. That left the cached session's lastPrompt stale, so sidebar search by the latest prompt text failed until a full reload. Forward lastPrompt through the projector and reducer, and cover it with a pipeline test. * refactor(web): avoid conditional spreads in meta patch Address Codex review: per the root AGENTS.md, optional object properties should be passed directly rather than via conditional spreads. Use nullish coalescing so a field the event does not carry keeps its prior value. * fix(web): stop Escape from aborting a run while search is focused Address Codex review: ConversationPane registers a document-level keydown that aborts the active prompt on Escape. Without handling it on the search input, pressing Escape to dismiss the search would unexpectedly stop the agent. Stop propagation and clear the query, matching the inline rename inputs. * fix(web): exclude hidden-workspace sessions from search Address Codex review: removing a workspace only records its root in hiddenWorkspaceRoots and leaves the sessions intact; the grouped sidebar skips the hidden root, but sessionsForView (the search source) did not, so a matching title or prompt could resurrect sessions from a removed workspace. Filter sessionsForView by the visible workspace set so the flat list matches what the grouped sidebar renders. |
||
|
|
cde7ca51cc
|
feat(goal): support guided goal authoring (#839) | ||
|
|
9a8fea5c85
|
feat(web): introduce Kimi web app and daemon gateway (#625)
* docs(reports): collapse P3 plan into a single final-solution doc Drop the per-step TDD/commit scaffolding; keep the substance as one final approach per area (what it does, files to touch, key types/events/projection, component responsibilities, verification, risks, sequencing). * fix(kimi-web): normalize chat block spacing Group consecutive tool cards structurally so chat block spacing is applied consistently without leaking card borders or shadows. * feat(web): land P3 — goal / swarm / subagent + terminal + view split Implements the locked P3 design end-to-end: - subagent lifecycle projection (spawned→started→suspended→completed/failed) + inline Agent / AgentGroup cards; swarm progress card (multi-column) derived from swarmIndex; goal dock strip (expandable) from goal.updated; plan/goal/ swarm activation badges in the composer status line. - terminal as a view (xterm + WS terminal_* frames with since_seq replay) and a tab/view-dimension split (usePaneLayout tree + ViewGroup + SplitLayout, VSCode editor-group style), persisted to localStorage. Adds swarm-groups / subagent-goal / agent-group-turns unit tests and stub-daemon seeds. 98 tests pass; vue-tsc + oxlint clean; production build OK. Accepted by review (see reports/web-p3-acceptance.md); no blocking issues. * docs(reports): P3 landing acceptance review Comprehensive acceptance of the P3 landing ( |
||
|
|
18aa21575b
|
ci: release packages (#746)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
18f299fd0b
|
mcp suport sse (#744)
Some checks are pending
CI / build (push) Waiting to run
CI / test (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 / Native release artifact (push) Blocked by required conditions
Release / Release (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
Co-authored-by: yuchengzhen <yuchengzhen@moonshot.cn> |
||
|
|
dff9fd4e32
|
chore: use raw query imports for prompt sources (#682) | ||
|
|
588cdaa152
|
chore: remove pnpm catalog usage (#653) | ||
|
|
3f9226f014
|
ci: release packages (#608)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
4603d8ad6e
|
feat(protocol): extract shared protocol package from agent-core (#612)
* feat(protocol): extract shared protocol package from agent-core - add `@moonshot-ai/protocol` package with REST/WS schemas, envelopes, error codes, event types, and display schemas\n- migrate agent-core `events.ts` and `display/schemas.ts` to re-export from protocol - add centralized `onUnexpectedError` handler for safe emitter listener callbacks - reject forkSession when source session has an active running turn - add protocol schema tests and unexpectedError handler tests |