@zhin.js/runtime 1.1.3 → 1.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/config-composer.d.ts +633 -2
- package/lib/config-composer.js +2 -1
- package/lib/hmr-coordinator.js +23 -5
- package/lib/host-config-schema.json +30 -0
- package/lib/invalidation-planner.js +5 -4
- package/lib/module-dependency-index.js +8 -7
- package/lib/native-development-runtime.js +5 -4
- package/lib/plugin-scope-assembler.d.ts +4 -1
- package/lib/plugin-scope-assembler.js +12 -0
- package/lib/root-runtime.js +11 -9
- package/lib/source-ownership.js +3 -2
- package/lib/source-path.d.ts +4 -0
- package/lib/source-path.js +25 -0
- package/lib/subtree-generation-preparer.js +1 -0
- package/lib/topology-generation-preparer.js +1 -0
- package/package.json +14 -14
package/lib/config-composer.d.ts
CHANGED
|
@@ -1,6 +1,637 @@
|
|
|
1
|
-
import type { RuntimeConfigDocument } from '@zhin.js/plugin-runtime';
|
|
2
|
-
import type { PluginId } from '@zhin.js/plugin-runtime';
|
|
1
|
+
import type { RuntimeConfigDocument, PluginId } from '@zhin.js/plugin-runtime';
|
|
3
2
|
import type { ProjectGraph } from './project-graph.js';
|
|
3
|
+
export declare const HOST_CONFIG_SCHEMA: {
|
|
4
|
+
$schema: string;
|
|
5
|
+
type: string;
|
|
6
|
+
additionalProperties: boolean;
|
|
7
|
+
properties: {
|
|
8
|
+
http: {
|
|
9
|
+
type: string;
|
|
10
|
+
additionalProperties: boolean;
|
|
11
|
+
description: string;
|
|
12
|
+
"x-descriptionZh": string;
|
|
13
|
+
properties: {
|
|
14
|
+
readiness: {
|
|
15
|
+
type: string;
|
|
16
|
+
additionalProperties: boolean;
|
|
17
|
+
description: string;
|
|
18
|
+
"x-descriptionZh": string;
|
|
19
|
+
properties: {
|
|
20
|
+
database: {
|
|
21
|
+
type: string;
|
|
22
|
+
default: boolean;
|
|
23
|
+
description: string;
|
|
24
|
+
"x-descriptionZh": string;
|
|
25
|
+
};
|
|
26
|
+
endpoints: {
|
|
27
|
+
type: string;
|
|
28
|
+
uniqueItems: boolean;
|
|
29
|
+
description: string;
|
|
30
|
+
"x-descriptionZh": string;
|
|
31
|
+
items: {
|
|
32
|
+
type: string;
|
|
33
|
+
additionalProperties: boolean;
|
|
34
|
+
required: string[];
|
|
35
|
+
properties: {
|
|
36
|
+
owner: {
|
|
37
|
+
type: string;
|
|
38
|
+
pattern: string;
|
|
39
|
+
};
|
|
40
|
+
name: {
|
|
41
|
+
type: string;
|
|
42
|
+
minLength: number;
|
|
43
|
+
pattern: string;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
agents: {
|
|
49
|
+
type: string;
|
|
50
|
+
uniqueItems: boolean;
|
|
51
|
+
items: {
|
|
52
|
+
type: string;
|
|
53
|
+
minLength: number;
|
|
54
|
+
};
|
|
55
|
+
description: string;
|
|
56
|
+
"x-descriptionZh": string;
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
database: {
|
|
63
|
+
type: string;
|
|
64
|
+
additionalProperties: boolean;
|
|
65
|
+
description: string;
|
|
66
|
+
"x-descriptionZh": string;
|
|
67
|
+
};
|
|
68
|
+
ai: {
|
|
69
|
+
type: string;
|
|
70
|
+
additionalProperties: boolean;
|
|
71
|
+
description: string;
|
|
72
|
+
"x-descriptionZh": string;
|
|
73
|
+
properties: {
|
|
74
|
+
decisions: {
|
|
75
|
+
type: string;
|
|
76
|
+
additionalProperties: boolean;
|
|
77
|
+
required: string[];
|
|
78
|
+
description: string;
|
|
79
|
+
"x-descriptionZh": string;
|
|
80
|
+
properties: {
|
|
81
|
+
provider: {
|
|
82
|
+
type: string;
|
|
83
|
+
pattern: string;
|
|
84
|
+
description: string;
|
|
85
|
+
"x-descriptionZh": string;
|
|
86
|
+
};
|
|
87
|
+
skills: {
|
|
88
|
+
$ref: string;
|
|
89
|
+
};
|
|
90
|
+
tools: {
|
|
91
|
+
$ref: string;
|
|
92
|
+
};
|
|
93
|
+
memory: {
|
|
94
|
+
$ref: string;
|
|
95
|
+
};
|
|
96
|
+
agents: {
|
|
97
|
+
$ref: string;
|
|
98
|
+
};
|
|
99
|
+
approval: {
|
|
100
|
+
$ref: string;
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
workroom: {
|
|
105
|
+
type: string;
|
|
106
|
+
additionalProperties: boolean;
|
|
107
|
+
description: string;
|
|
108
|
+
"x-descriptionZh": string;
|
|
109
|
+
properties: {
|
|
110
|
+
trustedPackPublishers: {
|
|
111
|
+
type: string;
|
|
112
|
+
items: {
|
|
113
|
+
type: string;
|
|
114
|
+
minLength: number;
|
|
115
|
+
};
|
|
116
|
+
uniqueItems: boolean;
|
|
117
|
+
description: string;
|
|
118
|
+
"x-descriptionZh": string;
|
|
119
|
+
};
|
|
120
|
+
disclosure: {
|
|
121
|
+
type: string;
|
|
122
|
+
additionalProperties: boolean;
|
|
123
|
+
description: string;
|
|
124
|
+
"x-descriptionZh": string;
|
|
125
|
+
properties: {
|
|
126
|
+
tenantId: {
|
|
127
|
+
type: string;
|
|
128
|
+
minLength: number;
|
|
129
|
+
};
|
|
130
|
+
modelProviders: {
|
|
131
|
+
type: string;
|
|
132
|
+
additionalProperties: {
|
|
133
|
+
type: string;
|
|
134
|
+
additionalProperties: boolean;
|
|
135
|
+
required: string[];
|
|
136
|
+
properties: {
|
|
137
|
+
endpoint: {
|
|
138
|
+
type: string;
|
|
139
|
+
minLength: number;
|
|
140
|
+
};
|
|
141
|
+
owner: {
|
|
142
|
+
type: string;
|
|
143
|
+
minLength: number;
|
|
144
|
+
};
|
|
145
|
+
trustDomain: {
|
|
146
|
+
type: string;
|
|
147
|
+
minLength: number;
|
|
148
|
+
};
|
|
149
|
+
processingRegions: {
|
|
150
|
+
type: string;
|
|
151
|
+
minItems: number;
|
|
152
|
+
uniqueItems: boolean;
|
|
153
|
+
items: {
|
|
154
|
+
type: string;
|
|
155
|
+
minLength: number;
|
|
156
|
+
};
|
|
157
|
+
};
|
|
158
|
+
maxConfidentiality: {
|
|
159
|
+
type: string;
|
|
160
|
+
enum: string[];
|
|
161
|
+
};
|
|
162
|
+
external: {
|
|
163
|
+
type: string;
|
|
164
|
+
};
|
|
165
|
+
noTraining: {
|
|
166
|
+
type: string;
|
|
167
|
+
};
|
|
168
|
+
loggingMode: {
|
|
169
|
+
type: string;
|
|
170
|
+
enum: string[];
|
|
171
|
+
};
|
|
172
|
+
maximumRetentionSeconds: {
|
|
173
|
+
type: string;
|
|
174
|
+
minimum: number;
|
|
175
|
+
};
|
|
176
|
+
allowsRedisclosure: {
|
|
177
|
+
type: string;
|
|
178
|
+
};
|
|
179
|
+
supportsDeletion: {
|
|
180
|
+
type: string;
|
|
181
|
+
};
|
|
182
|
+
};
|
|
183
|
+
};
|
|
184
|
+
};
|
|
185
|
+
};
|
|
186
|
+
};
|
|
187
|
+
};
|
|
188
|
+
};
|
|
189
|
+
agent: {
|
|
190
|
+
type: string;
|
|
191
|
+
additionalProperties: boolean;
|
|
192
|
+
description: string;
|
|
193
|
+
"x-descriptionZh": string;
|
|
194
|
+
properties: {
|
|
195
|
+
inboundQueue: {
|
|
196
|
+
type: string;
|
|
197
|
+
additionalProperties: boolean;
|
|
198
|
+
description: string;
|
|
199
|
+
"x-descriptionZh": string;
|
|
200
|
+
properties: {
|
|
201
|
+
groupMode: {
|
|
202
|
+
type: string;
|
|
203
|
+
enum: string[];
|
|
204
|
+
description: string;
|
|
205
|
+
"x-descriptionZh": string;
|
|
206
|
+
};
|
|
207
|
+
};
|
|
208
|
+
};
|
|
209
|
+
execSecurity: {
|
|
210
|
+
type: string;
|
|
211
|
+
enum: string[];
|
|
212
|
+
description: string;
|
|
213
|
+
"x-descriptionZh": string;
|
|
214
|
+
};
|
|
215
|
+
execPreset: {
|
|
216
|
+
type: string;
|
|
217
|
+
enum: string[];
|
|
218
|
+
description: string;
|
|
219
|
+
"x-descriptionZh": string;
|
|
220
|
+
};
|
|
221
|
+
execApprovalMode: {
|
|
222
|
+
type: string;
|
|
223
|
+
enum: string[];
|
|
224
|
+
description: string;
|
|
225
|
+
"x-descriptionZh": string;
|
|
226
|
+
};
|
|
227
|
+
subagentExecApprovalMode: {
|
|
228
|
+
type: string;
|
|
229
|
+
enum: string[];
|
|
230
|
+
description: string;
|
|
231
|
+
"x-descriptionZh": string;
|
|
232
|
+
};
|
|
233
|
+
workerExecApprovalMode: {
|
|
234
|
+
type: string;
|
|
235
|
+
enum: string[];
|
|
236
|
+
description: string;
|
|
237
|
+
"x-descriptionZh": string;
|
|
238
|
+
};
|
|
239
|
+
taskExecApprovalMode: {
|
|
240
|
+
type: string;
|
|
241
|
+
enum: string[];
|
|
242
|
+
description: string;
|
|
243
|
+
"x-descriptionZh": string;
|
|
244
|
+
};
|
|
245
|
+
toolExecution: {
|
|
246
|
+
type: string;
|
|
247
|
+
enum: string[];
|
|
248
|
+
description: string;
|
|
249
|
+
"x-descriptionZh": string;
|
|
250
|
+
};
|
|
251
|
+
modelSizeHint: {
|
|
252
|
+
type: string;
|
|
253
|
+
enum: string[];
|
|
254
|
+
description: string;
|
|
255
|
+
"x-descriptionZh": string;
|
|
256
|
+
};
|
|
257
|
+
promptCacheRetention: {
|
|
258
|
+
type: string;
|
|
259
|
+
enum: string[];
|
|
260
|
+
description: string;
|
|
261
|
+
"x-descriptionZh": string;
|
|
262
|
+
};
|
|
263
|
+
steeringMode: {
|
|
264
|
+
type: string;
|
|
265
|
+
enum: string[];
|
|
266
|
+
description: string;
|
|
267
|
+
"x-descriptionZh": string;
|
|
268
|
+
};
|
|
269
|
+
followUpMode: {
|
|
270
|
+
type: string;
|
|
271
|
+
enum: string[];
|
|
272
|
+
description: string;
|
|
273
|
+
"x-descriptionZh": string;
|
|
274
|
+
};
|
|
275
|
+
outputSchema: {
|
|
276
|
+
anyOf: ({
|
|
277
|
+
type: string;
|
|
278
|
+
enum?: undefined;
|
|
279
|
+
} | {
|
|
280
|
+
type: string;
|
|
281
|
+
enum: string[];
|
|
282
|
+
})[];
|
|
283
|
+
description: string;
|
|
284
|
+
"x-descriptionZh": string;
|
|
285
|
+
};
|
|
286
|
+
schedule: {
|
|
287
|
+
type: string;
|
|
288
|
+
additionalProperties: boolean;
|
|
289
|
+
description: string;
|
|
290
|
+
"x-descriptionZh": string;
|
|
291
|
+
properties: {
|
|
292
|
+
security: {
|
|
293
|
+
type: string;
|
|
294
|
+
additionalProperties: boolean;
|
|
295
|
+
description: string;
|
|
296
|
+
"x-descriptionZh": string;
|
|
297
|
+
properties: {
|
|
298
|
+
execPreset: {
|
|
299
|
+
type: string;
|
|
300
|
+
enum: string[];
|
|
301
|
+
description: string;
|
|
302
|
+
"x-descriptionZh": string;
|
|
303
|
+
};
|
|
304
|
+
};
|
|
305
|
+
};
|
|
306
|
+
};
|
|
307
|
+
};
|
|
308
|
+
};
|
|
309
|
+
};
|
|
310
|
+
};
|
|
311
|
+
};
|
|
312
|
+
mcp: {
|
|
313
|
+
type: string;
|
|
314
|
+
additionalProperties: boolean;
|
|
315
|
+
description: string;
|
|
316
|
+
"x-descriptionZh": string;
|
|
317
|
+
};
|
|
318
|
+
a2a: {
|
|
319
|
+
type: string;
|
|
320
|
+
additionalProperties: boolean;
|
|
321
|
+
description: string;
|
|
322
|
+
"x-descriptionZh": string;
|
|
323
|
+
};
|
|
324
|
+
speech: {
|
|
325
|
+
type: string;
|
|
326
|
+
additionalProperties: boolean;
|
|
327
|
+
description: string;
|
|
328
|
+
"x-descriptionZh": string;
|
|
329
|
+
};
|
|
330
|
+
htmlRenderer: {
|
|
331
|
+
type: string;
|
|
332
|
+
additionalProperties: boolean;
|
|
333
|
+
description: string;
|
|
334
|
+
"x-descriptionZh": string;
|
|
335
|
+
properties: {
|
|
336
|
+
width: {
|
|
337
|
+
type: string;
|
|
338
|
+
minimum: number;
|
|
339
|
+
maximum: number;
|
|
340
|
+
description: string;
|
|
341
|
+
"x-descriptionZh": string;
|
|
342
|
+
};
|
|
343
|
+
defaultWidth: {
|
|
344
|
+
type: string;
|
|
345
|
+
minimum: number;
|
|
346
|
+
maximum: number;
|
|
347
|
+
description: string;
|
|
348
|
+
"x-descriptionZh": string;
|
|
349
|
+
};
|
|
350
|
+
viewport: {
|
|
351
|
+
type: string;
|
|
352
|
+
additionalProperties: boolean;
|
|
353
|
+
description: string;
|
|
354
|
+
"x-descriptionZh": string;
|
|
355
|
+
properties: {
|
|
356
|
+
width: {
|
|
357
|
+
type: string;
|
|
358
|
+
minimum: number;
|
|
359
|
+
maximum: number;
|
|
360
|
+
description: string;
|
|
361
|
+
"x-descriptionZh": string;
|
|
362
|
+
};
|
|
363
|
+
height: {
|
|
364
|
+
type: string;
|
|
365
|
+
minimum: number;
|
|
366
|
+
maximum: number;
|
|
367
|
+
description: string;
|
|
368
|
+
"x-descriptionZh": string;
|
|
369
|
+
};
|
|
370
|
+
};
|
|
371
|
+
};
|
|
372
|
+
backgroundColor: {
|
|
373
|
+
type: string;
|
|
374
|
+
description: string;
|
|
375
|
+
"x-descriptionZh": string;
|
|
376
|
+
};
|
|
377
|
+
defaultBackgroundColor: {
|
|
378
|
+
type: string;
|
|
379
|
+
description: string;
|
|
380
|
+
"x-descriptionZh": string;
|
|
381
|
+
};
|
|
382
|
+
scale: {
|
|
383
|
+
type: string;
|
|
384
|
+
minimum: number;
|
|
385
|
+
maximum: number;
|
|
386
|
+
description: string;
|
|
387
|
+
"x-descriptionZh": string;
|
|
388
|
+
};
|
|
389
|
+
type: {
|
|
390
|
+
type: string;
|
|
391
|
+
enum: string[];
|
|
392
|
+
description: string;
|
|
393
|
+
"x-descriptionZh": string;
|
|
394
|
+
};
|
|
395
|
+
quality: {
|
|
396
|
+
type: string;
|
|
397
|
+
minimum: number;
|
|
398
|
+
maximum: number;
|
|
399
|
+
description: string;
|
|
400
|
+
"x-descriptionZh": string;
|
|
401
|
+
};
|
|
402
|
+
timeout: {
|
|
403
|
+
type: string;
|
|
404
|
+
minimum: number;
|
|
405
|
+
maximum: number;
|
|
406
|
+
description: string;
|
|
407
|
+
"x-descriptionZh": string;
|
|
408
|
+
};
|
|
409
|
+
waitUntil: {
|
|
410
|
+
type: string;
|
|
411
|
+
enum: string[];
|
|
412
|
+
description: string;
|
|
413
|
+
"x-descriptionZh": string;
|
|
414
|
+
};
|
|
415
|
+
fontFamily: {
|
|
416
|
+
type: string;
|
|
417
|
+
description: string;
|
|
418
|
+
"x-descriptionZh": string;
|
|
419
|
+
};
|
|
420
|
+
maxImageHeight: {
|
|
421
|
+
type: string;
|
|
422
|
+
minimum: number;
|
|
423
|
+
maximum: number;
|
|
424
|
+
description: string;
|
|
425
|
+
"x-descriptionZh": string;
|
|
426
|
+
};
|
|
427
|
+
sliceCompression: {
|
|
428
|
+
type: string;
|
|
429
|
+
minimum: number;
|
|
430
|
+
maximum: number;
|
|
431
|
+
description: string;
|
|
432
|
+
"x-descriptionZh": string;
|
|
433
|
+
};
|
|
434
|
+
allowFileAccess: {
|
|
435
|
+
type: string;
|
|
436
|
+
description: string;
|
|
437
|
+
"x-descriptionZh": string;
|
|
438
|
+
};
|
|
439
|
+
takeOverHtmlSegments: {
|
|
440
|
+
type: string;
|
|
441
|
+
description: string;
|
|
442
|
+
"x-descriptionZh": string;
|
|
443
|
+
};
|
|
444
|
+
cacheDir: {
|
|
445
|
+
type: string;
|
|
446
|
+
description: string;
|
|
447
|
+
"x-descriptionZh": string;
|
|
448
|
+
};
|
|
449
|
+
cacheMaxBytes: {
|
|
450
|
+
type: string;
|
|
451
|
+
minimum: number;
|
|
452
|
+
description: string;
|
|
453
|
+
"x-descriptionZh": string;
|
|
454
|
+
};
|
|
455
|
+
userAgent: {
|
|
456
|
+
type: string;
|
|
457
|
+
description: string;
|
|
458
|
+
"x-descriptionZh": string;
|
|
459
|
+
};
|
|
460
|
+
idleTimeoutMs: {
|
|
461
|
+
type: string;
|
|
462
|
+
minimum: number;
|
|
463
|
+
maximum: number;
|
|
464
|
+
description: string;
|
|
465
|
+
"x-descriptionZh": string;
|
|
466
|
+
};
|
|
467
|
+
logStats: {
|
|
468
|
+
type: string;
|
|
469
|
+
description: string;
|
|
470
|
+
"x-descriptionZh": string;
|
|
471
|
+
};
|
|
472
|
+
mode: {
|
|
473
|
+
type: string;
|
|
474
|
+
enum: string[];
|
|
475
|
+
description: string;
|
|
476
|
+
"x-descriptionZh": string;
|
|
477
|
+
};
|
|
478
|
+
aiTextAsImage: {
|
|
479
|
+
anyOf: ({
|
|
480
|
+
type: string;
|
|
481
|
+
additionalProperties?: undefined;
|
|
482
|
+
description?: undefined;
|
|
483
|
+
"x-descriptionZh"?: undefined;
|
|
484
|
+
properties?: undefined;
|
|
485
|
+
} | {
|
|
486
|
+
type: string;
|
|
487
|
+
additionalProperties: boolean;
|
|
488
|
+
description: string;
|
|
489
|
+
"x-descriptionZh": string;
|
|
490
|
+
properties: {
|
|
491
|
+
enabled: {
|
|
492
|
+
type: string;
|
|
493
|
+
description: string;
|
|
494
|
+
"x-descriptionZh": string;
|
|
495
|
+
};
|
|
496
|
+
onlyAdapters: {
|
|
497
|
+
type: string;
|
|
498
|
+
items: {
|
|
499
|
+
type: string;
|
|
500
|
+
minLength: number;
|
|
501
|
+
};
|
|
502
|
+
uniqueItems: boolean;
|
|
503
|
+
description: string;
|
|
504
|
+
"x-descriptionZh": string;
|
|
505
|
+
};
|
|
506
|
+
minLength: {
|
|
507
|
+
type: string;
|
|
508
|
+
minimum: number;
|
|
509
|
+
description: string;
|
|
510
|
+
"x-descriptionZh": string;
|
|
511
|
+
};
|
|
512
|
+
maxLength: {
|
|
513
|
+
type: string;
|
|
514
|
+
minimum: number;
|
|
515
|
+
description: string;
|
|
516
|
+
"x-descriptionZh": string;
|
|
517
|
+
};
|
|
518
|
+
skipIfRich: {
|
|
519
|
+
type: string;
|
|
520
|
+
description: string;
|
|
521
|
+
"x-descriptionZh": string;
|
|
522
|
+
};
|
|
523
|
+
width: {
|
|
524
|
+
type: string;
|
|
525
|
+
minimum: number;
|
|
526
|
+
maximum: number;
|
|
527
|
+
description: string;
|
|
528
|
+
"x-descriptionZh": string;
|
|
529
|
+
};
|
|
530
|
+
height: {
|
|
531
|
+
type: string;
|
|
532
|
+
minimum: number;
|
|
533
|
+
maximum: number;
|
|
534
|
+
description: string;
|
|
535
|
+
"x-descriptionZh": string;
|
|
536
|
+
};
|
|
537
|
+
backgroundColor: {
|
|
538
|
+
type: string;
|
|
539
|
+
description: string;
|
|
540
|
+
"x-descriptionZh": string;
|
|
541
|
+
};
|
|
542
|
+
fontSize: {
|
|
543
|
+
type: string;
|
|
544
|
+
minimum: number;
|
|
545
|
+
description: string;
|
|
546
|
+
"x-descriptionZh": string;
|
|
547
|
+
};
|
|
548
|
+
color: {
|
|
549
|
+
type: string;
|
|
550
|
+
description: string;
|
|
551
|
+
"x-descriptionZh": string;
|
|
552
|
+
};
|
|
553
|
+
padding: {
|
|
554
|
+
type: string;
|
|
555
|
+
minimum: number;
|
|
556
|
+
description: string;
|
|
557
|
+
"x-descriptionZh": string;
|
|
558
|
+
};
|
|
559
|
+
scale: {
|
|
560
|
+
type: string;
|
|
561
|
+
minimum: number;
|
|
562
|
+
maximum: number;
|
|
563
|
+
description: string;
|
|
564
|
+
"x-descriptionZh": string;
|
|
565
|
+
};
|
|
566
|
+
fileName: {
|
|
567
|
+
type: string;
|
|
568
|
+
minLength: number;
|
|
569
|
+
description: string;
|
|
570
|
+
"x-descriptionZh": string;
|
|
571
|
+
};
|
|
572
|
+
};
|
|
573
|
+
})[];
|
|
574
|
+
description: string;
|
|
575
|
+
"x-descriptionZh": string;
|
|
576
|
+
};
|
|
577
|
+
};
|
|
578
|
+
};
|
|
579
|
+
assistant: {
|
|
580
|
+
type: string;
|
|
581
|
+
additionalProperties: boolean;
|
|
582
|
+
description: string;
|
|
583
|
+
"x-descriptionZh": string;
|
|
584
|
+
};
|
|
585
|
+
log_level: {
|
|
586
|
+
type: string[];
|
|
587
|
+
description: string;
|
|
588
|
+
"x-descriptionZh": string;
|
|
589
|
+
};
|
|
590
|
+
plugin: {
|
|
591
|
+
type: string;
|
|
592
|
+
description: string;
|
|
593
|
+
"x-descriptionZh": string;
|
|
594
|
+
};
|
|
595
|
+
};
|
|
596
|
+
$defs: {
|
|
597
|
+
decisionTask: {
|
|
598
|
+
type: string;
|
|
599
|
+
additionalProperties: boolean;
|
|
600
|
+
required: string[];
|
|
601
|
+
properties: {
|
|
602
|
+
mode: {
|
|
603
|
+
type: string;
|
|
604
|
+
enum: string[];
|
|
605
|
+
};
|
|
606
|
+
timeoutMs: {
|
|
607
|
+
type: string;
|
|
608
|
+
minimum: number;
|
|
609
|
+
maximum: number;
|
|
610
|
+
};
|
|
611
|
+
minConfidence: {
|
|
612
|
+
type: string;
|
|
613
|
+
minimum: number;
|
|
614
|
+
maximum: number;
|
|
615
|
+
};
|
|
616
|
+
topK: {
|
|
617
|
+
type: string;
|
|
618
|
+
minimum: number;
|
|
619
|
+
maximum: number;
|
|
620
|
+
};
|
|
621
|
+
maxCandidates: {
|
|
622
|
+
type: string;
|
|
623
|
+
minimum: number;
|
|
624
|
+
maximum: number;
|
|
625
|
+
};
|
|
626
|
+
maxSelections: {
|
|
627
|
+
type: string;
|
|
628
|
+
minimum: number;
|
|
629
|
+
maximum: number;
|
|
630
|
+
};
|
|
631
|
+
};
|
|
632
|
+
};
|
|
633
|
+
};
|
|
634
|
+
};
|
|
4
635
|
/** Host configuration keys consumed by Runtime composition and Host installers. */
|
|
5
636
|
export declare const HOST_CONFIG_KEYS: readonly string[];
|
|
6
637
|
export type JsonSchema = Readonly<Record<string, unknown>>;
|
package/lib/config-composer.js
CHANGED
|
@@ -10,7 +10,7 @@ function deepFreeze(value) {
|
|
|
10
10
|
}
|
|
11
11
|
return value;
|
|
12
12
|
}
|
|
13
|
-
const HOST_CONFIG_SCHEMA = deepFreeze(hostConfigSchema);
|
|
13
|
+
export const HOST_CONFIG_SCHEMA = deepFreeze(hostConfigSchema);
|
|
14
14
|
/** Host configuration keys consumed by Runtime composition and Host installers. */
|
|
15
15
|
export const HOST_CONFIG_KEYS = Object.freeze(Object.keys(HOST_CONFIG_SCHEMA.properties));
|
|
16
16
|
export class ConfigSchemaCollisionError extends Error {
|
|
@@ -57,6 +57,7 @@ export class ConfigComposer {
|
|
|
57
57
|
// start-command, not Plugin ConfigViews.
|
|
58
58
|
const effectiveSchema = Object.freeze({
|
|
59
59
|
type: 'object',
|
|
60
|
+
$defs: HOST_CONFIG_SCHEMA.$defs,
|
|
60
61
|
additionalProperties: false,
|
|
61
62
|
properties: {
|
|
62
63
|
...HOST_CONFIG_SCHEMA.properties,
|
package/lib/hmr-coordinator.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { normalizeSourcePath } from './source-path.js';
|
|
1
2
|
import { InvalidationPlanner, } from './invalidation-planner.js';
|
|
2
3
|
export class HmrCoordinator {
|
|
3
4
|
options;
|
|
@@ -31,11 +32,28 @@ export class HmrCoordinator {
|
|
|
31
32
|
if (this.#stopResult)
|
|
32
33
|
return this.#stopResult;
|
|
33
34
|
this.#closing = true;
|
|
34
|
-
this.#unwatch
|
|
35
|
+
const unwatch = this.#unwatch;
|
|
35
36
|
this.#unwatch = undefined;
|
|
36
|
-
this.#stopResult = (async () => {
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
this.#stopResult = Promise.resolve().then(async () => {
|
|
38
|
+
const errors = [];
|
|
39
|
+
try {
|
|
40
|
+
await unwatch?.();
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
errors.push(error);
|
|
44
|
+
}
|
|
45
|
+
// Watcher disposal failure must not bypass already admitted reloads.
|
|
46
|
+
try {
|
|
47
|
+
await this.#draining;
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
errors.push(error);
|
|
51
|
+
}
|
|
52
|
+
if (errors.length === 1)
|
|
53
|
+
throw errors[0];
|
|
54
|
+
if (errors.length > 1)
|
|
55
|
+
throw new AggregateError(errors, 'HMR stop failed');
|
|
56
|
+
});
|
|
39
57
|
return this.#stopResult;
|
|
40
58
|
}
|
|
41
59
|
enqueue(source) {
|
|
@@ -45,7 +63,7 @@ export class HmrCoordinator {
|
|
|
45
63
|
if (this.#restartRequired) {
|
|
46
64
|
return Promise.reject(new Error('HMR coordinator requires a process restart'));
|
|
47
65
|
}
|
|
48
|
-
this.#pending.add(source);
|
|
66
|
+
this.#pending.add(normalizeSourcePath(source));
|
|
49
67
|
const completed = new Promise((resolve, reject) => {
|
|
50
68
|
this.#waiters.push({ resolve, reject });
|
|
51
69
|
});
|
|
@@ -46,6 +46,21 @@
|
|
|
46
46
|
"description": "Providers, Agents, sessions, memory, tools, and execution security.",
|
|
47
47
|
"x-descriptionZh": "Provider、Agent、会话、记忆、工具与执行安全策略。",
|
|
48
48
|
"properties": {
|
|
49
|
+
"decisions": {
|
|
50
|
+
"type": "object",
|
|
51
|
+
"additionalProperties": false,
|
|
52
|
+
"required": ["provider"],
|
|
53
|
+
"description": "Optional structured-decision service. Missing tasks are off; use shadow before active.",
|
|
54
|
+
"x-descriptionZh": "可选的结构化决策服务。未配置的任务关闭;建议先用 shadow 验证。",
|
|
55
|
+
"properties": {
|
|
56
|
+
"provider": { "type": "string", "pattern": "^root(/[a-z0-9][a-z0-9-]*)+$", "description": "Exact enabled DecisionProvider Plugin owner, such as root/typesafe.", "x-descriptionZh": "提供已启用 DecisionProvider 的精确插件身份,例如 root/typesafe。" },
|
|
57
|
+
"skills": { "$ref": "#/$defs/decisionTask" },
|
|
58
|
+
"tools": { "$ref": "#/$defs/decisionTask" },
|
|
59
|
+
"memory": { "$ref": "#/$defs/decisionTask" },
|
|
60
|
+
"agents": { "$ref": "#/$defs/decisionTask" },
|
|
61
|
+
"approval": { "$ref": "#/$defs/decisionTask" }
|
|
62
|
+
}
|
|
63
|
+
},
|
|
49
64
|
"workroom": {
|
|
50
65
|
"type": "object",
|
|
51
66
|
"additionalProperties": true,
|
|
@@ -264,5 +279,20 @@
|
|
|
264
279
|
"assistant": { "type": "object", "additionalProperties": true, "description": "Scheduled jobs, event ingress, and failure notifications.", "x-descriptionZh": "调度任务、事件入口和失败通知。" },
|
|
265
280
|
"log_level": { "type": ["string", "number"], "description": "Runtime log level.", "x-descriptionZh": "Runtime 日志级别。" },
|
|
266
281
|
"plugin": { "type": "object", "description": "Root Plugin configuration; replaced by its project schema during composition.", "x-descriptionZh": "Root Plugin 配置;组合时由项目 Schema 替换。" }
|
|
282
|
+
},
|
|
283
|
+
"$defs": {
|
|
284
|
+
"decisionTask": {
|
|
285
|
+
"type": "object",
|
|
286
|
+
"additionalProperties": false,
|
|
287
|
+
"required": ["mode"],
|
|
288
|
+
"properties": {
|
|
289
|
+
"mode": { "type": "string", "enum": ["off", "shadow", "active"] },
|
|
290
|
+
"timeoutMs": { "type": "integer", "minimum": 1, "maximum": 2147483647 },
|
|
291
|
+
"minConfidence": { "type": "number", "minimum": 0, "maximum": 1 },
|
|
292
|
+
"topK": { "type": "integer", "minimum": 1, "maximum": 9007199254740991 },
|
|
293
|
+
"maxCandidates": { "type": "integer", "minimum": 1, "maximum": 9007199254740991 },
|
|
294
|
+
"maxSelections": { "type": "integer", "minimum": 1, "maximum": 9007199254740991 }
|
|
295
|
+
}
|
|
296
|
+
}
|
|
267
297
|
}
|
|
268
298
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { normalizeSourcePath } from './source-path.js';
|
|
2
|
+
import { basename } from 'node:path';
|
|
2
3
|
import { rootPluginId } from '@zhin.js/plugin-runtime';
|
|
3
4
|
const processFiles = new Set([
|
|
4
5
|
'pnpm-lock.yaml',
|
|
@@ -14,7 +15,7 @@ export class InvalidationPlanner {
|
|
|
14
15
|
this.dependencies = dependencies;
|
|
15
16
|
}
|
|
16
17
|
plan(sources) {
|
|
17
|
-
const changed = unique(sources.map((source) =>
|
|
18
|
+
const changed = unique(sources.map((source) => normalizeSourcePath(source)));
|
|
18
19
|
if (changed.some((source) => processFiles.has(basename(source)))) {
|
|
19
20
|
return Object.freeze({
|
|
20
21
|
kind: 'process',
|
|
@@ -32,7 +33,7 @@ export class InvalidationPlanner {
|
|
|
32
33
|
if (basename(source) === 'package.json') {
|
|
33
34
|
addManifestSource(manifestSources, reasons, source);
|
|
34
35
|
}
|
|
35
|
-
const affected = unique([source, ...(this.dependencies?.affectedSources(source) ?? [])].map((item) =>
|
|
36
|
+
const affected = unique([source, ...(this.dependencies?.affectedSources(source) ?? [])].map((item) => normalizeSourcePath(item)));
|
|
36
37
|
let matched = false;
|
|
37
38
|
for (const item of affected) {
|
|
38
39
|
const records = this.ownership.recordsFor(item);
|
|
@@ -95,7 +96,7 @@ export class InvalidationPlanner {
|
|
|
95
96
|
}
|
|
96
97
|
}
|
|
97
98
|
function addManifestSource(manifestSources, reasons, source) {
|
|
98
|
-
const manifest =
|
|
99
|
+
const manifest = normalizeSourcePath(source);
|
|
99
100
|
manifestSources.add(manifest);
|
|
100
101
|
reasons.add(`Manifest source changed: ${manifest}`);
|
|
101
102
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { normalizeSourcePath } from './source-path.js';
|
|
1
2
|
import { access, readFile } from 'node:fs/promises';
|
|
2
3
|
import { basename, dirname, extname, isAbsolute, join, relative, resolve } from 'node:path';
|
|
3
4
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
@@ -21,7 +22,7 @@ export class ModuleDependencyIndex {
|
|
|
21
22
|
#commonJsByDirectory = new Map();
|
|
22
23
|
#dirtyEntries = new Set();
|
|
23
24
|
async analyze(entry) {
|
|
24
|
-
const normalized =
|
|
25
|
+
const normalized = normalizeSourcePath(entry);
|
|
25
26
|
const cached = this.#dependenciesByEntry.get(normalized);
|
|
26
27
|
if (cached && !this.#dirtyEntries.has(normalized)) {
|
|
27
28
|
return analysis(cached, this.#commonJsSourcesByEntry.get(normalized) ?? new Set());
|
|
@@ -34,7 +35,7 @@ export class ModuleDependencyIndex {
|
|
|
34
35
|
return analysis(dependencies, commonJsSources);
|
|
35
36
|
}
|
|
36
37
|
commit(entry, result) {
|
|
37
|
-
const normalized =
|
|
38
|
+
const normalized = normalizeSourcePath(entry);
|
|
38
39
|
this.#remove(normalized);
|
|
39
40
|
const dependencies = new Set(result.dependencies);
|
|
40
41
|
const commonJsSources = new Set(result.commonJsSources);
|
|
@@ -50,7 +51,7 @@ export class ModuleDependencyIndex {
|
|
|
50
51
|
}
|
|
51
52
|
/** Marks the changed entry and every entry importing it for lazy re-analysis. */
|
|
52
53
|
invalidate(source) {
|
|
53
|
-
const normalized =
|
|
54
|
+
const normalized = normalizeSourcePath(source);
|
|
54
55
|
if (basename(normalized) === 'package.json') {
|
|
55
56
|
this.#commonJsByDirectory.clear();
|
|
56
57
|
const packageRoot = dirname(normalized);
|
|
@@ -69,7 +70,7 @@ export class ModuleDependencyIndex {
|
|
|
69
70
|
}
|
|
70
71
|
/** Drops entries that no longer belong to the successfully committed generation. */
|
|
71
72
|
retain(entries) {
|
|
72
|
-
const active = new Set(entries.map((entry) =>
|
|
73
|
+
const active = new Set(entries.map((entry) => normalizeSourcePath(entry)));
|
|
73
74
|
for (const entry of this.#dependenciesByEntry.keys()) {
|
|
74
75
|
if (!active.has(entry))
|
|
75
76
|
this.#remove(entry);
|
|
@@ -84,7 +85,7 @@ export class ModuleDependencyIndex {
|
|
|
84
85
|
this.#dirtyEntries.clear();
|
|
85
86
|
}
|
|
86
87
|
hasCommonJsImpact(source) {
|
|
87
|
-
const normalized =
|
|
88
|
+
const normalized = normalizeSourcePath(source);
|
|
88
89
|
if (isExplicitCommonJsSource(normalized))
|
|
89
90
|
return true;
|
|
90
91
|
if (this.#entriesByCommonJsSource.has(normalized))
|
|
@@ -92,7 +93,7 @@ export class ModuleDependencyIndex {
|
|
|
92
93
|
return [...(this.#entriesByDependency.get(normalized) ?? [])].some((entry) => this.#commonJsSourcesByEntry.get(entry)?.has(entry) ?? false);
|
|
93
94
|
}
|
|
94
95
|
affectedSources(source) {
|
|
95
|
-
const normalized =
|
|
96
|
+
const normalized = normalizeSourcePath(source);
|
|
96
97
|
const entries = [...(this.#entriesByDependency.get(normalized) ?? [])].sort();
|
|
97
98
|
return Object.freeze([normalized, ...entries.filter((entry) => entry !== normalized)]);
|
|
98
99
|
}
|
|
@@ -363,7 +364,7 @@ async function resolveLocalImport(importer, specifier) {
|
|
|
363
364
|
}
|
|
364
365
|
for (const candidate of importCandidates(requested)) {
|
|
365
366
|
if (await exists(candidate))
|
|
366
|
-
return
|
|
367
|
+
return normalizeSourcePath(candidate);
|
|
367
368
|
}
|
|
368
369
|
return undefined;
|
|
369
370
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { normalizeSourcePath } from './source-path.js';
|
|
1
2
|
import { readdirSync, statSync, watch as watchDirectory, } from 'node:fs';
|
|
2
3
|
import { basename, extname, isAbsolute, relative, resolve, sep } from 'node:path';
|
|
3
4
|
import { pathToFileURL } from 'node:url';
|
|
@@ -29,14 +30,14 @@ export class NativeDevelopmentModuleRuntime {
|
|
|
29
30
|
#closed = false;
|
|
30
31
|
constructor(options) {
|
|
31
32
|
ensureTypeScriptSpecifierRemap();
|
|
32
|
-
this.#projectRoot =
|
|
33
|
+
this.#projectRoot = normalizeSourcePath(options.projectRoot);
|
|
33
34
|
this.#watchEnabled = options.watch ?? true;
|
|
34
35
|
this.#tsxLoader = options.tsxLoader;
|
|
35
36
|
this.#watchRoots = normalizeWatchRoots([this.#projectRoot]);
|
|
36
37
|
}
|
|
37
38
|
async load(source) {
|
|
38
39
|
this.#assertOpen();
|
|
39
|
-
const normalized =
|
|
40
|
+
const normalized = normalizeSourcePath(source);
|
|
40
41
|
if (isNativeTypeScriptSource(normalized))
|
|
41
42
|
assertNativeTypeScriptSupport();
|
|
42
43
|
const analysis = this.#pendingDependencies?.get(normalized)
|
|
@@ -67,7 +68,7 @@ export class NativeDevelopmentModuleRuntime {
|
|
|
67
68
|
return this.#dependencies.affectedSources(source);
|
|
68
69
|
}
|
|
69
70
|
requiresProcessRestart(source) {
|
|
70
|
-
const normalized =
|
|
71
|
+
const normalized = normalizeSourcePath(source);
|
|
71
72
|
const packageRoot = nearestWatchRoot(this.#watchRoots, normalized);
|
|
72
73
|
// Installed packages and external paths are intentionally not watched.
|
|
73
74
|
// The HMR coordinator turns this into a visible process restart reason.
|
|
@@ -353,7 +354,7 @@ function isNodeModulesSource(root, source) {
|
|
|
353
354
|
return relative(root, source).split(sep).some((part) => part === 'node_modules');
|
|
354
355
|
}
|
|
355
356
|
function normalizeWatchRoots(roots) {
|
|
356
|
-
const sorted = [...new Set(roots.map((root) =>
|
|
357
|
+
const sorted = [...new Set(roots.map((root) => normalizeSourcePath(root)))].sort((left, right) => left.length - right.length);
|
|
357
358
|
return Object.freeze(sorted.filter((root, index) => !sorted.slice(0, index).some((parent) => isWithin(parent, root))));
|
|
358
359
|
}
|
|
359
360
|
function sameRoots(left, right) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DisposeStack, Scope, type Dispose, type FeatureId, type GenerationHandoff, type GenerationAdmissionGate, type GenerationHandoffRegistry, type PluginId, type PluginNodeSnapshot, type SetupCapabilityRegistration, type TokenId } from '@zhin.js/plugin-runtime';
|
|
1
|
+
import { DisposeStack, Scope, type Dispose, type FeatureId, type GenerationHandoff, type GenerationAdmissionGate, type GenerationHandoffRegistry, type RuntimeSnapshot, type PluginId, type PluginNodeSnapshot, type SetupCapabilityRegistration, type TokenId } from '@zhin.js/plugin-runtime';
|
|
2
2
|
import { type RuntimeEnvironment } from './environment.js';
|
|
3
3
|
import { type EnvironmentLayers } from './environment-store.js';
|
|
4
4
|
import type { ModuleRuntime } from './module-runtime.js';
|
|
@@ -10,6 +10,8 @@ export type PluginConfigResolver = (node: PluginGraphNode) => unknown;
|
|
|
10
10
|
export interface RootResourceContext {
|
|
11
11
|
/** Exact shadow generation being assembled; never inferred from a latest snapshot. */
|
|
12
12
|
readonly generation: number;
|
|
13
|
+
/** Exact projected candidate, available during handoff activation, never the committed previous generation. */
|
|
14
|
+
readonly readCandidateSnapshot?: () => RuntimeSnapshot;
|
|
13
15
|
readonly signal: AbortSignal;
|
|
14
16
|
readonly resources: Scope;
|
|
15
17
|
readonly lifecycle: DisposeStack;
|
|
@@ -51,6 +53,7 @@ export declare class PluginScopeAssembler {
|
|
|
51
53
|
setupTree(node: PluginGraphNode, signal: AbortSignal): Promise<void>;
|
|
52
54
|
synchronizeTree(node: PluginGraphNode): void;
|
|
53
55
|
createdScopeDisposers(): readonly (readonly [PluginId, Dispose])[];
|
|
56
|
+
bindCandidateSnapshot(snapshot: RuntimeSnapshot): void;
|
|
54
57
|
generationHandoff(): GenerationHandoff | undefined;
|
|
55
58
|
setupCapabilities(): readonly Readonly<SetupCapabilityRegistration>[];
|
|
56
59
|
/** Root resources are process-owned; every Plugin Scope receives an owner-bound facade. */
|
|
@@ -21,6 +21,7 @@ export class PluginScopeAssembler {
|
|
|
21
21
|
#handoffs = new GenerationHandoffStack();
|
|
22
22
|
#admission = createGenerationAdmissionGate();
|
|
23
23
|
#envStores;
|
|
24
|
+
#candidateSnapshot;
|
|
24
25
|
#setupFeatureAliases = new Map();
|
|
25
26
|
constructor(modules, configResolver, environment, primaryConfigDocument, generation, installResources, environmentLayers = {}, seed, isolation) {
|
|
26
27
|
this.modules = modules;
|
|
@@ -71,6 +72,11 @@ export class PluginScopeAssembler {
|
|
|
71
72
|
scope.provide(primaryConfigToken, config);
|
|
72
73
|
await this.installResources?.({
|
|
73
74
|
generation: this.generation,
|
|
75
|
+
readCandidateSnapshot: () => {
|
|
76
|
+
if (!this.#candidateSnapshot)
|
|
77
|
+
throw new Error('Candidate snapshot is not projected yet');
|
|
78
|
+
return this.#candidateSnapshot;
|
|
79
|
+
},
|
|
74
80
|
signal,
|
|
75
81
|
resources: scope,
|
|
76
82
|
lifecycle: scope.disposers,
|
|
@@ -206,6 +212,12 @@ export class PluginScopeAssembler {
|
|
|
206
212
|
return [owner, () => scope.disposers.dispose()];
|
|
207
213
|
});
|
|
208
214
|
}
|
|
215
|
+
bindCandidateSnapshot(snapshot) {
|
|
216
|
+
if (snapshot.generation !== this.generation || this.#candidateSnapshot) {
|
|
217
|
+
throw new Error('Candidate snapshot does not match this Plugin assembly');
|
|
218
|
+
}
|
|
219
|
+
this.#candidateSnapshot = snapshot;
|
|
220
|
+
}
|
|
209
221
|
generationHandoff() {
|
|
210
222
|
return this.#handoffs.seal();
|
|
211
223
|
}
|
package/lib/root-runtime.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { normalizeSourcePath } from './source-path.js';
|
|
1
2
|
import { resolve } from 'node:path';
|
|
2
3
|
import { isDeepStrictEqual } from 'node:util';
|
|
3
4
|
import { DisposeStack, GenerationHandoffStack, RootController, ConfigDocumentDivergenceError, createSnapshotView, rootPluginId, } from '@zhin.js/plugin-runtime';
|
|
@@ -41,7 +42,7 @@ export class RootRuntime {
|
|
|
41
42
|
#controller;
|
|
42
43
|
#disabledPluginInstanceKeys;
|
|
43
44
|
constructor(options) {
|
|
44
|
-
this.#projectRoot =
|
|
45
|
+
this.#projectRoot = normalizeSourcePath(options.projectRoot);
|
|
45
46
|
this.#modules = options.modules;
|
|
46
47
|
this.#environment = defineRuntimeEnvironment(options.environment);
|
|
47
48
|
this.#environmentLayers = defineEnvironmentLayers(options.environmentVariables);
|
|
@@ -55,7 +56,7 @@ export class RootRuntime {
|
|
|
55
56
|
this.#runtimeInputSources = new Set([
|
|
56
57
|
...(this.#configPort?.sources ?? []),
|
|
57
58
|
...(this.#environmentSource?.sources ?? []),
|
|
58
|
-
].map((source) =>
|
|
59
|
+
].map((source) => normalizeSourcePath(source)));
|
|
59
60
|
this.#installResources = options.installResources;
|
|
60
61
|
this.#isolation = options.isolation;
|
|
61
62
|
this.#disabledPluginInstanceKeys = Object.freeze([...(options.disabledPluginInstanceKeys ?? [])]);
|
|
@@ -105,7 +106,7 @@ export class RootRuntime {
|
|
|
105
106
|
modules: this.#modules,
|
|
106
107
|
ownership: () => this.sourceOwnership,
|
|
107
108
|
runtime: {
|
|
108
|
-
handlesSource: (source) => this.#runtimeInputSources.has(
|
|
109
|
+
handlesSource: (source) => this.#runtimeInputSources.has(normalizeSourcePath(source)),
|
|
109
110
|
reload: async (plan) => {
|
|
110
111
|
const result = await this.#reloadPlan(plan);
|
|
111
112
|
return isProcessPlan(result) ? result : undefined;
|
|
@@ -139,7 +140,7 @@ export class RootRuntime {
|
|
|
139
140
|
? Object.freeze({
|
|
140
141
|
...plan,
|
|
141
142
|
subtrees: collapseInvalidationSubtrees([...plan.subtrees, ...inputs.roots]),
|
|
142
|
-
fallbacks: Object.freeze(plan.fallbacks.filter((fallback) => !inputs.inputSources.has(
|
|
143
|
+
fallbacks: Object.freeze(plan.fallbacks.filter((fallback) => !inputs.inputSources.has(normalizeSourcePath(fallback.source)))),
|
|
143
144
|
})
|
|
144
145
|
: plan;
|
|
145
146
|
let restart;
|
|
@@ -189,11 +190,11 @@ export class RootRuntime {
|
|
|
189
190
|
return this.#controller.committed.state.model;
|
|
190
191
|
}
|
|
191
192
|
async #planRuntimeInputs(changed) {
|
|
192
|
-
const inputSources = new Set(changed.map((source) =>
|
|
193
|
+
const inputSources = new Set(changed.map((source) => normalizeSourcePath(source)).filter((source) => this.#runtimeInputSources.has(source)));
|
|
193
194
|
if (inputSources.size === 0 || !this.#model)
|
|
194
195
|
return undefined;
|
|
195
|
-
const configChanged = this.#configPort?.sources?.some((source) => inputSources.has(
|
|
196
|
-
const environmentChanged = this.#environmentSource?.sources.some((source) => inputSources.has(
|
|
196
|
+
const configChanged = this.#configPort?.sources?.some((source) => inputSources.has(normalizeSourcePath(source))) ?? false;
|
|
197
|
+
const environmentChanged = this.#environmentSource?.sources.some((source) => inputSources.has(normalizeSourcePath(source))) ?? false;
|
|
197
198
|
const configSnapshot = configChanged ? await this.#configPort?.read() : undefined;
|
|
198
199
|
const document = configSnapshot?.document ?? requireConfigDocument(this.#configDocument);
|
|
199
200
|
const environmentLayers = environmentChanged && this.#environmentSource
|
|
@@ -210,7 +211,7 @@ export class RootRuntime {
|
|
|
210
211
|
if (inputPlan.hostKeys.length > 0) {
|
|
211
212
|
return Object.freeze({
|
|
212
213
|
kind: 'process',
|
|
213
|
-
changed: Object.freeze([...changed].map((source) =>
|
|
214
|
+
changed: Object.freeze([...changed].map((source) => normalizeSourcePath(source))),
|
|
214
215
|
reasons: Object.freeze(inputPlan.hostKeys.map((key) => `Host configuration changed: ${key}`)),
|
|
215
216
|
});
|
|
216
217
|
}
|
|
@@ -263,7 +264,7 @@ export class RootRuntime {
|
|
|
263
264
|
if (plan.subtrees.length === 0 || plan.subtrees.includes(rootPluginId()))
|
|
264
265
|
return false;
|
|
265
266
|
return plan.changed.every((source) => {
|
|
266
|
-
if (this.#runtimeInputSources.has(
|
|
267
|
+
if (this.#runtimeInputSources.has(normalizeSourcePath(source)))
|
|
267
268
|
return true;
|
|
268
269
|
const records = this.sourceOwnership.recordsFor(source);
|
|
269
270
|
return records.length > 0 && records.every((record) => record.role === 'plugin' || record.role === 'schema');
|
|
@@ -519,6 +520,7 @@ class GenerationAssembler {
|
|
|
519
520
|
}
|
|
520
521
|
const state = projected.state;
|
|
521
522
|
const snapshot = createSnapshotView(this.generation, state);
|
|
523
|
+
this.#plugins.bindCandidateSnapshot(snapshot);
|
|
522
524
|
const ownership = SourceOwnershipIndex.fromGeneration(this.graph, snapshot, this.#featureIdsByPackageRoot);
|
|
523
525
|
const assets = GenerationAssets.create(this.#plugins.createdScopeDisposers(), this.#projectionDisposers);
|
|
524
526
|
return prepareRuntimeGeneration({
|
package/lib/source-ownership.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { normalizeSourcePath } from './source-path.js';
|
|
1
2
|
import { isAbsolute, relative, resolve } from 'node:path';
|
|
2
3
|
export class SourceOwnershipIndex {
|
|
3
4
|
#records = new Map();
|
|
@@ -102,7 +103,7 @@ export class SourceOwnershipIndex {
|
|
|
102
103
|
return Object.freeze([...this.#watchRoots.values()]);
|
|
103
104
|
}
|
|
104
105
|
addWatchRoot(root) {
|
|
105
|
-
const normalized =
|
|
106
|
+
const normalized = normalizeSourcePath(root.root);
|
|
106
107
|
this.#watchRoots.set(normalized, Object.freeze({ ...root, root: normalized }));
|
|
107
108
|
}
|
|
108
109
|
}
|
|
@@ -112,7 +113,7 @@ function visitPlugin(node, visit) {
|
|
|
112
113
|
visitPlugin(child, visit);
|
|
113
114
|
}
|
|
114
115
|
function normalizeSource(source) {
|
|
115
|
-
return
|
|
116
|
+
return normalizeSourcePath(source);
|
|
116
117
|
}
|
|
117
118
|
function contains(packageRoot, source) {
|
|
118
119
|
const path = relative(packageRoot, source);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { realpathSync } from 'node:fs';
|
|
2
|
+
import { basename, dirname, join, resolve } from 'node:path';
|
|
3
|
+
/** Keep file events and scanned sources in the same physical path namespace.
|
|
4
|
+
* Resolve the nearest existing parent for unlink events and newly added files.
|
|
5
|
+
*/
|
|
6
|
+
export function normalizeSourcePath(source) {
|
|
7
|
+
const absolute = resolve(source);
|
|
8
|
+
let parent = absolute;
|
|
9
|
+
const suffix = [];
|
|
10
|
+
for (;;) {
|
|
11
|
+
try {
|
|
12
|
+
return join(realpathSync(parent), ...suffix);
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
const code = error.code;
|
|
16
|
+
if (code !== 'ENOENT' && code !== 'ENOTDIR')
|
|
17
|
+
throw error;
|
|
18
|
+
const next = dirname(parent);
|
|
19
|
+
if (next === parent)
|
|
20
|
+
return absolute;
|
|
21
|
+
suffix.unshift(basename(parent));
|
|
22
|
+
parent = next;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -82,6 +82,7 @@ export class SubtreeGenerationPreparer {
|
|
|
82
82
|
projectionDisposers.set(feature, dispose);
|
|
83
83
|
}
|
|
84
84
|
const snapshot = createSnapshotView(current.generation + 1, projected.state);
|
|
85
|
+
plugins.bindCandidateSnapshot(snapshot);
|
|
85
86
|
const ownership = SourceOwnershipIndex.fromGeneration(this.graph, snapshot, this.model.featureIdsByPackageRoot);
|
|
86
87
|
const replacements = new Map(plugins.createdScopeDisposers());
|
|
87
88
|
// Local prepare still commits a complete immutable generation. The
|
|
@@ -89,6 +89,7 @@ export class TopologyGenerationPreparer {
|
|
|
89
89
|
projectionDisposers.set(feature, dispose);
|
|
90
90
|
}
|
|
91
91
|
const snapshot = createSnapshotView(current.generation + 1, projected.state);
|
|
92
|
+
plugins.bindCandidateSnapshot(snapshot);
|
|
92
93
|
const ownership = SourceOwnershipIndex.fromGeneration(this.graph, snapshot, featureTopology.featureIdsByPackageRoot);
|
|
93
94
|
const replacements = new Map(plugins.createdScopeDisposers());
|
|
94
95
|
const assets = this.model.assets.replaceScopes(graphOrder(this.graph), replacements, projectionDisposers);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/runtime",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.5",
|
|
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",
|
|
@@ -20,24 +20,24 @@
|
|
|
20
20
|
"es-module-lexer": "2.3.1",
|
|
21
21
|
"import-meta-resolve": "4.2.0",
|
|
22
22
|
"semver": "7.8.5",
|
|
23
|
-
"@zhin.js/
|
|
24
|
-
"@zhin.js/
|
|
23
|
+
"@zhin.js/plugin-runtime": "1.1.12",
|
|
24
|
+
"@zhin.js/feature-kit": "1.1.3"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/node": "^26.1.2",
|
|
28
28
|
"tsx": "^4.23.1",
|
|
29
29
|
"typescript": "^6.0.3",
|
|
30
|
-
"@zhin.js/adapter": "1.1.
|
|
31
|
-
"@zhin.js/agent-feature": "1.1.
|
|
32
|
-
"@zhin.js/command": "1.1.
|
|
33
|
-
"@zhin.js/component": "1.1.
|
|
34
|
-
"@zhin.js/layout": "1.1.
|
|
35
|
-
"@zhin.js/mcp-feature": "1.1.
|
|
36
|
-
"@zhin.js/middleware": "1.1.
|
|
37
|
-
"@zhin.js/
|
|
38
|
-
"@zhin.js/
|
|
39
|
-
"@zhin.js/
|
|
40
|
-
"@zhin.js/
|
|
30
|
+
"@zhin.js/adapter": "1.1.17",
|
|
31
|
+
"@zhin.js/agent-feature": "1.1.4",
|
|
32
|
+
"@zhin.js/command": "1.1.5",
|
|
33
|
+
"@zhin.js/component": "1.1.4",
|
|
34
|
+
"@zhin.js/layout": "1.1.4",
|
|
35
|
+
"@zhin.js/mcp-feature": "1.1.4",
|
|
36
|
+
"@zhin.js/middleware": "1.1.4",
|
|
37
|
+
"@zhin.js/page": "1.1.4",
|
|
38
|
+
"@zhin.js/prompt-section": "1.1.3",
|
|
39
|
+
"@zhin.js/skill": "1.1.4",
|
|
40
|
+
"@zhin.js/tool": "1.1.4"
|
|
41
41
|
},
|
|
42
42
|
"repository": {
|
|
43
43
|
"type": "git",
|