arcane-os 0.56.0 → 0.58.0
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/CHANGELOG.md +43 -0
- package/README.md +6 -2
- package/browser-runtime/ai/core-local.mjs +306 -0
- package/browser-runtime/ai/core-onnx.mjs +96 -0
- package/browser-runtime/ai/onnx-tensors.mjs +85 -0
- package/browser-runtime/core/client.mjs +151 -16
- package/docs/architecture.md +5 -2
- package/docs/platform-targets.md +30 -13
- package/docs/reference/README.md +38 -3
- package/docs/reference/availability-and-normalization.md +9 -6
- package/docs/reference/cli.md +29 -9
- package/docs/reference/core-client.md +80 -0
- package/docs/reference/core-native-packaging.md +304 -12
- package/docs/reference/core-preferences.md +49 -0
- package/docs/reference/diarization.md +206 -0
- package/docs/reference/git-text-snapshot.md +104 -0
- package/docs/reference/inventory/package-api.json +330 -22
- package/docs/reference/local-ai.md +331 -0
- package/docs/reference/protocols.md +97 -20
- package/docs/reference/pwa.md +5 -2
- package/docs/reference/runtime-modules.md +6 -5
- package/docs/reference/sdk-api.md +611 -63
- package/package.json +15 -3
- package/runtime/arcane/modules/LocalAIReadiness.js +3 -1
- package/schemas/arcane-app.schema.json +55 -1
- package/schemas/arcane-package.schema.json +44 -0
- package/schemas/native-build-plan.schema.json +27 -1
- package/schemas/target-adapter.schema.json +2 -0
- package/src/app-descriptor.mjs +18 -2
- package/src/cli/main.mjs +20 -4
- package/src/constants.mjs +2 -0
- package/src/core/host.mjs +23 -0
- package/src/core/hosts/macos/ArcaneCoreProcess.h +85 -0
- package/src/core/hosts/macos/ArcaneCoreProcess.m +357 -0
- package/src/core/hosts/macos/ArcaneHost.h +86 -0
- package/src/core/hosts/macos/ArcaneHost.m +455 -0
- package/src/core/hosts/macos/ArcaneLauncher.m +432 -0
- package/src/core/hosts/windows/ArcaneCoreProcess.cs +3 -3
- package/src/core/hosts/windows/ArcaneHost.cs +695 -0
- package/src/core/hosts/windows/ArcaneHost.manifest +22 -0
- package/src/core/hosts/windows/ArcaneLauncher.cs +239 -0
- package/src/core/services/local-ai.mjs +621 -0
- package/src/core/services/packaged-web.mjs +89 -0
- package/src/core/services/preferences.mjs +201 -0
- package/src/core-classic-source.mjs +2 -2
- package/src/dev-server.mjs +9 -5
- package/src/diarization/build.mjs +35 -0
- package/src/diarization/index.mjs +432 -0
- package/src/diarization/native/CMakeLists.txt +9 -0
- package/src/diarization/native/main.cpp +269 -0
- package/src/diarization/service.mjs +129 -0
- package/src/git-text-snapshot.mjs +265 -0
- package/src/import-map.mjs +2 -0
- package/src/index.mjs +1 -0
- package/src/local-ai/archive.mjs +52 -0
- package/src/local-ai/config.mjs +62 -0
- package/src/local-ai/dev.mjs +390 -0
- package/src/local-ai/discover.mjs +71 -0
- package/src/local-ai/http.mjs +106 -0
- package/src/local-ai/install.mjs +459 -0
- package/src/local-ai/onnx-worker.mjs +85 -0
- package/src/local-ai/onnx.mjs +368 -0
- package/src/local-ai/server.mjs +262 -0
- package/src/native/macos-provider.mjs +291 -0
- package/src/native/portable-layout.mjs +37 -4
- package/src/native/portable-provider.mjs +44 -8
- package/src/native/windows-provider.mjs +262 -0
- package/src/native-plan.mjs +9 -1
- package/src/native-provider-loader.mjs +10 -2
- package/src/packager/core.mjs +6 -2
- package/src/process.mjs +184 -20
- package/src/scaffold.mjs +1 -1
- package/src/targets/index.mjs +11 -1
- package/src/templates/workspace-template.mjs +6 -5
- package/src/toolchain.mjs +33 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "arcane-os",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.58.0",
|
|
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",
|
|
@@ -39,6 +39,8 @@
|
|
|
39
39
|
"./speech-playback": "./runtime/arcane/modules/SpeechPlayback.js",
|
|
40
40
|
"./speech-text": "./browser-runtime/speech-text.mjs",
|
|
41
41
|
"./ai/browser-wasm": "./browser-runtime/ai/browser-wasm.mjs",
|
|
42
|
+
"./ai/core-local": "./browser-runtime/ai/core-local.mjs",
|
|
43
|
+
"./ai/core-onnx": "./browser-runtime/ai/core-onnx.mjs",
|
|
42
44
|
"./ai/browser-decisions": "./browser-runtime/ai/browser-decisions.mjs",
|
|
43
45
|
"./ai/tool-text-stream": "./browser-runtime/ai/tool-text-stream.mjs",
|
|
44
46
|
"./ai/twin-cloud": "./browser-runtime/ai/twin-cloud.mjs",
|
|
@@ -49,12 +51,22 @@
|
|
|
49
51
|
"./native": "./src/native-plan.mjs",
|
|
50
52
|
"./native-provider": "./src/native-provider-loader.mjs",
|
|
51
53
|
"./native/portable-provider": "./src/native/portable-provider.mjs",
|
|
54
|
+
"./native/windows-provider": "./src/native/windows-provider.mjs",
|
|
55
|
+
"./native/macos-provider": "./src/native/macos-provider.mjs",
|
|
52
56
|
"./core/client": "./browser-runtime/core/client.mjs",
|
|
53
57
|
"./core/contracts": "./browser-runtime/core/contracts.mjs",
|
|
54
58
|
"./core/classic-source": "./src/core-classic-source.mjs",
|
|
55
59
|
"./core/runtime": "./src/core/runtime.mjs",
|
|
56
60
|
"./core/stdio": "./src/core/stdio.mjs",
|
|
57
61
|
"./core/host": "./src/core/host.mjs",
|
|
62
|
+
"./core/packaged-web": "./src/core/services/packaged-web.mjs",
|
|
63
|
+
"./core/preferences": "./src/core/services/preferences.mjs",
|
|
64
|
+
"./core/diarization": "./src/diarization/service.mjs",
|
|
65
|
+
"./core/local-ai": "./src/core/services/local-ai.mjs",
|
|
66
|
+
"./diarization": "./src/diarization/index.mjs",
|
|
67
|
+
"./diarization/build": "./src/diarization/build.mjs",
|
|
68
|
+
"./local-ai": "./src/local-ai/install.mjs",
|
|
69
|
+
"./local-ai/onnx": "./src/local-ai/onnx.mjs",
|
|
58
70
|
"./integrated-provider": "./src/integrated-provider-loader.mjs",
|
|
59
71
|
"./packager": "./src/packager/core.mjs",
|
|
60
72
|
"./release-bundle": "./src/release-bundle.mjs",
|
|
@@ -96,8 +108,8 @@
|
|
|
96
108
|
"test": "npm run test:unit && npm run test:functional && npm run test:integration && npm run test:regression",
|
|
97
109
|
"test:release": "node ./bin/arcane-test.mjs test/npm-release.test.mjs",
|
|
98
110
|
"test:unit": "node ./bin/arcane-test.mjs test/app-descriptor.test.mjs test/app-schema.test.mjs test/app-selection.test.mjs test/contracts.test.mjs test/conversation-closing-report.test.mjs test/doctor.test.mjs test/mail-credentials.test.mjs test/mail-outbox.test.mjs test/mail-public-api.test.mjs test/mail-send.test.mjs test/mail-transport.test.mjs test/targets.test.mjs test/workspace-operation-lock.test.mjs",
|
|
99
|
-
"test:functional": "node ./bin/arcane-test.mjs test/ai-request-model.test.mjs test/ai-request-retry.test.mjs test/ai-stream-cancellation.test.mjs test/browser-decisions.test.mjs test/browser-speech-providers.test.mjs test/browser-wasm-gpu-notice.test.mjs test/browser-wasm-download-resume.test.mjs test/chat-input.test.mjs test/chat-stream-speech.test.mjs test/chat-transcript-scroll.test.mjs test/chat-transient-retention.test.mjs test/cli.test.mjs test/continuous-voice-capture.test.mjs test/core-classic-source.test.mjs test/core-client.test.mjs test/core-host.test.mjs test/core-runtime.test.mjs test/core-stdio.test.mjs test/dbopfs-document-library.test.mjs test/dbopfs-png.test.mjs test/dbopfs.test.mjs test/dev-server.test.mjs test/dev-pwa.test.mjs test/dom-event-instrumentation.test.mjs test/event-manager.test.mjs test/events.test.mjs test/file-preview.test.mjs test/import-map.test.mjs test/mail-cli.test.mjs test/mail-runtime.test.mjs test/mail-server.test.mjs test/markdown-editor.test.mjs test/markdown-media.test.mjs test/markdown-source-map.test.mjs test/modal.test.mjs test/native-module-packaging.test.mjs test/native-module-resource-references.test.mjs test/packaging.test.mjs test/pwa-packaging.test.mjs test/pwa-client.test.mjs test/pwa-install.test.mjs test/pwa-worker.test.mjs test/persistent-ai-chat-session.test.mjs test/reference-completeness.test.mjs test/rendered-print.test.mjs test/runtime-api-behavior.test.mjs test/runtime.test.mjs test/scaffold.test.mjs test/speech-playback.test.mjs test/site.test.mjs test/theme-manager.test.mjs test/twin-cloud-images.test.mjs test/twin-cloud.test.mjs test/websocket-client-import-map.test.mjs test/websocket.test.mjs test/update-check.test.mjs test/user-explicit-updates.test.mjs",
|
|
100
|
-
"test:integration": "node ./bin/arcane-test.mjs test/installed-package-runtime.test.mjs test/root-app-layout.test.mjs test/integrated-shared.test.mjs test/integrated-workspace.test.mjs test/mail-browser.test.mjs test/native-plan.test.mjs test/native-portable-provider.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 test/browser-wasm-cpu.test.mjs test/wllama-webgpu-runtime.test.mjs",
|
|
111
|
+
"test:functional": "node ./bin/arcane-test.mjs test/ai-request-model.test.mjs test/ai-request-retry.test.mjs test/ai-stream-cancellation.test.mjs test/browser-decisions.test.mjs test/browser-speech-providers.test.mjs test/browser-wasm-gpu-notice.test.mjs test/browser-wasm-download-resume.test.mjs test/chat-input.test.mjs test/chat-stream-speech.test.mjs test/chat-transcript-scroll.test.mjs test/chat-transient-retention.test.mjs test/cli.test.mjs test/continuous-voice-capture.test.mjs test/core-classic-source.test.mjs test/core-client.test.mjs test/core-host.test.mjs test/core-packaged-web.test.mjs test/core-runtime.test.mjs test/core-stdio.test.mjs test/dbopfs-document-library.test.mjs test/dbopfs-png.test.mjs test/dbopfs.test.mjs test/dev-server.test.mjs test/dev-pwa.test.mjs test/dom-event-instrumentation.test.mjs test/event-manager.test.mjs test/events.test.mjs test/file-preview.test.mjs test/import-map.test.mjs test/mail-cli.test.mjs test/mail-runtime.test.mjs test/mail-server.test.mjs test/markdown-editor.test.mjs test/markdown-media.test.mjs test/markdown-source-map.test.mjs test/modal.test.mjs test/native-module-packaging.test.mjs test/native-module-resource-references.test.mjs test/packaging.test.mjs test/pwa-packaging.test.mjs test/pwa-client.test.mjs test/pwa-install.test.mjs test/pwa-worker.test.mjs test/persistent-ai-chat-session.test.mjs test/reference-completeness.test.mjs test/rendered-print.test.mjs test/runtime-api-behavior.test.mjs test/runtime.test.mjs test/scaffold.test.mjs test/speech-playback.test.mjs test/site.test.mjs test/theme-manager.test.mjs test/twin-cloud-images.test.mjs test/twin-cloud.test.mjs test/websocket-client-import-map.test.mjs test/websocket.test.mjs test/update-check.test.mjs test/user-explicit-updates.test.mjs",
|
|
112
|
+
"test:integration": "node ./bin/arcane-test.mjs test/installed-package-runtime.test.mjs test/root-app-layout.test.mjs test/integrated-shared.test.mjs test/integrated-workspace.test.mjs test/mail-browser.test.mjs test/native-macos-provider.test.mjs test/native-plan.test.mjs test/native-portable-provider.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 test/browser-wasm-cpu.test.mjs test/wllama-webgpu-runtime.test.mjs",
|
|
101
113
|
"test:regression": "node ./bin/arcane-test.mjs test/channel-workflows.test.mjs test/html-import-registration.test.mjs test/html-import-packaged-script.test.mjs test/logging-regression.test.mjs test/markdown-speech.test.mjs test/prepared-speech.test.mjs test/native-provider-generation.test.mjs test/speech-queue-regression.test.mjs test/testing.test.mjs test/test-sets.test.mjs",
|
|
102
114
|
"check": "node tools/check-source.mjs && npm test",
|
|
103
115
|
"check:release": "node tools/check-source.mjs --package-only && npm run test:release",
|
|
@@ -555,7 +555,9 @@ async function probeRequiredServices({
|
|
|
555
555
|
arcane,
|
|
556
556
|
requirements.llm.model
|
|
557
557
|
)
|
|
558
|
-
:
|
|
558
|
+
:is.function(arcane?.localAI?.status)
|
|
559
|
+
?probeNativeOllama(arcane,requirements.llm.model)
|
|
560
|
+
:unavailableBrowserOllama()
|
|
559
561
|
:null,
|
|
560
562
|
requiresSpeech
|
|
561
563
|
?mode==='native'
|
|
@@ -119,6 +119,19 @@
|
|
|
119
119
|
"oneOf": [{ "$ref": "#/$defs/rasterIcon" }, { "type": "null" }]
|
|
120
120
|
},
|
|
121
121
|
"order": { "type": "integer", "minimum": 0 },
|
|
122
|
+
"services": {
|
|
123
|
+
"description": "Explicit application-owned Core factory modules from the selected native release. Factories receive authored options first and launch context second.",
|
|
124
|
+
"type": "array",
|
|
125
|
+
"items": {
|
|
126
|
+
"type": "object",
|
|
127
|
+
"required": ["module"],
|
|
128
|
+
"properties": {
|
|
129
|
+
"module": { "$ref": "#/$defs/relativePath" },
|
|
130
|
+
"options": {}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
"localAI": { "$ref": "#/$defs/localAI" },
|
|
122
135
|
"bundledApps": {
|
|
123
136
|
"type": "array",
|
|
124
137
|
"uniqueItems": true,
|
|
@@ -167,7 +180,7 @@
|
|
|
167
180
|
"minItems": 1,
|
|
168
181
|
"uniqueItems": true,
|
|
169
182
|
"items": {
|
|
170
|
-
"enum": ["android-arm64", "browser", "linux-arm64", "linux-x64", "portable", "windows-x64"]
|
|
183
|
+
"enum": ["android-arm64", "browser", "linux-arm64", "linux-x64", "macos-arm64", "macos-x64", "portable", "windows-x64"]
|
|
171
184
|
}
|
|
172
185
|
}
|
|
173
186
|
},
|
|
@@ -240,6 +253,47 @@
|
|
|
240
253
|
}
|
|
241
254
|
],
|
|
242
255
|
"$defs": {
|
|
256
|
+
"localAI": {
|
|
257
|
+
"type": "object",
|
|
258
|
+
"required": ["runtimes"],
|
|
259
|
+
"description": "Required Core AI runtimes. Development ensures selected runtimes locally; native builds bundle their upstream runtime distributions. Model selection remains application-owned.",
|
|
260
|
+
"properties": {
|
|
261
|
+
"runtimes": {
|
|
262
|
+
"type": "array",
|
|
263
|
+
"items": {
|
|
264
|
+
"oneOf": [
|
|
265
|
+
{ "enum": ["llama.cpp", "ollama", "onnx"] },
|
|
266
|
+
{
|
|
267
|
+
"type": "object",
|
|
268
|
+
"required": ["id"],
|
|
269
|
+
"properties": {
|
|
270
|
+
"id": { "enum": ["llama.cpp", "ollama", "onnx"] },
|
|
271
|
+
"version": { "type": "string" },
|
|
272
|
+
"url": { "type": "string" }
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
]
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
"llamaCpp": {
|
|
279
|
+
"type": "object",
|
|
280
|
+
"properties": {
|
|
281
|
+
"url": { "type": "string" },
|
|
282
|
+
"model": { "type": "string" },
|
|
283
|
+
"modelsDirectory": { "type": "string" },
|
|
284
|
+
"args": { "type": "array", "items": { "type": "string" } }
|
|
285
|
+
}
|
|
286
|
+
},
|
|
287
|
+
"ollama": {
|
|
288
|
+
"type": "object",
|
|
289
|
+
"properties": {
|
|
290
|
+
"url": { "type": "string" },
|
|
291
|
+
"modelsDirectory": { "type": "string" },
|
|
292
|
+
"args": { "type": "array", "items": { "type": "string" } }
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
},
|
|
243
297
|
"pwa": {
|
|
244
298
|
"type": "object",
|
|
245
299
|
"additionalProperties": false,
|
|
@@ -57,6 +57,9 @@
|
|
|
57
57
|
"localAIModelPolicy": {
|
|
58
58
|
"$ref": "#/$defs/localAIModelPolicy"
|
|
59
59
|
},
|
|
60
|
+
"localAI": {
|
|
61
|
+
"$ref": "#/$defs/localAI"
|
|
62
|
+
},
|
|
60
63
|
"pwa": {
|
|
61
64
|
"$ref": "#/$defs/pwa"
|
|
62
65
|
},
|
|
@@ -144,6 +147,47 @@
|
|
|
144
147
|
}
|
|
145
148
|
],
|
|
146
149
|
"$defs": {
|
|
150
|
+
"localAI": {
|
|
151
|
+
"type": "object",
|
|
152
|
+
"required": ["runtimes"],
|
|
153
|
+
"description": "Required Core AI runtimes. Development ensures selected runtimes locally; native builds bundle their upstream runtime distributions. Model selection remains application-owned.",
|
|
154
|
+
"properties": {
|
|
155
|
+
"runtimes": {
|
|
156
|
+
"type": "array",
|
|
157
|
+
"items": {
|
|
158
|
+
"oneOf": [
|
|
159
|
+
{ "enum": ["llama.cpp", "ollama", "onnx"] },
|
|
160
|
+
{
|
|
161
|
+
"type": "object",
|
|
162
|
+
"required": ["id"],
|
|
163
|
+
"properties": {
|
|
164
|
+
"id": { "enum": ["llama.cpp", "ollama", "onnx"] },
|
|
165
|
+
"version": { "type": "string" },
|
|
166
|
+
"url": { "type": "string" }
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
]
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
"llamaCpp": {
|
|
173
|
+
"type": "object",
|
|
174
|
+
"properties": {
|
|
175
|
+
"url": { "type": "string" },
|
|
176
|
+
"model": { "type": "string" },
|
|
177
|
+
"modelsDirectory": { "type": "string" },
|
|
178
|
+
"args": { "type": "array", "items": { "type": "string" } }
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
"ollama": {
|
|
182
|
+
"type": "object",
|
|
183
|
+
"properties": {
|
|
184
|
+
"url": { "type": "string" },
|
|
185
|
+
"modelsDirectory": { "type": "string" },
|
|
186
|
+
"args": { "type": "array", "items": { "type": "string" } }
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
},
|
|
147
191
|
"pwa": {
|
|
148
192
|
"type": "object",
|
|
149
193
|
"additionalProperties": false,
|
|
@@ -117,7 +117,7 @@
|
|
|
117
117
|
{
|
|
118
118
|
"properties": {
|
|
119
119
|
"target": { "const": "portable" },
|
|
120
|
-
"platform": { "enum": ["windows", "linux"] },
|
|
120
|
+
"platform": { "enum": ["windows", "linux", "macos"] },
|
|
121
121
|
"architecture": { "enum": ["x64", "arm64"] },
|
|
122
122
|
"format": { "const": "portable" }
|
|
123
123
|
}
|
|
@@ -163,6 +163,32 @@
|
|
|
163
163
|
}
|
|
164
164
|
]
|
|
165
165
|
},
|
|
166
|
+
{
|
|
167
|
+
"allOf": [
|
|
168
|
+
{ "$ref": "#/$defs/unsignedTargetRequest" },
|
|
169
|
+
{
|
|
170
|
+
"properties": {
|
|
171
|
+
"target": { "const": "macos-arm64" },
|
|
172
|
+
"platform": { "const": "macos" },
|
|
173
|
+
"architecture": { "const": "arm64" },
|
|
174
|
+
"format": { "const": "app" }
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
]
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
"allOf": [
|
|
181
|
+
{ "$ref": "#/$defs/unsignedTargetRequest" },
|
|
182
|
+
{
|
|
183
|
+
"properties": {
|
|
184
|
+
"target": { "const": "macos-x64" },
|
|
185
|
+
"platform": { "const": "macos" },
|
|
186
|
+
"architecture": { "const": "x64" },
|
|
187
|
+
"format": { "const": "app" }
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
]
|
|
191
|
+
},
|
|
166
192
|
{
|
|
167
193
|
"type": "object",
|
|
168
194
|
"required": ["target", "platform", "architecture", "format", "signing", "signingProfileId"],
|
package/src/app-descriptor.mjs
CHANGED
|
@@ -5,6 +5,7 @@ import {readFile, writeFile} from 'node:fs/promises';
|
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
import {throwIfAborted} from './errors.mjs';
|
|
7
7
|
import {normalizePwaConfig} from './pwa.mjs';
|
|
8
|
+
import {normalizeLocalAIConfig} from './local-ai/config.mjs';
|
|
8
9
|
import {
|
|
9
10
|
ARCANE_MACHINE_BUNDLE_VERSION,
|
|
10
11
|
ARCANE_PROTOCOL,
|
|
@@ -235,7 +236,7 @@ function validateDocumentCatalog(value){
|
|
|
235
236
|
}
|
|
236
237
|
|
|
237
238
|
function validateNative(value,appId){
|
|
238
|
-
assertOnlyKeys(value,new Set(['type','icon','order','bundledApps','documentCatalog']),'descriptor.native');
|
|
239
|
+
assertOnlyKeys(value,new Set(['type','icon','order','bundledApps','documentCatalog','localAI','services']),'descriptor.native');
|
|
239
240
|
if(!NATIVE_TYPES.has(value.type))fail('descriptor.native.type is unsupported.');
|
|
240
241
|
const icon=value.icon===null?null:normalizeRelativePath(value.icon,'descriptor.native.icon');
|
|
241
242
|
if(!is.integer(value.order)||value.order<0){
|
|
@@ -245,11 +246,21 @@ function validateNative(value,appId){
|
|
|
245
246
|
pattern:APP_ID_PATTERN
|
|
246
247
|
});
|
|
247
248
|
const documentCatalog=validateDocumentCatalog(value.documentCatalog);
|
|
249
|
+
let services;
|
|
250
|
+
if(value.services!==undefined){
|
|
251
|
+
if(!is.array(value.services))fail('descriptor.native.services must be an array.');
|
|
252
|
+
services=value.services.map(function nativeService(service,index){
|
|
253
|
+
if(!isObject(service))fail(`descriptor.native.services[${index}] must be an object.`);
|
|
254
|
+
return {...service,module:normalizeRelativePath(service.module,`descriptor.native.services[${index}].module`)};
|
|
255
|
+
});
|
|
256
|
+
}
|
|
248
257
|
return completeValue({
|
|
249
258
|
type:value.type,
|
|
250
259
|
icon,
|
|
251
260
|
order:value.order,
|
|
252
261
|
bundledApps,
|
|
262
|
+
...(services===undefined?{}:{services}),
|
|
263
|
+
...(value.localAI===undefined?{}:{localAI:normalizeLocalAIConfig(value.localAI)}),
|
|
253
264
|
...(documentCatalog?{documentCatalog}:{})
|
|
254
265
|
});
|
|
255
266
|
}
|
|
@@ -337,6 +348,7 @@ export function projectPackageManifest(descriptor){
|
|
|
337
348
|
mediaOrigins:[...value.security.mediaOrigins]
|
|
338
349
|
}}:{}),
|
|
339
350
|
...(value.package.localAIModelPolicy?{localAIModelPolicy:value.package.localAIModelPolicy}:{}),
|
|
351
|
+
...(value.native.localAI===undefined?{}:{localAI:value.native.localAI}),
|
|
340
352
|
...(value.package.pwa===undefined?{}:{pwa:value.package.pwa}),
|
|
341
353
|
include:[...value.package.include],
|
|
342
354
|
exclude:[...value.package.exclude],
|
|
@@ -382,6 +394,8 @@ export function projectNativeDescriptor(descriptor,{source}={}){
|
|
|
382
394
|
}}:{}),
|
|
383
395
|
...(value.native.bundledApps.length?{bundledApps:[...value.native.bundledApps]}:{}),
|
|
384
396
|
...(value.native.documentCatalog?{documentCatalog:value.native.documentCatalog}:{}),
|
|
397
|
+
...(value.native.services===undefined?{}:{services:value.native.services}),
|
|
398
|
+
...(value.native.localAI===undefined?{}:{localAI:value.native.localAI}),
|
|
385
399
|
include:[...value.package.include]
|
|
386
400
|
};
|
|
387
401
|
}
|
|
@@ -425,6 +439,8 @@ function synthesizedDescriptor(packageManifest,nativeDescriptor){
|
|
|
425
439
|
icon:native.icon??null,
|
|
426
440
|
order:is.integer(native.order)?native.order:100,
|
|
427
441
|
bundledApps:[...(native.bundledApps??[])],
|
|
442
|
+
...(native.services===undefined?{}:{services:native.services}),
|
|
443
|
+
...((packageManifest.localAI??native.localAI)===undefined?{}:{localAI:packageManifest.localAI??native.localAI}),
|
|
428
444
|
...(native.documentCatalog?{documentCatalog:native.documentCatalog}:{})
|
|
429
445
|
},
|
|
430
446
|
requirements:{
|
|
@@ -433,7 +449,7 @@ function synthesizedDescriptor(packageManifest,nativeDescriptor){
|
|
|
433
449
|
features:[]
|
|
434
450
|
},
|
|
435
451
|
targets:nativeDescriptor!==undefined
|
|
436
|
-
?['android-arm64','browser','linux-arm64','linux-x64','portable','windows-x64']
|
|
452
|
+
?['android-arm64','browser','linux-arm64','linux-x64','macos-arm64','macos-x64','portable','windows-x64']
|
|
437
453
|
:['browser']
|
|
438
454
|
},{appId:packageManifest.id});
|
|
439
455
|
}
|
package/src/cli/main.mjs
CHANGED
|
@@ -16,6 +16,7 @@ const VALUE_OPTIONS=new Set([
|
|
|
16
16
|
'app',
|
|
17
17
|
'apps-root',
|
|
18
18
|
'sdk-runtime-source',
|
|
19
|
+
'local-ai',
|
|
19
20
|
'arcane-root',
|
|
20
21
|
'host',
|
|
21
22
|
'port',
|
|
@@ -66,7 +67,7 @@ Usage:
|
|
|
66
67
|
${CLI_NAME} upgrade [--workspace <directory>] [--app <id>]
|
|
67
68
|
${CLI_NAME} doctor [--workspace <directory>] [--arcane-root <directory>]
|
|
68
69
|
${CLI_NAME} import-map [--workspace <directory>] [--app <id>]
|
|
69
|
-
${CLI_NAME} dev [--app <id>] [--public] [--http | --https] [--cert <pem>] [--key <pem>] [--host <address>] [--port 8000] [--http-port 0] [--sdk-runtime-source <sdk-root>]
|
|
70
|
+
${CLI_NAME} dev [--app <id>] [--public] [--http | --https] [--cert <pem>] [--key <pem>] [--host <address>] [--port 8000] [--http-port 0] [--sdk-runtime-source <sdk-root>] [--local-ai llama.cpp,ollama,onnx]
|
|
70
71
|
${CLI_NAME} test [--app <id>] [--scope app]
|
|
71
72
|
${CLI_NAME} test --scope shared --test-file <repo-relative.test.mjs>
|
|
72
73
|
${CLI_NAME} check [--app <id>] [--scope app] [--skip-tests]
|
|
@@ -97,6 +98,7 @@ Development:
|
|
|
97
98
|
--host <address> Override the bind address; takes precedence over --public.
|
|
98
99
|
--http-port <port> Browser dev/run HTTP redirect port; 0 selects an available port (default).
|
|
99
100
|
--sdk-runtime-source <sdk-root> Dev-only live SDK checkout; omitted preserves the workspace runtime mode.
|
|
101
|
+
--local-ai <runtimes> Add required Core runtimes to app config and ensure them for development.
|
|
100
102
|
|
|
101
103
|
Global:
|
|
102
104
|
--workspace <directory> Select an external or integrated Arcane workspace.
|
|
@@ -450,6 +452,9 @@ function operationOptions(command,parsed,cwd){
|
|
|
450
452
|
if(values['sdk-runtime-source']!==undefined&&command!=='dev'){
|
|
451
453
|
usage('--sdk-runtime-source is supported only by dev.');
|
|
452
454
|
}
|
|
455
|
+
if(values['local-ai']!==undefined&&command!=='dev'){
|
|
456
|
+
usage('--local-ai is supported only by dev.');
|
|
457
|
+
}
|
|
453
458
|
if(flags.has('public')&&command!=='dev'){
|
|
454
459
|
usage('--public is supported only by dev.');
|
|
455
460
|
}
|
|
@@ -546,6 +551,7 @@ function operationOptions(command,parsed,cwd){
|
|
|
546
551
|
...browserServerOptions,
|
|
547
552
|
host:values.host??(flags.has('public')?'0.0.0.0':'127.0.0.1'),
|
|
548
553
|
port:readPort(values.port,8000),
|
|
554
|
+
...(values['local-ai']===undefined?{}:{localAI:values['local-ai']}),
|
|
549
555
|
...(values['sdk-runtime-source']===undefined?{}:{
|
|
550
556
|
sdkRuntimeSourceRoot:path.resolve(cwd,values['sdk-runtime-source'])
|
|
551
557
|
})
|
|
@@ -732,6 +738,16 @@ function operationOptions(command,parsed,cwd){
|
|
|
732
738
|
}
|
|
733
739
|
|
|
734
740
|
const NATIVE_REQUESTS={
|
|
741
|
+
'macos-arm64':{
|
|
742
|
+
platform:'macos',architecture:'arm64',defaultFormat:'app',formats:new Set(['app']),
|
|
743
|
+
defaultSigning:'unsigned-local-test',defaultProfileId:null,
|
|
744
|
+
signingModes:new Set(['unsigned-local-test'])
|
|
745
|
+
},
|
|
746
|
+
'macos-x64':{
|
|
747
|
+
platform:'macos',architecture:'x64',defaultFormat:'app',formats:new Set(['app']),
|
|
748
|
+
defaultSigning:'unsigned-local-test',defaultProfileId:null,
|
|
749
|
+
signingModes:new Set(['unsigned-local-test'])
|
|
750
|
+
},
|
|
735
751
|
'windows-x64':{
|
|
736
752
|
platform:'windows',architecture:'x64',defaultFormat:'exe',formats:new Set(['exe']),
|
|
737
753
|
defaultSigning:'unsigned-local-test',defaultProfileId:null,
|
|
@@ -755,9 +771,9 @@ const NATIVE_REQUESTS={
|
|
|
755
771
|
};
|
|
756
772
|
|
|
757
773
|
function portableRequestDefinition(){
|
|
758
|
-
const platform=process.platform==='win32'?'windows':process.platform;
|
|
774
|
+
const platform=process.platform==='win32'?'windows':process.platform==='darwin'?'macos':process.platform;
|
|
759
775
|
const architecture=process.arch==='x64'?'x64':process.arch==='arm64'?'arm64':process.arch;
|
|
760
|
-
if(!['windows','linux'].includes(platform)||!['x64','arm64'].includes(architecture)){
|
|
776
|
+
if(!['windows','linux','macos'].includes(platform)||!['x64','arm64'].includes(architecture)){
|
|
761
777
|
throw new ArcaneError(
|
|
762
778
|
ERROR_CODES.targetUnavailable,
|
|
763
779
|
`The portable native provider does not support ${process.platform}/${process.arch}.`
|
|
@@ -811,7 +827,7 @@ async function pairNativeProvider(command,options,loadProvider,{signal,onEvent}=
|
|
|
811
827
|
usage(`${command} requires one native target.`);
|
|
812
828
|
}
|
|
813
829
|
const targetRequest=createNativeTargetRequest(options);
|
|
814
|
-
if(!options.arcaneRoot
|
|
830
|
+
if(!options.arcaneRoot&&!['portable','windows-x64','macos-arm64','macos-x64'].includes(options.target)){
|
|
815
831
|
usage(`${command} for target ${options.target} requires --arcane-root <directory>.`);
|
|
816
832
|
}
|
|
817
833
|
const loaded=await loadProvider({
|
package/src/constants.mjs
CHANGED
package/src/core/host.mjs
CHANGED
|
@@ -1,6 +1,29 @@
|
|
|
1
|
+
import {readFile} from 'node:fs/promises';
|
|
2
|
+
import Is from 'strong-type';
|
|
1
3
|
import {createCoreRuntime} from './runtime.mjs';
|
|
2
4
|
import {startCoreStdio} from './stdio.mjs';
|
|
3
5
|
|
|
6
|
+
const is = new Is(false);
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Read only the explicitly supplied --arcane-launch-config filename.
|
|
10
|
+
* Return the complete JSON object for the service factories' second argument;
|
|
11
|
+
* field meanings belong to the launch owner and individual services.
|
|
12
|
+
*/
|
|
13
|
+
export async function readCoreLaunchContext({argv = process.argv.slice(2)} = {}) {
|
|
14
|
+
const flag = argv.indexOf('--arcane-launch-config');
|
|
15
|
+
if (flag === -1) return {};
|
|
16
|
+
const filename = argv[flag + 1];
|
|
17
|
+
if (filename === undefined || filename === '') {
|
|
18
|
+
throw new TypeError('--arcane-launch-config requires a filename.');
|
|
19
|
+
}
|
|
20
|
+
const context = JSON.parse(await readFile(filename, 'utf8'));
|
|
21
|
+
if (context === null || !is.object(context) || is.array(context)) {
|
|
22
|
+
throw new TypeError('Core launch configuration must be a JSON object.');
|
|
23
|
+
}
|
|
24
|
+
return context;
|
|
25
|
+
}
|
|
26
|
+
|
|
4
27
|
/** Compose app services with the shared dispatcher and draining transport. */
|
|
5
28
|
export function startCoreHost({application, version, services = [], input, output, onError, signal} = {}) {
|
|
6
29
|
const runtime = createCoreRuntime({application, version, services});
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#import <Foundation/Foundation.h>
|
|
2
|
+
|
|
3
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
4
|
+
|
|
5
|
+
@class ArcaneCoreProcess;
|
|
6
|
+
|
|
7
|
+
typedef NS_ENUM(NSUInteger, ArcaneCoreOutputStream) {
|
|
8
|
+
ArcaneCoreStandardOutput,
|
|
9
|
+
ArcaneCoreStandardError
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Callbacks run on process-owned background queues. Each output stream retains
|
|
14
|
+
* its order; different streams, writes and exit observation can be concurrent.
|
|
15
|
+
* Marshal UI work at the host. Callbacks must return normally and must not wait
|
|
16
|
+
* for another callback or for completion. The process retains its delegate
|
|
17
|
+
* through didCompleteWithErrors, then releases it.
|
|
18
|
+
*
|
|
19
|
+
* receivedOutputData delivers every unmodified stdout/stderr chunk. Stdout
|
|
20
|
+
* includes framing; receivedFrameData additionally delivers each complete
|
|
21
|
+
* opaque JSON body. No payload is decoded, parsed or rewritten here. Following
|
|
22
|
+
* a framing error, raw stdout continues to EOF without guessing a new boundary.
|
|
23
|
+
*/
|
|
24
|
+
@protocol ArcaneCoreProcessDelegate <NSObject>
|
|
25
|
+
- (void)coreProcess:(ArcaneCoreProcess *)process didLaunch:(pid_t)processIdentifier;
|
|
26
|
+
- (void)coreProcess:(ArcaneCoreProcess *)process receivedFrameData:(NSData *)data;
|
|
27
|
+
- (void)coreProcess:(ArcaneCoreProcess *)process receivedOutputData:(NSData *)data
|
|
28
|
+
stream:(ArcaneCoreOutputStream)stream;
|
|
29
|
+
- (void)coreProcess:(ArcaneCoreProcess *)process didEncounterError:(NSError *)error;
|
|
30
|
+
- (void)coreProcess:(ArcaneCoreProcess *)process didExitWithStatus:(int)status
|
|
31
|
+
reason:(NSTaskTerminationReason)reason;
|
|
32
|
+
/**
|
|
33
|
+
* Last callback: launch/exit observation, accepted writes and both streams have
|
|
34
|
+
* settled, successfully or with reported errors. Launch failure has no exit
|
|
35
|
+
* callback; an exit-observation failure is not proof that the child exited.
|
|
36
|
+
*/
|
|
37
|
+
- (void)coreProcess:(ArcaneCoreProcess *)process didCompleteWithErrors:(NSArray<NSError *> *)errors;
|
|
38
|
+
@end
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Foundation-only ownership of one explicit Core executable and framed pipes.
|
|
42
|
+
* Compile with Objective-C ARC and blocks; no third-party runtime is linked.
|
|
43
|
+
*/
|
|
44
|
+
API_AVAILABLE(macos(11.0))
|
|
45
|
+
@interface ArcaneCoreProcess : NSObject
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Starts asynchronously without shell execution, PATH lookup, environment
|
|
49
|
+
* mutation or a foreground wait. Arguments exclude argv[0]; the selected child
|
|
50
|
+
* inherits the host environment. Launch failure is reported through the
|
|
51
|
+
* delegate and completion. Callbacks can begin before this method returns.
|
|
52
|
+
*/
|
|
53
|
+
+ (instancetype)startExecutableURL:(NSURL *)executableURL
|
|
54
|
+
arguments:(NSArray<NSString *> *)arguments
|
|
55
|
+
workingDirectoryURL:(NSURL *)workingDirectoryURL
|
|
56
|
+
delegate:(id<ArcaneCoreProcessDelegate>)delegate;
|
|
57
|
+
|
|
58
|
+
/** Zero until a successful launch; the original child PID remains after exit. */
|
|
59
|
+
@property(nonatomic, readonly) pid_t processIdentifier;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Copies and queues the complete opaque JSON body. YES accepts the write and
|
|
63
|
+
* calls completion exactly once on the input queue. nil completion-error means
|
|
64
|
+
* the full frame reached child stdin, not that Core accepted or completed its
|
|
65
|
+
* operation. NO supplies a synchronous error and never calls completion.
|
|
66
|
+
* A partial/failed write is never retried. Payload length is transport framing
|
|
67
|
+
* only, never an application limit or policy.
|
|
68
|
+
*/
|
|
69
|
+
- (BOOL)sendJSONData:(NSData *)data
|
|
70
|
+
completion:(void (^)(NSError * _Nullable error))completion
|
|
71
|
+
error:(NSError * _Nullable * _Nullable)error;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Idempotent and nonblocking: reject new sends, finish accepted writes, then
|
|
75
|
+
* close stdin. Keep reading stdout/stderr and observe child exit. There is no
|
|
76
|
+
* forced termination or deadline. Accepted service work can outlive a renderer;
|
|
77
|
+
* renderer cancellation belongs to the public Core control protocol.
|
|
78
|
+
*/
|
|
79
|
+
- (void)closeInput;
|
|
80
|
+
|
|
81
|
+
- (instancetype)init NS_UNAVAILABLE;
|
|
82
|
+
+ (instancetype)new NS_UNAVAILABLE;
|
|
83
|
+
@end
|
|
84
|
+
|
|
85
|
+
NS_ASSUME_NONNULL_END
|