feat(vscode): show runtime restore points (#2828)
This commit is contained in:
+7
-6
@@ -59,14 +59,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
local runtime attach checks, status bar state, and a read-only Agent View
|
||||
preview backed by recent runtime thread summaries, plus a read-only
|
||||
`GET /v1/snapshots` endpoint for GUI clients to inspect side-git restore
|
||||
points. Thread summaries now include read-only workspace and branch metadata
|
||||
so the VS Code Agent View can show when a thread or agent lane is on another
|
||||
points. The extension now renders those restore points read-only in its Agent
|
||||
View, and thread summaries include read-only workspace and branch metadata so
|
||||
the VS Code Agent View can show when a thread or agent lane is on another
|
||||
branch. This answers the VS Code GUI lane without exposing chat webviews,
|
||||
inline edits, or retry/undo/restore runtime mutation endpoints yet (#461,
|
||||
#462, #480, #1217, #2341, #1584, #2580, #2808). Thanks @AiurArtanis for the
|
||||
Agent View prompt, @lbcheng888 for the earlier scaffold, @gaord for the GUI
|
||||
runtime API direction, @douglarek, @caeserchen, and @nightt5879 for the branch
|
||||
visibility trail, and @BigBenLabs, @lzx1545642258, @yangdaowan,
|
||||
#462, #480, #1217, #2341, #1584, #2327, #2580, #2808). Thanks @AiurArtanis
|
||||
for the Agent View prompt, @lbcheng888 for the earlier scaffold, @gaord for
|
||||
the GUI runtime API direction, @douglarek, @caeserchen, and @nightt5879 for
|
||||
the branch visibility trail, and @BigBenLabs, @lzx1545642258, @yangdaowan,
|
||||
@mangdehuang, @VerrPower, @hejia-v, @nasus9527, and @ygzhang-cn for the
|
||||
GUI/VS Code demand and validation trail.
|
||||
- Added inline live-output refresh for background shell Exec cards keyed by the
|
||||
|
||||
@@ -59,14 +59,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
local runtime attach checks, status bar state, and a read-only Agent View
|
||||
preview backed by recent runtime thread summaries, plus a read-only
|
||||
`GET /v1/snapshots` endpoint for GUI clients to inspect side-git restore
|
||||
points. Thread summaries now include read-only workspace and branch metadata
|
||||
so the VS Code Agent View can show when a thread or agent lane is on another
|
||||
points. The extension now renders those restore points read-only in its Agent
|
||||
View, and thread summaries include read-only workspace and branch metadata so
|
||||
the VS Code Agent View can show when a thread or agent lane is on another
|
||||
branch. This answers the VS Code GUI lane without exposing chat webviews,
|
||||
inline edits, or retry/undo/restore runtime mutation endpoints yet (#461,
|
||||
#462, #480, #1217, #2341, #1584, #2580, #2808). Thanks @AiurArtanis for the
|
||||
Agent View prompt, @lbcheng888 for the earlier scaffold, @gaord for the GUI
|
||||
runtime API direction, @douglarek, @caeserchen, and @nightt5879 for the branch
|
||||
visibility trail, and @BigBenLabs, @lzx1545642258, @yangdaowan,
|
||||
#462, #480, #1217, #2341, #1584, #2327, #2580, #2808). Thanks @AiurArtanis
|
||||
for the Agent View prompt, @lbcheng888 for the earlier scaffold, @gaord for
|
||||
the GUI runtime API direction, @douglarek, @caeserchen, and @nightt5879 for
|
||||
the branch visibility trail, and @BigBenLabs, @lzx1545642258, @yangdaowan,
|
||||
@mangdehuang, @VerrPower, @hejia-v, @nasus9527, and @ygzhang-cn for the
|
||||
GUI/VS Code demand and validation trail.
|
||||
- Added inline live-output refresh for background shell Exec cards keyed by the
|
||||
|
||||
@@ -10,6 +10,7 @@ This first slice is intentionally small:
|
||||
- show connection state in the status bar
|
||||
- show a read-only Agent View with recent runtime thread summaries from
|
||||
`/v1/threads/summary`
|
||||
- show recent read-only restore points from `/v1/snapshots`
|
||||
|
||||
It does not expose the full chat webview, VS Code Agent View chat/editor
|
||||
integration, inline edit application, marketplace publish workflow, or
|
||||
|
||||
@@ -51,6 +51,12 @@ function activate(context) {
|
||||
statusView.updateThreads(threads, "Showing recent runtime threads.");
|
||||
output.appendLine(`Loaded ${threads.length} runtime thread summaries.`);
|
||||
};
|
||||
const refreshSnapshots = async () => {
|
||||
const config = (0, runtime_1.readRuntimeConfig)();
|
||||
const snapshots = await (0, runtime_1.listSnapshots)(config);
|
||||
statusView.updateSnapshots(snapshots, "Showing recent restore points.");
|
||||
output.appendLine(`Loaded ${snapshots.length} runtime restore points.`);
|
||||
};
|
||||
const updateStatus = (text, tooltip) => {
|
||||
status.text = text;
|
||||
status.tooltip = tooltip;
|
||||
@@ -80,21 +86,25 @@ function activate(context) {
|
||||
updateStatus("$(check) CodeWhale", state.detail);
|
||||
try {
|
||||
await refreshAgentView();
|
||||
await refreshSnapshots();
|
||||
}
|
||||
catch (error) {
|
||||
const detail = error instanceof Error ? error.message : String(error);
|
||||
statusView.updateThreads([], detail);
|
||||
output.appendLine(`Runtime thread summaries unavailable: ${detail}`);
|
||||
statusView.updateThreads([], "Runtime thread summaries unavailable.");
|
||||
statusView.updateSnapshots([], detail);
|
||||
output.appendLine(`Runtime Agent View details unavailable: ${detail}`);
|
||||
}
|
||||
break;
|
||||
case "auth-required":
|
||||
updateStatus("$(lock) CodeWhale", state.detail);
|
||||
statusView.updateThreads([], "Runtime token is required before threads can load.");
|
||||
statusView.updateSnapshots([], "Runtime token is required before restore points can load.");
|
||||
break;
|
||||
case "offline":
|
||||
case "error":
|
||||
updateStatus("$(warning) CodeWhale", state.detail);
|
||||
statusView.updateThreads([], "Connect to the runtime to load recent threads.");
|
||||
statusView.updateSnapshots([], "Connect to the runtime to load restore points.");
|
||||
break;
|
||||
}
|
||||
output.appendLine(`${new Date().toISOString()} ${state.kind}: ${state.detail}`);
|
||||
@@ -103,11 +113,24 @@ function activate(context) {
|
||||
context.subscriptions.push(vscode.commands.registerCommand("codewhale.refreshAgentView", async () => {
|
||||
try {
|
||||
await refreshAgentView();
|
||||
await refreshSnapshots();
|
||||
}
|
||||
catch (error) {
|
||||
const detail = error instanceof Error ? error.message : String(error);
|
||||
statusView.updateThreads([], detail);
|
||||
output.appendLine(`Runtime thread summaries unavailable: ${detail}`);
|
||||
statusView.updateThreads([], "Runtime thread summaries unavailable.");
|
||||
statusView.updateSnapshots([], detail);
|
||||
output.appendLine(`Runtime Agent View details unavailable: ${detail}`);
|
||||
void vscode.window.showWarningMessage(detail);
|
||||
}
|
||||
}));
|
||||
context.subscriptions.push(vscode.commands.registerCommand("codewhale.refreshSnapshots", async () => {
|
||||
try {
|
||||
await refreshSnapshots();
|
||||
}
|
||||
catch (error) {
|
||||
const detail = error instanceof Error ? error.message : String(error);
|
||||
statusView.updateSnapshots([], detail);
|
||||
output.appendLine(`Runtime restore points unavailable: ${detail}`);
|
||||
void vscode.window.showWarningMessage(detail);
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"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"}
|
||||
{"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"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"}
|
||||
@@ -37,6 +37,7 @@ exports.readRuntimeConfig = readRuntimeConfig;
|
||||
exports.runtimeBaseUrl = runtimeBaseUrl;
|
||||
exports.checkRuntime = checkRuntime;
|
||||
exports.listThreadSummaries = listThreadSummaries;
|
||||
exports.listSnapshots = listSnapshots;
|
||||
exports.startRuntimeTerminal = startRuntimeTerminal;
|
||||
exports.openCodeWhaleTerminal = openCodeWhaleTerminal;
|
||||
const http = __importStar(require("node:http"));
|
||||
@@ -96,6 +97,17 @@ async function listThreadSummaries(config, limit = 8) {
|
||||
}
|
||||
return readThreadSummaries(response.body);
|
||||
}
|
||||
async function listSnapshots(config, limit = 8) {
|
||||
const baseUrl = runtimeBaseUrl(config);
|
||||
const response = await requestJson(`${baseUrl}/v1/snapshots?limit=${encodeURIComponent(String(limit))}`, config.token);
|
||||
if (response.statusCode === 401) {
|
||||
throw new Error("Restore points require the runtime bearer token.");
|
||||
}
|
||||
if (response.statusCode !== 200) {
|
||||
throw new Error(`Restore points returned HTTP ${response.statusCode}.`);
|
||||
}
|
||||
return readSnapshots(response.body);
|
||||
}
|
||||
function startRuntimeTerminal(config) {
|
||||
const terminal = vscode.window.createTerminal("CodeWhale Runtime");
|
||||
const args = [
|
||||
@@ -193,9 +205,30 @@ function readThreadSummaries(value) {
|
||||
];
|
||||
});
|
||||
}
|
||||
function readSnapshots(value) {
|
||||
if (!Array.isArray(value)) {
|
||||
return [];
|
||||
}
|
||||
return value.flatMap((item) => {
|
||||
if (!item || typeof item !== "object") {
|
||||
return [];
|
||||
}
|
||||
const record = item;
|
||||
const id = readString(record.id);
|
||||
const label = readString(record.label);
|
||||
const timestamp = readNumber(record.timestamp);
|
||||
if (!id || !label || timestamp === undefined) {
|
||||
return [];
|
||||
}
|
||||
return [{ id, label, timestamp }];
|
||||
});
|
||||
}
|
||||
function readString(value) {
|
||||
return typeof value === "string" ? value : undefined;
|
||||
}
|
||||
function readNumber(value) {
|
||||
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
||||
}
|
||||
function shellQuote(value) {
|
||||
if (/^[A-Za-z0-9_./:=+-]+$/.test(value)) {
|
||||
return value;
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -45,6 +45,8 @@ class RuntimeStatusView {
|
||||
};
|
||||
threads = [];
|
||||
threadsDetail = "Connect to the runtime to load recent threads.";
|
||||
snapshots = [];
|
||||
snapshotsDetail = "Connect to the runtime to load restore points.";
|
||||
resolveWebviewView(view) {
|
||||
this.view = view;
|
||||
view.webview.options = { enableScripts: true };
|
||||
@@ -61,6 +63,9 @@ class RuntimeStatusView {
|
||||
else if (message.command === "threads") {
|
||||
void vscode.commands.executeCommand("codewhale.refreshAgentView");
|
||||
}
|
||||
else if (message.command === "snapshots") {
|
||||
void vscode.commands.executeCommand("codewhale.refreshSnapshots");
|
||||
}
|
||||
});
|
||||
this.render();
|
||||
}
|
||||
@@ -73,6 +78,11 @@ class RuntimeStatusView {
|
||||
this.threadsDetail = detail;
|
||||
this.render();
|
||||
}
|
||||
updateSnapshots(snapshots, detail) {
|
||||
this.snapshots = snapshots;
|
||||
this.snapshotsDetail = detail;
|
||||
this.render();
|
||||
}
|
||||
render() {
|
||||
if (!this.view) {
|
||||
return;
|
||||
@@ -82,6 +92,9 @@ class RuntimeStatusView {
|
||||
const threadsHtml = this.threads.length > 0
|
||||
? this.threads.map((thread) => renderThread(thread)).join("")
|
||||
: `<p class="detail">${escapeHtml(this.threadsDetail)}</p>`;
|
||||
const snapshotsHtml = this.snapshots.length > 0
|
||||
? this.snapshots.map((snapshot) => renderSnapshot(snapshot)).join("")
|
||||
: `<p class="detail">${escapeHtml(this.snapshotsDetail)}</p>`;
|
||||
this.view.webview.html = `<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
@@ -94,7 +107,8 @@ class RuntimeStatusView {
|
||||
.detail { margin: 0 0 14px; color: var(--vscode-descriptionForeground); line-height: 1.45; }
|
||||
.section-title { margin: 18px 0 8px; font-size: 11px; font-weight: 700; letter-spacing: 0; text-transform: uppercase; color: var(--vscode-descriptionForeground); }
|
||||
.thread { padding: 8px 0; border-top: 1px solid var(--vscode-sideBarSectionHeader-border, var(--vscode-panel-border)); }
|
||||
.thread-title { margin-bottom: 4px; font-weight: 600; overflow-wrap: anywhere; }
|
||||
.snapshot { padding: 8px 0; border-top: 1px solid var(--vscode-sideBarSectionHeader-border, var(--vscode-panel-border)); }
|
||||
.thread-title, .snapshot-title { margin-bottom: 4px; font-weight: 600; overflow-wrap: anywhere; }
|
||||
.thread-preview { margin-bottom: 5px; color: var(--vscode-descriptionForeground); line-height: 1.35; overflow-wrap: anywhere; }
|
||||
.thread-meta { color: var(--vscode-descriptionForeground); font-size: 11px; overflow-wrap: anywhere; }
|
||||
code { color: var(--vscode-textLink-foreground); }
|
||||
@@ -107,10 +121,13 @@ class RuntimeStatusView {
|
||||
<p class="detail"><code>${escapeHtml(this.state.baseUrl)}</code></p>
|
||||
<button data-command="check">Check Runtime</button>
|
||||
<button data-command="threads">Refresh Threads</button>
|
||||
<button data-command="snapshots">Refresh Restore Points</button>
|
||||
<button data-command="start">Start Local Runtime</button>
|
||||
<button data-command="terminal">Open CodeWhale Terminal</button>
|
||||
<div class="section-title">Agent View</div>
|
||||
${threadsHtml}
|
||||
<div class="section-title">Restore Points</div>
|
||||
${snapshotsHtml}
|
||||
<script nonce="${nonce}">
|
||||
const vscode = acquireVsCodeApi();
|
||||
for (const button of document.querySelectorAll("button[data-command]")) {
|
||||
@@ -122,6 +139,12 @@ class RuntimeStatusView {
|
||||
}
|
||||
}
|
||||
exports.RuntimeStatusView = RuntimeStatusView;
|
||||
function renderSnapshot(snapshot) {
|
||||
return `<div class="snapshot">
|
||||
<div class="snapshot-title">${escapeHtml(snapshot.label)}</div>
|
||||
<div class="thread-meta">${escapeHtml(`${snapshot.id} · ${formatUnixTimestamp(snapshot.timestamp)}`)}</div>
|
||||
</div>`;
|
||||
}
|
||||
function renderThread(thread) {
|
||||
const status = thread.latestTurnStatus ? ` · ${thread.latestTurnStatus}` : "";
|
||||
const archived = thread.archived ? " · archived" : "";
|
||||
@@ -153,6 +176,13 @@ function formatTimestamp(value) {
|
||||
}
|
||||
return date.toLocaleString();
|
||||
}
|
||||
function formatUnixTimestamp(value) {
|
||||
const date = new Date(value * 1000);
|
||||
if (Number.isNaN(date.getTime())) {
|
||||
return String(value);
|
||||
}
|
||||
return date.toLocaleString();
|
||||
}
|
||||
function escapeHtml(value) {
|
||||
return value
|
||||
.replace(/&/g, "&")
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"status.js","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+CAAiC;AAGjC,MAAa,iBAAiB;IACrB,MAAM,CAAU,QAAQ,GAAG,yBAAyB,CAAC;IAEpD,IAAI,CAAsB;IAC1B,KAAK,GAAiB;QAC5B,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,uBAAuB;QAChC,MAAM,EAAE,mCAAmC;KAC5C,CAAC;IACM,OAAO,GAAoB,EAAE,CAAC;IAC9B,aAAa,GAAG,gDAAgD,CAAC;IAEzE,kBAAkB,CAAC,IAAwB;QACzC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,CAAC,OAAO,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;QAC/C,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC,OAA6B,EAAE,EAAE;YACjE,IAAI,OAAO,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;gBAChC,KAAK,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,wBAAwB,CAAC,CAAC;YAChE,CAAC;iBAAM,IAAI,OAAO,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;gBACvC,KAAK,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,wBAAwB,CAAC,CAAC;YAChE,CAAC;iBAAM,IAAI,OAAO,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;gBAC1C,KAAK,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,wBAAwB,CAAC,CAAC;YAChE,CAAC;iBAAM,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;gBACzC,KAAK,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,4BAA4B,CAAC,CAAC;YACpE,CAAC;QACH,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC;IAED,MAAM,CAAC,KAAmB;QACxB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC;IAED,aAAa,CAAC,OAAwB,EAAE,MAAc;QACpD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC;QAC5B,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC;IAEO,MAAM;QACZ,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACxC,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;QAC1B,MAAM,WAAW,GACf,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;YACrB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7D,CAAC,CAAC,qBAAqB,UAAU,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;QAChE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG;;;;yHAI4F,KAAK;;;;;;;;;;;;;;;;wBAgBtG,UAAU,CAAC,KAAK,CAAC;sBACnB,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;4BACvB,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;;;;;;IAMtD,WAAW;mBACI,KAAK;;;;;;;QAOhB,CAAC;IACP,CAAC;;AAxFH,8CAyFC;AAED,SAAS,YAAY,CAAC,MAAqB;IACzC,MAAM,MAAM,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9E,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;IACtD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACjE,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACnE,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,eAAe,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAClF,OAAO;gCACuB,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC;kCACtB,UAAU,CAAC,MAAM,CAAC,OAAO,IAAI,oBAAoB,CAAC;+BACrD,UAAU,CAAC,GAAG,MAAM,CAAC,IAAI,MAAM,MAAM,CAAC,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,EAAE,CAAC;SACvH,CAAC;AACV,CAAC;AAED,SAAS,QAAQ,CAAC,IAA0B;IAC1C,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,WAAW;YACd,OAAO,WAAW,CAAC;QACrB,KAAK,eAAe;YAClB,OAAO,gBAAgB,CAAC;QAC1B,KAAK,OAAO;YACV,OAAO,eAAe,CAAC;QACzB,KAAK,SAAS;YACZ,OAAO,SAAS,CAAC;IACrB,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,KAAa;IACpC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7B,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;QACjC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC,cAAc,EAAE,CAAC;AAC/B,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,KAAK;SACT,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,SAAS;IAChB,MAAM,QAAQ,GAAG,gEAAgE,CAAC;IAClF,IAAI,KAAK,GAAG,EAAE,CAAC;IACf,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,EAAE,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAC3C,KAAK,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
||||
{"version":3,"file":"status.js","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"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"}
|
||||
@@ -21,6 +21,7 @@
|
||||
"onCommand:codewhale.startRuntime",
|
||||
"onCommand:codewhale.checkRuntime",
|
||||
"onCommand:codewhale.refreshAgentView",
|
||||
"onCommand:codewhale.refreshSnapshots",
|
||||
"onCommand:codewhale.openRuntimeDocs",
|
||||
"onView:codewhale.runtimeStatus"
|
||||
],
|
||||
@@ -49,6 +50,10 @@
|
||||
"command": "codewhale.refreshAgentView",
|
||||
"title": "CodeWhale: Refresh Agent View"
|
||||
},
|
||||
{
|
||||
"command": "codewhale.refreshSnapshots",
|
||||
"title": "CodeWhale: Refresh Restore Points"
|
||||
},
|
||||
{
|
||||
"command": "codewhale.openRuntimeDocs",
|
||||
"title": "CodeWhale: Open Runtime API Docs"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import * as vscode from "vscode";
|
||||
import {
|
||||
checkRuntime,
|
||||
listSnapshots,
|
||||
listThreadSummaries,
|
||||
openCodeWhaleTerminal,
|
||||
readRuntimeConfig,
|
||||
@@ -27,6 +28,13 @@ export function activate(context: vscode.ExtensionContext): void {
|
||||
output.appendLine(`Loaded ${threads.length} runtime thread summaries.`);
|
||||
};
|
||||
|
||||
const refreshSnapshots = async (): Promise<void> => {
|
||||
const config = readRuntimeConfig();
|
||||
const snapshots = await listSnapshots(config);
|
||||
statusView.updateSnapshots(snapshots, "Showing recent restore points.");
|
||||
output.appendLine(`Loaded ${snapshots.length} runtime restore points.`);
|
||||
};
|
||||
|
||||
const updateStatus = (text: string, tooltip: string): void => {
|
||||
status.text = text;
|
||||
status.tooltip = tooltip;
|
||||
@@ -66,20 +74,24 @@ export function activate(context: vscode.ExtensionContext): void {
|
||||
updateStatus("$(check) CodeWhale", state.detail);
|
||||
try {
|
||||
await refreshAgentView();
|
||||
await refreshSnapshots();
|
||||
} catch (error: unknown) {
|
||||
const detail = error instanceof Error ? error.message : String(error);
|
||||
statusView.updateThreads([], detail);
|
||||
output.appendLine(`Runtime thread summaries unavailable: ${detail}`);
|
||||
statusView.updateThreads([], "Runtime thread summaries unavailable.");
|
||||
statusView.updateSnapshots([], detail);
|
||||
output.appendLine(`Runtime Agent View details unavailable: ${detail}`);
|
||||
}
|
||||
break;
|
||||
case "auth-required":
|
||||
updateStatus("$(lock) CodeWhale", state.detail);
|
||||
statusView.updateThreads([], "Runtime token is required before threads can load.");
|
||||
statusView.updateSnapshots([], "Runtime token is required before restore points can load.");
|
||||
break;
|
||||
case "offline":
|
||||
case "error":
|
||||
updateStatus("$(warning) CodeWhale", state.detail);
|
||||
statusView.updateThreads([], "Connect to the runtime to load recent threads.");
|
||||
statusView.updateSnapshots([], "Connect to the runtime to load restore points.");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -92,10 +104,25 @@ export function activate(context: vscode.ExtensionContext): void {
|
||||
vscode.commands.registerCommand("codewhale.refreshAgentView", async () => {
|
||||
try {
|
||||
await refreshAgentView();
|
||||
await refreshSnapshots();
|
||||
} catch (error: unknown) {
|
||||
const detail = error instanceof Error ? error.message : String(error);
|
||||
statusView.updateThreads([], detail);
|
||||
output.appendLine(`Runtime thread summaries unavailable: ${detail}`);
|
||||
statusView.updateThreads([], "Runtime thread summaries unavailable.");
|
||||
statusView.updateSnapshots([], detail);
|
||||
output.appendLine(`Runtime Agent View details unavailable: ${detail}`);
|
||||
void vscode.window.showWarningMessage(detail);
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
context.subscriptions.push(
|
||||
vscode.commands.registerCommand("codewhale.refreshSnapshots", async () => {
|
||||
try {
|
||||
await refreshSnapshots();
|
||||
} catch (error: unknown) {
|
||||
const detail = error instanceof Error ? error.message : String(error);
|
||||
statusView.updateSnapshots([], detail);
|
||||
output.appendLine(`Runtime restore points unavailable: ${detail}`);
|
||||
void vscode.window.showWarningMessage(detail);
|
||||
}
|
||||
}),
|
||||
|
||||
@@ -23,6 +23,12 @@ export interface ThreadSummary {
|
||||
latestTurnStatus?: string;
|
||||
}
|
||||
|
||||
export interface SnapshotEntry {
|
||||
id: string;
|
||||
label: string;
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
export interface RuntimeConfig {
|
||||
commandPath: string;
|
||||
host: string;
|
||||
@@ -99,6 +105,23 @@ export async function listThreadSummaries(
|
||||
return readThreadSummaries(response.body);
|
||||
}
|
||||
|
||||
export async function listSnapshots(config: RuntimeConfig, limit = 8): Promise<SnapshotEntry[]> {
|
||||
const baseUrl = runtimeBaseUrl(config);
|
||||
const response = await requestJson(
|
||||
`${baseUrl}/v1/snapshots?limit=${encodeURIComponent(String(limit))}`,
|
||||
config.token,
|
||||
);
|
||||
|
||||
if (response.statusCode === 401) {
|
||||
throw new Error("Restore points require the runtime bearer token.");
|
||||
}
|
||||
if (response.statusCode !== 200) {
|
||||
throw new Error(`Restore points returned HTTP ${response.statusCode}.`);
|
||||
}
|
||||
|
||||
return readSnapshots(response.body);
|
||||
}
|
||||
|
||||
export function startRuntimeTerminal(config: RuntimeConfig): vscode.Terminal {
|
||||
const terminal = vscode.window.createTerminal("CodeWhale Runtime");
|
||||
const args = [
|
||||
@@ -210,10 +233,35 @@ function readThreadSummaries(value: unknown): ThreadSummary[] {
|
||||
});
|
||||
}
|
||||
|
||||
function readSnapshots(value: unknown): SnapshotEntry[] {
|
||||
if (!Array.isArray(value)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return value.flatMap((item) => {
|
||||
if (!item || typeof item !== "object") {
|
||||
return [];
|
||||
}
|
||||
const record = item as Record<string, unknown>;
|
||||
const id = readString(record.id);
|
||||
const label = readString(record.label);
|
||||
const timestamp = readNumber(record.timestamp);
|
||||
if (!id || !label || timestamp === undefined) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [{ id, label, timestamp }];
|
||||
});
|
||||
}
|
||||
|
||||
function readString(value: unknown): string | undefined {
|
||||
return typeof value === "string" ? value : undefined;
|
||||
}
|
||||
|
||||
function readNumber(value: unknown): number | undefined {
|
||||
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
||||
}
|
||||
|
||||
function shellQuote(value: string): string {
|
||||
if (/^[A-Za-z0-9_./:=+-]+$/.test(value)) {
|
||||
return value;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as vscode from "vscode";
|
||||
import type { RuntimeState, ThreadSummary } from "./runtime";
|
||||
import type { RuntimeState, SnapshotEntry, ThreadSummary } from "./runtime";
|
||||
|
||||
export class RuntimeStatusView implements vscode.WebviewViewProvider {
|
||||
public static readonly viewType = "codewhale.runtimeStatus";
|
||||
@@ -12,6 +12,8 @@ export class RuntimeStatusView implements vscode.WebviewViewProvider {
|
||||
};
|
||||
private threads: ThreadSummary[] = [];
|
||||
private threadsDetail = "Connect to the runtime to load recent threads.";
|
||||
private snapshots: SnapshotEntry[] = [];
|
||||
private snapshotsDetail = "Connect to the runtime to load restore points.";
|
||||
|
||||
resolveWebviewView(view: vscode.WebviewView): void {
|
||||
this.view = view;
|
||||
@@ -25,6 +27,8 @@ export class RuntimeStatusView implements vscode.WebviewViewProvider {
|
||||
void vscode.commands.executeCommand("codewhale.openTerminal");
|
||||
} else if (message.command === "threads") {
|
||||
void vscode.commands.executeCommand("codewhale.refreshAgentView");
|
||||
} else if (message.command === "snapshots") {
|
||||
void vscode.commands.executeCommand("codewhale.refreshSnapshots");
|
||||
}
|
||||
});
|
||||
this.render();
|
||||
@@ -41,6 +45,12 @@ export class RuntimeStatusView implements vscode.WebviewViewProvider {
|
||||
this.render();
|
||||
}
|
||||
|
||||
updateSnapshots(snapshots: SnapshotEntry[], detail: string): void {
|
||||
this.snapshots = snapshots;
|
||||
this.snapshotsDetail = detail;
|
||||
this.render();
|
||||
}
|
||||
|
||||
private render(): void {
|
||||
if (!this.view) {
|
||||
return;
|
||||
@@ -52,6 +62,10 @@ export class RuntimeStatusView implements vscode.WebviewViewProvider {
|
||||
this.threads.length > 0
|
||||
? this.threads.map((thread) => renderThread(thread)).join("")
|
||||
: `<p class="detail">${escapeHtml(this.threadsDetail)}</p>`;
|
||||
const snapshotsHtml =
|
||||
this.snapshots.length > 0
|
||||
? this.snapshots.map((snapshot) => renderSnapshot(snapshot)).join("")
|
||||
: `<p class="detail">${escapeHtml(this.snapshotsDetail)}</p>`;
|
||||
this.view.webview.html = `<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
@@ -64,7 +78,8 @@ export class RuntimeStatusView implements vscode.WebviewViewProvider {
|
||||
.detail { margin: 0 0 14px; color: var(--vscode-descriptionForeground); line-height: 1.45; }
|
||||
.section-title { margin: 18px 0 8px; font-size: 11px; font-weight: 700; letter-spacing: 0; text-transform: uppercase; color: var(--vscode-descriptionForeground); }
|
||||
.thread { padding: 8px 0; border-top: 1px solid var(--vscode-sideBarSectionHeader-border, var(--vscode-panel-border)); }
|
||||
.thread-title { margin-bottom: 4px; font-weight: 600; overflow-wrap: anywhere; }
|
||||
.snapshot { padding: 8px 0; border-top: 1px solid var(--vscode-sideBarSectionHeader-border, var(--vscode-panel-border)); }
|
||||
.thread-title, .snapshot-title { margin-bottom: 4px; font-weight: 600; overflow-wrap: anywhere; }
|
||||
.thread-preview { margin-bottom: 5px; color: var(--vscode-descriptionForeground); line-height: 1.35; overflow-wrap: anywhere; }
|
||||
.thread-meta { color: var(--vscode-descriptionForeground); font-size: 11px; overflow-wrap: anywhere; }
|
||||
code { color: var(--vscode-textLink-foreground); }
|
||||
@@ -77,10 +92,13 @@ export class RuntimeStatusView implements vscode.WebviewViewProvider {
|
||||
<p class="detail"><code>${escapeHtml(this.state.baseUrl)}</code></p>
|
||||
<button data-command="check">Check Runtime</button>
|
||||
<button data-command="threads">Refresh Threads</button>
|
||||
<button data-command="snapshots">Refresh Restore Points</button>
|
||||
<button data-command="start">Start Local Runtime</button>
|
||||
<button data-command="terminal">Open CodeWhale Terminal</button>
|
||||
<div class="section-title">Agent View</div>
|
||||
${threadsHtml}
|
||||
<div class="section-title">Restore Points</div>
|
||||
${snapshotsHtml}
|
||||
<script nonce="${nonce}">
|
||||
const vscode = acquireVsCodeApi();
|
||||
for (const button of document.querySelectorAll("button[data-command]")) {
|
||||
@@ -92,6 +110,13 @@ export class RuntimeStatusView implements vscode.WebviewViewProvider {
|
||||
}
|
||||
}
|
||||
|
||||
function renderSnapshot(snapshot: SnapshotEntry): string {
|
||||
return `<div class="snapshot">
|
||||
<div class="snapshot-title">${escapeHtml(snapshot.label)}</div>
|
||||
<div class="thread-meta">${escapeHtml(`${snapshot.id} · ${formatUnixTimestamp(snapshot.timestamp)}`)}</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
function renderThread(thread: ThreadSummary): string {
|
||||
const status = thread.latestTurnStatus ? ` · ${thread.latestTurnStatus}` : "";
|
||||
const archived = thread.archived ? " · archived" : "";
|
||||
@@ -126,6 +151,14 @@ function formatTimestamp(value: string): string {
|
||||
return date.toLocaleString();
|
||||
}
|
||||
|
||||
function formatUnixTimestamp(value: number): string {
|
||||
const date = new Date(value * 1000);
|
||||
if (Number.isNaN(date.getTime())) {
|
||||
return String(value);
|
||||
}
|
||||
return date.toLocaleString();
|
||||
}
|
||||
|
||||
function escapeHtml(value: string): string {
|
||||
return value
|
||||
.replace(/&/g, "&")
|
||||
|
||||
Reference in New Issue
Block a user