Skip to content

feat(snapshot): add packages field for npm/bun dependencies in declarative YAML#994

Merged
jhaynie merged 6 commits intomainfrom
task/npm-dependencies-in-yaml-cli-964
Feb 21, 2026
Merged

feat(snapshot): add packages field for npm/bun dependencies in declarative YAML#994
jhaynie merged 6 commits intomainfrom
task/npm-dependencies-in-yaml-cli-964

Conversation

@jhaynie
Copy link
Copy Markdown
Member

@jhaynie jhaynie commented Feb 18, 2026

Summary

  • Adds a packages field to the snapshot YAML schema for declarative npm/bun package installation
  • Packages are validated, hashed into the content hash, displayed in output, and sent to the API
  • Enables reproducible snapshot builds that include npm/bun packages without manual shell scripts

Problem

The declarative snapshot build file (agentuity-snapshot.yaml) only supports apt packages in the dependencies field. Any snapshot that needs npm packages (e.g., opencode-ai, typescript) must be built manually via sandbox create → exec → snapshot → delete, which is not reproducible from the YAML alone.

Solution

New packages field in the YAML schema:

version: 1
runtime: agentuity:latest
name: my-snapshot

dependencies:
  - curl           # apt packages (existing)

packages:           # npm/bun packages (new)
  - opencode-ai
  - typescript

Changes

File Change
packages/server/.../snapshot-build.ts Added packages to Zod schema + validation refinement
packages/server/.../snapshot.ts Added packages to finalize API params
packages/cli/.../snapshot/build.ts Package name validation (regex), content hash, dry-run + success display, finalize call
packages/cli/.../snapshot/generate.ts Updated YAML/JSON templates with packages example

Security

Package names are validated against a strict regex that prevents shell injection (no ;, |, &, $, backticks, etc.), since package names are used in a bun install -g command at container startup.

Companion PRs

  • hadron: Generates install-packages.sh and passes to pilot via --script
  • catalyst: Needs to store and return packages in snapshot metadata (separate change)

Resolves #964

Summary by CodeRabbit

  • New Features

    • Support for specifying npm/bun packages across sandbox snapshots, templates, creation requests, and API responses.
    • Packages are shown in CLI dry-run and final summaries and returned by sandbox fetches.
  • Validation

    • Build and creation flows validate package names and surface user-friendly errors for invalid entries before build/finalization.

…ative YAML

Support npm/bun packages in the snapshot build file via a new 'packages'
field. Packages are validated against a regex to prevent shell injection,
included in the content hash for change detection, displayed in dry-run
and success output, and sent to the API in the finalize call.

Example usage in agentuity-snapshot.yaml:

  packages:
    - opencode-ai
    - typescript

Resolves #964
@agentuity-agent
Copy link
Copy Markdown

agentuity-agent Bot commented Feb 18, 2026

The latest Agentuity deployment details. Learn more about Agentuity.

Project Deployment Preview Updated (UTC)
docs 🔴 Failed - Feb 21, 2026 6:03 AM

The build failed with the following:

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 18, 2026

📝 Walkthrough

Walkthrough

Adds an optional packages field across sandbox APIs and CLI: validated by a new NPM package name pattern, included in schemas and types, propagated into content hashing and finalize payloads, surfaced in CLI templates and outputs, and re‑exported from the server sandbox API module.

Changes

Cohort / File(s) Summary
CLI: snapshot build
packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts
generateContentHash now accepts packages?: string[] and includes them in the hash; validates package names with NPM_PACKAGE_NAME_PATTERN; displays a "Packages (npm/bun)" section in dry-run and final outputs; passes packages in snapshotBuildFinalize payload.
CLI: template generation
packages/cli/src/cmd/cloud/sandbox/snapshot/generate.ts
Added example packages array to JSON template and a commented optional packages section in the YAML template.
CLI: sandbox get
packages/cli/src/cmd/cloud/sandbox/get.ts
Added optional packages: string[] to SandboxGetResponseSchema; CLI renders a Packages column and returns packages: result.packages from getSubcommand.
Server: snapshot build schema & export
packages/server/src/api/sandbox/snapshot-build.ts, packages/server/src/api/sandbox/index.ts
Introduced exported NPM_PACKAGE_NAME_PATTERN; SnapshotBuildFileBaseSchema gains optional packages: string[] validated by the pattern; schema refinement updated to require at least one of dependencies/files/env/packages; re-exported NPM_PACKAGE_NAME_PATTERN.
Server: snapshot finalize API
packages/server/src/api/sandbox/snapshot.ts
_SnapshotBuildFinalizeParamsSchema and inferred SnapshotBuildFinalizeParams include optional packages: string[] (validated by the pattern); snapshotBuildFinalize adds packages to request body when present.
Server: sandbox create/get APIs
packages/server/src/api/sandbox/create.ts, packages/server/src/api/sandbox/get.ts
SandboxCreateRequestSchema gains optional packages: string[] validated with NPM_PACKAGE_NAME_PATTERN and forwards options.packages in sandboxCreate; SandboxInfoDataSchema and sandboxGet include packages in the returned sandbox info.
Core: sandbox service types
packages/core/src/services/sandbox.ts
Added packages?: string[] to public SandboxCreateOptions and SandboxInfo interfaces to represent globally installed npm/bun packages.
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed PR implements all core requirements from #964: adds declarative packages field to snapshot YAML, validates package names, includes in content hash, displays in CLI output, and sends to API finalization.
Out of Scope Changes check ✅ Passed All changes are directly scoped to implement the packages feature across CLI, server, and core modules with consistent validation and propagation patterns.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Feb 18, 2026

📦 Canary Packages Published

version: 1.0.14-0956376

Packages
Package Version URL
@agentuity/workbench 1.0.14-0956376 https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-workbench-1.0.14-0956376.tgz
@agentuity/server 1.0.14-0956376 https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-server-1.0.14-0956376.tgz
@agentuity/postgres 1.0.14-0956376 https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-postgres-1.0.14-0956376.tgz
@agentuity/frontend 1.0.14-0956376 https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-frontend-1.0.14-0956376.tgz
@agentuity/schema 1.0.14-0956376 https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-schema-1.0.14-0956376.tgz
@agentuity/cli 1.0.14-0956376 https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-cli-1.0.14-0956376.tgz
@agentuity/runtime 1.0.14-0956376 https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-runtime-1.0.14-0956376.tgz
@agentuity/opencode 1.0.14-0956376 https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-opencode-1.0.14-0956376.tgz
@agentuity/drizzle 1.0.14-0956376 https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-drizzle-1.0.14-0956376.tgz
@agentuity/core 1.0.14-0956376 https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-core-1.0.14-0956376.tgz
@agentuity/evals 1.0.14-0956376 https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-evals-1.0.14-0956376.tgz
@agentuity/claude-code 1.0.14-0956376 https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-claude-code-1.0.14-0956376.tgz
@agentuity/auth 1.0.14-0956376 https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-auth-1.0.14-0956376.tgz
@agentuity/react 1.0.14-0956376 https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-react-1.0.14-0956376.tgz
Install

Add to your package.json:

