fix(web): address session fork review findings

This commit is contained in:
imccyu
2026-07-30 21:28:13 +08:00
parent 57fb5b488e
commit 36f1489398
31 files changed
+346 -80

No files matched your search

@@ -33,7 +33,8 @@ export interface ISessions {
* Fork a session from a completed-turn prefix of the source; on resolution
* the child is in the list store and `open()` can target it.
* @param opts - source session id and the optional event seq anchoring the
* cut (the boundary is the first turn/end at or after it).
* cut (the boundary is the first turn/end at or after it; an in-log
* anchor in an open turn is unavailable rather than clipped backward).
* @returns the child session id.
*/
fork(opts: { sessionId: SessionId; atSeq?: number }): Promise<SessionId>
@@ -293,7 +293,8 @@ export class SessionManager {
* Contract session.fork; on success merge the child into summaries
* immediately (same synchronous-addressability guarantee as create). The
* child carries the source's history, so it is never blank; lineage rides
* parentSessionId so the list nests it under its source.
* parentSessionId so the list nests it under its source. A child published
* before Workspace attachment fails is also reconciled into the list.
* @param opts - source session and the optional seq anchoring the cut.
* @returns the fork result (the child session id).
*/
@@ -306,9 +307,12 @@ export class SessionManager {
sessionId: opts.sessionId,
...opts.atSeq === undefined ? {} : { atSeq: opts.atSeq },
})
if (result.ok) {
const childId = result.ok
? result.value.sessionId
: workspaceAttachSessionId(result.error)
if (childId !== undefined) {
this.recordMutation({ kind: 'upsert', summary: {
sessionId: result.value.sessionId, updatedAt: Date.now(), running: false, blank: false,
sessionId: childId, updatedAt: Date.now(), running: false, blank: false,
parentSessionId: opts.sessionId,
...(source?.cwd !== undefined ? { cwd: source.cwd } : {}),
} })
@@ -338,7 +338,8 @@ export class SessionsService implements ISessions {
* synchronous-addressability guarantee as {@link SessionsService.create}:
* on resolution the child is in the list store and open() can target it).
* @param opts - source session id and the optional event seq anchoring the
* cut (the boundary is the first turn/end at or after it).
* cut (the boundary is the first turn/end at or after it; an in-log
* anchor in an open turn is unavailable rather than clipped backward).
* @returns the child session id.
* @throws {SessionForkError} with the source id.
*/