@volter/supercode-frontend-vscode 0.1.37 → 0.1.38
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 +2 -1
- package/dist/extension.js +58 -32
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -160,7 +160,8 @@ default is never stored as a choice (a pick equal to the default follows the def
|
|
|
160
160
|
changes), and an Auto approve is never stored for a conversation that cannot answer. Conversations opened before 0.1.36 saved their picker's
|
|
161
161
|
**Ask** when opened and keep it. Auto approve approves the requests the harness would ask you about, including requests to run
|
|
162
162
|
outside its sandbox (Codex's approval requests are its sandbox escalations); the harness's deny
|
|
163
|
-
rules still apply. Each request it answers is noted in the turn ("auto-approved: …").
|
|
163
|
+
rules still apply. Each request it answers is noted in the turn ("auto-approved: …"). A turn
|
|
164
|
+
re-joined after a page reload (the conversation's active response) is answered the same way. Unsupported modes are refused. Unanswerable
|
|
164
165
|
harnesses show **Harness permissions**. Previously answered requests cannot affect another
|
|
165
166
|
connection. Native command-button fallback limitations are documented below.
|
|
166
167
|
|
package/dist/extension.js
CHANGED
|
@@ -369,6 +369,7 @@ export async function activate(context) {
|
|
|
369
369
|
};
|
|
370
370
|
// The approval sweeps of each conversation's running turns, so a picker change reaches a turn already running.
|
|
371
371
|
const runningTurns = new Map();
|
|
372
|
+
const answeredRequests = new Map();
|
|
372
373
|
// The host's default for a conversation no one has chosen for (Model Editor declares Auto approve).
|
|
373
374
|
const hostDefault = () => controls?.state.defaultPermission === 'autoApprove' ? 'autoApprove' : 'ask';
|
|
374
375
|
const canAnswer = (connection) => Boolean(connection.session.descriptor?.actions.respond && connection.session.permissions.has('approve'));
|
|
@@ -882,6 +883,7 @@ export async function activate(context) {
|
|
|
882
883
|
attached: (connection) => attachedIds.has(connection.id),
|
|
883
884
|
catalogue: () => controls?.state.sessions ?? [],
|
|
884
885
|
bindings: boundId,
|
|
886
|
+
watchApprovals: (connection, stream, token) => watchApprovals(connection, stream, token, () => approvalFor(connection.id)),
|
|
885
887
|
};
|
|
886
888
|
context.subscriptions.push(vscode.commands.registerCommand('supercode.frontend.activateSession', async (resource) => { await connectionFor(vscode.Uri.parse(resource)); }));
|
|
887
889
|
// The host's native focus event is authoritative even when a cached model
|
|
@@ -986,25 +988,15 @@ export async function activate(context) {
|
|
|
986
988
|
});
|
|
987
989
|
}));
|
|
988
990
|
context.subscriptions.push({ dispose: () => frontends.dispose() });
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
canRespond: connection.session.descriptor?.actions.respond !== false,
|
|
999
|
-
};
|
|
1000
|
-
const cancellation = token.onCancellationRequested(() => {
|
|
1001
|
-
void connection.session.interrupt().catch(() => {
|
|
1002
|
-
// The runtime may already be idle; interrupting twice is not an error
|
|
1003
|
-
// this view reports.
|
|
1004
|
-
});
|
|
1005
|
-
});
|
|
1006
|
-
// Read at every event and on every picker change, so switching to Auto approve mid-turn
|
|
1007
|
-
// answers the approvals already waiting and the ones after them.
|
|
991
|
+
// Auto-answers a conversation's approvals while a response is written into `stream`: read at every event
|
|
992
|
+
// (`sweep`) and on every picker change for that conversation, so switching to Auto approve mid-turn answers
|
|
993
|
+
// the approvals already waiting and the ones after them. Used by a turn this window runs and by a turn it
|
|
994
|
+
// re-joins after a reload (the session's active response), whose original handler is gone.
|
|
995
|
+
const watchApprovals = (connection, stream, token, approval) => {
|
|
996
|
+
// One answered set per conversation, shared by every watch on it, so a re-joined response and a live turn
|
|
997
|
+
// never both answer the same request (the second answer would be refused and noted as a failure).
|
|
998
|
+
const answered = answeredRequests.get(connection.id) ?? new Set();
|
|
999
|
+
answeredRequests.set(connection.id, answered);
|
|
1008
1000
|
const sweep = () => {
|
|
1009
1001
|
if (approval() !== 'autoApprove' || token.isCancellationRequested || !canAnswer(connection))
|
|
1010
1002
|
return;
|
|
@@ -1034,18 +1026,41 @@ export async function activate(context) {
|
|
|
1034
1026
|
};
|
|
1035
1027
|
const sweeps = runningTurns.get(connection.id) ?? new Set();
|
|
1036
1028
|
runningTurns.set(connection.id, sweeps.add(sweep));
|
|
1029
|
+
return { sweep, dispose: () => {
|
|
1030
|
+
sweeps.delete(sweep);
|
|
1031
|
+
if (!sweeps.size && runningTurns.get(connection.id) === sweeps) {
|
|
1032
|
+
runningTurns.delete(connection.id);
|
|
1033
|
+
answeredRequests.delete(connection.id);
|
|
1034
|
+
}
|
|
1035
|
+
} };
|
|
1036
|
+
};
|
|
1037
|
+
const runTurnInto = async (connection, prompt, stream, token, approval) => {
|
|
1038
|
+
if (approval() === 'autoApprove' && !canAnswer(connection)) {
|
|
1039
|
+
throw new Error('This harness does not support automatic approval through Chat. Select Harness permissions.');
|
|
1040
|
+
}
|
|
1041
|
+
const state = { toolInputs: new Map(), toolNames: new Map() };
|
|
1042
|
+
const projection = {
|
|
1043
|
+
connectionId: connection.id,
|
|
1044
|
+
pendingRequest: (requestId) => connection.session.pendingRequests.get(requestId) ?? connection.session.resolvedRequests.get(requestId),
|
|
1045
|
+
canRespond: connection.session.descriptor?.actions.respond !== false,
|
|
1046
|
+
};
|
|
1047
|
+
const cancellation = token.onCancellationRequested(() => {
|
|
1048
|
+
void connection.session.interrupt().catch(() => {
|
|
1049
|
+
// The runtime may already be idle; interrupting twice is not an error
|
|
1050
|
+
// this view reports.
|
|
1051
|
+
});
|
|
1052
|
+
});
|
|
1053
|
+
const watch = watchApprovals(connection, stream, token, approval);
|
|
1037
1054
|
let completed = false;
|
|
1038
1055
|
try {
|
|
1039
1056
|
await connection.session.runTurn(prompt, (event) => {
|
|
1040
1057
|
writeProjected(stream, projectEvent(event, projection), granted, state);
|
|
1041
|
-
sweep();
|
|
1058
|
+
watch.sweep();
|
|
1042
1059
|
});
|
|
1043
1060
|
completed = true;
|
|
1044
1061
|
}
|
|
1045
1062
|
finally {
|
|
1046
|
-
|
|
1047
|
-
if (!sweeps.size && runningTurns.get(connection.id) === sweeps)
|
|
1048
|
-
runningTurns.delete(connection.id);
|
|
1063
|
+
watch.dispose();
|
|
1049
1064
|
cancellation.dispose();
|
|
1050
1065
|
if (controls && !attachedIds.has(connection.id)) {
|
|
1051
1066
|
if (connection.session.descriptor?.session_id)
|
|
@@ -1686,18 +1701,29 @@ function registerSessions(context, frontends, participant, granted, handler, his
|
|
|
1686
1701
|
requestHandler: boundHandler,
|
|
1687
1702
|
activeResponseCallback: busy
|
|
1688
1703
|
? async (stream, token) => {
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
writeProjected(stream,
|
|
1704
|
+
// A turn re-joined after a reload has lost the handler that ran it, so its approvals are
|
|
1705
|
+
// answered here under the conversation's mode (t_39dac582): Auto approve answers the cards
|
|
1706
|
+
// already waiting and later ones; Ask leaves them for the person, as before.
|
|
1707
|
+
const watch = controls && !controls.attached(connection) ? controls.watchApprovals(connection, stream, token) : undefined;
|
|
1708
|
+
try {
|
|
1709
|
+
const state = { toolInputs: new Map(), toolNames: new Map() };
|
|
1710
|
+
writeProjected(stream, projectPendingRequests(connection.session.pendingRequests.values(), {
|
|
1696
1711
|
connectionId: connection.id,
|
|
1697
|
-
pendingRequest: (id) => connection.session.pendingRequests.get(id) ?? connection.session.resolvedRequests.get(id),
|
|
1698
1712
|
canRespond: connection.session.descriptor?.actions.respond !== false,
|
|
1699
1713
|
}), granted, state);
|
|
1700
|
-
|
|
1714
|
+
watch?.sweep();
|
|
1715
|
+
await observeActiveResponse(connection.session, token, (event) => {
|
|
1716
|
+
writeProjected(stream, projectEvent(event, {
|
|
1717
|
+
connectionId: connection.id,
|
|
1718
|
+
pendingRequest: (id) => connection.session.pendingRequests.get(id) ?? connection.session.resolvedRequests.get(id),
|
|
1719
|
+
canRespond: connection.session.descriptor?.actions.respond !== false,
|
|
1720
|
+
}), granted, state);
|
|
1721
|
+
watch?.sweep();
|
|
1722
|
+
});
|
|
1723
|
+
}
|
|
1724
|
+
finally {
|
|
1725
|
+
watch?.dispose();
|
|
1726
|
+
}
|
|
1701
1727
|
}
|
|
1702
1728
|
: undefined,
|
|
1703
1729
|
};
|
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.
|
|
4
|
+
"version": "0.1.38",
|
|
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",
|