diff --git a/apps/cli/src/tui.ts b/apps/cli/src/tui.ts index 773d1e78e8..db10b2f06c 100644 --- a/apps/cli/src/tui.ts +++ b/apps/cli/src/tui.ts @@ -144,23 +144,15 @@ export async function runTui( const entry = process.argv[1] const execve = process.execve?.bind(process) const app: { current?: Context } = {} - // Resuming reproduces THIS invocation with a different id. Meta mode is a - // subcommand that rejects `--config`, while the default surface carries it, so - // both the in-place handoff and the printed command derive from one shape. - // `meta` is only reproducible for a target inside this checkout: it chdirs to - // SOURCE_ROOT itself, which would override any other workspace, so a - // cross-workspace resume takes the default surface and the caller supplies the - // directory instead. - const resumeArgs = (sessionId: string, targetCwd?: string): string[] => - workspace !== undefined && (targetCwd === undefined || targetCwd === workspace) - ? ['meta', `--resume=${sessionId}`] - : [ - `--resume=${sessionId}`, - // Both config flags must survive the handoff: resuming into a different - // tree than the session was created in would silently change the agent. - ...resolvedConfig !== undefined ? ['--config', resolvedConfig] : [], - ...resolvedConfigReplace !== undefined ? ['--config-replace', resolvedConfigReplace] : [], - ] + // Resume always enters the default surface because meta rejects parent + // options, including `--resume`. The resumed session already persists its cwd. + const resumeArgs = (sessionId: string, _targetCwd?: string): string[] => [ + `--resume=${sessionId}`, + // Both config flags must survive the handoff: resuming into a different + // tree than the session was created in would silently change the agent. + ...resolvedConfig !== undefined ? ['--config', resolvedConfig] : [], + ...resolvedConfigReplace !== undefined ? ['--config-replace', resolvedConfigReplace] : [], + ] // Mint the fresh id here rather than in the app bundle: the exit line names // the session to resume, so the launcher must know it before the tree boots. const identity: MainSessionIdentity = resumeSessionId === undefined diff --git a/packages/ui/app-boot/src/index.ts b/packages/ui/app-boot/src/index.ts index 2a2460f18e..2c2a84c18b 100644 --- a/packages/ui/app-boot/src/index.ts +++ b/packages/ui/app-boot/src/index.ts @@ -208,7 +208,7 @@ export function assertEntriesLoaded(ctx: Context, binName: string): void { * (see {@link resolveConfigPath}). * @param patches - optional overlay patches applied over the included tree * (see {@link loadPersonalPatches}); an empty list mounts none. - * @param prepare - optional host setup run against the root context before any Loader entry mounts. + * @param prepare - optional host setup run after Loader installation and before any config-tree entry mounts. * @returns the root context once every entry has started. */ export async function boot( @@ -218,10 +218,10 @@ export async function boot( prepare?: (ctx: Context) => Promise | void, ): Promise { const ctx = new Context() - await prepare?.(ctx) ctx.baseUrl = pathToFileURL(dirname(absoluteConfigPath)).href + '/' await ctx.plugin(Loader) ctx.loader.builtins.include = Include + await prepare?.(ctx) await ctx.loader.create({ name: 'cordis:include', config: { diff --git a/packages/ui/app-boot/tests/app-boot.spec.ts b/packages/ui/app-boot/tests/app-boot.spec.ts index 3da19e67c2..ba72902308 100644 --- a/packages/ui/app-boot/tests/app-boot.spec.ts +++ b/packages/ui/app-boot/tests/app-boot.spec.ts @@ -195,7 +195,11 @@ describe('boot', () => { writeFileSync(join(dir, 'noop.mjs'), 'export const name = "noop"\nexport function apply() {}\n') writeFileSync(join(dir, 'cordis.yml'), '- id: noop\n name: ./noop.mjs\n') const prepared: Context[] = [] - const ctx = await boot(NAME, join(dir, 'cordis.yml'), undefined, (hostCtx) => { prepared.push(hostCtx) }) + const ctx = await boot(NAME, join(dir, 'cordis.yml'), undefined, (hostCtx) => { + expect(hostCtx.loader).toBeDefined() + expect([...hostCtx.loader.entries()]).toEqual([]) + prepared.push(hostCtx) + }) try { expect(prepared).toEqual([ctx]) } finally { diff --git a/packages/ui/tui/src/index.ts b/packages/ui/tui/src/index.ts index 392cb0e356..7fb8cd8158 100644 --- a/packages/ui/tui/src/index.ts +++ b/packages/ui/tui/src/index.ts @@ -1676,7 +1676,9 @@ export function apply(ctx: Context, config: Config): void { initialSkill === undefined ? {} : { initialSkill }, ), { terminal: new ProcessTerminal(), - exit: code => process.exit(code), + exit: (code) => { + void ctx.fiber.dispose().finally(() => { process.exit(code) }) + }, ...resumeHost === undefined ? {} : { handoffResume: (sessionId, cwd) => resumeHost.handoff(sessionId, cwd) }, ...goodbyeMessage === undefined ? {} : { goodbyeMessage }, })