Skip to content

📖 Load Repository Instructions for Attached Workspaces - #16008

Merged
danny-avila merged 5 commits into
devfrom
danny-avila/repository-instructions
Sep 16, 2026
Merged

danny-avila merged 5 commits into
devfrom
danny-avila/repository-instructions

Conversation

@danny-avila

@danny-avila danny-avila commented Sep 16, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Attached-workspace agents currently have to remember to read repository guidance themselves. This adds automatic, authorized loading of worker-advertised AGENTS.md (or CLAUDE.md fallback), with a persisted Run Code setting: prefer repository conventions, defer to agent preferences, or off.

The workspace picker displays the discovered file, bounded size and truncation status. Existing workers without instruction metadata behave unchanged.

How it works

Live workspace authorization → advertised snapshot → hash-fenced read_file → bounded tenant/principal/machine/workspace cache → stable agent instructions.

  • Content is limited to 32 KiB and verified against its advertised digest before use. Missing, unreadable or changed snapshots are omitted rather than breaking a run. Optional authorization/read acquisition defaults to a two-second deadline, configurable through endpoints.agents.repositoryInstructions.timeoutMs (100–30,000 ms).
  • Fresh authorization and configured content filtering still run on cache hits. The bounded cache is owned by the host and injected into the portable module. Repository prose cannot grant filesystem/network access or bypass tool approval policy.
  • Shared TypeScript initialization consumes the saved setting directly for full-tool and definitions-only ingresses. CJS adapters supply authority dependencies only.
  • The setting survives agent create, update, management API projection and version restoration. No migration is required.
  • Initial scope is the registered root only, not parent traversal or nested directory chains.

Rollout

Requires LibreChat-AI/code-interpreter#226 for discovery. Deploy LibreChat and Code API support first, then update workers and opt in with --repository-instructions. Do not enable worker metadata against older LibreChat versions, which validate descriptors strictly.

Change Type

  • New feature
  • Requires documentation update

Testing

  • Focused API loader, initialization and management tests: passed (7 cases), including all saved modes, optional auth timeout, and cancellation.
  • Agent persistence enum regression: passed.
  • Data-provider typecheck: passed.
  • Repository-instruction configuration regression: passed, including bounds and default behavior.
  • Touched-file lint and diff whitespace checks: passed.
  • Client picker and settings regressions passed locally after supplying the missing Babel plugin from an isolated temporary dependency directory.
  • Combined local LibreChat loader → Code API HTTP → real worker/filesystem test passed: cache reuse, new hash refresh and off mode. Redis was mocked, listeners used disposable loopback ports, and no deployed services were modified.
  • API, client and data-schemas local typechecks encountered stale shared dependency declarations. Clean CI builds and typechecks now pass on f2c2abf1a2; all 39 checks are green. No full suites ran locally.
  • Codegraph indexed bases confirmed; authoritative test-selector credentials unavailable, so focused selection was reconciled against source call sites.

Checklist

  • Focused regression coverage added
  • Self-reviewed authorization, bounds, persistence and rollout boundaries
  • Clean CI verified
  • Browser acceptance verified

@danny-avila

Copy link
Copy Markdown
Collaborator Author

@codex review

Please review the current PR head ab086ed. Confirm that this exact commit is the reviewed commit and ignore findings that apply only to earlier heads. Coordinated worker protocol: LibreChat-AI/code-interpreter#226.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 16, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-16T12:44:43.026621Z f2c2abf Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ab086ed1f3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread api/server/services/ToolService.js Outdated
Comment thread api/server/services/ToolService.js Outdated
Comment thread api/server/services/ToolService.js Outdated
Comment thread packages/api/src/code/instructions.ts Outdated
Comment thread packages/api/src/agents/validation.ts
Comment thread packages/api/src/code/instructions.ts
@danny-avila

Copy link
Copy Markdown
Collaborator Author

@codex review

