multi-forge 0.2.0__py3-none-any.whl

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.
Files changed (311) hide show
  1. forge/__init__.py +3 -0
  2. forge/_extensions/agents/.gitkeep +0 -0
  3. forge/_extensions/commands/.gitkeep +0 -0
  4. forge/_extensions/skills/analyze/SKILL.md +87 -0
  5. forge/_extensions/skills/challenge/SKILL.md +91 -0
  6. forge/_extensions/skills/consensus/SKILL.md +120 -0
  7. forge/_extensions/skills/consensus/resources/code_consensus_evaluation.md +94 -0
  8. forge/_extensions/skills/consensus/resources/consensus_evaluation.md +70 -0
  9. forge/_extensions/skills/consensus/resources/synthesis.md +101 -0
  10. forge/_extensions/skills/debate/SKILL.md +116 -0
  11. forge/_extensions/skills/debate/resources/code_debate_evaluation.md +101 -0
  12. forge/_extensions/skills/debate/resources/debate_evaluation.md +90 -0
  13. forge/_extensions/skills/panel/SKILL.md +141 -0
  14. forge/_extensions/skills/panel/resources/synthesis.md +103 -0
  15. forge/_extensions/skills/qa/SKILL.md +704 -0
  16. forge/_extensions/skills/qa/resources/checklist/0-enable.md +78 -0
  17. forge/_extensions/skills/qa/resources/checklist/1-preflight.md +24 -0
  18. forge/_extensions/skills/qa/resources/checklist/10-resume.md +143 -0
  19. forge/_extensions/skills/qa/resources/checklist/11-config.md +150 -0
  20. forge/_extensions/skills/qa/resources/checklist/12-search.md +58 -0
  21. forge/_extensions/skills/qa/resources/checklist/13-guard.md +237 -0
  22. forge/_extensions/skills/qa/resources/checklist/14-workflow.md +305 -0
  23. forge/_extensions/skills/qa/resources/checklist/15-skills.md +155 -0
  24. forge/_extensions/skills/qa/resources/checklist/16-handoff.md +224 -0
  25. forge/_extensions/skills/qa/resources/checklist/17-info.md +50 -0
  26. forge/_extensions/skills/qa/resources/checklist/18-disable.md +84 -0
  27. forge/_extensions/skills/qa/resources/checklist/19-uninstall.md +146 -0
  28. forge/_extensions/skills/qa/resources/checklist/2-extensions.md +188 -0
  29. forge/_extensions/skills/qa/resources/checklist/20-cleanup.md +36 -0
  30. forge/_extensions/skills/qa/resources/checklist/3-auth.md +234 -0
  31. forge/_extensions/skills/qa/resources/checklist/4-proxy.md +481 -0
  32. forge/_extensions/skills/qa/resources/checklist/5-session.md +541 -0
  33. forge/_extensions/skills/qa/resources/checklist/6-hooks.md +275 -0
  34. forge/_extensions/skills/qa/resources/checklist/7-costs.md +309 -0
  35. forge/_extensions/skills/qa/resources/checklist/8-status-line.md +174 -0
  36. forge/_extensions/skills/qa/resources/checklist/9-direct-commands.md +146 -0
  37. forge/_extensions/skills/qa/resources/checklist.md +103 -0
  38. forge/_extensions/skills/qa/resources/report-template.md +62 -0
  39. forge/_extensions/skills/qa/scripts/start-container.sh +529 -0
  40. forge/_extensions/skills/qa/scripts/walkthrough-state.py +1137 -0
  41. forge/_extensions/skills/review/SKILL.md +125 -0
  42. forge/_extensions/skills/review/references/claude-4.6.md +474 -0
  43. forge/_extensions/skills/review/references/claude-4.7.md +710 -0
  44. forge/_extensions/skills/review/references/gemini-3.1.md +546 -0
  45. forge/_extensions/skills/review/references/gpt-5.5.md +490 -0
  46. forge/_extensions/skills/review/references/skills-writing-guide.md +1588 -0
  47. forge/_extensions/skills/review/resources/code-anthropic.md +160 -0
  48. forge/_extensions/skills/review/resources/code-gemini.md +184 -0
  49. forge/_extensions/skills/review/resources/code-openai.md +203 -0
  50. forge/_extensions/skills/review/resources/code.md +160 -0
  51. forge/_extensions/skills/review-docs/SKILL.md +121 -0
  52. forge/_extensions/skills/review-docs/resources/docs-anthropic.md +170 -0
  53. forge/_extensions/skills/review-docs/resources/docs-gemini.md +204 -0
  54. forge/_extensions/skills/review-docs/resources/docs-openai.md +231 -0
  55. forge/_extensions/skills/review-docs/resources/docs.md +170 -0
  56. forge/_extensions/skills/smoke-test/SKILL.md +27 -0
  57. forge/_extensions/skills/smoke-test/scripts/smoke-test.sh +118 -0
  58. forge/_extensions/skills/understand/SKILL.md +148 -0
  59. forge/_extensions/skills/understand/resources/code-anthropic.md +163 -0
  60. forge/_extensions/skills/understand/resources/code-gemini.md +194 -0
  61. forge/_extensions/skills/understand/resources/code-openai.md +181 -0
  62. forge/_extensions/skills/understand/resources/code.md +163 -0
  63. forge/_extensions/skills/understand/resources/docs-anthropic.md +177 -0
  64. forge/_extensions/skills/understand/resources/docs-gemini.md +202 -0
  65. forge/_extensions/skills/understand/resources/docs-openai.md +191 -0
  66. forge/_extensions/skills/understand/resources/docs.md +177 -0
  67. forge/_extensions/skills/walkthrough/SKILL.md +599 -0
  68. forge/_extensions/skills/walkthrough/resources/checklist.md +765 -0
  69. forge/_extensions/skills/walkthrough/scripts/run-in-repo.sh +118 -0
  70. forge/_extensions/skills/walkthrough/scripts/setup-test-repo.sh +198 -0
  71. forge/_extensions/skills/walkthrough/scripts/walkthrough-state.py +1137 -0
  72. forge/backend/__init__.py +174 -0
  73. forge/backend/adapters/__init__.py +38 -0
  74. forge/backend/adapters/litellm.py +158 -0
  75. forge/backend/creation.py +89 -0
  76. forge/backend/registry.py +178 -0
  77. forge/cli/__init__.py +16 -0
  78. forge/cli/auth.py +483 -0
  79. forge/cli/backend.py +298 -0
  80. forge/cli/claude.py +411 -0
  81. forge/cli/config_cmd.py +303 -0
  82. forge/cli/extensions.py +1001 -0
  83. forge/cli/gc.py +165 -0
  84. forge/cli/guard.py +1018 -0
  85. forge/cli/guards.py +106 -0
  86. forge/cli/handoff.py +110 -0
  87. forge/cli/hooks/__init__.py +36 -0
  88. forge/cli/hooks/_group.py +20 -0
  89. forge/cli/hooks/_helpers.py +149 -0
  90. forge/cli/hooks/commands.py +1677 -0
  91. forge/cli/hooks/direct_commands.py +1304 -0
  92. forge/cli/hooks/install.py +232 -0
  93. forge/cli/hooks/policy.py +151 -0
  94. forge/cli/hooks/read_hygiene.py +74 -0
  95. forge/cli/hooks/verification.py +370 -0
  96. forge/cli/logs.py +406 -0
  97. forge/cli/main.py +292 -0
  98. forge/cli/proxy.py +1821 -0
  99. forge/cli/proxy_costs.py +313 -0
  100. forge/cli/search.py +416 -0
  101. forge/cli/session.py +892 -0
  102. forge/cli/session_addendum.py +81 -0
  103. forge/cli/session_fork.py +750 -0
  104. forge/cli/session_handoff.py +141 -0
  105. forge/cli/session_lifecycle.py +2053 -0
  106. forge/cli/session_manage.py +1336 -0
  107. forge/cli/session_memory.py +201 -0
  108. forge/cli/status_line.py +1398 -0
  109. forge/cli/workflow.py +1964 -0
  110. forge/config/__init__.py +110 -0
  111. forge/config/dataclass_utils.py +88 -0
  112. forge/config/defaults/__init__.py +0 -0
  113. forge/config/defaults/backends/__init__.py +0 -0
  114. forge/config/defaults/backends/litellm.yaml +196 -0
  115. forge/config/defaults/templates/__init__.py +0 -0
  116. forge/config/defaults/templates/litellm-anthropic-local.yaml +33 -0
  117. forge/config/defaults/templates/litellm-anthropic.yaml +24 -0
  118. forge/config/defaults/templates/litellm-gemini-flash-local.yaml +37 -0
  119. forge/config/defaults/templates/litellm-gemini-local.yaml +32 -0
  120. forge/config/defaults/templates/litellm-gemini-test.yaml +34 -0
  121. forge/config/defaults/templates/litellm-gemini.yaml +21 -0
  122. forge/config/defaults/templates/litellm-openai-codex-local.yaml +36 -0
  123. forge/config/defaults/templates/litellm-openai-local.yaml +38 -0
  124. forge/config/defaults/templates/litellm-openai.yaml +28 -0
  125. forge/config/defaults/templates/openrouter-anthropic.yaml +23 -0
  126. forge/config/defaults/templates/openrouter-deepseek.yaml +26 -0
  127. forge/config/defaults/templates/openrouter-gemini-flash.yaml +26 -0
  128. forge/config/defaults/templates/openrouter-gemini.yaml +23 -0
  129. forge/config/defaults/templates/openrouter-glm.yaml +23 -0
  130. forge/config/defaults/templates/openrouter-kimi.yaml +30 -0
  131. forge/config/defaults/templates/openrouter-minimax.yaml +26 -0
  132. forge/config/defaults/templates/openrouter-openai-codex.yaml +23 -0
  133. forge/config/defaults/templates/openrouter-openai.yaml +28 -0
  134. forge/config/defaults/templates/openrouter-qwen.yaml +25 -0
  135. forge/config/loader.py +675 -0
  136. forge/config/schema.py +448 -0
  137. forge/core/__init__.py +5 -0
  138. forge/core/auth/__init__.py +67 -0
  139. forge/core/auth/capabilities.py +219 -0
  140. forge/core/auth/credentials_file.py +244 -0
  141. forge/core/auth/protocols.py +18 -0
  142. forge/core/auth/secrets.py +243 -0
  143. forge/core/auth/template_secrets.py +112 -0
  144. forge/core/data/__init__.py +5 -0
  145. forge/core/data/model_catalog.yaml +1522 -0
  146. forge/core/data/pricing.yaml +140 -0
  147. forge/core/data/system_prompt_addendums/__init__.py +0 -0
  148. forge/core/data/system_prompt_addendums/gemini.md +330 -0
  149. forge/core/data/system_prompt_addendums/openai.md +328 -0
  150. forge/core/llm/__init__.py +231 -0
  151. forge/core/llm/clients/__init__.py +14 -0
  152. forge/core/llm/clients/base.py +115 -0
  153. forge/core/llm/clients/litellm.py +619 -0
  154. forge/core/llm/clients/openai_compat.py +244 -0
  155. forge/core/llm/clients/openrouter.py +234 -0
  156. forge/core/llm/credentials.py +439 -0
  157. forge/core/llm/detection.py +86 -0
  158. forge/core/llm/errors.py +44 -0
  159. forge/core/llm/protocols.py +80 -0
  160. forge/core/llm/types.py +176 -0
  161. forge/core/logging.py +146 -0
  162. forge/core/models/__init__.py +91 -0
  163. forge/core/models/catalog.py +467 -0
  164. forge/core/models/pricing.py +165 -0
  165. forge/core/models/types.py +167 -0
  166. forge/core/naming.py +212 -0
  167. forge/core/ops/__init__.py +73 -0
  168. forge/core/ops/context.py +141 -0
  169. forge/core/ops/gc.py +802 -0
  170. forge/core/ops/proxy.py +146 -0
  171. forge/core/ops/resolution.py +135 -0
  172. forge/core/ops/session.py +344 -0
  173. forge/core/ops/session_context.py +548 -0
  174. forge/core/paths.py +38 -0
  175. forge/core/process.py +54 -0
  176. forge/core/reactive/__init__.py +38 -0
  177. forge/core/reactive/cost_tracking.py +300 -0
  178. forge/core/reactive/env.py +180 -0
  179. forge/core/reactive/proxy.py +78 -0
  180. forge/core/reactive/routing.py +622 -0
  181. forge/core/reactive/session_runner.py +185 -0
  182. forge/core/reactive/structured_output.py +62 -0
  183. forge/core/reactive/tagger.py +94 -0
  184. forge/core/reactive/throttle.py +132 -0
  185. forge/core/state/__init__.py +59 -0
  186. forge/core/state/exceptions.py +59 -0
  187. forge/core/state/io.py +140 -0
  188. forge/core/state/lock.py +99 -0
  189. forge/core/state/timestamps.py +60 -0
  190. forge/core/transcript.py +78 -0
  191. forge/core/typing_helpers.py +24 -0
  192. forge/core/workqueue/__init__.py +67 -0
  193. forge/core/workqueue/queue.py +552 -0
  194. forge/core/workqueue/types.py +63 -0
  195. forge/guard/__init__.py +26 -0
  196. forge/guard/deterministic/__init__.py +26 -0
  197. forge/guard/deterministic/base.py +158 -0
  198. forge/guard/deterministic/coding_standards.py +256 -0
  199. forge/guard/deterministic/registry.py +148 -0
  200. forge/guard/deterministic/tdd.py +171 -0
  201. forge/guard/engine.py +216 -0
  202. forge/guard/protocols.py +91 -0
  203. forge/guard/queries.py +96 -0
  204. forge/guard/semantic/__init__.py +34 -0
  205. forge/guard/semantic/promotion.py +18 -0
  206. forge/guard/semantic/supervisor.py +813 -0
  207. forge/guard/semantic/verdict.py +183 -0
  208. forge/guard/store.py +124 -0
  209. forge/guard/team/__init__.py +6 -0
  210. forge/guard/team/config.py +24 -0
  211. forge/guard/team/handlers.py +209 -0
  212. forge/guard/team/prompts.py +41 -0
  213. forge/guard/types.py +125 -0
  214. forge/guard/workflow/__init__.py +17 -0
  215. forge/guard/workflow/branches.py +67 -0
  216. forge/guard/workflow/config.py +63 -0
  217. forge/guard/workflow/divergence.py +113 -0
  218. forge/guard/workflow/policy.py +87 -0
  219. forge/guard/workflow/stages.py +205 -0
  220. forge/install/__init__.py +55 -0
  221. forge/install/cli.py +281 -0
  222. forge/install/exceptions.py +163 -0
  223. forge/install/hooks.py +109 -0
  224. forge/install/installer.py +1037 -0
  225. forge/install/models.py +321 -0
  226. forge/install/preset.py +272 -0
  227. forge/install/settings_merge.py +831 -0
  228. forge/install/tracking.py +238 -0
  229. forge/install/version.py +141 -0
  230. forge/proxy/__init__.py +0 -0
  231. forge/proxy/base_client.py +181 -0
  232. forge/proxy/client_adapter.py +476 -0
  233. forge/proxy/client_factory.py +531 -0
  234. forge/proxy/converters.py +1206 -0
  235. forge/proxy/cost_logger.py +132 -0
  236. forge/proxy/cost_tracker.py +242 -0
  237. forge/proxy/data_models.py +338 -0
  238. forge/proxy/error_hints.py +92 -0
  239. forge/proxy/metrics.py +222 -0
  240. forge/proxy/model_spec.py +158 -0
  241. forge/proxy/proxies.py +333 -0
  242. forge/proxy/proxy_identity.py +134 -0
  243. forge/proxy/proxy_orchestrator.py +1018 -0
  244. forge/proxy/proxy_startup.py +54 -0
  245. forge/proxy/server.py +1561 -0
  246. forge/proxy/utils.py +537 -0
  247. forge/review/__init__.py +6 -0
  248. forge/review/adversarial.py +111 -0
  249. forge/review/consensus.py +236 -0
  250. forge/review/engine.py +356 -0
  251. forge/review/models.py +437 -0
  252. forge/review/resources/__init__.py +5 -0
  253. forge/review/resources/codereview-performance.md +85 -0
  254. forge/review/resources/codereview-quick.md +75 -0
  255. forge/review/resources/codereview-security.md +92 -0
  256. forge/review/resources/codereview.md +85 -0
  257. forge/review/resources/docreview-quick.md +75 -0
  258. forge/review/resources/docreview.md +86 -0
  259. forge/review/resources/thinkdeep.md +89 -0
  260. forge/review/routing.py +368 -0
  261. forge/review/synthesis.py +73 -0
  262. forge/runtime_config.py +438 -0
  263. forge/search/__init__.py +55 -0
  264. forge/search/bm25_store.py +264 -0
  265. forge/search/content_store.py +197 -0
  266. forge/search/engine.py +352 -0
  267. forge/search/exceptions.py +51 -0
  268. forge/search/extractor.py +234 -0
  269. forge/search/index_state.py +295 -0
  270. forge/search/store.py +215 -0
  271. forge/search/tokenizer.py +24 -0
  272. forge/session/__init__.py +130 -0
  273. forge/session/active.py +339 -0
  274. forge/session/artifacts.py +202 -0
  275. forge/session/claude/__init__.py +50 -0
  276. forge/session/claude/cleanup.py +105 -0
  277. forge/session/claude/invoke.py +236 -0
  278. forge/session/claude/paths.py +200 -0
  279. forge/session/cleanup.py +216 -0
  280. forge/session/config.py +34 -0
  281. forge/session/direct_model.py +107 -0
  282. forge/session/effective.py +169 -0
  283. forge/session/exceptions.py +255 -0
  284. forge/session/handoff.py +881 -0
  285. forge/session/handoff_agent.py +544 -0
  286. forge/session/hooks/__init__.py +35 -0
  287. forge/session/hooks/models.py +73 -0
  288. forge/session/hooks/session_start.py +507 -0
  289. forge/session/identity.py +84 -0
  290. forge/session/index.py +553 -0
  291. forge/session/manager.py +1506 -0
  292. forge/session/models.py +572 -0
  293. forge/session/overrides.py +344 -0
  294. forge/session/plan_resolution.py +286 -0
  295. forge/session/prev_sessions.py +128 -0
  296. forge/session/store.py +431 -0
  297. forge/session/validation.py +47 -0
  298. forge/session/worktree/__init__.py +65 -0
  299. forge/session/worktree/cleanup.py +262 -0
  300. forge/session/worktree/config_copy.py +203 -0
  301. forge/session/worktree/create.py +332 -0
  302. forge/sidecar/__init__.py +29 -0
  303. forge/sidecar/container.py +161 -0
  304. forge/sidecar/docker.py +86 -0
  305. forge/sidecar/secrets.py +19 -0
  306. multi_forge-0.2.0.dist-info/METADATA +242 -0
  307. multi_forge-0.2.0.dist-info/RECORD +311 -0
  308. multi_forge-0.2.0.dist-info/WHEEL +4 -0
  309. multi_forge-0.2.0.dist-info/entry_points.txt +2 -0
  310. multi_forge-0.2.0.dist-info/licenses/LICENSE +203 -0
  311. multi_forge-0.2.0.dist-info/licenses/NOTICE +14 -0
