@link-assistant/hive-mind 0.39.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/CHANGELOG.md +20 -0
- package/LICENSE +24 -0
- package/README.md +769 -0
- package/package.json +58 -0
- package/src/agent.lib.mjs +705 -0
- package/src/agent.prompts.lib.mjs +196 -0
- package/src/buildUserMention.lib.mjs +71 -0
- package/src/claude-limits.lib.mjs +389 -0
- package/src/claude.lib.mjs +1445 -0
- package/src/claude.prompts.lib.mjs +203 -0
- package/src/codex.lib.mjs +552 -0
- package/src/codex.prompts.lib.mjs +194 -0
- package/src/config.lib.mjs +207 -0
- package/src/contributing-guidelines.lib.mjs +268 -0
- package/src/exit-handler.lib.mjs +205 -0
- package/src/git.lib.mjs +145 -0
- package/src/github-issue-creator.lib.mjs +246 -0
- package/src/github-linking.lib.mjs +152 -0
- package/src/github.batch.lib.mjs +272 -0
- package/src/github.graphql.lib.mjs +258 -0
- package/src/github.lib.mjs +1479 -0
- package/src/hive.config.lib.mjs +254 -0
- package/src/hive.mjs +1500 -0
- package/src/instrument.mjs +191 -0
- package/src/interactive-mode.lib.mjs +1000 -0
- package/src/lenv-reader.lib.mjs +206 -0
- package/src/lib.mjs +490 -0
- package/src/lino.lib.mjs +176 -0
- package/src/local-ci-checks.lib.mjs +324 -0
- package/src/memory-check.mjs +419 -0
- package/src/model-mapping.lib.mjs +145 -0
- package/src/model-validation.lib.mjs +278 -0
- package/src/opencode.lib.mjs +479 -0
- package/src/opencode.prompts.lib.mjs +194 -0
- package/src/protect-branch.mjs +159 -0
- package/src/review.mjs +433 -0
- package/src/reviewers-hive.mjs +643 -0
- package/src/sentry.lib.mjs +284 -0
- package/src/solve.auto-continue.lib.mjs +568 -0
- package/src/solve.auto-pr.lib.mjs +1374 -0
- package/src/solve.branch-errors.lib.mjs +341 -0
- package/src/solve.branch.lib.mjs +230 -0
- package/src/solve.config.lib.mjs +342 -0
- package/src/solve.error-handlers.lib.mjs +256 -0
- package/src/solve.execution.lib.mjs +291 -0
- package/src/solve.feedback.lib.mjs +436 -0
- package/src/solve.mjs +1128 -0
- package/src/solve.preparation.lib.mjs +210 -0
- package/src/solve.repo-setup.lib.mjs +114 -0
- package/src/solve.repository.lib.mjs +961 -0
- package/src/solve.results.lib.mjs +558 -0
- package/src/solve.session.lib.mjs +135 -0
- package/src/solve.validation.lib.mjs +325 -0
- package/src/solve.watch.lib.mjs +572 -0
- package/src/start-screen.mjs +324 -0
- package/src/task.mjs +308 -0
- package/src/telegram-bot.mjs +1481 -0
- package/src/telegram-markdown.lib.mjs +64 -0
- package/src/usage-limit.lib.mjs +218 -0
- package/src/version.lib.mjs +41 -0
- package/src/youtrack/solve.youtrack.lib.mjs +116 -0
- package/src/youtrack/youtrack-sync.mjs +219 -0
- package/src/youtrack/youtrack.lib.mjs +425 -0
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
// Sentry integration library for hive-mind
|
|
2
|
+
import { isSentryEnabled, captureException, captureMessage, startTransaction } from './instrument.mjs';
|
|
3
|
+
|
|
4
|
+
// Lazy import of Sentry to handle cases where it's not installed
|
|
5
|
+
let Sentry = null;
|
|
6
|
+
const getSentry = async () => {
|
|
7
|
+
if (!Sentry) {
|
|
8
|
+
try {
|
|
9
|
+
Sentry = await import('@sentry/node');
|
|
10
|
+
} catch {
|
|
11
|
+
// Sentry not installed, return null
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return Sentry;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
// Flag to track if Sentry should be disabled
|
|
19
|
+
let sentryDisabled = false;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Initialize Sentry integration
|
|
23
|
+
* This should be called early in the application lifecycle
|
|
24
|
+
* @param {Object} options - Configuration options
|
|
25
|
+
* @param {boolean} options.noSentry - Disable Sentry if true
|
|
26
|
+
* @param {boolean} options.debug - Enable debug mode
|
|
27
|
+
* @param {string} options.environment - Environment name (production, development, etc)
|
|
28
|
+
*/
|
|
29
|
+
export const initializeSentry = async (options = {}) => {
|
|
30
|
+
// Check if --no-sentry flag is present
|
|
31
|
+
if (options.noSentry || process.argv.includes('--no-sentry')) {
|
|
32
|
+
sentryDisabled = true;
|
|
33
|
+
if (options.debug) {
|
|
34
|
+
console.log('ℹ️ Sentry is disabled via --no-sentry flag');
|
|
35
|
+
}
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Sentry is already initialized in instrument.mjs
|
|
40
|
+
// This function is for additional runtime configuration
|
|
41
|
+
if (isSentryEnabled()) {
|
|
42
|
+
const sentry = await getSentry();
|
|
43
|
+
if (sentry) {
|
|
44
|
+
// Set user context if available
|
|
45
|
+
if (process.env.USER || process.env.USERNAME) {
|
|
46
|
+
sentry.setUser({
|
|
47
|
+
username: process.env.USER || process.env.USERNAME,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Set additional tags
|
|
52
|
+
sentry.setTags({
|
|
53
|
+
node_version: process.version,
|
|
54
|
+
platform: process.platform,
|
|
55
|
+
arch: process.arch,
|
|
56
|
+
hive_mind_version: options.version || process.env.npm_package_version || 'unknown',
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
if (options.debug) {
|
|
60
|
+
console.log('✅ Sentry integration configured');
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Wrap a function with Sentry error tracking
|
|
68
|
+
* @param {Function} fn - Function to wrap
|
|
69
|
+
* @param {string} name - Name of the operation
|
|
70
|
+
* @param {string} op - Operation type (default: 'task')
|
|
71
|
+
* @returns {Function} Wrapped function
|
|
72
|
+
*/
|
|
73
|
+
export const withSentry = (fn, name, op = 'task') => {
|
|
74
|
+
return async (...args) => {
|
|
75
|
+
if (!isSentryEnabled() || sentryDisabled) {
|
|
76
|
+
return fn(...args);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const transaction = startTransaction(name, op);
|
|
80
|
+
|
|
81
|
+
try {
|
|
82
|
+
const result = await fn(...args);
|
|
83
|
+
transaction.setStatus('ok');
|
|
84
|
+
return result;
|
|
85
|
+
} catch (error) {
|
|
86
|
+
transaction.setStatus('internal_error');
|
|
87
|
+
captureException(error, {
|
|
88
|
+
operation: name,
|
|
89
|
+
args: args.length > 0 ? `${args.length} arguments` : 'no arguments',
|
|
90
|
+
});
|
|
91
|
+
throw error;
|
|
92
|
+
} finally {
|
|
93
|
+
// In Sentry v10, use end() instead of finish()
|
|
94
|
+
if (transaction.end) {
|
|
95
|
+
transaction.end();
|
|
96
|
+
} else if (transaction.finish) {
|
|
97
|
+
// Fallback for compatibility
|
|
98
|
+
transaction.finish();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Create a Sentry span for tracking a specific operation
|
|
106
|
+
* @param {string} name - Name of the span
|
|
107
|
+
* @param {Function} callback - Callback to execute within the span
|
|
108
|
+
* @returns {Promise} Result of the callback
|
|
109
|
+
*/
|
|
110
|
+
export const withSpan = async (name, callback) => {
|
|
111
|
+
if (!isSentryEnabled() || sentryDisabled) {
|
|
112
|
+
return callback();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const sentry = await getSentry();
|
|
116
|
+
if (!sentry) {
|
|
117
|
+
return callback();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return sentry.startSpan({
|
|
121
|
+
name,
|
|
122
|
+
op: 'function',
|
|
123
|
+
}, async () => {
|
|
124
|
+
return callback();
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Log a message to Sentry
|
|
130
|
+
* @param {string} message - Message to log
|
|
131
|
+
* @param {string} level - Log level (debug, info, warning, error, fatal)
|
|
132
|
+
* @param {Object} context - Additional context
|
|
133
|
+
*/
|
|
134
|
+
export const logToSentry = (message, level = 'info', context = {}) => {
|
|
135
|
+
if (!isSentryEnabled() || sentryDisabled) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
captureMessage(message, level, context);
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Report an error to Sentry
|
|
144
|
+
* Use this for actual errors that indicate something went wrong
|
|
145
|
+
* @param {Error} error - Error to capture
|
|
146
|
+
* @param {Object} context - Additional context
|
|
147
|
+
*/
|
|
148
|
+
export const reportError = (error, context = {}) => {
|
|
149
|
+
if (!isSentryEnabled() || sentryDisabled) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
captureException(error, { ...context, level: 'error' });
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Report a warning to Sentry
|
|
158
|
+
* Use this for non-critical issues that should be tracked but don't indicate failure
|
|
159
|
+
* @param {string|Error} warning - Warning message or error object
|
|
160
|
+
* @param {Object} context - Additional context
|
|
161
|
+
*/
|
|
162
|
+
export const reportWarning = (warning, context = {}) => {
|
|
163
|
+
if (!isSentryEnabled() || sentryDisabled) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Convert string warnings to Error objects for better stack traces
|
|
168
|
+
const warningError = typeof warning === 'string' ? new Error(warning) : warning;
|
|
169
|
+
captureException(warningError, { ...context, level: 'warning' });
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Add breadcrumb for better error context
|
|
174
|
+
* @param {Object} breadcrumb - Breadcrumb data
|
|
175
|
+
*/
|
|
176
|
+
export const addBreadcrumb = async (breadcrumb) => {
|
|
177
|
+
if (!isSentryEnabled() || sentryDisabled) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const sentry = await getSentry();
|
|
182
|
+
if (sentry) {
|
|
183
|
+
sentry.addBreadcrumb(breadcrumb);
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Set user context for Sentry
|
|
189
|
+
* @param {Object} user - User data
|
|
190
|
+
*/
|
|
191
|
+
export const setUserContext = async (user) => {
|
|
192
|
+
if (!isSentryEnabled() || sentryDisabled) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const sentry = await getSentry();
|
|
197
|
+
if (sentry) {
|
|
198
|
+
sentry.setUser(user);
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Set extra context for Sentry
|
|
204
|
+
* @param {string} key - Context key
|
|
205
|
+
* @param {any} value - Context value
|
|
206
|
+
*/
|
|
207
|
+
export const setExtraContext = async (key, value) => {
|
|
208
|
+
if (!isSentryEnabled() || sentryDisabled) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const sentry = await getSentry();
|
|
213
|
+
if (sentry) {
|
|
214
|
+
sentry.setExtra(key, value);
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Set tags for Sentry
|
|
220
|
+
* @param {Object} tags - Tags to set
|
|
221
|
+
*/
|
|
222
|
+
export const setTags = async (tags) => {
|
|
223
|
+
if (!isSentryEnabled() || sentryDisabled) {
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const sentry = await getSentry();
|
|
228
|
+
if (sentry) {
|
|
229
|
+
sentry.setTags(tags);
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Flush Sentry events before exit
|
|
235
|
+
* @param {number} timeout - Timeout in milliseconds (default: 2000)
|
|
236
|
+
* @returns {Promise} Promise that resolves when flush is complete
|
|
237
|
+
*/
|
|
238
|
+
export const flushSentry = async (timeout = 2000) => {
|
|
239
|
+
if (!isSentryEnabled() || sentryDisabled) {
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const sentry = await getSentry();
|
|
244
|
+
if (!sentry) {
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
try {
|
|
249
|
+
await sentry.flush(timeout);
|
|
250
|
+
} catch (error) {
|
|
251
|
+
// Silently fail if flush fails
|
|
252
|
+
if (process.env.DEBUG === 'true') {
|
|
253
|
+
console.error('Failed to flush Sentry events:', error.message);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Close Sentry client
|
|
260
|
+
* @param {number} timeout - Timeout in milliseconds (default: 2000)
|
|
261
|
+
* @returns {Promise} Promise that resolves when close is complete
|
|
262
|
+
*/
|
|
263
|
+
export const closeSentry = async (timeout = 2000) => {
|
|
264
|
+
if (!isSentryEnabled() || sentryDisabled) {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const sentry = await getSentry();
|
|
269
|
+
if (!sentry) {
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
try {
|
|
274
|
+
await sentry.close(timeout);
|
|
275
|
+
} catch (error) {
|
|
276
|
+
// Silently fail if close fails
|
|
277
|
+
if (process.env.DEBUG === 'true') {
|
|
278
|
+
console.error('Failed to close Sentry:', error.message);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
// Export the Sentry check function
|
|
284
|
+
export { isSentryEnabled };
|