fraim 2.0.167 → 2.0.168

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.
Files changed (54) hide show
  1. package/dist/src/ai-hub/catalog.js +28 -14
  2. package/dist/src/ai-hub/server.js +10 -403
  3. package/dist/src/cli/commands/init-project.js +1 -98
  4. package/dist/src/cli/commands/manager.js +40 -0
  5. package/dist/src/cli/commands/sync.js +17 -21
  6. package/dist/src/cli/fraim.js +2 -0
  7. package/dist/src/cli/utils/github-workflow-sync.js +12 -146
  8. package/dist/src/cli/utils/manager-pack-sync.js +188 -0
  9. package/dist/src/cli/utils/manager-publish.js +76 -0
  10. package/dist/src/cli/utils/user-config.js +20 -0
  11. package/dist/src/core/fraim-config-schema.generated.js +85 -10
  12. package/dist/src/core/manager-pack.js +26 -0
  13. package/dist/src/first-run/install-state.js +1 -0
  14. package/dist/src/first-run/server.js +9 -0
  15. package/dist/src/first-run/session-service.js +117 -23
  16. package/dist/src/first-run/types.js +2 -5
  17. package/dist/src/local-mcp-server/learning-context-builder.js +45 -8
  18. package/dist/src/local-mcp-server/stdio-server.js +28 -0
  19. package/index.js +1 -1
  20. package/package.json +1 -2
  21. package/public/ai-hub/index.html +0 -81
  22. package/public/ai-hub/powerpoint-taskpane/index.html +236 -236
  23. package/public/ai-hub/powerpoint-taskpane/manifest.xml +29 -29
  24. package/public/ai-hub/script.js +3 -219
  25. package/public/ai-hub/styles.css +8 -36
  26. package/public/first-run/index.html +1 -1
  27. package/public/first-run/script.js +459 -530
  28. package/public/first-run/styles.css +288 -73
  29. package/public/portfolio/ashley.html +1 -1
  30. package/public/portfolio/casey.html +1 -1
  31. package/public/portfolio/celia.html +1 -1
  32. package/public/portfolio/gautam.html +1 -1
  33. package/public/portfolio/hari.html +1 -1
  34. package/public/portfolio/maestro.html +1 -1
  35. package/public/portfolio/mandy.html +1 -1
  36. package/public/portfolio/pam.html +6 -6
  37. package/public/portfolio/qasm.html +1 -1
  38. package/public/portfolio/sade.html +1 -1
  39. package/public/portfolio/sam.html +1 -1
  40. package/public/portfolio/swen.html +6 -6
  41. package/dist/src/ai-hub/word-sideload.js +0 -95
  42. package/dist/src/cli/commands/test-mcp.js +0 -171
  43. package/dist/src/cli/setup/first-run.js +0 -242
  44. package/dist/src/config/ai-manager-hiring.js +0 -121
  45. package/dist/src/config/compat.js +0 -16
  46. package/dist/src/config/feature-flags.js +0 -25
  47. package/dist/src/config/persona-capability-bundles.js +0 -273
  48. package/dist/src/config/persona-hiring.js +0 -270
  49. package/dist/src/config/portfolio-slug-overrides.js +0 -17
  50. package/dist/src/config/pricing.js +0 -37
  51. package/dist/src/config/stripe.js +0 -43
  52. package/dist/src/core/config-writer.js +0 -75
  53. package/dist/src/core/utils/job-aliases.js +0 -47
  54. package/dist/src/core/utils/workflow-parser.js +0 -174
