@link-assistant/hive-mind 0.46.1 → 0.47.1
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 -15
- package/README.md +42 -8
- package/package.json +16 -3
- package/src/agent.lib.mjs +49 -70
- package/src/agent.prompts.lib.mjs +6 -20
- package/src/buildUserMention.lib.mjs +4 -17
- package/src/claude-limits.lib.mjs +15 -15
- package/src/claude.lib.mjs +617 -626
- package/src/claude.prompts.lib.mjs +7 -22
- package/src/codex.lib.mjs +39 -71
- package/src/codex.prompts.lib.mjs +6 -20
- package/src/config.lib.mjs +3 -16
- package/src/contributing-guidelines.lib.mjs +5 -18
- package/src/exit-handler.lib.mjs +4 -4
- package/src/git.lib.mjs +7 -7
- package/src/github-issue-creator.lib.mjs +17 -17
- package/src/github-linking.lib.mjs +8 -33
- package/src/github.batch.lib.mjs +20 -16
- package/src/github.graphql.lib.mjs +18 -18
- package/src/github.lib.mjs +89 -91
- package/src/hive.config.lib.mjs +50 -50
- package/src/hive.mjs +1293 -1296
- package/src/instrument.mjs +7 -11
- package/src/interactive-mode.lib.mjs +112 -138
- package/src/lenv-reader.lib.mjs +1 -6
- package/src/lib.mjs +36 -45
- package/src/lino.lib.mjs +2 -2
- package/src/local-ci-checks.lib.mjs +15 -14
- package/src/memory-check.mjs +52 -60
- package/src/model-mapping.lib.mjs +25 -32
- package/src/model-validation.lib.mjs +31 -31
- package/src/opencode.lib.mjs +37 -62
- package/src/opencode.prompts.lib.mjs +7 -21
- package/src/protect-branch.mjs +14 -15
- package/src/review.mjs +28 -27
- package/src/reviewers-hive.mjs +64 -69
- package/src/sentry.lib.mjs +13 -10
- package/src/solve.auto-continue.lib.mjs +48 -38
- package/src/solve.auto-pr.lib.mjs +111 -69
- package/src/solve.branch-errors.lib.mjs +17 -46
- package/src/solve.branch.lib.mjs +16 -23
- package/src/solve.config.lib.mjs +263 -261
- package/src/solve.error-handlers.lib.mjs +21 -79
- package/src/solve.execution.lib.mjs +10 -18
- package/src/solve.feedback.lib.mjs +25 -46
- package/src/solve.mjs +59 -60
- package/src/solve.preparation.lib.mjs +10 -36
- package/src/solve.repo-setup.lib.mjs +4 -19
- package/src/solve.repository.lib.mjs +37 -37
- package/src/solve.results.lib.mjs +32 -46
- package/src/solve.session.lib.mjs +7 -22
- package/src/solve.validation.lib.mjs +19 -17
- package/src/solve.watch.lib.mjs +20 -33
- package/src/start-screen.mjs +24 -24
- package/src/task.mjs +38 -44
- package/src/telegram-bot.mjs +125 -121
- package/src/telegram-top-command.lib.mjs +32 -48
- package/src/usage-limit.lib.mjs +9 -13
- package/src/version-info.lib.mjs +1 -1
- package/src/version.lib.mjs +1 -1
- package/src/youtrack/solve.youtrack.lib.mjs +3 -8
- package/src/youtrack/youtrack-sync.mjs +8 -14
- package/src/youtrack/youtrack.lib.mjs +26 -28
package/src/agent.lib.mjs
CHANGED
|
@@ -29,7 +29,7 @@ const { fetchModelInfo } = claudeLib;
|
|
|
29
29
|
* @param {string} output - Raw stdout output from agent command
|
|
30
30
|
* @returns {Object} Aggregated token usage and cost data
|
|
31
31
|
*/
|
|
32
|
-
export const parseAgentTokenUsage =
|
|
32
|
+
export const parseAgentTokenUsage = output => {
|
|
33
33
|
const usage = {
|
|
34
34
|
inputTokens: 0,
|
|
35
35
|
outputTokens: 0,
|
|
@@ -37,7 +37,7 @@ export const parseAgentTokenUsage = (output) => {
|
|
|
37
37
|
cacheReadTokens: 0,
|
|
38
38
|
cacheWriteTokens: 0,
|
|
39
39
|
totalCost: 0,
|
|
40
|
-
stepCount: 0
|
|
40
|
+
stepCount: 0,
|
|
41
41
|
};
|
|
42
42
|
|
|
43
43
|
// Try to parse each line as JSON (agent outputs NDJSON format)
|
|
@@ -114,17 +114,17 @@ export const calculateAgentPricing = async (modelId, tokenUsage) => {
|
|
|
114
114
|
inputPerMillion: cost.input || 0,
|
|
115
115
|
outputPerMillion: cost.output || 0,
|
|
116
116
|
cacheReadPerMillion: cost.cache_read || 0,
|
|
117
|
-
cacheWritePerMillion: cost.cache_write || 0
|
|
117
|
+
cacheWritePerMillion: cost.cache_write || 0,
|
|
118
118
|
},
|
|
119
119
|
tokenUsage,
|
|
120
120
|
breakdown: {
|
|
121
121
|
input: inputCost,
|
|
122
122
|
output: outputCost,
|
|
123
123
|
cacheRead: cacheReadCost,
|
|
124
|
-
cacheWrite: cacheWriteCost
|
|
124
|
+
cacheWrite: cacheWriteCost,
|
|
125
125
|
},
|
|
126
126
|
totalCostUSD: totalCost,
|
|
127
|
-
isFreeModel: cost.input === 0 && cost.output === 0
|
|
127
|
+
isFreeModel: cost.input === 0 && cost.output === 0,
|
|
128
128
|
};
|
|
129
129
|
}
|
|
130
130
|
|
|
@@ -135,7 +135,7 @@ export const calculateAgentPricing = async (modelId, tokenUsage) => {
|
|
|
135
135
|
provider: 'Unknown',
|
|
136
136
|
tokenUsage,
|
|
137
137
|
totalCostUSD: null,
|
|
138
|
-
error: 'Model not found in models.dev API'
|
|
138
|
+
error: 'Model not found in models.dev API',
|
|
139
139
|
};
|
|
140
140
|
} catch (error) {
|
|
141
141
|
// Error fetching pricing, return with error info
|
|
@@ -144,23 +144,23 @@ export const calculateAgentPricing = async (modelId, tokenUsage) => {
|
|
|
144
144
|
modelName,
|
|
145
145
|
tokenUsage,
|
|
146
146
|
totalCostUSD: null,
|
|
147
|
-
error: error.message
|
|
147
|
+
error: error.message,
|
|
148
148
|
};
|
|
149
149
|
}
|
|
150
150
|
};
|
|
151
151
|
|
|
152
152
|
// Model mapping to translate aliases to full model IDs for Agent
|
|
153
153
|
// Agent uses OpenCode's JSON interface and models
|
|
154
|
-
export const mapModelToId =
|
|
154
|
+
export const mapModelToId = model => {
|
|
155
155
|
const modelMap = {
|
|
156
|
-
|
|
156
|
+
grok: 'opencode/grok-code',
|
|
157
157
|
'grok-code': 'opencode/grok-code',
|
|
158
158
|
'grok-code-fast-1': 'opencode/grok-code',
|
|
159
159
|
'big-pickle': 'opencode/big-pickle',
|
|
160
160
|
'gpt-5-nano': 'openai/gpt-5-nano',
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
161
|
+
sonnet: 'anthropic/claude-3-5-sonnet',
|
|
162
|
+
haiku: 'anthropic/claude-3-5-haiku',
|
|
163
|
+
opus: 'anthropic/claude-3-opus',
|
|
164
164
|
'gemini-3-pro': 'google/gemini-3-pro',
|
|
165
165
|
};
|
|
166
166
|
|
|
@@ -209,7 +209,9 @@ export const validateAgentConnection = async (model = 'grok-code-fast-1') => {
|
|
|
209
209
|
|
|
210
210
|
if (stderr.includes('auth') || stderr.includes('login')) {
|
|
211
211
|
await log('❌ Agent authentication failed', { level: 'error' });
|
|
212
|
-
await log(' 💡 Note: Agent uses OpenCode models. For premium models, you may need: opencode auth', {
|
|
212
|
+
await log(' 💡 Note: Agent uses OpenCode models. For premium models, you may need: opencode auth', {
|
|
213
|
+
level: 'error',
|
|
214
|
+
});
|
|
213
215
|
return false;
|
|
214
216
|
}
|
|
215
217
|
|
|
@@ -223,7 +225,9 @@ export const validateAgentConnection = async (model = 'grok-code-fast-1') => {
|
|
|
223
225
|
return true;
|
|
224
226
|
} catch (error) {
|
|
225
227
|
await log(`❌ Failed to validate Agent connection: ${error.message}`, { level: 'error' });
|
|
226
|
-
await log(' 💡 Make sure @link-assistant/agent is installed globally: bun install -g @link-assistant/agent', {
|
|
228
|
+
await log(' 💡 Make sure @link-assistant/agent is installed globally: bun install -g @link-assistant/agent', {
|
|
229
|
+
level: 'error',
|
|
230
|
+
});
|
|
227
231
|
return false;
|
|
228
232
|
}
|
|
229
233
|
};
|
|
@@ -240,28 +244,8 @@ export const handleAgentRuntimeSwitch = async () => {
|
|
|
240
244
|
};
|
|
241
245
|
|
|
242
246
|
// Main function to execute Agent with prompts and settings
|
|
243
|
-
export const executeAgent = async
|
|
244
|
-
const {
|
|
245
|
-
issueUrl,
|
|
246
|
-
issueNumber,
|
|
247
|
-
prNumber,
|
|
248
|
-
prUrl,
|
|
249
|
-
branchName,
|
|
250
|
-
tempDir,
|
|
251
|
-
isContinueMode,
|
|
252
|
-
mergeStateStatus,
|
|
253
|
-
forkedRepo,
|
|
254
|
-
feedbackLines,
|
|
255
|
-
forkActionsUrl,
|
|
256
|
-
owner,
|
|
257
|
-
repo,
|
|
258
|
-
argv,
|
|
259
|
-
log,
|
|
260
|
-
formatAligned,
|
|
261
|
-
getResourceSnapshot,
|
|
262
|
-
agentPath = 'agent',
|
|
263
|
-
$
|
|
264
|
-
} = params;
|
|
247
|
+
export const executeAgent = async params => {
|
|
248
|
+
const { issueUrl, issueNumber, prNumber, prUrl, branchName, tempDir, isContinueMode, mergeStateStatus, forkedRepo, feedbackLines, forkActionsUrl, owner, repo, argv, log, formatAligned, getResourceSnapshot, agentPath = 'agent', $ } = params;
|
|
265
249
|
|
|
266
250
|
// Import prompt building functions from agent.prompts.lib.mjs
|
|
267
251
|
const { buildUserPrompt, buildSystemPrompt } = await import('./agent.prompts.lib.mjs');
|
|
@@ -281,7 +265,7 @@ export const executeAgent = async (params) => {
|
|
|
281
265
|
forkActionsUrl,
|
|
282
266
|
owner,
|
|
283
267
|
repo,
|
|
284
|
-
argv
|
|
268
|
+
argv,
|
|
285
269
|
});
|
|
286
270
|
|
|
287
271
|
// Build the system prompt
|
|
@@ -294,7 +278,7 @@ export const executeAgent = async (params) => {
|
|
|
294
278
|
tempDir,
|
|
295
279
|
isContinueMode,
|
|
296
280
|
forkedRepo,
|
|
297
|
-
argv
|
|
281
|
+
argv,
|
|
298
282
|
});
|
|
299
283
|
|
|
300
284
|
// Log prompt details in verbose mode
|
|
@@ -331,25 +315,12 @@ export const executeAgent = async (params) => {
|
|
|
331
315
|
forkedRepo,
|
|
332
316
|
feedbackLines,
|
|
333
317
|
agentPath,
|
|
334
|
-
|
|
318
|
+
$,
|
|
335
319
|
});
|
|
336
320
|
};
|
|
337
321
|
|
|
338
|
-
export const executeAgentCommand = async
|
|
339
|
-
const {
|
|
340
|
-
tempDir,
|
|
341
|
-
branchName,
|
|
342
|
-
prompt,
|
|
343
|
-
systemPrompt,
|
|
344
|
-
argv,
|
|
345
|
-
log,
|
|
346
|
-
formatAligned,
|
|
347
|
-
getResourceSnapshot,
|
|
348
|
-
forkedRepo,
|
|
349
|
-
feedbackLines,
|
|
350
|
-
agentPath,
|
|
351
|
-
$
|
|
352
|
-
} = params;
|
|
322
|
+
export const executeAgentCommand = async params => {
|
|
323
|
+
const { tempDir, branchName, prompt, systemPrompt, argv, log, formatAligned, getResourceSnapshot, forkedRepo, feedbackLines, agentPath, $ } = params;
|
|
353
324
|
|
|
354
325
|
// Retry configuration
|
|
355
326
|
const maxRetries = 3;
|
|
@@ -411,7 +382,7 @@ export const executeAgentCommand = async (params) => {
|
|
|
411
382
|
// Pipe the prompt file to agent via stdin
|
|
412
383
|
execCommand = $({
|
|
413
384
|
cwd: tempDir,
|
|
414
|
-
mirror: false
|
|
385
|
+
mirror: false,
|
|
415
386
|
})`cat ${promptFile} | ${agentPath} --model ${mappedModel}`;
|
|
416
387
|
|
|
417
388
|
await log(`${formatAligned('📋', 'Command details:', '')}`);
|
|
@@ -458,7 +429,7 @@ export const executeAgentCommand = async (params) => {
|
|
|
458
429
|
// 1. Non-zero exit code (agent returns 1 on errors)
|
|
459
430
|
// 2. Explicit JSON error messages from agent (type: "error")
|
|
460
431
|
// 3. Usage limit detection (handled separately)
|
|
461
|
-
const detectAgentErrors =
|
|
432
|
+
const detectAgentErrors = stdoutOutput => {
|
|
462
433
|
const lines = stdoutOutput.split('\n');
|
|
463
434
|
|
|
464
435
|
for (const line of lines) {
|
|
@@ -489,12 +460,12 @@ export const executeAgentCommand = async (params) => {
|
|
|
489
460
|
type: 'error',
|
|
490
461
|
exitCode,
|
|
491
462
|
errorDetectedInOutput: outputError.detected,
|
|
492
|
-
errorType: outputError.detected ? outputError.type :
|
|
463
|
+
errorType: outputError.detected ? outputError.type : exitCode !== 0 ? 'NonZeroExitCode' : null,
|
|
493
464
|
errorMatch: outputError.detected ? outputError.match : null,
|
|
494
465
|
message: null,
|
|
495
466
|
sessionId,
|
|
496
467
|
limitReached: false,
|
|
497
|
-
limitResetTime: null
|
|
468
|
+
limitResetTime: null,
|
|
498
469
|
};
|
|
499
470
|
|
|
500
471
|
// Check for usage limit errors first (more specific)
|
|
@@ -511,7 +482,7 @@ export const executeAgentCommand = async (params) => {
|
|
|
511
482
|
tool: 'Agent',
|
|
512
483
|
resetTime: limitInfo.resetTime,
|
|
513
484
|
sessionId,
|
|
514
|
-
resumeCommand: sessionId ? `${process.argv[0]} ${process.argv[1]} ${argv.url} --resume ${sessionId}` : null
|
|
485
|
+
resumeCommand: sessionId ? `${process.argv[0]} ${process.argv[1]} ${argv.url} --resume ${sessionId}` : null,
|
|
515
486
|
});
|
|
516
487
|
|
|
517
488
|
for (const line of messageLines) {
|
|
@@ -544,10 +515,10 @@ export const executeAgentCommand = async (params) => {
|
|
|
544
515
|
sessionId,
|
|
545
516
|
limitReached,
|
|
546
517
|
limitResetTime,
|
|
547
|
-
errorInfo,
|
|
518
|
+
errorInfo, // Include structured error information
|
|
548
519
|
tokenUsage,
|
|
549
520
|
pricingInfo,
|
|
550
|
-
publicPricingEstimate: pricingInfo.totalCostUSD
|
|
521
|
+
publicPricingEstimate: pricingInfo.totalCostUSD,
|
|
551
522
|
};
|
|
552
523
|
}
|
|
553
524
|
|
|
@@ -590,14 +561,14 @@ export const executeAgentCommand = async (params) => {
|
|
|
590
561
|
limitResetTime,
|
|
591
562
|
tokenUsage,
|
|
592
563
|
pricingInfo,
|
|
593
|
-
publicPricingEstimate: pricingInfo.totalCostUSD
|
|
564
|
+
publicPricingEstimate: pricingInfo.totalCostUSD,
|
|
594
565
|
};
|
|
595
566
|
} catch (error) {
|
|
596
567
|
reportError(error, {
|
|
597
568
|
context: 'execute_agent',
|
|
598
569
|
command: params.command,
|
|
599
570
|
agentPath: params.agentPath,
|
|
600
|
-
operation: 'run_agent_command'
|
|
571
|
+
operation: 'run_agent_command',
|
|
601
572
|
});
|
|
602
573
|
|
|
603
574
|
await log(`\n\n❌ Error executing Agent command: ${error.message}`, { level: 'error' });
|
|
@@ -608,7 +579,7 @@ export const executeAgentCommand = async (params) => {
|
|
|
608
579
|
limitResetTime: null,
|
|
609
580
|
tokenUsage: null,
|
|
610
581
|
pricingInfo: null,
|
|
611
|
-
publicPricingEstimate: null
|
|
582
|
+
publicPricingEstimate: null,
|
|
612
583
|
};
|
|
613
584
|
}
|
|
614
585
|
};
|
|
@@ -649,13 +620,19 @@ export const checkForUncommittedChanges = async (tempDir, owner, repo, branchNam
|
|
|
649
620
|
if (pushResult.code === 0) {
|
|
650
621
|
await log('✅ Changes pushed successfully');
|
|
651
622
|
} else {
|
|
652
|
-
await log(`⚠️ Warning: Could not push changes: ${pushResult.stderr?.toString().trim()}`, {
|
|
623
|
+
await log(`⚠️ Warning: Could not push changes: ${pushResult.stderr?.toString().trim()}`, {
|
|
624
|
+
level: 'warning',
|
|
625
|
+
});
|
|
653
626
|
}
|
|
654
627
|
} else {
|
|
655
|
-
await log(`⚠️ Warning: Could not commit changes: ${commitResult.stderr?.toString().trim()}`, {
|
|
628
|
+
await log(`⚠️ Warning: Could not commit changes: ${commitResult.stderr?.toString().trim()}`, {
|
|
629
|
+
level: 'warning',
|
|
630
|
+
});
|
|
656
631
|
}
|
|
657
632
|
} else {
|
|
658
|
-
await log(`⚠️ Warning: Could not stage changes: ${addResult.stderr?.toString().trim()}`, {
|
|
633
|
+
await log(`⚠️ Warning: Could not stage changes: ${addResult.stderr?.toString().trim()}`, {
|
|
634
|
+
level: 'warning',
|
|
635
|
+
});
|
|
659
636
|
}
|
|
660
637
|
return false;
|
|
661
638
|
} else if (autoRestartEnabled) {
|
|
@@ -679,14 +656,16 @@ export const checkForUncommittedChanges = async (tempDir, owner, repo, branchNam
|
|
|
679
656
|
return false;
|
|
680
657
|
}
|
|
681
658
|
} else {
|
|
682
|
-
await log(`⚠️ Warning: Could not check git status: ${gitStatusResult.stderr?.toString().trim()}`, {
|
|
659
|
+
await log(`⚠️ Warning: Could not check git status: ${gitStatusResult.stderr?.toString().trim()}`, {
|
|
660
|
+
level: 'warning',
|
|
661
|
+
});
|
|
683
662
|
return false;
|
|
684
663
|
}
|
|
685
664
|
} catch (gitError) {
|
|
686
665
|
reportError(gitError, {
|
|
687
666
|
context: 'check_uncommitted_changes_agent',
|
|
688
667
|
tempDir,
|
|
689
|
-
operation: 'git_status_check'
|
|
668
|
+
operation: 'git_status_check',
|
|
690
669
|
});
|
|
691
670
|
await log(`⚠️ Warning: Error checking for uncommitted changes: ${gitError.message}`, { level: 'warning' });
|
|
692
671
|
return false;
|
|
@@ -701,5 +680,5 @@ export default {
|
|
|
701
680
|
executeAgentCommand,
|
|
702
681
|
checkForUncommittedChanges,
|
|
703
682
|
parseAgentTokenUsage,
|
|
704
|
-
calculateAgentPricing
|
|
683
|
+
calculateAgentPricing,
|
|
705
684
|
};
|
|
@@ -8,22 +8,8 @@
|
|
|
8
8
|
* @param {Object} params - Parameters for building the user prompt
|
|
9
9
|
* @returns {string} The formatted user prompt
|
|
10
10
|
*/
|
|
11
|
-
export const buildUserPrompt =
|
|
12
|
-
const {
|
|
13
|
-
issueUrl,
|
|
14
|
-
issueNumber,
|
|
15
|
-
prNumber,
|
|
16
|
-
prUrl,
|
|
17
|
-
branchName,
|
|
18
|
-
tempDir,
|
|
19
|
-
isContinueMode,
|
|
20
|
-
forkedRepo,
|
|
21
|
-
feedbackLines,
|
|
22
|
-
forkActionsUrl,
|
|
23
|
-
owner,
|
|
24
|
-
repo,
|
|
25
|
-
argv
|
|
26
|
-
} = params;
|
|
11
|
+
export const buildUserPrompt = params => {
|
|
12
|
+
const { issueUrl, issueNumber, prNumber, prUrl, branchName, tempDir, isContinueMode, forkedRepo, feedbackLines, forkActionsUrl, owner, repo, argv } = params;
|
|
27
13
|
|
|
28
14
|
const promptLines = [];
|
|
29
15
|
|
|
@@ -70,7 +56,7 @@ export const buildUserPrompt = (params) => {
|
|
|
70
56
|
low: 'Think.',
|
|
71
57
|
medium: 'Think hard.',
|
|
72
58
|
high: 'Think harder.',
|
|
73
|
-
max: 'Ultrathink.'
|
|
59
|
+
max: 'Ultrathink.',
|
|
74
60
|
};
|
|
75
61
|
promptLines.push(thinkMessages[argv.think]);
|
|
76
62
|
}
|
|
@@ -87,7 +73,7 @@ export const buildUserPrompt = (params) => {
|
|
|
87
73
|
* @param {Object} params - Parameters for building the prompt
|
|
88
74
|
* @returns {string} The formatted system prompt
|
|
89
75
|
*/
|
|
90
|
-
export const buildSystemPrompt =
|
|
76
|
+
export const buildSystemPrompt = params => {
|
|
91
77
|
const { owner, repo, issueNumber, prNumber, branchName, argv } = params;
|
|
92
78
|
|
|
93
79
|
// Build thinking instruction based on --think level
|
|
@@ -97,7 +83,7 @@ export const buildSystemPrompt = (params) => {
|
|
|
97
83
|
low: 'You always think on every step.',
|
|
98
84
|
medium: 'You always think hard on every step.',
|
|
99
85
|
high: 'You always think harder on every step.',
|
|
100
|
-
max: 'You always ultrathink on every step.'
|
|
86
|
+
max: 'You always ultrathink on every step.',
|
|
101
87
|
};
|
|
102
88
|
thinkLine = `\n${thinkMessages[argv.think]}\n`;
|
|
103
89
|
}
|
|
@@ -192,5 +178,5 @@ GitHub CLI command patterns.
|
|
|
192
178
|
// Export all functions as default object too
|
|
193
179
|
export default {
|
|
194
180
|
buildUserPrompt,
|
|
195
|
-
buildSystemPrompt
|
|
181
|
+
buildSystemPrompt,
|
|
196
182
|
};
|
|
@@ -13,14 +13,7 @@
|
|
|
13
13
|
* @param {'HTML'|'Markdown'|'MarkdownV2'} [options.parseMode='HTML'] - The parse mode to use.
|
|
14
14
|
* @returns {string} A formatted mention link for the user.
|
|
15
15
|
*/
|
|
16
|
-
export function buildUserMention({
|
|
17
|
-
user,
|
|
18
|
-
id: idParam,
|
|
19
|
-
username: usernameParam,
|
|
20
|
-
first_name: firstNameParam,
|
|
21
|
-
last_name: lastNameParam,
|
|
22
|
-
parseMode = 'HTML',
|
|
23
|
-
}) {
|
|
16
|
+
export function buildUserMention({ user, id: idParam, username: usernameParam, first_name: firstNameParam, last_name: lastNameParam, parseMode = 'HTML' }) {
|
|
24
17
|
// Derive core fields from `user` with inline overrides
|
|
25
18
|
const id = idParam ?? user?.id;
|
|
26
19
|
const username = usernameParam ?? user?.username;
|
|
@@ -34,10 +27,8 @@ export function buildUserMention({
|
|
|
34
27
|
// Trim all string names, then filter out empty values
|
|
35
28
|
const raw = [firstName, lastName];
|
|
36
29
|
// Trim whitespace and Hangul filler (ㅤ) characters from names
|
|
37
|
-
const trimmedAll = raw.map((rawName)
|
|
38
|
-
|
|
39
|
-
));
|
|
40
|
-
const cleaned = trimmedAll.filter((name) => typeof name === 'string' && name.length > 0);
|
|
30
|
+
const trimmedAll = raw.map(rawName => (typeof rawName === 'string' ? rawName.trim().replace(/^[\s\t\n\rㅤ]+|[\s\t\n\rㅤ]+$/g, '') : rawName));
|
|
31
|
+
const cleaned = trimmedAll.filter(name => typeof name === 'string' && name.length > 0);
|
|
41
32
|
// Use cleaned names or fallback to id
|
|
42
33
|
if (cleaned.length > 0) {
|
|
43
34
|
displayName = cleaned.join(' ');
|
|
@@ -60,11 +51,7 @@ export function buildUserMention({
|
|
|
60
51
|
case 'HTML':
|
|
61
52
|
default: {
|
|
62
53
|
// HTML mode: <a href="url">text</a>
|
|
63
|
-
const escapedHtml = displayName
|
|
64
|
-
.replace(/&/g, '&')
|
|
65
|
-
.replace(/</g, '<')
|
|
66
|
-
.replace(/>/g, '>')
|
|
67
|
-
.replace(/"/g, '"');
|
|
54
|
+
const escapedHtml = displayName.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
68
55
|
return `<a href="${link}">${escapedHtml}</a>`;
|
|
69
56
|
}
|
|
70
57
|
}
|
|
@@ -149,7 +149,7 @@ export async function getClaudeUsageLimits(verbose = false, credentialsPath = DE
|
|
|
149
149
|
if (!credentials) {
|
|
150
150
|
return {
|
|
151
151
|
success: false,
|
|
152
|
-
error: 'Could not read Claude credentials. Make sure Claude is properly installed and authenticated.'
|
|
152
|
+
error: 'Could not read Claude credentials. Make sure Claude is properly installed and authenticated.',
|
|
153
153
|
};
|
|
154
154
|
}
|
|
155
155
|
|
|
@@ -158,7 +158,7 @@ export async function getClaudeUsageLimits(verbose = false, credentialsPath = DE
|
|
|
158
158
|
if (!accessToken) {
|
|
159
159
|
return {
|
|
160
160
|
success: false,
|
|
161
|
-
error: 'No access token found in Claude credentials. Please use `/solve` or `/hive` commands to trigger re-authentication of Claude.'
|
|
161
|
+
error: 'No access token found in Claude credentials. Please use `/solve` or `/hive` commands to trigger re-authentication of Claude.',
|
|
162
162
|
};
|
|
163
163
|
}
|
|
164
164
|
|
|
@@ -170,12 +170,12 @@ export async function getClaudeUsageLimits(verbose = false, credentialsPath = DE
|
|
|
170
170
|
const response = await fetch(USAGE_API_ENDPOINT, {
|
|
171
171
|
method: 'GET',
|
|
172
172
|
headers: {
|
|
173
|
-
|
|
173
|
+
Accept: 'application/json',
|
|
174
174
|
'Content-Type': 'application/json',
|
|
175
175
|
'User-Agent': 'claude-code/2.0.55',
|
|
176
|
-
|
|
177
|
-
'anthropic-beta': 'oauth-2025-04-20'
|
|
178
|
-
}
|
|
176
|
+
Authorization: `Bearer ${accessToken}`,
|
|
177
|
+
'anthropic-beta': 'oauth-2025-04-20',
|
|
178
|
+
},
|
|
179
179
|
});
|
|
180
180
|
|
|
181
181
|
if (!response.ok) {
|
|
@@ -188,13 +188,13 @@ export async function getClaudeUsageLimits(verbose = false, credentialsPath = DE
|
|
|
188
188
|
if (response.status === 401) {
|
|
189
189
|
return {
|
|
190
190
|
success: false,
|
|
191
|
-
error: 'Claude authentication expired. Please use `/solve` or `/hive` commands to trigger re-authentication of Claude.'
|
|
191
|
+
error: 'Claude authentication expired. Please use `/solve` or `/hive` commands to trigger re-authentication of Claude.',
|
|
192
192
|
};
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
return {
|
|
196
196
|
success: false,
|
|
197
|
-
error: `Failed to fetch usage from API: ${response.status} ${response.statusText}
|
|
197
|
+
error: `Failed to fetch usage from API: ${response.status} ${response.statusText}`,
|
|
198
198
|
};
|
|
199
199
|
}
|
|
200
200
|
|
|
@@ -214,23 +214,23 @@ export async function getClaudeUsageLimits(verbose = false, credentialsPath = DE
|
|
|
214
214
|
currentSession: {
|
|
215
215
|
percentage: data.five_hour?.utilization ?? null,
|
|
216
216
|
resetTime: formatResetTime(data.five_hour?.resets_at),
|
|
217
|
-
resetsAt: data.five_hour?.resets_at ?? null
|
|
217
|
+
resetsAt: data.five_hour?.resets_at ?? null,
|
|
218
218
|
},
|
|
219
219
|
allModels: {
|
|
220
220
|
percentage: data.seven_day?.utilization ?? null,
|
|
221
221
|
resetTime: formatResetTime(data.seven_day?.resets_at),
|
|
222
|
-
resetsAt: data.seven_day?.resets_at ?? null
|
|
222
|
+
resetsAt: data.seven_day?.resets_at ?? null,
|
|
223
223
|
},
|
|
224
224
|
sonnetOnly: {
|
|
225
225
|
percentage: data.seven_day_sonnet?.utilization ?? null,
|
|
226
226
|
resetTime: formatResetTime(data.seven_day_sonnet?.resets_at),
|
|
227
|
-
resetsAt: data.seven_day_sonnet?.resets_at ?? null
|
|
228
|
-
}
|
|
227
|
+
resetsAt: data.seven_day_sonnet?.resets_at ?? null,
|
|
228
|
+
},
|
|
229
229
|
};
|
|
230
230
|
|
|
231
231
|
return {
|
|
232
232
|
success: true,
|
|
233
|
-
usage
|
|
233
|
+
usage,
|
|
234
234
|
};
|
|
235
235
|
} catch (error) {
|
|
236
236
|
if (verbose) {
|
|
@@ -238,7 +238,7 @@ export async function getClaudeUsageLimits(verbose = false, credentialsPath = DE
|
|
|
238
238
|
}
|
|
239
239
|
return {
|
|
240
240
|
success: false,
|
|
241
|
-
error: `Failed to get usage limits: ${error.message}
|
|
241
|
+
error: `Failed to get usage limits: ${error.message}`,
|
|
242
242
|
};
|
|
243
243
|
}
|
|
244
244
|
}
|
|
@@ -385,5 +385,5 @@ export default {
|
|
|
385
385
|
getClaudeUsageLimits,
|
|
386
386
|
getProgressBar,
|
|
387
387
|
calculateTimePassedPercentage,
|
|
388
|
-
formatUsageMessage
|
|
388
|
+
formatUsageMessage,
|
|
389
389
|
};
|