arcane-os 0.1.0-dev.5

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 (248) hide show
  1. package/CHANGELOG.md +154 -0
  2. package/COMMERCIAL-LICENSE.md +13 -0
  3. package/LICENSE +661 -0
  4. package/NOTICE +70 -0
  5. package/README.md +448 -0
  6. package/bin/arcane-test.mjs +741 -0
  7. package/bin/arcane.mjs +5 -0
  8. package/docs/architecture.md +234 -0
  9. package/docs/compatibility.md +36 -0
  10. package/docs/event-manager.md +166 -0
  11. package/docs/platform-targets.md +108 -0
  12. package/docs/publishing.md +203 -0
  13. package/docs/reference/README.md +117 -0
  14. package/docs/reference/arcane-ollama.md +288 -0
  15. package/docs/reference/availability-and-normalization.md +123 -0
  16. package/docs/reference/behavioral-testing.md +86 -0
  17. package/docs/reference/cli.md +569 -0
  18. package/docs/reference/core/README.md +62 -0
  19. package/docs/reference/core/arcane-ai-contracts.md +873 -0
  20. package/docs/reference/core/arcane-api.md +601 -0
  21. package/docs/reference/core/arcane-entities.md +65 -0
  22. package/docs/reference/core/arcane-events.md +134 -0
  23. package/docs/reference/core/ollama-module.md +181 -0
  24. package/docs/reference/core/reference/arcane-api/ai-and-ollama.md +1909 -0
  25. package/docs/reference/core/reference/arcane-api/applications-terminal-capabilities.md +1057 -0
  26. package/docs/reference/core/reference/arcane-api/core-and-events.md +320 -0
  27. package/docs/reference/core/reference/arcane-api/filesystem-storage-preferences-appearance.md +610 -0
  28. package/docs/reference/core/reference/arcane-api/namespaces.md +1157 -0
  29. package/docs/reference/core/reference/arcane-api/platform-installation-users-system.md +1423 -0
  30. package/docs/reference/core/reference/arcane-api/session-provisioning-diagnostics-development.md +315 -0
  31. package/docs/reference/event-manager.md +957 -0
  32. package/docs/reference/inventory/package-api.json +2632 -0
  33. package/docs/reference/inventory/runtime-components.json +934 -0
  34. package/docs/reference/inventory/runtime-entities.json +26 -0
  35. package/docs/reference/inventory/runtime-modules.json +1249 -0
  36. package/docs/reference/protocols.md +242 -0
  37. package/docs/reference/runtime-components.md +1098 -0
  38. package/docs/reference/runtime-entities.md +303 -0
  39. package/docs/reference/runtime-modules.md +2010 -0
  40. package/docs/reference/sdk-api.md +4901 -0
  41. package/docs/roadmap.md +79 -0
  42. package/docs/work-amplification.md +124 -0
  43. package/node_modules/event-pubsub/CHANGELOG.md +55 -0
  44. package/node_modules/event-pubsub/MIGRATION.md +70 -0
  45. package/node_modules/event-pubsub/README.md +363 -0
  46. package/node_modules/event-pubsub/SECURITY.md +37 -0
  47. package/node_modules/event-pubsub/index.js +141 -0
  48. package/node_modules/event-pubsub/licence +21 -0
  49. package/node_modules/event-pubsub/package.json +59 -0
  50. package/node_modules/strong-type/README.md +408 -0
  51. package/node_modules/strong-type/assets/strong-type-header.png +0 -0
  52. package/node_modules/strong-type/index.js +1151 -0
  53. package/node_modules/strong-type/licence +21 -0
  54. package/node_modules/strong-type/node.js +125 -0
  55. package/node_modules/strong-type/package.json +61 -0
  56. package/package.json +95 -0
  57. package/runtime/ARCANE_RUNTIME_RELEASE.json +791 -0
  58. package/runtime/arcane/components/app-bar.html +468 -0
  59. package/runtime/arcane/components/assistant-panel.html +715 -0
  60. package/runtime/arcane/components/calculator.html +8 -0
  61. package/runtime/arcane/components/chart.html +655 -0
  62. package/runtime/arcane/components/chat.html +1225 -0
  63. package/runtime/arcane/components/conversation-view.html +13 -0
  64. package/runtime/arcane/components/dashboard-config.html +341 -0
  65. package/runtime/arcane/components/data-maintenance.html +112 -0
  66. package/runtime/arcane/components/data-view.html +92 -0
  67. package/runtime/arcane/components/directory-picker.html +197 -0
  68. package/runtime/arcane/components/document-inspector.html +252 -0
  69. package/runtime/arcane/components/file-drop.html +264 -0
  70. package/runtime/arcane/components/file-inspector.html +293 -0
  71. package/runtime/arcane/components/file-manager.html +1715 -0
  72. package/runtime/arcane/components/header.html +142 -0
  73. package/runtime/arcane/components/integration-settings.html +14 -0
  74. package/runtime/arcane/components/local-ai-status.html +360 -0
  75. package/runtime/arcane/components/markdown-document.html +1048 -0
  76. package/runtime/arcane/components/markdown-editor.html +360 -0
  77. package/runtime/arcane/components/media-embed.html +8 -0
  78. package/runtime/arcane/components/modal.html +402 -0
  79. package/runtime/arcane/components/output-panel.html +259 -0
  80. package/runtime/arcane/components/preferences-form.html +135 -0
  81. package/runtime/arcane/components/record-timeline.html +105 -0
  82. package/runtime/arcane/components/relationship-board.html +116 -0
  83. package/runtime/arcane/components/screen-capture.html +8 -0
  84. package/runtime/arcane/components/source-code-viewer.html +441 -0
  85. package/runtime/arcane/components/source-explanation.html +124 -0
  86. package/runtime/arcane/components/speech.html +365 -0
  87. package/runtime/arcane/components/summary-strip.html +177 -0
  88. package/runtime/arcane/components/table.html +77 -0
  89. package/runtime/arcane/components/task-progress.html +282 -0
  90. package/runtime/arcane/components/terminal-workspace.html +65 -0
  91. package/runtime/arcane/components/theme-editor.html +41 -0
  92. package/runtime/arcane/components/theme-switcher.html +46 -0
  93. package/runtime/arcane/components/unified-inbox.html +20 -0
  94. package/runtime/arcane/components/voice-transcription.html +476 -0
  95. package/runtime/arcane/components/weather-widget.html +8 -0
  96. package/runtime/arcane/components/web-navigator.html +239 -0
  97. package/runtime/arcane/css/communications.css +1 -0
  98. package/runtime/arcane/css/dashboard-config.css +45 -0
  99. package/runtime/arcane/css/document-site.css +981 -0
  100. package/runtime/arcane/css/layout.css +438 -0
  101. package/runtime/arcane/css/primitives.css +321 -0
  102. package/runtime/arcane/css/theme.css +112 -0
  103. package/runtime/arcane/css/utility-workspace.css +1 -0
  104. package/runtime/arcane/entities/ApiModelRecord.js +20 -0
  105. package/runtime/arcane/entities/Calculation.js +13 -0
  106. package/runtime/arcane/entities/Chat.js +581 -0
  107. package/runtime/arcane/entities/CommunicationMessage.js +29 -0
  108. package/runtime/arcane/entities/CommunicationThread.js +21 -0
  109. package/runtime/arcane/entities/Document.js +10 -0
  110. package/runtime/arcane/entities/File.js +143 -0
  111. package/runtime/arcane/entities/Image.js +135 -0
  112. package/runtime/arcane/entities/IntentEnvelope.js +834 -0
  113. package/runtime/arcane/entities/Preference.js +83 -0
  114. package/runtime/arcane/entities/TWiNPolicyDecision.js +1092 -0
  115. package/runtime/arcane/entities/TerminalSession.js +46 -0
  116. package/runtime/arcane/entities/Theme.js +107 -0
  117. package/runtime/arcane/entities/User.js +1046 -0
  118. package/runtime/arcane/entities/Weather.js +23 -0
  119. package/runtime/arcane/img/arcane-os-everywhere.png +0 -0
  120. package/runtime/arcane/img/arrow-left.png +0 -0
  121. package/runtime/arcane/img/arrow-right.png +0 -0
  122. package/runtime/arcane/img/doc.svg +5 -0
  123. package/runtime/arcane/img/folder.svg +4 -0
  124. package/runtime/arcane/img/image.svg +5 -0
  125. package/runtime/arcane/img/refresh.png +0 -0
  126. package/runtime/arcane/img/send.svg +9 -0
  127. package/runtime/arcane/img/trash.svg +5 -0
  128. package/runtime/arcane/img/upload.svg +5 -0
  129. package/runtime/arcane/modules/AI.js +2048 -0
  130. package/runtime/arcane/modules/AIPreferenceRuntime.js +32 -0
  131. package/runtime/arcane/modules/AIPreferenceTuple.js +92 -0
  132. package/runtime/arcane/modules/AIResponseLength.js +42 -0
  133. package/runtime/arcane/modules/AIResponseURLPolicy.js +626 -0
  134. package/runtime/arcane/modules/AnsiText.js +53 -0
  135. package/runtime/arcane/modules/ApiModelDatabase.js +25 -0
  136. package/runtime/arcane/modules/AppDataScope.js +245 -0
  137. package/runtime/arcane/modules/AppearancePreferences.js +28 -0
  138. package/runtime/arcane/modules/ArcaneCommunicationBridge.js +22 -0
  139. package/runtime/arcane/modules/ArcaneNavigationPolicy.js +135 -0
  140. package/runtime/arcane/modules/ArcaneNetworkPolicy.js +255 -0
  141. package/runtime/arcane/modules/AsyncBoundary.js +161 -0
  142. package/runtime/arcane/modules/BrowserTestSuite.js +326 -0
  143. package/runtime/arcane/modules/CalculatorEngine.js +20 -0
  144. package/runtime/arcane/modules/CaseEvidenceIndexer.js +134 -0
  145. package/runtime/arcane/modules/ChartLibrary.js +35 -0
  146. package/runtime/arcane/modules/ChatRecords.js +13 -0
  147. package/runtime/arcane/modules/CommunicationAppController.js +43 -0
  148. package/runtime/arcane/modules/CommunicationHub.js +16 -0
  149. package/runtime/arcane/modules/CommunicationPreferences.js +13 -0
  150. package/runtime/arcane/modules/CommunicationProviderRegistry.js +16 -0
  151. package/runtime/arcane/modules/ComponentContracts.js +586 -0
  152. package/runtime/arcane/modules/ConfiguredAIChatSession.js +288 -0
  153. package/runtime/arcane/modules/ConversationActionItems.js +488 -0
  154. package/runtime/arcane/modules/ConversationClosingReport.js +274 -0
  155. package/runtime/arcane/modules/ConversationTimebox.js +527 -0
  156. package/runtime/arcane/modules/CoreLocalModelCatalog.js +255 -0
  157. package/runtime/arcane/modules/DBLS.js +171 -0
  158. package/runtime/arcane/modules/DBOPFS.js +1154 -0
  159. package/runtime/arcane/modules/DBOPFSWorker.js +116 -0
  160. package/runtime/arcane/modules/DataMaintenance.js +91 -0
  161. package/runtime/arcane/modules/DevelopmentWorkspace.js +74 -0
  162. package/runtime/arcane/modules/DirectoryPicker.js +109 -0
  163. package/runtime/arcane/modules/DocumentNavigation.js +223 -0
  164. package/runtime/arcane/modules/Errors.js +1025 -0
  165. package/runtime/arcane/modules/GifEncoder.js +29 -0
  166. package/runtime/arcane/modules/HTMLImport.js +114 -0
  167. package/runtime/arcane/modules/InMemoryCommunicationProvider.js +14 -0
  168. package/runtime/arcane/modules/IsolatedModelQuestionRunner.js +275 -0
  169. package/runtime/arcane/modules/LocalAIReadiness.js +870 -0
  170. package/runtime/arcane/modules/LocalAIReadinessController.js +156 -0
  171. package/runtime/arcane/modules/MD.js +111 -0
  172. package/runtime/arcane/modules/Mail.js +352 -0
  173. package/runtime/arcane/modules/MailTransport.mjs +180 -0
  174. package/runtime/arcane/modules/Marked.min.js +71 -0
  175. package/runtime/arcane/modules/MemoryRecords.js +44 -0
  176. package/runtime/arcane/modules/MessageAdvisory.js +38 -0
  177. package/runtime/arcane/modules/ModelDefinition.js +189 -0
  178. package/runtime/arcane/modules/Ollama.js +74 -0
  179. package/runtime/arcane/modules/OllamaModelIdentifier.js +21 -0
  180. package/runtime/arcane/modules/OllamaSettings.js +24 -0
  181. package/runtime/arcane/modules/OpenMeteoWeatherProvider.js +14 -0
  182. package/runtime/arcane/modules/PreferenceStore.js +109 -0
  183. package/runtime/arcane/modules/QRCode.min.js +1 -0
  184. package/runtime/arcane/modules/Questionnaire.js +61 -0
  185. package/runtime/arcane/modules/RecordLinkIndex.js +24 -0
  186. package/runtime/arcane/modules/RecordPassageIndex.js +222 -0
  187. package/runtime/arcane/modules/RecordReviewStore.js +94 -0
  188. package/runtime/arcane/modules/RevocableProjectionLedger.js +1623 -0
  189. package/runtime/arcane/modules/RiskSignalAnalyzer.js +37 -0
  190. package/runtime/arcane/modules/ScamRiskPolicy.js +62 -0
  191. package/runtime/arcane/modules/ScopedOPFSCache.js +183 -0
  192. package/runtime/arcane/modules/ScreenCapture.js +20 -0
  193. package/runtime/arcane/modules/SpeechPlayback.js +581 -0
  194. package/runtime/arcane/modules/StaticDocumentCatalog.js +1248 -0
  195. package/runtime/arcane/modules/SystemAppearance.js +20 -0
  196. package/runtime/arcane/modules/SystemPlatformPresentation.js +51 -0
  197. package/runtime/arcane/modules/SystemToolRegistry.js +28 -0
  198. package/runtime/arcane/modules/TerminalClient.js +52 -0
  199. package/runtime/arcane/modules/TerminalCommandRegistry.js +50 -0
  200. package/runtime/arcane/modules/ThemeBootstrap.js +26 -0
  201. package/runtime/arcane/modules/ThemeManager.js +131 -0
  202. package/runtime/arcane/modules/TimeGuard.js +149 -0
  203. package/runtime/arcane/modules/ToolCallRouter.js +83 -0
  204. package/runtime/arcane/modules/WaitForComponent.js +102 -0
  205. package/runtime/arcane/modules/YouTubeMedia.js +16 -0
  206. package/runtime/arcane/modules/uPlot.LICENSE.txt +21 -0
  207. package/runtime/arcane/modules/uPlot.iife.min.js +2 -0
  208. package/runtime/arcane/modules/uPlot.min.css +1 -0
  209. package/runtime/arcane/security/arcane-network-policy.json +6 -0
  210. package/runtime/strong-type/index.js +352 -0
  211. package/runtime/strong-type/licence +21 -0
  212. package/runtime/strong-type/package.json +45 -0
  213. package/schemas/arcane-app-bundle.schema.json +125 -0
  214. package/schemas/arcane-app.schema.json +329 -0
  215. package/schemas/arcane-lock.schema.json +86 -0
  216. package/schemas/arcane-package.schema.json +224 -0
  217. package/schemas/cli-event.schema.json +122 -0
  218. package/schemas/event-stack.schema.json +152 -0
  219. package/schemas/native-build-plan.schema.json +176 -0
  220. package/schemas/target-adapter.schema.json +117 -0
  221. package/src/app-descriptor.mjs +500 -0
  222. package/src/cli/main.mjs +561 -0
  223. package/src/constants.mjs +31 -0
  224. package/src/dev-server.mjs +718 -0
  225. package/src/doctor.mjs +315 -0
  226. package/src/dom-event-instrumentation.mjs +594 -0
  227. package/src/errors.mjs +75 -0
  228. package/src/event-manager.mjs +1342 -0
  229. package/src/event-queue.mjs +138 -0
  230. package/src/events.mjs +219 -0
  231. package/src/index.mjs +177 -0
  232. package/src/integrated-provider-loader.mjs +432 -0
  233. package/src/native-plan.mjs +698 -0
  234. package/src/native-provider-loader.mjs +1126 -0
  235. package/src/packager/core.mjs +2691 -0
  236. package/src/process.mjs +353 -0
  237. package/src/release-bundle.mjs +2523 -0
  238. package/src/repository.mjs +90 -0
  239. package/src/runtime.mjs +452 -0
  240. package/src/scaffold.mjs +380 -0
  241. package/src/targets/index.mjs +436 -0
  242. package/src/templates/assets/app-icon.png +0 -0
  243. package/src/templates/workspace-template.mjs +388 -0
  244. package/src/testing-loader.mjs +9 -0
  245. package/src/testing.mjs +427 -0
  246. package/src/toolchain.mjs +1335 -0
  247. package/src/update-check.mjs +307 -0
  248. package/src/workspace.mjs +449 -0
