een-api-toolkit 0.3.43 → 0.3.47

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 (44) hide show
  1. package/.claude/agents/docs-accuracy-reviewer.md +35 -5
  2. package/.claude/agents/een-automations-agent.md +264 -0
  3. package/.claude/agents/een-devices-agent.md +5 -7
  4. package/.claude/agents/een-events-agent.md +30 -16
  5. package/.claude/agents/een-media-agent.md +12 -15
  6. package/.claude/agents/een-users-agent.md +2 -2
  7. package/CHANGELOG.md +6 -8
  8. package/dist/index.cjs +3 -3
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.d.ts +815 -0
  11. package/dist/index.js +986 -719
  12. package/dist/index.js.map +1 -1
  13. package/docs/AI-CONTEXT.md +17 -1
  14. package/docs/ai-reference/AI-AUTH.md +1 -1
  15. package/docs/ai-reference/AI-AUTOMATIONS.md +833 -0
  16. package/docs/ai-reference/AI-DEVICES.md +1 -1
  17. package/docs/ai-reference/AI-EVENTS.md +1 -1
  18. package/docs/ai-reference/AI-GROUPING.md +128 -66
  19. package/docs/ai-reference/AI-MEDIA.md +1 -1
  20. package/docs/ai-reference/AI-SETUP.md +1 -1
  21. package/docs/ai-reference/AI-USERS.md +1 -1
  22. package/examples/vue-automations/.env.example +11 -0
  23. package/examples/vue-automations/README.md +205 -0
  24. package/examples/vue-automations/e2e/app.spec.ts +83 -0
  25. package/examples/vue-automations/e2e/auth.spec.ts +468 -0
  26. package/examples/vue-automations/index.html +13 -0
  27. package/examples/vue-automations/package-lock.json +1722 -0
  28. package/examples/vue-automations/package.json +29 -0
  29. package/examples/vue-automations/playwright.config.ts +46 -0
  30. package/examples/vue-automations/src/App.vue +122 -0
  31. package/examples/vue-automations/src/main.ts +23 -0
  32. package/examples/vue-automations/src/router/index.ts +61 -0
  33. package/examples/vue-automations/src/views/Automations.vue +692 -0
  34. package/examples/vue-automations/src/views/Callback.vue +76 -0
  35. package/examples/vue-automations/src/views/Home.vue +172 -0
  36. package/examples/vue-automations/src/views/Login.vue +33 -0
  37. package/examples/vue-automations/src/views/Logout.vue +66 -0
  38. package/examples/vue-automations/src/vite-env.d.ts +1 -0
  39. package/examples/vue-automations/tsconfig.json +21 -0
  40. package/examples/vue-automations/tsconfig.node.json +10 -0
  41. package/examples/vue-automations/vite.config.ts +12 -0
  42. package/examples/vue-event-subscriptions/e2e/auth.spec.ts +8 -12
  43. package/package.json +1 -1
  44. package/scripts/setup-agents.ts +38 -19
