Skip to content

Added TypeScript SDK#492

Open
Timandes wants to merge 50 commits intoalibaba:masterfrom
Timandes:feature/ts-sdk
Open

Added TypeScript SDK#492
Timandes wants to merge 50 commits intoalibaba:masterfrom
Timandes:feature/ts-sdk

Conversation

@Timandes
Copy link
Contributor

@Timandes Timandes commented Feb 12, 2026

关联Issue #495

包地址:https://www.npmjs.com/package/rl-rock

支持:

🚀 沙箱管理 - 创建、启动、停止远程容器沙箱

📁 文件系统 - 上传、下载、读取、写入文件

🖥️ 命令执行 - 同步/异步执行 Shell 命令

🔧 运行时环境 - 支持 Python、Node.js 运行时环境管理

🤖 Agent 框架 - 内置 Agent 支持自动化任务

📦 EnvHub - 环境注册与管理

🔄 双模式构建 - 同时支持 ESM 和 CommonJS

@CLAassistant
Copy link

CLAassistant commented Feb 12, 2026

CLA assistant check
All committers have signed the CLA.

- Add ts-case-convert for automatic case conversion
- Implement HTTP layer auto-transform (request → snake_case, response → camelCase)
- Refactor all response types to use camelCase
- Update examples and documentation

BREAKING CHANGE: All response fields now use camelCase instead of snake_case
(e.g., sandbox_id → sandboxId, exit_code → exitCode)
- Fix getStatus URL to use sandbox_id instead of sandboxId
- Fix logger getLogLevel to use lowercase for level matching
- Rename write_file() to writeFile()
- Rename read_file() to readFile()
- Add ESLint naming-convention rule to enforce camelCase
- Update examples to use new method names
- Modify HttpUtils.get/post/postMultipart to return structured response
  with {status, result, headers}
- Add HeaderFieldsSchema with cluster, requestId, eagleeyeTraceid
- Update all Response types to include header-derived fields
- Extract headers in all Sandbox methods and merge into results
- Fix HttpUtils generic type parameter usage in client methods
- Fix EnvHubClient to use response.result from new HttpUtils return type
Copy link
Collaborator

@dengwx2026 dengwx2026 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TypeScript SDK Review

Overall this is a solid foundation for the TS SDK — good module structure, nice mirroring of the Python SDK patterns, and sensible use of Zod for type definitions. However, there are several critical bugs that will cause runtime failures, plus some architectural concerns worth addressing before merging.

Summary

  • 5 Critical issues — will cause runtime failures (stub uploadDir, broken multipart uploads, __dirname in ESM, heredoc expansion bug, malformed URL)
  • 8 Major issues — should be fixed (version mismatch, command injection, infinite loops, unused exception system, etc.)
  • 9 Minor issues — code quality improvements (duplication, hardcoded values, dead code)

Architectural Suggestions

  1. Use typed exceptions or remove them: RockException, BadRequestRockError, raiseForCode() etc. are well-designed but never called anywhere. All errors are thrown as generic new Error(...). Either integrate raiseForCode() into the HTTP layer, or remove the unused exception hierarchy.

  2. Validate with Zod or drop it: Zod schemas are defined for all request/response types but .parse() / .safeParse() is never called on API data. They only serve as z.infer<> type extraction — plain TypeScript interfaces would eliminate the Zod dependency with the same result.

  3. Remove browser compatibility stubs: The SDK imports fs, crypto, child_process, https, Buffer — it fundamentally cannot work in browsers. The isBrowser() checks in system.ts are misleading.

  4. Consolidate duplicated code: RunModeType/RunMode are duplicated in sandbox/types.ts and common/constants.ts. extractNohupPid is duplicated in sandbox/utils.ts and utils/http.ts. sleep is duplicated in model/client.ts and utils/retry.ts.

  5. Add cancellation support: ModelClient polling loops (while(true)) need AbortController or timeout mechanisms to avoid blocking forever.

