@nomad-e/bluma-cli 0.1.0 → 0.1.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/dist/main.js +120 -28
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -3071,8 +3071,9 @@ async function readArtifact(args) {
|
|
|
3071
3071
|
import https from "https";
|
|
3072
3072
|
import http from "http";
|
|
3073
3073
|
var DEFAULT_SOURCES = ["reddit", "github", "stackoverflow"];
|
|
3074
|
-
var MAX_RESULTS_DEFAULT =
|
|
3075
|
-
var REQUEST_TIMEOUT =
|
|
3074
|
+
var MAX_RESULTS_DEFAULT = 5;
|
|
3075
|
+
var REQUEST_TIMEOUT = 15e3;
|
|
3076
|
+
var MAX_CONTENT_LENGTH = 4e3;
|
|
3076
3077
|
function httpGet(url, customHeaders) {
|
|
3077
3078
|
return new Promise((resolve, reject) => {
|
|
3078
3079
|
const protocol = url.startsWith("https") ? https : http;
|
|
@@ -3081,7 +3082,6 @@ function httpGet(url, customHeaders) {
|
|
|
3081
3082
|
"Accept": "application/json, text/html, */*",
|
|
3082
3083
|
"Accept-Language": "en-US,en;q=0.9",
|
|
3083
3084
|
"Accept-Encoding": "identity",
|
|
3084
|
-
// Não usar gzip para simplificar
|
|
3085
3085
|
"Cache-Control": "no-cache",
|
|
3086
3086
|
"Connection": "keep-alive",
|
|
3087
3087
|
...customHeaders
|
|
@@ -3111,10 +3111,18 @@ function httpGet(url, customHeaders) {
|
|
|
3111
3111
|
});
|
|
3112
3112
|
});
|
|
3113
3113
|
}
|
|
3114
|
+
function cleanContent(text, maxLength = MAX_CONTENT_LENGTH) {
|
|
3115
|
+
if (!text) return "";
|
|
3116
|
+
let cleaned = text.replace(/```[\s\S]*?```/g, (match) => match.substring(0, 500) + (match.length > 500 ? "\n[...code truncated...]" : "")).replace(/\n{3,}/g, "\n\n").trim();
|
|
3117
|
+
if (cleaned.length > maxLength) {
|
|
3118
|
+
cleaned = cleaned.substring(0, maxLength) + "\n\n[...content truncated...]";
|
|
3119
|
+
}
|
|
3120
|
+
return cleaned;
|
|
3121
|
+
}
|
|
3114
3122
|
async function searchReddit(query, limit) {
|
|
3115
3123
|
const results = [];
|
|
3116
3124
|
try {
|
|
3117
|
-
const subreddits = "programming+webdev+javascript+typescript+python+node+reactjs+learnprogramming";
|
|
3125
|
+
const subreddits = "programming+webdev+javascript+typescript+python+node+reactjs+learnprogramming+rust+golang+devops";
|
|
3118
3126
|
const encodedQuery = encodeURIComponent(query);
|
|
3119
3127
|
const url = `https://www.reddit.com/r/${subreddits}/search.json?q=${encodedQuery}&sort=relevance&limit=${limit}&restrict_sr=on`;
|
|
3120
3128
|
const response = await httpGet(url);
|
|
@@ -3122,12 +3130,46 @@ async function searchReddit(query, limit) {
|
|
|
3122
3130
|
if (data.data?.children) {
|
|
3123
3131
|
for (const child of data.data.children.slice(0, limit)) {
|
|
3124
3132
|
const post = child.data;
|
|
3133
|
+
let content = `# ${post.title}
|
|
3134
|
+
|
|
3135
|
+
`;
|
|
3136
|
+
content += `**Subreddit:** r/${post.subreddit} | **Score:** ${post.score} | **Comments:** ${post.num_comments}
|
|
3137
|
+
|
|
3138
|
+
`;
|
|
3139
|
+
if (post.selftext) {
|
|
3140
|
+
content += `## Post Content:
|
|
3141
|
+
${cleanContent(post.selftext, 2e3)}
|
|
3142
|
+
|
|
3143
|
+
`;
|
|
3144
|
+
}
|
|
3145
|
+
try {
|
|
3146
|
+
const commentsUrl = `https://www.reddit.com${post.permalink}.json?limit=3&depth=1`;
|
|
3147
|
+
const commentsResponse = await httpGet(commentsUrl);
|
|
3148
|
+
const commentsData = JSON.parse(commentsResponse);
|
|
3149
|
+
if (commentsData[1]?.data?.children) {
|
|
3150
|
+
content += `## Top Comments:
|
|
3151
|
+
`;
|
|
3152
|
+
for (const comment of commentsData[1].data.children.slice(0, 3)) {
|
|
3153
|
+
if (comment.data?.body) {
|
|
3154
|
+
content += `
|
|
3155
|
+
**[${comment.data.score || 0} pts]** ${cleanContent(comment.data.body, 500)}
|
|
3156
|
+
`;
|
|
3157
|
+
}
|
|
3158
|
+
}
|
|
3159
|
+
}
|
|
3160
|
+
} catch {
|
|
3161
|
+
}
|
|
3125
3162
|
results.push({
|
|
3126
3163
|
title: post.title || "",
|
|
3127
3164
|
url: `https://reddit.com${post.permalink}`,
|
|
3128
3165
|
source: "reddit",
|
|
3129
|
-
|
|
3130
|
-
score: post.score
|
|
3166
|
+
content: cleanContent(content),
|
|
3167
|
+
score: post.score,
|
|
3168
|
+
metadata: {
|
|
3169
|
+
author: post.author,
|
|
3170
|
+
date: new Date(post.created_utc * 1e3).toISOString().split("T")[0],
|
|
3171
|
+
comments_count: post.num_comments
|
|
3172
|
+
}
|
|
3131
3173
|
});
|
|
3132
3174
|
}
|
|
3133
3175
|
}
|
|
@@ -3145,12 +3187,35 @@ async function searchGitHub(query, limit) {
|
|
|
3145
3187
|
const data = JSON.parse(response);
|
|
3146
3188
|
if (data.items) {
|
|
3147
3189
|
for (const item of data.items.slice(0, limit)) {
|
|
3190
|
+
let content = `# ${item.title}
|
|
3191
|
+
|
|
3192
|
+
`;
|
|
3193
|
+
content += `**Repo:** ${item.repository_url?.split("/").slice(-2).join("/") || "unknown"}
|
|
3194
|
+
`;
|
|
3195
|
+
content += `**State:** ${item.state} | **Comments:** ${item.comments} | **Reactions:** ${item.reactions?.total_count || 0}
|
|
3196
|
+
|
|
3197
|
+
`;
|
|
3198
|
+
if (item.body) {
|
|
3199
|
+
content += `## Issue Description:
|
|
3200
|
+
${cleanContent(item.body, 2500)}
|
|
3201
|
+
`;
|
|
3202
|
+
}
|
|
3203
|
+
if (item.labels?.length > 0) {
|
|
3204
|
+
content += `
|
|
3205
|
+
**Labels:** ${item.labels.map((l) => l.name).join(", ")}
|
|
3206
|
+
`;
|
|
3207
|
+
}
|
|
3148
3208
|
results.push({
|
|
3149
3209
|
title: item.title || "",
|
|
3150
3210
|
url: item.html_url || "",
|
|
3151
3211
|
source: "github",
|
|
3152
|
-
|
|
3153
|
-
score: item.reactions?.total_count || 0
|
|
3212
|
+
content: cleanContent(content),
|
|
3213
|
+
score: item.reactions?.total_count || 0,
|
|
3214
|
+
metadata: {
|
|
3215
|
+
author: item.user?.login,
|
|
3216
|
+
date: item.created_at?.split("T")[0],
|
|
3217
|
+
comments_count: item.comments
|
|
3218
|
+
}
|
|
3154
3219
|
});
|
|
3155
3220
|
}
|
|
3156
3221
|
}
|
|
@@ -3163,17 +3228,56 @@ async function searchStackOverflow(query, limit) {
|
|
|
3163
3228
|
const results = [];
|
|
3164
3229
|
try {
|
|
3165
3230
|
const encodedQuery = encodeURIComponent(query);
|
|
3166
|
-
const url = `https://api.stackexchange.com/2.3/search?order=desc&sort=relevance&
|
|
3231
|
+
const url = `https://api.stackexchange.com/2.3/search/advanced?order=desc&sort=relevance&q=${encodedQuery}&site=stackoverflow&pagesize=${limit}&filter=withbody`;
|
|
3167
3232
|
const response = await httpGet(url);
|
|
3168
3233
|
const data = JSON.parse(response);
|
|
3169
3234
|
if (data.items) {
|
|
3170
3235
|
for (const item of data.items.slice(0, limit)) {
|
|
3236
|
+
let content = `# ${item.title}
|
|
3237
|
+
|
|
3238
|
+
`;
|
|
3239
|
+
content += `**Score:** ${item.score} | **Answers:** ${item.answer_count} | **Views:** ${item.view_count}`;
|
|
3240
|
+
content += item.is_answered ? " | \u2705 Answered" : "";
|
|
3241
|
+
content += `
|
|
3242
|
+
|
|
3243
|
+
`;
|
|
3244
|
+
if (item.body) {
|
|
3245
|
+
const cleanBody = item.body.replace(/<code>/g, "`").replace(/<\/code>/g, "`").replace(/<pre>/g, "```\n").replace(/<\/pre>/g, "\n```").replace(/<[^>]+>/g, "").replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&").replace(/"/g, '"');
|
|
3246
|
+
content += `## Question:
|
|
3247
|
+
${cleanContent(cleanBody, 1500)}
|
|
3248
|
+
|
|
3249
|
+
`;
|
|
3250
|
+
}
|
|
3251
|
+
if (item.tags?.length > 0) {
|
|
3252
|
+
content += `**Tags:** ${item.tags.join(", ")}
|
|
3253
|
+
|
|
3254
|
+
`;
|
|
3255
|
+
}
|
|
3256
|
+
if (item.accepted_answer_id) {
|
|
3257
|
+
try {
|
|
3258
|
+
const answerUrl = `https://api.stackexchange.com/2.3/answers/${item.accepted_answer_id}?site=stackoverflow&filter=withbody`;
|
|
3259
|
+
const answerResponse = await httpGet(answerUrl);
|
|
3260
|
+
const answerData = JSON.parse(answerResponse);
|
|
3261
|
+
if (answerData.items?.[0]?.body) {
|
|
3262
|
+
const cleanAnswer = answerData.items[0].body.replace(/<code>/g, "`").replace(/<\/code>/g, "`").replace(/<pre>/g, "```\n").replace(/<\/pre>/g, "\n```").replace(/<[^>]+>/g, "").replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&").replace(/"/g, '"');
|
|
3263
|
+
content += `## \u2705 Accepted Answer (${answerData.items[0].score} pts):
|
|
3264
|
+
${cleanContent(cleanAnswer, 2e3)}
|
|
3265
|
+
`;
|
|
3266
|
+
}
|
|
3267
|
+
} catch {
|
|
3268
|
+
}
|
|
3269
|
+
}
|
|
3171
3270
|
results.push({
|
|
3172
3271
|
title: item.title || "",
|
|
3173
3272
|
url: item.link || "",
|
|
3174
3273
|
source: "stackoverflow",
|
|
3175
|
-
|
|
3176
|
-
score: item.score
|
|
3274
|
+
content: cleanContent(content),
|
|
3275
|
+
score: item.score,
|
|
3276
|
+
metadata: {
|
|
3277
|
+
author: item.owner?.display_name,
|
|
3278
|
+
date: item.creation_date ? new Date(item.creation_date * 1e3).toISOString().split("T")[0] : void 0,
|
|
3279
|
+
is_answered: item.is_answered
|
|
3280
|
+
}
|
|
3177
3281
|
});
|
|
3178
3282
|
}
|
|
3179
3283
|
}
|
|
@@ -3182,15 +3286,6 @@ async function searchStackOverflow(query, limit) {
|
|
|
3182
3286
|
}
|
|
3183
3287
|
return results;
|
|
3184
3288
|
}
|
|
3185
|
-
function getXSearchUrl(query) {
|
|
3186
|
-
const encodedQuery = encodeURIComponent(query);
|
|
3187
|
-
return {
|
|
3188
|
-
title: `Search X for: "${query}"`,
|
|
3189
|
-
url: `https://twitter.com/search?q=${encodedQuery}&src=typed_query&f=live`,
|
|
3190
|
-
source: "x",
|
|
3191
|
-
snippet: "X/Twitter requires authentication. Click the link to search manually."
|
|
3192
|
-
};
|
|
3193
|
-
}
|
|
3194
3289
|
async function searchWeb(args) {
|
|
3195
3290
|
try {
|
|
3196
3291
|
const {
|
|
@@ -3224,9 +3319,6 @@ async function searchWeb(args) {
|
|
|
3224
3319
|
case "stackoverflow":
|
|
3225
3320
|
searches.push(searchStackOverflow(query, resultsPerSource));
|
|
3226
3321
|
break;
|
|
3227
|
-
case "x":
|
|
3228
|
-
allResults.push(getXSearchUrl(query));
|
|
3229
|
-
break;
|
|
3230
3322
|
}
|
|
3231
3323
|
}
|
|
3232
3324
|
const searchResults = await Promise.all(searches);
|
|
@@ -3240,8 +3332,7 @@ async function searchWeb(args) {
|
|
|
3240
3332
|
query,
|
|
3241
3333
|
results: limitedResults,
|
|
3242
3334
|
sources_searched: sourcesSearched,
|
|
3243
|
-
total_results: limitedResults.length
|
|
3244
|
-
note: sources.includes("x") ? "X/Twitter requires manual search due to API restrictions" : void 0
|
|
3335
|
+
total_results: limitedResults.length
|
|
3245
3336
|
};
|
|
3246
3337
|
} catch (error) {
|
|
3247
3338
|
return {
|
|
@@ -4644,8 +4735,8 @@ var ToolCallNormalizer = class {
|
|
|
4644
4735
|
*/
|
|
4645
4736
|
static extractFromContent(content) {
|
|
4646
4737
|
const results = [];
|
|
4647
|
-
const
|
|
4648
|
-
const jsonMatches = this.extractJsonObjects(
|
|
4738
|
+
const cleanContent2 = content.replace(/```(?:json)?\s*([\s\S]*?)```/g, "$1");
|
|
4739
|
+
const jsonMatches = this.extractJsonObjects(cleanContent2);
|
|
4649
4740
|
for (const jsonStr of jsonMatches) {
|
|
4650
4741
|
try {
|
|
4651
4742
|
const parsed = JSON.parse(jsonStr);
|
|
@@ -4956,7 +5047,8 @@ ${editData.error.display}`;
|
|
|
4956
5047
|
"count_file_lines",
|
|
4957
5048
|
"read_file_lines",
|
|
4958
5049
|
"todo",
|
|
4959
|
-
"load_skill"
|
|
5050
|
+
"load_skill",
|
|
5051
|
+
"search_web"
|
|
4960
5052
|
];
|
|
4961
5053
|
const toolToCall = validToolCalls[0];
|
|
4962
5054
|
const isSafeTool = autoApprovedTools.some((safeTool) => toolToCall.function.name.includes(safeTool));
|