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,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SHIM — replaces zoo-code/src/utils/json-schema.ts.
|
|
3
|
+
*
|
|
4
|
+
* The original contains a 300-line zod-driven JSON Schema normalizer (and
|
|
5
|
+
* imports `zod/v4` types). The vendored `native-tools/mcp_server.ts` only uses
|
|
6
|
+
* `normalizeToolSchema` and `JsonSchema` to prepare MCP tool schemas. MCP
|
|
7
|
+
* servers are not wired in Phase 1, so this shim provides an identity
|
|
8
|
+
* normalization with a structural type. Needs adaptation when real MCP support
|
|
9
|
+
* lands.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export type JsonSchema = Record<string, unknown>
|
|
13
|
+
|
|
14
|
+
export function normalizeToolSchema(schema: Record<string, unknown>): Record<string, unknown> {
|
|
15
|
+
return schema
|
|
16
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SHIM — console-backed logger replacing zoo-code/src/utils/logging.ts.
|
|
3
|
+
*
|
|
4
|
+
* The original wraps VS Code output channels; the headless harness logs to
|
|
5
|
+
* stdout/stderr instead.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export const logger = {
|
|
9
|
+
info: (message: string, meta?: unknown): void => {
|
|
10
|
+
console.log(`[headlesscode] ${message}`, meta ?? "")
|
|
11
|
+
},
|
|
12
|
+
warn: (message: string, meta?: unknown): void => {
|
|
13
|
+
console.warn(`[headlesscode] ${message}`, meta ?? "")
|
|
14
|
+
},
|
|
15
|
+
error: (message: string, meta?: unknown): void => {
|
|
16
|
+
console.error(`[headlesscode] ${message}`, meta ?? "")
|
|
17
|
+
},
|
|
18
|
+
debug: (message: string, meta?: unknown): void => {
|
|
19
|
+
console.debug(`[headlesscode] ${message}`, meta ?? "")
|
|
20
|
+
},
|
|
21
|
+
}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utilities for sanitizing MCP server and tool names to conform to
|
|
3
|
+
* API function name requirements across all providers.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Separator used between MCP prefix, server name, and tool name.
|
|
8
|
+
* We use "--" (double hyphen) because:
|
|
9
|
+
* 1. It's allowed by all providers (dashes are permitted in function names)
|
|
10
|
+
* 2. It won't conflict with underscores in sanitized server/tool names
|
|
11
|
+
* 3. It's unique enough to be a reliable delimiter for parsing
|
|
12
|
+
*/
|
|
13
|
+
export const MCP_TOOL_SEPARATOR = "--"
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Prefix for all MCP tool function names.
|
|
17
|
+
*/
|
|
18
|
+
export const MCP_TOOL_PREFIX = "mcp"
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Normalize a string for comparison by treating hyphens and underscores as equivalent.
|
|
22
|
+
* This is used to match tool names when models convert hyphens to underscores.
|
|
23
|
+
*
|
|
24
|
+
* @param name - The name to normalize
|
|
25
|
+
* @returns The normalized name with all hyphens converted to underscores
|
|
26
|
+
*/
|
|
27
|
+
export function normalizeForComparison(name: string): string {
|
|
28
|
+
return name.replace(/-/g, "_")
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Normalize an MCP tool name by converting underscore separators back to hyphens.
|
|
33
|
+
* This handles the case where models (especially Claude) convert hyphens to underscores
|
|
34
|
+
* in tool names when using native tool calling.
|
|
35
|
+
*
|
|
36
|
+
* For example: "mcp__server__tool" -> "mcp--server--tool"
|
|
37
|
+
*
|
|
38
|
+
* This function uses fuzzy matching - it treats hyphens and underscores as equivalent
|
|
39
|
+
* when normalizing the separator pattern.
|
|
40
|
+
*
|
|
41
|
+
* @param toolName - The tool name that may have underscore separators
|
|
42
|
+
* @returns The normalized tool name with hyphen separators
|
|
43
|
+
*/
|
|
44
|
+
export function normalizeMcpToolName(toolName: string): string {
|
|
45
|
+
// Normalize for comparison to detect MCP tools regardless of separator style
|
|
46
|
+
const normalized = normalizeForComparison(toolName)
|
|
47
|
+
|
|
48
|
+
// Only normalize if it looks like an MCP tool (starts with mcp__)
|
|
49
|
+
if (normalized.startsWith("mcp__")) {
|
|
50
|
+
// Find the pattern: mcp{sep}server{sep}tool where sep is -- or __
|
|
51
|
+
// We need to convert the separators while preserving the rest
|
|
52
|
+
|
|
53
|
+
// First, try to parse assuming all separators are underscores
|
|
54
|
+
// Pattern: mcp__server__tool or mcp__server__tool_with_underscores
|
|
55
|
+
const parts = toolName.split(/__|--/)
|
|
56
|
+
|
|
57
|
+
if (parts.length >= 3 && parts[0].toLowerCase() === "mcp") {
|
|
58
|
+
// Reconstruct with proper -- separators
|
|
59
|
+
const serverName = parts[1]
|
|
60
|
+
const toolNamePart = parts.slice(2).join("--") // Rejoin in case tool name had separator
|
|
61
|
+
return `${MCP_TOOL_PREFIX}${MCP_TOOL_SEPARATOR}${serverName}${MCP_TOOL_SEPARATOR}${toolNamePart}`
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return toolName
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Check if a tool name is an MCP tool (starts with the MCP prefix and separator).
|
|
69
|
+
* Uses fuzzy matching to handle both hyphen and underscore separators.
|
|
70
|
+
*
|
|
71
|
+
* @param toolName - The tool name to check
|
|
72
|
+
* @returns true if the tool name starts with "mcp--" or "mcp__", false otherwise
|
|
73
|
+
*/
|
|
74
|
+
export function isMcpTool(toolName: string): boolean {
|
|
75
|
+
const normalized = normalizeForComparison(toolName)
|
|
76
|
+
return normalized.startsWith(`${MCP_TOOL_PREFIX}__`)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Sanitize a name to be safe for use in API function names.
|
|
81
|
+
* This removes special characters and ensures the name starts correctly.
|
|
82
|
+
*
|
|
83
|
+
* Note: Hyphens are preserved since they are valid in function names.
|
|
84
|
+
* Models may convert hyphens to underscores, but we handle this with
|
|
85
|
+
* fuzzy matching when parsing tool names.
|
|
86
|
+
*
|
|
87
|
+
* @param name - The original name (e.g., MCP server name or tool name)
|
|
88
|
+
* @returns A sanitized name that conforms to API requirements
|
|
89
|
+
*/
|
|
90
|
+
export function sanitizeMcpName(name: string): string {
|
|
91
|
+
if (!name) {
|
|
92
|
+
return "_"
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Replace spaces with underscores first
|
|
96
|
+
let sanitized = name.replace(/\s+/g, "_")
|
|
97
|
+
|
|
98
|
+
// Only allow alphanumeric, underscores, and hyphens
|
|
99
|
+
sanitized = sanitized.replace(/[^a-zA-Z0-9_\-]/g, "")
|
|
100
|
+
|
|
101
|
+
// Replace any double-hyphen sequences with single hyphen to avoid separator conflicts
|
|
102
|
+
sanitized = sanitized.replace(/--+/g, "-")
|
|
103
|
+
|
|
104
|
+
// Ensure the name starts with a letter or underscore
|
|
105
|
+
if (sanitized.length > 0 && !/^[a-zA-Z_]/.test(sanitized)) {
|
|
106
|
+
sanitized = "_" + sanitized
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// If empty after sanitization, use a placeholder
|
|
110
|
+
if (!sanitized) {
|
|
111
|
+
sanitized = "_unnamed"
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return sanitized
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Build a full MCP tool function name from server and tool names.
|
|
119
|
+
* The format is: mcp--{sanitized_server_name}--{sanitized_tool_name}
|
|
120
|
+
*
|
|
121
|
+
* The total length is capped at 64 characters to conform to API limits.
|
|
122
|
+
*
|
|
123
|
+
* @param serverName - The MCP server name
|
|
124
|
+
* @param toolName - The tool name
|
|
125
|
+
* @returns A sanitized function name in the format mcp--serverName--toolName
|
|
126
|
+
*/
|
|
127
|
+
export function buildMcpToolName(serverName: string, toolName: string): string {
|
|
128
|
+
const sanitizedServer = sanitizeMcpName(serverName)
|
|
129
|
+
const sanitizedTool = sanitizeMcpName(toolName)
|
|
130
|
+
|
|
131
|
+
// Build the full name: mcp--{server}--{tool}
|
|
132
|
+
const fullName = `${MCP_TOOL_PREFIX}${MCP_TOOL_SEPARATOR}${sanitizedServer}${MCP_TOOL_SEPARATOR}${sanitizedTool}`
|
|
133
|
+
|
|
134
|
+
// Truncate if necessary (max 64 chars for Gemini)
|
|
135
|
+
if (fullName.length > 64) {
|
|
136
|
+
return fullName.slice(0, 64)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return fullName
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Parse an MCP tool function name back into server and tool names.
|
|
144
|
+
* This handles both hyphen and underscore separators using fuzzy matching.
|
|
145
|
+
*
|
|
146
|
+
* @param mcpToolName - The full MCP tool name (e.g., "mcp--weather--get_forecast" or "mcp__weather__get_forecast")
|
|
147
|
+
* @returns An object with serverName and toolName, or null if parsing fails
|
|
148
|
+
*/
|
|
149
|
+
export function parseMcpToolName(mcpToolName: string): { serverName: string; toolName: string } | null {
|
|
150
|
+
// Normalize the name to handle both separator styles
|
|
151
|
+
const normalizedName = normalizeMcpToolName(mcpToolName)
|
|
152
|
+
|
|
153
|
+
const prefix = MCP_TOOL_PREFIX + MCP_TOOL_SEPARATOR
|
|
154
|
+
if (!normalizedName.startsWith(prefix)) {
|
|
155
|
+
return null
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Remove the "mcp--" prefix
|
|
159
|
+
const remainder = normalizedName.slice(prefix.length)
|
|
160
|
+
|
|
161
|
+
// Split on the separator to get server and tool names
|
|
162
|
+
const separatorIndex = remainder.indexOf(MCP_TOOL_SEPARATOR)
|
|
163
|
+
if (separatorIndex === -1) {
|
|
164
|
+
return null
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const serverName = remainder.slice(0, separatorIndex)
|
|
168
|
+
const toolName = remainder.slice(separatorIndex + MCP_TOOL_SEPARATOR.length)
|
|
169
|
+
|
|
170
|
+
if (!serverName || !toolName) {
|
|
171
|
+
return null
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return {
|
|
175
|
+
serverName,
|
|
176
|
+
toolName,
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Check if two tool names match using fuzzy comparison.
|
|
182
|
+
* Treats hyphens and underscores as equivalent.
|
|
183
|
+
*
|
|
184
|
+
* @param name1 - First tool name
|
|
185
|
+
* @param name2 - Second tool name
|
|
186
|
+
* @returns true if the names match (treating - and _ as equivalent)
|
|
187
|
+
*/
|
|
188
|
+
export function toolNamesMatch(name1: string, name2: string): boolean {
|
|
189
|
+
return normalizeForComparison(name1) === normalizeForComparison(name2)
|
|
190
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check if an object is empty (has no own enumerable properties)
|
|
3
|
+
* @param obj The object to check
|
|
4
|
+
* @returns true if the object is empty, false otherwise
|
|
5
|
+
*/
|
|
6
|
+
export function isEmpty(obj: unknown): boolean {
|
|
7
|
+
if (!obj || typeof obj !== "object") {
|
|
8
|
+
return true
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Check if it's an array
|
|
12
|
+
if (Array.isArray(obj)) {
|
|
13
|
+
return obj.length === 0
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Check if it's an object with no own properties
|
|
17
|
+
return Object.keys(obj).length === 0
|
|
18
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SHIM — replaces zoo-code/src/utils/path.ts.
|
|
3
|
+
*
|
|
4
|
+
* The original file resolves the workspace root from `vscode.workspace`. The
|
|
5
|
+
* headless harness has no VS Code, so the workspace root comes from the
|
|
6
|
+
* `HEADLESSCODE_WORKSPACE_ROOT` environment variable (falling back to
|
|
7
|
+
* `process.cwd()`).
|
|
8
|
+
*
|
|
9
|
+
* This module also installs `String.prototype.toPosix()` exactly like the
|
|
10
|
+
* original (declaration merging + prototype assignment), which the vendored
|
|
11
|
+
* prompt sections (rules.ts, system-info.ts) rely on. Import it once for its
|
|
12
|
+
* side effect, e.g. from the harness entry point or the smoke test.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import * as path from "path"
|
|
16
|
+
|
|
17
|
+
function toPosixPath(p: string): string {
|
|
18
|
+
// Extended-Length Paths in Windows start with "\\?\" and must be left alone.
|
|
19
|
+
const isExtendedLengthPath = p.startsWith("\\\\?\\")
|
|
20
|
+
if (isExtendedLengthPath) {
|
|
21
|
+
return p
|
|
22
|
+
}
|
|
23
|
+
return p.replace(/\\/g, "/")
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
declare global {
|
|
27
|
+
interface String {
|
|
28
|
+
toPosix(): string
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
String.prototype.toPosix = function (this: string): string {
|
|
33
|
+
return toPosixPath(this)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function normalizePath(p: string): string {
|
|
37
|
+
let normalized = path.normalize(p)
|
|
38
|
+
if (normalized.length > 1 && (normalized.endsWith("/") || normalized.endsWith("\\"))) {
|
|
39
|
+
normalized = normalized.slice(0, -1)
|
|
40
|
+
}
|
|
41
|
+
return normalized
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Safe path comparison that works across different platforms. */
|
|
45
|
+
export function arePathsEqual(path1?: string, path2?: string): boolean {
|
|
46
|
+
if (!path1 && !path2) {
|
|
47
|
+
return true
|
|
48
|
+
}
|
|
49
|
+
if (!path1 || !path2) {
|
|
50
|
+
return false
|
|
51
|
+
}
|
|
52
|
+
const normalized1 = normalizePath(path1)
|
|
53
|
+
const normalized2 = normalizePath(path2)
|
|
54
|
+
if (process.platform === "win32") {
|
|
55
|
+
return normalized1.toLowerCase() === normalized2.toLowerCase()
|
|
56
|
+
}
|
|
57
|
+
return normalized1 === normalized2
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function getReadablePath(cwd: string, relPath?: string): string {
|
|
61
|
+
if (relPath === undefined) {
|
|
62
|
+
return ""
|
|
63
|
+
}
|
|
64
|
+
const absolutePath = path.resolve(cwd, relPath)
|
|
65
|
+
if (arePathsEqual(path.normalize(absolutePath), path.normalize(cwd))) {
|
|
66
|
+
return path.basename(absolutePath).toPosix()
|
|
67
|
+
}
|
|
68
|
+
const normalizedRelPath = path.relative(cwd, absolutePath)
|
|
69
|
+
if (absolutePath.includes(cwd)) {
|
|
70
|
+
return normalizedRelPath.toPosix()
|
|
71
|
+
}
|
|
72
|
+
return absolutePath.toPosix()
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export const toRelativePath = (filePath: string, cwd: string): string => {
|
|
76
|
+
const relativePath = path.relative(cwd, filePath).toPosix()
|
|
77
|
+
return filePath.endsWith("/") ? relativePath + "/" : relativePath
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Headless workspace root. The original reads `vscode.workspace.workspaceFolders`;
|
|
82
|
+
* here we prefer the HEADLESSCODE_WORKSPACE_ROOT env var, then process.cwd().
|
|
83
|
+
*/
|
|
84
|
+
export const getWorkspacePath = (defaultCwdPath = ""): string => {
|
|
85
|
+
const override = process.env.HEADLESSCODE_WORKSPACE_ROOT
|
|
86
|
+
if (override) {
|
|
87
|
+
return override
|
|
88
|
+
}
|
|
89
|
+
return process.cwd() || defaultCwdPath
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export const getWorkspacePathForContext = (_contextPath?: string): string => {
|
|
93
|
+
return getWorkspacePath()
|
|
94
|
+
}
|