feat(opencode): open a fresh session on clear (#1300)

* test(opencode): specify fresh-session clear

* feat(opencode): open a fresh session on clear

* fix(opencode): release clear latch on cancel

* fix(opencode): retry transient clear handoffs

* fix(opencode): confirm clear archive delivery

* fix(web): preserve superseded session access

* fix(clear): invalidate transferred schedules

* fix(runner): restore live spawn dedupe

* fix(clear): preserve latched scheduled prompts

* fix(runner): quarantine unverified children

* fix(clear): retain handoff retry ownership

* fix(runner): release recovered spawn dedupe

* fix(clear): retain archive retry ownership

* fix(clear): settle rejected immediate prompts

* fix(clear): block reopening replaced sources

* fix(clear): settle prompts when clear is cancelled

* fix(clear): make fresh-session handoff durable

* fix(clear): finalize only after native cleanup

* fix(clear): abort failed native handoffs

* fix(clear): gate recovery on cleanup proof

* fix(clear): retry metadata persistence failures

* fix(clear): preserve handoff ownership through teardown

* fix(clear): abort incomplete cleanup reservations

* fix(clear): require explicit exit before abort

* fix(clear): verify owner exit before recovery

* fix(clear): guard recovery handoff races

* fix(clear): serialize cleanup callbacks

* fix(clear): make callback retries idempotent

* fix(clear): bind callbacks to reservations

* fix(clear): recover pending spawns

* fix(clear): deduplicate held prompts

* fix(clear): validate redirect ownership

* fix(clear): replay prompts in FIFO order

* fix(clear): gate replacement delivery
This commit is contained in:
Junmo Kim
2026-08-03 18:06:39 +08:00
committed by GitHub
parent 1b8cc334ea
commit f44c9ff3e6
41 changed files with 3209 additions and 73 deletions
+3 -6
View File
@@ -119,11 +119,8 @@ describe('resolveOpencodeSlashCommand', () => {
}
});
it('returns a not-yet-supported message for /clear', () => {
expect(resolveOpencodeSlashCommand('/clear', state)).toEqual({
kind: 'handled',
message: '/clear is not yet supported in HAPI OpenCode sessions.'
});
it('resolves builtin /clear to the dedicated fresh-session operation', () => {
expect(resolveOpencodeSlashCommand('/clear', state)).toEqual({ kind: 'clear' });
});
it('resolves /compact to a dedicated kind so the launcher can bridge to native compaction asynchronously', () => {
@@ -168,7 +165,7 @@ describe('resolveOpencodeSlashCommand', () => {
expect(help.message).toContain('/plan');
expect(help.message).toContain('/permissions');
expect(help.message).toContain('/compact` — compact (summarize) the OpenCode session context (remote sessions only)');
expect(help.message).toContain('/clear` is not yet supported');
expect(help.message).toContain('/clear` — archive this HAPI session and open a fresh OpenCode session');
}
});
+5 -6
View File
@@ -24,6 +24,9 @@ export type OpencodeSlashResolution =
// synchronous 'handled' shape below. The launcher (runOpencode.ts)
// intercepts this kind and drives that flow itself.
| { kind: 'compact' }
// /clear exits the current runner-backed HAPI process after its FIFO
// predecessors finish, then asks the hub to spawn a fresh OpenCode one.
| { kind: 'clear' }
| {
kind: 'handled';
message: string;
@@ -174,10 +177,7 @@ export function resolveOpencodeSlashCommand(
}
if (command === 'clear') {
return {
kind: 'handled',
message: `/${command} is not yet supported in HAPI OpenCode sessions.`
};
return { kind: 'clear' };
}
if (command === 'init') {
@@ -204,12 +204,11 @@ export function resolveOpencodeSlashCommand(
'- `/default` — return to default permission mode',
'- `/init [extra]` — generate or refresh AGENTS.md for this project',
'- `/compact` — compact (summarize) the OpenCode session context (remote sessions only)',
'- `/clear` — archive this HAPI session and open a fresh OpenCode session',
'',
'Model, reasoning effort, and permission mode have dedicated buttons in the composer. ' +
'You can still type `/model`, `/reasoning`, or `/permissions` if you prefer.',
'',
'`/clear` is not yet supported in HAPI OpenCode sessions.',
'',
'Custom commands from `~/.config/opencode/command` or `.opencode/command` are expanded before sending.'
].join('\n')
};