Root Cause
getAwxClient() in packages/awx/src/index.ts returns undefined because input.client.getSecret?.("awx") always returns undefined at runtime.
Evidence
Discovered via diagnostic tool (awx-diagnose) showing:
- ✅
options.baseUrl: "https://aap.tanscloud-internal.com" (configured correctly — server passes tuple options)
- ❌
client.getSecret: does not exist (typeof: undefined)
The getSecret method is purely a TypeScript type augmentation in packages/awx/src/opencode-augment.d.ts:
declare module '@opencode-ai/sdk' {
interface OpencodeClient {
getSecret?(key: string): Promise<string | undefined>;
}
}
This augmentation:
- Is NOT in the OpenCode SDK types or runtime
- Is NOT in the OpenCode server binary
- Does NOT ship in the published npm package (
files: ["dist/**", ...] excludes src/)
- Has ZERO matches searching the entire
@opencode-ai SDK packages
When the ?. optional chain calls a non-existent method, it silently returns undefined,
causing getAwxClient() to fail at guard 2 (if (!token) return undefined).
AuthHook.loader — The Correct API
The OpenCode plugin SDK defines AuthHook.loader as the mechanism for retrieving stored provider credentials:
type AuthHook = {
provider: string;
loader?: (auth: () => Promise<Auth>, provider: Provider) => Promise<Record<string, any>>;
methods: [...];
};
Where Auth for type: "api" is:
{ type: "api"; key: string; metadata?: Record<string, string> }
So await auth() returns { type: "api", key: "<PAT>" } — the stored bearer token.
Open Questions (Need Verification)
- Does the OpenCode binary (v1.17.4) actually invoke
loader at plugin load time?
- What does the
Record<string, any> return value get merged into?
- Does
loader work without a prior authorize() having completed?
Files Involved
packages/awx/src/index.ts — getAwxClient() and server() entry point
packages/awx/src/auth.ts — createAwxAuthHook() needs loader added
packages/awx/src/opencode-augment.d.ts — fictional getSecret declaration (may be removed)
packages/awx/src/diagnose.ts — diagnostic tool (already created)
Suggested Fix Approach
- Modify
createAwxAuthHook() to accept a token callback
- Add
loader that captures await auth().key into a module-level variable
- Replace
input.client.getSecret?.("awx") with that variable in getAwxClient()
- Verify: restart OpenCode, run AWX tools
Root Cause
getAwxClient()inpackages/awx/src/index.tsreturnsundefinedbecauseinput.client.getSecret?.("awx")always returnsundefinedat runtime.Evidence
Discovered via diagnostic tool (
awx-diagnose) showing:options.baseUrl:"https://aap.tanscloud-internal.com"(configured correctly — server passes tuple options)client.getSecret: does not exist (typeof: undefined)The
getSecretmethod is purely a TypeScript type augmentation inpackages/awx/src/opencode-augment.d.ts:This augmentation:
files: ["dist/**", ...]excludes src/)@opencode-aiSDK packagesWhen the
?.optional chain calls a non-existent method, it silently returnsundefined,causing
getAwxClient()to fail at guard 2 (if (!token) return undefined).AuthHook.loader — The Correct API
The OpenCode plugin SDK defines
AuthHook.loaderas the mechanism for retrieving stored provider credentials:Where
Authfortype: "api"is:So
await auth()returns{ type: "api", key: "<PAT>" }— the stored bearer token.Open Questions (Need Verification)
loaderat plugin load time?Record<string, any>return value get merged into?loaderwork without a priorauthorize()having completed?Files Involved
packages/awx/src/index.ts—getAwxClient()andserver()entry pointpackages/awx/src/auth.ts—createAwxAuthHook()needsloaderaddedpackages/awx/src/opencode-augment.d.ts— fictionalgetSecretdeclaration (may be removed)packages/awx/src/diagnose.ts— diagnostic tool (already created)Suggested Fix Approach
createAwxAuthHook()to accept a token callbackloaderthat capturesawait auth().keyinto a module-level variableinput.client.getSecret?.("awx")with that variable ingetAwxClient()