arcane-os 0.1.0 → 0.1.2

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.
Files changed (31) hide show
  1. package/NOTICE +10 -0
  2. package/browser-runtime/ARCANE_SDK_BROWSER_RELEASE.json +80 -4
  3. package/browser-runtime/ai/ARCANE_AI_BROWSER_WASM_COMPONENTS.json +69 -0
  4. package/browser-runtime/ai/browser-wasm-llm-provider.mjs +1151 -0
  5. package/browser-runtime/ai/browser-wasm.mjs +44 -0
  6. package/browser-runtime/ai/browser-wllama-runtime.mjs +390 -0
  7. package/browser-runtime/ai/internal/sha256.mjs +166 -0
  8. package/browser-runtime/ai/model-controller.mjs +581 -0
  9. package/browser-runtime/ai/wllama/LICENCE +21 -0
  10. package/browser-runtime/ai/wllama/index.mjs +3494 -0
  11. package/browser-runtime/ai/wllama/llama.cpp-LICENSE +21 -0
  12. package/browser-runtime/ai/wllama/wllama.wasm +0 -0
  13. package/docs/publishing.md +23 -18
  14. package/docs/reference/README.md +9 -5
  15. package/docs/reference/ai/browser-wasm.md +335 -0
  16. package/docs/reference/availability-and-normalization.md +17 -0
  17. package/docs/reference/behavioral-testing.md +8 -0
  18. package/docs/reference/cli.md +86 -3
  19. package/docs/reference/event-manager.md +15 -6
  20. package/docs/reference/inventory/package-api.json +84 -4
  21. package/docs/reference/protocols.md +113 -14
  22. package/docs/reference/sdk-api.md +244 -11
  23. package/package.json +8 -5
  24. package/runtime/ARCANE_RUNTIME_RELEASE.json +1 -1
  25. package/schemas/arcane-lock.schema.json +17 -6
  26. package/src/dev-server.mjs +2 -1
  27. package/src/doctor.mjs +1 -1
  28. package/src/import-map.mjs +25 -1
  29. package/src/sdk-browser-runtime.mjs +134 -17
  30. package/src/templates/workspace-template.mjs +6 -0
  31. package/src/workspace.mjs +7 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arcane-os",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Arcane OS JavaScript SDK, project-local CLI, browser runtime, and repository-portable application packager.",
5
5
  "type": "module",
6
6
  "main": "./src/index.mjs",
@@ -13,6 +13,7 @@
13
13
  "./toolchain": "./src/toolchain.mjs",
14
14
  "./events": "./src/events.mjs",
15
15
  "./event-manager": "./src/event-manager.mjs",
16
+ "./ai/browser-wasm": "./browser-runtime/ai/browser-wasm.mjs",
16
17
  "./testing": "./src/testing.mjs",
17
18
  "./targets": "./src/targets/index.mjs",
18
19
  "./native": "./src/native-plan.mjs",
@@ -46,14 +47,13 @@
46
47
  ],
47
48
  "scripts": {
48
49
  "test": "npm run test:unit && npm run test:functional && npm run test:integration && npm run test:regression",
49
- "test:release": "npm run test:unit && npm run test:functional:release && npm run test:integration && npm run test:regression",
50
+ "test:release": "node ./bin/arcane-test.mjs test/npm-release.test.mjs",
50
51
  "test:unit": "node ./bin/arcane-test.mjs test/app-descriptor.test.mjs test/app-schema.test.mjs test/contracts.test.mjs test/doctor.test.mjs test/targets.test.mjs test/workspace-operation-lock.test.mjs",
51
52
  "test:functional": "node ./bin/arcane-test.mjs test/cli.test.mjs test/dev-server.test.mjs test/dom-event-instrumentation.test.mjs test/event-manager.test.mjs test/events.test.mjs test/import-map.test.mjs test/packaging.test.mjs test/reference-completeness.test.mjs test/runtime-api-behavior.test.mjs test/runtime-sync.test.mjs test/runtime.test.mjs test/scaffold.test.mjs test/site.test.mjs test/update-check.test.mjs",
52
- "test:functional:release": "node ./bin/arcane-test.mjs test/cli.test.mjs test/dev-server.test.mjs test/dom-event-instrumentation.test.mjs test/event-manager.test.mjs test/events.test.mjs test/import-map.test.mjs test/packaging.test.mjs test/runtime-api-behavior.test.mjs test/runtime-sync.test.mjs test/runtime.test.mjs test/scaffold.test.mjs test/update-check.test.mjs",
53
53
  "test:integration": "node ./bin/arcane-test.mjs test/integrated-shared.test.mjs test/integrated-workspace.test.mjs test/native-plan.test.mjs test/native-provider-loader.test.mjs test/npm-release.test.mjs test/release-bundle.test.mjs test/release-capability-smoke.test.mjs test/shared-payload-batch.test.mjs test/tarball.test.mjs",
54
54
  "test:regression": "node ./bin/arcane-test.mjs test/channel-workflows.test.mjs test/native-provider-generation.test.mjs test/testing.test.mjs test/test-sets.test.mjs",
55
55
  "check": "node tools/check-source.mjs && node tools/runtime-manifest.mjs --verify && node tools/sdk-browser-runtime-manifest.mjs --verify && npm test",
56
- "check:release": "node tools/check-source.mjs && node tools/runtime-manifest.mjs --verify && node tools/sdk-browser-runtime-manifest.mjs --verify && npm run test:release",
56
+ "check:release": "node tools/check-source.mjs --package-only && node tools/runtime-manifest.mjs --verify && node tools/sdk-browser-runtime-manifest.mjs --verify && npm run test:release",
57
57
  "runtime:verify": "node tools/runtime-manifest.mjs --verify",
58
58
  "runtime:sync": "node tools/sync-runtime.mjs",
59
59
  "pack:local": "npm pack --ignore-scripts",
@@ -95,5 +95,8 @@
95
95
  "bundleDependencies": [
96
96
  "event-pubsub",
97
97
  "strong-type"
98
- ]
98
+ ],
99
+ "devDependencies": {
100
+ "@wllama/wllama": "3.6.0"
101
+ }
99
102
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "builder": "arcane-sdk-runtime-v1",
4
- "sdkVersion": "0.1.0",
4
+ "sdkVersion": "0.1.2",
5
5
  "source": {
6
6
  "repository": "https://github.com/TheWizardNexus/ARCANE-OS.git",
7
7
  "commit": "567ad110bf57a1c2d4a3daa22ae93716cc5f4d7e",
@@ -28,7 +28,7 @@
28
28
  "const": "arcane-os"
29
29
  },
30
30
  "version": {
31
- "const": "0.1.0"
31
+ "const": "0.1.2"
32
32
  }
33
33
  }
34
34
  },
@@ -69,16 +69,16 @@
69
69
  "const": "node_modules/arcane-os/browser-runtime/ARCANE_SDK_BROWSER_RELEASE.json"
70
70
  },
71
71
  "manifestSha256": {
72
- "const": "43baaec850291c28795f6c194001deb5febab88ccab1b033bce6597dd6f6f08f"
72
+ "const": "88395493b411fd5461fbb2bb065ae2b745f6d1672f796583fd248ec97f71f4f7"
73
73
  },
74
74
  "contentSha256": {
75
- "const": "0caa302bc07d4a45f5290504ec62ddce98fdf5e3412f916c10aae3d51b1e5f7c"
75
+ "const": "5e03f45a732db51cb5a2b2193cc79ecda34501d07a9b2e82e794e5fa37d55d00"
76
76
  },
77
77
  "builder": {
78
78
  "const": "arcane-sdk-browser-runtime-v1"
79
79
  },
80
80
  "sdkVersion": {
81
- "const": "0.1.0"
81
+ "const": "0.1.2"
82
82
  },
83
83
  "source": {
84
84
  "type": "object",
@@ -105,8 +105,8 @@
105
105
  },
106
106
  "dependencies": {
107
107
  "type": "array",
108
- "minItems": 2,
109
- "maxItems": 2,
108
+ "minItems": 3,
109
+ "maxItems": 3,
110
110
  "prefixItems": [
111
111
  {
112
112
  "type": "object",
@@ -129,6 +129,17 @@
129
129
  "resolved": {"const": "https://registry.npmjs.org/strong-type/-/strong-type-2.0.0.tgz"},
130
130
  "integrity": {"const": "sha512-HHrY9qYC7yn+5mlewiI3k9RQM9gZqGQsqbomZcd10Ks0h4RlX01nnkWbCe4AsVPCI6KaFvpkWm1nHMD+Ykup6g=="}
131
131
  }
132
+ },
133
+ {
134
+ "type": "object",
135
+ "additionalProperties": false,
136
+ "required": ["name", "version", "resolved", "integrity"],
137
+ "properties": {
138
+ "name": {"const": "@wllama/wllama"},
139
+ "version": {"const": "3.6.0"},
140
+ "resolved": {"const": "https://registry.npmjs.org/@wllama/wllama/-/wllama-3.6.0.tgz"},
141
+ "integrity": {"const": "sha512-NN3ZBXqaaUwGXTQubkNvsCaLPjN2XVa0bVS40OYCE8zquYmRc2W3oHYEgwvuSWWDB8aUqTLyMioySCXNkcnD1w=="}
142
+ }
132
143
  }
133
144
  ],
134
145
  "items": false
@@ -31,6 +31,7 @@ const MIME_TYPES=new Map([
31
31
  ['.png','image/png'],
32
32
  ['.svg','image/svg+xml; charset=utf-8'],
33
33
  ['.txt','text/plain; charset=utf-8'],
34
+ ['.wasm','application/wasm'],
34
35
  ['.webp','image/webp'],
35
36
  ['.woff','font/woff'],
36
37
  ['.woff2','font/woff2']
@@ -51,7 +52,7 @@ const PRIVATE_SOURCE_SEGMENTS=new Set([
51
52
  // development CSP from being exposed as a general network service.
52
53
  const DEVELOPMENT_CSP=[
53
54
  "default-src 'self'",
54
- "script-src 'self' 'unsafe-inline'",
55
+ "script-src 'self' 'unsafe-inline' 'wasm-unsafe-eval'",
55
56
  "style-src 'self' 'unsafe-inline'",
56
57
  "img-src 'self' data: blob: http: https:",
57
58
  "font-src 'self' data:",
package/src/doctor.mjs CHANGED
@@ -8,7 +8,7 @@ import {runProcess} from './process.mjs';
8
8
  import {ARCANE_PROTOCOL,SDK_VERSION} from './constants.mjs';
9
9
  import {ERROR_CODES,ArcaneError,throwIfAborted} from './errors.mjs';
10
10
 
11
- const MINIMUM_NODE=[22,14,0];
11
+ const MINIMUM_NODE=[22,23,2];
12
12
  const WINDOWS_SERVICE_NAME='ArcaneOllama';
13
13
  const WINDOWS_SERVICE_HOST='C:\\Program Files\\Ollama\\ArcaneOllamaService.exe';
14
14
  const WINDOWS_SERVICE_COMMAND=`"${WINDOWS_SERVICE_HOST}"`;
@@ -15,7 +15,18 @@ const JAVASCRIPT_EXTENSION=/\.(?:js|mjs)$/u;
15
15
  const NODE_ONLY_MODULE='modules/CaseEvidenceIndexer.js';
16
16
  const RUNTIME_STRONG_TYPE_IMPORT='../../node_modules/strong-type/index.js';
17
17
  const SDK_BROWSER_ENTRY='sdk/event-manager.mjs';
18
+ const SDK_BROWSER_AI_ENTRY='sdk/ai/browser-wasm.mjs';
18
19
  const SDK_BROWSER_FILES=Object.freeze([
20
+ 'sdk/ai/ARCANE_AI_BROWSER_WASM_COMPONENTS.json',
21
+ 'sdk/ai/browser-wasm-llm-provider.mjs',
22
+ SDK_BROWSER_AI_ENTRY,
23
+ 'sdk/ai/browser-wllama-runtime.mjs',
24
+ 'sdk/ai/internal/sha256.mjs',
25
+ 'sdk/ai/model-controller.mjs',
26
+ 'sdk/ai/wllama/LICENCE',
27
+ 'sdk/ai/wllama/index.mjs',
28
+ 'sdk/ai/wllama/llama.cpp-LICENSE',
29
+ 'sdk/ai/wllama/wllama.wasm',
19
30
  SDK_BROWSER_ENTRY,
20
31
  'sdk/dom-event-instrumentation.mjs',
21
32
  'sdk/dependencies/event-pubsub/index.js',
@@ -954,6 +965,10 @@ export async function buildImportMap({files,readFile,signal}={}){
954
965
  roots.push(relative);
955
966
  }
956
967
  const hasSdkBrowserGraph=inventory.has(SDK_BROWSER_ENTRY);
968
+ const hasSdkAiGraph=inventory.has(SDK_BROWSER_AI_ENTRY);
969
+ if(hasSdkAiGraph&&!hasSdkBrowserGraph){
970
+ unresolved(SDK_BROWSER_AI_ENTRY,'<authenticated SDK browser closure>',SDK_BROWSER_ENTRY);
971
+ }
957
972
  if(hasSdkBrowserGraph){
958
973
  for(const required of SDK_BROWSER_FILES){
959
974
  if(!inventory.has(required)){
@@ -995,9 +1010,18 @@ export async function buildImportMap({files,readFile,signal}={}){
995
1010
  'arcane-os/event-manager',
996
1011
  './arcane/sdk/event-manager.mjs'
997
1012
  );
1013
+ if(hasSdkAiGraph){
1014
+ registerSpecifier(
1015
+ namedRegistry,
1016
+ 'arcane-os/ai/browser-wasm',
1017
+ './arcane/sdk/ai/browser-wasm.mjs'
1018
+ );
1019
+ }
998
1020
  }
999
1021
 
1000
- const queue=[...roots,...(hasSdkBrowserGraph?[SDK_BROWSER_ENTRY]:[])];
1022
+ const sdkRoots=hasSdkBrowserGraph
1023
+ ?[SDK_BROWSER_ENTRY,...(hasSdkAiGraph?[SDK_BROWSER_AI_ENTRY]:[])]:[];
1024
+ const queue=[...roots,...sdkRoots];
1001
1025
  const reached=new Set();
1002
1026
  const entities=new Set();
1003
1027
  let usesRuntimeStrongType=false;
@@ -9,9 +9,9 @@ const MANIFEST_NAME='ARCANE_SDK_BROWSER_RELEASE.json';
9
9
  const BUILDER='arcane-sdk-browser-runtime-v1';
10
10
  const PROTOCOL='arcane-sdk-browser-runtime/1';
11
11
  export const SDK_BROWSER_RUNTIME_MANIFEST_SHA256=
12
- '43baaec850291c28795f6c194001deb5febab88ccab1b033bce6597dd6f6f08f';
12
+ '88395493b411fd5461fbb2bb065ae2b745f6d1672f796583fd248ec97f71f4f7';
13
13
  export const SDK_BROWSER_RUNTIME_CONTENT_SHA256=
14
- '0caa302bc07d4a45f5290504ec62ddce98fdf5e3412f916c10aae3d51b1e5f7c';
14
+ '5e03f45a732db51cb5a2b2193cc79ecda34501d07a9b2e82e794e5fa37d55d00';
15
15
  const REPOSITORY='https://github.com/TheWizardNexus/arcane-os-sdk.git';
16
16
  const SHA256_PATTERN=/^[a-f0-9]{64}$/u;
17
17
  const READ_ONLY_NO_FOLLOW=FS_CONSTANTS.O_RDONLY|(FS_CONSTANTS.O_NOFOLLOW??0);
@@ -19,8 +19,87 @@ const MAX_VERIFIED_FILE_BYTES=64*1024*1024;
19
19
  const packageRoot=path.resolve(path.dirname(fileURLToPath(import.meta.url)),'..');
20
20
  const defaultRoot=path.join(packageRoot,'browser-runtime');
21
21
  const issuedReceipts=new WeakSet();
22
+ const expectedAiComponents=Object.freeze({
23
+ schemaVersion:1,
24
+ kind:'arcane-ai-browser-wasm-components',
25
+ protocol:'arcane-ai-browser-wasm/1',
26
+ packageExport:'arcane-os/ai/browser-wasm',
27
+ browserEntry:'ai/browser-wasm.mjs',
28
+ runtimePolicy:{
29
+ modelAuthorities:'caller-supplied-exact-bytes-and-sha256',
30
+ modelWeightsPacked:false,
31
+ remoteModelHelpers:false,
32
+ compatibilityRuntime:false,
33
+ toolCalls:'structural-only-never-executed'
34
+ },
35
+ components:[
36
+ {
37
+ name:'@wllama/wllama',
38
+ version:'3.6.0',
39
+ licenseSpdx:'MIT',
40
+ sourceRepository:'https://github.com/ngxson/wllama.git',
41
+ sourceRevision:'f16050d8d51a00602c6a2a6b8ac9c09f490eea7f',
42
+ npm:{
43
+ resolved:'https://registry.npmjs.org/@wllama/wllama/-/wllama-3.6.0.tgz',
44
+ integrity:'sha512-NN3ZBXqaaUwGXTQubkNvsCaLPjN2XVa0bVS40OYCE8zquYmRc2W3oHYEgwvuSWWDB8aUqTLyMioySCXNkcnD1w==',
45
+ tarballBytes:5671369,
46
+ tarballSha256:'137c35ceccb4911a9b0ce9b427889f75991654ec6a6d1dd8fabd879b14b07a1b'
47
+ },
48
+ files:[
49
+ {
50
+ role:'runtime-module',
51
+ path:'ai/wllama/index.mjs',
52
+ sourcePath:'node_modules/@wllama/wllama/esm/index.js',
53
+ bytes:373519,
54
+ sha256:'4637e42d636010493a9b274fbbe70bfd8120365da726b1d9e589d85ca84a00d6'
55
+ },
56
+ {
57
+ role:'runtime-wasm',
58
+ path:'ai/wllama/wllama.wasm',
59
+ sourcePath:'node_modules/@wllama/wllama/esm/wasm/wllama.wasm',
60
+ bytes:8524865,
61
+ sha256:'95c6ff9ef2a03ff2c63bc91db132f0126a0bd0456b272cd8ae2e0f592fb059f6'
62
+ },
63
+ {
64
+ role:'license',
65
+ path:'ai/wllama/LICENCE',
66
+ sourcePath:'node_modules/@wllama/wllama/LICENCE',
67
+ bytes:1071,
68
+ sha256:'5866e3bd7e3cbd3f7c8bea6efd8a1e7fa7cc8de68c30f428aff7c6584a0fb720'
69
+ }
70
+ ]
71
+ },
72
+ {
73
+ name:'llama.cpp',
74
+ version:'b10454',
75
+ licenseSpdx:'MIT',
76
+ sourceRepository:'https://github.com/ggerganov/llama.cpp.git',
77
+ sourceRevision:'4df29be4f4c3673f428170fda944a5b19f743bb8',
78
+ embeddedBy:'@wllama/wllama@3.6.0',
79
+ files:[
80
+ {
81
+ role:'license',
82
+ path:'ai/wllama/llama.cpp-LICENSE',
83
+ sourceUrl:'https://raw.githubusercontent.com/ggerganov/llama.cpp/4df29be4f4c3673f428170fda944a5b19f743bb8/LICENSE',
84
+ bytes:1078,
85
+ sha256:'94f29bbed6a22c35b992c5c6ebf0e7c92f13b836b90f36f461c9cf2f0f1d010d'
86
+ }
87
+ ]
88
+ }
89
+ ]
90
+ });
22
91
 
23
92
  const expectedFiles=Object.freeze([
93
+ ['ai/ARCANE_AI_BROWSER_WASM_COMPONENTS.json','browser-runtime/ai/ARCANE_AI_BROWSER_WASM_COMPONENTS.json','sdk-source-identity'],
94
+ ['ai/browser-wasm-llm-provider.mjs','browser-runtime/ai/browser-wasm-llm-provider.mjs','sdk-source-identity'],
95
+ ['ai/browser-wasm.mjs','browser-runtime/ai/browser-wasm.mjs','sdk-source-identity'],
96
+ ['ai/browser-wllama-runtime.mjs','browser-runtime/ai/browser-wllama-runtime.mjs','sdk-source-identity'],
97
+ ['ai/internal/sha256.mjs','browser-runtime/ai/internal/sha256.mjs','sdk-source-identity'],
98
+ ['ai/model-controller.mjs','browser-runtime/ai/model-controller.mjs','sdk-source-identity'],
99
+ ['ai/wllama/LICENCE','node_modules/@wllama/wllama/LICENCE','vendor-package-identity'],
100
+ ['ai/wllama/index.mjs','node_modules/@wllama/wllama/esm/index.js','vendor-package-identity'],
101
+ ['ai/wllama/llama.cpp-LICENSE','browser-runtime/ai/wllama/llama.cpp-LICENSE','vendor-source-identity'],
102
+ ['ai/wllama/wllama.wasm','node_modules/@wllama/wllama/esm/wasm/wllama.wasm','vendor-package-identity'],
24
103
  ['dependencies/event-pubsub/index.js','node_modules/event-pubsub/index.js','vendor-package-identity'],
25
104
  ['dependencies/event-pubsub/licence','node_modules/event-pubsub/licence','vendor-package-identity'],
26
105
  ['dependencies/event-pubsub/package.json','node_modules/event-pubsub/package.json','vendor-package-identity'],
@@ -83,13 +162,35 @@ function immutableInventory(files){
83
162
  return Object.freeze(files.map(file=>Object.freeze({...file})));
84
163
  }
85
164
 
165
+ function validateAiComponents(bytes,releaseFiles){
166
+ let receipt;
167
+ try{receipt=JSON.parse(bytes.toString('utf8'));}
168
+ catch(error){fail(`Arcane AI browser WASM component receipt is invalid JSON: ${error.message}`);}
169
+ if(JSON.stringify(receipt)!==JSON.stringify(expectedAiComponents)){
170
+ fail('Arcane AI browser WASM component authority is invalid.');
171
+ }
172
+ for(const component of receipt.components){
173
+ for(const file of component.files){
174
+ const declared=releaseFiles.find(candidate=>candidate.path===file.path);
175
+ if(!declared||declared.bytes!==file.bytes||declared.sha256!==file.sha256
176
+ ||('sourcePath' in file&&declared.sourcePath!==file.sourcePath)){
177
+ fail(`Arcane AI browser WASM component projection drifted for ${file.path}.`);
178
+ }
179
+ }
180
+ }
181
+ }
182
+
183
+ function requiresInstalledPackageSource(file){
184
+ return !file.sourcePath.startsWith('node_modules/@wllama/wllama/');
185
+ }
186
+
86
187
  function validateSource(source){
87
188
  if(!source||typeof source!=='object'||Array.isArray(source)
88
189
  ||!exactKeys(source,['authority','browserEntry','dependencies','protocol','repository'])
89
190
  ||source.authority!=='arcane-os-sdk'||source.browserEntry!=='arcane-os/event-manager'
90
191
  ||source.protocol!==PROTOCOL
91
192
  ||source.repository!==REPOSITORY||!Array.isArray(source.dependencies)
92
- ||source.dependencies.length!==2){
193
+ ||source.dependencies.length!==3){
93
194
  fail('SDK browser runtime manifest source authority is invalid.');
94
195
  }
95
196
  const expectedDependencies=[
@@ -104,6 +205,12 @@ function validateSource(source){
104
205
  version:'2.0.0',
105
206
  resolved:'https://registry.npmjs.org/strong-type/-/strong-type-2.0.0.tgz',
106
207
  integrity:'sha512-HHrY9qYC7yn+5mlewiI3k9RQM9gZqGQsqbomZcd10Ks0h4RlX01nnkWbCe4AsVPCI6KaFvpkWm1nHMD+Ykup6g=='
208
+ },
209
+ {
210
+ name:'@wllama/wllama',
211
+ version:'3.6.0',
212
+ resolved:'https://registry.npmjs.org/@wllama/wllama/-/wllama-3.6.0.tgz',
213
+ integrity:'sha512-NN3ZBXqaaUwGXTQubkNvsCaLPjN2XVa0bVS40OYCE8zquYmRc2W3oHYEgwvuSWWDB8aUqTLyMioySCXNkcnD1w=='
107
214
  }
108
215
  ];
109
216
  for(const [index,expected] of expectedDependencies.entries()){
@@ -514,6 +621,7 @@ export async function verifySdkBrowserRuntime({
514
621
  const identities=[];
515
622
  const sourceIdentities=[];
516
623
  const sourceRoot=path.dirname(canonical);
624
+ let aiComponentsBytes;
517
625
  let verifiedBytes=0;
518
626
  for(const [index,file] of release.files.entries()){
519
627
  throwIfAborted(signal);
@@ -527,23 +635,28 @@ export async function verifySdkBrowserRuntime({
527
635
  if(createHash('sha256').update(result.bytes).digest('hex')!==file.sha256){
528
636
  fail(`SDK browser runtime integrity check failed for ${file.path}.`);
529
637
  }
530
- const sourceResult=await openVerified(
531
- containedPath(sourceRoot,file.sourcePath,'source file'),
532
- {
533
- expectedBytes:file.bytes,
534
- root:sourceRoot,
535
- relative:file.sourcePath,
536
- signal
537
- }
538
- );
539
- if(!result.bytes.equals(sourceResult.bytes)){
540
- fail(
541
- `SDK browser runtime file does not match its declared package source: `
542
- +`${file.path} (${file.sourcePath}).`
638
+ if(file.path==='ai/ARCANE_AI_BROWSER_WASM_COMPONENTS.json'){
639
+ aiComponentsBytes=result.bytes;
640
+ }
641
+ if(requiresInstalledPackageSource(file)){
642
+ const sourceResult=await openVerified(
643
+ containedPath(sourceRoot,file.sourcePath,'source file'),
644
+ {
645
+ expectedBytes:file.bytes,
646
+ root:sourceRoot,
647
+ relative:file.sourcePath,
648
+ signal
649
+ }
543
650
  );
651
+ if(!result.bytes.equals(sourceResult.bytes)){
652
+ fail(
653
+ `SDK browser runtime file does not match its declared package source: `
654
+ +`${file.path} (${file.sourcePath}).`
655
+ );
656
+ }
657
+ sourceIdentities.push(Object.freeze({path:file.sourcePath,...sourceResult.identity}));
544
658
  }
545
659
  identities.push(Object.freeze({path:file.path,...result.identity}));
546
- sourceIdentities.push(Object.freeze({path:file.sourcePath,...sourceResult.identity}));
547
660
  verifiedBytes+=file.bytes;
548
661
  await emit(onEvent,{
549
662
  type:'sdk-browser-runtime.verify.progress',
@@ -554,6 +667,10 @@ export async function verifySdkBrowserRuntime({
554
667
  path:file.path
555
668
  });
556
669
  }
670
+ if(!aiComponentsBytes){
671
+ fail('Arcane AI browser WASM component receipt is missing.');
672
+ }
673
+ validateAiComponents(aiComponentsBytes,release.files);
557
674
  const receipt=Object.freeze({
558
675
  schemaVersion:1,
559
676
  kind:'arcane-sdk-browser-runtime-verification',
@@ -63,6 +63,12 @@ export function workspaceTemplate({
63
63
  version:'2.0.0',
64
64
  resolved:'https://registry.npmjs.org/strong-type/-/strong-type-2.0.0.tgz',
65
65
  integrity:'sha512-HHrY9qYC7yn+5mlewiI3k9RQM9gZqGQsqbomZcd10Ks0h4RlX01nnkWbCe4AsVPCI6KaFvpkWm1nHMD+Ykup6g=='
66
+ },
67
+ {
68
+ name:'@wllama/wllama',
69
+ version:'3.6.0',
70
+ resolved:'https://registry.npmjs.org/@wllama/wllama/-/wllama-3.6.0.tgz',
71
+ integrity:'sha512-NN3ZBXqaaUwGXTQubkNvsCaLPjN2XVa0bVS40OYCE8zquYmRc2W3oHYEgwvuSWWDB8aUqTLyMioySCXNkcnD1w=='
66
72
  }
67
73
  ];
68
74
  const packageInclude=[`${appId}.css`,'index.html'];
package/src/workspace.mjs CHANGED
@@ -325,9 +325,15 @@ function validateLock(lock){
325
325
  version:'2.0.0',
326
326
  resolved:'https://registry.npmjs.org/strong-type/-/strong-type-2.0.0.tgz',
327
327
  integrity:'sha512-HHrY9qYC7yn+5mlewiI3k9RQM9gZqGQsqbomZcd10Ks0h4RlX01nnkWbCe4AsVPCI6KaFvpkWm1nHMD+Ykup6g=='
328
+ },
329
+ {
330
+ name:'@wllama/wllama',
331
+ version:'3.6.0',
332
+ resolved:'https://registry.npmjs.org/@wllama/wllama/-/wllama-3.6.0.tgz',
333
+ integrity:'sha512-NN3ZBXqaaUwGXTQubkNvsCaLPjN2XVa0bVS40OYCE8zquYmRc2W3oHYEgwvuSWWDB8aUqTLyMioySCXNkcnD1w=='
328
334
  }
329
335
  ];
330
- const dependenciesMatch=Array.isArray(dependencies)&&dependencies.length===2
336
+ const dependenciesMatch=Array.isArray(dependencies)&&dependencies.length===expectedDependencies.length
331
337
  &&dependencies.every((actual,index)=>{
332
338
  const expected=expectedDependencies[index];
333
339
  return exactKeys(actual,['name','version','resolved','integrity'])