@wxip/dsh-sub2api 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +158 -0
- package/README.zh.md +160 -0
- package/assets/icons/claude.svg +1 -0
- package/assets/icons/grok.svg +1 -0
- package/assets/icons/openai.svg +1 -0
- package/cordis.patch.yml +11 -0
- package/lib/client.cjs +1098 -0
- package/lib/client.js +1107 -0
- package/lib/image-tools.d.ts +18 -0
- package/lib/index.d.ts +148 -0
- package/lib/index.js +1220 -0
- package/lib/invariant.d.ts +13 -0
- package/lib/invariant.js +9 -0
- package/lib/pi-ai-patch.d.ts +45 -0
- package/lib/pi-ai.d.ts +50 -0
- package/lib/routes.d.ts +43 -0
- package/package.json +160 -0
- package/src/client/icons.tsx +38 -0
- package/src/client/index.tsx +31 -0
- package/src/client/settings.tsx +847 -0
- package/src/client/toolview.tsx +76 -0
- package/src/image-tools.ts +590 -0
- package/src/index.ts +339 -0
- package/src/invariant.ts +17 -0
- package/src/pi-ai-patch.ts +94 -0
- package/src/pi-ai.ts +185 -0
- package/src/routes.ts +442 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global image-generation tool.
|
|
3
|
+
*
|
|
4
|
+
* These call a configured Sub2API model independently of the current chat
|
|
5
|
+
* route, so a text-only session can still create images. Results include a workspace path and an image attachment.
|
|
6
|
+
*
|
|
7
|
+
* @module dsh-sub2api/image-tools
|
|
8
|
+
*/
|
|
9
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
10
|
+
import { type Config, type ProviderProfile } from './index.js';
|
|
11
|
+
export declare const GENERATE_IMAGE_NAME = "generate_image";
|
|
12
|
+
export declare const DEFAULT_IMAGE_TOOL_TIMEOUT_MS = 180000;
|
|
13
|
+
export declare const DEFAULT_MAX_IMAGE_BYTES: number;
|
|
14
|
+
export interface ImageToolHost {
|
|
15
|
+
config: () => Config;
|
|
16
|
+
resolveApiKey: (route: string, profile: ProviderProfile) => Promise<string>;
|
|
17
|
+
}
|
|
18
|
+
export declare function registerImageTools(ctx: Context, host: ImageToolHost): void;
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sub2API gateway integration for the harness LLM seam.
|
|
3
|
+
*
|
|
4
|
+
* One OpenAI-compatible base URL, many provider routes. In the sub2api
|
|
5
|
+
* gateway each API key is bound to a group, and the group decides the
|
|
6
|
+
* platform (openai / anthropic / grok) and the model list the key
|
|
7
|
+
* can serve.
|
|
8
|
+
*
|
|
9
|
+
* The LLM routes this plugin used to own (`sub2api-openai` / `sub2api-claude`
|
|
10
|
+
* / `sub2api-grok`) are served by the harness's own pi-ai
|
|
11
|
+
* adapter (`dsh-llm-pi-ai`, mounted dormant by dsh-base): protocol
|
|
12
|
+
* serialization, streaming, usage mapping, replay, and retry handling all live
|
|
13
|
+
* in pi-ai, which speaks each platform's native wire protocol upstream (OpenAI
|
|
14
|
+
* → Responses API, Claude → Messages API, the rest → chat/completions).
|
|
15
|
+
* This plugin contributes the sub2api-specific surface on top: the
|
|
16
|
+
* `llm-sub2api:` settings section and its web page (baseURL + per-key model
|
|
17
|
+
* catalogs + keys), gateway model discovery and usage probes, the global
|
|
18
|
+
* image-generation tools, and a bridge
|
|
19
|
+
* that materializes the configured groups as `llm-pi-ai:` provider profiles
|
|
20
|
+
* the moment the section lands (see `./pi-ai.ts`).
|
|
21
|
+
*
|
|
22
|
+
* Keys are stored through the harness credential seam; the base URL and
|
|
23
|
+
* per-key model catalogs live in the `llm-sub2api:` settings section
|
|
24
|
+
* (the active profile `cordis.patch.yml`, written by the web settings page).
|
|
25
|
+
*
|
|
26
|
+
* @module dsh-sub2api
|
|
27
|
+
*/
|
|
28
|
+
import type { Context, Volatile } from '@deepseek-ai/cordis';
|
|
29
|
+
import z from '@deepseek-ai/schemastery';
|
|
30
|
+
export { PI_AI_NS, ROUTE_PREFIX, syncPiAiProfiles, translateToPiAi, type PiAiModelProfile, type PiAiProviderProfile, type PiAiSettingsSection, } from './pi-a./pi-ai.jsort { applyPiAiMultiTurnPatch, type PiAiPatchResult } from './pi-a./pi-ai-patch.jsort declare const name = "llm-sub2api";
|
|
31
|
+
export declare const inject: string[];
|
|
32
|
+
/** Context capacity assumed for a model neither configuration nor discovery sizes. */
|
|
33
|
+
export declare const DEFAULT_CONTEXT_WINDOW = 128000;
|
|
34
|
+
/** Output capability assumed for a model neither configuration nor discovery sizes. */
|
|
35
|
+
export declare const DEFAULT_MAX_TOKENS = 8192;
|
|
36
|
+
/**
|
|
37
|
+
* Reasoning effort levels exposed for reasoning-capable models. The gateway
|
|
38
|
+
* speaks the OpenAI chat-completions protocol, so the ids are the OpenAI
|
|
39
|
+
* `reasoning_effort` vocabulary and are sent through verbatim. Per-model
|
|
40
|
+
* configuration (filled from models.dev `reasoning_options`) may expose
|
|
41
|
+
* additional vocabulary such as `none`, `xhigh`, or `max`.
|
|
42
|
+
*/
|
|
43
|
+
export declare const REASONING_EFFORTS: readonly {
|
|
44
|
+
id: string;
|
|
45
|
+
name: string;
|
|
46
|
+
}[];
|
|
47
|
+
export type ProviderKey = 'openai' | 'claude' | 'grok';
|
|
48
|
+
export interface ProviderDef {
|
|
49
|
+
key: ProviderKey;
|
|
50
|
+
route: string;
|
|
51
|
+
label: string;
|
|
52
|
+
icon: string;
|
|
53
|
+
}
|
|
54
|
+
/** The provider routes this plugin owns, keyed by sub2api platform name. */
|
|
55
|
+
export declare const PROVIDERS: readonly ProviderDef[];
|
|
56
|
+
export interface CatalogModel {
|
|
57
|
+
/** Model id sent to the provider and accepted by {@link GenerateOptions.model}. */
|
|
58
|
+
id: string;
|
|
59
|
+
/** Display name for selectors; defaults to the id. */
|
|
60
|
+
name?: string;
|
|
61
|
+
/** Maximum combined request and response context in tokens. */
|
|
62
|
+
contextWindow?: number;
|
|
63
|
+
/** Maximum output tokens. */
|
|
64
|
+
maxTokens?: number;
|
|
65
|
+
/**
|
|
66
|
+
* Accepted request modalities. Absent or empty: the adapter guesses from
|
|
67
|
+
* the model id (multimodal families such as gpt/claude/gemini/grok/glm
|
|
68
|
+
* declare `[text, image]`, everything else stays `[text]`). Non-empty:
|
|
69
|
+
* exactly those modalities, e.g. `[text]` to pin a multimodal-looking
|
|
70
|
+
* model to text only.
|
|
71
|
+
*/
|
|
72
|
+
input?: Array<'text' | 'image'>;
|
|
73
|
+
/**
|
|
74
|
+
* Reasoning effort levels selectable for this model. Absent: every non-image
|
|
75
|
+
* model on any route exposes low/medium/high (the gateway is OpenAI-compatible
|
|
76
|
+
* on all routes). Empty array: reasoning effort is explicitly off for this
|
|
77
|
+
* model. Non-empty: exposes exactly those levels verbatim (e.g. models.dev
|
|
78
|
+
* vocabularies such as `xhigh`/`max`/`none`).
|
|
79
|
+
*/
|
|
80
|
+
reasoningEfforts?: string[];
|
|
81
|
+
}
|
|
82
|
+
export interface ProviderProfile {
|
|
83
|
+
/** Credential reference (environment-variable name) resolved per request through `ctx.credentials`. */
|
|
84
|
+
apiKeyEnv?: string;
|
|
85
|
+
/**
|
|
86
|
+
* Wire protocol spoken to the gateway for this platform group. Absent
|
|
87
|
+
* selects the group's native protocol (openai → responses, claude →
|
|
88
|
+
* messages, grok → chat/completions). Explicitly name a protocol to
|
|
89
|
+
* force a different endpoint, e.g. a gateway that serves a group through
|
|
90
|
+
* chat/completions after all.
|
|
91
|
+
*/
|
|
92
|
+
api?: ApiProtocol;
|
|
93
|
+
/** Advisory model catalog for this route. */
|
|
94
|
+
models?: CatalogModel[];
|
|
95
|
+
}
|
|
96
|
+
/** One dedicated model used by a global image tool, independent of the chat route. */
|
|
97
|
+
export interface ImageToolModelRef {
|
|
98
|
+
/** Sub2API platform that owns the key and catalog (`openai` / `claude` / `grok`). */
|
|
99
|
+
provider: string;
|
|
100
|
+
/** Model id sent to the gateway. */
|
|
101
|
+
model: string;
|
|
102
|
+
}
|
|
103
|
+
export interface ImageToolsConfig {
|
|
104
|
+
/** Image-generation model used by the global `generate_image` tool. */
|
|
105
|
+
generate?: ImageToolModelRef;
|
|
106
|
+
}
|
|
107
|
+
export interface Config {
|
|
108
|
+
/** OpenAI-compatible gateway base URL, e.g. http://localhost:8080/v1. */
|
|
109
|
+
baseURL: string;
|
|
110
|
+
/** Per-platform provider profiles keyed by sub2api platform name. */
|
|
111
|
+
providers: Record<ProviderKey, ProviderProfile>;
|
|
112
|
+
/** Dedicated models for the global image-generation tools. */
|
|
113
|
+
tools?: ImageToolsConfig;
|
|
114
|
+
}
|
|
115
|
+
/** Live configuration references owned by the DSH Loader. */
|
|
116
|
+
export interface LiveConfig {
|
|
117
|
+
baseURL: Volatile<string>;
|
|
118
|
+
providers: Volatile<Record<ProviderKey, ProviderProfile>>;
|
|
119
|
+
tools: Volatile<ImageToolsConfig>;
|
|
120
|
+
}
|
|
121
|
+
/** Capture one configuration snapshot for a gateway operation. */
|
|
122
|
+
export declare function readConfig(config: LiveConfig): Config;
|
|
123
|
+
export declare const Config: z<Partial<Config>, LiveConfig>;
|
|
124
|
+
/**
|
|
125
|
+
* Wire protocol the adapter speaks to the gateway for one route. Each value
|
|
126
|
+
* names a real endpoint: `openai-completions` → `/chat/completions`,
|
|
127
|
+
* `openai-responses` → `/responses`, `anthropic-messages` → `/messages`.
|
|
128
|
+
*/
|
|
129
|
+
export type ApiProtocol = 'openai-completions' | 'openai-responses' | 'anthropic-messages';
|
|
130
|
+
export declare const API_PROTOCOLS: readonly ApiProtocol[];
|
|
131
|
+
/** Resolve the wire protocol for one provider key; shared by chat routes and the global image tools. */
|
|
132
|
+
export declare function apiProtocolForKey(key: ProviderKey, profile: ProviderProfile): ApiProtocol;
|
|
133
|
+
/**
|
|
134
|
+
* The OpenAI-style API root for a gateway base URL. The Sub2API settings page
|
|
135
|
+
* stores the bare host (e.g. `https://gateway.example:6443`); OpenAI-compatible
|
|
136
|
+
* endpoints (`/responses`, `/chat/completions`, `/models`, `/usage`) live under
|
|
137
|
+
* the `/v1` root, so it is appended here when missing. A URL already carrying
|
|
138
|
+
* `/v1` passes through unchanged.
|
|
139
|
+
*/
|
|
140
|
+
export declare function gatewayApiRoot(baseURL: string): string;
|
|
141
|
+
/**
|
|
142
|
+
* The bare-host form the Anthropic SDK expects: `@anthropic-ai/sdk` treats the
|
|
143
|
+
* configured URL as the host and always appends `/v1/messages` itself, so a
|
|
144
|
+
* `/v1`-rooted URL would hit `/v1/v1/messages` (404). Strips a trailing `/v1`
|
|
145
|
+
* when present.
|
|
146
|
+
*/
|
|
147
|
+
export declare function gatewayAnthropicRoot(baseURL: string): string;
|
|
148
|
+
export declare function apply(ctx: Context, config: LiveConfig): void;
|