feat(core): store relative path for sessions (#24704)

This commit is contained in:
James Long
2026-04-28 11:51:24 -04:00
committed by GitHub
parent ea3c6c3481
commit 2c2fc3499b
10 changed files with 1460 additions and 4 deletions
@@ -0,0 +1 @@
ALTER TABLE `session` ADD `path` text;
File diff suppressed because it is too large Load Diff
@@ -44,6 +44,7 @@ export function toPartialRow(info: DeepPartial<Session.Info>) {
parent_id: grab(info, "parentID"), parent_id: grab(info, "parentID"),
slug: grab(info, "slug"), slug: grab(info, "slug"),
directory: grab(info, "directory"), directory: grab(info, "directory"),
path: grab(info, "path"),
title: grab(info, "title"), title: grab(info, "title"),
version: grab(info, "version"), version: grab(info, "version"),
share_url: grab(info, "share", (v) => grab(v, "url")), share_url: grab(info, "share", (v) => grab(v, "url")),
@@ -24,6 +24,7 @@ export const SessionTable = sqliteTable(
parent_id: text().$type<SessionID>(), parent_id: text().$type<SessionID>(),
slug: text().notNull(), slug: text().notNull(),
directory: text().notNull(), directory: text().notNull(),
path: text(),
title: text().notNull(), title: text().notNull(),
version: text().notNull(), version: text().notNull(),
share_url: text(), share_url: text(),
+16 -4
View File
@@ -74,6 +74,7 @@ export function fromRow(row: SessionRow): Info {
projectID: row.project_id, projectID: row.project_id,
workspaceID: row.workspace_id ?? undefined, workspaceID: row.workspace_id ?? undefined,
directory: row.directory, directory: row.directory,
path: row.path ?? undefined,
parentID: row.parent_id ?? undefined, parentID: row.parent_id ?? undefined,
title: row.title, title: row.title,
version: row.version, version: row.version,
@@ -98,6 +99,7 @@ export function toRow(info: Info) {
parent_id: info.parentID, parent_id: info.parentID,
slug: info.slug, slug: info.slug,
directory: info.directory, directory: info.directory,
path: info.path,
title: info.title, title: info.title,
version: info.version, version: info.version,
share_url: info.share?.url, share_url: info.share?.url,
@@ -124,6 +126,10 @@ function getForkedTitle(title: string): string {
return `${title} (fork #1)` return `${title} (fork #1)`
} }
function sessionPath(worktree: string, cwd: string) {
return path.relative(path.resolve(worktree), cwd).replaceAll("\\", "/")
}
const Summary = Schema.Struct({ const Summary = Schema.Struct({
additions: Schema.Number, additions: Schema.Number,
deletions: Schema.Number, deletions: Schema.Number,
@@ -155,6 +161,7 @@ export const Info = Schema.Struct({
projectID: ProjectID, projectID: ProjectID,
workspaceID: optionalOmitUndefined(WorkspaceID), workspaceID: optionalOmitUndefined(WorkspaceID),
directory: Schema.String, directory: Schema.String,
path: optionalOmitUndefined(Schema.String),
parentID: optionalOmitUndefined(SessionID), parentID: optionalOmitUndefined(SessionID),
summary: optionalOmitUndefined(Summary), summary: optionalOmitUndefined(Summary),
share: optionalOmitUndefined(Share), share: optionalOmitUndefined(Share),
@@ -245,6 +252,7 @@ const UpdatedInfo = Schema.Struct({
projectID: Schema.optional(Schema.NullOr(ProjectID)), projectID: Schema.optional(Schema.NullOr(ProjectID)),
workspaceID: Schema.optional(Schema.NullOr(WorkspaceID)), workspaceID: Schema.optional(Schema.NullOr(WorkspaceID)),
directory: Schema.optional(Schema.NullOr(Schema.String)), directory: Schema.optional(Schema.NullOr(Schema.String)),
path: Schema.optional(Schema.NullOr(Schema.String)),
parentID: Schema.optional(Schema.NullOr(SessionID)), parentID: Schema.optional(Schema.NullOr(SessionID)),
summary: Schema.optional(Schema.NullOr(Summary)), summary: Schema.optional(Schema.NullOr(Summary)),
share: Schema.optional(UpdatedShare), share: Schema.optional(UpdatedShare),
@@ -442,6 +450,7 @@ export const layer: Layer.Layer<Service, never, Bus.Service | Storage.Service> =
parentID?: SessionID parentID?: SessionID
workspaceID?: WorkspaceID workspaceID?: WorkspaceID
directory: string directory: string
path?: string
permission?: Permission.Ruleset permission?: Permission.Ruleset
}) { }) {
const ctx = yield* InstanceState.context const ctx = yield* InstanceState.context
@@ -451,6 +460,7 @@ export const layer: Layer.Layer<Service, never, Bus.Service | Storage.Service> =
version: InstallationVersion, version: InstallationVersion,
projectID: ctx.project.id, projectID: ctx.project.id,
directory: input.directory, directory: input.directory,
path: input.path,
workspaceID: input.workspaceID, workspaceID: input.workspaceID,
parentID: input.parentID, parentID: input.parentID,
title: input.title ?? createDefaultTitle(!!input.parentID), title: input.title ?? createDefaultTitle(!!input.parentID),
@@ -566,11 +576,12 @@ export const layer: Layer.Layer<Service, never, Bus.Service | Storage.Service> =
permission?: Permission.Ruleset permission?: Permission.Ruleset
workspaceID?: WorkspaceID workspaceID?: WorkspaceID
}) { }) {
const directory = yield* InstanceState.directory const ctx = yield* InstanceState.context
const workspace = yield* InstanceState.workspaceID const workspace = yield* InstanceState.workspaceID
return yield* createNext({ return yield* createNext({
parentID: input?.parentID, parentID: input?.parentID,
directory, directory: ctx.directory,
path: sessionPath(ctx.worktree, ctx.directory),
title: input?.title, title: input?.title,
permission: input?.permission, permission: input?.permission,
workspaceID: workspace, workspaceID: workspace,
@@ -578,11 +589,12 @@ export const layer: Layer.Layer<Service, never, Bus.Service | Storage.Service> =
}) })
const fork = Effect.fn("Session.fork")(function* (input: { sessionID: SessionID; messageID?: MessageID }) { const fork = Effect.fn("Session.fork")(function* (input: { sessionID: SessionID; messageID?: MessageID }) {
const directory = yield* InstanceState.directory const ctx = yield* InstanceState.context
const original = yield* get(input.sessionID) const original = yield* get(input.sessionID)
const title = getForkedTitle(original.title) const title = getForkedTitle(original.title)
const session = yield* createNext({ const session = yield* createNext({
directory, directory: ctx.directory,
path: sessionPath(ctx.worktree, ctx.directory),
workspaceID: original.workspaceID, workspaceID: original.workspaceID,
title, title,
}) })
@@ -208,6 +208,7 @@ export async function run(db: SQLiteBunDatabase<any, any> | NodeSQLiteDatabase<a
parent_id: data.parentID ?? null, parent_id: data.parentID ?? null,
slug: data.slug ?? "", slug: data.slug ?? "",
directory: data.directory ?? "", directory: data.directory ?? "",
path: data.path ?? null,
title: data.title ?? "", title: data.title ?? "",
version: data.version ?? "", version: data.version ?? "",
share_url: data.share?.url ?? null, share_url: data.share?.url ?? null,
@@ -59,6 +59,7 @@ describe("Session.Info", () => {
projectID, projectID,
workspaceID, workspaceID,
directory: "/tmp/proj", directory: "/tmp/proj",
path: "packages/opencode",
parentID: sessionIDChild, parentID: sessionIDChild,
summary: { summary: {
additions: 10, additions: 10,
@@ -54,6 +54,7 @@ describe("session.created event", () => {
expect(receivedInfo?.id).toBe(info.id) expect(receivedInfo?.id).toBe(info.id)
expect(receivedInfo?.projectID).toBe(info.projectID) expect(receivedInfo?.projectID).toBe(info.projectID)
expect(receivedInfo?.directory).toBe(info.directory) expect(receivedInfo?.directory).toBe(info.directory)
expect(receivedInfo?.path).toBe(info.path)
expect(receivedInfo?.title).toBe(info.title) expect(receivedInfo?.title).toBe(info.title)
await remove(info.id) await remove(info.id)
+3
View File
@@ -936,6 +936,7 @@ export type Session = {
projectID: string projectID: string
workspaceID?: string workspaceID?: string
directory: string directory: string
path?: string
parentID?: string parentID?: string
summary?: { summary?: {
additions: number additions: number
@@ -1063,6 +1064,7 @@ export type SyncEventSessionUpdated = {
projectID?: string | null projectID?: string | null
workspaceID?: string | null workspaceID?: string | null
directory?: string | null directory?: string | null
path?: string | null
parentID?: string | null parentID?: string | null
summary?: { summary?: {
additions: number additions: number
@@ -1882,6 +1884,7 @@ export type GlobalSession = {
projectID: string projectID: string
workspaceID?: string workspaceID?: string
directory: string directory: string
path?: string
parentID?: string parentID?: string
summary?: { summary?: {
additions: number additions: number
+16
View File
@@ -10154,6 +10154,9 @@
"directory": { "directory": {
"type": "string" "type": "string"
}, },
"path": {
"type": "string"
},
"parentID": { "parentID": {
"type": "string", "type": "string",
"pattern": "^ses.*" "pattern": "^ses.*"
@@ -10584,6 +10587,16 @@
} }
] ]
}, },
"path": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"parentID": { "parentID": {
"anyOf": [ "anyOf": [
{ {
@@ -12538,6 +12551,9 @@
"directory": { "directory": {
"type": "string" "type": "string"
}, },
"path": {
"type": "string"
},
"parentID": { "parentID": {
"type": "string", "type": "string",
"pattern": "^ses.*" "pattern": "^ses.*"