@andoai/opencode 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,12 +5,16 @@ Official Ando Wallet integration for [OpenCode](https://opencode.ai/).
5
5
  ## Install
6
6
 
7
7
  ```sh
8
- opencode plugin --global --force @andoai/opencode@0.2.1
8
+ opencode plugin --global --force @andoai/opencode@0.2.2
9
9
  ```
10
10
 
11
11
  Then run `/connect` in OpenCode, choose **Ando**, and select **Connect Ando Wallet**. Your browser opens
12
12
  `wallet.andoai.xyz`, where you choose an existing open, funded OpenCode session or open a new one.
13
13
 
14
+ The plugin owns the Ando provider implementation, endpoint, and authentication fields. It ignores legacy
15
+ `provider.ando` API-key or authorization-header overrides so the credential saved by `/connect` is always
16
+ used, while preserving unrelated provider options.
17
+
14
18
  The browser returns only a short-lived, single-use authorization code over the IPv4 loopback callback.
15
19
  The plugin redeems that code over HTTPS using an S256 PKCE verifier that never leaves the OpenCode process.
16
20
  The MPP session credential is therefore never placed in the callback URL or submitted from HTTPS to an HTTP
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import { exchangeAuthorizationCode } from "./token-exchange.js";
3
3
  const WALLET_ORIGIN = "https://wallet.andoai.xyz";
4
4
  const INFERENCE_BASE_URL = "https://inference.andoai.xyz/v1/mpp";
5
5
  const MODELS = {
6
- "Ando/Kimi-k2.6": { name: "Kimi K2.6" },
6
+ "Ando/Model-Optimisation": { name: "Model Optimisation" },
7
7
  "Ando/gpt-oss-120b": { name: "GPT OSS 120B" },
8
8
  "ando/nemotron-3-ultra-550b-a55b": { name: "Nemotron 3 Ultra 550B" }
9
9
  };
@@ -12,6 +12,7 @@ export function createAndoOpenCodePlugin(runtime = {}) {
12
12
  const exchangeCode = runtime.exchangeCode ?? exchangeAuthorizationCode;
13
13
  return async () => {
14
14
  const pending = new Set();
15
+ let connectedCredential;
15
16
  return {
16
17
  config: async (config) => configureAndoProvider(config),
17
18
  auth: {
@@ -33,13 +34,15 @@ export function createAndoOpenCodePlugin(runtime = {}) {
33
34
  instructions: "Choose an open, funded OpenCode session in Ando Wallet.",
34
35
  callback: async () => {
35
36
  try {
37
+ const credential = await exchangeCode({
38
+ code: await callback.waitForCode(),
39
+ codeVerifier: callback.codeVerifier
40
+ });
41
+ connectedCredential = credential;
36
42
  return {
37
43
  type: "success",
38
44
  provider: "ando",
39
- key: await exchangeCode({
40
- code: await callback.waitForCode(),
41
- codeVerifier: callback.codeVerifier
42
- })
45
+ key: credential
43
46
  };
44
47
  }
45
48
  catch {
@@ -55,7 +58,13 @@ export function createAndoOpenCodePlugin(runtime = {}) {
55
58
  }
56
59
  ]
57
60
  },
61
+ "chat.headers": async (input, output) => {
62
+ if (input.model.providerID !== "ando" || !connectedCredential)
63
+ return;
64
+ output.headers.Authorization = `Bearer ${connectedCredential}`;
65
+ },
58
66
  dispose: async () => {
67
+ connectedCredential = undefined;
59
68
  const callbacks = Array.from(pending);
60
69
  pending.clear();
61
70
  await Promise.all(callbacks.map((callback) => callback.close()));
@@ -68,18 +77,33 @@ function configureAndoProvider(config) {
68
77
  const current = providers.ando;
69
78
  providers.ando = {
70
79
  ...current,
71
- name: current?.name ?? "Ando",
72
- npm: current?.npm ?? "@ai-sdk/openai-compatible",
80
+ name: "Ando",
81
+ npm: "@ai-sdk/openai-compatible",
73
82
  models: {
74
83
  ...MODELS,
75
84
  ...current?.models
76
85
  },
77
86
  options: {
78
- baseURL: INFERENCE_BASE_URL,
79
- ...current?.options
87
+ ...managedProviderOptions(current?.options),
88
+ baseURL: INFERENCE_BASE_URL
80
89
  }
81
90
  };
82
91
  config.provider = providers;
83
92
  }
93
+ function managedProviderOptions(options) {
94
+ // OpenCode injects the credential from /connect only when config does not provide one.
95
+ return Object.fromEntries(Object.entries(options ?? {}).flatMap(([name, value]) => {
96
+ if (name === "apiKey" || name === "baseURL")
97
+ return [];
98
+ if (name === "headers")
99
+ return [[name, withoutAuthorizationHeader(value)]];
100
+ return [[name, value]];
101
+ }));
102
+ }
103
+ function withoutAuthorizationHeader(value) {
104
+ if (typeof value !== "object" || value === null || Array.isArray(value))
105
+ return value;
106
+ return Object.fromEntries(Object.entries(value).filter(([name]) => name.toLowerCase() !== "authorization"));
107
+ }
84
108
  const AndoOpenCodePlugin = createAndoOpenCodePlugin();
85
109
  export default AndoOpenCodePlugin;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andoai/opencode",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Official Ando Wallet integration for OpenCode",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",