@memberjunction/ng-dashboards 6.2.0-edge.6 → 6.2.0-edge.8

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 (233) hide show
  1. package/README.md +23 -16
  2. package/dist/AI/components/analytics/agent-runs/agent-run-analysis.component.js +2 -2
  3. package/dist/AI/components/analytics/agent-runs/agent-run-analysis.component.js.map +1 -1
  4. package/dist/AI/components/analytics/realtime/realtime-management.component.d.ts.map +1 -1
  5. package/dist/AI/components/analytics/realtime/realtime-management.component.js +3 -1
  6. package/dist/AI/components/analytics/realtime/realtime-management.component.js.map +1 -1
  7. package/dist/AI/components/analytics/realtime/realtime-overview.component.d.ts +1 -1
  8. package/dist/AI/components/analytics/realtime/realtime-overview.component.js +3 -3
  9. package/dist/AI/components/analytics/realtime/realtime-overview.component.js.map +1 -1
  10. package/dist/AI/components/analytics/realtime/realtime-session-data.d.ts +6 -4
  11. package/dist/AI/components/analytics/realtime/realtime-session-data.d.ts.map +1 -1
  12. package/dist/AI/components/analytics/realtime/realtime-session-data.js +8 -2
  13. package/dist/AI/components/analytics/realtime/realtime-session-data.js.map +1 -1
  14. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts.map +1 -1
  15. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +31 -10
  16. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -1
  17. package/dist/AI/components/autotagging/components/classify-item-grid.component.js +1 -1
  18. package/dist/AI/components/autotagging/components/classify-item-grid.component.js.map +1 -1
  19. package/dist/AI/components/autotagging/components/classify-org-context-editor.component.d.ts.map +1 -1
  20. package/dist/AI/components/autotagging/components/classify-org-context-editor.component.js +1 -0
  21. package/dist/AI/components/autotagging/components/classify-org-context-editor.component.js.map +1 -1
  22. package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.d.ts.map +1 -1
  23. package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.js +1 -0
  24. package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.js.map +1 -1
  25. package/dist/AI/components/autotagging/tabs/sources-tab.component.d.ts.map +1 -1
  26. package/dist/AI/components/autotagging/tabs/sources-tab.component.js +1 -0
  27. package/dist/AI/components/autotagging/tabs/sources-tab.component.js.map +1 -1
  28. package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts.map +1 -1
  29. package/dist/AI/components/duplicates/duplicate-detection-resource.component.js +1 -0
  30. package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -1
  31. package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js +2 -2
  32. package/dist/AI/components/tags/tags-resource.component.d.ts.map +1 -1
  33. package/dist/AI/components/tags/tags-resource.component.js +14 -24
  34. package/dist/AI/components/tags/tags-resource.component.js.map +1 -1
  35. package/dist/AI/components/vectors/vector-management-resource.component.d.ts.map +1 -1
  36. package/dist/AI/components/vectors/vector-management-resource.component.js +14 -7
  37. package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
  38. package/dist/AI/services/ai-instrumentation.service.d.ts.map +1 -1
  39. package/dist/AI/services/ai-instrumentation.service.js +4 -2
  40. package/dist/AI/services/ai-instrumentation.service.js.map +1 -1
  41. package/dist/Actions/action-result-code.d.ts +80 -0
  42. package/dist/Actions/action-result-code.d.ts.map +1 -0
  43. package/dist/Actions/action-result-code.js +163 -0
  44. package/dist/Actions/action-result-code.js.map +1 -0
  45. package/dist/Actions/components/actions-overview.component.d.ts +8 -0
  46. package/dist/Actions/components/actions-overview.component.d.ts.map +1 -1
  47. package/dist/Actions/components/actions-overview.component.js +12 -9
  48. package/dist/Actions/components/actions-overview.component.js.map +1 -1
  49. package/dist/Actions/components/execution-monitoring.component.d.ts +29 -9
  50. package/dist/Actions/components/execution-monitoring.component.d.ts.map +1 -1
  51. package/dist/Actions/components/execution-monitoring.component.js +65 -42
  52. package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
  53. package/dist/Actions/components/explorer/action-card.component.d.ts.map +1 -1
  54. package/dist/Actions/components/explorer/action-card.component.js +5 -4
  55. package/dist/Actions/components/explorer/action-card.component.js.map +1 -1
  56. package/dist/ChiefOfStaff/chief-of-staff-agent-context.d.ts +92 -130
  57. package/dist/ChiefOfStaff/chief-of-staff-agent-context.d.ts.map +1 -1
  58. package/dist/ChiefOfStaff/chief-of-staff-agent-context.js +189 -274
  59. package/dist/ChiefOfStaff/chief-of-staff-agent-context.js.map +1 -1
  60. package/dist/ChiefOfStaff/chief-of-staff-approvals.component.d.ts +29 -0
  61. package/dist/ChiefOfStaff/chief-of-staff-approvals.component.d.ts.map +1 -0
  62. package/dist/ChiefOfStaff/chief-of-staff-approvals.component.js +666 -0
  63. package/dist/ChiefOfStaff/chief-of-staff-approvals.component.js.map +1 -0
  64. package/dist/ChiefOfStaff/chief-of-staff-governance.component.d.ts +56 -0
  65. package/dist/ChiefOfStaff/chief-of-staff-governance.component.d.ts.map +1 -0
  66. package/dist/ChiefOfStaff/chief-of-staff-governance.component.js +515 -0
  67. package/dist/ChiefOfStaff/chief-of-staff-governance.component.js.map +1 -0
  68. package/dist/ChiefOfStaff/chief-of-staff-live-refresh.d.ts +14 -0
  69. package/dist/ChiefOfStaff/chief-of-staff-live-refresh.d.ts.map +1 -0
  70. package/dist/ChiefOfStaff/chief-of-staff-live-refresh.js +39 -0
  71. package/dist/ChiefOfStaff/chief-of-staff-live-refresh.js.map +1 -0
  72. package/dist/ChiefOfStaff/chief-of-staff-overview.component.d.ts +17 -0
  73. package/dist/ChiefOfStaff/chief-of-staff-overview.component.d.ts.map +1 -0
  74. package/dist/ChiefOfStaff/chief-of-staff-overview.component.js +485 -0
  75. package/dist/ChiefOfStaff/chief-of-staff-overview.component.js.map +1 -0
  76. package/dist/ChiefOfStaff/chief-of-staff-page-base.d.ts +139 -0
  77. package/dist/ChiefOfStaff/chief-of-staff-page-base.d.ts.map +1 -0
  78. package/dist/ChiefOfStaff/chief-of-staff-page-base.js +602 -0
  79. package/dist/ChiefOfStaff/chief-of-staff-page-base.js.map +1 -0
  80. package/dist/ChiefOfStaff/index.d.ts +4 -1
  81. package/dist/ChiefOfStaff/index.d.ts.map +1 -1
  82. package/dist/ChiefOfStaff/index.js +4 -1
  83. package/dist/ChiefOfStaff/index.js.map +1 -1
  84. package/dist/Communication/communication-monitor-resource.component.js +3 -3
  85. package/dist/Communication/communication-monitor-resource.component.js.map +1 -1
  86. package/dist/Communication/communication-runs-resource.component.js +3 -3
  87. package/dist/Communication/communication-runs-resource.component.js.map +1 -1
  88. package/dist/ComponentStudio/component-studio-dashboard.component.d.ts.map +1 -1
  89. package/dist/ComponentStudio/component-studio-dashboard.component.js +1 -0
  90. package/dist/ComponentStudio/component-studio-dashboard.component.js.map +1 -1
  91. package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts.map +1 -1
  92. package/dist/ComponentStudio/components/artifact-selection-dialog.component.js +2 -1
  93. package/dist/ComponentStudio/components/artifact-selection-dialog.component.js.map +1 -1
  94. package/dist/ComponentStudio/services/component-version.service.d.ts.map +1 -1
  95. package/dist/ComponentStudio/services/component-version.service.js +3 -0
  96. package/dist/ComponentStudio/services/component-version.service.js.map +1 -1
  97. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +21 -2
  98. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
  99. package/dist/DataExplorer/data-explorer-dashboard.component.js +32 -5
  100. package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
  101. package/dist/DevTools/graphql-console.component.js +2 -2
  102. package/dist/DevTools/lazy-module-status.component.js +2 -2
  103. package/dist/FormBuilder/form-builder-resource.component.d.ts.map +1 -1
  104. package/dist/FormBuilder/form-builder-resource.component.js +5 -0
  105. package/dist/FormBuilder/form-builder-resource.component.js.map +1 -1
  106. package/dist/Integration/components/connections/connections.component.js +2 -2
  107. package/dist/Integration/services/integration-data.service.d.ts +1 -1
  108. package/dist/Integration/services/integration-data.service.d.ts.map +1 -1
  109. package/dist/Integration/services/integration-data.service.js +4 -3
  110. package/dist/Integration/services/integration-data.service.js.map +1 -1
  111. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.d.ts.map +1 -1
  112. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js +11 -3
  113. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js.map +1 -1
  114. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js +16 -16
  115. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js.map +1 -1
  116. package/dist/KnowledgeHub/components/visualize/semantic-graph/semantic-graph-explorer.component.d.ts +113 -0
  117. package/dist/KnowledgeHub/components/visualize/semantic-graph/semantic-graph-explorer.component.d.ts.map +1 -0
  118. package/dist/KnowledgeHub/components/visualize/semantic-graph/semantic-graph-explorer.component.js +1184 -0
  119. package/dist/KnowledgeHub/components/visualize/semantic-graph/semantic-graph-explorer.component.js.map +1 -0
  120. package/dist/KnowledgeHub/components/visualize/visualize-agent-context.d.ts +1 -1
  121. package/dist/KnowledgeHub/components/visualize/visualize-agent-context.d.ts.map +1 -1
  122. package/dist/KnowledgeHub/components/visualize/visualize-agent-context.js +1 -1
  123. package/dist/KnowledgeHub/components/visualize/visualize-agent-context.js.map +1 -1
  124. package/dist/KnowledgeHub/components/visualize/visualize-resource.component.d.ts +1 -1
  125. package/dist/KnowledgeHub/components/visualize/visualize-resource.component.d.ts.map +1 -1
  126. package/dist/KnowledgeHub/components/visualize/visualize-resource.component.js +21 -10
  127. package/dist/KnowledgeHub/components/visualize/visualize-resource.component.js.map +1 -1
  128. package/dist/Lists/components/lists-browse-resource.component.js +1 -1
  129. package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
  130. package/dist/Lists/components/lists-my-lists-resource.component.js +1 -1
  131. package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
  132. package/dist/LoginStudio/login-studio-resource.component.d.ts.map +1 -1
  133. package/dist/LoginStudio/login-studio-resource.component.js +1 -0
  134. package/dist/LoginStudio/login-studio-resource.component.js.map +1 -1
  135. package/dist/PredictiveStudio/components/ps-experiments.component.d.ts.map +1 -1
  136. package/dist/PredictiveStudio/components/ps-experiments.component.js +1 -0
  137. package/dist/PredictiveStudio/components/ps-experiments.component.js.map +1 -1
  138. package/dist/PredictiveStudio/components/ps-pipeline-wizard.component.js +2 -2
  139. package/dist/PredictiveStudio/components/ps-predictions-grid.component.d.ts.map +1 -1
  140. package/dist/PredictiveStudio/components/ps-predictions-grid.component.js +3 -0
  141. package/dist/PredictiveStudio/components/ps-predictions-grid.component.js.map +1 -1
  142. package/dist/PredictiveStudio/engine/predictive-studio.engine.d.ts.map +1 -1
  143. package/dist/PredictiveStudio/engine/predictive-studio.engine.js +1 -0
  144. package/dist/PredictiveStudio/engine/predictive-studio.engine.js.map +1 -1
  145. package/dist/PredictiveStudio/resources/ps-predictions-resource.component.d.ts.map +1 -1
  146. package/dist/PredictiveStudio/resources/ps-predictions-resource.component.js +1 -0
  147. package/dist/PredictiveStudio/resources/ps-predictions-resource.component.js.map +1 -1
  148. package/dist/QueryBrowser/query-browser-resource.component.d.ts +26 -0
  149. package/dist/QueryBrowser/query-browser-resource.component.d.ts.map +1 -1
  150. package/dist/QueryBrowser/query-browser-resource.component.js +375 -252
  151. package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
  152. package/dist/SystemDiagnostics/system-diagnostics.component.d.ts.map +1 -1
  153. package/dist/SystemDiagnostics/system-diagnostics.component.js +4 -2
  154. package/dist/SystemDiagnostics/system-diagnostics.component.js.map +1 -1
  155. package/dist/UserRoutines/user-routines-resource.component.d.ts +8 -1
  156. package/dist/UserRoutines/user-routines-resource.component.d.ts.map +1 -1
  157. package/dist/UserRoutines/user-routines-resource.component.js +22 -4
  158. package/dist/UserRoutines/user-routines-resource.component.js.map +1 -1
  159. package/dist/VersionHistory/components/diff-resource.component.d.ts.map +1 -1
  160. package/dist/VersionHistory/components/diff-resource.component.js +1 -0
  161. package/dist/VersionHistory/components/diff-resource.component.js.map +1 -1
  162. package/dist/VideoStudio/components/vs-archetype-editor.component.d.ts +162 -0
  163. package/dist/VideoStudio/components/vs-archetype-editor.component.d.ts.map +1 -0
  164. package/dist/VideoStudio/components/vs-archetype-editor.component.js +1105 -0
  165. package/dist/VideoStudio/components/vs-archetype-editor.component.js.map +1 -0
  166. package/dist/VideoStudio/components/vs-audio-options.component.d.ts +27 -0
  167. package/dist/VideoStudio/components/vs-audio-options.component.d.ts.map +1 -0
  168. package/dist/VideoStudio/components/vs-audio-options.component.js +119 -0
  169. package/dist/VideoStudio/components/vs-audio-options.component.js.map +1 -0
  170. package/dist/VideoStudio/components/vs-copilot-panel.component.d.ts +105 -0
  171. package/dist/VideoStudio/components/vs-copilot-panel.component.d.ts.map +1 -0
  172. package/dist/VideoStudio/components/vs-copilot-panel.component.js +560 -0
  173. package/dist/VideoStudio/components/vs-copilot-panel.component.js.map +1 -0
  174. package/dist/VideoStudio/components/vs-production-brief.component.d.ts +163 -0
  175. package/dist/VideoStudio/components/vs-production-brief.component.d.ts.map +1 -0
  176. package/dist/VideoStudio/components/vs-production-brief.component.js +1054 -0
  177. package/dist/VideoStudio/components/vs-production-brief.component.js.map +1 -0
  178. package/dist/VideoStudio/components/vs-setup-health-card.component.d.ts +43 -0
  179. package/dist/VideoStudio/components/vs-setup-health-card.component.d.ts.map +1 -0
  180. package/dist/VideoStudio/components/vs-setup-health-card.component.js +412 -0
  181. package/dist/VideoStudio/components/vs-setup-health-card.component.js.map +1 -0
  182. package/dist/VideoStudio/components/vs-studio-slide-in.component.d.ts +73 -0
  183. package/dist/VideoStudio/components/vs-studio-slide-in.component.d.ts.map +1 -0
  184. package/dist/VideoStudio/components/vs-studio-slide-in.component.js +271 -0
  185. package/dist/VideoStudio/components/vs-studio-slide-in.component.js.map +1 -0
  186. package/dist/VideoStudio/index.d.ts +12 -0
  187. package/dist/VideoStudio/index.d.ts.map +1 -0
  188. package/dist/VideoStudio/index.js +12 -0
  189. package/dist/VideoStudio/index.js.map +1 -0
  190. package/dist/VideoStudio/resources/video-studio-archetypes-resource.component.d.ts +118 -0
  191. package/dist/VideoStudio/resources/video-studio-archetypes-resource.component.d.ts.map +1 -0
  192. package/dist/VideoStudio/resources/video-studio-archetypes-resource.component.js +964 -0
  193. package/dist/VideoStudio/resources/video-studio-archetypes-resource.component.js.map +1 -0
  194. package/dist/VideoStudio/resources/video-studio-brand-kits-resource.component.d.ts +70 -0
  195. package/dist/VideoStudio/resources/video-studio-brand-kits-resource.component.d.ts.map +1 -0
  196. package/dist/VideoStudio/resources/video-studio-brand-kits-resource.component.js +600 -0
  197. package/dist/VideoStudio/resources/video-studio-brand-kits-resource.component.js.map +1 -0
  198. package/dist/VideoStudio/resources/video-studio-productions-resource.component.d.ts +182 -0
  199. package/dist/VideoStudio/resources/video-studio-productions-resource.component.d.ts.map +1 -0
  200. package/dist/VideoStudio/resources/video-studio-productions-resource.component.js +1481 -0
  201. package/dist/VideoStudio/resources/video-studio-productions-resource.component.js.map +1 -0
  202. package/dist/VideoStudio/services/vs-studio-slide-in-state.service.d.ts +102 -0
  203. package/dist/VideoStudio/services/vs-studio-slide-in-state.service.d.ts.map +1 -0
  204. package/dist/VideoStudio/services/vs-studio-slide-in-state.service.js +240 -0
  205. package/dist/VideoStudio/services/vs-studio-slide-in-state.service.js.map +1 -0
  206. package/dist/VideoStudio/video-studio-agent-context.d.ts +495 -0
  207. package/dist/VideoStudio/video-studio-agent-context.d.ts.map +1 -0
  208. package/dist/VideoStudio/video-studio-agent-context.js +992 -0
  209. package/dist/VideoStudio/video-studio-agent-context.js.map +1 -0
  210. package/dist/ai-dashboards.module.d.ts +46 -41
  211. package/dist/ai-dashboards.module.d.ts.map +1 -1
  212. package/dist/ai-dashboards.module.js +33 -7
  213. package/dist/ai-dashboards.module.js.map +1 -1
  214. package/dist/module.d.ts +13 -12
  215. package/dist/module.d.ts.map +1 -1
  216. package/dist/module.js +7 -0
  217. package/dist/module.js.map +1 -1
  218. package/dist/public-api.d.ts +8 -1
  219. package/dist/public-api.d.ts.map +1 -1
  220. package/dist/public-api.js +10 -2
  221. package/dist/public-api.js.map +1 -1
  222. package/dist/shared/action-scheduled-job.d.ts.map +1 -1
  223. package/dist/shared/action-scheduled-job.js +2 -0
  224. package/dist/shared/action-scheduled-job.js.map +1 -1
  225. package/dist/video-studio-dashboards.module.d.ts +40 -0
  226. package/dist/video-studio-dashboards.module.d.ts.map +1 -0
  227. package/dist/video-studio-dashboards.module.js +159 -0
  228. package/dist/video-studio-dashboards.module.js.map +1 -0
  229. package/package.json +78 -71
  230. package/dist/ChiefOfStaff/chief-of-staff-dashboard.component.d.ts +0 -195
  231. package/dist/ChiefOfStaff/chief-of-staff-dashboard.component.d.ts.map +0 -1
  232. package/dist/ChiefOfStaff/chief-of-staff-dashboard.component.js +0 -2910
  233. package/dist/ChiefOfStaff/chief-of-staff-dashboard.component.js.map +0 -1
