@volter/supercode-frontend-vscode 0.1.55 → 0.1.57

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -88,6 +88,11 @@ the pinned workbench's [first-send materialization](https://github.com/volter-ai
88
88
  and [draft acceptance](https://github.com/volter-ai/code-oss/blob/f16dc165c0dffe701a7bbf59aefb1c662b206cee/src/vs/workbench/contrib/chat/browser/widget/chatWidget.ts#L3493)
89
89
  paths. A failed startup leaves the draft available to retry.
90
90
 
91
+ New Chat highlights the agent from the focused conversation (or an already
92
+ chosen draft) before opening the blank chat. With no matching choice it keeps
93
+ the host/native default. This is a source correction with
94
+ [real Chat qualification still open](../../docs/evidence/chat-agent-picker-focus-2026-10-09.md).
95
+
91
96
  The pending agent/model choice belongs to that blank chat's untitled resource
92
97
  and is retired when another conversation opens. Cancelling or opening sign-in
93
98
  does not choose an agent. Readiness polling continues to discover
@@ -120,7 +125,13 @@ The host publishes durable conversation IDs and their exact harness history iden
120
125
  `POST /open` resumes only the requested saved conversation; `POST /remember` binds its
121
126
  reported native session ID to discovered history. Unknown or missing bindings fail explicitly,
122
127
  never falling back to the currently active runtime. The host may provide an `openSessionCommand`
123
- to reveal an exact resource through its native widget service. Cached native widgets should
128
+ to reveal an exact resource through its native widget service.
129
+ Native session-list updates reuse unchanged row objects, and readiness refreshes
130
+ skip unchanged composer option groups. Transcript and approval events remain
131
+ immediate. This removes redundant native publications; the
132
+ [Windows typing-lag cause and candidate latency remain unmeasured](../../docs/evidence/chat-composer-update-churn-2026-10-09.md).
133
+
134
+ Cached native widgets should
124
135
  notify `supercode.frontend.focusSession` on every native focused-resource change,
125
136
  including untitled resources and leaving harness Chat (`undefined` when there is
126
137
  no focused session). This retires abandoned draft choices even when returning to
package/dist/extension.js CHANGED
@@ -948,7 +948,9 @@ export async function activate(context) {
948
948
  quick.title = title;
949
949
  quick.placeholder = placeholder;
950
950
  quick.items = items;
951
- quick.activeItems = items.filter(item => item.id === currentId);
951
+ // Agent choices can also contain a model-configuration row with the same
952
+ // harness id. The ordinary agent row comes first; activate only that row.
953
+ quick.activeItems = items.filter(item => item.id === currentId).slice(0, 1);
952
954
  return new Promise(resolve => {
953
955
  quick.onDidAccept(() => resolve(quick.selectedItems[0]));
954
956
  quick.onDidHide(() => resolve(undefined));
@@ -1176,6 +1178,15 @@ export async function activate(context) {
1176
1178
  return;
1177
1179
  }
1178
1180
  await controls.refresh();
1181
+ // Capture the conversation's agent before opening the blank chat clears
1182
+ // focus. A saved conversation need not be the host's active runtime yet.
1183
+ const previousId = focusedResource ? boundId(focusedResource) : controls.state.activeSession;
1184
+ const previousAttachment = focusedResource && attachedIds.has(focusedResource.authority)
1185
+ ? frontends.get(focusedResource.authority) : undefined;
1186
+ const previousHarness = previousAttachment?.session.descriptor?.source_harness
1187
+ ?? draftSelection()?.harness
1188
+ ?? controls.state.sessions.find(session => session.id === previousId)?.selection.harness
1189
+ ?? controls.state.selection.harness;
1179
1190
  const agents = setupAgents(controls.state);
1180
1191
  const localChoices = agents.map(agent => ({ label: agent.name, id: agent.harness,
1181
1192
  description: agent.harness === 'codex' ? (agent.signedIn ? 'Signed in with ChatGPT' : 'Sign in with ChatGPT…')
@@ -1192,7 +1203,7 @@ export async function activate(context) {
1192
1203
  return;
1193
1204
  }
1194
1205
  await chooseNewChat(async () => {
1195
- const harness = await vscode.window.showQuickPick(choices, { title: 'New chat', placeHolder: 'Choose your coding agent' });
1206
+ const harness = await pickWithCurrent(choices, 'New chat', 'Choose your coding agent', previousHarness);
1196
1207
  if (!harness)
1197
1208
  return { kind: 'cancelled' };
1198
1209
  if (harness.configure) {
@@ -2008,43 +2019,54 @@ function historyText(part) {
2008
2019
  return `**${part.title}**\n\n${part.message}`;
2009
2020
  }
2010
2021
  }
2011
- /**
2012
- * The editor's session list ALWAYS reads `timing.created` and renders the epoch
2013
- * ("57 yrs ago") when a provider supplies none — measured in
2014
- * `agentSessionsViewer`, which has no path that omits the time. `frontend.v2`
2015
- * carries no session timestamp of its own, so the true times this frontend
2016
- * knows are its own: when this window attached, and the turn boundaries it
2017
- * watched. Those are what the item gets.
2018
- */
2019
- function applyTiming(item, connection) {
2020
- const created = connection.session.attachedAtMs;
2021
- if (created === null)
2022
- return;
2023
- item.timing = {
2024
- created,
2025
- lastRequestStarted: connection.session.lastTurnStartedMs ?? undefined,
2026
- lastRequestEnded: connection.session.lastTurnEndedMs ?? undefined,
2027
- };
2028
- }
2029
2022
  function registerSessions(context, frontends, participant, granted, handler, historyParticipant, controls) {
2030
2023
  const turns = vscode;
2031
2024
  const items = () => {
2032
2025
  return (controls?.catalogue() ?? []).filter(entry => !frontends.get(entry.id)).map(entry => {
2033
- const item = controller.createChatSessionItem(vscode.Uri.from({ scheme: SESSION_SCHEME, authority: entry.id, path: '/conversation' }), entry.title);
2034
- item.description = runtimeIdentity(entry.selection.harness, entry.selection.model, controls?.effective(entry)).name;
2035
- item.status = vscode.ChatSessionStatus.Completed;
2036
- item.timing = { created: entry.created };
2037
- return item;
2026
+ return { resource: vscode.Uri.from({ scheme: SESSION_SCHEME, authority: entry.id, path: '/conversation' }), label: entry.title,
2027
+ description: runtimeIdentity(entry.selection.harness, entry.selection.model, controls?.effective(entry)).name,
2028
+ status: vscode.ChatSessionStatus.Completed, timing: { created: entry.created } };
2038
2029
  });
2039
2030
  };
2040
- const connectedItem = (connection) => {
2041
- const item = controller.createChatSessionItem(sessionResource(connection), connection.label);
2042
- item.description = connection.label;
2043
- applyTiming(item, connection);
2044
- item.status = vscode.ChatSessionStatus[sessionStatus(connection.session)];
2031
+ const connectedRow = (connection) => ({
2032
+ resource: sessionResource(connection), label: connection.label, description: connection.label,
2033
+ timing: connection.session.attachedAtMs === null ? undefined : {
2034
+ created: connection.session.attachedAtMs,
2035
+ lastRequestStarted: connection.session.lastTurnStartedMs ?? undefined,
2036
+ lastRequestEnded: connection.session.lastTurnEndedMs ?? undefined,
2037
+ },
2038
+ status: vscode.ChatSessionStatus[sessionStatus(connection.session)],
2039
+ });
2040
+ const rowKey = (row) => JSON.stringify([
2041
+ row.label, row.description, row.status,
2042
+ row.timing?.created, row.timing?.lastRequestStarted, row.timing?.lastRequestEnded,
2043
+ ]);
2044
+ const cachedItems = new Map();
2045
+ const itemFor = (row) => {
2046
+ const resource = row.resource.toString();
2047
+ const key = rowKey(row);
2048
+ const cached = cachedItems.get(resource);
2049
+ if (cached?.key === key)
2050
+ return cached.item;
2051
+ // Native collection diffs compare object identity. Recreating an unchanged
2052
+ // item on each text delta sends a catalogue update and invalidates the
2053
+ // workbench's resolved-session cache while the person types in Chat.
2054
+ const item = controller.createChatSessionItem(row.resource, row.label);
2055
+ item.description = row.description;
2056
+ item.timing = row.timing;
2057
+ item.status = row.status;
2058
+ cachedItems.set(resource, { key, item });
2045
2059
  return item;
2046
2060
  };
2047
- const refreshItems = () => controller.items.replace(items().concat(frontends.all.map(connectedItem)));
2061
+ const connectedItem = (connection) => itemFor(connectedRow(connection));
2062
+ const refreshItems = () => {
2063
+ const rows = items().concat(frontends.all.map(connectedRow));
2064
+ const retained = new Set(rows.map(row => row.resource.toString()));
2065
+ for (const resource of cachedItems.keys())
2066
+ if (!retained.has(resource))
2067
+ cachedItems.delete(resource);
2068
+ controller.items.replace(rows.map(itemFor));
2069
+ };
2048
2070
  const controller = vscode.chat.createChatSessionItemController(SESSION_SCHEME, async () => { refreshItems(); });
2049
2071
  context.subscriptions.push(controller, frontends.onDidChange(refreshItems));
2050
2072
  if (controls) {
@@ -2088,7 +2110,12 @@ function registerSessions(context, frontends, participant, granted, handler, his
2088
2110
  for (const state of states) {
2089
2111
  const groups = controls.options(state.sessionResource);
2090
2112
  const value = draftPermissions.get(state);
2091
- state.groups = state.sessionResource || !value ? groups : applyOptions(groups, [{ optionId: 'permissions', value }]);
2113
+ const next = state.sessionResource || !value ? groups : applyOptions(groups, [{ optionId: 'permissions', value }]);
2114
+ // The native setter always publishes to the composer, even when its
2115
+ // values match. Readiness polls must not rebuild an unchanged picker.
2116
+ // Compare the live input state so a person's selection still wins.
2117
+ if (JSON.stringify(state.groups) !== JSON.stringify(next))
2118
+ state.groups = next;
2092
2119
  }
2093
2120
  }));
2094
2121
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@volter/supercode-frontend-vscode",
3
3
  "displayName": "Volter Harness",
4
- "version": "0.1.55",
4
+ "version": "0.1.57",
5
5
  "type": "module",
6
6
  "description": "VS Code chat-view frontend for an existing Volter Harness SDK runtime",
7
7
  "publisher": "volter-ai-dev",