@mars-sea/dsh-commandcode-provider 0.10.0-alpha.3 → 0.10.0-alpha.5
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 +18 -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 +61 -5
- package/lib/index.js +209 -8
- 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.40.1) 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.40.1 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
|
|
@@ -40,7 +41,9 @@ declare const KNOWN_IMAGE_MODELS: ReadonlySet<string>;
|
|
|
40
41
|
* joined this set in command-code@1.37.0 — reasoning:!0, no efforts, 1M
|
|
41
42
|
* context, routed through OpenRouter — then gained selectable
|
|
42
43
|
* `['low', 'medium', 'high']` efforts in command-code@1.38.0 and moved to
|
|
43
|
-
* `KNOWN_EFFORTS`.
|
|
44
|
+
* `KNOWN_EFFORTS`. `moonshotai/Kimi-K3` followed the same path in
|
|
45
|
+
* command-code@1.39.3 — it gained `['low', 'high', 'max']` efforts and moved
|
|
46
|
+
* to `KNOWN_EFFORTS`.)
|
|
44
47
|
* Keep in sync via the dsh-commandcode-upstream skill.
|
|
45
48
|
*/
|
|
46
49
|
declare const KNOWN_THINKING_MODELS: ReadonlySet<string>;
|
|
@@ -191,7 +194,7 @@ declare function peakPricingState(modelId: string, now?: number): 'peak' | 'off-
|
|
|
191
194
|
* for models without time-of-day pricing.
|
|
192
195
|
*/
|
|
193
196
|
declare function peakPricingLabel(modelId: string, now?: number): string | undefined;
|
|
194
|
-
declare const COMMAND_CODE_CLI_VERSION = "1.
|
|
197
|
+
declare const COMMAND_CODE_CLI_VERSION = "1.40.1";
|
|
195
198
|
declare const DEFAULT_API_BASE = "https://api.commandcode.ai";
|
|
196
199
|
declare const DEFAULT_GENERATE_MAX_TOKENS = 64000;
|
|
197
200
|
declare const DEFAULT_MAX_OUTPUT_TOKENS = 65536;
|
|
@@ -948,6 +951,48 @@ declare class CommandCodeLoginFlow {
|
|
|
948
951
|
private teardown;
|
|
949
952
|
}
|
|
950
953
|
//#endregion
|
|
954
|
+
//#region src/web-search.d.ts
|
|
955
|
+
/** Stable id this provider registers under in `ctx.web`. */
|
|
956
|
+
declare const COMMANDCODE_SEARCH_PROVIDER_ID = "commandcode";
|
|
957
|
+
/**
|
|
958
|
+
* The factory-declared search provider id dsh ships by default (from
|
|
959
|
+
* `dsh-base`'s cordis patch `web.config.searchProvider`). A plugin that wants
|
|
960
|
+
* its own backend to win rewrites `WebRuntime.searchProviderId` to its own id;
|
|
961
|
+
* disabling that plugin restores this value.
|
|
962
|
+
*/
|
|
963
|
+
declare const DEFAULT_WEB_SEARCH_PROVIDER_ID = "deepseek-official";
|
|
964
|
+
/**
|
|
965
|
+
* Point the web seam's search selection at this plugin's provider (`commandcode`).
|
|
966
|
+
* Sets the runtime field; the next search call honours it because `search()`
|
|
967
|
+
* re-reads `searchProviderId` each time. Returns the prior id (or undefined).
|
|
968
|
+
*/
|
|
969
|
+
declare function selectCommandCodeSearchProvider(web: WebRuntime, enable: boolean): string | undefined;
|
|
970
|
+
/** Per-request facts the provider needs, all injected so the class stays cordis-free and testable. */
|
|
971
|
+
interface CommandCodeSearchProviderDeps {
|
|
972
|
+
/** Resolve one usable Command Code key (credential seam → env → auth file), or undefined when none. */
|
|
973
|
+
resolveKey(): Promise<string | undefined>;
|
|
974
|
+
/** The API base host (defaults to `https://api.commandcode.ai`). */
|
|
975
|
+
apiBase(): string;
|
|
976
|
+
/** Injectable fetch for tests; defaults to the global fetch. */
|
|
977
|
+
fetchImpl?: typeof fetch;
|
|
978
|
+
}
|
|
979
|
+
/**
|
|
980
|
+
* A `ctx.web` search provider backed by the Command Code Provider API. Reuses
|
|
981
|
+
* the plugin's credential chain and `apiBase`, so search "just works" with the
|
|
982
|
+
* existing key — the model-facing `web_search` tool needs no separate
|
|
983
|
+
* configuration. Selection between multiple search providers is the web seam's
|
|
984
|
+
* job (pin `searchProvider: commandcode` if ambiguous).
|
|
985
|
+
*/
|
|
986
|
+
declare class CommandCodeSearchProvider implements WebSearchProvider {
|
|
987
|
+
private readonly deps;
|
|
988
|
+
readonly id = "commandcode";
|
|
989
|
+
constructor(deps: CommandCodeSearchProviderDeps);
|
|
990
|
+
/** Cheap local check; must not make network calls. Presence of a key path + a parseable base is enough. */
|
|
991
|
+
available(): boolean;
|
|
992
|
+
search(request: WebSearchRequest, signal?: AbortSignal): Promise<WebSearchResult>;
|
|
993
|
+
private resolveKey;
|
|
994
|
+
}
|
|
995
|
+
//#endregion
|
|
951
996
|
//#region src/index.d.ts
|
|
952
997
|
declare const name = "llm-commandcode";
|
|
953
998
|
declare const inject: string[];
|
|
@@ -1012,6 +1057,17 @@ interface Config {
|
|
|
1012
1057
|
* gate. The first matching rule wins.
|
|
1013
1058
|
*/
|
|
1014
1059
|
modelAccountRules?: CommandCodeModelAccountRule[];
|
|
1060
|
+
/**
|
|
1061
|
+
* Whether to use Command Code as the backend for dsh's model-facing
|
|
1062
|
+
* `web_search` tool. When enabled, the plugin registers a `commandcode`
|
|
1063
|
+
* search provider on `ctx.web` AND rewrites the web seam's selected
|
|
1064
|
+
* `searchProviderId` to `commandcode` (so it wins over the shipped
|
|
1065
|
+
* `deepseek-official`), using the SAME Command Code API key/base as chat.
|
|
1066
|
+
* The rewrite rides dsh's internal `searchProviderId`, which is read per
|
|
1067
|
+
* search call, so a setting change lands on the next search without a
|
|
1068
|
+
* restart. Defaults to true.
|
|
1069
|
+
*/
|
|
1070
|
+
webSearch?: boolean;
|
|
1015
1071
|
/**
|
|
1016
1072
|
* Language override for the `/commandcode` Host-side command's user-facing
|
|
1017
1073
|
* copy. Host commands cannot read the client's `ctx.locale`, so this is
|
|
@@ -1039,5 +1095,5 @@ interface ResolvedCommandCodeOptions extends CommandCodeConnectionOptions {
|
|
|
1039
1095
|
declare function resolveAdapterOptions(config: Config): ResolvedCommandCodeOptions;
|
|
1040
1096
|
declare function apply(ctx: Context, config: Config): void;
|
|
1041
1097
|
//#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 };
|
|
1098
|
+
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
1099
|
//# 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.40.1 — 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,
|
|
@@ -391,6 +392,11 @@ const KNOWN_EFFORTS = {
|
|
|
391
392
|
"xhigh",
|
|
392
393
|
"max"
|
|
393
394
|
],
|
|
395
|
+
"moonshotai/Kimi-K3": [
|
|
396
|
+
"low",
|
|
397
|
+
"high",
|
|
398
|
+
"max"
|
|
399
|
+
],
|
|
394
400
|
"sakana/fugu-ultra": ["high", "xhigh"],
|
|
395
401
|
"tencent/hy4-preview": [
|
|
396
402
|
"low",
|
|
@@ -481,7 +487,7 @@ const KNOWN_IMAGE_MODELS = /* @__PURE__ */ new Set([
|
|
|
481
487
|
"z-ai/glm-5.3-flash"
|
|
482
488
|
]);
|
|
483
489
|
/**
|
|
484
|
-
* Models the official CLI's model table (command-code@1.
|
|
490
|
+
* Models the official CLI's model table (command-code@1.40.1) marks
|
|
485
491
|
* `reasoning:!0` but defines no selectable `reasoning_effort` levels — they
|
|
486
492
|
* think automatically, with Command Code driving the depth. This is the
|
|
487
493
|
* authoritative "thinks, effort not adjustable" set: `KNOWN_EFFORTS` (which
|
|
@@ -489,7 +495,7 @@ const KNOWN_IMAGE_MODELS = /* @__PURE__ */ new Set([
|
|
|
489
495
|
* effort levels, and this snapshot is not surfaced in the picker's compact
|
|
490
496
|
* description — it exists for programmatic consumers.
|
|
491
497
|
*
|
|
492
|
-
* Source: the command-code@1.
|
|
498
|
+
* Source: the command-code@1.40.1 bundled model table (dist/cli.mjs),
|
|
493
499
|
* cross-checked with https://commandcode.ai/docs/reference/cli/models.
|
|
494
500
|
* (`stealth/ox-alpha` left this set in command-code@1.32.1, which gave it
|
|
495
501
|
* selectable `['low', 'high', 'max']` efforts; the preview then ended in
|
|
@@ -497,7 +503,9 @@ const KNOWN_IMAGE_MODELS = /* @__PURE__ */ new Set([
|
|
|
497
503
|
* joined this set in command-code@1.37.0 — reasoning:!0, no efforts, 1M
|
|
498
504
|
* context, routed through OpenRouter — then gained selectable
|
|
499
505
|
* `['low', 'medium', 'high']` efforts in command-code@1.38.0 and moved to
|
|
500
|
-
* `KNOWN_EFFORTS`.
|
|
506
|
+
* `KNOWN_EFFORTS`. `moonshotai/Kimi-K3` followed the same path in
|
|
507
|
+
* command-code@1.39.3 — it gained `['low', 'high', 'max']` efforts and moved
|
|
508
|
+
* to `KNOWN_EFFORTS`.)
|
|
501
509
|
* Keep in sync via the dsh-commandcode-upstream skill.
|
|
502
510
|
*/
|
|
503
511
|
const KNOWN_THINKING_MODELS = /* @__PURE__ */ new Set([
|
|
@@ -508,7 +516,6 @@ const KNOWN_THINKING_MODELS = /* @__PURE__ */ new Set([
|
|
|
508
516
|
"Qwen/Qwen3.7-Max",
|
|
509
517
|
"Qwen/Qwen3.7-Plus",
|
|
510
518
|
"minimax/minimax-m3-free",
|
|
511
|
-
"moonshotai/Kimi-K3",
|
|
512
519
|
"moonshotai/Kimi-K2.7-Code",
|
|
513
520
|
"moonshotai/Kimi-K2.7-Code-Highspeed",
|
|
514
521
|
"stepfun/Step-3.5-Flash",
|
|
@@ -791,7 +798,7 @@ function peakPricingLabel(modelId, now = Date.now()) {
|
|
|
791
798
|
if (state === void 0) return void 0;
|
|
792
799
|
return state === "peak" ? "Peak" : "Half";
|
|
793
800
|
}
|
|
794
|
-
const COMMAND_CODE_CLI_VERSION = "1.
|
|
801
|
+
const COMMAND_CODE_CLI_VERSION = "1.40.1";
|
|
795
802
|
const DEFAULT_API_BASE = "https://api.commandcode.ai";
|
|
796
803
|
const DEFAULT_GENERATE_MAX_TOKENS = 64e3;
|
|
797
804
|
const DEFAULT_MAX_OUTPUT_TOKENS = 65536;
|
|
@@ -2749,6 +2756,185 @@ function corsOrigin(origin) {
|
|
|
2749
2756
|
return origin !== void 0 && LOGIN_ALLOWED_ORIGINS.includes(origin) ? origin : "";
|
|
2750
2757
|
}
|
|
2751
2758
|
//#endregion
|
|
2759
|
+
//#region src/web-search.ts
|
|
2760
|
+
/**
|
|
2761
|
+
* dsh-commandcode-provider — Command Code web search provider over `ctx.web`.
|
|
2762
|
+
*
|
|
2763
|
+
* The official Command Code CLI ships a built-in `web_search` tool that POSTs
|
|
2764
|
+
* `{ query, numResults, allowedDomains?, blockedDomains? }` to
|
|
2765
|
+
* `{apiBase}/alpha/web-search` and reads `{ results: [{ title, url, snippet }] }`
|
|
2766
|
+
* back. It authenticates with the SAME `Authorization: Bearer <key>` header and
|
|
2767
|
+
* `x-command-code-version` the model adapter uses, so this provider reuses the
|
|
2768
|
+
* plugin's existing credential chain (`COMMANDCODE_API_KEY` → credentials seam →
|
|
2769
|
+
* `~/.commandcode/auth.json`) — no separate DeepSeek key, no extra endpoint.
|
|
2770
|
+
*
|
|
2771
|
+
* This mirrors the host-side `@deepseek-ai/dsh-web-search-deepseek` provider in
|
|
2772
|
+
* shape: a cordis-free class registered into the web seam, resolving its key per
|
|
2773
|
+
* search, mapping each server-side result to the harness's normalized
|
|
2774
|
+
* `WebSearchSource`. The web seam owns `maxResults` truncation.
|
|
2775
|
+
*
|
|
2776
|
+
* @module dsh-commandcode-provider/web-search
|
|
2777
|
+
*/
|
|
2778
|
+
/** Stable id this provider registers under in `ctx.web`. */
|
|
2779
|
+
const COMMANDCODE_SEARCH_PROVIDER_ID = "commandcode";
|
|
2780
|
+
/**
|
|
2781
|
+
* The factory-declared search provider id dsh ships by default (from
|
|
2782
|
+
* `dsh-base`'s cordis patch `web.config.searchProvider`). A plugin that wants
|
|
2783
|
+
* its own backend to win rewrites `WebRuntime.searchProviderId` to its own id;
|
|
2784
|
+
* disabling that plugin restores this value.
|
|
2785
|
+
*/
|
|
2786
|
+
const DEFAULT_WEB_SEARCH_PROVIDER_ID = "deepseek-official";
|
|
2787
|
+
/**
|
|
2788
|
+
* Point the web seam's search selection at this plugin's provider (`commandcode`).
|
|
2789
|
+
* Sets the runtime field; the next search call honours it because `search()`
|
|
2790
|
+
* re-reads `searchProviderId` each time. Returns the prior id (or undefined).
|
|
2791
|
+
*/
|
|
2792
|
+
function selectCommandCodeSearchProvider(web, enable) {
|
|
2793
|
+
const field = web;
|
|
2794
|
+
const prior = field.searchProviderId;
|
|
2795
|
+
field.searchProviderId = enable ? COMMANDCODE_SEARCH_PROVIDER_ID : DEFAULT_WEB_SEARCH_PROVIDER_ID;
|
|
2796
|
+
return prior;
|
|
2797
|
+
}
|
|
2798
|
+
/** Command Code's lower/upper bound on `numResults` (from the CLI's `web_search` schema). */
|
|
2799
|
+
const MIN_NUM_RESULTS = 1;
|
|
2800
|
+
const MAX_NUM_RESULTS = 10;
|
|
2801
|
+
/** CLI default when the caller sets no result cap. */
|
|
2802
|
+
const DEFAULT_NUM_RESULTS = 5;
|
|
2803
|
+
/** The endpoint the search POST goes to; `{apiBase}` is prepended. */
|
|
2804
|
+
const SEARCH_ROUTE = "/alpha/web-search";
|
|
2805
|
+
/**
|
|
2806
|
+
* Clamp a DSH `maxResults` bound into Command Code's 1–10 range, applying the
|
|
2807
|
+
* CLI default of 5 when the caller supplied none.
|
|
2808
|
+
*/
|
|
2809
|
+
function clampNumResults(maxResults) {
|
|
2810
|
+
return maxResults === void 0 ? DEFAULT_NUM_RESULTS : Math.max(MIN_NUM_RESULTS, Math.min(MAX_NUM_RESULTS, Math.round(maxResults)));
|
|
2811
|
+
}
|
|
2812
|
+
/** Build a `WebSearchSource` from one raw `{ title, url, snippet }` result, omitting empty optional fields. */
|
|
2813
|
+
function toSource(result) {
|
|
2814
|
+
const url = result.url?.trim();
|
|
2815
|
+
if (url === void 0 || url.length === 0) return void 0;
|
|
2816
|
+
const title = result.title?.trim();
|
|
2817
|
+
const snippet = result.snippet?.trim();
|
|
2818
|
+
return {
|
|
2819
|
+
url,
|
|
2820
|
+
...title !== void 0 && title.length > 0 ? { title } : {},
|
|
2821
|
+
...snippet !== void 0 && snippet.length > 0 ? { snippet } : {}
|
|
2822
|
+
};
|
|
2823
|
+
}
|
|
2824
|
+
function isAbortError(error) {
|
|
2825
|
+
return error instanceof DOMException && error.name === "AbortError";
|
|
2826
|
+
}
|
|
2827
|
+
/** Build the provider's stable cancellation error while retaining the caller's reason. */
|
|
2828
|
+
function searchAborted(signal, fallback) {
|
|
2829
|
+
return new WebError("Command Code web search aborted", "WEB_ABORTED", { cause: signal?.aborted === true ? signal.reason : fallback });
|
|
2830
|
+
}
|
|
2831
|
+
function throwIfAborted(signal) {
|
|
2832
|
+
if (signal?.aborted === true) throw searchAborted(signal, void 0);
|
|
2833
|
+
}
|
|
2834
|
+
/**
|
|
2835
|
+
* A `ctx.web` search provider backed by the Command Code Provider API. Reuses
|
|
2836
|
+
* the plugin's credential chain and `apiBase`, so search "just works" with the
|
|
2837
|
+
* existing key — the model-facing `web_search` tool needs no separate
|
|
2838
|
+
* configuration. Selection between multiple search providers is the web seam's
|
|
2839
|
+
* job (pin `searchProvider: commandcode` if ambiguous).
|
|
2840
|
+
*/
|
|
2841
|
+
var CommandCodeSearchProvider = class {
|
|
2842
|
+
deps;
|
|
2843
|
+
id = COMMANDCODE_SEARCH_PROVIDER_ID;
|
|
2844
|
+
constructor(deps) {
|
|
2845
|
+
this.deps = deps;
|
|
2846
|
+
}
|
|
2847
|
+
/** Cheap local check; must not make network calls. Presence of a key path + a parseable base is enough. */
|
|
2848
|
+
available() {
|
|
2849
|
+
const base = this.deps.apiBase();
|
|
2850
|
+
return base.length > 0 && URL.canParse(base);
|
|
2851
|
+
}
|
|
2852
|
+
async search(request, signal) {
|
|
2853
|
+
throwIfAborted(signal);
|
|
2854
|
+
const apiBase = this.deps.apiBase();
|
|
2855
|
+
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");
|
|
2856
|
+
const key = await this.resolveKey(signal);
|
|
2857
|
+
throwIfAborted(signal);
|
|
2858
|
+
const endpoint = `${apiBase.replace(/\/$/, "")}${SEARCH_ROUTE}`;
|
|
2859
|
+
const body = {
|
|
2860
|
+
query: request.query,
|
|
2861
|
+
numResults: clampNumResults(request.maxResults)
|
|
2862
|
+
};
|
|
2863
|
+
let response;
|
|
2864
|
+
try {
|
|
2865
|
+
response = await (this.deps.fetchImpl ?? fetch)(endpoint, {
|
|
2866
|
+
method: "POST",
|
|
2867
|
+
headers: {
|
|
2868
|
+
"Content-Type": "application/json",
|
|
2869
|
+
Authorization: `Bearer ${key}`,
|
|
2870
|
+
"x-command-code-version": COMMAND_CODE_CLI_VERSION,
|
|
2871
|
+
"x-cli-environment": "production",
|
|
2872
|
+
...attributionHeaders()
|
|
2873
|
+
},
|
|
2874
|
+
body: JSON.stringify(body),
|
|
2875
|
+
...signal !== void 0 ? { signal } : {}
|
|
2876
|
+
});
|
|
2877
|
+
} catch (error) {
|
|
2878
|
+
if (signal?.aborted === true || isAbortError(error)) throw searchAborted(signal, error);
|
|
2879
|
+
throw new WebError(`Command Code web search request failed: ${error instanceof Error ? error.message : String(error)}`, "WEB_PROVIDER_ERROR", { cause: error });
|
|
2880
|
+
}
|
|
2881
|
+
if (!response.ok) {
|
|
2882
|
+
let message = `Command Code web search failed (HTTP ${response.status})`;
|
|
2883
|
+
try {
|
|
2884
|
+
const parsed = await response.json();
|
|
2885
|
+
const detail = typeof parsed === "object" && parsed !== null ? parsed?.error : void 0;
|
|
2886
|
+
if (typeof detail === "string" && detail.length > 0) message += `: ${detail}`;
|
|
2887
|
+
else if (typeof detail === "object" && detail !== null) {
|
|
2888
|
+
const code = detail?.code;
|
|
2889
|
+
const inner = detail?.message;
|
|
2890
|
+
if (typeof code === "string" || typeof inner === "string") message += `: ${typeof code === "string" ? code : ""}${typeof code === "string" && typeof inner === "string" ? " — " : ""}${typeof inner === "string" ? inner : ""}`;
|
|
2891
|
+
}
|
|
2892
|
+
} catch (error) {
|
|
2893
|
+
if (signal?.aborted === true || isAbortError(error)) throw searchAborted(signal, error);
|
|
2894
|
+
}
|
|
2895
|
+
throw new WebError(message, "WEB_PROVIDER_ERROR");
|
|
2896
|
+
}
|
|
2897
|
+
let payload;
|
|
2898
|
+
try {
|
|
2899
|
+
payload = await response.json();
|
|
2900
|
+
} catch (error) {
|
|
2901
|
+
if (signal?.aborted === true || isAbortError(error)) throw searchAborted(signal, error);
|
|
2902
|
+
throw new WebError("Command Code web search returned an unparseable response body", "WEB_PROVIDER_ERROR");
|
|
2903
|
+
}
|
|
2904
|
+
const results = payload?.results;
|
|
2905
|
+
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");
|
|
2906
|
+
const sources = [];
|
|
2907
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2908
|
+
for (const item of results) {
|
|
2909
|
+
if (typeof item !== "object" || item === null) continue;
|
|
2910
|
+
const source = toSource(item);
|
|
2911
|
+
if (source === void 0 || seen.has(source.url)) continue;
|
|
2912
|
+
seen.add(source.url);
|
|
2913
|
+
sources.push(source);
|
|
2914
|
+
}
|
|
2915
|
+
return {
|
|
2916
|
+
sources,
|
|
2917
|
+
truncated: false
|
|
2918
|
+
};
|
|
2919
|
+
}
|
|
2920
|
+
async resolveKey(signal) {
|
|
2921
|
+
let key;
|
|
2922
|
+
try {
|
|
2923
|
+
key = await this.deps.resolveKey();
|
|
2924
|
+
} catch (error) {
|
|
2925
|
+
if (signal?.aborted === true || isAbortError(error)) throw searchAborted(signal, error);
|
|
2926
|
+
if (error instanceof Error && typeof error.code === "string") {
|
|
2927
|
+
const code = error.code;
|
|
2928
|
+
if (code === "MISSING_CREDENTIAL") throw new WebError(error.message, "WEB_PROVIDER_CREDENTIAL_MISSING", { cause: error });
|
|
2929
|
+
if (code === "INVALID_CREDENTIAL" || code === "RATE_LIMIT") throw new WebError(error.message, "WEB_PROVIDER_ERROR", { cause: error });
|
|
2930
|
+
}
|
|
2931
|
+
throw new WebError(`Command Code web search credential resolution failed: ${error instanceof Error ? error.message : String(error)}`, "WEB_PROVIDER_ERROR", { cause: error });
|
|
2932
|
+
}
|
|
2933
|
+
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");
|
|
2934
|
+
return key;
|
|
2935
|
+
}
|
|
2936
|
+
};
|
|
2937
|
+
//#endregion
|
|
2752
2938
|
//#region src/index.ts
|
|
2753
2939
|
/**
|
|
2754
2940
|
* dsh-commandcode-provider — DeepSeek Harness LLM provider plugin for Command
|
|
@@ -2794,6 +2980,7 @@ const Config = z.object({
|
|
|
2794
2980
|
requestTimeoutMs: z.number().min(1).max(MAX_TIMER_DELAY_MS),
|
|
2795
2981
|
streamIdleTimeoutMs: z.number().min(1).max(MAX_TIMER_DELAY_MS),
|
|
2796
2982
|
filterModelsByPlan: z.boolean(),
|
|
2983
|
+
webSearch: z.boolean().default(true),
|
|
2797
2984
|
accounts: z.array(z.object({
|
|
2798
2985
|
label: z.string(),
|
|
2799
2986
|
apiKeyEnv: z.string().role("credential-ref"),
|
|
@@ -2962,16 +3149,30 @@ function apply(ctx, config) {
|
|
|
2962
3149
|
login: loginFlow,
|
|
2963
3150
|
listModels: catalogForRules
|
|
2964
3151
|
});
|
|
3152
|
+
let webRuntime;
|
|
3153
|
+
ctx.inject(["web"], (webCtx) => {
|
|
3154
|
+
webRuntime = webCtx.web;
|
|
3155
|
+
webCtx.web.registerSearchProvider(new CommandCodeSearchProvider({
|
|
3156
|
+
resolveKey: async () => {
|
|
3157
|
+
const resolved = await pool.resolveKey();
|
|
3158
|
+
return resolved === void 0 ? void 0 : resolved.key;
|
|
3159
|
+
},
|
|
3160
|
+
apiBase: () => options().apiBase
|
|
3161
|
+
}));
|
|
3162
|
+
selectCommandCodeSearchProvider(webCtx.web, current().webSearch ?? true);
|
|
3163
|
+
});
|
|
2965
3164
|
ctx.inject(["settings"], (settingsCtx) => {
|
|
2966
3165
|
settingsCtx.settings.installSection(ctx, NS, Config, config, {
|
|
2967
3166
|
setSource: (source) => {
|
|
2968
3167
|
current = source;
|
|
2969
3168
|
},
|
|
2970
|
-
onChange: () => {
|
|
3169
|
+
onChange: () => {
|
|
3170
|
+
if (webRuntime !== void 0) selectCommandCodeSearchProvider(webRuntime, current().webSearch ?? true);
|
|
3171
|
+
}
|
|
2971
3172
|
});
|
|
2972
3173
|
});
|
|
2973
3174
|
}
|
|
2974
3175
|
//#endregion
|
|
2975
|
-
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 };
|
|
3176
|
+
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 };
|
|
2976
3177
|
|
|
2977
3178
|
//# sourceMappingURL=index.js.map
|