Repository navigation
Conversation
jatmn
left a comment
There was a problem hiding this comment.
Findings
- [P1] Return normal ToolResult objects from the new tools
src/tools/HttpRequestTool/HttpRequestTool.ts:76
The three new tools implementasync *call(...)andyield { type: 'result', result: ... }, but this repo's tool executor awaitstool.call(...)and then readsresult.databefore callingtool.mapToolResultToToolResultBlockParam(...). Because an async generator is returned immediately whencallis awaited, none of the request logic runs,result.dataisundefined, and these tools also do not definemapToolResultToToolResultBlockParam, so invoking any of them fails in the tool execution path instead of returning output to the model. Please makecallanasyncfunction that returns{ data: ... }and add the normal result mapping, as existing tools such asWebFetchTooldo; the tests should also exercisecall()through this contract for all three new tools.
HttpRequestTool - HTTP/REST API client with 7 methods (GET/POST/PUT/PATCH/DELETE/HEAD/OPTIONS), custom headers, query params, body (JSON/string), redirect handling, configurable timeout. Uses native fetch. GraphqlTool - GraphQL query/mutation/subscription client with variables, operation name, custom headers, timeout. Uses native fetch. isReadOnly classifies query vs mutation/subscription. NetworkDiagnosticTool - Network diagnostics with 7 actions: ping (cross-platform), dns (dig/nslookup with record types), traceroute, port-check, ssl-cert (openssl), http-status (curl), latency. Input sanitization via escapeShell. All tools follow the existing buildTool pattern with isReadOnly, validateInput, renderToolUseMessage/renderToolResultMessage. Tests: 43/43 passing (12 HttpRequestTool + 15 GraphqlTool + 16 NetworkDiagnosticTool)
7e4d748 to
d592480
Compare
|
Addressed all reviewer findings from @jatmn [P1] async call generators → proper async call contract** ✅ Rewrote all three tools (HttpRequestTool, GraphqlTool, NetworkDiagnosticTool) from async *call(input, context) { yield { type: 'result', result: ... } } generators to the correct async call(args, context, canUseTool?, parentMessage?, onProgress?): Promise<ToolResult> contract. Each now returns { data: { ... } } — the tool executor's call().data is now properly populated. [P1] Added mapToolResultToToolResultBlockParam ✅ Added mapToolResultToToolResultBlockParam(output, toolUseID) to all three tools, returning the required { tool_use_id, type: 'tool_result', content: JSON.stringify(output) }. Tools now produce valid tool_result blocks that the execution pipeline can consume. Tests: 36/36 passing · Build: compiles clean · Pushed: d592480 on feature/api-network-tools |
jatmn
left a comment
There was a problem hiding this comment.
Thanks for following up on the earlier review. The requested call() contract and result-mapping fixes look addressed now, but I found two remaining issues below.
Findings
-
[P1] Wrap the new tool definitions with
buildTool
src/tools/HttpRequestTool/HttpRequestTool.ts:34
The three new tools are exported as plainToolDefobjects instead ofbuildTool({ ... }), even though they are registered directly ingetAllBaseTools(). At runtime that means the default methods supplied bybuildToolare missing:checkPermissions,isEnabled,isConcurrencySafe, anduserFacingNameare all undefined on these exports. The focused tests instantiate the tools directly and only cover methods the PR defines, so they pass, but the normal tool permission path callstool.checkPermissions(...); invoking any of these registered tools will fail before reaching the fixedcall()implementation. Please export all three viabuildTool(...)and add a registry/tool-execution smoke test that catches the missing default methods. -
[P2] Do not mark mutating HTTP requests as read-only
src/tools/HttpRequestTool/HttpRequestTool.ts:42
HttpRequestTool.isReadOnly()always returnstrue, while the schema and implementation allowPOST,PUT,PATCH, andDELETErequests with arbitrary bodies. That advertises calls that can create, modify, or delete remote resources as safe read-only tool use, unlike the GraphQL tool which treats mutations as non-read-only. Please classify only safe methods such asGET,HEAD, and maybeOPTIONSas read-only, and add coverage for mutating methods so permission UI/SDK annotations do not understate the risk.
|
Addressed both remaining findings: [P1] Wrapped all 3 tools with buildTool({...})
[P1] Fixed HttpRequestTool isReadOnly — only safe methods classified as read-only
[P2] Added checkPermissions for GraphqlTool and NetworkDiagnosticTool
|
cb6aa8f to
ec68d5d
Compare
jatmn
left a comment
There was a problem hiding this comment.
Thanks for following up on the earlier review. The requested call() contract, result mapping, buildTool(...) wrapping, and HTTP read-only classification fixes look addressed now. I found a few remaining issues below.
Findings
-
[P1] Do not auto-allow arbitrary HTTP GET/HEAD/OPTIONS requests
src/tools/HttpRequestTool/HttpRequestTool.ts:52
checkPermissions()returnsallowfor every safe-looking HTTP method, but this new tool can reach arbitrary URLs with arbitrary headers and query params. That bypasses the host-based permission behavior used byWebFetchTool, so the model can read private network endpoints or trigger GET-based side effects without any user approval. Please ask/reuse per-host permission rules for new destinations even when the method is read-only, while still classifying mutating methods as non-read-only. -
[P1] Detect GraphQL mutations after comments before allowing without permission
src/tools/GraphqlTool/GraphqlTool.ts:54
The mutation/subscription check only matches when the first non-whitespace token ismutationorsubscription, but GraphQL documents can start with comments. For example# comment\nmutation { createUser { id } }currently returnsisReadOnly === trueandcheckPermissions().behavior === "allow", so a mutating operation can bypass the permission prompt. Please parse or normalize GraphQL comments before classifying the operation, and add coverage for commented mutations/subscriptions. -
[P2] Make port-check and latency work on Windows or report the missing command
src/tools/NetworkDiagnosticTool/NetworkDiagnosticTool.ts:75
The Windows-aware branches cover ping/DNS/traceroute, butport-checkandlatencyalways executebash -cwith/dev/tcp. On a normal Windows install withoutbash,spawnSyncreturns an error object rather than throwing, and this code reportssuccess: falsewithoutput: "No output"and noerror, so two advertised diagnostic actions are unusable and hard to debug. Please either implement these actions with a cross-platform TCP socket path or gate them with a clear platform/command error, and include a test forresult.error.
…port-check/latency
|
Addressed all 3 findings: [P1] HttpRequestTool now asks permission for ALL requests
[P1] GraphqlTool strips # comments before classifying operations
[P2] port-check and latency now work cross-platform
|
jatmn
left a comment
There was a problem hiding this comment.
Thanks for following up on the earlier reviews. The requested call() contract, result mapping, buildTool(...) wrapping, HTTP read-only classification/permission prompting, GraphQL comment handling, and Windows diagnostic error reporting fixes look addressed now. I found two remaining issues below.
Findings
-
[P1] Ask before sending GraphQL queries to arbitrary endpoints
src/tools/GraphqlTool/GraphqlTool.ts:59
checkPermissions()still returnsallowfor every operation classified as a query, even though the tool POSTs to an arbitrary URL with caller-supplied headers and variables. That preserves the same arbitrary-host access issue fixed forHttpRequestTool: the model can query private network GraphQL endpoints or include custom auth headers without any user approval, whileWebFetchTooland the new HTTP tool both require host/request approval. Please require permission for GraphQL requests by endpoint/host as well, while still usingisReadOnly()only to classify query vs mutation semantics. -
[P2] Treat closed ports and TCP timeouts as failed diagnostics
src/tools/NetworkDiagnosticTool/NetworkDiagnosticTool.ts:75
Theport-checkandlatencycommands print failure text such asclosedortimeoutbut still exit with status 0, so line 92 reportssuccess: truefor failed connectivity checks. I reproduced this locally withport-checkagainst127.0.0.1:9, which returned{"success":true,"output":"closed\n"}. That gives the caller the opposite signal from the diagnostic output. Please make these branches exit non-zero or derivesuccessfrom the parsed result, and add coverage for closed/timeout cases.
…put, deep review fixes
|
Addressed both reviewer findings plus additional issues caught during deep review:
[P2] Closed ports and timeouts now report success: false
Additional issues found during self-review:
|
|
@LifeJiggy currently does not pass smoke, please fix. Will be glad to re-review after |
|
Replaced AbortSignal.timeout(...) with cleanup-registered abort controllers in both HttpRequestTool and GraphqlTool. The pattern: Also fixed registerCleanup to accept sync functions (() => void | Promise) and added setCleanupTimeout, setCleanupInterval, createCleanupAbortController helpers to cleanupRegistry.ts. This should resolve the "raw timeout signal guard" CI test. |
jatmn
left a comment
There was a problem hiding this comment.
Findings
-
[P1] Windows timeouts are reported as successful
port-check/latencyresults
File:src/tools/NetworkDiagnosticTool/NetworkDiagnosticTool.ts
The Windows branches useTcpClient.ConnectAsync(...).Wait(5000)inside atryblock and then immediately printopenor"$elapsed ms"on the success path.Task.Wait(timeoutMs)returnsfalseon timeout; it does not throw. That means a filtered or blackholed target can time out and still be reported asopen(port-check) or as a numeric latency (latency), which flips the diagnostic result from failure to success. This affects the tool's core correctness on Windows. -
[P2] The new cleanup-safe timeout helper leaks shutdown callbacks across tool calls
File:src/utils/cleanupRegistry.ts
setCleanupTimeout()registers() => clearTimeout(id)into the global cleanup registry but never unregisters that callback after the timer fires or after the request completes. BothHttpRequestToolandGraphqlToolcall this helper for every request, so long-lived sessions accumulate one permanent cleanup closure per invocation. The rest of the codebase usually keeps the unregister handle and removes cleanup handlers when the resource lifetime ends; this helper does not, so repeated use of the new tools growscleanupFunctionsunboundedly.
P1 - Windows timeout detection in NetworkDiagnosticTool:
- port-check and latency actions now correctly check Task.Wait() return value
- Previously relied on try/catch which doesn't work - Task.Wait returns false on timeout
- Changed to explicit if/else to properly detect timeout vs success
P2 - Cleanup callback leak in cleanupRegistry:
- setCleanupTimeout now returns { id, unregister } instead of just id
- HttpRequestTool and GraphqlTool now call unregister() in finally block
- Ensures cleanup callbacks are removed after each request completes
- Prevents memory leak from accumulated closures in long-lived sessions
Windows EBUSY fix (pre-existing):
- knowledgeGraph.ts:641 now wraps sqlitePath deletion in try/catch
- Matches existing pattern for oramaPath at line 644
288bc37 to
ca955cc
Compare
|
This PR addresses all feedback from jatmn's code review: P1 - Windows timeout bug (NetworkDiagnosticTool.ts:77,84)
P2 - Cleanup callback leak (cleanupRegistry.ts + callers)
|
…t CCR Closes Twigpine#402 — JavaScript heap OOM during large tasks. The CLI entry point only set --max-old-space-size=8192 when CLAUDE_CODE_REMOTE=true, leaving local users with V8's ~2 GB default ceiling. Long agentic tasks (multi-file refactors, large prompts, tool loops) hit that ceiling and abort with: FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory Fix: remove the CCR gate and apply the 8 GB cap unconditionally, with a user-override guard -- if the runner already set NODE_OPTIONS --max-old-space-size to an explicit value, their setting is preserved (no silent clobbering). Files changed: - src/entrypoints/cli.tsx — remove CLAUDE_CODE_REMOTE guard, add user-override predicate, update comments - src/entrypoints/cli.test.ts — 6 regression tests (new file)
… not just CCR" This reverts commit 2864e75.
|
Closing this PR. Adding multiple new tools in a single PR without prior maintainer discussion is not the right approach for a 25k+ star project. If you want to contribute tools, please:
Bulk tool additions create review burden and maintenance overhead. |
|
Bulk tool addition without prior discussion. |
Summary
what changed: Added three new built-in tools —
HttpRequestTool(REST API client),GraphqlTool(GraphQL client), andNetworkDiagnosticTool(network diagnostics with 7 actions).why it changed: API testing and network diagnostics are core developer workflows that previously required raw
curl/bashcommands viaBashTool, yielding unstructured output with no error handling, safety classification, or input validation.Impact
user-facing impact: Users can now make HTTP requests, run GraphQL queries, and diagnose network issues (ping, DNS, traceroute, port checks, SSL inspection, latency) directly through the agent with structured responses, proper error handling, and safety checks. Combined with the existing
BashToolandWebFetchTool, this completes the API interaction workflow.developer/maintainer impact: Low. All three tools follow the exact
buildTool({...})pattern used by 50+ existing tools. No new npm dependencies —HttpRequestToolandGraphqlTooluse nativefetch,NetworkDiagnosticToolwraps system CLIs withescapeShell()sanitization. Adding new HTTP methods, DNS record types, or diagnostic actions is a one-line config change.Testing
bun run build— compiles cleanlybun run smokebun test src/tools/HttpRequestTool/HttpRequestTool.test.ts— 12/12 passbun test src/tools/GraphqlTool/GraphqlTool.test.ts— 15/15 passbun test src/tools/NetworkDiagnosticTool/NetworkDiagnosticTool.test.ts— 16/16 passNotes
fetchand system CLIs, not AI providers)NetworkDiagnosticToolrequires system tools:ping,dig/nslookup,traceroute/tracert,openssl,curl— these may not be pre-installed on minimal containersNetworkDiagnosticToolport-check on Linux uses/dev/tcpbash feature (may fail in restricted shells orshinstead ofbash)HttpRequestToolredirect chain tracking only captures the final URL — intermediate redirect hops are not preserved