## Problem
When a HITL (Human-in-the-Loop) tool has no parameters, some providers
(e.g., Google ADK) send `arguments` as an empty string `""`.
`JSON.parse("")` throws `"Unexpected end of JSON input"`, crashing the
tool execution pipeline with an opaque error instead of executing the
tool with empty args.
Fixes#3263
## Root Cause
In `run-handler.ts`, both the specific-tool and wildcard-tool execution
paths call `JSON.parse(toolCall.function.arguments)` without checking
for empty/falsy values:
```ts
// Line 309 — specific tool path
parsedArgs = JSON.parse(toolCall.function.arguments); // crashes on ""
// Line 448 — wildcard tool path
parsedArgs = JSON.parse(toolCall.function.arguments); // crashes on ""
```
## Fix
Treat empty/falsy argument strings as `{}` (empty object) before
parsing:
```ts
const rawArgs = toolCall.function.arguments;
parsedArgs = rawArgs ? JSON.parse(rawArgs) : {};
```
This matches the existing defensive patterns:
- **v1 `agui-to-gql.ts`**: already catches parse errors and falls back
to `{}`
- **v2 `web-inspector`**: already checks `args === "" ` before parsing
(line 818)
## Changes
| File | Change |
|------|--------|
| `packages/v2/core/src/core/run-handler.ts` | Safe empty-args fallback
at both parse sites |
| `packages/v2/core/src/__tests__/core-edge-cases.test.ts` | Updated
test: empty args → handler called with `{}` |
| `packages/v2/core/src/__tests__/core-full.test.ts` | Updated test:
empty args → handler called with `{}` |
## Testing
- All 230 passing tests still pass (61 pre-existing failures in
unrelated packages unchanged)
- Updated 2 tests that previously expected a crash on empty args to
verify the handler is called with `{}`
Address review feedback:
- Extract parseToolArguments() to deduplicate empty/null/undefined handling
- Add debug-level warning when arguments fallback to {} (no longer silent)
- Type toolCall parameter as ToolCall instead of any in executeSpecificTool
and executeWildcardTool
- Both specific-tool and wildcard paths share the same parsing logic
Treat empty, null, or undefined tool arguments as {} instead of throwing
a JSON parse error. Uses explicit checks (=== '' || === null || === undefined)
rather than a broad falsy check, as recommended in review.
Addresses all review feedback from jpr5:
- Added tests for wildcard tool path with empty args
- Added tests for null and undefined arguments
- Used explicit empty/null/undefined check instead of broad falsy
- Added inline comments explaining the fallback rationale
- Removed duplicate tests (TEST 7/8) from core-full.test.ts
- Removed console.log debugging statements from tests
Run prettier on ~1,865 files across examples/ to match the monorepo's
formatting standards. These files were imported as-is from standalone
repos that used different prettier configs.
- base-command: wrap checkCLIVersion() fetch in try-catch so CLI
doesn't crash when offline (version check is non-critical)
- init: forward argv to Create instead of dropping all flags, remove
misleading flag definitions (init is just a deprecated redirect)
- detect-endpoint-type: fix Promise.all destructuring (5 promises but
only 4 variables caused isCopilot to receive the LangGraph FastAPI
result), add missing isMCP branch, use isLangGraphFastAPI result
- auth.service: validate OAuth state parameter before tracking analytics
with user data, add reject()+server.close() on state mismatch so the
Promise settles instead of hanging the CLI forever
- create.test: fix quote-style assertion to match prettier output
- Remove copy-paste triplication in scaffoldAgent (LangSmith block
duplicated twice, causing duplicate .env entries and redundant writes)
- Update AgentTemplates URLs to point to monorepo paths instead of
archived standalone repos
- Fix flags.projectName → args.projectName in banner logic (projectName
is an Args field, not Flags)
- Remove stale trpc-cli path mapping and project reference from
tsconfig.json (package doesn't exist in this monorepo)
Migrate the copilotkit CLI (npx copilotkit create/init/dev) from
CopilotCloud into packages/v1/cli. TEMPLATE_REPOS updated to use
monorepo subdirectory sparse checkout for all CopilotKit-owned
templates, with tarball fallback for external repos (ag2).
Mark all publishable @copilotkitnext/* packages as deprecated in
package.json, pointing users to the @copilotkit/* equivalents.
V2 features will be available under the /v2 subpath.
Affected packages: shared, core, agent, angular, react, runtime,
sqlite-runner, web-inspector.
Remove throw on isArgumentError — matches main's behavior where parse
errors are emitted via subscribers and the run continues, rather than
crashing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a new `runTool()` method to `CopilotKitCore` that allows programmatic
execution of registered frontend tools without requiring an LLM turn. This
enables UI-driven tool invocations (e.g., button clicks triggering tool
handlers) while maintaining proper message history and subscriber notifications.
Key changes:
- Extract `executeToolHandler` helper from duplicated logic in
`executeSpecificTool` to share with `runTool`
- Add `runTool()` on `RunHandler` with tool/agent lookup, message creation,
handler execution, and optional follow-up support
- Add `TOOL_NOT_FOUND` and `AGENT_NOT_FOUND` error codes
- Add `CopilotKitCoreRunToolParams` and `CopilotKitCoreRunToolResult` types
- Add delegation method on `CopilotKitCore`
- Add 16 comprehensive tests covering all runTool behaviors
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Same fix as zod-regression — the mock was missing addHookRenderToolCall
and removeHookRenderToolCall methods.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The mock was missing addHookRenderToolCall/removeHookRenderToolCall methods
introduced by the separate hook vs prop render tool call storage refactor.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Address review feedback: remove `as ReactToolCallRenderer` cast in
useFrontendTool by guarding with `tool.parameters` check (matching
CopilotKitProvider's pattern). Remove unused ReactToolCallRenderer
imports from use-frontend-tool.tsx and use-render-tool.tsx.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add tests verifying:
- useFrontendTool render registrations survive StrictMode remount
- Hook and prop render entries coexist through StrictMode remount
- Hook render entries survive provider prop changes
- Update useRenderTool test mock to match new addHookRenderToolCall API
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
CopilotKitProvider's didMountRef guard breaks under React Strict Mode:
refs persist across the simulated unmount/remount cycle, causing the
provider's setRenderToolCalls effect to overwrite registrations from
useFrontendTool and useRenderTool hooks.
Split render tool call storage in CopilotKitCoreReact into two layers:
- _renderToolCalls: prop-based entries (set by provider)
- _hookRenderToolCalls: hook-based entries (set by useFrontendTool/useRenderTool)
The renderToolCalls getter merges both with a cached result for
useSyncExternalStore referential stability. Provider and hooks can
never overwrite each other, eliminating the race by design.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace Zod-specific types (z.ZodType, z.infer) with Standard Schema V1
interfaces across the V2 public API surface. This allows users to use any
Standard Schema V1 compatible library (Zod 3.24+, Valibot v1+, ArkType v2+)
for tool parameters, with zero breaking changes for existing Zod users.
- Add schemaToJsonSchema() utility in shared with Standard JSON Schema V1
support and Zod fallback
- Update FrontendTool, ToolDefinition, useRenderTool, useComponent, and
Angular tool types to accept StandardSchemaV1
- Move zod from dependencies to devDependencies in core and angular
- Add runtime tests (40) and type-level tests (38) across all packages
verifying Zod, Valibot, and ArkType compatibility
CRITICAL 1: ensureObjectArgs (renamed from safeParseToolArgs) in
run-handler.ts now throws on non-object parsed results so the catch
block fires TOOL_ARGUMENT_PARSE_FAILED structured errors.
CRITICAL 2: partialJSONParse return type reverted from
Record<string,unknown> to unknown — callers handle the type.
IMPORTANT 3: safeParseToolArgs consolidated into shared/utils.ts and
exported. Agent/index.ts imports from @copilotkitnext/shared. V1 keeps
a local copy with a comment noting it mirrors the shared version.
IMPORTANT 4: All non-object fallback sites now emit console.warn with
consistent [CopilotKit] prefix format.
IMPORTANT 5: Removed console.warn from getPartialArguments catch block
(incomplete JSON is expected during streaming). Warning is now only in
the try-block non-object guard.
TEST 6: Added run-handler-ensureObjectArgs.test.ts covering valid
object, string, number, array, null, boolean, and undefined inputs.
TEST 7: Added conversion.test.ts for v1 safeParseToolArgs covering
valid object, string, number, array, malformed JSON, null, boolean,
and empty string inputs.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>