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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentgui",
3
- "version": "1.0.744",
3
+ "version": "1.0.745",
4
4
  "description": "Multi-agent ACP client with real-time communication",
5
5
  "type": "module",
6
6
  "main": "electron/main.js",
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()) {
@@ -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
- label.textContent = sec < 60 ? sec + 's' : Math.floor(sec / 60) + 'm ' + (sec % 60) + 's';
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);