Skip to content

Commit 89d6174

Browse files
fix(runtime): resolve the configured plugin root exactly as written; trim only for the blank check
1 parent 6c901e7 commit 89d6174

2 files changed

Lines changed: 15 additions & 4 deletions

File tree

‎packages/rsc-runtime/src/plugin-root.ts‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,19 +49,20 @@ const defaultWarn = (message: string): void => {
4949
* so `(await agent()).plugin.stateRoot` is by construction the directory the
5050
* kernel, the notice ledger, and the lineage journal use.
5151
*
52-
* `AGENT_BUNDLE_PLUGIN_ROOT` wins when it is set to a non-empty, expanded
53-
* value (`source: 'native'`). An empty value or one still carrying a `${…}`
52+
* `AGENT_BUNDLE_PLUGIN_ROOT` wins when it is set to a non-blank, expanded
53+
* value (`source: 'native'`), taken exactly as written — a path is never
54+
* trimmed. A blank value or one still carrying a `${…}`
5455
* token is treated as unset — the token case is reported once on stderr,
5556
* because it means the host did not expand its manifest — and the shell's
5657
* `fallback` anchors the plugin (`source: 'derived'`). Both roots are made
5758
* absolute against the working directory, as the kernel always did.
5859
*/
5960
export const resolvePluginRoot = (options: ResolvePluginRootOptions): ResolvedPluginRoot => {
6061
const env = options.env ?? process.env;
61-
const declared = env[PLUGIN_ROOT_ENV_ANCHOR]?.trim() ?? '';
62+
const declared = env[PLUGIN_ROOT_ENV_ANCHOR] ?? '';
6263
let root: string;
6364
let source: 'native' | 'derived';
64-
if (declared === '') {
65+
if (declared.trim() === '') {
6566
root = resolve(options.fallback);
6667
source = 'derived';
6768
} else if (unexpandedToken.test(declared)) {
@@ -71,6 +72,8 @@ export const resolvePluginRoot = (options: ResolvePluginRootOptions): ResolvedPl
7172
root = resolve(options.fallback);
7273
source = 'derived';
7374
} else {
75+
// The value is a path: trimming would move the anchor, so only the
76+
// blank check above looks at a trimmed copy.
7477
root = resolve(declared);
7578
source = 'native';
7679
}

‎packages/rsc-runtime/tests/plugin-root.test.ts‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ describe('resolvePluginRoot (#468)', () => {
2020
expect(Object.isFrozen(resolved)).toBe(true);
2121
});
2222

23+
it('takes the configured path exactly as written, whitespace included', () => {
24+
const resolved = resolvePluginRoot({ env: { [PLUGIN_ROOT_ENV_ANCHOR]: '/opt/curator ' }, fallback });
25+
26+
expect(resolved.root).toBe('/opt/curator ');
27+
expect(resolved.stateRoot).toBe(join('/opt/curator ', 'state'));
28+
expect(resolved.source).toBe('native');
29+
});
30+
2331
it('makes a relative anchor absolute against the working directory, as Codex hands "./"', () => {
2432
const resolved = resolvePluginRoot({ env: { [PLUGIN_ROOT_ENV_ANCHOR]: './' }, fallback });
2533

0 commit comments

Comments
 (0)