@try-works/dsh-tool-mode 0.5.49 → 0.5.51
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/catalog/desert-ant-models.json +84 -55
- package/client/index.js +86 -24
- package/lib/extensions-service.d.ts.map +1 -1
- package/lib/extensions-service.js +10 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +39 -15
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/store.d.ts +63 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/store.d.ts.map +1 -1
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/store.js +226 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/package.json +0 -1
- package/package.json +1 -1
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
"modelSizeMB": null,
|
|
48
48
|
"appleOnly": false,
|
|
49
49
|
"closedBeta": false,
|
|
50
|
-
"verifiedRunnableOnWindows":
|
|
51
|
-
"windowsSupport": "
|
|
50
|
+
"verifiedRunnableOnWindows": true,
|
|
51
|
+
"windowsSupport": "onnxruntime-node",
|
|
52
52
|
"npmPackage": "@desert-ant-labs/clear",
|
|
53
53
|
"npmSubpath": "/native",
|
|
54
54
|
"requiresRuntime": [],
|
|
@@ -58,17 +58,20 @@
|
|
|
58
58
|
"hfRepo": "https://huggingface.co/desert-ant-labs/clear",
|
|
59
59
|
"tool": {
|
|
60
60
|
"name": "enhance_speech",
|
|
61
|
-
"description": "
|
|
61
|
+
"description": "Denoise and dereverb a speech recording on device and return the enhanced 48 kHz mono WAV with honest coverage of the analysed audio.",
|
|
62
62
|
"params": {
|
|
63
|
-
"audio_path": "Absolute path to the
|
|
64
|
-
"output_path": "Absolute path to write the enhanced audio to."
|
|
63
|
+
"audio_path": "Absolute path to the WAV file. Read from the caller's granted filesystem, never uploaded."
|
|
65
64
|
},
|
|
66
|
-
"returns": "
|
|
65
|
+
"returns": "Base64 48 kHz mono WAV, sample rate, duration and coverage."
|
|
67
66
|
},
|
|
68
67
|
"skill": {
|
|
69
68
|
"name": "desert-ant-clear",
|
|
70
69
|
"description": "Enhance noisy speech recordings on device with the Desert Ant Clear model.",
|
|
71
70
|
"whenToUse": "Use when a recording needs denoising, dereverberation or loudness normalization before publication."
|
|
71
|
+
},
|
|
72
|
+
"provider": {
|
|
73
|
+
"extension": "@try-works/extension-clear-recipe",
|
|
74
|
+
"modelId": "clear"
|
|
72
75
|
}
|
|
73
76
|
},
|
|
74
77
|
{
|
|
@@ -119,8 +122,8 @@
|
|
|
119
122
|
"modelSizeMB": null,
|
|
120
123
|
"appleOnly": false,
|
|
121
124
|
"closedBeta": false,
|
|
122
|
-
"verifiedRunnableOnWindows":
|
|
123
|
-
"windowsSupport": "
|
|
125
|
+
"verifiedRunnableOnWindows": true,
|
|
126
|
+
"windowsSupport": "onnxruntime-node",
|
|
124
127
|
"npmPackage": "@desert-ant-labs/ear",
|
|
125
128
|
"npmSubpath": "/native",
|
|
126
129
|
"requiresRuntime": [],
|
|
@@ -129,17 +132,25 @@
|
|
|
129
132
|
"docsUrl": "https://desertant.com/models/ear/",
|
|
130
133
|
"hfRepo": "https://huggingface.co/desert-ant-labs/ear",
|
|
131
134
|
"tool": {
|
|
132
|
-
"name": "
|
|
133
|
-
"description": "Identify
|
|
135
|
+
"name": "identify_language",
|
|
136
|
+
"description": "Identify the spoken language of an audio recording on device: the most likely language, its confidence, a reliability flag and the top candidates.",
|
|
134
137
|
"params": {
|
|
135
|
-
"audio_path": "Absolute path to the
|
|
138
|
+
"audio_path": "Absolute path to the WAV file. Read from the caller's granted filesystem, never uploaded.",
|
|
139
|
+
"windows": {
|
|
140
|
+
"description": "How many 30 second windows to listen to, spread across the recording and ranked by syllabic modulation. Defaults to 3.",
|
|
141
|
+
"type": "integer"
|
|
142
|
+
}
|
|
136
143
|
},
|
|
137
|
-
"returns": "
|
|
144
|
+
"returns": "language, confidence, isReliable, ranked candidates and window timings."
|
|
138
145
|
},
|
|
139
146
|
"skill": {
|
|
140
147
|
"name": "desert-ant-ear",
|
|
141
148
|
"description": "Identify the spoken language of a recording on device with the Desert Ant Ear model.",
|
|
142
149
|
"whenToUse": "Use to pick a transcription language or route audio before running speech recognition."
|
|
150
|
+
},
|
|
151
|
+
"provider": {
|
|
152
|
+
"extension": "@try-works/extension-ear-recipe",
|
|
153
|
+
"modelId": "ear"
|
|
143
154
|
}
|
|
144
155
|
},
|
|
145
156
|
{
|
|
@@ -154,8 +165,8 @@
|
|
|
154
165
|
"modelSizeMB": 10.2,
|
|
155
166
|
"appleOnly": false,
|
|
156
167
|
"closedBeta": false,
|
|
157
|
-
"verifiedRunnableOnWindows":
|
|
158
|
-
"windowsSupport": "
|
|
168
|
+
"verifiedRunnableOnWindows": true,
|
|
169
|
+
"windowsSupport": "onnxruntime-node",
|
|
159
170
|
"npmPackage": "@desert-ant-labs/emo",
|
|
160
171
|
"npmSubpath": "/native",
|
|
161
172
|
"requiresRuntime": [],
|
|
@@ -164,21 +175,25 @@
|
|
|
164
175
|
"docsUrl": "https://desertant.com/models/emo/",
|
|
165
176
|
"hfRepo": "https://huggingface.co/desert-ant-labs/emo",
|
|
166
177
|
"tool": {
|
|
167
|
-
"name": "
|
|
168
|
-
"description": "Suggest
|
|
178
|
+
"name": "suggest_emojis",
|
|
179
|
+
"description": "Suggest emojis for a piece of text on device: the top labels by probability with their confidences.",
|
|
169
180
|
"params": {
|
|
170
|
-
"text": "The text to suggest
|
|
181
|
+
"text": "The text to suggest emojis for, counted in Unicode code points, 1..1024. Empty or whitespace-only text is refused.",
|
|
171
182
|
"limit": {
|
|
172
|
-
"description": "
|
|
183
|
+
"description": "How many suggestions to return: the top labels by descending probability. Defaults to 5.",
|
|
173
184
|
"type": "integer"
|
|
174
185
|
}
|
|
175
186
|
},
|
|
176
|
-
"returns": "
|
|
187
|
+
"returns": "Top emoji labels by probability with confidences."
|
|
177
188
|
},
|
|
178
189
|
"skill": {
|
|
179
190
|
"name": "desert-ant-emo",
|
|
180
191
|
"description": "Suggest fitting emoji for text with the Desert Ant Emo model.",
|
|
181
192
|
"whenToUse": "Use when writing release notes, commit summaries or UI copy that should carry emoji."
|
|
193
|
+
},
|
|
194
|
+
"provider": {
|
|
195
|
+
"extension": "@try-works/extension-emo-recipe",
|
|
196
|
+
"modelId": "emo"
|
|
182
197
|
}
|
|
183
198
|
},
|
|
184
199
|
{
|
|
@@ -313,8 +328,8 @@
|
|
|
313
328
|
"modelSizeMB": 9.2,
|
|
314
329
|
"appleOnly": false,
|
|
315
330
|
"closedBeta": false,
|
|
316
|
-
"verifiedRunnableOnWindows":
|
|
317
|
-
"windowsSupport": "
|
|
331
|
+
"verifiedRunnableOnWindows": true,
|
|
332
|
+
"windowsSupport": "onnxruntime-node",
|
|
318
333
|
"npmPackage": "@desert-ant-labs/moderator",
|
|
319
334
|
"npmSubpath": "/native",
|
|
320
335
|
"requiresRuntime": [],
|
|
@@ -323,20 +338,27 @@
|
|
|
323
338
|
"docsUrl": "https://desertant.com/models/moderator/",
|
|
324
339
|
"hfRepo": "https://huggingface.co/desert-ant-labs/moderator",
|
|
325
340
|
"tool": {
|
|
326
|
-
"name": "
|
|
327
|
-
"description": "Check
|
|
341
|
+
"name": "classify_nsfw",
|
|
342
|
+
"description": "Check an image for nudity or sexual content on device: per-region scores, an NSFW decision at a threshold, and the policy and quality used.",
|
|
328
343
|
"params": {
|
|
329
|
-
"
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
344
|
+
"image_path": "Absolute path to the PNG file. Read from the caller's granted filesystem, never uploaded.",
|
|
345
|
+
"quality": "How many crops to score: fast = 1 center crop, balanced = 4 crops, accurate = 8 crops. Defaults to balanced.",
|
|
346
|
+
"threshold": {
|
|
347
|
+
"description": "Decision threshold; isNSFW is true when score >= threshold. Defaults to 0.5.",
|
|
348
|
+
"type": "number"
|
|
349
|
+
},
|
|
350
|
+
"policy": "standard counts all five heads; allowTopless counts all but nipples. Defaults to standard."
|
|
333
351
|
},
|
|
334
|
-
"returns": "
|
|
352
|
+
"returns": "isNSFW, score, threshold, policy, quality, per-region scores and crops."
|
|
335
353
|
},
|
|
336
354
|
"skill": {
|
|
337
355
|
"name": "desert-ant-moderator",
|
|
338
356
|
"description": "Screen images for NSFW content on device with the Desert Ant Moderator model.",
|
|
339
357
|
"whenToUse": "Use to gate user-supplied images before storing, publishing or sending them anywhere."
|
|
358
|
+
},
|
|
359
|
+
"provider": {
|
|
360
|
+
"extension": "@try-works/extension-moderator-recipe",
|
|
361
|
+
"modelId": "moderator"
|
|
340
362
|
}
|
|
341
363
|
},
|
|
342
364
|
{
|
|
@@ -351,8 +373,8 @@
|
|
|
351
373
|
"modelSizeMB": null,
|
|
352
374
|
"appleOnly": false,
|
|
353
375
|
"closedBeta": false,
|
|
354
|
-
"verifiedRunnableOnWindows":
|
|
355
|
-
"windowsSupport": "
|
|
376
|
+
"verifiedRunnableOnWindows": true,
|
|
377
|
+
"windowsSupport": "native-node",
|
|
356
378
|
"npmPackage": "@desert-ant-labs/redact",
|
|
357
379
|
"npmSubpath": "/native",
|
|
358
380
|
"requiresRuntime": [],
|
|
@@ -361,25 +383,21 @@
|
|
|
361
383
|
"docsUrl": "https://desertant.com/models/redact/",
|
|
362
384
|
"hfRepo": "https://huggingface.co/desert-ant-labs/redact",
|
|
363
385
|
"tool": {
|
|
364
|
-
"name": "
|
|
365
|
-
"description": "
|
|
386
|
+
"name": "redact_text",
|
|
387
|
+
"description": "Detect PII and secrets in text as labelled UTF-16 spans, with honest coverage when the local window cap truncates a long document.",
|
|
366
388
|
"params": {
|
|
367
|
-
"text": "The text to redact."
|
|
368
|
-
"labels": {
|
|
369
|
-
"description": "Optional list of entity labels to restrict redaction to, for example [\"EMAIL\", \"PHONE\"].",
|
|
370
|
-
"type": "string[]"
|
|
371
|
-
},
|
|
372
|
-
"minimum_confidence": {
|
|
373
|
-
"description": "Optional confidence floor between 0 and 1 (default 0.6).",
|
|
374
|
-
"type": "number"
|
|
375
|
-
}
|
|
389
|
+
"text": "The text to redact. Long documents are processed up to the local window cap; coverage reports truncation."
|
|
376
390
|
},
|
|
377
|
-
"returns": "
|
|
391
|
+
"returns": "Labelled UTF-16 spans and coverage of the analysed text."
|
|
378
392
|
},
|
|
379
393
|
"skill": {
|
|
380
394
|
"name": "desert-ant-redact",
|
|
381
395
|
"description": "Strip personal data from text on device with the Desert Ant Redact model before sending it to any remote service.",
|
|
382
396
|
"whenToUse": "Use before sending logs, transcripts, tickets or documents containing names, emails or numbers to a remote model or API."
|
|
397
|
+
},
|
|
398
|
+
"provider": {
|
|
399
|
+
"extension": "@try-works/extension-redact",
|
|
400
|
+
"modelId": "redact"
|
|
383
401
|
}
|
|
384
402
|
},
|
|
385
403
|
{
|
|
@@ -430,8 +448,8 @@
|
|
|
430
448
|
"modelSizeMB": null,
|
|
431
449
|
"appleOnly": false,
|
|
432
450
|
"closedBeta": false,
|
|
433
|
-
"verifiedRunnableOnWindows":
|
|
434
|
-
"windowsSupport": "
|
|
451
|
+
"verifiedRunnableOnWindows": true,
|
|
452
|
+
"windowsSupport": "native-node",
|
|
435
453
|
"npmPackage": "@desert-ant-labs/shapes",
|
|
436
454
|
"npmSubpath": "/native",
|
|
437
455
|
"requiresRuntime": [],
|
|
@@ -440,18 +458,25 @@
|
|
|
440
458
|
"docsUrl": "https://desertant.com/models/shapes/",
|
|
441
459
|
"hfRepo": "https://huggingface.co/desert-ant-labs/shapes",
|
|
442
460
|
"tool": {
|
|
443
|
-
"name": "
|
|
444
|
-
"description": "
|
|
461
|
+
"name": "shape_recognize",
|
|
462
|
+
"description": "Recognize a single hand-drawn stroke as one of the Shapes classes and return the ranked candidates with confidences.",
|
|
445
463
|
"params": {
|
|
446
|
-
"points": "The stroke as an array of [x, y] points
|
|
447
|
-
"closed":
|
|
464
|
+
"points": "The stroke in drawing order as an array of [x, y] points (first stroke only).",
|
|
465
|
+
"closed": {
|
|
466
|
+
"description": "Whether the stroke was drawn closed; the fitted-geometry gates use it.",
|
|
467
|
+
"type": "boolean"
|
|
468
|
+
}
|
|
448
469
|
},
|
|
449
|
-
"returns": "The recognized shape
|
|
470
|
+
"returns": "The recognized shape, its confidence, the ranked candidates and rejected labels."
|
|
450
471
|
},
|
|
451
472
|
"skill": {
|
|
452
473
|
"name": "desert-ant-shapes",
|
|
453
474
|
"description": "Recognize hand-drawn strokes as clean shapes with the Desert Ant Shapes model.",
|
|
454
475
|
"whenToUse": "Use in drawing or diagram tooling to snap an ink stroke to a geometric shape."
|
|
476
|
+
},
|
|
477
|
+
"provider": {
|
|
478
|
+
"extension": "@try-works/extension-shapes-recipe",
|
|
479
|
+
"modelId": "shapes"
|
|
455
480
|
}
|
|
456
481
|
},
|
|
457
482
|
{
|
|
@@ -585,10 +610,10 @@
|
|
|
585
610
|
"output": "[{ start, end, word }] filler spans to cut",
|
|
586
611
|
"languages": null,
|
|
587
612
|
"modelSizeMB": null,
|
|
588
|
-
"appleOnly":
|
|
613
|
+
"appleOnly": false,
|
|
589
614
|
"closedBeta": false,
|
|
590
|
-
"verifiedRunnableOnWindows":
|
|
591
|
-
"windowsSupport": "
|
|
615
|
+
"verifiedRunnableOnWindows": true,
|
|
616
|
+
"windowsSupport": "onnxruntime-node",
|
|
592
617
|
"npmPackage": null,
|
|
593
618
|
"npmSubpath": null,
|
|
594
619
|
"requiresRuntime": [],
|
|
@@ -598,16 +623,20 @@
|
|
|
598
623
|
"hfRepo": "https://huggingface.co/desert-ant-labs/uhm",
|
|
599
624
|
"tool": {
|
|
600
625
|
"name": "detect_fillers",
|
|
601
|
-
"description": "Find every um,
|
|
626
|
+
"description": "Find every uh, um, hmm and filler \"and\" in a recording on device and return the millisecond spans to cut, with honest coverage.",
|
|
602
627
|
"params": {
|
|
603
|
-
"audio_path": "Absolute path to the audio
|
|
628
|
+
"audio_path": "Absolute path to the audio to analyse. Read from the caller's granted filesystem, never uploaded."
|
|
604
629
|
},
|
|
605
|
-
"returns": "
|
|
630
|
+
"returns": "Millisecond filler spans to cut, plus coverage."
|
|
606
631
|
},
|
|
607
632
|
"skill": {
|
|
608
633
|
"name": "desert-ant-uhm",
|
|
609
634
|
"description": "Detect filler words in speech on device with the Desert Ant Uhm model.",
|
|
610
635
|
"whenToUse": "Use when editing spoken audio to remove hesitations and tighten a transcript."
|
|
636
|
+
},
|
|
637
|
+
"provider": {
|
|
638
|
+
"extension": "@try-works/extension-uhm-recipe",
|
|
639
|
+
"modelId": "uhm"
|
|
611
640
|
}
|
|
612
641
|
},
|
|
613
642
|
{
|
package/client/index.js
CHANGED
|
@@ -2233,12 +2233,11 @@ function createToolInsights(createElement, reactLib) {
|
|
|
2233
2233
|
"name": "Clear",
|
|
2234
2234
|
"summary": "On-device speech enhancement: denoise, dereverb and loudness-normalize to 48 kHz.",
|
|
2235
2235
|
"package": "@desert-ant-labs/clear",
|
|
2236
|
-
"extension":
|
|
2236
|
+
"extension": "@try-works/extension-clear-recipe",
|
|
2237
2237
|
"capability": "audio.speech-enhancement",
|
|
2238
2238
|
"sizeMB": null,
|
|
2239
2239
|
"license": "source-available",
|
|
2240
|
-
"runnable":
|
|
2241
|
-
"reason": "Clear has no prebuilt native build for win32-x64: @desert-ant-labs/clear/native supports linux-x64, linux-arm64 and darwin-arm64 only."
|
|
2240
|
+
"runnable": true
|
|
2242
2241
|
},
|
|
2243
2242
|
{
|
|
2244
2243
|
"id": "clips",
|
|
@@ -2257,24 +2256,22 @@ function createToolInsights(createElement, reactLib) {
|
|
|
2257
2256
|
"name": "Ear",
|
|
2258
2257
|
"summary": "On-device spoken language identification across 102 languages from a short audio stretch.",
|
|
2259
2258
|
"package": "@desert-ant-labs/ear",
|
|
2260
|
-
"extension":
|
|
2259
|
+
"extension": "@try-works/extension-ear-recipe",
|
|
2261
2260
|
"capability": "audio.spoken-language-identification",
|
|
2262
2261
|
"sizeMB": null,
|
|
2263
2262
|
"license": "source-available",
|
|
2264
|
-
"runnable":
|
|
2265
|
-
"reason": "Ear has no prebuilt native build for win32-x64: @desert-ant-labs/ear/native supports linux-x64, linux-arm64 and darwin-arm64 only."
|
|
2263
|
+
"runnable": true
|
|
2266
2264
|
},
|
|
2267
2265
|
{
|
|
2268
2266
|
"id": "emo",
|
|
2269
2267
|
"name": "Emo",
|
|
2270
2268
|
"summary": "Type a task or message and get the emoji that fit, in 22 languages, on the device.",
|
|
2271
2269
|
"package": "@desert-ant-labs/emo",
|
|
2272
|
-
"extension":
|
|
2270
|
+
"extension": "@try-works/extension-emo-recipe",
|
|
2273
2271
|
"capability": "text.emoji-suggestion",
|
|
2274
2272
|
"sizeMB": 10.2,
|
|
2275
2273
|
"license": "source-available",
|
|
2276
|
-
"runnable":
|
|
2277
|
-
"reason": "Emo has no prebuilt native build for win32-x64: @desert-ant-labs/emo/native supports linux-x64, linux-arm64 and darwin-arm64 only."
|
|
2274
|
+
"runnable": true
|
|
2278
2275
|
},
|
|
2279
2276
|
{
|
|
2280
2277
|
"id": "eye",
|
|
@@ -2317,24 +2314,22 @@ function createToolInsights(createElement, reactLib) {
|
|
|
2317
2314
|
"name": "Moderator",
|
|
2318
2315
|
"summary": "On-device NSFW detection that flags nudity before upload, trained only on licensed and synthetic data.",
|
|
2319
2316
|
"package": "@desert-ant-labs/moderator",
|
|
2320
|
-
"extension":
|
|
2317
|
+
"extension": "@try-works/extension-moderator-recipe",
|
|
2321
2318
|
"capability": "image.nsfw-detection",
|
|
2322
2319
|
"sizeMB": 9.2,
|
|
2323
2320
|
"license": "source-available",
|
|
2324
|
-
"runnable":
|
|
2325
|
-
"reason": "Moderator has no prebuilt native build for win32-x64: @desert-ant-labs/moderator/native supports linux-x64, linux-arm64 and darwin-arm64 only."
|
|
2321
|
+
"runnable": true
|
|
2326
2322
|
},
|
|
2327
2323
|
{
|
|
2328
2324
|
"id": "redact",
|
|
2329
2325
|
"name": "Redact",
|
|
2330
2326
|
"summary": "On-device redaction that strips personal data as you type, in 27 languages, with restore support.",
|
|
2331
2327
|
"package": "@desert-ant-labs/redact",
|
|
2332
|
-
"extension":
|
|
2328
|
+
"extension": "@try-works/extension-redact",
|
|
2333
2329
|
"capability": "text.pii-redaction",
|
|
2334
2330
|
"sizeMB": null,
|
|
2335
2331
|
"license": "source-available",
|
|
2336
|
-
"runnable":
|
|
2337
|
-
"reason": "Redact has no prebuilt native build for win32-x64: @desert-ant-labs/redact/native supports linux-x64, linux-arm64 and darwin-arm64 only."
|
|
2332
|
+
"runnable": true
|
|
2338
2333
|
},
|
|
2339
2334
|
{
|
|
2340
2335
|
"id": "schemer",
|
|
@@ -2353,12 +2348,11 @@ function createToolInsights(createElement, reactLib) {
|
|
|
2353
2348
|
"name": "Shapes",
|
|
2354
2349
|
"summary": "On-device shape recognition that turns one hand-drawn stroke into a rectangle, ellipse, triangle, star or line in under 10ms.",
|
|
2355
2350
|
"package": "@desert-ant-labs/shapes",
|
|
2356
|
-
"extension":
|
|
2351
|
+
"extension": "@try-works/extension-shapes-recipe",
|
|
2357
2352
|
"capability": "stroke.shape-recognition",
|
|
2358
2353
|
"sizeMB": null,
|
|
2359
2354
|
"license": "source-available",
|
|
2360
|
-
"runnable":
|
|
2361
|
-
"reason": "Shapes has no prebuilt native build for win32-x64: @desert-ant-labs/shapes/native supports linux-x64, linux-arm64 and darwin-arm64 only."
|
|
2355
|
+
"runnable": true
|
|
2362
2356
|
},
|
|
2363
2357
|
{
|
|
2364
2358
|
"id": "title",
|
|
@@ -2400,12 +2394,11 @@ function createToolInsights(createElement, reactLib) {
|
|
|
2400
2394
|
"name": "Uhm",
|
|
2401
2395
|
"summary": "On-device filler detection that marks every um, uh and hmm to within 20ms, an hour of audio in 12s.",
|
|
2402
2396
|
"package": null,
|
|
2403
|
-
"extension":
|
|
2397
|
+
"extension": "@try-works/extension-uhm-recipe",
|
|
2404
2398
|
"capability": "audio.filler-detection",
|
|
2405
2399
|
"sizeMB": null,
|
|
2406
2400
|
"license": "source-available",
|
|
2407
|
-
"runnable":
|
|
2408
|
-
"reason": "Uhm is Apple-only (Core ML/MLX through the Swift package); there is no JavaScript SDK, so it cannot run in a Node process. Point `remote.endpoint` at a bridge on an Apple machine to reach it."
|
|
2401
|
+
"runnable": true
|
|
2409
2402
|
},
|
|
2410
2403
|
{
|
|
2411
2404
|
"id": "voz",
|
|
@@ -3285,9 +3278,72 @@ function createToolInsights(createElement, reactLib) {
|
|
|
3285
3278
|
}
|
|
3286
3279
|
}
|
|
3287
3280
|
|
|
3288
|
-
/**
|
|
3289
|
-
|
|
3290
|
-
|
|
3281
|
+
/** How long a normalized describe() snapshot is reused before a real host read. */
|
|
3282
|
+
const REMOTE_SNAPSHOT_TTL_MS = 5000
|
|
3283
|
+
|
|
3284
|
+
/**
|
|
3285
|
+
* Per-namespace read state: one in-flight promise, the last snapshot and when
|
|
3286
|
+
* it was taken. A WeakMap because the namespace object is the mounted Remote;
|
|
3287
|
+
* entries disappear with it.
|
|
3288
|
+
*/
|
|
3289
|
+
const extensionReads = new WeakMap()
|
|
3290
|
+
|
|
3291
|
+
/** The read state for one namespace, created on first use. */
|
|
3292
|
+
function extensionReadState(namespace) {
|
|
3293
|
+
let state = extensionReads.get(namespace)
|
|
3294
|
+
if (state === undefined) {
|
|
3295
|
+
state = { inFlight: null, snapshot: null, at: 0, generation: 0 }
|
|
3296
|
+
extensionReads.set(namespace, state)
|
|
3297
|
+
}
|
|
3298
|
+
return state
|
|
3299
|
+
}
|
|
3300
|
+
|
|
3301
|
+
/**
|
|
3302
|
+
* Read one extension state snapshot, coalesced per namespace.
|
|
3303
|
+
*
|
|
3304
|
+
* The page reads from four places (mount, Recheck, the post-action re-read and
|
|
3305
|
+
* its follow-up); each would otherwise pay the host's describe, which can take
|
|
3306
|
+
* minutes on a large store. Concurrent callers share one in-flight promise, a
|
|
3307
|
+
* caller within REMOTE_SNAPSHOT_TTL_MS of the last answer gets that snapshot,
|
|
3308
|
+
* and a rejection is never cached, so a retry reaches the host again.
|
|
3309
|
+
*/
|
|
3310
|
+
function describeExtensions(namespace) {
|
|
3311
|
+
const state = extensionReadState(namespace)
|
|
3312
|
+
if (state.inFlight !== null) return state.inFlight
|
|
3313
|
+
if (state.snapshot !== null && Date.now() - state.at < REMOTE_SNAPSHOT_TTL_MS) {
|
|
3314
|
+
return Promise.resolve(state.snapshot)
|
|
3315
|
+
}
|
|
3316
|
+
const generation = state.generation
|
|
3317
|
+
const read = (async () => {
|
|
3318
|
+
try {
|
|
3319
|
+
const described = normalizeDescribe(unwrapRemoteResult(await namespace.describe()))
|
|
3320
|
+
// Publish only an answer the current state still wants: an invalidation
|
|
3321
|
+
// that arrived while this read was in flight must win over it.
|
|
3322
|
+
if (state.generation === generation) {
|
|
3323
|
+
state.snapshot = described
|
|
3324
|
+
state.at = Date.now()
|
|
3325
|
+
}
|
|
3326
|
+
return described
|
|
3327
|
+
} finally {
|
|
3328
|
+
if (state.inFlight === read) state.inFlight = null
|
|
3329
|
+
}
|
|
3330
|
+
})()
|
|
3331
|
+
state.inFlight = read
|
|
3332
|
+
return read
|
|
3333
|
+
}
|
|
3334
|
+
|
|
3335
|
+
/**
|
|
3336
|
+
* Drop the cached and in-flight read state for a namespace.
|
|
3337
|
+
*
|
|
3338
|
+
* Called after install/enable/disable/prepare and by Recheck ("Try again"):
|
|
3339
|
+
* after an action the page must read the host, not a snapshot from before it.
|
|
3340
|
+
*/
|
|
3341
|
+
function invalidateExtensionState(namespace) {
|
|
3342
|
+
const state = extensionReadState(namespace)
|
|
3343
|
+
state.generation += 1
|
|
3344
|
+
state.inFlight = null
|
|
3345
|
+
state.snapshot = null
|
|
3346
|
+
state.at = 0
|
|
3291
3347
|
}
|
|
3292
3348
|
|
|
3293
3349
|
/**
|
|
@@ -3902,6 +3958,7 @@ function createToolInsights(createElement, reactLib) {
|
|
|
3902
3958
|
setExtRemote({ kind: 'absent' })
|
|
3903
3959
|
return
|
|
3904
3960
|
}
|
|
3961
|
+
invalidateExtensionState(namespace)
|
|
3905
3962
|
try {
|
|
3906
3963
|
setExtRemote({ kind: 'ready', namespace, ...(await describeExtensions(namespace)) })
|
|
3907
3964
|
} catch (error) {
|
|
@@ -3959,6 +4016,7 @@ function createToolInsights(createElement, reactLib) {
|
|
|
3959
4016
|
unwrapRemoteResult(await namespace.disable(id))
|
|
3960
4017
|
await dualWriteDisabledExtensions(id, 'disable')
|
|
3961
4018
|
}
|
|
4019
|
+
invalidateExtensionState(namespace)
|
|
3962
4020
|
setExtRemote({ kind: 'ready', namespace, ...(await describeExtensions(namespace)) })
|
|
3963
4021
|
// A store write and the following describe can land in either order
|
|
3964
4022
|
// under load. One bounded re-read after a successful action settles
|
|
@@ -3970,6 +4028,7 @@ function createToolInsights(createElement, reactLib) {
|
|
|
3970
4028
|
try {
|
|
3971
4029
|
const settled = modelToolsRemote(ctx, mounted())
|
|
3972
4030
|
if (settled !== null) {
|
|
4031
|
+
invalidateExtensionState(settled)
|
|
3973
4032
|
setExtRemote({ kind: 'ready', namespace: settled, ...(await describeExtensions(settled)) })
|
|
3974
4033
|
}
|
|
3975
4034
|
} catch (settleError) {
|
|
@@ -3984,6 +4043,7 @@ function createToolInsights(createElement, reactLib) {
|
|
|
3984
4043
|
try {
|
|
3985
4044
|
const namespace = modelToolsRemote(ctx, mounted())
|
|
3986
4045
|
if (namespace !== null) {
|
|
4046
|
+
invalidateExtensionState(namespace)
|
|
3987
4047
|
setExtRemote({ kind: 'ready', namespace, ...(await describeExtensions(namespace)) })
|
|
3988
4048
|
}
|
|
3989
4049
|
} catch (readError) {
|
|
@@ -4202,6 +4262,8 @@ function createToolInsights(createElement, reactLib) {
|
|
|
4202
4262
|
unwrapRemoteResult,
|
|
4203
4263
|
normalizeDescribe,
|
|
4204
4264
|
describeExtensions,
|
|
4265
|
+
invalidateExtensionState,
|
|
4266
|
+
REMOTE_SNAPSHOT_TTL_MS,
|
|
4205
4267
|
findExtensionState,
|
|
4206
4268
|
nextDisabledExtensions,
|
|
4207
4269
|
extensionRequirements,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extensions-service.d.ts","sourceRoot":"","sources":["../src/extensions-service.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"extensions-service.d.ts","sourceRoot":"","sources":["../src/extensions-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1014,12 +1014,22 @@ export class ExtensionsService {
|
|
|
1014
1014
|
requirements.push(requirement('platform', false, `the extension supports ${input.facts.platforms.map(platformLabel).join(', ')} but this host is ${process.platform}/${process.arch}`, 'none'));
|
|
1015
1015
|
}
|
|
1016
1016
|
// INTEGRITY: the installed bytes must still be the recorded bytes.
|
|
1017
|
+
//
|
|
1018
|
+
// SKIPPED is not FAILED. describeFast() does not digest installed trees (a 4.6 GB
|
|
1019
|
+
// store would stall the page for minutes), so it reports integrity 'unknown' with no
|
|
1020
|
+
// reason. That is absence of evidence, not evidence of tampering: the digest is
|
|
1021
|
+
// verified when the extension activates, and the full describe() still reports it.
|
|
1022
|
+
// Only a real verification verdict — 'changed', or 'unknown' WITH a reason, which is
|
|
1023
|
+
// the digest pass itself failing — may block the row.
|
|
1017
1024
|
if (!input.installed) {
|
|
1018
1025
|
requirements.push(requirement('integrity', true, 'the extension is not installed, so there are no installed bytes to verify'));
|
|
1019
1026
|
}
|
|
1020
1027
|
else if (input.integrity === 'unchanged') {
|
|
1021
1028
|
requirements.push(requirement('integrity', true, 'the installed content matches the recorded digest'));
|
|
1022
1029
|
}
|
|
1030
|
+
else if (input.integrity === 'unknown' && input.integrityReason === null) {
|
|
1031
|
+
requirements.push(requirement('integrity', true, 'integrity verification was skipped for this page read; the installed digest is verified when the extension activates'));
|
|
1032
|
+
}
|
|
1023
1033
|
else {
|
|
1024
1034
|
requirements.push(requirement('integrity', false, input.integrityReason ?? `the installed content's integrity is ${input.integrity}`, 'install'));
|
|
1025
1035
|
}
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,CAAC,MAAM,0BAA0B,CAAA;AAMxC,OAAO,EAAqB,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAyBvE,OAAO,EAAoH,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAC5K,OAAO,EAAsF,KAAK,SAAS,EAAE,MAAM,UAAU,CAAA;AAG7H,OAAO,EAAoG,KAAK,WAAW,EAAuB,MAAM,8BAA8B,CAAA;AA8CtL,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAa/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AAiC9D,eAAO,MAAM,IAAI,gBAAgB,CAAA;AACjC,eAAO,MAAM,MAAM,UAAY,CAAA;AAmB/B,4BAA4B;AAC5B,MAAM,WAAW,MAAM;IACrB,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,oEAAoE;IACpE,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,2DAA2D;IAC3D,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,gEAAgE;IAChE,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC5B;;;;;;;;;OASG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;OAIG;IACH,aAAa,CAAC,EAAE,KAAK,GAAG,YAAY,CAAA;IACpC;;;;OAIG;IACH,GAAG,CAAC,EAAE;QACJ,0EAA0E;QAC1E,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB,0DAA0D;QAC1D,OAAO,CAAC,EAAE,MAAM,CAAA;KACjB,CAAA;IACD;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE;QACP,mEAAmE;QACnE,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,gDAAgD;QAChD,KAAK,CAAC,EAAE,MAAM,CAAA;KACf,CAAA;IACD;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,gFAAgF;IAChF,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;;;;;;;;;;;;OAaG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B;;;;;;;;;;;OAWG;IACH,sBAAsB,CAAC,EAAE,UAAU,GAAG,WAAW,GAAG,MAAM,CAAA;IAC1D;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,0EAA0E;IAC1E,wBAAwB,CAAC,EAAE,MAAM,CAAA;IACjC;;;OAGG;IACH,yBAAyB,CAAC,EAAE,MAAM,CAAA;IAClC,+DAA+D;IAC/D,0BAA0B,CAAC,EAAE,MAAM,CAAA;IACnC;;;;;;OAMG;IACH,wBAAwB,CAAC,EAAE,MAAM,CAAA;IACjC;;;OAGG;IACH,2BAA2B,CAAC,EAAE,MAAM,CAAA;IACpC;;;;;;;;;;OAUG;IACH,6BAA6B,CAAC,EAAE,OAAO,CAAA;IACvC;;;;;;;OAOG;IACH,4BAA4B,CAAC,EAAE,MAAM,CAAA;IACrC;;;;;OAKG;IACH,2BAA2B,CAAC,EAAE,MAAM,EAAE,CAAA;IACtC;;;;;;;;;;;;;OAaG;IACH,0BAA0B,CAAC,EAAE,OAAO,CAAA;IACpC;;;;;;;;OAQG;IACH,yBAAyB,CAAC,EAAE,OAAO,CAAA;IACnC;;;6DAGyD;IACzD,kBAAkB,CAAC,EAAE,MAAM,iBAAiB,CAAA;IAC5C,mFAAmF;IACnF,sBAAsB,CAAC,EAAE,MAAM,CAAA;IAC/B,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B;;;;;;OAMG;IACH,qBAAqB,CAAC,EAAE;QACtB,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,KAAK,OAAO,CAAA;QACzD,aAAa,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAA;KACzC,CAAA;IACD;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,2EAA2E;IAC3E,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;IAC9C,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,UAAU,CAAC,EAAE;QACX,aAAa,CAAC,EAAE,MAAM,CAAA;QACtB,eAAe,CAAC,EAAE,MAAM,CAAA;QACxB,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,kBAAkB,CAAC,EAAE,OAAO,CAAA;QAC5B,kBAAkB,CAAC,EAAE,OAAO,CAAA;QAC5B,sBAAsB,CAAC,EAAE,OAAO,CAAA;QAChC,gBAAgB,CAAC,EAAE,OAAO,CAAA;QAC1B,iBAAiB,CAAC,EAAE,OAAO,CAAA;KAC5B,CAAA;IACD,KAAK,CAAC,EAAE;QACN,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;QAC3B,mBAAmB,CAAC,EAAE,OAAO,CAAA;QAC7B,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,IAAI,CAAC,EAAE,MAAM,CAAA;QACb;;;;;;WAMG;QACH,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;QACzB;;;;WAIG;QACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;QACtB,qFAAqF;QACrF,MAAM,CAAC,EAAE,iBAAiB,CAAA;QAC1B,YAAY,CAAC,EAAE,MAAM,CAAA;QACrB,iBAAiB,CAAC,EAAE,MAAM,CAAA;QAC1B,IAAI,CAAC,EAAE;YAAE,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,0BAA0B,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;SAAE,CAAA;KACrE,CAAA;IACD,aAAa,CAAC,EAAE;QACd,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB,gBAAgB,CAAC,EAAE,MAAM,CAAA;QACzB,YAAY,CAAC,EAAE,MAAM,CAAA;QACrB,YAAY,CAAC,EAAE,MAAM,CAAA;QACrB,qBAAqB,CAAC,EAAE,MAAM,CAAA;QAC9B,oBAAoB,CAAC,EAAE,MAAM,CAAA;KAC9B,CAAA;IACD,YAAY,CAAC,EAAE;QACb,iBAAiB,CAAC,EAAE,MAAM,CAAA;QAC1B,eAAe,CAAC,EAAE,MAAM,CAAA;QACxB,cAAc,CAAC,EAAE,MAAM,CAAA;QACvB,iBAAiB,CAAC,EAAE,MAAM,CAAA;QAC1B,uBAAuB,CAAC,EAAE,OAAO,CAAA;KAClC,CAAA;IACD,iBAAiB,CAAC,EAAE;QAClB,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB,eAAe,CAAC,EAAE,MAAM,CAAA;QACxB,sBAAsB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACtC,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,CAAA;QAC9C,kBAAkB,CAAC,EAAE,MAAM,CAAA;QAC3B,qBAAqB,CAAC,EAAE,MAAM,CAAA;QAC9B,sBAAsB,CAAC,EAAE,MAAM,CAAA;QAC/B,gBAAgB,CAAC,EAAE,MAAM,CAAA;QACzB,mBAAmB,CAAC,EAAE,OAAO,CAAA;QAC7B,mBAAmB,CAAC,EAAE,OAAO,CAAA;KAC9B,CAAA;IACD,SAAS,CAAC,EAAE;QACV,aAAa,CAAC,EAAE,MAAM,CAAA;QACtB,mBAAmB,CAAC,EAAE,OAAO,CAAA;QAC7B,mBAAmB,CAAC,EAAE,OAAO,CAAA;QAC7B,wBAAwB,CAAC,EAAE,OAAO,CAAA;KACnC,CAAA;IACD,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,CAAA;IAC/C,SAAS,CAAC,EAAE;QACV,MAAM,CAAC,EAAE,OAAO,CAAA;QAChB,aAAa,CAAC,EAAE,MAAM,CAAA;QACtB,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,mBAAmB,CAAC,EAAE;YAAE,OAAO,CAAC,EAAE,OAAO,CAAC;YAAC,aAAa,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KACpE,CAAA;IACD;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAClC;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,+DAA+D;IAC/D,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,UAAU,GAAG,eAAe,CAAA;IAC7C;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,WAAW,CAAA;IAC7B;;;;OAIG;IACH,eAAe,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAA;IACxG;;;;;;;;;;OAUG;IACH,YAAY,CAAC,EAAE,kBAAkB,CAAA;IACjC;;;;;;;;OAQG;IACH,GAAG,CAAC,EAAE,SAAS,CAAA;IACf;;;;;;;;;;;OAWG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,mFAAmF;IACnF,4BAA4B,CAAC,EAAE,MAAM,CAAA;IACrC;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC7B;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC/B,iEAAiE;IACjE,MAAM,CAAC,EAAE;QACP,aAAa,CAAC,EAAE,MAAM,CAAA;QACtB,eAAe,CAAC,EAAE,MAAM,CAAA;QACxB,cAAc,CAAC,EAAE,MAAM,CAAA;QACvB,aAAa,CAAC,EAAE,MAAM,CAAA;QACtB,eAAe,CAAC,EAAE,MAAM,CAAA;QACxB,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,UAAU,CAAC,EAAE,MAAM,CAAA;KACpB,CAAA;CACF;AAkBD,eAAO,MAAM,MAAM,EAAE,CAAC,CAAC,MAAM,CA+L3B,CAAA;AAEF;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAiBhE;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAStD;AAYD,8DAA8D;AAC9D,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED,2EAA2E;AAC3E,wBAAgB,cAAc,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,GAAG,eAAe,EAAE,CAgBpF;AAkCD,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,GAAE,MAAW,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/lib/index.js
CHANGED
|
@@ -818,7 +818,11 @@ export async function apply(ctx, config = {}) {
|
|
|
818
818
|
? config.customToolsDir
|
|
819
819
|
: join(dirname(resolve(config.stateFile ?? defaultStateFile())), 'custom-tools'));
|
|
820
820
|
const remoteService = {
|
|
821
|
-
describe:
|
|
821
|
+
// The Remote-facing describe is a PAGE read: it must not digest multi-GB installed
|
|
822
|
+
// trees (EXT-33 verification stays available through the full describe() and runs
|
|
823
|
+
// when an extension activates). A skipped digest is reported as integrity 'unknown'
|
|
824
|
+
// and does not block a row.
|
|
825
|
+
describe: signal => extensionsService.describeFast(signal),
|
|
822
826
|
install: (id, source, signal) => extensionsService.install(id, source, signal),
|
|
823
827
|
enable: (id, signal) => extensionsService.enable(id, signal),
|
|
824
828
|
disable: (id, signal) => extensionsService.disable(id, signal),
|
|
@@ -1926,12 +1930,6 @@ export async function apply(ctx, config = {}) {
|
|
|
1926
1930
|
* lifecycle yet, so their existing capability verdict remains the readiness
|
|
1927
1931
|
* source.
|
|
1928
1932
|
*/
|
|
1929
|
-
const callableReadiness = new Set([
|
|
1930
|
-
'prepared-cold',
|
|
1931
|
-
'loading',
|
|
1932
|
-
'ready',
|
|
1933
|
-
'busy',
|
|
1934
|
-
]);
|
|
1935
1933
|
const readinessOf = async (item) => {
|
|
1936
1934
|
if (item.verdict.route !== 'extension')
|
|
1937
1935
|
return 'ready';
|
|
@@ -2003,6 +2001,17 @@ export async function apply(ctx, config = {}) {
|
|
|
2003
2001
|
if (entry.contract !== null && contractById.has(entry.contract)) {
|
|
2004
2002
|
const binding = bindings.get(entry.contract);
|
|
2005
2003
|
if (binding === undefined) {
|
|
2004
|
+
/**
|
|
2005
|
+
* A provider-bound model whose contract has no host binding is still served
|
|
2006
|
+
* by its extension, which owns the tool name. Record it and report success;
|
|
2007
|
+
* only a model with no owner is the "not the selected provider" case.
|
|
2008
|
+
*/
|
|
2009
|
+
if (entry.provider !== undefined && extensionOwnsToolName(entry.tool.name)) {
|
|
2010
|
+
catalogueDeferred.add(entry.id);
|
|
2011
|
+
installed.set(entry.id, { entry, toolName: entry.tool.name, dispose: () => { } });
|
|
2012
|
+
notifyCatalogChange();
|
|
2013
|
+
return true;
|
|
2014
|
+
}
|
|
2006
2015
|
// The model implements a contract but lost provider selection, or cannot
|
|
2007
2016
|
// run. Report rather than register a second tool for the same contract.
|
|
2008
2017
|
ctx.logger.info(`model-tools: ${entry.name} implements ${entry.contract} but is not the selected provider; `
|
|
@@ -2045,7 +2054,10 @@ export async function apply(ctx, config = {}) {
|
|
|
2045
2054
|
catalogueDeferred.add(entry.id);
|
|
2046
2055
|
ctx.logger.info(`model-tools: ${entry.name}'s tool ${entry.tool.name} is owned by an installed extension; `
|
|
2047
2056
|
+ 'the catalogue registration is deferred until the extension releases the name');
|
|
2048
|
-
|
|
2057
|
+
// The extension serves the tool already: enabling the catalogue entry is a
|
|
2058
|
+
// success that records the model, never "cannot be installed here".
|
|
2059
|
+
toolName = entry.tool.name;
|
|
2060
|
+
dispose = () => { };
|
|
2049
2061
|
}
|
|
2050
2062
|
else {
|
|
2051
2063
|
const registered = registerContractTool(ctx, binding, host);
|
|
@@ -2061,14 +2073,22 @@ export async function apply(ctx, config = {}) {
|
|
|
2061
2073
|
});
|
|
2062
2074
|
}
|
|
2063
2075
|
}
|
|
2064
|
-
else {
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2076
|
+
else if (entry.provider !== undefined) {
|
|
2077
|
+
/**
|
|
2078
|
+
* PROVIDER-BOUND: the extension owns the tool name. When it is active the
|
|
2079
|
+
* catalogue joins that tool instead of registering a second one; when it is
|
|
2080
|
+
* not active there is no tool to join, so the entry is skipped rather than
|
|
2081
|
+
* replaced by a provider-bridge tool the MCP surface cannot export.
|
|
2082
|
+
*/
|
|
2083
|
+
if (!extensionOwnsToolName(entry.tool.name)) {
|
|
2084
|
+
ctx.logger.info(`model-tools: ${entry.name}'s provider extension is not active; skipping ${entry.tool.name}`);
|
|
2085
|
+
return false;
|
|
2071
2086
|
}
|
|
2087
|
+
catalogueDeferred.add(entry.id);
|
|
2088
|
+
toolName = entry.tool.name;
|
|
2089
|
+
dispose = () => { };
|
|
2090
|
+
}
|
|
2091
|
+
else {
|
|
2072
2092
|
const adapter = createAdapter(entry, { route: verdict.route, ...transportOptions }, undefined, bridge);
|
|
2073
2093
|
if (adapter === undefined) {
|
|
2074
2094
|
// Runnable but no adapter yet: report rather than register a dead tool.
|
|
@@ -2170,6 +2190,10 @@ export async function apply(ctx, config = {}) {
|
|
|
2170
2190
|
if (extensionOwnsToolName(item.entry.tool.name))
|
|
2171
2191
|
continue;
|
|
2172
2192
|
catalogueDeferred.delete(modelId);
|
|
2193
|
+
// A deferred model was recorded as served by the extension; drop that record
|
|
2194
|
+
// first or install() short-circuits on it and never registers the catalogue tool.
|
|
2195
|
+
if (installed.has(modelId))
|
|
2196
|
+
uninstall(modelId);
|
|
2173
2197
|
ctx.logger.info(`model-tools: ${item.entry.name}'s tool ${item.entry.tool.name} is released; restoring the catalogue registration`);
|
|
2174
2198
|
try {
|
|
2175
2199
|
await install(item);
|
|
@@ -150,6 +150,45 @@ export interface StateReadResult<T> {
|
|
|
150
150
|
* @returns the content digest, lowercase hex.
|
|
151
151
|
*/
|
|
152
152
|
export declare function digestInstalledContent(directory: string): string;
|
|
153
|
+
/** A cheap metadata fingerprint of an installed tree (task-28 cache key). */
|
|
154
|
+
export interface InstallFingerprint {
|
|
155
|
+
/** Content files, excluding the install receipt. */
|
|
156
|
+
readonly fileCount: number;
|
|
157
|
+
/** Sum of the content files' byte sizes. */
|
|
158
|
+
readonly totalSize: number;
|
|
159
|
+
/** Newest modification time, in milliseconds since the epoch. */
|
|
160
|
+
readonly maxMtimeMs: number;
|
|
161
|
+
/**
|
|
162
|
+
* Newest change time (ctime), in milliseconds since the epoch. This is the fingerprint field
|
|
163
|
+
* that catches an in-place rewrite whose author restored the modification time: writing the
|
|
164
|
+
* bytes advances ctime on the supported filesystems.
|
|
165
|
+
*/
|
|
166
|
+
readonly maxChangeTimeMs: number;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Digest an installed package with a bounded worker pool (task-28).
|
|
170
|
+
*
|
|
171
|
+
* Byte-identical to {@link digestInstalledContent}: the per-file sha256 values are gathered
|
|
172
|
+
* (in parallel) and then the final sha256 is updated in the same sorted order, with the same
|
|
173
|
+
* relative name, size and separators. A worker failure falls back to bounded async I/O, which
|
|
174
|
+
* produces the same values; the parallelism can only change how fast the digest is computed.
|
|
175
|
+
* @param directory - the installed package directory.
|
|
176
|
+
* @param options - concurrency override (defaults to min(8, cpus - 1)).
|
|
177
|
+
* @returns the content digest, lowercase hex.
|
|
178
|
+
*/
|
|
179
|
+
export declare function digestInstalledContentAsync(directory: string, options?: {
|
|
180
|
+
readonly concurrency?: number;
|
|
181
|
+
}): Promise<string>;
|
|
182
|
+
/**
|
|
183
|
+
* The cheap metadata fingerprint verifyUnchangedAsync caches against (task-28).
|
|
184
|
+
*
|
|
185
|
+
* It walks the tree (directory reads and stat calls only, never file contents) and records the
|
|
186
|
+
* content-file count, their total size, the newest modification time and the newest change time.
|
|
187
|
+
* The install receipt is excluded so rewriting it cannot invalidate an otherwise unchanged tree.
|
|
188
|
+
* @param directory - the installed package directory.
|
|
189
|
+
* @returns the fingerprint.
|
|
190
|
+
*/
|
|
191
|
+
export declare function installContentFingerprint(directory: string): InstallFingerprint;
|
|
153
192
|
/**
|
|
154
193
|
* Whether a process with this pid exists. `process.kill(pid, 0)` is the probe.
|
|
155
194
|
*
|
|
@@ -162,6 +201,7 @@ export declare function digestInstalledContent(directory: string): string;
|
|
|
162
201
|
export declare function isProcessAlive(pid: number): boolean;
|
|
163
202
|
/** The operator-owned extension store. */
|
|
164
203
|
export declare class ExtensionStore {
|
|
204
|
+
#private;
|
|
165
205
|
/** Absolute path of the store root. */
|
|
166
206
|
readonly rootDir: string;
|
|
167
207
|
constructor(rootDir: string);
|
|
@@ -238,6 +278,29 @@ export declare class ExtensionStore {
|
|
|
238
278
|
contentDigest?: string;
|
|
239
279
|
diagnostic?: string;
|
|
240
280
|
};
|
|
281
|
+
/**
|
|
282
|
+
* Async, cached form of {@link verifyUnchanged} (task-28).
|
|
283
|
+
*
|
|
284
|
+
* Uses the worker-pool digest so a multi-GB installation does not block the event loop for
|
|
285
|
+
* minutes, and reuses the last verified answer while the cheap fingerprint and the record's
|
|
286
|
+
* digest both still match. A stale or forged record is never served from the cache: the
|
|
287
|
+
* cache entry must carry the SAME recorded digest, and any fingerprint change falls back to a
|
|
288
|
+
* full digest. A failed check removes the entry, so a tampered tree is re-digested next time.
|
|
289
|
+
*
|
|
290
|
+
* Residual limitation: a rewrite that preserved byte size, mtime AND ctime would not change
|
|
291
|
+
* the cheap fingerprint, so a warm cache could not see it without re-reading the bytes. That
|
|
292
|
+
* is why the full digest remains the authority on a fresh process and on every fingerprint
|
|
293
|
+
* change; the ctime component makes ordinary "restore the timestamps" tampering detectable.
|
|
294
|
+
* @param record - the recorded installation.
|
|
295
|
+
* @returns whether the content is unchanged, the current digest when computed, and whether
|
|
296
|
+
* the answer came from the cache.
|
|
297
|
+
*/
|
|
298
|
+
verifyUnchangedAsync(record: InstalledRecord): Promise<{
|
|
299
|
+
unchanged: boolean;
|
|
300
|
+
contentDigest?: string;
|
|
301
|
+
diagnostic?: string;
|
|
302
|
+
cached: boolean;
|
|
303
|
+
}>;
|
|
241
304
|
/**
|
|
242
305
|
* Read one profile's activation state.
|
|
243
306
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/install/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/install/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,7 +19,10 @@
|
|
|
19
19
|
*/
|
|
20
20
|
import { createHash, randomUUID } from 'node:crypto';
|
|
21
21
|
import { existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync, } from 'node:fs';
|
|
22
|
+
import { readFile } from 'node:fs/promises';
|
|
23
|
+
import { cpus } from 'node:os';
|
|
22
24
|
import { dirname, join, relative, resolve, sep } from 'node:path';
|
|
25
|
+
import { Worker } from 'node:worker_threads';
|
|
23
26
|
import { ManagementError } from "./../errors.js";
|
|
24
27
|
import { STATE_SCHEMA_VERSION, STATE_VERSION, applyLegacyChoices, parseLegacyModelState, } from "./migration.js";
|
|
25
28
|
/** Reentrant acquisition depth per resolved store root, process-local. */
|
|
@@ -64,6 +67,177 @@ export function digestInstalledContent(directory) {
|
|
|
64
67
|
}
|
|
65
68
|
return hash.digest('hex');
|
|
66
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* The worker source. EVAL keeps the pool self-contained in this module (no separate file and
|
|
72
|
+
* no build/config coupling); the worker only reads files and returns per-file digests, so the
|
|
73
|
+
* digest itself is still assembled in ONE deterministic order on the main thread.
|
|
74
|
+
*/
|
|
75
|
+
const DIGEST_WORKER_SOURCE = `
|
|
76
|
+
const { parentPort, workerData } = require('node:worker_threads')
|
|
77
|
+
const { readFileSync } = require('node:fs')
|
|
78
|
+
const { createHash } = require('node:crypto')
|
|
79
|
+
const digests = workerData.files.map((file) => {
|
|
80
|
+
const bytes = readFileSync(file)
|
|
81
|
+
return { file, size: bytes.byteLength, digest: createHash('sha256').update(bytes).digest('hex') }
|
|
82
|
+
})
|
|
83
|
+
parentPort.postMessage(digests)
|
|
84
|
+
`;
|
|
85
|
+
/** The default worker-pool size: min(8, cpus - 1), never less than one. */
|
|
86
|
+
const digestConcurrency = () => Math.max(1, Math.min(8, cpus().length - 1));
|
|
87
|
+
/**
|
|
88
|
+
* Walk an installed tree exactly as digestInstalledContent does: sorted-by-name directories,
|
|
89
|
+
* files collected and then sorted by absolute path. The async digest must not change identity,
|
|
90
|
+
* so the file list is produced with the same ordering rule.
|
|
91
|
+
*/
|
|
92
|
+
function installedFilesForDigest(directory) {
|
|
93
|
+
const files = [];
|
|
94
|
+
const walk = (current) => {
|
|
95
|
+
for (const entry of readdirSync(current, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
96
|
+
const absolute = join(current, entry.name);
|
|
97
|
+
if (entry.isDirectory())
|
|
98
|
+
walk(absolute);
|
|
99
|
+
else if (entry.isFile())
|
|
100
|
+
files.push(absolute);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
walk(directory);
|
|
104
|
+
return files.sort();
|
|
105
|
+
}
|
|
106
|
+
/** The digest's relative name for a file: forward slashes on every platform. */
|
|
107
|
+
const relativeContentName = (directory, file) => relative(directory, file).split(sep).join('/');
|
|
108
|
+
/** Hash files on the main thread with bounded async I/O (the worker-free fallback). */
|
|
109
|
+
async function digestFilesInline(files, concurrency) {
|
|
110
|
+
const results = new Array(files.length);
|
|
111
|
+
let cursor = 0;
|
|
112
|
+
const run = async () => {
|
|
113
|
+
for (;;) {
|
|
114
|
+
const index = cursor;
|
|
115
|
+
cursor += 1;
|
|
116
|
+
const file = files[index];
|
|
117
|
+
if (file === undefined)
|
|
118
|
+
return;
|
|
119
|
+
const bytes = await readFile(file);
|
|
120
|
+
results[index] = { file, size: bytes.byteLength, digest: createHash('sha256').update(bytes).digest('hex') };
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
await Promise.all(Array.from({ length: Math.min(concurrency, files.length) }, () => run()));
|
|
124
|
+
return results;
|
|
125
|
+
}
|
|
126
|
+
/** Hash a chunk of files inside one worker. */
|
|
127
|
+
function digestFilesInWorker(files) {
|
|
128
|
+
return new Promise((resolvePromise, reject) => {
|
|
129
|
+
const worker = new Worker(DIGEST_WORKER_SOURCE, { eval: true, workerData: { files } });
|
|
130
|
+
let settled = false;
|
|
131
|
+
const fail = (error) => {
|
|
132
|
+
if (settled)
|
|
133
|
+
return;
|
|
134
|
+
settled = true;
|
|
135
|
+
void worker.terminate();
|
|
136
|
+
reject(error instanceof Error ? error : new Error(String(error)));
|
|
137
|
+
};
|
|
138
|
+
worker.once('message', (value) => {
|
|
139
|
+
if (settled)
|
|
140
|
+
return;
|
|
141
|
+
settled = true;
|
|
142
|
+
void worker.terminate();
|
|
143
|
+
resolvePromise(value);
|
|
144
|
+
});
|
|
145
|
+
worker.once('error', fail);
|
|
146
|
+
worker.once('exit', (code) => {
|
|
147
|
+
if (code !== 0)
|
|
148
|
+
fail(new Error('the digest worker exited with code ' + String(code)));
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Digest an installed package with a bounded worker pool (task-28).
|
|
154
|
+
*
|
|
155
|
+
* Byte-identical to {@link digestInstalledContent}: the per-file sha256 values are gathered
|
|
156
|
+
* (in parallel) and then the final sha256 is updated in the same sorted order, with the same
|
|
157
|
+
* relative name, size and separators. A worker failure falls back to bounded async I/O, which
|
|
158
|
+
* produces the same values; the parallelism can only change how fast the digest is computed.
|
|
159
|
+
* @param directory - the installed package directory.
|
|
160
|
+
* @param options - concurrency override (defaults to min(8, cpus - 1)).
|
|
161
|
+
* @returns the content digest, lowercase hex.
|
|
162
|
+
*/
|
|
163
|
+
export async function digestInstalledContentAsync(directory, options = {}) {
|
|
164
|
+
const files = installedFilesForDigest(directory);
|
|
165
|
+
const requested = options.concurrency ?? digestConcurrency();
|
|
166
|
+
const concurrency = Math.max(1, Math.min(requested, files.length === 0 ? 1 : files.length));
|
|
167
|
+
let digests = [];
|
|
168
|
+
if (files.length > 0) {
|
|
169
|
+
if (concurrency === 1) {
|
|
170
|
+
digests = await digestFilesInline(files, 1);
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
const chunks = Array.from({ length: concurrency }, () => []);
|
|
174
|
+
for (let index = 0; index < files.length; index += 1) {
|
|
175
|
+
const file = files[index];
|
|
176
|
+
if (file !== undefined)
|
|
177
|
+
chunks[index % concurrency]?.push(file);
|
|
178
|
+
}
|
|
179
|
+
try {
|
|
180
|
+
const parts = await Promise.all(chunks.filter((chunk) => chunk.length > 0).map((chunk) => digestFilesInWorker(chunk)));
|
|
181
|
+
digests = parts.flat();
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
digests = await digestFilesInline(files, concurrency);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
const byFile = new Map(digests.map((entry) => [entry.file, entry]));
|
|
189
|
+
const hash = createHash('sha256');
|
|
190
|
+
for (const file of files) {
|
|
191
|
+
const name = relativeContentName(directory, file);
|
|
192
|
+
if (name === '.tool-mode-install.json')
|
|
193
|
+
continue;
|
|
194
|
+
const entry = byFile.get(file);
|
|
195
|
+
if (entry === undefined)
|
|
196
|
+
throw new Error('the async digest did not hash ' + JSON.stringify(name));
|
|
197
|
+
hash.update(name);
|
|
198
|
+
hash.update('\0');
|
|
199
|
+
hash.update(String(entry.size));
|
|
200
|
+
hash.update('\0');
|
|
201
|
+
hash.update(Buffer.from(entry.digest, 'hex'));
|
|
202
|
+
hash.update('\0');
|
|
203
|
+
}
|
|
204
|
+
return hash.digest('hex');
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* The cheap metadata fingerprint verifyUnchangedAsync caches against (task-28).
|
|
208
|
+
*
|
|
209
|
+
* It walks the tree (directory reads and stat calls only, never file contents) and records the
|
|
210
|
+
* content-file count, their total size, the newest modification time and the newest change time.
|
|
211
|
+
* The install receipt is excluded so rewriting it cannot invalidate an otherwise unchanged tree.
|
|
212
|
+
* @param directory - the installed package directory.
|
|
213
|
+
* @returns the fingerprint.
|
|
214
|
+
*/
|
|
215
|
+
export function installContentFingerprint(directory) {
|
|
216
|
+
const files = installedFilesForDigest(directory);
|
|
217
|
+
let fileCount = 0;
|
|
218
|
+
let totalSize = 0;
|
|
219
|
+
let maxMtimeMs = 0;
|
|
220
|
+
let maxChangeTimeMs = 0;
|
|
221
|
+
for (const file of files) {
|
|
222
|
+
if (relativeContentName(directory, file) === '.tool-mode-install.json')
|
|
223
|
+
continue;
|
|
224
|
+
const stats = statSync(file);
|
|
225
|
+
fileCount += 1;
|
|
226
|
+
totalSize += stats.size;
|
|
227
|
+
if (stats.mtimeMs > maxMtimeMs)
|
|
228
|
+
maxMtimeMs = stats.mtimeMs;
|
|
229
|
+
if (stats.ctimeMs > maxChangeTimeMs)
|
|
230
|
+
maxChangeTimeMs = stats.ctimeMs;
|
|
231
|
+
}
|
|
232
|
+
return { fileCount, totalSize, maxMtimeMs, maxChangeTimeMs };
|
|
233
|
+
}
|
|
234
|
+
/** Whether two fingerprints describe the same metadata state. */
|
|
235
|
+
function sameFingerprint(left, right) {
|
|
236
|
+
return left.fileCount === right.fileCount
|
|
237
|
+
&& left.totalSize === right.totalSize
|
|
238
|
+
&& left.maxMtimeMs === right.maxMtimeMs
|
|
239
|
+
&& left.maxChangeTimeMs === right.maxChangeTimeMs;
|
|
240
|
+
}
|
|
67
241
|
/**
|
|
68
242
|
* Whether a process with this pid exists. `process.kill(pid, 0)` is the probe.
|
|
69
243
|
*
|
|
@@ -127,6 +301,12 @@ function readJsonBounded(path, maxBytes = 4 * 1024 * 1024) {
|
|
|
127
301
|
export class ExtensionStore {
|
|
128
302
|
/** Absolute path of the store root. */
|
|
129
303
|
rootDir;
|
|
304
|
+
/**
|
|
305
|
+
* Verified digests per install path (task-28). A process-local performance cache: it may only
|
|
306
|
+
* short-circuit the full digest when the cheap fingerprint is identical AND the record's
|
|
307
|
+
* digest equals the digest that was verified for that fingerprint.
|
|
308
|
+
*/
|
|
309
|
+
#verifiedContent = new Map();
|
|
130
310
|
constructor(rootDir) {
|
|
131
311
|
this.rootDir = resolve(rootDir);
|
|
132
312
|
}
|
|
@@ -358,6 +538,52 @@ export class ExtensionStore {
|
|
|
358
538
|
}
|
|
359
539
|
return { unchanged: true, contentDigest };
|
|
360
540
|
}
|
|
541
|
+
/**
|
|
542
|
+
* Async, cached form of {@link verifyUnchanged} (task-28).
|
|
543
|
+
*
|
|
544
|
+
* Uses the worker-pool digest so a multi-GB installation does not block the event loop for
|
|
545
|
+
* minutes, and reuses the last verified answer while the cheap fingerprint and the record's
|
|
546
|
+
* digest both still match. A stale or forged record is never served from the cache: the
|
|
547
|
+
* cache entry must carry the SAME recorded digest, and any fingerprint change falls back to a
|
|
548
|
+
* full digest. A failed check removes the entry, so a tampered tree is re-digested next time.
|
|
549
|
+
*
|
|
550
|
+
* Residual limitation: a rewrite that preserved byte size, mtime AND ctime would not change
|
|
551
|
+
* the cheap fingerprint, so a warm cache could not see it without re-reading the bytes. That
|
|
552
|
+
* is why the full digest remains the authority on a fresh process and on every fingerprint
|
|
553
|
+
* change; the ctime component makes ordinary "restore the timestamps" tampering detectable.
|
|
554
|
+
* @param record - the recorded installation.
|
|
555
|
+
* @returns whether the content is unchanged, the current digest when computed, and whether
|
|
556
|
+
* the answer came from the cache.
|
|
557
|
+
*/
|
|
558
|
+
async verifyUnchangedAsync(record) {
|
|
559
|
+
if (!existsSync(record.installPath)) {
|
|
560
|
+
this.#verifiedContent.delete(record.installPath);
|
|
561
|
+
return { unchanged: false, diagnostic: 'the installation directory is missing', cached: false };
|
|
562
|
+
}
|
|
563
|
+
const before = installContentFingerprint(record.installPath);
|
|
564
|
+
const cached = this.#verifiedContent.get(record.installPath);
|
|
565
|
+
if (cached !== undefined && cached.contentDigest === record.contentDigest && sameFingerprint(cached.fingerprint, before)) {
|
|
566
|
+
return { unchanged: true, contentDigest: cached.contentDigest, cached: true };
|
|
567
|
+
}
|
|
568
|
+
const contentDigest = await digestInstalledContentAsync(record.installPath);
|
|
569
|
+
if (contentDigest !== record.contentDigest) {
|
|
570
|
+
this.#verifiedContent.delete(record.installPath);
|
|
571
|
+
return {
|
|
572
|
+
unchanged: false,
|
|
573
|
+
contentDigest,
|
|
574
|
+
diagnostic: 'the installed content differs from the recorded digest; the package changed on disk after installation',
|
|
575
|
+
cached: false,
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
// Cache only if the tree did not move while it was being hashed (otherwise the entry would
|
|
579
|
+
// pair the new digest with the old fingerprint and hide a later change).
|
|
580
|
+
const after = installContentFingerprint(record.installPath);
|
|
581
|
+
if (sameFingerprint(before, after))
|
|
582
|
+
this.#verifiedContent.set(record.installPath, { contentDigest, fingerprint: after });
|
|
583
|
+
else
|
|
584
|
+
this.#verifiedContent.delete(record.installPath);
|
|
585
|
+
return { unchanged: true, contentDigest, cached: false };
|
|
586
|
+
}
|
|
361
587
|
/**
|
|
362
588
|
* Read one profile's activation state.
|
|
363
589
|
*
|