arcane-os 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "builder": "arcane-sdk-runtime-v1",
4
- "sdkVersion": "0.3.0",
4
+ "sdkVersion": "0.3.1",
5
5
  "source": {
6
6
  "authority": "sdk-canonical",
7
7
  "repository": "https://github.com/TheWizardNexus/arcane-os-sdk.git",
@@ -14,8 +14,8 @@
14
14
  }
15
15
  },
16
16
  "fileCount": 161,
17
- "totalBytes": 4160019,
18
- "contentSha256": "a8e40b65723ed608d68674885bea2b39d68569688a445481c858768d2a0ab7cb",
17
+ "totalBytes": 4161715,
18
+ "contentSha256": "9ed39694d9f286e0994404a82fb6002c3ba48be0d085a6b68d51c7facc17c56f",
19
19
  "files": [
20
20
  {
21
21
  "path": "arcane/components/app-bar.html",
@@ -374,8 +374,8 @@
374
374
  },
375
375
  {
376
376
  "path": "arcane/modules/AI.js",
377
- "bytes": 201054,
378
- "sha256": "ceaa8089f2f5a2f59c776eea3e54a005dcf7eff1c701d2a8f45a02b0c4672875"
377
+ "bytes": 201388,
378
+ "sha256": "2224391b2b22e93cb8be321382fcecd25cb5a2e8d09211dd6ce88b901df9c9ab"
379
379
  },
380
380
  {
381
381
  "path": "arcane/modules/AIPreferenceRuntime.js",
@@ -389,8 +389,8 @@
389
389
  },
390
390
  {
391
391
  "path": "arcane/modules/AIProviderRuntime.js",
392
- "bytes": 122595,
393
- "sha256": "054a19ef6b5aa9569fa595ff3fde3edf0c7341c1c5059856a208b8781e4f2625"
392
+ "bytes": 123957,
393
+ "sha256": "65234004cc7ed64060475d5f6076712f926ae3786f8b57cc5321d6e0d5cd97c8"
394
394
  },
395
395
  {
396
396
  "path": "arcane/modules/AIResponseLength.js",
@@ -2089,6 +2089,14 @@ class AI {
2089
2089
  );
2090
2090
  if(!record
2091
2091
  ||!this.#providerRuntime.ownsProvider(role,record.provider)){
2092
+ const pendingIdentity=this.#providerRuntime.providerIdentity(
2093
+ role,
2094
+ selection.providerId
2095
+ );
2096
+ if(pendingIdentity===null&&selection.localOnly===null){
2097
+ expectedProviders[role]=null;
2098
+ continue;
2099
+ }
2092
2100
  throw this.#browserSpeechProviderRouteOwnershipError(
2093
2101
  `The selected ${role} route is not owned by the replaceable AI legacy speech boundary.`
2094
2102
  );
@@ -1124,6 +1124,30 @@ export class AIProviderRuntime {
1124
1124
  }
1125
1125
  }
1126
1126
 
1127
+ #pendingSpeechProviderHydrationMatches(role, slot, provider, routes) {
1128
+ if (!provider || !slot.selection || !routes.default) {
1129
+ return false;
1130
+ }
1131
+ const pending = slot.selection;
1132
+ if (this.#providers.has(providerKey(role, pending.providerId))
1133
+ || provider.id !== pending.providerId
1134
+ || routes.default.providerId !== pending.providerId
1135
+ || routes.default.modelId !== pending.modelId) {
1136
+ return false;
1137
+ }
1138
+ const currentSelections = [
1139
+ slot.selection,
1140
+ slot.routes.default,
1141
+ slot.routes.localOnly
1142
+ ].filter(Boolean);
1143
+ return currentSelections.length > 0
1144
+ && currentSelections.every(selection =>
1145
+ selection.providerId === pending.providerId
1146
+ && selection.modelId === pending.modelId
1147
+ && selection.localOnly === null
1148
+ );
1149
+ }
1150
+
1127
1151
  #commitSpeechProviderRoleReplacement(role, value) {
1128
1152
  const replacement = immutableSpeechProviderRoleReplacement(role, value);
1129
1153
  const currentState = getAIRuntimeState();
@@ -1168,9 +1192,15 @@ export class AIProviderRuntime {
1168
1192
  `AI role ${role} selected routes no longer belong to the expected provider identity.`
1169
1193
  );
1170
1194
  }
1171
- } else if (slot.routes.default
1195
+ } else if ((slot.routes.default
1172
1196
  || slot.routes.localOnly
1173
- || slot.selection) {
1197
+ || slot.selection)
1198
+ && !this.#pendingSpeechProviderHydrationMatches(
1199
+ role,
1200
+ slot,
1201
+ replacement.provider,
1202
+ replacement.routes
1203
+ )) {
1174
1204
  throw speechProviderReplacementError(
1175
1205
  'ARCANE_AI_SPEECH_PROVIDER_REPLACEMENT_EXPECTED_PROVIDER_REQUIRED',
1176
1206
  'speech-provider-replacement-expected-provider-required',
@@ -1315,9 +1345,15 @@ export class AIProviderRuntime {
1315
1345
  `AI role ${role} selected routes no longer belong to the expected provider identity.`
1316
1346
  );
1317
1347
  }
1318
- } else if (slot.routes.default
1348
+ } else if ((slot.routes.default
1319
1349
  || slot.routes.localOnly
1320
- || slot.selection) {
1350
+ || slot.selection)
1351
+ && !this.#pendingSpeechProviderHydrationMatches(
1352
+ role,
1353
+ slot,
1354
+ replacement.providers[role],
1355
+ replacement.routes[role]
1356
+ )) {
1321
1357
  throw speechProviderReplacementError(
1322
1358
  'ARCANE_AI_SPEECH_PROVIDER_REPLACEMENT_EXPECTED_PROVIDER_REQUIRED',
1323
1359
  'speech-provider-replacement-expected-provider-required',
@@ -28,7 +28,7 @@
28
28
  "const": "arcane-os"
29
29
  },
30
30
  "version": {
31
- "const": "0.3.0"
31
+ "const": "0.3.1"
32
32
  }
33
33
  }
