arcane-os 0.3.0 → 0.3.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 (153) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +86 -117
  3. package/bin/arcane-test.mjs +170 -46
  4. package/browser-runtime/ai/browser-speech-artifacts.mjs +887 -909
  5. package/browser-runtime/ai/browser-speech-providers.mjs +96 -152
  6. package/browser-runtime/ai/browser-wasm-llm-provider.mjs +627 -819
  7. package/browser-runtime/ai/browser-wasm.mjs +24 -35
  8. package/browser-runtime/ai/browser-wllama-runtime.mjs +64 -316
  9. package/browser-runtime/ai/model-controller.mjs +584 -181
  10. package/browser-runtime/ai/speech-worker-client.mjs +8 -146
  11. package/browser-runtime/ai/speech-worker-runtime.mjs +643 -363
  12. package/browser-runtime/dom-event-instrumentation.mjs +55 -147
  13. package/browser-runtime/event-manager.mjs +239 -624
  14. package/package.json +5 -6
  15. package/runtime/arcane/components/app-bar.html +3 -15
  16. package/runtime/arcane/components/assistant-panel.html +10 -10
  17. package/runtime/arcane/components/calculator.html +1 -1
  18. package/runtime/arcane/components/chat.html +1359 -135
  19. package/runtime/arcane/components/conversation-view.html +2 -2
  20. package/runtime/arcane/components/document-inspector.html +11 -17
  21. package/runtime/arcane/components/file-manager.html +13 -56
  22. package/runtime/arcane/components/markdown-document.html +82 -281
  23. package/runtime/arcane/components/markdown-editor.html +7 -10
  24. package/runtime/arcane/components/media-embed.html +6 -6
  25. package/runtime/arcane/components/screen-capture.html +4 -4
  26. package/runtime/arcane/components/source-explanation.html +2 -2
  27. package/runtime/arcane/components/speech.html +112 -68
  28. package/runtime/arcane/components/terminal-workspace.html +4 -4
  29. package/runtime/arcane/components/theme-editor.html +1 -1
  30. package/runtime/arcane/components/unified-inbox.html +2 -2
  31. package/runtime/arcane/components/voice-transcription.html +31 -21
  32. package/runtime/arcane/entities/Calculation.js +2 -3
  33. package/runtime/arcane/entities/Chat.js +228 -43
  34. package/runtime/arcane/entities/Preference.js +3 -5
  35. package/runtime/arcane/entities/Weather.js +5 -5
  36. package/runtime/arcane/modules/AI.js +1050 -427
  37. package/runtime/arcane/modules/AIProviderRuntime.js +658 -363
  38. package/runtime/arcane/modules/AIResponseLength.js +9 -19
  39. package/runtime/arcane/modules/AIRuntimeState.js +109 -72
  40. package/runtime/arcane/modules/ArcaneNavigationPolicy.js +45 -32
  41. package/runtime/arcane/modules/BrowserTestSuite.js +78 -122
  42. package/runtime/arcane/modules/CalculatorEngine.js +9 -9
  43. package/runtime/arcane/modules/CommunicationAppController.js +3 -7
  44. package/runtime/arcane/modules/ComponentContracts.js +30 -32
  45. package/runtime/arcane/modules/ConfiguredAIChatSession.js +281 -230
  46. package/runtime/arcane/modules/ConversationActionItems.js +26 -59
  47. package/runtime/arcane/modules/ConversationClosingReport.js +34 -61
  48. package/runtime/arcane/modules/ConversationTimebox.js +27 -15
  49. package/runtime/arcane/modules/DBOPFSDocumentLibrary.js +152 -344
  50. package/runtime/arcane/modules/DocumentLexicalSearch.js +25 -91
  51. package/runtime/arcane/modules/HTMLImport.js +54 -1
  52. package/runtime/arcane/modules/IsolatedModelQuestionRunner.js +40 -203
  53. package/runtime/arcane/modules/LocalAIReadiness.js +40 -60
  54. package/runtime/arcane/modules/LocalAIReadinessController.js +15 -13
  55. package/runtime/arcane/modules/MD.js +1 -45
  56. package/runtime/arcane/modules/Mail.js +51 -103
  57. package/runtime/arcane/modules/MailOutbox.mjs +95 -193
  58. package/runtime/arcane/modules/MailTransport.mjs +36 -57
  59. package/runtime/arcane/modules/ModelDefinition.js +22 -106
  60. package/runtime/arcane/modules/OpenMeteoWeatherProvider.js +39 -101
  61. package/runtime/arcane/modules/PersistentAIChatSession.js +281 -18
  62. package/runtime/arcane/modules/PreferenceStore.js +102 -30
  63. package/runtime/arcane/modules/RiskSignalAnalyzer.js +8 -9
  64. package/runtime/arcane/modules/ScopedOPFSCache.js +7 -42
  65. package/runtime/arcane/modules/ScreenCapture.js +175 -128
  66. package/runtime/arcane/modules/SpeechPlayback.js +46 -149
  67. package/runtime/arcane/modules/StaticDocumentCatalog.js +173 -407
  68. package/runtime/arcane/modules/ToolCallRouter.js +25 -12
  69. package/runtime/arcane/modules/YouTubeMedia.js +6 -5
  70. package/schemas/arcane-app-bundle.schema.json +13 -78
  71. package/schemas/arcane-app.schema.json +9 -25
  72. package/schemas/arcane-lock.schema.json +18 -151
  73. package/schemas/arcane-package.schema.json +2 -16
  74. package/schemas/native-build-plan.schema.json +119 -122
  75. package/src/app-descriptor.mjs +75 -132
  76. package/src/application-tests.mjs +200 -0
  77. package/src/cli/main.mjs +27 -46
  78. package/src/constants.mjs +3 -4
  79. package/src/dev-server.mjs +30 -324
  80. package/src/doctor.mjs +92 -154
  81. package/src/dom-event-instrumentation.mjs +55 -147
  82. package/src/errors.mjs +2 -3
  83. package/src/event-manager.mjs +239 -624
  84. package/src/event-queue.mjs +3 -3
  85. package/src/import-map.mjs +273 -1028
  86. package/src/index.mjs +14 -16
  87. package/src/installed-sdk-runtime.mjs +40 -62
  88. package/src/integrated-provider-loader.mjs +53 -382
  89. package/src/mail-api.mjs +0 -2
  90. package/src/mail-server.mjs +224 -580
  91. package/src/mail.mjs +4 -10
  92. package/src/native-plan.mjs +163 -598
  93. package/src/native-provider-loader.mjs +104 -1063
  94. package/src/packager/core.mjs +485 -3229
  95. package/src/process.mjs +5 -10
  96. package/src/release-bundle.mjs +292 -2405
  97. package/src/runtime.mjs +76 -396
  98. package/src/scaffold.mjs +30 -80
  99. package/src/sdk-browser-runtime.mjs +70 -626
  100. package/src/source-server.mjs +588 -0
  101. package/src/targets/index.mjs +78 -188
  102. package/src/templates/workspace-template.mjs +19 -135
  103. package/src/testing-loader.mjs +164 -0
  104. package/src/testing.mjs +1 -1
  105. package/src/toolchain.mjs +131 -544
  106. package/src/update-check.mjs +26 -64
  107. package/src/workspace-operation-lock.mjs +139 -430
  108. package/src/workspace-runtime.mjs +112 -779
  109. package/src/workspace.mjs +40 -302
  110. package/browser-runtime/ARCANE_SDK_BROWSER_RELEASE.json +0 -218
  111. package/browser-runtime/ai/ARCANE_AI_BROWSER_SPEECH_COMPONENTS.json +0 -203
  112. package/browser-runtime/ai/ARCANE_AI_BROWSER_WASM_COMPONENTS.json +0 -80
  113. package/browser-runtime/ai/internal/sha256.mjs +0 -166
  114. package/docs/architecture.md +0 -344
  115. package/docs/compatibility.md +0 -36
  116. package/docs/event-manager.md +0 -294
  117. package/docs/platform-targets.md +0 -108
  118. package/docs/publishing.md +0 -201
  119. package/docs/reference/README.md +0 -187
  120. package/docs/reference/ai/browser-speech-package-authority.json +0 -835
  121. package/docs/reference/ai/browser-speech.md +0 -1252
  122. package/docs/reference/ai/browser-wasm.md +0 -530
  123. package/docs/reference/arcane-ollama.md +0 -288
  124. package/docs/reference/availability-and-normalization.md +0 -183
  125. package/docs/reference/behavioral-testing.md +0 -133
  126. package/docs/reference/cli.md +0 -779
  127. package/docs/reference/core/README.md +0 -62
  128. package/docs/reference/core/arcane-ai-contracts.md +0 -907
  129. package/docs/reference/core/arcane-api.md +0 -601
  130. package/docs/reference/core/arcane-entities.md +0 -65
  131. package/docs/reference/core/arcane-events.md +0 -134
  132. package/docs/reference/core/ollama-module.md +0 -181
  133. package/docs/reference/core/reference/arcane-api/ai-and-ollama.md +0 -1909
  134. package/docs/reference/core/reference/arcane-api/applications-terminal-capabilities.md +0 -1057
  135. package/docs/reference/core/reference/arcane-api/core-and-events.md +0 -320
  136. package/docs/reference/core/reference/arcane-api/filesystem-storage-preferences-appearance.md +0 -610
  137. package/docs/reference/core/reference/arcane-api/namespaces.md +0 -1157
  138. package/docs/reference/core/reference/arcane-api/platform-installation-users-system.md +0 -1423
  139. package/docs/reference/core/reference/arcane-api/session-provisioning-diagnostics-development.md +0 -315
  140. package/docs/reference/event-manager.md +0 -1511
  141. package/docs/reference/inventory/package-api.json +0 -3284
  142. package/docs/reference/inventory/runtime-components.json +0 -1011
  143. package/docs/reference/inventory/runtime-entities.json +0 -26
  144. package/docs/reference/inventory/runtime-modules.json +0 -1431
  145. package/docs/reference/mail.md +0 -316
  146. package/docs/reference/protocols.md +0 -677
  147. package/docs/reference/runtime-components.md +0 -1366
  148. package/docs/reference/runtime-entities.md +0 -303
  149. package/docs/reference/runtime-modules.md +0 -2960
  150. package/docs/reference/sdk-api.md +0 -6694
  151. package/docs/roadmap.md +0 -79
  152. package/docs/work-amplification.md +0 -129
  153. package/runtime/ARCANE_RUNTIME_RELEASE.json +0 -826
