arcane-os 0.3.1 → 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 +14 -0
  2. package/README.md +86 -117
  3. package/bin/arcane-test.mjs +170 -46
  4. package/browser-runtime/ai/browser-speech-artifacts.mjs +855 -895
  5. package/browser-runtime/ai/browser-speech-providers.mjs +80 -204
  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 -148
  11. package/browser-runtime/ai/speech-worker-runtime.mjs +642 -374
  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 +1042 -427
  37. package/runtime/arcane/modules/AIProviderRuntime.js +618 -359
  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 +27 -67
  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 +109 -1558
  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 -185
  120. package/docs/reference/ai/browser-speech-package-authority.json +0 -835
  121. package/docs/reference/ai/browser-speech.md +0 -1295
  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 -719
  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 -2965
  150. package/docs/reference/sdk-api.md +0 -6698
  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
- "Strict 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,33 +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
- const strictGraphLoad = graphLoad
298
- && payload?.configuration?.security?.secure === true;
299
- if (strictGraphLoad) {
300
- initialPrivatePort = this.#establishPrivateTransport();
301
- } else if (this.#transportMode === null) {
302
- this.#transportMode = "worker-global-message";
303
- this.#transport = worker;
304
- }
305
- if (op === "load"
306
- && !strictGraphLoad
307
- && this.#transportMode === "private-message-port") {
308
- throw clientError(
309
- "ARCANE_AI_ADAPTER_PROTOCOL_MISMATCH",
310
- "A private strict artifact graph Worker cannot load an ordinary runtime descriptor.",
311
- undefined,
312
- `${this.#role}-worker-runtime-transport-mode-mismatch`,
313
- );
314
- }
191
+ this.#transport = worker;
315
192
  } catch (error) {
316
193
  return Promise.reject(error);
317
194
  }
@@ -332,7 +209,7 @@ class SpeechWorkerClient {
332
209
  ).catch(() => undefined);
333
210
  };
334
211
  signal?.addEventListener?.("abort", onAbort, { once: true });
335
- this.#pending.set(id, { resolve, reject, progress, cleanup, op });
212
+ this.#pending.set(id, { resolve, reject, cleanup, op });
336
213
  const message = {
337
214
  protocol: SPEECH_WORKER_PROTOCOL,
338
215
  id,
@@ -340,14 +217,8 @@ class SpeechWorkerClient {
340
217
  payload,
341
218
  };
342
219
  const transfers = collectSpeechTransferables(payload);
343
- let destination = this.#transport;
344
- if (initialPrivatePort) {
345
- message.privatePort = initialPrivatePort;
346
- transfers.push(initialPrivatePort);
347
- destination = worker;
348
- }
349
220
  try {
350
- destination.postMessage(message, transfers);
221
+ this.#transport.postMessage(message, transfers);
351
222
  } catch (error) {
352
223
  this.#pending.delete(id);
353
224
  cleanup();
@@ -390,23 +261,12 @@ class SpeechWorkerClient {
390
261
  for (const pending of pendingOperations) pending.cleanup();
391
262
  this.#pending.clear();
392
263
  try {
393
- for (const port of [
394
- this.#privatePorts?.clientPort,
395
- this.#privatePorts?.workerPort,
396
- ]) {
397
- try {
398
- port?.close();
399
- } catch {
400
- // Worker termination remains the authoritative cancellation boundary.
401
- }
402
- }
403
- this.#privatePorts = null;
404
264
  this.#transport = null;
405
265
  const termination = worker?.terminate();
406
266
  if (termination && typeof termination.then === "function") await termination;
407
267
  } finally {
408
268
  for (const pending of pendingOperations) pending.reject(terminationReason);
409
- this.#onTermination(Object.freeze({ reason: terminationReason, intentional }));
269
+ this.#onTermination(completeValue({ reason: terminationReason, intentional }));
410
270
  }
411
271
  }
412
272
  }