@zeniai/web-components 4.3.60 → 4.3.62-beta0ND

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 (26) hide show
  1. package/dist/{SessionTimeoutPopup-DOvBM1F6.cjs → SessionTimeoutPopup-CG3zQGql.cjs} +17283 -16427
  2. package/dist/{SessionTimeoutPopup-BmGGI1m1.js → SessionTimeoutPopup-G4OLmSKh.js} +90386 -88118
  3. package/dist/appLocale.d.ts +146 -0
  4. package/dist/cockpit.cjs.js +2 -2
  5. package/dist/cockpit.esm.js +79 -76
  6. package/dist/components/aiCfo/AiCfoPage.d.ts +68 -0
  7. package/dist/components/aiCfo/components/AiCfoCombobox.d.ts +24 -0
  8. package/dist/components/aiCfo/components/AiCfoRoutineDetail.d.ts +29 -0
  9. package/dist/components/aiCfo/components/AiCfoRoutineEditor.d.ts +46 -0
  10. package/dist/components/aiCfo/components/AiCfoRoutineRunsPanel.d.ts +42 -0
  11. package/dist/components/aiCfo/components/AiCfoRoutinesBrowser.d.ts +41 -0
  12. package/dist/components/aiCfo/components/AiCfoScrollArea.d.ts +11 -0
  13. package/dist/components/aiCfo/components/helpers/aiCfoRoutines.d.ts +197 -0
  14. package/dist/components/aiCfo/stories/hooks/useAiCfoStreamingState.d.ts +1 -0
  15. package/dist/components/appDrawerContent/AiCfoMenuContent.d.ts +29 -1
  16. package/dist/components/appDrawerContent/AppDrawerContent.d.ts +8 -1
  17. package/dist/components/appDrawerContent/MenuButton.d.ts +4 -3
  18. package/dist/components/appDrawerContent/MenuList.d.ts +8 -1
  19. package/dist/components/appDrawerContent/appDrawerContent.helpers.d.ts +5 -0
  20. package/dist/components/settingsPage/Notifications/NotificationSettingsPage.d.ts +9 -2
  21. package/dist/components/settingsPage/Notifications/{taskNotifications/TaskNotificationsSection.d.ts → notificationControls/NotificationControlsSection.d.ts} +4 -2
  22. package/dist/index.cjs.js +1 -1
  23. package/dist/index.d.ts +2 -0
  24. package/dist/index.esm.js +130 -127
  25. package/dist/strings/strings.d.ts +146 -0
  26. package/package.json +5 -5
