opencode-qoder-bridge 0.1.11 → 0.1.12
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/CHANGELOG.md +223 -223
- package/LICENSE +21 -21
- package/README.md +331 -331
- package/RELEASING.md +62 -62
- package/SECURITY.md +25 -25
- package/THIRD_PARTY_NOTICES.md +18 -18
- package/bin/statusline.mjs +66 -66
- package/bin/usage.mjs +36 -36
- package/dist/language-model.d.ts.map +1 -1
- package/dist/language-model.js +13 -0
- package/dist/language-model.js.map +1 -1
- package/dist/sdk-control.d.ts.map +1 -1
- package/dist/sdk-control.js +13 -0
- package/dist/sdk-control.js.map +1 -1
- package/dist/types.d.ts +4 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +117 -117
package/RELEASING.md
CHANGED
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
# Releasing
|
|
2
|
-
|
|
1
|
+
# Releasing
|
|
2
|
+
|
|
3
3
|
## Before a public release
|
|
4
|
-
|
|
5
|
-
1. Confirm that publishing this integration and using the Qoder name and SDK
|
|
6
|
-
complies with the current Qoder Product Service Terms. Keep any written
|
|
7
|
-
permission with the project records.
|
|
4
|
+
|
|
5
|
+
1. Confirm that publishing this integration and using the Qoder name and SDK
|
|
6
|
+
complies with the current Qoder Product Service Terms. Keep any written
|
|
7
|
+
permission with the project records.
|
|
8
8
|
2. Confirm the public GitHub repository is available:
|
|
9
|
-
`https://github.com/naoufalelbani/opencode-qoder-bridge`.
|
|
10
|
-
3. Create an npm account, enable two-factor authentication, and run `npm login`.
|
|
11
|
-
4. Review production dependency advisories with `npm audit --omit=dev`. Do not
|
|
12
|
-
apply forced or major-version fixes without running the full integration
|
|
13
|
-
suite.
|
|
14
|
-
|
|
9
|
+
`https://github.com/naoufalelbani/opencode-qoder-bridge`.
|
|
10
|
+
3. Create an npm account, enable two-factor authentication, and run `npm login`.
|
|
11
|
+
4. Review production dependency advisories with `npm audit --omit=dev`. Do not
|
|
12
|
+
apply forced or major-version fixes without running the full integration
|
|
13
|
+
suite.
|
|
14
|
+
|
|
15
15
|
## Public publish
|
|
16
|
-
|
|
17
|
-
Run the complete release gate from a clean checkout:
|
|
18
|
-
|
|
19
|
-
```bash
|
|
16
|
+
|
|
17
|
+
Run the complete release gate from a clean checkout:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
20
|
npm ci
|
|
21
21
|
npm run check
|
|
22
22
|
npm run test:stress
|
|
23
23
|
QODER_E2E=1 npm run test:e2e # requires qoder login; consumes quota
|
|
24
24
|
npm pack --dry-run
|
|
25
25
|
npm publish --access public
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
The end-to-end gate is mandatory for any release that touches
|
|
29
|
-
`src/language-model.ts`, `src/models.ts`, or `src/usage.ts`: unit tests mock
|
|
30
|
-
the SDK, so only `QODER_E2E=1` exercises real streaming, tool calls, provider
|
|
31
|
-
metadata, and live model discovery. Verify before publishing that the dry-run
|
|
32
|
-
tarball contains `dist/` (including `errors.js`, `logger.js`,
|
|
33
|
-
`state-dir.js`) and both `bin/` scripts, and nothing else unexpected.
|
|
34
|
-
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The end-to-end gate is mandatory for any release that touches
|
|
29
|
+
`src/language-model.ts`, `src/models.ts`, or `src/usage.ts`: unit tests mock
|
|
30
|
+
the SDK, so only `QODER_E2E=1` exercises real streaming, tool calls, provider
|
|
31
|
+
metadata, and live model discovery. Verify before publishing that the dry-run
|
|
32
|
+
tarball contains `dist/` (including `errors.js`, `logger.js`,
|
|
33
|
+
`state-dir.js`) and both `bin/` scripts, and nothing else unexpected.
|
|
34
|
+
|
|
35
35
|
Verify the registry package and install it through OpenCode:
|
|
36
|
-
|
|
37
|
-
```bash
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
38
|
npm view opencode-qoder-bridge
|
|
39
39
|
```
|
|
40
40
|
|
|
@@ -46,38 +46,38 @@ the bundled Worker runtime is required:
|
|
|
46
46
|
npm install-scripts approve @qoder-ai/qoder-agent-sdk@1.0.31
|
|
47
47
|
npm rebuild @qoder-ai/qoder-agent-sdk
|
|
48
48
|
```
|
|
49
|
-
|
|
50
|
-
```json
|
|
51
|
-
{
|
|
52
|
-
"plugin": ["opencode-qoder-bridge"]
|
|
53
|
-
}
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
## Trusted publishing
|
|
57
|
-
|
|
58
|
-
After the package exists on npm:
|
|
59
|
-
|
|
60
|
-
1. Open the package settings on npmjs.com.
|
|
61
|
-
2. Add a GitHub Actions trusted publisher for:
|
|
62
|
-
- Owner: `naoufalelbani`
|
|
63
|
-
- Repository: `opencode-qoder-bridge`
|
|
64
|
-
- Workflow: `publish.yml`
|
|
65
|
-
- Allowed action: `npm publish`
|
|
66
|
-
3. Keep the repository public so npm can generate provenance.
|
|
67
|
-
4. Consider configuring the npm package to disallow token-based publishing
|
|
68
|
-
after the trusted workflow succeeds.
|
|
69
|
-
|
|
70
|
-
## Subsequent releases
|
|
71
|
-
|
|
72
|
-
Update `version` using semantic versioning, document the release in
|
|
73
|
-
`CHANGELOG.md`, run the release gate, commit the change, and push a matching
|
|
74
|
-
tag:
|
|
75
|
-
|
|
76
|
-
```bash
|
|
77
|
-
npm version patch
|
|
78
|
-
git push origin main --follow-tags
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
The tag triggers `.github/workflows/publish.yml`. Never reuse a version already
|
|
82
|
-
published to npm.
|
|
83
|
-
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"plugin": ["opencode-qoder-bridge"]
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Trusted publishing
|
|
57
|
+
|
|
58
|
+
After the package exists on npm:
|
|
59
|
+
|
|
60
|
+
1. Open the package settings on npmjs.com.
|
|
61
|
+
2. Add a GitHub Actions trusted publisher for:
|
|
62
|
+
- Owner: `naoufalelbani`
|
|
63
|
+
- Repository: `opencode-qoder-bridge`
|
|
64
|
+
- Workflow: `publish.yml`
|
|
65
|
+
- Allowed action: `npm publish`
|
|
66
|
+
3. Keep the repository public so npm can generate provenance.
|
|
67
|
+
4. Consider configuring the npm package to disallow token-based publishing
|
|
68
|
+
after the trusted workflow succeeds.
|
|
69
|
+
|
|
70
|
+
## Subsequent releases
|
|
71
|
+
|
|
72
|
+
Update `version` using semantic versioning, document the release in
|
|
73
|
+
`CHANGELOG.md`, run the release gate, commit the change, and push a matching
|
|
74
|
+
tag:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
npm version patch
|
|
78
|
+
git push origin main --follow-tags
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The tag triggers `.github/workflows/publish.yml`. Never reuse a version already
|
|
82
|
+
published to npm.
|
|
83
|
+
|
package/SECURITY.md
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
# Security Policy
|
|
2
|
-
|
|
3
|
-
## Reporting a vulnerability
|
|
4
|
-
|
|
5
|
-
Please do not open a public issue for a suspected vulnerability.
|
|
6
|
-
|
|
7
|
-
Use GitHub's private vulnerability reporting for this repository:
|
|
8
|
-
|
|
9
|
-
https://github.com/naoufalelbani/opencode-qoder-bridge/security/advisories/new
|
|
10
|
-
|
|
11
|
-
Include the affected version, reproduction steps, impact, and any suggested
|
|
12
|
-
mitigation. You should receive an acknowledgement within seven days.
|
|
13
|
-
|
|
14
|
-
## Supported versions
|
|
15
|
-
|
|
16
|
-
Security fixes are provided for the latest published version. Users should also
|
|
17
|
-
keep OpenCode, the Qoder CLI, and package dependencies current.
|
|
18
|
-
|
|
19
|
-
## Credential handling
|
|
20
|
-
|
|
21
|
-
This plugin does not distribute Qoder credentials. Authentication remains with
|
|
22
|
-
the Qoder Agent SDK. Use a personal access token or local Qoder sign-in as
|
|
23
|
-
documented by the SDK; its bundled Worker runtime can be used without a
|
|
24
|
-
separately installed Qoder CLI. Never include files from `~/.qoder/`, npm
|
|
25
|
-
tokens, prompts containing secrets, or local usage ledgers in a report.
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Reporting a vulnerability
|
|
4
|
+
|
|
5
|
+
Please do not open a public issue for a suspected vulnerability.
|
|
6
|
+
|
|
7
|
+
Use GitHub's private vulnerability reporting for this repository:
|
|
8
|
+
|
|
9
|
+
https://github.com/naoufalelbani/opencode-qoder-bridge/security/advisories/new
|
|
10
|
+
|
|
11
|
+
Include the affected version, reproduction steps, impact, and any suggested
|
|
12
|
+
mitigation. You should receive an acknowledgement within seven days.
|
|
13
|
+
|
|
14
|
+
## Supported versions
|
|
15
|
+
|
|
16
|
+
Security fixes are provided for the latest published version. Users should also
|
|
17
|
+
keep OpenCode, the Qoder CLI, and package dependencies current.
|
|
18
|
+
|
|
19
|
+
## Credential handling
|
|
20
|
+
|
|
21
|
+
This plugin does not distribute Qoder credentials. Authentication remains with
|
|
22
|
+
the Qoder Agent SDK. Use a personal access token or local Qoder sign-in as
|
|
23
|
+
documented by the SDK; its bundled Worker runtime can be used without a
|
|
24
|
+
separately installed Qoder CLI. Never include files from `~/.qoder/`, npm
|
|
25
|
+
tokens, prompts containing secrets, or local usage ledgers in a report.
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
# Third-Party Notices
|
|
2
|
-
|
|
3
|
-
This community project is not affiliated with, endorsed by, or sponsored by
|
|
4
|
-
Qoder or OpenCode.
|
|
5
|
-
|
|
6
|
-
The MIT license in this repository applies only to this project's own source
|
|
7
|
-
code. Runtime dependencies remain subject to their respective licenses and
|
|
8
|
-
terms.
|
|
9
|
-
|
|
10
|
-
In particular, `@qoder-ai/qoder-agent-sdk` is provided by Qoder under the Qoder
|
|
11
|
-
Product Service Terms:
|
|
12
|
-
|
|
13
|
-
https://qoder.com/product-service
|
|
14
|
-
|
|
15
|
-
Installing or using this plugin installs and uses that SDK. Users are
|
|
16
|
-
responsible for reviewing and complying with the Qoder terms and the terms of
|
|
17
|
-
any models or third-party services they access.
|
|
18
|
-
|
|
1
|
+
# Third-Party Notices
|
|
2
|
+
|
|
3
|
+
This community project is not affiliated with, endorsed by, or sponsored by
|
|
4
|
+
Qoder or OpenCode.
|
|
5
|
+
|
|
6
|
+
The MIT license in this repository applies only to this project's own source
|
|
7
|
+
code. Runtime dependencies remain subject to their respective licenses and
|
|
8
|
+
terms.
|
|
9
|
+
|
|
10
|
+
In particular, `@qoder-ai/qoder-agent-sdk` is provided by Qoder under the Qoder
|
|
11
|
+
Product Service Terms:
|
|
12
|
+
|
|
13
|
+
https://qoder.com/product-service
|
|
14
|
+
|
|
15
|
+
Installing or using this plugin installs and uses that SDK. Users are
|
|
16
|
+
responsible for reviewing and complying with the Qoder terms and the terms of
|
|
17
|
+
any models or third-party services they access.
|
|
18
|
+
|
package/bin/statusline.mjs
CHANGED
|
@@ -1,66 +1,66 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { lstatSync, readFileSync } from "node:fs";
|
|
3
|
-
import { homedir } from "node:os";
|
|
4
|
-
import { join } from "node:path";
|
|
5
|
-
|
|
6
|
-
// Mirrors resolveStateDir() from src/state-dir.ts:
|
|
7
|
-
// QODER_BRIDGE_STATE_DIR > XDG_CONFIG_HOME > ~/.config.
|
|
8
|
-
function resolveStateDir(env = process.env) {
|
|
9
|
-
const override = env.QODER_BRIDGE_STATE_DIR?.trim();
|
|
10
|
-
if (override) return join(override);
|
|
11
|
-
const configHome = env.XDG_CONFIG_HOME?.trim()
|
|
12
|
-
|| (process.platform === "win32" ? env.APPDATA?.trim() : undefined);
|
|
13
|
-
return join(configHome || join(homedir(), ".config"), "opencode-qoder-bridge");
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const STATE_FILE = join(resolveStateDir(), "usage.json");
|
|
17
|
-
const MAX_STATE_BYTES = 1_000_000;
|
|
18
|
-
|
|
19
|
-
function fmt(usd) {
|
|
20
|
-
const n = typeof usd === "number" && Number.isFinite(usd) ? usd : 0;
|
|
21
|
-
return `$${n.toFixed(4)}`;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function count(value) {
|
|
25
|
-
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : 0;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function add(left, right) {
|
|
29
|
-
const total = left + right;
|
|
30
|
-
return Number.isFinite(total) ? total : Number.MAX_SAFE_INTEGER;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function main() {
|
|
34
|
-
let state = null;
|
|
35
|
-
try {
|
|
36
|
-
const info = lstatSync(STATE_FILE);
|
|
37
|
-
if (!info.isFile() || info.isSymbolicLink() || info.size > MAX_STATE_BYTES) {
|
|
38
|
-
process.stdout.write("qoder: no usage yet");
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
state = JSON.parse(readFileSync(STATE_FILE, "utf8"));
|
|
42
|
-
if (!state || typeof state !== "object" || Array.isArray(state)) {
|
|
43
|
-
process.stdout.write("qoder: no usage yet");
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
} catch {
|
|
47
|
-
process.stdout.write("qoder: no usage yet");
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const parts = [
|
|
52
|
-
`cost ${fmt(state.totalCostUsd)}`,
|
|
53
|
-
`turns ${count(state.turnCount)}`,
|
|
54
|
-
`tok ${add(count(state.totalInputTokens), count(state.totalOutputTokens))}`,
|
|
55
|
-
];
|
|
56
|
-
|
|
57
|
-
const last = Array.isArray(state.recent) ? state.recent.at(-1) : null;
|
|
58
|
-
if (typeof last?.model === "string" && last.model) {
|
|
59
|
-
const model = last.model.replace(/[\u0000-\u001f\u007f]/g, " ").slice(0, 256);
|
|
60
|
-
parts.push(`last ${model}`);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
process.stdout.write(`qoder: ${parts.join(" · ")}`);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
main();
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { lstatSync, readFileSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
|
|
6
|
+
// Mirrors resolveStateDir() from src/state-dir.ts:
|
|
7
|
+
// QODER_BRIDGE_STATE_DIR > XDG_CONFIG_HOME > ~/.config.
|
|
8
|
+
function resolveStateDir(env = process.env) {
|
|
9
|
+
const override = env.QODER_BRIDGE_STATE_DIR?.trim();
|
|
10
|
+
if (override) return join(override);
|
|
11
|
+
const configHome = env.XDG_CONFIG_HOME?.trim()
|
|
12
|
+
|| (process.platform === "win32" ? env.APPDATA?.trim() : undefined);
|
|
13
|
+
return join(configHome || join(homedir(), ".config"), "opencode-qoder-bridge");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const STATE_FILE = join(resolveStateDir(), "usage.json");
|
|
17
|
+
const MAX_STATE_BYTES = 1_000_000;
|
|
18
|
+
|
|
19
|
+
function fmt(usd) {
|
|
20
|
+
const n = typeof usd === "number" && Number.isFinite(usd) ? usd : 0;
|
|
21
|
+
return `$${n.toFixed(4)}`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function count(value) {
|
|
25
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function add(left, right) {
|
|
29
|
+
const total = left + right;
|
|
30
|
+
return Number.isFinite(total) ? total : Number.MAX_SAFE_INTEGER;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function main() {
|
|
34
|
+
let state = null;
|
|
35
|
+
try {
|
|
36
|
+
const info = lstatSync(STATE_FILE);
|
|
37
|
+
if (!info.isFile() || info.isSymbolicLink() || info.size > MAX_STATE_BYTES) {
|
|
38
|
+
process.stdout.write("qoder: no usage yet");
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
state = JSON.parse(readFileSync(STATE_FILE, "utf8"));
|
|
42
|
+
if (!state || typeof state !== "object" || Array.isArray(state)) {
|
|
43
|
+
process.stdout.write("qoder: no usage yet");
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
} catch {
|
|
47
|
+
process.stdout.write("qoder: no usage yet");
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const parts = [
|
|
52
|
+
`cost ${fmt(state.totalCostUsd)}`,
|
|
53
|
+
`turns ${count(state.turnCount)}`,
|
|
54
|
+
`tok ${add(count(state.totalInputTokens), count(state.totalOutputTokens))}`,
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
const last = Array.isArray(state.recent) ? state.recent.at(-1) : null;
|
|
58
|
+
if (typeof last?.model === "string" && last.model) {
|
|
59
|
+
const model = last.model.replace(/[\u0000-\u001f\u007f]/g, " ").slice(0, 256);
|
|
60
|
+
parts.push(`last ${model}`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
process.stdout.write(`qoder: ${parts.join(" · ")}`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
main();
|
package/bin/usage.mjs
CHANGED
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { getLiveUsage, formatUsageReport } from "../dist/usage.js";
|
|
3
|
-
import { summarize, formatCost } from "../dist/cost.js";
|
|
4
|
-
import { describeError } from "../dist/logger.js";
|
|
5
|
-
|
|
6
|
-
async function main() {
|
|
7
|
-
const lines = [];
|
|
8
|
-
const live = await getLiveUsage(true);
|
|
9
|
-
lines.push(
|
|
10
|
-
live
|
|
11
|
-
? formatUsageReport(live)
|
|
12
|
-
: "Live Qoder usage unavailable (not logged in or Qoder runtime unavailable).",
|
|
13
|
-
);
|
|
14
|
-
|
|
15
|
-
const summary = summarize();
|
|
16
|
-
lines.push("");
|
|
17
|
-
lines.push("Local Usage Ledger");
|
|
18
|
-
lines.push(` Reference cost: ${formatCost(summary?.totalCostUsd ?? 0)}`);
|
|
19
|
-
lines.push(` Turns: ${summary?.turnCount ?? 0}`);
|
|
20
|
-
lines.push(` Tokens: ${summary?.totalInputTokens ?? 0} in / ${summary?.totalOutputTokens ?? 0} out`);
|
|
21
|
-
|
|
22
|
-
const models = Object.entries(summary?.byModel ?? {});
|
|
23
|
-
if (models.length > 0) {
|
|
24
|
-
lines.push(" By model:");
|
|
25
|
-
for (const [name, bucket] of models) {
|
|
26
|
-
lines.push(` ${name}: ${formatCost(bucket.costUsd)} (${bucket.turns} turns)`);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
process.stdout.write(lines.join("\n"));
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
main().catch((error) => {
|
|
34
|
-
process.stderr.write(`Unable to read Qoder usage: ${describeError(error)}\n`);
|
|
35
|
-
process.exitCode = 1;
|
|
36
|
-
});
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { getLiveUsage, formatUsageReport } from "../dist/usage.js";
|
|
3
|
+
import { summarize, formatCost } from "../dist/cost.js";
|
|
4
|
+
import { describeError } from "../dist/logger.js";
|
|
5
|
+
|
|
6
|
+
async function main() {
|
|
7
|
+
const lines = [];
|
|
8
|
+
const live = await getLiveUsage(true);
|
|
9
|
+
lines.push(
|
|
10
|
+
live
|
|
11
|
+
? formatUsageReport(live)
|
|
12
|
+
: "Live Qoder usage unavailable (not logged in or Qoder runtime unavailable).",
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
const summary = summarize();
|
|
16
|
+
lines.push("");
|
|
17
|
+
lines.push("Local Usage Ledger");
|
|
18
|
+
lines.push(` Reference cost: ${formatCost(summary?.totalCostUsd ?? 0)}`);
|
|
19
|
+
lines.push(` Turns: ${summary?.turnCount ?? 0}`);
|
|
20
|
+
lines.push(` Tokens: ${summary?.totalInputTokens ?? 0} in / ${summary?.totalOutputTokens ?? 0} out`);
|
|
21
|
+
|
|
22
|
+
const models = Object.entries(summary?.byModel ?? {});
|
|
23
|
+
if (models.length > 0) {
|
|
24
|
+
lines.push(" By model:");
|
|
25
|
+
for (const [name, bucket] of models) {
|
|
26
|
+
lines.push(` ${name}: ${formatCost(bucket.costUsd)} (${bucket.turns} turns)`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
process.stdout.write(lines.join("\n"));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
main().catch((error) => {
|
|
34
|
+
process.stderr.write(`Unable to read Qoder usage: ${describeError(error)}\n`);
|
|
35
|
+
process.exitCode = 1;
|
|
36
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"language-model.d.ts","sourceRoot":"","sources":["../src/language-model.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,eAAe,EACf,0BAA0B,EAG1B,6BAA6B,EAC7B,yBAAyB,EACzB,2BAA2B,EAE5B,MAAM,kBAAkB,CAAC;AAE1B,OAAO,KAAK,EAAkB,eAAe,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAEtG,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAKzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAOrD,KAAK,gBAAgB,GAAG,+BAA+B,CAAC,yBAAyB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"language-model.d.ts","sourceRoot":"","sources":["../src/language-model.ts"],"names":[],"mappings":"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"}
|
package/dist/language-model.js
CHANGED
|
@@ -180,6 +180,13 @@ function requestTimeoutMs(value) {
|
|
|
180
180
|
return DEFAULT_REQUEST_TIMEOUT_MS;
|
|
181
181
|
return Math.min(MAX_REQUEST_TIMEOUT_MS, Math.max(1, Math.floor(value)));
|
|
182
182
|
}
|
|
183
|
+
function boundedMilliseconds(value, fallback, max) {
|
|
184
|
+
if (value === undefined)
|
|
185
|
+
return undefined;
|
|
186
|
+
if (typeof value !== "number" || !Number.isFinite(value))
|
|
187
|
+
return fallback;
|
|
188
|
+
return Math.min(max, Math.max(0, Math.floor(value)));
|
|
189
|
+
}
|
|
183
190
|
function abortError() {
|
|
184
191
|
const error = new Error("Qoder request aborted");
|
|
185
192
|
error.name = "AbortError";
|
|
@@ -735,6 +742,12 @@ export class QoderLanguageModel {
|
|
|
735
742
|
cwd,
|
|
736
743
|
abortController,
|
|
737
744
|
};
|
|
745
|
+
const controlRequestTimeoutMs = boundedMilliseconds(this.bridgeOptions.controlRequestTimeoutMs, 60_000, 5 * 60_000);
|
|
746
|
+
if (controlRequestTimeoutMs !== undefined)
|
|
747
|
+
opts.controlRequestTimeoutMs = controlRequestTimeoutMs;
|
|
748
|
+
const closeGraceMs = boundedMilliseconds(this.bridgeOptions.closeGraceMs, 2_000, CLEANUP_GRACE_MS);
|
|
749
|
+
if (closeGraceMs !== undefined)
|
|
750
|
+
opts.closeGraceMs = closeGraceMs;
|
|
738
751
|
if (onAuthExpired)
|
|
739
752
|
opts.onAuthExpired = onAuthExpired;
|
|
740
753
|
if (cli)
|