@amir83nasr/10router 0.1.17 → 0.1.18
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/.next/BUILD_ID +1 -1
- package/.next/app-path-routes-manifest.json +8 -8
- package/.next/build-manifest.json +2 -2
- package/.next/prerender-manifest.json +3 -3
- package/.next/server/app/(dashboard)/dashboard/cli-tools/[toolId]/page.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/cli-tools/[toolId]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/cli-tools/page.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/cli-tools/page_client-reference-manifest.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/combos/page.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/combos/page_client-reference-manifest.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/console-log/page.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/console-log/page_client-reference-manifest.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/endpoint/page.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/endpoint/page_client-reference-manifest.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/media-providers/systemone/[id]/page.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/media-providers/systemone/[id]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/media-providers/systemone/page.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/media-providers/systemone/page_client-reference-manifest.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/page.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/page_client-reference-manifest.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/profile/page.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/profile/page_client-reference-manifest.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/providers/[id]/page.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/providers/[id]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/providers/new/page.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/providers/new/page_client-reference-manifest.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/providers/page.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/providers/page_client-reference-manifest.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/proxy-pools/page.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/proxy-pools/page_client-reference-manifest.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/pxpipe/page.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/pxpipe/page_client-reference-manifest.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/quota/page.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/quota/page_client-reference-manifest.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/token-saver/page.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/token-saver/page_client-reference-manifest.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/usage/page.js +1 -1
- package/.next/server/app/(dashboard)/dashboard/usage/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_global-error.html +1 -1
- package/.next/server/app/_global-error.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found/page.js +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.rsc +5 -5
- package/.next/server/app/_not-found.segments/_full.segment.rsc +5 -5
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +5 -5
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/api/cli-tools/all-statuses/route.js +1 -1
- package/.next/server/app/api/cli-tools/claude-settings/route.js +1 -1
- package/.next/server/app/api/cli-tools/codex-settings/route.js +1 -1
- package/.next/server/app/api/cli-tools/cowork-mcp-registry/route.js +1 -1
- package/.next/server/app/api/cli-tools/cowork-mcp-tools/route.js +1 -1
- package/.next/server/app/api/cli-tools/cowork-settings/route.js +1 -1
- package/.next/server/app/api/cli-tools/dsh-settings/route.js +1 -1
- package/.next/server/app/api/cli-tools/opencode-settings/route.js +1 -1
- package/.next/server/app/api/models/route.js +1 -1
- package/.next/server/app/api/oauth/[provider]/[action]/route.js +1 -1
- package/.next/server/app/api/oauth/codex/bulk-import/route.js +1 -1
- package/.next/server/app/api/oauth/codex/import-token/route.js +1 -1
- package/.next/server/app/api/providers/[id]/models/route.js +1 -1
- package/.next/server/app/api/providers/[id]/test/route.js +1 -1
- package/.next/server/app/api/providers/client/route.js +1 -1
- package/.next/server/app/api/providers/route.js +1 -1
- package/.next/server/app/api/providers/test-batch/route.js +1 -1
- package/.next/server/app/api/providers/validate/route.js +1 -1
- package/.next/server/app/api/settings/route.js +1 -1
- package/.next/server/app/api/translator/console-logs/route.js +1 -1
- package/.next/server/app/api/translator/console-logs/stream/route.js +1 -1
- package/.next/server/app/api/translator/send/route.js +1 -1
- package/.next/server/app/api/translator/translate/route.js +1 -1
- package/.next/server/app/api/tunnel/disable/route.js +1 -1
- package/.next/server/app/api/tunnel/enable/route.js +1 -1
- package/.next/server/app/api/tunnel/tailscale-disable/route.js +1 -1
- package/.next/server/app/api/tunnel/tailscale-enable/route.js +1 -1
- package/.next/server/app/api/tunnel/tailscale-install/route.js +2 -2
- package/.next/server/app/api/usage/[connectionId]/codex-reset-credits/route.js +1 -1
- package/.next/server/app/api/usage/[connectionId]/route.js +1 -1
- package/.next/server/app/api/v1/api/chat/route.js +1 -1
- package/.next/server/app/api/v1/audio/speech/route.js +1 -1
- package/.next/server/app/api/v1/audio/transcriptions/route.js +1 -1
- package/.next/server/app/api/v1/chat/completions/route.js +1 -1
- package/.next/server/app/api/v1/embeddings/route.js +1 -1
- package/.next/server/app/api/v1/images/generations/route.js +1 -1
- package/.next/server/app/api/v1/messages/route.js +1 -1
- package/.next/server/app/api/v1/models/[...model]/route.js +1 -1
- package/.next/server/app/api/v1/models/route.js +1 -1
- package/.next/server/app/api/v1/responses/compact/route.js +1 -1
- package/.next/server/app/api/v1/responses/route.js +1 -1
- package/.next/server/app/api/v1/route.js +1 -1
- package/.next/server/app/api/v1/search/route.js +1 -1
- package/.next/server/app/api/v1/systemone/route.js +1 -1
- package/.next/server/app/api/v1/videos/[id]/route.js +1 -1
- package/.next/server/app/api/v1/videos/edits/route.js +1 -1
- package/.next/server/app/api/v1/videos/extensions/route.js +1 -1
- package/.next/server/app/api/v1/videos/generations/route.js +1 -1
- package/.next/server/app/api/v1/web/fetch/route.js +1 -1
- package/.next/server/app/api/v1beta/models/[...path]/route.js +1 -1
- package/.next/server/app/api/version/route.js +1 -1
- package/.next/server/app/callback/page.js +1 -1
- package/.next/server/app/callback/page_client-reference-manifest.js +1 -1
- package/.next/server/app/callback.html +1 -1
- package/.next/server/app/callback.rsc +6 -6
- package/.next/server/app/callback.segments/_full.segment.rsc +6 -6
- package/.next/server/app/callback.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/callback.segments/callback/__PAGE__.segment.rsc +6 -6
- package/.next/server/app/dashboard/cli-tools.html +1 -1
- package/.next/server/app/dashboard/cli-tools.rsc +8 -8
- package/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools/__PAGE__.segment.rsc +7 -7
- package/.next/server/app/dashboard/cli-tools.segments/_full.segment.rsc +8 -8
- package/.next/server/app/dashboard/cli-tools.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/dashboard/combos.html +1 -1
- package/.next/server/app/dashboard/combos.rsc +7 -7
- package/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos/__PAGE__.segment.rsc +7 -7
- package/.next/server/app/dashboard/combos.segments/_full.segment.rsc +7 -7
- package/.next/server/app/dashboard/combos.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/dashboard/endpoint.html +1 -1
- package/.next/server/app/dashboard/endpoint.rsc +8 -8
- package/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint/__PAGE__.segment.rsc +7 -7
- package/.next/server/app/dashboard/endpoint.segments/_full.segment.rsc +8 -8
- package/.next/server/app/dashboard/endpoint.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/dashboard/media-providers/systemone.html +1 -1
- package/.next/server/app/dashboard/media-providers/systemone.rsc +7 -7
- package/.next/server/app/dashboard/media-providers/systemone.segments/!KGRhc2hib2FyZCk/dashboard/media-providers/systemone/__PAGE__.segment.rsc +7 -7
- package/.next/server/app/dashboard/media-providers/systemone.segments/_full.segment.rsc +7 -7
- package/.next/server/app/dashboard/media-providers/systemone.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/dashboard/profile.html +1 -1
- package/.next/server/app/dashboard/profile.rsc +7 -7
- package/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile/__PAGE__.segment.rsc +7 -7
- package/.next/server/app/dashboard/profile.segments/_full.segment.rsc +7 -7
- package/.next/server/app/dashboard/profile.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/dashboard/providers/new.html +1 -1
- package/.next/server/app/dashboard/providers/new.rsc +7 -7
- package/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new/__PAGE__.segment.rsc +7 -7
- package/.next/server/app/dashboard/providers/new.segments/_full.segment.rsc +7 -7
- package/.next/server/app/dashboard/providers/new.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/dashboard/providers.html +1 -1
- package/.next/server/app/dashboard/providers.rsc +7 -7
- package/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers/__PAGE__.segment.rsc +7 -7
- package/.next/server/app/dashboard/providers.segments/_full.segment.rsc +7 -7
- package/.next/server/app/dashboard/providers.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/dashboard/proxy-pools.html +1 -1
- package/.next/server/app/dashboard/proxy-pools.rsc +7 -7
- package/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools/__PAGE__.segment.rsc +7 -7
- package/.next/server/app/dashboard/proxy-pools.segments/_full.segment.rsc +7 -7
- package/.next/server/app/dashboard/proxy-pools.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/dashboard/pxpipe.html +1 -1
- package/.next/server/app/dashboard/pxpipe.rsc +6 -6
- package/.next/server/app/dashboard/pxpipe.segments/!KGRhc2hib2FyZCk/dashboard/pxpipe/__PAGE__.segment.rsc +6 -6
- package/.next/server/app/dashboard/pxpipe.segments/_full.segment.rsc +6 -6
- package/.next/server/app/dashboard/pxpipe.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/dashboard/quota.html +2 -2
- package/.next/server/app/dashboard/quota.rsc +8 -8
- package/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota/__PAGE__.segment.rsc +8 -8
- package/.next/server/app/dashboard/quota.segments/_full.segment.rsc +8 -8
- package/.next/server/app/dashboard/quota.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/dashboard/settings/pricing/page.js +1 -1
- package/.next/server/app/dashboard/settings/pricing/page_client-reference-manifest.js +1 -1
- package/.next/server/app/dashboard/settings/pricing.html +1 -1
- package/.next/server/app/dashboard/settings/pricing.rsc +5 -5
- package/.next/server/app/dashboard/settings/pricing.segments/_full.segment.rsc +5 -5
- package/.next/server/app/dashboard/settings/pricing.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing/__PAGE__.segment.rsc +5 -5
- package/.next/server/app/dashboard/token-saver.html +1 -1
- package/.next/server/app/dashboard/token-saver.rsc +6 -6
- package/.next/server/app/dashboard/token-saver.segments/!KGRhc2hib2FyZCk/dashboard/token-saver/__PAGE__.segment.rsc +6 -6
- package/.next/server/app/dashboard/token-saver.segments/_full.segment.rsc +6 -6
- package/.next/server/app/dashboard/token-saver.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/dashboard/usage.html +2 -2
- package/.next/server/app/dashboard/usage.rsc +7 -7
- package/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage/__PAGE__.segment.rsc +7 -7
- package/.next/server/app/dashboard/usage.segments/_full.segment.rsc +7 -7
- package/.next/server/app/dashboard/usage.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/dashboard.html +1 -1
- package/.next/server/app/dashboard.rsc +8 -8
- package/.next/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard/__PAGE__.segment.rsc +7 -7
- package/.next/server/app/dashboard.segments/_full.segment.rsc +8 -8
- package/.next/server/app/dashboard.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/index.html +1 -1
- package/.next/server/app/index.rsc +5 -5
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +5 -5
- package/.next/server/app/index.segments/_full.segment.rsc +5 -5
- package/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/landing/page.js +1 -1
- package/.next/server/app/landing/page_client-reference-manifest.js +1 -1
- package/.next/server/app/landing.html +1 -1
- package/.next/server/app/landing.rsc +6 -6
- package/.next/server/app/landing.segments/_full.segment.rsc +6 -6
- package/.next/server/app/landing.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/landing.segments/landing/__PAGE__.segment.rsc +6 -6
- package/.next/server/app/login/page.js +1 -1
- package/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/server/app/login.html +1 -1
- package/.next/server/app/login.rsc +5 -5
- package/.next/server/app/login.segments/_full.segment.rsc +5 -5
- package/.next/server/app/login.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +5 -5
- package/.next/server/app/page.js +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +8 -8
- package/.next/server/chunks/1003.js +1 -1
- package/.next/server/chunks/1649.js +1 -1
- package/.next/server/chunks/2143.js +1 -1
- package/.next/server/chunks/2151.js +1 -1
- package/.next/server/chunks/2282.js +2 -2
- package/.next/server/chunks/2801.js +1 -1
- package/.next/server/chunks/3671.js +1 -1
- package/.next/server/chunks/6343.js +10 -10
- package/.next/server/chunks/7591.js +1 -1
- package/.next/server/chunks/9429.js +1 -1
- package/.next/server/middleware-build-manifest.js +1 -1
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.js +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/{1660-e0fb9957b437ec4a.js → 1660-084df607ff4f889d.js} +1 -1
- package/.next/static/chunks/{1699-13ee6864a8a31a96.js → 1699-49be310981e2759e.js} +2 -2
- package/.next/static/chunks/{3577-cd98d40e3099e1b0.js → 3577-1f02993330d7fba7.js} +1 -1
- package/.next/static/chunks/{5862-f98c2f3d480b80d2.js → 5862-6f3a3a6d4c00100d.js} +1 -1
- package/.next/static/chunks/{6770-e2921b2ce695ed57.js → 6770-9e948c92e87956c4.js} +1 -1
- package/.next/static/chunks/{9150-8316559e1687b4a8.js → 9150-32b4247b1af5e206.js} +1 -1
- package/.next/static/chunks/{9ce8c186-3c7d7dbc5d428052.js → 9ce8c186-6cd204e9c27ecee1.js} +1 -1
- package/CHANGELOG.md +4 -0
- package/open-sse/executors/opencode.js +20 -0
- package/open-sse/providers/capabilities.js +30 -0
- package/open-sse/providers/models/helpers.js +14 -0
- package/open-sse/services/lazyRuntime.js +110 -0
- package/open-sse/services/opencodeTlsClient.js +91 -0
- package/open-sse/utils/writableDataDir.js +32 -0
- package/package.json +1 -1
- /package/.next/static/{alTg1qNVWmX6-0j1DLgF7 → PyHCF87rmgiD0pV5fDUOP}/_buildManifest.js +0 -0
- /package/.next/static/{alTg1qNVWmX6-0j1DLgF7 → PyHCF87rmgiD0pV5fDUOP}/_ssgManifest.js +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to 10Router will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.1.18] — 2026-10-30
|
|
6
|
+
|
|
7
|
+
- Synced OpenCode free-tier and OpenCode Go improvements from 9router: TLS-impersonating client (wreq-js) for the free tier, opencode free-tier capability entries (glm-5.3-flash-free on openai format, mimo reasoning, deepseek-v4.1-flash-free 330k context cap), and `isOpencodeFreeTierModel`/`isDeepSeekModel` helpers.
|
|
8
|
+
|
|
5
9
|
## [0.1.17] — 2026-10-26
|
|
6
10
|
|
|
7
11
|
- Fix: OpenCode Go routed each model to the provider's default endpoint instead of one it actually serves. An OpenAI-format client asking for a claude-only model (`claude-haiku-5-5`, `minimax-m2.7`) was sent to `/chat/completions` and rejected upstream with `ModelProtocolUnsupported`; `chatCore` and the tests now share `resolveModelTransport` (`open-sse/services/provider.js`), which prefers the sourceFormat-matched endpoint (no translation) and otherwise a model-declared one.
|
|
@@ -6,6 +6,7 @@ import { getThinkingLevels } from "../providers/thinkingLevels.js";
|
|
|
6
6
|
import { injectReasoningContent } from "../utils/reasoningContentInjector.js";
|
|
7
7
|
import { resolveSessionId } from "../utils/sessionManager.js";
|
|
8
8
|
import { isMuseSparkModel } from "../providers/models/helpers.js";
|
|
9
|
+
import { opencodeTlsFetch, OpencodeTlsUnavailableError } from "../services/opencodeTlsClient.js";
|
|
9
10
|
import {
|
|
10
11
|
applyFingerprintTools,
|
|
11
12
|
detectToolShape,
|
|
@@ -357,6 +358,25 @@ export class OpenCodeExecutor extends BaseExecutor {
|
|
|
357
358
|
const result = await super.execute({
|
|
358
359
|
...args,
|
|
359
360
|
credentials: this.prepareRequestCredentials(args),
|
|
361
|
+
directFetch: async (url, options) => {
|
|
362
|
+
try {
|
|
363
|
+
return await opencodeTlsFetch(
|
|
364
|
+
url,
|
|
365
|
+
{
|
|
366
|
+
method: options.method,
|
|
367
|
+
headers: options.headers,
|
|
368
|
+
body: options.body,
|
|
369
|
+
},
|
|
370
|
+
{ signal: options.signal },
|
|
371
|
+
);
|
|
372
|
+
} catch (error) {
|
|
373
|
+
if (error instanceof OpencodeTlsUnavailableError) {
|
|
374
|
+
// Fail-open: wreq-js not installed; use native fetch.
|
|
375
|
+
return fetch(url, options);
|
|
376
|
+
}
|
|
377
|
+
throw error;
|
|
378
|
+
}
|
|
379
|
+
},
|
|
360
380
|
});
|
|
361
381
|
// Only a temporary quota window earns the breaker. Entitlement 429s
|
|
362
382
|
// ("free models work in OpenCode") are permanent plan gates: cooling the
|
|
@@ -253,6 +253,16 @@ export const MODEL_CAPABILITIES = {
|
|
|
253
253
|
contextWindow: 1000000,
|
|
254
254
|
maxOutput: 131072,
|
|
255
255
|
},
|
|
256
|
+
"glm-5.3-flash-free": {
|
|
257
|
+
vision: true,
|
|
258
|
+
videoInput: true,
|
|
259
|
+
pdf: true,
|
|
260
|
+
reasoning: true,
|
|
261
|
+
thinkingFormat: "openai",
|
|
262
|
+
thinkingCanDisable: false,
|
|
263
|
+
contextWindow: 1000000,
|
|
264
|
+
maxOutput: 128000,
|
|
265
|
+
},
|
|
256
266
|
"glm-4.6v": {
|
|
257
267
|
vision: true,
|
|
258
268
|
videoInput: true,
|
|
@@ -621,6 +631,26 @@ export const PROVIDER_CAPABILITIES = {
|
|
|
621
631
|
// /api/v2/image/upload and leaves image_urls/chat_context.imageUrls null
|
|
622
632
|
// (same as qodercli). reasoning:true on all of them — every model can
|
|
623
633
|
// reason; the upstream is_reasoning flag only drives model_config selection.
|
|
634
|
+
// OpenCode Free (oc)
|
|
635
|
+
opencode: {
|
|
636
|
+
"mimo-v2.6-flash-free": {
|
|
637
|
+
vision: true,
|
|
638
|
+
audioInput: true,
|
|
639
|
+
videoInput: true,
|
|
640
|
+
reasoning: true,
|
|
641
|
+
thinkingFormat: "openai",
|
|
642
|
+
thinkingCanDisable: true,
|
|
643
|
+
contextWindow: 1048576,
|
|
644
|
+
maxOutput: 131072,
|
|
645
|
+
},
|
|
646
|
+
"deepseek-v4.1-flash-free": {
|
|
647
|
+
vision: true,
|
|
648
|
+
reasoning: true,
|
|
649
|
+
thinkingFormat: "deepseek",
|
|
650
|
+
contextWindow: 330000,
|
|
651
|
+
maxOutput: 128000,
|
|
652
|
+
},
|
|
653
|
+
},
|
|
624
654
|
// thinkingFormat keeps the true-model family for documentation/UI, but
|
|
625
655
|
// thinkingCanDisable:false everywhere: the executor only forwards
|
|
626
656
|
// messages/tools/max_tokens, and thinking is fixed upstream via
|
|
@@ -25,3 +25,17 @@ export function isMuseSparkModel(modelId) {
|
|
|
25
25
|
const base = clean.includes("/") ? clean.split("/").pop() : clean;
|
|
26
26
|
return /^muse[-_]?spark(?:$|[-_:.\s])/i.test(base);
|
|
27
27
|
}
|
|
28
|
+
|
|
29
|
+
export function isDeepSeekModel(modelId) {
|
|
30
|
+
if (!modelId || typeof modelId !== "string") return false;
|
|
31
|
+
const clean = modelId.replace(/\([^()]+\)\s*$/, "").trim();
|
|
32
|
+
const base = clean.includes("/") ? clean.split("/").pop() : clean;
|
|
33
|
+
return /^deepseek-/i.test(base);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function isOpencodeFreeTierModel(modelId) {
|
|
37
|
+
if (!modelId || typeof modelId !== "string") return false;
|
|
38
|
+
const clean = modelId.replace(/\([^()]+\)\s*$/, "").trim();
|
|
39
|
+
const base = clean.includes("/") ? clean.split("/").pop() : clean;
|
|
40
|
+
return /-free$/i.test(base);
|
|
41
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// Lazy loader for heavy optional runtime deps (playwright-core, wreq-js).
|
|
2
|
+
//
|
|
3
|
+
// They are devDependencies only, so end-user installs stay small. On first
|
|
4
|
+
// use the package is downloaded into <DATA_DIR>/runtime and imported from there.
|
|
5
|
+
|
|
6
|
+
import { spawn } from "node:child_process";
|
|
7
|
+
import fs from "node:fs";
|
|
8
|
+
import path from "node:path";
|
|
9
|
+
import { pathToFileURL } from "node:url";
|
|
10
|
+
import { getWritableDataDir } from "../utils/writableDataDir.js";
|
|
11
|
+
|
|
12
|
+
const LAZY_DEP_VERSIONS = {
|
|
13
|
+
"playwright-core": "^1.62.1",
|
|
14
|
+
"wreq-js": "^3.2.0",
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
function getRuntimeDir() {
|
|
18
|
+
return path.join(getWritableDataDir(), "runtime");
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let createRequirePromise;
|
|
22
|
+
function getCreateRequire() {
|
|
23
|
+
createRequirePromise ??= import(/* webpackIgnore: true */ "node:module").then(
|
|
24
|
+
(mod) => mod.createRequire,
|
|
25
|
+
);
|
|
26
|
+
return createRequirePromise;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function isModuleMissing(error) {
|
|
30
|
+
const code = String(error?.code || "");
|
|
31
|
+
return code === "MODULE_NOT_FOUND" || code === "ERR_MODULE_NOT_FOUND";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function npmInstall(pkg, version) {
|
|
35
|
+
const cwd = getRuntimeDir();
|
|
36
|
+
fs.mkdirSync(cwd, { recursive: true });
|
|
37
|
+
const manifest = path.join(cwd, "package.json");
|
|
38
|
+
if (!fs.existsSync(manifest)) {
|
|
39
|
+
fs.writeFileSync(
|
|
40
|
+
manifest,
|
|
41
|
+
JSON.stringify({ name: "10router-runtime", private: true }, null, 2),
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
const npm = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
45
|
+
const args = ["install", "--no-audit", "--no-fund", "--prefer-online", `${pkg}@${version}`];
|
|
46
|
+
return new Promise((resolve) => {
|
|
47
|
+
const child = spawn(npm, args, {
|
|
48
|
+
cwd,
|
|
49
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
50
|
+
shell: process.platform === "win32",
|
|
51
|
+
});
|
|
52
|
+
let stderr = "";
|
|
53
|
+
child.stderr?.on("data", (chunk) => {
|
|
54
|
+
stderr += String(chunk);
|
|
55
|
+
});
|
|
56
|
+
child.on("error", (error) => resolve({ ok: false, stderr: String(error.message || error) }));
|
|
57
|
+
child.on("close", (status) => resolve({ ok: status === 0, stderr }));
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async function installIntoRuntime(pkg, version) {
|
|
62
|
+
const res = await npmInstall(pkg, version);
|
|
63
|
+
if (!res.ok) {
|
|
64
|
+
const reason =
|
|
65
|
+
(res.stderr.match(/npm ERR! ?(.+)/) || [])[1] ||
|
|
66
|
+
res.stderr.split("\n").filter(Boolean).pop() ||
|
|
67
|
+
"unknown npm error";
|
|
68
|
+
throw new Error(
|
|
69
|
+
`${pkg} is missing and the on-demand install failed (${String(reason).slice(0, 160)}) — ` +
|
|
70
|
+
`install it manually: cd "${getRuntimeDir()}" && npm install ${pkg}@${version}`,
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const inflight = new Map();
|
|
76
|
+
|
|
77
|
+
async function load(pkg) {
|
|
78
|
+
try {
|
|
79
|
+
return await import(/* webpackIgnore: true */ pkg);
|
|
80
|
+
} catch (error) {
|
|
81
|
+
if (!isModuleMissing(error)) throw error;
|
|
82
|
+
}
|
|
83
|
+
const createRequire = await getCreateRequire();
|
|
84
|
+
const runtimeRequire = createRequire(path.join(getRuntimeDir(), "package.json"));
|
|
85
|
+
try {
|
|
86
|
+
return await import(/* webpackIgnore: true */ pathToFileURL(runtimeRequire.resolve(pkg)).href);
|
|
87
|
+
} catch (error) {
|
|
88
|
+
if (!isModuleMissing(error)) throw error;
|
|
89
|
+
}
|
|
90
|
+
const version = LAZY_DEP_VERSIONS[pkg] || "latest";
|
|
91
|
+
await installIntoRuntime(pkg, version);
|
|
92
|
+
try {
|
|
93
|
+
return await import(/* webpackIgnore: true */ pathToFileURL(runtimeRequire.resolve(pkg)).href);
|
|
94
|
+
} catch (error) {
|
|
95
|
+
if (!isModuleMissing(error)) throw error;
|
|
96
|
+
fs.rmSync(path.join(getRuntimeDir(), "node_modules", pkg), { recursive: true, force: true });
|
|
97
|
+
await installIntoRuntime(pkg, version);
|
|
98
|
+
return import(/* webpackIgnore: true */ pathToFileURL(runtimeRequire.resolve(pkg)).href);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function loadRuntimeDep(pkg) {
|
|
103
|
+
if (!inflight.has(pkg)) {
|
|
104
|
+
inflight.set(
|
|
105
|
+
pkg,
|
|
106
|
+
load(pkg).finally(() => inflight.delete(pkg)),
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
return inflight.get(pkg);
|
|
110
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// TLS-impersonating HTTP client for opencode.ai's free tier.
|
|
2
|
+
|
|
3
|
+
import { loadRuntimeDep } from "./lazyRuntime.js";
|
|
4
|
+
|
|
5
|
+
const OPENCODE_CIPHER_LIST = [
|
|
6
|
+
"TLS_AES_128_GCM_SHA256",
|
|
7
|
+
"TLS_AES_256_GCM_SHA384",
|
|
8
|
+
"TLS_CHACHA20_POLY1305_SHA256",
|
|
9
|
+
"ECDHE-ECDSA-AES128-GCM-SHA256",
|
|
10
|
+
"ECDHE-RSA-AES128-GCM-SHA256",
|
|
11
|
+
"ECDHE-ECDSA-AES256-GCM-SHA384",
|
|
12
|
+
"ECDHE-RSA-AES256-GCM-SHA384",
|
|
13
|
+
"ECDHE-ECDSA-CHACHA20-POLY1305",
|
|
14
|
+
"ECDHE-RSA-CHACHA20-POLY1305",
|
|
15
|
+
"ECDHE-ECDSA-AES128-SHA",
|
|
16
|
+
"ECDHE-RSA-AES128-SHA",
|
|
17
|
+
"ECDHE-ECDSA-AES256-SHA",
|
|
18
|
+
"ECDHE-RSA-AES256-SHA",
|
|
19
|
+
"AES128-GCM-SHA256",
|
|
20
|
+
"AES256-GCM-SHA384",
|
|
21
|
+
"AES128-SHA",
|
|
22
|
+
"AES256-SHA",
|
|
23
|
+
].join(":");
|
|
24
|
+
|
|
25
|
+
const DEFAULT_TIMEOUT_MS = 120000;
|
|
26
|
+
|
|
27
|
+
let sessionPromise = null;
|
|
28
|
+
|
|
29
|
+
export class OpencodeTlsUnavailableError extends Error {
|
|
30
|
+
constructor(message) {
|
|
31
|
+
super(message);
|
|
32
|
+
this.name = "OpencodeTlsUnavailableError";
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function loadSession() {
|
|
37
|
+
if (!sessionPromise) {
|
|
38
|
+
sessionPromise = (async () => {
|
|
39
|
+
const wreq = await loadRuntimeDep("wreq-js");
|
|
40
|
+
if (typeof wreq.createSession !== "function") {
|
|
41
|
+
throw new Error("wreq-js runtime is missing createSession");
|
|
42
|
+
}
|
|
43
|
+
return wreq.createSession({
|
|
44
|
+
emulation: { tlsOptions: { cipherList: OPENCODE_CIPHER_LIST } },
|
|
45
|
+
});
|
|
46
|
+
})().catch((error) => {
|
|
47
|
+
sessionPromise = null;
|
|
48
|
+
throw error;
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
return sessionPromise;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function resetOpencodeTlsSession() {
|
|
55
|
+
const pending = sessionPromise;
|
|
56
|
+
sessionPromise = null;
|
|
57
|
+
pending?.then((session) => session.close?.()).catch(() => {});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export async function opencodeTlsFetch(
|
|
61
|
+
url,
|
|
62
|
+
init = {},
|
|
63
|
+
{ signal, timeoutMs = DEFAULT_TIMEOUT_MS } = {},
|
|
64
|
+
) {
|
|
65
|
+
let session;
|
|
66
|
+
try {
|
|
67
|
+
session = await loadSession();
|
|
68
|
+
} catch (error) {
|
|
69
|
+
throw new OpencodeTlsUnavailableError(
|
|
70
|
+
`wreq-js unavailable (${error instanceof Error ? error.message : "unknown"}) — install the optional wreq-js dependency to reach the OpenCode free tier`,
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const options = {
|
|
75
|
+
method: init.method || "GET",
|
|
76
|
+
headers: init.headers,
|
|
77
|
+
redirect: "follow",
|
|
78
|
+
timeout: timeoutMs,
|
|
79
|
+
};
|
|
80
|
+
if (init.body !== undefined) options.body = init.body;
|
|
81
|
+
if (signal) options.signal = signal;
|
|
82
|
+
|
|
83
|
+
const res = await session.fetch(url, options);
|
|
84
|
+
const headers = {};
|
|
85
|
+
res.headers?.forEach?.((value, key) => {
|
|
86
|
+
headers[key] = value;
|
|
87
|
+
});
|
|
88
|
+
return new Response(res.body, { status: res.status, statusText: res.statusText, headers });
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export const __test__ = { OPENCODE_CIPHER_LIST };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// Resolve a writable data directory: DATA_DIR first, then ~/.10router, then
|
|
2
|
+
// legacy ~/.9router, then tmpdir. Some installs point DATA_DIR at root-owned
|
|
3
|
+
// paths that the server process cannot write browser profiles or runtime
|
|
4
|
+
// installs into.
|
|
5
|
+
|
|
6
|
+
import fs from "node:fs";
|
|
7
|
+
import os from "node:os";
|
|
8
|
+
import path from "node:path";
|
|
9
|
+
|
|
10
|
+
let cached = null;
|
|
11
|
+
|
|
12
|
+
export function getWritableDataDir() {
|
|
13
|
+
if (cached) return cached;
|
|
14
|
+
const candidates = [
|
|
15
|
+
process.env.DATA_DIR,
|
|
16
|
+
path.join(os.homedir(), ".10router"),
|
|
17
|
+
path.join(os.homedir(), ".9router"),
|
|
18
|
+
path.join(os.tmpdir(), "10router"),
|
|
19
|
+
].filter(Boolean);
|
|
20
|
+
for (const base of candidates) {
|
|
21
|
+
try {
|
|
22
|
+
fs.mkdirSync(base, { recursive: true });
|
|
23
|
+
fs.accessSync(base, fs.constants.W_OK);
|
|
24
|
+
cached = base;
|
|
25
|
+
return base;
|
|
26
|
+
} catch {
|
|
27
|
+
// Not writable — try the next candidate.
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
cached = process.cwd();
|
|
31
|
+
return cached;
|
|
32
|
+
}
|
package/package.json
CHANGED
|
File without changes
|
|
File without changes
|