opencode-qoder 0.1.0
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 +45 -0
- package/dist/auth.d.ts +38 -0
- package/dist/auth.js +175 -0
- package/dist/constants.d.ts +30 -0
- package/dist/constants.js +127 -0
- package/dist/cosy.d.ts +9 -0
- package/dist/cosy.js +114 -0
- package/dist/encoding.d.ts +1 -0
- package/dist/encoding.js +19 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +272 -0
- package/dist/language-model.d.ts +18 -0
- package/dist/language-model.js +539 -0
- package/dist/transform.d.ts +45 -0
- package/dist/transform.js +150 -0
- package/package.json +48 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
function dataContentToUrl(part) {
|
|
2
|
+
if (part.data instanceof URL)
|
|
3
|
+
return part.data.toString();
|
|
4
|
+
if (typeof part.data === "string") {
|
|
5
|
+
if (/^(https?:|data:)/i.test(part.data))
|
|
6
|
+
return part.data;
|
|
7
|
+
return `data:${part.mediaType};base64,${part.data}`;
|
|
8
|
+
}
|
|
9
|
+
return `data:${part.mediaType};base64,${Buffer.from(part.data).toString("base64")}`;
|
|
10
|
+
}
|
|
11
|
+
function stringifyToolResultOutput(output) {
|
|
12
|
+
switch (output.type) {
|
|
13
|
+
case "text":
|
|
14
|
+
case "error-text":
|
|
15
|
+
return output.value;
|
|
16
|
+
case "json":
|
|
17
|
+
case "error-json":
|
|
18
|
+
return JSON.stringify(output.value);
|
|
19
|
+
case "execution-denied":
|
|
20
|
+
return output.reason ? `Execution denied: ${output.reason}` : "Execution denied";
|
|
21
|
+
case "content":
|
|
22
|
+
return output.value
|
|
23
|
+
.map((part) => {
|
|
24
|
+
if (part.type === "text")
|
|
25
|
+
return part.text;
|
|
26
|
+
if (part.type === "file-url")
|
|
27
|
+
return part.url;
|
|
28
|
+
if (part.type === "file-id")
|
|
29
|
+
return typeof part.fileId === "string" ? part.fileId : JSON.stringify(part.fileId);
|
|
30
|
+
if (part.type === "image-url")
|
|
31
|
+
return part.url;
|
|
32
|
+
if (part.type === "image-file-id")
|
|
33
|
+
return typeof part.fileId === "string" ? part.fileId : JSON.stringify(part.fileId);
|
|
34
|
+
return "mediaType" in part ? `[${part.mediaType}]` : `[${part.type}]`;
|
|
35
|
+
})
|
|
36
|
+
.join("\n");
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function textFromContent(content) {
|
|
40
|
+
if (!content)
|
|
41
|
+
return "";
|
|
42
|
+
if (typeof content === "string")
|
|
43
|
+
return content;
|
|
44
|
+
return content.map((part) => (part.type === "text" ? part.text : "")).join("");
|
|
45
|
+
}
|
|
46
|
+
function transformUserMessage(message) {
|
|
47
|
+
const parts = [];
|
|
48
|
+
let hasFile = false;
|
|
49
|
+
for (const part of message.content) {
|
|
50
|
+
if (part.type === "text") {
|
|
51
|
+
parts.push({ type: "text", text: part.text });
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (part.type === "file" && part.mediaType.startsWith("image/")) {
|
|
55
|
+
hasFile = true;
|
|
56
|
+
parts.push({ type: "image_url", image_url: { url: dataContentToUrl(part) } });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
role: "user",
|
|
61
|
+
content: hasFile ? parts : parts.map((part) => (part.type === "text" ? part.text : "")).join(""),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function transformAssistantMessage(message) {
|
|
65
|
+
let content = "";
|
|
66
|
+
const toolCalls = [];
|
|
67
|
+
for (const part of message.content) {
|
|
68
|
+
if (part.type === "text")
|
|
69
|
+
content += part.text;
|
|
70
|
+
if (part.type === "reasoning")
|
|
71
|
+
content += `<thinking>${part.text}</thinking>\n\n`;
|
|
72
|
+
if (part.type === "tool-call") {
|
|
73
|
+
toolCalls.push({
|
|
74
|
+
id: part.toolCallId,
|
|
75
|
+
type: "function",
|
|
76
|
+
function: {
|
|
77
|
+
name: part.toolName,
|
|
78
|
+
arguments: typeof part.input === "string" ? part.input : JSON.stringify(part.input),
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const result = { role: "assistant", content: content || null };
|
|
84
|
+
if (toolCalls.length > 0)
|
|
85
|
+
result.tool_calls = toolCalls;
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
function transformToolMessage(message) {
|
|
89
|
+
return message.content.flatMap((part) => {
|
|
90
|
+
if (part.type !== "tool-result")
|
|
91
|
+
return [];
|
|
92
|
+
return [
|
|
93
|
+
{
|
|
94
|
+
role: "tool",
|
|
95
|
+
tool_call_id: part.toolCallId,
|
|
96
|
+
content: stringifyToolResultOutput(part.output),
|
|
97
|
+
},
|
|
98
|
+
];
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
export function transformPrompt(prompt) {
|
|
102
|
+
const system = [];
|
|
103
|
+
const messages = [];
|
|
104
|
+
for (const message of prompt) {
|
|
105
|
+
if (message.role === "system") {
|
|
106
|
+
system.push(message.content);
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
if (message.role === "user") {
|
|
110
|
+
messages.push(transformUserMessage(message));
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
if (message.role === "assistant") {
|
|
114
|
+
messages.push(transformAssistantMessage(message));
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
if (message.role === "tool")
|
|
118
|
+
messages.push(...transformToolMessage(message));
|
|
119
|
+
}
|
|
120
|
+
let lastUserText = "";
|
|
121
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
122
|
+
if (messages[i].role !== "user")
|
|
123
|
+
continue;
|
|
124
|
+
lastUserText = textFromContent(messages[i].content);
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
return { system: system.join("\n\n"), messages, lastUserText };
|
|
128
|
+
}
|
|
129
|
+
export function transformTools(tools) {
|
|
130
|
+
if (!tools?.length)
|
|
131
|
+
return { tools: [], ignoredTools: 0 };
|
|
132
|
+
const result = [];
|
|
133
|
+
let ignoredTools = 0;
|
|
134
|
+
for (const tool of tools) {
|
|
135
|
+
if (tool.type !== "function") {
|
|
136
|
+
ignoredTools++;
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
const functionTool = tool;
|
|
140
|
+
result.push({
|
|
141
|
+
type: "function",
|
|
142
|
+
function: {
|
|
143
|
+
name: functionTool.name,
|
|
144
|
+
description: functionTool.description,
|
|
145
|
+
parameters: functionTool.inputSchema,
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
return { tools: result, ignoredTools };
|
|
150
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "opencode-qoder",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Qoder provider plugin for opencode",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ai-sdk-provider",
|
|
7
|
+
"opencode",
|
|
8
|
+
"opencode-plugin",
|
|
9
|
+
"qoder"
|
|
10
|
+
],
|
|
11
|
+
"homepage": "https://github.com/Moorad/opencode-qoder#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/Moorad/opencode-qoder/issues"
|
|
14
|
+
},
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/Moorad/opencode-qoder.git"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"README.md"
|
|
23
|
+
],
|
|
24
|
+
"type": "module",
|
|
25
|
+
"main": "./dist/index.js",
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"import": "./dist/index.js"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@ai-sdk/provider": "3.0.8",
|
|
35
|
+
"@opencode-ai/plugin": "1.17.13",
|
|
36
|
+
"@types/node": "^24.0.0",
|
|
37
|
+
"typescript": "^5.8.2",
|
|
38
|
+
"vitest": "^4.1.9"
|
|
39
|
+
},
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"@opencode-ai/plugin": ">=1.17.0"
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "rm -rf ./dist && tsc -p tsconfig.json",
|
|
45
|
+
"check": "tsc -p tsconfig.json --noEmit",
|
|
46
|
+
"test": "vitest run src"
|
|
47
|
+
}
|
|
48
|
+
}
|