Skip to content

test: isolate E2E LLM profiles store#1015

Merged
enyst merged 3 commits into
developfrom
chore/e2e-isolate-llm-profiles
Mar 27, 2026
Merged

test: isolate E2E LLM profiles store#1015
enyst merged 3 commits into
developfrom
chore/e2e-isolate-llm-profiles

Conversation

@enyst
Copy link
Copy Markdown
Owner

@enyst enyst commented Mar 26, 2026

Ensure E2E runs never touch a developer's real ~/.openhands/llm-profiles.

What changed

  • Extension: when running under E2E (non-production + TEST_NAME), set E2E_LLM_PROFILES_DIR/OPENHANDS_LLM_PROFILES_DIR to a per-run directory under the VS Code user-data-dir globalStorage.
  • Agent SDK: LLM profile store now honors OPENHANDS_LLM_PROFILES_DIR (and E2E_LLM_PROFILES_DIR) as the default root.
  • E2E suites that validate default profile seeding now resolve the store dir via env override.

Verification

  • npm run typecheck
  • npm test
  • npm run lint
  • npm run e2e

Open with Devin

Summary by CodeRabbit

  • New Features

    • Added environment-variable-driven resolution for the LLM profiles directory with deterministic on-disk setup in test runs.
  • Bug Fixes

    • Fixed conditional default-profile seeding so profiles are only skipped when genuinely using a non-default store.
  • Tests

    • Enhanced E2E tests to honor env var overrides, trigger profile seeding during setup, and use the resolved profiles directory.

Co-authored-by: smolpaws <engel@enyst.org>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 27, 2026

Warning

Rate limit exceeded

@enyst has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 15 minutes and 3 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 15 minutes and 3 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 897f5629-435e-4954-93d2-369f01f9e245

📥 Commits

Reviewing files that changed from the base of the PR and between dfacea6 and 4854a84.

📒 Files selected for processing (1)
  • src/extension.ts
📝 Walkthrough

Walkthrough

Adds environment-variable driven LLM profiles directory resolution and E2E test setup: the SDK reads OPENHANDS_LLM_PROFILES_DIR/E2E_LLM_PROFILES_DIR when resolving the profiles root and the extension creates and wires a deterministic on-disk llm-profiles directory during test-mode activation.

Changes

Cohort / File(s) Summary
Core Profile Resolution Logic
packages/agent-sdk/src/sdk/llm/profiles.ts
resolveRootDir now reads process.env.OPENHANDS_LLM_PROFILES_DIR then process.env.E2E_LLM_PROFILES_DIR (trimmed) before falling back to DEFAULT_LLM_PROFILES_DIR. ensureDefaultProfilesForDefaultStore only skips seeding when options.rootDir resolves to a different path than the default resolved root.
Extension E2E Test Setup
src/extension.ts
Added ensureE2eLlmProfilesStoreDir(context) and wired it into activate. Resolves an on-disk test store (preferring E2E_LLM_PROFILES_DIR then OPENHANDS_LLM_PROFILES_DIR, else <globalStorageUri>/llm-profiles), performs best-effort fs.mkdirSync(..., { recursive: true, mode: 0o700 }), swallows errors, and sets both env vars to the resolved directory. Added fs and path imports.
E2E Test Suite Support
tests/e2e/suite/defaultProfilesSeeding.ts
getProfilesDir() updated to prefer OPENHANDS_LLM_PROFILES_DIR (trimmed, resolved), then E2E_LLM_PROFILES_DIR, else previous default. Calls vscode.commands.executeCommand('openhands._listProfiles') early in run() to trigger default-profile seeding before assertions.
Formatting / Minor
tests/e2e/suite/llmProfiles.ts
Inserted blank lines only; no functional changes.

Sequence Diagram(s)

(Skipped — changes are small and self-contained; no multi-component control-flow requiring visualization.)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 I hopped through env vars, nose to the ground,

