@volter/supercode-frontend-vscode 0.1.56 → 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
@@ -125,7 +125,13 @@ The host publishes durable conversation IDs and their exact harness history iden
125
125
  `POST /open` resumes only the requested saved conversation; `POST /remember` binds its
126
126
  reported native session ID to discovered history. Unknown or missing bindings fail explicitly,
127
127
  never falling back to the currently active runtime. The host may provide an `openSessionCommand`
128
- 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
129
135
  notify `supercode.frontend.focusSession` on every native focused-resource change,
130
136
  including untitled resources and leaving harness Chat (`undefined` when there is
131
137
  no focused session). This retires abandoned draft choices even when returning to
package/dist/extension.js CHANGED
@@ -2019,43 +2019,54 @@ function historyText(part) {
2019
2019
  return `**${part.title}**\n\n${part.message}`;
2020
2020
  }
2021
2021
  }
2022
- /**
2023
- * The editor's session list ALWAYS reads `timing.created` and renders the epoch
2024
- * ("57 yrs ago") when a provider supplies none — measured in
2025
- * `agentSessionsViewer`, which has no path that omits the time. `frontend.v2`
2026
- * carries no session timestamp of its own, so the true times this frontend
2027
- * knows are its own: when this window attached, and the turn boundaries it
2028
- * watched. Those are what the item gets.
2029
- */
2030
- function applyTiming(item, connection) {
2031
- const created = connection.session.attachedAtMs;
2032
- if (created === null)
2033
- return;
2034
- item.timing = {
2035
- created,
2036
- lastRequestStarted: connection.session.lastTurnStartedMs ?? undefined,
2037
- lastRequestEnded: connection.session.lastTurnEndedMs ?? undefined,
2038
- };
2039
- }
2040
2022
  function registerSessions(context, frontends, participant, granted, handler, historyParticipant, controls) {
2041
2023
  const turns = vscode;
2042
2024
  const items = () => {
2043
2025
  return (controls?.catalogue() ?? []).filter(entry => !frontends.get(entry.id)).map(entry => {
2044
- const item = controller.createChatSessionItem(vscode.Uri.from({ scheme: SESSION_SCHEME, authority: entry.id, path: '/conversation' }), entry.title);
2045
- item.description = runtimeIdentity(entry.selection.harness, entry.selection.model, controls?.effective(entry)).name;
2046
- item.status = vscode.ChatSessionStatus.Completed;
2047
- item.timing = { created: entry.created };
2048
- 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 } };
2049
2029
  });
2050
2030
  };
2051
- const connectedItem = (connection) => {
2052
- const item = controller.createChatSessionItem(sessionResource(connection), connection.label);
2053
- item.description = connection.label;
2054
- applyTiming(item, connection);
2055
- 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 });
2056
2059
  return item;
2057
2060
  };
2058
- 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
+ };
2059
2070
  const controller = vscode.chat.createChatSessionItemController(SESSION_SCHEME, async () => { refreshItems(); });
2060
2071
  context.subscriptions.push(controller, frontends.onDidChange(refreshItems));
2061
2072
  if (controls) {
@@ -2099,7 +2110,12 @@ function registerSessions(context, frontends, participant, granted, handler, his
2099
2110
  for (const state of states) {
2100
2111
  const groups = controls.options(state.sessionResource);
2101
2112
  const value = draftPermissions.get(state);
2102
- 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;
2103
2119
  }
2104
2120
  }));
2105
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.56",
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",