@volter/supercode-frontend-vscode 0.1.18 → 0.1.20
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/NOTICE.md +5 -1
- package/dist/extension.js +180 -17
- package/dist/host-controls.d.ts +1 -0
- package/dist/request-schema.LICENSE.txt +157 -0
- package/dist/request-schema.d.ts +22 -0
- package/dist/request-schema.js +8572 -0
- package/dist/session.js +8 -1
- package/dist/view.js +30 -4
- package/package.json +5 -2
package/dist/session.js
CHANGED
|
@@ -121,7 +121,9 @@ export class VscodeFrontendSession {
|
|
|
121
121
|
// dead id. An approval can only be outstanding while a turn is running,
|
|
122
122
|
// because `decide_approval` blocks the agent loop, so an idle runtime has
|
|
123
123
|
// none no matter what its replay still carries.
|
|
124
|
-
|
|
124
|
+
// Hosted Codex also receives standalone MCP elicitations. Its host retains
|
|
125
|
+
// request/resolved pairs without the native broker's turn compaction.
|
|
126
|
+
if (staged.descriptor?.turn_state !== 'busy' && staged.descriptor?.source_harness !== 'codex')
|
|
125
127
|
staged.pendingRequests.clear();
|
|
126
128
|
this.descriptor = staged.descriptor;
|
|
127
129
|
this.history = structuredClone(snapshot.history);
|
|
@@ -278,6 +280,11 @@ export class VscodeFrontendSession {
|
|
|
278
280
|
}
|
|
279
281
|
state.pendingRequests.delete(payload.request_id);
|
|
280
282
|
}
|
|
283
|
+
if (event.kind === 'runtime_disconnected') {
|
|
284
|
+
state.pendingRequests.clear();
|
|
285
|
+
if (state.descriptor)
|
|
286
|
+
state.descriptor = { ...state.descriptor, connection_state: 'shutting_down', turn_state: 'idle', actions: { ...state.descriptor.actions, submit: false, steer: false, interrupt: false, respond: false } };
|
|
287
|
+
}
|
|
281
288
|
if (state === this) {
|
|
282
289
|
if (BUSY_KINDS.has(event.kind))
|
|
283
290
|
this.lastTurnStartedMs = Date.now();
|
package/dist/view.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { typedRequestContent } from './request-schema.js';
|
|
1
2
|
/**
|
|
2
3
|
* The bounded projection this presentation package renders. Mirrors
|
|
3
4
|
* `@volter/supercode-frontend-browser`'s rule: the view is size-bounded
|
|
@@ -111,8 +112,10 @@ export function requestSummary(request) {
|
|
|
111
112
|
// naming a runtime uses and falls back to bounded JSON.
|
|
112
113
|
for (const field of ['subject', 'message', 'tool', 'tool_name', 'summary', 'prompt', 'reason']) {
|
|
113
114
|
const value = fields[field];
|
|
114
|
-
if (typeof value === 'string')
|
|
115
|
-
|
|
115
|
+
if (typeof value === 'string') {
|
|
116
|
+
const url = typeof fields.url === 'string' ? `\n\n${fields.url}` : '';
|
|
117
|
+
return clamp(stripControls(value + url), VSCODE_CHAT_LIMITS.partCharacters);
|
|
118
|
+
}
|
|
116
119
|
}
|
|
117
120
|
}
|
|
118
121
|
return opaqueText(payload);
|
|
@@ -121,6 +124,18 @@ export function requestSummary(request) {
|
|
|
121
124
|
export function requestAnswers(request, connectionId) {
|
|
122
125
|
const base = { connectionId, requestId: request.id };
|
|
123
126
|
if (request.kind === 'approval') {
|
|
127
|
+
const options = request.payload && typeof request.payload === 'object' && !Array.isArray(request.payload)
|
|
128
|
+
? request.payload.options : undefined;
|
|
129
|
+
if (Array.isArray(options)) {
|
|
130
|
+
return options.flatMap(option => {
|
|
131
|
+
if (!option || typeof option !== 'object' || Array.isArray(option) || typeof option.id !== 'string' || typeof option.label !== 'string')
|
|
132
|
+
return [];
|
|
133
|
+
const response = ['allow', 'allow_for_session', 'deny'].includes(option.id)
|
|
134
|
+
? { kind: 'approval', request_id: request.id, decision: option.id }
|
|
135
|
+
: { kind: 'other', request_id: request.id, action: 'accept', content: { option_id: option.id } };
|
|
136
|
+
return [{ ...base, label: option.label, response }];
|
|
137
|
+
});
|
|
138
|
+
}
|
|
124
139
|
const all = [
|
|
125
140
|
{ ...base, label: 'Allow', response: { kind: 'approval', request_id: request.id, decision: 'allow' } },
|
|
126
141
|
{
|
|
@@ -161,6 +176,9 @@ export function requestAnswers(request, connectionId) {
|
|
|
161
176
|
export function typedAnswer(request, reply) {
|
|
162
177
|
const normalized = reply.trim().toLowerCase();
|
|
163
178
|
if (request.kind === 'approval') {
|
|
179
|
+
if (['cancel', 'allow_always', 'execpolicy'].includes(normalized) || /^network_\d+$/.test(normalized)) {
|
|
180
|
+
return { kind: 'other', request_id: request.id, action: 'accept', content: { option_id: normalized } };
|
|
181
|
+
}
|
|
164
182
|
if (['allow for session', 'allow_for_session', 'session'].includes(normalized)) {
|
|
165
183
|
return { kind: 'approval', request_id: request.id, decision: 'allow_for_session' };
|
|
166
184
|
}
|
|
@@ -174,7 +192,7 @@ export function typedAnswer(request, reply) {
|
|
|
174
192
|
return { kind, request_id: request.id, action: 'cancel' };
|
|
175
193
|
if (['decline', 'no'].includes(normalized))
|
|
176
194
|
return { kind, request_id: request.id, action: 'decline' };
|
|
177
|
-
return { kind, request_id: request.id, action: 'accept', content: reply };
|
|
195
|
+
return { kind, request_id: request.id, action: 'accept', content: typedRequestContent(request, reply) };
|
|
178
196
|
}
|
|
179
197
|
/** The decisions a runtime said its harness accepts, when it said so. */
|
|
180
198
|
export function acceptedDecisions(request) {
|
|
@@ -194,6 +212,8 @@ export function requestNeedsTypedReply(request) {
|
|
|
194
212
|
const payload = request.payload;
|
|
195
213
|
if (!payload || typeof payload !== 'object' || Array.isArray(payload))
|
|
196
214
|
return false;
|
|
215
|
+
if (Array.isArray(payload.questions))
|
|
216
|
+
return true;
|
|
197
217
|
const schema = payload.requested_schema;
|
|
198
218
|
return schema !== undefined && schema !== null;
|
|
199
219
|
}
|
|
@@ -211,6 +231,12 @@ export function resolutionSentence(response, request, requestId) {
|
|
|
211
231
|
const verb = { allow: 'Allowed', allow_for_session: 'Allowed for session', deny: 'Denied' }[response.decision];
|
|
212
232
|
return `${verb ?? 'Resolved'}${suffix}`;
|
|
213
233
|
}
|
|
234
|
+
if (response.kind === 'other' && response.content && typeof response.content === 'object' && !Array.isArray(response.content) && typeof response.content.option_id === 'string') {
|
|
235
|
+
const options = request?.payload && typeof request.payload === 'object' && !Array.isArray(request.payload) ? request.payload.options : undefined;
|
|
236
|
+
const option = Array.isArray(options) ? options.find(value => value && typeof value === 'object' && !Array.isArray(value) && value.id === response.content.option_id) : undefined;
|
|
237
|
+
if (option && typeof option === 'object' && !Array.isArray(option) && typeof option.label === 'string')
|
|
238
|
+
return `Selected “${option.label}” for${suffix}`;
|
|
239
|
+
}
|
|
214
240
|
const verb = { accept: 'Accepted', decline: 'Declined', cancel: 'Cancelled' }[response.action];
|
|
215
241
|
const content = typeof response.content === 'string' && response.content.length > 0
|
|
216
242
|
? ` — ${clamp(stripControls(response.content), 160)}`
|
|
@@ -419,7 +445,7 @@ export function projectEvent(event, context) {
|
|
|
419
445
|
// runtime is left blocked. A preferred path that silently swallows
|
|
420
446
|
// the answer is worse than a plain one that works.
|
|
421
447
|
// A command button runs inside the live turn and carries its own answer,
|
|
422
|
-
// so
|
|
448
|
+
// so the runtime's offered answers remain usable. It cannot be withdrawn
|
|
423
449
|
// once pushed (`chatCommandContentPart` enables on `!isStale` and has no
|
|
424
450
|
// used-state), so `supercode.frontend.respond` refuses a request that is
|
|
425
451
|
// no longer pending and SAYS so instead of sending a stale answer.
|
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.20",
|
|
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",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"media"
|
|
24
24
|
],
|
|
25
25
|
"scripts": {
|
|
26
|
-
"build": "node scripts/sync-sdk.mjs && node scripts/fetch-icon.mjs && tsc -p tsconfig.build.json",
|
|
26
|
+
"build": "node scripts/sync-sdk.mjs && node scripts/fetch-icon.mjs && tsc -p tsconfig.build.json && node scripts/build-request-schema.mjs",
|
|
27
27
|
"extension": "npm run build && node scripts/pack-extension.mjs",
|
|
28
28
|
"prepack": "npm run build"
|
|
29
29
|
},
|
|
@@ -194,6 +194,9 @@
|
|
|
194
194
|
"devDependencies": {
|
|
195
195
|
"@types/node": "22.10.0",
|
|
196
196
|
"@types/vscode": "1.138.0",
|
|
197
|
+
"ajv": "8.18.0",
|
|
198
|
+
"ajv-formats": "3.0.1",
|
|
199
|
+
"esbuild": "0.28.2",
|
|
197
200
|
"typescript": "5.6.3"
|
|
198
201
|
},
|
|
199
202
|
"supercodeFrontendWelcome": {
|