@alisio/plugin-opencode-go 0.1.0-alpha.2 → 0.1.0-alpha.6
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/dist/index.js +2 -1
- package/dist/provider.js +69 -6
- package/dist/version.d.ts +8 -0
- package/dist/version.js +28 -0
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { definePlugin } from "@alisio/sdk";
|
|
2
2
|
import { OpenCodeGoProvider } from "./provider.js";
|
|
3
|
+
import { loadVersion } from "./version.js";
|
|
3
4
|
const profileString = (request, key) => typeof request.profile[key] === "string" ? String(request.profile[key]) : "";
|
|
4
5
|
export function createOpenCodeGoPlugin() {
|
|
5
6
|
return definePlugin({
|
|
@@ -7,7 +8,7 @@ export function createOpenCodeGoPlugin() {
|
|
|
7
8
|
name: "OpenCode Go",
|
|
8
9
|
description: "OpenCode Go multi-protocol model gateway",
|
|
9
10
|
categories: ["model-provider"],
|
|
10
|
-
version:
|
|
11
|
+
version: loadVersion(import.meta.url),
|
|
11
12
|
apiVersion: 1,
|
|
12
13
|
setup(api) {
|
|
13
14
|
api.providers.register({
|
package/dist/provider.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { loadVersion } from "./version.js";
|
|
1
2
|
const protocolMap = (groups) => new Map(Object.entries(groups).flatMap(([protocol, models]) => (models ?? []).map((model) => [model, protocol])));
|
|
2
3
|
const GO_MODELS = protocolMap({
|
|
3
4
|
responses: [
|
|
@@ -48,6 +49,8 @@ export function classifyOpenCodeGoModel(id) {
|
|
|
48
49
|
}
|
|
49
50
|
const dataUrl = (a) => `data:${a.mimeType};base64,${a.data}`;
|
|
50
51
|
const modelId = (id) => id.replace(/^opencode(?:-go)?\//, "");
|
|
52
|
+
/** Default user agent derives from the package manifest at runtime; never a hardcoded version. */
|
|
53
|
+
const DEFAULT_USER_AGENT = `alisio/${loadVersion(import.meta.url)}`;
|
|
51
54
|
async function* sse(response) {
|
|
52
55
|
if (!response.ok)
|
|
53
56
|
throw new Error(`OpenCode request failed: HTTP ${response.status}`);
|
|
@@ -134,7 +137,7 @@ export class OpenCodeGatewayProvider {
|
|
|
134
137
|
this.displayName = "OpenCode Go";
|
|
135
138
|
this.classify = config.classify;
|
|
136
139
|
this.baseURL = config.baseURL.replace(/\/$/, "");
|
|
137
|
-
this.userAgent = config.userAgent ??
|
|
140
|
+
this.userAgent = config.userAgent ?? DEFAULT_USER_AGENT;
|
|
138
141
|
const url = new URL(this.baseURL);
|
|
139
142
|
if (url.protocol !== "https:" && url.hostname !== "127.0.0.1" && url.hostname !== "localhost")
|
|
140
143
|
throw new Error("OpenCode base URL must use HTTPS");
|
|
@@ -256,12 +259,23 @@ export class OpenCodeGatewayProvider {
|
|
|
256
259
|
if (choice.finish_reason)
|
|
257
260
|
finish = choice.finish_reason;
|
|
258
261
|
}
|
|
259
|
-
if (finish !== "stop" && finish !== "tool_calls")
|
|
262
|
+
if (finish !== "stop" && finish !== "tool_calls" && finish !== "length")
|
|
260
263
|
throw new Error(`OpenCode chat response incomplete: ${finish ?? "stream ended"}`);
|
|
261
264
|
const completed = [...calls.entries()].sort(([a], [b]) => a - b).map(([, call]) => call);
|
|
262
265
|
if (completed.some((call) => !call.id || !call.name))
|
|
263
266
|
throw new Error("Incomplete tool call");
|
|
264
|
-
|
|
267
|
+
if (finish === "length" && !text.trim())
|
|
268
|
+
throw new Error("OpenCode chat response cut off by max output tokens before any usable content; raise limits.maxOutputTokens");
|
|
269
|
+
yield {
|
|
270
|
+
type: "completed",
|
|
271
|
+
message: {
|
|
272
|
+
role: "assistant",
|
|
273
|
+
text,
|
|
274
|
+
calls: completed,
|
|
275
|
+
...(finish === "length" ? { truncated: true } : {}),
|
|
276
|
+
},
|
|
277
|
+
usage,
|
|
278
|
+
};
|
|
265
279
|
}
|
|
266
280
|
responsesInput(messages) {
|
|
267
281
|
const input = [];
|
|
@@ -312,8 +326,39 @@ export class OpenCodeGatewayProvider {
|
|
|
312
326
|
yield { type: "text_delta", delta: event.delta };
|
|
313
327
|
if (event.type === "response.reasoning_summary_text.delta")
|
|
314
328
|
yield { type: "reasoning_delta", delta: event.delta };
|
|
315
|
-
if (["response.failed", "
|
|
329
|
+
if (["response.failed", "error"].includes(event.type))
|
|
316
330
|
throw new Error(`OpenCode Responses request failed: ${event.type}`);
|
|
331
|
+
if (event.type === "response.incomplete") {
|
|
332
|
+
complete = true;
|
|
333
|
+
const output = event.response.output;
|
|
334
|
+
const calls = output
|
|
335
|
+
.filter((item) => item.type === "function_call")
|
|
336
|
+
.map((item) => ({ id: item.call_id, name: item.name, arguments: item.arguments }));
|
|
337
|
+
const text = output
|
|
338
|
+
.filter((item) => item.type === "message")
|
|
339
|
+
.flatMap((item) => item.content ?? [])
|
|
340
|
+
.filter((item) => item.type === "output_text")
|
|
341
|
+
.map((item) => item.text)
|
|
342
|
+
.join("");
|
|
343
|
+
if (!text.trim())
|
|
344
|
+
throw new Error("OpenCode Responses response cut off by max output tokens before any usable content; raise limits.maxOutputTokens");
|
|
345
|
+
if (calls.some((call) => !call.id || !call.name))
|
|
346
|
+
throw new Error("Incomplete tool call");
|
|
347
|
+
const u = event.response.usage;
|
|
348
|
+
yield {
|
|
349
|
+
type: "completed",
|
|
350
|
+
message: { role: "assistant", text, calls, providerData: output, truncated: true },
|
|
351
|
+
usage: u
|
|
352
|
+
? {
|
|
353
|
+
input: u.input_tokens ?? 0,
|
|
354
|
+
output: u.output_tokens ?? 0,
|
|
355
|
+
...(typeof u.input_tokens_details?.cached_tokens === "number"
|
|
356
|
+
? { cachedInput: u.input_tokens_details.cached_tokens }
|
|
357
|
+
: {}),
|
|
358
|
+
}
|
|
359
|
+
: undefined,
|
|
360
|
+
};
|
|
361
|
+
}
|
|
317
362
|
if (event.type === "response.completed") {
|
|
318
363
|
complete = true;
|
|
319
364
|
const output = event.response.output;
|
|
@@ -456,7 +501,8 @@ export class OpenCodeGatewayProvider {
|
|
|
456
501
|
stopReason = event.delta?.stop_reason ?? stopReason;
|
|
457
502
|
}
|
|
458
503
|
}
|
|
459
|
-
|
|
504
|
+
const truncated = stopReason === "max_tokens";
|
|
505
|
+
if (!truncated && stopReason !== "end_turn" && stopReason !== "tool_use")
|
|
460
506
|
throw new Error(`OpenCode Messages response incomplete: ${stopReason ?? "stream ended"}`);
|
|
461
507
|
const calls = [];
|
|
462
508
|
for (let index = 0; index < blocks.length; index++) {
|
|
@@ -465,7 +511,24 @@ export class OpenCodeGatewayProvider {
|
|
|
465
511
|
continue;
|
|
466
512
|
const args = argumentParts.get(index) || JSON.stringify(block.input ?? {});
|
|
467
513
|
calls.push({ id: block.id, name: block.name, arguments: args });
|
|
468
|
-
|
|
514
|
+
try {
|
|
515
|
+
block.input = JSON.parse(args || "{}");
|
|
516
|
+
}
|
|
517
|
+
catch {
|
|
518
|
+
if (!truncated)
|
|
519
|
+
throw new Error("Incomplete tool call");
|
|
520
|
+
throw new Error(`OpenCode Messages response incomplete: tool call arguments cut off for ${block.name}`);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
if (truncated) {
|
|
524
|
+
if (!text.trim())
|
|
525
|
+
throw new Error("OpenCode Messages response cut off by max output tokens before any usable content; raise limits.maxOutputTokens");
|
|
526
|
+
yield {
|
|
527
|
+
type: "completed",
|
|
528
|
+
message: { role: "assistant", text, calls, providerData: blocks, truncated: true },
|
|
529
|
+
usage: { input, output },
|
|
530
|
+
};
|
|
531
|
+
return;
|
|
469
532
|
}
|
|
470
533
|
yield {
|
|
471
534
|
type: "completed",
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads this plugin package's version at runtime so plugin metadata, user-agent defaults and CLI
|
|
3
|
+
* reports stay in sync with the published package without a build-time constant to update.
|
|
4
|
+
* The manifest is resolved relative to the module (`src/version.ts` → `../package.json` in the
|
|
5
|
+
* source tree; `dist/version.js` → `../package.json` of the installed package). Standalone
|
|
6
|
+
* binaries inject the version at build time via ALISIO_PACKAGE_VERSION (scripts/binary-build.ts).
|
|
7
|
+
*/
|
|
8
|
+
export declare function loadVersion(fromHere: string): string;
|
package/dist/version.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
/**
|
|
5
|
+
* Fallback used when neither the build-time injection nor the package manifest is readable
|
|
6
|
+
* (e.g. an unpackaged embed). Keep it a development marker, never a publish literal, so it
|
|
7
|
+
* cannot silently desync from the published package.
|
|
8
|
+
*/
|
|
9
|
+
const FALLBACK = "dev";
|
|
10
|
+
/**
|
|
11
|
+
* Reads this plugin package's version at runtime so plugin metadata, user-agent defaults and CLI
|
|
12
|
+
* reports stay in sync with the published package without a build-time constant to update.
|
|
13
|
+
* The manifest is resolved relative to the module (`src/version.ts` → `../package.json` in the
|
|
14
|
+
* source tree; `dist/version.js` → `../package.json` of the installed package). Standalone
|
|
15
|
+
* binaries inject the version at build time via ALISIO_PACKAGE_VERSION (scripts/binary-build.ts).
|
|
16
|
+
*/
|
|
17
|
+
export function loadVersion(fromHere) {
|
|
18
|
+
if (process.env.ALISIO_PACKAGE_VERSION)
|
|
19
|
+
return process.env.ALISIO_PACKAGE_VERSION;
|
|
20
|
+
try {
|
|
21
|
+
const manifest = join(dirname(fileURLToPath(fromHere)), "..", "package.json");
|
|
22
|
+
const parsed = JSON.parse(readFileSync(manifest, "utf8"));
|
|
23
|
+
return typeof parsed.version === "string" && parsed.version ? parsed.version : FALLBACK;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return FALLBACK;
|
|
27
|
+
}
|
|
28
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alisio/plugin-opencode-go",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.6",
|
|
4
4
|
"description": "Built-in OpenCode Go model provider for Alisio.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -21,10 +21,10 @@
|
|
|
21
21
|
"node": ">=22.16"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|
|
24
|
-
"@alisio/sdk": "^0.1.0-alpha.
|
|
24
|
+
"@alisio/sdk": "^0.1.0-alpha.5"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
|
-
"@alisio/sdk": "0.1.0-alpha.
|
|
27
|
+
"@alisio/sdk": "0.1.0-alpha.5"
|
|
28
28
|
},
|
|
29
29
|
"publishConfig": {
|
|
30
30
|
"access": "public",
|