@deepseek-ai/dsh-llm-pi-ai 0.1.2-alpha.2 → 0.1.2-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/README.i18n.yaml CHANGED
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/llm/llm-pi-ai/README.md
5
- README.md: dcafde78e176bd0acd142145d651d6d5b5539626
6
- README.zh.md: a7292638b8449d7192d3e003f0377967d11ef94d
5
+ README.md: 5994a72f28b0a52890cb7bf7a5bc2ee33eedf418
6
+ README.zh.md: 5f1c893128714caf24941943c57eaf3ab43314e0
package/README.md CHANGED
@@ -106,7 +106,7 @@ Profiles are re-read once per operation through the optional settings seam: the
106
106
 
107
107
  ### Discover models from endpoints
108
108
 
109
- The plugin answers "which models can this provider serve?" for a route a configuration surface is editing or drafting. A route the installed catalog ships is answered from that catalog with no network call; only a route the catalog does not describe is interrogated over the wire (`openai-completions` and `openai-responses` shapes). The reply is candidate metadata a surface may offer for adoption — nothing is stored, and `settings.yaml` remains the only thing that decides what a route serves.
109
+ The plugin answers "which models can this provider serve?" for a route a configuration surface is editing or drafting. A route the installed catalog ships is answered from that catalog with no network call; only a route the catalog does not describe is interrogated over the wire (`openai-completions` and `openai-responses` shapes). A named configured route supplies its stored credential and profile `headers` inside the Host, so deployment headers configured through `settings.yaml` or Cordis config reach `GET /models` without becoming discovery-request or Models-page fields; a key typed into the form still wins over the stored credential. The reply is candidate metadata a surface may offer for adoption — nothing is stored, and `settings.yaml` remains the only thing that decides what a route serves.
110
110
 
111
111
  ### Failures and recovery
112
112
 
