@volter/supercode-frontend-vscode 0.1.38 → 0.1.39

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.
Files changed (2) hide show
  1. package/dist/extension.js +35 -2
  2. package/package.json +1 -1
package/dist/extension.js CHANGED
@@ -238,6 +238,8 @@ function writePart(stream, part, state) {
238
238
  return;
239
239
  }
240
240
  case 'answers':
241
+ if (part.approval && part.answers.length > 0 && state.quiet?.(part.answers[0].requestId))
242
+ return;
241
243
  if (part.approval && nativeInTurnApprovalCards && part.answers.length > 0) {
242
244
  stream.confirmation(part.title, part.message, {
243
245
  kind: 'supercode.inTurnApproval', version: 1, answers: part.answers,
@@ -997,6 +999,21 @@ export async function activate(context) {
997
999
  // never both answer the same request (the second answer would be refused and noted as a failure).
998
1000
  const answered = answeredRequests.get(connection.id) ?? new Set();
999
1001
  answeredRequests.set(connection.id, answered);
1002
+ // Requests whose card was not shown because this watch was going to answer them.
1003
+ const unshown = new Set();
1004
+ const answers = (requestId) => {
1005
+ if (approval() !== 'autoApprove' || token.isCancellationRequested || !canAnswer(connection))
1006
+ return false;
1007
+ const pending = connection.session.pendingRequests.get(requestId);
1008
+ // Hidden only when this watch's own sweep will answer it: one another watch claimed keeps its card here.
1009
+ if (!pending || pending.kind !== 'approval' || answered.has(requestId))
1010
+ return false;
1011
+ const decisions = acceptedDecisions(pending);
1012
+ if (decisions && !decisions.includes('allow'))
1013
+ return false;
1014
+ unshown.add(requestId);
1015
+ return true;
1016
+ };
1000
1017
  const sweep = () => {
1001
1018
  if (approval() !== 'autoApprove' || token.isCancellationRequested || !canAnswer(connection))
1002
1019
  return;
@@ -1018,15 +1035,30 @@ export async function activate(context) {
1018
1035
  log.info(text.trim());
1019
1036
  } };
1020
1037
  void connection.session.respond({ kind: 'approval', request_id: pending.id, decision: 'allow' }).then(() => {
1038
+ // A card that was never shown needs no note: its resolution line says it was allowed.
1039
+ if (unshown.has(pending.id))
1040
+ return;
1021
1041
  note(`\n_auto-approved: ${opaqueText(named ?? `request #${pending.id}`, 200)}_\n`);
1022
1042
  }, error => {
1023
1043
  note(`\nApproval failed: ${String(error.message || error)}. Use the approval buttons to answer.\n`);
1044
+ // A card this watch hid is shown now: a typed reply cannot reach a running turn, its buttons can.
1045
+ if (unshown.delete(pending.id) && connection.session.pendingRequests.has(pending.id)) {
1046
+ try {
1047
+ writeProjected(stream, projectPendingRequests([pending], {
1048
+ connectionId: connection.id,
1049
+ canRespond: connection.session.descriptor?.actions.respond !== false,
1050
+ }), granted, { toolInputs: new Map(), toolNames: new Map() });
1051
+ }
1052
+ catch {
1053
+ log.info(`Approval card for request #${pending.id} could not be shown: the response has closed`);
1054
+ }
1055
+ }
1024
1056
  });
1025
1057
  }
1026
1058
  };
1027
1059
  const sweeps = runningTurns.get(connection.id) ?? new Set();
1028
1060
  runningTurns.set(connection.id, sweeps.add(sweep));
1029
- return { sweep, dispose: () => {
1061
+ return { sweep, answers, dispose: () => {
1030
1062
  sweeps.delete(sweep);
1031
1063
  if (!sweeps.size && runningTurns.get(connection.id) === sweeps) {
1032
1064
  runningTurns.delete(connection.id);
@@ -1051,6 +1083,7 @@ export async function activate(context) {
1051
1083
  });
1052
1084
  });
1053
1085
  const watch = watchApprovals(connection, stream, token, approval);
1086
+ state.quiet = watch.answers;
1054
1087
  let completed = false;
1055
1088
  try {
1056
1089
  await connection.session.runTurn(prompt, (event) => {
@@ -1706,7 +1739,7 @@ function registerSessions(context, frontends, participant, granted, handler, his
1706
1739
  // already waiting and later ones; Ask leaves them for the person, as before.
1707
1740
  const watch = controls && !controls.attached(connection) ? controls.watchApprovals(connection, stream, token) : undefined;
1708
1741
  try {
1709
- const state = { toolInputs: new Map(), toolNames: new Map() };
1742
+ const state = { toolInputs: new Map(), toolNames: new Map(), quiet: watch?.answers };
1710
1743
  writeProjected(stream, projectPendingRequests(connection.session.pendingRequests.values(), {
1711
1744
  connectionId: connection.id,
1712
1745
  canRespond: connection.session.descriptor?.actions.respond !== false,
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.38",
4
+ "version": "0.1.39",
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",