{
  "dependencies": {
    "@agentuity/workbench": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-workbench-1.0.14-0956376.tgz",
    "@agentuity/server": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-server-1.0.14-0956376.tgz",
    "@agentuity/postgres": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-postgres-1.0.14-0956376.tgz",
    "@agentuity/frontend": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-frontend-1.0.14-0956376.tgz",
    "@agentuity/schema": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-schema-1.0.14-0956376.tgz",
    "@agentuity/cli": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-cli-1.0.14-0956376.tgz",
    "@agentuity/runtime": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-runtime-1.0.14-0956376.tgz",
    "@agentuity/opencode": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-opencode-1.0.14-0956376.tgz",
    "@agentuity/drizzle": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-drizzle-1.0.14-0956376.tgz",
    "@agentuity/core": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-core-1.0.14-0956376.tgz",
    "@agentuity/evals": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-evals-1.0.14-0956376.tgz",
    "@agentuity/claude-code": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-claude-code-1.0.14-0956376.tgz",
    "@agentuity/auth": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-auth-1.0.14-0956376.tgz",
    "@agentuity/react": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-react-1.0.14-0956376.tgz"
  }
}

Or install directly:

bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-workbench-1.0.14-0956376.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-server-1.0.14-0956376.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-postgres-1.0.14-0956376.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-frontend-1.0.14-0956376.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-schema-1.0.14-0956376.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-cli-1.0.14-0956376.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-runtime-1.0.14-0956376.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-opencode-1.0.14-0956376.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-drizzle-1.0.14-0956376.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-core-1.0.14-0956376.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-evals-1.0.14-0956376.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-claude-code-1.0.14-0956376.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-auth-1.0.14-0956376.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.14-0956376/agentuity-react-1.0.14-0956376.tgz

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts (1)

976-998: Indentation inconsistency within the if (!options.json) block.

The Dependencies, Packages (npm/bun), and Environment output sections (lines 976-998) appear to have lost a level of indentation compared to the Metadata section (lines 1000-1006) and other code within the same if (!options.json) block starting at line 956. These sections should be indented to align with the rest of the block.

