logancyang_obsidian-copilot/src/tools
Zero Liu 7aa1733857
fix(tools): remove zod transforms that break autonomous agent tool binding (#2551)
* fix(tools): remove zod transforms from tool schemas that break agent bindTools

readNote.chunkIndex was defined as z.preprocess(...).optional(), which is a
zod transform/pipe. When the autonomous agent binds tools, LangChain's
toJsonSchema() rewrites the schema to its input form (interopZodTransformInputSchema),
exposing the transform node, then zod v4's toJSONSchema() throws
"Transforms cannot be represented in JSON Schema". This surfaces at
langchainStream.ts as "Model request failed: ..." and breaks the entire
brain-icon ReAct agent loop (the non-agent Plus path is unaffected because it
binds only clean utility tools).

Replace the preprocess fields with JSON-Schema-representable unions and move the
string coercion into each tool's func:
- readNote.chunkIndex -> z.union([z.number().int().min(0), z.string()]).optional()
- writeFile.confirmation -> z.union([z.boolean(), z.string()]).optional()
  (writeFile only dodged the throw via its .default() wrapper; fixed defensively)

Add src/tools/toolSchemas.jsonschema.test.ts, which runs LangChain's
toJsonSchema() over the read/composer tools so a future transform in a tool
schema fails in CI instead of at runtime.

Refs logancyang/obsidian-copilot-preview#69

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(tools): validate readNote chunkIndex to prevent out-of-bounds crash

The union schema's string branch bypassed the old z.number().int().min(0)
validation, so a string like "-1" or "1.5" was coerced straight through; the
bounds check only rejects index >= totalChunks, so chunks[chunkIndex] became
undefined and the tool crashed while logging chunk.chunkIndex.

coerceChunkIndex now returns null for any value that is not a non-negative
integer (undefined still defaults to 0), and readNote returns a structured
invalid_chunk_index response instead of indexing out of bounds. Add coverage
for "-1", "1.5", and "abc".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 05:56:57 +08:00
..
allTools.validation.test.ts feat(agent-mode): introduce Agent Mode feature 2026-05-20 19:05:41 -07:00
builtinTools.ts Enforce no-global-app via ESLint and fix all violations (#2533) 2026-05-30 14:52:46 -07:00
CanvasLoader.ts fix(tools): replace cachedRead with vault.read in agent/tool paths (#2274) 2026-03-10 14:53:54 -07:00
ComposerTools.test.ts Composer V2: Replace replaceInFile with editFile as the primary targeted-edit tool (#2305) 2026-03-17 18:51:39 +09:00
ComposerTools.ts fix(tools): remove zod transforms that break autonomous agent tool binding (#2551) 2026-06-03 05:56:57 +08:00
createLangChainTool.ts chore(deps): remove unused deps and dead code to shrink bundle (#2460) 2026-05-14 22:25:59 -07:00
FileParserManager.ts Enforce no-global-app via ESLint and fix all violations (#2533) 2026-05-30 14:52:46 -07:00
FileTreeTools.test.ts Enforce no-global-app via ESLint and fix all violations (#2533) 2026-05-30 14:52:46 -07:00
FileTreeTools.ts Enforce no-global-app via ESLint and fix all violations (#2533) 2026-05-30 14:52:46 -07:00
memoryTools.ts Enforce no-global-app via ESLint and fix all violations (#2533) 2026-05-30 14:52:46 -07:00
NoteTools.ts fix(tools): remove zod transforms that break autonomous agent tool binding (#2551) 2026-06-03 05:56:57 +08:00
ObsidianCliDailyTools.test.ts chore(eslint): enable no-unsafe-assignment for tests (#2434) 2026-05-13 22:56:46 -07:00
ObsidianCliDailyTools.ts Add Obsidian CLI daily/random read tools and reasoning summaries (#2181) 2026-03-05 17:40:07 -08:00
ObsidianCliTools.test.ts chore(eslint): enable no-unsafe-assignment for tests (#2434) 2026-05-13 22:56:46 -07:00
ObsidianCliTools.ts chore(eslint): enable no-unnecessary-type-assertion and no-misused-promises (#2441) 2026-05-13 21:27:35 -07:00
ReadNoteTool.test.ts fix(tools): remove zod transforms that break autonomous agent tool binding (#2551) 2026-06-03 05:56:57 +08:00
SearchTools.dedupe.test.ts Implement inline citation (#1821) 2025-09-21 20:03:09 -07:00
SearchTools.schema.test.ts fix: remove returnAll from agent-facing search tools to prevent token spikes (#2272) (#2273) 2026-03-06 19:59:03 -08:00
SearchTools.ts Enforce no-global-app via ESLint and fix all violations (#2533) 2026-05-30 14:52:46 -07:00
TagTools.test.ts Enforce no-global-app via ESLint and fix all violations (#2533) 2026-05-30 14:52:46 -07:00
TagTools.ts Enforce no-global-app via ESLint and fix all violations (#2533) 2026-05-30 14:52:46 -07:00
TimeTools.test.ts chore(eslint): enable no-unsafe-assignment for tests (#2434) 2026-05-13 22:56:46 -07:00
TimeTools.timezone.test.ts chore(eslint): enable no-unsafe-assignment for tests (#2434) 2026-05-13 22:56:46 -07:00
TimeTools.ts Enable basic obsidian eslint rules (#2410) 2026-05-13 00:49:49 -07:00
toolManager.ts chore(eslint): enable no-explicit-any; fix ~395 violations (#2452) 2026-05-14 02:08:45 -07:00
ToolRegistry.ts Add Obsidian CLI daily/random read tools and reasoning summaries (#2181) 2026-03-05 17:40:07 -08:00
ToolResultFormatter.test.ts chore(eslint): enable @typescript-eslint/no-unsafe-argument and fix violations (#2440) 2026-05-13 21:40:26 -07:00
ToolResultFormatter.ts chore(eslint): enable no-explicit-any; fix ~395 violations (#2452) 2026-05-14 02:08:45 -07:00
toolSchemas.jsonschema.test.ts fix(tools): remove zod transforms that break autonomous agent tool binding (#2551) 2026-06-03 05:56:57 +08:00
YoutubeTools.ts feat: self-host web search (Firecrawl) + YouTube (Supadata) (#2190) 2026-02-18 23:23:39 -08:00