Skip to content

fix(agent-workspace): create missing secret/provider during workspace creation - #2381

Merged
jeffmaury merged 3 commits into
openkaiden:mainfrom
jeffmaury:jeffmaury/GH-2371-1
Jul 7, 2026
Merged

jeffmaury merged 3 commits into
openkaiden:mainfrom
jeffmaury:jeffmaury/GH-2371-1

Conversation

@jeffmaury

@jeffmaury jeffmaury commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

How to test

  • Ensure you have no OpenShell gataway running and no OpenShell binaries in the PATH
  • Start kaiden and create a VertexAI connection
  • Build Kaiden binary
  • Restart Kaiden and start a Claude workspace
  • Verify you can talk to the model

Summary

  • Secret/provider creation for inference connections can silently fail at registration time. When this happens, workspace creation proceeds without credentials.
  • Extracted secret creation logic from SecretManager.onInferenceConnectionRegistered into a public createSecretForConnection method, and added ensureSecretForModel which creates the secret on the spot if the inference connection exists but its secret is missing.
  • AgentWorkspaceManager.ensureModelSecretFromConfig now calls ensureSecretForModel instead of getSecretForModel, so workspaces always get their credentials when a connection is available.

Fixes #2371

Test plan

  • Unit tests for createSecretForConnection — creates secret when none exists, returns undefined when _type not configured, returns undefined when secret already exists
  • Unit tests for ensureSecretForModel — returns existing secret without creating, creates and returns secret when missing but connection exists, returns undefined when no inference connection found
  • Updated AgentWorkspaceManager tests to use ensureSecretForModel
  • All 110 tests pass across both spec files

🤖 Generated with Claude Code

… creation

Secret/provider creation for inference connections can silently fail at
registration time. When this happens, workspace creation proceeds without
credentials. Now ensureModelSecretFromConfig creates the secret on the
spot if the inference connection exists but its secret is missing.

Fixes openkaiden#2371

Signed-off-by: Jeff MAURY <jmaury@redhat.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jeffmaury
jeffmaury requested a review from a team as a code owner July 7, 2026 07:02
@jeffmaury
jeffmaury requested review from MarsKubeX and bmahabirbu and removed request for a team July 7, 2026 07:02
@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@jeffmaury, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 44 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: d7e4bd71-313f-47e8-9928-19ffd3a36229

📥 Commits

Reviewing files that changed from the base of the PR and between 832e9c4 and 3170729.

📒 Files selected for processing (2)
  • packages/main/src/plugin/secret-manager/secret-manager.spec.ts
  • packages/main/src/plugin/secret-manager/secret-manager.ts
📝 Walkthrough

Walkthrough

OpenshellGateway now emits a start event during initialization. SecretManager listens for that event and refactors inference-secret creation behind new helper methods. AgentWorkspaceManager switches to the new secret lookup path and updates its tests accordingly.

Changes

Gateway start notifications and secret provisioning

Layer / File(s) Summary
OpenshellGateway start event
packages/main/src/plugin/openshell-cli/openshell-gateway.ts, packages/main/src/plugin/openshell-cli/openshell-gateway.spec.ts
Adds onDidGatewayStart, fires it during gateway init for healthy or auto-started gateways, and covers the new event flow in tests.
SecretManager secret provisioning
packages/main/src/plugin/secret-manager/secret-manager.ts
Wires in OpenshellGateway, emits secret-manager-update on gateway start, and moves model-secret creation into ensureSecretForModel and createSecretForConnection.
SecretManager tests
packages/main/src/plugin/secret-manager/secret-manager.spec.ts
Adds gateway-start subscription coverage and new secret provisioning cases for provider creation, reuse, and missing inputs.
AgentWorkspaceManager secret flow
packages/main/src/plugin/agent-workspace/agent-workspace-manager.ts, packages/main/src/plugin/agent-workspace/agent-workspace-manager.spec.ts
Injects OpenshellGateway, listens for gateway start updates, switches to ensureSecretForModel, and updates mocked secret lookups in the workspace tests.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

  • openkaiden/kaiden#2073: Both touch the inference-connection secret/config path used by ensureModelSecretFromConfig.
  • openkaiden/kaiden#2085: Both affect OpenshellGateway init and gateway health/startup handling.
  • openkaiden/kaiden#2308: Both modify secret-manager.ts around inference-connection registration and provider lifecycle logic.