@@ -210,7 +210,7 @@ These limits define where the adapter stops and future work begins. They are cur
210
210
  - **Provider-native discovery answers through this plugin's ambient context** — a route naming no credential defers to the catalog provider's own resolution, which asks for environment values (`AZURE_OPENAI_API_KEY`, `AWS_PROFILE`, and each provider's own set) and for local credential files. Both questions are answered here: the credential seam is consulted before the process environment, and file existence is checked against the host process's filesystem with `~` expanded. What it cannot do is *read* a credential file's contents — a provider that parses `~/.aws/credentials` itself does so directly, outside the seam.
211
211
  - **Settings can add or override routes, not remove composition routes** — the user layer merges over the composition base, so deleting a `cordis.yml`-provided provider is a composition change.
212
212
  - **The layered merge has no delete for dict keys** — a `reasoningEfforts` level, `modelOverrides` entry, or `compat` field the base declares can be overridden but not removed by the user layer.
213
- - **`headers` can carry a credential the redactor never sees** — the profile's `headers` dict is plain strings; store credentials as `apiKeyEnv` references.
213
+ - **`headers` can carry a credential the redactor never sees** — profile resolution rejects names and values Fetch cannot represent, but the dict remains plain strings; store credentials as `apiKeyEnv` references.
214
214
  - **A route's catalog never refreshes itself** — the catalog is whatever `settings.yaml` says; nothing here queries a provider for the models it serves.
215
215
  - **One wire protocol per route** — a mixed-protocol catalog route cannot host a model of the other protocol; splitting the provider across two route keys is the workaround.
216
216
  - **A modality declaration is not verified** — a model declaring `image` its gateway does not serve is refused by the provider after prompt admission. The durable image remains in history and the same misdeclared model can fail again; switching to a text-only model remains possible because the shared LLM runtime projects image references into stable text for that request.
@@ -232,3 +232,5 @@ This Dev Note is non-authoritative working context: undecided directions and not
232
232
  - The `compat` switch set is pinned to pi-ai's compat types by drift gates; an upstream upgrade that adds a field, gives a further protocol a compat type, or widens a value union fails the build until someone classifies it.
233
233
 
234
234
  </details>
235
+
236
+ **Runtime invariant:** No companion is published. This package exposes no independent event sequence or mutable data relation beyond contracts enforced at its owning seam.
package/README.zh.md CHANGED
@@ -106,7 +106,7 @@ profile 通过可选 settings seam 每次操作重新读取:base 与用户的
106
106
 
107
107
  ### 从端点发现模型
108
108
 
109
- 插件会回答"该提供方可以提供哪些模型?",供配置界面正在编辑或起草的路由使用。已安装目录提供的路由直接由目录回答,不发网络请求;只有目录未描述的路由才会经网络询问(`openai-completions` 与 `openai-responses` 形状)。回答是界面可以提供给用户采纳的候选元数据——不存储任何内容,`settings.yaml` 仍然是决定路由服务内容的唯一事实。
109
+ 插件会回答"该提供方可以提供哪些模型?",供配置界面正在编辑或起草的路由使用。已安装目录提供的路由直接由目录回答,不发网络请求;只有目录未描述的路由才会经网络询问(`openai-completions` 与 `openai-responses` 形状)。已配置且具名的路由会在 Host 内部提供已存凭据与 profile `headers`,因此通过 `settings.yaml` 或 Cordis 配置设置的部署标头可以到达 `GET /models`,但不会成为发现请求或 Models 页面的字段;表单中新键入的密钥仍优先于已存凭据。回答是界面可以提供给用户采纳的候选元数据——不存储任何内容,`settings.yaml` 仍然是决定路由服务内容的唯一事实。
110
110
 
111
111
  ### 失败与恢复
112
112
 
@@ -210,7 +210,7 @@ pi-ai 事件变成 harness 的推理、文本、工具调用、用量与 finish
210
210
  - **提供方原生发现经本插件的 ambient context 回答**——不点名凭据的路由交由目录提供方自身解析,它会询问环境值(`AZURE_OPENAI_API_KEY`、`AWS_PROFILE` 及各提供方自有集合)与本地凭据文件。两个问题都在这里得到回答:凭据 seam 先于进程环境被查询,文件存在性则针对宿主进程的文件系统以 `~` 展开后检查。它做不到的是*读取*凭据文件内容——自行解析 `~/.aws/credentials` 的提供方会直接读取,不经该 seam。
211
211
  - **设置可以新增或覆盖路由,不能移除组合路由**——用户层覆盖组合 base,因此删除 `cordis.yml` 提供的提供方属于组合变更。
212
212
  - **分层合并对字典键没有删除**——base 声明的 `reasoningEfforts` 等级、`modelOverrides` 条目或 `compat` 字段可以被用户层覆盖,但不能被移除。
213
- - **`headers` 可以携带 redactor 永远看不到的凭据**——profile 的 `headers` 字典是纯字符串;以 `apiKeyEnv` 引用存储凭据。
213
+ - **`headers` 可以携带 redactor 永远看不到的凭据**——profile 解析会拒绝 Fetch 无法表示的名称与值,但该字典仍是纯字符串;以 `apiKeyEnv` 引用存储凭据。
214
214
  - **路由目录不会自行刷新**——目录就是 `settings.yaml` 的内容;这里没有任何机制向提供方查询它提供的模型。
215
215
  - **每条路由一种协议格式**——混合协议目录路由无法承载另一协议格式的模型;把提供方拆到两个路由键是变通办法。
216
216
  - **模态声明不受校验**——声明 `image` 而其网关不支持的模型会在提示词准入后被提供方拒绝。持久图片仍留在历史中,同一误声明模型可能再次失败;切换到纯文本模型仍然可行,因为共享 LLM 运行时会针对该请求把图片引用投影为稳定文本。
@@ -232,3 +232,5 @@ pi-ai 事件变成 harness 的推理、文本、工具调用、用量与 finish
232
232
  - `compat` 开关集合由漂移门禁钉在 pi-ai 的 compat 类型上;上游升级若新增字段、为更多协议赋予 compat 类型或扩大值联合,会在有人分类前让构建失败。
233
233
 
234
234
  </details>
235
+
236
+ **运行时不变式:** 不发布伴生入口。本包没有独立事件序列或可变数据关系,相关约定在所属 seam 强制执行。
package/lib/index.js CHANGED
@@ -984,7 +984,7 @@ const Config = z.object({ providers: z.dict(profile).default({}) });
984
984
  * renders and the value an absent section resolves to; wrapping it would break
985
985
  * both.
986
986
  * @param config - the resolved section to check.
987
- * @throws Error naming the route and model that cannot be served.
987
+ * @throws Error naming the route and configuration entry that cannot be served.
988
988
  */
989
989
  function assertServiceable(config) {
990
990
  resolveProfiles(config.providers);
@@ -995,6 +995,14 @@ function rejectRemovedFields(provider, source) {
995
995
  if ("provider" in legacy) throw new Error(`llm-pi-ai: provider "${provider}" sets "provider", which moved to the providers dict key`);
996
996
  if ("maxRetries" in legacy || "maxRetryDelayMs" in legacy) throw new Error(`llm-pi-ai: provider "${provider}" sets maxRetries or maxRetryDelayMs, which were removed; compose agent recovery with dsh-llm-retry`);
997
997
  }
998
+ /** Reject a profile header that Fetch cannot put on a provider request. */
999
+ function assertValidHeaders(provider, headers) {
1000
+ for (const [name, value] of Object.entries(headers ?? {})) try {
1001
+ new Headers([[name, value]]);
1002
+ } catch {
1003
+ throw new Error(`llm-pi-ai: provider "${provider}" header "${name}" is not valid for Fetch; use a valid HTTP field name and a single-line value representable as bytes`);
1004
+ }
1005
+ }
998
1006
  /**
999
1007
  * Validate profiles and return a detached route-keyed map suitable for
1000
1008
  * per-request reads. This is the one explicit resolve step, so an omitted dict
@@ -1012,6 +1020,7 @@ function resolveProfiles(providers) {
1012
1020
  if (provider.length === 0) throw new Error("llm-pi-ai: provider names must be non-empty");
1013
1021
  if (source.baseURL !== void 0 && source.baseURL.length === 0) throw new Error(`llm-pi-ai: provider "${provider}" has an empty baseURL`);
1014
1022
  if (source.displayName !== void 0 && source.displayName.length === 0) throw new Error(`llm-pi-ai: provider "${provider}" has an empty displayName`);
1023
+ assertValidHeaders(provider, source.headers);
1015
1024
  const streamIdleTimeoutMs = source.streamIdleTimeoutMs ?? 3e5;
1016
1025
  if (!Number.isFinite(streamIdleTimeoutMs) || streamIdleTimeoutMs <= 0 || streamIdleTimeoutMs > MAX_TIMER_DELAY_MS) throw new Error(`llm-pi-ai: provider "${provider}" streamIdleTimeoutMs must be a positive finite number no greater than ${MAX_TIMER_DELAY_MS}`);
1017
1026
  const maxRequestImageBytes = source.maxRequestImageBytes ?? 20971520;
@@ -2140,16 +2149,14 @@ function usableProbeKey(raw) {
2140
2149
  /**
2141
2150
  * Interrogate one draft provider endpoint for the models it advertises.
2142
2151
  * @param request - the endpoint, protocol, and one-shot credential to use.
2143
- * @param storedApiKey - the credential the named route already stored, asked
2144
- * for only when the draft carries none and only on the path that reaches the
2145
- * network. A configuration surface never holds a stored secret — it edits a
2146
- * redacted descriptor — so without this an already-configured route would be
2147
- * interrogated unauthenticated and answer 401.
2152
+ * @param storedProfile - Host-owned headers and lazy credential resolution for
2153
+ * the named route. It is read only on the path that reaches the network; the
2154
+ * credential is resolved only when the draft carries none.
2148
2155
  * @returns the advertised models in endpoint order.
2149
2156
  * @throws LlmError when the protocol has no readable listing, the endpoint
2150
2157
  * refuses or fails the request, or the reply is not a model listing.
2151
2158
  */
2152
- async function discoverModels(request, storedApiKey) {
2159
+ async function discoverModels(request, storedProfile) {
2153
2160
  if (request.provider !== void 0) {
2154
2161
  const installed = catalogModels(request.provider);
2155
2162
  if (installed.size > 0) return [...installed.values()].map((model) => ({
@@ -2163,17 +2170,18 @@ async function discoverModels(request, storedApiKey) {
2163
2170
  const api = request.api ?? "openai-completions";
2164
2171
  if (!LISTABLE_PROTOCOLS.has(api)) throw new LlmError(`pi-ai protocol "${api}" has no model listing this build can read; enter this provider's models by hand`, "DISCOVERY_UNSUPPORTED");
2165
2172
  const url = listingUrl(request.baseURL);
2166
- const supplied = request.apiKey ?? await storedApiKey?.();
2173
+ const stored = storedProfile?.();
2174
+ const supplied = request.apiKey ?? await stored?.resolveApiKey();
2167
2175
  const apiKey = supplied === void 0 ? void 0 : usableProbeKey(supplied);
2168
2176
  let response;
2169
2177
  try {
2178
+ const headers = new Headers(stored?.headers === void 0 ? void 0 : Object.entries(stored.headers));
2179
+ headers.set("accept", "application/json");
2180
+ if (apiKey !== void 0) headers.set("authorization", `Bearer ${apiKey}`);
2181
+ for (const [name, value] of Object.entries(attributionHeaders())) headers.set(name, value);
2170
2182
  response = await fetch(url, {
2171
2183
  method: "GET",
2172
- headers: {
2173
- accept: "application/json",
2174
- ...apiKey === void 0 ? {} : { authorization: `Bearer ${apiKey}` },
2175
- ...attributionHeaders()
2176
- },
2184
+ headers,
2177
2185
  ...request.signal === void 0 ? {} : { signal: request.signal }
2178
2186
  });
2179
2187
  } catch (error) {
@@ -2503,23 +2511,20 @@ function apply(ctx, config) {
2503
2511
  directoryFacts = entries;
2504
2512
  };
2505
2513
  ensureDirectory();
2506
- /**
2507
- * The credential a named route already resolves, for an interrogation whose
2508
- * draft carries none. A route being declared for the first time names no
2509
- * profile yet, and a profile that names no credential defers to pi-ai's own
2510
- * discovery, so both answer `undefined` and the endpoint is asked
2511
- * unauthenticated — the same posture a request to that route would take.
2512
- */
2513
- const storedApiKey = async (provider) => {
2514
+ /** Host-owned request inputs for discovery of one configured route. */
2515
+ const storedDiscoveryProfile = (provider) => {
2514
2516
  if (provider === void 0) return void 0;
2515
2517
  const profile = profiles().get(provider);
2516
2518
  if (profile === void 0) return void 0;
2517
- return resolveApiKey(provider, profile);
2519
+ return {
2520
+ headers: profile.headers,
2521
+ resolveApiKey: () => resolveApiKey(provider, profile)
2522
+ };
2518
2523
  };
2519
2524
  ctx.llm.registerModelDiscovery(NS, (request, signal) => discoverModels({
2520
2525
  ...request,
2521
2526
  ...signal === void 0 ? {} : { signal }
2522
- }, () => storedApiKey(request.provider)));
2527
+ }, () => storedDiscoveryProfile(request.provider)));
2523
2528
  let registration;
2524
2529
  let registeredFacts;
2525
2530
  const ensureRegistrationFacts = () => {
@@ -110,7 +110,7 @@ export interface PiAiProviderProfile {
110
110
  * to answer instead.
111
111
  */
112
112
  defaultInput?: PiAiModality[];
113
- /** Provider request headers; Harness attribution wins reserved names. */
113
+ /** Provider request headers, validated against Fetch when the profile resolves; Harness attribution wins reserved names. */
114
114
  headers?: Record<string, string>;
115
115
  /** Provider-neutral pi-ai reasoning level. */
116
116
  reasoning?: ModelThinkingLevel;
@@ -196,7 +196,7 @@ export declare const Config: z<Config>;
196
196
  * renders and the value an absent section resolves to; wrapping it would break
197
197
  * both.
198
198
  * @param config - the resolved section to check.
199
- * @throws Error naming the route and model that cannot be served.
199
+ * @throws Error naming the route and configuration entry that cannot be served.
200
200
  */
201
201
  export declare function assertServiceable(config: Config): void;
202
202
  /**
@@ -22,17 +22,22 @@
22
22
  * @module dsh-llm-pi-ai/discovery
23
23
  */
24
24
  import type { LlmDiscoveredModel, LlmModelDiscoveryOperation } from '@deepseek-ai/dsh-llm';
25
+ /** Host-owned profile inputs that a configuration draft deliberately omits. */
26
+ export interface StoredModelDiscoveryProfile {
27
+ /** Deployment headers configured on the named route. */
28
+ readonly headers: Readonly<Record<string, string>> | undefined;
29
+ /** Resolve the named route's credential only when the draft carries none. */
30
+ readonly resolveApiKey: () => Promise<string | undefined>;
31
+ }
25
32
  /**
26
33
  * Interrogate one draft provider endpoint for the models it advertises.
27
34
  * @param request - the endpoint, protocol, and one-shot credential to use.
28
- * @param storedApiKey - the credential the named route already stored, asked
29
- * for only when the draft carries none and only on the path that reaches the
30
- * network. A configuration surface never holds a stored secret — it edits a
31
- * redacted descriptor — so without this an already-configured route would be
32
- * interrogated unauthenticated and answer 401.
35
+ * @param storedProfile - Host-owned headers and lazy credential resolution for
36
+ * the named route. It is read only on the path that reaches the network; the
37
+ * credential is resolved only when the draft carries none.
33
38
  * @returns the advertised models in endpoint order.
34
39
  * @throws LlmError when the protocol has no readable listing, the endpoint
35
40
  * refuses or fails the request, or the reply is not a model listing.
36
41
  */
37
- export declare function discoverModels(request: LlmModelDiscoveryOperation, storedApiKey?: () => Promise<string | undefined>): Promise<readonly LlmDiscoveredModel[]>;
42
+ export declare function discoverModels(request: LlmModelDiscoveryOperation, storedProfile?: () => StoredModelDiscoveryProfile | undefined): Promise<readonly LlmDiscoveredModel[]>;
38
43
  //# sourceMappingURL=discovery.d.ts.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-llm-pi-ai",
3
3
  "description": "pi-ai-backed DeepSeek adapter for the DeepSeek Harness LLM seam (design-verification twin of dsh-llm-deepseek)",
4
- "version": "0.1.2-alpha.2",
4
+ "version": "0.1.2-alpha.4",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -18,48 +18,41 @@
18
18
  "types": "./lib/types/index.d.ts",
19
19
  "default": "./lib/index.js"
20
20
  },
21
- "./invariant": {
22
- "types": "./lib/types/invariant.d.ts",
23
- "default": "./lib/invariant.js"
24
- },
25
21
  "./src/*": "./src/*",
26
22
  "./package.json": "./package.json"
27
23
  },
28
24
  "files": [
29
25
  "lib/index.js",
30
- "lib/invariant.js",
31
26
  "lib/types/**/*.d.ts"
32
27
  ],
33
28
  "license": "MIT",
34
29
  "peerDependencies": {
35
30
  "@deepseek-ai/cordis": "^4.0.2",
36
- "@deepseek-ai/dsh-attachment": "^0.1.2-alpha.2",
37
- "@deepseek-ai/dsh-authorization": "^0.1.2-alpha.2",
38
- "@deepseek-ai/dsh-fs": "^0.1.2-alpha.2",
39
- "@deepseek-ai/dsh-invariants": "^0.1.2-alpha.2",
40
- "@deepseek-ai/dsh-credentials": "^0.1.2-alpha.2",
41
- "@deepseek-ai/dsh-launch-environment": "^0.1.2-alpha.2",
42
- "@deepseek-ai/dsh-llm": "^0.1.2-alpha.2",
43
- "@deepseek-ai/dsh-settings": "^0.1.2-alpha.2",
44
- "@deepseek-ai/dsh-timeout": "^0.1.2-alpha.2"
31
+ "@deepseek-ai/dsh-credentials": "^0.1.2-alpha.4",
32
+ "@deepseek-ai/dsh-fs": "^0.1.2-alpha.4",
33
+ "@deepseek-ai/dsh-launch-environment": "^0.1.2-alpha.4",
34
+ "@deepseek-ai/dsh-llm": "^0.1.2-alpha.4",
35
+ "@deepseek-ai/dsh-settings": "^0.1.2-alpha.4",
36
+ "@deepseek-ai/dsh-timeout": "^0.1.2-alpha.4",
37
+ "@deepseek-ai/dsh-attachment": "^0.1.2-alpha.4",
38
+ "@deepseek-ai/dsh-authorization": "^0.1.2-alpha.4"
45
39
  },
46
40
  "dependencies": {
47
41
  "@earendil-works/pi-ai": "^0.84.2",
48
- "@deepseek-ai/dsh-brand": "^0.1.2-alpha.2",
49
- "@deepseek-ai/dsh-util-values": "^0.1.2-alpha.2",
42
+ "@deepseek-ai/dsh-util-values": "^0.1.2-alpha.4",
43
+ "@deepseek-ai/dsh-brand": "^0.1.2-alpha.4",
50
44
  "@deepseek-ai/schemastery": "^3.18.2"
51
45
  },
52
46
  "devDependencies": {
53
47
  "@deepseek-ai/cordis": "^4.0.2",
54
- "@deepseek-ai/dsh-attachment": "^0.1.2-alpha.2",
55
- "@deepseek-ai/dsh-authorization": "^0.1.2-alpha.2",
56
- "@deepseek-ai/dsh-credentials": "^0.1.2-alpha.2",
57
- "@deepseek-ai/dsh-invariants": "^0.1.2-alpha.2",
58
- "@deepseek-ai/dsh-launch-environment": "^0.1.2-alpha.2",
59
- "@deepseek-ai/dsh-llm": "^0.1.2-alpha.2",
60
- "@deepseek-ai/dsh-llm-deepseek": "^0.1.2-alpha.2",
61
- "@deepseek-ai/dsh-fs": "^0.1.2-alpha.2",
62
- "@deepseek-ai/dsh-settings": "^0.1.2-alpha.2",
63
- "@deepseek-ai/dsh-timeout": "^0.1.2-alpha.2"
48
+ "@deepseek-ai/dsh-attachment": "^0.1.2-alpha.4",
49
+ "@deepseek-ai/dsh-authorization": "^0.1.2-alpha.4",
50
+ "@deepseek-ai/dsh-credentials": "^0.1.2-alpha.4",
51
+ "@deepseek-ai/dsh-fs": "^0.1.2-alpha.4",
52
+ "@deepseek-ai/dsh-launch-environment": "^0.1.2-alpha.4",
53
+ "@deepseek-ai/dsh-llm": "^0.1.2-alpha.4",
54
+ "@deepseek-ai/dsh-llm-deepseek": "^0.1.2-alpha.4",
55
+ "@deepseek-ai/dsh-settings": "^0.1.2-alpha.4",
56
+ "@deepseek-ai/dsh-timeout": "^0.1.2-alpha.4"
64
57
  }
65
58
  }
package/lib/invariant.js DELETED
@@ -1,23 +0,0 @@
1
- //#region lib/types/invariant.js
2
- /**
3
- * Package-owned invariant companion for `@deepseek-ai/dsh-llm-pi-ai`.
4
- * @module @deepseek-ai/dsh-llm-pi-ai/invariant
5
- */
6
- const PACKAGE_NAME = "@deepseek-ai/dsh-llm-pi-ai";
7
- /** Cordis companion plugin name. */
8
- const name = "llm-pi-ai-invariant";
9
- /** Service required before the companion can reserve package ownership. */
10
- const inject = ["invariants"];
11
- /**
12
- * No runtime invariant: this package exposes no independent event sequence or mutable data relation
13
- * beyond contracts enforced at its owning seam.
14
- */
15
- const install = () => {};
16
- /**
17
- * Register this package's invariant companion.
18
- * @param ctx - Cordis context carrying the invariant service.
19
- * @returns the installed registration's disposer after setup succeeds.
20
- */
21
- const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
22
- //#endregion
23
- export { apply, inject, name };
@@ -1,16 +0,0 @@
1
- /**
2
- * Package-owned invariant companion for `@deepseek-ai/dsh-llm-pi-ai`.
3
- * @module @deepseek-ai/dsh-llm-pi-ai/invariant
4
- */
5
- import type { Context } from '@deepseek-ai/cordis';
6
- /** Cordis companion plugin name. */
7
- export declare const name = "llm-pi-ai-invariant";
8
- /** Service required before the companion can reserve package ownership. */
9
- export declare const inject: string[];
10
- /**
11
- * Register this package's invariant companion.
12
- * @param ctx - Cordis context carrying the invariant service.
13
- * @returns the installed registration's disposer after setup succeeds.
14
- */
15
- export declare const apply: (ctx: Context) => Promise<() => void>;
16
- //# sourceMappingURL=invariant.d.ts.map