@@ -0,0 +1,307 @@
1
+ import {ArcaneError,ERROR_CODES,throwIfAborted} from './errors.mjs';
2
+ import {parseSemver} from './packager/core.mjs';
3
+ import {SDK_NAME,SDK_VERSION} from './constants.mjs';
4
+
5
+ export const SDK_UPDATE_REGISTRY='https://registry.npmjs.org/';
6
+ export const SDK_UPDATE_TIMEOUT_MS=2500;
7
+
8
+ const MAX_RESPONSE_BYTES=32*1024;
9
+ const MAX_DIST_TAGS=64;
10
+ const DIST_TAG_PATTERN=/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/u;
11
+ const FORBIDDEN_DIST_TAG_KEYS=new Set(['__proto__','constructor','prototype']);
12
+
13
+ function updateFailure(message,{cause,details}={}){
14
+ return new ArcaneError(ERROR_CODES.updateCheckFailed,message,{cause,details});
15
+ }
16
+
17
+ function plainObject(value){
18
+ return value!==null&&typeof value==='object'&&!Array.isArray(value);
19
+ }
20
+
21
+ function canonicalPackageName(value){
22
+ if(value!==SDK_NAME){
23
+ throw updateFailure('The SDK update check is restricted to the installed Arcane SDK package.');
24
+ }
25
+ return value;
26
+ }
27
+
28
+ export function validateUpdateRegistry(value,{
29
+ allowedHosts=new Set(['registry.npmjs.org'])
30
+ }={}){
31
+ let registry;
32
+ try{
33
+ registry=new URL(value);
34
+ }catch(error){
35
+ throw updateFailure('The SDK update registry URL is invalid.',{cause:error});
36
+ }
37
+ if(registry.protocol!=='https:'
38
+ ||registry.username||registry.password
39
+ ||registry.search||registry.hash
40
+ ||registry.pathname!=='/'
41
+ ||(registry.port&&registry.port!=='443')
42
+ ||!allowedHosts.has(registry.hostname.toLowerCase())){
43
+ throw updateFailure(
44
+ 'The SDK update registry must be an approved credential-free HTTPS origin.',
45
+ {details:{registryOrigin:registry.origin}}
46
+ );
47
+ }
48
+ return registry;
49
+ }
50
+
51
+ function registryEndpoint(registry,packageName){
52
+ return new URL('-/package/'+encodeURIComponent(packageName)+'/dist-tags',registry);
53
+ }
54
+
55
+ function validateTimeout(value){
56
+ if(!Number.isSafeInteger(value)||value<100||value>10_000){
57
+ throw updateFailure('The SDK update timeout must be between 100 and 10000 milliseconds.');
58
+ }
59
+ return value;
60
+ }
61
+
62
+ function linkedAbortSignal(signal,timeoutMs,{schedule=setTimeout,cancel=clearTimeout}={}){
63
+ const controller=new AbortController();
64
+ let timedOut=false;
65
+ const abort=()=>controller.abort(signal?.reason);
66
+ if(signal?.aborted){
67
+ abort();
68
+ }else{
69
+ signal?.addEventListener('abort',abort,{once:true});
70
+ }
71
+ const timer=schedule(()=>{
72
+ timedOut=true;
73
+ controller.abort(new Error('SDK update registry request timed out.'));
74
+ },timeoutMs);
75
+ timer?.unref?.();
76
+ return {
77
+ signal:controller.signal,
78
+ timedOut:()=>timedOut,
79
+ cleanup(){
80
+ cancel(timer);
81
+ signal?.removeEventListener('abort',abort);
82
+ }
83
+ };
84
+ }
85
+
86
+ async function boundedResponseBytes(response){
87
+ const contentType=response.headers?.get?.('content-type')??'';
88
+ if(!/^(?:application\/json|application\/[A-Za-z0-9.+-]+\+json)(?:\s*;|$)/iu.test(contentType)){
89
+ throw updateFailure('The npm registry returned a non-JSON update response.');
90
+ }
91
+ const declared=response.headers?.get?.('content-length');
92
+ if(declared!==null&&declared!==undefined&&declared!==''){
93
+ if(!/^\d+$/u.test(declared)||Number(declared)>MAX_RESPONSE_BYTES){
94
+ throw updateFailure('The npm registry update response exceeded the byte limit.');
95
+ }
96
+ }
97
+ if(!response.body||typeof response.body.getReader!=='function'){
98
+ throw updateFailure('The npm registry returned no readable update response.');
99
+ }
100
+ const reader=response.body.getReader();
101
+ const chunks=[];
102
+ let total=0;
103
+ try{
104
+ while(true){
105
+ const {done,value}=await reader.read();
106
+ if(done)break;
107
+ if(!(value instanceof Uint8Array)){
108
+ await reader.cancel();
109
+ throw updateFailure('The npm registry update response was not a byte stream.');
110
+ }
111
+ total+=value.byteLength;
112
+ if(total>MAX_RESPONSE_BYTES){
113
+ await reader.cancel();
114
+ throw updateFailure('The npm registry update response exceeded the byte limit.');
115
+ }
116
+ chunks.push(value);
117
+ }
118
+ }finally{
119
+ reader.releaseLock?.();
120
+ }
121
+ const bytes=new Uint8Array(total);
122
+ let offset=0;
123
+ for(const chunk of chunks){
124
+ bytes.set(chunk,offset);
125
+ offset+=chunk.byteLength;
126
+ }
127
+ try{
128
+ return new TextDecoder('utf-8',{fatal:true}).decode(bytes);
129
+ }catch(error){
130
+ throw updateFailure('The npm registry update response was not valid UTF-8.',{cause:error});
131
+ }
132
+ }
133
+
134
+ function canonicalDistTags(value){
135
+ if(!plainObject(value)){
136
+ throw updateFailure('The npm registry update response was not a dist-tag object.');
137
+ }
138
+ const entries=Object.entries(value);
139
+ if(entries.length<1||entries.length>MAX_DIST_TAGS){
140
+ throw updateFailure('The npm registry update response contained an invalid dist-tag count.');
141
+ }
142
+ const tags=Object.create(null);
143
+ for(const [tag,version] of entries){
144
+ if(!DIST_TAG_PATTERN.test(tag)||FORBIDDEN_DIST_TAG_KEYS.has(tag)
145
+ ||typeof version!=='string'||version.length>128){
146
+ throw updateFailure('The npm registry update response contained an invalid dist-tag.');
147
+ }
148
+ try{
149
+ parseSemver(version);
150
+ }catch(error){
151
+ throw updateFailure('The npm registry dist-tag '+tag+' is not a semantic version.',{cause:error});
152
+ }
153
+ tags[tag]=version;
154
+ }
155
+ return Object.freeze(tags);
156
+ }
157
+
158
+ function comparePrerelease(left,right){
159
+ const length=Math.max(left.length,right.length);
160
+ for(let index=0;index<length;index+=1){
161
+ const leftPart=left[index];
162
+ const rightPart=right[index];
163
+ if(leftPart===undefined)return -1;
164
+ if(rightPart===undefined)return 1;
165
+ if(leftPart===rightPart)continue;
166
+ const leftNumeric=/^\d+$/u.test(leftPart);
167
+ const rightNumeric=/^\d+$/u.test(rightPart);
168
+ if(leftNumeric&&rightNumeric){
169
+ if(leftPart.length!==rightPart.length)return leftPart.length<rightPart.length?-1:1;
170
+ return leftPart<rightPart?-1:1;
171
+ }
172
+ if(leftNumeric!==rightNumeric)return leftNumeric?-1:1;
173
+ return leftPart<rightPart?-1:1;
174
+ }
175
+ return 0;
176
+ }
177
+
178
+ export function compareSdkVersions(leftValue,rightValue){
179
+ const left=parseSemver(leftValue);
180
+ const right=parseSemver(rightValue);
181
+ for(const key of ['major','minor','patch']){
182
+ if(left[key]!==right[key])return left[key]<right[key]?-1:1;
183
+ }
184
+ if(!left.prerelease.length&&!right.prerelease.length)return 0;
185
+ if(!left.prerelease.length)return 1;
186
+ if(!right.prerelease.length)return -1;
187
+ return comparePrerelease(left.prerelease,right.prerelease);
188
+ }
189
+
190
+ export function updateTagForVersion(value){
191
+ try{
192
+ return parseSemver(value).prerelease.length?'dev':'latest';
193
+ }catch(error){
194
+ throw updateFailure('The installed SDK version is invalid.',{cause:error});
195
+ }
196
+ }
197
+
198
+ export async function checkForSdkUpdate({
199
+ packageName=SDK_NAME,
200
+ currentVersion=SDK_VERSION,
201
+ registry=SDK_UPDATE_REGISTRY,
202
+ allowedRegistryHosts,
203
+ timeoutMs=SDK_UPDATE_TIMEOUT_MS,
204
+ fetchImpl=globalThis.fetch,
205
+ signal,
206
+ onEvent,
207
+ clock=()=>new Date()
208
+ }={}){
209
+ throwIfAborted(signal);
210
+ const selectedPackage=canonicalPackageName(packageName);
211
+ const selectedRegistry=validateUpdateRegistry(registry,{
212
+ ...(allowedRegistryHosts===undefined?{}:{allowedHosts:allowedRegistryHosts})
213
+ });
214
+ const selectedTimeout=validateTimeout(timeoutMs);
215
+ if(typeof fetchImpl!=='function'){
216
+ throw updateFailure('The SDK update HTTP client is unavailable.');
217
+ }
218
+ const tag=updateTagForVersion(currentVersion);
219
+ const endpoint=registryEndpoint(selectedRegistry,selectedPackage);
220
+ await onEvent?.({
221
+ type:'update.check.started',
222
+ message:'Checking npm '+tag+' for '+selectedPackage+'.',
223
+ data:{packageName:selectedPackage,currentVersion,tag,registry:selectedRegistry.origin}
224
+ });
225
+ const linked=linkedAbortSignal(signal,selectedTimeout);
226
+ try{
227
+ const response=await fetchImpl(endpoint,{
228
+ method:'GET',
229
+ headers:Object.freeze({accept:'application/json'}),
230
+ redirect:'error',
231
+ cache:'no-store',
232
+ credentials:'omit',
233
+ referrerPolicy:'no-referrer',
234
+ signal:linked.signal
235
+ });
236
+ throwIfAborted(signal);
237
+ if(!response||typeof response.status!=='number'
238
+ ||response.redirected===true
239
+ ||(response.url&&response.url!==endpoint.href)){
240
+ throw updateFailure('The npm registry update response changed origin or request identity.');
241
+ }
242
+ if(response.status!==200){
243
+ throw updateFailure(
244
+ 'The npm registry update request failed with HTTP '+response.status+'.',
245
+ {details:{status:response.status}}
246
+ );
247
+ }
248
+ const body=await boundedResponseBytes(response);
249
+ let document;
250
+ try{
251
+ document=JSON.parse(body);
252
+ }catch(error){
253
+ throw updateFailure('The npm registry update response was not valid JSON.',{cause:error});
254
+ }
255
+ const tags=canonicalDistTags(document);
256
+ const registryVersion=tags[tag];
257
+ if(!registryVersion){
258
+ throw updateFailure('The npm registry does not define the required '+tag+' dist-tag.');
259
+ }
260
+ let comparison;
261
+ try{
262
+ comparison=compareSdkVersions(currentVersion,registryVersion);
263
+ }catch(error){
264
+ if(error instanceof ArcaneError&&error.code===ERROR_CODES.updateCheckFailed)throw error;
265
+ throw updateFailure('The installed or registry SDK version is invalid.',{cause:error});
266
+ }
267
+ const status=comparison<0?'update-available':comparison===0?'current':'ahead';
268
+ const result=Object.freeze({
269
+ packageName:selectedPackage,
270
+ currentVersion,
271
+ registryVersion,
272
+ tag,
273
+ status,
274
+ updateAvailable:status==='update-available',
275
+ registry:selectedRegistry.origin,
276
+ checkedAt:clock().toISOString()
277
+ });
278
+ await onEvent?.({
279
+ type:'update.check.completed',
280
+ message:status==='update-available'
281
+ ?selectedPackage+' '+registryVersion+' is available under npm '+tag+'.'
282
+ :selectedPackage+' '+currentVersion+' is '+status+' for npm '+tag+'.',
283
+ data:result
284
+ });
285
+ return result;
286
+ }catch(error){
287
+ if(signal?.aborted){
288
+ throwIfAborted(signal);
289
+ }
290
+ const normalized=error instanceof ArcaneError&&error.code===ERROR_CODES.updateCheckFailed
291
+ ?error
292
+ :updateFailure(
293
+ linked.timedOut()
294
+ ?'The npm registry update request exceeded '+selectedTimeout+' milliseconds.'
295
+ :'The npm registry update request failed.',
296
+ {cause:error}
297
+ );
298
+ await onEvent?.({
299
+ type:'update.check.failed',
300
+ message:normalized.message,
301
+ data:{code:normalized.code,tag,packageName:selectedPackage}
302
+ });
303
+ throw normalized;
304
+ }finally{
305
+ linked.cleanup();
306
+ }
307
+ }