dsh-opencode 0.1.0 → 0.1.1
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 +2 -2
- package/lib/commands.js +43 -18
- package/lib/index.js +5 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -57,12 +57,12 @@ Refreshes run single-flight per source (Models.dev once for both products) with
|
|
|
57
57
|
|
|
58
58
|
| Command | Effect |
|
|
59
59
|
|---|---|
|
|
60
|
-
| `/dsh-opencode` |
|
|
60
|
+
| `/dsh-opencode [<api-key>]` | Store the API key securely and enable Zen/Go immediately; with no argument, checks status and guides setup |
|
|
61
61
|
| `/opencode-refresh [all\|zen\|go]` | Force a catalog refresh (joins in-flight fetches) |
|
|
62
62
|
| `/opencode-status` | Freshness, per-source errors, ready/pending counts, credential presence |
|
|
63
63
|
| `/opencode-models <zen\|go> [--all]` | Ready models, or every candidate with its state and reason |
|
|
64
64
|
|
|
65
|
-
None of these commands displays key values or fragments, and none registers a model-visible tool.
|
|
65
|
+
None of these commands displays key values or fragments, and none registers a model-visible tool. `/dsh-opencode` accepts the key only as its single argument and writes it through the DSH credential seam (`recordInput: false` keeps it out of session logs); it never echoes the value back.
|
|
66
66
|
|
|
67
67
|
## Configuration
|
|
68
68
|
|
package/lib/commands.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { PRODUCT_BY_ROUTE, ROUTE_BY_PRODUCT, describeNonReadyState } from "./normalize.js";
|
|
2
|
+
import { assertUsableApiKey } from "@deepseek-ai/dsh-llm";
|
|
2
3
|
//#region src/commands.ts
|
|
3
4
|
const USAGE_REFRESH = "Usage: /opencode-refresh [all|zen|go]";
|
|
4
5
|
const USAGE_MODELS = "Usage: /opencode-models <zen|go> [--all]";
|
|
5
|
-
const USAGE_ENABLE = "Usage: /dsh-opencode — never pass the API key in the command line";
|
|
6
6
|
/** Whether one date stamp renders as a short local time. */
|
|
7
7
|
function renderTime(timestamp) {
|
|
8
8
|
if (timestamp === void 0) return "never";
|
|
@@ -37,6 +37,10 @@ function parseProduct(raw) {
|
|
|
37
37
|
if (raw === "zen") return "zen";
|
|
38
38
|
if (raw === "go") return "go";
|
|
39
39
|
}
|
|
40
|
+
/** Distinct credential references across the configured routes. */
|
|
41
|
+
function configuredRefs(services) {
|
|
42
|
+
return [...new Set([...services.config().providers.values()].map((provider) => provider.apiKeyEnv))];
|
|
43
|
+
}
|
|
40
44
|
/** Build the three command definitions. */
|
|
41
45
|
function commandDefinitions(ctx, services) {
|
|
42
46
|
return [
|
|
@@ -130,25 +134,46 @@ function commandDefinitions(ctx, services) {
|
|
|
130
134
|
},
|
|
131
135
|
{
|
|
132
136
|
name: "dsh-opencode",
|
|
133
|
-
description: "
|
|
137
|
+
description: "Store the OpenCode API key and enable Zen/Go immediately",
|
|
134
138
|
recordInput: false,
|
|
135
139
|
handler: async (invocation) => {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
+
const raw = invocation.rawInput.trim();
|
|
141
|
+
let stored = false;
|
|
142
|
+
if (raw.length > 0) {
|
|
143
|
+
try {
|
|
144
|
+
assertUsableApiKey(raw, "opencode-live", "input");
|
|
145
|
+
} catch (error) {
|
|
146
|
+
return {
|
|
147
|
+
kind: "error",
|
|
148
|
+
text: error.message
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
const failures = [];
|
|
152
|
+
for (const ref of configuredRefs(services)) try {
|
|
153
|
+
await services.storeCredential(ref, raw);
|
|
154
|
+
} catch (error) {
|
|
155
|
+
failures.push(`${ref}: ${error.message}`);
|
|
156
|
+
}
|
|
157
|
+
if (failures.length > 0) return {
|
|
158
|
+
kind: "error",
|
|
159
|
+
text: ["Could not store the OpenCode API key:", ...failures].join("\n")
|
|
160
|
+
};
|
|
161
|
+
stored = true;
|
|
162
|
+
}
|
|
140
163
|
const routes = [ROUTE_BY_PRODUCT.zen, ROUTE_BY_PRODUCT.go];
|
|
141
|
-
if (!
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
164
|
+
if (!stored) {
|
|
165
|
+
if (!(await Promise.all(routes.map(async (route) => {
|
|
166
|
+
return (await services.describeCredential(route))?.configured === true;
|
|
167
|
+
}))).some((configured) => configured)) return {
|
|
168
|
+
kind: "success",
|
|
169
|
+
text: [
|
|
170
|
+
"No OpenCode API key is configured yet.",
|
|
171
|
+
"Run /dsh-opencode <your-api-key> to store it securely and enable both routes at once,",
|
|
172
|
+
"or store it through the standard credentials input (the web Models page writes it) and run /dsh-opencode again.",
|
|
173
|
+
"This command never displays key values."
|
|
174
|
+
].join("\n")
|
|
175
|
+
};
|
|
176
|
+
}
|
|
152
177
|
if (invocation.signal.aborted) return {
|
|
153
178
|
kind: "success",
|
|
154
179
|
text: "Refresh cancelled."
|
|
@@ -159,7 +184,7 @@ function commandDefinitions(ctx, services) {
|
|
|
159
184
|
signal: invocation.signal
|
|
160
185
|
});
|
|
161
186
|
} catch {}
|
|
162
|
-
const lines = ["OpenCode API key configured. Zen and Go are enabled:"];
|
|
187
|
+
const lines = [stored ? "OpenCode API key stored. Zen and Go are enabled:" : "OpenCode API key configured. Zen and Go are enabled:"];
|
|
163
188
|
for (const route of routes) lines.push(await productStatus(ctx, services, PRODUCT_BY_ROUTE[route]));
|
|
164
189
|
return {
|
|
165
190
|
kind: "success",
|
package/lib/index.js
CHANGED
|
@@ -154,6 +154,11 @@ function apply(ctx, config = {}) {
|
|
|
154
154
|
const provider = currentConfig.providers.get(route);
|
|
155
155
|
if (provider === void 0) return void 0;
|
|
156
156
|
return describeCredential(ctx, provider.apiKeyEnv);
|
|
157
|
+
},
|
|
158
|
+
storeCredential: async (ref, value) => {
|
|
159
|
+
const credentials = ctx.get("credentials");
|
|
160
|
+
if (credentials === void 0) throw new Error("opencode-live: no credentials service is mounted; export the API key in the launch environment instead");
|
|
161
|
+
await credentials.set(ref, value);
|
|
157
162
|
}
|
|
158
163
|
});
|
|
159
164
|
});
|