@@ -0,0 +1,140 @@
1
+ # Model pricing: USD per million tokens.
2
+ #
3
+ # Forge uses this for cost estimates. Prices change — update with releases.
4
+ #
5
+ # cached_input = price for prompt-cache HIT tokens (a subset of input_tokens).
6
+ # Cost formula: (input - cached) * input + cached * cached_input + output * output
7
+ schema_version: 1
8
+ updated_at: "2026-05-12"
9
+
10
+ models:
11
+ # --- Anthropic ---
12
+ claude-opus-4-7:
13
+ input: 5.00
14
+ output: 25.00
15
+ cached_input: 0.50
16
+ claude-opus-4-6:
17
+ input: 5.00
18
+ output: 25.00
19
+ cached_input: 0.50
20
+ claude-sonnet-4-6:
21
+ input: 3.00
22
+ output: 15.00
23
+ cached_input: 0.30
24
+ claude-haiku-4-5-20251001:
25
+ input: 1.00
26
+ output: 5.00
27
+ cached_input: 0.10
28
+
29
+ # --- OpenAI ---
30
+ gpt-5.5:
31
+ input: 5.00
32
+ output: 30.00
33
+ cached_input: 0.50
34
+ gpt-5:
35
+ input: 1.25
36
+ output: 10.00
37
+ cached_input: 0.625
38
+ gpt-5-mini:
39
+ input: 0.25
40
+ output: 2.00
41
+ cached_input: 0.125
42
+ gpt-5.4:
43
+ input: 2.50
44
+ output: 15.00
45
+ cached_input: 0.25
46
+ gpt-5.4-mini:
47
+ input: 0.75
48
+ output: 4.50
49
+ cached_input: 0.075
50
+ gpt-4o:
51
+ input: 2.50
52
+ output: 10.00
53
+ cached_input: 1.25
54
+ gpt-4o-mini:
55
+ input: 0.15
56
+ output: 0.60
57
+ cached_input: 0.075
58
+ o3:
59
+ input: 2.00
60
+ output: 8.00
61
+ cached_input: 0.50
62
+ o4-mini:
63
+ input: 1.10
64
+ output: 4.40
65
+ cached_input: 0.275
66
+
67
+ # --- Google Gemini ---
68
+ gemini-2.5-pro:
69
+ input: 1.25
70
+ output: 10.00
71
+ cached_input: 0.125
72
+ gemini-2.5-flash:
73
+ input: 0.30
74
+ output: 2.50
75
+ cached_input: 0.03
76
+ gemini-3.1-pro-preview:
77
+ input: 2.00
78
+ output: 12.00
79
+ cached_input: 0.20
80
+
81
+ # --- Open-source via OpenRouter ---
82
+ # Source: https://openrouter.ai/api/v1/models (fetched 2026-05-12).
83
+ deepseek-v4-flash:
84
+ input: 0.14
85
+ output: 0.28
86
+ cached_input: 0.0028
87
+ deepseek-v4-pro:
88
+ input: 0.435
89
+ output: 0.87
90
+ cached_input: 0.003625
91
+ kimi-k2.5:
92
+ input: 0.40
93
+ output: 1.98
94
+ cached_input: 0.05
95
+ kimi-k2.6:
96
+ input: 0.74
97
+ output: 3.50
98
+ cached_input: 0.25
99
+ qwen3.6-flash:
100
+ input: 0.25
101
+ output: 1.50
102
+ cached_input: 0.25
103
+ qwen3.6-plus:
104
+ input: 0.325
105
+ output: 1.95
106
+ cached_input: 0.325
107
+ qwen3.6-max-preview:
108
+ input: 1.04
109
+ output: 6.24
110
+ cached_input: 1.04
111
+ qwen3-coder:
112
+ input: 0.22
113
+ output: 1.80
114
+ cached_input: 0.22
115
+ minimax-m2.5:
116
+ input: 0.15
117
+ output: 1.15
118
+ cached_input: 0.15
119
+ minimax-m2.7:
120
+ input: 0.299
121
+ output: 1.20
122
+ cached_input: 0.299
123
+ glm-4.7-flash:
124
+ input: 0.06
125
+ output: 0.40
126
+ cached_input: 0.01
127
+ glm-5.1:
128
+ input: 0.98
129
+ output: 3.08
130
+ cached_input: 0.182
131
+ gemma-4-31b-it:
132
+ input: 0.12
133
+ output: 0.37
134
+ cached_input: 0.12
135
+
136
+ # Fallback for unknown models (OpenRouter's open model space, etc.)
137
+ default:
138
+ input: 3.00
139
+ output: 15.00
140
+ cached_input: 0.30
File without changes
@@ -0,0 +1,330 @@
1
+ # Tool Parameter Guidance
2
+
3
+ You are working inside Claude Code, which provides tools with specific parameter contracts.
4
+
5
+ Follow these rules exactly. Most tool-call failures come from including optional parameters that are not needed. Before
6
+ every tool call, construct the parameter object from scratch using the smallest valid object for that specific call. Do
7
+ not reuse a previous failed tool-call object.
8
+
9
+ ## Universal tool-call rule
10
+
11
+ For every tool call:
12
+
13
+ 1. Start with only the required parameters.
14
+ 2. Add an optional parameter only if this exact call needs it.
15
+ 3. Never include optional parameters with placeholder values.
16
+ 4. Never pass `""`, `null`, `[]`, or `{}` just to satisfy a schema.
17
+ 5. If a tool call fails because of an invalid optional parameter, the next retry MUST remove that parameter entirely
18
+ unless it is required.
19
+ 6. Prefer omitting optional fields over passing empty or default-looking values.
20
+ 7. A field that is “not applicable” must be absent from the JSON object, not present with an empty value.
21
+
22
+ Bad:
23
+
24
+ ```json
25
+ {"file_path":"/workspace/README.md","pages":""}
26
+ ```
27
+
28
+ Good:
29
+
30
+ ```json
31
+ {"file_path":"/workspace/README.md"}
32
+ ```
33
+
34
+ ## Read
35
+
36
+ Default call shape for ordinary files:
37
+
38
+ ```json
39
+ {"file_path":"/absolute/path/to/file"}
40
+ ```
41
+
42
+ Use this default for normal-sized non-PDF files, including:
43
+
44
+ - .md
45
+ - .txt
46
+ - source code files
47
+ - .json
48
+ - .yaml / .yml
49
+ - config files
50
+ - notebooks, unless notebook-specific handling is explicitly needed
51
+
52
+ Do not add offset, limit, or pages unless this exact read requires them.
53
+
54
+ ### `pages`
55
+
56
+ `pages` is only for PDF files.
57
+
58
+ If `file_path` does not end in `.pdf`, the `pages` key is forbidden.
59
+
60
+ For non-PDF files:
61
+
62
+ - Do not include `pages`.
63
+ - Do not include `"pages": ""`.
64
+ - Do not include `"pages": null`.
65
+ - Do not include `"pages": "1"`.
66
+ - Do not include `pages` together with `offset`/`limit`.
67
+ - The correct non-PDF retry after any `pages` error is usually only:
68
+
69
+ ```json
70
+ {"file_path":"/absolute/path/to/file"}
71
+ ```
72
+
73
+ Correct non-PDF examples:
74
+
75
+ ```json
76
+ {"file_path":"/workspace/README.md"}
77
+ ```
78
+
79
+ ```json
80
+ {"file_path":"/workspace/src/app.ts"}
81
+ ```
82
+
83
+ ```json
84
+ {"file_path":"/workspace/package.json"}
85
+ ```
86
+
87
+ Correct PDF examples:
88
+
89
+ ```json
90
+ {"file_path":"/workspace/spec.pdf","pages":"1-5"}
91
+ ```
92
+
93
+ ```json
94
+ {"file_path":"/workspace/spec.pdf","pages":"3"}
95
+ ```
96
+
97
+ Incorrect:
98
+
99
+ ```json
100
+ {"file_path":"/workspace/README.md","pages":""}
101
+ ```
102
+
103
+ ```json
104
+ {"file_path":"/workspace/README.md","pages":"1"}
105
+ ```
106
+
107
+ ```json
108
+ {"file_path":"/workspace/README.md","offset":1,"limit":2000,"pages":""}
109
+ ```
110
+
111
+ ```json
112
+ {"file_path":"/workspace/src/app.ts","pages":null}
113
+ ```
114
+
115
+ ### `offset` and `limit`
116
+
117
+ `offset` and `limit` are optional.
118
+
119
+ For normal-sized files, omit both and let the tool return the full content.
120
+
121
+ Default:
122
+
123
+ ```json
124
+ {"file_path":"/absolute/path/to/file"}
125
+ ```
126
+
127
+ Only include `offset` and/or `limit` when:
128
+
129
+ - the file is known to be large,
130
+ - you need a specific section,
131
+ - a previous successful read showed that the relevant content is outside the default range.
132
+
133
+ Correct large-file section example:
134
+
135
+ ```json
136
+ {"file_path":"/absolute/path/to/file","offset":2000,"limit":200}
137
+ ```
138
+
139
+ Incorrect for ordinary files:
140
+
141
+ ```json
142
+ {"file_path":"/workspace/README.md","offset":1,"limit":2000}
143
+ ```
144
+
145
+ The above is not invalid, but it is unnecessary. Prefer:
146
+
147
+ ```json
148
+ {"file_path":"/workspace/README.md"}
149
+ ```
150
+
151
+ ### Read retry rule
152
+
153
+ If a Read call fails because of an invalid optional parameter, retry with the smallest valid object.
154
+
155
+ For a non-PDF file, that means:
156
+
157
+ ```json
158
+ {"file_path":"/absolute/path/to/file"}
159
+ ```
160
+
161
+ Do not use Bash as a workaround for a failed Read call until you have retried once with the minimal valid Read object.
162
+
163
+ ## Edit
164
+
165
+ Use Edit for modifying existing files whenever possible.
166
+
167
+ `old_string` must be an exact substring of the current file content.
168
+
169
+ Rules:
170
+
171
+ - Copy `old_string` character-for-character from the file content.
172
+ - Preserve exact whitespace and indentation.
173
+ - Never include line number prefixes from Read.
174
+ - The line number prefix shown by Read is display-only and is not part of the file.
175
+ - If `old_string` is not unique, include more surrounding context.
176
+ - Do not make broad replacements when a narrow exact replacement is possible.
177
+ - Prefer Edit over Write for existing files.
178
+
179
+ Correct:
180
+
181
+ ```json
182
+ {
183
+ "file_path":"/workspace/src/app.py",
184
+ "old_string":"def greet(name):\n return f\"Hello {name}\"",
185
+ "new_string":"def greet(name):\n return f\"Hello, {name}!\""
186
+ }
187
+ ```
188
+
189
+ Incorrect because it includes a line number prefix:
190
+
191
+ ```json
192
+ {
193
+ "file_path":"/workspace/src/app.py",
194
+ "old_string":"12\tdef greet(name):\n13\t return f\"Hello {name}\"",
195
+ "new_string":"def greet(name):\n return f\"Hello, {name}!\""
196
+ }
197
+ ```
198
+
199
+ ### Edit retry rule
200
+
201
+ If Edit fails because `old_string` is not found:
202
+
203
+ 1. Re-read the relevant file or section.
204
+ 2. Copy the exact current text.
205
+ 3. Retry with a more precise `old_string`.
206
+
207
+ If Edit fails because `old_string` is not unique:
208
+
209
+ 1. Include more surrounding lines in `old_string`.
210
+ 2. Do not use `replace_all` unless every occurrence should actually change.
211
+
212
+ ## Write
213
+
214
+ Use Write only for:
215
+
216
+ - creating a new file,
217
+ - intentionally replacing an entire existing file after reading it first.
218
+
219
+ Rules:
220
+
221
+ - Prefer Edit for modifying existing files.
222
+ - Do not use Write to make a small change to an existing file.
223
+ - If writing an existing file, read it first.
224
+ - Do not create documentation files unless explicitly requested by the user.
225
+ - Do not use emojis in files unless explicitly requested by the user.
226
+
227
+ Correct use for a new file:
228
+
229
+ ```json
230
+ {
231
+ "file_path":"/workspace/src/new_module.py",
232
+ "content":"def main():\n return None\n"
233
+ }
234
+ ```
235
+
236
+ Incorrect use for a small edit to an existing file:
237
+
238
+ ```json
239
+ {
240
+ "file_path":"/workspace/src/app.py",
241
+ "content":"<entire rewritten file just to change one line>"
242
+ }
243
+ ```
244
+
245
+ Use Edit instead.
246
+
247
+ ## Bash
248
+
249
+ **You must prefer dedicated tools over Bash.** This is critical: do not use `cat`, `head`, `grep`, or `sed` when Read,
250
+ Edit, or Write can do the job. If you find yourself reaching for a shell command to read or modify a file, stop and use
251
+ the dedicated tool instead.
252
+
253
+ Dedicated tool equivalents:
254
+
255
+ - Read instead of `cat`, `head`, `tail`, or `sed -n`.
256
+ - Edit instead of `sed -i`, `perl -pi`, or shell redirection.
257
+ - Write instead of `cat > file` or heredoc file creation.
258
+
259
+ Do not use Bash as a workaround for a failed dedicated tool call until you have retried once with the minimal valid
260
+ parameter object.
261
+
262
+ Example:
263
+
264
+ If this fails:
265
+
266
+ ```json
267
+ {"file_path":"/workspace/README.md","pages":""}
268
+ ```
269
+
270
+ Do not immediately use Bash. Retry:
271
+
272
+ ```json
273
+ {"file_path":"/workspace/README.md"}
274
+ ```
275
+
276
+ Only use Bash if the dedicated tool still cannot accomplish the task.
277
+
278
+ ## Common valid tool-call shapes
279
+
280
+ ### Read an ordinary file
281
+
282
+ ```json
283
+ {"file_path":"/workspace/README.md"}
284
+ ```
285
+
286
+ ### Read a section of a large ordinary file
287
+
288
+ ```json
289
+ {"file_path":"/workspace/large.log","offset":1000,"limit":200}
290
+ ```
291
+
292
+ ### Read a PDF page range
293
+
294
+ ```json
295
+ {"file_path":"/workspace/spec.pdf","pages":"1-5"}
296
+ ```
297
+
298
+ ### Edit an existing file
299
+
300
+ ```json
301
+ {
302
+ "file_path":"/workspace/src/app.py",
303
+ "old_string":"old exact text",
304
+ "new_string":"new exact text"
305
+ }
306
+ ```
307
+
308
+ ### Create a new file
309
+
310
+ ```json
311
+ {
312
+ "file_path":"/workspace/src/new_file.py",
313
+ "content":"file contents\n"
314
+ }
315
+ ```
316
+
317
+ ## Final preflight checklist
318
+
319
+ Before sending any tool call, ask:
320
+
321
+ 1. Are all required fields present?
322
+ 2. Did I omit every optional field that is not needed?
323
+ 3. Did I avoid empty-string, null, empty-list, and empty-object placeholders?
324
+ 4. If this is Read, is `pages` absent unless the file is a PDF?
325
+ 5. If this is Read for a normal file, am I using only `file_path`?
326
+ 6. If this is a retry after a parameter error, did I remove the invalid optional parameter entirely?
327
+ 7. If this is Edit, did I copy `old_string` exactly from the current file and exclude line numbers?
328
+ 8. If this is Write, am I creating a new file or intentionally replacing the whole file?
329
+
330
+ When in doubt, use the smallest valid object.