@volter/supercode-frontend-vscode 0.1.36 → 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 +15 -6
- package/dist/extension.js +142 -60
- package/dist/host-controls.d.ts +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -94,9 +94,11 @@ which startable agent to use. It refreshes the host's available choices first;
|
|
|
94
94
|
with one ready local agent and no pending native sign-in choices it opens
|
|
95
95
|
immediately, even when the official ChatGPT choice is available. Otherwise the
|
|
96
96
|
picker includes the official choice on supported hosts; with no choices it returns
|
|
97
|
-
to setup.
|
|
98
|
-
and reasoning
|
|
99
|
-
even if the previous conversation used explicit settings.
|
|
97
|
+
to setup. Picking an agent sends model
|
|
98
|
+
and reasoning as empty values, leaving both at the harness's own defaults,
|
|
99
|
+
even if the previous conversation used explicit settings. Each agent whose model
|
|
100
|
+
and reasoning a chat can set (Claude Code, Codex) is also listed in the picker as **<agent>: model
|
|
101
|
+
and reasoning…**, which goes on to the model and effort choices below. Cancelling the agent
|
|
100
102
|
picker starts no backend conversation.
|
|
101
103
|
|
|
102
104
|
The native blank chat opens before the picker appears. First send waits for the
|
|
@@ -116,8 +118,14 @@ sign-in choice it uses that agent once ready, otherwise it keeps the draft with
|
|
|
116
118
|
a visible sign-in error.
|
|
117
119
|
|
|
118
120
|
The composer's native **Model settings** control offers **Choose model and reasoning
|
|
119
|
-
for a new chat…** for Claude Code and Codex
|
|
120
|
-
|
|
121
|
+
for a new chat…** for Claude Code and Codex, and **Chat: Model and Reasoning: Open New
|
|
122
|
+
Chat** does the same from anywhere (with no conversation open it asks for the agent
|
|
123
|
+
first). The models and each model's reasoning efforts are the host's
|
|
124
|
+
`modelsByHarness` choices, which a host reads from the harness itself (Model Editor:
|
|
125
|
+
Claude Code's `--help`, Codex's models cache), so levels such as `xhigh` and `max`
|
|
126
|
+
appear as the harness offers them; a host that sends no efforts gets low/medium/high.
|
|
127
|
+
Exact model ID entry remains. When a turn ends, its reply notes the model it ran on
|
|
128
|
+
(as the harness's replies name it) and the effort it was given. Only completing the choices
|
|
121
129
|
configures the new blank chat; its backend starts on first send. Cancelling a
|
|
122
130
|
choice starts no backend and leaves the blank chat available.
|
|
123
131
|
A conversation's harness, model and reasoning remain fixed: this integration does
|
|
@@ -152,7 +160,8 @@ default is never stored as a choice (a pick equal to the default follows the def
|
|
|
152
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
|
|
153
161
|
**Ask** when opened and keep it. Auto approve approves the requests the harness would ask you about, including requests to run
|
|
154
162
|
outside its sandbox (Codex's approval requests are its sandbox escalations); the harness's deny
|
|
155
|
-
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
|
|
156
165
|
harnesses show **Harness permissions**. Previously answered requests cannot affect another
|
|
157
166
|
connection. Native command-button fallback limitations are documented below.
|
|
158
167
|
|
package/dist/extension.js
CHANGED
|
@@ -11,6 +11,8 @@ import { observeActiveResponse, sessionStatus } from './native-session.js';
|
|
|
11
11
|
import { RequestNotPendingError, VscodeFrontendSession } from './session.js';
|
|
12
12
|
import { acceptedDecisions, opaqueText, projectEvent, projectPendingRequests, projectHistory, projectReplayTurns, resolveParts, resolutionSentence, typedAnswer, } from './view.js';
|
|
13
13
|
const SESSION_SCHEME = 'supercode';
|
|
14
|
+
/** The harnesses whose model and reasoning effort a new chat can set (the host passes them to the CLI). */
|
|
15
|
+
const CONFIGURABLE_HARNESSES = ['claude-code', 'codex'];
|
|
14
16
|
const PARTICIPANT_ID = 'supercode.chat';
|
|
15
17
|
const DEFAULT_PARTICIPANT_ID = 'supercode.chat.default';
|
|
16
18
|
/** `package.json` gates the `isDefault` participant on this key. */
|
|
@@ -367,6 +369,7 @@ export async function activate(context) {
|
|
|
367
369
|
};
|
|
368
370
|
// The approval sweeps of each conversation's running turns, so a picker change reaches a turn already running.
|
|
369
371
|
const runningTurns = new Map();
|
|
372
|
+
const answeredRequests = new Map();
|
|
370
373
|
// The host's default for a conversation no one has chosen for (Model Editor declares Auto approve).
|
|
371
374
|
const hostDefault = () => controls?.state.defaultPermission === 'autoApprove' ? 'autoApprove' : 'ask';
|
|
372
375
|
const canAnswer = (connection) => Boolean(connection.session.descriptor?.actions.respond && connection.session.permissions.has('approve'));
|
|
@@ -739,6 +742,44 @@ export async function activate(context) {
|
|
|
739
742
|
throw new vscode.CancellationError();
|
|
740
743
|
return draft;
|
|
741
744
|
};
|
|
745
|
+
// A new chat's model and reasoning effort, offered from what the harness itself lists (the host reads its models
|
|
746
|
+
// and each model's efforts from the harness). Escape cancels; "Harness default" passes nothing, so the harness's
|
|
747
|
+
// own settings decide. A host that sends no efforts gets the levels every configurable harness takes.
|
|
748
|
+
// A single pick that opens on the current value (showQuickPick's `picked` applies only to multi-select).
|
|
749
|
+
const pickWithCurrent = (items, title, placeholder, currentId) => {
|
|
750
|
+
const quick = vscode.window.createQuickPick();
|
|
751
|
+
quick.title = title;
|
|
752
|
+
quick.placeholder = placeholder;
|
|
753
|
+
quick.items = items;
|
|
754
|
+
quick.activeItems = items.filter(item => item.id === currentId);
|
|
755
|
+
return new Promise(resolve => {
|
|
756
|
+
quick.onDidAccept(() => resolve(quick.selectedItems[0]));
|
|
757
|
+
quick.onDidHide(() => resolve(undefined));
|
|
758
|
+
quick.show();
|
|
759
|
+
}).finally(() => quick.dispose());
|
|
760
|
+
};
|
|
761
|
+
const pickModelAndEffort = async (harness, current) => {
|
|
762
|
+
const choices = controls?.state.modelsByHarness?.[harness] ?? [{ id: '', name: 'Harness default' }];
|
|
763
|
+
const name = harnessDisplayName(harness);
|
|
764
|
+
const items = [...choices.map(model => ({ label: model.name, description: [model.id, model.description].filter(Boolean).join(' · ') || undefined, id: model.id, efforts: model.efforts })),
|
|
765
|
+
{ label: 'Enter an exact model ID…', description: undefined, id: '__custom__', efforts: choices.find(model => model.id === '')?.efforts }];
|
|
766
|
+
const picked = await pickWithCurrent(items, `New chat · ${name} model`, 'Model availability depends on your harness account.', current?.model ?? '');
|
|
767
|
+
if (!picked)
|
|
768
|
+
return;
|
|
769
|
+
let model = picked.id;
|
|
770
|
+
if (picked.id === '__custom__') {
|
|
771
|
+
const typed = await vscode.window.showInputBox({ title: `New chat · ${name} exact model`, prompt: 'Model ID or CLI alias supported by this harness account.', value: current?.model });
|
|
772
|
+
if (typed === undefined)
|
|
773
|
+
return;
|
|
774
|
+
model = typed.trim();
|
|
775
|
+
}
|
|
776
|
+
const levels = picked.efforts ?? ['low', 'medium', 'high'];
|
|
777
|
+
const efforts = [{ label: 'Harness default', id: '' }, ...levels.map(id => ({ label: id, id }))];
|
|
778
|
+
const effort = levels.length === 0 ? efforts[0] : await pickWithCurrent(efforts, `New chat · ${name} reasoning effort`, model ? `For ${model}` : 'For the harness default model', current?.effort ?? '');
|
|
779
|
+
if (!effort)
|
|
780
|
+
return;
|
|
781
|
+
return { model, effort: effort.id };
|
|
782
|
+
};
|
|
742
783
|
const chooseNewChat = async (pick) => {
|
|
743
784
|
if (pendingDraft?.choosing)
|
|
744
785
|
throw new Error('Finish choosing an agent before starting another chat.');
|
|
@@ -842,6 +883,7 @@ export async function activate(context) {
|
|
|
842
883
|
attached: (connection) => attachedIds.has(connection.id),
|
|
843
884
|
catalogue: () => controls?.state.sessions ?? [],
|
|
844
885
|
bindings: boundId,
|
|
886
|
+
watchApprovals: (connection, stream, token) => watchApprovals(connection, stream, token, () => approvalFor(connection.id)),
|
|
845
887
|
};
|
|
846
888
|
context.subscriptions.push(vscode.commands.registerCommand('supercode.frontend.activateSession', async (resource) => { await connectionFor(vscode.Uri.parse(resource)); }));
|
|
847
889
|
// The host's native focus event is authoritative even when a cached model
|
|
@@ -880,13 +922,17 @@ export async function activate(context) {
|
|
|
880
922
|
// Sign-in choices stay visible alongside agents that can be explicitly started.
|
|
881
923
|
const login = controls.state.setup?.actions.filter(action => action.kind === 'login') ?? [];
|
|
882
924
|
const localChoices = [
|
|
883
|
-
...login.map(action => ({ label: action.name, id: action.harness, description: 'Sign in…', login: true, autoStart: false })),
|
|
925
|
+
...login.map(action => ({ label: action.name, id: action.harness, description: 'Sign in…', login: true, autoStart: false, configure: false })),
|
|
884
926
|
...controls.state.harnesses.filter(h => !login.some(action => action.harness === h.id))
|
|
885
|
-
.map(h => ({ label: h.name, id: h.id, description: h.description, login: false, autoStart: h.autoStart === true })),
|
|
927
|
+
.map(h => ({ label: h.name, id: h.id, description: h.description, login: false, autoStart: h.autoStart === true, configure: false })),
|
|
886
928
|
];
|
|
929
|
+
// Each agent whose model and reasoning a chat can set also offers that, right where the agent is chosen.
|
|
930
|
+
const modelChoices = localChoices.filter(choice => !choice.login && CONFIGURABLE_HARNESSES.includes(choice.id))
|
|
931
|
+
.map(choice => ({ ...choice, label: `${choice.label}: model and reasoning…`, description: 'Choose the model and reasoning effort', autoStart: false, configure: true }));
|
|
887
932
|
const choices = [
|
|
888
|
-
...(offerChatGPT ? [{ label: 'Sign in with ChatGPT', id: CHATGPT_SIGN_IN, description: 'Official Codex extension', login: false, autoStart: false }] : []),
|
|
933
|
+
...(offerChatGPT ? [{ label: 'Sign in with ChatGPT', id: CHATGPT_SIGN_IN, description: 'Official Codex extension', login: false, autoStart: false, configure: false }] : []),
|
|
889
934
|
...localChoices,
|
|
935
|
+
...modelChoices,
|
|
890
936
|
];
|
|
891
937
|
if (!choices.length) {
|
|
892
938
|
await revealSetup();
|
|
@@ -895,9 +941,13 @@ export async function activate(context) {
|
|
|
895
941
|
// A sole sign-in option still requires a deliberate click before opening its terminal.
|
|
896
942
|
// The official choice must not disable the existing sole-local-agent shortcut.
|
|
897
943
|
await chooseNewChat(async () => {
|
|
898
|
-
const harness = localChoices.length === 1 && localChoices[0].autoStart ? localChoices[0] : await vscode.window.showQuickPick(choices, { title: 'New chat · Agent', placeHolder: 'Choose your coding agent.
|
|
944
|
+
const harness = localChoices.length === 1 && localChoices[0].autoStart ? localChoices[0] : await vscode.window.showQuickPick(choices, { title: 'New chat · Agent', placeHolder: 'Choose your coding agent. Its default model and reasoning apply unless you choose them.' });
|
|
899
945
|
if (!harness)
|
|
900
946
|
return { kind: 'cancelled' };
|
|
947
|
+
if (harness.configure) {
|
|
948
|
+
const chosen = await pickModelAndEffort(harness.id);
|
|
949
|
+
return chosen ? { kind: 'agent', selection: { harness: harness.id, ...chosen } } : { kind: 'cancelled' };
|
|
950
|
+
}
|
|
901
951
|
if (harness.id === CHATGPT_SIGN_IN) {
|
|
902
952
|
await vscode.commands.executeCommand(CHATGPT_SIGN_IN);
|
|
903
953
|
return { kind: 'signIn' };
|
|
@@ -917,53 +967,36 @@ export async function activate(context) {
|
|
|
917
967
|
const bound = resource ? boundId(resource) : undefined;
|
|
918
968
|
if (resource && (!bound || (sessionId && bound !== sessionId)))
|
|
919
969
|
throw new Error('Model settings have no matching conversation binding.');
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
const
|
|
925
|
-
|
|
926
|
-
|
|
970
|
+
// The conversation it was opened from sets the agent and the current values; with none open (a fresh project,
|
|
971
|
+
// the command palette) the person picks the agent first. Either way the choice opens a new chat.
|
|
972
|
+
const selected = controls.state.sessions.find(session => session.id === (bound ?? controls.state.activeSession));
|
|
973
|
+
// An agent that still needs sign-in is set up from the agent picker first, as there.
|
|
974
|
+
const needsSignIn = new Set((controls.state.setup?.actions ?? []).filter(action => action.kind === 'login').map(action => action.harness));
|
|
975
|
+
const configurable = controls.state.harnesses.filter(harness => CONFIGURABLE_HARNESSES.includes(harness.id) && !needsSignIn.has(harness.id));
|
|
976
|
+
if (!configurable.length && !(selected && CONFIGURABLE_HARNESSES.includes(selected.selection.harness)))
|
|
977
|
+
throw new Error('No agent on this machine takes a model or reasoning choice here; its own defaults apply.');
|
|
927
978
|
await chooseNewChat(async () => {
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
if (picked.id === '__custom__') {
|
|
933
|
-
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 });
|
|
934
|
-
if (model === undefined)
|
|
979
|
+
let harness = selected && CONFIGURABLE_HARNESSES.includes(selected.selection.harness) ? selected.selection.harness : undefined;
|
|
980
|
+
if (!harness) {
|
|
981
|
+
const agent = configurable.length === 1 ? configurable[0] : await vscode.window.showQuickPick(configurable.map(choice => ({ ...choice, label: choice.name })), { title: 'New chat · Agent', placeHolder: 'Choose the agent whose model and reasoning to set.' });
|
|
982
|
+
if (!agent)
|
|
935
983
|
return { kind: 'cancelled' };
|
|
936
|
-
|
|
984
|
+
harness = agent.id;
|
|
937
985
|
}
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
const effort = await vscode.window.showQuickPick([{ label: 'Harness default', id: '' }, ...['low', 'medium', 'high'].map(id => ({ label: id, id }))], { title: 'New chat · Reasoning effort' });
|
|
941
|
-
if (!effort)
|
|
942
|
-
return { kind: 'cancelled' };
|
|
943
|
-
selection.effort = effort.id;
|
|
944
|
-
return { kind: 'agent', selection };
|
|
986
|
+
const chosen = await pickModelAndEffort(harness, selected?.selection.harness === harness ? selected.selection : undefined);
|
|
987
|
+
return chosen ? { kind: 'agent', selection: { harness, ...chosen } } : { kind: 'cancelled' };
|
|
945
988
|
});
|
|
946
989
|
}));
|
|
947
990
|
context.subscriptions.push({ dispose: () => frontends.dispose() });
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
canRespond: connection.session.descriptor?.actions.respond !== false,
|
|
958
|
-
};
|
|
959
|
-
const cancellation = token.onCancellationRequested(() => {
|
|
960
|
-
void connection.session.interrupt().catch(() => {
|
|
961
|
-
// The runtime may already be idle; interrupting twice is not an error
|
|
962
|
-
// this view reports.
|
|
963
|
-
});
|
|
964
|
-
});
|
|
965
|
-
// Read at every event and on every picker change, so switching to Auto approve mid-turn
|
|
966
|
-
// 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);
|
|
967
1000
|
const sweep = () => {
|
|
968
1001
|
if (approval() !== 'autoApprove' || token.isCancellationRequested || !canAnswer(connection))
|
|
969
1002
|
return;
|
|
@@ -977,25 +1010,57 @@ export async function activate(context) {
|
|
|
977
1010
|
// Its card is already in the stream (the event that raised it was written first), so say it was answered.
|
|
978
1011
|
const payload = pending.payload && typeof pending.payload === 'object' && !Array.isArray(pending.payload) ? pending.payload : {};
|
|
979
1012
|
const named = [payload.title, payload.tool, payload.tool_name].find((value) => typeof value === 'string');
|
|
1013
|
+
// The answer can settle after the turn's response has closed, when writing to it throws: the note is then dropped.
|
|
1014
|
+
const note = (text) => { try {
|
|
1015
|
+
stream.markdown(text);
|
|
1016
|
+
}
|
|
1017
|
+
catch {
|
|
1018
|
+
log.info(text.trim());
|
|
1019
|
+
} };
|
|
980
1020
|
void connection.session.respond({ kind: 'approval', request_id: pending.id, decision: 'allow' }).then(() => {
|
|
981
|
-
|
|
1021
|
+
note(`\n_auto-approved: ${opaqueText(named ?? `request #${pending.id}`, 200)}_\n`);
|
|
982
1022
|
}, error => {
|
|
983
|
-
|
|
1023
|
+
note(`\nApproval failed: ${String(error.message || error)}. Use the approval buttons to answer.\n`);
|
|
984
1024
|
});
|
|
985
1025
|
}
|
|
986
1026
|
};
|
|
987
1027
|
const sweeps = runningTurns.get(connection.id) ?? new Set();
|
|
988
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);
|
|
1054
|
+
let completed = false;
|
|
989
1055
|
try {
|
|
990
1056
|
await connection.session.runTurn(prompt, (event) => {
|
|
991
1057
|
writeProjected(stream, projectEvent(event, projection), granted, state);
|
|
992
|
-
sweep();
|
|
1058
|
+
watch.sweep();
|
|
993
1059
|
});
|
|
1060
|
+
completed = true;
|
|
994
1061
|
}
|
|
995
1062
|
finally {
|
|
996
|
-
|
|
997
|
-
if (!sweeps.size && runningTurns.get(connection.id) === sweeps)
|
|
998
|
-
runningTurns.delete(connection.id);
|
|
1063
|
+
watch.dispose();
|
|
999
1064
|
cancellation.dispose();
|
|
1000
1065
|
if (controls && !attachedIds.has(connection.id)) {
|
|
1001
1066
|
if (connection.session.descriptor?.session_id)
|
|
@@ -1003,6 +1068,12 @@ export async function activate(context) {
|
|
|
1003
1068
|
await controls.refresh().catch(error => log.warn(`Could not refresh chat identity: ${String(error)}`));
|
|
1004
1069
|
controlsChanged.fire();
|
|
1005
1070
|
}
|
|
1071
|
+
// The model the turn ran on: what the harness's own replies name (the host watches them), else what the
|
|
1072
|
+
// runtime reports; and the effort it was given.
|
|
1073
|
+
const ran = (controls?.state.activeSession === connection.id ? controls.state.actualModel : undefined) || connection.session.descriptor?.model;
|
|
1074
|
+
const effort = controls?.state.sessions.find(session => session.id === connection.id)?.selection.effort;
|
|
1075
|
+
if (completed && ran && !token.isCancellationRequested)
|
|
1076
|
+
stream.markdown(`\n\n_Ran on ${opaqueText(ran, 120)}${effort ? ` · ${opaqueText(effort, 24)} effort` : ''}_`);
|
|
1006
1077
|
}
|
|
1007
1078
|
};
|
|
1008
1079
|
const handler = async (request, chatContext, stream, token) => {
|
|
@@ -1630,18 +1701,29 @@ function registerSessions(context, frontends, participant, granted, handler, his
|
|
|
1630
1701
|
requestHandler: boundHandler,
|
|
1631
1702
|
activeResponseCallback: busy
|
|
1632
1703
|
? async (stream, token) => {
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
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(), {
|
|
1640
1711
|
connectionId: connection.id,
|
|
1641
|
-
pendingRequest: (id) => connection.session.pendingRequests.get(id) ?? connection.session.resolvedRequests.get(id),
|
|
1642
1712
|
canRespond: connection.session.descriptor?.actions.respond !== false,
|
|
1643
1713
|
}), granted, state);
|
|
1644
|
-
|
|
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
|
+
}
|
|
1645
1727
|
}
|
|
1646
1728
|
: undefined,
|
|
1647
1729
|
};
|
package/dist/host-controls.d.ts
CHANGED
|
@@ -5,11 +5,13 @@ export interface ChatSelection {
|
|
|
5
5
|
model: string;
|
|
6
6
|
effort: string;
|
|
7
7
|
}
|
|
8
|
+
/** `efforts`: the reasoning efforts a model takes, as the host read them from the harness (absent from older hosts). */
|
|
8
9
|
export interface ChatChoice {
|
|
9
10
|
id: string;
|
|
10
11
|
name: string;
|
|
11
12
|
description?: string;
|
|
12
13
|
autoStart?: boolean;
|
|
14
|
+
efforts?: string[];
|
|
13
15
|
}
|
|
14
16
|
export interface ManagedChatSession {
|
|
15
17
|
id: string;
|
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",
|