mirror of
https://github.com/MoonshotAI/kimi-code.git
synced 2026-08-02 13:04:50 +00:00
18 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
527d485d92
|
feat: add global default MCP server timeout configs (#2065)
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
* feat: add global default MCP server startup timeout config Add a `[mcp] startup_timeout_ms` config.toml section with a `KIMI_MCP_STARTUP_TIMEOUT_MS` env override as the global default MCP server connection (startup + tool discovery) timeout. Precedence: per-server `startupTimeoutMs` in mcp.json > env var > config.toml > built-in 30s default. * feat: add global default MCP tool call timeout config Extend the `[mcp]` section with `tool_timeout_ms` and the `KIMI_MCP_TOOL_TIMEOUT_MS` env override as the global default for single MCP tool calls, mirroring the startup timeout: a per-server `toolTimeoutMs` in mcp.json still wins, and unset entries fall back to the SDK built-in 60s default. * chore: shorten the mcp timeouts changeset * feat(agent-core): add global default MCP server timeout configs Port the `[mcp]` section (`startup_timeout_ms` / `tool_timeout_ms`) and the `KIMI_MCP_STARTUP_TIMEOUT_MS` / `KIMI_MCP_TOOL_TIMEOUT_MS` env overrides to agent-core (v1), mirroring the v2 semantics: per-server fields in mcp.json > env vars > config.toml > built-in defaults. The v1 TOML loader gains explicit `mcp` read/write mappings, and both connection-manager construction sites (Session, testGlobalMcpServer RPC) pass the resolved defaults through. * fix(agent-core): validate and apply MCP timeout defaults * fix: propagate MCP startup timeout to SDK requests * refactor(agent-core-v2): resolve MCP default timeouts at connect time Keep the session connection manager synchronously lazy instead of gating its existence on config readiness: resolveDefaultTimeouts is read from the mcp config section at each (re)connect, so AgentMcpService's eager construction stays unconditionally safe and reconnects pick up changed preferences. The initial connect still awaits config.ready for a deterministic snapshot. Also restore the ISessionMcpService method docs, bump the changeset to minor, and fix the v1 env-parse comment. * chore(agent-core-v2): regenerate config manifest for the mcp section * Add global default MCP server timeouts configuration Specify the new global default MCP server timeouts in both the config file and environment variables. Signed-off-by: 7Sageer <sag77r@hotmail.com> --------- Signed-off-by: 7Sageer <sag77r@hotmail.com> |
||
|
|
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> |
||
|
|
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 |
||
|
|
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 |
||
|
|
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
|
||
|
|
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) | ||
|
|
072eed476b
|
fix(agent-core-v2): keep context size readings on the measured path (#1782)
* fix(agent-core-v2): keep context size readings on the measured path The step fold creates the assistant message in the context before the exchange finishes (a skeleton at step.begin, filled by content.part folds during streaming), and the input array llmRequester passes to contextSize.measured() is that same live array — it already includes the output. Taking input.length + output.length therefore counted the folded output twice, storing a measured prefix length one past the live context. The inflated length permanently failed get()'s measured fast path, so reads silently fell back to per-message estimates (e.g. ~50 tokens shown for a ~29k-token "hi"). Take the live context length as the measured prefix instead (input and context are identical under the identity guard), and clamp the measured prefix to the context length in get() so a bad record can never knock reads off the measured path again. Add contextSize tests driving real turns that assert the wire model, get(), and rpc getContext against the exchange totals. * feat(klient): add context-usage example tracing a fresh session Polls agent.getContext()/agent.getUsage() and streams agent events for a new session after one "hi" against a real server, printing a timeline of when the context/token readings move, plus a final consistency check comparing the measured tokenCount to cumulative usage. Model seeding is optional via KIMI_EXAMPLE_* env; the server token resolves from <kimi-home>/server.token like the v2 e2e helpers. * chore: add changeset for the context size fix |
||
|
|
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 |
||
|
|
a160915596
|
test(klient): add real-server smoke coverage (#1713)
Add transport and persisted-session smoke scripts for HTTP, WebSocket, and scoped service calls. Type-check all examples and document remote-server usage and side effects. |
||
|
|
2383137f3e
|
ci: release packages (#1583)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
1c85f94472
|
feat(agent-core-v2): gate image formats and add media recovery resends (#1626)
* feat(kap-server): drop WS heartbeat; never terminate idle connections
- remove ping interval / pong timeout / socket.terminate() from both the
v1 (WsConnectionV1) and v2 (WsConnection) WebSocket connections
- v2 protocol: drop pong from the client message schema, remove PingMessage
and ReadyMessage.heartbeatMs; the ready frame is now bare { type: 'ready' }
- v1 protocol: remove buildPing/PingFrame and ServerHelloPayload.heartbeat_ms;
server_hello no longer advertises a heartbeat
- drop pingIntervalMs/pongTimeoutMs options from registerWs/registerWsV1
* feat(agent-core-v2): gate image formats and add media-stripped resend
- add image-format-policy as the single source of truth for the
provider-accepted image MIME set (PNG/JPEG/GIF/WebP), with MIME
normalization, data-URL parsing, byte sniffing, and refusal notices
- enforce the format gate at every ingestion point: ReadMediaFile refuses
unsupported formats with per-OS conversion guidance, MCP tool results and
prompt step requests drop them for a text notice, and kap-server prompt
routes gate inline, uploaded, and remote-URL images on the sniffed bytes
- resend once with every media part replaced by a text marker when the
provider rejects an image's format, and keep later steps of the same turn
on the media-stripped projection (v1 parity)
- commit the WebP decoder wasm as a base64 module for the bundled CLI, with
a regenerate script
* feat(agent-core-v2): add media-degraded 413 resend and WebP re-encoding
- resend once with the media-degraded projection after an HTTP 413
body-size rejection: all but the two most recent media parts are replaced
by text markers, and later steps of the turn stay degraded (stripped
still wins over degraded)
- generalize stripAllMediaParts into degradeOlderMediaParts; the
media-stripped resend is now the keepRecent=0 case
- re-encode non-animated WebP through the wasm decoder and the PNG/JPEG
ladder instead of passing oversized WebP through (animated WebP still
passes through whole)
- stop lossless PNG rescaling at a 1000px floor and switch to the JPEG
ladder below it, so small byte budgets stay readable
- add the @jsquash/webp dependency
* feat(agent-core-v2): add flag-gated fault injection for recovery testing
- add the faultInjection domain: a one-shot arm/take latch that raises a
deterministic provider failure (HTTP 413 body-size or image-format 400)
before the provider is contacted, so the media-degraded / media-stripped
recovery resends can be exercised end-to-end against a real provider
- gate arming behind the new fault-injection experimental flag
(KIMI_CODE_EXPERIMENTAL_FAULT_INJECTION), off by default
- expose IAgentPromptService and IFaultInjectionService over the kap-server
/api/v2 RPC channel
- add a klient example that drives the REST ingestion gate and both
recovery resends against a live server
|
||
|
|
83e175399f
|
feat: auto-background timed-out foreground bash commands (#1591)
* feat: auto-background timed-out foreground bash commands * fix: discourage blocking TaskOutput waits on background tasks * test: avoid unsafe string conversion in bash timeout test * fix: align bash timeout description with auto-background opt-out * feat(agent-core-v2): auto-background timed-out bash commands - detach timed-out foreground Bash tasks and re-arm the background deadline - align TaskOutput guidance with non-blocking background task handling - add klient SEA end-to-end coverage for the v2 server * fix(klient): clean up lint errors in auto-background e2e example --------- Co-authored-by: haozhe.yang <yanghaozhe@moonshot.ai> |
||
|
|
bc8eb1e417
|
chore: drop #/ import array fallbacks and custom resolution plugins (#1594) | ||
|
|
ceb158dc54
|
feat(v2): land agent-core-v2 engine and kap-server behind experimental flag (#1441)
Some checks are pending
CI / typecheck (push) Waiting to run
CI / test-pi-tui (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
Release / Release (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
CI / test-windows (push) Waiting to run
CI / lint (push) Waiting to run
CI / build (push) Waiting to run
CI / test (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Release / Desktop release artifact (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions
* fix: adapt grep tool to agent-core-v2 * fix(agent-core-v2): enrich PATH from the user's login shell at startup - port probeLoginShellPath/mergeLoginShellPath/applyLoginShellPath into _base/execEnv/loginShellPath.ts as a pure helper (no DI) - export execFileText from environmentProbe for reuse by the probe - run applyLoginShellPathFromNode concurrently with the host probe in HostEnvironmentService, mirroring kaos LocalKaos.create() Aligns agent-core-v2 with kaos |