Skip to content

Conversation

@Gladdonilli
Copy link
Contributor

@Gladdonilli Gladdonilli commented Jan 16, 2026

Summary

This PR fixes background agent authentication failures. Background agents were failing silently because API calls to the OpenCode server lacked authentication headers.

Changes

1. Background Agent Authentication Fix (src/features/background-agent/manager.ts)

Problem: Background agent API calls (session.create, session.prompt, session.messages, etc.) were failing with 401 Unauthorized when OpenCode server has authentication enabled.

Root Cause: The BackgroundManager was using ctx.client directly, which doesn't include HTTP Basic Auth headers required by the server.

Solution:

  • Added createAuthenticatedClient() helper function that creates an OpenCode SDK client with HTTP Basic Auth headers
  • Credentials are read from OPENCODE_SERVER_USERNAME (default: "opencode") and OPENCODE_SERVER_PASSWORD environment variables
  • Created lazy-initialized authClient instance via getAuthenticatedClient() method
  • All background agent API calls now use the authenticated client

API calls now authenticated:

  • session.get() - fetching parent session info
  • session.create() - creating background sessions
  • session.prompt() - sending prompts to background agents
  • session.todo() - checking session todos
  • session.messages() - fetching session messages
  • session.status() - polling task status

2. Tool Authentication Fixes

delegate_task tool (src/index.ts)

  • Updated createDelegateTask() to use backgroundManager.getAuthenticatedClient() instead of ctx.client

look_at tool (src/tools/look-at/tools.ts)

  • Added client: SdkOpencodeClient parameter to createLookAt()
  • All session API calls (session.get, session.create, session.prompt, session.messages) now use authenticated client
  • Updated src/index.ts to pass backgroundManager.getAuthenticatedClient()

call_omo_agent tool (src/tools/call-omo-agent/tools.ts)

  • Added client: SdkOpencodeClient parameter to executeSync()
  • All session API calls in sync mode now use authenticated client
  • Background mode already used backgroundManager.launch() which handles auth internally

Background tools (background_output, background_cancel)

  • Updated createBackgroundTools() call to use authenticated client

3. Shared Authenticated Fetch Utility (src/shared/authenticated-fetch.ts)

New file providing a reusable createAuthenticatedFetch() function:

  • Creates a fetch wrapper that adds HTTP Basic Auth headers
  • Handles both Request objects (SDK style) and url + init style calls
  • Critical fix: Properly reconstructs Request objects with duplex: 'half' for streaming body support
  • Uses lowercase authorization header key to properly override existing headers
  • Handles method-based body exclusion (no body for GET/HEAD requests)
  • Password is read lazily at first use (after OpenCode sets it post-plugin-init)

4. LSP Client Shutdown Sequence Fix (src/tools/lsp/client.ts)

Problem: LSP client was using notify("shutdown") which violates LSP spec.

Solution:

  • LSP spec requires shutdown to be a REQUEST (not notification) - must wait for response
  • Added proper sequence: send("shutdown") → wait for response → notify("exit")
  • Added 3-second timeout for shutdown request
  • Added 500ms grace period before force kill
  • Added early return if process already exited

5. Schema and Migration Cleanup

assets/oh-my-opencode.schema.json

  • Updated disabled_hooks enum: sisyphus-task-retrydelegate-task-retry
  • Removed preemptive-compaction from enum (feature was removed)

src/shared/migration.ts

  • Fixed require path: ../tools/sisyphus-task/constants../tools/delegate-task/constants

6. Improved Exception Logging (src/tools/delegate-task/tools.ts)

Added logging to the swallowed exception in parent session lookup:

.catch((err) => {
  log("[delegate_task] Failed to get parent session:", err)
  return null
})

7. Review Feedback Addressed

  • Added duplex: 'half' for streaming body in Request reconstruction
  • Used lowercase authorization key to properly override headers
  • Handle method-based body exclusion (no body for GET/HEAD)
  • Fixed log tag from [sisyphus_task] to [delegate_task]
  • Restored preemptive-compaction to disabled_hooks enum
  • Implemented lazy auth client initialization

Testing

  • Background agents (explore, librarian, oracle, etc.) now successfully authenticate and execute
  • Verified session.create, session.prompt, and polling all work with auth enabled
  • Confirmed backward compatibility when auth is not configured (no password = no auth header)
  • TypeScript typecheck passes
  • Build succeeds

Breaking Changes

None. Auth is only added when OPENCODE_SERVER_PASSWORD is set.

@Gladdonilli
Copy link
Contributor Author

(this is my local version, could be different from current upstream)

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 5 files