34
34
  },
@@ -82,7 +82,7 @@
82
82
  "const": "arcane-sdk-browser-runtime-v1"
83
83
  },
84
84
  "sdkVersion": {
85
- "const": "0.3.0"
85
+ "const": "0.3.1"
86
86
  },
87
87
  "source": {
88
88
  "type": "object",
@@ -3,6 +3,7 @@ import path from 'node:path';
3
3
  import {verifyRuntime} from './runtime.mjs';
4
4
  import {verifySdkBrowserRuntime} from './sdk-browser-runtime.mjs';
5
5
  import {materializeWorkspaceRuntime} from './workspace-runtime.mjs';
6
+ import {withWorkspaceOperationLock} from './workspace-operation-lock.mjs';
6
7
  import {
7
8
  resolveInstalledSdkInstallation,
8
9
  resolveSdkPackageDeclaration
@@ -71,42 +72,59 @@ async function readRootPackage(workspaceRoot){
71
72
  export async function materializeInstalledSdkRuntime({
72
73
  workspaceRoot,
73
74
  sdkPackageSource,
75
+ workspaceOperationLease,
74
76
  signal,
75
77
  onEvent
76
78
  }={}){
77
79
  throwIfAborted(signal);
78
80
  const canonicalRoot=await canonicalWorkspaceRoot(workspaceRoot);
79
- const rootPackage=await readRootPackage(canonicalRoot);
80
- const declaration=resolveSdkPackageDeclaration(rootPackage,
81
- sdkPackageSource===undefined?{}:{packageSource:sdkPackageSource});
82
- const installation=await resolveInstalledSdkInstallation(canonicalRoot,declaration);
83
- const [runtimeReceipt,sdkBrowserRuntimeReceipt]=await Promise.all([
84
- verifyRuntime({
81
+ return withWorkspaceOperationLock({
82
+ workspaceRoot:canonicalRoot,
83
+ operation:'installed-sdk-runtime',
84
+ signal,
85
+ onEvent,
86
+ workspaceOperationLease
87
+ },async()=>{
88
+ throwIfAborted(signal);
89
+ const rootPackage=await readRootPackage(canonicalRoot);
90
+ const declaration=resolveSdkPackageDeclaration(rootPackage,
91
+ sdkPackageSource===undefined?{}:{packageSource:sdkPackageSource});
92
+ const installation=await resolveInstalledSdkInstallation(canonicalRoot,declaration);
93
+ const [runtimeReceipt,sdkBrowserRuntimeReceipt]=await Promise.all([
94
+ verifyRuntime({
95
+ runtimeRoot:installation.runtimeRoot,
96
+ signal,
97
+ onEvent
98
+ }),
99
+ verifySdkBrowserRuntime({
100
+ browserRuntimeRoot:installation.browserRuntimeRoot,
101
+ signal,
102
+ onEvent
103
+ })
104
+ ]);
105
+ const workspaceRuntimeReceipt=await materializeWorkspaceRuntime({
106
+ workspaceRoot:canonicalRoot,
85
107
  runtimeRoot:installation.runtimeRoot,
86
- signal,
87
- onEvent
88
- }),
89
- verifySdkBrowserRuntime({
108
+ runtimeReceipt,
90
109
  browserRuntimeRoot:installation.browserRuntimeRoot,
110
+ sdkBrowserRuntimeReceipt,
111
+ installedSdkAuthority:Object.freeze({declaration,installation}),
91
112
  signal,
92
113
  onEvent
93
- })
94
- ]);
95
- const workspaceRuntimeReceipt=await materializeWorkspaceRuntime({
96
- workspaceRoot:canonicalRoot,
97
- runtimeRoot:installation.runtimeRoot,
98
- runtimeReceipt,
99
- browserRuntimeRoot:installation.browserRuntimeRoot,
100
- sdkBrowserRuntimeReceipt,
101
- signal,
102
- onEvent
103
- });
104
- return Object.freeze({
105
- schemaVersion:1,
106
- kind:'arcane-installed-sdk-runtime-materialization',
107
- installation,
108
- runtimeReceipt,
109
- sdkBrowserRuntimeReceipt,
110
- workspaceRuntimeReceipt
114
+ });
115
+ const materialization=workspaceRuntimeReceipt.materialization;
116
+ return Object.freeze({
117
+ schemaVersion:1,
118
+ kind:'arcane-installed-sdk-runtime-materialization',
119
+ status:materialization.status,
120
+ generation:materialization.generation,
121
+ receiptPath:materialization.receiptPath,
122
+ persistentReceipt:materialization.persistentReceipt,
123
+ cleanupWarnings:materialization.cleanupWarnings,
124
+ installation,
125
+ runtimeReceipt,
126
+ sdkBrowserRuntimeReceipt,
127
+ workspaceRuntimeReceipt
128
+ });
111
129
  });
112
130
  }