Minor Issues (not inlined)

  • utils/retry.ts:26 — Default backoff = 1.0 means no actual exponential backoff. Should default to 2.0.
  • sandbox/client.ts:396String(e).includes('already exists') for session detection is fragile and will break if the server message changes or is localized.
  • logger.ts:69loggerCache Map grows without bound — potential memory leak in long-running processes.
  • common/constants.ts:22-29Constants class with all empty string static properties and @deprecated tag is dead code.
  • utils/deprecated.ts — Uses console.warn instead of the project's Winston logger, and fires on every call (standard practice is warn-once-per-function).

Timandes added 7 commits March 2, 2026 18:21
- Configure Jest projects to separate unit and integration tests
- Unit tests run from src/, integration tests from tests/integration/
- Add test:unit and test:integration npm scripts
- Add sandbox lifecycle integration test (start, isAlive, stop)
- Implement uploadDir method in LinuxFileSystem following Python SDK pattern
- Add arun method to AbstractSandbox interface for command execution
- Support validation, local tar packing, upload, remote extraction, and cleanup
- Add integration tests for uploadDir functionality
…quests

- Remove manual Content-Type header that prevented axios from adding boundary
- Set Content-Type to null in post config to allow axios auto-detection
- Add unit tests for postMultipart method
__dirname is not available in ESM modules. Enable tsup shims option
to inject proper polyfill using fileURLToPath(import.meta.url).
Using single-quoted heredoc delimiter (<< 'EOF') prevented shell
variable expansion, causing $(lsb_release -cs) to be written literally
instead of being evaluated to the Ubuntu codename (e.g., 'jammy').

This fix ensures the command substitution is properly expanded when
configuring APT mirror sources.
VERSION constant was hardcoded to '1.2.1' while package.json declared
'1.2.4', causing version mismatch. Now reads version from package.json
at runtime to ensure consistency.
Timandes added 12 commits March 3, 2026 15:16
- Add RuntimeEnv module for Python/Node.js runtime management in sandbox
- Add ModelService module for model service lifecycle in sandbox
- Add Agent module for automated task orchestration
- Remove old model/service.ts (local Node.js server approach)
- Add example files for new modules
- Update README with new module documentation

This resolves the 'server directory not found' issue by using
Python SDK's model service inside sandbox via pip install.
…ing loops

- Add DEFAULT_POLL_TIMEOUT constant (60 seconds)
- Add PollOptions interface for timeout and AbortSignal support
- Update popRequest() to accept timeout and cancellation via AbortSignal
- Update waitForFirstRequest() to accept timeout and cancellation
- Add comprehensive unit tests for timeout and cancellation scenarios

Fixes issue where while(true) loops could block forever without
timeout or cancellation mechanism. Aligns with Python SDK PR alibaba#559.
…lient

The exception classes (RockException, BadRequestRockError, etc.) and
raiseForCode() were well-designed but never used. All errors were thrown
as generic new Error(...), losing error code information.

Now all Sandbox methods check response.result.code and call raiseForCode()
to throw appropriate typed exceptions based on error code ranges:
- 4xxx: BadRequestRockError
- 5xxx: InternalServerRockError
- 6xxx: CommandRockError

This matches the Python SDK's exception handling pattern.
Add runtime validation for all API responses using Zod schemas,
matching Python SDK's Pydantic validation behavior (Model(**result)).

- Import response schemas for runtime validation
- Add Schema.parse() calls in execute(), getStatus(), createSession(),
  closeSession(), runInSession(), readFile(), isAlive() methods
- Add 9 test cases verifying Zod validation catches invalid data types

This addresses the PR review feedback that Zod schemas were defined
but .parse() was never called, only used for z.infer<> type extraction.
- RunModeType/RunMode: re-export from common/constants.ts in sandbox/types.ts
- extractNohupPid: re-export from utils/http.ts in sandbox/utils.ts
- sleep: import from utils/retry.ts in model/client.ts instead of private method

Addresses code duplication feedback from PR alibaba#492 review.
…etry

Default backoff=1.0 resulted in fixed delay intervals (no exponential
backoff). Changed to backoff=2.0 so delays double on each retry,
which is the standard exponential backoff behavior.

Addresses PR alibaba#492 review feedback.
Add comprehensive input validation and shell escaping to prevent
command injection attacks in network, file_system, and runtime_env
modules.

- Add shell.ts utility module with safe escaping functions
- Refactor network.ts to use script-based execution with validation
- Add path/username validation in file_system.ts for chown/chmod
- Add extensive test coverage for injection protection scenarios

