@memberjunction/ng-dashboards 6.2.0-edge.6 → 6.2.0-edge.7
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.
- package/README.md +23 -16
- package/dist/AI/components/analytics/agent-runs/agent-run-analysis.component.js +2 -2
- package/dist/AI/components/analytics/agent-runs/agent-run-analysis.component.js.map +1 -1
- package/dist/AI/components/analytics/realtime/realtime-management.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/realtime/realtime-management.component.js +3 -1
- package/dist/AI/components/analytics/realtime/realtime-management.component.js.map +1 -1
- package/dist/AI/components/analytics/realtime/realtime-overview.component.d.ts +1 -1
- package/dist/AI/components/analytics/realtime/realtime-overview.component.js +3 -3
- package/dist/AI/components/analytics/realtime/realtime-overview.component.js.map +1 -1
- package/dist/AI/components/analytics/realtime/realtime-session-data.d.ts +6 -4
- package/dist/AI/components/analytics/realtime/realtime-session-data.d.ts.map +1 -1
- package/dist/AI/components/analytics/realtime/realtime-session-data.js +8 -2
- package/dist/AI/components/analytics/realtime/realtime-session-data.js.map +1 -1
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +6 -6
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -1
- package/dist/AI/components/autotagging/components/classify-item-grid.component.js +1 -1
- package/dist/AI/components/autotagging/components/classify-item-grid.component.js.map +1 -1
- package/dist/AI/components/autotagging/components/classify-org-context-editor.component.d.ts.map +1 -1
- package/dist/AI/components/autotagging/components/classify-org-context-editor.component.js +1 -0
- package/dist/AI/components/autotagging/components/classify-org-context-editor.component.js.map +1 -1
- package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.d.ts.map +1 -1
- package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.js +1 -0
- package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.js.map +1 -1
- package/dist/AI/components/autotagging/tabs/sources-tab.component.d.ts.map +1 -1
- package/dist/AI/components/autotagging/tabs/sources-tab.component.js +1 -0
- package/dist/AI/components/autotagging/tabs/sources-tab.component.js.map +1 -1
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts.map +1 -1
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js +1 -0
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -1
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js +2 -2
- package/dist/AI/components/tags/tags-resource.component.d.ts.map +1 -1
- package/dist/AI/components/tags/tags-resource.component.js +3 -2
- package/dist/AI/components/tags/tags-resource.component.js.map +1 -1
- package/dist/AI/components/vectors/vector-management-resource.component.d.ts.map +1 -1
- package/dist/AI/components/vectors/vector-management-resource.component.js +12 -6
- package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
- package/dist/AI/services/ai-instrumentation.service.d.ts.map +1 -1
- package/dist/AI/services/ai-instrumentation.service.js +4 -2
- package/dist/AI/services/ai-instrumentation.service.js.map +1 -1
- package/dist/Actions/action-result-code.d.ts +80 -0
- package/dist/Actions/action-result-code.d.ts.map +1 -0
- package/dist/Actions/action-result-code.js +163 -0
- package/dist/Actions/action-result-code.js.map +1 -0
- package/dist/Actions/components/actions-overview.component.d.ts +8 -0
- package/dist/Actions/components/actions-overview.component.d.ts.map +1 -1
- package/dist/Actions/components/actions-overview.component.js +12 -9
- package/dist/Actions/components/actions-overview.component.js.map +1 -1
- package/dist/Actions/components/execution-monitoring.component.d.ts +29 -9
- package/dist/Actions/components/execution-monitoring.component.d.ts.map +1 -1
- package/dist/Actions/components/execution-monitoring.component.js +65 -42
- package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-card.component.d.ts.map +1 -1
- package/dist/Actions/components/explorer/action-card.component.js +5 -4
- package/dist/Actions/components/explorer/action-card.component.js.map +1 -1
- package/dist/ChiefOfStaff/chief-of-staff-agent-context.d.ts +92 -130
- package/dist/ChiefOfStaff/chief-of-staff-agent-context.d.ts.map +1 -1
- package/dist/ChiefOfStaff/chief-of-staff-agent-context.js +189 -274
- package/dist/ChiefOfStaff/chief-of-staff-agent-context.js.map +1 -1
- package/dist/ChiefOfStaff/chief-of-staff-approvals.component.d.ts +29 -0
- package/dist/ChiefOfStaff/chief-of-staff-approvals.component.d.ts.map +1 -0
- package/dist/ChiefOfStaff/chief-of-staff-approvals.component.js +666 -0
- package/dist/ChiefOfStaff/chief-of-staff-approvals.component.js.map +1 -0
- package/dist/ChiefOfStaff/chief-of-staff-governance.component.d.ts +56 -0
- package/dist/ChiefOfStaff/chief-of-staff-governance.component.d.ts.map +1 -0
- package/dist/ChiefOfStaff/chief-of-staff-governance.component.js +515 -0
- package/dist/ChiefOfStaff/chief-of-staff-governance.component.js.map +1 -0
- package/dist/ChiefOfStaff/chief-of-staff-live-refresh.d.ts +14 -0
- package/dist/ChiefOfStaff/chief-of-staff-live-refresh.d.ts.map +1 -0
- package/dist/ChiefOfStaff/chief-of-staff-live-refresh.js +39 -0
- package/dist/ChiefOfStaff/chief-of-staff-live-refresh.js.map +1 -0
- package/dist/ChiefOfStaff/chief-of-staff-overview.component.d.ts +17 -0
- package/dist/ChiefOfStaff/chief-of-staff-overview.component.d.ts.map +1 -0
- package/dist/ChiefOfStaff/chief-of-staff-overview.component.js +485 -0
- package/dist/ChiefOfStaff/chief-of-staff-overview.component.js.map +1 -0
- package/dist/ChiefOfStaff/chief-of-staff-page-base.d.ts +139 -0
- package/dist/ChiefOfStaff/chief-of-staff-page-base.d.ts.map +1 -0
- package/dist/ChiefOfStaff/chief-of-staff-page-base.js +602 -0
- package/dist/ChiefOfStaff/chief-of-staff-page-base.js.map +1 -0
- package/dist/ChiefOfStaff/index.d.ts +4 -1
- package/dist/ChiefOfStaff/index.d.ts.map +1 -1
- package/dist/ChiefOfStaff/index.js +4 -1
- package/dist/ChiefOfStaff/index.js.map +1 -1
- package/dist/Communication/communication-monitor-resource.component.js +3 -3
- package/dist/Communication/communication-monitor-resource.component.js.map +1 -1
- package/dist/Communication/communication-runs-resource.component.js +3 -3
- package/dist/Communication/communication-runs-resource.component.js.map +1 -1
- package/dist/ComponentStudio/component-studio-dashboard.component.d.ts.map +1 -1
- package/dist/ComponentStudio/component-studio-dashboard.component.js +1 -0
- package/dist/ComponentStudio/component-studio-dashboard.component.js.map +1 -1
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.js +2 -1
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/services/component-version.service.d.ts.map +1 -1
- package/dist/ComponentStudio/services/component-version.service.js +3 -0
- package/dist/ComponentStudio/services/component-version.service.js.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +21 -2
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.js +32 -5
- package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
- package/dist/DevTools/graphql-console.component.js +2 -2
- package/dist/DevTools/lazy-module-status.component.js +2 -2
- package/dist/FormBuilder/form-builder-resource.component.d.ts.map +1 -1
- package/dist/FormBuilder/form-builder-resource.component.js +5 -0
- package/dist/FormBuilder/form-builder-resource.component.js.map +1 -1
- package/dist/Integration/components/connections/connections.component.js +2 -2
- package/dist/Integration/services/integration-data.service.d.ts +1 -1
- package/dist/Integration/services/integration-data.service.d.ts.map +1 -1
- package/dist/Integration/services/integration-data.service.js +4 -3
- package/dist/Integration/services/integration-data.service.js.map +1 -1
- package/dist/Lists/components/lists-browse-resource.component.js +1 -1
- package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-my-lists-resource.component.js +1 -1
- package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
- package/dist/LoginStudio/login-studio-resource.component.d.ts.map +1 -1
- package/dist/LoginStudio/login-studio-resource.component.js +1 -0
- package/dist/LoginStudio/login-studio-resource.component.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-experiments.component.d.ts.map +1 -1
- package/dist/PredictiveStudio/components/ps-experiments.component.js +1 -0
- package/dist/PredictiveStudio/components/ps-experiments.component.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-pipeline-wizard.component.js +2 -2
- package/dist/PredictiveStudio/components/ps-predictions-grid.component.d.ts.map +1 -1
- package/dist/PredictiveStudio/components/ps-predictions-grid.component.js +3 -0
- package/dist/PredictiveStudio/components/ps-predictions-grid.component.js.map +1 -1
- package/dist/PredictiveStudio/engine/predictive-studio.engine.d.ts.map +1 -1
- package/dist/PredictiveStudio/engine/predictive-studio.engine.js +1 -0
- package/dist/PredictiveStudio/engine/predictive-studio.engine.js.map +1 -1
- package/dist/PredictiveStudio/resources/ps-predictions-resource.component.d.ts.map +1 -1
- package/dist/PredictiveStudio/resources/ps-predictions-resource.component.js +1 -0
- package/dist/PredictiveStudio/resources/ps-predictions-resource.component.js.map +1 -1
- package/dist/QueryBrowser/query-browser-resource.component.d.ts +26 -0
- package/dist/QueryBrowser/query-browser-resource.component.d.ts.map +1 -1
- package/dist/QueryBrowser/query-browser-resource.component.js +375 -252
- package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
- package/dist/UserRoutines/user-routines-resource.component.d.ts +8 -1
- package/dist/UserRoutines/user-routines-resource.component.d.ts.map +1 -1
- package/dist/UserRoutines/user-routines-resource.component.js +22 -4
- package/dist/UserRoutines/user-routines-resource.component.js.map +1 -1
- package/dist/VersionHistory/components/diff-resource.component.d.ts.map +1 -1
- package/dist/VersionHistory/components/diff-resource.component.js +1 -0
- package/dist/VersionHistory/components/diff-resource.component.js.map +1 -1
- package/dist/VideoStudio/components/vs-archetype-editor.component.d.ts +162 -0
- package/dist/VideoStudio/components/vs-archetype-editor.component.d.ts.map +1 -0
- package/dist/VideoStudio/components/vs-archetype-editor.component.js +1105 -0
- package/dist/VideoStudio/components/vs-archetype-editor.component.js.map +1 -0
- package/dist/VideoStudio/components/vs-audio-options.component.d.ts +27 -0
- package/dist/VideoStudio/components/vs-audio-options.component.d.ts.map +1 -0
- package/dist/VideoStudio/components/vs-audio-options.component.js +119 -0
- package/dist/VideoStudio/components/vs-audio-options.component.js.map +1 -0
- package/dist/VideoStudio/components/vs-copilot-panel.component.d.ts +105 -0
- package/dist/VideoStudio/components/vs-copilot-panel.component.d.ts.map +1 -0
- package/dist/VideoStudio/components/vs-copilot-panel.component.js +560 -0
- package/dist/VideoStudio/components/vs-copilot-panel.component.js.map +1 -0
- package/dist/VideoStudio/components/vs-production-brief.component.d.ts +163 -0
- package/dist/VideoStudio/components/vs-production-brief.component.d.ts.map +1 -0
- package/dist/VideoStudio/components/vs-production-brief.component.js +1054 -0
- package/dist/VideoStudio/components/vs-production-brief.component.js.map +1 -0
- package/dist/VideoStudio/components/vs-setup-health-card.component.d.ts +43 -0
- package/dist/VideoStudio/components/vs-setup-health-card.component.d.ts.map +1 -0
- package/dist/VideoStudio/components/vs-setup-health-card.component.js +412 -0
- package/dist/VideoStudio/components/vs-setup-health-card.component.js.map +1 -0
- package/dist/VideoStudio/components/vs-studio-slide-in.component.d.ts +73 -0
- package/dist/VideoStudio/components/vs-studio-slide-in.component.d.ts.map +1 -0
- package/dist/VideoStudio/components/vs-studio-slide-in.component.js +271 -0
- package/dist/VideoStudio/components/vs-studio-slide-in.component.js.map +1 -0
- package/dist/VideoStudio/index.d.ts +12 -0
- package/dist/VideoStudio/index.d.ts.map +1 -0
- package/dist/VideoStudio/index.js +12 -0
- package/dist/VideoStudio/index.js.map +1 -0
- package/dist/VideoStudio/resources/video-studio-archetypes-resource.component.d.ts +118 -0
- package/dist/VideoStudio/resources/video-studio-archetypes-resource.component.d.ts.map +1 -0
- package/dist/VideoStudio/resources/video-studio-archetypes-resource.component.js +964 -0
- package/dist/VideoStudio/resources/video-studio-archetypes-resource.component.js.map +1 -0
- package/dist/VideoStudio/resources/video-studio-brand-kits-resource.component.d.ts +70 -0
- package/dist/VideoStudio/resources/video-studio-brand-kits-resource.component.d.ts.map +1 -0
- package/dist/VideoStudio/resources/video-studio-brand-kits-resource.component.js +600 -0
- package/dist/VideoStudio/resources/video-studio-brand-kits-resource.component.js.map +1 -0
- package/dist/VideoStudio/resources/video-studio-productions-resource.component.d.ts +182 -0
- package/dist/VideoStudio/resources/video-studio-productions-resource.component.d.ts.map +1 -0
- package/dist/VideoStudio/resources/video-studio-productions-resource.component.js +1481 -0
- package/dist/VideoStudio/resources/video-studio-productions-resource.component.js.map +1 -0
- package/dist/VideoStudio/services/vs-studio-slide-in-state.service.d.ts +102 -0
- package/dist/VideoStudio/services/vs-studio-slide-in-state.service.d.ts.map +1 -0
- package/dist/VideoStudio/services/vs-studio-slide-in-state.service.js +240 -0
- package/dist/VideoStudio/services/vs-studio-slide-in-state.service.js.map +1 -0
- package/dist/VideoStudio/video-studio-agent-context.d.ts +495 -0
- package/dist/VideoStudio/video-studio-agent-context.d.ts.map +1 -0
- package/dist/VideoStudio/video-studio-agent-context.js +992 -0
- package/dist/VideoStudio/video-studio-agent-context.js.map +1 -0
- package/dist/ai-dashboards.module.d.ts +25 -22
- package/dist/ai-dashboards.module.d.ts.map +1 -1
- package/dist/ai-dashboards.module.js +23 -7
- package/dist/ai-dashboards.module.js.map +1 -1
- package/dist/module.d.ts +13 -12
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +7 -0
- package/dist/module.js.map +1 -1
- package/dist/public-api.d.ts +7 -1
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +9 -2
- package/dist/public-api.js.map +1 -1
- package/dist/shared/action-scheduled-job.d.ts.map +1 -1
- package/dist/shared/action-scheduled-job.js +2 -0
- package/dist/shared/action-scheduled-job.js.map +1 -1
- package/dist/video-studio-dashboards.module.d.ts +40 -0
- package/dist/video-studio-dashboards.module.d.ts.map +1 -0
- package/dist/video-studio-dashboards.module.js +159 -0
- package/dist/video-studio-dashboards.module.js.map +1 -0
- package/package.json +77 -71
- package/dist/ChiefOfStaff/chief-of-staff-dashboard.component.d.ts +0 -195
- package/dist/ChiefOfStaff/chief-of-staff-dashboard.component.d.ts.map +0 -1
- package/dist/ChiefOfStaff/chief-of-staff-dashboard.component.js +0 -2910
- 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
|
|
3
|
-
* agent context
|
|
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
|
|
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,
|
|
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 {
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
'
|
|
34
|
-
'
|
|
35
|
-
'
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* is
|
|
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
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
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
|
|
65
|
-
|
|
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
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
return
|
|
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
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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
|
-
|
|
84
|
-
return
|
|
101
|
+
catch {
|
|
102
|
+
return null;
|
|
85
103
|
}
|
|
86
|
-
|
|
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
|
|
98
|
-
const
|
|
99
|
-
|
|
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
|
|
103
|
-
const
|
|
104
|
-
|
|
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
|
-
|
|
107
|
-
|
|
108
|
-
const
|
|
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
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
-
/**
|
|
116
|
-
export
|
|
117
|
-
|
|
118
|
-
|
|
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
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
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
|
-
*
|
|
165
|
-
*
|
|
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
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
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
|
|
176
|
-
if (
|
|
212
|
+
export function ParseOptionalDate(val) {
|
|
213
|
+
if (!val) {
|
|
177
214
|
return null;
|
|
178
215
|
}
|
|
179
|
-
|
|
180
|
-
|
|
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
|
-
|
|
219
|
+
const parsed = new Date(val);
|
|
220
|
+
return isNaN(parsed.getTime()) ? null : parsed;
|
|
185
221
|
}
|
|
186
|
-
export function
|
|
187
|
-
const
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
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
|
-
|
|
280
|
-
Surface: '
|
|
281
|
-
|
|
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
|
-
|
|
326
|
-
|
|
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
|