Files
open-design-crew[bot] 4d0376e437 fix(byok): restore local runtime configuration (#6356)
* fix(byok): restore local runtime configuration

Return BYOK settings to the browser-local configuration path and pass credentials only to the active OpenCode child run.

Remove the unpublished secure-profile migration, credential backends, API, CLI, contracts, and MCP exposure while retaining raw-secret rejection on external MCP calls.

Validated with focused web and daemon suites, full web tests, workspace typecheck, guard, and diff checks.

* test(e2e): align BYOK settings checks with local storage

Update the settings UI contract after rolling BYOK credentials back to local app config storage. Assert the entered key is persisted, keep incomplete BYOK drafts from activating, and seed the Local CLI isolation case with a usable BYOK key.

Validated with all seven P0 cases in settings-api-protocol.test.ts and the e2e TypeScript check.

* fix(daemon): validate plugin request ids explicitly

Use a field-specific canonical UUID/ULID validator for attributed request IDs and document that format in the MCP schema and server instructions. Invalid calls now identify requestId instead of incorrectly blaming pluginWorkflowId, while Codex can generate a valid ID on its first attempt.

Validated with a red/green MCP observability regression test, daemon typecheck, repository guard, and a real Local Codex plugin smoke that completed in one start_run attempt.

* test(pack): follow active PTY consumer in prebundle coverage

Point the macOS prebundle boundary test at the Terminal runtime after the retired BYOK credential service was removed. This keeps native node-pty externalization covered without restoring legacy credential code.

Validated with the focused mac-prebundle suite, the complete tools-pack suite, tools-pack typechecks, repository guard, and deleted-file reference scans.

---------

Co-authored-by: Cheems <94773058+itscheems@users.noreply.github.com>
2026-08-03 09:40:31 +00:00

76 lines
2.3 KiB
TypeScript

import fs from 'node:fs';
import { createRequire } from 'node:module';
import path from 'node:path';
import type * as NodePty from 'node-pty';
const NODE_PTY_UNAVAILABLE_CODE = 'NODE_PTY_UNAVAILABLE';
export class NodePtyUnavailableError extends Error {
readonly code = NODE_PTY_UNAVAILABLE_CODE;
constructor(cause: unknown) {
super('The native PTY helper could not be loaded.', { cause });
this.name = 'NodePtyUnavailableError';
}
}
export function isNodePtyUnavailableError(error: unknown): error is NodePtyUnavailableError {
return error instanceof NodePtyUnavailableError
|| (
error instanceof Error
&& 'code' in error
&& error.code === NODE_PTY_UNAVAILABLE_CODE
);
}
/**
* Resolve node-pty's POSIX spawn-helper candidates without importing its
* native addon. The lookup keeps Terminal users on the package-relative
* runtime boundary used by the packaged app.
*/
export function spawnHelperCandidatePaths(): string[] {
if (process.platform === 'win32') return [];
let packageRoot: string;
try {
const require = createRequire(import.meta.url);
packageRoot = path.dirname(path.dirname(require.resolve('node-pty')));
} catch {
return [];
}
return [
path.join(packageRoot, 'build', 'Release', 'spawn-helper'),
path.join(packageRoot, 'prebuilds', `${process.platform}-${process.arch}`, 'spawn-helper'),
];
}
/**
* npm's published prebuild may unpack spawn-helper without execute bits.
* Repair it before loading node-pty; failure remains best-effort because the
* subsequent import/spawn provides the attributable capability error.
*/
export function ensureSpawnHelperExecutable(): void {
for (const file of spawnHelperCandidatePaths()) {
try {
const metadata = fs.statSync(file);
if (metadata.mode & 0o100) continue;
fs.chmodSync(file, metadata.mode | 0o111);
} catch {
// Missing/read-only candidates are handled by the import or spawn call.
}
}
}
let loadedNodePty: typeof NodePty | null = null;
export async function loadNodePty(): Promise<typeof NodePty> {
if (loadedNodePty != null) return loadedNodePty;
ensureSpawnHelperExecutable();
try {
loadedNodePty = (await import('node-pty')) as typeof NodePty;
return loadedNodePty;
} catch (error) {
throw new NodePtyUnavailableError(error);
}
}