@volter/supercode-frontend-vscode 0.1.42 → 0.1.44
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/dist/extension.js +62 -39
- package/package.json +1 -1
package/dist/extension.js
CHANGED
|
@@ -410,6 +410,8 @@ export async function activate(context) {
|
|
|
410
410
|
const resourceBindings = new Map(context.workspaceState.get('supercode.sessionBindings', []));
|
|
411
411
|
const boundId = (resource) => resolveSessionBinding(resource, controls?.state.sessions ?? [], resourceBindings);
|
|
412
412
|
let applying = Promise.resolve();
|
|
413
|
+
// the reason the last send from a new chat made no conversation, said by that draft's request handler
|
|
414
|
+
let refusedSend;
|
|
413
415
|
let pendingDraft;
|
|
414
416
|
let focusedResource;
|
|
415
417
|
let focusGeneration = 0;
|
|
@@ -606,8 +608,12 @@ export async function activate(context) {
|
|
|
606
608
|
const applied = pending.then(() => undefined, () => undefined);
|
|
607
609
|
applying = applied;
|
|
608
610
|
const revealed = pending.then(async (target) => {
|
|
611
|
+
// A blank chat the workbench restored keeps the focus, except from a conversation whose turn runs or waits for an
|
|
612
|
+
// answer: after a reload mid-turn, that is the chat a person needs (its Stop button, its pending approval).
|
|
613
|
+
const live = target?.kind === 'managed' && Boolean(frontends.get(target.id)?.session.pendingRequests.size
|
|
614
|
+
|| frontends.get(target.id)?.session.descriptor?.turn_state === 'busy');
|
|
609
615
|
if (!target || !controls || applying !== applied || target.generation !== focusGeneration
|
|
610
|
-
|| focusedResource?.path.startsWith('/untitled-'))
|
|
616
|
+
|| (focusedResource?.path.startsWith('/untitled-') && !live))
|
|
611
617
|
return;
|
|
612
618
|
if (target.kind === 'managed') {
|
|
613
619
|
if ((controls.state.setup && !controls.state.setup.ready) || controls.state.activeSession !== target.id
|
|
@@ -744,13 +750,7 @@ export async function activate(context) {
|
|
|
744
750
|
const openNewChat = async () => {
|
|
745
751
|
if (!controls || !granted.has('chatSessionsProvider'))
|
|
746
752
|
throw new Error('This host does not expose native conversation creation.');
|
|
747
|
-
//
|
|
748
|
-
// would reach the person as a bare "Canceled" or not at all through the contributed-command boundary.
|
|
749
|
-
const refusal = busyRefusal(managed(), 'starting a new chat');
|
|
750
|
-
if (refusal) {
|
|
751
|
-
void vscode.window.showWarningMessage(refusal);
|
|
752
|
-
throw new vscode.CancellationError();
|
|
753
|
-
}
|
|
753
|
+
// A turn running elsewhere does not stop a draft: its first send is refused there, in the chat (`create`).
|
|
754
754
|
// Code-OSS materializes this untitled session on first send, awaiting our
|
|
755
755
|
// newChatSessionItemHandler before accepting/clearing the draft. Never boot
|
|
756
756
|
// beside the old widget and reveal another resource after it accepts input.
|
|
@@ -816,7 +816,6 @@ export async function activate(context) {
|
|
|
816
816
|
try {
|
|
817
817
|
// Open before the picker: a send can beat its result across the extension-
|
|
818
818
|
// host boundary. Materialization awaits this exact draft's choice too.
|
|
819
|
-
// Inside the try: a busy refusal is a cancellation already explained.
|
|
820
819
|
const opened = draft = await openNewChat();
|
|
821
820
|
picking = (async () => {
|
|
822
821
|
const choice = await pick();
|
|
@@ -845,6 +844,42 @@ export async function activate(context) {
|
|
|
845
844
|
// Publish capability-honest input groups only after the handoff descriptor is available.
|
|
846
845
|
if (controls?.state.connection)
|
|
847
846
|
await connectManaged().catch(error => log.warn(`Could not attach before registering chat input: ${String(error)}`));
|
|
847
|
+
const createConversation = async (inputState) => {
|
|
848
|
+
if (!controls)
|
|
849
|
+
throw new Error('The host does not expose conversation creation.');
|
|
850
|
+
const busy = busyRefusal(managed(), 'starting a new chat');
|
|
851
|
+
if (busy)
|
|
852
|
+
throw new Error(busy);
|
|
853
|
+
const draft = activeDraft();
|
|
854
|
+
await draft?.choosing;
|
|
855
|
+
if (draft && activeDraft() !== draft)
|
|
856
|
+
throw new vscode.CancellationError();
|
|
857
|
+
await controls.refresh();
|
|
858
|
+
controlsChanged.fire();
|
|
859
|
+
const choice = draft?.choice;
|
|
860
|
+
const loginHarness = choice?.kind === 'signIn' ? choice.harness : undefined;
|
|
861
|
+
if (loginHarness && !controls.state.harnesses.some(h => h.id === loginHarness && h.autoStart)) {
|
|
862
|
+
throw new Error(`Finish signing in with ${harnessDisplayName(loginHarness)} before sending.`);
|
|
863
|
+
}
|
|
864
|
+
if (choice?.kind !== 'agent' && controls.state.setup && !controls.state.setup.ready) {
|
|
865
|
+
throw new Error('Sign in before sending; use Check again after signing in.');
|
|
866
|
+
}
|
|
867
|
+
const selection = choice?.kind === 'agent' ? choice.selection
|
|
868
|
+
: { harness: loginHarness ?? controls.state.selection.harness, model: '', effort: '' };
|
|
869
|
+
const pending = applying.then(() => applySelection(selection));
|
|
870
|
+
applying = pending.then(() => undefined, () => undefined);
|
|
871
|
+
const connection = await pending;
|
|
872
|
+
// The picker shows the host's default until someone changes it; only a change is the person's choice.
|
|
873
|
+
const selected = inputState.groups.find(group => group.id === 'permissions')?.selected?.id;
|
|
874
|
+
const picked = selected === 'ask' || selected === 'autoApprove' ? selected : permission ?? newChatDefault();
|
|
875
|
+
choosePermission(connection.id, picked, permission !== undefined ? null : newChatDefault());
|
|
876
|
+
permission = undefined;
|
|
877
|
+
if (pendingDraft === draft) {
|
|
878
|
+
pendingDraft = undefined;
|
|
879
|
+
controlsChanged.fire();
|
|
880
|
+
}
|
|
881
|
+
return connection;
|
|
882
|
+
};
|
|
848
883
|
const providerControls = {
|
|
849
884
|
changed: controlsChanged.event,
|
|
850
885
|
currentOptions,
|
|
@@ -883,38 +918,19 @@ export async function activate(context) {
|
|
|
883
918
|
else
|
|
884
919
|
permission = turnPermission(value);
|
|
885
920
|
},
|
|
921
|
+
// A send that makes no conversation (another turn runs, or the host or a sign-in refuses it) answers no item: the
|
|
922
|
+
// host then runs the request on the draft itself, and its handler says why in the chat. A rejection here reaches
|
|
923
|
+
// nobody (the host's acceptInput drops it), so every refusal goes that way (#1282 review).
|
|
886
924
|
create: async (inputState) => {
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
const draft = activeDraft();
|
|
890
|
-
await draft?.choosing;
|
|
891
|
-
if (draft && activeDraft() !== draft)
|
|
892
|
-
throw new vscode.CancellationError();
|
|
893
|
-
await controls.refresh();
|
|
894
|
-
controlsChanged.fire();
|
|
895
|
-
const choice = draft?.choice;
|
|
896
|
-
const loginHarness = choice?.kind === 'signIn' ? choice.harness : undefined;
|
|
897
|
-
if (loginHarness && !controls.state.harnesses.some(h => h.id === loginHarness && h.autoStart)) {
|
|
898
|
-
throw new Error(`Finish signing in with ${harnessDisplayName(loginHarness)} before sending. Your draft is kept.`);
|
|
899
|
-
}
|
|
900
|
-
if (choice?.kind !== 'agent' && controls.state.setup && !controls.state.setup.ready) {
|
|
901
|
-
throw new Error('Sign in before sending. Your draft is kept; use Check again after signing in.');
|
|
925
|
+
try {
|
|
926
|
+
return await createConversation(inputState);
|
|
902
927
|
}
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
// The picker shows the host's default until someone changes it; only a change is the person's choice.
|
|
909
|
-
const selected = inputState.groups.find(group => group.id === 'permissions')?.selected?.id;
|
|
910
|
-
const picked = selected === 'ask' || selected === 'autoApprove' ? selected : permission ?? newChatDefault();
|
|
911
|
-
choosePermission(connection.id, picked, permission !== undefined ? null : newChatDefault());
|
|
912
|
-
permission = undefined;
|
|
913
|
-
if (pendingDraft === draft) {
|
|
914
|
-
pendingDraft = undefined;
|
|
915
|
-
controlsChanged.fire();
|
|
928
|
+
catch (error) {
|
|
929
|
+
if (error instanceof vscode.CancellationError)
|
|
930
|
+
throw error;
|
|
931
|
+
refusedSend = String(error?.message ?? error);
|
|
932
|
+
return undefined;
|
|
916
933
|
}
|
|
917
|
-
return connection;
|
|
918
934
|
},
|
|
919
935
|
resolve: (resource) => connectionFor(resource, false),
|
|
920
936
|
attached: (connection) => attachedIds.has(connection.id),
|
|
@@ -1161,6 +1177,12 @@ export async function activate(context) {
|
|
|
1161
1177
|
const handler = async (request, chatContext, stream, token) => {
|
|
1162
1178
|
await applying;
|
|
1163
1179
|
const requestedResource = chatContext.chatSessionContext?.chatSessionItem?.resource;
|
|
1180
|
+
if (refusedSend && requestedResource?.path.startsWith('/untitled-') && !boundId(requestedResource)) {
|
|
1181
|
+
const refusal = refusedSend;
|
|
1182
|
+
refusedSend = undefined;
|
|
1183
|
+
// thrown as is: the workbench writes a handler's error into the chat
|
|
1184
|
+
throw new Error(`${refusal} Nothing was sent; send it again in a new chat.`);
|
|
1185
|
+
}
|
|
1164
1186
|
if (controls?.state.setup && !controls.state.setup.ready) {
|
|
1165
1187
|
stream.markdown('Sign in before sending a message. Use **New Chat: Choose Agent** to get started.');
|
|
1166
1188
|
return {};
|
|
@@ -1713,7 +1735,8 @@ function registerSessions(context, frontends, participant, granted, handler, his
|
|
|
1713
1735
|
controller.newChatSessionItemHandler = async ({ inputState }, token) => {
|
|
1714
1736
|
if (token.isCancellationRequested)
|
|
1715
1737
|
throw new vscode.CancellationError();
|
|
1716
|
-
|
|
1738
|
+
const connection = await controls.create(inputState);
|
|
1739
|
+
return connection ? connectedItem(connection) : undefined;
|
|
1717
1740
|
};
|
|
1718
1741
|
context.subscriptions.push(controls.changed(() => {
|
|
1719
1742
|
refreshItems();
|
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.44",
|
|
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",
|