opencode-qoder-bridge 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/LICENSE +21 -0
- package/README.md +185 -0
- package/RELEASING.md +64 -0
- package/SECURITY.md +24 -0
- package/THIRD_PARTY_NOTICES.md +18 -0
- package/bin/statusline.mjs +33 -0
- package/bin/usage.mjs +35 -0
- package/dist/auth.d.ts +10 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +75 -0
- package/dist/auth.js.map +1 -0
- package/dist/cost.d.ts +53 -0
- package/dist/cost.d.ts.map +1 -0
- package/dist/cost.js +173 -0
- package/dist/cost.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +148 -0
- package/dist/index.js.map +1 -0
- package/dist/language-model.d.ts +15 -0
- package/dist/language-model.d.ts.map +1 -0
- package/dist/language-model.js +408 -0
- package/dist/language-model.js.map +1 -0
- package/dist/mcp-bridge.d.ts +8 -0
- package/dist/mcp-bridge.d.ts.map +1 -0
- package/dist/mcp-bridge.js +81 -0
- package/dist/mcp-bridge.js.map +1 -0
- package/dist/models.d.ts +27 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/models.js +112 -0
- package/dist/models.js.map +1 -0
- package/dist/prompt-builder.d.ts +30 -0
- package/dist/prompt-builder.d.ts.map +1 -0
- package/dist/prompt-builder.js +308 -0
- package/dist/prompt-builder.js.map +1 -0
- package/dist/provider.d.ts +12 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +17 -0
- package/dist/provider.js.map +1 -0
- package/dist/sdk-session.d.ts +3 -0
- package/dist/sdk-session.d.ts.map +1 -0
- package/dist/sdk-session.js +8 -0
- package/dist/sdk-session.js.map +1 -0
- package/dist/tool-normalizer.d.ts +13 -0
- package/dist/tool-normalizer.d.ts.map +1 -0
- package/dist/tool-normalizer.js +99 -0
- package/dist/tool-normalizer.js.map +1 -0
- package/dist/tui-register.d.ts +2 -0
- package/dist/tui-register.d.ts.map +1 -0
- package/dist/tui-register.js +67 -0
- package/dist/tui-register.js.map +1 -0
- package/dist/tui.d.ts +9 -0
- package/dist/tui.d.ts.map +1 -0
- package/dist/tui.js +190 -0
- package/dist/tui.js.map +1 -0
- package/dist/types.d.ts +34 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/usage.d.ts +11 -0
- package/dist/usage.d.ts.map +1 -0
- package/dist/usage.js +87 -0
- package/dist/usage.js.map +1 -0
- package/package.json +78 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maps qodercli tool names to opencode tool names and normalizes their inputs.
|
|
3
|
+
*
|
|
4
|
+
* - Casing: Read -> read, Bash -> bash
|
|
5
|
+
* - Builtins: AskUserQuestion -> question, Agent -> task, ExitPlanMode -> plan_exit
|
|
6
|
+
* - MCP proxy: mcp__{server}__{tool} -> {server}_{tool}
|
|
7
|
+
*/
|
|
8
|
+
const NAME_MAP = {
|
|
9
|
+
askuserquestion: "question",
|
|
10
|
+
agent: "task",
|
|
11
|
+
exitplanmode: "plan_exit",
|
|
12
|
+
str_replace_based_edit_tool: "edit",
|
|
13
|
+
};
|
|
14
|
+
const KEY_RENAMES = {
|
|
15
|
+
read: { file_path: "filePath" },
|
|
16
|
+
write: { file_path: "filePath" },
|
|
17
|
+
task: { subagentType: "subagent_type" },
|
|
18
|
+
edit: {
|
|
19
|
+
file_path: "filePath",
|
|
20
|
+
old_string: "oldString",
|
|
21
|
+
new_string: "newString",
|
|
22
|
+
replace_all: "replaceAll",
|
|
23
|
+
},
|
|
24
|
+
skill: { skill: "name" },
|
|
25
|
+
};
|
|
26
|
+
const SUBAGENT_TYPE_MAP = {
|
|
27
|
+
"general-purpose": "general",
|
|
28
|
+
"general_purpose": "general",
|
|
29
|
+
"general purpose": "general",
|
|
30
|
+
"code-reviewer": "general",
|
|
31
|
+
"task-executor": "general",
|
|
32
|
+
"design-agent": "general",
|
|
33
|
+
"spec-review-agent": "explore",
|
|
34
|
+
"qoder-guide": "explore",
|
|
35
|
+
explorer: "explore",
|
|
36
|
+
};
|
|
37
|
+
const UNSAFE_KEYS = new Set(["__proto__", "prototype", "constructor"]);
|
|
38
|
+
function isRecord(v) {
|
|
39
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
40
|
+
}
|
|
41
|
+
export function normalizeToolName(name) {
|
|
42
|
+
const lower = name.toLowerCase();
|
|
43
|
+
const mapped = Object.hasOwn(NAME_MAP, lower) ? NAME_MAP[lower] : undefined;
|
|
44
|
+
if (mapped)
|
|
45
|
+
return mapped;
|
|
46
|
+
if (lower.startsWith("mcp__")) {
|
|
47
|
+
const rest = lower.slice(5);
|
|
48
|
+
const sep = rest.indexOf("__");
|
|
49
|
+
if (sep > 0)
|
|
50
|
+
return `${rest.slice(0, sep)}_${rest.slice(sep + 2)}`;
|
|
51
|
+
return rest;
|
|
52
|
+
}
|
|
53
|
+
return lower;
|
|
54
|
+
}
|
|
55
|
+
/** Normalize a parsed tool-input object for the given (already normalized) tool name. */
|
|
56
|
+
export function normalizeToolInput(toolName, input) {
|
|
57
|
+
if (!isRecord(input))
|
|
58
|
+
return input;
|
|
59
|
+
const renames = Object.hasOwn(KEY_RENAMES, toolName) ? KEY_RENAMES[toolName] : undefined;
|
|
60
|
+
const out = {};
|
|
61
|
+
for (const [k, v] of Object.entries(input)) {
|
|
62
|
+
if (UNSAFE_KEYS.has(k))
|
|
63
|
+
continue;
|
|
64
|
+
const renamed = renames && Object.hasOwn(renames, k) ? renames[k] : k;
|
|
65
|
+
if (!UNSAFE_KEYS.has(renamed))
|
|
66
|
+
out[renamed] = v;
|
|
67
|
+
}
|
|
68
|
+
if (toolName === "task" && typeof out.subagent_type === "string") {
|
|
69
|
+
const type = out.subagent_type.trim().toLowerCase();
|
|
70
|
+
out.subagent_type = Object.hasOwn(SUBAGENT_TYPE_MAP, type) ? SUBAGENT_TYPE_MAP[type] : type;
|
|
71
|
+
}
|
|
72
|
+
if (toolName === "grep") {
|
|
73
|
+
if (typeof out.include !== "string") {
|
|
74
|
+
const glob = out.glob;
|
|
75
|
+
const type = out.type;
|
|
76
|
+
if (typeof glob === "string")
|
|
77
|
+
out.include = glob;
|
|
78
|
+
else if (typeof type === "string")
|
|
79
|
+
out.include = `*.${type}`;
|
|
80
|
+
}
|
|
81
|
+
for (const k of ["glob", "type", "output_mode", "multiline", "head_limit", "-i", "-n", "-B", "-A", "-C"]) {
|
|
82
|
+
delete out[k];
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return out;
|
|
86
|
+
}
|
|
87
|
+
/** Parse a JSON input string, normalize, and re-serialize. Falls back to the original on parse error. */
|
|
88
|
+
export function normalizeToolInputString(toolName, input) {
|
|
89
|
+
const trimmed = input.trim();
|
|
90
|
+
if (!trimmed)
|
|
91
|
+
return "{}";
|
|
92
|
+
try {
|
|
93
|
+
return JSON.stringify(normalizeToolInput(toolName, JSON.parse(trimmed)));
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return input;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=tool-normalizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-normalizer.js","sourceRoot":"","sources":["../src/tool-normalizer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui-register.d.ts","sourceRoot":"","sources":["../src/tui-register.ts"],"names":[],"mappings":"AA8BA,wBAAsB,mBAAmB,CACvC,UAAU,SAAwB,EAClC,KAAK,SAAY,GAChB,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,CA6C9B"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { mkdir, readFile, rename, unlink, writeFile } from "node:fs/promises";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
import { applyEdits, modify, parse } from "jsonc-parser";
|
|
6
|
+
const TUI_ENTRY = new URL("./tui.js", import.meta.url).href;
|
|
7
|
+
function globalTuiConfigPath() {
|
|
8
|
+
const configHome = process.env.XDG_CONFIG_HOME?.trim();
|
|
9
|
+
return join(configHome || join(homedir(), ".config"), "opencode", "tui.json");
|
|
10
|
+
}
|
|
11
|
+
function isMissingFile(error) {
|
|
12
|
+
return (error instanceof Error &&
|
|
13
|
+
"code" in error &&
|
|
14
|
+
error.code === "ENOENT");
|
|
15
|
+
}
|
|
16
|
+
async function readConfig(path) {
|
|
17
|
+
try {
|
|
18
|
+
return await readFile(path, "utf8");
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
if (isMissingFile(error))
|
|
22
|
+
return "";
|
|
23
|
+
throw error;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export async function ensureTuiRegistered(configPath = globalTuiConfigPath(), entry = TUI_ENTRY) {
|
|
27
|
+
const source = await readConfig(configPath);
|
|
28
|
+
const errors = [];
|
|
29
|
+
const current = source.trim()
|
|
30
|
+
? parse(source, errors, { allowTrailingComma: true })
|
|
31
|
+
: {};
|
|
32
|
+
if (errors.length > 0 || !current || Array.isArray(current)) {
|
|
33
|
+
throw new Error(`Cannot update invalid OpenCode TUI configuration: ${configPath}`);
|
|
34
|
+
}
|
|
35
|
+
const configured = current.plugin;
|
|
36
|
+
if (configured !== undefined && !Array.isArray(configured)) {
|
|
37
|
+
throw new Error(`OpenCode TUI "plugin" must be an array: ${configPath}`);
|
|
38
|
+
}
|
|
39
|
+
const plugins = (configured ?? []);
|
|
40
|
+
if (plugins.includes(entry) || plugins.includes("opencode-qoder-bridge")) {
|
|
41
|
+
return "present";
|
|
42
|
+
}
|
|
43
|
+
const base = source.trim()
|
|
44
|
+
? source
|
|
45
|
+
: '{\n "$schema": "https://opencode.ai/tui.json"\n}\n';
|
|
46
|
+
const eol = base.includes("\r\n") ? "\r\n" : "\n";
|
|
47
|
+
const edits = modify(base, ["plugin"], [...plugins, entry], {
|
|
48
|
+
formattingOptions: {
|
|
49
|
+
insertSpaces: true,
|
|
50
|
+
tabSize: 2,
|
|
51
|
+
eol,
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
const updated = applyEdits(base, edits);
|
|
55
|
+
await mkdir(dirname(configPath), { recursive: true, mode: 0o700 });
|
|
56
|
+
const temporary = `${configPath}.${process.pid}.${randomUUID()}.tmp`;
|
|
57
|
+
try {
|
|
58
|
+
await writeFile(temporary, updated, { encoding: "utf8", mode: 0o600 });
|
|
59
|
+
await rename(temporary, configPath);
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
await unlink(temporary).catch(() => undefined);
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
return "added";
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=tui-register.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui-register.js","sourceRoot":"","sources":["../src/tui-register.ts"],"names":[],"mappings":"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"}
|
package/dist/tui.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { TuiPlugin } from "@opencode-ai/plugin/tui";
|
|
2
|
+
export declare const id = "opencode-qoder-bridge-sidebar";
|
|
3
|
+
export declare const tui: TuiPlugin;
|
|
4
|
+
declare const _default: {
|
|
5
|
+
id: string;
|
|
6
|
+
tui: TuiPlugin;
|
|
7
|
+
};
|
|
8
|
+
export default _default;
|
|
9
|
+
//# sourceMappingURL=tui.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui.d.ts","sourceRoot":"","sources":["../src/tui.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAmB,MAAM,yBAAyB,CAAC;AAkF1E,eAAO,MAAM,EAAE,kCAAkC,CAAC;AAElD,eAAO,MAAM,GAAG,EAAE,SAkIjB,CAAC;;;;;AAEF,wBAAqD"}
|
package/dist/tui.js
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { jsx, jsxs } from "@opentui/solid/jsx-runtime";
|
|
2
|
+
import { createEffect, Show, createSignal } from "solid-js";
|
|
3
|
+
import { getLiveUsage } from "./usage.js";
|
|
4
|
+
const REFRESH_MS = 30_000;
|
|
5
|
+
const POST_TURN_REFRESH_MS = 5_000;
|
|
6
|
+
function formatCredits(value) {
|
|
7
|
+
return Number.isInteger(value)
|
|
8
|
+
? value.toString()
|
|
9
|
+
: value.toLocaleString("en-US", { maximumFractionDigits: 2 });
|
|
10
|
+
}
|
|
11
|
+
function formatSessionCredits(value) {
|
|
12
|
+
return value.toFixed(2);
|
|
13
|
+
}
|
|
14
|
+
function usesQoder(api, sessionID) {
|
|
15
|
+
const session = api.state.session.get(sessionID);
|
|
16
|
+
if (session?.model)
|
|
17
|
+
return session.model.providerID === "qoder";
|
|
18
|
+
const messages = api.state.session.messages(sessionID);
|
|
19
|
+
const latest = messages.at(-1);
|
|
20
|
+
if (!latest)
|
|
21
|
+
return false;
|
|
22
|
+
return latest.role === "user"
|
|
23
|
+
? latest.model.providerID === "qoder"
|
|
24
|
+
: latest.providerID === "qoder";
|
|
25
|
+
}
|
|
26
|
+
function formatQuota(usage) {
|
|
27
|
+
const quota = usage?.userQuota;
|
|
28
|
+
if (!usage || !quota || quota.total == null) {
|
|
29
|
+
return {
|
|
30
|
+
error: "usage unavailable",
|
|
31
|
+
warning: true,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
const used = quota.used ?? Math.max(0, quota.total - (quota.remaining ?? quota.total));
|
|
35
|
+
const remaining = quota.remaining ?? Math.max(0, quota.total - used);
|
|
36
|
+
const percent = quota.percentage ??
|
|
37
|
+
usage.totalUsagePercentage ??
|
|
38
|
+
(quota.total > 0 ? (used / quota.total) * 100 : 0);
|
|
39
|
+
return {
|
|
40
|
+
used,
|
|
41
|
+
total: quota.total,
|
|
42
|
+
remaining,
|
|
43
|
+
percent,
|
|
44
|
+
warning: usage.isQuotaExceeded === true || remaining <= Math.max(10, quota.total * 0.1),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function sessionSpent(api, sessionID) {
|
|
48
|
+
const sessionCost = api.state.session.get(sessionID)?.cost;
|
|
49
|
+
if (typeof sessionCost === "number")
|
|
50
|
+
return sessionCost;
|
|
51
|
+
return api.state.session
|
|
52
|
+
.messages(sessionID)
|
|
53
|
+
.reduce((total, message) => total + (message.role === "assistant" ? message.cost : 0), 0);
|
|
54
|
+
}
|
|
55
|
+
function estimatedSessionCredits(api, sessionID) {
|
|
56
|
+
// Qoder's Credits Log presents reference cost in dollars and Credits in
|
|
57
|
+
// cent-denominated units. The personal-account SDK exposes only a rounded
|
|
58
|
+
// whole-account quota, so session.cost * 100 is the best fractional signal
|
|
59
|
+
// available until the SDK exposes per-request credit events.
|
|
60
|
+
return sessionSpent(api, sessionID) * 100;
|
|
61
|
+
}
|
|
62
|
+
export const id = "opencode-qoder-bridge-sidebar";
|
|
63
|
+
export const tui = async (api) => {
|
|
64
|
+
const [quota, setQuota] = createSignal({
|
|
65
|
+
error: "loading…",
|
|
66
|
+
warning: false,
|
|
67
|
+
});
|
|
68
|
+
const sessionBaselines = new Map();
|
|
69
|
+
const sessionCredits = (sessionID) => {
|
|
70
|
+
const used = quota().used;
|
|
71
|
+
if (used == null)
|
|
72
|
+
return undefined;
|
|
73
|
+
const key = `opencode-qoder-bridge:credit-baseline:${sessionID}`;
|
|
74
|
+
let baseline = sessionBaselines.get(sessionID);
|
|
75
|
+
if (baseline == null) {
|
|
76
|
+
baseline = api.kv.get(key, undefined);
|
|
77
|
+
if (baseline == null || baseline > used) {
|
|
78
|
+
baseline = used;
|
|
79
|
+
api.kv.set(key, baseline);
|
|
80
|
+
}
|
|
81
|
+
sessionBaselines.set(sessionID, baseline);
|
|
82
|
+
}
|
|
83
|
+
return Math.max(0, used - baseline);
|
|
84
|
+
};
|
|
85
|
+
let refreshing = false;
|
|
86
|
+
let refreshedAt = 0;
|
|
87
|
+
const refresh = async () => {
|
|
88
|
+
if (refreshing)
|
|
89
|
+
return;
|
|
90
|
+
refreshing = true;
|
|
91
|
+
try {
|
|
92
|
+
setQuota(formatQuota(await getLiveUsage(true)));
|
|
93
|
+
refreshedAt = Date.now();
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
refreshing = false;
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
const refreshIfNeeded = () => {
|
|
100
|
+
if (Date.now() - refreshedAt >= REFRESH_MS)
|
|
101
|
+
void refresh();
|
|
102
|
+
};
|
|
103
|
+
const activeSessionUsesQoder = () => {
|
|
104
|
+
const route = api.route.current;
|
|
105
|
+
const sessionID = route.name === "session" &&
|
|
106
|
+
route.params &&
|
|
107
|
+
typeof route.params.sessionID === "string"
|
|
108
|
+
? route.params.sessionID
|
|
109
|
+
: undefined;
|
|
110
|
+
return sessionID ? usesQoder(api, sessionID) : false;
|
|
111
|
+
};
|
|
112
|
+
const timer = setInterval(() => {
|
|
113
|
+
if (activeSessionUsesQoder())
|
|
114
|
+
void refresh();
|
|
115
|
+
}, REFRESH_MS);
|
|
116
|
+
let postTurnTimer;
|
|
117
|
+
const stopIdleRefresh = api.event.on("session.idle", (event) => {
|
|
118
|
+
if (!usesQoder(api, event.properties.sessionID))
|
|
119
|
+
return;
|
|
120
|
+
void refresh();
|
|
121
|
+
clearTimeout(postTurnTimer);
|
|
122
|
+
postTurnTimer = setTimeout(() => void refresh(), POST_TURN_REFRESH_MS);
|
|
123
|
+
});
|
|
124
|
+
api.lifecycle.onDispose(() => {
|
|
125
|
+
clearInterval(timer);
|
|
126
|
+
clearTimeout(postTurnTimer);
|
|
127
|
+
stopIdleRefresh();
|
|
128
|
+
});
|
|
129
|
+
api.slots.register({
|
|
130
|
+
order: 50,
|
|
131
|
+
slots: {
|
|
132
|
+
sidebar_content: ({ theme }, { session_id }) => {
|
|
133
|
+
const isQoder = () => usesQoder(api, session_id);
|
|
134
|
+
createEffect(() => {
|
|
135
|
+
if (isQoder())
|
|
136
|
+
refreshIfNeeded();
|
|
137
|
+
});
|
|
138
|
+
return jsx(Show, {
|
|
139
|
+
get when() {
|
|
140
|
+
return isQoder();
|
|
141
|
+
},
|
|
142
|
+
get children() {
|
|
143
|
+
return jsxs("box", {
|
|
144
|
+
flexDirection: "column",
|
|
145
|
+
marginTop: 1,
|
|
146
|
+
children: [
|
|
147
|
+
jsx("text", {
|
|
148
|
+
fg: theme.current.text,
|
|
149
|
+
children: jsx("b", { children: "Qoder Credits" }),
|
|
150
|
+
}),
|
|
151
|
+
jsx("text", {
|
|
152
|
+
get fg() {
|
|
153
|
+
return quota().warning ? theme.current.warning : theme.current.textMuted;
|
|
154
|
+
},
|
|
155
|
+
get children() {
|
|
156
|
+
const accountDelta = sessionCredits(session_id);
|
|
157
|
+
const estimate = estimatedSessionCredits(api, session_id);
|
|
158
|
+
if (estimate > 0) {
|
|
159
|
+
return `Session: ~${formatSessionCredits(estimate)} credits used`;
|
|
160
|
+
}
|
|
161
|
+
return accountDelta == null
|
|
162
|
+
? `Session: ${quota().error ?? "loading…"}`
|
|
163
|
+
: `Session: ${formatSessionCredits(accountDelta)} credits used`;
|
|
164
|
+
},
|
|
165
|
+
}),
|
|
166
|
+
jsx("text", {
|
|
167
|
+
fg: theme.current.textMuted,
|
|
168
|
+
get children() {
|
|
169
|
+
return `Spent: $${sessionSpent(api, session_id).toFixed(4)}`;
|
|
170
|
+
},
|
|
171
|
+
}),
|
|
172
|
+
jsx("text", {
|
|
173
|
+
fg: theme.current.textMuted,
|
|
174
|
+
get children() {
|
|
175
|
+
const current = quota();
|
|
176
|
+
return current.used == null || current.total == null || current.remaining == null
|
|
177
|
+
? "Account quota unavailable"
|
|
178
|
+
: `Account: ${formatCredits(current.used)}/${formatCredits(current.total)} · ${formatCredits(current.remaining)} left`;
|
|
179
|
+
},
|
|
180
|
+
}),
|
|
181
|
+
],
|
|
182
|
+
});
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
};
|
|
189
|
+
export default { id, tui };
|
|
190
|
+
//# sourceMappingURL=tui.js.map
|
package/dist/tui.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui.js","sourceRoot":"","sources":["../src/tui.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export interface QoderModelDef {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
attachment: boolean;
|
|
5
|
+
reasoning: boolean;
|
|
6
|
+
toolCall: boolean;
|
|
7
|
+
/** Billing multiplier relative to the base rate. 0 = free. */
|
|
8
|
+
multiplier: number;
|
|
9
|
+
cost: {
|
|
10
|
+
input: number;
|
|
11
|
+
output: number;
|
|
12
|
+
cacheRead: number;
|
|
13
|
+
cacheWrite: number;
|
|
14
|
+
};
|
|
15
|
+
limit: {
|
|
16
|
+
context: number;
|
|
17
|
+
output: number;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export interface QoderBridgeOptions {
|
|
21
|
+
/** Force a transport mode. `sdk` (default) streams via the agent SDK. */
|
|
22
|
+
mode?: "sdk";
|
|
23
|
+
/** Extra CLI flags forwarded to qodercli, e.g. { "--experimental-mcp-load": null }. */
|
|
24
|
+
extraArgs?: Record<string, string | null>;
|
|
25
|
+
/** Bridged MCP server configs keyed by server name. */
|
|
26
|
+
mcpServers?: Record<string, unknown>;
|
|
27
|
+
}
|
|
28
|
+
export interface ModelCost {
|
|
29
|
+
input: number;
|
|
30
|
+
output: number;
|
|
31
|
+
cacheRead: number;
|
|
32
|
+
cacheWrite: number;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,8DAA8D;IAC9D,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,KAAK,EAAE;QACL,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,MAAM,WAAW,kBAAkB;IACjC,yEAAyE;IACzE,IAAI,CAAC,EAAE,KAAK,CAAC;IACb,uFAAuF;IACvF,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IAC1C,uDAAuD;IACvD,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/dist/usage.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { UsageInfo } from "@qoder-ai/qoder-agent-sdk";
|
|
2
|
+
/**
|
|
3
|
+
* Fetch live account usage by opening a short-lived SDK session and calling
|
|
4
|
+
* `getUsageInfo()`. Results are cached for CACHE_TTL_MS and de-duplicated so
|
|
5
|
+
* concurrent callers share one session.
|
|
6
|
+
*/
|
|
7
|
+
export declare function getLiveUsage(force?: boolean): Promise<UsageInfo | null>;
|
|
8
|
+
export declare function invalidateUsageCache(): void;
|
|
9
|
+
/** Format a UsageInfo into a compact human-readable report. */
|
|
10
|
+
export declare function formatUsageReport(u: UsageInfo): string;
|
|
11
|
+
//# sourceMappingURL=usage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../src/usage.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAU3D;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,UAAQ,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAqCrE;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAG3C;AAQD,+DAA+D;AAC/D,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,SAAS,GAAG,MAAM,CAsBtD"}
|
package/dist/usage.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { query, qodercliAuth } from "@qoder-ai/qoder-agent-sdk";
|
|
2
|
+
import { findQoderCLI } from "./auth.js";
|
|
3
|
+
import { idlePrompt } from "./sdk-session.js";
|
|
4
|
+
const CACHE_TTL_MS = 60_000;
|
|
5
|
+
let cached = null;
|
|
6
|
+
let cacheExpiry = 0;
|
|
7
|
+
let inflight = null;
|
|
8
|
+
/**
|
|
9
|
+
* Fetch live account usage by opening a short-lived SDK session and calling
|
|
10
|
+
* `getUsageInfo()`. Results are cached for CACHE_TTL_MS and de-duplicated so
|
|
11
|
+
* concurrent callers share one session.
|
|
12
|
+
*/
|
|
13
|
+
export function getLiveUsage(force = false) {
|
|
14
|
+
const now = Date.now();
|
|
15
|
+
if (!force && cached && now < cacheExpiry)
|
|
16
|
+
return Promise.resolve(cached);
|
|
17
|
+
if (inflight)
|
|
18
|
+
return inflight;
|
|
19
|
+
inflight = (async () => {
|
|
20
|
+
const cli = findQoderCLI();
|
|
21
|
+
if (!cli)
|
|
22
|
+
return null;
|
|
23
|
+
const abortController = new AbortController();
|
|
24
|
+
const q = query({
|
|
25
|
+
prompt: idlePrompt(abortController.signal),
|
|
26
|
+
options: {
|
|
27
|
+
auth: qodercliAuth(),
|
|
28
|
+
pathToQoderCLIExecutable: cli,
|
|
29
|
+
abortController,
|
|
30
|
+
maxTurns: 1,
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
try {
|
|
34
|
+
const usage = await q.getUsageInfo();
|
|
35
|
+
if (usage) {
|
|
36
|
+
cached = usage;
|
|
37
|
+
cacheExpiry = Date.now() + CACHE_TTL_MS;
|
|
38
|
+
}
|
|
39
|
+
return usage;
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return cached;
|
|
43
|
+
}
|
|
44
|
+
finally {
|
|
45
|
+
abortController.abort();
|
|
46
|
+
void q.return(undefined).catch(() => { });
|
|
47
|
+
inflight = null;
|
|
48
|
+
}
|
|
49
|
+
})();
|
|
50
|
+
return inflight;
|
|
51
|
+
}
|
|
52
|
+
export function invalidateUsageCache() {
|
|
53
|
+
cached = null;
|
|
54
|
+
cacheExpiry = 0;
|
|
55
|
+
}
|
|
56
|
+
function bucketLine(label, b) {
|
|
57
|
+
if (!b || b.total == null)
|
|
58
|
+
return null;
|
|
59
|
+
const unit = b.unit ?? "";
|
|
60
|
+
return `${label}: ${b.used ?? 0}/${b.total} ${unit} (${b.remaining ?? 0} remaining)`;
|
|
61
|
+
}
|
|
62
|
+
/** Format a UsageInfo into a compact human-readable report. */
|
|
63
|
+
export function formatUsageReport(u) {
|
|
64
|
+
const lines = ["Qoder Account Usage"];
|
|
65
|
+
if (u.userType)
|
|
66
|
+
lines.push(` Plan: ${u.userType}`);
|
|
67
|
+
if (typeof u.totalUsagePercentage === "number")
|
|
68
|
+
lines.push(` Usage: ${u.totalUsagePercentage.toFixed(1)}%`);
|
|
69
|
+
const quota = bucketLine(" Quota", u.userQuota);
|
|
70
|
+
if (quota)
|
|
71
|
+
lines.push(quota);
|
|
72
|
+
if (u.addOnQuota && (u.addOnQuota.total ?? 0) > 0) {
|
|
73
|
+
const addOn = bucketLine(" Add-on", u.addOnQuota);
|
|
74
|
+
if (addOn)
|
|
75
|
+
lines.push(addOn);
|
|
76
|
+
}
|
|
77
|
+
if (u.orgResourcePackage?.available) {
|
|
78
|
+
const org = u.orgResourcePackage;
|
|
79
|
+
lines.push(` Org Package: ${org.used ?? 0}/${org.cap ?? 0} ${org.unit ?? ""} (${org.remaining ?? 0} remaining)`);
|
|
80
|
+
}
|
|
81
|
+
if (u.isQuotaExceeded)
|
|
82
|
+
lines.push(" WARNING: quota exceeded");
|
|
83
|
+
if (u.expiresAt && u.expiresAt > 0)
|
|
84
|
+
lines.push(` Expires: ${new Date(u.expiresAt).toISOString().slice(0, 10)}`);
|
|
85
|
+
return lines.join("\n");
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=usage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage.js","sourceRoot":"","sources":["../src/usage.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "opencode-qoder-bridge",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "opencode plugin that bridges Qoder AI models via @qoder-ai/qoder-agent-sdk",
|
|
5
|
+
"author": "Naoufal El Bani",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"homepage": "https://github.com/naoufalelbani/opencode-qoder-bridge#readme",
|
|
9
|
+
"bugs": {
|
|
10
|
+
"url": "https://github.com/naoufalelbani/opencode-qoder-bridge/issues"
|
|
11
|
+
},
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/naoufalelbani/opencode-qoder-bridge.git"
|
|
15
|
+
},
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public"
|
|
18
|
+
},
|
|
19
|
+
"main": "dist/index.js",
|
|
20
|
+
"types": "dist/index.d.ts",
|
|
21
|
+
"bin": {
|
|
22
|
+
"opencode-qoder-bridge": "bin/statusline.mjs",
|
|
23
|
+
"qoder-usage": "bin/usage.mjs"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist",
|
|
27
|
+
"bin",
|
|
28
|
+
"README.md",
|
|
29
|
+
"LICENSE",
|
|
30
|
+
"RELEASING.md",
|
|
31
|
+
"SECURITY.md",
|
|
32
|
+
"THIRD_PARTY_NOTICES.md"
|
|
33
|
+
],
|
|
34
|
+
"exports": {
|
|
35
|
+
".": {
|
|
36
|
+
"types": "./dist/index.d.ts",
|
|
37
|
+
"default": "./dist/index.js"
|
|
38
|
+
},
|
|
39
|
+
"./provider": {
|
|
40
|
+
"types": "./dist/provider.d.ts",
|
|
41
|
+
"default": "./dist/provider.js"
|
|
42
|
+
},
|
|
43
|
+
"./tui": {
|
|
44
|
+
"types": "./dist/tui.d.ts",
|
|
45
|
+
"default": "./dist/tui.js"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsc -p tsconfig.json",
|
|
50
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
51
|
+
"test": "npm run build && node --test test/bridge.test.mjs",
|
|
52
|
+
"check": "npm run typecheck && npm test",
|
|
53
|
+
"prepublishOnly": "npm run check"
|
|
54
|
+
},
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"@ai-sdk/provider": "^3.0.14",
|
|
57
|
+
"@opencode-ai/plugin": "1.18.5",
|
|
58
|
+
"@opentui/solid": "0.4.5",
|
|
59
|
+
"@qoder-ai/qoder-agent-sdk": "^1.0.15",
|
|
60
|
+
"jsonc-parser": "^3.3.1",
|
|
61
|
+
"solid-js": "1.9.12",
|
|
62
|
+
"zod": "^3.25.0"
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@types/node": "^22.10.0",
|
|
66
|
+
"typescript": "^5.7.0"
|
|
67
|
+
},
|
|
68
|
+
"engines": {
|
|
69
|
+
"node": ">=20"
|
|
70
|
+
},
|
|
71
|
+
"keywords": [
|
|
72
|
+
"opencode",
|
|
73
|
+
"opencode-plugin",
|
|
74
|
+
"qoder",
|
|
75
|
+
"ai",
|
|
76
|
+
"llm"
|
|
77
|
+
]
|
|
78
|
+
}
|