feat: drop abort_current option, always keep current session alive
This commit is contained in:
parent
a563fafdcf
commit
4a9479e3a8
2 changed files with 3 additions and 22 deletions
|
|
@ -28,7 +28,7 @@ The plugin registers one tool, `session_restart`, that the agent can call when t
|
||||||
|
|
||||||
- Creates a child session (via the SDK `session.create` with `parentID`), so it shows up in the session tree under the original.
|
- Creates a child session (via the SDK `session.create` with `parentID`), so it shows up in the session tree under the original.
|
||||||
- Immediately prompts it (via `session.promptAsync`) with the focused `task` plus optional carry-over `notes` and a fresh-start preamble that points at the parent session for the full earlier conversation and tells the new session to orient itself from the working tree.
|
- Immediately prompts it (via `session.promptAsync`) with the focused `task` plus optional carry-over `notes` and a fresh-start preamble that points at the parent session for the full earlier conversation and tells the new session to orient itself from the working tree.
|
||||||
- Leaves the current session running by default, so its full history stays visible and readable in the session tree. Optionally `abort_current` freezes it instead.
|
- Leaves the current session running, so its full history stays visible and readable in the session tree.
|
||||||
- Returns the new session ID so the agent can tell you where to switch.
|
- Returns the new session ID so the agent can tell you where to switch.
|
||||||
|
|
||||||
## Static handoff text
|
## Static handoff text
|
||||||
|
|
@ -65,13 +65,11 @@ Either way the text is prepended to the handoff prompt under a `STANDING INSTRUC
|
||||||
| `notes` | string | — | Durable context to carry over: decisions, constraints, files touched, unfinished steps. Omit to rely on the working tree only. |
|
| `notes` | string | — | Durable context to carry over: decisions, constraints, files touched, unfinished steps. Omit to rely on the working tree only. |
|
||||||
| `model` | string | current | `"providerID/modelID"` for the restarted session. |
|
| `model` | string | current | `"providerID/modelID"` for the restarted session. |
|
||||||
| `agent` | string | current | Agent for the restarted session. |
|
| `agent` | string | current | Agent for the restarted session. |
|
||||||
| `abort_current` | boolean | `false` | Abort this session after restarting. Default leaves the current session alive with its history readable. |
|
|
||||||
|
|
||||||
### Notes on behavior
|
### Notes on behavior
|
||||||
|
|
||||||
- The new session keeps the fresh prompt as its user-turn text and immediately starts working. On-disk state (git status, staged or uncommitted changes) carries over because it is the same project directory.
|
- The new session keeps the fresh prompt as its user-turn text and immediately starts working. On-disk state (git status, staged or uncommitted changes) carries over because it is the same project directory.
|
||||||
- By default the original session is left running and its full transcript remains in the session tree — the clean context lives in the child session. The handoff prompt includes the parent session ID so both you and the model know where to read the earlier conversation.
|
- The original session is always left running and its full transcript remains in the session tree — the clean context lives in the child session. The handoff prompt includes the parent session ID so both you and the model know where to read the earlier conversation.
|
||||||
- `abort_current: true` freezes the original session after the new one is started. Because abort cancels the current agent turn, the tool's returned text may not be delivered to the old session — the side effects (create + prompt) complete first.
|
|
||||||
- `disable_compaction_continue` (default `true`) rejects the synthetic "continue" turn opencode would append after a compaction, so a compaction that does slip through never silently continues. Set it to `false` to keep stock behavior.
|
- `disable_compaction_continue` (default `true`) rejects the synthetic "continue" turn opencode would append after a compaction, so a compaction that does slip through never silently continues. Set it to `false` to keep stock behavior.
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
|
||||||
19
index.ts
19
index.ts
|
|
@ -6,12 +6,6 @@ export const id = "opencode-session-restart"
|
||||||
type PluginClient = PluginInput["client"]
|
type PluginClient = PluginInput["client"]
|
||||||
|
|
||||||
export type RestartPluginOptions = {
|
export type RestartPluginOptions = {
|
||||||
/**
|
|
||||||
* Abort the current session once the new session has been started.
|
|
||||||
* Default: false — the current session stays warm and its full history
|
|
||||||
* remains readable in the session tree.
|
|
||||||
*/
|
|
||||||
abort_current: boolean
|
|
||||||
/**
|
/**
|
||||||
* Reject the synthetic "continue" turn opencode appends after compaction,
|
* Reject the synthetic "continue" turn opencode appends after compaction,
|
||||||
* forcing a human (or the restart tool) to decide what happens next.
|
* forcing a human (or the restart tool) to decide what happens next.
|
||||||
|
|
@ -27,7 +21,6 @@ export type RestartPluginOptions = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_OPTIONS: RestartPluginOptions = {
|
const DEFAULT_OPTIONS: RestartPluginOptions = {
|
||||||
abort_current: false,
|
|
||||||
disable_compaction_continue: true,
|
disable_compaction_continue: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -93,7 +86,7 @@ export const server: Plugin = async ({ client }, rawOptions = {}) => {
|
||||||
"Start a fresh child session on this project with a clean context window and prompt it to continue a single focused task, " +
|
"Start a fresh child session on this project with a clean context window and prompt it to continue a single focused task, " +
|
||||||
"keeping the current session alive with its full history readable in the session tree. " +
|
"keeping the current session alive with its full history readable in the session tree. " +
|
||||||
"Use this when the current session is getting too long or about to compact, so work continues without losing context fidelity. " +
|
"Use this when the current session is getting too long or about to compact, so work continues without losing context fidelity. " +
|
||||||
"The current session is left running by default: after calling this tool, stop working here and hand off — the restarted session continues.",
|
"The current session is always left running: after calling this tool, stop working here and hand off — the restarted session continues.",
|
||||||
args: {
|
args: {
|
||||||
task: tool.schema
|
task: tool.schema
|
||||||
.string()
|
.string()
|
||||||
|
|
@ -109,13 +102,8 @@ export const server: Plugin = async ({ client }, rawOptions = {}) => {
|
||||||
.optional()
|
.optional()
|
||||||
.describe('Model for the restarted session as "providerID/modelID". Defaults to this session\'s model.'),
|
.describe('Model for the restarted session as "providerID/modelID". Defaults to this session\'s model.'),
|
||||||
agent: tool.schema.string().optional().describe("Agent for the restarted session. Defaults to the current agent."),
|
agent: tool.schema.string().optional().describe("Agent for the restarted session. Defaults to the current agent."),
|
||||||
abort_current: tool
|
|
||||||
.schema.boolean()
|
|
||||||
.optional()
|
|
||||||
.describe("Abort this session after restarting. Defaults to false — the current session stays alive."),
|
|
||||||
},
|
},
|
||||||
async execute(args, ctx) {
|
async execute(args, ctx) {
|
||||||
const abortCurrent = args.abort_current ?? options.abort_current
|
|
||||||
const title = args.task.length > MAX_TITLE_LENGTH ? `${args.task.slice(0, MAX_TITLE_LENGTH - 1)}…` : args.task
|
const title = args.task.length > MAX_TITLE_LENGTH ? `${args.task.slice(0, MAX_TITLE_LENGTH - 1)}…` : args.task
|
||||||
|
|
||||||
const created = await client.session.create({
|
const created = await client.session.create({
|
||||||
|
|
@ -137,17 +125,12 @@ export const server: Plugin = async ({ client }, rawOptions = {}) => {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
if (abortCurrent) {
|
|
||||||
await client.session.abort({ path: { id: ctx.sessionID } }).catch(() => undefined)
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title: `Restarted in session ${restartedID}`,
|
title: `Restarted in session ${restartedID}`,
|
||||||
output: `Started a fresh child session ${restartedID} with a clean context window; it is already running the focused task. The current session stays alive with its full history readable. Switch to session ${restartedID} to continue the work.`,
|
output: `Started a fresh child session ${restartedID} with a clean context window; it is already running the focused task. The current session stays alive with its full history readable. Switch to session ${restartedID} to continue the work.`,
|
||||||
metadata: {
|
metadata: {
|
||||||
restartedSessionID: restartedID,
|
restartedSessionID: restartedID,
|
||||||
parentSessionID: ctx.sessionID,
|
parentSessionID: ctx.sessionID,
|
||||||
abort_current: abortCurrent,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue