mirror of
https://github.com/MoonshotAI/kimi-code.git
synced 2026-07-31 20:14:53 +00:00
552 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
f4c3967a41
|
ci: release packages (#2061)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
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
|
||
|
|
ca38b7ed86
|
chore: remove superpowers toolbar tip (#2089) | ||
|
|
e0f2a41769
|
feat(datasource): add wind, imf, gildata, sec_edgar, and sp_data sources (#2029)
Some checks are pending
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / build (push) Waiting to run
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / 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 / Publish native release assets (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
* feat(datasource): add wind, imf, gildata, sec_edgar, and sp_data sources * feat(datasource): strengthen source routing in skill and tool schema * feat(datasource): retry on credential rotation and enforce single-source routing contract * feat(datasource): neutral source selection with objective capability boundaries * feat(datasource): note wind_search_fields field-name mapping in skill and schema |
||
|
|
64f053cf46
|
feat: agent-core-v2 permission/workspace refactors and transcript durability (#2021)
* refactor(agent-core-v2): extract toolApproval domain from permissionGate
- add agent-scoped `toolApproval` domain owning the approval round-trip:
builds approval requests, drives the session/approval broker, publishes
permission.approval.* events, records session approval rules, and
resolves ask continuations
- slim permissionPolicy down to the static risk-adjudication chain; drop
the dynamic `registerPolicy` mechanism
- move harness constraints out of the policy chain into their owning
domains as toolExecutor hooks ordered before 'permission': plan-mode
guard (plan), swarm batch exclusivity and AgentSwarm approve (swarm),
goal-start review (goal), exit-plan review (plan/exitPlanModeReview),
and btw deny (session/btw)
- delete the now-unused policies (deny-all, plan-mode-guard-deny,
plan-mode-tool-approve, goal-start-review-ask, swarm-mode-agent-swarm-
approve, agent-swarm-exclusive-deny)
- update Permission.md, AGENTS.md, and check-domain-layers for the new
domain layout
* feat(kimi-inspect): add App Services view for app-scope service reflection
- add `services` top-level view (`AppServicesView`) on the NavRail, showing
the full-width app-scope Service panel grid; session/agent scopes stay in
the Chat view's Inspector
- extract shared `ServicePanels` from Inspector and add `methodArgs` helper
to build per-method argument editors from channel metadata
- support variadic service calls in `panels.ts` (`call(svc, method, ...args)`)
- update agent-core-dev skill docs for the toolApproval extraction and the
guard/review-off-chain permission design
* refactor(agent-core-v2): restructure workspace domains
- rename workspaceRegistry to workspace and workspaceLocalConfig to
projectLocalConfig
- extract id-spelling resolution into the workspaceAliases domain
(IWorkspaceAliases)
- extract workspace-centric session queries into workspaceSessions
(IWorkspaceSessions)
- update kap-server routes, klient contracts, and related tests to the
new services
* feat(transcript): add op-batch sequencing and point-to-point catch-up
- wire: transcriptSeqSchema with per-agent batch seq watermark on
transcript.reset/ops and the REST transcript response, the
transcript_since subscription cursor, and the GET transcript/ops
catch-up shape; seq stays optional everywhere so legacy peers fall
back to loss-signal-driven refreshes
- wire: drop interactionFrame, interactions live on the interaction
item in the ops stream
- kap-server: TranscriptService assigns consecutive per-agent batch
seqs and retains them in a bounded in-memory journal; the
transcript_since cursor replays journaled batches instead of a
baseline reset, and the baseline reset is now items-empty because
history always pages in over REST
- kimi-inspect: transcript REST/WS clients track the op-batch
watermark and run seq-gap/reconnect catch-up with full-refresh
fallback; add the Transcript audit panel (AuditTrail timeline,
structural diff, state tree) docked right of the chat
- docs: sync AGENTS.md and agent-core-dev skill notes with the new
transcript contract
* feat(transcript): persist plan revisions and task/interaction facts, add user-messages endpoint
- record each ExitPlanMode submission as a versioned plan blob via a reference-only plan.revision op, projected live and cold as a plan.revision marker plus the plan badge (reviewPath, version)
- persist task.started/task.terminated (with a bounded output tail) and interaction.request/interaction.resolved ops, and add foldFacts so a cold transcript rebuilds tasks, interactions, todos and goal/plan/swarm meta from the wire journal
- add GET /sessions/{session_id}/transcript/user-messages returning all turn-opening prompts grouped per agent
* fix(agent-core-v2): anchor external PreToolUse hooks before the permission gate
The toolApproval extraction forces the gate to construct early (planService injects it to anchor plan-guard), so the 'permission' hook registered ahead of 'externalHooks' and a policy ask waited on the approval broker before PreToolUse could block, hanging the turn. Fetch the gate first in registerListeners and register the PreToolUse hook with before: 'permission', falling back to appending when the gate is stubbed without its hook.
* refactor(agent-core-v2): replace ordered onBeforeExecuteTool hook with veto-event pattern
- introduce BeforeToolExecuteEvent with veto/allow/pass/waitUntil statements
- add BeforeToolExecuteEmitter with two-pass fire (immediate then deferred)
- split readiness work into separate onWillExecuteTool participation event
- migrate all domain listeners: permissionGate, plan, goal, swarm, btw,
externalHooks, toolDedupe, mcp
- remove IAgentPermissionGate force-injection for hook ordering
- update docs, tests, and domain-layer check to match
* refactor(agent-core-v2): unify veto payload on ExecutableToolResult
- veto() and waitUntil factories now carry a plain ExecutableToolResult:
isError reads as a denial, anything else as a short-circuit;
the block/reason/syntheticResult weak union is gone
- add denyToolExecution(reason) helper for the common denial shape, and
narrow the fire/authorize return to BeforeExecuteDecision ({ veto } or
{ executionMetadata })
- narrow the policy 'result' resolution to { kind: 'result'; result }
- settle vetoed calls through a single normalize/merge path in the executor
* fix(agent-core-v2): pull up IAgentPermissionGate in agent activation
The permission gate only subscribes `onBeforeExecuteTool` from its
constructor. The veto-event refactor removed the ordering-driven
force-injections that used to pull it up, so without an explicit
resolution tool execution would run without policy adjudication.
* refactor(agent-core-v2): fold systemReminder domain into contextMemory appendTagged
- add `appendTagged(content, tag, origin)` to `IAgentContextMemoryService`,
storing content pure with a `tag` field on `ContextMessage`
- apply the XML tag at projection time in `contextProjector` via the new
`tag.ts` helpers (`wrapTag` / `applyTagToContent`)
- delete the `systemReminder` domain and migrate all call sites
(contextInjector, goal, plugin, prompt, swarm, btw, sessionInit,
toolSelectAnnouncements) to `appendTagged`
- build toolDedupe reminder strings with `wrapTag`
* refactor(klient): merge providers/models/catalog into global.kosong facade
Converge three separate facade namespaces (global.providers,
global.models, global.catalog) into a single global.kosong facade
that exposes two domain concepts: provider (CRUD) and model
(read-only view). Add streaming generate() method for direct
LLM calls through the facade.
- Define ProviderAuth (api-key | oauth), ProviderInput,
AnonymousProviderInput, GenerateInput, GenerateParams,
GenerateEvent as klient-owned public types
- Extend KlientChannel with stream() for AsyncIterable transport
- Add streaming IPC protocol (stream/stream_data/stream_end/
stream_error/stream_cancel frame types)
- Add StreamingProcedureContract, ScopedStreamCaller, and
per-chunk zod validation in the contract layer
- Implement generate via dispatcher special-case routing to
IModelCatalog.getRequester().request()
- Rename events: providers.changed -> kosong.providers.changed,
models.changed -> kosong.models.changed,
catalog.changed -> kosong.changed
- Remove GlobalProvidersFacade, GlobalModelsFacade,
GlobalCatalogFacade, and ModelRecord from public exports
- Update all tests, examples, and README
BREAKING CHANGE: global.providers, global.models, and
global.catalog replaced by global.kosong; event names changed;
ModelRecord no longer exported.
* feat(transcript,kimi-inspect): add tag field to text frames and improve session creation
transcript:
- add optional `tag` field to TextFrame, textFrameSchema, and HistoryMessage
- propagate tag through contextTranscript MutableMessage
kimi-inspect:
- render tagged frames with violet badge and distinct styling in ChatView
- skip cwd prompt for workspace-based session creation in Sidebar
- auto-bind default model on new sessions via resolveDefaultModel
* refactor(transcript): rename wire/ directory to contract/
The transcript package's REST/WS schemas and event types lived in
src/wire/, which collided with the engine's persisted wire.jsonl
record vocabulary. Rename it to src/contract/ so "wire" unambiguously
refers to wire.jsonl records (foldWireRecordFacts, HistoryWireRecord
stay unchanged).
- rename src/wire/{schema,events}.ts to src/contract/
- update index exports and test imports accordingly
- reword comments: "wire shape" -> "contract shape", "on the wire" ->
"in ops" / "in transit" / "on the WS channel" / "transcript API"
- events.ts: "transcript frame" -> "transcript event" for WS envelope
messages, avoiding confusion with TranscriptFrame
- kap-server tests: TranscriptWire/TurnWire/FrameWire/OpsCatchupWire/
UserMessagesWire -> *Contract
- update AGENTS.md references
* refactor(transcript): rename wire/ directory to contract/
The transcript package's REST/WS schemas and event types lived in
src/wire/, which collided with the engine's persisted wire.jsonl
record vocabulary. Rename it to src/contract/ so "wire" unambiguously
refers to wire.jsonl records (foldWireRecordFacts, HistoryWireRecord
stay unchanged).
- rename src/wire/{schema,events}.ts to src/contract/
- update index exports and test imports accordingly
- reword comments: "wire shape" -> "contract shape", "on the wire" ->
"in ops" / "in transit" / "on the WS channel" / "transcript API"
- kap-server tests: TranscriptWire/TurnWire/FrameWire/OpsCatchupWire/
UserMessagesWire -> *Contract
- update AGENTS.md references
* Revert "refactor(agent-core-v2): fold systemReminder domain into contextMemory appendTagged"
This reverts commit 55afaa3d96f729c4f73a71f1fbd23d3f6087453b.
Restore the systemReminder domain: reminders go back to being baked
into message text at write time, and ContextMessage loses the `tag`
field (projection-time wrapping is removed with it).
* feat(transcript): add wire-equivalent detail, dedupe session events
- transcript: add step usage/timing/retry, turn durationMs/error/usage,
tool inputText/progress, task resultSummary/error, meta.agent status,
a global prompts entity, and the 'hook' marker
- kap-server: project the new fields in coreEventMap and suppress
transcript-projected session events on connections subscribed to the
transcript protocol (live fan-out and cursor replay)
- kimi-inspect: mechanical type sync for the new snapshot prompts field
* fix(klient): resolve lint errors in ipc channel stream and e2e matrix test
|
||
|
|
c6291c3ad7
|
feat(v2-print): align kimi -p run lifecycle with the default engine (#2017)
* feat(v2-print): align kimi -p run lifecycle with the default engine (13 files) - add applyPrintModeConfigDefaults in agent-core-v2: fill print-mode config defaults (bash task timeout / max steps per turn / subagent timeout all unbounded) into the memory layer, respecting user-set keys - applyPrintBackgroundPolicy: keep the run alive while cron tasks have future fires so their steered turns can run, with an anti-spin guard for wedged ticks; goal/cron waiting shares the steer ceiling budget - default print background mode changed from exit to steer - add task.bashTaskTimeoutS config key and wire it into BashTool's detachTimeoutMs - v2 print runner now forwards turn.step.retrying events to writeRetrying - allow subagent timeoutMs = 0 (no timeout) * test(agent-core-v2): remove duplicate loop config imports in config test |
||
|
|
8bf5bacba9
|
ci: release packages (#1989)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
4c763f6763
|
feat: send prompt-attached videos directly with the prompt (#1999)
Some checks are pending
CI / lint (push) Waiting to run
CI / build (push) Waiting to run
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / typecheck (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Release / Native release artifact (push) Blocked by required conditions
Release / Release (push) Waiting to run
CI / test-windows (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
Release / Deploy docs (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
* feat: send prompt-attached videos directly with the prompt
Videos attached to a prompt (pasted in the TUI, uploaded in the web UI)
previously reached the model only after it opened the file with
ReadMediaFile — an extra tool round trip that could leave the video
unseen when the model never made that call. They are now uploaded
through the model provider's file channel and embedded directly in the
user message as the provider-issued reference; ReadMediaFile stays as
the fallback and as the model's own way to open video files.
- agent-core: new uploadVideo agent RPC and Session.uploadVideo in the
SDK; the TUI uploads pasted videos at submit time, falling back to
the file-tag form on failure
- kap-server: inline file-source video prompt parts at the REST edge
and map provider file ids back to local uploads behind
GET /files/llm/{llm_id}
- kimi-web: play provider-referenced prompt videos after reload/resume
* fix: fall back to inline video when the upload channel fails
ReadMediaFile only used the provider's video upload channel when one
was bound, and surfaced a hard tool error when the upload itself
failed — on providers without a files endpoint (or a transient upload
failure) the model was told the video could not be read at all. Now a
missing or failing upload falls back to delivering the video inline
(base64), the same shape providers without an upload channel already
get. Both engines (agent-core and agent-core-v2) are fixed.
* test: cover prompt video edge cases and failure paths
Stress coverage for the prompt video pipeline:
- agent-core uploadVideo RPC: extension/magic classification
(.txt with video bytes accepted, extension trusted when magic is
absent), exact 100MB boundary, directory and nonexistent paths
- TUI: mixed per-video outcomes (one inlined, one tag fallback),
submission order behind an in-flight upload, queued video messages
carrying final uploaded parts
- kap-server: per-video provider-id mappings, Range requests through
the llm redirect, mapping persistence across a server restart
* fix: surface auth rejections from the video upload channel
The base64 fallback for a failing video upload must not mask auth
rejections: a 401/403 (surfaced as provider.auth_error) drives the
credential force-refresh and a clear auth error, while an inline
payload would just be rejected again by the next request. Only a
missing or broken upload channel (no files endpoint, network/server
errors) falls back to inline delivery.
* fix: keep the by-design no-hook video error from degrading to inline
Main's contract for a provider with no video upload hook is an honest
"does not support video upload" tool error — an inline payload would
be dropped on that protocol's wire anyway. The base64 fallback now only
applies to an upload channel that exists but failed at runtime. The
no-hook throw gets a stable type (VideoUploadUnsupportedError) so the
two cases are told apart without matching message text.
* fix: constrain the llm video route param to a safe alphabet
The provider file id is used as a blob-store key, and the node-fs
backend joins scope and key into a storage path. An id containing an
encoded path separator (%2F) could address a different storage path
than the intended llm-video mapping; the route now only accepts the
provider-id alphabet.
* style(agent-core-v2): move added explanations into top-of-file comment blocks
The package's comment convention keeps comments solely in the top-of-file
block; relocate the new notes (url-source id pairing, video delivery
fallback, VideoUploadUnsupportedError) from functions and schema fields
into their module headers.
* fix: reject prompt video uploads when the model lacks video input
The uploadVideo RPC only checked the provider's upload channel, so an
SDK caller on a text-only or unknown-capability model could obtain a
valid-looking video_url part the current model is not supposed to
accept. The TUI capability guard does not cover this public path, so
the agent now gates on video_in itself.
* fix: sniff uploaded video bytes before inlining them
The inline branch trusted the upload-time content type; now the bytes
are sniffed first, and anything magic-confirmed as a non-video kind
(e.g. an image mislabeled as video/mp4) falls back to the file-tag
form instead of being uploaded. Like the image gate, bytes are
authoritative where the container format allows it — an MPEG-PS
lookalike still rides the extension, matching ReadMediaFile.
* test: keep the generation stub pending until the abort lands
An immediately-answered 404 ends the turn (non-retryable) before the
test's abort call, racing the cleanup into a 409; the stub now hangs
generation until the abort cancels it.
* fix: validate prompt file references before mutating session controls
A stale file_id failed inside media resolution — after the model,
thinking and permission overrides had already been applied — so a
rejected prompt still changed the session's controls. File references
are now checked up front, keeping failed submits side-effect free.
* fix: serialize prompt submissions per session
A slow provider video upload let a later text-only request reach the
queue ahead of an earlier video one, silently reordering the
conversation for REST clients and multiple tabs. Submissions to the
same session now chain, matching the ordering the TUI already
guarantees locally.
* fix: play reloaded provider videos through the authenticated fetch path
A video recovered from an ms:// reference carried only the bare redirect
URL, which 401s under daemon auth when loaded natively. The attachment
now keeps the provider file id (llmFileId) end to end, and AuthMedia
fetches the bytes with the Bearer credential through the daemon's llm
redirect — the same blob-URL path uploaded files already use.
* fix: fence pending video submits against session and model switches
A slow paste-upload left the TUI idle, so /new, the session picker or
/model could fire mid-upload; the continuation then dispatched the old
session's provider reference into the newly selected session or a
model that cannot resolve it. The dispatch now re-checks that the
session and model are unchanged and asks for a resend instead.
* fix: preserve the caller's video path verbatim in uploadVideo
Trimming the path changed the filesystem target before validation and
upload, so a name that legitimately starts or ends with whitespace
resolved to the wrong file; the trim is now only the emptiness check.
* fix: forward provider-issued ids on image URL prompt parts too
The shared url-source schema accepts id for image and video parts, but
only the video path forwarded it, dropping provider-keyed image ids
between prompt acceptance and the model request.
* fix(web): reconcile inlined video echoes into the optimistic user message
The loose user-message matcher counted media parts and <video path>
tags but not the [video:ms://…] text shape, so a racing server echo of
an inlined upload slipped through as a duplicate user bubble.
* fix: queue bash submits behind a pending video upload
A bash-mode submit could start while a pasted video was still
uploading, recording shell context before the earlier prompt was
dispatched and reordering user actions; it now chains behind the
upload like normal submits.
* test: cast the driver through unknown for the session-switch fence test
* fix: validate prompt file references before resolving the prompt agent
A stale file_id posted to a fresh or cold session materialized the main
agent (registering it in session metadata and igniting agent-scoped
services) before the request was rejected. The file check now runs
first, so failed submits create nothing and mutate nothing.
* fix: key the playback mapping by the id embedded in the reference URL
Projections and clients read the provider id from the ms:// URL, not
the id field, so an upload that returns an id-less or mismatched
reference would inline fine but 404 on playback. The mapping now
derives its key from the URL, falling back to the explicit id.
* fix: sanitize provider video ids on the write side of the playback map
The read route got the safe-alphabet guard, but recordLlmVideoRef still
used the provider-returned id verbatim as a blob-store key; a crafted
provider response could write the mapping outside the llm-video
namespace. Out-of-alphabet ids are now dropped on both put and get.
* fix(web): keep recovered provider videos resendable through the edit path
The composer reload path only honored fileId and fell back to a
bare fetch(url) without the Bearer token, so editing a reloaded
provider-video turn dropped the chip after a 401. llmFileId is now
threaded through and the bytes are re-uploaded via the authenticated
llm redirect.
* fix: fall back to inline video for no-hook providers whose wire carries it
The by-design no-hook error is only the honest answer when the wire
would drop an inline payload anyway (the OpenAI family). Protocols
that convert video_url (kimi, anthropic, google-genai, vertex) now
take the base64 fallback instead of failing every video read; the
registrar computes the flag from the model's protocol.
* test: satisfy the full IBlobStore shape in the playback-map stub
The tsgo typecheck job rejects a structural stub missing _serviceBrand
and list even though plain tsc accepted it.
* fix: queue prompt-producing slash commands behind pending uploads
Skill activations and plugin commands started their turn immediately
while a pasted video was still uploading, so the earlier video prompt
queued behind them and user actions ran out of order. Both paths now
chain behind inputSubmitChain (and re-check session/model at dispatch)
like normal and bash submits.
* fix: validate media kinds in the prompt file-reference preflight
The preflight only proved a referenced file exists; a real upload used
with the wrong kind (e.g. a PDF submitted as video) still passed it and
mutated session controls before assertMediaFile rejected the request.
The kind assertion now runs up front with the existence check.
* fix(web): play sent and recovered videos in the file preview
The media preview returned early for every kind except image, so a
user-turn video chip's play action was a no-op even with llmFileId
threaded through. The preview now handles video: bytes come from the
authenticated file/llm fetch into a blob URL and render in a native
player.
* fix(web): preview recovered videos with the authenticated blob URL
The llm re-upload branch fetched bytes with auth but kept the protected
redirect URL as the chip preview, which 401s as a native video src; the
fetched blob now becomes the preview URL, mirroring the fileId branch.
* style(agent-core-v2): move the inline-fallback note into the module header
Same package comment convention as before: rationale lives in the
top-of-file block, not beside the registration call.
* fix: fence delayed bash submits to the originating session
The chained bash callback ran runShellCommandFromInput against whatever
session was active at dispatch time, so a command submitted in session
A could execute in session B's workspace and be recorded there after a
mid-upload switch. The originating session is now captured at submit
and re-verified at dispatch, like the prompt and skill paths.
* fix: emit prompt video telemetry from the agent scope
video_upload is an agent-level event requiring ambient agent identity,
but the uploader was built with the Core-scoped session view, leaving
prompt-upload events unattributable. The route now resolves telemetry
from the target agent for the uploader while image compression keeps
the session-scoped view.
* fix: preserve provider image ids through legacy projections and web mappers
The url-source id accepted by the prompt schema was dropped again by
the legacy message projection and the web wire mapper, so provider-
keyed image references lost their id across messages, snapshots, and
undo responses. It now flows through both directions.
* fix(web): revoke recovered video blob URLs before dropping attachments
A failed llm re-upload removed the attachment without revoking the
freshly created preview blob URL, pinning the whole video in the
browser blob store until page unload on every failed edit attempt.
* fix: serialize foreground slash commands behind pending uploads
/compact and /init started their turn while a pasted video was still
uploading, so the earlier message landed after them — and compaction
summarized the context without it. Prompt-producing builtin commands
now share the same queueBehindPendingUploads chain (with the
session/model dispatch fence) as skill, plugin, and bash submits.
* fix: defer session controls until media preparation succeeds
Media resolution now runs before any profile/model/thinking/permission/
denylist mutation, with the uploader resolved transiently from the
requested (or currently bound) model — a failed submission leaves the
session's controls untouched. A concurrent model switch during
preparation is rejected with session.busy instead of enqueueing a
reference uploaded for the previous model.
* chore: bump the new SDK video upload API as a minor release
Session.uploadVideo is new public API surface, not a patch-level tweak.
* fix: re-check busy state before draining upload-queued commands
A slash command deferred behind a video upload ran the moment the video
prompt dispatched, landing on an already-running turn: beginSessionRequest
wiped the active turn's live pane, and /init or /compact started on top
of it. The deferred callbacks for skills, plugin commands, /compact and
/init now re-run the resolver's busy check at dispatch and show the same
blocked message the user would get when typing while streaming.
* fix: resolve profile-bound models before choosing the uploader
A first prompt carrying "profile" without "model" resolved the upload
model from the still-unbound alias, so no uploader was installed and
every attached video fell back to a tool-read tag even when the
configured default model supports provider upload. The transient
resolution now mirrors AgentProfileService.bind: an explicit body model
wins, a profile bind falls back to the configured default model, and
only otherwise does the currently bound alias apply.
* refactor: resolve prompt videos at request time inside the engine
Move prompt-video delivery out of the submission edge: the TUI submits
synchronously with a local file:// part the v1 turn resolves before the
message enters history, and kap-server carries an internal kimi-file://
reference the v2 requester resolves against the effective model with an
app-scoped upload cache. History keeps the durable local file id, the
/messages projection emits structured video parts, and the web plays
videos back through the authenticated /files channel - deleting the
submit fences, per-session serialization, provider-id reverse mapping,
redirect endpoint, and the unreleased SDK upload API.
* fix: propagate abort through video upload delivery instead of degrading
A turn cancelled mid-upload used to be treated as an ordinary upload
failure: v1 fell back to an inline base64 part and appended the degraded
message to history, and the v2 resolver memoized the tag fallback for the
rest of the agent's lifetime. Both catch sites now check the delivery
signal itself - abort rejections vary in shape by provider - and re-throw
so cancellation ends the turn (v1, classified as cancelled via the abort
reason) or the request (v2, not memoized, so the next turn uploads).
* fix: keep the tag form for no-upload providers whose wire drops inline video
An OpenAI-family model configured with video_in but no provider upload
channel used to receive prompt videos as an inline base64 part - which
chat completions rejects and the Responses adapter degrades to an
omitted-video placeholder, persisting ~4/3x the file size in history for
bytes the model never sees. The prompt path now mirrors the v2 resolver's
protocol gate and degrades to the <video path> tag instead; ReadMediaFile's
own delivery is unchanged. Also merges the prompt-video changesets into a
single user-facing entry.
* fix: escape the NUL separator in the video upload cache key
The cache-key template literal contained a literal NUL byte instead of
the \0 escape, which made Git classify the whole source file as binary
- no inline diffs, unreliable text tooling. The escape produces the
byte-identical runtime string, so hashed cache keys are unchanged.
* fix: check the abort signal before the inline video fallback
The no-uploader inline path (and the post-upload-failure fall-through)
never consulted the delivery signal, so cancelling a turn while the video
bytes were being read still base64-encoded the file and appended the
degraded message to history. The inline branch now re-throws the abort
reason first, matching the upload catch.
* fix: retry transient prompt video upload failures on later steps
A generic upload failure used to memoize its tag fallback for the rest of
the agent's lifetime, freezing a transient files-endpoint error into a
permanently degraded video. The resolver now marks failure-born fallbacks
as non-memoizable: the current request keeps the lightweight tag form and
the next step retries the upload. Structural outcomes (successful uploads,
capability and sniff fallbacks, no-hook inline) stay memoized for
step-retry stability.
|
||
|
|
430cd382a8
|
refactor(agent-core-v2): drop pass-through methods from AgentRPCService (#2042)
- trim AgentRPCService/AgentAPI to the 10 methods with real logic (prompt, steer, cancel, undoHistory, setPermission, cancelCompaction, activateSkill, activatePluginCommand, getContext, getTools) - route the klient agent facade to the domain services directly (shellCommand, profile, usage, plan, task) with new wire contracts - keep the test harness ctx.rpc surface unchanged via passthrough adapters - rewire kap-server rpc tests and the kimi-inspect RPC panel |
||
|
|
b5efba7abc
|
fix: consume the model metadata declared by the models.dev catalog (#2015)
* fix: stop advertising Claude thinking efforts for non-Claude models Models served over the Anthropic protocol whose names carry no Claude marker (e.g. a catalog-imported Kimi K3) no longer inherit the latest Opus effort list, so the model selector stops offering levels the model does not accept. The models.dev catalog import now also parses reasoning_options and records the declared effort levels on the model alias, so K3 offers its real levels (low / high / max). * fix: consume deprecated, override, and input-limit metadata from the models.dev catalog - Models declared status=deprecated in the catalog are no longer offered for import. - Per-model provider overrides on gateway providers (an npm package targeting an Anthropic SDK plus a usable endpoint) now land as alias protocol and base_url, so those models are served over the right protocol and endpoint; overrides without a usable URL are skipped. - A declared limit.input now sizes the context budget instead of the larger total context window (e.g. gpt-5: 272k instead of 400k). The model alias schema gains an optional base_url field (not accepted in overrides) that Anthropic wire resolution prefers over the provider-level base URL. * fix: honor thinking-disable semantics and the OpenAI-compatible fallback in catalog imports - reasoning_options 'none' is the model's off encoding: off_effort flows from the catalog through the model alias to the OpenAI wire providers, so turning thinking off sends 'none' instead of omitting the effort field; models with effort levels but no way to disable thinking are imported as always_thinking and no longer offer an Off option. - Bare Claude family aliases (e.g. sonnet-latest) recover the inferred Anthropic effort profile; v2 comment conventions restored. - Providers whose SDK the catalog does not type now fall back to the OpenAI-compatible wire (with a visible "guessed" note) instead of being refused; imports lacking a usable endpoint ask for one (--base-url on the CLI, a prompt in the TUI). Proprietary SDKs (Amazon Bedrock), unrecognized explicit types, and env-placeholder URLs are refused with a clear reason. * fix: align catalog imports with the reference models.dev consumer - A JSON null tier in declared effort values is now read as the 'none' off-encoding (previously such models were wrongly imported as always-thinking with no way to turn reasoning off). - Alpha-status models are filtered out alongside deprecated ones. - Models whose per-model provider override targets a wire that cannot be expressed per-model (e.g. Claude on google-vertex, whose wire here is Gemini-mode Vertex, or gpt entries on an Anthropic provider) are skipped instead of being imported under the silently wrong protocol. - interleaved: true no longer pins reasoning_content: the provider's default three-field scan is wider and the pinned key only narrowed reasoning parsing for gateways answering with another field name. * fix: require endpoints for Anthropic-compatible catalog imports and honor --base-url - catalogProviderNeedsBaseUrl now covers the Anthropic wire: a non-official Anthropic-compatible vendor without a concrete catalog endpoint (e.g. google-vertex-anthropic) must supply --base-url / the TUI prompt instead of silently falling back to the default Anthropic endpoint. - --base-url now takes precedence over the catalog-declared endpoint, and an empty --base-url is rejected instead of persisting a blank endpoint. * fix: enforce always-on thinking on every wire and refuse Cohere at import A model that declares always_thinking (e.g. a catalog-imported gpt-5) no longer resolves to a dishonest off state via thinking.enabled=false or an SDK/ACP off request: resolution clamps to the model's default effort on every wire instead of letting upstream keep reasoning while the UI reports Off. The Anthropic warn-and-send path for unlisted effort levels is unchanged. Cohere's proprietary SDK joins Amazon Bedrock on the import-refusal list instead of being guessed as OpenAI-compatible. * fix: harden catalog import edge cases - An explicit but unrecognized catalog type is now refused before npm/id inference, so a future catalog protocol is never silently miswired through the OpenAI fallback. - User-supplied --base-url values for Anthropic-wire providers get the same trailing-/v1 normalization as catalog endpoints, avoiding /v1/v1/messages requests. - The TUI import prompt rejects env-placeholder base URLs like the CLI does. * fix: await the floating assertion promise in the catalog add CLI test * refactor: unify catalog import resolution into a single decision function Wire-type inference, the OpenAI-compatible fallback, proprietary-SDK refusal, endpoint adaptation, and the base-URL requirement are now produced together by resolveCatalogImport, one pure resolver consumed by both the CLI and the TUI — replacing the cooperating predicates (inferWireType, isGuessedWireType, catalogProviderNeedsBaseUrl) whose permutations kept producing edge cases. No behavior change. * fix: close configured-off clamp hole, keep inferWireType compat, carry same-wire override endpoints - A configured thinking.effort = "off" no longer bypasses the always-on clamp: it is treated as absent and the model default applies, mirrored on both engines. - The previously public inferWireType stays as a deprecated compatibility wrapper over resolveCatalogImport so existing SDK consumers do not break on a patch release. - Catalog model overrides that stay on the provider's wire but declare their own endpoint now persist it on the alias (and the v1 OpenAI wire branches honor alias-level base URLs like the Anthropic branch). * fix: split total window from input cap and close override/endpoint gaps - max_context_tokens once again means the total context window (used by completion budgeting); a model's declared input limit is tracked as max_input_tokens, which compaction, context-splice and usage-ratio checks prefer — fixing the over-clamping introduced when the input cap was stored as the context budget. - A catalog endpoint declared only as an env placeholder now always produces needs-base-url (official SDK included), so credentials are never sent to the public vendor host by default. - api-only per-model overrides are honored as same-wire endpoint changes; overrides targeting another known but inexpressible wire (e.g. google-genai on an OpenAI gateway) are skipped; same-wire models whose declared endpoint is an unusable placeholder are skipped instead of silently rerouted. * style: drop a function-level comment from the v2 thinking resolver * chore: consolidate the PR's changesets into two user-facing entries |
||
|
|
154e082488
|
fix(web): keep transparent images readable over a checkerboard canvas (#2022)
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 / Native release artifact (push) Blocked by required conditions
Release / Release (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
White-on-transparent images disappeared on light surfaces and black-on-transparent ones on dark surfaces (markdown inline images, tool result media, and the file preview's large view). Add a shared --media-alpha-canvas token — a checkerboard of two mid-gray squares mixed from --color-bg/--color-text, each >=3:1 against both white and black — and paint it directly on <img> so opaque images stay pixel-identical and only transparent pixels reveal the canvas. Also let check-style's no-gradient-text skip custom-property definitions (a token is never rendered text), and register the new tokens in the design system view. |
||
|
|
576d650380
|
feat(cli): add third-party source note to update prompt (#2014)
* feat(cli): add third-party source note to update prompt * fix(cli): adjust third-party source note wording * refactor(cli): move official install URL into app constants * chore: simplify changeset wording * chore: adjust changeset wording |
||
|
|
e45832398d
|
fix(tui): keep long sessions responsive and bound resumed history (#1976)
* fix(pi-tui): reuse processed lines across frames in the renderer Each frame previously re-truncated, re-normalized, and re-compared every transcript line, so steady-state frames (spinner ticks, streaming flushes) cost O(total lines x chars) and pegged one core in long sessions. Keep the previous frame's raw lines, processed output, and per-line kitty image ids; a line whose raw string reference is unchanged reuses its processed output verbatim, and image-id consumers read the cache instead of re-scanning text. * fix(tui): stop tree-wide transcript invalidation on structural updates Grouping a second Read/Agent call, removing swarm progress, finalizing an MCP status row, replay tool-call removal, and /undo each invalidated the entire transcript tree, forcing every mounted message to re-render (markdown lexing + code highlighting) on the next frame. The container's render cache already validates per child by reference, so structural child-list changes are picked up without a tree-wide invalidate; reserve it for global style changes such as theme switches. * fix(tui): fold older assistant messages into the turn step summary Step merging only collapsed thinking/tool steps, so assistant text blocks accumulated without bound inside a turn (hundreds of markdown components in a single long turn, all re-processed every frame). A running turn now keeps its last 20 assistant messages (KIMI_CODE_TUI_KEEP_RECENT_ASSISTANT), and a finished turn folds down to its conclusion tail of 2 (KIMI_CODE_TUI_KEEP_RECENT_ASSISTANT_COMPLETED); older ones collapse into the step summary line with a message count. Entries are kept, so expand behavior is unchanged. * fix(session): bound resumed history to the most recent user turns Resume used to return every agent's full replay over the RPC boundary (a long session can reach ~100MB, serialized and parsed several times on an in-process call), while the TUI only renders the last 10 user turns. The resume payload now accepts an optional replayTurnLimit, the turn-boundary predicate moves into agent-core as the single source of truth (limitAgentReplayByTurns, re-exported through the SDK), and the CLI passes its existing 10-turn limit so resume transfers just the tail. * fix(session): count goal continuation rounds as replay turns Replay turn boundaries only matched real user input, so a 100-round goal (a handful of user prompts plus 100 system-trigger continuations) fell entirely inside the 10-turn replay window and resumed by rendering the whole run from the start. The goal driver already fires one synthetic prompt per goal turn and counts those as turns itself, so replay trimming now treats goal_continuation prompts as turn boundaries and keeps the most recent 10 rounds. The continuation prompt is model-facing and hidden live; replay no longer renders it as a user bubble either, while still advancing the replay turn so each round groups separately. * fix(tui): keep replay turn folding when goal continuations are hidden Suppressing goal continuation bubbles removed every turn-boundary component from goal-session replays, so mergeAllTurnSteps found no turn edges and skipped step/assistant folding entirely — a single oversized goal round still mounted all of its tool cards and assistant messages. Mount an invisible ReplayTurnBoundaryComponent for each hidden continuation: it renders zero lines but keeps the turn edges discoverable to folding and window trimming, matching replay trimming's per-round turn semantics. * chore: consolidate and simplify changesets |
||
|
|
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>
|
||
|
|
beeb964393
|
fix(vscode): reduce webview streaming re-render churn (#1994)
Chat components subscribed to the entire chat store, so every streaming delta re-rendered every assistant message. Subscribe to narrow store slices and memoize ChatMessage so settled messages no longer re-render on each delta. Cap getImageDataUri at 10MB, matching the media picker, so oversized local images are not inlined into the webview DOM. |
||
|
|
6dd4fd3368
|
refactor(agent-core-v2): rebuild the model wire layer on the kosong architecture (#1970)
* refactor(v2): land kosong contract layer (L0 wire contract) * refactor(v2): land kosong protocol layer (L1 traits and base registry) * refactor(v2): land kosong provider layer (bases, trait composers, kimi definition) * refactor(v2): land kosong model and catalog layers * refactor(v2): migrate engine callers to kosong, drop old llmProtocol layer * test(v2): migrate agent-core-v2 tests and harness to kosong * refactor: sync peripheral packages to kosong architecture * refactor(v2): replace provider dialects with per-protocol definitions * refactor(v2): merge the vertexai protocol into google-genai via providerOptions * refactor(v2): remove vendor-name gates outside the kosong layer * feat(v2): add model resolution inspection and connectivity ping * refactor(v2): remove the unused platform config layer * test(klient): pin invalid-input behavior across providers in e2e * refactor(agent-core-v2): merge kimi traits, split bases by protocol - merge the seven kimi trait modules into kimi.contrib.ts as two trait objects: kimiOpenAITrait (all native-transport hooks) and kimiAnthropicTrait (thinking only) - move bases/* implementations into per-protocol directories (openai/, anthropic/, google-genai/) and rename openai.contrib.ts to openai-legacy.contrib.ts - add per-directory index.ts registration barrels (import = registration) and exempt them in check-domain-layers.mjs alongside *.contrib.ts * refactor(agent-core-v2): reorganize model and request-layer types - consolidate shared model types (ModelOverrides, CompletionBudgetConfig/Params, ResolvedModelAuthMaterial, ThinkingDefaults/ModelThinkingMetadata) into kosong/model/model.types.ts and drop modelOverrides.ts - rename L2 request types to the ModelRequest* prefix: LLMEvent -> ModelRequestEvent, LLMRequestInput -> ModelRequestInput, LLMCallParams -> ModelRequestParams - extract ModelRequestTiming to replace three duplicated copies of the stream-timing shape - rename L3 llmRequester types with the Agent prefix to match IAgentLLMRequesterService (AgentLLMRequestOverrides/Finish/Task/Source/ PartHandler/LogFields) - delete the unused LLMRequestParams type * refactor(agent-core-v2): fold kosong/catalog into kosong/model - merge IModelCatalogService's enumeration surface (listModels / listProviders / getProvider / setDefaultModel and the wire shapes) into IModelCatalog; delete kosong/catalog/modelCatalog.ts - move the remote refresh path to the new IProviderDiscoveryService (discovery.ts + discoveryService.ts, renamed from catalog/modelCatalogService.ts) - relocate configSection / errors to discoveryConfigSection.ts / errors.ts; DEFAULT_MODEL_SECTION now lives in kosong/model/model.ts - drop the L3 catalog layer from check-domain-layers.mjs - kap-server routes / refresh scheduler / channelRegistry follow the split; klient renames the contract modelCatalogService to modelResolver and adds providerDiscovery; kimi-inspect reads via IModelCatalog - modelRequesterImpl: drop the streamedAnyPart backfill, onMessagePart already delivers every part - tests: remove the app/modelCatalog and kosong/catalog suites, add the kosong/model catalog and discovery suites * feat(klient): trim trailing undefined args and add boundary smoke probes - add trimTrailingUndefined helper so optional trailing args no longer cross the wire as null in http/ipc transports, which defeated server-side default parameters - add model-requester-boundary smoke probe for ChatProvider error wrapping behavior against real config and a local stub - add kimi-select-tools smoke probe verifying the kimi-only wire encoding of dynamic tool declarations - extend smoke.ts with a models set/get/delete round-trip, catalog list assertions, and update AGENTS.md with the new scripts * fix(agent-core-v2): declare openai chat hooks as function properties Method-shorthand members on OpenAIChatCompletionsHooks tripped typescript-eslint(unbound-method) at every extraction site (`const hook = this._hooks?.convertMessage` and friends), failing the repo-wide lint job. Every implementation is a plain closure composed by openaiHooks.ts, so declare the members as function-typed properties, which matches the actual semantics and clears the four errors. * fix: repair stale references surfaced by the origin/main rebase - agent-core-v2: point vacuousContent's ContentPart import at kosong/contract - kap-server: rewrite the transcript test seed as IModelCatalog (IModelResolver is gone) - klient: inline onceEvent/waitFor after the http transport helpers were dropped - kimi-inspect: remove useLiveEvent from ModelCatalogView; catalog polls on a slow interval * chore: downgrade the kosong architecture changeset to patch |
||
|
|
73eb5f89e0
|
fix(tui): remove red coloring from code syntax highlighting (#1995) | ||
|
|
115b0968ce
|
fix(tui): hide system-trigger messages in resume replay (#1990)
Goal mode stores its per-turn continuation prompt as a user message with a system_trigger origin. Live rendering never shows these model-facing messages, but resume replay only filtered three specific system_trigger names, so the continuation prompt leaked into the transcript as a user message. Skip all system_trigger user messages during replay, matching the live path and the markdown exporter, and drop the two goal-specific filters this makes redundant. |
||
|
|
efacf0452d
|
ci: release packages (#1946)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
ad8cc85251
|
feat(cli): foreground-only web servers, deprecated kimi server kill (#1967)
- the /web slash command now always starts a new server instead of offering to reuse a running one - remove the kimi web kill and kimi web ps subcommands; foreground servers stop with Ctrl+C - keep kimi server kill as a deprecated fallback that only stops servers started by a version before 0.28.0 (recorded in the legacy server lock) |
||
|
|
dde92fe5ab
|
feat: support max and exact version targeting for tips banner (#1960)
* feat: support max and exact version targeting for tips banner Add optional banner_max_version (exclusive upper bound) and banner_version (exact match) fields to the remote tips banner schema. They combine with banner_min_version (all must pass) and apply to both the active banner and fallback list entries. Invalid semver constraints fail closed and hide the banner. * chore: drop changeset for banner version targeting |
||
|
|
bcee3ac542
|
chore(vscode): release 0.6.4 (#1958) | ||
|
|
9223a37622
|
feat(vscode): scope thinking effort to the current session (#1951) | ||
|
|
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
|
||
|
|
a05228c671
|
ci: release packages (#1868)
Some checks are pending
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
CI / build (push) Waiting to run
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-windows (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 / Release (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
d71bf9e5a5
|
feat(web): add a cache invalidation note to the model switcher (#1940)
* feat(web): add a cache invalidation note to the model switcher * feat(web): show the cache note in the mobile settings sheet |
||
|
|
11c1683a1c
|
feat: scope thinking effort to the current session (#1933)
* feat: scope thinking effort to the current session Selecting a model or thinking mode in the TUI or web UI no longer persists the concrete effort to the config; only the boolean thinking toggle is saved. The web UI now restores and submits each session's own daemon-reported level instead of a browser-wide per-model pick, whose localStorage store is removed. * feat: persist bounded thinking efforts and migrate persisted max once Only low/medium/high/xhigh are written to the config on a pick; max and unrecognized levels stay session-only with just the boolean toggle saved. A one-shot migration rewrites a previously persisted thinking.effort max to high (recorded in migrations.json, never re-run). The web UI brings back the per-model localStorage pick as the seed for new sessions, while a session's own daemon-reported level keeps winning for existing ones. * feat: gate effort persistence on the model top declared level The session-only tier is now the last entry of the model's own support_efforts (ordered by strength) instead of a fixed name list, so custom provider-declared levels get the same treatment; anything below the top persists as before, and unknown model metadata keeps the concrete effort. * docs: align changeset wording with the top-tier persistence rule * refactor: rename the config migration marker file to migrations-effort.json * feat: drop the legacy global thinking pick fallback in the web UI A raw single-level string left in localStorage by older versions was migrated into a '*' fallback entry applied to every model; stale values (typically max) could silently steer any session. Non-map content is now discarded instead of inherited. * feat: drop the web per-model thinking pick store entirely Thinking in the web UI is now sourced only from the daemon: a session's own reported level wins when the model declares it, and everything else falls back to the model's catalog default. The stale localStorage key is cleaned up on startup. * feat: skip the effort write when the picker confirms its initial value Re-confirming the effort shown when the model/effort picker opened is not an explicit choice: the TUI persists only the model (no effort key, or no write at all when nothing changed), and the web skips the global config write the same way it already did for model switches. * revert: keep the web global thinking write on re-confirm for now Only the TUI skips the effort write when the picker confirms its initial value; the web behavior stays unchanged until the interaction is reconsidered. * fix: carry the draft thinking pick into a newly created session A level picked on the empty composer lived only in rawState.thinking, so selectSession's watcher overwrote it with the catalog default and the first prompt/skill submitted that instead of the pick. createDraftSession now captures the draft level and seeds the new session's own entry. * docs: simplify the changeset wording * fix: close the remaining top-tier persistence and draft-capture gaps The provider-add default-model flow now resolves support_efforts through effectiveModelForHost (overrides + protocol-profile inference), so a top-tier pick on catalog models without declared efforts no longer persists. The draft thinking level is captured before the session creation awaits, so a concurrent session switch can no longer seed the new session with another session's effort. * fix: wait for the session status fold before resolving prompt thinking In the cold window right after a reload or session switch, the session's own level has not landed from /status yet; resolving straight to the catalog default would carry the wrong level to the daemon, which writes it into the session profile. Send, steer, side-chat and skill-activation paths now await the fold when the session entry is missing. |
||
|
|
a41a09c33c
|
feat(cli): replace the kimi server command tree with kimi web and share one home across servers (#1826)
Some checks are pending
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / build (push) Waiting to run
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / test (3) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
Release / Release (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
* feat(kap-server): enable multi-server shared home by default - always register kap-server instances under server/instances and drop the legacy single-instance lock (acquireLock/getLiveLock/ServerLockedError) - remove the multi_server experimental flag and its KIMI_CODE_EXPERIMENTAL_MULTI_SERVER env var from agent-core-v2 - discover running servers via the instance registry in server ps/kill/rotate-token, kimi web daemon reuse, and the desktop app - remove the pending minidb changesets * feat(cli): add per-instance targeting to server kill and ps - `kimi server kill [serverId]` stops only the matching instance; without an id it still stops the longest-running one, and an unknown id errors with the live server ids listed - `kimi server ps` lists connections grouped per server id (`--json` nests them under a per-server object); an unreachable instance degrades to a per-server note instead of failing the whole listing - update the zh/en command reference and the multi-server changeset * feat(cli): replace kimi server with the kimi web command tree - `kimi web` now runs the local server in the foreground and opens the browser; the background daemon (ensureDaemon / spawn / idle-exit) is removed, so repeated runs simply start another instance on the next free port - drop the OS-service lifecycle (install/uninstall/start/stop/restart/ status) together with kap-server's svc layer - `kimi web kill [serverId]`, `kimi web ps`, and `kimi web rotate-token` manage instances from the registry - the TUI /web command now connects to an already-running instance instead of spawning a background daemon - update the zh/en command reference, dev scripts, and tests * feat(cli): route kimi server invocations to a deprecation notice Any `kimi server …` call — bare or with any legacy subcommand/flags — now prints a deprecation notice pointing at `kimi web` and exits 1, instead of failing with an opaque "unknown command". The shim is scheduled for removal in the next major version. * feat(cli): add the `all` keyword to kimi web kill `kimi web kill all` stops every live instance in the registry (ULIDs can never collide with the keyword). Each instance still gets the API shutdown + SIGTERM/SIGKILL treatment; a failure on one instance does not stop the sweep and is reported at the end. * docs(changeset): drop the web-foreground-default changeset The kimi web command tree replaces the foreground-default behavior this entry describes: --background, daemon reuse, and the version-mismatch hint no longer exist, so the pending entry would contradict the actual release notes. * docs(changeset): tighten the multi-server entry wording * feat(cli): let /web pick a running server or start a new one The /web picker now lists the live instances from the registry with their versions (flagging a CLI mismatch) instead of only connecting to the longest-running one, and offers starting a new server: that one runs in the foreground attached to the terminal after the TUI exits, via the restored exit-takeover wiring. formatReadyBanner is exported and adapts its Stop hint to Ctrl+C for the attached case. * feat(cli): skip the /web picker and start a new server when none is running |
||
|
|
4f3c7240c4
|
feat(cli): run kimi web and the TUI /web command in the foreground by default (#1853)
Some checks are pending
CI / lint (push) Waiting to run
CI / build (push) Waiting to run
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-windows (push) Waiting to run
CI / typecheck (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
Release / Release (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
* feat(cli): run kimi web and the TUI /web command in the foreground by default kimi web and /web now start the server attached to the terminal (Ctrl+C stops it) instead of backgrounding a daemon; --background opts back into the daemon behavior. kimi server run is unchanged. A foreground kimi web reuses an already-running server instead of failing to bind, the /web handoff prints the same ready banner as kimi web (plus the session deep link), and the banner Stop hint adapts to the hosting mode. * fix(cli): resolve the server token after the server is up in /web The token lookup had moved ahead of ensureDaemon()/startServerForeground() during the foreground-default refactor, so a first-time start (no server.token on disk yet) opened the browser without the #token= fragment and left the user at the auth gate. Resolve the token after the daemon is healthy, and inside the foreground ready hook. * docs(changeset): flag the web foreground default as breaking in the changelog The bump stays minor, but the entry now calls out the behavior break and the --background mitigation for scripts that expect kimi web to return immediately. * feat(cli): flag a version mismatch when reusing a server from an older CLI After an upgrade, an older still-running server is reused as-is. The lock's host_version is now surfaced: kimi web / server run print a version-mismatch line next to the reuse notice, /web shows the same as a status warning, and the docs plus changeset tell users a single kimi server kill switches them onto the new version. |
||
|
|
3086e47039
|
fix: unify YOLO and Auto permission mode descriptions across surfaces (#1867)
Some checks are pending
CI / test-windows (push) Waiting to run
CI / lint (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 / build (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
* fix(tui): correct YOLO and Auto permission mode descriptions * fix: unify YOLO and Auto permission mode descriptions across CLI, ACP, web, and docs * docs: correct YOLO and Auto mode descriptions in the interaction guide * fix: correct YOLO mode notices in session replay and vscode extension * feat(vscode): rename /afk command to /auto, keeping afk as hidden alias Also correct the stale 'afk' mode reference in the built-in MCP config skill guidance of both agent engines. * fix(vscode): forward engine approval requests instead of blanket-approving them The extension-level approval handler auto-approved every request when legacy yolo/afk was on, silently swallowing the sensitive-file, plan-review, and ask-rule prompts the engine yolo mode still sends. Forward every request to the user and let the engine permission mode do the auto-approving, matching TUI and web behavior. |
||
|
|
7d393b56fb
|
chore(vscode): release 0.6.3 (#1856) | ||
|
|
5cc194956f
|
ci: release packages (#1785)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
f441193e1d
|
chore: remove kimi-desktop app and desktop release pipeline (#1849)
* chore: remove kimi-desktop app and desktop release pipeline The desktop client has moved to a dedicated internal repository. Drop the Electron shell app, the desktop-build reusable workflow and its release job, and all workspace references (dev script, typecheck filter, onlyBuiltDependencies, flake.nix entries, lockfile). The kimi-web desktop detection code is intentionally kept intact. * chore: fix flake.nix after kimi-desktop removal Complete the workspaceNames cleanup missed in the previous commit and refresh the pnpmDeps fixed-output hash for the regenerated lockfile. |
||
|
|
9e1248416f
|
fix(web): remember the thinking level per model (#1838)
* fix(web): remember the thinking level per model Persist kimi-web.thinking as a JSON map of model id to level instead of a single global value, and resolve the active level against the model's catalog (stored pick when still declared, else the model default) at loadModels, setModel, and on active-model changes via a watcher. Fixes the empty, unresponsive thinking picker shown for a model that does not declare a previously stored level (e.g. a max-only model with a stale global 'low'). * fix(web): resolve a submitted prompt's thinking from its own model submitPromptInternal and the steer path read the single active-session rawState.thinking, so a queue drain for a background session submitted the level of whichever session the user had switched to since enqueueing — the same cross-model leak on the submit path. Thinking now joins model and the per-session modes in being resolved from the prompt's own session model (its stored pick when declared, else the catalog default), falling back to the active value only when the model has left the catalog. * fix(web): keep model switches from persisting derived thinking defaults setModel routed the resolved level through applyThinkingLevel, which writes per-model storage unconditionally — a switch to a model with no saved pick stored the catalog default as if it were an explicit choice, pinning the user to it across later default changes, and the rollback path did the same write for a switch that never happened. Model switches now update the in-memory level only; storage writes stay with setThinking, the explicit picker path. * fix(web): resolve thinking per target session on the BTW and skill paths sendSideChatPromptOn combined the captured parent's model with the active-session level, so a session switch during the startBtw await sent the BTW first turn at the wrong model's effort — resolve it from the parent's own model, falling back to the active value off-catalog, same as the other submit paths. activateSkill carries no thinking either, so the daemon ran skills at the session profile effort, which can predate the per-model restore the picker now shows. Persist the resolved level to the session profile first, mirroring the new-session skill path; that path itself now resolves against the new session's model instead of the raw active value. * fix(web): keep per-model thinking picks in memory as the runtime truth The resolver re-read localStorage on every submission, letting storage — not the displayed state — decide what the daemon receives: with storage unavailable (policy/quota) an explicit pick reached the UI while every submit path fell back to the catalog default, and a pick made in another tab silently changed what this tab submits mid-session. Per-model picks now live in an in-memory map hydrated from localStorage at startup; explicit picks update it first and persist best-effort (read-modify-write merge, so concurrent tabs' entries still survive). localStorage is only hydration plus persistence — another tab's pick can no longer alter this tab's runtime level. * fix(web): carry the legacy global thinking pick forward as a fallback Pre-map installs stored a single global level as a raw string; the map parser dropped it, silently resetting the user's explicit preference to the catalog default on upgrade. The legacy value is now carried as a fallback for models without their own entry — validated against each model's catalog at resolution, so effort models keep the user's pick while a max-only model still falls through to its default and can never be trapped by it. * fix(web): keep the legacy thinking fallback across the first map rewrite The first explicit pick after an upgrade rewrote the raw legacy value into a map containing only that one model, so the next reload saw a nonempty map and dropped the legacy fallback for every other model. The migrated value now lives inside the map under a '*' key that no real model id can collide with: per-model entries override it, and rewrites persist it alongside them instead of deleting it. * fix(web): persist only the changed thinking pick on write Overlaying the whole in-memory map on write could revert a newer pick made in another tab for a model this tab still held a stale copy of. Write the changed entry alone (delta-style, like saveUnread), carrying only the migrated legacy '*' fallback along so it survives the first rewrite into map format. * fix(web): abort skill activation when the thinking profile persist fails persistSessionProfile surfaces failures itself and resolves, so awaiting it never blocked a following activation: a failed /profile write still launched the skill at the session's stale effort. It now resolves a success flag; both activation paths (existing session and new-session draft) gate on it and skip activating when the persist fails, without reporting a second, synthetic error. * refactor(web): persist the new-session skill profile's thinking once startSessionAndActivateSkill persisted the resolved thinking and then activateSkill persisted it again unconditionally — a redundant profile update and status refresh whose transient failure would false-veto an activation whose prerequisite profile was already applied. Thinking is now written by activateSkill alone (the single, gated writer); the draft patch carries only model, plan/swarm and permission. * fix(web): throw an Error instance for the profile-persist sentinel oxlint --type-aware (only-throw-error) rejects throwing a Symbol; the identity-based sentinel works the same as a shared Error instance. * fix(web): resolve an empty session model through the default before skills session.model can be '' transiently (daemon profile echo), so activateSkill fell back to the raw active-view level; in the new-session flow a concurrent switch could persist another model's effort onto the target session. Normalize '' through the configured default_model first, same as the prompt/BTW/steer paths. |
||
|
|
18d3374137
|
fix(vscode): reliable cancel and preserved session model on attach (#1845) | ||
|
|
03021b6db7
|
fix(kimi-web): stop the prompt queue from ghost-sending stale attachments (#1833)
* fix(kimi-web): stop the prompt queue from ghost-sending stale attachments Sending while a turn was running queues prompts locally. A failed flush left entries stuck, and every later session open silently re-submitted them with their old file attachments. Gate the drain on locally witnessed turns, re-drive stuck entries FIFO from real events with a failure budget, restore merged entries on steer failure, persist the queue per session so a refresh loses nothing, and converge queues across tabs via storage events. * fix(kimi-web): merge cross-tab queue updates by entry id (review P1/P2) Whole-record adoption could silently discard a prompt another tab enqueued concurrently. Queue entries now carry a stable id and enqueue timestamp; adoption union-merges snapshots by id, a shared TTL'd removal set stops flushed/discarded entries from resurrecting (and being flushed twice), an in-flight marker covers the submit window, and manual reorders re-stamp timestamps so they survive merges. The flush failure budget is also tracked per entry instead of per session, so removing or reordering the head no longer hands its strikes to the next entry. * fix(kimi-web): single-flusher queue entries, merge order convergence, forget guard (review round 2) Turn-end events reach every open tab and the server accepts concurrent submissions as distinct prompts, so two tabs holding the same adopted entry could both submit it. Entries now record their owner tab and only the owner flushes (ownerless legacy entries flush anywhere); an idle send adopts entries left behind by closed tabs so a stranded queue can still drain. Cross-tab merges now keep the newer enqueuedAt copy per id so a manual reorder converges instead of ping-ponging writes, and the flush failure callback no longer resurrects a queue whose session was forgotten while the submit was pending. * refactor(kimi-web): drop the cross-tab queue persistence, keep the minimal fix Cross-tab queue sync over localStorage is a distributed-systems problem (claim/lease, conflict merge, ownership) that keeps generating review findings far beyond this PR's scope. Remove the persistence/hydration/ adoption machinery wholesale; keep the bug fix proper: gated queue drain, event-driven FIFO retry with a per-entry failure budget, steer queue restore, and the forgotten-session flush guard. Durable queued prompts will be designed together with the server-side prompt queue. * chore: align the changeset wording with the reduced scope * fix(kimi-web): never duplicate on ambiguous submit failures; advance after drop Two review findings: (1) restoring merged queue entries after ANY steer failure could re-submit prompts the daemon had already accepted when the failure was a lost response — submits now report ok/rejected/uncertain and restores + flush re-queues happen only on definitive daemon rejections, while ambiguous failures drop the entry (the failure toast still tells the user); (2) dropping an exhausted queue head no longer strands the entries behind it — the new head is submitted immediately, carrying its own failure budget. |
||
|
|
429521b669
|
fix(vscode): allow editor mentions for files outside the working directory (#1836)
* fix(vscode): allow editor mentions for files outside the working directory * fix(vscode): quote editor mentions whose paths contain spaces |
||
|
|
1b907b07cd
|
fix(tui): hide whitespace-only thinking from the transcript (#1829)
Models occasionally stream whitespace-only thinking (e.g. a single space). It starts a thinking draft that renders as a bare bullet line, both while streaming and when replaying session history. Skip whitespace-only thinking deltas before they create a draft, and skip whitespace-only think text at the component funnel so stored whitespace think parts never render on replay. Stored thinking is still replayed verbatim to the model. |
||
|
|
bfecd0128f
|
feat: refresh model list for API-key providers at the managed endpoint (#1824)
* feat: refresh model list for API-key providers at the managed endpoint * docs: simplify changeset wording * docs: add kimi-code/k3 to the default config example * fix: clear stale default model when a refresh drops its alias * fix: clear refresh defaults via replace; set(undefined) cannot delete * docs: drop the auto model refresh paragraph from providers page * docs: simplify changeset wording |
||
|
|
a5c568dc7a
|
feat(tui): add /copy slash command to copy the last assistant message (#1822)
* feat(tui): add /copy slash command to copy the last assistant message The command copies the latest assistant reply (text parts only, skipping thinking, tool-call-only turns, error and internal messages) to the clipboard. Clipboard writes now also emit an OSC 52 sequence (tmux-aware) so copying keeps working over SSH and in containers where no native clipboard tool exists. * fix(tui): gate /copy to idle and report OSC 52-only copies as unverified During streaming the in-flight assistant text is not in getContext() history yet, so /copy would silently copy an older message; make the command idle-only like /export-md. copyTextToClipboard now returns how the text was delivered so /copy can say when only an unverified OSC 52 escape carried it. * fix(tui): source /copy text from the visible transcript After /compact the model context keeps only user messages plus a user-role summary, so scanning it found no assistant message even though the last reply is still on screen. Read the last assistant transcript entry instead — it matches what the user sees and survives compaction and resume. * fix(tui): mark real model text in the transcript so /copy skips synthetic cards Hook-result and goal-completion cards are also 'assistant' transcript entries appended after the real reply, so /copy could copy a hook card instead of the answer. Tag the single entry-creation site for genuine model text (both live and replay flow through it) and have /copy only accept tagged entries. |
||
|
|
9b496946dc
|
feat(kimi-inspect): add kap-server web inspector with dev-only /api/v1/debug RPC surface (#1806)
* feat(kimi-inspect): add web inspector for kap-server /api/v2 surface - new apps/kimi-inspect app: connect screen (server URL + optional bearer token, persisted in localStorage, deep-linkable via ?url=/?token=), workspace/session browser sidebar, per-session chat view, and live Service panels with data and trigger buttons for Session/Agent scopes - built on @moonshot-ai/klient (HTTP for calls, /api/v2/ws for events); Vite dev server proxies /api to a running kap-server - register the workspace in AGENTS.md project map and flake.nix workspacePaths/workspaceNames * fix(kimi-inspect): align dependency versions with the workspace (sherif) * feat: dev /api/v1/debug RPC surface and kimi-inspect channel rework - kimi-inspect: replace @moonshot-ai/klient with an in-app old-klient-style channel layer (service-bound IChannel, HTTP ProxyChannel, shared /api/v2/ws socket with ref-counted event listens), typed by agent-core-v2 interfaces; /channels descriptors + serviceByName keep every wire protocol loaded 1:1 - kimi-inspect: local server auto-discovery (Vite middleware over the kap-server instance registry + home token), zero-config startup connect, and a header switcher for runtime server switching - kap-server: wire the dormant --debug-endpoints flag to a new whitelist-free /api/v1/debug dispatcher (every scoped service callable), gated to loopback binds; repo dev scripts pass the flag - kimi-inspect: probe the debug surface at connect, falling back to /api/v2 on servers without it - tests: channel + discovery unit tests in kimi-inspect; debug RPC and loopback-gating coverage in the kap-server rpc/debugNonloopback suites * chore(changesets): ignore @moonshot-ai/kimi-inspect The private dev app never ships, so it should never appear in a changeset. Add it to the changeset config ignore list (next to vis*) and note the rule in the gen-changesets skill. |
||
|
|
66cc279975
|
chore(vscode): release 0.6.2 (#1820) | ||
|
|
56a321d4d1
|
fix(workspace): dedupe workspaces across Windows path spelling variants (#1809)
* fix(workspace): dedupe workspaces across Windows path spelling variants The same directory reached the workspace registry as distinct strings on Windows (drive-letter casing, typed vs on-disk casing, slash style), and every identity check compared exact strings, so one folder could appear as multiple workspaces with sessions split across hash-keyed buckets. - add workspaceRootKey (slash-normalize + case-fold Windows-shaped paths) in agent-core, agent-core-v2, and the web app, and compare roots by identity key everywhere instead of exact strings - registry createOrTouch folds alias spellings onto the existing entry instead of minting a new workspace id; session buckets reuse the registered id via a resolver in the v1 session store - list endpoints expand alias buckets (resolveAliasIds / resolveAliasWorkDirs, including session-index-only spellings) so previously split workspaces list all sessions and counts under one merged group; session_index entries use the registry-resolved id * fix(workspace): fold the runtime touch path and drive-root identity keys Two gaps in the Windows path-spelling folding, both reachable in the v1 session-create flow: - touchWorkspaceRegistry minted the alias spelling's id outright; the freshly persisted alias entry then became the resolver's preferred id on the next create, splitting sessions into a duplicate bucket again. It now folds onto the identity-matching existing entry, mirroring the registry service. - workspaceRootKey stripped trailing separators before testing the Windows shape, so a drive root (C:\) collapsed to C: and escaped the case-fold. The shape test now runs before the strip in all three copies (agent-core, agent-core-v2, web). * fix(workspace): unfold symmetric operations that escaped the identity key Two asymmetric spots left the folded comparison one-sided: - the web app matched hidden roots by folded key but cleared them on re-add by exact string, so hiding C:\Foo and re-adding c:\foo kept the workspace hidden forever; clearing now folds too - registry delete (both engines) removed and tombstoned only the exact id, so a legacy split sibling resurfaced as the directory's representative on the next list; delete now removes every registered spelling sharing the root's identity key and tombstones the full alias set (registered ids plus session-index spelling mints), so the session-index merge cannot resurrect the directory either |
||
|
|
1a5c0de19a
|
fix(vscode): stop mid-turn core errors from corrupting the active turn (#1807)
* fix(vscode): stop mid-turn core errors from corrupting the active turn * fix(vscode): reject prompts during exclusive operations with a terminal error |
||
|
|
cec15e2188
|
fix(tui): dismiss /btw panel before cancelling compaction on Esc and Ctrl+C (#1811) | ||
|
|
319001ae5c
|
refactor: remove git detection from workspace wire and folder browse (#1787) | ||
|
|
36b05820cb
|
ci: release packages (#1767)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
3ace52b697
|
chore(vscode): release 0.6.1 (#1783)
* chore(vscode): release 0.6.1 * test(vscode): read the extension version from the manifest in version assertions * test(vscode): declare version on the runtime rig type |
||
|
|
ba36c6a563
|
fix(vscode): make the gear sign-in actually log in (#1779)
* fix(vscode): count configured provider credentials as signed in and make the gear sign-in actually log in * fix(vscode): keep the gear auth action scoped to the Kimi account session |
||
|
|
d531398d01
|
fix: scope Anthropic effort fallback profile to non-Kimi providers (#1765)
* fix: scope Anthropic effort fallback profile to non-Kimi providers Managed Kimi models routed through the Anthropic protocol (protocol = "anthropic", no catalog-declared think_efforts) inherited the inferred latest-Opus effort profile, so the UI showed reasoning effort choices the server never declared. The fallback now applies only when the provider type is known, non-kimi, and the effective wire protocol is Anthropic; Kimi providers keep catalog-declared efforts only, and callers without provider context fall back to name matching. * fix: align v2 catalog with resolver for providerless Anthropic models Flat models (inline base_url, no named provider) and providers without a declared type now fall back to the model's own protocol when deciding the Anthropic fallback effort profile, so the model catalog stays consistent with runtime resolution. * fix: keep flat Anthropic model effort metadata in TUI and ACP catalogs Flat models without a named provider (inline base_url, protocol: "anthropic") have no provider entry to look up; fall back to the model's own protocol as the provider identity so the effort picker and ACP catalog stay consistent with runtime resolution. * style: move v2 anthropic fallback rationale into the modelAuth header The v2 comment convention keeps comments in the top-of-file block only; drop the inline explanations added beside functions and statements. |