agentgui 1.0.744 → 1.0.745
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/package.json +1 -1
- package/server.js +22 -0
- package/static/js/client.js +7 -1
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -2116,6 +2116,28 @@ const server = http.createServer(async (req, res) => {
|
|
|
2116
2116
|
return;
|
|
2117
2117
|
}
|
|
2118
2118
|
|
|
2119
|
+
if (pathOnly === '/api/restore' && req.method === 'POST') {
|
|
2120
|
+
const dbPath = path.join(os.homedir(), '.gmgui', 'data.db');
|
|
2121
|
+
const backupPath = dbPath + '.bak-' + Date.now();
|
|
2122
|
+
const chunks = [];
|
|
2123
|
+
req.on('data', (chunk) => chunks.push(chunk));
|
|
2124
|
+
req.on('end', () => {
|
|
2125
|
+
try {
|
|
2126
|
+
const body = Buffer.concat(chunks);
|
|
2127
|
+
if (body.length < 100 || body.slice(0, 16).toString() !== 'SQLite format 3\0') {
|
|
2128
|
+
sendJSON(req, res, 400, { error: 'Invalid SQLite database file' });
|
|
2129
|
+
return;
|
|
2130
|
+
}
|
|
2131
|
+
fs.copyFileSync(dbPath, backupPath);
|
|
2132
|
+
fs.writeFileSync(dbPath, body);
|
|
2133
|
+
sendJSON(req, res, 200, { success: true, backupPath, size: body.length });
|
|
2134
|
+
} catch (e) {
|
|
2135
|
+
sendJSON(req, res, 500, { error: e.message });
|
|
2136
|
+
}
|
|
2137
|
+
});
|
|
2138
|
+
return;
|
|
2139
|
+
}
|
|
2140
|
+
|
|
2119
2141
|
if (pathOnly === '/api/debug/machines' && req.method === 'GET' && process.env.DEBUG) {
|
|
2120
2142
|
const toolSnap = {};
|
|
2121
2143
|
for (const [id, actor] of toolInstallMachine.getMachineActors()) {
|
package/static/js/client.js
CHANGED
|
@@ -915,12 +915,14 @@ class AgentGUIClient {
|
|
|
915
915
|
}
|
|
916
916
|
|
|
917
917
|
this._streamStartedAt = Date.now();
|
|
918
|
+
this._sessionCost = 0;
|
|
918
919
|
if (this._elapsedTimer) clearInterval(this._elapsedTimer);
|
|
919
920
|
this._elapsedTimer = setInterval(() => {
|
|
920
921
|
const label = streamingDiv?.querySelector('.streaming-indicator-label');
|
|
921
922
|
if (label) {
|
|
922
923
|
const sec = ((Date.now() - this._streamStartedAt) / 1000) | 0;
|
|
923
|
-
|
|
924
|
+
const time = sec < 60 ? sec + 's' : Math.floor(sec / 60) + 'm ' + (sec % 60) + 's';
|
|
925
|
+
label.textContent = this._sessionCost > 0 ? time + ' · $' + this._sessionCost.toFixed(4) : time;
|
|
924
926
|
}
|
|
925
927
|
}, 1000);
|
|
926
928
|
|
|
@@ -1040,6 +1042,10 @@ class AgentGUIClient {
|
|
|
1040
1042
|
return;
|
|
1041
1043
|
}
|
|
1042
1044
|
|
|
1045
|
+
if (block.type === 'result' && block.total_cost_usd) {
|
|
1046
|
+
this._sessionCost = (this._sessionCost || 0) + block.total_cost_usd;
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1043
1049
|
const el = this.renderer.renderBlock(block, data, blocksEl);
|
|
1044
1050
|
if (el) {
|
|
1045
1051
|
blocksEl.appendChild(el);
|