@volter/supercode-frontend-vscode 0.1.23 → 0.1.25
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 +17 -1
- package/dist/chat-setup.d.ts +8 -1
- package/dist/chat-setup.js +41 -4
- package/dist/extension.js +24 -5
- package/dist/view.d.ts +3 -1
- package/dist/view.js +24 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,6 +11,19 @@ package or npm.
|
|
|
11
11
|
|
|
12
12
|
## Native chat controls
|
|
13
13
|
|
|
14
|
+
When the host has an extension gallery and the workbench install command, setup
|
|
15
|
+
also offers **Sign in with ChatGPT** using the official `openai.chatgpt` extension.
|
|
16
|
+
Only a click installs it, using `workbench.extensions.installExtension` with
|
|
17
|
+
`enable: true` so the workbench waits for registration in the running extension
|
|
18
|
+
registry; subsequent clicks reuse it. `chatgpt.openSidebar` then opens its own sign-in view
|
|
19
|
+
(the extension does not contribute a public sign-in command). No terminal or
|
|
20
|
+
Supercode settings are involved in this path. The choice also appears whenever
|
|
21
|
+
the agent picker is shown; it does not interrupt automatic startup or the
|
|
22
|
+
sole-local-agent New Session shortcut.
|
|
23
|
+
Gallery detection reads the host's `product.json` through `vscode.workspace.fs`
|
|
24
|
+
at `vscode.env.appRoot`; hosts without an inspectable gallery configuration hide
|
|
25
|
+
the choice. Neither the extension nor its credentials are bundled or copied.
|
|
26
|
+
|
|
14
27
|
The optional host-controls state can include `setup: { ready, actions, reason,
|
|
15
28
|
cwd }`. Each action supplies `kind` (`login` or `install`), `harness`, `name` and
|
|
16
29
|
the exact `command` shown before execution. Chat renders native buttons, with
|
|
@@ -45,7 +58,10 @@ The contract is in `src/host-controls.ts`.
|
|
|
45
58
|
|
|
46
59
|
With that host, **New Session** / **Chat: New Chat: Choose Agent** asks only
|
|
47
60
|
which startable agent to use. It refreshes the host's available choices first;
|
|
48
|
-
with one
|
|
61
|
+
with one ready local agent and no pending native sign-in choices it opens
|
|
62
|
+
immediately, even when the official ChatGPT choice is available. Otherwise the
|
|
63
|
+
picker includes the official choice on supported hosts; with no choices it returns
|
|
64
|
+
to setup. Model
|
|
49
65
|
and reasoning are sent as empty values, leaving both at the harness's own defaults,
|
|
50
66
|
even if the previous conversation used explicit settings. Cancelling the agent
|
|
51
67
|
picker creates nothing.
|
package/dist/chat-setup.d.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
/** Native Chat presentation; the host supplies inventory and terminal actions. */
|
|
2
2
|
import * as vscode from 'vscode';
|
|
3
3
|
import type { ChatSetupState } from './host-controls.js';
|
|
4
|
-
export declare
|
|
4
|
+
export declare const CHATGPT_SIGN_IN = "supercode.frontend.signInWithChatGPT";
|
|
5
|
+
/** The install command also exists in gallery-less Code-OSS. Fail closed when
|
|
6
|
+
* the host's product configuration cannot be inspected through the VS Code API. */
|
|
7
|
+
export declare function chatGPTAvailable(): Promise<boolean>;
|
|
8
|
+
/** Only called by an explicit click. The gallery and extension own installation
|
|
9
|
+
* and authentication; there is no terminal or provider credential handling here. */
|
|
10
|
+
export declare function signInWithChatGPT(): Promise<void>;
|
|
11
|
+
export declare function setupParts(setup: ChatSetupState, chatGPT?: boolean): Array<vscode.ChatResponseMarkdownPart | vscode.ChatResponseCommandButtonPart>;
|
package/dist/chat-setup.js
CHANGED
|
@@ -1,9 +1,46 @@
|
|
|
1
1
|
/** Native Chat presentation; the host supplies inventory and terminal actions. */
|
|
2
2
|
import * as vscode from 'vscode';
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
export const CHATGPT_SIGN_IN = 'supercode.frontend.signInWithChatGPT';
|
|
4
|
+
const CODEX_EXTENSION = 'openai.chatgpt';
|
|
5
|
+
const INSTALL_EXTENSION = 'workbench.extensions.installExtension';
|
|
6
|
+
/** The install command also exists in gallery-less Code-OSS. Fail closed when
|
|
7
|
+
* the host's product configuration cannot be inspected through the VS Code API. */
|
|
8
|
+
export async function chatGPTAvailable() {
|
|
9
|
+
try {
|
|
10
|
+
if (!vscode.env.appRoot || !(await vscode.commands.getCommands(true)).includes(INSTALL_EXTENSION))
|
|
11
|
+
return false;
|
|
12
|
+
const bytes = await vscode.workspace.fs.readFile(vscode.Uri.joinPath(vscode.Uri.file(vscode.env.appRoot), 'product.json'));
|
|
13
|
+
const product = JSON.parse(Buffer.from(bytes).toString('utf8'));
|
|
14
|
+
const serviceUrl = product?.extensionsGallery?.serviceUrl;
|
|
15
|
+
return typeof serviceUrl === 'string' && /^https?:\/\//.test(serviceUrl);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/** Only called by an explicit click. The gallery and extension own installation
|
|
22
|
+
* and authentication; there is no terminal or provider credential handling here. */
|
|
23
|
+
export async function signInWithChatGPT() {
|
|
24
|
+
if (!await chatGPTAvailable())
|
|
25
|
+
throw new Error('This host does not provide an extension gallery.');
|
|
26
|
+
if (!vscode.extensions.getExtension(CODEX_EXTENSION)) {
|
|
27
|
+
// enable makes the workbench await the running extension registry, not
|
|
28
|
+
// just the installed inventory, before we dispatch the contributed command.
|
|
29
|
+
await vscode.commands.executeCommand(INSTALL_EXTENSION, CODEX_EXTENSION, { enable: true });
|
|
30
|
+
}
|
|
31
|
+
// openai.chatgpt contributes this command, not a public sign-in command.
|
|
32
|
+
// Revealing its sidebar presents its own Sign in with ChatGPT when signed out.
|
|
33
|
+
await vscode.commands.executeCommand('chatgpt.openSidebar');
|
|
34
|
+
}
|
|
35
|
+
export function setupParts(setup, chatGPT = false) {
|
|
36
|
+
const parts = [];
|
|
37
|
+
if (chatGPT) {
|
|
38
|
+
parts.push(new vscode.ChatResponseCommandButtonPart({ title: 'Sign in with ChatGPT', command: CHATGPT_SIGN_IN }));
|
|
39
|
+
parts.push(new vscode.ChatResponseMarkdownPart('Uses the official Codex extension. Installs it from the extension gallery if needed.'));
|
|
40
|
+
}
|
|
41
|
+
parts.push(new vscode.ChatResponseMarkdownPart(chatGPT
|
|
42
|
+
? '**Supercode · use a local agent**\n\nComplete your local agent’s sign-in in the terminal and browser.'
|
|
43
|
+
: 'Sign in to use Chat. Complete sign-in in the terminal and browser.'));
|
|
7
44
|
for (const action of setup.actions) {
|
|
8
45
|
const title = action.kind === 'install' ? `Install ${action.name}`
|
|
9
46
|
: action.harness === 'codex' ? 'Sign in with ChatGPT' : `Sign in with ${action.name}`;
|
package/dist/extension.js
CHANGED
|
@@ -2,7 +2,7 @@ import { resolveSessionBinding } from './bindings.js';
|
|
|
2
2
|
import { withTextContext } from './context.js';
|
|
3
3
|
import { randomUUID } from 'node:crypto';
|
|
4
4
|
import { ChatHostControls, runtimeIdentity, harnessDisplayName, turnPermission } from './host-controls.js';
|
|
5
|
-
import { setupParts } from './chat-setup.js';
|
|
5
|
+
import { CHATGPT_SIGN_IN, chatGPTAvailable, setupParts, signInWithChatGPT } from './chat-setup.js';
|
|
6
6
|
import * as vscode from 'vscode';
|
|
7
7
|
import { createFrontendClient } from './client.js';
|
|
8
8
|
import { readCredentialFile } from './credential.js';
|
|
@@ -313,6 +313,15 @@ export async function activate(context) {
|
|
|
313
313
|
const granted = grantedProposals(context.extension.packageJSON);
|
|
314
314
|
log.info(`Volter Harness: proposals requested ${REQUESTED_PROPOSALS.join(', ')}; granted ${granted.size ? [...granted].join(', ') : 'none (stable chat parts only)'}`);
|
|
315
315
|
const controls = await ChatHostControls.fromEnvironment();
|
|
316
|
+
const offerChatGPT = await chatGPTAvailable();
|
|
317
|
+
let signingInWithChatGPT;
|
|
318
|
+
context.subscriptions.push(vscode.commands.registerCommand(CHATGPT_SIGN_IN, () => {
|
|
319
|
+
signingInWithChatGPT ??= signInWithChatGPT().catch(error => {
|
|
320
|
+
log.error(`Could not open ChatGPT sign-in: ${String(error)}`);
|
|
321
|
+
void vscode.window.showErrorMessage(`Could not open ChatGPT sign-in: ${error instanceof Error ? error.message : String(error)}`);
|
|
322
|
+
}).finally(() => { signingInWithChatGPT = undefined; });
|
|
323
|
+
return signingInWithChatGPT;
|
|
324
|
+
}));
|
|
316
325
|
const controlsChanged = new vscode.EventEmitter();
|
|
317
326
|
context.subscriptions.push(controlsChanged);
|
|
318
327
|
let permission = 'ask';
|
|
@@ -597,6 +606,7 @@ export async function activate(context) {
|
|
|
597
606
|
catalogue: () => controls?.state.sessions ?? [],
|
|
598
607
|
bindings: boundId,
|
|
599
608
|
setup: () => controls?.state.setup,
|
|
609
|
+
offerChatGPT,
|
|
600
610
|
};
|
|
601
611
|
context.subscriptions.push(vscode.commands.registerCommand('supercode.frontend.activateSession', async (resource) => { await connectionFor(vscode.Uri.parse(resource)); }));
|
|
602
612
|
context.subscriptions.push(vscode.commands.registerCommand('supercode.frontend.openSession', async (id) => {
|
|
@@ -624,19 +634,28 @@ export async function activate(context) {
|
|
|
624
634
|
await controls.refresh();
|
|
625
635
|
// Sign-in choices stay visible alongside agents that can be explicitly started.
|
|
626
636
|
const login = controls.state.setup?.actions.filter(action => action.kind === 'login') ?? [];
|
|
627
|
-
const
|
|
637
|
+
const localChoices = [
|
|
628
638
|
...login.map(action => ({ label: action.name, id: action.harness, description: 'Sign in…', login: true, autoStart: false })),
|
|
629
639
|
...controls.state.harnesses.filter(h => !login.some(action => action.harness === h.id))
|
|
630
640
|
.map(h => ({ label: h.name, id: h.id, description: h.description, login: false, autoStart: h.autoStart === true })),
|
|
631
641
|
];
|
|
642
|
+
const choices = [
|
|
643
|
+
...(offerChatGPT ? [{ label: 'Sign in with ChatGPT', id: CHATGPT_SIGN_IN, description: 'Official Codex extension', login: false, autoStart: false }] : []),
|
|
644
|
+
...localChoices,
|
|
645
|
+
];
|
|
632
646
|
if (!choices.length) {
|
|
633
647
|
await revealSetup();
|
|
634
648
|
return;
|
|
635
649
|
}
|
|
636
650
|
// A sole sign-in option still requires a deliberate click before opening its terminal.
|
|
637
|
-
|
|
651
|
+
// The official choice must not disable the existing sole-local-agent shortcut.
|
|
652
|
+
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.' });
|
|
638
653
|
if (!harness)
|
|
639
654
|
return;
|
|
655
|
+
if (harness.id === CHATGPT_SIGN_IN) {
|
|
656
|
+
await vscode.commands.executeCommand(CHATGPT_SIGN_IN);
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
640
659
|
if (harness.login) {
|
|
641
660
|
await vscode.commands.executeCommand('supercode.frontend.setup', 'login', harness.id);
|
|
642
661
|
return;
|
|
@@ -734,7 +753,7 @@ export async function activate(context) {
|
|
|
734
753
|
await applying;
|
|
735
754
|
const requestedResource = chatContext.chatSessionContext?.chatSessionItem?.resource;
|
|
736
755
|
if (controls?.state.setup && !controls.state.setup.ready) {
|
|
737
|
-
for (const part of setupParts(controls.state.setup))
|
|
756
|
+
for (const part of setupParts(controls.state.setup, offerChatGPT))
|
|
738
757
|
stream.push(part);
|
|
739
758
|
return {};
|
|
740
759
|
}
|
|
@@ -1281,7 +1300,7 @@ function registerSessions(context, frontends, participant, granted, handler, con
|
|
|
1281
1300
|
title: controls?.setup() ? 'Sign in to Chat' : 'Volter Harness · no runtime',
|
|
1282
1301
|
history: [
|
|
1283
1302
|
new turns.ChatRequestTurn(STATUS_MARKER_PROMPT, undefined, [], participant.id, []),
|
|
1284
|
-
new turns.ChatResponseTurn(controls?.setup() ? setupParts(controls.setup()) : [new vscode.ChatResponseMarkdownPart(unavailableMarkdown(frontends.unavailable))], {}, participant.id),
|
|
1303
|
+
new turns.ChatResponseTurn(controls?.setup() ? setupParts(controls.setup(), controls.offerChatGPT) : [new vscode.ChatResponseMarkdownPart(unavailableMarkdown(frontends.unavailable))], {}, participant.id),
|
|
1285
1304
|
],
|
|
1286
1305
|
requestHandler: boundHandler,
|
|
1287
1306
|
};
|
package/dist/view.d.ts
CHANGED
|
@@ -173,4 +173,6 @@ export declare function projectReplayTurns(events: readonly FrontendEvent[], gra
|
|
|
173
173
|
* The attach snapshot's canonical history as chat turns. Bounded: when older
|
|
174
174
|
* turns are omitted the view says so, the way the browser observer does.
|
|
175
175
|
*/
|
|
176
|
-
export declare function projectHistory(history: readonly ChatMessage
|
|
176
|
+
export declare function projectHistory(history: readonly (ChatMessage & {
|
|
177
|
+
metadata?: Record<string, string>;
|
|
178
|
+
})[], granted: ReadonlySet<string>, pendingToolNames?: ReadonlySet<string>): ProjectedTurn[];
|
package/dist/view.js
CHANGED
|
@@ -642,8 +642,31 @@ export function projectHistory(history, granted, pendingToolNames = new Set()) {
|
|
|
642
642
|
turns.push({ role: 'assistant', parts });
|
|
643
643
|
};
|
|
644
644
|
for (const message of history) {
|
|
645
|
-
|
|
645
|
+
let body = messageText(message);
|
|
646
646
|
if (message.role === 'user') {
|
|
647
|
+
// The codec preserves typed UserMessage content separately from prepared
|
|
648
|
+
// model input. Native provenance, not wrapper-shaped text, selects it.
|
|
649
|
+
const typed = message.metadata?.codex_typed_user;
|
|
650
|
+
if (typed) {
|
|
651
|
+
try {
|
|
652
|
+
const input = JSON.parse(typed);
|
|
653
|
+
if (input?.role === 'user')
|
|
654
|
+
body = messageText(input);
|
|
655
|
+
}
|
|
656
|
+
catch { /* A bounded/corrupt metadata field must not break history. */ }
|
|
657
|
+
}
|
|
658
|
+
// A host may restore the SDK's full normalized session, which retains
|
|
659
|
+
// model context. Codex's codec classifies native fragments before they
|
|
660
|
+
// are flattened; never infer context from the person's displayed text.
|
|
661
|
+
const contextual = message.metadata?.codex_contextual_kind;
|
|
662
|
+
if (contextual === 'hidden')
|
|
663
|
+
continue;
|
|
664
|
+
if (contextual === 'hook_prompt') {
|
|
665
|
+
const text = message.metadata?.codex_hook_prompt_text;
|
|
666
|
+
if (text)
|
|
667
|
+
pushAssistant([{ part: 'markdown', value: clamp(stripControls(text), VSCODE_CHAT_LIMITS.partCharacters) }]);
|
|
668
|
+
continue;
|
|
669
|
+
}
|
|
647
670
|
toolRows.clear();
|
|
648
671
|
turns.push({ role: 'user', prompt: clamp(stripControls(body), VSCODE_CHAT_LIMITS.partCharacters) });
|
|
649
672
|
continue;
|
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.25",
|
|
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",
|