Commit graph

744 commits

Author SHA1 Message Date
qer
2f795ccac7 test(transcript): move the contract e2e timeout to the describe arg (jest lint) 2026-08-21 14:21:34 +08:00
qer
11f9cd04f4 fix(transcript): settle the spawned agent row when its lifecycle redirects to the task row 2026-08-21 02:41:11 +08:00
qer
7daf99e20a test(agent-core-v2): re-record event stream snapshots with prompt.accepted published 2026-08-21 02:41:11 +08:00
qer
eae29201d7 fix(transcript): guard the prompt backfill against missing services; align stream expectations with prompt.accepted on the bus 2026-08-21 02:41:11 +08:00
qer
281ebf8114 test(transcript): add the contract-level e2e covering every entity the client renders from 2026-08-21 02:41:11 +08:00
qer
2ea5f794de fix(agent-core-v2): publish prompt.accepted on the event bus 2026-08-21 02:41:11 +08:00
qer
3e5976ecfd fix(transcript): include the prompts entity in the REST transcript response 2026-08-21 02:41:11 +08:00
qer
d86f3e3ac0 fix(transcript): reconcile liveness and the prompt queue at backfill from the live loop state 2026-08-21 02:41:11 +08:00
qer
4733e9e593 fix(transcript): populate the prompts entity from prompt.accepted/queued engine events 2026-08-21 02:41:11 +08:00
qer
609d849596 fix(transcript): mirror turn liveness into meta.activity, live and cold 2026-08-21 02:41:11 +08:00
qer
57ee405347 feat(transcript): carry subagent model and thinking effort on task entities 2026-08-21 02:41:11 +08:00
qer
ea6d64d12a fix(transcript): derive task-turn boundaries from durable turn.prompt records 2026-08-21 02:41:11 +08:00
qer
7c36d456ea fix(transcript): keep other tasks' notifications in task-origin turns 2026-08-21 02:41:11 +08:00
qer
bbb2559160 fix(transcript): attach mid-turn task notifications to the following step, cold and live 2026-08-21 02:41:11 +08:00
qer
b43e971eae fix(transcript): drop folded notifications without a persisted step, truncate only at output blocks 2026-08-21 02:41:11 +08:00
qer
163ec98e75 fix(transcript): truncate folded notification text at the first child-block tag, not just the tag lines 2026-08-21 02:41:11 +08:00
qer
9905e3bee4 fix(transcript): stop folded notification text before child blocks, preserve legacy background_task turns absent from the boundary set 2026-08-21 02:41:11 +08:00
qer
2f2b2c5cbb fix(transcript): normalize folded notification text to the live title/body form 2026-08-21 02:41:11 +08:00
qer
04255a7aa7 fix(transcript): fold consecutive task notifications into the same turn 2026-08-21 02:41:11 +08:00
qer
0ccda12a16 fix(transcript): collect background_task turn origins too, and fall back when the wire has no turn.started records 2026-08-21 02:41:11 +08:00
qer
599d0d90b1 fix(transcript): key the notification fold on persisted task-turn boundaries, not the previous message role 2026-08-21 02:41:11 +08:00
qer
d9459eaf79 fix(transcript): fold mid-turn task notifications into the current turn on cold rebuild 2026-08-21 02:41:10 +08:00
wszqkzqk
30e7f62d2c
fix(kaos): resolve Git Bash POSIX paths for file tools on Windows (#2200)
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-vscode-legacy (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 a shell path bridge that translates between win32 paths and the
MSYS2/Git Bash path dialect. File tools resolve model-supplied paths
through it before canonicalization and workspace checks: drive-letter
forms translate lexically, root-relative paths resolve via cygpath -w
with per-segment caching, and every failure mode falls back to the
previous behavior.

Fixes #2199
2026-08-20 22:42:16 +08:00
Haozhe
381142aff1
fix(agent-core-v2): let session archive proceed after a failed resume (#3139)
A failed resume is cached by SessionManager and rethrown from
whenResumeSettled, so archiving a session whose workspace is gone
failed with the stale resume error even though cold archive only
rewrites session metadata. Swallow the settle failure: still wait for
an in-flight resume before the live/cold classification, but fall
through to the cold metadata path after a failed one.
2026-08-20 22:40:27 +08:00
7Sageer
f6736d7c0d
feat(agent-core-v2): add a fork parameter to the Agent tool (#3007)
* feat(agent-core-v2): add a fork parameter to the Agent tool

Spawning with fork: true starts the subagent from a one-time snapshot of
the calling agent's completed conversation history — same profile, tool
set, and model — instead of zero context. The seed trims the trailing
open tool exchange (the in-flight Agent call itself) before appending
into the child's context memory, and the first prompt carries an
inheritance notice framing the seeded history as reference material.

Fork rejects resume, a different subagent_type, or a model override as
tool errors, and skips the subagents allowlist since a self-inheritance
is not a delegation.

* fix(agent-core-v2): bind the stale-todo reminder only into the main agent

Subagents share the session todo list but no longer receive the
stale-todo nudge — the reminder injector now registers only on the main
agent, so delegated and forked agents are not prompted to maintain a
list they do not own.

* fix(agent-core-v2): inherit the caller's live binding and label fork launches correctly

Review follow-ups for the Agent tool fork mode:

- overlay the caller's live profile.data() via applyBindingSnapshot after
  the catalog re-bind, so ephemeral addActiveTool deltas, the rendered
  system prompt, and runtime model/subagents updates survive the fork;
  skip the profile prompt prefix since the caller's prefixed first
  prompt is already part of the seeded history
- resolve the fork activity label and approval-rule subject from the
  caller's own profile instead of falling back to the default subagent
  type, so an Agent(<other profile>) rule cannot approve a fork

* fix(agent-core-v2): close inherited in-flight tool calls instead of trimming them

Fork seeding now answers the source's trailing open tool calls with a
synthetic in-flight result instead of cutting the whole trailing
exchange: the seeded history stays protocol-valid, keeps the source's
final step visible as reference, and no longer confuses side-question
(btw) agents forked while the main agent is mid-turn. The close helper
is shared by the Agent tool fork and IAgentLifecycleService.fork.

Fork launches also stop requiring the caller's profile to still exist
in the session catalog: the child is created unbound and overlaid with
the caller's live binding snapshot, matching the lifecycle fork path,
and now records forkedFrom provenance.

* refactor(agent-core-v2): route Agent tool forks through agentLifecycle.fork

* feat(agent-core-v2): add a fork parameter to the AgentSwarm tool

* fix(agent-core-v2): seal partial assistant forks

* fix(agent-core-v2): align fork parameter descriptions

* fix(agent-core-v2): drop the main-only registration gate from goal tools

* fix(agent-core-v2): disclose dates via reminders to keep the system prompt byte-stable

* docs: condense the fork changesets to single sentences

* docs(agent-core-v2): frame the tool-contribution when gate as a fork parity trade-off

* test(agent-core-v2): plug fork coverage gaps and decouple swarm tests from spawn internals

* docs(agent-core-v2): keep the when-gate guidance in the contribution JSDoc only

* fix(agent-core-v2): contribute cron tools to every agent for fork prefix-cache parity

CronCreate/CronList/CronDelete were registered directly into the main
agent's tool registry by SessionCronServiceImpl, bypassing the
AgentToolContribution seam and keying on per-agent identity — so a forked
agent rebuilt a tool surface three tools shorter than its caller and the
inherited prompt prefix missed the cache.

Register the three tools through registerAgentToolService like the goal
tools do (no when gate, identical surface for every agent) and enforce
the main-agent restriction at execution time instead. Also fall back to
DEFAULT_CRON_CONFIG when the config section is absent, since the service
can now be constructed after the main agent exists.

* feat(agent-core-v2): track the fork parameter in the subagent_created event

* fix(agent-core-v2): gate tower orchestration tools at execution time

TowerInit/TowerPlan/TowerSpawn/TowerMerge/TowerTeardown were contributed
with a when predicate keyed on agentId === 'main', so a forked agent
rebuilt a tool surface missing TowerInit (always present for the default
profile) plus the rest of the tower set once it was enabled — breaking
prompt prefix-cache parity with the caller.

Contribute the tools with no when gate (profile policy still controls
visibility) and reject non-main callers at execution time instead.

* test(agent-core-v2): expect the fork field in the subagent_created mirror assertion

* test(agent-core-v2): cover fork subagent first-request prefix parity

* refactor(agent-core-v2): share the main-agent-only tool refusal across cron and goal tools

Goal tools rejected subagent callers by throwing GOAL_UNSUPPORTED_AGENT
from the service, which the executor wrapped as a resolution failure;
cron tools returned a clean refusal but each tool open-coded the same
identity check. Centralize the check and both messages in
agent/tools/mainAgentOnly.ts and use it from all seven tools, keeping
AgentGoalService.assertSupportedAgent as the coded boundary for RPC and
SDK callers.

* refactor(agent-core-v2): keep the goal main-agent gate at the tool layer only

* fix(agent-core-v2): preserve the fork tool surface when inheriting user tools

* Revert "refactor(agent-core-v2): keep the goal main-agent gate at the tool layer only"

This reverts commit fc09a8fa32.

* test(agent-core-v2): complete fork lifecycle stub

* Delete .changeset/btw-inflight-tool-calls.md

Signed-off-by: 7Sageer <sag77r@hotmail.com>

* Delete .changeset/todo-reminder-main-only.md

Signed-off-by: 7Sageer <sag77r@hotmail.com>

* Delete .changeset/swarm-fork-context.md

Signed-off-by: 7Sageer <sag77r@hotmail.com>

* Add optional 'fork' parameter to subagent tools

Signed-off-by: 7Sageer <sag77r@hotmail.com>

* docs(agent-core-v2): drop the fork JSDoc comments

* feat(agent-core-v2): add prompt_cache_probe telemetry for forked agents

* feat(agent-core-v2): gate the subagent fork parameter behind an experimental flag

---------

Signed-off-by: 7Sageer <sag77r@hotmail.com>
2026-08-20 21:50:44 +08:00
github-actions[bot]
0999454bdc
ci: release packages (#3074)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-20 21:11:45 +08:00
Haozhe
3b69765cf3
fix(agent-core-v2): remove duplicate launch-time subagent.spawned (#3134) 2026-08-20 20:55:33 +08:00
Haozhe
fc0f275dd4
refactor(agent-core-v2): extract goal domain into a self-contained feature (#3130) 2026-08-20 19:52:57 +08:00
7Sageer
3899079a2c
fix(agent-core-v2): guard config persistence against lossy writes (#3121)
* fix(agent-core-v2): guard config persistence against lossy writes

- A failed load no longer clears the in-memory snapshot: the service keeps
  the last-known-good config, reports an error diagnostic, and taints.
  set/replace/replaceSections on the persisted layer then fail fast with
  Error2(config.persist_blocked) instead of erasing the file; memory-layer
  overrides stay available, and a successful reload clears the taint.
- persistDomains is now read-modify-write: the file is re-read and only the
  domains being written are applied on top of current disk content, so
  external edits are merged instead of clobbered, and an external delete is
  honored instead of resurrected.
- External changes absorbed at persist time trigger a full reload so change
  events fire for domains the writer did not touch.

* fix(agent-core-v2): rebase set() merges onto re-read config state

set(domain, patch) now merges the patch against the freshly re-read file
content and refreshes the in-memory snapshot from the same read, so external
edits to the same section survive a concurrent write instead of being
overwritten by the stale in-memory copy.

* fix(protocol): register config.persist_blocked in KimiErrorCode

Add the new code to the KimiErrorCode union and kimiErrorCodeSchema so the
persist-refusal error payload passes protocol validation across RPC
boundaries.

* fix(agent-core-v2): compute every config write against the re-read file

Move strip/merge/validate for set/replace/replaceSections into the persist
rebase callback so each write is derived from the file content re-read at
persist time. Overlay strip handlers (e.g. the KIMI_MODEL_* mask restoring
default_model) now read the fresh snapshot instead of the stale in-memory
one, and the unconditional snapshot sync makes the separate
absorbed-external reload redundant.

* fix(agent-core-v2): build defaults when the initial config load fails

A failed first load has no last-known-good state worth preserving, so fall
through with an empty document: registered section defaults are still
validated and applied (consumers of defaulted sections keep working), while
the taint keeps blocking persisted writes until a reload succeeds. Only
reload failures preserve the previous in-memory state.

* fix(agent-core-v2): stage re-read config snapshots until the write succeeds

Build the rebased raw/rawSnake snapshots in locals and publish them only
after the rebase and documentStore.set both succeed, so a validation error
or a storage failure cannot leave userValue and effective pointing at
different snapshots. stripEnv now takes the staged snapshots explicitly.
2026-08-20 18:04:59 +08:00
Haozhe
3fdce983f8
fix: drain in-flight persistence and log writes on session close and shutdown (#3122) 2026-08-20 17:19:20 +08:00
Haozhe
a09d904140
refactor(agent-core-v2): migrate agent domains to model-as-container architecture (#3103) 2026-08-20 16:06:59 +08:00
Haozhe
15da84606a
feat(kap-server): add workspace-grouped sessions view and lifecycle events (#3114)
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-vscode-legacy (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 / 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
Nix Build / Check flake.nix workspace sync (push) Waiting to run
GET /api/v2/sessions gains view=by_workspace: one request returns every
workspace with a matching session, each carrying its first group.page_size
sessions under the requested sort plus the workspace's full matching total,
with group-level page_token pagination (40922 on condition drift). Groups
key on the alias-canonical workspace id, so legacy split buckets of one
physical directory merge into a single group, matching the v1 alias
semantics. meta.has_prompt filters sessions by prompt presence (the v1
exclude_empty equivalent) in both views. The flat view and v1 routes stay
byte-compatible.

The global WS stream now fans out event.session.archived (live and cold
paths; payload carries the session id and workspace_id) and
event.workspace.created/updated/deleted, published by the core
IWorkspaceService on every mutation path including the implicit
createOrTouch on session creation.

kimi-inspect consumes the grouped projection as a single-column
workspace/session tree in the chat view; the session pane merges into the
right dock as the Session tab. The server API reference (en + zh) documents
the new parameters, the grouped response, and the new events.
2026-08-20 13:45:38 +08:00
liruifengv
f1208c8d72
feat(agent-core-v2): rework the title generation excerpts (#3109)
* feat(agent-core-v2): rework the title generation excerpts

- Rebalance the excerpt budgets toward the user's prompts (400 chars
  each) and trim the assistant segments (300) so titles follow the
  user's task instead of narrating the assistant's reply.
- Cap each prompt in the default user_prompts excerpt so one long
  paste no longer starves the remaining prompts.
- Compose the digest excerpt from the full conversation arc: every
  natural-language user prompt in the live window paired with its own
  turn's final assistant text, interleaved chronologically, with
  per-segment caps and a 3000-char total budget (middle turns elided).

* chore: scope the title changeset to agent-core-v2

* fix(agent-core-v2): dedupe digest prompts and elide whole turns

- Drop the redundant `| undefined` from the optional
  TitleDigestTurn.assistant per the monorepo optional-property
  convention.
- Deduplicate user messages by id when constructing digest turns, so a
  prompt already in the context and still active in the queue does not
  produce two turns.
- Elide the over-budget digest at whole-turn granularity, keeping each
  assistant line paired with its own user line.

* docs(agent-core-v2): describe the full-arc digest in the SessionTitleSource contract
2026-08-20 12:25:51 +08:00
Kimi Agent
d96b4a0149
fix: fail fast on provider-filtered empty responses (#3101)
* fix: fail fast on provider-filtered empty responses

An APIEmptyResponseError carrying finishReason 'filtered' (OpenAI
content_filter, Anthropic refusal) is deterministic: replaying the same
request re-triggers the provider safety filter. Both isRetryableGenerateError
implementations (kosong, agent-core-v2) treated every empty response as
retryable, so step retry replayed the doomed request the full 10 attempts
before the filter notice surfaced. Return non-retryable for filtered empty
responses in both engines; the error already carries the provider.filtered
code, so the turn fails immediately with the existing filter notice.

* fix: skip the compaction shrink-retry for filtered empty responses

Both full-compaction loops routed every APIEmptyResponseError into the
shrink-and-continue branch before isRetryableGenerateError was consulted,
so a filtered response was retried with shrinking input instead of failing
fast. Exclude finishReason 'filtered' from the shrink branch in both
engines; it now falls through to the retryability check and throws
immediately. Add end-to-end tests (real kosong generate over a filtered
think-only stream) asserting a single attempt with the history untouched.

---------

Co-authored-by: kimi-agent-bot <kimi-agent-bot@users.noreply.github.com>
2026-08-20 11:55:26 +08:00
liruifengv
3d7762003a
feat(kimi-code): support two OAuth login endpoints (#2862)
* feat(kimi-code): add China/International region selection for OAuth login

- Add region profiles (cn/overseas) and resolver in @moonshot-ai/kimi-code-oauth:
  env override → persisted login host → install-channel marker → default cn
- /login now offers Kimi Code (China) / Kimi Code (International); the CLI
  login entries (kimi login, kimi acp --login) accept --region cn|overseas
- Update/plugin/site/telemetry endpoints derive from the selected region;
  plugin trust list covers both .com and .ai hosts
- kap-server: POST /oauth/login accepts an optional region; new GET /oauth/region

* fix(oauth): keep an explicit default-slot login ahead of the install marker

A China login persists no oauthHost (the default credential slot carries
no host trace), so after switching back from International the resolver
fell through to a stale overseas install marker. Treat a persisted
default-slot oauth ref (key === oauth/kimi-code) as an explicit-cn signal
that outranks the marker; getRegion() on the v2 side mirrors it.

* fix(agent-core-v2): thread the default-slot key through capability region resolution

Capability installs resolved the region from the persisted oauthHost only,
so an explicit China login (which persists no host) lost to a stale
overseas install marker. Pass the oauth ref key through as well, matching
getRegion(). Also move the region contract notes into the auth.ts file
header per the package comment convention.

* fix(agent-core-v2): honor the region-marker opt-out for the telemetry endpoint

Hosts that set KIMI_CODE_REGION_MARKER=off (the desktop embedded server)
skip the install marker in getRegion(), but the default telemetry endpoint
still consulted it, so a stale overseas marker could split the reported
region from the telemetry destination.

* feat(cli): show region site domains in login platform selector

* chore: reword oauth login changesets

* fix: honor the region marker opt-out in the CLI and capability resolvers

* refactor: rename login region values to mainland-cn and global

* fix: keep the --region help text in English

* fix: simplify the --region help text to site domains

* feat: drop the suggested login platform order

* feat: split a browser-safe region profile table out of the region resolver

* Revert "feat: split a browser-safe region profile table out of the region resolver"

This reverts commit a037b1143e.

* fix: read the install marker from the bootstrapped home directory

* fix: resolve the server plugin marketplace from the active login region

* feat: expose the login region option through the klient auth facade

* fix: drop a comment from the v2 auth region test

* fix: keep scoped base-only logins on their environment for a bare login

* fix: invalidate the region cache on the provider-manager logout path

* fix: route client-config fetches through the active region profile

* fix: resolve the telemetry endpoint per flush so a login region switch applies in-process

* test: expect the telemetry endpoint resolver in the CLI init assertions

* fix: resolve the default telemetry endpoint from the bootstrapped home

* chore: reword the oauth login changeset around the two login methods

* chore: trim the oauth login changeset to the headline

* feat: let hosts override the region marker env through the server bootstrap env bag
2026-08-20 11:24:02 +08:00
Haozhe
ca87c58e62
fix(agent-core-v2): cap default subagent delegation at one level (#3012)
- give the builtin agent profile an explicit subagents allowlist (coder, explore, plan), restoring v1 semantics
- inherit the default profile's allowlist when a caller profile declares none, instead of leaving delegation unrestricted
- pass a lone "*" subagents field through as an explicit unrestricted marker
2026-08-20 09:53:11 +08:00
Haozhe
67fbcdf1ba
feat(agent-core-v2): guard Edit and Write against stale or unread files (#3096)
* feat(agent-core-v2): guard Edit and Write against stale or unread files

* feat(agent-core-v2): guard Edit and Write against stale or unread files
2026-08-19 22:55:55 +08:00
Haozhe
4ff06f17e3
fix(kap-server): serve real session usage in snapshot and persist per-turn context readings (#3094)
* fix(kap-server): serve real session usage in snapshot and persist per-turn context readings

* fix(kap-server): omit unknown session usage fields instead of reporting zero
2026-08-19 22:06:53 +08:00
Haozhe
056f02c2de
fix(agent-core-v2): record step.end for failed or interrupted steps in wire log (#3095)
Some checks are pending
CI / build (push) Waiting to run
CI / test-vscode-legacy (push) Waiting to run
CI / test-windows (push) Waiting to run
Release / Publish native release assets (push) Blocked by required conditions
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 / 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
2026-08-19 21:30:56 +08:00
Haozhe
eac9ea88e8
refactor(agent-core-v2): persist cron tasks as durable wire records (#3093)
* refactor(agent-core-v2): persist cron tasks as durable wire records

- write CronAdd/CronDelete/CronCursor as durable wire records and rebuild the cron task table from dispatcher replay
- migrate legacy per-workspace cron JSON files into the wire on first resume, then drop the file-based persistence service, its registrations, and the bootstrap cron scope
- derive the session cron view from the agent replayable cron state and remove the redundant session-level copy
- let session forks inherit cron tasks through the copied wire instead of duplicating task files

* fix(agent-core-v2): keep legacy cron tasks on cold forks and flush before cleanup

- inherit legacy cron task files into a full fork's wire so cold sessions forked before their first post-upgrade resume do not silently lose scheduled tasks
- flush the migrated wire records before deleting legacy files so a crash cannot lose both copies

* refactor(agent-core-v2): drop the legacy cron file migration

- stop reading legacy per-workspace cron JSON files entirely; pre-upgrade tasks simply stop applying instead of being migrated into the wire
- remove the legacy read path, the fork-time legacy inheritance, and the now-unused session context/document store injections
2026-08-19 21:26:57 +08:00
Haozhe
c843d3a7f9
refactor(kap-server): table-driven dispatch for multi-action routes (#3092)
* refactor(kap-server): table-driven dispatch for multi-action routes

- add a shared action-dispatch helper; sessions, prompts, plugins, questions, and modelCatalog collection routes declare action tables with module-level handlers
- add ISessionManager.status returning the session summary; the archive action checks it instead of resuming the session
- archive cold sessions through the persisted-metadata path shared with batch archive

* fix(agent-core-v2): read-your-writes for session index point gets

Overlay pending mirror summaries in getFromReadModel so a freshly recorded
summary (e.g. cold-session archive) is visible to GET immediately, matching
the existing pending overlays in list and cursor resolution.
2026-08-19 21:19:50 +08:00
qer
38a5a934ae
feat: project prompt attachments into the live transcript and clear the transcript goal on clear (#3088)
* feat(agent-core-v2): carry prompt attachments on turn.started so the live transcript projects them

* fix(transcript): clear the transcript goal when the goal is cleared

* fix(agent-core-v2): count a prompt media part as a transcript attachment only when its id matches its daemon file URL

* test(kap-server): expect the session-media file id on converted prompt parts
2026-08-19 18:38:21 +08:00
7Sageer
2ea2ef62e4
feat(agent-core-v2): report the bound model alias in subagent_created telemetry (#3086) 2026-08-19 17:13:03 +08:00
Haozhe
16499408d5
refactor(agent-core-v2): extract externalHooks into a scope-organized feature (#2805)
Move the external hook services out of app/externalHooksRunner,
session/externalHooks, and agent/externalHooks into
features/externalHooks, assembled as the ExternalHooksFeature unit:

- services live under per-scope subdirectories (app/, session/, agent/);
  shared pure helpers (types, hook matching/dispatch, process spawn,
  prompt result rendering) live under internal/
- the runner and the two observers are contributed through the Feature
  seams (ScopeUnits materialization); the hooks config section stays on
  the static import=register channel
- update the package entry leaf exports, the plugin domain imports, the
  kap-server events-zod import, and the affected tests; regenerate the
  state manifest
2026-08-19 16:52:51 +08:00
Haozhe
cb8a7e5f81
feat(kap-server): expose engine feature list on /api/v1/meta (#3085) 2026-08-19 16:32:45 +08:00
7Sageer
571bcc2f75
fix(agent-core-v2): register needs-auth MCP authenticate tool regardless of settle timing (#3083) 2026-08-19 16:32:26 +08:00
qer
be8e017597
fix(agent-core-v2): emit subagent.spawned after task registration (#3005)
* fix(agent-core-v2): emit subagent.spawned after task registration

The spawned signal previously fired at launch, before the run's task
registration, so clients learned the agent id with no task id to bind
cancel/status actions to; a failed registration also left a spawned row
behind for a run that never registered. Emit it only after registerTask
succeeds and carry the task id on the event.

* fix(agent-core-v2): keep spawned ahead of started for Agent-tool runs

The TUI drops subagent.started until spawned has established the row,
and a failed registration must not leave a started row behind with no
terminal event. Defer the mirrored started dispatch so the Agent tool
can emit it itself after registration and spawned.

* fix(agent-core-v2): void the deferred started dispatch

* fix(kap-server): key Agent-tool transcript rows by the registered task id

Transcript-protocol clients suppress the raw task.*/subagent.* session
events, so they only saw a subagent row keyed by agent id that cannot
address /tasks/{id}, plus a second row once task.started landed. Key the
spawned row by the task id it now carries, fold task.started and the
subagent lifecycle back into it, and keep the agent-id path for spawns
without a registration (swarm/session-init/tower). Statement-level
ordering notes move to the file headers per package convention.

* test(agent-core-v2): split the spawned/started ordering contract into its own test

* fix(kap-server): keep subagent result details across task termination and drop stale task mappings on taskless respawns

* fix(kap-server): recover the agent-to-task association from a backfilled task.started

* fix(kap-server): seed pre-attach Agent task mappings on the transcript binding

* fix(kap-server): seed the full in-flight task row on transcript bind, not only its id

* docs(agent-core-v2): name the state-domain event dispatcher in the Agent tool header

* style(kap-server): drop comments in transcript services per the no-comments lint rule
2026-08-19 14:58:55 +08:00
Luyu Cheng
01eeacb59b
feat(kimi-code): specialize the WaitFor tool's transcript display (#3066)
* feat(kimi-code): specialize the WaitFor tool's transcript display

* feat(agent-core-v2): emit status progress while WaitFor is pending

* fix(kimi-code): route WaitFor dimming through the TUI theme

* feat(kimi-code): support replaceable status updates in tool progress

* fix(kimi-code): forward status progress to subagent activity surfaces

* fix(agent-core-v2): drop the redundant undefined from ToolUpdate.replace

* fix(kimi-code): honor replace semantics in the subagent live status path

* test(agent-core-v2): drive the WaitFor progress test through a manual tick

* fix(kap-server): mirror ToolUpdate.replace in the ws event schema

* refactor(agent-core-v2): expose the WaitFor progress scheduler as a public seam

* fix(kimi-code): pass child wait statuses without the trailing newline

* feat(agent-core-v2): tick the WaitFor progress status every second

* feat(agent-core-v2): format WaitFor progress durations as 1m 15s

* feat(agent-core-v2): omit zero seconds and minutes in WaitFor durations
2026-08-19 14:15:38 +08:00
7Sageer
c908a39e32
refactor(agent-core-v2): unify the loop-event fold into one core with two materializations (#3018)
* refactor(agent-core-v2): unify the loop-event fold into one core with two materializations

The loop-event stream was reduced by two hand-mirrored state machines:
loopEventFold.ts for the live/replayed context and contextTranscript.ts
for the full transcript behind the messages endpoints, kept in sync by
comments alone and already drifted (transcript dropped tool-result note
metadata and never closed a dangling tool exchange at step.end).

createLoopEventFold now owns the shared state machine once (settle,
pending tool exchanges, deferred appends, vacuous tracking) and both
views plug in as LoopEventFoldSink materializations. New parity tests
pin the foldedLength === live length invariant the endpoints splice on.

* fix(agent-core-v2): drop every removed prompt's injections on multi-turn transcript undo

The transcript undo only walked prompt-owned injections off the oldest
counted anchor, so with count > 1 an injection owned by a newer removed
prompt (e.g. an image-compression caption) survived the display undo
while the live context removed it. Collect every counted anchor's id
during the walk and sweep their owned injections afterwards, keeping
the transcript's 'prompt-owned ones leave with their prompt' contract
for every count and matching the live view.

* refactor(agent-core-v2): drop module headers from the context fold modules

The comment-free zone lint only allows JSDoc on exported symbols.

* fix(agent-core-v2): recover fold state after rehydration

* fix(agent-core-v2): scope undo injections to their prompt

* fix(agent-core-v2): settle open transcript frames when compaction lands mid-fold

An overflow-triggered compaction arrives with the failed attempt's
frame still open. The transcript appended the summary marker and reset
the fold but left the frame, so a vacuous partial stayed in the entries
while the live context dropped it, and a pending tool exchange lost its
interrupted result. Settle through the shared fold core at the marker
instead: close pending tool calls, drop or seal the open frame, then
append the summary. recoverFoldedLength recomputes the absolute count
right after either way.

* fix(agent-core-v2): keep legacy compaction recovery on the pre-settlement count

A legacy context.apply_compaction record (compactedCount without
keptUserMessageCount) recovers foldedLength as 1 + (foldedLength -
compactedCount), and the live legacy tail shape keeps the unsettled
open frame inside history.slice(compactedCount). Settling the fold for
those records shifted foldedLength by the settlement delta before the
recovery read it, leaving the transcript count one off the live
context. Gate the settle to modern records; legacy records keep the
previous freeze-and-reset behavior.
2026-08-19 14:09:22 +08:00
7Sageer
f13f379044
fix(agent-core-v2): stop advertising unavailable ReadMediaFile to non-multimodal models (#3046)
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-vscode-legacy (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 / Publish native release assets (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
* fix(agent-core-v2): stop advertising unavailable ReadMediaFile to non-multimodal models

* fix(agent-core-v2): honor the effective tool policy before advertising ReadMediaFile

* fix(agent-core-v2): keep media-unavailable guidance reason-neutral and within the active toolset

* fix(agent-core-v2): recommend MCP fallbacks only when an active MCP tool exists

* fix(agent-core-v2): stop naming other tools in Read descriptions and errors

* fix(agent-core-v2): drop tool roster from plan agent prompt
2026-08-19 12:43:50 +08:00