Confidence score: 3/5

  • src/shared/authenticated-fetch.ts drops any overrides supplied to fetch(Request, init), so headers, method, body, or abort signals can’t be customized when reusing a Request, which is a concrete user-facing regression.
  • Given the medium severity and high confidence of this behavior change, the current merge poses some risk until override handling matches native fetch semantics.
  • Pay close attention to src/shared/authenticated-fetch.ts – fix the missing init overrides logic.
Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="src/shared/authenticated-fetch.ts">

<violation number="1" location="src/shared/authenticated-fetch.ts:33">
P2: Init overrides are ignored when input is a Request, diverging from fetch(Request, init) semantics (headers/method/body/signal overrides are dropped).</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@cubic-dev-ai
Copy link

cubic-dev-ai bot commented Jan 16, 2026

@greptile
@MacroscopeApp
@cubic-dev-ai

@Gladdonilli I have started the AI code review. It will take a few minutes to complete.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="src/shared/authenticated-fetch.ts">

<violation number="1" location="src/shared/authenticated-fetch.ts:48">
P2: Nullish coalescing prevents `init.body = null` from overriding the cloned body, so callers cannot clear an inherited body</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

7 issues found across 6 files

Confidence score: 2/5

  • Rebuilding requests in src/shared/authenticated-fetch.ts can crash Node fetch whenever a body stream is present because duplex isn’t set, so any non-empty POST/PUT fails outright.
  • The same file leaves multiple Authorization headers when overriding, meaning downstream services may receive malformed credentials and reject the call.
  • assets/oh-my-opencode.schema.json drops the documented preemptive-compaction enum value, which will make existing user configs invalid until they change their settings.
  • Pay close attention to src/shared/authenticated-fetch.ts, assets/oh-my-opencode.schema.json - they’re introducing user-visible runtime and compatibility regressions.
Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="src/tools/delegate-task/tools.ts">

<violation number="1" location="src/tools/delegate-task/tools.ts:566">
P2: Misleading log tag: uses "[sisyphus_task]" instead of this tool’s "[delegate_task]", hindering correct log filtering/alerts.</violation>
</file>

<file name="assets/oh-my-opencode.schema.json">

<violation number="1" location="assets/oh-my-opencode.schema.json:75">
P2: Removed `preemptive-compaction` from `disabled_hooks` enum breaks schema compatibility; documented configs using it now fail validation</violation>
</file>

<file name="src/shared/authenticated-fetch.ts">

<violation number="1" location="src/shared/authenticated-fetch.ts:38">
P1: Authorization header not overridden: uppercase key is added alongside existing lowercase header, leading to combined Authorization values when Request is rebuilt.</violation>

<violation number="2" location="src/shared/authenticated-fetch.ts:48">
P2: Request body merging ignores null and may pass a body with GET/HEAD overrides, causing runtime errors</violation>

<violation number="3" location="src/shared/authenticated-fetch.ts:57">
P1: Reconstructed Request passes a streaming body without required `duplex`, causing Node fetch to throw for any non-empty body</violation>
</file>

<file name="src/features/background-agent/manager.ts">

<violation number="1" location="src/features/background-agent/manager.ts:90">
P2: Authenticated client captures server password only at construction, so if the password is populated after plugin init (as documented), background agent requests will keep using an unauthenticated client and persistently 401.</violation>
</file>

<file name="src/features/background-agent/manager.test.ts">

<violation number="1" location="src/features/background-agent/manager.test.ts:174">
P2: Tests construct BackgroundManager with a real server URL, causing resume/launch paths to fire real HTTP requests via authClient instead of the stubbed client</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@kdcokenny
Copy link
Collaborator

please resolve the cubic bot conversations @Gladdonilli

@Gladdonilli
Copy link
Contributor Author

please resolve the cubic bot conversations @Gladdonilli

im not sure If i actually recommend to merge this build even after fixes, I made this pr to show the one other person whos having auth issue and Q

have you ever experienced the issues mentioned?

@Gladdonilli
Copy link
Contributor Author

I'll also add in my other patches

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

2 issues found across 6 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="src/tools/lsp/client.ts">

<violation number="1" location="src/tools/lsp/client.ts:595">
P2: stop() now awaits shutdown/exit, but cleanup calls it without await before process.exit(), so graceful/forced termination may never run and LSP servers can be orphaned</violation>

<violation number="2" location="src/tools/lsp/client.ts:596">
P2: Shutdown request sends params as null, which violates JSON-RPC/LSP (params must be array/object or omitted) and may cause servers to reject shutdown.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@Gladdonilli
Copy link
Contributor Author

Update: Rebased onto latest upstream/dev + added skills parsing fix

