@volter/supercode-frontend-vscode 0.1.28 → 0.1.29
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 +25 -3
- package/dist/extension.js +145 -35
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -73,12 +73,29 @@ picker includes the official choice on supported hosts; with no choices it retur
|
|
|
73
73
|
to setup. Model
|
|
74
74
|
and reasoning are sent as empty values, leaving both at the harness's own defaults,
|
|
75
75
|
even if the previous conversation used explicit settings. Cancelling the agent
|
|
76
|
-
picker
|
|
76
|
+
picker starts no backend conversation.
|
|
77
|
+
|
|
78
|
+
The native blank chat opens before the picker appears. First send waits for the
|
|
79
|
+
choice and the host's new connection through Code-OSS's session-creation handler;
|
|
80
|
+
the composer keeps the draft until the request is accepted. There is no later
|
|
81
|
+
conversation swap that can hide a message sent while the agent starts. This follows
|
|
82
|
+
the pinned workbench's [first-send materialization](https://github.com/volter-ai/code-oss/blob/f16dc165c0dffe701a7bbf59aefb1c662b206cee/src/vs/workbench/contrib/chat/common/chatService/chatServiceImpl.ts#L1272)
|
|
83
|
+
and [draft acceptance](https://github.com/volter-ai/code-oss/blob/f16dc165c0dffe701a7bbf59aefb1c662b206cee/src/vs/workbench/contrib/chat/browser/widget/chatWidget.ts#L3493)
|
|
84
|
+
paths. A failed startup leaves the draft available to retry.
|
|
85
|
+
|
|
86
|
+
The pending agent/model choice belongs to that blank chat's untitled resource
|
|
87
|
+
and is retired when another conversation opens. Cancelling or opening sign-in
|
|
88
|
+
does not choose an agent. Readiness polling and **Check again** still discover
|
|
89
|
+
agents while a draft is open, updating the welcome and model catalogue without
|
|
90
|
+
replacing its widget or input. First send refreshes readiness; after a native
|
|
91
|
+
sign-in choice it uses that agent once ready, otherwise it keeps the draft with
|
|
92
|
+
a visible sign-in error.
|
|
77
93
|
|
|
78
94
|
The composer's native **Model settings** control offers **Choose model and reasoning
|
|
79
95
|
for a new chat…** for Claude Code and Codex. This optional path retains the model
|
|
80
96
|
list, exact model ID entry and reasoning choices. Only completing the choices
|
|
81
|
-
|
|
97
|
+
configures the new blank chat; its backend starts on first send. Cancelling a
|
|
98
|
+
choice starts no backend and leaves the blank chat available.
|
|
82
99
|
A conversation's harness, model and reasoning remain fixed: this integration does
|
|
83
100
|
not advertise hot swapping. The built-in model picker still displays the selected
|
|
84
101
|
model and provider icon; nondelegating session providers cannot add its Manage
|
|
@@ -93,7 +110,12 @@ The host publishes durable conversation IDs and their exact harness history iden
|
|
|
93
110
|
reported native session ID to discovered history. Unknown or missing bindings fail explicitly,
|
|
94
111
|
never falling back to the currently active runtime. The host may provide an `openSessionCommand`
|
|
95
112
|
to reveal an exact resource through its native widget service. Cached native widgets should
|
|
96
|
-
notify `supercode.frontend.
|
|
113
|
+
notify `supercode.frontend.focusSession` on every native focused-resource change,
|
|
114
|
+
including untitled resources and leaving harness Chat (`undefined` when there is
|
|
115
|
+
no focused session). This retires abandoned draft choices even when returning to
|
|
116
|
+
the same cached conversation. Managed resources then notify
|
|
117
|
+
`supercode.frontend.activateSession` to restore their exact backend. The frontend
|
|
118
|
+
owns no processes.
|
|
97
119
|
|
|
98
120
|
The permission group offers **Ask for approval** and, on an answerable interactive attachment,
|
|
99
121
|
**Auto approve**. Policies are scoped by conversation and captured for each turn; automatic
|
package/dist/extension.js
CHANGED
|
@@ -321,6 +321,21 @@ export async function activate(context) {
|
|
|
321
321
|
const resourceBindings = new Map(context.workspaceState.get('supercode.sessionBindings', []));
|
|
322
322
|
const boundId = (resource) => resolveSessionBinding(resource, controls?.state.sessions ?? [], resourceBindings);
|
|
323
323
|
let applying = Promise.resolve();
|
|
324
|
+
let pendingDraft;
|
|
325
|
+
let focusedResource;
|
|
326
|
+
const activeDraft = () => pendingDraft?.resource && pendingDraft.resource.toString() === focusedResource?.toString() ? pendingDraft : undefined;
|
|
327
|
+
const draftSelection = () => {
|
|
328
|
+
const choice = activeDraft()?.choice;
|
|
329
|
+
return choice?.kind === 'agent' ? choice.selection : undefined;
|
|
330
|
+
};
|
|
331
|
+
const focusSession = (resource) => {
|
|
332
|
+
const changed = focusedResource?.toString() !== resource?.toString();
|
|
333
|
+
focusedResource = resource;
|
|
334
|
+
if (pendingDraft?.resource && pendingDraft.resource.toString() !== resource?.toString())
|
|
335
|
+
pendingDraft = undefined;
|
|
336
|
+
if (changed)
|
|
337
|
+
controlsChanged.fire();
|
|
338
|
+
};
|
|
324
339
|
const frontends = new SupercodeFrontends();
|
|
325
340
|
// Runtimes attached by address ("Set Runtime Token", "Attach to Runtime")
|
|
326
341
|
// beside a host's managed conversation. The host's catalogue does not know
|
|
@@ -343,6 +358,9 @@ export async function activate(context) {
|
|
|
343
358
|
if (focusedAttached)
|
|
344
359
|
return runtimeIdentity(focusedAttached.session.descriptor?.source_harness, focusedAttached.session.descriptor?.model);
|
|
345
360
|
const descriptor = managed()?.session.descriptor;
|
|
361
|
+
const selection = draftSelection();
|
|
362
|
+
if (selection)
|
|
363
|
+
return runtimeIdentity(selection.harness, selection.model);
|
|
346
364
|
return runtimeIdentity(controls?.state.selection.harness ?? descriptor?.source_harness, controls?.state.selection.model || controls?.state.actualModel || descriptor?.model);
|
|
347
365
|
};
|
|
348
366
|
const icon = () => {
|
|
@@ -357,7 +375,9 @@ export async function activate(context) {
|
|
|
357
375
|
provideLanguageModelChatInformation: () => {
|
|
358
376
|
if (controls.state.setup && !controls.state.setup.ready)
|
|
359
377
|
return [];
|
|
360
|
-
const
|
|
378
|
+
const draft = draftSelection();
|
|
379
|
+
const selection = draft ?? controls.state.selection;
|
|
380
|
+
const models = draft ? controls.state.modelsByHarness?.[selection.harness] ?? [] : controls.state.models;
|
|
361
381
|
// A running harness does not advertise hot model changes. Configuration
|
|
362
382
|
// belongs to the explicit new-conversation flow.
|
|
363
383
|
const choices = models.filter(model => model.id === selection.model);
|
|
@@ -401,7 +421,7 @@ export async function activate(context) {
|
|
|
401
421
|
await frontends.disconnect(connection.id);
|
|
402
422
|
const connection = await frontends.connect({ connectionId: id, baseUrl: env.SUPERCODE_FRONTEND_URL,
|
|
403
423
|
token: await readCredentialFile(env.SUPERCODE_FRONTEND_CREDENTIAL_FILE), clientId: env.SUPERCODE_FRONTEND_CLIENT_ID,
|
|
404
|
-
permissions: normalizePermissions(env.SUPERCODE_FRONTEND_PERMISSIONS, ['observe']), label:
|
|
424
|
+
permissions: normalizePermissions(env.SUPERCODE_FRONTEND_PERMISSIONS, ['observe']), label: runtimeIdentity(controls.state.selection.harness, controls.state.selection.model || controls.state.actualModel).name }, log);
|
|
405
425
|
if (!connection)
|
|
406
426
|
throw new Error('Could not connect to the requested conversation.');
|
|
407
427
|
return connection;
|
|
@@ -441,18 +461,23 @@ export async function activate(context) {
|
|
|
441
461
|
refreshingSetup ??= (async () => {
|
|
442
462
|
if (!controls)
|
|
443
463
|
return;
|
|
464
|
+
// Discover and publish readiness even while a blank chat holds a draft.
|
|
465
|
+
// Only the automatic reveal is suppressed; discovery must never stall.
|
|
444
466
|
await controls.refresh();
|
|
467
|
+
controlsChanged.fire();
|
|
468
|
+
const preserveDraft = focusedResource?.path.startsWith('/untitled-');
|
|
445
469
|
if (controls.state.setup?.ready) {
|
|
446
470
|
setupRevealed = false;
|
|
447
471
|
await connectManaged();
|
|
448
472
|
controlsChanged.fire();
|
|
449
|
-
if (!setupHandoffComplete())
|
|
473
|
+
if (!preserveDraft && !setupHandoffComplete())
|
|
450
474
|
await revealManaged();
|
|
451
475
|
}
|
|
452
476
|
else {
|
|
453
477
|
setupHandoff = undefined;
|
|
454
478
|
controlsChanged.fire();
|
|
455
|
-
|
|
479
|
+
if (!preserveDraft)
|
|
480
|
+
await revealSetup();
|
|
456
481
|
}
|
|
457
482
|
})().finally(() => { refreshingSetup = undefined; });
|
|
458
483
|
return refreshingSetup;
|
|
@@ -488,6 +513,7 @@ export async function activate(context) {
|
|
|
488
513
|
terminal.show();
|
|
489
514
|
}));
|
|
490
515
|
const connectionFor = async (resource) => {
|
|
516
|
+
focusSession(resource);
|
|
491
517
|
if (!controls) {
|
|
492
518
|
const connection = frontends.get(resource.authority);
|
|
493
519
|
if (!connection)
|
|
@@ -525,7 +551,7 @@ export async function activate(context) {
|
|
|
525
551
|
controlsChanged.fire();
|
|
526
552
|
return connection;
|
|
527
553
|
};
|
|
528
|
-
async function applySelection(selection
|
|
554
|
+
async function applySelection(selection) {
|
|
529
555
|
if (!controls)
|
|
530
556
|
throw new Error('This host does not expose harness or model configuration.');
|
|
531
557
|
const active = managed();
|
|
@@ -534,13 +560,61 @@ export async function activate(context) {
|
|
|
534
560
|
await controls.select(selection);
|
|
535
561
|
await connectManaged();
|
|
536
562
|
controlsChanged.fire();
|
|
537
|
-
if (openChat)
|
|
538
|
-
await revealManaged();
|
|
539
563
|
}
|
|
540
|
-
const
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
564
|
+
const openNewChat = async () => {
|
|
565
|
+
if (!controls || !granted.has('chatSessionsProvider'))
|
|
566
|
+
throw new Error('This host does not expose native conversation creation.');
|
|
567
|
+
const active = managed();
|
|
568
|
+
if (active?.session.descriptor?.turn_state === 'busy' || active?.session.pendingRequests.size)
|
|
569
|
+
throw new Error('Finish or cancel the current turn before starting a new chat.');
|
|
570
|
+
// Code-OSS materializes this untitled session on first send, awaiting our
|
|
571
|
+
// newChatSessionItemHandler before accepting/clearing the draft. Never boot
|
|
572
|
+
// beside the old widget and reveal another resource after it accepts input.
|
|
573
|
+
if (!controls.state.openSessionCommand)
|
|
574
|
+
throw new Error('The host cannot reveal a new conversation.');
|
|
575
|
+
// Use Code-OSS's untitled URI format and its existing native widget bridge.
|
|
576
|
+
// Blank sessions resolve content lazily, so a content-provider callback
|
|
577
|
+
// cannot be used to discover which resource owns the pending selection.
|
|
578
|
+
const draft = { resource: vscode.Uri.from({ scheme: SESSION_SCHEME, path: `/untitled-${randomUUID()}` }) };
|
|
579
|
+
pendingDraft = draft;
|
|
580
|
+
focusedResource = draft.resource;
|
|
581
|
+
focusedAttached = undefined;
|
|
582
|
+
controlsChanged.fire();
|
|
583
|
+
await vscode.commands.executeCommand(controls.state.openSessionCommand, draft.resource.toString());
|
|
584
|
+
if (pendingDraft !== draft)
|
|
585
|
+
throw new vscode.CancellationError();
|
|
586
|
+
return draft;
|
|
587
|
+
};
|
|
588
|
+
const chooseNewChat = async (pick) => {
|
|
589
|
+
if (pendingDraft?.choosing)
|
|
590
|
+
throw new Error('Finish choosing an agent before starting another chat.');
|
|
591
|
+
// Open before the picker: a send can beat its result across the extension-
|
|
592
|
+
// host boundary. Materialization awaits this exact draft's choice too.
|
|
593
|
+
const draft = await openNewChat();
|
|
594
|
+
const picking = (async () => {
|
|
595
|
+
const choice = await pick();
|
|
596
|
+
if (activeDraft() !== draft)
|
|
597
|
+
throw new vscode.CancellationError();
|
|
598
|
+
draft.choice = choice;
|
|
599
|
+
controlsChanged.fire();
|
|
600
|
+
if (choice.kind !== 'agent')
|
|
601
|
+
throw new vscode.CancellationError();
|
|
602
|
+
})();
|
|
603
|
+
draft.choosing = picking;
|
|
604
|
+
try {
|
|
605
|
+
await picking;
|
|
606
|
+
}
|
|
607
|
+
catch (error) {
|
|
608
|
+
if (!(error instanceof vscode.CancellationError))
|
|
609
|
+
throw error;
|
|
610
|
+
}
|
|
611
|
+
finally {
|
|
612
|
+
if (draft.choosing === picking)
|
|
613
|
+
draft.choosing = undefined;
|
|
614
|
+
if (draft.choice?.kind === 'signIn') {
|
|
615
|
+
void refreshSetup().catch(error => log.warn(`Could not refresh sign-in: ${String(error)}`)).finally(pollSetup);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
544
618
|
};
|
|
545
619
|
// Publish capability-honest input groups only after the handoff descriptor is available.
|
|
546
620
|
if (controls?.state.connection)
|
|
@@ -561,7 +635,7 @@ export async function activate(context) {
|
|
|
561
635
|
if (selected && ['claude-code', 'codex'].includes(selected.selection.harness)) {
|
|
562
636
|
// Native session-option commands remain reachable for nondelegating providers,
|
|
563
637
|
// whose built-in model picker deliberately omits Manage Models. Do not advertise
|
|
564
|
-
// hot swapping: the command
|
|
638
|
+
// hot swapping: the command configures a separate native blank chat.
|
|
565
639
|
// A locked selected item hides the entire native dropdown, including commands.
|
|
566
640
|
const item = { id: 'settings', name: 'Model settings' };
|
|
567
641
|
groups.push({ id: 'modelSettings', name: 'Model', items: [item], selected: item,
|
|
@@ -581,17 +655,45 @@ export async function activate(context) {
|
|
|
581
655
|
create: async (inputState) => {
|
|
582
656
|
if (!controls)
|
|
583
657
|
throw new Error('The host does not expose conversation creation.');
|
|
584
|
-
|
|
658
|
+
const draft = activeDraft();
|
|
659
|
+
await draft?.choosing;
|
|
660
|
+
if (draft && activeDraft() !== draft)
|
|
661
|
+
throw new vscode.CancellationError();
|
|
662
|
+
await controls.refresh();
|
|
663
|
+
controlsChanged.fire();
|
|
664
|
+
const choice = draft?.choice;
|
|
665
|
+
const loginHarness = choice?.kind === 'signIn' ? choice.harness : undefined;
|
|
666
|
+
if (loginHarness && !controls.state.harnesses.some(h => h.id === loginHarness && h.autoStart)) {
|
|
667
|
+
throw new Error(`Finish signing in with ${harnessDisplayName(loginHarness)} before sending. Your draft is kept.`);
|
|
668
|
+
}
|
|
669
|
+
if (choice?.kind !== 'agent' && controls.state.setup && !controls.state.setup.ready) {
|
|
670
|
+
throw new Error('Sign in before sending. Your draft is kept; use Check again after signing in.');
|
|
671
|
+
}
|
|
672
|
+
const selection = choice?.kind === 'agent' ? choice.selection
|
|
673
|
+
: { harness: loginHarness ?? controls.state.selection.harness, model: '', effort: '' };
|
|
674
|
+
const pending = applying.then(() => applySelection(selection));
|
|
675
|
+
applying = pending.catch(() => undefined);
|
|
676
|
+
await pending;
|
|
585
677
|
const connection = frontends.get(controls.state.activeSession);
|
|
586
678
|
savePermission(connection.id, turnPermission(inputState.groups.find(group => group.id === 'permissions')?.selected?.id));
|
|
679
|
+
if (pendingDraft === draft) {
|
|
680
|
+
pendingDraft = undefined;
|
|
681
|
+
controlsChanged.fire();
|
|
682
|
+
}
|
|
587
683
|
return connection;
|
|
588
684
|
},
|
|
589
685
|
resolve: connectionFor,
|
|
686
|
+
focus: focusSession,
|
|
590
687
|
attached: (connection) => attachedIds.has(connection.id),
|
|
591
688
|
catalogue: () => controls?.state.sessions ?? [],
|
|
592
689
|
bindings: boundId,
|
|
593
690
|
};
|
|
594
691
|
context.subscriptions.push(vscode.commands.registerCommand('supercode.frontend.activateSession', async (resource) => { await connectionFor(vscode.Uri.parse(resource)); }));
|
|
692
|
+
// The host's native focus event is authoritative even when a cached model
|
|
693
|
+
// skips content resolution. Untitled/non-harness focus never starts a runtime.
|
|
694
|
+
context.subscriptions.push(vscode.commands.registerCommand('supercode.frontend.focusSession', (resource) => {
|
|
695
|
+
focusSession(resource ? vscode.Uri.parse(resource) : undefined);
|
|
696
|
+
}));
|
|
595
697
|
context.subscriptions.push(vscode.commands.registerCommand('supercode.frontend.openSession', async (id) => {
|
|
596
698
|
await connectionFor(vscode.Uri.from({ scheme: SESSION_SCHEME, authority: id, path: '/conversation' }));
|
|
597
699
|
await revealManaged();
|
|
@@ -607,7 +709,7 @@ export async function activate(context) {
|
|
|
607
709
|
return currentOptions();
|
|
608
710
|
}
|
|
609
711
|
if (supplied && typeof supplied.harness === 'string') {
|
|
610
|
-
await
|
|
712
|
+
await chooseNewChat(async () => ({ kind: 'agent', selection: supplied }));
|
|
611
713
|
return currentOptions();
|
|
612
714
|
}
|
|
613
715
|
if (!controls) {
|
|
@@ -632,18 +734,20 @@ export async function activate(context) {
|
|
|
632
734
|
}
|
|
633
735
|
// A sole sign-in option still requires a deliberate click before opening its terminal.
|
|
634
736
|
// The official choice must not disable the existing sole-local-agent shortcut.
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
737
|
+
await chooseNewChat(async () => {
|
|
738
|
+
const harness = localChoices.length === 1 && localChoices[0].autoStart ? localChoices[0] : await vscode.window.showQuickPick(choices, { title: 'New chat · Agent', placeHolder: 'Choose your coding agent. Model and reasoning use its defaults.' });
|
|
739
|
+
if (!harness)
|
|
740
|
+
return { kind: 'cancelled' };
|
|
741
|
+
if (harness.id === CHATGPT_SIGN_IN) {
|
|
742
|
+
await vscode.commands.executeCommand(CHATGPT_SIGN_IN);
|
|
743
|
+
return { kind: 'signIn' };
|
|
744
|
+
}
|
|
745
|
+
if (harness.login) {
|
|
746
|
+
await vscode.commands.executeCommand('supercode.frontend.setup', 'login', harness.id);
|
|
747
|
+
return { kind: 'signIn', harness: harness.id };
|
|
748
|
+
}
|
|
749
|
+
return { kind: 'agent', selection: { harness: harness.id, model: '', effort: '' } };
|
|
750
|
+
});
|
|
647
751
|
}));
|
|
648
752
|
context.subscriptions.push(vscode.commands.registerCommand('supercode.frontend.configureModel', async (resource, sessionId) => {
|
|
649
753
|
if (!controls || focusedAttached)
|
|
@@ -660,25 +764,25 @@ export async function activate(context) {
|
|
|
660
764
|
const selection = { ...selected.selection };
|
|
661
765
|
if (!['claude-code', 'codex'].includes(selection.harness))
|
|
662
766
|
throw new Error('This harness uses its own model defaults; configuration is not advertised.');
|
|
663
|
-
|
|
767
|
+
await chooseNewChat(async () => {
|
|
664
768
|
const choices = controls.state.modelsByHarness?.[selection.harness] ?? [{ id: '', name: 'Harness default' }];
|
|
665
769
|
const picked = await vscode.window.showQuickPick([...choices.map(model => ({ label: model.name, id: model.id })), { label: 'Enter an exact model ID…', id: '__custom__' }], { title: 'New chat · Model', placeHolder: 'Model availability depends on your harness account.' });
|
|
666
770
|
if (!picked)
|
|
667
|
-
return;
|
|
771
|
+
return { kind: 'cancelled' };
|
|
668
772
|
if (picked.id === '__custom__') {
|
|
669
773
|
const model = await vscode.window.showInputBox({ title: 'New chat · Exact model', prompt: 'Model ID or CLI alias supported by this harness account.', value: selection.model });
|
|
670
774
|
if (model === undefined)
|
|
671
|
-
return;
|
|
775
|
+
return { kind: 'cancelled' };
|
|
672
776
|
selection.model = model.trim();
|
|
673
777
|
}
|
|
674
778
|
else
|
|
675
779
|
selection.model = picked.id;
|
|
676
780
|
const effort = await vscode.window.showQuickPick([{ label: 'Harness default', id: '' }, ...['low', 'medium', 'high'].map(id => ({ label: id, id }))], { title: 'New chat · Reasoning effort' });
|
|
677
781
|
if (!effort)
|
|
678
|
-
return;
|
|
782
|
+
return { kind: 'cancelled' };
|
|
679
783
|
selection.effort = effort.id;
|
|
680
|
-
|
|
681
|
-
|
|
784
|
+
return { kind: 'agent', selection };
|
|
785
|
+
});
|
|
682
786
|
}));
|
|
683
787
|
context.subscriptions.push({ dispose: () => frontends.dispose() });
|
|
684
788
|
const runTurnInto = async (connection, prompt, stream, token, approval) => {
|
|
@@ -804,8 +908,10 @@ export async function activate(context) {
|
|
|
804
908
|
if (welcomeValue === welcome?.value)
|
|
805
909
|
return;
|
|
806
910
|
welcomeValue = welcome?.value;
|
|
911
|
+
// Metadata updates merge across RPC; undefined can leave the previous
|
|
912
|
+
// sign-in message behind. An explicit empty value clears it in place.
|
|
807
913
|
for (const participant of participants)
|
|
808
|
-
participant.additionalWelcomeMessage = welcome;
|
|
914
|
+
participant.additionalWelcomeMessage = welcome ?? new vscode.MarkdownString('');
|
|
809
915
|
};
|
|
810
916
|
updateWelcome();
|
|
811
917
|
context.subscriptions.push(controlsChanged.event(updateWelcome), frontends.onDidChange(updateWelcome));
|
|
@@ -817,7 +923,7 @@ export async function activate(context) {
|
|
|
817
923
|
// canDelegate is disabled to avoid a generic workbench-owned registration.
|
|
818
924
|
// A participant names the harness; the native model picker names the model.
|
|
819
925
|
// Keep the author stable when a model changes during request dispatch.
|
|
820
|
-
const participantName = () => harnessDisplayName(focusedAttached?.session.descriptor?.source_harness ?? controls?.state.selection.harness ?? managed()?.session.descriptor?.source_harness);
|
|
926
|
+
const participantName = () => harnessDisplayName(focusedAttached?.session.descriptor?.source_harness ?? draftSelection()?.harness ?? controls?.state.selection.harness ?? managed()?.session.descriptor?.source_harness);
|
|
821
927
|
const participantKey = () => `${participantName()}/${identity().provider ?? ''}`;
|
|
822
928
|
const makeParticipant = () => {
|
|
823
929
|
const current = { name: participantName() };
|
|
@@ -1067,9 +1173,12 @@ export async function activate(context) {
|
|
|
1067
1173
|
let setupTimer;
|
|
1068
1174
|
let setupDisposed = false;
|
|
1069
1175
|
const pollSetup = () => {
|
|
1070
|
-
|
|
1176
|
+
const choice = activeDraft()?.choice;
|
|
1177
|
+
const awaitingLogin = choice?.kind === 'signIn' && choice.harness && !controls?.state.harnesses.some(h => h.id === choice.harness && h.autoStart);
|
|
1178
|
+
if (setupTimer || setupDisposed || !controls?.state.setup || (controls.state.setup.ready && setupHandoffComplete() && !awaitingLogin))
|
|
1071
1179
|
return;
|
|
1072
1180
|
setupTimer = setTimeout(() => {
|
|
1181
|
+
setupTimer = undefined;
|
|
1073
1182
|
void refreshSetup().catch(error => log.warn(`Could not refresh sign-in: ${String(error)}`)).finally(pollSetup);
|
|
1074
1183
|
}, 3000);
|
|
1075
1184
|
};
|
|
@@ -1261,6 +1370,7 @@ function registerSessions(context, frontends, participant, granted, handler, con
|
|
|
1261
1370
|
}
|
|
1262
1371
|
context.subscriptions.push(vscode.chat.registerChatSessionContentProvider(SESSION_SCHEME, {
|
|
1263
1372
|
provideChatSessionContent: async (resource, _token, { inputState }) => {
|
|
1373
|
+
controls?.focus(resource);
|
|
1264
1374
|
const boundHandler = (request, chatContext, stream, token) => handler(request, { ...chatContext, chatSessionContext: { chatSessionItem: { resource, label: 'Conversation' } } }, stream, token);
|
|
1265
1375
|
// Only a native untitled resource can create a conversation. Existing
|
|
1266
1376
|
// resources must resolve their exact saved binding; there is no fallback.
|
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.29",
|
|
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",
|