Skip to content

Commit cd736e2

Browse files
authored
Merge pull request #184 from aictrl-dev/chore/issue-181-remove-snapshots
refactor(session): remove the snapshot, revert and session-diff subsystem (#181)
2 parents f30eda8 + d18da58 commit cd736e2

31 files changed

Lines changed: 363 additions & 2966 deletions

‎packages/cli/BUN_SHELL_MIGRATION_PLAN.md‎

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ Current baseline from audit:
1515
- Largest hotspots:
1616
- `src/worktree/index.ts` (22)
1717
- `src/installation/index.ts` (20)
18-
- `src/snapshot/index.ts` (18)
1918

2019
## Decisions
2120

@@ -78,7 +77,6 @@ Migrate these first:
7877

7978
- `src/worktree/index.ts`
8079
- `src/installation/index.ts`
81-
- `src/snapshot/index.ts`
8280

8381
Within each file, migrate git paths first where applicable.
8482

@@ -89,7 +87,6 @@ Migrate git-centric call sites to `Process.git*` helpers:
8987
- `src/file/index.ts`
9088
- `src/project/vcs.ts`
9189
- `src/file/watcher.ts`
92-
- `src/storage/storage.ts`
9390

9491
### Phase 3: Remaining non-git files
9592

@@ -110,7 +107,7 @@ Migrate residual non-git usages:
110107

111108
- Unit tests for new `Process` methods and options.
112109
- Integration tests on hotspot modules.
113-
- Smoke tests for install, snapshot, and worktree flows.
110+
- Smoke tests for install and worktree flows.
114111
- Regression checks for output parsing behavior.
115112

116113
## Risk mitigation

‎packages/cli/README.md‎

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -104,13 +104,6 @@ the agent to keep one in a file.
104104

105105
Aictrl reads config from `.aictrl/` (project) or `~/.config/aictrl/` (global).
106106

107-
### Snapshots
108-
109-
Sessions snapshot the git worktree at each model step, which backs patches, session
110-
diffs and revert. `aictrl run` (without `--attach`) skips them, because nothing in a
111-
headless run reads them and each one stages the whole worktree. Set `"snapshot": true`
112-
in config to keep them in a run, or `"snapshot": false` to turn them off everywhere.
113-
114107
### Models
115108

116109
| Provider | Env Var |

‎packages/cli/src/cli/cmd/debug/index.ts‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import { FileCommand } from "./file"
66
import { RipgrepCommand } from "./ripgrep"
77
import { ScrapCommand } from "./scrap"
88
import { SkillCommand } from "./skill"
9-
import { SnapshotCommand } from "./snapshot"
109
import { AgentCommand } from "./agent"
1110

1211
export const DebugCommand = cmd({
@@ -19,7 +18,6 @@ export const DebugCommand = cmd({
1918
.command(FileCommand)
2019
.command(ScrapCommand)
2120
.command(SkillCommand)
22-
.command(SnapshotCommand)
2321
.command(AgentCommand)
2422
.command(PathsCommand)
2523
.command({

‎packages/cli/src/cli/cmd/debug/snapshot.ts‎

Lines changed: 0 additions & 52 deletions
This file was deleted.

‎packages/cli/src/cli/cmd/import.ts‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ export type ShareData =
1515
| { type: "session"; data: SDKSession }
1616
| { type: "message"; data: Message }
1717
| { type: "part"; data: Part }
18-
| { type: "session_diff"; data: unknown }
1918
| { type: "model"; data: unknown }
2019

2120
/** Extract share ID from a share URL like https://opncd.ai/share/abc123 */

‎packages/cli/src/cli/cmd/run.ts‎

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import { PermissionNext } from "../../permission/next"
2323
import { Session } from "../../session"
2424
import type { MessageV2 } from "../../session/message-v2"
2525
import { SessionPrompt } from "../../session/prompt"
26-
import { Snapshot } from "../../snapshot"
2726
import { Config } from "../../config/config"
2827
import { GlobalBus } from "../../bus/global"
2928
import { Instance } from "../../project/instance"
@@ -1120,10 +1119,6 @@ export const RunCommand = cmd({
11201119
await Shutdown.flush()
11211120
}
11221121

1123-
// Nothing in a run reads snapshots, patches or session diffs, so local sessions skip
1124-
// them unless config sets `snapshot: true` (#146).
1125-
// consolidate with HeadlessRun (#152)
1126-
Snapshot.setDefault(false)
11271122
invocation.phase("bootstrap")
11281123
if (args.attach) {
11291124
return await invocation.run(() => execute(createAictrlClient({ baseUrl: args.attach, directory })))

‎packages/cli/src/cli/cmd/uninstall.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export const UninstallCommand = {
3636
.option("keep-data", {
3737
alias: "d",
3838
type: "boolean",
39-
describe: "keep session data and snapshots",
39+
describe: "keep session data",
4040
default: false,
4141
})
4242
.option("dry-run", {

‎packages/cli/src/config/config.ts‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,9 @@ export namespace Config {
217217

218218
if (!result.username) result.username = os.userInfo().username
219219

220+
// `snapshot` toggled the removed worktree snapshots (#181). It stays valid so old configs still load.
221+
if (result.snapshot !== undefined) log.warn("config key `snapshot` is deprecated and ignored")
222+
220223
// Handle migration from autoshare to share field
221224
if (result.autoshare === true && !result.share) {
222225
result.share = "auto"
@@ -998,7 +1001,10 @@ export namespace Config {
9981001
})
9991002
.optional(),
10001003
plugin: z.string().array().optional(),
1001-
snapshot: z.boolean().optional(),
1004+
snapshot: z
1005+
.boolean()
1006+
.optional()
1007+
.describe("@deprecated Worktree snapshots were removed; this key is accepted and ignored."),
10021008
share: z
10031009
.enum(["manual", "auto", "disabled"])
10041010
.optional()

‎packages/cli/src/project/bootstrap.ts‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import { Instance } from "./instance"
99
import { Vcs } from "./vcs"
1010
import { Log } from "@/util/log"
1111
import { ShareNext } from "@/share/share-next"
12-
import { Snapshot } from "../snapshot"
1312
import { Truncate } from "../tool/truncation"
1413

1514
export async function InstanceBootstrap() {
@@ -20,7 +19,6 @@ export async function InstanceBootstrap() {
2019
FileWatcher.init()
2120
File.init()
2221
Vcs.init()
23-
Snapshot.init()
2422
Truncate.init()
2523

2624
Bus.subscribe(Command.Event.Executed, async (payload) => {

‎packages/cli/src/session/index.ts‎

Lines changed: 0 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,12 @@ import { Database, NotFoundError, eq, and, or, gte, isNull, desc, like, inArray,
1515
import type { SQL } from "../storage/db"
1616
import { SessionTable, MessageTable, PartTable } from "./session.sql"
1717
import { ProjectTable } from "../project/project.sql"
18-
import { Storage } from "@/storage/storage"
1918
import { Log } from "../util/log"
2019
import { MessageV2 } from "./message-v2"
2120
import { Instance } from "../project/instance"
2221
import { SessionPrompt } from "./prompt"
2322
import { fn } from "@/util/fn"
2423
import { Command } from "../command"
25-
import { Snapshot } from "@/snapshot"
2624

2725
import type { Provider } from "@/provider/provider"
2826
import { PermissionNext } from "@/permission/next"
@@ -49,17 +47,7 @@ export namespace Session {
4947
type SessionRow = typeof SessionTable.$inferSelect
5048

5149
export function fromRow(row: SessionRow): Info {
52-
const summary =
53-
row.summary_additions !== null || row.summary_deletions !== null || row.summary_files !== null
54-
? {
55-
additions: row.summary_additions ?? 0,
56-
deletions: row.summary_deletions ?? 0,
57-
files: row.summary_files ?? 0,
58-
diffs: row.summary_diffs ?? undefined,
59-
}
60-
: undefined
6150
const share = row.share_url ? { url: row.share_url } : undefined
62-
const revert = row.revert ?? undefined
6351
return {
6452
id: row.id,
6553
slug: row.slug,
@@ -69,9 +57,7 @@ export namespace Session {
6957
parentID: row.parent_id ?? undefined,
7058
title: row.title,
7159
version: row.version,
72-
summary,
7360
share,
74-
revert,
7561
permission: row.permission ?? undefined,
7662
time: {
7763
created: row.time_created,
@@ -93,11 +79,6 @@ export namespace Session {
9379
title: info.title,
9480
version: info.version,
9581
share_url: info.share?.url,
96-
summary_additions: info.summary?.additions,
97-
summary_deletions: info.summary?.deletions,
98-
summary_files: info.summary?.files,
99-
summary_diffs: info.summary?.diffs,
100-
revert: info.revert ?? null,
10182
permission: info.permission,
10283
time_created: info.time.created,
10384
time_updated: info.time.updated,
@@ -124,14 +105,6 @@ export namespace Session {
124105
workspaceID: z.string().optional(),
125106
directory: z.string(),
126107
parentID: Identifier.schema("session").optional(),
127-
summary: z
128-
.object({
129-
additions: z.number(),
130-
deletions: z.number(),
131-
files: z.number(),
132-
diffs: Snapshot.FileDiff.array().optional(),
133-
})
134-
.optional(),
135108
share: z
136109
.object({
137110
url: z.string(),
@@ -146,14 +119,6 @@ export namespace Session {
146119
archived: z.number().optional(),
147120
}),
148121
permission: PermissionNext.Ruleset.optional(),
149-
revert: z
150-
.object({
151-
messageID: z.string(),
152-
partID: z.string().optional(),
153-
snapshot: z.string().optional(),
154-
diff: z.string().optional(),
155-
})
156-
.optional(),
157122
})
158123
.meta({
159124
ref: "Session",
@@ -210,13 +175,6 @@ export namespace Session {
210175
info: Info,
211176
}),
212177
),
213-
Diff: BusEvent.define(
214-
"session.diff",
215-
z.object({
216-
sessionID: z.string(),
217-
diff: Snapshot.FileDiff.array(),
218-
}),
219-
),
220178
Error: BusEvent.define(
221179
"session.error",
222180
z.object({
@@ -471,86 +429,6 @@ export namespace Session {
471429
},
472430
)
473431

474-
export const setRevert = fn(
475-
z.object({
476-
sessionID: Identifier.schema("session"),
477-
revert: Info.shape.revert,
478-
summary: Info.shape.summary,
479-
}),
480-
async (input) => {
481-
return Database.use((db) => {
482-
const row = db
483-
.update(SessionTable)
484-
.set({
485-
revert: input.revert ?? null,
486-
summary_additions: input.summary?.additions,
487-
summary_deletions: input.summary?.deletions,
488-
summary_files: input.summary?.files,
489-
time_updated: Date.now(),
490-
})
491-
.where(eq(SessionTable.id, input.sessionID))
492-
.returning()
493-
.get()
494-
if (!row) throw new NotFoundError({ message: `Session not found: ${input.sessionID}` })
495-
const info = fromRow(row)
496-
Database.effect(() => Bus.publish(Event.Updated, { info }))
497-
return info
498-
})
499-
},
500-
)
501-
502-
export const clearRevert = fn(Identifier.schema("session"), async (sessionID) => {
503-
return Database.use((db) => {
504-
const row = db
505-
.update(SessionTable)
506-
.set({
507-
revert: null,
508-
time_updated: Date.now(),
509-
})
510-
.where(eq(SessionTable.id, sessionID))
511-
.returning()
512-
.get()
513-
if (!row) throw new NotFoundError({ message: `Session not found: ${sessionID}` })
514-
const info = fromRow(row)
515-
Database.effect(() => Bus.publish(Event.Updated, { info }))
516-
return info
517-
})
518-
})
519-
520-
export const setSummary = fn(
521-
z.object({
522-
sessionID: Identifier.schema("session"),
523-
summary: Info.shape.summary,
524-
}),
525-
async (input) => {
526-
return Database.use((db) => {
527-
const row = db
528-
.update(SessionTable)
529-
.set({
530-
summary_additions: input.summary?.additions,
531-
summary_deletions: input.summary?.deletions,
532-
summary_files: input.summary?.files,
533-
time_updated: Date.now(),
534-
})
535-
.where(eq(SessionTable.id, input.sessionID))
536-
.returning()
537-
.get()
538-
if (!row) throw new NotFoundError({ message: `Session not found: ${input.sessionID}` })
539-
const info = fromRow(row)
540-
Database.effect(() => Bus.publish(Event.Updated, { info }))
541-
return info
542-
})
543-
},
544-
)
545-
546-
export const diff = fn(Identifier.schema("session"), async (sessionID) => {
547-
try {
548-
return await Storage.read<Snapshot.FileDiff[]>(["session_diff", sessionID])
549-
} catch {
550-
return []
551-
}
552-
})
553-
554432
export const messages = fn(
555433
z.object({
556434
sessionID: Identifier.schema("session"),

0 commit comments

Comments
 (0)