mirror of
https://github.com/MoonshotAI/kimi-code.git
synced 2026-07-31 20:14:53 +00:00
72 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
ceaa96942b
|
feat(kap-server): add global message search with literal and live-session modes (#2321)
* feat(kap-server): add the /api/v1/search global message search endpoint Cross-session full-text search over user messages, assistant text and session titles, backed by a minidb index under <home>/search-index with a single-writer lock election and read-only WAL catch-up for other processes. Hits carry transcript anchors (turn ordinal and step id) so clients can jump straight to the matching turn or step. * feat(kimi-inspect): add a search view with chat-timeline navigation The left rail gains a Search view over the global search endpoint, with role and sort filters and cursor pagination. Clicking a hit switches to the chat view and navigates to its session, agent, turn and step — the channel pages the turn into the loaded window, scrolls it into view and flashes the target briefly. * chore(kimi-code): start the dev server without built web assets The repo's dev server scripts (dev:server, dev:kap-server, dev:kap-server:multi, dev:server:restart) now set KIMI_CODE_DEV_SERVER=1. When it is set and dist-web/index.html is missing, kimi web starts the API server without the bundled web UI instead of failing at startup, so backend dev no longer requires a kimi-web build. * feat(kap-server): add literal substring search and a live session route - minidb: text indexes accept an injectable tokenizer/queryTokenizer, and a hashed 2/3-gram tokenizer (NFKC + lowercase, code-point windows) backs substring search; tokenizer names persist in db.textindexes.json with backward-compatible defaults - /api/v1/search gains mode: 'literal' — n-gram candidates confirmed against the original text (zero false positives), with an 'candidate_cap' incomplete flag when the candidate set truncates - container.session_id queries against a session live in this process scan the in-memory transcript store instead of the index (both modes); the response's source: live|index field names the serving route and rides in the page-token fingerprint - kimi-inspect: exact-match toggle and source badge in the search view, plus an in-chat session search bar with jump-to-hit navigation * test(kimi-inspect): avoid stringifying BodyInit in search api tests |
||
|
|
d03a4886fd
|
feat(server): remove the 50 MiB upload size cap and stream uploads to disk (#2312)
Some checks are pending
CI / build (push) Waiting to run
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
Release / Release (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
- add writeStream/putStream to the storage and blob store interfaces so large values are written incrementally (tmp + fsync + rename) instead of being buffered in memory - FileService.save now streams the request body straight to the blob store and only counts bytes for FileMeta.size - drop the multipart fileSize limit and the file.too_large error from the /files upload path (41301 stays in the wire protocol for session export) |
||
|
|
b0f43aea28
|
feat(oauth): return structured managed usage rows (#2300)
* feat(oauth): return structured managed usage rows
Stop formatting plan-usage labels and reset hints into English strings
at the oauth layer. The parser still absorbs backend field drift, but
now emits a stable structured row (name / window{duration,unit} / used
/ limit / resetAt) that kap-server passes through and clients localize
themselves:
- window: normalized from duration/timeUnit (minute/hour/day/week),
whole-hour minute windows fold to hours, unnamed summaries are the
weekly limit
- resetAt: absolute ISO timestamp; relative reset_in/ttl seconds are
converted at parse time
- TUI /usage panel formats labels and reset hints locally
* refactor(oauth): parse managed usage strictly to the current payload shape
Drop the defensive drift tolerance (alternate reset-time spellings,
reset_in/ttl seconds, remaining-derived used, title/scope names,
top-level duration/timeUnit, fuzzy time-unit matching) and parse only
what the platform actually sends: numeric strings, resetTime, nested
detail/window records, TIME_UNIT_* enums.
* fix(node-sdk): update managed usage smoke example and facade tests for structured rows
|
||
|
|
7e30add445
|
feat(kap-server): add global fs:mkdir endpoint (#2281)
* feat(kap-server): add global fs:mkdir endpoint Add POST /api/v1/fs:mkdir to create a directory on the host filesystem by absolute path, backing the folder picker's "new folder" action. Implemented directly on node:fs/promises.mkdir in the transport layer for now, non-recursive by design, with wire errors mapped to the existing fs.* codes (40001/40409/40411/40919). * test(kap-server): update api surface snapshot for fs:mkdir * test(kap-server): stop export tests from holding server.close() open The export download tests reused pooled undici keep-alive connections, so afterEach's server.close() could wait out fastify's 72s default keepAliveTimeout and die on the 10s hook timeout (flaky on CI). Send connection: close on the streamed export requests, matching the fs:content tests. |
||
|
|
77618e38c3
|
feat(kap-server): wire cloud telemetry for engine events (#2230)
Some checks are pending
CI / build (push) Waiting to run
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
Release / Release (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
* feat(kap-server): wire cloud telemetry for engine events The v2 engine registers a full telemetry event catalog, but kap-server never attached an appender, so events from web-hosted sessions were dropped to the null appender. Add an opt-in `telemetry` start option that attaches a CloudAppender (app_name kimi-code-cli, ui_mode web, matching the v1 `kimi web` host conventions), still gated by the config `telemetry` toggle, with periodic flush and a bounded flush on close. The option defaults off so tests never post to the real endpoint; the CLI's `kimi web` host enables it. * fix(kap-server): honor telemetry disable environment * fix(agent-core-v2): isolate session telemetry context * fix(kap-server): seed telemetry client version * fix(cli): share telemetry shutdown deadline * fix(telemetry): make shutdown ownership durable * fix(kap-server): keep telemetry shutdown best-effort |
||
|
|
a77ee03829
|
feat(agent-core-v2): add hostIdentity domain for host-overridable system prompt identity (#2144)
* feat(agent-core-v2): add hostIdentity domain for host-overridable system prompt identity
- add app-scope hostIdentity domain (L3) with productName / replyStyleGuide
overrides and hostIdentitySeed for composition roots
- render ${product_name} and ${reply_style_guide} in the base system prompt,
falling back to CLI defaults when the host provides no override
- seed the variables from AgentProfileService via IHostIdentity
- expose hostIdentity on kap-server's ServerStartOptions
* chore: add changeset for host identity system prompt
* fix(agent-core-v2): adapt hostIdentity registration to ScopeActivation
The DI refactor on main removed _base/di/extensions (InstantiationType);
register with ScopeActivation.OnScopeCreated instead, and regenerate the
state manifest for the new SystemPromptContext fields.
---------
Co-authored-by: liruifengv <liruifeng1024@gmail.com>
|
||
|
|
3b017821cf
|
feat(kap-server): accept secondary_model in the config API (#2228)
* feat(kap-server): accept secondary_model in the config API POST /api/v1/config now accepts secondary_model, persisted to the [secondary_model] config section via the generic per-domain dispatch. GET /config also hides the synthesized __secondary__ derived entry from the models view, matching the GET /models listing. * Update config-api-secondary-model.md Signed-off-by: 7Sageer <sag77r@hotmail.com> --------- Signed-off-by: 7Sageer <sag77r@hotmail.com> |
||
|
|
48bf3d4c28
|
feat(kap-server): bundle the desktop app log into session exports on request (#2223)
* feat(kap-server): bundle the desktop app log into session exports on request * refactor(agent-core-v2): align the desktop log export with repo conventions |
||
|
|
d40d0d305d
|
refactor(agent-core-v2): make undo domain-owned (#2055)
* refactor(agent-core-v2): rebuild undo as wire-level journal rewind Replace the compensating context.undo op with a wire-layer rewind primitive: a log.cut control record with a persisted target, applied uniformly by the wire during fold. Turn boundaries become first-class (TurnIndexModel indexing turn.prompt record positions), models declare a temporal classification (rewindable), and a single IAgentRewindService owns the undo pipeline (quiesce -> precheck -> cut -> reconcile) with all entry points converged. - wire: log.cut record, rewindable model flag, re-fold rebuild; OpApplyContext.recordIndex for position-aware reducers - rewind service: aborts the active turn, cancels in-flight compaction, preserves the pending queue, rebases measured tokens, reconciles lastPrompt, tracks conversation_undo - todo list, plan mode, task-notification delivery and the turn index now rewind together with the undone turns - transcript reducer applies cut ranges so snapshot/messages surfaces stay consistent with the model context - REST/RPC/debug undo entry points converge on the rewind service; TUI parses the v2 undo-unavailable error shape - legacy context.undo records keep replaying for old journals * refactor(agent-core-v2): keep undo domain-owned * refactor: enhance /undo functionality for consistency and safety, including todo list rollback and improved event handling * chore: clean up undo changeset artifacts * refactor: rebuild rewind consistency * fix: make conversation undo durable and consistent * fix(agent-core-v2): stabilize undo restoration * fix: keep TUI undo on legacy error contract * refactor(agent-core-v2): drop unused full compaction cancel API Undo now rejects with session.busy while compaction runs instead of cancelling it, so the awaitable cancel() added for the earlier rewind semantics has no callers left. Remove it from the interface and implementation; the RPC cancel path keeps using the task abort controller directly. * fix(agent-core-v2): remove injected context on undo * chore(agent-core-v2): regenerate wire manifest * docs(agent-core-dev): rename rewind to undo in layer table * fix(agent-core-v2): undo prompt-owned image reminders * refactor: remove transcript undo reconciliation * fix(kap-server): map undo busy errors * refactor(agent-core-v2): rename undo participant registry and attribute checkpoint depth - Rename IAgentConversationUndoReconciliationRegistry to IAgentConversationUndoParticipantRegistry (conversationUndoParticipants). - Return the limiting model from checkpointDepth and include it in the SESSION_UNDO_UNAVAILABLE details; report checkpoint_lost instead of compaction_boundary when no compaction explains the missing depth. - Add a registry invariant test: every model reacting to context.* ops must be registered via defineCheckpointedModel or explicitly exempt. * Delete .changeset/fix-undo-injections.md Signed-off-by: 7Sageer <sag77r@hotmail.com> --------- Signed-off-by: 7Sageer <sag77r@hotmail.com> |
||
|
|
cc9b25e132
|
fix(kap-server): flush public and control WS frames immediately (#2221)
Only subscription events now enter the timed coalescing buffer. server_hello, acks, resync_required, and global session events join the outbound FIFO and flush it right away, so they no longer wait behind the flush window and cannot overtake earlier buffered subscription frames. The broadcaster marks global fan-out with the new BroadcastDelivery 'immediate' lane. |
||
|
|
bf8e967d5c
|
refactor(agent-core-v2): register tools as scoped services (#2196)
Some checks are pending
CI / build (push) Waiting to run
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
Release / Release (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
* refactor(agent-core-v2): register agent tools as DI services with profile-aware activation - replace module-level registerTool + Eager AgentBuiltinToolsRegistrar with registerAgentTool double registration (Agent-scope DI service + contribution table) - add toolActivation domain: AgentToolActivationService filters contributions by the bound Profile's tool policy using declared names, resolves instances lazily via accessor.get, and re-activates on agent.status.updated - rename BuiltinTool to AgentTool service interface; tools become Agent-scope services with decorator-injected dependencies (e.g. AgentTool -> SubagentTool/ISubagentTool) - AgentLifecycleService.create runs one activation pass after restore and profile binding so tools reflect the Profile before the first turn - update tool registrations, scripts, and tests; add toolActivationService tests * refactor(agent-core-v2): centralize builtin tools under agent/tools - move builtin tools from scattered domain folders (plan/tools, goal/tools, os/backends/node-local/tools, task/tools, etc.) into a unified agent/tools/ directory - split each tool into a kebab-case definition file (bash.ts) and a registration file (bashTool.ts) pairing with its prompt markdown - update imports across src, tests, kap-server, and TUI comments * fix(agent-core-v2): keep agent tools out of scope-creation instantiation Main's instantiateAll constructs every registered service at scope creation, but agent tool constructors may legitimately throw when their host capability is absent (e.g. WebSearchTool without a configured provider), and profile-aware activation must stay the only resolution path so the runtime registry holds real instances, never proxies. - add SyncDescriptor.instantiateWithScope (default true) and let registerScopedService opt registrations out of the instantiateAll sweep - registerAgentTool passes the opt-out, restoring lazy activation-driven construction on top of the eager-scope semantics - regenerate docs/state-manifest.d.ts * refactor(agent-core-v2): replace delayed DI with scope activation - add explicit OnScopeCreated and OnDemand activation modes - remove delayed proxy and idle initialization support - migrate service registrations, tests, and DI guidance |
||
|
|
7799bd7346
|
feat(agent-core-v2): add per-scope keyed state container (#2192)
* refactor(agent-core-v2): instantiate all registered services eagerly at scope creation - add instantiateAll to scope creation: every service registered for a scope tier is constructed when the scope is created, following the static dependency graph; a failing constructor fails scope creation - drop the hand-maintained eager-resolution lists: igniteEagerServices in AgentLifecycleService, the force-instantiated session services in SessionLifecycleService, and the kosong config bridge get in bootstrap - update DI docs and agent-core-dev skill guidance for the new semantics - adjust affected tests (registry hygiene, timer draining, listener ordering) and add scope-tree coverage for eager instantiation * feat(agent-core-v2): add per-scope keyed state container (state domain) - add _base StateRegistry: typed StateKey/defineState descriptors with register/get/set, per-key onDidChange and global onDidChangeAny events, and BugIndicatingError on duplicate or unregistered key access - bind thin per-scope services at each tier: IStateService (App), ISessionStateService (Session), IAgentStateService (Agent), so scoped plain-data state lives in one observable container that dies with the scope - register the state domain in the layer check script and export the new services from the package index - add StateRegistry unit tests and scoped resolution tests * refactor(agent-core-v2): move session-scope service state into ISessionStateService - add StateRegistry.snapshot() with JSON-safe serialization for Map/Set/Date/circular values - migrate plain-data fields of 13 session-scope services (cron, interaction, sessionActivity, agentProfileCatalog, fs, fsWatch, log, metadata, skillCatalog, toolPolicy, workspaceCommand, workspaceContext) to defineState keys registered in sessionState - register SessionStateService in affected tests and add test/state/stubs.ts helper * feat(kimi-inspect): rework chat layout with session pane and tabbed right dock - add SessionPane column next to the sidebar: Services tab (pending interactions + session Service panels) and State tab polling ISessionStateService.snapshot() every second, rendered as a live diff tree - merge the transcript audit panel and the agent inspector into one RightPanel with Audit/Agent tabs that keep panel state across switches - extract InteractionsCard from Inspector into its own component - collapse multiline strings in StateTree into a compact hover-preview button with a viewport-clamped fixed popup - test: cover StateRegistry.snapshot() conversions (Map/Set/circular); pass a session state service to SessionInteractionService in kap-server test fakes - update the AGENTS.md project map for the new layout * refactor(agent-core-v2): move agent-scope service mutable state into agentState Register each Agent-scope service's mutable fields into the agent-state container (IAgentStateService) via defineState keys, and access them through get/set accessors backed by states.get/set. Promise locks, disposables, and other mechanism-only fields stay plain instance fields. - define per-service state keys (e.g. activityView.*, goal.*, toolDedupe.*) and register them in each service constructor - replace direct field reads/writes with states-backed accessors across the touched services - update the affected unit tests for the new IAgentStateService dependency * fix(agent-core-v2): collapse class instances in state snapshots - StateRegistry.snapshot() now stops at custom-prototype boundaries and emits '(ClassName)' markers, so resource graphs reachable from registered values (e.g. tool instances holding service references) can no longer exhaust the heap during export; plain data keeps recursing - add agent-scope state test covering the full assembled agent scope - kimi-inspect: extract the session State card into a shared StateCard and add an agent State tab in RightPanel polling IAgentStateService.snapshot() - document the per-scope state container pattern in the agent-core-dev skill * refactor(agent-core-v2): keep resource-holding state out of the state container - move fields holding live resources (tool entries, managed tasks, turn jobs, prompt records, MCP registrations, profile callbacks) back to plain private fields so the agent state service only holds snapshot-safe plain data - add gen:state-manifest script that statically collects defineState keys and their register call sites into docs/state-manifest.d.ts - add state manifest freshness test and update agent-state docs * chore: add changeset for session-scope state container * docs(agent-core-v2): move eager-instantiation notes into the scope.ts header * fix(kimi-inspect): suppress stale state tree while switching state owner |
||
|
|
a2401cc1ed
|
feat(kap-server): add provider write endpoints and models.dev/registry import (#2110)
* fix(agent-core-v2): honor explicit undefined field deletes in modelsToToml
The models TOML transform merged each entry as { ...oldRaw, ...converted },
so a field the new record carried with an explicit undefined — deleted from
'converted' by setDefined — was put right back from the old on-disk raw.
Field-level clears issued through config.replace (e.g. the provider write
routes dropping base_url, display_name, capabilities) only took effect in
memory and resurrected on the next boot. Merge via setDefined onto the old
raw directly, matching providerEntryToToml.
* feat(kap-server): add provider write endpoints and models.dev/registry import
Add the provider management write surface plus server-proxied catalogs so
API clients (the desktop app first) can manage providers without editing
config.toml by hand:
- POST/PUT/DELETE /providers: manual create, replace-style edit (new_id
rename with pointer migration, tri-state api_key, form-unknown fields
merged through), and delete with real alias removal.
- GET /providers/{id} additionally reveals the stored api_key for edit
prefill on the loopback+bearer transport; the list stays redacted.
- GET /catalog/providers[{id}]: pruned models.dev directory with import
eligibility resolved server-side (10-min cache, stale fallback, built-in
snapshot, shared in-flight fetch).
- POST /providers:import_catalog and :import_registry (collection actions
next to :refresh): catalog/registry imports with TUI-aligned
remove-then-apply refresh semantics, OAuth-managed guards, and the
registry source blob that scheduled refreshes rediscover.
Write-path consistency: field-level clears assign explicit undefined (the
TOML transforms only drop keys that way), import refreshes swap aliases in
two passes so stale on-disk fields cannot ride along, re-imports keep the
stored credential when api_key is omitted, and multi-step writes serialize
through a process-local chain. Global default_provider/default_model are
never modified by provider writes.
* fix(kap-server): cache the built-in catalog fallback and guard alias-key collisions on replace
- Cache the built-in snapshot on upstream failure, so an offline install no
longer pays the full upstream timeout on every catalog call.
- Reject a PUT whose rebuilt alias keys collide with an alias owned by
another provider (foreign-prefix keys are global), checked before any
write so a collision never lands half the edit.
* fix(kap-server): make toCatalogProviderItem's switch explicit for older TS control-flow
* chore(agent-core-v2): drop inline rationale per package comment conventions
* feat(kap-server): seed default_model on provider create/import when none is configured
A fresh setup has no global default model, so the first provider added
through the write endpoints left GET /auth permanently unready and new
sessions without a selected model. Seed default_model from the created
provider's default (or first) model on POST /providers, :import_catalog
and :import_registry when — and only when — no default is configured;
an existing pointer is never moved, not even a dangling one.
* refactor(agent-core-v2): own the models.dev provider import in the engine
kap-server's provider write endpoints imported @moonshot-ai/kosong and
@moonshot-ai/kimi-code-oauth directly for the models.dev browse/import
and custom-registry import. Move that capability behind a new App-scope
IModelsDevImportService so the server only talks to agent-core-v2:
- app/kosongConfig/modelsDev.ts mirrors the third-party api.json schema
and hosts the pure translation (wire inference, endpoint resolution,
model pruning, thinking/gateway overrides) ported from kosong's
catalog.ts; kosong's own type surface stays limited to built-in
vocabulary
- modelsDevUpstream.ts owns the directory fetch, 10-minute cache, and
built-in snapshot fallback; modelsDevImportService.ts owns the import
orchestration (tri-state api_key, two-pass alias swap, OAuth-managed
rejection, serialized writes) with coded modelsDev.* errors
- kap-server routes shrink to wire mapping (zod schemas + numeric error
code mapping) and drop the kosong/oauth dependencies
The /api/v1 surface is byte-identical: the apiSurface snapshot and all
existing modelCatalog tests pass unchanged.
* chore: drop the branch's changesets
* fix(agent-core-v2): route the models.dev always-thinking exemption through kosong
The zero-tolerance vendor-name gate forbids a 'kimi' compare outside the
kosong layer, and the engine-side models.dev port carried one inline.
Kosong (the vendor layer, owner of thinking semantics) now answers the
verdict — wireHasProtocolThinkingDisable — and kosongConfig/modelsDev.ts
asks it instead of comparing wire ids.
---------
Co-authored-by: haozhe.yang <yanghaozhe@moonshot.ai>
|
||
|
|
7b62ed5b2c
|
feat: support a configurable secondary model for subagents (#2064)
* feat: support a configurable secondary model for subagents * refactor: move the subagent model config to a consumer-neutral [secondary_model] The secondary model becomes a model-domain concept next to default_model so future consumers beyond subagents can share it: [secondary_model] model / effort in config.toml, KIMI_SECONDARY_MODEL / KIMI_SECONDARY_EFFORT env overrides, and the Agent / AgentSwarm per-spawn choice renamed from "subagent" to "secondary". * docs: replace "v2 engine only" notes with the concrete effective surfaces State that [secondary_model], its env overrides, the Agent/AgentSwarm model parameter, and SYSTEM.md take effect only under kimi web and experimental kimi -p (the TUI ignores them), and that --agent / --agent-file are available only under experimental kimi -p. Also drop the SYSTEM.md claim of parity with --agent/--agent-file, which was inaccurate: SYSTEM.md is an agent-core-v2 app-domain feature and also applies under kimi web, while the flags are gated at the CLI. * fix: review follow-ups for the subagent secondary model - Drop the "cheaper" claim from the Agent/AgentSwarm model parameter descriptions and the advertised model list — the secondary model is not necessarily the cheaper one. - Downgrade the changeset to patch, note the kimi web / experimental kimi -p effective surface, and tighten the wording. - Remove the onWillRestore stub fields from two lifecycle stubs; they belong to upcoming lifecycle work, not to this change. * fix(agent-core-v2): prevent ghost agents from invalid model bindings * fix: narrow the secondary-model error hint to missing-alias failures The model catalog's not-configured throw now carries details.model, and wrapSubagentModelError only decorates errors whose details.model matches the bound model. Malformed [models.*] entries and unrelated config.invalid failures during agent creation pass through untouched instead of being misattributed to an invalid secondary-model alias. * fix: mark subagent resume semantics as breaking * chore(agent-core-v2): follow header-only comment convention * fix(agent-core-v2): await agent restore preparation * feat(agent-core-v2): support agent model preferences * Update subagent-secondary-model.md Signed-off-by: 7Sageer <12210216@mail.sustech.edu.cn> * fix: validate secondary models before agent creation * Delete .changeset/secondary-model-startup-warning.md Signed-off-by: 7Sageer <12210216@mail.sustech.edu.cn> * Add secondary_model config section for subagents Individual agents can override this via the new `model_preference` field in their agent file. Signed-off-by: 7Sageer <sag77r@hotmail.com> * feat(agent-core-v2): support override patches in [secondary_model] The recipe is now `model` plus the flattened ModelOverride field set. With any patch field set, a config overlay synthesizes a derived registry entry (base copy, patch merged into overrides, aliases dropped) so subagent spawning rides the standard effectiveModelConfig merge; with none, subagents bind the pointed entry directly. `default_effort` replaces `effort` (KIMI_SECONDARY_EFFORT rebinds) and doubles as the explicit subagent thinking; unset, thinking resolves naturally instead of inheriting the caller. The overlay strips the derived entry (and any defaultModel pointer to it) from writes, and the kap-server GET /models route hides it from pickers. * fix(agent-core-v2): fire section events for overlay-rewritten domains rebuildEffective only committed the caller-named domains, so a ConfigEffectiveOverlay or section env binding that rewrote a sibling domain (setting [secondary_model] synthesizes a derived models entry; removing the recipe retracts it) left consumers of the models section stale. Widen the commit candidates with every domain the recompute actually changed; commit() deepEqual-guards each candidate, so the widening costs nothing. * feat(agent-core-v2): gate secondary model behind experimental flag * Update subagent-secondary-model.md Signed-off-by: 7Sageer <sag77r@hotmail.com> --------- Signed-off-by: 7Sageer <12210216@mail.sustech.edu.cn> Signed-off-by: 7Sageer <sag77r@hotmail.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
|
||
|
|
188c0fcbf7
|
refactor(agent-core-v2): decouple kosong from config persistence (#2068)
Some checks are pending
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / build (push) Waiting to run
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
CI / test (3) (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
* refactor(agent-core-v2): decouple kosong from config persistence
- keep the kosong provider/model registries in memory and sync them with
config.toml through a new app/kosongConfig two-way bridge: hydrate on
startup, push config section changes into the registries, and persist
runtime mutations (discovery refresh, OAuth provisioning, default-model
pointer changes) back to disk
- declare the providers/models/thinking section constants, zod schemas,
env bindings, and TOML transforms in a single app/kosongConfig
configSection.ts; kosong keeps hand-written types only
- pin every schema to its kosong type at compile time via
AssertExact<Equal<...>> (_base/utils/typeEquality)
- register a transitional auth>kosongConfig exception in the domain-layer
checker for the OAuth provisioning flows
* chore(agent-core-v2): drop unused IConfigService import from authLegacy
* fix(agent-core-v2): reconcile registry with env-pinned default pointers
A registry-originated default-model/provider write lands only in the
config user layer when an effective overlay pins the section
(KIMI_MODEL_NAME pins defaultModel to the reserved env model): the
effective value does not move and no change event fires, so the registry
diverged from the effective config view — catalog/auth reads reported the
user pick while profile resolution kept the pinned model. After
persisting, the bridge now re-asserts the effective value into the
registry, restoring the pre-refactor behavior where every default-pointer
write was arbitrated by the effective view.
* fix(agent-core-v2): await persistence before resolving kosong registry mutations
ProviderService/ModelService mutations resolved as soon as the in-memory
registry updated, while the kosongConfig bridge persisted the change on an
unawaited private chain — callers (klient kosong.*, set_default route,
OAuth provision, discovery refresh) could observe success before the write
reached config.toml, and a restart right after could lose it.
- fire registry change events through AsyncEmitter and await delivery in
set/delete/replaceAll/setDefaultX, so a mutation resolves only after
listeners' waitUntil work completes; loadAll keeps synchronous timing
- the bridge hooks its persists into waitUntil, hoists the equality guards
into the listeners so config-originated echoes stay fully synchronous,
and serializes persists on the chain as before
- retry a failed persist with bounded backoff (3 attempts); failures are
logged, never rejected to callers, and the in-memory change stands
- default-pointer change events now carry an { id } payload (fireAsync
requires object events)
- add the klient kosong-config stress example covering read-after-write,
concurrent bursts, and restart durability
|
||
|
|
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
|
||
|
|
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.
|
||
|
|
ba921ca531
|
fix: gate always-thinking inference to OpenAI wires, plus catalog review follow-ups (#2036)
* fix: gate always-thinking inference to OpenAI wires, plus review follow-ups
- catalog: strip the inferred alwaysThinking marker on non-OpenAI wires so
Claude/Gemini keep their native off; verified against live models.dev
- v1 provider-manager: honor per-alias baseUrl on kimi/google-genai/vertexai
- thinking: rewrite the PHASE-6 contract comment, drop three dead
cannot-disable warning branches, normalize requested effort in v1 to
match v2
- tests: input-cap compaction preference in both engines, kap-server WS
status cap, v2 legacy status input cap
- docs + changeset: new model fields, catalog-refresh behavior, kap-server
* fix: strip always-thinking only where the wire encodes a true off
The previous gate kept the marker only on the OpenAI wires, which wrongly
stripped it from Gemini 3 on the Google wires: its floor is
thinkingLevel MINIMAL with suppressed thoughts — still reasoning — so an
Off option there would be a lie. The criterion is now the wire's encoding,
not its family: strip only on anthropic and kimi, the two wires with a
protocol-level `thinking: {type: 'disabled'}` that the catalog's effort
list can never show. Verified against live models.dev data: google now
marks exactly the gemini-3 family (10), anthropic and moonshotai stay 0.
* docs(agent-core-v2): move the strict-validation contract into the thinking.ts file header
The scoped guide keeps comments in the top-of-file block only; the
function JSDoc shrinks to a short what-it-answers note matching its
neighbors. No behavior change.
|
||
|
|
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 |
||
|
|
ec88d352e8
|
fix: five correctness follow-ups to the catalog metadata work (#2030)
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
* fix: five correctness follow-ups to the catalog metadata work - Normalize a configured effort value (case/whitespace) before thinking resolution on both engines, so "OFF" is read as off instead of being sent upstream as an invalid effort. - Clamp a declared input cap to the effective context window in the effective model resolution, so an override lowering max_context_size cannot leave a stale larger cap behind. - Report context usage against the same effective cap (max_input_tokens ?? max_context_tokens) in the SDK getStatus and the v2 legacy status projections, matching the session-event and service surfaces. - Preserve concretely declared per-model endpoints when the override npm is unrecognized, via the same OpenAI-compatible fallback used for top-level entries. - Attribute resolved.maxInputSize and resolved.capabilities .max_input_tokens in the model inspector to their config, override, or clamp provenance. * fix: honor observed context caps and publish the effective cap in v2 status - The overflow-learned provider window is now written into both max_context_tokens and max_input_tokens of the effective compaction context, so the strategy cannot bypass it by re-selecting the raw catalog input cap during overflow recovery. - agent.status.updated publishes max_input_tokens ?? max_context_tokens, matching the other v1/v2 status surfaces. * fix: never mutate config on clamp, cap usage ratio, and refuse proprietary override SDKs - effectiveModelAlias / effectiveModelConfig now build a copy before clamping maxInputSize to the effective window instead of rewriting the caller's config record in place. - context_usage is clamped to 1 in the v2 legacy status, the v1 session service, and the SDK getStatus; the default-model status fallback also resolves the input cap. - Overrides naming known proprietary SDKs (Bedrock, Cohere) are refused before the OpenAI-compatible fallback, matching top-level import behavior. - The inspector attributes a clamped maxInputSize to the clamp even when the raw value came from models.*.overrides. * fix: normalize forced efforts, prefer input cap in WS status, keep raw event ratio - Whitespace-only configured efforts now read as absent, and the KIMI_MODEL_THINKING_EFFORT override is lowercased on both engines. - kap-server's WS legacy status publishes max_input_tokens ?? max_context_tokens like the other status surfaces. - SDK getStatus keeps the ratio unclamped on purpose (>100% is the documented overflow signal on that path); schema-bounded REST status stays clamped to 1. - Pin the provider-observed window beating a declared input cap with a v1 full-compaction regression test. * fix: attribute resolved.maxInputSize provenance and drop test-body comments in v2 |
||
|
|
8e0dcf3049
|
feat(kap-server): add GET /api/v1/oauth/usage for managed account plan usage (#2027) | ||
|
|
37eda4e59a
|
feat(config): add env overrides for loop control and background task limits (#1993)
* feat(config): add env overrides for loop control and background task limits
Add three operational environment overrides, resolved as env > config.toml
> default in both engines (agent-core and agent-core-v2), matching the
existing KIMI_IMAGE_MAX_EDGE_PX / KIMI_SUBAGENT_TIMEOUT_MS pattern:
- KIMI_LOOP_MAX_STEPS_PER_TURN overrides loop_control.max_steps_per_turn
- KIMI_LOOP_MAX_RETRIES_PER_STEP overrides loop_control.max_retries_per_step
- KIMI_CODE_BACKGROUND_MAX_RUNNING_TASKS overrides background.max_running_tasks
Invalid values are ignored and fall back to the config value. The v2 engine
resolves them through config section env bindings (effective-only, never
persisted); the v1 engine resolves them at the consumption point.
* fix(config): strip env-bound fields before persisting config writes
Environment overrides resolved into the effective config could be echoed
back through IConfigService.set/replace (e.g. GET then POST
/api/v1/config) and persisted into config.toml, outliving the env var.
This affected the pre-existing image / subagent / keep-alive bindings as
well as the new loop control and max-running-tasks bindings.
Extend ConfigStripEnv with a getEnv parameter and add a shared
stripEnvBoundFields helper: while a field's env var is set, writes
restore the field's raw on-disk value (or drop it) instead of persisting
an echoed env value; when unset, normal writes persist. Register it for
the loopControl, task/background, image, and subagent sections.
Also fix ConfigService.stripEnv looking up rawSnake by the camelCase
domain key; on-disk sections are keyed snake_case.
* fix(config): honor binding parsers when stripping env fields on persist
An invalid env value (e.g. KIMI_LOOP_MAX_STEPS_PER_TURN=abc) is ignored
on the read path but still marked the field env-owned on the write path,
so a config write for that field was silently dropped.
stripEnvBoundFields now derives the guard from the section's envBindings
and skips fields whose env value fails the binding's parse, so invalid
env values are ignored on both paths — and the duplicated field/env
descriptor list is gone.
Also drop function-level comments added beside helpers; agent-core-v2
keeps comments solely in the top-of-file block, so the strip semantics
now live in the config.ts / configService.ts headers.
* fix(config): re-apply env overlays from the env-free base on every read
Two follow-ups from review:
- ConfigService.get()/getAll() re-applied section env bindings on the
already-overlaid effective cache (and get() mutated it in place), so a
valid override degraded to invalid or unset kept serving the stale
value until the next reload — and an echoed stale value could then be
persisted by a config write. Reads now recompute from a cached
env-free validated base, so degraded or removed env values fall back
to the file immediately.
- stripEnvBoundFields restored env-owned fields from the raw snake
sub-object, missing values persisted under legacy keys (e.g.
max_steps_per_run). Section stripEnv now receives the env-free,
fromToml-normalized raw base, so legacy aliases are honored.
* test(kap-server): retry temp-home cleanup in auth tests
auth.test.ts removed its temp home with a plain recursive rm, which races
late async writers in the server shutdown path and flakes with ENOTEMPTY
(seen on main CI and locally on main). Harden the cleanup with the same
maxRetries/retryDelay options sessions.test.ts already uses.
* chore(changeset): consolidate the env-override changesets into two entries
One feature entry (loop/background env overrides, both engines plus the
CLI) and one fix entry (env values persisting on writes and sticking
after degrade/unset, agent-core-v2 plus the CLI).
* fix(config): clear fully-stripped sections and refresh overlay domains on get()
Two follow-ups from review:
- stripEnvBoundFields returned an empty object when every written field
was env-owned, so a section with a non-empty default (e.g. subagent)
stored raw = {} and the default stopped applying until the next
reload. A fully stripped result now clears the raw section instead.
- get(domain) only recomputed env overlays for sections with env
bindings, so domains written solely by a ConfigEffectiveOverlay
(models / defaultModel from KIMI_MODEL_NAME) kept serving stale cached
values after the env changed. get() now derives every non-memory
domain from the fresh env-free base, matching getAll().
* test(config): drive the get() overlay freshness test with an inline overlay
The previous version imported the model env overlay to activate it, which
the CI runners failed to resolve from this test file (both tsgo and
vitest, while the same specifier resolves elsewhere — not reproducible
locally). An inline ConfigEffectiveOverlay double exercises the same
ConfigService contract with a tighter seam and no module dependency.
* fix(config): preserve unknown fields on full strip and clone nested env targets
Two follow-ups from review:
- stripEnvBoundFields cleared the raw section whenever the stripped
result was empty, so an env echo write could drop unknown
forward-compatible fields from the TOML table. An emptied section now
keeps its raw table while the env-free base still holds other fields,
and is cleared only when nothing remains (defaults keep applying).
- applyEnvBindings reused nested child objects in place, so a nested
env binding on a persistable key would mutate the env-free validated
base and serve stale values after the env var is removed. Children
are now cloned before descending.
* fix(config): keep the env-free base when a strip leaves nothing to persist
Returning {} for a fully stripped write stored the empty object into the
raw layer while the TOML table survived via rawSnake, so the bases
diverged; a second echo write then saw an empty base, cleared the
section, and deleted the table — dropping unknown forward-compatible
fields. When nothing persistable remains, the write is now a no-op for
the section (the env-free base is kept as-is), and the section is
cleared only when the base is empty.
* fix(config): revalidate stripped results so restored raw values never persist
A strip may restore on-disk values from the unvalidated raw base (e.g.
an env-masked invalid field), smuggling them past the merge-time
validation into the stored config: the section would then fail the next
buildValidated pass, dropping accompanying valid edits from the runtime
while the invalid value stayed persisted. set() now revalidates the
stripped result — discarding the parse output so unknown fields survive
— and rejects the write instead, matching replace().
|
||
|
|
a3699dd6aa
|
feat(kap-server): expose per-tool active state in GET /api/v1/tools (#2005)
* feat(kap-server): expose per-tool active state in GET /api/v1/tools * Update tools-list-active-flag.md Signed-off-by: 7Sageer <7sageer@djwcb.cn> --------- Signed-off-by: 7Sageer <7sageer@djwcb.cn> |
||
|
|
d67a2003ab
|
feat(kap-server): add GET /api/v1/fs:content endpoint for host files (#2012)
* feat(kap-server): add GET /api/v1/fs:content endpoint for host files - serve any host file by absolute path as raw content with Content-Type, ETag caching, and single-range support - extract shared file metadata helpers (binary detection, line counting, etag, mime/language guessing) into agent-core-v2 _base/utils/fileMeta - extract pickHeader/parseRangeHeader into kap-server lib/httpRange for reuse across download/content routes * fix(kap-server): resolve lint and typecheck errors in fs:content route Return the reply.send(stream) result through the handler promise instead of using return-await, matching the session fs download route pattern. * fix(kap-server): reject non-regular files in fs:content Device nodes, FIFOs, sockets, and zero-size virtual files (/proc, /sys) would otherwise hang the request or stream unbounded data. Addresses review feedback; also folds fileMeta symbol comments into the header block per the agent-core-v2 header-only comment convention. |
||
|
|
74da87a457
|
feat(kap-server): broadcast agent.created/agent.disposed session events (#1997)
* feat(kap-server): broadcast agent.created/agent.disposed session events - emit durable agent.created / agent.disposed facts from the SessionEventBroadcaster lifecycle callbacks, ahead of the agent's own events, and let them bypass per-subscription agent allowlists - add the agent.created / agent.disposed wire types and zod schemas - stamp disposedAt on the transcript roster entry via TranscriptStore.markDisposed so REST consumers can tell a dead agent from a live one * chore: add changeset for agent lifecycle events |
||
|
|
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>
|
||
|
|
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 |
||
|
|
efacf0452d
|
ci: release packages (#1946)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
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
|
||
|
|
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 |
||
|
|
56ba8e0196
|
fix(server): allow inline styles in CSP so web math renders on non-loopback binds (#1847)
* fix(server): allow inline styles in CSP so web math renders on non-loopback binds The security CSP fell back to default-src 'self' for styles, which strips the inline style attributes that KaTeX (injected via innerHTML) uses for all glyph positioning — formulas collapsed into overlapping characters on any non-loopback-served web UI. Shiki highlighting and Mermaid diagrams hit the same mechanism. Add style-src 'self' 'unsafe-inline'; scripts remain strictly restricted. * test(server): assert the effective script-src in the CSP regression test A negative substring check only rejects one exact string: default-src gaining 'unsafe-inline' (inline <script> allowed via fallback) or an explicit script-src 'unsafe-inline' would both slip through. Parse the directives and assert the effective script policy (script-src, falling back to default-src) excludes 'unsafe-inline'/'unsafe-eval'/data:. |
||
|
|
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. |
||
|
|
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 |
||
|
|
319001ae5c
|
refactor: remove git detection from workspace wire and folder browse (#1787) | ||
|
|
09e855401b
|
fix: report task stop reasons to the model (#1781)
* fix: report task stop reasons to the model * chore: add task stop reason changeset |
||
|
|
4cffd732c2
|
feat(klient): contract-driven facade with http/ipc/memory transports (#1768)
* feat(klient): contract-driven facade with http/ipc/memory transports - add zod-validated contract sections (global/session/agent) under src/contract and a facade exposing global.*, session(id).*, agent(id).* - select transport once at creation via subpath entries (@moonshot-ai/klient/http|ipc|memory); drop legacy channel/client/ httpChannel/wsChannel/wsKlient/proxy implementations - absorb packages/server-e2e into packages/klient test/e2e suites (dual-backend, legacy v1, v2 wire) and remove the server-e2e workspace - expose model registry and catalog services on kap-server v2 RPC surface * fix(klient): derive session status from agentActivityView The engine retired its sessionActivity service in #1751 (session busy is now derived from agent activity views), but the facade still called the deleted wire channel and imported the deleted engine module, breaking typecheck and every klient suite at import time. - drop the sessionActivity contract/registry entries and mirror the agentActivityView service instead (agent scope) - compose session status() client-side from the pending interaction lists and each agent's agentActivityView, keeping the retired service's precedence and typing SessionStatus locally in the facade - replace the deleted-channel call in the v2 smoke suite with a sessionInteractionService probe - fix the legacy image-file suite to wait with the harness's waitForSessionBusy |
||
|
|
78967e283d
|
refactor(model-catalog): drop WS catalog-changed event; refresh on picker open (#1772)
- kap-server: remove event.model_catalog.changed from the v1 WS union, broadcaster forwarding, and the zod event registry - web: refresh all providers (POST /providers:refresh) before loading models when the model picker opens, replacing the event-driven refresh - keep domain publishers, the protocol schema, and the web receiver for compatibility with older daemons |
||
|
|
df75a0f5c2
|
refactor(agent-core-v2): derive session busy from agent activity (#1751) | ||
|
|
d8ddabb605
|
fix(kap-server): close auth bypass via percent-encoded API paths (#1753)
* fix(kap-server): fail closed on percent-encoded API paths in auth bypass
The auth hook checked the raw, still percent-encoded request URL against
its bypass policy, while find-my-way matches routes against the decoded
path. A raw /%61pi/v1/... URL therefore skipped the bearer-token check
yet still reached the /api/... handlers, allowing unauthenticated access
to every API route.
Decode the request path the same way the router does before matching,
and fail closed when the path cannot be decoded. Add tests covering
encoded /api/ paths, encoded meta documents, the encoded healthz probe,
and unaffected non-API bypasses.
* fix(agent-core-v2): make session fs path confinement symlink-aware
SessionFsService confined paths only lexically, so a symlink planted
inside the workspace could steer read, list, stat, mkdir, resolvePath
and resolveDownload to host files outside the session directory.
- add IHostFileSystem.realpath (Node fs.realpath semantics) and
implement it in the node-local HostFileSystem
- resolveWithin now re-verifies each candidate through realpath of the
longest existing prefix (so not-yet-created paths still work) and
rejects paths escaping the canonicalized workspace roots, which are
resolved once and cached
- cover symlink escapes for every fs entry point plus kap-server
read/download e2e; in-workspace symlink targets remain allowed
* fix(agent-core-v2): accept workspace roots given through a symlink
WorkspaceRegistryService.createOrTouch probes the root with the
lstat-based IHostFileSystem.stat, so a root given as a symlink to a
directory reported isDirectory=false and session creation was rejected
with fs.path_not_found ("not a directory").
Re-check a non-directory root through IHostFileSystem.realpath before
failing, while keeping the workspace identity lexical (v1 deliberately
never realpaths the root either). Covered by a unit test for a
symlink-form root and a kap-server e2e that creates a session with a
symlinked cwd and reads a file through it.
|
||
|
|
4f99114342
|
refactor(kap-server): drop the @moonshot-ai/protocol dependency (#1755) | ||
|
|
0b790cdc05
|
feat(web): allow attaching any file type and fix CSP on non-loopback binds (#1731)
* feat(web): allow attaching any file type in chat - Composer, paste, and drop no longer filter out non-media files; arbitrary files upload as generic icon chips and are submitted as file content parts - kap-server materializes file parts into the session's attachments dir and replaces them with a path reference, so the model opens the file with the Read tool on demand instead of receiving inline bytes - Images rejected by the provider format gate (SVG, AVIF, ...) are now persisted and referenced by path instead of being dropped with a notice; uploaded file names are sanitized before hitting disk * fix(server): stop CSP from blocking web bootstrap script and fonts - Move the anti-FOUC bootstrap from an inline <script> in index.html to /boot.js: CSP 'self' never covers inline scripts, while a classic same-origin script keeps the same render-blocking timing - Allow data: in font-src — KaTeX and the Inter / JetBrains Mono Variable fonts ship @font-face data URIs in their distributed CSS - Set explicit form-action, base-uri, and frame-ancestors, which do not fall back to default-src - Add a regression test asserting the served index.html carries no inline scripts or inline event handlers * fix(web): normalize empty attachment MIME so extensionless files submit Files with an empty File.type (Makefile, LICENSE, other extensionless or unknown types) stored mediaType: '' on the chip, and the submit fallback used ?? which does not catch empty strings — the wire schema requires a non-empty media_type, so the prompt was rejected. Normalize to application/octet-stream at attachment creation, adopt the server-recorded MIME after upload completes, and make both submit mappings use || so reloaded chips with '' are covered too. * feat(web): render all user-turn attachments as chips * feat(web): attach files by dropping them anywhere in the window * refactor(web): share one attachment chip between composer and chat bubble * fix(web): neutral attachment chips, paperclip attach icon, and clickable file chips * fix(web): drop the extension badge from attachment chips * fix(web): use the tabler paperclip for the attach button * fix(web): whitelist attachment previews, reject active document types Clicking a file chip navigated a new tab to a blob: URL of the uploaded bytes whenever the type looked browser-renderable. blob: inherits the web origin, so a text/html or image/svg+xml attachment would execute same-origin script with the daemon credential (localStorage) and a live window.opener. Preview is now restricted to inert types (pdf, non-SVG images, video, audio, non-HTML text), the blob is re-wrapped with the whitelisted MIME instead of trusting the recorded content-type, and window.opener is severed. Non-whitelisted types no longer silently download: the chip reports 'unsupported' and the pane shows a transient hint. * fix(web): recover file attachment chips from the server notice The kap-server prompt route replaces file parts with an "Attached file …" text notice before enqueueing, so after any snapshot resync the attachment chip degraded into raw notice text leaking the absolute server path — unlike image/video uploads, which already recover their chip from the <video|image path> tag. Parse the notice the same way: the materialized basename carries the file id, so the chip becomes clickable again (and editable back into the composer); inline-base64 notices (content-hash named, no file id) still collapse into a non-clickable chip instead of raw text. The notice wording is now a client/server contract — flagged on buildAttachedFileNotice. * fix(web): preserve UUID file ids when rebuilding attachment chips * fix(web): skip unresendable file chips when loading attachments for edit --------- Co-authored-by: qer <wbxl2000@outlook.com> |
||
|
|
27236bd75f
|
refactor(agent-core-v2): drop the @moonshot-ai/protocol dependency (#1745) | ||
|
|
8a3f1ffa6f
|
fix(kap-server): derive session title from first skill slash command (#1741) | ||
|
|
b24a347e20
|
fix(kap-server): carry the live subagent roster in the session snapshot (#1719)
* fix(kap-server): carry the live subagent roster in the session snapshot * fix(kap-server): clear the subagent roster on the next main turn start * fix(kap-server): exclude background subagents from the snapshot roster * fix(kap-server): finalize live roster entries when the main turn aborts * fix(kap-server): drop roster entries when foreground subagents detach * fix(web): expand the swarm card by default while subagents are running * docs(kap-server): qualify the roster-clearing durability claim |
||
|
|
286d3e7aca
|
feat: add check-kimi-code-docs builtin skill (#1727)
* feat(agent-core): add check-kimi-code-docs builtin skill * feat(agent-core-v2): add check-kimi-code-docs builtin skill * docs: list check-kimi-code-docs in builtin skill commands * chore: add changeset for check-kimi-code-docs skill |
||
|
|
7de218a909
|
fix(kimi-web): resume paused goals (#1693)
Some checks are pending
Release / Release (push) Waiting to run
CI / typecheck (push) Waiting to run
CI / test (3) (push) Waiting to run
CI / test (4) (push) Waiting to run
CI / test (5) (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / build (push) Waiting to run
CI / test (1) (push) Waiting to run
CI / test (2) (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
Release / Deploy docs (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
Release / Desktop release artifact (push) Blocked by required conditions
* fix(kimi-web): resume paused goals * fix(agent-core-v2): defer paused goal continuation |
||
|
|
2bf009fe27
|
fix(agent-core-v2): reject subagent goals (#1697)
* fix(agent-core-v2): reject subagent goals * fix(kap-server): guard reflected subagent goals |
||
|
|
26d499bca7
|
refactor(agent-core-v2): consolidate wire services (#1680) |