@@ -1,248 +1,235 @@
1
1
  /**
2
- * Pure, unit-testable helpers for the "My Chief of Staff" Executive Cockpit's
3
- * agent context + client tools.
2
+ * Pure, unit-testable helpers for the Chief of Staff application's pages (Overview,
3
+ * Approvals & Wakes, Governance): their agent context, client tools and policy drafts.
4
+ *
5
+ * Core only: everything here reads core entities (`MJ: AI Agent User Policies`,
6
+ * `MJ: User Routines`, `MJ: AI Agent Requests`). Business data such as priorities, tasks and
7
+ * to-dos comes from Open Apps that add their own nav items to the Chief of Staff application
8
+ * through `NavItem.*` application settings; core never names an Open App's entities.
4
9
  *
5
10
  * 🚨 SAFETY BOUNDARY 🚨
6
- * The Chief of Staff Cockpit exposes ONLY navigation / tab-switch / filter / search /
11
+ * The Chief of Staff pages expose ONLY navigation / search /
7
12
  * refresh / detail-view tools to the co-agent. DELIBERATELY NOT exposed as client tools
8
13
  * (mutations stay human-driven in the UI):
9
14
  * - Approving or rejecting `MJ: AI Agent Requests`
10
15
  * - Modifying or saving `MJ: AI Agent User Policies` governance toggles / thresholds
11
16
  * - Triggering "Wake Now" or pausing/resuming `MJ: User Routines`
12
17
  *
13
- * Published context exposes only aggregate counts, active tab/filter state, governance
18
+ * Published context exposes only aggregate counts, the current page and search, governance
14
19
  * mode summaries, and bounded display names (capped at 25) — never raw request payloads,
15
20
  * custom instructions overrides, or private message content.
16
21
  */