@@ -774,16 +774,6 @@ function renderRail() {
774
774
  statusSpan.textContent = conversationStateLabel(conv);
775
775
  statusSpan.classList.add(conversationUiState(conv));
776
776
  btn.appendChild(statusSpan);
777
- // Issue #578: sourceTrigger chip — show scheduled/webhook badge on automated runs.
778
- if (conv.sourceTrigger && conv.sourceTrigger !== 'manager') {
779
- const trigBadge = document.createElement('span');
780
- trigBadge.className = 'trigger-badge trigger-badge--' + conv.sourceTrigger;
781
- trigBadge.textContent = conv.sourceTrigger === 'scheduled' ? 'Scheduled' : 'Webhook';
782
- trigBadge.title = conv.sourceTrigger === 'scheduled'
783
- ? 'This run was started by the built-in cron scheduler'
784
- : 'This run was triggered by an inbound webhook';
785
- btn.appendChild(trigBadge);
786
- }
787
777
  // Issue #442: A/B badge on rail entry.
788
778
  if (conv.compareMode === 'ab') {
789
779
  const badge = document.createElement('span');
@@ -3814,7 +3804,7 @@ function renderAgentInstallPanel() {
3814
3804
 
3815
3805
  const skipBtn = document.createElement('button');
3816
3806
  skipBtn.className = 'ghost small';
3817
- skipBtn.textContent = 'Skip for now';
3807
+ skipBtn.textContent = 'Choose another agent';
3818
3808
  skipBtn.style.marginLeft = '6px';
3819
3809
  skipBtn.addEventListener('click', () => {
3820
3810
  delete agentInstallState[emp.id];
@@ -4255,18 +4245,7 @@ function startPolling() {
4255
4245
  }
4256
4246
  try {
4257
4247
  if (!fraimDone) {
4258
- const runResp = await fetch(`/api/ai-hub/runs/${conv.runId}`, { headers: { 'x-api-key': 'local-dev' } });
4259
- if (runResp.status === 404) {
4260
- // Run no longer in server registry (e.g. after restart). Stop polling.
4261
- window.clearInterval(state.pollHandle);
4262
- state.pollHandle = null;
4263
- conv.status = 'done';
4264
- upsertConversation(conv);
4265
- renderRail();
4266
- renderActive();
4267
- return;
4268
- }
4269
- const run = await runResp.json();
4248
+ const run = await requestJson(`/api/ai-hub/runs/${conv.runId}`);
4270
4249
  foldRunIntoConversation(conv, run);
4271
4250
  }
4272
4251
  // Issue #442: also poll the compare run when present and not yet terminal.
@@ -4958,7 +4937,7 @@ function wireEvents() {
4958
4937
  }
4959
4938
 
4960
4939
  if (isFirstRun) {
4961
- renderFirstRunLanding();
4940
+ renderActive();
4962
4941
  return;
4963
4942
  }
4964
4943
 
@@ -5372,8 +5351,6 @@ function tfSelectProjectView(view, projectId) {
5372
5351
  tfRenderTree();
5373
5352
  tfRenderProjectContextTop();
5374
5353
  tfApplyWorkspaceMode();
5375
- // Issue #578: reload deployment roster when entering workspace.
5376
- loadDeployments();
5377
5354
  }
5378
5355
  }
5379
5356
 
@@ -5855,197 +5832,6 @@ function tfShowProjectBrief() { const a = document.getElementById('proj-brief-ac
5855
5832
  function tfShowProjectLearnings() { const a = document.getElementById('proj-learnings-acc'); if (a) a.open = true; }
5856
5833
  function tfHideProjectLearnings() { /* panels removed in #521; brief/learnings are inline top sections */ }
5857
5834
 
5858
- // ---------------------------------------------------------------------------
5859
- // Issue #578: Deployment roster (scheduled + webhook triggers)
5860
- // ---------------------------------------------------------------------------
5861
-
5862
- async function loadDeployments() {
5863
- const list = document.getElementById('proj-deployments-list');
5864
- if (!list) return;
5865
- try {
5866
- const [schResp, whResp] = await Promise.all([
5867
- fetch('/api/ai-hub/schedules'),
5868
- fetch('/api/ai-hub/webhooks'),
5869
- ]);
5870
- const schedules = schResp.ok ? await schResp.json() : [];
5871
- const webhooks = whResp.ok ? await whResp.json() : [];
5872
- renderDeploymentList(list, [...schedules, ...webhooks]);
5873
- } catch {
5874
- list.textContent = 'Could not load deployments.';
5875
- }
5876
- }
5877
-
5878
- function renderDeploymentList(container, deployments) {
5879
- container.innerHTML = '';
5880
- if (!deployments.length) {
5881
- const empty = document.createElement('p');
5882
- empty.className = 'dep-empty';
5883
- empty.textContent = 'No deployments yet. Use + Schedule or + Webhook above to add automated triggers.';
5884
- container.appendChild(empty);
5885
- return;
5886
- }
5887
- for (const dep of deployments) {
5888
- const card = document.createElement('div');
5889
- card.className = 'dep-card';
5890
- const top = document.createElement('div');
5891
- top.className = 'dep-card-top';
5892
- const icon = document.createElement('span');
5893
- icon.className = 'dep-type-icon';
5894
- icon.textContent = dep.type === 'scheduled' ? '⏱' : '🔗';
5895
- const label = document.createElement('span');
5896
- label.className = 'dep-label';
5897
- label.textContent = dep.label;
5898
- const typeBadge = document.createElement('span');
5899
- typeBadge.className = 'dep-type-badge dep-type-badge--' + dep.type;
5900
- typeBadge.textContent = dep.type === 'scheduled' ? 'Scheduled' : 'Webhook';
5901
- top.appendChild(icon);
5902
- top.appendChild(label);
5903
- top.appendChild(typeBadge);
5904
- card.appendChild(top);
5905
-
5906
- if (dep.cronExpr) {
5907
- const cron = document.createElement('div');
5908
- cron.className = 'dep-detail';
5909
- cron.textContent = dep.cronExpr;
5910
- card.appendChild(cron);
5911
- }
5912
- if (dep.inboundUrl) {
5913
- const urlRow = document.createElement('div');
5914
- urlRow.className = 'dep-detail dep-detail--url';
5915
- const urlCode = document.createElement('code');
5916
- urlCode.textContent = dep.inboundUrl;
5917
- urlCode.className = 'dep-inbound-url dep-inbound-url--inline';
5918
- const copyBtn = document.createElement('button');
5919
- copyBtn.type = 'button';
5920
- copyBtn.className = 'hm-copy-btn';
5921
- copyBtn.textContent = 'Copy';
5922
- copyBtn.addEventListener('click', () => { navigator.clipboard.writeText(dep.inboundUrl).catch(() => {}); });
5923
- urlRow.appendChild(urlCode);
5924
- urlRow.appendChild(copyBtn);
5925
- card.appendChild(urlRow);
5926
- }
5927
-
5928
- const delBtn = document.createElement('button');
5929
- delBtn.type = 'button';
5930
- delBtn.className = 'dep-del-btn';
5931
- delBtn.title = 'Remove this deployment';
5932
- delBtn.textContent = 'Remove';
5933
- delBtn.addEventListener('click', async () => {
5934
- const endpoint = dep.type === 'scheduled' ? 'schedules' : 'webhooks';
5935
- await fetch('/api/ai-hub/' + endpoint + '/' + dep.id, { method: 'DELETE' });
5936
- await loadDeployments();
5937
- });
5938
- card.appendChild(delBtn);
5939
- container.appendChild(card);
5940
- }
5941
- }
5942
-
5943
- function initDeploymentButtons() {
5944
- const addSchBtn = document.getElementById('dep-add-schedule-btn');
5945
- const addWhBtn = document.getElementById('dep-add-webhook-btn');
5946
- if (addSchBtn) addSchBtn.addEventListener('click', () => openDeploymentModal('schedule'));
5947
- if (addWhBtn) addWhBtn.addEventListener('click', () => openDeploymentModal('webhook'));
5948
-
5949
- // Close buttons
5950
- const schClose = document.getElementById('dep-schedule-close');
5951
- const whClose = document.getElementById('dep-webhook-close');
5952
- if (schClose) schClose.addEventListener('click', () => { document.getElementById('dep-schedule-modal').hidden = true; });
5953
- if (whClose) whClose.addEventListener('click', () => { document.getElementById('dep-webhook-modal').hidden = true; });
5954
-
5955
- // Cancel buttons
5956
- const schCancel = document.getElementById('dep-sch-cancel-btn');
5957
- const whCancel = document.getElementById('dep-wh-cancel-btn');
5958
- if (schCancel) schCancel.addEventListener('click', () => { document.getElementById('dep-schedule-modal').hidden = true; });
5959
- if (whCancel) whCancel.addEventListener('click', () => { document.getElementById('dep-webhook-modal').hidden = true; });
5960
-
5961
- // Save buttons
5962
- const schSave = document.getElementById('dep-sch-save-btn');
5963
- if (schSave) schSave.addEventListener('click', saveScheduleDeployment);
5964
- const whSave = document.getElementById('dep-wh-save-btn');
5965
- if (whSave) whSave.addEventListener('click', saveWebhookDeployment);
5966
-
5967
- // Copy inbound URL button
5968
- const copyBtn = document.getElementById('dep-wh-copy-btn');
5969
- if (copyBtn) copyBtn.addEventListener('click', () => {
5970
- const url = document.getElementById('dep-wh-inbound-url').textContent;
5971
- navigator.clipboard.writeText(url).catch(() => {});
5972
- });
5973
- }
5974
-
5975
- function openDeploymentModal(type) {
5976
- const jobs = state.bootstrap?.jobs ?? [];
5977
- if (type === 'schedule') {
5978
- const modal = document.getElementById('dep-schedule-modal');
5979
- const jobSel = document.getElementById('dep-sch-job');
5980
- jobSel.innerHTML = '';
5981
- for (const j of jobs) {
5982
- const opt = document.createElement('option');
5983
- opt.value = j.id;
5984
- opt.textContent = j.title;
5985
- jobSel.appendChild(opt);
5986
- }
5987
- document.getElementById('dep-sch-error').hidden = true;
5988
- document.getElementById('dep-sch-label').value = '';
5989
- document.getElementById('dep-sch-cron').value = '';
5990
- document.getElementById('dep-sch-instructions').value = '';
5991
- modal.hidden = false;
5992
- } else {
5993
- const modal = document.getElementById('dep-webhook-modal');
5994
- const jobSel = document.getElementById('dep-wh-job');
5995
- jobSel.innerHTML = '';
5996
- for (const j of jobs) {
5997
- const opt = document.createElement('option');
5998
- opt.value = j.id;
5999
- opt.textContent = j.title;
6000
- jobSel.appendChild(opt);
6001
- }
6002
- document.getElementById('dep-wh-error').hidden = true;
6003
- document.getElementById('dep-wh-inbound-row').hidden = true;
6004
- document.getElementById('dep-wh-label').value = '';
6005
- document.getElementById('dep-wh-instructions').value = '';
6006
- modal.hidden = false;
6007
- }
6008
- }
6009
-
6010
- async function saveScheduleDeployment() {
6011
- const label = document.getElementById('dep-sch-label').value.trim();
6012
- const jobId = document.getElementById('dep-sch-job').value;
6013
- const cronExpr = document.getElementById('dep-sch-cron').value.trim();
6014
- const instructions = document.getElementById('dep-sch-instructions').value.trim();
6015
- const errEl = document.getElementById('dep-sch-error');
6016
- if (!label || !cronExpr) { errEl.textContent = 'Label and cron expression are required.'; errEl.hidden = false; return; }
6017
- try {
6018
- const resp = await fetch('/api/ai-hub/schedules', {
6019
- method: 'POST',
6020
- headers: { 'Content-Type': 'application/json' },
6021
- body: JSON.stringify({ label, jobId, cronExpr, instructions: instructions || undefined }),
6022
- });
6023
- if (!resp.ok) { const e = await resp.json().catch(() => ({})); errEl.textContent = e.error || 'Failed to create schedule.'; errEl.hidden = false; return; }
6024
- document.getElementById('dep-schedule-modal').hidden = true;
6025
- await loadDeployments();
6026
- } catch { errEl.textContent = 'Network error — is the Hub running?'; errEl.hidden = false; }
6027
- }
6028
-
6029
- async function saveWebhookDeployment() {
6030
- const label = document.getElementById('dep-wh-label').value.trim();
6031
- const jobId = document.getElementById('dep-wh-job').value;
6032
- const instructions = document.getElementById('dep-wh-instructions').value.trim();
6033
- const errEl = document.getElementById('dep-wh-error');
6034
- if (!label) { errEl.textContent = 'Label is required.'; errEl.hidden = false; return; }
6035
- try {
6036
- const resp = await fetch('/api/ai-hub/webhooks', {
6037
- method: 'POST',
6038
- headers: { 'Content-Type': 'application/json' },
6039
- body: JSON.stringify({ label, jobId, instructions: instructions || undefined }),
6040
- });
6041
- if (!resp.ok) { const e = await resp.json().catch(() => ({})); errEl.textContent = e.error || 'Failed to create webhook.'; errEl.hidden = false; return; }
6042
- const dep = await resp.json();
6043
- document.getElementById('dep-wh-inbound-url').textContent = dep.inboundUrl;
6044
- document.getElementById('dep-wh-inbound-row').hidden = false;
6045
- await loadDeployments();
6046
- } catch { errEl.textContent = 'Network error — is the Hub running?'; errEl.hidden = false; }
6047
- }
6048
-
6049
5835
  // ---------------------------------------------------------------------------
6050
5836
  // Company / Manager / Brain content
6051
5837
  // ---------------------------------------------------------------------------
@@ -8019,8 +7805,6 @@ function tfInitShell() {
8019
7805
  tfRenderRail();
8020
7806
  tfRenderProjectTabs();
8021
7807
  tfShowArea('projects');
8022
- // Issue #578: wire deployment modal buttons.
8023
- initDeploymentButtons();
8024
7808
  // Open the workspace by default so the conversation surface (#conversation,
8025
7809
  // #new-conv-btn, #empty, the welcome line, the project button) is visible on
8026
7810
  // load — preserving the contract the shipped #339/#347/#429/#442 Hub UI
@@ -1731,6 +1731,14 @@ button.small { padding: 4px 10px; font-size: 12px; }
1731
1731
  keep the journey visible. */
1732
1732
  @media (max-width: 640px) {
1733
1733
  .tracker .stage .stage-label { display: none; }
1734
+ .tracker .stage { min-width: 24px; }
1735
+ .tracker .stage-circle {
1736
+ width: 20px;
1737
+ height: 20px;
1738
+ border-width: 1px;
1739
+ font-size: 10px;
1740
+ }
1741
+ .tracker .stage::before { top: 10px; }
1734
1742
  .tracker-active-label { display: block; }
1735
1743
  }
1736
1744
 
@@ -3985,39 +3993,3 @@ body.hub-shell { display: flex; flex-direction: column; height: 100vh; overflow:
3985
3993
  .hs-btn--primary:hover { opacity:.85; }
3986
3994
  .hs-btn--ghost { background:transparent; color:var(--muted); border:1px solid var(--line); }
3987
3995
  .hs-btn--ghost:hover { color:var(--text); border-color:var(--text); }
3988
-
3989
- /* ── Issue #578: Scheduled + Reactive Employees ── */
3990
-
3991
- /* sourceTrigger chip on run rail items */
3992
- .trigger-badge { display:inline-block; padding:1px 6px; border-radius:4px; font-size:10px; font-weight:600; letter-spacing:.02em; flex-shrink:0; }
3993
- .trigger-badge--scheduled { background:rgba(0,122,255,.12); color:#0071e3; }
3994
- .trigger-badge--webhook { background:rgba(88,86,214,.12); color:#5856d6; }
3995
-
3996
- /* Deployment roster accordion */
3997
- #proj-deployments-acc { margin-top:0; }
3998
- .dep-actions { display:flex; gap:8px; margin-top:8px; }
3999
- .dep-add-btn { padding:4px 12px; background:var(--accent-soft,rgba(0,113,227,.08)); color:var(--accent,#0071e3); border:1px solid rgba(0,113,227,.2); border-radius:8px; font-size:12px; font-weight:600; cursor:pointer; }
4000
- .dep-add-btn:hover { background:var(--accent,#0071e3); color:#fff; }
4001
-
4002
- /* Deployment cards */
4003
- .dep-card { display:flex; flex-wrap:wrap; align-items:baseline; gap:6px; padding:8px 10px; background:var(--surface,#fff); border:1px solid var(--line,#e5e5e5); border-radius:10px; margin-bottom:6px; }
4004
- .dep-card-top { display:flex; align-items:center; gap:6px; flex:1; min-width:0; }
4005
- .dep-type-icon { font-size:14px; flex-shrink:0; }
4006
- .dep-label { font-size:13px; font-weight:600; color:var(--text,#1d1d1f); flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
4007
- .dep-type-badge { display:inline-block; padding:1px 7px; border-radius:4px; font-size:10px; font-weight:600; flex-shrink:0; }
4008
- .dep-type-badge--scheduled { background:rgba(0,122,255,.12); color:#0071e3; }
4009
- .dep-type-badge--webhook { background:rgba(88,86,214,.12); color:#5856d6; }
4010
- .dep-detail { width:100%; font-size:11px; color:var(--muted,#888); margin-left:20px; }
4011
- .dep-detail--url { display:flex; align-items:center; gap:6px; }
4012
- .dep-inbound-url { font-size:11px; word-break:break-all; color:var(--muted,#888); flex:1; }
4013
- .dep-inbound-url--inline { display:inline; font-size:11px; }
4014
- .dep-del-btn { margin-left:auto; padding:2px 8px; background:transparent; border:1px solid var(--line,#e5e5e5); border-radius:6px; font-size:11px; color:var(--muted,#888); cursor:pointer; flex-shrink:0; }
4015
- .dep-del-btn:hover { border-color:#ff3b30; color:#ff3b30; }
4016
- .dep-empty { color:var(--muted,#888); font-size:12px; margin:4px 0 8px; line-height:1.5; }
4017
-
4018
- /* Deployment modals */
4019
- .dep-modal-actions { display:flex; gap:8px; margin-top:12px; }
4020
- .dep-error { color:#ff3b30; font-size:12px; margin-top:4px; }
4021
- .cancel-button { padding:7px 18px; border-radius:8px; font-size:13px; font-weight:600; cursor:pointer; background:transparent; color:var(--muted,#888); border:1px solid var(--line,#e5e5e5); }
4022
- .cancel-button:hover { border-color:var(--text,#1d1d1f); color:var(--text,#1d1d1f); }
4023
- .dep-inbound-url-row { display:flex; align-items:center; gap:8px; padding:6px 10px; background:var(--bg,#f5f5f7); border-radius:8px; margin-top:6px; }
@@ -20,8 +20,8 @@
20
20
  Replaced wholesale by script.js once /api/first-run/session returns. -->
21
21
  <li class="row skeleton-row" data-row-id="node" data-row-status="pending"><span class="icon" aria-hidden="true">.</span><span class="label">Node.js</span><span class="verb" data-testid="row-verb">checking...</span></li>
22
22
  <li class="row skeleton-row" data-row-id="git" data-row-status="pending"><span class="icon" aria-hidden="true">.</span><span class="label">git</span><span class="verb" data-testid="row-verb">checking...</span></li>
23
+ <li class="row skeleton-row" data-row-id="agent" data-row-status="pending"><span class="icon" aria-hidden="true">.</span><span class="label">Locally installed AI agents</span><span class="verb" data-testid="row-verb">checking...</span></li>
23
24
  <li class="row skeleton-row" data-row-id="fraim" data-row-status="pending"><span class="icon" aria-hidden="true">.</span><span class="label">FRAIM</span><span class="verb" data-testid="row-verb">checking...</span></li>
24
- <li class="row skeleton-row" data-row-id="agent" data-row-status="pending"><span class="icon" aria-hidden="true">.</span><span class="label">Execution surfaces</span><span class="verb" data-testid="row-verb">checking...</span></li>
25
25
  </ul>
26
26
  <div class="actions">
27
27
  <button id="primary-button" class="primary-button" data-testid="primary-button">Set up FRAIM</button>