@ginkoai/cli 1.6.2 â 1.7.0
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/dist/commands/agent/agent-client.d.ts +150 -0
- package/dist/commands/agent/agent-client.d.ts.map +1 -0
- package/dist/commands/agent/agent-client.js +170 -0
- package/dist/commands/agent/agent-client.js.map +1 -0
- package/dist/commands/agent/index.d.ts +22 -0
- package/dist/commands/agent/index.d.ts.map +1 -0
- package/dist/commands/agent/index.js +121 -0
- package/dist/commands/agent/index.js.map +1 -0
- package/dist/commands/agent/list.d.ts +22 -0
- package/dist/commands/agent/list.d.ts.map +1 -0
- package/dist/commands/agent/list.js +119 -0
- package/dist/commands/agent/list.js.map +1 -0
- package/dist/commands/agent/register.d.ts +21 -0
- package/dist/commands/agent/register.d.ts.map +1 -0
- package/dist/commands/agent/register.js +97 -0
- package/dist/commands/agent/register.js.map +1 -0
- package/dist/commands/agent/status.d.ts +19 -0
- package/dist/commands/agent/status.d.ts.map +1 -0
- package/dist/commands/agent/status.js +271 -0
- package/dist/commands/agent/status.js.map +1 -0
- package/dist/commands/agent/work.d.ts +22 -0
- package/dist/commands/agent/work.d.ts.map +1 -0
- package/dist/commands/agent/work.js +459 -0
- package/dist/commands/agent/work.js.map +1 -0
- package/dist/commands/checkpoint/create.d.ts +27 -0
- package/dist/commands/checkpoint/create.d.ts.map +1 -0
- package/dist/commands/checkpoint/create.js +82 -0
- package/dist/commands/checkpoint/create.js.map +1 -0
- package/dist/commands/checkpoint/index.d.ts +23 -0
- package/dist/commands/checkpoint/index.d.ts.map +1 -0
- package/dist/commands/checkpoint/index.js +91 -0
- package/dist/commands/checkpoint/index.js.map +1 -0
- package/dist/commands/checkpoint/list.d.ts +27 -0
- package/dist/commands/checkpoint/list.d.ts.map +1 -0
- package/dist/commands/checkpoint/list.js +115 -0
- package/dist/commands/checkpoint/list.js.map +1 -0
- package/dist/commands/checkpoint/show.d.ts +23 -0
- package/dist/commands/checkpoint/show.d.ts.map +1 -0
- package/dist/commands/checkpoint/show.js +102 -0
- package/dist/commands/checkpoint/show.js.map +1 -0
- package/dist/commands/dlq.d.ts +24 -0
- package/dist/commands/dlq.d.ts.map +1 -0
- package/dist/commands/dlq.js +172 -0
- package/dist/commands/dlq.js.map +1 -0
- package/dist/commands/escalation/create.d.ts +22 -0
- package/dist/commands/escalation/create.d.ts.map +1 -0
- package/dist/commands/escalation/create.js +122 -0
- package/dist/commands/escalation/create.js.map +1 -0
- package/dist/commands/escalation/escalation-client.d.ts +101 -0
- package/dist/commands/escalation/escalation-client.d.ts.map +1 -0
- package/dist/commands/escalation/escalation-client.js +129 -0
- package/dist/commands/escalation/escalation-client.js.map +1 -0
- package/dist/commands/escalation/index.d.ts +22 -0
- package/dist/commands/escalation/index.d.ts.map +1 -0
- package/dist/commands/escalation/index.js +94 -0
- package/dist/commands/escalation/index.js.map +1 -0
- package/dist/commands/escalation/list.d.ts +24 -0
- package/dist/commands/escalation/list.d.ts.map +1 -0
- package/dist/commands/escalation/list.js +170 -0
- package/dist/commands/escalation/list.js.map +1 -0
- package/dist/commands/escalation/resolve.d.ts +20 -0
- package/dist/commands/escalation/resolve.d.ts.map +1 -0
- package/dist/commands/escalation/resolve.js +102 -0
- package/dist/commands/escalation/resolve.js.map +1 -0
- package/dist/commands/graph/api-client.d.ts +21 -1
- package/dist/commands/graph/api-client.d.ts.map +1 -1
- package/dist/commands/graph/api-client.js +23 -0
- package/dist/commands/graph/api-client.js.map +1 -1
- package/dist/commands/handoff.d.ts.map +1 -1
- package/dist/commands/handoff.js +9 -1
- package/dist/commands/handoff.js.map +1 -1
- package/dist/commands/log.d.ts +3 -0
- package/dist/commands/log.d.ts.map +1 -1
- package/dist/commands/log.js +73 -14
- package/dist/commands/log.js.map +1 -1
- package/dist/commands/notifications/history.d.ts +21 -0
- package/dist/commands/notifications/history.d.ts.map +1 -0
- package/dist/commands/notifications/history.js +160 -0
- package/dist/commands/notifications/history.js.map +1 -0
- package/dist/commands/notifications/index.d.ts +22 -0
- package/dist/commands/notifications/index.d.ts.map +1 -0
- package/dist/commands/notifications/index.js +87 -0
- package/dist/commands/notifications/index.js.map +1 -0
- package/dist/commands/notifications/list.d.ts +19 -0
- package/dist/commands/notifications/list.d.ts.map +1 -0
- package/dist/commands/notifications/list.js +132 -0
- package/dist/commands/notifications/list.js.map +1 -0
- package/dist/commands/notifications/test.d.ts +19 -0
- package/dist/commands/notifications/test.d.ts.map +1 -0
- package/dist/commands/notifications/test.js +217 -0
- package/dist/commands/notifications/test.js.map +1 -0
- package/dist/commands/orchestrate.d.ts +25 -0
- package/dist/commands/orchestrate.d.ts.map +1 -0
- package/dist/commands/orchestrate.js +858 -0
- package/dist/commands/orchestrate.js.map +1 -0
- package/dist/commands/sprint/deps.d.ts +29 -0
- package/dist/commands/sprint/deps.d.ts.map +1 -0
- package/dist/commands/sprint/deps.js +269 -0
- package/dist/commands/sprint/deps.js.map +1 -0
- package/dist/commands/sprint/index.d.ts +10 -5
- package/dist/commands/sprint/index.d.ts.map +1 -1
- package/dist/commands/sprint/index.js +26 -5
- package/dist/commands/sprint/index.js.map +1 -1
- package/dist/commands/start/index.d.ts.map +1 -1
- package/dist/commands/start/index.js +6 -0
- package/dist/commands/start/index.js.map +1 -1
- package/dist/commands/start/start-reflection.d.ts.map +1 -1
- package/dist/commands/start/start-reflection.js +8 -0
- package/dist/commands/start/start-reflection.js.map +1 -1
- package/dist/commands/verify.d.ts +17 -0
- package/dist/commands/verify.d.ts.map +1 -0
- package/dist/commands/verify.js +232 -0
- package/dist/commands/verify.js.map +1 -0
- package/dist/core/session-log-manager.d.ts +1 -1
- package/dist/core/session-log-manager.d.ts.map +1 -1
- package/dist/index.js +78 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/__tests__/task-timeout.test.d.ts +12 -0
- package/dist/lib/__tests__/task-timeout.test.d.ts.map +1 -0
- package/dist/lib/__tests__/task-timeout.test.js +278 -0
- package/dist/lib/__tests__/task-timeout.test.js.map +1 -0
- package/dist/lib/agent-heartbeat.d.ts +68 -0
- package/dist/lib/agent-heartbeat.d.ts.map +1 -0
- package/dist/lib/agent-heartbeat.js +117 -0
- package/dist/lib/agent-heartbeat.js.map +1 -0
- package/dist/lib/checkpoint.d.ts +85 -0
- package/dist/lib/checkpoint.d.ts.map +1 -0
- package/dist/lib/checkpoint.js +323 -0
- package/dist/lib/checkpoint.js.map +1 -0
- package/dist/lib/context-metrics.d.ts +230 -0
- package/dist/lib/context-metrics.d.ts.map +1 -0
- package/dist/lib/context-metrics.js +372 -0
- package/dist/lib/context-metrics.js.map +1 -0
- package/dist/lib/dead-letter-queue.d.ts +108 -0
- package/dist/lib/dead-letter-queue.d.ts.map +1 -0
- package/dist/lib/dead-letter-queue.js +378 -0
- package/dist/lib/dead-letter-queue.js.map +1 -0
- package/dist/lib/event-logger.d.ts +9 -1
- package/dist/lib/event-logger.d.ts.map +1 -1
- package/dist/lib/event-logger.js +45 -3
- package/dist/lib/event-logger.js.map +1 -1
- package/dist/lib/event-queue.d.ts.map +1 -1
- package/dist/lib/event-queue.js +13 -2
- package/dist/lib/event-queue.js.map +1 -1
- package/dist/lib/examples/timeout-demo.d.ts +13 -0
- package/dist/lib/examples/timeout-demo.d.ts.map +1 -0
- package/dist/lib/examples/timeout-demo.js +102 -0
- package/dist/lib/examples/timeout-demo.js.map +1 -0
- package/dist/lib/examples/timeout-integration-example.d.ts +17 -0
- package/dist/lib/examples/timeout-integration-example.d.ts.map +1 -0
- package/dist/lib/examples/timeout-integration-example.js +223 -0
- package/dist/lib/examples/timeout-integration-example.js.map +1 -0
- package/dist/lib/notification-hooks.d.ts +103 -0
- package/dist/lib/notification-hooks.d.ts.map +1 -0
- package/dist/lib/notification-hooks.js +223 -0
- package/dist/lib/notification-hooks.js.map +1 -0
- package/dist/lib/notifications/discord.d.ts +20 -0
- package/dist/lib/notifications/discord.d.ts.map +1 -0
- package/dist/lib/notifications/discord.js +140 -0
- package/dist/lib/notifications/discord.js.map +1 -0
- package/dist/lib/notifications/index.d.ts +66 -0
- package/dist/lib/notifications/index.d.ts.map +1 -0
- package/dist/lib/notifications/index.js +120 -0
- package/dist/lib/notifications/index.js.map +1 -0
- package/dist/lib/notifications/slack.d.ts +20 -0
- package/dist/lib/notifications/slack.d.ts.map +1 -0
- package/dist/lib/notifications/slack.js +186 -0
- package/dist/lib/notifications/slack.js.map +1 -0
- package/dist/lib/notifications/teams.d.ts +20 -0
- package/dist/lib/notifications/teams.d.ts.map +1 -0
- package/dist/lib/notifications/teams.js +146 -0
- package/dist/lib/notifications/teams.js.map +1 -0
- package/dist/lib/notifications/webhook.d.ts +23 -0
- package/dist/lib/notifications/webhook.d.ts.map +1 -0
- package/dist/lib/notifications/webhook.js +65 -0
- package/dist/lib/notifications/webhook.js.map +1 -0
- package/dist/lib/orchestrator-state.d.ts +194 -0
- package/dist/lib/orchestrator-state.d.ts.map +1 -0
- package/dist/lib/orchestrator-state.js +332 -0
- package/dist/lib/orchestrator-state.js.map +1 -0
- package/dist/lib/realtime-cursor.d.ts +107 -0
- package/dist/lib/realtime-cursor.d.ts.map +1 -0
- package/dist/lib/realtime-cursor.js +260 -0
- package/dist/lib/realtime-cursor.js.map +1 -0
- package/dist/lib/rollback.d.ts +86 -0
- package/dist/lib/rollback.d.ts.map +1 -0
- package/dist/lib/rollback.js +405 -0
- package/dist/lib/rollback.js.map +1 -0
- package/dist/lib/sprint-loader.d.ts +39 -2
- package/dist/lib/sprint-loader.d.ts.map +1 -1
- package/dist/lib/sprint-loader.js +255 -4
- package/dist/lib/sprint-loader.js.map +1 -1
- package/dist/lib/stale-agent-detector.d.ts +102 -0
- package/dist/lib/stale-agent-detector.d.ts.map +1 -0
- package/dist/lib/stale-agent-detector.js +156 -0
- package/dist/lib/stale-agent-detector.js.map +1 -0
- package/dist/lib/task-dependencies.d.ts +143 -0
- package/dist/lib/task-dependencies.d.ts.map +1 -0
- package/dist/lib/task-dependencies.js +357 -0
- package/dist/lib/task-dependencies.js.map +1 -0
- package/dist/lib/task-timeout.d.ts +153 -0
- package/dist/lib/task-timeout.d.ts.map +1 -0
- package/dist/lib/task-timeout.js +505 -0
- package/dist/lib/task-timeout.js.map +1 -0
- package/dist/lib/verification/build-check.d.ts +55 -0
- package/dist/lib/verification/build-check.d.ts.map +1 -0
- package/dist/lib/verification/build-check.js +111 -0
- package/dist/lib/verification/build-check.js.map +1 -0
- package/dist/lib/verification/index.d.ts +19 -0
- package/dist/lib/verification/index.d.ts.map +1 -0
- package/dist/lib/verification/index.js +17 -0
- package/dist/lib/verification/index.js.map +1 -0
- package/dist/lib/verification/lint-check.d.ts +34 -0
- package/dist/lib/verification/lint-check.d.ts.map +1 -0
- package/dist/lib/verification/lint-check.js +215 -0
- package/dist/lib/verification/lint-check.js.map +1 -0
- package/dist/lib/verification/test-runner.d.ts +50 -0
- package/dist/lib/verification/test-runner.d.ts.map +1 -0
- package/dist/lib/verification/test-runner.js +225 -0
- package/dist/lib/verification/test-runner.js.map +1 -0
- package/dist/utils/command-helpers.d.ts.map +1 -1
- package/dist/utils/command-helpers.js +7 -0
- package/dist/utils/command-helpers.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileType: utility
|
|
3
|
+
* @status: current
|
|
4
|
+
* @updated: 2025-12-07
|
|
5
|
+
* @tags: [notifications, hooks, epic-004, resilience, alerts]
|
|
6
|
+
* @related: [notifications/index.ts, event-logger.ts, orchestrator-state.ts]
|
|
7
|
+
* @priority: high
|
|
8
|
+
* @complexity: medium
|
|
9
|
+
* @dependencies: [fs-extra, minimatch]
|
|
10
|
+
*/
|
|
11
|
+
import fs from 'fs-extra';
|
|
12
|
+
import path from 'path';
|
|
13
|
+
import minimatch from 'minimatch';
|
|
14
|
+
import { getProjectRoot } from '../utils/config-loader.js';
|
|
15
|
+
/**
|
|
16
|
+
* Load notification hooks from ginko.config.json
|
|
17
|
+
*
|
|
18
|
+
* @returns Array of notification hooks
|
|
19
|
+
*/
|
|
20
|
+
export async function loadNotificationHooks() {
|
|
21
|
+
try {
|
|
22
|
+
const projectRoot = await getProjectRoot();
|
|
23
|
+
const configPath = path.join(projectRoot, 'ginko.config.json');
|
|
24
|
+
// Check if config file exists
|
|
25
|
+
if (!await fs.pathExists(configPath)) {
|
|
26
|
+
console.log('[NotificationHooks] No ginko.config.json found, no hooks configured');
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
// Load config
|
|
30
|
+
const config = await fs.readJSON(configPath);
|
|
31
|
+
// Extract notification hooks
|
|
32
|
+
if (!config.notifications?.hooks) {
|
|
33
|
+
console.log('[NotificationHooks] No notification hooks configured');
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
const hooks = config.notifications.hooks;
|
|
37
|
+
// Validate hooks
|
|
38
|
+
const validHooks = hooks.filter(hook => {
|
|
39
|
+
if (!hook.id || !hook.events || !hook.destination) {
|
|
40
|
+
console.warn(`[NotificationHooks] Invalid hook configuration (missing id, events, or destination)`);
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
if (!Array.isArray(hook.events) || hook.events.length === 0) {
|
|
44
|
+
console.warn(`[NotificationHooks] Invalid hook ${hook.id}: events must be non-empty array`);
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
if (!hook.destination.type || !hook.destination.config) {
|
|
48
|
+
console.warn(`[NotificationHooks] Invalid hook ${hook.id}: destination must have type and config`);
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
return true;
|
|
52
|
+
});
|
|
53
|
+
// Filter enabled hooks (default: true)
|
|
54
|
+
const enabledHooks = validHooks.filter(hook => hook.enabled !== false);
|
|
55
|
+
console.log(`[NotificationHooks] Loaded ${enabledHooks.length} notification hooks`);
|
|
56
|
+
return enabledHooks;
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
console.error('[NotificationHooks] Failed to load notification hooks:', error instanceof Error ? error.message : String(error));
|
|
60
|
+
return [];
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Check if a hook matches the given payload based on filters
|
|
65
|
+
*
|
|
66
|
+
* @param hook - Notification hook to check
|
|
67
|
+
* @param payload - Notification payload to match against
|
|
68
|
+
* @returns True if hook matches filters
|
|
69
|
+
*/
|
|
70
|
+
export function matchesFilter(hook, payload) {
|
|
71
|
+
const filter = hook.filter;
|
|
72
|
+
// No filter means match all
|
|
73
|
+
if (!filter) {
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
// Check severity filter
|
|
77
|
+
if (filter.severity && filter.severity.length > 0) {
|
|
78
|
+
if (!filter.severity.includes(payload.severity)) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// Check epic ID filter
|
|
83
|
+
if (filter.epicId && payload.epicId) {
|
|
84
|
+
if (filter.epicId !== payload.epicId) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Check task pattern filter (glob)
|
|
89
|
+
if (filter.taskPattern && payload.taskId) {
|
|
90
|
+
if (!minimatch(payload.taskId, filter.taskPattern)) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Trigger a notification to all matching hooks
|
|
98
|
+
*
|
|
99
|
+
* @param event - Notification event type
|
|
100
|
+
* @param payload - Notification payload
|
|
101
|
+
*/
|
|
102
|
+
export async function triggerNotification(event, payload) {
|
|
103
|
+
try {
|
|
104
|
+
// Load hooks
|
|
105
|
+
const hooks = await loadNotificationHooks();
|
|
106
|
+
if (hooks.length === 0) {
|
|
107
|
+
console.log(`[NotificationHooks] No hooks configured for event: ${event}`);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
// Filter hooks that match this event
|
|
111
|
+
const matchingHooks = hooks.filter(hook => {
|
|
112
|
+
// Check if hook listens for this event type
|
|
113
|
+
if (!hook.events.includes(event)) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
// Check if hook matches filters
|
|
117
|
+
return matchesFilter(hook, payload);
|
|
118
|
+
});
|
|
119
|
+
if (matchingHooks.length === 0) {
|
|
120
|
+
console.log(`[NotificationHooks] No matching hooks for event: ${event}`);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
console.log(`[NotificationHooks] Triggering ${matchingHooks.length} hooks for event: ${event}`);
|
|
124
|
+
// Dispatch to each matching hook (in parallel, non-blocking)
|
|
125
|
+
const dispatchPromises = matchingHooks.map(async (hook) => {
|
|
126
|
+
try {
|
|
127
|
+
const success = await dispatchToDestination(hook.destination, payload);
|
|
128
|
+
if (success) {
|
|
129
|
+
console.log(`[NotificationHooks] â Notification sent to ${hook.id} (${hook.destination.type})`);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
console.warn(`[NotificationHooks] â Notification failed for ${hook.id} (${hook.destination.type})`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
// Log error but don't propagate - notification failures shouldn't block workflow
|
|
137
|
+
console.error(`[NotificationHooks] Error dispatching to ${hook.id}:`, error instanceof Error ? error.message : String(error));
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
// Wait for all dispatches to complete (but don't block on errors)
|
|
141
|
+
await Promise.allSettled(dispatchPromises);
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
// Top-level error handling - log but don't propagate
|
|
145
|
+
console.error('[NotificationHooks] Failed to trigger notifications:', error instanceof Error ? error.message : String(error));
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Dispatch a notification to a specific destination
|
|
150
|
+
*
|
|
151
|
+
* @param destination - Notification destination config
|
|
152
|
+
* @param payload - Notification payload
|
|
153
|
+
* @returns Promise<boolean> - True if dispatch succeeded
|
|
154
|
+
*/
|
|
155
|
+
export async function dispatchToDestination(destination, payload) {
|
|
156
|
+
try {
|
|
157
|
+
// Dynamically import the appropriate adapter
|
|
158
|
+
const { sendNotification } = await import(`./notifications/${destination.type}.js`);
|
|
159
|
+
// Call adapter's sendNotification function
|
|
160
|
+
const result = await sendNotification(destination.config, payload);
|
|
161
|
+
return result;
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
if (error instanceof Error && error.message.includes('Cannot find module')) {
|
|
165
|
+
console.error(`[NotificationHooks] Unsupported destination type: ${destination.type}`);
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
console.error(`[NotificationHooks] Dispatch error for ${destination.type}:`, error instanceof Error ? error.message : String(error));
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Validate notification hook configuration
|
|
174
|
+
*
|
|
175
|
+
* @param hook - Hook configuration to validate
|
|
176
|
+
* @returns Validation result with errors
|
|
177
|
+
*/
|
|
178
|
+
export function validateHook(hook) {
|
|
179
|
+
const errors = [];
|
|
180
|
+
if (!hook.id) {
|
|
181
|
+
errors.push('Hook must have an id');
|
|
182
|
+
}
|
|
183
|
+
if (!hook.events || !Array.isArray(hook.events) || hook.events.length === 0) {
|
|
184
|
+
errors.push('Hook must have a non-empty events array');
|
|
185
|
+
}
|
|
186
|
+
if (!hook.destination) {
|
|
187
|
+
errors.push('Hook must have a destination');
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
if (!hook.destination.type) {
|
|
191
|
+
errors.push('Destination must have a type');
|
|
192
|
+
}
|
|
193
|
+
if (!hook.destination.config || typeof hook.destination.config !== 'object') {
|
|
194
|
+
errors.push('Destination must have a config object');
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
// Validate event types
|
|
198
|
+
const validEvents = [
|
|
199
|
+
'escalation',
|
|
200
|
+
'blocker',
|
|
201
|
+
'failure',
|
|
202
|
+
'milestone',
|
|
203
|
+
'completion',
|
|
204
|
+
'stale_agent',
|
|
205
|
+
'human_required'
|
|
206
|
+
];
|
|
207
|
+
if (hook.events) {
|
|
208
|
+
const invalidEvents = hook.events.filter(e => !validEvents.includes(e));
|
|
209
|
+
if (invalidEvents.length > 0) {
|
|
210
|
+
errors.push(`Invalid event types: ${invalidEvents.join(', ')}`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
// Validate destination type
|
|
214
|
+
const validDestinations = ['slack', 'discord', 'teams', 'webhook', 'email'];
|
|
215
|
+
if (hook.destination?.type && !validDestinations.includes(hook.destination.type)) {
|
|
216
|
+
errors.push(`Invalid destination type: ${hook.destination.type}. Must be one of: ${validDestinations.join(', ')}`);
|
|
217
|
+
}
|
|
218
|
+
return {
|
|
219
|
+
valid: errors.length === 0,
|
|
220
|
+
errors
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
//# sourceMappingURL=notification-hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification-hooks.js","sourceRoot":"","sources":["../../src/lib/notification-hooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileType: utility
|
|
3
|
+
* @status: current
|
|
4
|
+
* @updated: 2025-12-07
|
|
5
|
+
* @tags: [notifications, discord, webhook, epic-004]
|
|
6
|
+
* @related: [index.ts, notification-hooks.ts, slack.ts, teams.ts, webhook.ts]
|
|
7
|
+
* @priority: high
|
|
8
|
+
* @complexity: low
|
|
9
|
+
* @dependencies: []
|
|
10
|
+
*/
|
|
11
|
+
import { NotificationPayload } from '../notification-hooks.js';
|
|
12
|
+
/**
|
|
13
|
+
* Send notification to Discord via webhook
|
|
14
|
+
*
|
|
15
|
+
* @param config - Discord configuration (must include webhook_url)
|
|
16
|
+
* @param payload - Notification payload
|
|
17
|
+
* @returns Promise<boolean> - True if notification sent successfully
|
|
18
|
+
*/
|
|
19
|
+
export declare function sendNotification(config: Record<string, string>, payload: NotificationPayload): Promise<boolean>;
|
|
20
|
+
//# sourceMappingURL=discord.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discord.d.ts","sourceRoot":"","sources":["../../../src/lib/notifications/discord.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAU/D;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,OAAO,CAAC,CAoClB"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileType: utility
|
|
3
|
+
* @status: current
|
|
4
|
+
* @updated: 2025-12-07
|
|
5
|
+
* @tags: [notifications, discord, webhook, epic-004]
|
|
6
|
+
* @related: [index.ts, notification-hooks.ts, slack.ts, teams.ts, webhook.ts]
|
|
7
|
+
* @priority: high
|
|
8
|
+
* @complexity: low
|
|
9
|
+
* @dependencies: []
|
|
10
|
+
*/
|
|
11
|
+
import { retryWithBackoff, truncate } from './index.js';
|
|
12
|
+
/**
|
|
13
|
+
* Send notification to Discord via webhook
|
|
14
|
+
*
|
|
15
|
+
* @param config - Discord configuration (must include webhook_url)
|
|
16
|
+
* @param payload - Notification payload
|
|
17
|
+
* @returns Promise<boolean> - True if notification sent successfully
|
|
18
|
+
*/
|
|
19
|
+
export async function sendNotification(config, payload) {
|
|
20
|
+
const discordConfig = config;
|
|
21
|
+
// Validate required config
|
|
22
|
+
if (!discordConfig.webhook_url) {
|
|
23
|
+
console.error('[DiscordNotification] Missing webhook_url in config');
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
// Build Discord message
|
|
28
|
+
const message = buildDiscordMessage(payload);
|
|
29
|
+
// Send with retry logic
|
|
30
|
+
await retryWithBackoff(async () => {
|
|
31
|
+
const response = await fetch(discordConfig.webhook_url, {
|
|
32
|
+
method: 'POST',
|
|
33
|
+
headers: {
|
|
34
|
+
'Content-Type': 'application/json',
|
|
35
|
+
},
|
|
36
|
+
body: JSON.stringify(message),
|
|
37
|
+
signal: AbortSignal.timeout(5000), // 5 second timeout
|
|
38
|
+
});
|
|
39
|
+
if (!response.ok) {
|
|
40
|
+
throw new Error(`Discord webhook returned ${response.status}: ${response.statusText}`);
|
|
41
|
+
}
|
|
42
|
+
return response;
|
|
43
|
+
});
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
console.error('[DiscordNotification] Failed to send notification:', error instanceof Error ? error.message : String(error));
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Build Discord message with embed
|
|
53
|
+
*
|
|
54
|
+
* @param payload - Notification payload
|
|
55
|
+
* @returns Discord message object
|
|
56
|
+
*/
|
|
57
|
+
function buildDiscordMessage(payload) {
|
|
58
|
+
const embed = {
|
|
59
|
+
title: truncate(payload.title, 256), // Discord limit: 256 chars
|
|
60
|
+
description: truncate(payload.description, 4096), // Discord limit: 4096 chars
|
|
61
|
+
color: getSeverityColor(payload.severity),
|
|
62
|
+
fields: [],
|
|
63
|
+
timestamp: payload.timestamp,
|
|
64
|
+
footer: {
|
|
65
|
+
text: `Ginko ${payload.event}`,
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
// Add fields
|
|
69
|
+
if (payload.severity) {
|
|
70
|
+
embed.fields.push({
|
|
71
|
+
name: 'Severity',
|
|
72
|
+
value: capitalizeFirst(payload.severity),
|
|
73
|
+
inline: true,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
if (payload.taskId) {
|
|
77
|
+
embed.fields.push({
|
|
78
|
+
name: 'Task',
|
|
79
|
+
value: payload.taskId,
|
|
80
|
+
inline: true,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
if (payload.epicId) {
|
|
84
|
+
embed.fields.push({
|
|
85
|
+
name: 'Epic',
|
|
86
|
+
value: payload.epicId,
|
|
87
|
+
inline: true,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
if (payload.agentId) {
|
|
91
|
+
embed.fields.push({
|
|
92
|
+
name: 'Agent',
|
|
93
|
+
value: payload.agentId,
|
|
94
|
+
inline: true,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
// Add custom metadata fields (limit to 25 fields total - Discord limit)
|
|
98
|
+
if (payload.metadata) {
|
|
99
|
+
for (const [key, value] of Object.entries(payload.metadata)) {
|
|
100
|
+
if (embed.fields.length >= 25)
|
|
101
|
+
break;
|
|
102
|
+
embed.fields.push({
|
|
103
|
+
name: capitalizeFirst(key),
|
|
104
|
+
value: truncate(String(value), 1024), // Discord limit: 1024 chars per field
|
|
105
|
+
inline: true,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return { embeds: [embed] };
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Get color for severity level (Discord uses decimal color codes)
|
|
113
|
+
*
|
|
114
|
+
* @param severity - Severity level
|
|
115
|
+
* @returns Discord color code
|
|
116
|
+
*/
|
|
117
|
+
function getSeverityColor(severity) {
|
|
118
|
+
switch (severity) {
|
|
119
|
+
case 'critical':
|
|
120
|
+
return 0xFF0000; // Red
|
|
121
|
+
case 'high':
|
|
122
|
+
return 0xFF8C00; // Orange
|
|
123
|
+
case 'medium':
|
|
124
|
+
return 0xFFD700; // Yellow/Gold
|
|
125
|
+
case 'low':
|
|
126
|
+
return 0x1E90FF; // Blue
|
|
127
|
+
default:
|
|
128
|
+
return 0x808080; // Gray
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Capitalize first letter of string
|
|
133
|
+
*
|
|
134
|
+
* @param str - String to capitalize
|
|
135
|
+
* @returns Capitalized string
|
|
136
|
+
*/
|
|
137
|
+
function capitalizeFirst(str) {
|
|
138
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=discord.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discord.js","sourceRoot":"","sources":["../../../src/lib/notifications/discord.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileType: utility
|
|
3
|
+
* @status: current
|
|
4
|
+
* @updated: 2025-12-07
|
|
5
|
+
* @tags: [notifications, adapters, epic-004, resilience]
|
|
6
|
+
* @related: [notification-hooks.ts, slack.ts, discord.ts, teams.ts, webhook.ts]
|
|
7
|
+
* @priority: high
|
|
8
|
+
* @complexity: low
|
|
9
|
+
* @dependencies: []
|
|
10
|
+
*/
|
|
11
|
+
import { NotificationPayload } from '../notification-hooks.js';
|
|
12
|
+
/**
|
|
13
|
+
* Standard notification adapter interface
|
|
14
|
+
* All adapters must implement this interface
|
|
15
|
+
*/
|
|
16
|
+
export interface NotificationAdapter {
|
|
17
|
+
/**
|
|
18
|
+
* Send a notification via this adapter
|
|
19
|
+
*
|
|
20
|
+
* @param config - Adapter-specific configuration
|
|
21
|
+
* @param payload - Notification payload
|
|
22
|
+
* @returns Promise<boolean> - True if notification sent successfully
|
|
23
|
+
*/
|
|
24
|
+
sendNotification(config: Record<string, string>, payload: NotificationPayload): Promise<boolean>;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Retry configuration for notification dispatches
|
|
28
|
+
*/
|
|
29
|
+
export interface RetryConfig {
|
|
30
|
+
maxAttempts: number;
|
|
31
|
+
initialDelayMs: number;
|
|
32
|
+
maxDelayMs: number;
|
|
33
|
+
backoffMultiplier: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Retry helper for notification dispatches
|
|
37
|
+
* Implements exponential backoff with configurable limits
|
|
38
|
+
*
|
|
39
|
+
* @param fn - Async function to retry
|
|
40
|
+
* @param config - Retry configuration
|
|
41
|
+
* @returns Promise with function result
|
|
42
|
+
*/
|
|
43
|
+
export declare function retryWithBackoff<T>(fn: () => Promise<T>, config?: Partial<RetryConfig>): Promise<T>;
|
|
44
|
+
/**
|
|
45
|
+
* Format severity with emoji for notifications
|
|
46
|
+
*
|
|
47
|
+
* @param severity - Severity level
|
|
48
|
+
* @returns Formatted severity string with emoji
|
|
49
|
+
*/
|
|
50
|
+
export declare function formatSeverity(severity: string): string;
|
|
51
|
+
/**
|
|
52
|
+
* Truncate text to a maximum length
|
|
53
|
+
*
|
|
54
|
+
* @param text - Text to truncate
|
|
55
|
+
* @param maxLength - Maximum length
|
|
56
|
+
* @returns Truncated text
|
|
57
|
+
*/
|
|
58
|
+
export declare function truncate(text: string, maxLength: number): string;
|
|
59
|
+
/**
|
|
60
|
+
* Format timestamp for display
|
|
61
|
+
*
|
|
62
|
+
* @param timestamp - ISO timestamp string
|
|
63
|
+
* @returns Formatted timestamp
|
|
64
|
+
*/
|
|
65
|
+
export declare function formatTimestamp(timestamp: string): string;
|
|
66
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/notifications/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;;OAMG;IACH,gBAAgB,CACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,OAAO,CAAC,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AASD;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAAC,CAAC,EACtC,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAChC,OAAO,CAAC,CAAC,CAAC,CA2BZ;AA0BD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAavD;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAKhE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAUzD"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileType: utility
|
|
3
|
+
* @status: current
|
|
4
|
+
* @updated: 2025-12-07
|
|
5
|
+
* @tags: [notifications, adapters, epic-004, resilience]
|
|
6
|
+
* @related: [notification-hooks.ts, slack.ts, discord.ts, teams.ts, webhook.ts]
|
|
7
|
+
* @priority: high
|
|
8
|
+
* @complexity: low
|
|
9
|
+
* @dependencies: []
|
|
10
|
+
*/
|
|
11
|
+
const DEFAULT_RETRY_CONFIG = {
|
|
12
|
+
maxAttempts: 3,
|
|
13
|
+
initialDelayMs: 1000,
|
|
14
|
+
maxDelayMs: 5000,
|
|
15
|
+
backoffMultiplier: 2
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Retry helper for notification dispatches
|
|
19
|
+
* Implements exponential backoff with configurable limits
|
|
20
|
+
*
|
|
21
|
+
* @param fn - Async function to retry
|
|
22
|
+
* @param config - Retry configuration
|
|
23
|
+
* @returns Promise with function result
|
|
24
|
+
*/
|
|
25
|
+
export async function retryWithBackoff(fn, config = {}) {
|
|
26
|
+
const finalConfig = { ...DEFAULT_RETRY_CONFIG, ...config };
|
|
27
|
+
let lastError = null;
|
|
28
|
+
let delay = finalConfig.initialDelayMs;
|
|
29
|
+
for (let attempt = 1; attempt <= finalConfig.maxAttempts; attempt++) {
|
|
30
|
+
try {
|
|
31
|
+
return await fn();
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
35
|
+
// Check if error is retryable (4xx errors are not retryable)
|
|
36
|
+
if (isNonRetryableError(error)) {
|
|
37
|
+
throw lastError;
|
|
38
|
+
}
|
|
39
|
+
if (attempt < finalConfig.maxAttempts) {
|
|
40
|
+
console.log(`[NotificationRetry] Attempt ${attempt}/${finalConfig.maxAttempts} failed, retrying in ${delay}ms...`);
|
|
41
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
42
|
+
// Exponential backoff with max delay cap
|
|
43
|
+
delay = Math.min(delay * finalConfig.backoffMultiplier, finalConfig.maxDelayMs);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
throw lastError || new Error('Retry failed with unknown error');
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Check if an error is non-retryable (client errors)
|
|
51
|
+
*
|
|
52
|
+
* @param error - Error to check
|
|
53
|
+
* @returns True if error should not be retried
|
|
54
|
+
*/
|
|
55
|
+
function isNonRetryableError(error) {
|
|
56
|
+
// Check for HTTP client errors (4xx)
|
|
57
|
+
if (error.response?.status) {
|
|
58
|
+
const status = error.response.status;
|
|
59
|
+
return status >= 400 && status < 500 && status !== 429; // Retry 429 (rate limit)
|
|
60
|
+
}
|
|
61
|
+
// Check for specific error messages
|
|
62
|
+
if (error instanceof Error) {
|
|
63
|
+
const message = error.message.toLowerCase();
|
|
64
|
+
if (message.includes('invalid') || message.includes('unauthorized') || message.includes('forbidden')) {
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Format severity with emoji for notifications
|
|
72
|
+
*
|
|
73
|
+
* @param severity - Severity level
|
|
74
|
+
* @returns Formatted severity string with emoji
|
|
75
|
+
*/
|
|
76
|
+
export function formatSeverity(severity) {
|
|
77
|
+
switch (severity) {
|
|
78
|
+
case 'critical':
|
|
79
|
+
return 'đ¨ Critical';
|
|
80
|
+
case 'high':
|
|
81
|
+
return 'â ī¸ High';
|
|
82
|
+
case 'medium':
|
|
83
|
+
return 'đĄ Medium';
|
|
84
|
+
case 'low':
|
|
85
|
+
return 'âšī¸ Low';
|
|
86
|
+
default:
|
|
87
|
+
return severity;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Truncate text to a maximum length
|
|
92
|
+
*
|
|
93
|
+
* @param text - Text to truncate
|
|
94
|
+
* @param maxLength - Maximum length
|
|
95
|
+
* @returns Truncated text
|
|
96
|
+
*/
|
|
97
|
+
export function truncate(text, maxLength) {
|
|
98
|
+
if (text.length <= maxLength) {
|
|
99
|
+
return text;
|
|
100
|
+
}
|
|
101
|
+
return text.substring(0, maxLength - 3) + '...';
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Format timestamp for display
|
|
105
|
+
*
|
|
106
|
+
* @param timestamp - ISO timestamp string
|
|
107
|
+
* @returns Formatted timestamp
|
|
108
|
+
*/
|
|
109
|
+
export function formatTimestamp(timestamp) {
|
|
110
|
+
const date = new Date(timestamp);
|
|
111
|
+
return date.toLocaleString('en-US', {
|
|
112
|
+
year: 'numeric',
|
|
113
|
+
month: 'short',
|
|
114
|
+
day: 'numeric',
|
|
115
|
+
hour: '2-digit',
|
|
116
|
+
minute: '2-digit',
|
|
117
|
+
timeZoneName: 'short'
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/notifications/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileType: utility
|
|
3
|
+
* @status: current
|
|
4
|
+
* @updated: 2025-12-07
|
|
5
|
+
* @tags: [notifications, slack, webhook, epic-004]
|
|
6
|
+
* @related: [index.ts, notification-hooks.ts, discord.ts, teams.ts, webhook.ts]
|
|
7
|
+
* @priority: high
|
|
8
|
+
* @complexity: low
|
|
9
|
+
* @dependencies: []
|
|
10
|
+
*/
|
|
11
|
+
import { NotificationPayload } from '../notification-hooks.js';
|
|
12
|
+
/**
|
|
13
|
+
* Send notification to Slack via webhook
|
|
14
|
+
*
|
|
15
|
+
* @param config - Slack configuration (must include webhook_url)
|
|
16
|
+
* @param payload - Notification payload
|
|
17
|
+
* @returns Promise<boolean> - True if notification sent successfully
|
|
18
|
+
*/
|
|
19
|
+
export declare function sendNotification(config: Record<string, string>, payload: NotificationPayload): Promise<boolean>;
|
|
20
|
+
//# sourceMappingURL=slack.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slack.d.ts","sourceRoot":"","sources":["../../../src/lib/notifications/slack.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AA6B/D;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,OAAO,CAAC,CAoClB"}
|