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,81 @@
|
|
|
1
|
+
import type OpenAI from "openai"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Native tool definition for read_command_output.
|
|
5
|
+
*
|
|
6
|
+
* This tool allows the LLM to retrieve full command output that was truncated
|
|
7
|
+
* during execute_command. When command output exceeds the preview threshold,
|
|
8
|
+
* the full output is persisted to disk and an artifact_id is provided. The
|
|
9
|
+
* LLM can then use this tool to read the full content or search within it.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const READ_COMMAND_OUTPUT_DESCRIPTION = `Retrieve the full output from a command that was truncated in execute_command. Use this tool when:
|
|
13
|
+
1. The execute_command result shows "[OUTPUT TRUNCATED - Full output saved to artifact: cmd-XXXX.txt]"
|
|
14
|
+
2. You need to see more of the command output beyond the preview
|
|
15
|
+
3. You want to search for specific content in large command output
|
|
16
|
+
|
|
17
|
+
The tool supports two modes:
|
|
18
|
+
- **Read mode**: Read output starting from a byte offset with optional limit
|
|
19
|
+
- **Search mode**: Filter lines matching a regex or literal pattern (like grep)
|
|
20
|
+
|
|
21
|
+
Parameters:
|
|
22
|
+
- artifact_id: (required) The artifact filename from the truncated output message (e.g., "cmd-1706119234567.txt")
|
|
23
|
+
- search: (optional) Pattern to filter lines. Supports regex or literal strings. Case-insensitive. **Omit this parameter entirely if you don't need to filter - do not pass null or empty string.**
|
|
24
|
+
- offset: (optional) Byte offset to start reading from. Default: 0. Use for pagination.
|
|
25
|
+
- limit: (optional) Maximum bytes to return. Default: 40KB.
|
|
26
|
+
|
|
27
|
+
Example: Reading truncated command output
|
|
28
|
+
{ "artifact_id": "cmd-1706119234567.txt" }
|
|
29
|
+
|
|
30
|
+
Example: Reading with pagination (after first 40KB)
|
|
31
|
+
{ "artifact_id": "cmd-1706119234567.txt", "offset": 40960 }
|
|
32
|
+
|
|
33
|
+
Example: Searching for errors in build output
|
|
34
|
+
{ "artifact_id": "cmd-1706119234567.txt", "search": "error|failed|Error" }
|
|
35
|
+
|
|
36
|
+
Example: Finding specific test failures
|
|
37
|
+
{ "artifact_id": "cmd-1706119234567.txt", "search": "FAIL" }`
|
|
38
|
+
|
|
39
|
+
const ARTIFACT_ID_DESCRIPTION = `The artifact filename from the truncated command output (e.g., "cmd-1706119234567.txt")`
|
|
40
|
+
|
|
41
|
+
const SEARCH_DESCRIPTION = `Optional regex or literal pattern to filter lines (case-insensitive, like grep). Omit this parameter if not searching - do not pass null or empty string.`
|
|
42
|
+
|
|
43
|
+
const OFFSET_DESCRIPTION = `Byte offset to start reading from (default: 0, for pagination)`
|
|
44
|
+
|
|
45
|
+
const LIMIT_DESCRIPTION = `Maximum bytes to return (default: 40KB)`
|
|
46
|
+
|
|
47
|
+
export default {
|
|
48
|
+
type: "function",
|
|
49
|
+
function: {
|
|
50
|
+
name: "read_command_output",
|
|
51
|
+
description: READ_COMMAND_OUTPUT_DESCRIPTION,
|
|
52
|
+
// Note: strict mode is intentionally disabled for this tool.
|
|
53
|
+
// With strict: true, OpenAI requires ALL properties to be in the 'required' array,
|
|
54
|
+
// which forces the LLM to always provide explicit values (even null) for optional params.
|
|
55
|
+
// This creates verbose tool calls and poor UX. By disabling strict mode, the LLM can
|
|
56
|
+
// omit optional parameters entirely, making the tool easier to use.
|
|
57
|
+
parameters: {
|
|
58
|
+
type: "object",
|
|
59
|
+
properties: {
|
|
60
|
+
artifact_id: {
|
|
61
|
+
type: "string",
|
|
62
|
+
description: ARTIFACT_ID_DESCRIPTION,
|
|
63
|
+
},
|
|
64
|
+
search: {
|
|
65
|
+
type: "string",
|
|
66
|
+
description: SEARCH_DESCRIPTION,
|
|
67
|
+
},
|
|
68
|
+
offset: {
|
|
69
|
+
type: "number",
|
|
70
|
+
description: OFFSET_DESCRIPTION,
|
|
71
|
+
},
|
|
72
|
+
limit: {
|
|
73
|
+
type: "number",
|
|
74
|
+
description: LIMIT_DESCRIPTION,
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
required: ["artifact_id"],
|
|
78
|
+
additionalProperties: false,
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
} satisfies OpenAI.Chat.ChatCompletionTool
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import type OpenAI from "openai"
|
|
2
|
+
|
|
3
|
+
// ─── Constants ────────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
/** Default maximum lines to return per file (Codex-inspired predictable limit) */
|
|
6
|
+
export const DEFAULT_LINE_LIMIT = 2000
|
|
7
|
+
|
|
8
|
+
/** Maximum characters per line before truncation */
|
|
9
|
+
export const MAX_LINE_LENGTH = 2000
|
|
10
|
+
|
|
11
|
+
/** Default indentation levels to include above anchor (0 = unlimited) */
|
|
12
|
+
export const DEFAULT_MAX_LEVELS = 0
|
|
13
|
+
|
|
14
|
+
// ─── Helper Functions ─────────────────────────────────────────────────────────
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Generates the file support note, optionally including image format support.
|
|
18
|
+
*
|
|
19
|
+
* @param supportsImages - Whether the model supports image processing
|
|
20
|
+
* @returns Support note string
|
|
21
|
+
*/
|
|
22
|
+
function getReadFileSupportsNote(supportsImages: boolean): string {
|
|
23
|
+
if (supportsImages) {
|
|
24
|
+
return `Supports text extraction from PDF and DOCX files. Automatically processes and returns image files (PNG, JPG, JPEG, GIF, BMP, SVG, WEBP, ICO, AVIF) for visual analysis. May not handle other binary files properly.`
|
|
25
|
+
}
|
|
26
|
+
return `Supports text extraction from PDF and DOCX files, but may not handle other binary files properly.`
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// ─── Types ────────────────────────────────────────────────────────────────────
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Options for creating the read_file tool definition.
|
|
33
|
+
*/
|
|
34
|
+
export interface ReadFileToolOptions {
|
|
35
|
+
/** Whether the model supports image processing (default: false) */
|
|
36
|
+
supportsImages?: boolean
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// ─── Schema Builder ───────────────────────────────────────────────────────────
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Creates the read_file tool definition with Codex-inspired modes.
|
|
43
|
+
*
|
|
44
|
+
* Two reading modes are supported:
|
|
45
|
+
*
|
|
46
|
+
* 1. **Slice Mode** (default): Simple offset/limit reading
|
|
47
|
+
* - Reads contiguous lines starting from `offset` (1-based, default: 1)
|
|
48
|
+
* - Limited to `limit` lines (default: 2000)
|
|
49
|
+
* - Predictable and efficient for agent planning
|
|
50
|
+
*
|
|
51
|
+
* 2. **Indentation Mode**: Semantic code block extraction
|
|
52
|
+
* - Anchored on a specific line number (1-based)
|
|
53
|
+
* - Extracts the block containing that line plus context
|
|
54
|
+
* - Respects code structure based on indentation hierarchy
|
|
55
|
+
* - Useful for extracting functions, classes, or logical blocks
|
|
56
|
+
*
|
|
57
|
+
* @param options - Configuration options for the tool
|
|
58
|
+
* @returns Native tool definition for read_file
|
|
59
|
+
*/
|
|
60
|
+
export function createReadFileTool(options: ReadFileToolOptions = {}): OpenAI.Chat.ChatCompletionTool {
|
|
61
|
+
const { supportsImages = false } = options
|
|
62
|
+
|
|
63
|
+
// Build description based on capabilities
|
|
64
|
+
const descriptionIntro =
|
|
65
|
+
"Read a file and return its contents with line numbers for diffing or discussion. IMPORTANT: This tool reads exactly one file per call. If you need multiple files, issue multiple parallel read_file calls."
|
|
66
|
+
|
|
67
|
+
const modeDescription =
|
|
68
|
+
` Supports two modes: 'slice' (default) reads lines sequentially with offset/limit; 'indentation' extracts complete semantic code blocks around an anchor line based on indentation hierarchy.` +
|
|
69
|
+
` Slice mode is ideal for initial file exploration, understanding overall structure, reading configuration/data files, or when you need a specific line range. Use it when you don't have a target line number.` +
|
|
70
|
+
` PREFER indentation mode when you have a specific line number from search results, error messages, or definition lookups - it guarantees complete, syntactically valid code blocks without mid-function truncation.` +
|
|
71
|
+
` IMPORTANT: Indentation mode requires anchor_line to be useful. Without it, only header content (imports) is returned.`
|
|
72
|
+
|
|
73
|
+
const limitNote = ` By default, returns up to ${DEFAULT_LINE_LIMIT} lines per file. Lines longer than ${MAX_LINE_LENGTH} characters are truncated.`
|
|
74
|
+
|
|
75
|
+
const description =
|
|
76
|
+
descriptionIntro +
|
|
77
|
+
modeDescription +
|
|
78
|
+
limitNote +
|
|
79
|
+
" " +
|
|
80
|
+
getReadFileSupportsNote(supportsImages) +
|
|
81
|
+
` Example: { path: 'src/app.ts' }` +
|
|
82
|
+
` Example (indentation mode): { path: 'src/app.ts', mode: 'indentation', indentation: { anchor_line: 42 } }`
|
|
83
|
+
|
|
84
|
+
const indentationProperties: Record<string, unknown> = {
|
|
85
|
+
anchor_line: {
|
|
86
|
+
type: "integer",
|
|
87
|
+
description:
|
|
88
|
+
"1-based line number to anchor the extraction. REQUIRED for meaningful indentation mode results. The extractor finds the semantic block (function, method, class) containing this line and returns it completely. Without anchor_line, indentation mode defaults to line 1 and returns only imports/header content. Obtain anchor_line from: search results, error stack traces, definition lookups, codebase_search results, or condensed file summaries (e.g., '14--28 | export class UserService' means anchor_line=14).",
|
|
89
|
+
},
|
|
90
|
+
max_levels: {
|
|
91
|
+
type: "integer",
|
|
92
|
+
description: `Maximum indentation levels to include above the anchor (indentation mode, 0 = unlimited (default)). Higher values include more parent context.`,
|
|
93
|
+
},
|
|
94
|
+
include_siblings: {
|
|
95
|
+
type: "boolean",
|
|
96
|
+
description:
|
|
97
|
+
"Include sibling blocks at the same indentation level as the anchor block (indentation mode, default: false). Useful for seeing related methods in a class.",
|
|
98
|
+
},
|
|
99
|
+
include_header: {
|
|
100
|
+
type: "boolean",
|
|
101
|
+
description:
|
|
102
|
+
"Include file header content (imports, module-level comments) at the top of output (indentation mode, default: true).",
|
|
103
|
+
},
|
|
104
|
+
max_lines: {
|
|
105
|
+
type: "integer",
|
|
106
|
+
description:
|
|
107
|
+
"Hard cap on lines returned for indentation mode. Acts as a separate limit from the top-level 'limit' parameter.",
|
|
108
|
+
},
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const properties: Record<string, unknown> = {
|
|
112
|
+
path: {
|
|
113
|
+
type: "string",
|
|
114
|
+
description: "Path to the file to read, relative to the workspace",
|
|
115
|
+
},
|
|
116
|
+
mode: {
|
|
117
|
+
type: "string",
|
|
118
|
+
enum: ["slice", "indentation"],
|
|
119
|
+
description:
|
|
120
|
+
"Reading mode. 'slice' (default): read lines sequentially with offset/limit - use for general file exploration or when you don't have a target line number (may truncate code mid-function). 'indentation': extract complete semantic code blocks containing anchor_line - PREFERRED when you have a line number because it guarantees complete, valid code blocks. WARNING: Do not use indentation mode without specifying indentation.anchor_line, or you will only get header content.",
|
|
121
|
+
},
|
|
122
|
+
offset: {
|
|
123
|
+
type: "integer",
|
|
124
|
+
description: "1-based line offset to start reading from (slice mode, default: 1)",
|
|
125
|
+
},
|
|
126
|
+
limit: {
|
|
127
|
+
type: "integer",
|
|
128
|
+
description: `Maximum number of lines to return (slice mode, default: ${DEFAULT_LINE_LIMIT})`,
|
|
129
|
+
},
|
|
130
|
+
indentation: {
|
|
131
|
+
type: "object",
|
|
132
|
+
description:
|
|
133
|
+
"Indentation mode options. Only used when mode='indentation'. You MUST specify anchor_line for useful results - it determines which code block to extract.",
|
|
134
|
+
properties: indentationProperties,
|
|
135
|
+
required: [],
|
|
136
|
+
additionalProperties: false,
|
|
137
|
+
},
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return {
|
|
141
|
+
type: "function",
|
|
142
|
+
function: {
|
|
143
|
+
name: "read_file",
|
|
144
|
+
description,
|
|
145
|
+
// PATCHED (headlesscode, not upstream): `strict: true` was set here
|
|
146
|
+
// while `required` only lists `path` — `mode`, `offset`, `limit`,
|
|
147
|
+
// and `indentation` are all genuinely optional and NOT required,
|
|
148
|
+
// which violates OpenAI's own strict-mode contract (when
|
|
149
|
+
// strict:true, every property must be in `required`). Lenient
|
|
150
|
+
// hosts silently tolerate this; DeepSeek's official API endpoint
|
|
151
|
+
// validates it correctly and rejects the whole request with
|
|
152
|
+
// HTTP 400 the moment this tool is included — confirmed live,
|
|
153
|
+
// 2026-08-01. `read_command_output.ts` right next to this file
|
|
154
|
+
// already disables strict mode for exactly this reason (see its
|
|
155
|
+
// own comment) — this is the same fix, just missed here upstream.
|
|
156
|
+
parameters: {
|
|
157
|
+
type: "object",
|
|
158
|
+
properties,
|
|
159
|
+
required: ["path"],
|
|
160
|
+
additionalProperties: false,
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
} satisfies OpenAI.Chat.ChatCompletionTool
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Default read_file tool with all parameters
|
|
168
|
+
*/
|
|
169
|
+
export const read_file = createReadFileTool()
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type OpenAI from "openai"
|
|
2
|
+
|
|
3
|
+
const RUN_SLASH_COMMAND_DESCRIPTION = `Execute a slash command to get specific instructions or content. Slash commands are predefined templates that provide detailed guidance for common tasks.`
|
|
4
|
+
|
|
5
|
+
const COMMAND_PARAMETER_DESCRIPTION = `Name of the slash command to run (e.g., init, test, deploy)`
|
|
6
|
+
|
|
7
|
+
const ARGS_PARAMETER_DESCRIPTION = `Optional additional context or arguments for the command`
|
|
8
|
+
|
|
9
|
+
export default {
|
|
10
|
+
type: "function",
|
|
11
|
+
function: {
|
|
12
|
+
name: "run_slash_command",
|
|
13
|
+
description: RUN_SLASH_COMMAND_DESCRIPTION,
|
|
14
|
+
strict: true,
|
|
15
|
+
parameters: {
|
|
16
|
+
type: "object",
|
|
17
|
+
properties: {
|
|
18
|
+
command: {
|
|
19
|
+
type: "string",
|
|
20
|
+
description: COMMAND_PARAMETER_DESCRIPTION,
|
|
21
|
+
},
|
|
22
|
+
args: {
|
|
23
|
+
type: ["string", "null"],
|
|
24
|
+
description: ARGS_PARAMETER_DESCRIPTION,
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
required: ["command", "args"],
|
|
28
|
+
additionalProperties: false,
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
} satisfies OpenAI.Chat.ChatCompletionTool
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type OpenAI from "openai"
|
|
2
|
+
|
|
3
|
+
const SEARCH_FILES_DESCRIPTION = `Request to perform a regex search across files in a specified directory, providing context-rich results. This tool searches for patterns or specific content across multiple files, displaying each match with encapsulating context.
|
|
4
|
+
|
|
5
|
+
Craft your regex patterns carefully to balance specificity and flexibility. Use this tool to find code patterns, TODO comments, function definitions, or any text-based information across the project. The results include surrounding context, so analyze the surrounding code to better understand the matches. Leverage this tool in combination with other tools for more comprehensive analysis.
|
|
6
|
+
|
|
7
|
+
Parameters:
|
|
8
|
+
- path: (required) The path of the directory to search in (relative to the current workspace directory). This directory will be recursively searched.
|
|
9
|
+
- regex: (required) The regular expression pattern to search for. Uses Rust regex syntax.
|
|
10
|
+
- file_pattern: (optional) Glob pattern to filter files (e.g., '*.ts' for TypeScript files). If not provided, it will search all files (*).
|
|
11
|
+
|
|
12
|
+
Example: Searching for all .ts files in the current directory
|
|
13
|
+
{ "path": ".", "regex": ".*", "file_pattern": "*.ts" }
|
|
14
|
+
|
|
15
|
+
Example: Searching for function definitions in JavaScript files
|
|
16
|
+
{ "path": "src", "regex": "function\\s+\\w+", "file_pattern": "*.js" }`
|
|
17
|
+
|
|
18
|
+
const PATH_PARAMETER_DESCRIPTION = `Directory to search recursively, relative to the workspace`
|
|
19
|
+
|
|
20
|
+
const REGEX_PARAMETER_DESCRIPTION = `Rust-compatible regular expression pattern to match`
|
|
21
|
+
|
|
22
|
+
const FILE_PATTERN_PARAMETER_DESCRIPTION = `Optional glob to limit which files are searched (e.g., *.ts)`
|
|
23
|
+
|
|
24
|
+
export default {
|
|
25
|
+
type: "function",
|
|
26
|
+
function: {
|
|
27
|
+
name: "search_files",
|
|
28
|
+
description: SEARCH_FILES_DESCRIPTION,
|
|
29
|
+
strict: true,
|
|
30
|
+
parameters: {
|
|
31
|
+
type: "object",
|
|
32
|
+
properties: {
|
|
33
|
+
path: {
|
|
34
|
+
type: "string",
|
|
35
|
+
description: PATH_PARAMETER_DESCRIPTION,
|
|
36
|
+
},
|
|
37
|
+
regex: {
|
|
38
|
+
type: "string",
|
|
39
|
+
description: REGEX_PARAMETER_DESCRIPTION,
|
|
40
|
+
},
|
|
41
|
+
file_pattern: {
|
|
42
|
+
type: ["string", "null"],
|
|
43
|
+
description: FILE_PATTERN_PARAMETER_DESCRIPTION,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
required: ["path", "regex", "file_pattern"],
|
|
47
|
+
additionalProperties: false,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
} satisfies OpenAI.Chat.ChatCompletionTool
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type OpenAI from "openai"
|
|
2
|
+
|
|
3
|
+
const SEARCH_REPLACE_DESCRIPTION = `Use this tool to propose a search and replace operation on an existing file.
|
|
4
|
+
|
|
5
|
+
The tool will replace ONE occurrence of old_string with new_string in the specified file.
|
|
6
|
+
|
|
7
|
+
CRITICAL REQUIREMENTS FOR USING THIS TOOL:
|
|
8
|
+
|
|
9
|
+
1. UNIQUENESS: The old_string MUST uniquely identify the specific instance you want to change. This means:
|
|
10
|
+
- Include AT LEAST 3-5 lines of context BEFORE the change point
|
|
11
|
+
- Include AT LEAST 3-5 lines of context AFTER the change point
|
|
12
|
+
- Include all whitespace, indentation, and surrounding code exactly as it appears in the file
|
|
13
|
+
|
|
14
|
+
2. SINGLE INSTANCE: This tool can only change ONE instance at a time. If you need to change multiple instances:
|
|
15
|
+
- Make separate calls to this tool for each instance
|
|
16
|
+
- Each call must uniquely identify its specific instance using extensive context
|
|
17
|
+
|
|
18
|
+
3. VERIFICATION: Before using this tool:
|
|
19
|
+
- If multiple instances exist, gather enough context to uniquely identify each one
|
|
20
|
+
- Plan separate tool calls for each instance`
|
|
21
|
+
|
|
22
|
+
const search_replace = {
|
|
23
|
+
type: "function",
|
|
24
|
+
function: {
|
|
25
|
+
name: "search_replace",
|
|
26
|
+
description: SEARCH_REPLACE_DESCRIPTION,
|
|
27
|
+
parameters: {
|
|
28
|
+
type: "object",
|
|
29
|
+
properties: {
|
|
30
|
+
file_path: {
|
|
31
|
+
type: "string",
|
|
32
|
+
description:
|
|
33
|
+
"The path to the file you want to search and replace in. 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.",
|
|
34
|
+
},
|
|
35
|
+
old_string: {
|
|
36
|
+
type: "string",
|
|
37
|
+
description:
|
|
38
|
+
"The text to replace (must be unique within the file, and must match the file contents exactly, including all whitespace and indentation)",
|
|
39
|
+
},
|
|
40
|
+
new_string: {
|
|
41
|
+
type: "string",
|
|
42
|
+
description: "The edited text to replace the old_string (must be different from the old_string)",
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
required: ["file_path", "old_string", "new_string"],
|
|
46
|
+
additionalProperties: false,
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
} satisfies OpenAI.Chat.ChatCompletionTool
|
|
50
|
+
|
|
51
|
+
export default search_replace
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type OpenAI from "openai"
|
|
2
|
+
|
|
3
|
+
const SKILL_DESCRIPTION = `Load and execute a skill by name. Skills provide specialized instructions for common tasks like creating MCP servers or custom modes.
|
|
4
|
+
|
|
5
|
+
Use this tool when you need to follow specific procedures documented in a skill. Available skills are listed in the AVAILABLE SKILLS section of the system prompt.`
|
|
6
|
+
|
|
7
|
+
const SKILL_PARAMETER_DESCRIPTION = `Name of the skill to load (e.g., create-mcp-server, create-mode). Must match a skill name from the available skills list.`
|
|
8
|
+
|
|
9
|
+
const ARGS_PARAMETER_DESCRIPTION = `Optional context or arguments to pass to the skill`
|
|
10
|
+
|
|
11
|
+
export default {
|
|
12
|
+
type: "function",
|
|
13
|
+
function: {
|
|
14
|
+
name: "skill",
|
|
15
|
+
description: SKILL_DESCRIPTION,
|
|
16
|
+
strict: true,
|
|
17
|
+
parameters: {
|
|
18
|
+
type: "object",
|
|
19
|
+
properties: {
|
|
20
|
+
skill: {
|
|
21
|
+
type: "string",
|
|
22
|
+
description: SKILL_PARAMETER_DESCRIPTION,
|
|
23
|
+
},
|
|
24
|
+
args: {
|
|
25
|
+
type: ["string", "null"],
|
|
26
|
+
description: ARGS_PARAMETER_DESCRIPTION,
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
required: ["skill", "args"],
|
|
30
|
+
additionalProperties: false,
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
} satisfies OpenAI.Chat.ChatCompletionTool
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type OpenAI from "openai"
|
|
2
|
+
|
|
3
|
+
const SWITCH_MODE_DESCRIPTION = `Request to switch to a different mode. This tool allows modes to request switching to another mode when needed, such as switching to Code mode to make code changes. The user must approve the mode switch.`
|
|
4
|
+
|
|
5
|
+
const MODE_SLUG_PARAMETER_DESCRIPTION = `Slug of the mode to switch to (e.g., code, ask, architect)`
|
|
6
|
+
|
|
7
|
+
const REASON_PARAMETER_DESCRIPTION = `Explanation for why the mode switch is needed`
|
|
8
|
+
|
|
9
|
+
export default {
|
|
10
|
+
type: "function",
|
|
11
|
+
function: {
|
|
12
|
+
name: "switch_mode",
|
|
13
|
+
description: SWITCH_MODE_DESCRIPTION,
|
|
14
|
+
strict: true,
|
|
15
|
+
parameters: {
|
|
16
|
+
type: "object",
|
|
17
|
+
properties: {
|
|
18
|
+
mode_slug: {
|
|
19
|
+
type: "string",
|
|
20
|
+
description: MODE_SLUG_PARAMETER_DESCRIPTION,
|
|
21
|
+
},
|
|
22
|
+
reason: {
|
|
23
|
+
type: "string",
|
|
24
|
+
description: REASON_PARAMETER_DESCRIPTION,
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
required: ["mode_slug", "reason"],
|
|
28
|
+
additionalProperties: false,
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
} satisfies OpenAI.Chat.ChatCompletionTool
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type OpenAI from "openai"
|
|
2
|
+
|
|
3
|
+
const UPDATE_TODO_LIST_DESCRIPTION = `Replace the entire TODO list with an updated checklist reflecting the current state. Always provide the full list; the system will overwrite the previous one. This tool is designed for step-by-step task tracking, allowing you to confirm completion of each step before updating, update multiple task statuses at once (e.g., mark one as completed and start the next), and dynamically add new todos discovered during long or complex tasks.
|
|
4
|
+
|
|
5
|
+
Checklist Format:
|
|
6
|
+
- Use a single-level markdown checklist (no nesting or subtasks)
|
|
7
|
+
- List todos in the intended execution order
|
|
8
|
+
- Status options: [ ] (pending), [x] (completed), [-] (in progress)
|
|
9
|
+
|
|
10
|
+
Core Principles:
|
|
11
|
+
- Before updating, always confirm which todos have been completed
|
|
12
|
+
- You may update multiple statuses in a single update
|
|
13
|
+
- Add new actionable items as they're discovered
|
|
14
|
+
- Only mark a task as completed when fully accomplished
|
|
15
|
+
- Keep all unfinished tasks unless explicitly instructed to remove
|
|
16
|
+
|
|
17
|
+
Example: Initial task list
|
|
18
|
+
{ "todos": "[x] Analyze requirements\\n[x] Design architecture\\n[-] Implement core logic\\n[ ] Write tests\\n[ ] Update documentation" }
|
|
19
|
+
|
|
20
|
+
Example: After completing implementation
|
|
21
|
+
{ "todos": "[x] Analyze requirements\\n[x] Design architecture\\n[x] Implement core logic\\n[-] Write tests\\n[ ] Update documentation\\n[ ] Add performance benchmarks" }
|
|
22
|
+
|
|
23
|
+
When to Use:
|
|
24
|
+
- Task involves multiple steps or requires ongoing tracking
|
|
25
|
+
- Need to update status of several todos at once
|
|
26
|
+
- New actionable items are discovered during execution
|
|
27
|
+
- Task is complex and benefits from stepwise progress tracking
|
|
28
|
+
|
|
29
|
+
When NOT to Use:
|
|
30
|
+
- Only a single, trivial task
|
|
31
|
+
- Task can be completed in one or two simple steps
|
|
32
|
+
- Request is purely conversational or informational`
|
|
33
|
+
|
|
34
|
+
const TODOS_PARAMETER_DESCRIPTION = `Full markdown checklist in execution order, using [ ] for pending, [x] for completed, and [-] for in progress`
|
|
35
|
+
|
|
36
|
+
export default {
|
|
37
|
+
type: "function",
|
|
38
|
+
function: {
|
|
39
|
+
name: "update_todo_list",
|
|
40
|
+
description: UPDATE_TODO_LIST_DESCRIPTION,
|
|
41
|
+
strict: true,
|
|
42
|
+
parameters: {
|
|
43
|
+
type: "object",
|
|
44
|
+
properties: {
|
|
45
|
+
todos: {
|
|
46
|
+
type: "string",
|
|
47
|
+
description: TODOS_PARAMETER_DESCRIPTION,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
required: ["todos"],
|
|
51
|
+
additionalProperties: false,
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
} satisfies OpenAI.Chat.ChatCompletionTool
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type OpenAI from "openai"
|
|
2
|
+
|
|
3
|
+
const WRITE_TO_FILE_DESCRIPTION = `Request to write content to a file. This tool is primarily used for creating new files or for scenarios where a complete rewrite of an existing file is intentionally required. If the file exists, it will be overwritten. If it doesn't exist, it will be created. This tool will automatically create any directories needed to write the file.
|
|
4
|
+
|
|
5
|
+
**Important:** You should prefer using other editing tools over write_to_file when making changes to existing files, since write_to_file is slower and cannot handle large files. Use write_to_file primarily for new file creation.
|
|
6
|
+
|
|
7
|
+
When using this tool, use it directly with the desired content. You do not need to display the content before using the tool. ALWAYS provide the COMPLETE file content in your response. This is NON-NEGOTIABLE. Partial updates or placeholders like '// rest of code unchanged' are STRICTLY FORBIDDEN. Failure to do so will result in incomplete or broken code.
|
|
8
|
+
|
|
9
|
+
When creating a new project, organize all new files within a dedicated project directory unless the user specifies otherwise. Structure the project logically, adhering to best practices for the specific type of project being created.
|
|
10
|
+
|
|
11
|
+
Example: Writing a configuration file
|
|
12
|
+
{ "path": "frontend-config.json", "content": "{\\n \\"apiEndpoint\\": \\"https://api.example.com\\",\\n \\"theme\\": {\\n \\"primaryColor\\": \\"#007bff\\"\\n }\\n}" }`
|
|
13
|
+
|
|
14
|
+
const PATH_PARAMETER_DESCRIPTION = `The path of the file to write to (relative to the current workspace directory)`
|
|
15
|
+
|
|
16
|
+
const CONTENT_PARAMETER_DESCRIPTION = `The content to write to the file. ALWAYS provide the COMPLETE intended content of the file, without any truncation or omissions. You MUST include ALL parts of the file, even if they haven't been modified. Do NOT include line numbers in the content.`
|
|
17
|
+
|
|
18
|
+
export default {
|
|
19
|
+
type: "function",
|
|
20
|
+
function: {
|
|
21
|
+
name: "write_to_file",
|
|
22
|
+
description: WRITE_TO_FILE_DESCRIPTION,
|
|
23
|
+
strict: true,
|
|
24
|
+
parameters: {
|
|
25
|
+
type: "object",
|
|
26
|
+
properties: {
|
|
27
|
+
path: {
|
|
28
|
+
type: "string",
|
|
29
|
+
description: PATH_PARAMETER_DESCRIPTION,
|
|
30
|
+
},
|
|
31
|
+
content: {
|
|
32
|
+
type: "string",
|
|
33
|
+
description: CONTENT_PARAMETER_DESCRIPTION,
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
required: ["path", "content"],
|
|
37
|
+
additionalProperties: false,
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
} satisfies OpenAI.Chat.ChatCompletionTool
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings passed to system prompt generation functions
|
|
3
|
+
*/
|
|
4
|
+
export interface SystemPromptSettings {
|
|
5
|
+
todoListEnabled: boolean
|
|
6
|
+
useAgentRules: boolean
|
|
7
|
+
/** When true, recursively discover and load .roo/rules from subdirectories */
|
|
8
|
+
enableSubfolderRules?: boolean
|
|
9
|
+
newTaskRequireTodos: boolean
|
|
10
|
+
/** When true, model should hide vendor/company identity in responses */
|
|
11
|
+
isStealthModel?: boolean
|
|
12
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SHIM — replaces zoo-code/src/i18n/index.ts.
|
|
3
|
+
*
|
|
4
|
+
* The original is a full i18n catalog keyed to the webview UI. The vendored
|
|
5
|
+
* CustomModesManager uses `t()` only to build user-facing error strings. The
|
|
6
|
+
* headless harness surfaces those as plain console output, so this shim returns
|
|
7
|
+
* the key (with `{param}` interpolation applied).
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export function t(key: string, params?: Record<string, unknown>): string {
|
|
11
|
+
if (!params) {
|
|
12
|
+
return key
|
|
13
|
+
}
|
|
14
|
+
let result = key
|
|
15
|
+
for (const [name, value] of Object.entries(params)) {
|
|
16
|
+
result = result.replaceAll(`{${name}}`, String(value))
|
|
17
|
+
}
|
|
18
|
+
return result
|
|
19
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vendored subset of `zoo-code/src/integrations/misc/extract-text.ts`.
|
|
3
|
+
*
|
|
4
|
+
* Only the three pure text-formatting helpers used by the vendored
|
|
5
|
+
* MultiSearchReplaceDiffStrategy are carried here (verbatim from upstream):
|
|
6
|
+
*
|
|
7
|
+
* - addLineNumbers
|
|
8
|
+
* - everyLineHasLineNumbers
|
|
9
|
+
* - stripLineNumbers
|
|
10
|
+
*
|
|
11
|
+
* The full upstream file also contains PDF/DOCX/XLSX extractors, binary-file
|
|
12
|
+
* detection and indentation slicing, none of which the headless harness needs —
|
|
13
|
+
* they pull in `pdf-parse`, `mammoth`, `isbinaryfile` and other GUI/service
|
|
14
|
+
* dependencies that are not worth carrying.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
export function addLineNumbers(content: string, startLine: number = 1): string {
|
|
18
|
+
// If content is empty, return empty string - empty files should not have line numbers
|
|
19
|
+
// If content is empty but startLine > 1, return "startLine | " because we know the file is not empty
|
|
20
|
+
// but the content is empty at that line offset
|
|
21
|
+
if (content === "") {
|
|
22
|
+
return startLine === 1 ? "" : `${startLine} | \n`
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Split into lines and handle trailing line feeds (\n)
|
|
26
|
+
const lines = content.split("\n")
|
|
27
|
+
const lastLineEmpty = lines[lines.length - 1] === ""
|
|
28
|
+
if (lastLineEmpty) {
|
|
29
|
+
lines.pop()
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const maxLineNumberWidth = String(startLine + lines.length - 1).length
|
|
33
|
+
const numberedContent = lines
|
|
34
|
+
.map((line, index) => {
|
|
35
|
+
const lineNumber = String(startLine + index).padStart(maxLineNumberWidth, " ")
|
|
36
|
+
return `${lineNumber} | ${line}`
|
|
37
|
+
})
|
|
38
|
+
.join("\n")
|
|
39
|
+
|
|
40
|
+
return numberedContent + "\n"
|
|
41
|
+
}
|
|
42
|
+
// Checks if every line in the content has line numbers prefixed (e.g., "1 | content" or "123 | content")
|
|
43
|
+
// Line numbers must be followed by a single pipe character (not double pipes)
|
|
44
|
+
export function everyLineHasLineNumbers(content: string): boolean {
|
|
45
|
+
const lines = content.split(/\r?\n/) // Handles both CRLF (carriage return (\r) + line feed (\n)) and LF (line feed (\n)) line endings
|
|
46
|
+
return lines.length > 0 && lines.every((line) => /^\s*\d+\s+\|(?!\|)/.test(line))
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Strips line numbers from content while preserving the actual content.
|
|
51
|
+
*
|
|
52
|
+
* @param content The content to process
|
|
53
|
+
* @param aggressive When false (default): Only strips lines with clear number patterns like "123 | content"
|
|
54
|
+
* When true: Uses a more lenient pattern that also matches lines with just a pipe character,
|
|
55
|
+
* which can be useful when LLMs don't perfectly format the line numbers in diffs
|
|
56
|
+
* @returns The content with line numbers removed
|
|
57
|
+
*/
|
|
58
|
+
export function stripLineNumbers(content: string, aggressive: boolean = false): string {
|
|
59
|
+
// Split into lines to handle each line individually
|
|
60
|
+
const lines = content.split(/\r?\n/)
|
|
61
|
+
|
|
62
|
+
// Process each line
|
|
63
|
+
const processedLines = lines.map((line) => {
|
|
64
|
+
// Match line number pattern and capture everything after the pipe
|
|
65
|
+
const match = aggressive ? line.match(/^\s*(?:\d+\s)?\|\s(.*)$/) : line.match(/^\s*\d+\s+\|(?!\|)\s?(.*)$/)
|
|
66
|
+
return match ? match[1] : line
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
// Join back with original line endings (carriage return (\r) + line feed (\n) or just line feed (\n))
|
|
70
|
+
const lineEnding = content.includes("\r\n") ? "\r\n" : "\n"
|
|
71
|
+
let result = processedLines.join(lineEnding)
|
|
72
|
+
|
|
73
|
+
// Preserve trailing newline if present in original content
|
|
74
|
+
if (content.endsWith(lineEnding)) {
|
|
75
|
+
if (!result.endsWith(lineEnding)) {
|
|
76
|
+
result += lineEnding
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return result
|
|
81
|
+
}
|