Skip to content

fix: cross-version session compatibility and real message times in snapshot history - #1704

Merged
sailist merged 7 commits into
MoonshotAI:mainfrom
sailist:fix/session-meta-heal-agents-custom
Jul 14, 2026
Merged

fix: cross-version session compatibility and real message times in snapshot history#1704
sailist merged 7 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

Three user-visible fixes, all around running mixed CLI builds against the same KIMI_CODE_HOME plus one web UI display fix:

  1. kimi server reported the internal server package version (0.0.1) as server_version, so the web UI settings dialog showed a meaningless version.
  2. Sessions created by newer (agent-core-v2) builds failed to open in older v1 builds on the same machine: v1's wire replay hard-rejects logs whose first record is not the metadata envelope, and v1's Session.resume() indexes agents['main'] unconditionally while pre-fix v2 state.json omitted the agents / custom maps entirely.
  3. After reloading a session in the web UI, every message in the recent history showed the session creation time instead of its actual send time — the snapshot endpoint synthesized created_at from session.createdAt + index even though the real per-record times are persisted in wire.jsonl.

What changed

1. Report the CLI version as server_version

  • The server start path now carries the CLI package version through to the /meta response instead of the private server package's own 0.0.1; boot tests cover the User-Agent and version reporting.

2. Make v2-created sessions resumable by v1 builds

  • wireRecord.seal() writes the metadata envelope at agent creation, called before any op dispatch in AgentLifecycleService.create; it is a no-op when the log already has records (resume / forked copies), and wireRecord.restore() still heals legacy envelope-less logs.
  • Session metadata creation seeds the agents / custom maps v1 reads unconditionally.
  • SessionMetadata.load() heals existing pre-fix documents: missing maps are backfilled and persisted on first open, deliberately without touching updatedAt so session listings keep their order.
  • Seal unit tests, lifecycle sealing tests, and metadata heal tests added.

3. Show real message send times in snapshot history

  • SnapshotReader keeps the per-record times returned by reduceContextTranscript (previously discarded) and passes them as the created_at override, falling back to session.createdAt + index for records predating the time stamp and clamping so the page stays strictly increasing (mirroring MessageLegacyService.list).
  • Unit tests cover real-time mapping, fallback, clamping, and page-offset indexing.

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 4 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
@changeset-bot

changeset-bot Bot commented Jul 14, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 5541e8f

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

@pkg-pr-new

pkg-pr-new Bot commented Jul 14, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@moonshot-ai/kimi-code@5541e8f
npx https://pkg.pr.new/@moonshot-ai/kimi-code@5541e8f

commit: 5541e8f

@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: ded76570ac

ℹ️ 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 +27 to +30
/**
* Ensure the on-disk wire log starts with the `metadata` envelope: append it
* when the log is still empty (fresh agent), no-op otherwise. Called at
* agent creation so the log always satisfies v1's replay invariant — v1's

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 Move seal documentation into the file header

packages/agent-core-v2/AGENTS.md says comments in this tree must live only in the top-of-file /** */ header and never beside functions or methods. This new method-level JSDoc violates that convention; move the v1-compatibility rationale into the file header or remove the inline documentation.

Useful? React with 👍 / 👎.

sailist added 3 commits July 14, 2026 18:13
- 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
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