11import type { Argv } from "yargs"
2+ import { Effect } from "effect"
23import { cmd } from "./cmd"
4+ import { effectCmd , fail } from "../effect-cmd"
35import { Session } from "@/session/session"
46import { SessionID } from "../../session/schema"
5- import { bootstrap } from "../bootstrap"
67import { UI } from "../ui"
78import { Locale } from "@/util/locale"
89import { Flag } from "@opencode-ai/core/flag/flag"
@@ -11,7 +12,8 @@ import { Process } from "@/util/process"
1112import { EOL } from "os"
1213import path from "path"
1314import { which } from "../../util/which"
14- import { AppRuntime } from "@/effect/app-runtime"
15+ import { InstanceRef } from "@/effect/instance-ref"
16+ import { InstanceStore } from "@/project/instance-store"
1517
1618function pagerCmd ( ) : string [ ] {
1719 const lessOptions = [ "-R" , "-S" ]
@@ -47,36 +49,35 @@ export const SessionCommand = cmd({
4749 async handler ( ) { } ,
4850} )
4951
50- export const SessionDeleteCommand = cmd ( {
52+ export const SessionDeleteCommand = effectCmd ( {
5153 command : "delete <sessionID>" ,
5254 describe : "delete a session" ,
53- builder : ( yargs : Argv ) => {
54- return yargs . positional ( "sessionID" , {
55+ builder : ( yargs ) =>
56+ yargs . positional ( "sessionID" , {
5557 describe : "session ID to delete" ,
5658 type : "string" ,
5759 demandOption : true ,
58- } )
59- } ,
60- handler : async ( args ) => {
61- await bootstrap ( process . cwd ( ) , async ( ) => {
60+ } ) ,
61+ handler : Effect . fn ( "Cli.session.delete" ) ( function * ( args ) {
62+ const ctx = yield * InstanceRef
63+ if ( ! ctx ) return
64+ const store = yield * InstanceStore . Service
65+ return yield * Effect . gen ( function * ( ) {
66+ const svc = yield * Session . Service
6267 const sessionID = SessionID . make ( args . sessionID )
63- try {
64- await AppRuntime . runPromise ( Session . Service . use ( ( svc ) => svc . get ( sessionID ) ) )
65- } catch {
66- UI . error ( `Session not found: ${ args . sessionID } ` )
67- process . exit ( 1 )
68- }
69- await AppRuntime . runPromise ( Session . Service . use ( ( svc ) => svc . remove ( sessionID ) ) )
68+ // Match legacy try/catch — Session.get surfaces NotFoundError as a defect.
69+ yield * svc . get ( sessionID ) . pipe ( Effect . catchCause ( ( ) => fail ( `Session not found: ${ args . sessionID } ` ) ) )
70+ yield * svc . remove ( sessionID )
7071 UI . println ( UI . Style . TEXT_SUCCESS_BOLD + `Session ${ args . sessionID } deleted` + UI . Style . TEXT_NORMAL )
71- } )
72- } ,
72+ } ) . pipe ( Effect . ensuring ( store . dispose ( ctx ) ) )
73+ } ) ,
7374} )
7475
75- export const SessionListCommand = cmd ( {
76+ export const SessionListCommand = effectCmd ( {
7677 command : "list" ,
7778 describe : "list sessions" ,
78- builder : ( yargs : Argv ) => {
79- return yargs
79+ builder : ( yargs ) =>
80+ yargs
8081 . option ( "max-count" , {
8182 alias : "n" ,
8283 describe : "limit to N most recent sessions" ,
@@ -87,47 +88,42 @@ export const SessionListCommand = cmd({
8788 type : "string" ,
8889 choices : [ "table" , "json" ] ,
8990 default : "table" ,
90- } )
91- } ,
92- handler : async ( args ) => {
93- await bootstrap ( process . cwd ( ) , async ( ) => {
94- const sessions = await AppRuntime . runPromise (
95- Session . Service . use ( ( svc ) => svc . list ( { roots : true , limit : args . maxCount } ) ) ,
96- )
97-
98- if ( sessions . length === 0 ) {
99- return
100- }
91+ } ) ,
92+ handler : Effect . fn ( "Cli.session.list" ) ( function * ( args ) {
93+ const ctx = yield * InstanceRef
94+ if ( ! ctx ) return
95+ const store = yield * InstanceStore . Service
96+ return yield * Effect . gen ( function * ( ) {
97+ const sessions = yield * Session . Service . use ( ( svc ) => svc . list ( { roots : true , limit : args . maxCount } ) )
10198
102- let output : string
103- if ( args . format === "json" ) {
104- output = formatSessionJSON ( sessions )
105- } else {
106- output = formatSessionTable ( sessions )
107- }
99+ if ( sessions . length === 0 ) return
100+
101+ const output = args . format === "json" ? formatSessionJSON ( sessions ) : formatSessionTable ( sessions )
108102
109103 const shouldPaginate = process . stdout . isTTY && ! args . maxCount && args . format === "table"
110104
111105 if ( shouldPaginate ) {
112- const proc = Process . spawn ( pagerCmd ( ) , {
113- stdin : "pipe" ,
114- stdout : "inherit" ,
115- stderr : "inherit" ,
106+ yield * Effect . promise ( async ( ) => {
107+ const proc = Process . spawn ( pagerCmd ( ) , {
108+ stdin : "pipe" ,
109+ stdout : "inherit" ,
110+ stderr : "inherit" ,
111+ } )
112+
113+ if ( ! proc . stdin ) {
114+ console . log ( output )
115+ return
116+ }
117+
118+ proc . stdin . write ( output )
119+ proc . stdin . end ( )
120+ await proc . exited
116121 } )
117-
118- if ( ! proc . stdin ) {
119- console . log ( output )
120- return
121- }
122-
123- proc . stdin . write ( output )
124- proc . stdin . end ( )
125- await proc . exited
126122 } else {
127123 console . log ( output )
128124 }
129- } )
130- } ,
125+ } ) . pipe ( Effect . ensuring ( store . dispose ( ctx ) ) )
126+ } ) ,
131127} )
132128
133129function formatSessionTable ( sessions : Session . Info [ ] ) : string {
0 commit comments