@mars-sea/dsh-commandcode-provider 0.10.0-alpha.2 → 0.10.0-alpha.4
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 +22 -0
- package/README.md +13 -0
- package/README.zh-CN.md +13 -0
- package/lib/client.js +20 -2
- package/lib/client.js.map +1 -1
- package/lib/index.d.ts +58 -4
- package/lib/index.js +209 -17
- package/lib/index.js.map +1 -1
- package/package.json +4 -2
package/lib/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import z from "@deepseek-ai/schemastery";
|
|
|
2
2
|
import { GenerateOptions, LlmAdapter, LlmModelInfo, LlmProviderInfo, LlmResolvedModelInfo, ResolvedRetryPolicy, StreamChunk } from "@deepseek-ai/dsh-llm";
|
|
3
3
|
import { CredentialRef } from "@deepseek-ai/dsh-credentials";
|
|
4
4
|
import { TypertRemoteService, TypertSchema } from "@deepseek-ai/dsh-typert-protocol";
|
|
5
|
+
import { WebRuntime, WebSearchProvider, WebSearchRequest, WebSearchResult } from "@deepseek-ai/dsh-web";
|
|
5
6
|
import { Context } from "@deepseek-ai/cordis";
|
|
6
7
|
import { AttachmentStore } from "@deepseek-ai/dsh-attachment";
|
|
7
8
|
import { CommandDefinition } from "@deepseek-ai/dsh-commands";
|
|
@@ -24,7 +25,7 @@ declare const KNOWN_EFFORTS: Readonly<Record<string, readonly string[]>>;
|
|
|
24
25
|
*/
|
|
25
26
|
declare const KNOWN_IMAGE_MODELS: ReadonlySet<string>;
|
|
26
27
|
/**
|
|
27
|
-
* Models the official CLI's model table (command-code@1.
|
|
28
|
+
* Models the official CLI's model table (command-code@1.39.2) marks
|
|
28
29
|
* `reasoning:!0` but defines no selectable `reasoning_effort` levels — they
|
|
29
30
|
* think automatically, with Command Code driving the depth. This is the
|
|
30
31
|
* authoritative "thinks, effort not adjustable" set: `KNOWN_EFFORTS` (which
|
|
@@ -32,7 +33,7 @@ declare const KNOWN_IMAGE_MODELS: ReadonlySet<string>;
|
|
|
32
33
|
* effort levels, and this snapshot is not surfaced in the picker's compact
|
|
33
34
|
* description — it exists for programmatic consumers.
|
|
34
35
|
*
|
|
35
|
-
* Source: the command-code@1.
|
|
36
|
+
* Source: the command-code@1.39.2 bundled model table (dist/cli.mjs),
|
|
36
37
|
* cross-checked with https://commandcode.ai/docs/reference/cli/models.
|
|
37
38
|
* (`stealth/ox-alpha` left this set in command-code@1.32.1, which gave it
|
|
38
39
|
* selectable `['low', 'high', 'max']` efforts; the preview then ended in
|
|
@@ -191,7 +192,7 @@ declare function peakPricingState(modelId: string, now?: number): 'peak' | 'off-
|
|
|
191
192
|
* for models without time-of-day pricing.
|
|
192
193
|
*/
|
|
193
194
|
declare function peakPricingLabel(modelId: string, now?: number): string | undefined;
|
|
194
|
-
declare const COMMAND_CODE_CLI_VERSION = "1.
|
|
195
|
+
declare const COMMAND_CODE_CLI_VERSION = "1.39.2";
|
|
195
196
|
declare const DEFAULT_API_BASE = "https://api.commandcode.ai";
|
|
196
197
|
declare const DEFAULT_GENERATE_MAX_TOKENS = 64000;
|
|
197
198
|
declare const DEFAULT_MAX_OUTPUT_TOKENS = 65536;
|
|
@@ -948,6 +949,48 @@ declare class CommandCodeLoginFlow {
|
|
|
948
949
|
private teardown;
|
|
949
950
|
}
|
|
950
951
|
//#endregion
|
|
952
|
+
//#region src/web-search.d.ts
|
|
953
|
+
/** Stable id this provider registers under in `ctx.web`. */
|
|
954
|
+
declare const COMMANDCODE_SEARCH_PROVIDER_ID = "commandcode";
|
|
955
|
+
/**
|
|
956
|
+
* The factory-declared search provider id dsh ships by default (from
|
|
957
|
+
* `dsh-base`'s cordis patch `web.config.searchProvider`). A plugin that wants
|
|
958
|
+
* its own backend to win rewrites `WebRuntime.searchProviderId` to its own id;
|
|
959
|
+
* disabling that plugin restores this value.
|
|
960
|
+
*/
|
|
961
|
+
declare const DEFAULT_WEB_SEARCH_PROVIDER_ID = "deepseek-official";
|
|
962
|
+
/**
|
|
963
|
+
* Point the web seam's search selection at this plugin's provider (`commandcode`).
|
|
964
|
+
* Sets the runtime field; the next search call honours it because `search()`
|
|
965
|
+
* re-reads `searchProviderId` each time. Returns the prior id (or undefined).
|
|
966
|
+
*/
|
|
967
|
+
declare function selectCommandCodeSearchProvider(web: WebRuntime, enable: boolean): string | undefined;
|
|
968
|
+
/** Per-request facts the provider needs, all injected so the class stays cordis-free and testable. */
|
|
969
|
+
interface CommandCodeSearchProviderDeps {
|
|
970
|
+
/** Resolve one usable Command Code key (credential seam → env → auth file), or undefined when none. */
|
|
971
|
+
resolveKey(): Promise<string | undefined>;
|
|
972
|
+
/** The API base host (defaults to `https://api.commandcode.ai`). */
|
|
973
|
+
apiBase(): string;
|
|
974
|
+
/** Injectable fetch for tests; defaults to the global fetch. */
|
|
975
|
+
fetchImpl?: typeof fetch;
|
|
976
|
+
}
|
|
977
|
+
/**
|
|
978
|
+
* A `ctx.web` search provider backed by the Command Code Provider API. Reuses
|
|
979
|
+
* the plugin's credential chain and `apiBase`, so search "just works" with the
|
|
980
|
+
* existing key — the model-facing `web_search` tool needs no separate
|
|
981
|
+
* configuration. Selection between multiple search providers is the web seam's
|
|
982
|
+
* job (pin `searchProvider: commandcode` if ambiguous).
|
|
983
|
+
*/
|
|
984
|
+
declare class CommandCodeSearchProvider implements WebSearchProvider {
|
|
985
|
+
private readonly deps;
|
|
986
|
+
readonly id = "commandcode";
|
|
987
|
+
constructor(deps: CommandCodeSearchProviderDeps);
|
|
988
|
+
/** Cheap local check; must not make network calls. Presence of a key path + a parseable base is enough. */
|
|
989
|
+
available(): boolean;
|
|
990
|
+
search(request: WebSearchRequest, signal?: AbortSignal): Promise<WebSearchResult>;
|
|
991
|
+
private resolveKey;
|
|
992
|
+
}
|
|
993
|
+
//#endregion
|
|
951
994
|
//#region src/index.d.ts
|
|
952
995
|
declare const name = "llm-commandcode";
|
|
953
996
|
declare const inject: string[];
|
|
@@ -1012,6 +1055,17 @@ interface Config {
|
|
|
1012
1055
|
* gate. The first matching rule wins.
|
|
1013
1056
|
*/
|
|
1014
1057
|
modelAccountRules?: CommandCodeModelAccountRule[];
|
|
1058
|
+
/**
|
|
1059
|
+
* Whether to use Command Code as the backend for dsh's model-facing
|
|
1060
|
+
* `web_search` tool. When enabled, the plugin registers a `commandcode`
|
|
1061
|
+
* search provider on `ctx.web` AND rewrites the web seam's selected
|
|
1062
|
+
* `searchProviderId` to `commandcode` (so it wins over the shipped
|
|
1063
|
+
* `deepseek-official`), using the SAME Command Code API key/base as chat.
|
|
1064
|
+
* The rewrite rides dsh's internal `searchProviderId`, which is read per
|
|
1065
|
+
* search call, so a setting change lands on the next search without a
|
|
1066
|
+
* restart. Defaults to true.
|
|
1067
|
+
*/
|
|
1068
|
+
webSearch?: boolean;
|
|
1015
1069
|
/**
|
|
1016
1070
|
* Language override for the `/commandcode` Host-side command's user-facing
|
|
1017
1071
|
* copy. Host commands cannot read the client's `ctx.locale`, so this is
|
|
@@ -1039,5 +1093,5 @@ interface ResolvedCommandCodeOptions extends CommandCodeConnectionOptions {
|
|
|
1039
1093
|
declare function resolveAdapterOptions(config: Config): ResolvedCommandCodeOptions;
|
|
1040
1094
|
declare function apply(ctx: Context, config: Config): void;
|
|
1041
1095
|
//#endregion
|
|
1042
|
-
export { type ApiKeyValidation, BILLING_ACCESS_TTL_MS, COMMAND_CODE_CLI_VERSION, type CommandCodeAccountConfig, CommandCodeAccountPool, type CommandCodeAccountSlot, type CommandCodeAccountState, type CommandCodeAccountUsage, type CommandCodeAccountsReport, CommandCodeAdapter, type CommandCodeAdapterDeps, type CommandCodeBillingAccess, type CommandCodeCommandDeps, type CommandCodeConnectionOptions, type CommandCodeLoginCredentials, type CommandCodeLoginFailureReason, CommandCodeLoginFlow, type CommandCodeLoginFlowDeps, type CommandCodeLoginStatus, type CommandCodeModelAccountRule, type CommandCodeUsageDeps, type CommandCodeUsageReport, CommandCodeUsageService, Config, DEFAULT_API_BASE, DEFAULT_GENERATE_MAX_TOKENS, DEFAULT_MAX_OUTPUT_TOKENS, DEFAULT_MODELS_CACHE_PATH, DEFAULT_REQUEST_TIMEOUT_MS, DEFAULT_STREAM_IDLE_TIMEOUT_MS, KNOWN_DEALS, KNOWN_EFFORTS, KNOWN_IMAGE_MODELS, KNOWN_PEAK_PRICING, KNOWN_PLANS, KNOWN_SUBSCRIPTION_PLANS, KNOWN_THINKING_MODELS, LOGIN_ALLOWED_ORIGINS, LOGIN_BEGIN_ENDPOINT, LOGIN_BODY_LIMIT_BYTES, LOGIN_CANCEL_ENDPOINT, LOGIN_MAX_PORT_ATTEMPTS, LOGIN_START_PORT, LOGIN_STATUS_ENDPOINT, LOGIN_TIMEOUT_MS, type LoginFlowFacade, PLAN_LABELS, PLAN_ORDER, PROVIDER, type ResolveAttachments, ResolvedCommandCodeOptions, USAGE_REPORT_ENDPOINT, accountUsable, apply, applyCommands, applyUsageRemote, buildCommandAuthUrl, capabilityDescription, commandDefinition, compareByPlan, dealLabel, formatContext, inject, loginStatusSchema, matchModelRule, modelVisibleInPlan, name, parseLoginStatus, peakPricingLabel, peakPricingState, planLabel, projectSlugFromPath, resolveAdapterOptions, resolveAuthFileApiKey, selectAccountForModel, selectActiveAccount, studioBaseForApiBase, subscriptionPlanInfo, usageReportSchema, validateCommandApiKey };
|
|
1096
|
+
export { type ApiKeyValidation, BILLING_ACCESS_TTL_MS, COMMANDCODE_SEARCH_PROVIDER_ID, COMMAND_CODE_CLI_VERSION, type CommandCodeAccountConfig, CommandCodeAccountPool, type CommandCodeAccountSlot, type CommandCodeAccountState, type CommandCodeAccountUsage, type CommandCodeAccountsReport, CommandCodeAdapter, type CommandCodeAdapterDeps, type CommandCodeBillingAccess, type CommandCodeCommandDeps, type CommandCodeConnectionOptions, type CommandCodeLoginCredentials, type CommandCodeLoginFailureReason, CommandCodeLoginFlow, type CommandCodeLoginFlowDeps, type CommandCodeLoginStatus, type CommandCodeModelAccountRule, CommandCodeSearchProvider, type CommandCodeSearchProviderDeps, type CommandCodeUsageDeps, type CommandCodeUsageReport, CommandCodeUsageService, Config, DEFAULT_API_BASE, DEFAULT_GENERATE_MAX_TOKENS, DEFAULT_MAX_OUTPUT_TOKENS, DEFAULT_MODELS_CACHE_PATH, DEFAULT_REQUEST_TIMEOUT_MS, DEFAULT_STREAM_IDLE_TIMEOUT_MS, DEFAULT_WEB_SEARCH_PROVIDER_ID, KNOWN_DEALS, KNOWN_EFFORTS, KNOWN_IMAGE_MODELS, KNOWN_PEAK_PRICING, KNOWN_PLANS, KNOWN_SUBSCRIPTION_PLANS, KNOWN_THINKING_MODELS, LOGIN_ALLOWED_ORIGINS, LOGIN_BEGIN_ENDPOINT, LOGIN_BODY_LIMIT_BYTES, LOGIN_CANCEL_ENDPOINT, LOGIN_MAX_PORT_ATTEMPTS, LOGIN_START_PORT, LOGIN_STATUS_ENDPOINT, LOGIN_TIMEOUT_MS, type LoginFlowFacade, PLAN_LABELS, PLAN_ORDER, PROVIDER, type ResolveAttachments, ResolvedCommandCodeOptions, USAGE_REPORT_ENDPOINT, accountUsable, apply, applyCommands, applyUsageRemote, buildCommandAuthUrl, capabilityDescription, commandDefinition, compareByPlan, dealLabel, formatContext, inject, loginStatusSchema, matchModelRule, modelVisibleInPlan, name, parseLoginStatus, peakPricingLabel, peakPricingState, planLabel, projectSlugFromPath, resolveAdapterOptions, resolveAuthFileApiKey, selectAccountForModel, selectActiveAccount, selectCommandCodeSearchProvider, studioBaseForApiBase, subscriptionPlanInfo, usageReportSchema, validateCommandApiKey };
|
|
1043
1097
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.js
CHANGED
|
@@ -11,6 +11,7 @@ import { randomBytes, randomUUID } from "node:crypto";
|
|
|
11
11
|
import { TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
|
|
12
12
|
import { createServer } from "node:http";
|
|
13
13
|
import { createServer as createServer$1 } from "node:net";
|
|
14
|
+
import { WebError } from "@deepseek-ai/dsh-web";
|
|
14
15
|
//#region src/accounts.ts
|
|
15
16
|
/**
|
|
16
17
|
* Multi-account pool for the Command Code provider (host side).
|
|
@@ -243,7 +244,7 @@ var CommandCodeAccountPool = class {
|
|
|
243
244
|
* and API key or subscription, and Command Code's terms apply.
|
|
244
245
|
*
|
|
245
246
|
* Wire protocol (reverse-engineered by the pi plugin, command-code@1.28.4;
|
|
246
|
-
* re-verified against command-code@1.
|
|
247
|
+
* re-verified against command-code@1.39.2 — endpoints, request shape, and
|
|
247
248
|
* stream events unchanged):
|
|
248
249
|
* POST {apiBase}/alpha/generate
|
|
249
250
|
* body: { config, memory, taste, skills, params: { model, messages, tools,
|
|
@@ -314,6 +315,11 @@ const KNOWN_EFFORTS = {
|
|
|
314
315
|
"xhigh",
|
|
315
316
|
"max"
|
|
316
317
|
],
|
|
318
|
+
"deepseek/deepseek-v4-flash-fast": [
|
|
319
|
+
"low",
|
|
320
|
+
"high",
|
|
321
|
+
"max"
|
|
322
|
+
],
|
|
317
323
|
"deepseek/deepseek-v4-flash": ["high", "max"],
|
|
318
324
|
"deepseek/deepseek-v4-flash-vision-exp": ["high", "max"],
|
|
319
325
|
"deepseek/deepseek-v4-pro": ["high", "max"],
|
|
@@ -476,7 +482,7 @@ const KNOWN_IMAGE_MODELS = /* @__PURE__ */ new Set([
|
|
|
476
482
|
"z-ai/glm-5.3-flash"
|
|
477
483
|
]);
|
|
478
484
|
/**
|
|
479
|
-
* Models the official CLI's model table (command-code@1.
|
|
485
|
+
* Models the official CLI's model table (command-code@1.39.2) marks
|
|
480
486
|
* `reasoning:!0` but defines no selectable `reasoning_effort` levels — they
|
|
481
487
|
* think automatically, with Command Code driving the depth. This is the
|
|
482
488
|
* authoritative "thinks, effort not adjustable" set: `KNOWN_EFFORTS` (which
|
|
@@ -484,7 +490,7 @@ const KNOWN_IMAGE_MODELS = /* @__PURE__ */ new Set([
|
|
|
484
490
|
* effort levels, and this snapshot is not surfaced in the picker's compact
|
|
485
491
|
* description — it exists for programmatic consumers.
|
|
486
492
|
*
|
|
487
|
-
* Source: the command-code@1.
|
|
493
|
+
* Source: the command-code@1.39.2 bundled model table (dist/cli.mjs),
|
|
488
494
|
* cross-checked with https://commandcode.ai/docs/reference/cli/models.
|
|
489
495
|
* (`stealth/ox-alpha` left this set in command-code@1.32.1, which gave it
|
|
490
496
|
* selectable `['low', 'high', 'max']` efforts; the preview then ended in
|
|
@@ -544,6 +550,7 @@ const KNOWN_PLANS = {
|
|
|
544
550
|
"Qwen/Qwen3.8-27B": "go",
|
|
545
551
|
"Qwen/Qwen3.8-Flash": "go",
|
|
546
552
|
"Qwen/Qwen3.8-Max": "go",
|
|
553
|
+
"deepseek/deepseek-v4-flash-fast": "go",
|
|
547
554
|
"deepseek/deepseek-v4-flash": "go",
|
|
548
555
|
"deepseek/deepseek-v4-flash-vision-exp": "go",
|
|
549
556
|
"deepseek/deepseek-v4-pro": "go",
|
|
@@ -729,16 +736,6 @@ const KNOWN_DEALS = {
|
|
|
729
736
|
"MiniMaxAI/MiniMax-M3": { label: "50% off" },
|
|
730
737
|
"xiaomi/mimo-v2.5-pro": { label: "99% off" },
|
|
731
738
|
"xiaomi/mimo-v2.5": { label: "98% off" },
|
|
732
|
-
"minimax/minimax-m3-free": {
|
|
733
|
-
label: "FREE",
|
|
734
|
-
free: true,
|
|
735
|
-
expiresAt: "2026-09-05T23:59:59Z"
|
|
736
|
-
},
|
|
737
|
-
"minimax/minimax-m2.7-free": {
|
|
738
|
-
label: "FREE",
|
|
739
|
-
free: true,
|
|
740
|
-
expiresAt: "2026-09-05T23:59:59Z"
|
|
741
|
-
},
|
|
742
739
|
"poolside/laguna-s-2.1-free": {
|
|
743
740
|
label: "FREE",
|
|
744
741
|
free: true
|
|
@@ -769,7 +766,8 @@ const KNOWN_DEALS = {
|
|
|
769
766
|
const KNOWN_PEAK_PRICING = /* @__PURE__ */ new Set([
|
|
770
767
|
"deepseek/deepseek-v4-pro",
|
|
771
768
|
"deepseek/deepseek-v4-flash",
|
|
772
|
-
"deepseek/deepseek-v4-flash-vision-exp"
|
|
769
|
+
"deepseek/deepseek-v4-flash-vision-exp",
|
|
770
|
+
"deepseek/deepseek-v4-flash-fast"
|
|
773
771
|
]);
|
|
774
772
|
/** Peak hours (UTC, hour-of-day range end-exclusive): 01–03 and 06–09. */
|
|
775
773
|
const PEAK_HOUR_RANGES = [[1, 4], [6, 10]];
|
|
@@ -794,7 +792,7 @@ function peakPricingLabel(modelId, now = Date.now()) {
|
|
|
794
792
|
if (state === void 0) return void 0;
|
|
795
793
|
return state === "peak" ? "Peak" : "Half";
|
|
796
794
|
}
|
|
797
|
-
const COMMAND_CODE_CLI_VERSION = "1.
|
|
795
|
+
const COMMAND_CODE_CLI_VERSION = "1.39.2";
|
|
798
796
|
const DEFAULT_API_BASE = "https://api.commandcode.ai";
|
|
799
797
|
const DEFAULT_GENERATE_MAX_TOKENS = 64e3;
|
|
800
798
|
const DEFAULT_MAX_OUTPUT_TOKENS = 65536;
|
|
@@ -2752,6 +2750,185 @@ function corsOrigin(origin) {
|
|
|
2752
2750
|
return origin !== void 0 && LOGIN_ALLOWED_ORIGINS.includes(origin) ? origin : "";
|
|
2753
2751
|
}
|
|
2754
2752
|
//#endregion
|
|
2753
|
+
//#region src/web-search.ts
|
|
2754
|
+
/**
|
|
2755
|
+
* dsh-commandcode-provider — Command Code web search provider over `ctx.web`.
|
|
2756
|
+
*
|
|
2757
|
+
* The official Command Code CLI ships a built-in `web_search` tool that POSTs
|
|
2758
|
+
* `{ query, numResults, allowedDomains?, blockedDomains? }` to
|
|
2759
|
+
* `{apiBase}/alpha/web-search` and reads `{ results: [{ title, url, snippet }] }`
|
|
2760
|
+
* back. It authenticates with the SAME `Authorization: Bearer <key>` header and
|
|
2761
|
+
* `x-command-code-version` the model adapter uses, so this provider reuses the
|
|
2762
|
+
* plugin's existing credential chain (`COMMANDCODE_API_KEY` → credentials seam →
|
|
2763
|
+
* `~/.commandcode/auth.json`) — no separate DeepSeek key, no extra endpoint.
|
|
2764
|
+
*
|
|
2765
|
+
* This mirrors the host-side `@deepseek-ai/dsh-web-search-deepseek` provider in
|
|
2766
|
+
* shape: a cordis-free class registered into the web seam, resolving its key per
|
|
2767
|
+
* search, mapping each server-side result to the harness's normalized
|
|
2768
|
+
* `WebSearchSource`. The web seam owns `maxResults` truncation.
|
|
2769
|
+
*
|
|
2770
|
+
* @module dsh-commandcode-provider/web-search
|
|
2771
|
+
*/
|
|
2772
|
+
/** Stable id this provider registers under in `ctx.web`. */
|
|
2773
|
+
const COMMANDCODE_SEARCH_PROVIDER_ID = "commandcode";
|
|
2774
|
+
/**
|
|
2775
|
+
* The factory-declared search provider id dsh ships by default (from
|
|
2776
|
+
* `dsh-base`'s cordis patch `web.config.searchProvider`). A plugin that wants
|
|
2777
|
+
* its own backend to win rewrites `WebRuntime.searchProviderId` to its own id;
|
|
2778
|
+
* disabling that plugin restores this value.
|
|
2779
|
+
*/
|
|
2780
|
+
const DEFAULT_WEB_SEARCH_PROVIDER_ID = "deepseek-official";
|
|
2781
|
+
/**
|
|
2782
|
+
* Point the web seam's search selection at this plugin's provider (`commandcode`).
|
|
2783
|
+
* Sets the runtime field; the next search call honours it because `search()`
|
|
2784
|
+
* re-reads `searchProviderId` each time. Returns the prior id (or undefined).
|
|
2785
|
+
*/
|
|
2786
|
+
function selectCommandCodeSearchProvider(web, enable) {
|
|
2787
|
+
const field = web;
|
|
2788
|
+
const prior = field.searchProviderId;
|
|
2789
|
+
field.searchProviderId = enable ? COMMANDCODE_SEARCH_PROVIDER_ID : DEFAULT_WEB_SEARCH_PROVIDER_ID;
|
|
2790
|
+
return prior;
|
|
2791
|
+
}
|
|
2792
|
+
/** Command Code's lower/upper bound on `numResults` (from the CLI's `web_search` schema). */
|
|
2793
|
+
const MIN_NUM_RESULTS = 1;
|
|
2794
|
+
const MAX_NUM_RESULTS = 10;
|
|
2795
|
+
/** CLI default when the caller sets no result cap. */
|
|
2796
|
+
const DEFAULT_NUM_RESULTS = 5;
|
|
2797
|
+
/** The endpoint the search POST goes to; `{apiBase}` is prepended. */
|
|
2798
|
+
const SEARCH_ROUTE = "/alpha/web-search";
|
|
2799
|
+
/**
|
|
2800
|
+
* Clamp a DSH `maxResults` bound into Command Code's 1–10 range, applying the
|
|
2801
|
+
* CLI default of 5 when the caller supplied none.
|
|
2802
|
+
*/
|
|
2803
|
+
function clampNumResults(maxResults) {
|
|
2804
|
+
return maxResults === void 0 ? DEFAULT_NUM_RESULTS : Math.max(MIN_NUM_RESULTS, Math.min(MAX_NUM_RESULTS, Math.round(maxResults)));
|
|
2805
|
+
}
|
|
2806
|
+
/** Build a `WebSearchSource` from one raw `{ title, url, snippet }` result, omitting empty optional fields. */
|
|
2807
|
+
function toSource(result) {
|
|
2808
|
+
const url = result.url?.trim();
|
|
2809
|
+
if (url === void 0 || url.length === 0) return void 0;
|
|
2810
|
+
const title = result.title?.trim();
|
|
2811
|
+
const snippet = result.snippet?.trim();
|
|
2812
|
+
return {
|
|
2813
|
+
url,
|
|
2814
|
+
...title !== void 0 && title.length > 0 ? { title } : {},
|
|
2815
|
+
...snippet !== void 0 && snippet.length > 0 ? { snippet } : {}
|
|
2816
|
+
};
|
|
2817
|
+
}
|
|
2818
|
+
function isAbortError(error) {
|
|
2819
|
+
return error instanceof DOMException && error.name === "AbortError";
|
|
2820
|
+
}
|
|
2821
|
+
/** Build the provider's stable cancellation error while retaining the caller's reason. */
|
|
2822
|
+
function searchAborted(signal, fallback) {
|
|
2823
|
+
return new WebError("Command Code web search aborted", "WEB_ABORTED", { cause: signal?.aborted === true ? signal.reason : fallback });
|
|
2824
|
+
}
|
|
2825
|
+
function throwIfAborted(signal) {
|
|
2826
|
+
if (signal?.aborted === true) throw searchAborted(signal, void 0);
|
|
2827
|
+
}
|
|
2828
|
+
/**
|
|
2829
|
+
* A `ctx.web` search provider backed by the Command Code Provider API. Reuses
|
|
2830
|
+
* the plugin's credential chain and `apiBase`, so search "just works" with the
|
|
2831
|
+
* existing key — the model-facing `web_search` tool needs no separate
|
|
2832
|
+
* configuration. Selection between multiple search providers is the web seam's
|
|
2833
|
+
* job (pin `searchProvider: commandcode` if ambiguous).
|
|
2834
|
+
*/
|
|
2835
|
+
var CommandCodeSearchProvider = class {
|
|
2836
|
+
deps;
|
|
2837
|
+
id = COMMANDCODE_SEARCH_PROVIDER_ID;
|
|
2838
|
+
constructor(deps) {
|
|
2839
|
+
this.deps = deps;
|
|
2840
|
+
}
|
|
2841
|
+
/** Cheap local check; must not make network calls. Presence of a key path + a parseable base is enough. */
|
|
2842
|
+
available() {
|
|
2843
|
+
const base = this.deps.apiBase();
|
|
2844
|
+
return base.length > 0 && URL.canParse(base);
|
|
2845
|
+
}
|
|
2846
|
+
async search(request, signal) {
|
|
2847
|
+
throwIfAborted(signal);
|
|
2848
|
+
const apiBase = this.deps.apiBase();
|
|
2849
|
+
if (!URL.canParse(apiBase)) throw new WebError(`Command Code web search is misconfigured: apiBase ${JSON.stringify(apiBase)} is not a valid URL`, "WEB_PROVIDER_ERROR");
|
|
2850
|
+
const key = await this.resolveKey(signal);
|
|
2851
|
+
throwIfAborted(signal);
|
|
2852
|
+
const endpoint = `${apiBase.replace(/\/$/, "")}${SEARCH_ROUTE}`;
|
|
2853
|
+
const body = {
|
|
2854
|
+
query: request.query,
|
|
2855
|
+
numResults: clampNumResults(request.maxResults)
|
|
2856
|
+
};
|
|
2857
|
+
let response;
|
|
2858
|
+
try {
|
|
2859
|
+
response = await (this.deps.fetchImpl ?? fetch)(endpoint, {
|
|
2860
|
+
method: "POST",
|
|
2861
|
+
headers: {
|
|
2862
|
+
"Content-Type": "application/json",
|
|
2863
|
+
Authorization: `Bearer ${key}`,
|
|
2864
|
+
"x-command-code-version": COMMAND_CODE_CLI_VERSION,
|
|
2865
|
+
"x-cli-environment": "production",
|
|
2866
|
+
...attributionHeaders()
|
|
2867
|
+
},
|
|
2868
|
+
body: JSON.stringify(body),
|
|
2869
|
+
...signal !== void 0 ? { signal } : {}
|
|
2870
|
+
});
|
|
2871
|
+
} catch (error) {
|
|
2872
|
+
if (signal?.aborted === true || isAbortError(error)) throw searchAborted(signal, error);
|
|
2873
|
+
throw new WebError(`Command Code web search request failed: ${error instanceof Error ? error.message : String(error)}`, "WEB_PROVIDER_ERROR", { cause: error });
|
|
2874
|
+
}
|
|
2875
|
+
if (!response.ok) {
|
|
2876
|
+
let message = `Command Code web search failed (HTTP ${response.status})`;
|
|
2877
|
+
try {
|
|
2878
|
+
const parsed = await response.json();
|
|
2879
|
+
const detail = typeof parsed === "object" && parsed !== null ? parsed?.error : void 0;
|
|
2880
|
+
if (typeof detail === "string" && detail.length > 0) message += `: ${detail}`;
|
|
2881
|
+
else if (typeof detail === "object" && detail !== null) {
|
|
2882
|
+
const code = detail?.code;
|
|
2883
|
+
const inner = detail?.message;
|
|
2884
|
+
if (typeof code === "string" || typeof inner === "string") message += `: ${typeof code === "string" ? code : ""}${typeof code === "string" && typeof inner === "string" ? " — " : ""}${typeof inner === "string" ? inner : ""}`;
|
|
2885
|
+
}
|
|
2886
|
+
} catch (error) {
|
|
2887
|
+
if (signal?.aborted === true || isAbortError(error)) throw searchAborted(signal, error);
|
|
2888
|
+
}
|
|
2889
|
+
throw new WebError(message, "WEB_PROVIDER_ERROR");
|
|
2890
|
+
}
|
|
2891
|
+
let payload;
|
|
2892
|
+
try {
|
|
2893
|
+
payload = await response.json();
|
|
2894
|
+
} catch (error) {
|
|
2895
|
+
if (signal?.aborted === true || isAbortError(error)) throw searchAborted(signal, error);
|
|
2896
|
+
throw new WebError("Command Code web search returned an unparseable response body", "WEB_PROVIDER_ERROR");
|
|
2897
|
+
}
|
|
2898
|
+
const results = payload?.results;
|
|
2899
|
+
if (!Array.isArray(results)) throw new WebError("Command Code web search returned no results array (the server may have rejected the query)", "WEB_PROVIDER_ERROR");
|
|
2900
|
+
const sources = [];
|
|
2901
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2902
|
+
for (const item of results) {
|
|
2903
|
+
if (typeof item !== "object" || item === null) continue;
|
|
2904
|
+
const source = toSource(item);
|
|
2905
|
+
if (source === void 0 || seen.has(source.url)) continue;
|
|
2906
|
+
seen.add(source.url);
|
|
2907
|
+
sources.push(source);
|
|
2908
|
+
}
|
|
2909
|
+
return {
|
|
2910
|
+
sources,
|
|
2911
|
+
truncated: false
|
|
2912
|
+
};
|
|
2913
|
+
}
|
|
2914
|
+
async resolveKey(signal) {
|
|
2915
|
+
let key;
|
|
2916
|
+
try {
|
|
2917
|
+
key = await this.deps.resolveKey();
|
|
2918
|
+
} catch (error) {
|
|
2919
|
+
if (signal?.aborted === true || isAbortError(error)) throw searchAborted(signal, error);
|
|
2920
|
+
if (error instanceof Error && typeof error.code === "string") {
|
|
2921
|
+
const code = error.code;
|
|
2922
|
+
if (code === "MISSING_CREDENTIAL") throw new WebError(error.message, "WEB_PROVIDER_CREDENTIAL_MISSING", { cause: error });
|
|
2923
|
+
if (code === "INVALID_CREDENTIAL" || code === "RATE_LIMIT") throw new WebError(error.message, "WEB_PROVIDER_ERROR", { cause: error });
|
|
2924
|
+
}
|
|
2925
|
+
throw new WebError(`Command Code web search credential resolution failed: ${error instanceof Error ? error.message : String(error)}`, "WEB_PROVIDER_ERROR", { cause: error });
|
|
2926
|
+
}
|
|
2927
|
+
if (key === void 0 || key.length === 0) throw new WebError("Command Code web search has no API key; store COMMANDCODE_API_KEY through the credentials service (the web Models page writes it), export it in the launching environment, set config.apiKey, or run `command-code login` to write ~/.commandcode/auth.json", "WEB_PROVIDER_CREDENTIAL_MISSING");
|
|
2928
|
+
return key;
|
|
2929
|
+
}
|
|
2930
|
+
};
|
|
2931
|
+
//#endregion
|
|
2755
2932
|
//#region src/index.ts
|
|
2756
2933
|
/**
|
|
2757
2934
|
* dsh-commandcode-provider — DeepSeek Harness LLM provider plugin for Command
|
|
@@ -2797,6 +2974,7 @@ const Config = z.object({
|
|
|
2797
2974
|
requestTimeoutMs: z.number().min(1).max(MAX_TIMER_DELAY_MS),
|
|
2798
2975
|
streamIdleTimeoutMs: z.number().min(1).max(MAX_TIMER_DELAY_MS),
|
|
2799
2976
|
filterModelsByPlan: z.boolean(),
|
|
2977
|
+
webSearch: z.boolean().default(true),
|
|
2800
2978
|
accounts: z.array(z.object({
|
|
2801
2979
|
label: z.string(),
|
|
2802
2980
|
apiKeyEnv: z.string().role("credential-ref"),
|
|
@@ -2965,16 +3143,30 @@ function apply(ctx, config) {
|
|
|
2965
3143
|
login: loginFlow,
|
|
2966
3144
|
listModels: catalogForRules
|
|
2967
3145
|
});
|
|
3146
|
+
let webRuntime;
|
|
3147
|
+
ctx.inject(["web"], (webCtx) => {
|
|
3148
|
+
webRuntime = webCtx.web;
|
|
3149
|
+
webCtx.web.registerSearchProvider(new CommandCodeSearchProvider({
|
|
3150
|
+
resolveKey: async () => {
|
|
3151
|
+
const resolved = await pool.resolveKey();
|
|
3152
|
+
return resolved === void 0 ? void 0 : resolved.key;
|
|
3153
|
+
},
|
|
3154
|
+
apiBase: () => options().apiBase
|
|
3155
|
+
}));
|
|
3156
|
+
selectCommandCodeSearchProvider(webCtx.web, current().webSearch ?? true);
|
|
3157
|
+
});
|
|
2968
3158
|
ctx.inject(["settings"], (settingsCtx) => {
|
|
2969
3159
|
settingsCtx.settings.installSection(ctx, NS, Config, config, {
|
|
2970
3160
|
setSource: (source) => {
|
|
2971
3161
|
current = source;
|
|
2972
3162
|
},
|
|
2973
|
-
onChange: () => {
|
|
3163
|
+
onChange: () => {
|
|
3164
|
+
if (webRuntime !== void 0) selectCommandCodeSearchProvider(webRuntime, current().webSearch ?? true);
|
|
3165
|
+
}
|
|
2974
3166
|
});
|
|
2975
3167
|
});
|
|
2976
3168
|
}
|
|
2977
3169
|
//#endregion
|
|
2978
|
-
export { BILLING_ACCESS_TTL_MS, COMMAND_CODE_CLI_VERSION, CommandCodeAccountPool, CommandCodeAdapter, CommandCodeLoginFlow, CommandCodeUsageService, Config, DEFAULT_API_BASE, DEFAULT_GENERATE_MAX_TOKENS, DEFAULT_MAX_OUTPUT_TOKENS, DEFAULT_MODELS_CACHE_PATH, DEFAULT_REQUEST_TIMEOUT_MS, DEFAULT_STREAM_IDLE_TIMEOUT_MS, KNOWN_DEALS, KNOWN_EFFORTS, KNOWN_IMAGE_MODELS, KNOWN_PEAK_PRICING, KNOWN_PLANS, KNOWN_SUBSCRIPTION_PLANS, KNOWN_THINKING_MODELS, LOGIN_ALLOWED_ORIGINS, LOGIN_BEGIN_ENDPOINT, LOGIN_BODY_LIMIT_BYTES, LOGIN_CANCEL_ENDPOINT, LOGIN_MAX_PORT_ATTEMPTS, LOGIN_START_PORT, LOGIN_STATUS_ENDPOINT, LOGIN_TIMEOUT_MS, PLAN_LABELS, PLAN_ORDER, PROVIDER, USAGE_REPORT_ENDPOINT, accountUsable, apply, applyCommands, applyUsageRemote, buildCommandAuthUrl, capabilityDescription, commandDefinition, compareByPlan, dealLabel, formatContext, inject, loginStatusSchema, matchModelRule, modelVisibleInPlan, name, parseLoginStatus, peakPricingLabel, peakPricingState, planLabel, projectSlugFromPath, resolveAdapterOptions, resolveAuthFileApiKey, selectAccountForModel, selectActiveAccount, studioBaseForApiBase, subscriptionPlanInfo, usageReportSchema, validateCommandApiKey };
|
|
3170
|
+
export { BILLING_ACCESS_TTL_MS, COMMANDCODE_SEARCH_PROVIDER_ID, COMMAND_CODE_CLI_VERSION, CommandCodeAccountPool, CommandCodeAdapter, CommandCodeLoginFlow, CommandCodeSearchProvider, CommandCodeUsageService, Config, DEFAULT_API_BASE, DEFAULT_GENERATE_MAX_TOKENS, DEFAULT_MAX_OUTPUT_TOKENS, DEFAULT_MODELS_CACHE_PATH, DEFAULT_REQUEST_TIMEOUT_MS, DEFAULT_STREAM_IDLE_TIMEOUT_MS, DEFAULT_WEB_SEARCH_PROVIDER_ID, KNOWN_DEALS, KNOWN_EFFORTS, KNOWN_IMAGE_MODELS, KNOWN_PEAK_PRICING, KNOWN_PLANS, KNOWN_SUBSCRIPTION_PLANS, KNOWN_THINKING_MODELS, LOGIN_ALLOWED_ORIGINS, LOGIN_BEGIN_ENDPOINT, LOGIN_BODY_LIMIT_BYTES, LOGIN_CANCEL_ENDPOINT, LOGIN_MAX_PORT_ATTEMPTS, LOGIN_START_PORT, LOGIN_STATUS_ENDPOINT, LOGIN_TIMEOUT_MS, PLAN_LABELS, PLAN_ORDER, PROVIDER, USAGE_REPORT_ENDPOINT, accountUsable, apply, applyCommands, applyUsageRemote, buildCommandAuthUrl, capabilityDescription, commandDefinition, compareByPlan, dealLabel, formatContext, inject, loginStatusSchema, matchModelRule, modelVisibleInPlan, name, parseLoginStatus, peakPricingLabel, peakPricingState, planLabel, projectSlugFromPath, resolveAdapterOptions, resolveAuthFileApiKey, selectAccountForModel, selectActiveAccount, selectCommandCodeSearchProvider, studioBaseForApiBase, subscriptionPlanInfo, usageReportSchema, validateCommandApiKey };
|
|
2979
3171
|
|
|
2980
3172
|
//# sourceMappingURL=index.js.map
|