123module cli45import json6import src.fmt7import src.history8import src.snapshot910pub fn cmd_save(raw []string, is_checkpoint bool) int {11 verb := if is_checkpoint { 'checkpoint' } else { 'save' }12 args := parse(verb, raw, Options{13 values: ['agent', 'session']14 flags: ['json']15 }) or { return usage_error(err.msg()) }16 message := args.positional_at(0)17 if message == '' {18 example := if is_checkpoint {19 'before combine replay engine'20 } else {21 'fix off-by-one in chunk boundary'22 }23 return usage_error('${verb} needs a message, e.g. koh ${verb} "${example}"')24 }25 store := open_store() or { return refuse(args.json(), err.msg()) }26 defer {27 store.close()28 }29 save := history.commit_worktree(store, store.root, snapshot.load(store.root), history.SaveInput{30 message: message31 agent: args.value('agent')32 session: args.value('session')33 is_checkpoint: is_checkpoint34 }) or { return refuse(args.json(), err.msg()) }3536 files := history.files_of(store, save.id) or { []snapshot.FileEntry{} }37 if args.json() {38 emit_json(json.encode(SaveOut{39 id: save.id40 parent: save.parent41 message: save.message42 created_at: save.created_at43 machine: save.machine44 is_checkpoint: save.is_checkpoint45 agent: save.agent46 session: save.session47 files: files.len48 size_bytes: save.size_bytes49 }))50 auto_offer(store, true)51 return 052 }53 ok('saved [${save.id}] ${save.message}')54 mut detail := []string{}55 if save.is_checkpoint {56 detail << 'checkpoint'57 }58 detail << fmt.stamp(save.created_at)59 detail << fmt.plural(files.len, 'file')60 detail << fmt.human_bytes(save.size_bytes)61 note(detail.join(' · '))62 mut attribution := []string{}63 if save.agent != '' {64 attribution << 'agent: ${save.agent}'65 }66 if save.session != '' {67 attribution << 'session: ${save.session}'68 }69 if attribution.len > 0 {70 note(attribution.join(' · '))71 }72 auto_offer(store, false)73 return 074}75767778struct SaveOut {79 id string80 parent string81 message string82 created_at i6483 machine string84 is_checkpoint bool85 agent string86 session string87 files int88 size_bytes i6489}