This PR has been rebased onto the latest upstream/dev branch (30+ new commits integrated) and includes an additional fix.

Changes in this update:

  1. Rebased onto upstream/dev - Integrated all recent upstream changes including:

    • LSP client refactored to use notify("shutdown", {}) instead of send("shutdown", null)
    • delegate_task rename and related refactors
  2. New fix: delegate_task skills parameter parsing (commit 8636bec)

    • When XML parameter handling passes skills=null, it can be received as the string literal "null" instead of actual null
    • This caused the string to be split into characters ['n','u','l','l'] and fail with "Skills not found: n, u, l, l"
    • Added explicit check to convert string "null" to actual null

Regarding cubic-dev-ai reviews:

The reviews were on commits that are now obsolete after the rebase. Here's the status:

Issue Status
P2: LSP shutdown null params ✅ Fixed by upstream (uses notify("shutdown", {}))
P1: duplex missing for streaming body ✅ Already fixed in authenticated-fetch.ts
P1: Authorization header override ✅ Already fixed (lowercase key)
P2: GET/HEAD body exclusion ✅ Already fixed
P2: Lazy auth client ✅ Already implemented

@cubic-dev-ai please re-review on the latest commits.

@cubic-dev-ai
Copy link

cubic-dev-ai bot commented Jan 16, 2026

Update: Rebased onto latest upstream/dev + added skills parsing fix

This PR has been rebased onto the latest upstream/dev branch (30+ new commits integrated) and includes an additional fix.

Changes in this update:

...

@Gladdonilli I have started the AI code review. It will take a few minutes to complete.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

3 issues found across 10 files

Confidence score: 3/5

  • Creating the authenticated background client eagerly in src/index.ts bypasses the intended lazy auth and risks caching an unauthenticated client, so user sessions could behave unexpectedly.
  • src/features/background-agent/manager.ts still mixes Authorization casing, which can produce duplicate headers once merged by the SDK and break Basic Auth.
  • The polling loop in src/tools/call-omo-agent/tools.ts ignores API errors, so failures are reported as idle/timeout rather than surfaced to users, masking real outages.
  • Pay close attention to src/index.ts, src/features/background-agent/manager.ts, src/tools/call-omo-agent/tools.ts - each needs fixes to avoid auth and error-reporting regressions.
Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="src/index.ts">

<violation number="1" location="src/index.ts:231">
P1: Authenticated background client is now created during plugin init, defeating the intended post-init lazy auth and potentially caching an unauthenticated client</violation>
</file>

<file name="src/features/background-agent/manager.ts">

<violation number="1" location="src/features/background-agent/manager.ts:31">
P1: Use a consistent lowercase `authorization` key for the Basic Auth header to avoid duplicate/combined Authorization values when the SDK merges headers.</violation>
</file>

<file name="src/tools/call-omo-agent/tools.ts">

<violation number="1" location="src/tools/call-omo-agent/tools.ts:229">
P2: Polling loop ignores errors from status/messages calls, misreporting API failures as idle/timeout</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@KNN-07
Copy link
Collaborator

KNN-07 commented Jan 16, 2026

Saw a report about this problem. Prolly fix the cubic review then its lgtm
Edit: alr prob should create a branch for this fix

@Gladdonilli
Copy link
Contributor Author

@cubic-dev-ai please re-review on the latest commits.

@cubic-dev-ai
Copy link

cubic-dev-ai bot commented Jan 16, 2026

@cubic-dev-ai please re-review on the latest commits.

@Gladdonilli I have started the AI code review. It will take a few minutes to complete.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 12 files

Confidence score: 3/5

  • Explicitly setting init.body to null is ignored and reuses the previous payload, so requests meant to clear the body could inadvertently send stale data—worth fixing before release.
  • Pay close attention to src/shared/authenticated-fetch.ts - null bodies currently reuse previous payloads instead of clearing them.
Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="src/shared/authenticated-fetch.ts">

<violation number="1" location="src/shared/authenticated-fetch.ts:50">
P2: `init.body` can be `null`, but `init?.body ?? cloned.body` treats `null` as missing and reuses the original body. Use an `undefined` check so `null` correctly overrides the body.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@GollyJer
Copy link
Collaborator

GollyJer commented Jan 17, 2026

I’m down to help test this, but I’m a bit stuck on the specific failure state. My recent PR cleared out a few of these bugs, but the auth header issue is definitely still there.

@Gladdonilli what’s the actual indicator that auth is failing? I’d expect the agents to stop reporting back to the TUI, but I'm still seeing them check in. I’m clearly missing a piece of the puzzle here.

Let me know what to look for so I can help knock this out. Thanks!

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.

4 participants