@zhin.js/runtime 1.0.17 → 1.0.19

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.
@@ -23,6 +23,8 @@ export declare class ConfigValidationError extends Error {
23
23
  source?: string | undefined);
24
24
  }
25
25
  export declare class ConfigComposer {
26
+ private readonly inactivePluginInstanceKeys;
27
+ constructor(inactivePluginInstanceKeys?: readonly string[]);
26
28
  compose(graph: ProjectGraph, input?: RuntimeConfigDocument,
27
29
  /** Source config file name, annotated on ConfigValidationError. */
28
30
  source?: string): Promise<ComposedConfig>;
@@ -36,6 +36,10 @@ export class ConfigValidationError extends Error {
36
36
  }
37
37
  }
38
38
  export class ConfigComposer {
39
+ inactivePluginInstanceKeys;
40
+ constructor(inactivePluginInstanceKeys = []) {
41
+ this.inactivePluginInstanceKeys = inactivePluginInstanceKeys;
42
+ }
39
43
  async compose(graph, input = {},
40
44
  /** Source config file name, annotated on ConfigValidationError. */
41
45
  source) {
@@ -61,7 +65,10 @@ export class ConfigComposer {
61
65
  type: 'object',
62
66
  additionalProperties: false,
63
67
  default: {},
64
- properties: Object.fromEntries(childSchemas.map(([key, schema]) => [key, withDefault(schema)])),
68
+ properties: Object.fromEntries([
69
+ ...this.inactivePluginInstanceKeys.map((key) => [key, {}]),
70
+ ...childSchemas.map(([key, schema]) => [key, withDefault(schema)]),
71
+ ]),
65
72
  },
66
73
  },
67
74
  });
@@ -3,7 +3,42 @@
3
3
  "type": "object",
4
4
  "additionalProperties": false,