Please review the current PR head c7ed076. Confirm that this exact commit is the reviewed commit. Loading now lives in shared TypeScript initialization, after both loader paths return authorized source dependencies. Saved prefer/defer/off is consumed directly from the agent; optional auth/read acquisition is bounded to 2 seconds. Focused regressions and combined local HTTP worker test pass.

@danny-avila

Copy link
Copy Markdown
Collaborator Author

@codex review

Current head is 1d4f88f. Please review this exact head. The only change since c7ed076 is the explicit ReturnType annotation required by isolated declaration builds; runtime behavior is unchanged. All first-round fixes remain included.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1d4f88f04e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/api/src/code/instructions.ts Outdated
Comment thread packages/api/src/code/bridge.ts
@danny-avila

Copy link
Copy Markdown
Collaborator Author

@codex review

Please review exact head f2c2abf. The valid timeout finding is fixed through configSchema with a 2000ms default and 100–30000ms range. The cache is now host-owned and injected, not a packages/api singleton. Focused schema, deadline, mode and declaration regressions pass.

The rollout finding was reviewed and rejected with evidence in its thread: the companion worker emits no metadata on ordinary upgrade, only after explicit --repository-instructions opt-in following the documented server-first rollout. That staged gate remains intentional.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

Reviewed commit: f2c2abf1a2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@danny-avila
danny-avila merged commit 299dbc6 into dev Sep 16, 2026
40 checks passed
@danny-avila
danny-avila deleted the danny-avila/repository-instructions branch September 16, 2026 13:00
lia-by-librechat Bot pushed a commit that referenced this pull request Sep 16, 2026
The drift check added by #15928 fails on dev: #16008 added
`repositoryInstructions` to the agent schema without regenerating the
committed spec, so every branch merging dev inherits the failure. This is
the remedy the check itself prescribes and carries no hand-written change.
Drop this commit if dev regenerates first.
danny-avila pushed a commit that referenced this pull request Sep 16, 2026
…ns` (#16029)

Regenerates packages/api/openapi/agents.openapi.json from the code so
openapi:check passes again. #16008 added repositoryInstructions to the
agent schema and merged before #15928, whose committed spec was
generated from a branch that predated the field, leaving dev red.

Co-authored-by: Lia <lia@librechat.ai>
danny-avila added a commit that referenced this pull request Sep 17, 2026
* fix: Serialize MCP OAuth token refresh across replicas

`MCPTokenStorage.inflightRefreshes` coalesces refresh-token redemptions
inside one Node process. Behind a load balancer without session affinity,
one user's concurrent requests land on different replicas, each reads the
same not-yet-rotated refresh token and redeems it. RFC 9700 servers treat
the second redemption as replay and revoke the whole grant family, so the
user is asked to authorize the MCP server again.

`forceRefreshTokens` now takes a cross-replica refresh flight before
redeeming, using the same `FlowStateManager.acquireLease` primitive the
OAuth teardown fence uses under a distinct key. A replica that waited for
the flight adopts the tokens the holder rotated instead of redeeming
again; when the flight is still held after the wait window it falls back
to the unfenced redemption every earlier release performed.

* fix: Redeem unfenced when the refresh flight lease store fails

* fix: Fence MCP refresh waiters instead of redeeming unfenced

A waiter that could not take the cross-replica refresh flight fell through to
an unfenced redemption after 10s, while the holder's own stale abort does not
fire until 60s. A refresh taking 11 to 60 seconds therefore still let two
replicas redeem one refresh token, the replay this fence exists to prevent.

The waiter now polls until it either adopts the tokens the holder rotated or
acquires the flight, and fails as MCPTokenRefreshUnavailableError rather than
redeeming beside a live holder. `getTokens` callers defer connection recovery
on that error, and the stored credential is left intact for a later attempt.

The flight is keyed by the stored credential (tenant, user, server name)
rather than the caller's OAuth binding digest, so a rolling config change
cannot hand two replicas different locks over one stored token. The wait is
an operator lever, `oauthRefreshWaitTimeout`, clamped to half the stale
window. An adoption read that fails no longer gives up the held flight.

* fix: Annotate derived refresh-flight constants for isolatedDeclarations

* fix: Recapture the credential generation a peer published on adoption

* fix: Hold the MCP refresh flight until redemption settles

Four corrections to the cross-replica refresh flight.

The flight lease equalled the window that aborts a stalled redemption, on
the claim that an expired flight could never belong to a redemption still
able to reach the token endpoint. Aborting proves no such thing: the
request may have been processed with its response lost, and a stalled
event loop can delay the abort past its own deadline. The lease now
outlives the abort, so a peer cannot redeem a credential the provider has
already rotated. A live replica still releases on settle, so the margin is
paid only by one that died holding the flight.

The credential snapshot was taken after the first failed acquisition, so a
holder that stored and released in that gap was snapshotted post-rotation:
the next attempt saw an unchanged record and redeemed the credential it
should have adopted. It is taken before the first attempt now.

`oauthRefreshWaitTimeout` accepted zero while the runtime mapped every
non-positive value to the default, so the config validated and then
behaved contrary to its value. Zero is rejected at load.

Adoption announced a second credential change through
`handleOAuthRefreshSuccess`, whose `onOAuthCredentialsChanged` advances
authorization state after persistence this replica did not perform. That
retired the generation recaptured beside it and fenced the build against
its own tool publication. Adoption now updates the local token-flow cache
and recaptures, without announcing.

* fix: Check every held MCP refresh flight for a peer's rotation

Four corrections, two of them consequences of moving the credential
observation ahead of the first lease attempt.

That move created a storage read inside `beginRefreshFlight`, and its
failure reached a handler written for a lease-store outage, so a transient
read error became an unfenced redemption beside a live peer. The flight
now handles its own reads: losing the observation costs adoption and
nothing else, and only the lease store failing may redeem unfenced.

The observation was also never compared when the first acquisition
succeeded. A peer that rotated and released before this replica contended
left an acquisition that looked uncontended, and its fresh credential was
redeemed a second time. Every acquisition now runs one rotation check,
which also collapses two code paths into one.

`getTokens` already loads the refresh record to decide a refresh is
needed, so it is passed on as the observation baseline instead of read
again, and the read taken under the flight is reused as the credential
redeemed. Two reads on a latency-counted path where there were three.

`runSilentRefresh` collapsed contention into null, sending the 401 path to
interactive OAuth, so a slow peer prompted the user to authorize a server
whose credential was about to be valid. The retryable outcome now travels
through the silent-refresh layers and the connection defers, matched by
name as well as identity because these errors cross the package boundary.

* chore: Regenerate the Agents OpenAPI spec for repositoryInstructions

The drift check added by #15928 fails on dev: #16008 added
`repositoryInstructions` to the agent schema without regenerating the
committed spec, so every branch merging dev inherits the failure. This is
the remedy the check itself prescribes and carries no hand-written change.
Drop this commit if dev regenerates first.

* fix: preserve MCP refresh outcomes across replica boundaries

* fix: keep MCP adoption fenced through publication

* fix: anchor MCP refresh adoption to rejected credentials

* fix: Complete OAuth Adoption Adapters and Isolate Legacy Flow Readers

* fix: Preserve OAuth Request Identity Through Recovery and Discovery

* fix: Fence OAuth Adoption Against All Credential Writers

* fix: Gate Coordinated OAuth Rollout and Preserve Unauthenticated Identity

* fix: Preserve OAuth Coalescing Across the Staged Rollout

* style: Sort OAuth Timeout Constant Import

* fix: Invalidate Both OAuth Token Flow Protocols on Rotation

* test: Complete the Rollback Token Flow Fixture

---------

Co-authored-by: Lia <lia@librechat.ai>
Co-authored-by: Danny Avila <danny@librechat.ai>
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