arcane-os 0.2.3 → 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.
- package/CHANGELOG.md +30 -0
- package/README.md +8 -8
- package/browser-runtime/ARCANE_SDK_BROWSER_RELEASE.json +29 -22
- package/browser-runtime/ai/ARCANE_AI_BROWSER_SPEECH_COMPONENTS.json +203 -0
- package/browser-runtime/ai/browser-kokoro-worker.mjs +11 -2
- package/browser-runtime/ai/browser-speech-artifacts.mjs +3242 -391
- package/browser-runtime/ai/browser-speech-providers.mjs +1209 -157
- package/browser-runtime/ai/browser-speech.mjs +2 -0
- package/browser-runtime/ai/browser-whisper-worker.mjs +11 -2
- package/browser-runtime/ai/model-controller.mjs +285 -95
- package/browser-runtime/ai/speech-worker-client.mjs +249 -32
- package/browser-runtime/ai/speech-worker-runtime.mjs +2322 -167
- package/browser-runtime/event-manager.mjs +1097 -1
- package/docs/architecture.md +2 -2
- package/docs/event-manager.md +155 -27
- package/docs/reference/README.md +18 -20
- package/docs/reference/ai/browser-speech-package-authority.json +835 -0
- package/docs/reference/ai/browser-speech.md +1205 -246
- package/docs/reference/ai/browser-wasm.md +18 -7
- package/docs/reference/availability-and-normalization.md +2 -2
- package/docs/reference/behavioral-testing.md +28 -5
- package/docs/reference/cli.md +115 -7
- package/docs/reference/core/arcane-ai-contracts.md +1 -1
- package/docs/reference/event-manager.md +577 -32
- package/docs/reference/inventory/package-api.json +478 -2
- package/docs/reference/inventory/runtime-components.json +86 -37
- package/docs/reference/inventory/runtime-modules.json +126 -49
- package/docs/reference/mail.md +316 -0
- package/docs/reference/protocols.md +185 -33
- package/docs/reference/runtime-components.md +192 -80
- package/docs/reference/runtime-modules.md +589 -70
- package/docs/reference/sdk-api.md +1017 -24
- package/package.json +5 -4
- package/runtime/ARCANE_RUNTIME_RELEASE.json +145 -140
- package/runtime/arcane/components/app-bar.html +34 -13
- package/runtime/arcane/components/assistant-panel.html +110 -57
- package/runtime/arcane/components/calculator.html +7 -4
- package/runtime/arcane/components/chart.html +58 -17
- package/runtime/arcane/components/chat.html +606 -136
- package/runtime/arcane/components/conversation-view.html +13 -6
- package/runtime/arcane/components/dashboard-config.html +96 -59
- package/runtime/arcane/components/data-maintenance.html +69 -14
- package/runtime/arcane/components/data-view.html +53 -7
- package/runtime/arcane/components/directory-picker.html +118 -32
- package/runtime/arcane/components/document-inspector.html +47 -10
- package/runtime/arcane/components/file-drop.html +81 -35
- package/runtime/arcane/components/file-inspector.html +72 -22
- package/runtime/arcane/components/file-manager.html +374 -79
- package/runtime/arcane/components/integration-settings.html +12 -5
- package/runtime/arcane/components/local-ai-status.html +48 -19
- package/runtime/arcane/components/markdown-document.html +161 -68
- package/runtime/arcane/components/markdown-editor.html +110 -33
- package/runtime/arcane/components/media-embed.html +8 -5
- package/runtime/arcane/components/modal.html +15 -5
- package/runtime/arcane/components/output-panel.html +28 -23
- package/runtime/arcane/components/preferences-form.html +22 -4
- package/runtime/arcane/components/record-timeline.html +18 -2
- package/runtime/arcane/components/relationship-board.html +23 -3
- package/runtime/arcane/components/screen-capture.html +10 -4
- package/runtime/arcane/components/source-code-viewer.html +76 -9
- package/runtime/arcane/components/source-explanation.html +23 -3
- package/runtime/arcane/components/speech.html +453 -131
- package/runtime/arcane/components/summary-strip.html +22 -11
- package/runtime/arcane/components/table.html +39 -21
- package/runtime/arcane/components/task-progress.html +79 -21
- package/runtime/arcane/components/terminal-workspace.html +7 -4
- package/runtime/arcane/components/theme-editor.html +7 -3
- package/runtime/arcane/components/unified-inbox.html +9 -4
- package/runtime/arcane/components/voice-transcription.html +244 -72
- package/runtime/arcane/components/weather-widget.html +5 -3
- package/runtime/arcane/components/web-navigator.html +48 -8
- package/runtime/arcane/entities/Chat.js +1 -1
- package/runtime/arcane/entities/User.js +110 -23
- package/runtime/arcane/modules/AI.js +2117 -130
- package/runtime/arcane/modules/AIProviderRuntime.js +756 -13
- package/runtime/arcane/modules/AIRuntimeState.js +109 -52
- package/runtime/arcane/modules/ApiModelDatabase.js +390 -17
- package/runtime/arcane/modules/BrowserTestSuite.js +205 -28
- package/runtime/arcane/modules/CalculatorEngine.js +63 -3
- package/runtime/arcane/modules/CommunicationAppController.js +588 -28
- package/runtime/arcane/modules/CommunicationHub.js +590 -10
- package/runtime/arcane/modules/ComponentContracts.js +235 -37
- package/runtime/arcane/modules/ConversationTimebox.js +152 -33
- package/runtime/arcane/modules/DBLS.js +40 -7
- package/runtime/arcane/modules/DBOPFS.js +35 -11
- package/runtime/arcane/modules/DataMaintenance.js +12 -2
- package/runtime/arcane/modules/Errors.js +65 -7
- package/runtime/arcane/modules/HTMLImport.js +198 -14
- package/runtime/arcane/modules/LocalAIReadinessController.js +208 -29
- package/runtime/arcane/modules/Mail.js +738 -115
- package/runtime/arcane/modules/MailOutbox.mjs +1395 -0
- package/runtime/arcane/modules/MailTransport.mjs +197 -39
- package/runtime/arcane/modules/Ollama.js +36 -1
- package/runtime/arcane/modules/OpenMeteoWeatherProvider.js +583 -7
- package/runtime/arcane/modules/PreferenceStore.js +367 -33
- package/runtime/arcane/modules/RecordReviewStore.js +322 -23
- package/runtime/arcane/modules/ScreenCapture.js +1397 -15
- package/runtime/arcane/modules/SpeechPlayback.js +438 -41
- package/runtime/arcane/modules/TerminalClient.js +277 -12
- package/runtime/arcane/modules/ThemeBootstrap.js +80 -6
- package/runtime/arcane/modules/ThemeManager.js +39 -7
- package/runtime/arcane/modules/TimeGuard.js +131 -20
- package/runtime/arcane/modules/WaitForComponent.js +386 -33
- package/schemas/arcane-lock.schema.json +2 -2
- package/src/cli/main.mjs +435 -9
- package/src/event-manager.mjs +1097 -1
- package/src/import-map.mjs +21 -3
- package/src/index.mjs +13 -0
- package/src/installed-sdk-runtime.mjs +130 -0
- package/src/mail-api.mjs +22 -0
- package/src/mail-credentials.mjs +667 -0
- package/src/mail-server.mjs +1769 -0
- package/src/mail.mjs +261 -0
- package/src/sdk-browser-runtime.mjs +85 -41
- package/src/testing-loader.mjs +7 -0
- package/src/toolchain.mjs +3 -0
- package/src/workspace-runtime.mjs +804 -22
- package/src/workspace.mjs +1 -1
|
@@ -2,9 +2,28 @@ import {
|
|
|
2
2
|
checkLocalAIReadiness,
|
|
3
3
|
deriveLocalAIRequirements
|
|
4
4
|
} from './LocalAIReadiness.js?v=4';
|
|
5
|
+
import {
|
|
6
|
+
createArcaneEventSource,
|
|
7
|
+
projectArcaneDOMEvent
|
|
8
|
+
} from 'arcane-os/event-manager';
|
|
5
9
|
|
|
6
10
|
const SLOT_NAMES=Object.freeze(['llm','stt','tts']);
|
|
7
11
|
|
|
12
|
+
export const LOCAL_AI_READINESS_CONTROLLER_EVENT_TYPES=Object.freeze({
|
|
13
|
+
changed:'local-ai-readiness-change'
|
|
14
|
+
});
|
|
15
|
+
export const LOCAL_AI_READINESS_CONTROLLER_ERROR_CODES=Object.freeze({
|
|
16
|
+
aborted:'ARCANE_LOCAL_AI_READINESS_CONTROLLER_ABORTED',
|
|
17
|
+
disposed:'ARCANE_LOCAL_AI_READINESS_CONTROLLER_DISPOSED',
|
|
18
|
+
statusReadyTimeout:'ARCANE_LOCAL_AI_STATUS_COMPONENT_READY_TIMEOUT'
|
|
19
|
+
});
|
|
20
|
+
export const LOCAL_AI_READINESS_CONTROLLER_REASONS=Object.freeze({
|
|
21
|
+
checked:'local-ai-readiness-checked',
|
|
22
|
+
aborted:'local-ai-readiness-controller-aborted',
|
|
23
|
+
disposed:'local-ai-readiness-controller-disposed',
|
|
24
|
+
statusReadyTimeout:'local-ai-status-component-ready-timeout'
|
|
25
|
+
});
|
|
26
|
+
|
|
8
27
|
function availabilityFromReport(report={}){
|
|
9
28
|
const slots=report.slots||{};
|
|
10
29
|
return Object.freeze(Object.fromEntries(SLOT_NAMES.map(name=>{
|
|
@@ -29,19 +48,85 @@ function pendingReport(requirements){
|
|
|
29
48
|
});
|
|
30
49
|
}
|
|
31
50
|
|
|
32
|
-
|
|
51
|
+
function localAIReadinessAbortError(reason,disposed=false){
|
|
52
|
+
const code=disposed
|
|
53
|
+
?LOCAL_AI_READINESS_CONTROLLER_ERROR_CODES.disposed
|
|
54
|
+
:LOCAL_AI_READINESS_CONTROLLER_ERROR_CODES.aborted;
|
|
55
|
+
const errorReason=disposed
|
|
56
|
+
?LOCAL_AI_READINESS_CONTROLLER_REASONS.disposed
|
|
57
|
+
:LOCAL_AI_READINESS_CONTROLLER_REASONS.aborted;
|
|
58
|
+
if(reason instanceof Error
|
|
59
|
+
&&reason.name==='AbortError'
|
|
60
|
+
&&reason.code===code
|
|
61
|
+
&&reason.reason===errorReason){
|
|
62
|
+
return reason;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const error=new Error(
|
|
66
|
+
disposed
|
|
67
|
+
?'The local AI readiness controller has been disposed.'
|
|
68
|
+
:'The local AI readiness check was aborted.'
|
|
69
|
+
);
|
|
70
|
+
error.name='AbortError';
|
|
71
|
+
error.code=code;
|
|
72
|
+
error.reason=errorReason;
|
|
73
|
+
if(reason!==undefined){
|
|
74
|
+
error.cause=reason;
|
|
75
|
+
}
|
|
76
|
+
return error;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async function waitForStatusComponent(status,signal){
|
|
33
80
|
if(!status||status.ready){
|
|
34
81
|
return status;
|
|
35
82
|
}
|
|
36
83
|
|
|
37
|
-
await new Promise(resolve
|
|
38
|
-
|
|
39
|
-
|
|
84
|
+
await new Promise(function waitForLocalAIStatusPromise(resolve,reject){
|
|
85
|
+
let settled=false;
|
|
86
|
+
const timeout=globalThis.setTimeout(failTimeout,10000);
|
|
87
|
+
|
|
88
|
+
function cleanup(){
|
|
40
89
|
globalThis.clearTimeout(timeout);
|
|
41
|
-
status.removeEventListener('local-ai-status-ready',
|
|
90
|
+
status.removeEventListener('local-ai-status-ready',complete);
|
|
91
|
+
signal?.removeEventListener('abort',abortWait);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function complete(){
|
|
95
|
+
if(settled){
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
settled=true;
|
|
99
|
+
cleanup();
|
|
42
100
|
resolve();
|
|
43
101
|
}
|
|
44
|
-
|
|
102
|
+
|
|
103
|
+
function fail(error){
|
|
104
|
+
if(settled){
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
settled=true;
|
|
108
|
+
cleanup();
|
|
109
|
+
reject(error);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function failTimeout(){
|
|
113
|
+
const error=new Error('Local AI status component readiness timed out after 10000 ms.');
|
|
114
|
+
error.code=LOCAL_AI_READINESS_CONTROLLER_ERROR_CODES.statusReadyTimeout;
|
|
115
|
+
error.reason=LOCAL_AI_READINESS_CONTROLLER_REASONS.statusReadyTimeout;
|
|
116
|
+
fail(error);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function abortWait(){
|
|
120
|
+
fail(localAIReadinessAbortError(signal?.reason));
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if(signal?.aborted){
|
|
124
|
+
abortWait();
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
signal?.addEventListener('abort',abortWait,{once:true});
|
|
129
|
+
status.addEventListener('local-ai-status-ready',complete,{once:true});
|
|
45
130
|
});
|
|
46
131
|
return status;
|
|
47
132
|
}
|
|
@@ -62,35 +147,76 @@ export function createLocalAIReadinessController({
|
|
|
62
147
|
throw new TypeError('A chat component is required.');
|
|
63
148
|
}
|
|
64
149
|
|
|
150
|
+
const lifecycleController=new AbortController();
|
|
151
|
+
const eventOwner=Object.freeze({kind:'local-ai-readiness-controller'});
|
|
152
|
+
const events=createArcaneEventSource(
|
|
153
|
+
eventOwner,
|
|
154
|
+
{
|
|
155
|
+
source:'local-ai-readiness-controller',
|
|
156
|
+
eventTypes:Object.freeze(
|
|
157
|
+
Object.values(LOCAL_AI_READINESS_CONTROLLER_EVENT_TYPES)
|
|
158
|
+
)
|
|
159
|
+
}
|
|
160
|
+
);
|
|
65
161
|
let active=null;
|
|
162
|
+
let chatReadyListenerPending=false;
|
|
163
|
+
let destroyed=false;
|
|
66
164
|
let latestReport=null;
|
|
67
165
|
let currentAvailability=availabilityFromReport({});
|
|
166
|
+
let operationSequence=0;
|
|
68
167
|
|
|
69
|
-
|
|
168
|
+
function publishAvailability(){
|
|
169
|
+
if(destroyed){
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
70
172
|
if(typeof chat.setAIAvailability==='function'){
|
|
173
|
+
if(chatReadyListenerPending){
|
|
174
|
+
chat.removeEventListener('chat-ready',publishAvailability);
|
|
175
|
+
}
|
|
176
|
+
chatReadyListenerPending=false;
|
|
71
177
|
chat.setAIAvailability(currentAvailability);
|
|
72
|
-
}else{
|
|
73
|
-
|
|
178
|
+
}else if(!chatReadyListenerPending){
|
|
179
|
+
chatReadyListenerPending=true;
|
|
180
|
+
chat.addEventListener(
|
|
181
|
+
'chat-ready',
|
|
182
|
+
publishAvailability,
|
|
183
|
+
{
|
|
184
|
+
once:true,
|
|
185
|
+
signal:lifecycleController.signal
|
|
186
|
+
}
|
|
187
|
+
);
|
|
74
188
|
}
|
|
75
|
-
}
|
|
189
|
+
}
|
|
76
190
|
|
|
77
|
-
|
|
191
|
+
function applyAvailability(report){
|
|
78
192
|
currentAvailability=availabilityFromReport(report);
|
|
79
193
|
publishAvailability();
|
|
80
|
-
}
|
|
194
|
+
}
|
|
81
195
|
|
|
82
|
-
|
|
196
|
+
async function check(){
|
|
197
|
+
if(destroyed){
|
|
198
|
+
throw localAIReadinessAbortError(
|
|
199
|
+
lifecycleController.signal.reason,
|
|
200
|
+
true
|
|
201
|
+
);
|
|
202
|
+
}
|
|
83
203
|
if(active){
|
|
84
204
|
return active;
|
|
85
205
|
}
|
|
86
206
|
|
|
87
|
-
active=(async()
|
|
207
|
+
active=(async function runLocalAIReadinessCheck(){
|
|
88
208
|
const preferenceTuple=selectedPreferences(preferences);
|
|
89
209
|
const requirements=deriveLocalAIRequirements(preferenceTuple);
|
|
90
210
|
const required=SLOT_NAMES.some(name=>requirements[name].required);
|
|
91
211
|
|
|
92
212
|
applyAvailability(pendingReport(requirements));
|
|
93
|
-
await waitForStatusComponent(status);
|
|
213
|
+
await waitForStatusComponent(status,lifecycleController.signal);
|
|
214
|
+
if(destroyed){
|
|
215
|
+
throw localAIReadinessAbortError(
|
|
216
|
+
lifecycleController.signal.reason,
|
|
217
|
+
true
|
|
218
|
+
);
|
|
219
|
+
}
|
|
94
220
|
status?.configure?.({profileHref});
|
|
95
221
|
if(required){
|
|
96
222
|
status?.begin?.(requirements);
|
|
@@ -102,42 +228,95 @@ export function createLocalAIReadinessController({
|
|
|
102
228
|
...checkOptions,
|
|
103
229
|
preferences:preferenceTuple
|
|
104
230
|
});
|
|
231
|
+
if(destroyed){
|
|
232
|
+
throw localAIReadinessAbortError(
|
|
233
|
+
lifecycleController.signal.reason,
|
|
234
|
+
true
|
|
235
|
+
);
|
|
236
|
+
}
|
|
105
237
|
status?.present?.(latestReport);
|
|
106
238
|
applyAvailability(latestReport);
|
|
107
239
|
if(typeof onChange==='function'){
|
|
108
240
|
onChange(latestReport);
|
|
109
241
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
242
|
+
const availability=availabilityFromReport(latestReport);
|
|
243
|
+
if(destroyed){
|
|
244
|
+
throw localAIReadinessAbortError(
|
|
245
|
+
lifecycleController.signal.reason,
|
|
246
|
+
true
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
operationSequence+=1;
|
|
250
|
+
const operationId=`${events.instanceId}:check:${operationSequence.toString(36)}`;
|
|
251
|
+
const reason=LOCAL_AI_READINESS_CONTROLLER_REASONS.checked;
|
|
252
|
+
const publication=events.dispatch(
|
|
253
|
+
LOCAL_AI_READINESS_CONTROLLER_EVENT_TYPES.changed,
|
|
254
|
+
Object.freeze({operationId,reason,report:latestReport}),
|
|
255
|
+
{
|
|
256
|
+
operationId,
|
|
257
|
+
publicDetail:Object.freeze({availability,reason})
|
|
258
|
+
}
|
|
259
|
+
);
|
|
260
|
+
projectArcaneDOMEvent(
|
|
261
|
+
chat,
|
|
262
|
+
publication.occurrence,
|
|
263
|
+
{
|
|
264
|
+
bubbles:true,
|
|
265
|
+
composed:true
|
|
266
|
+
}
|
|
267
|
+
);
|
|
115
268
|
return latestReport;
|
|
116
|
-
})().finally(()
|
|
269
|
+
})().finally(function releaseLocalAIReadinessCheck(){
|
|
117
270
|
active=null;
|
|
118
271
|
});
|
|
119
272
|
|
|
120
273
|
return active;
|
|
121
|
-
}
|
|
274
|
+
}
|
|
122
275
|
|
|
123
|
-
|
|
276
|
+
function ensure(){
|
|
124
277
|
if(active){
|
|
125
278
|
return active;
|
|
126
279
|
}
|
|
127
280
|
return latestReport
|
|
128
281
|
?Promise.resolve(latestReport)
|
|
129
282
|
:check();
|
|
130
|
-
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function retry(){
|
|
286
|
+
void check().catch(function ignoreDestroyedLocalAIRetry(error){
|
|
287
|
+
if(error?.name!=='AbortError'){
|
|
288
|
+
console.error('Local AI readiness retry failed.',error);
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
status?.addEventListener(
|
|
293
|
+
'local-ai-retry',
|
|
294
|
+
retry,
|
|
295
|
+
{signal:lifecycleController.signal}
|
|
296
|
+
);
|
|
131
297
|
|
|
132
|
-
|
|
133
|
-
|
|
298
|
+
function destroy(){
|
|
299
|
+
if(destroyed){
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
destroyed=true;
|
|
303
|
+
lifecycleController.abort(
|
|
304
|
+
localAIReadinessAbortError(undefined,true)
|
|
305
|
+
);
|
|
306
|
+
if(chatReadyListenerPending){
|
|
307
|
+
chat.removeEventListener('chat-ready',publishAvailability);
|
|
308
|
+
chatReadyListenerPending=false;
|
|
309
|
+
}
|
|
310
|
+
status?.removeEventListener('local-ai-retry',retry);
|
|
311
|
+
events.dispose();
|
|
312
|
+
return true;
|
|
313
|
+
}
|
|
134
314
|
|
|
135
315
|
return Object.freeze({
|
|
136
316
|
check,
|
|
137
317
|
ensure,
|
|
138
|
-
destroy
|
|
139
|
-
|
|
140
|
-
},
|
|
318
|
+
destroy,
|
|
319
|
+
dispose:destroy,
|
|
141
320
|
get availability(){
|
|
142
321
|
return currentAvailability;
|
|
143
322
|
},
|