@qilin-agent/llm 3.1.4 → 3.1.6

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
@@ -24,8 +24,8 @@
24
24
  en: 7550d716b90fcb09
25
25
  zh: 77891a44ee623c7a
26
26
  /qilin-agent-llm/use-this-package/what-you-can-do:
27
- en: b45d7a414141734e
28
- zh: a641c8ea3827cee6
27
+ en: 2d766530fc00ae24
28
+ zh: de0baea57bfae093
29
29
  /qilin-agent-llm/use-this-package/failures-and-recovery:
30
30
  en: 4db9ebfa25dbadfd
31
31
  zh: b2aebbd3215d50fc
@@ -39,8 +39,8 @@
39
39
  en: ae1618577f4e8364
40
40
  zh: a6e8ab1563c08dfb
41
41
  /qilin-agent-llm/understand-the-implementation/main-flow:
42
- en: b6a378ff4b7caf20
43
- zh: 1453cd5e7f774575
42
+ en: 0b97d7ed2fff9e5b
43
+ zh: 753f8b042ee2e4dc
44
44
  /qilin-agent-llm/understand-the-implementation/invariants:
45
45
  en: 0163a050239248e5
46
46
  zh: 885c95bedcbe2ff4
package/README.md CHANGED
@@ -64,7 +64,7 @@ After a successful mount, `ctx.llm.listProviders()` reports the registered route
64
64
 
65
65
  - **Stream one model call** — `ctx.llm.stream(options)` yields raw chunks (token-level deltas) for any registered provider and model; consumers assemble them with `BlockAssembler`.
66
66
  - **Register provider adapters** — an adapter owns one or more provider routes, and its registration captures that route's retry policy; registering the same route twice fails with `DUPLICATE_ADAPTER`.
67
- - **Expose and activate providers through configuration** — adapters declare configurable-provider routes plus a settings namespace, so configuration surfaces can activate dormant providers and edit connection facts without a restart. `LlmConfigurableProvider.error` reports a configuration diagnostic for repair; unaffected models can remain serviceable.
67
+ - **Expose and activate providers through configuration** — adapters declare configurable-provider routes plus a settings namespace, so configuration surfaces can activate dormant providers and edit connection facts without a restart. `LlmConfigurableProvider.error` reports a configuration diagnostic for repair; unaffected models can remain serviceable. An entry can also carry `defaultBaseURL`, the endpoint the adapter uses when the profile sets none, `nativeAuth`, the environment variables and OAuth sign-in that the adapter's authentication reads when the profile names no credential reference, and `baseURLEnv`, environment variables used to configure the endpoint. Configuration UIs read these fields from the directory without calling the adapter.
68
68
  - **Discover and resolve models** — List the models an adapter advertises, interrogate an endpoint for the models it serves (candidates carry optional `inputModalities`; absence means unknown), and resolve one exact model's context window, output default, reasoning efforts, input modalities, and system prompt update mode: `LlmResolvedModelInfo.systemPromptUpdate` is `'in-history'` when the model reads the latest `system` message at any position as the effective system prompt and absent when only a leading system message is read; `normalizeModelInfo` rejects any other value with `INVALID_MODEL_INFO`.
69
69
  - **Validate call config** — an explicit or configured reasoning effort is checked against the exact model before any provider I/O, and an adapter-configured output cap is materialized when the request omits one.
70
70
  - **Read an embedded Assistant stream without expanding it** — `assistantStreamFirstTokenTime` (first token), `assistantStreamHasVisibleContent` (any visible content), and `assistantStreamHasVisibleText` (any visible text) answer their questions from the compact records with early exit; `lastAssistantStreamChunk` scans backward to the last raw chunk of one type, `assistantStreamChunks` and `joinAssistantStreamText` scan the whole stream, and `assembleAssistantStream` feeds a `BlockAssembler` one joined delta per run with the same blocks, usage, and replay state as the per-member expansion. `runFirstTokenTime` and `runFirstVisibleTime` do the early-exit scan for one packed run, and `isTokenDelta`, `isVisibleChunk`, and `chunkHasVisibleText` define the token and visibility rules for a single chunk. `expandAssistantStream` remains the validating path for records read at a durable boundary; it is not memoized, because a retained expansion costs roughly ten times the compact stream for as long as the event lives.
@@ -105,7 +105,7 @@ The service is built on one separation: **the logical contract is provider-neutr
105
105
 
106
106
  ### Main flow
107
107
 
108
- A request is validated against its exact model's capability — context window, output default, reasoning efforts, input modalities, and `systemPromptUpdate` mode — and any adapter-configured defaults are materialized. The runtime preserves freezing for already-frozen input; hand-built callers own input immutability. `prepareCall()` binds those facts, detached context, and retry policy to the exact adapter generation that performs terminal dispatch, so HMR or dynamic settings cannot combine one generation's image capability with another generation's endpoint. An image-capable adapter projects durable references into route-specific request versions; `resolveImageAttachmentAccess()` separately maps an attachment provider's optional host object into the current tool execution world without changing the request image or its `variantId`. A text-only route receives deterministic per-image placeholders, including tool-role result images, without rewriting append-only session history. Durable `FileBlock` references never reach any adapter: request assembly replaces each one, including tool-role result occurrences, with deterministic handle text naming the file and its saved read-only path, resolved through the mounted attachment and filesystem providers. `ctx.llm.fileRequestText(ref)` exposes that exact synchronous projection to request measurement. An image occurrence derived with `offloaded: true` reaches every route as placeholder text through `projectOffloadedImages()`. An image-capable route whose retained occurrences exceed its `LlmImageRequestBudget` at their exact bytes fails with `IMAGE_OFFLOAD_REQUIRED` naming the additional oldest occurrences (`requiredImageOffload()`), never with an unlogged projection; `qilin-compaction-image-offload` logs the selected occurrences in one `image/offload` event and retries. Adapters that charge visual tokens declare per-route `imageRequestPricing`, which `ctx.llm.imageRequestPricing(provider, model)` resolves synchronously for the token meter. Dispatch goes through the `llm/stream` waterfall, then chunks return as token-level deltas and every adapter outcome reaches the consumer as one terminal `finish` chunk.
108
+ A request is validated against its exact model's capability — context window, output default, reasoning efforts, input modalities, and `systemPromptUpdate` mode — and any adapter-configured defaults are materialized. The runtime preserves freezing for already-frozen input; hand-built callers own input immutability. `prepareCall()` binds those facts, detached context, and retry policy to the exact adapter generation that performs terminal dispatch, so HMR or dynamic settings cannot combine one generation's image capability with another generation's endpoint. An image-capable adapter projects durable references into route-specific request versions; `resolveImageAttachmentAccess()` separately maps an attachment provider's optional host object into the current tool execution world without changing the request image or its `variantId`. A text-only route receives deterministic per-image placeholders, including tool-role result images, without rewriting append-only session history. Durable `FileBlock` references never reach any adapter: request assembly replaces each one, including tool-role result occurrences, with deterministic handle text naming the file and its saved read-only path, resolved through the mounted attachment and filesystem providers. `ctx.llm.fileRequestText(ref)` exposes that exact synchronous projection to request measurement. An image occurrence derived with `offloaded: true` reaches every route as placeholder text through `projectOffloadedImages()`. An image-capable route whose retained occurrences exceed its `LlmImageRequestBudget` at their exact bytes fails with `IMAGE_OFFLOAD_REQUIRED` naming the additional oldest occurrences (`requiredImageOffload()`), never with an unlogged projection; `qilin-compaction-image-offload` logs the selected occurrences in one `image/offload` event and retries. Adapters that charge visual tokens declare per-route `imageRequestPricing`, which `ctx.llm.imageRequestPricing(provider, model)` resolves synchronously for the token meter. Dispatch goes through the `llm/stream` waterfall, then chunks return as token-level deltas and every adapter outcome reaches the consumer as one terminal `finish` chunk. `imageRequestTarget(provider, model, image)` exposes the same request-image dimensions and byte target to screenshot consumers; adapters without image resizing preserve the normalized source.
109
109
 
110
110
  File detection reads current content, including tool-role result content, on every request without caching message identities or freeze state. The [file-scan decision](../../../.agents/notes/implemented/simplification/2026-09-07-file-content-scan.md) records the measured traversal cost.
111
111
 