OPENHANDS and E2E paths I found.
I dug a neat burrow for tests to reside,
Made directories snug, with permissions applied.
Hooray — profiles seeded, in a cozy tide!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'test: isolate E2E LLM profiles store' directly and clearly summarizes the main change: isolating E2E test runs to prevent them from modifying a developer's real LLM profiles directory.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/e2e-isolate-llm-profiles

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

gemini-code-assist[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

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.

🧹 Nitpick comments (1)
tests/e2e/suite/defaultProfilesSeeding.ts (1)

19-31: Environment variable priority differs from SDK's resolveRootDir.

The test helper checks E2E_LLM_PROFILES_DIR first, then OPENHANDS_LLM_PROFILES_DIR. However, the SDK's resolveRootDir in packages/agent-sdk/src/sdk/llm/profiles.ts (lines 44-48) checks them in the opposite order: OPENHANDS_LLM_PROFILES_DIR first, then E2E_LLM_PROFILES_DIR.

In practice this works because extension.ts sets both variables to the same value, but the inconsistent priority could cause confusion or subtle bugs if someone sets only one variable in the future.

Consider aligning the priority order with the SDK:

♻️ Suggested alignment
 const getProfilesDir = (): string => {
-  const fromEnv = typeof process.env.E2E_LLM_PROFILES_DIR === 'string'
-    ? process.env.E2E_LLM_PROFILES_DIR.trim()
+  const fromSdkEnv = typeof process.env.OPENHANDS_LLM_PROFILES_DIR === 'string'
+    ? process.env.OPENHANDS_LLM_PROFILES_DIR.trim()
     : '';
-  if (fromEnv) return path.resolve(fromEnv);
+  if (fromSdkEnv) return path.resolve(fromSdkEnv);
 
-  const fromSdkEnv = typeof process.env.OPENHANDS_LLM_PROFILES_DIR === 'string'
-    ? process.env.OPENHANDS_LLM_PROFILES_DIR.trim()
+  const fromEnv = typeof process.env.E2E_LLM_PROFILES_DIR === 'string'
+    ? process.env.E2E_LLM_PROFILES_DIR.trim()
     : '';
-  if (fromSdkEnv) return path.resolve(fromSdkEnv);
+  if (fromEnv) return path.resolve(fromEnv);
 
   return path.join(os.homedir(), '.openhands', 'llm-profiles');
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/e2e/suite/defaultProfilesSeeding.ts` around lines 19 - 31, The
getProfilesDir helper currently prefers E2E_LLM_PROFILES_DIR over
OPENHANDS_LLM_PROFILES_DIR, which is the opposite order used by the SDK's
resolveRootDir; update getProfilesDir so it checks OPENHANDS_LLM_PROFILES_DIR
first and falls back to E2E_LLM_PROFILES_DIR to match resolveRootDir's priority
(refer to getProfilesDir and resolveRootDir and the env vars
OPENHANDS_LLM_PROFILES_DIR and E2E_LLM_PROFILES_DIR).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@tests/e2e/suite/defaultProfilesSeeding.ts`:
- Around line 19-31: The getProfilesDir helper currently prefers
E2E_LLM_PROFILES_DIR over OPENHANDS_LLM_PROFILES_DIR, which is the opposite
order used by the SDK's resolveRootDir; update getProfilesDir so it checks
OPENHANDS_LLM_PROFILES_DIR first and falls back to E2E_LLM_PROFILES_DIR to match
resolveRootDir's priority (refer to getProfilesDir and resolveRootDir and the
env vars OPENHANDS_LLM_PROFILES_DIR and E2E_LLM_PROFILES_DIR).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9b7e3c06-07f8-4bef-a039-fb1676885204

📥 Commits

Reviewing files that changed from the base of the PR and between 9c11841 and 7bcbb1b.

📒 Files selected for processing (4)
  • packages/agent-sdk/src/sdk/llm/profiles.ts
  • src/extension.ts
  • tests/e2e/suite/defaultProfilesSeeding.ts
  • tests/e2e/suite/llmProfiles.ts

Co-authored-by: smolpaws <engel@enyst.org>
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.

🧹 Nitpick comments (1)
src/extension.ts (1)

228-230: Align env-var precedence with SDK root resolution for consistency.

When both env vars are set, this picks E2E_LLM_PROFILES_DIR first, but packages/agent-sdk/src/sdk/llm/profiles.ts resolves OPENHANDS_LLM_PROFILES_DIR first. Matching the same order avoids surprising overrides in mixed setups.

Suggested diff
-  const explicitE2e = process.env.E2E_LLM_PROFILES_DIR?.trim() ?? '';
-  const explicitSdk = process.env.OPENHANDS_LLM_PROFILES_DIR?.trim() ?? '';
-  const rootDir = path.resolve(explicitE2e || explicitSdk || path.join(context.globalStorageUri.fsPath, 'llm-profiles'));
+  const explicitSdk = process.env.OPENHANDS_LLM_PROFILES_DIR?.trim() ?? '';
+  const explicitE2e = process.env.E2E_LLM_PROFILES_DIR?.trim() ?? '';
+  const rootDir = path.resolve(explicitSdk || explicitE2e || path.join(context.globalStorageUri.fsPath, 'llm-profiles'));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/extension.ts` around lines 228 - 230, The env-var precedence is reversed
compared to the SDK: change the rootDir resolution to prefer
OPENHANDS_LLM_PROFILES_DIR over E2E_LLM_PROFILES_DIR so behavior matches
packages/agent-sdk/src/sdk/llm/profiles.ts; specifically update the rootDir
expression that currently uses explicitE2e || explicitSdk || ... to use
explicitSdk || explicitE2e || ..., keeping explicitE2e and explicitSdk variables
and the fallback path.resolve(path.join(context.globalStorageUri.fsPath,
'llm-profiles')) unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/extension.ts`:
- Around line 228-230: The env-var precedence is reversed compared to the SDK:
change the rootDir resolution to prefer OPENHANDS_LLM_PROFILES_DIR over
E2E_LLM_PROFILES_DIR so behavior matches
packages/agent-sdk/src/sdk/llm/profiles.ts; specifically update the rootDir
expression that currently uses explicitE2e || explicitSdk || ... to use
explicitSdk || explicitE2e || ..., keeping explicitE2e and explicitSdk variables
and the fallback path.resolve(path.join(context.globalStorageUri.fsPath,
'llm-profiles')) unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8fc91e36-da13-4855-ba7b-f1a492283e15

📥 Commits

Reviewing files that changed from the base of the PR and between 7bcbb1b and dfacea6.

📒 Files selected for processing (3)
  • packages/agent-sdk/src/sdk/llm/profiles.ts
  • src/extension.ts
  • tests/e2e/suite/defaultProfilesSeeding.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/agent-sdk/src/sdk/llm/profiles.ts

Co-authored-by: smolpaws <engel@enyst.org>
@github-actions
Copy link
Copy Markdown

🔧 VSCode Extension Built Successfully

• File: openhands-tab-0.9.3.vsix (548 KB)
• Download: https://github.com/enyst/OpenHands-Tab/actions/runs/23624525903

To install:

  1. Download the artifact from the run page above
  2. VS Code → Command Palette → "Extensions: Install from VSIX..."
  3. Select the downloaded .vsix

Built with Node 22. Commit 52c61f3.

@enyst
Copy link
Copy Markdown
Owner Author

enyst commented Mar 27, 2026

Addressed Gemini/Devin/CodeRabbit notes:

  • Kept env-var precedence consistent everywhere (prefer OPENHANDS over E2E).
  • In E2E mode, the extension now syncs both env vars to the same resolved directory so all call sites agree.
  • Simplified env-root trimming in agent-sdk and env checks in extension.

All checks green.

@enyst enyst merged commit 43c56dc into develop Mar 27, 2026
8 checks passed
@enyst enyst deleted the chore/e2e-isolate-llm-profiles branch March 27, 2026 00:45
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.

1 participant