fraim-hub 2.0.291 → 2.0.292

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.
@@ -78,6 +78,13 @@ function normalizeConversationKey(key) {
78
78
  function normalizeProjectPath(projectPath) {
79
79
  return normalizeConversationKey(projectPath);
80
80
  }
81
+ function scopeForBucket(projectPath) {
82
+ if (projectPath === exports.MANAGER_SCOPE_KEY)
83
+ return 'manager';
84
+ if (projectPath === exports.COMPANY_SCOPE_KEY)
85
+ return 'company';
86
+ return undefined;
87
+ }
81
88
  // Issue #708: fold legacy manager/company-invoked runs into the reserved scope buckets on read.
82
89
  function migrateScopeBuckets(store) {
83
90
  const projects = {};
@@ -297,9 +304,11 @@ function normalizeConversation(projectPath, raw) {
297
304
  return null;
298
305
  if (value.status !== 'running' && value.status !== 'completed' && value.status !== 'failed')
299
306
  return null;
307
+ const repairedScope = value.scope ?? scopeForBucket(projectPath);
300
308
  return {
301
309
  ...value,
302
310
  id: value.id,
311
+ ...(repairedScope !== undefined && { scope: repairedScope }),
303
312
  projectPath: normalizeProjectPath(typeof value.projectPath === 'string' ? value.projectPath : projectPath),
304
313
  title: value.title,
305
314
  jobId: value.jobId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fraim-hub",
3
- "version": "2.0.291",
3
+ "version": "2.0.292",
4
4
  "description": "FRAIM Hub local companion package.",
5
5
  "author": "Sid Mathur <sid.mathur@gmail.com>",
6
6
  "homepage": "https://github.com/mathursrus/FRAIM#readme",
@@ -211,7 +211,7 @@
211
211
  "electron-updater": "^6.8.9",
212
212
  "express": "^5.2.1",
213
213
  "extract-zip": "^2.0.1",
214
- "fraim": "2.0.291",
214
+ "fraim": "2.0.292",
215
215
  "mongodb": "^7.0.0",
216
216
  "node-cron": "4.2.1",
217
217
  "node-edge-tts": "^1.2.10",
@@ -1405,6 +1405,12 @@ function persistConversations(options) {
1405
1405
  if (opts.disk !== false) scheduleConversationDiskPersist();
1406
1406
  }
1407
1407
 
1408
+ function renderActiveScopedArea() {
1409
+ if (typeof tf === 'undefined') return;
1410
+ if (tf.area === 'manager' && typeof tfRenderManager === 'function') tfRenderManager();
1411
+ else if (tf.area === 'company' && typeof tfRenderCompany === 'function') tfRenderCompany();
1412
+ }
1413
+
1408
1414
  async function hydrateConversationsFromServer() {
1409
1415
  // Issue #708: load the project-independent scope buckets (manager/company) first, so
1410
1416
  // manager runs are present regardless of whether a project is selected.
@@ -1425,7 +1431,7 @@ async function hydrateConversationsFromServer() {
1425
1431
  console.warn('Could not hydrate manager/company conversations:', error);
1426
1432
  }
1427
1433
  if (!state.projectPath) {
1428
- if (typeof tfRenderManager === 'function' && typeof tf !== 'undefined' && tf.area === 'manager') tfRenderManager();
1434
+ renderActiveScopedArea();
1429
1435
  return;
1430
1436
  }
1431
1437
  const projectPath = state.projectPath;
@@ -1454,6 +1460,7 @@ async function hydrateConversationsFromServer() {
1454
1460
  renderRail();
1455
1461
  renderActive();
1456
1462
  await hydrateConversationBody(projectPath, state.activeId);
1463
+ renderActiveScopedArea();
1457
1464
  syncConversationRefreshPolling();
1458
1465
  } catch (error) {
1459
1466
  if (state.conversationBodiesPending === projectPath) state.conversationBodiesPending = null;
@@ -6280,8 +6287,9 @@ function renderNextJobRecommendations(conv) {
6280
6287
  const instructions = issueNumber
6281
6288
  ? `Continue from issue #${issueNumber}: ${summary}`
6282
6289
  : `Continue from ${conv.jobTitle || 'the previous job'}: ${summary}`;
6283
- const area = conv.scope === 'manager' ? 'manager'
6284
- : conv.scope === 'company' ? 'company'
6290
+ const scope = convScope(conv);
6291
+ const area = scope === 'manager' ? 'manager'
6292
+ : scope === 'company' ? 'company'
6285
6293
  : 'projects';
6286
6294
  const employeeId = conversationAgentName(conv) || (state.selectedEmployeeId) || 'claude';
6287
6295
  // Issue #989 R1-R6: open step-2 with job pre-selected and instructions pre-filled
@@ -8053,7 +8061,7 @@ async function startRun(job, instructions, employeeId, preassignedConvId, invoke
8053
8061
  projectPath: state.projectPath,
8054
8062
  // Issue #892: send the run scope so project-independent runs (Company/Manager
8055
8063
  // onboarding) can start with no project selected.
8056
- scope: conv.scope,
8064
+ scope: convScope(conv),
8057
8065
  hostId: baseHostIdForAgent(employeeId),
8058
8066
  configuredAgentId: employeeId,
8059
8067
  jobId: job.id,
@@ -8105,13 +8113,14 @@ async function restartConvWithAgent(conv, newAgentId, text) {
8105
8113
  renderRail();
8106
8114
  renderActive();
8107
8115
  try {
8116
+ const scope = convScope(conv);
8108
8117
  const result = await requestJson(`/api/ai-hub/conversations/${encodeURIComponent(conv.id)}/switch-agent`, {
8109
8118
  method: 'POST',
8110
8119
  headers: { 'Content-Type': 'application/json' },
8111
8120
  body: JSON.stringify({
8112
8121
  projectPath: state.projectPath,
8113
8122
  configuredAgentId: newAgentId,
8114
- scope: conv.scope === 'manager' || conv.scope === 'company' ? conv.scope : undefined,
8123
+ scope: scope === 'manager' || scope === 'company' ? scope : undefined,
8115
8124
  instructions: text,
8116
8125
  }),
8117
8126
  });
@@ -11599,6 +11608,12 @@ function kbMakeCard(conv) {
11599
11608
  // Kanban/Cards overview is read-only. Clicking anywhere on the card navigates to the workspace.
11600
11609
  const navigate = () => {
11601
11610
  if (!conv.id) return;
11611
+ const scope = convScope(conv);
11612
+ if (scope === 'manager' || scope === 'company') {
11613
+ tfShowArea(scope);
11614
+ switchToConversation(conv.id);
11615
+ return;
11616
+ }
11602
11617
  const _proj = conv.projectPath ? tfProjectForPath(conv.projectPath) : null;
11603
11618
  tfSelectProjectView('workspace', _proj ? _proj.id : tf.activeProjectId);
11604
11619
  switchToConversation(conv.id);