Repository navigation
feat(vended-tools): add python_repl vended tool to TS [replica of harness-sdk PR 5041] - #35
poshinchen wants to merge 3 commits into
Conversation
poshinchen
left a comment
There was a problem hiding this comment.
Strandly v4-reason (optimized) review — run af1746, Opus 4.8
Assessment: approve
Assessment: Approve
Clean, well-scoped TypeScript port of the Python python_repl tool with thorough tests (shim behavior, local execution, timeout, cancellation, validation) and complete docs/README.
Review Categories
- Error handling: One important note — the timeout path mutates
err.messageto embed JSON partial output, forcing consumers (and the test) to parse the message string; a structured field would be more robust. - Input validation: Minor edge cases — empty-string
descriptionbypasses the default, and whitespace-onlynamepasses the non-empty check. - Typing: The
PythonReplOutputindex signature widens the public type; a note or narrower boundary cast would preserve type safety.
Overall a solid contribution with strong test coverage and clear documentation.
| name, | ||
| description: options.description ?? PYTHON_REPL_DESCRIPTION, | ||
| inputSchema: pythonReplInputSchema, | ||
| callback: async (input, context): Promise<PythonReplOutput> => { |
There was a problem hiding this comment.
Suggestion
Issue: description uses ??, so an explicitly-provided empty string (description: '') silently bypasses the default and ships an empty description to the model. name is guarded against empty, but description is not.
Suggestion: Treat an empty description as unset (or validate it), e.g. options.description || PYTHON_REPL_DESCRIPTION, to mirror the non-empty intent applied to name.
| return { output: result.stdout, error: result.stderr, exit_code: result.exitCode } | ||
| } catch (err) { | ||
| // Let cancellation propagate as-is rather than reporting it as a sandbox failure. | ||
| if (err instanceof SandboxAbortError) throw err |
There was a problem hiding this comment.
Important
Issue: The SandboxTimeoutError branch mutates err.message in place by appending the JSON partial output. If a caller inspects or logs this same error object elsewhere, they now see a message with embedded JSON. Mutating a caught error is a surprising side effect and makes the message harder to parse programmatically (the partial output is only recoverable via .split('\n')[1], as the test shows).
Suggestion: Consider attaching the partial output as a structured property on the error (or on PythonReplError-style wrapper) rather than mutating message, so consumers can read it without string parsing.
| const language = options.language ?? DEFAULT_LANGUAGE | ||
|
|
||
| if (!name) { | ||
| throw new Error('name must be a non-empty string') |
There was a problem hiding this comment.
Suggestion
Issue: name is only validated as non-empty via !name, so a whitespace-only name (e.g. ' ') passes construction but is effectively invalid as a tool identifier.
Suggestion: Consider trimming before the check (e.g. if (!name.trim())) if whitespace-only names should be rejected, matching the "non-empty string" intent in the error message.
| const payload = JSON.parse((error as Error).message.split('\n')[1]!) | ||
| expect(payload).toStrictEqual({ output: 'partial\n', error: '', exit_code: 124 }) | ||
| }) | ||
|
|
There was a problem hiding this comment.
Suggestion
Issue: The timeout test asserts the partial payload by splitting the error message on \n and parsing index [1]. This couples the test to the exact message layout, so any formatting change (even an extra newline in the base message) breaks it in a non-obvious way.
Suggestion: If the partial output were exposed as a structured field on the error (see comment in python-repl.ts), this assertion could read that field directly instead of parsing the message string.
| /** | ||
| * Allow indexing with string keys for JSONValue compatibility. | ||
| */ | ||
| [key: string]: string | number |
There was a problem hiding this comment.
Suggestion
Issue: The PythonReplOutput interface includes an index signature [key: string]: string | number solely for JSONValue compatibility. This weakens type safety — any arbitrary string key is now accepted as valid, so typos like result.exitcode won't be caught at compile time.
Suggestion: If the index signature is required by a JSONValue constraint, a brief inline note on why it's unavoidable would help; otherwise consider a narrower cast at the boundary where JSONValue is required rather than widening the public return type.
|
Live Strandly's actual comments on the original PR 5041 (sanitized copy: mentions escaped, links backticked) Review (COMMENTED):
Review (APPROVED):
Inline at
Inline at
Inline at
Inline at
|
Documentation Preview FailedThe documentation deployment encountered an error. Please check the deployment logs for more details. |
Replica of
https://github.com/strands-agents/harness-sdk/pull/5041(backticked: no cross-reference). Below: the v4-reason optimized review and a sanitized copy of live Strandly's actual comments.