17
- import { CompositeKey } from '@memberjunction/core';
18
- import { EscapeSQLString, GroupByUUID, UUIDsEqual } from '@memberjunction/global';
22
+ import { EscapeSQLString } from '@memberjunction/global';
19
23
  import { AGENT_CONTEXT_NAME_LIST_CAP, BoundNameList, ValidateEnumParam, ValidateStringParam, } from '../shared/agent-tool-validation';
20
24
  /**
21
- * The cockpit serves one agent, identified by its metadata name. The id is resolved at runtime
25
+ * The pages serve one agent, identified by its metadata name. The id is resolved at runtime
22
26
  * through `AIEngineBase.GetAgentByName`, never hardcoded.
23
27
  */
24
28
  export const CHIEF_OF_STAFF_AGENT_NAME = 'Chief of Staff';
25
- export const VALID_CHIEF_OF_STAFF_TABS = [
29
+ /** The name of the Chief of Staff application whose nav items open the pages. */
30
+ export const CHIEF_OF_STAFF_APP_NAME = 'Chief of Staff';
31
+ export const CHIEF_OF_STAFF_PAGES = [
26
32
  'overview',
27
- 'priorities',
28
33
  'approvals-wakes',
29
34
  'governance',
30
35
  ];
31
- export const VALID_HEALTH_FILTERS = [
32
- 'all',
33
- 'OnTrack',
34
- 'AtRisk',
35
- 'OffTrack',
36
- 'Completed',
37
- 'Paused',
38
- ];
36
+ /** Each page's nav item label; must match the application's `DefaultNavItems`. */
37
+ export const CHIEF_OF_STAFF_PAGE_LABELS = {
38
+ overview: 'Overview',
39
+ 'approvals-wakes': 'Approvals & Wakes',
40
+ governance: 'Governance',
41
+ };
42
+ /** Each page's Font Awesome icon; matches the application's `DefaultNavItems`. */
43
+ export const CHIEF_OF_STAFF_PAGE_ICONS = {
44
+ overview: 'fa-solid fa-compass',
45
+ 'approvals-wakes': 'fa-solid fa-bell-concierge',
46
+ governance: 'fa-solid fa-shield-halved',
47
+ };
39
48
  /**
40
- * Returns `true` when an `MJ: AI Agent Requests` row represents an actionable approval or
41
- * review request for the Executive Cockpit's Pending Approvals queue, and `false` when it
42
- * is a conversational `Information` turn created by `BaseAgent` when ending a chat turn.
49
+ * True for a one-shot routine that has run and has no next time: the dispatcher disables a one-shot
50
+ * once it fires, so "Disabled" here means "done", not "broken". A one-shot still waiting for its
51
+ * time is not spent, whatever it has run before (a manual run keeps the schedule); a one-shot that
52
+ * was disabled before ever running is just disabled; a recurring routine is never spent.
43
53
  */
44
- export function IsApprovalRequest(req) {
45
- // The RequestType virtual field carries the type name; classify on it alone.
46
- const typeName = req.RequestType?.trim().toLowerCase() ?? '';
47
- return typeName !== 'information';
54
+ export function IsSpentOneShotRoutine(routine) {
55
+ return routine.ScheduleMode === 'OneShot'
56
+ && routine.Status === 'Disabled'
57
+ && routine.NextRunAt == null
58
+ && routine.LastRunAt != null;
48
59
  }
49
- export function ParseOptionalDate(val) {
50
- if (!val) {
51
- return null;
52
- }
53
- if (val instanceof Date) {
54
- return isNaN(val.getTime()) ? null : val;
55
- }
56
- const parsed = new Date(val);
57
- return isNaN(parsed.getTime()) ? null : parsed;
60
+ /** 'Fired' for a spent one-shot, otherwise the routine's own Status. */
61
+ export function RoutineDisplayStatus(routine) {
62
+ return IsSpentOneShotRoutine(routine) ? 'Fired' : routine.Status;
58
63
  }
59
64
  /**
60
- * Builds the primary key of a BizApps task from the entity's own primary key column(s) and the
61
- * in-memory row. Tasks is an OpenApp entity, so neither the column name nor the column count is
62
- * assumed; the same key feeds `OpenEntityRecord` and the `PrimaryKey` parameter of `Update Record`.
65
+ * Display order for the wake schedule: routines with a next wake first, soonest first; then the
66
+ * unscheduled (paused, or disabled before ever running); spent one-shots last, most recent first.
67
+ * Returns a new array.
63
68
  */
64
- export function BuildTaskRecordKey(entityInfo, task) {
65
- return CompositeKey.FromEntityRecord(entityInfo, { ...task });
69
+ export function SortRoutinesForDisplay(routines) {
70
+ const rank = (r) => (IsSpentOneShotRoutine(r) ? 2 : r.NextRunAt != null ? 0 : 1);
71
+ const time = (value) => {
72
+ const parsed = ParseOptionalDate(value);
73
+ return parsed ? parsed.getTime() : Number.POSITIVE_INFINITY;
74
+ };
75
+ return [...routines].sort((a, b) => {
76
+ const ra = rank(a);
77
+ const rb = rank(b);
78
+ if (ra !== rb)
79
+ return ra - rb;
80
+ if (ra === 0)
81
+ return time(a.NextRunAt) - time(b.NextRunAt);
82
+ if (ra === 2)
83
+ return time(b.LastRunAt) - time(a.LastRunAt);
84
+ return 0;
85
+ });
66
86
  }
67
- export function IsTaskPriorityObjective(task) {
68
- if (task.IsPriority === true || task.IsPriority === 1) {
69
- return true;
70
- }
71
- const typeLabel = (task.Type ?? task.TaskType ?? '').toLowerCase();
72
- if (typeLabel.includes('priority') ||
73
- typeLabel.includes('objective') ||
74
- typeLabel.includes('okr')) {
75
- return true;
87
+ /**
88
+ * Reads the email draft out of an approval request's Comments. Returns null when the comments are
89
+ * empty, not JSON, or not an email (a call brief, say), so callers can show the draft only when
90
+ * there is one. An older payload without `Operation` counts as a `Send` when To and Subject exist.
91
+ */
92
+ export function ParseEmailApprovalPayload(comments) {
93
+ const text = comments?.trim();
94
+ if (!text || !text.startsWith('{')) {
95
+ return null;
76
96
  }
77
- return task.ParentID == null && (task.HealthStatus != null || task.PlanningPeriod != null);
78
- }
79
- export function NormalizeTaskHealth(task) {
80
- if (task.Status === 'Completed' || task.Status === 'Done' || task.HealthStatus === 'Completed') {
81
- return 'Completed';
97
+ let raw;
98
+ try {
99
+ raw = JSON.parse(text);
82
100
  }
83
- if (task.HealthStatus === 'AtRisk' || task.HealthStatus === 'OffTrack' || task.HealthStatus === 'Paused') {
84
- return task.HealthStatus;
101
+ catch {
102
+ return null;
85
103
  }
86
- return 'OnTrack';
87
- }
88
- /**
89
- * Percent progress from `BaselineValue` toward `TargetValue`, clamped to 0-100.
90
- * Honors `MetricDirection` implicitly: a Down target (target < baseline) measures reduction.
91
- * Returns null when there is no target or the target equals the baseline (no measurable span).
92
- */
93
- export function ComputeTaskMetricPercent(task) {
94
- if (task.TargetValue == null) {
104
+ if (!raw || typeof raw !== 'object') {
95
105
  return null;
96
106
  }
97
- const baseline = task.BaselineValue ?? 0;
98
- const span = task.TargetValue - baseline;
99
- if (span === 0) {
107
+ const record = raw;
108
+ const to = stringField(record, 'To');
109
+ const subject = stringField(record, 'Subject');
110
+ const body = stringField(record, 'Body');
111
+ if (to == null || subject == null || body == null) {
100
112
  return null;
101
113
  }
102
- const current = task.CurrentValue ?? baseline;
103
- const raw = ((current - baseline) / span) * 100;
104
- return Math.max(0, Math.min(100, Math.round(raw)));
114
+ const operation = stringField(record, 'Operation');
115
+ const op = operation === 'Reply' || operation === 'Forward' ? operation : 'Send';
116
+ const cc = Array.isArray(record['CCRecipients'])
117
+ ? record['CCRecipients'].filter((c) => typeof c === 'string' && c.trim().length > 0)
118
+ : [];
119
+ return { Operation: op, From: stringField(record, 'From'), To: to, CC: cc, Subject: subject, Body: body };
105
120
  }
106
- export function BuildCockpitScopeFilters(currentUserId, chiefOfStaffAgentId) {
107
- const user = EscapeSQLString(currentUserId);
108
- const agent = EscapeSQLString(chiefOfStaffAgentId);
121
+ /** The draft as plain text for a mail client: headers, a blank line, then the body. */
122
+ export function FormatEmailDraftForClipboard(draft) {
123
+ const lines = [`To: ${draft.To}`];
124
+ if (draft.CC.length > 0) {
125
+ lines.push(`CC: ${draft.CC.join(', ')}`);
126
+ }
127
+ lines.push(`Subject: ${draft.Subject}`, '', draft.Body);
128
+ return lines.join('\n');
129
+ }
130
+ function stringField(record, key) {
131
+ const value = record[key];
132
+ return typeof value === 'string' ? value : null;
133
+ }
134
+ /** The draft shown before the user has a policy record. */
135
+ export function CreateDefaultPolicyDraft() {
109
136
  return {
110
- Policy: `AgentID = '${agent}' AND UserID = '${user}'`,
111
- Routines: `UserID = '${user}' AND (RoutineType = 'AgentWake' OR TargetID = '${agent}')`,
112
- Requests: `AgentID = '${agent}' AND RequestForUserID = '${user}' AND (RequestType IS NULL OR RequestType <> 'Information')`,
137
+ DisplayNameOverride: 'Chief of Staff',
138
+ Status: 'Active',
139
+ OnboardingStatus: 'Completed',
140
+ CoordinationMode: 'Coordinator',
141
+ DefaultDataAccessMode: 'UserCeiling',
142
+ EmailChannelMode: 'DraftOnly',
143
+ CalendarChannelMode: 'ProposeWithApproval',
144
+ PhoneChannelMode: 'Disabled',
145
+ MessagingChannelMode: 'Enabled',
146
+ AllowInterAgentCoordination: true,
147
+ RequireApprovalForExternalComms: true,
148
+ RequireApprovalForFinancials: true,
149
+ RequireApprovalForDestructiveActions: true,
150
+ AutoApproveAmountThreshold: 0,
151
+ InstructionsOverride: '',
113
152
  };
114
153
  }
115
- /** OpenApp entity holding the person linked to the signed-in MJ user (`LinkedUserID`). */
116
- export const BIZAPPS_PEOPLE_ENTITY_NAME = 'MJ_BizApps_Common: People';
117
- /** OpenApp entity linking tasks to the people assigned to them. */
118
- export const BIZAPPS_TASK_ASSIGNMENTS_ENTITY_NAME = 'MJ_BizApps_Tasks: Task Assignments';
119
- /** CSS modifier for a task priority badge, keyed by the Tasks `Priority` value list (Critical/High/Medium/Low). */
120
- export function GetTaskPriorityClass(priority) {
121
- switch ((priority ?? '').toLowerCase()) {
122
- case 'critical':
123
- return 'priority-critical';
124
- case 'high':
125
- return 'priority-high';
126
- case 'low':
127
- return 'priority-low';
128
- default:
129
- return 'priority-normal';
154
+ /** A draft copied from the user's policy record, or the default draft when there is none. */
155
+ export function BuildPolicyDraftFromEntity(entity) {
156
+ if (!entity) {
157
+ return CreateDefaultPolicyDraft();
130
158
  }
159
+ return {
160
+ DisplayNameOverride: entity.DisplayNameOverride ?? '',
161
+ Status: entity.Status,
162
+ OnboardingStatus: entity.OnboardingStatus,
163
+ CoordinationMode: entity.CoordinationMode,
164
+ DefaultDataAccessMode: entity.DefaultDataAccessMode,
165
+ EmailChannelMode: entity.EmailChannelMode,
166
+ CalendarChannelMode: entity.CalendarChannelMode,
167
+ PhoneChannelMode: entity.PhoneChannelMode,
168
+ MessagingChannelMode: entity.MessagingChannelMode,
169
+ AllowInterAgentCoordination: entity.AllowInterAgentCoordination,
170
+ RequireApprovalForExternalComms: entity.RequireApprovalForExternalComms,
171
+ RequireApprovalForFinancials: entity.RequireApprovalForFinancials,
172
+ RequireApprovalForDestructiveActions: entity.RequireApprovalForDestructiveActions,
173
+ AutoApproveAmountThreshold: entity.AutoApproveAmountThreshold,
174
+ InstructionsOverride: entity.InstructionsOverride ?? '',
175
+ };
131
176
  }
132
- /**
133
- * Resolve the BizApps person linked to `currentUserId` and the filter that limits the Tasks query to work
134
- * that person created or is assigned to. Throws when either lookup fails so the caller can show the error.
135
- */
136
- export async function ResolvePersonTaskScope(runner, currentUserId) {
137
- const people = await runner.RunView({
138
- EntityName: BIZAPPS_PEOPLE_ENTITY_NAME,
139
- ExtraFilter: `LinkedUserID = '${EscapeSQLString(currentUserId)}'`,
140
- Fields: ['ID'],
141
- MaxRows: 1,
142
- ResultType: 'simple',
143
- });
144
- if (!people.Success) {
145
- throw new Error(people.ErrorMessage ?? 'Failed to resolve the linked person.');
146
- }
147
- const personID = people.Results[0]?.ID;
148
- if (!personID) {
149
- return { HasLinkedPerson: false };
150
- }
151
- const assignments = await runner.RunView({
152
- EntityName: BIZAPPS_TASK_ASSIGNMENTS_ENTITY_NAME,
153
- ExtraFilter: `PersonID = '${EscapeSQLString(personID)}'`,
154
- Fields: ['TaskID'],
155
- ResultType: 'simple',
156
- });
157
- if (!assignments.Success) {
158
- throw new Error(assignments.ErrorMessage ?? 'Failed to load task assignments.');
159
- }
160
- const assignedTaskIDs = assignments.Results.map((a) => a.TaskID).filter((id) => !!id);
161
- return { HasLinkedPerson: true, PersonID: personID, Filter: BuildPersonScopedTaskFilter(personID, assignedTaskIDs) };
177
+ /** The display name: the draft's override, or 'My Chief of Staff'. */
178
+ export function ChiefOfStaffDisplayName(draft) {
179
+ const override = draft.DisplayNameOverride.trim();
180
+ return override.length > 0 ? override : 'My Chief of Staff';
181
+ }
182
+ /** The governance summary published in the agent context. */
183
+ export function BuildGovernanceSummary(draft, hasPolicyRecord) {
184
+ return {
185
+ HasPolicyRecord: hasPolicyRecord,
186
+ DisplayName: ChiefOfStaffDisplayName(draft),
187
+ Status: draft.Status,
188
+ OnboardingStatus: draft.OnboardingStatus,
189
+ CoordinationMode: draft.CoordinationMode,
190
+ DefaultDataAccessMode: draft.DefaultDataAccessMode,
191
+ EmailChannelMode: draft.EmailChannelMode,
192
+ CalendarChannelMode: draft.CalendarChannelMode,
193
+ PhoneChannelMode: draft.PhoneChannelMode,
194
+ MessagingChannelMode: draft.MessagingChannelMode,
195
+ AllowInterAgentCoordination: draft.AllowInterAgentCoordination,
196
+ RequireApprovalForExternalComms: draft.RequireApprovalForExternalComms,
197
+ RequireApprovalForFinancials: draft.RequireApprovalForFinancials,
198
+ RequireApprovalForDestructiveActions: draft.RequireApprovalForDestructiveActions,
199
+ AutoApproveAmountThreshold: draft.AutoApproveAmountThreshold,
200
+ };
162
201
  }
163
202
  /**
164
- * ExtraFilter for `MJ_BizApps_Tasks: Tasks` limiting rows to work the given person created or is assigned to.
165
- * `assignedTaskIDs` come from `MJ_BizApps_Tasks: Task Assignments` for the same person.
203
+ * Returns `true` when an `MJ: AI Agent Requests` row represents an actionable approval or
204
+ * review request for the Chief of Staff's Pending Approvals queue, and `false` when it
205
+ * is a conversational `Information` turn created by `BaseAgent` when ending a chat turn.
166
206
  */
167
- export function BuildPersonScopedTaskFilter(personID, assignedTaskIDs) {
168
- const createdClause = `CreatedByPersonID = '${EscapeSQLString(personID)}'`;
169
- if (assignedTaskIDs.length === 0) {
170
- return createdClause;
171
- }
172
- const idList = assignedTaskIDs.map((id) => `'${EscapeSQLString(id)}'`).join(', ');
173
- return `${createdClause} OR ID IN (${idList})`;
207
+ export function IsApprovalRequest(req) {
208
+ // The RequestType virtual field carries the type name; classify on it alone.
209
+ const typeName = req.RequestType?.trim().toLowerCase() ?? '';
210
+ return typeName !== 'information';
174
211
  }
175
- export function FormatTaskMetricProgress(task) {
176
- if (task.TargetValue == null && task.CurrentValue == null) {
212
+ export function ParseOptionalDate(val) {
213
+ if (!val) {
177
214
  return null;
178
215
  }
179
- const unit = task.UnitOfMeasure ? ` ${task.UnitOfMeasure}` : '';
180
- const current = task.CurrentValue ?? task.BaselineValue ?? 0;
181
- if (task.TargetValue != null) {
182
- return `${current}${unit} / ${task.TargetValue}${unit}`;
216
+ if (val instanceof Date) {
217
+ return isNaN(val.getTime()) ? null : val;
183
218
  }
184
- return `${current}${unit}`;
219
+ const parsed = new Date(val);
220
+ return isNaN(parsed.getTime()) ? null : parsed;
185
221
  }
186
- export function CalculateChiefOfStaffMetrics(tasks, routines, requests, now = new Date()) {
187
- const subtasksByParent = GroupByUUID(tasks.filter((t) => !!t.ParentID), (t) => t.ParentID);
188
- const priorityTasks = [];
189
- for (const task of tasks) {
190
- const hasChildren = subtasksByParent.Has(task.ID);
191
- if (!task.ParentID && (IsTaskPriorityObjective(task) || hasChildren)) {
192
- priorityTasks.push(task);
193
- }
194
- }
195
- // Only qualifying objectives are shown; an empty list renders the tab's empty state rather than unrelated root tasks.
196
- const rootsToDisplay = priorityTasks;
197
- let onTrackCount = 0;
198
- let atRiskCount = 0;
199
- let offTrackCount = 0;
200
- let completedPriorityCount = 0;
201
- let confidenceSum = 0;
202
- let confidenceCount = 0;
203
- let progressSum = 0;
204
- const priorityCards = rootsToDisplay.map((root) => {
205
- const children = subtasksByParent.Get(root.ID) ?? [];
206
- const completedChildren = children.filter((c) => c.Status === 'Completed' || c.Status === 'Done' || (c.PercentComplete ?? 0) >= 100).length;
207
- const metricPercent = ComputeTaskMetricPercent(root);
208
- const rawPercent = metricPercent !== null
209
- ? metricPercent
210
- : typeof root.PercentComplete === 'number' && root.PercentComplete > 0
211
- ? root.PercentComplete
212
- : children.length > 0
213
- ? Math.round((completedChildren / children.length) * 100)
214
- : root.Status === 'Completed' || root.Status === 'Done'
215
- ? 100
216
- : 0;
217
- const effectivePercent = Math.max(0, Math.min(100, rawPercent));
218
- const effectiveHealth = NormalizeTaskHealth(root);
219
- if (effectiveHealth === 'OnTrack')
220
- onTrackCount++;
221
- else if (effectiveHealth === 'AtRisk')
222
- atRiskCount++;
223
- else if (effectiveHealth === 'OffTrack')
224
- offTrackCount++;
225
- else if (effectiveHealth === 'Completed')
226
- completedPriorityCount++;
227
- if (typeof root.ConfidenceScore === 'number' && Number.isFinite(root.ConfidenceScore)) {
228
- confidenceSum += root.ConfidenceScore;
229
- confidenceCount++;
230
- }
231
- progressSum += effectivePercent;
232
- const dueDate = ParseOptionalDate(root.DueAt);
233
- const isOverdue = dueDate !== null &&
234
- dueDate.getTime() < now.getTime() &&
235
- effectiveHealth !== 'Completed';
236
- return {
237
- Task: root,
238
- Subtasks: children,
239
- CompletedSubtaskCount: completedChildren,
240
- EffectivePercentComplete: effectivePercent,
241
- EffectiveHealth: effectiveHealth,
242
- MetricProgressLabel: FormatTaskMetricProgress(root),
243
- IsOverdue: isOverdue,
244
- };
245
- });
222
+ export function BuildChiefOfStaffScopeFilters(currentUserId, chiefOfStaffAgentId) {
223
+ const user = EscapeSQLString(currentUserId);
224
+ const agent = EscapeSQLString(chiefOfStaffAgentId);
225
+ return {
226
+ Policy: `AgentID = '${agent}' AND UserID = '${user}'`,
227
+ Routines: `UserID = '${user}' AND (RoutineType = 'AgentWake' OR TargetID = '${agent}')`,
228
+ Requests: `AgentID = '${agent}' AND RequestForUserID = '${user}' AND (RequestType IS NULL OR RequestType <> 'Information')`,
229
+ };
230
+ }
231
+ /** The core counts: pending approvals and active wakes. */
232
+ export function CalculateChiefOfStaffMetrics(routines, requests) {
246
233
  const pendingRequests = requests.filter((r) => r.Status === 'Requested' && IsApprovalRequest(r));
247
234
  const highPriorityPending = pendingRequests.filter((r) => r.Priority >= 51);
248
235
  const activeWakeRoutines = routines.filter((r) => r.Status === 'Active');
@@ -253,41 +240,20 @@ export function CalculateChiefOfStaffMetrics(tasks, routines, requests, now = ne
253
240
  nextScheduledWakeAt = nextRun;
254
241
  }
255
242
  }
256
- const totalSubtasks = tasks.filter((t) => !!t.ParentID).length;
257
243
  return {
258
- TotalTaskCount: tasks.length,
259
- PriorityObjectiveCount: priorityCards.length,
260
- SubtaskCount: totalSubtasks,
261
- OnTrackCount: onTrackCount,
262
- AtRiskCount: atRiskCount,
263
- OffTrackCount: offTrackCount,
264
- CompletedPriorityCount: completedPriorityCount,
265
- AverageConfidenceScore: confidenceCount > 0 ? Math.round((confidenceSum / confidenceCount) * 10) / 10 : null,
266
- AveragePriorityProgress: priorityCards.length > 0 ? Math.round(progressSum / priorityCards.length) : 0,
267
244
  PendingApprovalCount: pendingRequests.length,
268
245
  HighPriorityPendingCount: highPriorityPending.length,
269
246
  ActiveWakeRoutineCount: activeWakeRoutines.length,
270
247
  NextScheduledWakeAt: nextScheduledWakeAt,
271
- PriorityCards: priorityCards,
272
248
  };
273
249
  }
274
250
  export function BuildChiefOfStaffAgentContext(input) {
275
- const priorityNames = input.Metrics.PriorityCards.map((c) => c.Task.Name).filter((n) => !!n);
276
- const boundedPriorityNames = BoundNameList(priorityNames, AGENT_CONTEXT_NAME_LIST_CAP);
277
251
  const routineNames = input.Routines.map((r) => `${r.Name} (${r.Status})`).filter((n) => !!n);
278
252
  const boundedRoutineNames = BoundNameList(routineNames, AGENT_CONTEXT_NAME_LIST_CAP);
279
- const context = {
280
- Surface: 'ChiefOfStaffDashboard',
281
- ActiveTab: input.ActiveTab,
253
+ return {
254
+ Surface: 'ChiefOfStaff',
255
+ Page: input.Page,
282
256
  SearchText: input.SearchText,
283
- HealthFilter: input.HealthFilter,
284
- PriorityObjectiveCount: input.Metrics.PriorityObjectiveCount,
285
- SubtaskCount: input.Metrics.SubtaskCount,
286
- OnTrackCount: input.Metrics.OnTrackCount,
287
- AtRiskCount: input.Metrics.AtRiskCount,
288
- OffTrackCount: input.Metrics.OffTrackCount,
289
- CompletedPriorityCount: input.Metrics.CompletedPriorityCount,
290
- AveragePriorityProgressPercent: input.Metrics.AveragePriorityProgress,
291
257
  PendingApprovalCount: input.Metrics.PendingApprovalCount,
292
258
  HighPriorityPendingCount: input.Metrics.HighPriorityPendingCount,
293
259
  ActiveWakeRoutineCount: input.Metrics.ActiveWakeRoutineCount,
@@ -310,65 +276,14 @@ export function BuildChiefOfStaffAgentContext(input) {
310
276
  RequireApprovalForDestructiveActions: input.Governance.RequireApprovalForDestructiveActions,
311
277
  AutoApproveAmountThreshold: input.Governance.AutoApproveAmountThreshold,
312
278
  },
313
- VisiblePriorityObjectiveNames: boundedPriorityNames,
314
279
  VisibleWakeRoutineNames: boundedRoutineNames,
315
280
  };
316
- if (priorityNames.length > boundedPriorityNames.length) {
317
- context['VisiblePriorityObjectiveNamesTruncated'] = true;
318
- context['VisiblePriorityObjectiveNamesTotal'] = priorityNames.length;
319
- }
320
- return context;
321
- }
322
- export function ValidateChiefOfStaffTabParam(raw) {
323
- return ValidateEnumParam(raw, VALID_CHIEF_OF_STAFF_TABS, 'tab');
324
281
  }
325
- export function ValidateHealthFilterParam(raw) {
326
- return ValidateEnumParam(raw, VALID_HEALTH_FILTERS, 'health');
282
+ /** Validates a page parameter against the Chief of Staff application's own pages. */
283
+ export function ValidateChiefOfStaffPageParam(raw) {
284
+ return ValidateEnumParam(raw, CHIEF_OF_STAFF_PAGES, 'page');
327
285
  }
328
286
  export function ValidateSearchQueryParam(raw) {
329
287
  return ValidateStringParam(raw, 'query');
330
288
  }
331
- export function ResolvePriorityObjectiveByIDOrName(cards, rawRef) {
332
- if (typeof rawRef !== 'string' || rawRef.trim().length === 0) {
333
- return {
334
- ok: false,
335
- error: `Provide a priority objective ID or name. ${availableObjectiveNames(cards)}`,
336
- };
337
- }
338
- const ref = rawRef.trim();
339
- const byId = cards.find((c) => UUIDsEqual(c.Task.ID, ref));
340
- if (byId) {
341
- return { ok: true, value: byId };
342
- }
343
- const byName = cards.find((c) => c.Task.Name.trim().toLowerCase() === ref.toLowerCase());
344
- if (byName) {
345
- return { ok: true, value: byName };
346
- }
347
- const partial = cards.filter((c) => c.Task.Name.toLowerCase().includes(ref.toLowerCase()));
348
- if (partial.length === 1) {
349
- return { ok: true, value: partial[0] };
350
- }
351
- if (partial.length > 1) {
352
- const names = partial
353
- .slice(0, AGENT_CONTEXT_NAME_LIST_CAP)
354
- .map((c) => c.Task.Name)
355
- .join(', ');
356
- return {
357
- ok: false,
358
- error: `'${ref}' matches multiple priority objectives: ${names}. Be more specific.`,
359
- };
360
- }
361
- return {
362
- ok: false,
363
- error: `No priority objective matches '${ref}'. ${availableObjectiveNames(cards)}`,
364
- };
365
- }
366
- function availableObjectiveNames(cards) {
367
- if (cards.length === 0) {
368
- return 'There are no priority objectives loaded.';
369
- }
370
- const names = cards.slice(0, AGENT_CONTEXT_NAME_LIST_CAP).map((c) => c.Task.Name);
371
- const suffix = cards.length > AGENT_CONTEXT_NAME_LIST_CAP ? ', …' : '';
372
- return `Available priority objectives: ${names.join(', ')}${suffix}`;
373
- }
374
289
  //# sourceMappingURL=chief-of-staff-agent-context.js.map