Inspired by Python SDK shlex.quote() approach.
Replace String(e).includes('already exists') pattern with Python SDK
behavior:
- NORMAL mode: run command directly without pre-creating session
- NOHUP mode: only create session when session parameter is not provided

This eliminates dependency on server error message format, making the
SDK more robust against server-side message changes or localization.

Add unit tests for session creation behavior and update integration
tests to explicitly create sessions when needed.
Replace manual Map-based loggerCache with winston.Container to prevent
potential memory leaks in long-running processes. Add clearLoggerCache()
and getLoggerCacheSize() functions for cache lifecycle management.
The Constants class was deprecated with all empty string values for
BASE_URL_* properties and was never used anywhere in the codebase.
Tests now verify that Constants is not exported from the module.
- Replace console.warn with Winston logger for consistency
- Implement warn-once pattern using Set to track warned keys
- Each deprecated function/class only warns once per session
- Add clearDeprecatedWarnings() for testing isolation
- Add comprehensive test suite (11 tests)
Timandes added 10 commits March 5, 2026 14:47
Replace hardcoded default values in sandbox config with environment
variables, allowing users to customize defaults without code changes.

New environment variables:
- ROCK_DEFAULT_IMAGE, ROCK_DEFAULT_MEMORY, ROCK_DEFAULT_CPUS
- ROCK_DEFAULT_CLUSTER, ROCK_DEFAULT_AUTO_CLEAR_SECONDS
- ROCK_DEFAULT_GROUP_SIZE, ROCK_DEFAULT_START_CONCURRENCY
- ROCK_DEFAULT_START_RETRY_TIMES
- ROCK_DEFAULT_ARUN_TIMEOUT, ROCK_DEFAULT_NOHUP_WAIT_TIMEOUT
- ROCK_DEFAULT_NOHUP_WAIT_INTERVAL, ROCK_DEFAULT_STATUS_CHECK_INTERVAL

This addresses PR alibaba#492 review feedback about hardcoded defaults
scattered in sandbox/client.ts and config.ts.
- Move SpeedupType to network.ts where it's used
- Update all RunMode/RunModeType imports to use common/constants.ts
- Remove unused RuntimeEnvId and AgentType from types.ts
- Delete sandbox/types.ts and types.test.ts

This addresses the PR review feedback about duplicated type definitions.
…s only

- Remove isBrowser() function that implied browser compatibility
- Simplify getEnv() and isEnvSet() to directly use process.env
- SDK fundamentally cannot run in browsers due to Node.js module imports
- Add tests to verify isBrowser is not exported
- Add static factory method RockEnv.create() for async initialization
- Call 'make' API to get sandboxId during initialization
- Replace raw AxiosInstance with HttpUtils for consistent camelCase/snake_case conversion
- Update make() factory function to be async
- Add comprehensive tests for RockEnv
… in ModelClient

- Add try/catch for JSON.parse in parseRequestLine and parseResponseLine
  to handle corrupted log files gracefully with meaningful error messages
- Replace readFileSync/appendFileSync with async readFile/appendFile
  from fs/promises to avoid blocking the event loop
- Re-throw parse errors immediately in popRequest instead of retrying
- Add tests for JSON parse error handling and async file I/O usage

Fixes PR alibaba#492 review feedback
- Add module-level sharedHttpsAgent with keepAlive enabled
- Prevents creating new https.Agent on every HTTP request
- Enables TLS session reuse and connection pooling
- Follows Python SDK pattern (_SHARED_SSL_CONTEXT)

Fixes PR alibaba#492 reviewer feedback about performance degradation under load.
Replace sync fs.existsSync and fs.readFileSync with async
fs/promises.access and fs/promises.readFile to avoid blocking
the event loop when uploading large files.
Zod .default(envVars.XXX) captured values at module load time.
If environment variables changed after module load, the schema still
used stale values. Now using factory functions .default(() => envVars.XXX)
to evaluate defaults at parse time, matching Python SDK's Field(default_factory=...) pattern.
Change the default pip index URL from China-specific mirror
(mirrors.aliyun.com) to the public PyPI mirror (pypi.org) for
better compatibility with international users of this open-source SDK.
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.

3 participants