@@ -4,8 +4,8 @@ import {
4
4
  SPEECH_WORKER_PROTOCOL,
5
5
  } from "./speech-worker-runtime.mjs";
6
6
 
7
- const ARTIFACT_GRAPH_MODULE_GRAPH =
8
- "browser-speech-authenticated-artifact-graph";
7
+ const completeValue = (value) => value;
8
+
9
9
  const PUBLIC_WORKER_OPERATIONS = new Set([
10
10
  "load",
11
11
  "use",
@@ -42,24 +42,6 @@ function abortError(signal, role, op) {
42
42
  );
43
43
  }
44
44
 
45
- function validProgress(role, progress) {
46
- if (!progress || typeof progress !== "object" || Array.isArray(progress)) return false;
47
- const keys = Object.keys(progress).sort().join(",");
48
- if (keys !== "completed,heartbeat,phase,total,unit") return false;
49
- const phases = new Set([
50
- `${role}-runtime-import-started`,
51
- `${role}-model-load-started`,
52
- `${role}-model-load-progress`,
53
- `${role}-provider-ready`,
54
- ]);
55
- return phases.has(progress.phase)
56
- && Number.isFinite(progress.completed)
57
- && progress.completed >= 0
58
- && (progress.total === null || (Number.isFinite(progress.total) && progress.total >= 0))
59
- && (progress.unit === "bytes" || progress.unit === "items")
60
- && progress.heartbeat === true;
61
- }
62
-
63
45
  function validateWorker(worker) {
64
46
  if (!worker || typeof worker.postMessage !== "function" || typeof worker.terminate !== "function") {
65
47
  throw new TypeError("The packaged speech worker did not create a Worker.");
@@ -67,23 +49,6 @@ function validateWorker(worker) {
67
49
  return worker;
68
50
  }
69
51
 
70
- function validateMessagePort(port) {
71
- if (
72
- !port
73
- || typeof port.postMessage !== "function"
74
- || typeof port.addEventListener !== "function"
75
- || typeof port.close !== "function"
76
- ) {
77
- throw clientError(
78
- "ARCANE_AI_WORKER_MESSAGE_ERROR",
79
- "The browser did not create a usable private speech Worker MessagePort.",
80
- undefined,
81
- "artifact-graph-private-message-port-unavailable",
82
- );
83
- }
84
- return port;
85
- }
86
-
87
52
  const WORKER_CLIENTS = new WeakSet();
88
53
 
89
54
  /**
@@ -95,8 +60,6 @@ class SpeechWorkerClient {
95
60
  #createWorker;
96
61
  #worker = null;
97
62
  #transport = null;
98
- #transportMode = null;
99
- #privatePorts = null;
100
63
  #pending = new Map();
101
64
  #nextId = 1;
102
65
  #listeners = [];
@@ -140,7 +103,6 @@ class SpeechWorkerClient {
140
103
  const worker = validateWorker(this.#createWorker());
141
104
  this.#worker = worker;
142
105
  this.#listen(worker, "message", (event) => {
143
- if (this.#transportMode === "private-message-port") return;
144
106
  this.#handleMessage(event.data);
145
107
  });
146
108
  this.#listen(worker, "messageerror", (event) => {
@@ -162,44 +124,6 @@ class SpeechWorkerClient {
162
124
  return worker;
163
125
  }
164
126
 
165
- #establishPrivateTransport() {
166
- if (this.#transportMode === "private-message-port") return null;
167
- if (this.#transportMode !== null) {
168
- throw clientError(
169
- "ARCANE_AI_ADAPTER_PROTOCOL_MISMATCH",
170
- "The speech Worker already uses the legacy global message transport.",
171
- undefined,
172
- "artifact-graph-private-message-port-established-too-late",
173
- );
174
- }
175
- const MessageChannelConstructor = globalThis.MessageChannel;
176
- if (typeof MessageChannelConstructor !== "function") {
177
- throw clientError(
178
- "ARCANE_AI_WORKER_MESSAGE_ERROR",
179
- "Authenticated artifact graph loading requires MessageChannel.",
180
- undefined,
181
- "artifact-graph-private-message-channel-unavailable",
182
- );
183
- }
184
- const channel = new MessageChannelConstructor();
185
- const clientPort = validateMessagePort(channel.port1);
186
- const workerPort = validateMessagePort(channel.port2);
187
- this.#privatePorts = Object.freeze({ clientPort, workerPort });
188
- this.#transport = clientPort;
189
- this.#transportMode = "private-message-port";
190
- this.#listen(clientPort, "message", (event) => this.#handleMessage(event.data));
191
- this.#listen(clientPort, "messageerror", (event) => {
192
- void this.terminate(clientError(
193
- "ARCANE_AI_WORKER_MESSAGE_ERROR",
194
- "The private speech Worker MessagePort returned an unreadable message.",
195
- event,
196
- `${this.#role}-worker-private-message-rejected`,
197
- ), { intentional: false }).catch(() => undefined);
198
- });
199
- clientPort.start?.();
200
- return workerPort;
201
- }
202
-
203
127
  #handleMessage(message) {
204
128
  if (message?.protocol !== SPEECH_WORKER_PROTOCOL) {
205
129
  void this.terminate(clientError(
@@ -210,30 +134,6 @@ class SpeechWorkerClient {
210
134
  ), { intentional: false }).catch(() => undefined);
211
135
  return;
212
136
  }
213
- if (message.event === "progress") {
214
- const pending = this.#pending.get(message.requestId);
215
- if (!pending) return;
216
- if (!validProgress(this.#role, message.progress)) {
217
- void this.terminate(clientError(
218
- "ARCANE_AI_WORKER_MESSAGE_ERROR",
219
- "The speech Worker progress envelope was rejected.",
220
- undefined,
221
- `${this.#role}-worker-progress-envelope-rejected`,
222
- ), { intentional: false }).catch(() => undefined);
223
- return;
224
- }
225
- try {
226
- pending.progress(message.progress);
227
- } catch (error) {
228
- void this.terminate(clientError(
229
- "ARCANE_AI_PROGRESS_CALLBACK_THREW",
230
- "The speech load progress callback threw an exception.",
231
- error,
232
- `${this.#role}-load-progress-callback-threw`,
233
- ), { intentional: false }).catch(() => undefined);
234
- }
235
- return;
236
- }
237
137
  if (!Number.isSafeInteger(message.id) || typeof message.ok !== "boolean") {
238
138
  void this.terminate(clientError(
239
139
  "ARCANE_AI_WORKER_MESSAGE_ERROR",
@@ -270,12 +170,12 @@ class SpeechWorkerClient {
270
170
  pending.reject(clientError(
271
171
  admitted.code,
272
172
  admitted.message,
273
- undefined,
173
+ admitted.cause,
274
174
  admitted.reason,
275
175
  ));
276
176
  }
277
177
 
278
- request(op, payload, { signal = null, progress = () => undefined } = {}) {
178
+ request(op, payload, { signal = null } = {}) {
279
179
  if (!PUBLIC_WORKER_OPERATIONS.has(op)) {
280
180
  return Promise.reject(clientError(
281
181
  "ARCANE_AI_INVALID_REQUEST",
@@ -285,31 +185,10 @@ class SpeechWorkerClient {
285
185
  ));
286
186
  }
287
187
  if (signal?.aborted) return Promise.reject(abortError(signal, this.#role, op));
288
- if (typeof progress !== "function") {
289
- return Promise.reject(new TypeError("Speech Worker progress must be a function."));
290
- }
291
188
  let worker;
292
- let initialPrivatePort = null;
293
189
  try {
294
190
  worker = this.#start();
295
- const graphLoad = op === "load"
296
- && payload?.configuration?.runtime?.moduleGraph === ARTIFACT_GRAPH_MODULE_GRAPH;
297
- if (graphLoad) {
298
- initialPrivatePort = this.#establishPrivateTransport();
299
- } else if (this.#transportMode === null) {
300
- this.#transportMode = "worker-global-message";
301
- this.#transport = worker;
302
- }
303
- if (op === "load"
304
- && !graphLoad
305
- && this.#transportMode === "private-message-port") {
306
- throw clientError(
307
- "ARCANE_AI_ADAPTER_PROTOCOL_MISMATCH",
308
- "A private artifact graph Worker cannot load a legacy runtime descriptor.",
309
- undefined,
310
- `${this.#role}-worker-runtime-transport-mode-mismatch`,
311
- );
312
- }
191
+ this.#transport = worker;
313
192
  } catch (error) {
314
193
  return Promise.reject(error);
315
194
  }
@@ -330,7 +209,7 @@ class SpeechWorkerClient {
330
209
  ).catch(() => undefined);
331
210
  };
332
211
  signal?.addEventListener?.("abort", onAbort, { once: true });
333
- this.#pending.set(id, { resolve, reject, progress, cleanup, op });
212
+ this.#pending.set(id, { resolve, reject, cleanup, op });
334
213
  const message = {
335
214
  protocol: SPEECH_WORKER_PROTOCOL,
336
215
  id,
@@ -338,14 +217,8 @@ class SpeechWorkerClient {
338
217
  payload,
339
218
  };
340
219
  const transfers = collectSpeechTransferables(payload);
341
- let destination = this.#transport;
342
- if (initialPrivatePort) {
343
- message.privatePort = initialPrivatePort;
344
- transfers.push(initialPrivatePort);
345
- destination = worker;
346
- }
347
220
  try {
348
- destination.postMessage(message, transfers);
221
+ this.#transport.postMessage(message, transfers);
349
222
  } catch (error) {
350
223
  this.#pending.delete(id);
351
224
  cleanup();
@@ -388,23 +261,12 @@ class SpeechWorkerClient {
388
261
  for (const pending of pendingOperations) pending.cleanup();
389
262
  this.#pending.clear();
390
263
  try {
391
- for (const port of [
392
- this.#privatePorts?.clientPort,
393
- this.#privatePorts?.workerPort,
394
- ]) {
395
- try {
396
- port?.close();
397
- } catch {
398
- // Worker termination remains the authoritative cancellation boundary.
399
- }
400
- }
401
- this.#privatePorts = null;
402
264
  this.#transport = null;
403
265
  const termination = worker?.terminate();
404
266
  if (termination && typeof termination.then === "function") await termination;
405
267
  } finally {
406
268
  for (const pending of pendingOperations) pending.reject(terminationReason);
407
- this.#onTermination(Object.freeze({ reason: terminationReason, intentional }));
269
+ this.#onTermination(completeValue({ reason: terminationReason, intentional }));
408
270
  }
409
271
  }
410
272
  }