package/README.zh.md CHANGED
@@ -64,7 +64,7 @@ for await (const chunk of ctx.llm.stream({
64
64
 
65
65
  - **流式发起一次模型调用**——`ctx.llm.stream(options)` 为任何已注册提供方与模型产出原始分片(token 级增量);消费方用 `BlockAssembler` 组装。
66
66
  - **注册提供方适配器**——一个适配器拥有一个或多个提供方路由,其注册会捕获该路由的重试策略;重复注册同一路由会以 `DUPLICATE_ADAPTER` 失败。
67
- - **通过配置暴露并激活提供方**——适配器声明可配置提供方路由与 settings namespace,配置界面因此可以激活休眠提供方并编辑连接信息,无需重启。`LlmConfigurableProvider.error` 报告供修复的配置诊断;未受影响的模型仍可提供服务。
67
+ - **通过配置暴露并激活提供方**——适配器声明可配置提供方路由与 settings namespace,配置界面因此可以激活休眠提供方并编辑连接信息,无需重启。`LlmConfigurableProvider.error` 报告供修复的配置诊断;未受影响的模型仍可提供服务。条目还可以携带 `defaultBaseURL`(profile 未设置端点时适配器使用的端点)、`nativeAuth`(profile 未命名凭据引用时适配器认证读取的环境变量与 OAuth 登录)和 `baseURLEnv`(用于配置端点的环境变量)。配置界面从目录读取这些字段,无需调用适配器。
68
68
  - **发现与解析模型**——列出适配器公布的模型、询问端点它提供哪些模型(候选携带可选的 `inputModalities`;缺省表示未知),并解析某个精确模型的上下文窗口、输出默认值、推理(reasoning)强度、输入模态与系统提示词更新模式:当模型把任意位置最新的 `system` 消息读作有效系统提示词时,`LlmResolvedModelInfo.systemPromptUpdate` 为 `'in-history'`;只读取开头 system 消息时该字段缺失;`normalizeModelInfo` 以 `INVALID_MODEL_INFO` 拒绝任何其他值。
69
69
  - **校验调用配置**——显式或配置的推理强度会在任何提供方 I/O 之前对照精确模型校验;请求省略输出上限时,会填入适配器配置的输出上限。
70
70
  - **不展开即读取内嵌 Assistant 流**——`assistantStreamFirstTokenTime`(首 token)、`assistantStreamHasVisibleContent`(任一可见内容)与 `assistantStreamHasVisibleText`(任一可见文本)通过可提前退出的扫描直接从紧凑记录得出结果;`lastAssistantStreamChunk` 反向扫描到某一类型的最后一个原始 chunk,`assistantStreamChunks` 与 `joinAssistantStreamText` 扫描整个流,`assembleAssistantStream` 向 `BlockAssembler` 每个 run 喂一段拼接 delta,blocks/usage/replayState 与逐成员展开相同。`runFirstTokenTime` 与 `runFirstVisibleTime` 对单个打包 run 做提前退出扫描,`isTokenDelta`、`isVisibleChunk` 与 `chunkHasVisibleText` 定义单个 chunk 的 token 与可见性规则。`expandAssistantStream` 仍是持久边界读取记录的校验路径;它不被记忆化,因为保留的展开在事件生命周期内约花费紧凑流的十倍内存。
@@ -105,7 +105,7 @@ for await (const chunk of ctx.llm.stream({
105
105
 
106
106
  ### 主流程
107
107
 
108
- 请求会对照其精确模型的能力校验,包括上下文窗口、输出默认值、推理强度、输入模态与 `systemPromptUpdate` 模式,并填入任何适配器配置的默认值。运行时保留已冻结输入的冻结状态;手动构建请求的调用方负责保证输入不可变。`prepareCall()` 把这些事实、分离的上下文与重试策略绑定到执行最终分发的精确适配器代次,因此 HMR(热模块替换)或动态设置无法把一个代次的图片能力与另一代次的端点混用。支持图片的适配器把持久引用投影为路由专用请求版本;`resolveImageAttachmentAccess()` 会单独把附件提供方的可选宿主对象映射进当前工具执行世界,而不改变请求图片或其 `variantId`。纯文本路由接收确定性的逐图片占位符,包括 tool-role 结果图片,而不会改写仅追加会话历史。持久 `FileBlock` 引用永远不会到达任何适配器:请求组装把每个引用(包括 tool-role 结果中的出现)替换为确定性句柄文本,指出文件与其只读保存路径,路径经由挂载的附件与文件系统提供方解析。`ctx.llm.fileRequestText(ref)` 向请求计量公开相同的同步投影。派生后带有 `offloaded: true` 的图片出现位置,经 `projectOffloadedImages()` 以占位文本到达每条路由。支持图片的路由在保留的出现位置按精确字节超过其 `LlmImageRequestBudget` 时,以 `IMAGE_OFFLOAD_REQUIRED` 失败并说明还需省略多少最老的出现位置(`requiredImageOffload()`),绝不发送未记录的投影;`qilin-compaction-image-offload` 用一条 `image/offload` 事件记录所选位置并重试。对视觉 token 收费的适配器声明按路由的 `imageRequestPricing`,`ctx.llm.imageRequestPricing(provider, model)` 为 token meter 同步解析它。分发经过 `llm/stream` waterfall(瀑布式事件),随后分片以 token 级增量返回,每个适配器结果都以唯一一个终止 `finish` 分片到达消费方。
108
+ 请求会对照其精确模型的能力校验,包括上下文窗口、输出默认值、推理强度、输入模态与 `systemPromptUpdate` 模式,并填入任何适配器配置的默认值。运行时保留已冻结输入的冻结状态;手动构建请求的调用方负责保证输入不可变。`prepareCall()` 把这些事实、分离的上下文与重试策略绑定到执行最终分发的精确适配器代次,因此 HMR(热模块替换)或动态设置无法把一个代次的图片能力与另一代次的端点混用。支持图片的适配器把持久引用投影为路由专用请求版本;`resolveImageAttachmentAccess()` 会单独把附件提供方的可选宿主对象映射进当前工具执行世界,而不改变请求图片或其 `variantId`。纯文本路由接收确定性的逐图片占位符,包括 tool-role 结果图片,而不会改写仅追加会话历史。持久 `FileBlock` 引用永远不会到达任何适配器:请求组装把每个引用(包括 tool-role 结果中的出现)替换为确定性句柄文本,指出文件与其只读保存路径,路径经由挂载的附件与文件系统提供方解析。`ctx.llm.fileRequestText(ref)` 向请求计量公开相同的同步投影。派生后带有 `offloaded: true` 的图片出现位置,经 `projectOffloadedImages()` 以占位文本到达每条路由。支持图片的路由在保留的出现位置按精确字节超过其 `LlmImageRequestBudget` 时,以 `IMAGE_OFFLOAD_REQUIRED` 失败并说明还需省略多少最老的出现位置(`requiredImageOffload()`),绝不发送未记录的投影;`qilin-compaction-image-offload` 用一条 `image/offload` 事件记录所选位置并重试。对视觉 token 收费的适配器声明按路由的 `imageRequestPricing`,`ctx.llm.imageRequestPricing(provider, model)` 为 token meter 同步解析它。分发经过 `llm/stream` waterfall(瀑布式事件),随后分片以 token 级增量返回,每个适配器结果都以唯一一个终止 `finish` 分片到达消费方。 `imageRequestTarget(provider, model, image)` 向截图调用方提供与模型请求一致的图片尺寸和字节目标;不缩放图片的适配器保留归一化后的原图。
109
109
 
110
110
  文件检测在每次请求时读取当前内容,包括 tool-role 结果内容,不缓存消息身份或冻结状态。[文件扫描决策](../../../.agents/notes/implemented/simplification/2026-09-07-file-content-scan.zh.md)记录了实测遍历成本。
111
111
 
package/lib/index.js CHANGED
@@ -1694,6 +1694,21 @@ var LlmAdapter = class {
1694
1694
  */
1695
1695
  imageRequestPricing(_provider, _model) {}
1696
1696
  /**
1697
+ * Resolve the image dimensions and byte target this adapter sends to the model.
1698
+ * The default preserves normalized images; adapters that resize must override it.
1699
+ * @param _provider - registered provider route.
1700
+ * @param _model - exact model id.
1701
+ * @param image - normalized image whose request projection is being resolved.
1702
+ * @returns the same target used by request serialization, before provider-internal processing.
1703
+ */
1704
+ imageRequestTarget(_provider, _model, image) {
1705
+ return {
1706
+ width: image.width,
1707
+ height: image.height,
1708
+ maxBytes: image.bytes
1709
+ };
1710
+ }
1711
+ /**
1697
1712
  * List models this adapter can currently advertise for one owned provider.
1698
1713
  * Core routing accepts unlisted model ids; catalog-driven entry points such
1699
1714
  * as the GUI may require membership. Adapters used there must advertise
@@ -1924,7 +1939,12 @@ let LlmRuntime = (() => {
1924
1939
  if (this.directory.has(entry.provider) && !own.has(entry.provider) || detached.some((seen) => seen.provider === entry.provider)) throw new LlmError(`configurable provider "${entry.provider}" is already declared`, "DUPLICATE_DIRECTORY");
1925
1940
  detached.push({
1926
1941
  ...entry,
1927
- settingsPath: [...entry.settingsPath]
1942
+ settingsPath: [...entry.settingsPath],
1943
+ ...entry.baseURLEnv === void 0 ? {} : { baseURLEnv: [...entry.baseURLEnv] },
1944
+ ...entry.nativeAuth === void 0 ? {} : { nativeAuth: {
1945
+ ...entry.nativeAuth,
1946
+ env: [...entry.nativeAuth.env]
1947
+ } }
1928
1948
  });
1929
1949
  }
1930
1950
  for (const entry of held) this.directory.delete(entry.provider);
@@ -1956,7 +1976,12 @@ let LlmRuntime = (() => {
1956
1976
  listConfigurableProviders() {
1957
1977
  return [...this.directory.values()].map((entry) => ({
1958
1978
  ...entry,
1959
- settingsPath: [...entry.settingsPath]
1979
+ settingsPath: [...entry.settingsPath],
1980
+ ...entry.baseURLEnv === void 0 ? {} : { baseURLEnv: [...entry.baseURLEnv] },
1981
+ ...entry.nativeAuth === void 0 ? {} : { nativeAuth: {
1982
+ ...entry.nativeAuth,
1983
+ env: [...entry.nativeAuth.env]
1984
+ } }
1960
1985
  }));
1961
1986
  }
1962
1987
  /**
@@ -2049,6 +2074,16 @@ let LlmRuntime = (() => {
2049
2074
  return this.adapters.get(provider)?.adapter.imageRequestPricing(provider, model);
2050
2075
  }
2051
2076
  /**
2077
+ * Resolve the image projection for an exact registered model route.
2078
+ * @param provider - registered provider route.
2079
+ * @param model - exact model id.
2080
+ * @param image - normalized image reference.
2081
+ * @returns dimensions and byte target used by the adapter's request serializer.
2082
+ */
2083
+ imageRequestTarget(provider, model, image) {
2084
+ return this.registration(provider).adapter.imageRequestTarget(provider, model, image);
2085
+ }
2086
+ /**
2052
2087
  * Resolve the exact text one durable file occurrence contributes to every
2053
2088
  * provider request in the current execution environment.
2054
2089
  * @param ref - durable verbatim file reference from model history.
@@ -1,70 +1,96 @@
1
1
  /* Generated by @qilin-agent/typert-generator from FaceModel — do not edit. */
2
2
  import { z } from 'zod'
3
3
 
4
+ import { createTypertRemoteInfo } from '@qilin-agent/typert-protocol/remote-info'
5
+
4
6
  let _qilin_agent_llm_llm_discoverModels_parameter_0$schema$value
5
7
  const _qilin_agent_llm_llm_discoverModels_parameter_0$schema = () => (_qilin_agent_llm_llm_discoverModels_parameter_0$schema$value ??= z.string())
6
8
  let _qilin_agent_llm_llm_discoverModels_parameter_1$schema$value
7
9
  const _qilin_agent_llm_llm_discoverModels_parameter_1$schema = () => (_qilin_agent_llm_llm_discoverModels_parameter_1$schema$value ??= z.object({
8
- 'provider': z.string().optional(),
9
- 'baseURL': z.string().optional(),
10
- 'api': z.string().optional(),
11
- 'apiKey': z.string().optional(),
10
+ 'provider': z.string().optional().describe('Route the draft is editing, when it edits an existing one. A route whose adapter already knows its models answers from that knowledge instead of asking the endpoint — the adapter\'s own registry is the better answer, and it costs no network call.'),
11
+ 'baseURL': z.string().optional().describe('Endpoint to interrogate. Optional because a route the adapter already describes needs none; a route it does not must supply one.'),
12
+ 'api': z.string().optional().describe('Wire protocol the endpoint speaks, when the draft names one.'),
13
+ 'apiKey': z.string().optional().describe('Credential for this interrogation alone; the harness never stores it.'),
12
14
  }))
13
15
  let _qilin_agent_llm_llm_discoverModels_result$schema$value
14
16
  const _qilin_agent_llm_llm_discoverModels_result$schema = () => (_qilin_agent_llm_llm_discoverModels_result$schema$value ??= z.array(z.object({
15
- 'id': z.string(),
16
- 'name': z.string().optional(),
17
- 'contextWindow': z.number().optional(),
18
- 'maxTokens': z.number().optional(),
19
- 'inputModalities': z.array(z.union([z.literal("text"), z.literal("image")])).optional(),
17
+ 'id': z.string().describe('Model id the endpoint accepts.'),
18
+ 'name': z.string().optional().describe('Human-readable name when the endpoint supplies one.'),
19
+ 'contextWindow': z.number().optional().describe('Maximum combined request and response context, when disclosed.'),
20
+ 'maxTokens': z.number().optional().describe('Maximum output tokens, when disclosed.'),
21
+ 'inputModalities': z.array(z.union([z.literal("text"), z.literal("image")])).optional().describe('Accepted input types when disclosed by the catalog or endpoint; absent means unknown.'),
20
22
  })))
21
23
  let _qilin_agent_llm_llm_listConfigurableProviders_result$schema$value
22
24
  const _qilin_agent_llm_llm_listConfigurableProviders_result$schema = () => (_qilin_agent_llm_llm_listConfigurableProviders_result$schema$value ??= z.array(z.object({
23
- 'provider': z.string(),
24
- 'displayName': z.string(),
25
- 'settingsNs': z.string(),
26
- 'settingsPath': z.array(z.string()),
27
- 'declared': z.boolean().optional(),
28
- 'error': z.string().optional(),
25
+ 'provider': z.string().describe('Provider route key this entry activates when configured.'),
26
+ 'displayName': z.string().describe('Human-readable provider name for configuration surfaces.'),
27
+ 'settingsNs': z.string().describe('User-settings namespace whose section configures this provider.'),
28
+ 'settingsPath': z.array(z.string()).describe('Path from that namespace\'s section root to this provider\'s profile object; empty when the whole section is the profile.'),
29
+ 'declared': z.boolean().optional().describe('Whether the owning adapter knows this route only because configuration declared it — a gateway or self-hosted server it ships nothing about. Absent means the adapter draws no such distinction; false means it does and this route is one of its own. Only the adapter can answer: a stored profile is how a user-added route AND a corrected shipped one both look from outside.'),
30
+ 'defaultBaseURL': z.string().optional().describe('Route endpoint the adapter uses when the profile sets no `baseURL`; the adapter may still send an individual model to that model\'s own endpoint. Absent when the route has no fixed endpoint.'),
31
+ 'baseURLEnv': z.array(z.string()).optional().describe('Environment variables used to construct a provider endpoint; absent when none are reported.'),
32
+ 'nativeAuth': z.object({
33
+ 'env': z.array(z.string()).describe('Environment variables the route\'s authentication reads, in lookup order; empty when it reads none.'),
34
+ 'oauth': z.boolean().describe('Whether a stored OAuth sign-in can authenticate the route.'),
35
+ }).optional().describe('Authentication the adapter performs when the profile names no credential reference; absent when it reports none.'),
36
+ 'error': z.string().optional().describe('Configuration diagnostic for repair; unaffected models may remain serviceable.'),
29
37
  })))
30
38
  let _qilin_agent_llm_llm_listProviders_result$schema$value
31
39
  const _qilin_agent_llm_llm_listProviders_result$schema = () => (_qilin_agent_llm_llm_listProviders_result$schema$value ??= z.array(z.object({
32
- 'id': z.string(),
33
- 'name': z.string(),
40
+ 'id': z.string().describe('Provider route key used by {@link GenerateOptions.provider}.'),
41
+ 'name': z.string().describe('Human-readable provider name for selectors and diagnostics.'),
34
42
  })))
43
+ let _qilin_agent_llm_llm_discoverModels_parameter_0_strict$schema$value
44
+ const _qilin_agent_llm_llm_discoverModels_parameter_0_strict$schema = () => (_qilin_agent_llm_llm_discoverModels_parameter_0_strict$schema$value ??= z.string())
45
+ let _qilin_agent_llm_llm_discoverModels_parameter_1_strict$schema$value
46
+ const _qilin_agent_llm_llm_discoverModels_parameter_1_strict$schema = () => (_qilin_agent_llm_llm_discoverModels_parameter_1_strict$schema$value ??= z.strictObject({
47
+ 'provider': z.string().optional().describe('Route the draft is editing, when it edits an existing one. A route whose adapter already knows its models answers from that knowledge instead of asking the endpoint — the adapter\'s own registry is the better answer, and it costs no network call.'),
48
+ 'baseURL': z.string().optional().describe('Endpoint to interrogate. Optional because a route the adapter already describes needs none; a route it does not must supply one.'),
49
+ 'api': z.string().optional().describe('Wire protocol the endpoint speaks, when the draft names one.'),
50
+ 'apiKey': z.string().optional().describe('Credential for this interrogation alone; the harness never stores it.'),
51
+ }))
35
52
 
36
- export const TYPERT = {
53
+ const $remote = createTypertRemoteInfo({
37
54
  package: '@qilin-agent/llm',
38
- face: 'host',
39
- schemas: [
40
- ],
41
- invocations: [
42
- {
43
- id: '@qilin-agent/llm#llm/discoverModels',
55
+ methods: {
56
+ 'llm/discoverModels': {
44
57
  service: 'llm',
45
- namespace: 'llm',
46
- method: 'discoverModels',
58
+ description: 'Remote adapter for one draft provider interrogation.',
47
59
  implementation: 'remoteDiscoverModels',
48
60
  invocation: { kind: 'direct' },
49
61
  parameters: [
50
62
  {
51
63
  name: 'settingsNs',
52
- wire: 'settingsNs',
64
+ description: 'namespace whose registered discovery serves this draft.',
53
65
  source: 'json',
54
66
  codec: {
55
67
  mode: 'strict',
56
68
  typeSymbol: '@qilin-agent/llm#llm/discoverModels:settingsNs',
57
69
  create: _qilin_agent_llm_llm_discoverModels_parameter_0$schema,
70
+ jsonSchema: {"type":"string"},
71
+ },
72
+ strictCodec: {
73
+ mode: 'strict',
74
+ typeSymbol: '@qilin-agent/llm#llm/discoverModels:settingsNs',
75
+ create: _qilin_agent_llm_llm_discoverModels_parameter_0_strict$schema,
76
+ jsonSchema: {"type":"string"},
58
77
  },
59
78
  },
60
79
  {
61
80
  name: 'request',
62
- wire: 'request',
81
+ description: 'endpoint, protocol, and one-shot credential to use.',
63
82
  source: 'json',
64
83
  codec: {
65
84
  mode: 'strict',
66
85
  typeSymbol: '@qilin-agent/llm/types#LlmModelDiscoveryRequest',
67
86
  create: _qilin_agent_llm_llm_discoverModels_parameter_1$schema,
87
+ jsonSchema: {"type":"object","properties":{"provider":{"type":"string","description":"Route the draft is editing, when it edits an existing one. A route whose adapter already knows its models answers from that knowledge instead of asking the endpoint — the adapter's own registry is the better answer, and it costs no network call."},"baseURL":{"type":"string","description":"Endpoint to interrogate. Optional because a route the adapter already describes needs none; a route it does not must supply one."},"api":{"type":"string","description":"Wire protocol the endpoint speaks, when the draft names one."},"apiKey":{"type":"string","description":"Credential for this interrogation alone; the harness never stores it."}},"required":[],"additionalProperties":true},
88
+ },
89
+ strictCodec: {
90
+ mode: 'strict',
91
+ typeSymbol: '@qilin-agent/llm/types#LlmModelDiscoveryRequest',
92
+ create: _qilin_agent_llm_llm_discoverModels_parameter_1_strict$schema,
93
+ jsonSchema: {"type":"object","properties":{"provider":{"type":"string","description":"Route the draft is editing, when it edits an existing one. A route whose adapter already knows its models answers from that knowledge instead of asking the endpoint — the adapter's own registry is the better answer, and it costs no network call."},"baseURL":{"type":"string","description":"Endpoint to interrogate. Optional because a route the adapter already describes needs none; a route it does not must supply one."},"api":{"type":"string","description":"Wire protocol the endpoint speaks, when the draft names one."},"apiKey":{"type":"string","description":"Credential for this interrogation alone; the harness never stores it."}},"required":[],"additionalProperties":false},
68
94
  },
69
95
  },
70
96
  ],
@@ -73,14 +99,14 @@ export const TYPERT = {
73
99
  mode: 'strict',
74
100
  typeSymbol: '@qilin-agent/llm#llm/discoverModels:result',
75
101
  create: _qilin_agent_llm_llm_discoverModels_result$schema,
102
+ description: 'advertised models in endpoint order.',
103
+ jsonSchema: {"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Model id the endpoint accepts."},"name":{"type":"string","description":"Human-readable name when the endpoint supplies one."},"contextWindow":{"type":"number","description":"Maximum combined request and response context, when disclosed."},"maxTokens":{"type":"number","description":"Maximum output tokens, when disclosed."},"inputModalities":{"type":"array","items":{"type":"string","enum":["text","image"]},"description":"Accepted input types when disclosed by the catalog or endpoint; absent means unknown."}},"required":["id"],"additionalProperties":true}},
76
104
  },
77
- sourceLocation: {"file":"packages/llm/llm/src/index.ts","line":638,"column":9},
105
+ sourceLocation: {"file":"packages/llm/llm/src/index.ts","line":660,"column":9},
78
106
  },
79
- {
80
- id: '@qilin-agent/llm#llm/listConfigurableProviders',
107
+ 'llm/listConfigurableProviders': {
81
108
  service: 'llm',
82
- namespace: 'llm',
83
- method: 'listConfigurableProviders',
109
+ description: 'List every declared configurable provider, registered or dormant.',
84
110
  invocation: { kind: 'direct' },
85
111
  parameters: [
86
112
  ],
@@ -88,14 +114,14 @@ export const TYPERT = {
88
114
  mode: 'strict',
89
115
  typeSymbol: '@qilin-agent/llm#llm/listConfigurableProviders:result',
90
116
  create: _qilin_agent_llm_llm_listConfigurableProviders_result$schema,
117
+ description: 'detached directory entries in declaration order.',
118
+ jsonSchema: {"type":"array","items":{"type":"object","properties":{"provider":{"type":"string","description":"Provider route key this entry activates when configured."},"displayName":{"type":"string","description":"Human-readable provider name for configuration surfaces."},"settingsNs":{"type":"string","description":"User-settings namespace whose section configures this provider."},"settingsPath":{"type":"array","items":{"type":"string"},"description":"Path from that namespace's section root to this provider's profile object; empty when the whole section is the profile."},"declared":{"type":"boolean","description":"Whether the owning adapter knows this route only because configuration declared it — a gateway or self-hosted server it ships nothing about. Absent means the adapter draws no such distinction; false means it does and this route is one of its own. Only the adapter can answer: a stored profile is how a user-added route AND a corrected shipped one both look from outside."},"defaultBaseURL":{"type":"string","description":"Route endpoint the adapter uses when the profile sets no `baseURL`; the adapter may still send an individual model to that model's own endpoint. Absent when the route has no fixed endpoint."},"baseURLEnv":{"type":"array","items":{"type":"string"},"description":"Environment variables used to construct a provider endpoint; absent when none are reported."},"nativeAuth":{"type":"object","properties":{"env":{"type":"array","items":{"type":"string"},"description":"Environment variables the route's authentication reads, in lookup order; empty when it reads none."},"oauth":{"type":"boolean","description":"Whether a stored OAuth sign-in can authenticate the route."}},"required":["env","oauth"],"additionalProperties":true,"description":"Authentication the adapter performs when the profile names no credential reference; absent when it reports none."},"error":{"type":"string","description":"Configuration diagnostic for repair; unaffected models may remain serviceable."}},"required":["provider","displayName","settingsNs","settingsPath"],"additionalProperties":true}},
91
119
  },
92
- sourceLocation: {"file":"packages/llm/llm/src/index.ts","line":550,"column":3},
120
+ sourceLocation: {"file":"packages/llm/llm/src/index.ts","line":567,"column":3},
93
121
  },
94
- {
95
- id: '@qilin-agent/llm#llm/listProviders',
122
+ 'llm/listProviders': {
96
123
  service: 'llm',
97
- namespace: 'llm',
98
- method: 'listProviders',
124
+ description: 'Describe provider routes with a registered adapter.',
99
125
  invocation: { kind: 'direct' },
100
126
  parameters: [
101
127
  ],
@@ -103,10 +129,20 @@ export const TYPERT = {
103
129
  mode: 'strict',
104
130
  typeSymbol: '@qilin-agent/llm#llm/listProviders:result',
105
131
  create: _qilin_agent_llm_llm_listProviders_result$schema,
132
+ description: 'detached provider metadata in registration order.',
133
+ jsonSchema: {"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Provider route key used by {@link GenerateOptions.provider}."},"name":{"type":"string","description":"Human-readable provider name for selectors and diagnostics."}},"required":["id","name"],"additionalProperties":true}},
106
134
  },
107
- sourceLocation: {"file":"packages/llm/llm/src/index.ts","line":478,"column":3},
135
+ sourceLocation: {"file":"packages/llm/llm/src/index.ts","line":490,"column":3},
108
136
  },
137
+ },
138
+ }, z)
139
+
140
+ export const TYPERT = {
141
+ package: '@qilin-agent/llm',
142
+ face: 'host',
143
+ schemas: [
109
144
  ],
145
+ get invocations() { return $remote.descriptors },
110
146
  model: {
111
147
  "services": [
112
148
  {
@@ -180,6 +216,13 @@ export const TYPERT = {
180
216
  "summary": "Resolve provider-side request-image pricing for one exact route, or `undefined` when the provider is unregistered or declares none.",
181
217
  "jsDoc": "/**\n * Resolve provider-side request-image pricing for one exact route, or\n * `undefined` when the provider is unregistered or declares none. Unknown\n * providers degrade to `undefined` rather than throwing because callers\n * price durable history whose route may no longer be mounted.\n * @param provider - provider route named by a request header.\n * @param model - exact model id named by the same header.\n * @returns the owning adapter's image pricing for the route, when declared.\n */"
182
218
  },
219
+ {
220
+ "kind": "method",
221
+ "name": "imageRequestTarget",
222
+ "signature": "imageRequestTarget(provider: string, model: string, image: ImageAttachmentRef): ImageRequestTarget",
223
+ "summary": "Resolve the image projection for an exact registered model route.",
224
+ "jsDoc": "/**\n * Resolve the image projection for an exact registered model route.\n * @param provider - registered provider route.\n * @param model - exact model id.\n * @param image - normalized image reference.\n * @returns dimensions and byte target used by the adapter's request serializer.\n */"
225
+ },
183
226
  {
184
227
  "kind": "method",
185
228
  "name": "fileRequestText",
@@ -332,9 +375,13 @@ export const TYPERT = {
332
375
  "name": "ImageMediaType",
333
376
  "declaration": "export type ImageMediaType = 'image/png' | 'image/jpeg' | 'image/webp' | 'image/gif';"
334
377
  },
378
+ {
379
+ "name": "ImageRequestTarget",
380
+ "declaration": "export interface ImageRequestTarget {\n width: number;\n height: number;\n maxBytes: number;\n}"
381
+ },
335
382
  {
336
383
  "name": "LlmAdapter",
337
- "declaration": "export abstract class LlmAdapter {\n providerInfo(provider: string): LlmProviderInfo;\n providerRetryPolicy(_provider: string): ResolvedRetryPolicy | undefined;\n imageRequestPricing(_provider: string, _model: string): LlmImageRequestPricing | undefined;\n listModels(_provider: string): Promise<readonly LlmModelInfo[]>;\n resolveModel(provider: string, model: string, _signal?: AbortSignal): Promise<LlmResolvedModelInfo>;\n prepareCall(provider: string, model: string, signal?: AbortSignal): Promise<PreparedAdapterCall>;\n abstract stream(options: GenerateOptions): AsyncIterable<StreamChunk>;\n}"
384
+ "declaration": "export abstract class LlmAdapter {\n providerInfo(provider: string): LlmProviderInfo;\n providerRetryPolicy(_provider: string): ResolvedRetryPolicy | undefined;\n imageRequestPricing(_provider: string, _model: string): LlmImageRequestPricing | undefined;\n imageRequestTarget(_provider: string, _model: string, image: ImageAttachmentRef): ImageRequestTarget;\n listModels(_provider: string): Promise<readonly LlmModelInfo[]>;\n resolveModel(provider: string, model: string, _signal?: AbortSignal): Promise<LlmResolvedModelInfo>;\n prepareCall(provider: string, model: string, signal?: AbortSignal): Promise<PreparedAdapterCall>;\n abstract stream(options: GenerateOptions): AsyncIterable<StreamChunk>;\n}"
338
385
  },
339
386
  {
340
387
  "name": "LlmCallConfig",
@@ -346,7 +393,7 @@ export const TYPERT = {
346
393
  },
347
394
  {
348
395
  "name": "LlmConfigurableProvider",
349
- "declaration": "export interface LlmConfigurableProvider {\n provider: string;\n displayName: string;\n settingsNs: string;\n settingsPath: readonly string[];\n declared?: boolean;\n error?: string;\n}"
396
+ "declaration": "export interface LlmConfigurableProvider {\n provider: string;\n displayName: string;\n settingsNs: string;\n settingsPath: readonly string[];\n declared?: boolean;\n defaultBaseURL?: string;\n baseURLEnv?: readonly string[];\n nativeAuth?: LlmNativeAuth;\n error?: string;\n}"
350
397
  },
351
398
  {
352
399
  "name": "LlmDiscoveredModel",
@@ -380,6 +427,10 @@ export const TYPERT = {
380
427
  "name": "LlmModelReasoningInfo",
381
428
  "declaration": "export interface LlmModelReasoningInfo {\n efforts: readonly LlmReasoningEffortInfo[];\n defaultEffort?: ReasoningEffortId;\n}"
382
429
  },
430
+ {
431
+ "name": "LlmNativeAuth",
432
+ "declaration": "export interface LlmNativeAuth {\n env: readonly string[];\n oauth: boolean;\n}"
433
+ },
383
434
  {
384
435
  "name": "LlmProviderInfo",
385
436
  "declaration": "export interface LlmProviderInfo {\n id: string;\n name: string;\n}"
@@ -414,7 +465,7 @@ export const TYPERT = {
414
465
  },
415
466
  {
416
467
  "name": "MessageSourceMap",
417
- "declaration": "export interface MessageSourceMap {\n user: { kind: 'user'; };\n model: ModelMessageSource;\n tool: ToolMessageSource;\n 'system-prompt': SystemPromptMessageSource;\n 'model-selection': { kind: 'model-selection'; } & ContextFormed;\n 'user-approval': { kind: 'user-approval'; } & ContextFormed;\n 'working-directory': { kind: 'working-directory'; };\n 'ptc-mode': { kind: 'ptc-mode'; };\n 'tool-registry': { kind: 'tool-registry'; };\n 'user-rpc': { kind: 'user'; rpcId: SessionRequestId; clientTimeZone?: string; };\n 'sidechat-boundary': { kind: 'sidechat-boundary'; };\n 'agent-message': AgentMessageSource;\n 'subagent-settled': SubagentSettledMessageSource;\n 'skill-invocation': SkillInvocationSource;\n 'team-message': TeamMessageSource;\n goal: GoalMessageSource;\n 'kylin-host-runner': { kind: 'kylin-host-runner'; };\n schedule: { kind: 'schedule'; } & ContextFormed;\n 'compact-checkpoint': CompactionCheckpointSource;\n 'session-reference': SessionReferenceSource;\n 'user-question-reply': { kind: 'user-question-reply'; callId: ToolCallId; outcome: 'answered'; };\n}"
468
+ "declaration": "export interface MessageSourceMap {\n user: { kind: 'user'; };\n model: ModelMessageSource;\n tool: ToolMessageSource;\n 'system-prompt': SystemPromptMessageSource;\n 'model-selection': { kind: 'model-selection'; } & ContextFormed;\n 'runtime-context': { kind: 'runtime-context'; } & ContextFormed;\n 'user-approval': { kind: 'user-approval'; } & ContextFormed;\n 'working-directory': { kind: 'working-directory'; };\n 'ptc-mode': { kind: 'ptc-mode'; };\n 'tool-registry': { kind: 'tool-registry'; };\n 'user-rpc': { kind: 'user'; rpcId: SessionRequestId; clientTimeZone?: string; principal?: Principal; };\n 'sidechat-boundary': { kind: 'sidechat-boundary'; };\n 'agent-message': AgentMessageSource;\n 'subagent-settled': SubagentSettledMessageSource;\n 'skill-invocation': SkillInvocationSource;\n 'compact-checkpoint': CompactionCheckpointSource;\n 'team-message': TeamMessageSource;\n 'user-question-reply': { kind: 'user-question-reply'; callId: ToolCallId; outcome: 'answered'; };\n webhook: { readonly kind: 'webhook'; readonly provider: string; readonly source: WebhookSourceId; readonly deliveryId: WebhookDeliveryId; readonly ruleId: WebhookRuleId; readonly form: 'notice'; readonly summary: string; };\n goal: GoalMessageSource;\n 'kylin-host-runner': { kind: 'kylin-host-runner'; };\n 'plan-mode': { kind: 'plan-mode'; } & ContextFormed;\n schedule: { kind: 'schedule'; } & ContextFormed;\n 'session-reference': SessionReferenceSource;\n}"
418
469
  },
419
470
  {
420
471
  "name": "ModelMessageSource",
@@ -440,6 +491,14 @@ export const TYPERT = {
440
491
  "name": "PreparedLlmCall",
441
492
  "declaration": "export interface PreparedLlmCall {\n readonly config: LlmCallConfig;\n readonly retryPolicy: ResolvedRetryPolicy;\n readonly context?: LlmModelContext;\n readonly inputModalities?: readonly ModelModality[];\n readonly systemPromptUpdate?: SystemPromptUpdate;\n readonly toolUpdate?: ToolUpdate;\n readonly adapterDefaults: LlmCallConfigAdapterDefaults;\n stream(options: GenerateOptions): AsyncIterable<StreamChunk>;\n}"
442
493
  },
494
+ {
495
+ "name": "Principal",
496
+ "declaration": "export type Principal = PrincipalMap[keyof PrincipalMap];"
497
+ },
498
+ {
499
+ "name": "PrincipalMap",
500
+ "declaration": "export interface PrincipalMap {\n owner: { readonly kind: 'owner'; };\n}"
501
+ },
443
502
  {
444
503
  "name": "ProviderRequestId",
445
504
  "declaration": "export type ProviderRequestId = Branded<'ProviderRequestId'>;"
@@ -579,6 +638,18 @@ export const TYPERT = {
579
638
  {
580
639
  "name": "UserMessage",
581
640
  "declaration": "export interface UserMessage extends MessageBase {\n readonly role: 'user';\n}"
641
+ },
642
+ {
643
+ "name": "WebhookDeliveryId",
644
+ "declaration": "export type WebhookDeliveryId = Branded<'WebhookDeliveryId'>;"
645
+ },
646
+ {
647
+ "name": "WebhookRuleId",
648
+ "declaration": "export type WebhookRuleId = Branded<'WebhookRuleId'>;"
649
+ },
650
+ {
651
+ "name": "WebhookSourceId",
652
+ "declaration": "export type WebhookSourceId = Branded<'WebhookSourceId'>;"
582
653
  }
583
654
  ]
584
655
  }
@@ -1,7 +1,8 @@
1
1
  /* Generated by @qilin-agent/typert-generator from the Host FaceModel — do not edit. */
2
2
  import type {
3
3
  RemoteResult,
4
- TypertRemoteContribution,
4
+ TypertRemoteInfo,
5
+ TypertRemoteMethod,
5
6
  } from '@qilin-agent/typert-protocol'
6
7
  import type { LlmConfigurableProvider, LlmDiscoveredModel, LlmModelDiscoveryRequest, LlmProviderInfo } from '@qilin-agent/llm/types'
7
8
 
@@ -21,6 +22,10 @@ declare module '@qilin-agent/typert-protocol' {
21
22
  }
22
23
  }
23
24
 
24
- export declare const TYPERT_REMOTE: TypertRemoteContribution
25
+ export declare const TYPERT_REMOTE: TypertRemoteInfo<{
26
+ readonly 'llm/discoverModels': TypertRemoteMethod<{ readonly 'settingsNs': string; readonly 'request': LlmModelDiscoveryRequest }, LlmDiscoveredModel[]>
27
+ readonly 'llm/listConfigurableProviders': TypertRemoteMethod<{ }, LlmConfigurableProvider[]>
28
+ readonly 'llm/listProviders': TypertRemoteMethod<{ }, LlmProviderInfo[]>
29
+ }>
25
30
  export default TYPERT_REMOTE
26
31
  //# sourceMappingURL=typert.remote-client.d.ts.map
@@ -1,67 +1,96 @@
1
1
  /* Generated by @qilin-agent/typert-generator from the Host FaceModel — do not edit. */
2
2
  import { z } from 'zod'
3
3
 
4
+ import { createTypertRemoteInfo } from '@qilin-agent/typert-protocol/remote-info'
5
+
4
6
  let _qilin_agent_llm_llm_discoverModels_parameter_0$schema$value
5
7
  const _qilin_agent_llm_llm_discoverModels_parameter_0$schema = () => (_qilin_agent_llm_llm_discoverModels_parameter_0$schema$value ??= z.string())
6
8
  let _qilin_agent_llm_llm_discoverModels_parameter_1$schema$value
7
9
  const _qilin_agent_llm_llm_discoverModels_parameter_1$schema = () => (_qilin_agent_llm_llm_discoverModels_parameter_1$schema$value ??= z.object({
8
- 'provider': z.string().optional(),
9
- 'baseURL': z.string().optional(),
10
- 'api': z.string().optional(),
11
- 'apiKey': z.string().optional(),
10
+ 'provider': z.string().optional().describe('Route the draft is editing, when it edits an existing one. A route whose adapter already knows its models answers from that knowledge instead of asking the endpoint — the adapter\'s own registry is the better answer, and it costs no network call.'),
11
+ 'baseURL': z.string().optional().describe('Endpoint to interrogate. Optional because a route the adapter already describes needs none; a route it does not must supply one.'),
12
+ 'api': z.string().optional().describe('Wire protocol the endpoint speaks, when the draft names one.'),
13
+ 'apiKey': z.string().optional().describe('Credential for this interrogation alone; the harness never stores it.'),
12
14
  }))
13
15
  let _qilin_agent_llm_llm_discoverModels_result$schema$value
14
16
  const _qilin_agent_llm_llm_discoverModels_result$schema = () => (_qilin_agent_llm_llm_discoverModels_result$schema$value ??= z.array(z.object({
15
- 'id': z.string(),
16
- 'name': z.string().optional(),
17
- 'contextWindow': z.number().optional(),
18
- 'maxTokens': z.number().optional(),
19
- 'inputModalities': z.array(z.union([z.literal("text"), z.literal("image")])).optional(),
17
+ 'id': z.string().describe('Model id the endpoint accepts.'),
18
+ 'name': z.string().optional().describe('Human-readable name when the endpoint supplies one.'),
19
+ 'contextWindow': z.number().optional().describe('Maximum combined request and response context, when disclosed.'),
20
+ 'maxTokens': z.number().optional().describe('Maximum output tokens, when disclosed.'),
21
+ 'inputModalities': z.array(z.union([z.literal("text"), z.literal("image")])).optional().describe('Accepted input types when disclosed by the catalog or endpoint; absent means unknown.'),
20
22
  })))
21
23
  let _qilin_agent_llm_llm_listConfigurableProviders_result$schema$value
22
24
  const _qilin_agent_llm_llm_listConfigurableProviders_result$schema = () => (_qilin_agent_llm_llm_listConfigurableProviders_result$schema$value ??= z.array(z.object({
23
- 'provider': z.string(),
24
- 'displayName': z.string(),
25
- 'settingsNs': z.string(),
26
- 'settingsPath': z.array(z.string()),
27
- 'declared': z.boolean().optional(),
28
- 'error': z.string().optional(),
25
+ 'provider': z.string().describe('Provider route key this entry activates when configured.'),
26
+ 'displayName': z.string().describe('Human-readable provider name for configuration surfaces.'),
27
+ 'settingsNs': z.string().describe('User-settings namespace whose section configures this provider.'),
28
+ 'settingsPath': z.array(z.string()).describe('Path from that namespace\'s section root to this provider\'s profile object; empty when the whole section is the profile.'),
29
+ 'declared': z.boolean().optional().describe('Whether the owning adapter knows this route only because configuration declared it — a gateway or self-hosted server it ships nothing about. Absent means the adapter draws no such distinction; false means it does and this route is one of its own. Only the adapter can answer: a stored profile is how a user-added route AND a corrected shipped one both look from outside.'),
30
+ 'defaultBaseURL': z.string().optional().describe('Route endpoint the adapter uses when the profile sets no `baseURL`; the adapter may still send an individual model to that model\'s own endpoint. Absent when the route has no fixed endpoint.'),
31
+ 'baseURLEnv': z.array(z.string()).optional().describe('Environment variables used to construct a provider endpoint; absent when none are reported.'),
32
+ 'nativeAuth': z.object({
33
+ 'env': z.array(z.string()).describe('Environment variables the route\'s authentication reads, in lookup order; empty when it reads none.'),
34
+ 'oauth': z.boolean().describe('Whether a stored OAuth sign-in can authenticate the route.'),
35
+ }).optional().describe('Authentication the adapter performs when the profile names no credential reference; absent when it reports none.'),
36
+ 'error': z.string().optional().describe('Configuration diagnostic for repair; unaffected models may remain serviceable.'),
29
37
  })))
30
38
  let _qilin_agent_llm_llm_listProviders_result$schema$value
31
39
  const _qilin_agent_llm_llm_listProviders_result$schema = () => (_qilin_agent_llm_llm_listProviders_result$schema$value ??= z.array(z.object({
32
- 'id': z.string(),
33
- 'name': z.string(),
40
+ 'id': z.string().describe('Provider route key used by {@link GenerateOptions.provider}.'),
41
+ 'name': z.string().describe('Human-readable provider name for selectors and diagnostics.'),
34
42
  })))
43
+ let _qilin_agent_llm_llm_discoverModels_parameter_0_strict$schema$value
44
+ const _qilin_agent_llm_llm_discoverModels_parameter_0_strict$schema = () => (_qilin_agent_llm_llm_discoverModels_parameter_0_strict$schema$value ??= z.string())
45
+ let _qilin_agent_llm_llm_discoverModels_parameter_1_strict$schema$value
46
+ const _qilin_agent_llm_llm_discoverModels_parameter_1_strict$schema = () => (_qilin_agent_llm_llm_discoverModels_parameter_1_strict$schema$value ??= z.strictObject({
47
+ 'provider': z.string().optional().describe('Route the draft is editing, when it edits an existing one. A route whose adapter already knows its models answers from that knowledge instead of asking the endpoint — the adapter\'s own registry is the better answer, and it costs no network call.'),
48
+ 'baseURL': z.string().optional().describe('Endpoint to interrogate. Optional because a route the adapter already describes needs none; a route it does not must supply one.'),
49
+ 'api': z.string().optional().describe('Wire protocol the endpoint speaks, when the draft names one.'),
50
+ 'apiKey': z.string().optional().describe('Credential for this interrogation alone; the harness never stores it.'),
51
+ }))
35
52
 
36
- export const TYPERT_REMOTE = {
53
+ export const TYPERT_REMOTE = createTypertRemoteInfo({
37
54
  package: '@qilin-agent/llm',
38
- descriptors: [
39
- {
40
- id: '@qilin-agent/llm#llm/discoverModels',
55
+ methods: {
56
+ 'llm/discoverModels': {
41
57
  service: 'llm',
42
- namespace: 'llm',
43
- method: 'discoverModels',
58
+ description: 'Remote adapter for one draft provider interrogation.',
44
59
  implementation: 'remoteDiscoverModels',
45
60
  invocation: { kind: 'direct' },
46
61
  parameters: [
47
62
  {
48
63
  name: 'settingsNs',
49
- wire: 'settingsNs',
64
+ description: 'namespace whose registered discovery serves this draft.',
50
65
  source: 'json',
51
66
  codec: {
52
67
  mode: 'strict',
53
68
  typeSymbol: '@qilin-agent/llm#llm/discoverModels:settingsNs',
54
69
  create: _qilin_agent_llm_llm_discoverModels_parameter_0$schema,
70
+ jsonSchema: {"type":"string"},
71
+ },
72
+ strictCodec: {
73
+ mode: 'strict',
74
+ typeSymbol: '@qilin-agent/llm#llm/discoverModels:settingsNs',
75
+ create: _qilin_agent_llm_llm_discoverModels_parameter_0_strict$schema,
76
+ jsonSchema: {"type":"string"},
55
77
  },
56
78
  },
57
79
  {
58
80
  name: 'request',
59
- wire: 'request',
81
+ description: 'endpoint, protocol, and one-shot credential to use.',
60
82
  source: 'json',
61
83
  codec: {
62
84
  mode: 'strict',
63
85
  typeSymbol: '@qilin-agent/llm/types#LlmModelDiscoveryRequest',
64
86
  create: _qilin_agent_llm_llm_discoverModels_parameter_1$schema,
87
+ jsonSchema: {"type":"object","properties":{"provider":{"type":"string","description":"Route the draft is editing, when it edits an existing one. A route whose adapter already knows its models answers from that knowledge instead of asking the endpoint — the adapter's own registry is the better answer, and it costs no network call."},"baseURL":{"type":"string","description":"Endpoint to interrogate. Optional because a route the adapter already describes needs none; a route it does not must supply one."},"api":{"type":"string","description":"Wire protocol the endpoint speaks, when the draft names one."},"apiKey":{"type":"string","description":"Credential for this interrogation alone; the harness never stores it."}},"required":[],"additionalProperties":true},
88
+ },
89
+ strictCodec: {
90
+ mode: 'strict',
91
+ typeSymbol: '@qilin-agent/llm/types#LlmModelDiscoveryRequest',
92
+ create: _qilin_agent_llm_llm_discoverModels_parameter_1_strict$schema,
93
+ jsonSchema: {"type":"object","properties":{"provider":{"type":"string","description":"Route the draft is editing, when it edits an existing one. A route whose adapter already knows its models answers from that knowledge instead of asking the endpoint — the adapter's own registry is the better answer, and it costs no network call."},"baseURL":{"type":"string","description":"Endpoint to interrogate. Optional because a route the adapter already describes needs none; a route it does not must supply one."},"api":{"type":"string","description":"Wire protocol the endpoint speaks, when the draft names one."},"apiKey":{"type":"string","description":"Credential for this interrogation alone; the harness never stores it."}},"required":[],"additionalProperties":false},
65
94
  },
66
95
  },
67
96
  ],
@@ -70,14 +99,14 @@ export const TYPERT_REMOTE = {
70
99
  mode: 'strict',
71
100
  typeSymbol: '@qilin-agent/llm#llm/discoverModels:result',
72
101
  create: _qilin_agent_llm_llm_discoverModels_result$schema,
102
+ description: 'advertised models in endpoint order.',
103
+ jsonSchema: {"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Model id the endpoint accepts."},"name":{"type":"string","description":"Human-readable name when the endpoint supplies one."},"contextWindow":{"type":"number","description":"Maximum combined request and response context, when disclosed."},"maxTokens":{"type":"number","description":"Maximum output tokens, when disclosed."},"inputModalities":{"type":"array","items":{"type":"string","enum":["text","image"]},"description":"Accepted input types when disclosed by the catalog or endpoint; absent means unknown."}},"required":["id"],"additionalProperties":true}},
73
104
  },
74
- sourceLocation: {"file":"packages/llm/llm/src/index.ts","line":638,"column":9},
105
+ sourceLocation: {"file":"packages/llm/llm/src/index.ts","line":660,"column":9},
75
106
  },
76
- {
77
- id: '@qilin-agent/llm#llm/listConfigurableProviders',
107
+ 'llm/listConfigurableProviders': {
78
108
  service: 'llm',
79
- namespace: 'llm',
80
- method: 'listConfigurableProviders',
109
+ description: 'List every declared configurable provider, registered or dormant.',
81
110
  invocation: { kind: 'direct' },
82
111
  parameters: [
83
112
  ],
@@ -85,14 +114,14 @@ export const TYPERT_REMOTE = {
85
114
  mode: 'strict',
86
115
  typeSymbol: '@qilin-agent/llm#llm/listConfigurableProviders:result',
87
116
  create: _qilin_agent_llm_llm_listConfigurableProviders_result$schema,
117
+ description: 'detached directory entries in declaration order.',
118
+ jsonSchema: {"type":"array","items":{"type":"object","properties":{"provider":{"type":"string","description":"Provider route key this entry activates when configured."},"displayName":{"type":"string","description":"Human-readable provider name for configuration surfaces."},"settingsNs":{"type":"string","description":"User-settings namespace whose section configures this provider."},"settingsPath":{"type":"array","items":{"type":"string"},"description":"Path from that namespace's section root to this provider's profile object; empty when the whole section is the profile."},"declared":{"type":"boolean","description":"Whether the owning adapter knows this route only because configuration declared it — a gateway or self-hosted server it ships nothing about. Absent means the adapter draws no such distinction; false means it does and this route is one of its own. Only the adapter can answer: a stored profile is how a user-added route AND a corrected shipped one both look from outside."},"defaultBaseURL":{"type":"string","description":"Route endpoint the adapter uses when the profile sets no `baseURL`; the adapter may still send an individual model to that model's own endpoint. Absent when the route has no fixed endpoint."},"baseURLEnv":{"type":"array","items":{"type":"string"},"description":"Environment variables used to construct a provider endpoint; absent when none are reported."},"nativeAuth":{"type":"object","properties":{"env":{"type":"array","items":{"type":"string"},"description":"Environment variables the route's authentication reads, in lookup order; empty when it reads none."},"oauth":{"type":"boolean","description":"Whether a stored OAuth sign-in can authenticate the route."}},"required":["env","oauth"],"additionalProperties":true,"description":"Authentication the adapter performs when the profile names no credential reference; absent when it reports none."},"error":{"type":"string","description":"Configuration diagnostic for repair; unaffected models may remain serviceable."}},"required":["provider","displayName","settingsNs","settingsPath"],"additionalProperties":true}},
88
119
  },
89
- sourceLocation: {"file":"packages/llm/llm/src/index.ts","line":550,"column":3},
120
+ sourceLocation: {"file":"packages/llm/llm/src/index.ts","line":567,"column":3},
90
121
  },
91
- {
92
- id: '@qilin-agent/llm#llm/listProviders',
122
+ 'llm/listProviders': {
93
123
  service: 'llm',
94
- namespace: 'llm',
95
- method: 'listProviders',
124
+ description: 'Describe provider routes with a registered adapter.',
96
125
  invocation: { kind: 'direct' },
97
126
  parameters: [
98
127
  ],
@@ -100,10 +129,12 @@ export const TYPERT_REMOTE = {
100
129
  mode: 'strict',
101
130
  typeSymbol: '@qilin-agent/llm#llm/listProviders:result',
102
131
  create: _qilin_agent_llm_llm_listProviders_result$schema,
132
+ description: 'detached provider metadata in registration order.',
133
+ jsonSchema: {"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Provider route key used by {@link GenerateOptions.provider}."},"name":{"type":"string","description":"Human-readable provider name for selectors and diagnostics."}},"required":["id","name"],"additionalProperties":true}},
103
134
  },
104
- sourceLocation: {"file":"packages/llm/llm/src/index.ts","line":478,"column":3},
135
+ sourceLocation: {"file":"packages/llm/llm/src/index.ts","line":490,"column":3},
105
136
  },
106
- ],
107
- }
137
+ },
138
+ }, z)
108
139
 
109
140
  export default TYPERT_REMOTE
@@ -12,7 +12,7 @@ import type { ResolvedRetryPolicy } from './retry-policy.ts';
12
12
  import type { ProviderRequestId } from './brand.ts';
13
13
  import type { LlmCallConfig, LlmCallConfigAdapterDefaults } from './call-config.ts';
14
14
  import { HarnessError } from './error.ts';
15
- import type { FileAttachmentRef } from '@qilin-agent/attachment';
15
+ import type { FileAttachmentRef, ImageAttachmentRef, ImageRequestTarget } from '@qilin-agent/attachment';
16
16
  export * from './attribution.ts';
17
17
  export * from './brand.ts';
18
18
  export * from './error.ts';
@@ -150,6 +150,15 @@ export declare abstract class LlmAdapter {
150
150
  * @returns route-owned image pricing, or `undefined` when the route declares none.
151
151
  */
152
152
  imageRequestPricing(_provider: string, _model: string): LlmImageRequestPricing | undefined;
153
+ /**
154
+ * Resolve the image dimensions and byte target this adapter sends to the model.
155
+ * The default preserves normalized images; adapters that resize must override it.
156
+ * @param _provider - registered provider route.
157
+ * @param _model - exact model id.
158
+ * @param image - normalized image whose request projection is being resolved.
159
+ * @returns the same target used by request serialization, before provider-internal processing.
160
+ */
161
+ imageRequestTarget(_provider: string, _model: string, image: ImageAttachmentRef): ImageRequestTarget;
153
162
  /**
154
163
  * List models this adapter can currently advertise for one owned provider.
155
164
  * Core routing accepts unlisted model ids; catalog-driven entry points such
@@ -331,6 +340,14 @@ export declare class LlmRuntime extends TypertRemoteService {
331
340
  * @returns the owning adapter's image pricing for the route, when declared.
332
341
  */
333
342
  imageRequestPricing(provider: string, model: string): LlmImageRequestPricing | undefined;
343
+ /**
344
+ * Resolve the image projection for an exact registered model route.
345
+ * @param provider - registered provider route.
346
+ * @param model - exact model id.
347
+ * @param image - normalized image reference.
348
+ * @returns dimensions and byte target used by the adapter's request serializer.
349
+ */
350
+ imageRequestTarget(provider: string, model: string, image: ImageAttachmentRef): ImageRequestTarget;
334
351
  /**
335
352
  * Resolve the exact text one durable file occurrence contributes to every
336
353
  * provider request in the current execution environment.
@@ -167,6 +167,17 @@ export class LlmAdapter {
167
167
  imageRequestPricing(_provider, _model) {
168
168
  return undefined;
169
169
  }
170
+ /**
171
+ * Resolve the image dimensions and byte target this adapter sends to the model.
172
+ * The default preserves normalized images; adapters that resize must override it.
173
+ * @param _provider - registered provider route.
174
+ * @param _model - exact model id.
175
+ * @param image - normalized image whose request projection is being resolved.
176
+ * @returns the same target used by request serialization, before provider-internal processing.
177
+ */
178
+ imageRequestTarget(_provider, _model, image) {
179
+ return { width: image.width, height: image.height, maxBytes: image.bytes };
180
+ }
170
181
  /**
171
182
  * List models this adapter can currently advertise for one owned provider.
172
183
  * Core routing accepts unlisted model ids; catalog-driven entry points such
@@ -392,7 +403,12 @@ let LlmRuntime = (() => {
392
403
  || detached.some(seen => seen.provider === entry.provider)) {
393
404
  throw new LlmError(`configurable provider "${entry.provider}" is already declared`, 'DUPLICATE_DIRECTORY');
394
405
  }
395
- detached.push({ ...entry, settingsPath: [...entry.settingsPath] });
406
+ detached.push({
407
+ ...entry,
408
+ settingsPath: [...entry.settingsPath],
409
+ ...entry.baseURLEnv === undefined ? {} : { baseURLEnv: [...entry.baseURLEnv] },
410
+ ...(entry.nativeAuth === undefined ? {} : { nativeAuth: { ...entry.nativeAuth, env: [...entry.nativeAuth.env] } }),
411
+ });
396
412
  }
397
413
  for (const entry of held)
398
414
  this.directory.delete(entry.provider);
@@ -428,7 +444,12 @@ let LlmRuntime = (() => {
428
444
  * @returns detached directory entries in declaration order.
429
445
  */
430
446
  listConfigurableProviders() {
431
- return [...this.directory.values()].map(entry => ({ ...entry, settingsPath: [...entry.settingsPath] }));
447
+ return [...this.directory.values()].map(entry => ({
448
+ ...entry,
449
+ settingsPath: [...entry.settingsPath],
450
+ ...entry.baseURLEnv === undefined ? {} : { baseURLEnv: [...entry.baseURLEnv] },
451
+ ...(entry.nativeAuth === undefined ? {} : { nativeAuth: { ...entry.nativeAuth, env: [...entry.nativeAuth.env] } }),
452
+ }));
432
453
  }
433
454
  /**
434
455
  * Offer to interrogate provider endpoints on behalf of the settings
@@ -533,6 +554,16 @@ let LlmRuntime = (() => {
533
554
  imageRequestPricing(provider, model) {
534
555
  return this.adapters.get(provider)?.adapter.imageRequestPricing(provider, model);
535
556
  }
557
+ /**
558
+ * Resolve the image projection for an exact registered model route.
559
+ * @param provider - registered provider route.
560
+ * @param model - exact model id.
561
+ * @param image - normalized image reference.
562
+ * @returns dimensions and byte target used by the adapter's request serializer.
563
+ */
564
+ imageRequestTarget(provider, model, image) {
565
+ return this.registration(provider).adapter.imageRequestTarget(provider, model, image);
566
+ }
536
567
  /**
537
568
  * Resolve the exact text one durable file occurrence contributes to every
538
569
  * provider request in the current execution environment.
@@ -242,9 +242,26 @@ export interface LlmConfigurableProvider {
242
242
  * from outside.
243
243
  */
244
244
  declared?: boolean;
245
+ /**
246
+ * Route endpoint the adapter uses when the profile sets no `baseURL`; the
247
+ * adapter may still send an individual model to that model's own endpoint.
248
+ * Absent when the route has no fixed endpoint.
249
+ */
250
+ defaultBaseURL?: string;
251
+ /** Environment variables used to construct a provider endpoint; absent when none are reported. */
252
+ baseURLEnv?: readonly string[];
253
+ /** Authentication the adapter performs when the profile names no credential reference; absent when it reports none. */
254
+ nativeAuth?: LlmNativeAuth;
245
255
  /** Configuration diagnostic for repair; unaffected models may remain serviceable. */
246
256
  error?: string;
247
257
  }
258
+ /** Authentication a provider route performs without a credential reference in its profile. */
259
+ export interface LlmNativeAuth {
260
+ /** Environment variables the route's authentication reads, in lookup order; empty when it reads none. */
261
+ env: readonly string[];
262
+ /** Whether a stored OAuth sign-in can authenticate the route. */
263
+ oauth: boolean;
264
+ }
248
265
  /**
249
266
  * One interrogation of a provider endpoint that configuration has not stored
250
267
  * yet. Configuration surfaces send the draft a user is still editing, so the
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@qilin-agent/llm",
3
3
  "description": "Provider-neutral LLM service interface for the QiLin",
4
- "version": "3.1.4",
4
+ "version": "3.1.6",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -59,19 +59,19 @@
59
59
  ],
60
60
  "license": "MIT",
61
61
  "peerDependencies": {
62
- "@qilin-agent/kylin": "~4.0.3"
62
+ "@qilin-agent/kylin": "~4.0.5"
63
63
  },
64
64
  "dependencies": {
65
65
  "zod": "^4.4.3",
66
- "@qilin-agent/util-crypto": "3.1.4",
67
- "@qilin-agent/util-values": "3.1.4",
68
- "@qilin-agent/schemastery": "~3.18.3",
69
- "@qilin-agent/brand": "3.1.4",
70
- "@qilin-agent/typert-protocol": "3.1.4",
71
- "@qilin-agent/timeout": "3.1.4"
66
+ "@qilin-agent/timeout": "3.1.6",
67
+ "@qilin-agent/schemastery": "~3.18.5",
68
+ "@qilin-agent/brand": "3.1.6",
69
+ "@qilin-agent/typert-protocol": "3.1.6",
70
+ "@qilin-agent/util-crypto": "3.1.6",
71
+ "@qilin-agent/util-values": "3.1.6"
72
72
  },
73
73
  "devDependencies": {
74
- "@qilin-agent/attachment": "3.1.4",
75
- "@qilin-agent/kylin": "~4.0.3"
74
+ "@qilin-agent/attachment": "3.1.6",
75
+ "@qilin-agent/kylin": "~4.0.5"
76
76
  }
77
77
  }