fraim 2.0.138 → 2.0.140

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.
@@ -762,7 +762,6 @@ class FirstRunSessionService {
762
762
  const hubServer = new AiHubServer({ projectPath: this.state.workspacePath });
763
763
  await hubServer.start(port);
764
764
  const hubUrl = `http://127.0.0.1:${port}/ai-hub/?firstRun=true`;
765
- this.openBrowser(hubUrl);
766
765
  appendInstallLog(`hub-opened ${hubUrl}`);
767
766
  return {
768
767
  ok: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fraim",
3
- "version": "2.0.138",
3
+ "version": "2.0.140",
4
4
  "description": "FRAIM CLI - Framework for Rigor-based AI Management (alias for fraim-framework)",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -366,13 +366,20 @@ function renderActive() {
366
366
 
367
367
  // Render the inline employee selector shown in the coach section of an
368
368
  // active conversation. Allows switching agents without reopening the modal.
369
+ //
370
+ // Two invariants keep agent-switching working correctly:
371
+ // 1. sel.value is only reset when the active conversation changes — not on
372
+ // every poll tick. This preserves a user's in-progress selection.
373
+ // 2. conv.employeeId is NOT updated by the change handler, only by the send
374
+ // handler after a restart completes. This keeps the comparison in the send
375
+ // handler accurate: sel.value !== conv.employeeId ↔ "user changed agent".
369
376
  function renderActiveEmployeeSelect(conv) {
370
377
  const sel = els['active-employee-select'];
371
378
  if (!sel) return;
372
379
  const employees = state.bootstrap?.employees || [];
373
380
  if (employees.length === 0) { sel.hidden = true; return; }
374
381
  sel.hidden = false;
375
- // Only rebuild the options when the employee list changes (avoid reset on every poll).
382
+ // Rebuild options when the employee list changes.
376
383
  const newKey = employees.map((e) => `${e.id}:${e.available}`).join('|');
377
384
  if (sel.dataset.optionsKey !== newKey) {
378
385
  sel.innerHTML = '';
@@ -385,8 +392,14 @@ function renderActiveEmployeeSelect(conv) {
385
392
  }
386
393
  sel.dataset.optionsKey = newKey;
387
394
  }
388
- const current = (conv && conv.employeeId) || state.selectedEmployeeId || 'claude';
389
- if (sel.value !== current) sel.value = current;
395
+ // Only reset the selected value when the conversation itself changes.
396
+ // Never reset it during normal poll ticks — that would clobber the user's
397
+ // in-progress agent selection before they click Send.
398
+ const convId = (conv && conv.id) || '';
399
+ if (sel.dataset.convId !== convId) {
400
+ sel.dataset.convId = convId;
401
+ sel.value = (conv && conv.employeeId) || state.selectedEmployeeId || 'claude';
402
+ }
390
403
  }
391
404
 
392
405
  // Issue #347 R1 — render the pizza tracker. Reads conv.run.stages and
@@ -1479,13 +1492,11 @@ function wireEvents() {
1479
1492
 
1480
1493
  if (els['active-employee-select']) {
1481
1494
  els['active-employee-select'].addEventListener('change', () => {
1482
- const conv = activeConversation();
1483
- const newAgent = els['active-employee-select'].value;
1484
- state.selectedEmployeeId = newAgent;
1485
- if (conv) {
1486
- conv.employeeId = newAgent;
1487
- persistConversations();
1488
- }
1495
+ // Only update the global preference here. Do NOT update conv.employeeId
1496
+ // the send handler compares sel.value vs conv.employeeId to detect a
1497
+ // switch; updating conv here would make them equal and the restart would
1498
+ // never fire.
1499
+ state.selectedEmployeeId = els['active-employee-select'].value;
1489
1500
  });
1490
1501
  }
1491
1502