opencode-claude-tailguard 0.0.0 → 0.0.1-alpha.8
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 +14 -8
- package/dist/logger.d.ts +9 -2
- package/dist/logger.js +19 -7
- package/dist/transform.js +2 -2
- package/dist/transform.test.js +2 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
# opencode-claude-tailguard
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
An [OpenCode](https://opencode.ai) plugin that prevents `This model does not support assistant message prefill.` errors caused by the deprecated assistant message prefill in Claude Opus 4.6, Sonnet 4.6.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
Due to a bug in OpenCode, the conversation array can end with an assistant message, which the Claude 4.6 API rejects. This plugin fixes the message array before it is sent to the API.
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
`~/.config/opencode/opencode.json`:
|
|
10
10
|
|
|
11
|
-
```
|
|
12
|
-
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"plugins": [
|
|
14
|
+
"opencode-claude-tailguard",
|
|
15
|
+
]
|
|
16
|
+
}
|
|
13
17
|
```
|
|
14
18
|
|
|
15
|
-
|
|
19
|
+
## Notes
|
|
20
|
+
|
|
21
|
+
The transformation is applied only when a Claude 4.6 model is in use. Other models are not affected.
|
package/dist/logger.d.ts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
export
|
|
1
|
+
export interface Logger {
|
|
2
2
|
log(...args: unknown[]): void;
|
|
3
|
-
}
|
|
3
|
+
}
|
|
4
|
+
interface LoggerOptions {
|
|
5
|
+
stderr: boolean;
|
|
6
|
+
logfile: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function createLogger(options?: Partial<LoggerOptions>): Promise<Logger>;
|
|
9
|
+
export declare const logger: Logger;
|
|
10
|
+
export {};
|
package/dist/logger.js
CHANGED
|
@@ -1,25 +1,37 @@
|
|
|
1
1
|
import { createWriteStream } from "fs";
|
|
2
|
+
import { lstat, mkdir } from "fs/promises";
|
|
2
3
|
import { homedir } from "os";
|
|
3
|
-
import { join } from "path";
|
|
4
|
+
import { dirname, join } from "path";
|
|
4
5
|
import { stdout } from "process";
|
|
5
6
|
const defaultLogPath = join(homedir(), ".local", "share", "opencode", "claude-tailguard-plugin.log");
|
|
6
|
-
function
|
|
7
|
+
async function createStream(path) {
|
|
8
|
+
try {
|
|
9
|
+
const dirPath = dirname(path);
|
|
10
|
+
if (!(await lstat(dirPath)).isDirectory()) {
|
|
11
|
+
await mkdir(dirPath, { recursive: true });
|
|
12
|
+
}
|
|
13
|
+
return createWriteStream(path, { flush: true });
|
|
14
|
+
}
|
|
15
|
+
finally {
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export async function createLogger(options) {
|
|
7
19
|
const combinedOptions = {
|
|
8
20
|
stderr: true,
|
|
9
21
|
logfile: defaultLogPath,
|
|
10
22
|
...options,
|
|
11
23
|
};
|
|
12
24
|
const stream = combinedOptions.logfile
|
|
13
|
-
?
|
|
25
|
+
? await createStream(combinedOptions.logfile)
|
|
14
26
|
: null;
|
|
15
27
|
return {
|
|
16
28
|
log(...args) {
|
|
17
|
-
const line = `[${new Date().toISOString()}] ${args.join(
|
|
29
|
+
const line = `[${new Date().toISOString()}] ${args.join(" ")}\n`;
|
|
18
30
|
if (combinedOptions.stderr)
|
|
19
31
|
stdout.write(line);
|
|
20
|
-
if (stream)
|
|
32
|
+
if (combinedOptions.logfile && stream)
|
|
21
33
|
stream.write(line);
|
|
22
|
-
}
|
|
34
|
+
},
|
|
23
35
|
};
|
|
24
36
|
}
|
|
25
|
-
export const logger = createLogger();
|
|
37
|
+
export const logger = await createLogger();
|
package/dist/transform.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { logger } from "./logger";
|
|
2
|
-
// Matches Claude 4.
|
|
2
|
+
// Matches Claude 4.6 variants where prefill is not supported
|
|
3
3
|
// Handles separators: -, ., _ between major.minor version
|
|
4
|
-
const TARGET_PATTERN = /claude-(opus|sonnet
|
|
4
|
+
const TARGET_PATTERN = /claude-(opus|sonnet)-4[._-]6/;
|
|
5
5
|
export function isTargetModel(modelID) {
|
|
6
6
|
return TARGET_PATTERN.test(modelID);
|
|
7
7
|
}
|
package/dist/transform.test.js
CHANGED
|
@@ -111,10 +111,10 @@ describe("isTargetModel", () => {
|
|
|
111
111
|
expect(isTargetModel("claude-sonnet-4-6")).toBe(true);
|
|
112
112
|
});
|
|
113
113
|
test("matches claude-haiku-4-5", () => {
|
|
114
|
-
expect(isTargetModel("claude-haiku-4-5")).toBe(
|
|
114
|
+
expect(isTargetModel("claude-haiku-4-5")).toBe(false);
|
|
115
115
|
});
|
|
116
116
|
test("matches claude-sonnet-4.5", () => {
|
|
117
|
-
expect(isTargetModel("claude-sonnet-4.5")).toBe(
|
|
117
|
+
expect(isTargetModel("claude-sonnet-4.5")).toBe(false);
|
|
118
118
|
});
|
|
119
119
|
test("does not match claude-3-opus", () => {
|
|
120
120
|
expect(isTargetModel("claude-3-opus")).toBe(false);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-claude-tailguard",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.1-alpha.8",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"opencode",
|
|
6
6
|
"plugin"
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
},
|
|
14
14
|
"repository": {
|
|
15
15
|
"type": "git",
|
|
16
|
-
"url": "https://github.com/pycabbage/opencode-claude-tailguard
|
|
16
|
+
"url": "git+https://github.com/pycabbage/opencode-claude-tailguard.git"
|
|
17
17
|
},
|
|
18
18
|
"files": [
|
|
19
19
|
"dist/**/*"
|