arcane-os 0.3.4 → 0.3.6
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 +22 -0
- package/README.md +7 -7
- package/browser-runtime/ai/browser-wasm-llm-provider.mjs +315 -119
- package/browser-runtime/ai/model-controller.mjs +439 -95
- package/package.json +1 -1
- package/runtime/arcane/components/assistant-panel.html +2 -1
- package/runtime/arcane/components/chat.html +469 -220
- package/runtime/arcane/components/speech.html +33 -13
- package/runtime/arcane/components/voice-transcription.html +27 -3
- package/runtime/arcane/entities/Chat.js +165 -97
- package/runtime/arcane/entities/IntentEnvelope.js +52 -118
- package/runtime/arcane/entities/TWiNPolicyDecision.js +33 -130
- package/runtime/arcane/entities/User.js +38 -44
- package/runtime/arcane/modules/AI.js +569 -302
- package/runtime/arcane/modules/AIProviderRuntime.js +776 -151
- package/runtime/arcane/modules/AIRuntimeState.js +22 -24
- package/runtime/arcane/modules/ApiModelDatabase.js +54 -48
- package/runtime/arcane/modules/CaseEvidenceIndexer.js +6 -10
- package/runtime/arcane/modules/CommunicationHub.js +90 -94
- package/runtime/arcane/modules/ComponentContracts.js +23 -9
- package/runtime/arcane/modules/ConfiguredAIChatSession.js +77 -77
- package/runtime/arcane/modules/ConversationTimebox.js +76 -104
- package/runtime/arcane/modules/DBLS.js +14 -12
- package/runtime/arcane/modules/DBOPFS.js +20 -15
- package/runtime/arcane/modules/Errors.js +196 -436
- package/runtime/arcane/modules/HTMLImport.js +49 -32
- package/runtime/arcane/modules/Ollama.js +16 -14
- package/runtime/arcane/modules/PersistentAIChatSession.js +174 -93
- package/runtime/arcane/modules/RecordReviewStore.js +40 -35
- package/runtime/arcane/modules/TerminalClient.js +12 -14
- package/runtime/arcane/modules/ThemeBootstrap.js +7 -7
- package/runtime/arcane/modules/ThemeManager.js +5 -5
- package/runtime/arcane/modules/TimeGuard.js +5 -65
- package/runtime/arcane/modules/WaitForComponent.js +43 -40
- package/src/installed-sdk-runtime.mjs +11 -1
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {createArcaneEventSource} from 'arcane-os/event-manager';
|
|
2
2
|
import TerminalSession from '../entities/TerminalSession.js';
|
|
3
3
|
|
|
4
|
-
export const TERMINAL_CLIENT_EVENT_TYPES=
|
|
4
|
+
export const TERMINAL_CLIENT_EVENT_TYPES={
|
|
5
5
|
sessionStarted:'terminal-session',
|
|
6
6
|
sessionExited:'terminal-exit',
|
|
7
7
|
sessionError:'terminal-error',
|
|
8
8
|
sessionOutput:'terminal-output'
|
|
9
|
-
}
|
|
10
|
-
export const TERMINAL_CLIENT_ERROR_CODES=
|
|
9
|
+
};
|
|
10
|
+
export const TERMINAL_CLIENT_ERROR_CODES={
|
|
11
11
|
capabilityUnavailable:'ARCANE_TERMINAL_CAPABILITY_UNAVAILABLE',
|
|
12
12
|
disposed:'ARCANE_TERMINAL_CLIENT_DISPOSED',
|
|
13
13
|
hostEventSubscriptionInvalid:'ARCANE_TERMINAL_HOST_EVENT_SUBSCRIPTION_INVALID',
|
|
@@ -15,8 +15,8 @@ export const TERMINAL_CLIENT_ERROR_CODES=Object.freeze({
|
|
|
15
15
|
eventTypeInvalid:'ARCANE_TERMINAL_CLIENT_EVENT_TYPE_INVALID',
|
|
16
16
|
staleSessionCleanupRejected:'ARCANE_TERMINAL_STALE_SESSION_CLEANUP_REJECTED',
|
|
17
17
|
sessionHostError:'ARCANE_TERMINAL_SESSION_HOST_ERROR'
|
|
18
|
-
}
|
|
19
|
-
export const TERMINAL_CLIENT_REASONS=
|
|
18
|
+
};
|
|
19
|
+
export const TERMINAL_CLIENT_REASONS={
|
|
20
20
|
capabilityUnavailable:'terminal-capability-unavailable',
|
|
21
21
|
disposed:'terminal-client-disposed',
|
|
22
22
|
hostEventSubscriptionInvalid:'terminal-host-event-subscription-invalid',
|
|
@@ -27,7 +27,7 @@ export const TERMINAL_CLIENT_REASONS=Object.freeze({
|
|
|
27
27
|
sessionExited:'terminal-session-exited',
|
|
28
28
|
sessionHostErrorReceived:'terminal-session-host-error-received',
|
|
29
29
|
sessionOutputReceived:'terminal-session-output-received'
|
|
30
|
-
}
|
|
30
|
+
};
|
|
31
31
|
|
|
32
32
|
function terminalClientError(code,reason,message,cause){
|
|
33
33
|
const error=cause===undefined
|
|
@@ -53,14 +53,14 @@ function terminalPublicDetail(detail,type,reason){
|
|
|
53
53
|
?detail.code
|
|
54
54
|
:TERMINAL_CLIENT_ERROR_CODES.sessionHostError
|
|
55
55
|
:null;
|
|
56
|
-
return
|
|
56
|
+
return {
|
|
57
57
|
...(typeof id==='string'&&id?{id}:{}),
|
|
58
58
|
...(typeof detail?.stream==='string'?{stream:detail.stream}:{}),
|
|
59
|
-
...(
|
|
59
|
+
...(typeof detail?.data==='string'?{data:output}:{}),
|
|
60
60
|
...(typeof detail?.session?.state==='string'?{status:detail.session.state}:{}),
|
|
61
61
|
...(code?{code}:{}),
|
|
62
62
|
reason
|
|
63
|
-
}
|
|
63
|
+
};
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
export default class TerminalClient extends EventTarget{
|
|
@@ -75,9 +75,7 @@ export default class TerminalClient extends EventTarget{
|
|
|
75
75
|
this.unsubscribe=[];
|
|
76
76
|
this.#events=createArcaneEventSource(this,{
|
|
77
77
|
source:'terminal-client',
|
|
78
|
-
eventTypes:Object.
|
|
79
|
-
Object.values(TERMINAL_CLIENT_EVENT_TYPES)
|
|
80
|
-
)
|
|
78
|
+
eventTypes:Object.values(TERMINAL_CLIENT_EVENT_TYPES)
|
|
81
79
|
});
|
|
82
80
|
const events=globalThis.Arcane?.events;
|
|
83
81
|
if(events?.on){
|
|
@@ -279,11 +277,11 @@ export default class TerminalClient extends EventTarget{
|
|
|
279
277
|
const reason=terminalEventReason(type);
|
|
280
278
|
this.#operationSequence+=1;
|
|
281
279
|
const operationId=`${this.#events.instanceId}:${type}:${this.#operationSequence.toString(36)}`;
|
|
282
|
-
const compatibilityDetail=
|
|
280
|
+
const compatibilityDetail={
|
|
283
281
|
...detail,
|
|
284
282
|
operationId,
|
|
285
283
|
reason
|
|
286
|
-
}
|
|
284
|
+
};
|
|
287
285
|
return this.#events.dispatch(
|
|
288
286
|
eventType,
|
|
289
287
|
compatibilityDetail,
|
|
@@ -3,13 +3,13 @@ import {createArcaneEventSource} from 'arcane-os/event-manager';
|
|
|
3
3
|
|
|
4
4
|
const sharedKey='arcaneThemeReady';
|
|
5
5
|
const listenerKey='arcaneThemeAppearanceListener';
|
|
6
|
-
const THEME_BOOTSTRAP_EVENT_OWNER=
|
|
6
|
+
const THEME_BOOTSTRAP_EVENT_OWNER={};
|
|
7
7
|
let themeBootstrapOperationSequence=0;
|
|
8
8
|
const themeBootstrapEvents=createArcaneEventSource(
|
|
9
9
|
THEME_BOOTSTRAP_EVENT_OWNER,
|
|
10
10
|
{
|
|
11
11
|
source:'theme-bootstrap',
|
|
12
|
-
eventTypes:
|
|
12
|
+
eventTypes:['appearance.changed']
|
|
13
13
|
}
|
|
14
14
|
);
|
|
15
15
|
|
|
@@ -24,20 +24,20 @@ function installAppearanceListener(ready){
|
|
|
24
24
|
'appearance.changed',
|
|
25
25
|
function forwardAppearanceChange(detail={}){
|
|
26
26
|
themeBootstrapOperationSequence+=1;
|
|
27
|
-
const forwarded=
|
|
27
|
+
const forwarded={
|
|
28
28
|
scheme:typeof detail?.scheme==='string'?detail.scheme:null,
|
|
29
29
|
effectiveScheme:typeof detail?.effectiveScheme==='string'
|
|
30
30
|
?detail.effectiveScheme
|
|
31
31
|
:null,
|
|
32
32
|
source:typeof detail?.source==='string'?detail.source:null,
|
|
33
33
|
reason:'host-appearance-changed'
|
|
34
|
-
}
|
|
34
|
+
};
|
|
35
35
|
themeBootstrapEvents.dispatch(
|
|
36
36
|
'appearance.changed',
|
|
37
37
|
forwarded,
|
|
38
38
|
{
|
|
39
39
|
operationId:`theme-bootstrap-${themeBootstrapEvents.instanceId}-${themeBootstrapOperationSequence}`,
|
|
40
|
-
publicDetail:forwarded
|
|
40
|
+
publicDetail:{...forwarded}
|
|
41
41
|
}
|
|
42
42
|
);
|
|
43
43
|
Promise.resolve(ready).then(function reloadTheme(result){
|
|
@@ -66,8 +66,8 @@ function installAppearanceListener(ready){
|
|
|
66
66
|
Object.defineProperty(dispose,'dispose',{
|
|
67
67
|
value:dispose,
|
|
68
68
|
enumerable:false,
|
|
69
|
-
configurable:
|
|
70
|
-
writable:
|
|
69
|
+
configurable:true,
|
|
70
|
+
writable:true
|
|
71
71
|
});
|
|
72
72
|
globalThis[listenerKey]=dispose;
|
|
73
73
|
}
|
|
@@ -7,10 +7,10 @@ import {
|
|
|
7
7
|
projectArcaneDOMEvent
|
|
8
8
|
} from 'arcane-os/event-manager';
|
|
9
9
|
|
|
10
|
-
const skinSchema=
|
|
10
|
+
const skinSchema=[
|
|
11
11
|
{key:'appearance.activeSkin',type:'text',defaultValue:''},
|
|
12
12
|
{key:'appearance.customSkin',type:'text',defaultValue:''}
|
|
13
|
-
]
|
|
13
|
+
];
|
|
14
14
|
|
|
15
15
|
export default class ThemeManager{
|
|
16
16
|
#events;
|
|
@@ -26,7 +26,7 @@ export default class ThemeManager{
|
|
|
26
26
|
this.customTheme=null;
|
|
27
27
|
this.#events=createArcaneEventSource(this,{
|
|
28
28
|
source:'theme-manager',
|
|
29
|
-
eventTypes:
|
|
29
|
+
eventTypes:['arcane-theme-change']
|
|
30
30
|
});
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -125,14 +125,14 @@ export default class ThemeManager{
|
|
|
125
125
|
|
|
126
126
|
emit(reason='theme-state-applied'){
|
|
127
127
|
const state=this.current();
|
|
128
|
-
const detail=
|
|
128
|
+
const detail={...state,reason};
|
|
129
129
|
this.#operationSequence+=1;
|
|
130
130
|
const {occurrence}=this.#events.dispatch(
|
|
131
131
|
'arcane-theme-change',
|
|
132
132
|
detail,
|
|
133
133
|
{
|
|
134
134
|
operationId:`theme-manager-${this.#events.instanceId}-${this.#operationSequence}`,
|
|
135
|
-
publicDetail:
|
|
135
|
+
publicDetail:{mode:detail.mode,reason}
|
|
136
136
|
}
|
|
137
137
|
);
|
|
138
138
|
if(typeof globalThis.CustomEvent==='function'
|
|
@@ -30,14 +30,6 @@ class TimeGuard {
|
|
|
30
30
|
|
|
31
31
|
ready=false;
|
|
32
32
|
|
|
33
|
-
// Default to 17 day grace period from last check
|
|
34
|
-
#gracePeriod = 1000 * 60 * 60 * 24 * 17;
|
|
35
|
-
// ms s m h d
|
|
36
|
-
|
|
37
|
-
// Allow a six (6) hour grace period to handle time changes
|
|
38
|
-
#gracePeriodClock = 1000 * 60 * 60 * 6;
|
|
39
|
-
// ms s m h
|
|
40
|
-
|
|
41
33
|
// Note, all times are in milliseconds
|
|
42
34
|
#storedTime = 0;
|
|
43
35
|
#lastSuccessfulTime = 0;
|
|
@@ -49,7 +41,7 @@ class TimeGuard {
|
|
|
49
41
|
|
|
50
42
|
this.#events=createArcaneEventSource(this,{
|
|
51
43
|
source:'time-guard',
|
|
52
|
-
eventTypes:
|
|
44
|
+
eventTypes:[TIME_GUARD_READY_EVENT]
|
|
53
45
|
});
|
|
54
46
|
this.#loadTime();
|
|
55
47
|
}
|
|
@@ -123,16 +115,6 @@ class TimeGuard {
|
|
|
123
115
|
this.#assertOpen();
|
|
124
116
|
this.#checkTime(time);
|
|
125
117
|
|
|
126
|
-
if (time < this.#lastSuccessfulTime) {
|
|
127
|
-
//console.log('Clock rollback detected');
|
|
128
|
-
throw timeGuardError(
|
|
129
|
-
'ARCANE_TIME_GUARD_SUCCESS_TIME_ROLLBACK',
|
|
130
|
-
'successful-check-time-rollback',
|
|
131
|
-
'The successful-check time cannot precede its stored value.',
|
|
132
|
-
RangeError
|
|
133
|
-
);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
118
|
this.#lastSuccessfulTime = time;
|
|
137
119
|
window.user.last_successful_time = time;
|
|
138
120
|
|
|
@@ -141,53 +123,11 @@ class TimeGuard {
|
|
|
141
123
|
|
|
142
124
|
checkClockRollback() {
|
|
143
125
|
this.#assertOpen();
|
|
144
|
-
// Get current time and add time change grace period.
|
|
145
|
-
// This is to allow for time changes up to six hours
|
|
146
|
-
const currentTimeWithTimeChangeGracePeriod = Date.now() + this.#gracePeriodClock;
|
|
147
|
-
|
|
148
|
-
if (currentTimeWithTimeChangeGracePeriod < this.#storedTime) {
|
|
149
|
-
//console.log('Clock rollback detected');
|
|
150
|
-
throw timeGuardError(
|
|
151
|
-
'ARCANE_TIME_GUARD_CLOCK_ROLLBACK_LIMIT_EXCEEDED',
|
|
152
|
-
'clock-rollback-limit-exceeded',
|
|
153
|
-
'The clock precedes the stored time by more than the allowed tolerance.',
|
|
154
|
-
RangeError
|
|
155
|
-
);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
126
|
return true;
|
|
159
127
|
}
|
|
160
128
|
|
|
161
129
|
checkGracePeriod() {
|
|
162
130
|
this.#assertOpen();
|
|
163
|
-
this.checkClockRollback();
|
|
164
|
-
|
|
165
|
-
const currentTime = Date.now();
|
|
166
|
-
|
|
167
|
-
if (currentTime < this.#lastSuccessfulTime) {
|
|
168
|
-
//console.log('Clock rollback detected');
|
|
169
|
-
throw timeGuardError(
|
|
170
|
-
'ARCANE_TIME_GUARD_CURRENT_TIME_PRECEDES_SUCCESS',
|
|
171
|
-
'current-time-precedes-successful-check',
|
|
172
|
-
'The current time precedes the last successful check.',
|
|
173
|
-
RangeError
|
|
174
|
-
);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
const timeDifferenceBetweenChecks = currentTime - this.#lastSuccessfulTime;
|
|
178
|
-
|
|
179
|
-
console.log(timeDifferenceBetweenChecks);
|
|
180
|
-
|
|
181
|
-
// Note, if the last known time check has not been set, this error will always be emitted
|
|
182
|
-
if (timeDifferenceBetweenChecks > this.#gracePeriod) {
|
|
183
|
-
throw timeGuardError(
|
|
184
|
-
'ARCANE_TIME_GUARD_GRACE_PERIOD_EXCEEDED',
|
|
185
|
-
'grace-period-exceeded',
|
|
186
|
-
'The elapsed time exceeds the allowed time guard grace period.',
|
|
187
|
-
RangeError
|
|
188
|
-
);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
131
|
return true;
|
|
192
132
|
}
|
|
193
133
|
|
|
@@ -196,16 +136,16 @@ class TimeGuard {
|
|
|
196
136
|
const operationId=`${this.#events.instanceId}:initialize:${(++this.#operationSequence).toString(36)}`;
|
|
197
137
|
const {occurrence}=this.#events.dispatch(
|
|
198
138
|
TIME_GUARD_READY_EVENT,
|
|
199
|
-
|
|
139
|
+
{
|
|
200
140
|
db:this,
|
|
201
141
|
reason:TIME_GUARD_READY_REASON
|
|
202
|
-
}
|
|
142
|
+
},
|
|
203
143
|
{
|
|
204
144
|
operationId,
|
|
205
|
-
publicDetail:
|
|
145
|
+
publicDetail:{
|
|
206
146
|
ready:true,
|
|
207
147
|
reason:TIME_GUARD_READY_REASON
|
|
208
|
-
}
|
|
148
|
+
}
|
|
209
149
|
}
|
|
210
150
|
);
|
|
211
151
|
projectArcaneDOMEvent(window,occurrence);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
const componentWaitErrorCodes={
|
|
2
2
|
abortSignalInvalid:'ARCANE_COMPONENT_READINESS_ABORT_SIGNAL_INVALID',
|
|
3
3
|
elementRequired:'ARCANE_COMPONENT_READINESS_ELEMENT_REQUIRED',
|
|
4
4
|
errorEventReported:'ARCANE_COMPONENT_READINESS_ERROR_EVENT_REPORTED',
|
|
@@ -12,9 +12,9 @@ export const COMPONENT_WAIT_ERROR_CODES=Object.freeze({
|
|
|
12
12
|
waitAborted:'ARCANE_COMPONENT_READINESS_WAIT_ABORTED',
|
|
13
13
|
waitOptionsInvalid:'ARCANE_COMPONENT_READINESS_WAIT_OPTIONS_INVALID',
|
|
14
14
|
waitTimedOut:'COMPONENT_READY_TIMEOUT'
|
|
15
|
-
}
|
|
15
|
+
};
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
const componentWaitReasons={
|
|
18
18
|
abortSignalInvalid:'component-readiness-abort-signal-invalid',
|
|
19
19
|
elementMissing:'component-readiness-element-missing',
|
|
20
20
|
errorEventReported:'component-readiness-error-event-reported',
|
|
@@ -28,7 +28,10 @@ export const COMPONENT_WAIT_REASONS=Object.freeze({
|
|
|
28
28
|
waitAborted:'component-readiness-wait-aborted',
|
|
29
29
|
waitOptionsInvalid:'component-readiness-wait-options-invalid',
|
|
30
30
|
waitTimedOut:'component-readiness-wait-timed-out'
|
|
31
|
-
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const COMPONENT_WAIT_ERROR_CODES={...componentWaitErrorCodes};
|
|
34
|
+
export const COMPONENT_WAIT_REASONS={...componentWaitReasons};
|
|
32
35
|
|
|
33
36
|
function defineComponentWaitError(error,code,reason,cause){
|
|
34
37
|
const priorCode=typeof error?.code==='string'&&error.code
|
|
@@ -92,8 +95,8 @@ function componentWaitAbortError(reason){
|
|
|
92
95
|
}
|
|
93
96
|
return defineComponentWaitError(
|
|
94
97
|
error,
|
|
95
|
-
|
|
96
|
-
|
|
98
|
+
componentWaitErrorCodes.waitAborted,
|
|
99
|
+
componentWaitReasons.waitAborted,
|
|
97
100
|
reason
|
|
98
101
|
);
|
|
99
102
|
}
|
|
@@ -103,8 +106,8 @@ function waitForComponent(element,options={}){
|
|
|
103
106
|
return Promise.reject(
|
|
104
107
|
componentWaitError(
|
|
105
108
|
'Component readiness wait options must be an object.',
|
|
106
|
-
|
|
107
|
-
|
|
109
|
+
componentWaitErrorCodes.waitOptionsInvalid,
|
|
110
|
+
componentWaitReasons.waitOptionsInvalid,
|
|
108
111
|
TypeError
|
|
109
112
|
)
|
|
110
113
|
);
|
|
@@ -128,18 +131,18 @@ function waitForComponent(element,options={}){
|
|
|
128
131
|
return Promise.reject(
|
|
129
132
|
componentWaitError(
|
|
130
133
|
'Component readiness event, errorEvent, property, and methods options are invalid.',
|
|
131
|
-
|
|
132
|
-
|
|
134
|
+
componentWaitErrorCodes.waitOptionsInvalid,
|
|
135
|
+
componentWaitReasons.waitOptionsInvalid,
|
|
133
136
|
TypeError
|
|
134
137
|
)
|
|
135
138
|
);
|
|
136
139
|
}
|
|
137
|
-
if(!Number.isFinite(timeoutMs)||timeoutMs<0
|
|
140
|
+
if(!Number.isFinite(timeoutMs)||timeoutMs<0){
|
|
138
141
|
return Promise.reject(
|
|
139
142
|
componentWaitError(
|
|
140
|
-
'timeoutMs must be
|
|
141
|
-
|
|
142
|
-
|
|
143
|
+
'timeoutMs must be a non-negative finite number.',
|
|
144
|
+
componentWaitErrorCodes.waitOptionsInvalid,
|
|
145
|
+
componentWaitReasons.waitOptionsInvalid,
|
|
143
146
|
RangeError
|
|
144
147
|
)
|
|
145
148
|
);
|
|
@@ -154,8 +157,8 @@ function waitForComponent(element,options={}){
|
|
|
154
157
|
return Promise.reject(
|
|
155
158
|
componentWaitError(
|
|
156
159
|
'signal must be an AbortSignal.',
|
|
157
|
-
|
|
158
|
-
|
|
160
|
+
componentWaitErrorCodes.abortSignalInvalid,
|
|
161
|
+
componentWaitReasons.abortSignalInvalid,
|
|
159
162
|
TypeError
|
|
160
163
|
)
|
|
161
164
|
);
|
|
@@ -222,8 +225,8 @@ function waitForComponent(element,options={}){
|
|
|
222
225
|
reject(
|
|
223
226
|
componentWaitError(
|
|
224
227
|
'Component readiness listener cleanup failed.',
|
|
225
|
-
|
|
226
|
-
|
|
228
|
+
componentWaitErrorCodes.listenerCleanupFailed,
|
|
229
|
+
componentWaitReasons.listenerCleanupFailed,
|
|
227
230
|
Error,
|
|
228
231
|
cleanupError
|
|
229
232
|
)
|
|
@@ -271,8 +274,8 @@ function waitForComponent(element,options={}){
|
|
|
271
274
|
fail(
|
|
272
275
|
componentWaitError(
|
|
273
276
|
'Component readiness state inspection failed.',
|
|
274
|
-
|
|
275
|
-
|
|
277
|
+
componentWaitErrorCodes.stateInspectionFailed,
|
|
278
|
+
componentWaitReasons.stateInspectionFailed,
|
|
276
279
|
Error,
|
|
277
280
|
error
|
|
278
281
|
)
|
|
@@ -302,8 +305,8 @@ function waitForComponent(element,options={}){
|
|
|
302
305
|
fail(
|
|
303
306
|
defineComponentWaitError(
|
|
304
307
|
error,
|
|
305
|
-
|
|
306
|
-
|
|
308
|
+
componentWaitErrorCodes.errorEventReported,
|
|
309
|
+
componentWaitReasons.errorEventReported,
|
|
307
310
|
detail?.error
|
|
308
311
|
)
|
|
309
312
|
);
|
|
@@ -311,8 +314,8 @@ function waitForComponent(element,options={}){
|
|
|
311
314
|
fail(
|
|
312
315
|
componentWaitError(
|
|
313
316
|
'Component readiness error-event inspection failed.',
|
|
314
|
-
|
|
315
|
-
|
|
317
|
+
componentWaitErrorCodes.errorEventInspectionFailed,
|
|
318
|
+
componentWaitReasons.errorEventInspectionFailed,
|
|
316
319
|
Error,
|
|
317
320
|
error
|
|
318
321
|
)
|
|
@@ -324,8 +327,8 @@ function waitForComponent(element,options={}){
|
|
|
324
327
|
fail(
|
|
325
328
|
componentWaitError(
|
|
326
329
|
'Component element is required.',
|
|
327
|
-
|
|
328
|
-
|
|
330
|
+
componentWaitErrorCodes.elementRequired,
|
|
331
|
+
componentWaitReasons.elementMissing,
|
|
329
332
|
TypeError
|
|
330
333
|
)
|
|
331
334
|
);
|
|
@@ -339,8 +342,8 @@ function waitForComponent(element,options={}){
|
|
|
339
342
|
fail(
|
|
340
343
|
componentWaitError(
|
|
341
344
|
'The component readiness listener target must provide addEventListener() and removeEventListener().',
|
|
342
|
-
|
|
343
|
-
|
|
345
|
+
componentWaitErrorCodes.listenerTargetInvalid,
|
|
346
|
+
componentWaitReasons.listenerTargetInvalid,
|
|
344
347
|
TypeError
|
|
345
348
|
)
|
|
346
349
|
);
|
|
@@ -359,8 +362,8 @@ function waitForComponent(element,options={}){
|
|
|
359
362
|
fail(
|
|
360
363
|
componentWaitError(
|
|
361
364
|
'Component readiness abort-listener installation failed.',
|
|
362
|
-
|
|
363
|
-
|
|
365
|
+
componentWaitErrorCodes.listenerInstallationFailed,
|
|
366
|
+
componentWaitReasons.listenerInstallationFailed,
|
|
364
367
|
Error,
|
|
365
368
|
error
|
|
366
369
|
)
|
|
@@ -380,8 +383,8 @@ function waitForComponent(element,options={}){
|
|
|
380
383
|
fail(
|
|
381
384
|
componentWaitError(
|
|
382
385
|
'Component readiness listener installation failed.',
|
|
383
|
-
|
|
384
|
-
|
|
386
|
+
componentWaitErrorCodes.listenerInstallationFailed,
|
|
387
|
+
componentWaitReasons.listenerInstallationFailed,
|
|
385
388
|
Error,
|
|
386
389
|
error
|
|
387
390
|
)
|
|
@@ -395,8 +398,8 @@ function waitForComponent(element,options={}){
|
|
|
395
398
|
fail(
|
|
396
399
|
componentWaitError(
|
|
397
400
|
'A component readiness event is required.',
|
|
398
|
-
|
|
399
|
-
|
|
401
|
+
componentWaitErrorCodes.readinessEventRequired,
|
|
402
|
+
componentWaitReasons.readinessEventMissing
|
|
400
403
|
)
|
|
401
404
|
);
|
|
402
405
|
return;
|
|
@@ -413,8 +416,8 @@ function waitForComponent(element,options={}){
|
|
|
413
416
|
fail(
|
|
414
417
|
componentWaitError(
|
|
415
418
|
'Component readiness error-listener installation failed.',
|
|
416
|
-
|
|
417
|
-
|
|
419
|
+
componentWaitErrorCodes.listenerInstallationFailed,
|
|
420
|
+
componentWaitReasons.listenerInstallationFailed,
|
|
418
421
|
Error,
|
|
419
422
|
error
|
|
420
423
|
)
|
|
@@ -428,8 +431,8 @@ function waitForComponent(element,options={}){
|
|
|
428
431
|
fail(
|
|
429
432
|
componentWaitError(
|
|
430
433
|
`Component readiness timed out after ${timeoutMs} ms.`,
|
|
431
|
-
|
|
432
|
-
|
|
434
|
+
componentWaitErrorCodes.waitTimedOut,
|
|
435
|
+
componentWaitReasons.waitTimedOut
|
|
433
436
|
)
|
|
434
437
|
);
|
|
435
438
|
},timeoutMs);
|
|
@@ -437,8 +440,8 @@ function waitForComponent(element,options={}){
|
|
|
437
440
|
fail(
|
|
438
441
|
componentWaitError(
|
|
439
442
|
'Component readiness timeout installation failed.',
|
|
440
|
-
|
|
441
|
-
|
|
443
|
+
componentWaitErrorCodes.timeoutInstallationFailed,
|
|
444
|
+
componentWaitReasons.timeoutInstallationFailed,
|
|
442
445
|
Error,
|
|
443
446
|
error
|
|
444
447
|
)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {lstat,readFile,realpath,stat,writeFile} from 'node:fs/promises';
|
|
1
|
+
import {lstat,readFile,realpath,rm,stat,writeFile} from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import {materializeWorkspaceRuntimeContent} from './workspace-runtime.mjs';
|
|
4
4
|
import {withWorkspaceOperationLock} from './workspace-operation-lock.mjs';
|
|
@@ -68,6 +68,15 @@ async function writeWorkspaceLock(lockPath,lock){
|
|
|
68
68
|
await writeFile(lockPath,`${JSON.stringify(lock,null,2)}\n`,'utf8');
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
async function removeRetiredInstalledRuntimeReceipt(canonicalRoot){
|
|
72
|
+
const receiptPath=path.join(
|
|
73
|
+
canonicalRoot,
|
|
74
|
+
'.arcane',
|
|
75
|
+
'installed-sdk-runtime.json'
|
|
76
|
+
);
|
|
77
|
+
await rm(receiptPath,{force:true});
|
|
78
|
+
}
|
|
79
|
+
|
|
71
80
|
export async function materializeInstalledSdkRuntime({
|
|
72
81
|
workspaceRoot,
|
|
73
82
|
sdkPackageSource,
|
|
@@ -85,6 +94,7 @@ export async function materializeInstalledSdkRuntime({
|
|
|
85
94
|
workspaceOperationLease
|
|
86
95
|
},async()=>{
|
|
87
96
|
const authority=await installedSdkAuthority(canonicalRoot,{sdkPackageSource});
|
|
97
|
+
await removeRetiredInstalledRuntimeReceipt(canonicalRoot);
|
|
88
98
|
const workspaceRuntime=await materializeWorkspaceRuntimeContent({
|
|
89
99
|
workspaceRoot:canonicalRoot,
|
|
90
100
|
runtimeRoot:authority.installation.runtimeRoot,
|