@@ -0,0 +1,24 @@
1
+ import { default as React } from 'react';
2
+ /**
3
+ * A type-to-filter picker.
4
+ *
5
+ * Replaces `<input list>` + `<datalist>`: the native control cannot be styled,
6
+ * renders in the OS's own popup rather than the app's, and positions itself
7
+ * over whatever sits below the field. Everything here is app chrome.
8
+ *
9
+ * The component owns only the open/highlight state. The typed text lives with
10
+ * the caller, which is what lets a caller resolve it to an id (or reject it) on
11
+ * its own terms — a picker that also owned the value would have to know what
12
+ * the value meant.
13
+ */
14
+ export interface AiCfoComboboxProps {
15
+ id: string;
16
+ /** Rendered as-is; already filtered options are not expected. */
17
+ options: string[];
18
+ query: string;
19
+ placeholder?: string;
20
+ onQueryChange: (query: string) => void;
21
+ onBlur?: () => void;
22
+ }
23
+ declare const AiCfoCombobox: React.FC<AiCfoComboboxProps>;
24
+ export default AiCfoCombobox;
@@ -0,0 +1,29 @@
1
+ import { default as React } from 'react';
2
+ import { Routine, RoutineRun, SchedulableSkill } from './helpers/aiCfoRoutines';
3
+ export interface AiCfoRoutineDetailProps {
4
+ historyError: boolean;
5
+ historyLoading: boolean;
6
+ /** The routine being shown. */
7
+ routine: Routine;
8
+ /** True while a Run-now is in flight for this routine. */
9
+ running: boolean;
10
+ runs: RoutineRun[];
11
+ /** Used to name the skill this runs, rather than showing a raw macro id. */
12
+ skills: SchedulableSkill[];
13
+ /**
14
+ * What this routine will run, if the host has loaded it.
15
+ *
16
+ * Not on `Routine`: the list endpoint returns schedules, and the text lives
17
+ * behind the skill-detail fetch. Absent simply hides the card rather than
18
+ * showing an empty one.
19
+ */
20
+ instructions?: string;
21
+ onBack: () => void;
22
+ onDelete: () => void;
23
+ onEdit: () => void;
24
+ onOpenRun: (run: RoutineRun) => void;
25
+ onRun: () => void;
26
+ onSetEnabled: (enabled: boolean) => void;
27
+ }
28
+ declare const AiCfoRoutineDetail: React.FC<AiCfoRoutineDetailProps>;
29
+ export default AiCfoRoutineDetail;
@@ -0,0 +1,46 @@
1
+ import { default as React } from 'react';
2
+ import { Routine, RoutineEditorDraft, SchedulableSkill } from './helpers/aiCfoRoutines';
3
+ export interface AiCfoRoutineEditorProps {
4
+ editing: Routine | undefined;
5
+ saveError: boolean;
6
+ saving: boolean;
7
+ /**
8
+ * Skills this user can schedule. Empty hides the skill option entirely rather
9
+ * than offering a picker with nothing in it — a new user's only real choice
10
+ * is a one-off, and an empty dropdown reads as something being broken.
11
+ */
12
+ skills: SchedulableSkill[];
13
+ /**
14
+ * The routine being edited. Absent means this is a new one.
15
+ *
16
+ * The host MUST mount this with `key={editing?.scheduleId ?? "new"}`. Every
17
+ * field seeds from `editing` once, so without the key, opening B after
18
+ * cancelling A shows A's schedule and saves it onto B.
19
+ */
20
+ /**
21
+ * Instructions to start a NEW routine from, from the list page's composer.
22
+ *
23
+ * Also switches the source to the one-off branch: someone who described what
24
+ * they want has already said it is not a saved skill.
25
+ */
26
+ draftPrompt?: string;
27
+ /**
28
+ * The instructions behind the skill last requested via `onLoadSkillInstructions`.
29
+ *
30
+ * Carries its own `macroId` because this is the same detail slice the skills
31
+ * browser fills: without the check, opening a skill there and then opening
32
+ * this editor would seed the box from whatever that slice happened to hold.
33
+ */
34
+ skillInstructions?: {
35
+ instructions: string;
36
+ macroId: string;
37
+ };
38
+ skillInstructionsError?: boolean;
39
+ skillInstructionsLoading?: boolean;
40
+ onCancel: () => void;
41
+ onSave: (draft: RoutineEditorDraft) => void;
42
+ /** Absent withholds the "start from a skill" picker rather than offering one that cannot load. */
43
+ onLoadSkillInstructions?: (macroId: string) => void;
44
+ }
45
+ declare const AiCfoRoutineEditor: React.FC<AiCfoRoutineEditorProps>;
46
+ export default AiCfoRoutineEditor;
@@ -0,0 +1,42 @@
1
+ import { default as React } from 'react';
2
+ import { RoutineRun } from './helpers/aiCfoRoutines';
3
+ /**
4
+ * The routine's past runs, beside its conversation.
5
+ *
6
+ * A routine's runs all append to ONE thread, so scrolling is the only way to
7
+ * find the run you came for. This lists them, newest first, and says which are
8
+ * unread — the same question the rail badge raises, answered where the answers
9
+ * actually are.
10
+ */
11
+ export interface AiCfoRoutineRunsPanelProps {
12
+ error: boolean;
13
+ /**
14
+ * True while the runs are being fetched OR before the fetch has begun.
15
+ *
16
+ * Both, because an empty list with nothing in flight rendered "No runs yet."
17
+ * on a routine that had runs — the panel answered before it had asked.
18
+ */
19
+ loading: boolean;
20
+ routineName: string;
21
+ runs: RoutineRun[];
22
+ /** The cadence sentence, so the panel says what this thing does unprompted. */
23
+ schedule: string;
24
+ /** The routine's timezone, so run times read as the routine's own. */
25
+ tzName: string | null;
26
+ /** Runs newer than this many are marked unread. 0 means none are. */
27
+ unreadCount: number;
28
+ /**
29
+ * The conversation currently on screen, so its run reads as the one being
30
+ * looked at. Null on the routine's own page, where no run is open.
31
+ */
32
+ openSessionId?: string | null;
33
+ /** The skill this runs, when it runs one. Absent for a written prompt. */
34
+ skillName?: string;
35
+ onOpenRun: (run: RoutineRun) => void;
36
+ /** Opens the routine's own page, where it is configured and edited. */
37
+ onOpenRoutine?: () => void;
38
+ /** Absent renders the skill as text rather than a link that goes nowhere. */
39
+ onOpenSkill?: () => void;
40
+ }
41
+ declare const AiCfoRoutineRunsPanel: React.FC<AiCfoRoutineRunsPanelProps>;
42
+ export default AiCfoRoutineRunsPanel;
@@ -0,0 +1,41 @@
1
+ import { default as React } from 'react';
2
+ import { Routine } from './helpers/aiCfoRoutines';
3
+ export interface AiCfoRoutinesBrowserProps {
4
+ /** False withholds "New routine" — the server states the cap, not the client. */
5
+ canCreate: boolean;
6
+ listError: boolean;
7
+ /**
8
+ * The list is being fetched. Distinct from "no routines": opening the tab
9
+ * triggers the fetch, so without this an empty list reads as "you have none"
10
+ * for the whole round trip.
11
+ */
12
+ listLoading: boolean;
13
+ /** The server's cap, for the message when it is reached. */
14
+ maxRoutines: number;
15
+ routines: Routine[];
16
+ /**
17
+ * Open one routine.
18
+ *
19
+ * Everything a routine can DO — run, pause, edit, delete, its run history —
20
+ * lives on that page. The list stayed readable while it had two controls; at
21
+ * six it was a wall of identical text links with no hierarchy.
22
+ */
23
+ /**
24
+ * Required: every row renders as a button with a chevron, so a list
25
+ * mounted without this looks navigable and silently does nothing — and
26
+ * opening a routine is the only thing this list does.
27
+ */
28
+ onOpen: (routine: Routine) => void;
29
+ /** Absent withholds the control rather than rendering one the API refuses. */
30
+ onCreate?: () => void;
31
+ /**
32
+ * Start a routine from a description.
33
+ *
34
+ * Opens the editor with the text as the instructions — it does NOT infer a
35
+ * schedule from the sentence. The cadence is one control away and getting it
36
+ * wrong silently is worse than asking.
37
+ */
38
+ onDraft?: (instructions: string) => void;
39
+ }
40
+ declare const AiCfoRoutinesBrowser: React.FC<AiCfoRoutinesBrowserProps>;
41
+ export default AiCfoRoutinesBrowser;
@@ -1,5 +1,16 @@
1
1
  /** Shared height for the scroll area fade gradient. */
