Repository navigation
Conversation
d95b901 to
11e6929
Compare
|
Hey @zzyking , what's the reason behind keeping it read-only? |
|
@perry-the-agent can you review this change? |
| .and_then(Value::as_bool) | ||
| .unwrap_or(false); | ||
| let mut output = object.get("output").cloned().unwrap_or(Value::Null); | ||
| if let Some(note) = object.get("note").and_then(Value::as_str) |
There was a problem hiding this comment.
note is retained only when output is a string. For a result such as {"output": {"x": 1}, "note": "truncated"} (or output: null), this branch leaves the JSON output unchanged and silently drops the note, despite the format doc saying truncation/permission annotations are preserved. Please preserve note for every output shape and add object/null regression cases.
| if !content.is_empty() { | ||
| wire.push(json!({"type": "context.append_message", "time": time, "message": {"role": "user", "content": content, "toolCalls": []}})); | ||
| } | ||
| for block in &message.content { |
There was a problem hiding this comment.
This two-pass encoding reorders mixed user blocks: all text is emitted first, then all tool results. A Common message containing [ToolResult, Text] round-trips through Kimi as [Text, ToolResult], violating the codec's block-order invariant and potentially changing continuation semantics. Please emit blocks in one ordered pass (coalescing only adjacent text if needed) and add a mixed-order fixpoint test.
| common <--> cursor["Cursor CLI"] | ||
| common <--> cursordesktop["Cursor desktop"] | ||
| common <--> grok["Grok CLI"] | ||
| common <--> kimi["Kimi Code"] |
There was a problem hiding this comment.
The bidirectional arrow conflicts with the table and implementation, which describe Kimi as source-only/read-only. This should be kimi --> common, like the other source-only harnesses.
|
Reviewed at I found two reproducible issues: non-text Kimi tool-result notes are dropped, and mixed user blocks are reordered during a Common → Kimi round trip. I also flagged the README diagram's bidirectional arrow, which conflicts with the read-only/source-only behavior. Verification passed: |
|
You're right that read-only was too conservative here — I checked it against the real CLI, and Kimi does accept sessions written from outside. Testing in an isolated It isn't just listing a directory, either: Writing a session needs four plain file operations: the session directory, Nothing here is compressed, schema-validated, or fails closed, so Kimi sits in the same class as |
bd0f5b8 to
acd01f4
Compare
|
All three findings are fixed and pushed, and the branch is rebased onto
On the read-only point from my previous comment: since Kimi turns out to be writable, |
|
Confirming what I said above: the write support is a follow-up, not part of this PR — #32 ( Keeping them apart means this PR stays what it was reviewed as (the reader plus the three fixes), and the read/write change gets reviewed on its own terms. #32's diff currently includes this branch's commits, because it is stacked on it; that narrows to a single commit once this merges. Merge order is #18, then #32. One thing worth surfacing here, since it bears on the read-only question: the probe I posted above listed at |
Three review findings: - A Kimi tool result's `note` — a truncation or permission annotation — was only retained when `output` was a string. For an object, array, or null output the note was silently dropped. Text output still takes the note as a suffix; every other shape now keeps its structure and carries the note beside it. - Encoding a user message in two passes emitted all text before all tool results, so a Common message holding `[ToolResult, Text]` round-tripped through Kimi as `[Text, ToolResult]`. Blocks are now emitted in one ordered pass, coalescing adjacent text and flushing it ahead of each tool result. - The README diagram showed `common <--> kimi`, contradicting the table and the read-only store. It is now `kimi --> common`, alongside the other source-only harnesses.
`kimi fork` records the source session's id in the forked session's `state.json` as top-level `forkedFrom`. Fill `Meta::lineage` from it as a Fork, at discovery as well as on load, so forked Kimi sessions link back to their source the way pi, Codex and OpenCode sessions already do. Subagents are not sessions of their own in Kimi — they live under the same session's `agents/<name>/` — so there is no spawn link to read.
acd01f4 to
396f94f
Compare
Summary
~/.kimi-code/sessions/(or$KIMI_HOME/sessions) asstate.jsonplusagents/main/wire.jsonlsave,delete, same-harness continue, and--with kimiare refused; the native resume command iskimi --session <id>Format
state.jsonhas two observed shapes. Schema version 2 recordsidandcwd. Version 1 has noversionmarker, usesworkDir, and has no id field. The id is resolvedsessionId→id→ thesession_*segment of an agenthomedir→ the directory name.createdAtis accepted as RFC3339 or epoch milliseconds.Conversational projection:
context.append_message(user)content.parttext / thinktool.call/tool.resultisErrorandnotekept)context.undocountturnswire.jsonlis append-only, so a retried prompt is still on disk.countis in turns, not entries: one turn can append a prompt plus reminders, and a singlecount: 1undo drops all of them. Logs withoutturn.promptmarkers fall back to entry granularity.The codec can still render a synthetic Kimi body so other harnesses can hop through Common. The store never writes
~/.kimi-code/sessions.Provenance
The wire protocol is not a published contract. This reader is based on local Kimi Code CLI sessions (protocol 1.4 / state v1 and 1.5 / state v2) and on
kimi --help. Unknown events are retained so format drift shows up as unexplained native data rather than dropped history.Verification
cargo fmt --all -- --checkcargo clippy --workspace --all-targets --all-features -- -D warningscargo test --workspace --all-features