Repository navigation
Conversation
setup() configures logging.outfile and logging.level, but the module captured both when it loaded. Anything requiring opencode.log before setup runs — a plugin spec's top-level require, for instance — pinned the default path and threshold, so the configured file stayed empty and debug lines were dropped without a trace. Read the path and the threshold per call.
Opening the panel created a server session so the panel had something to show. That session carried no title and no tokens; nothing distinguished it from one a user had worked in. The tab layout snapshot stored it all the same, so the next open restored it and displayed "New session". Leave the tab empty instead. messaging.send_message creates the session when the first prompt arrives, waits until the session resource reports current, and submits the mode, model, context and variant captured at submit time, so a change made in another tab during that wait cannot redirect the prompt. The snapshot stores only tabs that carry a session, and its write names the stored ids, the active index and the trigger (exit, change <group>, group switch, manual); a snapshot lookup that fails names the session id it could not read.
The "New session" report could not be traced: the snapshot lookup that failed and the write that stored the empty session both returned without a word. A logged outcome is the difference between a guess and a lead. Cover the boundaries that decide the panel's content: observation resource loads, stream failures and event routing; contract checks; port mapping loads; session part lookups; store listeners; history reads and writes.
The v2 service sends text, reasoning and tool parts without a stable part id, so the plugin synthesizes one as owner ":" kind ":" key and only ever compares it. A colon inside the owner lets two different coordinates produce the same string, which renders two parts as one. Ids without a colon is current server behaviour, but that is an external contract; check it where the id is synthesized instead of assuming it.
The empty multi-select answer needs a second Enter and the test waited 200ms for it. That is enough locally and not on the macOS runners.
24eae9d to
8d29476
Compare
|
I like the idea of not creating a real session until a prompt is sent. I have so many empty sessions. 😅. I will play with this MR today. Thanks |
|
Maybe I did not understand correctly the behavior, but I tought that creating a new session will not persist it. Open the panel create a new session And the new session is visible in the session switcher. |
|
Right — opening in a directory with nothing to restore no longer creates a session; the first prompt does. The new-session action is separate: it still creates one right away(After all, it's an intention), |
|
However, accidental triggers are indeed possible, so we might as well adjust it in this PR. This would also be more consistent with TUI behavior. This is actually the first time I've used this shortcut in opencode.nvim. I'll probably have to wait until I get home from work to handle it, though. |
|
Perfect no problems, I also think we should match the TUI on this aspect. |
|
There’s an issue with the latest commit. I’ll deal with it when I get home...... |
|
I don't usually use this tab feature, but I've noticed that after opening it with N, mashing 1/2 randomly makes it quite easy for two tabs to point to the same session, which is almost never what we want. |
`<c-x>N` and switching to a tab without a session both went through
`M.open`, which resumed the last workspace session. The resume ran through
`set_active`, which bound that session to whichever tab was active, so the
tab that already owned it ended up duplicated.
Sessions are now owned by the tab: `runtime.active_session` is the source
of truth, `store.active_session` only projects the active tab, and asking
for a session another tab owns activates that tab instead of creating a
second one. `verify_unique_session_tabs` reports a violation loudly at
every point that mutates the registry.
An empty tab stays empty: `M.open({ draft = true })` skips the resume
branch, and the first prompt creates the session.
|
@sudo-tee plz try and feel free to adjust what you need, i need to go to bad (。・ω・。)ノ♡ |
TL;DR — opening the panel no longer creates a session. The first prompt does, and the session stays in the single tab that owns it.
Opening created a session so the panel had something to show. It carried no prompt, so nothing in the snapshot separated it from a session someone had worked in, and the next open restored it as "New session". Which write stored that id could not be recovered afterwards: writes recorded neither the ids nor a trigger, and a failed lookup did not name the missing id.
A tab now stays empty until a prompt arrives.
send_messagecreates the session and waits for the session resource to be current before sending, because a submit against a resource still syncing is rejected.A session belongs to exactly one tab. Asking for a session another tab already holds focuses that tab; binding it twice raises instead of quietly producing a second tab. The tab runtime owns that fact;
store.active_sessionis a projection of the active tab.On the write side, a tab without a session produces no snapshot entry, and every write logs the stored ids, the active index and its trigger. A snapshot written by an older version may already hold an empty session: it restores once, unfiltered, and the log names the write that stored it.
Also in this branch, separable if unwanted:
:are rejected — the only change that can reject data the old code accepted; revert that commit alone if you disagreeVerified in an isolated instance: opening leaves no server session, the first prompt creates and sends one, restarting restores it.
./run_tests.shpasses.