@volter/supercode-frontend-vscode 0.1.51 → 0.1.52
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 +16 -0
- package/dist/extension.js +71 -23
- package/dist/native-session.d.ts +1 -1
- package/dist/native-session.js +7 -2
- package/dist/session.d.ts +2 -1
- package/dist/session.js +8 -3
- package/dist/view.d.ts +1 -9
- package/dist/view.js +14 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -393,6 +393,22 @@ are read only for backwards compatibility.
|
|
|
393
393
|
Restored response cancellation interrupts the runtime and waits for acknowledgement.
|
|
394
394
|
Session-list updates consistently prioritize pending input over busy status.
|
|
395
395
|
|
|
396
|
+
Reload restoration joins the runtime's canonical history to events after its
|
|
397
|
+
`history_cursor`. A separately loaded native transcript is a fallback when the
|
|
398
|
+
runtime has no user history; it never replaces the live event tail. The final
|
|
399
|
+
running response is replayed through `activeResponseCallback`, with each pending
|
|
400
|
+
request drawn once from the snapshot and later events followed by sequence.
|
|
401
|
+
An idle runtime with a pending request also keeps this callback open until the
|
|
402
|
+
request is resolved. Standalone requests use the explicit runtime-history marker
|
|
403
|
+
instead of reopening an earlier answer. Managed conversations save their native
|
|
404
|
+
identity before sending input, as well as when a turn ends.
|
|
405
|
+
Stop is observed during the save and checked before input, including a lease
|
|
406
|
+
renewal retry. Retained request/decision records with no originating replay
|
|
407
|
+
prompt appear in a separate runtime-history turn.
|
|
408
|
+
The [reload investigation](../../docs/evidence/chat-pending-approval-reload-2026-10-08.md)
|
|
409
|
+
separates the retained first-user failure from this source change; a live
|
|
410
|
+
candidate reload and approval click remain unmeasured.
|
|
411
|
+
|
|
396
412
|
The pinned Code-OSS host needs a resource-scoping repair in its input-state change
|
|
397
413
|
routing: stock code broadcasts changes to all input states of a provider. The
|
|
398
414
|
Volter overlay guards this fix with a native regression test. The former legacy
|
package/dist/extension.js
CHANGED
|
@@ -10,7 +10,7 @@ import { readCredentialFile } from './credential.js';
|
|
|
10
10
|
import { grantedProposals, PROPOSAL_EFFECTS, REQUESTED_PROPOSALS } from './proposals.js';
|
|
11
11
|
import { observeActiveResponse, sessionStatus } from './native-session.js';
|
|
12
12
|
import { RequestNotPendingError, VscodeFrontendSession } from './session.js';
|
|
13
|
-
import { acceptedDecisions, opaqueText, projectEvent, projectPendingRequests, projectHistory, projectReplayTurns, resolveParts, resolutionSentence, typedAnswer, } from './view.js';
|
|
13
|
+
import { acceptedDecisions, opaqueText, projectEvent, projectPendingRequests, projectHistory, projectReplayTurns, HISTORY_MARKER_PROMPT, resolveParts, resolutionSentence, typedAnswer, } from './view.js';
|
|
14
14
|
const SESSION_SCHEME = 'supercode';
|
|
15
15
|
/** The harnesses whose model and reasoning effort a new chat can set (the host passes them to the CLI). */
|
|
16
16
|
const CONFIGURABLE_HARNESSES = ['claude-code', 'codex'];
|
|
@@ -1295,6 +1295,11 @@ export async function activate(context) {
|
|
|
1295
1295
|
} };
|
|
1296
1296
|
};
|
|
1297
1297
|
const runTurnInto = async (connection, prompt, stream, token, approval) => {
|
|
1298
|
+
const throwIfCancelled = () => {
|
|
1299
|
+
if (token.isCancellationRequested)
|
|
1300
|
+
throw new vscode.CancellationError();
|
|
1301
|
+
};
|
|
1302
|
+
throwIfCancelled();
|
|
1298
1303
|
if (approval() === 'autoApprove' && !canAnswer(connection)) {
|
|
1299
1304
|
throw new Error('This harness does not support automatic approval through Chat. Select Harness permissions.');
|
|
1300
1305
|
}
|
|
@@ -1335,13 +1340,20 @@ export async function activate(context) {
|
|
|
1335
1340
|
const unwatchTasks = connection.session.onChange(sayTasks);
|
|
1336
1341
|
let completed = false;
|
|
1337
1342
|
try {
|
|
1343
|
+
// Observe Stop throughout the save, then check the token before input.
|
|
1344
|
+
// A cancellation while this idle runtime saves cannot be handled by an
|
|
1345
|
+
// interrupt alone: there is no running turn to interrupt yet.
|
|
1346
|
+
if (controls && !attachedIds.has(connection.id) && connection.session.descriptor?.session_id) {
|
|
1347
|
+
await controls.remember(connection.id, connection.session.descriptor.session_id);
|
|
1348
|
+
}
|
|
1349
|
+
throwIfCancelled();
|
|
1338
1350
|
await connection.session.runTurn(prompt, (event) => {
|
|
1339
1351
|
// A turn the person stopped is marked stopped by VS Code itself; only an interruption from elsewhere is said.
|
|
1340
1352
|
if (event.kind === 'turn_interrupted' && token.isCancellationRequested)
|
|
1341
1353
|
return;
|
|
1342
1354
|
writeProjected(stream, projectEvent(event, projection), granted, state);
|
|
1343
1355
|
watch.sweep();
|
|
1344
|
-
});
|
|
1356
|
+
}, { throwIfCancelled });
|
|
1345
1357
|
completed = true;
|
|
1346
1358
|
}
|
|
1347
1359
|
finally {
|
|
@@ -2026,12 +2038,16 @@ function registerSessions(context, frontends, participant, granted, handler, his
|
|
|
2026
2038
|
// canonical transcript, replayed as turns.
|
|
2027
2039
|
const history = [];
|
|
2028
2040
|
const authorId = historyParticipant(connection);
|
|
2029
|
-
//
|
|
2030
|
-
//
|
|
2031
|
-
//
|
|
2032
|
-
//
|
|
2033
|
-
//
|
|
2034
|
-
const
|
|
2041
|
+
// History and replay are one runtime snapshot, joined by its cursor.
|
|
2042
|
+
// A host's separately loaded native transcript has no replay cursor;
|
|
2043
|
+
// selecting it instead hid every turn started since the runtime was
|
|
2044
|
+
// created. Keep it only as a fallback when no runtime user history is
|
|
2045
|
+
// available, rather than trying to align equal-looking prompt text.
|
|
2046
|
+
const runtimeHistory = connection.session.history;
|
|
2047
|
+
const replay = connection.session.replay.filter(event => event.sequence > connection.session.historyCursor);
|
|
2048
|
+
const hasRuntimeHistory = runtimeHistory.length > 0 || replay.some(event => event.kind === 'user_message');
|
|
2049
|
+
const usingSavedHistory = !hasRuntimeHistory && Boolean(connection.persistedHistory?.length);
|
|
2050
|
+
const canonicalHistory = usingSavedHistory ? connection.persistedHistory : runtimeHistory;
|
|
2035
2051
|
const pendingToolNames = new Set();
|
|
2036
2052
|
if (connection.session.descriptor?.turn_state === 'busy') {
|
|
2037
2053
|
for (const request of connection.session.pendingRequests.values()) {
|
|
@@ -2043,14 +2059,44 @@ function registerSessions(context, frontends, participant, granted, handler, his
|
|
|
2043
2059
|
pendingToolNames.add(name);
|
|
2044
2060
|
}
|
|
2045
2061
|
}
|
|
2046
|
-
const projected =
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2062
|
+
const projected = projectReplayTurns(replay.filter(event => {
|
|
2063
|
+
if (event.kind !== 'request')
|
|
2064
|
+
return true;
|
|
2065
|
+
const payload = event.payload;
|
|
2066
|
+
return !payload?.request || !connection.session.pendingRequests.has(payload.request.id);
|
|
2067
|
+
}), granted, {
|
|
2068
|
+
connectionId: connection.id,
|
|
2069
|
+
pendingRequest: (id) => connection.session.pendingRequests.get(id) ?? connection.session.resolvedRequests.get(id),
|
|
2070
|
+
canRespond: Boolean(connection.session.descriptor?.actions.respond && connection.session.permissions.has('approve')),
|
|
2071
|
+
}, projectHistory(canonicalHistory, granted, pendingToolNames));
|
|
2072
|
+
const live = connection.session.descriptor?.turn_state === 'busy' || connection.session.pendingRequests.size > 0;
|
|
2073
|
+
const activeParts = [];
|
|
2074
|
+
if (live) {
|
|
2075
|
+
// Standalone requests have no user turn. Give their live response
|
|
2076
|
+
// an explicit runtime marker instead of reopening an old answer.
|
|
2077
|
+
let lastBoundary = -1;
|
|
2078
|
+
let lastUser = -1;
|
|
2079
|
+
for (const event of replay) {
|
|
2080
|
+
if (['turn_succeeded', 'turn_failed', 'turn_interrupted'].includes(event.kind))
|
|
2081
|
+
lastBoundary = event.sequence;
|
|
2082
|
+
if (event.kind === 'user_message')
|
|
2083
|
+
lastUser = event.sequence;
|
|
2084
|
+
}
|
|
2085
|
+
if (!projected.some(turn => turn.role === 'user')
|
|
2086
|
+
|| (connection.session.descriptor?.turn_state !== 'busy' && lastUser <= lastBoundary)) {
|
|
2087
|
+
projected.push({ role: 'user', prompt: HISTORY_MARKER_PROMPT });
|
|
2088
|
+
}
|
|
2089
|
+
// Leave the final request without a historical response, so the
|
|
2090
|
+
// callback creates its response from live progress. Rehydrated
|
|
2091
|
+
// responses can be stale; their command buttons are disabled.
|
|
2092
|
+
const last = projected.at(-1);
|
|
2093
|
+
if (last?.role === 'assistant') {
|
|
2094
|
+
activeParts.push(...(projected.pop()?.parts ?? []).map(part => part.part === 'answers'
|
|
2095
|
+
? { part: 'markdown', value: `**${part.title}**\n\n${part.message}` }
|
|
2096
|
+
: part));
|
|
2097
|
+
}
|
|
2098
|
+
}
|
|
2099
|
+
if (usingSavedHistory && connection.historyTruncated)
|
|
2054
2100
|
history.push(new turns.ChatRequestTurn('[Earlier conversation history]', undefined, [], authorId, []), new turns.ChatResponseTurn([new vscode.ChatResponseMarkdownPart('_Showing the latest 120 saved messages. Earlier context remains in the harness session._')], {}, authorId));
|
|
2055
2101
|
for (const turn of projected) {
|
|
2056
2102
|
if (turn.role === 'user') {
|
|
@@ -2059,16 +2105,16 @@ function registerSessions(context, frontends, participant, granted, handler, his
|
|
|
2059
2105
|
}
|
|
2060
2106
|
history.push(new turns.ChatResponseTurn(historyParts(oneRowPerToolCall(turn.parts ?? [])), {}, authorId));
|
|
2061
2107
|
}
|
|
2062
|
-
const busy = connection.session.descriptor?.turn_state === 'busy';
|
|
2063
2108
|
const renderedCursor = connection.session.cursor;
|
|
2064
|
-
|
|
2109
|
+
const pendingAtCursor = [...connection.session.pendingRequests.values()];
|
|
2110
|
+
if (!live)
|
|
2065
2111
|
connection.viewReady = attached;
|
|
2066
2112
|
return {
|
|
2067
2113
|
title: connection.label,
|
|
2068
2114
|
options: controls?.attached(connection) ? undefined : controls?.currentOptions(resource),
|
|
2069
2115
|
history,
|
|
2070
2116
|
requestHandler: boundHandler,
|
|
2071
|
-
activeResponseCallback:
|
|
2117
|
+
activeResponseCallback: live
|
|
2072
2118
|
? async (stream, token) => {
|
|
2073
2119
|
// A turn re-joined after a reload has lost the handler that ran it, so its approvals are
|
|
2074
2120
|
// answered here under the conversation's mode (t_39dac582): Auto approve answers the cards
|
|
@@ -2076,22 +2122,24 @@ function registerSessions(context, frontends, participant, granted, handler, his
|
|
|
2076
2122
|
const watch = controls && !controls.attached(connection) ? controls.watchApprovals(connection, stream, token) : undefined;
|
|
2077
2123
|
try {
|
|
2078
2124
|
const state = { toolInputs: new Map(), toolNames: new Map(), toolTitles: new Map(), toolCommands: new Map(), quiet: watch?.answers };
|
|
2079
|
-
|
|
2125
|
+
for (const part of oneRowPerToolCall(activeParts))
|
|
2126
|
+
writePart(stream, part, state);
|
|
2127
|
+
writeProjected(stream, projectPendingRequests(pendingAtCursor.filter(request => connection.session.pendingRequests.has(request.id)), {
|
|
2080
2128
|
connectionId: connection.id,
|
|
2081
|
-
canRespond: connection.session.descriptor?.actions.respond
|
|
2129
|
+
canRespond: Boolean(connection.session.descriptor?.actions.respond && connection.session.permissions.has('approve')),
|
|
2082
2130
|
}), granted, state);
|
|
2083
2131
|
watch?.sweep();
|
|
2084
2132
|
await observeActiveResponse(connection.session, token, (event) => {
|
|
2085
2133
|
writeProjected(stream, projectEvent(event, {
|
|
2086
2134
|
connectionId: connection.id,
|
|
2087
2135
|
pendingRequest: (id) => connection.session.pendingRequests.get(id) ?? connection.session.resolvedRequests.get(id),
|
|
2088
|
-
canRespond: connection.session.descriptor?.actions.respond
|
|
2136
|
+
canRespond: Boolean(connection.session.descriptor?.actions.respond && connection.session.permissions.has('approve')),
|
|
2089
2137
|
}), granted, state);
|
|
2090
2138
|
watch?.sweep();
|
|
2091
2139
|
}, () => { connection.viewReady = true; }, renderedCursor);
|
|
2092
2140
|
}
|
|
2093
2141
|
finally {
|
|
2094
|
-
connection.viewReady = connection.session.descriptor?.turn_state !== 'busy';
|
|
2142
|
+
connection.viewReady = connection.session.descriptor?.turn_state !== 'busy' && !connection.session.pendingRequests.size;
|
|
2095
2143
|
watch?.dispose();
|
|
2096
2144
|
}
|
|
2097
2145
|
}
|
package/dist/native-session.d.ts
CHANGED
|
@@ -3,4 +3,4 @@ import type { FrontendEvent } from '../vendor/supercode-frontend/generated.mjs';
|
|
|
3
3
|
import { type VscodeFrontendSession } from './session.js';
|
|
4
4
|
export declare function sessionStatus(session: Pick<VscodeFrontendSession, 'descriptor' | 'pendingRequests'>): 'NeedsInput' | 'InProgress' | 'Completed';
|
|
5
5
|
/** Follow a restored turn, including the interval between snapshot and callback. */
|
|
6
|
-
export declare function observeActiveResponse(session: Pick<VscodeFrontendSession, 'descriptor' | 'onEvent' | 'interrupt' | 'actions' | 'replay'>, token: CancellationToken, write: (event: FrontendEvent) => void, onSubscribed?: () => void, afterSequence?: number): Promise<void>;
|
|
6
|
+
export declare function observeActiveResponse(session: Pick<VscodeFrontendSession, 'descriptor' | 'pendingRequests' | 'onEvent' | 'interrupt' | 'actions' | 'replay'>, token: CancellationToken, write: (event: FrontendEvent) => void, onSubscribed?: () => void, afterSequence?: number): Promise<void>;
|
package/dist/native-session.js
CHANGED
|
@@ -34,7 +34,12 @@ export async function observeActiveResponse(session, token, write, onSubscribed,
|
|
|
34
34
|
reject(error);
|
|
35
35
|
return;
|
|
36
36
|
}
|
|
37
|
-
if (
|
|
37
|
+
if (event.kind === 'runtime_disconnected') {
|
|
38
|
+
resolve();
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const ended = TURN_TERMINAL_KINDS.includes(event.kind) || event.kind === 'request_resolved';
|
|
42
|
+
if (!cancelling && ended && session.descriptor?.turn_state !== 'busy' && !session.pendingRequests.size)
|
|
38
43
|
resolve();
|
|
39
44
|
};
|
|
40
45
|
unsubscribe = session.onEvent(consume);
|
|
@@ -47,7 +52,7 @@ export async function observeActiveResponse(session, token, write, onSubscribed,
|
|
|
47
52
|
cancellation = token.onCancellationRequested(cancel);
|
|
48
53
|
if (token.isCancellationRequested)
|
|
49
54
|
cancel();
|
|
50
|
-
else if (session.descriptor?.turn_state !== 'busy')
|
|
55
|
+
else if (session.descriptor?.turn_state !== 'busy' && !session.pendingRequests.size)
|
|
51
56
|
resolve();
|
|
52
57
|
});
|
|
53
58
|
}
|
package/dist/session.d.ts
CHANGED
|
@@ -147,7 +147,7 @@ export declare class VscodeFrontendSession {
|
|
|
147
147
|
actions(): VscodeFrontendActions;
|
|
148
148
|
/** Run one controller action, re-taking an expired lease exactly once. */
|
|
149
149
|
private withControl;
|
|
150
|
-
submit(prompt: string): Promise<void>;
|
|
150
|
+
submit(prompt: string, throwIfCancelled?: () => void): Promise<void>;
|
|
151
151
|
steer(prompt: string): Promise<void>;
|
|
152
152
|
interrupt(): Promise<void>;
|
|
153
153
|
/** Stop one of the harness's own background tasks, by the id it listed it with. */
|
|
@@ -164,6 +164,7 @@ export declare class VscodeFrontendSession {
|
|
|
164
164
|
*/
|
|
165
165
|
runTurn(prompt: string, onEvent: (event: FrontendEvent) => void, options?: {
|
|
166
166
|
onCancel?: (cancel: () => void) => void;
|
|
167
|
+
throwIfCancelled?: () => void;
|
|
167
168
|
}): Promise<FrontendEvent | null>;
|
|
168
169
|
private require;
|
|
169
170
|
private notify;
|
package/dist/session.js
CHANGED
|
@@ -356,11 +356,16 @@ export class VscodeFrontendSession {
|
|
|
356
356
|
return action();
|
|
357
357
|
}
|
|
358
358
|
}
|
|
359
|
-
async submit(prompt) {
|
|
359
|
+
async submit(prompt, throwIfCancelled) {
|
|
360
|
+
throwIfCancelled?.();
|
|
360
361
|
this.require('submit');
|
|
361
362
|
if (prompt.length === 0)
|
|
362
363
|
throw new TypeError('prompt must not be empty');
|
|
363
|
-
await this.withControl(() =>
|
|
364
|
+
await this.withControl(() => {
|
|
365
|
+
// The same guard covers a send retried after an awaited lease renewal.
|
|
366
|
+
throwIfCancelled?.();
|
|
367
|
+
return this.client.sendInput(prompt);
|
|
368
|
+
});
|
|
364
369
|
}
|
|
365
370
|
async steer(prompt) {
|
|
366
371
|
this.require('steer');
|
|
@@ -474,7 +479,7 @@ export class VscodeFrontendSession {
|
|
|
474
479
|
void this.interrupt().catch((error) => fail?.(error));
|
|
475
480
|
});
|
|
476
481
|
try {
|
|
477
|
-
await this.submit(prompt);
|
|
482
|
+
await this.submit(prompt, options.throwIfCancelled);
|
|
478
483
|
return await finished;
|
|
479
484
|
}
|
|
480
485
|
finally {
|
package/dist/view.d.ts
CHANGED
|
@@ -170,14 +170,6 @@ export interface ProjectedTurn {
|
|
|
170
170
|
/** Rendered parts for an assistant turn. */
|
|
171
171
|
parts?: ChatPart[];
|
|
172
172
|
}
|
|
173
|
-
/**
|
|
174
|
-
* A HOSTED harness runtime's transcript as chat turns.
|
|
175
|
-
*
|
|
176
|
-
* `HostedHarnessRuntime::attach` returns `history: Vec::new()` and puts the
|
|
177
|
-
* whole conversation in `replay` — the canonical ChatMessage history belongs to
|
|
178
|
-
* supercode's own agent loop, and a hosted harness has none. So a resumed
|
|
179
|
-
* Claude Code session's turns are here or nowhere.
|
|
180
|
-
*/
|
|
181
173
|
/**
|
|
182
174
|
* A "user" message no person typed: Claude Code's `<task-notification>` (a background task reporting back) or the
|
|
183
175
|
* editor's automatic tripwire nudge. Neither is shown as the person's words. A task notification is said as one
|
|
@@ -186,7 +178,7 @@ export interface ProjectedTurn {
|
|
|
186
178
|
export declare function automaticPrompt(body: string): {
|
|
187
179
|
notice?: string;
|
|
188
180
|
} | undefined;
|
|
189
|
-
export declare function projectReplayTurns(events: readonly FrontendEvent[], granted: ReadonlySet<string>, context: ProjectionContext): ProjectedTurn[];
|
|
181
|
+
export declare function projectReplayTurns(events: readonly FrontendEvent[], granted: ReadonlySet<string>, context: ProjectionContext, history?: readonly ProjectedTurn[]): ProjectedTurn[];
|
|
190
182
|
/**
|
|
191
183
|
* The attach snapshot's canonical history as chat turns. Bounded: when older
|
|
192
184
|
* turns are omitted the view says so, the way the browser observer does.
|
package/dist/view.js
CHANGED
|
@@ -650,14 +650,6 @@ function messageText(message) {
|
|
|
650
650
|
.filter(Boolean)
|
|
651
651
|
.join('\n');
|
|
652
652
|
}
|
|
653
|
-
/**
|
|
654
|
-
* A HOSTED harness runtime's transcript as chat turns.
|
|
655
|
-
*
|
|
656
|
-
* `HostedHarnessRuntime::attach` returns `history: Vec::new()` and puts the
|
|
657
|
-
* whole conversation in `replay` — the canonical ChatMessage history belongs to
|
|
658
|
-
* supercode's own agent loop, and a hosted harness has none. So a resumed
|
|
659
|
-
* Claude Code session's turns are here or nowhere.
|
|
660
|
-
*/
|
|
661
653
|
/**
|
|
662
654
|
* A "user" message no person typed: Claude Code's `<task-notification>` (a background task reporting back) or the
|
|
663
655
|
* editor's automatic tripwire nudge. Neither is shown as the person's words. A task notification is said as one
|
|
@@ -675,8 +667,13 @@ export function automaticPrompt(body) {
|
|
|
675
667
|
return {};
|
|
676
668
|
return undefined;
|
|
677
669
|
}
|
|
678
|
-
export function projectReplayTurns(events, granted, context) {
|
|
679
|
-
|
|
670
|
+
export function projectReplayTurns(events, granted, context, history = []) {
|
|
671
|
+
// Join canonical history with its sequenced tail. Retained request/decision
|
|
672
|
+
// events can be re-sequenced past history_cursor with no originating turn.
|
|
673
|
+
// Before the replay supplies a prompt, give its parts their own runtime
|
|
674
|
+
// history turn rather than attributing old approvals to the latest answer.
|
|
675
|
+
const turns = history.map(turn => ({ ...turn, parts: turn.parts?.slice() }));
|
|
676
|
+
let replayTurn = false;
|
|
680
677
|
let streamedText;
|
|
681
678
|
for (const event of events) {
|
|
682
679
|
if (event.kind === 'user_message') {
|
|
@@ -686,8 +683,10 @@ export function projectReplayTurns(events, granted, context) {
|
|
|
686
683
|
if (automatic) {
|
|
687
684
|
if (!automatic.notice)
|
|
688
685
|
continue;
|
|
689
|
-
if (
|
|
686
|
+
if (!replayTurn) {
|
|
690
687
|
turns.push({ role: 'user', prompt: HISTORY_MARKER_PROMPT });
|
|
688
|
+
replayTurn = true;
|
|
689
|
+
}
|
|
691
690
|
const last = turns[turns.length - 1];
|
|
692
691
|
const notice = { part: 'markdown', value: `\n\n${automatic.notice}\n\n` };
|
|
693
692
|
if (last.role === 'assistant' && last.parts)
|
|
@@ -697,6 +696,7 @@ export function projectReplayTurns(events, granted, context) {
|
|
|
697
696
|
continue;
|
|
698
697
|
}
|
|
699
698
|
turns.push({ role: 'user', prompt: clamp(stripControls(text(payload.text)), VSCODE_CHAT_LIMITS.partCharacters) });
|
|
699
|
+
replayTurn = true;
|
|
700
700
|
continue;
|
|
701
701
|
}
|
|
702
702
|
const parts = resolveParts(projectEvent(event, context), granted);
|
|
@@ -712,8 +712,10 @@ export function projectReplayTurns(events, granted, context) {
|
|
|
712
712
|
else {
|
|
713
713
|
streamedText = undefined;
|
|
714
714
|
}
|
|
715
|
-
if (
|
|
715
|
+
if (!replayTurn) {
|
|
716
716
|
turns.push({ role: 'user', prompt: HISTORY_MARKER_PROMPT });
|
|
717
|
+
replayTurn = true;
|
|
718
|
+
}
|
|
717
719
|
const last = turns[turns.length - 1];
|
|
718
720
|
if (last.role === 'assistant' && last.parts)
|
|
719
721
|
last.parts.push(...parts);
|
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.52",
|
|
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",
|