@@ -0,0 +1,833 @@
1
+ # Automations API - EEN API Toolkit
2
+
3
+ > **Version:** 0.3.47
4
+ >
5
+ > Complete reference for automation rules and alert actions.
6
+ > Load this document when working with automated alert workflows.
7
+
8
+ ---
9
+
10
+ ## Overview
11
+
12
+ The Automations API provides read access to the EEN alert automation system:
13
+
14
+ | Entity | Description |
15
+ |--------|-------------|
16
+ | **Event Alert Condition Rules** | Filter incoming events to generate alerts |
17
+ | **Alert Condition Rules** | Process events and create alerts with actors |
18
+ | **Alert Action Rules** | Route alerts to appropriate actions |
19
+ | **Alert Actions** | Execute notifications, webhooks, integrations |
20
+
21
+ ### Workflow Diagram
22
+
23
+ ```
24
+ ┌─────────────┐ ┌─────────────────────────┐ ┌─────────┐
25
+ │ Events │────▶│ Event Alert Condition │────▶│ Alerts │
26
+ │ (from │ │ Rules │ │ │
27
+ │ cameras) │ │ (filter & prioritize) │ │ │
28
+ └─────────────┘ └─────────────────────────┘ └────┬────┘
29
+
30
+ ┌─────────────────────────┐ │
31
+ │ Alert Action Rules │◀─────────┘
32
+ │ (match alerts to │
33
+ │ actions) │
34
+ └───────────┬─────────────┘
35
+
36
+ ┌───────────▼─────────────┐
37
+ │ Alert Actions │
38
+ │ (notification, webhook, │
39
+ │ SMS, email, etc.) │
40
+ └─────────────────────────┘
41
+ ```
42
+
43
+ ---
44
+
45
+ ## Event Alert Condition Rule Types
46
+
47
+ ```typescript
48
+ interface EventAlertConditionRule {
49
+ id: string
50
+ createTimestamp: string // ISO 8601
51
+ updateTimestamp: string // ISO 8601
52
+ name: string
53
+ priority: number // 1-10 (higher = more important)
54
+ notes?: string
55
+ enabled: boolean
56
+ cooldownSeconds: number // Seconds between alerts
57
+ humanValidation?: HumanValidation
58
+ eventFilter: EventFilter
59
+ outputAlertTypes: string[]
60
+ }
61
+
62
+ interface HumanValidation {
63
+ required: boolean
64
+ timeoutSeconds?: number
65
+ }
66
+
67
+ interface EventFilter {
68
+ types: string[] // Event types to match
69
+ resourceFilter?: EventResourceFilter
70
+ }
71
+
72
+ interface EventResourceFilter {
73
+ accountIds?: string[]
74
+ actorIds?: string[]
75
+ actorTags__contains?: string[] // All tags must match
76
+ actorTags__any?: string[] // Any tag matches
77
+ }
78
+
79
+ interface EventAlertConditionRuleFieldValues {
80
+ eventTypes?: string[]
81
+ outputAlertTypes?: string[]
82
+ }
83
+
84
+ interface ListEventAlertConditionRulesParams {
85
+ pageSize?: number
86
+ pageToken?: string
87
+ enabled?: boolean
88
+ id__in?: string[]
89
+ outputAlertType__in?: string[]
90
+ priority__gte?: number
91
+ priority__lte?: number
92
+ }
93
+ ```
94
+
95
+ ---
96
+
97
+ ## Alert Condition Rule Types
98
+
99
+ ```typescript
100
+ interface AlertConditionRule {
101
+ id: string
102
+ createTimestamp: string
103
+ type: string
104
+ creatorId: string
105
+ name: string
106
+ notes?: string
107
+ enabled: boolean
108
+ priority: number // 1-10
109
+ actors: AlertConditionRuleActor[]
110
+ inputEventTypes: string[]
111
+ outputAlertType: string
112
+ actions?: AlertConditionRuleAction[] // include=actions
113
+ insights?: AlertConditionRuleInsights // include=insights
114
+ }
115
+
116
+ interface AlertConditionRuleActor {
117
+ id: string
118
+ type: string
119
+ accountId?: string
120
+ }
121
+
122
+ interface AlertConditionRuleAction {
123
+ id: string
124
+ name?: string
125
+ type?: string
126
+ }
127
+
128
+ interface AlertConditionRuleInsights {
129
+ totalAlerts?: number
130
+ lastTriggered?: string // ISO 8601
131
+ alertCounts?: {
132
+ last24Hours?: number
133
+ last7Days?: number
134
+ last30Days?: number
135
+ }
136
+ }
137
+
138
+ type AlertConditionRuleInclude = 'actions' | 'insights'
139
+
140
+ interface ListAlertConditionRulesParams {
141
+ pageSize?: number
142
+ pageToken?: string
143
+ enabled?: boolean
144
+ id__in?: string[]
145
+ actorId__in?: string[]
146
+ inputEventType__in?: string[]
147
+ outputAlertType?: string
148
+ type?: string
149
+ include?: AlertConditionRuleInclude[]
150
+ }
151
+ ```
152
+
153
+ ---
154
+
155
+ ## Alert Action Rule Types
156
+
157
+ ```typescript
158
+ interface AlertActionRule {
159
+ id: string
160
+ createTimestamp: string
161
+ name: string
162
+ notes?: string
163
+ enabled: boolean
164
+ alertTypes: string[] // Alert types this rule matches
165
+ actorIds: string[]
166
+ actorTypes: string[]
167
+ ruleIds: string[] // Alert condition rule IDs
168
+ alertActionIds: string[] // Actions to execute
169
+ priority__gte?: number
170
+ priority__lte?: number
171
+ }
172
+
173
+ interface ListAlertActionRulesParams {
174
+ pageSize?: number
175
+ pageToken?: string
176
+ enabled?: boolean
177
+ id__in?: string[]
178
+ alertType__in?: string[]
179
+ actorId__in?: string[]
180
+ alertActionId__in?: string[]
181
+ ruleId__in?: string[]
182
+ }
183
+ ```
184
+
185
+ ---
186
+
187
+ ## Alert Action Types
188
+
189
+ ```typescript
190
+ type AlertActionType =
191
+ | 'notification' // Push notifications to mobile app
192
+ | 'sms' // SMS text messages
193
+ | 'smtp' // Email notifications
194
+ | 'slack' // Slack webhook
195
+ | 'webhook' // Generic HTTP webhook
196
+ | 'brivo' // Brivo access control
197
+ | 'zendesk' // Zendesk ticket creation
198
+ | 'immix' // Immix integration
199
+ | 'zapier' // Zapier automation
200
+ | 'sentinel' // Sentinel integration
201
+ | 'evalinkTalos' // Evalink Talos integration
202
+ | 'outputPort' // Physical output port trigger
203
+ | 'ebus' // eBus integration
204
+ | 'playSpeakerAudioClip' // Play audio on speaker
205
+ | 'zulipPrivate' // Zulip private message
206
+ | 'zulipStream' // Zulip stream message
207
+
208
+ interface AutomationAlertAction {
209
+ id: string
210
+ createTimestamp: string
211
+ type: AlertActionType
212
+ name: string
213
+ notes?: string
214
+ enabled: boolean
215
+ settings: AlertActionSettings // Type-specific
216
+ }
217
+
218
+ // Type-specific settings interfaces
219
+ interface NotificationSettings {
220
+ userIds: string[]
221
+ }
222
+
223
+ interface SmsSettings {
224
+ phoneNumbers: string[]
225
+ }
226
+
227
+ interface SmtpSettings {
228
+ recipients: string[]
229
+ subject?: string
230
+ body?: string
231
+ }
232
+
233
+ interface SlackSettings {
234
+ webhookUrl: string
235
+ channel?: string
236
+ username?: string
237
+ }
238
+
239
+ interface WebhookSettings {
240
+ url: string
241
+ method?: 'GET' | 'POST' | 'PUT'
242
+ headers?: Record<string, string>
243
+ }
244
+
245
+ interface OutputPortSettings {
246
+ deviceId: string
247
+ outputPort: number
248
+ durationMs?: number
249
+ }
250
+
251
+ interface PlaySpeakerAudioClipSettings {
252
+ speakerId: string
253
+ audioClipId: string
254
+ volume?: number
255
+ }
256
+
257
+ interface ListAlertActionsParams {
258
+ pageSize?: number
259
+ pageToken?: string
260
+ enabled?: boolean
261
+ id__in?: string[]
262
+ type__in?: AlertActionType[]
263
+ }
264
+ ```
265
+
266
+ ---
267
+
268
+ ## Event Alert Condition Rule Functions
269
+
270
+ ### listEventAlertConditionRules(params?)
271
+
272
+ ```typescript
273
+ import { listEventAlertConditionRules } from 'een-api-toolkit'
274
+
275
+ // Get all enabled rules
276
+ const { data, error } = await listEventAlertConditionRules({
277
+ enabled: true,
278
+ pageSize: 50
279
+ })
280
+
281
+ if (data) {
282
+ data.results.forEach(rule => {
283
+ console.log(`${rule.name} (priority: ${rule.priority})`)
284
+ console.log(` Events: ${rule.eventFilter.types.join(', ')}`)
285
+ console.log(` Outputs: ${rule.outputAlertTypes.join(', ')}`)
286
+ })
287
+ }
288
+
289
+ // Filter by priority
290
+ const { data: highPriority } = await listEventAlertConditionRules({
291
+ priority__gte: 7,
292
+ priority__lte: 10
293
+ })
294
+
295
+ // Filter by output alert type
296
+ const { data: motionRules } = await listEventAlertConditionRules({
297
+ outputAlertType__in: ['een.motionDetectionAlert.v1']
298
+ })
299
+ ```
300
+
301
+ ### getEventAlertConditionRuleFieldValues(params?)
302
+
303
+ Discover available filter values for building UIs:
304
+
305
+ ```typescript
306
+ import { getEventAlertConditionRuleFieldValues } from 'een-api-toolkit'
307
+
308
+ const { data, error } = await getEventAlertConditionRuleFieldValues()
309
+
310
+ if (data) {
311
+ // Populate event type dropdown
312
+ const eventTypeOptions = data.eventTypes ?? []
313
+
314
+ // Populate alert type dropdown
315
+ const alertTypeOptions = data.outputAlertTypes ?? []
316
+ }
317
+ ```
318
+
319
+ ### getEventAlertConditionRule(ruleId)
320
+
321
+ ```typescript
322
+ import { getEventAlertConditionRule } from 'een-api-toolkit'
323
+
324
+ const { data, error } = await getEventAlertConditionRule('rule-123')
325
+
326
+ if (error) {
327
+ if (error.code === 'NOT_FOUND') {
328
+ console.log('Rule not found')
329
+ }
330
+ return
331
+ }
332
+
333
+ console.log(`Rule: ${data.name}`)
334
+ console.log(`Cooldown: ${data.cooldownSeconds} seconds`)
335
+ console.log(`Human validation: ${data.humanValidation?.required ?? false}`)
336
+ ```
337
+
338
+ ---
339
+
340
+ ## Alert Condition Rule Functions
341
+
342
+ ### listAlertConditionRules(params?)
343
+
344
+ ```typescript
345
+ import { listAlertConditionRules } from 'een-api-toolkit'
346
+
347
+ // Get rules with actions and insights
348
+ const { data, error } = await listAlertConditionRules({
349
+ enabled: true,
350
+ include: ['actions', 'insights']
351
+ })
352
+
353
+ if (data) {
354
+ data.results.forEach(rule => {
355
+ console.log(`${rule.name}`)
356
+ console.log(` Type: ${rule.type}`)
357
+ console.log(` Input events: ${rule.inputEventTypes.join(', ')}`)
358
+ console.log(` Output alert: ${rule.outputAlertType}`)
359
+
360
+ if (rule.actions) {
361
+ console.log(` Actions: ${rule.actions.length}`)
362
+ }
363
+
364
+ if (rule.insights) {
365
+ console.log(` Total alerts: ${rule.insights.totalAlerts}`)
366
+ console.log(` Last triggered: ${rule.insights.lastTriggered}`)
367
+ }
368
+ })
369
+ }
370
+
371
+ // Filter by actor
372
+ const { data: cameraRules } = await listAlertConditionRules({
373
+ actorId__in: ['camera-123', 'camera-456']
374
+ })
375
+
376
+ // Filter by event type
377
+ const { data: motionRules } = await listAlertConditionRules({
378
+ inputEventType__in: ['een.motionDetectionEvent.v1']
379
+ })
380
+ ```
381
+
382
+ ### getAlertConditionRule(ruleId, params?)
383
+
384
+ ```typescript
385
+ import { getAlertConditionRule } from 'een-api-toolkit'
386
+
387
+ const { data, error } = await getAlertConditionRule('rule-123', {
388
+ include: ['actions', 'insights']
389
+ })
390
+
391
+ if (data) {
392
+ console.log(`Rule: ${data.name}`)
393
+ console.log(`Actors: ${data.actors.length}`)
394
+ console.log(`Actions: ${data.actions?.length ?? 0}`)
395
+
396
+ // Display insights
397
+ if (data.insights) {
398
+ console.log(`Alerts last 24h: ${data.insights.alertCounts?.last24Hours}`)
399
+ console.log(`Alerts last 7d: ${data.insights.alertCounts?.last7Days}`)
400
+ }
401
+ }
402
+ ```
403
+
404
+ ---
405
+
406
+ ## Alert Action Rule Functions
407
+
408
+ ### listAlertActionRules(params?)
409
+
410
+ ```typescript
411
+ import { listAlertActionRules } from 'een-api-toolkit'
412
+
413
+ // Get enabled rules for motion alerts
414
+ const { data, error } = await listAlertActionRules({
415
+ enabled: true,
416
+ alertType__in: ['een.motionDetectionAlert.v1']
417
+ })
418
+
419
+ if (data) {
420
+ data.results.forEach(rule => {
421
+ console.log(`${rule.name}`)
422
+ console.log(` Alert types: ${rule.alertTypes.join(', ')}`)
423
+ console.log(` Action count: ${rule.alertActionIds.length}`)
424
+
425
+ if (rule.priority__gte !== undefined) {
426
+ console.log(` Min priority: ${rule.priority__gte}`)
427
+ }
428
+ })
429
+ }
430
+
431
+ // Find rules for specific actions
432
+ const { data: webhookRules } = await listAlertActionRules({
433
+ alertActionId__in: ['webhook-action-123']
434
+ })
435
+ ```
436
+
437
+ ### getAlertActionRule(ruleId)
438
+
439
+ ```typescript
440
+ import { getAlertActionRule } from 'een-api-toolkit'
441
+
442
+ const { data, error } = await getAlertActionRule('rule-123')
443
+
444
+ if (data) {
445
+ console.log(`Rule: ${data.name}`)
446
+ console.log(`Alert types: ${data.alertTypes.join(', ')}`)
447
+ console.log(`Actor IDs: ${data.actorIds.join(', ')}`)
448
+ console.log(`Actions: ${data.alertActionIds.join(', ')}`)
449
+ }
450
+ ```
451
+
452
+ ---
453
+
454
+ ## Alert Action Functions
455
+
456
+ ### listAlertActions(params?)
457
+
458
+ ```typescript
459
+ import { listAlertActions } from 'een-api-toolkit'
460
+
461
+ // Get all enabled notification and webhook actions
462
+ const { data, error } = await listAlertActions({
463
+ enabled: true,
464
+ type__in: ['notification', 'webhook', 'slack']
465
+ })
466
+
467
+ if (data) {
468
+ data.results.forEach(action => {
469
+ console.log(`${action.name} (${action.type})`)
470
+
471
+ switch (action.type) {
472
+ case 'notification':
473
+ const notifSettings = action.settings as NotificationSettings
474
+ console.log(` Users: ${notifSettings.userIds.join(', ')}`)
475
+ break
476
+ case 'webhook':
477
+ const webhookSettings = action.settings as WebhookSettings
478
+ console.log(` URL: ${webhookSettings.url}`)
479
+ break
480
+ case 'slack':
481
+ const slackSettings = action.settings as SlackSettings
482
+ console.log(` Channel: ${slackSettings.channel}`)
483
+ break
484
+ }
485
+ })
486
+ }
487
+
488
+ // Get all SMS actions
489
+ const { data: smsActions } = await listAlertActions({
490
+ type__in: ['sms']
491
+ })
492
+ ```
493
+
494
+ ### getAlertAction(actionId)
495
+
496
+ ```typescript
497
+ import { getAlertAction } from 'een-api-toolkit'
498
+
499
+ const { data, error } = await getAlertAction('action-123')
500
+
501
+ if (data) {
502
+ console.log(`Action: ${data.name}`)
503
+ console.log(`Type: ${data.type}`)
504
+ console.log(`Enabled: ${data.enabled}`)
505
+ console.log('Settings:', JSON.stringify(data.settings, null, 2))
506
+ }
507
+ ```
508
+
509
+ ---
510
+
511
+ ## Vue Component Example
512
+
513
+ ```typescript
514
+ import { ref, computed, onMounted } from 'vue'
515
+ import {
516
+ listEventAlertConditionRules,
517
+ listAlertConditionRules,
518
+ listAlertActionRules,
519
+ listAlertActions,
520
+ type EventAlertConditionRule,
521
+ type AlertConditionRule,
522
+ type AlertActionRule,
523
+ type AutomationAlertAction,
524
+ type EenError
525
+ } from 'een-api-toolkit'
526
+
527
+ // Active tab
528
+ type TabName = 'eventAlertRules' | 'conditionRules' | 'actionRules' | 'actions'
529
+ const activeTab = ref<TabName>('eventAlertRules')
530
+
531
+ // Modal state
532
+ type SelectedItem = EventAlertConditionRule | AlertConditionRule | AlertActionRule | AutomationAlertAction
533
+ const showModal = ref(false)
534
+ const selectedItem = ref<SelectedItem | null>(null)
535
+ const selectedItemTitle = ref('')
536
+
537
+ function openModal(item: SelectedItem, title: string) {
538
+ selectedItem.value = item
539
+ selectedItemTitle.value = title
540
+ showModal.value = true
541
+ }
542
+
543
+ function closeModal() {
544
+ showModal.value = false
545
+ selectedItem.value = null
546
+ selectedItemTitle.value = ''
547
+ }
548
+
549
+ function formatJson(obj: unknown): string {
550
+ return JSON.stringify(obj, null, 2)
551
+ }
552
+
553
+ // Event Alert Condition Rules
554
+ const eventAlertRules = ref<EventAlertConditionRule[]>([])
555
+ const eventAlertRulesLoading = ref(false)
556
+ const eventAlertRulesError = ref<EenError | null>(null)
557
+ const eventAlertRulesNextToken = ref<string | undefined>(undefined)
558
+ const hasMoreEventAlertRules = computed(() => !!eventAlertRulesNextToken.value)
559
+
560
+ // Alert Condition Rules
561
+ const conditionRules = ref<AlertConditionRule[]>([])
562
+ const conditionRulesLoading = ref(false)
563
+ const conditionRulesError = ref<EenError | null>(null)
564
+ const conditionRulesNextToken = ref<string | undefined>(undefined)
565
+ const hasMoreConditionRules = computed(() => !!conditionRulesNextToken.value)
566
+
567
+ // Alert Action Rules
568
+ const actionRules = ref<AlertActionRule[]>([])
569
+ const actionRulesLoading = ref(false)
570
+ const actionRulesError = ref<EenError | null>(null)
571
+ const actionRulesNextToken = ref<string | undefined>(undefined)
572
+ const hasMoreActionRules = computed(() => !!actionRulesNextToken.value)
573
+
574
+ // Alert Actions
575
+ const actions = ref<AutomationAlertAction[]>([])
576
+ const actionsLoading = ref(false)
577
+ const actionsError = ref<EenError | null>(null)
578
+ const actionsNextToken = ref<string | undefined>(undefined)
579
+ const hasMoreActions = computed(() => !!actionsNextToken.value)
580
+
581
+ // Filter state
582
+ const enabledFilter = ref<'all' | 'enabled' | 'disabled'>('all')
583
+
584
+ // Fetch functions
585
+ async function fetchEventAlertRules(append = false) {
586
+ eventAlertRulesLoading.value = true
587
+ eventAlertRulesError.value = null
588
+
589
+ const params: Parameters<typeof listEventAlertConditionRules>[0] = {
590
+ pageSize: 10,
591
+ ...(append && eventAlertRulesNextToken.value ? { pageToken: eventAlertRulesNextToken.value } : {}),
592
+ ...(enabledFilter.value !== 'all' ? { enabled: enabledFilter.value === 'enabled' } : {})
593
+ }
594
+
595
+ const result = await listEventAlertConditionRules(params)
596
+
597
+ if (result.error) {
598
+ eventAlertRulesError.value = result.error
599
+ if (!append) eventAlertRules.value = []
600
+ eventAlertRulesNextToken.value = undefined
601
+ } else {
602
+ if (append) {
603
+ eventAlertRules.value = [...eventAlertRules.value, ...result.data.results]
604
+ } else {
605
+ eventAlertRules.value = result.data.results
606
+ }
607
+ eventAlertRulesNextToken.value = result.data.nextPageToken
608
+ }
609
+
610
+ eventAlertRulesLoading.value = false
611
+ }
612
+
613
+ async function fetchConditionRules(append = false) {
614
+ conditionRulesLoading.value = true
615
+ conditionRulesError.value = null
616
+
617
+ const params: Parameters<typeof listAlertConditionRules>[0] = {
618
+ pageSize: 10,
619
+ include: ['actions', 'insights'],
620
+ ...(append && conditionRulesNextToken.value ? { pageToken: conditionRulesNextToken.value } : {}),
621
+ ...(enabledFilter.value !== 'all' ? { enabled: enabledFilter.value === 'enabled' } : {})
622
+ }
623
+
624
+ const result = await listAlertConditionRules(params)
625
+
626
+ if (result.error) {
627
+ conditionRulesError.value = result.error
628
+ if (!append) conditionRules.value = []
629
+ conditionRulesNextToken.value = undefined
630
+ } else {
631
+ if (append) {
632
+ conditionRules.value = [...conditionRules.value, ...result.data.results]
633
+ } else {
634
+ conditionRules.value = result.data.results
635
+ }
636
+ conditionRulesNextToken.value = result.data.nextPageToken
637
+ }
638
+
639
+ conditionRulesLoading.value = false
640
+ }
641
+
642
+ async function fetchActionRules(append = false) {
643
+ actionRulesLoading.value = true
644
+ actionRulesError.value = null
645
+
646
+ const params: Parameters<typeof listAlertActionRules>[0] = {
647
+ pageSize: 10,
648
+ ...(append && actionRulesNextToken.value ? { pageToken: actionRulesNextToken.value } : {}),
649
+ ...(enabledFilter.value !== 'all' ? { enabled: enabledFilter.value === 'enabled' } : {})
650
+ }
651
+
652
+ const result = await listAlertActionRules(params)
653
+
654
+ if (result.error) {
655
+ actionRulesError.value = result.error
656
+ if (!append) actionRules.value = []
657
+ actionRulesNextToken.value = undefined
658
+ } else {
659
+ if (append) {
660
+ actionRules.value = [...actionRules.value, ...result.data.results]
661
+ } else {
662
+ actionRules.value = result.data.results
663
+ }
664
+ actionRulesNextToken.value = result.data.nextPageToken
665
+ }
666
+
667
+ actionRulesLoading.value = false
668
+ }
669
+
670
+ async function fetchActions(append = false) {
671
+ actionsLoading.value = true
672
+ actionsError.value = null
673
+
674
+ const params: Parameters<typeof listAlertActions>[0] = {
675
+ pageSize: 10,
676
+ ...(append && actionsNextToken.value ? { pageToken: actionsNextToken.value } : {}),
677
+ ...(enabledFilter.value !== 'all' ? { enabled: enabledFilter.value === 'enabled' } : {})
678
+ }
679
+
680
+ const result = await listAlertActions(params)
681
+
682
+ if (result.error) {
683
+ actionsError.value = result.error
684
+ if (!append) actions.value = []
685
+ actionsNextToken.value = undefined
686
+ } else {
687
+ if (append) {
688
+ actions.value = [...actions.value, ...result.data.results]
689
+ } else {
690
+ actions.value = result.data.results
691
+ }
692
+ actionsNextToken.value = result.data.nextPageToken
693
+ }
694
+
695
+ actionsLoading.value = false
696
+ }
697
+
698
+ function refreshCurrentTab() {
699
+ switch (activeTab.value) {
700
+ case 'eventAlertRules':
701
+ fetchEventAlertRules()
702
+ break
703
+ case 'conditionRules':
704
+ fetchConditionRules()
705
+ break
706
+ case 'actionRules':
707
+ fetchActionRules()
708
+ break
709
+ case 'actions':
710
+ fetchActions()
711
+ break
712
+ }
713
+ }
714
+
715
+ function loadMore() {
716
+ switch (activeTab.value) {
717
+ case 'eventAlertRules':
718
+ fetchEventAlertRules(true)
719
+ break
720
+ case 'conditionRules':
721
+ fetchConditionRules(true)
722
+ break
723
+ case 'actionRules':
724
+ fetchActionRules(true)
725
+ break
726
+ case 'actions':
727
+ fetchActions(true)
728
+ break
729
+ }
730
+ }
731
+
732
+ function switchTab(tab: TabName) {
733
+ activeTab.value = tab
734
+ // Fetch data for the tab if not loaded
735
+ switch (tab) {
736
+ case 'eventAlertRules':
737
+ if (eventAlertRules.value.length === 0 && !eventAlertRulesLoading.value) {
738
+ fetchEventAlertRules()
739
+ }
740
+ break
741
+ case 'conditionRules':
742
+ if (conditionRules.value.length === 0 && !conditionRulesLoading.value) {
743
+ fetchConditionRules()
744
+ }
745
+ break
746
+ case 'actionRules':
747
+ if (actionRules.value.length === 0 && !actionRulesLoading.value) {
748
+ fetchActionRules()
749
+ }
750
+ break
751
+ case 'actions':
752
+ if (actions.value.length === 0 && !actionsLoading.value) {
753
+ fetchActions()
754
+ }
755
+ break
756
+ }
757
+ }
758
+
759
+ const isLoading = computed(() => {
760
+ switch (activeTab.value) {
761
+ case 'eventAlertRules':
762
+ return eventAlertRulesLoading.value
763
+ case 'conditionRules':
764
+ return conditionRulesLoading.value
765
+ case 'actionRules':
766
+ return actionRulesLoading.value
767
+ case 'actions':
768
+ return actionsLoading.value
769
+ default:
770
+ return false
771
+ }
772
+ })
773
+
774
+ const hasMore = computed(() => {
775
+ switch (activeTab.value) {
776
+ case 'eventAlertRules':
777
+ return hasMoreEventAlertRules.value
778
+ case 'conditionRules':
779
+ return hasMoreConditionRules.value
780
+ case 'actionRules':
781
+ return hasMoreActionRules.value
782
+ case 'actions':
783
+ return hasMoreActions.value
784
+ default:
785
+ return false
786
+ }
787
+ })
788
+
789
+ onMounted(() => {
790
+ fetchEventAlertRules()
791
+ })
792
+ ```
793
+
794
+ ---
795
+
796
+ ## Filter Patterns
797
+
798
+ | Filter | Entity | Example | Description |
799
+ |--------|--------|---------|-------------|
800
+ | `enabled` | All | `true` | Filter by enabled/disabled |
801
+ | `id__in` | All | `['id1', 'id2']` | Filter by IDs |
802
+ | `pageSize` | All | `50` | Results per page |
803
+ | `pageToken` | All | `'token'` | Pagination cursor |
804
+ | `priority__gte` | Event Alert Rules | `5` | Min priority (1-10) |
805
+ | `priority__lte` | Event Alert Rules | `10` | Max priority (1-10) |
806
+ | `outputAlertType__in` | Event Alert Rules | `['type']` | Output alert types |
807
+ | `actorId__in` | Alert Condition Rules | `['actor1']` | Actor IDs |
808
+ | `inputEventType__in` | Alert Condition Rules | `['type']` | Input event types |
809
+ | `outputAlertType` | Alert Condition Rules | `'type'` | Output alert type |
810
+ | `type` | Alert Condition Rules | `'basic'` | Rule type |
811
+ | `include` | Alert Condition Rules | `['actions']` | Include fields |
812
+ | `alertType__in` | Alert Action Rules | `['type']` | Alert types |
813
+ | `alertActionId__in` | Alert Action Rules | `['id']` | Action IDs |
814
+ | `ruleId__in` | Alert Action Rules | `['id']` | Rule IDs |
815
+ | `type__in` | Alert Actions | `['webhook']` | Action types |
816
+
817
+ ---
818
+
819
+ ## Error Handling
820
+
821
+ | Error Code | HTTP Status | Meaning | Action |
822
+ |------------|-------------|---------|--------|
823
+ | AUTH_REQUIRED | 401 | Not authenticated | Redirect to login |
824
+ | FORBIDDEN | 403 | No permission | Show access denied |
825
+ | NOT_FOUND | 404 | Entity not found | Show "not found" |
826
+ | RATE_LIMITED | 429 | Too many requests | Retry with backoff |
827
+ | API_ERROR | 5xx | Server error | Show error, retry |
828
+
829
+ ---
830
+
831
+ ## Reference Examples
832
+
833
+ - `examples/vue-automations/` - Automation rules listing