headlesscode 1.0.2
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/ATTRIBUTION.md +53 -0
- package/CODE_OF_CONDUCT.md +130 -0
- package/CONTRIBUTING.md +107 -0
- package/LICENSE +202 -0
- package/README.md +486 -0
- package/SECURITY.md +211 -0
- package/bin/headlesscode.mjs +83 -0
- package/package.json +63 -0
- package/shared/prompts/review-mode-prompt-short.md +93 -0
- package/shared/prompts/review-mode-prompt.md +281 -0
- package/shared/rules-code/rules.md +22 -0
- package/shared/stacks/cpp/rules.md +30 -0
- package/shared/stacks/fastapi/rules.md +30 -0
- package/shared/stacks/javascript/rules.md +37 -0
- package/shared/stacks/postgresql/rules.md +31 -0
- package/shared/stacks/python/rules.md +35 -0
- package/shared/stacks/react/rules.md +11 -0
- package/shared/stacks/typescript/rules.md +10 -0
- package/src/budget/budget.ts +221 -0
- package/src/budget/concurrency.ts +126 -0
- package/src/budget/cost.ts +309 -0
- package/src/budget/index.ts +8 -0
- package/src/checkpoints/cli.ts +256 -0
- package/src/checkpoints/service.ts +227 -0
- package/src/cli.ts +1535 -0
- package/src/cloud/docker-provider.ts +334 -0
- package/src/cloud/provider.ts +300 -0
- package/src/codeintel/call-graph.ts +78 -0
- package/src/codeintel/find-references.ts +123 -0
- package/src/codeintel/go-to-definition.ts +193 -0
- package/src/codeintel/handlers.ts +190 -0
- package/src/codeintel/import-graph.ts +173 -0
- package/src/codeintel/outline.ts +180 -0
- package/src/codeintel/position.ts +77 -0
- package/src/codeintel/program.ts +350 -0
- package/src/codeintel/rename-symbol.ts +213 -0
- package/src/codeintel/tools.ts +280 -0
- package/src/codemap/build.ts +135 -0
- package/src/codemap/cli.ts +190 -0
- package/src/codemap/extract.ts +339 -0
- package/src/codemap/files.ts +236 -0
- package/src/codemap/fingerprint.ts +65 -0
- package/src/codemap/flows.ts +62 -0
- package/src/codemap/html.ts +451 -0
- package/src/codemap/lock.ts +80 -0
- package/src/codemap/types.ts +101 -0
- package/src/codesearch/airunner-embedder.ts +185 -0
- package/src/codesearch/chunk.ts +339 -0
- package/src/codesearch/cli.ts +223 -0
- package/src/codesearch/embedder.ts +332 -0
- package/src/codesearch/files.ts +280 -0
- package/src/codesearch/index.ts +469 -0
- package/src/codesearch/ollama-embedder.ts +205 -0
- package/src/codesearch/search.ts +141 -0
- package/src/codesearch/types.ts +100 -0
- package/src/config/mode-models.ts +218 -0
- package/src/dashboard/aggregate.ts +364 -0
- package/src/dashboard/chat-thread.ts +141 -0
- package/src/dashboard/checkpoints.ts +124 -0
- package/src/dashboard/cli.ts +193 -0
- package/src/dashboard/codemap.ts +44 -0
- package/src/dashboard/files.ts +121 -0
- package/src/dashboard/page.ts +2803 -0
- package/src/dashboard/self-improvement-metrics.ts +282 -0
- package/src/dashboard/server.ts +1103 -0
- package/src/dashboard/session-launch.ts +310 -0
- package/src/dashboard/timeline.ts +273 -0
- package/src/dashboard/tool-exec.ts +107 -0
- package/src/dashboard/trend-cli.ts +141 -0
- package/src/dashboard/trend.ts +413 -0
- package/src/decision-proxy/cli.ts +261 -0
- package/src/decision-proxy/proxy.ts +569 -0
- package/src/deploy/gate-cli.ts +147 -0
- package/src/deploy/gate.ts +254 -0
- package/src/engine/condense.ts +512 -0
- package/src/engine/events.ts +428 -0
- package/src/engine/handoff.ts +71 -0
- package/src/engine/lazy-tools.ts +160 -0
- package/src/engine/local-explore.ts +653 -0
- package/src/engine/logger.ts +96 -0
- package/src/engine/loop.ts +5517 -0
- package/src/engine/parser.ts +347 -0
- package/src/engine/prompt.ts +860 -0
- package/src/engine/reports.ts +47 -0
- package/src/engine/stacks.ts +448 -0
- package/src/engine/types.ts +291 -0
- package/src/engine/usage.ts +186 -0
- package/src/github/app-auth.ts +161 -0
- package/src/github/cli.ts +448 -0
- package/src/github/installations.ts +133 -0
- package/src/github/pr.ts +321 -0
- package/src/github/provision.ts +118 -0
- package/src/github/push.ts +122 -0
- package/src/index-util.ts +50 -0
- package/src/index.ts +81 -0
- package/src/init/cli.ts +248 -0
- package/src/init/gitignore.ts +74 -0
- package/src/llm/ollama.ts +308 -0
- package/src/llm/openrouter.ts +868 -0
- package/src/llm/preflight.ts +367 -0
- package/src/llm/transcript-capture.ts +84 -0
- package/src/memory/embed.ts +110 -0
- package/src/memory/index.ts +22 -0
- package/src/memory/local.ts +259 -0
- package/src/memory/summarizer.ts +283 -0
- package/src/memory/types.ts +153 -0
- package/src/memory/uwuchat.ts +157 -0
- package/src/migrate/cli.ts +115 -0
- package/src/orchestrator/analyze-cli.ts +104 -0
- package/src/orchestrator/auto-split.ts +206 -0
- package/src/orchestrator/cleanup.ts +1003 -0
- package/src/orchestrator/cli.ts +3571 -0
- package/src/orchestrator/cost-estimate.ts +564 -0
- package/src/orchestrator/cost-history-cli.ts +242 -0
- package/src/orchestrator/cost-history.ts +397 -0
- package/src/orchestrator/git-sync.ts +250 -0
- package/src/orchestrator/index.ts +153 -0
- package/src/orchestrator/log-analysis.ts +0 -0
- package/src/orchestrator/merge-check.ts +108 -0
- package/src/orchestrator/pipeline.ts +411 -0
- package/src/orchestrator/resume.ts +1940 -0
- package/src/orchestrator/reviewer.ts +503 -0
- package/src/orchestrator/split.ts +296 -0
- package/src/orchestrator/state.ts +542 -0
- package/src/orchestrator/status.ts +697 -0
- package/src/orchestrator/verification-gate.ts +134 -0
- package/src/orchestrator/watch.ts +898 -0
- package/src/permissions/commands.ts +1083 -0
- package/src/permissions/config.ts +241 -0
- package/src/permissions/index.ts +12 -0
- package/src/permissions/protected-files.ts +96 -0
- package/src/permissions/store-protection.ts +272 -0
- package/src/project-store.ts +648 -0
- package/src/projects/cli.ts +382 -0
- package/src/qa/qa.ts +487 -0
- package/src/tools/browser/handler.ts +346 -0
- package/src/tools/browser/service.ts +406 -0
- package/src/tools/browser/smoke.ts +78 -0
- package/src/tools/browser/tool.ts +99 -0
- package/src/tools/executor.ts +2575 -0
- package/src/tools/language-detect.ts +183 -0
- package/src/tools/output-summarizer.ts +369 -0
- package/src/tools/run-tests.ts +302 -0
- package/src/tools/set-indentation-tool.ts +49 -0
- package/src/tools/test-selection.ts +160 -0
- package/src/vendor/tests/smoke.ts +103 -0
- package/src/vendor/zoo-code/VENDOR-NOTES.md +213 -0
- package/src/vendor/zoo-code/shim/anthropic.ts +71 -0
- package/src/vendor/zoo-code/shim/openai.d.ts +60 -0
- package/src/vendor/zoo-code/shim/os-name.ts +18 -0
- package/src/vendor/zoo-code/shim/strip-bom.ts +14 -0
- package/src/vendor/zoo-code/shim/vscode.ts +76 -0
- package/src/vendor/zoo-code/src/core/config/CustomModesManager.ts +1015 -0
- package/src/vendor/zoo-code/src/core/diff/strategies/multi-search-replace.ts +670 -0
- package/src/vendor/zoo-code/src/core/prompts/sections/capabilities.ts +46 -0
- package/src/vendor/zoo-code/src/core/prompts/sections/custom-instructions.ts +559 -0
- package/src/vendor/zoo-code/src/core/prompts/sections/index.ts +10 -0
- package/src/vendor/zoo-code/src/core/prompts/sections/markdown-formatting.ts +7 -0
- package/src/vendor/zoo-code/src/core/prompts/sections/modes.ts +35 -0
- package/src/vendor/zoo-code/src/core/prompts/sections/objective.ts +13 -0
- package/src/vendor/zoo-code/src/core/prompts/sections/rules.ts +95 -0
- package/src/vendor/zoo-code/src/core/prompts/sections/skills.ts +105 -0
- package/src/vendor/zoo-code/src/core/prompts/sections/system-info.ts +30 -0
- package/src/vendor/zoo-code/src/core/prompts/sections/tool-use-guidelines.ts +9 -0
- package/src/vendor/zoo-code/src/core/prompts/sections/tool-use.ts +7 -0
- package/src/vendor/zoo-code/src/core/prompts/system.ts +176 -0
- package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/access_mcp_resource.ts +41 -0
- package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/apply_diff.ts +40 -0
- package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/apply_patch.ts +61 -0
- package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/ask_followup_question.ts +62 -0
- package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/attempt_completion.ts +33 -0
- package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/codebase_search.ts +43 -0
- package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/converters.ts +109 -0
- package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/edit.ts +48 -0
- package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/edit_file.ts +72 -0
- package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/execute_command.ts +54 -0
- package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/generate_image.ts +51 -0
- package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/index.ts +75 -0
- package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/list_files.ts +41 -0
- package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/mcp_server.ts +75 -0
- package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/new_task.ts +39 -0
- package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/read_command_output.ts +81 -0
- package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/read_file.ts +169 -0
- package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/run_slash_command.ts +31 -0
- package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/search_files.ts +50 -0
- package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/search_replace.ts +51 -0
- package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/skill.ts +33 -0
- package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/switch_mode.ts +31 -0
- package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/update_todo_list.ts +54 -0
- package/src/vendor/zoo-code/src/core/prompts/tools/native-tools/write_to_file.ts +40 -0
- package/src/vendor/zoo-code/src/core/prompts/types.ts +12 -0
- package/src/vendor/zoo-code/src/i18n/index.ts +19 -0
- package/src/vendor/zoo-code/src/integrations/misc/extract-text.ts +81 -0
- package/src/vendor/zoo-code/src/services/checkpoints/RepoPerTaskCheckpointService.ts +15 -0
- package/src/vendor/zoo-code/src/services/checkpoints/ShadowCheckpointService.ts +553 -0
- package/src/vendor/zoo-code/src/services/checkpoints/excludes.ts +212 -0
- package/src/vendor/zoo-code/src/services/checkpoints/index.ts +3 -0
- package/src/vendor/zoo-code/src/services/checkpoints/types.ts +35 -0
- package/src/vendor/zoo-code/src/services/code-index/manager.ts +19 -0
- package/src/vendor/zoo-code/src/services/mcp/McpHub.ts +36 -0
- package/src/vendor/zoo-code/src/services/roo-config/index.ts +441 -0
- package/src/vendor/zoo-code/src/services/search/file-search.ts +143 -0
- package/src/vendor/zoo-code/src/services/skills/SkillsManager.ts +20 -0
- package/src/vendor/zoo-code/src/shared/globalFileNames.ts +9 -0
- package/src/vendor/zoo-code/src/shared/language.ts +43 -0
- package/src/vendor/zoo-code/src/shared/modes.ts +257 -0
- package/src/vendor/zoo-code/src/shared/tools.ts +385 -0
- package/src/vendor/zoo-code/src/utils/fs.ts +39 -0
- package/src/vendor/zoo-code/src/utils/globalContext.ts +22 -0
- package/src/vendor/zoo-code/src/utils/json-schema.ts +16 -0
- package/src/vendor/zoo-code/src/utils/logging.ts +21 -0
- package/src/vendor/zoo-code/src/utils/mcp-name.ts +190 -0
- package/src/vendor/zoo-code/src/utils/object.ts +18 -0
- package/src/vendor/zoo-code/src/utils/path.ts +94 -0
- package/src/vendor/zoo-code/src/utils/shell.ts +376 -0
- package/src/vendor/zoo-code/src/utils/text-normalization.ts +99 -0
- package/src/vendor/zoo-code/types/global-settings.ts +19 -0
- package/src/vendor/zoo-code/types/index.ts +22 -0
- package/src/vendor/zoo-code/types/message.ts +375 -0
- package/src/vendor/zoo-code/types/mode.ts +241 -0
- package/src/vendor/zoo-code/types/todo.ts +19 -0
- package/src/vendor/zoo-code/types/tool-params.ts +116 -0
- package/src/vendor/zoo-code/types/tool.ts +67 -0
- package/src/vendor/zoo-code/types/vscode.ts +84 -0
- package/src/vision/describe.ts +242 -0
- package/src/vision/tool.ts +91 -0
- package/src/watcher/cli.ts +369 -0
- package/src/watcher/github.ts +304 -0
- package/src/watcher/index.ts +59 -0
- package/src/watcher/state.ts +254 -0
- package/src/watcher/watch.ts +562 -0
- package/tsconfig.json +18 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type OpenAI from "openai"
|
|
2
|
+
|
|
3
|
+
const ATTEMPT_COMPLETION_DESCRIPTION = `After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again.
|
|
4
|
+
|
|
5
|
+
IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must confirm that you've received successful results from the user for any previous tool uses. If not, then DO NOT use this tool.
|
|
6
|
+
|
|
7
|
+
Parameters:
|
|
8
|
+
- result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance.
|
|
9
|
+
|
|
10
|
+
Example: Completing after updating CSS
|
|
11
|
+
{ "result": "I've updated the CSS to use flexbox layout for better responsiveness" }`
|
|
12
|
+
|
|
13
|
+
const RESULT_PARAMETER_DESCRIPTION = `Final result message to deliver to the user once the task is complete`
|
|
14
|
+
|
|
15
|
+
export default {
|
|
16
|
+
type: "function",
|
|
17
|
+
function: {
|
|
18
|
+
name: "attempt_completion",
|
|
19
|
+
description: ATTEMPT_COMPLETION_DESCRIPTION,
|
|
20
|
+
strict: true,
|
|
21
|
+
parameters: {
|
|
22
|
+
type: "object",
|
|
23
|
+
properties: {
|
|
24
|
+
result: {
|
|
25
|
+
type: "string",
|
|
26
|
+
description: RESULT_PARAMETER_DESCRIPTION,
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
required: ["result"],
|
|
30
|
+
additionalProperties: false,
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
} satisfies OpenAI.Chat.ChatCompletionTool
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type OpenAI from "openai"
|
|
2
|
+
|
|
3
|
+
const CODEBASE_SEARCH_DESCRIPTION = `Find files most relevant to the search query using semantic search. Searches based on meaning rather than exact text matches. By default searches entire workspace. Reuse the user's exact wording unless there's a clear reason not to - their phrasing often helps semantic search. Queries MUST be in English (translate if needed).
|
|
4
|
+
|
|
5
|
+
**CRITICAL: For ANY exploration of code you haven't examined yet in this conversation, you MUST use this tool FIRST before any other search or file exploration tools.** This applies throughout the entire conversation, not just at the beginning. This tool uses semantic search to find relevant code based on meaning rather than just keywords, making it far more effective than regex-based search_files for understanding implementations. Even if you've already explored some code, any new area of exploration requires codebase_search first.
|
|
6
|
+
|
|
7
|
+
Parameters:
|
|
8
|
+
- query: (required) The search query. Reuse the user's exact wording/question format unless there's a clear reason not to.
|
|
9
|
+
- path: (optional) Limit search to specific subdirectory (relative to the current workspace directory). Leave empty for entire workspace.
|
|
10
|
+
|
|
11
|
+
Example: Searching for user authentication code
|
|
12
|
+
{ "query": "User login and password hashing", "path": "src/auth" }
|
|
13
|
+
|
|
14
|
+
Example: Searching entire workspace
|
|
15
|
+
{ "query": "database connection pooling", "path": null }`
|
|
16
|
+
|
|
17
|
+
const QUERY_PARAMETER_DESCRIPTION = `Meaning-based search query describing the information you need`
|
|
18
|
+
|
|
19
|
+
const PATH_PARAMETER_DESCRIPTION = `Optional subdirectory (relative to the workspace) to limit the search scope`
|
|
20
|
+
|
|
21
|
+
export default {
|
|
22
|
+
type: "function",
|
|
23
|
+
function: {
|
|
24
|
+
name: "codebase_search",
|
|
25
|
+
description: CODEBASE_SEARCH_DESCRIPTION,
|
|
26
|
+
strict: true,
|
|
27
|
+
parameters: {
|
|
28
|
+
type: "object",
|
|
29
|
+
properties: {
|
|
30
|
+
query: {
|
|
31
|
+
type: "string",
|
|
32
|
+
description: QUERY_PARAMETER_DESCRIPTION,
|
|
33
|
+
},
|
|
34
|
+
path: {
|
|
35
|
+
type: ["string", "null"],
|
|
36
|
+
description: PATH_PARAMETER_DESCRIPTION,
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
required: ["query", "path"],
|
|
40
|
+
additionalProperties: false,
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
} satisfies OpenAI.Chat.ChatCompletionTool
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import type OpenAI from "openai"
|
|
2
|
+
import type Anthropic from "../../../../../shim/anthropic"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Converts an OpenAI ChatCompletionTool to Anthropic's Tool format.
|
|
6
|
+
*
|
|
7
|
+
* OpenAI format wraps the tool definition in a `function` object with `parameters`,
|
|
8
|
+
* while Anthropic uses a flatter structure with `input_schema`.
|
|
9
|
+
*
|
|
10
|
+
* @param tool - OpenAI ChatCompletionTool to convert
|
|
11
|
+
* @returns Anthropic Tool definition
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* const openAITool = {
|
|
16
|
+
* type: "function",
|
|
17
|
+
* function: {
|
|
18
|
+
* name: "get_weather",
|
|
19
|
+
* description: "Get weather",
|
|
20
|
+
* parameters: { type: "object", properties: {...} }
|
|
21
|
+
* }
|
|
22
|
+
* }
|
|
23
|
+
*
|
|
24
|
+
* const anthropicTool = convertOpenAIToolToAnthropic(openAITool)
|
|
25
|
+
* // Returns: { name: "get_weather", description: "Get weather", input_schema: {...} }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export function convertOpenAIToolToAnthropic(tool: OpenAI.Chat.ChatCompletionTool): Anthropic.Tool {
|
|
29
|
+
// Handle both ChatCompletionFunctionTool and ChatCompletionCustomTool
|
|
30
|
+
if (tool.type !== "function") {
|
|
31
|
+
throw new Error(`Unsupported tool type: ${tool.type}`)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
name: tool.function.name,
|
|
36
|
+
description: tool.function.description || "",
|
|
37
|
+
input_schema: tool.function.parameters as Anthropic.Tool.InputSchema,
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Converts an array of OpenAI ChatCompletionTools to Anthropic's Tool format.
|
|
43
|
+
*
|
|
44
|
+
* @param tools - Array of OpenAI ChatCompletionTools to convert
|
|
45
|
+
* @returns Array of Anthropic Tool definitions
|
|
46
|
+
*/
|
|
47
|
+
export function convertOpenAIToolsToAnthropic(tools: OpenAI.Chat.ChatCompletionTool[]): Anthropic.Tool[] {
|
|
48
|
+
return tools.map(convertOpenAIToolToAnthropic)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Converts OpenAI tool_choice to Anthropic ToolChoice format.
|
|
53
|
+
*
|
|
54
|
+
* Maps OpenAI's tool_choice parameter to Anthropic's equivalent format:
|
|
55
|
+
* - "none" → undefined (Anthropic doesn't have "none", just omit tools)
|
|
56
|
+
* - "auto" → { type: "auto" }
|
|
57
|
+
* - "required" → { type: "any" }
|
|
58
|
+
* - { type: "function", function: { name } } → { type: "tool", name }
|
|
59
|
+
*
|
|
60
|
+
* @param toolChoice - OpenAI tool_choice parameter
|
|
61
|
+
* @param parallelToolCalls - When true (default), allows parallel tool calls. When false, disables parallel tool calls.
|
|
62
|
+
* @returns Anthropic ToolChoice or undefined if tools should be omitted
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```typescript
|
|
66
|
+
* convertOpenAIToolChoiceToAnthropic("auto", false)
|
|
67
|
+
* // Returns: { type: "auto", disable_parallel_tool_use: true }
|
|
68
|
+
*
|
|
69
|
+
* convertOpenAIToolChoiceToAnthropic({ type: "function", function: { name: "get_weather" } })
|
|
70
|
+
* // Returns: { type: "tool", name: "get_weather", disable_parallel_tool_use: false }
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export function convertOpenAIToolChoiceToAnthropic(
|
|
74
|
+
toolChoice: OpenAI.Chat.ChatCompletionCreateParams["tool_choice"],
|
|
75
|
+
parallelToolCalls?: boolean,
|
|
76
|
+
): Anthropic.Messages.MessageCreateParams["tool_choice"] | undefined {
|
|
77
|
+
// Parallel tool calls are enabled by default. When parallelToolCalls is explicitly false,
|
|
78
|
+
// we disable parallel tool use to ensure one tool call at a time.
|
|
79
|
+
const disableParallelToolUse = parallelToolCalls === false
|
|
80
|
+
|
|
81
|
+
if (!toolChoice) {
|
|
82
|
+
// Default to auto with parallel tool use control
|
|
83
|
+
return { type: "auto", disable_parallel_tool_use: disableParallelToolUse }
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (typeof toolChoice === "string") {
|
|
87
|
+
switch (toolChoice) {
|
|
88
|
+
case "none":
|
|
89
|
+
return undefined // Anthropic doesn't have "none", just omit tools
|
|
90
|
+
case "auto":
|
|
91
|
+
return { type: "auto", disable_parallel_tool_use: disableParallelToolUse }
|
|
92
|
+
case "required":
|
|
93
|
+
return { type: "any", disable_parallel_tool_use: disableParallelToolUse }
|
|
94
|
+
default:
|
|
95
|
+
return { type: "auto", disable_parallel_tool_use: disableParallelToolUse }
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Handle object form { type: "function", function: { name: string } }
|
|
100
|
+
if (typeof toolChoice === "object" && "function" in toolChoice) {
|
|
101
|
+
return {
|
|
102
|
+
type: "tool",
|
|
103
|
+
name: toolChoice.function.name,
|
|
104
|
+
disable_parallel_tool_use: disableParallelToolUse,
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return { type: "auto", disable_parallel_tool_use: disableParallelToolUse }
|
|
109
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type OpenAI from "openai"
|
|
2
|
+
|
|
3
|
+
const EDIT_DESCRIPTION = `Performs exact string replacements in files.
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
- You must use your \`Read\` tool at least once in the conversation before editing. This tool will error if you attempt an edit without reading the file.
|
|
7
|
+
- When editing text from Read tool output, ensure you preserve the exact indentation (tabs/spaces) as it appears AFTER the line number prefix. The line number prefix format is: spaces + line number + tab. Everything after that tab is the actual file content to match. Never include any part of the line number prefix in the old_string or new_string.
|
|
8
|
+
- ALWAYS prefer editing existing files in the codebase. NEVER write new files unless explicitly required.
|
|
9
|
+
- Only use emojis if the user explicitly requests it. Avoid adding emojis to files unless asked.
|
|
10
|
+
- The edit will FAIL if \`old_string\` is not unique in the file. Either provide a larger string with more surrounding context to make it unique or use \`replace_all\` to change every instance of \`old_string\`.
|
|
11
|
+
- Use \`replace_all\` for replacing and renaming strings across the file. This parameter is useful if you want to rename a variable for instance.`
|
|
12
|
+
|
|
13
|
+
const edit = {
|
|
14
|
+
type: "function",
|
|
15
|
+
function: {
|
|
16
|
+
name: "edit",
|
|
17
|
+
description: EDIT_DESCRIPTION,
|
|
18
|
+
parameters: {
|
|
19
|
+
type: "object",
|
|
20
|
+
properties: {
|
|
21
|
+
file_path: {
|
|
22
|
+
type: "string",
|
|
23
|
+
description: "The path of the file to edit (relative to the working directory)",
|
|
24
|
+
},
|
|
25
|
+
old_string: {
|
|
26
|
+
type: "string",
|
|
27
|
+
description:
|
|
28
|
+
"The exact text to find in the file. Must match exactly, including all whitespace, indentation, and line endings.",
|
|
29
|
+
},
|
|
30
|
+
new_string: {
|
|
31
|
+
type: "string",
|
|
32
|
+
description:
|
|
33
|
+
"The replacement text that will replace old_string. Must include all necessary whitespace and indentation.",
|
|
34
|
+
},
|
|
35
|
+
replace_all: {
|
|
36
|
+
type: "boolean",
|
|
37
|
+
description:
|
|
38
|
+
"When true, replaces ALL occurrences of old_string in the file. When false (default), only replaces the first occurrence and errors if multiple matches exist.",
|
|
39
|
+
default: false,
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
required: ["file_path", "old_string", "new_string"],
|
|
43
|
+
additionalProperties: false,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
} satisfies OpenAI.Chat.ChatCompletionTool
|
|
47
|
+
|
|
48
|
+
export default edit
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type OpenAI from "openai"
|
|
2
|
+
|
|
3
|
+
const EDIT_FILE_DESCRIPTION = `Use this tool to replace text in an existing file, or create a new file.
|
|
4
|
+
|
|
5
|
+
This tool performs literal string replacement with support for multiple occurrences.
|
|
6
|
+
|
|
7
|
+
To be resilient to minor formatting drift, the tool normalizes line endings (CRLF/LF) for matching and may fall back to deterministic matching strategies when an exact literal match fails (exact → whitespace-tolerant match → token-based match). The original file's line endings are preserved when writing.
|
|
8
|
+
|
|
9
|
+
USAGE PATTERNS:
|
|
10
|
+
|
|
11
|
+
1. MODIFY EXISTING FILE (default):
|
|
12
|
+
- Provide file_path, old_string (text to find), and new_string (replacement)
|
|
13
|
+
- By default, expects exactly 1 occurrence of old_string
|
|
14
|
+
- Use expected_replacements to replace multiple occurrences
|
|
15
|
+
|
|
16
|
+
2. CREATE NEW FILE:
|
|
17
|
+
- Set old_string to empty string ""
|
|
18
|
+
- new_string becomes the entire file content
|
|
19
|
+
- File must not already exist
|
|
20
|
+
|
|
21
|
+
CRITICAL REQUIREMENTS:
|
|
22
|
+
|
|
23
|
+
1. EXACT MATCHING (BEST): The old_string should match the file contents EXACTLY, including:
|
|
24
|
+
- All whitespace (spaces, tabs, newlines)
|
|
25
|
+
- All indentation
|
|
26
|
+
- All punctuation and special characters
|
|
27
|
+
|
|
28
|
+
2. CONTEXT FOR UNIQUENESS: For single replacements (default), include at least 3 lines of context BEFORE and AFTER the target text to ensure uniqueness.
|
|
29
|
+
|
|
30
|
+
3. MULTIPLE REPLACEMENTS: If you need to replace multiple identical occurrences:
|
|
31
|
+
- Set expected_replacements to the exact count you expect to replace
|
|
32
|
+
- ALL occurrences will be replaced
|
|
33
|
+
|
|
34
|
+
4. NO ESCAPING: Provide the literal text - do not escape special characters.`
|
|
35
|
+
|
|
36
|
+
const edit_file = {
|
|
37
|
+
type: "function",
|
|
38
|
+
function: {
|
|
39
|
+
name: "edit_file",
|
|
40
|
+
description: EDIT_FILE_DESCRIPTION,
|
|
41
|
+
parameters: {
|
|
42
|
+
type: "object",
|
|
43
|
+
properties: {
|
|
44
|
+
file_path: {
|
|
45
|
+
type: "string",
|
|
46
|
+
description:
|
|
47
|
+
"The path to the file to modify or create. You can use either a relative path in the workspace or an absolute path. If an absolute path is provided, it will be preserved as is.",
|
|
48
|
+
},
|
|
49
|
+
old_string: {
|
|
50
|
+
type: "string",
|
|
51
|
+
description:
|
|
52
|
+
"The exact literal text to replace (must match the file contents exactly, including all whitespace and indentation). For single replacements (default), include at least 3 lines of context BEFORE and AFTER the target text. Use empty string to create a new file.",
|
|
53
|
+
},
|
|
54
|
+
new_string: {
|
|
55
|
+
type: "string",
|
|
56
|
+
description:
|
|
57
|
+
"The exact literal text to replace old_string with. When creating a new file (old_string is empty), this becomes the file content.",
|
|
58
|
+
},
|
|
59
|
+
expected_replacements: {
|
|
60
|
+
type: "number",
|
|
61
|
+
description:
|
|
62
|
+
"Number of replacements expected. Defaults to 1 if not specified. Use when you want to replace multiple occurrences of the same text.",
|
|
63
|
+
minimum: 1,
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
required: ["file_path", "old_string", "new_string"],
|
|
67
|
+
additionalProperties: false,
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
} satisfies OpenAI.Chat.ChatCompletionTool
|
|
71
|
+
|
|
72
|
+
export default edit_file
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type OpenAI from "openai"
|
|
2
|
+
|
|
3
|
+
const EXECUTE_COMMAND_DESCRIPTION = `Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Prefer relative commands and paths that avoid location sensitivity for terminal consistency.
|
|
4
|
+
|
|
5
|
+
Parameters:
|
|
6
|
+
- command: (required) The CLI command to execute. This should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions.
|
|
7
|
+
- cwd: (optional) The working directory to execute the command in
|
|
8
|
+
- timeout: (optional) Timeout in seconds. When exceeded, the command keeps running in the background and you receive the output so far. Set this for commands that may run indefinitely, such as dev servers or file watchers, so you can proceed without waiting for them to exit.
|
|
9
|
+
|
|
10
|
+
Example: Executing npm run dev
|
|
11
|
+
{ "command": "npm run dev", "cwd": null, "timeout": null }
|
|
12
|
+
|
|
13
|
+
Example: Executing ls in a specific directory if directed
|
|
14
|
+
{ "command": "ls -la", "cwd": "/home/user/projects", "timeout": null }
|
|
15
|
+
|
|
16
|
+
Example: Using relative paths
|
|
17
|
+
{ "command": "touch ./testdata/example.file", "cwd": null, "timeout": null }
|
|
18
|
+
|
|
19
|
+
Example: Running a build with a timeout
|
|
20
|
+
{ "command": "npm run build", "cwd": null, "timeout": 30 }`
|
|
21
|
+
|
|
22
|
+
const COMMAND_PARAMETER_DESCRIPTION = `Shell command to execute`
|
|
23
|
+
|
|
24
|
+
const CWD_PARAMETER_DESCRIPTION = `Optional working directory for the command, relative or absolute`
|
|
25
|
+
|
|
26
|
+
const TIMEOUT_PARAMETER_DESCRIPTION = `Timeout in seconds. When exceeded, the command continues running in the background and output collected so far is returned. Use this for long-running processes like dev servers, file watchers, or any command that may not exit on its own`
|
|
27
|
+
|
|
28
|
+
export default {
|
|
29
|
+
type: "function",
|
|
30
|
+
function: {
|
|
31
|
+
name: "execute_command",
|
|
32
|
+
description: EXECUTE_COMMAND_DESCRIPTION,
|
|
33
|
+
strict: true,
|
|
34
|
+
parameters: {
|
|
35
|
+
type: "object",
|
|
36
|
+
properties: {
|
|
37
|
+
command: {
|
|
38
|
+
type: "string",
|
|
39
|
+
description: COMMAND_PARAMETER_DESCRIPTION,
|
|
40
|
+
},
|
|
41
|
+
cwd: {
|
|
42
|
+
type: ["string", "null"],
|
|
43
|
+
description: CWD_PARAMETER_DESCRIPTION,
|
|
44
|
+
},
|
|
45
|
+
timeout: {
|
|
46
|
+
type: ["number", "null"],
|
|
47
|
+
description: TIMEOUT_PARAMETER_DESCRIPTION,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
required: ["command", "cwd", "timeout"],
|
|
51
|
+
additionalProperties: false,
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
} satisfies OpenAI.Chat.ChatCompletionTool
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type OpenAI from "openai"
|
|
2
|
+
|
|
3
|
+
const GENERATE_IMAGE_DESCRIPTION = `Request to generate or edit an image using AI models through OpenRouter API. This tool can create new images from text prompts or modify existing images based on your instructions. When an input image is provided, the AI will apply the requested edits, transformations, or enhancements to that image.
|
|
4
|
+
|
|
5
|
+
Parameters:
|
|
6
|
+
- prompt: (required) The text prompt describing what to generate or how to edit the image
|
|
7
|
+
- path: (required) The file path where the generated/edited image should be saved (relative to the current workspace directory). The tool will automatically add the appropriate image extension if not provided.
|
|
8
|
+
- image: (optional) The file path to an input image to edit or transform (relative to the current workspace directory). Supported formats: PNG, JPG, JPEG, GIF, WEBP.
|
|
9
|
+
|
|
10
|
+
Example: Generating a sunset image
|
|
11
|
+
{ "prompt": "A beautiful sunset over mountains with vibrant orange and purple colors", "path": "images/sunset.png", "image": null }
|
|
12
|
+
|
|
13
|
+
Example: Editing an existing image
|
|
14
|
+
{ "prompt": "Transform this image into a watercolor painting style", "path": "images/watercolor-output.png", "image": "images/original-photo.jpg" }
|
|
15
|
+
|
|
16
|
+
Example: Upscaling and enhancing an image
|
|
17
|
+
{ "prompt": "Upscale this image to higher resolution, enhance details, improve clarity and sharpness while maintaining the original content and composition", "path": "images/enhanced-photo.png", "image": "images/low-res-photo.jpg" }`
|
|
18
|
+
|
|
19
|
+
const PROMPT_PARAMETER_DESCRIPTION = `Text description of the image to generate or the edits to apply`
|
|
20
|
+
|
|
21
|
+
const PATH_PARAMETER_DESCRIPTION = `Filesystem path (relative to the workspace) where the resulting image should be saved`
|
|
22
|
+
|
|
23
|
+
const IMAGE_PARAMETER_DESCRIPTION = `Optional path (relative to the workspace) to an existing image to edit; supports PNG, JPG, JPEG, GIF, and WEBP`
|
|
24
|
+
|
|
25
|
+
export default {
|
|
26
|
+
type: "function",
|
|
27
|
+
function: {
|
|
28
|
+
name: "generate_image",
|
|
29
|
+
description: GENERATE_IMAGE_DESCRIPTION,
|
|
30
|
+
strict: true,
|
|
31
|
+
parameters: {
|
|
32
|
+
type: "object",
|
|
33
|
+
properties: {
|
|
34
|
+
prompt: {
|
|
35
|
+
type: "string",
|
|
36
|
+
description: PROMPT_PARAMETER_DESCRIPTION,
|
|
37
|
+
},
|
|
38
|
+
path: {
|
|
39
|
+
type: "string",
|
|
40
|
+
description: PATH_PARAMETER_DESCRIPTION,
|
|
41
|
+
},
|
|
42
|
+
image: {
|
|
43
|
+
type: ["string", "null"],
|
|
44
|
+
description: IMAGE_PARAMETER_DESCRIPTION,
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
required: ["prompt", "path", "image"],
|
|
48
|
+
additionalProperties: false,
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
} satisfies OpenAI.Chat.ChatCompletionTool
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type OpenAI from "openai"
|
|
2
|
+
import accessMcpResource from "./access_mcp_resource"
|
|
3
|
+
import { apply_diff } from "./apply_diff"
|
|
4
|
+
import applyPatch from "./apply_patch"
|
|
5
|
+
import askFollowupQuestion from "./ask_followup_question"
|
|
6
|
+
import attemptCompletion from "./attempt_completion"
|
|
7
|
+
import codebaseSearch from "./codebase_search"
|
|
8
|
+
import editTool from "./edit"
|
|
9
|
+
import executeCommand from "./execute_command"
|
|
10
|
+
import generateImage from "./generate_image"
|
|
11
|
+
import listFiles from "./list_files"
|
|
12
|
+
import newTask from "./new_task"
|
|
13
|
+
import readCommandOutput from "./read_command_output"
|
|
14
|
+
import { createReadFileTool, type ReadFileToolOptions } from "./read_file"
|
|
15
|
+
import runSlashCommand from "./run_slash_command"
|
|
16
|
+
import skill from "./skill"
|
|
17
|
+
import searchReplace from "./search_replace"
|
|
18
|
+
import edit_file from "./edit_file"
|
|
19
|
+
import searchFiles from "./search_files"
|
|
20
|
+
import switchMode from "./switch_mode"
|
|
21
|
+
import updateTodoList from "./update_todo_list"
|
|
22
|
+
import writeToFile from "./write_to_file"
|
|
23
|
+
|
|
24
|
+
export { getMcpServerTools } from "./mcp_server"
|
|
25
|
+
export { convertOpenAIToolToAnthropic, convertOpenAIToolsToAnthropic } from "./converters"
|
|
26
|
+
export type { ReadFileToolOptions } from "./read_file"
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Options for customizing the native tools array.
|
|
30
|
+
*/
|
|
31
|
+
export interface NativeToolsOptions {
|
|
32
|
+
/** Whether the model supports image processing (default: false) */
|
|
33
|
+
supportsImages?: boolean
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Get native tools array, optionally customizing based on settings.
|
|
38
|
+
*
|
|
39
|
+
* @param options - Configuration options for the tools
|
|
40
|
+
* @returns Array of native tool definitions
|
|
41
|
+
*/
|
|
42
|
+
export function getNativeTools(options: NativeToolsOptions = {}): OpenAI.Chat.ChatCompletionTool[] {
|
|
43
|
+
const { supportsImages = false } = options
|
|
44
|
+
|
|
45
|
+
const readFileOptions: ReadFileToolOptions = {
|
|
46
|
+
supportsImages,
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return [
|
|
50
|
+
accessMcpResource,
|
|
51
|
+
apply_diff,
|
|
52
|
+
applyPatch,
|
|
53
|
+
askFollowupQuestion,
|
|
54
|
+
attemptCompletion,
|
|
55
|
+
codebaseSearch,
|
|
56
|
+
executeCommand,
|
|
57
|
+
generateImage,
|
|
58
|
+
listFiles,
|
|
59
|
+
newTask,
|
|
60
|
+
readCommandOutput,
|
|
61
|
+
createReadFileTool(readFileOptions),
|
|
62
|
+
runSlashCommand,
|
|
63
|
+
skill,
|
|
64
|
+
searchReplace,
|
|
65
|
+
edit_file,
|
|
66
|
+
editTool,
|
|
67
|
+
searchFiles,
|
|
68
|
+
switchMode,
|
|
69
|
+
updateTodoList,
|
|
70
|
+
writeToFile,
|
|
71
|
+
] satisfies OpenAI.Chat.ChatCompletionTool[]
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Backward compatibility: export default tools with line ranges enabled
|
|
75
|
+
export const nativeTools = getNativeTools()
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type OpenAI from "openai"
|
|
2
|
+
|
|
3
|
+
const LIST_FILES_DESCRIPTION = `Request to list files and directories within the specified directory. If recursive is true, it will list all files and directories recursively. If recursive is false or not provided, it will only list the top-level contents. Do not use this tool to confirm the existence of files you may have created, as the user will let you know if the files were created successfully or not.
|
|
4
|
+
|
|
5
|
+
Parameters:
|
|
6
|
+
- path: (required) The path of the directory to list contents for (relative to the current workspace directory)
|
|
7
|
+
- recursive: (required) Whether to list files recursively. Use true for recursive listing, false for top-level only.
|
|
8
|
+
|
|
9
|
+
Example: Listing all files in the current directory (top-level only)
|
|
10
|
+
{ "path": ".", "recursive": false }
|
|
11
|
+
|
|
12
|
+
Example: Listing all files recursively in src directory
|
|
13
|
+
{ "path": "src", "recursive": true }`
|
|
14
|
+
|
|
15
|
+
const PATH_PARAMETER_DESCRIPTION = `Directory path to inspect, relative to the workspace`
|
|
16
|
+
|
|
17
|
+
const RECURSIVE_PARAMETER_DESCRIPTION = `Set true to list contents recursively; false to show only the top level`
|
|
18
|
+
|
|
19
|
+
export default {
|
|
20
|
+
type: "function",
|
|
21
|
+
function: {
|
|
22
|
+
name: "list_files",
|
|
23
|
+
description: LIST_FILES_DESCRIPTION,
|
|
24
|
+
strict: true,
|
|
25
|
+
parameters: {
|
|
26
|
+
type: "object",
|
|
27
|
+
properties: {
|
|
28
|
+
path: {
|
|
29
|
+
type: "string",
|
|
30
|
+
description: PATH_PARAMETER_DESCRIPTION,
|
|
31
|
+
},
|
|
32
|
+
recursive: {
|
|
33
|
+
type: "boolean",
|
|
34
|
+
description: RECURSIVE_PARAMETER_DESCRIPTION,
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
required: ["path", "recursive"],
|
|
38
|
+
additionalProperties: false,
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
} satisfies OpenAI.Chat.ChatCompletionTool
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type OpenAI from "openai"
|
|
2
|
+
import { McpHub } from "../../../../services/mcp/McpHub"
|
|
3
|
+
import { buildMcpToolName } from "../../../../utils/mcp-name"
|
|
4
|
+
import { normalizeToolSchema, type JsonSchema } from "../../../../utils/json-schema"
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Dynamically generates native tool definitions for all enabled tools across connected MCP servers.
|
|
8
|
+
* Tools are deduplicated by name to prevent API errors. When the same server exists in both
|
|
9
|
+
* global and project configs, project servers take priority (handled by McpHub.getServers()).
|
|
10
|
+
*
|
|
11
|
+
* @param mcpHub The McpHub instance containing connected servers.
|
|
12
|
+
* @returns An array of OpenAI.Chat.ChatCompletionTool definitions.
|
|
13
|
+
*/
|
|
14
|
+
export function getMcpServerTools(mcpHub?: McpHub, allowedServers?: string[]): OpenAI.Chat.ChatCompletionTool[] {
|
|
15
|
+
if (!mcpHub) {
|
|
16
|
+
return []
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let servers = mcpHub.getServers()
|
|
20
|
+
|
|
21
|
+
// Filter servers by allowlist if provided
|
|
22
|
+
if (allowedServers) {
|
|
23
|
+
const allowSet = new Set(allowedServers)
|
|
24
|
+
servers = servers.filter((s) => allowSet.has(s.name))
|
|
25
|
+
}
|
|
26
|
+
const tools: OpenAI.Chat.ChatCompletionTool[] = []
|
|
27
|
+
// Track seen tool names to prevent duplicates (e.g., when same server exists in both global and project configs)
|
|
28
|
+
const seenToolNames = new Set<string>()
|
|
29
|
+
|
|
30
|
+
for (const server of servers) {
|
|
31
|
+
if (!server.tools) {
|
|
32
|
+
continue
|
|
33
|
+
}
|
|
34
|
+
for (const tool of server.tools) {
|
|
35
|
+
// Filter tools where tool.enabledForPrompt is not explicitly false
|
|
36
|
+
if (tool.enabledForPrompt === false) {
|
|
37
|
+
continue
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Build sanitized tool name for API compliance
|
|
41
|
+
// The name is sanitized to conform to API requirements (e.g., Gemini's function name restrictions)
|
|
42
|
+
const toolName = buildMcpToolName(server.name, tool.name)
|
|
43
|
+
|
|
44
|
+
// Skip duplicate tool names - first occurrence wins (project servers come before global servers)
|
|
45
|
+
if (seenToolNames.has(toolName)) {
|
|
46
|
+
continue
|
|
47
|
+
}
|
|
48
|
+
seenToolNames.add(toolName)
|
|
49
|
+
|
|
50
|
+
const originalSchema = tool.inputSchema as Record<string, unknown> | undefined
|
|
51
|
+
|
|
52
|
+
// Normalize schema for JSON Schema 2020-12 compliance (type arrays → anyOf)
|
|
53
|
+
let parameters: JsonSchema
|
|
54
|
+
if (originalSchema) {
|
|
55
|
+
parameters = normalizeToolSchema(originalSchema) as JsonSchema
|
|
56
|
+
} else {
|
|
57
|
+
// No schema provided - create a minimal valid schema
|
|
58
|
+
parameters = { type: "object", additionalProperties: false } as JsonSchema
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const toolDefinition: OpenAI.Chat.ChatCompletionTool = {
|
|
62
|
+
type: "function",
|
|
63
|
+
function: {
|
|
64
|
+
name: toolName,
|
|
65
|
+
description: tool.description,
|
|
66
|
+
parameters: parameters as OpenAI.FunctionParameters,
|
|
67
|
+
},
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
tools.push(toolDefinition)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return tools
|
|
75
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type OpenAI from "openai"
|
|
2
|
+
|
|
3
|
+
const NEW_TASK_DESCRIPTION = `Create a new task instance in the chosen mode using your provided message and initial todo list (if required).
|
|
4
|
+
|
|
5
|
+
CRITICAL: This tool MUST be called alone. Do NOT call this tool alongside other tools in the same message turn. If you need to gather information before delegating, use other tools in a separate turn first, then call new_task by itself in the next turn.`
|
|
6
|
+
|
|
7
|
+
const MODE_PARAMETER_DESCRIPTION = `Slug of the mode to begin the new task in (e.g., code, debug, architect)`
|
|
8
|
+
|
|
9
|
+
const MESSAGE_PARAMETER_DESCRIPTION = `Initial user instructions or context for the new task`
|
|
10
|
+
|
|
11
|
+
const TODOS_PARAMETER_DESCRIPTION = `Optional initial todo list written as a markdown checklist; required when the workspace mandates todos`
|
|
12
|
+
|
|
13
|
+
export default {
|
|
14
|
+
type: "function",
|
|
15
|
+
function: {
|
|
16
|
+
name: "new_task",
|
|
17
|
+
description: NEW_TASK_DESCRIPTION,
|
|
18
|
+
strict: true,
|
|
19
|
+
parameters: {
|
|
20
|
+
type: "object",
|
|
21
|
+
properties: {
|
|
22
|
+
mode: {
|
|
23
|
+
type: "string",
|
|
24
|
+
description: MODE_PARAMETER_DESCRIPTION,
|
|
25
|
+
},
|
|
26
|
+
message: {
|
|
27
|
+
type: "string",
|
|
28
|
+
description: MESSAGE_PARAMETER_DESCRIPTION,
|
|
29
|
+
},
|
|
30
|
+
todos: {
|
|
31
|
+
type: ["string", "null"],
|
|
32
|
+
description: TODOS_PARAMETER_DESCRIPTION,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
required: ["mode", "message", "todos"],
|
|
36
|
+
additionalProperties: false,
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
} satisfies OpenAI.Chat.ChatCompletionTool
|