aegis-desktop 0.5.4 → 0.5.5

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.
@@ -946,6 +946,11 @@ function createLocalEngine({ aegis, settings, ollama, providers, tools, promptBu
946
946
  let shell = null;
947
947
  const getShell = () => shell || (shell = new ShellSession({ cwd: envFor(payload).cwd }));
948
948
  const toolCtx = { getShell, signal };
949
+ // The turn's working directory. It rides on every tool frame because a
950
+ // tool row's args are the command or the path — never the directory the
951
+ // command runs in — which left "where is it working in" unanswerable from
952
+ // the transcript.
953
+ const turnCwd = envFor(payload).cwd;
949
954
 
950
955
  try {
951
956
  const cfg = cls === 'aegis' || cls === 'ollama' ? {} : settings.get(cls) || {};
@@ -1207,6 +1212,18 @@ function createLocalEngine({ aegis, settings, ollama, providers, tools, promptBu
1207
1212
  });
1208
1213
 
1209
1214
  for (const call of calls) {
1215
+ // Open the live row BEFORE the tool runs. The CLI paints
1216
+ // `Running N … · 3s` off a `phase: 'run'` frame and ticks it while
1217
+ // the tool is still going; reporting the tool only once, after it
1218
+ // finished, left the transcript showing a spinner verb and nothing
1219
+ // else for the whole exec timeout (120s, up to 600s) — which reads
1220
+ // as a wedged turn rather than a working one.
1221
+ if (onDelta) {
1222
+ onDelta({
1223
+ delta: '',
1224
+ tool: { name: call.name, args: call.args, id: call.id, cwd: turnCwd, phase: 'run' },
1225
+ });
1226
+ }
1210
1227
  const result = call.name === T.SUBAGENT_TOOL
1211
1228
  ? await runSubagent(call.args, {
1212
1229
  cls, model, statedMaxTokens, effort: payload && payload.effort,
@@ -1215,7 +1232,15 @@ function createLocalEngine({ aegis, settings, ollama, providers, tools, promptBu
1215
1232
  : await gatedExecuteTool(call, { toolCtx, rootSessionId, rootOnDelta, signal });
1216
1233
  // A subagent's spend rides back on its tool result (see runSubagent).
1217
1234
  if (result && result.usage) addUsage({ usage: result.usage });
1218
- if (onDelta) onDelta({ delta: '', tool: { name: call.name, args: call.args, ok: result.ok } });
1235
+ // The id is carried on both frames: the CLI pairs them by id first,
1236
+ // precisely so parallel same-name calls don't collapse into one row
1237
+ // with the wrong plural.
1238
+ if (onDelta) {
1239
+ onDelta({
1240
+ delta: '',
1241
+ tool: { name: call.name, args: call.args, ok: result.ok, id: call.id, cwd: turnCwd, phase: 'done' },
1242
+ });
1243
+ }
1219
1244
  history.push({
1220
1245
  role: 'tool',
1221
1246
  tool_call_id: call.id,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "aegis-desktop",
3
3
  "productName": "AEGIS Desktop",
4
- "version": "0.5.4",
4
+ "version": "0.5.5",
5
5
  "description": "Thin Electron host for AEGIS — a local chat UI over the shared client/aegis.js transport. Ships transport + UI only; engine logic stays server-side.",
6
6
  "author": {
7
7
  "name": "AEGIS Code",
package/renderer/app.js CHANGED
@@ -1613,6 +1613,11 @@ async function spawnPath(card, spec) {
1613
1613
  card.classList.remove('pending');
1614
1614
  state.textContent = 'streaming…';
1615
1615
  }
1616
+ // `phase: 'run'` is the frame that opens the CLI's live row before the
1617
+ // tool executes. This line is retrospective by design (see
1618
+ // toolActivityLabel), so acting on the run frame too would print every
1619
+ // tool twice — once when it starts, once when it finishes.
1620
+ if (chunk.tool.phase === 'run') return;
1616
1621
  appendToolActivity(card, chunk.tool, 'flow-tools', '.flow-body');
1617
1622
  return;
1618
1623
  }
@@ -2598,6 +2603,11 @@ async function send() {
2598
2603
  return;
2599
2604
  }
2600
2605
  if (chunk && chunk.tool) {
2606
+ // See the flow-stream handler above: the run frame is the CLI's live
2607
+ // row. Ignored here, and ignored *before* `toolLog.push` — a run frame
2608
+ // counted as a completed tool would inflate the turn summary's tool
2609
+ // count for a call that hasn't run yet.
2610
+ if (chunk.tool.phase === 'run') return;
2601
2611
  toolLog.push(chunk.tool);
2602
2612
  const row = ensurePendingRow();
2603
2613
  row.classList.remove('pending');