-
Notifications
You must be signed in to change notification settings - Fork 26
Expand file tree
/
Copy pathagent-graph.ts
More file actions
156 lines (143 loc) · 4.13 KB
/
Copy pathagent-graph.ts
File metadata and controls
156 lines (143 loc) · 4.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
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
/**
* Single source of truth for the HAIP agent dependency graph.
*
* HAIP orchestrates HAIP agents (RManager + schedules/events).
* OTAIP orchestrates OTAIP agents over the Connect API — do not embed
* a second generic pipeline runtime here.
*/
/** All known agent type keys (incl. types without an implementation yet). */
export const VALID_AGENT_TYPES = [
'pricing',
'demand_forecast',
'channel_mix',
'overbooking',
'night_audit',
'housekeeping',
'cancellation',
'guest_comms',
'review_response',
'ar_collections',
'deposit_risk',
'group_pickup',
'revenue_manager',
] as const;
export type AgentType = (typeof VALID_AGENT_TYPES)[number];
export type AgentSubgraph = 'revenue' | 'ops' | 'guest_commercial';
export interface AgentGraphEdge {
from: AgentType;
to: AgentType;
}
/**
* Order RManager gathers revenue levers: demand first, then consumers.
* `revenue_manager` itself is the synthesizer (not a lever).
*/
export const REVENUE_LEVER_ORDER = [
'demand_forecast',
'pricing',
'overbooking',
'channel_mix',
'group_pickup',
] as const satisfies readonly AgentType[];
export type RevenueLeverType = (typeof REVENUE_LEVER_ORDER)[number];
/** Revenue subgraph edges: demand → levers → RManager. */
export const REVENUE_EDGES: readonly AgentGraphEdge[] = [
{ from: 'demand_forecast', to: 'pricing' },
{ from: 'demand_forecast', to: 'overbooking' },
{ from: 'demand_forecast', to: 'channel_mix' },
{ from: 'demand_forecast', to: 'group_pickup' },
{ from: 'pricing', to: 'revenue_manager' },
{ from: 'overbooking', to: 'revenue_manager' },
{ from: 'channel_mix', to: 'revenue_manager' },
{ from: 'group_pickup', to: 'revenue_manager' },
];
/** Ops specialists (event/cron; not inside RManager). */
export const OPS_AGENT_TYPES = [
'night_audit',
'housekeeping',
'cancellation',
] as const satisfies readonly AgentType[];
/** Guest / commercial specialists. */
export const GUEST_COMMERCIAL_AGENT_TYPES = [
'guest_comms',
'review_response',
'ar_collections',
'deposit_risk',
] as const satisfies readonly AgentType[];
/** All edges exposed by the graph API (revenue only today; ops/guest are peers). */
export const AGENT_GRAPH_EDGES: readonly AgentGraphEdge[] = REVENUE_EDGES;
export function subgraphFor(agentType: AgentType): AgentSubgraph {
if (
agentType === 'revenue_manager' ||
(REVENUE_LEVER_ORDER as readonly string[]).includes(agentType)
) {
return 'revenue';
}
if ((OPS_AGENT_TYPES as readonly string[]).includes(agentType)) {
return 'ops';
}
return 'guest_commercial';
}
export function isValidAgentType(agentType: string): agentType is AgentType {
return (VALID_AGENT_TYPES as readonly string[]).includes(agentType);
}
/**
* Default external-cron matrix. Revenue levers have no independent cron —
* they run via RManager. Empty string = manual / event only.
*/
export const DEFAULT_SCHEDULE_MATRIX: Record<
AgentType,
{ cron: string; notes: string }
> = {
revenue_manager: {
cron: '0 6 * * *',
notes: 'Owns revenue cadence; pulls demand + levers',
},
demand_forecast: {
cron: '',
notes: 'Via RManager; manual run still allowed',
},
pricing: {
cron: '',
notes: 'Via RManager; manual run still allowed',
},
overbooking: {
cron: '',
notes: 'Via RManager; manual run still allowed',
},
channel_mix: {
cron: '',
notes: 'Via RManager; manual run still allowed',
},
group_pickup: {
cron: '',
notes: 'Via RManager; manual run still allowed',
},
housekeeping: {
cron: '0 8 * * *',
notes: 'Daily ops window',
},
cancellation: {
cron: '0 */6 * * *',
notes: 'Every 6 hours',
},
ar_collections: {
cron: '0 6 * * *',
notes: 'Daily with RManager window',
},
night_audit: {
cron: '0 23 * * *',
notes: 'Before night audit close',
},
guest_comms: {
cron: '0 7 * * *',
notes: 'Daily pre-arrival, day-of, delayed post-stay, win-back; lifecycle events for confirmation/welcome',
},
review_response: {
cron: '',
notes: 'Event-driven on review ingest + manual',
},
deposit_risk: {
cron: '',
notes: 'Type reserved; no implementation yet',
},
};