Suggested reviewers: gastoner, benoitf

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately reflects the main change around creating missing secrets/providers during workspace creation.
Description check ✅ Passed The description matches the changeset and test coverage, including on-demand secret creation and workspace startup behavior.
Linked Issues check ✅ Passed The PR addresses #2371 by initializing gateway-related updates during startup and ensuring provider/secret setup is available.
Out of Scope Changes check ✅ Passed All code changes support gateway startup notifications and on-demand secret/provider creation; no unrelated edits stand out.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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.

@jeffmaury
jeffmaury requested review from fbricon and gastoner July 7, 2026 07:04

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/main/src/plugin/secret-manager/secret-manager.ts`:
- Around line 163-173: `createSecretForConnection` currently returns `undefined`
for both “secret already exists” and “cannot resolve secret type,” which makes
the result ambiguous. Update the existing-secret branch in
`SecretManager.createSecretForConnection` to return the already found
`SecretInfo` (or equivalent secret metadata) instead of `undefined`, while
keeping the missing-config path as-is so callers can distinguish no-op from
failure.
- Around line 98-106: `ensureSecretForModel` is doing redundant provider/secret
lookups by calling `getSecretForModel`, then
`providerRegistry.getInferenceConnection`, and finally
`createSecretForConnection` which triggers another `this.list()` call. Update
`SecretManager.ensureSecretForModel` to reuse the already-resolved
connection/secrets data from `getSecretForModel` instead of re-querying, and
adjust `getSecretForModel` and/or `createSecretForConnection` to accept or
return the pre-fetched info needed to avoid duplicate round-trips. Use the
`SecretManager`, `getSecretForModel`, `ensureSecretForModel`, and
`createSecretForConnection` paths to centralize the lookup and dedup logic.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e3c02bfa-1331-4281-8208-8b300986775d

📥 Commits

Reviewing files that changed from the base of the PR and between 351c92b and a19cab9.

📒 Files selected for processing (4)
  • packages/main/src/plugin/agent-workspace/agent-workspace-manager.spec.ts
  • packages/main/src/plugin/agent-workspace/agent-workspace-manager.ts
  • packages/main/src/plugin/secret-manager/secret-manager.spec.ts
  • packages/main/src/plugin/secret-manager/secret-manager.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (9)
  • GitHub Check: linter, formatters
  • GitHub Check: smoke-e2e-tests (prod) / ubuntu-24.04 (ollama)
  • GitHub Check: smoke-e2e-tests (dev) / ubuntu-24.04 (ollama)
  • GitHub Check: Windows
  • GitHub Check: unit tests / windows-2022
  • GitHub Check: Linux
  • GitHub Check: unit tests / ubuntu-24.04
  • GitHub Check: unit tests / macos-15
  • GitHub Check: macOS
⚠️ CI failures not shown inline (4)

GitHub Actions: fullsend / dispatch _ Route: fix(agent-workspace): create missing secret/provider during workspace creation

Conclusion: failure

View job details

##[group]Run set -euo pipefail
 �[36;1mset -euo pipefail�[0m
 �[36;1m�[0m
 �[36;1mif [[ ! "$STAGE" =~ ^[a-z][a-z0-9_-]*$ ]]; then�[0m
 �[36;1m  echo "::error::Invalid stage name: must start with lowercase letter and contain only [a-z0-9_-]"�[0m

GitHub Actions: fullsend / 6_dispatch _ Route.txt: fix(agent-workspace): create missing secret/provider during workspace creation

Conclusion: failure

View job details

##[group]Run set -euo pipefail
 �[36;1mset -euo pipefail�[0m
 �[36;1m�[0m
 �[36;1mif [[ ! "$STAGE" =~ ^[a-z][a-z0-9_-]*$ ]]; then�[0m
 �[36;1m  echo "::error::Invalid stage name: must start with lowercase letter and contain only [a-z0-9_-]"�[0m

GitHub Actions: fullsend / dispatch _ Route: fix(agent-workspace): create missing secret/provider during workspace creation

Conclusion: failure

View job details

##[group]Run set -euo pipefail
 �[36;1mset -euo pipefail�[0m
 �[36;1mEVENT_PAYLOAD=$(jq -c '{�[0m
 �[36;1m  issue: (.issue // null | if . then {number, html_url} else null end),�[0m
 �[36;1m  pull_request: (.pull_request // null | if . then {number, html_url,�[0m
 �[36;1m    head: {ref: .head.ref, sha: .head.sha, repo: {full_name: .head.repo.full_name}},�[0m
 �[36;1m    base: {ref: .base.ref, repo: {full_name: .base.repo.full_name}}} else null end),�[0m
 �[36;1m  comment: (.comment // null | if . then {body: .body[:4096]} else null end)�[0m
 �[36;1m}' "$GITHUB_EVENT_PATH") || {�[0m
 �[36;1m  echo "::error::Failed to extract event payload from GITHUB_EVENT_PATH"�[0m

GitHub Actions: fullsend / dispatch _ Route: fix(agent-workspace): create missing secret/provider during workspace creation

Conclusion: failure

View job details

##[group]Run set -euo pipefail
 �[36;1mset -euo pipefail�[0m
 �[36;1mif [[ -f .fullsend/config.yaml ]]; then�[0m
 �[36;1m  KILL_SWITCH=$(yq '.kill_switch // false' .fullsend/config.yaml)�[0m
 �[36;1m  if [[ "$KILL_SWITCH" == "true" ]]; then�[0m
 �[36;1m    echo "::error::Kill switch is active — all agent dispatch halted"�[0m
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use /@/ path aliases instead of relative paths for imports outside the current directory's module group; use relative imports only for sibling modules within the same directory

Files:

  • packages/main/src/plugin/agent-workspace/agent-workspace-manager.ts
  • packages/main/src/plugin/secret-manager/secret-manager.ts
  • packages/main/src/plugin/agent-workspace/agent-workspace-manager.spec.ts
  • packages/main/src/plugin/secret-manager/secret-manager.spec.ts
packages/main/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

packages/main/src/**/*.{ts,tsx}: Use ipcHandle() to expose handlers in the main process with naming convention <registry-name>:<action> (e.g., container-provider-registry:listContainers)
Use apiSender.send() to send events from main process to renderer for real-time updates
Long-running operations should use TaskManager.createTask() with title and action configuration

Files:

  • packages/main/src/plugin/agent-workspace/agent-workspace-manager.ts
  • packages/main/src/plugin/secret-manager/secret-manager.ts
  • packages/main/src/plugin/agent-workspace/agent-workspace-manager.spec.ts
  • packages/main/src/plugin/secret-manager/secret-manager.spec.ts
packages/{main,renderer,preload}/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Container operations must include engineId parameter to identify the container engine

Files:

  • packages/main/src/plugin/agent-workspace/agent-workspace-manager.ts
  • packages/main/src/plugin/secret-manager/secret-manager.ts
  • packages/main/src/plugin/agent-workspace/agent-workspace-manager.spec.ts
  • packages/main/src/plugin/secret-manager/secret-manager.spec.ts
**/*.spec.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.spec.{ts,tsx,js,jsx}: Use test() instead of it() for test cases in Vitest unit tests
Use vi.mock(import('...')) for auto-mocking modules in unit tests; avoid manual mock factories when possible
Use vi.resetAllMocks() in beforeEach hooks instead of vi.clearAllMocks() for resetting mocks between tests
When an auto-mocked function or class method needs a real implementation, use vi.mocked(...) with the prototype pattern for class methods: vi.mocked(MyClass.prototype.myMethod).mockImplementation(...)

Files:

  • packages/main/src/plugin/agent-workspace/agent-workspace-manager.spec.ts
  • packages/main/src/plugin/secret-manager/secret-manager.spec.ts
🧠 Learnings (3)
📚 Learning: 2026-03-09T08:47:09.657Z
Learnt from: benoitf
Repo: kortex-hub/kortex PR: 1077
File: packages/main/src/plugin/skill/skill-manager.ts:80-109
Timestamp: 2026-03-09T08:47:09.657Z
Learning: In the kortex-hub/kortex repository, IPC handlers (via ipcHandle()) may be registered directly inside feature manager/service classes (e.g., SkillManager in packages/main/src/plugin/skill/skill-manager.ts) rather than exclusively in packages/main/src/plugin/index.ts. Treat this as an accepted design pattern for files under the plugin directory. Reviewers should not require centralization in index.ts; allow IPC registration proximity to the feature that owns the handler. When reviewing code, accept direct ipcHandle() registrations inside feature managers and ensure the pattern is consistently applied across similar feature-manager modules.

Applied to files:

  • packages/main/src/plugin/agent-workspace/agent-workspace-manager.ts
  • packages/main/src/plugin/secret-manager/secret-manager.ts
  • packages/main/src/plugin/agent-workspace/agent-workspace-manager.spec.ts
  • packages/main/src/plugin/secret-manager/secret-manager.spec.ts
📚 Learning: 2026-05-12T17:14:02.153Z
Learnt from: MarsKubeX
Repo: openkaiden/kaiden PR: 1850
File: packages/renderer/src/lib/agent-workspaces/AgentWorkspaceList.svelte:66-70
Timestamp: 2026-05-12T17:14:02.153Z
Learning: When reviewing code that uses `AgentWorkspaceSummaryUI.runtime`, treat it as a required, non-null `string` per the `openkaiden/kdn-api` 0.12.0 schema. Therefore, code like `a.runtime.localeCompare(b.runtime)` is safe and should not trigger warnings about possible `undefined`/`null` values or suggestions to use nullish coalescing/optional chaining for `runtime` (unless the current local types still mark `runtime` as optional, indicating a schema/version mismatch).

Applied to files:

  • packages/main/src/plugin/agent-workspace/agent-workspace-manager.ts
  • packages/main/src/plugin/secret-manager/secret-manager.ts
  • packages/main/src/plugin/agent-workspace/agent-workspace-manager.spec.ts
  • packages/main/src/plugin/secret-manager/secret-manager.spec.ts
📚 Learning: 2026-06-29T13:16:53.102Z
Learnt from: benoitf
Repo: openkaiden/kaiden PR: 2296
File: extensions/container/packages/extension/src/helper/socket-finder/_socket-finder-module.ts:28-29
Timestamp: 2026-06-29T13:16:53.102Z
Learning: When reviewing imports in openkaiden/kaiden TypeScript/JavaScript files, prefer the configured `/@/` path alias instead of relative imports that would require traversing out of the current directory/module group (i.e., paths containing `..` that cross boundaries). 

Do not require alias conversion for descendant-path relative imports within the socket-finder module directory—for example, in `extensions/container/packages/extension/src/helper/socket-finder/**`, imports like `./podman/podman-version-detector` and `./podman/podman-windows-finder` are acceptable and should not be flagged.

Applied to files:

  • packages/main/src/plugin/agent-workspace/agent-workspace-manager.ts
  • packages/main/src/plugin/secret-manager/secret-manager.ts
  • packages/main/src/plugin/agent-workspace/agent-workspace-manager.spec.ts
  • packages/main/src/plugin/secret-manager/secret-manager.spec.ts
🔇 Additional comments (6)
packages/main/src/plugin/agent-workspace/agent-workspace-manager.ts (1)

383-390: LGTM!

packages/main/src/plugin/agent-workspace/agent-workspace-manager.spec.ts (1)

143-143: LGTM!

Also applies to: 589-590, 633-633, 805-809, 818-818, 827-827

packages/main/src/plugin/secret-manager/secret-manager.spec.ts (2)

470-550: Test comment confirms the duplicate-lookup overhead flagged in the source file.

The comment at Lines 499-500 explicitly documents listProviders being invoked twice per ensureSecretForModel call (once via getSecretForModel, once via the dedup check in createSecretForConnection). This is good test coverage; see the companion comment on secret-manager.ts Lines 98-106 for the suggested consolidation.


380-468: LGTM!

packages/main/src/plugin/secret-manager/secret-manager.ts (2)

175-177: LGTM!


108-173: 🩺 Stability & Availability

Serialize secret creation per connection. onDidRegisterInferenceConnection and ensureSecretForModel can both reach this non-atomic list()create() path for the same secretName, so concurrent calls can race into a duplicate create. If the CLI rejects duplicate provider names, an in-flight map keyed by secretName or an idempotent create path would avoid the failure.

Comment thread packages/main/src/plugin/secret-manager/secret-manager.ts
Comment thread packages/main/src/plugin/secret-manager/secret-manager.ts Outdated
@codecov

codecov Bot commented Jul 7, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Signed-off-by: Jeff MAURY <jmaury@redhat.com>

@MarsKubeX MarsKubeX left a comment

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.

LGTM. Tested and working as expected

Signed-off-by: Jeff MAURY <jmaury@redhat.com>
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.

Gatexay not initialized when extensions are started

2 participants