Skip to content

fix(agent-core-v2): backfill session metadata and align subagent timeout and print-mode lifecycle with v1 - #1710

Closed
sailist wants to merge 10 commits into
MoonshotAI:mainfrom
sailist:fix/session-meta-heal-agents-custom
Closed

fix(agent-core-v2): backfill session metadata and align subagent timeout and print-mode lifecycle with v1#1710
sailist wants to merge 10 commits into
MoonshotAI:mainfrom
sailist:fix/session-meta-heal-agents-custom

Conversation

@sailist

@sailist sailist commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

Related Issue

No linked issue — the problems are explained below.

Problem

This branch collects a set of agent-core-v2 (experimental engine) fixes and v1-alignment work:

  1. Session format drift: sessions created by agent-core-v2 could not be resumed by older v1 builds, and existing sessions missing agents / custom metadata maps were not healed. The kap-server snapshot history also showed wrong message times, and server_version did not report the CLI version.
  2. Subagent timeout mismatch: v2 hard-coded a 30-minute subagent timeout while v1 uses 2 hours and allows [subagent] timeout_ms / KIMI_SUBAGENT_TIMEOUT_MS overrides.
  3. Print-mode lifecycle mismatch: kimi -p on v2 ignored print_background_mode / print_max_turns (it always drained background tasks), and kimi -p "/goal ..." exited after the first turn — v2 drives goal continuation as new turns, which the print runner never waited for.

What changed

Session format & server fixes

  • Backfill missing agents / custom maps in existing session metadata, with a strict-equality heal.
  • Persist the session format so new v2 sessions stay resumable by older v1 builds.
  • kap-server: show real message send times in snapshot history; report the CLI version as server_version.

Subagent timeout alignment

  • New v2 [subagent] config-section owner (timeout_ms, 2-hour default, KIMI_SUBAGENT_TIMEOUT_MS env override), shared by the Agent and AgentSwarm tools; timeout messages render the effective duration.

Print-mode lifecycle alignment

  • The v2 task / legacy background config section gains print_background_mode (exit / drain / steer) and print_max_turns, resolved with v1 semantics (explicit mode > keep_alive_on_exit fallback > default exit).
  • The v2 print runner applies the three modes: steer stays alive so background-task completions steer new main turns, bounded by print_wait_ceiling_s and print_max_turns, and warns when either cap is hit.
  • Print runs also stay alive while a goal is active, so goal continuation turns run to a terminal state (v1 parity for kimi -p "/goal ...").

Tests

  • New unit tests for the config sections and the print background policy; SEA end-to-end verification of the background bash / subagent / cron / goal scenarios.
  • Fixed the sessionLegacy test stub for the ensureMainAgent (create) path.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

sailist added 10 commits July 14, 2026 17:17
- kap-server: accept opts.version in startServer, reported as
  server_version (/meta, OpenAPI, session exports, lock registry,
  default User-Agent); defaults to its own package version
- kimi-code: pass the CLI product version when starting the server
- add boot test covering /api/v1/meta, lock file, and User-Agent
- add wireRecord.seal() to write the metadata envelope at agent creation,
  so fresh logs satisfy v1 replay's first-record-must-be-metadata invariant
- seal the wire log before any op dispatch in AgentLifecycleService.create;
  no-op when the log already has records (resume / forked copies)
- seed empty agents/custom maps in session metadata so v1 Session.resume()
  can index agents['main'] on a v2-created state.json
- add seal unit tests and lifecycle sealing tests
- read per-record times stamped on wire.jsonl via reduceContextTranscript
  and cache them alongside the transcript messages
- prefer each record's real dispatch time for created_at; records without a
  stamp fall back to session.createdAt + index, clamped so the page stays
  strictly increasing (mirrors MessageLegacyService.list)
- add tests for fallback, clamping, and the page-offset index mapping
…ession metadata

- load() now heals pre-fix v2 state.json documents that never gained the
  agents/custom maps, persisting the backfill so one open on a new build
  leaves the session resumable by released v1 builds (Session.resume()
  indexes agents['main'] unconditionally)
- updatedAt is deliberately untouched so the format heal does not reorder
  session listings
- add [subagent] config section with timeout_ms and KIMI_SUBAGENT_TIMEOUT_MS env override
- resolve Agent and AgentSwarm per-run timeouts through resolveSubagentTimeoutMs
- update tool descriptions and tests to reflect the 2-hour default
- add printBackgroundMode/printMaxTurns to the task config section with resolvePrintBackgroundMode (keepAliveOnExit fallback)
- apply exit/drain/steer policy to kimi -p on the experimental engine, buffering turn.ended events and failing the run when a steered turn fails
- register the subagent config section from the package entry
…e headers only

- replace == null with === undefined in the session-metadata heal to
  satisfy eqeqeq (oxlint --type-aware in CI)
- move the seal() rationale into the wireRecord contract header and the
  agents/custom invariant into the sessionMetadata header per the
  tree's header-only comment convention
applyPrintBackgroundPolicy now emits the ceiling warning when the turn.ended wait itself elapses with tasks still pending, matching the deadline-reached path.
- applyPrintBackgroundPolicy waits for goal continuation turns via a goalActive hook before applying the exit/drain/steer mode, bounded by the wait ceiling
- createPrintTurnEndings skips the timeout when the remaining budget is not finite
- update the changeset to cover the goal-run lifecycle
@changeset-bot

changeset-bot Bot commented Jul 14, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 19dba2f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@moonshot-ai/kimi-code Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@sailist

sailist commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator Author

Closing as duplicate: everything on this branch except the goal-continuation fix was already merged via #1704. The remaining piece is re-submitted as the focused PR #1712.

@sailist sailist closed this Jul 14, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 19dba2f275

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +612 to +613
input.warn(`print goal wait ceiling reached (${input.ceilingS}s), finishing`);
return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Return non-zero when goal wait times out

When kimi -p "/goal ..." hits print_wait_ceiling_s while the goal is still active, this branch only warns and returns. runNativeGoal then summarizes that active snapshot and calls the existing goalExitCode('active'), which falls through to success, so long-running or low-ceiling goal runs can exit with code 0 even though the goal never reached a terminal success state. Treat this ceiling path as a failed/paused goal or otherwise force a non-zero exit before returning.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant