profclaw 0.0.1-beta.2 → 2.0.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 +21 -38
- package/CONTRIBUTING.md +3 -5
- package/README.md +128 -63
- package/dist/chat/execution/tools/index.d.ts +1 -1
- package/dist/chat/execution/tools/index.js +41 -2
- package/dist/chat/providers/slack/index.d.ts +2 -2
- package/dist/cli/commands/models.js +39 -26
- package/dist/cli/commands/onboard.js +64 -79
- package/dist/cli/commands/setup.js +293 -90
- package/dist/cli/index.js +0 -6
- package/dist/cli/providers.d.ts +15 -0
- package/dist/cli/providers.js +41 -0
- package/dist/core/deployment.js +2 -0
- package/dist/providers/ai-sdk.js +26 -6
- package/dist/routes/channels.d.ts +12 -0
- package/dist/routes/channels.js +166 -0
- package/dist/server/route-loader.js +1 -0
- package/dist/server.js +115 -109
- package/package.json +1 -1
- package/skills/git-workflow/SKILL.md +3 -3
- package/ui/dist/assets/{ActivityView-DIPQSJ_d.js → ActivityView-BeshZXmE.js} +1 -1
- package/ui/dist/assets/{AgentList-CqyaYrcq.js → AgentList-QVHeldPi.js} +1 -1
- package/ui/dist/assets/{AnalyticsDashboard-C-mjuGHT.js → AnalyticsDashboard-C9R97dXE.js} +1 -1
- package/ui/dist/assets/{AreaChart-CfYWmbtr.js → AreaChart-B73gaiVQ.js} +1 -1
- package/ui/dist/assets/{CartesianChart-BaQ3It0c.js → CartesianChart-CXYL2R-A.js} +1 -1
- package/ui/dist/assets/{ChatView-DxxQy6pl.js → ChatView-qjZErlrp.js} +1 -1
- package/ui/dist/assets/{CostsDashboard-CDBBcGkg.js → CostsDashboard-O4DCLy1i.js} +1 -1
- package/ui/dist/assets/{EstimateSelect-CDjf5qKl.js → EstimateSelect-1hQf4Osk.js} +1 -1
- package/ui/dist/assets/{FloatingChatbot-CZHjvJIe.js → FloatingChatbot-BZBzrJxd.js} +1 -1
- package/ui/dist/assets/{InviteCodeManagement-DTm-IPTm.js → InviteCodeManagement-LEoGqYeA.js} +1 -1
- package/ui/dist/assets/{ProjectDetail-DlYUcOss.js → ProjectDetail--gPfvATB.js} +1 -1
- package/ui/dist/assets/{ProjectIcon-BMRpnM04.js → ProjectIcon-Chd_ofsw.js} +1 -1
- package/ui/dist/assets/{ProjectList-D85TN0i0.js → ProjectList-BvUfVB6c.js} +1 -1
- package/ui/dist/assets/{Settings-CgPqzUvj.js → Settings-1kaf7VHE.js} +1 -1
- package/ui/dist/assets/{StatusIndicator-yig0uZEA.js → StatusIndicator-pRfkNcdV.js} +1 -1
- package/ui/dist/assets/{SummaryDetail-CwLAfHgJ.js → SummaryDetail-DV3AmONk.js} +1 -1
- package/ui/dist/assets/{SummaryList-BvS5Idnu.js → SummaryList-B6kXiTxL.js} +1 -1
- package/ui/dist/assets/{TaskDetail-zarC1fOt.js → TaskDetail-CV6CzbOS.js} +1 -1
- package/ui/dist/assets/{TaskList-CyJq3ANE.js → TaskList-DL7brQKd.js} +1 -1
- package/ui/dist/assets/{TicketBoard-BlWr3-iH.js → TicketBoard-CrkkFj7C.js} +1 -1
- package/ui/dist/assets/{TicketDetail-DmqWKj2W.js → TicketDetail-hnnYclpD.js} +1 -1
- package/ui/dist/assets/{TicketList-Scj4pMWa.js → TicketList-CsDAyQCL.js} +1 -1
- package/ui/dist/assets/{UserManagement-BH7uG7dw.js → UserManagement-BGFQyTSr.js} +1 -1
- package/ui/dist/assets/{ViewSwitcher-3HzZUdWn.js → ViewSwitcher-CnL0OqA8.js} +1 -1
- package/ui/dist/assets/{alert-dialog-DWPb2IfQ.js → alert-dialog-SKM6Gjz4.js} +1 -1
- package/ui/dist/assets/{archive-CGck7gxR.js → archive-BsLa7brF.js} +1 -1
- package/ui/dist/assets/{badge-DEmc3Z_l.js → badge-CVHH1a-v.js} +1 -1
- package/ui/dist/assets/{brain-CfFdLVqb.js → brain-6o_RHVpe.js} +1 -1
- package/ui/dist/assets/{bug-DqSGPUUE.js → bug-CmZI7jqM.js} +1 -1
- package/ui/dist/assets/{calendar-BuZ4zbPW.js → calendar-Bf0t2B82.js} +1 -1
- package/ui/dist/assets/{chevron-up-DcJ4LL_N.js → chevron-up-CoUsOvZj.js} +1 -1
- package/ui/dist/assets/{circle-x-C78PNZjF.js → circle-x-Dgw11LgT.js} +1 -1
- package/ui/dist/assets/{constants-DhDjZe4P.js → constants-Q5Zivl-a.js} +1 -1
- package/ui/dist/assets/{cpu-Ck6AoG8c.js → cpu-DiPMQICV.js} +1 -1
- package/ui/dist/assets/{database-CA2w8Lvt.js → database-BwTfupDi.js} +1 -1
- package/ui/dist/assets/{dialog-BOdGWhgE.js → dialog-BUqN9Psj.js} +1 -1
- package/ui/dist/assets/{ellipsis-FhHKRbfl.js → ellipsis-UJx4Xnf6.js} +1 -1
- package/ui/dist/assets/{ellipsis-vertical-CO0UqE4-.js → ellipsis-vertical-DoULYEKn.js} +1 -1
- package/ui/dist/assets/{file-code-ChnhYYj1.js → file-code-B2UrJLwi.js} +1 -1
- package/ui/dist/assets/{folder-open-CHwA1-ve.js → folder-open-BJi577JH.js} +1 -1
- package/ui/dist/assets/{funnel-ByEjRFNB.js → funnel-PkaD_HSR.js} +1 -1
- package/ui/dist/assets/{git-branch-GTOPQgU4.js → git-branch-C_K30am0.js} +1 -1
- package/ui/dist/assets/{git-commit-horizontal-F5M84Kut.js → git-commit-horizontal-IT6ecxWQ.js} +1 -1
- package/ui/dist/assets/{globe-CQWfr7hT.js → globe-f-jjCa_g.js} +1 -1
- package/ui/dist/assets/{hash-nKC9gtLg.js → hash-DNEv8Elo.js} +1 -1
- package/ui/dist/assets/{history-DfFSA9xJ.js → history-BQSBo_1Q.js} +1 -1
- package/ui/dist/assets/{index-DHGvP9mp.js → index-BUmnwPQr.js} +1 -1
- package/ui/dist/assets/{index-Z4-RtZcs.js → index-BfF5G4Cw.js} +1 -1
- package/ui/dist/assets/{index-DeI8lKRR.js → index-C8N375c2.js} +1 -1
- package/ui/dist/assets/index-CuxnqVVz.css +1 -0
- package/ui/dist/assets/{index-Ca3vk7Gq.js → index-CzMM3QOk.js} +1 -1
- package/ui/dist/assets/{index--JkIxVXb.js → index-lJlNPFVJ.js} +3 -3
- package/ui/dist/assets/{index-a4Fxq0Hb.js → index-nS3EErDg.js} +1 -1
- package/ui/dist/assets/{layers-DFeLExSa.js → layers-jFqVrWMD.js} +1 -1
- package/ui/dist/assets/{layout-dashboard-WmgjMhWF.js → layout-dashboard-CcKt1hXw.js} +1 -1
- package/ui/dist/assets/{lightbulb-Bo8hEr7B.js → lightbulb-Jhp7FvbU.js} +1 -1
- package/ui/dist/assets/{link-2-YqrpQXBH.js → link-2-DdO7ostF.js} +1 -1
- package/ui/dist/assets/{markdown-renderer-Croje6Xe.js → markdown-renderer-n1ToC4XQ.js} +1 -1
- package/ui/dist/assets/{message-square-CD0H5hot.js → message-square-CBgH65X7.js} +1 -1
- package/ui/dist/assets/{pencil-DpFnj5dn.js → pencil-CYXCEPQh.js} +1 -1
- package/ui/dist/assets/{play-DVgea_jT.js → play-d1ONaH0-.js} +1 -1
- package/ui/dist/assets/{popover-JXecfWG5.js → popover-CrmZgoWu.js} +1 -1
- package/ui/dist/assets/{progress-C1ghf1Fu.js → progress-uv4SPkL5.js} +1 -1
- package/ui/dist/assets/{rocket-BFxPYGx9.js → rocket-DhvUetsk.js} +1 -1
- package/ui/dist/assets/{select-MADP8m6Q.js → select-CeQ8AHGy.js} +1 -1
- package/ui/dist/assets/{send-eYnW_7n-.js → send-P0r5D7td.js} +1 -1
- package/ui/dist/assets/{server-CPMaysH8.js → server-CVHTZB72.js} +1 -1
- package/ui/dist/assets/{settings-2-scXUOuE_.js → settings-2-ocj5uHGx.js} +1 -1
- package/ui/dist/assets/{sheet-r6NSOxi-.js → sheet-DuQExSho.js} +1 -1
- package/ui/dist/assets/{shield-check-PEr7nmVw.js → shield-check-DfVdE34l.js} +1 -1
- package/ui/dist/assets/{shield-off-CLtXio62.js → shield-off-8l0J6R-8.js} +1 -1
- package/ui/dist/assets/{skeleton-C9oEzNlU.js → skeleton-TFiFJ3nB.js} +1 -1
- package/ui/dist/assets/{smartphone-DusFfY0U.js → smartphone-77_g3SQn.js} +1 -1
- package/ui/dist/assets/{square-e1yxB2eR.js → square-Ckzsr3Rn.js} +1 -1
- package/ui/dist/assets/{switch-tNs0n-kz.js → switch-CAePkd6k.js} +1 -1
- package/ui/dist/assets/{table-CXxtLicg.js → table-ZjAZ7hkt.js} +1 -1
- package/ui/dist/assets/{tag-tAwMmQ9G.js → tag-C35mgoEv.js} +1 -1
- package/ui/dist/assets/{textarea-BjiEeIWh.js → textarea-DsVPnSgR.js} +1 -1
- package/ui/dist/assets/{timer-Vel1N3RP.js → timer-DHJBS2w1.js} +1 -1
- package/ui/dist/assets/{tooltip-ZMwtfr1J.js → tooltip-BYmQ331W.js} +1 -1
- package/ui/dist/assets/{trash-2-eM-CNwsZ.js → trash-2-keO5tKPE.js} +1 -1
- package/ui/dist/assets/{trending-up-BGafmjRo.js → trending-up-BBv8KbrY.js} +1 -1
- package/ui/dist/assets/{wand-sparkles-DPvcd9Pi.js → wand-sparkles-BusQ52ZK.js} +1 -1
- package/ui/dist/assets/{wrench-B8s3zYVV.js → wrench-02YaOSiK.js} +1 -1
- package/ui/dist/index.html +2 -2
- package/dist/chat/auto-reply.d.ts +0 -90
- package/dist/chat/auto-reply.js +0 -272
- package/dist/chat/execution/pty.d.ts +0 -92
- package/dist/chat/execution/pty.js +0 -285
- package/dist/chat/execution/tools/glinr-ops.d.ts +0 -202
- package/dist/chat/execution/tools/glinr-ops.js +0 -694
- package/dist/cli/commands/browser.d.ts +0 -3
- package/dist/cli/commands/browser.js +0 -138
- package/dist/cli/commands/canvas.d.ts +0 -3
- package/dist/cli/commands/canvas.js +0 -155
- package/dist/cli/commands/nodes.d.ts +0 -3
- package/dist/cli/commands/nodes.js +0 -193
- package/dist/diagnostics/exporters.d.ts +0 -21
- package/dist/diagnostics/exporters.js +0 -138
- package/dist/diagnostics/index.d.ts +0 -10
- package/dist/diagnostics/index.js +0 -9
- package/dist/diagnostics/middleware.d.ts +0 -12
- package/dist/diagnostics/middleware.js +0 -58
- package/dist/diagnostics/tracer.d.ts +0 -133
- package/dist/diagnostics/tracer.js +0 -257
- package/dist/discovery/index.d.ts +0 -8
- package/dist/discovery/index.js +0 -7
- package/dist/discovery/mdns.d.ts +0 -40
- package/dist/discovery/mdns.js +0 -249
- package/dist/plugins/registry.d.ts +0 -122
- package/dist/plugins/registry.js +0 -352
- package/dist/plugins/sandbox.d.ts +0 -77
- package/dist/plugins/sandbox.js +0 -287
- package/dist/plugins/search/brave.d.ts +0 -9
- package/dist/plugins/search/brave.js +0 -157
- package/dist/plugins/search/duckduckgo.d.ts +0 -9
- package/dist/plugins/search/duckduckgo.js +0 -171
- package/dist/plugins/search/index.d.ts +0 -13
- package/dist/plugins/search/index.js +0 -23
- package/dist/plugins/search/searxng.d.ts +0 -9
- package/dist/plugins/search/searxng.js +0 -170
- package/dist/plugins/search/serper.d.ts +0 -9
- package/dist/plugins/search/serper.js +0 -135
- package/dist/plugins/search/tavily.d.ts +0 -9
- package/dist/plugins/search/tavily.js +0 -146
- package/dist/providers/adapters/anthropic.d.ts +0 -26
- package/dist/providers/adapters/anthropic.js +0 -306
- package/dist/providers/adapters/base.d.ts +0 -53
- package/dist/providers/adapters/base.js +0 -99
- package/dist/providers/adapters/ollama.d.ts +0 -30
- package/dist/providers/adapters/ollama.js +0 -292
- package/dist/utils/ai-cache.d.ts +0 -72
- package/dist/utils/ai-cache.js +0 -204
- package/dist/utils/file-lock.d.ts +0 -85
- package/dist/utils/file-lock.js +0 -204
- package/ui/dist/assets/index-WclMPci1.css +0 -1
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Brave Search Provider
|
|
3
|
-
*
|
|
4
|
-
* Privacy-focused search with independent index.
|
|
5
|
-
* https://brave.com/search/api/
|
|
6
|
-
*/
|
|
7
|
-
import type { SearchPluginDefinition } from '../types.js';
|
|
8
|
-
export declare const BRAVE_DEFINITION: SearchPluginDefinition;
|
|
9
|
-
//# sourceMappingURL=brave.d.ts.map
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Brave Search Provider
|
|
3
|
-
*
|
|
4
|
-
* Privacy-focused search with independent index.
|
|
5
|
-
* https://brave.com/search/api/
|
|
6
|
-
*/
|
|
7
|
-
const BRAVE_API_URL = 'https://api.search.brave.com/res/v1/web/search';
|
|
8
|
-
class BraveProvider {
|
|
9
|
-
metadata = BRAVE_DEFINITION.metadata;
|
|
10
|
-
apiKey;
|
|
11
|
-
safeSearch;
|
|
12
|
-
constructor(config) {
|
|
13
|
-
this.apiKey = config.credentials?.apiKey || '';
|
|
14
|
-
this.safeSearch = config.settings?.safeSearch || 'moderate';
|
|
15
|
-
}
|
|
16
|
-
async search(query, options) {
|
|
17
|
-
if (!this.apiKey) {
|
|
18
|
-
throw new Error('Brave Search API key not configured');
|
|
19
|
-
}
|
|
20
|
-
const startTime = Date.now();
|
|
21
|
-
const params = new URLSearchParams({
|
|
22
|
-
q: query,
|
|
23
|
-
count: String(options?.limit || 10),
|
|
24
|
-
safesearch: this.safeSearch,
|
|
25
|
-
});
|
|
26
|
-
if (options?.language)
|
|
27
|
-
params.set('search_lang', options.language);
|
|
28
|
-
if (options?.region)
|
|
29
|
-
params.set('country', options.region);
|
|
30
|
-
if (options?.freshness) {
|
|
31
|
-
const freshnessMap = {
|
|
32
|
-
day: 'pd',
|
|
33
|
-
week: 'pw',
|
|
34
|
-
month: 'pm',
|
|
35
|
-
year: 'py',
|
|
36
|
-
};
|
|
37
|
-
params.set('freshness', freshnessMap[options.freshness] || '');
|
|
38
|
-
}
|
|
39
|
-
const response = await fetch(`${BRAVE_API_URL}?${params}`, {
|
|
40
|
-
headers: {
|
|
41
|
-
'Accept': 'application/json',
|
|
42
|
-
'Accept-Encoding': 'gzip',
|
|
43
|
-
'X-Subscription-Token': this.apiKey,
|
|
44
|
-
},
|
|
45
|
-
});
|
|
46
|
-
if (!response.ok) {
|
|
47
|
-
const error = await response.text();
|
|
48
|
-
throw new Error(`Brave Search API error: ${response.status} - ${error}`);
|
|
49
|
-
}
|
|
50
|
-
const data = await response.json();
|
|
51
|
-
const searchTime = Date.now() - startTime;
|
|
52
|
-
const results = (data.web?.results || []).map((item) => ({
|
|
53
|
-
title: item.title,
|
|
54
|
-
url: item.url,
|
|
55
|
-
snippet: item.description || '',
|
|
56
|
-
date: item.age,
|
|
57
|
-
source: 'brave',
|
|
58
|
-
favicon: item.profile?.img,
|
|
59
|
-
metadata: {
|
|
60
|
-
language: item.language,
|
|
61
|
-
familyFriendly: item.family_friendly,
|
|
62
|
-
extraSnippets: item.extra_snippets,
|
|
63
|
-
},
|
|
64
|
-
}));
|
|
65
|
-
return {
|
|
66
|
-
results,
|
|
67
|
-
query: data.query?.original || query,
|
|
68
|
-
totalResults: data.web?.total_results,
|
|
69
|
-
searchTime,
|
|
70
|
-
provider: 'brave',
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
async isAvailable() {
|
|
74
|
-
return !!this.apiKey;
|
|
75
|
-
}
|
|
76
|
-
async healthCheck() {
|
|
77
|
-
if (!this.apiKey) {
|
|
78
|
-
return {
|
|
79
|
-
healthy: false,
|
|
80
|
-
lastCheck: new Date(),
|
|
81
|
-
errorMessage: 'API key not configured',
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
try {
|
|
85
|
-
const startTime = Date.now();
|
|
86
|
-
await this.search('test', { limit: 1 });
|
|
87
|
-
const latency = Date.now() - startTime;
|
|
88
|
-
return {
|
|
89
|
-
healthy: true,
|
|
90
|
-
lastCheck: new Date(),
|
|
91
|
-
latency,
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
catch (error) {
|
|
95
|
-
return {
|
|
96
|
-
healthy: false,
|
|
97
|
-
lastCheck: new Date(),
|
|
98
|
-
errorMessage: error instanceof Error ? error.message : 'Health check failed',
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
export const BRAVE_DEFINITION = {
|
|
104
|
-
metadata: {
|
|
105
|
-
id: 'brave',
|
|
106
|
-
name: 'Brave Search',
|
|
107
|
-
description: 'Privacy-first search with independent index - great for enterprise',
|
|
108
|
-
category: 'search',
|
|
109
|
-
icon: 'shield-check',
|
|
110
|
-
version: '1.0.0',
|
|
111
|
-
homepage: 'https://brave.com/search/api/',
|
|
112
|
-
pricing: {
|
|
113
|
-
type: 'freemium',
|
|
114
|
-
costPer1k: 3.0,
|
|
115
|
-
freeQuota: 2000, // 2000 free queries/month
|
|
116
|
-
},
|
|
117
|
-
rateLimit: {
|
|
118
|
-
requestsPerSecond: 1, // Free tier
|
|
119
|
-
requestsPerMinute: 15, // Free tier
|
|
120
|
-
},
|
|
121
|
-
},
|
|
122
|
-
settingsSchema: {
|
|
123
|
-
credentials: [
|
|
124
|
-
{
|
|
125
|
-
key: 'apiKey',
|
|
126
|
-
type: 'password',
|
|
127
|
-
label: 'API Key',
|
|
128
|
-
description: 'Your Brave Search API key',
|
|
129
|
-
placeholder: 'BSA...',
|
|
130
|
-
required: true,
|
|
131
|
-
},
|
|
132
|
-
],
|
|
133
|
-
settings: [
|
|
134
|
-
{
|
|
135
|
-
key: 'safeSearch',
|
|
136
|
-
type: 'select',
|
|
137
|
-
label: 'Safe Search',
|
|
138
|
-
description: 'Content filtering level',
|
|
139
|
-
default: 'moderate',
|
|
140
|
-
options: [
|
|
141
|
-
{ value: 'off', label: 'Off' },
|
|
142
|
-
{ value: 'moderate', label: 'Moderate' },
|
|
143
|
-
{ value: 'strict', label: 'Strict' },
|
|
144
|
-
],
|
|
145
|
-
},
|
|
146
|
-
{
|
|
147
|
-
key: 'useGoggles',
|
|
148
|
-
type: 'boolean',
|
|
149
|
-
label: 'Use Goggles',
|
|
150
|
-
description: 'Enable custom result re-ranking with Brave Goggles',
|
|
151
|
-
default: false,
|
|
152
|
-
},
|
|
153
|
-
],
|
|
154
|
-
},
|
|
155
|
-
factory: (config) => new BraveProvider(config),
|
|
156
|
-
};
|
|
157
|
-
//# sourceMappingURL=brave.js.map
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DuckDuckGo Search Provider
|
|
3
|
-
*
|
|
4
|
-
* Free, privacy-focused search - great for fallback.
|
|
5
|
-
* Note: Uses the instant answer API, not official search API.
|
|
6
|
-
*/
|
|
7
|
-
import type { SearchPluginDefinition } from '../types.js';
|
|
8
|
-
export declare const DUCKDUCKGO_DEFINITION: SearchPluginDefinition;
|
|
9
|
-
//# sourceMappingURL=duckduckgo.d.ts.map
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DuckDuckGo Search Provider
|
|
3
|
-
*
|
|
4
|
-
* Free, privacy-focused search - great for fallback.
|
|
5
|
-
* Note: Uses the instant answer API, not official search API.
|
|
6
|
-
*/
|
|
7
|
-
// DuckDuckGo HTML search endpoint (no official API)
|
|
8
|
-
const DDG_SEARCH_URL = 'https://html.duckduckgo.com/html/';
|
|
9
|
-
class DuckDuckGoProvider {
|
|
10
|
-
metadata = DUCKDUCKGO_DEFINITION.metadata;
|
|
11
|
-
safeSearch;
|
|
12
|
-
constructor(config) {
|
|
13
|
-
this.safeSearch = config.settings?.safeSearch ?? true;
|
|
14
|
-
}
|
|
15
|
-
async search(query, options) {
|
|
16
|
-
const startTime = Date.now();
|
|
17
|
-
const limit = options?.limit || 10;
|
|
18
|
-
// Use DuckDuckGo HTML endpoint with form data
|
|
19
|
-
const formData = new URLSearchParams();
|
|
20
|
-
formData.append('q', query);
|
|
21
|
-
formData.append('kl', options?.region || 'wt-wt'); // Region
|
|
22
|
-
if (this.safeSearch || options?.safeSearch) {
|
|
23
|
-
formData.append('kp', '1'); // Safe search on
|
|
24
|
-
}
|
|
25
|
-
const response = await fetch(DDG_SEARCH_URL, {
|
|
26
|
-
method: 'POST',
|
|
27
|
-
headers: {
|
|
28
|
-
'Content-Type': 'application/x-www-form-urlencoded',
|
|
29
|
-
'User-Agent': 'profClaw/1.0',
|
|
30
|
-
},
|
|
31
|
-
body: formData.toString(),
|
|
32
|
-
});
|
|
33
|
-
if (!response.ok) {
|
|
34
|
-
throw new Error(`DuckDuckGo search failed: ${response.status}`);
|
|
35
|
-
}
|
|
36
|
-
const html = await response.text();
|
|
37
|
-
const results = this.parseResults(html, limit);
|
|
38
|
-
const searchTime = Date.now() - startTime;
|
|
39
|
-
return {
|
|
40
|
-
results,
|
|
41
|
-
query,
|
|
42
|
-
searchTime,
|
|
43
|
-
provider: 'duckduckgo',
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
parseResults(html, limit) {
|
|
47
|
-
const results = [];
|
|
48
|
-
// Simple regex parsing for DuckDuckGo HTML results
|
|
49
|
-
// Match result blocks
|
|
50
|
-
const resultRegex = /<a[^>]*class="result__a"[^>]*href="([^"]*)"[^>]*>([^<]*)<\/a>[\s\S]*?<a[^>]*class="result__snippet"[^>]*>([^<]*)/g;
|
|
51
|
-
let match;
|
|
52
|
-
while ((match = resultRegex.exec(html)) !== null && results.length < limit) {
|
|
53
|
-
const [, url, title, snippet] = match;
|
|
54
|
-
if (url && title) {
|
|
55
|
-
// DuckDuckGo wraps URLs, extract the actual URL
|
|
56
|
-
const actualUrl = this.extractUrl(url);
|
|
57
|
-
results.push({
|
|
58
|
-
title: this.decodeHtml(title.trim()),
|
|
59
|
-
url: actualUrl,
|
|
60
|
-
snippet: this.decodeHtml(snippet?.trim() || ''),
|
|
61
|
-
source: 'duckduckgo',
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
// Fallback: Try simpler pattern if main regex didn't match
|
|
66
|
-
if (results.length === 0) {
|
|
67
|
-
const linkRegex = /<a[^>]*class="[^"]*result__url[^"]*"[^>]*href="([^"]*)"[^>]*>.*?<\/a>[\s\S]*?<h2[^>]*class="[^"]*result__title[^"]*"[^>]*>[\s\S]*?<a[^>]*>([^<]*)<\/a>/g;
|
|
68
|
-
while ((match = linkRegex.exec(html)) !== null && results.length < limit) {
|
|
69
|
-
const [, url, title] = match;
|
|
70
|
-
if (url && title) {
|
|
71
|
-
results.push({
|
|
72
|
-
title: this.decodeHtml(title.trim()),
|
|
73
|
-
url: this.extractUrl(url),
|
|
74
|
-
snippet: '',
|
|
75
|
-
source: 'duckduckgo',
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
return results;
|
|
81
|
-
}
|
|
82
|
-
extractUrl(wrappedUrl) {
|
|
83
|
-
// DuckDuckGo wraps URLs like: //duckduckgo.com/l/?uddg=https%3A%2F%2Fexample.com
|
|
84
|
-
if (wrappedUrl.includes('uddg=')) {
|
|
85
|
-
const match = wrappedUrl.match(/uddg=([^&]*)/);
|
|
86
|
-
if (match) {
|
|
87
|
-
return decodeURIComponent(match[1]);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
// Return as-is if not wrapped
|
|
91
|
-
return wrappedUrl.startsWith('//') ? `https:${wrappedUrl}` : wrappedUrl;
|
|
92
|
-
}
|
|
93
|
-
decodeHtml(text) {
|
|
94
|
-
return text
|
|
95
|
-
.replace(/&/g, '&')
|
|
96
|
-
.replace(/</g, '<')
|
|
97
|
-
.replace(/>/g, '>')
|
|
98
|
-
.replace(/"/g, '"')
|
|
99
|
-
.replace(/'/g, "'")
|
|
100
|
-
.replace(/<[^>]*>/g, ''); // Strip any remaining HTML tags
|
|
101
|
-
}
|
|
102
|
-
async isAvailable() {
|
|
103
|
-
// DuckDuckGo is always available (no API key needed)
|
|
104
|
-
return true;
|
|
105
|
-
}
|
|
106
|
-
async healthCheck() {
|
|
107
|
-
try {
|
|
108
|
-
const startTime = Date.now();
|
|
109
|
-
await this.search('test', { limit: 1 });
|
|
110
|
-
const latency = Date.now() - startTime;
|
|
111
|
-
return {
|
|
112
|
-
healthy: true,
|
|
113
|
-
lastCheck: new Date(),
|
|
114
|
-
latency,
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
catch (error) {
|
|
118
|
-
return {
|
|
119
|
-
healthy: false,
|
|
120
|
-
lastCheck: new Date(),
|
|
121
|
-
errorMessage: error instanceof Error ? error.message : 'Health check failed',
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
export const DUCKDUCKGO_DEFINITION = {
|
|
127
|
-
metadata: {
|
|
128
|
-
id: 'duckduckgo',
|
|
129
|
-
name: 'DuckDuckGo',
|
|
130
|
-
description: 'Privacy-focused search - free, no API key required',
|
|
131
|
-
category: 'search',
|
|
132
|
-
icon: 'shield',
|
|
133
|
-
version: '1.0.0',
|
|
134
|
-
homepage: 'https://duckduckgo.com',
|
|
135
|
-
pricing: {
|
|
136
|
-
type: 'free',
|
|
137
|
-
},
|
|
138
|
-
rateLimit: {
|
|
139
|
-
requestsPerSecond: 1, // Be nice to DuckDuckGo
|
|
140
|
-
requestsPerMinute: 30,
|
|
141
|
-
},
|
|
142
|
-
},
|
|
143
|
-
settingsSchema: {
|
|
144
|
-
credentials: [], // No credentials needed
|
|
145
|
-
settings: [
|
|
146
|
-
{
|
|
147
|
-
key: 'safeSearch',
|
|
148
|
-
type: 'boolean',
|
|
149
|
-
label: 'Safe Search',
|
|
150
|
-
description: 'Filter explicit content from results',
|
|
151
|
-
default: true,
|
|
152
|
-
},
|
|
153
|
-
{
|
|
154
|
-
key: 'region',
|
|
155
|
-
type: 'select',
|
|
156
|
-
label: 'Region',
|
|
157
|
-
description: 'Search region preference',
|
|
158
|
-
default: 'wt-wt',
|
|
159
|
-
options: [
|
|
160
|
-
{ value: 'wt-wt', label: 'No region (worldwide)' },
|
|
161
|
-
{ value: 'us-en', label: 'United States' },
|
|
162
|
-
{ value: 'uk-en', label: 'United Kingdom' },
|
|
163
|
-
{ value: 'de-de', label: 'Germany' },
|
|
164
|
-
{ value: 'fr-fr', label: 'France' },
|
|
165
|
-
],
|
|
166
|
-
},
|
|
167
|
-
],
|
|
168
|
-
},
|
|
169
|
-
factory: (config) => new DuckDuckGoProvider(config),
|
|
170
|
-
};
|
|
171
|
-
//# sourceMappingURL=duckduckgo.js.map
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Search Provider Plugins
|
|
3
|
-
*
|
|
4
|
-
* Export all built-in search provider definitions.
|
|
5
|
-
*/
|
|
6
|
-
export { SERPER_DEFINITION } from './serper.js';
|
|
7
|
-
export { TAVILY_DEFINITION } from './tavily.js';
|
|
8
|
-
export { BRAVE_DEFINITION } from './brave.js';
|
|
9
|
-
export { DUCKDUCKGO_DEFINITION } from './duckduckgo.js';
|
|
10
|
-
export { SEARXNG_DEFINITION } from './searxng.js';
|
|
11
|
-
import type { SearchPluginDefinition } from '../types.js';
|
|
12
|
-
export declare const ALL_SEARCH_PLUGINS: SearchPluginDefinition[];
|
|
13
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Search Provider Plugins
|
|
3
|
-
*
|
|
4
|
-
* Export all built-in search provider definitions.
|
|
5
|
-
*/
|
|
6
|
-
export { SERPER_DEFINITION } from './serper.js';
|
|
7
|
-
export { TAVILY_DEFINITION } from './tavily.js';
|
|
8
|
-
export { BRAVE_DEFINITION } from './brave.js';
|
|
9
|
-
export { DUCKDUCKGO_DEFINITION } from './duckduckgo.js';
|
|
10
|
-
export { SEARXNG_DEFINITION } from './searxng.js';
|
|
11
|
-
import { SERPER_DEFINITION } from './serper.js';
|
|
12
|
-
import { TAVILY_DEFINITION } from './tavily.js';
|
|
13
|
-
import { BRAVE_DEFINITION } from './brave.js';
|
|
14
|
-
import { DUCKDUCKGO_DEFINITION } from './duckduckgo.js';
|
|
15
|
-
import { SEARXNG_DEFINITION } from './searxng.js';
|
|
16
|
-
export const ALL_SEARCH_PLUGINS = [
|
|
17
|
-
SERPER_DEFINITION,
|
|
18
|
-
TAVILY_DEFINITION,
|
|
19
|
-
BRAVE_DEFINITION,
|
|
20
|
-
DUCKDUCKGO_DEFINITION,
|
|
21
|
-
SEARXNG_DEFINITION,
|
|
22
|
-
];
|
|
23
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SearXNG Search Provider
|
|
3
|
-
*
|
|
4
|
-
* Self-hosted metasearch engine - complete privacy control.
|
|
5
|
-
* https://docs.searxng.org/
|
|
6
|
-
*/
|
|
7
|
-
import type { SearchPluginDefinition } from '../types.js';
|
|
8
|
-
export declare const SEARXNG_DEFINITION: SearchPluginDefinition;
|
|
9
|
-
//# sourceMappingURL=searxng.d.ts.map
|
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SearXNG Search Provider
|
|
3
|
-
*
|
|
4
|
-
* Self-hosted metasearch engine - complete privacy control.
|
|
5
|
-
* https://docs.searxng.org/
|
|
6
|
-
*/
|
|
7
|
-
class SearXNGProvider {
|
|
8
|
-
metadata = SEARXNG_DEFINITION.metadata;
|
|
9
|
-
baseUrl;
|
|
10
|
-
engines;
|
|
11
|
-
constructor(config) {
|
|
12
|
-
this.baseUrl = config.credentials?.baseUrl || 'http://localhost:8080';
|
|
13
|
-
this.engines = config.settings?.engines || [];
|
|
14
|
-
}
|
|
15
|
-
async search(query, options) {
|
|
16
|
-
if (!this.baseUrl) {
|
|
17
|
-
throw new Error('SearXNG base URL not configured');
|
|
18
|
-
}
|
|
19
|
-
const startTime = Date.now();
|
|
20
|
-
const params = new URLSearchParams({
|
|
21
|
-
q: query,
|
|
22
|
-
format: 'json',
|
|
23
|
-
});
|
|
24
|
-
if (options?.limit)
|
|
25
|
-
params.set('pageno', '1'); // SearXNG uses pagination
|
|
26
|
-
if (options?.language)
|
|
27
|
-
params.set('language', options.language);
|
|
28
|
-
if (options?.safeSearch)
|
|
29
|
-
params.set('safesearch', '2'); // 0=off, 1=moderate, 2=strict
|
|
30
|
-
if (this.engines.length > 0) {
|
|
31
|
-
params.set('engines', this.engines.join(','));
|
|
32
|
-
}
|
|
33
|
-
const url = `${this.baseUrl.replace(/\/$/, '')}/search?${params}`;
|
|
34
|
-
const response = await fetch(url, {
|
|
35
|
-
headers: {
|
|
36
|
-
'Accept': 'application/json',
|
|
37
|
-
},
|
|
38
|
-
});
|
|
39
|
-
if (!response.ok) {
|
|
40
|
-
const error = await response.text();
|
|
41
|
-
throw new Error(`SearXNG error: ${response.status} - ${error}`);
|
|
42
|
-
}
|
|
43
|
-
const data = await response.json();
|
|
44
|
-
const searchTime = Date.now() - startTime;
|
|
45
|
-
const limit = options?.limit || 10;
|
|
46
|
-
const results = (data.results || []).slice(0, limit).map((item) => ({
|
|
47
|
-
title: item.title,
|
|
48
|
-
url: item.url,
|
|
49
|
-
snippet: item.content || '',
|
|
50
|
-
source: 'searxng',
|
|
51
|
-
metadata: {
|
|
52
|
-
engine: item.engine,
|
|
53
|
-
engines: item.engines,
|
|
54
|
-
category: item.category,
|
|
55
|
-
score: item.score,
|
|
56
|
-
publishedDate: item.publishedDate,
|
|
57
|
-
},
|
|
58
|
-
}));
|
|
59
|
-
return {
|
|
60
|
-
results,
|
|
61
|
-
query: data.query || query,
|
|
62
|
-
totalResults: data.number_of_results,
|
|
63
|
-
searchTime,
|
|
64
|
-
provider: 'searxng',
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
async isAvailable() {
|
|
68
|
-
if (!this.baseUrl)
|
|
69
|
-
return false;
|
|
70
|
-
try {
|
|
71
|
-
const response = await fetch(`${this.baseUrl}/config`, {
|
|
72
|
-
signal: AbortSignal.timeout(5000),
|
|
73
|
-
});
|
|
74
|
-
return response.ok;
|
|
75
|
-
}
|
|
76
|
-
catch {
|
|
77
|
-
return false;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
async healthCheck() {
|
|
81
|
-
if (!this.baseUrl) {
|
|
82
|
-
return {
|
|
83
|
-
healthy: false,
|
|
84
|
-
lastCheck: new Date(),
|
|
85
|
-
errorMessage: 'Base URL not configured',
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
try {
|
|
89
|
-
const startTime = Date.now();
|
|
90
|
-
const response = await fetch(`${this.baseUrl}/config`, {
|
|
91
|
-
signal: AbortSignal.timeout(5000),
|
|
92
|
-
});
|
|
93
|
-
if (!response.ok) {
|
|
94
|
-
return {
|
|
95
|
-
healthy: false,
|
|
96
|
-
lastCheck: new Date(),
|
|
97
|
-
errorMessage: `SearXNG returned ${response.status}`,
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
const latency = Date.now() - startTime;
|
|
101
|
-
return {
|
|
102
|
-
healthy: true,
|
|
103
|
-
lastCheck: new Date(),
|
|
104
|
-
latency,
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
catch (error) {
|
|
108
|
-
return {
|
|
109
|
-
healthy: false,
|
|
110
|
-
lastCheck: new Date(),
|
|
111
|
-
errorMessage: error instanceof Error ? error.message : 'Connection failed',
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
export const SEARXNG_DEFINITION = {
|
|
117
|
-
metadata: {
|
|
118
|
-
id: 'searxng',
|
|
119
|
-
name: 'SearXNG',
|
|
120
|
-
description: 'Self-hosted metasearch - 246+ sources, complete privacy',
|
|
121
|
-
category: 'search',
|
|
122
|
-
icon: 'server',
|
|
123
|
-
version: '1.0.0',
|
|
124
|
-
homepage: 'https://docs.searxng.org/',
|
|
125
|
-
pricing: {
|
|
126
|
-
type: 'free',
|
|
127
|
-
},
|
|
128
|
-
rateLimit: {
|
|
129
|
-
requestsPerSecond: 10, // Depends on your instance
|
|
130
|
-
},
|
|
131
|
-
},
|
|
132
|
-
settingsSchema: {
|
|
133
|
-
credentials: [
|
|
134
|
-
{
|
|
135
|
-
key: 'baseUrl',
|
|
136
|
-
type: 'url',
|
|
137
|
-
label: 'Instance URL',
|
|
138
|
-
description: 'URL of your SearXNG instance (e.g., http://localhost:8080)',
|
|
139
|
-
placeholder: 'http://localhost:8080',
|
|
140
|
-
required: true,
|
|
141
|
-
},
|
|
142
|
-
],
|
|
143
|
-
settings: [
|
|
144
|
-
{
|
|
145
|
-
key: 'engines',
|
|
146
|
-
type: 'text',
|
|
147
|
-
label: 'Engines',
|
|
148
|
-
description: 'Comma-separated list of engines to use (leave empty for all)',
|
|
149
|
-
placeholder: 'google,duckduckgo,bing',
|
|
150
|
-
},
|
|
151
|
-
{
|
|
152
|
-
key: 'safeSearch',
|
|
153
|
-
type: 'boolean',
|
|
154
|
-
label: 'Safe Search',
|
|
155
|
-
description: 'Enable strict safe search filtering',
|
|
156
|
-
default: true,
|
|
157
|
-
},
|
|
158
|
-
{
|
|
159
|
-
key: 'timeout',
|
|
160
|
-
type: 'number',
|
|
161
|
-
label: 'Timeout (seconds)',
|
|
162
|
-
description: 'Request timeout in seconds',
|
|
163
|
-
default: 10,
|
|
164
|
-
validation: { min: 1, max: 60 },
|
|
165
|
-
},
|
|
166
|
-
],
|
|
167
|
-
},
|
|
168
|
-
factory: (config) => new SearXNGProvider(config),
|
|
169
|
-
};
|
|
170
|
-
//# sourceMappingURL=searxng.js.map
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Serper Search Provider
|
|
3
|
-
*
|
|
4
|
-
* Fast and cost-effective Google Search API.
|
|
5
|
-
* https://serper.dev/
|
|
6
|
-
*/
|
|
7
|
-
import type { SearchPluginDefinition } from '../types.js';
|
|
8
|
-
export declare const SERPER_DEFINITION: SearchPluginDefinition;
|
|
9
|
-
//# sourceMappingURL=serper.d.ts.map
|