Skip to content

feat(validation): add tool definition and message content validators - #1

Merged
Goldokpa merged 1 commit into
identArk:mainfrom
Kem-Ada:feat/validation
Sep 23, 2026
Merged

Goldokpa merged 1 commit into
identArk:mainfrom
Kem-Ada:feat/validation

Conversation

@Kem-Ada

@Kem-Ada Kem-Ada commented Sep 21, 2026

Copy link
Copy Markdown
Contributor

Summary

Ports the Python SDK's identark/validation.py to TypeScript as src/validation.ts, bringing the three validators into the TS SDK:

  • validateToolDefinitions(tools) checks that tools follow the OpenAI function-calling schema and throws ConfigurationError on malformed input.
  • validateToolResultJson(content, toolName) calls console.warn (never throws) when a tool result isn't valid JSON.
  • validateMessageContent(content) accepts a string, an array of content blocks (each needs a type), or null/undefined. It throws ConfigurationError otherwise.

validateToolDefinitions now runs at the start of DirectGateway.invokeLlm / invokeLlmStream, so malformed tools are rejected before any provider call. As in Python, MockGateway does not validate. All three functions are exported from the package index.

Wiring into ControlPlaneGateway is deferred to PR #8 (control plane).

Python → TS parity mapping

Python (identark/validation.py) TypeScript (src/validation.ts) Notes
validate_tool_definitions(tools) validateToolDefinitions(tools) Same checks, same order. None → undefined/null.
validate_tool_result_json(content, tool_name) validateToolResultJson(content, toolName) logger.warning → console.warn (the TS SDK has no logger).
validate_message_content(content) validateMessageContent(content) str | list[dict] | None → string | object[] | null | undefined.
logger.debug(... parameters missing 'type' ...) (comment only) Still allowed. The debug log line is dropped because the TS SDK has no debug logger.
ConfigurationError ConfigurationError Existing class, unchanged.
DirectGateway.invoke_llm / invoke_llm_stream call validate_tool_definitions DirectGateway.invokeLlm / invokeLlmStream Same position: invokeLlm validates after the cost-cap check, and the stream validates before it (as in Python).
MockGateway does not validate MockGateway does not validate Unchanged. A test pins this so the mock stays lenient, as in Python.
ControlPlaneGateway.invoke_llm* call validate_tool_definitions Deferred to PR #8 Control-plane code is out of scope for this PR.

Error wording uses TS terms: "must be an array" / "must be an object" instead of Python's "must be a list" / "must be a dict", and type names are array/object/number instead of list/dict/int. Everything else in the messages matches Python word for word (e.g. tools[0] missing required 'type' field, tools[1].function.name must be a non-empty string).

Test plan

New file tests/validation.test.ts (30 tests) mirrors every case in tests/unit/test_validation.py (22 cases) and adds:

  • negative: array-typed tool, numeric function.name, array parameters, plain-object message content, index reporting (tools[1])
  • positive: parameters without type, null for tools and content
  • wiring: index exports; DirectGateway invoke and stream reject bad tools without calling the provider or growing history; valid tools reach the provider unchanged; MockGateway still accepts unvalidated tools (parity with Python)

Gate output (run locally on this branch):

$ npm ci                      # ok
$ npm run lint
> eslint src --max-warnings 0
                              # clean
$ npm run typecheck
> tsc --noEmit
                              # clean
$ npx vitest run
 ✓ tests/types.test.ts  (5 tests)
 ✓ tests/managed-tools.test.ts  (2 tests)
 ✓ tests/vercel-integration.test.ts  (5 tests)
 ✓ tests/control-plane.test.ts  (17 tests)
 ✓ tests/mock-gateway.test.ts  (12 tests)
 ✓ tests/direct-gateway.test.ts  (13 tests)
 ✓ tests/validation.test.ts  (30 tests)

 Test Files  7 passed (7)
      Tests  84 passed (84)
$ ../scripts/check_scope.sh
check_scope: OK — no control-plane code touched.

Baseline before this PR: 54 tests / 6 files. After: 84 tests / 7 files (+30).

Control-plane: untouched (check_scope OK)

🤖 Generated with Claude Code

Port identark/validation.py to src/validation.ts:
- validateToolDefinitions: OpenAI function-calling schema checks,
  throws ConfigurationError on malformed tools
- validateToolResultJson: warns (console.warn) on non-JSON tool results
- validateMessageContent: string | content-block array | null

Wire validateToolDefinitions into DirectGateway invokeLlm/invokeLlmStream
(as Python's DirectGateway does) and export all three from the package
index. MockGateway is left unvalidated, matching the Python MockGateway.
ControlPlaneGateway wiring is deferred to PR identArk#8.

Co-Authored-By: Claude <noreply@anthropic.com>
@Goldokpa
Goldokpa merged commit 268d080 into identArk:main Sep 23, 2026
4 checks passed
Goldokpa pushed a commit that referenced this pull request Oct 9, 2026
)

Port identark/validation.py to src/validation.ts:
- validateToolDefinitions: OpenAI function-calling schema checks,
  throws ConfigurationError on malformed tools
- validateToolResultJson: warns (console.warn) on non-JSON tool results
- validateMessageContent: string | content-block array | null

Wire validateToolDefinitions into DirectGateway invokeLlm/invokeLlmStream
(as Python's DirectGateway does) and export all three from the package
index. MockGateway is left unvalidated, matching the Python MockGateway.
ControlPlaneGateway wiring is deferred to PR #8.

Co-authored-by: Kem-Ada <283358351+Kem-Ada@users.noreply.github.com>
@Goldokpa Goldokpa mentioned this pull request Oct 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants