arcane-os 0.1.0-dev.5 → 0.1.1
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/NOTICE +10 -0
- package/browser-runtime/ARCANE_SDK_BROWSER_RELEASE.json +162 -0
- package/browser-runtime/ai/ARCANE_AI_BROWSER_WASM_COMPONENTS.json +69 -0
- package/browser-runtime/ai/browser-wasm-llm-provider.mjs +1151 -0
- package/browser-runtime/ai/browser-wasm.mjs +44 -0
- package/browser-runtime/ai/browser-wllama-runtime.mjs +390 -0
- package/browser-runtime/ai/internal/sha256.mjs +166 -0
- package/browser-runtime/ai/model-controller.mjs +581 -0
- package/browser-runtime/ai/wllama/LICENCE +21 -0
- package/browser-runtime/ai/wllama/index.mjs +3494 -0
- package/browser-runtime/ai/wllama/llama.cpp-LICENSE +21 -0
- package/browser-runtime/ai/wllama/wllama.wasm +0 -0
- package/browser-runtime/dependencies/event-pubsub/index.js +141 -0
- package/browser-runtime/dependencies/event-pubsub/licence +21 -0
- package/browser-runtime/dependencies/event-pubsub/package.json +59 -0
- package/browser-runtime/dependencies/strong-type/index.js +1151 -0
- package/browser-runtime/dependencies/strong-type/licence +21 -0
- package/browser-runtime/dependencies/strong-type/package.json +61 -0
- package/browser-runtime/dom-event-instrumentation.mjs +594 -0
- package/browser-runtime/event-manager.mjs +1342 -0
- package/docs/publishing.md +65 -67
- package/docs/reference/README.md +2 -1
- package/docs/reference/cli.md +86 -3
- package/docs/reference/event-manager.md +20 -11
- package/docs/reference/inventory/package-api.json +1 -1
- package/docs/reference/protocols.md +112 -14
- package/docs/reference/sdk-api.md +40 -11
- package/docs/work-amplification.md +4 -3
- package/package.json +15 -8
- package/runtime/ARCANE_RUNTIME_RELEASE.json +1 -1
- package/schemas/arcane-lock.schema.json +97 -1
- package/src/cli/main.mjs +5 -0
- package/src/dev-server.mjs +78 -34
- package/src/doctor.mjs +77 -3
- package/src/import-map.mjs +2352 -0
- package/src/packager/core.mjs +607 -29
- package/src/scaffold.mjs +122 -5
- package/src/sdk-browser-runtime.mjs +702 -0
- package/src/targets/index.mjs +31 -4
- package/src/templates/workspace-template.mjs +141 -23
- package/src/toolchain.mjs +288 -55
- package/src/workspace-operation-lock.mjs +716 -0
- package/src/workspace-runtime.mjs +841 -0
- package/src/workspace.mjs +292 -37
package/src/targets/index.mjs
CHANGED
|
@@ -163,6 +163,8 @@ const browserAdapter=Object.freeze({
|
|
|
163
163
|
dryRun=false,
|
|
164
164
|
signal,
|
|
165
165
|
onEvent,
|
|
166
|
+
workspaceOperationLease,
|
|
167
|
+
runtimeVerificationState,
|
|
166
168
|
validateSourceState
|
|
167
169
|
}={}){
|
|
168
170
|
await this.plan({workspaceRoot,appId,format,signing,signal});
|
|
@@ -173,17 +175,42 @@ const browserAdapter=Object.freeze({
|
|
|
173
175
|
dryRun,
|
|
174
176
|
signal,
|
|
175
177
|
onEvent,
|
|
178
|
+
workspaceOperationLease,
|
|
179
|
+
runtimeVerificationState,
|
|
176
180
|
validateSourceState
|
|
177
181
|
});
|
|
178
182
|
return {target:'browser',format,signing,release};
|
|
179
183
|
},
|
|
180
|
-
async verify({workspaceRoot,appId,signal,onEvent}={}){
|
|
184
|
+
async verify({workspaceRoot,appId,runtimeVerificationState,signal,onEvent}={}){
|
|
181
185
|
throwIfAborted(signal);
|
|
182
|
-
return {
|
|
186
|
+
return {
|
|
187
|
+
target:'browser',
|
|
188
|
+
release:await verifyApp({
|
|
189
|
+
workspaceRoot,
|
|
190
|
+
appId,
|
|
191
|
+
runtimeVerificationState,
|
|
192
|
+
signal,
|
|
193
|
+
onEvent
|
|
194
|
+
})
|
|
195
|
+
};
|
|
183
196
|
},
|
|
184
|
-
async run({
|
|
197
|
+
async run({
|
|
198
|
+
workspaceRoot,
|
|
199
|
+
appId,
|
|
200
|
+
runtimeVerificationState,
|
|
201
|
+
host='127.0.0.1',
|
|
202
|
+
port=0,
|
|
203
|
+
signal,
|
|
204
|
+
onEvent
|
|
205
|
+
}={}){
|
|
185
206
|
throwIfAborted(signal);
|
|
186
|
-
const verified=await verifyApp({
|
|
207
|
+
const verified=await verifyApp({
|
|
208
|
+
workspaceRoot,
|
|
209
|
+
appId,
|
|
210
|
+
runtimeVerificationState,
|
|
211
|
+
signal,
|
|
212
|
+
onEvent
|
|
213
|
+
});
|
|
187
214
|
const server=await startDevServer({
|
|
188
215
|
workspaceRoot,
|
|
189
216
|
appId,
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import {SDK_NAME,SDK_VERSION} from '../constants.mjs';
|
|
2
|
+
import {
|
|
3
|
+
SDK_BROWSER_RUNTIME_CONTENT_SHA256,
|
|
4
|
+
SDK_BROWSER_RUNTIME_MANIFEST_SHA256
|
|
5
|
+
} from '../sdk-browser-runtime.mjs';
|
|
2
6
|
|
|
3
7
|
function json(value){
|
|
4
8
|
return `${JSON.stringify(value,null,2)}\n`;
|
|
@@ -23,7 +27,9 @@ export function workspaceTemplate({
|
|
|
23
27
|
appId,
|
|
24
28
|
displayName,
|
|
25
29
|
runtimeRelease,
|
|
30
|
+
sdkBrowserRuntimeRelease,
|
|
26
31
|
appOnly=false,
|
|
32
|
+
namedImports=true,
|
|
27
33
|
minimumCoreVersion='0.8.12',
|
|
28
34
|
target='browser',
|
|
29
35
|
appIcon
|
|
@@ -42,6 +48,29 @@ export function workspaceTemplate({
|
|
|
42
48
|
const packageName=`arcane-${appId}`;
|
|
43
49
|
const runtimeContentSha256=runtimeRelease?.contentSha256;
|
|
44
50
|
const upstreamCommit=runtimeRelease?.source?.commit;
|
|
51
|
+
const browserManifestSha256=sdkBrowserRuntimeRelease?.manifestSha256;
|
|
52
|
+
const browserContentSha256=sdkBrowserRuntimeRelease?.contentSha256;
|
|
53
|
+
const browserSource=sdkBrowserRuntimeRelease?.source;
|
|
54
|
+
const expectedBrowserDependencies=[
|
|
55
|
+
{
|
|
56
|
+
name:'event-pubsub',
|
|
57
|
+
version:'6.1.0',
|
|
58
|
+
resolved:'https://registry.npmjs.org/event-pubsub/-/event-pubsub-6.1.0.tgz',
|
|
59
|
+
integrity:'sha512-FEMlhTxwqGM0hztTixG6FhVFXqp7Eq1ltk5mSreK6Mhy3xWWpLAzEUR6OMvMdNqT3jgSxA8JDhnhyAG3X4Xy7Q=='
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name:'strong-type',
|
|
63
|
+
version:'2.0.0',
|
|
64
|
+
resolved:'https://registry.npmjs.org/strong-type/-/strong-type-2.0.0.tgz',
|
|
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=='
|
|
72
|
+
}
|
|
73
|
+
];
|
|
45
74
|
const packageInclude=[`${appId}.css`,'index.html'];
|
|
46
75
|
if(native)packageInclude.push('img/icon.png');
|
|
47
76
|
packageInclude.push('manifest.json','modules');
|
|
@@ -72,7 +101,36 @@ appropriate.
|
|
|
72
101
|
if(!appOnly&&(typeof upstreamCommit!=='string'||!/^[a-f0-9]{40}$/.test(upstreamCommit))){
|
|
73
102
|
throw new Error('The SDK runtime release does not contain a valid upstream commit.');
|
|
74
103
|
}
|
|
104
|
+
if(!appOnly&&(
|
|
105
|
+
browserManifestSha256!==SDK_BROWSER_RUNTIME_MANIFEST_SHA256
|
|
106
|
+
||browserContentSha256!==SDK_BROWSER_RUNTIME_CONTENT_SHA256
|
|
107
|
+
||sdkBrowserRuntimeRelease?.builder!=='arcane-sdk-browser-runtime-v1'
|
|
108
|
+
||sdkBrowserRuntimeRelease?.sdkVersion!==SDK_VERSION
|
|
109
|
+
||browserSource?.protocol!=='arcane-sdk-browser-runtime/1'
|
|
110
|
+
||browserSource?.authority!=='arcane-os-sdk'
|
|
111
|
+
||browserSource?.repository!=='https://github.com/TheWizardNexus/arcane-os-sdk.git'
|
|
112
|
+
||browserSource?.browserEntry!=='arcane-os/event-manager'
|
|
113
|
+
||!Array.isArray(browserSource?.dependencies)
|
|
114
|
+
||browserSource.dependencies.length!==expectedBrowserDependencies.length
|
|
115
|
+
||browserSource.dependencies.some((actual,index)=>{
|
|
116
|
+
const expected=expectedBrowserDependencies[index];
|
|
117
|
+
return !actual||Object.keys(actual).sort().join('\0')
|
|
118
|
+
!==['name','version','resolved','integrity'].sort().join('\0')
|
|
119
|
+
||actual.name!==expected.name||actual.version!==expected.version
|
|
120
|
+
||actual.resolved!==expected.resolved||actual.integrity!==expected.integrity;
|
|
121
|
+
})
|
|
122
|
+
)){
|
|
123
|
+
throw new Error('The SDK browser runtime release does not contain a valid trusted identity.');
|
|
124
|
+
}
|
|
75
125
|
|
|
126
|
+
const importMapMarkup=namedImports?` <script type="importmap" data-arcane-import-map>
|
|
127
|
+
{
|
|
128
|
+
"imports": {}
|
|
129
|
+
}
|
|
130
|
+
</script>
|
|
131
|
+
`:'';
|
|
132
|
+
const bootstrapMarkup=namedImports?'':
|
|
133
|
+
' <script type="module" src="./arcane/modules/ThemeBootstrap.js?v=1"></script>\n';
|
|
76
134
|
const files=new Map();
|
|
77
135
|
files.set('.gitignore',[
|
|
78
136
|
'node_modules/',
|
|
@@ -96,7 +154,7 @@ appropriate.
|
|
|
96
154
|
|
|
97
155
|
- Use plain JavaScript, HTML, and CSS; do not introduce TypeScript or TSX.
|
|
98
156
|
- Keep reusable mechanisms in Arcane OS and app-specific behavior under \`apps/${appId}/\`.
|
|
99
|
-
- Keep \`arcane/css/theme.css\` and \`ThemeBootstrap
|
|
157
|
+
- Keep \`arcane/css/theme.css\` before app styles and import \`arcane/ThemeBootstrap\` before app code runs.
|
|
100
158
|
- Use \`rgb(...)\` or \`rgba(...)\` for new CSS colors.
|
|
101
159
|
- Build one named app and one explicit target at a time. Native targets may be unavailable until their adapters are installed.
|
|
102
160
|
- Run \`npm run check\` before committing.
|
|
@@ -113,20 +171,32 @@ npm run doctor
|
|
|
113
171
|
npm run dev
|
|
114
172
|
\`\`\`
|
|
115
173
|
|
|
116
|
-
Open the loopback URL printed by the development server. The source server exposes this app and
|
|
174
|
+
Open the loopback URL printed by the development server. The source server exposes this app and its authenticated physical \`arcane/\` runtime; it does not expose an Ollama HTTP endpoint.
|
|
117
175
|
|
|
118
176
|
Commit the generated \`package-lock.json\` after dependency installation. CI intentionally uses \`npm ci\` and therefore requires that lock. Before the SDK is published, install a locally packed \`${SDK_NAME}\` \`.tgz\` with \`npm install --save-dev --save-exact <path-to-tarball>\`; keep that tarball at the lock file's relative path for repeatable local \`npm ci\` runs.
|
|
119
177
|
|
|
120
|
-
## Check and package
|
|
178
|
+
## Check and release the browser package
|
|
121
179
|
|
|
122
180
|
\`\`\`sh
|
|
123
181
|
npm run check
|
|
182
|
+
npm run import-map
|
|
124
183
|
npm run package
|
|
184
|
+
npm run verify
|
|
185
|
+
npm run bundle
|
|
125
186
|
npm run run
|
|
126
187
|
\`\`\`
|
|
127
188
|
|
|
128
|
-
The
|
|
129
|
-
|
|
189
|
+
The explicit \`import-map\` command refreshes
|
|
190
|
+
\`apps/${appId}/modules/arcane.importmap.json\` and the managed inline browser
|
|
191
|
+
import map in \`index.html\`. Development, package, and build refresh it
|
|
192
|
+
automatically. Named \`arcane/*\` imports resolve against the physical workspace
|
|
193
|
+
\`arcane/\` tree. Packaging copies the same authenticated bytes and specifier map
|
|
194
|
+
to \`dist/${appId}\`, \`verify\` authenticates that directory, \`bundle\` creates
|
|
195
|
+
its distributable archive, and \`run\` launches the verified packaged browser
|
|
196
|
+
release.
|
|
197
|
+
|
|
198
|
+
Native targets are provider-supplied and must be scaffolded and selected
|
|
199
|
+
explicitly; this browser workflow does not imply a standalone native executable.
|
|
130
200
|
${nativeGuide}
|
|
131
201
|
|
|
132
202
|
Every browser release also carries Arcane OS licensing material under \`licenses/arcane-os/\`. Review those terms before distribution.
|
|
@@ -140,11 +210,16 @@ Every browser release also carries Arcane OS licensing material under \`licenses
|
|
|
140
210
|
dev:'arcane dev',
|
|
141
211
|
test:'arcane test',
|
|
142
212
|
check:'arcane check',
|
|
213
|
+
'import-map':'arcane import-map',
|
|
143
214
|
package:'arcane package',
|
|
215
|
+
verify:'arcane verify',
|
|
216
|
+
bundle:'arcane bundle',
|
|
144
217
|
build:`arcane build --target ${buildTarget}`,
|
|
145
218
|
run:`arcane run --target ${runTarget}`,
|
|
146
|
-
|
|
147
|
-
|
|
219
|
+
...(native?{
|
|
220
|
+
'build:browser':'arcane build --target browser',
|
|
221
|
+
'run:browser':'arcane run --target browser'
|
|
222
|
+
}:{})
|
|
148
223
|
},
|
|
149
224
|
devDependencies:{
|
|
150
225
|
[SDK_NAME]:SDK_VERSION
|
|
@@ -158,15 +233,9 @@ Every browser release also carries Arcane OS licensing material under \`licenses
|
|
|
158
233
|
sharedPayloads:{
|
|
159
234
|
'browser-runtime':[
|
|
160
235
|
{
|
|
161
|
-
source:'
|
|
236
|
+
source:'arcane',
|
|
162
237
|
destination:'arcane',
|
|
163
|
-
include:['components','css','entities','img','modules','security'],
|
|
164
|
-
exclude:[]
|
|
165
|
-
},
|
|
166
|
-
{
|
|
167
|
-
source:'node_modules/arcane-os/runtime/strong-type',
|
|
168
|
-
destination:'node_modules/strong-type',
|
|
169
|
-
include:['index.js','licence','package.json'],
|
|
238
|
+
include:['components','css','dependencies','entities','img','modules','sdk','security'],
|
|
170
239
|
exclude:[]
|
|
171
240
|
},
|
|
172
241
|
{
|
|
@@ -186,6 +255,14 @@ Every browser release also carries Arcane OS licensing material under \`licenses
|
|
|
186
255
|
contentSha256:runtimeContentSha256,
|
|
187
256
|
upstreamCommit
|
|
188
257
|
},
|
|
258
|
+
sdkBrowserRuntime:{
|
|
259
|
+
manifest:'node_modules/arcane-os/browser-runtime/ARCANE_SDK_BROWSER_RELEASE.json',
|
|
260
|
+
manifestSha256:browserManifestSha256,
|
|
261
|
+
contentSha256:browserContentSha256,
|
|
262
|
+
builder:sdkBrowserRuntimeRelease?.builder,
|
|
263
|
+
sdkVersion:sdkBrowserRuntimeRelease?.sdkVersion,
|
|
264
|
+
source:sdkBrowserRuntimeRelease?.source
|
|
265
|
+
},
|
|
189
266
|
protocols:{
|
|
190
267
|
arcane:'arcane/1',
|
|
191
268
|
cliEvents:'arcane-cli-events/1',
|
|
@@ -288,15 +365,14 @@ jobs:
|
|
|
288
365
|
<meta charset="utf-8">
|
|
289
366
|
<meta name="arcane-app-id" content="${html(appId)}">
|
|
290
367
|
<base href="../../">
|
|
291
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
368
|
+
${importMapMarkup} <meta name="viewport" content="width=device-width, initial-scale=1">
|
|
292
369
|
<meta name="theme-color" content="rgb(23, 34, 56)">
|
|
293
370
|
<title>${html(name)}</title>
|
|
294
371
|
<link rel="manifest" href="./apps/${html(appId)}/manifest.json">
|
|
295
372
|
<link rel="stylesheet" href="./arcane/css/theme.css?v=1">
|
|
296
373
|
<link rel="stylesheet" href="./arcane/css/primitives.css?v=1">
|
|
297
374
|
<link rel="stylesheet" href="./apps/${html(appId)}/${html(appId)}.css?v=1">
|
|
298
|
-
|
|
299
|
-
</head>
|
|
375
|
+
${bootstrapMarkup}</head>
|
|
300
376
|
<body>
|
|
301
377
|
<main class="app-shell">
|
|
302
378
|
<section class="arcane-card" aria-labelledby="app-title">
|
|
@@ -337,12 +413,49 @@ jobs:
|
|
|
337
413
|
text-transform: uppercase;
|
|
338
414
|
}
|
|
339
415
|
`);
|
|
340
|
-
|
|
416
|
+
if(namedImports){
|
|
417
|
+
files.set(`apps/${appId}/modules/arcane.importmap.json`,json({imports:{}}));
|
|
418
|
+
}
|
|
419
|
+
const themeSpecifier=namedImports
|
|
420
|
+
?'arcane/ThemeBootstrap':'../../../arcane/modules/ThemeBootstrap.js';
|
|
421
|
+
const appDataSpecifier=namedImports
|
|
422
|
+
?'arcane/AppDataScope':'../../../arcane/modules/AppDataScope.js';
|
|
423
|
+
files.set(`apps/${appId}/modules/App.js`,`import arcaneThemeReady from '${themeSpecifier}';
|
|
424
|
+
import {
|
|
425
|
+
resolveApplicationId,
|
|
426
|
+
resolveApplicationLocalStorageKey
|
|
427
|
+
} from '${appDataSpecifier}';
|
|
428
|
+
|
|
429
|
+
const appName=${JSON.stringify(name)};
|
|
341
430
|
const action=document.querySelector('#app-action');
|
|
342
431
|
const status=document.querySelector('#app-status');
|
|
343
432
|
|
|
433
|
+
await arcaneThemeReady;
|
|
434
|
+
|
|
435
|
+
const appId=await resolveApplicationId();
|
|
436
|
+
const countKey=resolveApplicationLocalStorageKey('hello-count',{applicationId:appId});
|
|
437
|
+
|
|
438
|
+
function loadHelloCount(){
|
|
439
|
+
try{
|
|
440
|
+
const value=Number(globalThis.localStorage?.getItem(countKey)??0);
|
|
441
|
+
return Number.isSafeInteger(value)&&value>=0?value:0;
|
|
442
|
+
}catch{
|
|
443
|
+
return 0;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
function saveHelloCount(value){
|
|
448
|
+
try{
|
|
449
|
+
globalThis.localStorage?.setItem(countKey,String(value));
|
|
450
|
+
}catch{
|
|
451
|
+
// The greeting still works when browser persistence is unavailable.
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
344
455
|
action?.addEventListener('click',()=>{
|
|
345
|
-
|
|
456
|
+
const count=loadHelloCount()+1;
|
|
457
|
+
saveHelloCount(count);
|
|
458
|
+
status.textContent=\`Hello from \${appName}! Greeting \${count}.\`;
|
|
346
459
|
});
|
|
347
460
|
`);
|
|
348
461
|
if(native){
|
|
@@ -355,17 +468,22 @@ import test from '${SDK_NAME}/testing';
|
|
|
355
468
|
const appRoot=new URL('../',import.meta.url);
|
|
356
469
|
|
|
357
470
|
test('application shell uses the shared Arcane theme in order',async()=>{
|
|
358
|
-
const source=await
|
|
471
|
+
const [source,appSource]=await Promise.all([
|
|
472
|
+
readFile(new URL('index.html',appRoot),'utf8'),
|
|
473
|
+
readFile(new URL('modules/App.js',appRoot),'utf8')
|
|
474
|
+
]);
|
|
359
475
|
const theme=source.indexOf('./arcane/css/theme.css');
|
|
360
476
|
const primitives=source.indexOf('./arcane/css/primitives.css');
|
|
361
477
|
const appStyle=source.indexOf('./apps/${appId}/${appId}.css');
|
|
362
|
-
const
|
|
478
|
+
const importMap=source.indexOf('${namedImports?'data-arcane-import-map':'./arcane/modules/ThemeBootstrap.js'}');
|
|
363
479
|
const appModule=source.indexOf('./apps/${appId}/modules/App.js');
|
|
364
480
|
|
|
365
481
|
assert.match(source,/<base href="\\.\\.\\/\\.\\.\\/">/);
|
|
366
482
|
assert.match(source,/<meta name="arcane-app-id" content="${appId}">/);
|
|
367
483
|
assert.ok(theme>=0&&primitives>theme&&appStyle>primitives);
|
|
368
|
-
assert.ok(
|
|
484
|
+
assert.ok(importMap>=0&&appModule>importMap);
|
|
485
|
+
assert.ok(appSource.includes("from '${themeSpecifier}'"));
|
|
486
|
+
assert.ok(appSource.includes("from '${appDataSpecifier}'"));
|
|
369
487
|
});
|
|
370
488
|
|
|
371
489
|
test('application package identity matches its directory',async()=>{
|