5
5
  "properties": {
6
- "http": { "type": "object", "additionalProperties": true, "description": "HTTP, Console, REST/RPC/SSE, and Webhook Host.", "x-descriptionZh": "HTTP、Console、REST/RPC/SSE 与 Webhook Host。" },
6
+ "http": {
7
+ "type": "object", "additionalProperties": true,
8
+ "description": "HTTP, Console, REST/RPC/SSE, and Webhook Host.",
9
+ "x-descriptionZh": "HTTP、Console、REST/RPC/SSE 与 Webhook Host。",
10
+ "properties": {
11
+ "readiness": {
12
+ "type": "object", "additionalProperties": false,
13
+ "description": "Required runtime components for /pub/ready; no external network probes.",
14
+ "x-descriptionZh": "/pub/ready 要求就绪的运行时组件;不执行外部网络探测。",
15
+ "properties": {
16
+ "database": {
17
+ "type": "boolean", "default": true,
18
+ "description": "Require an initialized Database Host (not a live database query).",
19
+ "x-descriptionZh": "要求 Database Host 已初始化(不执行实时数据库查询)。"
20
+ },
21
+ "endpoints": {
22
+ "type": "array", "uniqueItems": true,
23
+ "description": "Required Endpoint admission slots, selected by exact plugin owner and stable slot name.",
24
+ "x-descriptionZh": "必须开放入站的 Endpoint,按插件 owner 与稳定槽名精确选择。",
25
+ "items": {
26
+ "type": "object", "additionalProperties": false, "required": ["owner", "name"],
27
+ "properties": {
28
+ "owner": { "type": "string", "pattern": "^root(?:/[a-z0-9][a-z0-9-]*)*$" },
29
+ "name": { "type": "string", "minLength": 1, "pattern": "^[^\\u0000]+$" }
30
+ }
31
+ }
32
+ },
33
+ "agents": {
34
+ "type": "array", "uniqueItems": true, "items": { "type": "string", "minLength": 1 },
35
+ "description": "Required configured Agent bindings; does not verify model credentials or provider reachability.",
36
+ "x-descriptionZh": "必须存在的 Agent binding;不验证模型凭据或 Provider 网络可用性。"
37
+ }
38
+ }
39
+ }
40
+ }
41
+ },
7
42
  "database": { "type": "object", "additionalProperties": true, "description": "Database Host and dialect connection options.", "x-descriptionZh": "Database Host 与方言连接参数。" },
8
43
  "ai": {
9
44
  "type": "object",
@@ -160,7 +195,72 @@
160
195
  "mcp": { "type": "object", "additionalProperties": true, "description": "Expose Bot tools through an MCP Server.", "x-descriptionZh": "把 Bot 工具公开为 MCP Server。" },
161
196
  "a2a": { "type": "object", "additionalProperties": true, "description": "A2A Agent Card, remote execution, and Workroom callbacks.", "x-descriptionZh": "A2A Agent Card、远程执行与 Workroom 回调。" },
162
197
  "speech": { "type": "object", "additionalProperties": true, "description": "Speech-to-text and text-to-speech Host.", "x-descriptionZh": "语音识别与语音合成 Host。" },
163
- "htmlRenderer": { "type": "object", "additionalProperties": true, "description": "HTML and image rendering options.", "x-descriptionZh": "HTML/图片渲染参数。" },
198
+ "htmlRenderer": {
199
+ "type": "object",
200
+ "additionalProperties": true,
201
+ "description": "HTML and image rendering options backed by Shotium.",
202
+ "x-descriptionZh": "基于 Shotium 的 HTML/图片渲染参数。",
203
+ "properties": {
204
+ "width": { "type": "number", "minimum": 1, "maximum": 30000, "description": "Default layout width in CSS pixels.", "x-descriptionZh": "默认排版宽度(CSS 像素)。" },
205
+ "defaultWidth": { "type": "number", "minimum": 1, "maximum": 30000, "description": "Legacy alias of width.", "x-descriptionZh": "width 的旧别名。" },
206
+ "viewport": {
207
+ "type": "object",
208
+ "additionalProperties": true,
209
+ "description": "Default viewport for Shotium rendering.",
210
+ "x-descriptionZh": "Shotium 渲染默认视窗。",
211
+ "properties": {
212
+ "width": { "type": "number", "minimum": 1, "maximum": 30000, "description": "Viewport width in CSS pixels.", "x-descriptionZh": "视窗宽度(CSS 像素)。" },
213
+ "height": { "type": "number", "minimum": 1, "maximum": 30000, "description": "Viewport height in CSS pixels.", "x-descriptionZh": "视窗高度(CSS 像素)。" }
214
+ }
215
+ },
216
+ "backgroundColor": { "type": "string", "description": "Fragment background color.", "x-descriptionZh": "HTML 片段背景色。" },
217
+ "defaultBackgroundColor": { "type": "string", "description": "Legacy alias of backgroundColor.", "x-descriptionZh": "backgroundColor 的旧别名。" },
218
+ "scale": { "type": "number", "minimum": 0.01, "maximum": 8, "description": "Device scale factor.", "x-descriptionZh": "设备像素比。" },
219
+ "type": { "type": "string", "enum": ["png", "jpeg", "webp"], "description": "Default raster output format.", "x-descriptionZh": "默认位图输出格式。" },
220
+ "quality": { "type": "number", "minimum": 1, "maximum": 100, "description": "Quality for jpeg/webp output.", "x-descriptionZh": "jpeg/webp 输出质量。" },
221
+ "timeout": { "type": "number", "minimum": 1, "maximum": 600000, "description": "Navigation timeout in milliseconds.", "x-descriptionZh": "导航超时(毫秒)。" },
222
+ "waitUntil": { "type": "string", "enum": ["load", "networkidle"], "description": "Navigation wait strategy.", "x-descriptionZh": "导航等待策略。" },
223
+ "fontFamily": { "type": "string", "description": "Default font-family for fragments.", "x-descriptionZh": "HTML 片段默认字体栈。" },
224
+ "maxImageHeight": { "type": "number", "minimum": 0, "maximum": 100000, "description": "Split overly tall PNGs above this height; 0 disables splitting.", "x-descriptionZh": "超过该高度时切分 PNG;0 表示不切分。" },
225
+ "sliceCompression": { "type": "number", "minimum": 0, "maximum": 9, "description": "Compression level used when splitting PNGs.", "x-descriptionZh": "PNG 切片时使用的压缩级别。" },
226
+ "allowFileAccess": { "type": "boolean", "description": "Allow local file subresources.", "x-descriptionZh": "允许访问本地文件子资源。" },
227
+ "takeOverHtmlSegments": { "type": "boolean", "description": "Take over html/markdown rich-segment image rendering.", "x-descriptionZh": "接管 html/markdown 富媒体段转图。" },
228
+ "cacheDir": { "type": "string", "description": "HTTP cache directory; use off to disable.", "x-descriptionZh": "HTTP 缓存目录;off 表示关闭。" },
229
+ "cacheMaxBytes": { "type": "number", "minimum": 0, "description": "Maximum HTTP cache size in bytes.", "x-descriptionZh": "HTTP 缓存最大字节数。" },
230
+ "userAgent": { "type": "string", "description": "Custom user agent string.", "x-descriptionZh": "自定义 User-Agent。" },
231
+ "idleTimeoutMs": { "type": "number", "minimum": 0, "maximum": 86400000, "description": "Daemon idle-exit timeout in milliseconds.", "x-descriptionZh": "daemon 空闲退出超时(毫秒)。" },
232
+ "logStats": { "type": "boolean", "description": "Log render timing statistics.", "x-descriptionZh": "记录渲染耗时统计。" },
233
+ "mode": { "type": "string", "enum": ["inprocess", "daemon"], "description": "Whether Shotium runs in-process or as a daemon.", "x-descriptionZh": "Shotium 在进程内运行还是以 daemon 运行。" },
234
+ "aiTextAsImage": {
235
+ "anyOf": [
236
+ { "type": "boolean" },
237
+ {
238
+ "type": "object",
239
+ "additionalProperties": true,
240
+ "description": "Convert plain text output to an image before send.",
241
+ "x-descriptionZh": "发送前将纯文本输出转成图片。",
242
+ "properties": {
243
+ "enabled": { "type": "boolean", "description": "Enable text-to-image conversion.", "x-descriptionZh": "启用文本转图片。" },
244
+ "onlyAdapters": { "type": "array", "items": { "type": "string", "minLength": 1 }, "uniqueItems": true, "description": "Only apply to these adapter names.", "x-descriptionZh": "仅对这些适配器名称生效。" },
245
+ "minLength": { "type": "number", "minimum": 1, "description": "Minimum plain-text length to trigger conversion; defaults to 1 at runtime.", "x-descriptionZh": "触发转换的最小纯文本长度;运行时默认为 1。" },
246
+ "maxLength": { "type": "number", "minimum": 1, "description": "Maximum plain-text length to convert; defaults to 12000 at runtime.", "x-descriptionZh": "允许转换的最大纯文本长度;运行时默认为 12000。" },
247
+ "skipIfRich": { "type": "boolean", "description": "Skip when content already contains rich segments; defaults to true at runtime.", "x-descriptionZh": "内容已包含富媒体段时跳过;运行时默认为 true。" },
248
+ "width": { "type": "number", "minimum": 1, "maximum": 30000, "description": "Image width in CSS pixels.", "x-descriptionZh": "图片宽度(CSS 像素)。" },
249
+ "height": { "type": "number", "minimum": 1, "maximum": 30000, "description": "Image height in CSS pixels.", "x-descriptionZh": "图片高度(CSS 像素)。" },
250
+ "backgroundColor": { "type": "string", "description": "Image background color.", "x-descriptionZh": "图片背景色。" },
251
+ "fontSize": { "type": "number", "minimum": 1, "description": "Font size in CSS pixels.", "x-descriptionZh": "字体大小(CSS 像素)。" },
252
+ "color": { "type": "string", "description": "Text color.", "x-descriptionZh": "文字颜色。" },
253
+ "padding": { "type": "number", "minimum": 0, "description": "Image padding in CSS pixels.", "x-descriptionZh": "图片内边距(CSS 像素)。" },
254
+ "scale": { "type": "number", "minimum": 0.01, "maximum": 8, "description": "Device scale factor.", "x-descriptionZh": "设备像素比。" },
255
+ "fileName": { "type": "string", "minLength": 1, "description": "Image file name.", "x-descriptionZh": "图片文件名。" }
256
+ }
257
+ }
258
+ ],
259
+ "description": "Optional plain-text to image conversion before send.",
260
+ "x-descriptionZh": "发送前可选的纯文本转图片。"
261
+ }
262
+ }
263
+ },
164
264
  "assistant": { "type": "object", "additionalProperties": true, "description": "Scheduled jobs, event ingress, and failure notifications.", "x-descriptionZh": "调度任务、事件入口和失败通知。" },
165
265
  "log_level": { "type": ["string", "number"], "description": "Runtime log level.", "x-descriptionZh": "Runtime 日志级别。" },
166
266
  "plugin": { "type": "object", "description": "Root Plugin configuration; replaced by its project schema during composition.", "x-descriptionZh": "Root Plugin 配置;组合时由项目 Schema 替换。" }
@@ -20,6 +20,7 @@ export interface ProjectGraph {
20
20
  }
21
21
  export interface ProjectGraphServiceOptions {
22
22
  readonly engineVersion?: string;
23
+ readonly disabledPluginInstanceKeys?: readonly string[];
23
24
  }
24
25
  export declare class ProjectGraphError extends Error {
25
26
  constructor(message: string);
@@ -11,11 +11,15 @@ export class ProjectGraphError extends Error {
11
11
  export class ProjectGraphService {
12
12
  #resolver;
13
13
  #engineVersion;
14
+ #disabledPluginInstanceKeys;
14
15
  constructor(resolver, engineVersionOrOptions = runtimeEngineVersion) {
15
16
  this.#resolver = resolver;
16
17
  this.#engineVersion = typeof engineVersionOrOptions === 'string'
17
18
  ? engineVersionOrOptions
18
19
  : (engineVersionOrOptions.engineVersion ?? runtimeEngineVersion);
20
+ this.#disabledPluginInstanceKeys = new Set(typeof engineVersionOrOptions === 'string'
21
+ ? []
22
+ : (engineVersionOrOptions.disabledPluginInstanceKeys ?? []));
19
23
  }
20
24
  async inspect(projectRoot) {
21
25
  const rootPackage = await this.#resolver.root(projectRoot);
@@ -58,6 +62,9 @@ export class ProjectGraphService {
58
62
  pluginRefs = mergeChildPluginReferences(manifest.plugins, inheritedPlugins);
59
63
  }
60
64
  }
65
+ if (isRoot && this.#disabledPluginInstanceKeys.size > 0) {
66
+ pluginRefs = pluginRefs.filter((reference) => !this.#disabledPluginInstanceKeys.has(reference.instanceKey));
67
+ }
61
68
  const featurePackages = new Set();
62
69
  const features = await Promise.all(featureRefs.map(async (reference) => {
63
70
  if (featurePackages.has(reference.package)) {
@@ -21,6 +21,7 @@ export interface RootRuntimeOptions {
21
21
  readonly installResources?: RootResourceInstaller;
22
22
  readonly isolation?: IsolatedPluginRuntimePort;
23
23
  readonly onControlError?: ControlErrorHandler;
24
+ readonly disabledPluginInstanceKeys?: readonly string[];
24
25
  }
25
26
  export type RootHmrOptions = Omit<HmrCoordinatorOptions, 'modules' | 'ownership' | 'runtime'>;
26
27
  export declare class RootRuntime {
@@ -37,6 +37,7 @@ export class RootRuntime {
37
37
  #configPatchTail = Promise.resolve();
38
38
  #stopResult;
39
39
  #controller;
40
+ #disabledPluginInstanceKeys;
40
41
  constructor(options) {
41
42
  this.#projectRoot = resolve(options.projectRoot);
42
43
  this.#modules = options.modules;
@@ -50,6 +51,7 @@ export class RootRuntime {
50
51
  this.#configDocument = structuredClone(options.config ?? {});
51
52
  this.#installResources = options.installResources;
52
53
  this.#isolation = options.isolation;
54
+ this.#disabledPluginInstanceKeys = Object.freeze([...(options.disabledPluginInstanceKeys ?? [])]);
53
55
  this.#controller = new RootController(emptyState(), options.onControlError, Object.freeze({ ownership: SourceOwnershipIndex.empty() }));
54
56
  }
55
57
  get snapshot() {
@@ -187,7 +189,9 @@ export class RootRuntime {
187
189
  }
188
190
  async #inspectProject() {
189
191
  const resolver = await NodePackageResolver.create(this.#projectRoot);
190
- const graph = await new ProjectGraphService(resolver).inspect(this.#projectRoot);
192
+ const graph = await new ProjectGraphService(resolver, {
193
+ disabledPluginInstanceKeys: this.#disabledPluginInstanceKeys,
194
+ }).inspect(this.#projectRoot);
191
195
  await this.#refreshConfigDocument();
192
196
  if (this.#configResolver) {
193
197
  return {
@@ -196,7 +200,8 @@ export class RootRuntime {
196
200
  primaryConfigDocument: Object.freeze({}),
197
201
  };
198
202
  }
199
- const composed = await new ConfigComposer().compose(graph, this.#configDocument);
203
+ const composed = await new ConfigComposer(this.#disabledPluginInstanceKeys)
204
+ .compose(graph, this.#configDocument);
200
205
  return {
201
206
  graph,
202
207
  configResolver: this.#configViewResolver(composed.views),
@@ -243,8 +248,10 @@ export class RootRuntime {
243
248
  let prepared;
244
249
  signal.throwIfAborted();
245
250
  const resolver = await NodePackageResolver.create(this.#projectRoot);
246
- const graph = await new ProjectGraphService(resolver).inspect(this.#projectRoot);
247
- const planned = await new ConfigPatchPlanner().plan(graph, currentDocument, patches);
251
+ const graph = await new ProjectGraphService(resolver, {
252
+ disabledPluginInstanceKeys: this.#disabledPluginInstanceKeys,
253
+ }).inspect(this.#projectRoot);
254
+ const planned = await new ConfigPatchPlanner(new ConfigComposer(this.#disabledPluginInstanceKeys)).plan(graph, currentDocument, patches);
248
255
  plan = planned;
249
256
  if (!planned.documentChanged)
250
257
  return undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/runtime",
3
- "version": "1.0.17",
3
+ "version": "1.0.19",
4
4
  "description": "Static Plugin graph, generation transaction and HMR Root runtime for Zhin.js",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -24,9 +24,9 @@
24
24
  "devDependencies": {
25
25
  "@types/node": "^26.1.2",
26
26
  "typescript": "^6.0.3",
27
- "@zhin.js/adapter": "1.2.1",
28
- "@zhin.js/command": "1.0.16",
27
+ "@zhin.js/adapter": "1.2.2",
29
28
  "@zhin.js/agent-feature": "1.0.13",
29
+ "@zhin.js/command": "1.0.16",
30
30
  "@zhin.js/component": "1.0.13",
31
31
  "@zhin.js/layout": "1.0.13",
32
32
  "@zhin.js/mcp-feature": "1.0.13",