♻️ Proposed fix
-		if (buildConfig.dependencies && buildConfig.dependencies.length > 0) {
-			console.log('');
-			tui.info('Dependencies:');
-			for (const dep of buildConfig.dependencies) {
-				console.log(`  ${tui.muted('•')} ${dep}`);
+			if (buildConfig.dependencies && buildConfig.dependencies.length > 0) {
+				console.log('');
+				tui.info('Dependencies:');
+				for (const dep of buildConfig.dependencies) {
+					console.log(`  ${tui.muted('•')} ${dep}`);
+				}
 			}
-		}
 
-		if (buildConfig.packages && buildConfig.packages.length > 0) {
-			console.log('');
-			tui.info('Packages (npm/bun):');
-			for (const pkg of buildConfig.packages) {
-				console.log(`  ${tui.muted('•')} ${pkg}`);
+			if (buildConfig.packages && buildConfig.packages.length > 0) {
+				console.log('');
+				tui.info('Packages (npm/bun):');
+				for (const pkg of buildConfig.packages) {
+					console.log(`  ${tui.muted('•')} ${pkg}`);
+				}
 			}
-		}
 
-		if (finalEnv && Object.keys(finalEnv).length > 0) {
-			console.log('');
-			tui.info('Environment:');
-			for (const [envKey, envValue] of Object.entries(finalEnv)) {
-				console.log(`  ${tui.muted('•')} ${envKey}=${tui.maskSecret(envValue)}`);
+			if (finalEnv && Object.keys(finalEnv).length > 0) {
+				console.log('');
+				tui.info('Environment:');
+				for (const [envKey, envValue] of Object.entries(finalEnv)) {
+					console.log(`  ${tui.muted('•')} ${envKey}=${tui.maskSecret(envValue)}`);
+				}
 			}
-		}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts` around lines 976 - 998,
The console output blocks for dependencies, packages and environment are
mis-indented inside the if (!options.json) block; move the entire blocks that
reference buildConfig (buildConfig.dependencies, buildConfig.packages) and
finalEnv (Object.entries(finalEnv), using tui.info, tui.muted, tui.maskSecret)
so they align with the surrounding Metadata output code inside the same if
(!options.json) scope—i.e., increase their indentation level to match the other
statements in that block without changing logic or conditions.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5d2f6d0 and be6c13f.

📒 Files selected for processing (4)
  • packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts
  • packages/cli/src/cmd/cloud/sandbox/snapshot/generate.ts
  • packages/server/src/api/sandbox/snapshot-build.ts
  • packages/server/src/api/sandbox/snapshot.ts
🧰 Additional context used
📓 Path-based instructions (7)
packages/cli/**/*.ts

📄 CodeRabbit inference engine (packages/cli/AGENTS.md)

Use Bun.file(f).exists() instead of existsSync(f) for file existence checks

Files:

  • packages/cli/src/cmd/cloud/sandbox/snapshot/generate.ts
  • packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts
**/*.{ts,tsx,js,jsx,json,md}

📄 CodeRabbit inference engine (AGENTS.md)

Use Prettier with tabs (width 3), single quotes, and semicolons for code formatting

Files:

  • packages/cli/src/cmd/cloud/sandbox/snapshot/generate.ts
  • packages/server/src/api/sandbox/snapshot-build.ts
  • packages/server/src/api/sandbox/snapshot.ts
  • packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript in strict mode with ESNext target and bundler moduleResolution

Files:

  • packages/cli/src/cmd/cloud/sandbox/snapshot/generate.ts
  • packages/server/src/api/sandbox/snapshot-build.ts
  • packages/server/src/api/sandbox/snapshot.ts
  • packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use StructuredError from @agentuity/core for error handling

Files:

  • packages/cli/src/cmd/cloud/sandbox/snapshot/generate.ts
  • packages/server/src/api/sandbox/snapshot-build.ts
  • packages/server/src/api/sandbox/snapshot.ts
  • packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts
packages/cli/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use commander.js framework for CLI implementation in the cli package

Files:

  • packages/cli/src/cmd/cloud/sandbox/snapshot/generate.ts
  • packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts
packages/server/src/**/*.ts

📄 CodeRabbit inference engine (packages/server/AGENTS.md)

packages/server/src/**/*.ts: All code must be written in TypeScript
Use zod for runtime validation of schemas and data

Files:

  • packages/server/src/api/sandbox/snapshot-build.ts
  • packages/server/src/api/sandbox/snapshot.ts
packages/server/src/api/**/*.ts

📄 CodeRabbit inference engine (packages/server/AGENTS.md)

Organize API clients by feature domain in src/api/ subdirectories (apikey, db, eval, org, project, queue, region, sandbox, session, thread, user)

Files:

  • packages/server/src/api/sandbox/snapshot-build.ts
  • packages/server/src/api/sandbox/snapshot.ts
🧠 Learnings (5)
📚 Learning: 2025-12-21T00:31:41.858Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 274
File: packages/cli/src/cmd/build/vite/server-bundler.ts:12-41
Timestamp: 2025-12-21T00:31:41.858Z
Learning: In Bun runtime, BuildMessage and ResolveMessage are global types and are not exported from the bun module. Do not import { BuildMessage } from 'bun' or similar; these types are available globally and should be used without import. This applies to all TypeScript files that target the Bun runtime within the repository.

Applied to files:

  • packages/cli/src/cmd/cloud/sandbox/snapshot/generate.ts
  • packages/server/src/api/sandbox/snapshot-build.ts
  • packages/server/src/api/sandbox/snapshot.ts
  • packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts
📚 Learning: 2026-01-13T04:32:02.691Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 565
File: packages/cli/src/cmd/cloud/region-lookup.ts:14-26
Timestamp: 2026-01-13T04:32:02.691Z
Learning: Enforce sandbox identifier prefixes in new code within the CLI cloud region lookup: new sandboxes must use the sbx_ prefix. The snbx_ prefix may appear in legacy code or examples, but do not use snbx_ for new sandboxes. When reviewing changes in packages/cli/src/cmd/cloud/, ensure any created sandbox identifiers use sbx_ and remove or migrate any snbx_ usages in newly added code.

Applied to files:

  • packages/cli/src/cmd/cloud/sandbox/snapshot/generate.ts
  • packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts
📚 Learning: 2026-02-17T14:23:15.448Z
Learnt from: potofpie
Repo: agentuity/sdk PR: 974
File: packages/cli/src/cmd/git/account/list.ts:39-40
Timestamp: 2026-02-17T14:23:15.448Z
Learning: In the Agentuity CLI framework (packages/cli), when a subcommand declares requires: { auth: true }, the framework will automatically call requireAuth() before invoking the handler. Do not call requireAuth(ctx) manually inside command handlers. This applies to all TypeScript command files under packages/cli/src, including paths like packages/cli/src/cmd/git/account/list.ts.

Applied to files:

  • packages/cli/src/cmd/cloud/sandbox/snapshot/generate.ts
  • packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts
📚 Learning: 2025-12-19T14:19:33.765Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 259
File: packages/cli/src/cmd/build/vite/registry-generator.ts:306-312
Timestamp: 2025-12-19T14:19:33.765Z
Learning: Route files under src/api should use the .ts extension only (no .tsx) and regex patterns for such paths should anchor to \.ts$ (e.g., /\/.ts$/). Agent files may support both .ts and .tsx, but route files in the Agentuity SDK codebase are restricted to .ts. This guideline applies to all similar route files under src/api across the repository.

Applied to files:

  • packages/server/src/api/sandbox/snapshot-build.ts
  • packages/server/src/api/sandbox/snapshot.ts
📚 Learning: 2025-12-30T00:13:37.849Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 355
File: packages/server/src/api/sandbox/util.ts:2-6
Timestamp: 2025-12-30T00:13:37.849Z
Learning: In the packages/server tree, treat code as runtime-agnostic between Node.js and Bun. Ensure TypeScript files (e.g., util.ts) import and use APIs in a way that works under both runtimes. It is acceptable to rely on Bun’s Node.js compatibility for built-ins accessed via the node: namespace (e.g., node:events, node:stream, node:buffer). During reviews, prefer patterns and imports that remain compatible with Bun's environment, and flag any hard dependencies on runtime-specific globals or non-portable Node APIs.

Applied to files:

  • packages/server/src/api/sandbox/snapshot-build.ts
  • packages/server/src/api/sandbox/snapshot.ts
🪛 GitHub Actions: Build Packages & Test
packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts

[error] 586-586: ESLint: Unnecessary escape character: - (no-useless-escape).

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: Pack & Upload
  • GitHub Check: Queue SDK Tests
  • GitHub Check: Queue CLI Tests
  • GitHub Check: Sandbox CLI Tests
  • GitHub Check: Framework Integration Tests (TanStack & Next.js)
  • GitHub Check: Playwright E2E Smoke Test
  • GitHub Check: Template Integration Tests
  • GitHub Check: Package Installation & Usage Test
  • GitHub Check: SDK Integration Test Suite
  • GitHub Check: Cloud Deployment Tests
🔇 Additional comments (4)
packages/cli/src/cmd/cloud/sandbox/snapshot/generate.ts (1)

38-42: LGTM!

The new packages field is well-documented in the YAML template with clear guidance on its purpose (global npm/bun packages installed via bun install -g). The JSON template includes a practical example. Both are consistent with the broader PR changes.

Also applies to: 77-77

packages/server/src/api/sandbox/snapshot.ts (1)

597-597: LGTM!

The packages field is correctly added to the finalize params schema with appropriate Zod typing. The destructuring and conditional body assignment follow the established pattern used for dependencies, env, and metadata.

Also applies to: 675-676, 686-686

packages/server/src/api/sandbox/snapshot-build.ts (1)

25-30: LGTM!

The packages field is correctly integrated into both the base schema and the validation refinement. The "at least one of" validation now properly includes packages as a valid option alongside dependencies, files, and env.

Also applies to: 58-58, 65-66, 69-69

packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts (1)

300-300: LGTM on packages integration throughout the build flow.

The implementation correctly:

  • Adds packages to the content hash for reproducibility (with deterministic sorting)
  • Validates package names using a regex to prevent shell injection (security requirement per PR objectives)
  • Propagates packages through dry-run output, finalization, and final success output
  • Follows the same patterns established for dependencies

Also applies to: 319-322, 584-598, 638-638, 673-679, 948-948

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts`:
- Around line 586-587: The packageNameRegex contains an unnecessary escape for
the hyphen in the character class, triggering ESLint no-useless-escape; update
the regex definition (packageNameRegex) to remove the backslash before the
hyphen (or place the hyphen at the end of the class) so the character class
becomes valid without the useless escape and re-run lint/tests.

---

Nitpick comments:
In `@packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts`:
- Around line 976-998: The console output blocks for dependencies, packages and
environment are mis-indented inside the if (!options.json) block; move the
entire blocks that reference buildConfig (buildConfig.dependencies,
buildConfig.packages) and finalEnv (Object.entries(finalEnv), using tui.info,
tui.muted, tui.maskSecret) so they align with the surrounding Metadata output
code inside the same if (!options.json) scope—i.e., increase their indentation
level to match the other statements in that block without changing logic or
conditions.

Comment thread packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts Outdated
…faces

Add npm/bun packages support to the sandbox CRUD APIs, mirroring the
existing dependencies field:
- core: SandboxCreateOptions and SandboxInfo interfaces
- server: SandboxCreateRequestSchema, sandboxCreate function, SandboxInfoDataSchema, sandboxGet return
- cli: SandboxGetResponseSchema
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/cli/src/cmd/cloud/sandbox/get.ts (1)

139-171: ⚠️ Potential issue | 🟡 Minor

Surface packages in CLI output and JSON return.

Right now the CLI parses packages but never shows/returns them, so the new field is effectively hidden from users.

✅ Proposed fix
 			if (result.dependencies && result.dependencies.length > 0) {
 				tableData['Dependencies'] = result.dependencies.join(', ');
 			}
+			if (result.packages && result.packages.length > 0) {
+				tableData['Packages'] = result.packages.join(', ');
+			}
 			if (resourceParts.length > 0) {
 				tableData['Resources'] = resourceParts.join(', ');
 			}
@@
 			stderrStreamUrl: result.stderrStreamUrl,
 			dependencies: result.dependencies,
+			packages: result.packages,
 			metadata: result.metadata,
 			resources: result.resources,
 			url: result.url,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cli/src/cmd/cloud/sandbox/get.ts` around lines 139 - 171, The CLI
builds tableData from result but never includes result.packages nor returns
packages in the JSON response; update the display and return to surface packages
by adding a tableData['Packages'] entry when result.packages exists (e.g.,
tableData['Packages'] = result.packages.join(', ')) and include packages:
result.packages in the final returned object alongside the other fields
(sandboxId, name, description, etc.) so both the tui.table output and the
function's JSON return expose the packages field.
packages/server/src/api/sandbox/create.ts (1)

85-92: ⚠️ Potential issue | 🔴 Critical

Add server-side package-name validation to block injection attacks.

The API currently accepts arbitrary strings for npm/bun packages and forwards them to bun install -g. While dependencies (apt) are validated in the CLI, the packages field lacks validation entirely, creating a security gap. Client-side validation can be bypassed.

Suggested schema hardening
+const PackageNameSchema = z
+	.string()
+	.regex(/^[a-z0-9@][a-z0-9@/._-]*$/i, 'Invalid package name');
+
 export const SandboxCreateRequestSchema = z
 	.object({
 		dependencies: z
 			.array(z.string())
 			.optional()
 			.describe('Apt packages to install when creating the sandbox'),
-		packages: z
-			.array(z.string())
+		packages: z
+			.array(PackageNameSchema)
 			.optional()
 			.describe('npm/bun packages to install globally when creating the sandbox'),

Apply the same validation to SnapshotBuildFileBaseSchema in packages/server/src/api/sandbox/snapshot-build.ts (lines 25-30).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/server/src/api/sandbox/create.ts` around lines 85 - 92, The packages
array currently accepts arbitrary strings; add server-side package-name
validation by replacing the freeform z.array(z.string()) for the "packages"
field in create.ts with the same package-name validator used elsewhere (e.g., a
PackageNameSchema or similar validator) so only safe npm/bun package names are
allowed, and apply the identical change to SnapshotBuildFileBaseSchema in
snapshot-build.ts (the packages field in that schema) so both endpoints enforce
the same validated package-name format and block injection vectors.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between be6c13f and dffedb1.

📒 Files selected for processing (4)
  • packages/cli/src/cmd/cloud/sandbox/get.ts
  • packages/core/src/services/sandbox.ts
  • packages/server/src/api/sandbox/create.ts
  • packages/server/src/api/sandbox/get.ts
🧰 Additional context used
📓 Path-based instructions (9)
packages/cli/**/*.ts

📄 CodeRabbit inference engine (packages/cli/AGENTS.md)

Use Bun.file(f).exists() instead of existsSync(f) for file existence checks

Files:

  • packages/cli/src/cmd/cloud/sandbox/get.ts
**/*.{ts,tsx,js,jsx,json,md}

📄 CodeRabbit inference engine (AGENTS.md)

Use Prettier with tabs (width 3), single quotes, and semicolons for code formatting

Files:

  • packages/cli/src/cmd/cloud/sandbox/get.ts
  • packages/core/src/services/sandbox.ts
  • packages/server/src/api/sandbox/create.ts
  • packages/server/src/api/sandbox/get.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript in strict mode with ESNext target and bundler moduleResolution

Files:

  • packages/cli/src/cmd/cloud/sandbox/get.ts
  • packages/core/src/services/sandbox.ts
  • packages/server/src/api/sandbox/create.ts
  • packages/server/src/api/sandbox/get.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use StructuredError from @agentuity/core for error handling

Files:

  • packages/cli/src/cmd/cloud/sandbox/get.ts
  • packages/core/src/services/sandbox.ts
  • packages/server/src/api/sandbox/create.ts
  • packages/server/src/api/sandbox/get.ts
packages/cli/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use commander.js framework for CLI implementation in the cli package

Files:

  • packages/cli/src/cmd/cloud/sandbox/get.ts
packages/core/src/**/*.ts

📄 CodeRabbit inference engine (packages/core/AGENTS.md)

packages/core/src/**/*.ts: Use TypeScript for all code in the @agentuity/core package
Prefer interfaces for public API definitions in @agentuity/core
Use generic types for reusable type utilities in @agentuity/core
Ensure no side effects in exports - all exports must be pure functions or types with no global mutations
Ensure code is compatible with both Browser and Node/Bun runtime environments

Files:

  • packages/core/src/services/sandbox.ts
packages/core/src/services/*.ts

📄 CodeRabbit inference engine (packages/core/AGENTS.md)

Use FetchAdapter abstraction for HTTP service implementations

Files:

  • packages/core/src/services/sandbox.ts
packages/server/src/**/*.ts

📄 CodeRabbit inference engine (packages/server/AGENTS.md)

packages/server/src/**/*.ts: All code must be written in TypeScript
Use zod for runtime validation of schemas and data

Files:

  • packages/server/src/api/sandbox/create.ts
  • packages/server/src/api/sandbox/get.ts
packages/server/src/api/**/*.ts

📄 CodeRabbit inference engine (packages/server/AGENTS.md)

Organize API clients by feature domain in src/api/ subdirectories (apikey, db, eval, org, project, queue, region, sandbox, session, thread, user)

Files:

  • packages/server/src/api/sandbox/create.ts
  • packages/server/src/api/sandbox/get.ts
🧠 Learnings (5)
📚 Learning: 2025-12-21T00:31:41.858Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 274
File: packages/cli/src/cmd/build/vite/server-bundler.ts:12-41
Timestamp: 2025-12-21T00:31:41.858Z
Learning: In Bun runtime, BuildMessage and ResolveMessage are global types and are not exported from the bun module. Do not import { BuildMessage } from 'bun' or similar; these types are available globally and should be used without import. This applies to all TypeScript files that target the Bun runtime within the repository.

Applied to files:

  • packages/cli/src/cmd/cloud/sandbox/get.ts
  • packages/core/src/services/sandbox.ts
  • packages/server/src/api/sandbox/create.ts
  • packages/server/src/api/sandbox/get.ts
📚 Learning: 2026-01-13T04:32:02.691Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 565
File: packages/cli/src/cmd/cloud/region-lookup.ts:14-26
Timestamp: 2026-01-13T04:32:02.691Z
Learning: Enforce sandbox identifier prefixes in new code within the CLI cloud region lookup: new sandboxes must use the sbx_ prefix. The snbx_ prefix may appear in legacy code or examples, but do not use snbx_ for new sandboxes. When reviewing changes in packages/cli/src/cmd/cloud/, ensure any created sandbox identifiers use sbx_ and remove or migrate any snbx_ usages in newly added code.

Applied to files:

  • packages/cli/src/cmd/cloud/sandbox/get.ts
📚 Learning: 2026-02-17T14:23:15.448Z
Learnt from: potofpie
Repo: agentuity/sdk PR: 974
File: packages/cli/src/cmd/git/account/list.ts:39-40
Timestamp: 2026-02-17T14:23:15.448Z
Learning: In the Agentuity CLI framework (packages/cli), when a subcommand declares requires: { auth: true }, the framework will automatically call requireAuth() before invoking the handler. Do not call requireAuth(ctx) manually inside command handlers. This applies to all TypeScript command files under packages/cli/src, including paths like packages/cli/src/cmd/git/account/list.ts.

Applied to files:

  • packages/cli/src/cmd/cloud/sandbox/get.ts
📚 Learning: 2025-12-19T14:19:33.765Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 259
File: packages/cli/src/cmd/build/vite/registry-generator.ts:306-312
Timestamp: 2025-12-19T14:19:33.765Z
Learning: Route files under src/api should use the .ts extension only (no .tsx) and regex patterns for such paths should anchor to \.ts$ (e.g., /\/.ts$/). Agent files may support both .ts and .tsx, but route files in the Agentuity SDK codebase are restricted to .ts. This guideline applies to all similar route files under src/api across the repository.

Applied to files:

  • packages/server/src/api/sandbox/create.ts
  • packages/server/src/api/sandbox/get.ts
📚 Learning: 2025-12-30T00:13:37.849Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 355
File: packages/server/src/api/sandbox/util.ts:2-6
Timestamp: 2025-12-30T00:13:37.849Z
Learning: In the packages/server tree, treat code as runtime-agnostic between Node.js and Bun. Ensure TypeScript files (e.g., util.ts) import and use APIs in a way that works under both runtimes. It is acceptable to rely on Bun’s Node.js compatibility for built-ins accessed via the node: namespace (e.g., node:events, node:stream, node:buffer). During reviews, prefer patterns and imports that remain compatible with Bun's environment, and flag any hard dependencies on runtime-specific globals or non-portable Node APIs.

Applied to files:

  • packages/server/src/api/sandbox/create.ts
  • packages/server/src/api/sandbox/get.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Framework Integration Tests (TanStack & Next.js)
  • GitHub Check: Package Installation & Usage Test
  • GitHub Check: Playwright E2E Smoke Test
  • GitHub Check: SDK Integration Test Suite
  • GitHub Check: Sandbox CLI Tests
  • GitHub Check: Cloud Deployment Tests
🔇 Additional comments (2)
packages/core/src/services/sandbox.ts (1)

463-467: Packages fields look good in core sandbox types.

Clear docs and optionality mirror the existing dependencies surface cleanly.

Also applies to: 711-714

packages/server/src/api/sandbox/get.ts (1)

122-129: Packages field is wired through schema and response mapping.

Nice and consistent with other sandbox metadata.

Also applies to: 215-216

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@packages/cli/src/cmd/cloud/sandbox/get.ts`:
- Around line 139-171: The CLI builds tableData from result but never includes
result.packages nor returns packages in the JSON response; update the display
and return to surface packages by adding a tableData['Packages'] entry when
result.packages exists (e.g., tableData['Packages'] = result.packages.join(',
')) and include packages: result.packages in the final returned object alongside
the other fields (sandboxId, name, description, etc.) so both the tui.table
output and the function's JSON return expose the packages field.

In `@packages/server/src/api/sandbox/create.ts`:
- Around line 85-92: The packages array currently accepts arbitrary strings; add
server-side package-name validation by replacing the freeform
z.array(z.string()) for the "packages" field in create.ts with the same
package-name validator used elsewhere (e.g., a PackageNameSchema or similar
validator) so only safe npm/bun package names are allowed, and apply the
identical change to SnapshotBuildFileBaseSchema in snapshot-build.ts (the
packages field in that schema) so both endpoints enforce the same validated
package-name format and block injection vectors.

…e validation

- Add packages field to sandbox get table display and JSON return
- Extract shared NPM_PACKAGE_NAME_PATTERN regex to snapshot-build.ts
- Apply package name validation to create.ts and snapshot-build.ts schemas
- Update CLI build command to use shared pattern instead of local regex
- Fix pre-existing indentation issues (prettier)
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/server/src/api/sandbox/snapshot.ts (1)

597-600: Consider adding regex validation for defense-in-depth.

The packages field here accepts any strings, while SnapshotBuildFileBaseSchema in snapshot-build.ts validates each package name against NPM_PACKAGE_NAME_PATTERN. For defense-in-depth (since these package names are used in shell commands), consider applying the same validation here.

♻️ Proposed refactor
+import { NPM_PACKAGE_NAME_PATTERN } from './snapshot-build';
+
 // In _SnapshotBuildFinalizeParamsSchema:
-		packages: z
-			.array(z.string())
-			.optional()
-			.describe('List of npm/bun packages to install globally'),
+		packages: z
+			.array(
+				z.string().regex(
+					NPM_PACKAGE_NAME_PATTERN,
+					'Invalid npm/bun package name'
+				)
+			)
+			.optional()
+			.describe('List of npm/bun packages to install globally'),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/server/src/api/sandbox/snapshot.ts` around lines 597 - 600, The
packages array schema currently allows any strings; update the packages field in
snapshot.ts to validate each item against the same NPM_PACKAGE_NAME_PATTERN used
in SnapshotBuildFileBaseSchema (import NPM_PACKAGE_NAME_PATTERN from
snapshot-build.ts) so entries become
z.array(z.string().regex(NPM_PACKAGE_NAME_PATTERN)).optional().describe(...),
keeping optional/describe semantics to ensure defense-in-depth for values later
interpolated into shell commands.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dffedb1 and 7233848.

📒 Files selected for processing (6)
  • packages/cli/src/cmd/cloud/sandbox/get.ts
  • packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts
  • packages/server/src/api/sandbox/create.ts
  • packages/server/src/api/sandbox/index.ts
  • packages/server/src/api/sandbox/snapshot-build.ts
  • packages/server/src/api/sandbox/snapshot.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/server/src/api/sandbox/create.ts
🧰 Additional context used
📓 Path-based instructions (8)
packages/cli/**/*.ts

📄 CodeRabbit inference engine (packages/cli/AGENTS.md)

Use Bun.file(f).exists() instead of existsSync(f) for file existence checks

Files:

  • packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts
  • packages/cli/src/cmd/cloud/sandbox/get.ts
**/*.{ts,tsx,js,jsx,json,md}

📄 CodeRabbit inference engine (AGENTS.md)

Use Prettier with tabs (width 3), single quotes, and semicolons for code formatting

Files:

  • packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts
  • packages/server/src/api/sandbox/snapshot-build.ts
  • packages/server/src/api/sandbox/snapshot.ts
  • packages/cli/src/cmd/cloud/sandbox/get.ts
  • packages/server/src/api/sandbox/index.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript in strict mode with ESNext target and bundler moduleResolution

Files:

  • packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts
  • packages/server/src/api/sandbox/snapshot-build.ts
  • packages/server/src/api/sandbox/snapshot.ts
  • packages/cli/src/cmd/cloud/sandbox/get.ts
  • packages/server/src/api/sandbox/index.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use StructuredError from @agentuity/core for error handling

Files:

  • packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts
  • packages/server/src/api/sandbox/snapshot-build.ts
  • packages/server/src/api/sandbox/snapshot.ts
  • packages/cli/src/cmd/cloud/sandbox/get.ts
  • packages/server/src/api/sandbox/index.ts
packages/cli/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use commander.js framework for CLI implementation in the cli package

Files:

  • packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts
  • packages/cli/src/cmd/cloud/sandbox/get.ts
packages/server/src/**/*.ts

📄 CodeRabbit inference engine (packages/server/AGENTS.md)

packages/server/src/**/*.ts: All code must be written in TypeScript
Use zod for runtime validation of schemas and data

Files:

  • packages/server/src/api/sandbox/snapshot-build.ts
  • packages/server/src/api/sandbox/snapshot.ts
  • packages/server/src/api/sandbox/index.ts
packages/server/src/api/**/*.ts

📄 CodeRabbit inference engine (packages/server/AGENTS.md)

Organize API clients by feature domain in src/api/ subdirectories (apikey, db, eval, org, project, queue, region, sandbox, session, thread, user)

Files:

  • packages/server/src/api/sandbox/snapshot-build.ts
  • packages/server/src/api/sandbox/snapshot.ts
  • packages/server/src/api/sandbox/index.ts
**/index.ts

📄 CodeRabbit inference engine (AGENTS.md)

Use named exports from package index.ts files

Files:

  • packages/server/src/api/sandbox/index.ts
🧠 Learnings (5)
📚 Learning: 2025-12-21T00:31:41.858Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 274
File: packages/cli/src/cmd/build/vite/server-bundler.ts:12-41
Timestamp: 2025-12-21T00:31:41.858Z
Learning: In Bun runtime, BuildMessage and ResolveMessage are global types and are not exported from the bun module. Do not import { BuildMessage } from 'bun' or similar; these types are available globally and should be used without import. This applies to all TypeScript files that target the Bun runtime within the repository.

Applied to files:

  • packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts
  • packages/server/src/api/sandbox/snapshot-build.ts
  • packages/server/src/api/sandbox/snapshot.ts
  • packages/cli/src/cmd/cloud/sandbox/get.ts
  • packages/server/src/api/sandbox/index.ts
📚 Learning: 2026-01-13T04:32:02.691Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 565
File: packages/cli/src/cmd/cloud/region-lookup.ts:14-26
Timestamp: 2026-01-13T04:32:02.691Z
Learning: Enforce sandbox identifier prefixes in new code within the CLI cloud region lookup: new sandboxes must use the sbx_ prefix. The snbx_ prefix may appear in legacy code or examples, but do not use snbx_ for new sandboxes. When reviewing changes in packages/cli/src/cmd/cloud/, ensure any created sandbox identifiers use sbx_ and remove or migrate any snbx_ usages in newly added code.

Applied to files:

  • packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts
  • packages/cli/src/cmd/cloud/sandbox/get.ts
📚 Learning: 2026-02-17T14:23:15.448Z
Learnt from: potofpie
Repo: agentuity/sdk PR: 974
File: packages/cli/src/cmd/git/account/list.ts:39-40
Timestamp: 2026-02-17T14:23:15.448Z
Learning: In the Agentuity CLI framework (packages/cli), when a subcommand declares requires: { auth: true }, the framework will automatically call requireAuth() before invoking the handler. Do not call requireAuth(ctx) manually inside command handlers. This applies to all TypeScript command files under packages/cli/src, including paths like packages/cli/src/cmd/git/account/list.ts.

Applied to files:

  • packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts
  • packages/cli/src/cmd/cloud/sandbox/get.ts
📚 Learning: 2025-12-19T14:19:33.765Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 259
File: packages/cli/src/cmd/build/vite/registry-generator.ts:306-312
Timestamp: 2025-12-19T14:19:33.765Z
Learning: Route files under src/api should use the .ts extension only (no .tsx) and regex patterns for such paths should anchor to \.ts$ (e.g., /\/.ts$/). Agent files may support both .ts and .tsx, but route files in the Agentuity SDK codebase are restricted to .ts. This guideline applies to all similar route files under src/api across the repository.

Applied to files:

  • packages/server/src/api/sandbox/snapshot-build.ts
  • packages/server/src/api/sandbox/snapshot.ts
  • packages/server/src/api/sandbox/index.ts
📚 Learning: 2025-12-30T00:13:37.849Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 355
File: packages/server/src/api/sandbox/util.ts:2-6
Timestamp: 2025-12-30T00:13:37.849Z
Learning: In the packages/server tree, treat code as runtime-agnostic between Node.js and Bun. Ensure TypeScript files (e.g., util.ts) import and use APIs in a way that works under both runtimes. It is acceptable to rely on Bun’s Node.js compatibility for built-ins accessed via the node: namespace (e.g., node:events, node:stream, node:buffer). During reviews, prefer patterns and imports that remain compatible with Bun's environment, and flag any hard dependencies on runtime-specific globals or non-portable Node APIs.

Applied to files:

  • packages/server/src/api/sandbox/snapshot-build.ts
  • packages/server/src/api/sandbox/snapshot.ts
  • packages/server/src/api/sandbox/index.ts
🧬 Code graph analysis (2)
packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts (1)
packages/server/src/api/sandbox/snapshot-build.ts (1)
  • NPM_PACKAGE_NAME_PATTERN (10-11)
packages/server/src/api/sandbox/snapshot-build.ts (1)
packages/server/src/api/sandbox/index.ts (2)
  • NPM_PACKAGE_NAME_PATTERN (174-174)
  • SnapshotBuildFileSchema (174-174)
🪛 GitHub Actions: Build Packages & Test
packages/server/src/api/sandbox/snapshot-build.ts

[error] 11-11: ESLint: Unnecessary escape character: - no-useless-escape

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Queue CLI Tests
  • GitHub Check: Framework Integration Tests (TanStack & Next.js)
  • GitHub Check: Package Installation & Usage Test
  • GitHub Check: Sandbox CLI Tests
  • GitHub Check: SDK Integration Test Suite
  • GitHub Check: Playwright E2E Smoke Test
  • GitHub Check: Cloud Deployment Tests
🔇 Additional comments (12)
packages/cli/src/cmd/cloud/sandbox/get.ts (3)

43-43: LGTM: packages surfaced in the response schema.


142-144: LGTM: packages included in human-readable output.


171-171: LGTM: packages included in handler return value.

packages/server/src/api/sandbox/snapshot-build.ts (2)

35-47: LGTM!

The packages field is well-defined with proper regex validation at the schema level, clear error messaging about the security rationale, and appropriate documentation.


77-88: LGTM!

The refinement logic correctly includes hasPackages in the validation check and the error message is updated accordingly.

packages/server/src/api/sandbox/snapshot.ts (1)

678-689: LGTM!

The destructuring and conditional body inclusion follow the established pattern used for dependencies.

packages/server/src/api/sandbox/index.ts (1)

174-174: LGTM!

The NPM_PACKAGE_NAME_PATTERN is correctly exported alongside SnapshotBuildFileSchema, making it available for validation in the CLI and other consumers.

packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts (5)

15-16: LGTM!

Importing NPM_PACKAGE_NAME_PATTERN from @agentuity/server ensures consistent validation across server and CLI.


320-323: LGTM!

The content hash correctly incorporates sorted packages, ensuring reproducible hashes and proper change detection.


585-597: LGTM!

This CLI-level validation provides good UX with specific error messages before the build proceeds, complementing the schema-level validation.


672-678: LGTM!

The "Packages (npm/bun)" output sections in both dry-run and success paths follow the established pattern used for "Dependencies" output.

Also applies to: 983-989


947-947: LGTM!

The packages field is correctly passed to snapshotBuildFinalize alongside other configuration.

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/server/src/api/sandbox/snapshot-build.ts`:
- Around line 10-11: The exported constant NPM_PACKAGE_NAME_PATTERN contains an
unnecessary escaped hyphen inside the character class which triggers the
no-useless-escape ESLint rule; update the regex in NPM_PACKAGE_NAME_PATTERN by
removing the backslash before the hyphen in the character class (or place the
hyphen at the end of the class without escaping) so the pattern remains the same
but no longer uses a useless escape.

---

Nitpick comments:
In `@packages/server/src/api/sandbox/snapshot.ts`:
- Around line 597-600: The packages array schema currently allows any strings;
update the packages field in snapshot.ts to validate each item against the same
NPM_PACKAGE_NAME_PATTERN used in SnapshotBuildFileBaseSchema (import
NPM_PACKAGE_NAME_PATTERN from snapshot-build.ts) so entries become
z.array(z.string().regex(NPM_PACKAGE_NAME_PATTERN)).optional().describe(...),
keeping optional/describe semantics to ensure defense-in-depth for values later
interpolated into shell commands.

Comment thread packages/server/src/api/sandbox/snapshot-build.ts Outdated
…e validation

- Add packages field to sandbox get table display and JSON return
- Extract shared NPM_PACKAGE_NAME_PATTERN regex to snapshot-build.ts
- Use permissive blocklist (reject shell injection chars) not strict allowlist,
  matching ion/catalyst which accepts URLs, git refs, GitHub shorthand, etc.
- Apply validation to create.ts and snapshot-build.ts schemas
- Update CLI build command to use shared pattern instead of local regex
- Fix pre-existing indentation issues (prettier)
…es-in-yaml-cli-964' into task/npm-dependencies-in-yaml-cli-964

# Conflicts:
#	packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts
#	packages/server/src/api/sandbox/create.ts
#	packages/server/src/api/sandbox/snapshot-build.ts
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7233848 and 0956376.

📒 Files selected for processing (4)
  • packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts
  • packages/server/src/api/sandbox/create.ts
  • packages/server/src/api/sandbox/snapshot-build.ts
  • packages/server/src/api/sandbox/snapshot.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/server/src/api/sandbox/snapshot.ts
🧰 Additional context used
📓 Path-based instructions (7)
packages/server/src/**/*.ts

📄 CodeRabbit inference engine (packages/server/AGENTS.md)

packages/server/src/**/*.ts: All code must be written in TypeScript
Use zod for runtime validation of schemas and data

Files:

  • packages/server/src/api/sandbox/snapshot-build.ts
  • packages/server/src/api/sandbox/create.ts
packages/server/src/api/**/*.ts

📄 CodeRabbit inference engine (packages/server/AGENTS.md)

Organize API clients by feature domain in src/api/ subdirectories (apikey, db, eval, org, project, queue, region, sandbox, session, thread, user)

Files:

  • packages/server/src/api/sandbox/snapshot-build.ts
  • packages/server/src/api/sandbox/create.ts
**/*.{ts,tsx,js,jsx,json,md}

📄 CodeRabbit inference engine (AGENTS.md)

Use Prettier with tabs (width 3), single quotes, and semicolons for code formatting

Files:

  • packages/server/src/api/sandbox/snapshot-build.ts
  • packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts
  • packages/server/src/api/sandbox/create.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript in strict mode with ESNext target and bundler moduleResolution

Files:

  • packages/server/src/api/sandbox/snapshot-build.ts
  • packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts
  • packages/server/src/api/sandbox/create.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use StructuredError from @agentuity/core for error handling

Files:

  • packages/server/src/api/sandbox/snapshot-build.ts
  • packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts
  • packages/server/src/api/sandbox/create.ts
packages/cli/**/*.ts

📄 CodeRabbit inference engine (packages/cli/AGENTS.md)

Use Bun.file(f).exists() instead of existsSync(f) for file existence checks

Files:

  • packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts
packages/cli/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use commander.js framework for CLI implementation in the cli package

Files:

  • packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts
🧠 Learnings (5)
📚 Learning: 2025-12-19T14:19:33.765Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 259
File: packages/cli/src/cmd/build/vite/registry-generator.ts:306-312
Timestamp: 2025-12-19T14:19:33.765Z
Learning: Route files under src/api should use the .ts extension only (no .tsx) and regex patterns for such paths should anchor to \.ts$ (e.g., /\/.ts$/). Agent files may support both .ts and .tsx, but route files in the Agentuity SDK codebase are restricted to .ts. This guideline applies to all similar route files under src/api across the repository.

Applied to files:

  • packages/server/src/api/sandbox/snapshot-build.ts
  • packages/server/src/api/sandbox/create.ts
📚 Learning: 2025-12-21T00:31:41.858Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 274
File: packages/cli/src/cmd/build/vite/server-bundler.ts:12-41
Timestamp: 2025-12-21T00:31:41.858Z
Learning: In Bun runtime, BuildMessage and ResolveMessage are global types and are not exported from the bun module. Do not import { BuildMessage } from 'bun' or similar; these types are available globally and should be used without import. This applies to all TypeScript files that target the Bun runtime within the repository.

Applied to files:

  • packages/server/src/api/sandbox/snapshot-build.ts
  • packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts
  • packages/server/src/api/sandbox/create.ts
📚 Learning: 2025-12-30T00:13:37.849Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 355
File: packages/server/src/api/sandbox/util.ts:2-6
Timestamp: 2025-12-30T00:13:37.849Z
Learning: In the packages/server tree, treat code as runtime-agnostic between Node.js and Bun. Ensure TypeScript files (e.g., util.ts) import and use APIs in a way that works under both runtimes. It is acceptable to rely on Bun’s Node.js compatibility for built-ins accessed via the node: namespace (e.g., node:events, node:stream, node:buffer). During reviews, prefer patterns and imports that remain compatible with Bun's environment, and flag any hard dependencies on runtime-specific globals or non-portable Node APIs.

Applied to files:

  • packages/server/src/api/sandbox/snapshot-build.ts
  • packages/server/src/api/sandbox/create.ts
📚 Learning: 2026-01-13T04:32:02.691Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 565
File: packages/cli/src/cmd/cloud/region-lookup.ts:14-26
Timestamp: 2026-01-13T04:32:02.691Z
Learning: Enforce sandbox identifier prefixes in new code within the CLI cloud region lookup: new sandboxes must use the sbx_ prefix. The snbx_ prefix may appear in legacy code or examples, but do not use snbx_ for new sandboxes. When reviewing changes in packages/cli/src/cmd/cloud/, ensure any created sandbox identifiers use sbx_ and remove or migrate any snbx_ usages in newly added code.

Applied to files:

  • packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts
📚 Learning: 2026-02-17T14:23:15.448Z
Learnt from: potofpie
Repo: agentuity/sdk PR: 974
File: packages/cli/src/cmd/git/account/list.ts:39-40
Timestamp: 2026-02-17T14:23:15.448Z
Learning: In the Agentuity CLI framework (packages/cli), when a subcommand declares requires: { auth: true }, the framework will automatically call requireAuth() before invoking the handler. Do not call requireAuth(ctx) manually inside command handlers. This applies to all TypeScript command files under packages/cli/src, including paths like packages/cli/src/cmd/git/account/list.ts.

Applied to files:

  • packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts
🧬 Code graph analysis (1)
packages/server/src/api/sandbox/create.ts (1)
packages/server/src/api/sandbox/snapshot-build.ts (1)
  • NPM_PACKAGE_NAME_PATTERN (13-13)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Sandbox CLI Tests
  • GitHub Check: Framework Integration Tests (TanStack & Next.js)
  • GitHub Check: Playwright E2E Smoke Test
  • GitHub Check: SDK Integration Test Suite
  • GitHub Check: Cloud Deployment Tests
  • GitHub Check: Pack & Upload
  • GitHub Check: Build
🔇 Additional comments (8)
packages/server/src/api/sandbox/snapshot-build.ts (2)

37-49: LGTM: packages added to the build-file schema with validation and description.


77-88: LGTM: refinement correctly treats packages as a valid non-empty field.

packages/server/src/api/sandbox/create.ts (2)

4-4: LGTM: shared regex is reused for packages validation in the create schema.

Also applies to: 90-100


217-219: LGTM: packages are propagated into the request body only when non-empty.

packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts (4)

15-15: LGTM: shared package regex imported for CLI validation consistency.


297-323: LGTM: packages are included in the content hash for reproducible builds.

Also applies to: 635-640


674-680: Nice touch listing npm/bun packages in both dry-run and final outputs.

Also applies to: 985-991


939-949: LGTM: packages included in the finalize payload.

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts`:
- Around line 585-599: Replace the current direct CLI exit flow in the package
validation block (the buildConfig.packages check that uses
NPM_PACKAGE_NAME_PATTERN, tui.error, tui.bullet, and process.exit(1)) with a
thrown StructuredError from `@agentuity/core`: import StructuredError, construct
an error that includes a clear message like "Invalid package specifiers" and
include the invalidPackages (from the invalidPackages array) as either a single
joined string or as structured details on the StructuredError, then throw it
instead of calling tui/error and process.exit so the existing CLI error handling
can surface the message.

In `@packages/server/src/api/sandbox/snapshot-build.ts`:
- Around line 3-13: The NPM_PACKAGE_NAME_PATTERN currently allows &, <, and >
which can enable shell injection when interpolated into bun install -g; update
the pattern used by NPM_PACKAGE_NAME_PATTERN to explicitly forbid additional
shell metacharacters (at least &, <, > and any other shell operators you deem
risky) or switch to a whitelist approach for allowed characters; locate and
modify the exported constant NPM_PACKAGE_NAME_PATTERN in snapshot-build.ts to
implement the tightened regex (or replace runtime interpolation with proper
quoting/escaping before executing bun).

Comment on lines +585 to +599
if (buildConfig.packages && buildConfig.packages.length > 0) {
// Validate package specifiers using shared pattern (also enforced at schema level)
const invalidPackages = buildConfig.packages.filter(
(pkg) => !NPM_PACKAGE_NAME_PATTERN.test(pkg)
);
if (invalidPackages.length > 0) {
tui.error('Invalid package specifiers:');
for (const pkg of invalidPackages) {
tui.bullet(
`${pkg}: must not contain whitespace, semicolons, backticks, pipes, or dollar signs`
);
}
process.exit(1);
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, check if the file exists and get context around the mentioned lines
head -n 610 packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts | tail -n 30

Repository: agentuity/sdk

Length of output: 1071


🏁 Script executed:

# Search for StructuredError usage in CLI commands
rg "StructuredError" packages/cli/src --type ts --type tsx -B 2 -A 5

Repository: agentuity/sdk

Length of output: 84


🏁 Script executed:

# Check if StructuredError is already imported in the build.ts file
rg "import.*StructuredError|from.*@agentuity/core" packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts

Repository: agentuity/sdk

Length of output: 39


🏁 Script executed:

# Look for other validation error patterns in CLI files
rg "tui\.error|process\.exit" packages/cli/src/cmd --type ts --type tsx -B 1 -A 1 | head -n 100

Repository: agentuity/sdk

Length of output: 84


🏁 Script executed:

# Search for StructuredError without type specification
rg "StructuredError" packages/cli/src -B 2 -A 5

Repository: agentuity/sdk

Length of output: 42203


🏁 Script executed:

# Look for how errors are thrown in other CLI commands
rg "throw new" packages/cli/src/cmd -B 1 -A 3 | head -n 80

Repository: agentuity/sdk

Length of output: 4986


🏁 Script executed:

# Check imports from `@agentuity/core` in CLI files
rg "from '@agentuity/core'" packages/cli/src/cmd -B 1 -A 1 | head -n 100

Repository: agentuity/sdk

Length of output: 6922


🏁 Script executed:

# Look for validation error patterns specifically
rg "process\.exit" packages/cli/src/cmd -B 3 -A 1 | head -n 120

Repository: agentuity/sdk

Length of output: 6981


Use StructuredError for package validation failures.

This validation block prints errors and exits directly, bypassing structured error handling. Replace the tui.error() + loop + process.exit(1) with a StructuredError and add the import from @agentuity/core. This aligns with the CLI's error-handling standard used throughout validation logic.

🔧 Suggested change
-			tui.error('Invalid package specifiers:');
-			for (const pkg of invalidPackages) {
-				tui.bullet(
-					`${pkg}: must not contain whitespace, semicolons, backticks, pipes, or dollar signs`
-				);
-			}
-			process.exit(1);
+			throw new StructuredError('INVALID_PACKAGE_SPECIFIER', {
+				packages: invalidPackages,
+				message:
+					'must not contain whitespace, semicolons, backticks, pipes, or dollar signs',
+			});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cli/src/cmd/cloud/sandbox/snapshot/build.ts` around lines 585 - 599,
Replace the current direct CLI exit flow in the package validation block (the
buildConfig.packages check that uses NPM_PACKAGE_NAME_PATTERN, tui.error,
tui.bullet, and process.exit(1)) with a thrown StructuredError from
`@agentuity/core`: import StructuredError, construct an error that includes a
clear message like "Invalid package specifiers" and include the invalidPackages
(from the invalidPackages array) as either a single joined string or as
structured details on the StructuredError, then throw it instead of calling
tui/error and process.exit so the existing CLI error handling can surface the
message.

Comment on lines +3 to +13
/**
* Regex pattern for validating npm/bun package specifiers.
* Uses a blocklist approach: rejects shell injection characters while allowing
* all legitimate specifier formats (names, scoped packages, URLs, git refs, etc.).
*
* Valid examples: "typescript", "@types/node", "opencode-ai@1.2.3",
* "https://github.com/user/repo", "git+https://github.com/user/repo.git",
* "github:user/repo", "file:../local-pkg"
* Invalid examples: "foo bar", "pkg;rm -rf", "pkg|cat /etc/passwd", "$(evil)"
*/
export const NPM_PACKAGE_NAME_PATTERN = /^[^\s;`|$]+$/;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Tighten the package-specifier regex to fully block shell metacharacters.

The current pattern still allows &, <, and > which are shell operators and can be used for chaining or redirection without spaces. Since these specifiers are interpolated into a bun install -g command, this leaves a remaining injection path. Consider blocking those characters (or ensure safe quoting/escaping at execution).

🔧 Suggested regex hardening
-export const NPM_PACKAGE_NAME_PATTERN = /^[^\s;`|$]+$/;
+export const NPM_PACKAGE_NAME_PATTERN = /^[^\s;`|$&<>]+$/;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* Regex pattern for validating npm/bun package specifiers.
* Uses a blocklist approach: rejects shell injection characters while allowing
* all legitimate specifier formats (names, scoped packages, URLs, git refs, etc.).
*
* Valid examples: "typescript", "@types/node", "opencode-ai@1.2.3",
* "https://github.com/user/repo", "git+https://github.com/user/repo.git",
* "github:user/repo", "file:../local-pkg"
* Invalid examples: "foo bar", "pkg;rm -rf", "pkg|cat /etc/passwd", "$(evil)"
*/
export const NPM_PACKAGE_NAME_PATTERN = /^[^\s;`|$]+$/;
/**
* Regex pattern for validating npm/bun package specifiers.
* Uses a blocklist approach: rejects shell injection characters while allowing
* all legitimate specifier formats (names, scoped packages, URLs, git refs, etc.).
*
* Valid examples: "typescript", "@types/node", "opencode-ai@1.2.3",
* "https://github.com/user/repo", "git+https://github.com/user/repo.git",
* "github:user/repo", "file:../local-pkg"
* Invalid examples: "foo bar", "pkg;rm -rf", "pkg|cat /etc/passwd", "$(evil)"
*/
export const NPM_PACKAGE_NAME_PATTERN = /^[^\s;`|$&<>]+$/;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/server/src/api/sandbox/snapshot-build.ts` around lines 3 - 13, The
NPM_PACKAGE_NAME_PATTERN currently allows &, <, and > which can enable shell
injection when interpolated into bun install -g; update the pattern used by
NPM_PACKAGE_NAME_PATTERN to explicitly forbid additional shell metacharacters
(at least &, <, > and any other shell operators you deem risky) or switch to a
whitelist approach for allowed characters; locate and modify the exported
constant NPM_PACKAGE_NAME_PATTERN in snapshot-build.ts to implement the
tightened regex (or replace runtime interpolation with proper quoting/escaping
before executing bun).

@jhaynie jhaynie merged commit 52b8d92 into main Feb 21, 2026
28 of 30 checks passed
@jhaynie jhaynie deleted the task/npm-dependencies-in-yaml-cli-964 branch February 21, 2026 20:01
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.

Snapshot build: support npm/bun dependencies in declarative YAML

1 participant