gencode-ai 0.1.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/.env.example +11 -0
- package/CLAUDE.md +70 -0
- package/LICENSE +21 -0
- package/README.md +117 -0
- package/dist/agent/agent.d.ts +84 -0
- package/dist/agent/agent.d.ts.map +1 -0
- package/dist/agent/agent.js +233 -0
- package/dist/agent/agent.js.map +1 -0
- package/dist/agent/index.d.ts +6 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +6 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/types.d.ts +47 -0
- package/dist/agent/types.d.ts.map +1 -0
- package/dist/agent/types.js +5 -0
- package/dist/agent/types.js.map +1 -0
- package/dist/cli/components/App.d.ts +14 -0
- package/dist/cli/components/App.d.ts.map +1 -0
- package/dist/cli/components/App.js +395 -0
- package/dist/cli/components/App.js.map +1 -0
- package/dist/cli/components/CommandSuggestions.d.ts +13 -0
- package/dist/cli/components/CommandSuggestions.d.ts.map +1 -0
- package/dist/cli/components/CommandSuggestions.js +32 -0
- package/dist/cli/components/CommandSuggestions.js.map +1 -0
- package/dist/cli/components/Header.d.ts +9 -0
- package/dist/cli/components/Header.d.ts.map +1 -0
- package/dist/cli/components/Header.js +13 -0
- package/dist/cli/components/Header.js.map +1 -0
- package/dist/cli/components/Input.d.ts +13 -0
- package/dist/cli/components/Input.d.ts.map +1 -0
- package/dist/cli/components/Input.js +27 -0
- package/dist/cli/components/Input.js.map +1 -0
- package/dist/cli/components/Logo.d.ts +2 -0
- package/dist/cli/components/Logo.d.ts.map +1 -0
- package/dist/cli/components/Logo.js +8 -0
- package/dist/cli/components/Logo.js.map +1 -0
- package/dist/cli/components/Messages.d.ts +37 -0
- package/dist/cli/components/Messages.d.ts.map +1 -0
- package/dist/cli/components/Messages.js +106 -0
- package/dist/cli/components/Messages.js.map +1 -0
- package/dist/cli/components/ModelSelector.d.ts +13 -0
- package/dist/cli/components/ModelSelector.d.ts.map +1 -0
- package/dist/cli/components/ModelSelector.js +72 -0
- package/dist/cli/components/ModelSelector.js.map +1 -0
- package/dist/cli/components/Spinner.d.ts +12 -0
- package/dist/cli/components/Spinner.d.ts.map +1 -0
- package/dist/cli/components/Spinner.js +45 -0
- package/dist/cli/components/Spinner.js.map +1 -0
- package/dist/cli/components/index.d.ts +12 -0
- package/dist/cli/components/index.d.ts.map +1 -0
- package/dist/cli/components/index.js +12 -0
- package/dist/cli/components/index.js.map +1 -0
- package/dist/cli/components/theme.d.ts +31 -0
- package/dist/cli/components/theme.d.ts.map +1 -0
- package/dist/cli/components/theme.js +36 -0
- package/dist/cli/components/theme.js.map +1 -0
- package/dist/cli/index-legacy.d.ts +7 -0
- package/dist/cli/index-legacy.d.ts.map +1 -0
- package/dist/cli/index-legacy.js +431 -0
- package/dist/cli/index-legacy.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +116 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/ink-cli.d.ts +7 -0
- package/dist/cli/ink-cli.d.ts.map +1 -0
- package/dist/cli/ink-cli.js +105 -0
- package/dist/cli/ink-cli.js.map +1 -0
- package/dist/cli/session-picker.d.ts +16 -0
- package/dist/cli/session-picker.d.ts.map +1 -0
- package/dist/cli/session-picker.js +280 -0
- package/dist/cli/session-picker.js.map +1 -0
- package/dist/cli/ui.d.ts +61 -0
- package/dist/cli/ui.d.ts.map +1 -0
- package/dist/cli/ui.js +364 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/config/index.d.ts +7 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +6 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/manager.d.ts +31 -0
- package/dist/config/manager.d.ts.map +1 -0
- package/dist/config/manager.js +65 -0
- package/dist/config/manager.js.map +1 -0
- package/dist/config/types.d.ts +22 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +6 -0
- package/dist/config/types.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/memory/index.d.ts +10 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +9 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/init.d.ts +20 -0
- package/dist/memory/init.d.ts.map +1 -0
- package/dist/memory/init.js +332 -0
- package/dist/memory/init.js.map +1 -0
- package/dist/memory/manager.d.ts +85 -0
- package/dist/memory/manager.d.ts.map +1 -0
- package/dist/memory/manager.js +234 -0
- package/dist/memory/manager.js.map +1 -0
- package/dist/memory/types.d.ts +74 -0
- package/dist/memory/types.d.ts.map +1 -0
- package/dist/memory/types.js +6 -0
- package/dist/memory/types.js.map +1 -0
- package/dist/permissions/index.d.ts +7 -0
- package/dist/permissions/index.d.ts.map +1 -0
- package/dist/permissions/index.js +6 -0
- package/dist/permissions/index.js.map +1 -0
- package/dist/permissions/manager.d.ts +32 -0
- package/dist/permissions/manager.d.ts.map +1 -0
- package/dist/permissions/manager.js +79 -0
- package/dist/permissions/manager.js.map +1 -0
- package/dist/permissions/types.d.ts +14 -0
- package/dist/permissions/types.d.ts.map +1 -0
- package/dist/permissions/types.js +17 -0
- package/dist/permissions/types.js.map +1 -0
- package/dist/providers/anthropic.d.ts +20 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +185 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/gemini.d.ts +21 -0
- package/dist/providers/gemini.d.ts.map +1 -0
- package/dist/providers/gemini.js +241 -0
- package/dist/providers/gemini.js.map +1 -0
- package/dist/providers/index.d.ts +34 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +72 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/openai.d.ts +19 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +221 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/types.d.ts +125 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +6 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/session/index.d.ts +6 -0
- package/dist/session/index.d.ts.map +1 -0
- package/dist/session/index.js +6 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/manager.d.ts +101 -0
- package/dist/session/manager.d.ts.map +1 -0
- package/dist/session/manager.js +295 -0
- package/dist/session/manager.js.map +1 -0
- package/dist/session/types.d.ts +39 -0
- package/dist/session/types.d.ts.map +1 -0
- package/dist/session/types.js +10 -0
- package/dist/session/types.js.map +1 -0
- package/dist/tools/builtin/bash.d.ts +7 -0
- package/dist/tools/builtin/bash.d.ts.map +1 -0
- package/dist/tools/builtin/bash.js +80 -0
- package/dist/tools/builtin/bash.js.map +1 -0
- package/dist/tools/builtin/edit.d.ts +7 -0
- package/dist/tools/builtin/edit.d.ts.map +1 -0
- package/dist/tools/builtin/edit.js +32 -0
- package/dist/tools/builtin/edit.js.map +1 -0
- package/dist/tools/builtin/glob.d.ts +7 -0
- package/dist/tools/builtin/glob.d.ts.map +1 -0
- package/dist/tools/builtin/glob.js +36 -0
- package/dist/tools/builtin/glob.js.map +1 -0
- package/dist/tools/builtin/grep.d.ts +7 -0
- package/dist/tools/builtin/grep.d.ts.map +1 -0
- package/dist/tools/builtin/grep.js +59 -0
- package/dist/tools/builtin/grep.js.map +1 -0
- package/dist/tools/builtin/read.d.ts +7 -0
- package/dist/tools/builtin/read.d.ts.map +1 -0
- package/dist/tools/builtin/read.js +29 -0
- package/dist/tools/builtin/read.js.map +1 -0
- package/dist/tools/builtin/write.d.ts +7 -0
- package/dist/tools/builtin/write.d.ts.map +1 -0
- package/dist/tools/builtin/write.js +24 -0
- package/dist/tools/builtin/write.js.map +1 -0
- package/dist/tools/index.d.ts +38 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +32 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/registry.d.ts +22 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +71 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/types.d.ts +62 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +126 -0
- package/dist/tools/types.js.map +1 -0
- package/docs/README.md +16 -0
- package/docs/proposals/0001-web-fetch-tool.md +293 -0
- package/docs/proposals/0002-web-search-tool.md +306 -0
- package/docs/proposals/0003-task-subagents.md +333 -0
- package/docs/proposals/0004-plan-mode.md +338 -0
- package/docs/proposals/0005-todo-system.md +299 -0
- package/docs/proposals/0006-memory-system.md +539 -0
- package/docs/proposals/0007-context-management.md +429 -0
- package/docs/proposals/0008-checkpointing.md +327 -0
- package/docs/proposals/0009-hooks-system.md +343 -0
- package/docs/proposals/0010-mcp-integration.md +382 -0
- package/docs/proposals/0011-custom-commands.md +374 -0
- package/docs/proposals/0012-ask-user-question.md +317 -0
- package/docs/proposals/0013-multi-edit-tool.md +345 -0
- package/docs/proposals/0014-lsp-tool.md +478 -0
- package/docs/proposals/0015-ls-tool.md +407 -0
- package/docs/proposals/0016-kill-shell-tool.md +455 -0
- package/docs/proposals/0017-background-tasks.md +489 -0
- package/docs/proposals/0018-parallel-tool-execution.md +415 -0
- package/docs/proposals/0019-session-enhancements.md +462 -0
- package/docs/proposals/0020-session-summarization.md +447 -0
- package/docs/proposals/0021-skills-system.md +409 -0
- package/docs/proposals/0022-plugin-system.md +467 -0
- package/docs/proposals/0023-permission-enhancements.md +470 -0
- package/docs/proposals/0024-keyboard-shortcuts.md +443 -0
- package/docs/proposals/0025-cost-tracking.md +447 -0
- package/docs/proposals/0026-git-integration.md +475 -0
- package/docs/proposals/0027-enhanced-read-tool.md +514 -0
- package/docs/proposals/0028-enhanced-bash-tool.md +511 -0
- package/docs/proposals/0029-notebook-edit-tool.md +413 -0
- package/docs/proposals/0030-plugin-marketplace.md +360 -0
- package/docs/proposals/0031-command-suggestions.md +295 -0
- package/docs/proposals/0032-ide-integrations.md +328 -0
- package/docs/proposals/0033-enterprise-deployment.md +221 -0
- package/docs/proposals/0034-sandboxing.md +273 -0
- package/docs/proposals/0035-auto-updater.md +311 -0
- package/docs/proposals/0036-enhanced-glob-tool.md +267 -0
- package/docs/proposals/0037-enhanced-grep-tool.md +360 -0
- package/docs/proposals/0038-interactive-cli-ui.md +373 -0
- package/docs/proposals/0039-streaming-enhancements.md +359 -0
- package/docs/proposals/0040-multi-provider-enhancements.md +369 -0
- package/docs/proposals/README.md +84 -0
- package/docs/proposals/TEMPLATE.md +57 -0
- package/docs/proposals/research/claude-code-research.md +307 -0
- package/examples/agent-demo.ts +115 -0
- package/examples/basic.ts +166 -0
- package/package.json +50 -0
- package/src/agent/agent.ts +276 -0
- package/src/agent/index.ts +6 -0
- package/src/agent/types.ts +62 -0
- package/src/cli/components/App.tsx +565 -0
- package/src/cli/components/CommandSuggestions.tsx +58 -0
- package/src/cli/components/Header.tsx +36 -0
- package/src/cli/components/Input.tsx +60 -0
- package/src/cli/components/Logo.tsx +16 -0
- package/src/cli/components/Messages.tsx +210 -0
- package/src/cli/components/ModelSelector.tsx +135 -0
- package/src/cli/components/Spinner.tsx +72 -0
- package/src/cli/components/index.ts +21 -0
- package/src/cli/components/theme.ts +36 -0
- package/src/cli/index.tsx +136 -0
- package/src/config/index.ts +7 -0
- package/src/config/manager.ts +77 -0
- package/src/config/types.ts +25 -0
- package/src/index.ts +86 -0
- package/src/permissions/index.ts +7 -0
- package/src/permissions/manager.ts +97 -0
- package/src/permissions/types.ts +29 -0
- package/src/providers/anthropic.ts +224 -0
- package/src/providers/gemini.ts +295 -0
- package/src/providers/index.ts +97 -0
- package/src/providers/openai.ts +261 -0
- package/src/providers/types.ts +181 -0
- package/src/session/index.ts +6 -0
- package/src/session/manager.ts +354 -0
- package/src/session/types.ts +49 -0
- package/src/tools/builtin/bash.ts +92 -0
- package/src/tools/builtin/edit.ts +37 -0
- package/src/tools/builtin/glob.ts +42 -0
- package/src/tools/builtin/grep.ts +67 -0
- package/src/tools/builtin/read.ts +34 -0
- package/src/tools/builtin/write.ts +27 -0
- package/src/tools/index.ts +36 -0
- package/src/tools/registry.ts +83 -0
- package/src/tools/types.ts +172 -0
- package/tsconfig.json +21 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
# Proposal: WebFetch Tool
|
|
2
|
+
|
|
3
|
+
- **Proposal ID**: 0001
|
|
4
|
+
- **Author**: mycode team
|
|
5
|
+
- **Status**: Draft
|
|
6
|
+
- **Created**: 2025-01-15
|
|
7
|
+
- **Updated**: 2025-01-15
|
|
8
|
+
|
|
9
|
+
## Summary
|
|
10
|
+
|
|
11
|
+
Implement a WebFetch tool that fetches content from URLs, converts HTML to markdown, and optionally processes the content with an AI model. This enables the agent to access web documentation, API references, and external resources during coding tasks.
|
|
12
|
+
|
|
13
|
+
## Motivation
|
|
14
|
+
|
|
15
|
+
Currently, mycode cannot access web content. This limits the agent's ability to:
|
|
16
|
+
|
|
17
|
+
1. **Read documentation**: Can't fetch API docs or library references
|
|
18
|
+
2. **Access examples**: Can't retrieve code examples from GitHub gists
|
|
19
|
+
3. **Verify information**: Can't check current versions or changelogs
|
|
20
|
+
4. **Gather context**: Can't read linked resources in user messages
|
|
21
|
+
5. **Stay current**: Can't access up-to-date information beyond training cutoff
|
|
22
|
+
|
|
23
|
+
A WebFetch tool enables the agent to access web resources as needed.
|
|
24
|
+
|
|
25
|
+
## Claude Code Reference
|
|
26
|
+
|
|
27
|
+
Claude Code's WebFetch tool provides intelligent web content retrieval:
|
|
28
|
+
|
|
29
|
+
### Tool Definition
|
|
30
|
+
```typescript
|
|
31
|
+
WebFetch({
|
|
32
|
+
url: "https://example.com/docs",
|
|
33
|
+
prompt: "Extract the API endpoint documentation"
|
|
34
|
+
})
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Key Features
|
|
38
|
+
- Fetches URL content and converts HTML to markdown
|
|
39
|
+
- Processes content with AI model using provided prompt
|
|
40
|
+
- 15-minute self-cleaning cache for repeated requests
|
|
41
|
+
- HTTP auto-upgrade to HTTPS
|
|
42
|
+
- Redirect handling with notification
|
|
43
|
+
- Large content summarization
|
|
44
|
+
|
|
45
|
+
### Example Usage
|
|
46
|
+
```
|
|
47
|
+
User: What's the latest version of React?
|
|
48
|
+
|
|
49
|
+
Agent: Let me check the React documentation.
|
|
50
|
+
[WebFetch: https://react.dev/versions]
|
|
51
|
+
|
|
52
|
+
Based on the React documentation, the latest version is React 19...
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Redirect Handling
|
|
56
|
+
When a URL redirects to a different host:
|
|
57
|
+
```
|
|
58
|
+
The URL redirected to: https://new-host.com/page
|
|
59
|
+
Please make a new WebFetch request with this URL.
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Detailed Design
|
|
63
|
+
|
|
64
|
+
### API Design
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
// src/tools/web-fetch/types.ts
|
|
68
|
+
interface WebFetchInput {
|
|
69
|
+
url: string; // URL to fetch (must be valid)
|
|
70
|
+
prompt: string; // Instructions for processing content
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
interface WebFetchOutput {
|
|
74
|
+
success: boolean;
|
|
75
|
+
content?: string; // Processed content
|
|
76
|
+
redirectUrl?: string; // If redirect to different host
|
|
77
|
+
error?: string;
|
|
78
|
+
metadata?: {
|
|
79
|
+
title: string;
|
|
80
|
+
contentLength: number;
|
|
81
|
+
contentType: string;
|
|
82
|
+
fetchedAt: Date;
|
|
83
|
+
cached: boolean;
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
interface WebFetchConfig {
|
|
88
|
+
maxContentSize: number; // Default: 5MB
|
|
89
|
+
timeout: number; // Default: 30000ms
|
|
90
|
+
cacheTimeout: number; // Default: 15 minutes
|
|
91
|
+
userAgent: string; // Custom user agent
|
|
92
|
+
allowedDomains?: string[]; // Whitelist (optional)
|
|
93
|
+
blockedDomains?: string[]; // Blacklist (optional)
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
// src/tools/web-fetch/web-fetch-tool.ts
|
|
99
|
+
const webFetchTool: Tool<WebFetchInput> = {
|
|
100
|
+
name: 'WebFetch',
|
|
101
|
+
description: `Fetch content from a URL and process it with AI.
|
|
102
|
+
|
|
103
|
+
Features:
|
|
104
|
+
- Converts HTML to clean markdown
|
|
105
|
+
- Processes content based on your prompt
|
|
106
|
+
- 15-minute cache for repeated requests
|
|
107
|
+
- Auto-upgrades HTTP to HTTPS
|
|
108
|
+
|
|
109
|
+
Usage notes:
|
|
110
|
+
- URL must be fully-formed and valid
|
|
111
|
+
- Prompt should describe what to extract
|
|
112
|
+
- For redirects to different hosts, make a new request with the provided URL
|
|
113
|
+
`,
|
|
114
|
+
parameters: z.object({
|
|
115
|
+
url: z.string().url(),
|
|
116
|
+
prompt: z.string().min(1)
|
|
117
|
+
}),
|
|
118
|
+
execute: async (input, context) => { ... }
|
|
119
|
+
};
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Implementation Approach
|
|
123
|
+
|
|
124
|
+
1. **URL Validation**: Validate and normalize URLs
|
|
125
|
+
2. **Caching**: Implement 15-minute cache with automatic cleanup
|
|
126
|
+
3. **HTML to Markdown**: Use turndown or similar library
|
|
127
|
+
4. **Content Processing**: Use current provider to process with prompt
|
|
128
|
+
5. **Redirect Handling**: Detect cross-host redirects
|
|
129
|
+
6. **Size Limits**: Truncate large content with summary
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
// Core fetch logic
|
|
133
|
+
async function fetchAndProcess(url: string, prompt: string, context: ToolContext): Promise<WebFetchOutput> {
|
|
134
|
+
// Check cache first
|
|
135
|
+
const cached = cache.get(url);
|
|
136
|
+
if (cached && !cached.expired) {
|
|
137
|
+
return processWithPrompt(cached.content, prompt, context);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Fetch URL
|
|
141
|
+
const response = await fetch(url, {
|
|
142
|
+
redirect: 'manual',
|
|
143
|
+
headers: { 'User-Agent': config.userAgent }
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
// Handle redirects
|
|
147
|
+
if (response.status >= 300 && response.status < 400) {
|
|
148
|
+
const redirectUrl = response.headers.get('Location');
|
|
149
|
+
if (isExternalRedirect(url, redirectUrl)) {
|
|
150
|
+
return { success: true, redirectUrl };
|
|
151
|
+
}
|
|
152
|
+
return fetchAndProcess(redirectUrl, prompt, context);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Convert HTML to markdown
|
|
156
|
+
const html = await response.text();
|
|
157
|
+
const markdown = htmlToMarkdown(html);
|
|
158
|
+
|
|
159
|
+
// Cache the content
|
|
160
|
+
cache.set(url, markdown, config.cacheTimeout);
|
|
161
|
+
|
|
162
|
+
// Process with AI
|
|
163
|
+
return processWithPrompt(markdown, prompt, context);
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### File Changes
|
|
168
|
+
|
|
169
|
+
| File | Action | Description |
|
|
170
|
+
|------|--------|-------------|
|
|
171
|
+
| `src/tools/web-fetch/types.ts` | Create | Type definitions |
|
|
172
|
+
| `src/tools/web-fetch/web-fetch-tool.ts` | Create | Tool implementation |
|
|
173
|
+
| `src/tools/web-fetch/html-converter.ts` | Create | HTML to markdown conversion |
|
|
174
|
+
| `src/tools/web-fetch/cache.ts` | Create | URL content cache |
|
|
175
|
+
| `src/tools/web-fetch/index.ts` | Create | Module exports |
|
|
176
|
+
| `src/tools/index.ts` | Modify | Register tool |
|
|
177
|
+
| `package.json` | Modify | Add turndown dependency |
|
|
178
|
+
|
|
179
|
+
## User Experience
|
|
180
|
+
|
|
181
|
+
### Basic Usage
|
|
182
|
+
```
|
|
183
|
+
User: What does the lodash debounce function do?
|
|
184
|
+
|
|
185
|
+
Agent: Let me check the lodash documentation.
|
|
186
|
+
[WebFetch: https://lodash.com/docs#debounce]
|
|
187
|
+
|
|
188
|
+
The lodash `debounce` function creates a debounced version of a function
|
|
189
|
+
that delays invoking until after `wait` milliseconds have elapsed since
|
|
190
|
+
the last time the debounced function was invoked...
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Redirect Notification
|
|
194
|
+
```
|
|
195
|
+
Agent: [WebFetch: https://old-docs.example.com/api]
|
|
196
|
+
|
|
197
|
+
The URL redirected to a different host: https://new-docs.example.com/api
|
|
198
|
+
Let me fetch from the new location.
|
|
199
|
+
|
|
200
|
+
[WebFetch: https://new-docs.example.com/api]
|
|
201
|
+
...
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Error Handling
|
|
205
|
+
```
|
|
206
|
+
Agent: [WebFetch: https://private-server.internal/docs]
|
|
207
|
+
|
|
208
|
+
Unable to fetch URL: Connection refused
|
|
209
|
+
The URL may be inaccessible from my environment.
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Cache Indicator
|
|
213
|
+
```
|
|
214
|
+
Agent: [WebFetch: https://react.dev/docs] (cached)
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Alternatives Considered
|
|
218
|
+
|
|
219
|
+
### Alternative 1: Raw HTML Return
|
|
220
|
+
Return raw HTML without processing.
|
|
221
|
+
|
|
222
|
+
**Pros**: Simpler, faster
|
|
223
|
+
**Cons**: Harder for agent to parse, wastes context
|
|
224
|
+
**Decision**: Rejected - Markdown conversion is essential
|
|
225
|
+
|
|
226
|
+
### Alternative 2: Browser Automation
|
|
227
|
+
Use Puppeteer/Playwright for JS-rendered sites.
|
|
228
|
+
|
|
229
|
+
**Pros**: Better for dynamic sites
|
|
230
|
+
**Cons**: Heavy dependency, slower, more complex
|
|
231
|
+
**Decision**: Deferred - Start with simple fetch, add later if needed
|
|
232
|
+
|
|
233
|
+
### Alternative 3: No AI Processing
|
|
234
|
+
Just return markdown without prompt-based processing.
|
|
235
|
+
|
|
236
|
+
**Pros**: Simpler, no extra API calls
|
|
237
|
+
**Cons**: Large pages waste context, less useful output
|
|
238
|
+
**Decision**: Rejected - Processing adds significant value
|
|
239
|
+
|
|
240
|
+
## Security Considerations
|
|
241
|
+
|
|
242
|
+
1. **SSRF Prevention**: Block internal/private IPs (localhost, 10.x, 192.168.x, etc.)
|
|
243
|
+
2. **Domain Restrictions**: Support allowlist/blocklist configuration
|
|
244
|
+
3. **Content Size**: Limit maximum content size
|
|
245
|
+
4. **Timeout**: Enforce request timeout
|
|
246
|
+
5. **Protocol**: Only allow HTTP/HTTPS
|
|
247
|
+
6. **Credentials**: Never send credentials or cookies
|
|
248
|
+
7. **User Agent**: Use identifiable user agent string
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
// SSRF protection
|
|
252
|
+
const BLOCKED_HOSTS = [
|
|
253
|
+
'localhost', '127.0.0.1', '0.0.0.0',
|
|
254
|
+
/^10\./,
|
|
255
|
+
/^192\.168\./,
|
|
256
|
+
/^172\.(1[6-9]|2[0-9]|3[0-1])\./,
|
|
257
|
+
/^169\.254\./, // Link-local
|
|
258
|
+
/^::1$/, // IPv6 localhost
|
|
259
|
+
];
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
## Testing Strategy
|
|
263
|
+
|
|
264
|
+
1. **Unit Tests**:
|
|
265
|
+
- URL validation
|
|
266
|
+
- HTML to markdown conversion
|
|
267
|
+
- Cache behavior
|
|
268
|
+
- SSRF protection
|
|
269
|
+
|
|
270
|
+
2. **Integration Tests**:
|
|
271
|
+
- End-to-end fetch and process
|
|
272
|
+
- Redirect handling
|
|
273
|
+
- Error cases
|
|
274
|
+
|
|
275
|
+
3. **Manual Testing**:
|
|
276
|
+
- Various website types
|
|
277
|
+
- Large pages
|
|
278
|
+
- Redirect chains
|
|
279
|
+
|
|
280
|
+
## Migration Path
|
|
281
|
+
|
|
282
|
+
1. **Phase 1**: Basic fetch and markdown conversion
|
|
283
|
+
2. **Phase 2**: AI processing with prompt
|
|
284
|
+
3. **Phase 3**: Caching system
|
|
285
|
+
4. **Phase 4**: Domain restrictions and security hardening
|
|
286
|
+
|
|
287
|
+
No breaking changes to existing functionality.
|
|
288
|
+
|
|
289
|
+
## References
|
|
290
|
+
|
|
291
|
+
- [Claude Code WebFetch Documentation](https://code.claude.com/docs/en/tools)
|
|
292
|
+
- [Turndown (HTML to Markdown)](https://github.com/mixmark-io/turndown)
|
|
293
|
+
- [OWASP SSRF Prevention](https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html)
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
# Proposal: WebSearch Tool
|
|
2
|
+
|
|
3
|
+
- **Proposal ID**: 0002
|
|
4
|
+
- **Author**: mycode team
|
|
5
|
+
- **Status**: Draft
|
|
6
|
+
- **Created**: 2025-01-15
|
|
7
|
+
- **Updated**: 2025-01-15
|
|
8
|
+
|
|
9
|
+
## Summary
|
|
10
|
+
|
|
11
|
+
Implement a WebSearch tool that enables the agent to search the web and use results to inform responses. This provides access to current information, recent documentation, and up-to-date technical resources beyond the model's training cutoff.
|
|
12
|
+
|
|
13
|
+
## Motivation
|
|
14
|
+
|
|
15
|
+
Currently, mycode cannot search the web. This limits the agent when:
|
|
16
|
+
|
|
17
|
+
1. **Outdated information**: Model knowledge has a cutoff date
|
|
18
|
+
2. **New libraries**: Can't find docs for recently released packages
|
|
19
|
+
3. **Current events**: Can't access recent security advisories, updates
|
|
20
|
+
4. **Error debugging**: Can't search for recent solutions to errors
|
|
21
|
+
5. **Best practices**: Can't find current community recommendations
|
|
22
|
+
|
|
23
|
+
A WebSearch tool enables access to current web information.
|
|
24
|
+
|
|
25
|
+
## Claude Code Reference
|
|
26
|
+
|
|
27
|
+
Claude Code's WebSearch tool provides intelligent web searching:
|
|
28
|
+
|
|
29
|
+
### Tool Definition
|
|
30
|
+
```typescript
|
|
31
|
+
WebSearch({
|
|
32
|
+
query: "React 19 new features 2025",
|
|
33
|
+
allowed_domains: ["react.dev", "github.com"], // Optional
|
|
34
|
+
blocked_domains: ["spam-site.com"] // Optional
|
|
35
|
+
})
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Key Features
|
|
39
|
+
- Returns formatted search results with links
|
|
40
|
+
- Supports domain filtering (allow/block lists)
|
|
41
|
+
- Results include titles and URLs as markdown hyperlinks
|
|
42
|
+
- Requires source citation in responses
|
|
43
|
+
- Minimum 2-character query
|
|
44
|
+
|
|
45
|
+
### Example Usage
|
|
46
|
+
```
|
|
47
|
+
User: What's new in TypeScript 5.4?
|
|
48
|
+
|
|
49
|
+
Agent: Let me search for the latest TypeScript updates.
|
|
50
|
+
[WebSearch: "TypeScript 5.4 new features 2025"]
|
|
51
|
+
|
|
52
|
+
Based on my search, TypeScript 5.4 introduces:
|
|
53
|
+
- NoInfer utility type for better type inference
|
|
54
|
+
- Improved narrowing for closures
|
|
55
|
+
...
|
|
56
|
+
|
|
57
|
+
Sources:
|
|
58
|
+
- [TypeScript 5.4 Release Notes](https://www.typescriptlang.org/docs/...)
|
|
59
|
+
- [What's New in TypeScript 5.4](https://devblogs.microsoft.com/...)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Source Citation Requirement
|
|
63
|
+
Claude Code mandates including sources after answering:
|
|
64
|
+
```
|
|
65
|
+
[Your answer here]
|
|
66
|
+
|
|
67
|
+
Sources:
|
|
68
|
+
- [Source Title 1](https://example.com/1)
|
|
69
|
+
- [Source Title 2](https://example.com/2)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Detailed Design
|
|
73
|
+
|
|
74
|
+
### API Design
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
// src/tools/web-search/types.ts
|
|
78
|
+
interface WebSearchInput {
|
|
79
|
+
query: string; // Search query (min 2 chars)
|
|
80
|
+
allowed_domains?: string[]; // Only include these domains
|
|
81
|
+
blocked_domains?: string[]; // Exclude these domains
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
interface SearchResult {
|
|
85
|
+
title: string;
|
|
86
|
+
url: string;
|
|
87
|
+
snippet: string;
|
|
88
|
+
domain: string;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
interface WebSearchOutput {
|
|
92
|
+
success: boolean;
|
|
93
|
+
results?: SearchResult[];
|
|
94
|
+
query: string;
|
|
95
|
+
error?: string;
|
|
96
|
+
metadata?: {
|
|
97
|
+
resultCount: number;
|
|
98
|
+
searchTime: number;
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
interface WebSearchConfig {
|
|
103
|
+
provider: 'google' | 'bing' | 'duckduckgo' | 'serper';
|
|
104
|
+
apiKey?: string;
|
|
105
|
+
maxResults: number; // Default: 10
|
|
106
|
+
timeout: number; // Default: 10000ms
|
|
107
|
+
safeSearch: boolean; // Default: true
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
// src/tools/web-search/web-search-tool.ts
|
|
113
|
+
const webSearchTool: Tool<WebSearchInput> = {
|
|
114
|
+
name: 'WebSearch',
|
|
115
|
+
description: `Search the web for current information.
|
|
116
|
+
|
|
117
|
+
Use this tool when you need:
|
|
118
|
+
- Up-to-date information beyond your knowledge cutoff
|
|
119
|
+
- Current documentation or release notes
|
|
120
|
+
- Recent solutions to technical problems
|
|
121
|
+
- Current best practices
|
|
122
|
+
|
|
123
|
+
IMPORTANT: After answering, include a "Sources:" section with all relevant URLs as markdown hyperlinks.
|
|
124
|
+
|
|
125
|
+
Example:
|
|
126
|
+
[Your answer]
|
|
127
|
+
|
|
128
|
+
Sources:
|
|
129
|
+
- [Title 1](https://url1)
|
|
130
|
+
- [Title 2](https://url2)
|
|
131
|
+
`,
|
|
132
|
+
parameters: z.object({
|
|
133
|
+
query: z.string().min(2),
|
|
134
|
+
allowed_domains: z.array(z.string()).optional(),
|
|
135
|
+
blocked_domains: z.array(z.string()).optional()
|
|
136
|
+
}),
|
|
137
|
+
execute: async (input, context) => { ... }
|
|
138
|
+
};
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Implementation Approach
|
|
142
|
+
|
|
143
|
+
1. **Search Provider**: Integrate with search API (Serper, Google, Bing, or DuckDuckGo)
|
|
144
|
+
2. **Query Processing**: Clean and optimize search queries
|
|
145
|
+
3. **Domain Filtering**: Apply allow/block lists to results
|
|
146
|
+
4. **Result Formatting**: Format results as markdown with links
|
|
147
|
+
5. **Rate Limiting**: Respect API rate limits
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
// Search provider abstraction
|
|
151
|
+
interface SearchProvider {
|
|
152
|
+
search(query: string, options: SearchOptions): Promise<SearchResult[]>;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Serper.dev implementation (recommended)
|
|
156
|
+
class SerperProvider implements SearchProvider {
|
|
157
|
+
async search(query: string, options: SearchOptions): Promise<SearchResult[]> {
|
|
158
|
+
const response = await fetch('https://google.serper.dev/search', {
|
|
159
|
+
method: 'POST',
|
|
160
|
+
headers: {
|
|
161
|
+
'X-API-KEY': this.apiKey,
|
|
162
|
+
'Content-Type': 'application/json'
|
|
163
|
+
},
|
|
164
|
+
body: JSON.stringify({
|
|
165
|
+
q: query,
|
|
166
|
+
num: options.maxResults
|
|
167
|
+
})
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
const data = await response.json();
|
|
171
|
+
return data.organic.map(r => ({
|
|
172
|
+
title: r.title,
|
|
173
|
+
url: r.link,
|
|
174
|
+
snippet: r.snippet,
|
|
175
|
+
domain: new URL(r.link).hostname
|
|
176
|
+
}));
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### File Changes
|
|
182
|
+
|
|
183
|
+
| File | Action | Description |
|
|
184
|
+
|------|--------|-------------|
|
|
185
|
+
| `src/tools/web-search/types.ts` | Create | Type definitions |
|
|
186
|
+
| `src/tools/web-search/web-search-tool.ts` | Create | Tool implementation |
|
|
187
|
+
| `src/tools/web-search/providers/` | Create | Search provider implementations |
|
|
188
|
+
| `src/tools/web-search/index.ts` | Create | Module exports |
|
|
189
|
+
| `src/tools/index.ts` | Modify | Register tool |
|
|
190
|
+
| `src/config/settings-manager.ts` | Modify | Add search config |
|
|
191
|
+
|
|
192
|
+
## User Experience
|
|
193
|
+
|
|
194
|
+
### Basic Search
|
|
195
|
+
```
|
|
196
|
+
User: How do I use the new Bun test runner?
|
|
197
|
+
|
|
198
|
+
Agent: Let me search for the latest Bun testing documentation.
|
|
199
|
+
[WebSearch: "Bun test runner documentation 2025"]
|
|
200
|
+
|
|
201
|
+
Based on my search, here's how to use Bun's test runner:
|
|
202
|
+
|
|
203
|
+
1. Create a test file with `.test.ts` extension
|
|
204
|
+
2. Import `expect` and `test` from `bun:test`
|
|
205
|
+
3. Run with `bun test`
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
import { expect, test } from "bun:test";
|
|
209
|
+
|
|
210
|
+
test("2 + 2", () => {
|
|
211
|
+
expect(2 + 2).toBe(4);
|
|
212
|
+
});
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Sources:
|
|
216
|
+
- [Bun Test Runner](https://bun.sh/docs/cli/test)
|
|
217
|
+
- [Bun Testing Guide](https://bun.sh/guides/test/run-tests)
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Domain-Filtered Search
|
|
221
|
+
```
|
|
222
|
+
User: Search for React hooks best practices, only from official sources
|
|
223
|
+
|
|
224
|
+
Agent: [WebSearch: "React hooks best practices", allowed_domains: ["react.dev", "reactjs.org"]]
|
|
225
|
+
|
|
226
|
+
Here are the best practices from official React documentation...
|
|
227
|
+
|
|
228
|
+
Sources:
|
|
229
|
+
- [Rules of Hooks](https://react.dev/reference/rules/rules-of-hooks)
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Error Case
|
|
233
|
+
```
|
|
234
|
+
Agent: [WebSearch: "..."]
|
|
235
|
+
|
|
236
|
+
I wasn't able to perform the web search. This might be due to:
|
|
237
|
+
- No search API configured
|
|
238
|
+
- Rate limit exceeded
|
|
239
|
+
- Network connectivity issues
|
|
240
|
+
|
|
241
|
+
I'll answer based on my training data instead...
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Alternatives Considered
|
|
245
|
+
|
|
246
|
+
### Alternative 1: Scraping-Based Search
|
|
247
|
+
Scrape Google/Bing results directly.
|
|
248
|
+
|
|
249
|
+
**Pros**: No API costs
|
|
250
|
+
**Cons**: Terms of service violations, blocking, reliability
|
|
251
|
+
**Decision**: Rejected - Use proper search APIs
|
|
252
|
+
|
|
253
|
+
### Alternative 2: Single Provider Only
|
|
254
|
+
Only support one search provider.
|
|
255
|
+
|
|
256
|
+
**Pros**: Simpler implementation
|
|
257
|
+
**Cons**: Lock-in, single point of failure
|
|
258
|
+
**Decision**: Rejected - Provider abstraction adds flexibility
|
|
259
|
+
|
|
260
|
+
### Alternative 3: No Domain Filtering
|
|
261
|
+
Skip allow/block list feature.
|
|
262
|
+
|
|
263
|
+
**Pros**: Simpler
|
|
264
|
+
**Cons**: Less control over result quality
|
|
265
|
+
**Decision**: Rejected - Filtering adds significant value
|
|
266
|
+
|
|
267
|
+
## Security Considerations
|
|
268
|
+
|
|
269
|
+
1. **API Key Security**: Store search API keys securely
|
|
270
|
+
2. **Query Sanitization**: Sanitize search queries
|
|
271
|
+
3. **Result Validation**: Validate returned URLs
|
|
272
|
+
4. **Rate Limiting**: Prevent abuse of search API
|
|
273
|
+
5. **Safe Search**: Enable safe search by default
|
|
274
|
+
6. **Content Filtering**: Consider filtering adult/malicious content
|
|
275
|
+
|
|
276
|
+
## Testing Strategy
|
|
277
|
+
|
|
278
|
+
1. **Unit Tests**:
|
|
279
|
+
- Query validation
|
|
280
|
+
- Domain filtering logic
|
|
281
|
+
- Result formatting
|
|
282
|
+
|
|
283
|
+
2. **Integration Tests**:
|
|
284
|
+
- Provider integration (with mock)
|
|
285
|
+
- End-to-end search flow
|
|
286
|
+
|
|
287
|
+
3. **Manual Testing**:
|
|
288
|
+
- Various query types
|
|
289
|
+
- Domain filtering
|
|
290
|
+
- Error handling
|
|
291
|
+
|
|
292
|
+
## Migration Path
|
|
293
|
+
|
|
294
|
+
1. **Phase 1**: Basic search with Serper provider
|
|
295
|
+
2. **Phase 2**: Domain filtering
|
|
296
|
+
3. **Phase 3**: Additional providers
|
|
297
|
+
4. **Phase 4**: Search result caching
|
|
298
|
+
|
|
299
|
+
Configuration required: User must provide search API key.
|
|
300
|
+
|
|
301
|
+
## References
|
|
302
|
+
|
|
303
|
+
- [Claude Code WebSearch Documentation](https://code.claude.com/docs/en/tools)
|
|
304
|
+
- [Serper API](https://serper.dev/)
|
|
305
|
+
- [Google Custom Search API](https://developers.google.com/custom-search)
|
|
306
|
+
- [Bing Web Search API](https://www.microsoft.com/en-us/bing/apis/bing-web-search-api)
|