2
2
  export declare const AI_CFO_SCROLL_GRADIENT_HEIGHT: string;
3
+ /**
4
+ * The conversation and whatever sits beside it.
5
+ *
6
+ * A row so a side panel takes width from the chat rather than overlaying it —
7
+ * an overlay would cover the answer the panel exists to help you find. Takes
8
+ * over the height AiCfoScrollWrapper used to claim directly, and passes it on.
9
+ */
10
+ export declare const ChatWithPanel: import('@emotion/styled').StyledComponent<{
11
+ theme?: import('@emotion/react').Theme;
12
+ as?: React.ElementType;
13
+ }, import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
3
14
  export declare const AiCfoScrollWrapper: import('@emotion/styled').StyledComponent<{
4
15
  theme?: import('@emotion/react').Theme;
5
16
  as?: React.ElementType;
@@ -0,0 +1,197 @@
1
+ /**
2
+ * Imported from `@zeniai/client-epic-state` once #3360 publishes. Declared here
3
+ * meanwhile because that import does not fail today — it degrades silently, so
4
+ * every guarantee below would be unchecked.
5
+ */
6
+ export type RoutineRecurrence = "daily" | "weekly" | "monthly";
7
+ export type RoutineStatus = "succeeded" | "failed" | "timeout";
8
+ export interface Routine {
9
+ consecutiveFailures: number;
10
+ dayOfMonth: number | null;
11
+ enabled: boolean;
12
+ hour: number;
13
+ isAdHoc: boolean;
14
+ lastRunAt: string | null;
15
+ lastStatus: RoutineStatus | null;
16
+ /** '' when the skill behind this routine was deleted. */
17
+ macroId: string;
18
+ minute: number;
19
+ name: string;
20
+ nextRunAt: string | null;
21
+ pinnedVersion: number | null;
22
+ /** Null when this client does not recognise the server's cadence. */
23
+ recurrence: RoutineRecurrence | null;
24
+ scheduleId: string;
25
+ sessionId: string | null;
26
+ tzName: string | null;
27
+ /** Runs whose answer has not been opened. Drives the "N new" badge. */
28
+ unreadRuns: number;
29
+ weekday: number | null;
30
+ }
31
+ /** Mirrors `RoutineDraft`; imported from the package once #3360 publishes. */
32
+ export interface RoutineEditorDraft {
33
+ hour: number;
34
+ minute: number;
35
+ name: string;
36
+ recurrence: RoutineRecurrence;
37
+ tzName: string;
38
+ dayOfMonth?: number;
39
+ macroId?: string;
40
+ prompt?: string;
41
+ weekday?: number;
42
+ }
43
+ /**
44
+ * Just the cadence fields, so the editor can describe a draft it has not saved
45
+ * yet. `Routine` satisfies this structurally, which keeps one implementation of
46
+ * the sentence behind both the list row and the editor's summary line.
47
+ */
48
+ export interface RoutineSchedule {
49
+ dayOfMonth: number | null;
50
+ hour: number;
51
+ minute: number;
52
+ recurrence: RoutineRecurrence | null;
53
+ weekday: number | null;
54
+ }
55
+ /** Mirrors `RoutineRunStatus`; imported from the package once #3360 publishes. */
56
+ export type RoutineRunStatus = "claimed" | "running" | "succeeded" | "failed" | "timeout";
57
+ /** Mirrors `RoutineRun`; imported from the package once #3360 publishes. */
58
+ export interface RoutineRun {
59
+ attempt: number;
60
+ /** Why it failed. The only place a failed run explains itself. */
61
+ error: string | null;
62
+ finishedAt: string | null;
63
+ isManual: boolean;
64
+ /** The message this run produced. Null opens the thread instead. */
65
+ questionAnswerId: string | null;
66
+ runId: string;
67
+ scheduledFor: string | null;
68
+ /**
69
+ * This run's own conversation.
70
+ *
71
+ * Each run gets one, so a follow-up about one report stays with that report.
72
+ * Null on runs from before that was true, and on a run that has not started
73
+ * — neither has a thread to open.
74
+ */
75
+ sessionId: string | null;
76
+ startedAt: string | null;
77
+ /** Null when this client does not recognise the server's status. */
78
+ status: RoutineRunStatus | null;
79
+ }
80
+ /** Whether a run is still going, and so has no outcome to report yet. */
81
+ export declare const isRunInFlight: (run: RoutineRun) => boolean;
82
+ /**
83
+ * When a run happened, in the routine's own timezone.
84
+ *
85
+ * `finishedAt` first, then `startedAt`, then the occurrence it belongs to: a
86
+ * run in flight has no finish, and a claimed one has no start, but every run
87
+ * has something honest to show.
88
+ */
89
+ export declare const runTimestamp: (run: RoutineRun) => string | null;
90
+ /** A skill the user may schedule, as the editor's picker needs it. */
91
+ export interface SchedulableSkill {
92
+ macroId: string;
93
+ name: string;
94
+ }
95
+ /**
96
+ * Whether this client can honestly describe — and therefore edit — the schedule.
97
+ *
98
+ * One predicate feeding the label, the hint AND the Edit control, because when
99
+ * those disagree the user gets an editor for a routine the app just said it did
100
+ * not understand, and saving rewrites the schedule to whatever the form
101
+ * defaulted to. Range checks are part of it: a weekday of 7 or an hour of 24
102
+ * otherwise renders a confident, wrong sentence instead of the honest fallback.
103
+ */
104
+ export declare const isDescribable: (routine: RoutineSchedule) => boolean;
105
+ /**
106
+ * A routine's time of day, in its own timezone.
107
+ *
108
+ * Formatted from the stored hour/minute rather than a Date, because the
109
+ * routine's timezone is not the viewer's: constructing a Date would render 9am
110
+ * Pacific as whatever that is locally.
111
+ */
112
+ export declare const formatTime: (hour: number, minute: number) => string;
113
+ /** An hour, for a picker. */
114
+ export declare const formatHour: (hour: number) => string;
115
+ /** The human sentence for a routine's cadence, or an honest admission. */
116
+ export declare const describeSchedule: (routine: RoutineSchedule) => string;
117
+ /**
118
+ * A date rendered in the ROUTINE's timezone, not the viewer's.
119
+ *
120
+ * `formatIsoDateShort` converts to the browser's zone, which put "Next Sep 8"
121
+ * (a Tuesday) under "Every Monday at 9:00am (America/Los_Angeles)" for a viewer
122
+ * in Tokyo. Everything else here avoids Date for that reason; these dates have
123
+ * to as well, or the row contradicts itself.
124
+ */
125
+ export declare const formatDateInZone: (iso: string | null, tzName: string | null) => string | null;
126
+ /** Whether a timezone string is one the platform actually knows. */
127
+ export declare const isValidTimezone: (tzName: string) => boolean;
128
+ /**
129
+ * A timezone's current UTC offset, e.g. "GMT+5:30", for the schedule summary.
130
+ *
131
+ * Offsets shift with DST, so this is what the zone reads TODAY — enough to
132
+ * confirm you picked the right zone, which is all the summary claims.
133
+ */
134
+ export declare const formatZoneOffset: (tzName: string) => string | null;
135
+ /**
136
+ * Every timezone the platform knows, for the picker's suggestions.
137
+ *
138
+ * Empty on a browser without `Intl.supportedValuesOf` — the field stays a plain
139
+ * text input there, which still works because the value is validated anyway.
140
+ */
141
+ export declare const timezoneOptions: () => string[];
142
+ /**
143
+ * The last-run sentence, which must never claim success for a failed run.
144
+ *
145
+ * Lives here rather than in the list, because the detail page had its own copy
146
+ * that hardcoded the success string — so a routine the list correctly showed as
147
+ * failed reported "Last run 3 Sep" on the page you opened to find out why.
148
+ */
149
+ export declare const describeLastRun: (routine: RoutineSchedule & {
150
+ lastRunAt: string | null;
151
+ lastStatus: RoutineStatus | null;
152
+ tzName: string | null;
153
+ }) => string;
154
+ /** Whether the routine's last run went wrong, for the status colour. */
155
+ export declare const lastRunFailed: (routine: {
156
+ lastStatus: RoutineStatus | null;
157
+ }) => boolean;
158
+ /**
159
+ * The cadence in one or two words, for a rail row.
160
+ *
161
+ * `describeSchedule` gives the full sentence a page can afford; a rail row
162
+ * cannot. "Custom" for a cadence this client does not recognise, matching
163
+ * everywhere else that refuses to guess one.
164
+ */
165
+ export declare const shortCadence: (routine: {
166
+ recurrence: RoutineRecurrence | null;
167
+ }) => string;
168
+ /**
169
+ * The prefix chat gives a routine's own conversation.
170
+ *
171
+ * Mirrors `_ROUTINE_SESSION_PREFIX` in chat's services/routine_runner.py. A
172
+ * routine's runs all append to one session, and that session comes back in the
173
+ * ordinary session list, so without this the rail listed every routine twice —
174
+ * once under Routines and again under Chat history.
175
+ */
176
+ export declare const ROUTINE_SESSION_PREFIX = "routine_";
177
+ export declare const isRoutineSession: (chatSessionId: string | null | undefined) => boolean;
178
+ /** Mirrors `_SESSION_ID_SEPARATOR` in chat's services/routine_runner.py. */
179
+ export declare const ROUTINE_SESSION_SEPARATOR = "__";
180
+ /**
181
+ * The routine a run's conversation belongs to, or null.
182
+ *
183
+ * `routine_<scheduleId>__<runUuid>`. Kept here rather than in each caller so
184
+ * the rail and the screen cannot drift on how a session id is read — they both
185
+ * answer "which routine is open" and have to agree.
186
+ */
187
+ export declare const routineIdFromSession: (chatSessionId: string | null | undefined) => string | null;
188
+ /**
189
+ * When a run happened, to the minute.
190
+ *
191
+ * Runs need the time and scheduled dates do not: a routine can run more than
192
+ * once a day — pressing Run does exactly that — and two rows both reading
193
+ * "Sep 3, 2026" gave no way to tell which run was which. A next-run date takes
194
+ * `formatDateInZone` instead, because the cadence line beside it already says
195
+ * the time.
196
+ */
197
+ export declare const formatRunTime: (iso: string | null, tzName: string | null) => string | null;
@@ -27,6 +27,7 @@ export declare const useAiCfoStreamingState: ({ initialAiCfoView, currentChatSes
27
27
  };
28
28
  agentId?: import('@zeniai/client-epic-state').ID;
29
29
  aiCfoSidePanelHostPageKey?: string;
30
+ isRoutinesBrowserOpen?: boolean;
30
31
  isSkillsBrowserOpen?: boolean;
31
32
  lastContextMessage?: string;
32
33
  lastContextStatus?: import('@zeniai/client-epic-state/view/aiCfoView/aiCfoViewPayload').ContextStatus;
@@ -1,14 +1,42 @@
1
1
  import { AiCfoViewSelector } from '@zeniai/client-epic-state';
2
2
  import { AiCfoMenu, InvoicingMenu, MenuListItem, Menu as MenuType, SettingsMenu } from './MenuButton';
3
3
  export declare const aiCfoMenuList: MenuListItem[];
4
+ /** Just what the rail row needs; the full type lives with the Routines page. */
5
+ export interface RailRoutine {
6
+ /** One or two words — "Daily", "Custom". Shown when nothing is unread. */
7
+ cadence: string;
8
+ name: string;
9
+ scheduleId: string;
10
+ /**
11
+ * The latest run's conversation, or null before the routine has run.
12
+ *
13
+ * Reported by the server rather than derived from the schedule id: runs each
14
+ * open their own conversation, so a derived id names one that was never
15
+ * created and the rail lands on an empty thread.
16
+ */
17
+ sessionId: string | null;
18
+ unreadRuns: number;
19
+ }
4
20
  export interface Props {
5
21
  selectedMenu: MenuType | SettingsMenu | AiCfoMenu | InvoicingMenu;
6
22
  aiCfoView?: AiCfoViewSelector;
7
23
  isMobile?: boolean;
24
+ /** Listed under the Routines entry, newest first, as the server ordered them. */
25
+ routines?: RailRoutine[];
8
26
  /** Absent/false hides the Skills entry entirely — the server decides. */
27
+ /**
28
+ * Absent/false hides the Routines entry. Gated on the SAME server flag as
29
+ * Skills: a routine runs a skill, so a tenant without skills has nothing to
30
+ * schedule and an entry leading to a permanently empty list.
31
+ */
32
+ routinesEnabled?: boolean;
33
+ /** Which routine's page is open, so the rail marks it like any other row. */
34
+ selectedRoutineId?: string;
9
35
  skillsEnabled?: boolean;
10
36
  onClick: (_menu: MenuListItem) => void;
11
37
  onDeleteChatSession?: (chatSessionId: string) => void;
38
+ /** Absent hides the list rather than rendering rows that go nowhere. */
39
+ onRoutineSelect?: (scheduleId: string, sessionId: string | null) => void;
12
40
  updateCurrentChatSessionId?: (chatSessionId: string) => void;
13
41
  }
14
- export default function AiCfoMenuContent({ selectedMenu, aiCfoView, isMobile, skillsEnabled, onClick, onDeleteChatSession, updateCurrentChatSessionId, }: Readonly<Props>): import("react/jsx-runtime").JSX.Element;
42
+ export default function AiCfoMenuContent({ selectedMenu, aiCfoView, isMobile, routinesEnabled, routines, selectedRoutineId, skillsEnabled, onClick, onRoutineSelect, onDeleteChatSession, updateCurrentChatSessionId, }: Readonly<Props>): import("react/jsx-runtime").JSX.Element;
@@ -1,6 +1,7 @@
1
1
  import { AiCfoViewSelector, CurrentTenant, FetchStateAndError, ID, LoggedInUser, MonthEndCloseChecksView, MonthYearPeriod, RewardsPlanData, TenantBaseView } from '@zeniai/client-epic-state';
2
2
  import { DisableMode } from '../formElements/common/common';
3
3
  import { AiCfoMenu, InvoicingMenu, Menu, MenuListItem, SettingsMenu } from './MenuButton';
4
+ import { RailRoutine } from './AiCfoMenuContent';
4
5
  export interface Props {
5
6
  aiCfoView: AiCfoViewSelector;
6
7
  currentTenantId: ID;
@@ -36,7 +37,12 @@ export interface Props {
36
37
  count: number;
37
38
  fetchStatus: FetchStateAndError;
38
39
  };
40
+ /** Forwarded to the AI CFO rail: the Scheduled list under Routines. */
41
+ routines?: RailRoutine[];
39
42
  /** Forwarded to the AI CFO rail: absent/false hides the Skills entry. */
43
+ /** Gates the Routines rail entry. Its OWN server flag, not the skills one. */
44
+ routinesEnabled?: boolean;
45
+ selectedRoutineId?: string;
40
46
  skillsEnabled?: boolean;
41
47
  thanksGivingAnimationEnabled?: boolean;
42
48
  handleLogOutClick: () => void;
@@ -50,7 +56,8 @@ export interface Props {
50
56
  onCalendarOpen?: (isOpen: boolean) => void;
51
57
  onDeleteChatSession?: (chatSessionId: string) => void;
52
58
  onPeriodChange?: (period: MonthYearPeriod) => void;
59
+ onRoutineSelect?: (scheduleId: string, sessionId: string | null) => void;
53
60
  onZeniLogoClick?: () => void;
54
61
  updateCurrentChatSessionId?: (chatSessionId: string) => void;
55
62
  }
56
- export default function AppDrawerContent({ currentTenantId, tenants, isVendorsTabVisible, isZeniAccountEnabled, isTreasuryEnabled, isChargeCardEnabled, rewardsConfiguration, selectedMenu, isTenantDropdownDisabled, isSettings, isInvoicing, isAiCfo, isAiCfoAccessEnabled, skillsEnabled, isNotificationsTabVisible, isSettingsFeatureEnabled, signedInUser, aiCfoView, currentTenant, christmasAnimationEnabled, expenseAutomationEnabledCompanies: _expenseAutomationEnabledCompanies, halloweenAnimationEnabled, newYearAnimationEnabled, thanksGivingAnimationEnabled, notificationCountDetails, isExpenseAutomationEnabledForUser, isTaskManagerAccessEnabled, onNotificationIconClick, handleLogOutClick, handleMenuChange, onZeniLogoClick, handleBackClick, handleCockpitClick, handleMyProfileClick, handleReferralsClick, handleTenantSelect, monthEndCloseChecksView, onCalendarOpen, onDeleteChatSession, onPeriodChange, updateCurrentChatSessionId, }: Readonly<Props>): import("react/jsx-runtime").JSX.Element;
63
+ export default function AppDrawerContent({ currentTenantId, tenants, isVendorsTabVisible, isZeniAccountEnabled, isTreasuryEnabled, isChargeCardEnabled, rewardsConfiguration, selectedMenu, isTenantDropdownDisabled, isSettings, isInvoicing, isAiCfo, isAiCfoAccessEnabled, routinesEnabled, routines, selectedRoutineId, onRoutineSelect, skillsEnabled, isNotificationsTabVisible, isSettingsFeatureEnabled, signedInUser, aiCfoView, currentTenant, christmasAnimationEnabled, expenseAutomationEnabledCompanies: _expenseAutomationEnabledCompanies, halloweenAnimationEnabled, newYearAnimationEnabled, thanksGivingAnimationEnabled, notificationCountDetails, isExpenseAutomationEnabledForUser, isTaskManagerAccessEnabled, onNotificationIconClick, handleLogOutClick, handleMenuChange, onZeniLogoClick, handleBackClick, handleCockpitClick, handleMyProfileClick, handleReferralsClick, handleTenantSelect, monthEndCloseChecksView, onCalendarOpen, onDeleteChatSession, onPeriodChange, updateCurrentChatSessionId, }: Readonly<Props>): import("react/jsx-runtime").JSX.Element;
@@ -49,6 +49,7 @@ export declare const MENU_TITLE_MAP: {
49
49
  reports: string;
50
50
  rewards: string;
51
51
  settings: string;
52
+ routines: string;
52
53
  skills: string;
53
54
  transaction_categorization: string;
54
55
  treasury: string;
@@ -72,9 +73,9 @@ export declare const ALL_SETTINGS_MENU_OPTIONS: readonly ["accounting", "approva
72
73
  export declare const toSettingsMenuOptionType: (v: string) => "my_profile" | "accounting" | "billing" | "company_details" | "integrations" | "notifications" | "approval_rules" | "bank_connections" | "business_verification" | "my_bank_connections";
73
74
  export declare const toSettingsMenuOptionTypeStrict: (v: string) => "my_profile" | "accounting" | "billing" | "company_details" | "integrations" | "notifications" | "approval_rules" | "bank_connections" | "business_verification" | "my_bank_connections" | undefined;
74
75
  export type SettingsMenu = (typeof ALL_SETTINGS_MENU_OPTIONS)[number];
75
- export declare const ALL_AI_CFO_MENU_OPTIONS: readonly ["new_chat", "explore", "skills", "search_chats"];
76
- export declare const toAiCfoMenuOptionType: (v: string) => "skills" | "new_chat" | "explore" | "search_chats";
77
- export declare const toAiCfoMenuOptionTypeStrict: (v: string) => "skills" | "new_chat" | "explore" | "search_chats" | undefined;
76
+ export declare const ALL_AI_CFO_MENU_OPTIONS: readonly ["new_chat", "explore", "skills", "routines", "search_chats"];
77
+ export declare const toAiCfoMenuOptionType: (v: string) => "skills" | "routines" | "new_chat" | "explore" | "search_chats";
78
+ export declare const toAiCfoMenuOptionTypeStrict: (v: string) => "skills" | "routines" | "new_chat" | "explore" | "search_chats" | undefined;
78
79
  export type AiCfoMenu = (typeof ALL_AI_CFO_MENU_OPTIONS)[number];
79
80
  export declare const ALL_INVOICING_MENU_OPTIONS: readonly ["invoicing_overview", "invoicing_analytics", "invoicing_customers", "invoicing_subscriptions", "invoicing_invoices", "invoicing_payments", "invoicing_credits", "invoicing_discounts", "invoicing_dunning", "invoicing_reports", "invoicing_catalog", "invoicing_settings", "invoicing_settings_payment_destination", "invoicing_settings_branding", "invoicing_settings_integrations", "invoicing_settings_dunning", "invoicing_settings_quickbooks", "invoicing_integrations", "invoicing_data_import", "invoicing_audit_log"];
80
81
  export declare const toInvoicingMenuOptionType: (v: string) => "invoicing_overview" | "invoicing_analytics" | "invoicing_customers" | "invoicing_subscriptions" | "invoicing_invoices" | "invoicing_payments" | "invoicing_credits" | "invoicing_discounts" | "invoicing_dunning" | "invoicing_reports" | "invoicing_catalog" | "invoicing_settings" | "invoicing_settings_payment_destination" | "invoicing_settings_branding" | "invoicing_settings_integrations" | "invoicing_settings_dunning" | "invoicing_settings_quickbooks" | "invoicing_integrations" | "invoicing_data_import" | "invoicing_audit_log";
@@ -1,4 +1,5 @@
1
1
  import { AiCfoViewSelector, CurrentTenant, LoggedInUser, MonthEndCloseChecksView, MonthYearPeriod, RewardsPlanData } from '@zeniai/client-epic-state';
2
+ import { RailRoutine } from './AiCfoMenuContent';
2
3
  import { AiCfoMenu, InvoicingMenu, Menu, MenuListItem, SettingsMenu } from './MenuButton';
3
4
  export declare const COMMAND_CENTER_SUBMENU_TYPES: readonly ["transaction_categorization", "je_schedules", "missing_receipts", "flux_analysis", "reconciliation"];
4
5
  export declare const INVOICING_SETTINGS_SUBMENU_TYPES: readonly ["invoicing_settings_branding", "invoicing_settings_integrations", "invoicing_settings_dunning", "invoicing_settings_quickbooks"];
@@ -31,6 +32,11 @@ interface Props {
31
32
  currentTenant?: CurrentTenant;
32
33
  isTaskManagerAccessEnabled?: boolean;
33
34
  monthEndCloseChecksView?: MonthEndCloseChecksView;
35
+ /** Forwarded to the AI CFO rail: the Scheduled list under Routines. */
36
+ routines?: RailRoutine[];
37
+ /** Forwarded to the AI CFO rail: absent/false hides the Routines entry. */
38
+ routinesEnabled?: boolean;
39
+ selectedRoutineId?: string;
34
40
  /** Forwarded to the AI CFO rail: absent/false hides the Skills entry. */
35
41
  skillsEnabled?: boolean;
36
42
  style?: React.CSSProperties;
@@ -39,7 +45,8 @@ interface Props {
39
45
  onCalendarOpen?: (isOpen: boolean) => void;
40
46
  onDeleteChatSession?: (chatSessionId: string) => void;
41
47
  onPeriodChange?: (period: MonthYearPeriod) => void;
48
+ onRoutineSelect?: (scheduleId: string, sessionId: string | null) => void;
42
49
  updateCurrentChatSessionId?: (chatSessionId: string) => void;
43
50
  }
44
- export default function MenuList({ selectedMenu, currentTenant, isVendorsTabVisible, isSetting, isInvoicing, isAiCfo, isAiCfoAccessEnabled, skillsEnabled, isZeniAccountEnabled, isChargeCardEnabled, isTreasuryEnabled, rewardsConfiguration, className, style, isNotificationsTabVisible, isTaskManagerAccessEnabled, isExpenseAutomationEnabledForUser, aiCfoView, additionalMessage, monthEndCloseChecksView, onCalendarOpen, onPeriodChange, onSelectionChanged, onDeleteChatSession, updateCurrentChatSessionId, onBackClick, }: Readonly<Props>): import("react/jsx-runtime").JSX.Element;
51
+ export default function MenuList({ selectedMenu, currentTenant, isVendorsTabVisible, isSetting, isInvoicing, isAiCfo, isAiCfoAccessEnabled, routinesEnabled, routines, selectedRoutineId, onRoutineSelect, skillsEnabled, isZeniAccountEnabled, isChargeCardEnabled, isTreasuryEnabled, rewardsConfiguration, className, style, isNotificationsTabVisible, isTaskManagerAccessEnabled, isExpenseAutomationEnabledForUser, aiCfoView, additionalMessage, monthEndCloseChecksView, onCalendarOpen, onPeriodChange, onSelectionChanged, onDeleteChatSession, updateCurrentChatSessionId, onBackClick, }: Readonly<Props>): import("react/jsx-runtime").JSX.Element;
45
52
  export {};
@@ -4,6 +4,11 @@ export declare const isBillPayTabVisible: (currentTenant: TenantView, globalInfo
4
4
  export declare const isReimbursementTabVisible: (currentTenant: TenantView, globalInfo: GlobalInfo) => boolean;
5
5
  export declare const isZeniAccountsTabVisible: (isZeniAccountEnabled: boolean, globalInfo: GlobalInfo) => boolean;
6
6
  export declare const isTreasuryTabVisible: (isTreasuryEnabled: boolean, globalInfo: GlobalInfo) => boolean;
7
+ /**
8
+ * Invoicing is restricted to a company's super admins and Zeni's own internal
9
+ * roles — `hasAdminLevelAccess` covers exactly those two. The Statsig gate
10
+ * still has to be on; this narrows who sees the tab once it is.
11
+ */
7
12
  export declare const isInvoicingTabVisible: (isInvoicingFeatureEnabled: boolean, globalInfo: GlobalInfo) => boolean;
8
13
  export declare const isCardsTabVisible: (currentTenant: TenantView, isCardsModuleGateEnabled: boolean, globalInfo: GlobalInfo, isCardsHidden?: boolean) => boolean;
9
14
  export declare const isZeniFinopsRoles: (globalInfo: GlobalInfo | undefined) => boolean;
@@ -7,7 +7,7 @@ export declare const uniqueName: (formId: ID) => `${string}_form`;
7
7
  /**
8
8
  * Props
9
9
  */
10
- export interface TaskNotificationsSectionData {
10
+ export interface NotificationControlsSectionData {
11
11
  isZeniUser: boolean;
12
12
  preferences: NotificationPreferences;
13
13
  registry: NotificationRegistry;
@@ -15,11 +15,18 @@ export interface TaskNotificationsSectionData {
15
15
  onSetGroupFrequency: (groupId: string, frequency: NotificationFrequency) => void;
16
16
  onToggleEventChannel: (eventId: string, channel: NotificationChannel, enabled: boolean) => void;
17
17
  }
18
+ /**
19
+ * @deprecated Use `NotificationControlsSectionData`. Kept so consumers keep
20
+ * compiling while they migrate; the shape is identical.
21
+ */
22
+ export type TaskNotificationsSectionData = NotificationControlsSectionData;
18
23
  export interface NotificationSettingsPageProps {
19
24
  notificationSettingsView: NotificationSettingsSelectorView;
20
25
  signedInUser: LoggedInUser;
26
+ commentingNotifications?: NotificationControlsSectionData;
27
+ isCommentingNotificationsDirty?: boolean;
21
28
  isTaskNotificationsDirty?: boolean;
22
- taskNotifications?: TaskNotificationsSectionData;
29
+ taskNotifications?: NotificationControlsSectionData;
23
30
  onCancel: () => void;
24
31
  onClickMenuIcon: () => void;
25
32
  onFormDataChange: (formData: NotificationSettingsLocalData) => void;
@@ -1,10 +1,12 @@
1
1
  import { NotificationChannel, NotificationFrequency, NotificationPreferences, NotificationRegistry } from '@zeniai/client-epic-state';
2
- export interface TaskNotificationsSectionProps {
2
+ export interface NotificationControlsSectionProps {
3
+ formPrefix: string;
3
4
  isZeniUser: boolean;
4
5
  preferences: NotificationPreferences;
5
6
  registry: NotificationRegistry;
7
+ title: string;
6
8
  onSetGroupChannelMaster: (groupId: string, channel: NotificationChannel, enabled: boolean) => void;
7
9
  onSetGroupFrequency: (groupId: string, frequency: NotificationFrequency) => void;
8
10
  onToggleEventChannel: (eventId: string, channel: NotificationChannel, enabled: boolean) => void;
9
11
  }
10
- export declare const TaskNotificationsSection: ({ isZeniUser, registry, preferences, onToggleEventChannel, onSetGroupChannelMaster, onSetGroupFrequency, }: TaskNotificationsSectionProps) => import("react/jsx-runtime").JSX.Element;
12
+ export declare const NotificationControlsSection: ({ title, formPrefix, isZeniUser, registry, preferences, onToggleEventChannel, onSetGroupChannelMaster, onSetGroupFrequency, }: NotificationControlsSectionProps) => import("react/jsx-runtime").JSX.Element;